感知机是机器学习入门的第一个算法,也是最简单的算法。我们可以从理论上证明,对于一个线性可分的分类问题,感知机总能在有限次迭代后从无限的假设空间中找到一个解。
代码所做的工作主要是假定分界线f已知,由此随机生成数据,然后用感知机模型找到一个边界并显示在图上。
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号
#判断是否所有样本已被正确分类
def judge(X, y, w):
n = X.shape[0]
# 判断是否同号
num = np.sum(X.dot(w) * y > 0)
return num == n
#生成N个d维点(不包括偏置项1),x1+...+xd>0的点标记为+1,x1+...+xd<=0的点标记为-1
def data(N, d, rnd):
X = []
w = np.ones(d)
while (len(X) < N):
#rnd为随机数生成器,rnd = np.random.RandomState(seed),seed为随机种子
x = rnd.uniform(-1, 1, size=(d))
if x.dot(w) != 0:
X.append(x)
X = np.array(X)
y = 2 * (X.dot(w) > 0) - 1
# 添加第一个分量为1
X = np.c_[np.ones((N, 1)), X]
return X, y
def f(N, d, rnd):
#生成数据
X, y = data(N, d, rnd)
#迭代次数
s = 0
#初始化w
w = np.zeros(d + 1)
#样本数
n = X.shape[0]
while(judge(X, y, w) == 0):
for i in range(n):
if X[i, :].dot(w) * y[i] <= 0:
w = w + y[i] * X[i, :]
s = s + 1
return X, y, w, s
#画出感知机找到的边界
def border_plot(X, y, w, s):
x1 = np.arange(-1, 1, 0.1)
x2 = np.arange(-1, 1, 0.1)
x1, x2 = np.meshgrid(x1, x2)
plt.scatter(X[y == 1][:, 1], X[y == 1][:, 2], c='r', s=1)
plt.scatter(X[y == -1][:, 1], X[y == -1][:, 2], c='b', s=1)
f = w[0] + w[1] * x1 + w[2] * x2
plt.contour(x1, x2, f, 0,)
plt.title(u"经过" + str(s) + u"次迭代收敛")
plt.show()
#初始化参数并运行
seed = 20
rnd = np.random.RandomState(seed)
N = 30
d = 2
X, y, w, s = f(N, d, rnd)
border_plot(X, y, w, s)
运行结果示例: