ホーム » 画像解析

画像解析」カテゴリーアーカイブ

Feature Importanceを知る

こんにちは。kzです。

世の中ではやはり解釈性が重要らしいです。

前回、SHAP含めてモデル解釈の指標についていくつか触れました。やはり一度では僕は残念ながら理解できないので復習も含めて今回この記事を書きます。

前回の復習

上記のリンク先が前回の記事になります。

  • Permutation Importance
  • Partial Dependence
  • LIME
  • SHAP
雑におさらいするとPIは対象の変数をシャッフルして精度の変化からその変数の影響力を見る手法。PDは対象の変数以外を周辺化で消すことによってその変数のみの影響力を見る手法。LIMEは対象の入力データ周辺でブラックボックスモデルを線形近似しその重みでそれぞれの変数の寄与具合を見る手法。SHAPはLIMEのモデルに複数の制約(Consistencyなど)を与えてできた特殊な距離を使った手法(LIMEの上位互換)

ちなみに他にもDrop-Column Importanceとかもあるらしいです。

Feature Importance

順番的には逆になってしまいましたが、決定木自体にはFeature Importanceというものがあります。ご存知ですよね。どうやって算出されてるのや?と思ったので調べました。結論から言えばあまりにも式が複雑で完全に理解し切るのはかなりハードです。。

なのでその計算の核となるGini Impurityから始めます。

Gini不純度

あるノードにおけるGini不純度は上のように定義されます。記号については以下の通り

  • Cはクラスの総数
  • p_iはクラスiの割合
分類においては各ノードではできるだけ少数のクラスであって欲しいですよね。具体的に計算してみます。
         二郎系   家系     まぜそば 
count = 4 4 4
p = 4/12 4/12 4/12
= 1/3 1/3 1/3
GI = 1 - [ (1/3)^2 + (1/3)^2 + (1/3)^2 ]
= 1 - [ 1/9 + 1/9 + 1/9 ]
= 1 - 1/3
= 2/3
= 0.667
各クラスから均等な量の場合とあるクラスに偏りがある場合
         二郎系   家系     まぜそば 
count = 3 3 6
p = 3/12 3/12 6/12
= 1/4 1/4 1/2
GI = 1 - [ (1/4)^2 + (1/4)^2 + (1/2)^2 ]
= 1 - [ 1/16 + 1/16 + 1/4 ]
= 1 - 6/16
= 10/16
= 0.625
少し小さくなりました。ではあるノードにおいて単一のクラスのみある場合はどうでしょうか。
         二郎系   家系     まぜそば 
count = 0 12 0
p = 0/12 12/12 0/12
= 0 1 0
GI = 1 - [ 0^2 + 1^2 + 0^2 ]
= 1 - [ 0 + 1 + 0 ]
= 1 - 1
= 0.00
0となりました。きれいに分類できている証拠ですね。決定木のFeature ImportanceはこのGiniを用いて算出されているようです。 参考文献によると
とありました。難しいですが、要は最後の式だけ見ればなんとなくわかります。分母は前ノードにおけるImpurity Reductionの総和であり、分子は対象の特徴量jによる分岐ノードでのImpurity Reductionの総和となっています。

つまり、対象の特徴量が木全体においてどれだけGini不純度の減少に寄与できたかという指標でFeature Importanceが算出されているということです。

ということはです。分岐点を多く作りやすい変数の方が相対的にFeature Importanceが大きくなるのは直感的ですよね。単純に考えるとカテゴリカル変数よりも連続値変数の方がFeature Importanceが相対的に高まってしまうということです。さらに木を深めることで多くの分岐点が生成されるのであればその効果は莫大です。

実際Feature ImportanceにはCardinalityが密接に関係します。次にCardinalityについてみてみます。

Cardinality

みんな大好きKaggleにおいて次のような質問があった。
タイタニックデータをxgboostでバイナリ分類したのちfeature importanceをみた結果、特徴量の1つであるSexは目的変数と高い相関があるにもかかわらず、比較的低いimportaceが得られたらしい。 これに対して気になるコメントがあった。
なにを言っているのかというと。カーディナリティによってfeature importanceにバイアスが生じる。high-cardinalityはhigh-importanceを持つ。これが原因でSexが相対的にlow-importaceになっている。

ここでカーディナリティとは、対象の変数の多様性のこと。つまり性別のようなカテゴリカル変数よりは連続値の変数の方がカーディナリティは相対的に高い。

これはまさに上記のGiniの定義より得られた考えのことだ。よってさきほどのFeature Importanceに対する理解は正しかったということだ。

Information Gain

実は決定木における重要な指標はGini Impurityだけではなく、Information Gain(平均情報量)というものが別であります。
じゃあ、どっちを決定木では使うの?どっちのほうがいいの?という問に対する答えはGini Impurityです。理由は簡単で計算が楽だからです。後者を選んでしまうと対数の計算が必要になります。詳しくは次のリンクへどうぞ

LIME

じゃあ、どうしたらちゃんとした、まともな、直感的なFeature Importanceが得られるのか。という問に対する答えは僕の知るベストだとSHAPだ。もうSHAPしかない。

上述した理由から決定木におけるFeature Importanceに信憑性はない、結果的に重回帰がやはり好かれている。しかし、分類という点においては決定木やNNには重回帰では残念ながら勝てない。

最高に分類できる状態を保ちつつ、重回帰のように最高の形でFeature Importanceがほしい、という欲求を満たしてくれるのがSHAPだ。LIMEの上位互換なのでやってることはほぼ同じ。

記事の最後になりましたがここでは低次元空間においてLIMEの振る舞いを簡単に実装してSHAP(LIMEの上位互換)のイメージを理解します。下のような非線形データを考えます。
可視化に力をいれたいのでgridでデータを再度作成し、とあるインプット(青)を考えます。このインプットしたいするlimeを求めます。
LIMEもSHAPもローカルなので局所的な空間を考えます。多様体の言葉でいうとチャート、または局所座標近傍です。
距離関数としてL2距離を算出します。実際にロス関数を定義して重みを最適化するのではなく、この距離を線形回帰のライブラリのweightというパラメータに用いて外れ値を考慮した線形モデルを構築します。
前述通り今回はロス関数を定義して計算しているわけではないので厳密なLIMEの実装ではないので注意。あとは線形回帰モデルを作って重みを取得するだけです。
両軸を特徴量として扱っているので線形モデルの直線は可視化できませんが上のマークより、その振る舞いは理解できたのでわないかと思います。ピンクの部分はプラスでグレーの部分はマイナスと分類されています。その時の切片、係数も取得できます。これがlimeです。 厳密ではないですがLIMEのやっていることは理解できたかな?と思います。

ちなみにSHAPの凄いところは制約3つめのConsistencyです。これによって対象の特徴量のFIがより重み付されます。これによって決定木におけるFIの相対的なつぶれよりも直感的なFIを得ることができます。
SHAPの距離のところがよくわからない。でわ

Reference

モデル評価 入門

こんにちは。kzです。

本日は機械学習のモデルの評価方法についてまとめます。Gistsがかなり重くなってしまったので一発で見れない場合はColabで開くか、Gistsに飛んだのちページを何度か更新してみてください。

分類指標

この記事では分類問題に焦点を当てます。なので回帰におけるMSEとかは話しません。

  • TP / TN / FP / FN (真陽性 / 真陰性 / 偽陽性 / 偽陰性)
  • confusion matrix (混同行列)
  • simple accuracy (正解率)
  • recall (再現率) (sensitivity)
  • precision (適合率)
  • f1 measure (F値)
  • f1 beta measure (重み付きF値)
  • threshold (閾値)
  • ROC / AUC (受信者操作特性 / AUC下部の面積)
  • MCC (マシューズ相関係数)
これらのベーシックな指標についてまとめます。またF-betaについては少し深入りします。でわやっていきましょう。

分類指標の必要性

もちろん、汎用性がめちゃくちゃ高いものがあればそれでいいんですが残念ながら私は知らないです。。。他にも具体例で考えてみましょう。

たとえば、100枚のラーメンの写真をデータセットとします。モデルf

  1. 二郎系だ
  2. 二郎系ではない
という分類をしたとするじゃないですか、Accuracy=99%となったとするじゃないですか、この数値だけ見ればすごく上出来なんですけど仮に100枚中1枚しか二郎系がなかったとしたらfはなにも考えず1を出力するだけで99%とれちゃいますよね。これってfはまともな学習をしていないことになりますよね。つまり、このモデルfよくないですよね。

Confusion Matrix

クラス分類の結果をまとめた表のこと。各要素がTP / TN / FP / FNとなる。ただし、これは二値の場合。しかし多値分類でも同様に作れます。
Pythonで実装する際はパーセンテージも表示させるといいですね。
で、Confusion Matrixの中の指標を一個づつ見ていきます。

Accuracy

もっとも、シンプルかつ、直感的な正答率

Precision

少しの外れを許すが機会損失したくない時に使う

Recall (Sensitivity)

機会損失してでもとにかく正確に当てたい時に使う

PrecisionとRecallの具体例

たとえば全国の二郎系を制覇したいという目的に対してはRecallよりもPrecisionを重視します。なぜならば行ったラーメン店が高い確率で二郎系あっても素通りしてしまっては目標が達成できないからです。

逆にRecallを重視するのはたとえば病気を判別するときです。病気なのに病気ではない、と判断すると大変ですよね

とはいえ、完璧な分類は共に高いのでどうせならこの二つの指標を同時に見たいですよね。つまり。2つの指標を同時に加味して「全体としての良さ」を測りたい時にF_1の登場です。

F1 measure

RecallとPrecisionを同時に考慮する指標です。調和平均という見方もできますがFP + FNが「外れの総数」であることに注意すると外れの平均を考慮した正解率と考えることができます。
しかしです。先程の例のようにどっちかを特別重要視してモデルを評価したい時多いですよね。つまり、recallとprecisionを同じくらい重視して全体の良さを図るのではなくどちらかを相対的に重視したモデルの良さの指標が欲しい時の方がぼくは多い気がします、そこでF-betaの登場です。

F-beta measure

RecallとPrecisionに重みを加えたF measureです。いわば一般化です。
Precisionを重視したいなら  (F_0 = Precision)

    \[ \beta \in (0,1) \]


Recallを重視したいなら  (F_\infty = Recall)

    \[ \beta \in (1,\infty) \]


\beta=1のときはまさにF1となります。 しかしです、この式おかしいと思いませんか?相対的に重みづけするならば一方がw_1 \in [0,1]でもう片方はw_2 \in [0,1]だと思いませんか?つまり
のほうが自然なF-betaですよね?え?ぼくだけ、、?笑。まあそういうことにしてちょっと聞いてください。

van Rijsbergen’s E (effectiveness) function

F-measureは実は別の指標から導出されたものらしいです。起源は次のもの
前述のF_\betaの定義が[Chinchor, 1992]なのに対してこれは[van Rijsbergen, 1979]です。たしかに古い。

代入して変形します。
この関数ER, P \in [0,1]でプロットしてみます。

次は\betaを動かしていってF_\betaを見てみます。Eではないことに注意。
で、このグラフを頭に置いたまま話を戻すと関数E(R, P)\alphaはなぜあのような形なのか?気になります。調べますと次の条件を満たすようにされているらしいです。
真実を確かめるために計算していきます。
ここで \beta=R/P なので R を \beta P^2と置き換えて
と、確かに導出されました。しかし、勾配が等しくなるという条件にどういう意味があり、なぜ必要なのかは理解できませんでした。すいません、、

とはいえ、わかったことをまとめると直感的な加重調和平均は\alphaの方だということ。重み\alphaに戻して考えると\betasqrt{2}のとき重みが1/3対2/3になり、たしかに直感的に2倍の重みを置いていることになりますね。

ROCとAUC

確率出力に対して最もいい閾値を見つけると同時に、モデルを比較するための指標をグラフ化したものです。

グラフ上の点は特定の閾値を用いてラベリングされたのちの混合行列から算出されたspecificity, sensitivityである。次の動画がかなりわかりやすいので絶対見てください。

簡単にまとめると、例えばロジスティック回帰を用いた2値分類を考えます。この時に閾値をいくつにするかが問題ですよね。出力の確率と閾値を比較して大きければ1,小さければ0のようにラベルを振る必要があるからです。つまり実数からカテゴリカルに変換する必要性。

ということはです、もちろん閾値と混合行列は一対一対応します。

どの閾値がもっともいい分類をしてくれるのか?という問に答えてくれるのがROCです。

そしていくつかのモデルに対してどのモデルがいいか、つまりどのROCがいいかという問に答えてくれるのがAUCです。
各軸はTPR、FPRとよばれます。言い換えると縦がRecallで横が(1-Sepecificity)です。つまり左上に近づくほど理想的であることがこの定義よりわかります。

そして上の図中の点ですが、これひとつひとつが特定の閾値によって算出された混合行列を用いて計算されたTPR、FPRです。

ここでわかったこととして他クラスのROCはそう単純ではないということです。sklearnに実装はありますがバイナリ で実装されているのか閾値をクラス数で分割しているのかわかりませんが、理論上はそう簡単にROCが作れないことは気にかけておいた方がいいと思います。

MCC

各クラスのサイズが非常に異なっていても使用できる評価指標です。

この記事の冒頭で極端な例をあげましたが、実世界の分析においてはよくあることだと思います。ですのでその点ではいい指標だなと思います。
でわコードを貼って終わりにします。
パラメータ空間は位相空間。でわ

SHAP値で解釈する前にPermutation ImportanceとPDPを知る

こんにちは。kzです。

昔、kaggleから宿題メールみたいなものが届いたんですよね。
今回はこれをやっていきます。先に一言で言うと機械学習のfitを説明しよう、と言うことです。言い換えるとモデルがデータをどう扱ったか解釈しよう、と言うことです。なんとなくまとめを先に行っておくと次の通りです。

ブラックボックス

機械学習も僕の知っている2年前に比べて色々と賑やかになってきました。決定木だとLightGBMやXGBOOSTありますし、ニューラルネットだとStacked LSTMやGANとかですねえ。そんな優秀なアルゴリズム達をどうやって理解すればいいんだろう?と言うのがブラックボックス問題です。例えば「ニューラルネットで学習させたけどこの重みの意味って、、、?」とか「この入力と出力の間の関係は、、?」とか「この変数って予測にプラスに働いたのか、、、?」などです。

この記事ではそんなブラックボックスを少しでも理解するための方法をまとめます。

Permutation Importance

例えば決定木だとFeature Importanceがあります。これはモデルが使用する特徴量の重要度を数値化したものです。アルゴリズムに関してここでは触れませんがPlotはこんな感じです。
人間はやはり可視化が好きなんですよね、上のものは決定木から得られたんですがこれを別のアルゴリズム、例えばリッジとラッソとかでもやりたくないですか?そんな時に使うのがPermutation Importanceです。これはある列を選択しその列内の値をランダムに並び替えて再度予測することでその精度の変化から逆算的に、選択した列の重要度を測るアルゴリズムです。

Partial Dependence Plots

上でどの特徴量が重要か分かりました。ではその特徴量と出力の間の関係知りたくなりますよね?そこでpartial dependence plotの登場です。参考文献にあるLINEさんのスライド見てあまりにも感動したんです。なんでかと言いますとこのアルゴリズムは選択した特徴量以外を周辺化で消すんですよね、その周辺化がまさに積分なんです。ベイズで出てくる周辺分布と同じようなことをしてるんです。
とは言っても周辺分布(周辺確率)のイメージとは異なる気がします。具体的な計算は次のようになっているようです。
最後はこれらの平均をとるのですが加重平均もOKです。これを見て思ったのが着目する特徴量がカテゴリカルでない場合は計算量がえぐそうですね、、、

ではプロットを見てみます。データはirisです。
  • x軸は変数の値
  • y軸はbaseline(一番左の点)との予測(prediction)の比較
  • 青枠は信頼区間
となります。例えばpetal length(class 1)だと4cmの時に予測が最もうまく働いていますが4cmを超えてからは悪い影響を与えていると読み取ることができます。

SHapley Additive exPlanations Value

やっときましたSHAP値。これは予測値と特徴量の関係を与えます。例えばプラスに働いたのか、マイナスに働いたのかと言うことです。

LIME

SHAPアルゴリズムについてはLIMEというものがベースとなっているようです。
LIMEでは対象のデータ周辺で局所的にモデルを線形近似します。上の図において、赤・青のバックグラウンドで表現されているのがブラックボックスである関数fです。濃い目の赤が説明したいデータ(インスタンス)です。黒のダッシュが局所的に線形近似した分類モデルになります。その係数の大小で各特徴量の重みを測ります。ちなみにLIMEは以下の最小化を行うようです。
二乗誤差を重み付けして最小化していますね。なんか気持ちいいです。まあこんな感じです(これ以上はわからない、、)

SHAP

話が少しそれましたがSHAPのアルゴリズムに移ります。これが非常に難しかった。。

論文中にある「Simple Properties Uniquely Determine Additive Feature Attributions」の部分が肝です。LIMEに制約を設ける感じです。
はいまず制約その1です。ブラックボックスモデルと近似モデルが等しい。

制約その2です。存在しない説明変数の貢献度はゼロとします。まあそんなに気にしてくていいです。
制約その3です。重み\phiが大きくなる条件のようですがすいませんよくわかりません。
これらの制約をうまく満たしてくれるのが上のモデルになります。LIMEに比べて距離関数のところがかっこよくなりました。

これ以上は全くわからないのですいません、説明はここまでします。ここでは使えるようになることに集中します。 例えばwineのデータにかけてみると
SHAP値ではベースライン(データ全体の期待値)との比較を行っているようです。これがよくわかってないです、コメントください。
上のようにクラス別でも見れます。
上の図は目的変数との相関になります。(分類だとplotできなかったため回帰問題のデータに変えました)

横軸が目的変数の値で縦軸が特徴変数の貢献度の高さです。赤が正の値を、青が負の値となります。例えば、s5は目的変数が大きく(右側)なるほど赤い分布となり、目的変数が小さく(左側)なるほど青い分布となります。つまり、目的変数とs5は正の相関があることがわかります。
上のグラフにおいてs5は血清測定値5という特徴量です。s5の値が大きいほど目的変数である1年後の疾患進行状況指標が高いことがわかります。
一通りやってみました。ここでは触れてませんが画像処理において画像のどの部分が寄与したか、などもわかるようです。ぜひ参考リンクをご覧ください。

アルゴリズム勉強します。

Reference

ハイパラ最適化に困ってるんやろ?Optunaやで

こんにちは。kzです。

久しぶりに欲しいものができたんですよね。無印の「軽量オーストラリアダウンポケッタブルマフラー」なんですけどオンラインでも全部在庫がないみたいで入荷を心待ちにしています。

そんなことはおいておいて、本日はハイパーパラメータ最適化についてです。

ハイパーパラメータとは

ハイパーパラメータの前にパラメータがありますよね、違いはなんでしょう?LassoとRidgeを例に取りましょう。

上の記事で解説したのでそちらもみていただきたいのですが、モデルを定義する際に学習させる変数がありますよね。よく\thetaで表されるやつです。例えばRidgeの場合だと
となり、Lassoの場合だと
となりました。このように学習(よくfitやtrainと言われる)において学習される変数をパラメータといいます。ではハイパーパラメータとはなんでしょう?これは我々が手動で設定する必要があるパラメータのことです。例えば次のLassoの目的関数を見てみましょう。
先ほど通り、\thetaがパラメータです。一方で、\lambdaがありますよね。これは我々が決めるパラメータなのでハイパーパラメータになります。

これでパラメータとハイパーパラメータの違いが理解できたと思います。真相学習や機械学習の問題の一つはこのハイパーパラメータの最適化です。例えばニューラルネットワークにおいて活性化関数に何を使うかや決定木において深さをどうするかめっちゃ悩みますよね?それを最適化したいんです。

Grid Search

よくある手法の一つがグリッドサーチです。これは格子状にハイパーパラメータの候補を作り、総当たりしてその結果を見てハイパーパラメータを選ぶという手法です。sklearnにあるのでみてみましょう。
いいんです、これでもいいんですけど「探索の最適化」したいですよね?紹介しましょう。オプチュナを。

Optuna

あの最強のPreferred Networks, Inc.さんが開発しました。
Optuna はハイパーパラメータの最適化を自動化するためのソフトウェアフレームワークです。ハイパーパラメータの値に関する試行錯誤を自動的に行いながら、優れた性能を発揮するハイパーパラメータの値を自動的に発見します。現在は Python で利用できます。
Optuna は次の試行で試すべきハイパーパラメータの値を決めるために、完了している試行の履歴を用いています。そこまでで完了している試行の履歴に基づき、有望そうな領域を推定し、その領域の値を実際に試すということを繰り返します。そして、新たに得られた結果に基づき、更に有望そうな領域を推定します。具体的には、Tree-structured Parzen Estimator というベイズ最適化アルゴリズムの一種を用いています。

これがすごいんです。論文にもなったようです。

使い方

テンプレは上の感じです。超シンプルなんですよね。ちなみに最後にgistsを貼りますが、出力も多く、plotもplotlyを用いているのでnotebookでは表示されませんので注意です。
例えばSVCのパラメータ探索をしたいときのコードは上の感じ。
時にはLightGBMとXGboostのように異なるアルゴリズムで比較したいときもありますよね。できるんです。
で、このOptunaの最大の魅力だと個人的に思っているのがPlotでして、plot自体が魅力的ではなくて、plotからOptunaが使っているアルゴリズムがすごいということがわかるんです。
これをみていただくとわかるかもしれませんが、ベイズ最適化を使っているんですよね。デフォルトだとTPEと呼ばれるアルゴリズムを使用されているようです。僕もベイズ最適化あたりは勉強しないといけないので良さそうなリンクを上げておきます。

で、まだ特徴があってデータベースに学習記録が保存できるらしいです。使い道はよくわかりませんが、、コメントください、

Code

Optunaはすごいですね、これからさらに追加される機能も気になりますし、gitからベイズ最適化のアルゴリズムの勉強もさせてもらえそうです。勉強頑張りましょう。でわ

References

Softmaxを数式から実装まで

こんにちは。

本日は待ちに待ったソフトマックス回帰の実装です。ロジスティックの兄さんのような存在のロジスティック。出力が確率の多値分類になっただけです。この記事では数式をゴリゴリ計算していこうと思います。

Softmax function

    \[\phi: \mathbb{R}^n \rightarrow \mathbb{R}^K     \textbf{    s.t.     } \sum_{i=1}^{K} \phi_i = 1   }\]


    \[\phi_j(z) = \dfrac{\exp(z_j)}{\sum_{k=1}^{K}\exp(z_k)}     \textbf{for}j=1,…,K\]

n次元の入力に対してK種類に分類する写像です。ロジスティックの場合はK=2です、なので特に問題はなさそうですね。ではとりあえずこのソフトマックスを微分してみます。まずj \neq kの時

    \[\frac{\partial \phi_{j}}{\partial z_{k}} &=\frac{0-\exp \left(z_{j}\right) \exp \left(z_{k}\right)}{\left(\sum_{k} \exp \left(z_{k}\right)\right)^{2}} \ &=-\phi_{j} \phi_{k}\]

同様にj = kの時、

    \[\frac{\partial \phi_{j}}{\partial z_{k}} =\frac{\exp \left(z_{j}\right) \sum_{k} \exp \left(z_{k}\right)-\exp \left(z_{j}\right) \exp \left(z_{k}\right)}{\left(\sum_{k} \exp \left(z_{k}\right)\right)^{2}}\]


    \[=\phi_{j}\left{\frac{\sum_{k} \exp \left(z_{k}\right)-\exp \left(z_{k}\right)}{\sum_{k} \exp \left(z_{k}\right)}\right}\]


    \[=\phi_{j}\left(1-\phi_{k}\right)\]

これで微分ができました。次にソフトマックス関数の実装時、大切になる次の性質を紹介します。

    \[\dfrac{\exp({\theta^{(k)}}^T x^{(i)})}{\sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)})} = \dfrac{C\exp({\theta^{(k)}}^T x^{(i)})}{C\sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)})} = \dfrac{\exp({\theta^{(k)}}^T x^{(i)} + \log C)}{\sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)} + \log C)}\]

ソフトマックスを実装の際、何がやばいかというとオーバーフローなんです。それは指数関数を使ってるので当たり前なんですが僕のように情報上がりでない方はなぜエラーが起きるのか・オーバーフローとはなんなのかわからない方もいると思います。しかし、上の性質よりオーバーフロー対策ができます。つまり、定数を加えてもOKだよ、ということです。なので\log C = - \max_j {\theta^{(j)}}^T x^{(i)}とすることでその対策ができます。これは便利。 ではコスト関数に参ります。今回使うデータを次のようにします。

    \[{ (x^{(0)} , y^{(0)}), \cdots, (x^{(N)} , y^{(N)})   }\]

また、便宜上、1 { True } = 1, 1 {False } = 0となる関数を定義しておきます。するとコスト関数は次のようになります。

    \[J(\theta) = - \left[ \sum_{i=1}^{N}\sum_{k=1}^{K} 1{y^{(i)} = k} \log \dfrac{\exp({\theta^{(k)}}^T x^{(i)})}{\sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)})} \right]\]

今からこれを微分するんですが式がちょっと複雑なので

    \[P(y=1|x;\theta) = \phi(x;\theta) = \dfrac{\exp({\theta^{(1)}}^T x)}{\sum_{k=1}^{K}\exp({\theta^{(k)}}^T x)}\]

とおきます。では微分行きましょう。

    \[\nabla_{\theta^{(k)}} J(\theta) = - \nabla_{\theta^{(k)}} \left[ \sum_{i=1}^{N}\sum_{k=1}^{K} 1{y^{(i)} = k} \log \dfrac{\exp({\theta^{(k)}}^T x^{(i)})}{\sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)})} \right]\]


    \[= - \nabla_{\theta^{(k)}} \sum_{i=1}^{N}\sum_{k=1}^{K} \left[ 1{y^{(i)} = k}  \left{  {\theta^{(k)}}^T x^{(i)} - \left { \log \sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)}) \right}\right} \right]\]


    \[= - \sum_{i=1}^{N} \left{  1{y^{(i)} = k} [x^{(i)} - P(y^{(i)}=k|x^{(i)};\theta) x^{(i)}]\]


    \[= - \sum_{i=1}^{N} x^{(i)} \left[ 1{y^{(i)} = k} - P(y^{(i)}=k|x^{(i)};\theta)  \right]\]

となりました。最後はちょっとだけシンプルですね!ではコーディングに移ります。用いるデータはsklearnのdigitsです。
でわ。

参考

物体検出をとりあえず

こんにちは。
僕が初めて書いた比較的まともなコードって多分物体検出なんですよね。物体検出、つまりObject Detectionとはなんぞや、の方のために以下の画像を用意しました。
The future of computer vision with the TensorFlow Object Detection API from Google. You won't have to describe any photo....
https://www.flickr.com/photos/drbeachvacation/35477618781
見たことありませんか?僕毎朝めざましテレビを個人的に見てるんですけどそこでも天気予報の際に物体検出を使っていてびっくりしました。そんなObject Detectionが今回のテーマです。
非常に難しそうに思えるかもしれませんが、単一種類の物体検出ならとても簡単です。cv2というライブラリを使いましょう。今私は単一の、と言いました。これは例えば人の顔であったり、犬の顔であったりします。もう少し深くいうと、人の顔(正面)、人の顔(横顔)などもあります。そしてこれらはカスケードファイルという形で保存されています。これは機械学習でいう所の正解ラベルのようなものです。このカスケードファイルには色々な種類があります。 例えば上のリンクを見てもらうと多種多様なカスケードファイルがあることがわかります。つまり、オリジナルのカスケードファイルを作ればオリジナルの物体検出ができるということです。カスケードの自作は可能ですがどうやら少し難しいようです。機会があれば記事にしたいと思っています。リンクを一応貼っておきます。
物体検出はやっていて楽しいので自分への課題としてFlaskを使った簡単なサービスをできないかなと思っていたりします。しかし、サーバーなどの知識があまりないのですぐにとは行きそうにないです。。。なのはともあれコードを見ましょう。の前に1つだけ注意です。opencvを使うとエラーが頻繁に起こります、実際に次のコード内でもおきています。しかし、ほとんどの原因はPATHです。なのでフルパスで渡すか、今回の場合はwebのurlで作動しなかったのでwgetコマンドを使ってダウンロードして同じディレクトリ上にファイルを置くことで解決しました。このへんは注意してください。また、Pythonの仕様かMacの仕様かはわかりませんがplt.imshowにおいて画像の色が反転してしまうのでRGBを変更するコマンドを忘れないように注意してください。
ポイントとしては物体検出で使う次の2つのパラメータについてです。
これらについてまとめると
  • scaleFactorは小さいほど検出が正確になる
  • minNeighborsは大きいほど検出が正確になる
です。x86_64が詰まってしまいました。誰か助けてください。でわ

CNNの目的関数の考察と歴史

こんにちは。

久しぶりの投稿になりました。本日の内容はタイトル通りです。

線形回帰とかの目的関数って最適解を持ちましたね。
しかし、ニューラルネットワークはそうはいかないと言いました。

つまり、目的関数が凸関数ではない可能性が非常に高いんですね。
目的関数や凸関数、勾配法がわからない方は次の記事をみてください。

CNNの目的関数を可視化した論文があります。
その図をお借りして実際にどんな感じか見てみましょう。

skip(residual) connectionとはResNetの特徴であるResidul blockの恒等写像のことです。

ちなみにこれは余談ですが、ResNetとXGBって考え方似てると思いませんか?

見ての通り左は明らかに凸ではないですね、右もマシではありそうですがサドルポイントが見られます。
別の図も見てみましょう。次のはCIFAR-10 datasetの学習の際のプロットになります。

すごくないですか?何がってskip connectionのおかげで少し凸っぽくなってます。

VGGとDenseNetは初見なので調べてみました。というかいろんなモデル多過ぎ、、、
この際なのでニューラルネットワークのモデルをちょろっとみてみましょう。
そもそも現在流行りのCNNの基盤となったアルゴリズムはLeNet-5というものです。
開発者はフランス人のYann LeCun’s Home Pageです。

僕も最近知ったんですがこれ何がえぐいかって1998年に発表されているんです。
1998年ですよ?、どんな時代かググってみました。
パソコンの歴史/年代流行によると
1. Windows98発売
2. アップルが初代iMacを発売
だそうです。まだちょっとすごさがわからないので調べてみると
Windows 98 – Virtual x86
What’s iMac – AirMac
だそうです。言いたいことは今のスマホの足元に到底及ばないスペックです。
まあこの話は置いておいて、VGGとDensenetは僕は初見だったので調べてみました。

まずはVGGです。下のアーキテクチャは論文のものです。
2014年のアルゴリズムで当時はかなり深いとされていたようです。

それほど喋ることが見当たらないのですが強いていうなら
このモデルのアウトプットベクトルが1000なので1000種類の画像を識別できます。
Fine Tuningすればあなたの好みの画像を分類できます。例えば、好みの女優とか?
なんでモデルを最初から作らずFine Tuningするのか?
という問に対する答えは、学習量が減るからのようです。
具体的には元々のモデル上層部の重みは学習データを変えてもそれほど変化しないようなので
そのまま使い下層部つまり出力層に近い重みを更新するようです。
入力が人からキリンとかになったらどうかと思いますがね、、、

続きまして、DenseNetです。
これはResNetの改良版と言えるでしょう。改良版というのは次のようにResNetを問題視したからです。

An advantage of ResNets is that the gradient can flow directly through the identity function from later layers to the earlier layers. However, the identity function and the output of H` are combined by summation, which may impede the information flow in the network.

そもそもResNetの背景には深層における勾配消失問題があります。
この対策としてidentity functionが導入されResNetができたのですがDenseNetでは
それはメリットである一方、モデルにおける情報フローを阻害していると考えたようです。
言われてみるとそうかも知れませんね。そこで考えたれた

ResNetの特徴Residul blockに対するDense blockです。見ての通り前工程の出力を全て入力に使っています。
で、使われたモデルはこんな感じで

ResNet含め、その他のアルゴリズムとの比較結果がこれ

青の数値がDenseNetです。エラーが小さいのでいい精度であることがわかります。
長くなりましたがいろんなCNNと目的関数の凸性を見てみました。

ちなみにこれら全てkerasにあります。
Applications
便利な時代ですね。。。。そしてこれらも勾配法使われていると思うとエグい、、、

でわ。

READMORE

ねぇPython、CNNって何?(理論編 Part-1)

本日からはニューラルネットワークweek。最新のものまで突っ走りましょう。

てゆーか、ニューラルネットワークってなんだったっけ?

入出力数とか層数などは気にせずこんな風にニューロンを使った関数がニューラルネットワークでした。そして層が比較的深いものを多層パーセプトロンといいました。よく見ると

入出力がベクトル

になっていますね。いいんです。実際データなんてベクトル形式なんです。各学生のテストのデータも、競馬のデータも株価も終値とかを横並びにしてベクトルです。

しかーーし!

これ今日僕がとって虹なんですけど。こんな風に画像を入力としたい場合はベクトルじゃなくないですか?実際サイズは(691 × 502)ですし、しかもRGBなんです。RGBはレッド・グリーン・ブルーの略です、つまり3次元。

この画像のニューラルネットワークの入力として使いたいとするとこのままだと無理なので作戦を考える必要があります。

  1. とりあえずグレースケールにする(RGBからモノクロ)

こうするととりあえずデータのシェイプ(横,縦,奥)が(691\times 502\times 1)になります。しかしまだ行列のままなのでもう一工夫

  1. 各行を横に並べて1\times (502\times 691)のベクトルにするもしくは縦に並べたベクトルにする

こうすることで画像をベクトルとして扱えるようになりました!わーい

それは無理やりすぎる

ごもっともです。行列をベクトルにするなんて邪道すぎますね。行列入力できるニューラルネットワークが

畳み込みニューラルネットワーク(Convolutional Neural Network)

なんです。そう、画像に特化したニューラルネットワーク

けどどうやって行列入力可能にしたんや?

その前に、そもそもなんで画像をベクトルとして扱うべきでないかというと

たとえばこの画像、四角で囲ったところを1ピクセルだとします。ここだけ見ても何もわからなくないですか?というのはこのピクセルから学習できそうなことはあるのか?ということです。一方で

こう見るとどうですか?虹がハッキリと映っていてさっきよりは意味あるピクセルになっていますよね、つまり、コンピューターが画像を学習するには今までのようなベクトルの要素単位ではなくもっと大きな範囲を1単位として見る必要があるからです。それが

畳み込み

なんです。この場合だと真ん中の(2\times 2)行列がコンピューターの目となりKernel matrixといったりします。これをずらしていって手前の出力を作るんですがとりあえず一気に定式化します。

  • 入力シェイプはW_1 \times H_1 \times D_1
    フィルタ数: K
    フィルタサイズ: F
    スライド幅: S
    パディング: P
  • 出力シェイプはW_2 \times H_2 \times D_2
    W_2 = (W_1 − F + 2P)/S + 1
    H_2 = (H_1 − F + 2P)/S + 1
    D_2 = K

フィルタサイズとはKernelサイズのこと、スライド幅はフィルタのずらし幅、パディングは画像の縁に新たなピクセルを組み込むことzero-paddingがメジャー。これは縁に0ピクセルを付け加えること、こうすることで

  • 縁の畳み込み回数が増える
  • パラメータの更新数が増える
  • カーネルのサイズを調節できる

などのメリットがあります。

そして出力のシェイプで分母にSとありますがこれについては次の図を見てください。緑が入力、オレンジが出力

スライド幅: 1

スライド幅: 2

 

緑のブロックにカーネルを重ね合わせ線型結合を計算します。この際、スライド幅が適切でないシェイプが少数になるのでそこだけ注意。

CNNでは畳み込みに加えてPoolingという操作があります。これは画像の縮小です。今までのニューラルネットワークでは隠れ層のノード数を減らすことで次元を落としていました。これを行列入力においても可能にしようというものです。

具体的な方法はMax-poolingというものです。(2\times 2)のKernelでスライド幅2だと次のようになります。

定式化すると

  • 入力: W_1 \times H_1 \times D_1
    フィルタサイズ: F
    スライド幅: S
  • 出力: W_2 \times H_2 \times D_2
    W_2 = (W_1 − F)/S + 1
    H_2 = (H_1 − F)/S + 1
    D_2 = D_1

となります。しかし、Poolingという操作はあまり人気がないらしいのでスライド幅の大きい畳み込みで対処するようです。

最後に次のリンクが非常に参考になるので見てみてください。

 

本日はここまでです。でわ。

ねぇPython、PCAって何?(実装編+)

こんにちは。では前回の内容を踏まえて空間を変えないPCAを行いましょう。今回使うのは

顔のデータ

各次元4096で400サンプル。これを空間を保ち64次元に落とす。つまり4096次元の空間で64本の固有ベクトルがはる空間へ射影する。

これでPCAは一件落着。

 

ニューラルネットワークに深入りしていく予定。

でわ。