[Python: XGBoost を使ってみる](https://blog.amedama.jp/entry/2019/01/29/235642)

上記ページの「学習過程を可視化する」の項目での質問です。

上記HPのサンプルコードで

```

    # 学習過程を記録するための辞書
    evals_result = {}
    print('@A'. evals_result)
    bst = xgb.train(xgb_params,
                    dtrain,
                    num_boost_round=1000,  # ラウンド数を増やしておく
                    evals=evals,
                    evals_result=evals_result,
                    )
    
    print('@B'. evals_result)
    
```

＠Aの部分でprintするとevals_resultは当然カラです。  
しかし＠Bのところでprintするとevals_resultにいろいろと何かが代入されています。

evals_resultには何が代入されているのですか？

HPの「# 学習の課程を折れ線グラフとしてプロットする」以降の部分がなぜ出力されるのかがよくわからなくコードを１行1行追ってみています。

とりあえず evals_result について解説をいただきたく思います。  
よろしくお願いします。
CC BY-SA 4.0
2020-10-05T23:29:07.753
70941
2020-10-06T02:35:10.190
2020-10-06T00:53:25.210
3060
37681
question
python
pythonのxgboostのグリッドサーチとクロスバリデーション関連での質問です。
> evals_resultには何も代入していないのに、なぜか＠B時点には何やらが代入されています。 まずそこがよくわからないです。

何も代入されていない（空の辞書であった）`evals_result`に対して、`xgb.train()`の処理中に要素（学習用データと検証用データの損失）が追加されています。

> xgb.trainのところでも「カラのevals_resultを.trainの引数evals_result引数に代入している」ように見えます。

はい。そうです。`xgb.train()`の処理中に`evals_result`に値が代入（要素が追加）されるように、引数で渡しています。「参照渡し」を理解されていないのかもしれませんね。このキーワードでググってみて下さい。

> またxgb.trainによってevals_resultに何かが代入されたのだとしたら、ではなんでevals_result =
> {}が必要なの？とまた疑問が浮かびます。

定義されていない変数は使えないからです。

> また「学習過程を記録するための辞書」というのが何を指しているのかもわからないです。 すみません。

参照しているページを見ると、この辞書から取得した学習用データと検証用データの損失をプロットしています。100ラウンドを超えると、学習が進んでも精度が上がっていかない様子が読み取れますよね。

> こんな状態です。 evals_resultにはどこで何が代入されたのでしょうか？そこがよくわかりません。

前述した通りです。

`evals_result`を`xgb.train()`の戻り値にしていないのは、おそらく他の同様のメソッドとの統一を図るためではないかと思います（※推測ですが...）。
CC BY-SA 4.0
2020-10-06T01:46:36.743
70947
2020-10-06T01:46:36.743
21092
70941
answer
@Kohei TAMURA さん回答への補足(蛇足?)と、今後の学習のための考え方として、「
**何かを疑問に感じたら、使用しているAPIや元となっている仕様を調べてみましょう。** 」を心掛けてください。

以下にAPIの仕様が記述されています。  
[xgboost.train(params, dtrain, num_boost_round=10, evals=(), obj=None,
feval=None, maximize=False, early_stopping_rounds=None, evals_result=None,
verbose_eval=True, xgb_model=None,
callbacks=None)](https://xgboost.readthedocs.io/en/latest/python/python_api.html#xgboost.train)

>   * evals_result (dict) –  
>  This dictionary stores the evaluation results of all the items in
> watchlist.  
>  Example: with a watchlist containing [(dtest,'eval'), (dtrain,'train')] and
> a parameter containing ('eval_metric': 'logloss'), the evals_result returns
``` >     {'train': {'logloss': ['0.48253', '0.35953']},

>     'eval': {'logloss': ['0.480385', '0.357756']}}
>  
```

>
>

つまり質問の「 **evals_resultには何が代入されているのですか？**
」については、`train()`メソッドの処理により、その結果が格納されているということになるでしょう。

上記説明や、質問の参照記事、および以下の記事を合わせると、`watchlist`というのは`evals`パラメータに指定されたDMatrixと名称のtupleのリストでしょう。  
[Access train and evaluation error in
xgboost](https://stackoverflow.com/q/35197799/9014308)

コメントの「 **なんでevals_result = {}が必要なの？** 」と「 **学習過程を記録するための辞書とは何か？**
」の疑問については、その記述自身や英語記事回答の「One way to save your intermediate
results」、そしてAPI仕様の「early_stopping_roundsパラメータ」の記述を基に推測すると、`evals_result`に情報を格納して、処理を中断・再開したり、パラメータを調整して何回も`train()`メソッドを呼ぶやり方があるのかもしれません。そのために1回の呼び出し毎に新規の結果として通知するのではなく、使い回せるように参照渡しになっている可能性が考えられます。

そうした機能があるという推測が当たっていれば、`evals_result = {}`は一番最初のクリーンな状態を設定していることになるでしょう。
CC BY-SA 4.0
2020-10-06T02:35:10.190
70949
2020-10-06T02:35:10.190
26370
70941
answer