更新记录:

2018年2月5日 初始文章版本


近几天需要进行英语手写体识别,查阅了很多资料,但是大多数资料都是针对MNIST数据集的,并且主要识别手写数字。为了满足实际的英文手写识别需求,需要从训练集构造到神经网络搭建各个方面对现有代码进行修改。

神经网络的结构:

1.输入28*28=784维行向量

2.卷积层:卷积核大小5*5,共32个,激活函数ReLu

3.池化层:最大值池化,2*2窗口

4.卷积层:卷积核大小5*5,共64个,激活函数ReLu

5.池化层:最大值池化,2*2窗口

6.全连接层(多层感知机)

训练代码:

  1. import tensorflow as tf
  2. import numpy as np
  3. import xlrd
  4. # 开始读取训练数据
  5. data = xlrd.open_workbook('train_set.xlsx')
  6. table = data.sheets()[0]
  7. nrows = table.nrows
  8. ncols = table.ncols
  9. c1 = np.arange(0, nrows, 1)
  10. datamatrix = np.zeros((nrows, ncols))
  11. for x in range(ncols):
  12. cols = table.col_values(x)
  13. cols1 = np.matrix(cols) # 把list转换为矩阵进行矩阵操作
  14. datamatrix[:, x] = cols1 # 把数据进行存储
  15. x_data = datamatrix
  16.  
  17. table = data.sheets()[1]
  18. nrows = table.nrows
  19. ncols = table.ncols
  20. c1 = np.arange(0, nrows, 1)
  21. datamatrix = np.zeros((nrows, ncols))
  22. for x in range(ncols):
  23. cols = table.col_values(x)
  24. cols1 = np.matrix(cols) # 把list转换为矩阵进行矩阵操作
  25. datamatrix[:, x] = cols1 # 把数据进行存储
  26. y_data = datamatrix
  27. # 完成训练数据读取
  28. # 开始定义神经网络结构
  29.  
  30. # 定义占位符x和y_
  31. x = tf.placeholder(tf.float32, shape=[None, 784])
  32. y_ = tf.placeholder(tf.float32, shape=[None, 26])
  33.  
  34. # 开始定义用于初始化的两个函数
  35. def weight_variable(shape):
  36. initial = tf.truncated_normal(shape, stddev=0.1)
  37. return tf.Variable(initial)
  38.  
  39. def bias_variable(shape):
  40. initial = tf.constant(0.1, shape=shape)
  41. return tf.Variable(initial)
  42.  
  43. # 完成初始化函数定义
  44.  
  45. # 开始定义卷积和池化的函数
  46. # 卷积使用1步长(stride size),0边距(padding size)的模板,保证输出和输入大小相同
  47. # 池化用简单传统的2x2大小的模板做max pooling,因此输出的长宽会变为输入的一半
  48.  
  49. def conv2d(x, W):
  50. return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
  51.  
  52. def max_pool_2x2(x):
  53. return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1, 2, 2, 1], padding='SAME')
  54. # 完成卷积池化函数定义
  55.  
  56. # 开始定义神经网络结构定义
  57. # 第一层卷积,卷积在每个5x5的patch中算出32个特征
  58. W_conv1 = weight_variable([5, 5, 1, 32])
  59. b_conv1 = bias_variable([32])
  60. x_image = tf.reshape(x, [-1, 28, 28, 1])
  61. # 第2、第3维对应图片的宽、高,最后一维代表图片的颜色通道数(因为是灰度图所以这里的通道数为1,如果是rgb彩色图,则为3)
  62. h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
  63. h_pool1 = max_pool_2x2(h_conv1)
  64.  
  65. # 第二层卷积,每个5x5的patch会得到64个特征
  66. W_conv2 = weight_variable([5, 5, 32, 64])
  67. b_conv2 = bias_variable([64])
  68. h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
  69. h_pool2 = max_pool_2x2(h_conv2)
  70.  
  71. # 有1024个神经元的全连接层,此时图片大小为7*7
  72. W_fc1 = weight_variable([7*7*64, 1024])
  73. b_fc1 = bias_variable([1024])
  74. h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
  75. h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
  76.  
  77. # 为了减少过拟合,在输出层之前加入dropout。用一个placeholder代表一个神经元的输出在dropout中保持不变的概率。
  78. # 这样可以在训练过程中启用dropout,在测试过程中关闭dropout。
  79. keep_prob = tf.placeholder(tf.float32)
  80. h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
  81. # softmax输出层
  82. W_fc2 = weight_variable([1024, 26])
  83. b_fc2 = bias_variable([26])
  84. y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
  85. # 应为 y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
  86. # 完成神经网络结构定义
  87.  
  88. # 开始定义训练和评估操作
  89. # 用更加复杂的ADAM优化器来做梯度最速下降,在feed_dict中加入额外的参数keep_prob来控制dropout比例
  90. cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
  91. train_step = tf.train.AdamOptimizer(1e-6).minimize(cross_entropy)
  92. correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
  93. accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
  94. # 完成训练和评估操作的定义
  95.  
  96. # 开始定义储存器操作并装载已经训练过的神经网络
  97. saver = tf.train.Saver(write_version=tf.train.SaverDef.V1)
  98. sess = tf.InteractiveSession()
  99. saver.restore(sess, "cnnres/model.ckpt")
  100. # sess.run(tf.global_variables_initializer())
  101. # 完成定义储存器操作和装载神经网络
  102.  
  103. # 开始对训练集进行循环训练
  104. for k in range(20):
  105. for i in range(55): # 为减少训练时间,降低迭代次数
  106. x_datap = x_data[i*26:(i+1)*26, 0:28*28]
  107. y_datap = y_data[i*26:(i+1)*26, 0:26]
  108. for j in range(3000):
  109. if j % 100 == 0:
  110. train_accuracy = accuracy.eval(feed_dict={x: x_data, y_: y_data, keep_prob: 1.0})
  111. print("step %d, training accuracy %g"%(i, train_accuracy))
  112. train_step.run(feed_dict={x: x_datap, y_: y_datap, keep_prob: 0.5})
  113. # if train_accuracy >= 0.942:
  114. # train_step = tf.train.AdamOptimizer(1e-6).minimize(cross_entropy)
  115. # if train_accuracy <= 0.9:
  116. # train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
  117. if train_accuracy >= 0.95:
  118. saver_path = saver.save(sess, "cnnres/model.ckpt")
  119. print('Save the par in', saver_path)
  120. # 完成训练和储存过程

备注:

1.由于GUP运算能力的限制,需要将训练集每次取出一部分进行训练,但是对模型的准确度进行评估时应当feed全部数据。

相关代码:

x_datap = x_data[i*26:(i+1)*26, 0:28*28]
y_datap = y_data[i*26:(i+1)*26, 0:26]
train_accuracy = accuracy.eval(feed_dict={x: x_data, y_: y_data, keep_prob: 1.0})
train_step.run(feed_dict={x: x_datap, y_: y_datap, keep_prob: 0.5})
2.考虑到对训练集的读取是顺序的,因此训练集必须随机乱序,绝对不能按照字母表排序,否则将会出现严重的过拟合。

3.神经网络的训练结果被储存在cnnres/model.ckpt中

4.在精确度达到0.8之前将步长定为1E-4,在精确度达到0.9之后将步长定为1E-6,不要将步长设定为小于这个值,否则训练进展极为缓慢。

训练集构成:

储存在train_set.xlsx中。共有两张表,第一张表每一行有28*28=784列,对应一个784维输入向量;第二张表每一行有26列,该行与第一张表同一行的预期输出结果对应,在第x列值为1,其余列值为0,表示第一张表同一行的预期输出结果是字母表中第x个字母。

训练集的生成代码:

  1. import numpy as np
  2. from PIL import Image
  3. import xlsxwriter
  4.  
  5. # 开始读取测试图片
  6.  
  7. def ImageToMatrix(filename):
  8. im = Image.open(filename)
  9. width, height = im.size
  10. im = im.convert("L")
  11. data = im.getdata()
  12. data = np.matrix(data, dtype='float')/255.0
  13. new_data = np.reshape(data, (height, width))
  14. return new_data
  15.  
  16. def ImageToMatrix2(ima):
  17. width, height = ima.size
  18. ima = ima.convert("L")
  19. data = ima.getdata()
  20. data = np.matrix(data, dtype='float')/255.0
  21. new_data = np.reshape(data, (height, width))
  22. return new_data
  23.  
  24. def MatrixToImage(data):
  25. data = data*255
  26. new_im = Image.fromarray(data.astype(np.uint8))
  27. return new_im
  28.  
  29. # 循环读取测试图片并写入
  30. # 开始进行写excel的准备
  31. book = xlsxwriter.Workbook(r'train_set.xlsx')
  32. sheet1 = book.add_worksheet('train_input1')
  33. sheet2 = book.add_worksheet('train_input2')
  34. sheet3 = book.add_worksheet('train_input3')
  35. sheet4 = book.add_worksheet('train_input4')
  36. # 完成写excel的准备
  37. for i in range(1, 1430+1):
  38. test_pic = ImageToMatrix(str(i)+'.png')
  39. # 完成测试图片读取
  40. # -------------------------
  41. # 开始处理测试图片
  42. # 开始寻找图片四边
  43. hang, lie = np.shape(test_pic)
  44. for top in range(0, hang):
  45. if np.min(test_pic[top, :]) != 1:
  46. break
  47. for bot in range(hang-1, 0, -1):
  48. if np.min(test_pic[bot, :]) != 1:
  49. break
  50. for left in range(0, lie):
  51. if np.min(test_pic[:, left]) != 1:
  52. break
  53. for right in range(lie - 1, 0, -1):
  54. if np.min(test_pic[:, right]) != 1:
  55. break
  56. new_test_pic = test_pic[top:bot, left:right]
  57. # 完成图片四边寻找
  58. # 开始进行图片尺寸转换
  59. pic = MatrixToImage(new_test_pic)
  60. pic2 = pic.resize((28, 28))
  61. test_datap = ImageToMatrix2(pic2)
  62. test_data = np.reshape(test_datap, (1, 784))
  63. # 完成图片尺寸转换
  64. # 对行向量进行储存
  65. for j in range(0, 200):
  66. sheet1.write(i-1, j, test_data[0, j])
  67. sheet2.write(i - 1, j, test_data[0, j+200])
  68. sheet3.write(i - 1, j, test_data[0, j+400])
  69. if j+600 <= 783:
  70. sheet4.write(i - 1, j, test_data[0, j+600])
  71. print(i)
  72. book.close()

备注:此处由于python提供的xlsxwriter库存如下限制:每一行最多可以写256列,因此必须将这个786维的向量分别写到4张表的同一行,再进行手工合并。而第二张预期输出表需要使用其它方法进行构造,此处不给出相关代码。

测试代码:

  1. import tensorflow as tf
  2. import numpy as np
  3. from PIL import Image
  4. import matplotlib.pyplot as plt
  5. # 开始读取测试图片
  6.  
  7. def ImageToMatrix(filename):
  8. im = Image.open(filename)
  9. width, height = im.size
  10. im = im.convert("L")
  11. data = im.getdata()
  12. data = np.matrix(data, dtype='float')/255.0
  13. new_data = np.reshape(data, (height, width))
  14. return new_data
  15.  
  16. def ImageToMatrix2(ima):
  17. width, height = ima.size
  18. ima = ima.convert("L")
  19. data = ima.getdata()
  20. data = np.matrix(data, dtype='float')/255.0
  21. new_data = np.reshape(data, (height, width))
  22. return new_data
  23.  
  24. def MatrixToImage(data):
  25. data = data*255
  26. new_im = Image.fromarray(data.astype(np.uint8))
  27. return new_im
  28.  
  29. test_pic = ImageToMatrix('test.png')
  30.  
  31. # 完成测试图片读取
  32. # -------------------------
  33. # 开始处理测试图片
  34. # 开始寻找图片四边
  35. hang, lie = np.shape(test_pic)
  36. for top in range(0, hang):
  37. if np.min(test_pic[top, :]) != 1:
  38. break
  39. for bot in range(hang-1, 0, -1):
  40. if np.min(test_pic[bot, :]) != 1:
  41. break
  42. for left in range(0, lie):
  43. if np.min(test_pic[:, left]) != 1:
  44. break
  45. for right in range(lie - 1, 0, -1):
  46. if np.min(test_pic[:, right]) != 1:
  47. break
  48. new_test_pic = test_pic[top:bot, left:right]
  49. # 完成图片四边寻找
  50. # 开始进行图片尺寸转换
  51. pic = MatrixToImage(new_test_pic)
  52. pic2 = pic.resize((28, 28))
  53. test_data = ImageToMatrix2(pic2)
  54. test_data = np.reshape(test_data, (1, 784))
  55. # 完成图片尺寸转换
  56.  
  57. # 完成测试图片的处理
  58. # --------------------------
  59. # 开始定义神经网络结构
  60.  
  61. # 定义占位符x和y_
  62. x = tf.placeholder(tf.float32, shape=[None, 784])
  63. y_ = tf.placeholder(tf.float32, shape=[None, 26])
  64.  
  65. # 开始定义用于初始化的两个函数
  66. def weight_variable(shape):
  67. initial = tf.truncated_normal(shape, stddev=0.1)
  68. return tf.Variable(initial)
  69.  
  70. def bias_variable(shape):
  71. initial = tf.constant(0.1, shape=shape)
  72. return tf.Variable(initial)
  73.  
  74. # 完成初始化函数定义
  75.  
  76. # 开始定义卷积和池化的函数
  77. # 卷积使用1步长(stride size),0边距(padding size)的模板,保证输出和输入大小相同
  78. # 池化用简单传统的2x2大小的模板做max pooling,因此输出的长宽会变为输入的一半
  79.  
  80. def conv2d(x, W):
  81. return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
  82.  
  83. def max_pool_2x2(x):
  84. return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1, 2, 2, 1], padding='SAME')
  85. # 完成卷积池化函数定义
  86.  
  87. # 开始定义神经网络结构定义
  88. # 第一层卷积,卷积在每个5x5的patch中算出32个特征
  89. W_conv1 = weight_variable([5, 5, 1, 32])
  90. b_conv1 = bias_variable([32])
  91. x_image = tf.reshape(x, [-1, 28, 28, 1])
  92. # 第2、第3维对应图片的宽、高,最后一维代表图片的颜色通道数(因为是灰度图所以这里的通道数为1,如果是rgb彩色图,则为3)
  93. h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
  94. h_pool1 = max_pool_2x2(h_conv1)
  95.  
  96. # 第二层卷积,每个5x5的patch会得到64个特征
  97. W_conv2 = weight_variable([5, 5, 32, 64])
  98. b_conv2 = bias_variable([64])
  99. h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
  100. h_pool2 = max_pool_2x2(h_conv2)
  101.  
  102. # 有1024个神经元的全连接层,此时图片大小为7*7
  103. W_fc1 = weight_variable([7*7*64, 1024])
  104. b_fc1 = bias_variable([1024])
  105. h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
  106. h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
  107.  
  108. # 为了减少过拟合,在输出层之前加入dropout。用一个placeholder代表一个神经元的输出在dropout中保持不变的概率。
  109. # 这样可以在训练过程中启用dropout,在测试过程中关闭dropout。
  110. keep_prob = tf.placeholder(tf.float32)
  111. h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
  112. # softmax输出层
  113. W_fc2 = weight_variable([1024, 26])
  114. b_fc2 = bias_variable([26])
  115. y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
  116. # 应为 y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
  117. # 完成神经网络结构定义
  118.  
  119. # 开始定义训练和评估操作
  120. # 用更加复杂的ADAM优化器来做梯度最速下降,在feed_dict中加入额外的参数keep_prob来控制dropout比例
  121. cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
  122. train_step = tf.train.AdamOptimizer(1e-6).minimize(cross_entropy)
  123. correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
  124. accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
  125. # 完成训练和评估操作的定义
  126.  
  127. # 开始定义储存器操作并装载已经训练过的神经网络
  128. saver = tf.train.Saver(write_version=tf.train.SaverDef.V1)
  129. sess = tf.InteractiveSession()
  130. saver.restore(sess, "cnnres/model.ckpt")
  131. # sess.run(tf.global_variables_initializer())
  132. # 完成定义储存器操作和装载神经网络
  133.  
  134. # 开始对神经网络进行输入测试
  135. res = sess.run(y_conv, feed_dict={x: test_data, keep_prob: 1.0})
  136. temp = np.argmax(res)
  137. letter = chr(97+temp)
  138. print('The test letter is '+letter)
  139. # 完成测试

备注:

1.要求已经被训练完成的模型储存在cnnres/model.ckpt

2.预测函数为:res = sess.run(y_conv, feed_dict={x: test_data, keep_prob: 1.0})

不要试图计算y_占位符的值,那是用于训练的,不是用于结果预测的

对CNN的效果备注和研究:

1.在训练集为较粗字体的情况下测试图片必须相应采用较粗字体,否则结果很差

Tensorflow搭建卷积神经网络识别手写英语字母的更多相关文章

  1. 使用TensorFlow的卷积神经网络识别手写数字(3)-识别篇

    from PIL import Image import numpy as np import tensorflow as tf import time bShowAccuracy = True # ...

  2. 使用TensorFlow的卷积神经网络识别手写数字(2)-训练篇

    import numpy as np import tensorflow as tf import matplotlib import matplotlib.pyplot as plt import ...

  3. 使用TensorFlow的卷积神经网络识别手写数字(1)-预处理篇

    功能: 将文件夹下的20*20像素黑白图片,根据重心位置绘制到28*28图片上,然后保存.经过预处理的图片有利于数字的准确识别.参见MNIST对图片的要求. 此处可下载已处理好的图片: https:/ ...

  4. PyTorch基础——使用卷积神经网络识别手写数字

    一.介绍 实验内容 内容包括用 PyTorch 来实现一个卷积神经网络,从而实现手写数字识别任务. 除此之外,还对卷积神经网络的卷积核.特征图等进行了分析,引出了过滤器的概念,并简单示了卷积神经网络的 ...

  5. Pytorch卷积神经网络识别手写数字集

    卷积神经网络目前被广泛地用在图片识别上, 已经有层出不穷的应用, 如果你对卷积神经网络充满好奇心,这里为你带来pytorch实现cnn一些入门的教程代码 #首先导入包 import torchfrom ...

  6. 使用TensorFlow的卷积神经网络识别自己的单个手写数字,填坑总结

    折腾了几天,爬了大大小小若干的坑,特记录如下.代码在最后面. 环境: Python3.6.4 + TensorFlow 1.5.1 + Win7 64位 + I5 3570 CPU 方法: 先用MNI ...

  7. TensorFlow卷积神经网络实现手写数字识别以及可视化

    边学习边笔记 https://www.cnblogs.com/felixwang2/p/9190602.html # https://www.cnblogs.com/felixwang2/p/9190 ...

  8. 用BP人工神经网络识别手写数字

    http://wenku.baidu.com/link?url=HQ-5tZCXBQ3uwPZQECHkMCtursKIpglboBHq416N-q2WZupkNNH3Gv4vtEHyPULezDb5 ...

  9. 卷积神经网络CNN 手写数字识别

    1. 知识点准备 在了解 CNN 网络神经之前有两个概念要理解,第一是二维图像上卷积的概念,第二是 pooling 的概念. a. 卷积 关于卷积的概念和细节可以参考这里,卷积运算有两个非常重要特性, ...

随机推荐

  1. CAS部署在Windows上

    我这里有下载好的cas.war和tomcat7,然后我在将cas.war放在tomcat目录下的webapps下,启动tomcat自动解压war包.浏览器输入http://localhost:8080 ...

  2. P1450 [HAOI2008]硬币购物(完全背包+容斥)

    P1450 [HAOI2008]硬币购物 暴力做法:每次询问跑一遍多重背包. 考虑正解 其实每次跑多重背包都有一部分是被重复算的,浪费了大量时间 考虑先做一遍完全背包 算出$f[i]$表示买价值$i$ ...

  3. Linux网络属性管理

    Linux网络属性管理 局域网:以太网,令牌环网 Ethernet: CSMA/CD 冲突域 广播域 MAC:Media Access Control 48bits: 24bits: 24bits: ...

  4. Python3 tkinter基础 Tk quit 点击按钮退出窗体

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  5. 课后作业机票,赌骰子游戏,switch的使用实例

    一,课后第三题机票 package com.bd22; import java.util.Scanner; public class AirTicket { public static void ma ...

  6. 论文笔记:Towards Diverse and Natural Image Descriptions via a Conditional GAN

    论文笔记:Towards Diverse and Natural Image Descriptions via a Conditional GAN ICCV 2017 Paper: http://op ...

  7. 信息安全之路-web-xss学习(1)

    关于xss反射性漏洞 1.未加任何过滤的 (1).在dvwa平台上可以看到源代码,如下 low级别 为了便于理解,代码如下: <?php // Is there any input? if( a ...

  8. Python+MapReduce实现矩阵相乘

    算法原理 map阶段 在map阶段,需要做的是进行数据准备.把来自矩阵A的元素aij,标识成p条<key, value>的形式,key="i,k",(其中k=1,2,. ...

  9. Vue-admin工作整理(十五):Ajax-跨域问题

    跨域的定义: 解决方法: 1.前端通过配置来解决跨域问题:自定义的vue.config.js配置文件来进行跨域处理:就是只要存在跨域现象 都会代理到一个指定的地址上 devServer: { prox ...

  10. dp入门之01背包问题

    ...通过暴力手推得到的一点点感觉 动态规划是相对于贪心算法的一种取得最优解的算法,通过对每一步的取舍判断从 0 推到所拥有的第 n 件物品,每次判断可以列写出状态转移方程,通过记忆化相对暴力地取得最 ...