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

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

infura.ioを使ってBeacon Chain(ETH2.0)からBlockの情報を取得する

今回はBeacon Chainのblock情報をinfura.ioを使って取得する方法について記事にする。

twitterで話題になっている、reorgについて何が起きてるのかを調べるためにblockの情報を見てみたいなぁと思ったのがきっかけである。

なお、自前でnodeを立てるのは少し大変なので、infura.ioを使ってBeacon ChainのBlock情報などを取得する。
しかしながら、infura.ioを使ってBeacon Chainの情報を取得する方法をまとめた記事が少し調べただけだと見つからなかったので、今回記事として残しておこうと思った。

  • Clientツール
  • infura.ioでETH2.0のプロジェクトを作成
  • Beacon ChainのREST API
  • genesisデータを取得
  • blockの情報を取得
続きを読む

Docker環境でnltk.Treeグラフをpngとして出力する

今回も機械学習関連の記事である。
nltk.TreeのデータをPNG画像として出力したかったのですが、Docker環境で開発を行なっていた関係でちょっと手こずってしまった。
Docker環境でPNGを出力させる方法がなかなか見つからなかったので、記事としてまとめておく。

結論としては、以下のstackoverflowの回答でうまくいった。
stackoverflow.com

  • よくみる回答
  • 発生したエラー
  • エラーの原因
  • 解決方法
  • 余談:pngの背景を白に変更する方法
続きを読む

Attention Flowを追実験したい

最近は自然言語学習モデルのBERTを活用した実験を行っている。その中で、Attentionで何が表現されているのか?について興味が出てきた。
とあるツテから以下の論文を紹介してもらったので、この論文の中に出てきているサンプルコードを動かしたいというのが今回の記事の内容である。

https://arxiv.org/abs/2005.00928

なお、サンプルコードは動かせていないので、現時点までで把握した内容についての作業メモを記事として残す。

動かしたいサンプルコード

github.com

論文中に実験に用いたコードのgithubが紹介されていたので、そこにあるサンプルコードを動かす。今回の対象は↑のJyupiter Notebookファイル。
これをgoogle colabで動かそうとしている最中である。

大まかな問題点

HuggingfaceのTransformersを使っている。が、そのバージョンが古すぎるのが問題。論文作成時点でのバージョンは4.10.0だった。
現在の最新版(この記事執筆時点である2022/04/02)では4.18.0である。また、自分が今使っているバージョンは4.16.2なので、以降は基本的にtransformers==4.16.2で動かす方法である。

特に動いていない部分は、Tensorflowベースのモデルをpytorchベースに変換している部分であった。

修正箇所一覧

ここでは、次の作業のために、現時点で認識できている修正箇所を羅列する。

import部分

from transformers import *

ここの表記は最新版ではできない。

from  transformers import  (AutoTokenizer. AutoModel)

とかに書き換えたらよい。

tokenizerとmodelのマッピングとロード部分

MODELS = [(BertModel,       BertTokenizer,       'bert-base-uncased'),
          (OpenAIGPTModel,  OpenAIGPTTokenizer,  'openai-gpt'),
          (GPT2Model,       GPT2Tokenizer,       'gpt2'),
          (CTRLModel,       CTRLTokenizer,       'ctrl'),
          (TransfoXLModel,  TransfoXLTokenizer,  'transfo-xl-wt103'),
          (XLNetModel,      XLNetTokenizer,      'xlnet-base-cased'),
          (XLMModel,        XLMTokenizer,        'xlm-mlm-enfr-1024'),
          (DistilBertModel, DistilBertTokenizer, 'distilbert-base-uncased'),
          (RobertaModel,    RobertaTokenizer,    'roberta-base')]

# Each architecture is provided with several class for fine-tuning on down-stream tasks, e.g.
BERT_MODEL_CLASSES = [BertModel, BertForPreTraining, BertForMaskedLM, BertForNextSentencePrediction,
                      BertForSequenceClassification, BertForTokenClassification, BertForQuestionAnswering]

このマッピングはそもそも不要。Auto系が全部やってくれるので丸々コメントアウトでよい。

# Each architecture is provided with several class for fine-tuning on down-stream tasks, e.g.
BERT_MODEL_CLASSES = [BertModel, BertForPreTraining, BertForMaskedLM, BertForNextSentencePrediction,
                      BertForSequenceClassification, BertForTokenClassification, BertForQuestionAnswering]

# All the classes for an architecture can be initiated from pretrained weights for this architecture
# Note that additional weights added for fine-tuning are only initialized
# and need to be trained on the down-stream task
pretrained_weights = 'bert-base-uncased'
tokenizer = BertTokenizer.from_pretrained(pretrained_weights)

model = BertModel.from_pretrained(pretrained_weights,
                                    output_hidden_states=True,
                                    output_attentions=True)

そして、上記箇所を以下に書き換える

pretrained_weights = 'bert-base-uncased'
tokenizer = AutoTokenizer.from_pretrained(pretrained_weights)

model = AutoModel.from_pretrained(pretrained_weights,
                                    output_hidden_states=True,
                                    output_attentions=True)

sst2のデータセットがロードできない問題

data = tfds.load('glue/sst2')

# Prepare dataset for GLUE as a tf.data.Dataset instance
train_dataset = glue_convert_examples_to_features(data['train'], tokenizer, max_length=128, task='sst2')
valid_dataset = glue_convert_examples_to_features(data['validation'], tokenizer, max_length=128, task='sst2')
train_dataset = train_dataset.shuffle(100).batch(32).repeat(10)
valid_dataset = valid_dataset.batch(64)

valid_iter = iter(valid_dataset)

このコードブロックが動かなかった。理由は、tensorflowが公開しているはずの、GLUE/SST-2のデータセットが403エラーでダウンロードできないため。

ただ、よくよくコードを読むと多分ここはAttentionを抽出するためにBERTに流し込むdatasetを取ってきているだけに見える。
なので、huggingface/datasetsのload_datasetで置き換えればよさそう。

TFTFBertForSequenceClassificationをpytorchベースに変換している部分

model = TFBertForSequenceClassification.from_pretrained('bert-base-uncased')

# Prepare training: Compile tf.keras model with optimizer, loss and learning rate schedule 
optimizer = tf.keras.optimizers.Adam(learning_rate=3e-5, epsilon=1e-08, clipnorm=1.0)
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
metric = tf.keras.metrics.SparseCategoricalAccuracy('accuracy')
model.compile(optimizer=optimizer, loss=loss, metrics=[metric])

# Train and evaluate using tf.keras.Model.fit()
history = model.fit(train_dataset, epochs=10, steps_per_epoch=115,
                    validation_data=valid_dataset, validation_steps=7)

x,y = valid_iter.next()
print(x['input_ids'][0])

# Load the TensorFlow model in PyTorch for inspection
model.save_pretrained('save/')

pytorch_model = BertForSequenceClassification.from_pretrained('save/', from_tf=True, output_hidden_states=True,
                                    output_attentions=True)

この辺のコードはTensorflowベースのBERTモデルをpytorchベースに変換してるコードっぽい。
transformers 4.16.2であれば、最初からpytorchベースのBERTモデルをロードできるので多分このコードは不要。

今の段階でコードを整理できているのはここまで。

すでに修正済みにColabがあった。。。

と、この記事を書きつつなにげにgithubのREADMEを見ていたら上記の修正を実施したGoogle Colabのリンクがありました。。。。
colab.research.google.com

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の実行を動作させる
    • 発生したエラー
    • 修正方法
  • 参考
続きを読む