{"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":"# State farm distracted driver detection","metadata":{}},{"cell_type":"code","source":"#Importing modules to use\nimport os.path as osp\nfrom glob import glob\nimport random\nimport time\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport plotly.express as px\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import accuracy_score\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.utils.data as data\nimport torch.optim as optim\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-03-11T18:23:53.683131Z","iopub.execute_input":"2023-03-11T18:23:53.683964Z","iopub.status.idle":"2023-03-11T18:23:53.690075Z","shell.execute_reply.started":"2023-03-11T18:23:53.683912Z","shell.execute_reply":"2023-03-11T18:23:53.688981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def fix_seed(seed):\n    # random\n    random.seed(seed)\n    # Numpy\n    np.random.seed(seed)\n    # Pytorch\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    torch.backends.cudnn.deterministic = True","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:53.692421Z","iopub.execute_input":"2023-03-11T18:23:53.692680Z","iopub.status.idle":"2023-03-11T18:23:53.700910Z","shell.execute_reply.started":"2023-03-11T18:23:53.692646Z","shell.execute_reply":"2023-03-11T18:23:53.700089Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fixed\nSEED = 42\nfix_seed(SEED)\n\n#Define description for each class\nactivity_map = {\n    'c0': 'Safe driving', \n    'c1': 'Texting - right', \n    'c2': 'Talking on the phone - right', \n    'c3': 'Texting - left', \n    'c4': 'Talking on the phone - left', \n    'c5': 'Operating the radio', \n    'c6': 'Drinking', \n    'c7': 'Reaching behind', \n    'c8': 'Hair and makeup', \n    'c9': 'Talking to passenger'\n}\n\n#Define path\ndata_dir = '../input/state-farm-distracted-driver-detection'\ncsv_file_path = osp.join(data_dir, 'driver_imgs_list.csv')","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:53.702687Z","iopub.execute_input":"2023-03-11T18:23:53.703173Z","iopub.status.idle":"2023-03-11T18:23:53.710742Z","shell.execute_reply.started":"2023-03-11T18:23:53.703135Z","shell.execute_reply":"2023-03-11T18:23:53.710023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(csv_file_path) \n# read csv file\ndf.head(5) #show the first 5lines","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:53.712468Z","iopub.execute_input":"2023-03-11T18:23:53.712742Z","iopub.status.idle":"2023-03-11T18:23:53.743343Z","shell.execute_reply.started":"2023-03-11T18:23:53.712684Z","shell.execute_reply":"2023-03-11T18:23:53.742566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EDA","metadata":{}},{"cell_type":"code","source":"by_drivers = df.groupby('subject') #Groupby driver\nunique_drivers = by_drivers.groups.keys() #List of driver names\n\n#Number of drivers in dataset\nprint('unique drivers: ',len(unique_drivers)) \n#Number of drivers in dataset\nprint('mean of images: ', round(df.groupby('subject').count()['classname'].mean()))","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:53.745351Z","iopub.execute_input":"2023-03-11T18:23:53.745688Z","iopub.status.idle":"2023-03-11T18:23:53.761198Z","shell.execute_reply.started":"2023-03-11T18:23:53.745650Z","shell.execute_reply":"2023-03-11T18:23:53.760396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_file_num = len(glob(osp.join(data_dir, 'imgs/train/*/*.jpg'))) #Number of training data\ntest_file_num = len(glob(osp.join(data_dir, 'imgs/test/*.jpg'))) #Number of test data\ncategory_num = len(df['classname'].unique()) #Number of categories\nprint('train_file_num: ', train_file_num)\nprint('test_file_num: ', test_file_num)\nprint('category_num: ', category_num)","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:53.762566Z","iopub.execute_input":"2023-03-11T18:23:53.762828Z","iopub.status.idle":"2023-03-11T18:23:54.094104Z","shell.execute_reply.started":"2023-03-11T18:23:53.762795Z","shell.execute_reply":"2023-03-11T18:23:54.093173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# クラスごとのデータ数\npx.histogram(df, x=\"classname\", color=\"classname\", title=\"Number of images by categories \")","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:54.095505Z","iopub.execute_input":"2023-03-11T18:23:54.096197Z","iopub.status.idle":"2023-03-11T18:23:54.306072Z","shell.execute_reply.started":"2023-03-11T18:23:54.096163Z","shell.execute_reply":"2023-03-11T18:23:54.298320Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"drivers_id = pd.DataFrame((df['subject'].value_counts()).reset_index())\ndrivers_id.columns = ['driver_id', 'Counts']\npx.histogram(drivers_id, x=\"driver_id\",y=\"Counts\" ,color=\"driver_id\", title=\"Number of images by subjects \")","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:54.307562Z","iopub.execute_input":"2023-03-11T18:23:54.307997Z","iopub.status.idle":"2023-03-11T18:23:54.462819Z","shell.execute_reply.started":"2023-03-11T18:23:54.307960Z","shell.execute_reply":"2023-03-11T18:23:54.461991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Histogram of number of images per driver\n# do it yourself\npx.histogram(df, x='subject', color='subject', title='Number of images by subjects')","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:54.464184Z","iopub.execute_input":"2023-03-11T18:23:54.464492Z","iopub.status.idle":"2023-03-11T18:23:54.722188Z","shell.execute_reply.started":"2023-03-11T18:23:54.464458Z","shell.execute_reply":"2023-03-11T18:23:54.721377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Draw data for each class\n# do it yourself\nplt.figure(figsize=(12, 20))\nfor i, (key, value) in enumerate(activity_map.items()):\n    image_dir = osp.join(data_dir, 'imgs/train', key, '*.jpg')\n    image_path = glob(image_dir)[0]\n    image = cv2.imread(image_path)[:, :, (2, 1, 0)]\n    plt.subplot(5, 2, i+1)\n    plt.imshow(image)\n    plt.title(value)","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:54.723546Z","iopub.execute_input":"2023-03-11T18:23:54.724231Z","iopub.status.idle":"2023-03-11T18:23:56.780094Z","shell.execute_reply.started":"2023-03-11T18:23:54.724190Z","shell.execute_reply":"2023-03-11T18:23:56.778716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 前処理","metadata":{}},{"cell_type":"code","source":"#Add file path column \n#Implement by yourself\ndf['file_path'] = df.apply(lambda x: osp.join(data_dir, 'imgs/train', x.classname, x.img), axis=1)\n\n# Add column converting correct answer label to numbers\n\n# do it yourself\ndf['class_num'] = df['classname'].map(lambda x: int(x[1]))\ndf.head(5)","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:56.782536Z","iopub.execute_input":"2023-03-11T18:23:56.782962Z","iopub.status.idle":"2023-03-11T18:23:57.279859Z","shell.execute_reply.started":"2023-03-11T18:23:56.782927Z","shell.execute_reply":"2023-03-11T18:23:57.279033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Creation of dataset","metadata":{}},{"cell_type":"code","source":"class DataTransform():\n    \n    \"\"\"Image and annotation preprocessing classes. It behaves differently during training and testing.\n Attributes\n ---------\n input_size : int\n The size of the resized image.\n color_mean: (R,G,B)\n Average value for each color channel.\n color_std :(R,G,B)\nStandard deviation for each color channel.\n\n    \"\"\"\n\n    def __init__(self, input_size, color_mean, color_std):\n        self.data_transform = {\n            # Implement train by myself\n            'train': A.Compose([\n                A.HorizontalFlip(p=0.5),\n                A.Rotate(-10, 10),\n                A.Resize(input_size, input_size),  # リサイズ(input_size)\n                A.Normalize(color_mean, color_std),  # 色情報の標準化\n                ToTensorV2() # テンソル化\n            ]),\n            'val': A.Compose([\n                A.Resize(input_size, input_size),  # リサイズ(input_size)\n                A.Normalize(color_mean, color_std),  # 色情報の標準化\n                ToTensorV2() # テンソル化\n            ])\n        }\n\n    def __call__(self, phase, image):\n        \"\"\"\n        Parameters\n        ----------\n        phase : 'train' or 'val'\n            前処理のモードを指定。\n        \"\"\"\n        transformed = self.data_transform[phase](image=image)\n        return transformed['image']","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:57.281344Z","iopub.execute_input":"2023-03-11T18:23:57.281618Z","iopub.status.idle":"2023-03-11T18:23:57.288369Z","shell.execute_reply.started":"2023-03-11T18:23:57.281583Z","shell.execute_reply":"2023-03-11T18:23:57.287427Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 使用するモジュールのインポート\nimport os.path as osp\nfrom glob import glob\nimport random\nimport time\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport plotly.express as px\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import accuracy_score\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.utils.data as data\nimport torch.optim as optim\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-03-11T18:23:53.683131Z","iopub.execute_input":"2023-03-11T18:23:53.683964Z","iopub.status.idle":"2023-03-11T18:23:53.690075Z","shell.execute_reply.started":"2023-03-11T18:23:53.683912Z","shell.execute_reply":"2023-03-11T18:23:53.688981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Dataset(data.Dataset):\n    \"\"\"\n    Attributes\n    ----------\n    df : DataFrame\n        class_num, file_pathのカラムがあるデータフレーム\n    phase : 'train' or 'val'\n        学習か訓練かを設定する。\n    transform : object\n        前処理クラスのインスタンス\n    \"\"\"\n    def __init__(self, df, phase, transform):\n        self.df = df\n        self.phase = phase\n        self.transform = transform\n\n    def __len__(self):\n        '''画像の枚数を返す'''\n        return len(self.df)\n\n    def __getitem__(self, index):\n        '''前処理をした画像のTensor形式のデータを取得'''\n        image = self.pull_item(index)\n        return image, self.df.iloc[index]['class_num']\n\n    def pull_item(self, index):\n        '''画像のTensor形式のデータを取得する'''\n        \n        # 自分で実装\n        # 1. 画像読み込み\n        image_path = self.df.iloc[index]['file_path']\n        image = cv2.imread(image_path)[:, :, (2, 1, 0)]\n\n        # 2. 前処理を実施\n        return self.transform(self.phase, image)","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:57.289630Z","iopub.execute_input":"2023-03-11T18:23:57.290356Z","iopub.status.idle":"2023-03-11T18:23:57.300604Z","shell.execute_reply.started":"2023-03-11T18:23:57.290321Z","shell.execute_reply":"2023-03-11T18:23:57.299766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 動作確認\n\n# (RGB)の色の平均値と標準偏差\ncolor_mean = (0.485, 0.456, 0.406)\ncolor_std = (0.229, 0.224, 0.225)\ninput_size = 256\n\n# データ分割\ndf_train, df_val = train_test_split(df, stratify=df['subject'], random_state=SEED)\n\n# 自分で実装\n# データセット作成\ntrain_dataset = Dataset(df_train, phase=\"train\", transform=DataTransform(\n    input_size=input_size, color_mean=color_mean, color_std=color_std))\n\nval_dataset = Dataset(df_val, phase=\"val\", transform=DataTransform(\n    input_size=input_size, color_mean=color_mean, color_std=color_std))\n\n# 自分で実装\n# データの取り出し例\nimage, label = train_dataset[0]\nplt.imshow(image.permute(1, 2, 0))\nplt.title(label)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:57.301546Z","iopub.execute_input":"2023-03-11T18:23:57.301800Z","iopub.status.idle":"2023-03-11T18:23:57.551852Z","shell.execute_reply.started":"2023-03-11T18:23:57.301775Z","shell.execute_reply":"2023-03-11T18:23:57.551156Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataLoaderの作成","metadata":{}},{"cell_type":"code","source":"# データローダーの作成\nbatch_size = 64\n\n# 自分で実装\ntrain_dataloader = data.DataLoader(\n    train_dataset, batch_size=batch_size, shuffle=True)\n\nval_dataloader = data.DataLoader(\n    val_dataset, batch_size=batch_size, shuffle=False)\n\n# 辞書オブジェクトにまとめる\ndataloaders_dict = {\"train\": train_dataloader, \"val\": val_dataloader}\n\n# 自分で実装\n# 動作の確認\nbatch_iterator = iter(dataloaders_dict[\"val\"])  # イタレータに変換\nimages, labels = next(batch_iterator)  # 1番目の要素を取り出す\nprint(images.size())  # torch.Size([8, 3, 256, 256])\nprint(labels.size())  # torch.Size([8])","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:57.552875Z","iopub.execute_input":"2023-03-11T18:23:57.553235Z","iopub.status.idle":"2023-03-11T18:23:58.150732Z","shell.execute_reply.started":"2023-03-11T18:23:57.553200Z","shell.execute_reply":"2023-03-11T18:23:58.149797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# モデルの作成","metadata":{}},{"cell_type":"code","source":"!pip install efficientnet_pytorch\nfrom efficientnet_pytorch import EfficientNet\nmodel = EfficientNet.from_pretrained('efficientnet-b0', num_classes=10)\n\n# 自分で実装(練習)\n# class Model(nn.Module):\n#     def __init__(self, num_classes=10):\n#         super(Model, self).__init__()\n#         self.net = nn.Sequential(\n#             nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=2, padding=1),\n#             nn.BatchNorm2d(num_features=64),\n#             nn.ReLU(),\n#             nn.Conv2d(in_channels=64, out_channels=16, kernel_size=3, stride=2, padding=1),\n#             nn.BatchNorm2d(num_features=16),\n#             nn.ReLU(),\n#             nn.Flatten(),\n#             nn.Linear(in_features=65536, out_features=num_classes)\n#         )\n    \n#     def forward(self, x):\n#         output = self.net(x)\n#         return output\n# \n# model = Model(num_classes=10)","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:23:58.152318Z","iopub.execute_input":"2023-03-11T18:23:58.152601Z","iopub.status.idle":"2023-03-11T18:24:05.534681Z","shell.execute_reply.started":"2023-03-11T18:23:58.152563Z","shell.execute_reply":"2023-03-11T18:24:05.533881Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 学習","metadata":{}},{"cell_type":"code","source":"# 自分で実装(練習)\n# train_dataset = Dataset(df_train.iloc[:1000], phase=\"train\", transform=DataTransform(\n#     input_size=input_size, color_mean=color_mean, color_std=color_std))\n\n# val_dataset = Dataset(df_val.iloc[:1000], phase=\"val\", transform=DataTransform(\n#     input_size=input_size, color_mean=color_mean, color_std=color_std))\n\n# train_dataloader = data.DataLoader(\n#     train_dataset, batch_size=batch_size, shuffle=True)\n\n# val_dataloader = data.DataLoader(\n#     val_dataset, batch_size=batch_size, shuffle=False)\n\n# # 辞書オブジェクトにまとめる\n# dataloaders_dict = {\"train\": train_dataloader, \"val\": val_dataloader}\n\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n# optimizer = optim.Adam(model.parameters(), lr=1e-3)\n# criterion = nn.CrossEntropyLoss()\n\n# model = model.to(device)\n# for epoch in range(5):\n#     print(f'epoch: {epoch+1}')\n#     print('-'*50)\n    \n#     # train\n#     model.train()\n#     train_loss = 0\n#     for images, labels in train_dataloader:\n#         images = images.to(device)\n#         labels = labels.to(device)\n        \n#         optimizer.zero_grad()\n#         outputs = model(images)\n#         loss = criterion(outputs, labels)\n        \n#         loss.backward()\n#         optimizer.step()\n        \n#         train_loss += loss.item() / len(images)\n        \n#     print(f'epoch train loss: {train_loss: .4f}')\n\n#     # valid\n#     model.eval()\n#     valid_loss = 0\n#     preds = []\n#     trues = []\n#     for images, labels in val_dataloader:\n#         images = images.to(device)\n#         labels = labels.to(device)\n        \n#         with torch.no_grad():\n#             outputs = model(images)\n#             loss = criterion(outputs, labels)\n#             valid_loss = loss.item() / len(images)\n            \n#             trues += list(labels.cpu().numpy())\n#             preds += list(outputs.argmax(axis=1).cpu().numpy())\n    \n#     accuracy = accuracy_score(trues, preds)\n#     print(f'epoch valid loss: {valid_loss: .4f} accuracy: {accuracy: .4f}\\n')","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:24:05.537243Z","iopub.execute_input":"2023-03-11T18:24:05.537531Z","iopub.status.idle":"2023-03-11T18:24:05.542338Z","shell.execute_reply.started":"2023-03-11T18:24:05.537482Z","shell.execute_reply":"2023-03-11T18:24:05.541636Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# チェックポイントの保存\ndef save_checkpoint(model, optimizer, scheduler, epoch, path):\n    torch.save(\n        {'epoch': epoch,\n                'model': model.state_dict(),\n                'optimizer': optimizer.state_dict(),\n                'scheduler': scheduler.state_dict(), \n        }, path)\n\n# チェックポイントの読み込み\ndef load_checkpoint(model, optimizer, scheduler, path):\n    checkpoint = torch.load(path)\n    model.load_state_dict(checkpoint['model'])\n    optimizer.load_state_dict(checkpoint['optimizer'])\n    scheduler.load_state_dict(checkpoint['scheduler'])\n\n# モデルを学習させる関数\ndef train_model(model, dataloaders_dict, criterion, scheduler, optimizer, device, num_epochs, save_path):\n    # ネットワークをGPUへ\n    model.to(device)\n\n    best_val_loss = float('inf')\n    best_preds = None\n    \n    # epochのループ\n    for epoch in range(num_epochs):\n\n        # 開始時刻を保存\n        t_epoch_start = time.time()\n        epoch_train_loss = 0.0  # epochの損失和\n        epoch_val_loss = 0.0  # epochの損失和\n        preds = []\n        trues = []\n\n        print('-------------')\n        print(f'Epoch {epoch+1}/{num_epochs}')\n        print('-------------')\n\n        # epochごとの訓練と検証のループ\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                model.train()  # モデルを訓練モードに\n            else:\n                model.eval()   # モデルを検証モードに\n                print('-------------')\n                \n            # イテレーターループ\n            for i, (images, labels) in enumerate(dataloaders_dict[phase]):\n\n                # GPUが使えるならGPUにデータを送る\n                images = images.to(device)\n                labels = labels.to(device)\n\n                # 順伝搬（forward）計算\n                with torch.set_grad_enabled(phase == 'train'):\n                    outputs = model(images)\n                    loss = criterion(outputs, labels)\n                    \n                    # 訓練時はバックプロパゲーション\n                    if phase == 'train':\n                        loss.backward()  # 勾配の計算\n                        optimizer.step()\n                        optimizer.zero_grad() # 勾配の初期化\n                        epoch_train_loss += loss.item()/len(dataloaders_dict[phase].dataset)\n                    # 検証時\n                    else:\n                        preds += [outputs.detach().cpu().softmax(dim=1).numpy()]\n                        trues += [labels.detach().cpu()]\n                        epoch_val_loss += loss.item()/len(dataloaders_dict[phase].dataset)\n                    \n                    # 途中経過を表示\n                    if i%10 == 0:\n                        print(f'[{phase}][{i+1}/{len(dataloaders_dict[phase])}] loss: {loss.item()/images.size(0): .4f}')\n        \n        if phase == 'train':\n            scheduler.step()  # 最適化schedulerの更新\n            \n        # epochのphaseごとのlossと正解率\n        t_epoch_finish = time.time()\n        print('-------------')\n        print(f'epoch {epoch+1} epoch_train_Loss:{epoch_train_loss:.4f} epoch_val_loss:{epoch_val_loss:.4f} time: {t_epoch_finish - t_epoch_start:.4f} sec.')\n        print(f'epoch_val_acc: {accuracy_score(np.concatenate(trues), np.concatenate(preds).argmax(axis=1))}')\n        \n        # validation lossが一番低いエポックのモデルを保存\n        if best_val_loss > epoch_val_loss:\n            best_preds = np.concatenate(preds)\n            best_val_loss = epoch_val_loss\n            save_checkpoint(model, optimizer, scheduler, epoch, save_path)\n            print(\"save model\")\n    return best_val_loss, best_preds\n\n# 1foldの学習を行う関数\ndef run_one_fold(df_train, df_val, fold, device):\n    # データセット作成\n    train_dataset = Dataset(df_train, phase=\"train\", transform=DataTransform(\n        input_size=args.input_size, color_mean=args.color_mean, color_std=args.color_std))\n\n    val_dataset = Dataset(df_val, phase=\"val\", transform=DataTransform(\n        input_size=args.input_size, color_mean=args.color_mean, color_std=args.color_std))\n    \n    # データローダーの作成\n    train_dataloader = data.DataLoader(\n        train_dataset, batch_size=args.batch_size, shuffle=True)\n\n    val_dataloader = data.DataLoader(\n        val_dataset, batch_size=args.batch_size, shuffle=False)\n\n    # 辞書オブジェクトにまとめる\n    dataloaders_dict = {\"train\": train_dataloader, \"val\": val_dataloader}\n\n    # モデル定義\n    model = EfficientNet.from_pretrained(args.model_name, num_classes=args.num_classes)\n    optimizer = optim.Adam(model.parameters(), lr=args.lr) # 最適化手法\n    criterion = nn.CrossEntropyLoss() # 損失関数\n    scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma=args.gamma) # スケジューラ―\n    \n    save_path = f\"{args.model_name}_fold_{fold}.pth\"\n    best_val_loss, best_preds = train_model(model, dataloaders_dict, criterion, scheduler, optimizer, device, num_epochs=args.epochs, save_path=save_path)\n    return best_val_loss, best_preds\n\n# kfoldの学習を行う関数\ndef run_k_fold(df):\n    # GPUが使えるかを確認\n    device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n    print(\"使用デバイス：\", device)\n    \n    # 層化K分割交差検証\n    skf = StratifiedKFold(n_splits=args.folds, shuffle=True, random_state=SEED)\n    oof = pd.DataFrame(index=df.index)\n    for fold, (train_index, val_index) in enumerate(skf.split(df, df['subject'])):\n        print(f'\\n\\nFOLD: {fold}')\n        print('-'*50)\n        df_train, df_val = df.loc[train_index], df.loc[val_index]\n        best_val_loss, best_preds = run_one_fold(df_train, df_val, fold, device)\n        oof.loc[val_index, activity_map.keys()] = best_preds\n    return oof","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:24:05.543888Z","iopub.execute_input":"2023-03-11T18:24:05.544365Z","iopub.status.idle":"2023-03-11T18:24:05.567741Z","shell.execute_reply.started":"2023-03-11T18:24:05.544330Z","shell.execute_reply":"2023-03-11T18:24:05.566973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 学習パラメータ\nclass args:\n    model_name = 'efficientnet-b3'\n    color_mean = (0.485, 0.456, 0.406)\n    color_std = (0.229, 0.224, 0.225)\n    input_size = 256\n    num_classes = 10\n    batch_size = 64\n    epochs = 10\n    folds = 5\n    lr = 1e-3\n    gamma = 0.98\n    debug = True\n    train = False","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:24:05.568994Z","iopub.execute_input":"2023-03-11T18:24:05.569470Z","iopub.status.idle":"2023-03-11T18:24:05.578785Z","shell.execute_reply.started":"2023-03-11T18:24:05.569434Z","shell.execute_reply":"2023-03-11T18:24:05.578122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if args.debug:\n    df_train = df.iloc[:1000]\nelse:\n    df_train = df.copy()\n\nif args.train:\n    oof = run_k_fold(df_train)\n    accuracy = accuracy_score(df_train['class_num'], oof.values.argmax(axis=1))\n    print(f'\\n\\naccuracy: {accuracy}')","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:24:05.581395Z","iopub.execute_input":"2023-03-11T18:24:05.581823Z","iopub.status.idle":"2023-03-11T18:24:05.588804Z","shell.execute_reply.started":"2023-03-11T18:24:05.581780Z","shell.execute_reply":"2023-03-11T18:24:05.588064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testデータの予測","metadata":{}},{"cell_type":"code","source":"# 自分で実装\n# テストデータの推論を行う関数\ndef inference(model, dataloader, device):\n    model.to(device)\n    model.eval()\n    preds = []\n    for i, (images, labels) in enumerate(dataloader):\n        images = images.to(device)\n        with torch.no_grad():\n            outputs = model(images)\n        preds += [outputs.detach().cpu().softmax(dim=1).numpy()]\n        \n        if i%10 == 0:\n            print(f'[test][{i+1}/{len(dataloader)}]')\n        \n    preds = np.concatenate(preds)\n    return preds\n\n# k個のモデルに対して推論を行い，アンサンブル\ndef inference_k_fold(df_test):\n    test_dataset = Dataset(df_test, phase=\"val\", transform=DataTransform(\n        input_size=args.input_size, color_mean=args.color_mean, color_std=args.color_std))\n    test_dataloader = data.DataLoader(\n        test_dataset, batch_size=args.batch_size, shuffle=False)\n\n    model = EfficientNet.from_pretrained(args.model_name, num_classes=args.num_classes)\n    device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n    for fold in range(args.folds):\n        print(f'\\n\\nFOLD: {fold}')\n        print('-'*50)\n        model.load_state_dict(torch.load(f\"{args.model_name}_fold_{fold}.pth\")['model'])\n        df_test.loc[:, activity_map.keys()] += (inference(model, test_dataloader, device) / args.folds)","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:24:05.590107Z","iopub.execute_input":"2023-03-11T18:24:05.590379Z","iopub.status.idle":"2023-03-11T18:24:05.601857Z","shell.execute_reply.started":"2023-03-11T18:24:05.590345Z","shell.execute_reply":"2023-03-11T18:24:05.601133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if args.debug:\n    results = pd.read_csv('../input/statefarmdistracteddriverdetectionpretrain/result.csv')\n    results.to_csv('result.csv', index=False)\nelse:\n    # テストデータの読み込み\n    df_test = pd.read_csv(osp.join(data_dir, 'sample_submission.csv'))\n\n    # 前処理\n    df_test['file_path'] = df_test.apply(lambda row: osp.join(data_dir, f'imgs/test/{row.img}'), axis=1)\n    df_test['class_num'] = 0\n    df_test.loc[:, activity_map.keys()] = 0\n    \n    # k個分の推論結果を平均し，resultsに格納\n    inference_k_fold(df_test)\n    results = df_test.drop(['file_path', 'class_num'], axis=1)\n    results.iloc[:, 1:] = results.iloc[:, 1:].clip(0, 1)\n    results.to_csv('result.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-03-11T18:24:31.119065Z","iopub.execute_input":"2023-03-11T18:24:31.119343Z","iopub.status.idle":"2023-03-11T18:24:32.384154Z","shell.execute_reply.started":"2023-03-11T18:24:31.119309Z","shell.execute_reply":"2023-03-11T18:24:32.383365Z"},"trusted":true},"execution_count":null,"outputs":[]}]}