{"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":"# 使用するモジュールのインポート\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":"2021-12-02T12:52:07.172576Z","iopub.execute_input":"2021-12-02T12:52:07.172986Z","iopub.status.idle":"2021-12-02T12:52:14.070810Z","shell.execute_reply.started":"2021-12-02T12:52:07.172939Z","shell.execute_reply":"2021-12-02T12:52:14.069715Z"},"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":"2021-12-02T12:52:14.073341Z","iopub.execute_input":"2021-12-02T12:52:14.073639Z","iopub.status.idle":"2021-12-02T12:52:14.079209Z","shell.execute_reply.started":"2021-12-02T12:52:14.073609Z","shell.execute_reply":"2021-12-02T12:52:14.078130Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Seed値の固定\nSEED = 42\nfix_seed(SEED)\n\n# 各クラスの説明の定義\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# パスの定義\ndata_dir = '../input/state-farm-distracted-driver-detection'\ncsv_file_path = osp.join(data_dir, 'driver_imgs_list.csv')","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:14.082002Z","iopub.execute_input":"2021-12-02T12:52:14.082782Z","iopub.status.idle":"2021-12-02T12:52:14.101950Z","shell.execute_reply.started":"2021-12-02T12:52:14.082684Z","shell.execute_reply":"2021-12-02T12:52:14.100816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(csv_file_path) # csvファイルの読み込み\ndf.head(5) # 最初の5行を表示","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:14.104153Z","iopub.execute_input":"2021-12-02T12:52:14.104597Z","iopub.status.idle":"2021-12-02T12:52:14.151813Z","shell.execute_reply.started":"2021-12-02T12:52:14.104553Z","shell.execute_reply":"2021-12-02T12:52:14.150903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EDA","metadata":{}},{"cell_type":"code","source":"by_drivers = df.groupby('subject') # ドライバーでグループ化\nunique_drivers = by_drivers.groups.keys() # ドライバー名のリスト\n\n# データセットに含まれるドライバーの数\nprint('unique drivers: ',len(unique_drivers)) \n# ドライバー1人当たりの画像の数の平均\nprint('mean of images: ', round(df.groupby('subject').count()['classname'].mean()))","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:14.155270Z","iopub.execute_input":"2021-12-02T12:52:14.155580Z","iopub.status.idle":"2021-12-02T12:52:14.187087Z","shell.execute_reply.started":"2021-12-02T12:52:14.155522Z","shell.execute_reply":"2021-12-02T12:52:14.186070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_file_num = len(glob(osp.join(data_dir, 'imgs/train/*/*.jpg'))) # 訓練データの数\ntest_file_num = len(glob(osp.join(data_dir, 'imgs/test/*.jpg'))) # テストデータの数\ncategory_num = len(df['classname'].unique()) # カテゴリの数\nprint('train_file_num: ', train_file_num)\nprint('test_file_num: ', test_file_num)\nprint('category_num: ', category_num)","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:14.190879Z","iopub.execute_input":"2021-12-02T12:52:14.191164Z","iopub.status.idle":"2021-12-02T12:52:19.013108Z","shell.execute_reply.started":"2021-12-02T12:52:14.191132Z","shell.execute_reply":"2021-12-02T12:52:19.012109Z"},"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":"2021-12-02T12:52:19.015118Z","iopub.execute_input":"2021-12-02T12:52:19.015719Z","iopub.status.idle":"2021-12-02T12:52:20.293347Z","shell.execute_reply.started":"2021-12-02T12:52:19.015672Z","shell.execute_reply":"2021-12-02T12:52:20.292347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ドライバーごとの画像の数のヒストグラム\n# 自分で実装\npx.histogram(df, x=\"subject\", color=\"subject\", title=\"Number of images by subjects \")","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:20.294637Z","iopub.execute_input":"2021-12-02T12:52:20.294943Z","iopub.status.idle":"2021-12-02T12:52:20.670902Z","shell.execute_reply.started":"2021-12-02T12:52:20.294901Z","shell.execute_reply":"2021-12-02T12:52:20.669949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 各クラスの画像を描画\n# 自分で実装\nplt.figure(figsize=(10, 20))\nfor i, (key, value) in enumerate(activity_map.items()):\n    image_path = osp.join(data_dir, 'imgs/train', key, '*.jpg')\n    image_path = glob(image_path)[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":"2021-12-02T12:52:20.672688Z","iopub.execute_input":"2021-12-02T12:52:20.674443Z","iopub.status.idle":"2021-12-02T12:52:23.429348Z","shell.execute_reply.started":"2021-12-02T12:52:20.674386Z","shell.execute_reply":"2021-12-02T12:52:23.428488Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 前処理","metadata":{}},{"cell_type":"code","source":"# ファイルパスの列を追加\n# 自分で実装\ndf['file_path'] = df.apply(lambda row: osp.join(data_dir, f\"imgs/train/{row['classname']}/{row['img']}\"), axis=1)\n# 正解ラベルを数値に変換して列を追加\n\n# 自分で実装\ndf['class_num'] = df['classname'].map(lambda x: int(x[1]))\ndf.head(5)","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:23.430890Z","iopub.execute_input":"2021-12-02T12:52:23.431342Z","iopub.status.idle":"2021-12-02T12:52:24.217495Z","shell.execute_reply.started":"2021-12-02T12:52:23.431300Z","shell.execute_reply":"2021-12-02T12:52:24.216415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Datasetの作成","metadata":{}},{"cell_type":"code","source":"class DataTransform():\n    \"\"\"\n    画像とアノテーションの前処理クラス。訓練時と検証時で異なる動作をする。\n    画像のサイズをinput_size x input_sizeにする。\n    訓練時はデータオーギュメンテーションする。\n\n    Attributes\n    ----------\n    input_size : int\n        リサイズ先の画像の大きさ。\n    color_mean : (R, G, B)\n        各色チャネルの平均値。\n    color_std : (R, G, B)\n        各色チャネルの標準偏差。\n    \"\"\"\n\n    def __init__(self, input_size, color_mean, color_std):\n        self.data_transform = {\n            # trainだけ自分で実装\n            'train': A.Compose([\n                A.HorizontalFlip(p=0.5),\n                A.Rotate(limit=15),\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":"2021-12-02T12:52:24.222701Z","iopub.execute_input":"2021-12-02T12:52:24.223252Z","iopub.status.idle":"2021-12-02T12:52:24.242250Z","shell.execute_reply.started":"2021-12-02T12:52:24.223204Z","shell.execute_reply":"2021-12-02T12:52:24.241132Z"},"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    \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)\n\n        # 自分で実装\n        # 1. 画像読み込み\n        image_file_path = self.df.iloc[index]['file_path']\n        image = cv2.imread(image_file_path)   # [高さ][幅][色RGB]\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\n        # 2. 前処理を実施\n        image = self.transform(self.phase, image)\n        return image","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:24.244045Z","iopub.execute_input":"2021-12-02T12:52:24.244677Z","iopub.status.idle":"2021-12-02T12:52:24.267135Z","shell.execute_reply.started":"2021-12-02T12:52:24.244630Z","shell.execute_reply":"2021-12-02T12:52:24.265847Z"},"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":"2021-12-02T12:52:24.272295Z","iopub.execute_input":"2021-12-02T12:52:24.272631Z","iopub.status.idle":"2021-12-02T12:52:24.964763Z","shell.execute_reply.started":"2021-12-02T12:52:24.272588Z","shell.execute_reply":"2021-12-02T12:52:24.963911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataLoaderの作成","metadata":{}},{"cell_type":"code","source":"# データローダーの作成\nbatch_size = 64\n\n# 自分で実装\ntrain_dataloader = None\nval_dataloader = None\n\n# 辞書オブジェクトにまとめる\ndataloaders_dict = {\"train\": train_dataloader, \"val\": val_dataloader}\n\n# 自分で実装\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([64, 3, 256, 256])\nprint(labels.size())  # torch.Size([64])","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:24.971739Z","iopub.execute_input":"2021-12-02T12:52:24.972536Z","iopub.status.idle":"2021-12-02T12:52:26.088841Z","shell.execute_reply.started":"2021-12-02T12:52:24.972475Z","shell.execute_reply":"2021-12-02T12:52:26.087790Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# モデルの作成","metadata":{}},{"cell_type":"code","source":"# 自分で実装\nclass Model(nn.Module):\n    def __init__(self, num_classes):\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","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:26.090871Z","iopub.execute_input":"2021-12-02T12:52:26.091209Z","iopub.status.idle":"2021-12-02T12:52:26.100567Z","shell.execute_reply.started":"2021-12-02T12:52:26.091163Z","shell.execute_reply":"2021-12-02T12:52:26.098961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Model(num_classes=10)\noutput = model(images)\noutput.shape","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:26.102755Z","iopub.execute_input":"2021-12-02T12:52:26.103653Z","iopub.status.idle":"2021-12-02T12:52:27.537709Z","shell.execute_reply.started":"2021-12-02T12:52:26.103602Z","shell.execute_reply":"2021-12-02T12:52:27.536722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 学習","metadata":{}},{"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# モデルを学習させる関数\n# k-fold交差検証で学習する\n# 自分で実装\ndef run_k_fold(df):\n    pass","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:27.539171Z","iopub.execute_input":"2021-12-02T12:52:27.539526Z","iopub.status.idle":"2021-12-02T12:52:27.547980Z","shell.execute_reply.started":"2021-12-02T12:52:27.539480Z","shell.execute_reply":"2021-12-02T12:52:27.546895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# パラメータ\nclass args:\n    debug = True","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:27.549683Z","iopub.execute_input":"2021-12-02T12:52:27.550508Z","iopub.status.idle":"2021-12-02T12:52:27.560817Z","shell.execute_reply.started":"2021-12-02T12:52:27.550459Z","shell.execute_reply":"2021-12-02T12:52:27.559504Z"},"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\n# 学習\nrun_k_fold(df_train)\naccuracy = 0\nprint(f'\\n\\naccuracy: {accuracy}')","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:27.562558Z","iopub.execute_input":"2021-12-02T12:52:27.563095Z","iopub.status.idle":"2021-12-02T12:52:27.574813Z","shell.execute_reply.started":"2021-12-02T12:52:27.563007Z","shell.execute_reply":"2021-12-02T12:52:27.573469Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testデータの予測","metadata":{}},{"cell_type":"code","source":"# 自分で実装\n# k個のモデルに対して推論を行い，アンサンブル\ndef inference_k_fold(df_test):\n    pass","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:27.576640Z","iopub.execute_input":"2021-12-02T12:52:27.578224Z","iopub.status.idle":"2021-12-02T12:52:27.585957Z","shell.execute_reply.started":"2021-12-02T12:52:27.578174Z","shell.execute_reply":"2021-12-02T12:52:27.585059Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# テストデータの読み込み\ndf_test = pd.read_csv(osp.join(data_dir, 'sample_submission.csv'))\n# デバッグ時は500データだけ使用\nif args.debug:\n    df_test = df_test.iloc[:1000]\n\n# 前処理\ndf_test['file_path'] = df_test.apply(lambda row: osp.join(data_dir, f'imgs/test/{row.img}'), axis=1)\ndf_test['class_num'] = 0\ndf_test.loc[:, activity_map.keys()] = 0","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:27.587234Z","iopub.execute_input":"2021-12-02T12:52:27.589324Z","iopub.status.idle":"2021-12-02T12:52:27.787977Z","shell.execute_reply.started":"2021-12-02T12:52:27.589273Z","shell.execute_reply":"2021-12-02T12:52:27.786911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# k個分の推論結果を平均し，resultsに格納\n# inference_k_fold(df_test)\n# results = df_test.drop(['file_path', 'class_num'], axis=1)\n# results.to_csv('result.csv', index=False)\n# results","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:27.789805Z","iopub.execute_input":"2021-12-02T12:52:27.790144Z","iopub.status.idle":"2021-12-02T12:52:27.824558Z","shell.execute_reply.started":"2021-12-02T12:52:27.790098Z","shell.execute_reply":"2021-12-02T12:52:27.823339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nresult = pd.read_csv('../input/statefarmdistracteddriverdetectionpretrain/result.csv')\nresult.to_csv('result.csv', index=False)\nresult","metadata":{"execution":{"iopub.status.busy":"2021-12-02T12:52:27.826551Z","iopub.execute_input":"2021-12-02T12:52:27.826979Z","iopub.status.idle":"2021-12-02T12:52:30.162370Z","shell.execute_reply.started":"2021-12-02T12:52:27.826936Z","shell.execute_reply":"2021-12-02T12:52:30.161381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}