{"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":"# 必要なライブラリのimport\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n%matplotlib inline\nimport seaborn as sns\nfrom sklearn.preprocessing import OneHotEncoder\nfrom sklearn.model_selection import KFold\nfrom sklearn.utils import shuffle\nimport os\nimport re\nimport glob\nimport shutil\nimport gc\nimport pyarrow as pa\nimport dask as da\nfrom pathlib import Path\n\n# matplotlibの日本語化対応\nimport japanize_matplotlib\n\n# データフレーム表示用関数\nfrom IPython.display import display\n\n# 表示オプション調整\n# numpyの浮動小数点の表示精度\nnp.set_printoptions(suppress=True, precision=4)\n\n# pandasでの浮動小数点の表示精度\npd.options.display.float_format = '{:.4f}'.format\n\n# データフレームですべての項目を表示\npd.set_option(\"display.max_columns\",None)\n\n# グラフのデフォルトフォント指定\nplt.rcParams[\"font.size\"] = 14\n\n# グラフの表示方法調整\nsns.set(rc={'figure.figsize':(12,5)});\nplt.figure(figsize=(12,5));\n\n# 乱数の種\nrandom_seed = 123","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# タイマー\n# https://github.com/nyk510/vivid/blob/master/vivid/utils.py\nfrom contextlib import contextmanager\nfrom time import time\n\nclass Timer:\n    def __init__(self, logger=None, format_str='{:.3f}[s]', prefix=None, suffix=None, sep=' '):\n\n        if prefix: format_str = str(prefix) + sep + format_str\n        if suffix: format_str = format_str + sep + str(suffix)\n        self.format_str = format_str\n        self.logger = logger\n        self.start = None\n        self.end = None\n\n    @property\n    def duration(self):\n        if self.end is None:\n            return 0\n        return self.end - self.start\n\n    def __enter__(self):\n        self.start = time()\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        self.end = time()\n        out_str = self.format_str.format(self.duration)\n        if self.logger:\n            self.logger.info(out_str)\n        else:\n            print(out_str)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 機械学習とは\n機械学習とは、ざっと言ってしまうとあるデータ X を入力として対応する予測値 y を取り出すような対応関係を作成することです。\n\n例：タイタニック号で、乗客が生きるか死ぬかを予測する問題だと X は乗客の年齢, 性別, 船室のグレード… など乗客に紐づく情報のことを指します。通常、この情報のことを特徴量とよびます。\n\n特徴量 X と 予測値 y が用意できれば学習用データ (X - y の関係がわかっているデータ) を元にして X をいれて y になるようにモデルを調整する。この調整の段階を学習とよびます。学習には様々なアルゴリズムがあるが、X, y を用意しなくてはならない部分は基本的に変わらないです。","metadata":{}},{"cell_type":"markdown","source":"# 今回のコンペに関して","metadata":{}},{"cell_type":"markdown","source":"コンペ自体のデータサイズが大きいのでデータハンドリングが僕たちに取っては肝になりそうです（この辺をよく知っている人教えてください！）\n\n### データの読み込みに関して\n* 形式を変えたデータセットをpandasで読み込む\n  * [`feather`形式](https://www.kaggle.com/datasets/munumbutt/amexfeather) or [`Parquet`形式](https://www.kaggle.com/datasets/odins0n/amex-parquet)\n* [`pyspark`](https://www.kaggle.com/code/rakkaalhazimi/export-large-dataset-to-spark) or [`dask`](https://docs.dask.org/en/latest/dataframe.html) で読み込む\n\n### サイズが大きい場合の対処方法は以下のkaggle notebookを参考にしてみてください\n\n[> How to Work with BIG Datasets on 16G RAM (+Dask)](https://www.kaggle.com/code/yuliagm/how-to-work-with-big-datasets-on-16g-ram-dask)\n\n上記notebookの内容概要\n* TIP 1 - 使用していない変数を [`delete`](https://www.sejuku.net/blog/74447) するか & gc.collect()` で[ガベージコレクション](https://techacademy.jp/magazine/19437)(不要になったメモリ領域を開放して再利用する機能)をする\n* TIP 2 - データセット内の各カラムのデータタイプを予め定義しておく\n  * eg: 本来 float64 だったものを -> float32 と定義してサイズを圧縮する\n* TIP 3 - 読み込むデータセットを選択する (including generating your own subsamples)\n  * 読み込む行数を選ぶ\n  * (`skiprows`) で[読み飛ばす行数を指定する](https://bit.ly/3O90Ze7)\n  * 読み飛ばすリストを作成して、読み飛ばす（以下例）\n    * ```\n      skiplines = np.random.choice(np.arange(1, lines), size=lines-1-1000000, replace=False)\n      skiplines=np.sort(skiplines)\n      train = pd.read_csv('../input/train.csv', skiprows=skiplines, dtype=dtypes)\n      ```\n* TIP 4 - バッチ処理をする\n  * ひとまとまりのデータに対して、一連の処理を連続で実行する処理方式のこと。大きなデータに関しても、設定したデータ数(チャンク)ごとに処理をする\n* TIP 5 - 特定のカラムのみ `import` する\n  * 450,000行 × 150カラム より 100万行 × 2カラム の方がメモリ消費が少ないことは容易に想像できる\n* TIP 6 - groupby などの処理をするときも一部カラムの一部データのみにするˆ\n* TIP 7 - `Dask` を使用する。\n  * [DaskについてのQiita記事](https://qiita.com/simonritchie/items/e174f243bc03fb25462e)","metadata":{}},{"cell_type":"markdown","source":"## コンペの概要\n* コンペ名：[American Express - Default Prediction](https://www.kaggle.com/competitions/amex-default-prediction)\n\n* 目的：毎月の顧客プロファイルから、顧客がクレジットカードの残高分を将来返済しない確率を予測すること\n  * ターゲットのバイナリ変数は、最新のクレジットカード明細書から18ヶ月間のパフォーマンスウィンドウを観察することによって計算され、顧客が最新の明細書の日付から120日以内に支払額を支払わない場合、デフォルトとみなされる。\n\n* 評価方法(Evaluation)\n  * このコンペではクレカのデフォルト率を予測する。サブミットはちょっと特殊な評価方法で評価される。以下の通り:\n    * ```\n      M = 0.5*(G+D)  (*G = 正規化ジニ係数, D = デフォルト率 4% )\n      ```\n      機械学習における `正規化ジニ係数` は経済学などで使用される ジニ係数とは違うので注意です。以下記事を参照にしてみてください\n      * [機械学習のモデル評価、説明可能性のための指標　その１。ジニ係数とAUC](https://qiita.com/Derek/items/4ded249f7a75f8da176c)\n      * [DataRobot](https://docs.datarobot.com/ja/docs/modeling/reference/model-detail/opt-metric.html#gini-coefficient)\n      * [GINI and AUC relationship](https://stats.stackexchange.com/questions/342329/gini-and-auc-relationship)\n      * [Why use Normalized Gini Score instead of AUC as evaluation?](https://stats.stackexchange.com/questions/306287/why-use-normalized-gini-score-instead-of-auc-as-evaluation)","metadata":{}},{"cell_type":"markdown","source":"# データ管理環境整備\n\n≒ディレクトリ整備","metadata":{}},{"cell_type":"code","source":"# # input_dir（input directory） を作ります\ncurrent_note_path = os.path.dirname(os.path.abspath('__file__'))\nINPUT_DIR = os.path.join(current_note_path, \"data\")\n\n# INPUT_DIRがまだ作られていなければ作成\nif not os.path.isdir(INPUT_DIR):\n    os.mkdir(INPUT_DIR)\n\n# output_dir(output directory) を作ります\nOUTPUT_DIR = os.path.join(current_note_path, 'outputs')\n\n# OUTPUT_DIRがまだ作られていなければ作成\nif not os.path.isdir(OUTPUT_DIR):\n    os.mkdir(OUTPUT_DIR)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 一度やったらコメントアウトします\n\n# # csvファイルを `data` ディレクトリ（=フォルダー） に移動させます\n# unique_dir_names = []\n# for f in Path(f'{current_note_path}').rglob('*.csv'):\n#     unique_dir_names.append(f)\n\n# for file in list(set(unique_dir_names)):\n#     print(f'moved file: {file}')\n#     shutil.move(f'{file}', f'{INPUT_DIR}')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# csv(or any file)を簡単に読み込めるようにする関数\n# csv を読み取る関数を設定したあげると、pathや拡張子を書かずに読み込めるので入力が楽になります\n\n# 通常のcsvファイルを読み取るときは以下\ndef read_csv(name, **kwrgs):\n    path = os.path.join(INPUT_DIR, name + '.csv')\n    print(f'Load: {path}')\n    return pd.read_csv(path, **kwrgs)\n\n# 今回はparquet形式を読み込むので別途用意\ndef read_parquet(name, **kwrgs):\n    path = os.path.join(INPUT_DIR, name + '.parquet')\n    print(f'Load: {path}')\n    return pd.read_parquet(path, **kwrgs)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# データ読み込み","metadata":{}},{"cell_type":"markdown","source":"前記の通り、データサイズが大きく、安易に `pandas` などを使ってもローカルではメモリが足りないので、ここではcsv形式を `parquet` 形式に変えてimport します\n\n(*本来は自分でcsv -> parquet形式に変える必要がありますが、心優しい人がparquet形式にしてくれているのでそれを参照します。)\n* [該当データダウンロードページ](https://www.kaggle.com/datasets/odins0n/amex-parquet)\n* [Load Parquet Files with Low Memory](https://www.kaggle.com/code/odins0n/load-parquet-files-with-low-memory)\n* [parquetデータを使用したEDA](https://www.kaggle.com/code/odins0n/amex-default-prediction-detailed-eda)","metadata":{}},{"cell_type":"code","source":"# parquet で import をするのでもメモリが足りない人はまた教えてください！\n\ntest_df = read_parquet('test_data')\ntrain_df = read_parquet('train_data')\ntrain_labels = read_csv('train_labels')\nsample_sub = read_csv('sample_submission')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ガベージコレクション\ngc.collect()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.info()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 以下のカラムは頻出と考えられ、毎回入力するのはめんどくさいので、ポップアップされるように定義します\ncustomer_ID = 'customer_ID'","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 各テーブルの概説\n\n* データについて\n  * データセットには各顧客の特徴が各明細書日付ごとに集約されたものが含まれている。特徴は匿名化され、正規化されており、以下のカテゴリに分類されている（カラムの prefix を見ると分かる）:\n    * D_*: Delinquency variables\n    * S_*: Spend variables\n    * P_*: Payment variables\n    * B_*: Balance variables\n    * R_*: Risk variables\n  * 以下のカラムはカテゴリ変数である:\n    * B_30, B_38, D_63, D_64, D_66, D_68, D_114, D_116, D_117, D_120, D_126","metadata":{}},{"cell_type":"markdown","source":"# EDA (データ確認)\n\n> これ以降のデータハンドリングは Dask packageを使おうと思います（僕もまだ勉強中です）\n\nこの辺の記事を読んでなんとなく理解してみてください！\n* [PythonのDaskをしっかり調べてみた（大きなデータセットを快適に扱う）](https://qiita.com/simonritchie/items/e174f243bc03fb25462e)\n\n> EDA はこの辺もまずは参考にしてみてもいいと思います\n* [AMEX EDA (Comparison of training and test data)](https://www.kaggle.com/code/onodera1/amex-eda-comparison-of-training-and-test-data)","metadata":{}},{"cell_type":"code","source":"train_df.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 欠損値・異常値確認","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 前処理 + 特徴量エンジニアリング","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## カテゴリ変数の変換","metadata":{}},{"cell_type":"markdown","source":"## データマージ","metadata":{}},{"cell_type":"markdown","source":"# 学習・予測・サブミットファイル作成","metadata":{}},{"cell_type":"markdown","source":"## モデル構築","metadata":{}},{"cell_type":"markdown","source":"## モデル評価","metadata":{}},{"cell_type":"markdown","source":"## サブミットファイル作成","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}