{"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":"code","source":"import zipfile\nimport glob\nimport os\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport collections\n\nfrom PIL import Image\n\ntrain_dir = 'train'\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip', 'r') as train_zip:\n    train_zip.extractall('')\n\ntrain_list = glob.glob(os.path.join(train_dir,'*.jpg'))\nprint(f\"Train Data: {len(train_list)}\")\n\nbase_dir = '/kaggle/working'\ntrain_dir = os.path.join(base_dir, 'train')\n\ntest_dir = 'test'\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip', 'r') as test_zip:\n    test_zip.extractall('')\n\ntest_list = glob.glob(os.path.join(test_dir,'*.jpg'))\nprint(f\"Test Data: {len(test_list)}\")\n\nbase_dir = '/kaggle/working'\ntest_dir = os.path.join(base_dir, 'test')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-07-20T14:40:32.145597Z","iopub.execute_input":"2023-07-20T14:40:32.145967Z","iopub.status.idle":"2023-07-20T14:40:49.6478Z","shell.execute_reply.started":"2023-07-20T14:40:32.145937Z","shell.execute_reply":"2023-07-20T14:40:49.646753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ダウンロードしたデータを確認する\n画像ランダムに9つ表示","metadata":{}},{"cell_type":"code","source":"print(f'学習データ数：{len(train_list)}', f'先頭のデータ：{train_list[0]}')\nprint(f'テストデータ数：{len(test_list)}', f'先頭のデータ：{test_list[0]}')","metadata":{"execution":{"iopub.status.busy":"2023-07-20T14:40:49.650059Z","iopub.execute_input":"2023-07-20T14:40:49.650792Z","iopub.status.idle":"2023-07-20T14:40:49.658214Z","shell.execute_reply.started":"2023-07-20T14:40:49.650755Z","shell.execute_reply":"2023-07-20T14:40:49.657213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = [path.split('/')[-1].split('.')[0] for path in train_list]\n\nrandom_idx = np.random.randint(1, len(train_list), size=9)\nfig, axes = plt.subplots(3, 3, figsize=(16, 12))\n\nfor idx, ax in enumerate(axes.ravel()):\n    img = Image.open(train_list[idx])\n    img_r = img.transpose(Image.FLIP_LEFT_RIGHT)\n    ax.set_title(labels[idx])\n    ax.imshow(img_r)","metadata":{"execution":{"iopub.status.busy":"2023-07-20T14:40:49.659701Z","iopub.execute_input":"2023-07-20T14:40:49.66019Z","iopub.status.idle":"2023-07-20T14:40:52.732904Z","shell.execute_reply.started":"2023-07-20T14:40:49.660157Z","shell.execute_reply":"2023-07-20T14:40:52.731768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"2次元上にプロット\n赤：Dog\n青：Cat","metadata":{}},{"cell_type":"markdown","source":"## 学習データ・テストデータ・検証データの生成","metadata":{}},{"cell_type":"code","source":"#from PIL import Image\n#import os, glob\n#import numpy as np\nfrom PIL import ImageFile\nfrom sklearn.model_selection import train_test_split\n\nclasses = {'dog':0, 'cat':1}\nimage_size = 224 #推奨224\ndim = 1 # option\n\nX_train = []\ny_train = []\nX_test  = []\n\ntrain_labels = [path.split('/')[-1].split('.')[0] for path in train_list]\n\nfor i, img in enumerate(train_list) :\n    image = Image.open(img)\n    image = image.convert(\"L\") #グレースケール　本来はRGB\n    image = image.resize((image_size, image_size))\n    data = np.asarray(image)\n    X_train.append(data)\n    y_train.append(classes[train_labels[i]])\n    \nfor i, img in enumerate(test_list) :\n    image = Image.open(img)\n    image = image.convert(\"L\")\n    image = image.resize((image_size, image_size))\n    data = np.asarray(image)\n    X_test.append(data)\n\nX_train = np.array(X_train)\ny_train = np.array(y_train)\nX_train, X_val, y_train, y_val = train_test_split(X_train, y_train, train_size=0.7, random_state=0)\n\nX_test  = np.array(X_test)\n\n'''\n# 入力データの各画素値を0-1の範囲で正規化(学習コストを下げるため)\nX_train = X_train.astype(\"float\") / 255\nX_val  = X_val.astype(\"float\") / 255\nX_test  = X_test.astype(\"float\") / 255\n'''","metadata":{"execution":{"iopub.status.busy":"2023-07-20T14:40:52.734031Z","iopub.execute_input":"2023-07-20T14:40:52.73434Z","iopub.status.idle":"2023-07-20T14:42:27.074058Z","shell.execute_reply.started":"2023-07-20T14:40:52.734312Z","shell.execute_reply":"2023-07-20T14:42:27.072895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"生成データの確認","metadata":{}},{"cell_type":"code","source":"print('学習・検証・テストデータ')\nprint(f'学習データ数：{len(X_train)} 検証データ数:{len(X_val)} テストデータ数：{len(X_test)}')\nprint(f'学習ラベル数：{len(y_train)} 検証ラベル数:{len(y_val)}')\nprint('1つのデータ')\nprint(f'学習の次元数：{X_train[0].shape} 検証の次元数：{X_val[0].shape} テストの次元数：{X_test[0].shape}')\nprint(f'学習ラベル：{y_train[0]} 検証ラベル：{y_val[0]}')\n# メモリ確保のため変数の削除\ndel train_list\ndel train_labels\ndel image\ndel data","metadata":{"execution":{"iopub.status.busy":"2023-07-20T14:42:27.077606Z","iopub.execute_input":"2023-07-20T14:42:27.078031Z","iopub.status.idle":"2023-07-20T14:42:27.091373Z","shell.execute_reply.started":"2023-07-20T14:42:27.077998Z","shell.execute_reply":"2023-07-20T14:42:27.090234Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"ラベル分布","metadata":{}},{"cell_type":"code","source":"import collections\nc1 = collections.Counter(y_train)\nc2 = collections.Counter(y_val)\nprint(classes)\nprint(f'学習データのラベル分布：{c1}')\nprint(f'検証データのラベル分布：{c2}')","metadata":{"execution":{"iopub.status.busy":"2023-07-20T14:42:27.0929Z","iopub.execute_input":"2023-07-20T14:42:27.093771Z","iopub.status.idle":"2023-07-20T14:42:27.11175Z","shell.execute_reply.started":"2023-07-20T14:42:27.093731Z","shell.execute_reply":"2023-07-20T14:42:27.110636Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('学習・検証・テストデータ')\nprint(f'学習データ数：{len(X_train)} 検証データ数:{len(X_val)} テストデータ数：{len(X_test)}')\nprint(f'学習ラベル数：{len(y_train)} 検証ラベル数:{len(y_val)}')\nprint('1つのデータ')\nprint(f'学習の次元数：{X_train[0].shape} 検証の次元数：{X_val[0].shape} テストの次元数：{X_test[0].shape}')\nprint(f'学習ラベル：{y_train[0]} 検証ラベル：{y_val[0]}')","metadata":{"execution":{"iopub.status.busy":"2023-07-20T14:42:27.112991Z","iopub.execute_input":"2023-07-20T14:42:27.113432Z","iopub.status.idle":"2023-07-20T14:42:27.122988Z","shell.execute_reply.started":"2023-07-20T14:42:27.113399Z","shell.execute_reply":"2023-07-20T14:42:27.121884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 分類学習\nモデル構築\n\n事前学習モデルを呼び出す","metadata":{}},{"cell_type":"code","source":"from keras.models import Sequential ,Model\nfrom keras.layers import Conv2D, MaxPooling2D\nfrom keras.layers import Input, Activation, Dropout, Flatten, Dense\nfrom keras.optimizers import RMSprop\nimport tensorflow as tf\n\nimport keras\nimport numpy as np","metadata":{"execution":{"iopub.status.busy":"2023-07-20T14:42:27.124629Z","iopub.execute_input":"2023-07-20T14:42:27.125301Z","iopub.status.idle":"2023-07-20T14:42:35.865597Z","shell.execute_reply.started":"2023-07-20T14:42:27.125267Z","shell.execute_reply":"2023-07-20T14:42:35.864605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model(image_size, num_classes):\n    # 画像を受け取る層\n    inputs = Input(shape = image_size)\n    # EfficientNetB3を作成\n    x = tf.keras.applications.efficientnet.EfficientNetB3(include_top = False)(inputs)\n    # １次元に変換する層\n    x = Flatten()(x)\n    # 最終出力層\n    outputs = Dense(units = num_classes, activation = \"softmax\")(x)\n\n    # 定義した層を使ってモデル作成\n    model = Model(inputs = inputs, outputs = outputs)\n    # 最適化手法と損失関数を定義\n    model.compile(\n        optimizer = tf.keras.optimizers.Adam(learning_rate = 5e-5),\n        loss = \"sparse_categorical_crossentropy\",\n        metrics=['accuracy']\n    )\n    return model\n\n# モデルの呼び出し\ntf.keras.backend.clear_session()\nmodel = get_model((image_size, image_size, dim), 2)\n#model = get_model(X_train.shape[-3:], 2)\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-07-20T14:42:35.867181Z","iopub.execute_input":"2023-07-20T14:42:35.868035Z","iopub.status.idle":"2023-07-20T14:42:45.9111Z","shell.execute_reply.started":"2023-07-20T14:42:35.867998Z","shell.execute_reply":"2023-07-20T14:42:45.910145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## データセットの生成","metadata":{}},{"cell_type":"code","source":"'''\ntrain_dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))\ntest_dataset = tf.data.Dataset.from_tensor_slices((X_val, y_val))\n\ntrain_dataset = train_dataset.batch(32)\ntest_dataset = test_dataset.batch(32)\n\ntrain_dataset = train_dataset.shuffle(1024 * 50)\n\nbatch = next(iter(train_dataset))\nprint(batch[0].shape)\nprint(batch[1].shape)\n'''","metadata":{"execution":{"iopub.status.busy":"2023-07-20T14:42:45.913005Z","iopub.execute_input":"2023-07-20T14:42:45.914008Z","iopub.status.idle":"2023-07-20T14:42:45.921422Z","shell.execute_reply.started":"2023-07-20T14:42:45.913973Z","shell.execute_reply":"2023-07-20T14:42:45.920274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 分類モデルへの入力データ用の作成\nBATCH_SIZE = 32 # 学習バッチサイズ\n\ntrain_dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train)).batch(BATCH_SIZE)\n# メモリ確保のため変数の削除\ndel X_train\ndel y_train\n\ntest_dataset = tf.data.Dataset.from_tensor_slices((X_val, y_val)).batch(BATCH_SIZE)\ndel X_val # メモリ確保のため変数の削除\n\ntrain_dataset = train_dataset.shuffle(12345)","metadata":{"execution":{"iopub.status.busy":"2023-07-20T14:42:45.923163Z","iopub.execute_input":"2023-07-20T14:42:45.923661Z","iopub.status.idle":"2023-07-20T14:42:47.954193Z","shell.execute_reply.started":"2023-07-20T14:42:45.923628Z","shell.execute_reply":"2023-07-20T14:42:47.953207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"epoch数を10で学習","metadata":{}},{"cell_type":"code","source":"checkpoint = tf.keras.callbacks.ModelCheckpoint(\n    \"best_weight.h5\",     # ファイル名\n    monitor = \"val_loss\", # 参照するloss\n    mode = \"min\",         # monitorが最小のときに保存\n    save_best_only = True,\n    save_weights_only = True\n)\n\nhistory = model.fit(\n    train_dataset,\n    validation_data = test_dataset,\n    epochs = 10,\n    callbacks = [checkpoint]\n)","metadata":{"execution":{"iopub.status.busy":"2023-07-20T14:42:47.955484Z","iopub.execute_input":"2023-07-20T14:42:47.955843Z","iopub.status.idle":"2023-07-20T15:33:59.163971Z","shell.execute_reply.started":"2023-07-20T14:42:47.955812Z","shell.execute_reply":"2023-07-20T15:33:59.162938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_weights(\"best_weight.h5\")\npreds = model.predict(test_dataset)\nprint(preds[0])\nprint(y_val[0])","metadata":{"execution":{"iopub.status.busy":"2023-07-20T15:33:59.16738Z","iopub.execute_input":"2023-07-20T15:33:59.167704Z","iopub.status.idle":"2023-07-20T15:34:25.423255Z","shell.execute_reply.started":"2023-07-20T15:33:59.167672Z","shell.execute_reply":"2023-07-20T15:34:25.42223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(history.history[\"loss\"], label = \"train\")\nplt.plot(history.history[\"val_loss\"], label = \"valid\")\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-20T15:37:12.940378Z","iopub.execute_input":"2023-07-20T15:37:12.940753Z","iopub.status.idle":"2023-07-20T15:37:13.196489Z","shell.execute_reply.started":"2023-07-20T15:37:12.940721Z","shell.execute_reply":"2023-07-20T15:37:13.195532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_labels = preds.argmax(axis = 1)\nprint(pred_labels[:5])\nprint(y_val[:5].reshape(-1))","metadata":{"execution":{"iopub.status.busy":"2023-07-20T15:37:15.54263Z","iopub.execute_input":"2023-07-20T15:37:15.543742Z","iopub.status.idle":"2023-07-20T15:37:15.55709Z","shell.execute_reply.started":"2023-07-20T15:37:15.543698Z","shell.execute_reply":"2023-07-20T15:37:15.556036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score\n\nprint(accuracy_score(pred_labels, y_val.reshape(-1)))","metadata":{"execution":{"iopub.status.busy":"2023-07-20T15:38:31.160081Z","iopub.execute_input":"2023-07-20T15:38:31.160478Z","iopub.status.idle":"2023-07-20T15:38:31.169257Z","shell.execute_reply.started":"2023-07-20T15:38:31.160445Z","shell.execute_reply":"2023-07-20T15:38:31.168031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## submitデータの作成","metadata":{}},{"cell_type":"code","source":"# モデルの呼び出し\ntf.keras.backend.clear_session()\nmodel = get_model((image_size, image_size, dim), 2)\nmodel.load_weights(\"best_weight.h5\")","metadata":{"execution":{"iopub.status.busy":"2023-07-20T15:38:33.849661Z","iopub.execute_input":"2023-07-20T15:38:33.850914Z","iopub.status.idle":"2023-07-20T15:38:38.939345Z","shell.execute_reply.started":"2023-07-20T15:38:33.85087Z","shell.execute_reply":"2023-07-20T15:38:38.938211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''\npred = model.predict(X_test)\n\nimport pandas as pd\n\ndf1 = pd.DataFrame(pred, columns=['dog', 'cat'])\n\nids = [path.split('/')[-1].split('.')[0] for path in test_list]\nsubmit = list(zip(ids, df1['dog'].to_list()))\ndf2 = pd.DataFrame(submit, columns=['id', 'label'])\nprint(df2.head())\ndf2.to_csv('submit_trained.csv', index=False)\n'''\npred = model.predict(X_test)\n\nimport pandas as pd\n\ndf1 = pd.DataFrame(pred, columns=['dog', 'cat'])\nids = [path.split('/')[-1].split('.')[0] for path in test_list]\nsubmit = list(zip(ids, df1['dog'].to_list()))\ndf2 = pd.DataFrame(submit, columns=['id', 'label'])\nprint(df2.head())\ndf2.to_csv('submit_trained.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-07-20T15:41:03.493137Z","iopub.execute_input":"2023-07-20T15:41:03.493502Z","iopub.status.idle":"2023-07-20T15:41:45.846819Z","shell.execute_reply.started":"2023-07-20T15:41:03.49347Z","shell.execute_reply":"2023-07-20T15:41:45.845601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('submit_trained.csv')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-20T15:42:04.665856Z","iopub.execute_input":"2023-07-20T15:42:04.66622Z","iopub.status.idle":"2023-07-20T15:42:04.689814Z","shell.execute_reply.started":"2023-07-20T15:42:04.66619Z","shell.execute_reply":"2023-07-20T15:42:04.688157Z"},"trusted":true},"execution_count":null,"outputs":[]}]}