感知机于1957年由Rosenblatt提出,是神经网络和支持向量机的基础。适用于二类分类的线性分类模型,通过输入特征向量,输出得到实例的类别。
感知机对应于输入空间中将实例划分为正负两类的分离超平面。
主要思想就是:导入基于误分类的损失函数,利用梯度下降法对损失函数最小化,求得感知机模型。
在下例中,调用了鸢尾花数据集,特征集Y选取的是三类中的其中两类分类;由于想把特征可视化,选取特征集中的两类。预测时,如果 yi*(xi@w+b) <= 0,意味着预测出来的分类与实际分类不同号,为误分类点,则就这个误分类点进行优化,更新w和b。
同时,此表达式也可以用来代表误分类点与超平面的距离,基于其对w、b求偏导,进行梯度下降即可。
迭代直到没有误分类点为止。
from sklearn.datasets import load_iris
import numpy as np
from matplotlib import pyplot as plt
def pre_processing(X, Y, feat_num, cla_num):
mask = Y < cla_num
Y = Y[mask]
X = X[mask]
X = X[:, :feat_num]
Y = np.where(Y == 1, 1, -1)
return X, Y
def picture(X,Y):
fig, ax = plt.subplots()
idx0 = (Y == -1)
idx1 = (Y == 1)
ax.scatter(X[idx0, 0], X[idx0, 1], label='0')
ax.scatter(X[idx1, 0], X[idx1, 1], label='1')
ax.plot(X[:, 0], -(X[:, 0] * test_demo.w[0] + test_demo.b) / test_demo.w[1], c='red', label='fit') # X1W1+X2W2+B = 0 ,X2 = ...
ax.legend()
plt.show()
class Perceptron:
def __init__(self, X, Y, lr):
self.X = X
self.Y = Y
self.lr = lr
self.w = -1
self.b = -1
def get_param_w(self):
self.w = np.ones((self.X.shape[1],), dtype=np.float64)
def get_param_b(self):
self.b = 0
def get_param(self):
self.get_param_w()
self.get_param_b()
def train(self):
count = 0
while (1):
count += 1
err_num = 0
num = self.X.shape[0]
for i in range(num):
X = self.X[i]
Y = self.Y[i]
if Y * (X @ self.w + self.b) <= 0:
err_num += 1
self.optimizer(X, Y)
break
if err_num == 0:
break
print(count)
def optimizer(self, X, Y):
self.w += X * Y * self.lr
self.b += Y * self.lr
if __name__ == '__main__':
data = load_iris()
x, y = data['data'], data['target']
feat_num = 2
cla_num = 2
lr = 0.1
x, y = pre_processing(x, y, feat_num, cla_num)
test_demo = Perceptron(x, y, lr)
test_demo.get_param()
test_demo.train()
picture(x,y)