pytorch:如何从头开始训练一个CNN网络?


前言

在刚开始学习Deep Learning时,一件几乎不可能的事情就是知道每一个东西背后的原理和用法。但是,很多人又不得不在前期涉猎很多在前期不应该碰的东西。多摸索是好事,但考虑到性价比,最好的办法是有人带着你从头实现一下你所需要做的。在此,我希望本文是目标导向型的——即与你一同从头实现出一个属于你自己的CNN。


一、CNN?

CNN是卷积神经网络,在此,我们力图简洁(让各种trick xx去吧)。我们不会考虑太多的trick,只希望和你一同,实现一个最简单最简单的CNN。

二、用单批量测试模型

称之为”single-batch training“。 事实上,它只是一个用来测试用的、在模型正式训练之前的一个测试。这一步仅仅是为了测试你模型是否有毛病,如果你对你自己的模型有信心,大可不必进行这一步。

在这一步,我们仅需要用一个batch来进行训练,观察其Loss能否降到0(亦为过拟合overfitting),如能,则进行我们的正式训练。

1.引入库

import cv2
import math

import numpy as np
import torch
import torch.nn as nn
import torchvision.transforms as transforms
from torch.hub import load_state_dict_from_url

from PIL import Image
import matplotlib.pyplot as plt
from torchvision.datasets import ImageFolder
from torch.utils.data import Dataset,DataLoader
from torchvision import datasets

2.读入数据集

至于数据集的读入,你可以用老师给的数据库,也可以利用torchvision自带的数据库(如果允许)。我在这篇1里讲到了三种具体的实现方法。但是在这里,我们用老师给的数据库。存放到相对目录的“./train_set/train_set”中。这里存放了30个类(划重点,下面要讲到)。

在这里插入图片描述

我们利用ImageFolder 来进行操作。非常方便。它会自动地读取有几类(几个子文件夹),编号等等工作。

BATCH_SIZE = 64
# normalization
train_transform = transforms.Compose([
    transforms.ColorJitter(hue=0.2, saturation=0.2, brightness=0.2),
    transforms.RandomAffine(degrees=10, translate=(0.1,0.1), scale=(0.9,1.1)),
    transforms.RandomHorizontalFlip(p=0.5),
    transforms.ToTensor()
])

# introduce the dataset 
trainset = ImageFolder(root="./train_set/train_set", transform=train_transform)
train_loader = DataLoader(dataset=trainset, batch_size=BATCH_SIZE, shuffle=False)

有几个坑的地方要注意一下:

  • transform是将图片进行预处理的一个参数。这个参数是需要依赖你自己的想法做的。具体可以自己去查一下,这里不再详细赘述。
  • 如果你决定用”single-batch training“来勘察你的模型维度设置等是否正确,你需要将shuffle设置为False(不随机抽取)。函数参数具体含义已经在pytorch:数据读取操作里

3. 建造Module实例

所谓Module,我们即可以将其实例化为一个层,也可以将其实例化为一个网络(没错就是这么灵活,允许套娃)在此,我们继承nn.Module,设置一个CNN_model类。在 __init__方法中,我们使用将这个网络主要分为两个主要的模块:卷积模块(self.cnn)和全连接层模块(self.linear)。

我们利用 self.cnn = nn.Sequential()函数来整理一个大模块。它是有序的,模块将按照在传入构造器的顺序依次被添加到计算图中执行。注意,这里有30类,所以我们要保证最后一层的输出为30。

class CNN_model(nn.Module):
    def __init__(self):
        super(CNN_model, self).__init__()

        # conv1  
        self.cnn = nn.Sequential(
            nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(16),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2), # 16x16x650
            nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1), # 32x16x650
            nn.ReLU(),
            nn.Dropout2d(0.5),
            nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1), # 64x16x650
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2), # 64x8x325
            nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
            nn.ReLU() # 64x8x325
        )
        self.linear = nn.Sequential(
            nn.Linear(32768, 128),
            nn.ReLU(),
            nn.Linear(128, 256),
            nn.ReLU(),
            nn.Linear(256, 30)
        ) 
        
    def forward(self,x):
        x = self.cnn(x)
        fc_input=x.view(x.size(0),-1)
        fc_output = self.linear(fc_input)
        return fc_output
        
# 将其实例化
cnn = CNN_model()
for param in cnn.parameters():
    print(param.shape)
    
# 得到一个data,查看是否成功读取。
dataiter = iter(train_loader)
images, labels = dataiter.next()
print(labels)

4. 训练

在训练时,我们要确定我们需要什么损失函数。这又和具体的分类任务有关……如果想让本文篇幅稍微短点,恐怕还是绕过这个话题比较好。还记得我们所用的数据集吗?有30类对吧?我们用这CrossEntropyLoss()损失函数来完成分类的任务。

请仔细阅读代码与注释。

loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(cnn.parameters(), lr=0.001, momentum=0.9)

for epoch in range(nepochs):  # loop over the dataset multiple times
    correct = 0          # number of examples predicted correctly (for accuracy)
    total = 0            # number of examples
    running_loss = 0.0   # accumulated loss (for mean loss)
    n = 0                # number of minibatches
    
    # 每个epoch,我们都取第一个batch来进行训练。
    dataiter = iter(train_loader) 
    inputs, labels = dataiter.next()
    
    # ================== main body=========================
     # 将梯度清空(每轮epoch都清空)
    optimizer.zero_grad()
    # Forward, backward, and update parameters
    outputs = cnn(inputs)
    loss = loss_fn(outputs, labels)
    loss.backward()
    optimizer.step()
    # =====================================================
    # accumulate loss
    running_loss += loss.item()
    n += 1
        
    # accumulate data for accuracy
    _, predicted = torch.max(outputs.data, 1)
    total += labels.size(0)    # add in the number of labels in this minibatch
    correct += (predicted == labels).sum().item()  # add in the number of correct labels
    
    # collect together statistics for this epoch
    ltrn = running_loss/n
    atrn = correct/total 
    
    print(f"epoch: {epoch} training loss: {ltrn: .3f} training accuracy: {atrn: .1%} ")

总结

可以看到,核心代码区区不过几行。你可能会问:这只是单个batch的呀?需要多个batch只需要一个循环就解决了!在下一篇《pytorch:如何从头开始训练一个CNN网络?(二)》中,我们还会学习到一些使你涨点的技巧。记住我们的学习哲学:

我们在这里只是工程导向,并不详细阐述背后原理。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyTorch是一种用于开发深度学习模型的开源机器学习框架,可以用于训练滑坡检测模型。 首先,我们需要准备滑坡检测的数据集。这个数据集应包含正常地形和滑坡地形的图像样本。可以使用卫星图像、无人机图像或其他相关数据源获取这些图像。并且,这些图像应包含与滑坡相关的标签信息。 接下来,我们需要将数据集划分为训练集和验证集。通常,我们会将数据集的大部分用于训练,用于模型的参数优化和学习;其余的部分则用于验证模型的性能。 在PyTorch中,我们可以使用其强大的深度学习工具和函数来构建一个滑坡检测模型。可以选择使用预训练模型,如ResNet或VGG,并通过迁移学习将其适应于滑坡检测任务。或者,我们也可以从头开始构建自己的模型,例如使用卷积神经网络CNN)。 然后,我们需要定义模型的损失函数和优化器。常见的损失函数有交叉熵损失函数,用于多分类问题,或者均方误差损失函数,用于回归问题。优化器可以选择Adam、SGD或其他优化算法。 然后,我们可以开始训练模型。通过将训练集输入到模型中,并让模型根据损失函数来优化自身的权重和偏差。这个过程称为前向传播和反向传播。 在每个训练周期(epoch)结束后,我们可以用验证集评估模型的性能。可以计算模型的准确率、精确率、召回率等指标,以衡量模型的效果。 最后,当模型训练完成并满足我们的要求时,我们可以使用它对新的未知数据进行预测。将未知地形输入到模型中,模型将输出相应的滑坡概率或分类结果。 总之,使用PyTorch可以训练一个滑坡检测模型,其中包括数据准备、模型构建、损失函数和优化器定义、模型训练和验证过程。通过这个过程,我们可以得到一个性能良好的滑坡检测模型,用于识别滑坡地形。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值