先做入门笔记吧,从每个kaggler入门必学的泰塔尼克号幸存者开始。
先看问题,我们要思考什么类型的人得救的概率较大。这里会给出train.cvs文件让我们直接做处理和建模,然后需要对test.cvs数据集里的人幸存率做一个大概的猜测。
先对整个流程宏观处理:
- 到kaggle上下载幸存者数据集,思考问题,做出假设。
- 针对数据集做图形化处理。这里主要是处理数据信息,其中包括部分缺失的数据。
- 对数据清洗,做预处理。
- 拟合建模,验证猜测。
关于一些数据属性:
- PassengerId => 乘客ID
- Pclass => 乘客等级(1/2/3等舱位)
- Name => 乘客姓名
- Sex => 性别
- Age => 年龄
- SibSp => 堂兄弟/妹个数
- Parch => 父母与小孩个数
- Ticket => 船票信息
- Fare => 票价
- Cabin => 客舱
- Embarked => 登船港口
数据可以直接到kaggle上下载,首先对数据进行可视化处理,我们可以使用info函数来查看数据信息。
import pandas as pd import numpy as np data_train=pd.read_csv("E:/Titanic/train.csv") print(data_train.info())#查看数据缺失情况 print(data_train.describe())#查看数据基本统计信息
这是info函数采集到的信息:我们可以看到有891名乘客,但是age(年龄)和cabin(客舱)都有明显的数据缺失,其中年龄数据缺失了177个数据,客舱缺失687个数据。
这是describe函数采集到的信息,在这里我们可以看到891人里最后的幸存率是38.3%,幸存者平均年龄在29岁左右。接下来可以使用matplotlib函数开始对数据做可视化处理。
import matplotlib import matplotlib.pyplot as plt import numpy as np import pandas as pd from pylab import * plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 data_train = pd.read_csv("E:/titanic/train.csv") # 查看各乘客等级的获救情况 survived_0 = data_train.Pclass[data_train.Survived == 0].value_counts() survived_1 = data_train.Pclass[data_train.Survived == 1].value_counts() df = pd.DataFrame({'获救': survived_1, '未获救': survived_0}) df.plot(kind='bar', stacked=True) plt.title('各船舱乘客获救情况') plt.xlabel('船舱等级') plt.ylabel('人数') # 查看性别的获救情况 survived_0 = data_train.Sex[data_train.Survived == 0].value_counts() survived_1 = data_train.Sex[data_train.Survived == 1].value_counts() df2 = pd.DataFrame({'获救': survived_1, '未获救': survived_0}) df2.plot(kind='bar', stacked=True) plt.title('男女乘客获救情况') plt.xlabel('性别') plt.ylabel('人数')
#查看各船舱级别下的男女获救情况 fig=figure() plt.subplot(141) data_train.Survived[data_train.Sex=='female'][data_train.Pclass==3].value_counts().sort_index().plot(kind='bar',color='pink') plt.xticks(arange(2),['未获救','获救']) plt.yticks(arange(0,301,50)) plt.legend(['低等舱/女生'],loc='best') plt.subplot(142) data_train.Survived[data_train.Sex=='female'][data_train.Pclass!=3].value_counts().sort_index().plot(kind='bar',color='hotpink') plt.xticks(arange(2),['未获救','获救']) plt.yticks(arange(0,301,50)) plt.legend(['高等舱/女生'],loc='best') plt.subplot(143) data_train.Survived[data_train.Sex=='male'][data_train.Pclass==3].value_counts().sort_index().plot(kind='bar',color='lightsteelblue') plt.xticks(arange(2),['未获救','获救']) plt.yticks(arange(0,301,50)) plt.legend(['低等舱/男生'],loc='best') plt.subplot(144) data_train.Survived[data_train.Sex=='male'][data_train.Pclass!=3].value_counts().sort_index().plot(kind='bar',color='cornflowerblue') plt.xticks(arange(2),['未获救','获救']) plt.yticks(arange(0,301,50)) plt.legend(['高等舱/男生'],loc='best') fig.tight_layout() plt.show()
从这里可以看出来,获救几率和船舱等级成正比,船舱等级越高获救几率越大。
从这里可以看出,女性的获救几率明显大于男性。
对其他情况统一进行数据处理:
import matplotlib import matplotlib.pyplot as plt import numpy as np import pandas as pd from pylab import * fig=figure() fig.set(alpha=0.2) plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 plt.rcParams['axes.unicode_minus']=False #用来正常显示负号 data_train=pd.read_csv("E:/titanic/train.csv") plt.subplot(341) data_train.Survived.value_counts().plot(kind='bar') plt.title("获救情况(1为获救)") plt.ylabel("人数") plt.subplot(342) data_train.Pclass.value_counts().plot(kind='bar') plt.title("乘客等级分布") plt.ylabel("人数") plt.subplot(344) y=data_train.Age x=data_train.Survived plt.scatter(x,y) plt.title("按年龄看获救分布(1)为获救") plt.ylabel("年龄") plt.subplot(312) y=data_train.Age.value_counts() y.sort_index().plot(kind='bar') plt.xlabel("年龄") plt.ylabel("人数") plt.title("各年龄的乘客人数") plt.subplot(313) data_train.Age[data_train.Pclass==1].plot(kind='kde')#密度图 data_train.Age[data_train.Pclass==2].plot(kind='kde') data_train.Age[data_train.Pclass==3].plot(kind='kde') plt.xlabel("年龄") plt.ylabel("密度") plt.title("各等级的乘客年龄分布") plt.legend(('头等舱','二等舱','三等舱'),loc='best') plt.subplot(343) data_train.Embarked.value_counts().plot(kind='bar') plt.title("各登船口岸上船人数") plt.ylabel("人数") #subplots_adjust(wspace=0.5,hspace=1)#也可以调节各图形之间的间距 fig.tight_layout()#自动调整各图形之间的间距 plt.show()
到此我们可以针对图标结论做出猜测:
- 女性比男性更容易获救。
- 社会地位高的人更容易获救。
- 获救几率与年龄有关。
通过第一步的info函数查看数据的缺失情况,发现Age(年龄)缺失的数据较少,所以采用插值法来处理。用到的插值方法是随机森林。而Cabin(船舱号)则缺失了约3/4,而船舱号码暂时看不出来对获救有什么影响,所以我选择了对其进行数值化,有船舱号的值记为为1,没有船舱号的记为0。同样,为了方便后面的建模,我需要对非数值的属性Sex(性别),Embarked(登舱口),Name(名字),Ticket(票号)进行同样的数值化处理。这里用到了pandas库中的dummies函数。
from sklearn.ensemble import RandomForestRegressor import numpy as np import pandas as pd from sklearn import preprocessing data_train=pd.read_csv("E:/titanic/train.csv") # 使用 RandomForestClassifier 填补缺失的年龄属性 def set_missing_ages(df): age_df=df[['Age','Fare','Parch','SibSp','Pclass']] known_age=age_df[age_df.Age.notnull()].as_matrix() unknown_age=age_df[age_df.Age.isnull()].as_matrix() y=known_age[:,0]#第一列所有元素 x=known_age[:,1:]#分割出矩阵第二列以后的所有元素 rfr=RandomForestRegressor(random_state=0,n_estimators=2000,n_jobs=-1) rfr.fit(x,y) predictedAges=rfr.predict(unknown_age[:,1:]) df.loc[(df.Age.isnull()),'Age']=predictedAges#loc通过行标签来索引数据 return df def set_Cabin_type(df): df.loc[ (df.Cabin.notnull()), 'Cabin' ] = "Yes" df.loc[ (df.Cabin.isnull()), 'Cabin' ] = "No" return df data_train = set_missing_ages(data_train) data_train = set_Cabin_type(data_train) data_train.to_csv('processed_data1.csv')#新文件夹没有空值 dummies_Cabin=pd.get_dummies(data_train['Cabin'],prefix='Cabin') dummies_Embarked=pd.get_dummies(data_train['Embarked'],prefix='Embarked') dummies_Sex = pd.get_dummies(data_train['Sex'], prefix= 'Sex') dummies_Pclass = pd.get_dummies(data_train['Pclass'], prefix= 'Pclass') df = pd.concat([data_train, dummies_Cabin, dummies_Embarked, dummies_Sex, dummies_Pclass], axis=1)#增加列属性,concat默认是增加行,axis=1为增加列 df.drop(['Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked'], axis=1, inplace=True)#drop为删除原来的列,axis=1为删除列 df.to_csv('processed_data2.csv')#新文件夹的数据都为数值型,对原数据进行了特征因子化
处理后的数据都为数值型,但一些值的变化范围太大,如Fare,Age等,需要对其进行规范化处理,我采用的是零—均值规范化。
#将Age和Fare两个属性进行零——均值标准化。 scale_age=(df['Age']-df['Age'].mean())/df['Age'].std() scale_fare=(df['Fare']-df['Fare'].mean())/df['Fare'].std() df.copy() df['Age']=scale_age df['Fare']=scale_fare df.to_csv('processed_data3.csv')
输出文件:
构建逻辑回归模型并进行预测:
from sklearn import linear_model import numpy as np from sklearn.ensemble import RandomForestRegressor import pandas as pd from sklearn import preprocessing from datapreprocessing import set_Cabin_type df=pd.read_csv("E:/titanic/processed_data3.csv") train_df = df.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*') train_np = train_df.as_matrix() # y即Survival结果 y = train_np[:, 0] # X即特征属性值 X = train_np[:, 1:] # fit到LogisticRegression之中 clf = linear_model.LogisticRegression(C=1.0, penalty='l1', tol=1e-6) clf.fit(X, y) ####对测试数据同样进行数据预处理 data_test = pd.read_csv("E:/titanic/data/test.csv") data_train=pd.read_csv("E:/titanic/data/train.csv") #构建同一个随机森林 age_df=data_train[['Age','Fare','Parch','SibSp','Pclass']] known_age=age_df[age_df.Age.notnull()].as_matrix() unknown_age=age_df[age_df.Age.isnull()].as_matrix() y=known_age[:,0]#第一列所有元素 x=known_age[:,1:]#分割出矩阵第二列以后的所有元素 rfr=RandomForestRegressor(random_state=0,n_estimators=2000,n_jobs=-1) rfr.fit(x,y) data_test.loc[ (data_test.Fare.isnull()), 'Fare' ] = 0 tmp_df = data_test[['Age','Fare', 'Parch', 'SibSp', 'Pclass']] null_age = tmp_df[data_test.Age.isnull()].as_matrix() X = null_age[:, 1:] predictedAges = rfr.predict(X) data_test.loc[ (data_test.Age.isnull()), 'Age' ] = predictedAges data_test = set_Cabin_type(data_test) dummies_Cabin = pd.get_dummies(data_test['Cabin'], prefix= 'Cabin') dummies_Embarked = pd.get_dummies(data_test['Embarked'], prefix= 'Embarked') dummies_Sex = pd.get_dummies(data_test['Sex'], prefix= 'Sex') dummies_Pclass = pd.get_dummies(data_test['Pclass'], prefix= 'Pclass') df_test = pd.concat([data_test, dummies_Cabin, dummies_Embarked, dummies_Sex, dummies_Pclass], axis=1) df_test.drop(['Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked'], axis=1, inplace=True) data_test.to_csv('processed_test_data1.csv')#新文件夹没有空值 #将Age和Fare两个属性进行零——均值标准化。 scale_age=(df['Age']-df['Age'].mean())/df['Age'].std() scale_fare=(df['Fare']-df['Fare'].mean())/df['Fare'].std() df.copy() df['Age']=scale_age df['Fare']=scale_fare df.to_csv('processed_test_data2.csv') #用逻辑回归模型做预测 test = df_test.filter(regex='Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*') predictions = clf.predict(test) result = pd.DataFrame({'PassengerId':data_test['PassengerId'].as_matrix(), 'Survived':predictions.astype(np.int32)}) result.to_csv("logistic_regression_predictions.csv", index=False)
预测部分结果如下:
这个结果评分在kaggle上是0.76076
参考自:
https://blog.csdn.net/han_xiaoyang/article/details/49797143
https://blog.csdn.net/weixin_42036641/article/details/80294896
https://www.cnblogs.com/cutd/p/5713520.html