Splatoon2やってます

発売日からやっていましたが、本職のガチエリアでやっとS+に到達(人権獲得)したので何か書きます。

f:id:syou6162:20170921130244j:plain

イカリング2、いいですね。

Splatoon1との比較

前作は結構やり込んでいたんだけど(ウデマエは大したことない…)、実はSplatoon2あまりやり込めていませんでした。要因は色々あるけど

  • インクに足を取られやすくなった
    • 敵陣に突っ込んでいって無双みたいなことはしにくくなった
  • 無敵系のスペシャルがなくなった
    • 我等がわかバリア…
  • リッターが弱くなった
    • 自分はリッター使えないけど、リッターがある程度機能しないとブキのバランスがイマイチな気がした

などがありました。自分はわかバリアで一気に打開するのが好きだったので、それに代わるものが見つけられなかったというのが大きいのかもしれない。しかし、数回のアップデートを経て、かなりいい感じに調整がされてきたなぁと感じていて、最近は結構楽しんでやり込めています。

使っているブキ

  • もみじシューター
  • ジェットスイーパー

を中心に使っていますが、8割方もみじです。基本的には味方サポート中心の引き気味の立ち回りで、一試合3kill程度というのもよくあります。その代わりスペシャル(アメフラシ)の回転数を上げていくのを意識してプレイしています。つまり、なるべく死なずに塗り重視。S以上になってくると味方も優秀になってくるので、頃合いを見計らって味方をサポートしていると勝手にkillをしてくれる。エイムがない、1vs1が弱くてもS+まではいける。S帯までは勝手に死んでいく味方も多いので、ひたすら我慢。。

もみじシュータのサブはロボットボムで、近くに敵がいたらある程度追いかけていってくれる。スプラッシュボムと比較すると、ロボットボムで直接敵を倒せることは少ない。しかし、詮索してくれるというのはでかくて、相手の場所が分かったり相手の行動を限定させられるので、擬似的に人数有利な状況を作り出すことができる。Splatoon2では、一人で無双するのが難しくなったと感じていたので、擬似的にでも人数有利の状況を作ってくれるのは大きい。サブでロボットボムを持つブキは他にもいくつかある。ロボットボムの弱点はインク消費量が多いところだけど、もみじシューターはメインの燃費がわかばと同じでかなりよい。よって、ロボットボムを投げた後にも、牽制をしたり他の場所を塗ったりする余裕が他のブキよりあるのが特に気にいっている。同じサブを持つホクサイも使っていたけど、メインの燃費があまりよくないのでボムを投げた後の動きが割と難しかった。

ギア構成を見てもらうと分かるけど、スペシャルのアメフラシにかなり特化した構成になっている。スペシャル強化も付けているので、相手からすると死なないためには今いる場所から移動しないといけない。もみじの射程では届かないチャージャーやバレルスピナー、ジェットスイーパーなど長射程ブキを固定ポジションから強制的に動かせるのが強力。アメフラシを多少くらっているので、エイムががばがばでも普通よりは倒しやすくなっている。味方と交戦している敵周辺に投げてもアシストできることも多い。ヤグラやホコの絶対死守ポジションにアメフラシを投げ込むと突破できることも多いので、使い勝手がかなりよい。今後、弱体化されてもあまり文句は言えない。

一気にkillみたいなド派手な戦い方はできなくてとにかく地味だけど、ジワジワと相手を追い込んでいく戦い方ができ、自分の性格と合っていてお気に入りです。

Splatoon 2 (スプラトゥーン2)

Splatoon 2 (スプラトゥーン2)

SlackやTwitterをWeeChat経由で使う & 自分がやっている設定

Slack、最近では色々なところで使われますね。会社用、家庭用、友人との連絡用、研究室のOBOGの連絡用…などとあれこれチームに入っているとチームの切り替えが面倒になってきます。各チームでよく使うチャンネルをひとまとめで見たい、といった要望が出てきます(あと、Slack.appが定期的に日本語入力ぶっこわれるとか)。そういったことをうまくやるために、最近はWeeChat経由でslackを使っています。SlackはIRC経由で使うことができて、WeeChatはIRCクライアントなので、slackを使うことができます。

会社では数人使っている人がいますが、世の中的にはあまり使われていないような気もするので、メリット/デメリットをまとめてみました。

メリット

  • 軽い
  • (複数のチームを横断して)よく使うチャンネルを持ってくることができる
    • 以下のチャンネルを上にまとめて持ってきています
      • 会社: チームのメインチャンネル、チームの雑談チャンネル、自分の分報、仲いい人の分報、機械学習チャンネル
      • 自宅: #general、nasneの残量通知チャンネル
      • 友人連絡用: #general、ポエムチャンネル
      • twitter: プライベートリスト
  • CLIで動くので、ターミナルから動かなくてよい
    • itermの中でEmacsとweechatを並べるといったことができる
    • itermはホットキーで一瞬で呼び出せる
  • 通知も自分の好きなようにできる
    • ハイライトの正規表現をいい感じに書いたりできる
  • atig.rbとかを使うとtwitterも一緒に見れる
  • レイアウトを自由に変えることができる
    • 4分割にして、会社のチームのチャンネルだけ大きめに表示するなど
  • キーバインドの自由度がかなり高い

デメリット

  • 画像展開などは特にされない
    • mackerelの通知のグラフなどは見たい…
    • github連携とかもまあまあ困る
  • 絵文字は脳内で展開する必要がある
  • 他人のslackのstatusは分からない
  • もちろん、slack callはweechat内では使えない
    • ブラウザで開けば使えるので、そこまで困っていない

デメリットもあるけど、致命的ではないしメリットのほうが上回ってるかなと思うので、weechat使ってます。便利です。

自分がやっている設定

特に目新しいこともないけど、参考までに自分がどういうことやっているかメモしておきます。

いくつかのチャンネルを特別扱いして上に持ってくる(便利)。

/script install chanpriority.py
/chanpriority hatena.#mackerel, hatena.#times_syou6162, twitter.#private, ...

チャンネル横断でハイライトされてるものを一覧できる(便利!)。

/script install highmon.pl

見た目や配置の設定。

/set buffers.look.indenting on
/set irc.look.server_buffer independent
/set irc.look.new_channel_position near_server
/set irc.look.new_pv_position near_server

必要ない通知を切る。

/filter add irc_smart * irc_smart_filter *

C-gで移動したいチャンネルに移動しやすくなる。チャンネルの数が100個とか越えててもさっと移動できる。

/script install go.py
/key bind ctrl-G /go

水平分割。繰り返して4分割くらいにしていることが多い。

/window splith

分割すると入力バーがいくつもできるので、入力バーを一つにまとめる。

/bar add rootinput root bottom 1 0 [buffer_name]+[input_prompt]+(away),[input_search],[input_paste],input_text
/bar del input

レイアウトの保存を自動でやる。

/set weechat.look.save_layout_on_exit all

通知関連。weechat-growlなどもあるが、pythonのライブラリの関係で苦労したので、簡単なやつを使う。使えれば何でもいいと思う。

wget https://raw.githubusercontent.com/keith/terminal-notifier-weechat/master/terminal_notifier.py ~/.weechat/python
cd ~/.weechat/python/autoload
ln -s ../terminal_notifier.py

キーワードや正規表現を書いていく。

/set weechat.look.highlight "syou6162,yasuhisa,syou"

マウスの設定。

/mouse enable

サーバーへのログインの設定。

/server add my-team my-team.irc.slack.com/6667 -autoconnect -ssl -ssl_verify=off -password=my-team.XXXXXXXXXXXXX -nicks=syou6162
/connect my-team

サーバーの順番並び替えたいときに。

/server list
/server reorder

バッファの履歴を辿る。

/key bind meta-p /window page_up
/key bind meta-n /window page_down

参考

iTerm2でAquaSKKが使えるようにhammerspoonの設定をする

OSを上げると何か動かなくなるものなので、ついつい上げることが億劫になりますね。社内の大きなイベント*1がひと段落したので、やっと重い腰を上げてOSをSierraにしました。

すでにwebに色々情報が流れてますが、karabinnerがSierraでは使えません。普段AquaSKKを使っていますが、iterm2ではC-jが改行として取られてしまい、日本語入力がまともにできません。itermではemacsを立ち上げたり、weechatでslackへの書き込みをするので、影響範囲が大きいです。karabinner-elementとhammerspoonで解決するのがよくやられている方法だったので、メモ的に書いておきます。itermでC-jが効かないので設定を書いてごまかす作戦です。

local function keyCode(key, modifiers)
   modifiers = modifiers or {}
   return function()
      hs.eventtap.event.newKeyEvent(modifiers, string.lower(key), true):post()
      hs.timer.usleep(1000)
      hs.eventtap.event.newKeyEvent(modifiers, string.lower(key), false):post()      
   end
end

local function remapKey(modifiers, key, keyCode)
   hs.hotkey.bind(modifiers, key, keyCode, nil, keyCode)
end

remapKey({'ctrl'}, 'j', keyCode('kana'))

luaは分からんので、コードは適当…。

余談

AquaSKKがitermでそのままでは使えないとなった時にGoogle日本語入力に切り替えようとしばらく頑張ってみました。しかし、自分が今、かな入力/直接入力(英数)のどちらのモードに入るのかがぱっと見で分かりづらいこと、分かったとして、変換キーがSKKと比べると打鍵が多いことが非常にストレスとなり、脱出に失敗しました…(N年ぶりM度目)。日本語のみ/英語のみの文書だと問題ないのでしょうが、両方が入り混じったものだと難しいですね。ac-mozcでモードレスとかも試してみたけど、これはこれで難しかった…。

*1:インターンなどなど

Amazon Elasticsearch Serviceでcluster_block_exceptionが出てindexに書けなくなった場合の対処法

以前、自宅のElasticsearchをAmazon Elasticsearch Serviceに移した話を書いた。

www.yasuhisay.info

データは引越しせず新規のデータをAmazon Elasticsearch Serviceに放り込んでいくようにしていた(コストをめっちゃかけないと普通に動いてくれるのかちょっと不安だったので、最初は全部入れないようにした)。半年ほど経ったが、安定して運用できていたので元々あったデータもAmazon Elasticsearch Serviceに引っ越すことにした。schema(mapping)はどちらも同じなので、移行ツールを使ってデータの引っ越しをすることにした。

nmpでインストールして、inputを自宅のElasticsearch、outputをAmazon Elasticsearch Serviceに向けて動かす。

elasticdump \
  --input=http://production.es.com:9200/my_index \
  --output=http://staging.es.com:9200/my_index \
  --type=data

元気に引っ越しが始まったようだったので安心して寝たのだが、しばらくして様子を見に行ったら新規ドキュメントの追加ができなくなっており、上述のコマンドも以下のエラーで止まっていた。

{ _index: 'twitter_public_timeline',
  _type: 'tweet',
  _id: '841830783106990100',
  status: 403,
  error:
   { type: 'cluster_block_exception',
     reason: 'blocked by: [FORBIDDEN/8/index write (api)];' } }

cloudwatchに様子を見にいくと、disk fullになっており、やっちまったなーと思いながら不必要そうなドキュメントを削除。しかし、削除も403で怒られる…。調べてみるとどうやらディスクを増やすしかないようだ。

AWSのコンソールからEBS ボリュームサイズを35まで引き上げた(無料からは足が出る)。しばらくするとFreeStrageSpaceも0から余裕ができて、削除や新規のドキュメントの追加ができるようになった。AWSを普段から使っている人には慣れた操作かもしれないが、自分がメインで使っているサービスでなったのは初めてだったので、「なるほど、これが金の力で殴るってやつか」と妙な納得感が得られた。

雑なpythonスクリプトやjupyter notebookをdockerを使って動かす

気が付いたら三ヶ月ぶりのブログだった…。

きちんとした用途ならpyenv等を使って、きちんとpythonのversionを指定、使うライブラリも列挙というのをディレクトリ毎にやっていくようになりました。しかし、pythonを使いたいときはきちんとした用途だけではなく

  • 雑にスクレイピングしたい
  • 一度しかやらないようなテキスト処理をしたい
  • 後々使うか分からないけど、手元にあるtsvファイルをjupyter notebookでデータ解析したい

など、アドホックな用途も多いです。そういうときに毎回ライブラリをインストールして…とやるのはダルいので、上述のような用途で自分が使いそうなものをdockerにまとめておけば、さっと用事を済ませられるのではないかと思ってやってみました(N番煎じなのは分かってる)。

Docker、仕事ではすでに誰かが作ってくれているイメージをdocker runする程度しかやっていなかったのですが、意外と(自分にとって必要な)Dockerfileを書くのは簡単だということが分かってよかったです。

go-active-learningを改良している話(Slackからのアノテーションをサポートなど)

以下の話の続きです、地味に続いています。自分が普段使うツールを改良していくのは楽しいですね。

自分で使ってみて、これは欲しいといったものを追加していってます。社内で紹介したところフィードバックをもらったので、それを踏まえてどうしていきたいか(どうしたか)も書いてみます。

Slackからのアノテーションをサポート

以前はコマンドラインでのアノテーションのみをサポートしていました。Goで書いているので、macでもwindowsでも簡単に動かせるという利点はありましたが、エンジニア以外の人にもアノテーションをしてもらおうと思うとコマンドラインはハードルが高いのも事実です。そこで、slackからもアノテーションできるようにしてみました。もちろん、事例をアノテーションする順番は能動学習で決めています。

使い方はヘルプを見てもらうとよいですが、提示されたURLを見て、pとタイプすると正例としてアノテーション、nとタイプすると負例としてアノテーションされます。リアクションのところについているheavy_plus_sign(プラスのアイコン)やheavy_minus_sign(マイナスのアイコン)は正例/負例として能動学習のモデルに反映されたということを意味しています。slackはURLを投げるとスニペット的なものを表示してくれるので、アノテーションがしやすくなる(ブラウザで開きなおさなくてよい)という効用もありました。

有効な素性の提示

能動学習を使って事例をどんどんアノテーションしていくわけですが、わけも分からずどんどん事例を提示されても「なんでその事例が選ばれてきているんだよ!」という気持ちになってきます。そこで、show-active-featuresオプションを付けて、どういう素性が有効になってその事例が選ばれたのかを表示するようにしました。

% ./go-active-learning annotate cli --input-filename INPUT_FILE --output-filename OUTPUT_FILE --open-url

学習器の出力と正解ラベルが一貫していない事例を見る

数百件以上アノテーションをしていると、「あっ、これと似たような事例、さっき反対側のラベルに付けた気がする…」ということがときどきあります。一貫していない正解データは学習器の精度を落とす原因になるにもなるので、そういう事例はさっとラベルを修正したい。しかし、そういうのをいざ探そうと思うと結構大変です。

こういうのを探す助けになるように、学習器の出力と正解ラベルが一貫していない事例を見るコマンドを作りました。つまり

  • 正解ラベルは1なのに、スコアが負の大きい値
  • 正解ラベルは-1なのに、スコアが正の大きい値

といった事例を表示するということができます。使い方はこんな感じで。不一致の大きい順に出していきます。

下の例では、技術エントリかどうかを判定するためのデータに対して適用しています。facebookがマイナス(技術エントリではない)で出ているけど、正解のラベルは1になっていて、ラベルを付け間違えているっぽい、ということが分かります。

% ./go-active-learning diagnose label-conflict --input-filename INPUT_FILE
Index   Label   Score   URL Title
0   1   -0.400  https://www.facebook.com/   ログイン (日本語)
1   -1  -1.400  http://suumo.jp/town/   SUUMOタウン
2   1   2.000   http://hakobe932.hatenablog.com/    hakobe-blog ♨
3   -1  -2.000  http://r.gnavi.co.jp/g-interview/   ぐるなび みんなのごはん
4   1   32.400  http://www.songmu.jp/riji/  おそらくはそれさえも平凡な日々
5   1   90.000  http://motemen.hatenablog.com/  詩と創作・思索のひろば

もらったフィードバック

最近、go-active-learningを社内で紹介する機会があったので、そこでもらったフィードバックも紹介しておきます。

能動学習で使っている分類器/特徴量抽出器と実際に使う分類器/特徴量抽出器のズレ

go-active-learningでは能動学習をやるために

  • 特徴量抽出にタイトル、本文のBoW
  • 学習器に平均化パーセプトロン

を使用しています。しかし、本番ではもっとリッチな特徴量抽出を使っているかもしれませんし、学習器もSVMやロジステック回帰を使っているかもしれません。こういったズレがある場合、能動学習で提示された順にアノテーションしていっても思ったように効率が上がらないということがありえます(go-active-learningでは難しい事例だと思ったけど、本番の分類器にとっては簡単な事例だった、などなど)。これを防ぐためには、能動学習で使うもろもろと本番で使うもろもろが一緒になっているのが一番ですが、そうすると本番とべったりなツールになってしまいます。色んなところで使える能動学習のツールにしたいなと思うと、完全に一致しないのは仕方ないので、やり方としては

  • 本番に使われていそうな学習器をサポートして、なるべくズレが小さくなるようにする
  • 本番で使われていそうなURLに対する特徴量抽出(キーワードなどのメタデータなどなど)をなるべくサポート、選択できるようにする

などがあるかなと思います。goで数百行程度なので、本番用と一致するように移植するのもそんなに難しくはないとは思います。

ユーザーインターフェイス

便利そうだけど、CLIのみだとエンジニア以外にはハードルが高いという声があったので、今回slackからの入力をサポートしました。tokenの取得の手間はありますが、そこだけエンジニアがやってしまえばアノテーションはslackの画面のみで完結するので、大分ハードルは下げられたのではと思っています。

深層学習による自然言語処理 (機械学習プロフェッショナルシリーズ)

深層学習による自然言語処理 (機械学習プロフェッショナルシリーズ)

劣モジュラ最大化によるエントリの推薦をやってみた

背景

半年前から機械学習に関するよさそうなエントリを提示してくれるbot(ML君)を運用しています。

大量のtweetの中から関連するエントリを人手で探す手間は省けるようになったのですが、最近別の問題が起こっています。以下の画像はある日に提示されたエントリの結果ですが、arxivの論文(しかもほぼ深層学習関連のもの)ばかりになっています…。ML君はURLが与えられたときに、それが機械学習に関連するいいエントリかどうかを判定しますが、提示したエントリの話題が重複しているなど条件は全く考慮していないので、当然と言えば当然の結果です。ML君を責めてはいけない。

上のような推薦結果は私が深層学習研究者/エンジニアなら喜ぶかもしれませんが、残念ながらそうではありません。機械学習/自然言語処理に関連する企業のニュース/githubのライブラリなど、色々なトピックについてカバーして欲しいものです。問題設定が抽出型の複数文書要約と似ている(めっちゃ大雑把に説明すると、様々なトピックをカバーしつつ、重要な文を選択するタスク)なと思ったので、要約業界で使われる手法でこの問題を解決してみることにしました。

最適化問題としての自動要約/エントリ選択

X語以内でなるべく多くのトピックをカバーする(例えば異なり語をできるだけ多く)という問題は、典型的な離散最適化問題です。可能な解を全列挙すると

  • エントリ1を解に入れる/入れない
  • エントリ2を解に入れる/入れない
  • エントリNを解に入れる/入れない

となり、愚直にやると2^N通りについて考えなければなりません(これに加えて、その解が制約を満たしているかチェックする必要があります)。エントリは50個以上はあるので、全列挙は厳しいです。このような問題について研究している最適化理論の分野では、分枝限定法やラグランジュ緩和、劣モジュラ最適化などがよく使われます。今回は劣モジュラ最適化の方法を実装してみました。理由は以下の通りです。

  • 実装が簡単
    • 貪欲法の亜種のような形になるので、すぐ書ける
  • 高速
    • 線形計画法(ILP)のソルバーを使うと解が出るまで結構時間がかかります
  • 最悪ケースが保証されている
    • 目的関数が最適解の場合と比べて(1 - 1 / e) / 2以下にはならないってやつですね
    • かなり緩い下限ではあるものの、ないよりは安心できるし、実験的にはかなり最適解に近い解を出すことが多い

劣モジュラ最適化の欠点としては、目的関数が劣モジュラ関数である必要がある、というのがありますが、自分に必要なCoverage functionは劣モジュラ関数なので大丈夫です。

劣モジュラ最適化(最大化)のアルゴリズムは、あるエントリxを解に含めたときに目的関数が最も上昇するようなxを貪欲的に制約を越えるまで追加していく、という簡単なものです。目的関数はあるエントリの部分集合をS、元々のエントリ集合をVとすると、Vに含まれるエントリとSに含まれるエントリとの類似度の和のような形で表わされます。詳しくは元論文を参照してください。学生時代に紹介エントリも書いていました。

元論文では文iと文jの類似度を計算するために、それらの文に含まれている単語のtf-idfのコサイン類似度を計算していましたが、ML君でエントリから特徴抽出したベクトルに対する重みを保持していたので、エントリiとエントリjに関連する重みベクトルのコサイン類似度を今回は使ってみました(\mathbf{f}_i \odot \mathbf{w}\mathbf{f}_j \odot \mathbf{w}のコサイン類似度)。詳しい実装は以下を参照してください。

元論文ではCoverage function以外に多様性を考慮した項も入っています。しかし、論文の実験結果を見ると、この項がなくてもそれほど悪くならないようなので、今回は実装していません。

実験結果

元々100件程度あるML君の提示結果を、劣モジュラ最大化で20件に絞ってみました。結果はこちら。

arxivの論文もありつつ、最近出た本の話題や、人工知能系のニュースも入っていて、色々なトピックがカバーできたような気がします。自分で運用しているbotなので、評価用データセットなどは特に用意していないですが、しばらくこれで運用してみようと思います。

個々のアイテムのよしあしだけではなく、一覧や集合として出力されたもののよしあしを考慮したいケースはWebエンジニアでも結構あると思うので、他にも使いどころを探ってみたいところです。

劣モジュラ最適化と機械学習 (機械学習プロフェッショナルシリーズ)

劣モジュラ最適化と機械学習 (機械学習プロフェッショナルシリーズ)