在深度學習入門的過程中,卷積神經網絡(Convolutional Neural Netwok, CNN)模型的學習是必不可少的,CNN是深度學習理論和方法中的重要組成部分。爲了更好的學習到卷積神經網絡的應用,將通過卷積神經網絡模型在圖像識別領域的應用來入門。
**
應用背景:
**本項目將通過識別手寫的“對”、“錯”圖像,也就是常說的“√”“×”,訓練數據保存在’checkData.txt’文件中。checkData.txt
卷積神經網絡結構:
本例中使用3個卷積層來把輸入層的數據逐步進行特徵抽象,再進入2個全連接層進行特徵關係和權重值計算,並將結果輸出到輸出層。具體結構如下圖所示:
數據格式說明:
每一張圖像,用5×5的二維矩陣來表示,圖像爲純黑白影像,因此矩陣中的每個值爲0或者1,0表示的是白色,1表示的是黑色。例如:
0 0 0 0 0
0 0 0 0 1
0 1 0 1 0
0 0 1 0 0 表示‘√’
0 0 0 0 0
0 0 0 0 0
0 1 0 1 0
0 0 1 0 0
0 1 0 1 0 表示‘×’
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 1 1 1 1
0 0 0 0 0 表示無法識別,既不是‘√’,也不是‘×’
0 0 0 0 0
在文件‘’中,每條訓練數據包括28個數字,前25個數字表示的是5×5的圖像數據,後3個數字表示的是這個圖像屬於哪一類(因爲一共就3類,三個值分別表示‘√’、‘×’、‘無法識別’)。
識別的代碼如下:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tensorflow as tf
import numpy as np
import pandas as pd
import sys
roundCount = 100
learnRate = 0.01
argt = sys.argv[1:]
for v in argt:
if v.startswith('-round='):
roundCount = int(v[len('-round='):])
if v.startswith('-learnrate='):
learnRate = float(v[len('-learnrate='):])
fileData = pd.read_csv('checkData.txt', dtype=np.float32, header=None)
wholeData = fileData.as_matrix()
rowCount = wholeData.shape[0]
print('wholeData=%s' % wholeData)
print('rowCount=%s' % rowCount)
x = tf.placeholder(shape=[25], dtype=tf.float32)
yTrain = tf.placeholder(shape=[3], dtype=tf.float32)
filter1T = tf.Variable(tf.ones([2, 2, 1, 1]), dtype=tf.float32)
n1 = tf.nn.conv2d(input=tf.reshape(x, [1, 5, 5, 1]), filter=filter1T, strides=[1, 1, 1, 1], padding='SAME')
filter2T = tf.Variable(tf.ones([2, 2, 1, 1]), dtype=tf.float32)
n2 = tf.nn.conv2d(input=tf.reshape(n1, [1, 5, 5, 1]), filter=filter2T, strides=[1, 1, 1, 1], padding='VALID')
filter3T = tf.Variable(tf.ones([2, 2, 1, 1]), dtype=tf.float32)
n3 = tf.nn.conv2d(input=tf.reshape(n2, [1, 4, 4, 1]), filter=filter3T, strides=[1, 1, 1, 1], padding='VALID')
n3f = tf.reshape(n3, [1, 9])
w4 = tf.Variable(tf.random_normal([9, 16]), dtype=tf.float32)
b4 = tf.Variable(0, dtype=tf.float32)
n4 = tf.nn.tanh(tf.matmul(n3f, w4) + b4)
w5 = tf.Variable(tf.random_normal([16, 3]), dtype=tf.float32)
b5 = tf.Variable(0, dtype=tf.float32)
n5 = tf.reshape(tf.matmul(n4, w5) + b5, [-1])
y = tf.nn.softmax(n5)
loss = -tf.reduce_mean(yTrain * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
optimizer = tf.train.RMSPropOptimizer(learnRate)
train = optimizer.minimize(loss)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for i in range(roundCount):
lossSum = 0.0
for j in range(rowCount):
result = sess.run([train, x, yTrain, y, loss], feed_dict={x:wholeData[j][0:25], yTrain:wholeData[j][25:28]})
lossT = float(result[len(result) - 1])
lossSum = lossSum + lossT
if j == (rowCount - 1):
print('i: %d, loss: %10.10f, avgLoss: %10.10f' % (i, lossT, lossSum / (rowCount + 1)))
print(sess.run([y, loss], feed_dict={x: [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
yTrain: [1, 0, 0]}))
print(sess.run([y, loss], feed_dict={x: [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1],
yTrain: [0, 1, 0]}))
print(sess.run([y, loss], feed_dict={x: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
yTrain: [0, 0, 1]}))
將本代碼保存爲‘conv3.py’,在cmd中運行該代碼:
python conv3.py -round=10000 -learnrate=0.0001 #訓練次數爲10000次,學習率爲0.0001.
運行結果爲:
從最後的3行結果可知,第一行測試結果中最大值爲0.8422765,也就是爲‘√’的概率最大,同理可知,第二行爲‘×’,第三行爲‘√’。此時對比一下原代碼中的輸入圖片的真實值,第一行爲’√’,第二行爲‘×’,第三行爲‘無法識別’,這與訓練之後的測試值相比,第三行是預測錯誤的,說明本模型的預測精度還有待提高。
具體的提高方式可以從以下幾個方面考慮:
(1)增加訓練樣本數據集,(本例中只有15個訓練樣本,數據量太小)
(2)增加捲積層的數量,從而進行更高層次的特徵抽象和特徵提取
(3)增加每個圖像的像素點,本例中是5×5的,可以劃分成更多的數據。