{"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":"markdown","source":"# モジュールをインポート","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport gc\nimport time\nimport warnings\n\nfrom contextlib import contextmanager\nfrom matplotlib import pyplot as plt\nfrom lightgbm import LGBMClassifier\nfrom sklearn.model_selection import KFold, StratifiedKFold\nfrom sklearn.metrics import roc_auc_score, roc_curve\n\npd.options.display.max_columns = None\npd.options.display.max_rows = 100\npd.options.display.float_format = '{:.1f}'.format\n\nwarnings.simplefilter(action='ignore', category=FutureWarning)\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-07-06T07:22:48.389173Z","iopub.execute_input":"2023-07-06T07:22:48.391912Z","iopub.status.idle":"2023-07-06T07:22:51.224570Z","shell.execute_reply.started":"2023-07-06T07:22:48.391796Z","shell.execute_reply":"2023-07-06T07:22:51.222754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# データインプット","metadata":{}},{"cell_type":"code","source":"transactions = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/transactions_train.csv\")\ncustomers = pd.read_csv(\"../input/h-and-m-personalized-fashion-recommendations/customers.csv\")","metadata":{"execution":{"iopub.status.busy":"2023-07-06T07:22:51.227518Z","iopub.execute_input":"2023-07-06T07:22:51.228069Z","iopub.status.idle":"2023-07-06T07:24:29.240252Z","shell.execute_reply.started":"2023-07-06T07:22:51.228020Z","shell.execute_reply":"2023-07-06T07:24:29.234229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 関数","metadata":{}},{"cell_type":"markdown","source":"## 基本","metadata":{}},{"cell_type":"code","source":"#Baseとなる顧客ID 基本的にここにどんどんLeft joinしていく方針\ndef create_target_customers(transactions,pre_start_date,pre_end_date): #最終的にはstart_ym, end_ymを引数に指定\n    transactions['t_dat_dt'] = pd.to_datetime(transactions['t_dat'])\n    start_ym = pd.to_datetime(pre_start_date) \n    end_ym = pd.to_datetime(pre_end_date)\n    transaction_target_ym = transactions.query('t_dat_dt >= @start_ym & t_dat_dt < @end_ym').assign(target_customer = 1)\n    target_customers = transaction_target_ym[['customer_id','target_customer']].drop_duplicates()\n    return target_customers\n\n#ただcustomersの情報を取得するだけ\ndef create_customers_feature(customers): \n    return customers\n","metadata":{"execution":{"iopub.status.busy":"2023-07-06T07:24:29.246121Z","iopub.execute_input":"2023-07-06T07:24:29.247145Z","iopub.status.idle":"2023-07-06T07:24:29.271405Z","shell.execute_reply.started":"2023-07-06T07:24:29.247067Z","shell.execute_reply":"2023-07-06T07:24:29.268694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 目的変数作成","metadata":{}},{"cell_type":"code","source":"#目的変数を作成するための関数(create_target_customers()で作成したデータフレームを用いる)\ndef create_target_variable(transactions,target_customers,pos_start_date,pos_end_date):\n    #観察期間での購入フラグ作成\n    transactions['t_dat_dt'] = pd.to_datetime(transactions['t_dat'])\n    pos_start_ym = pd.to_datetime(pos_start_date) #ここはあとで関数の引数で指定できるようにする\n    pos_end_ym = pd.to_datetime(pos_end_date)\n    pos_transaction_target_ym = transactions.query('t_dat_dt >= @pos_start_ym & t_dat_dt < @pos_end_ym').assign(pos_target_customer = 1)\n    pos_target_customers = pos_transaction_target_ym[['customer_id','pos_target_customer']].drop_duplicates()\n    \n    #目的変数の作成\n    target_customers=pd.merge(target_customers, pos_target_customers, how=\"left\", on=\"customer_id\")\n    target_customers[\"pos_target_customer\"]=target_customers[\"pos_target_customer\"].fillna(0).astype(\"int\")\n    target_customers = target_customers[['customer_id','pos_target_customer']].drop_duplicates().rename(columns={\"pos_target_customer\":\"target\"})\n\n    return target_customers\n","metadata":{"execution":{"iopub.status.busy":"2023-07-06T07:24:29.277244Z","iopub.execute_input":"2023-07-06T07:24:29.278673Z","iopub.status.idle":"2023-07-06T07:24:29.303226Z","shell.execute_reply.started":"2023-07-06T07:24:29.278529Z","shell.execute_reply":"2023-07-06T07:24:29.300390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 特徴量作成","metadata":{}},{"cell_type":"markdown","source":"## モデル作成","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n@contextmanager\ndef timer(title):\n    t0 = time.time()\n    yield\n    print(\"{} - done in {:.0f}s\".format(title, time.time() - t0))\n\n# ダミー変数の作成(one-hot encording)\ndef one_hot_encoder(df, nan_as_category = True):\n    original_columns = list(df.columns)\n    categorical_columns = [col for col in df.columns if df[col].dtype == 'object']\n    df = pd.get_dummies(df, columns= categorical_columns, dummy_na= nan_as_category)\n    new_columns = [c for c in df.columns if c not in original_columns]\n    return df, new_columns\n\n#入力するデータフレームの欲しい変数\n\n# LightGBMを使用して、KFoldまたはStratified KFoldを用いたGBDT（Gradient Boosting Decision Tree）を実行する。\n# Parameters from Tilii kernel: https://www.kaggle.com/tilii7/olivier-lightgbm-parameters-by-bayesian-opt/code\ndef kfold_lightgbm(df, num_folds, stratified = False, debug= True):\n    # トレーニング/バリデーションデータとテストデータに分割する。\n    train_df = df[df[\"target\"].notnull()]\n    test_df = df[df[\"target\"].isnull()]\n    print(\"Starting LightGBM. Train shape: {}, test shape: {}\".format(train_df.shape, test_df.shape))\n    del df\n    gc.collect()\n    # クロスバリデーション\n    ## stratifiedの値で層化KFoldかKFoldのどちらのモデルを使うか決める。\n    if stratified:\n        folds = StratifiedKFold(n_splits= num_folds, shuffle=True, random_state=1001)\n    else:\n        folds = KFold(n_splits= num_folds, shuffle=True, random_state=1001)\n    # 結果を格納するための配列やデータフレームを作成する。\n    oof_preds = np.zeros(train_df.shape[0])\n    sub_preds = np.zeros(test_df.shape[0])\n    feature_importance_df = pd.DataFrame()\n    tmp_feats = [f for f in train_df.columns if f not in [\"target\",'customer_id','postal_code','index']]\n    categorical_feature = [col for col in tmp_feats if train_df[col].dtype == 'object']\n    feats = [f for f in tmp_feats if f not in categorical_feature]\n    #print(categorical_feature)\n    \n    for n_fold, (train_idx, valid_idx) in enumerate(folds.split(train_df[feats], train_df[\"target\"])):\n        train_x, train_y = train_df[feats].iloc[train_idx], train_df[\"target\"].iloc[train_idx]\n        valid_x, valid_y = train_df[feats].iloc[valid_idx], train_df[\"target\"].iloc[valid_idx]\n\n        # ベイズ最適化によって見つかったLightGBMのパラメータ:後ほど決める\n        clf = LGBMClassifier(\n            nthread=4,\n            n_estimators=10000,\n            learning_rate=0.02,\n            num_leaves=34,\n            colsample_bytree=0.9497036,\n            subsample=0.8715623,\n            max_depth=8,\n            reg_alpha=0.041545473,\n            reg_lambda=0.0735294,\n            min_split_gain=0.0222415,\n            min_child_weight=39.3259775,\n            silent=-1,\n            verbose=-1, )\n\n        clf.fit(train_x, train_y, eval_set=[(train_x, train_y), (valid_x, valid_y)], \n            eval_metric= 'auc', verbose= 200, early_stopping_rounds= 200)\n\n        oof_preds[valid_idx] = clf.predict_proba(valid_x, num_iteration=clf.best_iteration_)[:, 1]\n        #testデータフレームが存在する場合はコメントアウトしている部分も実行する\n        #sub_preds += clf.predict_proba(test_df[feats], num_iteration=clf.best_iteration_)[:, 1] / folds.n_splits\n\n        #評価指標はAUCから変更する可能性有り\n        fold_importance_df = pd.DataFrame()\n        fold_importance_df[\"feature\"] = feats\n        fold_importance_df[\"importance\"] = clf.feature_importances_\n        fold_importance_df[\"fold\"] = n_fold + 1\n        feature_importance_df = pd.concat([feature_importance_df, fold_importance_df], axis=0)\n        print('Fold %2d AUC : %.6f' % (n_fold + 1, roc_auc_score(valid_y, oof_preds[valid_idx])))\n        del clf, train_x, train_y, valid_x, valid_y\n        gc.collect()\n\n    print('Full AUC score %.6f' % roc_auc_score(train_df['target'], oof_preds))\n    #提出ファイルを作成し、特徴の重要度をプロットする(今回は必要ない？)\n    if not debug:\n        test_df['target'] = sub_preds\n        test_df[['SK_ID_CURR', 'target']].to_csv(submission_file_name, index= False)\n    display_importances(feature_importance_df)\n    return feature_importance_df\n\n# Display/plot feature importance\ndef display_importances(feature_importance_df_):\n    cols = feature_importance_df_[[\"feature\", \"importance\"]].groupby(\"feature\").mean().sort_values(by=\"importance\", ascending=False)[:40].index\n    best_features = feature_importance_df_.loc[feature_importance_df_.feature.isin(cols)]\n    plt.figure(figsize=(8, 10))\n    sns.barplot(x=\"importance\", y=\"feature\", data=best_features.sort_values(by=\"importance\", ascending=False))\n    plt.title('LightGBM Features (avg over folds)')\n    plt.tight_layout()\n    plt.savefig('lgbm_importances01.png')\n\n\n","metadata":{"execution":{"iopub.status.busy":"2023-07-06T07:24:29.311619Z","iopub.execute_input":"2023-07-06T07:24:29.314113Z","iopub.status.idle":"2023-07-06T07:24:29.388574Z","shell.execute_reply.started":"2023-07-06T07:24:29.313995Z","shell.execute_reply":"2023-07-06T07:24:29.385274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 実行関数","metadata":{}},{"cell_type":"code","source":"def main():\n    #Baseとなる顧客IDにleftjoinしていく\n    target_customers = create_target_customers(transactions=transactions,\n                                               pre_start_date=\"2018-12-01\",\n                                               pre_end_date=\"2019-03-01\")\n    print(\"target_customers:\", target_customers.shape)\n    \n    #目的変数と顧客IDの存在するデータフレームを作成する\n    target_variables = create_target_variable(transactions=transactions,\n                                             target_customers=target_customers,\n                                             pos_start_date=\"2019-03-01\",\n                                             pos_end_date=\"2019-06-01\")\n    print(\"target_variables:\",target_variables.shape)\n    \n    #目的変数の存在するデータフレームをBaseとなる顧客IDにleft joinする\n    target_customers = pd.merge(target_customers, target_variables, how='left', on='customer_id')\n    del target_variables\n    gc.collect()\n    \n    #customersの情報を付与する\n    customers_feature = create_customers_feature(customers=customers)\n    print(\"customers_feature:\", customers_feature.shape)\n    target_customers = pd.merge(target_customers, customers_feature, how='left', on='customer_id')\n    del customers_feature\n    gc.collect()\n    \n    #モデルを作成する\n    ##数値型やbool型の変数以外をダミー変数化する\n    #target_customers=one_hot_encoder(df=target_customers, nan_as_category = True)\n    with timer(\"Run LightGBM with kfold\"):\n        feat_importance = kfold_lightgbm(df=target_customers,num_folds=10,stratified=False,debug=True)\n    #feature_importanceを可視化する\n    #display_importances(feat_importance)\n    return feat_importance\n","metadata":{"execution":{"iopub.status.busy":"2023-07-06T07:30:47.232946Z","iopub.execute_input":"2023-07-06T07:30:47.233497Z","iopub.status.idle":"2023-07-06T07:30:47.244474Z","shell.execute_reply.started":"2023-07-06T07:30:47.233441Z","shell.execute_reply":"2023-07-06T07:30:47.243306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 実行結果","metadata":{}},{"cell_type":"code","source":"sample=main()\nprint(sample.shape)\nsample.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-06T07:30:48.260681Z","iopub.execute_input":"2023-07-06T07:30:48.261609Z","iopub.status.idle":"2023-07-06T07:34:21.372421Z","shell.execute_reply.started":"2023-07-06T07:30:48.261572Z","shell.execute_reply":"2023-07-06T07:34:21.370910Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}