Kiva/クラウドファンディングの資金調達額予測

マルチモーダルコンペティション!Ridgelinezとの共同開催です

賞金: 200,000 参加ユーザー数: 231 3年弱前に終了
スポンサー
Ridgelinez株式会社

LightGBM Base line(LB:360.74167)

Kiva/クラウドファンディングの資金調達額予測 LightGBM Base line

https://comp.probspace.com/competitions/kiva2021
Public(LB)スコア:360.74167(2021.12.21)

  • Google Colabで動作確認済
  • Google Driveへのファイル配備を想定
  • 想定するGoogle Driveのディレクトリ構成
     /content/drive/My Drive/ML/kiva/ の配下にinputとsubmitの2つのフォルダを作成
     inputフォルダ配下に、probspaceからダウンロードした5つのファイルを配備
     submitフォルダに、投稿用ファイルが出力される

##初期設定

モジュールのインストール

!python3 -m pip install -q slackweb
!echo "$(pip freeze | grep slackweb) is successfully installed"

ライブラリのインストール

import pandas as pd
import numpy as np
import datetime
import os
import warnings
warnings.filterwarnings("ignore")

import matplotlib
import matplotlib.pylab as plt

import sklearn
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error
from sklearn import preprocessing

import lightgbm as lgb

import slackweb

from google.colab import drive
drive.mount("/content/drive")

コンフィグ

SEED = 42

データの読み込み

Google Driveのディレクトリを指定

DRIVE = "/content/drive/My Drive/ML/kiva/"
INPUT = os.path.join(DRIVE, "input")
SUBMIT = os.path.join(DRIVE, "submit")

trainデータの読み込みと確認

train_df = pd.read_csv(f"{INPUT}/train.csv")
display(train_df.info())

testデータの読み込みと確認

test_df = pd.read_csv(f"{INPUT}/test.csv")
display(test_df.info())

sample_submission.csvの読み込み

submit_df = pd.read_csv(f"{INPUT}/sample_submission.csv")

画像の読み込み(本サンプルコードでは利用していないが、下記の議論を参考にColabへの読み込みまでを実装)
https://comp.probspace.com/competitions/kiva2021/discussions/goukaisei-Post6dbf79c59def6c1b327d
(検討事項)画像の有効利用について

# !cp "/content/drive/My Drive/ML/kiva/input/test_images.zip" .
# !unzip test_images.zip
# print(len(os.listdir("test_images"))) #should be 91819

LGBMの実行

trainデータの列名の再確認

  • 本サンプルコードでは、目的変数(LOAN_AMOUNT)を除く17列のうち、8列のみを説明変数として利用
  • (検討事項)前処理、特徴量作成を追加
    特にDESCRIPTION_TRNSLATED、IMAGE_ID(画像)、LOAN_USE、TAGSの4つをどう使うべきか
train_df.columns

trainデータを目的変数と説明変数に分割

train_columns = ["ORIGINAL_LANGUAGE", "ACTIVITY_NAME", "SECTOR_NAME", "COUNTRY_CODE","CURRENCY_POLICY",
       "CURRENCY","REPAYMENT_INTERVAL", "DISTRIBUTION_MODEL"]
target = "LOAN_AMOUNT"

X = train_df[train_columns]
y = train_df[target]

説明変数をラベルエンコーディング
(検討事項)エンコードの方法

for column in X.columns:
  le = preprocessing.LabelEncoder()
  target_column = X[column]
  le.fit(target_column)
  label_encoded_column = le.transform(target_column)
  X[column] = pd.Series(label_encoded_column).astype("category")

ラベルエンコード後の説明変数の確認

display(X)

trainデータを訓練用とテスト用に分割
(検討事項)K分割交差検証の導入

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state = SEED)

LGBM用のパラメータ設定

params = {
    "application" : "regression_l1",
    "metric" : "l1" #mae
}

LGBMの学習用のデータを作成

lgb_train = lgb.Dataset(X_train, y_train)
lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train) 

モデルの学習

%%time
evaluation_results = {}
model = lgb.train(params,
                  train_set=lgb_train,
                  valid_sets=lgb_eval,
                  valid_names=["train"],  
                  evals_result=evaluation_results
                  )

学習過程の可視化

plt.plot(evaluation_results["train"]["l1"], label="train")
plt.ylabel("MAE")
plt.xlabel("Num Boosting round")
plt.title("Training performance")
plt.legend()
plt.show()

テストデータによる予測

y_pred = model.predict(X_test)

真の値(y_test)と予測値(y_pred)の比較

display(pd.DataFrame({"y_test":y_test,"y_pred":y_pred}))

MAE算出

MAE = mean_absolute_error(y_test, y_pred)
print("MAE = " + str(MAE))
lgb.plot_importance(model)
plt.show()

推論

test_X = test_df[train_columns]

for column in test_X.columns:
  le = preprocessing.LabelEncoder()
  target_column = test_X[column]
  le.fit(target_column)
  label_encoded_column = le.transform(target_column)
  test_X[column] = pd.Series(label_encoded_column).astype("category")

test_predicted = model.predict(test_X)

検討事項

  • 他のモデルの追加(RandomForest,XGBoost等)
  • アンサンブル

提出データの作成

下記の議論よりLOAN_AMOUNTの推論値を25の倍数に整形
https://comp.probspace.com/competitions/kiva2021/discussions/XS330-Post2d3ac1900e595ca2f900
(検討事項)整形方法について要精査

test_predicted = (np.round(test_predicted/25)*25).astype(int)
submit_df["LOAN_AMOUNT"]=test_predicted
print(submit_df)

trainファイルとsubmitファイルのLOAN_AMOUNTについて比較

display(pd.DataFrame({"trainファイル":train_df["LOAN_AMOUNT"].describe(),"submitファイル":submit_df["LOAN_AMOUNT"].describe()}))

submitファイルのファイル名に利用する作成時刻の取得

now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=1)))
date_time = "{0:%Y%m%d_%H%M}".format(now)

submitファイルの出力(Google Driveに出力)
形式:submit_yyyymmdd_hhmm_(小数点3位までのMAE).csv
例:submit_20211221_0003_311.391.csv

submit_df.to_csv(os.path.join(SUBMIT, f"submit_{date_time}_{MAE:.3f}.csv"), index=False)

Slackへの作業完了通知(ファイル名とMAEのログ保存)
https://api.slack.com/messaging/webhooks#posting_with_webhooks
(検討事項)ログの追加

SLACK_CHANNEL="#general"
SLACK_USER="Colab"
SLACK_TEXT="Colab完了通知"

slack = slackweb.Slack(url="ご自身のIncoming Webhook URL")
attachments=[]
attachment={
            "color": "#2eb886",
            "fields":[
                  {
                  "title": "ファイル作成時刻","value": date_time,
                  },
                  {
                  "title": "MAE","value": MAE,
                  }
              ]
            }
attachments.append(attachment)
slack.notify(text=SLACK_TEXT, channel=SLACK_CHANNEL, username=SLACK_USER, attachments=attachments)

添付データ

  • lgbmsample20211221.ipynb?X-Amz-Expires=10800&X-Amz-Date=20241121T111127Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIP7GCBGMWPMZ42PQ
  • Icon2
    newduck

    コメント、質問、気軽に宜しくお願いします。

    上記の検討事項を全部実装した上で、 DESCRIPTION_TRNSLATED、IMAGE_ID(画像)、LOAN_USE、TAGSからの特徴量抽出辺りが、 スコア差に響く気がします。

    画像へのラベリング、特にハンドラベリングを許可するのかも気になっていますが。

    Icon2
    newduck

    上記の検討事項のうち幾つかを実装しLB:360.74167⇒338.41538となりました。

    • 効いた順に、エンコードの方法⇒パラメータ追加と最適化(Optuna等活用)⇒K分割交差検証の導入
    • アンサンブルは、tutorialにあったランダムフォレストを使ってみましたが、スコア改善とはならず。他は未実装。

    • 前処理、特徴量作成を追加
    • 画像の利用 を考えてみたいと思います。

    2021.12.26

    Favicon
    new user
    コメントするには 新規登録 もしくは ログイン が必要です。