Neste tutorial, vamos explorar o dataset do Titanic, analisá-lo e enviar os resultados para a competição real. Você já aprendeu como buscar os dados e importá-los no seu Notebook do Kaggle neste tutorial. Agora, vamos usar o DataLab como notebook de ciência de dados. Você vai aprender a usar as duas ferramentas em plataformas diferentes para escolher a sua favorita.
Primeiro, acesse a seção "Competitions" no Kaggle e pesquise por Titanic (Figura 5.4). Antes de ir direto para o notebook, entenda todas as informações nas seções "Description and Rules". Também vale conferir os notebooks de outros usuários, pois isso pode trazer boas ideias para sua solução.

A competição consiste em usar machine learning para criar um modelo que prevê quais passageiros sobreviveriam ao naufrágio do Titanic. Vamos usar um dataset com informações de passageiros como nome, gênero, idade etc. Usaremos 2 datasets diferentes. O primeiro é o 'train.csv'. Nele, além das informações dos passageiros, há os valores de referência (ground truth), como 'survived' e 'not survived'. No segundo dataset, o 'test.csv', não há valores de ground truth, já que precisamos prever esses valores e enviar nossos resultados.
O arquivo de submissão deve ter apenas 2 colunas: PassengerId e Survived. O sistema de submissões gera erro se você tentar enviar um arquivo com mais de 2 colunas. Observe que é possível fazer até 10 envios por dia.
Com as informações da seção "Competition Description", o próximo passo é buscar os dados no nosso DataLab e começar a análise.
Primeiro, baixe o dataset no Data Explorer, na aba Data (Figura 5.5). Baixe os arquivos 'train.csv' e 'test.csv'.
Depois de baixar os arquivos, acesse o DataLab. Você precisa criar uma conta antes. Criar a conta e usar o DataLab é gratuito.
Você pode simplesmente arrastar e soltar os arquivos no lado esquerdo do notebook (Figura 5.6).


O próximo passo é checar o dicionário de dados na descrição do dataset. Isso ajuda a decidir quais colunas visualizar.
- survival: sobrevivência
- pclass: classe do bilhete
- sex: sexo
- Age: idade em anos
- sibsp: nº de irmãos/cônjuges a bordo do Titanic
- parch: nº de pais/filhos a bordo do Titanic
- ticket: número do bilhete
- fare: tarifa do passageiro
- cabin: número da cabine
- embarked: porto de embarque
Importando os dados
Você pode usar comandos bash em notebooks Jupyter colocando um ponto de exclamação no início da célula. Vamos verificar o local dos arquivos enviados usando os comandos pwd e ls.
!pwd; ls
/work/files/workspace
notebook.ipynb test.csv train.csv
Pandas é uma biblioteca Python usada para manipulação e análise de dados. Removemos as colunas Ticket, Name e PassengerId porque não trazem informações numéricas ou categóricas úteis. Agora você verá o restante dos atributos que serão usados.
Nas próximas linhas, os arquivos de treino e teste são lidos com o método read_csv do Pandas. Note que as colunas Survived e PassengerId são adicionadas, respectivamente, aos dataframes de treino e teste. Vamos alimentar o modelo separadamente com os atributos em columns_to_be_added_as_features e os rótulos na coluna Survived. Mas, para simplificar o pré-processamento, podemos combiná-los por agora. A variável test_df_matcher inclui também o PassengerId. Vamos usá-la para casar o PassengerId com as previsões do conjunto de teste e gerar o CSV que será enviado ao Kaggle como nosso resultado.
import pandas as pd
columns_to_be_added_as_features = ['Sex','Age','SibSp','Parch','Pclass','Fare','Embarked']
train_df = pd.read_csv('train.csv', usecols=columns_to_be_added_as_features + ['Survived'])
test_df_matcher = pd.read_csv('test.csv', usecols=columns_to_be_added_as_features + ['PassengerId'])
test_df = test_df[columns_to_be_added_as_features]
Com o método head(), vemos as 5 primeiras linhas com seus nomes de coluna. Você pode definir quantas linhas iniciais quer ver passando esse número como parâmetro do head(). Em seguida, imprimimos a quantidade de linhas nos conjuntos de treino e teste.
print(train_df.head())

print("Number of rows in training set: {}".format(len(train_df)))
print("Number of rows in test set: {}".format(len(test_df)))
Number of rows in training set: 891 Number of rows in test set: 418
Pré-processamento
Precisamos converter para float os valores que serão usados como atributos no modelo. Essa conversão permite fazer operações numéricas ao normalizar os dados.
for column_title in columns_to_be_added_as_features:
if column_title in ['Embarked', "Sex"]:
continue
train_df[column_title] = pd.to_numeric(train_df[column_title], downcast="float")
test_df[column_title] = pd.to_numeric(test_df[column_title], downcast="float")
train_df["Survived"] = pd.to_numeric(train_df["Survived"], downcast="float")
O modelo precisa ser alimentado com valores numéricos. No trecho abaixo, as strings são convertidas em valores numéricos.
train_df['Embarked'].replace('Q', 0,inplace=True)
train_df['Embarked'].replace('S', 1,inplace=True)
train_df['Embarked'].replace('C', 2,inplace=True)
test_df['Embarked'].replace('Q', 0,inplace=True)
test_df['Embarked'].replace('S', 1,inplace=True)
test_df['Embarked'].replace('C', 2,inplace=True)
train_df['Sex'].replace('male', 0,inplace=True)
train_df['Sex'].replace('female', 1,inplace=True)
test_df['Sex'].replace('male', 0,inplace=True)
test_df['Sex'].replace('female', 1,inplace=True)
print(train_df.head())

Abaixo, todos os atributos são normalizados, ou seja, escalados entre 0 e 1 neste caso.
#Credit: Michael Aquilina,
#https://stackoverflow.com/questions/26414913/normalize-columns-of-pandas-data-frame
def normalize(df):
result = df.copy()
for feature_name in df.columns:
max_value = df[feature_name].max()
min_value = df[feature_name].min()
result[feature_name] = (df[feature_name] - min_value) / (max_value - min_value)
return result
train_df = normalize(train_df)
test_df = normalize(test_df)
print(train_df.head())

Como o dataset será dividido em treino e validação, vamos embaralhar os dados primeiro para evitar agrupamentos em apenas um dos conjuntos.
#Credit: Kris, https://stackoverflow.com/questions/29576430/shuffle-dataframe-rows
train_df = train_df.sample(frac=1).reset_index(drop=True)
Todos os valores vazios serão substituídos por 0; essa escolha foi feita para ganhar tempo. Porém, você pode ler este tutorial para aprender a tratar valores ausentes em machine learning.
train_df = train_df.fillna(0)
test_df = test_df.fillna(0)
Abaixo, a proporção do conjunto de validação foi definida como 0,2, ou seja, 20% dos dados serão usados para validação. Para dividir o dataset em treino e validação, usamos o train_test_split do Sklearn. Depois, separamos atributos e rótulos como mostrado nas 4 últimas linhas.
validation_set_ratio = 0.2
validation_set_size = int(len(train_df)*validation_set_ratio)
training_set_size = len(train_df) - validation_set_size
print("Total set size: {}".format(len(train_df)))
print("Training set size: {}".format(training_set_size))
print("Validation set size: {}".format(validation_set_size))
from sklearn.model_selection import train_test_split
train, val = train_test_split(train_df, test_size=validation_set_ratio)
train_X = train[columns_to_be_added_as_features]
train_Label = train[['Survived']]
val_X = val[columns_to_be_added_as_features]
val_Label = val[['Survived']]
Treinamento
Support Vector Machines são modelos de aprendizado supervisionado usados para classificação e regressão. Escolhemos esse modelo com os parâmetros abaixo. Experimente outros modelos e combinações de parâmetros. Não é preciso iniciar e parar o código sempre que quiser ajustar algo ou testar outro modelo — dá para automatizar esse processo. Se você se interessa por Support Vector Machines, confira o tutorial Support Vector Machines with Scikit-learn no DataCamp.
from sklearn.svm import SVC
SVM_KERNEL = "linear"
SVM_C = 10
SVM_GAMMA = 0.00001
svm_model = SVC(kernel = SVM_KERNEL, C = SVM_C, gamma = SVM_GAMMA)
svm_model.fit(train_X, train_Label)
Obtendo as previsões no conjunto de validação
Nesta etapa, vamos alimentar o modelo com os atributos do conjunto de validação e obter as previsões. Depois, comparamos com os valores de referência. Usamos o método metrics.accuracy_score do Sklearn para facilitar o cálculo da acurácia. A acurácia no conjunto de validação foi 0,799, um bom começo.
from sklearn import metrics
y_pred = svm_model.predict(val_X)
print("Accuracy:",metrics.accuracy_score(val_Label, y_pred))
Accuracy: 0.7988826815642458
Obtendo as previsões no conjunto de teste
Agora vamos gerar as previsões para o conjunto de teste real. Como não há valores de referência no teste, só saberemos a acurácia depois de enviar o arquivo de previsões ao Kaggle.
test_pred = svm_model.predict(test_df)
Gerando o dataframe de saída
A coluna PassengerId é extraída do dataframe test_df_matcher. Ao retorná-la diretamente, o tipo será Series. Por isso, vamos convertê-la para DataFrame do Pandas. Em seguida, inserimos as previsões do conjunto de teste como a segunda coluna do dataframe.
result = pd.DataFrame(test_df_matcher['PassengerId'])
print(result.head(10))

result.insert(1, "Survived", test_pred, True)
result["Survived"] = pd.to_numeric(result["Survived"], downcast="integer")
print(result.head(10))

Gerando o arquivo de saída
Pronto, o formato de saída está OK. No último passo, removemos os índices passando False para o parâmetro index. Agora é só baixar o arquivo gerado e enviar ao Kaggle. Assim, você verá a acurácia no conjunto de teste e será posicionado no ranking (leaderboard).
result.to_csv("out.csv", index=False)
Agora, volte à página da competição, clique em "Submit Predictions" e faça o upload do arquivo de previsões. Depois de alguns segundos, você verá sua acurácia no teste (Figura 5.12).

Conclusão
Neste tutorial, você aprendeu a analisar um dataset e enviar seus resultados para uma competição no Kaggle. Se você curte competições de ciência de dados, saiba mais sobre as DataCamp Competitions aqui.

