kaggle入門競賽--Titanic:Machine Learning from Disaster

Titanic是Kaggle入門競賽的第一個問題,泰坦尼克號已經是衆所周知的事情,在這場災難中存活下來的人非常少,運用機器學習的知識預測某個人在這場災難中是否能夠存活是這道題目的目的。這道題一共做了三次,總結一下做本題的步驟:

(1)首先是讀取數據,使用python的數據分析包pandas,numpy等讀取csv格式的數據;

(2)查看是否有缺失值,使用第三方模塊missingno可以十分直觀的查看數據是否有缺失值,在網上學到了處理缺失值的方法:如果缺失值達到15%以上即可刪掉,或者可以再去查看一下有缺失值的變量的異常值分佈,如果既有缺失值同時異常值也較多那麼該變量可能對最終的結果分析沒太大作用,可以考慮刪掉。這樣簡單粗暴的做法會對預測的結果產生影響嗎?應該會,不過影響不會很大;

(3)填充缺失值,對於那些缺失值較少的變量,還是有填充的必要的,可以用loc尋找缺失值的位置,然後用直接賦值的方法填充數據;

(4)對各個變量進行分析。分析每個變量之前,可以先畫一個熱度圖(heatmap),查看每個變量與survived之間的相關性,熱度圖可以讓我們對數據有一個比較全面的認識,在分析每個變量的時候,可以用seaborn模塊畫箱圖,直方圖,因子圖(factorplot),不知道是不是這麼翻譯的)等,觀察變量與是否存活的關係,對於一些出現頻數高,但與survived相關性小的變量可以選擇刪掉;

(5)訓練模型:當前面的數據預處理部分都做的差不多的時候,可以用模型對數據進行訓練了,這個過程中如果能對模型進行調參就更好了~~

(6)提交結果,最終的結果分爲兩列,一個是PassengerId,另一個是Survived,把模型預測的結果寫爲csv格式後便可提交了~

另外:1.放入模型訓練的數據要轉化成int或float型,並且數據不能有缺失值,之前做實驗的對結果預測的時候程序一直報錯,Input contains NAN,infinit or a value too large...後來查看數據發現Ticket1這個變量有一個缺失值==這個錯誤找了很久,可能是1308和1309長得比較像吧。。導致之前用info()查看數據的時候沒有發現==

2.對於Name這個變量,我選擇直接刪除了,因爲覺得沒什麼作用,但是看到別人的分析,名字中的Miss,Master中暗含了此人的年齡範圍,所以可以通過姓名來推測Age中的缺失值,這樣比隨機填充一個數值要更準確,這種方法非常可取。

下面是代碼,有詳細註釋:

#-*- coding:utf-8 -*-
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
import missingno as msno
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
#import re
import sklearn
from sklearn import *
from sklearn.linear_model import LogisticRegression

train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')

df = train.append(test)

#用info()函數查看缺失值,觀察哪些變量需要填充
#可視化缺失值,因爲有12個變量,所以figsize的寬度設置爲12
msno.matrix(df,figsize=(11,5))
#plt.show()

#填充Age缺失值
ave_age = df['Age'].mean()
std_age = df['Age'].std()
df.loc[pd.isnull(df['Age']),'Age']= np.random.randint(ave_age-std_age,ave_age+std_age,df['Age'].isnull().sum())

#填充Embarked缺失值
sns.countplot(data=train,x='Embarked')
#plt.show()
#S佔大多數,填充S
df.Embarked = df.Embarked.fillna('S')
#填充Fare變量
df['Fare'] = df['Fare'].fillna(df['Fare'].median())

#除了Survived和Cabin之外的缺失值都已經填充

# df.drop('Cabin',axis=1,inplace=True)
#畫熱度圖看各個變量與Survived之間的關係
#pd.notnull(df['Survived'])是爲了取出train中的數據,但是train沒有被填充,所以用這種方法取出來
cottMatt = df[pd.notnull(df['Survived'])].corr()
#mask把cottmatt轉換成矩陣
mask = np.array(cottMatt)
mask[np.tril_indices_from(mask)] = False
fig,axes = plt.subplots()
fig.set_size_inches(12,12)
sns.heatmap(data=cottMatt,mask=mask,annot=True,square=True)

#對Pclass分析,畫因子圖
sns.set_style('ticks')
sns.factorplot(x='Pclass',y='Survived',data=df)
#sns.countplot(x='Pclass',data=df)
#爲了刪掉Pclass裏的3,先把Pclass用指標矩陣表示出來
pclass_get_dummies = pd.get_dummies(df['Pclass'])
pclass_get_dummies.columns = ['class1','class2','class3']
pclass_get_dummies.drop(['class3'],axis=1,inplace=True)

df = pd.concat([df, pclass_get_dummies], axis=1)
df.drop(['Pclass'],axis=1,inplace=True)
# print df.info()
#分析name變量
df.drop(['Name'],axis=1,inplace=True)

#分析Sex變量
plt.figure()
plt.subplot(1,2,1)
sns.countplot(x='Sex',data=df)
plt.subplot(1,2,2)
sns.factorplot(x='Sex',y='Survived',data=df)
#plt.show()
#df['Sex'] = df['Sex'].map({'male':0,'female':1})
sex_get_dummies = pd.get_dummies(df['Sex'])
sex_get_dummies.drop(['male'],axis=1,inplace=True)
df.drop('Sex',axis=1,inplace=True)
df = pd.concat([df, sex_get_dummies], axis=1)

#Age變量分析


fig,axes = plt.subplots()
fig.set_size_inches(10,5)
bins=[0,18,28,38,48,60,80]
x = df['Age']
sns.distplot(x,bins=bins,hist=True,kde=True,rug=True,ax=axes)
df['Age'] = df['Age'].astype(int)
#plt.show()
#創建Family變量
df['Family'] = df['SibSp']+df['Parch']
df['Family'].loc[df['Family']<1] = 0
df['Family'].loc[df['Family']>=1] = 1
sns.set_style('whitegrid')
fig,axes = plt.subplots(nrows=2,ncols=1)
fig.set_size_inches(10,15)
#countplot()只有x,沒有y
sns.countplot(x='Family',data=df,ax=axes[0])
grouped = df[['Family','Survived']].groupby(df['Family']).mean()
sns.barplot(x='Family',y='Survived',data=grouped,ax=axes[1])
axes[0].set_xticklabels(["Alone","With Family"])
axes[1].set_xticklabels(["Alone","With Family"])
#從上圖可以看出,與家人在一起的比單獨乘船的存活率高

#把這兩個變量組合成一個變量Family之後,刪掉這兩個變量
df.drop('SibSp',axis=1,inplace=True)
df.drop('Parch',axis=1,inplace=True)
#分析Ticket變量,用正則表達式把Ticket中的前綴提取出來,分析不同類別的Ticket與survived之間的關係
def analysis(ticket):
    ticket = ticket.replace('/','')
    ticket = ticket.replace(',','')
    ticket = ticket.split()
    ticket = map(lambda t:t.strip(),ticket)
    #用filter函數取出經過split後的字母部分
    ticket = list(filter(lambda t:not t.isdigit(),ticket))
    if len(ticket)>0:
        return ticket[0]
    else:
        #這是全部是數字的部分
        return 'X'
df['Ticket1'] = df['Ticket'].map(analysis)
df['Ticket1'] = df['Ticket1'].replace(['A5','A5.','A.5.','A4.','A4'],'A')
df['Ticket1'] = df['Ticket1'].replace(['PC','PP','PPP'],'P')
df['Ticket1'] = df['Ticket1'].replace(['STON02','SCParis','S.C.A.4.','S.P.','S.O.C.','SOC','SOTONOQ','STONO','S.O.P.P','SOTONO.Q.','SWPP','SCOW','SCAH','STONO2.','SC','S.O.P.P.'],'S')
df['Ticket1'] = df['Ticket1'].replace(['C.A.','CA','C','CA.'],'C')
df['Ticket1'] = df['Ticket1'].replace(['W.C.','W.E.P.','WC'],'W')
df['Ticket1'] = df['Ticket1'].replace(['Fa','FC','LINE','F.C.C.','F.C.','S.C.PARIS','WEP','SCPARIS','S.O.P.','SCON02.','SCA.3','STONOQ.','SCA4','SOTON2','AQ4','A','LP','AQ3.','AS','S.W.PP','C.A.SOTON','SOTONO2'],'O')
df['Ticket1'] = df['Ticket1'].map({'X':0,'A':1,'P':2,'S':3,'C':4,'W':5,'O':6})
#df['Ticket1'] = df['Ticket1'].astype(int)
#df['Ticket1'] = df['Ticket1'].map({'X':0,'A':1,'P':2,'S':3,'C':4,'W':5,'O':6})
#df['Ticket1'] = df['Ticket1'].drop(pd.isnull(df['Ticket1']))
fig,axes = plt.subplots()
sns.countplot(x='Ticket1',data=df)
plt.show()
#df['Ticket1'] = df['Ticket1'].astype(int)
df.drop(['Ticket'],axis=1,inplace=True)
#分析Fare變量
#根據describe()中25%的Fare,50%,75%...劃分Fare的範圍
# fig,axes = plt.subplots()
# sns.countplot(x='Fare',data=df)
# plt.show()
df.loc[df['Fare']<=7.89,'Fare'] = 0
df.loc[(df['Fare']>7.89)&(df['Fare']<=14.45),'Fare'] = 1
df.loc[(df['Fare']>14.45)&(df['Fare']<=31.28),'Fare'] = 2
df.loc[df['Fare']>31.28,'Fare'] = 3
df['Fare'] = df['Fare'].astype(int)
fig,axes = plt.subplots(2,1)
sns.countplot(x='Fare',data=df,ax=axes[0])
sns.barplot(x='Fare',y='Survived',data=df,ax=axes[1])
#plt.show()


#分析Cabin變量,因爲缺失值太多,刪掉此變量
df.drop('Cabin',axis=1,inplace=True)
#分析Embarked變量
# fig,axes = plt.subplots(nrows=1,ncols=2)
# fig.set_size_inches(6,8)
# sns.countplot(x='Embarked',data=df,ax=axes[0])
# sns.factorplot(x='Embarked',y='Survived',data=df,ax=axes[1])
fig,ax = plt.subplots()
sns.countplot(x='Embarked',data=df)
sns.factorplot(x='Embarked',y='Survived',data=df)
#plt.show()
#根據上面兩個圖,發現Embarked的S雖然數量多,但是存活率低,可以考慮刪掉

embarked_get_dummies = pd.get_dummies(df['Embarked'])
embarked_get_dummies.drop(['S'],axis=1,inplace=True)
df['Embarked'] = df['Embarked'].map({'S':0,'C':1,'Q':2})
df.drop(['Embarked'],axis=1,inplace=True)
df = pd.concat([df, embarked_get_dummies], axis=1)


cottMatt = df[pd.notnull(df['Survived'])].corr()
#print (cottMatt)
#mask把cottmatt轉換成矩陣
mask = np.array(cottMatt)
mask[np.tril_indices_from(mask)] = False
fig,axes = plt.subplots()
fig.set_size_inches(12,12)
sns.heatmap(data=cottMatt,mask=mask,annot=True,square=True)
#plt.show()
X = df[pd.notnull(df['Survived'])].drop(['Survived'],axis=1)
X_test  = df[pd.isnull(df['Survived'])].drop(['Survived'],axis=1)
y = df[pd.notnull(df['Survived'])].Survived.astype(int)
#print (df)
logreg = LogisticRegression()
logreg.fit(X, y)
pre = logreg.predict(X_test)
print (pre)
logreg.score(X, y)

submission =pd.DataFrame({'PassengerId':X_test['PassengerId'],
                          'Survived':pre})
submission.to_csv('submission.csv',index=False)
另外第一次使用seaborn模塊,在知乎上學習了有關seaborn畫圖的方法,鏈接:Seaborn(sns)官方文檔學習筆記,這是第一章,在文末還有第二章第三章,學會了可以畫更炫酷的圖。嗯..就寫到這兒吧
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章