基於Tensorflow + Opencv 實現CNN自定義圖像分類
摘要:本篇文章主要通過Tensorflow+Opencv實現CNN自定義圖像分類案例,它能解決我們現實論文或實踐中的圖像分類問題,並與機器學習的圖像分類算法進行對比實驗。
本文分享自華為雲社區《Tensorflow+Opencv實現CNN自定義圖像分類及與KNN圖像分類對比》,作者:eastmount 。
一.圖像分類
圖像分類(Image Classification)是對圖像內容進行分類的問題,它利用計算機對圖像進行定量分析,把圖像或圖像中的區域劃分為若干個類別,以代替人的視覺判斷。圖像分類的傳統方法是特徵描述及檢測,這類傳統方法可能對於一些簡單的圖像分類是有效的,但由於實際情況非常複雜,傳統的分類方法不堪重負。現在,廣泛使用機器學習和深度學習的方法來處理圖像分類問題,其主要任務是給定一堆輸入圖片,將其指派到一個已知的混合類別中的某個標籤。
在下圖中,圖像分類模型將獲取單個圖像,並將為4個標籤{cat,dog,hat,mug},分別對應概率{0.6, 0.3, 0.05, 0.05},其中0.6表示圖像標籤為貓的概率,其餘類比。該圖像被表示為一個三維數組。在這個例子中,貓的圖像寬度為248像素,高度為400像素,並具有紅綠藍三個顏色通道(通常稱為RGB)。因此,圖像由248×400×3個數字組成或總共297600個數字,每個數字是一個從0(黑色)到255(白色)的整數。圖像分類的任務是將這接近30萬個數字變成一個單一的標籤,如「貓(cat)」。
那麼,如何編寫一個圖像分類的算法呢?又怎麼從眾多圖像中識別出貓呢?這裡所採取的方法和教育小孩看圖識物類似,給出很多圖像數據,讓模型不斷去學習每個類的特徵。在訓練之前,首先需要對訓練集的圖像進行分類標註,如圖所示,包括cat、dog、mug和hat四類。在實際工程中,可能有成千上萬類別的物體,每個類別都會有上百萬張圖像。
圖像分類是輸入一堆圖像的像素值數組,然後給它分配一個分類標籤,通過訓練學習來建立算法模型,接着使用該模型進行圖像分類預測,具體流程如下:
- 輸入: 輸入包含N個圖像的集合,每個圖像的標籤是K種分類標籤中的一種,這個集合稱為訓練集。
- 學習: 第二步任務是使用訓練集來學習每個類的特徵,構建訓練分類器或者分類模型。
- 評價: 通過分類器來預測新輸入圖像的分類標籤,並以此來評價分類器的質量。通過分類器預測的標籤和圖像真正的分類標籤對比,從而評價分類算法的好壞。如果分類器預測的分類標籤和圖像真正的分類標籤一致,表示預測正確,否則預測錯誤。
常見的分類算法包括樸素貝葉斯分類器、決策樹、K最近鄰分類算法、支持向量機、神經網絡和基於規則的分類算法等,同時還有用於組合單一類方法的集成學習算法,如Bagging和Boosting等。
二.基於KNN算法的圖像分類
1.KNN算法
K最近鄰分類(K-Nearest Neighbor Classifier)算法是一種基於實例的分類方法,是數據挖掘分類技術中最簡單常用的方法之一。該算法的核心思想是從訓練樣本中尋找所有訓練樣本X中與測試樣本距離(歐氏距離)最近的前K個樣本(作為相似度),再選擇與待分類樣本距離最小的K個樣本作為X的K個最鄰近,並檢測這K個樣本大部分屬於哪一類樣本,則認為這個測試樣本類別屬於這一類樣本。
假設現在需要判斷下圖中的圓形圖案屬於三角形還是正方形類別,採用KNN算法分析如下:
- 當K=3時,圖中第一個圈包含了三個圖形,其中三角形2個,正方形一個,該圓的則分類結果為三角形。
- 當K=5時,第二個圈中包含了5個圖形,三角形2個,正方形3個,則以3:2的投票結果預測圓為正方形類標。設置不同的K值,可能預測得到不同的結果。
簡而言之,一個樣本與數據集中的k個最相鄰樣本中的大多數的類別相同。由其思想可以看出,KNN是通過測量不同特徵值之間的距離進行分類,而且在決策樣本類別時,只參考樣本周圍k個「鄰居」樣本的所屬類別。因此比較適合處理樣本集存在較多重疊的場景,主要用於預測分析、文本分類、降維等處理。
KNN在Sklearn機器學習包中,實現的類是neighbors.KNeighborsClassifier,簡稱KNN算法。構造方法為:
KNeighborsClassifier(algorithm='ball_tree',
leaf_size=30,
metric='minkowski',
metric_params=None,
n_jobs=1,
n_neighbors=3,
p=2,
weights='uniform')
KNeighborsClassifier可以設置3種算法:brute、kd_tree、ball_tree,設置K值參數為n_neighbors=3。調用方法如下:
- from sklearn.neighbors import KNeighborsClassifier
- knn = KNeighborsClassifier(n_neighbors=3, algorithm=「ball_tree」)
它包括兩個步驟:
- 訓練:nbrs.fit(data, target)
- 預測:pre = clf.predict(data)
2.數據集
該部分主要使用Scikit-Learn包進行Python圖像分類處理。Scikit-Learn擴展包是用於Python數據挖掘和數據分析的經典、實用擴展包,通常縮寫為Sklearn。Scikit-Learn中的機器學習模型是非常豐富的,包括線性回歸、決策樹、SVM、KMeans、KNN、PCA等等,用戶可以根據具體分析問題的類型選擇該擴展包的合適模型,從而進行數據分析,其安裝過程主要通過「pip install scikit-learn」實現。
實驗所採用的數據集為Sort_1000pics數據集,該數據集包含了1000張圖片,總共分為10大類,分別是人(第0類)、沙灘(第1類)、建築(第2類)、大卡車(第3類)、恐龍(第4類)、大象(第5類)、花朵(第6類)、馬(第7類)、山峰(第8類)和食品(第9類),每類100張。如圖所示。
接着將所有各類圖像按照對應的類標劃分至「0」至「9」命名的文件夾中,如圖所示,每個文件夾中均包含了100張圖像,對應同一類別。
比如,文件夾名稱為「6」中包含了100張花的圖像,如下圖所示。
3.KNN圖像分類
下面是調用KNN算法進行圖像分類的完整代碼,它將1000張圖像按照訓練集為70%,測試集為30%的比例隨機劃分,再獲取每張圖像的像素直方圖,根據像素的特徵分佈情況進行圖像分類分析。KNeighborsClassifier()核心代碼如下:
- from sklearn.neighbors import KNeighborsClassifier
- clf = KNeighborsClassifier(n_neighbors=11).fit(XX_train, y_train)
- predictions_labels = clf.predict(XX_test)
完整代碼及注釋如下:
# -*- coding: utf-8 -*-
import os
import cv2
import numpy as np
from sklearn.cross_validation import train_test_split
from sklearn.metrics import confusion_matrix, classification_report
#----------------------------------------------------------------------------------
# 第一步 切分訓練集和測試集
#----------------------------------------------------------------------------------
X = [] #定義圖像名稱
Y = [] #定義圖像分類類標
Z = [] #定義圖像像素
for i in range(0, 10):
#遍歷文件夾,讀取圖片
for f in os.listdir("photo/%s" % i):
#獲取圖像名稱
X.append("photo//" +str(i) + "//" + str(f))
#獲取圖像類標即為文件夾名稱
Y.append(i)
X = np.array(X)
Y = np.array(Y)
#隨機率為100% 選取其中的30%作為測試集
X_train, X_test, y_train, y_test = train_test_split(X, Y,
test_size=0.3, random_state=1)
print len(X_train), len(X_test), len(y_train), len(y_test)
#----------------------------------------------------------------------------------
# 第二步 圖像讀取及轉換為像素直方圖
#----------------------------------------------------------------------------------
#訓練集
XX_train = []
for i in X_train:
#讀取圖像
#print i
image = cv2.imread(i)
#圖像像素大小一致
img = cv2.resize(image, (256,256),
interpolation=cv2.INTER_CUBIC)
#計算圖像直方圖並存儲至X數組
hist = cv2.calcHist([img], [0,1], None,
[256,256], [0.0,255.0,0.0,255.0])
XX_train.append(((hist/255).flatten()))
#測試集
XX_test = []
for i in X_test:
#讀取圖像
#print i
image = cv2.imread(i)
#圖像像素大小一致
img = cv2.resize(image, (256,256),
interpolation=cv2.INTER_CUBIC)
#計算圖像直方圖並存儲至X數組
hist = cv2.calcHist([img], [0,1], None,
[256,256], [0.0,255.0,0.0,255.0])
XX_test.append(((hist/255).flatten()))
#----------------------------------------------------------------------------------
# 第三步 基於KNN的圖像分類處理
#----------------------------------------------------------------------------------
from sklearn.neighbors import KNeighborsClassifier
clf = KNeighborsClassifier(n_neighbors=11).fit(XX_train, y_train)
predictions_labels = clf.predict(XX_test)
print u'預測結果:'
print predictions_labels
print u'算法評價:'
print (classification_report(y_test, predictions_labels))
#輸出前10張圖片及預測結果
k = 0
while k<10:
#讀取圖像
print X_test[k]
image = cv2.imread(X_test[k])
print predictions_labels[k]
#顯示圖像
cv2.imshow("img", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
k = k + 1
代碼中對預測集的前十張圖像進行了顯示,其中「818.jpg」圖像如圖所示,其分類預測的類標結果為「8」,表示第8類山峰,預測結果正確。
下圖展示了「452.jpg」圖像,其分類預測的類標結果為「4」,表示第4類恐龍,預測結果正確。
下圖展示了「507.jpg」圖像,其分類預測的類標結果為「7」,錯誤地預測為第7類恐龍,其真實結果應該是第5類大象。
使用KNN算法進行圖像分類實驗,最後算法評價的準確率(Precision)、召回率(Recall)和F值(F1-score)如圖所示,其中平均準確率為0.64,平均召回率為0.55,平均F值為0.50,其結果不是非常理想。那麼,如果採用CNN卷積神經網絡進行分類,通過不斷學習細節是否能提高準確度呢?
三.Tensorflow+Opencv實現CNN圖像分類
首先,我們需要在TensorFlow環境下安裝OpenCV擴展包;其次需要通過TensorFlow環境搭建CNN神經網絡;最後通過不斷學實現圖像分類實驗。
1.OpenCV庫安裝
第一步,打開Anaconda程序,並選擇已經安裝好的「TensorFlow」環境,運行Spyder。
第二步,我們需要在TensorFlow環境中安裝opencv-python擴展包,否則會提示錯誤「ModuleNotFoundError: No module named 『cv2』」。調用Anaconda Prompt安裝即可,如下圖所示:
activate tensorflow
pip install opencv-python
安裝成功如下圖所示。
但是,由於anaconda的.org服務器在國外,下載速度很慢,提示錯誤「Anaconda An HTTP error occurred when trying to retrieve this URL.HTTP errors are often intermittent」。
- 解決方法一:從國內清華的鏡像下載
- 解決方法二:從PYPI網站下載對應版本的opencv-python,在再安裝本地下載的.whl文件。下載地址://www.lfd.uci.edu/~gohlke/pythonlibs/#OpenCV
由於第一種方法一直失敗,這裡推薦讀者嘗試第二種方法,同時作者會將「opencv_python-4.1.2-cp36-cp36m-win_amd64.whl」文件上傳供大家直接使用。(4.1.2代表opencv的版本,cp36代表用的python3.6,並且是64位)。
第三步,調用PIP安裝本地opencv擴展包。
activate tensorflow
pip install C:\Users\xiuzhang\Desktop\TensorFlow\opencv_python-4.1.2-cp36-cp36m-win_amd64.whl
這種方法非常迅速,推薦大家使用。安裝成功之後,開始編寫我們的代碼吧!
2.讀取文件夾圖像
該部分具體步驟如下:
- 定義函數read_img(),讀取文件夾「photo」中「0」到「9」的圖像
- 調用cv2.imread()函數循環獲取每張圖片的所有像素值,並通過
cv2.resize()統一修改為32*32大小 - 依次獲取圖像像素、圖像類標和圖像路徑名稱:fpaths, data, label = read_img(path)
- 將圖像的順序隨機調整,並按照2-8比例劃分數據集,其中80%的數據用於訓練,20%的數據用於測試
#---------------------------------第一步 讀取圖像-----------------------------------
def read_img(path):
cate = [path + x for x in os.listdir(path) if os.path.isdir(path + x)]
imgs = []
labels = []
fpath = []
for idx, folder in enumerate(cate):
# 遍歷整個目錄判斷每個文件是不是符合
for im in glob.glob(folder + '/*.jpg'):
#print('reading the images:%s' % (im))
img = cv2.imread(im) #調用opencv庫讀取像素點
img = cv2.resize(img, (32, 32)) #圖像像素大小一致
imgs.append(img) #圖像數據
labels.append(idx) #圖像類標
fpath.append(path+im) #圖像路徑名
#print(path+im, idx)
return np.asarray(fpath, np.string_), np.asarray(imgs, np.float32), np.asarray(labels, np.int32)
# 讀取圖像
fpaths, data, label = read_img(path)
print(data.shape) # (1000, 256, 256, 3)
# 計算有多少類圖片
num_classes = len(set(label))
print(num_classes)
# 生成等差數列隨機調整圖像順序
num_example = data.shape[0]
arr = np.arange(num_example)
np.random.shuffle(arr)
data = data[arr]
label = label[arr]
fpaths = fpaths[arr]
# 拆分訓練集和測試集 80%訓練集 20%測試集
ratio = 0.8
s = np.int(num_example * ratio)
x_train = data[:s]
y_train = label[:s]
fpaths_train = fpaths[:s]
x_val = data[s:]
y_val = label[s:]
fpaths_test = fpaths[s:]
print(len(x_train),len(y_train),len(x_val),len(y_val)) #800 800 200 200
print(y_val)
3.搭建CNN
該部分具體步驟如下:
- 首先定義Placeholder,用於傳入輸入值,xs表示圖片32*32像素點,並且包含RGB三個圖層,故大小設置為32 * 32 * 3;ys表示每張圖片最終預測的類標值。
- 調用tf.layers.conv2d()函數定義卷積層,包括20個卷積核,卷積核大小為5,激勵函數為Relu;調用tf.layers.max_pooling2d()函數定義池化處理,步長為2,縮小一倍。
- 接着定義第二個卷積層和池化層,現共有conv0, pool0和conv1, pool1。
- 通過tf.layers.dense()函數定義全連接層,轉換為長度為400的特徵向量,加上DropOut防止過擬合。
- 輸出層為logits,包括10個數字,最終預測結果為predicted_labels,即為tf.arg_max(logits, 1)。
#---------------------------------第二步 建立神經網絡-----------------------------------
# 定義Placeholder
xs = tf.placeholder(tf.float32, [None, 32, 32, 3]) #每張圖片32*32*3個點
ys = tf.placeholder(tf.int32, [None]) #每個樣本有1個輸出
# 存放DropOut參數的容器
drop = tf.placeholder(tf.float32) #訓練時為0.25 測試時為0
# 定義卷積層 conv0
conv0 = tf.layers.conv2d(xs, 20, 5, activation=tf.nn.relu) #20個卷積核 卷積核大小為5 Relu激活
# 定義max-pooling層 pool0
pool0 = tf.layers.max_pooling2d(conv0, [2, 2], [2, 2]) #pooling窗口為2x2 步長為2x2
print("Layer0:\n", conv0, pool0)
# 定義卷積層 conv1
conv1 = tf.layers.conv2d(pool0, 40, 4, activation=tf.nn.relu) #40個卷積核 卷積核大小為4 Relu激活
# 定義max-pooling層 pool1
pool1 = tf.layers.max_pooling2d(conv1, [2, 2], [2, 2]) #pooling窗口為2x2 步長為2x2
print("Layer1:\n", conv1, pool1)
# 將3維特徵轉換為1維向量
flatten = tf.layers.flatten(pool1)
# 全連接層 轉換為長度為400的特徵向量
fc = tf.layers.dense(flatten, 400, activation=tf.nn.relu)
print("Layer2:\n", fc)
# 加上DropOut防止過擬合
dropout_fc = tf.layers.dropout(fc, drop)
# 未激活的輸出層
logits = tf.layers.dense(dropout_fc, num_classes)
print("Output:\n", logits)
# 定義輸出結果
predicted_labels = tf.arg_max(logits, 1)
4.定義損失函數和優化器
利用交叉熵定義損失,同時用AdamOptimizer優化器進行深度學習,核心代碼如下。
one-hot類型數據又稱為一位有效編碼,主要是採用N位狀態寄存器來對N個狀態進行編碼,每個狀態都由他獨立的寄存器位,並且在任意時候只有一位有效。例如[0 0 0 1 0 0 0 0 0 0…] 表示為「動物」。
# 利用交叉熵定義損失
losses = tf.nn.softmax_cross_entropy_with_logits(
labels = tf.one_hot(ys, num_classes), #將input轉化為one-hot類型數據輸出
logits = logits)
# 平均損失
mean_loss = tf.reduce_mean(losses)
# 定義優化器 學習效率設置為0.0001
optimizer = tf.train.AdamOptimizer(learning_rate=1e-4).minimize(losses)
5.模型訓練和預測
定義標記變量train,當它為True時進行訓練操作並保存訓練模型;當其為False時進行預測,20%預測集進行圖像分類預測實驗。
#------------------------------------第四步 模型訓練和預測-----------------------------------
# 用於保存和載入模型
saver = tf.train.Saver()
# 訓練或預測
train = False
# 模型文件路徑
model_path = "model/image_model"
with tf.Session() as sess:
if train:
print("訓練模式")
# 訓練初始化參數
sess.run(tf.global_variables_initializer())
# 定義輸入和Label以填充容器 訓練時dropout為0.25
train_feed_dict = {
xs: x_train,
ys: y_train,
drop: 0.25
}
# 訓練學習1000次
for step in range(1000):
_, mean_loss_val = sess.run([optimizer, mean_loss], feed_dict=train_feed_dict)
if step % 50 == 0: #每隔50次輸出一次結果
print("step = {}\t mean loss = {}".format(step, mean_loss_val))
# 保存模型
saver.save(sess, model_path)
print("訓練結束,保存模型到{}".format(model_path))
else:
print("測試模式")
# 測試載入參數
saver.restore(sess, model_path)
print("從{}載入模型".format(model_path))
# label和名稱的對照關係
label_name_dict = {
0: "人類",
1: "沙灘",
2: "建築",
3: "公交",
4: "恐龍",
5: "大象",
6: "花朵",
7: "野馬",
8: "雪山",
9: "美食"
}
# 定義輸入和Label以填充容器 測試時dropout為0
test_feed_dict = {
xs: x_val,
ys: y_val,
drop: 0
}
# 真實label與模型預測label
predicted_labels_val = sess.run(predicted_labels, feed_dict=test_feed_dict)
for fpath, real_label, predicted_label in zip(fpaths_test, y_val, predicted_labels_val):
# 將label id轉換為label名
real_label_name = label_name_dict[real_label]
predicted_label_name = label_name_dict[predicted_label]
print("{}\t{} => {}".format(fpath, real_label_name, predicted_label_name))
# 評價結果
print("正確預測個數:", sum(y_val==predicted_labels_val))
print("準確度為:", 1.0*sum(y_val==predicted_labels_val) / len(y_val))
6.完整代碼及實驗結果
完整代碼如下所示,這裡參考了王詩爺老師的部分代碼,強烈推薦大家學習他的博客。地址://blog.csdn.net/wills798
"""
Created on Sun Dec 29 19:21:08 2019
@author: xiuzhang Eastmount CSDN
"""
import os
import glob
import cv2
import numpy as np
import tensorflow as tf
# 定義圖片路徑
path = 'photo/'
#---------------------------------第一步 讀取圖像-----------------------------------
def read_img(path):
cate = [path + x for x in os.listdir(path) if os.path.isdir(path + x)]
imgs = []
labels = []
fpath = []
for idx, folder in enumerate(cate):
# 遍歷整個目錄判斷每個文件是不是符合
for im in glob.glob(folder + '/*.jpg'):
#print('reading the images:%s' % (im))
img = cv2.imread(im) #調用opencv庫讀取像素點
img = cv2.resize(img, (32, 32)) #圖像像素大小一致
imgs.append(img) #圖像數據
labels.append(idx) #圖像類標
fpath.append(path+im) #圖像路徑名
#print(path+im, idx)
return np.asarray(fpath, np.string_), np.asarray(imgs, np.float32), np.asarray(labels, np.int32)
# 讀取圖像
fpaths, data, label = read_img(path)
print(data.shape) # (1000, 256, 256, 3)
# 計算有多少類圖片
num_classes = len(set(label))
print(num_classes)
# 生成等差數列隨機調整圖像順序
num_example = data.shape[0]
arr = np.arange(num_example)
np.random.shuffle(arr)
data = data[arr]
label = label[arr]
fpaths = fpaths[arr]
# 拆分訓練集和測試集 80%訓練集 20%測試集
ratio = 0.8
s = np.int(num_example * ratio)
x_train = data[:s]
y_train = label[:s]
fpaths_train = fpaths[:s]
x_val = data[s:]
y_val = label[s:]
fpaths_test = fpaths[s:]
print(len(x_train),len(y_train),len(x_val),len(y_val)) #800 800 200 200
print(y_val)
#---------------------------------第二步 建立神經網絡-----------------------------------
# 定義Placeholder
xs = tf.placeholder(tf.float32, [None, 32, 32, 3]) #每張圖片32*32*3個點
ys = tf.placeholder(tf.int32, [None]) #每個樣本有1個輸出
# 存放DropOut參數的容器
drop = tf.placeholder(tf.float32) #訓練時為0.25 測試時為0
# 定義卷積層 conv0
conv0 = tf.layers.conv2d(xs, 20, 5, activation=tf.nn.relu) #20個卷積核 卷積核大小為5 Relu激活
# 定義max-pooling層 pool0
pool0 = tf.layers.max_pooling2d(conv0, [2, 2], [2, 2]) #pooling窗口為2x2 步長為2x2
print("Layer0:\n", conv0, pool0)
# 定義卷積層 conv1
conv1 = tf.layers.conv2d(pool0, 40, 4, activation=tf.nn.relu) #40個卷積核 卷積核大小為4 Relu激活
# 定義max-pooling層 pool1
pool1 = tf.layers.max_pooling2d(conv1, [2, 2], [2, 2]) #pooling窗口為2x2 步長為2x2
print("Layer1:\n", conv1, pool1)
# 將3維特徵轉換為1維向量
flatten = tf.layers.flatten(pool1)
# 全連接層 轉換為長度為400的特徵向量
fc = tf.layers.dense(flatten, 400, activation=tf.nn.relu)
print("Layer2:\n", fc)
# 加上DropOut防止過擬合
dropout_fc = tf.layers.dropout(fc, drop)
# 未激活的輸出層
logits = tf.layers.dense(dropout_fc, num_classes)
print("Output:\n", logits)
# 定義輸出結果
predicted_labels = tf.arg_max(logits, 1)
#---------------------------------第三步 定義損失函數和優化器---------------------------------
# 利用交叉熵定義損失
losses = tf.nn.softmax_cross_entropy_with_logits(
labels = tf.one_hot(ys, num_classes), #將input轉化為one-hot類型數據輸出
logits = logits)
# 平均損失
mean_loss = tf.reduce_mean(losses)
# 定義優化器 學習效率設置為0.0001
optimizer = tf.train.AdamOptimizer(learning_rate=1e-4).minimize(losses)
#------------------------------------第四步 模型訓練和預測-----------------------------------
# 用於保存和載入模型
saver = tf.train.Saver()
# 訓練或預測
train = False
# 模型文件路徑
model_path = "model/image_model"
with tf.Session() as sess:
if train:
print("訓練模式")
# 訓練初始化參數
sess.run(tf.global_variables_initializer())
# 定義輸入和Label以填充容器 訓練時dropout為0.25
train_feed_dict = {
xs: x_train,
ys: y_train,
drop: 0.25
}
# 訓練學習1000次
for step in range(1000):
_, mean_loss_val = sess.run([optimizer, mean_loss], feed_dict=train_feed_dict)
if step % 50 == 0: #每隔50次輸出一次結果
print("step = {}\t mean loss = {}".format(step, mean_loss_val))
# 保存模型
saver.save(sess, model_path)
print("訓練結束,保存模型到{}".format(model_path))
else:
print("測試模式")
# 測試載入參數
saver.restore(sess, model_path)
print("從{}載入模型".format(model_path))
# label和名稱的對照關係
label_name_dict = {
0: "人類",
1: "沙灘",
2: "建築",
3: "公交",
4: "恐龍",
5: "大象",
6: "花朵",
7: "野馬",
8: "雪山",
9: "美食"
}
# 定義輸入和Label以填充容器 測試時dropout為0
test_feed_dict = {
xs: x_val,
ys: y_val,
drop: 0
}
# 真實label與模型預測label
predicted_labels_val = sess.run(predicted_labels, feed_dict=test_feed_dict)
for fpath, real_label, predicted_label in zip(fpaths_test, y_val, predicted_labels_val):
# 將label id轉換為label名
real_label_name = label_name_dict[real_label]
predicted_label_name = label_name_dict[predicted_label]
print("{}\t{} => {}".format(fpath, real_label_name, predicted_label_name))
# 評價結果
print("正確預測個數:", sum(y_val==predicted_labels_val))
print("準確度為:", 1.0*sum(y_val==predicted_labels_val) / len(y_val))
訓練輸出結果如下所示:
(1000, 32, 32, 3)
10
800 800 200 200
[2 8 6 9 9 5 2 2 9 3 7 0 6 0 0 1 3 2 7 3 4 6 9 5 8 6 4 1 1 4 4 8 6 2 6 1 2
5 0 7 9 5 2 4 6 8 7 5 8 1 6 5 1 4 8 1 9 1 8 8 6 1 0 5 3 3 1 2 9 1 8 7 6 0
8 1 8 0 2 1 3 5 3 6 9 8 7 5 2 5 2 8 8 8 4 2 2 4 3 5 3 3 9 1 1 5 2 6 7 6 7
0 7 4 1 7 2 9 4 0 3 8 7 5 3 8 1 9 3 6 8 0 0 1 7 7 9 5 4 0 3 0 4 5 7 2 2 3
0 8 2 0 2 3 5 1 7 2 1 6 5 8 1 4 6 6 8 6 5 5 1 7 2 8 7 1 3 9 7 1 3 6 0 8 7
5 8 0 1 2 7 9 6 2 4 7 7 2 8 0]
Layer0:
Tensor("conv2d_1/Relu:0", shape=(?, 28, 28, 20), dtype=float32)
Tensor("max_pooling2d_1/MaxPool:0", shape=(?, 14, 14, 20), dtype=float32)
Layer1:
Tensor("conv2d_2/Relu:0", shape=(?, 11, 11, 40), dtype=float32)
Tensor("max_pooling2d_2/MaxPool:0", shape=(?, 5, 5, 40), dtype=float32)
Layer2:
Tensor("dense_1/Relu:0", shape=(?, 400), dtype=float32)
Output:
Tensor("dense_2/BiasAdd:0", shape=(?, 10), dtype=float32)
訓練模式
step = 0 mean loss = 66.93688201904297
step = 50 mean loss = 3.376957654953003
step = 100 mean loss = 0.5910811424255371
step = 150 mean loss = 0.061084795743227005
step = 200 mean loss = 0.013018212281167507
step = 250 mean loss = 0.006795921362936497
step = 300 mean loss = 0.004505819175392389
step = 350 mean loss = 0.0032660639844834805
step = 400 mean loss = 0.0024683878291398287
step = 450 mean loss = 0.0019308131886646152
step = 500 mean loss = 0.001541870180517435
step = 550 mean loss = 0.0012695763725787401
step = 600 mean loss = 0.0010685999877750874
step = 650 mean loss = 0.0009132082923315465
step = 700 mean loss = 0.0007910516578704119
step = 750 mean loss = 0.0006900889566168189
step = 800 mean loss = 0.0006068988586775959
step = 850 mean loss = 0.0005381597438827157
step = 900 mean loss = 0.0004809059901162982
step = 950 mean loss = 0.0004320790758356452
訓練結束,保存模型到model/image_model
預測輸出結果如下圖所示,最終預測正確181張圖片,準確度為0.905。相比之前機器學習KNN的0.500有非常高的提升。
測試模式
INFO:tensorflow:Restoring parameters from model/image_model
從model/image_model載入模型
b'photo/photo/3\\335.jpg' 公交 => 公交
b'photo/photo/1\\129.jpg' 沙灘 => 沙灘
b'photo/photo/7\\740.jpg' 野馬 => 野馬
b'photo/photo/5\\564.jpg' 大象 => 大象
...
b'photo/photo/9\\974.jpg' 美食 => 美食
b'photo/photo/2\\220.jpg' 建築 => 公交
b'photo/photo/9\\912.jpg' 美食 => 美食
b'photo/photo/4\\459.jpg' 恐龍 => 恐龍
b'photo/photo/5\\525.jpg' 大象 => 大象
b'photo/photo/0\\44.jpg' 人類 => 人類
正確預測個數: 181
準確度為: 0.905
四.總結
寫到這裡,這篇文章就講解完畢,更多TensorFlow深度學習文章會繼續分享,同時實驗評價、RNN、LSTM、各專業的案例都會進行深入講解。最後,希望這篇基礎性文章對您有所幫助,如果文章中存在錯誤或不足之處,還請海涵~作為人工智能的菜鳥,我希望自己能不斷進步並深入,後續將它應用於圖像識別、網絡安全、對抗樣本等領域,指導大家撰寫簡單的學術論文,一起加油!
參考文獻:
[1] 岡薩雷斯著. 數字圖像處理(第3版)[M]. 北京:電子工業出版社,2013.
[2] 楊秀璋, 顏娜. Python網絡數據爬取及分析從入門到精通(分析篇)[M]. 北京:北京航天航空大學出版社, 2018.
[3] 羅子江等. Python中的圖像處理[M]. 科學出版社,
2020.
[4] [python數據挖掘課程] 二十.KNN最近鄰分類算法分析詳解及平衡秤TXT數據集讀取
[5] TensorFlow【極簡】CNN – Yellow_python大神
[6] 基於深度神經網絡的定向激活功能開發相位信息的聲源定位 – 章子雎Kevin
[7] TensorFlow實戰:Chapter-5(CNN-3-經典卷積神經網絡(GoogleNet)) – DFann
[8] //github.com/siucaan/CNN_MNIST
[9] 圖像處理講解-以CNN對圖像進行分類為例 – 冰機靈
[10] 基於CNN的圖像缺陷分類 – BellaVita1
[12] tensorflow(六)訓練分類自己的圖片(CNN超詳細入門版)- Missayaa
[13] 詳解tensorflow訓練自己的數據集實現CNN圖像分類 – 王詩爺 (強推)
[14] //github.com/hujunxianligong/Tensorflow-CNN-Tutorial
[15] tensorflow(三):用CNN進行圖像分類 – flowrush
[16] TensorFlow圖像識別(物體分類)入門教程 – cococok2
[17] //github.com/calssion/Fun_AI
[18] CNN圖片分類 – 火舞_流沙
[19] CNN圖片單標籤分類(基於TensorFlow實現基礎VGG16網絡)
[20] //github.com/siucaan/CNN_MNIST/blob/master/cnn_mnist_TF.py
[21] Tensorflow實現CNN用於MNIST識別 – siucaan (強推)
[22] 使用Anaconda3安裝tensorflow,opencv,使其可以在spyder中運行