移動平均を選択しない理由

カルマンフィルタ・状態空間モデルに対して、移動平均を選択しないことの理由づけ。

下記、書籍を読みながら考えたことです。

www.asakura.co.jp

そもそもなぜ移動平均を求めるのか(現状、使われているのか)?

測定値にはノイズ(観測誤差)が含まれており、過去(数日間)のデータを用いて平均化してノイズの影響を緩和するため。言い換えると、仮にノイズの生じない状態であれば移動平均値を使用する必要はない(例えば、全数測定によって誤差なく目的とする測定ができる場合など)。

移動平均とは(逐次計算の観点から)

移動平均では、前日の予測値と今日の実測値の差分に重みを付けて今日の実測値から補正した今日の真値を予測する。この時の重みの分母にはk日移動平均のkが含まれ、kが大きな程重みが小さくなる。ここでは、k日の数が大きな程ノイズの影響が緩和される一方、補正は緩慢となり真値の推定に対する精度低下が起きうる。 (なお、厳密には前日の予測値と今日の実測値の差分ではなく、k日前の予測値と今日の差分。詳しくは森平本のp.26。)

移動平均を利用しない理由

上記の理由から、k日の移動平均のkを決める方針はノイズの影響を小さくする(kを大きくする)ことと強く補正する(kを小さくする)ことのトレードオフを考え最適点を見つけることであり、数学的に合理的に決定できる。その合理的な決定方法がカルマンフィルタであり、状態空間モデル。

移動平均を利用する理由

  • 計算が簡単
  • よく使われてきたので受け入れやすい
  • 簡単に理解できる気がする。

k日で事象が変わる場合にはk日移動平均が良いのでは?

例えば、1週間ごとに条件を変える製造工程では1週間内は同じものが作られ続けられるものであり、7日移動平均を選択することにある程度の合理性はあるという声もあるかもしれない。しかし、この考えには測定のノイズの大小の考えが欠落しており、何日の移動平均をとるかはノイズとの兼ね合いで考えるべきである(カルマンフィルタor状態空間モデルを使うことの合理性)。

【kaggle】pystanを始めたい

kaggleではpystanができない?

何も考えずに入れようとする。

import pystan

結果だめ

 No module named 'pystan'
import stan

だめ。

バージョン指定で入れようとする

! pip install pystan==3.0.0

結果だめ。

昔のバージョンで入れようとする

! pip install pystan==2.19.1.1

結果だめ。

! python3 -m pip install pystan==3.3.0
import nest_asyncio
nest_asyncio.apply()

import stan

schools_code = """

"""

schools_data = {"J": 8,
                "y": [28,  8, -3,  7, -1,  1, 18, 12],
                "sigma": [15, 10, 16, 11,  9, 11, 10, 18]}

posterior = stan.build(schools_code, data=schools_data)
fit = posterior.sample(num_chains=4, num_samples=1000)
eta = fit["eta"]  # array with shape (8, 4000)
df = fit.to_frame()  # pandas `DataFrame, requires pandas

warningがたくさん出た上で

ValueError: The JSON document has an improper structure: missing or superfluous commas, braces, missing keys, etc.

のエラーで終了。

pystan-jypyter+pre pystanでトライ

! pip install pystan-jupyter==0.2b1
! pip install --pre pystan

結果、同じくエラー

ValueError: The JSON document has an improper structure: missing or superfluous commas, braces, missing keys, etc.

他の人がやった過去のnotebook見るとできているようで、どうやら現在のバージョンとの違いによるものと推察。

どうしたものかね。。

参考にしました

WindowsマシンでPyStan3.2.0を使う

JupyterNotebookでPystanをインストールしてもうまくいかなかったら - えい夫のお気軽データサイエンス

Frustrating problems with Pystan (anaconda Python) - PyStan - The Stan Forums

Google ColaboratoryでPyStanをいじくる - 雑記 in hibernation

PyStan の実行例【 Eight Schools】

Pip install error ModuleNotFoundError: No module named 'pystan' · Issue #401 · facebook/prophet · GitHub

【Python】ベイズ統計を実践できるPyStanのインストール | ジコログ

時系列データ解析についてのページ

時系列データ分析全般

http://elsur.jpn.org/202004MMM/chap5.pdf

ランダムウォーク

Random Walks Have Never Been Funnier | by Vladimir Ilievski | Towards Data Science

【Python】株価をランダムウォークでシミュレートしてみる - turtlechanのブログ

市場データからボラティリティ・スマイルを確認してみた - Qiita

時系列分析の単位根過程、ランダムウォークとは? | AVILEN AI Trend

ARMA/ARIMA

AR,AM,ARMAモデルへのフィッテング - Qiita

【python+株価+statsmodel】ARIMAモデルでダウ平均株価を解析してみた - ころがる狸

【Python】ARMAモデルで時系列分析&予測をやってみる | ミナピピンの研究室

単位根検定

Pythonで時系列解析(adfで単位根検定) - あれもPython,これもPython

www.statsmodels.org

見せかけの回帰について(そして単位根過程・共和分など) - 渋谷駅前で働くデータサイエンティストのブログ

XGBoostingの最適化(Optuna)と特徴量

作成中ですが、暫定で投稿。

ちなみに、xgboostでは欠損値のnanはそのまま取り扱えるようです。

最適化

試行錯誤的に、動く条件を探索しました。

import xgboost as xgb

def objective_xgb(trial):
    #
    if trial.number == 0 :
        learning_rate = trial.suggest_loguniform('learning_rate', 0.3, 0.3)
        gamma         = trial.suggest_loguniform('gamma', 1e-8, 1e-8)
        max_depth     = trial.suggest_int('max_depth', 6, 6)
        min_child_weight = trial.suggest_loguniform('min_child_weight', 1.0, 1.0)
        #max_delta_step   = trial.suggest_uniform('max_delta_step', 1e-10, 1e-10)
        subsample  = trial.suggest_uniform('subsample', 1.0, 1.0)
        reg_lambda = trial.suggest_uniform('reg_lambda', 1.0, 1.0)
        reg_alpha  = trial.suggest_uniform('reg_alpha', 0.0, 0.0)
    else:
        learning_rate = trial.suggest_loguniform('learning_rate', 1e-8, 1.0)
        gamma         = trial.suggest_loguniform('gamma', 1e-15, 1e-5)
        max_depth     = trial.suggest_int('max_depth', 1, 20)
        min_child_weight = trial.suggest_loguniform('min_child_weight', 1e-8, 1e3)
        #max_delta_step   = trial.suggest_uniform('max_delta_step', 0, 1.0)
        subsample  = trial.suggest_uniform('subsample', 0.0, 1.0)
        reg_lambda = trial.suggest_uniform('reg_lambda', 0.0, 1000.0)
        reg_alpha  = trial.suggest_uniform('reg_alpha', 0.0, 1000.0)
        #reg_alpha  = trial.suggest_loguniform('reg_alpha', 1e-15, 1e4)
    #
    
    clf = xgb.XGBRegressor(
                            learning_rate = learning_rate, 
                            subsample = subsample,
                            max_depth = max_depth,
                            min_child_weight = min_child_weight, 
                            max_delta_step = 0,  # 1e-10で発散したため、0で固定
                            reg_lambda = reg_lambda,
                            gamma = gamma,                            
                            reg_alpha = reg_alpha,
                            #objective='reg:squarederror'
                          )
    
    scores = []
        
    for train_index, test_index in kf.split(X, y):
        #
        X_train = scaler.transform( X[train_index] )
        y_train = y[train_index]
        #
        X_test  = scaler.transform( X[test_index] )
        y_test  = y[test_index]
        #
        clf.fit(X_train,y_train)
        #
        y_pred = clf.predict(X_test)
        #
        scores.append((rmspe(y_test,y_pred)))
                
    #
    return np.mean(np.array(scores))
optuna.logging.disable_default_handler() # Optunaの出力を抑制する
#optuna.logging.enable_default_handler() # Optunaで出力する
n_trials = 5
# optuna
study = optuna.create_study()
study.optimize(objective_xgb, n_trials=n_trials)

特徴量評価

そのほか

WARNING: src/objective/regression_obj.cu:152: reg:linear is now deprecated in favor of reg:squarederror.

誤差設定に関するエラーがでてくる場合があるようで、objective='reg:squarederror'の指定で解決できる場合があります。

regressor = XGBRegressor(tree_method='gpu_hist', random_state=0, objective='reg:squarederror')

XGBRegressor で WARNING: src/objective/regression_obj.cu:152: reg:linear is now deprecated in favor of reg:squarederror. - Qiita

参考にしました

最適化

特徴量

Feature Importanceって結局何なの?|Yotaro Katayama|note

各モデルで使われる変数重要度についてまとめる - まずは蝋の翼から。

xgboost で Feature Importance を算出する。 - Qiita

pythonで回帰分析【xgb,lgbm,voting】

XGBoost、LightGBM、アンサンブル学習(Voting regressor)についての情報整理

kaggleはこちら。

www.kaggle.com

XGBoost

Python: XGBoost を使ってみる - CUBE SUGAR CONTAINER

XGBoostハイパーパラメータチューニング

Optunaを使ったxgboostの設定方法 - Qiita

XGBoostをOptunaでチューニング(コード解説付き) - Qiita

XGBトピックス

WARNING対応です。

WARNING: /workspace/src/objective/regression_obj.cu:152: reg:linear is now deprecated in favor of reg:squarederror.
regressor = XGBRegressor(tree_method='gpu_hist', random_state=0, objective='reg:squarederror')

XGBRegressor で WARNING: src/objective/regression_obj.cu:152: reg:linear is now deprecated in favor of reg:squarederror. - Qiita

LightGBM

公式はこちら

lightgbm.LGBMRegressor — LightGBM 3.2.1.99 documentation

LightGBM 徹底入門 – LightGBMの使い方や仕組み、XGBoostとの違いについて

LightGBM ハンズオン - もう一つのGradient Boostingライブラリ - Qiita

Python: LightGBM を使ってみる - CUBE SUGAR CONTAINER

LightGBMのPythonパッケージ触ってみた - お勉強メモ

LightGBMのweightの使い方、weightは一体何を行っているのか - Qiita

ハイパーパラメータチューニング

LightGBMのハイパーパラメーターチューニングの仕方(optuna) | 獣医 x プログラミング

LightGBMをOptunaでパラメータチューニングする - Qiita

Optuna の拡張機能 LightGBM Tuner によるハイパーパラメータ自動最適化 | Preferred Networks Research & Development

LightGBMをOptunaでパラメータチューニングする - Qiita

OptunaでLightGBMのパラメータ調整 - Qiita

Python 3.x - lightgbm のverbose パラメータが機能しない|teratail

LightGBMトピック

パラメータを辞書型で設定するときは、渡し方に注意。

params = {
'num_class':5,
'max_depth':8,
'num_leaves':200,
'learning_rate': 0.05,
'n_estimators':500
}

clf = LGBMClassifier(**params)

python - LightGBM on Numerical+Categorical+Text Features >> TypeError: Unknown type of parameter:boosting_type, got:dict - Stack Overflow

アンサンブル学習(Voting regressor)

その9 ボストンの住宅価格をアンサンブル学習(Voting regressor)で予測してみた - ヒノマルクのデータ分析ブログ

Python: アンサンブル学習の Voting を試す - CUBE SUGAR CONTAINER

最新アンサンブル学習SklearnStackingの性能調査(LBGM, RGF, ET, RF, LR, KNNモデル

scikit-learnでバギングとブースティングをやってみる - Qiita

Optuna【機械学習のパラメータ最適化】

Optunaを使ってハイパーパラメータを調整します。kaggleにまとめました。

www.kaggle.com

Optunaの基本

github.com

optuna.readthedocs.io

公式のチュートリアルは下。

import ...

# Define an objective function to be minimized.
def objective(trial):

    # Invoke suggest methods of a Trial object to generate hyperparameters.
    regressor_name = trial.suggest_categorical('classifier', ['SVR', 'RandomForest'])
    if regressor_name == 'SVR':
        svr_c = trial.suggest_float('svr_c', 1e-10, 1e10, log=True)
        regressor_obj = sklearn.svm.SVR(C=svr_c)
    else:
        rf_max_depth = trial.suggest_int('rf_max_depth', 2, 32)
        regressor_obj = sklearn.ensemble.RandomForestRegressor(max_depth=rf_max_depth)

    X, y = sklearn.datasets.load_boston(return_X_y=True)
    X_train, X_val, y_train, y_val = sklearn.model_selection.train_test_split(X, y, random_state=0)

    regressor_obj.fit(X_train, y_train)
    y_pred = regressor_obj.predict(X_val)

    error = sklearn.metrics.mean_squared_error(y_val, y_pred)

    return error  # An objective value linked with the Trial object.

study = optuna.create_study()  # Create a new study.
study.optimize(objective, n_trials=100)  # Invoke optimization of the objective function.

OptunaでXGBoost, LightGBM

そもそも、XGBoost,LightGBMにはパラメータチューニングの機能があるので、そちらの機能を使用してもよさそうです。

参考にしました

optuna入門 - Qiita

GridSearchCVはもう古い!Optunaでサポートベクターマシンもラクラクチューニング - Qiita

LightGBMをOptunaでパラメータチューニングする - Qiita

XGBoostをOptunaでパラメータチューニングする - INOUE-KOBO.COM

LightGBMのハイパーパラメータチューニング(Optuna)をしてみた - Qiita