Googleのブラウザアプリteachable-machineで遊んでみた



 

Googleのteachable-machineとは?

googleがつい先日オープンした機械学習とはなんぞや?という人のためのブラウザアプリです。

 

実際に画像をカメラで認識させて、このwebアプリに写真の違いを学習させます。実際に写真の被験体になることで機械学習について直感的に理解できるわけです。

 

pcとネットがあれば誰でも使えます。pcじゃなくても使えますが、おそらく機械学習の過程でフリーズすると思います。たとえpcでも計算能力やGPUの処理能力が高くないと動かないと思います。画像処理なので、動きは結構ヘビーです。

以下はgoogleの公式サイトの説明サイトです。動画もあるのでみてください。

こちらはteachable-machine(アプリ)です。説明いらんて人はこちらをクリックしてください。

 

使ってみる(使い方説明)

 

  1. teachable-machineのページに行くと以下の画面になります。今回は説明(チュートリアル)はスキップします。「skip the tutorial」をクリック。

 

 

2. 以下の画面になります。何かしらのポーズをとって緑ボタンをクリックしてください。

そうすると撮影が始まります。数秒ごとに一回クリックして学習させてください。何回かやっていると、撮影が終了します。

 

 

3. これを紫と赤のボタンでも繰り返します。その際、全て違うポーズ(手をあげたり、変顔するなり)して変えてください。何かしらわかりやすい違いを作らないと、学習結果がわかりづらいですからね。

ついでに自分は

  • 緑は手をあげて
  • 紫は真顔
  • 赤はiphoneで顔を隠す

感じにしてみました!

 

学習させて遊んでみます。

  • 手をあげると→白猫
  • 何もしない(顔だけ)→震える犬
  • iphoneで顔を隠す→りす?

という挙動が確認できます。リアルタイムの画面と右の写真の変化がタイムラグなしで反映されているのをみるとmacbook-proはかなり優秀ですね。学習結果も敏感に反応していますよね。ビミョーな時は50パーになったりと数値への変換スピードも相当なものです。

 

 

もう少し遊ぶ

さらに面白い機能もあります。音声も3パターン作成し撮影画像に対応させて、pcが発する音声を変えるという遊びもできます。

 

右側に出力を切り替えるタブがあるのでそこを選択します。

 

デフォルトでもhelloとかyesとか音声を出してくれるように設定されていますが、せっかくなので変えてみます。

  • 緑(手をあげた時)→shun
  • 紫(顔だけ)→fantastic
  • 赤(iphoneで顔を隠す)→iphone

と言ってくれるように設定しました!(言葉に特に意味はありません笑)

 

以下の動画をみるとわかると思います。ちゃんと画面に対応した出力(音声)を発してくれています。(音声録音できてなくてすみません。)

音がなくてわかりづらいですが、実際に瞬時の画像変化(自分の動き)にも対応して音声が切り替わります。

shun→iphone→shun→fantastic!みたいに早く手を動かしたりしてしばらく遊んでました笑。遊んでて楽しいのは間違いなくこちらですww

 

 

以上teachable-machineについて説明しました。こんなに面白く学習できるものが無料で誰でも利用できるなんて素晴らしい時代に生まれたものです。小学校とか中学校のプログラミングの授業でぜひ取り入れて欲しいです。きっと小学生とかはハマるはず!

 


スポンサーリンク

記事が役に立ったらシェア!

python機械学習プログラミング(サポートベクターマシン)



スポンサーリンク

 

Python機械学習プログラミング 達人データサイエンティストによる理論と実践 (impress top gear)」で勉強開始したので、3章のサポートベクターマシンについて書いてみます。

   

ついでに、本書2章のパーセプトロンとか、確率的勾配降下法については以前にまとめたので、今回は飛ばします。

 

 

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

2クラス分類において高性能を叩き出す分類器を作成する。汎化能力を上げる方法としてマージン最大化が行われる。マージン最大化のために、二次計画法、特にラグランジュの未定乗数法カルーシュ・クーンタッカー条件(KKT条件)が用いられる。

 

非線形分類では、リプレゼンター定理を用いカーネル化を行い特徴空間に写像する。

 

サポートベクターマシンについて本気で根本から理解しようとするとこれらの専門用語を掘り下げないといけません。

 

しかし、scikit-learnのライブラリに用意されているので理論的背景を理解しなくてもSVMを用いて実装はできるわけです。

 

でもブラックボックス状態で使うのは嫌なので、どこまで理解できるかわかりませんが、このたび本気で理解してみることに。

 

ついでに本書によると以下のマイクロソフトの公式チュートリアル(論文?)がおすすめらしいです。英文なのでしんどいですが。

日本語では以下がおすすめ。

 

 

図で説明

文章だけではわかり辛いと思うので図での説明。最大化

 

 

サポートベクトルマシンによる最大マージン分類

 

重みベクトル\(\vec{w}\)、サンプルの位置\(\vec{x}\)を用いると、

\begin{eqnarray}
&w_{0}& + \vec{w^{T}} \vec{x_{pos}} = 1 \\
&w_{0}& + \vec{w^{T}} \vec{x_{neg}} = -1 \\
\end{eqnarray}

2式を引き算すると
\begin{eqnarray}
\vec{w^{T}} (\vec{x_{pos}} – \vec{x_{neg}}) = 2  (1)\\
\end{eqnarray}

ベクトルの長さを定義して上の式を標準化する。ベクトルの長さは以下のように定義できる。

\begin{eqnarray}
\|w\| = \sqrt{\sum^{m}_{j=1}w_{j}^{2}}      (2)
\end{eqnarray}

式1,2より
\begin{eqnarray}
\frac{\sqrt{\sum^{m}_{j=1}w_{j}^{2}} }{\|w\|} = \frac{2}{\|w\|}
\end{eqnarray}
この式の左辺は、正の超平面と負の超平面の距離である、要するに最大化するマージンである。

サンプルが正しく分類されているという制約のもとでSVMの目的関数の最大化する問題は、マージン\(\frac{2}{\|w\|}\)を最大化する問題に帰着できる。
実際には、\(\frac{2}{\|w\|}\)を最大化するのではなく、\(\frac{1}{2}\|w\|^2 \)を最小化する方が簡単である。最小化する際には、二次計画法(ラグランジュの未定乗数法)により解ける。

 

スラック変数を使った非線形分離可能なケースへの対処

 

スラック変数\(\eta\)を用いることで非線形分類のために線形規約を緩和することができる。直感的に説明するならば、適切なコストペナルティを科した上で誤分類が存在する状態のまま最適化問題を収束させることが可能になった。

正値のスラック変数は線形規約の式にそのまま追加される。
\begin{eqnarray}
\vec{w^{T}} \vec{x^{(i)}} \geq = 1 – \xi^{i} (y^{i}= 1) \\
\vec{w^{T}} \vec{x^{(i)}} < -1 + \xi^{i} (y^{i}= -1) \\
\end{eqnarray}

 

したがって、最小化すべき新しい対象(先の制約の対象)は以下のようになる。
\begin{eqnarray}
\frac{1}{2}\|w\|^{2} + C \sum_{i}\xi^{(i)}
\end{eqnarray}

 

あとは、変数cを使って誤分類のペナルティを制御すれば良い。Cの値が大きいと誤分類のペナルティが大きく、小さければペナルティは小さく誤分類に対して寛容ということになる。これによりマージンの幅が制御できるので、以下の図に示すようにバイアスとバライアンスのトレードオフを調整できる。

 

確認のためパーセプトロンのアルゴリズム、ロジスティック回帰、SVMを用いて実際にIrisのデータセットを分類し、可視化してみる。

 

 

パーセプトロンによる分類
ロジスティック回帰モデルによる分類

 

 

 

 

 

 

サポートベクターマシンによる分類


スポンサーリンク

 

カーネルSVMを使った非線形問題の求解

SVMが人気の理由の一つに非線形問題をカーネル化するのが容易であることが挙げられます。例えば以下のようにnumpyのlogical_xor関数を使って200個のサンプルを用意し、2つのクラスラベルがつけられているとする。

 

これを線形SVMを用いた場合、サンプルをうまく分割できない(適切な超平面見つからない)のは明らかです。

そうした線形分離できないようなものを射影関数を用いて、高次元空間へと射影し線形分離できるようにします。以下の式で表現できる射影を使ってクラスを分離します。
\begin{eqnarray}
\phi(x_1,x_2) = (z_1,z_2,z_3) = (x_1,x_2,x_1^2 + x_2^2)
\end{eqnarray}

これによりグラフに示されている二つのクラスを線形超空間を使って分離できるようになります。それを元に特徴空間へ再度射影することで非線形の決定境界が得られます。

以下は、非線形分離するまでの過程を視覚的に表現したものです。

 

 

記事が役に立ったらシェア!

pythonで線形最適化問題を解いてみた



スポンサードリンク

pythonで線形最適化問題を解いたので記録しておきます。

参考にしたサイトはこちら。

ラグランジュの未定乗数法

関数の最適化問題を解くのに知っておかないといけないのは「ラグランジュの未定乗数法」です。

自然言語処理等の機械学習の分野ではこれを知るのと知らないのでは、論文の理解度も全く変わってくるそうです。

こちらの文献にも書いております。

 

条件

  • 目的関数(最適化したい関数)をf(x,y)とする
  • 制約条件(境界条件)をg(x,y)=0とする
  • \(\frac{\partial f}{\partial x}\neq 0\)
  • \(\frac{\partial f}{\partial y}\neq 0\)

の時、未定数\(\lambda\)を考えると以下が成り立つ。
\begin{eqnarray}
\left\{ \begin{array}{ll}
\frac{\partial f}{\partial x}+\lambda\frac{\partial g}{\partial x} = 0 \\
\frac{\partial f}{\partial y}+\lambda\frac{\partial g}{\partial y} = 0 \\
g(x,y) = 0
\end{array} \right.
\end{eqnarray}

以上の三式を満たす(x,y,\(\lambda\))を求める方法が「ラグランジュの未定乗数法」です。

そしてこれが制約条件の元での「最適解」ということです。

別途記事にして書こうと思いますが、この式はナイーブベイズやサポートヴェクターマシン等の最適問題を解く際に必須になる式です。

 

 



スポンサードリンク

pythonを用いて線形最適問題を解く。

pythonで線形計画問題を解く場合、pulpというライブラリを用います。非線形の場合は「open opt」というライブラリを用いるみたいです。今回はpulpの紹介のみで終わりにします。

まずはpulpをpipでインストール

今回の線形最適化問題を示します。

  • 目的関数 \(2x +3 y + 10\)
  • 制約条件 \( x + y = 0.5\)

以上の条件でpulpを用いて計算します。

problem で目的関数と制約条件を定義しています。problem.solve()で解きます。

実行結果

と結果が出ました。x = 0.5 ,y = 0 がどうやら最適解のようです。軽くラグランジュの未定乗数法の復習と、pulpの勉強ができました。
次は非線形問題の最適化についてpythonで勉強していきます。



スポンサードリンク

 

 

 

記事が役に立ったらシェア!

言語処理100本ノック(第2章前半)



スポンサードリンク

第1章の続きです。

第2章UNIXコマンドの基礎

hightemp.txtは,日本の最高気温の記録を「都道府県」「地点」「℃」「日」のタブ区切り形式で格納したファイルである.以下の処理を行うプログラムを作成し,hightemp.txtを入力ファイルとして実行せよ.さらに,同様の処理をUNIXコマンドでも実行し,プログラムの実行結果を確認せよ.』

hightemp.txt の中身は以下です。

10. 行数のカウント

『行数をカウントせよ.確認にはwcコマンドを用いよ.』

プログラムを実行するときに引数を渡すことができます。これをコマンドライン引数と言います。

sys.argv[]でコマンドライン引数を取得できます。ついでに引数が0は実行ファイル名が入ることに注意。

実行結果:

UNIXコマンドでの確認:

単純に行数を数えるだけならば、「wc -l ファイル名」 の方が早いらしい。

 

11. タブをスペースに置換

『タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ』

replaceというコマンドを用いるだけ。便利ですね!

実行結果:

UNIXコマンドでの確認:

 

12. 1列目をcol1.txtに,2列目をcol2.txtに保存

『各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ.』

特に難しいことはしてないです。ファイルをopenし1行ずつ読み込み、0番目(左から1列目)の要素と1番目(左から2列目)の要素だけファイルに書き込むように書いています。zip関数とか使ったらもう少し簡潔にかけそうです。

実行結果:

col1.txt

col2.txt

 いくつかおかしな箇所がありますが、おそらくhightemp.txtの形式に問題があり、プログラムの問題ではないでしょう。

UNIXコマンドでの確認:

 



スポンサードリンク

13. col1.txtとcol2.txtをマージ

『12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ.確認にはpasteコマンドを用いよ.』

これはだいぶ手こずりました笑。まずopenにこんな使い方があるのを知らなかったのと、readline()もこんな風に使えるなんて知りませんでした。

あとはちょくちょく出てくるzip関数ですね笑とりあえず、二つ配列やらリスト型のデータがあって、二つに同様のfor文処理をさせる時は『zip』って覚えますかね。

実行結果:

UNIXコマンドでの確認:

 

14. 先頭からN行を出力

『自然数Nをコマンドライン引数などの手段で受け取り,入力のうち先頭のN行だけを表示せよ.確認にはheadコマンドを用いよ』

コマンドライン引数と言っているので、sys.argv[]を使います。

問題はコマンドライン引数で取得した数値(文字列)をどうやって数値(数字)として読み込むかですね。8行目のようなint(”数値”)でいけます。

実行結果:第二引数にN = 5を入力した場合

UNIXコマンドでの確認:

以上で2章の前半は終了です。続きはこちら→2章後半!



スポンサードリンク

記事が役に立ったらシェア!

言語処理100本ノック(第1章)



スポンサードリンク

最近、自然言語処理の勉強を始めたので、東北大学のある教授?が作成した100本ノックをやってみることにしました。

00. 文字列の逆順

「文字列”stressed”の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.」

特に難しいことはないです。strの引数を[::-1]とすることに注意。

実行結果:

 

01. 「パタトクカシーー」

『「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ.』

配列の要素番号は0から始まることに注意です。strの最後の「2」は2つおきに(奇数なので)、[0,2,4,…]ということです。

実行結果:

 

02. 「パトカー」+「タクシー」=「パタトクカシーー」

『「パトカー」+「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ.』

自分はzip関数というものを知らなかったので、だいぶ手こずりました笑。どうやら二つのリストの要素ごとに、同時にfor文で回せるようです。

これを知らなかったので、自分は二つのfor文を書き無駄にてこづっていました。

実行結果:

 

03. 円周率

『”Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.”という文を単語に分解し,各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.』

スペースキーでsplitしたいときは、split(” “)ですね。ついでにタブでsplitしたいときは、split(“\t”)です。

実行結果:

04. 元素記号

『”Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.”という文を単語に分解し,1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字,それ以外の単語は先頭に2文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.』

連想配列を作成する方法はいくつかありますが、今回は辞書型と言われているので、ループする際にインデックスつきで要素を得られるenumurate(ループする際にインデックスつきで要素を得ることができる)を用いれば良いです。

for 文の引数を指定するときに、単語のnumberと単語自身のnum,word と二つ指定しなければいけないことに注意。このforの後に二つの引数を使うタイプに慣れていないです笑

実行結果:

 



スポンサードリンク

05. n-gram

『与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.この関数を用い,”I am an NLPer”という文から単語bi-gram,文字bi-gramを得よ.』

バイグラム以外のngramを一瞬で解析できます。ngram()の引数を変えるだけですね。

ついでにこの場合の文字バイグラムは空白(スペース)も一文字としてカウントしています。実行結果を見てもらえればわかると思います。

実行結果:

 

06. 集合

『”paraparaparadise”と”paragraph”に含まれる文字bi-gramの集合を,それぞれ, XとYとして求め,XとYの和集合,積集合,差集合を求めよ.さらに,’se’というbi-gramがXおよびYに含まれるかどうかを調べよ.』

ngramの関数は前の問題で作成したものを用いています。

setコマンドは重複を許さない配列の要素を作成します。

さらに二つの配列の中身を比較する際、リスト型からセット型に変換すると、&,-,等の記号だけで集合演算ができます。知らなかった!笑

実行結果:

 



スポンサードリンク

07. テンプレートによる文生成

『引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ.さらに,x=12, y=”気温”, z=22.4として,実行結果を確認せよ』

format関数を用いることで、変数の文字列の埋め込みが可能になります。format関数を用いずにやろうとすると、”気温”が数字ではなく文字列なのでエラーになります。

実行結果:

 

08. 暗号文

『与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.

  • 英小文字ならば(219 – 文字コード)の文字に置換
  • その他の文字はそのまま出力

この関数を用い,英語のメッセージを暗号化・復号化せよ.』

最初は、暗号文?なんだそれって感じでしたので、時間がかかりました。

chr()コマンドで暗号文に変換します。ord(c)は暗号化前の文字列です。ifで英小文字の範囲内ならjoin(chr(219-ord(c)、else ならそのまま”c”ということです。

さらにifとfor  を内包表記で書いています。この方がコードが複雑になってきたときの可読性が上がるので、この書き方にも慣れないといけませんね!

実行結果:

 

09. Typoglycemia

『スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し,それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ.ただし,長さが4以下の単語は並び替えないこととする.適当な英語の文(例えば”I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .”)を与え,その実行結果を確認せよ.』

いくつかコマンドについて説明します。

  • itertools.permutations():iterable の要素からなる順列 (permutation) を連続的に返す。
  • random.randint(a,b):a <= N <= b であるようなランダムな整数 N を返す。

難しいところは、単語を連想配列にして番号と記憶させるのと、文字の並び替えの組み合わせを順列で計算し、各組を乱数で番号付しているところでしょうか。

ここでも連想配列が登場しましたね。

実行結果:

以上で第1章は終わりです。続きはこちら>>>第二章前半。



スポンサードリンク

記事が役に立ったらシェア!

パーセプトロンのアルゴリズム(pythonその2)



スポンサードリンク

前回までで、パーセプトロンの理論的な背景と、そのデータセットの用意のところまではすでに説明し終えたので、その続きから説明していきます。

>>>全体のソースコードがみたい方は前回の記事をみてください。

>>>パーセプトロンの理論的な背景についての記事

パーセプトロンのアルゴリズム(確率的勾配降下法)

w0,w1,w2の初期値は全て0で始めていますね。

biasの部分は少し説明する必要があります。


スポンサードリンク

バイアス項とは何か?

バイアス項とはベクトル\(\phi_n\)の第一成分です。

ベクトル\(\phi_n\)の説明については以下の記事を読んでください

>>>パーセプロトンのアルゴリズム(線形分離)

求める直線の方程式を
\begin{eqnarray}
f(x,y) = w_{0}+w_{1}x+w_{2}y
\end{eqnarray}
とおきましたが、
\begin{eqnarray}
f(x,y) = cw_{0}+w_{1}x+w_{2}y
\end{eqnarray}
と仮定することもできます。この場合、ベクトル\(\phi_{n}\)のバイアス項は「c(任意定数)」になります。

ベクトルwの更新には\(t_{n}\phi_{n}\)が用いられますので、w0は±cだけ更新されることになります。

なので、このcを適切に選択すれば、アルゴリズムの収束速度を改善できるということになります。

上のコードではこのcの値(biasの部分)をデータに含まれる全てのxn,ynの平均値を使っています。

なぜ平均値をとるのか

データの値(xn,yn)がとてつもなく大きい数(1000とか10000)で、平均的に10000とかの場合、勾配降下法のアルゴリズムより、w1,w2も10000程度の大きさで一気に増減します。

もしバイアス項が”1″ならw0の値は更新されても±1でしか変化しないことになります。

w0の変化がw1,w2の変化に比べて小さすぎるので、正しいwが得られるのに時間がかかります。

そこでバイアス項もデータの平均的な値にすることで、w0の変化率もw1,w2と同等にしてやろうという意味です。

Iteration

Iterationはベクトルwの更新回数です。今回は30回です。

ここはそんなに説明する必要はないと思います。

前々回の記事で説明した理論的な計算をおこなっている部分です。要は「更新」作業の一番の根幹の部分です。

判定誤差の計算

分散が大きい場合と小さい場合での比較として、エラー率を計算しています。

前にも述べましたが、分散が小さい場合は綺麗に直線で二つのデータ群を分割できますが、分散が大きいと二つのデータ群に重なる領域が生まれますので、直線で分割することができなくなります。

30回更新し直しても、直線で分割したエリアとは違うエリアにデータが含まれている場合、それをエラー率として表示するようにしています。

結果の表示、2種類の分散での実行

ここはグラフを作るだけですので、特に問題ないと思います。

最後のfor文以降で、”2種類の分散”でこれまでの全ての計算を実行するようにしています。

忘れたかもしれませんがVariance(分散)は最初に配列で設定していますね。


スポンサードリンク

計算結果

上が計算結果です。

分散が小さい方(左上)は綺麗に直線で分割できます。その証拠にw0,w1,w2の更新も7回目くらいで収束しているのがわかります(左上)。

分散が大きい方(右上)は更新を30回やっても直線で綺麗に分割することはできず、エラー率6パーセントになっています。

実際、●のある領域に×のデータが入り混んでいます。エラーが出ているということは、30回更新してもw0,w1,w2は収束していないことが右下のグラフからわかります。

以上、パーセプトロンのアルゴリズムについて理論と実際にコードを用いてどのように計算されているのか述べてきました。

データセットの用意は乱数を用いているので、計算するたびに結果が異なります。更新回数や、データ数等変えて遊んでみてください。

 

 

記事が役に立ったらシェア!

パーセプトロンのアルゴリズム(python編)



スポンサードリンク

ここではパーセプトロンについて実際のプログラムを、pythonの数理統計関数の説明していきながら述べていきます。

計算に用いたプログラム

 

最初のパラメータのところは問題ないと思います。

Variancesdで2種類の分散を用意しているのは、分散が大きい時と小さい時で、分類結果を比較するためです。

分散が大きい時は、二つのデータ群が多かれ少なかれ、重なる領域が生じ、綺麗に二つのデータ群を直線で分割できなくなります。

前ページで言えば、総誤差ΣEは小さくすることはできるが、0にならないということになります。

分散が小さい時は二つのデータ群はそれぞれの中心座標からあまり離れることなく、データが分布するので、領域が明確になり、直線で二つのデータ群を分割できます。

前ページで言えば誤差関数=0の状態です。

データセットの用意に関して

  • varianceは標本から分散を推定する場合に用いるコマンドです。

「分散」とはデータの中心からのバラツキの度合いです。

ここでは、関数の変数として使われていますので、注意してください。

上記は二重にネストした配列を作成しています。


スポンサードリンク

  • multivariate_normal

このコマンドは

のように用いると多次元正規分布の乱数を生成してくれるみたいです。

よくわからないので、途中でreturnの前にprint df1を挟んで確認してみます。

Dateframeコマンドで、マトリクスを作成するみたいです。

columnsでインデックスの指定、さらにマトリクスに行とインデックスを追加する場合には別で

と書いていますね。

  • pd.concat

よくわからないのでprint

linuxのcatコマンドからきているのでしょう。df1とdf2を縦に連結しています。

もう一つ下のdfも不明なので、これまたprint.

df.reindex(np.random.permutationでランダムに並び替えています。

その次のreset_index(drop=True)で左端のインデックスのみ数字順に並び替えています。

以降ではパーセプトロンのアルゴリズムの部分と計算結果について述べていきます。

>>>続きはこちら。



スポンサードリンク

記事が役に立ったらシェア!

パーセプトロンのアルゴリズム(線形分離)



スポンサードリンク

パーセプトロンのアルゴリズム

データを分類する際の境界を決める手法です。

xy平面で言えば、あるデータ群があった場合、それをうまく二つに分類できるような、xy平面上の直線の方程式を探索することになります。

探索フロー(境界直線の決定)

ここでは簡便なため、データが(x,y)で与えられているとし、それらのデータを二つに分類するものとして話を進めていきます。

  1. 直線の方程式をf(x,y)=w0+w1x+w2y=0 と仮定
  2. f(x,y)>0の時t=1、 f(x,y)<0の時t=-1として二つに分類。与えられたデータ(xn,yn)を上の方程式に代入します。なお一番最初は(w0,w1,w2)はこちらで初期値として指定します。

なお分類が正しければ、f(xn,yn)×tn>0

間違っていれば、f(xn,yn)×tn<0 となります。

そして全ての(xn,yn)において、上が成り立つ直線(w0,w1,w2)を決定していきます(パーセプトロン)。

3.f(xn,yn)×tn<0の点(誤分類のデータ)がある場合、それを「誤差」としてカウントします

あるデータ(xn,yn)における誤差の大きさは次式で定義されます。これは幾何学的(点と直線の距離)にイメージできると思います(下の図を参照してください)。

\begin{eqnarray}
E_{n}=|f(x_{n},y_{n})|
\end{eqnarray}
全ての誤分類データにおける誤差の総量は
\begin{eqnarray}
\sum_{n}E_{n}&=&\sum_{n}|f(x_{n},y_{n})|\\
&=&-\sum_{n}f(x_{n},y_{n})\times t_{n}\\
&=&-\sum_{n}(w_{0}+w_{1}x_n+w_{2}y_{n})\times t_{n}\\
&=&-\sum_{n}t_{n}w^{T}\phi_{n}
\end{eqnarray}
ここで\(w^{T},\phi_{n}\)は次式で定義されるベクトルである。
\begin{eqnarray}
w = \left(
\begin{array}{c}
w_0 \\
w_1 \\
w_2 \\
\end{array}
\right)\\
\phi_{n} = \left(
\begin{array}{c}
1 \\
x_n \\
y_n \\
\end{array}
\right)\\
\end{eqnarray}

4. 総誤差ΣEを0(最小)にするように(w0,w1,w2)を探索していく

最も一般的なものが「確率的勾配降下法」です。


スポンサードリンク

確率的勾配降下法

これは「勾配ベクトル」の意味と「確率的」の意味を考える必要があります。

例えばh(x,y)=\(\frac{3}{4}(x^2+y^2)\)のグラフを考えます。

この場合勾配ベクトルは∇h(x,y)=(\(\frac{3}{2}x,\frac{3}{2}y\))となりますが、勾配ベクトルはその値(図で言うところのピンク)を最も増加させる方向を表しています。-∇hの方向に移動すれば、原点0に近づくことになります。

このことから、現在の居場所をxoldとして次の居場所xnewを求めるアルゴリズムが以下の式で表せられることになります。
\begin{eqnarray}
x_{new}=x_{old}-\nabla h
\end{eqnarray}
たとえ勾配ベクトルが大きく、xを更新した時に原点を通り過ぎても、問題ないことは以下の図でわかると思います。原点を行ったり来たりを繰り返し、最終的に原点にたどり着くと、勾配ベクトルは0になるので、そこで停止することになります。

話を戻します。今、勾配ベクトルは以下の式で計算できます。
\begin{eqnarray}
\nabla E(w) &=& \left(
\begin{array}{c}
\frac{\partial E}{\partial w_{0}} \\
\frac{\partial E}{\partial w_{1}} \\
\frac{\partial E}{\partial w_{2}} \\
\end{array}
\right)\\
&=&-\sum_{n}t_{n}\phi_{n}
\end{eqnarray}
そして誤差を0(最小)に近づけるには、上の例で見たように現在のw=(w0,w1,w2)から勾配ベクトルを引けば良いので、

\begin{eqnarray}
w_{new}=w_{old}+t{_n}\phi_{n}   (1)
\end{eqnarray}
となります。「勾配降下法」の「勾配降下」は勾配ベクトルの反対方向にパラメーターを修正して、誤差関数のグラフを下っていくところからきているのでしょう。

では「確率的」とは何を意味しているのでしょうか?

勾配ベクトルの計算方法について、もう少し深掘りしていきます。

\begin{eqnarray}
\nabla E(w) = -\sum_{n}t_{n}\phi_{n}
\end{eqnarray}
上の式から誤差関数の勾配ベクトルの計算は全ての誤分類されたデータの\(t_{n}\phi_{n}\)を合計することを意味しています。

データが大量にある場合、毎回正しい(w0,w1,w2)を更新していくために\(t_{n}\phi_{n}\)を計算するのは時間がかかるので、誤分類のデータを一つ選んで、とりあえずそのぶんだけパラメータを修正します。

そして修正された新しいwを用いて、また誤分類されたデータのうち一つを選んで同様に式(1)を用いて修正していきます。

このように誤分類データをランダムに選んでパラメータを修正するため「確率的」とついています。



スポンサードリンク


これからは、実際にコードを書いてどのように計算が行われているのか、上の説明を元に論じていきます。

>>>続きはこちら。

記事が役に立ったらシェア!