CNN
1995年, Yann LeCun 与Yoshua Bengio 提出了convolutional neural networks框架, 并用于手写体数字识别。
背景
在BP网络用于图像处理中, 如果要对输入图像分类, 可设计多层网络结构。如果采用全连接结构, 存在参数爆炸问题。 如对10001000的图像进行卷积, 大约需要1000100010001000个参数。利用局部卷积替换全连接结构, 可将参数降低至100010001010≈100M。
如果进一步采用权值共享的策略, 即同一特征图卷积核、Bias相同, 将卷积参数将至1010。 为尽可能地保存信息, 可设计多个卷积特征图, 将参数将至10K。
卷积
函数卷积
函数f(x)与g(x)卷积的定义(一维) 为:
图像卷积
在图像处理中, 卷积也被称为滤波, 一般是由卷积核(滤波器) w与在图像中f(x, y)的卷积结果为:
LeNet网络结构
输入层为3232图像, 一般限定字符最大范围为2020(居中)
C*: 卷基层
S*: 采样层(Pooling层)
F*: 全连接层
C1
输入层为3232图像, 卷积核大小为55
C1: 卷积层为6副28*28的特征图。 C1层具有如下特点:
- 拓扑结构: 输入层相邻节点卷积后仍然相邻
- 稀疏连接: 每个像素仅与输入层的相邻结点相连
- 权值共享: 同一副特征图共享相同的卷积核
C1层神经元连接数量为2828(55+1)6=122304, 由于采用了权值共享,
因此待学习参数为(55+1)6=156。
如果采用全连接策略, 总参数量可达(3232+1)(28*28)*6
S2
S2: Pooling层将2828的特征图将采样为1414的图像:
- 采用2*2非重叠采样。
- S2层每个单元的4个输入相加, 乘以一个可训练参数, 再加上一个可
训练偏置。
- 结果通过sigmoid函数计算。
S2层神经元连接数量为1414(2*2+1)6=5880, 待学习参数为62=12。
C3
C3: 将6副2828的特征图卷积为16副1010的图像, 卷积核为5*5:
- C3 中每副特征图与S2中的若干副特征图相关。
- C3层神经元连接数量为151600, 待学习参数为1516。
S4
S4: 将1010的特征图将采样为16副55的图像:
- 降采样过程与S2层一致
- S4层神经元连接数量为55(2*2+1)16=2000, 待学习参数为162=32
C5
C5: 将16副5*5的特征图卷积为长度为120的向量:
- F6中每个神经元与S4所有神经元相连。
- C5层神经元连接数量为120*(16*25+1) = 48120, 全部为待学习参数。
F6
F6: 构建84个神经元, 每个神经元与C5的120个神经元全连接:
- F6层神经元连接数量为84*(120+1)=10164, 全部为待学习参数。
输出
输出层: 为10个神经元, 每个神经元的激活值表示对应字符的相应强度,
最大值则为对应的识别结果。
数据集
0-9共十个数字每个数字训练集在6000张图片左右。
训练图片中倾斜,扭曲,粗细不一致,甚至旋转,如
倾斜
扭曲
粗细不一致
旋转(数字7)
代码及运行结果
import tensorflow as tf
import numpy as np
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
from tkinter import filedialog
import time
def creat_windows():
win = tk.Tk() # 创建窗口
sw = win.winfo_screenwidth()
sh = win.winfo_screenheight()
ww, wh = 400, 450
x, y = (sw-ww)/2, (sh-wh)/2
win.geometry("%dx%d+%d+%d"%(ww, wh, x, y-40)) # 居中放置窗口
win.title('手写体识别') # 窗口命名
bg1_open = Image.open("timg.jpg").resize((300, 300))
bg1 = ImageTk.PhotoImage(bg1_open)
canvas = tk.Label(win, image=bg1)
canvas.pack()
var = tk.StringVar() # 创建变量文字
var.set('')
tk.Label(win, textvariable=var, bg='#C1FFC1', font=('宋体', 21), width=20, height=2).pack()
tk.Button(win, text='选择图片', width=20, height=2, bg='#FF8C00', command=lambda:main(var, canvas), font=('圆体'