{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import collections\nimport math\nimport mxnet\nfrom mxnet import autograd, gluon, init, nd\nfrom mxnet.gluon import data as gdata, loss as gloss, model_zoo, nn\nimport os\nimport time","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"data_dir = '../input/'\nlabel_file, train_dir, test_dir = 'labels.csv', 'train', 'test'\nbatch_size, valid_ratio = 128, 0.1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"transform_train = gdata.vision.transforms.Compose([\n    # 随机对图像裁剪出面积为原图像面积0.08~1倍、且高和宽之比在3/4~4/3的图像，再放缩为高和\n    # 宽均为224像素的新图像\n    gdata.vision.transforms.RandomResizedCrop(224, scale=(0.08, 1.0),\n                                              ratio=(3.0/4.0, 4.0/3.0)),\n    gdata.vision.transforms.RandomFlipLeftRight(),\n    # 随机变化亮度、对比度和饱和度\n    gdata.vision.transforms.RandomColorJitter(brightness=0.4, contrast=0.4,\n                                              saturation=0.4),\n    # 随机加噪声\n    gdata.vision.transforms.RandomLighting(0.1),\n    gdata.vision.transforms.ToTensor(),\n    # 对图像的每个通道做标准化\n    gdata.vision.transforms.Normalize([0.485, 0.456, 0.406],\n                                      [0.229, 0.224, 0.225])])\n\ntransform_test = gdata.vision.transforms.Compose([\n    gdata.vision.transforms.Resize(256),\n    # 将图像中央的高和宽均为224的正方形区域裁剪出来\n    gdata.vision.transforms.CenterCrop(224),\n    gdata.vision.transforms.ToTensor(),\n    gdata.vision.transforms.Normalize([0.485, 0.456, 0.406],\n                                      [0.229, 0.224, 0.225])])\n\n\ntrain_valid_ds = gdata.vision.ImageFolderDataset(\n    os.path.join(data_dir, train_dir), flag=1)\ntest_ds = gdata.vision.ImageFolderDataset(\n    os.path.join(data_dir, test_dir), flag=1)\n\n\ntrain_valid_iter = gdata.DataLoader(train_valid_ds.transform_first(\n    transform_train), batch_size, shuffle=True, last_batch='keep')\ntest_iter = gdata.DataLoader(test_ds.transform_first(transform_test),\n                             batch_size, shuffle=False, last_batch='keep')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loss = gloss.SoftmaxCrossEntropyLoss()\n\ndef get_net(ctx):\n    finetune_net = model_zoo.vision.resnet34_v2(pretrained=True)\n    # 定义新的输出网络\n    finetune_net.output_new = nn.HybridSequential(prefix='')\n    finetune_net.output_new.add(nn.Dense(256, activation='relu'))\n    # 120是输出的类别个数\n    finetune_net.output_new.add(nn.Dense(120))\n    # 初始化输出网络\n    finetune_net.output_new.initialize(init.Xavier(), ctx=ctx)\n    # 把模型参数分配到内存或显存上\n    finetune_net.collect_params().reset_ctx(ctx)\n    return finetune_net\n\n\ndef evaluate_loss(data_iter, net, ctx):\n    l_sum, n = 0.0, 0\n    for X, y in data_iter:\n        y = y.as_in_context(ctx)\n        output_features = net.features(X.as_in_context(ctx))\n        outputs = net.output_new(output_features)\n        l_sum += loss(outputs, y).sum().asscalar()\n        n += y.size\n    return l_sum / n\n\ndef train(net, train_iter, valid_iter, num_epochs, lr, wd, ctx, lr_period,\n          lr_decay):\n    # 只训练自定义的小规模输出网络\n    trainer = gluon.Trainer(net.output_new.collect_params(), 'sgd',\n                            {'learning_rate': lr, 'momentum': 0.9, 'wd': wd})\n    for epoch in range(num_epochs):\n        train_l_sum, n, start = 0.0, 0, time.time()\n        if epoch > 0 and epoch % lr_period == 0:\n            trainer.set_learning_rate(trainer.learning_rate * lr_decay)\n        for X, y in train_iter:\n            y = y.as_in_context(ctx)\n            output_features = net.features(X.as_in_context(ctx))\n            with autograd.record():\n                outputs = net.output_new(output_features)\n                l = loss(outputs, y).sum()\n            l.backward()\n            trainer.step(batch_size)\n            train_l_sum += l.asscalar()\n            n += y.size\n        time_s = \"time %.2f sec\" % (time.time() - start)\n        if valid_iter is not None:\n            valid_loss = evaluate_loss(valid_iter, net, ctx)\n            epoch_s = (\"epoch %d, train loss %f, valid loss %f, \"\n                       % (epoch + 1, train_l_sum / n, valid_loss))\n        else:\n            epoch_s = (\"epoch %d, train loss %f, \"\n                       % (epoch + 1, train_l_sum / n))\n        print(epoch_s + time_s + ', lr ' + str(trainer.learning_rate))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def try_gpu():\n    \"\"\"If GPU is available, return mx.gpu(0); else return mx.cpu().\"\"\"\n    try:\n        ctx = mxnet.gpu()\n        _ = nd.array([0], ctx=ctx)\n    except mxnet.base.MXNetError:\n        ctx = mxnet.cpu()\n    return ctx\n\nctx, num_epochs, lr, wd = try_gpu(), 5, 0.01, 1e-4\nlr_period, lr_decay, net = 10, 0.1, get_net(ctx)\n\nnet.hybridize()\ntrain(net, train_valid_iter, None, num_epochs, lr, wd, ctx, lr_period, lr_decay)\n\npreds = []\nfor data, label in test_iter:\n    output_features = net.features(data.as_in_context(ctx))\n    output = nd.softmax(net.output_new(output_features))\n    preds.extend(output.asnumpy())\n\n\nids = sorted(os.listdir(os.path.join(data_dir, test_dir)))\nwith open('submission1.csv', 'w') as f:\n    f.write('id,' + ','.join(train_valid_ds.synsets) + '\\n')\n    for i, output in zip(ids, preds):\n        f.write(i.split('.')[0] + ',' + ','.join(\n            [str(num) for num in output]) + '\\n')","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}