此爲中文翻譯版python
咱們將學習如何爲Kaggle競賽生成一個提交答案(submisson
)。Kaggle是一個你經過完成算法和全世界機器學習從業者進行競賽的網站。若是你的算法精度是給出數據集中最高的,你將贏得比賽。Kaggle也是一個實踐你機器學習技能的很是有趣的方式。
Kaggle網站有幾種不一樣類型的比賽。其中的預測一個就是預測在泰坦尼克號沉沒的時候哪一個乘客會成爲倖存者。 在這個任務和下一個任務咱們將學習如何提交咱們的答案。
咱們的數據是csv
格式。你能夠在這裏下載數據開始比賽。
每一行重現了一個在泰坦尼克的乘客以及和他們有關的一些信息。讓咱們來看一下各列:git
一個好的開始就是有條理的思考各個列和咱們的預測之間的邏輯關係。
咱們都知道婦女和兒童更可能被救。所以,年齡
和性別
極可能更好的幫助咱們預測。認爲乘客的船層可能會影響結果也是符合邏輯的,由於第一層的船艙更靠近船的甲板。Fare
票價和乘客所住船層相關,並且多是高度相關的,可是也可能會增長一些額外的信息。SibSp、Parch
兄弟姐妹、配偶、父母/孩子的數量極可能關係到是否被某一個或不少我的救,會有不少人去幫助你或者有不少人想到你嘗試去救你。
像Embarked
登船(也許有一些信息和怎麼靠近船的頂部的人的船艙有關),Ticket
票號和Name
名字。
這一步一般是習得相關的領域知識[要對業務比較深刻],這對於絕大多數機器學習任務來講很是很是很是的重要。
咱們很是細緻的處理特徵以便咱們能從咱們現有的數據中得到最有用的信息來幫助咱們進行預測。算法
咱們將使用Python3,pandas庫和scikit-learn庫來分析咱們的數據而且生成一個提交答案submisson
。咱們將使用代碼框進行交互式編程,就和你看到的下面那個同樣。若是你對Python還不熟悉,你可能想看一看咱們的課程。
一個好的第二步就是仔細觀察數據中的高級描述。在這種狀況下,咱們使用pandas的.describe()
方法來查看每一列數值的特性的不一樣之處。編程
# We can use the pandas library in python to read in the csv file. # This creates a pandas dataframe and assigns it to the titanic variable. titanic = pandas.read_csv("titanic_train.csv") # Print the first 5 rows of the dataframe. print(titanic.describe())
在上一節你使用.describe()
方法查看titanic
數據框的時候,你可能注意到年齡列只有714個計數,而其餘列都有891個計數。這代表在年齡列有一些缺失值——空值(null,NA,非數字)。
這就意味着數據並非徹底的乾淨,咱們必須本身清洗數據。咱們不但願不得不刪除有缺失數據的行,由於更多的數據能幫助咱們訓練出一個更好的算法。固然,咱們也不想刪除整列,由於age年齡極可能對咱們的分析很是重要。
有不少種策略來處理缺失數據,可是一種簡單的方法就是將那一列的缺失值用中位數填充。
咱們能夠像字典同樣經過數據框索引選取一個單列。這樣會給咱們一個pandas Series(序列):數組
titanic['Age']
咱們可使用.fillna
方法替換序列中的任何缺失值。.fillna
能夠傳入一個參數用參數的值來替換缺失值。
在咱們的例子中,咱們打算用列的中位數來填充:app
titanic['Age'].fillna(titanic['Age'].median())
以後咱們必須將替換後的結果賦值回原來的列:dom
titanic['Age'] = titanic['Age'].fillna(titanic['Age'].median())
前兩節咱們使用過.describe()
,你也許也主要到並非全部的列都顯示出來了。只有數值列顯示了。咱們的列中有幾個是非數值的,當你開始作預測的時候這將是一個問題——咱們不能將非數值列傳入機器學習算法中而且指望機器學習算法能理解他們。
咱們在訓練咱們的算法時要麼必須排除這些非數值列(Name
, Sex
, Cabin
, Embarked
, Ticket
),要麼就要找到一種方法將他們轉換成數值列。
咱們將忽略Ticket
, Cabin
,Name
這三行。由於咱們不能從他們中提取出太多有用的信息。Cabin
列大多數值都是缺失的(891行中只有204行數值),並且起初看起來好像也不是特別有用的列。若是沒有一些關於船票號碼意義的專業領域知識和哪些名字的特色像大戶或者有錢家庭,那麼Ticket
和Name
列也不太可能會告訴咱們太多的信息。機器學習
Sex
列性別列是非數值的,可是咱們想把它保留——他可能很是有用。咱們將每個性別用數值碼替換將其轉換成一個數值列。以後機器學習算法可以使用這些類別去作預測。
爲了完成這個目的,咱們首先要找出列中全部的惟一性別(咱們知道有male男和female女,可是有沒有可能誰在數據集用的是其餘缺失值代碼呢?)。咱們將0賦值給male,將1賦值給female。
咱們能夠選擇Sex
列的全部值爲male的行而且用0替換male:函數
titanic.loc[titanic['Sex']=='male','Sex'] = 0 titanic.loc[titanic['Sex']=='female','Sex'] = 1 # 有一個問題就是我本身測試的時候,describe()方法仍是不顯示性別。
Embarked
列咱們如今能夠用和轉換Sex
列相同的方法將Embarked
列轉換成數值碼。Embarked
列的惟一值是S,C,Q
和缺失值nan
。每一個字母是一個登船港口名字的縮寫。
第一步是替換列中的缺失值。大部分共同的登船港口都是S
,因此咱們假設每一個人都是從那兒上船的。將Embarked
列的缺失值全都替換成S
。
咱們分別將0
賦值給S
,將1
賦值給C
,將2
賦值給Q
,替換每一個值相應的代碼:性能
# Find all the unique values for "Embarked". print(titanic["Embarked"].unique()) titanic['Embarked'] = titanic['Embarked'].fillna('S') titanic.loc[titanic['Embarked'] == 'S', 'Embarked'] = 0 titanic.loc[titanic['Embarked'] == 'C', 'Embarked'] = 1 titanic.loc[titanic['Embarked'] == 'Q', 'Embarked'] = 2
如今咱們的數據已經清洗得乾淨了一點了,咱們準備開始探索一些機器學習。咱們開始的一些行數據看起來像這樣:
Age |Sex |Survived
----|----|--------
10 | 0 |0
5 | 1 |1
30 | 0 |0
若是咱們想利用Age
列的數據來預測是否有人倖存或者沒有幸存,咱們可使用一種叫作線性迴歸的方法。線性迴歸的等式以下:(y=mx+b),y
的值是咱們設法預測的,m
是一個叫作斜率的係數,x
是一列的值,b
是一個叫作截距的常數。
咱們能夠經過賦值-2
給m
,賦值20
給b
作一個預測。咱們獲得這樣的結果:
Age | Sex | Survived | Predictions |
---|---|---|---|
10 | 0 | 0 | -2*10+20=0 |
5 | 1 | 1 | -2*5+20=10 |
30 | 0 | 0 | -2*30+20=-40 |
若是咱們將獲得的預測結果中任何大於0的值轉換成1,任何小於等於0的值換成0,咱們將獲得這樣的結果:
Age | Sex | Survived | Predictions |
---|---|---|---|
10 | 0 | 0 | 0 |
5 | 1 | 1 | 1 |
30 | 0 | 0 | 0 |
這個簡單的模型預測倖存者至關好。線性模型能夠是一個很是強大的算法,可是也有一些缺點:
咱們以後會討論如何處理這兩個問題。如今,咱們將學習如何自動的計算線性迴歸的迴歸係數,如何用多列數據來預測一個結果。
咱們如今使用線性迴歸在咱們的訓練數據集上作預測。
咱們想用除咱們作預測以外的不一樣的數據來訓練算法。若是咱們想避免過擬合這是很是關鍵的。過擬合是當一個模型擬合它自己過於複雜,不顯著。每一個數據都有其獨有的特色且不存在於全集。例如:若是我要求你利用一輛車的馬力和其餘特徵,而且給你一個隨機的很是高的最高速度數據集,來預測一輛車的最高速度,你將會創建一個速度太高的模型。解決的辦法就是用你沒有用來訓練模型的數據去測試性能。
每個機器學習算法均可以過擬合,即便有的(像線性迴歸)很是不容易。若是你測試(評估)你的算法和你訓練算法是用的同一個數據集,那麼你極可能不知道它的性能好究竟是算法很好仍是由於過擬合它本身的噪聲。
幸運的是,交叉驗證是一個很簡單的避免過擬合的方法。交叉驗證,你將你的數據分紅一些數字部分(或子類)。咱們使用3
做爲一個例子。而後你這樣作:
這種方式,評價咱們生成的預測的精度的整個數據集和曾經訓練咱們的模型沒有相同的數據。
咱們可使用極好的scikit-learn
庫來作預測。咱們將使用skelearn的一個助手來將數據分紅交叉驗證的子類,而後用每個子類分別來訓練算法作預測。最後,咱們將獲得一個預測列表,每個列表項包含了相關子類的預測數據。
# Import the linear regression class from sklearn.linear_model import LinearRegression # Sklearn also has a helper that makes it easy to do cross validation from sklearn.cross_validation import KFold # The columns we'll use to predict the target predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"] # Initialize our algorithm class alg = LinearRegression() # Generate cross validation folds for the titanic dataset. It return the row indices corresponding to train and test. # We set random_state to ensure we get the same splits every time we run this. kf = KFold(titanic.shape[0], n_folds=3, random_state=1) predictions = [] for train, test in kf: # The predictors we're using the train the algorithm. Note how we only take the rows in the train folds. train_predictors = (titanic[predictors].iloc[train,:]) # The target we're using to train the algorithm. train_target = titanic["Survived"].iloc[train] # Training the algorithm using the predictors and target. alg.fit(train_predictors, train_target) # We can now make predictions on the test fold test_predictions = alg.predict(titanic[predictors].iloc[test,:]) predictions.append(test_predictions)
如今咱們有了預測結果,咱們能夠測試咱們的偏差了。
第一步咱們須要先定義偏差的度量標準,因此咱們先算出咱們模型的精度。從Kaggle競賽的描述,偏差的度量標準是正確預測的百分比。咱們將使用這個相同的度量標準來測試咱們本地模型的性能。
這個度量標準將基本上是predictions
中找到的值和他們在titanic['Survived']
的副本中準確對應的值的數量而後再除以乘客的總數。
在咱們這麼作以前,咱們須要先將三個預測數據集合併到一個列中。由於每個預測數據集是一個numpy(python科學計算庫[注:真正的科學計算庫應該是scipy,而numpy主要是矩陣數組等數據處理運算])數組,咱們可使用一個numpy方法將他們鏈接到一個列裏。
算出predictions
預測值中和titanic["Survived"]
副本中準確相同的值的比例。這個計算結過應該是一個浮點數(小數)並將它賦值給變量accuracy
。
import numpy as np # The predictions are in three separate numpy arrays. Concatenate them into one. # We concatenate them on axis 0, as they only have one axis. predictions = np.concatenate(predictions, axis=0) # Map predictions to outcomes (only possible outcomes are 1 and 0) predictions[predictions > .5] = 1 predictions[predictions <=.5] = 0 accuracy = sum(predictions[predictions == titanic['Survived']])/(titanic['Survived'].count())
咱們有了咱們的第一個預測結果!但是結果並非很好,只有78.3%的正確率。在視頻中,咱們曾提到一種方式使線性迴歸的輸出值介於0
和1
之間。這種方法叫作邏輯迴歸。
一個好的方法就是將邏輯迴歸當成是線性迴歸的邏輯輸出,因此他的值就是0
和1
。用邏輯函數 logit function來完成。輸入任何值到邏輯函數都將經過「壓縮」極值匹配成0
和1
。這對咱們來講很是完美,由於咱們只關心兩種輸出結果。
Sklearn
有一個邏輯迴歸的類咱們可使用。經過使用一個Sklearn
助手函數可使咱們全部的交叉驗證和測試變得更簡單。
咱們的正確度已經能夠了,可是還不是很是好。咱們任然能夠嘗試一些方法來使它變得更好,在下一個任務將會討論。
可是咱們須要提交一個答案到比賽中。咱們須要在測試數據上採起一個和訓練數據上同樣的校準的步驟來完成這個事情。若是咱們沒有校準操做,咱們就不可以利用它作出有效的預測。
這些操做要在咱們對列全部的改變以前進行。
處理titanic_test
和處理titanic
用一樣的方法。
這涉及到:
titanic['Age'].median()
去找到中位數。Sex
列中的全部male
換成0
,全部female
換成1
。S
填充Embarked
列中的全部缺失值。Embarked
列中的S
換成0
,C
換成1
,Q
換成2
。Fare
列的缺失值替換掉。用.fillna
將測試集中的缺失值用中位數替換掉。訓練集中的Fare
列沒有缺失值了,可是測試集有時會不一樣。titanic_test = pandas.read_csv("titanic_test.csv") titanic_test['Age'] = titanic_test['Age'].fillna(titanic_test['Age'].median()) titanic_test['Fare'] = titanic_test['Fare'].fillna(titanic_test['Fare'].median()) titanic_test.loc[titanic_test['Sex'] == 'male','Sex'] = 0 titanic_test.loc[titanic_test['Sex'] == 'female','Sex'] = 1 titanic_test['Embarked'] = titanic_test['Embarked'].fillna('S') titanic_test.loc[titanic_test['Embarked'] == 'S', 'Embarked'] = 0 titanic_test.loc[titanic_test['Embarked'] == 'C', 'Embarked'] = 1 titanic_test.loc[titanic_test['Embarked'] == 'Q', 'Embarked'] = 2
如今咱們有了咱們須要生成一個比賽提交答案的全部東西了。
首先,咱們必須先在訓練數據上訓練一個算法。而後咱們在測試數據集上作一個預測。最後,咱們生成一個包含預測和乘客id的csv文件。
一旦你完成了下面步驟的代碼,你就能用submission.to_csv('kaggle.csv, index=False')
輸出一個csv結果。這將會給你的第一個條件全部須要的東西——雖然這沒有給你很好的準確率。(~0.75)
# Initialize the algorithm class alg = LogisticRegression(random_state=1) # Train the algorithm using all the training data alg.fit(titanic[predictors], titanic["Survived"]) # Make predictions using the test set. predictions = alg.predict(titanic_test[predictors]) # Create a new dataframe with only the columns Kaggle wants from the dataset. submission = pandas.DataFrame({ "PassengerId": titanic_test["PassengerId"], "Survived": predictions })
咱們只是生成了一個調教文件,可是準確率不是很好(0.75)。因爲咱們的預測在不一樣的數據集上致使在測試集上的分數低於咱們在交叉驗證上的分數。在下一個任務中咱們將學習如何生成更好的特徵和使用更好的模型來提升咱們的分數。
恭喜你完成了這個任務!