C++で簡単に実験結果をプロット&管理 ~wandb-cpp~

私が作ったライブラリの宣伝です! C++で[wandb](https://www.wandb.jp/)を叩くためのライブラリです!

https://github.com/yhisaki/wandb-cpp

GithubでStar⭐⭐やIssueで様々なご指摘，新規機能のリクエストなどをいただけると嬉しいです!! PRなどをしていただけると更に嬉しいです!!

## どんなことに使えるの？

C++で数値実験などをする方々は，その結果をどのようにプロット・管理していますか？プロットするだけであれば[Matplot++](https://github.com/alandefreitas/matplotplusplus)や[matplotlib-cpp](https://github.com/lava/matplotlib-cpp)などを使っているのではないでしょうか？また，結果の保存はローカルファイルにしているはずです．

このライブラリは，C++での数値実験の結果を**クラウドにアップロード**して**web上でビジュアライズ**するための便利ライブラリです．

![example_log_basic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320782/197b7ec1-8f15-520d-c17c-23e8c874c43c.png)


## Weight & Biases

Pythonには機械学習の研究者用の[Weight & Biases (wandb)](https://www.wandb.jp/)というメチャメチャ便利なフレームワークがあります．

このサービスを使うと，機械学習中の損失の履歴やその出力などを簡単にクラウドにアップロード・可視化出来ます．しかも，個人利用であれば，100GBまで無料で使えます．すごい！

詳しくは，以下の記事が参考になります．

https://qiita.com/Yu_Mochi/items/4fc283ebc31225d4e106

https://qiita.com/NH0/items/88ea528e02678f4cb7ff

## WandB-CPP

このwandbというフレームワーク，基本的にPythonでの利用のみサポートいます．現在，公式にC++での利用はサポートされていません．そこで，PythonプログラムをC++から呼び出せるようにしたのがこのライブラリです!

https://github.com/yhisaki/wandb-cpp

実装には[Python/C API](https://docs.python.org/ja/3/c-api/index.html)を生で使っています．基本的な使い方は，以下のような感じです．

```cpp
#include <cmath>

#include "wandbcpp.hpp"

int main() {
  wandbcpp::init({.project = "example_wandb_cpp", .tags = {"basic"}}); // この実験結果をexample_wandb_cppプロジェクトに保存・basicタグをつける

  int N = 100;

  wandbcpp::update_config({{"N", N}, {"mode", "abc"}}); // この実験のパラメータをconfigに保存

  for (int i = 0; i < N; i++) {
    double t = M_PI * i / N; // 数値実験のデータ: t
    double x = std::sin(M_PI * i / N); // 数値実験のデータ: x
    double y = std::cos(M_PI * i / N); // 数値実験のデータ: y
    wandbcpp::log({{"t", t}, {"x", x}, {"y", y}}); // 時刻t,数値x・yをログに記録
  }
  wandbcpp::update_summary({{"success", true}}); // summaryを保存
  wandbcpp::finish();
}
```

まず，`wandbcpp::init`でプロジェクトを指定します．
次に，`wandbcpp::update_config`でこの実験の設定(パラメータ)を保存し，
for文の中で実験を実行・ログを保存します．
最後に`wandbcpp::update_summary`でこの実験のsummaryを保存します．

`update_config`,`log`,`update_summary`の引数の`{{"...", ...}, ...}`はpythonのdictのように使えます．テンプレートを使って，適当な型のデータを入れても良しなに処理するようにしています．

実行すると，コンソールに以下のような表示がなされます．

<details><summary>出力</summary><div>
```bash
hisaki@FRONTIER:~/workspace/wandb-cpp$ ./build/examples/example_log_basic 
wandb: Currently logged in as: hisaki. Use `wandb login --relogin` to force relogin
...省略
wandb: Syncing run swept-deluge-103
wandb: ⭐️ View project at https://wandb.ai/hisaki/example_wandb_cpp
wandb: 🚀 View run at https://wandb.ai/hisaki/example_wandb_cpp/runs/d9c9ikz1
...省略
wandb: Run history:
wandb: t ▁▁▁▁▂▂▂▂▂▃▃▃▃▃▃▄▄▄▄▄▅▅▅▅▅▅▆▆▆▆▆▇▇▇▇▇▇███
wandb: x ▁▁▂▃▃▄▄▅▅▅▆▆▇▇▇██████████▇▇▇▇▆▆▅▅▅▄▄▃▃▂▁
wandb: y ████████▇▇▇▇▇▆▆▆▆▅▅▅▄▄▄▄▃▃▃▃▂▂▂▂▂▁▁▁▁▁▁▁
wandb: 
wandb: Run summary:
wandb: success True
wandb:       t 3.11018
wandb:       x 0.03141
wandb:       y -0.99951
wandb: 
wandb: 🚀 View run swept-deluge-103 at: https://wandb.ai/hisaki/example_wandb_cpp/runs/d9c9ikz1
wandb: Synced 5 W&B file(s), 0 media file(s), 0 artifact file(s) and 0 other file(s)
wandb: Find logs at: ./wandb/run-20240208_234343-d9c9ikz1/logs
```
</div></details>

表示されるリンクに行くと，以下のようになります．

- t,x,yのプロット
![Screenshot from 2024-02-08 23-50-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320782/000bf906-6a61-aa00-7042-980c73df4496.png)

- config, summaryのデータ
![Screenshot from 2024-02-08 23-46-22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320782/076a17bc-5f7d-f800-c22f-0c78c3de9359.png)

## ログ出力などの実行コスト

このライブラリは実行時間にシビアなロボット制御などでも使えるように，ログを保存する`wandbcpp::log`関数などには時間がかからないように設計しています．実際に計測したところ`wandbcpp::log`の実行にかかる時間は**3us**でした．

これは，ログの保存など，Pythonインタプリタを呼び出して行う処理は全て別のスレッドで行っているためです．

![Untitled-2023-12-06-2205.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320782/b29d9615-94d4-4a0f-33fb-28a50bd50c97.png)

なので，ロボットの制御ループのプログラムに，ログを保存するコードを入れても基本的に大丈夫です！ただし，wandb自体，大量のログを一度にアップロードする使い方が想定されていないため，アップロードするログの量が多くなりすぎないような工夫(100msに1回のみログを保存するようにするなど)を入れてください．

## その他の機能

例えば，OpenCVと連携して画像を保存する機能や
![example_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320782/6f033561-87ea-8c77-8516-3d9368d7c5a7.png)
動画を保存する機能など
![example_video.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320782/997b277d-01b2-9a94-1c20-bca0f2ebefbc.gif)
をサポートしています！

他にも色々あるのですが，詳しくは[リポジトリ](https://github.com/yhisaki/wandb-cpp)のREADMEを参照してください．

## 今後は公式でサポートされるかも...

Githubのwandbの公式に以下のようなリポジトリが作成されていたのですが，どうやらREADME.mdを作成したあと力尽きています．

https://github.com/wandb/libwandb-cpp

公式でサポートされると，おそらくwandbのAPIを直接用いたものになるはずなので，私のものより良くなるはずです．今後の開発に期待したいですね．