msdd’s blog

deep learning勉強中。プログラム関連のこと書きます。

TensorBoardにおけるデータのSmoothingのアルゴリズム

はじめに

tensorboardでスカラー表示のグラフのところに、smoothingを変更するスライダーがある。 名前的に滑らかさを調節するスライダーということはわかるが、どんなアルゴリズムで滑らかにしてるんだろうと思ったので調べた。

f:id:msdd:20191229172903p:plain
smoothingスライダー

smoothingのアルゴリズム

stack overflowでの回答

stack overflowで回答されているのを見つけた。

stackoverflow.com

ここでの回答によれば、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の実装しかないこともある。

f:id:msdd:20191208194145p:plain

分野ごとのページ

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(物体検出)などのタスクがある。

f:id:msdd:20191228005325p:plain
分野ごとに分かれている

タスクページ

そのタスクの中の1つimage classificationのページでを見てみる。image classificationのタスクは、与えられた画像に1つのラベルを割り当てていくタスクで、猫画像なら猫というラベルを付けるタスク。leaderboardにそのタスクごとのデータセットがのっている。image classificationのデータセットは、mnist(0から9までの10クラスのラベルが割り振られた白黒画像)やImageNet(1000クラスのラベルが割り振られた画像)などがあり、それぞれ個別のページがある。

f:id:msdd:20191208200635p:plain

データセットページ

ImageNetというデータセットのページを見てみると、上のグラフに円がいくつもある。この円が提案された手法で、横軸が提案された時期で、縦軸がデータセットでの指標となるもので、今回の場合は精度。一番上の線で結ばれているものがsotaのものの推移。 様々な手法が提案されて、精度が上がっていっていることがわかる。しばらくしてまた見に来ると、新しいものが出てきて、sotaになってたりする。進歩がすごく早い。

f:id:msdd:20191228013708p:plain
ImageNetのページ

上の画像の下部分にあるのが、論文とコードがセットになった表で、精度が高い順番に並んでいる。

個人的に気になった研究

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は、画像のアーカイブをタグ付きで保存してあるサイトで、検索もできる。

f:id:msdd:20191223023843p:plain
safebooru

画像が大量に欲しいので、このサイトからダウンロードすることにした。 

画像ダウンロード

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から画像ダウンロードするスクリプト作った。

f:id:msdd:20191223055405p:plain
xml

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。集めた画像のサンプルが下の画像。

f:id:msdd:20191225005237p:plain
サンプル

きちんと、一人のキャラの顔が写っている画像を集めることができた。

今後

このデータを使ってGANでアニメ画像生成していきたい。

コード置き場

github.com

参考サイト

safebooru.org qiita.com note.nkmk.me

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で見る
  2. tensorboardで見る
  3. PyTorchVizで見る

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ファイルをアップロードするとネットワーク構造が見れる。

f:id:msdd:20191218023623p:plain
netronでonnxファイルを可視化
層の名前は変わってしまうが、きちんと表示されている。

このnetronはonnxに変換せずにもpytorchの保存したファイルでも表示はできるみたい。しかし、サイトには実験的サポートと書いてある。

torch.save(model,"./test_model.pth")

保存されたファイルをアップロードしてみると、ネットワーク構造は表示されたが、relu、log_softmaxが表示されなかった。

f:id:msdd:20191218023811p:plain
netronでpytorch形式のファイルを可視化

2. tensorboard

tensorboardのグラフ表示する機能を使う方法。

msdd.hatenablog.com

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

f:id:msdd:20191222025725p:plain
tensorboardグラフ

ダブルクリックすると、中身も見れる。

f:id:msdd:20191222025901p:plain
tensorboardグラフ詳細

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()))

f:id:msdd:20200114141431p:plain
pytorchvizでモデル構造を可視化したもの

参考サイト

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にきちんと追加した値がグラフとして表示されている。

f:id:msdd:20191219170409p:plain
tensorboard起動時のSCALARS画面

GRAPHSの方もmobilenet v2の構造が表示されている。

f:id:msdd:20191219170622p:plain
tensorboard GRAPHS画面

気になる点、今後

firefoxのプライベートウィンドウで実行すると、下のように403が表示された。

f:id:msdd:20191219171802p:plain

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使用率を見る時に 使用している。

f:id:msdd:20200503133137j:plain

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

f:id:msdd:20191217213323p:plain
Tesla K80

f:id:msdd:20191214194622p:plain
Tesla P4

f:id:msdd:20191215022726p:plain
Tesla P100-PCIE-16GB

おわりに

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秒ごとに自動更新されて、アニメキャラが自動で変わっていく。

f:id:msdd:20200511140615p:plain
This Waifu Does Not Existのページ

手動で更新するには、下側にあるボタンを押すことで、更新できる。 また、後進を止めるには、下側にあるボタンの右側のボタン(PAUSE REFRESH)を押すことで止まる。

f:id:msdd:20200511140904p:plain

生成される画像は、サイズが大きく、1024x1024pixelのjpeg画像が生成される。

以下は、生成画像例である。 少し、滲んでいたり、 少し見えている体の部分が色や形がおかしいところがあるが、 きれいに描けている。

f:id:msdd:20191127010446p:plain f:id:msdd:20191127010705p:plain

MakeGirlsMoe

url: https://make.girls.moe/#/

ページを開いて、設定のところで髪の色などのオプションを指定して、 左側にある生成ボタンを押すことで生成できる。This Waifu Does Not Existと 違いオプションを指定できるので、変更したい点を調整しやすい。

f:id:msdd:20191127011442p:plain
サイト

生成画像サイズは256 x 256 pixel のpng画像。

以下は、生成画像例である。 こちらも、首から下の部分がおかしい。顔も描けているが、少し違和感はある。

f:id:msdd:20191127011620p:plain f:id:msdd:20191127204459p:plain


Waifu Labs

url : https://waifulabs.com/

f:id:msdd:20191127011331p:plain
サイト

ページを開くと、下のようなボタンがあるので、それを押すことで、 生成するためのキャラを選ぶページが出てくる。

f:id:msdd:20200511143056p:plain

下の初めの設定のページである。 まずは、ベースとなるキャラを選ぶ。 クリックして選ぶと、次のページへ進む。 このように、ベースとなるキャラ、色、詳細、ポーズを選んでいくことで、 キャラを生成していく。

f:id:msdd:20200511143143p:plain
生成過程のページ

生成画像サイズは400x400 pixel のpng画像で、 生成画像例は以下である。すごくかわいい。 しかし、どのサイトのものもそうだが、体の部分がやはりいびつ なことが多い。

f:id:msdd:20191127205223p:plain f:id:msdd:20191127205231p:plain

Chainer-DCGAN

url: http://mattya.github.io/chainer-DCGAN/

上のような画像を作る技術のサンプルのサイトなので、 他のサイトに比べると画像サイズが小さい。 生成画像サイズは96x96 pixel のpng画像で、

f:id:msdd:20191127211551p:plain
サイト

生成画像例

f:id:msdd:20191127211444p:plain f:id:msdd:20191127211717p:plain


参考サイト

Google Colabで変数をフォームでいじれるようにする

Google Colabでフォーム(form)というpythonの変数を簡単に調節できるような機能があったので、使ってみた。

使い方

コードセルを選択した状態で、 f:id:msdd:20191126013109p:plain

右クリックして、フォームの追加をクリック。(挿入 > フォームの項目追加 でもok)、 f:id:msdd:20191126013040p:plain

こんな感じで、タイトルが自動生成される。#@titleとあるように、#から始まっており、pythonでのコメント形式なので実行時には影響がない。 f:id:msdd:20191126013148p:plain

もう一度右クリックしてフォームの追加すると、新しいフォーム フィールドの追加というのが出てくるので、作りたいフォームフィールのタイプ、変数名など設定する。 f:id:msdd:20191126011516p:plain

保存ボタンを押すと、変数とその初期値が生成される。そのあとに、コメントとして #@param と続き、こちらも実行時には影響がない。 f:id:msdd:20191126013614p:plain

生成したフィールドを書き換えてみると、すぐに左側のコードの方も書き換えた値に変更される。

f:id:msdd:20191126235646g:plain

コードセル選択で右クリック > フォーム > コードを非表示 でコード部分の表示、非表示を切り替えられる。 フォーム部分も同様に表示、非表示を切り替えられる。 f:id:msdd:20191127201700g:plain

フォームの値を変更した時に、自動で変数値変更

下の画像のように、変数のコードセルを実行した後、その変数を違うコードセルで使うことがよくある。 f:id:msdd:20191127014655p:plain

変数の値をフォームで変える時、変数のコードセルを再実行する必要がある。実行を忘れると、前回の変数の状態のままその変数を使うことになってしまう。 変数の値をいじるたびに実行する必要があるので、変数の値を変更したら自動でコードの実行をして変数の値を更新してくれる機能がある。

#@title デフォルトのタイトル テキスト{ run: "auto" }のようにtitleのところに{ run: "auto" }を付け加えると、フォームで変数更新した時に自動で再実行してくれる。 f:id:msdd:20191127194103g:plain

フォームフィールドタイプ使用例

フォームフィールドタイプは4つある。

  • dropdown
  • input
  • slider
  • markdown

プルダウン項目を設定して、作成するとその項目を選べるdropdownができる。 入力を許可することで{allow-input: true}が生成され、自分で値を入れられるようになる。 f:id:msdd:20191127013240p:plain

input

入力欄に入力することで、値を変更する。 タイプはboolean, date, integer, number, raw, stringから選べる。 f:id:msdd:20191127012427p:plain

slider

スライダーが表示されるもの。スライダーを動かす、数字を入力、上下ボタンをクリックで数字を増やしたり減らしたりできる。最小値、最大値、ステップ幅を決めれる。 f:id:msdd:20191127012248p:plain

markdown

#@markdown ~~aaa~~のように#@markdownの後に、マークダウンを書くと、マークダウンの表示結果が右側に出る。

f:id:msdd:20191127012043p:plain

type : rawについて

入力したものがそのまま変数に入る。 f:id:msdd:20191127195520p:plain

最後に

Google Colabでフォームを使ってみました。 機械学習でパラメータを調節することがよくあるので、その時にフォームを使うことで、 調節が楽になるのではないかと思います。 とても便利なので、使ってみてはどうですか。

参考サイト

colab.research.google.com

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を使う方法の方がいいと思う。しかし、パラメータ共有などを使っている時は、バグっているので注意が必要。

参考サイト