记录自己学习《统计学习方法》的过程,包括自己对基本概念的理解和代码实现
我的理解
和其他方法一样,从三个方面去认识感知机(1)模型(2)策略(3)算法
模型:首先假设输入数据是线性可分的,感知机的最终目的是求解一个超平面,使得输入可以分布在超平面的两边,从而达到分类的目的,因此感知机是一个线性的二分类模型,用数学表达式可以表示为:
f
(
x
)
=
s
i
g
n
(
w
⋅
x
+
b
)
f(x)=sign(w\cdot x+b)
f(x)=sign(w⋅x+b)
这里的
w
和
x
w和x
w和x都是
n
n
n维列向量,
n
n
n是输入特征维度,
x
x
x是输入特征向量,
w
w
w是权重,
b
b
b为偏置,
s
i
g
n
sign
sign为符号函数
s
i
g
n
(
x
)
=
{
+
1
≥
0
−
1
e
l
s
e
sign(x)= \begin{cases} +1&&{\geq0}\\ -1&&{else} \end{cases}
sign(x)={+1−1≥0else
策略:感知机的优化策略是经验风险函数最小化,什么是经验风险函数呢?定义所有误分类点到超平面的距离之后为经验风险函数,最理想的情况是没有误分类点,这时经验风险函数达到最小。经验风险函数即损失函数,数学表达式定义如下:
L
(
w
,
b
)
=
−
∑
x
i
∈
M
y
i
(
w
⋅
x
i
+
b
)
L(w,b)=-\sum_{x_i\in M}y_i(w\cdot x_i + b)
L(w,b)=−xi∈M∑yi(w⋅xi+b)
M
M
M是误分类集合,此时
y
i
y_i
yi和
(
w
⋅
x
i
+
b
)
(w\cdot x_i + b)
(w⋅xi+b)符号相反,前面乘上一个符号表示距离,这里用的是函数间隔,区别于SVM中用到的几何间隔
算法:有了优化函数,接下来就是如何求解最优参数,使得经验风险函数达到最下,这里采用随机梯度下降的方法,每次随机选取一个误分类点,利用该点得到的梯度对参数进行更新,更新方式为:
θ
:
=
θ
−
η
∇
θ
l
(
θ
)
\theta:=\theta-\eta\nabla_\theta l(\theta)
θ:=θ−η∇θl(θ),
η
\eta
η为学习率,对上述损失函数求导可得:
∂
L
(
w
,
b
)
∂
w
=
−
∑
x
i
∈
M
y
i
x
i
∂
L
(
w
,
b
)
∂
b
=
−
∑
x
i
∈
M
y
i
\frac{\partial L(w,b)}{\partial w}=-\sum_{x_i\in M}y_ix_i\\ \frac{\partial L(w,b)}{\partial b}=-\sum_{x_i \in M}y_i
∂w∂L(w,b)=−xi∈M∑yixi∂b∂L(w,b)=−xi∈M∑yi
因为每次只随机选取一个误分类点对梯度进行更新,带入可得到
w
和
b
w和b
w和b的梯度更新公式:
w
:
=
w
+
η
y
i
x
i
b
:
=
b
+
y
i
w:=w+\eta y_ix_i\\ b:=b+y_i
w:=w+ηyixib:=b+yi
不断选取误分类点对梯度更新,直到所有点都正确分类
代码实现
主要放一下如何训练模型即梯度更新的代码,完整的代码,后续有时间我会把机器学习一系列的代码整理一下放在GitHub上,敬请期待
def train(self):
start = time.time()
sampleNum, featureNum = self.data.shape
data = np.concatenate((self.data, np.ones((sampleNum, 1))), axis=-1)
label = self.label
label[label>=5] = 1
label[label<5] = -1
#because cannot promise sample totally linear separable,set maxiter to stop training
for i in range(self.maxiter):
#every step choose one sample to update weight
for j in range(sampleNum):
if label[j] * sum((data[j] * self.weight)) <= 0:
self.weight += self.lr * label[j] * data[j] #update weight
print('training data spend {}s'.format(time.time() - start))
如有错误欢迎指正~