In [7]:
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.model_selection import ShuffleSplit
import pandas as pd
from sklearn.preprocessing import LabelEncoder # poderia ser LabelBinarizer
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from matplotlib import pyplot as plt
from sklearn.metrics import classification_report
%matplotlib inline
plt.style.use('ggplot')
In [1]:
class KNNClassifier(object):
def __init__(self, n = 1):
self.X_train = None
self.y_train = None
self.n = n
def closest(self, row):
"""
Retorna a classe respondente ao ponto mais próximo do dataset de treino.\
É um exemplo de implementação do kNN com k=1.
"""
# calcula as distâncias(norma L2) entre row e os pontos no dataset
distances = np.linalg.norm(self.X_train - row, axis=1)
# calcula os índices dos n pontos com menor distância para row
smallest_n_ix = np.argpartition(distances, self.n)[:self.n]
# calcula os labels dos pontos do passo anterior
labels = self.y_train[smallest_n_ix]
# retorna o label com a maior quantidade de ocorrências em labels
return np.bincount(labels).argmax()
def fit(self, training_data, training_labels):
self.X_train = training_data
self.y_train = training_labels
return self
def predict(self, to_classify):
predictions = []
for row in to_classify:
label = self.closest(row)
predictions.append(label)
return predictions
In [5]:
df = pd.read_csv("https://github.com/abevieiramota/kaggle-titanic/raw/master/data/train.csv")
df.head()
Out[5]:
In [17]:
df.describe()
Out[17]:
In [61]:
# converte valores categóricos em inteiros com range [0, n_categorias - 1]
sex_encoder = LabelEncoder().fit(df.Sex)
df['Sex_encoded'] = sex_encoder.transform(df.Sex)
cabin_encoder = LabelEncoder().fit(df.Cabin.fillna("None"))
# atribui None aos valores faltantes em Cabin
df["Cabin_encoded"] = cabin_encoder.transform(df.Cabin.fillna("None"))
embarked_encoder = LabelEncoder().fit(df.Embarked.fillna("None"))
# atribui None aos valores faltantes em Embarked
df["Embarked_encoded"] = embarked_encoder.transform(df.Embarked.fillna("None"))
# atribui a média de Age aos valores faltantes em Age
df['Age_imputed'] = df.Age.fillna(df.Age.mean())
In [62]:
# colunas selecionadas para treino
columns = ['Pclass', 'Sex_encoded', 'Cabin_encoded', 'Embarked_encoded', 'Age_imputed', 'SibSp', 'Parch']
In [63]:
df[columns].corr()
Out[63]:
In [64]:
# remove Cabin_encoded, dada a alta correlação com Pclass
columns.remove('Cabin_encoded')
In [66]:
# escala linearmente as colunas para o range [0, 1] e gera o dataset a ser utilizada
# no treinamento do modelo
X = MinMaxScaler().fit_transform(df[columns])
# gera o vetor y, com o atributo da classificação
y = df.Survived.values
In [67]:
# particiona o dataset em
# dataset de treino, a partir do qual o modelo será treinado
# dataset de validação, a partir do qual o modelo treinado será avaliado
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=.1, random_state=1)
In [68]:
knn = KNeighborsClassifier()
# objeto responsável por gerar uma partição(n_splits=1) aleatória
# com 75% dos dados para treino e 25% dos dados para teste(test_size=.25)
# fixa random_state=0 para permitir que o resultado seja reproduzido
ss = ShuffleSplit(test_size=.25, n_splits=1, random_state=0)
n_neighbors = np.arange(1, 30, 4)
param_grid = {'n_neighbors': n_neighbors}
# classe responsável por treinar o modelo com todas as combinações
# de parâmetros em param_grid, sobre todas as partições geradas pelo ShuffleSplit
cv = GridSearchCV(knn, param_grid, cv=ss)
# executa o treinamento
cv.fit(X_train, y_train)
Out[68]:
In [75]:
plt.figure(figsize=(10, 6))
plt.plot(n_neighbors, cv.cv_results_['mean_train_score'])
plt.plot(n_neighbors, cv.cv_results_['mean_test_score'])
plt.legend(['treino', 'teste'])
plt.title("Accuracy")
plt.xlabel("N neighbors")
Out[75]:
In [78]:
cv.best_params_
Out[78]:
In [80]:
# seleciona o modelo com melhor accuracy sobre o dataset de teste
# de acordo com as partições geradas pelo ShuffleSplit
best_fit = cv.best_estimator_
# treina com todo o dataset de treino
best_fit.fit(X_train, y_train)
Out[80]:
In [81]:
# avalia seu desempenho sobre o dataset de validação(não foi utilizado no treinamento)
print(classification_report(best_fit.predict(X_valid), y_valid))