简 介: 本文对于作业中给定的机械数字字符识别问题进行了实验研究。通过对于采样1000样本的数据集合进行训练,经过增加DropOut的可以增加网络的泛化性能。对于网络规模的增加对训练精度没有明显的改进。由于数据集合比较小,因此作业中的一些结论并不具有代表特性。

关键词旋转数字DropoutLeNet

#mermaid-svg-r8KwEarL5PsVwmgF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-r8KwEarL5PsVwmgF .error-icon{fill:#552222;}#mermaid-svg-r8KwEarL5PsVwmgF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-r8KwEarL5PsVwmgF .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-r8KwEarL5PsVwmgF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-r8KwEarL5PsVwmgF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-r8KwEarL5PsVwmgF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-r8KwEarL5PsVwmgF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-r8KwEarL5PsVwmgF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-r8KwEarL5PsVwmgF .marker.cross{stroke:#333333;}#mermaid-svg-r8KwEarL5PsVwmgF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-r8KwEarL5PsVwmgF .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-r8KwEarL5PsVwmgF .cluster-label text{fill:#333;}#mermaid-svg-r8KwEarL5PsVwmgF .cluster-label span{color:#333;}#mermaid-svg-r8KwEarL5PsVwmgF .label text,#mermaid-svg-r8KwEarL5PsVwmgF span{fill:#333;color:#333;}#mermaid-svg-r8KwEarL5PsVwmgF .node rect,#mermaid-svg-r8KwEarL5PsVwmgF .node circle,#mermaid-svg-r8KwEarL5PsVwmgF .node ellipse,#mermaid-svg-r8KwEarL5PsVwmgF .node polygon,#mermaid-svg-r8KwEarL5PsVwmgF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-r8KwEarL5PsVwmgF .node .label{text-align:center;}#mermaid-svg-r8KwEarL5PsVwmgF .node.clickable{cursor:pointer;}#mermaid-svg-r8KwEarL5PsVwmgF .arrowheadPath{fill:#333333;}#mermaid-svg-r8KwEarL5PsVwmgF .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-r8KwEarL5PsVwmgF .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-r8KwEarL5PsVwmgF .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-r8KwEarL5PsVwmgF .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-r8KwEarL5PsVwmgF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-r8KwEarL5PsVwmgF .cluster text{fill:#333;}#mermaid-svg-r8KwEarL5PsVwmgF .cluster span{color:#333;}#mermaid-svg-r8KwEarL5PsVwmgF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-r8KwEarL5PsVwmgF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

作业准备
目 录
Contents
作业要求
数据准备
构建网络
构建加载函数
构建LeNet网络
构建训练过程
训练网络
基本训练
利用模型去识
别红色字符
使用1000个灰度
图片训练模型
作业总结
附录

§01 作业准备


1.1 作业要求

根据 2021年人工神经网络第四次作业要求 对于第四次作业的要求,将作业条件整理如下:

1.1.1 数据库

  ROTATEDIGIT数据集合是采集到机械电能表显示的数字。这类数字中包含有数字滚轮在不同角度下数字的图片。这些数字不同角度除了对应了数字本身,还代表了整数之间的小数分量。

▲ 图1.1.1 机械电能表上的旋转数字

  在ROTATEDIGIT目录下包括有如下六个数据文件:

▲ 图1.1.2 六个数据文件

  将数据库使用MATLAB命令LOAD调入之后,会产生以下数据变量:

  1. digitsize: 表示数字图像的尺寸

  2. digit:1000×2128×3,数字图片。前面是数字图片的个数,中间是宽×高,后面是RGB三维。

  3. labels:数字标签:0~9

  4. fraction:表示数字整数之后的小数。即反映了数字旋转的程度。fraction部分,有的数据集合存在,有的不存在。

1.1.2 实验要求

  ① 选择合适的神经网络,完成对数据集合的字符识别。

  ② 讨论使用某一类数字集合训练之后的网络,在另外数字集合上的泛化性能。

  ③ 讨论网络正则化的方法对于网络泛化能力的影响:
  1. 对于网络权系数范数约束;
  2. 对输入样本增加噪声;
  3. 对输入样板进行变形增强;
  4. 使用Drop-out技术训练网络

  ④ 对于有Fraction标签的数据集合,构造一个具有输出带有小数点数字输出的回归网络。并讨论它与前面分类网络在网络结构,训练方法等方面的特点。

1.2 数据准备

1.2.1 下载并解压缩数据文件

  从网络学堂下载第四次作业数据文件,ANN-DATA.ZIP,经过解压缩之后,可以获得如下子目录。

├─CIFAR-10
├─FORBIDDEN
├─FruitAnimal
│  ├─动物
│  │  └─动物
│  └─水果
│      └─水果
├─MNIST
└─ROTATEDIGIT

  在ROTATEDEGIT目录中,具有如下六个MATLAB 的.MAT文件。

    black_10.matblack_11.matblack_1_1.matred_10.matred_20.matred_21.mat

1.2.2 Studio环境

  将上述数据文件上载到AI Studio的的work目录中。

  • 注意: 不要在data目录中存储数据文件。这个目录只是用于存储临时生成的数据文件。在下次启动的时候,该目录中除了项目一开始添加的数据文件之外,其它的数据和子目录将会被清除。

  上载到AI Studio work 子目录 rotatedigit子目录中的数据文件:

▲ 图1.2.1 上载到AI Studio work 子目录 rotatedigit子目录中的数据文件:

1.2.3 读取和分析数据

(1)安装mat4py

  根据 在Python读取MATLAB数据文件 介绍,利用mat4py读取MATLAB的数据文件的方法,所以需要在notebook环境下安装mat4py软件包。

! pip install mat4py
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting mat4pyDownloading https://pypi.tuna.tsinghua.edu.cn/packages/e8/56/41b3ffd7b5f3eb3056979e0dc37de184c6e5dacd1a353e5de42323e7d138/mat4py-0.5.0-py2.py3-none-any.whl
Installing collected packages: mat4py
Successfully installed mat4py-0.5.0

(2)读取分析数据文件

  读取 black_10.mat 数据文件并显示其中的内容。

  由于在原来的数据存在彩色数字图片数据,这是三维的数据。

  MATLAB的数据文件中存在三维度的数组,在使用 mat4py 的 loadmat 函数读取该文件的时候,会出现错误。

▲ 图1.2.2 MATLAB的数据文件中存在三维度的数组

import sys,os,math,time
import matplotlib.pyplot as plt
from numpy import *
import mat4pydatafile = '/home/aistudio/work/rotatedigit/black_10.mat'data = mat4py.loadmat(datafile)print(data.keys())
---------------------------------------------------------------------------
ParseError                                Traceback (most recent call last)
/tmp/ipykernel_250/1524074423.py in <module>6 datafile = '/home/aistudio/work/rotatedigit/black_10.mat'7
----> 8 data = mat4py.loadmat(datafile)9 10 print(data.keys())/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/mat4py/loadmat.py in loadmat(filename, meta)458     # read data elements459     while not eof(fd):
--> 460         hdr, next_position, fd_var = read_var_header(fd, endian)461         name = hdr['name']462         if name in mdict:/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/mat4py/loadmat.py in read_var_header(fd, endian)254                          'got {}'.format(etypes['miMATRIX']['n'], mtpn))255     # read the header
--> 256     header = read_header(fd, endian)257     return header, next_pos, fd258 /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/mat4py/loadmat.py in read_header(fd, endian)222     header['n_dims'] = len(header['dims'])223     if header['n_dims'] != 2:
--> 224         raise ParseError('Only matrices with dimension 2 are supported.')225     header['name'] = read_elements(fd, endian, ['miINT8'], is_name=True)226     return headerParseError: Only matrices with dimension 2 are supported.

(3)解决方法

  在MATLAB中将原来存储数字的图片矩阵修改成二维的数组,将原有的存储数字图片数组尺寸:(120×1776×3)修改成(120×5328)。然后重新存储这些数据文件,再上载AI Studio环境进行读取。

 Ⅰ.在MATLAB修改数组并存储
>>> digit2 = reshape(digit, 120, 5328)
>>> save('d:\temp\black_10_mod', 'digit2', 'labels')
 Ⅱ.上载读取测试
import sys,os,math,time
import matplotlib.pyplot as plt
from numpy import *
import mat4pydatafile = '/home/aistudio/work/rotatedigit/black_10_mod.mat'data = mat4py.loadmat(datafile)print(data.keys())

dict_keys(['digit2', 'labels'])

  可以看到在将原有的MATLAB数据文件中的三维数组修改成二维之后,便可以使用mat4py的loadmat函数正常读取了。

labels = data['labels']
images = data['digit2']print(type(labels), "\n",  shape(labels))
print(type(images), "\n",  shape(images))

<class 'list'>
(120,)
<class 'list'>
(120, 5328)

print(labels)

['4', '4', '4', '4', '4', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '9', '9', '9', '9', '9', '9', '9', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '9', '9', '9', '9', '9', '1', '1', '1', '1', '1', '0', '2', '2', '2', '2', '2', '2', '2', '0', '0', '0', '0', '0', '0', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4', '4', '4']

1.2.4 显示图片

(1)显示单张图片

imagewidth = 37
imageheight = 48imgdata = array(images[10]).reshape(3, imageheight, imagewidth).swapaxes(1,2).T
print(shape(imgdata))plt.figure(figsize=(5, 7))
plt.imshow(imgdata)

(48, 37, 3)
<matplotlib.image.AxesImage at 0x7f769d4ce350>
第10张图片对应的数字图片:

▲ 图1.2.3 第10张图片对应的数字图片:

(2)顺序显示所有图片

  顺序显示所有的图片,这是所有采集到的旋转移动的数字图片。

▲ 图1.2.4 顺序显示所有的图片

gifpath = '/home/aistudio/GIF'filedim = os.listdir(gifpath)
for f in filedim:fn = os.path.join(gifpath, f)if os.path.isfile(fn):os.remove(fn)for i in range(len(labels)):imgdata = array(images[i]).reshape(3,imageheight, imagewidth).swapaxes(1,2).Tplt.figure(figsize=(5,7))plt.imshow(imgdata)savefile = os.path.join(gifpath, '%03d.jpg'%i)plt.savefig(savefile)print('Save figure:%d'%i)

1.2.5 数据全部处理

  将所有的六个MATLAT的数据文件都按照上面的方式,首先在MATLAB中将图片都修改成一维数组,然后在重新存储到MAT文件,上载到AI Studio中进行处理。

(1)black_11_mod

图片参数:
图片尺寸:39×56
图片数量:180
图片色彩:黑白图片

.同样的数字,只是图片尺寸为39,56。

▲ .同样的数字,只是图片尺寸为39,56

(2)mod

数据参数:
图片尺寸平:38×56
图片色彩彩色图片
图片数量:1000

▲ 图1.2.6 彩色数字

§02 构建网络


2.1 构建加载函数

2.1.1 读取数据并预处理

(1)读取数据

import sys,os,math,time
import matplotlib.pyplot as plt
from numpy import *
import mat4pyimport paddle#------------------------------------------------------------
datafile = '/home/aistudio/work/rotatedigit/black_11_mod.mat'data = mat4py.loadmat(datafile)
print(data.keys())

dict_keys(['digit2', 'digitsize', 'labels'])

(2)预处理数据

  • 将图片输出处理成0 ~ 1的数据,并将存储维度修改成 (180,3,56,39)这种RGB分层的格式;
  • 将labels由原来的字符串修改成 0 - 9 的数据。
labels = data['labels']
images = data['digit2']
digitsize = data['digitsize']print(type(labels), "\n",  shape(labels))
print(type(images), "\n",  shape(images))
print(digitsize)imagewidth = digitsize[0]
imageheight = digitsize[1]imgdata = [(array(d)/255).reshape(3,imageheight,imagewidth).swapaxes(1,2) for d in images]
print(shape(imgdata))
imglabel = array([int(s) for s in labels])
print(shape(imglabel), "\n",  imglabel)
<class 'list'> (180,)
<class 'list'> (180, 6552)
[39, 56]
(180, 3, 39, 56)
(180,) [4 4 4 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 0 6 6 6 6 6 6 6 6 60 6 6 6 6 7 7 7 7 7 0 7 7 7 7 7 7 7 7 7 0 7 7 7 7 8 8 8 8 8 0 8 8 8 8 8 88 8 8 8 8 8 8 9 9 9 9 9 0 0 0 0 0 0 0 0 9 9 9 9 9 9 9 9 9 0 9 9 9 9 0 0 00 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 23 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4]

2.1.2 构建训练加载函数

class Dataset(paddle.io.Dataset):def __init__(self, num_samples):super(Dataset, self).__init__()self.num_samples = num_samplesdef __getitem__(self, index):data = imgdata[index]label = imglabel[index]return paddle.to_tensor(data,dtype='float32'), paddle.to_tensor(label,dtype='int64')def __len__(self):return self.num_samples_dataset = Dataset(len(imglabel))
train_loader = paddle.io.DataLoader(_dataset, batch_size=10, shuffle=True)

2.2 构建LeNet网络

imgwidth = shape(imgdata)[-2]
imgheight = shape(imgdata)[-1]
inputchannel = 3
kernelsize   = 5
targetsize = 10
ftwidth = ((imgwidth-kernelsize+1)//2-kernelsize+1)//2
ftheight = ((imgheight-kernelsize+1)//2-kernelsize+1)//2class lenet(paddle.nn.Layer):def __init__(self, ):super(lenet, self).__init__()self.conv1 = paddle.nn.Conv2D(in_channels=inputchannel, out_channels=6, kernel_size=kernelsize, stride=1, padding=0)self.conv2 = paddle.nn.Conv2D(in_channels=6, out_channels=16, kernel_size=kernelsize, stride=1, padding=0) self.mp1    = paddle.nn.MaxPool2D(kernel_size=2, stride=2)self.mp2    = paddle.nn.MaxPool2D(kernel_size=2, stride=2)self.L1     = paddle.nn.Linear(in_features=ftwidth*ftheight*16, out_features=120)self.L2     = paddle.nn.Linear(in_features=120, out_features=86)self.L3     = paddle.nn.Linear(in_features=86, out_features=targetsize)def forward(self, x):x = self.conv1(x)x = paddle.nn.functional.relu(x)x = self.mp1(x)x = self.conv2(x)x = paddle.nn.functional.relu(x)x = self.mp2(x)x = paddle.flatten(x, start_axis=1, stop_axis=-1)x = self.L1(x)x = paddle.nn.functional.relu(x)x = self.L2(x)x = paddle.nn.functional.relu(x)x = self.L3(x)return xmodel = lenet()

2.3 构建训练过程

optimizer = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())
accdim = []
def train(model):model.train()epochs = 20for epoch in range(epochs):for batch, data in enumerate(train_loader()):out = model(data[0])loss = paddle.nn.functional.cross_entropy(out, data[1])acc = paddle.metric.accuracy(out, data[1])loss.backward()optimizer.step()optimizer.clear_grad()accdim.append(acc.numpy())print('Epoch:{}, Loss:{}, Accuracys:{}'.format(epoch, loss.numpy(), acc.numpy()))#------------------------------------------------------------train(model)
paddle.save(model.state_dict(), './work/model.pdparams')

§03 训练网络


3.1 基本训练

3.1.1 训练参数

训练参数:
批次大小:20
训练循环:20
学习速率:0.001

  训练过程中Accuary曲线:

▲ 图3.1.1 训练过程中Accuary曲线

3.1.2 测试识别效果

predict = model(paddle.to_tensor(imgdata, dtype='float32'))
predtarget = paddle.fluid.layers.argmax(predict, axis=1)print(predtarget.numpy())
print(imglabel)error = [a-b for a,b in zip(predtarget.numpy(), imglabel)]
print(error)
Predict: [4 4 4 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 0 6 6 6 6 6 6 6 6 60 6 6 6 6 7 7 7 7 7 0 7 7 7 7 7 7 7 7 7 0 7 7 7 7 8 8 8 8 8 0 8 8 8 8 8 88 8 8 8 8 8 8 9 9 9 9 9 0 0 0 0 0 0 0 0 9 9 9 9 9 9 9 9 9 0 9 9 9 9 0 0 00 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 23 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4]
Labels: [4 4 4 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 0 6 6 6 6 6 6 6 6 60 6 6 6 6 7 7 7 7 7 0 7 7 7 7 7 7 7 7 7 0 7 7 7 7 8 8 8 8 8 0 8 8 8 8 8 88 8 8 8 8 8 8 9 9 9 9 9 0 0 0 0 0 0 0 0 9 9 9 9 9 9 9 9 9 0 9 9 9 9 0 0 00 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 23 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4]
Error: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

  测试了图片对应的LABEL。

3.2 利用模型去识别红色字符

  红色字符是转动角度更加小的数据集合,循环十个数字总共采集了1000个图片。下面测试用100个图片训练的数据集合是否可以识别这1000图片组成的数据集合。

3.2.1 加载红色图片

datafile1 = '/home/aistudio/work/rotatedigit/red_20_mod.mat'data1 = mat4py.loadmat(datafile)

3.2.2 数据预处理

labels1 = data1['labels']
images1 = data1['digit2']
digitsize1 = data1['digitsize']print(type(labels1), "\n",  shape(labels1))
print(type(images1), "\n",  shape(images1))
print(digitsize1)imagewidth1 = digitsize1[0]
imageheight1 = digitsize1[1]imgdata1 = [(array(d)/255).reshape(3,imageheight1,imagewidth1).swapaxes(1,2) for d in images1]
print(shape(imgdata1))
imglabel1 = array([int(s) for s in labels1])
print(shape(imglabel1))

<class 'list'>
(1000,)
<class 'list'>
(1000, 6384)
[38, 56]
(1000, 3, 38, 56)
(1000,)

  红色的图片尺寸为:38×56, 比起模型所需要的39×56小一点。通过在图片最后一列,进行延拓一列将其尺寸补成 39×56,使其能够应用model模型要求。

def imgappend1(a):b = a.swapaxes(0,1).tolist()b.append(b[-1])a = array(b).swapaxes(0,1)return aimgdata2 = array([imgappend1(a) for a in imgdata1])
print(shape(imgdata2))

(1000, 3, 39, 56)

  经过补充尺寸之后图片:

▲ 图3.2.1 经过补充尺寸之后图片

3.2.3 模型预测

import paddle
from paddle.fluid.layers import argmaxpredict = model(paddle.to_tensor(imgdata2, dtype='float32'))
predicttarget = argmax(predict, axis=1).numpy()print('Error:%d'%list(predicttarget == imglabel1).count(False))
print('Total:%d'%len(imglabel1))
Error:801
Total:1000

  可以看到,使用黑白训练的模型,对于彩色(红色)预测的精度只有20%左右。

3.2.4 将彩色图片转换成黑白图片

def img2gray(a):avv = mean(a, axis=0)a = array([avv, avv, avv])return aa = img2gray(imgdata2[0])
plt.figure(figsize=(10,5))
plt.subplot(121)
plt.imshow(a.T)
plt.subplot(122)
plt.imshow(imgdata2[0].T)

  将彩色图片转换成灰度图片。

▲ 图3.2.2 将彩色图片转换成灰度图片

def img2gray(a):avv = mean(a, axis=0)a = array([avv, avv, avv])return aimgdata3 = array([img2gray(a) for a in imgdata2])predict = model(paddle.to_tensor(imgdata3, dtype='float32'))
predicttarget = argmax(predict, axis=1).numpy()
print('Error:%d'%list(predicttarget == imglabel1).count(False))
print('Total:%d'%len(imglabel1))

Error:740
Total:1000

  对比上面的结果来看,改成灰度图片之后,识别的错误率仍然为74%。这说明:

  • 原来在小规模训练下的模型已经处于过学习状态。所以无法对于转动角度更加

3.3 使用1000个灰度图片训练模型

3.3.1 模型训练过程

  利用1000个彩色图片转换成绘图图片之后,再训练LeNet网络。

训练册数:
样本批次大小:100
学习速率:0.001
训练周期:20
总时间:13.44秒

  训练精度与测试精度变化曲线:

▲ 图3.3.1 训练精度与测试精度变化曲线

3.3.2 模型预测小数据集合

predict = model(paddle.to_tensor(imgdata, dtype='float32'))
predtarget = paddle.fluid.layers.argmax(predict, axis=1)print('Predict:', predtarget.numpy())
print('Labels:', "\n",  imglabel)error = [a==b for a,b in zip(predtarget.numpy(), imglabel)]
print('Error:', "\n",  error.count(False))
Predict: [4 4 4 4 8 8 8 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 9 0 0 0 0 0 0 0 0 69 5 6 6 6 6 6 6 6 6 9 7 7 7 7 7 7 7 7 7 9 2 7 2 2 7 7 7 7 5 9 4 4 4 4 4 44 9 4 9 9 9 5 9 9 2 2 2 0 0 0 0 0 0 0 0 9 9 9 9 9 9 9 9 9 0 9 9 9 9 0 0 00 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 22 5 5 8 8 9 9 9 9 9 9 9 9 9 9 9 9 9 3 3 3 7 3 4 4 4 4 4 4 4 4 4]
Labels: [4 4 4 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 0 6 6 6 6 6 6 6 6 60 6 6 6 6 7 7 7 7 7 0 7 7 7 7 7 7 7 7 7 0 7 7 7 7 8 8 8 8 8 0 8 8 8 8 8 88 8 8 8 8 8 8 9 9 9 9 9 0 0 0 0 0 0 0 0 9 9 9 9 9 9 9 9 9 0 9 9 9 9 0 0 00 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 23 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4]
Error: 84

  错误率仍然有40%。这个结果说明,使用大的数据集合也产生了过学习现象。

3.3.3 将网络改成更小的网络

---------------------------------------------------------------------------Layer (type)       Input Shape          Output Shape         Param #
===========================================================================Conv2D-43     [[50, 3, 39, 56]]     [50, 6, 37, 54]          168      MaxPool2D-43    [[50, 6, 37, 54]]     [50, 6, 18, 27]           0       Conv2D-44     [[50, 6, 18, 27]]     [50, 16, 16, 25]         880      MaxPool2D-44    [[50, 16, 16, 25]]    [50, 16, 8, 12]           0       Linear-64        [[50, 1536]]           [50, 30]           46,110     Linear-65         [[50, 30]]            [50, 20]             620      Linear-66         [[50, 20]]            [50, 10]             210
===========================================================================
Total params: 47,988
Trainable params: 47,988
Non-trainable params: 0
---------------------------------------------------------------------------
Input size (MB): 1.25
Forward/backward pass size (MB): 8.74
Params size (MB): 0.18
Estimated Total Size (MB): 10.17
---------------------------------------------------------------------------{'total_params': 47988, 'trainable_params': 47988}

  训练精度变化曲线:

  训练精度与测试精度变化曲线:

▲ 图3.3.2 训练精度与测试精度变化曲线

  从上面可以看到改用小模型之后,在测试集合上的误差增大了。

3.3.4 增加Dropout层

    def forward(self, x):x = self.conv1(x)x = paddle.nn.functional.relu(x)x = self.mp1(x)x = self.conv2(x)x = paddle.nn.functional.relu(x)x = self.mp2(x)x = paddle.flatten(x, start_axis=1, stop_axis=-1)x = self.L1(x)x = paddle.nn.functional.relu(x)x = self.L2(x)x = paddle.nn.functional.relu(x)x = paddle.fluid.layers.dropout(x,0.5)x = self.L3(x)return x

  训练精度与测试精度变化曲线:

▲ 图3.3.3 训练精度与测试精度变化曲线

  训练200循环,训练精度与测试精度变化曲线:

▲ 图3.3.4 训练精度与测试精度变化曲线

3.3.5 增加Conv层

---------------------------------------------------------------------------Layer (type)       Input Shape          Output Shape         Param #
===========================================================================Conv2D-28     [[50, 3, 39, 56]]     [50, 6, 35, 52]          456      MaxPool2D-28    [[50, 6, 35, 52]]     [50, 6, 17, 26]           0       Conv2D-29     [[50, 6, 17, 26]]     [50, 32, 13, 22]        4,832     MaxPool2D-29    [[50, 32, 13, 22]]    [50, 32, 6, 11]           0       Conv2D-30     [[50, 32, 6, 11]]      [50, 64, 2, 7]        51,264     MaxPool2D-30     [[50, 64, 2, 7]]      [50, 64, 1, 3]           0       Linear-40        [[50, 192]]           [50, 120]           23,160     Linear-41        [[50, 120]]            [50, 86]           10,406     Linear-42         [[50, 86]]            [50, 10]             870
===========================================================================
Total params: 90,988
Trainable params: 90,988
Non-trainable params: 0
---------------------------------------------------------------------------
Input size (MB): 1.25
Forward/backward pass size (MB): 9.97
Params size (MB): 0.35
Estimated Total Size (MB): 11.57
---------------------------------------------------------------------------{'total_params': 90988, 'trainable_params': 90988}

  训练精度与测试精度变化曲线:

▲ 图3.3.5 训练精度与测试精度变化曲线

§04 作业总结


  本文对于作业中给定的机械数字字符识别问题进行了实验研究。通过对于采样1000样本的数据集合进行训练,经过增加DropOut的可以增加网络的泛化性能。对于网络规模的增加对训练精度没有明显的改进。

  由于数据集合比较小,因此作业中的一些结论并不具有代表特性。


■ 相关文献链接:

  • 在Python中读取MATLAB的数据文件

● 相关图表链接:

  • 图1.1.1 机械电能表上的旋转数字
  • 图1.1.2 六个数据文件
  • 图1.2.1 上载到AI Studio work 子目录 rotatedigit子目录中的数据文件:
  • 图1.2.2 MATLAB的数据文件中存在三维度的数组
  • 图1.2.3 第10张图片对应的数字图片:
  • 图1.2.4 顺序显示所有的图片
  • .同样的数字,只是图片尺寸为39,56
  • 图1.2.6 彩色数字
  • 图3.1.1 训练过程中Accuary曲线
  • 图3.2.1 经过补充尺寸之后图片
  • 图3.2.2 将彩色图片转换成灰度图片
  • 图3.3.1 训练精度与测试精度变化曲线
  • 图3.3.2 训练精度与测试精度变化曲线
  • 图3.3.3 训练精度与测试精度变化曲线
  • 图3.3.4 训练精度与测试精度变化曲线
  • 图3.3.5 训练精度与测试精度变化曲线

◎ 附录

1、总的训练程序

#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST2.PY                     -- by Dr. ZhuoQing 2021-12-18
#
# Note:
#============================================================from headm import *                 # =
import mat4pyimport paddle#------------------------------------------------------------
#datafile = '/home/aistudio/work/rotatedigit/black_10_mod.mat'
#datafile = '/home/aistudio/work/rotatedigit/red_20_mod.mat'
datafile = '/home/aistudio/work/rotatedigit/black_11_mod.mat'data = mat4py.loadmat(datafile)
printf(data.keys())#------------------------------------------------------------
labels = data['labels']
images = data['digit2']
digitsize = data['digitsize']printf(type(labels), shape(labels))
printf(type(images), shape(images))
printf(digitsize)imagewidth = digitsize[0]
imageheight = digitsize[1]imgdata = [(array(d)/255).reshape(3,imageheight,imagewidth).swapaxes(1,2) for d in images]
printf(shape(imgdata))
imglabel = array([int(s) for s in labels])
printf(shape(imglabel), imglabel)#------------------------------------------------------------
plt.figure(figsize=(5,5))
plt.figure(figsize=(5, 5))
plt.imshow(imgdata[0].T)#------------------------------------------------------------
class Dataset(paddle.io.Dataset):def __init__(self, num_samples):super(Dataset, self).__init__()self.num_samples = num_samplesdef __getitem__(self, index):data = imgdata[index]label = imglabel[index]return paddle.to_tensor(data,dtype='float32'), paddle.to_tensor(label,dtype='int64')def __len__(self):return self.num_samples_dataset = Dataset(len(imglabel))
train_loader = paddle.io.DataLoader(_dataset, batch_size=20, shuffle=True)#------------------------------------------------------------
imgwidth = shape(imgdata)[-2]
imgheight = shape(imgdata)[-1]
inputchannel = 3
kernelsize   = 5
targetsize = 10
ftwidth = ((imgwidth-kernelsize+1)//2-kernelsize+1)//2
ftheight = ((imgheight-kernelsize+1)//2-kernelsize+1)//2class lenet(paddle.nn.Layer):def __init__(self, ):super(lenet, self).__init__()self.conv1 = paddle.nn.Conv2D(in_channels=inputchannel, out_channels=6, kernel_size=kernelsize, stride=1, padding=0)self.conv2 = paddle.nn.Conv2D(in_channels=6, out_channels=16, kernel_size=kernelsize, stride=1, padding=0)self.mp1    = paddle.nn.MaxPool2D(kernel_size=2, stride=2)self.mp2    = paddle.nn.MaxPool2D(kernel_size=2, stride=2)self.L1     = paddle.nn.Linear(in_features=ftwidth*ftheight*16, out_features=120)self.L2     = paddle.nn.Linear(in_features=120, out_features=86)self.L3     = paddle.nn.Linear(in_features=86, out_features=targetsize)def forward(self, x):x = self.conv1(x)x = paddle.nn.functional.relu(x)x = self.mp1(x)x = self.conv2(x)x = paddle.nn.functional.relu(x)x = self.mp2(x)x = paddle.flatten(x, start_axis=1, stop_axis=-1)x = self.L1(x)x = paddle.nn.functional.relu(x)x = self.L2(x)x = paddle.nn.functional.relu(x)x = self.L3(x)return xmodel = lenet()#------------------------------------------------------------optimizer = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())
accdim = []
def train(model):model.train()epochs = 20for epoch in range(epochs):for batch, data in enumerate(train_loader()):out = model(data[0])loss = paddle.nn.functional.cross_entropy(out, data[1])acc = paddle.metric.accuracy(out, data[1])loss.backward()optimizer.step()optimizer.clear_grad()print('Epoch:{}, Loss:{}, Accuracys:{}'.format(epoch, loss.numpy(), acc.numpy()))#------------------------------------------------------------train(model)
paddle.save(model.state_dict(), './work/model.pdparams')#------------------------------------------------------------
plt.figure(figsize=(10, 6))
plt.plot(accdim)
plt.xlabel("Step")
plt.ylabel("Accuracy")
plt.grid(True)
plt.tight_layout()
plt.show()#------------------------------------------------------------predict = model(paddle.to_tensor(imgdata, dtype='float32'))
predtarget = paddle.fluid.layers.argmax(predict, axis=1)print('Predict:', predtarget.numpy())
printf('Labels:', imglabel)error = [a==b for a,b in zip(predtarget.numpy(), imglabel)]
printf('Error:', error.count(False))#------------------------------------------------------------#------------------------------------------------------------
#        END OF FILE : TEST2.PY
#============================================================
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST4.PY                     -- by Dr. ZhuoQing 2021-12-18
#
# Note:
#============================================================from headm import *                 # =import mat4py
import paddle
#------------------------------------------------------------
#datafile = '/home/aistudio/work/rotatedigit/black_10_mod.mat'
datafile1 = '/home/aistudio/work/rotatedigit/red_20_mod.mat'
#datafile = '/home/aistudio/work/rotatedigit/black_11_mod.mat'data1 = mat4py.loadmat(datafile1)
#printf(data1.keys())#------------------------------------------------------------
labels1 = data1['labels']
images1 = data1['digit2']
digitsize1 = data1['digitsize']#printf(type(labels1), shape(labels1))
#printf(type(images1), shape(images1))
#printf(digitsize1)#------------------------------------------------------------
imagewidth1 = digitsize1[0]
imageheight1 = digitsize1[1]imgdata1 = [(array(d)/255).reshape(3,imageheight1,imagewidth1).swapaxes(1,2) for d in images1]
printf(shape(imgdata1))
imglabel1 = array([int(s) for s in labels1])
printf(shape(imglabel1))#------------------------------------------------------------
'''
plt.figure(figsize=(5, 5))
printf(imgdata1[0].shape)
plt.imshow(imgdata1[0].T)'''
#------------------------------------------------------------
def imgappend1(a):b = a.swapaxes(0,1).tolist()b.append(b[-1])a = array(b).swapaxes(0,1)return aimgdata2 = array([imgappend1(a) for a in imgdata1])
printf(shape(imgdata2))#------------------------------------------------------------
'''
plt.figure(figsize=(5, 5))
plt.imshow(imgdata2[0].T)
'''
#------------------------------------------------------------def img2gray(a):avv = mean(a, axis=0)a = array([avv, avv, avv])return aimgdata3 = array([img2gray(a) for a in imgdata2])#------------------------------------------------------------
class Dataset(paddle.io.Dataset):def __init__(self, num_samples):super(Dataset, self).__init__()self.num_samples = num_samplesdef __getitem__(self, index):data = imgdata3[index]label = imglabel1[index]return paddle.to_tensor(data,dtype='float32'), paddle.to_tensor(label,dtype='int64')def __len__(self):return self.num_samples_dataset = Dataset(len(imglabel1))
train_loader = paddle.io.DataLoader(_dataset, batch_size=100, shuffle=True)#------------------------------------------------------------
imgwidth = shape(imgdata3)[-2]
imgheight = shape(imgdata3)[-1]
inputchannel = 3
kernelsize   = 5
targetsize = 10
#ftwidth = ((imgwidth-kernelsize+1)//2-kernelsize+1)//2
#ftheight = ((imgheight-kernelsize+1)//2-kernelsize+1)//2
ftwidth = (((imgwidth-kernelsize+1)//2-kernelsize+1)//2-kernelsize+1)//2
ftheight = (((imgheight-kernelsize+1)//2-kernelsize+1)//2-kernelsize+1)//2class lenet(paddle.nn.Layer):def __init__(self, ):super(lenet, self).__init__()self.conv1 = paddle.nn.Conv2D(in_channels=inputchannel, out_channels=6, kernel_size=kernelsize, stride=1, padding=0)self.conv2 = paddle.nn.Conv2D(in_channels=6, out_channels=32, kernel_size=kernelsize, stride=1, padding=0)self.conv3 = paddle.nn.Conv2D(in_channels=32, out_channels=64, kernel_size=kernelsize, stride=1, padding=0)self.mp1    = paddle.nn.MaxPool2D(kernel_size=2, stride=2)self.mp2    = paddle.nn.MaxPool2D(kernel_size=2, stride=2)self.mp3    = paddle.nn.MaxPool2D(kernel_size=2, stride=2)self.L1     = paddle.nn.Linear(in_features=ftwidth*ftheight*64, out_features=120)self.L2     = paddle.nn.Linear(in_features=120, out_features=86)self.L3     = paddle.nn.Linear(in_features=86, out_features=targetsize)def forward(self, x):x = self.conv1(x)x = paddle.nn.functional.relu(x)x = self.mp1(x)x = self.conv2(x)x = paddle.nn.functional.relu(x)x = self.mp2(x)x = self.conv3(x)x = paddle.nn.functional.relu(x)x = self.mp3(x)x = paddle.flatten(x, start_axis=1, stop_axis=-1)x = self.L1(x)x = paddle.nn.functional.relu(x)x = paddle.fluid.layers.dropout(x,0.5)x = self.L2(x)x = paddle.nn.functional.relu(x)x = self.L3(x)return xmodel = lenet()#------------------------------------------------------------optimizer = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())
accdim = []
acctestdim = []
def train(model):model.train()epochs = 200for epoch in range(epochs):for batch, data in enumerate(train_loader()):out = model(data[0])loss = paddle.nn.functional.cross_entropy(out, data[1])acc = paddle.metric.accuracy(out, data[1])loss.backward()optimizer.step()optimizer.clear_grad()#------------------------------------------------out = model(paddle.to_tensor(array(imgdata), dtype='float32'))
#            print(shape(imglabel))
#            print(shape(imgdata))
#            print(out)
#            print(imglabel)
#            print(type(imglabel))
#            print(type(imgdata))acctest = paddle.metric.accuracy(out, paddle.to_tensor(imglabel[:,newaxis], dtype='int64'))accdim.append(acc.numpy())acctestdim.append(acctest.numpy())print('Epoch:{}, Loss:{}, Accuracys:{},{}\r'.format(epoch, loss.numpy(), acc.numpy(), acctest.numpy()))#------------------------------------------------------------train(model)
paddle.save(model.state_dict(), './work/model3.pdparams')#------------------------------------------------------------
plt.figure(figsize=(10, 6))
plt.plot(accdim, label='Train Acc')
plt.plot(acctestdim, label='Test Acc')
plt.xlabel("Step")
plt.ylabel("Accuracy")
plt.legend(loc='upper left')
plt.grid(True)
plt.tight_layout()
plt.show()#------------------------------------------------------------predict = model(paddle.to_tensor(imgdata3, dtype='float32'))
predtarget = paddle.fluid.layers.argmax(predict, axis=1)#print('Predict:', predtarget.numpy())
#printf('Labels:', imglabel1)error = [abs(a-b) for a,b in zip(predtarget.numpy(), imglabel1)]
printf('Error:', sum(error) )#------------------------------------------------------------
#print(array(imgdata).shape)#------------------------------------------------------------paddle.summary(model, (50, 3, imgwidth, imgheight))#------------------------------------------------------------
#        END OF FILE : TEST4.PY
#============================================================

2021年人工神经网络第四次作业-第四题:旋转的数字相关推荐

  1. 2021年人工神经网络第三次作业-第二题:遗传算法与人工神经网络-参考答案

    简 介: 给出了对于BP网络求解异或问题过程中,利用遗传算法完成网络演变的过程.所使用的遗传算法是最基本的遗传算法.利用遗传算法对于网络的系数进行演变,可以对网络系数初始化过程进行优化.对于不同的遗传 ...

  2. 2021年人工神经网络第四次作业:基于MATLAB的求解

    简 介: 本文选取了2021年人工神经网络第四次作业学生提交的作业.供交流使用. 关键词: 人工神经网络 #mermaid-svg-ATqdYQemfmABj2Hj {font-family:&quo ...

  3. 2021年人工神经网络第四次作业要求:第七题

    简 介: 对于MATLAB中的SimpleClass数据集合,对比了BP,RBF,SVM,SOFM,DHNN 等方法分类结果,可以看到BP,RBF,SVM,SOFM都具有非常好的分类效果.DHNN对于 ...

  4. 2021年人工神经网络第四次作业 - 第三题Cifar10

    简 介: 在Paddle下使用最基本的BP网络以及LeNet网络结构,测试了Cifar10数据集合.但实际运行在测试集合上的效果始终没有突破0.3,具体原因还需要进行查找. 后来经过测试,发现问题出现 ...

  5. 2021年人工神经网络第四次作业 - 第二题MNIST手写体识别

    简 介: ※MNIST数据集合是深度学习基础训练数据集合.改数据集合可以使用稠密前馈神经网络训练,也可以使用CNN.本文采用了单隐层BP网络和LeNet网络对于MNIST数据集合进行测试.实验结果标明 ...

  6. 2021年人工神经网络第四次作业-第五题:危险品识别

    简 介: 通过对于物品X射线数据集合的整理,挑选出15类体积比较大的物品,训练LeNet网络进行识别. 关键词: X射线,危险品识别,LeNet,Paddle #mermaid-svg-wZUMACG ...

  7. 2021年人工神经网络第四次作业-第一题:LeNet对于水果与动物进行分类

    简 介: 对于有五种动物和五中水果组成的FAMNIST数据集合的图像分类问题进行了测试.本文主要是集中在前期的数据库的准备和网络的构建方面.对于网络的详细测试参见在 对于FAMNIST中的十种动物和水 ...

  8. 2021年人工神经网络第一次作业:参考答案-1

    简 介: 本文给出了 2021年人工神经网络第一次作业要求 中,由同学提交的作业示例. 关键词: 人工神经网络,感知机,BP,数据压缩 #mermaid-svg-mAbRor9AKp6fkRrk {f ...

  9. 2021年人工神经网络第一次作业要求

    ## ◎ 参考答案: 2021年人工神经网络第一次作业:参考答案-1 §01 第一题 1.1 使用感知机求解下面的分类问题. ▲ 图1.1 1.1.1 题目要求 绘制出网络结构,并给出算法流程描述: ...

最新文章

  1. 分布式RPC实践--Dubbo基础篇
  2. java采集温湿度水浸_配电室水浸及温湿度监测系统可加强环境保障
  3. python画仿真图-仿真入门:几行 Python 代码实现复杂社会动力学
  4. zookeeper快速入门,配置虚拟机ip、mac、虚拟机免密,jdk的安装与卸载
  5. python 定时任务系统_Python定时任务,实现自动化的方法
  6. Redis系列六、redis的五种数据结构和相关指令之Sorted Set
  7. 问题三:类的头文件和实现文件分别写什么(用向量表示RGB输出“第一张图片”)
  8. win7 64位MMC管理控制台使用“远程桌面”
  9. java工程师容易秃头吗_程序员因发际线后悔学java!
  10. CISCO ASR9000 密码恢复
  11. python裁剪图片并保存
  12. 地铁怎么坐才不能做反_坐地铁怎样才不会坐反方向
  13. 都 要 悠 着 点 呀~~
  14. TNF 又见 《Cell》
  15. IOS开发 阅读器类APP可用开源框架介绍(2)
  16. OCI env setting
  17. Linux 文件系统只读
  18. yolov8 瑞芯微RKNN和地平线Horizon芯片仿真测试部署
  19. unable to access ‘https://sys-gitlab.n.com.cn/IPSC/web/Bumblebee/platform.w/platform.git/‘: SSL cert
  20. 01-mybatis-plus插入操作及主键策略

热门文章

  1. Spring Boot定时任务应用实践
  2. 去除文件名中的'.'符号
  3. 谢烟客---------Linux之文件安全上下文及特殊权限位
  4. java之final
  5. Mac-OSX的Python3.5虚拟环境下安装Opencv
  6. 03_NoSQL数据库之Redis数据库:list类型
  7. NHibernate之Mapping 之 Property
  8. jsp自定义图文新闻列表标签结合ssh2,带分页功能
  9. 《R语言游戏数据分析与挖掘》一3.4 小结
  10. 不忘历史才能开辟未来,善于继承才能善于创新