TensorBoardにおけるデータのSmoothingのアルゴリズム
はじめに
tensorboardでスカラー表示のグラフのところに、smoothingを変更するスライダーがある。 名前的に滑らかさを調節するスライダーということはわかるが、どんなアルゴリズムで滑らかにしてるんだろうと思ったので調べた。
smoothingのアルゴリズム
stack overflowでの回答
stack overflowで回答されているのを見つけた。
ここでの回答によれば、exponential moving average(指数移動平均)というものが使われているらしい。
wikipediaによると、
重みは指数関数的に減少するので、最近のデータを重視するとともに古いデータを完全には切り捨てない(重みは完全にゼロにはならない)。
というものらしい。
時刻tでの値をY[t]とする。時刻tでの指数移動平均をS[t]、係数aとすると、
S_[t] = a * Y_[t-1] + (1 - a) * S_[t-1]
で計算できる。参照元のページも見てみると、 0<=a<1とあり、Y[t-1]はY[t]に置き換えたものもあると書いてある。
tensorboardでの実装
tensorboardのリポジトリでsmoothingしてところ探した。 ここのresmoothDatasetで行っているようだ。
コードで試す
[1, 2, 3, 4, 4, 6, 5, 3]の値にsmoothingしてみる。
scalars=[1,2,3,4,4,6,5,3]
tensorboardのsmoothingの値を0.2にした値は、
[1, 1.833, 2.774, 3.756 ,3.951, 5.59, 5.118, 3.424]
となった。
stack overflowにあった関数をpythonで書いたもの
def smooth(scalars,weight): last=scalars[0] smoothed=[] for point in scalars: smoothed_val=last*weight+(1-weight)*point smoothed.append(smoothed_val) last=smoothed_val return smoothed
weight=0.2で実行してみる。
smoothed=smooth(scalars,0.2) print(smoothed)
出てきたものは、[1.0, 1.8, 2.7600000000000002, 3.7520000000000002, 3.9504, 5.59008, 5.118016, 3.4236032000000005]
近い値は、出てきているが微妙に違う。
tensorboardのコード見に行って書いたのが下のもの。前のものと違う点は、
最初の値に0を使っている(last=0
)のと、debias_weightを計算して、値を保存するときに、smooth_valをdebia_weightで割っているところが違う。
このdebias使う理由は、コードのコメントにかいてある。詳しくはわからないが、偏りが生じるのでそれをなくしているものと捉えている。
def debias_smooth(scalars,weight): last=scalars[0] last=0 smoothed=[] for i,point in enumerate(scalars,start=1): smoothed_val=last*weight+(1-weight)*point last=smoothed_val debias_weight=1-weight**i smoothed_val=smoothed_val/debias_weight smoothed.append(smoothed_val) return smoothed
同様にweigh=0.2で実行する。
smoothed=debias_smooth(scalars,0.2) print(smoothed)
[1.0, 1.8333333333333337, 2.7741935483870974, 3.756410256410257, 3.9513444302176697, 5.590373783922171, 5.118068711279505, 3.423609404440076]
となった。
tensorboard上の値と桁を整えれば一致している。
メモ
stack overflowのコードを式に直したら少し違っていたけど、よく見てみると一緒だった。
wikipediaの式では、
S_[t] = a * Y_[t-1] + (1 - a) * S_[t-1]
となっていた。 コードを直すと、
S_[t] = weight * S_[t-1] + (1 - weight) * Y_[t]
となる。wikipediaの式と違っていたのであれっとなった。
式変形してみる。weight=1-a
とおく。
S_[t] = (1-a) * S_[t-1] + a * Y_[t]
順番入れ替えて、
S_[t] = a * Y_[t] + (1-a) * S_[t-1]
あと違う部分は、Y_[t]
の部分だけだが、wikipediaの参照元のページを見てみると、Y_[t-1]
をY_[t]
に置き換えているものもあるということだったので、
これはこのままでもよさそう。ということで、ほぼ一緒になった。
まとめ
tensorboardのsmoothing処理はexponential moving average(指数移動平均)を用いてsmoothing処理が行われていて、 この指数移動平均は、現在の値に重点を置いてsmoothingする方法である。
参考サイト
AI最先端技術を調べられるサイト
紹介
どんなの
Papwers With Code というサイト。現在のAI研究がどんな研究がされているのか見れる。 AI研究の最先端の論文のとコードのリンクがセットでのっている。論文はだいたいarxivというサイトにある論文のリンクが張ってある。arxivはプレプリントを投稿できるサイト。コードはgithubで公開されているもの。コードはない時もあれば、色々な人が再実装していて、複数ある時もある。フレームワークもpytorchやtensorflowなど様々。pytorchでの実装が欲しいけど、tensorflowの実装しかないこともある。
分野ごとのページ
Browse the State-of-the-Art in Machine Learning | Papers With Code
sota(state-of-the-art)は最先端という意味で、色々な分野の最先端の研究を見つけられる。Computer Vision(画像とか動画とか扱っている)やNatural Language Processing(自然言語処理)などの分野にわかれていて、その中にその分野のタスクがある。Computer Visionの分野だと、Image Classification(画像分類) やObject Detection(物体検出)などのタスクがある。
タスクページ
そのタスクの中の1つimage classificationのページでを見てみる。image classificationのタスクは、与えられた画像に1つのラベルを割り当てていくタスクで、猫画像なら猫というラベルを付けるタスク。leaderboardにそのタスクごとのデータセットがのっている。image classificationのデータセットは、mnist(0から9までの10クラスのラベルが割り振られた白黒画像)やImageNet(1000クラスのラベルが割り振られた画像)などがあり、それぞれ個別のページがある。
データセットページ
ImageNetというデータセットのページを見てみると、上のグラフに円がいくつもある。この円が提案された手法で、横軸が提案された時期で、縦軸がデータセットでの指標となるもので、今回の場合は精度。一番上の線で結ばれているものがsotaのものの推移。 様々な手法が提案されて、精度が上がっていっていることがわかる。しばらくしてまた見に来ると、新しいものが出てきて、sotaになってたりする。進歩がすごく早い。
上の画像の下部分にあるのが、論文とコードがセットになった表で、精度が高い順番に並んでいる。
個人的に気になった研究
Lipreading
唇から言ってることを読み取って文字にする研究
タチコマが唇から読み取っていたのを思い出した。未来感がある。 どこまで読み取れるのかは、リーダーボードがなかったのでわからない。
Face Generation
存在しない人の顔の画像を作る研究
ほぼ、本物の人と見分けがつかないくらいきれいに作れてるのがすごい。 アニメ画像作りたいので、このへんの勉強しなくちゃ。
Code Generation
コード生成の研究
pix2codeのデモが面白かった。 UIのスクリーンショット画像から、htmlを作っていた。 www.youtube.com
おわりに
色々な分野の研究がまとめられているので、どんな研究がなされているのかをぱっと知るのに役に立つ。 論文とコードのリンクもセットでついてるのでとても便利。 また、タスクごとのデータセット調べたりする使い方もできる。
Safebooruからアニメ画像ダウンロード
はじめに
GANでアニメ画像生成したい。そのためには、データとして大量のアニメ画像を集める必要がある。 スクレイピングするのと、動画のSSとる方法があるが、今回は、楽そうな方のスクレイピングで画像集めることにした。
前にアニメデータセット探した中で、sabebooruというサイトを知った。 https://msdd.hatenablog.com/entry/2019/11/21/235937msdd.hatenablog.com
sabebooruは、画像のアーカイブをタグ付きで保存してあるサイトで、検索もできる。
画像が大量に欲しいので、このサイトからダウンロードすることにした。
画像ダウンロード
apiがあったので、それを使った。
api アクセスのurl: https://safebooru.org/index.php?page=dapi&s=post&q=index
limit:どれだけの投稿を検索するか。max100。
pid : ページ数。
tags: 検索するタグ。
などを追加して検索できる。 とりあえず、https://safebooru.org/index.php?page=dapi&s=post&q=indexにアクセスしてみると、xmlが表示されたので、pythonでxmlを扱って、urlから画像ダウンロードするスクリプト作った。
api_strはページ番号pidと検索するtagsを設定した文字列で、これを送りxmlを取得する。
今回は、一人の顔画像が欲しいので、タグはface 1girl solo
のものをダウンロードすることにした。
api_str="https://safebooru.org/index.php?page=dapi&s=post&q=index&pid={pid}&tags={tags}".format(pid=page,tags=request_tags.replace(" ","+")) with urllib.request.urlopen(api_str) as response: content=response.read()
pythonのxmlはElementTreeというもので扱うようだ。xmlをパースした後、それぞれ投稿の画像urlを取得した。一回のリクエストで、100件得られる。
xml=ET.fromstring(content) for post in xml.iter("post"): file_url=post.get("file_url")
これを今回は50回ループさせて、5000枚集めた。サイズは3.3G。集めた画像のサンプルが下の画像。
きちんと、一人のキャラの顔が写っている画像を集めることができた。
今後
このデータを使ってGANでアニメ画像生成していきたい。
コード置き場
参考サイト
PyTorchのネットワーク構造を可視化できるものを探してみた
はじめに
PyTorchでネットワーク構造を見たいけど、何使えばいいかわからなかったので、探した。
import torch import torch.nn as nn import torch.nn.functional as F class TestModel(nn.Module): def __init__(self): super().__init__() self.fc1=nn.Linear(10,5) self.fc2=nn.Linear(5,2) def forward(self,x): x=F.relu(self.fc1(x)) x=F.softmax(self.fc2(x)) return x model=TestModel() print(model)
テストで使うネットワーク。FC層2層のテストモデル。
TestModel( (fc1): Linear(in_features=10, out_features=5, bias=True) (fc2): Linear(in_features=5, out_features=2, bias=True) )
可視化手法
1. onnxに変換してnetronで見る
まず、pytorchのモデルをonnx形式に変換する。
dummy_input=torch.randn(1,10)#ダミーの入力を用意する input_names = [ "input"] output_names = [ "output" ] torch.onnx.export(model, dummy_input, "./test_model.onnx", verbose=True,input_names=input_names,output_names=output_names)
実行すると、下のような出力とtest_model.onnxというonnxファイルが出力される。
graph(%input : Float(1, 10), %fc1.weight : Float(5, 10), %fc1.bias : Float(5), %fc2.weight : Float(2, 5), %fc2.bias : Float(2)): %5 : Float(1, 5) = onnx::Gemm[alpha=1, beta=1, transB=1](%input, %fc1.weight, %fc1.bias), scope: TestModel/Linear[fc1] # /usr/local/lib/python3.6/dist-packages/torch/nn/functional.py:1370:0 %6 : Float(1, 5) = onnx::Relu(%5), scope: TestModel # /usr/local/lib/python3.6/dist-packages/torch/nn/functional.py:914:0 %7 : Float(1, 2) = onnx::Gemm[alpha=1, beta=1, transB=1](%6, %fc2.weight, %fc2.bias), scope: TestModel/Linear[fc2] # /usr/local/lib/python3.6/dist-packages/torch/nn/functional.py:1370:0 %output : Float(1, 2) = onnx::LogSoftmax[axis=1](%7), scope: TestModel # /usr/local/lib/python3.6/dist-packages/torch/nn/functional.py:1317:0 return (%output)
onnx形式に変換後、Netronというもので可視化できる。こののページにonnxファイルをアップロードするとネットワーク構造が見れる。
層の名前は変わってしまうが、きちんと表示されている。
このnetronはonnxに変換せずにもpytorchの保存したファイルでも表示はできるみたい。しかし、サイトには実験的サポートと書いてある。
torch.save(model,"./test_model.pth")
保存されたファイルをアップロードしてみると、ネットワーク構造は表示されたが、relu、log_softmaxが表示されなかった。
2. tensorboard
tensorboardのグラフ表示する機能を使う方法。
google colabのtensorflowのバージョンを2系へ変更して、 tensorboardの拡張を読み込む。
%tensorflow_version 2.x %load_ext tensorboard
add_graphを用いて、モデルの構造の出力する。
from torch.utils.tensorboard import SummaryWriter dummy_input=torch.randn(1,10) writer = SummaryWriter() writer.add_graph(model, dummy_input) writer.close()
tensorboardを起動して、グラフを見る。
%tensorboard --logdir ./runs
ダブルクリックすると、中身も見れる。
3. pytorchvizで見る
pytorchvizを使い、モデルを可視化する。
ライブラリをインストールする。
!apt-get install graphviz !pip install torchviz
次に、モデルを生成し、入力xを通して出力yを得る。 make_dotの引数に出力とモデルのパラメータを入れると、グラフが出てくる。
from torchviz import make_dot model=TestModel() x=torch.randn(1,10)#ダミー入力 y=model(x) make_dot(y,params=dict(model.named_parameters()))
参考サイト
Google Colab上でTensorBoardを使う
はじめに
google colab上でtensorboardを使えるみたいだったので、試してみた。
環境
- 使用ブラウザ: Firefox 71.0
- torch 1.3.1
- torchvision 0.4.2
tensorboard関連のライブラリわからないけど、一応。
- tensorflow 2.1.0rc1
- tensorboard 2.1.0
- tensorboardcolab 0.0.22
実行
ログファイルの準備
今回は、pytorchのtorch.utils.tensorboardを使ってログファイル作った。
tensorflowのバージョンを2系に切り変えておく。
%tensorflow_version 2.x
ログファイルの作成。グラフとスカラー値をログを作った。 グラフは、mobilenet v2のモデルを記録した。
import torch from torch.utils.tensorboard import SummaryWriter import torchvision.models as models model=models.mobilenet_v2() image=torch.randn(1,3,224,224) writer = SummaryWriter() writer.add_graph(model, image) writer.add_scalar("test",1,1) writer.add_scalar("test",2,2) writer.close()
実行すると、runsというフォルダーが出来て、ログが入っている。 これをtensorboard上に表示させてみる。
tensorboardを起動する準備
tensorboard notebookの拡張を読み込む
%load_ext tensorboard
tensorboard起動
%tensorboard
でtensorboarを起動する。--logdir
の後に生成したログフォルダの場所を指定する。
%tensorboard --logdir ./runs
SCALARSにきちんと追加した値がグラフとして表示されている。
GRAPHSの方もmobilenet v2の構造が表示されている。
気になる点、今後
firefoxのプライベートウィンドウで実行すると、下のように403が表示された。
chromeのシークレットウィンドウでも同じことになるのかと思って試してもならなかった。 原因はわからなかった。
学習結果をすぐに見れるのは便利なので、今後学習の時に使っていきたい。
参考サイト
Google Colabで使われているgpuの種類の調査
はじめに
Google ColaboratoryにはGPUガチャがあるよという話 - Qiita
この記事読んで、google colabのgpuでも色々な種類のものがあることを知った。
画像や動画でdeep learningをする時、gpuの性能が重要なことが多い。 deep learningの学習は、多くの時間がかかり、 google colabは、時間制限がある。 そのため学習時は、出来るだけ性能のいいgpuを使いたい。 そこで、どのようなgpuがあるのかを調べてみた。
調べ方は簡単で、コマンド!nvidia-smi
名前長くて見れないやつは!nvidia-smi -L
で
gpuの名前見て、その名前を検索して調べた。
このコマンドは、gpuの名前や使用率を見ることができるコマンドで、よくgpu使用率を見る時に
使用している。
gpuの調査
gpuの種類
実際にgoogle colabを使っていて、割り当てられたものは下のようになった。
自分でgoogle colabを使用していたが、割り当てられたのを見たことがない、未確認のものは下のようになった。
- Tesla T4
全てNvidia Teslaシリーズであった。
短くにまとめてみる。 注意点としては、Tesla K80は2つのgpuのうち1つのみ使えるらしく、Nvidiaの実際のスペック表に書いてあるものの半分だけ使えると思われる。 下の表には半分にした値を載せた。
GPU名前 | 発売日 | メモリ容量 | CUDAコアプロセッサ数 | 単精度浮動小数点性能 | |
---|---|---|---|---|---|
Tesla K80 | 2014年11月 | 12GB | 2496 コア | 4.37 TFLOPS (GPU Boost Clocks), 2.8 TFLOPS (Base Clocks) | |
Tesla P100-PCIE-16GB | 2016年6月 | 16GB | 3584 コア | 9.3 TFLOPS(最大ブースト) | |
Tesla P4 | 2016年9月 | 8GB | 2560 コア | 5.5 TFLOPS(最大ブースト) |
wikipediaを参考にした。
この表を見てみると、メモリ容量に関しては、P100がP4の2倍の16GBもあり、かなり容量が多い。 deep learningでは、メモリを多く使うのでこれはうれしい。コア数でも、やはりP100が多い。 なので、計算速度もP100が速いと思われる。K80とP4は、どちらが速いのかはわからない。
GeForceシリーズと比較
Teslaシリーズは、普段は見ることがないので、よく見る方のgeforceシリーズと比べてみる。 TeslaシリーズのP100と比較した。 GeForceシリーズは、最近のものだとRTX 2080 super,RTX 2070 superなどや、前に売られていたGTX 1080などのシリーズ。
GPU名前 | 発売日 | メモリ容量 | CUDAコアプロセッサ数 | 単精度浮動小数点性能 | |
---|---|---|---|---|---|
Tesla P100-PCIE-16GB | 2016年6月 | 16GB | 3584 コア | 9.3 TFLOPS(最大ブースト) | |
RTX 2080 Ti | 2018年8月 | 11GB | 4352 コア | 12.4 TFLOPS | |
RTX 2070 SUPER | 2019年7月 | 8GB | 2560 コア | 8.2 TFLOPS |
wikipediaを参考にした。
P100と比べると、GeForce RTX 2080 Tiはメモリが5GBほど少ないが、P100より新しいのでコア数は多く演算は早いと思われる。
nvidia-smi
で取得したSS
おわりに
google colabで使われているgpuの種類をnvidia-smi
のコマンドを使って、名前を調べると、
NVIDIA Teslaシリーズのgpuが使われていることがわかった。
さらに、割り当てられたことのある3つのgpuについて、性能やメモリ容量などをまとめてみた。
メモリでは、P100>K80>P4の順で容量が大きく、P100がP4の2倍の16Gとかなり大きい。 計算速度もP100が速い。K80とP4は、どちらが速いのかはわからない。
無料で使わせてもらえるのはとてもありがたい。 ありがたく使わせてもらいますm( )m。
新しいの見つけたら更新していきます。
AIでキャラ画像生成できるサイトまとめ
はじめに
最近、キャラクターの画像をAIで生成できるようになってきているようです。 そこで、そんなキャラ生成が出来るサイトを調べてまとめてみました。
サイトまとめ
This Waifu Does Not Exist
url: https://www.thiswaifudoesnotexist.net/index.html
サイトを開くと、左側に自動生成されたアニメ画像と右側には、同じく自動生成されたアニメプロットが書かれている。 ページは15秒ごとに自動更新されて、アニメキャラが自動で変わっていく。
手動で更新するには、下側にあるボタンを押すことで、更新できる。 また、後進を止めるには、下側にあるボタンの右側のボタン(PAUSE REFRESH)を押すことで止まる。
生成される画像は、サイズが大きく、1024x1024pixelのjpeg画像が生成される。
以下は、生成画像例である。 少し、滲んでいたり、 少し見えている体の部分が色や形がおかしいところがあるが、 きれいに描けている。
MakeGirlsMoe
url: https://make.girls.moe/#/
ページを開いて、設定のところで髪の色などのオプションを指定して、 左側にある生成ボタンを押すことで生成できる。This Waifu Does Not Existと 違いオプションを指定できるので、変更したい点を調整しやすい。
生成画像サイズは256 x 256 pixel のpng画像。
以下は、生成画像例である。 こちらも、首から下の部分がおかしい。顔も描けているが、少し違和感はある。
Waifu Labs
url : https://waifulabs.com/
ページを開くと、下のようなボタンがあるので、それを押すことで、 生成するためのキャラを選ぶページが出てくる。
下の初めの設定のページである。 まずは、ベースとなるキャラを選ぶ。 クリックして選ぶと、次のページへ進む。 このように、ベースとなるキャラ、色、詳細、ポーズを選んでいくことで、 キャラを生成していく。
生成画像サイズは400x400 pixel のpng画像で、 生成画像例は以下である。すごくかわいい。 しかし、どのサイトのものもそうだが、体の部分がやはりいびつ なことが多い。
Chainer-DCGAN
url: http://mattya.github.io/chainer-DCGAN/
上のような画像を作る技術のサンプルのサイトなので、 他のサイトに比べると画像サイズが小さい。 生成画像サイズは96x96 pixel のpng画像で、
生成画像例
参考サイト
Google Colabで変数をフォームでいじれるようにする
Google Colabでフォーム(form)というpythonの変数を簡単に調節できるような機能があったので、使ってみた。
使い方
コードセルを選択した状態で、
右クリックして、フォームの追加をクリック。(挿入 > フォームの項目追加 でもok)、
こんな感じで、タイトルが自動生成される。#@title
とあるように、#から始まっており、pythonでのコメント形式なので実行時には影響がない。
もう一度右クリックしてフォームの追加すると、新しいフォーム フィールドの追加というのが出てくるので、作りたいフォームフィールのタイプ、変数名など設定する。
保存ボタンを押すと、変数とその初期値が生成される。そのあとに、コメントとして #@param
と続き、こちらも実行時には影響がない。
生成したフィールドを書き換えてみると、すぐに左側のコードの方も書き換えた値に変更される。
コードセル選択で右クリック > フォーム > コードを非表示 でコード部分の表示、非表示を切り替えられる。 フォーム部分も同様に表示、非表示を切り替えられる。
フォームの値を変更した時に、自動で変数値変更
下の画像のように、変数のコードセルを実行した後、その変数を違うコードセルで使うことがよくある。
変数の値をフォームで変える時、変数のコードセルを再実行する必要がある。実行を忘れると、前回の変数の状態のままその変数を使うことになってしまう。 変数の値をいじるたびに実行する必要があるので、変数の値を変更したら自動でコードの実行をして変数の値を更新してくれる機能がある。
#@title デフォルトのタイトル テキスト{ run: "auto" }
のようにtitleのところに{ run: "auto" }
を付け加えると、フォームで変数更新した時に自動で再実行してくれる。
フォームフィールドタイプ使用例
フォームフィールドタイプは4つある。
- dropdown
- input
- slider
- markdown
dropdown
プルダウン項目を設定して、作成するとその項目を選べるdropdownができる。
入力を許可することで{allow-input: true}
が生成され、自分で値を入れられるようになる。
input
入力欄に入力することで、値を変更する。 タイプはboolean, date, integer, number, raw, stringから選べる。
slider
スライダーが表示されるもの。スライダーを動かす、数字を入力、上下ボタンをクリックで数字を増やしたり減らしたりできる。最小値、最大値、ステップ幅を決めれる。
markdown
#@markdown ~~aaa~~
のように#@markdown
の後に、マークダウンを書くと、マークダウンの表示結果が右側に出る。
type : rawについて
入力したものがそのまま変数に入る。
最後に
Google Colabでフォームを使ってみました。 機械学習でパラメータを調節することがよくあるので、その時にフォームを使うことで、 調節が楽になるのではないかと思います。 とても便利なので、使ってみてはどうですか。
参考サイト
PyTorchでTensorBoardのエラーが出た
はじめに
前までは、PyTorchでTensorBoardを使う時は、tensorboardX というものを使っていた。 最近では、PyTorchでもtorch.utils.tensorboardを使うことで、tensorboardを使えるようになっている。
このtorch.utils.tensorboard
を使おうとした時に、エラーが出てつまったので、その解決方法を残しておく。
エラー
下のようなコードを実行してエラーが出た。
from torch.utils.tensorboard import SummaryWriter
出たエラーは下のようなものだった。
raise ImportError('TensorBoard logging requires TensorBoard with Python summary writer installed. ' ImportError: TensorBoard logging requires TensorBoard with Python summary writer installed. This should be available in 1.14 or above.
解決法
何通りか解決しそうな方法を試したので、書いておく。
1. TensorBoardのバージョン変更
エラー内容からTensorBoardのバージョンが低いことによるエラーと思われる。
TensorBoardのバージョンを確認して、もし1.14
より低かったら、
1.14
以降のバージョンのTensorBoardをインストールする。
pipでインストールしてるなら、下のようなコマンドで、出てくる。
pip list | grep tensorboard
anacondaとかなら、conda list
を使って、表示されるものから探してみれば見れる。
実際に確認してみたが、きちんと、1.14
以降であったので、これが原因ではなかった。
2. PyTorchのバージョン変更
PyTorchのTensorBoardはどのバージョンでも動くわけではない。 PyTorchでtensorboardが実験的(experimental)に使えるようになったのがv1.1.0で、v1.2.0からはexperimentalが外れて正式に使えるようになった。 なので、PyTorchのバージョンを確認して、もしバージョンがv1.2.0より下ならPyTorchのバージョンを上げる必要がある。 PyTorchのバージョンを確認方法は、下で見ることが出来る。
import torch print(torch.__version__)
実際に確認してみたが、これも、1.2.0
以降のバージョンがインストールされていたので、原因ではなかった。
3. 実行ファイル名をtensorboard.pyというファイル名にする
実行ファイル名がtensorboard.py
であったら変更する。
バージョンも全部そろってるはずなのにエラー出るので、ソースコード見に行った。
try: from tensorboard.summary.writer.record_writer import RecordWriter # noqa F401 except ImportError: raise ImportError('TensorBoard logging requires TensorBoard with Python summary writer installed. ' 'This should be available in 1.14 or above.')
ここで、テスト用で名前をtensorboard.py
という名前にしていまっていることに気が付いた。
tensorboard
という名前が一致しているので、モジュールの読み込みが失敗していた。
ファイル名変えたらエラーが出なくなった。
まとめ
試しに動かしてみたいと、試し用で同じ名前にしてしまったことで、 結構な時間をとられてしまった。 モジュールと同じ名前を付けないように気を付けたい。
PyTorchでニューラルネットワークのパラメータ数を取得する方法
パラメータ取得方法
PyTorchでニューラルネットワークのパラメータを取得する方法として、自分で関数を 書いて求める方法、ライブラリを使って求める方法がある。 その方法を説明していく。
1. 自作関数を書く
自作の関数を使って、PyTorchのネットワークのパラメータ数を求めることが出来る。 作る関数は、下のような関数である。
count_parameters(model)
がネットワーク(model)の全パラメータ数を取得するもので、
count_trainable_parameters(model)
が全ての学習可能なパラメータを取得するものである。
引数は、いずれもパラメータ数を知りたいネットワーク。
中身はすごく単純で、model.parameters()
でネットワークの層を取得して、
そのパラメータ数を数え上げている。count_trainable_parameters
の方では、さらにrequires_grad
がTrue、つまりパラメータが学習可能なもののみを数え上げる。
def count_parameters(model): return sum(p.numel() for p in model.parameters()) def count_trainable_parameters(model): return sum(p.numel() for p in model.parameters() if p.requires_grad)
使い方は、下のようになる。
まず、パラメータ数をしりたいネットワークを読み込む。
下の例では、resnet18
を読み込んでいる。そして、上の関数を適用して
パラメータ数を取得する(count_parameters(model)
の部分)。
2つの関数を2つの条件で試している。
1つ目の条件は重みを固定しない時、もう一つは、ネットワークの重みを固定した時である。
import torch import torchvision #モデル読み込み model=torchvision.models.resnet18() #重み固定なし #パラメータ取得して表示 num_parameters=count_parameters(model) print(num_parameters) num_parameters=count_trainable_parameters(model) print(num_parameters) #重み固定してみる for param in model.parameters(): param.requires_grad=False #パラメータ取得して表示 num_parameters=count_parameters(model) print(num_parameters) num_parameters=count_trainable_parameters(model) print(num_parameters)
結果は、下のようになった。
上の2つは、ネットワークの重みを固定していないときで、どちらのパラメータ取得関数も同じ値となり、ネットワークの全パラメータ数が表示されている。
一方、下の2つは、ネットワークの重みを固定した時の結果で、重みを固定しているので、
パラメータは学習できない状態になるので、学習可能なパラメータ数を得る、count_trainable_parameters()
は、結果として、0を返した。
11689512 11689512 11689512 0
注意点としては、モデルのパラメータをlistで保持しているときちんと数えれない。 listではなくnn.ModuleList()を使うことで、数えることができる。
2. torchsummaryというライブラリを使う方法
PyTorchのパラメータ数を取得するライブラリに、 torchsummaryというライブラリがある。
GitHub - sksq96/pytorch-summary: Model summary in PyTorch similar to `model.summary()` in Keras
このライブラリは便利なもので、 レイヤーごとのに出力サイズとパラメータ数を出してくれて、さらに全体でのパラメータ数も表示してくれる。
使い方
pipでインストールできる。
pip install torchsummary
使い方は、簡単で、 下のmodelのところに、自分のネットワークモデルを入れる。(channel,H,W)を 自分のネットワークの入力の次元に変える。
from torchsummary import summary summary(model, input_size=(channels, H, W))
resnet18
で試してみる。使うPyTorchのモデルをsummary()
の第1引数に
入れて、第2引数に、入力するtensorのサイズ、(3,224,224)を入れた。
import torchvision.models as models from torchsummary import summary model=models.resnet18() summary(model,(3,224,224))
結果は、下のようなものが出力される。
それぞれのLayer
にレイヤーの名前、Output Shape
に第2引数で入れた時の出力のサイズ、
そして、Param #
にパラメータの数が表示される。そして、最後の部分に、
全体のパラメータ数と学習可能なパラメータ数が表示される。
---------------------------------------------------------------- Layer (type) Output Shape Param # ================================================================ Conv2d-1 [-1, 64, 112, 112] 9,408 BatchNorm2d-2 [-1, 64, 112, 112] 128 ReLU-3 [-1, 64, 112, 112] 0 MaxPool2d-4 [-1, 64, 56, 56] 0 Conv2d-5 [-1, 64, 56, 56] 36,864 BatchNorm2d-6 [-1, 64, 56, 56] 128 ReLU-7 [-1, 64, 56, 56] 0 Conv2d-8 [-1, 64, 56, 56] 36,864 BatchNorm2d-9 [-1, 64, 56, 56] 128 ReLU-10 [-1, 64, 56, 56] 0 BasicBlock-11 [-1, 64, 56, 56] 0 Conv2d-12 [-1, 64, 56, 56] 36,864 BatchNorm2d-13 [-1, 64, 56, 56] 128 ReLU-14 [-1, 64, 56, 56] 0 Conv2d-15 [-1, 64, 56, 56] 36,864 BatchNorm2d-16 [-1, 64, 56, 56] 128 ReLU-17 [-1, 64, 56, 56] 0 BasicBlock-18 [-1, 64, 56, 56] 0 Conv2d-19 [-1, 128, 28, 28] 73,728 BatchNorm2d-20 [-1, 128, 28, 28] 256 ReLU-21 [-1, 128, 28, 28] 0 Conv2d-22 [-1, 128, 28, 28] 147,456 BatchNorm2d-23 [-1, 128, 28, 28] 256 Conv2d-24 [-1, 128, 28, 28] 8,192 BatchNorm2d-25 [-1, 128, 28, 28] 256 ReLU-26 [-1, 128, 28, 28] 0 BasicBlock-27 [-1, 128, 28, 28] 0 Conv2d-28 [-1, 128, 28, 28] 147,456 BatchNorm2d-29 [-1, 128, 28, 28] 256 ReLU-30 [-1, 128, 28, 28] 0 Conv2d-31 [-1, 128, 28, 28] 147,456 BatchNorm2d-32 [-1, 128, 28, 28] 256 ReLU-33 [-1, 128, 28, 28] 0 BasicBlock-34 [-1, 128, 28, 28] 0 Conv2d-35 [-1, 256, 14, 14] 294,912 BatchNorm2d-36 [-1, 256, 14, 14] 512 ReLU-37 [-1, 256, 14, 14] 0 Conv2d-38 [-1, 256, 14, 14] 589,824 BatchNorm2d-39 [-1, 256, 14, 14] 512 Conv2d-40 [-1, 256, 14, 14] 32,768 BatchNorm2d-41 [-1, 256, 14, 14] 512 ReLU-42 [-1, 256, 14, 14] 0 BasicBlock-43 [-1, 256, 14, 14] 0 Conv2d-44 [-1, 256, 14, 14] 589,824 BatchNorm2d-45 [-1, 256, 14, 14] 512 ReLU-46 [-1, 256, 14, 14] 0 Conv2d-47 [-1, 256, 14, 14] 589,824 BatchNorm2d-48 [-1, 256, 14, 14] 512 ReLU-49 [-1, 256, 14, 14] 0 BasicBlock-50 [-1, 256, 14, 14] 0 Conv2d-51 [-1, 512, 7, 7] 1,179,648 BatchNorm2d-52 [-1, 512, 7, 7] 1,024 ReLU-53 [-1, 512, 7, 7] 0 Conv2d-54 [-1, 512, 7, 7] 2,359,296 BatchNorm2d-55 [-1, 512, 7, 7] 1,024 Conv2d-56 [-1, 512, 7, 7] 131,072 BatchNorm2d-57 [-1, 512, 7, 7] 1,024 ReLU-58 [-1, 512, 7, 7] 0 BasicBlock-59 [-1, 512, 7, 7] 0 Conv2d-60 [-1, 512, 7, 7] 2,359,296 BatchNorm2d-61 [-1, 512, 7, 7] 1,024 ReLU-62 [-1, 512, 7, 7] 0 Conv2d-63 [-1, 512, 7, 7] 2,359,296 BatchNorm2d-64 [-1, 512, 7, 7] 1,024 ReLU-65 [-1, 512, 7, 7] 0 BasicBlock-66 [-1, 512, 7, 7] 0 AdaptiveAvgPool2d-67 [-1, 512, 1, 1] 0 Linear-68 [-1, 1000] 513,000 ================================================================ Total params: 11,689,512 Trainable params: 11,689,512 Non-trainable params: 0 ---------------------------------------------------------------- Input size (MB): 0.57 Forward/backward pass size (MB): 62.79 Params size (MB): 44.59 Estimated Total Size (MB): 107.96 ----------------------------------------------------------------
前の自作関数のものと比べると、パラメータ数が同じになっているので、正しいことがわかる。
各層ごとのパラメータも見れて、とても便利である。
バグ
しかし、githubのissueを見てみると、パラメータ共有をしていると、バグってしまう と書いてあった。パラメータ共有をしているネットワークを使う時には、このライブラリ 以外でも確認した方がよさそうである。
まとめ
PyTorchのネットワークのパラメータ数を取得する方法として、自分で関数を作って求める方法と、torchsummaryというライブラリを使って取得する方法を紹介した。 torchsummaryは、importして、summary関数のみで、各層のパラメータ数など様々な情報を表示できるので、個人的にはtorchsummaryを使う方法の方がいいと思う。しかし、パラメータ共有などを使っている時は、バグっているので注意が必要。