在上一篇文章中,我们对图片进行了预处理,构建了数据集。今天我们将使用这个数据集来训练神经网络。学习数据集我们必须首先观察我们得到的任何数据集。一是我们要学会区分自己,这样才能引导神经网络更有针对性地进行分类;另一个是看我们要处理的问题的复杂性,这也很容易理解我们的神经网络有多复杂(或者说“更多”)。deep")。上图是我们数据集的截图,观察到“0”、“1”、“9”、“I”、“O”这五个字符没有图片,是不是我们的数据集有误?查看原始验证码图片发现确实没有这个字符,其实仔细想想就知道这些字符很容易和其他字符混淆,所以大概率可以生成验证码的时候去掉,这里要注意程序员的细心了,点个赞~另外观察也发现每个字符文件夹下的图片数量都差不多,这也是为了让神经神经网络设计神经网络说了这么多,终于要开始设计神经网络了,用Python写神经网络的库有很多,比如TensorFlow,PyTorch,Keras,等这里我们就不打碟了使用各自的优点和缺点。我在工作中使用Keras,所以这里我们使用Keras。因为是图像分类,我们用到了图像任务中最常用的神技——卷积神经网络(CNN)。fromkeras.layersimportFlatten,Input,Dropout,Conv2D,MaxPooling2D,Densefromkeras.modelsimportModelfromkeras.optimizersimportAdamdefmodel(input_size,class_num):输入=输入(shape=input_size)x=Conv2D(16,(3,3),activation='relu',padding='same')(输入)x=MaxPooling2D((2,2),strides=(2,2))(x)x=Conv2D(64,(3,3),activation='relu',padding='same')(input)x=MaxPooling2D((2,2),strides=(2,2))(x)x=Conv2D(256,(3,3),激活='relu',padding='same')(input)x=MaxPooling2D((2,2),strides=(2,2))(x)x=Flatten()(x)x=Dense(1024,激活='relu')(x)x=Dropout(0.5)(x)x=Dense(2048,activation='relu')(x)x=Dropout(0.5)(x)x=Dense(class_num,activation='softmax')(x)model=Model(input=input,output=x)model.compile(optimizer=Adam(lr=1e-4),loss='categorical_crossentropy',metrics=['accuracy'])返回模型这个基本上,它是最简单的CNN。模型结构大致如下:simpleconvolution-pooling-convolution-pooling-convolution-pooling-fullconnection-fullconnection-dropout结构,因为问题很简单,所以模型结构不需要很复杂来训练神经网络。网络设计好后,就可以开始训练了,也就是想办法把训练图片喂给模型,让它自动更新各种参数。因为我们前期已经做了一些工作,所以我们只需要按照类别读取图片,然后输入到模型的中间区域即可。读取图片生成标签的代码如下:image_path='./chars'data=[]labels=[]imagePaths=[]forlabelinos.listdir(image_path):forimageinos.listdir(os.path.join(image_path,label)):imagePaths.append(os.path.join(image_path,label),image))#获取图片数据路径,方便后续读取imagePaths=sorted(imagePaths)random.seed(42)random.shuffle(imagePaths)#遍历并读取imagePaths中imagePath的数据:#读取图像数据image=cv2.imread(imagePath,0)image=cv2.resize(image,(16,16))image=np.expand_dims(image,axis=-1)data.append(image)#读取标签label=imagePath.split(os.path.sep)[-2]labels.append(label)#缩放图像数据data=np.array(data,dtype="float")/255.0labels=np.array(labels)#数据集分割(trainX,testX,trainY,testY)=train_test_split(data,labels,test_size=0.25,random_state=42)#将标签转换为one-hot编码格式lb=LabelBinarizer()trainY=lb.fit_transform(trainY)testY=lb.transform(testY)训练模型的代码如下:print("------准备训练网络------")#设置初始化超参数EPOCHS=50BS=16#构建卷积神经网络model=model(input_size=(16,16,1),class_num=31)H=model.fit(trainX,trainY,validation_data=(testX,testY),epochs=EPOCHS,batch_size=BS)训练模型的代码最少,有没有发现训练一个神经网络其实一点都不难?看一下训练神经网络时的输出:Trainon332samples,validateon111samplesEpoch1/5016/332[>.........................................]-ETA:7s-损失:3.4399-精度:0.062532/332[=>...............]-ETA:4s-损失:3.4547-精度:0.031248/332[===>..............................]-ETA:3s-损失:3.4442-准确度:0.020864/332[====>......................]-ETA:2s-损失:3.4401-精度:0.031280/332[======>...........]-ETA:2s-损失:3.4368-准确度:0.025096/332[=======>................]-ETA:2s-损失:3.4366-精度:0.0208112/332[==========>......]-ETA:1s-损失:3.4371-精度:0.0179128/332[===========>......................]-ETA:1s-损失:3.4373-精度:0.0156144/332[=============>.................]-ETA:1s-损失:3.4358-精度:0.0139160/332[==============>................]-ETA:1s-损失:3.4337-精度:0.0188176/332[==============>......]-ETA:1s-损失:3.4330-精度:0.0170192/332[================>................]-ETA:1s-损失:3.4310-精度:0.0156208/332[=================>。......]-ETA:0s-损失:3.4313-精度:0.0192224/332[===================>.........]-ETA:0s-损失:3.4325-精度:0.0179240/332[====================>.........]-ETA:0s-损失:3.4300-精度:0.0208256/332[======================>......]-ETA:0s-损失:3.4315-精度:0.0195272/332[=======================>......]-ETA:0s-损失:3.4334-精度:0.0184288/332[=========================>....]-ETA:0s-损失:3.4341-精度:0.0208304/332[==========================>...]-ETA:0s-损失:3.4349-精度:0.0197320/332[===========================>..]-ETA:0s-损失:3.4315-精度:0.0281332/332[==============================]-2秒7毫秒/步-损失:3.4340-准确度:0.0271-val_loss:3.4193-val_accuracy:0.0270神经网络在运行每个Epoch时都会更新参数,这样会不断更新,最终达到最优:Epoch50/5016/332[>............]-ETA:1s-损失:0.0155-准确度:1.000032/332[=>..........................................]-ETA:1s-损失:0.0132-准确度:1.000048/332[===>.........]-ETA:1s-损失:0.0259-精度:1.000064/332[====>....................................]-ETA:1s-损失:0.0289-准确度:1.000080/332[======>....................]-ETA:1s-损失:0.0247-准确度:1.000096/332[=======>.........................................]-ETA:1s-损失:0.0271-精度:1.0000112/332[==========>...........]-ETA:1s-损失:0.0251-准确度:1.0000128/332[===========>.........]-ETA:1s-损失:0.0243-精度:1.0000144/332[=============>......]-ETA:1s-损失:0.0230-精度:1.0000160/332[==============>.....]-ETA:1s-损失:0.0234-精度:1.0000176/332[===============>......................]-ETA:0s-损失:0.0318-精度:0.9943192/332[================>。......]-ETA:0s-损失:0.0372-精度:0.9896208/332[=================>...........]-ETA:0s-损失:0.0354-精度:0.9904224/332[===================>..........]-ETA:0s-损失:0.0395-准确度:0.9866240/332[====================>.........]-ETA:0s-损失:0.0521-精度:0.9833256/332[======================>......]-ETA:0s-损失:0.0491-精度:0.9844272/332[=======================>......]-ETA:0s-损失:0.0531-精度:0.9816288/332[=======================>....]-ETA:0s-损失:0.0510-精度:0.9826304/332[========================>...]-ETA:0s-损失:0.0488-精度:0.9836320/332[=========================>..]-ETA:0s-损失:0.0488-精度:0.9844332/332[==============================]-2s6ms/step-loss:0.0478-accuracy:0.9849-val_loss:0.0197-val_accuracy:0.9910以下是整个训练过程中各个参数值??的曲线:简单来说,在训练过程中,无论是训练集还是验证集,它们的损失值都不断下降到无限接近于0,而模型的准确率无限接近于1。为了测试神经网络,我们随机取两个字符进行测试:测试代码如下:#加载测试数据并进行相同的预处理操作image=cv2.imread('./test_chars/3/1.jpg',0)output=image.copy()image=cv2.resize(image,(16,16))#缩放图像数据image=image.astype("float")/255.0image=np.expand_dims(image,axis=-1)#展平图像image=image.reshape((1,image.shape[0],image.shape[1],image.shape[2]))#读取模型和标签print("------读取模型和标签------")model=load_model('./output/cnn.model')lb=pickle.loads(open('./output/cnn_lb.pickle',"rb").read())#预测preds=model.predict(image)#get预测结果及其对应的标签i=preds.argmax(axis=1)[0]label=lb.classes_[i]#将结果绘制在图像中text="{}:{:.2f}%".format(label,preds[0][i]*100)print(text)输出结果为:tryagain:output结果为:两次实验的结果表明我们的神经网络模型的性能是可以接受的。本系列的所有源码都会放在下面的github仓库中,有需要的可以参考,有问题请指正,谢谢!https://github.com/TitusWongCN/AutoTokenAppointment得到了最新消息,最新的纪念币将在本月19日开放预约,所以这个系列也将在这个时候结束。敬请期待自动预约的最后部分~第一期:蟒盘纪念币系列一:简介第二期:蟒盘纪念币系列二:身份验证码01第三期:蟒盘纪念币系列二:身份验证码02第四期:蟒盘纪念币系列之二:身份验证码03
