{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"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","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"# 訓練データとテストデータの解凍\nimport os, shutil, zipfile\n\n# 解凍するzipファイル名\ndata = ['train', 'test']\n\n# train.zip、test.zipをカレントディレクトリに展開\nfor el in data:\n    with zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/' + el + \".zip\", \"r\") as z:\n        z.extractall()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\n\n# trainフォルダー内のファイル名を取得してfilenamesに格納\nfilenames = os.listdir(\"./train\")\n# store the label for each image file\ncategories = []\n\n# 訓練データのファイル名のdog.x.jpg、cat.x.jpgを使って1と0のラベルを生成\nfor filename in filenames:\n    # ファイル名を分割して先頭要素(dog/cat)のみを取り出し、\n    # dogは1、catは0をラベルにしてcategoryに格納\n    category = filename.split('.')[0]\n    if category == 'dog':\n        # dogならラベル1として追加\n        categories.append(1)\n    else:\n        # catならラベル0として追加\n        categories.append(0)\n\n# dfの列filenameにファイル名filenamesを格納\n# 列categoriesにラベルの値categoryを格納\ndf = pd.DataFrame({\n    'filename': filenames,\n    'category': categories\n})\n\n# データフレームの先頭から5行目までを出力\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# dog(1)とcat(0)の総数をグラフにする\ndf['category'].value_counts().plot.bar()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ランダムに選んだ12枚の画像を出力する\nfrom tensorflow.keras.preprocessing.image import load_img\nimport matplotlib.pyplot as plt\nimport random\n%matplotlib inline\n\n# ランダムに16枚取り出す\nsample = random.sample(filenames, 16)\n\n# 描画するエリアのサイズは12×12\nplt.figure(figsize=(12, 12))\n\nfor i in range(0, 16):\n    # 4×4のマス目の左上隅から順番に描画\n    plt.subplot(4, 4, i+1)\n    # sampleに格納されたi番目の画像\n    fname = sample[i]\n    # trainフォルダーから画像を読み込む\n    image = load_img(\"./train/\"+fname)\n    # 画像を描画\n    plt.imshow(image)\n    plt.axis('off') # 目盛りは非表示\nplt.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 訓練データを訓練用と検証用に分ける\nfrom sklearn.model_selection import train_test_split\n\n# 訓練データの総数25000の10%を検証データにする\ntrain_df, validate_df = train_test_split(df, test_size=0.1)\n# 行インデックスを振り直す\ntrain_df = train_df.reset_index()\nvalidate_df = validate_df.reset_index()\n\n# 訓練データの数を取得\ntotal_train = train_df.shape[0]\n# 検証データの数を取得\ntotal_validate = validate_df.shape[0]\n\n# 訓練、検証データの数を出力\nprint(total_train)\nprint(total_validate)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 訓練データを加工処理する\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n# 画像をリサイズするときのサイズ\nimg_width, img_height = 224, 224\ntarget_size = (img_width, img_height)\n# ミニバッチのサイズ\nbatch_size = 16\n\n# データフレームに格納したファイル名の列名とラベルの列名\nx_col, y_col = 'filename', 'category'\n# flow_from_dataframe()で画像を生成する際のclass_modeオプションの値\n# ジェネレーターが返すラベルの配列の形状として二値分類の'binary'を格納\nclass_mode = 'binary'\n\n# 画像を加工するジェネレーターを生成\ntrain_datagen = ImageDataGenerator(\n    rescale=1./255,         # RGB値を0～1.0の範囲に変換\n    rotation_range=15,      # ランダムに回転\n    shear_range=0.2,        # シアー変換\n    zoom_range=0.2,         # 拡大\n    horizontal_flip=True,   # 水平方向に反転\n    width_shift_range=0.1,  # 平行移動\n    height_shift_range=0.1  # 垂直移動\n)\n\n\n# flow_from_dataframe()の引数class_mode = \"binary\"の場合、\n# ラベルが格納されたtrain_dfのy_col = 'category'の列の値は\n# 文字列であることが必要なので、1と0の数値を文字列に変換しておく\ntrain_df['category'] = train_df['category'].astype(str) \n\n# ジェネレータで加工した画像の生成\ntrain_generator = train_datagen.flow_from_dataframe(\n    train_df,    # 訓練用のデータフレーム\n    \"./train/\",  # 画像データのディレクトリ\n    x_col=x_col, # ファイル名が格納された列\n    y_col=y_col, # ラベルが格納された列 (文字列に変換済み)\n    class_mode=class_mode, # ラベルの配列の形状\n    target_size=target_size, # 画像のサイズ\n    batch_size=batch_size    # ミニバッチのサイズ\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 検証データを加工処理する\n\n# 画像を加工するジェネレーターを生成\n# データ拡張は必要ないのでRGB値の変換のみを行う\nvalidation_datagen = ImageDataGenerator(rescale=1./255)\n\n# flow_from_dataframe()の引数class_mode = \"binary\"の場合、\n# ラベルが格納されたvalidate_dfのy_col = 'category'の列の値は\n# 文字列であることが必要なので、1と0の数値を文字列に変換しておく\nvalidate_df['category'] = validate_df['category'].astype(str)\n\n# ジェネレータで加工した画像の生成\nvalidation_generator = validation_datagen.flow_from_dataframe(\n    validate_df,  # 検証用のデータフレーム\n    \"./train/\",   # 画像データのディレクトリ\n    x_col=x_col,  # ファイル名が格納された列\n    y_col=y_col,  # ラベルが格納された列(文字列に変換済み)\n    class_mode=class_mode,   # ラベルの配列の形状\n    target_size=target_size, # 画像のサイズ\n    batch_size=batch_size    # ミニバッチのサイズ\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 訓練データから1サンプル取り出し、加工処理後の9パターンを表示\n\n# 訓練データから1サンプル取り出し、reset_index()でインデックスを振り直す\n# drop=Trueは元のインデックスを削除するためのもの\nexample_df = train_df.sample(n=1).reset_index(drop=True)\n# DataFrameIteratorオブジェクトを生成\nexample_generator = train_datagen.flow_from_dataframe(\n    example_df,       # サンプルデータを格納したデータフレーム\n    \"./train/\",       # 画像データの場所\n    x_col='filename', # ファイル名の列名\n    y_col='category', # 正解ラベルの列名\n    target_size=target_size # 画像をリサイズする\n)\n# 描画エリアのサイズは12×12\nplt.figure(figsize=(12, 12))\n# 加工処理後の9パターンを表示\nfor i in range(0, 9):\n    # 3×3のマス目の左上隅から順番に描画\n    plt.subplot(3, 3, i+1)\n    for X_batch, Y_batch in example_generator:\n        # X_batchの1つ目の画像データを抽出\n        image = X_batch[0]\n        # 抽出した画像を描画したらbreakする\n        plt.imshow(image)\n        break\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 3層の畳み込み層を持つCNN\n\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense\nfrom tensorflow.keras.layers import GlobalMaxPooling2D\nfrom tensorflow.keras import optimizers\nfrom tensorflow.keras import regularizers\n\n# Sequentualオブジェクトを生成\nmodel = Sequential()\n\n# 入力データの形状\ninput_shape = (img_width, img_height, 3)\n\n# 第1層:畳み込み層1\nmodel.add(\n    Conv2D(\n        filters=32,              # フィルターの数は32\n        kernel_size=(3, 3),      # 3×3のフィルターを使用\n        padding='same',          # ゼロパディングを行う\n        activation='relu',       # 活性化関数はReLU\n        input_shape=input_shape, # 入力データの形状\n        ))\n\n# 第2層:プーリング層\nmodel.add(\n    MaxPooling2D(pool_size=(2, 2)))\n# ドロップアウト25％\nmodel.add(Dropout(0.25))\n\n# 第3層:畳み込み層2\nmodel.add(\n    Conv2D(\n        filters = 64,        # フィルターの数は32\n        kernel_size = (3,3), # 3×3のフィルターを使用\n        padding='same',      # ゼロパディングを行う\n        activation='relu',   # 活性化関数はReLU\n        ))\n\n# 第4層:プーリング層\nmodel.add(\n    MaxPooling2D(pool_size=(2, 2)))\n# ドロップアウト25％\nmodel.add(Dropout(0.25))\n\n# 第5層:畳み込み層3\nmodel.add(\n    Conv2D(\n        filters=128,          # フィルターの数は64\n        kernel_size=(3, 3),   # 3×3のフィルターを使用\n        padding='same',       # ゼロパディングを行う\n        activation='relu',    # 活性化関数はReLU\n        ))\n\n# 第6層:プーリング層\nmodel.add(\n    MaxPooling2D(pool_size=(2, 2))\n)\n# ドロップアウト25％\nmodel.add(Dropout(0.25))\n\n# (batch_size, rows, cols, channels)の4階テンソルに\n# プーリング演算適用後、(batch_size, channels)の2階テンソルにフラット化\nmodel.add(\n    GlobalMaxPooling2D())\n\n# 第7層\nmodel.add(\n    Dense(128,                   # ユニット数128\n          activation='relu'))    # 活性化関数はReLU\n# ドロップアウト25％\nmodel.add(Dropout(0.25))\n\n# 第8層:出力層\nmodel.add(\n    Dense(1,                     # ニューロン数は1個\n          activation='sigmoid')) # 活性化関数はSigmoid\n\n# モデルのコンパイル\nmodel.compile(\n    loss='binary_crossentropy',    # バイナリ用のクロスエントロピー誤差\n    metrics=['accuracy'],          # 学習評価として正解率を指定\n    optimizer=optimizers.RMSprop() # RMSpropで最適化\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 学習を行う\n\nimport math\nfrom tensorflow.keras.callbacks import LearningRateScheduler, EarlyStopping, Callback\n\n# 学習率をスケジューリングする\ndef step_decay(epoch):\n    initial_lrate = 0.001 # 学習率の初期値\n    drop = 0.5            # 減衰率は50%\n    epochs_drop = 10.0    # 10エポック毎に減衰する\n    lrate = initial_lrate * math.pow(\n        drop,\n        math.floor((epoch)/epochs_drop)\n    )\n    return lrate\n\n# 学習率のコールバック\nlrate = LearningRateScheduler(step_decay)\n \n# 学習の進捗を監視して早期終了するコールバック\nearstop = EarlyStopping(\n    monitor='val_loss', # 監視対象は損失\n    min_delta=0,        # 改善として判定される最小変化値\n    patience=5)         # 改善が見られないと判断されるエポック数を5に拡大\n\n\n# 学習の実行\n# GPU使用による所要時間:\nepochs = 40        # エポック数\nhistory = model.fit(\n    # 訓練データ\n    train_generator,\n    # エポック数\n    epochs=epochs,\n    # 訓練時のステップ数\n    steps_per_epoch = total_train//batch_size,\n    # 検証データ\n    validation_data=validation_generator,\n    # 検証時のステップ数\n    validation_steps = total_validate//batch_size,\n    # 学習の進捗状況を出力する    \n    verbose=1,\n    # 学習率のスケジューラーとアーリーストッピングをコール\n    callbacks=[lrate, earstop]\n)","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}