2021年人工神经网络第四次作业-第四题:旋转的数字
简 介: 本文对于作业中给定的机械数字字符识别问题进行了实验研究。通过对于采样1000样本的数据集合进行训练,经过增加DropOut的可以增加网络的泛化性能。对于网络规模的增加对训练精度没有明显的改进。由于数据集合比较小,因此作业中的一些结论并不具有代表特性。
关键词
: 旋转数字,Dropout,LeNet
Contents
别红色字符
图片训练模型
§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年人工神经网络第四次作业-第四题:旋转的数字相关推荐
- 2021年人工神经网络第三次作业-第二题:遗传算法与人工神经网络-参考答案
简 介: 给出了对于BP网络求解异或问题过程中,利用遗传算法完成网络演变的过程.所使用的遗传算法是最基本的遗传算法.利用遗传算法对于网络的系数进行演变,可以对网络系数初始化过程进行优化.对于不同的遗传 ...
- 2021年人工神经网络第四次作业:基于MATLAB的求解
简 介: 本文选取了2021年人工神经网络第四次作业学生提交的作业.供交流使用. 关键词: 人工神经网络 #mermaid-svg-ATqdYQemfmABj2Hj {font-family:&quo ...
- 2021年人工神经网络第四次作业要求:第七题
简 介: 对于MATLAB中的SimpleClass数据集合,对比了BP,RBF,SVM,SOFM,DHNN 等方法分类结果,可以看到BP,RBF,SVM,SOFM都具有非常好的分类效果.DHNN对于 ...
- 2021年人工神经网络第四次作业 - 第三题Cifar10
简 介: 在Paddle下使用最基本的BP网络以及LeNet网络结构,测试了Cifar10数据集合.但实际运行在测试集合上的效果始终没有突破0.3,具体原因还需要进行查找. 后来经过测试,发现问题出现 ...
- 2021年人工神经网络第四次作业 - 第二题MNIST手写体识别
简 介: ※MNIST数据集合是深度学习基础训练数据集合.改数据集合可以使用稠密前馈神经网络训练,也可以使用CNN.本文采用了单隐层BP网络和LeNet网络对于MNIST数据集合进行测试.实验结果标明 ...
- 2021年人工神经网络第四次作业-第五题:危险品识别
简 介: 通过对于物品X射线数据集合的整理,挑选出15类体积比较大的物品,训练LeNet网络进行识别. 关键词: X射线,危险品识别,LeNet,Paddle #mermaid-svg-wZUMACG ...
- 2021年人工神经网络第四次作业-第一题:LeNet对于水果与动物进行分类
简 介: 对于有五种动物和五中水果组成的FAMNIST数据集合的图像分类问题进行了测试.本文主要是集中在前期的数据库的准备和网络的构建方面.对于网络的详细测试参见在 对于FAMNIST中的十种动物和水 ...
- 2021年人工神经网络第一次作业:参考答案-1
简 介: 本文给出了 2021年人工神经网络第一次作业要求 中,由同学提交的作业示例. 关键词: 人工神经网络,感知机,BP,数据压缩 #mermaid-svg-mAbRor9AKp6fkRrk {f ...
- 2021年人工神经网络第一次作业要求
## ◎ 参考答案: 2021年人工神经网络第一次作业:参考答案-1 §01 第一题 1.1 使用感知机求解下面的分类问题. ▲ 图1.1 1.1.1 题目要求 绘制出网络结构,并给出算法流程描述: ...
最新文章
- 分布式RPC实践--Dubbo基础篇
- java采集温湿度水浸_配电室水浸及温湿度监测系统可加强环境保障
- python画仿真图-仿真入门:几行 Python 代码实现复杂社会动力学
- zookeeper快速入门,配置虚拟机ip、mac、虚拟机免密,jdk的安装与卸载
- python 定时任务系统_Python定时任务,实现自动化的方法
- Redis系列六、redis的五种数据结构和相关指令之Sorted Set
- 问题三:类的头文件和实现文件分别写什么(用向量表示RGB输出“第一张图片”)
- win7 64位MMC管理控制台使用“远程桌面”
- java工程师容易秃头吗_程序员因发际线后悔学java!
- CISCO ASR9000 密码恢复
- python裁剪图片并保存
- 地铁怎么坐才不能做反_坐地铁怎样才不会坐反方向
- 都 要 悠 着 点 呀~~
- TNF 又见 《Cell》
- IOS开发 阅读器类APP可用开源框架介绍(2)
- OCI env setting
- Linux 文件系统只读
- yolov8 瑞芯微RKNN和地平线Horizon芯片仿真测试部署
- unable to access ‘https://sys-gitlab.n.com.cn/IPSC/web/Bumblebee/platform.w/platform.git/‘: SSL cert
- 01-mybatis-plus插入操作及主键策略