{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":30746,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"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":"2024-07-24T14:13:32.151966Z","iopub.execute_input":"2024-07-24T14:13:32.152371Z","iopub.status.idle":"2024-07-24T14:13:32.162293Z","shell.execute_reply.started":"2024-07-24T14:13:32.152344Z","shell.execute_reply":"2024-07-24T14:13:32.161061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 犬か猫か判別するシステムを作る\n\n## 犬か猫の写真を読み込み、犬ならば1猫ならば0と判別できるように学習させる","metadata":{}},{"cell_type":"markdown","source":"# ①データ準備","metadata":{}},{"cell_type":"markdown","source":"### zipファイルの解凍","metadata":{}},{"cell_type":"code","source":"import zipfile \n\n# train.zipの解凍\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/train')\n\n# test.zipの解凍\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/test')","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:32.164583Z","iopub.execute_input":"2024-07-24T14:13:32.165108Z","iopub.status.idle":"2024-07-24T14:13:44.296508Z","shell.execute_reply.started":"2024-07-24T14:13:32.165072Z","shell.execute_reply":"2024-07-24T14:13:44.295165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### ライブラリの追加","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd\nimport os\nimport shutil\nimport cv2\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nimport tensorflow.keras as keras\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import load_model\nimport csv","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:44.298291Z","iopub.execute_input":"2024-07-24T14:13:44.298730Z","iopub.status.idle":"2024-07-24T14:13:44.304356Z","shell.execute_reply.started":"2024-07-24T14:13:44.298685Z","shell.execute_reply":"2024-07-24T14:13:44.303297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 訓練データとテストデータフォルダの作成","metadata":{}},{"cell_type":"code","source":"train_dir = '/kaggle/working/train/train'","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:44.306690Z","iopub.execute_input":"2024-07-24T14:13:44.307557Z","iopub.status.idle":"2024-07-24T14:13:44.316768Z","shell.execute_reply.started":"2024-07-24T14:13:44.307524Z","shell.execute_reply":"2024-07-24T14:13:44.315655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dir = '/kaggle/working/test/test'","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:44.318181Z","iopub.execute_input":"2024-07-24T14:13:44.318554Z","iopub.status.idle":"2024-07-24T14:13:44.331790Z","shell.execute_reply.started":"2024-07-24T14:13:44.318524Z","shell.execute_reply":"2024-07-24T14:13:44.330670Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 画像サイズを統一","metadata":{}},{"cell_type":"code","source":"IMG_SIZE = 64","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:44.333296Z","iopub.execute_input":"2024-07-24T14:13:44.333708Z","iopub.status.idle":"2024-07-24T14:13:44.344188Z","shell.execute_reply.started":"2024-07-24T14:13:44.333676Z","shell.execute_reply":"2024-07-24T14:13:44.342968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ②データを読み込む関数の作成\n\n### defで関数を定義している\n### forでファイルの読み込みとファイルの取得を繰り返している\n### if で犬なら「１」猫なら「0」と定義し分類している","metadata":{}},{"cell_type":"code","source":"def load_data(data_dir, sample_size=1000):\n    images = [] \n    labels = [] \n    files = os.listdir(data_dir)[:sample_size]\n    \n    for file in files:\n        img_path = os.path.join(data_dir, file)\n        img = cv2.imread(img_path) \n        if img is not None:\n            img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))\n            images.append(img) \n            label = 1 if 'dog' in file else 0 \n            labels.append(label)\n        else: print(f'error{img_path}')\n    return np.array(images) / 255.0, np.array(labels)","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:44.345967Z","iopub.execute_input":"2024-07-24T14:13:44.346387Z","iopub.status.idle":"2024-07-24T14:13:44.357222Z","shell.execute_reply.started":"2024-07-24T14:13:44.346350Z","shell.execute_reply":"2024-07-24T14:13:44.356204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### trainデータとtestデータを読み込む","metadata":{}},{"cell_type":"code","source":"X_train, y_train = load_data(train_dir, sample_size=1000)\nX_test, y_test = load_data(test_dir, sample_size=500)","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:44.358569Z","iopub.execute_input":"2024-07-24T14:13:44.358956Z","iopub.status.idle":"2024-07-24T14:13:45.883289Z","shell.execute_reply.started":"2024-07-24T14:13:44.358925Z","shell.execute_reply":"2024-07-24T14:13:45.882066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ③データ拡張\n\n","metadata":{}},{"cell_type":"code","source":"datagen = ImageDataGenerator(\n    rotation_range=20, # 画像の回転\n    width_shift_range=0.2, # 水平に移動\n    height_shift_range=0.2, # 垂直に移動\n    shear_range=0.2, # せん断\n    zoom_range=0.2, # 拡大\n    horizontal_flip=True, # 水平に反転\n    fill_mode='nearest' # 空白処理\n)","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:45.884635Z","iopub.execute_input":"2024-07-24T14:13:45.884989Z","iopub.status.idle":"2024-07-24T14:13:45.890828Z","shell.execute_reply.started":"2024-07-24T14:13:45.884958Z","shell.execute_reply":"2024-07-24T14:13:45.889532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ④モデルの作成\n\n### 今回使用する説明変数である「畳み込みニュートラルネットワーク」を導入する","metadata":{}},{"cell_type":"markdown","source":"#### derでライブラリと関数を導入する\n\n#### モデルを追加していき、定義する\n\n#### Conv2Dの32(画像のエッジや色の変化などの低レベルの特徴を抽出)、64(初期層で抽出された基本的な特徴を基に、より複雑なパターンや形状を検出)、128(全体の構造や詳細なパターンなど、より高度な特徴を抽出)は、畳み込み層で使用するフィルターの数を表し、それぞれ異なる層で異なる特徴を抽出するために使用。これにより、モデルは入力画像から多様な特徴を学習","metadata":{}},{"cell_type":"code","source":"def create_model(neuron):\n    Dense = keras.layers.Dense\n    Conv2D = keras.layers.Conv2D\n    MaxPooling2D = keras.layers.MaxPooling2D\n    Flatten = keras.layers.Flatten\n    Dropout = keras.layers.Dropout\n    \n    model = keras.models.Sequential()\n    \n    \n   \n    model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)))\n    \n    model.add(MaxPooling2D((2, 2)))\n    \n    model.add(Conv2D(64, (3, 3), activation='relu'))\n    \n    model.add(MaxPooling2D((2, 2)))\n    \n    model.add(Conv2D(128, (3, 3), activation='relu'))\n    \n    model.add(MaxPooling2D((2, 2)))\n    \n    model.add(Flatten())\n   \n    model.add(Dense(neuron, activation='relu'))\n    \n    model.add(Dropout(0.5))\n    \n    model.add(Dense(1, activation='sigmoid'))\n\n    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:45.894050Z","iopub.execute_input":"2024-07-24T14:13:45.894425Z","iopub.status.idle":"2024-07-24T14:13:45.906834Z","shell.execute_reply.started":"2024-07-24T14:13:45.894395Z","shell.execute_reply":"2024-07-24T14:13:45.905645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ⑤モデルを保存する・ロードする関数を導入","metadata":{}},{"cell_type":"code","source":"def save_model(model, filename):\n    model.save(filename)","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:45.908548Z","iopub.execute_input":"2024-07-24T14:13:45.909567Z","iopub.status.idle":"2024-07-24T14:13:45.919185Z","shell.execute_reply.started":"2024-07-24T14:13:45.909524Z","shell.execute_reply":"2024-07-24T14:13:45.918046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_existing_model(filename):\n    return load_model(filename)","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:45.920745Z","iopub.execute_input":"2024-07-24T14:13:45.921272Z","iopub.status.idle":"2024-07-24T14:13:45.931249Z","shell.execute_reply.started":"2024-07-24T14:13:45.921229Z","shell.execute_reply":"2024-07-24T14:13:45.930115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ⑥モデルの学習\n\n## 3回学習した後、グラフ化し評価する","metadata":{}},{"cell_type":"code","source":"def fit_epoch(neuron, batch, epochs, initial_epoch=0, model_filename='model.h5'):\n    if initial_epoch == 0:model = create_model(neuron)\n    else: model = load_existing_model(model_filename) \n        \n    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])\n    hist = model.fit(datagen.flow(X_train, y_train, batch_size=batch),\n                     steps_per_epoch=len(X_train) // batch,\n                     validation_data=(X_test, y_test),\n                     epochs=epochs,\n                     initial_epoch=initial_epoch,\n                     verbose=1)\n    # モデルの評価\n    score = model.evaluate(X_test, y_test, verbose=1)\n    print('正解率=', score[1], 'loss=', score[0])\n    \n    # モデルの保存\n    save_model(model, model_filename)\n    \n    # trainデータの精度の表示（折れ線グラフ）\n    plt.plot(hist.history['accuracy'])\n    # testデータの精度の表示（折れ線グラフ）\n    plt.plot(hist.history['val_accuracy'])\n    # タイトルの表示\n    plt.title('Accuracy')\n    # 凡例の表示\n    plt.legend(['train', 'test'], loc='upper left')\n    # グラフの表示\n    plt.show()\n    # trainデータの損失関数の表示（折れ線グラフ）\n    plt.plot(hist.history['loss'])\n    # testデータの損失関数の表示（折れ線グラフ）\n    plt.plot(hist.history['val_loss'])\n    # タイトルの表示\n    plt.title('Loss')\n    # 凡例の表示\n    plt.legend(['train', 'test'], loc='upper left')\n    # グラフの表示\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:45.932640Z","iopub.execute_input":"2024-07-24T14:13:45.933028Z","iopub.status.idle":"2024-07-24T14:13:45.944870Z","shell.execute_reply.started":"2024-07-24T14:13:45.933000Z","shell.execute_reply":"2024-07-24T14:13:45.943755Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"total_epochs = 30  # 全体のエポック数\nneuron = 512  # ニューロン数\nbatch = 8  # バッチの大きさ\nmodel_filename = 'model.h5'  # モデルのファイル名","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:45.946215Z","iopub.execute_input":"2024-07-24T14:13:45.946543Z","iopub.status.idle":"2024-07-24T14:13:45.962045Z","shell.execute_reply.started":"2024-07-24T14:13:45.946516Z","shell.execute_reply":"2024-07-24T14:13:45.960750Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 一回目の学習\nfit_epoch(neuron=neuron, batch=batch, epochs=10, initial_epoch=0, model_filename=model_filename)","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:13:45.963312Z","iopub.execute_input":"2024-07-24T14:13:45.963635Z","iopub.status.idle":"2024-07-24T14:14:32.108496Z","shell.execute_reply.started":"2024-07-24T14:13:45.963607Z","shell.execute_reply":"2024-07-24T14:14:32.107259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 二回目の学習\nfit_epoch(neuron=neuron, batch=batch, epochs=20, initial_epoch=10, model_filename=model_filename)","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:14:32.109937Z","iopub.execute_input":"2024-07-24T14:14:32.110342Z","iopub.status.idle":"2024-07-24T14:15:13.975435Z","shell.execute_reply.started":"2024-07-24T14:14:32.110307Z","shell.execute_reply":"2024-07-24T14:15:13.974261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 三回目の学習\nfit_epoch(neuron=neuron, batch=batch, epochs=30, initial_epoch=20, model_filename=model_filename)","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:15:13.977688Z","iopub.execute_input":"2024-07-24T14:15:13.978392Z","iopub.status.idle":"2024-07-24T14:15:57.112887Z","shell.execute_reply.started":"2024-07-24T14:15:13.978353Z","shell.execute_reply":"2024-07-24T14:15:57.111706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ⑦予測結果をCSVファイルに保存","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport cv2\nimport tensorflow.keras as keras\nfrom tensorflow.keras.models import load_model\n\n# 定数の設定\nIMG_SIZE = 64  # 画像のサイズ\ntest_dir = '/kaggle/working/test/test'  # テストデータのディレクトリ\nmodel_filename = 'model.h5'  # 学習したモデルのファイル名\noutput_csv = '/kaggle/working/submission.csv'  # 提出するCSVファイルのパス\n\n# 画像データの読み込み関数\ndef load_test_data(data_dir):\n    images = []\n    filenames = os.listdir(data_dir)\n    for file in filenames:\n        img_path = os.path.join(data_dir, file)\n        img = cv2.imread(img_path)\n        if img is not None:\n            img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))\n            images.append(img)\n        else:\n            print(f'Error reading {img_path}')\n    return np.array(images) / 255.0, filenames\n\n# テストデータの読み込み\nX_test, test_filenames = load_test_data(test_dir)\n\n# モデルの読み込み\nmodel = load_model(model_filename)\n\n# 予測の実行\npredictions = model.predict(X_test)\n\n# 予測結果を0または1に変換\npredictions = (predictions > 0.5).astype(int).flatten()\n\n# CSVファイルの作成\noutput_df = pd.DataFrame({\n    'id': [os.path.splitext(f)[0] for f in test_filenames],  # ファイル名から拡張子を除去してIDにする\n    'label': predictions\n})\noutput_df.to_csv(output_csv, index=False)\n\nprint(f'CSVファイル {output_csv} を作成しました')","metadata":{"execution":{"iopub.status.busy":"2024-07-24T14:15:57.114380Z","iopub.execute_input":"2024-07-24T14:15:57.114811Z","iopub.status.idle":"2024-07-24T14:16:24.039195Z","shell.execute_reply.started":"2024-07-24T14:15:57.114755Z","shell.execute_reply":"2024-07-24T14:16:24.037943Z"},"trusted":true},"execution_count":null,"outputs":[]}]}