CNN循环训练的解释 | PyTorch系列(二十二)

点击上方“AI算法与图像处理”,选择加"星标"或“置顶”

重磅干货,第一时间送达

文 |AI_study

原标题:CNN Training Loop Explained - Neural Network Code Project

  • 准备数据

  • 建立模型

  • 训练模型

    • 建立训练 loop

  • 分析模型的结果

单个 batch  进行训练 

我们可以将单个 batch  训练的代码总结如下:

network = Network()


train_loader = torch.utils.data.DataLoader(train_set, batch_size=100)
optimizer = optim.Adam(network.parameters(), lr=0.01)


batch = next(iter(train_loader)) # Get Batch
images, labels = batch


preds = network(images) # Pass Batch
loss = F.cross_entropy(preds, labels) # Calculate Loss


loss.backward() # Calculate Gradients
optimizer.step() # Update Weights


print('loss1:', loss.item())
preds = network(images)
loss = F.cross_entropy(preds, labels)
print('loss2:', loss.item())

输出

loss1: 2.3034827709198
loss2: 2.2825052738189697

您会注意到的一件事是,每次运行这段代码都会得到不同的结果。这是因为模型每次都是在顶部创建的,我们从以前的文章中知道模型的权重是随机初始化的。

现在让我们看看如何修改这段代码来使用所有的batch,从而使用整个训练集进行训练。

所有 batch的训练 (epoch)

现在,为了训练我们的数据加载器中可用的所有批次,我们需要做一些更改并添加额外的一行代码:

network = Network()


train_loader = torch.utils.data.DataLoader(train_set, batch_size=100)
optimizer = optim.Adam(network.parameters(), lr=0.01)


total_loss = 0
total_correct = 0


for batch in train_loader: # Get Batch
    images, labels = batch


    preds = network(images) # Pass Batch
    loss = F.cross_entropy(preds, labels) # Calculate Loss


    optimizer.zero_grad()
    loss.backward() # Calculate Gradients
    optimizer.step() # Update Weights


    total_loss += loss.item()
    total_correct += get_num_correct(preds, labels)
    
print(
    "epoch:", 0, 
    "total_correct:", total_correct, 
    "loss:", total_loss
)

我们将创建一个for循环来迭代所有batch  处理,而不是从数据加载器获取单个batch  处理。

因为我们的训练集中有60,000个样本,所以我们将有60,000 / 100 = 600次迭代。由于这个原因,我们将从循环中删除print语句,并跟踪总损失和最后打印它们的正确预测总数。

关于这600次迭代需要注意的一点是,到循环结束时,我们的权重将更新600次。如果我们提高batch_size这个数字会下降如果我们降低batch_size这个数字会上升。

最后,在我们对loss张量调用backward() 方法之后,我们知道梯度将被计算出来并添加到网络参数的grad属性中。因为这个原因,我们需要把这些梯度归零。我们可以使用优化器附带的zero_grad()方法来实现这一点。

我们已经准备好运行这段代码。这一次代码将花费更长的时间,因为循环将处理600个批。

epoch: 0 total_correct: 42104 loss: 476.6809593439102

我们得到了结果,我们可以看到60000中正确的总数是42104。

> total_correct / len(train_set)
0.7017333333333333

在只有一个epoch(一次完整的数据传递)之后,这已经很好了。即使我们做了一个epoch,我们仍然需要记住,权重被更新了600次,这取决于我们的批大小。如果让batch_batch的大小更大一些,比如10,000,那么权重只会更新  6  次,结果也不会很好。

多个 epoch的 训练 

要执行多个epoch,我们所要做的就是将此代码放入for循环中。我们还将把epoch数添加到print语句中。

network = Network()


train_loader = torch.utils.data.DataLoader(train_set, batch_size=100)
optimizer = optim.Adam(network.parameters(), lr=0.01)


for epoch in range(10):
    
    total_loss = 0
    total_correct = 0
    
    for batch in train_loader: # Get Batch
        images, labels = batch


        preds = network(images) # Pass Batch
        loss = F.cross_entropy(preds, labels) # Calculate Loss


        optimizer.zero_grad()
        loss.backward() # Calculate Gradients
        optimizer.step() # Update Weights


        total_loss += loss.item()
        total_correct += get_num_correct(preds, labels)


    print(
        "epoch", epoch, 
        "total_correct:", total_correct, 
        "loss:", total_loss
    )

运行这段代码后,我们得到每个epoch的结果:

epoch 0 total_correct: 43301 loss: 447.59147948026657
epoch 1 total_correct: 49565 loss: 284.43429669737816
epoch 2 total_correct: 51063 loss: 244.08825492858887
epoch 3 total_correct: 51955 loss: 220.5841210782528
epoch 4 total_correct: 52551 loss: 204.73878084123135
epoch 5 total_correct: 52914 loss: 193.1240530461073
epoch 6 total_correct: 53195 loss: 184.50964668393135
epoch 7 total_correct: 53445 loss: 177.78808392584324
epoch 8 total_correct: 53629 loss: 171.81662507355213
epoch 9 total_correct: 53819 loss: 166.2412590533495

我们可以看到正确值的数量增加了,而loss减少了。

完整的训练 loop

将所有这些放在一起,我们可以将网络、优化器和train_loader从训练循环单元中提取出来。

network = Network()
optimizer = optim.Adam(network.parameters(), lr=0.01)
train_loader = torch.utils.data.DataLoader(
    train_set
    ,batch_size=100
    ,shuffle=True
)

optimizer = optim.Adam(network.parameters(), lr=0.01)

for epoch in range(10):


    total_loss = 0
    total_correct = 0


    for batch in train_loader: # Get Batch
        images, labels = batch


        preds = network(images) # Pass Batch
        loss = F.cross_entropy(preds, labels) # Calculate Loss


        optimizer.zero_grad()
        loss.backward() # Calculate Gradients
        optimizer.step() # Update Weights


        total_loss += loss.item()
        total_correct += get_num_correct(preds, labels)


    print(
        "epoch", epoch, 
        "total_correct:", total_correct, 
        "loss:", total_loss
    )

接下来是可视化结果

我们现在应该很好地理解了训练循环以及如何使用PyTorch来构建它们。PyTorch很酷的一点是,我们可以像调试forward()函数那样调试训练循环代码。

在下一篇文章中,我们将看到如何获得训练集中每个样本的预测,并使用这些预测创建一个混淆矩阵。下节课见!

文章中内容都是经过仔细研究的,本人水平有限,翻译无法做到完美,但是真的是费了很大功夫,希望小伙伴能动动你性感的小手,分享朋友圈或点个“在看”,支持一下我 ^_^

英文原文链接是:

https://deeplizard.com/learn/video/XfYmia3q2Ow

加群交流

欢迎小伙伴加群交流,目前已有交流群的方向包括:AI学习交流群,目标检测,秋招互助,资料下载等等;加群可扫描并回复感兴趣方向即可(注明:地区+学校/企业+研究方向+昵称)

 谢谢你看到这里! ????

当使用PyTorch实现CNN来处理二分类问题时,你需要完成以下步骤: 1. 导入所需的库和模块: ```python import torch import torch.nn as nn import torch.optim as optim ``` 2. 创建CNN模型类,继承自`nn.Module`: ```python class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() # 定义各个层和参数 def forward(self, x): # 定义前向传播过程 return x ``` 3. 在模型类的`__init__`方法中定义各个层和参数: ```python def __init__(self): super(CNN, self).__init__() self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1) self.relu = nn.ReLU() self.maxpool = nn.MaxPool2d(kernel_size=2, stride=2) self.flatten = nn.Flatten() self.fc1 = nn.Linear(32 * 14 * 14, 128) self.fc2 = nn.Linear(128, 2) ``` 上述代码中,我们定义了一个单通道输入、32个输出通道的卷积层,ReLU激活函数,2x2的最大池化层,将特征展平的层以及两个全连接层。 4. 在模型类的`forward`方法中定义前向传播过程: ```python def forward(self, x): x = self.conv1(x) x = self.relu(x) x = self.maxpool(x) x = self.flatten(x) x = self.fc1(x) x = self.relu(x) x = self.fc2(x) return x ``` 上述代码中,我们按照定义的层次顺序进行了前向传播,最后返回输出。 5. 定义训练循环: ```python model = CNN() criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9) for epoch in range(num_epochs): running_loss = 0.0 for i, data in enumerate(train_loader): inputs, labels = data optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if (i+1) % 100 == 0: print(f"Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{total_steps}], Loss: {running_loss/100:.4f}") running_loss = 0.0 ``` 上述代码中,我们定义了模型、损失函数和优化器。然后,在每个epoch中,对训练数据进行迭代,计算模型输出和损失,并进行反向传播和参数更新。 6. 在测试集上评估模型: ```python with torch.no_grad(): correct = 0 total = 0 for images, labels in test_loader: outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print(f"Accuracy on test set: {(correct/total)*100:.2f}%") ``` 上述代码中,我们关闭梯度计算,使用模型对测试集进行预测,并计算准确率。 这就是使用PyTorch实现CNN处理二分类问题的基本步骤。根据你的数据集和问题,你可能需要进行一些适应性的调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值