主要思想


设 $\vec w$ 为权重项,$b$ 为偏置项,$\vec x$ 为特征值,$y$ 为标签

线性可分的情况下,拟合线性函数 $\vec w\cdot\vec x+b$,使得:

也就是:


误分类点


根据上文,很容易知道对于一个特征向量 $\vec x$ 如果误分类了,则会有:

借此可以很方便的找出误分类点。


损失函数


把误分类点到线性函数的距离作为误差,组成损失函数:


更新权重项与偏置项


采用梯度下降的方法进行更新。设 $L(\vec w,b) = lossFunc$ 我们要使 $L(\vec w,b)$ 的值尽量小,则可以求其梯度的负数 $-\nabla L$ 即为该函数下降最快的方向,但是注意,通过这个方法可能无法到达全局最优点,可能会到达局部最优点或鞍点。不过这无所谓,对于感知机来说这就足够了。

其中 $\alpha$ 是学习率,要注意 $\vec xy$ 是一个向量。

模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import numpy as np

X_train = np.array([[1, 1], [1, 0], [0, 1], [0, 0]])
Y_train = np.array([1, 1, 1, -1])

class perceptron:
def __init__(self, X, Y, Alpha = 0.01): # X, Y can be list or numpy.ndarray
self.alpha = Alpha
self.X_trn = np.array(X)
self.Y_trn = np.array(Y)
self.B = np.random.rand()
self.W = np.random.rand(len(X[0]))

def check(self, i):
Sum = np.dot(self.W, self.X_trn[i]) + self.B
if (Sum * self.Y_trn[i] >= 0):
return True
else:
return False

def Loss_func(self, i):
self.W += self.alpha * self.X_trn[i] * self.Y_trn[i]
self.B += self.alpha * self.Y_trn[i]

def train(self):
Error = True
while (Error):
Error = False
for i in range(len(self.X_trn)):
if (self.check(i) == False):
self.Loss_func(i)
Error = True
print("W: ", self.W, "\tB: ", self.B)

per = perceptron(X_train, Y_train, 0.01)
per.train()

以及调库实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Perceptron

My_Data = datasets.load_iris()
clf = Perceptron()
x = My_Data['data']
y = My_Data['target']
train_x, test_x, train_y, test_y = train_test_split(x, y, test_size = 0.3)

clf.fit(train_x, train_y)
clf.predict(test_x)
print(clf.score(test_x, test_y))