0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

手把手教你使用Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法

電子工程師 ? 來源:lp ? 2019-04-04 16:49 ? 次閱讀

這是一篇手把手教你使用 Python 實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法,并在數(shù)值型數(shù)據(jù)和圖像數(shù)據(jù)集上運(yùn)行模型的入門教程,當(dāng)你看完本文后,你應(yīng)當(dāng)可以開始你的機(jī)器學(xué)習(xí)之旅了!

本教程會采用下述兩個庫來實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法:

scikit-learn

Keras

此外,你還將學(xué)習(xí)到:

評估你的問題

準(zhǔn)備數(shù)據(jù)(原始數(shù)據(jù)、特征提取、特征工程等等)

檢查各種機(jī)器學(xué)習(xí)算法

檢驗(yàn)實(shí)驗(yàn)結(jié)果

深入了解性能最好的算法

在本文會用到的機(jī)器學(xué)習(xí)算法包括:

KNN

樸素貝葉斯

邏輯回歸

SVM

決策樹

隨機(jī)森林

感知機(jī)

多層前向網(wǎng)絡(luò)

CNNs

安裝必備的 Python 機(jī)器學(xué)習(xí)庫

開始本教程前,需要先確保安裝了一下的 Python 庫:

Numpy:用于 Python 的數(shù)值處理

PIL:一個簡單的圖像處理庫

scikit-learn:包含多種機(jī)器學(xué)習(xí)算法(注意需要采用 0.2+ 的版本,所以下方安裝命令需要加上--upgrade)

Kears 和 TensorFlow:用于深度學(xué)習(xí)。本教程可以僅采用 CPU 版本的 TensorFlow

OpenCV:本教程并不會采用到 OpenCV,但imutils庫依賴它;

imutils:作者的圖像處理/計(jì)算機(jī)視覺

安裝命令如下,推薦采用虛擬環(huán)境(比如利用 anaconda 創(chuàng)建一個新的環(huán)境):

$pipinstallnumpy$pipinstallpillow$pipinstall--upgradescikit-learn$pipinstalltensorflow#ortensorflow-gpu$pipinstallkeras$pipinstallopencv-contrib-python$pipinstall--upgradeimutils

數(shù)據(jù)集

本教程會用到兩個數(shù)據(jù)集來幫助更好的了解每個機(jī)器學(xué)習(xí)算法的性能。

第一個數(shù)據(jù)集是 Iris(鳶尾花)數(shù)據(jù)集。這個數(shù)據(jù)集的地位,相當(dāng)于你剛開始學(xué)習(xí)一門編程語言時,敲下的 “Hello,World!”

這個數(shù)據(jù)集是一個數(shù)值型的數(shù)據(jù),如下圖所示,其實(shí)就是一個表格數(shù)據(jù),每一行代表一個樣本,然后每一列就是不同的屬性。這個數(shù)據(jù)集主要是收集了三種不同的鳶尾花的數(shù)據(jù),分別為:

Iris Setosa

Iris Versicolor

Iris Virginica

對應(yīng)圖中最后一列Class label,然后還有四種屬性,分別是:

Sepal length--萼片長度

Sepal width--萼片寬度

Petal length--花瓣長度

Petal width--花瓣寬度

這個數(shù)據(jù)集可能是最簡單的機(jī)器學(xué)習(xí)數(shù)據(jù)集之一了,通常是用于教導(dǎo)程序員工程師的機(jī)器學(xué)習(xí)和模式識別基礎(chǔ)的數(shù)據(jù)集。

對于該數(shù)據(jù)集,我們的目標(biāo)就是根據(jù)給定的四個屬性,訓(xùn)練一個機(jī)器學(xué)習(xí)模型來正確分類每個樣本的類別。

需要注意的是,其中有一個類別和另外兩個類別是線性可分的,但這兩個類別之間卻并非線性可分,所以我們需要采用一個非線性模型來對它們進(jìn)行分類。當(dāng)然了,在現(xiàn)實(shí)生活中,采用非線性模型的機(jī)器學(xué)習(xí)算法是非常常見的。

第二個數(shù)據(jù)集是一個三場景的圖像數(shù)據(jù)集。這是幫助初學(xué)者學(xué)習(xí)如何處理圖像數(shù)據(jù),并且哪種算法在這兩種數(shù)據(jù)集上性能最優(yōu)。

下圖是這個三場景數(shù)據(jù)集的部分圖片例子,它包括森林、高速公路和海岸線三種場景,總共是 948 張圖片,每個類別的具體圖片數(shù)量如下:

Coast: 360

Forest: 328

Highway: 260

這個三場景數(shù)據(jù)集是采樣于一個八場景數(shù)據(jù)集中,作者是 Oliva 和 Torralba 的 2001 年的一篇論文,Modeling the shape of the scene: a holistic representation of the spatial envelope

利用 Python 實(shí)現(xiàn)機(jī)器學(xué)習(xí)的步驟

無論什么時候?qū)崿F(xiàn)機(jī)器學(xué)習(xí)算法,推薦采用如下流程來開始:

評估你的問題

準(zhǔn)備數(shù)據(jù)(原始數(shù)據(jù)、特征提取、特征工程等等)

檢查各種機(jī)器學(xué)習(xí)算法

檢驗(yàn)實(shí)驗(yàn)結(jié)果

深入了解性能最好的算法

這個流程會隨著你機(jī)器學(xué)習(xí)方面的經(jīng)驗(yàn)的積累而改善和優(yōu)化,但對于初學(xué)者,這是我建議入門機(jī)器學(xué)習(xí)時采用的流程。

所以,現(xiàn)在開始吧!第一步,就是評估我們的問題,問一下自己:

數(shù)據(jù)集是哪種類型?數(shù)值型,類別型還是圖像?

模型的最終目標(biāo)是什么?

如何定義和衡量“準(zhǔn)確率”呢?

以目前自身的機(jī)器學(xué)習(xí)知識來看,哪些算法在處理這類問題上效果很好?

最后一個問題非常重要,隨著你使用 Python 實(shí)現(xiàn)機(jī)器學(xué)習(xí)的次數(shù)的增加,你也會隨之獲得更多的經(jīng)驗(yàn)。根據(jù)之前的經(jīng)驗(yàn),你可能知道有一種算法的性能還不錯。

因此,接著就是準(zhǔn)備數(shù)據(jù),也就是數(shù)據(jù)預(yù)處理以及特征工程了。

一般來說,這一步,包括了從硬盤中載入數(shù)據(jù),檢查數(shù)據(jù),然后決定是否需要做特征提取或者特征工程。

特征提取就是應(yīng)用某種算法通過某種方式來量化數(shù)據(jù)的過程。比如,對于圖像數(shù)據(jù),我們可以采用計(jì)算直方圖的方法來統(tǒng)計(jì)圖像中像素強(qiáng)度的分布,通過這種方式,我們就得到描述圖像顏色的特征。

而特征工程則是將原始輸入數(shù)據(jù)轉(zhuǎn)換成一個更好描述潛在問題的特征表示的過程。當(dāng)然特征工程是一項(xiàng)更先進(jìn)的技術(shù),這里建議在對機(jī)器學(xué)習(xí)有了一定經(jīng)驗(yàn)后再采用這種方法處理數(shù)據(jù)。

第三步,就是檢查各種機(jī)器學(xué)習(xí)算法,也就是實(shí)現(xiàn)一系列機(jī)器學(xué)習(xí)算法,并應(yīng)用在數(shù)據(jù)集上。

這里,你的工具箱應(yīng)當(dāng)包含以下幾種不同類型的機(jī)器學(xué)習(xí)算法:

線性模型(比如,邏輯回歸,線性 SVM)

非線性模型(比如 RBF SVM,梯度下降分類器)

樹和基于集成的模型(比如 決策樹和隨機(jī)森林)

神經(jīng)網(wǎng)絡(luò)(比如 多層感知機(jī),卷積神經(jīng)網(wǎng)絡(luò))

應(yīng)當(dāng)選擇比較魯棒(穩(wěn)定)的一系列機(jī)器學(xué)習(xí)模型來評估問題,因?yàn)槲覀兊哪繕?biāo)就是判斷哪種算法在當(dāng)前問題的性能很好,而哪些算法很糟糕。

決定好要采用的模型后,接下來就是訓(xùn)練模型并在數(shù)據(jù)集上測試,觀察每個模型在數(shù)據(jù)集上的性能結(jié)果。

在多次實(shí)驗(yàn)后,你可能就是有一種“第六感”,知道哪種算法更適用于哪種數(shù)據(jù)集。比如,你會發(fā)現(xiàn):

對于有很多特征的數(shù)據(jù)集,隨機(jī)森林算法的效果很不錯;

而邏輯回歸算法可以很好處理高維度的稀疏數(shù)據(jù);

對于圖像數(shù)據(jù),CNNs 的效果非常好。

而以上的經(jīng)驗(yàn)獲得,當(dāng)然就需要你多動手,多進(jìn)行實(shí)戰(zhàn)來深入了解不同的機(jī)器學(xué)習(xí)算法了!

開始動手吧!

接下來就開始敲代碼來實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法,并在上述兩個數(shù)據(jù)集上進(jìn)行測試。本教程的代碼文件目錄如下,包含四份代碼文件和一個3scenes文件夾,該文件夾就是三場景數(shù)據(jù)集,而Iris數(shù)據(jù)集直接采用scikit-learn庫載入即可。

├──3scenes│├──coast[360entries]│├──forest[328entries]│└──highway[260entries]├──classify_iris.py├──classify_images.py├──nn_iris.py└──basic_cnn.py

首先是實(shí)現(xiàn)classify_iris.py,這份代碼是采用機(jī)器學(xué)習(xí)算法來對Iris數(shù)據(jù)集進(jìn)行分類。

首先導(dǎo)入需要的庫:

fromsklearn.neighborsimportKNeighborsClassifierfromsklearn.naive_bayesimportGaussianNBfromsklearn.linear_modelimportLogisticRegressionfromsklearn.svmimportSVCfromsklearn.treeimportDecisionTreeClassifierfromsklearn.ensembleimportRandomForestClassifierfromsklearn.neural_networkimportMLPClassifierfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromsklearn.datasetsimportload_irisimportargparse#設(shè)置參數(shù)ap=argparse.ArgumentParser()ap.add_argument("-m","--model",type=str,default="knn",help="typeofpythonmachinelearningmodeltouse")args=vars(ap.parse_args())#定義一個保存模型的字典,根據(jù)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庫中就集成了我們將要實(shí)現(xiàn)的幾種機(jī)器學(xué)習(xí)算法的代碼,包括:

KNN

樸素貝葉斯

邏輯回歸

SVM

決策樹

隨機(jī)森林

感知機(jī)

我們直接調(diào)用sklearn中相應(yīng)的函數(shù)來實(shí)現(xiàn)對應(yīng)的算法即可,比如對于knn算法,直接調(diào)用sklearn.neighbors中的KNeighborsClassifier()即可,只需要設(shè)置參數(shù)n_neighbors,即最近鄰的個數(shù)。

這里直接用一個models的字典來保存不同模型的初始化,然后根據(jù)參數(shù)--model來調(diào)用對應(yīng)的模型,比如命令輸入python classify_irs.py --model knn就是調(diào)用knn算法模型。

接著就是載入數(shù)據(jù)部分:

print("[INFO]loadingdata...")dataset=load_iris()(trainX,testX,trainY,testY)=train_test_split(dataset.data,dataset.target,random_state=3,test_size=0.25)

這里直接調(diào)用sklearn.datasets中的load_iris()載入數(shù)據(jù),然后采用train_test_split來劃分訓(xùn)練集和數(shù)據(jù)集,這里是 75% 數(shù)據(jù)作為訓(xùn)練集,25% 作為測試集。

最后就是訓(xùn)練模型和預(yù)測部分:

#訓(xùn)練模型print("[INFO]using'{}'model".format(args["model"]))model=models[args["model"]]model.fit(trainX,trainY)#預(yù)測并輸出一份分類結(jié)果報(bào)告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#設(shè)置參數(shù)ap=argparse.ArgumentParser()ap.add_argument("-m","--model",type=str,default="knn",help="typeofpythonmachinelearningmodeltouse")args=vars(ap.parse_args())#定義一個保存模型的字典,根據(jù)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數(shù)據(jù)集,然后進(jìn)行訓(xùn)練集和測試集的劃分,75%數(shù)據(jù)作為訓(xùn)練集,其余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)#訓(xùn)練模型print("[INFO]using'{}'model".format(args["model"]))model=models[args["model"]]model.fit(trainX,trainY)#預(yù)測并輸出一份分類結(jié)果報(bào)告print("[INFO]evaluating")predictions=model.predict(testX)print(classification_report(testY,predictions,target_names=dataset.target_names))

接著就是采用三場景圖像數(shù)據(jù)集的分類預(yù)測代碼 classify_images.py ,跟 classify_iris.py 的代碼其實(shí)是比較相似的,首先導(dǎo)入庫部分,增加以下幾行代碼:

fromsklearn.preprocessingimportLabelEncoderfromPILimportImagefromimutilsimportpathsimportnumpyasnpimportos

其中LabelEncoder是為了將標(biāo)簽從字符串編碼為整型,然后其余幾項(xiàng)都是處理圖像相關(guān)。

對于圖像數(shù)據(jù),如果直接采用原始像素信息輸入模型中,大部分的機(jī)器學(xué)習(xí)算法效果都很不理想,所以這里采用特征提取方法,主要是統(tǒng)計(jì)圖像顏色通道的均值和標(biāo)準(zhǔn)差信息,總共是 RGB 3個通道,每個通道各計(jì)算均值和標(biāo)準(zhǔn)差,然后結(jié)合在一起,得到一個六維的特征,函數(shù)如下所示:

defextract_color_stats(image):'''將圖片分成RGB三通道,然后分別計(jì)算每個通道的均值和標(biāo)準(zhǔn)差,然后返回: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字典,代碼一樣,這里就不貼出來了,然后圖像載入部分的代碼如下:

#加載數(shù)據(jù)并提取特征print("[INFO]extractingimagefeatures...")imagePaths=paths.list_images(args['dataset'])data=[]labels=[]#循環(huán)遍歷所有的圖片數(shù)據(jù)forimagePathinimagePaths:#加載圖片,然后計(jì)算圖片的顏色通道統(tǒng)計(jì)信息image=Image.open(imagePath)features=extract_color_stats(image)data.append(features)#保存圖片的標(biāo)簽信息label=imagePath.split(os.path.sep)[-2]labels.append(label)#對標(biāo)簽進(jìn)行編碼,從字符串變?yōu)檎麛?shù)類型le=LabelEncoder()labels=le.fit_transform(labels)#進(jìn)行訓(xùn)練集和測試集的劃分,75%數(shù)據(jù)作為訓(xùn)練集,其余25%作為測試集(trainX,testX,trainY,testY)=train_test_split(data,labels,test_size=0.25)

上述代碼就完成從硬盤中加載圖片的路徑信息,然后依次遍歷,讀取圖片,提取特征,提取標(biāo)簽信息,保存特征和標(biāo)簽信息,接著編碼標(biāo)簽,然后就是劃分訓(xùn)練集和測試集。

接著是相同的訓(xùn)練模型和預(yù)測的代碼,同樣沒有任何改變,這里就不列舉出來了。

完整版如下:

fromsklearn.neighborsimportKNeighborsClassifierfromsklearn.naive_bayesimportGaussianNBfromsklearn.linear_modelimportLogisticRegressionfromsklearn.svmimportSVCfromsklearn.treeimportDecisionTreeClassifierfromsklearn.ensembleimportRandomForestClassifierfromsklearn.neural_networkimportMLPClassifierfromsklearn.preprocessingimportLabelEncoderfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromPILimportImagefromimutilsimportpathsimportnumpyasnpimportargparseimportosdefextract_color_stats(image):'''將圖片分成RGB三通道,然后分別計(jì)算每個通道的均值和標(biāo)準(zhǔn)差,然后返回: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#設(shè)置參數(shù)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())#定義一個保存模型的字典,根據(jù)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()}#加載數(shù)據(jù)并提取特征print("[INFO]extractingimagefeatures...")imagePaths=paths.list_images(args['dataset'])data=[]labels=[]#循環(huán)遍歷所有的圖片數(shù)據(jù)forimagePathinimagePaths:#加載圖片,然后計(jì)算圖片的顏色通道統(tǒng)計(jì)信息image=Image.open(imagePath)features=extract_color_stats(image)data.append(features)#保存圖片的標(biāo)簽信息label=imagePath.split(os.path.sep)[-2]labels.append(label)#對標(biāo)簽進(jìn)行編碼,從字符串變?yōu)檎麛?shù)類型le=LabelEncoder()labels=le.fit_transform(labels)#進(jìn)行訓(xùn)練集和測試集的劃分,75%數(shù)據(jù)作為訓(xùn)練集,其余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)))#訓(xùn)練模型print("[INFO]using'{}'model".format(args["model"]))model=models[args["model"]]model.fit(trainX,trainY)#預(yù)測并輸出分類結(jié)果報(bào)告print("[INFO]evaluating...")predictions=model.predict(testX)print(classification_report(testY,predictions,target_names=le.classes_))

完成這兩份代碼后,我們就可以開始運(yùn)行下代碼,對比不同算法在兩個數(shù)據(jù)集上的性能。

因?yàn)槠脑颍@里我會省略原文對每個算法的介紹,具體的可以查看之前我寫的對機(jī)器學(xué)習(xí)算法的介紹:

常用機(jī)器學(xué)習(xí)算法匯總比較(上)

常用機(jī)器學(xué)習(xí)算法匯總比較(中)

常用機(jī)器學(xué)習(xí)算法匯總比較(完)

KNN

這里我們先運(yùn)行下classify_irs.py,調(diào)用默認(rèn)的模型knn,看下KNN在Iris數(shù)據(jù)集上的實(shí)驗(yàn)結(jié)果,如下所示:

其中主要是給出了對每個類別的精確率、召回率、F1 以及該類別測試集數(shù)量,即分別對應(yīng)precision,recall,f1-score,support。根據(jù)最后一行第一列,可以看到KNN取得95%的準(zhǔn)確率。

接著是在三場景圖片數(shù)據(jù)集上的實(shí)驗(yàn)結(jié)果:

這里KNN取得72%的準(zhǔn)確率。

(ps:實(shí)際上,運(yùn)行這個算法,不同次數(shù)會有不同的結(jié)果,原文作者給出的是 75%,其主要原因是因?yàn)樵趧澐钟?xùn)練集和測試集的時候,代碼沒有設(shè)置參數(shù)random_state,這導(dǎo)致每次運(yùn)行劃分的訓(xùn)練集和測試集的圖片都是不同的,所以運(yùn)行結(jié)果也會不相同!)

樸素貝葉斯

接著是樸素貝葉斯算法,分別測試兩個數(shù)據(jù)集,結(jié)果如下:

同樣,樸素貝葉斯在Iris上有98%的準(zhǔn)確率,但是在圖像數(shù)據(jù)集上僅有63%的準(zhǔn)確率。

那么,我們是否可以說明KNN算法比樸素貝葉斯好呢?

當(dāng)然是不可以的,上述結(jié)果只能說明在三場景圖像數(shù)據(jù)集上,KNN算法優(yōu)于樸素貝葉斯算法。

實(shí)際上,每種算法都有各自的優(yōu)缺點(diǎn)和適用場景,不能一概而論地說某種算法任何時候都優(yōu)于另一種算法,這需要具體問題具體分析。

邏輯回歸

接著是邏輯回歸算法,分別測試兩個數(shù)據(jù)集,結(jié)果如下:

同樣,邏輯回歸在Iris上有98%的準(zhǔn)確率,但是在圖像數(shù)據(jù)集上僅有77%的準(zhǔn)確率(對比原文作者的邏輯回歸準(zhǔn)確率是 69%)

支持向量機(jī) SVM

接著是 SVM 算法,分別測試兩個數(shù)據(jù)集,結(jié)果如下:

同樣,SVM 在Iris上有98%的準(zhǔn)確率,但是在圖像數(shù)據(jù)集上僅有76%的準(zhǔn)確率(對比原文作者的準(zhǔn)確率是 83%,主要是發(fā)現(xiàn)類別coast差別有些大)

決策樹

接著是決策樹算法,分別測試兩個數(shù)據(jù)集,結(jié)果如下:

同樣,決策樹在Iris上有98%的準(zhǔn)確率,但是在圖像數(shù)據(jù)集上僅有71%的準(zhǔn)確率(對比原文作者的決策樹準(zhǔn)確率是 74%)

隨機(jī)森林

接著是隨機(jī)森林算法,分別測試兩個數(shù)據(jù)集,結(jié)果如下:

同樣,隨機(jī)森林在Iris上有96%的準(zhǔn)確率,但是在圖像數(shù)據(jù)集上僅有77%的準(zhǔn)確率(對比原文作者的決策樹準(zhǔn)確率是 84%)

注意了,一般如果決策樹算法的效果還不錯的話,隨機(jī)森林算法應(yīng)該也會取得不錯甚至更好的結(jié)果,這是因?yàn)殡S機(jī)森林實(shí)際上就是多棵決策樹通過集成學(xué)習(xí)方法組合在一起進(jìn)行分類預(yù)測。

多層感知機(jī)

最后是多層感知機(jī)算法,分別測試兩個數(shù)據(jù)集,結(jié)果如下:

同樣,多層感知機(jī)在Iris上有98%的準(zhǔn)確率,但是在圖像數(shù)據(jù)集上僅有79%的準(zhǔn)確率(對比原文作者的決策樹準(zhǔn)確率是 81%).

深度學(xué)習(xí)以及深度神經(jīng)網(wǎng)絡(luò)

神經(jīng)網(wǎng)絡(luò)

最后是實(shí)現(xiàn)深度學(xué)習(xí)的算法,也就是nn_iris.py和basic_cnn.py這兩份代碼。

(這里需要注意TensorFlow和Keras的版本問題,我采用的是TF=1.2和Keras=2.1.5)

首先是nn_iris.py的實(shí)現(xiàn),同樣首先是導(dǎo)入庫和數(shù)據(jù)的處理:

fromkeras.modelsimportSequentialfromkeras.layers.coreimportDensefromkeras.optimizersimportSGDfromsklearn.preprocessingimportLabelBinarizerfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromsklearn.datasetsimportload_iris#載入Iris數(shù)據(jù)集,然后進(jìn)行訓(xùn)練集和測試集的劃分,75%數(shù)據(jù)作為訓(xùn)練集,其余25%作為測試集print("[INFO]loadingdata...")dataset=load_iris()(trainX,testX,trainY,testY)=train_test_split(dataset.data,dataset.target,test_size=0.25)#將標(biāo)簽進(jìn)行one-hot編碼lb=LabelBinarizer()trainY=lb.fit_transform(trainY)testY=lb.transform(testY)

這里我們將采用Keras來實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò),然后這里需要將標(biāo)簽進(jìn)行one-hot編碼,即獨(dú)熱編碼。

接著就是搭建網(wǎng)絡(luò)模型的結(jié)構(gòu)和訓(xùn)練、預(yù)測代碼:

#利用Keras定義網(wǎng)絡(luò)模型model=Sequential()model.add(Dense(3,input_shape=(4,),activation="sigmoid"))model.add(Dense(3,activation="sigmoid"))model.add(Dense(3,activation="softmax"))#采用梯度下降訓(xùn)練模型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)#預(yù)測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 層全連接層的神經(jīng)網(wǎng)絡(luò),前兩層采用Sigmoid激活函數(shù),然后最后一層是輸出層,所以采用softmax將輸出變成概率值。接著就是定義了使用SGD的優(yōu)化算法,損失函數(shù)是categorical_crossentropy,迭代次數(shù)是 250 次,batch_size是 16。

完整版如下:

fromkeras.modelsimportSequentialfromkeras.layers.coreimportDensefromkeras.optimizersimportSGDfromsklearn.preprocessingimportLabelBinarizerfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromsklearn.datasetsimportload_iris#載入Iris數(shù)據(jù)集,然后進(jìn)行訓(xùn)練集和測試集的劃分,75%數(shù)據(jù)作為訓(xùn)練集,其余25%作為測試集print("[INFO]loadingdata...")dataset=load_iris()(trainX,testX,trainY,testY)=train_test_split(dataset.data,dataset.target,test_size=0.25)#將標(biāo)簽進(jìn)行one-hot編碼lb=LabelBinarizer()trainY=lb.fit_transform(trainY)testY=lb.transform(testY)#利用Keras定義網(wǎng)絡(luò)模型model=Sequential()model.add(Dense(3,input_shape=(4,),activation="sigmoid"))model.add(Dense(3,activation="sigmoid"))model.add(Dense(3,activation="softmax"))#采用梯度下降訓(xùn)練模型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)#預(yù)測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))

直接運(yùn)行命令python nn_iris.py, 輸出的結(jié)果如下:

這里得到的是 100% 的準(zhǔn)確率,和原文的一樣。當(dāng)然實(shí)際上原文給出的結(jié)果如下圖所示,可以看到其實(shí)類別數(shù)量上是不相同的。

CNN

最后就是實(shí)現(xiàn)basic_cnn.py這份代碼了。

同樣首先是導(dǎo)入必須的庫函數(shù):

fromkeras.modelsimportSequentialfromkeras.layers.convolutionalimportConv2Dfromkeras.layers.convolutionalimportMaxPooling2Dfromkeras.layers.coreimportActivationfromkeras.layers.coreimportFlattenfromkeras.layers.coreimportDensefromkeras.optimizersimportAdamfromsklearn.preprocessingimportLabelBinarizerfromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_reportfromPILimportImagefromimutilsimportpathsimportnumpyasnpimportargparseimportos#配置參數(shù)ap=argparse.ArgumentParser()ap.add_argument("-d","--dataset",type=str,default="3scenes",help="pathtodirectorycontainingthe'3scenes'dataset")args=vars(ap.parse_args())

同樣是要導(dǎo)入Keras來建立CNN的網(wǎng)絡(luò)模型,另外因?yàn)槭翘幚韴D像數(shù)據(jù),所以PIL、imutils也是要導(dǎo)入的。

然后是加載數(shù)據(jù)和劃分訓(xùn)練集和測試集,對于加載數(shù)據(jù),這里直接采用原始圖像像素?cái)?shù)據(jù),只需要對圖像數(shù)據(jù)做統(tǒng)一尺寸的調(diào)整,這里是統(tǒng)一調(diào)整為 32×32,并做歸一化到[0,1]的范圍。

#加載數(shù)據(jù)并提取特征print("[INFO]extractingimagefeatures...")imagePaths=paths.list_images(args['dataset'])data=[]labels=[]#循環(huán)遍歷所有的圖片數(shù)據(jù)forimagePathinimagePaths:#加載圖片,然后調(diào)整成32×32大小,并做歸一化到[0,1]image=Image.open(imagePath)image=np.array(image.resize((32,32)))/255.0data.append(image)#保存圖片的標(biāo)簽信息label=imagePath.split(os.path.sep)[-2]labels.append(label)#對標(biāo)簽編碼,從字符串變?yōu)檎蚻b=LabelBinarizer()labels=lb.fit_transform(labels)#劃分訓(xùn)練集和測試集(trainX,testX,trainY,testY)=train_test_split(np.array(data),np.array(labels),test_size=0.25)

接著定義了一個 4 層的CNN網(wǎng)絡(luò)結(jié)構(gòu),包含 3 層卷積層和最后一層輸出層,優(yōu)化算法采用的是Adam而不是SGD。代碼如下所示:

#定義CNN網(wǎng)絡(luò)模型結(jié)構(gòu)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"))#訓(xùn)練模型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)#預(yù)測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#配置參數(shù)ap=argparse.ArgumentParser()ap.add_argument("-d","--dataset",type=str,default="3scenes",help="pathtodirectorycontainingthe'3scenes'dataset")args=vars(ap.parse_args())#加載數(shù)據(jù)并提取特征print("[INFO]extractingimagefeatures...")imagePaths=paths.list_images(args['dataset'])data=[]labels=[]#循環(huán)遍歷所有的圖片數(shù)據(jù)forimagePathinimagePaths:#加載圖片,然后調(diào)整成32×32大小,并做歸一化到[0,1]image=Image.open(imagePath)image=np.array(image.resize((32,32)))/255.0data.append(image)#保存圖片的標(biāo)簽信息label=imagePath.split(os.path.sep)[-2]labels.append(label)#對標(biāo)簽編碼,從字符串變?yōu)檎蚻b=LabelBinarizer()labels=lb.fit_transform(labels)#劃分訓(xùn)練集和測試集(trainX,testX,trainY,testY)=train_test_split(np.array(data),np.array(labels),test_size=0.25)#定義CNN網(wǎng)絡(luò)模型結(jié)構(gòu)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"))#訓(xùn)練模型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)#預(yù)測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_))

運(yùn)行命令python basic_cnn.py, 輸出結(jié)果如下:

CNN的準(zhǔn)確率是達(dá)到90%,它是優(yōu)于之前的幾種機(jī)器學(xué)習(xí)算法的結(jié)果。

小結(jié)

最后,這僅僅是一份對機(jī)器學(xué)習(xí)完全是初學(xué)者的教程,其實(shí)就是簡單調(diào)用現(xiàn)有的庫來實(shí)現(xiàn)對應(yīng)的機(jī)器學(xué)習(xí)算法,讓初學(xué)者簡單感受下如何使用機(jī)器學(xué)習(xí)算法,正如同在學(xué)習(xí)編程語言的時候,對著書本的代碼例子敲起來,然后運(yùn)行代碼,看看自己寫出來的程序的運(yùn)行結(jié)果。

通過這份簡單的入門教程,你應(yīng)該明白的是:

沒有任何一種算法是完美的,可以完全適用所有的場景,即便是目前很熱門的深度學(xué)習(xí)方法,也存在它的局限性,所以應(yīng)該具體問題具體分析!

記住開頭推薦的 5 步機(jī)器學(xué)習(xí)操作流程,這里再次復(fù)習(xí)一遍:

評估你的問題

準(zhǔn)備數(shù)據(jù)(原始數(shù)據(jù)、特征提取、特征工程等等)

檢查各種機(jī)器學(xué)習(xí)算法

檢驗(yàn)實(shí)驗(yàn)結(jié)果

深入了解性能最好的算法

最后一點(diǎn),是我運(yùn)行算法結(jié)果,和原文作者的結(jié)果會不相同,這實(shí)際上就是每次采樣數(shù)據(jù),劃分訓(xùn)練集和測試集不相同的原因!這其實(shí)也說明了數(shù)據(jù)非常重要,對于機(jī)器學(xué)習(xí)來說,好的數(shù)據(jù)很重要!

接著,根據(jù)這份教程,你可以繼續(xù)進(jìn)一步了解每種機(jī)器學(xué)習(xí)算法,了解每種算法的基本原理和實(shí)現(xiàn),嘗試自己手動實(shí)現(xiàn),而不是簡單調(diào)用現(xiàn)有的庫,這樣更加能加深印象,這里推薦《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》,經(jīng)典的機(jī)器學(xué)習(xí)算法都有介紹,并且都會帶你一步步實(shí)現(xiàn)算法!

最后,極力推薦大家去閱讀下原文作者的博客,原文作者也是一個大神,他的博客地址如下:https://www.pyimagesearch.com/

他的博客包含了 Opencv、Python、機(jī)器學(xué)習(xí)和深度學(xué)習(xí)方面的教程和文章,而且作者喜歡通過實(shí)戰(zhàn)學(xué)習(xí),所以很多文章都是通過一些實(shí)戰(zhàn)練習(xí)來學(xué)習(xí)某個知識點(diǎn)或者某個算法,正如同本文通過實(shí)現(xiàn)這幾種常見的機(jī)器學(xué)習(xí)算法在兩個不同類型數(shù)據(jù)集上的實(shí)戰(zhàn)來帶領(lǐng)初學(xué)者入門機(jī)器學(xué)習(xí)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 機(jī)器學(xué)習(xí)

    關(guān)注

    66

    文章

    8306

    瀏覽量

    131840
  • python
    +關(guān)注

    關(guān)注

    53

    文章

    4753

    瀏覽量

    84071
  • 數(shù)據(jù)集
    +關(guān)注

    關(guān)注

    4

    文章

    1197

    瀏覽量

    24535

原文標(biāo)題:初學(xué)者的機(jī)器學(xué)習(xí)入門實(shí)戰(zhàn)教程!

文章出處:【微信號:rgznai100,微信公眾號:rgznai100】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    手把手教你制作機(jī)器

    手把手教你制作機(jī)器
    發(fā)表于 08-12 09:52

    原創(chuàng)手把手教你學(xué)習(xí)FPGA視頻教程,不看后悔喲

    很多囊中羞澀的初學(xué)者只能望板興嘆。針對現(xiàn)狀,推出了此款初學(xué)者能買得起的開發(fā)板,并以此開發(fā)板為硬件平臺,推出手把手教你學(xué)習(xí)FPGA原創(chuàng)視頻教程,帶領(lǐng)初學(xué)者輕松走進(jìn)FPGA設(shè)計(jì)開發(fā)的大門,手把手
    發(fā)表于 08-14 16:24

    手把手教你學(xué)習(xí)STM32

    手把手教你學(xué)習(xí)STM32
    發(fā)表于 12-17 07:18

    手把手教你構(gòu)建一個完整的工程

    手把手教你構(gòu)建一個完整的工程
    發(fā)表于 08-03 09:54 ?33次下載
    <b class='flag-5'>手把手</b><b class='flag-5'>教你</b>構(gòu)建一個完整的工程

    手把手教你寫批處理-批處理的介紹

    手把手教你寫批處理-批處理的介紹
    發(fā)表于 10-25 15:02 ?69次下載

    美女手把手教你如何裝機(jī)(中)

    美女手把手教你如何裝機(jī)(中) 再來是硬碟的部份,這款機(jī)殼還不錯,可以旋轉(zhuǎn)支架~
    發(fā)表于 01-27 11:14 ?1420次閱讀

    美女手把手教你如何裝機(jī)(下)

    美女手把手教你如何裝機(jī)(下) 接著下來就是今天的重頭戲,開核蘿!~
    發(fā)表于 01-27 11:16 ?2905次閱讀

    手把手教你學(xué)習(xí)FPGA—LED篇

    電子專業(yè)單片機(jī)相關(guān)知識學(xué)習(xí)教材資料——手把手教你學(xué)習(xí)FPGA—LED篇
    發(fā)表于 08-08 17:19 ?0次下載

    手把手教你安裝Quartus II

    本章手把手把教你如何安裝 Quartus II 軟件 ,并將它激活 。此外 還有USB -Blaster下載器的驅(qū)動安裝步驟 。
    發(fā)表于 09-18 14:55 ?9次下載

    手把手教你在家搭建監(jiān)控系統(tǒng)

    手把手教你在家搭建監(jiān)控系統(tǒng)
    發(fā)表于 01-17 19:47 ?25次下載

    手把手教你如何開始DSP編程

    手把手教你如何開始DSP編程。
    發(fā)表于 04-09 11:54 ?12次下載
    <b class='flag-5'>手把手</b><b class='flag-5'>教你</b>如何開始DSP編程

    手把手教你學(xué)LabVIEW視覺設(shè)計(jì)

    手把手教你學(xué)LabVIEW視覺設(shè)計(jì)手把手教你學(xué)LabVIEW視覺設(shè)計(jì)手把手教你學(xué)LabVIEW視
    發(fā)表于 03-06 01:41 ?2991次閱讀

    手把手教你開關(guān)電源PCB排板

    手把手教你開關(guān)電源PCB排板(新型電源技術(shù))-分享一下開關(guān)電源PCB排板的基本要點(diǎn)及分析,以及例子講解。絕對的手把手
    發(fā)表于 09-18 12:27 ?57次下載
    <b class='flag-5'>手把手</b><b class='flag-5'>教你</b>開關(guān)電源PCB排板

    手把手教你學(xué)習(xí)Spyglass工具

    作為IC設(shè)計(jì)人員,熟練掌握數(shù)字前端語法檢查工具Spyglass的重要性不言而喻,本文手把手教你學(xué)習(xí)Spyglass工具。
    的頭像 發(fā)表于 04-03 10:46 ?2372次閱讀

    手把手教你學(xué)FPGA仿真

    電子發(fā)燒友網(wǎng)站提供《手把手教你學(xué)FPGA仿真.pdf》資料免費(fèi)下載
    發(fā)表于 10-19 09:17 ?2次下載
    <b class='flag-5'>手把手</b><b class='flag-5'>教你</b>學(xué)FPGA仿真