00.写在前面
由于最近要出去实习,所以开始接触机器学习的内容,逐步将自己的实验内容整理成博,以供以后使用。这次主要是关于验证码的识别和手写数字的识别,其实两者根本上是相同的原理
工具: pycharm + python3.5 + keras
01.训练数据的获取
为了能得到后面实验所需的数据,我自己手写了一部分数据用于制作训练数据,并将其转化为数字格式。
1.1 调整图像大小与明暗,使得手写部分更为突出
这里在ps里面调整为32*32像素的大小,并且更改了对比度等,使得手写部分更为容易识别。
1.2 图片转为数字文本
我们知道在算法当中,直接的图片是无法识别的,需要使用能表征图片特征的元素来代替它。所以这里很容易想到用图片的像素值来代替,即原本的白色用0表示,黑色用1表示。(这里存在一定问题,在像素改变后,原本的黑色像素值不再是(0,0,0)而是接近黑色的灰色,所以在程序中可以识别白色,然后剩下的赋1。这里假设都是优质数据,所以直接按黑白来区分了)
Ps.读取的时候,图片会被颠倒,不是你在windows里面看到的样子,所以是getpixel((j,i))
from PIL import Image
im = Image.open("21.jpg")
fh = open('2_1.txt','w')
for i in range(0,im.size[1]):
for j in range(0,im.size[0]):
cl = im.getpixel((j,i))
clall = cl[0]+cl[1]+cl[2]
if clall == 0:
fh.write("1")
else:
fh.write("0")
fh.write("\n")
fh.close()
1.3 重复操作,得到足够多的训练样本
这里收集了每个数字的多种写法,一共得到1000+的训练样本,最后一并上传在github中供大家使用。
02.数据的预处理
为了后面训练模型的使用,我们需要从样本数据中得到两部分数据:(1)特征值,即我们上一步中得到的32*32的矩阵;(2)结果值,即每个矩阵代表的数字,也是我们识别的结果。
def datatoarray(fname):
arr = []
fh = open(fname)
for i in range(0, 32):
thisline = fh.readline()
for j in range(0, 32):
arr.append(int(thisline[j]))
return arr
def seplabel(fname):
filestr = fname.split(".")[0]
label = int(filestr.split("_")[0])
return label
def traindata():
labels = []
trainfile = listdir("D:/13.NerveNet/traindata")
num = len(trainfile)
# 长度1024(列),每一行存储一个文件
# 用一个数组存储所有训练数据,行:文件总数,列:1024
trainarr=zeros((num, 1024))
for i in range(0, num):
thisfname = trainfile[i]
thislabel = seplabel(thisfname)
labels.append(thislabel)
trainarr[i, :] = datatoarray("D:/13.NerveNet/traindata/"+thisfname)
return trainarr, labels
trainarr, labels = traindata()
# 数据类型和存储格式的转换
xf = pda.DataFrame(trainarr)
yf = pda.DataFrame(labels)
tx2 = xf.as_matrix().astype(int)
ty2 = yf.as_matrix().astype(int)
03.数据的预处理
根据bp神经网络的原理,确定输入层、输出层、激活函数等参数。
model = Sequential()
# 输入层
# 需指定输入层的层数和特征维数
model.add(Dense(10, input_dim=1024))
model.add(Activation("relu"))
# 输出层
model.add(Dense(1, input_dim=1))
model.add(Activation("sigmoid"))
# 模型的编译
model.compile(loss="mean_squared_error", optimizer="adam")
# 训练
model.fit(tx2, ty2, nb_epoch=10000, batch_size=10)
# 预测分类
rst = model.predict_classes(tx2).reshape(len(tx2))
# 计算正确率
x = 0
for i in range(0, len(tx2)):
if rst[i] != ty2[i]:
x += 1
print(1-x/len(tx2))
04.写在最后
其实最总要的不是代码如何写,而是去理解神经网络的原理。这里只是简答的一个运用。当然可以用来做一些预测,还有待学习。
代码和训练数据已经上传到github,供大家使用。神秘地址:
https://github.com/moonlighf/Leetcode/tree/master/04.bpNerveNet_WriteNum