{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"from torch import  nn\nimport torch as t\nfrom torch.nn import  functional as F\nimport torchvision as tv\nimport torch.optim as optim\nimport torchvision.transforms as transforms\nfrom torchvision.transforms import ToPILImage\nimport torch.backends.cudnn as cudnn\n\nimport matplotlib.pyplot as plt\n\nimport datetime","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def Conv1(in_planes, places, stride=2):\n    return nn.Sequential(\n        nn.Conv2d(in_channels=in_planes,out_channels=places,kernel_size=7,stride=stride,padding=3, bias=False),\n        nn.BatchNorm2d(places),\n        nn.ReLU(inplace=True),\n        nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n    )\n\nclass Bottleneck(nn.Module):\n    def __init__(self,in_places,places, stride=1,downsampling=False, expansion = 4):\n        super(Bottleneck,self).__init__()\n        self.expansion = expansion\n        self.downsampling = downsampling\n\n        self.bottleneck = nn.Sequential(\n            nn.Conv2d(in_channels=in_places,out_channels=places,kernel_size=1,stride=1, bias=False),\n            nn.BatchNorm2d(places),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(in_channels=places, out_channels=places, kernel_size=3, stride=stride, padding=1, bias=False),\n            nn.BatchNorm2d(places),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(in_channels=places, out_channels=places*self.expansion, kernel_size=1, stride=1, bias=False),\n            nn.BatchNorm2d(places*self.expansion),\n        )\n\n        if self.downsampling:\n            self.downsample = nn.Sequential(\n                nn.Conv2d(in_channels=in_places, out_channels=places*self.expansion, kernel_size=1, stride=stride, bias=False),\n                nn.BatchNorm2d(places*self.expansion)\n            )\n        self.relu = nn.ReLU(inplace=True)\n    def forward(self, x):\n        residual = x\n        out = self.bottleneck(x)\n\n        if self.downsampling:\n            residual = self.downsample(x)\n\n        out += residual\n        out = self.relu(out)\n        return out\n\nclass ResNet(nn.Module):\n    def __init__(self,blocks, num_classes=1000, expansion = 4):\n        super(ResNet,self).__init__()\n        self.expansion = expansion\n\n        self.conv1 = Conv1(in_planes = 3, places= 64)\n\n        self.layer1 = self.make_layer(in_places = 64, places= 64, block=blocks[0], stride=1)\n        self.layer2 = self.make_layer(in_places = 256,places=128, block=blocks[1], stride=2)\n        self.layer3 = self.make_layer(in_places=512,places=256, block=blocks[2], stride=2)\n        self.layer4 = self.make_layer(in_places=1024,places=512, block=blocks[3], stride=2)\n\n        self.avgpool = nn.AvgPool2d(7, stride=1)\n        self.fc = nn.Linear(2048,num_classes)\n\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')\n            elif isinstance(m, nn.BatchNorm2d):\n                nn.init.constant_(m.weight, 1)\n                nn.init.constant_(m.bias, 0)\n\n    def make_layer(self, in_places, places, block, stride):\n        layers = []\n        layers.append(Bottleneck(in_places, places,stride, downsampling =True))\n        for i in range(1, block):\n            layers.append(Bottleneck(places*self.expansion, places))\n\n        return nn.Sequential(*layers)\n\n\n    def forward(self, x):\n        x = self.conv1(x)\n\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n\n        x = self.avgpool(x)\n        x = x.view(x.size(0), -1)\n        x = self.fc(x)\n        return x\n\ndef ResNet50():\n    return ResNet([3, 4, 6, 3])\n\ndef ResNet101():\n    return ResNet([3, 4, 23, 3])\n\ndef ResNet152():\n    return ResNet([3, 8, 36, 3])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 样本读取线程数\nWORKERS = 4\n\n# 网络参赛保存文件名\nPARAS_FN = 'cifar_resnet_params.pkl'\n\n# minist数据存放位置\nROOT = '../input/cifar10-python'\n\n# 目标函数\nloss_func = nn.CrossEntropyLoss()\n\n# 最优结果\nbest_acc = 0\n\n# 记录准确率，显示曲线\nglobal_train_acc = []\nglobal_test_acc = []\n\n'''\n训练并测试网络\nnet：网络模型\ntrain_data_load：训练数据集\noptimizer：优化器\nepoch：第几次训练迭代\nlog_interval：训练过程中损失函数值和准确率的打印频率\n'''\ndef net_train(net, train_data_load, optimizer, epoch, log_interval):\n    net.train()\n\n    begin = datetime.datetime.now()\n\n    # 样本总数\n    total = len(train_data_load.dataset)\n\n    # 样本批次训练的损失函数值的和\n    train_loss = 0\n\n    # 识别正确的样本数\n    ok = 0\n\n    for i, data in enumerate(train_data_load, 0):\n        img, label = data\n        img, label = img.cuda(), label.cuda()\n\n        optimizer.zero_grad()\n\n        outs = net(img)\n        loss = loss_func(outs, label)\n        loss.backward()\n        optimizer.step()\n\n        # 累加损失值和训练样本数\n        train_loss += loss.item()\n\n        _, predicted = t.max(outs.data, 1)\n        # 累加识别正确的样本数\n        ok += (predicted == label).sum()\n\n        if (i + 1) % log_interval == 0:\n            # 训练结果输出\n\n            # 已训练的样本数\n            traind_total = (i + 1) * len(label)\n\n            # 准确度\n            acc = 100. * ok / traind_total\n\n            # 记录训练准确率以输出变化曲线\n            global_train_acc.append(acc)\n\n    end = datetime.datetime.now()\n    print('one epoch spend: ', end - begin)\n\n\n'''\n用测试集检查准确率\n'''\ndef net_test(net, test_data_load, epoch):\n    net.eval()\n\n    ok = 0\n\n    for i, data in enumerate(test_data_load):\n        img, label = data\n        img, label = img.cuda(), label.cuda()\n\n        outs = net(img)\n        _, pre = t.max(outs.data, 1)\n        ok += (pre == label).sum()\n\n    acc = ok.item() * 100. / (len(test_data_load.dataset))\n    print('EPOCH:{}, ACC:{}\\n'.format(epoch, acc))\n\n    # 记录测试准确率以输出变化曲线\n    global_test_acc.append(acc)\n\n    # 最好准确度记录\n    global best_acc\n    if acc > best_acc:\n        best_acc = acc\n\n\n'''\n显示数据集中一个图片\n'''\ndef img_show(dataset, index):\n    classes = ('plane', 'car', 'bird', 'cat',\n               'deer', 'dog', 'frog', 'horse', 'ship', 'truck')\n\n    show = ToPILImage()\n\n    data, label = dataset[index]\n    print('img is a ', classes[label])\n    show((data + 1) / 2).resize((100, 100)).show()\n\n\n'''\n显示训练准确率、测试准确率变化曲线\n'''\ndef show_acc_curv(ratio):\n    # 训练准确率曲线的x、y\n    train_x = list(range(len(global_train_acc)))\n    train_y = global_train_acc\n\n    # 测试准确率曲线的x、y\n    # 每ratio个训练准确率对应一个测试准确率\n    test_x = train_x[ratio-1::ratio]\n    test_y = global_test_acc\n\n    plt.title('CIFAR10 RESNET34 ACC')\n\n    plt.plot(train_x, train_y, color='green', label='training accuracy')\n    plt.plot(test_x, test_y, color='red', label='testing accuracy')\n\n    # 显示图例\n    plt.legend()\n    plt.xlabel('iterations')\n    plt.ylabel('accs')\n\n    plt.show()\n\n\nclass Args():\n    batch_size = 256\n    lr = 0.1\n    epochs = 10\n    log_interval = 10\n    no_train = False\n    save_model = True\n    momentum = 0.9\n    \n    \n    \n    \ndef main():\n    # 训练超参数设置，可通过命令行设置\n    '''\n    parser = argparse.ArgumentParser(description='PyTorch CIFA10 ResNet34 Example')\n    parser.add_argument('--batch-size', type=int, default=128, metavar='N',\n                        help='input batch size for training (default: 128)')\n    parser.add_argument('--test-batch-size', type=int, default=100, metavar='N',\n                        help='input batch size for testing (default: 100)')\n    parser.add_argument('--epochs', type=int, default=200, metavar='N',\n                        help='number of epochs to train (default: 200)')\n    parser.add_argument('--lr', type=float, default=0.1, metavar='LR',\n                        help='learning rate (default: 0.1)')\n    parser.add_argument('--momentum', type=float, default=0.9, metavar='M',\n                        help='SGD momentum (default: 0.9)')\n    parser.add_argument('--log-interval', type=int, default=10, metavar='N',\n                        help='how many batches to wait before logging training status (default: 10)')\n    parser.add_argument('--no-train', action='store_true', default=False,\n                        help='If train the Model')\n    parser.add_argument('--save-model', action='store_true', default=False,\n                        help='For Saving the current Model')\n    '''\n    args = Args()\n\n    # 图像数值转换，ToTensor源码注释\n    \"\"\"Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor.\n        Converts a PIL Image or numpy.ndarray (H x W x C) in the range\n        [0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0].\n        \"\"\"\n    # 归一化把[0.0, 1.0]变换为[-1,1], ([0, 1] - 0.5) / 0.5 = [-1, 1]\n    transform = tv.transforms.Compose([\n        transforms.ToTensor(),\n        transforms.RandomResizedCrop(224),\n        transforms.RandomHorizontalFlip(),\n        transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])\n    \n    train_data = tv.datasets.CIFAR10(root=ROOT, train=True, download=True,transform=transform)\n    train_load = t.utils.data.DataLoader(train_data, batch_size=args.batch_size, shuffle=True)\n\n    test_data = tv.datasets.CIFAR10(root=ROOT, train=False, download=False,transform=transform)\n    test_load = t.utils.data.DataLoader(test_data, batch_size=args.batch_size, shuffle=True)\n\n    net = ResNet101().cuda()\n    print(net)\n    \n\n    # 并行计算提高运行速度\n    net = nn.DataParallel(net)\n    cudnn.benchmark = True\n    # net.load_state_dict(t.load(PARAS_FN))\n    \n    # 如果不训练，直接加载保存的网络参数进行测试集验证\n    if args.no_train:\n        net.load_state_dict(t.load(PARAS_FN))\n        net_test(net, test_load, 0)\n        return\n\n    optimizer = optim.SGD(net.parameters(), lr=args.lr, momentum=args.momentum)\n\n    start_time = datetime.datetime.now()\n\n    for epoch in range(1, args.epochs + 1):\n        net_train(net, train_load, optimizer, epoch, args.log_interval)\n\n        # 每个epoch结束后用测试集检查识别准确度\n        net_test(net, test_load, epoch)\n\n    end_time = datetime.datetime.now()\n\n    global best_acc\n    print('CIFAR10 pytorch ResNet101 Train: EPOCH:{}, BATCH_SZ:{}, LR:{}, ACC:{}'.format(args.epochs, args.batch_size, args.lr, best_acc))\n    print('train spend time: ', end_time - start_time)\n\n    # 每训练一个迭代记录的训练准确率个数\n    ratio = len(train_data) / args.batch_size / args.log_interval\n    ratio = int(ratio)\n\n    # 显示曲线\n    show_acc_curv(ratio)\n\n    if args.save_model:\n        t.save(net.state_dict(), PARAS_FN)\n\n\n\nmain()","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}