卷積核大小一般是奇數,奇數大小的卷積核使得卷積核關於中間像素點中心對稱,因此卷積核尺寸一般是3×3、5×5或7×7。卷積核有中心,相應地就有半徑的概念,如7×7 大小的卷積核,其半徑為3。
卷積核所有的元素之和一般應等於1,這是為了保持圖像卷積計算過程中像素能量(亮度)的守恆。若濾波器矩陣所有元素之和大於1,那麼濾波後的圖像就會比原圖像更亮;反之,若小於1,那麼得到的圖像將會變暗。
濾波後可能會出現負數或大於255 的數值。對這種情況,通常將它們直接截斷到0~255之間即可。而對於負數,也可以取絕對值。
經卷積計算所得輸出通常被稱為「響應」,如果是邊緣檢測算子,那麼響應為圖像邊緣,能夠檢測到特定的圖像邊緣。在LeNet-5網絡中得到的響應是特徵圖(Feature Map),計算結果為輸入圖像的特徵表達,卷積核的參數權重可以通過優化算法在監督信息的指導下自適應地學習得到。LeNet-5 網絡中C1 層輸入圖像尺寸為32×32×1,卷積核大小為5×5,一共包括6 種大小為5×5 的卷積核,卷積核滑動一行之後,得到的結果的邊長變為32-5+1,提取的特徵映射大小是28×28,即(32-5+1)=28。6種不同的卷積核,可以從不同的角度提取圖像不同特性的特徵。神經元數量為28×28×6,則可訓練參數為(5×5+1)×6,即每個濾波器含5×5=25個單元權值參數和1個偏置參數,一共6 個濾波器,因此總的連接數為(5×5+1)×6×28×28=122 304。針對122 304 個連接,通過權值共享策略,只需學習156 個參數。3. S2 層1. """
2. 設置模型的超參數
3.
4.
5. KEEP_PROB: 網絡隨機失活的概率
6. LEARNING_RATE: 學習的速率,即梯度下降的速率
7. BATCH_SIZE: 一次訓練所選取的樣本數
8. PARAMETER_FILE: 模型參數保存的路徑
9. MAX_ITER: 最大迭代次數
10. """
11.
12. KEEP_PROB = 0.5
13. LEARNING_RATE = 1e-5
14. BATCH_SIZE =50
15. PARAMETER_FILE = "checkpoint/variable.ckpt"
16. MAX_ITER = 50000
1. import tensorflow as tf
2. import tensorflow.contrib.slim as slim
3. import config as cfg
4.
5. class Lenet:
6. def __init__(self):
7. """
8. 初始化LeNet 網絡
9. """
10. # 設置網絡輸入的圖片為二維張量,數據的類型為float32,行數不固定,列固定為784
11. self.raw_input_image = tf.placeholder(tf.float32, [None, 784])
12.
13. # 改變網絡輸入張量的形狀為四維,-1 表示數值不固定
14. self.input_images = tf.reshape(self.raw_input_image, [-1, 28, 28, 1])
15.
16. # 設置網絡輸入標籤為二維張量,數據類型為float,行數不固定,列固定為10
17. self.raw_input_label = tf.placeholder("float", [None, 10])
18.
19. # 改變標籤的數據類型為int32
20. self.input_labels = tf.cast(self.raw_input_label,tf.int32)
21.
22. # 設置網絡的隨機失活概率
23. self.dropout = cfg.KEEP_PROB
24.
25. # 構建兩個網絡
26. # train_digits 為訓練網絡,開啟dropout
27. # pred_digits 為預測網絡,關閉dropout
28. with tf.variable_scope("Lenet") as scope:
29. self.train_digits = self.construct_net(True)
30. scope.reuse_variables()
31. self.pred_digits = self.construct_net(False)
32.
33. # 獲取網絡的預測數值
34. self.prediction = tf.argmax(self.pred_digits, 1)
35.
36. # 獲取網絡的預測數值與標籤的匹配程度
37. self.correct_prediction = tf.equal(tf.argmax(self.pred_digits, 1), tf.argmax
(self.input_labels, 1))
38.
39. # 將匹配程度轉換為float 類型,表示為精度
40. self.train_accuracy = tf.reduce_mean(tf.cast(self.correct_prediction, "float"))
41.
42. # 計算train_digits 與labels 之間的係數softmax 交叉熵,定義為loss
43. self.loss = slim.losses.softmax_cross_entropy(self.train_digits, self.
input_labels)
44.
45. # 設置學習速率
46. self.lr = cfg.LEARNING_RATE
47. self.train_op = tf.train.AdamOptimizer(self.lr).minimize(self.loss)
48.
49.
50. def construct_net(self,is_trained = True):
51. """
52. 接收is_trained 參數判斷是否開啟dropout
53. 用slim 構建LeNet 模型
54. 第一、三、五層為卷積層、第二、四層為池化層
55. 接下來對第五層扁平化,再接入全連接
56. 接著進行隨機失活防止過擬合,再次接入全連接層
57. 最後返回構建的網絡
58. """
59. with slim.arg_scope([slim.conv2d], padding='VALID',
60. weights_initializer=tf.truncated_normal_initializer(stddev=0.01),
61. weights_regularizer=slim.l2_regularizer(0.0005)):
62. net = slim.conv2d(self.input_images,6,[5,5],1,padding='SAME',scope='conv1')
63. net = slim.max_pool2d(net, [2, 2], scope='pool2')
64. net = slim.conv2d(net,16,[5,5],1,scope='conv3')
65. net = slim.max_pool2d(net, [2, 2], scope='pool4')
66. net = slim.conv2d(net,120,[5,5],1,scope='conv5')
67. net = slim.flatten(net, scope='flat6')
68. net = slim.fully_connected(net, 84, scope='fc7')
69. net = slim.dropout(net, self.dropout,is_training=is_trained, scope=
'dropout8')
70. digits = slim.fully_connected(net, 10, scope='fc9')
71. return digits
1. import tensorflow.examples.tutorials.mnist.input_data as input_data
2. import tensorflow as tf
3. import config as cfg
4. import os
5. import lenet
6. from lenet import Lenet
7.
8.
9. def main():
10. # 從指定路徑加載訓練數據
11. mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
12.
13. # 開啟TensorFlow 會話
14. sess = tf.Session()
15.
16. # 設置超參數
17. batch_size = cfg.BATCH_SIZE
18. parameter_path = cfg.PARAMETER_FILE
19. lenet = Lenet()
20. max_iter = cfg.MAX_ITER
21.
22. # 加載已保存的模型參數文件,如果不存在則調用初始化函數生成初始網絡
23. saver = tf.train.Saver()
24. if os.path.exists(parameter_path):
25. saver.restore(parameter_path)
26. else:
27. sess.run(tf.initialize_all_variables())
28.
29. # 迭代訓練max_iter 次,每次抽取50 個樣本進行訓練
30. # 每100 次列印出當前數據的精度
31. # 訓練完成後保存模型參數
32. for i in range(max_iter):
33. batch = mnist.train.next_batch(50)
34. if i % 100 == 0:
35. train_accuracy = sess.run(lenet.train_accuracy,feed_dict={
36. lenet.raw_input_image: batch[0],lenet.raw_input_label: batch[1]
37. })
38. print("step %d, training accuracy %g" % (i, train_accuracy))
39. sess.run(lenet.train_op,feed_dict={lenet.raw_input_image: batch[0],lenet.
raw_input_label: batch[1]})
40. save_path = saver.save(sess, parameter_path)
41.
42. if __name__ == '__main__':
43. main(
1. import tensorflow as tf
2. from PIL import Image,ImageOps
3. import numpy as np
4. from lenet import Lenet
5. import config as cfg
6.
7. class inference:
8. def __init__(self):
9. """
10. 構建Lenet 網絡,設置模型參數文件路徑,開啟TensorFlow 會話
11. """
12. self.lenet = Lenet()
13. self.sess = tf.Session()
14. self.parameter_path = cfg.PARAMETER_FILE
15. self.saver = tf.train.Saver()
16.
17. def predict(self,image):
18. """
19. 接收要測試的圖片作為參數,返回預測值
20. """
21. # 將圖片轉換為合適的大小進行輸入
22. img = image.convert('L')
23. img = img.resize([28, 28], Image.ANTIALIAS)
24. image_input = np.array(img, dtype="float32") / 255
25. image_input = np.reshape(image_input, [-1, 784])
26.
27. # 讀取模型參數並對圖片進行預測,返回預測值
28. self.saver.restore(self.sess,self.parameter_path)
29. predition = self.sess.run(self.lenet.prediction, feed_dict={self.lenet.raw_
input_image: image_input})
30. return predition
1. import tkinter
2. from PIL import Image,ImageDraw
3. from Inference import inference
4.
5. class MyCanvas:
6. """
7. 設置一個256*256 大小的容器進行手寫界面的繪製
8. 背景色設置為黑色,繪製軌跡設置為白色
9. """
10. def __init__(self,root):
11. self.root=root
12. self.canvas=tkinter.Canvas(root,width=256,height=256,bg='black')
13. self.canvas.pack()
14. self.image1 = Image.new("RGB", (256, 256), "black")
15. self.draw = ImageDraw.Draw(self.image1)
16. self.canvas.bind('<B1-Motion>',self.Draw)
17.
18. # 繪製軌跡
19. def Draw(self,event):
20. self.canvas.create_oval(event.x,event.y,event.x,event.y,outline="white",
width = 20)
21. self.draw.ellipse((event.x-10,event.y-10,event.x+10,event.y+10),fill=(255,
255,255))
22.
23.
24. def main():
25. # 建立一個tkinter 對象, 設置大小為380*300
26. root = tkinter.Tk()
27. root.geometry('380x300')
28. # 創建一個256*256 的框架容納手寫的容器,位於tkinter 對象的左邊,填充y 方向
29. frame = tkinter.Frame(root, width=256, height=256)
30. frame.pack_propagate(0)
31. frame.pack(side="left", fill='y')
32. # 將frame 導入canvas 容器
33. canvas1 = MyCanvas(frame)
34. # 創建一個圖像識別的實例
35. infer = inference()
36.
37. # 定義識別按鈕觸發函數
38. # 按下的時候將cavas 導出為圖片,放入infer 中進行圖像識別,並將結果顯示在label2 中
39. def inference_click():
40. img = canvas1.image1
41. result = infer.predict(img)
42. result = int(result)
43. label2["text"] = str(result)
44.
45. # 定義清除按鈕的觸發函數
46. # 按下的時候將canvas 情況並重新繪製背景,並將label 設置為空
47. def clear_click():
48. canvas1.canvas.delete("all")
49. canvas1.image1 = Image.new("RGB", (256, 256), "black")
50. canvas1.draw = ImageDraw.Draw(canvas1.image1)
51. label2["text"] = ""
52.
53. # 定義識別按鈕的樣式
54. botton_Inference = tkinter.Button(root,
55. text=" 檢測",
56. width=14,
57. height=2,
58. command=inference_click
59. )
60. # 定義清除按鈕的樣式
61. botton_Clear = tkinter.Button(root,
62. text=" 清屏",
63. width=14,
64. height=2,
65. command=clear_click
66. )
67. # 綁定識別按鈕到tkinter 中,設置位置為頂層
68. botton_Inference.pack(side="top")
69.
70. # 綁定清除按鈕到tkinter 中
71. botton_Clear.pack(side="top")
72.
73. # 定義label1
74. label1 = tkinter.Label(root, justify="center", text=" 檢測結果為:")
75. label1.pack(side="top")
76.
77. # 定義label2
78. label2 = tkinter.Label(root, justify="center")
79.
80. # 設置字體樣式與大小
81. label2["font"] = ("Arial, 48")
82. label2.pack(side="top")
83. root.mainloop()
84.
85. if __name__ == '__main__':
86. main()
更多精彩推薦