博文配套视频课程:24小时实现从零到AI人工智能
编写函数调整权重
此处与机器学习的线性回归非常像,循环的过程就是不断调整权重与偏置的过程,如果样本有2个特征,那么需要调整的参数为2个权重加一个偏置
def perceptron(xn, yn, max_iter=10000, a=0.1, w=np.zeros(3)):
N = xn.shape[0]
# 函数里面在构造一个函数,对数据样本进行分类
# np.sign() 激活函数,可以把结果转化 1 或者 -1
# x ==> x[0] x[1]
f = lambda x: np.sign(w[0] * 1 + w[1] * x[0] + w[2] * x[1])
# 循环反向传播,如果预测值与标准值不等则修改权重和偏置
for _ in range(max_iter):
# 随机获取一个样本作为测试样本
i = np.random.randint(N)
# yn[i] 是样本的目标值, xn[i,:] 第i个样本的特征值 f(xn[i,:]) 预测值
if (yn[i] != f(xn[i, :])):
# 更新权重与偏置 权重原值 + 目标值 * 输入值 * 学习率
w[0] = w[0] + yn[i] * 1 * a
w[1] = w[1] + yn[i] * xn[i,0] * a
w[2] = w[2] + yn[i] * xn[i,1] * a
return w
寻找超平面
超平面本质上就是样本的分界线,由于当前的样本只有两个特征,那么分界线就是平面上的一条直线,因此通过前面获取的w与b的偏置来求线性参数a与b
w = perceptron(xn,yn,max_iter=10000)
print(w)
# 通过w生成预测分类线函数的a,b的值
bnew = -w[0] / w[2]
anew = -w[1] / w[2]
# 通过a与b生成预测分类线函数
y = lambda x:anew * x + bnew
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.plot(x,y(x),'b--',label="感知器分类线")
plt.legend()
plt.title('感知器生成分类线输出')
plt.show()
感知器分类结果
感知器完整代码如下
import numpy as np
import matplotlib.pyplot as plt
# 生成一条随机的直线
x = np.linspace(0, 1, 2)
print(x)
# 生成直线的方程: y = w * x + b
w = np.random.rand()
b = np.random.rand()
print(f'w={w},b={b}')
# 创建一个函数,返回y值
# def fn(x):
# return w*x+b
fn = lambda x: w * x + b
# 通过可视化来创建直线
plt.plot(x, fn(x), 'r',label='标准分类线')
# 通过直线把生成的100个点分成两个类别
N = 100
xn = np.random.rand(N, 2)
# 存储每个样本的类别 [1,-1]
yn = np.zeros([N, 1])
# 通过之前的直线把样本分成两类
for i in range(N):
if (fn(xn[i, 0]) >= xn[i, 1]):
# 当前的x[i]的点在直线的下方
yn[i] = -1
plt.plot(xn[i, 0], xn[i, 1], 'rx', markersize=8)
else:
yn[i] = 1
plt.plot(xn[i, 0], xn[i, 1], 'go', markersize=8)
# 对于给定的x,y值,感知器要寻找超平面
def perceptron(xn, yn, max_iter=10000, a=0.1, w=np.zeros(3)):
N = xn.shape[0]
# 函数里面在构造一个函数,对数据样本进行分类
# np.sign() 激活函数,可以把结果转化 1 或者 -1
# x ==> x[0] x[1]
f = lambda x: np.sign(w[0] * 1 + w[1] * x[0] + w[2] * x[1])
# 循环反向传播,如果预测值与标准值不等则修改权重和偏置
for _ in range(max_iter):
# 随机获取一个样本作为测试样本
i = np.random.randint(N)
# yn[i] 是样本的目标值, xn[i,:] 第i个样本的特征值 f(xn[i,:]) 预测值
if (yn[i] != f(xn[i, :])):
# 更新权重与偏置 权重原值 + 目标值 * 输入值 * 学习率
w[0] = w[0] + yn[i] * 1 * a
w[1] = w[1] + yn[i] * xn[i,0] * a
w[2] = w[2] + yn[i] * xn[i,1] * a
return w
w = perceptron(xn,yn,max_iter=10000)
print(w)
# 通过w生成预测分类线函数的a,b的值
bnew = -w[0] / w[2]
anew = -w[1] / w[2]
# 通过a与b生成预测分类线函数
y = lambda x:anew * x + bnew
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.plot(x,y(x),'b--',label="感知器分类线")
plt.legend()
plt.title('感知器生成分类线输出')
plt.show()