3.1设置问题:本书研究的问题为图像的纵向横向分类问题
图片的训练数据为
这些数据在图像上表示为
对于他们的分类我们可以用一条直线来区分他们,如图所示:
3.2 内积
对于分类问题并不是像回归一样找到这个函数的截距和斜率,而是要找出向量。分类的图像可以想象为带有大小和方向、带箭头的向量。
书上说这条直线是使“权重向量成为法线向量”的直线,意思就是两条直线互为法线,只是一条叫权重向量,另一条叫法线向量。设权重 向量为 w,那么那条直线的表达式就是这样的。 w · x = 0,那么就是这个样子:
3.3 感知机
感知机是接受多个输入后将每个值与 各自的权重相乘,最后输出总和的模型。感知机是非常简单的模型,基本不会应用在实际的问题中。 但它是神经网络和深度学习的基础模型。
3.3.1 训练数据的准备
w · x = |w|·|x| · cos θ
而cos θ在90◦ <θ< 270◦ 的时候为负,与权重向量 w 之间的夹角为 θ,在 90◦ <θ< 270◦ 范围内的所有向量都符合条件……所以是不是就在这条直线下面、与权重向量 方向相反的这个区域
与负的区域想法的区域为
3.3.2 权重向量的更新表达式
fw(x(i) ) ≠ y(i)意思是通过判别函数对宽和高的向量x进行分类的结果与实际标签的y结果不同。
fw(x(i) ) = y(i)判别函数的分类结果是准确的。
也就是说,刚才的更新表达式只有在判别函数分类失败的时候 才会更新参数值。
分类失败后的更新表达式为w := w + y(i) x),在这个状态下,我们随机画一个权重向量,并假设第一个训练数据为x(1)=(125,30)
训练数据的为:
现在权重向量 w 和训练数据的向量 x(1) 二者的方向几乎相 反,w 和 x(1) 之间的夹角 θ 的范围是 90◦ <θ< 270◦ ,内积为负。 也就是说,判别函数 fw(x(1)) 的分类结果为 −1。但是,训练数据 x(1) 的标签 y(1) 是 1,所以 fw(x(1)) = y(1) 说明分类失败。
现在他们在同一侧了, θ < 90◦,所以内积为正,判别函数 fw(x) 的分类结果为 1。而且x(1) 的标签也为 1,说明分类成功了。
import numpy as np
import matplotlib.pyplot as plt
# 读入训练数据
train = np.loadtxt('images1.csv', delimiter=',', skiprows=1)
train_x = train[:,0:2]
train_y = train[:,2]
# 权重的初始化
w = np.random.rand(2)
# 判别函数
def f(x):
if np.dot(w, x) >= 0:
return 1
else:
return -1
# 重复次数
epoch = 10
# 更新次数
count = 0
# 学习权重
for _ in range(epoch):
for x, y in zip(train_x, train_y):
if f(x) != y:
w = w + y * x
# 输出日志
count += 1
print(' 第 {} 次 : w = {}'.format(count, w))
#图像显示
x1 = np.arange(0,500)
plt.plot(train_x[train_y == 1, 0], train_x[train_y == 1, 1], 'o')
plt.plot(train_x[train_y == -1, 0], train_x[train_y == -1, 1], 'x')
plt.plot(x1, -w[0] / w[1] * x1, linestyle='dashed')
plt.show()
#验证
# 200×100 的横向图像
f([200, 100])
#1
# 100×200 的纵向图像
f([100, 200])
#-1
3.4 线性可分
3.5 逻辑回归
3.5.1 sigmoid 函数
exp(−θTx) 可以换成 ,它的函数图像为:
3.5.2 决策边界
所以我们可以把表达式 改写为这种形式
import numpy as np
import matplotlib.pyplot as plt
# 读入训练数据
train = np.loadtxt('images2.csv', delimiter=',', skiprows=1)
train_x = train[:,0:2]
train_y = train[:,2]
# 参数初始化
theta = np.random.rand(3)
# 标准化
mu = train_x.mean(axis=0)
sigma = train_x.std(axis=0)
def standardize(x):
return (x - mu) / sigma
train_z = standardize(train_x)
# 增加 x0
def to_matrix(x):
x0 = np.ones([x.shape[0], 1])
return np.hstack([x0, x])
X = to_matrix(train_z)
# sigmoid 函数
def f(x):
return 1 / (1 + np.exp(-np.dot(x, theta)))
# 分类函数
def classify(x):
return (f(x) >= 0.5).astype(np.int)
# 学习率
ETA = 1e-3
# 重复次数
epoch = 5000
# 更新次数
count = 0
# 重复学习
for _ in range(epoch):
theta = theta - ETA * np.dot(f(X) - train_y, X)
# 日志输出
count += 1
print(' 第 {} 次 : theta = {}'.format(count, theta))
# 绘图确认
x0 = np.linspace(-2, 2, 100)
plt.plot(train_z[train_y == 1, 0], train_z[train_y == 1, 1], 'o')
plt.plot(train_z[train_y == 0, 0], train_z[train_y == 0, 1], 'x')
plt.plot(x0, -(theta[0] + theta[1] * x0) / theta[2], linestyle='dashed')
plt.show()