赞
踩
近期开始学习Pytorch,在这里小小记录下。
由于是实现卷积神经网络,所以数据集统一使用CIFAR10。
首先,搭建最简单的卷积神经网络:
class Model(nn.Module): def __init__(self) : super().__init__() # 序列化 self.model1=Sequential( # 卷积层,参数依次为输入通道数、输出通道数、卷积核大小、填补大小 nn.Conv2d(3, 32, 5, padding=2), # 最大池化层 nn.MaxPool2d(2), nn.Conv2d(32, 32, 5, padding=2), nn.MaxPool2d(2), nn.Conv2d(32, 64, 5, padding=2), nn.MaxPool2d(2), # 扁平化 nn.Flatten(), # 线性层,参数依次为输入特征数、输出特征数 nn.Linear(1024,64), nn.Linear(64,10) ) # 前向传播函数 def forward(self,x): x=self.model1(x) return x
主要是定义一个继承torch.nn.Module的类,然后定义初始化函数和forward函数,其中初始化函数中的序列化函数中操作可以自己搭配(注意参数维度要对应),这里推荐阅读Pytorch官方文档详细了解个函数功能。
实现了卷积类之后,就可以调用训练集进行训练,然后在测试集上得到最终训练结果:
# 训练集,参数分别为数据集路径、是否为训练集、进行的transform转换、是否需要在线下载 train_set=torchvision.datasets.CIFAR10(root='../dataset',train=True,transform=transforms.ToTensor(),download=False) # 测试集 test_set=torchvision.datasets.CIFAR10(root='../dataset',train=False,transform=transforms.ToTensor(),download=False)、 # 加载训练集,参数依次为数据集、批次、是否打乱顺序 train_data=DataLoader(train_set,64,shuffle=True) # 加载测试集 test_data=DataLoader(test_set,64,shuffle=True) # 实例化卷积类 model=Model() # 迭代次数 epoch_time=5 # 学习率 learn_rate=1e-2 # 交叉熵验证损失 loss=torch.nn.CrossEntropyLoss() # 优化器,变量依次为待优化参数。学习率、动量 optim=torch.optim.SGD(model.parameters(),learn_rate,momentum=0.5) for epoch in range(epoch_time): print(f"---第{epoch+1}轮训练开始---") # 训练步数 total_train_step = 0 # 测试精度 total_accuracy=0 # 训练集前固定写法(不写也无妨) model.train() for data in train_data: images,targets=data output=model(images) # 计算损失 res_loss=loss(output,targets) # 清零梯度 optim.zero_grad() # 反向传播 res_loss.backward() # 更新参数 optim.step() total_train_step+=1 if total_train_step%100==0: print(f"训练次数:{total_train_step},损失值:{res_loss}") # 测试集固定写法 model.eval() # 测试集不需要梯度下降,加快计算效率 with torch.no_grad(): for data in test_data: images, targets = data output = model(images) accuracy=(output.argmax(1)==targets).sum() total_accuracy+=accuracy res_loss = loss(output, targets) print(f"精确度={total_accuracy/len(test_set)}")
如果电脑有GPU的话还可以使用cuda()函数加快运算,这里不在赘述。
接下来实现稍微复杂一点的CNN结果,这是GoogleNet中的一个inception模块,主要是使用1x1的卷积来进行升降维,然后在多个尺寸上同时进行卷积再聚合。
实现过程如下,首先定义inception模块:
class Inception(nn.Module): def __init__(self,input): super().__init__() self.block1=nn.Sequential( # 最大池化,参数依次为核大小、步长、填充 nn.MaxPool2d(3,stride=1,padding=1), nn.Conv2d(input,24,1) ) self.block2=nn.Conv2d(input,16,1) self.block3=nn.Sequential( nn.Conv2d(input,16,1), nn.Conv2d(16,24,5,padding=2) ) self.block4=nn.Sequential( nn.Conv2d(input,16,1), nn.Conv2d(16,24,3,padding=1), nn.Conv2d(24,24,3,padding=1), ) def forward(self,x): output1 = self.block1(x) output2 = self.block2(x) output3 = self.block3(x) output4 = self.block4(x) outputs=[output1,output2,output3,output4] # 合并这几个卷积结构处理得到的结果 return torch.cat(outputs,dim=1)
然后在主干网络上调用该模块:
class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.model1=nn.Sequential( nn.Conv2d(3,10,5), nn.MaxPool2d(2), nn.ReLU()) self.inc1=Inception(10) self.model2=nn.Sequential( nn.Conv2d(88,20,5), nn.MaxPool2d(2), nn.ReLU()) self.inc2=Inception(20) self.model3=nn.Sequential( nn.Flatten(), nn.Linear(2200,10) ) def forward(self,x): x=self.model1(x) x=self.inc1(x) x=self.model2(x) x=self.inc2(x) x=self.model3(x) return x
最后是ResNet,主要使用跳跃连接来解决深层神经网络中出现的梯度消失问题。
首先实现残差结构:
class Res(nn.Module):
def __init__(self,input) -> None:
super().__init__()
self.model1=nn.Sequential(
nn.Conv2d(input,input,3,padding=1),
nn.ReLU(),
nn.Conv2d(input, input, 3, padding=1)
)
self.model2=nn.ReLU()
def forward(self,x):
y=self.model1(x)
y=x+y
return self.model2(y)
然后调用该结构形成完整的神经网络:
class Net(nn.Module): def __init__(self) -> None: super().__init__() self.model=nn.Sequential( nn.Conv2d(3,16,5), nn.ReLU(), Res(16), nn.Conv2d(16,32,5), nn.ReLU(), Res(32), nn.MaxPool2d(2), nn.Flatten(), nn.Linear(4608,10) ) def forward(self,x): return self.model(x)
这里在测试时需要注意图片尺寸和卷积处理大小要对应。
如果对自己实现的模型比较满意,也可以使用如下代码保存调用模型:
# 两个参数分别为模型、保存路径
torch.save(model,"mymodel.pth")
# 加载保存的模型
model=torch.load("mymodel.pth")
时间仓促,如有纰漏,请多指教。
以上。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。