這是一篇手把手教你使用 Python 實現機器學習算法,并在數值型數據和圖像數據集上運行模型的入門教程,當你看完本文后,你應當可以開始你的機器學習之旅了!
本教程會采用下述兩個庫來實現機器學習算法:
scikit-learn
Keras
此外,你還將學習到:
評估你的問題
準備數據(原始數據、特征提取、特征工程等等)
檢查各種機器學習算法
檢驗實驗結果
深入了解性能最好的算法
在本文會用到的機器學習算法包括:
KNN
樸素貝葉斯
邏輯回歸
SVM
決策樹
隨機森林
感知機
多層前向網絡
CNNs
安裝必備的 Python 機器學習庫
開始本教程前,需要先確保安裝了一下的 Python 庫:
Numpy:用于 Python 的數值處理
PIL:一個簡單的圖像處理庫
scikit-learn:包含多種機器學習算法(注意需要采用 0.2+ 的版本,所以下方安裝命令需要加上--upgrade)
Kears 和 TensorFlow:用于深度學習。本教程可以僅采用 CPU 版本的 TensorFlow
OpenCV:本教程并不會采用到 OpenCV,但imutils庫依賴它;
imutils:作者的圖像處理/計算機視覺庫
安裝命令如下,推薦采用虛擬環境(比如利用 anaconda 創建一個新的環境):
$pipinstallnumpy$pipinstallpillow$pipinstall--upgradescikit-learn$pipinstalltensorflow#ortensorflow-gpu$pipinstallkeras$pipinstallopencv-contrib-python$pipinstall--upgradeimutils
數據集
本教程會用到兩個數據集來幫助更好的了解每個機器學習算法的性能。
第一個數據集是 Iris(鳶尾花)數據集。這個數據集的地位,相當于你剛開始學習一門編程語言時,敲下的 “Hello,World!”
這個數據集是一個數值型的數據,如下圖所示,其實就是一個表格數據,每一行代表一個樣本,然后每一列就是不同的屬性。這個數據集主要是收集了三種不同的鳶尾花的數據,分別為:
Iris Setosa
Iris Versicolor
Iris Virginica
對應圖中最后一列Class label,然后還有四種屬性,分別是:
Sepal length--萼片長度
Sepal width--萼片寬度
Petal length--花瓣長度
Petal width--花瓣寬度
這個數據集可能是最簡單的機器學習數據集之一了,通常是用于教導程序員和工程師的機器學習和模式識別基礎的數據集。
對于該數據集,我們的目標就是根據給定的四個屬性,訓練一個機器學習模型來正確分類每個樣本的類別。
需要注意的是,其中有一個類別和另外兩個類別是線性可分的,但這兩個類別之間卻并非線性可分,所以我們需要采用一個非線性模型來對它們進行分類。當然了,在現實生活中,采用非線性模型的機器學習算法是非常常見的。
第二個數據集是一個三場景的圖像數據集。這是幫助初學者學習如何處理圖像數據,并且哪種算法在這兩種數據集上性能最優。
下圖是這個三場景數據集的部分圖片例子,它包括森林、高速公路和海岸線三種場景,總共是 948 張圖片,每個類別的具體圖片數量如下:
Coast: 360
Forest: 328
Highway: 260
這個三場景數據集是采樣于一個八場景數據集中,作者是 Oliva 和 Torralba 的 2001 年的一篇論文,Modeling the shape of the scene: a holistic representation of the spatial envelope
利用 Python 實現機器學習的步驟
無論什么時候實現機器學習算法,推薦采用如下流程來開始:
評估你的問題
準備數據(原始數據、特征提取、特征工程等等)
檢查各種機器學習算法
檢驗實驗結果
深入了解性能最好的算法
這個流程會隨著你機器學習方面的經驗的積累而改善和優化,但對于初學者,這是我建議入門機器學習時采用的流程。
所以,現在開始吧!第一步,就是評估我們的問題,問一下自己:
數據集是哪種類型?數值型,類別型還是圖像?
模型的最終目標是什么?
如何定義和衡量“準確率”呢?
以目前自身的機器學習知識來看,哪些算法在處理這類問題上效果很好?
最后一個問題非常重要,隨著你使用 Python 實現機器學習的次數的增加,你也會隨之獲得更多的經驗。根據之前的經驗,你可能知道有一種算法的性能還不錯。
因此,接著就是準備數據,也就是數據預處理以及特征工程了。
一般來說,這一步,包括了從硬盤中載入數據,檢查數據,然后決定是否需要做特征提取或者特征工程。
特征提取就是應用某種算法通過某種方式來量化數據的過程。比如,對于圖像數據,我們可以采用計算直方圖的方法來統計圖像中像素強度的分布,通過這種方式,我們就得到描述圖像顏色的特征。
而特征工程則是將原始輸入數據轉換成一個更好描述潛在問題的特征表示的過程。當然特征工程是一項更先進的技術,這里建議在對機器學習有了一定經驗后再采用這種方法處理數據。
第三步,就是檢查各種機器學習算法,也就是實現一系列機器學習算法,并應用在數據集上。
這里,你的工具箱應當包含以下幾種不同類型的機器學習算法:
線性模型(比如,邏輯回歸,線性 SVM)
非線性模型(比如 RBF SVM,梯度下降分類器)
樹和基于集成的模型(比如 決策樹和隨機森林)
神經網絡(比如 多層感知機,卷積神經網絡)
應當選擇比較魯棒(穩定)的一系列機器學習模型來評估問題,因為我們的目標就是判斷哪種算法在當前問題的性能很好,而哪些算法很糟糕。
決定好要采用的模型后,接下來就是訓練模型并在數據集上測試,觀察每個模型在數據集上的性能結果。
在多次實驗后,你可能就是有一種“第六感”,知道哪種算法更適用于哪種數據集。比如,你會發現:
對于有很多特征的數據集,隨機森林算法的效果很不錯;
而邏輯回歸算法可以很好處理高維度的稀疏數據;
對于圖像數據,CNNs 的效果非常好。
而以上的經驗獲得,當然就需要你多動手,多進行實戰來深入了解不同的機器學習算法了!
開始動手吧!
接下來就開始敲代碼來實現機器學習算法,并在上述兩個數據集上進行測試。本教程的代碼文件目錄如下,包含四份代碼文件和一個3scenes文件夾,該文件夾就是三場景數據集,而Iris數據集直接采用scikit-learn庫載入即可。
├──3scenes│├──coast[360entries]│├──forest[328entries]│└──highway[260entries]├──classify_iris.py├──classify_images.py├──nn_iris.py└──basic_cnn.py
首先是實現classify_iris.py,這份代碼是采用機器學習算法來對Iris數據集進行分類。
首先導入需要的庫:
fromsklearn.neighborsimportKNeighborsClassifierfromsklearn.naive_bayesimportGaussianNBfromsklearn.linear_modelimportLogisticRegressionfromsklearn.svmimportSVCfromsklearn.treeimportDecisionTreeClassifierfromsklearn.ensembleimportRandomForestClassifierfromsklearn.neural_networkimportMLPClassifierfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromsklearn.datasetsimportload_irisimportargparse#設置參數ap=argparse.ArgumentParser()ap.add_argument("-m","--model",type=str,default="knn",help="typeofpythonmachinelearningmodeltouse")args=vars(ap.parse_args())#定義一個保存模型的字典,根據key來選擇加載哪個模型models={"knn":KNeighborsClassifier(n_neighbors=1),"naive_bayes":GaussianNB(),"logit":LogisticRegression(solver="lbfgs",multi_class="auto"),"svm":SVC(kernel="rbf",gamma="auto"),"decision_tree":DecisionTreeClassifier(),"random_forest":RandomForestClassifier(n_estimators=100),"mlp":MLPClassifier()}
可以看到在sklearn庫中就集成了我們將要實現的幾種機器學習算法的代碼,包括:
KNN
樸素貝葉斯
邏輯回歸
SVM
決策樹
隨機森林
感知機
我們直接調用sklearn中相應的函數來實現對應的算法即可,比如對于knn算法,直接調用sklearn.neighbors中的KNeighborsClassifier()即可,只需要設置參數n_neighbors,即最近鄰的個數。
這里直接用一個models的字典來保存不同模型的初始化,然后根據參數--model來調用對應的模型,比如命令輸入python classify_irs.py --model knn就是調用knn算法模型。
接著就是載入數據部分:
print("[INFO]loadingdata...")dataset=load_iris()(trainX,testX,trainY,testY)=train_test_split(dataset.data,dataset.target,random_state=3,test_size=0.25)
這里直接調用sklearn.datasets中的load_iris()載入數據,然后采用train_test_split來劃分訓練集和數據集,這里是 75% 數據作為訓練集,25% 作為測試集。
最后就是訓練模型和預測部分:
#訓練模型print("[INFO]using'{}'model".format(args["model"]))model=models[args["model"]]model.fit(trainX,trainY)#預測并輸出一份分類結果報告print("[INFO]evaluating")predictions=model.predict(testX)print(classification_report(testY,predictions,target_names=dataset.target_names))
完整版代碼代碼如下:
fromsklearn.neighborsimportKNeighborsClassifierfromsklearn.naive_bayesimportGaussianNBfromsklearn.linear_modelimportLogisticRegressionfromsklearn.svmimportSVCfromsklearn.treeimportDecisionTreeClassifierfromsklearn.ensembleimportRandomForestClassifierfromsklearn.neural_networkimportMLPClassifierfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromsklearn.datasetsimportload_irisimportargparse#設置參數ap=argparse.ArgumentParser()ap.add_argument("-m","--model",type=str,default="knn",help="typeofpythonmachinelearningmodeltouse")args=vars(ap.parse_args())#定義一個保存模型的字典,根據key來選擇加載哪個模型models={"knn":KNeighborsClassifier(n_neighbors=1),"naive_bayes":GaussianNB(),"logit":LogisticRegression(solver="lbfgs",multi_class="auto"),"svm":SVC(kernel="rbf",gamma="auto"),"decision_tree":DecisionTreeClassifier(),"random_forest":RandomForestClassifier(n_estimators=100),"mlp":MLPClassifier()}#載入Iris數據集,然后進行訓練集和測試集的劃分,75%數據作為訓練集,其余25%作為測試集print("[INFO]loadingdata...")dataset=load_iris()(trainX,testX,trainY,testY)=train_test_split(dataset.data,dataset.target,random_state=3,test_size=0.25)#訓練模型print("[INFO]using'{}'model".format(args["model"]))model=models[args["model"]]model.fit(trainX,trainY)#預測并輸出一份分類結果報告print("[INFO]evaluating")predictions=model.predict(testX)print(classification_report(testY,predictions,target_names=dataset.target_names))
接著就是采用三場景圖像數據集的分類預測代碼 classify_images.py ,跟 classify_iris.py 的代碼其實是比較相似的,首先導入庫部分,增加以下幾行代碼:
fromsklearn.preprocessingimportLabelEncoderfromPILimportImagefromimutilsimportpathsimportnumpyasnpimportos
其中LabelEncoder是為了將標簽從字符串編碼為整型,然后其余幾項都是處理圖像相關。
對于圖像數據,如果直接采用原始像素信息輸入模型中,大部分的機器學習算法效果都很不理想,所以這里采用特征提取方法,主要是統計圖像顏色通道的均值和標準差信息,總共是 RGB 3個通道,每個通道各計算均值和標準差,然后結合在一起,得到一個六維的特征,函數如下所示:
defextract_color_stats(image):'''將圖片分成RGB三通道,然后分別計算每個通道的均值和標準差,然后返回:paramimage::return:'''(R,G,B)=image.split()features=[np.mean(R),np.mean(G),np.mean(B),np.std(R),np.std(G),np.std(B)]returnfeatures
然后同樣會定義一個models字典,代碼一樣,這里就不貼出來了,然后圖像載入部分的代碼如下:
#加載數據并提取特征print("[INFO]extractingimagefeatures...")imagePaths=paths.list_images(args['dataset'])data=[]labels=[]#循環遍歷所有的圖片數據forimagePathinimagePaths:#加載圖片,然后計算圖片的顏色通道統計信息image=Image.open(imagePath)features=extract_color_stats(image)data.append(features)#保存圖片的標簽信息label=imagePath.split(os.path.sep)[-2]labels.append(label)#對標簽進行編碼,從字符串變為整數類型le=LabelEncoder()labels=le.fit_transform(labels)#進行訓練集和測試集的劃分,75%數據作為訓練集,其余25%作為測試集(trainX,testX,trainY,testY)=train_test_split(data,labels,test_size=0.25)
上述代碼就完成從硬盤中加載圖片的路徑信息,然后依次遍歷,讀取圖片,提取特征,提取標簽信息,保存特征和標簽信息,接著編碼標簽,然后就是劃分訓練集和測試集。
接著是相同的訓練模型和預測的代碼,同樣沒有任何改變,這里就不列舉出來了。
完整版如下:
fromsklearn.neighborsimportKNeighborsClassifierfromsklearn.naive_bayesimportGaussianNBfromsklearn.linear_modelimportLogisticRegressionfromsklearn.svmimportSVCfromsklearn.treeimportDecisionTreeClassifierfromsklearn.ensembleimportRandomForestClassifierfromsklearn.neural_networkimportMLPClassifierfromsklearn.preprocessingimportLabelEncoderfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromPILimportImagefromimutilsimportpathsimportnumpyasnpimportargparseimportosdefextract_color_stats(image):'''將圖片分成RGB三通道,然后分別計算每個通道的均值和標準差,然后返回:paramimage::return:'''(R,G,B)=image.split()features=[np.mean(R),np.mean(G),np.mean(B),np.std(R),np.std(G),np.std(B)]returnfeatures#設置參數ap=argparse.ArgumentParser()ap.add_argument("-d","--dataset",type=str,default="3scenes",help="pathtodirectorycontainingthe'3scenes'dataset")ap.add_argument("-m","--model",type=str,default="knn",help="typeofpythonmachinelearningmodeltouse")args=vars(ap.parse_args())#定義一個保存模型的字典,根據key來選擇加載哪個模型models={"knn":KNeighborsClassifier(n_neighbors=1),"naive_bayes":GaussianNB(),"logit":LogisticRegression(solver="lbfgs",multi_class="auto"),"svm":SVC(kernel="rbf",gamma="auto"),"decision_tree":DecisionTreeClassifier(),"random_forest":RandomForestClassifier(n_estimators=100),"mlp":MLPClassifier()}#加載數據并提取特征print("[INFO]extractingimagefeatures...")imagePaths=paths.list_images(args['dataset'])data=[]labels=[]#循環遍歷所有的圖片數據forimagePathinimagePaths:#加載圖片,然后計算圖片的顏色通道統計信息image=Image.open(imagePath)features=extract_color_stats(image)data.append(features)#保存圖片的標簽信息label=imagePath.split(os.path.sep)[-2]labels.append(label)#對標簽進行編碼,從字符串變為整數類型le=LabelEncoder()labels=le.fit_transform(labels)#進行訓練集和測試集的劃分,75%數據作為訓練集,其余25%作為測試集(trainX,testX,trainY,testY)=train_test_split(data,labels,random_state=3,test_size=0.25)#print('trainXnumbers={},testXnumbers={}'.format(len(trainX),len(testX)))#訓練模型print("[INFO]using'{}'model".format(args["model"]))model=models[args["model"]]model.fit(trainX,trainY)#預測并輸出分類結果報告print("[INFO]evaluating...")predictions=model.predict(testX)print(classification_report(testY,predictions,target_names=le.classes_))
完成這兩份代碼后,我們就可以開始運行下代碼,對比不同算法在兩個數據集上的性能。
因為篇幅的原因,這里我會省略原文對每個算法的介紹,具體的可以查看之前我寫的對機器學習算法的介紹:
常用機器學習算法匯總比較(上)
常用機器學習算法匯總比較(中)
常用機器學習算法匯總比較(完)
KNN
這里我們先運行下classify_irs.py,調用默認的模型knn,看下KNN在Iris數據集上的實驗結果,如下所示:
其中主要是給出了對每個類別的精確率、召回率、F1 以及該類別測試集數量,即分別對應precision,recall,f1-score,support。根據最后一行第一列,可以看到KNN取得95%的準確率。
接著是在三場景圖片數據集上的實驗結果:
這里KNN取得72%的準確率。
(ps:實際上,運行這個算法,不同次數會有不同的結果,原文作者給出的是 75%,其主要原因是因為在劃分訓練集和測試集的時候,代碼沒有設置參數random_state,這導致每次運行劃分的訓練集和測試集的圖片都是不同的,所以運行結果也會不相同!)
樸素貝葉斯
接著是樸素貝葉斯算法,分別測試兩個數據集,結果如下:
同樣,樸素貝葉斯在Iris上有98%的準確率,但是在圖像數據集上僅有63%的準確率。
那么,我們是否可以說明KNN算法比樸素貝葉斯好呢?
當然是不可以的,上述結果只能說明在三場景圖像數據集上,KNN算法優于樸素貝葉斯算法。
實際上,每種算法都有各自的優缺點和適用場景,不能一概而論地說某種算法任何時候都優于另一種算法,這需要具體問題具體分析。
邏輯回歸
接著是邏輯回歸算法,分別測試兩個數據集,結果如下:
同樣,邏輯回歸在Iris上有98%的準確率,但是在圖像數據集上僅有77%的準確率(對比原文作者的邏輯回歸準確率是 69%)
支持向量機 SVM
接著是 SVM 算法,分別測試兩個數據集,結果如下:
同樣,SVM 在Iris上有98%的準確率,但是在圖像數據集上僅有76%的準確率(對比原文作者的準確率是 83%,主要是發現類別coast差別有些大)
決策樹
接著是決策樹算法,分別測試兩個數據集,結果如下:
同樣,決策樹在Iris上有98%的準確率,但是在圖像數據集上僅有71%的準確率(對比原文作者的決策樹準確率是 74%)
隨機森林
接著是隨機森林算法,分別測試兩個數據集,結果如下:
同樣,隨機森林在Iris上有96%的準確率,但是在圖像數據集上僅有77%的準確率(對比原文作者的決策樹準確率是 84%)
注意了,一般如果決策樹算法的效果還不錯的話,隨機森林算法應該也會取得不錯甚至更好的結果,這是因為隨機森林實際上就是多棵決策樹通過集成學習方法組合在一起進行分類預測。
多層感知機
最后是多層感知機算法,分別測試兩個數據集,結果如下:
同樣,多層感知機在Iris上有98%的準確率,但是在圖像數據集上僅有79%的準確率(對比原文作者的決策樹準確率是 81%).
深度學習以及深度神經網絡
神經網絡
最后是實現深度學習的算法,也就是nn_iris.py和basic_cnn.py這兩份代碼。
(這里需要注意TensorFlow和Keras的版本問題,我采用的是TF=1.2和Keras=2.1.5)
首先是nn_iris.py的實現,同樣首先是導入庫和數據的處理:
fromkeras.modelsimportSequentialfromkeras.layers.coreimportDensefromkeras.optimizersimportSGDfromsklearn.preprocessingimportLabelBinarizerfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromsklearn.datasetsimportload_iris#載入Iris數據集,然后進行訓練集和測試集的劃分,75%數據作為訓練集,其余25%作為測試集print("[INFO]loadingdata...")dataset=load_iris()(trainX,testX,trainY,testY)=train_test_split(dataset.data,dataset.target,test_size=0.25)#將標簽進行one-hot編碼lb=LabelBinarizer()trainY=lb.fit_transform(trainY)testY=lb.transform(testY)
這里我們將采用Keras來實現神經網絡,然后這里需要將標簽進行one-hot編碼,即獨熱編碼。
接著就是搭建網絡模型的結構和訓練、預測代碼:
#利用Keras定義網絡模型model=Sequential()model.add(Dense(3,input_shape=(4,),activation="sigmoid"))model.add(Dense(3,activation="sigmoid"))model.add(Dense(3,activation="softmax"))#采用梯度下降訓練模型print('[INFO]trainingnetwork...')opt=SGD(lr=0.1,momentum=0.9,decay=0.1/250)model.compile(loss='categorical_crossentropy',optimizer=opt,metrics=["accuracy"])H=model.fit(trainX,trainY,validation_data=(testX,testY),epochs=250,batch_size=16)#預測print('[INFO]evaluatingnetwork...')predictions=model.predict(testX,batch_size=16)print(classification_report(testY.argmax(axis=1),predictions.argmax(axis=1),target_names=dataset.target_names))
這里是定義了 3 層全連接層的神經網絡,前兩層采用Sigmoid激活函數,然后最后一層是輸出層,所以采用softmax將輸出變成概率值。接著就是定義了使用SGD的優化算法,損失函數是categorical_crossentropy,迭代次數是 250 次,batch_size是 16。
完整版如下:
fromkeras.modelsimportSequentialfromkeras.layers.coreimportDensefromkeras.optimizersimportSGDfromsklearn.preprocessingimportLabelBinarizerfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromsklearn.datasetsimportload_iris#載入Iris數據集,然后進行訓練集和測試集的劃分,75%數據作為訓練集,其余25%作為測試集print("[INFO]loadingdata...")dataset=load_iris()(trainX,testX,trainY,testY)=train_test_split(dataset.data,dataset.target,test_size=0.25)#將標簽進行one-hot編碼lb=LabelBinarizer()trainY=lb.fit_transform(trainY)testY=lb.transform(testY)#利用Keras定義網絡模型model=Sequential()model.add(Dense(3,input_shape=(4,),activation="sigmoid"))model.add(Dense(3,activation="sigmoid"))model.add(Dense(3,activation="softmax"))#采用梯度下降訓練模型print('[INFO]trainingnetwork...')opt=SGD(lr=0.1,momentum=0.9,decay=0.1/250)model.compile(loss='categorical_crossentropy',optimizer=opt,metrics=["accuracy"])H=model.fit(trainX,trainY,validation_data=(testX,testY),epochs=250,batch_size=16)#預測print('[INFO]evaluatingnetwork...')predictions=model.predict(testX,batch_size=16)print(classification_report(testY.argmax(axis=1),predictions.argmax(axis=1),target_names=dataset.target_names))
直接運行命令python nn_iris.py, 輸出的結果如下:
這里得到的是 100% 的準確率,和原文的一樣。當然實際上原文給出的結果如下圖所示,可以看到其實類別數量上是不相同的。
CNN
最后就是實現basic_cnn.py這份代碼了。
同樣首先是導入必須的庫函數:
fromkeras.modelsimportSequentialfromkeras.layers.convolutionalimportConv2Dfromkeras.layers.convolutionalimportMaxPooling2Dfromkeras.layers.coreimportActivationfromkeras.layers.coreimportFlattenfromkeras.layers.coreimportDensefromkeras.optimizersimportAdamfromsklearn.preprocessingimportLabelBinarizerfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromPILimportImagefromimutilsimportpathsimportnumpyasnpimportargparseimportos#配置參數ap=argparse.ArgumentParser()ap.add_argument("-d","--dataset",type=str,default="3scenes",help="pathtodirectorycontainingthe'3scenes'dataset")args=vars(ap.parse_args())
同樣是要導入Keras來建立CNN的網絡模型,另外因為是處理圖像數據,所以PIL、imutils也是要導入的。
然后是加載數據和劃分訓練集和測試集,對于加載數據,這里直接采用原始圖像像素數據,只需要對圖像數據做統一尺寸的調整,這里是統一調整為 32×32,并做歸一化到[0,1]的范圍。
#加載數據并提取特征print("[INFO]extractingimagefeatures...")imagePaths=paths.list_images(args['dataset'])data=[]labels=[]#循環遍歷所有的圖片數據forimagePathinimagePaths:#加載圖片,然后調整成32×32大小,并做歸一化到[0,1]image=Image.open(imagePath)image=np.array(image.resize((32,32)))/255.0data.append(image)#保存圖片的標簽信息label=imagePath.split(os.path.sep)[-2]labels.append(label)#對標簽編碼,從字符串變為整型lb=LabelBinarizer()labels=lb.fit_transform(labels)#劃分訓練集和測試集(trainX,testX,trainY,testY)=train_test_split(np.array(data),np.array(labels),test_size=0.25)
接著定義了一個 4 層的CNN網絡結構,包含 3 層卷積層和最后一層輸出層,優化算法采用的是Adam而不是SGD。代碼如下所示:
#定義CNN網絡模型結構model=Sequential()model.add(Conv2D(8,(3,3),padding="same",input_shape=(32,32,3)))model.add(Activation("relu"))model.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(16,(3,3),padding="same"))model.add(Activation("relu"))model.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(32,(3,3),padding="same"))model.add(Activation("relu"))model.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))model.add(Flatten())model.add(Dense(3))model.add(Activation("softmax"))#訓練模型print("[INFO]trainingnetwork...")opt=Adam(lr=1e-3,decay=1e-3/50)model.compile(loss="categorical_crossentropy",optimizer=opt,metrics=["accuracy"])H=model.fit(trainX,trainY,validation_data=(testX,testY),epochs=50,batch_size=32)#預測print("[INFO]evaluatingnetwork...")predictions=model.predict(testX,batch_size=32)print(classification_report(testY.argmax(axis=1),predictions.argmax(axis=1),target_names=lb.classes_))
完整版如下:
fromkeras.modelsimportSequentialfromkeras.layers.convolutionalimportConv2Dfromkeras.layers.convolutionalimportMaxPooling2Dfromkeras.layers.coreimportActivationfromkeras.layers.coreimportFlattenfromkeras.layers.coreimportDensefromkeras.optimizersimportAdamfromsklearn.preprocessingimportLabelBinarizerfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromPILimportImagefromimutilsimportpathsimportnumpyasnpimportargparseimportos#配置參數ap=argparse.ArgumentParser()ap.add_argument("-d","--dataset",type=str,default="3scenes",help="pathtodirectorycontainingthe'3scenes'dataset")args=vars(ap.parse_args())#加載數據并提取特征print("[INFO]extractingimagefeatures...")imagePaths=paths.list_images(args['dataset'])data=[]labels=[]#循環遍歷所有的圖片數據forimagePathinimagePaths:#加載圖片,然后調整成32×32大小,并做歸一化到[0,1]image=Image.open(imagePath)image=np.array(image.resize((32,32)))/255.0data.append(image)#保存圖片的標簽信息label=imagePath.split(os.path.sep)[-2]labels.append(label)#對標簽編碼,從字符串變為整型lb=LabelBinarizer()labels=lb.fit_transform(labels)#劃分訓練集和測試集(trainX,testX,trainY,testY)=train_test_split(np.array(data),np.array(labels),test_size=0.25)#定義CNN網絡模型結構model=Sequential()model.add(Conv2D(8,(3,3),padding="same",input_shape=(32,32,3)))model.add(Activation("relu"))model.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(16,(3,3),padding="same"))model.add(Activation("relu"))model.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(32,(3,3),padding="same"))model.add(Activation("relu"))model.add(MaxPooling2D(pool_size=(2,2),strides=(2,2)))model.add(Flatten())model.add(Dense(3))model.add(Activation("softmax"))#訓練模型print("[INFO]trainingnetwork...")opt=Adam(lr=1e-3,decay=1e-3/50)model.compile(loss="categorical_crossentropy",optimizer=opt,metrics=["accuracy"])H=model.fit(trainX,trainY,validation_data=(testX,testY),epochs=50,batch_size=32)#預測print("[INFO]evaluatingnetwork...")predictions=model.predict(testX,batch_size=32)print(classification_report(testY.argmax(axis=1),predictions.argmax(axis=1),target_names=lb.classes_))
運行命令python basic_cnn.py, 輸出結果如下:
CNN的準確率是達到90%,它是優于之前的幾種機器學習算法的結果。
小結
最后,這僅僅是一份對機器學習完全是初學者的教程,其實就是簡單調用現有的庫來實現對應的機器學習算法,讓初學者簡單感受下如何使用機器學習算法,正如同在學習編程語言的時候,對著書本的代碼例子敲起來,然后運行代碼,看看自己寫出來的程序的運行結果。
通過這份簡單的入門教程,你應該明白的是:
沒有任何一種算法是完美的,可以完全適用所有的場景,即便是目前很熱門的深度學習方法,也存在它的局限性,所以應該具體問題具體分析!
記住開頭推薦的 5 步機器學習操作流程,這里再次復習一遍:
評估你的問題
準備數據(原始數據、特征提取、特征工程等等)
檢查各種機器學習算法
檢驗實驗結果
深入了解性能最好的算法
最后一點,是我運行算法結果,和原文作者的結果會不相同,這實際上就是每次采樣數據,劃分訓練集和測試集不相同的原因!這其實也說明了數據非常重要,對于機器學習來說,好的數據很重要!
接著,根據這份教程,你可以繼續進一步了解每種機器學習算法,了解每種算法的基本原理和實現,嘗試自己手動實現,而不是簡單調用現有的庫,這樣更加能加深印象,這里推薦《機器學習實戰》,經典的機器學習算法都有介紹,并且都會帶你一步步實現算法!
最后,極力推薦大家去閱讀下原文作者的博客,原文作者也是一個大神,他的博客地址如下:https://www.pyimagesearch.com/
他的博客包含了 Opencv、Python、機器學習和深度學習方面的教程和文章,而且作者喜歡通過實戰學習,所以很多文章都是通過一些實戰練習來學習某個知識點或者某個算法,正如同本文通過實現這幾種常見的機器學習算法在兩個不同類型數據集上的實戰來帶領初學者入門機器學習。
-
機器學習
+關注
關注
66文章
8478瀏覽量
133810 -
python
+關注
關注
56文章
4822瀏覽量
85802 -
數據集
+關注
關注
4文章
1220瀏覽量
25183
原文標題:初學者的機器學習入門實戰教程!
文章出處:【微信號:rgznai100,微信公眾號:rgznai100】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論