機器學習篇(四)
- 2019 年 10 月 6 日
- 筆記
1、認識決策樹
簡單來說就是我們程式中if判斷的過程,比如下圖就是一個簡單的決策過程:

圖中根據年齡,長相,收入,是否是程式設計師來判斷是否見面。這就是一個簡單的決策過程。
為什麼把年齡判斷放在第一個判斷,不把長相,收入,就是為了減少不確定性。
在相親過程中可能年齡這個特徵比較重要,但是在實際其他應用中,我們把哪個特徵放在第一位?
怎麼知道哪個特徵比較重要?
這裡引入一個名詞:資訊熵(單位bit)
關於資訊熵的定義可以去看這篇文章:
https://www.zhihu.com/question/22178202
簡單來說資訊熵越大,不確定性越大。(資訊和消除不確定性是相聯繫的)
資訊增益:滿足一個條件之後,減少的資訊熵大小。
這裡根據資訊熵計算出資訊增益,資訊增益最大的把他放在第一位進行決策。
資訊增益就是決策樹的分類依據之一。
2、決策樹模組
sklearn.tree.DecisionTreeClassifier(criterion='gini',max_depth=None,random_state=None)
criterion:默認為gini係數,也就是分類依據,也可以選擇entropy也就是資訊增益
max_depth:樹的深度大小
random_state:隨機數種子
3、實例
泰坦里克號數據:根據票的類別,存貨,年齡,性別等判斷在事故中的存活狀況。
數據來源:http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt
import pandas as pd from sklearn.feature_extraction import DictVectorizer from sklearn.model_selection import train_test_split,GridSearchCV from sklearn.tree import DecisionTreeClassifier,export_graphviz from sklearn.ensemble import RandomForestClassifier def decision(): '''決策樹預測泰坦尼克號存亡情況''' # 獲取數據 taitan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt") # 處理數據 # 目標值為survived # 特徵值我選擇:pclass,age,sex x = taitan[['pclass','age','sex']] y = taitan['survived'] # 處理age缺失值 x['age'].fillna(x['age'].mean(),inplace=True) # 分割數據集 x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25) # 處理數據 # 對pclass,home.dest,room,sex進行one-hot編碼 dict = DictVectorizer(sparse=False) # to_dict轉化成字典,orient="records"表示把每一行都轉化成一個字典 x_train = dict.fit_transform(x_train.to_dict(orient="records")) x_test = dict.transform(x_test.to_dict(orient="records")) # 用決策樹進行預測,暫時不寫參數,需要用網格搜索和交叉驗證 dec = DecisionTreeClassifier() dec.fit(x_train,y_train) print("預測的準確率:",dec.score(x_test,y_test)) ''' 預測的準確率: 0.8115501519756839 ''' if __name__ == "__main__": decision() 4、優缺點
優點:
樹木可視化,可以運用Graphviz工具將決策圖導出。
數據量準備較少,不用歸一化處理
缺點:
決策樹結構過於複雜,過擬合。
改進:
減枝cart演算法(DecisionTreeClassifier中的min_samples_split和min_samples_leaf參數)
隨機森林
隨機森林
集成學習方法:比如一個分類,可以用k-近鄰,樸素貝葉斯,決策樹,各自獨立學習作出預測,最後結合成單預測,優於其中的單個演算法預測。而多個決策樹集成學習就是隨機森林。
隨機森林建立多個決策樹的過程:
現在有N個樣本M個特徵。
單個樹建立:
1、隨機選擇N個樣本中的一個樣本,重複N次。隨機選擇樣本可能重複
2、隨機在M個特徵中選擇x個特徵
隨即有放回的抽樣叫做bootstrap抽樣。
隨機抽樣是為了每次的訓練集不一樣,如果都一樣,就沒有意義了。
隨機森林模組;
sklearn.ensemble.RandomForestClassifier(n_estimators=10,riterion='gini',max_depth=None,bootstrap=True,random_state=None)
n_estimators:生成多少個決策樹
riterion:默認為gini係數,也就是分類依據,也可以選擇entropy也就是資訊增益
max_depth:樹的最大深度
bootstrap:是否隨即有放回的抽樣
random_state:每個決策樹的最大特徵數量
實例:
import pandas as pd from sklearn.feature_extraction import DictVectorizer from sklearn.model_selection import train_test_split,GridSearchCV from sklearn.tree import DecisionTreeClassifier,export_graphviz from sklearn.ensemble import RandomForestClassifier def randdecision(): '''決策樹預測泰坦尼克號存亡情況''' # 獲取數據 taitan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt") # 處理數據 # 目標值為survived # 特徵值我選擇:pclass,age,sex x = taitan[['pclass','age','sex']] y = taitan['survived'] # 處理age缺失值 x['age'].fillna(x['age'].mean(),inplace=True) # 分割數據集 x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25) # 處理數據 # 對pclass,home.dest,room,sex進行one-hot編碼 dict = DictVectorizer(sparse=False) # to_dict轉化成字典,orient="records"表示把每一行都轉化成一個字典 x_train = dict.fit_transform(x_train.to_dict(orient="records")) x_test = dict.transform(x_test.to_dict(orient="records")) # 隨機森林進行預測 rf = RandomForestClassifier() # 網格搜索與交叉驗證 # 構造參數字典 param = {"n_estimators":[10,30,50,70],"max_depth":[3,5,10]} gc = GridSearchCV(rf,param_grid=param,cv=10) gc.fit(x_train,y_train) print("預測的準確率:",gc.score(x_test,y_test)) print("選擇的數據模型為:",gc.best_params_) ''' 預測的準確率: 0.78419452887538 選擇的數據模型為: {'max_depth': 3, 'n_estimators': 10} ''' if __name__ == "__main__": randdecision() 效果反而不好了!隨機森林的優勢是在大量數據和很多特徵值的情況下,可能這裡選擇參數不是很匹配。
優點:
1、準確率
2、有效處理大數據
3、能夠處理高維度的樣本,不需要降維
4、能夠評估各個特徵在分類中的重要性