统计学习方法 第2章+ 感知机python实现
生成训练数据
假设希望产生的分离超平面为2*x1+5*x2-3*x3-10=0
,在0~5的范围内随机生成x1,x2,x3,计算其应有的分类结果并加入训练数据集。
import random
#每类需要的数量
NUM = 1000
#计数
counter1 = 0
counter0 = 0
#存放训练集
lines = []
#超平面函数
def fx(x1, x2, x3):
return 2 * x1 + 5 * x2 - 3 * x3 - 10;
while(1):
#生成x1,x2,x3
x1 = random.random() * 5
x2 = random.random() * 5
x3 = random.random() * 5
f = open('data.txt', 'w')
#根据分类结果将对应数据项加入数据集
if fx(x1, x2, x3) > 0:
counter1 += 1
if counter1 <= NUM:
line = str(x1) + ',' + str(x2) + ',' + str(x3) + ',' + '1' + '\n'
lines.append(line)
elif fx(x1, x2, x3) < 0:
counter0 += 1
if counter0 <= NUM:
line = str(x1) + ',' + str(x2) + ',' + str(x3) + ',' + '-1' + '\n'
lines.append(line)
if counter1 >= NUM and counter0 >= NUM:
break
#写入文件供感知机程序读取
f.writelines(lines)
f.close()
生成的数据集:
感知机实现
读取上一步生成的训练数据集,依据感知机学习算法进行学习。
import numpy as np
#数据维度
DIM = 3
#学习率
LR = 0.01
#训练数据总数
SAMPLE_NUM = 2000
#符号函数
def sign(x):
if x > 0:
return 1
if x < 0:
return -1
#检查当前模型在整个数据集上分类结果的正确和错误数
def test(w, b, data):
right = 0
wrong = 0
for d in data:
y = np.vdot(w, d[:-1]) + b
if sign(y[0]) == d[-1]:
right += 1
else:
wrong += 1
print('result: ', 'right ', right, 'wrong ', wrong)
return right
#权值w
w = np.zeros((DIM))
#偏置b
b = np.zeros(1)
#读取数据并切分,转换为float
f = open('data.txt', 'r')
lines = f.readlines()
f.close()
data = [l[:-1].split(',') for l in lines]
data = [list(map(float, l)) for l in data]
#训练轮数
epoch = 0
while(1):
epoch += 1
print('epoch: ', epoch)
#对每条数据,若分类错误即更新w和b
for d in data:
x = d[:-1]
y = np.vdot(x, w) + b
if y[0] * d[-1] <= 0:
w += np.multiply(LR * d[-1], x)
b += LR * d[-1]
#直到所有数据均分类正确
if test(w, b, data) == SAMPLE_NUM:
break
print('w:', w, 'b:', b)
print(w[0] / b[0], w[1] / b[0], w[2] / b[0])
运行结果:
可见,经过120轮训练后得到w,b,且w1,w2,w3比b的值接近-0.2,-0.5和0.3,与原函数2*x1+5*x2-3*x3-10=0
相符。