感知机 (perceptron) 是二类分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别。
感知机的取值范围为 1 和 -1 二值。
感知机对应于输入空间中将实例划分为正负两类的分离超平面,属于判别模型。
一、主要思想:
设 w ⃗ \vec w w 为权重项, b b b 为偏置项, x ⃗ \vec x x 为特征值, y y y 为标签
在线性可分的情况下,拟合线性函数
w
⃗
⋅
x
⃗
+
b
\vec w\cdot\vec x+b
w⋅x+b,使得:
s
i
g
n
(
w
⃗
⋅
x
⃗
+
b
)
=
{
1
≥
0
−
1
<
0
\mathrm{sign}(\vec w\cdot\vec x+b)=\begin{cases}1&\ge0\\-1&<0\end{cases}
sign(w⋅x+b)={1−1≥0<0
也就是: s i g n ( w ⃗ ⋅ x ⃗ + b ) y ≥ 0 \mathrm{sign}(\vec w\cdot\vec x+b)y\ge0 sign(w⋅x+b)y≥0
二、误分类点:
根据上文,很容易知道对于一个特征向量
x
⃗
\vec x
x 如果误分类了,则会有:
s
i
g
n
(
w
⃗
⋅
x
⃗
+
b
)
y
<
0
\mathrm{sign}(\vec w\cdot\vec x+b)y<0
sign(w⋅x+b)y<0
借此可以很方便的找出误分类点。
三、损失函数:
把误分类点到线性函数的距离作为误差,组成损失函数:
l
o
s
s
F
u
n
c
=
−
(
w
⃗
⋅
x
⃗
+
b
)
y
∥
w
∥
2
lossFunc=-\frac{(\vec w\cdot\vec x+b)y}{\parallel w\parallel_2}
lossFunc=−∥w∥2(w⋅x+b)y
四、更新权重项与偏置项:
采用梯度下降的方法进行更新。设
L
(
w
⃗
,
b
)
=
l
o
s
s
F
u
n
c
L(\vec w,b) = lossFunc
L(w,b)=lossFunc 我们要使
L
(
w
⃗
,
b
)
L(\vec w,b)
L(w,b) 的值尽量小,则可以求其梯度的负数
−
∇
L
-\nabla L
−∇L 即为该函数下降最快的方向,但是注意,通过这个方法可能无法到达全局最优点,可能会到达局部最优点或鞍点。不过这无所谓,对于感知机来说这就足够了。
−
∇
L
=
<
x
⃗
y
,
y
>
w
⃗
=
w
⃗
+
α
x
⃗
y
b
=
b
+
α
y
\begin{aligned}-\nabla L&=<\vec xy,y>\\\vec w&=\vec w+\alpha\vec xy\\b&=b+\alpha y\end{aligned}
−∇Lwb=<xy,y>=w+αxy=b+αy
其中
α
\alpha
α 是学习率,要注意
x
⃗
y
\vec xy
xy 是一个向量。
模板:
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()
以及调库实现:
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))
同步更新于:SP-FA 的博客