決策樹
概念舉栗子
import numpy as np
引入數據:
s= '''在1948年,香農引入了信息熵,將其定義爲離散隨機事件出現的概率,一個系統越是有序,信息熵就越低,反之一個系統越是混亂,它的信息熵就越高。所以信息熵可以被認爲是系統有序化程度的一個度量。'''
s_l = list(s)
len(s_l)
Out:93
# 打亂順序
index = np.arange(93)
np.random.shuffle(index)
# 使用亂序作爲下標
s_new = np.array(s_l)[index]
np.array(s_l)[index]
Out:
array(['熵', '序', '爲', '入', '化', '息', '混', '低', '8', ',', '序', '散', '可',
'一', '9', '。', '將', '就', '是', '了', '以', '現', '息', '有', '一', '它',
'有', '越', '的', '義', ',', '出', '個', ',', '信', '統', '在', ',', '離',
'隨', '統', '度', '4', '系', '反', '爲', '所', '之', '熵', '是', '概', '息',
',', '息', '亂', ',', '度', '熵', '系', '一', '個', '越', '熵', '信', '1',
'信', '農', '被', '件', '信', '率', '其', '的', '定', '以', '的', '越', '統',
'認', '是', '引', '程', '年', '越', '量', '個', '高', '就', '。', '事', '系',
'機', '香'], dtype='<U1')
""" ''.join(s_new)==''.join(s_new.tolist()) """
# 還是這93個字符,順序打亂了
# 信息量很多,數據混亂了,熵增大了
''.join(s_new.tolist())
Out:
'熵序爲入化息混低8,序散可一9。將就是了以現息有一它有越的義,出個,信統在,離隨統度4系反爲所之熵是概息,息亂,度熵系一個越熵信1信農被件信率其的定以的越統認是引程年越量個高就。事系機香'
'''
計算機沒法理解概念;
計算機只能根據熵大小來決定,來判斷數據排序之後,有序了無序了.
'''
-np.log2(0.36)
Out: 1.4739311883324124
原理
【關鍵詞】樹,信息增益
決策樹的優缺點
優點:計算複雜度不高,輸出結果易於理解,對中間值的缺失不敏感,可以處理不相關特徵數據。既能用於分類,也能用於迴歸
缺點:可能會產生過度匹配問題
一、決策樹的原理
predict()
【二十個問題的遊戲】
遊戲的規則很簡單:參與遊戲的一方在腦海裏想某個事物,其他參與者向他提問題,只允許提20個問題,問題的答案也只能用對或錯回答。問問題的人通過推斷分解,逐步縮小待猜測事物的範圍。決策樹的工作原理與20個問題類似,用戶輸人一系列數據 ,然後給出遊戲的答案。
我們經常使用決策樹處理分類問題。近來的調查表明決策樹也是最經常使用的數據挖掘算法。它之所以如此流行,一個很重要的原因就是使用者基本上不用瞭解機器學習算法,也不用深究它是如何工作的。
如果以前沒有接觸過決策樹,完全不用擔心,它的概念非常簡單。即使不知道它也可以通過簡單的圖形瞭解其工作原理。
決策樹分類的思想類似於找對象。現想象一個女孩的母親要給這個女孩介紹男朋友,於是有了下面的對話:
女兒:多大年紀了?
母親:26。
女兒:長的帥不帥?
母親:挺帥的。
女兒:收入高不?
母親:不算很高,中等情況。
女兒:是公務員不?
母親:是,在稅務局上班呢。
女兒:那好,我去見見。
這個女孩的決策過程就是典型的分類樹決策。相當於通過年齡、長相、收入和是否公務員對將男人分爲兩個類別:見和不見。假設這個女孩對男人的要求是:30歲以下、長相中等以上並且是高收入者或中等以上收入的公務員,那麼這個可以用下圖表示女孩的決策邏輯:
上圖完整表達了這個女孩決定是否見一個約會對象的策略,其中綠色節點表示判斷條件,橙色節點表示決策結果,箭頭表示在一個判斷條件在不同情況下的決策路徑,圖中紅色箭頭表示了上面例子中女孩的決策過程。
這幅圖基本可以算是一顆決策樹,說它“基本可以算”是因爲圖中的判定條件沒有量化,如收入高中低等等,還不能算是嚴格意義上的決策樹,如果將所有條件量化,則就變成真正的決策樹了。
有了上面直觀的認識,我們可以正式定義決策樹了:
決策樹(decision tree)是一個樹結構(可以是二叉樹或非二叉樹)。其每個非葉節點表示一個特徵屬性上的測試,每個分支代表這個特徵屬性在某個值域上的輸出,而每個葉節點存放一個類別。使用決策樹進行決策的過程就是從根節點開始,測試待分類項中相應的特徵屬性,並按照其值選擇輸出分支,直到到達葉子節點,將葉子節點存放的類別作爲決策結果。
可以看到,決策樹的決策過程非常直觀,容易被人理解。目前決策樹已經成功運用於醫學、製造產業、天文學、分支生物學以及商業等諸多領域。
之前介紹的K-近鄰算法可以完成很多分類任務,但是它最大的缺點就是無法給出數據的內在含義,決策樹的主要優勢就在於數據形式非常容易理解。
決策樹算法能夠讀取數據集合,構建類似於上面的決策樹。決策樹很多任務都是爲了數據中所蘊含的知識信息,因此決策樹可以使用不熟悉的數據集合,並從中提取出一系列規則,機器學習算法最終將使用這些機器從數據集中創造的規則。專家系統中經常使用決策樹,而且決策樹給出結果往往可以匹敵在當前領域具有幾十年工作經驗的人類專家。
知道了決策樹的定義以及其應用方法,下面介紹決策樹的構造算法。
二、決策樹的構造
分類解決離散問題,迴歸解決連續問題
- 決策樹:信息論
- 邏輯斯底迴歸、貝葉斯:概率論
不同於邏輯斯蒂迴歸和貝葉斯算法,決策樹的構造過程不依賴領域知識,它使用屬性選擇度量來選擇將元組最好地劃分成不同的類的屬性。所謂決策樹的構造就是進行屬性選擇度量確定各個特徵屬性之間的拓撲結構。
構造決策樹的關鍵步驟是分裂屬性。所謂分裂屬性就是在某個節點處按照某一特徵屬性的不同劃分構造不同的分支,其目標是讓各個分裂子集儘可能地“純”。儘可能“純”就是儘量讓一個分裂子集中待分類項屬於同一類別。分裂屬性分爲三種不同的情況:
1、屬性是離散值且不要求生成二叉決策樹。此時用屬性的每一個劃分作爲一個分支。
2、屬性是離散值且要求生成二叉決策樹。此時使用屬性劃分的一個子集進行測試,按照“屬於此子集”和“不屬於此子集”分成兩個分支。
3、屬性是連續值。此時確定一個值作爲分裂點split_point,按照>split_point和<=split_point生成兩個分支。
構造決策樹的關鍵性內容是進行屬性選擇度量,屬性選擇度量是一種選擇分裂準則,它決定了拓撲結構及分裂點split_point的選擇。
屬性選擇度量算法有很多,一般使用自頂向下遞歸分治法,並採用不回溯的貪心策略。這裏介紹常用的ID3算法。
ID3算法
劃分數據集的大原則是:將無序的數據變得更加有序。
我們可以使用多種方法劃分數據集,但是每種方法都有各自的優缺點。組織雜亂無章數據的一種方法就是使用信息論度量信息,信息論是量化處理信息的分支科學。我們可以在劃分數據之前使用信息論量化度量信息的內容。
在劃分數據集之前之後信息發生的變化稱爲信息增益,知道如何計算信息增益,我們就可以計算每個特徵值劃分數據集獲得的信息增益,獲得信息增益最高的特徵就是最好的選擇。
在可以評測哪種數據劃分方式是最好的數據劃分之前,我們必須學習如何計算信息增益。集合信息的度量方式稱爲香農熵或者簡稱爲熵,這個名字來源於信息論之父克勞德•香農。
entropy
熵定義爲信息的期望值,在明晰這個概念之前,我們必須知道信息的定義。如果待分類的事務可能劃分在多個分類之中,則符號x的信息定義爲:
其中p(x)是選擇該分類的概率
爲了計算熵,我們需要計算所有類別所有可能值包含的信息期望值,通過下面的公式得到:
其中n是分類的數目。
在決策樹當中,設D爲用類別對訓練元組進行的劃分,則D的熵(entropy)表示爲:
其中pi表示第i個類別在整個訓練元組中出現的概率,可以用屬於此類別元素的數量除以訓練元組元素總數量作爲估計。熵的實際意義表示是D中元組的類標號所需要的平均信息量。
現在我們假設將訓練元組D按屬性A進行劃分,則A對D劃分的期望信息爲:
而信息增益即爲兩者的差值:
ID3算法就是在每次需要分裂時,計算每個屬性的增益率,然後選擇增益率最大的屬性進行分裂。下面我們繼續用SNS社區中不真實賬號檢測的例子說明如何使用ID3算法構造決策樹。爲了簡單起見,我們假設訓練集合包含10個元素:
其中s、m和l分別表示小、中和大。
設L、F和H表示日誌密度、好友密度、是否使用真實頭像,下面計算各屬性的信息增益。
# 賬號是否真實的信息熵
# no 0.3
# yes 0.7
info_D = -(0.3*np.log2(0.3) + 0.7*np.log2(0.7))
info_D
Out:0.8812908992306927
因此日誌密度的信息增益是0.276。
用同樣方法得到F和H的信息增益分別爲0.553和0.033。
因爲F具有最大的信息增益,所以第一次分裂選擇F爲分裂屬性,分裂後的結果如下圖表示:
在上圖的基礎上,再遞歸使用這個方法計算子節點的分裂屬性,最終就可以得到整個決策樹。
練習
計算上圖的信息熵,確定下一個分類的特徵
- # 賬號是否真實的信息熵
- # 根據屬性對目標值進行分類
- # 屬性:是否使用真實頭像、好友密度、日誌密度
- # 三個屬性作爲決策樹的樹頂,都可以,誰更好???
- # 計算機只能信息熵的變化,來決定使用哪個屬性作爲樹頂更好
- # 分別計算
根據好友密度進行決策樹構造:
- # 0.4 s -----> 3no(0.75) 1yes(0.25)
# 0.4 m -----> 4yes(1.0)
# 0.2 l -----> 2yes(1.0)
'''根據好友密度進行決策樹構造,
# 0.4 s -----> 3no(0.75) 1yes(0.25)
# 0.4 m -----> 4yes(1.0)
# 0.2 l -----> 2yes(1.0)'''
info_F_D = -0.4*(0.75*np.log2(0.75) + 0.25*np.log2(0.25)) - 0.4*(1.0*np.log2(1)) - 0.2*(np.log2(1))
info_F_D
Out: 0.32451124978365314
'''信息熵變小,根據好友密度進行劃分,數據結構變的有順序了'''
info_D - info_F_D
Out: 0.5567796494470396
根據日誌密度進行決策的構造:
- # 0.3s ---->2no(2/3) 1yes(1/3)
- # 0.4m ---->1no(0.25) 3yes(0.75)
- # 0.3l ---->3yes(1.0)
# 根據日誌密度進行決策的構造
# 0.3s ---->2no(2/3) 1yes(1/3)
# 0.4m ---->1no(0.25) 3yes(0.75)
# 0.3l ---->3yes(1.0)
info_L_D = -0.3*((2/3)*np.log2(2/3) + (1/3)*np.log2(1/3)) - 0.4*(0.25*np.log2(0.25) + 0.75*np.log2(0.75))
info_L_D
Out:0.6
info_D - info_L_D
Out:0.2812908992306927
DecisionTreeClassifier和DecisionTreeRegressor 重要參數調參注意點
轉載:https://blog.csdn.net/akon_wang_hkbu/article/details/77621631
爲了便於比較,這裏我們用表格的形式對DecisionTreeClassifier和DecisionTreeRegressor重要參數要點做一個比較。
參數 | DecisionTreeClassifier | DecisionTreeRegressor |
特徵選擇標準criterion |
可以使用"gini"或者"entropy",前者代表基尼係數,後者代表信息增益。一般說使用默認的基尼係數"gini"就可以了,即CART算法。除非你更喜歡類似ID3, C4.5的最優特徵選擇方法。 |
可以使用"mse"或者"mae",前者是均方差,後者是和均值之差的絕對值之和。推薦使用默認的"mse"。一般來說"mse"比"mae"更加精確。除非你想比較二個參數的效果的不同之處。 |
特徵劃分點選擇標準splitter |
可以使用"best"或者"random"。前者在特徵的所有劃分點中找出最優的劃分點。後者是隨機的在部分劃分點中找局部最優的劃分點。 默認的"best"適合樣本量不大的時候,而如果樣本數據量非常大,此時決策樹構建推薦"random" |
|
劃分時考慮的最大特徵數max_features |
可以使用很多種類型的值,默認是"None",意味着劃分時考慮所有的特徵數;如果是"log2"意味着劃分時最多考慮$log_2N$個特徵;如果是"sqrt"或者"auto"意味着劃分時最多考慮$\sqrt{N}$個特徵。如果是整數,代表考慮的特徵絕對數。如果是浮點數,代表考慮特徵百分比,即考慮(百分比xN)取整後的特徵數。其中N爲樣本總特徵數。 一般來說,如果樣本特徵數不多,比如小於50,我們用默認的"None"就可以了,如果特徵數非常多,我們可以靈活使用剛纔描述的其他取值來控制劃分時考慮的最大特徵數,以控制決策樹的生成時間。 |
|
決策樹最大深max_depth |
決策樹的最大深度,默認可以不輸入,如果不輸入的話,決策樹在建立子樹的時候不會限制子樹的深度。一般來說,數據少或者特徵少的時候可以不管這個值。如果模型樣本量多,特徵也多的情況下,推薦限制這個最大深度,具體的取值取決於數據的分佈。常用的可以取值10-100之間。 | |
內部節點再劃分所需最小樣本數min_samples_split |
這個值限制了子樹繼續劃分的條件,如果某節點的樣本數少於min_samples_split,則不會繼續再嘗試選擇最優特徵來進行劃分。 默認是2.如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。我之前的一個項目例子,有大概10萬樣本,建立決策樹時,我選擇了min_samples_split=10。可以作爲參考。 | |
葉子節點最少樣本數min_samples_leaf |
這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小於樣本數,則會和兄弟節點一起被剪枝。 默認是1,可以輸入最少的樣本數的整數,或者最少樣本數佔樣本總數的百分比。如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。之前的10萬樣本項目使用min_samples_leaf的值爲5,僅供參考。 | |
葉子節點最小的樣本權重和min_weight_fraction_leaf |
這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝。 默認是0,就是不考慮權重問題。一般來說,如果我們有較多樣本有缺失值,或者分類樹樣本的分佈類別偏差很大,就會引入樣本權重,這時我們就要注意這個值了。 | |
最大葉子節點數max_leaf_nodes |
通過限制最大葉子節點數,可以防止過擬合,默認是"None”,即不限制最大的葉子節點數。如果加了限制,算法會建立在最大葉子節點數內最優的決策樹。如果特徵不多,可以不考慮這個值,但是如果特徵分成多的話,可以加以限制,具體的值可以通過交叉驗證得到。 | |
類別權重class_weight |
指定樣本各類別的的權重,主要是爲了防止訓練集某些類別的樣本過多,導致訓練的決策樹過於偏向這些類別。這裏可以自己指定各個樣本的權重,或者用“balanced”,如果使用“balanced”,則算法會自己計算權重,樣本量少的類別所對應的樣本權重會高。當然,如果你的樣本類別分佈沒有明顯的偏倚,則可以不管這個參數,選擇默認的"None" | 不適用於迴歸樹 |
節點劃分最小不純度min_impurity_split |
這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值,則該節點不再生成子節點。即爲葉子節點 。 | |
數據是否預排序presort |
這個值是布爾值,默認是False不排序。一般來說,如果樣本量少或者限制了一個深度很小的決策樹,設置爲true可以讓劃分點選擇更加快,決策樹建立的更加快。如果樣本量太大的話,反而沒有什麼好處。問題是樣本量少的時候,我速度本來就不慢。所以這個值一般懶得理它就可以了。 |
除了這些參數要注意以外,其他在調參時的注意點有:
- 1)當樣本少數量但是樣本特徵非常多的時候,決策樹很容易過擬合,一般來說,樣本數比特徵數多一些會比較容易建立健壯的模型
- 2)如果樣本數量少但是樣本特徵非常多,在擬合決策樹模型前,推薦先做維度規約,比如主成分分析(PCA),特徵選擇(Losso)或者獨立成分分析(ICA)。這樣特徵的維度會大大減小。再來擬合決策樹模型效果會好。
- 3)推薦多用決策樹的可視化(下節會講),同時先限制決策樹的深度(比如最多3層),這樣可以先觀察下生成的決策樹裏數據的初步擬合情況,然後再決定是否要增加深度。
- 4)在訓練模型先,注意觀察樣本的類別情況(主要指分類樹),如果類別分佈非常不均勻,就要考慮用class_weight來限制模型過於偏向樣本多的類別。
- 5)決策樹的數組使用的是numpy的float32類型,如果訓練數據不是這樣的格式,算法會先做copy再運行。
- 6)如果輸入的樣本矩陣是稀疏的,推薦在擬合前調用
csc_matrix
稀疏化,在預測前調用csr_matrix稀疏化。
三、實戰
【注意】 參數max_depth越大,越容易過擬合
1、使用自帶的iris數據集
導包:
# 決策樹
'''
DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=None,
min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None,
random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0,
min_impurity_split=None, class_weight=None, presort=False)
'''
from sklearn.tree import DecisionTreeClassifier
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split
數據集:
iris = datasets.load_iris()
X = iris['data']
y = iris['target']
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.3)
X.shape
OUt:(150,4)
使用決策樹算法:
max_depth=5
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.3)
tree = DecisionTreeClassifier(max_depth=5)
tree.fit(X_train,y_train)
tree.score(X_test,y_test)
Out: 0.8888888888888888
max_depth=3
tree = DecisionTreeClassifier(max_depth=3)
tree.fit(X_train,y_train)
tree.score(X_test,y_test)
Out: 0.9555555555555556
max_depth=1
tree = DecisionTreeClassifier(max_depth=1)
tree.fit(X_train,y_train)
tree.score(X_test,y_test)
Out:0.6444444444444445
使用KNN算法:
n_neighbors=5
'''KNeighborsClassifier(n_neighbors=5, weights='uniform', algorithm='auto',
leaf_size=30, p=2, metric='minkowski', metric_params=None, n_jobs=1, **kwargs)
'''
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train,y_train)
knn.score(X_test,y_test)
Out:
0.9333333333333333
n_neighbors=15
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=15)
knn.fit(X_train,y_train)
knn.score(X_test,y_test)
Out: 0.9333333333333333
n_neighbors=1
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train,y_train)
knn.score(X_test,y_test)
Out: 0.9777777777777777
導繪圖包
import matplotlib.pyplot as plt
%matplotlib inline
目標數據的分類作爲顏色,一個分類一個顏色
y
Out:
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
'''plt.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None,
vmax=None, alpha=None, linewidths=None, verts=None, edgecolors=None, hold=None, data=None,
**kwargs)'''
plt.scatter(X[:,2],X[:,3],c = y)
使用邏輯斯蒂迴歸算法:
from sklearn.linear_model import LogisticRegression
'''LogisticRegression(penalty='l2', dual=False, tol=0.0001, C=1.0, fit_intercept=True,
intercept_scaling=1, class_weight=None, random_state=None, solver='liblinear',
max_iter=100, multi_class='ovr', verbose=0, warm_start=False, n_jobs=1)'''
logistic = LogisticRegression()
logistic.fit(X_train,y_train)
logistic.score(X_test,y_test)
Out: 0.9777777777777777
logistic.coef_
Out:
array([[ 0.38715484, 1.35756217, -2.0889337 , -0.96149223],
[ 0.18305144, -1.11389252, 0.58911239, -1.12108665],
[-1.30172323, -1.63587224, 2.03041769, 2.29236273]])
logistic.intercept_
Out:
array([ 0.26267869, 0.58829742, -0.8724249 ])
# 150個數據鳶尾花的數據4個屬性,從中取出來兩個屬性,進行學習預測
plt.scatter(X[:,0],X[:,1],c = y)
使用 np.meshgrid(x,y) 繪製畫布
'''np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)'''
x = np.linspace(4,8,100)
y = np.linspace(1.8,4.5,100)
''' np.meshgrid(*xi, **kwargs)'''
X,Y = np.meshgrid(x,y)
X.shape ——>(100, 100)
plt.scatter(X,Y)
a = np.array([2,3,4])
b = np.array([-1,-2,-3])
A,B = np.meshgrid(a,b)
display(A,B)
plt.scatter(A,B)
Out:
array([[2, 3, 4],
[2, 3, 4],
[2, 3, 4]])
array([[-1, -1, -1],
[-2, -2, -2],
[-3, -3, -3]])
使用級聯講兩個數據聯合到一個表格中
ab = np.concatenate([A.reshape(-1,1),B.reshape(-1,1)],axis = 1 )
plt.scatter(ab[:,0],ab[:,1])
設置背景數據:
# X.shape = (100,100)
X_test_1 = np.concatenate([X.reshape(-1,1),Y.reshape(-1,1)],axis = 1)
# 計算機創造的10000個鳶尾花(花萼長度、花萼寬度)
X_test_1.shape
Out : (10000, 2)
繪製圖形:
X_train = iris['data'][:,[0,1]]
y_train = iris['target']
tree = DecisionTreeClassifier(max_depth=3)
# 花萼長寬屬性
# ValueError: Unknown label type: 'continuous'
tree.fit(X_train,y_train)
# 預測分類邊界
y_ = tree.predict(X_test_1)
plt.scatter(X_test_1[:,0],X_test_1[:,1],c = y_)
'''plt.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None,
vmax=None, alpha=None, linewidths=None, verts=None, edgecolors=None, hold=None, data=None,
**kwargs)'''
plt.scatter(X_train[:,0],X_train[:,1],c = y_train,cmap = 'ocean')
使用邏輯斯蒂迴歸:
logistic = LogisticRegression()
logistic.fit(X_train,y_train)
y_ = logistic.predict(X_test)
plt.scatter(X_test[:,0],X_test[:,1],c = y_)
plt.scatter(X_train[:,0],X_train[:,1],c = y_train,cmap = 'ocean')
2、使用迴歸預測一個橢圓
- 使用RandomState生成固定隨機數
- 創建-100到100之間的角度
- 生成正弦值和餘弦值
- 添加噪聲
創建-100到100的預測數據,間隔爲0.01
- 對數據進行預測
- 顯示圖片
X = np.linspace(-100,100,100)
s = np.sin(X)
c = np.cos(X)
plt.scatter(s,c)
plt.axis('equal')
Out:
(-1.1053993341495696,
1.1053993341495667,
-1.110327464822749,
1.111091380563182)
將2列數據級聯成一個表
display(s.shape,c.shape)
Out:
(100,)
(100,)
y = np.concatenate([s.reshape(-1,1),c.reshape(-1,1)],axis = 1)
y.shape
Out: (100, 2)
創建不同深度的決策樹,進行數據訓練
from sklearn.tree import DecisionTreeRegressor
# X.shape :(100,) y:(100,2)
tree_5 = DecisionTreeRegressor(max_depth= 5)
tree_5.fit(X.reshape(-1,1),y)
X_test = np.linspace(-100,100,300).reshape(-1,1)
y_ = tree_5.predict(X_test)
plt.scatter(y_[:,0],y_[:,1])
plt.axis('equal')
tree_20 = DecisionTreeRegressor(max_depth= 20)
tree_20.fit(X.reshape(-1,1),y)
X_test = np.linspace(-100,100,300).reshape(-1,1)
y_ = tree_20.predict(X_test)
plt.scatter(y_[:,0],y_[:,1])
plt.axis('equal')
tree_50 = DecisionTreeRegressor(max_depth= 100)
tree_50.fit(X.reshape(-1,1),y)
X_test = np.linspace(-100,100,300).reshape(-1,1)
y_ = tree_50.predict(X_test)
plt.scatter(y_[:,0],y_[:,1])
plt.axis('equal')
tree_1= DecisionTreeRegressor(max_depth= 1)
tree_1.fit(X.reshape(-1,1),y)
X_test = np.linspace(-100,100,300).reshape(-1,1)
y_ = tree_1.predict(X_test)
plt.scatter(y_[:,0],y_[:,1])
plt.axis('equal')
使用Kfold進行數據劃分
sklearn中的數據集的劃分
sklearn數據集劃分方法有如下方法:
KFold,GroupKFold,StratifiedKFold,LeaveOneGroupOut,LeavePGroupsOut,LeaveOneOut,LeavePOut,ShuffleSplit,GroupShuffleSplit,StratifiedShuffleSplit,PredefinedSplit,TimeSeriesSplit,
①數據集劃分方法——K折交叉驗證:KFold,GroupKFold,StratifiedKFold,
- 將全部訓練集S分成k個不相交的子集,假設S中的訓練樣例個數爲m,那麼每一個自己有m/k個訓練樣例,相應的子集爲{s1,s2,...,sk}
- 每次從分好的子集裏面,拿出一個作爲測試集,其他k-1個作爲訓練集
- 在k-1個訓練集上訓練出學習器模型
- 把這個模型放到測試集上,得到分類率的平均值,作爲該模型或者假設函數的真實分類率
這個方法充分利用了所以樣本,但計算比較繁瑣,需要訓練k次,測試k次
---------------------------------------------------------------------------------------------
- 思路:將訓練/測試數據集劃分n_splits個互斥子集,每次用其中一個子集當作驗證集,剩下的n_splits-1個作爲訓練集,進行n_splits次訓練和測試,得到n_splits個結果
- 注意點:對於不能均等份的數據集,其前n_samples % n_splits子集擁有n_samples // n_splits + 1個樣本,其餘子集都只有n_samples // n_splits樣本
參數說明:
- n_splits:表示劃分幾等份
- shuffle:在每次劃分時,是否進行洗牌
- ①若爲Falses時,其效果等同於random_state等於整數,每次劃分的結果相同
- ②若爲True時,每次劃分的結果都不一樣,表示經過洗牌,隨機取樣的
- random_state:隨機種子數
屬性:
- ①get_n_splits(X=None, y=None, groups=None):獲取參數n_splits的值
- ②split(X, y=None, groups=None):將數據集劃分成訓練集和測試集,返回索引生成器
- 通過一個不能均等劃分的栗子,設置不同參數值,觀察其結果
- ①設置shuffle=False,運行兩次,發現兩次結果相同
導包
from sklearn.model_selection import KFold
'''n_splits=3, shuffle=False, random_state=None'''
kFold = KFold(n_splits=3)
for train_index,test_index in kFold.split(X,y):
print(train,test)
n_splits屬性值獲取方式
In [8]: kFold .split(X)
Out[8]: <generator object _BaseKFold.split at 0x00000000047FF990>
In [9]: kFold .get_n_splits()
Out[9]: 5
In [10]: kFold .n_splits
Out[10]: 5
交叉驗證
from sklearn.cross_validation import cross_val_score
轉載於: https://blog.csdn.net/qq_36523839/article/details/80707678
在構建模型時,調參是極爲重要的一個步驟,因爲只有選擇最佳的參數才能構建一個最優的模型。但是應該如何確定參數的值呢?所以這裏記錄一下選擇參數的方法,以便後期複習以及分享。
我知道的有兩種方法:1、通過經常使用某個模型的經驗和高超的數學知識。2、通過交叉驗證的方法,逐個來驗證。
很顯然我是屬於後者所以我需要在這裏記錄一下(如果你屬於前者可以教教我)
sklearn的cross_val_score:
我使用是cross_val_score方法,在sklearn中可以使用這個方法。交叉驗證的原理不好表述下面隨手畫了一個圖:
有點醜,簡單說下,比如上面,我們將數據集分爲10折,做一次交叉驗證,實際上它是計算了十次,將每一折都當做一次測試集,其餘九折當做訓練集,這樣循環十次。通過傳入的模型,訓練十次,最後將十次結果求平均值。將每個數據集都算一次
交叉驗證優點:
1:交叉驗證用於評估模型的預測性能,尤其是訓練好的模型在新數據上的表現,可以在一定程度上減小過擬合。
2:還可以從有限的數據中獲取儘可能多的有效信息。
我們如何利用它來選擇參數呢?
我們可以給它加上循環,通過循環不斷的改變參數,再利用交叉驗證來評估不同參數模型的能力。最終選擇能力最優的模型。
下面通過一個簡單的實例來說明:(iris鳶尾花)
from sklearn import datasets #自帶數據集
from sklearn.model_selection import train_test_split,cross_val_score #劃分數據 交叉驗證
from sklearn.neighbors import KNeighborsClassifier #一個簡單的模型,只有K一個參數,類似K-means
import matplotlib.pyplot as plt
iris = datasets.load_iris() #加載sklearn自帶的數據集
X = iris.data #這是數據
y = iris.target #這是每個數據所對應的標籤
train_X,test_X,train_y,test_y = train_test_split(X,y,test_size=1/3,random_state=3) #這裏劃分數據以1/3的來劃分 訓練集訓練結果 測試集測試結果
k_range = range(1,31)
cv_scores = [] #用來放每個模型的結果值
for n in k_range:
knn = KNeighborsClassifier(n) #knn模型,這裏一個超參數可以做預測,當多個超參數時需要使用另一種方法GndSearchCV
scores = cross_val_score(knn,train_X,train_y,cv=10,scoring='accuracy') #cv:選擇每次測試折數 accuracy:評價指標是準確度,可以不要
cv_scores.append(scores.mean())
plt.plot(k_range,cv_scores)
plt.xlabel('K')
plt.ylabel('Accuracy') #通過圖像選擇最好的參數
plt.show()
best_knn = KNeighborsClassifier(n_neighbors=3) # 選擇最優的K=3傳入模型
best_knn.fit(train_X,train_y) #訓練模型
print(best_knn.score(test_X,test_y)) #看看評分
最後得分0.94