在本章中,我们会用到两个分类算法,感知机和可调线性参数。
本章要点如下:
- 构建机器学习的直觉
- 基本的数据处理和可视化
- 运用线性分类算法
一、早期机器学习
1. 人工神经元的正式定义
我们可以把人工神经元放在一个朴素的二分类任务中,1代表正类,-1代表负类。设定一个决策函数
ϕ
(
z
)
\phi(z)
ϕ(z)对已知输入
x
x
x和响应权重向量
w
w
w进行线性组合,则
z
z
z被称为净输入:
z
=
w
1
x
1
+
…
+
w
m
x
m
z = w_1x_1 + \ldots + w_mx_m
z=w1x1+…+wmxm:
w
=
[
w
1
w
2
⋮
w
m
]
,
x
=
[
x
1
x
2
⋮
x
m
]
w = \begin{bmatrix} w_1 \\ w_2 \\ \vdots \\ w_m \end{bmatrix},x = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_m \end{bmatrix}\\
w=⎣⎢⎢⎢⎡w1w2⋮wm⎦⎥⎥⎥⎤,x=⎣⎢⎢⎢⎡x1x2⋮xm⎦⎥⎥⎥⎤
现在对于一个给定样本
x
(
i
)
x^{(i)}
x(i),如果其净输入大于给定阀值
θ
\theta
θ,我们可以预测其类别,1类或-1类。在感知机算法中,决策函数
ϕ
(
⋅
)
\phi(·)
ϕ(⋅)是一个分段函数:
ϕ
(
z
)
=
{
0
i
f
z
≥
θ
−
1
o
t
h
e
r
w
i
s
e
\phi(z) = \begin{cases} 0 & if\quad z \ge \theta \\ -1 & otherwise \end{cases}
ϕ(z)={0−1ifz≥θotherwise
为简化考虑,我们可以把阀值
θ
\theta
θ放在等式左边,令
w
0
=
−
θ
w_0 = -\theta
w0=−θ,
x
0
=
1
x_0 = 1
x0=1,得到一个更简便的
z
z
z:
z
=
w
0
x
0
+
w
1
x
1
+
…
+
w
m
x
m
=
w
T
x
z = w_0x_0 + w_1x_1 + \ldots + w_mx_m = \bm{w}^{T} \bm{x}
z=w0x0+w1x1+…+wmxm=wTx,以及:
ϕ
(
z
)
=
{
i
i
f
z
≥
0
−
1
o
t
h
e
r
w
i
s
e
\phi(z) = \begin{cases} i & if \quad z \ge 0 \\ -1& otherwise \end{cases}
ϕ(z)={i−1ifz≥0otherwise
在机器学习语言中,负的阀值,或权重
w
0
=
−
θ
w_0 = - \theta
w0=−θ,通常被称为偏置单元。
在下面的章节中,我们会用到很多线性代数的符号。
2. 感知机学习原理
原始感知理论可以被简单地概括为这几个步骤:
- 将权重初始化为0或一个很小的随机数
- 对训练集的每个样本
x
(
i
)
x^{(i)}
x(i):
a. 计算输出值 y ^ \hat{y} y^
b. 更新权重
这里的输出值就是根据我们预先定义的决策函数预测出的类标签(1或-1),同时更新每个权重
w
j
w_j
wj。这样权重向量可以这么写:
w
j
:
=
w
j
+
Δ
w
j
w_j:= w_j + \Delta w_j
wj:=wj+Δwj
这里
Δ
w
j
\Delta w_j
Δwj的值,就是根据感知机学习原理计算出来更新原值
w
j
w_j
wj的:
Δ
w
j
=
η
(
y
(
i
)
−
y
^
(
i
)
)
x
j
(
i
)
\Delta w_j = \eta (y^{(i)} - \hat{y}^{(i)})x^{(i)}_j
Δwj=η(y(i)−y^(i))xj(i)
η
\eta
η就是学习率(一个0到1之间的常数),
y
(
i
)
y^{(i)}
y(i)是第
i
i
i个样本的真实类标签,
y
^
(
i
)
\hat{y}^{(i)}
y^(i)是预测类标签。注意:在权重向量中,所有的权重值都是同步更新的,也就是说,我们不必等所有
Δ
w
j
\Delta w_j
Δwj更新后再次计算
y
^
(
i
)
\hat{y}^{(i)}
y^(i)。同理,对于二维数据集,我们也可以这么写权重更新值:
Δ
w
0
=
η
(
y
(
i
)
−
o
u
t
p
u
t
(
i
)
)
Δ
w
1
=
η
(
y
(
i
)
−
o
u
t
p
u
t
(
i
)
)
x
1
(
i
)
Δ
w
2
=
η
(
y
(
i
)
−
o
u
t
p
u
t
(
i
)
)
x
2
(
i
)
\Delta w_0 = \eta(y^{(i)} - output^{(i)}) \\ ~\\ \Delta w_1 = \eta(y^{(i)} - output^{(i)})x^{(i)}_1 \\ ~\\ \Delta w_2 = \eta(y^{(i)} - output^{(i)})x_2^{(i)}
Δw0=η(y(i)−output(i)) Δw1=η(y(i)−output(i))x1(i) Δw2=η(y(i)−output(i))x2(i)
在实际运行感知机算法之前,我们要感受一下这个规则的简单和美丽。在两个场景中,感知机正确的预测了分类,并且权重保持不变:
Δ
w
j
=
η
(
−
1
−
(
−
1
)
)
x
j
(
i
)
=
0
Δ
w
j
=
η
(
1
−
1
)
x
j
(
i
)
=
0
\Delta w_j = \eta (-1-(-1))x_j^{(i)} = 0 \\ ~\\ \Delta w_j = \eta (1-1)x_j^{(i)} = 0
Δwj=η(−1−(−1))xj(i)=0 Δwj=η(1−1)xj(i)=0
尽管有时感知机预测错误,但权重被推向了正负两个目标类:
Δ
w
j
=
η
(
1
−
−
1
)
x
j
(
i
)
=
η
(
2
)
x
j
(
i
)
Δ
w
j
=
η
(
−
1
−
1
)
x
j
(
i
)
=
η
(
−
2
)
x
j
(
i
)
\Delta w_j = \eta (1--1)x_j^{(i)} = \eta (2)x_j^{(i) }\\ ~\\ \Delta w_j = \eta (-1-1)x_j^{(i)} = \eta (-2)x_j^{(i) }
Δwj=η(1−−1)xj(i)=η(2)xj(i) Δwj=η(−1−1)xj(i)=η(−2)xj(i)
为了对这个乘数
x
j
(
i
)
x_j^{(i)}
xj(i)有更好的感觉,我们看另一个简单的例子:
y
^
(
i
)
=
−
1
,
y
(
i
)
=
+
1
,
η
=
1
\hat{y}^{(i)} = -1, \quad y^{(i)} = +1, \quad \eta = 1
y^(i)=−1,y(i)=+1,η=1
假设
x
j
(
i
)
=
0.5
x_j^{(i)} = 0.5
xj(i)=0.5,我们错误的把它分类为-1,。这种情况下,我们可以把响应权重
Δ
w
j
\Delta w_j
Δwj提高到1,这样下次再遇到这个样本的时候,净输入
x
j
(
i
)
×
w
j
x_j^{(i)} \times w_j
xj(i)×wj就更加趋正,也就更可能大于决策函数的阀值
θ
\theta
θ从而被预测为1:
Δ
w
j
=
(
1
−
−
1
)
0.5
=
(
2
)
0.5
=
1
\Delta w_j = (1--1)0.5 = (2)0.5 = 1
Δwj=(1−−1)0.5=(2)0.5=1
权重的更新对于
x
j
(
i
)
x_j^{(i)}
xj(i)来说是成比例的。比如说,我们有一个样本
x
j
(
i
)
=
2
x_j^{(i)} = 2
xj(i)=2被错误的标注了-1,那么下一次权重更新值增大使得其更可能被正确地分类:
Δ
w
j
=
(
1
−
−
1
)
2
=
(
2
)
2
=
4
\Delta w_j = (1--1)2 = (2)2 = 4
Δwj=(1−−1)2=(2)2=4
要指出:感知机只有在二类别线性可分且学习率充分小时才收敛。如果数据集线性不可分时,我们可以设定一个最大容错阀值。
下一节实操,我们来复习下感知机的主要原理吧
上面的图展示了,感知机接收到一个样本
x
x
x将其与权重结合来计算净输入。净输入传递到决策函数和阀值相比较,产生二分输出,-1或+1,也就是预测结果。在整个学习阶段,这个输出
y
y
y会用于计算预测错误率并更新权重。
二、在python中应用感知机算法
这里直接调用机器学习包sklearn。
# 导入Perceptron
from sklearn.linear_model import Perceptron
# 导入sklearn自带的鸢尾花数据集
from sklearn.datasets import load_iris
# 分割训练集和测试集
from sklearn.model_selection import train_test_split
# 引入三个评估函数
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
首先来看看数据集的格式,根据官网介绍,内置的数据集分为data和target两个部分,可以这么理解:data即解释变量,target即已经分类好的被解释变量。
iris = load_iris()
iris.data.shape
输出:(150, 4)
接下来将整个数据集分为训练集和测试集:
x = iris.data
y = iris.target
split_rate = 0.3 # 确定测试集占总数据集的比例
x_train, x_test, y_train, y_test = train_test_split(x, y,
test_size=split_rate, random_state=42)
查看分割结果:
print('x_train_shape:', x_train.shape)
print('x_test_shape:', x_test.shape)
print('y_train_shape:', y_train.shape)
print('y_test_shape:', y_test.shape)
输出:
x_train_shape: (105, 4)
x_test_shape: (45, 4)
y_train_shape: (105,)
y_test_shape: (45,)
接下来进行模型拟合及预测:
pcpr = Perceptron()
pcpr.fit(x_train, y_train)
输出:
Perceptron(alpha=0.0001, class_weight=None, early_stopping=False,
eta0=1.0, fit_intercept=True, max_iter=None, n_iter=None,
n_iter_no_change=5, n_jobs=None, penalty=None, random_state=0,
shuffle=True, tol=None, validation_fraction=0.1,
verbose=0, warm_start=False)
prediction = pcpr.predict(x_test)
接下来对预测结果进行评估:
print(classification_report(y_test, prediction))
print(confusion_matrix(y_test, prediction))
print(accuracy_score(y_test, prediction))
输出:
precision recall f1-score support
0 0.83 1.00 0.90 19
1 0.00 0.00 0.00 13
2 0.59 1.00 0.74 13
micro avg 0.71 0.71 0.71 45
macro avg 0.47 0.67 0.55 45
weighted avg 0.52 0.71 0.60 45
[[19 0 0]
[ 4 0 9]
[ 0 0 13]]
0.7111111111111111