Raspberry Pi対応ロボットAlphabot2をC++から動かす
Raspberry Piから制御できるロボットであるAlphabot2を手に入れたので,組み立ててC++から動かしてみる.



最初ニッケル水素電池を挿して動かそうとしたが稼働しなかった(電圧不足). リチウム電池に変えたらちゃんと動いた.
また,このAlphabot2はmicro USBポートから充電できるので,充電池を挿してあげると何回も使えて良さそう.
C++からwiringPiを使ってラズパイのGPIOに信号を送ってみる. WiringPiのPWM出力用の関数を使って,サーボ制御のためのPWM信号を出力する.
#include <wiringPi.h> #include <stdio.h> int RIGHT_FORWARD = 29; int LEFT_FORWARD = 23; int main(){ wiringPiSetup(); pinMode(LED,OUTPUT); while (1){ digitalWrite(RIGHT_FORWARD,HIGH); digitalWrite(LEFT_FORWARD,HIGH); delay(1000); digitalWrite(RIGHT_FORWARD, LOW); digitalWrite(LEFT_FORWARD, LOW); delay(1000); } }
$ g++ test.cc -lwiringPi -lcrypto -I<path to wiringPi> -lpthread -lcrypt -lrt
上記のようなコードをラズパイ上で実行することで,きちんとホイールが回転するか確認できる.
これにEdge TPUを積んだりすると面白そう.
ベイズ推論の概要(パラメータの事後分布と予測分布)
ベイズ学習の基本であるパラメータの事後分布および未観測データの予測分布の計算についての概要.
一般的に,機械学習モデルのもつパラメータをデータから決定することを学習と呼ぶ. ベイズ推論の枠組みでは,パラメータも何らかの不確実性を持っているような確率変数として扱う. この不確実性を持つパラメータの事後分布をデータの観測によって求めることが学習にあたる.
また,このようにして得られたモデルのパラメータに基づいて,未観測データに対する推論を行う際も,予測分布を確率推論を用いて求める.
パラメータの事後分布
訓練データ集合をとする.
ベイズ学習では同時分布
について考えることで,データを表現するようなモデルを構築する.
はモデルに含まれる未知のパラメータであり,観測されていないものとする.
パラメータ
に関する事前の不確実性は事前分布
を与えることでモデルに反映させることができる.
また,はあるパラメータ
からどのようにしてデータ
が発生するのかを記述している.
この
をパラメータ
についての尤度関数と呼ぶ.
データを観測したあとでは,パラメータの不確実性はベイズの定理を用いて以下のように更新される:
この条件付き分布の計算がベイズ学習における学習にあたる.
予測分布
学習された分布を用いて,未観測のデータに対する予測分布
を計算したい.
データ
,未知データ
, パラメータ
に関する同時分布は,
となる.
現在,データのみが手元にあるとすると,残りの変数の事後分布は,
上記の式においてパラメータを積分除去すると,
となり,求めたい予測分布が得られる.
Edge TPU USB Acceleratorでモデルの再学習を試してみた
Edge TPUを用いて,自作データセットによるClassifierの再学習(転移学習)を試してみた.

Edge TPUでは,サーバで分類モデルを再学習する代わりに,ImprintingEngine APIを使用してEdge TPU上で転移学習を実行することができる.
Edge TPUのImprintingEngine APIはCVPR2018で提案されたLow-shot learning with imprinted weights [1]を用いて転移学習を実現する.
この手法は,再学習の際にbackwardが必要ないため,Edge TPU上で高速に再学習を実行することが出来る.
Edge TPU APIのインストール
$ wget http://storage.googleapis.com/cloud-iot-edge-pretrained-models/edgetpu_api.tar.gz $ tar xzf edgetpu_api.tar.gz $ cd python-tflite-source $ bash ./install.sh
Feature extractorのダウンロード
特徴抽出を行うためのpretrained modelをダウンロードする.
$ wget http://storage.googleapis.com/cloud-iot-edge-pretrained-models/canned_models/mobilenet_v1_1.0_224_quant_embedding_extractor_edgetpu.tflite
データセットの準備
今回はハムスターとモルモットを分類してみる.

以下のようなディレクトリ構造で画像を保存しておく.
サブディレクトリ一つが一つの分類クラスに対応する.
cavy_hamster/
├── cavy
│ ├── 0000006.jpg
│ ├── 000001.jpg
│ ├── 000002.jpg
│ ├── 000003.jpg
│ ├── 000004.jpg
│ ├── 000005.jpg
└── hamster
├── 000001.jpg
├── 000002.jpg
├── 000003.jpg
├── 000004.jpg
├── 000005.jpg
今回は,各クラスで20枚ずつ画像を用意した.
学習の実行
Edge TPU USB AcceleratorをUSB接続した状態で以下を実行する.
$ python3 demo/classification_transfer_learning.py --extractor mobilenet_v1_1.0_224_quant_embedding_extractor_edgetpu.tflite --data /cavy_hamster --output cavy_model.tflite --test_ratio 0.95
- extractor: Edge TPU用にコンパイルした特徴抽出モデル
- data: 用意したデータセット
- output: Edge TPUで転移学習した結果のモデルの保存先
- test_ratio: テストに用いる画像の割合
学習結果
$ python3 demo/classification_transfer_learning.py --extractor mobilenet_v1_1.0_224_quant_embedding_extractor_edgetpu.tflite --data /cavy_hamster --output cavy_model.tflite --test_ratio 0.95 ---------------------- Args ---------------------- Embedding extractor : .//mobilenet_v1_1.0_224_quant_embedding_extractor_edgetpu.tflite Data set : .//cavy_hamster Output path : .//cavy_model.tflite Ratio of test images: 95% --------------- Parsing data set ----------------- Dataset path: .//cavy_hamster Image list successfully parsed! Category Num = 2 W third_party/darwinn/driver/package_registry.cc:65] Minimum runtime version required by package (5) is lower than expected (10). ---------------- Processing training data ---------------- This process may take more than 30 seconds. Processing category: cavy Processing category: hamster ---------------- Start training ----------------- W third_party/darwinn/driver/package_registry.cc:65] Minimum runtime version required by package (5) is lower than expected (10). ---------------- Training finished! ----------------- Model saved as : .//cavy_model.tflite Labels file saved as : .//cavy_model.txt ------------------ Start evaluating ------------------ W third_party/darwinn/driver/package_registry.cc:65] Minimum runtime version required by package (5) is lower than expected (10). Evaluating category [ cavy ] Evaluating category [ hamster ] ---------------- Evaluation result ----------------- Top 1 : 86% Top 2 : 100% Top 3 : 100% Top 4 : 100% Top 5 : 100%
再学習後には,以下が出力として得られる.
- cavy_model.tflite: 再学習後モデル
- cavy_model.txt: ラベルファイル
ラベルファイルは以下のフォーマットで保存されている.
$ cat cavy_model.txt 0 cavy 1 hamster
再学習したモデルを試す
先程学習したモデルをロードして,新しい入力画像に対して分類を行ってみる.
$ python3 demo/classify_image.py --model ./cavy_model.tflite --label ./cavy_model.txt --image test.jpg --------------------------- cavy Score : 0.71953125 --------------------------- hamster Score : 0.28046875
参考
- [1] Qi, Hang, Matthew Brown, and David G. Lowe. "Low-shot learning with imprinted weights." Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2018.
機械学習における正則化
一般的に教師あり学習モデルは,任意の損失関数に対してデータの「当てはまり具合」を最適化するように関数を選択する.
しかし,この関数が与えられたデータに対してあまりに複雑すぎると,今現在手元にある学習データのみに適合してしまい,未知のデータに弱くなってしまう過学習(over fitting)を引き起こしてしまう.
過学習は,モデルが複雑な場合に訓練誤差と汎化誤差の間に大きな差が生じてしまうことに起因する.
正則化
過学習を避ける方法として,より単純なモデルを選ぶといったモデルの選択の他に,正則化(regularization)が存在する.
ここで,モデルの選択も正則化も,データにふさわしい適切な複雑さの関数を選択するという意味では本質的には同じと捉えられる.
正則化は,モデルの訓練誤差を最小化する際,そのモデルの「複雑」さに対する罰則を加えて最小化を行う.
この「複雑さ」を定義する関数を正則化関数(regularization function)と呼ぶ.正則化関数をとすると,一般的な正則化学習法は,
ここでは正則化の強さを調整するパラメータ.上式は,データへの当てはまり具合を表す第一項とモデルの複雑さへの罰則を表す第二項から成り立っている.この罰則項の働きによってモデルの過学習を抑えることができる.
線形モデルについて,正則化項
としたとき,以下のような正則化関数がよく用いられる.
- リッジ正則化 [1]:
- L1正則化 [2]:
- ブリッジ正則化 [3]:ある
を用いて,
- エラスティックネット正則化 [4]:ある
]を用いて,
- SCAD (smoothly clipped absolute deviation) [5]:ある
と
を用いて,
上記から,ブリッジ正則化はL1正則化とリッジ正則化の一般化であることがわかる(のときL1正則化,
のときリッジ正則化).
また,SCAD正則化は非凸関数であるが,
で勾配が0になるため推定量にバイアスが乗りにくい.
最も単純なモデルである線形モデルであったとしても,次元が高い場合は自由度が高くなり,過学習を起こす可能性が存在してしまうため,上記のような正則化を用いることで過学習をを回避することができる.

スパース正則化としてのL1正則化
L1正則化は,学習結果をスパースにさせやすいという性質を持っている.ここで学習結果
がスパースであるとは,
の多くの成分が0であるという意味.
これは,予測に必要のない無駄な特徴量を切り捨てて,特徴選択を行っているとみなせる.
古くから,そうした特徴選択を実現する手法として赤池情報量基準(Akaike information criterion, AIC)が用いられてきた.例えば回帰において,ノイズが分散がのガウス分布に従っているとき,
であるような設定を考える.このとき,赤池情報量基準に従った特徴選択は,
ここで,pは
の非ゼロ要素の数で,
ノルムと呼ばれる.
を訓練誤差に足すのは,汎化誤差と訓練誤差の差を補うためであり,特徴量の数を罰則として訓練誤差に足すことで,学習結果をスパースにできる.より多くの特徴量を用いることは,それだけ複雑な関数を用いることに等しくなり,現在手元にある訓練データに当てはまりやすく,訓練誤差と汎化誤差の乖離が大きくなってしまう.AICはこのような乖離を補正するためには
を足せば良いと主張している.
がサンプル数より十分小さいとき,
となる.左辺は目的関数の訓練データの出方に対する期待値,右辺の第一項は汎化誤差の期待値,第二項はサンプルサイズが増えるに連れて消えていく項になる.
AICは汎化誤差の不偏推定量であり,AICを最小化する推定量は過学習を避けて正しく汎化誤差を小さくすることができる.しかし,次元が大きい場合,AICの最小化は組み合わせ最適化問題となり,NP困難であることが知られている.
そこで,ノルムの代わりに
ノルムという凸関数を用いるというのが
正則化の発想.実際,
ノルムは
ノルムを下から抑える最大の凸関数になっており,最適化の際に非常に都合が良い.
また,L1正則化を用いた線形回帰手法をLassoと呼ぶ.
L1正則化のようにスパースな学習結果を導く正則化をスパース正則化という.
スパース正則化
スパース正則化は,高次元な学習問題において非常に強力な手法である. ここで,スパース性をより広く,ある種の低次元性と捉えると,他にも様々なスパース正則化が考えられる.
グループ正則化
特徴量がいくつかのグループに分かれていると仮定する.グループ正則化は,同じグループに属する特徴量をまとめて一つの特徴量のように扱うスパース正則化である.グループをそれぞれインデックス集合とする.インデックス集合
に対する
の部分ベクトルを
とすると,グループ正則化は以下で表される.
一般化連結正則化
一般連結正則化は,あるグラフに関して隣接した変数は同じ値になるようにする正則化である.グラフについて,一般化連結正則化は,
として与えられる.
トレースノルム正則化
トレースノルム正則化は,低ランク行列を学習したい場合に用いられる.を並び替えた行列
を考え,その
番目の特異値を
と表すと,トレースノルム正則化は,
となる.これは特異値ベクトルへの正則化とみなせるので,スパースな特異値を持つ行列,すなわち低ランクな行列が学習されることになる.
正則化関数の組み合わせ
以上のように,正則化関数には多くの例が存在する.これらの正則化関数は,単独で用いるだけでなく,複合して適用することもできる.
正則化関数の組み合わせ方には,例えば以下のような方法がある.
- 和型:
- 畳み込み型
ちなみに,和型と畳込み型の2つの形式には,以下のような双対関係が成り立っている.
ここでは凸関数
のルシャンドル変換.
参考文献
- [1] Hoerl, Arthur E., and Robert W. Kennard. "Ridge regression: Biased estimation for nonorthogonal problems." Technometrics 12.1 (1970): 55-67.
- [2] Tibshirani, Robert. "Regression shrinkage and selection via the lasso." Journal of the Royal Statistical Society: Series B (Methodological) 58.1 (1996): 267-288.
- [3] Frank, LLdiko E., and Jerome H. Friedman. "A statistical view of some chemometrics regression tools." Technometrics 35.2 (1993): 109-135.
- [4] Zou, Hui, and Trevor Hastie. "Regularization and variable selection via the elastic net." Journal of the royal statistical society: series B (statistical methodology) 67.2 (2005): 301-320.
- [5] Fan, Jianqing, and Runze Li. "Variable selection via nonconcave penalized likelihood and its oracle properties." Journal of the American statistical Association 96.456 (2001): 1348-1360.
tqdmでプログレスバーの隣に標準出力する
いい感じのプログレスバーを作ってくれるPythonのライブラリであるtqdmで,プログレスバーの隣に標準出力を更新し続ける方法.
tqdm means "progress" in Arabic (taqadum, تقدّم) and is an abbreviation for "I love you so much" in Spanish (te quiero demasiado). Instantly make your loops show a smart progress meter - just wrap any iterable with tqdm(iterable), and you're done!
これは,tqdmで用意されているset_postfix関数を使うことで実現できる.
実装例
- ループの外側をtqdmで包んで,そのなかで
set_postfixを呼ぶ. - 引数はOrderedDict
for epoch in range(n_epochs): with tqdm(self.train_loader, ncols=100) as pbar: for idx, (inputs, targets) in enumerate(pbar): optimizer.zero_grad() outputs = network(inputs) loss = self.criterion(outputs, targets) loss.backward() self.optimizer.step() pbar.set_postfix(OrderedDict( epoch="{:>10}".format(epoch), loss="{:.4f}".format(loss.item())))
出力例

いい感じに出力できてる.
ニューラルネットワークの蒸留
大規模で複雑な教師ネットワークの出力をもとに,より小さなネットワークを学習する蒸留について.
機械学習モデルの性能評価で重要なのは,学習データに対する正解率ではなく,学習データに含まれていないようなデータに対する汎化性能の方. パラメータの多いモデルは学習データにはよくフィットする一方で,未知のデータに対しては汎化性能が落ちてしまうというケースが多々ある.
よって,学習時は豊富なデータセットから複雑でパラメータ数の多いネットワークを学習し,推論用途により軽量なネットワークを学習し直すというアプローチが考えられる.また,軽量なネットワークは複雑なネットワークと比べてより高速に推論できるため,時間的計算量の観点からも良いと言える.
ニューラルネットワークの蒸留は以下の論文で提案.
Transfer LearningとKnowledge Distillationの違い
Transfer learningとknowledge distillationは,学習の形式はよく似ているが目的が異なる.
Transfer learningは,転移元のネットワークと転移先のネットワークは同程度に複雑で,転移元のネットワークの重みを活用して学習を効果的に進めようという狙いがある.
一方でknowledge distillationは,教師データよりも軽量な生徒モデルを学習することが目的.
Teacher-Student model

Temperature in Softmax Activation
ソフトマックス関数は,出力を確率の範囲に収めることができる.つまり,出力は全て0と1の間を取り,その合計は1になる.
それに対して,温度付きソフトマックス関数は以下で与えられる.
上式は,入力を温度
で割っている形になる.
温度付きソフトマックスの出力例を以下に示す.

クラス7の確立が最も高いと仮定し,異なる温度を設定した時の温度付きソフトマックス関数の出力をプロットしている.
図から,温度を高くすれば高くするほど,ソフトマックス関数の出力は滑らかになっていく(ニューラルネットが断定的な判断をしにくくなっている).数字の例を使うと,0〜9の中だったら7に見えるけど1にも見えるといった反応に近くなる.
つまり,高い温度を用いた温度付きソフトマックス関数は,クラスAとクラスBがどれだけ似ているかといった情報を定量的に扱っているとみなせる.論文では,このような反応をdark knowledgeと呼んでいる.
Knowledge distillationの主なアイディアは,教師ネットワークの持つdark knowledgeを抽出して少ないパラメータの生徒ネットワークを効率的に学習させるという点にある.
Teacher-Student training
生徒ネットワークの学習では,一般的なsoftmax関数によるhard targetに加えて,教師ネットワークの出力を温度付きsoftmax関数に通したsoft targetを用いて学習を行う.
この過程を踏むことで,教師ネットワークのdark knowledgeの抽出を狙う.
最後に,knowledge distillationは,
- より軽量なモデルを使える
- 元々の大規模なネットワークよりも良い汎化性能が見込める
- 大規模なデータで学習された教師モデルがあれば,生徒モデルの学習時には少ないデータしかなくても学習可能
といった利点を持つとされている.
References
SNIP: Single-Shot Network Pruning Based Oo Connection Sensitivity
ICLR2019採択論文"SNIP: Single-Shot Network Pruning Based Oo Connection Sensitivity"をレビュー.
元論文はこちら:
パラメータ数の多い畳み込みニューラルネットワークを,分類精度をほとんど落とさずに大幅にスパース化するnetwork pruningについての研究.
Abstract
network pruningは,与えられた巨大なニューラルネットワークを,精度を維持したまま小規模化することが目的.
既存のnetwork pruningの手法は,再学習のプロセスや追加のハイパーパラメータが必要など,pruningそのものが高コストになってしまうものが多い.
これを受けて,学習前にデータに基づいてネットワークの接続の重要度を識別するnetwork pruningの手法を提案.
提案手法は以下の特徴を満たす.
- Simplicity: ネットワークを学習前に一度だけpruningするだけでよく,事前の学習や面倒なpruningのためのスケジューリングは必要ない.
- Versatility: 提案する構造的に重要な接続を発見する指標は,ネットワークアーキテクチャによらず汎用的に適用できる
- Interpretability: 提案手法は,データのミニバッチを用いてsingle-shotで重要な接続を発見できる
つまり,提案手法は既存のnetwork pruningの手法とは異なり,学習前からネットワークのスパース化を達成できる.
Neural Network Pruning
Neural network pruningの研究背景には,多くのネットワークはタスクに対してパラメータ過多であり,より小さなネットワークで同様の精度を達成できるはずであるという仮定に基づいている.
与えられたデータセットを,求められるsparsity levelを
とする.
neural network pruningは以下の最適化問題を解くことになる.
はcross-entropyのような一般的な損失関数,
はネットワークのパラメータ集合,
はパラメータ数,
は
ノルム.
重要度ベースのpruning手法では,冗長なパラメータや接続を重要度に基づいて削除することでネットワークの軽量化を実現する.こうした手法では,パラメータや接続の重要度を測る指標が非常に重要になる.
よく用いられるものとしては,重みパラメータの絶対値が閾値以下のものを重要でないと扱うものや,高いHessianを持つ重みの重要度が高いとする指標がある.
は接続
に対する重要度.
これらの指標を用いた手法は,ネットワークの再学習が必要であったり,ネットワークアーキテクチャに依存しすぎたりする.
Single-Shot Network Pruning Based on Connection Sensitivity
ネットワークとデータセットが与えられた時,タスクとデータに基づいて冗長な接続の枝刈りをしたい.
Connection Sensitivity: Architectural Perspective
提案する指標では,接続の重要度をその重みに依存せずに決定したい.
パラメータの接続の状況を表現するインジケータを
とする.
network pruningの目的関数は,
ここで,は接続が有効かどうかを表現しているので,
を切り替えた時の目的関数の差分に注目することで,その接続の重要度を判断できる.
は2値のため微分できず,最適化が難しいため実際にはこれを緩和した問題を解くことになる,
の勾配が大きい時は,ネットワークとタスクにとって重要な接続であるはずであるという仮説を立てる.これに基づくと,
Single-Shot Pruning at Initialization
Single-shot Network Pruning (SNIP)のアルゴリズムを以下に示す.

ネットワークアーキテクチャの変化に対するロバスト性についての議論
ニューラルネットワークの重みの初期値は通常,正規分布を用いてランダムに初期化される.
しかし,ネットワークのすべての層の重みの分散が決まった値をとっている場合,各レイヤを通る信号が同じ分散を持つことは保障されないため,勾配や本論文で注目している顕著性指標がネットワークアーキテクチャに強く依存してしまう.
これを避けるため,論文ではネットワークの初期化にvariance scaling手法を用いることを推奨している.
Pruningに用いるミニバッチに対するロバスト性についての議論
本手法ではミニバッチを用いてpruning対象のニューロンを選択するが,これはミニバッチに含まれるデータに依存してしまう.
よって,複数バッチにまたがって接続の重要度を蓄積してから最終的なpruning対象を決定するテクニックを紹介.
Experiments
SNIPを適用した複数のネットワークアーキテクチャに対して,MNISTとCIFAR-10の分類タスクを用いて実験.
LeNetのpruning
- LeNetを,複数のsparsity levelでpruningした際の実験結果
- 分類精度をほとんど落とさずにネットワークを大幅にスパースにできている
- さらに,sparsity levelによっては元のネットワークより汎化性能が高くなっているケースもある.

先行研究との比較実験
- 既存のpruningアルゴリズムとの比較実験
