這是一篇關(guān)于機(jī)器學(xué)習(xí)工具包Scikit-learn的入門級(jí)讀物,。對(duì)于程序員來說,,機(jī)器學(xué)習(xí)的重要性毋庸贅言。也許你還沒有開始,,也許曾經(jīng)失敗過,,都沒有關(guān)系,你將在這里找到或者重拾自信,。只要粗通Python,,略知NumPy,認(rèn)真讀完這21句話,,逐行敲完示例代碼,,就可以由此進(jìn)入自由的王國。
1. 機(jī)器學(xué)習(xí)有四種用途:分類,、聚類,、回歸和降維。
理解了這句話,就意味著學(xué)會(huì)了機(jī)器學(xué)習(xí),。迷茫的時(shí)候,,在心里默念這句話,就會(huì)找到前進(jìn)的方向,。更嚴(yán)格一點(diǎn),,機(jī)器學(xué)習(xí)的目的只有三個(gè):分類、聚類和回歸,,降維不過是達(dá)成目標(biāo)的手段之一,。
2. 分類和聚類都是對(duì)個(gè)體樣本歸類,看起來很相似,,實(shí)則相去甚遠(yuǎn)——前者屬于有監(jiān)督的學(xué)習(xí),,后者屬于無監(jiān)督的學(xué)習(xí)。
分類是基于經(jīng)驗(yàn)的,,而經(jīng)驗(yàn)來自過往的數(shù)據(jù),,這意味著分類需要訓(xùn)練;聚類則是基于當(dāng)前全部樣本的特征,,不依賴經(jīng)驗(yàn),,自然也就無需訓(xùn)練。舉個(gè)例子:讓你從一堆水果中挑出蘋果,、橘子和香蕉,,這是分類;讓你將畫在紙上的若干個(gè)圖案分組,,分組規(guī)則由你決定,,這是聚類。
3. 從字面上看,,分類和回歸看上去風(fēng)馬牛不相及,,其實(shí)二者是親兄弟,使用的算法幾乎完全重合,。
分類是對(duì)個(gè)體樣本做出定性判定,,回歸是對(duì)個(gè)體樣本做出定量判定,二者同屬于有監(jiān)督的學(xué)習(xí),,都是基于經(jīng)驗(yàn)的。舉個(gè)例子:有經(jīng)驗(yàn)的老師預(yù)測(cè)某學(xué)生考試及格或不及格,,這是分類,;預(yù)測(cè)某學(xué)生能考多少分,這是回歸,;不管是預(yù)測(cè)是否及格還是預(yù)測(cè)考多少分,,老師的經(jīng)驗(yàn)數(shù)據(jù)和思考方法是相同的,只是最后的表述不同而已。
4. 傳統(tǒng)的軟件開發(fā),,代碼是重點(diǎn),,而對(duì)于機(jī)器學(xué)習(xí),數(shù)據(jù)是重點(diǎn),。
在訓(xùn)練機(jī)器學(xué)習(xí)模型時(shí),,數(shù)據(jù)的質(zhì)量和數(shù)量都會(huì)影響訓(xùn)練結(jié)果的準(zhǔn)確性和有效性。因此,,無論是學(xué)習(xí)還是應(yīng)用機(jī)器學(xué)習(xí)模型解決問題,,前提都是要有足夠多且足夠好的數(shù)據(jù)集。
5. 數(shù)據(jù)集通常是指由若干個(gè)樣本數(shù)據(jù)組成的二維數(shù)組,,數(shù)組的每一行表示一個(gè)樣本的數(shù)據(jù),。
舉個(gè)例子:用性別、年齡,、身高(米),、體重(千克)、職業(yè),、年薪(萬元),、不動(dòng)產(chǎn)(萬元)、有價(jià)證券(萬元)等信息組成的一維數(shù)組表示一位征婚者的數(shù)據(jù),,下面的二維數(shù)組就是一個(gè)婚介機(jī)構(gòu)收集到的征婚者數(shù)據(jù)集,。
>>> import numpy as np
>>> members = np.array([
['男', '25', 185, 80, '程序員', 35, 200, 30],
['女', '23', 170, 55, '公務(wù)員', 15, 0, 80],
['男', '30', 180, 82, '律師', 60, 260, 300],
['女', '27', 168, 52, '記者', 20, 180, 150]
])
6. 數(shù)據(jù)集的列,也被稱為特征維或特征列,。
上面的征婚者數(shù)據(jù)集共有性別,、年齡、身高(米),、體重(千克),、職業(yè)、年薪(萬元),、不動(dòng)產(chǎn)(萬元),、有價(jià)證券(萬元)等8列,也可以說這個(gè)數(shù)據(jù)集有8個(gè)特征維或特征列,。
7. 所謂降維,,并非是將數(shù)據(jù)集從二維變成一維,而是減少數(shù)據(jù)集的特征維,。
征婚者的個(gè)人信息遠(yuǎn)不止上面所列出的這8項(xiàng),,還可以加上生日、業(yè)余愛好,、喜歡的顏色,、愛吃的食物等等。不過,要是將所有的個(gè)人信息都加入到數(shù)據(jù)集中,,不但會(huì)增加數(shù)據(jù)保存和處理的難度和成本,,對(duì)于擇偶者來說,也會(huì)因?yàn)樾畔⒘刻喽稚⒘俗⒁饬?,以至于忽略了最重要的信息,。降維就是從數(shù)據(jù)集中剔除對(duì)結(jié)果無影響或影響甚微的特征列。
8. 標(biāo)準(zhǔn)化是對(duì)樣本集的每個(gè)特征列減去該特征列的平均值進(jìn)行中心化,,再除以標(biāo)準(zhǔn)差進(jìn)行縮放,。
滿分為100分的考試中,你如果得了90分,,這自然是一個(gè)好成績,。不過要是和其他同學(xué)比的話,就未必是了:假如其他同學(xué)都是滿分,,那90分就是最差的一個(gè),。數(shù)據(jù)標(biāo)準(zhǔn)化的意義在于反映個(gè)體數(shù)據(jù)偏離所有樣本平均值的程度。下面是對(duì)征婚者數(shù)據(jù)集中有價(jià)證券特征列標(biāo)準(zhǔn)化后的結(jié)果,。
>>> security = np.float32((members[:,-1])) # 提取有價(jià)證券特征列數(shù)據(jù)
>>> security
array([ 30., 80., 300., 150.], dtype=float32)
>>> (security - security.mean())/security.std() # 減去均值再除以標(biāo)準(zhǔn)差
array([-1.081241, -0.5897678, 1.5727142, 0.09829464], dtype=float32)
9. 歸一化是對(duì)樣本集的每個(gè)特征列減去該特征列的最小值進(jìn)行中心化,,再除以極差(最大值最小值之差)進(jìn)行縮放。
歸一化處理類似于標(biāo)準(zhǔn)化,,結(jié)果收斂于[0,1]區(qū)間內(nèi),。下面是對(duì)征婚者數(shù)據(jù)集中有價(jià)證券特征列歸一化后的結(jié)果。
>>> security = np.float32((members[:,-1])) # 提取有價(jià)證券特征列數(shù)據(jù)
>>> security
array([ 30., 80., 300., 150.], dtype=float32)
>>> (security - security.min())/(security.max() - security.min()) # 減去最小值再除以極差
array([0., 0.18518518, 1., 0.44444445], dtype=float32)
10. 機(jī)器學(xué)習(xí)模型只能處理數(shù)值數(shù)據(jù),,因此需要將性別,、職業(yè)等非數(shù)值數(shù)據(jù)變成整數(shù),這個(gè)過程被稱為特征編碼,。
征婚者數(shù)據(jù)集中,,對(duì)于性別特征列,可以用0表示女性,,用1表示男性,,或者反過來也沒有問題。不過這個(gè)方法不適用于職業(yè)特征列的編碼,,因?yàn)椴煌殬I(yè)之間原本是無序的,,如果用這個(gè)方法編碼,就會(huì)產(chǎn)生2比1更接近3的問題,。此時(shí)通行的做法是使用獨(dú)熱碼(one-of-K):若有n個(gè)不同的職業(yè),,就用n位二進(jìn)制數(shù)字表示,每個(gè)數(shù)字只有1位為1其余為0,。此時(shí),職業(yè)特征列將從1個(gè)擴(kuò)展為n個(gè)。下面使用Scikit-learn的獨(dú)熱碼編碼器對(duì)性別和職業(yè)兩列做特征編碼,,生成6個(gè)特征列(性別2列,,職業(yè)4列)。該編碼器位于preprocessing子模塊中,。
>>> from sklearn import preprocessing as pp
>>> X = [
['男', '程序員'],
['女', '公務(wù)員'],
['男', '律師', ],
['女', '記者', ]
]
>>> ohe = pp.OneHotEncoder().fit(X)
>>> ohe.transform(X).toarray()
array([[0., 1., 0., 0., 1., 0.],
[1., 0., 1., 0., 0., 0.],
[0., 1., 0., 1., 0., 0.],
[1., 0., 0., 0., 0., 1.]])
11. Scikit-learn的數(shù)據(jù)集子模塊datasets提供了若干數(shù)據(jù)集:函數(shù)名以load 開頭的是模塊內(nèi)置的小型數(shù)據(jù)集,;函數(shù)名以fetch開頭,是需要從外部數(shù)據(jù)源下載的大型數(shù)據(jù)集,。
- datasets.load_boston([return_X_y]) :加載波士頓房價(jià)數(shù)據(jù)集
- datasets.load_breast_cancer([return_X_y]) :加載威斯康星州乳腺癌數(shù)據(jù)集
- datasets.load_diabetes([return_X_y]) :加載糖尿病數(shù)據(jù)集
- datasets.load_digits([n_class, return_X_y]) :加載數(shù)字?jǐn)?shù)據(jù)集
- datasets.load_iris([return_X_y]) :加載鳶尾花數(shù)據(jù)集,。
- datasets.load_linnerud([return_X_y]) :加載體能訓(xùn)練數(shù)據(jù)集
- datasets.load_wine([return_X_y]) :加載葡萄酒數(shù)據(jù)集
- datasets.fetch_20newsgroups([data_home, …]) :加載新聞文本分類數(shù)據(jù)集
- datasets.fetch_20newsgroups_vectorized([…]) :加載新聞文本向量化數(shù)據(jù)集
- datasets.fetch_california_housing([…]) :加載加利福尼亞住房數(shù)據(jù)集
- datasets.fetch_covtype([data_home, …]) :加載森林植被數(shù)據(jù)集
- datasets.fetch_kddcup99([subset, data_home, …]) :加載網(wǎng)絡(luò)入侵檢測(cè)數(shù)據(jù)集
- datasets.fetch_lfw_pairs([subset, …]) :加載人臉(成對(duì))數(shù)據(jù)集
- datasets.fetch_lfw_people([data_home, …]) :加載人臉(帶標(biāo)簽)數(shù)據(jù)集
- datasets.fetch_olivetti_faces([data_home, …]) :加載 Olivetti 人臉數(shù)據(jù)集
- datasets.fetch_rcv1([data_home, subset, …]):加載路透社英文新聞文本分類數(shù)據(jù)集
- datasets.fetch_species_distributions([…]) :加載物種分布數(shù)據(jù)集
12. 每個(gè)二維的數(shù)據(jù)集對(duì)應(yīng)著一個(gè)一維的標(biāo)簽集,用于標(biāo)識(shí)每個(gè)樣本的所屬類別或?qū)傩灾?。通常?shù)據(jù)集用大寫字母X表示,,標(biāo)簽集用小寫字母y表示。
下面的代碼從數(shù)據(jù)集子模塊datasets中提取了鳶尾花數(shù)據(jù)集——這是用來演示分類模型的最常用的數(shù)據(jù)集,。鳶尾花數(shù)據(jù)集X共有150個(gè)樣本,,每個(gè)樣本有4個(gè)特征列,分別是花萼的長度和寬度,、花瓣的長度和寬度,。這些樣本共有3種類型,分別用整數(shù)0,、1,、2表示,所有樣本的類型標(biāo)簽組成標(biāo)簽集y,,這是一個(gè)一維數(shù)組,。
>>> from sklearn.datasets import load_iris
>>> X, y = load_iris(return_X_y=True)
>>> X.shape # 數(shù)據(jù)集X有150個(gè)樣本,4個(gè)特征列
(150, 4)
>>> y.shape # 標(biāo)簽集y的每一個(gè)標(biāo)簽和數(shù)據(jù)集X的每一個(gè)樣本一一對(duì)應(yīng)
(150,)
>>> X[0], y[0]
(array([5.1, 3.5, 1.4, 0.2]), 0)
加載數(shù)據(jù)時(shí),,如果指定return_X_y參數(shù)為False(默認(rèn)值),,則可以查看標(biāo)簽的名字。
>>> iris = load_iris()
>>> iris.target_names # 查看標(biāo)簽的名字
array(['setosa', 'versicolor', 'virginica'], dtype='<U10')
>>> X = iris.data
>>> y = iris.target
13. 模型訓(xùn)練時(shí),,通常會(huì)將數(shù)據(jù)集和標(biāo)簽集分成兩部分:一部分用于訓(xùn)練,,一部分用于測(cè)試。
分割數(shù)據(jù)集是一項(xiàng)非常重要的工作,,不同的分割方法對(duì)于模型訓(xùn)練的結(jié)果有不同的影響,。 Scikit-learn提供了很多種數(shù)據(jù)集分割方法,train_test_split是其中最簡單的一種,,可以根據(jù)指定的比例隨機(jī)抽取測(cè)試集,。train_test_split函數(shù)位于模型選擇子模塊model_selection中。
>>> from sklearn.datasets import load_iris
>>> from sklearn.model_selection import train_test_split as tsplit
>>> X, y = load_iris(return_X_y=True)
>>> X_train, X_test, y_train, y_test = tsplit(X, y, test_size=0.1)
>>> X_train.shape, X_test.shape
((135, 4), (15, 4))
>>> y_train.shape, y_test.shape
((135,), (15,))
上面的代碼按照10%的比例隨機(jī)從數(shù)據(jù)集中抽取樣本作為測(cè)試集,,剩余樣本作為訓(xùn)練集,。分割完成后,,訓(xùn)練集有135個(gè)樣本,測(cè)試集有15個(gè)樣本,。
14. 近朱者赤,,近墨者黑,距離誰最近,,就和誰同類——這就是k-近鄰分類,。
k-近鄰分類是最簡單、最容易的分類方法,。對(duì)于待分類的樣本,,從訓(xùn)練集中找出k個(gè)和它距離最近的樣本,考察這些樣本中哪一個(gè)標(biāo)簽最多,,就給待分類樣本貼上該標(biāo)簽,。k值的最佳選擇高度依賴數(shù)據(jù),較大的k值會(huì)抑制噪聲的影響,,但同時(shí)也會(huì)使分類界限不明顯,。通常k值選擇不大于20的整數(shù)。
>>> from sklearn.datasets import load_iris
>>> from sklearn.model_selection import train_test_split as tsplit
>>> from sklearn.neighbors import KNeighborsClassifier # 導(dǎo)入k-近鄰分類模型
>>> X, y = load_iris(return_X_y=True) # 獲取鳶尾花數(shù)據(jù)集,,返回樣本集和標(biāo)簽集
>>> X_train, X_test, y_train, y_test = tsplit(X, y, test_size=0.1) # 拆分為訓(xùn)練集和測(cè)試集
>>> m = KNeighborsClassifier(n_neighbors=10) # 模型實(shí)例化,,n_neighbors參數(shù)指定k值,默認(rèn)k=5
>>> m.fit(X_train, y_train) # 模型訓(xùn)練
KNeighborsClassifier()
>>> m.predict(X_test) # 對(duì)測(cè)試集分類
array([2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 0, 1, 0, 0, 2])
>>> y_test # 這是實(shí)際的分類情況,,上面的預(yù)測(cè)只錯(cuò)了一個(gè)
array([2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 0, 1, 0, 0, 2])
>>> m.score(X_test, y_test) # 模型測(cè)試精度(介于0~1)
0.9333333333333333
應(yīng)用分類模型對(duì)15個(gè)測(cè)試樣本分類,,結(jié)果只有1個(gè)是錯(cuò)誤的,準(zhǔn)確率約為93%,。在分類算法中,,score是最常用的評(píng)估函數(shù),返回分類正確的樣本數(shù)與測(cè)試樣本總數(shù)之比,。
15. 一輛開了八年的大切諾基可以賣多少錢,?最簡單的方法是參考k輛同款車型且使用年限相近的二手車售價(jià)的均值——這就是k-近鄰回歸。
k-近鄰算法不僅可以用來解決分類問題,,也可以用來解決回歸問題,。k-近鄰回歸預(yù)測(cè)樣本的標(biāo)簽由它最近鄰標(biāo)簽的均值計(jì)算而來。下面的代碼以波士頓房價(jià)數(shù)據(jù)集為例,,演示了k-近鄰回歸模型的用法,。波士頓房價(jià)數(shù)據(jù)集統(tǒng)計(jì)的是20世紀(jì)70年代中期波士頓郊區(qū)房價(jià)的中位數(shù),一共有506條不同的數(shù)據(jù),,每條數(shù)據(jù)包含區(qū)域的人文環(huán)境,、自然環(huán)境、商業(yè)環(huán)境,、交通狀況等13個(gè)屬性,,標(biāo)簽是區(qū)域房價(jià)的平均值,。
>>> from sklearn.datasets import load_boston
>>> from sklearn.model_selection import train_test_split as tsplit
>>> from sklearn.neighbors import KNeighborsRegressor
>>> X, y = load_boston(return_X_y=True) # 加載波士頓房價(jià)數(shù)據(jù)集
>>> X.shape, y.shape, y.dtype # 該數(shù)據(jù)集共有506個(gè)樣本,13個(gè)特征列,,標(biāo)簽集為浮點(diǎn)型,,適用于回歸模型
((506, 13), (506,), dtype('float64'))
>>> X_train, X_test, y_train, y_test = tsplit(X, y, test_size=0.01) # 拆分為訓(xùn)練集和測(cè)試集
>>> m = KNeighborsRegressor(n_neighbors=10) # 模型實(shí)例化,,n_neighbors參數(shù)指定k值,,默認(rèn)k=5
>>> m.fit(X_train, y_train) # 模型訓(xùn)練
KNeighborsRegressor(n_neighbors=10)
>>> m.predict(X_test) # 預(yù)測(cè)6個(gè)測(cè)試樣本的房價(jià)
array([27.15, 31.97, 12.68, 28.52, 20.59, 21.47])
>>> y_test # 這是測(cè)試樣本的實(shí)際價(jià)格,除了第2個(gè)(索引為1)樣本偏差較大,,其他樣本偏差還算差強(qiáng)人意
array([29.1, 50. , 12.7, 22.8, 20.4, 21.5])
16. 常用的回歸模型的評(píng)價(jià)方法有均方誤差,、中位數(shù)絕對(duì)誤差和復(fù)相關(guān)系數(shù)等。
評(píng)價(jià)一個(gè)回歸結(jié)果的優(yōu)劣,,比評(píng)價(jià)一個(gè)分類結(jié)果要困難得多——前者需要考慮偏離程度,,而后者只考慮對(duì)錯(cuò)。常用的回歸評(píng)價(jià)函數(shù)是均方誤差函數(shù),、中位數(shù)絕對(duì)誤差函數(shù)和復(fù)相關(guān)系數(shù)函數(shù)等,,這幾個(gè)函數(shù)均被包含在模型評(píng)估指標(biāo)子模塊metrics中。均方誤差和中位數(shù)絕對(duì)誤差越小,,說明模型精確度越高,;復(fù)相關(guān)系數(shù)則相反,越接近1說明模型精確度越高,,越接近0說明模型越不可用,。
以上一段代碼為例,模型評(píng)估結(jié)果如下,。
>>> from sklearn import metrics
>>> y_pred = m.predict(X_test)
>>> metrics.mean_squared_error(y_test, y_pred) # 均方誤差
60.27319999999995
>>> metrics.median_absolute_error(y_test, y_pred) # 中位數(shù)絕對(duì)誤差
1.0700000000000003
>>> metrics.r2_score(y_test, y_pred) # 復(fù)相關(guān)系數(shù)
0.5612816401629652
復(fù)相關(guān)系數(shù)只有0.56,,顯然,用k-近鄰算法預(yù)測(cè)波士頓房價(jià)不是一個(gè)好的選擇,。下面的代碼嘗試用決策樹算法預(yù)測(cè)波士頓房價(jià),,得到了較好的效果,復(fù)相關(guān)系數(shù)達(dá)到0.98,,預(yù)測(cè)房價(jià)非常接近實(shí)際價(jià)格,,誤差極小。
>>> from sklearn.datasets import load_boston
>>> from sklearn.model_selection import train_test_split as tsplit
>>> from sklearn.tree import DecisionTreeRegressor
>>> X, y = load_boston(return_X_y=True) # 加載波士頓房價(jià)數(shù)據(jù)集
>>> X_train, X_test, y_train, y_test = tsplit(X, y, test_size=0.01) # 拆分為訓(xùn)練集和測(cè)試集
>>> m = DecisionTreeRegressor(max_depth=10) # 實(shí)例化模型,,決策樹深度為10
>>> m.fit(X, y) # 訓(xùn)練
DecisionTreeRegressor(max_depth=10)
>>> y_pred = m.predict(X_test) # 預(yù)測(cè)
>>> y_test # 這是測(cè)試樣本的實(shí)際價(jià)格,,除了第2個(gè)(索引為1)樣本偏差略大,其他樣本偏差較小
array([20.4, 21.9, 13.8, 22.4, 13.1, 7. ])
>>> y_pred # 這是6個(gè)測(cè)試樣本的預(yù)測(cè)房價(jià),,非常接近實(shí)際價(jià)格
array([20.14, 22.33, 14.34, 22.4, 14.62, 7. ])
>>> metrics.r2_score(y_test, y_pred) # 復(fù)相關(guān)系數(shù)
0.9848774474870712
>>> metrics.mean_squared_error(y_test, y_pred) # 均方誤差
0.4744784865112032
>>> metrics.median_absolute_error(y_test, y_pred) # 中位數(shù)絕對(duì)誤差
0.3462962962962983
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
17. 決策樹,、支持向量機(jī)(SVM)、貝葉斯等算法,,既可以解決分類問題,,也可以解決回歸問題,。
應(yīng)用這些算法解決分類和回歸問題的流程,與使用k-近鄰算法基本相同,,不同之處在于不同的算法提供了不同的參數(shù),。我們需要仔細(xì)閱讀算法文檔,搞清楚這些參數(shù)的含義,,選擇正確的參數(shù),,才有可能得到正確的結(jié)果。比如,,支持向量機(jī)(SVM)的回歸模型參數(shù)中,,比較重要的有kernel參數(shù)和C參數(shù)。kernel參數(shù)用來選擇內(nèi)核算法,;C是誤差項(xiàng)的懲罰參數(shù),,取值一般為10的整數(shù)次冪,如 0.001,、0.1,、1000 等。通常,,C值越大,,對(duì)誤差項(xiàng)的懲罰越大,因此訓(xùn)練集測(cè)試時(shí)準(zhǔn)確率就越高,,但泛化能力越弱,;C值越小,對(duì)誤差項(xiàng)的懲罰越小,,因此容錯(cuò)能力越強(qiáng),,泛化能力也相對(duì)越強(qiáng)。
下面的例子以糖尿病數(shù)據(jù)集為例,,演示了支持向量機(jī)(SVM)回歸模型中不同的C參數(shù)對(duì)回歸結(jié)果的影響,。糖尿病數(shù)據(jù)集收集了442 例糖尿病患者的10 個(gè)指標(biāo)(年齡、性別,、體重指數(shù),、平均血壓和6 個(gè)血清測(cè)量值),標(biāo)簽是一年后疾病進(jìn)展的定量測(cè)值,。需要特別指出,,糖尿病數(shù)據(jù)集并不適用于SVM算法,此處僅是為了演示參數(shù)選擇如何影響訓(xùn)練結(jié)果,。
>>> from sklearn.datasets import load_diabetes
>>> from sklearn.model_selection import train_test_split as tsplit
>>> from sklearn.svm import SVR
>>> from sklearn import metrics
>>> X, y = load_diabetes(return_X_y=True)
>>> X.shape, y.shape, y.dtype
((442, 10), (442,), dtype('float64'))
>>> X_train, X_test, y_train, y_test = tsplit(X, y, test_size=0.02)
>>> svr_1 = SVR(kernel='rbf', C=0.1) # 實(shí)例化SVR模型,,rbf核函數(shù),C=0.1
>>> svr_2 = SVR(kernel='rbf', C=100) # 實(shí)例化SVR模型,,rbf核函數(shù),,C=100
>>> svr_1.fit(X_train, y_train) # 模型訓(xùn)練
SVR(C=0.1)
>>> svr_2.fit(X_train, y_train) # 模型訓(xùn)練
SVR(C=100)
>>> z_1 = svr_1.predict(X_test) # 模型預(yù)測(cè)
>>> z_2 = svr_2.predict(X_test) # 模型預(yù)測(cè)
>>> y_test # 這是測(cè)試集的實(shí)際值
array([ 49., 317., 84., 181., 281., 198., 84., 52., 129.])
>>> z_1 # 這是C=0.1的預(yù)測(cè)值,,偏差很大
array([138.10720127, 142.1545034 , 141.25165838, 142.28652449,
143.19648143, 143.24670732, 137.57932272, 140.51891989,
143.24486911])
>>> z_2 # 這是C=100的預(yù)測(cè)值,偏差明顯變小
array([ 54.38891948, 264.1433666 , 169.71195204, 177.28782561,
283.65199575, 196.53405477, 61.31486045, 199.30275061,
184.94923477])
>>> metrics.mean_squared_error(y_test, z_1) # C=0.01的均方誤差
8464.946517460194
>>> metrics.mean_squared_error(y_test, z_2) # C=100的均方誤差
3948.37754995066
>>> metrics.r2_score(y_test, z_1) # C=0.01的復(fù)相關(guān)系數(shù)
0.013199351909129464
>>> metrics.r2_score(y_test, z_2) # C=100的復(fù)相關(guān)系數(shù)
0.5397181166871942
>>> metrics.median_absolute_error(y_test, z_1) # C=0.01的中位數(shù)絕對(duì)誤差
57.25165837797314
>>> metrics.median_absolute_error(y_test, z_2) # C=100的中位數(shù)絕對(duì)誤差
22.68513954888364
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
18. 隨機(jī)森林是將多棵分類決策樹或者回歸決策樹集成在一起的算法,,是機(jī)器學(xué)習(xí)的一個(gè)分支——集成學(xué)習(xí)的方法,。
以隨機(jī)森林分類為例,隨機(jī)森林包含的每棵決策樹都是一個(gè)分類模型,,對(duì)于一個(gè)輸入樣本,,每個(gè)分類模型都會(huì)產(chǎn)生一個(gè)分類結(jié)果,類似投票表決,。隨機(jī)森林集成了所有的投票分類結(jié)果,,并將被投票次數(shù)最多的類別指定為最終的輸出類別。隨機(jī)森林每棵決策樹的訓(xùn)練樣本都是隨機(jī)的,,決策樹中訓(xùn)練集的特征列也是隨機(jī)選擇確定的。正是因?yàn)檫@兩個(gè)隨機(jī)性的存在,,使得隨機(jī)森林不容易陷入過擬合,,并且具有很好的抗噪能力。
考慮到隨機(jī)森林的每一棵決策樹中訓(xùn)練集的特征列是隨機(jī)選擇確定的,,更適合處理具有多特征列的數(shù)據(jù),,這里選擇 Scikit-learn內(nèi)置的威斯康星州乳腺癌數(shù)據(jù)集來演示隨機(jī)森林分類模型的使用。該數(shù)據(jù)集有 569 個(gè)乳腺癌樣本,,每個(gè)樣本包含半徑,、紋理、周長,、面積,、是否平滑、是否緊湊,、是否凹凸等 30 個(gè)特征列,。
>>> from sklearn.datasets import load_breast_cancer # 導(dǎo)入數(shù)據(jù)加載函數(shù)
>>> from sklearn.tree import DecisionTreeClassifier # 導(dǎo)入隨機(jī)樹
>>> from sklearn.ensemble import RandomForestClassifier # 導(dǎo)入隨機(jī)森林
>>> from sklearn.model_selection import cross_val_score # 導(dǎo)入交叉驗(yàn)證
>>> ds = load_breast_cancer() # 加載威斯康星州乳腺癌數(shù)據(jù)集
>>> ds.data.shape # 569個(gè)乳腺癌樣本,每個(gè)樣本包含30個(gè)特征
(569, 30)
>>> dtc = DecisionTreeClassifier() # 實(shí)例化決策樹分類模型
>>> rfc = RandomForestClassifier() # 實(shí)例化隨機(jī)森林分類模型
>>> dtc_scroe = cross_val_score(dtc, ds.data, ds.target, cv=10) # 交叉驗(yàn)證
>>> dtc_scroe # 決策樹分類模型交叉驗(yàn)證10次的結(jié)果
array([0.92982456, 0.85964912, 0.92982456, 0.89473684, 0.92982456,
0.89473684, 0.87719298, 0.94736842, 0.92982456, 0.92857143])
>>> dtc_scroe.mean() # 決策樹分類模型交叉驗(yàn)證10次的平均精度
0.9121553884711779
>>> rfc_scroe = cross_val_score(rfc, ds.data, ds.target, cv=10) # 交叉驗(yàn)證
>>> rfc_scroe # 隨機(jī)森林分類模型交叉驗(yàn)證10次的結(jié)果
array([0.98245614, 0.89473684, 0.94736842, 0.94736842, 0.98245614,
0.98245614, 0.94736842, 0.98245614, 0.94736842, 1. ])
>>> rfc_scroe.mean()# 隨機(jī)森林分類模型交叉驗(yàn)證10次的平均精度
0.9614035087719298
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
上面的代碼使用了交叉驗(yàn)證法,,其原理是將樣本分成n份,,每次用其中的n-1份作訓(xùn)練集,剩余1份作測(cè)試集,,訓(xùn)練n次,,返回每次的訓(xùn)練結(jié)果。結(jié)果顯示,,同樣交叉驗(yàn)證10次,,96%對(duì)91%,隨機(jī)森林的分類準(zhǔn)確率明顯高于隨機(jī)樹,。
19. 基于質(zhì)心的聚類,,無論是k均值聚類還是均值漂移聚類,,其局限性都是顯而易見的:無法處理細(xì)長條、環(huán)形或者交叉的不規(guī)則的樣本分布,。
k均值(k-means)聚類通常被視為聚類的“入門算法”,,其算法原理非常簡單。首先從X數(shù)據(jù)集中選擇k個(gè)樣本作為質(zhì)心,,然后重復(fù)以下兩個(gè)步驟來更新質(zhì)心,,直到質(zhì)心不再顯著移動(dòng)為止:第一步將每個(gè)樣本分配到距離最近的質(zhì)心,第二步根據(jù)每個(gè)質(zhì)心所有樣本的平均值來創(chuàng)建新的質(zhì)心,。
基于質(zhì)心的聚類是通過把樣本分離成多個(gè)具有相同方差的類的方式來聚集數(shù)據(jù)的,,因此總是希望簇是凸(convex)的和各向同性(isotropic)的,但這并非總是能夠得到滿足,。例如,,對(duì)細(xì)長、環(huán)形或交叉等具有不規(guī)則形狀的簇,,其聚類效果不佳,。
>>> from sklearn import datasets as dss # 導(dǎo)入樣本生成器
>>> from sklearn.cluster import KMeans # 從聚類子模塊導(dǎo)入聚類模型
>>> import matplotlib.pyplot as plt
>>> plt.rcParams['font.sans-serif'] = ['FangSong']
>>> plt.rcParams['axes.unicode_minus'] = False
>>> X_blob, y_blob = dss.make_blobs(n_samples=[300,400,300], n_features=2)
>>> X_circle, y_circle = dss.make_circles(n_samples=1000, noise=0.05, factor=0.5)
>>> X_moon, y_moon = dss.make_moons(n_samples=1000, noise=0.05)
>>> y_blob_pred = KMeans(init='k-means++', n_clusters=3).fit_predict(X_blob)
>>> y_circle_pred = KMeans(init='k-means++', n_clusters=2).fit_predict(X_circle)
>>> y_moon_pred = KMeans(init='k-means++', n_clusters=2).fit_predict(X_moon)
>>> plt.subplot(131)
<matplotlib.axes._subplots.AxesSubplot object at 0x00000180AFDECB88>
>>> plt.title('團(tuán)狀簇')
Text(0.5, 1.0, '團(tuán)狀簇')
>>> plt.scatter(X_blob[:,0], X_blob[:,1], c=y_blob_pred)
<matplotlib.collections.PathCollection object at 0x00000180C495DF08>
>>> plt.subplot(132)
<matplotlib.axes._subplots.AxesSubplot object at 0x00000180C493FA08>
>>> plt.title('環(huán)狀簇')
Text(0.5, 1.0, '環(huán)狀簇')
>>> plt.scatter(X_circle[:,0], X_circle[:,1], c=y_circle_pred)
<matplotlib.collections.PathCollection object at 0x00000180C499B888>
>>> plt.subplot(133)
<matplotlib.axes._subplots.AxesSubplot object at 0x00000180C4981188>
>>> plt.title('新月簇')
Text(0.5, 1.0, '新月簇')
>>> plt.scatter(X_moon[:,0], X_moon[:,1], c=y_moon_pred)
<matplotlib.collections.PathCollection object at 0x00000180C49DD1C8>
>>> plt.show()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
上面的代碼首先使用樣本生成器生成團(tuán)狀簇、環(huán)狀簇和新月簇,,然后使用k均值聚類分別對(duì)其實(shí)施聚類操作,。結(jié)果表明,k均值聚類僅適用于團(tuán)狀簇,,對(duì)于環(huán)狀簇,、新月簇?zé)o能為力。聚類的最終效果如下圖所示,。
20. 基于密度的空間聚類具有更好的適應(yīng)性,,可以發(fā)現(xiàn)任何形狀的簇。
基于密度的空間聚類,,全稱是基于密度的帶噪聲的空間聚類應(yīng)用算法(英文簡寫為DBSCAN),。該聚類算法將簇視為被低密度區(qū)域分隔的高密度區(qū)域,這與K均值聚類假設(shè)簇總是凸的這一條件完全不同,,因此可以發(fā)現(xiàn)任何形狀的簇,。
DBSCAN類是Scikit-learn聚類子模塊cluster提供的基于密度的空間聚類算法,該類有兩個(gè)重要參數(shù)eps和min_samples,。要理解DBSCAN 類的參數(shù),,需要先理解核心樣本。如果一個(gè)樣本的eps距離范圍內(nèi)存在不少于min_sample個(gè)樣本(包括這個(gè)樣本),,則該樣本稱為核心樣本,。可見,參數(shù)eps和min_samples 定義了簇的稠密度,。
>>> from sklearn import datasets as dss
>>> from sklearn.cluster import DBSCAN
>>> import matplotlib.pyplot as plt
>>> plt.rcParams['font.sans-serif'] = ['FangSong']
>>> plt.rcParams['axes.unicode_minus'] = False
>>> X, y = dss.make_moons(n_samples=1000, noise=0.05)
>>> dbs_1 = DBSCAN() # 默認(rèn)核心樣本半徑0.5,,核心樣本鄰居5個(gè)
>>> dbs_2 = DBSCAN(eps=0.2) # 核心樣本半徑0.2,核心樣本鄰居5個(gè)
>>> dbs_3 = DBSCAN(eps=0.1) # 核心樣本半徑0.1,,核心樣本鄰居5個(gè)
>>> dbs_1.fit(X)
DBSCAN(algorithm='auto', eps=0.5, leaf_size=30, metric='euclidean',
metric_params=None, min_samples=5, n_jobs=None, p=None)
>>> dbs_2.fit(X)
DBSCAN(algorithm='auto', eps=0.2, leaf_size=30, metric='euclidean',
metric_params=None, min_samples=5, n_jobs=None, p=None)
>>> dbs_3.fit(X)
DBSCAN(algorithm='auto', eps=0.1, leaf_size=30, metric='euclidean',
metric_params=None, min_samples=5, n_jobs=None, p=None)
>>> plt.subplot(131)
<matplotlib.axes._subplots.AxesSubplot object at 0x00000180C4C5D708>
>>> plt.title('eps=0.5')
Text(0.5, 1.0, 'eps=0.5')
>>> plt.scatter(X[:,0], X[:,1], c=dbs_1.labels_)
<matplotlib.collections.PathCollection object at 0x00000180C4C46348>
>>> plt.subplot(132)
<matplotlib.axes._subplots.AxesSubplot object at 0x00000180C4C462C8>
>>> plt.title('eps=0.2')
Text(0.5, 1.0, 'eps=0.2')
>>> plt.scatter(X[:,0], X[:,1], c=dbs_2.labels_)
<matplotlib.collections.PathCollection object at 0x00000180C49FC8C8>
>>> plt.subplot(133)
<matplotlib.axes._subplots.AxesSubplot object at 0x00000180C49FCC08>
>>> plt.title('eps=0.1')
Text(0.5, 1.0, 'eps=0.1')
>>> plt.scatter(X[:,0], X[:,1], c=dbs_3.labels_)
<matplotlib.collections.PathCollection object at 0x00000180C49FC4C8>
>>> plt.show()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
以上代碼使用DBSCAN,,配合適當(dāng)?shù)膮?shù),最終將新月數(shù)據(jù)集的上弦月和下弦月分開,,效果如下圖所示,。
21. 主成分分析(PCA)是一種統(tǒng)計(jì)方法,也是最常用的降維方法,。
主成分分析通過正交變換將一組可能存在相關(guān)性的變量轉(zhuǎn)換為一組線性不相關(guān)的變量,,轉(zhuǎn)換后的這組變量叫主成分。顯然,,主成分分析的降維并不是簡單地丟掉一些特征,,而是通過正交變換,把具有相關(guān)性的高維變量合并為線性無關(guān)的低維變量,,從而達(dá)到降維的目的,。
以下代碼以鳶尾花數(shù)據(jù)集為例演示了如何使用 PCA 類來實(shí)現(xiàn)主成分分析和降維。已知鳶尾花數(shù)據(jù)集有 4 個(gè)特征列,,分別是花萼的長度、寬度和花瓣的長度,、寬度,。
>>> from sklearn import datasets as dss
>>> from sklearn.decomposition import PCA
>>> ds = dss.load_iris()
>>> ds.data.shape # 150個(gè)樣本,4個(gè)特征維
(150, 4)
>>> m = PCA() # 使用默認(rèn)參數(shù)實(shí)例化PCA類,,n_components=None
>>> m.fit(ds.data)
PCA(copy=True, iterated_power='auto', n_components=None, random_state=None,
svd_solver='auto', tol=0.0, whiten=False)
>>> m.explained_variance_ # 正交變換后各成分的方差值
array([4.22824171, 0.24267075, 0.0782095 , 0.02383509])
>>> m.explained_variance_ratio_ # 正交變換后各成分的方差值占總方差值的比例
array([0.92461872, 0.05306648, 0.01710261, 0.00521218])
對(duì)鳶尾花數(shù)據(jù)集的主成分分析結(jié)果顯示:存在一個(gè)明顯的成分,,其方差值占總方差值的比例超過92% ;存在一個(gè)方差值很小的成分,,其方差值占總方差值的比例只有0.52% ,;前兩個(gè)成分貢獻(xiàn)的方差占比超過97.7%,數(shù)據(jù)集特征列可以從4個(gè)降至2個(gè)而不至于損失太多有效信息,。
>>> m = PCA(n_components=0.97)
>>> m.fit(ds.data)
PCA(copy=True, iterated_power='auto', n_components=0.97, random_state=None,
svd_solver='auto', tol=0.0, whiten=False)
>>> m.explained_variance_
array([4.22824171, 0.24267075])
>>> m.explained_variance_ratio_
array([0.92461872, 0.05306648])
>>> d = m.transform(ds.data)
>>> d.shape
(150, 2)
指定參數(shù)n_components不小于0.97,,即可得到原數(shù)據(jù)集的降維結(jié)果:同樣是150個(gè)樣本,但特征列只有2個(gè),。若將2個(gè)特征列視為平面直角坐標(biāo)系中的x和y坐標(biāo),,就可以直觀地畫出全部樣本數(shù)據(jù)。
>>> import matplotlib.pyplot as plt
>>> plt.scatter(d[:,0], d[:,1], c=ds.target)
<matplotlib.collections.PathCollection object at 0x0000016FBF243CC8>
>>> plt.show()
下圖顯示只用2個(gè)特征維也基本可以分辨出鳶尾花的3種類型,。
|