[关闭]
@zsh-o 2018-08-26T20:39:36.000000Z 字数 6323 阅读 1055

2 - 感知器

《统计学习方法》


  1. %matplotlib inline
  2. import numpy as np
  3. from matplotlib import pyplot as plt
  1. epsilon = 1e-5

原始形式

输入空间,输出空间,映射如下

有一点需要注意的是感知机假设数据集是线性可分的,也就是会有一个分割超平面会把数据集完全正确的分隔开

输入空间中一点到超平面的距离为


由于在超平面下的分类结果为

误分类点可判定为
损失函数设定为误分类点的集合为到超平面的总距离为,

不考虑,损失函数为

最小化需要对其求梯度

进行梯度下降的时候需要注意,每次只选取一个误分类点进行梯度下降

如果原始数据集线性不可分,会陷入无限循环

  1. def perceptron(X, Y, eta):
  2. w = np.zeros(X.shape[1])
  3. b = 0
  4. M = []
  5. def get_M():
  6. M.clear()
  7. for index, (x, y) in enumerate(zip(X, Y)):
  8. if y*(np.dot(w, x) + b) <= 0:
  9. M.append(index)
  10. return M
  11. while len(get_M()) > 0:
  12. i = np.random.choice(M)
  13. x, y = X[i], Y[i]
  14. w = w + eta * y * x
  15. b = b + eta * y
  16. return w, b

例2.1

  1. ## 例2.1
  2. X = np.array([[3,3],[4,3],[1,1]])
  3. Y = np.array([[1], [1], [-1]])
  4. w, b = perceptron(X, Y, 1)
  5. w, b
(array([2., 1.]), array([-5]))
  1. postive_X = X[np.where(Y>0)[0]]
  2. plt.plot(postive_X[:,0], postive_X[:,1], 'ro')
  3. negative_X = X[np.where(Y<0)[0]]
  4. plt.plot(negative_X[:,0], negative_X[:,1], 'bo')
  5. aX = np.arange(0, 6, 0.1)
  6. aY = (-b - w[0]*aX)/(w[1]+epsilon)
  7. plt.axis([0,6, 0, 6])
  8. plt.plot(aX, aY)

output_7_1.png-6.5kB

算法收敛性

需要证明算法的迭代次数存在上界,,经过有限次迭代可以得到一个将训练数据集完全正确划分的分离超平面。这个证明是Novikoff在1962年给出的,收敛证明很重要

定理 2.1 (Novikoff) 设训练数据集是线性可分的,其中,则
- 存在满足条件的超平面将训练数据集完全正确分开;且满足,对所有


- 令,则感知器在训练数据集上的误分类次数满足不等式

证明:
- 由于训练数据集是线性可分的,所以存在超平面使训练集完全正确的分开,可取该超平面为,并满足,故对所有的训练数据集


所以存在
使

- 设表示第次迭代得到的参数,并且第k次迭代中根据判别条件得到的误分类样例为,则的更新为



现在推倒两个不等式:
- (1)

推倒:

- (2)

推倒:

结合上面几个不等式:

这个地方用了柯西-施瓦茨不等式的向量内积形式:,并且
整理得到


对偶形式

这个对偶形式的思想异常重要

对偶形式的基本思想为,将表示为实例和标记的线性组合的形式,通过求解其系数而求得

书上这个地方给出了一种直观上的对偶问题的解释,而SVM中的对偶形式是由拉格朗日乘子法求出来的,但朗格朗日乘子法的核心思想也是:所构建的超平面需要满足在训练数据集上的约束,利用朗格朗日乘子法把该约束加到损失函数里面,可以求出来原始原始参数的用训练数据集的表示形式(这里是线性组合,SVM也是线性组合),把参数带入到损失函数里面,得到对偶形式

对于每次的误分类点的迭代为


可把这个过程看成训练过程中的每次选取的误分类点均对其有影响,假设每个数据点误分类次数为,则该点的总影响为,则上式变为其对偶形式

故在迭代过程中每次选取误分类点,对应的更新方程为

表示第个实例点由于误分而进行更新的次数,实例点更新次数越多,意味着它距离分离超平面越近,也就越难正确分类。换句话说,这样的实例对学习结果影响最大

  1. def perceptron_duality(X, Y, eta):
  2. alpha = np.zeros((X.shape[0], 1)) ## 整个过程中每个样本误分类的次数n_i
  3. b = 0
  4. M = []
  5. def get_M():
  6. M.clear()
  7. w = eta * np.sum(alpha * Y * X, axis=0)
  8. for index, (x, y) in enumerate(zip(X, Y)):
  9. if y*(np.dot(w, x) + b) <= 0:
  10. M.append(index)
  11. return M
  12. while len(get_M()) > 0:
  13. i = np.random.choice(M)
  14. x, y = X[i], Y[i]
  15. alpha[i] = alpha[i] + 1
  16. b = b + eta * y
  17. w = eta * np.sum(alpha * Y * X, axis=0)
  18. return w, b, alpha
  1. ## 例2.2
  2. X = np.array([[3,3],[4,3],[1,1]])
  3. Y = np.array([[1], [1], [-1]])
  4. w, b, alpha = perceptron_duality(X, Y, 1)
  5. w, b
(array([1., 1.]), array([-3]))
  1. postive_X = X[np.where(Y>0)[0]]
  2. plt.plot(postive_X[:,0], postive_X[:,1], 'ro')
  3. negative_X = X[np.where(Y<0)[0]]
  4. plt.plot(negative_X[:,0], negative_X[:,1], 'bo')
  5. aX = np.arange(0, 6, 0.1)
  6. aY = (-b - w[0]*aX)/(w[1]+epsilon)
  7. plt.axis([0,6, 0, 6])
  8. plt.plot(aX, aY)
  9. alpha
array([[2.],
       [0.],
       [5.]])

output_12_1.png-6.2kB

  1. def perceptron_duality_gram(X, Y, eta):
  2. alpha = np.zeros((X.shape[0], 1)) ## 整个过程中每个样本误分类的次数n_i
  3. b = 0
  4. M = []
  5. Gram_Matrix = np.dot(X, X.T)
  6. def get_M():
  7. M.clear()
  8. for index, (x, y) in enumerate(zip(X, Y)):
  9. if y*(eta * np.sum(Gram_Matrix[index, :][:, np.newaxis] * Y * alpha) + b) <= 0:
  10. M.append(index)
  11. return M
  12. while len(get_M()) > 0:
  13. i = np.random.choice(M)
  14. x, y = X[i], Y[i]
  15. alpha[i] = alpha[i] + 1
  16. b = b + eta * y
  17. w = eta * np.sum(alpha * Y * X, axis=0)
  18. return w, b, alpha
  1. ## 例2.2
  2. X = np.array([[3,3],[4,3],[1,1]])
  3. Y = np.array([[1], [1], [-1]])
  4. w, b, alpha = perceptron_duality_gram(X, Y, 1)
  5. w, b
(array([1., 0.]), array([-2]))
  1. postive_X = X[np.where(Y>0)[0]]
  2. plt.plot(postive_X[:,0], postive_X[:,1], 'ro')
  3. negative_X = X[np.where(Y<0)[0]]
  4. plt.plot(negative_X[:,0], negative_X[:,1], 'bo')
  5. aX = np.arange(0, 6, 0.1)
  6. aY = (-b - w[0]*aX)/(w[1]+epsilon)
  7. plt.axis([0,6, 0, 6])
  8. plt.plot(aX, aY)
  9. alpha
array([[0.],
       [1.],
       [3.]])

output_15_1.png-3.2kB

柯西-施瓦茨不等式

维向量,,其内积满足不等式


展开

当且仅当共线时等式成立,网上一共给出了三种证法

证法1

共线需要满足,对所有的成立,让


,所有,此时不等式成立

,因为恒成立,所以成立(极值点:

证法2

证法2利用的二次方程组无解或有唯一解时判别式小于等于0,故

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注