画像
とある事情で画像を使うことになったので、ブログに貼る。
終わり。
ガンマ・ポアソン・リーセンシー・モデル
ガンマ・ポアソン・リーセンシー・モデル
リーセンシー(最近いつそのブランドを購入したか)からそのブランドの購入頻度(Frequency)や浸透率(Penetration)を導き出すモデル。
感想
もっと統計やらんとなあ
AtCoder Beginner Contest 169 B-Multiplicationの振り返り
愚直に実装した場合に起きる問題
・Python:オーバーフローは起こらないが、計算量O(N^2)でTLEになってしまう。
・C++:計算量は大丈夫だが、オーバーフローにより誤った計算結果になる。
*オーバーフロー(桁あふれ)とは??
数値型の変数について、己が持てる最大値を超えること。
これが起きるとぐちゃぐちゃな数字が変数に入ってしまうため、正しい数値が得られなくなる。
(例)A1~A3に10^9が入っている場合、A1×A2の段階では10^18でlong long型にギリギリ間に合う。しかし、A3がここに掛け算されるとオーバーフローし想定外の数値が入る。この後に10^18との間で大小比較を行っても、正しい結果が得られない。
【オーバーフローへの対処法】
①Pythonなどオーバーフローの心配がない言語で書く
②int 128型に変換する
正解のために求められる能力
・Pythonの場合: TLEへの対処力(正しい順序で判断処理を行い計算量を減らす)
・C++の場合: オーバーフローへの対処力 or 正しい順序で判断処理を行う力
入力値に0が含まれる場合に、正しい処理方法を実装できるかが勝利を分けた模様(なみだ)
解答例1(この順番で行うのが重要!)
①入力全読み込み → ②Aに0が含まれるか判断 → ③順番に掛け算を行い、積が10^18を超えるか判断
・②がなかったら・・・「Aに0を含んでいるケースで、誤った出力結果をしてしまう」
(例)A1とA2に10^18、A3に0が入っていた場合を考えてみる!このとき、A1×A2×A3は0になるはず。
しかし③のみで判断していると、A1×A2の段階で10^18を超えたことにより-1を出力してしまう結果に。
解答例2(よりスマートに見える):
①入力全読み込み → ②Aを小さい順に並び替え → ③順番に掛け算を行い、積が10^18を超えるか判断
まとめ
・今回のPythonでTLEが発生した理由は、普通に掛け算していくと計算結果は最大10^50000まで取りうるため計算量がO(N^2)になるから。
・そこで計算量を減らすための工夫が必要になるが、以下の2通りが多くみられる。
【方法1】
①入力値のいずれかに0があるかを判断し、あれば0を出力してプログラムを終了
②順番に掛け算し、10^18を超えているかを逐次判断。超えたら-1出力しプログラム終了
【方法2】
①入力値を小さい順にソートする
②順番に掛け算し、10^18を超えているかを逐次判断。超えたら-1出力しプログラム終了
・入力値のいずれかに0を含む場合は、他の入力値がどんなに大きかったとしても計算結果は0になることを想像できたかがカギでした。むずかしかった泣いちゃうほぼ泣いた
負の二項分布(Negative Binomial Distribution)
設定
赤玉と白玉の2種類が入っている袋があり、袋の中には赤玉θ個と白玉n-θ個の合計n個の玉が入っている。
かき混ぜて、中を見ず1個取り出す。
もし、赤玉が出たら、d個の赤玉を袋に加えて袋に戻す。
もし、白玉が出たら、d個の白玉を袋に加えて袋に戻す。
(その選択が次の選択に正の影響を与える感じ。成功は成功を呼ぶてきな。)
この操作をN回繰り返す。
負の二項分布(Negative Binomial Distribution)
M、Kを次のように定める。
(N回中、赤玉が出る平均回数)
N回中、r回赤玉が出る確率をとすると、
で表される分布を負の二項分布というらしい。
導出
また後ほど
実問題への適用
消費者全体の購買行動で負の二項分布を適用する。
また後ほど
思ったこと
TeXで数式書くのが面倒。
LightGBMでよくやるやつ
パラメータチューニング(optuna)、CV
scikit-learn インターフェースを使わずLightGBM
import numpy as np import pandas as pd from sklearn import metrics from sklearn.model_selection import train_test_split, StratifiedKFold import optuna import lightgbm as lgb def get_evaluate(y_test, predict): fpr, tpr, thr_arr = metrics.roc_curve(y_test, predict) auc = metrics.auc(fpr, tpr) precision = metrics.precision_score(y_test, predict) recall = metrics.recall_score(y_test, predict) return auc, precision, recall_score def objective(trial): train_x, test_x, train_y, test_y = train_test_split(X_train, y_train, test_size=0.25, shuffle=True, stratify=y_train) dtrain = lgb.Dataset(train_x, label=train_y) param = { 'objective': 'binary', 'metric': 'auc', 'verbosity': -1, 'boosting_type': trial.suggest_categorical('boosting', ['gbdt', 'dart', 'goss']), 'num_leaves': trial.suggest_int('num_leaves', 10, 1000), 'learning_rate': trial.suggest_loguniform('learning_rate', 1e-8, 1.0) } if param['boosting_type'] == 'dart': param['drop_rate'] = trial.suggest_loguniform('drop_rate', 1e-8, 1.0) param['skip_drop'] = trial.suggest_loguniform('skip_drop', 1e-8, 1.0) if param['boosting_type'] == 'goss': param['top_rate'] = trial.suggest_uniform('top_rate', 0.0, 1.0) param['other_rate'] = trial.suggest_uniform('other_rate', 0.0, 1.0 - param['top_rate']) gbm = lgb.train(param, dtrain) preds = gbm.predict(test_x) pred_labels = np.rint(preds) fpr, tpr, thr_arr = metrics.roc_curve(test_y, pred_labels) accuracy = metrics.auc(fpr, tpr) return accuracy k = 5 skf = StratifiedKFold(n_splits=k, shuffle=True, random_state=0) lgbm_params = {'objective': 'binary'} auc_list = [] precision_list = [] recall_list = [] for train_index, test_index in skf.split(X, y): X_train = X.iloc[train_index] y_train = y.iloc[train_index] X_test = X.iloc[test_index] y_test = y.iloc[test_index] study = optuna.create_study(direction='maximize') study.optimize(objective, n_trials=100) print('Number of finished trials: {}'.format(len(study.trials))) print('Best trial:') trial = study.best_trial print(' Value: {}'.format(trial.value)) print(' Params: ') for key, value in trial.params.items(): print(' {}: {}'.format(key, value)) # optunaでサーチしたパラメータ trial.params['objective'] = 'binary' lgbm_params = trial.params # ここではvalidをモデル評価、evalをフォールドアウト検証に使う・・・分割の大きさはデータセットと相談する X_eval, X_valid, y_eval, y_valid = train_test_split(X_test, y_test, random_state=90, shuffle=True, stratify=y_test, test_size=0.3) # データセットを生成する lgb_train = lgb.Dataset(X_train, y_train) # モデル評価用 lgb_valid = lgb.Dataset(X_valid, y_valid, reference=lgb_train) model = lgb.train(lgbm_params, lgb_train, valid_sets=lgb_valid, num_boost_round=100000, early_stopping_rounds=10) predict = model.predict(X_test, num_iteration=model.best_iteration) auc, precision, recall = get_evaluate(y_test, predict) print('AUC:{}, precision:{}, recall:{}'.format(auc, precision, recall)) auc_list.append(auc) precision_list.append(precision) recall_list.append(recall) # kfoldの平均値を取得 print('Kfold平均 AUC:{}, precision:{}, recall:{}'.format(np.mean(auc_list), np.mean(precision_list), np.mean(recall_list)))
scikit-learn インターフェースでのLightGBM
また今度