南宁设计网站建设,wordpress主题目录位置,重庆网站备案最快几天,网站效果图尺寸一、确定输入样本特征和输出特征
输入样本通道数4、期待输出样本通道数2、卷积核大小33 具体卷积层的构建可参考博文#xff1a;八、卷积层 设定卷积层 torch.nn.Conv2d(in_channelsin_channel,out_channelsout_channel,kernel_sizekernel_size,padding1,stride1) 必要参数八、卷积层 设定卷积层 torch.nn.Conv2d(in_channelsin_channel,out_channelsout_channel,kernel_sizekernel_size,padding1,stride1) 必要参数输入样本通道数in_channels、输出样本通道数out_channels、卷积核大小kernel_size padding是否加边默认不加这里为了保证输出图像的大小不变加边数设为1 stride步长设置默认为1
import torch
in_channel, out_channel 4, 2
width, heigh 512, 512
batch_size 1
inputs torch.randn(batch_size,in_channels,width,heigh)#[B,C,W,H]kernel_size 3conv_layer torch.nn.Conv2d(in_channelsin_channel,out_channelsout_channel,kernel_sizekernel_size,padding1,stride1)
outputs conv_layer(inputs)print(inputs.shape)torch.Size([1, 4, 512, 512])print(outputs.shape)torch.Size([1, 2, 512, 512])print(conv_layer.weight.shape)#看下卷积层核参数信息
# 卷积层权重参数大小因为batch_size为1故卷积核参数的B也为1
# 因为输入样本的通道数是3故卷积层传入参数的channel也为3
# 因为输出样本的通道数是1故卷积层传入参数的torch.Size([2, 4, 3, 3])二、确定卷积核内容进行卷积 import torch
inputs [1,1,1,1,1,2,2,2,2,2,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1]inputs torch.Tensor(inputs).view(1,1,5,5)kernel_size 3
padding 0
stride 1kernel torch.Tensor([1,2,1,2,1,2,1,2,1]).view(1,1,3,3)conv_layer torch.nn.Conv2d(1,1,kernel_sizekernel_size,paddingpadding,stridestride,biasFalse)
conv_layer.weight.data kernel.dataoutputs conv_layer(inputs)print(outputs)tensor([[[[19., 20., 19.],[20., 20., 20.],[17., 18., 17.]]]], grad_fnSlowConv2DBackward0)
print(inputs)tensor([[[[1., 1., 1., 1., 1.],[2., 2., 2., 2., 2.],[1., 1., 1., 1., 1.],[2., 2., 2., 2., 2.],[1., 1., 1., 1., 1.]]]])print(kernel)tensor([[[[1., 2., 1.],[2., 1., 2.],[1., 2., 1.]]]])print(inputs.shape)torch.Size([1, 1, 5, 5])print(outputs.shape)torch.Size([1, 1, 3, 3])print(kernel.shape)torch.Size([1, 1, 3, 3])print(conv_layer.weight.shape)torch.Size([1, 1, 3, 3])三、根据需求进行网络模型搭建
①准备数据集
还是以MNIST手写数字数据集为例数据集细节可参考博文九、多分类问题
设置batch_size64每个batch中有64张样本至于一共有多少个batch取决于数据集的总数量 使用transforms.Compose()组合操作把数据集都转换为Tensor数据类型并且全部都取均值和标准差方便训练强化训练效果这里的值都是经过计算过的直接用就行
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F #为了使用relu激活函数
import torch.optim as optim batch_size 64
transform transforms.Compose([transforms.ToTensor(),#把图片变成张量形式transforms.Normalize((0.1307,),(0.3081,)) #均值和标准差进行数据标准化这俩值都是经过整个样本集计算过的
])②加载数据集
pytorch提供MNIST接口直接调用相关函数即可
datasets中 参数root表示数据集路径 参数train表示是否是训练集True表示下载训练集False则表示下载测试集 参数download表示是否下载True表示若指定路径不存在数据集则联网下载 将所有的数据集都经过上面定义的transforms组合操作转换成Tensor格式和均值标准差归一化。
DataLoader中 参数train_dataset指定数据集datasets 参数shuffle表示是否将数据集中的样本打乱顺序训练集需要测试集不需要 参数batch_size表示一次(batch)取多少个样本至于一共取多少次取决于数据集总样本数
train_dataset datasets.MNIST(root./,trainTrue,downloadTrue,transform transform)
train_loader DataLoader(train_dataset,shuffleTrue,batch_sizebatch_size)test_dataset datasets.MNIST(root./,trainFalse,downloadTrue,transformtransform)
test_loader DataLoader(test_dataset,shuffleFalse,batch_sizebatch_size)③模型构建 由图可知输入图像(通道数为1)首先进入一个卷积层卷积核大小为5×5输出特征通道数为10即torch.nn.Conv2d(1,10,kernel_size5) 之后进入一个ReLU激活函数层激活函数无需参数即F.relu() 然后再进入一个核为2×2的MaxPool层即torch.nn.MaxPool2d(2)
之后将通道数为10的特征参数再送入一个卷积层卷积核大小为5×5输出特征通道数为20即torch.nn.Conv2d(10,20,kernel_size5) 之后进入一个ReLU激活函数层激活函数无需参数即F.relu() 然后再进入一个核为2×2的MaxPool层即torch.nn.MaxPool2d(2)
有第一张图可知最终的特征参数个数为20×4×4320将这320个特征参数通过线性层(全连接层)转到10个维度上即torch.nn.Linear(320,10)因为是10分类任务故需要转到10个维度上
在模型参数函数(def __init__(self):)中池化层操作都一样故定义一个即可最终卷积操作两个一个池化操作一个线性层(全连接)操作 在前向传播函数(def forward(self,x):)中数据集中x为[B,C,W,H]故通过x.size(0)取出batch_size即B的值
class yNet(torch.nn.Module):def __init__(self):super(yNet,self).__init__()self.conv_1 torch.nn.Conv2d(1,10,kernel_size5)self.pooling torch.nn.MaxPool2d(2)self.conv_2 torch.nn.Conv2d(10,20,kernel_size5)self.fc torch.nn.Linear(320,10)def forward(self,x):batch_size x.size(0)x self.pooling(F.relu(self.conv_1(x)))x self.pooling(F.relu(self.conv_2(x)))x x.view(batch_size,-1)x self.fc(x)return xmodel yNet()GPU加速 只需要通过.to()方法将模型、训练函数中数据集、测试函数中数据集调用该方法即可
device torch.device(cuda:0 if torch.cuda.is_available() else cpu)
model.to(device)④损失函数和优化器
lossf torch.nn.CrossEntropyLoss()
optimizer optim.SGD(model.parameters(),lr0.0001,momentum0.5)⑤训练函数定义
for i, data in enumerate(train_loader,0): 从train_loader这个DataLoader中进行枚举0表示从DataLoader下标为0处开始train_loader返回两个值索引和数据其中数据包括两类x和y i接收索引、data接收数据 x,y datax和y分别接收data中的28×28784个参数y为所对应的某一个类别
测试
x,y test_dataset[0]
x.shapetorch.Size([1, 28, 28])y7完整代码
def ytrain(epoch):loss_total 0.0for batch_index ,data in enumerate(train_loader,0):x,y data#x,y x.to(device), y.to(device)#GPU加速optimizer.zero_grad()y_hat model(x)loss lossf(y_hat,y)loss.backward()optimizer.step()loss_total loss.item()if batch_index % 300 299:# 每300epoch输出一次print(epoch:%d, batch_index:%5d \t loss:%.3f%(epoch1, batch_index1, loss_total/300))loss_total 0.0 #每次epoch都将损失清零方便计算下一次的损失⑥测试函数定义
def ytest():correct 0#模型预测正确的数量total 0#样本总数with torch.no_grad():#测试不需要梯度减小计算量for data in test_loader:#读取测试样本数据images, labels data#images, labels images.to(device), labels.to(device) #GPU加速pred model(images)#预测每一个样本占一行每行有十个值后续需要求每一行中最大值所对应的下标pred_maxvalue, pred_maxindex torch.max(pred.data,dim1)#沿着第一个维度一行一行来去找每行中的最大值返回每行的最大值和所对应下标total labels.size(0)#labels是一个(N,1)的向量对应每个样本的正确答案correct (pred_maxindex labels).sum().item()#使用预测得到的最大值的索引和正确答案labels进行比较一致就是1不一致就是0print(Accuracy on testset :%d %%%(100*correct / total))#correct预测正确的样本个数 / 样本总数 * 100 模型预测正确率⑦主函数调用
if __name__ __main__:for epoch in range(100):#训练10次ytrain(epoch)#训练一次if epoch%10 9:ytest()#训练10次测试1次⑧完整代码
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F #为了使用relu激活函数
import torch.optim as optim batch_size 64
transform transforms.Compose([transforms.ToTensor(),#把图片变成张量形式transforms.Normalize((0.1307,),(0.3081,)) #均值和标准差进行数据标准化这俩值都是经过整个样本集计算过的
])train_dataset datasets.MNIST(root./,trainTrue,downloadTrue,transform transform)
train_loader DataLoader(train_dataset,shuffleTrue,batch_sizebatch_size)test_dataset datasets.MNIST(root./,trainFalse,downloadTrue,transformtransform)
test_loader DataLoader(test_dataset,shuffleFalse,batch_sizebatch_size)class yNet(torch.nn.Module):def __init__(self):super(yNet,self).__init__()self.conv_1 torch.nn.Conv2d(1,10,kernel_size5)self.pooling torch.nn.MaxPool2d(2)self.conv_2 torch.nn.Conv2d(10,20,kernel_size5)self.fc torch.nn.Linear(320,10)def forward(self,x):#传入单张样本xbatch_size x.size(0)x self.pooling(F.relu(self.conv_1(x)))x self.pooling(F.relu(self.conv_2(x)))x x.view(batch_size,-1)x self.fc(x)return xmodel yNet()
device torch.device(cuda:0 if torch.cuda.is_available() else cpu)
model.to(device)lossf torch.nn.CrossEntropyLoss()
optimizer optim.SGD(model.parameters(),lr0.0001,momentum0.5)def ytrain(epoch):loss_total 0.0for batch_index ,data in enumerate(train_loader,0):x,y datax,y x.to(device), y.to(device)#GPU加速optimizer.zero_grad()y_hat model(x)loss lossf(y_hat,y)loss.backward()optimizer.step()loss_total loss.item()if batch_index % 300 299:# 每300epoch输出一次print(epoch:%d, batch_index:%5d \t loss:%.3f%(epoch1, batch_index1, loss_total/300))loss_total 0.0def ytest():correct 0#模型预测正确的数量total 0#样本总数with torch.no_grad():#测试不需要梯度减小计算量for data in test_loader:#读取测试样本数据images, labels dataimages, labels images.to(device), labels.to(device) #GPU加速pred model(images)#预测每一个样本占一行每行有十个值后续需要求每一行中最大值所对应的下标pred_maxvalue, pred_maxindex torch.max(pred.data,dim1)#沿着第一个维度一行一行来去找每行中的最大值返回每行的最大值和所对应下标total labels.size(0)#labels是一个(N,1)的向量对应每个样本的正确答案correct (pred_maxindex labels).sum().item()#使用预测得到的最大值的索引和正确答案labels进行比较一致就是1不一致就是0print(Accuracy on testset :%d %%%(100*correct / total))#correct预测正确的样本个数 / 样本总数 * 100 模型预测正确率if __name__ __main__:for epoch in range(10):#训练10次ytrain(epoch)#训练一次if epoch%10 9:ytest()#训练10次测试1次⑨测试一下
x,y train_dataset[9]#第9个数据x为图片对应的结果为2
y2x x.view(-1,1,28,28)#因为tensor需要格式为(B,C,W,H)转换一下格式
y_hat model(x)#放入模型中进行预测因为时十分类任务输出十个值
y_hat tensor([[-2.8711, -2.2891, -0.5218, -2.0884, 6.2099, -0.1559, 1.9904, -0.8938,1.3734, 2.9303]], grad_fnAddmmBackward0)
pred_maxvalue, pred_maxindex torch.max(y_hat,dim1)#选出值最大的和相对于的下标索引pred_maxvalue#最大值tensor([6.2099], grad_fnMaxBackward0)pred_maxindex#最大值所对应的索引下标值tensor([4])预测错了得多训练几轮
四、课后作业 除网络模型外其他的都可以复用
这里就不再赘述直接对模型结构进行搭建
查看下官网给的卷积层padding的计算公式 以下是我个人设计的网络模型接下来开始去实现模型架构
①调试
加载数据集
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F #为了使用relu激活函数
import torch.optim as optim batch_size 64
transform transforms.Compose([transforms.ToTensor(),#把图片变成张量形式transforms.Normalize((0.1307,),(0.3081,)) #均值和标准差进行数据标准化这俩值都是经过整个样本集计算过的
])train_dataset datasets.MNIST(root./,trainTrue,downloadTrue,transform transform)
train_loader DataLoader(train_dataset,shuffleTrue,batch_sizebatch_size)test_dataset datasets.MNIST(root./,trainFalse,downloadTrue,transformtransform)
test_loader DataLoader(test_dataset,shuffleFalse,batch_sizebatch_size)#这里取测试集中的一个样本
x,y test_dataset[1]x.shapetorch.Size([1, 28, 28])y2第一个卷积层
因为数据集中样本shape是torch.Size([1, 28, 28])而pytorch提供的接口都得适应[B,C,W,H]形式故需要先通过x x.view(-1,1,28,28)转换一下类型 根据结构需要定义第一个卷积层为了后续计算方便这里加边padding1保证输入和输出特征图大小一致这里仅为了测试batch取1 conv_1 torch.nn.Conv2d(1,5,kernel_size3,padding1)
x x.view(-1,1,28,28)
x.shapetorch.Size([1, 1, 28, 28])conv_1 torch.nn.Conv2d(1,5,kernel_size3,padding1)
x1 conv_1(x)
x1.shapetorch.Size([1, 5, 28, 28])由输出结果可知通过第一个卷积层之后特征图x1为[1,5,28,28] 将x1传入第一个最大池化层
第一个最大池化层
x1的形状为[1,5,28,28] 定义最大池化层pooling torch.nn.MaxPool2d(2) 将x1传入最大池化层得到特征x2
pooling torch.nn.MaxPool2d(2)
x2 pooling(x1)
x2.shapetorch.Size([1, 5, 14, 14])输出结果x2的形状为[1, 5, 14, 14] 将x2传入第二个卷积层中
第二个卷积层
x2的形状为[1, 5, 14, 14] 定义第二个卷积层conv_2 torch.nn.Conv2d(5,10,kernel_size3,padding1) 将x2传入第二个卷积层得到特征x3
conv_2 torch.nn.Conv2d(5,10,kernel_size3,padding1)
x3 conv_2(x2)
x3.shapetorch.Size([1, 10, 14, 14])输出结果x3的形状为[1, 10, 14, 14] 将x3传入第二个最大池化层中
第二个最大池化层
x3的形状为[1, 10, 14, 14] 使用上述同样的最大池化层pooling torch.nn.MaxPool2d(2) 将x3传入第二个最大池化层得到特征x4
pooling torch.nn.MaxPool2d(2)
x4 pooling(x3)
x4.shapetorch.Size([1, 10, 7, 7])输出结果x4的形状为[1, 10, 7, 7] 将x4传入第三个卷积层中
第三个卷积层
x4的形状为[1, 10, 7, 7] 定义第三个卷积层conv_3 torch.nn.Conv2d(10,20,kernel_size3,padding1) 将x4传入第三个卷积层得到特征x5
conv_3 torch.nn.Conv2d(10,20,kernel_size3,padding1)
x5 conv_3(x4)
x5.shapetorch.Size([1, 20, 7, 7])输出结果x5的形状为[1, 20, 7, 7] 将x5传入第三个最大池化层中
第三个最大池化层
x5的形状为[1, 20, 7, 7] 使用上述同样的最大池化层pooling torch.nn.MaxPool2d(2) 将x5传入第二个最大池化层得到特征x6 pooling torch.nn.MaxPool2d(2)
x6 pooling(x5)
x6.shapetorch.Size([1, 20, 3, 3])输出结果x6的形状为[1, 20, 3, 3] 将x6传入第一个线性层中
第一个全连接层
x6的形状为[1, 20, 3, 3]此时特征图x6共有1×20×3×3180个参数 因为线性层传入的特征是二维矩阵形式每个batch占一行每行存放单个样本的所有参数信息故需要将x6形状进行转变x6.size(0)获取batch这里的batch是1剩下的系统进行自动排列x_all x6.view(x6.size(0),-1)此时的x_all的形状为[1,180] 之后根据需求定义第一个线性层fc_1 torch.nn.Linear(180,120)这里的输入180必须和最终的特征x_all吻合 将x_all传入第一个全连接层得到特征x_x1
x6.shapetorch.Size([1, 20, 3, 3])x6.size(0)1
x_all x6.view(x6.size(0),-1)
x_all.shapetorch.Size([1, 180])
fc_1 torch.nn.Linear(180,120)
x_x1 fc_1(x_all)
x_x1.shapetorch.Size([1, 120])输出结果x_x1的形状为[1, 120] 将x_x1传入第二个全连接层中
第二个全连接层
x_x1的形状为[1, 120] 根据需求定义第二个全连接层fc_2 torch.nn.Linear(120,60) 将x_x1传入第二个全连接层得到特征x_x2
fc_2 torch.nn.Linear(120,60)
x_x2 fc_2(x_x1)
x_x2.shapetorch.Size([1, 60])输出结果x_x2的形状为[1, 60] 将x_x2传入第三个全连接层中
第三个全连接层
x_x2的形状为[1, 60] 根据需求定义第三个全连接层fc_3 torch.nn.Linear(60,10) 将x_x2传入第三个全连接层得到特征x_x3
fc_3 torch.nn.Linear(60,10)
x_x3 fc_3(x_x2)
x_x3.shapetorch.Size([1, 10])最终结果为x_x3形状为[1, 10]十分类任务十个概率值取最大的就是最终预测的结果
②模型构建
class yNet(torch.nn.Module):def __init__(self):super(yNet,self).__init__()self.conv_1 torch.nn.Conv2d(1,5,kernel_size3,padding1)self.pooling torch.nn.MaxPool2d(2)self.conv_2 torch.nn.Conv2d(5,10,kernel_size3,padding1)self.conv_3 torch.nn.Conv2d(10,20,kernel_size3,padding1)self.fc_1 torch.nn.Linear(180,120)self.fc_2 torch.nn.Linear(120,60)self.fc_3 torch.nn.Linear(60,10)def forward(self,x):batch_size x.size(0)x self.pooling(F.relu(self.conv_1(x)))x self.pooling(F.relu(self.conv_2(x)))x self.pooling(F.relu(self.conv_3(x)))x x.view(batch_size,-1)x self.fc_1(x)x self.fc_2(x)x self.fc_3(x)return xmodel yNet() device torch.device(cuda:0 if torch.cuda.is_available() else cpu)#GPU加速
model.to(device)③完整代码
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F #为了使用relu激活函数
import torch.optim as optim batch_size 64
transform transforms.Compose([transforms.ToTensor(),#把图片变成张量形式transforms.Normalize((0.1307,),(0.3081,)) #均值和标准差进行数据标准化这俩值都是经过整个样本集计算过的
])train_dataset datasets.MNIST(root./,trainTrue,downloadTrue,transform transform)
train_loader DataLoader(train_dataset,shuffleTrue,batch_sizebatch_size)test_dataset datasets.MNIST(root./,trainFalse,downloadTrue,transformtransform)
test_loader DataLoader(test_dataset,shuffleFalse,batch_sizebatch_size)class yNet(torch.nn.Module):def __init__(self):super(yNet,self).__init__()self.conv_1 torch.nn.Conv2d(1,5,kernel_size3,padding1)self.pooling torch.nn.MaxPool2d(2)self.conv_2 torch.nn.Conv2d(5,10,kernel_size3,padding1)self.conv_3 torch.nn.Conv2d(10,20,kernel_size3,padding1)self.fc_1 torch.nn.Linear(180,120)self.fc_2 torch.nn.Linear(120,60)self.fc_3 torch.nn.Linear(60,10)def forward(self,x):batch_size x.size(0)x self.pooling(F.relu(self.conv_1(x)))x self.pooling(F.relu(self.conv_2(x)))x self.pooling(F.relu(self.conv_3(x)))x x.view(batch_size,-1)x self.fc_1(x)x self.fc_2(x)x self.fc_3(x)return xmodel yNet()
device torch.device(cuda:0 if torch.cuda.is_available() else cpu)
model.to(device)lossf torch.nn.CrossEntropyLoss()
optimizer optim.SGD(model.parameters(),lr0.0001,momentum0.5)def ytrain(epoch):loss_total 0.0for batch_index ,data in enumerate(train_loader,0):x,y datax,y x.to(device), y.to(device)#GPU加速optimizer.zero_grad()y_hat model(x)loss lossf(y_hat,y)loss.backward()optimizer.step()loss_total loss.item()if batch_index % 300 299:# 每300epoch输出一次print(epoch:%d, batch_index:%5d \t loss:%.3f%(epoch1, batch_index1, loss_total/300))loss_total 0.0def ytest():correct 0#模型预测正确的数量total 0#样本总数with torch.no_grad():#测试不需要梯度减小计算量for data in test_loader:#读取测试样本数据images, labels dataimages, labels images.to(device), labels.to(device) #GPU加速pred model(images)#预测每一个样本占一行每行有十个值后续需要求每一行中最大值所对应的下标pred_maxvalue, pred_maxindex torch.max(pred.data,dim1)#沿着第一个维度一行一行来去找每行中的最大值返回每行的最大值和所对应下标total labels.size(0)#labels是一个(N,1)的向量对应每个样本的正确答案correct (pred_maxindex labels).sum().item()#使用预测得到的最大值的索引和正确答案labels进行比较一致就是1不一致就是0print(Accuracy on testset :%d %%%(100*correct / total))#correct预测正确的样本个数 / 样本总数 * 100 模型预测正确率if __name__ __main__:for epoch in range(10):#训练10次ytrain(epoch)#训练一次if epoch%10 9:ytest()#训练10次测试1次④测试一下
x,y train_dataset[12]#第12个数据x为图片对应的结果为3
y3x x.view(-1,1,28,28)#因为tensor需要格式为(B,C,W,H)转换一下格式
y_hat model(x)#放入模型中进行预测因为时十分类任务输出十个值
y_hat tensor([[ 0.0953, 0.0728, 0.0505, 0.0618, -0.0512, -0.1338, -0.0261, -0.0677,-0.0265, 0.0236]], grad_fnAddmmBackward0)
pred_maxvalue, pred_maxindex torch.max(y_hat,dim1)#选出值最大的和相对于的下标索引pred_maxvalue#最大值tensor([0.0953], grad_fnMaxBackward0)pred_maxindex#最大值所对应的索引下标值tensor([0])好家伙又预测错了确实得多训练几轮
又是动笔画又是单步调试若各位客官姥爷有所收获还请点个小小的赞这将是对我的最大的鼓励万分感谢~