{"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":"pip install keras==2.3.1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nimport os, zipfile\nfrom sklearn.model_selection import train_test_split\n\ndef prepareData():\n    \"\"\"データを読み込んで訓練データと検証データに分ける\n    \n    Returns:\n        train_df(DataFrame):\n          trainから抽出した訓練用のデータ(90%)\n        validate_df(DataFrame):\n          trainから抽出した検証用のデータ(10%)\n    \"\"\"\n    # 訓練データとテストデータの解凍\n    # 解凍するzipファイル名\n    data = ['train', 'test']\n\n    # train.zip、test.zipをカレントディレクトリに展開\n    for el in data:\n        with zipfile.ZipFile(\n            '../input/dogs-vs-cats-redux-kernels-edition/' +\n            el + \".zip\", \"r\") as z:\n            z.extractall(\".\")\n\n    # 訓練データのファイル名のdog.x.jpg、cat.x.jpgを使って1と0のラベルを生成\n    # trainフォルダー内のファイル名を取得してfilenamesに格納\n    filenames = os.listdir(\"./train\")\n    # 正解ラベルを格納するリスト\n    categories = []\n    \n    for 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を格納\n    df = pd.DataFrame({\n        'filename': filenames,\n        'category': categories\n    })\n    \n    # 訓練データの総数25000をランダムに90%をと10%に切り分け、\n    # 90%を訓練データ、10%を訓練時の検証データにする\n    train_df, validate_df = train_test_split(df, test_size=0.1)\n    # 行インデックスを振り直す\n    train_df = train_df.reset_index()\n    validate_df = validate_df.reset_index()\n   \n    return train_df, validate_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\n\ndef ImageDataGenerate(train_df, validate_df):\n    \"\"\"画像を加工処理する\n    \n    parameters:\n        train_df(DataFrame):\n          trainから抽出した訓練用のデータ(90%)\n        validate_df(DataFrame):\n          trainから抽出した検証用のデータ(10%)\n    Returns:\n        train_generator(DirectoryIterator):\n          加工処理後の訓練データ\n        validation_generator(DirectoryIterator):\n          加工処理後の検証データ\n    \"\"\"\n    # 画像をリサイズするサイズ\n    img_width, img_height = 224, 224\n    target_size = (img_width, img_height)\n    # ミニバッチのサイズ\n    batch_size = 16\n    \n    # ファイル名の列名とラベルの列名\n    x_col, y_col = 'filename', 'category'\n    # flow_from_dataframe()で画像を生成する際のclass_modeオプションの値\n    # ジェネレーターが返すラベルの配列の形状として'binary'を格納\n    class_mode = 'binary'\n\n    # 訓練データを加工するジェネレーターを生成\n    train_datagen = ImageDataGenerator(\n        rotation_range=15,\n        rescale=1./255,\n        shear_range=0.2,\n        zoom_range=0.2,\n        horizontal_flip=True,\n        fill_mode='nearest',\n        width_shift_range=0.1,\n        height_shift_range=0.1\n    )\n\n    # flow_from_dataframe()の引数class_mode = \"binary\"の場合、\n    # ラベルが格納されたtrain_dfのy_col = 'category'の列の値は\n    # 文字列であることが必要なので、1と0の数値を文字列に変換しておく\n    train_df['category'] = train_df['category'].astype(str)  #optional\n\n    # ジェネレータを使って訓練データを生成\n    train_generator = train_datagen.flow_from_dataframe(\n        train_df,     # 訓練用のデータフレーム\n        \"./train/\",   # 画像データのディレクトリ\n        x_col=x_col,  # ファイル名が格納された列\n        y_col=y_col,  # ラベルが格納された列 (文字列に変換済み)\n        class_mode=None,         # 出力層は存在しないのでclass_modeはNone\n        target_size=target_size, # 画像のサイズ\n        batch_size=batch_size,   # ミニバッチのサイズ\n        shuffle=False)           # データをシャッフルしない\n\n    # 検証データを加工するジェネレーター\n    validation_datagen = ImageDataGenerator(rescale=1./255)\n\n    # flow_from_dataframe()の引数class_mode = \"binary\"の場合、\n    # ラベルが格納されたvalidate_dfのy_col = 'category'の列の値は\n    # 文字列であることが必要なので、1と0の数値を文字列に変換しておく\n    validate_df['category'] = validate_df['category'].astype(str)\n\n    # ジェネレータを使って検証データを生成\n    validation_generator = validation_datagen.flow_from_dataframe(\n        validate_df,   # 検証用のデータフレーム\n        \"./train/\",    # 画像データのディレクトリ\n        x_col=x_col,   # ファイル名が格納された列\n        y_col=y_col,   # ラベルが格納された列(文字列に変換済み)\n        class_mode=None,         # 出力層は存在しないのでclass_modeはNone\n        target_size=target_size, # 画像のサイズ\n        batch_size=batch_size,   # ミニバッチのサイズ\n        shuffle=False)           # データをシャッフルしない\n        \n    # 生成した訓練データと検証データを返す\n    return train_generator, validation_generator","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.applications import VGG16\nimport numpy as np\n\ndef save_VGG16_outputs(train_generator,\n                       validation_generator):\n    '''VGG16に訓練データ、検証データを入力し、\n       それぞれの最終出力をnpyファイルに保存する\n       \n    parameters:\n        train_generator(DataFrameIterator):\n          加工済みの訓練用データ\n        validate_df(DataFrameIterator):\n          加工済みの検証データ\n　　'''  \n    # 画像のサイズを取得\n    image_size = len(train_generator[0][0][0])\n    # 入力データの形状をタプルにする\n    input_shape = (image_size, image_size, 3)\n\n    # VGG16モデルと学習済み重みを読み込む\n    model = VGG16(\n        include_top=False,      # 全結合の3層（FC層）は読み込まない\n        weights='imagenet',     # ImageNetで学習した重みを利用\n        input_shape=input_shape # 入力データの形状\n    )\n    # VGG16のサマリを表示\n    model.summary()\n\n    # 訓練データをVGG16モデルに入力し、その出力をファイルに保存\n    vgg16_train = model.predict_generator(\n        train_generator,              # ジェネレーターで加工した訓練データ\n        steps = len(train_generator), # ジェネレーターのサイズを設定\n        verbose=1                     # 進捗状況を出力\n    )\n    # 訓練データの出力を保存\n    np.save('vgg16_train.npy', vgg16_train)\n\n    # 検証データーをVGG16モデルに入力する\n    vgg16_test = model.predict_generator(\n        validation_generator,              # ジェネレーターで加工した検証データ\n        steps = len(validation_generator), # ジェネレーターのサイズを設定\n        verbose=1                          # 進捗状況を出力\n    )\n    # 検証データの出力を保存\n    np.save('vgg16_test.npy', vgg16_test)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nfrom keras.models import Sequential\nfrom keras import optimizers\nfrom keras.layers import Dropout, GlobalMaxPooling2D, Dense\n\ndef train_FClayer(train_labels, validation_labels):\n    '''VGG16の出力を独自のFC層に入力して学習する\n    \n    parameters:\n       train_labels(intのlist):訓練データの正解ラベル\n       validate_df(intのlist):検証データの正解ラベル\n    '''\n    # 訓練データのVGG16からの出力をNumPy配列に読み込む\n    train_data = np.load('vgg16_train.npy')\n\n    # テストデータのVGG16からの出力をNumPy配列に読み込む\n    validation_data = np.load('vgg16_test.npy')\n\n    # 独自のFCネットワークの作成\n    model = Sequential()\n    # (batch_size, rows, cols, channels)の\n    # 4階テンソルにプーリング演算を適用後、\n    # (batch_size, channels)の2階テンソルにフラット化\n    model.add(\n        GlobalMaxPooling2D())\n\n    # 全結合層\n    model.add(\n        Dense(512,               # ユニット数512\n              activation='relu') # 活性化関数はReLU\n    )\n    # 50%のドロップアウト\n    model.add(Dropout(0.5))\n\n    # 出力層\n    model.add(\n        Dense(1,                    # ユニット数1\n              activation='sigmoid') # 活性化関数はSigmoid\n    )\n    \n    # モデルのコンパイル\n    model.compile(loss='binary_crossentropy',\n                  optimizer=optimizers.RMSprop(lr=1e-5),\n                  metrics=['accuracy'])\n\n    # 学習の実行\n    epoch = 20                             # エポック数\n    batch_size = 16                        # ミニバッチのサイズ\n    history = model.fit(train_data,        # 訓練データ\n                        train_labels,      # 訓練データの正解ラベル\n                        epochs=epoch,\n                        batch_size=batch_size,\n                        verbose=1,\n                        # 検証データと正解ラベル\n                        validation_data=(validation_data,\n                                         validation_labels)\n                        )\n\n    # historyを返す\n    return history","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 訓練データと検証データを取得\ntrain_df, validate_df = prepareData()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display(train_df)\ndisplay(validate_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ジェネレーターで加工する\ntrain_generator, validation_generator = ImageDataGenerate(\n                                            train_df, validate_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display(train_generator)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_size = len(train_generator[0][0][0])\nprint(image_size)\n\ninput_shape = (image_size, image_size, 3)\nprint(input_shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_size = len(train_generator[0][0][0])\n\ninput_shape = (image_size, image_size, 3)\n\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Dropout, GlobalMaxPooling2D\nfrom tensorflow.keras import optimizers\nfrom tensorflow.keras.applications import VGG16\nfrom tensorflow.keras.callbacks import LearningRateScheduler\nimport math\n\n\nmodel = VGG16(\n        include_top=False,      # 全結合の3層（FC層）は読み込まない\n        weights='imagenet',     # ImageNetで学習した重みを利用\n        input_shape=input_shape # 入力データの形状\n    )\n    # VGG16のサマリを表示\nmodel.summary()\n\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"vgg16_train = model.predict_generator(train_generator,steps = len(train_generator),verbose=1)\n\nnp.save('vgg16_train.npy', vgg16_train)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"vgg16_test = model.predict_generator(validation_generator,steps = len(validation_generator),verbose=1)\nnp.save('vgg16_test.npy', vgg16_test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(vgg16_train.shape)\nprint(vgg16_test.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n# VGG16の出力をFCネットワークで学習\n\n# 訓練データの正解ラベルを取得\ntrain_labels = np.array(train_df['category'])\n# 検証データの正解ラベルを取得\nvalidation_labels = np.array(validate_df['category'])\n\nprint(train_labels)\nprint(validation_labels)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data = np.load('vgg16_train.npy')\nvalidation_data = np.load('vgg16_test.npy')\n\nmodel = Sequential()\nmodel.add(GlobalMaxPooling2D())\n\nmodel.add(Dense(512,activation='relu'))\nmodel.add(Dropout(0.5))\n\nmodel.add(Dense(1,activation='sigmoid'))\n    \nmodel.compile(loss='binary_crossentropy',\n              optimizer=optimizers.RMSprop(lr=1e-5),\n              metrics=['accuracy'])\n\nepoch = 20                            \nbatch_size = 16                      \nhistory = model.fit(train_data,        \n                        train_labels,  \n                        epochs=epoch,\n                        batch_size=batch_size,\n                        verbose=1,\n                        # 検証データと正解ラベル\n                        validation_data=(validation_data,\n                                         validation_labels)\n                        )\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%matplotlib inline\nimport matplotlib.pyplot as plt\n\ndef plot_acc_loss(history):\n    # 精度の推移をプロット\n    plt.plot(history.history['accuracy'],\"-\",label=\"accuracy\")\n    plt.plot(history.history['val_accuracy'],\"-\",label=\"val_acc\")\n    plt.title('accuracy')\n    plt.xlabel('epoch')\n    plt.ylabel('accuracy')\n    plt.legend(loc=\"lower right\")\n    plt.show()\n\n    # 損失の推移をプロット\n    plt.plot(history.history['loss'],\"-\",label=\"loss\",)\n    plt.plot(history.history['val_loss'],\"-\",label=\"val_loss\")\n    plt.title('loss')\n    plt.xlabel('epoch')\n    plt.ylabel('loss')\n    plt.legend(loc='upper right')\n    plt.show()\n    \n# 損失と精度をグラフに出力\nplot_acc_loss(history)","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}