St_Hakky’s blog

Data Science / Human Resources / Web Applicationについて書きます

【Kaggle】 Kaggle APIを使ってみる

こんにちは。

今日は、Kaggle APIを使って、データのダウンロードとかしてみたので、その作業内容をまとめる。

Kaggle APIとは

Pythonで実装されたコマンドラインツールを使用してアクセス可能なKaggleの公式APIのことです。Pythonのライブラリの一つなので、pipでインストールすることができます。

これを使うことで、データのダウンロードなどを行うことができます。

インストールと設定

pipでインストールすることができます。

$ pip install kaggle

この状態で、

$ kaggle

とうつと、おそらく次のようなエラーメッセージが表示されると思います。

Unauthorized: you must download an API key from https://www.kaggle.com/<username>/account
Then put kaggle.json in the folder /Users/st_hakky/.kaggle

指示通りに、Kaggleの個人アカウントのページに行って、以下のような部分があるので、そこで「Create New API Token」という部分をクリックします。

f:id:St_Hakky:20180519132638p:plain

自動的に自分のローカルにファイルがダウンロードされるので、あとは権限を変更します。

$ chmod 600 ~/.kaggle/kaggle.json

これで初期設定は完了です。

データをダウンロードしてみる

試しに、現在開催されているコンペのデータをダウンロードしてみます。

ダウンロードする時の手順としては、まずコンペに参加します。そのあと、コマンドを打ってダウンロードするというような感じです。

今回は、現在開催されている以下のコンペのデータをダウンロードしてみることにしました。

金融系のコンペみたいです。

まずは参加しないと行けないので、してください。しないままダウンロードしようとすると、「Forbidden」みたいな感じのエラーが出ます。

参加したあと、コンペティションの「Data」タブに行くと、データをダウンロードするためのコマンドが書いてあるので、それを打ちます。

$ kaggle competitions download -c home-credit-default-risk


そうするとデータのダウンロードが始まって、 「~/.kaggle/competitions//」のところにデータが入るようになります。

こんな感じで使えるのは便利ですよね。そのほかの便利なコマンド、例えば予測結果の提出などもあるので、またみてみようと思います。

今日はそんな感じで。

【Kaggle】「Mercari Price Suggestion Challenge」に参加したあと、改めて色々調べてみたのでまとめる

こんにちは。

Mercariが主催したKaggleのコンペティションである、「Mercari Price Suggestion Challenge」について、過去に参加して色々見ていたんですが、機会があって改めて調べてみることにしたので、調べた内容とかをまとめてみました。

今回のコンペの概要

コンペの内容

コンペの内容としては、「有名なフリマアプリであるMercariの中で、出品者が出品する際の商品の価格をレコメンドすること」です。

具体的には、過去の出品者が出して来た商品の情報、例えばアイテムの状態やブランド名、説明などから商品の価格をレコメンドすることが求められます。

過去の出品者の価格を元に商品価格のレコメンドを行うので、その意味では「あなたの商品の状態なら、このくらいの価格が過去の出品状態からすると適正ですよ」みたいなのをレコメンドする機能とかに使えそうです。

完全にこれは妄想ですが、フリマでお金儲けしている人とかだと、「如何にして売るか」みたいなのがメインになるので、少し違う観点から価格を決めたいとかはあるかもしれませんが、一般の出品者からすると「とりあえずみんなが出しているっぽい価格」みたいなのでいいと思うので、普通にアプリ内で登場してもおかしくなさそうな機能だなぁと思って見ていました(メルカリのアプリ使ったことないので知らないんですが、もしかしたら既にそういう機能があるのかもしれませんが)。

Kernels Only

今回のコンペは、「カーネルのみでデータのロード、前処理、モデルの学習、予測までを全部1時間以内に行う必要がある」という点が特徴的で、Kaggleのカーネル内で、前処理・モデルの学習・予測の全部を60分以内に終わるようにする必要がありました。

なので、計算機のスペックに依存しない戦いができるということで、よりフェアな戦いができた感があります。他のコンペだと、

  • そもそもデータセットが大きすぎて無理
  • 大きなモデルを沢山作って、力技で勝つ

みたいなこともあったりして、どのくらい課金するかみたいなところが勝負になるところもありますが、今回はKernels Onlyということで、その意味ではだいぶフェアだなぁと思いました。

Kernelのスペックとしては、

  • 16 GB ram
  • 1 GB disk
  • 4 core

という感じでした。

このようなルールもあった関係で、「2nd stageの方のテストデータを予測した時に、制限時間内に終わるのか」みたいなディスカッションがあったのですが、「とりあえず1st stageで終わっていれば確実に終わるようにするよ」みたいな感じで、そういうのも見ていて面白かったです。

今回のコンペ、私のようなお金のないガチ勢にとっては良かったのですが、稀に良くKernelが落ちていたので、とてもイライラしたというのはあります笑。

イベントもやっていた

先日、MercariでこのKaggleの優勝者の皆さんを集めてイベントをされていました。ツイッターに流れている、イベントの様子をみるだけでもめちゃめちゃ面白いので、ぜひ見て見てください(笑)(ちなみに私は予定が合わなくていけなかった、、、行きたかった、、、)

togetter.com

ブログでまとめてくださっている方もいます。会場の雰囲気とかはこれで結構わかるので、行けなかった身としてはとても嬉しい。

メルカリという日本の会社が出したコンペだったので、余計にそう思ったところがありますが、Kaggleの使い方みたいなところがうまくわかるなぁと思いました。

企業がコンペを出す意味というところは、以下の3つが主にあげられるかなぁと思います。

  • 採用活動
  • サービス/会社の宣伝
  • 良い解法の獲得

今回のメルカリが出したコンペは、これらのメリットをフルに生かしているなぁと感じました。

まず、題材が実際に使われそうなものであったので、実際のサービスの宣伝にもなりました。良い解法の獲得という意味でも、Kernels onlyという制約を設けることで「とんでもない計算量を要するモデル」みたいなのを防ぐこともできていたように思います。また、このコンペの後に優勝者や日本で上位だった方を読んでイベントも行なっていたので、その意味でも優秀なデータサイエンティストを採用するという意味ではかなり良かったのではないでしょうか。

Kaggleの問題を出す側としては、とてもお手本になるようなコンペだったと思います(Kaggleのコンペを出す側になることはないだろうけど)。

Kernels

EDA

データ分析をする前に必ず読むといっても過言ではないし、ちょっと遅れて参加したコンペとかでは必ず上がっているEDAですね。

今回のコンペでは、以下の3つのEDAがめちゃめちゃ参考になりました。

一番上のやつとか、すげー頑張っていて、自分でやる気も失せるくらいでした笑。

Top入賞者の解法を眺めてみる

優勝者の解法

優勝者の解法がコンペの後にしっかりと公開されていて、とても嬉しい限りです。とっても勉強になりました(正直、まだ100パーセント理解していない)

参考になるリンクを以下にあげていきます。

コードを見てもシンプルすぎて禿げますね(禿げないけど)。また、解法を解説したスライドもGithub上に上がっていました。

また、このコンペの解説動画を出している方がいますので、解説はこちらを見たほうがいいと思います。わかりやすかったです。

youtu.be

余談ですが、Kaggleのさいつよが集まったslackもこの動画を解説されている方が出しているので、そちらもぜひ。とても有益な知見がガンガン投稿されていて、普通にびっくりします笑。


Top陣の解法

トップ数パーセントにいる人たちの解法が上がっていたので、それをまとめてみました。

参加しての反省点

時間をめちゃめちゃかけないとどの道上位にいけない

途中までは結構順調に行っていたのですが、途中からスコアが伸び悩んでしまい、また修論などに重なってしまったのもあって、進捗が出せずそのままFinishになってしまいました…。

途中まではBaseラインのモデルを元に、前処理の内容とかを追加したりとかしていたんですが、気づいてしまったこととして、「人間性を捨ててスコアをあげるしかない」ということがあります。

ちなみに、「Kaggle 人間性」でTwitterで検索すると、やはり人間性を捨てているのかぁという気持ちになります。

twitter.com

正直スキルなどにも依存する部分もあると思いますが、最後の方になってくると「気合い」みたいなところも大事なんだなぁと思いました。

通常のNLPでよくやることをやってしまった

いわゆる前処理みたいなところとかを一通り試したんですが、これをやってしまうと時間が全然足りなくなり、なんとか高速化の道を模索していたんですが、優勝者の回答をみるとこれがダメだったみたいです…(辛い)

どう頑張っても時間がかかるなぁって思った瞬間に、やめるべきだったなぁと。

Kaggleの楽しみ方(なぜこのコンペに参加したか)

もちろんKaggle上で戦いたいというのもあったんですが、結構勉強にモチベーションがあったりしたので、そこらへんも書いて置こうかなと思います。

個人的な考え

メルカリのコンペは自然言語処理がキーだったのですが、私自身が自然言語処理にあまり詳しくなく(やったことがないわけではないが)、結構試行錯誤してやりました。

その過程で色々勉強になることもありましたし、得られるものもたくさんありました。カーネルを見て「あーこうやってやれば良いのかぁ」ってもったり、ディスカッションを見て「なるほど、このライブラリもあるなぁ」とか思ったりしていました。

なので、競い合うのがKaggleの目的なのかなぁと思っていたのですが、Kaggleはいろんな楽しみ方があるなぁと改めて思いました。

とりあえず分野ではなくてもやってみる、って感じが大事なのかなぁと思いました。


それでもやっぱり神の領域に近づきたい

とは言ってもやっぱり、神の領域に近づきたいなぁと思うわけですよね。

Kaggle – 神々に近づくために | threecourse's memo

頑張ろう。

今後も参加したコンペについては何かしらあげていきます。

【Python】時系列解析:Prophetで時系列解析してみたのでまとめる

こんにちは。

最近、時系列解析が熱いですね!(ただ、仕事で使っているだけという笑)

Rの方がまだ時系列解析のライブラリなどは揃っている感じはあります。Pythonでやろうと思うと、選択肢に上がってくるのは、statsmodelsなどもあると思いますが、今回はFacebookが作成して公開している、「Prophet」というライブラリを使用してみようと思います。

本家のサイト

いくつか参考になる本家のサイトをあげておきます。また、このライブラリ自体はRでも使用することができます。

Githubによると、このライブラリはFacebookの「Core Data Science team」によって作成されたオープンソースライブラリみたいです。どうでもいいけど、Data Science teamのページがかっこよすぎる、、、。

Install

今回使用した環境が、MacなのでMacでのインストール方法について書きます。このライブラリは、pystanに依存しているみたいですね。

■pip

pipでインストールすることができます。これが一番簡単かなと思いますね。

$ pip install fbprophet
■conda

私はAnacondaを使っているので、こちらの方法を試しました。

$ conda install gcc
$ conda install -c conda-forge fbprophet

gccをセットアップするにあたって、それも事前にインストールする必要があるみたいです。

Prophetを使ってみた

本家のサイトにもあるQuick Startをやってみます。

他のドキュメントについては、以下を見るのが早そうです。

論文を読んだメモ

以下の論文を読みました。

論文を読んだ時のメモだけでブログを書こうかと思ったが、先人があまりにも素晴らしすぎる記事を書いているので、改めて私が書く必要はないなと思ったので、ここでは簡単に実際にモデルを改良する際などに参考になりそうなメモを残します。

概要説明系の資料は、以下の参考のところにいくつかリンクを貼ったのですが、中身の具体的な理論については、以下のブログが参考になりました。

時系列データにおける異常値の取り扱いについて
  • 異常値は取り除く必要なく、普通に処理してくれるが、取り除いたほうが精度が改善する可能性があることがわかった
時系列データの周期性について
  • Prophetでは、いくつかの周期性の関数を入れることができるようになっていました。
  • 基本的には、フーリエ関数をいくつも重ね合わせた感じのものになっているので、周期性が複数見られるやつに関しては、その分関数を追加してやればよく、例えば、以下のような周期性のものを追加してやればいい。

- 週単位
- 月単位
- 年単位

休日・イベント効果について
  • Prophetが少しわかりにくいのだが、holidayとなっているところに、天気や祝日、イベントなどの効果を全部丸ごと入れることができる。ソースコードをいじって、改めてパラメーターなどを式に追加することも検討したが、結局は同じ構造になるので、普通にここに追加すればいい。

- add_regressor ってやつで、特殊な関数を入れ込むことができるので、モデルを作る際には、検討してみるのはアリかも。binaryである必要性はないようなので、気温などの効果もみることができるっぽい。

  • 一応、イベントの種類ごとに、事前分布とかのスケールもつけることができるので、休日なども、「普通の休日」と「3連休以上の大型連休の場合」みたいな、それごとに効果の影響を変えたい場合は、そうすることもできる。めんどくさいけど。
  • デフォルトでついている、build-inな国別の休日の処理やんちゃな設定でビビる。日本はないけど。
  • 連休効果などは、lower_windowとかupper_windowとかで処理が出来そうな予感。
予測の不確かさの幅
  • 最終的には、正規分布を仮定してのモデルになっているので、予測結果の不確かさもその分布でのものになる。
  • 異常検知を手っ取り早くやるなら、この値を使えば良いのかな。
異常検知について
  • Prophet上で、ChangePointの検出も行なっているが、あくまで多めに変化点をバラマキ、それに対してラプラス分布でL1のペナルティのようなものをおいた事前分布を表現し、検知しているだけである。よって、変化点を別モデルを使って検知しに行って、それをモデルに組み込むのはある程度理にかなっている可能性はある。

- デフォルトでは学習データの最初の80%しか使わずに、ChangePointを検知しないので、そこに注意する。サンプル数が少ない場合にはもっと少なくしてもいいかもしれない。
- これはすなわちトレンドの変化点という文脈で吸収しているだけなので、外れ値処理とは少し文脈が違う。検知を事前に行なって予測を行うのはアリかも。

  • 異常データの検知については、ラプラス分布(平均0, 分散τ)の分布をもつdeltaがthresholdを以上であった場合に検知するようになっている。これについては、正規分布の外れ値の検知方法となんら変わりない感じである。

- changepoint_prior_scaleを変えれば、事実上τを変更することになる

評価関数について
  • Prophetで提唱されている方法が良さそうだった。順序関係を操作できないので、厳密にはCrossValidationとは違うけど、そういうやり方をしてやっていました。他には、評価関数に関しては、以下の資料が参考になると論文にあった。

- [25 years of time series forecasting’, International Journal of Forecasting](https://robjhyndman.com/papers/ijf25.pdf)

終わりに

メモをそのまま晒しているだけなので、あんまり文脈とかわからない感じになってしまった(反省)。

それでは。

参考

概要説明系

取っ掛かりとして、以下の資料は参考になりました。

これよりももう少し深いところが知りたい場合には、以下のブログが参考になりました。

最後の細かいところをやっぱり知るには、ぶっちゃけ論文読んでソースコード読むしかないですが、論文もソースコードもすごく難しい訳ではないので、読んだ方がいいと思います。

Kaggle

Kaggleのカーネル上で実際にやってみた例を書いてあるもの。

時系列予測ライブラリ関係
外れ値検知・変化点検知

【Python】時系列解析:日本の休日を判定するライブラリ「jpholiday」を使ってみた

こんにちは。

日本の時系列データを今仕事で扱っている関係もあり、日本の休日を判定する必要がありまして、判定するPythonのライブラリを調べて使って見ました。

結構いろんなライブラリがあって、どれを使おうかなと迷ってしまうのですが、「jpholiday」というライブラリが便利で簡単そうだったので、使ってみることにしました。

jpholiday

本家のサイトを引用します。

このライブラリで出来ること

サクッと見た所、以下のことができるようです(これはREADMEに書いてあることですが)。

  • 祝日の名前の取得
  • 祝日かどうかの判定
  • 指定年の祝日の取得
  • 指定月の祝日を取得
  • 指定範囲の祝日を取得

最近追加された山の日も入っているので、とてもいい感じですね。振替の休日も入っているみたいなので、もしそこを見たい場合もいけます。

実装もみる感じそんなに難しくない感じでやられているので、見てみるのはありだと思います。

使い方

めちゃめちゃ簡単で、README.mdを見ればいけます。というのもアレなので、一部だけ紹介します。

そのほかの使い方は、本家のサイトを見ていただければと思います。

それでは。

Julia入門 - Tutorialを学びながら作ったのでまとめていく【随時更新】

こんにちは。

今年の目標の一つに「Juliaを使えるようになって、データサイエンスをJuliaでする」というものがあるので、いろんなサイトとか見て自分で基本を勉強しながらTutorialを作ってみることにしました。

これはまとめページです。

ちなみに、Julia初心者が勉強しながらやっているので、間違いとかあればコメントとかで教えてもらえると泣いて喜びます…。

参考サイトまとめ

st-hakky.hatenablog.com

JuliaでData Scienceしてみる

Juliaを用いて、普段PythonとかでやっているData分析をやってみようかなと思います。どんなネタがいいかなぁと考え中。



随時更新していきます。

それでは。

*1:Pythonとの違いはぶっちゃけ結構内容薄いので(汗)、Python知らなくてもいけます笑

Julia入門 - 入門者がまず読むべき参考サイトや本のまとめ【随時更新】

こんにちは。

Pythonはある程度かけるが、Juliaに関しては全くの初心者である私がこれからJuliaでデータサイエンスをしたり、Deep Learningをしたりしようと思っているので、その学んだ過程とかで参考になった資料とかをまとめておこうかと思います*1

Juliaは、まだPythonとかに比べてまだコミュニティのレベルとして大きくないせいもあってか、日本語の情報とかはやっぱり少なめですが、ことデータサイエンスの文脈で言えば、Pythonよりも実行速度が早く(C並)、動的プログラミング言語という性質が自分的にはかなり気になっているので、今後に期待って感じで、勉強していこうと思います。

自分も勉強になったこととかは、このブログで発信していこうかなーと思っています。

Video

The Julia Language | YouTube Channel

あまり詳しいことはわかってないんですが、おそらくJuliaのコミュニティが運営しているYoutube Channelがあります。以下がそのChannelです。

www.youtube.com

このChannelでは、Juliaに関する情報(JuliaConの様子とかTutorialとか)を流してくれているので、参考になります。

Introduction to Julia

あんまり詳しくはしらないですが、Juliaのコミュニティが「JuliaBox」の中に用意されているTutorialのJupyter Notebookに沿ってチュートリアルをしてくれています。その動画が以下です。

www.youtube.com

Pythonとかをある程度やっていた人は、この動画をみるだけでJuliaの雰囲気はつかめるようになるので、まずはこの動画を見るのがおすすめかなって感じです。

Books

Juliaデータサイエンス―Juliaを使って自分でゼロから作るデータサイエンス世界の探索

私はまだ読んでないですが、以下の本が販売されています。ある程度Juliaの基本をさらってそこそこの機械学習とかをできるようになったら読んでみようかなと。

書評は以下に書かれていました。


また勉強しながら情報を追加していこうと思います。それでは。

*1:そのため、まだ読んだこととか目を通しきれてない資料もここに乗ってます

【Python】ピアソンの相関係数をいろいろな方法で計算する方法まとめ(SciPy / Numpy / Pandas)

こんにちは。

今日は題名の通り。

色んな所で目にするピアソンの相関係数ですが、毎回実装の方法調べちゃうので、ピアソンの相関係数をいろんな方法で計算する方法をまとめておきたいと思います。

Pearsonの(積率)相関係数とは

ピアソンの相関係数は、英語ではPearson's correlation coefficientと呼びます。相関係数にもいろいろな種類があって、ピアソンの相関係数もそのうちの一つです。

定義

以下の式で表され、-1~1の値の間で値が変化します。

$$
\frac{ \sum_{i=1}^{n} ( x_{i} - \overline{x} ) ( y_{i} - \overline{y}) }{ \sqrt{ \sum_{i=1}^{n} ( x_{i} - \overline{x})^2 } \sqrt{ \sum_{i=1}^{n} ( y_{i} - \overline{y})^2 } }
$$

使い所

変数間の直線関係の強度を知りたいときにこの相関係数を使用します。定義の式を見ると、 $x$ からその平均 $\overline{x}$ を引いたものと、 $y$ からその平均
$\overline{y}$ を引いたものの $cos$ を表していることになります。よって、「データにおいて、$x$と$y$のばらつきぐあいが完全に一致していたら、相関係数が1になる」ことがわかります。

また、ピアソンの相関係数では、変数が正規分布に従っていることを仮定しています。なので、正規分布に従っていると仮定できるデータがあったとして、そのデータの直線関係の強度を知りたい時、これは使えます。

相関係数の値と相関の強さの関係

以下のように考えるのが目安らしいです。絶対値としているので、負の相関と正の相関の両方を一度に表していますが、相関の強さという意味では変わらないので、略します。

相関係数の絶対値 強さ
0.0~0.2 相関無し
0.2~0.4 やや相関有り
0.4~0.7 強い相関がある
0.7~1.0 非常に強い相関がある

Pythonによる実装

とまぁこんな感じで定義されるピアソンの相関係数ですが、定義自体は難しくないのです。

計算方法がいくつかPythonでは用意されているので、その計算方法を思いつくものをまとめておこうと思います。

scratch

スクラッチといっても、numpy使っちゃってますが、以下のようにかけます。SciPyの方でもソースコードを見たら同じような実装をしていました。

import numpy as np

def pearson_corr(x, y):
    x_diff = x - np.mean(x)
    y_diff = y - np.mean(y)
    return np.dot(x_diff, y_diff) / (np.sqrt(sum(x_diff ** 2)) * np.sqrt(sum(y_diff ** 2)))

SciPy : scipy.spatial.distance

scipyを使った例も書いておきます。

from scipy.spatial.distance import correlation
1 - correlation(x, y)

SciPyを使った場合の注意点として、この関数では以下の式をもとに計算されているので、1から引いてあげないと相関係数が計算できないことです。

$$
1 - \frac{ \sum_{i=1}^{n} ( x_{i} - \overline{x} ) ( y_{i} - \overline{y}) }{ \sqrt{ \sum_{i=1}^{n} ( x_{i} - \overline{x})^2 } \sqrt{ \sum_{i=1}^{n} ( y_{i} - \overline{y})^2 } }
$$

そこさえ注意すれば、特に難しくないかなと思います。

SciPy : scipy.stats.pearsonr

これは、ピアソンの相関係数だけではなく、帰無仮説(無相関)と設定した場合のp値も計算してくれるっぽいです。すばらしいですね。

from scipy.stats import pearsonr
pearsonr(x, y)

例えば上のコードを実行すると、次のような感じのtupleでデータが帰ってきます。

# (ピアソンの相関係数, p値)
(1.0, 0.0)

Numpy : numpy.corrcoef

先程までのscratchで書いたものやSciPyはいずれも1d-arrayを想定していたわけですが、ここでは、2次元配列における行同士の相関も計算することができます。

まず、これまで通り1次元の配列 $x$ と $y$ を入れて計算すると以下のようになります。

import numpy as np
np.corrcoef(x, y, rowvar=True)

ここでパラメーターとして指定している rowvarは、デフォルトでTrueなので、ここでは特に意味は無いです。が、行を変数として扱うのがデフォルトなので、それを反転したいときはここをFalseにするとできます。

この時、出力は、

# 以下のように、変数同士でそれぞれ相関係数を出している。
# array([[ xx    , xy ],
#            [ yx   , yy ]])
array([[ 1.        ,  0.77658027],
       [ 0.77658027,  1.        ]])

みたいな感じで出てきます。なので、通常の相関係数が欲しい場合は、行列の要素として、[0, 1]の部分を取って来ればいいです([1, 0]は事実上同じなので)。

2次元配列でその行(または列)同士の相関を見たい場合は、入力として $y$ を削ってあげればいいだけです。

Pandas : corrメソッド

PandasのDataFrameに、corrのメソッドが存在して、以下のように計算できます。

import pandas as pd
data = pd.DataFrame({"x":[1,2,3,4,5],
                     "y":[-1, -3, -5, 0, 8]})
data.corr()

ちなみに、このメソッドは他にもいろんな相関係数(スピアマンなど)を計算できて、methodパラメーターで指定することで計算できますが、デフォルトではピアソンの相関係数になっているので、特に気にすることはありません。

■参考


こんなくらいでしょうか。他にもあったり、ミスってたら教えてください。

それでは。

【Python】可視化ライブラリであるBokehのインストール

こんにちは。

最近、Bokehを使っているんですが、そのインストールについて備忘録かねてメモしておきます。

環境

今回試している環境は、以下の通りです。

$ cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)

Anacondaのインストール

この手のデータ分析とか可視化ライブラリを使う時は、依存関係を自分で克服していくのは非常に面倒ですし、そもそもその労力よりやりたいことやろうよって感じなので、anacondaをいれましょう(強め)。

condaでインストール

Bokehはcondaでインストールできます。

$ conda install bokeh

Bokehの開発環境を整えたいとか、pipでいれたいとか

普通にpipでも入れることができます。

ただし、その場合は依存関係を克服する必要があるので、こちらのページより、入れる必要があるものをみて、それらが入っていることを確認してから、以下のコマンドでインストールしてください。

$ pip install bokeh

Bokehに魅了された人は、開発環境もこちらのページを参考に作ることができます。

インストールできているかの確認

ipythonを起動して、以下のコマンドをいれます。

$ ipython
>>> import bokeh
>>> bokeh.__version__

これで動いていれば、多分大丈夫だと思います。

自然言語処理する時に計算するJaccard係数をPythonで計算する方法まとめ

こんにちは。

Jaccard係数についてPythonで実装する時にありそうなパターンをまとめてみました。また、自然言語処理の分野からJaccard係数についても調べました。

Jaccard係数

まず、Jaccard係数について説明して、その後実装の部分に入っていきます。

読み方

ジャッカード係数と呼びます。

Jaccard係数の定義

Jaccard係数を計算するには、ドキュメントをトークンのセットとして扱います。数式は次のとおりです。

$$
J (A, B) = \frac{|A \cap B|}{|A \cup B|}
$$

分母に和集合、分子に積集合の大きさをそれぞれ入れて計算します。これにより、要素 $A$ と $B$ の集合中にどの程度同じ要素があるかがわかり、この同じ要素が多いほど、値は1に近くなります。

Jaccard距離の定義

Jaccard係数に対してJaccard距離ということになると、似ているほど0に近くなって欲しいので、1-類似度ということになる。

$$
1 - J( A, B ) = \frac { \mid A \cup B \mid - \mid A \cap B \mid } { \mid A \cup B \mid }
$$

Jaccard係数の使い所

自然言語処理とかでは、文字列の距離や文章の距離を測るために用いられます。先にも述べたとおり、単語の文字一つ一つや、文章の単語一つ一つを集合の要素とみなし(もちろん重複は削除した上で)、2つの集合における積集合が和集合においてどのくらいの割合を示すかを見ることで、単語などの類似度を見ようというのに使われます。

自然言語処理のこういった類似度の計算方法は様々ありますが、Jaccard係数は最も簡単なのではないかと。ただ、文書などの順番の依存関係はJaccard係数だと破棄されるので、注意が必要です。

以下の資料がわかりやすかったです。

www.slideshare.net

Pythonでの実装

scratch

標準ライブラリ以外を使わずにで書くと、以下のようになります。x, yはリストを想定しています。

def jaccard_similarity(x, y):
    intersection = len(set.intersection(*[set(x), set(y)]))
    union = len(set.union(*[set(x), set(y)]))
    return intersection / float(union)

scikit-learn

一応ありますが、これはどうもベクトルのサイズが同じものでなければ比較ができないらしいので、自然言語処理などで使う際には微妙だと思います。

from sklearn.metrics import jaccard_similarity_score
jaccard_similarity_score(x, y)

nltk

自然言語処理の処理を行うときに何かとお世話になるnltkでは、以下のように処理を書くことができます。

また、入力はset型なのと、距離なので値が大きいほうが似ていないとなります。

from nltk.metrics import jaccard_distance
jaccard_distance(x, y)

データ分析とか学習回したりするときのPythonのログ出力について

こんにちは。

もう少し勉強していきたいなと思うものの、こればっかり一生懸命になっているとあんまりコードを書く手が進まなくなるので、ぼちぼち勉強して行こうと思っているのが、ログ出力(笑)

分析とかしていると、途中で学習が止まっていたり、思っていたのと違う挙動を実はしていたなんていうことがあって、それを回避するためにログとかも出力したいなぁと思うわけです。

○モデルの学習のログはライブラリに任せる

モデルの学習のログは、Tensorflowとかだと標準でTensorboardなんていう素晴らしい機能が使えるようになっていますし、学習の進捗とかも普通に標準で出力できるようにサポートしているものが多いと思います。


それはそういうライブラリに任せておけばいいとおもっていて、ここでは自分でチェックしたい時にどうするかみたいなのを書きます。

○とりあえずこれコピーしておけばいいんじゃね的なコード

ライブラリなどがおっきくなってきたらこうも行かないと思いますが、自分でデータ分析なコードを書くんだったらこれでいいんじゃねと思っています。

以下で、実行した時間とかメッセージとかが表示されます。使う時は、logger.debug('log message')みたいな感じで使えます。

from logging import getLogger, StreamHandler, DEBUG, Formatter, FileHandler

logger = getLogger(__name__)
handler = StreamHandler()

logger.setLevel(DEBUG)
handler.setLevel(DEBUG)
formatter = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

fh = FileHandler(filename='log.txt')
fh.setLevel(DEBUG)
fh.setFormatter(formatter)
logger.addHandler(fh)

以上。

【Python】数量データの正規化 ( 標準化 ) について

こんにちは。

今回はデータの正規化についてです。

いろんな文脈で様々な意味で使われている「正規化」っていう言葉ですが、今回は統計や機械学習で扱う数量のデータに対して行うことに絞り、まとめていきたいと思います。

Introduction

データの正規化とは

こちらの記事を読んでいたところ、Wikipediaを引用されていたので、Wikipediaの正規化のページも合わせてみることにしました。

すると、正規化とは

データ等々を一定のルール(規則)に基づいて変形し、利用しやすくすること。別の言い方をするならば、正規形でないものを正規形(比較・演算などの操作のために望ましい性質を持った一定の形)に変形することをいう。

だそうです。いちばん有名なのは後でも紹介するz-scoreだと思いますが、それでイメージしちゃえばわかりやすいかなと。文章の正規化とかもありますね。

つまり、「データを一定の方法で変形し、例えば身長と体重みたいな次元が違うものに対しても、なんとかして同じような単位で取り扱えるようにして、計算や比較しやすくしよう」、というのが正規化の狙いと言えます。

データの正規化手法

ここからは様々なデータの正規化手法についてまとめていきたいと思います。

まとめる際には、

  • 目的
  • 条件
  • 定義
  • 実装
  • 所感

の順番で紹介していきたいと思います。

z-score normalization (標準化)

標準化と言い換えられることも多い、z-scoreです。

これは、元データを平均0、標準偏差が1のものに変換する正規化法のことをさします。

■目的
  • 元データを平均0、標準偏差が1のものに変換する正規化法
  • 外れ値のあるデータに対して有効
  • 最大値・最小値に上限、下限がない場合は、z-scoreを使うとよい
■条件
  • データの分布形状がガウス分布になっていること
■定義

z-scoreの定義は以下の通り。

$$
x_{z-score}^{i} = \frac{x^i - \mu}{\sigma}
$$

$\mu$ と $\sigma$ はそれぞれ平均と標準偏差になります。

■実装

これは、Numpy / Scipy / Scikit-learnの3つのパッケージで実装されています。

ぶっちゃけそんなにたいしたことをしていないので、numpyの配列を以下の関数にぶちこめば一応計算はできます。

def zscore(x):
    xmean = x.mean()
    xstd  = np.std(x)

    zscore = (x-xmean)/xstd
    return zscore
■所感

正規分布に従っているデータは結構多いので、これが一番使われている印象だし、普通に使うことが多いです。何でもかんでもぶち込むのはあれだけど…。

Min-Max normalization

■目的
  • 最小値を0、最大値を1とする正規化
■条件
  • 最大値と最小値が予め決まっている様な場合には有効な手法
  • データとして外れ値が存在していないこと(これがあると、とんでもない最大値や最小値にひっぱられてしまうため、うまく正規化できない)
  • データの分布が一様分布であること
■定義

$$
x_{min-max}^{i} = \frac{ x^i - min }{ max - min }
$$

■実装

これも実装はめちゃめちゃ簡単で、以下のような感じで書けます。

def min_max_normalization(x):
    x_min = x.min()
    x_max = x.max()
    x_norm = (x - x_min) / ( x_max - x_min)
    return x_norm
■所感

もともと母集団レベルで最大値と最小値の範囲が決まっているときなどはmin-maxを扱う方が計算しやすいです。ただ、データが一様に分布していないと、結構この正規化だとずれが出てくるので、簡単だけど使いどころが難しいなぁと。

参考

z-scoreによる正規化とmin-max normalizationの違いについて

これについては以下の記事で説明されています。基本的には、上であげたとおり、データに仮定を置く分布形状が違うという点が異なっています。

正規化を行う際には、解析者が正規化を行う前に、各次元の特徴量がどのような分布形状になっているかを確認し、その上で仮定をおいて使うべきです。

正規化による効果

正規化を行ったことによる効果について、ロジスティック回帰を用いて検証している例がありました。

この例は、もうちょっと次元毎に分布とかを変えたら結果が変わるのかなと思いましたがどうなんでしょうか…そのうちやるかもしれません…。

Numpy / Scipy / Scikit-learnによる実装

別に自分で関数を作っても問題ないレベルの内容ですが、Numpyなどで実装されています。以下でそれぞれの内容についてみることができます。

BitbucketでJupyter Notebookがレンダリングされるようになったらしいので、やってみた

こんにちは。

今一緒にKaggleをやっているメンバーから、slackでレンダリングのサポートがされていることを聞いたので、やってみました(10/25には既に公開されていたのに知らなかったという笑)。

Githubでは既にあるのに今までなかった…

Bitbucketって便利なんですよね。普通にプライベートレポジトリ作れますし。

でも、データサイエンスというか、Python使う人はJupyter Notebookを使うわけです(断定)。

Githubの場合、普通にrepositoryに上がっているJupyter Notebookをブラウザ上で開くと、普通にレンダリングされるんです。

つまり、普通に見えていたのです。こんな感じで。

f:id:St_Hakky:20171211160408p:plain

で、Bitbucketではどうだったかというと、json形式になっていたんです。

f:id:St_Hakky:20171211163248p:plain

これがですね…Pythonを使ってデータサイエンスするユーザーが集まって、プライベートrepository上で無料で使おうとすると、「えっ、Bitbucketか…あれJupyter Notebook外から見れないんですよね…」ってなって、ちょっとモヤモヤする空気になっちゃうんですよね…。

◯Jupyter NotebookがBitbucketでレンダリングできる…だと…?

ですが、出来るようになったんです!

f:id:St_Hakky:20171211161418p:plain

詳細はこちらのissueを。

ちゃんとresolveになっているという笑。

ってことでやってみました。これで、Bitbucketでなんかやる時のモヤモヤが減るかなと思います笑。

◯設定の仕方

今のところ、チーム単位・アカウント単位でAdd onを追加して、Notebookファイルを開く時に、「Ipython Notebook」を設定する必要があるみたいです。

実際にやってみました。手順は以下のとおりです。

■Add onを追加

まず、個人ページに移動し、①「Settings > Find integrations」に移ります。その後、②「Bitbucket Notebook Viewer」を見つけたら、それを「Add」します。

f:id:St_Hakky:20171211162259p:plain

これで準備完了です。

■個人のrepository or チームのrepositoryに移動

移動したら、notebookファイルを見ます。えっ、「jsonのままやん」っておもってもご安心を。下の図にある通り、「Default File Viewer」っていうのが増えていると思います。これを、③クリックします。

f:id:St_Hakky:20171211162646p:plain

すると、プルダウンメニューで④「ipython Notebook」っていうのがあると思うので、これを選びます。

f:id:St_Hakky:20171211162635p:plain

そうすると、以下のように表示されます。

f:id:St_Hakky:20171211161418p:plain

おぉーー笑(感動)

Githubと違って無料でプライベートrepository作り放題なので、便利なのは事実なのですが、今までJupyterがブラウザからみれないのは不便だなぁと思っていたのでよかったです!

それでは。

フォンミーゼス・フィッシャー分布 ( von Mises-Fisher distribution)とは何なのかをPythonを使って確かめる(最尤推定もしてみた)

こんにちは。

今日は「フォンミーゼス・フィッシャー分布 ( von Mises-Fisher distribution)」について調べたのでそのことについてまとめます。PRMLの2章にも出てくる分布です(2章はこの前勉強会で話したんですがしんどかったです)。

◯フォンミーゼス・フィッシャー分布(Von Mises–Fisher distribution)とは

この確率分布が出てくると必ずみかけるのがこの図です(笑)。

https://upload.wikimedia.org/wikipedia/ja/thumb/a/ab/VonMises_3D.png/300px-VonMises_3D.png

フォンミーゼス・フィッシャー分布は、簡単に言うと「方向データに対する確率分布」です。方向データ、すなわち球面上における確率分布と考えれば、このような図がでてくるのもなるほどとなりますし、平均の方向ベクトルと同じ方向のベクトルであれば、大きな値になるのかなぁとかっていうのも想像できます。

といっても、まったくわかりませんよね笑(私がそうでした)。そこらへん解説していきます。

■方向データ(周期変数)とは

方向データとは、その名の通り「方向にだけ意味があるデータ」です。例えば円周上にのみ存在するデータ集合みたいな感じでしょうか。

ちゃんと定義してやると、$d$ 次元におけるデータ集合、$ \mathbf{D} = \{ \mathbf{x}^{(1)}, ..., \mathbf{x}^{(n)} \} $ なデータが与えられているときに、任意の $n$ について、$ \mathbf{x}^{(n)^{T}} \mathbf{x}^{(n)}$ が成り立つデータ集合全体のことを指します。

まぁつまり、データの大きさには意味を持たず、とにかく円周上や球面上のどこにあるか、すなわち角度にのみ意味を持つデータ集合って感じです。

角度にのみ意味を持つといえば、周期変数(ある一定周期で同じところに戻ってくる変数)です。これは24時間ごととか、2πごととか、そういう周期ごとの値です。

■余談:ガウス分布の周期変数への一般化としてのフォンミーゼス・フィッシャー分布

確率分布としては代表的なガウス分布をこういった方向データや周期変数に対してそのまま適用するみたいなことはできません。そこで、ガウス分布を周期変数へ一般化させた例として、今回説明しているフォンミーゼス・フィッシャー分布があります。

これについては、PRMLの2.3.8に解説がありますので、見たい方はそちらをどうぞ。

やっていることとしては、周期変数をパラメーター $\theta$ を導入して表現し、そのパラメーターを用いて $cos$ や $sin$ を用いて正規分布を書き換えていくということをしてフォンミーゼス・フィッシャー分布を導出し、それに対して最尤推定を行っているだけなので、普通に数式を追えばわからないことはないと思います(めんどくさいですが)。

■フォンミーゼス・フィッシャー分布の定義

さて、定義ですが、いろんな表現方法ができるので、いろんな定義で書かれていますが、以下では一つだけ示します(異常検知と変化検知の本を読んでいるときに勉強しなおしたので、その本の定義を参考にしています)。

フォンミーゼス・フィッシャー分布では、次の2つのパラメーターを持ちます。

  • 平均方向: $\mathbf{\mu}$
  • 集中度: $\kappa$

わかりやすさのため、円周上の方向データをイメージします。平均方向とは、文字通り平均値です。集中度は、分散の逆数である精度ととらえるとわかりやすいです。

集中度の値が小さいと、値が円周上全体に広がっていて、集中度の値が大きいと、平均方向の近くにデータが集中していることになります。これについては後でPythonで試してみた例を示すので、それの方がわかりやすいと思います。

この二つのパラメーターを用いて、次のように定義されます。

$$
M( \mathbf{x} | \mathbf{\mu}, \kappa) = \frac{ \kappa^{M/2 - 1} }{ (2\pi)^{M/2} I_{M/2 - 1} ( \kappa ) } \exp (\kappa \mathbf{ \mu }^T \mathbf{x} )
$$

ここで、 $I_{M/2 - 1} ( \kappa )$ は、以下で定義される第1種ベッセル関数です。

$$
I_{\alpha} ( \kappa ) = \frac{ 2^{ -\alpha } \kappa^{ \alpha }}{ \sqrt{ \pi } \gamma ( \alpha + (1/2)) } \int_0^{\pi} \d \phi \sin^{2 \alpha} \phi e^{\kappa \cos \phi}
$$

■方向データのモデリングをする際にはとりあえずこれを使っておけ

PRMLでも紹介されていますが、フォンミーゼス・フィッシャー分布は球面上の正規分布ともいえる分布です。平均方向とその周りの集中度(ばらつき)を与えたときに、適切にモデリングしてくれる分布であるので、とりあえずこれを使っておくのがよさそうです。

Pythonで分布を確かめてみる

pythonで愚直に書いてみました。以下がコードです。

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.special import iv


def von_mises_fisher_dist(x, mu, k):
    # normalize parameter
    def C(M, k): return k ** (M / 2 - 1) / \
        ((2 * np.pi) ** M / 2 * iv(M / 2. - 1, k))
    return C(x.ndim, k) * np.exp(k * np.dot(mu, x))


def normalize(x, axis=1):
    l2 = np.linalg.norm(x, axis=axis, keepdims=True)
    return x / l2


def __main():
    # parameters
    N = 1000
    M = 10
    k = 0.1

    # set data
    x = np.random.random([N, M])
    x = normalize(x)
    mu = normalize(x.mean(axis=0), axis=0)

    # visualization
    dist = [von_mises_fisher_dist(i, mu, k) for i in x]
    sns.distplot(dist, kde=False)
    plt.title("von Mises-Fisher distribution | k = {}".format(k))
    plt.xlabel("pdf")
    plt.ylabel("Freq")
    plt.show()

if __name__ == "__main__":
    __main()

上のコードの集中度パラメーターである $k$ をいじって、いろんな図を表示させると値のばらつきの変化がわかります。

■ $k=0.1$

f:id:St_Hakky:20171208171201p:plain

■ $k=0.5$

f:id:St_Hakky:20171208171237p:plain

■ $k=10$

f:id:St_Hakky:20171208171311p:plain

■ $k=30$

f:id:St_Hakky:20171208171323p:plain

まぁ、なんとなく実装してみたんですが、以下の関数を使うのがいいと思います。

最尤推定

最尤推定してみます。データ集合 $\mathbf{D}$ から求めるべきパラメーターは、先ほども登場した以下の2つのパラメーターです。

  • 平均方向: $\mathbf{\mu}$
  • 集中度: $\kappa$

しかし、集中度の方は、ベッセル関数の中にも入り込んでいるので、解析的には解けません。なので、ここでは平均方向のものだけ求めてみます。

実装でも出てきていますが、簡単のために分布の係数を $C_M (\kappa)$ とおきます。尤度関数は、以下のように書くことができ、

$$
L (\mathbf{mu}, \kappa | \mathbf{D}) = \ln \prod_{ n=1 }^{N} C_M (\kappa) e^{\kappa \mathbf{\mu}^T \mathbf{x}^{(n)}} = \sum_{n=1}^{N} \{ \ln C_M (\kappa) + \kappa \mathbf{\mu}^T \mathbf{x}^{(n)} \}
$$

$\mathbf{\mu}^T \mathbf{\mu} = 1$ をラグランジュ係数 $\lambda$ を使って取り込んで、その式を $\mathbf{\mu}$ に関して微分して計算し、$\mathbf{\mu}^T \mathbf{\mu} = 1$ と連立させると、以下のような解を得ます。

$$
\hat{ \mathbf{ \mu } } = \frac{ \mathbf{m} }{ \sqrt{ \mathbf{m}^T \mathbf{m} } }
$$

ただし、

$$
\mathbf{ m } = \frac{1}{N} \sum_{n=1}^{N} \mathbf{x}^{(n)}
$$

です。この結果は、普通に標本平均をとってそれを正規化したものと考えられます。いつもの最尤法の「結局それかい」みたいな(妥当な)結果になっています。

こんなもんですかね。それでは。

「異常検知と変化検知~機械学習プロフェッショナルシリーズ~」を読んで勉強会も開いて関連の情報とかも調べたのでまとめておく

こんにちは。

※このエントリは、途中ですが資料の共有とかのため、突貫で体裁だけ整えて掲載しています。異常検知と変化検知の分野は、初心者なので、「こんな手法あるよ」とか「こんな論文面白いよ」とかあれば教えてほしいです。

読んだ本

最近某勉強会でいろんな機械学習の勉強をしているんですが、私のデータ分析への興味が実世界への適用にあるのもあり、以下の本を一人読んで一人で発表することにしました(皆そんな感じで発表しているという笑)。

「異常検知と変化検知~機械学習プロフェッショナルシリーズ~」

サポートページ

サポートページ:本のサポートページ – Dr. Ide's Home Page

目次

目次は以下のような感じです。

  • 第1章 異常検知・変化検知の基本的な考え方
  • 第2章 ホテリングのT2法による異常検知
  • 第3章 単純ベイズ法による異常検知
  • 第4章 近傍法による異常検知
  • 第5章 混合分布モデルによる逐次更新型異常検知
  • 第6章 サポートベクトルデータ記述法による異常検知
  • 第7章 方向データの異常検知
  • 第8章 ガウス過程回帰による異常検知
  • 第9章 部分空間法による変化検知
  • 第10章 疎構造学習による異常検知
  • 第11章 密度比推定による異常検知
  • 第12章 密度比推定による変化検知

余談

まぁ、発表をするのですが、スライドがネットに転がっていて、正直私が改めて作るまでも無いくらいさいつよで(スライド最近作りすぎて嫌になってきたとかじゃないですよ!!)、利用させていただきました汗。

勉強していく過程で調べた内容をここに載せていこうと思います。

異常検知・変化検知とは

概要

以下の投稿が、かなりこの本の内容を数式無しで説明しているため、ほんの概要をざっくり速く理解したい人にはおすすめです。

qiita.com

また、「そもそも異常検知ってなんなんだよ!!!」っていう人とか、「どこで異常検知つかうんだよ!!」っていう人は以下の資料あたりが良いかと思います。

その他読むと良さそうな本


Slides

輪講会をしたんですが、一人で全部のスライドを作っている暇もなかったのと、素晴らしいスライドばかりで改めて私が作る必要もないなって思って、使わせていただいた、異常検知と変化検知のスライド一覧です。以下のスライドはマジで参考になります。

さて、ここから本で学べる内容に追加で自分が調べたこととか、本の内容のメモとかを残していきます。

Chapter 1:異常検知・変化検知の基本的な考え方

この章は、全部の章に通じる内容でした。

ネイマン・ピアソン決定則

正直本の内容とスライドを見ればわかると思います。以下のQiitaの記事も参考になりました。

Chapter 2:ホテリングのT2法による異常検知

多変量正規分布の最尤推定

多変量正規分布の最尤推定はどの本をよんでも出てくるのではないかっていうくらいには何回も出てきますが、それですね。

カイ二乗検定

そもそもカイ二乗検定ってなんやねんだと死ぬので、とりあえず以下のページを見れば雰囲気つかめるかと。

正規分布とカイ二乗検定の関係について

この本では、正規分布とカイ二乗検定の関係について示されています。正直本の内容だけだと私は理解しきれなかったので、以下のサイトも読みました。

式の展開に関しては一つ目のサイトが分かりやすかったです。具体的なイメージを掴むには、2つめのサイトの方が参考になりました。

Chapter 3:単純ベイズ法による異常検知

単純ベイズ法による異常検知について触れられています。

ここについては、単純ベイズ法がわかっていれば、どんな風にそれを異常検知に適用するかがわかります。単純ベイズ法については、分類タスクを解く場合などで、簡単に実装できることもあり、使われることもあります。

単純ベイズ法において問題になる、ゼロ頻度問題ですが、それを回避する方法として、ゲタをはかせる方法と、ディリクレ分布による事前分布の導入が等しくなることも、この本では紹介されています。

実装するにあたっては、以下の記事とかが参考になります。

Chapter 4:近傍法による異常検知

k近傍法とマージン最大化近傍法の2つによる異常検知について触れられています。

線形代数に関するネタが結構出てきますが、それらがわかればこの章は普通に大丈夫かと。また、マージン最大化近傍法の考え方は、2015年に出されたDeep LearningでFace Detectionをする論文でも使われていますし、結構応用が効く考え方だと思うので、勉強しておいて損はないかなと思います。

半正定値行列

半正定値行列の性質を考えれば、固有値の行列を正にする処理の理由とかがわかります。

マージン最大化近傍法

以下の記事が理解の助けになりました。

Chapter 5:混合分布モデルによる逐次更新型異常検知

この章はぶっちゃけEMアルゴリズムをわかっていればオッケーな章と言ってもいいです。

EMアルゴリズム

EMアルゴリズムを勉強する時に参考になるのは以下の資料あたりです。本でがっつり勉強するなら、自分が観測した範囲では、PRMLの9章のEMアルゴリズムの章か、続・わかりやすいパターン認識の6章とかがわかりやすいというか、しっかり勉強出来ると思います。

特にこの本では、イェンセンの不等式を用いているので、その意味ではそれを用いて論理を展開している続・わかりやすいパターン認識の方が参考になると思います。

Chapter 6:サポートベクトルデータ記述法による異常検知

この章も5章と同じように、SVMがわかっていれば何も難しくない章といえます。

最適化の入門くらいは知らねばならん笑

この本の内容を理解するためには、最適化の入門くらいは理解しておく必要があると思います。SVMを理解するためにって感じですが笑。

SVM

PRMLはここでも参考になります。

Chapter 7:方向データの異常検知

フォンミーゼスフィッシャー分布(Von Mises–Fisher distribution)がわからないと死ぬ章でした(笑)。ぼんやりとしか知らなかったので、今一度調べなおしてみながら、読み進めました。

フォンミーゼスフィッシャー分布(Von Mises–Fisher distribution)

なんか書いてたら思ったよりも長くなったので、以下でまとめました。

st-hakky.hatenablog.com

上のエントリでは、集中度の最尤推定は結局してませんが、異常検知においてはそれは問題にならないので、今回は無視しました。

このあたりについては以下の記事も参考になりました。

カイ二乗分布への近似

今回の方向データの異常検知では、フォンミーゼスフィッシャー分布から、ラベルなしの場合の分布を少し式を整えて出すと、以下のようになります。

$$
a(\mathbf{x}) = 1 - \mathbf{ \mu^{T} x^{'}}
$$

となります。これはパっと見なんでやねんって思うんですが、 $\mathbf{ \mu^{T} x^{'}}$ の部分が1になることから、結局この内積が $\cos \theta$ になることを利用して、本気を出すと、カイ二乗分布にうまく近似できるように式展開をもっていくことができるからです(詳しくは本を参考に)。結構むちゃありそうなんですが、データ数 $N$ が多く、$\kappa$ も大きいと仮定をおけば、フォンミーゼスフィッシャー分布は展開できます。

ということで、以下のようになります。

$$
1 - \mathbf{ \mu^{T} x^{'}} ~ \chi^{2} (M - 1, \frac{1}{2 \kappa})
$$

ここで、カイ二乗分布に近似できたんですが、フォンミーゼスフィッシャー分布の最尤推定の時にガン無視していた $\kappa$ 係数が出てきてしまっています。

推定する必要があるんですが、上の式の左辺がわかっていることから、積率法により、逆にカイ二乗分布を左辺にあてはめにいくことでパラメーターを求めます(詳しくは本を参照)。

この章の流れはこんな感じでした(自分がフォンミーゼスフィッシャー分布になれてなかったのもあり、章の流れを見失いそうになったのでまとめておきました汗)。

Chapter 8:ガウス過程回帰による異常検知

[随時更新]

Chapter 9:部分空間法による変化検知

[随時更新]

Chapter 10:疎構造学習による異常検知

[随時更新]

Chapter 11:密度比推定による異常検知

[随時更新]

Chapter 12:密度比推定による変化検知

[随時更新]

Jubatus

異常検知をJubatusでするという記事を見かけたので、私もやってみようと思います。

環境構築

環境構築は、こちらのQuickstartのページからUbuntuやDockerでぶち込む方法などが書かれています。私はWindowsなので、Dockerでやります。

■Dockerで環境構築

Dockerを入れていない人は、Dockerを入れていただき、起動します。起動したら以下のコマンドを入力します。

docker pull jubatus/jubatus
docker run --expose 9199 jubatus/jubatus jubaclassifier -f /opt/jubatus/share/jubatus/example/config/classifier/pa.json
■Install Jubatus Client Libraries

クライアント用の方もいれないといけないです。色々対応している言語はあるようですが、私はPythonを使います。

sudo pip install jubatus

python3をつかう人は、pipをpip3にしてねという感じ。Dockerをバインドするやつ。

自分はDockerで試そうかなと思ったんですが、なんかうまく行かなかったので、また時間があればやります笑。

Deep Learningを用いた異常検知

Deep Learningでやる異常検知も提案されています。

Anomaly Detection with Robust Deep Autoencoders

Robust PCAの中のPCAをAutoencoderに変更したという論文。KDD2017に通っていて、読んでいくとなるほどとなると同時にRobust PCAについて勉強しないとなってなりました笑(んーでもあんまりDeep要素はいらないかもってなったので、余計にRobust PCAが気になったっていう感じかも笑)。以下がスライド。

他にも論文とか実装とかも全部公開されていて、以下の資料が役に立つ。

そのほか勉強したい手法

まだ読めていないけど、ブログ記事とか読んでいて面白そうだなとか、これ勉強しておきたいなっておもったものを下にあげておきます。今後勉強したら随時追加します。

kerasでmultiple (複数の) 入力 / 出力 / 損失関数を扱う時のTipsをまとめる

こんにちは。

〇この記事のモチベーション

Deep Learningで自分でモデルとかを作ろうとすると、複数の入力や出力、そして損失関数を取扱たくなる時期が必ず来ると思います。

最近では、GoogleNetとかは中間層の途中で出力を出していたりするので、そういうのでも普通に遭遇します。

というわけで私も例に漏れず遭遇しました笑。

今回はkerasで複数の入力や出力、そして損失関数を取り扱うときにどうすればいいかについて実践したのでまとめておきます。

〇「複数の入力」を与えたい場合

これは簡単です。普段Modelのインスタンスを作る際に、inputsとoutputsを指定すると思いますが、その際に複数ある場合はリスト形式で渡せばいいだけです。

input_layer1 = Input(shape=(32,))
input_layer2 = Input(shape=(64,))

# ...(モデルの詳細を書く)...

model = Model(inputs=[input_layer1, input_layer2],
                         outputs=output_layer)

〇「複数の出力」を与えたい場合

このパターンを行う場合、損失関数をどう割り当てるかで場合がわかれますので、それについて書きます。

■「複数の出力」に対して、「そのそれぞれに同一の損失関数」を与えたい場合

これは簡単で、複数の入力の場合と同様に、以下のように設定するだけです。

model = Model(inputs=input_layer,
                        outputs=[output_layer1, output_layer2])
model.compile(optimizer='sgd',
                        loss='categorical_crossentropy',
                        metrics=['accuracy'])
■「複数の出力」に対して、「そのそれぞれに別の損失関数」を与えたい場合

さて、このパターンが結構複雑ってこともないんですが、色々やろうとした時につまづいたポイントです(特にオリジナルな損失関数とかを使おうとした時に自分ははまりました汗)

このパターンであるのは、以下のようなシチュエーションです。

  • 複数の出力で且つそのそれぞれに対して、別の損失関数を割り当てたい場合
  • それぞれの損失関数同士の比重、つまりどれくらい重要視するかを変えたい場合

論文にあるようなものとしては、マルチタスク学習とかは上のパターンに遭遇しやすいかなと思います。この実装をどうすればいいかですが、こちらのソースコード を見るか(514行目くらいから)、ドキュメントを見ると、わかると思います。

model = Model(inputs=input_layer,
                         outputs=[output_layer1, output_layer2])
model.compile(optimizer='sgd',
                        loss={'categorical_crossentropy': 'output_layer1', 'mse': 'output_layer2'},
                        loss_weights={'output_layer1': 0.1, 'output_layer2':0.7},
                        metrics=['accuracy'])

kerasではlossに値で渡した場合、辞書で渡した場合、そしてリストで渡した場合、のそれぞれについて、別のこととしてサポートしてくれているみたいですね。

このことをまとめると以下の様になると思います。

  • 値:一つのloss関数のみが適用される
  • リスト:複数のloss関数を、複数の出力のそれぞれに対して適用する
  • 辞書:ユーザーが辞書式で指定した、出力層の名前と対応するloss関数を出力層に対して適用する

ちなみに、'output_layer1'とかはlayerの名前です。Denseとかを使って、層を定義するときに name引数に対して値を指定すると層の名前を指定できると思いますが、その名前です。これを指定してなかったり、指定したけど違う名前にしていたとかだと、当たり前ですが、実行できないので注意が必要です。

こんなもんですかね。それでは。