原文連接:www.pyimagesearch.com/2019/01/14/…python
做者:Adrian Rosebrockgit
這是一篇手把手教你使用 Python 實現機器學習算法,並在數值型數據和圖像數據集上運行模型的入門教程,當你看完本文後,你應當能夠開始你的機器學習之旅了!程序員
本教程會採用下述兩個庫來實現機器學習算法:算法
此外,你還將學習到:shell
在本文會用到的機器學習算法包括:編程
開始本教程前,須要先確保安裝了一下的 Python 庫:bash
--upgrade
)安裝命令以下,推薦採用虛擬環境(好比利用 anaconda 建立一個新的環境):微信
$ pip install numpy
$ pip install pillow
$ pip install --upgrade scikit-learn
$ pip install tensorflow # or tensorflow-gpu
$ pip install keras
$ pip install opencv-contrib-python
$ pip install --upgrade imutils
複製代碼
本教程會用到兩個數據集來幫助更好的瞭解每一個機器學習算法的性能。網絡
第一個數據集是 Iris(鳶尾花) 數據集。這個數據集的地位,至關於你剛開始學習一門編程語言時,敲下的 「Hello,World!」app
這個數據集是一個數值型的數據,以下圖所示,其實就是一個表格數據,每一行表明一個樣本,而後每一列就是不一樣的屬性。這個數據集主要是收集了三種不一樣的鳶尾花的數據,分別爲:
對應圖中最後一列 Class label
,而後還有四種屬性,分別是:
這個數據集多是最簡單的機器學習數據集之一了,一般是用於教導程序員和工程師的機器學習和模式識別基礎的數據集。
對於該數據集,咱們的目標就是根據給定的四個屬性,訓練一個機器學習模型來正確分類每一個樣本的類別。
須要注意的是,其中有一個類別和另外兩個類別是線性可分的,但這兩個類別之間卻並不是線性可分,因此咱們須要採用一個非線性模型來對它們進行分類。固然了,在現實生活中,採用非線性模型的機器學習算法是很是常見的。
第二個數據集是一個三場景的圖像數據集。這是幫助初學者學習如何處理圖像數據,而且哪一種算法在這兩種數據集上性能最優。
下圖是這個三場景數據集的部分圖片例子,它包括森林、高速公路和海岸線三種場景,總共是 948 張圖片,每一個類別的具體圖片數量以下:
這個三場景數據集是採樣於一個八場景數據集中,做者是 Oliva 和 Torralba 的 2001 年的一篇論文,Modeling the shape of the scene: a holistic representation of the spatial envelope
不管何時實現機器學習算法,推薦採用以下流程來開始:
這個流程會隨着你機器學習方面的經驗的積累而改善和優化,但對於初學者,這是我建議入門機器學習時採用的流程。
因此,如今開始吧!第一步,就是評估咱們的問題,問一下本身:
最後一個問題很是重要,隨着你使用 Python 實現機器學習的次數的增長,你也會隨之得到更多的經驗。根據以前的經驗,你可能知道有一種算法的性能還不錯。
所以,接着就是準備數據,也就是數據預處理以及特徵工程了。
通常來講,這一步,包括了從硬盤中載入數據,檢查數據,而後決定是否須要作特徵提取或者特徵工程。
特徵提取就是應用某種算法經過某種方式來量化數據的過程。好比,對於圖像數據,咱們能夠採用計算直方圖的方法來統計圖像中像素強度的分佈,經過這種方式,咱們就獲得描述圖像顏色的特徵。
而特徵工程則是將原始輸入數據轉換成一個更好描述潛在問題的特徵表示的過程。固然特徵工程是一項更先進的技術,這裏建議在對機器學習有了必定經驗後再採用這種方法處理數據。
第三步,就是檢查各類機器學習算法,也就是實現一系列機器學習算法,並應用在數據集上。
這裏,你的工具箱應當包含如下幾種不一樣類型的機器學習算法:
應當選擇比較魯棒(穩定)的一系列機器學習模型來評估問題,由於咱們的目標就是判斷哪一種算法在當前問題的性能很好,而哪些算法很糟糕。
決定好要採用的模型後,接下來就是訓練模型並在數據集上測試,觀察每一個模型在數據集上的性能結果。
在屢次實驗後,你可能就是有一種「第六感」,知道哪一種算法更適用於哪一種數據集。
好比,你會發現:
而以上的經驗得到,固然就須要你多動手,多進行實戰來深刻了解不一樣的機器學習算法了!
接下來就開始敲代碼來實現機器學習算法,並在上述兩個數據集上進行測試。本教程的代碼文件目錄以下,包含四份代碼文件和一個 3scenes
文件夾,該文件夾就是三場景數據集,而 Iris
數據集直接採用 scikit-learn
庫載入便可。
├── 3scenes
│ ├── coast [360 entries]
│ ├── forest [328 entries]
│ └── highway [260 entries]
├── classify_iris.py
├── classify_images.py
├── nn_iris.py
└── basic_cnn.py
複製代碼
代碼和數據集文件能夠在公衆號後臺,也就是公衆號會話界面回覆 『py_ml』獲取!
首先是實現 classify_iris.py
,這份代碼是採用機器學習算法來對 Iris
數據集進行分類。
首先導入須要的庫:
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import load_iris
import argparse
# 設置參數
ap = argparse.ArgumentParser()
ap.add_argument("-m", "--model", type=str, default="knn", help="type of python machine learning model to use")
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
庫中就集成了咱們將要實現的幾種機器學習算法的代碼,包括:
咱們直接調用 sklearn
中相應的函數來實現對應的算法便可,好比對於 knn
算法,直接調用 sklearn.neighbors
中的 KNeighborsClassifier()
便可,只須要設置參數 n_neighbors
,即最近鄰的個數。
這裏直接用一個 models
的字典來保存不一樣模型的初始化,而後根據參數 --model
來調用對應的模型,好比命令輸入 python classify_irs.py --model knn
就是調用 knn
算法模型。
接着就是載入數據部分:
print("[INFO] loading data...")
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))
複製代碼
完整版代碼代碼以下:
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import load_iris
import argparse
# 設置參數
ap = argparse.ArgumentParser()
ap.add_argument("-m", "--model", type=str, default="knn", help="type of python machine learning model to use")
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] loading data...")
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
的代碼實際上是比較類似的,首先導入庫部分,增長如下幾行代碼:
from sklearn.preprocessing import LabelEncoder
from PIL import Image
from imutils import paths
import numpy as np
import os
複製代碼
其中 LabelEncoder
是爲了將標籤從字符串編碼爲整型,而後其他幾項都是處理圖像相關。
對於圖像數據,若是直接採用原始像素信息輸入模型中,大部分的機器學習算法效果都很不理想,因此這裏採用特徵提取方法,主要是統計圖像顏色通道的均值和標準差信息,總共是 RGB 3個通道,每一個通道各計算均值和標準差,而後結合在一塊兒,獲得一個六維的特徵,函數以下所示:
def extract_color_stats(image):
''' 將圖片分紅 RGB 三通道,而後分別計算每一個通道的均值和標準差,而後返回 :param image: :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)]
return features
複製代碼
而後一樣會定義一個 models
字典,代碼同樣,這裏就不貼出來了,而後圖像載入部分的代碼以下:
# 加載數據並提取特徵
print("[INFO] extracting image features...")
imagePaths = paths.list_images(args['dataset'])
data = []
labels = []
# 循環遍歷全部的圖片數據
for imagePath in imagePaths:
# 加載圖片,而後計算圖片的顏色通道統計信息
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)
複製代碼
上述代碼就完成從硬盤中加載圖片的路徑信息,而後依次遍歷,讀取圖片,提取特徵,提取標籤信息,保存特徵和標籤信息,接着編碼標籤,而後就是劃分訓練集和測試集。
接着是相同的訓練模型和預測的代碼,一樣沒有任何改變,這裏就不列舉出來了。
完整版以下:
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from PIL import Image
from imutils import paths
import numpy as np
import argparse
import os
def extract_color_stats(image):
''' 將圖片分紅 RGB 三通道,而後分別計算每一個通道的均值和標準差,而後返回 :param image: :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)]
return features
# 設置參數
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", type=str, default="3scenes",
help="path to directory containing the '3scenes' dataset")
ap.add_argument("-m", "--model", type=str, default="knn",
help="type of python machine learning model to use")
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] extracting image features...")
imagePaths = paths.list_images(args['dataset'])
data = []
labels = []
# 循環遍歷全部的圖片數據
for imagePath in imagePaths:
# 加載圖片,而後計算圖片的顏色通道統計信息
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('trainX numbers={}, testX numbers={}'.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_))
複製代碼
完成這兩份代碼後,咱們就能夠開始運行下代碼,對比不一樣算法在兩個數據集上的性能。
由於篇幅的緣由,這裏我會省略原文對每一個算法的介紹,具體的能夠查看以前我寫的對機器學習算法的介紹:
這裏咱們先運行下 classify_irs
,調用默認的模型 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 在 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
的實現,一樣首先是導入庫和數據的處理:
from keras.models import Sequential
from keras.layers.core import Dense
from keras.optimizers import SGD
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import load_iris
# 載入 Iris 數據集,而後進行訓練集和測試集的劃分,75%數據做爲訓練集,其他25%做爲測試集
print("[INFO] loading data...")
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] training network...')
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] evaluating network...')
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。
完整版以下:
from keras.models import Sequential
from keras.layers.core import Dense
from keras.optimizers import SGD
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import load_iris
# 載入 Iris 數據集,而後進行訓練集和測試集的劃分,75%數據做爲訓練集,其他25%做爲測試集
print("[INFO] loading data...")
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] training network...')
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] evaluating network...')
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% 的準確率,和原文的同樣。固然實際上原文給出的結果以下圖所示,能夠看到其實類別數量上是不相同的。
最後就是實現 basic_cnn.py
這份代碼了。
一樣首先是導入必須的庫函數:
from keras.models import Sequential
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation
from keras.layers.core import Flatten
from keras.layers.core import Dense
from keras.optimizers import Adam
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from PIL import Image
from imutils import paths
import numpy as np
import argparse
import os
# 配置參數
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", type=str, default="3scenes",
help="path to directory containing the '3scenes' dataset")
args = vars(ap.parse_args())
複製代碼
一樣是要導入 Keras
來創建 CNN
的網絡模型,另外由於是處理圖像數據,因此 PIL
、imutils
也是要導入的。
而後是加載數據和劃分訓練集和測試集,對於加載數據,這裏直接採用原始圖像像素數據,只須要對圖像數據作統一尺寸的調整,這裏是統一調整爲 32×32,並作歸一化到 [0,1]
的範圍。
# 加載數據並提取特徵
print("[INFO] extracting image features...")
imagePaths = paths.list_images(args['dataset'])
data = []
labels = []
# 循環遍歷全部的圖片數據
for imagePath in imagePaths:
# 加載圖片,而後調整成 32×32 大小,並作歸一化到 [0,1]
image = Image.open(imagePath)
image = np.array(image.resize((32, 32))) / 255.0
data.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] training network...")
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] evaluating network...")
predictions = model.predict(testX, batch_size=32)
print(classification_report(testY.argmax(axis=1),
predictions.argmax(axis=1), target_names=lb.classes_))
複製代碼
完整版以下:
from keras.models import Sequential
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation
from keras.layers.core import Flatten
from keras.layers.core import Dense
from keras.optimizers import Adam
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from PIL import Image
from imutils import paths
import numpy as np
import argparse
import os
# 配置參數
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", type=str, default="3scenes",
help="path to directory containing the '3scenes' dataset")
args = vars(ap.parse_args())
# 加載數據並提取特徵
print("[INFO] extracting image features...")
imagePaths = paths.list_images(args['dataset'])
data = []
labels = []
# 循環遍歷全部的圖片數據
for imagePath in imagePaths:
# 加載圖片,而後調整成 32×32 大小,並作歸一化到 [0,1]
image = Image.open(imagePath)
image = np.array(image.resize((32, 32))) / 255.0
data.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] training network...")
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] evaluating network...")
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%,它是優於以前的幾種機器學習算法的結果。
最後,這僅僅是一份對機器學習徹底是初學者的教程,其實就是簡單調用現有的庫來實現對應的機器學習算法,讓初學者簡單感覺下如何使用機器學習算法,正如同在學習編程語言的時候,對着書本的代碼例子敲起來,而後運行代碼,看看本身寫出來的程序的運行結果。
經過這份簡單的入門教程,你應該明白的是:
接着,根據這份教程,你能夠繼續進一步瞭解每種機器學習算法,瞭解每種算法的基本原理和實現,嘗試本身手動實現,而不是簡單調用現有的庫,這樣更加能加深印象,這裏推薦《機器學習實戰》,經典的機器學習算法都有介紹,而且都會帶你一步步實現算法!
最後,極力推薦你們去閱讀下原文做者的博客,原文做者也是一個大神,他的博客地址以下:
他的博客包含了 Opencv、Python、機器學習和深度學習方面的教程和文章,並且做者喜歡經過實戰學習,因此不少文章都是經過一些實戰練習來學習某個知識點或者某個算法,正如同本文經過實現這幾種常見的機器學習算法在兩個不一樣類型數據集上的實戰來帶領初學者入門機器學習。
對該教程的代碼和數據集獲取方式以下:
歡迎關注個人微信公衆號--機器學習與計算機視覺,或者掃描下方的二維碼,你們一塊兒交流,學習和進步!