From 77295c9d41fe757ae4ea842c48e28827aa064a4e Mon Sep 17 00:00:00 2001 From: wizardforcel <562826179@qq.com> Date: Sun, 17 Jan 2021 22:26:16 +0800 Subject: [PATCH] 2021-01-17 22:26:16 --- new/dl-pt-workshop/7.md | 735 +++++++++++++++------------------------- 1 file changed, 268 insertions(+), 467 deletions(-) diff --git a/new/dl-pt-workshop/7.md b/new/dl-pt-workshop/7.md index 72335aad..46a43a20 100644 --- a/new/dl-pt-workshop/7.md +++ b/new/dl-pt-workshop/7.md @@ -802,93 +802,70 @@ 1. 导入所需的库。 - 将 numpy 导入为 np - - 进口火炬 - - 从火炬进口 nn,乐观 - - 导入功能为 F 的 torch.nn。 - - 从 torchvision 导入数据集中 - - 导入 torchvision.transforms 作为转换 - - 从 torch.utils.data.sampler 导入 SubsetRandomSampler - - 从 sklearn.metrics 导入 precision_score - - 导入 matplotlib.pyplot 作为 plt + ```py + import numpy as np + import torch + from torch import nn, optim + import torch.nn.functional as F + from torchvision import datasets + import torchvision.transforms as transforms + from torch.utils.data.sampler import SubsetRandomSampler + from sklearn.metrics import accuracy_score + import matplotlib.pyplot as plt + ``` 2. 设置要对数据进行的变换,将数据转换为张量并对像素值进行归一化。 - 变换= \ - - transforms.Compose([[transforms.ToTensor(),\ - - transforms.Normalize((0.5,0.5,0.5),\ - - (0.5, 0.5, 0.5))]) + ```py + transform = \ +     transforms.Compose([transforms.ToTensor(), \ +                         transforms.Normalize((0.5, 0.5, 0.5),\ +                                              (0.5, 0.5, 0.5))]) + ``` 3. 设置批量大小为 100 张图像,并从 **CIFAR10** 数据集下载训练和测试数据。 + ```py batch_size = 100 - - train_data =数据集.CIFAR10('data',train = True,\ - - download = True,\ - - 转换=转换) - - test_data =数据集.CIFAR10('data',train = False,\ - - download = True,\ - - 转换=转换) + train_data = datasets.CIFAR10('data', train=True, \ +                               download=True, \ +                               transform=transform) + test_data = datasets.CIFAR10('data', train=False, \ +                              download=True, \ +                              transform=transform) + ``` 前面的代码将下载可通过 PyTorch 的`Torchvision`软件包获得的训练和测试数据集。 根据上一步中定义的转换对数据集进行转换。 4. 使用 20% 的验证大小,定义训练和验证采样器,用于将数据集划分为这两组。 + ```py dev_size = 0.2 - - idx =列表(范围(len(train_data))) - - np.random.shuffle(idx) - - split_size = int(np.floor(dev_size * len(train_data))) - - train_idx,dev_idx = idx [split_size:],idx [:split_size] - - train_sampler = SubsetRandomSampler(train_idx) - - dev_sampler = SubsetRandomSampler(dev_idx) + idx = list(range(len(train_data))) + np.random.shuffle(idx) + split_size = int(np.floor(dev_size * len(train_data))) + train_idx, dev_idx = idx[split_size:], idx[:split_size] + train_sampler = SubsetRandomSampler(train_idx) + dev_sampler = SubsetRandomSampler(dev_idx) + ``` 为了将训练集分为两组(训练和验证),为每个组定义了一个索引列表,然后可以使用`SubsetRandomSampler`函数对其进行随机采样。 5. 使用`DataLoader()`函数来定义要使用的每一组数据的批次。 + ```py train_loader = \ - - torch.utils.data.DataLoader(train_data,\ - - batch_size =批量大小,\ - - sampler = train_sampler) - + torch.utils.data.DataLoader(train_data, \ +                             batch_size=batch_size, \ +                             sampler=train_sampler) dev_loader = \ - - torch.utils.data.DataLoader(train_data,\ - - batch_size =批量大小,\ - - sampler = dev_sampler) - + torch.utils.data.DataLoader(train_data, \ +                             batch_size=batch_size, \ +                             sampler=dev_sampler) test_loader = \ - - torch.utils.data.DataLoader(test_data,\ - - batch_size =批量大小) + torch.utils.data.DataLoader(test_data, \ +                             batch_size=batch_size) + ``` PyTorch 的`DataLoader`函数用于创建批量,这些批量将在开发过程的训练,验证和测试阶段馈送到模型中。 @@ -910,319 +887,188 @@ Linear2:一个全连接层,可生成 10 个输出,每个类标签一个。 将`log_softmax`激活函数用于输出层: - CNN(nn.Module)类: - - def __init __(): - - 超级(CNN,自我).__ init __() - - self.conv1 = nn.Conv2d(3,10,3,1,1) - - self.conv2 = nn.Conv2d(10,20,3,1,1) - - self.conv3 = nn.Conv2d(20,40,3,1,1) - - self.pool = nn.MaxPool2d(2,2) - - self.linear1 = nn.Linear(40 * 4 * 4,100) - - self.linear2 = nn.Linear(100,10) - - self.dropout = nn.Dropout(0.2) - - def forward(self,x): - - x = self.pool(F.relu(self.conv1(x))) - - x = self.pool(F.relu(self.conv2(x))) - - x = self.pool(F.relu(self.conv3(x))) - - x = x.view(-1,40 * 4 * 4) - - x = self.dropout(x) - - x = F.relu(self.linear1(x)) - - x = self.dropout(x) - - x = F.log_softmax(self.linear2(x),dim = 1) - - 返回 x + ```py + class CNN(nn.Module): +     def __init__(self): +         super(CNN, self).__init__() +         self.conv1 = nn.Conv2d(3, 10, 3, 1, 1) +         self.conv2 = nn.Conv2d(10, 20, 3, 1, 1) +         self.conv3 = nn.Conv2d(20, 40, 3, 1, 1) +         self.pool = nn.MaxPool2d(2, 2) +         self.linear1 = nn.Linear(40 * 4 * 4, 100) +         self.linear2 = nn.Linear(100, 10) +         self.dropout = nn.Dropout(0.2) +     def forward(self, x): +         x = self.pool(F.relu(self.conv1(x))) +         x = self.pool(F.relu(self.conv2(x))) +         x = self.pool(F.relu(self.conv3(x))) +         x = x.view(-1, 40 * 4 * 4) +         x = self.dropout(x) +         x = F.relu(self.linear1(x)) +         x = self.dropout(x) +         x = F.log_softmax(self.linear2(x), dim=1) +         return x + ``` 前面的代码段包含一个定义了网络架构的类(`__init__`方法),以及在信息正向传递过程中所遵循的步骤(`forward`方法)。 7. 定义训练模型所需的所有参数。设置周期数为`50`。 - 型号= CNN() - - loss_function = nn.NLLLoss() - - 优化程序= optim.Adam(model.parameters(),lr = 0.001) - - 时代= 50 + ```py + model = CNN() + loss_function = nn.NLLLoss() + optimizer = optim.Adam(model.parameters(), lr=0.001) + epochs = 50 + ``` 我们为此练习选择的优化器是 Adam。 同样,负对数似然率用作损失函数,如本书前一章所述。 如果您的计算机具有可用的 GPU,则应按以下步骤完成模型的实例化: - 型号= CNN()。to(“ cuda”) + ```py + model = CNN().to("cuda") + ``` 8. 训练你的网络,并确保保存训练集和验证集的损失和准确性的值。 - train_losses,dev_losses,train_acc,dev_acc = [],[],[],[] - + ```py + train_losses, dev_losses, train_acc, dev_acc= [], [], [], [] x_axis = [] - - #循环遍历 - - 对于范围(1,历元+1)中的 e: - - 损失= 0 - - acc = 0 - - 迭代次数= 0 - - model.train() - - """ - - For 遍历批量(使用创建 - - 火车装载者) - - """ - - 对于数据,在 train_loader 中定位: - - 迭代次数== 1 - - #训练数据的前后传递 - - pred =模型(数据) - - 损失= loss_function(pred,目标) - - Optimizer.zero_grad() - - loss.backward() - - Optimizer.step() - - 损失+ = loss.item() - - p = torch.exp(pred) - - top_p,top_class = p.topk(1,暗= 1) - - acc + = precision_score(target,top_class) - - dev_losss = 0 - - dev_accs = 0 - - iter_2 = 0 - - #验证给定时期的模型 - - 如果 e% 5 == 0 或 e == 1: - - x_axis.append(e) - - 使用 torch.no_grad(): - - model.eval() - - """ - - 用于循环遍历 - - 验证集 - - """ - - 对于 dev_loader 中的 data_dev,target_dev: - - iter_2 + = 1 - - dev_pred =模型(data_dev) - - dev_loss = loss_function(dev_pred,target_dev) - - dev_losss + = dev_loss.item() - - dev_p = torch.exp(dev_pred) - - top_p,dev_top_class = dev_p.topk(1,暗= 1) - - dev_accs + = precision_score(target_dev,\ - - dev_top_class) - - #损失和准确率将附加打印 - - train_losses.append(损失/迭代) - - dev_losses.append(dev_losss / iter_2) - - train_acc.append(acc /迭代) - - dev_acc.append(dev_accs / iter_2) - - print(“ Epoch:{} / {} ..”“ .format(e,epochs),\ - - “训练损失:{:. 3f} ..” \ - - .format(损失/迭代),\ - - “验证损失:{:. 3f} ..” \ - - .format(dev_losss / iter_2),\ - - “训练准确率:{:. 3f} ..” \ - - .format(acc / iterations),\ - - “验证准确率:{:. 3f}” \ - - .format(dev_accs / iter_2)) + # For loop through the epochs + for e in range(1, epochs+1): +     losses = 0 +     acc = 0 +     iterations = 0 +     model.train() +     """ +     For loop through the batches (created using +     the train loader) +     """ +     for data, target in train_loader: +         iterations += 1 +         # Forward and backward pass of the training data +         pred = model(data) +         loss = loss_function(pred, target) +         optimizer.zero_grad() +         loss.backward() +         optimizer.step() +         losses += loss.item() +         p = torch.exp(pred) +         top_p, top_class = p.topk(1, dim=1) +         acc += accuracy_score(target, top_class) +     dev_losss = 0 +     dev_accs = 0 +     iter_2 = 0 +     # Validation of model for given epoch +     if e%5 == 0 or e == 1: +         x_axis.append(e) +         with torch.no_grad(): +             model.eval() +             """ +             For loop through the batches of +             the validation set +             """ +             for data_dev, target_dev in dev_loader: +                 iter_2 += 1 +                 dev_pred = model(data_dev) +                 dev_loss = loss_function(dev_pred, target_dev) +                 dev_losss += dev_loss.item() +                 dev_p = torch.exp(dev_pred) +                 top_p, dev_top_class = dev_p.topk(1, dim=1) +                 dev_accs += accuracy_score(target_dev, \ +                                            dev_top_class) +         # Losses and accuracy are appended to be printed +         train_losses.append(losses/iterations) +         dev_losses.append(dev_losss/iter_2) +         train_acc.append(acc/iterations) +         dev_acc.append(dev_accs/iter_2) +         print("Epoch: {}/{}.. ".format(e, epochs), \ +               "Training Loss: {:.3f}.. "\ +               .format(losses/iterations), \ +               "Validation Loss: {:.3f}.. "\ +               .format(dev_losss/iter_2), \ +               "Training Accuracy: {:.3f}.. "\ +               .format(acc/iterations), \ +               "Validation Accuracy: {:.3f}"\ +               .format(dev_accs/iter_2)) + ``` 如果您的计算机具有可用的 GPU,则对前面的代码进行一些修改,如下所示: - train_losses,dev_losses,train_acc,dev_acc = [],[],[],[] - + ```py + train_losses, dev_losses, train_acc, dev_acc= [], [], [], [] x_axis = [] - - #循环遍历 - - 对于范围(1,历元+1)中的 e: - - 损失= 0 - - acc = 0 - - 迭代次数= 0 - - model.train() - - """ - - 循环遍历批量 - - (使用火车装载程序创建) - - """ - - 对于数据,在 train_loader 中定位: - - 迭代次数== 1 - - #训练数据的前后传递 - - pred =模型(data.to(“ cuda”)) - - 损失= loss_function(pred,target.to(“ cuda”)) - - Optimizer.zero_grad() - - loss.backward() - - Optimizer.step() - - 损失+ = loss.item() - - p = torch.exp(pred) - - top_p,top_class = p.topk(1,暗= 1) - - acc + = precision_score(target.to(“ cpu”),\ - - top_class.to(“ cpu”)) - - dev_losss = 0 - - dev_accs = 0 - - iter_2 = 0 - - #验证给定时期的模型 - - 如果 e% 5 == 0 或 e == 1: - - x_axis.append(e) - - 使用 torch.no_grad(): - - model.eval() - - """ - - 用于循环遍历 - - 验证集 - - """ - - 对于 dev_loader 中的 data_dev,target_dev: - - iter_2 + = 1 - - dev_pred =模型(data_dev.to(“奇迹”)) - - dev_loss = loss_function(dev_pred,\ - - target_dev.to(“ cuda”)) - - dev_losss + = dev_loss.item() - - dev_p = torch.exp(dev_pred) - - top_p,dev_top_class = dev_p.topk(1,暗= 1) - - dev_accs + = \ - - precision_score(target_dev.to(“ cpu”),\ - - dev_top_class.to(“ cpu”)) - - #损失和准确率将附加打印 - - train_losses.append(损失/迭代) - - dev_losses.append(dev_losss / iter_2) - - train_acc.append(acc /迭代) - - dev_acc.append(dev_accs / iter_2) - - print(“ Epoch:{} / {} ..”“ .format(e,epochs),\ - - “训练损失:{:. 3f} ..” \ - - .format(损失/迭代),\ - - “验证损失:{:. 3f} ..” \ - - .format(dev_losss / iter_2),\ - - “训练准确率:{:. 3f} ..” \ - - .format(acc / iterations),\ - - “验证准确率:{:. 3f}” \ - - .format(dev_accs / iter_2)) + # For loop through the epochs + for e in range(1, epochs+1): +     losses = 0 +     acc = 0 +     iterations = 0 +      +     model.train() +     """ +     For loop through the batches +     (created using the train loader) +     """ +     for data, target in train_loader: +         iterations += 1 +         # Forward and backward pass of the training data +         pred = model(data.to("cuda")) +         loss = loss_function(pred, target.to("cuda")) +         optimizer.zero_grad() +         loss.backward() +         optimizer.step() +         losses += loss.item() +         p = torch.exp(pred) +         top_p, top_class = p.topk(1, dim=1) +         acc += accuracy_score(target.to("cpu"), \ +                top_class.to("cpu")) +     dev_losss = 0 +     dev_accs = 0 +     iter_2 = 0 +     # Validation of model for given epoch +     if e%5 == 0 or e == 1: +         x_axis.append(e) +         with torch.no_grad(): +             model.eval() +             """ +             For loop through the batches of +             the validation set +             """ +             for data_dev, target_dev in dev_loader: +                 iter_2 += 1 +                 dev_pred = model(data_dev.to("cuda")) +                 dev_loss = loss_function(dev_pred, \ +                            target_dev.to("cuda")) +                 dev_losss += dev_loss.item() +                 dev_p = torch.exp(dev_pred) +                 top_p, dev_top_class = dev_p.topk(1, dim=1) +                 dev_accs += \ +                 accuracy_score(target_dev.to("cpu"), \ +                                dev_top_class.to("cpu")) +         # Losses and accuracy are appended to be printed +         train_losses.append(losses/iterations) +         dev_losses.append(dev_losss/iter_2) +         train_acc.append(acc/iterations) +         dev_acc.append(dev_accs/iter_2) +         print("Epoch: {}/{}.. ".format(e, epochs), \ +               "Training Loss: {:.3f}.. "\ +               .format(losses/iterations), \ +               "Validation Loss: {:.3f}.. "\ +               .format(dev_losss/iter_2), \ +               "Training Accuracy: {:.3f}.. "\ +               .format(acc/iterations), \ +               "Validation Accuracy: {:.3f}"\ +               .format(dev_accs/iter_2)) + ``` 9. 绘制这两组数据的损失和精度。要绘制损失,请使用以下代码。 - plt.plot(x_axis,train_losses,label ='训练损失') - - plt.plot(x_axis,dev_losses,label ='验证损失') - - plt.legend(frameon = False) - + ```py + plt.plot(x_axis,train_losses, label='Training loss') + plt.plot(x_axis, dev_losses, label='Validation loss') + plt.legend(frameon=False) plt.show() + ``` 结果图应类似于以下内容: @@ -1232,13 +1078,12 @@ 要绘制精度,请使用以下代码: - plt.plot(x_axis,train_acc,label =“训练精度”) - - plt.plot(x_axis,dev_acc,label =“验证准确率”) - - plt.legend(frameon = False) - + ```py + plt.plot(x_axis, train_acc, label="Training accuracy") + plt.plot(x_axis, dev_acc, label="Validation accuracy") + plt.legend(frameon=False) plt.show() + ``` 该图应类似于以下内容: @@ -1250,51 +1095,36 @@ 10. 在测试集上检查模型的准确性。 - model.eval() - + ```py + model.eval() iter_3 = 0 - acc_test = 0 - - 对于 test_loader 中的 data_test 和 target_test: - - iter_3 + = 1 - - test_pred =模型(data_test) - - test_pred = torch.exp(test_pred) - - top_p,top_class_test = test_pred.topk(1,暗= 1) - - acc_test + =准确度得分(target_test,top_class_test) - - 打印(acc_test / iter_3) + for data_test, target_test in test_loader: +     iter_3 += 1 +     test_pred = model(data_test) +     test_pred = torch.exp(test_pred) +     top_p, top_class_test = test_pred.topk(1, dim=1) +     acc_test += accuracy_score(target_test, top_class_test) + print(acc_test/iter_3) + ``` 使用我们之前创建的数据加载器,可以对测试集数据进行图像分类,以估计模型在看不见数据上的准确率。 如果您的计算机具有可用的 GPU,则对前面的代码进行一些修改,如下所示: - model.eval() - + ```py + model.eval() iter_3 = 0 - acc_test = 0 - - 对于 test_loader 中的 data_test 和 target_test: - - iter_3 + = 1 - - test_pred =模型(data_test.to(“ cuda”)) - - test_pred = torch.exp(test_pred) - - top_p,top_class_test = test_pred.topk(1,暗= 1) - - acc_test + = precision_score(target_test .to(“ cpu”),\ - - top_class_test .to(“ cpu”)) - - 打印(acc_test / iter_3) + for data_test, target_test in test_loader: +     iter_3 += 1 +     test_pred = model(data_test.to("cuda")) +     test_pred = torch.exp(test_pred) +     top_p, top_class_test = test_pred.topk(1, dim=1) +     acc_test += accuracy_score(target_test .to("cpu"), \ +                                top_class_test .to("cpu")) + print(acc_test/iter_3) + ``` 测试集的准确率与其他两组所达到的准确率非常相似,这意味着该模型能够对看不见的数据表现出同样出色的性能。 它应该在 72% 左右。 @@ -1320,27 +1150,19 @@ 对于测试集,请勿添加任何其他转换: - 变换= \ - - {“火车”:transforms.Compose([\ - - transforms.RandomHorizo​​ntalFlip(0.5),\ - - transforms.RandomGrayscale(0.1),\ - - transforms.ToTensor(),\ - - transforms.Normalize((0.5,0.5,0.5),\ - - (0.5, 0.5, 0.5))]),\ - - “ test”:transforms.Compose([\ - - transforms.ToTensor(),\ - - transforms.Normalize((0.5,0.5,0.5),\ - - (0.5, 0.5, 0.5))])} + ```py + transform = \ + {"train": transforms.Compose([\ +           transforms.RandomHorizontalFlip(0.5), \ +           transforms.RandomGrayscale(0.1),\ +           transforms.ToTensor(),\ +           transforms.Normalize((0.5, 0.5, 0.5), \ +                                (0.5, 0.5, 0.5))]),\ + "test": transforms.Compose([\ +         transforms.ToTensor(),\ +         transforms.Normalize((0.5, 0.5, 0.5), \ +                              (0.5, 0.5, 0.5))])} + ``` 3. 训练模型 100 个纪元。 @@ -1382,53 +1204,32 @@ 网络的最终架构应如下: - CNN(nn.Module)类: - - def __init __(): - - 超级(净,自我).__ init __() - - self.conv1 = nn.Conv2d(3,10,3,1,1) - - self.norm1 = nn.BatchNorm2d(10) - - self.conv2 = nn.Conv2d(10,20,3,1,1) - - self.norm2 = nn.BatchNorm2d(20) - - self.conv3 = nn.Conv2d(20,40,3,1,1) - - self.norm3 = nn.BatchNorm2d(40) - - self.pool = nn.MaxPool2d(2,2) - - self.linear1 = nn.Linear(40 * 4 * 4,100) - - self.norm4 = nn.BatchNorm1d(100) - - self.linear2 = nn.Linear(100,10) - - self.dropout = nn.Dropout(0.2) - - def forward(self,x): - - x = self.pool(self.norm1(F.relu(self.conv1(x)))) - - x = self.pool(self.norm2(F.relu(self.conv2(x)))) - - x = self.pool(self.norm3(F.relu(self.conv3(x)))) - - x = x.view(-1,40 * 4 * 4) - - x = self.dropout(x) - - x = self.norm4(F.relu(self.linear1(x))) - - x = self.dropout(x) - - x = F.log_softmax(self.linear2(x),dim = 1) - - 返回 x + ```py + class CNN(nn.Module): +     def __init__(self): +         super(Net, self).__init__() +         self.conv1 = nn.Conv2d(3, 10, 3, 1, 1) +         self.norm1 = nn.BatchNorm2d(10) +         self.conv2 = nn.Conv2d(10, 20, 3, 1, 1) +         self.norm2 = nn.BatchNorm2d(20) +         self.conv3 = nn.Conv2d(20, 40, 3, 1, 1) +         self.norm3 = nn.BatchNorm2d(40) +         self.pool = nn.MaxPool2d(2, 2) +         self.linear1 = nn.Linear(40 * 4 * 4, 100) +         self.norm4 = nn.BatchNorm1d(100) +         self.linear2 = nn.Linear(100, 10) +         self.dropout = nn.Dropout(0.2) +     def forward(self, x): +         x = self.pool(self.norm1(F.relu(self.conv1(x)))) +         x = self.pool(self.norm2(F.relu(self.conv2(x)))) +         x = self.pool(self.norm3(F.relu(self.conv3(x)))) +         x = x.view(-1, 40 * 4 * 4) +         x = self.dropout(x) +         x = self.norm4(F.relu(self.linear1(x))) +         x = self.dropout(x) +         x = F.log_softmax(self.linear2(x), dim=1) +         return x + ``` 3. 训练模型 100 个纪元。 -- GitLab