tag:blogger.com,1999:blog-41032422869806199512024-03-22T02:38:29.011+09:00秩序と情報とブロッコリー意思決定のためのデータ分析amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.comBlogger37125tag:blogger.com,1999:blog-4103242286980619951.post-38104853210343280202023-05-04T10:41:00.001+09:002023-05-04T10:44:21.271+09:00アブダクション<p><a href="https://amzn.to/3Nxwmlb" target="_blank">アブダクション~仮説と発見の論理(米盛裕二)</a>を読んだので、内容を整理する。</p><p></p><ul style="text-align: left;"><li>アブダクションとは論理学者のチャールズ・パースが提唱しているもの。</li><li>彼によると推論は①演繹、②帰納、③アブダクションの3種類に分類される。それぞれの推論の特色は以下のとおり。</li><ul><li>演繹</li><ul><li>推論の内容を考慮に入れずに推論の形式(前提と結論の間に成り立つ論理的形式)のみによって真なる前提から必然的に真なる結論が導かれる。</li></ul><li>帰納</li><ul><li>経験にもとづく蓋然的推論。限られた経験に基づいて一般的言明を行う推論。</li></ul><li>アブダクション</li><ul><li>仮説的推論。仮説を導くための推論。</li></ul></ul><li>分析的推論と拡張的推論という分類</li><ul><li>分析的推論</li><ul><li>演繹推論はこれにあたる。</li><li>前提と結論の含意関係の分析のみに関わり、外的な経験的事実の世界には関わらない。そのため経験的事実による反証にさらされない</li><li>前提の中に暗々裏に含まれている情報を解明し、それを結論に明確に述べるだけ。</li></ul><li>拡張的推論</li><ul><li>帰納推論やアブダクションはこれにあたる。</li><li>結論は前提の内容以上のことを主張する。</li><li>帰納推論の場合は「部分」を述べる前提から「全体」へ知識を拡張する。</li><li>アブダクションの場合は、前提(事実)からそれを説明するため仮説へ拡張する。</li></ul></ul><li>帰納とアブダクションの関係</li><ul><li>仮説は帰納を積み重ねるだけでは仮説は生まれない。</li><li>例えばリンゴが落ちるのを何回も観察して一般化しても「万有引力」という仮説は生まれない。</li><li>アブダクションにより仮説を生み、仮説を帰納で推論するという関係。</li></ul><li>アブダクションの推論の形式は以下のように定式化される。</li><ol><li>驚くべき事実Cがある。</li><li>しかしHならば、Cである。</li><li>よってHである。</li></ol><li>アブダクションは、事実Cの観察からそれを説明しうると考えらえる仮説Hを推論するため「遡及推論(retroduction)」とも呼ばれる。</li></ul><p></p><p><br /></p><p><br /></p>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-75131497884902045202023-05-04T09:45:00.000+09:002023-05-04T09:45:58.745+09:00含意(AならばB)の真理値表<p> 論理学の勉強をしていると最初に躓くのが含意(AならばB, A->B))の真理値表。<br />教科書には以下のように書いている。</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEi7wrYoB80Y_NDPMMaVeVyLYtw6qhySdmn8B2_msZn9vRznRS_nurEoWWnQcsQ7ERMVaFvBjBnekdLXrIJEUgGNoLI3g5t4K-DM1ug-jQQFqKqnN710oB9UpilzS6XzmYAlMkSTI-rPb1lzP3aJXCe-EZatsVylTbbtgSF97FdrDgGKHx6biFfzgO3m" style="margin-left: 1em; margin-right: 1em;"></a><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEi7wrYoB80Y_NDPMMaVeVyLYtw6qhySdmn8B2_msZn9vRznRS_nurEoWWnQcsQ7ERMVaFvBjBnekdLXrIJEUgGNoLI3g5t4K-DM1ug-jQQFqKqnN710oB9UpilzS6XzmYAlMkSTI-rPb1lzP3aJXCe-EZatsVylTbbtgSF97FdrDgGKHx6biFfzgO3m" style="margin-left: 1em; margin-right: 1em;"></a><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgXiYC6Scn84AU_UB4lEwzsY8oFj43Ndvy3ZAHl6uS9vHqfts_ptHi9Irzcyw7wO3oIiSZzASIYRWPhRe8RCY7-Sf2RDQ_MqViNnP-OrX718npcvmh3qeZClIdnejUdVN2qw_dQnNZg2f0NHrz0SUXGg8dIg0hNdkNbkdarC79yRnCSZtnb6g9tPviM" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="131" data-original-width="261" height="161" src="https://blogger.googleusercontent.com/img/a/AVvXsEgXiYC6Scn84AU_UB4lEwzsY8oFj43Ndvy3ZAHl6uS9vHqfts_ptHi9Irzcyw7wO3oIiSZzASIYRWPhRe8RCY7-Sf2RDQ_MqViNnP-OrX718npcvmh3qeZClIdnejUdVN2qw_dQnNZg2f0NHrz0SUXGg8dIg0hNdkNbkdarC79yRnCSZtnb6g9tPviM" width="320" /></a></div><br /></div>AがTrueの場合は分かるが、AがFalseの時はなぜA→BがTrueになるのだろう?<p></p><p>答えとしては、A→Bは「Aが成り立つ<u>前提が満たされれば</u>Bが成り立つ(Trueとなる)」ことを示しており、Aが成り立たたないケースのことは何も規定していないことが重要。</p><p>なので、前提が満たされない(つまりAがFalseの場合)は、A→BはBが何であろうが成立する。という考え方。<br /></p><p>なお、A→B は !A || Bと等価であることがよく使われる。</p><p>※なぜ等価なのかは、!A || B の真理値表を自分で書いて確かめてみよう。</p>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-18701773548935065602023-03-26T08:41:00.005+09:002023-03-26T08:41:40.865+09:00PythonでMecabを使う (Unidic辞書編)日本語の自然言語処理には形態素解析が欠かせない。そこでよく使われるのがMecab。辞書として標準のipadicではなくUnidicを使おうとするといくつか落とし穴がある。<div>今回はそんな落とし穴に落ちずにインストールからmecabで品詞解析をするまでの手順を書いておく。<div><ul style="text-align: left;"><li>落とし穴①:Unidicを指定してmecabを動かそうとすると、<span style="font-family: courier;">`no such file or directory: /usr/local/lib/python3.9/site-packages/unidic/dicdir/mecabrc`</span>のエラーが発生。</li><li>落とし穴②:`Mecab.Tagger("-Ochasen")`とするとエラーが発生。</li></ul><div>まずpython3-mecabのインストールする。</div></div><div></div><blockquote><div><span style="font-family: courier;"># pip install mecab-python3</span></div><div><span style="font-family: courier;"># pip install unidic</span></div></blockquote><div></div><div>ただしUnidicはpipだけでは辞書本体がダウンロードされないため下記コマンドで辞書本体をダウンロードする。</div><div></div><blockquote><div><span style="font-family: courier;"># python -m unidic download</span></div></blockquote><p>Mecab本家とは違い<a href="https://github.com/SamuraiT/mecab-python3#using-unsupported-output-modes-like--ochasen" target="_blank">python3-mecabはchasen出力のフォーマットがデフォルトでは用意されていない</a>ため、そのまま`Mecab.Tagger("-Ochasen")` を実行すると「chasenというようなフォーマットは無い」という趣旨のエラーが発生する。そこで、`<span style="font-family: courier;">/usr/local/lib/python3.9/site-packages/unidic/dicdir/dicrc</span>`のファイル末尾にviなどで以下の<span style="color: #cc0000;">`; ChaSen`以下の</span>内容を追記する(<a href="http://taku910.github.io/mecab/format.html" target="_blank">参考</a>)。</p><p>以上。</p><p>参考文献:https://www.teamxeppet.com/python-mecab-unidic-lite_mac/</p>
<div><script src="https://gist.github.com/a-mitani/086d0432b11c5c917bd954d25236ff05.js"></script></div></div>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-58600028959246564342021-10-23T07:29:00.000+09:002021-10-23T07:29:19.449+09:00F1スコアについて(メモ)<p> </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbSkXMSfcNeXKi48IsSxjvkFmZWu5ndLp_vyeQrNm5uIbwtqHPFg5nn-I6IeM_6MfVm2tI9phlNpgCp3YpYItlUK7mulHPki7zF-OJC16vTjLe0DY8plg054OvjXZdJpY0OIM3IVNKyuE/s1920/%25E3%2583%2595%25E3%2582%259A%25E3%2583%25AC%25E3%2582%25BB%25E3%2582%2599%25E3%2583%25B3%25E3%2583%2586%25E3%2583%25BC%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%25B3+15.001.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="311" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbSkXMSfcNeXKi48IsSxjvkFmZWu5ndLp_vyeQrNm5uIbwtqHPFg5nn-I6IeM_6MfVm2tI9phlNpgCp3YpYItlUK7mulHPki7zF-OJC16vTjLe0DY8plg054OvjXZdJpY0OIM3IVNKyuE/w552-h311/%25E3%2583%2595%25E3%2582%259A%25E3%2583%25AC%25E3%2582%25BB%25E3%2582%2599%25E3%2583%25B3%25E3%2583%2586%25E3%2583%25BC%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%25B3+15.001.png" width="552" /></a></div><br /><p></p>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-30146704913758868012021-09-23T08:37:00.004+09:002021-09-23T08:37:56.780+09:00仮説検定に関するメモ<div style="text-align: left;"><a href="https://amzn.to/3ugPZ5v">統計学入門</a>で、仮説検定について再学習したのでメモ。改めて勉強すると曖昧な部分が整理されて良い。</div><div style="text-align: left;"><br /></div><div style="text-align: left;">仮説検定とは母集団について仮定された命題を標本で検証すること。帰無仮説を立てて<span style="color: #cc0000;">その仮説が正しいとした場合に得られた標本が実現する確率の大きさで帰無仮説を採択するか棄却するかを決める</span>。</div><div style="text-align: left;"><br /></div><div style="text-align: left;">例えばコイン投げを考える。20回コインを投げて14回表が出た時このコインに偏りがあるかを検討したい。</div><div style="text-align: left;">この時、帰無仮説として「コインに偏りは無い」という仮説を立てる。もし偏りがない場合、コイン投げの確率分布は二項分布Binary(20, p=0.5)に従うはずである。このとき表が14回以上出る確率を計算すると0.0577程度となる。これは有意水準10%で仮説が棄却される。つまり「コインに偏りは無いとは言えない」という結果となる。</div><div style="text-align: left;"><br /></div><div style="text-align: left;">ちなみに帰無仮説の「帰無」は特に意味がなく単なる仮説と言っても差し障りないとのこと。</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><p><br /></p>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-5857556909931767652021-02-20T09:27:00.003+09:002021-02-20T09:27:32.891+09:00ベイジアンネットワーク①<h3 style="text-align: left;"> ■ はじめに</h3><div>確率的に起きる事象に関して、限られた情報から正しく意思決定するためにはベイジアンネットワークは非常に強力なツールになる。ここでは、ベイジアンネットワークとは何か?pythonで実装するにはどうすれば良いか?を解説したい。また実際のデータを用いてベイジアンネットワークの計算結果から意思決定を行う例も示す。</div><div><br /></div><h3 style="text-align: left;">■ ベイジアンネットワークとは?</h3><div>ベイジアンネットワークは確率モデルの一種で、複数の事象の関連性を有向非巡回グラフ(Diredted Acyclic Graph: DAG)を用いて表現しようとするモデルだ。ここでDAGとは、ノードとそれらを繋ぐ有向エッジから構成され、ループ構造が存在しないグラフ構造のことをいう。</div><div><br /></div><div>下の図のようにベイジアンネットワークでは、DAGの各ノードを確率変数とし、ノード間が有向エッジで繋がれている場合は子の確率変数を親の確率変数の「条件付き確率」で表せると考える。</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj93POfetDqeMy4w7j3CiKAQegPNU6quimAsBnuMbKUrUIqloYgvzWHkOCDXYWC2tseiXk1XyHW8R9gMc4PYmn2az5T82NjDWejYmwrhAyacPv7eJ22fwNuucwArVzHYAOoikJfB6okNZo/s777/bayesian.001.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="777" data-original-width="727" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj93POfetDqeMy4w7j3CiKAQegPNU6quimAsBnuMbKUrUIqloYgvzWHkOCDXYWC2tseiXk1XyHW8R9gMc4PYmn2az5T82NjDWejYmwrhAyacPv7eJ22fwNuucwArVzHYAOoikJfB6okNZo/s320/bayesian.001.png" /></a></div><br /><h3 style="text-align: left;">■ 同時確率と条件付き確率</h3><div>ここで同時確率と条件付き確率について復習しておきたい。</div><div><br /></div><div>複数の事象を考えるときに、それらが同時に起きる確率を「同時確率」という。2つの確率的に起きる事象を確率変数AとBとすると、AとBがそれぞれaとbの値となる場合の確率を\(P(A=a, B=b)\)というように表す。</div><div><br /></div><div>一方で「条件付き確率」とは、「既にある事象が起きたと確定した条件下で」他の事象が起きる確率を示す。確率変数Aがaの値をとった「条件下」でBがbの値をとる確率を示し\(P(B=b|A=a)\)と表す。</div><div><br /></div><div>また、確率の連鎖律(Chain Rule)より下式が成り立つ。</div><div>\[P(A=a, B=b)=P(B=b|A=a)P(A=a)\]</div><div><br /></div><div>※以降、簡略化のため\(P(A=a)\)などは\(P(A)\)のように確率変数の実現値は省略して表記する。</div><div><br /></div><h3 style="text-align: left;">■ベイジアンネットワークでの同時確率</h3><div>上記の連鎖律を用いると上図のネットワークで確率変数\(X_1\)〜\(X_5\)の同時確率は</div><div>\[P(X_1, X_2, X_3, X_4, X_5)=P(X_5| X_3)P(X_4| X_3)P(X_3|X_1, X_2)P(X_1)P(X_2)\]</div><div>となる。</div><div>ここで、</div><div><ul style="text-align: left;"><li>\(P(X_3 | X_1, X_2)\)は、親である\(X_1\)と\(X_2\)がそれぞれ \(X_1=x_1\)、\(X_2=x_2\)と確定した時の\(X_3\)の条件付き確率。</li><li>\(P(X_1)\)、\(P(X_2)\)はそれぞれ、\(X_1=x_1\)、\(X_2=x_2\)の実現値をとる確率。</li><li>\(P(X_5 | X_3)\)や\(P(X_4 | X_3)\)は、親である\(X_3\)が(\(X_3=x_3\)と)確定した時の\(X_4\)、\(X_5\)の条件付き確率。</li></ul><div>を示している。この式を注意深く見るとベイジアンネットワークの同時確率は一般的に各ノードの親ノードに関する条件付き確率の積、つまり</div></div><div>\[P(X_1, ..., X_n)=\prod_{i=1}^n P(X_i| Parents(X_i)) \tag{1}\]</div><div>の形に書けることが容易に想像がつく。ここで\(Parents(X_i)\)は確率変数\(X_i\)の親ノードを表している。</div><div><br /></div><div><h3>■ 具体例</h3></div><div>簡単なベイジアンネットワークの具体例で同時確率を求めることをしていこう。</div><div>ここでは下図のような仮想的なシチュエーションの因果関係の例として考えていく。</div><div>ある家に警報システムが導入されており、家に異常(強盗 or 火事)が発生すると警報サイレンが鳴り、それを聞いた近所の人が警察もしくは消防に連絡することになるという因果関係を示している。</div><div><br /></div><div>それぞれの事象の確率変数は事象が発生(1)するか否(0)かの2値をとる。幸い強盗や火事が発生する可能性は極めて低いが、若干火事の発生確率の方が大きい。また強盗や火事が発生すると高確率でサイレンが鳴るようになっているが、強盗や火事以外の異常でなる可能性もある。またサイレンが鳴るとそれを聞いた近所の人が警察もしくは消防に連絡をする確率が高まる。</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimaP5_cpdC7rIKAU9mAxw8ISyiySdhZKf3_hXAv_nnYZjNuGVOFpzncTTOite8LBUgQPrAXCUGHGovci7DdGnCnfogo793Fjxs48nwqy0-umNEtS4UAGxuc1SMP4VtaaMxwR8UH0_Btc4/s1024/bayes02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1024" data-original-width="768" height="471" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimaP5_cpdC7rIKAU9mAxw8ISyiySdhZKf3_hXAv_nnYZjNuGVOFpzncTTOite8LBUgQPrAXCUGHGovci7DdGnCnfogo793Fjxs48nwqy0-umNEtS4UAGxuc1SMP4VtaaMxwR8UH0_Btc4/w353-h471/bayes02.png" width="353" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div>この時、何も起きない、すなわち\(B=F=S=P=D=0\)となる確率はいくらだろうか?先ほどのベイジアンネットワークの同時確率である(1)式に当てはめ表から実際の数値をとると、<div>\[P(B=0, F=0, S=0, P=0,D=0)\\\\=P(P=0|S=0)(D=0|S=0)P(S=0|B=0, F=0)P(B=0)P(F=0) \\\\=0.99*0.96*0.9*0.99*0.98=0.83\]</div><div><div>と計算ができる。</div><div><br /></div><div>ここまででベイジアンネットワークでの同時確率を求めることまでできた。ベイジアンネットワークの強力なところは、このモデルを用いると、ある事象が発生した場合に、その要因の分析が可能であることである。例えば上の例では警察に通報が行き(P=1)消防に通知が行かない(D=0)という事象が発生したときにその要因が火事である確率、もしくは強盗である確率を求めることができる(要因推定)。</div><div>次回は、要因推定について詳しく見ていきたい。</div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div></div>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com1tag:blogger.com,1999:blog-4103242286980619951.post-52489121732616162612021-02-06T11:25:00.003+09:002021-02-06T11:25:31.745+09:00行列の冪乗と固有値の関係について<p> メモ。</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeoInPS1ekVcGJkINDFiEwzvOmd23XErFVoGN_kBS6NzPHLgkpU8CbtK-yd1E2_3dwFbhhU8k40Z-GsfLADx39O7DTIrN5Hb3gms_oATXFtU9r63JwNjHc6IkkaESaXiAtgUBGCS6lSKQ/s1024/%25E8%25A1%258C%25E5%2588%2597%25E3%2581%25AE%25E5%2586%25AA%25E4%25B9%2597%25E3%2581%25A8%25E5%259B%25BA%25E6%259C%2589%25E5%2580%25A4%25E3%2581%25AE%25E9%2596%25A2%25E4%25BF%2582.001.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1024" data-original-width="768" height="733" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeoInPS1ekVcGJkINDFiEwzvOmd23XErFVoGN_kBS6NzPHLgkpU8CbtK-yd1E2_3dwFbhhU8k40Z-GsfLADx39O7DTIrN5Hb3gms_oATXFtU9r63JwNjHc6IkkaESaXiAtgUBGCS6lSKQ/w550-h733/%25E8%25A1%258C%25E5%2588%2597%25E3%2581%25AE%25E5%2586%25AA%25E4%25B9%2597%25E3%2581%25A8%25E5%259B%25BA%25E6%259C%2589%25E5%2580%25A4%25E3%2581%25AE%25E9%2596%25A2%25E4%25BF%2582.001.png" width="550" /></a></div><br /><p>参考:<a href="http://www.cc.okayama-u.ac.jp/~murai/lec/2019/ecmath/pdf/nB-3.pdf" target="_blank">リンク</a></p><p><br /></p>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-53691245055050201512021-02-02T13:55:00.000+09:002021-03-14T13:55:59.295+09:00ベイズ学習の枠組み②<p> <a href="https://blog.data-hacker.net/2021/03/blog-post.html">前回の投稿</a>では、ベイズ学習は以下の2ステップで行っていくことを述べた。</p><p></p><ol style="text-align: left;"><li>確率モデルの構築:グラフィカルモデルなどを利用しながら、事象の同時確率を定式化する。</li><li>推論:上で定式化した同時確率分布と、その未知のパラメータに対する周辺確率から事後確率を求める</li></ol><div>実際にこのステップに従って、非常にシンプルな例の推論を行ってみたい。これによって実際に同時確率と周辺確率を計算することで、事後確率が推論できることが実感できるとおもう。</div><div><br /></div><div>ここで考える例は以下のとおり。</div><div><b>例)箱の中のボールの数の推論</b></div><div>ある箱の中にボールが3つ入っている。ボールの色は赤か白のどちらかだが、どの色が何個入っているかはわからない。ここで箱の中からランダムに1つボールを取り出しそのボールの色を確認後箱の中に戻すという操作を行う。</div><div>【ケースA】1回の試行で「白」が出た場合</div><div>【ケースB】3回の試行で「白→赤→白」が出た場合</div><div>の2つの場合で箱の中の白ボールの数がどのように推論できるかを見ていこう。</div><div><br /></div><h3 style="text-align: left;"><span style="font-weight: 400;">■【ケースA】1回の試行で「白」が出た場合</span></h3><div>上のように、確率モデルの構築→推論とステップを踏んで進めていこう。</div><h4 style="text-align: left;">▼確率モデルの構築</h4><div>この場合の事象は下図のようなグラフィカルモデルで表せる。ここで\(W=\{0, 1, 2, 3\}\)は白玉の数を示す確率変数で、\(W\)の値により試行時に取り出される玉の色\(X=\{r, w\}\)の確率が決まるというモデルになっている。</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVVdOLuUkYfafVCzfd6wClKRxMrjIU8hC5vkW5LnFpWQ_OmP7h2R3_k5fc43AgaQnI7ZFbH0ygxn9xcvTyHGDZpuu58ND3GtiVB0RzGoJMOePFIYHk87tmtUC87VbcqcaeLvKFYZUA3BI/s586/20210202.001.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="446" data-original-width="586" height="219" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVVdOLuUkYfafVCzfd6wClKRxMrjIU8hC5vkW5LnFpWQ_OmP7h2R3_k5fc43AgaQnI7ZFbH0ygxn9xcvTyHGDZpuu58ND3GtiVB0RzGoJMOePFIYHk87tmtUC87VbcqcaeLvKFYZUA3BI/w287-h219/20210202.001.png" width="287" /></a></div><div><br /></div><div>また、簡単な確率の考察からそれぞれの確率は下表のようになる。ここで箱の中の玉の数は何の情報もないため等確率で発生するものとして\(P_0(W)=1/4\)、ここで\(W=\{0,1, 2, 3\}\)としている。この\(P_0(W)\)を事前確率という。</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtAYypnfEOu5zYeAzeJew0t6-KyIGPS3Vg_P_Nae5EzD-ybfwLLiva8NolKxLzxcfawxZ7kowx6nzUjk-aLz-TuFECJiy_i0qTPiIy0uqHLNKsgMhGERQLd3jd58A8OenB-ZHQhsl4s3Q/s1550/20210202.002.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="596" data-original-width="1550" height="163" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtAYypnfEOu5zYeAzeJew0t6-KyIGPS3Vg_P_Nae5EzD-ybfwLLiva8NolKxLzxcfawxZ7kowx6nzUjk-aLz-TuFECJiy_i0qTPiIy0uqHLNKsgMhGERQLd3jd58A8OenB-ZHQhsl4s3Q/w425-h163/20210202.002.png" width="425" /></a></div><div><h4>▼推論</h4></div><div>「1回の試行で白ボールを取り出した」というデータが確定したもとでの白ボールの数を推論したいので、求めたいのは事後確率\(P(W|X_1=w)\)であり、条件付き確率の定義から</div><div>\[P(W|X_1=w)=\frac{P(W,X_1=w)}{P(X_1=w)}=\frac{P(W,X_1=w)}{\sum_W{P(W, X_1=w)}}\tag{1}\]</div><div>と書ける。上記の最左辺の分子と分母はこれまでの情報で計算できることがわかると思う。それぞれ求めていってみよう。</div><div>分子の同時確率は\(P(W, X_1)=P(X_1|W)P(W)\)であり、\(P(W)_0=P(W)\)とすると、</div><div>上の表から以下のように計算できる。</div><div><div>\[\begin{cases}P(W=0, X_1=w) & =P(X_1=w|W=0)P_0(W=0)= 0 \cdot \frac{1}{4} = 0 \\P(W=1, X_1=w) & =P(X_1=w|W=1)P_0(W=1)= \frac{1}{3} \cdot \frac{1}{4} = \frac{1}{12} \\P(W=2, X_1=w) & =P(X_1=w|W=2)P_0(W=2)= \frac{2}{3} \cdot \frac{1}{4} = \frac{1}{6} \\P(W=3, X_1=w) & =P(X_1=w|W=3)P_0(W=3)= 1 \cdot \frac{1}{4} = \frac{1}{4} \\\end{cases}\]</div></div><div><br /></div><div>また(1)式の分母である周辺確率は</div><div>\[P(X_1=w)=\sum_{W}P(W, X_1=w) = 0+ \frac{1}{12} + \frac{1}{6} + \frac{1}{4} = \frac{1}{2}\]</div><div>となり、同様に\(P(X_1=w)=\frac{1}{2}\)となる。</div><div><br /></div><div>(1)式にこれらの結果を代入すると</div><div>\[\begin{cases}P(W=0|X_1=w) & = 0 / \frac{1}{2} = 0\\ P(W=1|X_1=w) & = \frac{1}{12} / \frac{1}{2} =\frac{1}{6}\\ P(W=2|X_1=w) & = \frac{1}{6} / \frac{1}{2} =\frac{1}{3}\\ P(W=3|X_1=w) & = \frac{1}{4} / \frac{1}{2} =\frac{1}{2}\\ \end{cases}\]</div><div>となり、1回目に白ボールが出た場合、確率的には箱の中のボールは全部白の可能性が一番高いと推論できることを示している。</div><div><br /></div><div><h3><span style="font-weight: 400;">■【ケースB】</span><span style="font-weight: normal;">3回の試行で「白→赤→白」が出た場合</span></h3></div><div>ケースAと同様の考察を繰り返すと良いが力尽きたので気が向いたら追記予定。</div><div>要点は、ボールを試行の度に箱に戻すため、Wが決定された状態では、各試行間は独立なので\[P(X_1,X_2,X_3)=P(X_1)P(X_2)P(X_3)\]</div><div>となることを利用すれば良い。</div><div><br /></div><p></p>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-13130366416165110582021-02-01T14:19:00.000+09:002021-03-14T09:41:27.375+09:00ベイズ学習の枠組み①<p>ベイズ学習は、観測できない未知の変数\(W\)の確率分布\(P(W)\)を、観測された事象(データ)\(D\)が得られたという条件のもとで推論するものです。すなわち事後分布\(P(W|D)\)を求める作業になります。<br /><br />例えば、赤玉と白玉が入っている箱がありそれぞれの色の個数の割合\(\theta\)が未知である場合、その\(\theta\)の確率分布\(P(\theta)\)を箱から無作為に取り出した玉の色のデータ\(D\)を得られた事実をもとに推論する、すなわち\(P(\Theta|D)\)を計算するというようなものになります。</p><p>もう1つの例としては線形回帰\( y=\boldsymbol{w} \cdot \boldsymbol{x} +b\)の学習パラメータ\(\boldsymbol{w}\)、\(b\)を未知の変数としその確率分布\(P(\boldsymbol{w})\)、\(P(b)\)を観測データ\(D\)から求める、すなわち\(P(\boldsymbol{w}|D)\)、\(P(b|D)\)を計算するというものが挙げられます。</p><p>ベイズ学習は一般的に以下の2つのStepで行っていくといえます。</p><h4 style="text-align: left;">▼ Step1:確率モデルの構築</h4><div>まず、着目する事象が確率的なプロセスから発生するものだという仮定を置き、そのプロセスをモデル化することから始めます。モデル化には事象間もしくは変数間の関係性をグラフ表現するグラフィカルモデルが有用です。</div><div>また事象の確率プロセスがモデル化できるとそれはすなわち変数間の同時確率分布を定式化することになります。</div><div>例えば上の赤玉と白玉の割合の例の場合、下左図のようにモデル化することができます。</div><div>下図はすなわち、赤玉と白玉の割合自体も確率的に決まっており(\(P(\Theta)\))、そこから取り出される玉の色は玉の割合が\(\theta\)と決まった上での条件付き確率で表されるとモデル化していることになります。</div><div>また、線形回帰の例の場合も下右図のようにモデル化することができます(*)。未知のパラメータが確率的に決まっているものとし(\(P(\boldsymbol{w})\)、\(P(b)\))、かつ、データ自体も確率的に発生し、目的変数はそれら確率変数が決定された上での条件付き確率として表現できるというモデリングを行っています。</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjon38LCO9qGRWVNIuHCe_iInqQBbLIh-rQCOyTRoqBuXieVuIENWAg-DJvALqhfoA3oU5i-xLVOtELYF2VABayCf4p2IrzB-j9TySFKPg5TaRIaP8thevfbRE_zk5r0tSs_o-XFZclluM/s1804/20210201.001.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="937" data-original-width="1804" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjon38LCO9qGRWVNIuHCe_iInqQBbLIh-rQCOyTRoqBuXieVuIENWAg-DJvALqhfoA3oU5i-xLVOtELYF2VABayCf4p2IrzB-j9TySFKPg5TaRIaP8thevfbRE_zk5r0tSs_o-XFZclluM/w562-h292/20210201.001.png" width="562" /></a></div><br /><div><br /></div><div><h4>▼ Step2:推論</h4><div>Step1で確率モデルが構築できたら、そのモデルと観測データから未知のパラメータの確率分布を推論します。これはすなわち冒頭での話のとおり、観測データ\(D\)を得た条件下で未知のパラメータがとる条件付き確率\(P(W|D)\)を推論することに相当します。</div></div><div>ではこの\(P(W|D)\)はどう計算すれば良いのかを考えていきましょう。条件付き確率の定義から</div><div>\[P(W|D)=\frac{P(W,D)}{P(D)}=\frac{P(W,X)}{\sum_W P(W,X)}\]</div><div>と書き換えられます。</div><div>分子の同時確率はStep1の確率モデルの構築ができた時点で定式化されており求めることができるし、分母は未知のパラメータの取りえる値全てに関して同時確率を足し合わす(周辺化する)ことで求められます。</div><div><br /></div><div>つまりこの式は、<u>どのような確率モデルの例であっても、同時確率とその未知のパラメータに対する周辺分布を計算することで事後分布\(P(W|D)\)を推論可能である</u>ということを示していることになります。</div><div><br /></div><div>実際の複雑な確率モデルを扱う場合、周辺確率を求めるのに非常にコストがかかるためサンプリングや変分法と呼ばれる近似手法によって事後分布を計算するケースが多いですが、おおもとのベイズ学習の発想は「同時確率とその未知のパラメータに対する周辺分布から事後分布を計算する」ということにあることは覚えておいた方が良いでしょう。</div><div><br /></div><div>次回は、非常に単純なモデルを例に、同時確率とその周辺確率から実際にベイズ推論を行う例を見たいと思います。</div><div><br /></div><span><a name='more'></a></span><div>(*)図内の四角形で囲った部分は、グラフィカルモデル のプレート図の表現で、独立のN個あるデータを1つにまとめたことを意味しています。</div>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-24972077018294373292021-01-17T16:41:00.001+09:002021-01-17T16:41:06.540+09:00Artificial Life(ALife)とはなにか?<p> 最近、ちょくちょくと人工生命(Artificial Life: ALife)というワードを聞くようになった。単語から読み取れるところなんとなくイメージできるけど、具体的にどういう研究なのか?どういう応用が期待できるか?人工知能(AI)と何が違うのか?などのイメージが沸かない。</p><p><a href="https://bizzine.jp/article/detail/2502" target="_blank">ここ</a>と<a href="https://thegradient.pub/an-introduction-to-artificial-life-for-people-who-like-ai/" target="_blank">ここ</a>の記事がその疑問を少し解決してくれたので改めて整理したい。</p><h3 style="text-align: left;">■ キャッチフレーズは "Life as it could be."</h3><div>人工生命のキャッチフレーズは"Life as it could be"、すなわち「あり得たかもしれない生命」などと言われるらしい。なるほど実際に地球上に存在する(していた)生物について研究する生物学とは異なり、よりメタ的な生命を研究する。つまり「生命」と呼べるものがもつ一般的な性質(生命であるための必要条件)を探ろうという学問と考えられる。そしてその必要条件が何かを探るために、構成論的にボトムアップで生命を作っていこうする。これは意識とは何かを探る、谷口忠大先生の<a href="https://amzn.to/2XMEdjH">記号創発ロボティクス</a>とアプローチが似ている。</div><div><br /></div><div><br /></div><h3 style="text-align: left;">■人工知能との違い</h3><div>人工知能は人間の知性すなわち、大脳新皮質の部分の役割にフォーカスしているのに対して、人工生命は<span style="background-color: white; font-family: "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", 游ゴシック, YuGothic, "Yu Gothic", メイリオ, Meiryo, Osaka, "MS Pゴシック", "MS PGothic", sans-serif;">身体知や生命維持など脳幹が司る知能にフォーカスを与えている。</span></div><div><span style="background-color: white; font-family: "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", 游ゴシック, YuGothic, "Yu Gothic", メイリオ, Meiryo, Osaka, "MS Pゴシック", "MS PGothic", sans-serif;">さらに私が最もガッテンしたのが、適用方法の違い。人工知能は学習、人工生命は「進化」という違いがある。学習はある程度収束するものであるが、進化は終わりなき進化を続けていく(Open-ended evolution)。そして学習が個の範囲で閉じるのに対して進化は集団として個が相互作用しながら長期的、永続的に進んでいくものである違いがある。</span></div><div><br /></div><div>少しづつ勉強を進めていこう。</div>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-58041529095319184842020-11-15T10:58:00.001+09:002020-11-15T11:03:38.049+09:00分散や標準偏差のオンライン計算 → Welfordアルゴリズム<p>データが逐次追加されていく際に、追加されるたびにその時点での「分散」や「標準偏差」を計算したい場合がある。その時点での全てのデータから毎度計算しても良いが、やはり計算量が馬鹿らしい。そこで欲しくなるのが、これらの量をオンライン(ストリーム処理)で計算できるアルゴリズムだ。</p><p>安心してください、ありますよ。「Welford アルゴリズム」というものです。</p><p>ここではそのWelfordアルゴリズムを紹介したい。</p><p>※以下、不偏分散を考えるが、標本分散の場合でも全く同じ考えが出来る。</p><h3 style="text-align: left;">■分散と標準偏差</h3><p>データサンプルが\(x_i, \ldots, x_N\)で与えられる場合を考えられる。この時、データの不偏分散\(s^2\)の定義は</p><p>\[s^2 = \frac{\sum_{i=1}^N (x_i – \bar{x})^2}{N-1}\]</p><p>として与えられる。そして標準偏差\(s\)はその平方根\(s = \sqrt{s^2}\)だ。</p><p>ここで\(\bar{x}\)はサンプルの平均、すなわち\(\bar{x} = \frac{1}{N}\sum_{i=1}^N x_i\)である。</p><p>この定義通りに分散を計算する場合、以下の2ステップを辿る。</p><p></p><ol style="text-align: left;"><li>データ全体の平均\(\bar{x}\)を計算。</li><li>各データ\(x_i\)と平均\(\bar{x}\)の差分の二乗を計算。</li></ol><div>このような計算は明らかに無駄が多い。まずデータ全体を舐める計算を2回も繰り返す必要がある。また、データ全体に対する計算を行うためにすべてのデータを保持しないといけないので今回の主題であるオンラインの計算をするためにはこのままではダメだ。何か工夫がいる。</div><div><br /></div><p></p><h3 style="text-align: left;">■Welfordアルゴリズム</h3><p>そこでWelfordアルゴリズムでは、サンプルが\(N\)個の時と\(N-1\)個の時の分散の差に着目して以下の計算を行う。</p><p>\begin{align} &(N-1)s_N^2 – (N-2)s_{N-1}^2 \\ &= \sum_{i=1}^N (x_i-\bar{x}_N)^2-\sum_{i=1}^{N-1} (x_i-\bar{x}_{N-1})^2 \\ &= (x_N-\bar{x}_N)^2 + \sum_{i=1}^{N-1}\left((x_i-\bar{x}_N)^2-(x_i-\bar{x}_{N-1})^2\right) \\ &= (x_N-\bar{x}_N)^2 + \sum_{i=1}^{N-1}(x_i-\bar{x}_N + x_i-\bar{x}_{N-1})(\bar{x}_{N-1} – \bar{x}_{N}) \\ &= (x_N-\bar{x}_N)^2 + (\bar{x}_N – x_N)(\bar{x}_{N-1} – \bar{x}_{N}) \\ &= (x_N-\bar{x}_N)(x_N-\bar{x}_N – \bar{x}_{N-1} + \bar{x}_{N}) \\ &= (x_N-\bar{x}_N)(x_N – \bar{x}_{N-1}) \\ \end{align}</p><p>この結果から、下式のようにデータが\(N\)個の時の分散を\(N-1\)個の時の分散から求められることがわかる。</p><p>\[ s_N^2 = \frac{N-2}{N-1} s_{N-1}^2 + \frac{1}{N-1} (x_N-\bar{x}_N)(x_N – \bar{x}_{N-1}) \]</p><p>この結果をもとに分散をオンラインで計算するアルゴリズムに落とすと、下の疑似コードのようになる。(forで各データを逐次回している部分がそれだ)</p>
<script src="https://gist.github.com/a-mitani/ee9b30892591097dfcc2d5c2e358dcda.js"></script>
<p>驚くほど簡単なアルゴリズムだ。</p><h3 style="text-align: left;">■ライブラリ</h3><p>簡単なので必要に応じて自分で実装すれば良いが、<a href="https://pypi.org/project/welford/">Python用のライブラリ</a>を作ってPypiに登録してみたのでよければそれを使ってみてください。改良点があれば<a href="https://github.com/a-mitani/welford">Githubリポジトリ</a>にIssue投げて頂ければ嬉しいです。</p><p><br /></p><p>■参考</p><p></p><ul style="text-align: left;"><li><a href="https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance">Wikipedia: Algorithms for calculating variance</a></li><li><a href="https://jonisalonen.com/2013/deriving-welfords-method-for-computing-variance/">Blog: Welford’s method for computing variance</a></li><li><a href="https://www.johndcook.com/blog/2008/09/26/comparing-three-methods-of-computing-standard-deviation/">Blog: Comparing three methods of computing standard deviation</a></li></ul><p></p>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-58251481349835037042020-11-14T10:46:00.000+09:002020-11-14T10:46:02.118+09:00Gradient Boosting(勾配ブースティング)とは<p>最近、Kaggleだとかその周辺では、XGboostだとかcatboostだとか、Gradient Boosting(勾配ブースティング)の手法が流行っているらしい。最終的にcatboostを勉強する目的で、その前段階として勾配ブースティングをひととおり勉強したので、そのメモ。</p><h3 style="text-align: left;">■Boosting(ブースティング)とは?</h3><div>ブースティングとはアンサンブル学習の一種で、弱学習機を「積み重ねる」ことで精度を上げようとするもの。下の図がわかりやすいが、バギングは複数の弱学習機を並列に並べてそれぞれの学習機の結果を平均したり投票したりして最終的な結果を出力するもので、Random Forestが代表的な例。一方でブースティングは複数の弱学習機を「直列」に並べてモデルを強化してあげようという思想のもの。具体的な例としてはLS_boostingが挙げられる。この手法は1つ目の弱学習機での回帰残差を2つめの弱学習機で最小化するようにし、さらにその結果の残差を3つめの弱学習機で最小化するようにし・・・・、というふうに学習機を繋いでいく。</div><div>ブースティングのアルゴリズムには幾つか種類があり、代表的なのはAdaboostや今回のトピックである勾配ブースティング。</div><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirxqdEVn9DC9I5ArAw2w2pI_Ix6CuDyPZDROmYCZpVnzfTa101PJ8he9bIjZE6bs4jBnKbLh52-gBgY-QkevNbpGet3qcQiXOqkwvdCt6ivTxCQ85xLf3f4W_5_n450L_9fK9_AyQB0Uw/s1398/bagging-boosting.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="518" data-original-width="1398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirxqdEVn9DC9I5ArAw2w2pI_Ix6CuDyPZDROmYCZpVnzfTa101PJ8he9bIjZE6bs4jBnKbLh52-gBgY-QkevNbpGet3qcQiXOqkwvdCt6ivTxCQ85xLf3f4W_5_n450L_9fK9_AyQB0Uw/s320/bagging-boosting.png" width="320" /></a></div><div style="text-align: center;"><a href="https://quantdare.com/what-is-the-difference-between-bagging-and-boosting/" target="_blank">Source</a></div></div><h3 style="text-align: left;">■勾配ブースティングの概要</h3><div>勾配ブースティングは、超ざっくりでいうと「前の学習機の誤差を埋めるように次の弱学習機を学習させる」ことをしている。</div><div>勾配ブースティングアルゴリズムの疑似コードは以下のようなものだ。</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj37sQHK5N54ffPgHAmed1AEY37vKHn9aCJhiyq1maiGakVMxM4Dcbhc-8RVSAviQcqWiAMjnJvwb9BARI6Bt_Fbj-ErUTXRzeUQtX7myUgo_MzPBre500W79U2XZQIW13EKSXnvRtH5RM/s1368/pseudo-code-bg.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="640" data-original-width="1368" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj37sQHK5N54ffPgHAmed1AEY37vKHn9aCJhiyq1maiGakVMxM4Dcbhc-8RVSAviQcqWiAMjnJvwb9BARI6Bt_Fbj-ErUTXRzeUQtX7myUgo_MzPBre500W79U2XZQIW13EKSXnvRtH5RM/w513-h240/pseudo-code-bg.png" width="513" /></a></div><br /><div>ここで、\(L\)は回帰や分類のLoss関数、\(h\)は個別の弱学習器、\(F_m\)は各弱学習器を統合した(つまり繋いだ)加法モデルを示している。</div><div><ul style="text-align: left;"><li>3行目:それぞれのサンプル(\(i\))についてのLossをその時点(の1つ前)の加法モデルの偏微分(\(F\)を微小変化させた時の\(L\)の変化量)のマイナスを\(\tilde{y}_i\)と計算している。つまりこれは<b>Lossを最小にするための勾配降下の方向</b>を示している。</li><li>4行目:3行目で求めた勾配降下の方向に最も近くなる修正を加える弱学習器を学習させる。</li><li>5行目:4行目で求めた弱学習機をその時点の加法モデルに加える時のパラメータ(学習レート?)を学習。</li><li>6行目:4行目と5行目の結果から、加法モデルを決定。</li></ul><div>というプロセスを繰り返すアルゴリズムとなっている。</div></div><div>ここで、勾配効果の方向にむけて弱学習器を学習させていくことから「勾配」ブースティングという名前がついているのだ。</div><div><br /></div><h3 style="text-align: left;">■勾配ブースティングの具体例</h3><div>勾配ブースティング自体は一般的なアルゴリズムのため、そのアルゴリズムの中で利用するLossの種類などは様々なバリエーションが存在する。</div><div>最もシンプルな具体的なLossを回帰の二乗誤差とするもので、LS_boosting。</div><div>Lossを二乗誤差、つまり\(L(y_i, F(\boldsymbol{x}_i))=\frac{1}{2}(y_i - F(\boldsymbol{x}_i))^2\)としたときに、3行目の偏微分は</div><div>\[\tilde{y}_i= - \left[\frac{\partial L}{\partial F}\right] _{F=F_{m-1}}= - \left[\frac{\partial \frac{1}{2}(y_i - F)^2}{\partial F}\right] _{F=F_{m-1}} = y_i - F_{m-1}\]</div><div>となり、一つ前のイタレーションで作成した加法モデルと実測との残差になる。そのため前述したようにLS_boostingはこの残差を最小化するように次の弱学習器を作成するということになる。</div><h3 style="text-align: left;">■参考</h3><div>https://www.st-hakky-blog.com/entry/2017/08/08/092031</div><div>https://ticc-econometrics.hatenablog.com/entry/gbdt2#fn-6241a4a1</div><div><br /></div>amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-87691370414954499652020-09-26T09:35:00.001+09:002020-09-26T09:35:28.135+09:00データは寡黙である。<div>これまで十数年間、いくつかの企業でデータ分析に携わってきた。その間にビッグデータや人工知能、ディープラーニングというようなバズワードが流行り「データ至上主義」ともいえる風潮が流れ始めているふうに感じる。</div><div><br /></div><div> 確かに画像などの判別技術や購買予測、レコメンデーション技術など、大量データを学習機に食わせて成果を出している分野もある。</div><div><br /></div><div>しかし、企業でデータ活用として期待されているのはこれらだけでない。それよりも「現在起きている、または予測されることに対して<span style="color: #cc0000;">どのようにアクションとるべきか?</span>」をデータから見出すこと(以降、これを「データからインサイトを得る」と表現する)が求められるケースが圧倒的に多い。</div><div><br /></div><div>注意が必要なのは、「購買予測をする」ことと「より売上を上げるためにとるべきアクションを見出す」ことは全く異なり、またそれに必要な技術も全く別物であることだ。</div><div><br /></div><div>典型的で有名な例として「アイスクリーム売上と犯罪発生数の関連性」を挙げてみる。下の左のグラフはある町のアイスクリームの売上と犯罪発生数の関連性を示したものだ。グラフから読み取るにアイスクリームの売上が多い時に犯罪発生数が多い<span style="color: #cc0000;">関係性</span>が見て取れる。しかしよく言われるように、これは関連性(相関)があるだけで、決して「アイスクリームの売上が増えたから犯罪発生数が増えた」という原因と結果を示しているわけではない。この裏には下右図のように、「気温」というアイスと犯罪の両者の増減に影響を与える共通の要因(交絡因子)が存在し、気温が暑い時にはアイスクリームの売上が増えるのと同時に、イライラして犯罪数も増えることで、直接関係のないアイスと犯罪に関連性が現れているのである(偽相関)。</div><div class="separator" style="clear: both; text-align: center;"><br /></div><div style="text-align: center;"><img border="0" data-original-height="760" data-original-width="1986" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimcVg-kmYIIM_mQacldRkrI1jdvTQeYxuyrBROXsX61IgpDZFXKHUC8ZnA996amz_JHORhc7VKRy_kVK9idXql4dmz3zVXkBP9ndyuChNmbBX7ofJT_JJyG9GJSvqV_vWfLZJzRq3-5HM/w499-h190/ice_crime.png" width="499" /></div><div><br /></div><div>この例は2つの重要なことを示している。</div><div><br /></div><div>1つは、「予測する」と「原因と結果の関係性(因果関係)を分析する」は別物であるということである。図から見て取れるようにアイスの売上を説明変数にして犯罪率を予測することは(ある程度の汎化性をもって)可能である。しかし、だからといって犯罪数を減らすためにアイスの売上を減らす(店舗を閉鎖させる)というアクションは全く有効ではないことは自明であろう。</div><div><br /></div><div>2つめは、ほとんどの場合にデータのみだけでは因果関係はわからないという事実だ。データからわかるのは事象間の関連性(相関)のみであり、原因と結果の関連性を見出すためには、事象の関係に対するその分野での固有の知識(ドメイン知識)が不可欠である。例えば上の例では、「アイスクリームが犯罪の発生に寄与することはないはずだ」、「両者に共通する要因として気温が考えられる」というという事前知識があるが故に本当の因果関係を見出すことができた。</div><div><br /></div><div>企業でデータ分析の業務を行っていると、データが大量にあればなんでもわかるという誤った神話に苦労することが多い。データは因果分析においては恐ろしいほど寡黙であり、データにドメイン知識を与えて初めてデータが物事を語り始めるということを認識しないといけない。</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><br />amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-73585642836771377992020-07-23T11:35:00.002+09:002020-07-23T12:01:17.555+09:00RandomForestはホントに交互作用を拾うか?木構造系のモデルは、分岐の組み合わせにより説明変数間の交互作用もモデルに自動的に組み込まれそうな「気がする」。しかし実際に実際に動かしてそのことを確認した記事がネット上になかったので自分自身で確認することに。<div><br /></div><div>まずはトイデータを用意。ここでX[:, 2]とX[:, 3]が交互作用で目的変数に効くようにしている。X[:, 0]は目的変数には無関係な説明変数。</div><div><br /></div>
<script src="https://gist.github.com/a-mitani/4758898e133b7938cba615e6c950769f.js"></script>
次に学習&テストデータセットに分けて学習と予測を行って精度評価してみる。<div>ここでは比較対象として単純な線形回帰モデルも使っている。<div><div><br /></div>
<script src="https://gist.github.com/a-mitani/6d8f27381bd48004d2462cf98a6c6a12.js"></script>
<div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx14FE_-7Uv7VLYKx19ueZYYIFf7aPOU-Wo_KGGJYAgVUz9EyFdZ3BN3eduwIh389fz6C0WhyCtU1JiNMXnDM2ys3sJxo9JMfRfcntPgmz7LBzRVuMaPQt-DemqNBLm3VJpK_kfKvhkiM/s318/accuracy.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="303" data-original-width="318" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx14FE_-7Uv7VLYKx19ueZYYIFf7aPOU-Wo_KGGJYAgVUz9EyFdZ3BN3eduwIh389fz6C0WhyCtU1JiNMXnDM2ys3sJxo9JMfRfcntPgmz7LBzRVuMaPQt-DemqNBLm3VJpK_kfKvhkiM/s0/accuracy.png" /></a></div>
<div><br /></div><div>なるほど、ほとんど予測できていない線形回帰と比べてRandomForestは精度良く予測できている。</div></div></div><div><br /></div><div>Importanceも一応見てみると、交互作用に関わる変数のImportanceが高くなっている。</div><div><br />
<script src="https://gist.github.com/a-mitani/aaae4723484498a1f176b611fe91390e.js"></script>
</div><div><br /></div><div>以上、当たり前といえば当たり前だけど実際に確認してみた。</div><div><br /></div><div>※ <a href="https://github.com/a-mitani/data-for-blog/blob/master/RandomForest_Interaction.ipynb" target="_blank">ここ</a>に元のNotebookを置いています。</div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-38001172485511319832020-04-26T06:00:00.002+09:002020-04-26T06:00:56.352+09:00ufwでのファイアウォール設定<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
ufw(<span style="background-color: white; color: #333333; font-family: , "segoe ui" , "helvetica neue" , "hiragino kaku gothic pron" , , "meiryo" , sans-serif; font-size: 16px;">Uncomplicated FireWall)はファイアウォールを設定するコマンドで、iptablesのwrapperのような位置付けのようである。</span><span style="background-color: white; color: #333333; font-family: , "segoe ui" , "helvetica neue" , "hiragino kaku gothic pron" , , "meiryo" , sans-serif; font-size: 16px;"><br /></span></div>
<div style="text-align: left;">
<span style="background-color: white; color: #333333; font-family: , "segoe ui" , "helvetica neue" , "hiragino kaku gothic pron" , , "meiryo" , sans-serif; font-size: 16px;"><br /></span></div>
<div style="text-align: left;">
<span style="color: #333333; font-family: , "segoe ui" , "helvetica neue" , "hiragino kaku gothic pron" , , "meiryo" , sans-serif;"><span style="background-color: white;">下記に設定の仕方をメモ。</span></span></div>
<div style="text-align: left;">
<br /></div>
</div>
<script src="https://gist.github.com/a-mitani/41d41a2c3519807a20bd130f65c359d2.js"></script></div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-53397134703449814382019-02-23T12:28:00.000+09:002019-02-23T12:44:54.268+09:00ジニ係数とは何か?解釈と実装<div dir="ltr" style="text-align: left;" trbidi="on">
決定木にて分類の基準によくジニ係数(Gini inpurity / Gini index)という尺度が使われる。<br />
このジニ係数について少し考察してみたのでメモ。<br />
<br />
<h3 style="text-align: left;">
ジニ係数の定義と挙動</h3>
<div>
あるデータセット\(t\)の中に\(K\)種のクラスのサンプルが含まれる場合、ジニ係数は
<br />
\[
I(t)= \sum_{i\neq j} P(C_i|t)P(C_j|t)=\sum_{i=1}^{K} P(C_i|t)(1-P(C_i|t) = 1- \sum_{i=1}^{K}P^2(C_i|t)
\]
と定義される。
ここで\(P(C_i|t)\)はデータセット\( t \)の中に含まれるクラス\( i \)のサンプル数の割合である。<br />
この定義式を元に2つのクラス(0, 1)が含まれる20個のデータを例にクラス0が含まれる数に応じたジニ係数の変化をプロットしたのが下図。期待通りデータセットの中に各クラスのデータが均等に含まれれば含まれるほどジニ係数の値は大きくなり、偏って含まれれる場合は小さくなり、純粋に1つのクラスしか含まれない場合はゼロになる。
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4QEVElKA6Uu_1SoY9zTn8-Xqo0ibbgnnp7TFB9Zeyxp-RGvZAKxbao_YiYSMm99Nr3qn_N-_eXp2k0CSh6JEJn73LP60j6bPVIFfaa_kIPsgTo1DTuylFozkkIEOlqkpRH_3OBIKt4AI/s1600/gini.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="564" data-original-width="960" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4QEVElKA6Uu_1SoY9zTn8-Xqo0ibbgnnp7TFB9Zeyxp-RGvZAKxbao_YiYSMm99Nr3qn_N-_eXp2k0CSh6JEJn73LP60j6bPVIFfaa_kIPsgTo1DTuylFozkkIEOlqkpRH_3OBIKt4AI/s320/gini.png" width="320" /></a></div>
<br />
<h3 style="text-align: left;">
</h3>
<h3 style="text-align: left;">
ジニ係数の解釈</h3>
ジニ係数の定義は「データセットの中から無作為に2つサンプルを取り出したときに異なるクラスのサンプルが取り出される確率」と解釈するとわかりやすい。<br />
データセット\( t \)の中から無作為に2回取り出すベルヌーイ試行<a href="https://data-hacker.blogspot.com/2019/02/gini-impurity.html#{fn001}"><sup>*1</sup></a>を考えたときに、同じクラスのサンプルが取り出される確率は\( \sum_{i=1}^{K}P^2(C_i|t) \)。その逆で異なるクラスのサンプルが取り出される確率は、\( 1- \sum_{i=1}^{K}P^2(C_i|t)\)となり、これがジニ係数の定義と一致するというわけ。
<br />
<br />
<h3 style="text-align: left;">
複数データセットでのジニ係数</h3>
決定木アルゴリズムでは決定木のノードで元のデータセットを2つ(\(L\)と\(R\))に分割する。そのためこの分割後の2つのデータセット全体の不純度が小さい分割の仕方を選ばないといけない。そのため決定木アルゴリズムでは、
\[
I_{split}(t)= p_{L}I(t_{L}) + p_{R}I(t_{R})
\]
の量が最小となる分割方法を見つけることになる<a href="https://data-hacker.blogspot.com/2019/02/gini-impurity.html#{fn002}"><sup>*2</sup></a>。ここで\(p_{L}\)と\(p_{R}\)はそれぞれ分割後のデータセットのサンプル数の元のデータセットに対する割合。<br />
<br />
<h3 style="text-align: left;">
ジニ係数と交差エントロピー</h3>
はじめてのパターン認識でも書かれているけど、不純度の尺度はジニ係数だけではなく、交差エントロピー
\[
I(t)= -\sum_{i=1}^{K}P(C_i|t)\log P(C_i|t)
\]
も使われることがある。ただし、<a href="https://qiita.com/murs13/items/0a2077f97664b58c2ea9" target="_blank">挙動がほぼ同じ</a>ということと、ジニ係数であれば、<a href="https://bambielli.com/til/2017-10-29-gini-impurity/#so-which-should-i-use-gini-impurity-or-entropy" target="_blank">計算コストの高いLogの計算をしなくて良いため</a>、ジニ係数が利用されることが多い様子。
<br />
<br />
<h3 style="text-align: left;">
ジニ係数の実装@Python3</h3>
折角なのでPythonでジニ係数を計算する関数をPythonで実装してみた。上記\( I_{split}(t)\)を計算するコードです。<br />
ここのジニ係数を計算する関数を参考にした。ただしジニ係数の定義上、ジニ係数の計算時に存在するクラスを事前に知る必要がないはず<a href="https://data-hacker.blogspot.com/2019/02/gini-impurity.html#{fn003}"><sup>*3</sup></a>なのでデータセットだけを関数に渡す方式に変更している。<br />
<script src="https://gist.github.com/a-mitani/6c8a90905eb4ad934d1551ec523c01c4.js?file=calc_gini_impurity.py"></script>
<a name="{fn001}">(*1)</a>: サンプルを複数回無作為に取り出す際に、一度取り出したサンプルを「戻して」再度サンプルを無作為に取り出す試行。<br />
<a name="{fn002}">(*2)</a>: 初めてのパターン認識の(11.11)式。<br />
<a name="{fn003}">(*3)</a>: たとえ対象のデータセットの中に現れないクラスが存在したとしてもそれはジニ係数に寄与しない。<br />
</div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-28459462349130800042018-05-15T11:24:00.000+09:002018-05-15T11:24:22.419+09:00Mac OSXへのoctaveインストール<div dir="ltr" style="text-align: left;" trbidi="on">
会社で<a href="https://www.coursera.org/learn/machine-learning">coursera machine learning</a>を受講することになった。<br />
その中で使うoctaveを<a href="http://blog.amedama.jp/entry/2017/04/28/232547">ここら</a>を参考にmac OSX(High Sierra)にインストールしようとして<br />
「brew install octave」コマンドを実行したら<br />
<blockquote class="tr_bq">
Error: Could not symlink include/octave-4.4.0 /usr/local/include is not writable.
</blockquote>
なるエラーが出てインストール(リンク)ができない事態が発生。<br />
<br />
色々調べて結局、以下の解決方法で解決。要は自分で/usr/local/includeのディレクトリを作成してから、brew実行する。(インストールは成功しているのでリンクだけ実行)<br />
<blockquote class="tr_bq">
$ sudo mkdir /usr/local/include<br />
$ sudo chown -R $(whoami):admin /usr/local/include<br />
$ sudo chown -R $(whoami):admin /usr/local/include<br />
$ brew link octave
</blockquote>
<br />
</div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-24495292436219027782018-01-28T11:40:00.001+09:002018-01-28T11:48:44.278+09:00add-apt-repositoryコマンド実行でエラーが出た時の対処法<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="background-color: white; color: #333333; font-size: 16px;">Ubuntu 16.04にて、OSインストール直後の状態ではadd-apt-repositoryのコマンドを実行すると「Command Not Found」エラーが出る。</span><span style="background-color: white; color: #333333; font-size: 16px;">その解消は下記の2つのコマンドを実行すればOK。</span><br />
<div>
<pre class="brush: bash">$ sudo apt-get update
$ sudo apt-get install software-properties-common</pre>
<br />
簡単。
<br />
<br />
<br />
<br />
<br />
<br /></div>
</div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com1tag:blogger.com,1999:blog-4103242286980619951.post-53619879055242933912018-01-28T11:00:00.001+09:002018-01-28T11:42:02.222+09:00Ubuntu16.04でssh接続するために<div dir="ltr" style="text-align: left;" trbidi="on">
Ubuntu16.04はOSインストール直後の状態ではssh接続すらできない。なぜなら、Ubuntuではsshクライアントはデフォルトで入っているけどssh-serverは入っていないから。なのでインストールする。<br />
<div>
$ sudo apt-get install openssh-server<br />
<br />
<br />
<div>
<br /></div>
<br /></div>
</div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-41574290178249966852017-12-10T09:24:00.000+09:002017-12-10T09:24:05.704+09:00ubuntu16.04 で pip3 のアップグレードにハマった。<div dir="ltr" style="text-align: left;" trbidi="on">
ubuntu16.04 で pip3 9.01にアップグレードする時に少しハマったのでメモ。<br />
<br />
■ python 2.7のpipのアップグレード<br />
$ sudo pip install --upgrade pip<br />
<br />
■ python 3.5 のpip3のアップグレード<br />
$ sudo pip3 install --upgrade pip<br />
<div>
※どうも、引数のほうはpip3でなくて「pip」とするところがミソらしい。</div>
<div>
<br /></div>
</div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-21026487927706820112017-04-15T09:00:00.002+09:002017-04-16T10:37:36.553+09:00MacにHomebrew&gitをインストールする<div dir="ltr" style="text-align: left;" trbidi="on">
Windows機が壊れたのでこの機会にMacbook Proを買った。<br />
<br />
開発環境等を作っていく上で、まずはパッケージ管理システムのHomebrewとgitをインストールする。その手順のメモ。<br />
<br />
<h3 style="text-align: left;">
■Javaをインストール</h3>
<h3 style="text-align: left;">
<ol style="text-align: left;">
<li style="font-size: medium; font-weight: normal;"><a href="https://www.java.com/ja/download/help/mac_install.xml" target="_blank">ここ</a>にしたがって、Java(JDK)を標準的な方法でインストール。</li>
</ol>
</h3>
<h3 style="text-align: left;">
■Command Line Tools for Xcodeをインストール</h3>
<div>
<ol style="text-align: left;">
<li>XcodeApp Storeからインストール。(ファイルが重いのでかなり時間がかかる・・・)</li>
<li>LaunchpadからXcodeを起動し、ライセンス使用許諾に同意する。</li>
<li>ターミナルを開いて下記のコマンドを実行すると、Command Line Tools for Xcodeをインストールするか?というポップアップが表示されるので、そのままインストールを実行。</li>
<pre class="brush: bash">$ xcode-select --install</pre>
</ol>
<div>
<br /></div>
</div>
<div>
<h3 style="text-align: left;">
■Homebrewをインストール</h3>
<div>
<ol style="text-align: left;">
<li>公式HPに載っているコマンドを実行。(2017−04−15時点では以下のコマンド)</li>
</ol>
<pre class="brush: bash">$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"</pre>
</div>
</div>
<div>
<br /></div>
<div>
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Hiragino Kaku Gothic ProN"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
</div>
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: "Hiragino Kaku Gothic ProN"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; orphans: 2; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<h3 style="font-weight: normal; text-align: left;">
■gitをインストール</h3>
<div style="font-weight: normal; text-align: left;">
実はMacには既にプレインストールされたgitが入っている。ただしバージョンも古いため公式のgitをHomebrew経由でインストールする。</div>
<div style="font-weight: normal; text-align: left;">
まずは下記のコマンドでプリインストールされているgitのバージョンを確認する。</div>
<div style="font-weight: normal; text-align: left;">
<pre class="brush: bash">$ git --version</pre>
</div>
<div style="font-weight: normal; text-align: left;">
今回の場合、「<span style="font-family: "verdana"; font-size: 11pt;">git
version 2.11.0 (Apple Git-81)</span>」の結果が帰った。</div>
<div style="font-weight: normal; text-align: left;">
次に下記のコマンドでHomebrewからgitをインストール。</div>
<pre class="brush: bash">$ brew install git</pre>
<div style="text-align: left;">
インストールが完了すると、<b>一度ターミナルを再起動し(再ログインし)</b>、再度先ほどのコマンドでインストールされているgitのバージョンを確認し新しいバージョンのものがインストールされていることを確認する。</div>
<div style="font-weight: normal; text-align: left;">
<br /></div>
</div>
</div>
</div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-11617109675793873762014-05-04T19:38:00.000+09:002019-02-19T09:28:13.506+09:00python(scikit-learn)で決定木<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="http://tjo.hatenablog.com/entry/2013/11/21/194654" target="_blank">ここ</a>でRのパッケージを使った決定木による分類の紹介をしていたので、python(というかscikit-learn)でも同じことをやってみた。せっかくなのでこの場で書いておく。<br />
<br />
※下記に示したpythonソースは<a href="http://nbviewer.ipython.org/github/a-mitani/data-for-blog/blob/master/broccoli/topic_20140504/decision_tree_sample.ipynb" target="_blank">IPythonNotebookにまとめた</a>のでこちらを参照してもらうとよいかも。<br />
<br />
<h3 style="text-align: left;">
■まずは分類したいデータを用意。</h3>
<div>
ここでは、わかりやすさのために、自家製のデータセットを学習データとして使う。用意したデータは説明変数が実数をとる「x」と「y」の2種類で、目的変数は「0」と「1」の2つのクラスをとるような学習データだ。この学習データの説明変数と目的変数の関係をプロットすると(※1)以下のようになる。青い点が「クラス0」、赤い点が「クラス1」のデータを表わす。<br />
<br />
<a href="http://tjo.hatenablog.com/entry/2013/11/21/194654" target="_blank">ここ</a>と同様にXORパターンデータにしていて、<br />
・クラス0は座標(1,1)と座標(-1,-1)を平均として分散0.5で正規分布<br />
・クラス1は座標(-1,1)と座標(1,-1)を平均として分散0.5で正規分布<br />
するという学習データになっている。</div>
<div>
<a href="https://github.com/a-mitani/data-for-blog/blob/master/broccoli/topic_20140504/xor_simple.csv" target="_blank">github</a>に学習データを置いておいた。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZlX0wdWw7m656gzOcrHCEpp8LB9fNllA_p0t_sQRKPY-UswjUMyPfdX63UYBKBrKSi_zfx-6z3wWwufoen9lAZX1GoyjEsH8zvgQnhNmtJip6P6FW4EJ1H-f-HPt7v0eZveusVoQNYsg/s1600/%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%83%E3%83%88%E3%83%97%E3%83%AD%E3%83%83%E3%83%88.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZlX0wdWw7m656gzOcrHCEpp8LB9fNllA_p0t_sQRKPY-UswjUMyPfdX63UYBKBrKSi_zfx-6z3wWwufoen9lAZX1GoyjEsH8zvgQnhNmtJip6P6FW4EJ1H-f-HPt7v0eZveusVoQNYsg/s1600/%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%83%E3%83%88%E3%83%97%E3%83%AD%E3%83%83%E3%83%88.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h3 style="text-align: left;">
■scikit-learnを使って決定木で分類してみる。</h3>
教師データからscikit-learnの決定木ライブラリで学習させて、その結果を用いて、新しいデータを与えて分類させる一連のコードを書いた。コードは以下のとおり。<br />
<script src="https://gist.github.com/a-mitani/87b582420dac63b5f880f289f95b1f2e.js"></script>
実行結果は、[0 1] となり、つまりは<br />
・ x=2.0, y=1.0 のデータはクラス「0」に分類<br />
・ x=1.0, y= -0.5のデータはクラス「1」に分類<br />
されており、予想どおりの分類結果になってメデタシ、メデタシ。<br />
<br />
<h3 style="text-align: left;">
■分類境界を可視化してみる。</h3>
上記の2つのデータでは、それっぽい分類ができているようだけれど、一般的にどう分類されるのかを確認してみる。そのためには上の図の学習データのプロット上に、決定木アルゴリズムの学習結果の分類境界をプロットするのが良いだろう。<br />
<br />
可視化のコードは以下のとおり(上述のコードに追記して実行する。)<br />
少々長いけど、やっていることはプロットの領域を細かいメッシュ(xとyをそれぞれ0.05区切り)に分けて、それぞれの点で学習結果からどちらに分類されるかを全て計算し、その結果(それぞれ0,か1の値)を等高線プロットしている。<br />
<br />
★上述のコードに追記して実行する。<br />
<script src="https://gist.github.com/a-mitani/70ab5201675d6b6ad2711021e33759ea.js"></script>
実行結果は以下の図のようになる。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX3U7bDPMP2jF_RA5_wZ1uUR5ndNsrBYe1KqBXbD9XYf4kwd9wA4f6iCR6W6XHyEIYAy7wwFgq7ldYQy8PyhJhN-D0stYZ9-6Kwm0trxsoQfC6RSpqMilQpzz7LN31zb6YjdGetpxAxgM/s1600/%E5%88%86%E9%A1%9E%E5%A2%83%E7%95%8C.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="254" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX3U7bDPMP2jF_RA5_wZ1uUR5ndNsrBYe1KqBXbD9XYf4kwd9wA4f6iCR6W6XHyEIYAy7wwFgq7ldYQy8PyhJhN-D0stYZ9-6Kwm0trxsoQfC6RSpqMilQpzz7LN31zb6YjdGetpxAxgM/s1600/%E5%88%86%E9%A1%9E%E5%A2%83%E7%95%8C.png" width="320" /></a></div>
<br />
本当の正解(第1&3象限は青(クラス0)で、第2&4象限は赤(クラス1))を知っている人間としては<br />
少々複雑に分類しすぎているとも思えるけれど、与えられた有限個の学習データをキチンと分類できていることが見て取れます。(データのない所は正しく学習できないのは当たり前)<br />
<br />
先に学習結果から分類した2つのデータ(2.0, 1.0)と(1.0, -0.5)は、それぞれ前者が上図の青の領域内、後者が赤の領域内にあったから、それぞれ青と赤に分類されたことになる。<br />
<br />
<h3>
■実際の決定木を可視化</h3>
<div>
他の分類アルゴリズムと比べたときの決定木の良さは、学習データを元にどのように分類されていっているのかを簡単に知ることができるところだ。</div>
<div>
<br /></div>
<div>
結局のところ決定木のアルゴリズムは、学習データをきれいに分類できる説明変数の閾値を探してその閾値で分類した各グループをさらに他の閾値で分類していく、If-Elseロジックを繰り返していっているだけである。If-Elseの数だけ判断の分岐が増えていきまるで木のような構造になるから「決定木」と呼ぶわけだ。</div>
<div>
<br /></div>
<div>
Python(scikit-learn)でも閾値によるの分岐の可視化もできるので、実際に出力してみて、上図の境界がどのように境界が決められていっているのかを見てみる。</div>
<div>
出力方法は、scikit-learnのライブラリで、決定木のツリーをdot言語で記述したdotファイルを出力し、それを<a href="http://www.graphviz.org/" target="_blank">graphviz</a>のような可視化ツールでツリー構造を可視化する流れになる。</div>
<div>
<br /></div>
<div>
dotファイルは以下のコードで出力する(前の2つのコードの後に追記して実行)。<br />
<script src="https://gist.github.com/a-mitani/17b815b9078020f5b3c658a008868104.js"></script>
<br /></div>
<div>
これを実行して出力した「xor_simple.dot」ファイルをgraphvizをつかって出力すると以下の図になる。(実際のツリー構造ははもっと大きいが一部だけをここでは表示している。)<br />
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL5yPFIodZfrJlkAzONi4TxEhbzPv2mvbm3t7JUVx7sP-vIBci50064YJnTyVxbYbOS_xLRC4GeFPx1iIGWcAIAit0F_kupXkxnVLcxIKRAe2u-jzFfhzm06goyTQSd0ww8fXiEoqMUVU/s1600/decision_tree.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="203" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL5yPFIodZfrJlkAzONi4TxEhbzPv2mvbm3t7JUVx7sP-vIBci50064YJnTyVxbYbOS_xLRC4GeFPx1iIGWcAIAit0F_kupXkxnVLcxIKRAe2u-jzFfhzm06goyTQSd0ww8fXiEoqMUVU/s1600/decision_tree.png" width="320" /></a></div>
<br />
<br />
この木構造が示しているのを一部説明すると、まず決定木は、<br />
<br />
<ol style="text-align: left;">
<li>X[1](これは説明変数「y」のライブラリ内部での名称)が1.862以下か否かを判定。(一番上部のノード)</li>
<li>上記の判定で「NO」の場合、それをクラス「0」とする。今回の学習データの場合、3つのデータが該当する。(上から2番目、右側のノード)</li>
<li>上記判定で「YES」の場合、2つめの閾値判定として、「X[0](これは説明変数「x」のライブラリ内部での名称)が1.9746以下か否か」の判定を行う。この判定を行うのは今回の学習データの場合77個(上から2番目、左側のノード)</li>
<li>以下同様の繰り返し</li>
</ol>
<div>
というようなIF-ELSEの判定を繰り返すことで分類が行われることを示している。</div>
<div>
<br /></div>
</div>
<h3 style="text-align: left;">
■汎化(剪定)</h3>
<div>
上記のような決定木のツリー構造をより深くしていき、学習データのほとんど全ての点を正しく分類するようにしても構わないが、いわゆる過学習の状態になりうる。そのため汎化性能を下げるような余分なツリー部分の判定ロジックを削る(つまり剪定(pruning))作業が必要になる。しかし、残念ながらその剪定アルゴリズムは現バージョンのscikit-learnのライブラリでは<a href="http://scikit-learn.org/stable/modules/tree.html">サポートしていない・・・</a><br />
そのため、剪定についてはこの場では割愛。もし必要であれば<a href="http://tjo.hatenablog.com/entry/2013/11/21/194654" target="_blank">ここ</a>とか<a href="https://amzn.to/2ImvlfV" target="_blank">この本</a>のP183~P187を参照してほしい。<br />
<br />
以上。<br />
<br /></div>
<div>
(※1)プロット用のpythonのソースはここ。</div>
(※2)ここと同様に、少し複雑にするように、XORパターンのデータを用意した。</div>
<div>
<br /></div>
</div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-82550302652835987952014-03-02T12:34:00.002+09:002014-03-13T09:19:19.447+09:00nginxのインストールからマルチドメインの設定まで(@CentOS)<div dir="ltr" style="text-align: left;" trbidi="on">
サイトを立ち上げる必要があったので、CentOSにnginxのインストールからマルチドメインの設定までの作業をした。今回はその時のメモ。(参考サイトは<a href="http://qiita.com/utano320/items/0c0d9b84a9a28525bcb9" target="_blank">ココ</a>と、<a href="http://d.hatena.ne.jp/hogesky/20120416/1334588838" target="_blank">ココ</a>と、<a href="http://vps-karuma.net/setting/nginx/1539/" target="_blank">ココ</a>)<br />
<div>
<br /></div>
<h3 style="text-align: left;">
■マルチドメインとは?</h3>
<div>
マルチドメインは1つのサーバ(IPアドレス)で、複数のドメインを管理できること。</div>
<div>
例えば、「aaa.comとbbb.comの2つドメインでそれぞれ のサイトを立ち上げたいけど、今のところそんなにアクセス数もないのでサイト毎にサーバを用意するのはリソース(≒お金)の無駄だなー」という時に、重宝する。</div>
<div>
マルチドメインは、Webサーバアプリケーション(ここではnginx)のバーチャルサーバ機能(※1)を利用して行う。</div>
<div>
nginx は、(ブラウザからの)HTTP リクエストヘッダの “Host”情報を読み取り、どのコンテンツを返すべきかを判定する(参考→<a href="http://nginx.org/en/docs/http/request_processing.html" target="_blank">nginx公式解説ページ</a>)(※2)。</div>
<div>
<br /></div>
<div>
<h3>
■作業環境</h3>
</div>
<div>
今回の作業環境は以下のとおり。</div>
<div>
<ul style="text-align: left;">
<li>サーバ: さくらインターネットのVPS</li>
<li>OS: CentOS 6</li>
<li>ドメイン:さくらインターネットであらかじめ2つのドメインを取得し、それぞれのドメインで上記VPSのIPアドレスへ紐づけの設定が完了している。</li>
</ul>
<br />
<ul style="text-align: left;">
</ul>
</div>
<div>
<h3>
■手順1(nginxのインストールまで)</h3>
</div>
<h4 style="text-align: left;">
▼CentOSに、nginx用のyumリポジトリを登録するRPMをインストール</h4>
<div>
<a href="http://nginx.org/en/linux_packages.html#stable" target="_blank">nginx公式ページ</a>で、CentOS 6 用のRPMのURLを調べて、以下のコマンドを実行する。</div>
<div style="background-color: #e3f2fb; border: 1px dotted #CCCCCC; padding: 5px;">
# rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm<br />
(ここで、http://~.noarch.rpmは、上記の公式ページで調べたRPMファイルのURL)
</div>
<div>
<br />
上記を実行したら、「/etc/yum.repos.d/nginx.repo」というファイルが作成されているはずなので、確認。<br />
<h4 style="text-align: left;">
▼yumでnginxをインストールし、動作確認</h4>
</div>
<div>
nginxをyumでインストールする。<br />
<div style="background-color: #e3f2fb; border: 1px dotted rgb(204, 204, 204); padding: 5px;">
# yum install nginx</div>
<div>
<br /></div>
</div>
<div>
<div>
<div>
インストール後、nginxを起動。<br />
<div style="background-color: #e3f2fb; border: 1px dotted rgb(204, 204, 204); padding: 5px;">
# /etc/init.d/nginx start</div>
<div>
<br /></div>
</div>
<div>
<div>
</div>
</div>
ブラウザからサーバのURL(※3)にアクセスしてみて、nginxのwelcomeページが表示されればOK。</div>
<div>
<div style="orphans: auto; text-align: left; text-indent: 0px; widows: auto;">
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'MS PGothic'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'MS PGothic'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<h3 style="text-align: left;">
■手順2(nginxのバーチャルサーバ機能の設定完了まで)</h3>
</div>
</div>
<div>
<h4 style="text-align: left;">
▼設定ファイルを置くためのディレクトリを作成</h4>
</div>
<div>
以下のコマンドを実行。</div>
<div>
<div style="background-color: #e3f2fb; border: 1px dotted rgb(204, 204, 204); padding: 5px;">
<div style="margin: 0px;">
# mkdir /etc/nginx/sites-available<br />
# mkdir /etc/nginx/sites-enable</div>
</div>
<div>
<div style="margin: 0px;">
<br /></div>
<div>
</div>
</div>
</div>
<div>
これから、運用する個々のドメイン用の設定ファイルを「sites-available」以下において、その設定ファイルを参照するシンボリックリンクを「sites-enable」以下に配置し、nginx自体はそのシンボリックリンクを参照するようにしていく(※4)。<br />
<div style="orphans: auto; text-align: left; text-indent: 0px; widows: auto;">
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'MS PGothic'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'MS PGothic'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<h4>
▼個々のドメイン用の設定ファイルを作成&配置</h4>
</div>
<div>
sites-availableディレクトリ以下に、それぞれのバーチャルホスト用の設定ファイルを作成する。ファイル名は「aaa.com」のようにドメイン名と同一にしたほうが運用しやすい。<br />
作成内容は下記の参照のこと。<br />
例えば「vi /etc/nginx/sites-available/aaa.com」 コマンドで以下の編集をする。</div>
<div>
<div style="background-color: #e3f2fb; border: 1px dotted rgb(204, 204, 204); padding: 5px;">
<div style="margin: 0px;">
# For aaa.com<br />
server {<br />
listen 80;<br />
server_name aaa.com www.aaa.com; #ドメイン名の指定。サブドメインも指定可。<br />
<br />
access_log /var/log/nginx/access.aaa.com.log; #アクセスログの保存先もドメイン毎に。<br />
<br />
location / { #コンテンツの置き場所も、ドメイン別に分けておく。<br />
root /usr/share/nginx/html/aaa.com;<br />
index index.html;<br />
}<br />
}</div>
</div>
<div>
<div style="margin: 0px;">
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'MS PGothic'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<div>
上記と同じものをバーチャルサーバをつくる分だけ作り配置する。(たとえばbbb.com用など)<br />
<br />
次に、ここで作った設定ファイルをsite-enableディレクトリ側から参照するシンボリックリンクをはる。</div>
<div>
<div style="background-color: #e3f2fb; border: 1px dotted rgb(204, 204, 204); padding: 5px;">
<div style="margin: 0px;">
# ln -s /etc/nginx/sites-available/aaa.com /etc/nginx/sites-enable/<br />
# ln -s /etc/nginx/sites-available/bbb.com /etc/nginx/sites-enable/</div>
</div>
<div>
<div>
</div>
</div>
</div>
<div>
<br /></div>
<h4 style="text-align: left;">
▼nginxが上記で作成した設定ファイルを参照するように設定。</h4>
<div>
<div>
viで「/etc/nginx/nginx.conf」に、</div>
<div>
<div>
<div style="background-color: #e3f2fb; border: 1px dotted rgb(204, 204, 204); padding: 5px;">
<div style="margin: 0px;">
include /etc/nginx/sites-enable/*;</div>
</div>
<div>
<div>
</div>
</div>
</div>
<div>
</div>
</div>
<div>
の行を加える。(他のinclude節の直後に配置しとけばよい)</div>
<div>
<br /></div>
</div>
<div>
<h4>
▼それぞれのドメイン用コンテンツを作成。</h4>
</div>
<div>
<div>
「site-available」以下に配置したドメイン毎の設定ファイル内でlocationのrootとして設定したディレクトリを作成。</div>
<div>
<div>
<div style="background-color: #e3f2fb; border: 1px dotted rgb(204, 204, 204); padding: 5px;">
<div style="margin: 0px;">
# mkdir /usr/share/nginx/html/aaa.com<br />
# mkdir /usr/share/nginx/html/bbb.com<span style="background-color: transparent;"> </span></div>
</div>
</div>
<div>
<br /></div>
</div>
</div>
<div>
作成後、それぞれのディレクトリ配下に、適当な「index.html」を作成し配置しておく。(あとで接続試験をするため)</div>
<div>
<br /></div>
<div>
<h4>
▼設定の確認→nginx再起動→接続試験</h4>
</div>
<div>
<div>
設定に不備がないかをテストツールでテストする。問題がなければ「test is successful」のような表示がされる。</div>
</div>
<div>
<div>
<div style="background-color: #e3f2fb; border: 1px dotted rgb(204, 204, 204); padding: 5px;">
<div style="margin: 0px;">
# /etc/init.d/nginx configtest<span style="background-color: transparent;"> </span></div>
</div>
</div>
<div>
<br /></div>
</div>
<div>
<div>
設定に問題がなければ、nginxを再起動。</div>
<div>
<div>
<div style="background-color: #e3f2fb; border: 1px dotted rgb(204, 204, 204); padding: 5px;">
<div style="margin: 0px;">
# /etc/init.d/nginx restart<span style="background-color: transparent;"> </span></div>
</div>
</div>
<div>
<br /></div>
</div>
</div>
<div>
<div>
<div>
再起動後、それぞれのドメイン(今回はaaa.com、bbb.com)にブラウザからアクセスし、それぞれ意図通りのコンテンツが表示されれればOK。</div>
</div>
</div>
<div>
<br />
<br />
以上。<br />
意外に簡単だったので、よかった。(<a href="http://vps-karuma.net/setting/nginx/1539/" target="_blank">ここ</a>に書いているようにデフォルトバーチャルホストを設定したほうが良いかもだけど、それは今後の課題ということで。)<br />
<br /></div>
</div>
</div>
</div>
</div>
</div>
<div>
<ul style="text-align: left;">
<li>(※1) apacheでも同じ機能があり、「バーチャルホスト機能」と呼んでる。</li>
<li>(※2) ちなみに、仕組み上HTTPリクエストヘッダに"Host"情報を入れないブラウザでアクセスされた場合には、上手く動かない。ただそのようなブラウザはよっぽど古いブラウザだけで、現在はほとんど、Host情報を入れるようになっている。</li>
<li>(※3) ドメイン名がまだない場合は、例えばhttp://xxx.xxx.xxx.xxxなど。ここでxxx.xxx.xxx.xxxはサーバのIPアドレス。</li>
<li>(※4) なぜシンボリックリンクで参照させるかというと、サイトを一時的に停止したい場合、sites-enable以下のシンボリックリンクを消すだけでOKになるという運用上のメリットがあるから。</li>
</ul>
</div>
<div>
<br /></div>
</div>
</div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-20840300457029969442014-02-11T15:31:00.002+09:002014-02-16T16:42:56.764+09:00行列の対角化とは何か?<div dir="ltr" style="text-align: left;" trbidi="on">
「<a href="http://www.amazon.co.jp/gp/product/4627849710/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=4627849710&linkCode=as2&tag=amitani-22">はじめてのパターン認識</a><img alt="" border="0" src="http://ir-jp.amazon-adsystem.com/e/ir?t=amitani-22&l=as2&o=9&a=4627849710" height="1" style="border: none !important; margin: 0px !important;" width="1" />」の観測データの無相関化の節を読んでいて、行列の対角化ってなんだっけ?という、そもそものところでつまづいたので(※1)、行列の対角化について、ここで少し整理しようと思う。<br />
<div>
<br /></div>
<div>
今回は純粋に線形代数学の話題に終始して、本来のデータの無相関化については、また後日書く予定。<br />
<br />
<h3 style="text-align: left;">
■対角化を理解するまでの道筋</h3>
<div>
すこし長くなるので、「行列の対角化とは何か?」を理解するための道筋を整理すると</div>
<div>
<ol style="text-align: left;">
<li>固有値と固有ベクトルの意味を理解する。</li>
<li>固有ベクトルを並べた変換行列の性質を理解する。</li>
<li>対角化操作を理解する。</li>
</ol>
</div>
<div>
になると思う。というわけでこの道筋に従って話しを進めようと思う。</div>
<div>
なお、ここでは話しの分かりやすさを優先するので、数学的な一般性(※2)はひとまずおいておいて、わかりやすいシチュエーションの話だけをしていきたいと思います。一般的な状況でのより詳しいことは<a href="http://minami106.web.fc2.com/math/linear_lecture.pdf" target="_blank">ここ(PDF)</a>を参照すると良いです。(上記、1、2の話題について、非常にわかりやすく整理&説明されています。)<br />
<br /></div>
<div>
<br /></div>
<div>
<h3>
■固有値と固有ベクトルの意味を理解する。</h3>
<div>
<h4 style="text-align: left;">
▼固有値と固有ベクトルの定義</h4>
<div>
まずは、固有値、固有ベクトルを定義をしておくと以下のとおり。</div>
<blockquote class="tr_bq">
任意の正方行列 \(A\) について, \(A \mathbf{v} = \lambda \mathbf{v}\)を満たす \(\lambda \) を\(A \) の固有値といい、\(\mathbf{v} \) を\(A \) の固有ベクトルという.</blockquote>
<div style="text-align: left;">
n次の正方行列にはn個の固有値とそれに対応した固有ベクトルを持つ(※3)。</div>
<h4>
▼固有値と固有ベクトルの意味</h4>
<div>
上記の定義だけだといまいちなので、これらが図形的に何を意味しているのかを少し説明しておく。</div>
<div>
一般にベクトル\(\mathbf{v} \) に行列\(A \)を作用させるということは、ベクトルを線形変換しそのベクトルの「方向」と「長さ」を変更する操作にあたる。</div>
<div>
<br /></div>
たとえば、<br />
行列\(A=\left(<br />
\begin{array}{cc}<br />
3 & 1 \\<br />
2 & 4 \\<br />
\end{array}<br />
\right)\)<br />
をベクトル \(\mathbf{v} = (5, 1)^T\) (下図:青)に作用させた場合、作用後のベクトルは\(A\mathbf{v} = (16, 14)^T\)(下図:赤)になる。行列を作用させることによって方向と長さが変更されたことがもわかる。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGDvqqHW5gl1QjkekiCEjUW7AdLKfC38CvR5fInn40NT6sRJ8Wcw5a1fO7zAjZFBZrv9oo5eaQGHnF_0hhOCB0lCwE6GYgmz6UkupcOWRHv7hyphenhyphen2PwBZEoRvV_K3B5pl0EH5SDV4WhNoT8/s1600/png.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGDvqqHW5gl1QjkekiCEjUW7AdLKfC38CvR5fInn40NT6sRJ8Wcw5a1fO7zAjZFBZrv9oo5eaQGHnF_0hhOCB0lCwE6GYgmz6UkupcOWRHv7hyphenhyphen2PwBZEoRvV_K3B5pl0EH5SDV4WhNoT8/s1600/png.png" height="220" width="320" /></a></div>
<br />
<br />
今回は2次元行列を考えているので、2次元の\(\mathbb{R}^2\)空間でのベクトルは(2つ特別なベクトルを除いて)どんなベクトルも上の例と同じように方向が変更される。<br />
<br />
その2つの特殊なベクトルが固有ベクトルであるわけだ。<br />
<br />
固有ベクトルの定義を見直すとわかるとおり、固有ベクトルに行列\(A \)を作用させても、元のベクトルの定数倍(固有値倍)にしかならない。つまり「方向が変更されない」のである。<br />
<br />
実際の例を見てみよう。行列\(A \)の固有値は、\(\lambda_1 = 5\), \(\lambda_1 = 2\)の2つであり、それに対応する固有ベクトルは、\(\mathbf{u}_1 = (1, 2)^T\), \(\mathbf{u}_2 = (1, -1)^T\)である(※4)。例えばそのうちの1つの固有ベクトル\((1,2)^T\)に行列\(A \)を作用させると\((5,10)^T=5(1,2)^T\)であり元のベクトルの固有値(定数)倍で方向は変わらないのである。下図はそれを図示したもので、青が行列\(A \)作用前、赤が作用後のベクトルとなっている。わざわざ図示するまでもないけれど、方向に変化がないことがわかる。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbbFVEDRLtXTFvYkNQ7TXIwkJFx2hdYHqxHZ7YSgfEG6pBH3Fj1YrWvm5VsHVvBCJG-SO4SiWl16KSy16h2dElMYtHkZPJQmwGSu6t8GVSUdrpl6aqEtt5pOXVOqDMjoY9Sbk1vhEN-8Q/s1600/same_dir.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbbFVEDRLtXTFvYkNQ7TXIwkJFx2hdYHqxHZ7YSgfEG6pBH3Fj1YrWvm5VsHVvBCJG-SO4SiWl16KSy16h2dElMYtHkZPJQmwGSu6t8GVSUdrpl6aqEtt5pOXVOqDMjoY9Sbk1vhEN-8Q/s1600/same_dir.png" height="223" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
\(\mathbf{x} = a_1 \mathbf{u}_1 + a_2 \mathbf{u}_2\)<br />
というように、固有ベクトルを線形結合することで、2次元\(\mathbb{R}^2\)空間の任意のベクトル\(\mathbf{x}\)が表現できることに注意すると、任意のベクトルに行列\(A \)を作用させるということは、<br />
\(A\mathbf{x} = a_1 A \mathbf{u}_1 + a_2 A \mathbf{u}_2 = a_1 \lambda_1 \mathbf{u}_1 + a_2 \lambda_2 \mathbf{u}_2\)<br />
であり、それぞれの固有ベクトル方向に固有値倍ずつ伸縮結果に他ならない。<br />
<br />
<h3>
■固有ベクトルを並べた変換行列の性質を理解する</h3>
<div>
行列Aに、一次独立なn個の固有ベクトルが存在し、それを並べた<br />
\(P=(\mathbf{u}_1, \cdot\cdot\cdot , \mathbf{u}_n)\)<br />
を考える。<br />
このとき、基底ベクトル \(\mathbf{e}_i (i = 1, 2, ..., n )\)に\(P\)を作用させると、<br />
\(P\mathbf{e}_i = \mathbf{u}_i\)<br />
と固有ベクトルに変換されることがわかる。<br />
結果、任意のベクトル<br />
\(\mathbf{x} = \sum_{i=1}^n a_n \mathbf{e}_i\)<br />
に\(P\)を作用させると<br />
\(P\mathbf{x} = P \sum_{i=1}^n a_n \mathbf{e}_i = \sum_{i=1}^n a_n P\mathbf{e}_i = \sum_{i=1}^n a_n \mathbf{u}_i \)<br />
<div>
と変換される。</div>
<br />
先述の具体的な行列を例に見ていく。<br />
<div>
固有値ベクトルを並べた変換行列\(P = (\mathbf{u}_1,\mathbf{u}_2)\)を考える。この行列を基底ベクトル、<br />
\(\mathbf{e}_1 = (1, 0)^T\),\(\mathbf{e}_2 = (0, 1)^T\)<br />
に作用させると、<br />
\(P\mathbf{e}_1 = (1, 2)^T = \mathbf{u}_1\), \(P\mathbf{e}_2 = (1, -1)^T = \mathbf{u}_2\)<br />
となり、基底を固有空間に移す行列になっていることがわかる。<br />
例えば、<br />
<div>
\(\mathbf{x} = (5, 1)^T = 5\mathbf{e}_1+ \mathbf{e}_2 \)</div>
<div>
に\(P\)を作用させると、</div>
<div>
\(P\mathbf{x} = 5\mathbf{u}_1+\mathbf{u}_2\)</div>
</div>
となる。<br />
<br />
<br />
<h3>
■対角化操作</h3>
<div>
</div>
上記のように、変換行列を書けることで、任意のベクトルを基底\(\mathbf{e}_i (i = 1, 2, ..., n )\)での表現から、行列Aの固有ベクトルの固有空間の表現に変換される。<br />
このような変換後、行列Aを作用させると\(\mathbf{u}_i\)は向きが変わらず、長さが \(\lambda_i\)倍になるだけ。<br />
\[AP\mathbf{x} = A \sum_{i=1}^n a_n \mathbf{u}_i = \sum_{i=1}^n \lambda_i a_i \mathbf{u}_i \]<br />
<div>
これにさらに\(P^{-1}\)を作用させると\(\mathbf{u}_i\)は元の\(\mathbf{e}_i\)に戻り、</div>
\[P^{-1}AP\mathbf{x} = \sum_{i=1}^n \lambda_i a_i P^{-1}\mathbf{u}_i = \sum_{i=1}^n \lambda_i a_i \mathbf{e}_i \ = D\mathbf{x}\]<br />
ここで、<br />
\[<br />
D = \left(<br />
\begin{array}{cccc}<br />
\lambda_1 & 0 & \cdots & 0 \\<br />
0 & \lambda_1 & \cdots & 0 \\<br />
\vdots & \vdots & \ddots & 0 \\<br />
0 & 0 & \cdots & \lambda_n<br />
\end{array}<br />
\right)<br />
\]<br />
<br />
となり、\(P^{-1}AP\)が対角化行列となるわけである。</div>
<div>
<br />
<br />
(追伸)<br />
ここで使った図はpython&matplotlibを使って描いた。そのソースは<a href="http://nbviewer.ipython.org/github/amitani-github/data-for-blog/blob/master/broccoli/ipython_notebooks/blog_note_20140211.ipynb" target="_blank">ここ</a>を参照のこと。<br />
<br /></div>
<ul style="text-align: left;">
<li>(※1)昔は、嫌というほど線形代数学を勉強したのに、情けない話だ・・・</li>
<li>(※2)固有値が重解になる場合はどうなんだ、とかそんな話。</li>
<li>(※3)固有値が重解を持つ場合などは、一見 n個よりも少ない固有値しかないようにみえることもあるが・・・。また、回転行列は実数の固有値はないが、複素数まで考えるとちゃんと固有値を持つ。</li>
<li>(※4)求め方はやはり<a href="http://minami106.web.fc2.com/math/linear_lecture.pdf" target="_blank">ここ(PDF)</a>が参考になる。</li>
<li>(※5)つまり、2つの固有ベクトルが2次元\(\mathbb{R}^2\)空間の基底であるということ。</li>
</ul>
</div>
</div>
<div>
<br /></div>
</div>
</div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0tag:blogger.com,1999:blog-4103242286980619951.post-24671058286170914402014-02-04T16:20:00.001+09:002019-04-12T06:45:16.942+09:00rpy2をインストールする。<div dir="ltr" style="text-align: left;" trbidi="on">
IPython NotebookからRを利用するためには、Rmagicという機能拡張を使えばいいとのことなのだけど、これがrpy2というライブラリを使うため、これをインストールしなくてはならない。<br />
折角なので、今回行ったインストール手順をまとめておく。<br />
<h3>
■インストール</h3>
<h4 style="text-align: left;">
▼前提</h4>
<div>
Windows7で、pythonとRはインストールされているものとする。</div>
<div>
<br /></div>
<div>
▼RのPATHを設定しておく。</div>
<div>
<br />
これをしないと・・・<br />
<ul style="text-align: left;">
<li>インストールの時に「Error: Tried to guess R's HOME but no R command in the PATH.」と、Rが見つからないよ!と怒られます。</li>
<li>pythonでモジュールをimportする際に、「RuntimeError: R_HOME not defined.」とか、「RuntimeError: R_USER not defined.」とか怒られます。</li>
</ul>
</div>
<div>
スタート>「コンピューター」を右クリック>プロパティ>左パネルの「システムの詳細設定」>環境変数 を開きます。その画面で次の3つを設定。<br />
<br />
<ul style="text-align: left;">
<li>ユーザー環境変数のPATHを編集し、R.exeのあるbinフォルダをセミコロンで区切って末尾に追記します。つまり「;C:\Program Files\R\R-2.15.3\bin」(←僕の環境の場合)を末尾に追加する。</li>
<li>システム環境変数で、以下のPATHを追加。</li>
<ul>
<li>変数名「R_HOME」、変数値「C:\Program Files\R\R-2.15.3」(←僕の環境の場合)</li>
<li>変数名「R_USER」、変数値「xxxx」(xxxxはWindowsのログイン名)</li>
</ul>
</ul>
</div>
<div>
<div>
<h4>
▼pipでインストール</h4>
</div>
</div>
<div>
上記で環境変数を指定した後、コマンドプロンプト(*1)を開き</div>
<div style="background-color: #e3f2fb; border: 1px dotted #CCCCCC; padding: 5px;">
$pip install rpy2
</div>
<div>
と打つ。簡単!</div>
<div>
<br /></div>
<div>
<br />
<h4>
▼pipでエラーが出る場合・・・</h4>
</div>
環境によっては、pipでインストールしようとしたら、<br />
<div style="background-color: #e3f2fb; border: 1px dotted rgb(204, 204, 204); padding: 5px;">
"C:\PROGRA~1\R\R-215~1.3\bin\R" CMD config --ldflags<br />
Invalid substring</div>
<br />
<div>
</div>
<br />
<div style="orphans: auto; text-align: left; text-indent: 0px; widows: auto;">
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'MS PGothic'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; margin: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
みたいなエラーが出る場合がある(*2)。</div>
<div style="margin: 0px;">
この場合は、<a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/#rpy2" target="_blank">この</a>ページの環境に合わせたバイナリ(僕の環境の場合はrpy2 2.3.9.win32 py2.7.exe)をダウンロードし、あとはダブルクリックでインストールすればよい模様(<a href="http://stackoverflow.com/questions/15311457/getting-error-in-installing-rpy2-on-windows" target="_blank">参考</a>)。</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'MS PGothic'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'MS PGothic'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
</div>
<h4 style="text-align: left;">
▼確認</h4>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'MS PGothic'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div>
コマンドプロンプトなりでpythonを起動して</div>
<div>
<div style="background-color: #e3f2fb; border: 1px dotted rgb(204, 204, 204); padding: 5px;">
import rpy2.robjects as robjects</div>
<div>
</div>
</div>
</div>
を打って、エラーとかでないと、とりあえずインストール成功!<br />
<br />
<h3 style="text-align: left;">
■Rmagic</h3>
<div>
rpy2をインストールしたら、IPython NotebookでRmagicを使ってRのコマンドが使えるようになる。</div>
<div>
使い方は<a href="http://nbviewer.ipython.org/github/ipython/ipython/blob/3607712653c66d63e0d7f13f073bde8c0f209ba8/docs/examples/notebooks/rmagic_extension.ipynb" target="_blank">ココ</a>が分かりやすい。</div>
<br />
<br />
<div>
(*1)Windows標準のコマンドプロントでもいいし、scipyスタックのanacondaを使ってる場合、「anaconda command prompt」でもいい。ただしどちらの場合も、環境変数の更新を行った場合には、プロンプトを開きなおさないと環境変数の設定変更が反映されないことに<span style="color: red;">注意</span>!(これでだいぶハマッた)<br />
<br />
(*2) 僕の職場のPCへのインストールはこれでハマる (+_+)。</div>
</div>
amitanihttp://www.blogger.com/profile/12311998459099814100noreply@blogger.com0