{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":7327,"databundleVersionId":861871,"sourceType":"competition"}],"dockerImageVersionId":30734,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"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","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-06-24T11:31:55.407364Z","iopub.execute_input":"2024-06-24T11:31:55.408190Z","iopub.status.idle":"2024-06-24T11:32:19.729330Z","shell.execute_reply.started":"2024-06-24T11:31:55.408157Z","shell.execute_reply":"2024-06-24T11:32:19.728420Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pip install d2l","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:32:19.731046Z","iopub.execute_input":"2024-06-24T11:32:19.731623Z","iopub.status.idle":"2024-06-24T11:33:09.299464Z","shell.execute_reply.started":"2024-06-24T11:32:19.731587Z","shell.execute_reply":"2024-06-24T11:33:09.298403Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab pytorch\nfrom d2l import torch as d2l\nimport torch\nimport torchvision\nfrom torch import nn\nimport os","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:33:09.301353Z","iopub.execute_input":"2024-06-24T11:33:09.301709Z","iopub.status.idle":"2024-06-24T11:33:14.150158Z","shell.execute_reply.started":"2024-06-24T11:33:09.301669Z","shell.execute_reply":"2024-06-24T11:33:14.148969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab all\n#@save \nd2l.DATA_HUB['dog_tiny'] = (d2l.DATA_URL + 'kaggle_dog_tiny.zip',\n                            '0cb91d09b814ecdc07b50f31f8dcad3e81d6a86d')\n\n# 如果使用Kaggle比赛的完整数据集，请将下面的变量更改为False\ndemo = True\nif demo:\n    data_dir = d2l.download_extract('dog_tiny')\nelse:\n    data_dir = os.path.join('..', 'data', 'dog-breed-identification')","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:33:14.152578Z","iopub.execute_input":"2024-06-24T11:33:14.153221Z","iopub.status.idle":"2024-06-24T11:33:15.127512Z","shell.execute_reply.started":"2024-06-24T11:33:14.153190Z","shell.execute_reply":"2024-06-24T11:33:15.126642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab all\ndef reorg_dog_data(data_dir, valid_ratio):\n    labels = d2l.read_csv_labels(os.path.join(data_dir, 'labels.csv'))\n    d2l.reorg_train_valid(data_dir, labels, valid_ratio)\n    d2l.reorg_test(data_dir)\n\n\nbatch_size = 32 if demo else 128\nvalid_ratio = 0.1\nreorg_dog_data(data_dir, valid_ratio)","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:33:15.128584Z","iopub.execute_input":"2024-06-24T11:33:15.128897Z","iopub.status.idle":"2024-06-24T11:33:15.482562Z","shell.execute_reply.started":"2024-06-24T11:33:15.128862Z","shell.execute_reply":"2024-06-24T11:33:15.481566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab pytorch\ntransform_train = torchvision.transforms.Compose([\n    # 随机裁剪图像，所得图像为原始面积的0.08～1之间，高宽比在3/4和4/3之间。\n    # 然后，缩放图像以创建224x224的新图像\n    torchvision.transforms.RandomResizedCrop(224, scale=(0.08, 1.0),\n                                             ratio=(3.0/4.0, 4.0/3.0)),\n    torchvision.transforms.RandomHorizontalFlip(),\n    # 随机更改亮度，对比度和饱和度\n    torchvision.transforms.ColorJitter(brightness=0.4,\n                                       contrast=0.4,\n                                       saturation=0.4),\n    # 添加随机噪声\n    torchvision.transforms.ToTensor(),\n    # 标准化图像的每个通道\n    torchvision.transforms.Normalize([0.485, 0.456, 0.406],\n                                     [0.229, 0.224, 0.225])])","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:33:15.483860Z","iopub.execute_input":"2024-06-24T11:33:15.484155Z","iopub.status.idle":"2024-06-24T11:33:15.491600Z","shell.execute_reply.started":"2024-06-24T11:33:15.484129Z","shell.execute_reply":"2024-06-24T11:33:15.490508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab pytorch\ntransform_test = torchvision.transforms.Compose([\n    torchvision.transforms.Resize(256),\n    # 从图像中心裁切224x224大小的图片\n    torchvision.transforms.CenterCrop(224),\n    torchvision.transforms.ToTensor(),\n    torchvision.transforms.Normalize([0.485, 0.456, 0.406],\n                                     [0.229, 0.224, 0.225])])","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:33:15.494946Z","iopub.execute_input":"2024-06-24T11:33:15.495208Z","iopub.status.idle":"2024-06-24T11:33:15.515039Z","shell.execute_reply.started":"2024-06-24T11:33:15.495185Z","shell.execute_reply":"2024-06-24T11:33:15.514154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab pytorch\ntrain_ds, train_valid_ds = [torchvision.datasets.ImageFolder(\n    os.path.join(data_dir, 'train_valid_test', folder),\n    transform=transform_train) for folder in ['train', 'train_valid']]\n\nvalid_ds, test_ds = [torchvision.datasets.ImageFolder(\n    os.path.join(data_dir, 'train_valid_test', folder),\n    transform=transform_test) for folder in ['valid', 'test']]","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:33:15.516149Z","iopub.execute_input":"2024-06-24T11:33:15.516479Z","iopub.status.idle":"2024-06-24T11:33:15.546829Z","shell.execute_reply.started":"2024-06-24T11:33:15.516446Z","shell.execute_reply":"2024-06-24T11:33:15.546151Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab pytorch\ntrain_iter, train_valid_iter = [torch.utils.data.DataLoader(\n    dataset, batch_size, shuffle=True, drop_last=True)\n    for dataset in (train_ds, train_valid_ds)]\n\nvalid_iter = torch.utils.data.DataLoader(valid_ds, batch_size, shuffle=False,\n                                         drop_last=True)\n\ntest_iter = torch.utils.data.DataLoader(test_ds, batch_size, shuffle=False,\n                                        drop_last=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:33:15.547832Z","iopub.execute_input":"2024-06-24T11:33:15.548145Z","iopub.status.idle":"2024-06-24T11:33:15.554627Z","shell.execute_reply.started":"2024-06-24T11:33:15.548114Z","shell.execute_reply":"2024-06-24T11:33:15.553286Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab pytorch\ndef get_net(devices):\n    finetune_net = nn.Sequential()\n    finetune_net.features = torchvision.models.resnet34(pretrained=True)\n    # 定义一个新的输出网络，共有120个输出类别\n    finetune_net.output_new = nn.Sequential(nn.Linear(1000, 256),\n                                            nn.ReLU(),\n                                            nn.Linear(256, 120))\n    # 将模型参数分配给用于计算的CPU或GPU\n    finetune_net = finetune_net.to(devices[0])\n    # 冻结参数\n    for param in finetune_net.features.parameters():\n        param.requires_grad = False\n    return finetune_net","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:33:15.557674Z","iopub.execute_input":"2024-06-24T11:33:15.558460Z","iopub.status.idle":"2024-06-24T11:33:15.569768Z","shell.execute_reply.started":"2024-06-24T11:33:15.558435Z","shell.execute_reply":"2024-06-24T11:33:15.568892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab pytorch\ndef get_net(devices):\n    finetune_net = nn.Sequential()\n    finetune_net.features = torchvision.models.resnet101(pretrained=True)\n    # 定义一个新的输出网络，共有120个输出类别\n    finetune_net.output_new = nn.Sequential(nn.Linear(1000, 256),\n                                            nn.ReLU(),\n                                            nn.Linear(256, 120))\n    # 将模型参数分配给用于计算的CPU或GPU\n    finetune_net = finetune_net.to(devices[0])\n    # 冻结参数\n    for param in finetune_net.features.parameters():\n        param.requires_grad = False\n    return finetune_net","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:44:42.750444Z","iopub.execute_input":"2024-06-24T11:44:42.750816Z","iopub.status.idle":"2024-06-24T11:44:42.757340Z","shell.execute_reply.started":"2024-06-24T11:44:42.750786Z","shell.execute_reply":"2024-06-24T11:44:42.756344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab pytorch\nloss = nn.CrossEntropyLoss(reduction='none')\n\ndef evaluate_loss(data_iter, net, devices):\n    l_sum, n = 0.0, 0\n    for features, labels in data_iter:\n        features, labels = features.to(devices[0]), labels.to(devices[0])\n        outputs = net(features)\n        l = loss(outputs, labels)\n        l_sum += l.sum()\n        n += labels.numel()\n    return (l_sum / n).to('cpu')","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:44:42.758873Z","iopub.execute_input":"2024-06-24T11:44:42.759212Z","iopub.status.idle":"2024-06-24T11:44:42.772892Z","shell.execute_reply.started":"2024-06-24T11:44:42.759185Z","shell.execute_reply":"2024-06-24T11:44:42.772031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab pytorch\ndef train(net, train_iter, valid_iter, num_epochs, lr, wd, devices, lr_period,\n          lr_decay):\n    # 只训练小型自定义输出网络\n    net = nn.DataParallel(net, device_ids=devices).to(devices[0])\n    trainer = torch.optim.SGD((param for param in net.parameters()\n                               if param.requires_grad), lr=lr,\n                              momentum=0.9, weight_decay=wd)\n    scheduler = torch.optim.lr_scheduler.StepLR(trainer, lr_period, lr_decay)\n    num_batches, timer = len(train_iter), d2l.Timer()\n    legend = ['train loss']\n    if valid_iter is not None:\n        legend.append('valid loss')\n    animator = d2l.Animator(xlabel='epoch', xlim=[1, num_epochs],\n                            legend=legend)\n    for epoch in range(num_epochs):\n        metric = d2l.Accumulator(2)\n        for i, (features, labels) in enumerate(train_iter):\n            timer.start()\n            features, labels = features.to(devices[0]), labels.to(devices[0])\n            trainer.zero_grad()\n            output = net(features)\n            l = loss(output, labels).sum()\n            l.backward()\n            trainer.step()\n            metric.add(l, labels.shape[0])\n            timer.stop()\n            if (i + 1) % (num_batches // 5) == 0 or i == num_batches - 1:\n                animator.add(epoch + (i + 1) / num_batches, \n                             (metric[0] / metric[1], None))\n        measures = f'train loss {metric[0] / metric[1]:.3f}'\n        if valid_iter is not None:\n            valid_loss = evaluate_loss(valid_iter, net, devices)\n            animator.add(epoch + 1, (None, valid_loss.detach().cpu()))\n        scheduler.step()\n    if valid_iter is not None:\n        measures += f', valid loss {valid_loss:.3f}'\n    print(measures + f'\\n{metric[1] * num_epochs / timer.sum():.1f}'\n          f' examples/sec on {str(devices)}')","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:44:42.773963Z","iopub.execute_input":"2024-06-24T11:44:42.774256Z","iopub.status.idle":"2024-06-24T11:44:42.787124Z","shell.execute_reply.started":"2024-06-24T11:44:42.774222Z","shell.execute_reply":"2024-06-24T11:44:42.786283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab pytorch\ndevices, num_epochs, lr, wd = d2l.try_all_gpus(), 10, 1e-4, 1e-4\nlr_period, lr_decay, net = 2, 0.9, get_net(devices)\ntrain(net, train_iter, valid_iter, num_epochs, lr, wd, devices, lr_period,\n      lr_decay)","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:44:42.794003Z","iopub.execute_input":"2024-06-24T11:44:42.794259Z","iopub.status.idle":"2024-06-24T11:46:20.949716Z","shell.execute_reply.started":"2024-06-24T11:44:42.794237Z","shell.execute_reply":"2024-06-24T11:46:20.948374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#@tab pytorch\nnet = get_net(devices)\ntrain(net, train_valid_iter, None, num_epochs, lr, wd, devices, lr_period,\n      lr_decay)\n\npreds = []\nfor data, label in test_iter:\n    output = torch.nn.functional.softmax(net(data.to(devices[0])), dim=1)\n    preds.extend(output.cpu().detach().numpy())\nids = sorted(os.listdir(\n    os.path.join(data_dir, 'train_valid_test', 'test', 'unknown')))\nwith open('submission.csv', 'w') as f:\n    f.write('id,' + ','.join(train_valid_ds.classes) + '\\n')\n    for i, output in zip(ids, preds):\n        f.write(i.split('.')[0] + ',' + ','.join(\n            [str(num) for num in output]) + '\\n')","metadata":{"execution":{"iopub.status.busy":"2024-06-24T11:46:20.952136Z","iopub.execute_input":"2024-06-24T11:46:20.953244Z","iopub.status.idle":"2024-06-24T11:47:59.802160Z","shell.execute_reply.started":"2024-06-24T11:46:20.953177Z","shell.execute_reply":"2024-06-24T11:47:59.800833Z"},"trusted":true},"execution_count":null,"outputs":[]}]}