アルゴリズムとかオーダーとか

仕事で勉強したことなどをまとめてます

HugginfaceのTrainerでTensorboard用のログを出力する

今回もDeepLearningについての記事です。
HuggingfaceのTrainerで学習させたときに、学習途中のログをTensorboard用に出力する方法についてまとめます。

huggingface.co

  • Tensorboardのログ出力設定
  • Tensorboardのログを出力するために必要なライブラリ
  • コマンド引数でログの出力先を指定する方法
続きを読む

BERTのpre-trainingをやってみた 〜雑記〜

今回は深層学習の自然言語モデルである、BERTについて色々触っていたのでその記録を簡単にまとめたいと思う。
ひょんなことから、BERTの事前学習からやらなければならなかったので、実際に用いたライブラリや環境、学習に必要な時間などについて書いていく。

BERTのライブラリ

BERTのライブラリとしては、huggingfaceのTransformersを利用。
huggingface.co

特に、Transformersを用いたMasked Language Modelのサンプルコードを参考に作成した。
github.com

ベースライブラリ(と言って良いのかな?)はPytorchを採用。TensorFlowの方が色々とやってくれてるぽい感じで楽そうではあったが、深層学習やBERTに初挑戦の身としては、逆に何をやっているのか分かりづらかったので、比較的細部までいじれるPytorchを採用した。

学習環境

AWSの色々なインスタンスタイプで学習をおこなった。その時に得た知見を整理していく。

AMI

Deep Learning AMI (Ubuntu 18.04) Version 57.0 - ami-0da3b2f58df4b61cb

を利用。最近はコンテナを使う方が主流らしいが一通り学習を流すだけだったので慣れているAMIを選択した。

Instance Type

さまざまなインスタンスタイプでの推定学習時間を計測した。今回は3日程度である程度学習を完了させる必要があったため、少しデータ件数やモデルのサイズを変更して試した。

inf1.2xlarge

最初はinf1.xlargeで試そうとしたが、そもそもtransfomersのライブラリインストールがうまくいかなかった。vCPUが1つだとインストール時にハングアウトしてしまい、失敗するようだ。そのため、以降でも基本的にvCPU数2以上のインスタンスを採用している。

こちらは以下の条件で、学習に必要な時間が 6300h over だった。。。。

  • 学習データ: 約 550万件
  • epoch数: 10
  • bach per device: 16
p2系

CPUのみだとやはり辛いことがわかったので、GPU系のインスタンスに切り替えた。
しかし、結果としてP2系ではPytorchがうまくGPUを認識してくれず、学習の実行まではできなかった。一応、Tesla系のライブラリを入れ直したりして、nvidia-smiではGPUが表示されるようになったのでOSレベルでは認識していたようだが、Pytorchからは相変わらず認識されなかった。


※後々調べてみたら、以下のページが見つかった。P2系は推奨ではないらしい?
docs.aws.amazon.com

p3.2xlarge

環境構築が終わった時点で Insufficient Error が発生して学習までできなかった。

vasteelab.com

p3.8xlarge

実際は、G4dn系を試した後なので時間軸的には前後するが同一系列なので並べて記載する。

以下の条件でおおよそ 60h程度だった。

  • 学習データ: 約 550万件
  • epoch数: 10
  • bach per device: 16

さらに条件を変更し、以下であれば4h程度。つまり1epochあたり1h。

  • 学習データ: 約 120万件
  • epoch数: 4
  • bert encoder layer: 8
  • bach per device: 24

bert_encoder_layerの数を12から8に減らして計算量を削減し、また、メモリに余裕ができたのでbatchサイズを増やして学習時間を短縮させた。

g4dn.8xlarge

以下の条件でおおよそ630hだった。

  • 学習データ: 約 550万件
  • epoch数: 10
  • bach per device: 16
g4dn.12xlarge

以下の条件でおおよそ 100hだった。

  • 学習データ: 約 300万件
  • epoch数: 10
  • bach per device: 16

GPU数が4つになっているため、単純に4倍速くなっている。

最初はmulti-GPU環境でプログラムがうまく動かなかった。原因は os.environ['CUDA_LAUNCH_BLOCKING'] = "1" を指定していたためだった。
HuggingfaceのTrainerを使っていたので、自動的にmulti-GPU環境に対応はしていたが、blockingモードで動かしていたために、並列実行がハングアウトしていたらしい。

今回学んだこと

  • Instanceのファミリーを変えると起動に失敗(?)する
    • 正確には起動はしていたがsshdの応答がなかった。p3 -> g4dnに変えたときに発生。多分GPUのドライバ周りが問題だったのかなぁ?と予想している。
  • p3系を使う場合は、instance capacityに注意
    • 発生したのが土日だったので、土日に合わせて誰かが大規模に動かしたのかもしれない?特に今回は、データ専用のEBSを付け替えながらの実験だったため、availability-zoneを固定していたのも発生頻発した原因かもしれない。
  • GLIBCXXエラーが派生する場合がある
    • transformersをimportする際に発生した。こちらの記事を参考に解決した。なんとなく、transformersというよりはcuda周りが原因の気がしないでもない。
  • データ件数、GPU数は線形で学習時間に影響する。
    • データ件数もGPU数も顕著に学習時間にn倍の影響を及ぼしていた。(データ件数半分にしたら学習時間も半分)
  • CUDA_LAUNCH_BLOCKING はmulti GPU環境では悪影響
    • わかってしまえば当たり前のことだが、結構ハマった。特に、学習時間を正確に計測したいならつけるべしみたいな記事をよくみていたのでつけるのが普通なのかな?程度の認識だった。

Windows 10 Home 21H2 + WSL2 + Ubuntu 20.04LTS環境にcudaをインストールする

最近、機械学習をいろいろと触っている。その関係で家のゲーミングPCに機械学習の環境を構築はしたけど、知識不足でcuda(GPUを使うやつ)環境はインストールできていない。
以前に導入を試みた際は、Windows 10ではcuda on WSL2が正式サポートされておらず、Windows Instant Preview版を使う必要があるという情報を見ていたため、チャレンジする前にあきらめた。
docs.microsoft.com

上記の情報により、最新版のバージョン21H2では正式にcuda on WSL2がサポートされたとのことなので、早速導入してみた。
今回の記事は自分が導入のために行った手順をまとめたものである。

  • 現在の環境
  • nvidiaのドライバを更新する
  • cudaをインストールする
  • cudaの動作確認
  • 参考
続きを読む

google公式のBERTを2021年の最近の環境で動かしてみる

vasteelab.com
の記事を参考に、BERTの事前学習を動かしてみたときの備忘録をまとめる。2021年12月現在では、tensorflowのバージョンが上がっていたりなどで、記事に書いてある手順通りではうまく動かなかった。自分が行った修正内容などを共有する目的で整理する。

  • 環境
    • OS等
    • Anaconda
  • tensorflowのインストール
  • 穴埋め問題を実行するためのファイル生成を動作させる
    • 発生したエラー
    • 修正方法
  • Pretrainingの実行を動作させる
    • 発生したエラー
    • 修正方法
  • 参考
続きを読む

go-ethereumのGraphQLを利用する

前回の記事から引き続きgo-ethereumから大量データを取得するために、今回はGraphQLを用いる方法について試したことをまとめる。

なお、前回の記事は以下を参照。
y-nakajo.hatenablog.com

  • go-ethereumのGraphQLについて
  • go-ethereumのGraphQLサーバを起動する
  • GraphQLを使ってみる
  • 最後に
続きを読む

go-ethereumのLevelDBを直接読む

ethereumのデータを分析する場合、大量のBlockHeaderやTransaction、Receiptを取得する必要がある。これらの膨大なデータをHTTPを介してJSON-RPCで取得しようとするとかなりの時間を要することとなる。
そのため、今回は大量データ処理をするために直接go-ethereumのLevelDBから値を読みだす方法を調べたのでその内容をまとめる。

  • 試した環境
  • go-ethereumのLevelDBをopenする
  • 最新のblock headerを読みだす
  • block headerをまとめて読みだす
  • block headerのパース
  • ancient DBについて
続きを読む

go-ethereumのpruningを試してみた

今回は、go-ethereumのv1.10から追加されたコマンドである、`go-ethereum snapshot prune-state`を試してみたのでその結果を共有する記事となる。
このコマンドは、go-ethereumのfull nodeを維持すると溜まっていってしまうstate trieのゴミデータを削除(枝切り)するためのコマンドである。つまり、言い換えるとgo-ethereumで肥大化していくストレージの容量を削減することができる。

より詳細な情報については公式ブログを参照。
blog.ethereum.org

  • state trieのゴミデータ
  • 今までpruningが実装されなかった理由
  • v1.10からpruningが実装された理由
  • 実際に試してみた
    • 環境
    • 実行前情報
    • 実行後情報
    • 実行時間
続きを読む