{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 1.5 「ファインチューニング」で精度向上を実現する方法  \n- 本ファイルでは、学習済みのVGGモデルを使用し、ファインチューニングでアリとハチの画像を分類するモデルを学習します","metadata":{}},{"cell_type":"markdown","source":"# 学習目標  \n1.PyTorchでGPUを使用する実装コードを書けるようになる  \n2.最適化手法の設定において、層ごとに異なる学習率を設定したファインチューニングを実装できるようになる  \n3.学習したネットワークを保存・ロードできるようになる ","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"# パッケージのimport\nimport os\nimport numpy as np\nimport glob\nimport tensorflow as tf\nimport json\nfrom PIL import Image\nimport io\nimport matplotlib.pyplot as plt\n%matplotlib inline\nimport random\n\n\nfrom tqdm import tqdm\n\nimport torch\nimport torchvision\nimport torch.utils.data as data\nimport torch.nn as nn\nimport torch.optim as optim\nimport pandas as pd\nfrom torchvision import models, transforms\nfrom sklearn.model_selection import train_test_split \n","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:55:38.574634Z","iopub.execute_input":"2021-11-25T00:55:38.574891Z","iopub.status.idle":"2021-11-25T00:55:38.587306Z","shell.execute_reply.started":"2021-11-25T00:55:38.574862Z","shell.execute_reply":"2021-11-25T00:55:38.586405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# PyTorchのバージョン確認\nprint(\"PyTorch Version: \",torch.__version__)\nprint(\"Torchvision Version: \",torchvision.__version__)","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:55:38.589006Z","iopub.execute_input":"2021-11-25T00:55:38.589797Z","iopub.status.idle":"2021-11-25T00:55:38.601439Z","shell.execute_reply.started":"2021-11-25T00:55:38.58975Z","shell.execute_reply":"2021-11-25T00:55:38.600606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 乱数のシードを設定\ntorch.manual_seed(1234)\nnp.random.seed(1234)\nrandom.seed(1234)","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:55:38.603168Z","iopub.execute_input":"2021-11-25T00:55:38.603473Z","iopub.status.idle":"2021-11-25T00:55:38.611152Z","shell.execute_reply.started":"2021-11-25T00:55:38.603438Z","shell.execute_reply":"2021-11-25T00:55:38.610441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 入力画像の前処理クラスを作成","metadata":{}},{"cell_type":"code","source":"\nresize = 224\nmean = (0.485, 0.456, 0.406)\nstd = (0.229, 0.224, 0.225)\n\ntrain_transforms = transforms.Compose([\n                transforms.RandomResizedCrop(\n                    resize, scale=(0.5, 1.0)),  # データオーギュメンテーション\n                transforms.RandomHorizontalFlip(),  # データオーギュメンテーション\n                transforms.ToTensor(),  # テンソルに変換\n                transforms.Normalize(mean, std)  # 標準化\n    ])\nval_transforms = transforms.Compose([\n                transforms.Resize(resize),  # リサイズ\n                transforms.CenterCrop(resize),  # 画像中央をresize×resizeで切り取り\n                transforms.ToTensor(),  # テンソルに変換\n                transforms.Normalize(mean, std)  # 標準化\n    ])\ntest_transforms = transforms.Compose([\n                transforms.Resize(resize),  # リサイズ\n                transforms.CenterCrop(resize),  # 画像中央をresize×resizeで切り取り\n                transforms.ToTensor(),  # テンソルに変換\n                transforms.Normalize(mean, std)  # 標準化\n    ])","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:55:38.613282Z","iopub.execute_input":"2021-11-25T00:55:38.61379Z","iopub.status.idle":"2021-11-25T00:55:38.623483Z","shell.execute_reply.started":"2021-11-25T00:55:38.613755Z","shell.execute_reply":"2021-11-25T00:55:38.622673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# テストデータを表示","metadata":{}},{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom tqdm import tqdm\nimport os\nimport pandas as pd\nfrom scipy import stats\nimport numpy as np\nimport glob\nimport tensorflow as tf\n# import timm\nimport random\nimport time\nimport copy\nfrom operator import itemgetter\n\nfrom collections import OrderedDict, namedtuple\nimport joblib\n\nimport logging\nimport sys\n\nimport PIL\nimport cv2\nimport albumentations as A\nimport io\nimport IPython.display as display\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.optim import lr_scheduler\nimport torch.optim as optim\n# import torch_xla\n# import torch_xla.core.xla_model as xm\n# import torch_xla.debug.metrics as met\n# import torch_xla.distributed.parallel_loader as pl\n# import torch_xla.distributed.xla_multiprocessing as xmp\n# import torch_xla.utils.utils as xu\n\nimport torchvision\n# from torchvision import datasets, transforms\nfrom torch.utils.data import Dataset, DataLoader, ConcatDataset\nimport torchvision.transforms as transforms\nfrom torchvision.utils import make_grid\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.model_selection import train_test_split\nfrom sklearn import metrics, model_selection\n\nimport warnings\nwarnings.filterwarnings(\"ignore\");\n\ntrain_files = glob.glob('../input/tpu-getting-started/*224/train/*.tfrec')\nval_files = glob.glob('../input/tpu-getting-started/*224/val/*.tfrec')\ntest_files = glob.glob('../input/tpu-getting-started/*224/test/*.tfrec')","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:55:38.625474Z","iopub.execute_input":"2021-11-25T00:55:38.625804Z","iopub.status.idle":"2021-11-25T00:55:38.661395Z","shell.execute_reply.started":"2021-11-25T00:55:38.625763Z","shell.execute_reply":"2021-11-25T00:55:38.660471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def parse_tfrec_data(files, test=False):\n    if not test: \n        feature_description = {\n            'class': tf.io.FixedLenFeature([], tf.int64),\n            'id': tf.io.FixedLenFeature([], tf.string),\n            'image': tf.io.FixedLenFeature([], tf.string),\n        }\n    else:\n        feature_description = {\n        'id': tf.io.FixedLenFeature([], tf.string),\n        'image': tf.io.FixedLenFeature([], tf.string),\n    }\n    parse_image_f = lambda x: tf.io.parse_single_example(x, feature_description)\n\n    ids = []\n    images = []\n    if not test:\n        cl = []\n\n    for i in tqdm(files):\n        image_dataset = tf.data.TFRecordDataset(i)\n        image_dataset = image_dataset.map(parse_image_f)\n\n        ids_ = [str(id_features['id'].numpy())[2:-1] for id_features in image_dataset] # [2:-1] is done to remove b' from 1st and 'from last in train id names\n        ids = ids + ids_\n\n        images_ = [image_features['image'].numpy() for image_features in image_dataset]\n        images = images + images_\n\n        if not test:\n                cl_ = [int(class_features['class'].numpy()) for class_features in image_dataset]\n                cl = cl + cl_\n    if test:\n        return ids, images\n    else:\n        return ids, cl, images","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:55:38.663471Z","iopub.execute_input":"2021-11-25T00:55:38.663963Z","iopub.status.idle":"2021-11-25T00:55:38.674083Z","shell.execute_reply.started":"2021-11-25T00:55:38.663926Z","shell.execute_reply":"2021-11-25T00:55:38.67334Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gpu_devices = tf.config.experimental.list_physical_devices('GPU')\nfor device in gpu_devices:\n    tf.config.experimental.set_memory_growth(device, True)\n\ntrain_ids, train_cl, train_images = parse_tfrec_data(train_files)\nval_ids, val_cl, val_images = parse_tfrec_data(val_files)\ntest_ids, test_images = parse_tfrec_data(test_files, test=True)","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:55:38.67619Z","iopub.execute_input":"2021-11-25T00:55:38.677679Z","iopub.status.idle":"2021-11-25T00:56:03.404314Z","shell.execute_reply.started":"2021-11-25T00:55:38.677643Z","shell.execute_reply":"2021-11-25T00:56:03.403609Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 画像前処理の動作を確認\n\n# 1. 画像読み込み\n#image_file_path = '../input/tpu-getting-started/tfrecords-jpeg-224x224/test/00-224x224-462.tfrec'\n#img = Image.open(image_file_path)  # [高さ][幅][色RGB]\nprint(train_ids[0])\nprint(train_cl[0])\nimg = Image.open(io.BytesIO(train_images[0]))\nimg\n\n# 2. 元の画像の表示\nplt.imshow(img)\nplt.show()\n\n# 3. 画像の前処理と処理済み画像の表示\nimg_transformed = train_transforms(img)  # torch.Size([3, 224, 224])\n\n# (色、高さ、幅)を (高さ、幅、色)に変換し、0-1に値を制限して表示\nimg_transformed = img_transformed.numpy().transpose((1, 2, 0))\nimg_transformed = np.clip(img_transformed, 0, 1)\nplt.imshow(img_transformed)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:03.40674Z","iopub.execute_input":"2021-11-25T00:56:03.407452Z","iopub.status.idle":"2021-11-25T00:56:04.070564Z","shell.execute_reply.started":"2021-11-25T00:56:03.407418Z","shell.execute_reply":"2021-11-25T00:56:04.06978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataSetを作成","metadata":{}},{"cell_type":"code","source":"class FlowerDataset(data.Dataset):\n    \n    def __init__(self, ids, images, cl, transforms, test=False):\n        \n        self.ids = ids\n        self.images = images\n        if not test:\n            self.cl = cl\n        self.transforms = transforms\n        self.is_test = test\n    \n    def __len__(self):\n        return len(self.ids)\n        \n    def __getitem__(self, idx):\n        \n        img = self.images[idx]\n        img = Image.open(io.BytesIO(img))\n        #img = np.array(img)\n        img = self.transforms(img)\n        \n        if self.is_test:\n            return img, -1, self.ids[idx]\n        return img, int(self.cl[idx]), self.ids[idx]\n\ntrain_dataset = FlowerDataset(train_ids, train_images, train_cl, transforms=train_transforms)\nval_dataset = FlowerDataset(val_ids, val_images, val_cl, transforms=val_transforms)\ntest_dataset = FlowerDataset(test_ids, test_images, None, transforms=test_transforms, test=True)","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:04.072036Z","iopub.execute_input":"2021-11-25T00:56:04.072517Z","iopub.status.idle":"2021-11-25T00:56:04.082938Z","shell.execute_reply.started":"2021-11-25T00:56:04.072474Z","shell.execute_reply":"2021-11-25T00:56:04.082113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataLoaderを作成","metadata":{}},{"cell_type":"code","source":"IMG_SIZE = 224\n\n# DataLoaderを作成する\nbatch_size = 32\n\ntrain_dataloader = torch.utils.data.DataLoader(\n    train_dataset, batch_size=batch_size, shuffle=True)\n\nval_dataloader = torch.utils.data.DataLoader(\n    val_dataset, batch_size=batch_size, shuffle=False)\n\ntest_loader = torch.utils.data.DataLoader(\n    test_dataset, batch_size=batch_size, shuffle=False)\n\n# 辞書オブジェクトにまとめる\ndataloaders_dict = {\"train\": train_dataloader, \"val\": val_dataloader, \"test\": test_loader}","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:04.084362Z","iopub.execute_input":"2021-11-25T00:56:04.084739Z","iopub.status.idle":"2021-11-25T00:56:04.095445Z","shell.execute_reply.started":"2021-11-25T00:56:04.084695Z","shell.execute_reply":"2021-11-25T00:56:04.094537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ネットワークモデルの作成","metadata":{}},{"cell_type":"code","source":"\n!pip install efficientnet_pytorch","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:04.096817Z","iopub.execute_input":"2021-11-25T00:56:04.097165Z","iopub.status.idle":"2021-11-25T00:56:11.749624Z","shell.execute_reply.started":"2021-11-25T00:56:04.097104Z","shell.execute_reply":"2021-11-25T00:56:11.74878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 学習済みのVGG-16モデルをロード\n\n# VGG-16モデルのインスタンスを生成\nuse_pretrained = True  # 学習済みのパラメータを使用\n#use_pretrained = False  # 学習済みのパラメータを使用\n#net = models.vgg16(pretrained=use_pretrained)\n\n\n# VGG16の最後の出力層の出力ユニットを病気4種と健康の5つに付け替える\n#net.classifier[6] = nn.Linear(in_features=4096, out_features=104)\n\n\nfrom efficientnet_pytorch import EfficientNet\n\nnet = EfficientNet.from_pretrained('efficientnet-b4')#Pretrained_modelのインポート\n#事前学習にはImageNetを用いているので、全結合層は1000クラスです。以下のようにクラス数を変更すれば転移学習に利用することができます。\n\nnum_ftrs = net._fc.in_features#全結合層の名前は\"_fc\"となっています\nnet._fc = nn.Linear(num_ftrs, 104)\n\n\n# 訓練モードに設定\nnet.train()\n\nprint('ネットワーク設定完了：学習済みの重みをロードし、訓練モードに設定しました')","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:11.751128Z","iopub.execute_input":"2021-11-25T00:56:11.751425Z","iopub.status.idle":"2021-11-25T00:56:12.866875Z","shell.execute_reply.started":"2021-11-25T00:56:11.751392Z","shell.execute_reply":"2021-11-25T00:56:12.866095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 損失関数を定義\n* 損失関数は、モデルが問題を学習出来ているかの指標”ロス(損失)”の計算方法を指定する","metadata":{}},{"cell_type":"code","source":"# 損失関数の設定\ncriterion = nn.CrossEntropyLoss()","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:12.868004Z","iopub.execute_input":"2021-11-25T00:56:12.868454Z","iopub.status.idle":"2021-11-25T00:56:12.872959Z","shell.execute_reply.started":"2021-11-25T00:56:12.868405Z","shell.execute_reply":"2021-11-25T00:56:12.872154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 最適化手法を設定\n* OptimizerがVGGモデルのどこのパラメータを更新(＝学習・最適化)するかを指定する\n* Optimizerは”誤差逆伝搬法”を用いて、損失関数を最小化するようにVGGモデルのパラメータを更新(＝学習・最適化)役割を担う","metadata":{}},{"cell_type":"code","source":"# ファインチューニングで学習させるパラメータを、変数params_to_updateの1～3に格納する\n#\n#params_to_update_1 = []\n#params_to_update_2 = []\n#params_to_update_3 = []\n\n# 学習させる層のパラメータ名を指定\n#update_param_names_1 = [\"features\"]\n#update_param_names_2 = [\"classifier.0.weight\",\n#                        \"classifier.0.bias\", \"classifier.3.weight\", \"classifier.3.bias\"]\n#update_param_names_3 = [\"classifier.6.weight\", \"classifier.6.bias\"]\n\n# パラメータごとに各リストに格納する\n#for name, param in net.named_parameters():\n#    if update_param_names_1[0] in name:\n#        param.requires_grad = True\n#        params_to_update_1.append(param)\n#        print(\"params_to_update_1に格納：\", name)\n#\n#    elif name in update_param_names_2:\n#        param.requires_grad = True\n#        params_to_update_2.append(param)\n#        print(\"params_to_update_2に格納：\", name)\n#\n#    elif name in update_param_names_3:\n#        param.requires_grad = True\n#        params_to_update_3.append(param)\n#        print(\"params_to_update_3に格納：\", name)\n#\n#    else:\n#        param.requires_grad = False\n#        print(\"勾配計算なし。学習しない：\", name)","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:12.874161Z","iopub.execute_input":"2021-11-25T00:56:12.875687Z","iopub.status.idle":"2021-11-25T00:56:13.083113Z","shell.execute_reply.started":"2021-11-25T00:56:12.875644Z","shell.execute_reply":"2021-11-25T00:56:13.07701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 最適化手法の設定\n#optimizer = optim.SGD([\n#    {'params': params_to_update_1, 'lr': 1e-4},\n#    {'params': params_to_update_2, 'lr': 5e-4},\n#    {'params': params_to_update_3, 'lr': 1e-3}\n#], momentum=0.9)\noptimizer = optim.Adam(net.parameters())","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:13.084347Z","iopub.execute_input":"2021-11-25T00:56:13.084622Z","iopub.status.idle":"2021-11-25T00:56:13.093553Z","shell.execute_reply.started":"2021-11-25T00:56:13.084585Z","shell.execute_reply":"2021-11-25T00:56:13.092815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 学習・検証を実施","metadata":{}},{"cell_type":"code","source":"# モデルを学習させる関数を作成\n\n\ndef train_model(net, dataloaders_dict, criterion, optimizer, num_epochs):\n\n    # 初期設定\n    # GPUが使えるかを確認\n    device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n    print(\"使用デバイス：\", device)\n\n    # ネットワークをGPUへ\n    net.to(device)\n\n    # ネットワークがある程度固定であれば、高速化させる\n    torch.backends.cudnn.benchmark = True\n\n    # epochのループ\n    for epoch in range(num_epochs):\n        print('Epoch {}/{}'.format(epoch+1, num_epochs))\n        print('-------------')\n\n        # epochごとの訓練と検証のループ\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                net.train()  # モデルを訓練モードに\n            else:\n                net.eval()   # モデルを検証モードに\n\n            epoch_loss = 0.0  # epochの損失和\n            epoch_corrects = 0  # epochの正解数\n\n            # 未学習時の検証性能を確かめるため、epoch=0の訓練は省略\n            #if (epoch == 0) and (phase == 'train'):\n            #    continue\n\n            # データローダーからミニバッチを取り出すループ\n            for inputs, labels, _ in tqdm(dataloaders_dict[phase]):\n\n                # GPUが使えるならGPUにデータを送る\n                inputs = inputs.to(device)\n                labels = labels.to(device)\n                                \n                # optimizerを初期化\n                optimizer.zero_grad()\n\n                # 順伝搬（forward）計算\n                with torch.set_grad_enabled(phase == 'train'):\n                    outputs = net(inputs)\n                    loss = criterion(outputs, labels)  # 損失を計算\n                    _, preds = torch.max(outputs, 1)  # ラベルを予測\n\n                    # 訓練時はバックプロパゲーション\n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n\n                    # 結果の計算\n                    epoch_loss += loss.item() * inputs.size(0)  # lossの合計を更新\n                    # 正解数の合計を更新\n                    epoch_corrects += torch.sum(preds == labels.data)\n\n            # epochごとのlossと正解率を表示\n            epoch_loss = epoch_loss / len(dataloaders_dict[phase].dataset)\n            epoch_acc = epoch_corrects.double(\n            ) / len(dataloaders_dict[phase].dataset)\n\n            print('{} Loss: {:.4f} Acc: {:.4f}'.format(\n                phase, epoch_loss, epoch_acc))\n            ","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:13.096677Z","iopub.execute_input":"2021-11-25T00:56:13.096932Z","iopub.status.idle":"2021-11-25T00:56:13.112498Z","shell.execute_reply.started":"2021-11-25T00:56:13.096904Z","shell.execute_reply":"2021-11-25T00:56:13.111516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 学習・検証を実行する\nnum_epochs=50\ntrain_model(net, dataloaders_dict, criterion, optimizer, num_epochs=num_epochs)","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:13.114072Z","iopub.execute_input":"2021-11-25T00:56:13.114502Z","iopub.status.idle":"2021-11-25T00:56:49.543262Z","shell.execute_reply.started":"2021-11-25T00:56:13.114333Z","shell.execute_reply":"2021-11-25T00:56:49.542397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 学習したネットワークを保存・ロード","metadata":{}},{"cell_type":"code","source":"# PyTorchのネットワークパラメータの保存\nsave_path = './weights_fine_tuning.pth'\ntorch.save(net.state_dict(), save_path)","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:49.54431Z","iopub.status.idle":"2021-11-25T00:56:49.545148Z","shell.execute_reply.started":"2021-11-25T00:56:49.544876Z","shell.execute_reply":"2021-11-25T00:56:49.544902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#結果投稿用のCSV作成関数\ndef make_submission(model, test_loader, cuda=True):\n\n    results=[]\n    for batch, _, ids in tqdm(test_loader):\n        with torch.no_grad():\n            if cuda:\n                batch = batch.cuda()\n            model.eval()\n            out = model(batch)\n            pred_labels = torch.argmax(out.data.cpu(), dim=1)\n            rows = list(\n                zip(\n                    list(ids), list(pred_labels.numpy().tolist())\n                )\n            )\n            results.append(pd.DataFrame(rows, columns=['id', 'label']))\n    result_df = pd.concat(results)\n    result_df['label'] = result_df['label'].astype(int)\n    return result_df\n","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:49.546613Z","iopub.status.idle":"2021-11-25T00:56:49.547032Z","shell.execute_reply.started":"2021-11-25T00:56:49.546809Z","shell.execute_reply":"2021-11-25T00:56:49.546832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# PyTorchのネットワークパラメータのロード\nload_path = './weights_fine_tuning.pth'\nload_weights = torch.load(load_path)\nnet.load_state_dict(load_weights)\n\n# GPU上で保存された重みをCPU上でロードする場合\n#load_weights = torch.load(load_path, map_location={'cuda:0': 'cpu'})\n#net.load_state_dict(load_weights)\n\nsubmission = make_submission(net, test_loader)\nsubmission.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2021-11-25T00:56:49.548193Z","iopub.status.idle":"2021-11-25T00:56:49.549253Z","shell.execute_reply.started":"2021-11-25T00:56:49.549018Z","shell.execute_reply":"2021-11-25T00:56:49.549043Z"},"trusted":true},"execution_count":null,"outputs":[]}]}