Hatena::ブログ(Diary)

はすけるとぱいそん

2011-11-11

Pythonでパーセプトロン。

最初Haskellで書こうとして死にました。
こういうプログラムはあまりHaskellには向かないようです(重みを変えてループさせたりとか)。
というわけでPythonでやることに。

こちらの記事が参考になりました。
本当に助かりました。ありがとうございます(ぺこり。

まだイマイチ確率的最急降下法というものが解っていないのですが(ぉぃ、
なにはともあれ書けたのでうp。
すごーくカンタンな例でやってみました。

(しかしなぜブログにうpするとタブがずれるんだ…。)
(あと、np.dotうんちゃらとかarrayうんちゃらとかを使うと、
HaskellのzipWith的な計算できるんだほえーって思った。知らなかった。)

#coding:shift-jis

import numpy as np
from pylab import *

# サンプルデータ。[(x,y,クラス)]。クラスは1か-1の値。
data = [(1,3,1),
		(2,4,1),
		(3,2,1),
		(1,5,-1),
		(2,7,-1),
		(3,6,-1)]

# データを散布図として描画。
for p in data:
	if p[2]==1:
		plot(p[0], p[1],'ro') #クラス1ならプロットを赤に。
	else:
		plot(p[0], p[1],'bo') #クラス-1ならプロットを青に。

# 重みの初期値。
w = array([1.0, 1.0, 1.0])

# 学習係数。
p = 0.01

# 分類が正解したデータ数
correct = 0

# パーセプトロンアルゴリズム。重み調整。
while True:
	for d in data:  # 全データについて検討。
		if np.dot(w, [1, d[0], d[1]]) * d[2] > 0: #分類が正しいならcorrect+1。
			correct += 1
		else:  # 誤分類なら重みを調整。
			w += p * array([1, d[0], d[1]]) * d[2]
	if (correct==len(data)): #全てが正しく分類されたらbreak。
		break
	else: #だめならcorrectを0に戻してループ。
		correct = 0
		continue

# プロットする。
x = linspace(0,5)
y = -w[1]/w[2] * x - w[0]/w[2]
plot(x, y)

#グラフの縦軸横軸の範囲。
xlim(0, 5)
ylim(0, 10)

# 最終的にグラフ描く!
show()

結果はこうなります。

f:id:Mr_Tsubaki:20111111121345p:image

データが6つしかないのでアレですが、とりあえずちゃんと線形分離されています。
Pythonでグラフが描けるなんて初めて知りました(今更。
またいろいろ楽しくなりそうです。

今後は「集合知プログラミング」や「フリーソフトでつくる音声認識システム」の続きを読んだりしながら、
個人的に一番興味のあるサポートベクターマシンSVMを実装していきたいと思います。
なんとか日曜までに形にしたいなあ。
これもまた、こちらの方の記事がものすごく参考になります。
その後非線形のSVMもやりたいです。これはさらに楽しそう。
本当に、本当にありがとうございます(ぺこり。
 
 

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/Mr_Tsubaki/20111111/1320981252