统计学习方法学习笔记第二章(感知机)
感知机是一个二分类的线性分类模型,是神经网络和支持向量机的基础。
考虑统计学习方法三要素:
模型:f(x) = sign(w*x+b)
策略:收敛前提条件:数据集是线性可分的
学习策略:考虑每一个点到超平面的距离:(二维的点到平面距离公式),对于分类错误的数据,yi*(w*xi_b)<0,则令损失函数为-Σyi*(w*xi+b)
算法:SGD,若分类错误则计算梯度然后更新。
算法的收敛性:
收敛次数k有上界(R/γ)^2,其中R是x1到xn中二阶范式的最大值,γ是满足对任意i,yi*(wopt * xi + bopt) >= γ的一个常数(由于判别是否分类正确的条件是yi*(wopt * xi + bopt) > 0, 所以肯定可以找到这样一个γ)
对偶形式的算法:
观察更新的过程可以发现,令αi = ni * η,则w = ∑ αi * yi * xi, b = ∑ αi * yi, 其中ni是算法运行过程中数据i被误分类的次数。
实际处理的过程中,可以预处理出Gram矩阵(作用是保存任意两个特征向量的叉积)
两种不同是算法对应的支持向量机的原始形式和对偶形式。
算法测试代码:
import random
import numpy as np
import math
import torch
import matplotlib.pyplot as plt
n = 10
k = -1
bias = 1
lr = 1
def line(x):
return k * x + bias
def learn(x, y):
w = np.random.randn(2)
b = 0
epoch = 0
while True:
flag = False
count = 0
for i in range(len(x)):
if (y[i] * (np.dot(w, x[i]) + b)) <= 0:
# print('updated')
w = w + lr * y[i] * x[i]
b = b + lr * y[i]
flag = True
count += 1
if not flag:
break
epoch += 1
print('epoch count', epoch, count)
return w, b
Gram = np.zeros((n, n))
def dual_learn(x, y):
alpha = np.zeros(n)
b = 0
epoch = 0
while True:
flag = False
count = 0
for i in range(len(x)):
tot = 0
for j in range(len(x)):
tot += alpha[j] * y[j] * Gram[j][i]
tot = y[i] * (tot + b)
if tot <= 0:
print('updated')
alpha[i] += lr
b += lr * y[i]
flag = True
count += 1
if not flag:
break
epoch += 1
print('epoch count', epoch, count)
return alpha, b
if __name__ == '__main__':
x = np.random.uniform(0, 1, (n, 2))
y = np.zeros(n)
for i in range(n):
for j in range(n):
Gram[i][j] = np.dot(x[i], x[j])
print(Gram)
for i in range(len(y)):
if x[i][1] > line(x[i][0]):
y[i] = 1
else:
y[i] = -1
# plt.show()
print(x, y)
alpha, b = dual_learn(x, y)
print(alpha)
w = np.zeros(2)
for i in range(n):
w += alpha[i] * y[i] * x[i]
vector = [0, 0]
ax = plt.gca()
ax.plot(x)
plt.show()
for i in range(10):
vector[0] = float(input())
vector[1] = float(input())
# print(w)
print(vector)
print(np.dot(w, np.array(vector).astype('float64')) + b)
以y=-x+1(0 <= x <= 1, 0 <= y <= 1)为分界线,随机生成一些点进行标记,通过SGD进行更新。

浙公网安备 33010602011771号