感知机原理
-
感知机是二分类的线性模型,其输入是实例的特征向量,输出的是实例的类别,分别是+1和-1,属于判别模型。
假设训练数据集是线性可分的,感知机学习的目标是求得一个能够将训练数据集 正实例点和负实例点完全正确分开的分离超平面 。如果是非线性可分的数据,则最后无法获得超平面 -
点到线的距离
- 公式中的直线方程为
A
x
+
B
y
+
C
=
0
A x+B y+C=0
Ax+By+C=0 , 点
P
P
P 的坐标为
(
x
0
,
y
0
)
\left(x_{0}, y_{0}\right)
(x0,y0) 。
d = A x 0 + B y 0 + C A 2 + B 2 d=\frac{A x_{0}+B y_{0}+C}{\sqrt{A{2}+B{2}}} d=A2+B2Ax0+By0+C
- 公式中的直线方程为
A
x
+
B
y
+
C
=
0
A x+B y+C=0
Ax+By+C=0 , 点
P
P
P 的坐标为
(
x
0
,
y
0
)
\left(x_{0}, y_{0}\right)
(x0,y0) 。
-
样本到超平面距离
- 我们假设超平面是
h
=
w
⋅
x
+
b
h=w \cdot x+b
h=w⋅x+b , 其中
w
=
(
w
0
,
w
1
,
…
w
m
)
,
x
=
(
x
0
,
x
1
,
…
x
m
)
w=\left(w_{0}, w_{1}, \ldots w_{m}\right), x=\left(x_{0}, x_{1}, \ldots x_{m}\right)
w=(w0,w1,…wm),x=(x0,x1,…xm) , 样本点
x
′
x^{\prime}
x′ 到超平面的距离如下:
d = w ⋅ x ′ + b ∥ w ∥ d=\frac{w \cdot x^{\prime}+b}{\|w\|} d=∥w∥w⋅x′+b
- 我们假设超平面是
h
=
w
⋅
x
+
b
h=w \cdot x+b
h=w⋅x+b , 其中
w
=
(
w
0
,
w
1
,
…
w
m
)
,
x
=
(
x
0
,
x
1
,
…
x
m
)
w=\left(w_{0}, w_{1}, \ldots w_{m}\right), x=\left(x_{0}, x_{1}, \ldots x_{m}\right)
w=(w0,w1,…wm),x=(x0,x1,…xm) , 样本点
x
′
x^{\prime}
x′ 到超平面的距离如下:
-
超平面(Hyperplanes)
- 超平面是在空间 R d R^d Rd中的一个子空间 R d − 1 R^{d-1} Rd−1。在2维空间中的超平面是一条线,在3维空间中的超平面是-一个平面。
感知机模型
- 定义 感知机假设输入空间(特征空间)是
X
⊆
R
n
X \subseteq R^{n}
X⊆Rn , 输出空间是
y
=
{
+
1
,
−
1
}
∘
\mathrm{y}=\{+1,-1\}_{\circ}
y={+1,−1}∘ 输入
x
∈
X
x \in X
x∈X 表示实例的特征向量, 对应于输入空间(特征空间)的点; 输出
y
∈
Y
y \in Y
y∈Y 表示实例的类别。有输入空间到输出空间的如下函数
f
(
x
)
=
sign
(
w
∙
x
+
b
)
f(x)=\operatorname{sign}(w \bullet x+b)\quad
f(x)=sign(w∙x+b)称为感知机。其中
w
w
w和
b
b
b为感知机模型参数,
w
∈
R
n
w \in R^{n}
w∈Rn 叫做权值(weight)或权值向量(weight vector),
b
∈
R
b \in R
b∈R 叫作偏置(bias),
w
∙
x
w \bullet x
w∙x 表示
w
\mathrm{w}
w 和
x
\mathrm{x}
x 的内积。
sign
\operatorname{sign}
sign 是符号函数,即:
sign ( x ) = { + 1 , x ⩾ 0 − 1 , x < 0 \operatorname{sign}(x)= \begin{cases}+1, & x \geqslant 0 \\ -1, & x<0\end{cases} sign(x)={+1,−1,x⩾0x<0 - 感知机是一种线性分类模型,属于判别模型
- 感知机的几何解释是线性方程:
w ∙ x + b = 0 w \bullet x+b=0 w∙x+b=0
对应于特征空间 R n R^{n} Rn中的一个超平面 S S S,其中 w w w是从超平面的法向量, b b b是超平面的截距。
这个超平面将特征空间划分为两个部分。位于两部分的点(特征向量)分别被分为 正、负两类 。
因此,超平面S成为分离超平面(separating hyperplane),如图2.1所示。
感知机学习,由训练数据集(实例的特征向量及类别)
T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x N , y N ) } } T=\left\{\left(x_{1}, y_{1}\right),\left(x_{2}, y_{2}\right), \ldots,\left(x_{N}, y_{N}\right)\right\}\} T={(x1,y1),(x2,y2),…,(xN,yN)}}
其中 x i ∈ X = R n , y i ∈ Y = { + 1 , − 1 } , i = 1 , 2 , … , N x_{i} \in X=R^{n}, y_{i} \in Y=\{+1,-1\}, i=1,2, \ldots, N xi∈X=Rn,yi∈Y={+1,−1},i=1,2,…,N , 求得感知机模型 f ( x ) f(x) f(x) , 即求得模型参数 w , b ∘ w, b_{\circ} w,b∘ 感知机预测, 通过学习得到的感知机模型, 对于新的输入实例给出其对应的输出类别。- 证明为什么w是直线(高维空间下为超平面)的法向量
- 证明为什么w是直线(高维空间下为超平面)的法向量
感知机的学习策略
损失函数
-
损失函数的一个自然选择是误分类点的总数, 但是这样损失函数不是参数 w w w和 b b b的连续可到函数, 不易优化。 损失函数的另一个选择是误分类点到超平面 S S S的总距离, 这是感知机所采用的。为此,首先写出输入空间 R n R^{n} Rn 中任一点 x 0 x_{0} x0 到超平面S的距离 1 ∥ w ∥ ∣ w ∙ x 0 + b ∣ \frac{1}{\|w\|}\left|w \bullet x_{0}+b\right| ∥w∥1∣w∙x0+b∣,这里, ∥ w ∥ \|w\| ∥w∥ 是w的 L 2 L_{2} L2 范数。其次, 对于误分类的数据 ( x i , y i ) \left(x_{i}, y_{i}\right) (xi,yi) 来说, − y i ( w ∙ x i + b ) > 0 -y_{i}\left(w \bullet x_{i}+b\right)>0 −yi(w∙xi+b)>0 成立。因为当 w ∙ x i + b > 0 w \bullet x_{i}+b>0 w∙xi+b>0 时, y i = − 1 y_{i}=-1 yi=−1, 而当 w ∙ x i + b < 0 w \bullet x_{i}+b<0 w∙xi+b<0 时, y i = + 1 y_{i}=+ 1 yi=+1 。因此, 误分类点 x i x_{i} xi 到超平面S的距离是 1 ∥ w ∥ y i ( w ∙ x i + b ) \frac{1}{\|w\|} y_{i}\left(w \bullet x_{i}+b\right) ∥w∥1yi(w∙xi+b) 这样, 假设超平面 S S S的误分类点集合为 M , M, M, 那么所有误分类点到超平面S的总距离为 1 ∥ w ∥ ∑ x i ∈ M y i ( w ∙ x i + b ) \frac{1}{\|w\|} \sum_{x_{i}\in M} y_{i}\left(w \bullet x_{i}+b\right) ∥w∥1∑xi∈Myi(w∙xi+b)不考虑 1 ∥ w ∥ \frac{1}{\|w\|} ∥w∥1, 就得到感知机学习的损失函数。
-
为什么不考虑 1 ∥ w ∥ \frac{1}{\|w\|} ∥w∥1??
有人说 1 ∥ w ∥ \frac{1}{\|w\|} ∥w∥1 是个定值, 但是我觉得平面不唯一, 这个值肯定也会变。通过参考他人观点结合思考, 觉得原因可以列为以下两点。- 1 ∥ w ∥ \frac{1}{\|w\|} ∥w∥1 不影响 y i ( w ⋅ x i + b ) y_{i}\left(w \cdot x_{i}+b\right) yi(w⋅xi+b) 正负的判断, 即不影响学习算法的中间过程。因为感知机学习算法是误分类驱动的, 这里需要注意 的是所谓的 “误分类驱动" 指的是我们只需要判断 − y i ( w ⋅ x i + b ) - y_{i}\left(w \cdot x_{i}+b\right) −yi(w⋅xi+b) 的正负来判断分类的正确与否, 而 1 ∥ w ∥ \frac{1}{\|w\|} ∥w∥1 并不影响正负值的判断。所以 1 ∥ w ∥ \frac{1}{\|w\|} ∥w∥1 对感知机学习算法的中间过程可以不考虑。
- 1 ∥ w ∥ \frac{1}{\|w\|} ∥w∥1 不影响感知机学习算法的最终结果。因为感知机学习算法最终的终止条件是所有的输入都被正确分类, 即不存在误分类的点。则此时损失函数为 0 . 对应于 − 1 ∥ w ∥ ∑ i ∈ M y i ( w ⋅ x i + b ) -\frac{1}{\|w\|} \sum_{i \in M} y_{i}\left(w \cdot x_{i}+b\right) −∥w∥1∑i∈Myi(w⋅xi+b) , 即分子为 0 . 则可以看出 1 ∥ w ∥ \frac{1}{\|w\|} ∥w∥1 对最终结果也无影响。
综上所述, 即使忽略 1 ∥ w ∥ \frac{1}{\|w\|} ∥w∥1 , 也不会对感知机学习算法的执行过程产生任何影响。反而还能简化运算, 提高算法执行效率。
感知机学习算法
原始形式
- 算法 2.1 (感知机学习算法的原始形式)
输入: 训练数据集 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x N , y N ) } , 其 中 x i ∈ X = R n , y i ∈ Y = − 1 , + 1 , i = 1 , 2 , … , N T=\left\{\left(x_{1}, y_{1}\right),\left(x_{2}, y_{2}\right), \ldots,\left(x_{N}, y_{N}\right)\right\} , 其中 x_{i} \in X=R^{n}, y_{i} \in Y=-1,+1, i=1,2, \ldots, N T={(x1,y1),(x2,y2),…,(xN,yN)},其中xi∈X=Rn,yi∈Y=−1,+1,i=1,2,…,N ; 学习率 η ( 0 < η ≤ 1 ) \eta(0<\eta \leq 1) η(0<η≤1) ;
输出: w w w, b b b; 感知机模型 f ( x ) = sign ( w ∙ x + b ) f(x)=\operatorname{sign}(w \bullet x+b) f(x)=sign(w∙x+b)- 选取初值 w 0 w_{0} w0, b 0 b_{0} b0
- 在训练集中选取数据 ( x i , y i ) \left(x_{i}, y_{i}\right) (xi,yi)
- 如果
y
i
(
w
⋅
x
i
+
b
)
⩽
0
y_{i}\left(w \cdot x_{i}+b\right) \leqslant 0
yi(w⋅xi+b)⩽0,
w ← w + η y i x i b ← b + η y i \begin{aligned} &w \leftarrow w+\eta y_{i} x_{i} \\ &b \leftarrow b+\eta y_{i} \end{aligned} w←w+ηyixib←b+ηyi - 转至 2 2 2,直至训练集中没有误分类点。
- 直观解释当一个实例点被误分类,及位于分离超平面的错误一侧时,则调整w, b的值,使分离超平面向该误分类点的一侧移动,以减少该误分类点与超平面的距离,直至超平面越过该误分类点使其被正确分类。
过渡到对偶形式
对偶形式的基本想法是, 将 w w w 和 b b b 表示为实例 x i x_{i} xi 和标记 y i y_{i} yi 的线性组合的形式, 通过求解其系数而求得 w w w 和 b b b 。不失一般性, 假设初始值 w 0 , b 0 w_{0}, b_{0} w0,b0 均为 0 。对误分类点 ( x i , y i ) \left(x_{i}, y_{i}\right) (xi,yi) 通过
w ← w + η y i x i b ← b + η y i \begin{aligned} &w \leftarrow w+\eta y_{i} x_{i} \\ &b \leftarrow b+\eta y_{i} \end{aligned} w←w+ηyixib←b+ηyi
逐步修改 w , b w, b w,b, 设修改 n n n 次, 则 w , b w, b w,b 关于 ( x i , y i ) \left(x_{i}, y_{i}\right) (xi,yi) 的增量分别是 α i y i x i \alpha_{i} y_{i} x_{i} αiyixi 和 α i y i \alpha_{i} y_{i} αiyi, 这里 α i = n i η \alpha_{i}=n_{i} \eta αi=niη. 这样, 从学习过程不难看出, 最后学习到的 w , b w, b w,b 可以分别表示为
w = ∑ i = 1 N α i y i x i b = ∑ i = 1 N α i y i \begin{gathered} w=\sum_{i=1}^{N} \alpha_{i} y_{i} x_{i} \\ b=\sum_{i=1}^{N} \alpha_{i} y_{i} \end{gathered} w=i=1∑Nαiyixib=i=1∑Nαiyi
对偶形式
-
算法 2.2 (感知机学习算法的对偶形式)
输入:线性可分的数据集 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x N , y N ) } T=\left\{\left(x_{1}, y_{1}\right),\left(x_{2}, y_{2}\right), \ldots,\left(x_{N}, y_{N}\right)\right\} T={(x1,y1),(x2,y2),…,(xN,yN)}, 其中 x i ∈ R , y i ∈ { − 1 , + 1 } , i = 1 , 2 , … , N x_{i} \in R, y_{i} \in\{-1,+1\}, i=1,2, \ldots, N xi∈R,yi∈{−1,+1},i=1,2,…,N ; 学习率 η ( 0 < η ≤ 1 ) ; \eta(0<\eta \leq 1) \text { ; } η(0<η≤1) ;
输出: α , b ; \alpha, b ; α,b;感知机模型 f ( x ) = sign ( ∑ j = 1 N α j y j x j ∙ x + b ) f(x)=\operatorname{sign}\left(\sum_{j=1}^{N} \alpha_{j} y_{j} x_{j} \bullet x+b\right) f(x)=sign(∑j=1Nαjyjxj∙x+b)
其中 α = ( α 1 , α 2 , … , α N ) T \alpha=\left(\alpha_{1}, \alpha_{2}, \ldots, \alpha_{N}\right)^{T} α=(α1,α2,…,αN)T- α ← 0 , b ← 0 \alpha \leftarrow 0, b \leftarrow 0 α←0,b←0
- 在训练集中选取数据 ( x i , y i ) \left(x_{i}, y_{i}\right) (xi,yi)
- 如果
y
i
(
∑
j
=
1
N
α
j
y
j
x
j
∙
x
i
+
b
)
≤
0
y_{i}\left(\sum_{j=1}^{N} \alpha_{j} y_{j} x_{j} \bullet x_{i}+b\right) \leq 0
yi(∑j=1Nαjyjxj∙xi+b)≤0
α i ← α i + η b ← b + η y i \begin{aligned} &\alpha_{i} \leftarrow \alpha_{i}+\eta \\ &b \leftarrow b+\eta y_{i} \end{aligned} αi←αi+ηb←b+ηyi - 转至
2
2
2直到没有误分类数据。
对偶形式中训练实例仅以内积的形式出现,为了方便,可以预先将训练集中实例间的内积计算出来并以矩阵形式存储,这个矩阵就是所谓的Gram矩阵(Gram matrix)
G = [ x i ∙ x j ] M × N G=\left[x_{i} \bullet x_{j}\right]_{M \times N} G=[xi∙xj]M×N -
问题
-
Gram矩阵是如何计算的?
-
对偶形式求得的浮点数如何处理?
w w w不用必须是整数,浮点数也可以 -
怎么理解 η i \eta_{i} ηi??
η i \eta_{i} ηi表示的是第 i i i 个样本点被误判的次数,而感知机一般形式中的 w w w 其实就是每个样本点被误判的次数乘以 x i y i x_{i}y_{i} xiyi的累加和,也就是 ∑ i = 1 N η i η x i y i \sum _ { i = 1 } ^ { N } \eta_{i}{\eta}x_{i}y_{i} ∑i=1Nηiηxiyi。在每次迭代的时候, η i \eta_{i} ηi表示的是到当前为止,第 i i i 个样本点被误判的次数,这个很重要。因为要反复让样本点中的输入 x x x两两相乘(这个在一般形式中计算 w w w的时候也要这样,自己模拟一遍就发现了),所以提前搞成一个矩阵存起来,类似于平时刷算法题说的打表。所以两个形式本质上是一样的,不过把 w w w用另外一种形式表示。
-
思考
N N N为训练集大小, n n n为特征数量
- 对偶形式:扫一遍 N N N,计算每条数据在之前被加了几个( a i a_{i} ai)次(当 η \eta η取 1 1 1时, a i a_{i} ai相当于第i组数据的梯度 x i y i x_{i}y_{i} xiyi被加了几次,找到一个误分点后直接加上,而不是每次加),因为 x i x j x_{i}x_{j} xixj已经被提前计算在Gram矩阵中,所以每次是 O ( 1 ) O(1) O(1),那么扫一遍 N N N就是 O ( N ) O(N) O(N)。
- 原始形式:每次计算 w ∗ x w*x w∗x,计算此内积复杂度为 O ( n ) O(n) O(n)
所以看下来,选择哪种计算方法取决于训练集和特征数量的大小。
代码实现
原始形式
- 对于输入空间,感知机通过以下函数将其映射至
{
+
1
,
−
1
}
}
\{+1,-1\}\}
{+1,−1}} 的输出空间
f ( x ) = sign ( w ⋅ x + b ) f(x)=\operatorname{sign}(w \cdot x+b) f(x)=sign(w⋅x+b)- 对于所有的错分类点
i
∈
M
i \in M
i∈M , 都有
−
y
i
(
w
⋅
x
i
+
b
)
>
0
-y_{i}\left(w \cdot x_{i}+b\right)>0
−yi(w⋅xi+b)>0 , 因此我们可以定义如下的损失函数作为优化准则:
L ( w , b ) = − ∑ x i ∈ M y i ( w ⋅ x i + b ) L(w, b)=-\sum_{x_{i} \in M} y_{i}\left(w \cdot x_{i}+b\right) L(w,b)=−∑xi∈Myi(w⋅xi+b) - 通过求解损失函数的梯度,
∇ w L ( w , b ) = − ∑ x i ∈ M y i x i ∇ b L ( w , b ) = − ∑ x i ∈ M y i \begin{array}{l}\nabla_{w} L(w, b)=-\sum_{x_{i} \in M} y_{i} x_{i} \\\nabla_{b} L(w, b)=-\sum_{x_{i} \in M} y_{i}\end{array} ∇wL(w,b)=−∑xi∈Myixi∇bL(w,b)=−∑xi∈Myi - 很容易就可以得到感知机学习算法的原始形式
w ← w + η y i x i b ← b + η y i \begin{array}{l} w \leftarrow w+\eta y_{i} x_{i} \\ b \leftarrow b+\eta y_{i} \end{array} w←w+ηyixib←b+ηyi - 整个算法流程如下:
- 选取初值 w 0 , b 0 w_{0}, b_{0} w0,b0
- 在训练集中任意选取点 ( x i , y i ) (x_{i},y_{i}) (xi,yi)
- 如果 − y i ( w ⋅ x i + b ) > 0 - y_{i}\left(w \cdot x_{i}+b\right)>0 −yi(w⋅xi+b)>0 则按照 3 3 3式更新 w , b \mathrm{w}, \mathrm{b} w,b
- 重复 2 2 2直到没有被误分的点
- 对于所有的错分类点
i
∈
M
i \in M
i∈M , 都有
−
y
i
(
w
⋅
x
i
+
b
)
>
0
-y_{i}\left(w \cdot x_{i}+b\right)>0
−yi(w⋅xi+b)>0 , 因此我们可以定义如下的损失函数作为优化准则:
from __future__ import division
import random
import numpy as np
import matplotlib.pyplot as plt
def train(epoch,train_datas,lr):
w=0.0
b=0
datas_len = len(train_datas)
alpha = [0 for i in range(datas_len)]
train_array = np.array(train_datas)
gram = np.dot(train_array[:,0:-1] , train_array[:,0:-1].T)
for idx in range(epoch):
tmp=0
i = random.randint(0,datas_len-1)
yi=train_array[i,-1]
for j in range(datas_len):
tmp+=alpha[j]*train_array[j,-1]*gram[i,j]
tmp+=b
if(yi*tmp<=0):
alpha[i]=alpha[i]+lr
b=b+lr*yi
for i in range(datas_len):
w+=alpha[i]*train_array[i,0:-1]*train_array[i,-1]
return w,b,alpha,gram
def plot_points(train_datas,w,b):
plt.figure()
x1 = np.linspace(0, 8, 100)
x2 = (-b-w[0]*x1)/(w[1]+1e-10)
plt.plot(x1, x2, color='r', label='y1 data')
datas_len=len(train_datas)
for i in range(datas_len):
if(train_datas[i][-1]==1):
plt.scatter(train_datas[i][0],train_datas[i][1],s=50)
else:
plt.scatter(train_datas[i][0],train_datas[i][1],marker='x',s=50)
plt.show()
if __name__=='__main__':
train_data1 = [[1, 3, 1], [2, 2, 1], [3, 8, 1], [2, 6, 1]] # 正样本
train_data2 = [[2, 1, -1], [4, 1, -1], [6, 2, -1], [7, 3, -1]] # 负样本
train_datas = train_data1 + train_data2 # 样本集
w,b,alpha,gram=train(epoch=500,train_datas=train_datas,lr=0.01)
plot_points(train_datas,w,b)
对偶形式
- 简而言之,感知机的对偶形式就是把对
w
,
b
w, b
w,b 的学习变成了对
α
,
b
\alpha, b
α,b 的学习,原始形式中,
w
w
w 在每一轮迭代错分时都需要更新, 而采用对偶式时,对于某一点
(
x
i
,
y
i
)
(x_{i},y_{i})
(xi,yi)发生错分时,我们只需要更新其对应的
α
i
\alpha_{i}
αi 即可,最后按照
5
5
5式即可一次计算出
w
w
w. 同时我们上述步骤
3
3
3中的
y
i
(
∑
j
=
1
N
α
j
y
j
x
j
⋅
x
i
+
b
)
≤
0
y_{i}\left(\sum_{j=1}^{N} \alpha_{j} y_{j} x_{j} \cdot x_{i}+b\right) \leq 0
yi(∑j=1Nαjyjxj⋅xi+b)≤0 可以看出,
x
j
⋅
x
i
x_{j} \cdot x_{i}
xj⋅xi 仅以内积的形式出现, 因此我们可以是先计算出
x
x
x的
g
r
a
m
gram
gram矩阵存 储起来,这样正式训练时只需要查表就可以得到
x
j
⋅
x
i
x_{j} \cdot x_{i}
xj⋅xi 的值, 这样做可以方便程序的优化, 提高运算的速度。 原始形式和对偶形式对参数b的处理是相同的。
5 5 5式为 f ( x ) = sign ( ∑ j = 1 N α j y j x j ⋅ x + b ) f(x)=\operatorname{sign}\left(\sum_{j=1}^{N} \alpha_{j} y_{j} x_{j} \cdot x+b\right) f(x)=sign(∑j=1Nαjyjxj⋅x+b) -
from __future__ import division import random import numpy as np import matplotlib.pyplot as plt def train(train_num,train_datas,lr): w=0.0 b=0 datas_len = len(train_datas) alpha = [0 for i in range(datas_len)] train_array = np.array(train_datas) gram = np.dot(train_array[:,0:-1] , train_array[:,0:-1].T) for idx in range(train_num): tmp=0 i = random.randint(0,datas_len-1) yi=train_array[i,-1] for j in range(datas_len): tmp+=alpha[j]*train_array[j,-1]*gram[i,j] tmp+=b if(yi*tmp<=0): alpha[i]=alpha[i]+lr b=b+lr*yi for i in range(datas_len): w+=alpha[i]*train_array[i,0:-1]*train_array[i,-1] return w,b,alpha,gram def plot_points(train_datas,w,b): plt.figure() x1 = np.linspace(0, 8, 100) x2 = (-b-w[0]*x1)/(w[1]+1e-10) plt.plot(x1, x2, color='r', label='y1 data') datas_len=len(train_datas) for i in range(datas_len): if(train_datas[i][-1]==1): plt.scatter(train_datas[i][0],train_datas[i][1],s=50) else: plt.scatter(train_datas[i][0],train_datas[i][1],marker='x',s=50) plt.show() if __name__=='__main__': train_data1 = [[1, 3, 1], [2, 2, 1], [3, 8, 1], [2, 6, 1]] # 正样本 train_data2 = [[2, 1, -1], [4, 1, -1], [6, 2, -1], [7, 3, -1]] # 负样本 train_datas = train_data1 + train_data2 # 样本集 w,b,alpha,gram=train(train_num=500,train_datas=train_datas,lr=0.01) plot_points(train_datas,w,b)