算法
输入:
- 线性可分的数据集T=(x1,y1),(x2,y2),...,(xN,yN)T={(x_1,y_1),(x_2,y_2),...,(x_N,y_N)}T=(x1,y1),(x2,y2),...,(xN,yN),其中xi∈X=Rn,yi∈Y={−1,1},i=1,2,...,Nx_i∈X=R^n,y_i∈Y=\{-1,1\},i=1,2,...,Nxi∈X=Rn,yi∈Y={−1,1},i=1,2,...,N
- 学习率η(0<η<=1)\eta(0<\eta<=1)η(0<η<=1)
输出:
- w,b
- 感知机模型f(x)=sign(w⋅x+b)f(x)=sign(w·x+b)f(x)=sign(w⋅x+b)
流程:
-
选取初始值w0,b0w_0,b_0w0,b0
-
在训练集中选取数据(xi,yi)(x_i,y_i)(xi,yi)
-
如果yi(w⋅xi+b)<=0y_i(w·xi+b)<=0yi(w⋅xi+b)<=0
w←w+ηyixib←b+ηyi w\leftarrow{w+{\eta}y_ix_i}\\ b\leftarrow{b+{\eta}y_i} w←w+ηyixib←b+ηyi -
跳转至2,直到训练集中没有误分类点
题目
有一训练集T,其正实例的点是x1=(3,3)T,x2=(4,3)Tx_1=(3,3)^T,x_2=(4,3)^Tx1=(3,3)T,x2=(4,3)T,负实例的点是x3=(1,1)Tx_3=(1,1)^Tx3=(1,1)T
求感知机模型f(x)=sign(w⋅x+b)f(x)=sign(w·x+b)f(x)=sign(w⋅x+b),其中,w=(w(1),w(2))Tw=(w^{(1)},w^{(2)})^Tw=(w(1),w(2))T,x=(x(1),x(2))Tx=(x^{(1)},x^{(2)})^Tx=(x(1),x(2))T
解法
-
构建最优化问题
minw,bL(w,b)=−∑xi∈Myi(wi⋅xi+b) \underset{w,b}{min}L(w,b) = -\sum_{x_i∈M}y_i(w_i·x_i+b) w,bminL(w,b)=−xi∈M∑yi(wi⋅xi+b) -
选取步长η\etaη为1
-
初始化w0=0,b0=0w_0=0,b_0=0w0=0,b0=0
-
循环实例x,如果yi(w⋅xi+b)<=0y_i(w·x_i+b)<=0yi(w⋅xi+b)<=0
w←w+ηyixib←b+ηyi w\leftarrow{w+{\eta}y_ix_i}\\ b\leftarrow{b+{\eta}y_i} w←w+ηyixib←b+ηyi -
重复执行第四步,直到没有误分类的点
代码
# -*- coding: UTF-8 -*-
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
class PERCEPTRON:
def __init__(self):
# 这里写死数据,可自行改为动态读取
df = pd.read_excel('../data/perceptronExample.xlsx')
self.df = pd.DataFrame(df)
# 最终的结果
self.w = 0
self.b = 0
'''训练'''
def train(self):
df = self.df
x = df.values[:, :-1] # 提取所有特征向量
y = df.values[:, -1] # 提取分类结果
# 获取特征向量的个数以及每个特征向量的长度
temp = x.shape
n = temp[0]
m = temp[1]
# 初始化w和b
w = np.zeros(m) # w的长度与特征向量长度相同
b = 0
# 循环迭代
flag = True
while flag:
flag = False
# 对每个实例进行计算并更新w和b
for i in range(n):
res = y[i] * (np.dot(w, x[i]) + b) # y(w * x + b),注意w和x是点积
if res <= 0:
w = w + np.dot(y[i], x[i])
b = b + y[i]
flag = True # 有失误,待继续迭代
self.w = w
self.b = b
print("计算得到法向量w={0},b={1}".format(w, b))
'''可视化展示'''
def show(self):
y = self.df.values[:, -1]
x1 = self.df.values[:, 0]
x2 = self.df.values[:, 1]
# 点
for i in range(len(self.df)):
if (y[i] == 1):
s1 = plt.scatter(x1[i], x2[i], c='red')
else:
s2 = plt.scatter(x1[i], x2[i], c='blue')
plt.legend([s1, s2], ['正类', '负类'])
# 线
xmin = self.df.values[:, :-1].min()
xmax = self.df.values[:, :-1].max()
xstep = (xmax - xmin) * 0.5 # 步长
xx = np.linspace(xmin - xstep, xmax + xstep, 3) # 横坐标
yy = -self.w[0] * xx - self.b # 根据得到的参数计算纵坐标
plt.plot(yy, xx)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 中文乱码问题
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.show()
if __name__ == '__main__':
perceptron = PERCEPTRON()
perceptron.train()
perceptron.show()

3004

被折叠的 条评论
为什么被折叠?



