數(shù)據(jù)分析 | 任性娜娜细溅,在線算命

大家好褥傍,今天也是被生活安排地明明白白的一天。

來龍去脈不細說了喇聊,總而言之就是根據(jù)賭約我要完成Kaggle里一個比賽恍风。縱然對方十分親切地幫我挑選了一個最最基礎的入門級別的比賽誓篱,可我一個數(shù)據(jù)分析小學生朋贬,忽然去搞機器學習……那好像還是有點拔苗助長喲(⊙_⊙;)

好吧,買定離手愿賭服輸窜骄。那么锦募,我就開始搜索如何從零開始入門機器學習了。
一個小時過后:我開始慌惹
兩個小時過后:我是誰我在哪我要干什么邻遏?糠亩?虐骑?

大概流程和框架捋了一下,娜某人就這么漫不經(jīng)心地去決定別人的生死了削解!這本生死簿富弦,就是正義!

泰坦尼克號幸存者預測 Titanic: Machine Learning from Disaster

先研究研究到底需要干什么吧》胀裕現(xiàn)在我手里有兩張表,一張叫train济似,一張叫test矫废。第一張表(train)上記錄了泰坦尼克號部分(891位)客人的姓名性別家里幾口人人均幾畝地等等各種信息,包括他們最后有沒有生還(Survived)砰蠢;另一張表(test)蓖扑,和train一樣也記錄著一部分(418位)客人的各種信息,唯一的不同是Survived這一列為空值台舱,也就是說不知道他們有沒有在災難中獲救律杠。好的!懂了竞惋!我的任務就是通過手里的兩張表安排一下那418位乘客有沒有獲救柜去。

891條數(shù)據(jù)有Survived值,418條數(shù)據(jù)Survived為空

表中各特征的含義如下:
PassengerId: 乘客編號
Survived: 是否生還(0 = 死亡拆宛,1 = 生存)
Pclass: 船票級別(1 = 高級嗓奢,2 = 中級,3 = 低級)
Name: 姓名
Sex: 性別(male = 男性浑厚,female = 女性)
Age: 年齡
SibSp: 在 Titanic 上的兄弟姐妹以及配偶的人數(shù)
Parch: 在 Titanic 上的父母以及子女的人數(shù)
Ticket: 船票編號
Fare: 票價
Cabin: 所在的船艙
Embarked: 登船的港口 (C=Cherbourg, Q=Queenstown, S=Southampton)

接下來是《算命速成》股耽,可能將浪費你人生中寶貴的15分鐘:
0 導入基本模塊以及加載數(shù)據(jù)
1 數(shù)據(jù)初探
2 數(shù)據(jù)預處理
3 特征工程
4 模型選擇
5 模型優(yōu)化

0 導入基本模塊以及加載數(shù)據(jù)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
% matplotlib inline

from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默認字體
mpl.rcParams['axes.unicode_minus'] # 負號正常顯示

import warnings
warnings.filterwarnings('ignore') 

import os
os.chdir(r'..\Desktop\泰坦尼克號幸存者模擬')
data = pd.read_csv('train.csv',header = 0)
1 數(shù)據(jù)初探

數(shù)據(jù)加載好了,看看我們能從數(shù)據(jù)里發(fā)現(xiàn)什么小秘密吧钳幅。
這里總結(jié)了一些數(shù)據(jù)初判的方法:

1.1 查看基本特征(空值物蝙、統(tǒng)計描述等)

(1) df.info() #查看基本信息
(2) df.isnull().sum() #查看每列空值數(shù)量,查看非空使用notnull()
(3) df.describe() #查看每列數(shù)據(jù)均值敢艰、標準差诬乞、分位數(shù)等統(tǒng)計值
(4) df['Pclass'].unique() #查看某列的幾種不重復的結(jié)果是什么

具體來看看:
1.2 查看基本數(shù)據(jù)分布(分布分析、對比分析等)

(1) df['Fare'].hist(bins=10) #查看某列直方圖盖矫,設置分段數(shù)量用bins=10
(2) df['Fare'].plot(kind='kde',style='k--',grid=True) #查看某列密度圖
(3) df['Fare'].boxplot(by='Pclass') #查看某列箱型圖丽惭,可按另一個特征分組查看
(4) 有一些特征變量是一些連續(xù)的數(shù)值,這時可以按照區(qū)間查看:
例如年齡Age辈双,是這樣的一些數(shù)值:18,30,45……责掏,單看這些年齡值不容易發(fā)現(xiàn)規(guī)律,這時用pd.cut()把它們劃分在不同區(qū)間里更容易看出規(guī)律湃望。

 bins = 4 #分成4組
 group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior'] #每組標簽
 agecut = pd.cut(data['Age'],bins,labels=group_names,right = False) #分組區(qū)間
 agecut_count = agecut.value_counts(sort = False)#不按count數(shù)量多少排序

針對上面的步驟舉幾個栗子:

# (1)直方圖:查看票價Fare的分布换衬,可發(fā)現(xiàn)大多為低價票
data.hist(column='Fare',
          bins = 20,        # bin箱子個數(shù)
          histtype = 'bar', # histtype 風格痰驱,bar,barstacked瞳浦,step担映,stepfilled
          align = 'mid',    # align : {‘left’, ‘mid’, ‘right’}, optional(對齊方式)
          orientation = 'vertical',# orientation 水平還是垂直{‘horizontal’, ‘vertical’}
          alpha=0.6,
          color='forestgreen',
          normed =True)    # normed 標準化

# (2)密度圖:查看票價Fare的分布
data['Fare'].plot(kind='kde',style='--',grid = True)
直方圖和密度圖:查看Fare票價分布,發(fā)現(xiàn)多數(shù)為低價票
# (3)箱型圖:查看按船艙等級Pclass分類的票價Fare箱型圖叫潦,船票級別1=高級蝇完,2=中等,3=低等
data.boxplot(column='Fare',
             by = 'Pclass',
             sym = 'o',    # 異常點形狀
             vert = True,  # 是否垂直
             whis = 1.5,   # IQR矗蕊,默認1.5短蜕,也可以設置區(qū)間比如[5,95],代表強制上下邊緣為數(shù)據(jù)95%和5%位置
             patch_artist = True,  # 上下四分位框內(nèi)是否填充傻咖,True為填充
             meanline = False,showmeans=True,  # 是否有均值線及其形狀
             showbox = True,     # 是否顯示箱線
             showcaps = True,    # 是否顯示邊緣線
             showfliers = True,  # 是否顯示異常值
             notch = False,      # 中間箱體是否缺口
             ) 
箱型圖:按不同船艙等級Pclass查看票價Fare分布朋魔,船艙等級越高票價越高
# (4)用pd.cut()查看年齡Age分組占比
bins = [0, 18, 40, 60, 80]
group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
agecut = pd.cut(data['Age'],bins)
agecut_count = agecut.value_counts(sort = False)
colors = ['lightcyan','paleturquoise','mediumturquoise','c']
plt.pie(agecut_count,labels = group_names,autopct='%i %%',colors=colors)
餅圖:查看年齡分組占比,大部分乘客處在18~40歲這個區(qū)間
# 除此之外還可以用熱圖初步查看幾個特征之間的相關(guān)性:
sns.heatmap(data[['Survived','SibSp','Parch','Age','Fare']].corr(),annot=True, fmt = '.2f', cmap = 'coolwarm')
熱圖:圖中發(fā)現(xiàn)似乎只有Fare與生存率密切相關(guān)卿操,但這不意味著其他因素與生存無關(guān)
1.3 查看數(shù)據(jù)分組分布(groupby顽腾、crosstab聊训、pivot_table、sns.pairplot)

只分析單一因素是不夠全面的,我們還需要查看不同因素聯(lián)立時的數(shù)據(jù)分布腿椎,下面的方法都可以用來進行分組查看:

(1) groupby:分組統(tǒng)計瞬浓,可代替下面的兩種
temp = data[['Sex','Pclass','Survived']].groupby(['Pclass','Sex']).sum()
temp.plot(kind='bar')

(2)交叉表crosstab:可以按照指定的行和列統(tǒng)計分組頻數(shù)
temp = pd.crosstab([data['Pclass'], data['Sex']], data.Survived.astype(bool))
temp.plot(kind='bar', stacked=True, color=['red','blue'], grid=False)

(3)透視表pivot_table:產(chǎn)生類似數(shù)據(jù)透視表的效果
temp = pd.pivot_table(data, index='Pclass', columns='Sex',values = 'Survived')
temp.plot(kind='bar',stacked=True)

(4)查看多個變量兩兩之間的相互關(guān)系
sns.pairplot()

快來看看具體是怎么應用的:
1.3.1 按照船上家庭人數(shù)查看生存率:groupby

data['Family_Size'] = data['Parch'] + data['SibSp'] + 1
temp = data[['Family_Size','Survived']].groupby(['Family_Size']).mean()
temp.plot(kind='bar',color='lightcoral',alpha=0.9)
家庭人數(shù)增多時生存率呈現(xiàn)增加趨勢旋讹,但人數(shù)大于一定值(4個)后生存率會大幅減小

1.3.2 查看登船港口Embarked與生存率的關(guān)系:groupby

temp = data[['Embarked','Survived']].groupby(['Embarked']).mean()
temp.plot(kind='bar',color = 'crimson',alpha=0.7)

泰坦尼克號航行路線:Southampton--Cherbourg-Octeville--Queenstown
考慮到在Southampton港口和Cherbourg-Octeville港口登船的人將有機會在Queenstown港口之前下船序厉,那么前面兩個港口登船的人果真生存率會更大嗎?


在Cherbourg-Octeville上船的人生還幾率最大溪王,Queenstown次之腮鞍,Southampton最小

1.3.3 查看船艙Cabin與生存率的關(guān)系,用船艙號首字母分組:groupby

data['Cabin_Initial'] = data['Cabin'].str[0]
temp = data[['Cabin_Initial','Survived']].groupby(['Cabin_Initial']).mean()
temp.plot(kind='bar',color = 'dodgerblue',alpha=0.7)
似乎并不能看出船艙號和獲救有什么直接關(guān)系莹菱,但直覺上船艙號決定了船艙位置移国,應該和逃生相關(guān)

1.3.4 查看按照Age分組區(qū)間幸存情況:crosstab

temp = pd.crosstab(agecut.values,data['Survived'])
temp.plot(kind='bar',color=['red','green'],alpha=0.7)
雖然18~40歲的乘客獲救人數(shù)最多,但獲救占比很小

1.3.5 按照船艙等級和性別查看幸存人數(shù):crosstab

temp = pd.crosstab([data['Pclass'], data['Sex']], data['Survived'].astype(bool))
temp.plot(kind='bar', stacked=True, color=['red','green'],alpha=0.7)
基本上呈現(xiàn)出“Lady First”道伟,同時船艙等級對能否獲救也有顯著影響

1.3.6 查看多個變量兩兩之間的相互關(guān)系

sns.pairplot(data[['Survived','Pclass','Age','Fare']], hue='Survived', palette = 'husl',diag_kind='kde',diag_kws=dict(shade=True),plot_kws=dict(s=10),markers=["o", "x"])
1.4 查看特征類別分布是否平衡

sns.countplot(x='Survived',data=data)

幸存和死亡人數(shù)相差不大迹缀,可以認為屬于類別平衡問題。

類別不平衡(class-imbalance)是指在分類任務中蜜徽,不同類別的訓練樣例數(shù)目相差很大的情況祝懂。(比如本例是一個二分類問題,每位乘客分為生存或者死亡兩種狀態(tài)拘鞋,如果絕大部分乘客死亡而生存人數(shù)僅有幾個的話砚蓬,就叫類別不平衡。)為什么要進行這樣的判斷呢盆色?因為對于分類問題的訓練集灰蛙,如果有999個都屬于A類祟剔,只有1個屬于B類,那么在預測時只需要永遠將新樣本預測為A類摩梧,這個分類器就能達到99.9%的精度物延,但這樣是沒有意義的。現(xiàn)實中仅父,在銀行信用欺詐交易識別中叛薯,屬于欺詐交易的應該是很少部分,絕大部分交易是正常的笙纤,這就是一個正常的類別不平衡問題案训。如果出現(xiàn)類別不平衡的情況,已經(jīng)超出我目前的知識范圍了粪糙,可以參考這里


2 數(shù)據(jù)預處理

經(jīng)過第一步我們假裝已經(jīng)了解手里的數(shù)據(jù)長什么樣了忿项,下面就需要對其中一些特征進行預處理了蓉冈。在此之前需要先把train表和test表用pd.concat()拼成一張表,這樣按照接下來的步驟處理完它兩還是相同的數(shù)據(jù)分布轩触。

data_01 = pd.read_csv('train.csv',header = 0)
data_02 = pd.read_csv('test.csv',header = 0)
data_12 = pd.concat([data_01,data_02]) #合并兩個
data_12.reset_index(inplace=True)

下面總結(jié)了一些數(shù)據(jù)預處理的方法:

2.1 處理缺失值
缺失值情況

(1) 如果缺失值對于學習來說不是很重要寞酿,同時占比非常小:可以刪掉這條數(shù)據(jù)或者填補均值or眾值
(2) 如果缺失值的特征相對重要脱柱,而且不屬于數(shù)值型:可以考慮重新賦值
(3) 如果缺失值占比很大而且相對重要:可以建立模型(線性回歸伐弹、隨機森林等)預測缺失值

2.1.1 年齡Age(177個缺失值)
由于年齡是比較重要的特征,缺失值占比也比較大榨为,考慮將Age完整的項作為訓練集惨好,將Age缺失的項作為測試集,采用RandomForestRegressor()随闺。因為想要利用其他特征量來預測Age日川,所以這里把Age的缺失值處理放到下面一步,先分析其他特征矩乐。

2.1.2 登船港口Embarked(2個缺失值)
缺失值很少龄句,考慮用眾值填補:

train_data = pd.DataFrame()

mod = data_12['Embarked'].mode()[0]
data_12['Embarked'].fillna(mod,inplace=True)
train_data['Embarked'] = data_12['Embarked']

2.1.3 船艙Cabin(1014個缺失值)
對于所在的船艙的大量缺失值,考慮按特殊情況重新賦值為"Z0"(特殊情況是指散罕,結(jié)合票價考慮分歇,這些缺失值出現(xiàn)的原因可能是因為實際中這些人沒有船艙)

data_12['Cabin'].fillna('Z0',inplace=True)
train_data['Cabin'] = data_12['Cabin']

2.1.4 票價Fare(1個缺失值)
票價Fare的缺失值只有一個,考慮按他所在的船艙等級均價填補欧漱;另外發(fā)現(xiàn)有些人的票價為0职抡,這些人共享同一個Ticket號碼,他們應該是團體票硫椰,因此還需要將團體票按總票價平均分配給這個團體中的每個人

# 缺失票價用所在船艙等級票價均值填補
train_data['Fare'] = data_12['Fare']
train_data['Pclass'] = data_12['Pclass']
train_data['Fare'] = train_data['Fare'].fillna(train_data.groupby('Pclass').transform('mean'))

# 將團體票的總價平均分配給組里每個人
train_data['Ticket'] = data_12['Ticket']
train_data['Group_Member'] = train_data['Fare'].groupby(by=train_data['Ticket']).transform('count')
# transform(func, args, *kwargs) 方法會把func應用到所有分組繁调,然后把結(jié)果放置到原數(shù)組的index上

train_data['Fare'] = train_data['Fare'] / train_data['Group_Member']

那么我們就把登船港口萨蚕、所在船艙和票價的缺失值填充好了!Age放在下一步處理蹄胰!

2.2 處理異常值

剛剛提到的Fare票價為0的值其實就算異常值岳遥,在處理上應該具體問題具體分析,看它為什么異常裕寨,異常在哪里浩蓉。用第一步中繪制箱型圖的方法可以查看異常值情況。箱型圖這里小小的解釋一下宾袜,箱型圖是用作顯示一組數(shù)據(jù)分散情況的統(tǒng)計圖捻艳。

箱形圖提供了一種只用5個點對數(shù)據(jù)集做簡單總結(jié)的方式。
這5個點包括中點庆猫、Q1认轨、Q3、分部狀態(tài)的高位和低位月培。
① 矩形盒兩端的邊線分別對應數(shù)據(jù)批的上下四分位數(shù)(Q3和Q1)嘁字。
② 矩形盒內(nèi)部的線為中位線,代表了中位數(shù)(Xm)杉畜。
③ 在Q3+1.5IQR和Q1-1.5IQR處的線段為異常值截斷點纪蜒,稱其為內(nèi)限;在Q3+3IQR和Q1-3IQR處的線段稱其為外限此叠。處于內(nèi)限以外位置的點表示的數(shù)據(jù)都是異常值:其中在內(nèi)限與外限之間的異常值為溫和的異常值(mild outliers)纯续;在外限以外的為極端的異常值(extreme outliers)。
④ 四分位距IQR=Q3-Q1灭袁。.
(以上內(nèi)容整理自百度百科)

2.3 數(shù)據(jù)連續(xù)屬性離散化

連續(xù)屬性變換成分類屬性猬错,即連續(xù)屬性離散化。第一步提到的年齡分組區(qū)間就是在做離散化简卧。在數(shù)值的取值范圍內(nèi)設定若干個離散劃分點兔魂,將取值范圍劃分為一些離散化的區(qū)間,最后用不同的符號或整數(shù)值代表每個子區(qū)間中的數(shù)據(jù)值举娩。
下面看看票價Fare如何做這樣的分組處理:

# 數(shù)據(jù)連續(xù)屬性離散化:票價Fare
train_data['Fare_bin'] = pd.qcut(train_data['Fare'], 5)
#cut是根據(jù)數(shù)值本身來選擇箱子均勻間隔析校,qcut是根據(jù)這些值的頻率來選擇箱子的均勻間隔
train_data['Fare_bin'].head()

將得到這樣的分組效果:Categories (5, interval[float64]): [(-0.001, 7.229] < (7.229, 7.896] < (7.896, 10.5] < (10.5, 26.277] < (26.277, 128.082]]

每個人會根據(jù)票價被劃分在不同組:
僅截取部分乘客
2.4 數(shù)據(jù)標準化

數(shù)據(jù)的標準化是將數(shù)據(jù)按比例縮放,使之落入一個小的特定區(qū)間铜涉。常在比較和評價的指標處理中用到智玻,去除數(shù)據(jù)的單位限制,將其轉(zhuǎn)化為無量綱的純數(shù)值芙代,便于不同單位或量級的指標能夠進行比較和加權(quán)吊奢。
(1) MinMaxScaler(最小最大值標準化):將數(shù)據(jù)統(tǒng)一映射到[0,1]區(qū)間上
(2) Standardization標準化:將特征數(shù)據(jù)的分布調(diào)整成標準正太分布,也叫高斯分布纹烹,也就是使得數(shù)據(jù)的均值維0页滚,方差為1召边。

下面以票價Fare為例做標準化處理:

# 數(shù)據(jù)標準化:票價Fare
from sklearn import preprocessing
train_data['Fare_scaled'] = preprocessing.StandardScaler().fit_transform(train_data['Fare'].values.reshape(-1,1))
#X.reshape(-1,1)是指我們不知道X的shape屬性是多少,但是想讓X變成只有一列裹驰。
#X.reshape(-1,1)由Numpy自動計算出有1309行隧熙,新的數(shù)組shape屬性為(1309, 1),與Fare列數(shù)據(jù)配套幻林。
2.5 特征類型轉(zhuǎn)換

回憶一下我們的數(shù)據(jù)贞盯,有一些特征是這樣不同類別的取值:male男性 / female女性,這樣的變量需要轉(zhuǎn)化為數(shù)值型才能被模型識別沪饺。但如果只是簡單地把男性轉(zhuǎn)化為0女性轉(zhuǎn)化為1躏敢,就會為它們帶來數(shù)值上的意義。例如用數(shù)字1-12表示1-12月整葡,那么就潛在表示了12月和1月差得很遠件余,其實它們離得很近。這時就需要引入下面的方法了:

(1) 引入虛擬變量dummy variable
當頻繁出現(xiàn)的幾個獨立變量時遭居,可以用pandas.get_dummies()將定性變量轉(zhuǎn)換為虛擬變量蛾扇。

(2) factorize因子化
當某個特征有非常多取值時,可以使用pandas.factorize()創(chuàng)建一些數(shù)字來表示類別變量魏滚,對每一個類別映射一個ID,這種映射最后只生成一個特征坟漱,不像dummy那樣生成多個特征鼠次。

說了這么多,到底怎么完成這種炫酷的操作呢:

# 對于船艙等級Pclass芋齿,引入dummy變量
Pclass_dummies_df = pd.get_dummies(train_data['Pclass']).rename(columns=lambda x: 'Pclass_' + str(x))
train_data = pd.concat([train_data, Pclass_dummies_df], axis=1)

Pclass這一特征就轉(zhuǎn)化完成了:
為船艙等級Pclass引入虛擬變量

其他幾個特征也同樣需要進行轉(zhuǎn)化:

# 票價Fare分組
Fare_bin_dummies_df = pd.get_dummies(train_data['Fare_bin']).rename(columns=lambda x: 'Fare_' + str(x))
train_data = pd.concat([train_data, Fare_bin_dummies_df], axis=1)


# 登船港口Embarked
Embarked_dummies_df = pd.get_dummies(train_data['Embarked']).rename(columns=lambda x: 'Embarked_' + str(x))
train_data = pd.concat([train_data, Embarked_dummies_df], axis=1)


# 性別Sex
train_data['Sex'] = data_12['Sex']
Sex_dummies_df = pd.get_dummies(train_data['Sex']).rename(columns=lambda x: 'Sex_' + str(x))
train_data = pd.concat([train_data, Sex_dummies_df], axis=1)

再來看船艙編號Cabin腥寇,這一特征下存在非常多的變量,所以這次采用factorize因子化的方法:

# 對于船艙Cabin:采用factorize因子化方法:
# 首先提取首字母Cabin_Initial
train_data['Cabin_Initial'] = data_12['Cabin'].str[0]
train_data['Cabin_Initial_factorize'] = pd.factorize(train_data['Cabin_Initial'])[0]

看下前幾行的效果:
factorize因子化

3 特征工程

特征工程即從各項參數(shù)中提取出可能影響到最終結(jié)果的特征觅捆,作為模型的預測依據(jù)赦役。回顧上面一步栅炒,已經(jīng)處理好了缺失值掂摔、異常值,也已經(jīng)轉(zhuǎn)換了一些特征的變量類型∮蓿現(xiàn)在再來梳理一下手里的特征:

(1)登船港口Embarked
經(jīng)過Step2預處理乙漓,登船港口引入虛擬變量,轉(zhuǎn)換為Embarked_C释移,Embarked_Q叭披,Embarked_S;
(2)票價Fare
經(jīng)過Step2預處理玩讳,將票價分為了5個等級涩蜘;
(3)性別Sex
經(jīng)過Step2預處理嚼贡,性別Sex轉(zhuǎn)換為Sex_female,Sex_male同诫;
(4)船艙等級Pclass
經(jīng)過Step2預處理粤策,船艙等級Pclass轉(zhuǎn)換為Pclass_1,Pclass_2剩辟,Pclass_3掐场;
(5)船艙Cabin
經(jīng)過Step2預處理,船艙Cabin轉(zhuǎn)換為Cabin_Initial_factorize贩猎;
(6)姓名Name
前面一直沒有細看這個特征熊户,我們可以從名字中提取到稱呼(例如“Mr.”,“Capt”等),或許可以發(fā)現(xiàn)社會地位對生存率的影響吭服。
(7)家庭成員Parch and SibSp
在Step1中發(fā)現(xiàn)嚷堡,家庭成員的多少對獲救有一定影響,這里可以將兩項合并一下艇棕,研究家庭成員數(shù)量對生存率的影響蝌戒。還可以根據(jù)人數(shù)對家庭進行分類:單個人、小型家庭沼琉、中型家庭北苟、大型家庭。
(8)年齡Age
這一步將解決step2的遺留問題打瘪,用模型預測缺失年齡友鼻。
(9)船票號碼Ticket
觀察Ticket的值,前綴相同的號碼似乎是一起訂的闺骚,他們應該也是在同一個船倉的彩扔,所以這里把船票號碼前綴提取出來。(后面發(fā)現(xiàn)預測時這一特征并不是重要特征僻爽。)

3.1 姓名Name提取Title
train_data['Title']=data_12['Name'].apply(lambda x: x.split(',')[1].split('.')[0].strip())
train_data['Title'].unique()

['Mr', 'Mrs', 'Miss', 'Master', 'Don', 'Rev', 'Dr', 'Mme', 'Ms','Major', 'Lady', 'Sir', 'Mlle', 'Col', 'Capt', 'the Countess','Jonkheer', 'Dona']
發(fā)現(xiàn)title種類很多虫碉,可以將相似的頭銜做合并為5類,并且引入虛擬變量胸梆。
(1) 有職務:Staff
Capt --上校
Col -- 上校
Major -- 少校
Dr -- 醫(yī)生/博士
Rev.= reverend -- 基督教的牧師

(2) 沒有頭銜的男性:Mr
Mr.= mister -- 先生

(3) 沒有頭銜的已婚女性:Mrs
Mrs.= mistress -- 太太/夫人
Mme.=Madame -- 女士
Ms -- 婚姻狀態(tài)不明的女性

(4) 沒有頭銜的未婚女性:Miss
Miss -- 未婚女性
Mlle -- 小姐

(5) 貴族:Noble
Lady -- 女士
Dona -- 夫人敦捧,女士
Master -- 主人
Don -- 先生
Sir -- 先生
Jonkheer -- 鄉(xiāng)紳
The Countless -- 女伯爵

train_data['Title'][train_data.Title.isin(['Capt', 'Col', 'Major', 'Dr', 'Rev'])] = 'Staff'
train_data['Title'][train_data.Title.isin(['Don', 'Sir', 'the Countess', 'Dona', 'Lady','Master','Jonkheer'])] = 'Noble'
train_data['Title'][train_data.Title.isin(['Mr'])] = 'Mr'
train_data['Title'][train_data.Title.isin(['Mme', 'Ms', 'Mrs'])] = 'Mrs'
train_data['Title'][train_data.Title.isin(['Mlle', 'Miss'])] = 'Miss'

# 稱謂Title:引入dummy變量
Title_dummies_df = pd.get_dummies(train_data['Title']).rename(columns=lambda x: 'Title_' + str(x))
train_data = pd.concat([train_data, Title_dummies_df], axis=1)
3.2 家庭成員Parch and SibSp

Parch和SibSp可以合并成家庭成員數(shù)量Family_Size,分類后引入虛擬變量碰镜。

train_data['Family_Size'] = data_12['Parch'] + data_12['SibSp'] + 1
def Family_Category(size):
    if size == 1:
        return 'Single'
    elif size < 3:
        return 'Small'
    elif size < 5:
        return 'Medium'
    else:
        return 'Large'
train_data['Family_Category'] = train_data['Family_Size'].map(Family_Category)
# Series的map方法可以接受一個函數(shù)或含有映射關(guān)系的字典型對象绞惦。 使用map()是一種實現(xiàn)元素級轉(zhuǎn)換以及其他數(shù)據(jù)清理工作的便捷方式。 

# 家庭類型Family_Category:引入dummy變量
Family_Category_dummies_df = pd.get_dummies(train_data['Family_Category']).rename(columns=lambda x: 'Family_Category_' + str(x))
train_data = pd.concat([train_data, Family_Category_dummies_df], axis=1)
3.3 年齡Age

前面提到過對于年齡Age的缺失值洋措,將年齡完整的項作為訓練集济蝉,將年齡缺失的項作為測試集,采用RandomForestRegressor()預測。

from sklearn.ensemble import RandomForestRegressor

# 選擇訓練集數(shù)據(jù)
train_data['Age'] = data_12['Age']
age_df = train_data[['Age','Family_Size','Pclass','Sex_female','Sex_male','Fare']]
age_df_notnull = age_df[age_df['Age'].notnull()]
age_df_isnull = age_df[age_df['Age'].isnull()]
X = age_df_notnull.values[:,1:] # 除第一列Age外其他非空數(shù)據(jù)
Y = age_df_notnull.values[:,0]  # 第一列Age非空
# 隨機森林回歸
RFR = RandomForestRegressor(n_estimators=500, n_jobs=-1)
RFR.fit(X,Y) # 訓練
predictAges = RFR.predict(age_df_isnull.values[:,1:]) # 測試
train_data.loc[train_data['Age'].isnull(),['Age']]= predictAges

# 查看預測年齡Age前后數(shù)據(jù)分布:與之前數(shù)據(jù)分布基本相同
fig,ax=plt.subplots(1,2,figsize=(12,6))
data_12['Age'].hist(bins=20,ax=ax[0],color='green')
train_data['Age'].hist(bins=20,ax=ax[1],color='yellowgreen')
預測前后年齡分布相似

差點忘了年齡也應該做標準化處理:

from sklearn import preprocessing
scaler = preprocessing.StandardScaler()
train_data['Age_scaled'] = scaler.fit_transform(train_data['Age'].values.reshape(-1,1))
3.4 船票號碼Ticket

船票數(shù)字部分暫時沒看出什么規(guī)律王滤,先嘗試把字母部分提取出來吧:

Ticket = []
for i in list(train_data['Ticket']):
    if not i.isdigit() :
        Ticket.append(i.replace('.','').replace('/','').strip().split(' ')[0]) 
    else:
        Ticket.append('X')
        
train_data['Ticket'] = Ticket

# 船票Ticket字母部分:引入dummy變量
Ticket_dummies_df = pd.get_dummies(train_data['Ticket']).rename(columns=lambda x: 'Ticket_' + str(x))
train_data = pd.concat([train_data, Ticket_dummies_df], axis=1)

特征工程其實是非常非常重要的一步贺嫂,但能力太菜時間緊迫只能分析出這么多了……


4 模型選擇

可以用于分類的模型很多很多,我也看得眼花繚亂雁乡,可以參考這里第喳。


看了Kaggle論壇里好多大神的分享,暫時選了幾種python會調(diào)用的(原理目前還不理解)先看一下準確率踱稍。

Where is a beginner to start? I recommend starting with Trees, Bagging, Random Forests, and Boosting. They are basically different implementations of a decision tree, which is the easiest concept to learn and understand. (轉(zhuǎn)自Kaggle論壇

計算準確率前需要用到train_test_split()曲饱,它的作用是給定數(shù)據(jù)集X和類別標簽Y,將數(shù)據(jù)集按一定比例隨機切分為訓練集和測試集珠月。挑選了下面四種模型進行準確率的計算:

(1) 邏輯回歸 Logistic Regression
我們熟悉的線性回歸模型通忱┑恚可以處理因變量是連續(xù)變量的問題,如果因變量是分類變量啤挎,線性回歸模型就不再適用了驻谆,可用邏輯回歸模型解決。

(2) 支持向量機 SVM
SVM是Support Vector Machines支持向量機的縮寫庆聘,可以用來做分類和回歸胜臊。SVC是SVM的一種Type,是用來的做分類的伙判。概念有點難理解象对,基本概念以及參數(shù)說明可以參考這里這里

(3) 隨機森林 Random Forest
隨機森林是集成學習的一個子類宴抚,它依靠決策樹的投票選擇來決定最后的分類結(jié)果织盼。

隨機森林的工作原理是生成多個子模型,各自獨立地學習和作出預測酱塔。這些預測最后結(jié)合成單預測,因此優(yōu)于任何一個單分類的做出預測危虱。 一個形象的比喻:森林中召開會議羊娃,討論某個動物到底是老鼠還是松鼠,每棵樹都要獨立地發(fā)表自己對這個問題的看法埃跷,也就是每棵樹都要投票蕊玷。該動物到底是老鼠還是松鼠,要依據(jù)投票情況來確定弥雹,獲得票數(shù)最多的類別就是森林的分類結(jié)果垃帅。森林中的每棵樹都是獨立的,99.9%不相關(guān)的樹做出的預測結(jié)果涵蓋所有的情況剪勿,這些預測結(jié)果將會彼此抵消贸诚。少數(shù)優(yōu)秀的樹的預測結(jié)果將會超脫于蕓蕓“噪音”,做出一個好的預測。將若干個弱分類器的分類結(jié)果進行投票選擇酱固,從而組成一個強分類器械念,這就是隨機森林bagging的思想。(隨機森林通俗易懂的解釋

(4) 梯度提升Gradient Boosting
Boosting是一種知錯就改的思想运悲。通過一系列的迭代來優(yōu)化分類結(jié)果龄减,每迭代一次引入一個弱分類器,來克服現(xiàn)在已經(jīng)存在的弱分類器組合的缺點班眯。Gradient Boosting 在迭代的時候選擇梯度下降的方向來保證最后的結(jié)果最好希停。

損失函數(shù)用來描述模型的“靠譜”程度,假設模型沒有過擬合署隘,損失函數(shù)越大宠能,模型的錯誤率越高。讓損失函數(shù)持續(xù)下降定踱,就能使得模型不斷改性提升性能棍潘,其最好的方法就是使損失函數(shù)沿著梯度方向下降。(參考這里

#備份一下崖媚,以備不時之需
data_backup = train_data.copy()
# 刪掉不需要的特征
train_data.drop(['Embarked', 'Cabin', 'Fare', 'Pclass', 'Ticket', 'Group_Mumber','Cabin_Initial', 
                'Fare_bin', 'Family_Size', 'Family_Category', 'Age','Sex','Title'],axis=1,inplace=True)
# 分開訓練集和測試集
Titanic_train_data = train_data[:891]
Titanic_test_data = train_data[891:]
train_data_X = Titanic_train_data
train_data_Y = data_01['Survived']
test_data_X = Titanic_test_data

# 各種模型預測準確率
from sklearn.model_selection import train_test_split  
seed = 4
train_X,test_X,train_Y,test_Y=train_test_split(train_data_X,train_data_Y,test_size=0.4,random_state=seed)  

# Logistic Regression
from sklearn.linear_model import LogisticRegression  
LR=LogisticRegression(C=1.0,tol=1e-6,random_state=seed)  
LR.fit(train_X,train_Y)  
print(LR.score(test_X,test_Y))  

# SVC
from sklearn.svm import SVC  
SVC=SVC(C=2, kernel='rbf', decision_function_shape='ovo',random_state=seed)  
SVC.fit(train_X,train_Y)  
print(SVC.score(test_X,test_Y))  

# Random Forest
from sklearn.ensemble import RandomForestClassifier  
RF=RandomForestClassifier(n_estimators=500,max_depth=5,random_state=seed)  
RF.fit(train_X,train_Y)  
print(RF.score(test_X,test_Y))  

# GradientBoosting
from sklearn.ensemble import GradientBoostingClassifier  
GB=GradientBoostingClassifier(n_estimators=600,max_depth=5,random_state=seed)  
GB.fit(train_X,train_Y)  
print(GB.score(test_X,test_Y))  

Logistic Regression亦歉、SVC、Random Forest畅哑、GradientBoosting模型的得分依次為:
四種模型準確率

試著變換隨機數(shù)種子肴楷,前三種模型得分依然比GradientBoosting模型高≤牛可以考慮用前面三種任意一種來做最終預測赛蔫,或者通過votingClassifer綜合幾種模型。

5 模型優(yōu)化

雖說特征工程非常非常重要泥张,但模型優(yōu)化也是必不可少的呵恢。準備從下面兩個方面入手:

(1) 篩選重要特征
(2) 參數(shù)調(diào)整

5.1 篩選重要特征

這一步目標是找到與應變量高度相關(guān)的特征變量。

# 用兩個模型來篩選重要特征
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingClassifier

def get_top_n_features(train_data_X, train_data_Y, top_n_features):
    seed = 4
    
    # RandomForest
    RF_estimator = RandomForestClassifier(random_state=seed)
    RF_param_grid = {'n_estimators': [500,1000], 'min_samples_split': [2, 3], 'max_depth': [10,20], 'min_samples_leaf':[2,3]}
    RF_grid = model_selection.GridSearchCV(RF_estimator, RF_param_grid, cv=10, verbose=1)
    RF_grid.fit(train_data_X, train_data_Y)
    feature_imp_sorted_RF = pd.DataFrame({'feature': list(train_data_X),
                                          'importance': RF_grid.best_estimator_.feature_importances_}).sort_values('importance', ascending=False)
    features_top_n_RF = feature_imp_sorted_RF.head(top_n_features)['feature']
    print('Sample 10 Features from RF_Classifier')
    print(str(features_top_n_RF[:10]))

    # GradientBoosting
    GB_estimator =GradientBoostingClassifier(random_state=seed)
    GB_param_grid = {'n_estimators': [500,1000], 'learning_rate': [0.001, 0.01, 0.1], 'max_depth': [10,20], 'min_samples_leaf':[2,3]}
    GB_grid = model_selection.GridSearchCV(GB_estimator, GB_param_grid, cv=10, verbose=1)
    GB_grid.fit(train_data_X, train_data_Y)
    feature_imp_sorted_GB = pd.DataFrame({'feature': list(train_data_X),
                                           'importance': GB_grid.best_estimator_.feature_importances_}).sort_values('importance', ascending=False)
    features_top_n_GB = feature_imp_sorted_GB.head(top_n_features)['feature']
    print('Sample 10 Feature from GB_Classifier:')
    print(str(features_top_n_GB[:10]))

    # concat
    features_top_n = pd.concat([features_top_n_RF, features_top_n_GB], 
                               ignore_index=True).drop_duplicates()
    features_importance = pd.concat([feature_imp_sorted_RF, feature_imp_sorted_GB],ignore_index=True)

    return features_top_n , features_importance

N = 20
feature_top_n, feature_importance = get_top_n_features(train_data_X, train_data_Y, N)
train_data_X = pd.DataFrame(train_data_X[feature_top_n])
test_data_X = pd.DataFrame(test_data_X[feature_top_n])
RandomForest
GradientBoosting

兩個分類模型的重要特征不盡相同媚创,但是可以發(fā)現(xiàn)票價渗钉、年齡、性別钞钙、社會地位及家庭大小是比他們在船上的位置更為重要的因素鳄橘。因此可以將Ticket相關(guān)的特征刪掉。

5.2 參數(shù)調(diào)整

參數(shù)調(diào)整采用交叉驗證芒炼,可以用scikit-learn中的網(wǎng)格搜索瘫怜,即GridSearchCV類。這是一種窮舉的搜索方式:在所有候選的參數(shù)選擇中本刽,通過循環(huán)遍歷鲸湃,嘗試每一種可能性赠涮,表現(xiàn)最好的參數(shù)就是最終的結(jié)果。

為什么叫網(wǎng)格搜索唤锉?以有兩個參數(shù)的模型為例世囊,參數(shù)a有3種可能,參數(shù)b有4種可能窿祥,把所有可能性列出來株憾,可以表示成一個3*4的表格,其中每個cell就是一個網(wǎng)格晒衩,循環(huán)過程就像是在每個網(wǎng)格里遍歷嗤瞎、搜索,所以叫g(shù)rid search(轉(zhuǎn)自這里

from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingClassifier

seed = 4
# SVC
SVC_estimator = SVC(random_state=seed)
SVC_param_grid = {'C': [0.1,1,2,5], 'gamma': [0.2,0.1,0.04,0.01]}
SVC_grid = model_selection.GridSearchCV(SVC_estimator, SVC_param_grid, cv=10, verbose=1)
SVC_grid.fit(train_data_X, train_data_Y)
print('Best SVC Params:',str(SVC_grid.best_params_))
print('Best SVC Score:',str(SVC_grid.best_score_))

    
# RandomForest
RF_estimator = RandomForestClassifier(random_state=seed)
RF_param_grid = {'n_estimators': [500,1000], 'min_samples_split': [2, 3], 'max_depth': [10,20], 'min_samples_leaf':[2,3]}
RF_grid = model_selection.GridSearchCV(RF_estimator, RF_param_grid, cv=10, verbose=1)
RF_grid.fit(train_data_X, train_data_Y)
print('Best RF Params:',str(RF_grid.best_params_))
print('Best RF Score:',str(RF_grid.best_score_))


# Logistic Regression
LR_estimator =LogisticRegression(tol=1e-6, random_state=seed)
LR_param_grid = [{'penalty':['l1','l2'],'C': [0.01,0.1,1,5,10],'solver':['liblinear']},
                 {'penalty':['l2'],'C': [0.01,0.1,1,5,10],'solver':['lbfgs']}]
LR_grid = model_selection.GridSearchCV(LR_estimator, LR_param_grid, cv=10, verbose=1)
LR_grid.fit(train_data_X, train_data_Y)
print('Best LR Params:',str(LR_grid.best_params_))
print('Best LR Score:',str(LR_grid.best_score_))

# GradientBoosting
GB_estimator =GradientBoostingClassifier(random_state=seed)
GB_param_grid = {'n_estimators': [500,1000], 'learning_rate': [0.001, 0.01, 0.1], 'max_depth': [10,20], 'min_samples_leaf':[2,3]}
GB_grid = model_selection.GridSearchCV(GB_estimator, GB_param_grid, cv=10, verbose=1)
GB_grid.fit(train_data_X, train_data_Y)
print('Best GB Params:' + str(GB_grid.best_params_))
print('Best GB Score:' + str(GB_grid.best_score_))

可以得到幾種模型最優(yōu)的參數(shù)設置:
Best SVC Params: {'C': 1, 'gamma': 0.2}
Best SVC Score: 0.843995510662

Best RF Params: {'max_depth': 10, 'min_samples_split': 2, 'n_estimators': 1000, 'min_samples_leaf': 2}
Best RF Score: 0.83950617284

Best LR Params: {'C': 5, 'solver': 'liblinear', 'penalty': 'l1'}
Best LR Score: 0.829405162738

Best GB Params:{'max_depth': 10, 'n_estimators': 1000, 'min_samples_leaf': 3, 'learning_rate': 0.001}
Best GB Score:0.818181818182

最后就可以用votingClassifer建立最終預測模型了(參考了Kaggle論壇):

# 將幾種模型的結(jié)果通過投票的方式進行聚合
from sklearn.ensemble import VotingClassifier
SVC_estimator = SVC(C=1, gamma = 0.2, kernel='rbf', decision_function_shape='ovo',random_state=seed, probability=True)  
RF_estimator = RandomForestClassifier(n_estimators=1000,max_depth=10, min_samples_split=2,
                                      max_features='sqrt',criterion = 'gini',
                                      min_samples_leaf=2,random_state =seed)
LR_estimator =LogisticRegression(tol=1e-6, C=5, solver='liblinear', penalty='l1', random_state=seed)
GB_estimator = GradientBoostingClassifier(n_estimators=1000, learning_rate=0.001, max_depth=10,
                                          min_samples_split=2, min_samples_leaf=3,random_state =seed)


vote_soft = VotingClassifier(estimators = [('SVC', SVC_estimator),('RF', RF_estimator),('LR', LR_estimator),('GB', GB_estimator)],
                             voting = 'soft', weights = [1.5,0.8,0.8,0.5],n_jobs =-1)
vote_soft.fit(train_data_X,train_data_Y)
predictions = vote_soft.predict(test_data_X).astype(np.int32)

最后別忘了輸出結(jié)果:

# 結(jié)果輸出
result = pd.DataFrame({'PassengerId':data_02['PassengerId'].as_matrix(),'Survived':predictions})
result.to_csv('submission_result_01.csv',index=False,sep=',')

準確率:0.79425

回顧這三天:

  • 參數(shù)調(diào)整過程太痛苦了听系,我的筆記本算的好慢...
  • 因為是帶著問題學習贝奇,所以很不系統(tǒng),有很多很多很多沒考慮到的地方靠胜,比如過擬合欠擬合掉瞳,比如提取到的特征不夠好,比如最終模型預測權(quán)重不知道怎么合理設置…
  • 一直以來都很喜歡邊用邊學浪漠,再學以致用的過程陕习,是痛并享受著的三天。最終并沒有成為算命大師址愿,準確率有點低~如果能讓屏幕前的你對數(shù)據(jù)分析產(chǎn)生一點點點點興趣的話就覺得很開心了该镣!
  • 可能你也會對數(shù)據(jù)分析,從入門到放棄感興趣响谓。

參考:
[1] http://www.cnblogs.com/fantasy01/p/4581803.html?utm_source=tuicool
[2] http://www.cnblogs.com/pinard/p/6126077.htm
[3] http://mars.run/2015/11/Machine%20learning%20kaggle%20titanic-0.8/
[4] https://blog.csdn.net/u012897374/article/details/74999940
[5] https://blog.csdn.net/app_12062011/article/details/50385522
[6] https://blog.csdn.net/app_12062011/article/details/50536369
[7] lhttps://zhuanlan.zhihu.com/p/30538352
[8] https://www.kaggle.com/yassineghouzam/titanic-top-4-with-ensemble-modeling
[9] https://www.kaggle.com/helgejo/an-interactive-data-science-tutorial

(-'?_?'-)謝謝您閱讀损合,請勿轉(zhuǎn)載。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末娘纷,一起剝皮案震驚了整個濱河市嫁审,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赖晶,老刑警劉巖律适,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嬉探,居然都是意外死亡,警方通過查閱死者的電腦和手機棉圈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門涩堤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人分瘾,你說我怎么就攤上這事胎围∮跸担” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵白魂,是天一觀的道長汽纤。 經(jīng)常有香客問我,道長福荸,這世上最難降的妖魔是什么蕴坪? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮敬锐,結(jié)果婚禮上背传,老公的妹妹穿的比我還像新娘。我一直安慰自己台夺,他們只是感情好径玖,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著颤介,像睡著了一般梳星。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上滚朵,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天冤灾,我揣著相機與錄音,去河邊找鬼始绍。 笑死瞳购,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的亏推。 我是一名探鬼主播学赛,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吞杭!你這毒婦竟也來了盏浇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤芽狗,失蹤者是張志新(化名)和其女友劉穎绢掰,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體童擎,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡滴劲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了顾复。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片班挖。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖芯砸,靈堂內(nèi)的尸體忽然破棺而出萧芙,到底是詐尸還是另有隱情给梅,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布双揪,位于F島的核電站动羽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏渔期。R本人自食惡果不足惜运吓,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望擎场。 院中可真熱鬧羽德,春花似錦、人聲如沸迅办。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽站欺。三九已至姨夹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間矾策,已是汗流浹背磷账。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留贾虽,地道東北人逃糟。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像蓬豁,于是被迫代替她去往敵國和親绰咽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 探索數(shù)據(jù)集-泰坦尼克號數(shù)據(jù) 一地粪、讀取數(shù)據(jù) import pandas as pdimport numpy as n...
    楊小彤閱讀 827評論 0 1
  • 對kaggle不做過多介紹 都知道這是一個數(shù)據(jù)挖掘的圣地取募,泰坦尼克號事件也不多做介紹,馬上進入正題 ...
    披風海膽放閱讀 1,206評論 1 4
  • pyspark.sql模塊 模塊上下文 Spark SQL和DataFrames的重要類: pyspark.sql...
    mpro閱讀 9,451評論 0 13
  • 1蟆技、加載文件玩敏,查看:(兩個數(shù)據(jù)集,train作為學習集進行數(shù)據(jù)建模质礼,通過test測試集查看建模的情況旺聚。) trai...
    12_21閱讀 1,043評論 0 0
  • 最近擠出時間,用python在kaggle上試了幾個project眶蕉,有點體會砰粹,記錄下。 Step1: Explor...
    JxKing閱讀 39,611評論 8 140