项目使用的是pytorch框架
注意事项:加载进的数据集并不符合卷积神经网络的训练格式,需要先使用Dataloader进行修改,而且加载时要先利用transform把图片数据转化为tensor张量形式
train_data=torchvision.datasets.MNIST('./data',True,torchvision.transforms.ToTensor(),download=True)
test_data=torchvision.datasets.MNIST('./data',False,torchvision.transforms.ToTensor(),download=True)
train_datasize=len(train_data) #训练集的长度
test_datasize=len(test_data)
print('训练集的长度为:{}'.format(train_datasize))
print('测试集的长度为:{}'.format(test_datasize))
#加载数据集部分
train_dataloader=DataLoader(train_data,batch_size=64)
test_dataloader=DataLoader(test_data,batch_size=64)
搭建网络的过程中,需要先计算好图片的像素点,根据卷积过程的计算公式,计算出输出的数值,如果计算错误会报错
#搭建神经网络:十个分类的网络:minist数据集是黑白图片,单通道,大小是28*28,种类是10个,本次采取2层卷积层和一层全连接层实现
class lf(nn.Module):
def __init__(self):
super(lf, self).__init__()
self.model=nn.Sequential( #原图像的像素点是1*28*28
nn.Conv2d(1,16,5,1,2), #输入形式的单通道形式,输出通道改为16 像素点为:16*28*28
nn.MaxPool2d(2), #像素点为 16*14*14
nn.Conv2d(16,32,5,1,2), #输出通道改为32通道
nn.MaxPool2d(2), #像素点为:32*7*7
nn.Flatten(), #展开后的数据大小为:32*7*7=1568
nn.Linear(1568,98), #填写98的原因,反照CFR数据训练比例,64除以1024再乘上1568
nn.Linear(98,10) #输出10类数据,判断概率性
)
def forward(self,x):
x=self.model(x) #训练网络
return x
手动设置学习率,0.03,训练轮数 ,30轮
选择交叉熵损失函数,适用于多分类问题
优化器选择随机梯度下降法
loss_function=nn.CrossEntropyLoss() #分类问题使用交叉熵损失函数
optim=torch.optim.SGD(l.parameters(),lr=0.01) #随机梯度下降法优化器,设定学习速率为0.03
train_step=0 #记录训练的次数
test_step=0 #记录测试的次数
epoch=30 #训练十轮
for i in range(30):
print('第{}轮训练开始了'.format(i+1))
for data in train_dataloader: #加载数据,每一轮batch_size都是64张图片
imgs,target=data #加载的data类型包括图片和标签数值俩钟数据???
output=l(imgs) #向模型中输入数据,返回的数据由output保存
loss=loss_function(output,target) #计算损失函数的损失值
optim.zero_grad() #每一轮训练都需要梯度清零,否则下一轮的梯度下降将会被上一轮训练的梯度值所影响
loss.backward() #反向传播,优化模型
optim.step() #梯度下降
训练过程中注意反向传播,如果没有反向传播的话将不会梯度下降(或者下降效果非常差,试过了)
with torch.no_grad(): #在此过程中,梯度始终为0,不会改变训练好的模型,可以用于验证模型
for data in test_dataloader:
imgs,target=data
output=l(imgs)
loss=loss_function(output,target)
test_loss+=loss #误差累加
test_step+=1 #测试步骤加一
writer.add_scalar('test_loss',test_loss,test_step)
accuracy=(output.argmax(1)==target).sum() #通过argmax函数把张量数据转化为位置信息,“1”表示横向比对,再将位置信息与target的位置信息相匹配,把匹配的结果求和,即可得到正确测试的数量
#每一轮之后,开始保存模型
total_accuracy=total_accuracy+accuracy
print("整体的测试集的准确率为:{}".format(total_accuracy/test_datasize)) #预测正确的总量除以全部数据量,将得出每一轮训练的准确率
torch.save(l,'保存模型{}.pth'.format(i+1)) #第一个参数千万不能带括号!!使用实例化的名称即可
所有的讲解都在代码的注释中,以上仅仅是大概的过程
import torch
import torchvision.datasets
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
train_data=torchvision.datasets.MNIST('./data',True,torchvision.transforms.ToTensor(),download=True)
test_data=torchvision.datasets.MNIST('./data',False,torchvision.transforms.ToTensor(),download=True)
train_datasize=len(train_data) #训练集的长度
test_datasize=len(test_data)
print('训练集的长度为:{}'.format(train_datasize))
print('测试集的长度为:{}'.format(test_datasize))
#加载数据集部分
train_dataloader=DataLoader(train_data,batch_size=64)
test_dataloader=DataLoader(test_data,batch_size=64)
writer=SummaryWriter('./logs') #可视化训练过程
#搭建神经网络:十个分类的网络:minist数据集是黑白图片,单通道,大小是28*28,种类是10个,本次采取2层卷积层和一层全连接层实现
class lf(nn.Module):
def __init__(self):
super(lf, self).__init__()
self.model=nn.Sequential( #原图像的像素点是1*28*28
nn.Conv2d(1,16,5,1,2), #输入形式的单通道形式,输出通道改为16 像素点为:16*28*28
nn.MaxPool2d(2), #像素点为 16*14*14
nn.Conv2d(16,32,5,1,2), #输出通道改为32通道
nn.MaxPool2d(2), #像素点为:32*7*7
nn.Flatten(), #展开后的数据大小为:32*7*7=1568
nn.Linear(1568,98), #填写98的原因,反照CFR数据训练比例,64除以1024再乘上1568
nn.Linear(98,10) #输出10类数据,判断概率性
)
def forward(self,x):
x=self.model(x) #训练网络
return x
if __name__ == '__main__':
l=lf() #创建网络模型
loss_function=nn.CrossEntropyLoss() #分类问题使用交叉熵损失函数
optim=torch.optim.SGD(l.parameters(),lr=0.01) #随机梯度下降法优化器,设定学习速率为0.03
train_step=0 #记录训练的次数
test_step=0 #记录测试的次数
epoch=30 #训练十轮
l.train() #改为训练网络
for i in range(30):
print('第{}轮训练开始了'.format(i+1))
for data in train_dataloader: #加载数据,每一轮batch_size都是64张图片
imgs,target=data #加载的data类型包括图片和标签数值俩钟数据???
output=l(imgs) #向模型中输入数据,返回的数据由output保存
loss=loss_function(output,target) #计算损失函数的损失值
optim.zero_grad() #每一轮训练都需要梯度清零,否则下一轮的梯度下降将会被上一轮训练的梯度值所影响
loss.backward() #反向传播,优化模型
optim.step() #梯度下降
train_step+=1 #训练次数增加
if train_step%100==0:
print('训练次数:{},loss:{}'.format(train_step,loss.item()))
writer.add_scalar('train',loss.item(),train_step) #可视化训练,图像名称,y内容,x内容,显示训练的效果
print('训练结束了')
#测试开始
l.eval() #改为测试网络
test_loss=0 #误差初始化
total_accuracy=0
with torch.no_grad(): #在此过程中,梯度始终为0,不会改变训练好的模型,可以用于验证模型
for data in test_dataloader:
imgs,target=data
output=l(imgs)
loss=loss_function(output,target)
test_loss+=loss #误差累加
test_step+=1 #测试步骤加一
writer.add_scalar('test_loss',test_loss,test_step)
accuracy=(output.argmax(1)==target).sum() #通过argmax函数把张量数据转化为位置信息,“1”表示横向比对,再将位置信息与target的位置信息相匹配,把匹配的结果求和,即可得到正确概率
#每一轮之后,开始保存模型
total_accuracy=total_accuracy+accuracy
print("整体的测试集的准确率为:{}".format(total_accuracy/test_datasize))
torch.save(l,'保存模型{}.pth'.format(i+1)) #第一个参数千万不能带括号!!
print('-------loss总和为:{}----------'.format(test_loss))
测试的图片的格式必须符合训练好的模型的网络要求输入格式,所以我事先使用opencv把图片灰度化了
import torch
import torchvision.transforms
from PIL import Image
from torch import nn
img='5.jpg' #读取单通道的图片,此模型就是适合单通道验证
image=Image.open(img)
print(image)
transform=torchvision.transforms.Compose([torchvision.transforms.Resize((28,28)),torchvision.transforms.ToTensor()]) #修改测试图片的大小及转化为张量形式
image=transform(image)
#需要导入卷积层
class lf(nn.Module):
def __init__(self):
super(lf, self).__init__()
self.model=nn.Sequential( #原图像的像素点是1*28*28
nn.Conv2d(1,16,5,1,2), #输入形式的单通道形式,输出通道改为16 像素点为:16*28*28
nn.MaxPool2d(2), #像素点为 16*14*14
nn.Conv2d(16,32,5,1,2), #输出通道改为32通道
nn.MaxPool2d(2), #像素点为:32*7*7
nn.Flatten(), #展开后的数据大小为:32*7*7=1568
nn.Linear(1568,98), #填写98的原因,反照CFR数据训练比例,64除以1024再乘上1568
nn.Linear(98,10) #输出10类数据,判断概率性
)
def forward(self,x):
x=self.model(x) #训练网络
return x
model =torch.load('lf49.pth',map_location=torch.device('cpu')) #加载网络模型,并且把GPU训练的模型映射到cpu上
print(model)
image=torch.reshape(image,(1,1,28,28)) #batch_size=1,输入通道为1 ,大小为28*28,修改输入图片适合卷积层的图像形式
model.eval() #测试模式
output=model(image)
print(output)
print(output.argmax(1)) #横向寻找对应位置,位置0--9,对应数字0--9,打印出相应的位置就是输出相应的分类结果