集成開發環境:Pycharmhtml
python版本:2.7(anaconda庫)python
用到的庫:科學計算庫numpy,數據分析包pandas,畫圖包matplotlib,機器學習庫sklearn數組
大致步驟分爲三步:機器學習
1.數據分析函數
2.交叉驗證學習
3.預測並輸出結果測試
導入庫函數spa
import numpy as np import pandas as pa import matplotlib.pyplot as pl from sklearn.linear_model import LogisticRegression from sklearn import model_selection # 最後一個庫是原來cross_validation的替代,原來那個過期了,再用會有警告,其實裏邊的函數都沒變
第一步:數據分析code
1.1經過畫圖分析出數據中對預測影響很小的特徵值,忽略這些特徵能夠減少工做量htm
1 # pandas庫裏的read_csv能夠把csv文件讀取爲dataFrame對象,這個對象就是不少列(數組)共享一個index,這個index 是真的存在的且能夠指定,每一列都有name 2 # 其形狀大小是真實數據的形狀,不包括index和name 3 # 路徑能夠是絕對路徑和相對路徑,注意路徑中的反斜線是兩根,或者一根/ 4 train_obj = pa.read_csv('train.csv') 5 test_obj = pa.read_csv('test.csv') 6 7 # 首先把一看就知道對結果沒有影響的數據去掉 8 # DataFrame對象的drop方法:刪除行或者列,能夠多行,drop('行名或者列名',axis=0/1(0是行,1是列)),多個行名或者列名:['',''] 9 trainData = train_obj.drop(['Name', 'Ticket', 'Cabin'], axis=1) 10 testData = test_obj.drop(['Name', 'Ticket', 'Cabin'], axis=1) 11 12 # 下面用畫圖的形式對其餘變量對最後結果的影響做出判斷: 13 # 首先考察船艙和性別,用groupby函數對的數據進行分類,groupby('列名'),根據給出的列,把具備相同數值的合爲一組,組數爲列值的種數 14 # 若是groupby(['列名1','列名2']),則列1爲分大類,大類中再根據列2進行分類 15 train_group1 = trainData.groupby(['Sex', 'Pclass']) # 返回類型是Groupby類型,裏邊有key1*key2組 16 # sum()是將各組內每一個特徵的全部數據相加,返回也是key1*key2組,只不過每組裏只有一行數據,是全部數據之和 17 # count()是統計各組每一個特徵的數據量(因爲有缺失數據,因此各個特徵間是不必定同樣的) 18 rate = (train_group1.sum() / train_group1.count())['Survived'] # 有6組,每組都只有一個值,生存率 19 20 # 下面開始畫圖,柱狀圖 21 x = np.array([1, 2, 3]) 22 wi = 0.15 23 # bar(left,height,width,color)用來化柱狀圖,參數分別是每一個柱子的中心位置座標,高度(通常就是數據),寬度,顏色,前三個通常都是集合 24 pl.bar(x-wi, rate.female, wi*2, color='r') 25 pl.bar(x+wi, rate.male, wi*2, color='b') 26 pl.title("survived rate") 27 # 座標軸名稱 28 pl.xlabel("Pclass") 29 pl.ylabel("rate") 30 # 指定網格線格式 31 pl.grid(True, linestyle='-', color='0.7') 32 # 軸的刻度 33 pl.xticks([1, 2, 3]) 34 # arange(起點,終點,間隔),建立一個等差序列 35 pl.yticks(np.arange(0.0, 1.1, 0.1)) 36 # 對不一樣的柱作標記 37 pl.legend(['female', 'male']) 38 pl.show() 39 # 接下來的過程和上邊差很少,分別是判斷了年齡、上船地點、船上親屬人數
分析性別和上船地點的結果,結果顯示兩個特徵的影響都須要保留
1.2數據預處理,將特徵中比較類似的直接相加做爲一個,非數值類型轉爲數值類型,對缺失值進行處理
1 # 船上的親屬人數就是把兩個表明家眷的變量相加 2 trainData['family'] = trainData['SibSp'] + trainData['Parch'] 3 # pandas中的map()函數通常是用來進行數據轉換的,參數是函數或者字典,一個series調用map(),會對照字典用的key,將series中的key所有改爲相應的value,map()函數返回一個新的,對源對象不操做 4 trainData['Sex'] = trainData['Sex'].map({'female': 0, 'male': 1}) 5 trainData['Embarked'] = trainData['Embarked'].map({'C': 0, 'Q': 1, 'S': 2}) 6 # numpy.isnan()函數的做用是返回一個Boolean數組,對應input的下標,若當前位置是nan那麼就是true,不然false 7 # 對一個數組挑選時能夠用array[True,False,True...]True就是選擇 8 # 挑選出age爲nan的,這個集合不用age這個特徵,作四特徵預測 9 train_age_nan = trainData[np.isnan(trainData['Age'])] 10 # 挑選出age不爲空的數據,直接調用dropna(),這個方法會去掉輸入數組中有nan特徵的數據,挑選後的具有全部特徵,因此能夠用全部特徵 11 train_all = trainData.dropna() 12 # 對於以上兩個數據集分別挑選出須要的特徵組成訓練集,由於以前已經確認了有的是對結果沒有影響的,因此能夠只挑選有用的 13 # dataframe選取列的格式是兩個方括號,[['列名','列名']] 14 train_five = train_all[['Sex', 'Embarked', 'family', 'Age', 'Pclass']] 15 train_four = train_age_nan[['Sex', 'Embarked', 'family', 'Pclass']] 16 17 # 兩個數據集的標記數組 18 train_five_label = train_all['Survived'] 19 train_four_label = train_age_nan['Survived'] 20 21 # 至此處理數據工做所有完成,接下來就是訓練模型
2.交叉驗證
1 # 使用分類器類 2 classifier = LogisticRegression(C=10000) # 這個做爲5特徵分類器,這裏的c是正則化係數,防止系統因爲過於複雜而產生過擬合 3 # 調用cross_validation.cross_val_score(分類器,data,target,cv),這個函數返回每次交叉驗證的準確率,方法是StratifiedKFold,具體看http://blog.sina.com.cn/s/blog_6a90ae320101a5rc.html 4 # 函數返回一個數組 5 score = model_selection.cross_val_score(classifier, train_five, train_five_label, cv=5) # 交叉驗證 6 classifier2 = LogisticRegression() # 這個做爲4特徵分類器 7 score2 = model_selection.cross_val_score(classifier2, train_four, train_four_label, cv=5) # 交叉驗證 8 # 查看平均值 9 print "五特徵分類器交叉驗證結果:" 10 print score.mean() 11 print "四特徵分類器交叉驗證結果:" 12 print score2.mean()
3.輸出結果
1 # 下面開始輸出結果 2 3 # 首先處理測試集 4 testData['Sex'] = testData['Sex'].map({'female': 0, 'male': 1}) 5 testData['Embarked'] = testData['Embarked'].map({'C': -1, 'Q': 0, 'S': 1}) 6 testData['family'] = testData['SibSp'] + testData['Parch'] 7 # 這裏不能用兩個數據集,由於若是將數據分開分別判斷,那麼沒法和乘客號對應 8 # 讀取官方結果 9 answer = pa.read_csv('gender_submission.csv') 10 11 # 訓練分類器 12 classifier.fit(train_five, train_five_label) 13 classifier2.fit(train_four, train_four_label) 14 15 # 輸出測試集結果 16 passengers = pa.DataFrame(testData['PassengerId']) 17 # 這裏必須先建立一個列,直接賦值會出錯 18 passengers['Survived'] = '' 19 # isnan()是numpy庫裏的函數 20 #這裏有個問題就是若是直接對passengers['Survived'][i]每行賦值的話會有SettingCopyWarning警告,正確的方法是先生成一個數組temp,而後把數組賦值給列,直接添加會有警告 21 #這裏建立數組不能用np.zeros(),由於用zeros生成的是float數組,最後結果要求int類型 22 temp = [0] * passengers.shape[0] 23 for i in range(len(testData)): 24 if np.isnan(testData['Age'][i]): 25 # 這裏也有一個問題:因爲須要一個一個作預測,可是predict函數要求輸入二維數組,單行數據是一維的 26 #因此要把數據轉爲numpy中的array,而後轉爲二維數組 27 #reshape()函數能夠利用原數組數據改變數組的尺寸,可是主要新舊數組數據量相同,而reshape(1,-1)能夠將[xxx]轉爲[[xxx]]這種,就能夠用了 28 temp[i] = int(classifier2.predict(np.array( testData[['Pclass', 'Sex', 'Embarked', 'family']].ix[i].dropna()).reshape(1,-1))) 29 else: 30 temp[i] = int(classifier.predict(np.array(testData[['Sex', 'Embarked', 'family', 'Age', 'Pclass']].ix[i]).reshape(1,-1))) 31 print temp 32 passengers['Survived'] = temp 33 # 結算準確率 34 acc = 1 - float(sum(abs(answer['Survived'] - passengers['Survived']))) / len(passengers) 35 print "準確率是:" 36 print acc 37 # 輸出文件 38 passengers.to_csv('result.csv',encoding='utf-8',index=False)
最後的結果,準確率有點低,再找找緣由