Volumioをディスプレイに出力してマウス操作する

自分は音楽を聞くときにメインでVolumioを利用している。
メインで1台、テレワーク用のデスク用に1台、それぞれraspberry pi 3で運用している。
Volumioにはプラグインでタッチディスプレイに出力しタッチ操作できるようにすることができる。デスクではネットワークの関係上、ブラウザ操作ではなくディスプレイでの操作がしたかったのでこのプラグインを利用した。プラグインのインストール方法等は別の人の記事を参考にして欲しい。

自分は安く以下のディスプレイを入手できたので使ってみた。Volumioを入れたraspberry piで表示とタッチ操作の確認ができたのを報告しておく。

電源供給もraspberry piからできるのでケーブルがraspberry piへの電源ケーブルのみでスッキリして便利だった。

上記ディスプレイはスピーカーも搭載しているようだがそれは試していない。スピーカーは別途安いやつを使っている。

これをraspberry piに直差しして簡易的なデスク用音楽環境を構築している。

いざこれをデスクで利用するとタッチ操作は悪くなかったが、別にタッチで操作する必要がないことに気がつく。
いちいちディスプレイに手をのばす必要があるし、正確にタッチできないこともある。別にマウス操作でいいのでは?

試しにVolumioを入れたraspberry piにUSBマウスを接続してみたがカーソルは出ない。やっぱりだめかと思ったがマウスを動かしてみると反応はある。どうやらカーソルが見えないだけでマウス操作はできる様子。カーソルが見えなくても操作はできるが少々やりにくい。どうにかしてカーソルを表示できないかと調べたら無事にカーソル表示ができた。

sudo nano /lib/systemd/system/volumio-kiosk.service

を実行してファイルを確認する。すると下の方に

ExecStart=/usr/bin/startx /etc/X11/Xsession /opt/volumiokiosk.sh -- -nocursor

という部分があり、これの -- -nocursorがカーソルを消す設定のようだった。この部分を削除して再起動(プラグインのリロードでもいいのかも?)したらカーソルが表示される。

めでたしめでたし。

MacBook Pro 13inch late2018で3台の外部ディスプレイを使用する

MacBook Pro 13inch late2018から外部ディスプレイ3台を接続するために試したこと・解決策について、同じことをしようとしている人たちのために。

結論から言うと下記のデバイスを使うことで外部ディスプレイのみのトリプルディスプレイ環境を構築できました。

以下はポエムです。


自宅の環境を整えウルトラワイドの大きめのディスプレイを2台購入した結果、MacBook Pro本体が邪魔になりクラムシェルでの使用を余儀なくされた。

今までは外部ディスプレイ2台とMacBook Proの画面1枚でのトリプルディスプレイを構築していたが、それをクラムシェルで外部ディスプレイ3台にしようと思ったわけだ。

色々調べるとMacBook Pro 13inchでは基本的に外部ディスプレイは2台までのようだ(15inchはそうではないらしい)。なので何かしらのエクストラなデバイスなりを使って拡張する必要がある。

MacBook Proでの外部ディスプレイ3台を使用する方法についてググるのは意外と難しかった。「外部ディスプレイ 3台 トリプルディスプレイ 」などのワードではどうもMacBook Pro本体のディスプレイ + 外部ディスプレイ2台といった当たり前の記事しかヒットしない。違う、MacBook Pro本体のディスプレイを使わないトリプルディスプレイを構築したいんだ。

調べるとUSBディスプレイアダプタとやらが必要らしい(ディスプレイを拡張するためのデバイスの名前をそもそもよく知らなかった)。ただ、この「USBディスプレイアダプタ」という言葉も微妙に厄介だった。特にMacBook Proの場合、USBはtype-c(Thunderbolt3)というものになり、ディスプレイを別途拡張するデバイスを探しているのに、「type-c USBディスプレイアダプタ」と検索をするとtype-cからHDMIなどへの変換ケーブルがヒットする。当然これらは今回の目的には合わず、2台の外部ディスプレイしか得られない。

勘違いのしたデバイスの一つがこれだ(これだと外部ディスプレイのみのトリプルディスプレイは構築できないので注意)。

なんとなくだが、別途ディスプレイ拡張するならそれなりの基盤やチップが必要で物理的に大きめなら大丈夫なのではなんて考えていた。上記のデバイスは3台目の外部ディスプレイには対応しておらず、結果的に返品した。ただ、このデバイスは親切に説明にそのことが明記してあり、購入したこちらに責任がある。

多くの「USBディスプレイアダプタ」という単語で引っかかるデバイスには説明がなく、可能性が高そうなのはUSB3.0を用いたもので、これならHDMI ot Display Portなどといった変換ではなくディスプレイを拡張するものであろうが、如何せんMacBook Pro late2018にはtype-c形状のUSBしかなく、USB3.0をtype-cに変換して効果が得られる自身がなくてが出せないでいた。また、これらのデバイスは価格がそこそこするのも問題だ。

また、外付けGPUに期待もしたが、外部ディスプレイのためにはオーバースペックだし、何より外部ディスプレイ2台の制約は超えられないらしくこれもボツ。

ディスプレイのデイジーチェーンなども考えたが、ディスプレイはすでにあるのでThunderbolt3対応ディスプレイの使用等も視野にない。

調べていてこちらの記事にたどり着いた。

discussionsjapan.apple.com

読んでみるとどうやらDisplaylink社のチップの入ったUSBディスプレイアダプタを使用すれば良いらしい。ドライバが必要らしいが、目的を達成できるなら全然構わない。記事のリンクから対応する製品をAmazonで調べる。評判と値段、性能を見た結果、WAVLINK社の下記製品を購入した。


USB3.0ポートの拡張などもついているが、あるに越したことはない。
ドライバをインストールしたら特に問題もなく認識した。これで念願の外部ディスプレイだけでのトリプルディスプレイ環境を構築できた。しかも、こちらのUSBディスプレイアダプタは2台まで対応しているようで、4台目の外部ディスプレイの接続も確認できた。そこまでは必要ないので今のところはクラムシェルでのトリプルディスプレイ環境で使用している。発熱も殆どない(MacBookは熱いがw)。

以上で、念願のクラムシェルトリプルディスプレイ環境を構築ができた。なお、使用しているディスプレイは

といったウルトラワイドディスプレイとEIZO EV2736という古いディスプレイを使用している。捗る。

AdaCos: Adaptively Scaling Cosine Logits for Effectively Learning Deep Face Representationsを読んだ

詳細はこちら
qiita.com

以前からArcFaceというmetric learningの手法が優秀なので使っていたが、AdaCosはArcFaceのハイパーパラメータを調整してくれるということで使ってみた。そしたら想像以上に優秀だったのでAdaCosが自分のデファクトスタンダードになった。
ただ気になる点もある。cos(\min(\frac{4}{\pi}, \theta_{med}^{(t)}))ということろがあるのだが、 \theta_{med}^{(t)}が正数になるとは断言できないのではということだ。xとWを正規化しているが、正数にしてはいない。もしも\theta_{med}^{(t)}が負になったら大変である。なので\max(\cos {\theta_{med}^{(t)}, \cos{\frac{\pi}{4}}})としたほうが良いのではということ。式的には論文のほうがきれいかな?もしかしたら見落としがあるかもしれない。

Invertible Grayscale

Invertible Grayscaleを読んで、実装、実験をした。詳細はこちら。

qiita.com

コードなどについてはtrain部分はあまり必要ない気がし、model.pyについてのみ載せた

正直需要もない気がする(手法が手法ゆえ)。
グレースケールに見えれば良いという考えはなるほどと感じた。確かに。
実験してみたが、なかなかうまく行かず、良い初期値を引き当てる必要がある。
グレースケールにするためのGrayscale Conformity Lossがなければすんなりと学習するので、この制約がなかなかきついのだろう。

Learning Confidence for Out-of-Distribution Detection in Neural Networks

クラス分類などで実際にニューラルネットを実際に使うとわかるが、ある入力が特定のクラスである確率が9割を超えていても間違えている事がある。
Adversarial Attackなどを考えればよく分かる。
この論文では、入力に対してクラスラベルの推定と共にその予測分布に対しての確信度も同時に推定する手法を提案している。
入力に対して、クラスAである確率が90%という出力が得られたとしても、確信度が低いものは間違っている可能性がある。
要するにグレーゾーンというわけだ。実システムで使う場合は、確信度の低いものは人が確認するといった手続きになるだろう。でも、そのグレーゾーンがわかることは非常に役立つ。
提案手法は実装もしやすい。

p, c = f(x, \theta)
p_i, c \in [0, 1], \sum^{M}_{i=1}p_i =1

入力 xに対しての出力はクラス確率 pと確信度cを得る。 cはsigmoidを通している。
そして、クラス確率 p_iと入力 xの実際のラベル分布y_iを確信度でブレンドした

p_{i}'=cp + (1 - c)y_i

をネットワークの出力として、この p_{i}' y_iとのクロスエントロピーを誤差として学習を行う。

 \mathcal{L}_t = - \sum^{M}_{i=1}\log(p_{i}')y_i

しかし、このlossだけだとネットワークはc=0とすることで常に正解ラベルを参照でき、lossを0にできてしまう。そこで-\log(c)のペナルティを与える。

 \mathcal{L}_c = -\log(c)

結果として全体のloss関数は

 \mathcal{L} = \mathcal{L}_t + \lambda\mathcal{L}_c

となる。\lambdaは確信度のlossを調整するハイパーパラメータで、確信度のlossの大きさによって学習中に逐一調整を行う。

クラス確率の予測が正確になればなるほど正解ラベルに頼る必要がなくなり確信度が1に張り付いてしまう。そうならないように\lambdaを小さくすることで正解ラベルを参照するコストを小さくする。逆に予測がうまくできない初期状態などは、正解ラベルを参照しすぎ、学習をしなくなるので\lambdaを大きくし、正解ラベル参照コストを大きくする。

つまり、予測に自信が持てないときはコスト( L_c)を払うことで、正解ラベルを使うことができるわけだ。ただ、正解ラベルを使うのにはコストが必要で、これが予測を間違えるよりも安くなければならない。予測を間違えるより、正解ラベルを使うコストほうが高ければ当然正解ラベルを使わなくなり、普通のクロスエントロピー誤差を使った学習と同じになってしまう。


chainerで書くとしたら大体以下のようになるだろう。

# 正解ラベルtはone-hot エンコーディング
y = F.softmax(h_class)
confidence = F.sigmoid(h_confidence)
c = F.broadcast_to(confidence.reshape(batch_size, class_num), y.shape)
y_prime = y * c + t * (1 - c)
loss_classify = - F.mean(F.log(F.select_item(y_prime, t.argmax(1))))
loss_confidence = - F.mean(F.log(confidence)) * lm

h_class、h_confidenceはニューラルネットのそれぞれの出力、tはone-hot形式の正解ラベル、batch_sizeはバッチサイズ、class_numはクラスの数、lmは係数ラムダを表す。
注意点としては2つ。確信度自体の出力はスカラーなのでクラス予測と同じ形のベクトルに変換することと、y_primeはすでに分布になっているのでF.softmax_cross_entropyを使うのではなく、単純にクロスエントロピーをとること。なお、正解ラベルは出力した分布とブレンドするのでone-hotエンコーディングにしておくor 変換する必要がある。

係数ラムダの調整はchainerのExtensionsでlossを見て調整するか、ここで直接調整すればよいだろう。

lm += 0.01 if loss_confidence > 0.3 else -0.01

みたいな感じで。
論文では、確信度誤差を0.3に保つように\lambdaを調整するとあった。e^{-0.3} \fallingdotseq 0.741なので学習データの中に難しいサンプルが25%程度含まれているという事前知識がある気がする。この難しいサンプルの割合が事前にわかっているなら、それに合わせて\lambdaの調整も変えたほうがいいだろう。

実際に使用してみるとなかなか良い。自分がやった実験ではラムダは0.55前後で安定した。
また、面白いことに学習後のモデルのvalidation accuracyが僅かだが上昇した(正解ラベルを混ぜたわけではない)。
予想だが、確信度の低いものは学習に悪影響を与えるサンプルで、それを学習に使用しなかった(確信度を下げ、正解ラベルのみ使う)ことで、より良い特徴を捕らえられたのでは。データセットクリーニングに近いのかもしれない。

あいかわらずひどい日本語だ...

Born Again Neural Networks

[1805.04770] Born Again Neural Networks

本来Knowledge distillation (KD) はモデルの圧縮に使われているが、そうではなくKDによって教師モデルより高いパフォーマンスの生徒モデルを作ることを試みたのがこの論文。
自分の記憶だとKD的なものは2014年あたりからちらほら見かけるようになった。
[1312.6184] Do Deep Nets Really Need to be Deep?
深い(Deep)ネットワークではなく層の数的に薄い(Shallow)ネットワークじゃだめなのか?ということをKDを用いて調べたものや
[1412.6550] FitNets: Hints for Thin Deep Nets
KDを用いてよりDeepで細いネットワークを生成するものなどが記憶にある。これらはネットワークの圧縮関係で教師モデルと同じ精度を保ったまま高速・軽量を目指したものだった。それに対してBorn Again Neural Networksは生徒モデルとして教師モデルと同じ、もしくはより複雑なモデルにすることで精度向上を図っている。手法はこうである。出来上がった教師モデルを用いて生徒モデルを学習する。これによってできた生徒モデルを新たな教師モデルとし再度ランダムに初期化された生徒モデルを学習する。これを繰り返す。これだけである。しかしこれで精度の向上が見られたそうな。なお、途中の生徒モデルを用いてアンサンブルもできる。これに関してはなるほどとなる。
f:id:Ninhydrin:20180608002800p:plain
本論文で提案するBorn Again Networks(BANs)について。正直図の通り。一般的にSGDなどを用いてDNNのような関数f(x, θ)ラベル付きデータ(x, y)に対するlossを最小化するパラメータ*θを求める。経験的にこの*θは最適解に近く、損失関数の変更によって改善できる可能性があるのではという考えに基づいている。よくある損失関数の変更はL2正則化とかだ。BANsではKDを用いて情報量豊富な出力を教師ラベルとすることでより良いモデルを得る。


DKの成功は本当に正解ラベル以外の情報のおかげなの?それとも単純に重み付けのおかげなの?これに関しても検証してる。
実験はCifar-10, 100とPenn Tree Bankの3つ。MNISTは必要ないがImageNetかMS COCOは欲しくないか?BANsは時間がかかるから仕方ないかな。
f:id:Ninhydrin:20180612232602p:plain
まずはCifar-10について。モデルが複雑になると効果が薄いように感じられる。まあCifar-10だしという気持ちもある。

f:id:Ninhydrin:20180612232940p:plain
table 2はCifar-100に対してBANを行った結果。Cifar-10のときと同様に複雑になるほど効果が薄い。アンサンブルに関してはかなりの効果が見込める。ここでCWTMとDKPPという二つの項目がある。CWTM(Confidence Weighted by Teacher Max)とDKPP(DK with Permuted Predictions)はDKの効果についての検証を行ったものである。CWTMは教師モデルの最大値のみを用いてラベルを重み付けし、他のラベルについての情報は扱わない。DKPPはCWTMと同様に教師モデルの結果を使うが、最大値以外の出力についてはその重みを入れ替える。結果としてCWTMとDKPPともに精度向上に効果があり、DKPPのほうが効果が高い。しかし、どちらも単純なDKには及ばなかった(つまりDKは効果があったということ)。

実装する際に特別なことも必要なく精度向上が見込めるという意味では使い勝手はありそう。ただ本当に効果が得られるのか、どれくらいでBorn Againすればいいのかなどは難しそう(というか難しかった)。

Learn to Pay Attention

https://arxiv.org/abs/1804.02391
ICLR2018。 CNNにおけるチャンネル方向ではなく空間方向へのAttentionモデルの提案。タイトルがいいよね。
図を見たほうが早い。
f:id:Ninhydrin:20180516223808j:plain
決められたそれぞれの特徴量マップに対してAttentionを行う。画像のどこに注目するかという感じかな。
これによって得られた特徴量を入力としてクラス識別を行う。
まずレイヤー{ \displaystyle s \in \{1, ... S\}} から特徴集合{\mathcal{L}^{s} = \{\mathcal{l}^{s}_{1}, \mathcal{l}^{s}_{2},...,\mathcal{l}^{s}_{n} \}}を抽出する。この\mathcal{l}^{s}_{i}は空間方向の特徴。ネットワークの出力のクラス識別の前の部分をグローバル特徴mathcal{g}とする。図で言うとFC-1の出力部分。\mathcal{l}^{s}_{i}mathcal{g}と同じ次元に線形写像したベクトルの集合\hat{\mathcal{L}^{s}}\mathcal{g}をcompatibility function \mathcal{C}に入力。\mathcal{C}(\hat{\mathcal{L}^{s}}, \mathcal{g}) = \{c^{s}_{1}, c^{s}_{2}, ... , c^{s}_{n}\}。compatibility scoreをsoftmax関数で正規化

a^{s}_{i} = \frac{exp(c^{s}_{i})}{\Sigma^{n}_{j}(c^{s}_{j})}, i \in \{1, ... ,n\}
正規化されたcompatibility score\mathcal{A}^{s} = \{a^{s}_{1}, a^{s}_{2}, ..., a^{s}_{n}\}を用いてレイヤー\mathcal{s}ごとに一つの特徴ベクトル\mathcal{g}^{s}_{a} = \Sigma^{n}_{i=1}{a^{s}_{i}\cdot \mathcal{l}^{s}_{i}}を得る。この\mathcal{g}^{s}_{a}を用いてクラス識別を行うが\mathcal{S} > 1のときは\mathcal{g}^{s}_{a}が複数になる。そのときはつなげて一つのベクトルとして識別するもよし、それぞれの\mathcal{g}^{s}_{a}を用いてそれぞれ識別を行い、その平均を使うもよし。

compatibility関数Cについては線形モデル
 c^s_i = \langle \mathcal{u}, \mathcal{l}^s_i + \mathcal{g}\rangle   i \in \{1, ... ,n\}
もしくはドット積
 c^s_i =  \langle \mathcal{l}^s_i, \mathcal{g}\rangle    i \in \{1, ... ,n\}
を用いる。

実験結果
f:id:Ninhydrin:20180516231842p:plain

attXのXの部分に最後からいくつのレイヤーをattentionするか、dpはglobal featureをドット積で、pcは線形モデル。concatはベクトルをすべて結合してFCに入力、indepはそれぞれでクラス予測を行いその平均を結果とする。基本的に比較はVGG-att2-concat-pcで、元のVGGに対して改善が見られるようだ。Table2のRN(ResNet)は他の論文からのものでImageNetでpre-trainしているらしい。それに対してVGG-att2-concat-pcはCifar-100でpre-trainしている。
このあとの実験はconcat-pcのみ
次はAdversarial Attack。今後はこういうものも検証したほうがいいのかな。
f:id:Ninhydrin:20180530004652p:plain
VGGより5%も低いとのことだがここはしっかり調べてない。ノイズが知覚できるレベル(Fig5の5列目とか)になるとVgg-att2-concat-pcのほうが大きくなる。
f:id:Ninhydrin:20180530231137p:plain
f:id:Ninhydrin:20180530232029p:plain
Table 7はクロスドメイン。Fine turningってことでいいのかな?Cifar 10/ 100のそれぞれで学習したモデルを特徴量抽出器とし、その出力をSVMに入力し汎化性能を測っている。どのデータセットに対しても平均6%ほどの改善。Cifarは32x32と解像度が低いが600x600サイズのデータセットでも向上が見られる。STLデータセットはCifar10とクラスが同じらしい。

f:id:Ninhydrin:20180530232108p:plain
最後は弱教師あり学習によるセグメンテーション。他のAttentionモデルよりも良い結果。saliency-basedに対しても車だけは良い結果となった。

End to EndでAttentinoを学習できるCNNというのは面白かった。grad-camなどCNNがどこに注目しているかを調べる手法があったがそれと似たようなことができるのも良い。実装も簡単だしいろいろと応用ができそう。GANなどの生成系にもつかえないかな。それと付録にglobal featureをクエリとすることができるとあった。
f:id:Ninhydrin:20180530233448p:plain

global feature ってクエリじゃね?ってことでまず、ある物体が顕著な画像をクエリ画像、その物体が含まれているが他の物体も多い複雑な画像をターゲット画像と呼ぶ。
Fig 10の1列目がクエリ画像、2列目がターゲット画像。ターゲット画像から得られた10層目の特徴マップに対してターゲット画像で得られたglobal featureを適用したのが3列目と6列目。この二つはcompatibility関数がドット積かパラメータを用いた関数かの違い。4列目と7列目はターゲット画像で得られた特徴マップに対してクエリ画像で得られたglobal featureを適用したもの。5列目と8列目は元のglobal featureを用いた特徴マップとの変化の割合を表している。ドット積を用いたほうがターゲットとなる物体の付近での変化が激しい。それに対して線形モデルの方は変化がほとんどない。これはパラメータ\mathcal{u}がそのあたりの特徴を獲得しているかららしい。そのためテストデータのような未知の画像に対しても適用できる。

読んだ感じこんなだった。間違いなどあればガンガン指摘してくださるとありがたいです。