前言
由于實(shí)驗(yàn)原因,準(zhǔn)備入坑 python 機(jī)器學(xué)習(xí),而 python 機(jī)器學(xué)習(xí)常用的包就是 scikit-learn ,準(zhǔn)備先了解一下這個(gè)工具。在這里搜了有 scikit-learn 關(guān)鍵字的書(shū),找到了3本:《Learning scikit-learn: Machine Learning in Python》《Mastering Machine Learning With scikit-learn》《scikit-learn Cookbook》,第一本是2013年出版,后兩本是2014年出版,都下下來(lái)看了下目錄和頁(yè)數(shù),第一本只有118頁(yè),后兩本分別為238頁(yè)和214頁(yè),考慮到希望能夠盡快看完一本,對(duì)整體 sklearn 有一定了解,最后選擇了第一本進(jìn)行閱讀。
這本書(shū)上周看完了,但是筆記還沒(méi)有整理,趁著寫(xiě)這個(gè)博客,重新復(fù)習(xí)一遍,加強(qiáng)理解,鞏固記憶,如果有說(shuō)錯(cuò)的地方,敬請(qǐng)指出。
本書(shū)概況
一共分為4個(gè)大章節(jié):第一章是對(duì)機(jī)器學(xué)習(xí)的一個(gè)入門(mén)介紹;第二章和第三章分別介紹了監(jiān)督學(xué)習(xí)和無(wú)監(jiān)督學(xué)習(xí)在 sklearn 中的幾種算法實(shí)現(xiàn),每個(gè)算法用一個(gè)例子進(jìn)行分別介紹,個(gè)人覺(jué)得很不錯(cuò);第四章是對(duì)一些前面提到的高級(jí)技巧進(jìn)行分類闡述,如果說(shuō)前面的算法實(shí)現(xiàn)只是一個(gè)基本模型構(gòu)建,第四章講的內(nèi)容,能夠讓模型進(jìn)一步優(yōu)化,達(dá)到如虎添翼的效果。
私以為這本書(shū)寫(xiě)得很不錯(cuò),雖然頁(yè)數(shù)不多,講的內(nèi)容也不是特別深入,但是對(duì)于一個(gè)機(jī)器學(xué)習(xí)小白來(lái)說(shuō),是一本很不錯(cuò)的入門(mén)書(shū)籍。看完這本書(shū),能夠?qū)κ褂脵C(jī)器學(xué)習(xí)方法解決問(wèn)題樹(shù)立一個(gè)比較系統(tǒng)的思路和流程,而且由于頁(yè)數(shù)不多,看完一本書(shū)基本也就花了大概一天半的時(shí)間,如果英語(yǔ)or有一定機(jī)器學(xué)習(xí)基礎(chǔ)可能會(huì)更快。
但是這本書(shū)也有一個(gè)非常嚴(yán)重的缺陷——太老了。里面的代碼都是用 python2 寫(xiě)的,而且一些函數(shù)接口,最新的 sklearn 快要不支持了,還有一些使用的數(shù)據(jù)集,鏈接下載的時(shí)候也遇到了一些問(wèn)題,還有一些 typos 錯(cuò)誤。這個(gè)讀書(shū)筆記邊整理的時(shí)候,也就邊在對(duì)一些代碼使用 python3 進(jìn)行實(shí)現(xiàn)。
第一章讀書(shū)筆記
前言
大多數(shù)用機(jī)器學(xué)習(xí)解決問(wèn)題的過(guò)程可以簡(jiǎn)化成3個(gè)步驟:
- 給一個(gè)任務(wù)T
- 需要學(xué)習(xí)一些經(jīng)驗(yàn)E(藏在數(shù)據(jù)集里)
- 有一個(gè)性能指標(biāo)P(用來(lái)評(píng)估任務(wù)完成得怎么樣)
安裝
Scikit-learn 需要提前安裝 Numpy 和 Scipy,參照后文的說(shuō)法,最好還要安裝 Pandas 和 Matplotlib。
windows 下建議直接安裝 Anaconda,不錯(cuò)的集成工具,包含 Jupyter Notebook 和 Spyder,以及幾乎所有的依賴包,如果沒(méi)有再安裝即可。
linux 下就直接安裝 python 的虛擬環(huán)境,利用 pip 包管理工具一個(gè)一個(gè)進(jìn)行安裝,可以看這里,總結(jié)了一個(gè)非常簡(jiǎn)要的linux下搭建python機(jī)器學(xué)習(xí)環(huán)境的相關(guān)命令。
Mac 下也有類似的工具 MacPorts 和 HomeBrew。
數(shù)據(jù)集
sklearn 包含一些公開(kāi)知名的數(shù)據(jù)集,只要引入相關(guān)的數(shù)據(jù)集包就可以。
這里引入了 1936 年鳶尾花的那個(gè)數(shù)據(jù)集,試一下代碼(本文的代碼都是基于python2實(shí)現(xiàn)的,但這個(gè)筆記都把代碼轉(zhuǎn)化成了 python 3的實(shí)現(xiàn)形式,后文就不一一贅述了)。
from sklearn import datasets
iris = datasets.load_iris()
X_iris, Y_iris = iris.data, iris.target
print(X_iris.shape, Y_iris.shape)
print(X_iris[0],Y_iris[0])
(150, 4) (150,)
[ 5.1 3.5 1.4 0.2] 0
shape表示矩陣的維度,行x列。
Numpy 會(huì)把數(shù)據(jù)按照類似 R 的數(shù)據(jù)框 or 矩陣的格式讀取進(jìn)來(lái),數(shù)據(jù)一行表示一個(gè)實(shí)例,一列表示一個(gè)特征,基本后續(xù)的算法輸入也是這種格式。
線性分類器模型構(gòu)建、評(píng)估、可視化展示
這里舉了個(gè)線性的例子,利用上面的數(shù)據(jù)集,用花萼的寬度和長(zhǎng)度作為特征。隨機(jī)選擇了75%的作為訓(xùn)練集,剩下的作為測(cè)試集,來(lái)預(yù)測(cè)花的類別。
#數(shù)據(jù)集初步處理,構(gòu)造訓(xùn)練集和驗(yàn)證集
from sklearn.cross_validation import train_test_split
from sklearn import preprocessing
X, y = X_iris[:,:2], Y_iris
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=33)
print(X_train.shape, y_train.shape)
(112, 2) (112,)
#對(duì)數(shù)據(jù)進(jìn)行歸一化
scaler = preprocessing.StandardScaler().fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
print(scaler)
StandardScaler(copy=True, with_mean=True, with_std=True)
#用橫坐標(biāo)為花萼長(zhǎng)度,縱坐標(biāo)為花萼寬度作圖,不同種類的花用不同顏色表示,對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行可視化展示,可以指導(dǎo)后續(xù)的模型選擇和建立
%matplotlib inline #這句話是在 jupyter 中展示圖片必須寫(xiě)的命令,否則圖片顯示不出來(lái)
import matplotlib.pyplot as plt
colors = ['red','greenyellow','blue']
for i in range(len(colors)):
xs = X_train[:,0][y_train == i]
ys = X_train[:,1][y_train == i]
plt.scatter(xs, ys, c=colors[i])
plt.legend(iris.target_names)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
Text(0,0.5,'Sepal width')

#訓(xùn)練模型
from sklearn.linear_model import SGDClassifier
clf = SGDClassifier()
clf.fit(X_train, y_train)
print(clf.coef_)
print(clf.intercept_)
[[-38.1319044 4.82101696]
[ 0.74533565 -12.21001281]
[ 10.94046262 -9.35131933]]
[-11.9120138 -2.94008476 -17.30968766]
#開(kāi)始作圖
x_min, x_max = X_train[:,0].min() - .5, X_train[:,0].max() + .5
y_min, y_max = X_train[:,1].min() - .5, X_train[:,1].max() + .5
import numpy as np
xs = np.arange(x_min, x_max, 0.5)
fig, axes = plt.subplots(1,3)
fig.set_size_inches(10,6)
for i in [0, 1, 2]:
axes[i].set_aspect('equal')
axes[i].set_title('Class' + str(i) + ' versus the rest')
axes[i].set_xlabel('Sepal length')
axes[i].set_ylabel('Sepal width')
axes[i].set_xlim(x_min, x_max)
axes[i].set_ylim(y_min, y_max)
plt.sca(axes[i])
plt.scatter(X_train[:,0], X_train[:, 1], c=y_train, cmap=plt.cm.prism)
ys = (-clf.intercept_[i] - xs * clf.coef_[i, 0]) /clf.coef_[i, 1]
plt.plot(xs, ys, hold=True)

給一個(gè)實(shí)例,進(jìn)行預(yù)測(cè)(訓(xùn)練集和測(cè)試集都要做同樣的數(shù)據(jù)處理工作,如正則化等):
#預(yù)測(cè)
print(clf.predict(scaler.transform([[4.7, 3.1]])))
[0]
print(clf.decision_function(scaler.transform([[4.7, 3.1]])))
[[ 36.57038398 -5.03172599 -31.97218356]]
模型構(gòu)建完畢,但是還需要評(píng)定性能:
#在訓(xùn)練集上的性能評(píng)估
from sklearn import metrics
y_train_pred = clf.predict(X_train)
print(metrics.accuracy_score(y_train, y_train_pred))
0.776785714286
#在測(cè)試集上的性能評(píng)估
y_pred = clf.predict(X_test)
print(metrics.accuracy_score(y_test, y_pred))
0.526315789474
算法在訓(xùn)練集上的效果肯定比測(cè)試集上要好,所以是一個(gè)檢測(cè)算法性能上限的方法。
F1值的計(jì)算是一個(gè)結(jié)合精確率和召回率的評(píng)估指標(biāo),值為 2* presion * recall/(precision + recall)
#整體的分析報(bào)告
print(metrics.classification_report(y_test, y_pred, target_names=iris.target_names))
precision recall f1-score support
setosa 1.00 1.00 1.00 8
versicolor 0.38 1.00 0.55 11
virginica 1.00 0.05 0.10 19
avg / total 0.82 0.53 0.42 38
#看混淆矩陣,可以看出到底是哪些判錯(cuò)影響了性能
print(metrics.confusion_matrix(y_test, y_pred))
[[ 8 0 0]
[ 0 11 0]
[ 0 18 1]]
常用的交叉驗(yàn)證方法來(lái)評(píng)估模型:
#采用5折交叉驗(yàn)證的方法對(duì)模型進(jìn)行評(píng)估
from sklearn.cross_validation import cross_val_score, KFold
from sklearn.pipeline import Pipeline
clf = Pipeline([
('scaler', preprocessing.StandardScaler()),
('linear_model', SGDClassifier())
])
cv = KFold(X.shape[0], 5, shuffle=True, random_state=33)
scores = cross_val_score(clf, X, y, cv=cv)
print(scores)
[ 0.66666667 0.63333333 0.6 0.83333333 0.86666667]
#計(jì)算5折的平均分值,即為模型的性能
from scipy.stats import sem
def mean_score(scores):
return ("Mean score: {0:.3f} (+/-{1:.3f})").format(np.mean(scores), sem(scores))
print(mean_score(scores))
Mean score: 0.720 (+/-0.054)
英語(yǔ)生詞總結(jié)
sepal:花萼;
petal:花瓣;
setosa:刺芒野古草;
versicolor:雜色的;
virginica:維爾吉尼卡;
harmonic:和諧的,和聲的;
intuitively:直觀的,直覺(jué)的;
adequately:充分的,足夠的,適當(dāng)?shù)模?br>
instantiation:實(shí)例化;
annotated:有注釋的,帶注釋的。
小結(jié)
整體來(lái)說(shuō),第一章用一個(gè)簡(jiǎn)單的線性分類器的例子,走了一遍簡(jiǎn)要的機(jī)器學(xué)習(xí)的流程,介紹了一些相關(guān)概念,能夠?qū)C(jī)器學(xué)習(xí)有一個(gè)簡(jiǎn)要的認(rèn)識(shí)。
機(jī)器學(xué)習(xí)的一些分類:
- 監(jiān)督學(xué)習(xí)(分類)
- 回歸(其實(shí)也是一種分類,只不過(guò)不是離散型的類別,而是連續(xù)型的數(shù)字)
- 非監(jiān)督學(xué)習(xí)(聚類)
機(jī)器學(xué)習(xí)的一些重要概念:
- 維數(shù)爆炸
- 過(guò)擬合/欠擬合
- 泛化能力
- 偏差和方差(其實(shí)和上面的過(guò)擬合和欠擬合是對(duì)應(yīng)的)
- 線性分類器高偏差低方差,KNN低偏差高方差,偏差高對(duì)應(yīng)欠擬合,方差高對(duì)應(yīng)過(guò)擬合
- 特征標(biāo)準(zhǔn)化和歸一化(數(shù)據(jù)的處理)
- 特征工程(特征提取和特征選擇)
- 模型選擇(模型的參數(shù)設(shè)置)