The jonki

呼ばれて飛び出てじょじょじょじょーんき

イラストで分かるNetwork Simplex

先日, 0x-seminar - [0x03] 最適輸送の情報科学における進展 というセミナーがあり,最適輸送について熱い2日があったらしいです.私はセミナーの存在を知らず,後からスライドを見ました.

1日目の資料は横井さんの資料で,そもそも最適輸送ってなんなの?とかNLPと絡めてこんな研究あるよ!っと色々とリンクが貼られていて勉強になりました.

2日目の佐藤さんの資料では,直感的な理解を重要視しつつ,最適輸送の問題をきっちりと定式化していて非常に勉強になりました.270ページぐらいあるのですが,すべて見る価値アリです.

その中でNetwork Simplexという最適輸送における主問題(輸送量のマトリックスを求める)を解く方法を最初に説明しています.Network Simplex法の解き方を誤解を恐れず簡単に言うと,適当な解から初めて違反的な辺がなくなるまで反復的に修正していく手法です.この修正により目的関数は広義単調減少(ゼロ改善もある)です.

なんとなくイメージはできたものの,具体的にどう解けていくのか確かめていくべく自分で問いてみました. 実例と解き方に関しては,Transportation Problem: Balancing | by Rodion Chachura | Medium の事例を参考にしました.この記事はpythonコード付きで分かりやすいです. この記事をざっと眺めた後,以下のスライドを1枚ずつめくっていくとあら不思議,なんとなくわかると思います.

speakerdeck.com

CNNのReceptive field(受容野)を可視するWebアプリを作った

f:id:jonki:20210321093723g:plain

CNNまるでわからん,jojonkiです.CNNを扱う上でReceptive field(受容野)を正しく認識することは,CNNを設計するにあたって非常に重要です(ということを最近認識しました).モデルの表現力が足りない,そんなときReceptive fieldを確認してみるのもよいでしょう.

ただ多段のCNNで組まれたプログラムを見てもReceptive fieldが直感的にわかるには私には経験不足,ということで可視化するツールをWebアプリをGithub pagesで作ってみました. 1次元CNNのカーネルストライド,パディング,ディレーションを指定して可視化できます.最後段のレイヤーの注目データ(赤色のブロック)から最初の入力データに矢印をたどっている色を塗っている領域がReceptive fieldです.Receptive fieldを大きくするためには,カーネルサイズを大きくしても良いですが,計算量が増えるのでストライドやディレーションを挟むことで非常に大きなReceptive fieldを得ることができます.

Visualizing Receptive Field

// コードも公開しているので何かバグを発見した方はissueでご連絡いただけると嬉しいです.



作るにあたって参考にしたページ(興味のある人向け)

Receptive fieldの理解には視覚的な理解が大事だと思うのですが,あまり視覚的に説明してくれるサイトは多くありません(だってビジュアル作るの面倒ですもんね).ただ下記のサイトはReceptive fieldを自分の設計したCNNに応じて可視化してくれます.私が作ったページでも大いに参考にさせていただきました.Receptive fieldの計算だけならこのページだけで良いのですが,CNN越しのビジュアルイメージも欲しかったので今回のものを作りました.

Receptive Field Calculator, Fomoro AI

そもそもCNNや先程でてきた用語がよくわかない?という方はこちらのCNNの解説が参考になると思います.アニメーションもあり素敵です. github.com

Receptive fieldの勉強に関しては,Googleエンジニアの方のブログで勉強にしました.こちらもよく引用されています. もとの系列データのサイズに合わせて可視化することでReceptive fieldがわかりやすくなっています.Receptive fieldの計算式に関しては覚えるものではないので,手元で図を書きながら納得感を持って導けるとよいです.式の導出イメージは人によって違うと思うので自分なりの解釈で良いと思います.またこのブログはディレーションを考慮していないのですが,Receptive field計算式の第2項(前レイヤーのReceptive field両側に対する計算)にディレーションを乗算すれば実現できます(jojonkiの該当コード). medium.com

下記はReceptive fieldの話ではないのですが,Checkerboard Artifactsという問題を可視化しているページです.カーネルストライドを変えることでこの現象が発生する様子を可視化できるツールで非常に素晴らしいです. distill.pub

PCAとLDA

PCA (Principal Component Analysis) と LDA (Linear Discriminant Analysis)について,目的関数の導出やpythonで自力で書いたりしたものをまとめたので公開します. 結構丁寧に書いたつもりです.

github.com

参考文献

M5StackでLINE連携型のCO2センサー

はじめに

在宅勤務も長くなり部屋の換気もサボりがちでCO2センサーを買おうかなと思ったら,怪しい商品しかAmazonで見つけられず.それなら自分でM5Stackで作ってみようかなと思いました.久しぶりの電気工作.以前に話題になってて乗り遅れましたが,今更Join.Arduinoと同じ要領で開発できるのに加えて,ディスプレイ,WiFiBluetooth,SDカードスロットが標準搭載!Arduinoでこれをやろうとすると色々キットを購入したり自分で配線したりと大変なので,だいぶ楽になったもんです.人気なのも頷けます.

作ったものはCO2センサーとして屋内で動かし,不快指数に達したらLINEで通知する,という感じです. CO2濃度が高くなったら画面を黄色くして,LINEに自動で通知,という風にしました. 通知方法は,IFTTTで設定したWebhookにCO2の値をPOSTで送り,LINE通知を使います.LINE通知アカウントができるので,グループに入れて家族と共有することも可能です.

用意するもの

バッテリーモジュールは必要であれば.プロトボードも配線を外に出す場合は不要です.

www.switch-science.com

IFTTT (Webhook -> LINE通知)

特定のアドレスにHTTP POSTすると,LINEに通知を届くようにしておきます.設定方法等は,Webに大量に転がっているので省略します.設定したら生成されたURLをメモしておきます.

配線

配線はシリアル通信用のSCL, SDAと電源及びGNDの4本をつなぐだけです.配線はこちらの方の記事を参考にしました. cami.jp

私はブロック内に配線を隠したかったので,プロトボードにはんだ付けしました.適当なジャンパーで繋ぎます.いまいちプロトボードの使い方わからずむりやり.

コード

M5Stackのソフトウェアはそれなりに大きいのでArduino IDEでは,コンパイル及び転送がめちゃくちゃ遅いです.私のMacbook Pro環境で1回3分ぐらいかかります.ぐぐったところPlatformIOを使うと早くなるということで,VS Code + Platform IO拡張で試したところ30秒もかからなくなりました.すごい.シリアルモニターも使えるし,VS Codeでコードのフォーマットとかも効くのでArduino IDEを使う理由はもうないですね.

コードはこちら.あまりPlatformIOの使い方を分かっていませんが,プロジェクトを作ると main.cpp ができており,これにコードを書くようです.またWiFiSSID,パスワード,IFTTTのURLは,あらかじめSDカード内のテキストファイルに記載しておくことで,コード上のハードコードを避けました.まぁこれはこれで危ないけど. github.com

参考

こちらのサイトの情報を参考にさせて頂きました.CO2に関しては1500ppmを下回ってたほうが良さそうですね.

github.com CCS811 CO2 VOC センサーを制御

まとめ&要調査

エージング等必要なもようでCO2が正しい値を取れているかはまだ実験中.本当は気温や湿度をフィードバックしたほうが良いらしいけど,この辺も含めて調査中.とはいっても正解となるCO2センサーを買ったら元も子もないような汗.

torch.nn.ConvTransposeの可視化

アップサンプリングなどで使われるConvTransposeについて,イマイチ理解できていなかったように思えるので可視化した. Convolutionといえば,conv_arithmeticのGIFが分かりやすいが,ConvTransposeに関しては,通常のConvolutionのように見え,strideやpaddingが通常のConv時とどう違うのか分かりにくいように感じたので,How PyTorch Transposed Convs1D Workを参考に書いてみた.

可視化

これがその図である.Convを逆順にたどるとConvTranposeになっているのがわかると思う. ConvTranpose時のpaddingがやや分かりにくいかもしれないが,どんだけはみ出して始めるか?(はみ出た分は後で捨てる),という考えで見ると分かりやすいかもしれない.

f:id:jonki:20210104211215p:plain

  • 純化のためバッチサイズ及びチャンネル数は1,畳み込み時のチャンネル出力も1に固定.
  • データの流れがわかりやすくなるので,入力データ及びカーネルの値はすべて1に固定.
  • 今回1dだが,2dでも同様.

コード

この図をpytorchで書くとこうなる.

import torch
import torch.nn as nn

x = torch.ones(1,1,6)

enc = nn.Conv1d(1,1,kernel_size=3,padding=2,stride=3,bias=False)
enc.weight.data = torch.ones(1, 1, 3)
dec = nn.ConvTranspose1d(1,1,kernel_size=3,padding=1,stride=2,bias=False)
dec.weight.data = torch.ones(1, 1, 3)

enc(x)
h = enc(x) # shape: (1, 1, 3), data: [[[1,3,2]]]
print('h:', h)
out = dec(h) # shape: (1, 1, 5), data: [[[1,4,3,5,2]]]
print('out:', out)

参考

medium.com

// ちなみに畳み込み全然初心者なので嘘ついてたら教えて下さい.