{"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":"# 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":"2023-07-27T01:06:25.320912Z","iopub.execute_input":"2023-07-27T01:06:25.321377Z","iopub.status.idle":"2023-07-27T01:06:25.345662Z","shell.execute_reply.started":"2023-07-27T01:06:25.321339Z","shell.execute_reply":"2023-07-27T01:06:25.344374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 必要なライブラリをインポート\nkerasで画像認識、VGG1でパラメータ数を少なくして多層化による表現力の向上、ImageDataGeneratorでデータの水増し、Sequentialでモデル層の積み重ね、Dense, Dropout, FlattenでCNNでの全結合層の出力次元の決定、ModelCheckpointでエポックを決めて過学習になった場合にモデルファイルが保存されているので便利になる、shutilファイルの集まりに対する高水準の操作方法、osで可能な限り同一のインタフェースで同一の機能を利用できるようにする、globで特定のパターンにマッチするファイルを取得する","metadata":{}},{"cell_type":"code","source":"from tensorflow import keras\nfrom keras.applications.vgg16 import VGG16\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.models import Sequential\nfrom keras.layers import Dense, Dropout, Flatten\nfrom keras.callbacks import ModelCheckpoint\nfrom matplotlib import pyplot as plt\nimport shutil\nimport os\nimport glob","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:06:29.005604Z","iopub.execute_input":"2023-07-27T01:06:29.005952Z","iopub.status.idle":"2023-07-27T01:06:37.090445Z","shell.execute_reply.started":"2023-07-27T01:06:29.005924Z","shell.execute_reply":"2023-07-27T01:06:37.089292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Zipファイルを解凍\n","metadata":{}},{"cell_type":"code","source":"shutil.unpack_archive('/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip', '/kaggle/working')\nshutil.unpack_archive('/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip', '/kaggle/working')\n\n\nshutil.copyfile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/sample_submission.csv','/kaggle/working/sample_submission.csv')\n\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n        \nfiles = glob.glob('/kaggle/working/*')\nfor file in files:\n    print(file)","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:06:39.889526Z","iopub.execute_input":"2023-07-27T01:06:39.890277Z","iopub.status.idle":"2023-07-27T01:06:55.616072Z","shell.execute_reply.started":"2023-07-27T01:06:39.890219Z","shell.execute_reply":"2023-07-27T01:06:55.615065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 画像サイズとディレクトリの設定\n画像の幅と高さ、学習データとテストデータを指定した。\nモデルの入力サイズを小さくして計算リソースを節約して使用した。","metadata":{}},{"cell_type":"code","source":"img_width, img_height = 150, 150\ntrain_dir = '/kaggle/working/train'\ntest_dir = '/kaggle/working/test'","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:07:10.769123Z","iopub.execute_input":"2023-07-27T01:07:10.770169Z","iopub.status.idle":"2023-07-27T01:07:10.776069Z","shell.execute_reply.started":"2023-07-27T01:07:10.770133Z","shell.execute_reply":"2023-07-27T01:07:10.774088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# エポック数の設定\n学習のエポック数を指定。\n20にした","metadata":{}},{"cell_type":"code","source":"epoch = 20","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:07:15.891567Z","iopub.execute_input":"2023-07-27T01:07:15.891920Z","iopub.status.idle":"2023-07-27T01:07:15.896264Z","shell.execute_reply.started":"2023-07-27T01:07:15.891891Z","shell.execute_reply":"2023-07-27T01:07:15.895300Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 分類クラス名の設定\n犬と猫の2つのクラスを持つ分類問題であるため、この変数を使用して指定した","metadata":{}},{"cell_type":"code","source":"classes = ['dog','cat']\nnb_classes = len(classes)","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:07:19.157695Z","iopub.execute_input":"2023-07-27T01:07:19.158762Z","iopub.status.idle":"2023-07-27T01:07:19.163724Z","shell.execute_reply.started":"2023-07-27T01:07:19.158721Z","shell.execute_reply":"2023-07-27T01:07:19.162468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# VGG16モデルのロード\nVGG16のデータモデルを定義した。","metadata":{}},{"cell_type":"code","source":"vgg_model = VGG16(include_top = False, weights = 'imagenet', input_shape = (img_height, img_width, 3))","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:07:22.293884Z","iopub.execute_input":"2023-07-27T01:07:22.294561Z","iopub.status.idle":"2023-07-27T01:07:26.156396Z","shell.execute_reply.started":"2023-07-27T01:07:22.294526Z","shell.execute_reply":"2023-07-27T01:07:26.155437Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# VGG16モデルの下に全結合層を追加\nニューラルネットワークを定義した。犬と猫の分類問題に適したモデルにするために使用した","metadata":{}},{"cell_type":"code","source":"model = Sequential()\nmodel.add(vgg_model)\nmodel.add(Flatten())\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(nb_classes, activation='softmax'))","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:07:29.331064Z","iopub.execute_input":"2023-07-27T01:07:29.331449Z","iopub.status.idle":"2023-07-27T01:07:29.438094Z","shell.execute_reply.started":"2023-07-27T01:07:29.331418Z","shell.execute_reply":"2023-07-27T01:07:29.437150Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# VGG16モデルの上位15層のパラメータを凍結(Fine tuning)","metadata":{}},{"cell_type":"code","source":"for layer in vgg_model.layers[:15]:\n layer.trainable = False","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:07:33.691807Z","iopub.execute_input":"2023-07-27T01:07:33.692149Z","iopub.status.idle":"2023-07-27T01:07:33.698057Z","shell.execute_reply.started":"2023-07-27T01:07:33.692123Z","shell.execute_reply":"2023-07-27T01:07:33.696902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# モデルの詳細を表示","metadata":{}},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:07:36.875059Z","iopub.execute_input":"2023-07-27T01:07:36.875780Z","iopub.status.idle":"2023-07-27T01:07:36.900327Z","shell.execute_reply.started":"2023-07-27T01:07:36.875744Z","shell.execute_reply":"2023-07-27T01:07:36.899605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 損失関数は交差エントロピー、最適化関数は確率的勾配法\n予測値と正解値の差を出力する誤差関数として使用した。この損失関数の値が最小となるようにパラメータを最適化する方法としてSDG(確立的勾配法)を使用した。","metadata":{}},{"cell_type":"code","source":"model.compile(loss = 'categorical_crossentropy', optimizer = 'sgd', metrics = ['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:07:40.772736Z","iopub.execute_input":"2023-07-27T01:07:40.773089Z","iopub.status.idle":"2023-07-27T01:07:40.795186Z","shell.execute_reply.started":"2023-07-27T01:07:40.773060Z","shell.execute_reply":"2023-07-27T01:07:40.794208Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 犬・猫の画像を，それぞれ保存するフォルダのパスを定義","metadata":{}},{"cell_type":"code","source":"dog_dir = '/kaggle/working/train/dog'\ncat_dir = '/kaggle/working/train/cat'\n\nos.makedirs(dog_dir, exist_ok = True)\nos.makedirs(cat_dir, exist_ok = True)","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:07:46.561892Z","iopub.execute_input":"2023-07-27T01:07:46.562278Z","iopub.status.idle":"2023-07-27T01:07:46.570355Z","shell.execute_reply.started":"2023-07-27T01:07:46.562224Z","shell.execute_reply":"2023-07-27T01:07:46.569310Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 犬・猫の画像をそれぞれのフォルダに移動","metadata":{}},{"cell_type":"markdown","source":"# 訓練用フォルダ内の全ファイルパスを取得","metadata":{}},{"cell_type":"code","source":"files = glob.glob('/kaggle/working/train/*.jpg')\nfor file in files:\n    file_name = os.path.basename(file)\n    if 'cat' in file:\n        shutil.move(file,'/kaggle/working/train/cat/' + file_name)\n    else:\n        shutil.move(file,'/kaggle/working/train/dog/' + file_name)","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:07:56.557645Z","iopub.execute_input":"2023-07-27T01:07:56.557993Z","iopub.status.idle":"2023-07-27T01:07:57.409193Z","shell.execute_reply.started":"2023-07-27T01:07:56.557965Z","shell.execute_reply":"2023-07-27T01:07:57.408205Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 学習データのデータ拡張を設定\n学習データのデータ拡張を設定した。データ拡張により学習データを増やし、過学習を防ぐために使用した。","metadata":{}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(rescale = 1.0 / 255, rotation_range = 90, shear_range = 0.2, zoom_range = 0.2, horizontal_flip = True,\n                vertical_flip = True, fill_mode = 'reflect', validation_split = 0.2)","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:08:02.054702Z","iopub.execute_input":"2023-07-27T01:08:02.055054Z","iopub.status.idle":"2023-07-27T01:08:02.060398Z","shell.execute_reply.started":"2023-07-27T01:08:02.055024Z","shell.execute_reply":"2023-07-27T01:08:02.059445Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 評価データのデータ拡張を設定\nテストデータのデータ拡張を設定した。データ拡張により学習データを増やし、過学習を防ぐために使用した。","metadata":{}},{"cell_type":"code","source":"test_datagen = ImageDataGenerator(rescale = 1.0 / 255)","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:08:11.389538Z","iopub.execute_input":"2023-07-27T01:08:11.390064Z","iopub.status.idle":"2023-07-27T01:08:11.394056Z","shell.execute_reply.started":"2023-07-27T01:08:11.390033Z","shell.execute_reply":"2023-07-27T01:08:11.393261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 学習データのジェネレータを生成\n学習データをバッチ処理した。データ拡張された画像データを扱う際に便利であるため使用した。","metadata":{}},{"cell_type":"code","source":"train_generator = train_datagen.flow_from_directory(train_dir, target_size = (img_height, img_width), classes = classes, batch_size = 32, class_mode = 'categorical', subset = \"training\")","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:08:14.959582Z","iopub.execute_input":"2023-07-27T01:08:14.959936Z","iopub.status.idle":"2023-07-27T01:08:15.504685Z","shell.execute_reply.started":"2023-07-27T01:08:14.959907Z","shell.execute_reply":"2023-07-27T01:08:15.503752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 評価データのジェネレータを生成\nテストデータをバッチ処理した。データ拡張された画像データを扱う際に便利であるため使用した。","metadata":{}},{"cell_type":"code","source":"test_generator = train_datagen.flow_from_directory(train_dir, target_size = (img_height, img_width), classes = classes, batch_size = 32, class_mode = 'categorical', subset = \"validation\")","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:08:17.859744Z","iopub.execute_input":"2023-07-27T01:08:17.860086Z","iopub.status.idle":"2023-07-27T01:08:18.085497Z","shell.execute_reply.started":"2023-07-27T01:08:17.860058Z","shell.execute_reply":"2023-07-27T01:08:18.084464Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# コールバック関数(モデル保存)の設定","metadata":{}},{"cell_type":"code","source":"mc_cb = ModelCheckpoint(filepath = 'finetuning.h5', monitor = 'vol_loss', verbose = 1, save_best_only = True)","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:08:26.366916Z","iopub.execute_input":"2023-07-27T01:08:26.367275Z","iopub.status.idle":"2023-07-27T01:08:26.372614Z","shell.execute_reply.started":"2023-07-27T01:08:26.367239Z","shell.execute_reply":"2023-07-27T01:08:26.371594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ジェネレータを用いたモデル学習","metadata":{}},{"cell_type":"code","source":"history = model.fit_generator(train_generator, epochs=epoch, validation_data = test_generator, callbacks = [mc_cb])\n\nmodel.save('finetuning.h5')","metadata":{"execution":{"iopub.status.busy":"2023-07-27T01:08:29.141667Z","iopub.execute_input":"2023-07-27T01:08:29.142016Z","iopub.status.idle":"2023-07-27T02:11:03.440157Z","shell.execute_reply.started":"2023-07-27T01:08:29.141987Z","shell.execute_reply":"2023-07-27T02:11:03.439087Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 予想誤差のグラフ化","metadata":{}},{"cell_type":"code","source":"plt.plot(range(len(history.history['loss'])), history.history['loss'], marker='o', color = 'black', label='loss')\nplt.plot(range(len(history.history['val_loss'])), history.history['val_loss'], marker='v', linestyle='--', color='red', label='val_loss')\nplt.xlabel('epoch')\nplt.ylabel('loss')\nplt.legend(loc='best')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-27T02:12:22.193127Z","iopub.execute_input":"2023-07-27T02:12:22.194220Z","iopub.status.idle":"2023-07-27T02:12:22.481147Z","shell.execute_reply.started":"2023-07-27T02:12:22.194175Z","shell.execute_reply":"2023-07-27T02:12:22.480138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 予想精度のグラフ化","metadata":{}},{"cell_type":"code","source":"plt.plot(range(len(history.history['accuracy'])), history.history['accuracy'], marker='o', color = 'black', label='acc')\nplt.plot(range(len(history.history['val_accuracy'])), history.history['val_accuracy'], marker='v', linestyle='--', color = 'red', label='val_acc')\nplt.xlabel('epoch')\nplt.ylabel('accuracy')\nplt.legend(loc='best')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-27T02:12:25.751773Z","iopub.execute_input":"2023-07-27T02:12:25.752133Z","iopub.status.idle":"2023-07-27T02:12:26.035652Z","shell.execute_reply.started":"2023-07-27T02:12:25.752102Z","shell.execute_reply":"2023-07-27T02:12:26.034534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 分類予測に必要なライブラリをインポート","metadata":{}},{"cell_type":"code","source":"import sys\nimport glob\nimport numpy as np\nfrom keras.preprocessing import image\nfrom keras.models import load_model","metadata":{"execution":{"iopub.status.busy":"2023-07-27T02:12:47.197894Z","iopub.execute_input":"2023-07-27T02:12:47.198288Z","iopub.status.idle":"2023-07-27T02:12:47.204057Z","shell.execute_reply.started":"2023-07-27T02:12:47.198249Z","shell.execute_reply":"2023-07-27T02:12:47.202897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 画像サイズの設定","metadata":{}},{"cell_type":"code","source":"img_height, img_width = 150, 150","metadata":{"execution":{"iopub.status.busy":"2023-07-27T02:12:49.969264Z","iopub.execute_input":"2023-07-27T02:12:49.969613Z","iopub.status.idle":"2023-07-27T02:12:49.974605Z","shell.execute_reply.started":"2023-07-27T02:12:49.969586Z","shell.execute_reply":"2023-07-27T02:12:49.973574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 分類クラス名の設定","metadata":{}},{"cell_type":"code","source":"classes = ['dog','cat']\nnb_classes = len(classes)","metadata":{"execution":{"iopub.status.busy":"2023-07-27T02:12:59.296686Z","iopub.execute_input":"2023-07-27T02:12:59.297040Z","iopub.status.idle":"2023-07-27T02:12:59.301648Z","shell.execute_reply.started":"2023-07-27T02:12:59.297011Z","shell.execute_reply":"2023-07-27T02:12:59.300414Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ファインチューニングしたCNNモデルのロード","metadata":{}},{"cell_type":"code","source":"model = load_model('finetuning.h5')","metadata":{"execution":{"iopub.status.busy":"2023-07-27T02:13:03.033773Z","iopub.execute_input":"2023-07-27T02:13:03.034130Z","iopub.status.idle":"2023-07-27T02:13:03.462547Z","shell.execute_reply.started":"2023-07-27T02:13:03.034100Z","shell.execute_reply":"2023-07-27T02:13:03.461495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# テストフォルダー内の全画像ファイル名を取得","metadata":{}},{"cell_type":"code","source":"filename = glob.glob('/content/drive/MyDrive/data/test/*/*.jpg')","metadata":{"execution":{"iopub.status.busy":"2023-07-27T02:13:07.955728Z","iopub.execute_input":"2023-07-27T02:13:07.956141Z","iopub.status.idle":"2023-07-27T02:13:07.963601Z","shell.execute_reply.started":"2023-07-27T02:13:07.956108Z","shell.execute_reply":"2023-07-27T02:13:07.962316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# テストフォルダ内の全画像を分類予測し各クラスの分類確率値を出力","metadata":{}},{"cell_type":"code","source":"for i in range(len(filename)):\n print('input:', filename[i])\n\n# 入力画像のロード、4次元テンソルへ変換 \n img = image.load_img(filename[i], target_size = (img_height, img_width))\n x = image.img_to_array(img)\n x = np.expand_dims(x, axis = 0)\n\n# 入力データへの正規化\n x = x / 255.0\n\n# 分類クラスを予測\n pred = model.predict(x)[0]\n\n#予測結果を予測確率が上位10件分、クラス名と予測確率を出力\n top_n = 10\n top_indices = pred.argsort()[-top_n:][::-1]\n result = [(classes[i], pred[i]) for i in top_indices]\n for x in result:\n  print(x)","metadata":{"execution":{"iopub.status.busy":"2023-07-27T02:13:13.974506Z","iopub.execute_input":"2023-07-27T02:13:13.974868Z","iopub.status.idle":"2023-07-27T02:13:13.982617Z","shell.execute_reply.started":"2023-07-27T02:13:13.974840Z","shell.execute_reply":"2023-07-27T02:13:13.981574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}}]}