zoukankan      html  css  js  c++  java
  • pytorch识别CIFAR10:训练ResNet-34(准确率80%)

    版权声明:本文为博主原创文章,欢迎转载,并请注明出处。联系方式:460356155@qq.com

    CNN的层数越多,能够提取到的特征越丰富,但是简单地增加卷积层数,训练时会导致梯度弥散或梯度爆炸。

    何凯明2015年提出了残差神经网络,即Reset,并在ILSVRC-2015的分类比赛中获得冠军。

    ResNet可以有效的消除卷积层数增加带来的梯度弥散或梯度爆炸问题。

    ResNet的核心思想是网络输出分为2部分恒等映射(identity mapping)、残差映射(residual mapping),即y = x + F(x),图示如下:

    ResNet通过改变学习目标,即由学习完整的输出变为学习残差,解决了传统卷积在信息传递时存在的信息丢失核损耗问题,通过将输入直接绕道传递到输出,保护了信息的完整性。此外学习目标的简化也降低了学习难度。

    常见的ResNet结构有:

    34层的ResNet图示如下:

    pytorch实现核训练ResNet-34的代码如下:

      1 # -*- coding:utf-8 -*-
      2 
      3 u"""ResNet训练学习CIFAR10"""
      4 
      5 __author__ = 'zhengbiqing 460356155@qq.com'
      6 
      7 
      8 import torch as t
      9 import torchvision as tv
     10 import torch.nn as nn
     11 import torch.optim as optim
     12 import torchvision.transforms as transforms
     13 from torchvision.transforms import ToPILImage
     14 import torch.backends.cudnn as cudnn
     15 
     16 import matplotlib.pyplot as plt
     17 
     18 import datetime
     19 import argparse
     20 
     21 
     22 # 样本读取线程数
     23 WORKERS = 4
     24 
     25 # 网络参赛保存文件名
     26 PARAS_FN = 'cifar_resnet_params.pkl'
     27 
     28 # minist数据存放位置
     29 ROOT = '/home/zbq/PycharmProjects/cifar'
     30 
     31 # 目标函数
     32 loss_func = nn.CrossEntropyLoss()
     33 
     34 # 最优结果
     35 best_acc = 0
     36 
     37 # 记录准确率,显示曲线
     38 global_train_acc = []
     39 global_test_acc = []
     40 
     41 
     42 '''
     43 残差块
     44 in_channels, out_channels:残差块的输入、输出通道数
     45 对第一层,in out channel都是64,其他层则不同
     46 对每一层,如果in out channel不同, stride是1,其他层则为2
     47 '''
     48 class ResBlock(nn.Module):
     49     def __init__(self, in_channels, out_channels, stride=1):
     50         super(ResBlock, self).__init__()
     51 
     52         # 残差块的第一个卷积
     53         # 通道数变换in->out,每一层(除第一层外)的第一个block
     54         # 图片尺寸变换:stride=2时,w-3+2 / 2 + 1 = w/2,w/2 * w/2
     55         # stride=1时尺寸不变,w-3+2 / 1 + 1 = w
     56         self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1)
     57         self.bn1 = nn.BatchNorm2d(out_channels)
     58         self.relu = nn.ReLU(inplace=True)
     59 
     60         # 残差块的第二个卷积
     61         # 通道数、图片尺寸均不变
     62         self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1)
     63         self.bn2 = nn.BatchNorm2d(out_channels)
     64 
     65         # 残差块的shortcut
     66         # 如果残差块的输入输出通道数不同,则需要变换通道数及图片尺寸,以和residual部分相加
     67         # 输出:通道数*2 图片尺寸/2
     68         if in_channels != out_channels:
     69             self.downsample = nn.Sequential(
     70                 nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=2),
     71                 nn.BatchNorm2d(out_channels)
     72             )
     73         else:
     74             # 通道数相同,无需做变换,在forward中identity = x
     75             self.downsample = None
     76 
     77     def forward(self, x):
     78         identity = x
     79 
     80         out = self.conv1(x)
     81         out = self.bn1(out)
     82         out = self.relu(out)
     83 
     84         out = self.conv2(out)
     85         out = self.bn2(out)
     86 
     87         if self.downsample is not None:
     88             identity = self.downsample(x)
     89 
     90         out += identity
     91         out = self.relu(out)
     92 
     93         return out
     94 
     95 
     96 '''
     97 定义网络结构
     98 '''
     99 class ResNet34(nn.Module):
    100     def __init__(self, block):
    101         super(ResNet34, self).__init__()
    102 
    103         # 初始卷积层核池化层
    104         self.first = nn.Sequential(
    105             # 卷基层1:7*7kernel,2stride,3padding,outmap:32-7+2*3 / 2 + 1,16*16
    106             nn.Conv2d(3, 64, 7, 2, 3),
    107             nn.BatchNorm2d(64),
    108             nn.ReLU(inplace=True),
    109 
    110             # 最大池化,3*3kernel,1stride(32的原始输入图片较小,不再缩小尺寸),1padding,
    111             # outmap:16-3+2*1 / 1 + 1,16*16
    112             nn.MaxPool2d(3, 1, 1)
    113         )
    114 
    115         # 第一层,通道数不变
    116         self.layer1 = self.make_layer(block, 64, 64, 3, 1)
    117 
    118         # 第2、3、4层,通道数*2,图片尺寸/2
    119         self.layer2 = self.make_layer(block, 64, 128, 4, 2)  # 输出8*8
    120         self.layer3 = self.make_layer(block, 128, 256, 6, 2)  # 输出4*4
    121         self.layer4 = self.make_layer(block, 256, 512, 3, 2)  # 输出2*2
    122 
    123         self.avg_pool = nn.AvgPool2d(2)  # 输出512*1
    124         self.fc = nn.Linear(512, 10)
    125 
    126     def make_layer(self, block, in_channels, out_channels, block_num, stride):
    127         layers = []
    128 
    129         # 每一层的第一个block,通道数可能不同
    130         layers.append(block(in_channels, out_channels, stride))
    131 
    132         # 每一层的其他block,通道数不变,图片尺寸不变
    133         for i in range(block_num - 1):
    134             layers.append(block(out_channels, out_channels, 1))
    135 
    136         return nn.Sequential(*layers)
    137 
    138     def forward(self, x):
    139         x = self.first(x)
    140         x = self.layer1(x)
    141         x = self.layer2(x)
    142         x = self.layer3(x)
    143         x = self.layer4(x)
    144         x = self.avg_pool(x)
    145 
    146         # x.size()[0]: batch size
    147         x = x.view(x.size()[0], -1)
    148         x = self.fc(x)
    149 
    150         return x
    151 
    152 
    153 '''
    154 训练并测试网络
    155 net:网络模型
    156 train_data_load:训练数据集
    157 optimizer:优化器
    158 epoch:第几次训练迭代
    159 log_interval:训练过程中损失函数值和准确率的打印频率
    160 '''
    161 def net_train(net, train_data_load, optimizer, epoch, log_interval):
    162     net.train()
    163 
    164     begin = datetime.datetime.now()
    165 
    166     # 样本总数
    167     total = len(train_data_load.dataset)
    168 
    169     # 样本批次训练的损失函数值的和
    170     train_loss = 0
    171 
    172     # 识别正确的样本数
    173     ok = 0
    174 
    175     for i, data in enumerate(train_data_load, 0):
    176         img, label = data
    177         img, label = img.cuda(), label.cuda()
    178 
    179         optimizer.zero_grad()
    180 
    181         outs = net(img)
    182         loss = loss_func(outs, label)
    183         loss.backward()
    184         optimizer.step()
    185 
    186         # 累加损失值和训练样本数
    187         train_loss += loss.item()
    188 
    189         _, predicted = t.max(outs.data, 1)
    190         # 累加识别正确的样本数
    191         ok += (predicted == label).sum()
    192 
    193         if (i + 1) % log_interval == 0:
    194             # 训练结果输出
    195 
    196             # 已训练的样本数
    197             traind_total = (i + 1) * len(label)
    198 
    199             # 准确度
    200             acc = 100. * ok / traind_total
    201 
    202             # 记录训练准确率以输出变化曲线
    203             global_train_acc.append(acc)
    204 
    205     end = datetime.datetime.now()
    206     print('one epoch spend: ', end - begin)
    207 
    208 
    209 '''
    210 用测试集检查准确率
    211 '''
    212 def net_test(net, test_data_load, epoch):
    213     net.eval()
    214 
    215     ok = 0
    216 
    217     for i, data in enumerate(test_data_load):
    218         img, label = data
    219         img, label = img.cuda(), label.cuda()
    220 
    221         outs = net(img)
    222         _, pre = t.max(outs.data, 1)
    223         ok += (pre == label).sum()
    224 
    225     acc = ok.item() * 100. / (len(test_data_load.dataset))
    226     print('EPOCH:{}, ACC:{}
    '.format(epoch, acc))
    227 
    228     # 记录测试准确率以输出变化曲线
    229     global_test_acc.append(acc)
    230 
    231     # 最好准确度记录
    232     global best_acc
    233     if acc > best_acc:
    234         best_acc = acc
    235 
    236 
    237 '''
    238 显示数据集中一个图片
    239 '''
    240 def img_show(dataset, index):
    241     classes = ('plane', 'car', 'bird', 'cat',
    242                'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
    243 
    244     show = ToPILImage()
    245 
    246     data, label = dataset[index]
    247     print('img is a ', classes[label])
    248     show((data + 1) / 2).resize((100, 100)).show()
    249 
    250 
    251 '''
    252 显示训练准确率、测试准确率变化曲线
    253 '''
    254 def show_acc_curv(ratio):
    255     # 训练准确率曲线的x、y
    256     train_x = list(range(len(global_train_acc)))
    257     train_y = global_train_acc
    258 
    259     # 测试准确率曲线的x、y
    260     # 每ratio个训练准确率对应一个测试准确率
    261     test_x = train_x[ratio-1::ratio]
    262     test_y = global_test_acc
    263 
    264     plt.title('CIFAR10 RESNET34 ACC')
    265 
    266     plt.plot(train_x, train_y, color='green', label='training accuracy')
    267     plt.plot(test_x, test_y, color='red', label='testing accuracy')
    268 
    269     # 显示图例
    270     plt.legend()
    271     plt.xlabel('iterations')
    272     plt.ylabel('accs')
    273 
    274     plt.show()
    275 
    276 
    277 def main():
    278     # 训练超参数设置,可通过命令行设置
    279     parser = argparse.ArgumentParser(description='PyTorch CIFA10 ResNet34 Example')
    280     parser.add_argument('--batch-size', type=int, default=128, metavar='N',
    281                         help='input batch size for training (default: 128)')
    282     parser.add_argument('--test-batch-size', type=int, default=100, metavar='N',
    283                         help='input batch size for testing (default: 100)')
    284     parser.add_argument('--epochs', type=int, default=200, metavar='N',
    285                         help='number of epochs to train (default: 200)')
    286     parser.add_argument('--lr', type=float, default=0.1, metavar='LR',
    287                         help='learning rate (default: 0.1)')
    288     parser.add_argument('--momentum', type=float, default=0.9, metavar='M',
    289                         help='SGD momentum (default: 0.9)')
    290     parser.add_argument('--log-interval', type=int, default=10, metavar='N',
    291                         help='how many batches to wait before logging training status (default: 10)')
    292     parser.add_argument('--no-train', action='store_true', default=False,
    293                         help='If train the Model')
    294     parser.add_argument('--save-model', action='store_true', default=False,
    295                         help='For Saving the current Model')
    296     args = parser.parse_args()
    297 
    298     # 图像数值转换,ToTensor源码注释
    299     """Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor.
    300         Converts a PIL Image or numpy.ndarray (H x W x C) in the range
    301         [0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0].
    302         """
    303     # 归一化把[0.0, 1.0]变换为[-1,1], ([0, 1] - 0.5) / 0.5 = [-1, 1]
    304     transform = tv.transforms.Compose([
    305         transforms.ToTensor(),
    306         transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])
    307 
    308     # 定义数据集
    309     train_data = tv.datasets.CIFAR10(root=ROOT, train=True, download=True, transform=transform)
    310     test_data = tv.datasets.CIFAR10(root=ROOT, train=False, download=False, transform=transform)
    311 
    312     train_load = t.utils.data.DataLoader(train_data, batch_size=args.batch_size, shuffle=True, num_workers=WORKERS)
    313     test_load = t.utils.data.DataLoader(test_data, batch_size=args.test_batch_size, shuffle=False, num_workers=WORKERS)
    314 
    315     net = ResNet34(ResBlock).cuda()
    316     print(net)
    317 
    318     # 并行计算提高运行速度
    319     net = nn.DataParallel(net)
    320     cudnn.benchmark = True
    321 
    322     # 如果不训练,直接加载保存的网络参数进行测试集验证
    323     if args.no_train:
    324         net.load_state_dict(t.load(PARAS_FN))
    325         net_test(net, test_load, 0)
    326         return
    327 
    328     optimizer = optim.SGD(net.parameters(), lr=args.lr, momentum=args.momentum)
    329 
    330     start_time = datetime.datetime.now()
    331 
    332     for epoch in range(1, args.epochs + 1):
    333         net_train(net, train_load, optimizer, epoch, args.log_interval)
    334 
    335         # 每个epoch结束后用测试集检查识别准确度
    336         net_test(net, test_load, epoch)
    337 
    338     end_time = datetime.datetime.now()
    339 
    340     global best_acc
    341     print('CIFAR10 pytorch ResNet34 Train: EPOCH:{}, BATCH_SZ:{}, LR:{}, ACC:{}'.format(args.epochs, args.batch_size, args.lr, best_acc))
    342     print('train spend time: ', end_time - start_time)
    343 
    344     # 每训练一个迭代记录的训练准确率个数
    345     ratio = len(train_data) / args.batch_size / args.log_interval
    346     ratio = int(ratio)
    347 
    348     # 显示曲线
    349     show_acc_curv(ratio)
    350 
    351     if args.save_model:
    352         t.save(net.state_dict(), PARAS_FN)
    353 
    354 
    355 if __name__ == '__main__':
    356     main()

    运行结果:

    Files already downloaded and verified
    ResNet34(
      (first): Sequential(
        (0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3))
        (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): ReLU(inplace)
        (3): MaxPool2d(kernel_size=3, stride=1, padding=1, dilation=1, ceil_mode=False)
      )
      (layer1): Sequential(
        (0): ResBlock(
          (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
        (1): ResBlock(
          (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
        (2): ResBlock(
          (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
      (layer2): Sequential(
        (0): ResBlock(
          (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))
          (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (downsample): Sequential(
            (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2))
            (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
        (1): ResBlock(
          (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
        (2): ResBlock(
          (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
        (3): ResBlock(
          (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
      (layer3): Sequential(
        (0): ResBlock(
          (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))
          (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (downsample): Sequential(
            (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2))
            (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
        (1): ResBlock(
          (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
        (2): ResBlock(
          (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
        (3): ResBlock(
          (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
        (4): ResBlock(
          (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
        (5): ResBlock(
          (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
      (layer4): Sequential(
        (0): ResBlock(
          (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))
          (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (downsample): Sequential(
            (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2))
            (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          )
        )
        (1): ResBlock(
          (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
        (2): ResBlock(
          (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
          (relu): ReLU(inplace)
          (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
          (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
      (avg_pool): AvgPool2d(kernel_size=2, stride=2, padding=0)
      (fc): Linear(in_features=512, out_features=10, bias=True)
    )
    one epoch spend:  0:00:23.971338
    EPOCH:1, ACC:48.54

    one epoch spend:  0:00:22.339190
    EPOCH:2, ACC:61.06

    ......

    one epoch spend:  0:00:22.023034
    EPOCH:199, ACC:79.84

    one epoch spend:  0:00:22.057692
    EPOCH:200, ACC:79.6

    CIFAR10 pytorch ResNet34 Train: EPOCH:200, BATCH_SZ:128, LR:0.1, ACC:80.19
    train spend time:  1:18:40.948080

    运行200个迭代,每个迭代耗时22秒,准确率不高,只有80%。准确率变化曲线如下:

  • 相关阅读:
    【luogu P1307 数字反转】 题解
    【luogu P1111 公路修建】 题解
    字符串与正则运算
    Java 正则表达式的总结和一些小例子
    js -history.back(-1)和history.go(-1) 区别
    js
    html _ 提取html片段内的纯文本
    vue-x action 的相互调用
    java通过过滤器 设置跨域允许
    git-搭建企业git服务器
  • 原文地址:https://www.cnblogs.com/zhengbiqing/p/10432169.html
Copyright © 2011-2022 走看看