import torch
import torch.nn as nn
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
#1.构建数据集
batch_size=64
transform=transforms.Compose([ #compose类的实例化 RGB多通道(1,2,3) w*h*c 转化为 通道数chanel*宽width*高h
transforms.ToTensor(), #像素:Z(28*28)>>R(1*28*28) 转化为图像张量(C*W*H)
transforms.Normalize((0.1307,),(0.3081,)) # 像素值:pixel(0~255)>>[0,1] 均值和方差 x=(x-mean)/std
])
train_dataset=datasets.MNIST(root='../dataset/mnist/',
train=True,
transform=transform,
download=True)
test_dataset=datasets.MNIST(root='../dataset/mnist/',
train=False,
transform=transform,
download=True)
train_loader=DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True)
test_loader=DataLoader(dataset=test_dataset,
batch_size=batch_size,
shuffle=False)
#2.搭建神经网络
class Inception(nn.Module):
def __init__(self,in_channels):#输入通道数定为未知量,当实例化模型时可以调用
super(Inception,self).__init__()
self.branch11=nn.Conv2d(in_channels,16,kernel_size=1) #1*1的卷积分支 C1=16 图片形状(h,w)未发生变化
self.branch55_1=nn.Conv2d(in_channels,16,kernel_size=1)
self.branch55_2=nn.Conv2d(16,24,kernel_size=5,padding=2) #5*5的卷积分支 C2=24 图片形状不发生变化
self.branch33_1=nn.Conv2d(in_channels,16,kernel_size=1)
self.branch33_2=nn.Conv2d(16,24,kernel_size=3,padding=1)
self.branch33_3=nn.Conv2d(24,24,kernel_size=3,padding=1) #3*3的卷积分支 C3=24 图片形状不发生变化
self.branch_pool=nn.Conv2d(in_channels,24,kernel_size=1) #1*1的池化分支 C4=24 图片形状不发生变化
def forward(self,x):
branch11=self.branch11(x)
branch55=self.branch55_1(x)
branch55=self.branch55_2(branch55)
branch33=self.branch33_1(x)
branch33=self.branch33_2(branch33)
branch33=self.branch33_3(branch33)
branch_pool=F.avg_pool2d(x,kernel_size=3,stride=1,padding=1)
branch_pool=self.branch_pool(branch_pool)
outputs=[branch11,branch33,branch55,branch_pool]
return torch.cat(outputs,dim=1) #dim=1,在(B,C,H,W)的第二个维度C上合并 其他维度的值必须相同
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.conv1=nn.Conv2d(1,10,kernel_size=5)
self.conv2=nn.Conv2d(88,20,kernel_size=5) #将Inception沿着C维度拼接之后,通道总数未=为88
self.incep1=Inception(in_channels=10)
self.incep2=Inception(in_channels=20)
self.mp=nn.MaxPool2d(kernel_size=2)
self.fc=nn.Linear(1408,10) ###
def forward(self,x):
in_size=x.size(0)
x=F.relu(self.mp(self.conv1(x)))
x=self.incep1(x)
x=F.relu(self.mp(self.conv2(x)))
x=self.incep2(x)
x=x.view(in_size,-1) ###
x=self.fc(x) ### 随机产生一个x 去掉这三行 输出x.size()
return x
net=Net()
device=torch.device("cuda:0"if torch.cuda.is_available()else"cpu") #cuda:1 第二块显卡
net.to(device) #将模型迁移到GPU
#3.定义优化器和损失函数
criterion=nn.CrossEntropyLoss() #这也算是神经网络的一部分
optimizer=optim.SGD(net.parameters(),lr=0.01,momentum=0.5) #冲量值定为0.5 更容易避免 鞍点 或 局部最优解 而找到全局最优解 下山更快
#4.训练模型
def train(epoch):
running_loss=0.0
for batch_idx, data in enumerate(train_loader, 0): # 此函数返回小批量样本的下标数,0代表从第一个开始 ## i,(inputs,labels)
inputs, target = data # 本身读出的是一个样本,但是loader自动组合成矩阵并且转化成tensor
inputs, target = inputs.to(device),target.to(device) #要放到同一块显卡上
optimizer.zero_grad()
outputs = net(inputs)
loss=criterion(outputs,target)
loss.backward()
optimizer.step()
running_loss+=loss.item()
if batch_idx % 300 == 299:
print('[%d,%5d] loss: %.3f' %(epoch+1,batch_idx+1,running_loss/300))
running_loss=0.0
def test():
correct=0 #正确数
total=0 #总数
with torch.no_grad(): #测试集不需要构建计算图
for data in train_loader:
images,labels=data
images,labels=images.to(device),labels.to(device)
outputs = net(images)
_,predicted=torch.max(outputs.data,dim=1) #dim=1 代表对矩阵的行进行求最大值 返回最大值的数值和下标(类别)
total+=labels.size(0) #size为元组(N,10) 返回N
correct+=(predicted==labels).sum().item() #每行若预测正确,则为真 最后矩阵求和即为本批量正确个数
print('Accurance on test set : %d %%' %(100*correct/total))
if __name__=='__main__':
for epoch in range(10):
train(epoch)
test() #每轮更新后进行一次测试
卷积神经网络:Inception Model下的Mnist实例
猜你喜欢
转载自blog.csdn.net/qq_21686871/article/details/114376576
今日推荐
周排行