機械学習の初歩ということでパーセプトロンを実装してみました.
パーセプトロンとは2値識別器です.
クラスは1イテレーションを表しています.
2次元以上でも計算できるようにしました.
import sys from optparse import OptionParser import matplotlib as mpl mpl.use('PDF') import matplotlib.pyplot as plt import numpy import random def get_train_data(filename): '''make dictionary from training data''' train = [] with open(filename) as f: for line in f: line = line.split() train.append((line)) return train def plot_point(train_data): '''plot points with color''' for coord in train_data: if int(coord[-1])==1: c = 'b' else: c = 'r' plt.scatter(float(coord[0]),float(coord[1]),color=c) def plot_line(weight,bias): '''plot result line''' x = [-1.0,1.0] # from -1.0 to 1.0 y = [-weight[0]*xi/weight[1]+bias/weight[1] for xi in x] plt.plot(x,y) def make_train_data(N): '''make random training data''' w0 = numpy.array([-0.2, 0.5, -1]) x1, x2 = -1 + numpy.random.rand(N)*2, -1 + numpy.random.rand(N)*2 t = (w0[0]+x1*w0[1]+x2*w0[2]>=0) * 2 - 1 return x1,x2,t class Perceptron(object): '''Perceptron class learns one iteration. when you call this function learning(), it complete one iteration for training dataset.''' def __init__(self,train_data,eta,bias): '''train_data is x which is coords''' dimention = len(train_data[0])-1 self.weight = [0.0 for i in range(dimention)] self.bias = bias self.eta = eta def activation(self,coord): '''this is an activation function. so it returns positive or negative''' summation = sum(map((lambda x,y: float(x)*y),coord[:-1],self.weight)) - self.bias if summation>=0: self.output = 1 else: self.output = -1 def calc_value(self,coord): self.value = float(coord[-1])-self.output def update_weights(self,coord): '''update weight parameters ''' new_weight = [] for i,w in enumerate(self.weight): va = w+self.eta*(self.value)*float(coord[i]) new_weight.append(va) self.weight = new_weight def update_bias(self): '''update bias parameter''' self.bias -= self.eta*(self.value) def learning(self): '''learning parameters''' for coord in train_data: self.activation(coord) self.calc_value(coord) self.update_weights(coord) self.update_bias() if __name__ == '__main__': usage = 'usage: %prog FILE [options]' parser = OptionParser(usage) parser.add_option('--iter',dest='iter',type='int',default = 16) parser.add_option('-b',dest='bias',type='float',default = 0.0) parser.add_option('-e',dest='eta',type='float',default = 1.0) parser.add_option('-f','--file',dest='filename',default = '') (options,args) = parser.parse_args() if options.filename=="": m = make_train_data(50) train_data = zip(m[0],m[1],m[2]) else: train_data = get_train_data(options.filename) PR = Perceptron(train_data,options.eta,options.bias) for i in range(options.iter*len(train_data)): PR.learning() print PR.weight,PR.bias plot_point(train_data) plot_line(PR.weight,PR.bias) plt.savefig('output')
eta:学習率
bias:PDFで言うθ
weight:これはそのまま重み
- グラフによる直感的な意味
- weightは原点を中心とした向きを表している.従って,グラフでは重みを変えると回転するイメージ
- biasは原点からの距離を表している.従ってグラフではbiasを変えると平行移動する.
- 学習率は1回の学習でどれくらいパラメータを変えるかの度合い.小さければパラメータの更新も少ない.
またORの入力だったら
0 0 -1 0 1 1 1 0 1 1 1 1
こういうテキストファイルを読み込ませても出力出来る。
結果は以下
参考文献
パーセプトロンのPDF
パーセプトロンとNNのコード書いてみた - きちめも
他にもテキストマイニングのための機械学習超入門 二夜目 パーセプトロン - あんちべ!などで詳しく解説されてます.