白话机器学习的数学学习总结(二):分类问题

 3.1设置问题:本书研究的问题为图像的纵向横向分类问题

 图片的训练数据为

 这些数据在图像上表示为

 

对于他们的分类我们可以用一条直线来区分他们,如图所示:

 

3.2 内积

 对于分类问题并不是像回归一样找到这个函数的截距和斜率,而是要找出向量。分类的图像可以想象为带有大小和方向、带箭头的向量

书上说这条直线是使“权重向量成为法线向量”的直线,意思就是两条直线互为法线,只是一条叫权重向量,另一条叫法线向量。设权重 向量为 w,那么那条直线的表达式就是这样的。 w · x = 0,那么就是这个样子:

3.3 感知机

 感知机是接受多个输入后将每个值与 各自的权重相乘,最后输出总和的模型。感知机是非常简单的模型,基本不会应用在实际的问题中。 但它是神经网络和深度学习的基础模型。

3.3.1 训练数据的准备
首先是训练数据。设表示宽的轴为 x 1 、表示高的轴为 x 2 ,用 y 来 表示图像是横向还是纵向的,横向的值为 1 、纵向的值为 1

根据参数向量 x 来判断图像是横向还是纵向的函 数,即返回 1 或者 1 的函数 f w ( x ) 的定义如下。这个函数被称为 判别函数

 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) 说明分类失败。

所以更新表 达式是这样的,其实就是向量的加法。 w + y (1) x (1) = w + x (1)

 

这个 w + x (1) 就是下一个新的 w ,画一条与新的权重向量 垂直的直线,相当于把原来的线旋转了一下

现在他们在同一侧了,  θ < 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 逻辑回归
接下来要讲的算法与感知机的不同之处在于,它是把分类作为概率来考虑的。
在学习感知机时之所以设置值为 1 1 ,是因为这样会使参数更新表达式看起来更简洁, 而现在则是设置为 1 0 会更简洁。
3.5.1 sigmoid 函数

exp(θTx) 可以换成 e_{}^{-\Theta tx },它的函数图像为:

 

θ T x = 0 f θ ( x )=0 . 5 ,以及 0 < f θ ( x ) < 1 sigmoid 函数的两 个特征。 因为 sigmoid 函数的
取值范围是 0 < f θ ( x ) < 1 ,所以它可以作为概率来使用。
3.5.2 决策边界
刚才说到把表达式 f θ ( x ) 当作概率来使用,那么接下来我们就把未知数据 x 是横向图像的概率作为 f θ ( x ) 。其表达式是这样的。
在给出 x 数据时 y = 1 ,即图像为横向 的概率。假如 f θ ( x ) 的计算结果是 0.7,图像为横向的概率是 70% 吧。一般来说这样就可以把 x 分类为横向了。在 θ T x >  0 时, f θ ( x )>0 . 5,0.5是这个函数的阈值,因此可以划分为

 所以我们可以把表达式 改写为这种形式

 

我们像学习感知机时那样,设横轴为图像的宽( x 1 )、纵轴为 图像的高(x 2),并且画出图来。
然后像学习回归时那样,先随便确定 θ 再具体地去考虑。 比如当 θ 是这样的向量时,我们来画一下 θ T x 0 的图像。

我们将 θ T x = 0 这条直线作为边界线,就可以把这条线两侧的数据分类为横向和纵向了。这样用于数据分类的直线称为决策边界
实际应用时这个决策边界似乎不能正确地分类图像(图 3-24 ),这 是因为我们决定参数时太随意了,为了求得正确的参数 θ 而定义 目标函数 ,进行微分,然后求参数 的更新表达式

 

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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值