Voici l’histoire de votre première participation au concours Kaggle </ b>. Dans le précédent "Essayez tous les modèles de scikit-learn avec le Titanic de Kaggle", effectuez une "validation croisée" sur le modèle de scikit-learn. J'ai pu augmenter un peu le score. Cette fois, je voudrais faire "vérifier les données brutes" qui aurait dû être fait en premier.
Histoire
J'ai lu un livre intitulé Le pouvoir de l'analyse pour changer l'entreprise. L'un des contenus du livre dit: "Vérifions les données brutes avant d'analyser les données." Les valeurs aberrantes ne peuvent pas être trouvées sans regarder les données brutes. Avant de commencer l'analyse des données, visualisez d'abord les données brutes et vérifiez visuellement les valeurs aberrantes. On dit que vous devriez acquérir une telle habitude. Vérifiez les données brutes, vérifiez les valeurs anormales et vérifiez comment utiliser à nouveau les données.
Selon le résultat, en scrutant les données d'entrée, le score a légèrement augmenté et est devenu "0.80382". Le résultat est le top 9% (au 7 janvier 2020). J'aimerais voir le déroulement de la soumission.
Vérifions quelques données brutes.
Faisons un nuage de points du tarif pour chaque pclass (classe de billet). C'est devenu comme suit.
L'axe horizontal est pclass. Le tarif «1» a tendance à être élevé. Quant à la classe de billets, la note semble s'améliorer de l'ordre de 1> 2> 3. À partir du nuage de points, vous pouvez voir que le tarif "0" est dans chaque pclass. Jetons un coup d'œil aux données brutes. Trier par ordre croissant de tarif (tarif).
PassengerId | Survived | Pclass | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked |
---|---|---|---|---|---|---|---|---|---|---|
180 | 0 | 3 | male | 36 | 0 | 0 | LINE | 0 | S | |
264 | 0 | 1 | male | 40 | 0 | 0 | 112059 | 0 | B94 | S |
272 | 1 | 3 | male | 25 | 0 | 0 | LINE | 0 | S | |
278 | 0 | 2 | male | 0 | 0 | 239853 | 0 | S | ||
303 | 0 | 3 | male | 19 | 0 | 0 | LINE | 0 | S | |
414 | 0 | 2 | male | 0 | 0 | 239853 | 0 | S | ||
467 | 0 | 2 | male | 0 | 0 | 239853 | 0 | S | ||
482 | 0 | 2 | male | 0 | 0 | 239854 | 0 | S | ||
598 | 0 | 3 | male | 49 | 0 | 0 | LINE | 0 | S | |
634 | 0 | 1 | male | 0 | 0 | 112052 | 0 | S | ||
675 | 0 | 2 | male | 0 | 0 | 239856 | 0 | S | ||
733 | 0 | 2 | male | 0 | 0 | 239855 | 0 | S | ||
807 | 0 | 1 | male | 39 | 0 | 0 | 112050 | 0 | A36 | S |
816 | 0 | 1 | male | 0 | 0 | 112058 | 0 | B102 | S | |
823 | 0 | 1 | male | 38 | 0 | 0 | 19972 | 0 | S | |
379 | 0 | 3 | male | 20 | 0 | 0 | 2648 | 4.0125 | C | |
873 | 0 | 1 | male | 33 | 0 | 0 | 695 | 5 | B51 B53 B55 | S |
327 | 0 | 3 | male | 61 | 0 | 0 | 345364 | 6.2375 | S | |
844 | 0 | 3 | male | 34.5 | 0 | 0 | 2683 | 6.4375 | C |
Dans l'ordre croissant du tarif, le tarif est «0» et PClass est 1, 2 et 3. Le tarif «0» n'est pas gratuit et semble signifier «frais inconnus». Excluez le tarif «0» des données d'entraînement. Si vous excluez le tarif «0» et créez à nouveau un diagramme de dispersion, ce sera comme suit.
C'est un peu plus facile à voir. Je suis également préoccupé par le petit point de pclass "1". En regardant le tableau ci-dessus, il y a des données pour le tarif "5" avec pclass "1". Cela peut également être une valeur aberrante, alors excluons-la.
Il s'agit d'une carte à dispersion avec une certaine gamme de tarifs pour chaque classe.
Les numéros de billets sont une échelle nominale. Je les organiserai par ordre croissant de numéros de billets.
PassengerId | Survived | Pclass | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked |
---|---|---|---|---|---|---|---|---|---|---|
258 | 1 | 1 | female | 30 | 0 | 0 | 110152 | 86.5 | B77 | S |
505 | 1 | 1 | female | 16 | 0 | 0 | 110152 | 86.5 | B79 | S |
760 | 1 | 1 | female | 33 | 0 | 0 | 110152 | 86.5 | B77 | S |
263 | 0 | 1 | male | 52 | 1 | 1 | 110413 | 79.65 | E67 | S |
559 | 1 | 1 | female | 39 | 1 | 1 | 110413 | 79.65 | E67 | S |
586 | 1 | 1 | female | 18 | 0 | 2 | 110413 | 79.65 | E68 | S |
111 | 0 | 1 | male | 47 | 0 | 0 | 110465 | 52 | C110 | S |
476 | 0 | 1 | male | 0 | 0 | 110465 | 52 | A14 | S | |
431 | 1 | 1 | male | 28 | 0 | 0 | 110564 | 26.55 | C52 | S |
367 | 1 | 1 | female | 60 | 1 | 0 | 110813 | 75.25 | D37 | C |
Si vous regardez le numéro du billet, vous ne pouvez pas lire la régularité, comme uniquement des chiffres ou une combinaison de lettres et de chiffres. Vous pouvez également voir qu'il y a des personnes avec le même numéro de billet. Les personnes ayant le même numéro de billet ont souvent le même nom de famille lorsqu'elles consultent leurs noms. Je pense que c'est une famille. De plus, par rapport à Survived of people with the same ticket number, Survived a tendance à être le même avec le même numéro de ticket. Nous envisagerons une politique d'étiquetage par numéro de billet. L'image ci-dessous.
PassengerId | Survived | Ticket | Ticket (étiquette) |
---|---|---|---|
505 | 1 | 110152 | Billet A |
258 | 1 | 110152 | Billet A |
760 | 1 | 110152 | Billet A |
586 | 1 | 110413 | Billet B |
559 | 1 | 110413 | Billet B |
263 | 0 | 110413 | Billet B |
111 | 0 | 110465 | Billet C |
476 | 0 | 110465 | Billet C |
431 | 1 | 110564 | NaN |
367 | 1 | 110813 | NaN |
Nous voulons regrouper les mêmes numéros de billets, nous utiliserons donc "NaN" pour les billets uniques. Les tickets A et B peuvent être numérisés tels quels, mais le codage à chaud est utilisé pour indiquer clairement qu'ils sont étiquetés. L'image est la suivante. Le code source sera décrit plus tard, mais vous pouvez effectuer un encodage One-Hot avec pandas.get_dummies.
PassengerId | Survived | Billet A | Billet B | Billet C |
---|---|---|---|---|
505 | 1 | 1 | 0 | 0 |
258 | 1 | 1 | 0 | 0 |
760 | 1 | 1 | 0 | 0 |
586 | 1 | 0 | 1 | 0 |
559 | 1 | 0 | 1 | 0 |
263 | 0 | 0 | 1 | 0 |
111 | 0 | 0 | 0 | 1 |
476 | 0 | 0 | 0 | 1 |
431 | 1 | 0 | 0 | 0 |
367 | 1 | 0 | 0 | 0 |
sibsp et parch ont également représenté graphiquement précédemment, mais reprenons le graphique. Il n'y avait pas de différence significative dans le coefficient de corrélation, mais ce qui suit peut être vu en regardant les graphiques pour sibsp et parch. ・ Lorsque sibsp et parch sont à 0, Survived est supérieur à 0 (environ deux fois) · Si sibsp, parch vaut 1 ou 2, les 0 et 1 survécus sont à peu près identiques ・ Sibsp et parch avec 3 ou plus ont une petite population
La dernière fois, je l'ai exclu des données d'entraînement car le coefficient de corrélation est petit, mais il semble que 0, 1 et 2 peuvent être utilisés comme données d'étiquette. Lorsque sibsp et parch sont extraits uniquement pour les données de 3 ou moins et que le coefficient de corrélation est confirmé, le résultat est le suivant.
#Vérifiez le nombre d'associations Kramer lorsque SibSp est inférieur à 3
df_SibSp = df[df['SibSp'] < 3]
cramersV(df_SibSp['Survived'], df_SibSp['SibSp'])
#Survécu et SibSp(Moins de 3)Afficher le tableau croisé de
cross_sibsp = pandas.crosstab(df_SibSp['Survived'], df_SibSp['SibSp'])
cross_sibsp
cross_sibsp.T.plot(kind='bar', stacked=False, width=0.8)
plt.show()
0.16260950922794606
Le coefficient de corrélation était de 0,16, ce qui était «faiblement corrélé». Je vais l'omettre, mais Parch a des résultats similaires. Donc, comme Ticket, essayons l'encodage One-Hot pour SibSp et Parch. L'image est la suivante.
PassengerId | Survived | SibSp_1 | SibSp_2 | SibSp_3 | SibSp_4 | SibSp_5 | SibSp_8 |
---|---|---|---|---|---|---|---|
505 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
258 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
760 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
586 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
559 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
263 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
111 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
476 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
431 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
367 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
Vérifions Cabin. Sur les 900 données de vérification (train.csv), environ 200 Cabin. La cabine est une échelle nominale. Lorsque le premier caractère est considéré comme le même groupe et groupé, il devient comme suit.
Le résultat est qu'il y a de nombreux "1" survivants dans chaque cas. Les données d'étiquette du premier caractère semblent être utiles. Cabin essaiera également de coder One-Hot le premier caractère. L'image est la suivante.
PassengerId | Survived | Cabin_A | Cabin_B | Cabin_C | Cabin_D | Cabin_E | Cabin_F | Cabin_G | Cabin_T |
---|---|---|---|---|---|---|---|---|---|
505 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
258 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
760 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
586 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
559 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
263 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
111 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
476 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
431 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
367 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
Apprenons en fonction de la situation jusqu'à présent. Les données d'entrée sont les suivantes.
No | nom de l'article | nom de l'article(Japonais) | Méthode de conversion |
---|---|---|---|
1 | Pclass | Classe de billet | Standardisation |
2 | Sex | sexe | Quantifier |
3 | SibSp | Frère/époux | one-encodage à chaud |
4 | Parch | parent/les enfants | one-encodage à chaud |
5 | Ticket | Numéro de billet | one-encodage à chaud |
6 | Fare | tarif | Standardisation |
7 | Cabin | Numéro de chambre | Le premier personnage est un-encodage à chaud |
Essayez tous les modèles de kaggle⑤, et aussi avec le modèle par grille de recherche de kaggle④ Quand j'ai essayé les paramètres, j'ai obtenu ce qui suit:
GradientBoostingClassifier(criterion='friedman_mse', init=None,
learning_rate=0.1, loss='exponential', max_depth=6,
max_features=None, max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=100,
n_iter_no_change=None, presort='auto',
random_state=1, subsample=1.0, tol=0.0001,
validation_fraction=0.1, verbose=0,
warm_start=False)
Le code complet est ci-dessous. Cependant, quand je l'ai réellement entraîné, le score n'augmentait pas lorsque "Cabin" était inclus, donc j'ai finalement exclu Cabin.
import numpy
import pandas
import matplotlib.pyplot as plt
######################################
#Nombre d'associations Klamer
# Cramer's coefficient of association
# 0.5 >= :Très forte corrélation
# 0.25 >= :Corrélation forte
# 0.1 >= :Corrélation légèrement faible
# 0.1 < :Aucune corrélation
######################################
def cramersV(x, y):
"""
Calc Cramer's V.
Parameters
----------
x : {numpy.ndarray, pandas.Series}
y : {numpy.ndarray, pandas.Series}
"""
table = numpy.array(pandas.crosstab(x, y)).astype(numpy.float32)
n = table.sum()
colsum = table.sum(axis=0)
rowsum = table.sum(axis=1)
expect = numpy.outer(rowsum, colsum) / n
chisq = numpy.sum((table - expect) ** 2 / expect)
return numpy.sqrt(chisq / (n * (numpy.min(table.shape) - 1)))
######################################
#Rapport de corrélation
# Correlation ratio
# 0.5 >= :Très forte corrélation
# 0.25 >= :Corrélation forte
# 0.1 >= :Corrélation légèrement faible
# 0.1 < :Aucune corrélation
######################################
def CorrelationV(x, y):
"""
Calc Correlation ratio
Parameters
----------
x : nominal scale {numpy.ndarray, pandas.Series}
y : ratio scale {numpy.ndarray, pandas.Series}
"""
variation = ((y - y.mean()) ** 2).sum()
inter_class = sum([((y[x == i] - y[x == i].mean()) ** 2).sum() for i in numpy.unique(x)])
correlation_ratio = inter_class / variation
return 1 - correlation_ratio
# train.Charger csv
# Load train.csv
df = pandas.read_csv('/kaggle/input/titanic/train.csv')
# test.Charger csv
# Load test.csv
df_test = pandas.read_csv('/kaggle/input/titanic/test.csv')
# 'PassengerId'Extraire(À combiner avec le résultat)
# Extract 'PassengerId'(To combine with the result)
df_test_index = df_test[['PassengerId']]
df_all = pandas.concat([df, df_test], sort=False)
##############################
#Prétraitement des données
#Extraire les éléments requis
# Data preprocessing
# Extract necessary items
##############################
df = df[['Survived', 'Pclass', 'Sex', 'SibSp', 'Parch', 'Ticket', 'Fare']]
df_test = df_test[['Pclass', 'Sex', 'SibSp', 'Parch', 'Ticket', 'Fare']]
##############################
#Tracez le diagramme de dispersion de Fare et pclass
# Draw scatter plot of Fare and pclass
##############################
plt.scatter(df['Pclass'], df['Fare'])
plt.xticks(numpy.linspace(1, 3, 3))
plt.ylim(0, 300)
plt.show()
##############################
#Exclure le tarif 0
# Exclude Fare 0
##############################
df = df[df['Fare'] != 0].reset_index(drop=True)
##############################
#Tracez le diagramme de dispersion de Fare et pclass
# Draw scatter plot of Fare and pclass
##############################
plt.scatter(df['Pclass'], df['Fare'])
plt.xticks(numpy.linspace(1, 3, 3))
#plt.xlim(1, 3)
plt.ylim(0, 300)
plt.show()
##############################
#Exclure le tarif 0
# Exclude Fare 0
##############################
df = df[df['Fare'] != 5].reset_index(drop=True)
##############################
#Tracez le diagramme de dispersion de Fare et pclass
# Draw scatter plot of Fare and pclass
##############################
plt.scatter(df['Pclass'], df['Fare'])
plt.xticks(numpy.linspace(1, 3, 3))
plt.ylim(0, 300)
plt.show()
##############################
#Afficher les tableaux croisés des survivants et de l'âge
# Display Survived and Age crosstabulation table
##############################
cross_age = pandas.crosstab(df_all['Survived'], round(df_all['Age'],-1))
cross_age
cross_age.T.plot(kind='bar', stacked=False, width=0.8)
plt.show()
##############################
#Afficher le tableau croisé Survived et SibSp
# Display Survived and SibSp crosstabulation table
##############################
cross_sibsp = pandas.crosstab(df['Survived'], df['SibSp'])
cross_sibsp
cross_sibsp.T.plot(kind='bar', stacked=False, width=0.8)
plt.show()
#Vérifiez le nombre d'associations Kramer lorsque SibSp est inférieur à 3
# Check Cramer's coefficient of association when SibSp is less than 3
df_SibSp = df[df['SibSp'] < 3]
cramersV(df_SibSp['Survived'], df_SibSp['SibSp'])
##############################
#Survécu et SibSp(Moins de 3)Afficher le tableau croisé de
# Display a crosstabulation of Survived and SibSp (less than 3)
##############################
cross_sibsp = pandas.crosstab(df_SibSp['Survived'], df_SibSp['SibSp'])
cross_sibsp
cross_sibsp.T.plot(kind='bar', stacked=False, width=0.8)
plt.show()
##############################
#Afficher les tableaux croisés Survived et Parch
# Display Survived and Parch crosstabulation table
##############################
cross_parch = pandas.crosstab(df['Survived'], df['Parch'])
cross_parch
cross_parch.T.plot(kind='bar', stacked=False, width=0.8)
plt.show()
#Vérifiez le nombre d'associations Kramer lorsque Parch est inférieur à 3
# Check Cramer's coefficient of association when Parch is less than 3
df_Parch = df[df['Parch'] < 3]
cramersV(df_Parch['Survived'], df_Parch['Parch'])
##############################
#Survécu et Parch(Moins de 3)Afficher le tableau croisé de
# Display a crosstabulation of Survived and Parch (less than 3)
##############################
cross_parch = pandas.crosstab(df_Parch['Survived'], df_Parch['Parch'])
cross_parch
cross_parch = pandas.crosstab(df_Parch['Survived'], df_Parch['Parch'])
cross_parch
cross_parch.T.plot(kind='bar', stacked=False, width=0.8)
plt.show()
from sklearn.preprocessing import LabelEncoder
##############################
#Prétraitement des données
#Quantifier l'étiquette (nom)
# Data preprocessing
# Digitize labels
##############################
##############################
# Sex
##############################
encoder_sex = LabelEncoder()
df['Sex'] = encoder_sex.fit_transform(df['Sex'].values)
df_test['Sex'] = encoder_sex.transform(df_test['Sex'].values)
##############################
#Prétraitement des données
# One-Encodage à chaud
# Data preprocessing
# One-Hot Encoding
##############################
##############################
# SibSp
##############################
SibSp_values = df_all['SibSp'].value_counts()
SibSp_values = pandas.Series(SibSp_values.index, name='SibSp')
categories = set(SibSp_values.tolist())
df['SibSp'] = pandas.Categorical(df['SibSp'], categories=categories)
df_test['SibSp'] = pandas.Categorical(df_test['SibSp'], categories=categories)
df = pandas.get_dummies(df, columns=['SibSp'])
df_test = pandas.get_dummies(df_test, columns=['SibSp'])
##############################
# Parch
##############################
Parch_values = df_all['Parch'].value_counts()
Parch_values = pandas.Series(Parch_values.index, name='Parch')
categories = set(Parch_values.tolist())
df['Parch'] = pandas.Categorical(df['Parch'], categories=categories)
df_test['Parch'] = pandas.Categorical(df_test['Parch'], categories=categories)
df = pandas.get_dummies(df, columns=['Parch'])
df_test = pandas.get_dummies(df_test, columns=['Parch'])
##############################
# Ticket
##############################
ticket_values = df_all['Ticket'].value_counts()
ticket_values = ticket_values[ticket_values > 1]
ticket_values = pandas.Series(ticket_values.index, name='Ticket')
categories = set(ticket_values.tolist())
df['Ticket'] = pandas.Categorical(df['Ticket'], categories=categories)
df_test['Ticket'] = pandas.Categorical(df_test['Ticket'], categories=categories)
df = pandas.get_dummies(df, columns=['Ticket'])
df_test = pandas.get_dummies(df_test, columns=['Ticket'])
##############################
#Prétraitement des données
#Normaliser les nombres
# Data preprocessing
# Standardize numbers
##############################
from sklearn.preprocessing import StandardScaler
#Standardisation
# Standardize numbers
standard = StandardScaler()
df_std = pandas.DataFrame(standard.fit_transform(df[['Pclass', 'Fare']]), columns=['Pclass', 'Fare'])
df['Pclass'] = df_std['Pclass']
df['Fare'] = df_std['Fare']
df_test_std = pandas.DataFrame(standard.transform(df_test[['Pclass', 'Fare']]), columns=['Pclass', 'Fare'])
df_test['Pclass'] = df_test_std['Pclass']
df_test['Fare'] = df_test_std['Fare']
##############################
#Prétraitement des données
#Gérer les valeurs manquantes
# Data preprocessing
# Fill or remove missing values
##############################
df_test = df_test.fillna({'Fare':0})
#Préparer les données d'entraînement
# Prepare training data
x_train = df.drop(columns='Survived').values
y_train = df[['Survived']].values
# y_Supprimer la cote du train
# Delete y_train dimension
y_train = numpy.ravel(y_train)
##############################
#Construire un modèle
# Build the model
# GradientBoostingClassifier
##############################
from sklearn.ensemble import GradientBoostingClassifier
model = GradientBoostingClassifier(random_state=1,loss='exponential', learning_rate=0.1, max_depth=6)
import os
if(os.path.exists('./result.csv')):
os.remove('./result.csv')
##############################
#Apprentissage
# Trainig
##############################
model.fit(x_train, y_train)
##############################
#Prédire les résultats
# Predict results
##############################
x_test = df_test.values
y_test = model.predict(x_test)
#Combinez le résultat avec le DataFrame du PassengerId
# Combine the data frame of PassengerId and the result
df_output = pandas.concat([df_test_index, pandas.DataFrame(y_test, columns=['Survived'])], axis=1)
# result.Ecrire csv dans le répertoire courant
# Write result.csv to the current directory
df_output.to_csv('result.csv', index=False)
Lorsque j'ai soumis cela, le score est devenu "0.80382".
Le score dépassait 0,8 et j'ai pu être dans le top 10%. Les données d'entrée utilisées à la fin sont les suivantes.
No | nom de l'article | nom de l'article(Japonais) | Méthode de conversion |
---|---|---|---|
1 | Pclass | Classe de billet | Standardisation |
2 | Sex | sexe | Quantifier |
3 | SibSp | Frère/époux | one-encodage à chaud |
4 | Parch | parent/les enfants | one-encodage à chaud |
5 | Ticket | Numéro de billet | one-encodage à chaud |
6 | Fare | tarif | Standardisation |
Jusqu'à cette époque, j'étudiais avec scicit-learn. Il existe d'autres frameworks pour l'apprentissage automatique, alors utilisons également un autre framework. La prochaine fois aimerait apprendre à utiliser les keras.
2020/01/29 Première édition publiée 2020/02/03 Corrigé les fautes de frappe 2020/02/15 Ajouter le lien suivant
Recommended Posts