導(dǎo)讀:機(jī)器學(xué)習(xí)是一門復(fù)雜的交叉學(xué)科。針對普通程序員來講,里面有太多的數(shù)學(xué)概念振劳,我嘗試機(jī)器學(xué)習(xí)斷斷續(xù)續(xù)約半年,公式和概念這兩只攔路虎多次擋道油狂,再加上自己數(shù)學(xué)太渣历恐,毫無懸念的多次敗下陣來寸癌。
最近,我買了幾門機(jī)器學(xué)習(xí)的視頻課程弱贼,硬著頭皮從概率蒸苇、微積分、統(tǒng)計(jì)分析哮洽、矩陣填渠、凸優(yōu)化開始看起,逐漸有了點(diǎn)兒感覺鸟辅,雖有很多還是看不懂氛什,但不至于看睡著。然后結(jié)合趙志勇的《Python機(jī)器學(xué)習(xí)算法》這本書匪凉,漸漸的也能上手了枪眉。如果你不是算法工程師,那就選擇看視頻了解概念再层,在寫代碼中使用成熟的機(jī)器學(xué)習(xí)算法包贸铜。
本文翻譯自scikit-learn v0.19.0的tutorial,希望能讓不熟悉機(jī)器學(xué)習(xí)的同學(xué)在代碼層面上有個直觀的了解聂受。
雖然scikit-learn幫我們封裝了很多算法蒿秦,可以黑盒調(diào)用,但是作為一個程序員蛋济,一定要清楚棍鳖,會調(diào)包和只會調(diào)包是有很大的區(qū)別。
scikit-learn是Python(>= 2.7 or >= 3.3)中的機(jī)器學(xué)習(xí)包(庫)碗旅,其構(gòu)建在NumPy(>= 1.8.2)渡处, SciPy(>= 0.13.3)和 matplotlib之上。采用BSD授權(quán)祟辟,可放心的用在商業(yè)應(yīng)用中医瘫。
- 進(jìn)行數(shù)據(jù)挖掘和數(shù)據(jù)分析的簡單而高效的工具
- 任何人都可使用,可在多種場景/應(yīng)用上下文中重復(fù)使用
- 基于NumPy旧困,SciPy和matplotlib構(gòu)建
- 開放源代碼醇份,可用于商業(yè)用途-采用BSD協(xié)議
使用pip install -U scikit-learn
命令在線安裝scikit-learn包。
安裝完畢后吼具,執(zhí)行以下示例被芳,驗(yàn)證安裝是否正確。
from sklearn import datasets
import matplotlib.pyplot as plt
#加載數(shù)字?jǐn)?shù)據(jù)集
digits = datasets.load_digits()
#展示第一個數(shù)字
plt.figure(1, figsize=(3, 3))
plt.imshow(digits.images[-1], cmap=plt.cm.gray_r, interpolation='nearest')
plt.show()
在Windows 10上安裝完成后馍悟,sklearn版本顯示為0.0畔濒,原因未知,但是能正常使用锣咒。
本教程使用版本:v0.19.0
原文:scikit-learn tutorial
本文參考了Tacey Wong在cnblogs上的譯文侵状,針對最新版本做了調(diào)整赞弥,文中代碼全部經(jīng)過驗(yàn)證。
該章節(jié)趣兄,我們將介紹貫穿scikit-learn使用中的“ 機(jī)器學(xué)習(xí)(Machine Learning) ”這個詞匯绽左,并給出一些簡單的學(xué)習(xí)示例。
0. 前言
機(jī)器學(xué)習(xí)的幾個關(guān)鍵主題有:分類艇潭、回歸拼窥、聚類、降維和預(yù)處理蹋凝。
0.1 分類
分類算法鲁纠,在實(shí)際工作中有很多中應(yīng)用場景,如
- 客戶標(biāo)簽:描述客戶的風(fēng)險(xiǎn)等級程度鳍寂,高改含、中或低
- 欺詐評級:描述一筆交易的欺詐可能性,高迄汛、中或低
目的:識別一個對象屬于那一種類別
應(yīng)用:垃圾郵件檢測捍壤,圖像識別
算法:SVM(支持向量機(jī)),KNN(K近鄰)鞍爱,隨機(jī)森林
0.2 回歸
目的:預(yù)測與某個對象相關(guān)聯(lián)的連續(xù)值屬性
應(yīng)用:藥物反應(yīng)鹃觉,股票價(jià)格
算法:線性回歸,SVR(支持向量回歸)睹逃,ridge regression(嶺回歸)盗扇,LASSO回歸
0.3 聚類
目的:將相似的對象自動聚集到不同的集合中
應(yīng)用:顧客細(xì)分,分組試驗(yàn)結(jié)果
算法:K-Means唯卖,譜聚類粱玲,mean-shift中值移動
0.4 降維
降維打擊:請給我一片二向箔躬柬,清理用拜轨。
目的:降低隨機(jī)變量的數(shù)目
應(yīng)用:可視化,提高效率
算法:PCA(主成分分析)允青,特征選取橄碾,非負(fù)矩陣分解
0.5 預(yù)處理
目的:特征提取和正則化
應(yīng)用:轉(zhuǎn)換數(shù)據(jù)以便機(jī)器學(xué)習(xí)算法使用
模塊:預(yù)處理,特征提取
1. 機(jī)器學(xué)習(xí):問題設(shè)定
通常颠锉,一個學(xué)習(xí)問題是通過分析一些數(shù)據(jù)樣本來嘗試預(yù)測未知數(shù)據(jù)的屬性法牲。如果每一個樣本不僅僅是一個單獨(dú)的數(shù)字,比如一個多維的實(shí)例(multivariate data)琼掠,也就是說有著多個屬性特征拒垃。
我們可以把學(xué)習(xí)問題分成如下的幾個大類:
-
有監(jiān)督學(xué)習(xí),數(shù)據(jù)帶有我們要預(yù)測的屬性瓷蛙。這種問題主要有如下幾種:
- 分類: 樣例屬于兩類或多類悼瓮,我們想要從已經(jīng)帶有標(biāo)簽(分類結(jié)果戈毒,如好/壞)的數(shù)據(jù)中學(xué)習(xí)以預(yù)測未帶標(biāo)簽的數(shù)據(jù)。識別手寫數(shù)字就是一個分類問題横堡,這個問題的主要目標(biāo)就是把每一個輸出指派到一個有限的類別中的一類埋市。另一種思路去思考分類問題,其實(shí)分類問題是有監(jiān)督學(xué)習(xí)中的離散形式問題命贴。每一個都有一個有限的分類道宅。對于樣例提供的多個標(biāo)簽,我們要做的就是把未知類別的數(shù)據(jù)劃分到其中的一種胸蛛。
- 回歸:如果預(yù)期的輸出包含連續(xù)的變量污茵,那么這樣的任務(wù)叫做回歸。根據(jù)三文魚的年齡和重量預(yù)測其長度就是一個回歸的例子胚泌。
無監(jiān)督學(xué)習(xí)省咨,針對那些訓(xùn)練數(shù)據(jù)只包含輸入向量x但是不帶有目標(biāo)值的場景,機(jī)器學(xué)習(xí)的目標(biāo)就是根據(jù)數(shù)據(jù)發(fā)現(xiàn)樣本中相似的群組--聚類玷室,或者是在輸入空間中判定數(shù)據(jù)的分布--密度估計(jì)零蓉,或者把數(shù)據(jù)從高維空間轉(zhuǎn)換到低維空間以用于可視化。
訓(xùn)練集和測試集:機(jī)器學(xué)習(xí)是學(xué)習(xí)一些數(shù)據(jù)集的特征屬性并將其應(yīng)用于新的數(shù)據(jù)集穷缤。這就是為什么在機(jī)器學(xué)習(xí)過程中用來評估算法時(shí)敌蜂,一般會把手頭的數(shù)據(jù)分成兩部分。一部分我們稱之為訓(xùn)練集津肛,用以學(xué)習(xí)數(shù)據(jù)的特征屬性章喉。另外一部分我們稱之為測試集,用以檢驗(yàn)學(xué)習(xí)到的特征屬性身坐。
2. 加載樣本數(shù)據(jù)集
scikit-learn本身帶有一些標(biāo)準(zhǔn)數(shù)據(jù)集秸脱。比如用來分類的iris(鳶尾花)數(shù)據(jù)集、digits(手寫數(shù)字圖像)數(shù)據(jù)集部蛇;用來回歸的boston house price(波士頓房屋價(jià)格) 數(shù)據(jù)集摊唇。
接下來,我們我們從shell開啟一個Python解釋器并加載iris和digits兩個數(shù)據(jù)集涯鲁。本教程中的符號約定:$
表示操作系統(tǒng)(Linux)提示符巷查,>>>
表示Python解釋器提示符。
$ python
>>> from sklearn import datasets #從sklearn包中加載數(shù)據(jù)集模塊
>>> iris = datasets.load_iris() #加載鳶尾花數(shù)據(jù)集
>>> digits = datasets.load_digits() #加載數(shù)字圖像數(shù)據(jù)集
一個數(shù)據(jù)集是一個包含數(shù)據(jù)所有元數(shù)據(jù)的類字典對象抹腿。這個數(shù)據(jù)存儲(X)在 '.data'成員變量中岛请,是一個n_samples
乘n_features
的數(shù)組,行表示樣例警绩,列表示特征崇败。在有監(jiān)督學(xué)習(xí)問題中,一個或多個響應(yīng)變量(Y)存儲在‘.target’成員變量中肩祥。不同數(shù)據(jù)集的更多細(xì)節(jié)可以在sklearn文檔的專屬章節(jié)中找到后室。
例如微渠,對于digits數(shù)據(jù)集,digits.data
可以訪問用來對數(shù)字進(jìn)行分類的特征:
>>> print(digits.data)
[[ 0. 0. 5. ..., 0. 0. 0.]
[ 0. 0. 0. ..., 10. 0. 0.]
[ 0. 0. 0. ..., 16. 9. 0.]
...,
[ 0. 0. 1. ..., 6. 0. 0.]
[ 0. 0. 2. ..., 12. 0. 0.]
[ 0. 0. 10. ..., 12. 1. 0.]]
digits.target
就是數(shù)字?jǐn)?shù)據(jù)集中各樣例對應(yīng)的真實(shí)數(shù)字值咧擂。也就是我們的程序要學(xué)習(xí)的逞盆。
>>> digits.target
array([0, 1, 2, ..., 8, 9, 8])
數(shù)據(jù)數(shù)組的形狀
盡管原始數(shù)據(jù)也許有不同的形狀,但實(shí)際使用的數(shù)據(jù)通常是一個二維數(shù)組(n個樣例松申,n個特征)云芦。對于digits數(shù)據(jù)集,每一個原始的樣例是一張(8 x 8)的圖片贸桶,使用以下的數(shù)組進(jìn)行存染艘荨:digits.images[0] array([[ 0., 0., 5., 13., 9., 1., 0., 0.], [ 0., 0., 13., 15., 10., 15., 5., 0.], [ 0., 3., 15., 2., 0., 11., 8., 0.], [ 0., 4., 12., 0., 0., 8., 8., 0.], [ 0., 5., 8., 0., 0., 9., 8., 0.], [ 0., 4., 11., 0., 1., 12., 7., 0.], [ 0., 2., 14., 5., 10., 12., 0., 0.], [ 0., 0., 6., 13., 10., 0., 0., 0.]])
3. 學(xué)習(xí)和預(yù)測
對于數(shù)字?jǐn)?shù)據(jù)集(digits dataset),任務(wù)是預(yù)測一張圖片中的數(shù)字是什么皇筛。數(shù)字?jǐn)?shù)據(jù)集提供了0-9每一個數(shù)字的可能樣例琉历,在此之上,我們選擇一個算法(estimator)對其進(jìn)行擬合分類水醋。
在scikit-learn中旗笔,用以分類的擬合(評估)函數(shù)是一個Python對象,具體有fit(X,y)和predic(T)兩種成員方法拄踪。
其中一個擬合(評估)樣例是sklearn.svmSVC類蝇恶,它實(shí)現(xiàn)了支持向量分類(SVC)。一個擬合(評估)函數(shù)的構(gòu)造函數(shù)需要模型的參數(shù)惶桐,但是時(shí)間問題撮弧,我們將會把這個擬合(評估)函數(shù)作為一個黑箱:
>>> from sklearn import svm
>>> clf = svm.SVC(gamma=0.001, C=100.)
選擇模型參數(shù)
在這個例子中,我們手動設(shè)定γ值姚糊。通常也可以使用網(wǎng)格搜索(grid search)
和交叉驗(yàn)證(cross validation)
等工具贿衍,自動找到較合適的參數(shù)值。
我們調(diào)用擬合(估測)實(shí)例clf作為我們的分類器救恨。它現(xiàn)在必須要擬合模型贸辈,也就是說,它必須要學(xué)習(xí)模型忿薇。這可以通過把我們的訓(xùn)練集傳遞給fit方法裙椭。作為訓(xùn)練集躏哩,我們使用除最后一組的所有圖像署浩。我們可以通過Python的分片語法[:-1]
來選取訓(xùn)練集,這個操作將產(chǎn)生一個新數(shù)組扫尺,這個數(shù)組包含digits.data中除最后一組數(shù)據(jù)的所有實(shí)例筋栋。
>>> clf.fit(digits.data[:-1], digits.target[:-1])
SVC(C=100.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma=0.001, kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
現(xiàn)在你就可以預(yù)測新的數(shù)值了。我們可以讓這個分類器預(yù)測沒有作為訓(xùn)練數(shù)據(jù)使用的最后一張圖像是什么數(shù)字正驻。
>>> clf.predict(digits.data[-1:])
array([8])
相應(yīng)的圖片如下圖:
正如你所看到的弊攘,這是一個很有挑戰(zhàn)的任務(wù):這張圖片的分辨率很低抢腐。你同意分類器給出的答案嗎?
這個分類問題的完整示例在這里:識別手寫數(shù)字襟交,你可以學(xué)習(xí)并運(yùn)行它迈倍。
4. 模型持久化
可以使用Python的自帶模塊——pickle來保存scikit中的模型:
>>> from sklearn import svm
>>> from sklearn import datasets
>>> clf = svm.SVC()
>>> iris = datasets.load_iris()
>>> X, y = iris.data, iris.target
>>> clf.fit(X, y)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
>>> import pickle
>>> s = pickle.dumps(clf)
>>> clf2 = pickle.loads(s)
>>> clf2.predict(X[0:1])
array([0])
>>> y[0]
0
對于scikit,也許使用joblib的pickle替代--(joblib.dump&joblib.load)更有趣捣域。因?yàn)樗谔幚泶髷?shù)據(jù)時(shí)更高效啼染。但是遺憾的是它只能把數(shù)據(jù)持久化到硬盤而不內(nèi)存。
>>> from sklearn.externals import joblib
>>> joblib.dump(clf, 'filename.pkl')
之后焕梅,你就可以重新加載這個持久化后的模型(也能在另一個Python進(jìn)程中使用)迹鹅,如下:
>>> clf = joblib.load('filename.pkl')
注意:
joblib.dump和 joblib.load函數(shù)除了可以接受文件名參數(shù)外,也可接受文件類的對象贞言。更多有關(guān)Joblib持久化數(shù)據(jù)的信息斜棚,請參考這里。
可以返回一個文件名的列表该窗,每一個numpy數(shù)組元素包含一個clf在文件系統(tǒng)上的名字弟蚀,在用joblib.load加載的時(shí)候所有的文件需要在相同的文件夾下
注意:pickle有一些安全性和可維護(hù)性方面的問題。更多信息酗失,請參考Model persistent 粗梭,以獲得在scikit-learn中模型持久化的更細(xì)節(jié)的信息。
5. 慣例約定
scikit-learn的各種擬合(評估)函數(shù)遵循一些確定的規(guī)則以使得他們的用法能夠更加統(tǒng)一级零。
5.1 類型轉(zhuǎn)換
除非明確指定断医,輸入將被轉(zhuǎn)換為float64
>>> import numpy as np
>>> from sklearn import random_projection
>>> rng = np.random.RandomState(0)
>>> X = rng.rand(10, 2000)
>>> X = np.array(X, dtype='float32')
>>> X.dtype
dtype('float32')
>>> transformer = random_projection.GaussianRandomProjection()
>>> X_new = transformer.fit_transform(X)
>>> X_new.dtype
dtype('float64')
在這個例子中,X是float32奏纪,被fit_transform(X)轉(zhuǎn)換成float64鉴嗤。
回歸的結(jié)果被轉(zhuǎn)換成float64,分類結(jié)果維持不變:
>>> from sklearn import datasets
>>> from sklearn.svm import SVC
>>> iris = datasets.load_iris()
>>> clf = SVC()
>>> clf.fit(iris.data, iris.target)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
>>> list(clf.predict(iris.data[:3]))
[0, 0, 0]
>>> clf.fit(iris.data, iris.target_names[iris.target])
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
>>> list(clf.predict(iris.data[:3]))
['setosa', 'setosa', 'setosa']
這里的第一個predict()返回一個整數(shù)數(shù)組序调,是因?yàn)閕ris.target(一個整數(shù)數(shù)組)被用于擬合。第二個predict()返回一個字符串?dāng)?shù)組发绢,因?yàn)閕ris.target_names被用于擬合硬耍。
5.2 重?cái)M合和更新參數(shù)
一個擬合(評估)函數(shù)的混合參數(shù)(超參數(shù))能夠在通過sklearn.pipeline.Pipeline.set_params方法構(gòu)造之后被更新。多次調(diào)用fit()能夠覆寫之前fit()學(xué)習(xí)的內(nèi)容:
>>> import numpy as np
>>> from sklearn.svm import SVC
>>> rng = np.random.RandomState(0)
>>> X = rng.rand(100, 10)
>>> y = rng.binomial(1, 0.5, 100)
>>> X_test = rng.rand(5, 10)
>>> clf = SVC()
>>> clf.set_params(kernel='linear').fit(X, y)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='linear',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
>>> clf.predict(X_test)
array([1, 0, 1, 1, 0])
>>> clf.set_params(kernel='rbf').fit(X, y)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
>>> clf.predict(X_test)
array([0, 0, 0, 1, 0])
這里的擬合函數(shù)用SVC()構(gòu)造之后边酒,默認(rèn)內(nèi)核rbf
被設(shè)置成'linear'擬合后做了第一次預(yù)測经柴,后來又改回rbf
去重?cái)M合做第二次的預(yù)測。
5.3 Multiclass與multilabel擬合
當(dāng)我們使用multiclass分類器時(shí)墩朦,學(xué)習(xí)和預(yù)測任務(wù)的執(zhí)行就取決于擬合的目標(biāo)數(shù)據(jù)格式:
>>> from sklearn.svm import SVC
>>> from sklearn.multiclass import OneVsRestClassifier
>>> from sklearn.preprocessing import LabelBinarizer
>>> X = [[1, 2], [2, 4], [4, 5], [3, 2], [3, 1]]
>>> y = [0, 0, 1, 1, 2]
>>> classif = OneVsRestClassifier(estimator=SVC(random_state=0))
>>> classif.fit(X, y).predict(X)
array([0, 0, 1, 1, 2])
在上述情況下坯认,分類器在一個適合multiclass標(biāo)簽的一維數(shù)組上進(jìn)行擬合,
因此predict()方法提供multiclass相應(yīng)的分類預(yù)測。
它還可以擬合二維二元標(biāo)簽指標(biāo)(binary label indicators)數(shù)組:
>>> y = LabelBinarizer().fit_transform(y)
>>> classif.fit(X, y).predict(X)
array([[1, 0, 0],
[1, 0, 0],
[0, 1, 0],
[0, 0, 0],
[0, 0, 0]])
這里牛哺,分類器使用LabelBinarizer在二元標(biāo)簽(binary label陋气,表示為y)上擬合。所以相應(yīng)的預(yù)測也返回multilabel二維數(shù)組引润。
注意巩趁,第4和5個元素返回的都是0,表明它們與三個標(biāo)簽中的任何一個都不匹配淳附。用多標(biāo)簽輸出時(shí)晶渠,對一個元素,有可能被打上多個標(biāo)簽:
>>> from sklearn.preprocessing import MultiLabelBinarizer
>>> y = [[0, 1], [0, 2], [1, 3], [0, 2, 3], [2, 4]]
>>> y = MultiLabelBinarizer().fit_transform(y)
>>> classif.fit(X, y).predict(X)
array([[1, 1, 0, 0, 0],
[1, 0, 1, 0, 0],
[0, 1, 0, 1, 0],
[1, 0, 1, 1, 0],
[0, 0, 1, 0, 1]])
這種情況下燃观,分類器擬合后褒脯,為每個元素都打上了多個標(biāo)簽。MultiLabelBinarizer被用來二分?jǐn)M合多標(biāo)簽的二維數(shù)組缆毁。結(jié)果就是predict() 方法為返回的二維數(shù)組中的每個元素打上了多個標(biāo)簽番川。
6. 示例
一個展示怎樣用scikit-learn識別手寫數(shù)字的樣例。
6.1 繪制數(shù)字
from sklearn import datasets
import matplotlib.pyplot as plt
#加載數(shù)字?jǐn)?shù)據(jù)集
digits = datasets.load_digits()
#展示第一個數(shù)字
plt.figure(1, figsize=(3, 3))
plt.imshow(digits.images[-1], cmap=plt.cm.gray_r, interpolation='nearest')
plt.show()
6.2 識別手寫數(shù)字
以下是sklearn官方示例中的代碼脊框,基于自帶的數(shù)據(jù)颁督,使用支持向量分類器(svm.SVC(gamma=0.001))學(xué)習(xí)后進(jìn)行預(yù)測。
# coding:UTF-8
print(__doc__)
# Author: Gael Varoquaux <gael dot varoquaux at normalesup dot org>
# License: BSD 3 clause
# Standard scientific Python imports
import matplotlib.pyplot as plt
# Import datasets, classifiers and performance metrics
from sklearn import datasets, svm, metrics
# The digits dataset
digits = datasets.load_digits()
# The data that we are interested in is made of 8x8 images of digits, let's
# have a look at the first 4 images, stored in the `images` attribute of the
# dataset. If we were working from image files, we could load them using
# matplotlib.pyplot.imread. Note that each image must have the same size. For these
# images, we know which digit they represent: it is given in the 'target' of
# the dataset.
images_and_labels = list(zip(digits.images, digits.target))
for index, (image, label) in enumerate(images_and_labels[:4]):
plt.subplot(2, 4, index + 1)
plt.axis('off')
plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
plt.title('Training: %i' % label)
# To apply a classifier on this data, we need to flatten the image, to
# turn the data in a (samples, feature) matrix:
n_samples = len(digits.images)
data = digits.images.reshape((n_samples, -1))
# Create a classifier: a support vector classifier
classifier = svm.SVC(gamma=0.001)
# We learn the digits on the first half of the digits
classifier.fit(data[:n_samples // 2], digits.target[:n_samples // 2])
# Now predict the value of the digit on the second half:
expected = digits.target[n_samples // 2:]
predicted = classifier.predict(data[n_samples // 2:])
print("Classification report for classifier %s:\n%s\n"
% (classifier, metrics.classification_report(expected, predicted)))
print("Confusion matrix:\n%s" % metrics.confusion_matrix(expected, predicted))
images_and_predictions = list(zip(digits.images[n_samples // 2:], predicted))
for index, (image, prediction) in enumerate(images_and_predictions[:4]):
plt.subplot(2, 4, index + 5)
plt.axis('off')
plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
plt.title('Prediction: %i' % prediction)
plt.show()
以上代碼保存到python源文件中浇雹,在PyCharm中執(zhí)行沉御,結(jié)果如下: