{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport json\n\nimport numpy as np\nimport pandas as pd\nimport seaborn as sn # Pythonのデータ可視化ライブラリ(matplotlibと比べて少ないコードで図が描ける)\nimport matplotlib.pyplot as plt # Pythonのデータ可視化ライブラリ\nimport cv2                  # OpenCV-Pythonのこと。画像の読み込み、作成、編集、リサイズ、反転など多様なことが可能。\nimport albumentations as A  # 画像データを加工するライブラリ\nfrom sklearn import metrics as sk_metrics # スコア関数、パフォーマンスメトリック(精度とか)、ペアワイズメトリック(XとYの距離・親和性を求める？）、距離計算\n# metrics 参考：https://data-analysis-stats.jp/python/%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E8%A9%95%E4%BE%A1%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%AEsklearn-metrics/\n\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# キャッサバの分類のコンペ\n### 目的\n- アフリカ諸国の食糧供給に物質的な害をもたらすいくつかの病気を区別することが目的です。\n\n### 概要\n- 本コンペで提供されているキャッサバの画像には5種類の画像が提供されています。4種類は病気になっているキャッサバで残り1つが健康なキャッサバです。どの画像どの種類に分類されるかは、label_num_to_disease_map.json ファイルに記載されています。\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"BASE_DIR = \"../input/cassava-leaf-disease-classification/\"\n# open->ファイルのオープン、os.path.join->文字列の連結、file.read()->ファイルの読み込み\n# json.loads->JSON形式のデータをdict型に変換\nwith open(os.path.join(BASE_DIR, \"label_num_to_disease_map.json\")) as file:\n    map_classes = json.loads(file.read())\n    # dictのキーをintに変換\n    map_classes = {int(k) : v for k, v in map_classes.items()}\n\n# JSON形式のデータを出力\nprint(json.dumps(map_classes, indent=4))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"# 画像ファイルの枚数を表示\ninput_files = os.listdir(os.path.join(BASE_DIR, \"train_images\"))\nprint(f\"Number of train images: {len(input_files)}\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_shapes = {}\n# キャッサバの画像のサイズを確認\n# cv2->OpenCV-Pythonのこと。画像の読み込み、作成、編集、リサイズ、反転など多様なことが可能。\n# cv2.imread()->画像ファイルから読み込み  image.shape-> 画像サイズ取得\n# img_shapes.get(image.shape, 0)->image.shpaeで取得したサイズをキーになり、そのキーが存在しなければ新しくそのキーを作成、キーに対応する値を0とする。\nfor image_name in os.listdir(os.path.join(BASE_DIR, \"train_images\"))[:300]:\n    image = cv2.imread(os.path.join(BASE_DIR, \"train_images\", image_name))\n    img_shapes[image.shape] = img_shapes.get(image.shape, 0) + 1\n\nprint(img_shapes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ラベルに対応するクラス名を対応付けたデータを作成する。\ndf_train = pd.read_csv(os.path.join(BASE_DIR, \"train.csv\"))\n\ndf_train[\"class_name\"] = df_train[\"label\"].map(map_classes)\n\ndf_train","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ラベルごとの画像の枚数をプロット\n# 数も見たいけど、ソースコードの書き方が分からなかった。\n# 不均衡データになっている。\nplt.figure(figsize=(8, 4))\nsn.countplot(y=\"label\", data=df_train);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 可視化"},{"metadata":{"trusted":true},"cell_type":"code","source":"def visualize_batch(image_ids, labels):\n    # figure->グラフや文字など、全てが描かれるウインドウ\n    # ウィンドサイズを設定\n    plt.figure(figsize=(16, 12))\n    \n    # ind=0から始まるカウンタ\n    for ind, (image_id, label) in enumerate(zip(image_ids, labels)):\n        # 画像の位置づけ、3x3(9個)の配置があり、ind+1で配置のどこに割り当てるかを決定\n        plt.subplot(3, 3, ind + 1)\n        image = cv2.imread(os.path.join(BASE_DIR, \"train_images\", image_id))\n        # OpenCVの色の順番はBGRであるため、RGBに変換する。(入力の画像がRGBだから？)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\n        # imshowとshowの両方を使う必要が分からなかった。\n        plt.imshow(image)\n        plt.title(f\"Class: {label}\", fontsize=12)\n        # 軸線とラベルをオフにする\n        plt.axis(\"off\")\n    \n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ランダムに9個のデータを取り出す\ntmp_df = df_train.sample(9)\n# 対象ラベルの値を取り出す\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"class_name\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 0 - CBB - Cassava Bacterial Blight\n"},{"metadata":{},"cell_type":"markdown","source":"0 - CBB - Cassava Bacterial Blight\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"# labelが0のデータだけを取得\ntmp_df = df_train[df_train[\"label\"] == 0]\nprint(f\"Total train images for class 0: {tmp_df.shape[0]}\")\n\ntmp_df = tmp_df.sample(9)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"label\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 1 - CBSD - Cassava Brown Streak Disease"},{"metadata":{"trusted":true},"cell_type":"code","source":"tmp_df = df_train[df_train[\"label\"] == 1]\nprint(f\"Total train images for class 1: {tmp_df.shape[0]}\")\n\ntmp_df = tmp_df.sample(9)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"label\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 2 - CGM - Cassava Green Mottle\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"tmp_df = df_train[df_train[\"label\"] == 2]\nprint(f\"Total train images for class 2: {tmp_df.shape[0]}\")\n\ntmp_df = tmp_df.sample(9)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"label\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 3 - CMD - Cassava Mosaic Disease\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"tmp_df = df_train[df_train[\"label\"] == 3]\nprint(f\"Total train images for class 3: {tmp_df.shape[0]}\")\n\ntmp_df = tmp_df.sample(9)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"label\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 4 - Healthy\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"tmp_df = df_train[df_train[\"label\"] == 4]\nprint(f\"Total train images for class 4: {tmp_df.shape[0]}\")\n\ntmp_df = tmp_df.sample(9)\nimage_ids = tmp_df[\"image_id\"].values\nlabels = tmp_df[\"label\"].values\n\nvisualize_batch(image_ids, labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Augmentation Examples\n"},{"metadata":{},"cell_type":"markdown","source":"画像の水増しは、既存の画像から新しい学習例を作成するプロセスです。新しい画像は、明るさを変更したり、画像の一部を切り出したり、画像の反転（上下・左右）することで作成できます。"},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_augmentation(image_id, transform):\n    plt.figure(figsize=(16, 4))\n    img = cv2.imread(os.path.join(BASE_DIR, \"train_images\", image_id))\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n\n    plt.subplot(1, 3, 1)\n    plt.imshow(img)\n    plt.axis(\"off\")\n\n    plt.subplot(1, 3, 2)\n    x = transform(image=img)[\"image\"]\n    plt.imshow(x)\n    plt.axis(\"off\")\n\n    plt.subplot(1, 3, 3)\n    x = transform(image=img)[\"image\"]\n    plt.imshow(x)\n    plt.axis(\"off\")\n    \n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# ShiftScaleRotate->画像をランダムに平行移動、拡大縮小、回転する。\n# shift_limit->平行移動の範囲,scale_limit->平行移動の範囲。rotate_limit->回転の範囲。interpolation->補完方法。border_mode->\n# 参考URL:https://qiita.com/kurilab/items/b69e1be8d0224ae139ad\n# ShiftScaleRotateの公式マニュアルをみつけることができなかった。\ntransform_shift_scale_rotate = A.ShiftScaleRotate(\n    p=1.0, \n    shift_limit=(-0.3, 0.3), \n    scale_limit=(-0.1, 0.1), \n    rotate_limit=(-180, 180), \n    interpolation=0, \n    border_mode=4, \n)\n\nplot_augmentation(\"1003442061.jpg\", transform_shift_scale_rotate)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 矩形領域のドロップアウト（虫食い）\n# min_holes/max_holes->ゼロに落とす領域数の最小・最大数。min_height/max_height-> 領域の最小・最大の高さ。min_width/max_width->領域の最小・最大幅。\ntransform_coarse_dropout = A.CoarseDropout(\n    p=1.0, \n    max_holes=100, \n    max_height=50, \n    max_width=50, \n    min_holes=30, \n    min_height=20, \n    min_width=20,\n)\n\nplot_augmentation(\"1003442061.jpg\", transform_coarse_dropout)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Compose->複数の処理をまとめる\n# 上記２つの画像の反転と虫食いの処理をまとめている\ntransform = A.Compose(\n    transforms=[\n        transform_shift_scale_rotate,\n        transform_coarse_dropout,\n    ],\n    p=1.0,\n)\n\nplot_augmentation(\"1003442061.jpg\", transform)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Submission Example\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"# サンプルの読み込み\ndf_sub = pd.read_csv(\"../input/cassava-leaf-disease-classification/sample_submission.csv\", index_col=0)\ndf_sub\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# テストイメージは1つだけ\nos.listdir(os.path.join(BASE_DIR, \"test_images\"))\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- コードのコンペであるため、テストデータに使われる画像は1枚だけです。フルセットの画像は採点の時に使われます。テストデータには15000枚のデータ使われます。\n- このコンペティションの指標は「精度」です。\n- 精度:総サンプル数に対する正しく予測されたサンプル数の比率"},{"metadata":{"trusted":true},"cell_type":"code","source":"# すべての例に対して1つのクラスのみを選択した場合の学習セットの精度を計算\nfor pred_class in range(0, 5):\n    y_true = df_train[\"label\"].values\n    # full_like->第1引数と同じ配列を作成し、その値を第2引数の値とする。\n    # ex. y_true=[0,1,3,4,2,3,4,4] -> pred_class=[0,0,0,0,0,0,0,0](1回目のループ)\n    y_pred = np.full_like(y_true, pred_class)\n    # 精度をスコアとして出力\n    print(f\"accuracy score (predict {pred_class}): {sk_metrics.accuracy_score(y_true, y_pred):.3f}\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"クラスの不均衡が大きいので，最も頻度の高いクラス(class:3)を予測すれば，この場合の精度はより高くなる。"},{"metadata":{"trusted":true},"cell_type":"code","source":"# 頻度の高いクラス3だけのデータを作成する。\ndf_sub[\"label\"] = 3\ndf_sub.to_csv(\"submission.csv\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"評価のために結果を提出すると、0.614という精度になります。これは、公開テストの分布上でもクラスの不均衡があることを示しているのかもしれません。"},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}