バナナでもわかる話

開設当初は計量経済学・統計学が専門の大学院生でした。今はデータを扱うお仕事をしています。統計学・経済学・投資理論・マーケティング等々に関する勉強・解説ブログ。ときどき趣味も。極力数式は使わずイメージで説明出来るよう心掛けていますが、時々暴走します。

画像認識始めました~手始めにRでスクラッチでフィルタリングしてみた~

なんか、最近自動運転だなんだと画像認識が流行りらしくて、私画像認識についてはあまり詳しくないので入門の為に買ってみました。

で、まだ全部は読んではいないのですが、とりあえず読んだ傍からスクラッチでコードを書いてみようかと思ってるわけです。

スポンサーリンク



空間フィルタリング

まず、何をするのかというと、画像認識をするためには色々画像から特徴を取り出したいというモチベがあるようで、でも特徴を取り出す前に元の画像だと細かすぎるというか、ざっくりいってしまうとノイズが多いので、画像を均すという処理をする必要があるようです。

その処理がフィルタリング


で、そのフィルタリングにもいっぱい種類があるとのことで説明してあったのですが、とりあえず手始めに平均化フィルタというものを試してみたいと思います。

平均化フィルタっていうのは何かというと、

画像データって縦横に色を示す値が並んだ行列のように表すことが出来るんですけど(正確には配列)

周りの色のデータと共に平均を取って均してやろう(平滑化,スムージング)と言う処理を取ります。

早速Rコード

画像の読み込みだけは流石にスクラッチではよくわからないというか、そんなとこで努力する意味も無いので、jpegパッケージで読み込みます。

install.packages("jpeg")
library(jpeg)
image=readJPEG("DSC_0004.JPG")

元画像DSC_0004.JPGは何かというと、この間記事であげたイグアナちゃんです。
f:id:bananarian:20181120002450p:plain


というわけで平均して均してノイズを取ります。

#平均を取る幅
k=1
image2=array(0,dim=c(dim(image)[1],dim(image)[2],3))
for(i in 1:(dim(image)[1])){
	for(j in 1:(dim(image)[2])){
		zzz=image[max(1,(i-k)):min(dim(image)[1],(i+k)),max(1,(j-k)):min(dim(image)[2],(j+k)),]
		image2[i,j,]=apply(zzz,3,mean)
}}

ということで均した結果
f:id:bananarian:20181120002846p:plain

均す前
f:id:bananarian:20181120002450p:plain

あんまわからないですかね。微妙に色薄くなってます笑
k=1だからあんまりわからないですね~
恐らくこの平均化する周辺の範囲を拡大することでどんどん荒い画像になっていくはずです。

ためしに5でもやってみます。

k=5
image3=array(0,dim=c(dim(image)[1],dim(image)[2],3))
for(i in 1:(dim(image)[1])){
	for(j in 1:(dim(image)[2])){
		zzz=image[max(1,(i-k)):min(dim(image)[1],(i+k)),max(1,(j-k)):min(dim(image)[2],(j+k)),]
		image3[i,j,]=apply(zzz,3,mean)
}}

均した結果
f:id:bananarian:20181120014508p:plain

均す前
f:id:bananarian:20181120002450p:plain

手のあたりとか見ると結構荒いというか滑らかになってるのがわかりますね。
あと顔のあたりとか。

こんな風に元の画像のノイズを取ってから処理する必要があるみたいですね。
次回はまた別のフィルタリングを試してみます。

人間の選択をモデル化するプロビット・ロジットモデルの違いと経済学的解釈法

今日は人間の選択をモデル化する方法について書いてみようと思います。


一応事前にプロビット・ロジットについてネット記事が無いか漁ってみたのですが、

・機械学習の文脈で説明されていることが多い
・プロビット・ロジットの選択基準が説明変数の観点から説明されていることが多い(実はもう一個ある)

ということで

「じゃあ私は経済学的な観点から定式化を行って、統計学的な観点からこのモデルの説明をして、モデルにおける2種類の選択基準に関して説明をすることで差別化して書いてみよう~」

なんて考えてみました。
それでは記事を書いていきます。


ちなみに、プロビット・ロジットや経済学の話はとりあえず良いから、この二つのモデルの違いだけ知りたい!という方は

↓下の方にあるこの見出しから読むと良い感じに理解できるかと。

プロビット・ロジットの特徴



スポンサーリンク


人間の選択とは

まず人間の選択について少し経済学の観点から考えます。
例えば今、夕食の献立を考えているとしてとりあえずザックリ「肉」か「魚」かみたいなものを選択したいとします。

人によっては「その日の気分」のみで決めるかもしれないし、とりあえずスーパーへ行ってみて「値段」を見て決めようと思うかもしれないし、はたまたスーパーで実際に見て「おいしそうな方」にしようと思うかもしれないし、今の基準を全て総合して決めるかもしれません。

とにかく人によって何かしらの選択の「基準」があって、その「基準」に従って

「今日は肉より魚だな」

とか決めているわけです。


この考え方は妥当でしょうか?

①「いやいや私は、どっちでも良いと思ってスーパーに赴いて先に目に入った方を取るから何も考えてないよ」
②「肉とか魚だから今の例が成り立つけど、例えば何か甘いものを食べたいなと思ってコンビニに行き、何も考えずにほとんどランダムに近い形でチョコレートを手に取り、買うことだってあるよ」

みたいな反応もあるかもしれません。

ただ、これは解釈の拡張次第でどうにでもなって
①は「一番初めに目に入ったものを買う」という基準に従って選択をした結果であり、
②は確かに何も考えて居なかったかもしれませんが、ということは最も手に取りやすい配置にあった商品が取られる可能性が高かったはずです。つまり無意識に配置によって選ばされていると考えれば「配置」という基準に従って選択をした結果です。


つまり、こんな風に人間の選択を考えると実際にその人が基準に従って選択をしているか否かに関わらず、柔軟に当てはめることが可能になります。


選択の定式化

さて、このままでは数式に出来そうにないのでもう少し考えてみます。
先ほどの選択で「肉より魚だな」と選ぶ時、人は何らかの基準に従って「肉を買った時の嬉しさよりも魚を買った時の嬉しさの方が大きいな」と思ったから魚を選んだと考えましょう。

"嬉しさ"と言ってしまうと多少語弊があるので"メリット"と言い換えてもらっても問題ありません。

この嬉しさ(メリット)は測ることは出来ませんが、各人が自分の頭の中で大きさを比べて、その大きい方を選んでいると考えます。
この嬉しさ(メリット)を経済学の用語で効用と呼びます。


肉を選ぶ際の効用を U_{肉},魚を選ぶ際の効用を U_{魚}とし、

「肉より魚を選んだ」というのを次のように表現します。

 U_{肉}< U_{魚}



そして、この効用の大きさ自体は分かりませんが、選んだ基準(価格や配置等々)を数値化することは可能です。

そこで回帰分析の要領で次のように考えてやろうというわけですね。



 U_{肉}=X' \beta_{肉} +\epsilon_{肉}
 U_{魚}=X' \beta_{魚} +\epsilon_{魚}

そんでもって U_{肉}< U_{魚}という式に放り込んでやれば

 X' \beta_{肉} +\epsilon_{肉}<X' \beta_{魚} +\epsilon_{魚}
つまり
 X' (\beta_{魚}-\beta_{肉}) +(\epsilon_{魚}-\epsilon_{肉})>0

よってこの式は
 X' \beta +\epsilon>0

と変形出来ました。この左側は回帰分析でよく見る形ですね。


ただ、このままでは回帰分析としては扱えません。だって Uの値はわからないわけですから。

そこで次のように考えます。

 U_{肉}< U_{魚} Y=1,
 U_{魚}< U_{肉} Y=0と表現することにします。

そして、 Xという情報(先ほどの価格等の基準)が与えられた時に Y=1を取る確率を Prob(Y=1|X)と書くことにすると

 Prob(Y=1|X)=Prob(X' \beta +\epsilon>0|X)


ですね。

ちなみにこれは次のように解釈することも出来ます。
 Y^*=X' \beta +\epsilonという線形関係を考えます。この時点では Y^*\in \mathcal{R}なので、

 Y^*≧0ならば Y=1
 Y^*<0ならば Y=0

つまり、実数範囲を取る潜在的な変数 Y^*が取る値に対して観測される変数 Y=0,1を結びつけるわけです。
統計や機械学習の文脈でこの話を学ぶ人はこちらの解釈の方が慣れてるかもしれませんね。

とにもかくにもこれでモデル化が出来ました。このプロセスが経済学的な観点から人間の選択を数式化するプロセスになります。



もっと背後のモデル

次に、個々の選択確率がわかったので、もっと背後にある確率を考えましょう。単純に考えると、0か1かという選択はベルヌーイ型の分布を考えるべきですよね。そこで次のような質量関数を考えます。

 f(y_i |X_i)=\pi_i^{y_i}(1-\pi_i)^{1-y_i}
 y_i=0,1

そしてこの \pi_iを先ほど考えた個々の選択確率に置き換えてやるわけです。
 \pi_i=Prob(Y_i=1|X_i)=Prob(X_i' \beta +\epsilon_i>0|X_i)


プロビット・ロジットモデル

ところで確率 Prob(Y=1|X)と確率 Prob(Y=0|X)はどうやって決めればよいでしょうか。

今のままだと漠然と Probとかいうよくわかんない記号でごまかしているにすぎませんよね。


そこでこの Probに対して、もう少し具体的な確率モデルを与えてやろうという方針が生まれ、そのモデルとしてプロビットモデル、ロジットモデルがあります。

それでは一つずつ見てみましょう。


プロビットモデル

別にロジットから説明しても良いんですけど、"プロビット"モデルの名付け親が日本人なので愛着をこめてこちらから説明します笑
先ほどの統計学的な解釈を思い出してみます。


 Y^*=X' \beta +\epsilonという線形関係を考えます。
この時点では Y^*\in \mathcal{R}なので、

 Y^*≧0ならば Y=1
 Y^*<0ならば Y=0

という話でした。線形回帰ではよく正規分布が考えられるので、プロビットでも正規分布を考えます。
使い勝手がよいので標準正規分布で考えましょう。つまり

 \epsilon ~Normal(0,1)

更に Y^*≧0とはつまり X' \beta +\epsilon≧0,

よって -X' \beta ≦\epsilonです。ということは

 -X' \beta ≦\epsilonならば Y=1
 -X' \beta >\epsilonならば Y=0

と書きなおすことが出来ます。
 \epsilonは標準正規分布に従うと仮定しているので図に表すとこんな感じ。

 -X' \beta ≦\epsilonならば Y=1
f:id:bananarian:20181115151037p:plain


この赤色部分を全部足してやれば Y=1の確率が出るよねということです。よって
 (標準正規分布の密度関数)=\phi(t)とおくことにすると

 Prob(Y=1|X)=\int_{-X'\beta}^{\infty}\phi(t)dt=1-\int_{-\infty}^{-X'\beta}\phi(t)dt

また、同様にして
 Prob(Y=0|X)=\int_{-\infty}^{-X'\beta}\phi(t)dt


これで分布による表現が出来ました。あとは先ほどのベルヌーイ型関数に放り込んで最尤法を行えば完了です。
ベイズの文脈で語るのであれば事前分布を設定して事後分布を見てやればおしまいです。

ロジットモデル

次、ロジットですね。こちらはどちらかというと数学的な扱いやすさから、よく使用されるモデルです。
 Prob(Y=1|X)=\frac{exp(X'\beta)}{1+exp(X'\beta)}

によって定義されます。これは何なんだというとロジスティック分布関数と呼ばれる分布です。少しマイナーですかね。


どういう点で数学的に扱いやすいかというと、オッズ比として解釈出来る点が強いです。
こちらのサイトさんのロジットの紹介がわかりやすかったので載せて置きます。是非参考にしてみてください。
ロジットとプロビットの使い分け - アドファイブ日記


※ちなみに、他にもモデルは存在します。記事下に補足として書いておくので興味のある方はご覧ください。


プロビット・ロジットの特徴

プロビットは標準正規分布を使っているので当たり前ですが、ロジットの方も左右対称になります。
というか、裾の重さを除いて標準正規分布とロジスティック分布はほぼ同じです。
実際-1.2から1.2の範囲においてこの二つの分布はほぼ同じ確率を弾きます。
ただ、ロジスティック関数の方が裾の重い分布となるのが特徴です。


「ほぼ同じならば、オッズ比を使えるロジットの方が扱いやすそうだし、ロジットの方がいいじゃ~ん。」

ということで考えるのが面倒な場面ではロジットを使う人が多かったりしますが、一応しっかり考えると次の二つの観点からモデル選択を行う必要があります。

①使っている基準(独立変数、Xのこと)の取りうる値の範囲が広いか否か(変数が多くある場合は、そのうち特に重要なものを見る)

②0,1の選択(従属変数、Yのこと)のデータでどちらか片方のデータがほとんど無いような場合



①はよく言われる話で、先ほど載せたサイトさんでも"サチる"といった言葉で説明していました。
要はロジットの方が裾が重いので、X'\betaがメチャメチャ大きい値を取った時の Y=1を取る確率、小さい値を取ったりした時の Y=0を取る確率がある程度大きいく、独立変数が広い範囲で動く場合はロジットを使うのが良いということです。
イメージとしては0から1へのシフトが緩やかって感じですね。


で、今回説明したかったのが②の方で、

例えば10000人のデータを取ってみて Y=0を選んでいる人が20人とかしかいなかったーなんてデータがあったとします。

この時、もしプロビットの方を適用しようとすると、標準正規分布の両端はほぼゼロに近いのでプロビットは使えません
これは別の記事で説明した「正規分布を適用するモデリングでは、外れ値(?)のようなデータに弱い」という話に似ていますね。

ただ、外れ値モデリングの話でもやりましたが、突飛な特徴がなく、0も1も万遍なくあるならより無難な分布を考慮できるという背景からプロビットを使った方が良さそうです。


プロビット・ロジットの使い分け

よって、次のような事が言えるかと思います。

まず、 Y=0, Y=1の内どちらかのデータが極端に少ない場合はロジットを考慮に入れ、
更に(重要な)説明変数の取りうる値の範囲が広いなら、ロジット使用が濃厚。

また、モデルを使用した後にオッズ比を考えたいような場面でもロジットが良い。

上の状況に該当しなければ、無難にプロビットの方が良い。


もし、他にも使い分けが考えられるよーという方がいれば是非コメントを頂けるとありがたいです。


オマケ

ちなみに、上の話では次のような疑問に答えていません。

対称性

ロジットもプロビットも左右対称な分布になっていました。この仮定は妥当なのか?という疑問があるかもしれません。そんな時はこのモデル

ガンベル分布を使ったガンベルモデルです。
 Prob(Y=1|X)=exp(-exp(-X'\beta))

ちなみに補対数対数モデルというのもあります。
 Prob(Y=1|X)=1-exp(exp(X'\beta))

独立性

プロビットもロジットも各選択が独立だという仮定を置いて、同時分布では各確率の積を取っているが、誤差の共分散は本当にゼロなのか?という疑問もあり得ます。そんな時は誤差を多変量に拡張した、多変量プロビットモデルというモデルがあります。

多項選択

今回は「肉」と「魚」の2種類の選択だったから Y=0, Y=1のモデルで良かったけど、サーロインステーキか焼肉か焼き鳥かケバブかどれにするみたいな選択だったらどうするんだという疑問も考えられますね。

そんな時はベルヌーイ型を多項分布に拡張し、多項プロビットモデル・多項ロジットモデルを考えたりします。

リッジ回帰(ridge)で解決できる多重共線性問題と注意すべき点

リッジ回帰の記事でも書こうと思って、キーワード検索で「リッジ回帰」と打ち込んでみたら、

「リッジ回帰 多重共線性」

という検索候補が出て来たのでちょっとかいてみることにしました。

多重共線性記事について書いていたところだったので、丁度いいですね。
多重共線性とは~回避の方法として相関を見るだけでは..... - バナナでもわかる話
多重共線性を回避するためのVIF基準の解釈について - バナナでもわかる話


スポンサーリンク



先に結論

先に私の結論ですが、

「このあたりの議論は、やりたいことが機械学習なのか、統計学なのかで対応が異なる」


という結論になりました。


多重共線性問題

ここでまず強い多重共線性と弱い多重共線性について定義しておこうと思います。

多重共線性には、大きく分けて2種類あって、
①説明変数間に完全な線形関係があり、従来の線形回帰分析では解が求まらないケース
②説明変数間に線形関係があるものの、確率的な誤差が混じり、一応解は求まるが、推定量の分散が大きくなってしまうケース、特に不偏推定量の場合、分散は推定量の質に直結するので、これは問題です。

①の、そもそも解が求まらない状況を強い多重共線性

②の、推定結果が不安定になる状況を弱い多重共線性

と呼んでおきます。
詳しくは過去記事にて、もう少し詳しく説明しています。
多重共線性とは~回避の方法として相関を見るだけでは..... - バナナでもわかる話


リッジ回帰と過去記事

検索してて見つけたのは次のような記事です。
強い意味での多重共線性問題とリッジ回帰の関係がわかりやすく説明されています。
リッジ回帰による多重共線性の問題回避について - 統計学と疫学と時々、助教生活

この方が一番わかりやすく短めに記事にされていたので、載せさせていただきました。


強い意味での多重共線性問題が発生している際はそもそも解が不定になるので、何かしらの意味で推定結果を求めることの出来るリッジ回帰は確かに有用そうです。

ただ、この記事の内容自体は正しいとは思うのですが、①の話しかしていません。②はどうでしょう。
そして、仮に②もうまく解決できたとして、このリッジ回帰はどういう点で有用なのでしょう。



私が感じた疑問


確かにridge回帰は解を計算する際の固有値が0より大きくなるため、解は求まるわけですが、

その解がどういう意味で適当な解なのかは理解して使わなければいけないと思います。

これは、恐らく分析の文脈が「機械学習」なのか「統計学」なのかによると思っていて、


機械学習における線形回帰の目的は非説明変数の予測であって、
パラメータの正確な推定値ではなく、MSE(平均二乗誤差)の小ささが重要になります。

リッジ回帰では、コストパラメータ \lambdaを使って各変数の影響を均等に潰します。

これにより、例えば外れ値の影響も潰れるため、もし外れ値があった場合に変な予測をする過学習を回避することが可能になります。
※必ずしも有効とは限らない。言うてリッジ回帰では外れ値の影響を潰しきれないことも知られている



また、機械学習の文脈では、②の意味での多重共線性は正直致命的な問題ではありません。要は良い予測が出来ればよいわけなので、 \lambdaでうまく潰せて、結果を出力出来て、更に良い予測(例えばMSEや予測誤差が小さい)が出来れば問題ないわけです。



統計学における線形回帰の目的の一つには非説明変数に与える説明変数の影響の推定もあるため、パラメータの推定値も重要になります。
よって、この文脈での多重共線性は①は当然のことながら②も重要になります。

更にリッジ回帰を使って値は出せても推定値にバイアスが出てしまっては、解釈が難しくなりそうです。一致性を備えて、サンプルサイズが大きい場合しかまともに解釈出来なさそうです。


つまり、ネット上の記事をあさっていて思った感想として、

確かに①の問題を解決出来るという点で、機械学習の文脈であればリッジ回帰は有用そうだが、統計学の文脈で語るなら②の意味での多重共線性も解決して、なおかつバイアスが小さい状態が望ましい。

そう思うと、統計学の文脈においては、わざわざリッジ回帰を持ち出さずとも、他の対応法を取れば良いわけで

「リッジ回帰で多重共線性を解消できるよー」

という触れ込みは、統計学と機械学習の区別のない初心者相手には少々危ないというか、誤解を招く恐れがあるのではと思いました。



リッジ回帰による①の意味での多重共線性の解決

①の状態の説明変数を用意して、実験してみましょう。

X1=as.matrix(sample(1:1000,100,replace=TRUE))
X2=as.matrix(sample(1:1000,100,replace=TRUE))
X3=0.8*X1

X=cbind(X1,X2)
X=cbind(X,X3)
Y=1.4+0.9*X1+0.01*X2+0.5*X3+rnorm(100,0,1)

 X_1 X_3が従属関係にあるため、従来の回帰分析では当然解は求まりません。試しに、線形回帰分析を行う関数lmを使って、回帰分析してみます。

> lm(Y~X)

Call:
lm(formula = Y ~ X)

Coefficients:
(Intercept)           X1           X2           X3  
    1.49489      1.29965      0.01015           NA  

内部でどういう処理をしているのかわかりませんが、まあとにかく X_3の部分はNAになりました。

恐らく不定になり、計算が出来なくなったため、 X_3を除いて回帰してくれたんだと思います。
実際、 X_1の係数は 0.9+0.5*0.8=1.3に近い値をとっています。




同じデータにリッジ回帰をやってみましょう。
コストパラメータ \lambdaを選択するのが面倒なので、今回は0から1000まで0.1刻みで全部出力してプロットしてみます。

とりあえずリッジ回帰の各推定値を出力する関数を作成します。

ridge=function(X,y,lambda){
	n=nrow(X);
	p=ncol(X);
	X=as.matrix(X);
	x.bar=array(dim=p);
	for(j in 1:p){
		x.bar[j]=mean(X[,j]);
	}
	for(j in 1:p){
		X[,j]=X[,j]-x.bar[j];
	}
	y=as.vector(y);
	y.bar=mean(y);
	y=y-y.bar;
	beta=as.vector(solve(t(X)%*%X+n*lambda*diag(p))%*%t(X)%*%y)
	beta.0=y.bar-x.bar%*%beta;
	return(list(beta=beta,beta.0=beta.0))
}

パラメータを変化させて、値を出してみます。

pl1=vector()
pl2=vector()
pl3=vector()
for(lambda in seq(1,1000,0.1)){
	res=ridge(X,Y,lambda)
	pl1[which(seq(1,1000,0.1)==lambda)]=res$beta[1]
	pl2[which(seq(1,1000,0.1)==lambda)]=res$beta[2]
	pl3[which(seq(1,1000,0.1)==lambda)]=res$beta[3]
}

par(mfcol=c(2,2))
plot(seq(1,1000,0.1),type="l",pl1,xlab="lambda",ylab="推定値",main="beta1")
plot(seq(1,1000,0.1),type="l",pl2,xlab="lambda",ylab="推定値",main="beta2")
plot(seq(1,1000,0.1),type="l",pl3,xlab="lambda",ylab="推定値",main="beta3")

f:id:bananarian:20181027200627p:plain

 \lambdaが大きくなると値がどんどん小さくなっています。

確かに不定にはなっていませんが....値はどうでしょう。元の値と比べて随分離れた値を取っていませんか。
これは、コストパラメータによって値が潰れている証拠です。



以上のことから、確かに値が不定になる問題は解決できたけども、統計学の意味での推定に、積極的に用いるべきかは疑問です。
確かにチューニング次第でMSEの点で最小二乗法より優れた解を導くことは出来るとは思いますが、説明変数を除いて実行したlmの方がバイアスが無く、実際近い値が出て来ています。



②の意味での多重共線性とリッジ回帰

改めてデータを作ってみます。

X1=as.matrix(sample(1:1000,100,replace=TRUE))
X2=as.matrix(sample(1:1000,100,replace=TRUE))
X3=0.8*X1+rnorm(100,0,1)

X=cbind(X1,X2)
X=cbind(X,X3)

Y=1.4+0.9*X1+0.01*X2+0.5*X3+rnorm(100,0,1)


線形回帰をやってみます。

> lm(Y~X)

Call:
lm(formula = Y ~ X)

Coefficients:
(Intercept)           X1           X2           X3  
   1.827952     0.995931     0.009426     0.379831  

不定にはなっていませんね。ただ、推定値の値が大きくはずれていますね(偶然の可能性もありますが)。
弱い多重共線性によって、分散が大きくなった結果と考えるのが自然でしょう。


ではリッジをやってみます。

pl1=vector()
pl2=vector()
pl3=vector()
for(lambda in seq(1,1000,0.1)){
	res=ridge(X,Y,lambda)
	pl1[which(seq(1,1000,0.1)==lambda)]=res$beta[1]
	pl2[which(seq(1,1000,0.1)==lambda)]=res$beta[2]
	pl3[which(seq(1,1000,0.1)==lambda)]=res$beta[3]
}

f:id:bananarian:20181027201520p:plain

何やら値が収束していますが、よくよく見ていただきたいのは、ちょっと本来の値より離れた場所で収束していますね。やはりコストパラメータでバイアスがかかった結果、本来の値と少しずれたところの値をとっています。

それでも、しっかりパラメータチューニングを行えば、MSEの点では良い推定量と言えるわけですが、biasの点ではやはり怪しいかなとは思います。
それならば説明変数の片方を取り除いたりした方が安心できる結果が得られそうです。



結論

というわけで、多重共線性はリッジ回帰で解決できると言ってしまうと、少々誤解を招く恐れがあると私は考えています。

機械学習の文脈で回帰を行う場合に、多重共線性が発生した場合はリッジ回帰を使うのがよい

統計学の文脈であれば、説明変数を取り除いたり、サンプルサイズを増やした方が無難なのでは?

ということも理解しておく必要がありそうです。



この辺の話も、詳しい方からすると自明な話なのかもしれませんが、初心者目線であればあるほど、

「そうか!多重共線性にはリッジ回帰か!!」

と処方箋的に使う人が多そうなので、記事にさせていただきました。

『AIアルゴリズムマーケティング 自動化のための機械学習/経済モデル』が個人的にとても面白かった

最近買った

AIアルゴリズムマーケティング 自動化のための機械学習/経済モデル、ベストプラクティス、アーキテクチャ 

 

という本がメチャメチャ面白かったので、紹介します。

ちなみに下の本です。

 

 この本の概要

最新のマーケティングサイエンスのトピックを「統計学」「機械学習」「経済学」「経営学」「最適化」等様々な側面から総合的に紹介しています。

そんな本なので、メチャメチャ前提知識があると思いきや、必要最低限の前提知識を初めに全部解説してくれます。

 

特に、この本は「自動化」「実用性」という点にも強いこだわりを持っており、これらの手法を総合的に活用し、ではどう実用に活かすか、どのような点で「自動化」するのかを懇切丁寧に解説してくれています。

 

これ一冊読めば、マーケティングのみならず機械学習、統計学、経済学、経営学の基礎までまとめて身につくお得本かなと個人的には思います。

 

スポンサーリンク

 

個人的に特に気に入った点

正直、統計×経営学本、機械学習×経営学本ならいっぱいあるんです。ネットにもいっぱい転がっているし、なんなら一部のトピックであればこのブログでも書いています。

 

この本の凄い所は、統計×機械学習×経営学×経済学本であるという点です。

個人的に、特にミクロ経済学・計量経済学はもっともっと経営に活かされて良いと思っているので、このような実用的な本に経済学の利用例が載っているのはとても嬉しい限りです。

 

 

数式に抵抗の無い方であれば、統計・機械学習・経営・経済全て無知の方でもスラスラ読めます。

 

数式に抵抗のある方でも、数式読み飛ばしで、特にマーケティングと機械学習がどう活かせるのかを雰囲気で知ることが出来ます。

 

 

こんな方にお勧め

 

・身近な例から機械学習・AIを学びたい人

・最新のマーケティングがどういうものなのか学びたい人

・機械学習や統計学・経済学がどうマーケティングに活かせるか知りたい人

・ビジネスデータをどう活かすべきか知りたい人

・マーケティング意思決定の自動化に関心がある人

・経済学の実用性を知りたい人

 

このどれかに当てはまれば、きっとこの本は楽しめるかと!

 

 

 

こんな良書なかなか無いなあ~と本当に感動しました。

また今度もう一周しようと思います。

 

皆さんも是非是非気軽に読んでみてください!

 

 

機械学習を使ったデータリサーチコンサルって難しそうだなって思った

今日は色々用事があるので、軽めに思ったことを記事にしておきます。

統計・機械学習って結構便利で万能みたいな印象が多分まだまだ世の中にあって、人工知能ブーム減退期ではあるものの、未だ機械学習に対する万能感は世に根強いのかなと思っています。

 

 

で、そんな統計・機械学習の手法ってどういう所で活用するのかっていうと、

アカデミックな世界なら当然研究や実験

 

ビジネスの世界であれば、様々活用場面があるわけですが、活用方式に恐らく違いがあって、自社にデータサイエンティストを持っている企業なら自社で実装。持っていない企業であれば外注を依頼したり。あと、リサーチャーやリサーチコンサルの方がクライアント企業に実装を提案する。

 

アカデミアでの研究や実験、企業の自社実装等であれば、用法用量を守って(!?)正しくお使いくださいという話になるわけなんですけど、

 

外注したり、クライアントに実装を提案する場合って結構多くの障壁があるんじゃないかなあと思いました。

 

スポンサーリンク

 

 

 

機械学習の難しさ

機械学習って、基本的には「既存のデータで一回解析して終わり」ってわけじゃないんです。

(統計学を用いた場合もそういう状況は起こりうるわけですが)

 

恐らく、クライアントに提案する場合は最低限、

 

「今回の結果はどれくらいの期間運用が可能で」、

 

所謂「メンテナンスをどれくらいの期間で行うか」、

 

そしてそのうえで「現状の正答率がどの程度」で、

 

「その正答率はどういうデータを使って検証したのか」

 

を言う必要があるんじゃないかなあと思うわけです。

そうなると、自社に機械学習運用技術を持ち合わせていない企業相手だと、実装提案以前に、

 

何故機械学習は運用期間があって、どういうメンテナンスを行う必要があり、その手法はどのように行うのかを全て丁寧に説明する必要が生じるなあ。

 

ということにまず気付き。

 

 

機械学習実装技術を備えていない企業に機械学習の実装を支援するって、もしかしてメチャメチャハードル高いのでは?と思った次第です。

 

システムとかだとメンテナンスの外注を請け負っているITコンサルタントの方々がいたりしますよね。データサイエンティストもそんな感じなんでしょうかね。

 

 

またデータリサーチ系のコンサルタントだと、機械学習を使わずともビジネスソリューションに関する提案って行えることが多いと思うわけですが、

 

その一方で、もし機械学習の実装まで提案して、それがクライアントさんに採用されて、じゃあ実装したいから機械学習に関する実装支援やメンテ支援もお願いしたいと言われたら、追加で売り上げが増えるわけじゃないですか。

 

それなら、極力機械学習を使った方が、受注が増えて会社が潤うわけだから、使っても使わなくてもいい場面では実装提案までしちゃおう~とか思っちゃったりしないのかな~と思えてきて。

 

また一方で、実装まで提案するとクライアントさんに納得してもらえないような場合もあったりするのかな~なんてのも考えてみたり。

 

なんかタイトルはデータリサーチコンサルの話だったのに、普通に機械学習の外注の話も混ざってしっちゃかめっちゃになってしまったような。まあいいか。

 

 

その辺ビジネスサイドはどうやって解決しているのだろう。

データサイエンティスト系のインターンにも、ちょっと参加してみようかなあ。

 

 

【AIに対する誤解】人工知能に代替される職業とされない職業

最近話題ですね。人工知能

人工知能って、その時代その時代で、意味合いが変わっていくみたいで、


一昔前はグーグル検索のことを「人工知能」なんて呼んでいた時代もありました。

今の人工知能(AI)ブームも、そんな感じで、ブームが過ぎれば

「あれが、人工知能?えー、何かイメージと違うねー」

と言われるようになるんじゃないかなあと思って見ております。



さて、先ほどTwitterを見ていたら、こんな感じのツイートが流れてきて、ちょっと気になりました。



「医者とか弁護士とか会計士といった、大量の知識を必要とする職業は全て人工知能(AI)によって無くなるはずだ」



ぼく個人としては、「えー、むしろ最もAIに取って代わられることのない職業だと思うけどなあ」と思っていますが、どうやらそういったイメージを持っていない方もいるみたいなので、記事にまとめてみました。


スポンサーリンク




今の時代に言われているところのAI

今騒がれているところのAIは、どうやら話を聞いている限り次のようなものを指すようです。


機械学習やディープラーニング、その他高度なITテクノロジーを利用して完成した便利なサービスのことをAIと呼び、文脈次第ではそれらを応用したロボットも含む



何やら色々なものを含んで概念だけが膨張し、一人歩きしている印象もあるため、色々思うところのある方もいるでしょうが、とりあえず、世間一般のイメージに合わせて広めに定義しておきます



AIに対する一番の誤解

よく、「AIが決めた」とか「AIが発見した」とか「AIが予測した」といった言説が多いため、一般の方々がよく誤解していらっしゃるんですが


現状AIと言われているテクノロジーは自律的に意思決定をしているわけでも、何か物を考えているわけでもありません。



誤解を恐れずに大雑把に言ってしまえば

既存のデータをフル活用して、分類したり仕訳したりしているだけです。


「でもその分類や仕訳の結果として、予測をしているんなら一緒でしょう?」

と言う方もいらっしゃるかもしれませんが、全く違うということを頭に入れておいてください。



AIが最も苦手なもの

AIは確かにあるアルゴリズムに従って情報を分類・仕訳し、一定の結果を出力します。

そういう作業は確かに得意です。


しかし、その分類理由や、仕訳の意図を説明したり、他者に説得する術は持ち合わせていませんし、仮に知識のある人間がそのAIのアルゴリズムをじっくり眺めたとしても、


AIの意図なんてものはわかりません。


だってAIは意図も何も持っていないのだもの。


よって、何か人を説得したり、人に説明をしたり、とにかく人間同士の合意形成をはかる職種や、人間に納得感を与えるような職種は現状のAIと言われるテクノロジーでは代替出来ません。



つまり、会計士や弁護士や医者はその辺にモロ直撃するため、効率化されるだけで、代替はされません。



AIに代替される恐れのある職種

AIに代替されうる職種は、むしろ次のような性質を持つ職業ではないかと考えます。


・何も考えずとも手続きさえ覚えれば出来る、パターン化された職種
他者に対して安心感や納得感を与える必要のない職種


パターン化された職種が代替されるという言説は多いですが、今回特に声を大にして言いたいのは二つめのやつです。

多少パターン化されていても、他者に対して安心感や納得感を与える必要が伴う職種は現状のAIでは代替できません。



だってよく考えてみてほしいんですけど、



あなたが冤罪事件に巻き込まれたとして、

「なんか理由はよくわからないけど、AIが死刑って結論下したからあなたは死刑です。」


って言われて納得出来ますか?

「いやいやいやいや。訳が分からないから、もっと理由を説明しろ。」

ってなるんじゃないですか?そういうことです。

【初心者向け】SVMのパラメタチューニング

前回ソフトマージンサポートベクターマシンの話をして、ラディアルカーネルにはパラメータが2つあるというところまでやりました。
bananarian.hatenablog.com


前回はパラメータをいじって、極端な値の場合は、マズそうだといったことを確認して終わったわけですが、結局どんな値を使えばいいのでしょうか。今回はそれについてやっていきます。

スポンサーリンク



チューニング

前回のようにパラメータの値を変化させて、どんな値が適切かを見る作業を、機械学習の用語でパラメタのチューニングと呼びます。

前回は手作業で値を変化させたため、少しの値しか確認できませんでしたが、要はこの作業をコンピュータに任せてしまえば、もっとたくさんの候補から最適なものを決定することが出来ますね。


コンピュータが評価を行うには、まず「どんな性質を持つパラメータが適当か」ということを定義しておかなければなりません。
この評価基準がイマイチだとあまり良い結果は期待できないわけですが、今回はパッケージで簡単にやる方法をお伝えしますので、


誤判別率(どれくらいミスったか)


を基準に各パラメータの値を評価していきます。


ラディアルカーネル確認

ラディアルカーネルは二つのパラメータを持つのでした。

コストパラメータ:C
カーネルパラメータ: \gamma


Cは罰則です。この値が大きいほどミスを認めない分類器になります。
 \gammaは複雑さに関するパラメータです。



使うデータを作る

仮のデータセットを作ります。

#e1071パッケージを使う
library(e1071)
#標準正規分布に従うデータを200×2だけ2列分生成
x=matrix(rnorm(200*2), ncol=2);
#最初の150個のデータを+2だけずらす
x[1:150,]=x[1:150,]+2;
#次の50個のデータを-2だけずらす
x[151:200,]=x[151:200,]-2
#+2ずらしたものを1,-2ずらしたものを2と名前を付ける
y=c(rep(1,150), rep(2,50));
#データの生成
dat=data.frame(x=x,y=as.factor(y))
#100個適当に取り出して訓練データとする
train=sample(200,100)
train_dat=dat[train,]

以上、適当に乱数を発生させたあとに1,2でわけるために2だけずらし、そこから訓練データを適当にとってきました。


ブートストラップ法

元のサンプルを母集団に見立てて、そこからリサンプリングを行うことをブートストラップ法と呼びます。
要はこんな感じです。

f:id:bananarian:20180910203922p:plain


これを利用してサンプルサイズ \bar{n}のブートストラップ標本をB個取り出し、各ブートストラップ標本における誤判別率を出し、誤判別率の平均を取ることで、平均値が最小になるようなパラメータの組を採用するというものを考えます。



これは普通にコードを書こうとすると面倒なわけですが、e1071パッケージのtune.svm関数で簡単に出来ちゃいます。
そこで \bar{n}=(データ数の9割), B=400として試してみます。

model=tune.svm(y~., data=train_dat, kernel ="radial", 
gamma=10^(-10:-5),cost=10^(1:10),
tunecontrol=tune.control(sampling="boot",nboot=400,boot.size=9/10),best.model)
summary(model)

こんな感じでベストなパラメータが見つかります。

- best parameters:
 gamma  cost
 1e-09 1e+08
- best performance: 0 

本来ならば、チューニングは1回で済ますことなく、範囲を絞っていって何度も行うべきなのですが、とりあえず今回は1回でやめておきます。


というわけでgamma=0.0000001,cost=10000000が最適であるという結果になります。ちなみにベストパフォーマンスとは、要は今回はミスが少ない方が良いということだったわけで、誤判別率が表示されています。今回は完全に分離可能だったようで、ミスなく分離できているようです。まあ人工的につくったものなんでそりゃそうですよね。


クロスバリデーション(CV)

データの一部を抜き取って、残ったものを訓練データとして利用する方法をクロスバリデーションと呼びます。この方法であれば、訓練データと検証データに分離することが難しいような少なめのデータであってもチューニングを行うことが出来ますね


今回は1行消去CVを利用します。コードは次の通りです。

model=tune.svm(y~., data=train_dat, kernel ="radial", 
gamma=10^(-10:-5),cost=10^(1:10),
tunecontrol=tune.control(sampling="cross",cross=length(train)),best.model)
summary(model)
- best parameters:
 gamma cost
 1e-05 1000

- best performance: 0 


結果からgamma=0.0001,cost=1000が良いということがわかりました。


テストデータを使ってうまくいくか試す

クロスバリデーションから得られたチューニングパラメータを使って、テストデータに対して分類を行ってみましょう。

#テストデータの用意
test_dat=dat[-train,]
#トレーニングデータとチューニングパラメータでモデルを用意
model=svm(y~., data=train_dat, kernel ="radial",gamma=0.00005,cost=1000,probability=TRUE)
#テストデータに対して適用してみる
test_pred=predict(model,newdata=test_dat,probability=TRUE)
#判別がうまくいったかtable関数で確認
table(test_dat[,3],test_pred)
   test_pred
     1  2
  1 77  0
  2  0 23

ミスなく分類できていますね。


まとめ

このように、パラメタチューニングを行って、テストデータで検証するというプロセスが予測においては不可欠になります。
また、今回はミス率0ですが、これは人工データだから発生する現象であって、普通はこんなことはありえません。むしろ何か怪しいと思うようにした方が無難です。

【初心者向け】ソフトマージンSVMの実装

前回まででSVMの導入と計算方法は終わりました。

SVMの導入
bananarian.hatenablog.com


最適化問題を解く話
bananarian.hatenablog.com


しかし、前回までは頑なに
データをきれいに線形に分類できる、線形分離可能という仮定を置いていました。
これをハードマージンと呼びます。

ただ実際のデータはそんなにきれいな形をしていません。多少のミスくらいは許容してやる分類器を考えたって問題なさそうです。

この多少のミスは許すSVMをソフトマージンと呼びます。

今回はソフトマージンSVMの内、ラディアルカーネルSVMの実装についての話をします。


スポンサーリンク



ラディアルカーネルSVMのパラメータ

コストパラメータ:C
カーネルパラメータ: \gamma

の二つがあります。これについてですが、

Cは罰則です。この値が大きいほどミスを認めない分類器になります。
 \gammaは複雑さに関するパラメータです。この値が大きいほど複雑な形で分類できます。小さいと前説明した通りの直線になります。


パラメータを変えて試してみる

では試しにRで実装して何が起こっているか確認してみます。

まず、試すために仮のデータセットを作ります。

#e1071パッケージを使う
library(e1071)
#標準正規分布に従うデータを200×2だけ2列分生成
x=matrix(rnorm(200*2), ncol=2);
#最初の150個のデータを+2だけずらす
x[1:150,]=x[1:150,]+2;
#次の50個のデータを-2だけずらす
x[151:200,]=x[151:200,]-2
#+2ずらしたものを1,-2ずらしたものを2と名前を付ける
y=c(rep(1,150), rep(2,50));
#データの生成
dat=data.frame(x=x,y=as.factor(y))
plot(x, col=y)

f:id:bananarian:20180903022541p:plain


ラディアルカーネルSVMをこれに試してみます。
C=1, \gamma=1で分類してみます。

#100個適当に取り出して訓練データとする
train=sample(200,100)
#e1071パッケージのsvm関数を使う
svmfit=svm(y~., data=dat[train,], kernel ="radial", gamma=1,cost=1)
plot(svmfit, dat[train,])

f:id:bananarian:20180903022153p:plain

ちなみに×印はSVMを引くにあたって利用した境界に近い点です。これをサポートベクターと呼びます。
多少のミスを許したうえで赤いやつは赤いグループに分類できています。

ちなみに、 \gamma=10に変えてみるとこんな感じです。複雑な分類器が出来ています。
f:id:bananarian:20180903023156p:plain

ここからC=0.01にしてみると次のようになります。
f:id:bananarian:20180903023332p:plain
罰則が全く機能せず、全て青の領域に入ってしまっていることが分かります。


 \gamma=100,C=1にしてみました。これはやりすぎですね。ここまでいくと過適合しすぎていて、新しいデータを加えた時に正しく分類してくれなさそうです。
f:id:bananarian:20180903023542p:plain

【初心者向け】KKT条件を使ってSVMの計画問題を解く

前回はSVMについての導入を行いました。
bananarian.hatenablog.com


しかし、前回の記事では肝心の最適化問題を解く部分は長くなるのでカットしていました。そういうわけで今回はSVMに関係する部分だけピックアップして説明していきます。

 

KKT条件についてもう少し知りたいって人は、とりあえずここのpdf見れば大丈夫です。
http://www.cit.nihon-u.ac.jp/kouendata/No.42/7_sujo/7-047.pdf

スポンサーリンク




前回の復習

とにもかくにも次のような最適化問題を解きたいということでした。

制約  y_i=1の時は(aX_i-h)≧1であり、y_i=-1の時は(aX_i-h)≦-1 の下で

 ||a||^2を最小化したい。


まず、もう少し制約の部分をスタイリッシュに書いてみましょう。

 y_i(aX_i-h)≧1

ですね。

そういうわけで今回考えたい問題は

制約  y_i(aX_i-h)≧1 の下で、
 ||a||^2を最小化したい。

という問題になります。


KKT条件

さて、このように制約に不等式があるような問題の場合用いられるのがKKT条件です。
http://www.cit.nihon-u.ac.jp/kouendata/No.42/7_sujo/7-047.pdfの最初のページに詳細は書いてあります。


まず、pdfの表記に揃えるために、次のように置くことにします。

 f(a,h)=||a||^2
 g_i(a,h)=y_i(aX_i-h)-1

さらに、ラグランジュ乗数 \lambda≧0を導入することで次のようなラグランジュ関数 L(a,h,\lambda)を得られます。

 L(a,h,\lambda)=||a||^2-\sum_{i=1}^{n}\lambda_i(y_i(aX_i-h)-1)


そこでラグランジュ関数に対して次の条件を満たすような a,hを考えてやるわけです。

(1)  \frac{\partial L(a,h,\lambda)}{\partial a}=0
(2) \frac{\partial L(a,h,\lambda)}{\partial h}=0
(3) \frac{\partial L(a,h,\lambda)}{\partial  \lambda_i}≦0←全てのiで成り立つ
(4) \lambda_i g_i(a,h)=0←全てのiで成り立つ


これで a,hが出てきます。しかし、なんか大変そうですね。別にこれでも出来るんですが、双対問題という問題に変換することでより、簡単に解くことが出来ます。


KKT条件は何をやっているのか

一般的な話をしていると、とてもじゃないけど一つの記事におさまらないので、今回は変形過程を説明することにとどめます。でもまあ結構自然に変換していけるのでほとんど違和感はないかなあとは思います。


まず、さっきまで考えていた問題はこうでした。

 L(a,h,\lambda)=||a||^2-\sum_{i=1}^{n}\lambda_i g_i(a,h)を最小化したいわけですが、



まず、(4)からわかる通り、 a,hに適当な値を入れた後での L(a,h,\lambda)は元の目的関数 ||a||^2になっていると言うことに注意してください。つまりこの問題は結局ゴリゴリ条件を加えただけで、最小化したい目的関数は元のままなのです。


次に、(1)から(4)の条件は一旦忘れて、 a,hを適当な値に止めて置いて、よくよく L(a,h,\lambda)を眺めながら \lambdaを色々な値に動かしてみてほしいんですけど、

もし何れかの g_i g_i(a,h)≧0が成り立っていたら、 \lambdaを大きくすればするほどいくらでも Lを小さくすることが出来ます。つまりこの時最小値は -\inftyになってしまうわけです。

しかし、全ての g_i g_i(a,h)<0が成り立つ限りにおいて、 L(a,h,\lambda)の最小値はしっかり元の目的関数の最小値に一致します。これは \lambda=0でないと、元の関数に変な値が足されて大きくなるのでわかりますね。

整理すると次のようになります。



 g_i(a,h)<0の時、
 \min_{\lambda} L(a,h,\lambda)=||a||^2

 g_i(a,h)≧0の時、
 \min_{\lambda} L(a,h,\lambda)=-\infty


つまり、私たちは g_i(a,h)≧0の場合の最小値は興味がないわけです。元の目的関数の最小値と一致する場合だけ知りたいわけです。


というわけで、 a,hを固定した下で \lambdaを動かし、最小値の挙動を上のように調べた後は、 -\inftyをはじく為に、a,hについて最大化する必要があるのです。

つまり、こういうことです。

 \max_{a,h}\min_{\lambda} L(a,h,\lambda)

こうすることで、 -\inftyか||a||^2かとなった段階で大きい方、つまり ||a||^2が選ばれます。

これを言葉で説明せずに数式で簡潔に示すと先ほどの(1)~(4)となります。


双対問題

ところで、双対問題とはなんでしょう。先ほどの \max_{a,h}\min_{\lambda} L(a,h,\lambda)は双対問題に対して主問題と呼びますが、双対問題は次のようになります。

 \min_{\lambda} \max_{a,h} L(a,h,\lambda)

主問題の \minと\maxをひっくり返しただけですね。



これは必ず次のような関係があります。
 \min_{\lambda} \max_{a,h} L(a,h,\lambda)≧\max_{a,h}\min_{\lambda} L(a,h,\lambda)

これはどういうことかというと、
まず左の項を見るととりあえず a,hを動かして L(a,h,\lambda)最も大きくしています。

次に右の項ですが、一旦 \lambdaを動かして制約をつけてから、更に a,hを動かして最も大きな L(a,h,\lambda)を見つけています。

つまり、 a,hの点から見ると左は純粋に a,hの点の中で最も大きくなるようなものを見つけている一方、右は一旦制約を与えてから a,hの点の中で最も大きくなるようなものを見つけています。

制約がかかっている以上、右の項は左の項と同じ値かそれより小さくなるのは当然ですね。ちなみに同じ話を \lambdaで見てみてもしっかり成り立っています。

強双対定理

最後に強双対定理です。


これは今回のように不等式線形制約しかなくて、目的関数が凸である場合には先ほどの関係

 \min_{\lambda} \max_{a,h} L(a,h,\lambda)≧\max_{a,h}\min_{\lambda} L(a,h,\lambda)

の不等号部分>が外れて、必ず等号が成り立ちますよという定理です。

まとめ

以上より、少なくともこのSVMのケースでは主問題ではなく双対問題で a,hを求めても良いと言うことになります。
主問題でも解けますが、この場合、ちょっと条件が多いので強双対定理は重宝します。

【初心者向け】2値分類SVM(サポートベクターマシン)の考え方と最適化問題

今日はSVM(サポートベクターマシン)について整理します。

サポートベクターマシンとは

SVMは理系の方なら耳にすることも多いかもしれません。機械学習的な手法は文系にとってはあまり需要が無いので、文系の人は馴染みがないかもしれません。一つ説明する前に補足しておくと、SVMはよく機械学習の文脈で説明されますが、厳密に区別するのであればパターン認識という手法の一つであって、機械学習ではありません。でも最近ではパターン認識機械学習も目的の点で似通っているので、あまり区別されなくなってきています。

機械学習のイメージを知りたい方は前記事で。
bananarian.hatenablog.com



で、SVMは結局何をするためのものなのかというと、要は事前に学習したデータを元に、新しいデータがどの分類にあてはまるか割り当てるという手法です。


具体例を挙げると、例えば

ある時期に届いたメール、300件について、適当な基準に基づいて迷惑メール重要なメールかに分けるとします。最初はまあ手動で分けているわけですが、いつまでも手動で分けていても面倒くさいので、適当な基準があるわけだからその基準で分けてくれるよう機械に命令すればいいわけです。

しかし、もう少しよくよく考えてみるとこの適当な基準というのは結構難しくて、これから届く全てのメールに対して分類を失敗する確率が0になるような確定的な基準を考えるのは結構しんどい。というか多分ムリ。

そこで、各メールの特徴を学習させていって、そこそこの精度で分類できるような分類器を作るという方法に転換します。この分類器の一つがSVM(サポートベクターマシン)になります。

サポートベクターマシンによる分類のイメージ

その分類方法ですが、基本的には直線(or超平面)によって平面(or空間)を分割するという方法を取ります。図にするとこんな感じです。
f:id:bananarian:20180902173818p:plain

この黒い直線がSVMです。2グループに分けてます。

このようにうまく分類してくれる直線を引きたいというわけです。

SVMの数式

ちょっとベクトルで考えるとしんどいっすって人もいると思うので、とりあえず特徴量が1種類のケースで定式化してみます。
わかりやすくなるようメールの例で書いていきます。
今、メールを300通受け取りました。そしてそのメールに対して

 (y_i=-1):i通目のメールが迷惑メールである
 (y_i=1):i通目のメールが重要なメールである

という分類をしていき、メールの特徴として、「謎のURLが何個貼ってあるか」というような特徴 Xを考えます。
(よく、迷惑メールってURLいっぱい貼ってあったりしますよね?しないかな。その辺はわかんないけどあくまで例として)

そして、次のような分類を考えます。

 aX-h=0

この式を分類器であると考えるとこの式の意味はしきい値である h aX超える超えないかを見る話だということがわかりますね。

この超えるか超えないかを迷惑メールか否かの意思決定に対応させたいので次のような関数を考えます。

 sgn(aX-h)

この sgn()とは、中身が0以上であれば1を0未満であれば-1をとる関数とします。
こうすることで、空間を二つの領域に分解することが出来ました。要は sgn(aX-h)=1を取る領域と、 sgn(aX-h)=-1を取る領域です。

さっきの図に書き加えると次の通り。
f:id:bananarian:20180902182226p:plain


ですが、直感的にわかるかもしれませんが、300個のデータをきれいに分類する直線は

そもそも引けないかもしれない
反対にたくさん引けるかもしれない

という2種類の可能性があります。

そういうわけで、とりあえず与えられたデータ及びこれから与えられるデータはこのように直線で分類することが可能であると仮定しましょう。

これを線形分離可能と呼びます。

しかし、まだこのままでは色々な直線が考えられます。


そこで次のような概念を考えます。

マージン

どっかの点とスレスレになるような直線ではなく、余裕をもった直線を引きたいというようなことを考えるとします。

つまり下のような直線を引くよりは
f:id:bananarian:20180902183530p:plain

このような直線を引く方が望ましいというわけです。
f:id:bananarian:20180902182226p:plain


そこで、直線を引いた時に、一番近い点との距離が最も遠くなるようにしたい

と言うことを考えるわけです。


まず、各点と直線の距離はこうなりますね。

 d(X_i,a,h)=\frac{|aX_i-h|}{||a||}

ここでまず一番近いXとの距離を考えます。
 \min_{X_i}d(X_i,a,h)=\min_{X_i}\frac{|aX_i-h|}{||a||}

その中で距離が最も遠くなるように aとhを決めます。
 \max_{a,h}\min_{X_i}d(X_i,a,h)=\max_{a,h}\min_{X_i}\frac{|aX_i-h|}{||a||}


これを最大マージンと呼びます。


最大マージンの計算方法

しかし、式では書けるけど、これどうやって解けばいいんだとなるので、もう少し工夫します。まず、

 aX=h

ですが、これ、別に両辺定数倍しても関係式はおかしなことにはなりませんよね。
というわけで適当に定数倍を行うことで


全てのサンプルに対して
 y_i=1の時は(aX_i-h)≧1であり、y_i=-1の時は(aX_i-h)≦-1であるという条件を加えてみます。


そうすると \min_{X_i}|aX_i-h|=1なので最大マージンは \frac{1}{||a||}を最大化すればよいということになりますね。


しかし、このままではまだ考えにくいので、二乗して逆数を取ってやり、

 ||a||^2を最小化する問題を考えよう

という話に変換します。



これなら二乗したものを最小化するという話に落ち着いたので、考えることが出来そうです。



というわけで、長くなりましたがまとめると次のような定式化となります。


制約  y_i=1の時は(aX_i-h)≧1であり、y_i=-1の時は(aX_i-h)≦-1 の下で

 ||a||^2を最小化したい。


で、後はどうするかというと不等式制約を持つ最大最小化問題なので、KKT条件を使ってやって、ちょっと計算しにくいので双対問題を考えてやり、強双対定理が成り立つことを適当に示した後で最適化問題を解いてやればよいということになります。

※よく、機械学習関連のブログでラグランジュ未定乗数法を使うといった記述が見られますが、不等式制約に関する問題にラグランジュ未定乗数法は使えません。KKT条件を活用します。


KKT条件に関する話はまた別の記事で。

補足

今回は最大マージンを考える方法でSVMを考えましたが、別の基準に従って考えることもできます。これについてもまた別の記事で書いていきたいと思います。