Après Dernière fois, Kaggle Titanic dans le top 1,5% (0.83732) Je vais expliquer l'approche de. Le code à utiliser est titanic (0.83732) _3 de Github. J'expliquerai comment améliorer le score soumis donné dans Dernière fois à 0.83732.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline,make_pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectKBest
from sklearn import model_selection
from sklearn.model_selection import GridSearchCV
import warnings
warnings.filterwarnings('ignore')
#Lire CSV
train= pd.read_csv("train.csv")
test= pd.read_csv("test.csv")
#Intégration de données
dataset = pd.concat([train, test], ignore_index = True)
#Pour soumission
PassengerId = test['PassengerId']
#Comparaison du taux de survie par niveau de chambre
dataset['Cabin'] = dataset['Cabin'].fillna('Unknown') #Remplacer Inconnu si les données de la salle sont manquantes
dataset['Deck']= dataset['Cabin'].str.get(0) #Obtenez la première lettre (0e lettre) de la cabine (numéro de chambre)
#Comparaison du taux de survie par le nombre de caractères du ticket
Ticket_Count = dict(dataset['Ticket'].value_counts()) #Regrouper par le nombre de caractères du ticket
dataset['TicketGroup'] = dataset['Ticket'].apply(lambda x:Ticket_Count[x]) #Distribution de groupe
#Divisez-vous en deux groupes, un groupe avec un taux de survie élevé en termes de nombre de personnages dans le ticket et un groupe avec un taux de survie faible.
#Remplacez 2 si élevé et 1 si faible
def Ticket_Label(s):
if (s >= 2) & (s <= 4): #Groupe avec un taux de survie élevé en nombre de caractères
return 2
elif ((s > 4) & (s <= 8)) | (s == 1): #Groupe avec un faible taux de survie en nombre de caractères
return 1
elif (s > 8):
return 0
dataset['TicketGroup'] = dataset['TicketGroup'].apply(Ticket_Label)
En regardant le code des meilleurs joueurs de Kaggle, nous pouvons voir que l'utilisation du titre du nom est la clé d'un score élevé. Les titres sont Mr, Mrs, Miss, etc. inclus au milieu du nom. Des professions telles que Dr (médecin) et Rév (prêtre et pasteur) peuvent être répertoriées sans utiliser M. Extrayez et regroupez ces informations.
# 'Honorifics'(Titre)Diviser par caractéristiques par
dataset['Honorifics'] = dataset['Name'].apply(lambda x:x.split(',')[1].split('.')[0].strip()) #Titre(','Quand'.'Mots entre)Extrait
#Titres de groupe
#Exemple:'Capt', 'Col', 'Major', 'Dr', 'Rev'Est'Officer'À
Honorifics_Dict = {}
Honorifics_Dict.update(dict.fromkeys(['Capt', 'Col', 'Major', 'Dr', 'Rev'], 'Officer'))
Honorifics_Dict.update(dict.fromkeys(['Don', 'Sir', 'the Countess', 'Dona', 'Lady'], 'Royalty'))
Honorifics_Dict.update(dict.fromkeys(['Mme', 'Ms', 'Mrs'], 'Mrs'))
Honorifics_Dict.update(dict.fromkeys(['Mlle', 'Miss'], 'Miss'))
Honorifics_Dict.update(dict.fromkeys(['Mr'], 'Mr'))
Honorifics_Dict.update(dict.fromkeys(['Master','Jonkheer'], 'Master'))
dataset['Honorifics'] = dataset['Honorifics'].map(Honorifics_Dict)
sns.barplot(x="Honorifics", y="Survived", data=dataset, palette='Set3')
"""Liste des titres
Mr: homme,Maître: Garçon,Jonkheer: aristocrate néerlandais(Homme),
Mlle: Mademoiselle(Femme célibataire française),Miss: Femmes célibataires, filles,Mme: Madame(Femme mariée française),Ms: Femme(Célibataire ou marié),Mme: femme mariée,
Don: Homme(Espagne),Monsieur: Homme(Angleterre),la comtesse: la comtesse,Dona: femme mariée(Espagne),Dame: femme mariée(Angleterre),
Capt: Capitaine,Col: Colonel,Major: militaire,Dr: Docteur,Rev: Prêtres et ministres
"""
Après tout, les hommes adultes ont un faible taux de survie et les femmes et les enfants ont un taux de survie élevé. Mais cette fois, nous pouvons découvrir que les groupes royaux comme les aristocrates sont plus élevés que les enfants. Je pense que vous pouvez voir que les aristocrates de cette époque sont priorisés et sauvés. Cela semble être une arme que de pouvoir utiliser comme données, que vous soyez un noble ou non en termes de taux de survie.
Dernière fois et Dernière fois mettent la valeur médiane dans la valeur manquante pour le moment. Examinez-les pour améliorer la précision de vos prédictions.
Remplacez ce qui était prédit par l'apprentissage automatique par la valeur manquante de l'âge Il semble que les données relatives au titre (occupation) mentionnées précédemment puissent également être utilisées pour la prédiction. (Le Dr peut supprimer la prédiction de 5 ans)
##Prédire et remplacer les valeurs d'âge manquantes
#Extraire les éléments utilisés pour la prédiction de l'âge et créer des variables factices
age = dataset[['Age','Pclass','Sex','Honorifics']]
age_dummies = pd.get_dummies(age)
age_dummies.head(3)
#Divisez-vous entre ceux dont l'âge est connu et ceux dont l'âge est manquant
known_age = age_dummies[age_dummies.Age.notnull()].as_matrix()
null_age = age_dummies[age_dummies.Age.isnull()].as_matrix()
#Diviser en quantité d'entités et corriger les données de réponse
age_X = known_age[:, 1:]
age_y = known_age[:, 0]
#Créez un modèle de prédiction d'âge et remplacez la valeur prédite
rf = RandomForestRegressor()
rf.fit(age_X, age_y)
pred_Age = rf.predict(null_age[:, 1:])
dataset.loc[(dataset.Age.isnull()),'Age'] = pred_Age
Ensuite, vérifiez les données manquantes pour remplir les valeurs manquantes pour «Embarqué».
# 'Embarked'(Point de départ)Afficher les données manquantes
dataset[dataset['Embarked'].isnull()]
Dans les deux cas, la classe P '' (classe de billet) est 1 et le
tarif '' (tarif) est de 80.
En comparant le «tarif» médian (frais) pour chaque «inscrit» avec une «classe P» de 1, C est le plus proche. Remplacez C pour les deux valeurs manquantes.
# 'Pclass'(Classe de billet)Est 1,'Embarked'(Point de départ)Chaque'Fare'(Frais)Afficher la médiane
C = dataset[(dataset['Embarked']=='C') & (dataset['Pclass'] == 1)]['Fare'].median()
print("Valeur médiane de C", C)
S = dataset[(dataset['Embarked']=='S') & (dataset['Pclass'] == 1)]['Fare'].median()
print("Valeur médiane de S", S)
Q = dataset[(dataset['Embarked']=='Q') & (dataset['Pclass'] == 1)]['Fare'].median()
print("Médiane Q", Q)
# 'Embarked'Remplacez C par la valeur manquante de
dataset['Embarked'] = dataset['Embarked'].fillna('C')
Médiane C 76,7292 Médiane S 52,0 Médiane Q 90,0
Si vous regardez les données, vous pouvez voir que la «classe P» (classe de billet) est 3 et «Embarqué» (port de départ) est «'S ». Par conséquent, remplacez la valeur médiane «Pclass» (classe de billet) de 3 et «Embarqué» (port de départ) de'S »par cette valeur manquante. Maintenant que vous avez renseigné les valeurs manquantes pour Age, Embarqué et Tarif, vérifiez-les.
# 'Fare'(Frais)Afficher les données manquantes
dataset[dataset['Fare'].isnull()]
# 'Pclass'(Classe de billet)Est 3'Embarked'(Point de départ)Mais'S'Remplacez la valeur médiane de
fare_median=dataset[(dataset['Embarked'] == "S") & (dataset['Pclass'] == 3)].Fare.median()
dataset['Fare']=dataset['Fare'].fillna(fare_median)
#Vérifiez le nombre total de données manquantes
dataset_null = dataset.fillna(np.nan)
dataset_null.isnull().sum()
Age 0 Cabin 0 Embarked 0 Fare 0 Name 0 Parch 0 PassengerId 0 Pclass 0 Sex 0 SibSp 0 Survived 418 Ticket 0 Deck 0 TicketGroup 0 Honorifics 0 dtype: int64
Il n'y a aucune valeur manquante.
Deux fois avant Traite le nombre de frères et sœurs / conjoints et le nombre de parents / enfants à bord qui n'ont pas pu être correctement traités en données utilisables. Regroupez les familles à bord et regroupez-les en fonction du taux de survie en fonction du nombre de membres de la famille à bord.
#Frères à bord/Comparaison des taux de survie par nombre de conjoints
sns.barplot(x="SibSp", y="Survived", data=train, palette='Set3')
#Parents à bord/Comparaison des taux de survie par nombre d'enfants
sns.barplot(x="Parch", y="Survived", data=train, palette='Set3')
#Nombre de familles à bord
dataset['FamilySize']=dataset['SibSp']+dataset['Parch']+1
sns.barplot(x="FamilySize", y="Survived", data=dataset, palette='Set3')
#Regroupement par taux de survie par nombre de familles
def Family_label(s):
if (s >= 2) & (s <= 4):
return 2
elif ((s > 4) & (s <= 7)) | (s == 1):
return 1
elif (s > 7):
return 0
dataset['FamilyLabel']=dataset['FamilySize'].apply(Family_label)
sns.barplot(x="FamilyLabel", y="Survived", data=dataset, palette='Set3')
J'ai pu le diviser en belles différences.
Dans les exemples ci-dessus «SibSp» et «Parque», la relation familiale après la troisième année est inconnue, nous allons donc enquêter sur le taux de survie dans le nom de famille au lieu de la famille. Vous pouvez voir une grande différence dans le taux de survie dans le nom de famille.
#Examiner les caractéristiques du nom de famille
dataset['Surname'] = dataset['Name'].apply(lambda x:x.split(',')[0].strip()) #Nom de famille(Du nom","Extraire le mot avant)
Surname_Count = dict(dataset['Surname'].value_counts()) #Comptez le nombre de noms de famille
dataset['Surname_Count'] = dataset['Surname'].apply(lambda x:Surname_Count[x]) #Remplacez le numéro du nom de famille
#Divisez les personnes avec un double nom de famille en un groupe de femmes et d'enfants et un groupe d'adultes et d'hommes.
Female_Child_Group=dataset.loc[(dataset['Surname_Count']>=2) & ((dataset['Age']<=12) | (dataset['Sex']=='female'))]
Male_Adult_Group=dataset.loc[(dataset['Surname_Count']>=2) & (dataset['Age']>12) & (dataset['Sex']=='male')]
#Comparez le nombre moyen de taux de survie pour chaque nom de famille dans un groupe de femmes et d'enfants
Female_Child_mean = Female_Child_Group.groupby('Surname')['Survived'].mean() #Taux de survie moyen pour chaque nom de famille
Female_Child_mean_count = pd.DataFrame(Female_Child_mean.value_counts()) #Nombre moyen de taux de survie par nom de famille
Female_Child_mean_count.columns=['GroupCount']
Female_Child_mean_count
#Comparez le nombre moyen de taux de survie pour chaque nom de famille dans le groupe des hommes (adultes)
Male_Adult_mean = Male_Adult_Group.groupby('Surname')['Survived'].mean() #Taux de survie moyen pour chaque nom de famille
Male_Adult_mean_count = pd.DataFrame(Male_Adult_mean.value_counts()) #Nombre moyen de taux de survie par nom de famille
Male_Adult_mean_count.columns=['GroupCount']
Male_Adult_mean_count
Les deux groupes sont généralement 1 ou 0, ce qui indique qu'il existe une grande différence entre les groupes. Est-ce aussi une règle que si le nom de famille est le même que celui d'une famille avec des filles et des enfants (adultes et hommes), tout le monde survivra (mourra)? Cette quantité de fonctionnalités claires est précieuse. En traitant le résultat opposé à cette règle comme une valeur aberrante, on peut s'attendre à ce qu'il contribue à l'amélioration du score. Ce que nous faisons, c'est réécrire les données. Toutes les personnes portant le même nom de famille que la famille avec filles et enfants (adultes et hommes) mais toutes sont décédées (survivantes) seront profilées selon la règle inverse.
#Gérer les exceptions pour chaque groupe
#Extraire le nom de famille qui fait exception pour chaque groupe
# Dead_Liste: nom de famille décédé dans un groupe de femmes et d'enfants
# Survived_Liste: nom de famille décédé dans le groupe des hommes (adultes)
Dead_List = set(Female_Child_mean[Female_Child_mean.apply(lambda x:x==0)].index)
print("Dead_List", Dead_List, sep="\n")
Survived_List = set(Male_Adult_mean[Male_Adult_mean.apply(lambda x:x==1)].index)
print("Survived_List", Survived_List, sep="\n")
Dead_List {'Danbom', 'Turpin', 'Zabour', 'Bourke', 'Olsson', 'Goodwin', 'Cacic', 'Robins', 'Canavan', 'Lobb', 'Palsson', 'Ilmakangas', 'Oreskovic', 'Lefebre', 'Sage', 'Johnston', 'Arnold-Franchi', 'Skoog', 'Attalah', 'Lahtinen', 'Jussila', 'Ford', 'Vander Planke', 'Rosblom', 'Boulos', 'Rice', 'Caram', 'Strom', 'Panula', 'Barbara', 'Van Impe'} Survived_List {'Chambers', 'Beane', 'Jonsson', 'Cardeza', 'Dick', 'Bradley', 'Duff Gordon', 'Greenfield', 'Daly', 'Nakid', 'Taylor', 'Frolicher-Stehli', 'Beckwith', 'Kimball', 'Jussila', 'Frauenthal', 'Harder', 'Bishop', 'Goldenberg', 'McCoy'}
#Réécrire les données de test
#Décomposer les données en train et tester
train = dataset.loc[dataset['Survived'].notnull()]
test = dataset.loc[dataset['Survived'].isnull()]
#Une personne portant un nom de famille décédée dans un groupe de femmes et d'enfants → Un homme de 60 ans, dont le titre est M.
#Une personne avec un nom de famille qui a tous survécu dans un groupe d'hommes (adultes) → Une femme de 5 ans, intitulée Miss.
test.loc[(test['Surname'].apply(lambda x:x in Dead_List)),'Sex'] = 'male'
test.loc[(test['Surname'].apply(lambda x:x in Dead_List)),'Age'] = 60
test.loc[(test['Surname'].apply(lambda x:x in Dead_List)),'Title'] = 'Mr'
test.loc[(test['Surname'].apply(lambda x:x in Survived_List)),'Sex'] = 'female'
test.loc[(test['Surname'].apply(lambda x:x in Survived_List)),'Age'] = 5
test.loc[(test['Surname'].apply(lambda x:x in Survived_List)),'Title'] = 'Miss'
#Combinez à nouveau les données
dataset = pd.concat([train, test])
#Extraire les variables à utiliser
dataset6 = dataset[['Survived','Pclass','Sex','Age','Fare','Embarked','Honorifics','FamilyLabel','Deck','TicketGroup']]
#Créer une variable factice
dataset_dummies = pd.get_dummies(dataset6)
dataset_dummies.head(3)
#Décomposer les données en train et tester
#( 'Survived'Existe en train,Pas de test)
train_set = dataset_dummies[dataset_dummies['Survived'].notnull()]
test_set = dataset_dummies[dataset_dummies['Survived'].isnull()]
del test_set["Survived"]
#Séparez les données du train en variables et les bonnes réponses
X = train_set.as_matrix()[:, 1:] #Variables après Pclass
y = train_set.as_matrix()[:, 0] #Corriger les données de réponse
#Créer un modèle prédictif
pipe = Pipeline([('classify', RandomForestClassifier(random_state = 10, max_features = 'sqrt'))])
param_test = {'classify__n_estimators':list(range(20, 30, 1)),
'classify__max_depth':list(range(3, 10, 1))}
gsearch = GridSearchCV(estimator = pipe, param_grid = param_test, scoring='accuracy', cv=10)
gsearch.fit(X, y)
print(gsearch.best_params_, gsearch.best_score_)
#Prédiction des données de test
predictions = gsearch.predict(test_set)
#Création d'un fichier csv pour la soumission Kaggle
submission = pd.DataFrame({"PassengerId": PassengerId, "Survived": predictions.astype(np.int32)})
submission.to_csv("submission6.csv", index=False)
'classify__max_depth': 5, 'classify__n_estimators': 28} 0.8451178451178452 La note soumise était de 0,81818.
Le nombre de fonctionnalités ayant considérablement augmenté à 26 par rapport à la fois précédente, nous exclurons les fonctionnalités sans importance.
pipe = Pipeline([('select',SelectKBest(k=20)), #Créer un modèle à l'aide de 20 fonctionnalités utiles pour la prédiction
('classify', RandomForestClassifier(random_state = 10, max_features = 'sqrt'))])
param_test = {'classify__n_estimators':list(range(20, 30, 1)),
'classify__max_depth':list(range(3, 10, 1))}
gsearch = GridSearchCV(estimator = pipe, param_grid = param_test, scoring='accuracy', cv=10)
gsearch.fit(X, y)
print(gsearch.best_params_, gsearch.best_score_)
{'classify__max_depth': 6, 'classify__n_estimators': 26} 0.8451178451178452
select = SelectKBest(k = 20)
clf = RandomForestClassifier(random_state = 10, warm_start = True,
n_estimators = 26,
max_depth = 6,
max_features = 'sqrt')
pipeline = make_pipeline(select, clf)
pipeline.fit(X, y)
Le modèle précédent et max_depth et n_estimators ont changé. En utilisant ces informations max_depth et n_estimators, la quantité de caractéristiques est à nouveau réduite à 20 pour créer un modèle de prédiction et effectuer une prédiction.
#Étant donné max_profondeur et n_À l'aide d'estimateurs, réduisez la quantité d'entités à 20 et créez à nouveau un modèle de prédiction pour prédire
select = SelectKBest(k = 20)
clf = RandomForestClassifier(random_state = 10,
warm_start = True,
n_estimators = 26,
max_depth = 6,
max_features = 'sqrt')
pipeline = make_pipeline(select, clf)
pipeline.fit(X, y)
cv_score = model_selection.cross_val_score(pipeline, X, y, cv= 10)
print("CV Score : Mean - %.7g | Std - %.7g " % (np.mean(cv_score), np.std(cv_score)))
#Prédiction des données de test
predictions = pipeline.predict(test_set)
#Création d'un fichier csv pour la soumission Kaggle
submission = pd.DataFrame({"PassengerId": PassengerId, "Survived": predictions.astype(np.int32)})
submission.to_csv("submission7.csv", index=False)
CV Score : Mean - 0.8451402 | Std - 0.03276752 Le score soumis doit maintenant être de 0,83732. Le classement en 2019 est 217e. Cela correspond aux 1,5% supérieurs.
En remplissant logiquement les valeurs manquantes, en générant de nouvelles fonctionnalités telles que des titres et en réécrivant les données de test, nous avons obtenu un score de 0,83732, ce qui équivaut aux 1,5% supérieurs de Kaggle Titanic. Divers traitements de données sont en train de sortir et vous pouvez voir que Titanic est traité comme un tutoriel sur la capacité d'analyse des données.
C'est la fin du Titanic. J'espère que cela aidera ceux qui ont lu cet article.
Recommended Posts