2017年の振り返り技術編

ふと思いたったので書く。2016年は自然言語研究者からWeb系エンジニアになったということで、今振り返ってもキャッチアップで精一杯だったなーと思うが、2017年は去年よりは慣れたこともあり、もう少し自分にとって新しいことに取り組めたかなーと思う。といっても、XXXやり始めたという内容のほとんどが仕事で必要だったという理由なので、Mackerelチームで働くための基礎体力が本当になかったんだなと改めて痛感している(なぜはてなに入社できたのか謎)。飽きる暇もなく勉強の毎日です。来年はもう少し狭く深く掘り進めていきたいかな。

Go言語やり始めた

仕事でGo言語をやる必要があって勉強し始めたのが今年の初めだった。A Tour of Goを最初にやったけど、実際に手を動かしてレビューで見てもらったほうが早いなと思って、MackerelのグラフアノテーションをmkrでできるようにPRを出したのが初めだったと思う。

書き始めた最初はsortやるにもあれこれやんないといけないし、かっこよく書けないなーと思っていた。しかし、慣れてくるととにかく素朴に書くのがいい文化であることが分かってきて、慣れるとそれはそれでよいもんだということが分かってきた。最近では一番好きになった言語かもしれない。mattn/memoのソースコードを読んで小さいPRを出したり、中規模なものではSlackで能動学習をできるようなアプリケーションを書いたり、係り受け解析器、エントリ推薦を書いたりした。このくらいの規模をいくつか書くと大分慣れることができた。go routineはまだ使いこなせているとは言えない。

Goはcliアプリをさっと書けて、シングルバイナリで簡単に使ってもらえるのが最高だということが分かって以降、Mackerelのプラグインを作りまくったりしていた。Goの練習に丁度いいと思うので、どんどん書いて欲しい。

勢い余って他の人のプラグインのmkr plugin install対応活動もやっていた(しゅっとmerge & releaseしてもらってありがとうございました)。

Pythonやり始めた

こちらも今さら感がある。去年は仕事の機械学習のコードはPerlで書いていたけれど、今年はPythonで書く仕事がきた。Python自体は遠い昔書いていた時代があったので、大きな戸惑いは特になかった。scikit-learnやjupyterがあって、便利な世の中になっていた(激しく今さら感)。githubやgithub enterprizeがipynb対応していて、プロトタイプや調査結果の共有に便利。はてなのインターンの機械学習講義も今年からついにPythonにしました、講師を担当していた。

一方で機械学習以外ではGoがよかったこともあって、趣味ではあまりPythonのコードを書く機会がなかった。色んな環境でさっと使ってもらえることを考えるとpyenvでpython3.6をインストールしてもらって、pipでライブラリをインストールしてもらって...というを考えると面倒で、この辺はGoがいいなと思う。

異常検知やり始めた

書籍での勉強は昨年末に始めたけど、今年は手を動かして社内の多次元の時系列データでの異常検知のプロトタイプやproductionのコードを書いたりしていた。異常検知、教師なしがdefaultなので難しいだろうなと思っていたけど、予想通り簡単ではなかった。現場的には誤検知をどうやって抑えればいいか、どういうデータにはどういう手法ならばいいかのノウハウを少しずつ貯めていってという感じだった。中間アウトプットとしてMackerelのチェック監視で異常検知を行なうものを出したりしていた(これはさすがにGoじゃなくてPython)。

論文もちまちまと読んでいた。異常検知回りは問題設定でまだまだやられていないことも多いので、論文読んでて楽しいですね。

一般の機械学習や深層学習はそこかしこで勉強会やコミュニティが存在するけど、異常検知peopleはどこに行くと会えるんでしょうか。

深層学習やり始めた

仕事で現状必要になっているわけではないが、これからどう向きあっていくかを含めて色々試している。深層学習の本は山ほど出ているので、それで勉強しつつkerasで手を動かして感覚を掴んだりしていた。LSTMやCNNを使って社内の既存タスクを解き直してみたが、多少精度は上がるものの劇的というほどではなかった。これまで社内で取り扱っていなかった生成系のタスクや画像系の問題について面白い(かつお金にもなるような)問題を探っていく試行錯誤がもう少し必要そう。画像系は教師データと大量の計算機リソースが必要だと思っていたが、転移学習をベースにすれば全く手が出ないなんてことはなかった。とはいえ、深層学習に関係なく、社内のコーパスを含めたリソースは今後も定期的に整備していきたい。

AWSやり始めた

これも仕事で必要だった。MackerelのAWS/AzureのIntegrationをやっているにも関わらずcloudほとんど自分では使ったことがなく、仕事でもLambdaやDynamodb、EC2を使っていなかった。これはどう考えてもまずい、と思って趣味で動かしていたElasticsearchをAWS Elasticsearch Serviceに引っ越ししたり、Mac Miniで動かしていたクローラーをEC2に引っ越ししたりすることから始めた(これはraspberry piを買ったので、今はやめた)。Jenkinsで動かしていたいくつかのJobをAWS Lambdaで動かすようにした。

仕事でやるような規模のものは趣味の範囲では無理なので、この辺で得た知見をベースに仕事でも生かしていきたいなという感じ。

Docker&Ansible始めた

これも仕事で。最初はすでに存在するdocker imageをdocker runしかやっていなかったけど、Dockerfile書いたり、composeが何者か分かってきた。簡単なやつではあるけど、自分でよく使いそうなものはDocker Hubに置いたりしていた。

Ansibleは自分のクローラーのコードや環境設定をEC2でバチっとやりたかったので、少し勉強した。sshしてあれこれやらなくていいのは便利ですね。EC2だと環境作っては壊してというのがお手軽にできる。mackerel agentのcheck監視の設定で細かいところに手が届かなかったのでPull Request送ったりしていた。

IDEに魂を売った

これは仕事じゃなくて趣味。去年までは頑張ってScalaをEmacs(ensime)で書いていたんだけど、いよいよ辛くなってきた。これはEmacsに固執している場合じゃないと思って、IntelliJ IDEAを使い始めた。変数の型が分かったり、関数の定義元にさくさく飛べるので、大分効率が上がった。メモリがっつり持っていかれるのが痛いけど、これは諦めた。IntelliJ IDEAが便利だったので、Python(PyCharm)やGo(Goland)を書くのもIDEを使うようになってしまった。

Emacsで書くものがmarkdownだけになってしまったので、気分転換がてらvimに乗り換えをした。今のところそんなに困っていない。左手が楽になった。なお、SKKはまだ捨てれていない。多分捨てられない。

AWS Batchのメトリックを収集するMackerelプラグインを作りました

AWS Batchを仕事で使うことになりそうなので、Mackerelのプラグインを作りました。Queueの状態をカスタムメトリックとして収集します。mkr plugin install mackerelio/mackerel-plugin-aws-batchでインストールしてくれ!

AWS Batchの困りどころ

全然使い込んでいるわけではないので、他にもありそうですが。AWS Batchの裏側で起動するEC2インスタンスのCPUとMemoryの組み合わせでいいものがないと、BatchがfailするわけではなくRUNNABLEという状態に行って滞留するようです。

知らないうちにQueueが溢れていると困るから監視したいなーと思ったので、プラグインを作りました。Mackerelのプラグインではないですが、同じようなことをしている先人がいらっしゃいました。

cloudwatchから直接メトリクスを取れるわけではないので、同じようにstatus毎に集計をしています。

特定のDockerコンテナが起動しているか確認するチェックプラグインを作りました

Dockerコンテナをデーモンとして起動(docker run -d ...)させていたけど、いつの間にか死んでいたのを後から知った...ということがあって悲しかったので、特定のDockerコンテナが起動しているかを確認してくれるMackerelのチェックプラグインを作りました。mkr plugin install syou6162/check-docker-psでインストールしてくれ!

check-procsプラグインのdocker版のイメージで作りましたが、コンテナ名はexact matchのみ、個数はまだ指定できないといった感じです。使ってくれそうな人がいたら対応していこうかなという気持ち。

mkrのプラグインインストール機能を使って自分のプラグインをインストールしよう

3行まとめ。

  • mkrにプラグインインストール機能が付きました
  • jenkinsのビルド時間を監視するチェックプラグインを作って、mkrでインストールできるようにしました
  • 簡単にできるので、是非色々なプラグインを作ってみてください!!

mkrにプラグインインストール機能が付きました

mkrはMackerelをコマンドラインから手軽に操作できるツールですが、最近のリリースでなんとpluginインストールの機能が付きました。これまで独自のpluginチェック監視を入れようと思うと、以下の2つの方法がメインだったと思います。

  • (1)公式リポジトリにPull Requestを送り、レビューを経てマージされ、リポジトリに取り込まれる
    • 「やっつけで書いたけど、レビューされるならテストも書かないと...」
    • 「英語でPull Request送るの微妙にハードルが高い...」
    • と感じて、公式にPull Request送るのに躊躇していた人もいたのでは
    • しかしながら、公式に取り込まれるとapt-getyumでも手軽にインストールしてもらえるようになるというメリットは大きい
  • (2)個人のリポジトリに置いて、使いたい人の手元でビルドしてもらう
    • レビューはないので、その分気は楽
    • 自分の用途に特化したニッチなプラグインでもいける
    • しかし、apt-get installなどでは入らないので、使ってもらう側に一手間かけてもらう必要がある

mkrでのプラグインインストーラーはその間を取った方法で、以下のような特徴があります。

  • 個人のリポジトリに置いておけるので、レビューしてもらう必要はない
  • 個人のリポジトリにビルド済みの成果物を置く形式なので、使ってもらう人にビルドしてもらう必要はない
    • mkr plugin install ...で成果物をインストールしてこれる
    • 個人のリポジトリの管理者は成果物をGithub Releasesに置いておく必要はある
  • 個人のリポジトリに置いているけど広く使ってもらいたい、という場合にはプラグインレジストリに登録してもらうのがお勧めです

jenkinsのビルド時間を監視するチェックプラグインをmkrでインストールできるようにする

業務でscalaプロジェクトのビルドや成果物をまとめるのにjenkinsを使っているのですが、ときどきビルドが終わらず1日経っていた...ということがあります。1時間経ってもビルドが終わってなかったら通知してくれるようなチェック監視があれば便利だなと思って、Mackerel Plugin Hackathonのときにプラグインを書きました。ただ、公式に入れるには用途的にニッチ過ぎるやんということで、一旦closeしていました。そして、個人のリポジトリで置いとくのも面倒だなと思って放置していました...。

しかし、mkrのプラグインインストーラーができたので、リポジトリを作って再チャレンンジしました。といっても元のスクリプトはほとんど変更せず、Githubへリリースする仕組みをsampleリポジトリを参考にして追加しただけです。思ったよりお手軽。

簡単にできるので、是非色々なプラグインを作ってみてください!!

お手軽なやり方、より詳しくは公式ドキュメントを参照してください。

mkr plugin installできるいいプラグインができたら、今年のadvent calendarで是非自慢を書いてみてください!お待ちしております!

Anomaly Detection in Streams with Extreme Value Theoryを読んだ

KDD2017の異常検知の論文です。異常検知を行なうとき、何らかの閾値を設定しますがこの閾値の決定は難しいことが多いです(そして精度にはよく効いてくる...)。正規分布のように理論的によく知られていて、解析的にも扱いやすいような分布では、累積分布関数を逆に辿ると「99.9%に対応する閾値はこれ!」と設定することができます。しかし、確率分布を陽に仮定するとそれ以外の分布ではきちんと動かなかったり、データ毎にモデル化をする必要があります。陽に確率分布を仮定しない方法もありますが、そちらはデータが少ないor厳しめのパーセンタイルを指定したいときに難しさがあります。例えば、データが1000個しか取れないような場合に99.9%に対応する閾値を知ろうと思って、異常値のスコアの999番目に大きい値を取ろうとすると、その値がぐらつくだけで閾値が大きく変わってしまう場合などです。こういう場合は理論値が知りたい。

この論文ではデータ自体の分布を陽に仮定はせず、データの最大値や分位点に関する分布を異常検知に用いることを考えます。最大値のような極端な値(Extream Value)は順序統計量と呼ばれたり、極値統計学と呼ばれる理論があり、自然災害への対応やファイナンス(Value at riskなど)などに特に応用されています(津波や地震などは平均的な挙動が知りたいわけではなく、例えば一年間で最も災害をもたらしそうな値がどれくらいのものなのかを知りたい)。Extream Valueを異常検知に適応する考え方自体は前からあったようですが、この論文ではサイバーセキュリティのように大量のデータが流れてくる、かつデータの傾向も動的に変動するといったケースに対応できるようにしようというのがこの論文の主な貢献です。

極値統計学

  • 極値分布はi.i.dなサンプルの最大値や最小値をモデル化した分布
    • i.i.dの元になってる分布によって極値分布も変わるが、一様分布、ガンマ分布など、様々な分布を包含した一般的な形で書くことができる
  • P(X > zq) < qとなるような閾値zqを極値分布を使って知りたい
  • 極値分布のパラメータ推定をすればよいが、特定のケースしかあまりうまく行かないようだ
  • そこで、分布のtailの部分をfitingする他のアプローチとして、Peaks-Over-Threshold(POT) approachというものを使う
  • このアプローチは緩い仮定の条件下で、条件付きの累積分布がSection3.3にあるような形で分布収束するというもの
    • Xが閾値tよりもx以上大きくなる確率(P(X - t > x | X > t))
    • 収束先の分布に対して推定を行う(この場合、パーセンタイルにそれがなる)
  • 収束先の分布は一般化パレート分布になってる
  • 最尤推定でパラメータを計算できたら、欲しい確率qに対応した閾値zqを(1)式によって計算することができる
    • この式はどこから出てきたんだ...?
    • この辺((2.9)式)あたりを見ると分かりそうだった
  • 静的でバッチでいいときはAlgorithm 1で決める
    • 最初の閾値tをどうやって決めるかが謎だが、section 4.3.2によると学習データの98%タイルのようなある程度大きい(かつ1-qより小さい)empirical quantileを使うようだった

Streamへの対応

  • やりたいこととしてはデータの傾向が動的に変わる場合だが、その前にパラメータがをstreamで更新できるように拡張する
    • Algorithm 2
  • ストリームと書いてあるけど、閾値を超えてる集合(Y)をmaintainして、パラメータはバッチでどかっと再計算してた...。オンラインっぽいノリではないのか
  • ただ、多分、異常検知の文脈で閾値を超えたようなやつのサンプル数って多くないからバッチでやり直しても実質問題ないってことなんだと理解した
  • 元データが10000あっても99%タイルだと100個しか学習に実質使われない、みたいなノリ
    • これのおかげで、秒間1000くらいデータが流れ込んできても平気だそうな
  • 集合に追加はされるが、削除はされない
  • パラメータ推定はGrimshaw's trick(section 3.4.2)というのを使うそうだけど、一般化パレート分布のパラメータ推定ではよく使うテクニックらしい

Drift caseへの対応

  • Streamへの対応だけでは保持してる集合に追加してくだけで、分布が変化していく場合に対応できない(drift case)。それに対応できるようにする
    • (streamってそもそもメモリにデータ全部乗っけとけないって設定だった気がするけど、この論文はそういうこと考えてない気がする)
  • 移動平均使って若干ずらしていく感じ?アドホック過ぎて正当性はあまりなさそう
    • この方法でなんでいいのかは述べずに実験の章に突入
  • こっそりとwindow-sizeという新しくて重要なパラメータが追加されている

実験

  • 人口データで理論値と閾値の食い違いを評価(section 5.1)
  • 静的なデータの例(サイバーセキュリティ)はうまくいってそう(section 5.2)
  • 動的なケースもまあまあ(section 5.3)
    • window-sizeの調整は難しそうではある

論文を読んだ感想

  • 異常検知では分布全体よりも極端な値の傾向を知りたいことが多いので、極値分布や一般化パレート分布を用いてtail部分を重点的にfittingしにいくというアプローチは面白い
  • 極値理論という硬派な(?)理論をベースにしているわりにはstreamやdrift caseへの対応はアドホックな感じで、理論的な正当性があまりない
  • empiricalにはよいでしょう、という感じで実験で保証
    • しかし、実験はもっと他の手法とも比較実験をして欲しかった
    • おそらく事前に分布の形状が分かっているならば提案手法が負けてしまうから、というのが大きい気はする...
    • とはいえ、分布の形状が事前に分からなくてもこれくらいcomparativeな結果が出ます、というので十分だとは思う

IBIS2017の聴講ログ

今年で20周年のIBIS2017に仕事で聴講参加しました。IBISは意外と初参加。とにかく大量の発表があり、全部書いてると膨大になってしまうので、自分のアンテナに引っ掛かった研究についてのみログを残しておきます。問題設定やモチベーションを重点的にメモしており、理論面は嘘を書いている可能性が高いので、気になる人はそれぞれの論文を読むといいと思います。

Learning from Complementary Labels (NIPS 2017)

  • 国際会議採択論文(論文pdf)
  • 多値分類でラベル数がそれなりに多い(数十〜100程度?)問題設定を考える
  • 「このインスタンスはこのラベル」というのをぴったりアノテーションするのは結構大変
  • しかし、「このインスタンスはこのラベルではない!」というのを見つけるのは↑より圧倒的に簡単でアノテーションコストが低い
    • このラベルの付け方をcomplementary labelと呼ぶ
    • 最近のクラウドソーシングでのアノテーションに向いている?
  • このラベルの付け方でも学習できる枠組みを提案
    • unbiased estimatorが得られる
  • complementary labelに加えて、これまでのラベル(このインスタンスはこのラベル、という付け方)も教師データに混ぜることができる
  • 学習時にcomplementaryを考えるのは以前からもあったけど、学習データ自体をcomplementaryにするという考え方は面白いなと思った

Semi-Supervised Classification Based on Classification from Positive and Unlabeled Data (ICML 2017)

  • 杉山研で正例+ラベルなしデータのみからの学習(PU学習)の研究がたくさん出ていたけど、その中でも一番気にいった
    • PU学習の肝: ラベルなしデータは正例の分布と負例の分布の重み付き和からなるとしたところ
    • 論文pdf
  • ラベルなしデータを教師あり学習に活用する半教師あり学習が昔からあるが、分布に対する仮定が成立しないとラベルなしデータを追加すると精度がかえって悪くなってしまう場合がある
    • この研究ではそういった分布への仮定を一切置かない
  • PU学習の考え方を使って目的関数を以下の3つのパートに分解
    • PU(positive/unlabeled)
    • PN(positive/negative)
    • NU(negative/unlabeled)
  • 3つそれぞれ別の分類器を学習するわけではなく、3つのパートを考慮した1つの分類器を作る
    • 学習は損失関数の形によって異なる
  • ラベルなしを混ぜたほうが理論的にも強いことが言える
    • エラーバウンドが小さい、分散が小さいなど
  • 正例を集めるのは簡単でも負例の多様性があってカバーしきれないときは結構実務でもあるので、ラベルなしでうまいことやれそうだなーと思いながら聞いていた
    • 例: non-spamなエントリでも色んなカテゴリのエントリや色んな言語のエントリがある

音声対話アシスタントに関する最近の研究動向とYahoo! JAPAN研究所での取り組み

  • 企画セッション:自然言語処理への機械学習の応用

  • 音声対話を実環境で運用する際に課題になる研究をいくつか紹介されていた、非常に面白かった
  • 新ドメインの迅速な追加
    • 最近は多様なドメインで音声対話が使われるようになってきた
    • これに対応するために分野適用(domain adaptation)がよく行なわれる
    • 従来法では新しく転移元ドメインが追加されると、学習を全データでやりなおさないといけない
      • 転移元ドメインの数が多い場合に非効率になってしまう
    • 提案法は転移元ドメイン毎にモデル(BiLSTM)を学習しておいて、attentionでそれらを束ねて計算する仕組み
    • attenstion部分の再学習のみなので、転移元ドメイン数が増えても学習時間の増加を抑えられる
  • タスクと雑談の切り分け
    • タスク型の対話アプリと注記しても、ユーザーはそんなこと構わず雑談をしてくる
    • 実環境ではタスク型と雑談型を切り分けるのは難しいので、どちらの発話かを見分ける必要がある
    • 特徴量を工夫する
      • 雑談っぽさを捉えるためにreply付きのtweetから言語モデルを作る
      • タスクっぽさを捉えるためにWebの検索ログをタスク要求の発話と見なして、これも言語モデルを作る
      • これらの対数尤度をそれぞれ特徴量に入れる
      • 極端に長い/短い発話に対して特に有効だったそうだ
    • 検索の会社ならではの特徴量が聞いていてよさがあった
  • ユーザー満足度の自動化
    • 対話研究は真の正解がないので客観評価が難しい
    • ユーザーの行動パターンからユーザーの満足度を推定するモデルを作る
    • 特徴量の工夫
      • 発話に対してアクションラベル(Select、Command、Confirmなど)を推定、系列を特徴量として入れる
      • クリックや音声認識の確信度
      • 音声入力からテキスト入力に切り替えた、など

ディープラーニングによる画像変換

  • 企画セッション:画像処理への機械学習の応用
  • 画像補完
    • 飯塚里志 — ディープネットワークによる画像補完(SIGGRAPH 2017)
    • とにかく魔法みたいだった(小並感)
    • 元画像をランダムに欠損させたデータからCNNを作るだけだとぼやけた補完しかできない
    • GANを使うことでボヤけにくく
    • GAN以外にも画像全体が整合性が取れるように大域識別ネットワーク、局所的な整合性が取れるように局所識別ネットワークも入っている
  • ラフスケッチの自動線画化
    • シモセラ エドガー ラフスケッチの自動線画化
    • デモページは見たことがあって、CNNでやってるんだろうくらいに思っていたが、教師データが何と68枚しかない!
    • その状況であれだけ動くものをどうやって作るかの話が面白かった
    • 素朴な工夫: data augumentation
    • ラフスケッチと線画のアライメントが取れているデータはない(あるいはあっても結構書き変えられたりされているらしい)が、ラフスケッチ単独、線画単独のデータはたくさんある
    • ラフスケットと線画のアライメントがあるようなデータに対して
      • ラフスケッチを線画化、元から線画になっているデータのどっちが本物であるかを判定するGANを作る
    • アライメント取れていないデータに対して
      • 似たようにGANを作っていく

D1-22: 機械学習モデルの列挙

  • 機械学習が高精度の出力を出せるようになってきているが、ユーザーが結果に納得するかは別問題
    • 例: この特徴量が効いてないのはおかしい、こんな分類器は何か間違ってるんじゃないか!
  • ある程度同程度の精度のモデルをk個出力して、その中からユーザーに納得できるようなものを選んでもらう
  • 候補をいかに効率的に列挙するか
  • 特徴量全部入りのものから徐々に減らしていく
  • 使えるモデルは線形モデル(LASSO)とルールベースのモデル

D1-38: 自己回帰テンソル分解による時空間予測

  • ICDM2017
  • ある時、ある場所の人の数を予測したい
  • これまで観測されていなかった場所を予測するものは外挿問題になる
  • ARとテンソル分解を交互に推定
  • ARなのに周期性を捉えられているのがよく分からなかったが、基底が周期性的なものを学習してくれているとARでもいけているっぽかった
    • 理解が曖昧

D1-32: Maximum mean discrepancyに基づく分布マッチングを用いた教師なしドメイン適応

  • セキュリティなどの分野は刻一刻と分布が変化していく
    • 教師なしのドメイン適応の必要性
  • targetのxの分布がsourceのxに近くなるようにAx + xの変換行列Aを学習
    • かつ、Aのノルムはなるべく小さくなるように
  • targetのラベルがないので、トレードオフのハイパーパラメーター設定は難しそうだった
  • セキュリティの場合、分布が変わるというより新しい特徴量が入ってくることのほうが難しくて問題そうだなと思ったら、ご本人がすでにそういう研究やっていた

D2-4: Delayed Feedback を考慮した予測モデルの提案

  • クリックしてからコンバージョンするまでに日数(max30日くらい?)がかかる場合も考慮してcpmの予測モデルを作る
  • p(C=1, D=d | X=x) = p(C=1, X=x) p(D=d | X=x, C=1)として前者をロジステック回帰、後者を指数分布でfittingさせるのが既存研究
  • 広告主によってはコンバージョンするまでの分布が結構違うと思われるので、指数分布より柔軟なカーネル密度推定(KDE)を使うのが今回の提案手法
  • KDEは学習データの足し算が出てくるのでメモリ的にも計算時間的にも割と大変だが、広告で使えるのかなという点が気になった
    • 指数分布の混合分布くらいでよくないかな?
  • 補足: 共著者様から補足で説明してもらいました。KDEっぽい定式化ではあるけど、学習データを使った密度推定は行なわない & 学習データも全て使うわけではないので、それほど重くないそうです

D2-36: 観測が制限されたオンラインスパース線形回帰問題に対する効率的アルゴリズム

  • 理論的な研究であり紹介されていたregret解析はほとんど理解できなかったが、問題設定として新しいものが出てきているんだなあと思ったので紹介
  • 機械学習の特徴量はM次元あったらM次元全て埋まっているような前提で動くものが多い
  • 実世界への応用を考えると全部埋まっていないことも多々ある
    • 病気の予測にいくつかの検査結果の項目を使いたいが、M個全てやってもらうと患者への負担が多いので、k個しか受けたくない
  • 現在の設定だとkはインスタンス毎に変えられず、グローバルに一個持っておく設定
  • 検査の受診コストみたいなものも反映されるようになってくると面白いですね
    • 例: 同じくらいの予測精度なんだけど、受診コストは最小
    • 例: これくらいの受診コストは払えるからその中で予測精度が一番高くなるような受診項目教えて

ホストメトリックの異常検知を行なうmackerel-agentのチェックプラグインを作りました

最近、異常検知の実験/実装を行なっていますが、その過程の中間成果物をmackerel-agentのチェックプラグインとして切り出しました(非公式のプラグインです。サポート宛てにお問い合わせしてもらっても回答できません。id:syou6162まで個人的に連絡してもらえたら対応できるかもしれません)。docker pull yasuhisa/check-host-metric-anomalyで簡単に使えるので、是非遊んでみてください。

このチェックプラグインの使いどころは

  • ホスト監視をしたいが、どれくらいの閾値が適当なのか分からない/閾値の調整が面倒なので、よしなにやって欲しい
  • 閾値による監視や式監視だけでは対応できないようなホストメトリックの変化を早期に発見したい
    • 例: 周期性があるので、静的な閾値監視だけでは不十分

といったところを想定しています。サービスメトリックにも仕組みとしては対応できますが、ホストメトリックと異なり投稿頻度が1分粒度とは限らないため、今回はひとまずホストメトリックのみ対応しています。

mackerel-agent.confに監視したいホストメトリック毎に以下のような設定項目を追記、mackerel-agentを再起動すれば、異常検知によるホストメトリックの監視が開始されます。異常検知アルゴリズムの学習データとして3週間程度の直近のホストメトリックを取得する必要があるため、MACKEREL_APIKEYが必要です。オプションの-v /tmp:/tmpは学習済みのモデルファイルの置き場を指定しています。

[plugin.checks.anomaly_sample]
command = "/path/to/docker run --rm -e MACKEREL_APIKEY=XXXXX -v /tmp:/tmp yasuhisa/check-host-metric-anomaly /app/run.sh --host-id HOST_ID --metric-name METRIC_NAME"
max_check_attempts = 3

たくさんのホストメトリックに対して異常検知したい場合、毎回docker runしているとコンテナの起動/停止コストが大きくなってくるため、docker startdocker execを使う方法がお勧めです。詳しくはREADMEを参照してください。

簡単な解説

  • 時系列データに対する異常検知の代表的なアルゴリズムの一つであるLOF(Local Outlier Factor)を利用しています
    • 教師なし学習であり、教師データ(どのデータ点が異常か/そうでないか)を与える必要はありません
    • 大雑把には「自分の近傍にデータ点が少ないデータほど異常である」というk近傍法的な考え方のアルゴリズムです
    • 1次元の時系列データをwindow幅Dで区切り、D次元ベクトルに変換後、LOFを用いて異常か判別します
  • モニタリング専用のホストで動かすのがオススメです
    • アルゴリズムの学習(ディフォルトは1時間おき)と予測をmackerel-agentを動かしているホスト内で行なうので、多少負荷がかかります
    • あまりに多くのホストメトリックの監視を行なうと、command timeoutしてUNKNOWNになってしまう場合があります
    • Dockerコンテナ上で動かさず、ホスト上で動かすようにすれば負荷は下がる(timeoutも起こしにくくなる)と思いますが、scikit-learnなどのPythonのライブラリを手元にインストールしてもらう手間がかかるため、このようにしています
  • 異常が検知できない/誤検知する場合
    • LOFは様々なタイプのデータに対して頑健に動くアルゴリズムですが、当然完璧ではありません
    • 例えば以下のようなタイプのデータは苦手です
      • 1日に一回のみ動くバッチが走っているホストのメトリック
      • ディスク容量のような単調増加するメトリック
    • 誤検知(異常でないにも関わらずアラートが発生)が起きる場合、mackerel-agent.confに以下の設定を行なってみると誤検知を回避できるかもしれません
      • --window-sizeを大きめに設定する
      • --warning--criticalを小さめの値に設定する
    • 異常であるにも関わらずアラートが起きない場合は、上記と逆のことをやってみるとうまくいくかもしれません

入門 機械学習による異常検知―Rによる実践ガイド

入門 機械学習による異常検知―Rによる実践ガイド

Mackerel サーバ監視[実践]入門

Mackerel サーバ監視[実践]入門

  • 作者: 井上大輔,粕谷大輔,杉山広通,田中慎司,坪内佑樹,松木雅幸
  • 出版社/メーカー: 技術評論社
  • 発売日: 2017/08/26
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る