The jonki

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

macOS CatalinaでKarabiner-Elementsを動かす

macOS Catalinaのpublic betaを入れたらKarabiner-Elementsが動かなくなったのでメモ.基本的には公式対応を待った方が良いが,もうアップデートしてしまった方は下記issueをウォッチしておくのをオススメする.今回は本日7/3時点でのワークアラウンドを説明する. github.com

環境

  • macOS Catalina 10.15 Beta
  • Karabiner-Elements: 12.5.3

問題の内容と原因

入力操作のための権限設定のプロンプトが出ないことが原因のため,Karabinerは起動するものの機能が全く動作していない事象が発生する

解決策(ワークアラウンド

現時点での解決策を書いておく.これは変わる可能性があるので,上記issueをウォッチしといた方が良い

1. Karabiner-EventViewerを起動する(Elementsじゃないよ!)

2. 権限設定のためのプロンプトが(確か)立ち上がったので、+ボタンを押して,パスを辿って下記を追加する.GUIでパスが辿れない場合,/Libraryとかをコマンドプロンプトからopenで開いてお気に入りに入れておけば良いと思う.

/Library/Application Support/org.pqrs/Karabiner-Elements/bin/karabiner_grabber
/Library/Application Support/org.pqrs/Karabiner-Elements/bin/karabiner_observer

うまく設定できれば下記のように表示されるはず. f:id:jonki:20190703230020p:plain

3. プロセスをkillallする

$ sudo killall karabiner_observer karabiner_grabber

4. これで動いてるようになってるはず..

下手なことはすべきではないですね笑.でもSidecar試したかったんだもん..

NMAX 155にUSB電源をつける

今回は珍しくバイクの改造ブログです.最近NMAX 155(2018)を買ったので,それにUSB電源を付けてみました.もう多くの方がやっていると思いますが,参考になる写真はいくつ合っても良いと思うので書いてみます. またこの記事を参考にして行う作業は自己責任でお願いします.不安な方はバイク屋にお願いしましょう.

今回のUSB電源はキースイッチをONにした時に,導通するようにします.また右側のポケットに穴を開けて配線するとスッキリしますが,本体に傷をつけるのが嫌だったのでハンドルバーに配置するスタイルにしました.nmaxはデフォルトではハンドルバーがないので,enduranceのハンドルバーを私は付けています.ミラーのボルトに噛ませる形のものです.

買うもの

色々ブログを見るに当たって,YAMAHAのワイヤーリードを使う方法が一番楽だと思います.これはライトなどに繋がっているプラグの間に噛ませることで2口の電源を確保するものです.

これは必要ならば.

【楽天市場】汎用 ミラーポストマルチバー(ブラック) NMAX NMAX155 / パーツ / マルチバーホルダー【mbr】 cam_nmax_:エンデュランス楽天市場店

工具

六角レンチとメガネレンチ等があれば良いです.4mm〜14mmぐらいの一般的なもので大丈夫です.

手順

まずスクリーンとカバーを外します.私のは純正のハイスクリーン がついてますが,標準スクリーンでも大差ないと思います.赤いところを六角レンチで外します.

f:id:jonki:20190618225325p:plain

次にスクリーンを固定しているバー?のようなものもレンチで外します(赤丸の4箇所).これはハイスクリーン だけかも. そして,本体の外装カバーを外します.これは3つのボルトでくっついているのでこれも外します(緑丸の3箇所,左右の2つが裏側にあります)

f:id:jonki:20190618225832p:plain

カバーは真上に引っ張るだけで簡単に外せます.中身が見えてきました.結構余裕があります.この中で茶色と黒色のプラグを見つけます.(写真は赤っぽく見えてますが,茶色です) f:id:jonki:20190618230107p:plain f:id:jonki:20190618181250j:plain

この茶色のプラグを外し,ワイヤーリードで中継するようにします. f:id:jonki:20190618230415p:plain f:id:jonki:20190618230421p:plain

次にデイトナのUSBソケットを取り出します.肝心なところで写真がないのですが,電源をつなぐ側の口が合っていないので,ケーブルを切断します.そして,ワイヤーリードについていた金色の接続端子に噛み合わせて端子を作ります.ワイヤーストリッパーがあると便利です(なくてもニッパでできるけど). で,できた金属端子を,ワイヤリードについていた端子のキャップ(写真緑色のところ)を外し,それに金属端子を突っ込むことで端子が出来上がります.やり方が合ってるか不安でしたが押し込むと,カチッと音がしました.私は逆にやってしまったのですが,金属端子とバイク側の端子内の金属が噛み合う向きがあるっぽいので,端子方向に気をつけて差し込む必要がありそうです.私は逆に作ってしまったようで,無理やり端子をかみあわせました(軸の色(プラスマイナス)の対応を間違えていなければ大丈夫...).USB電源の赤いケーブルをバイク側の茶色に,USB電源の黒いケーブルをバイク側の黒色に,プラスマイナスに気をつけて配線します.

f:id:jonki:20190618230900p:plain

金属端子の作り方に関しては,こちらの方のブログに写真が載っているので参考にしてみてください.金属線をむき出しにして押し込んだら,金属端子手前側のところでペンチなどで巻き込むようにしてケーブルと金属を固定するようにします. mihiro.sakura.ne.jp

端子ができたら,接続して,キースイッチをONにして,USBから充電できるか試してみましょう.iPhone XRが普通に充電できました.

動作確認ができたらケーブルの配線です.ハンドル中心部から右手側にケーブルが通っている経路があるのでそこに下からねじ込んで行きます.ハンドルカバーを外さずにできましたが,USB端子が大きいので通すのは少し時間がかかりました. f:id:jonki:20190618231435p:plain

あとは適当にハンドルバーのところに設置します.デイトナのUSB電源にバークリップがあるので,それを使いましょう.これで快適なツーリングライフの出来上がりです.ハンドルを左右に切って,ケーブルに十分な遊びがあることを確認してから,余ったケーブルなどは結束バンドで綺麗にまとめて起きましょう.最後にスクリーンを元に戻して完成です.

作業時間は端子の作り方などを調べてやっていたので2時間ぐらいかかりましたが,慣れた方であれば30分ぐらいで終わる内容だと思います.バイク本体をいじる必要がないので安心してできる作業だと思います.

NAACL 2019のBest Paper Awardsを一人で読み会

NAACL 2019のBest Paper Awardsが公開されていましたので,1件を除いた*1ペーパーをLeading NLP Ninjaで解説しました.

Best Long Paper

BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding anchor.fm

Best Short Paper

Probing the Need for Visual Context in Multimodal Machine Translation anchor.fm

Best Thematic Paper

What’s in a Name? Reducing Bias in Bios Without Access to Protected Attributes anchor.fm

Best Resource Paper

CommonsenseQA: A Question Answering Challenge Targeting Commonsense Knowledge anchor.fm

サポーター募集中

ポッドキャストの運営には実は色々とお金がかかっていまして,2ドル,5ドル,9ドルの月額サポータープランがあるので,もし良ければご加入待っております! www.patreon.com

*1:Best Explainable NLP Paperは量子力学を利用してNNの説明性を付与する,というモノで全然わかりませんでした.

ギブスサンプリング入門

前回2次元のガウス分布を条件付き確率により得られた1次元ガウス分布から推定する記事を書きましたが,今回はもっと単純な例で説明します. www.jonki.net

というのもGraham先生のチュートリアル資料(トピックモデル)にかなり分かりやすい例があったので,それを利用させていただいて説明します.チュートリアル資料の例題と対応しているので,それと合わせて本記事を見てみてください.

単純なサンプリング

まずサンプルする,ということはどういうことなのか,を説明します.これは何らかの確率分布から,その確率に応じてサンプル(標本)を抽出することを意味します.例えばある確率分布にはA, B, Cの3つの値がそれぞれ0.5, 0.3, 0.2で生起するような分布を考えます.そのような確率分布から1つののサンプルを得るには下記のようなコードになります.

import random

def sampleOne(probs):
    z = sum(probs.values())
    remaining = random.uniform(0, z)
    for k, v in probs.items():
        remaining -= v
        if remaining <= 0:
            return k

def main():
    probs = {
        'A': 0.5,
        'B': 0.3,
        'C': 0.2
    }

    N = 10000
    samples = {k: 0 for k in probs.keys()}
    for _ in range(N):
        sample = sampleOne(probs)
        # print('Try sample:', sample)
        samples[sample] += 1

    print('Result:')
    for k, v in samples.items():
        print('{}: {:.3f} ({}/{})'.format(k, v/N, v, N))

if __name__ == '__main__':
    main()

プログラムでは1万回サンプルを行い,A, B, Cがどれぐらいの確率で生起したか見てみましょう.だいたい元の分布の値と等しいですね.

$ python sample.py
Result:
A: 0.500 (5005/10000)
B: 0.302 (3016/10000)
C: 0.198 (1979/10000)

ちなみに上記コードのNを100に変えて,100回サンプルのときの例を見てみます.そうすると,先程よりも少しずれた値になってしまいました.このようにサンプリングでは基本的にサンプルする回数を多くすればするほど,元の分布に近しい値を獲得することができます.

Result:
A: 0.460 (46/100)
B: 0.300 (30/100)
C: 0.240 (24/100)

ギブスサンプリング

では,次にギブスサンプリングの説明をします.ギブスサンプリングでは,解析的に解けない同時確率を,条件付き確率に分解し,サンプリングを行うことで,元の確率(同時確率)を近似的に得ようというものです.その際に,各々の確率変量は同時には扱えないので,1つ以外を残して固定することで(観測値とする),サンプリングを行うものです.

例題として,Graham先生の資料を利用します.この問題では,親A(父or母)と子B(息子or娘)が買い物をしている状況を考え,それぞれの同時確率(例えばP(母,娘))などをギブスサンプリングで求めます.Givenの情報として,AとBの条件付き確率は与えられているところからスタートしています.この例では同時確率は,解析的に計算できてしまう(後述)のですが,まずはギブスサンプリングで得てみましょう.

今回はAとBの2変量なので,Bを固定した状態でAをサンプル(A'〜P(A|B)),Aを固定した状態でBをサンプル(B'〜P(B|A)を交互に行います(〜は確率分布からのサンプルを表します).そしてサンプルしたA'とB'が同時に買い物をしていた,としてカウントをしていき,各ケースの頻度を計算することで,擬似的に同時確率を求めます.このとき,AとBの初期値が必要になりますが,適当で良いです.

import random

# given probabilities
probs = {
    'mom|dag': 5/6,
    'fat|dag': 1/6,

    'mom|son': 5/8,
    'fat|son': 3/8,

    'dag|mom': 2/3,
    'son|mom': 1/3,

    'dag|fat': 2/5,
    'son|fat': 3/5
}

def sampleOne(probs):
    z = sum(probs.values())
    remaining = random.uniform(0, z)
    for k, v in probs.items():
        remaining -= v
        if remaining <= 0:
            return k

def gibbsSampling():
    samples = {
        'mom,dag': 0,
        'mom,son': 0,
        'fat,dag': 0,
        'fat,son': 0,
    }

    # initial values
    A = 'mom'
    B = 'dag'

    # sampling count
    N = 10000

    for _ in range(N):
        # Bを固定でAをサンプル
        _A = sampleOne({k:v for k, v in probs.items() if k.endswith(B)}).split('|')[0]
        # Aを固定でBをサンプル
        _B = sampleOne({k:v for k, v in probs.items() if k.endswith(A)}).split('|')[0]
        samples['{},{}'.format(_A, _B)] += 1

    print('Result:')
    for k, v in samples.items():
        print('P({}) = {:.3f} ({}/{})'.format(k, v/N, v, N))

if __name__ == '__main__':
    gibbsSampling()

これを実行すると,下記のようになりました.どうやらA=母,B=娘である確率が大きそうですね.

$ python gibbs_sampling.py
Result:
P(mom,dag) = 0.550 (5503/10000)
P(mom,son) = 0.278 (2776/10000)
P(fat,dag) = 0.111 (1107/10000)
P(fat,son) = 0.061 (614/10000)

ところでこの同時確率はギブスサンプリングを使わなくても解析的に解けるので,先程の事例の答え合わせができます.ベイズの定理より,下記が得られます.

P(母, 娘) = P(母|娘)P(娘)

P(娘)は明に与えられていませんが,娘と息子が選ばれる内,娘が選ばれる確率であるので,\frac{P(娘|母)+P(娘|父)}{P(娘|母)+P(娘|父)+P(息子|母)+P(息子|父)}=\frac{2/3+2/5}{2}=\frac{8}{15} \fallingdotseq 0.533で先程求めた値(0.55)と近しい値であり,正しくギブスサンプリングが出来ていそうです.他の同時確率についても同様に計算ができます.

まとめ

サンプリング及びギブスサンプリングについて,Graham先生の資料を元に説明してみました.条件付き確率にうまく分解し,ギブスサンプリングを行うことで,元の確率に近しいものを獲得できることを,実例で見てみました.名前は仰々しいですが,意外と単純なしくみですよね.

今回のプログラムは下記にまとめています.

github.com

2次元ガウス分布をギブスサンプリングする

2019/5/3 更新

ギブスサンプリングの簡単な例題を説明した記事を書いたので,こちらを先に見たほうが理解が進むかもしれません. www.jonki.net

ベイズ推論を勉強中に,サンプリングの1つ,ギブスサンプリングが出てきてよく分からず色々調べていたのだけど,ようやく少しわかったので,数式展開及びPythonのコードをかなり丁寧に書いてみた. はてなブログで数式を書こうと思ったけど,さすがにつらすぎたのでTeXで書いてみましたので,下記のリンクからPDFを見てみてください.

PDFには下記を含みます.

github.com