Dataset: Titanic: Machine Learning from Disaster
https://www.kaggle.com/c/titanic/data
Partindo da aula passada:
Atualizar a função que mede a distância euclidiana para o pacote do scikit-learn
Implementar uma função que selecione os k vizinhos mais próximos (k > 1)
Implementar uma função que recebe os k vizinhos mais próximos e determinar a classe correta
Transformar as features categoricas em numéricas (tip: pandas ou scikit-learn)
Analisar a necessidade de normalizar as features numéricas (tip: pandas ou scikit-learn)
Selecionar as features baseada na correlação (tip: pandas)
Separar o dataset em treino (75%) / teste (25%) / validação (10% do treino)
Execute o classificador para 30 k's pulando de 4 em 4 e apresente todas as acurácias utilizando o dataset de validação (Qual o melhor k?) [plotar um gráfico com os resultados]
Executar o classificador para o melhor k encontrado utilizando o dataset de teste e apresentar um relatório da precisão (tip: scikit-learn) [plotar um gráfico com os resultados]
In [1]:
# Importando as bibliotecas
from sklearn.metrics import classification_report, accuracy_score
from sklearn.neighbors import DistanceMetric
from sklearn.preprocessing import LabelEncoder, MinMaxScaler
from sklearn.model_selection import train_test_split
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
In [2]:
class KNNClassifier(object):
def __init__(self):
self.X_train = None
self.y_train = None
self.dist = DistanceMetric.get_metric("euclidean")
def euc_distance(self,row, point):
return self.dist.pairwise([row], [point])[0,0]
def closest(self, row, K):
"""
Retorna a classe respondente ao ponto mais próximo do dataset de treino.\
É um exemplo de implementação do kNN com k=1.
"""
allDist = [self.euc_distance(row, points) for points in self.X_train]
closests = np.argsort(allDist)[:K]
return self.y_train[closests]
def fit(self, training_data, training_labels):
self.X_train = training_data
self.y_train = training_labels
def predict(self, to_classify, K):
predictions = []
for row in to_classify:
labels = np.argmax(np.bincount(self.closest(row, K)))
predictions.append(labels)
return predictions
In [3]:
# Carregando os dados
data_train = pd.read_csv("train.csv")
data_train.head()
Out[3]:
In [4]:
# Inputando dados faltosos em Idade, usando a média
data_train["Age"] = data_train.Age.fillna(data_train.Age.mean())
# Remove linhas com dados faltosos (falta de informação e impossibilidade de inputação)
data_train = data_train.dropna(axis=0, how="any")
# Remove os atributos "Name" e "Ticket" pois, de forma crua, eles provavelmente
# não oferecem informações que permitam inferir se a pessoa sobreviveu ou não
data_train.drop(labels=["Name", "Ticket"], axis=1, inplace=True)
# Separando entradas/saída
X_train = data_train.loc[:,"Pclass":]
y_train = data_train[["Survived"]]
In [5]:
# Transformando dados categoricos
LE = LabelEncoder()
for feature in ["Sex", "Cabin", "Embarked"]:
X_train[[feature]] = X_train[[feature]].astype(str)
LE.fit(X_train.loc[:,feature])
X_train[[feature]] = LE.transform(X_train.loc[:,feature])
X_train.head()
Out[5]:
In [6]:
# Verificando a Matriz de Correlação (Numérica)
corrMatrix = X_train.corr()
corrMatrix
Out[6]:
In [7]:
# Verificando a Matriz de Correlação (Plotagem)
plt.matshow(corrMatrix.values)
plt.show()
# Removeremos o atributo "Cabin", apesar de a correlação não ser realmente muito forte
data_train.drop(labels=["Cabin"], axis=1, inplace=True)
In [8]:
# Normalizando as features numéricas
X_train = MinMaxScaler().fit_transform(X_train)
np.disp(X_train)
In [9]:
# Separação dos Datasets
# Treino(75%) / Teste(25%)
X_train, X_test, y_train, y_test = train_test_split(X_train, y_train.values.flatten(), test_size=0.25)
In [10]:
# Cross-Validation
knn = KNNClassifier()
knn.fit(X_train, y_train)
score_cv = []
k_cv = np.arange(3, 123, 4) # O K=1 foi removido pois estava causando over-fitting
for k in k_cv:
_, X_cv, _, Y_cv = train_test_split(X_train, y_train, test_size=0.1)
y_pred_cv = knn.predict(X_cv, k)
score_cv.append(accuracy_score(y_pred=y_pred_cv, y_true=Y_cv))
optK = k_cv[np.argmax(score_cv)]
print("# Optimal number of neighbors: ", optK)
print("# Score: ", np.max(score_cv)*100, "%")
plt.figure()
plt.plot(k_cv, score_cv, 'r-')
plt.show()
In [11]:
# Testando o K ótimo
y_pred = knn.predict(X_test, optK)
print(classification_report(y_test, y_pred, target_names=["Survived", "Not Survived"]))