课程4. 线性模型
线性 ML 模型
线性分类和回归模型在经典机器学习中发挥着重要作用。我们将看到,线性模型易于使用和学习,具有部分可解释性,并且具有许多有趣的修改。将来,我们将会了解到神经网络在某种程度上是线性模型的扩展,也是线性模型的显著复杂化。
线性分类和回归模型彼此有很大不同,因此我们将分别考虑它们。讲座的第一部分将专门讨论线性分类模型,第二部分将专门讨论线性回归模型。
线性分类模型
我们需要以下概念:
向量及其操作。
两个向量的标量积。
平面、超平面上的直线方程。
数理统计要素:数学期望、离差、标准差。
广义线性分类器
广义线性分类器的想法是,我们将采取一些线性曲面,或者也称为超平面,作为这样的边界。
让我提醒你,线性曲面是可以用线性方程形式定义的曲面。在最简单的情况下,它只是一条直线:
y
=
k
x
+
b
y = kx + b
y=kx+b 或者,数学家会写出相同的等式:
A
x
+
B
y
+
C
=
0
Ax + By + C = 0
Ax+By+C=0
为什么我说这个案例最简单呢?关键在于我们这里只有 2 个变量,也就是说,我们在平面上工作。但是,同样的方程可以写出更多数量的变量:3、4,一般来说,我们可以写出任意数量的变量。一般来说它看起来像这样:
w
1
x
1
+
w
2
x
2
+
w
3
x
3
+
.
.
.
+
w
N
x
N
+
w
0
=
0
w_1{x_1} + w_2{x_2} + w_3{x_3} + ... + w_N{x_N} + {w_0} = 0
w1x1+w2x2+w3x3+...+wNxN+w0=0
满足该方程的点 x x x 的集合可以在 N N N 维平面上绘制,它将为我们提供一些表面。我们可以通过选择系数 w 0 , w 1 . . . w N {w_0}, {w_1} ... {w_N} w0,w1...wN 来判断这将是什么样的表面。
在二维情况下,这个表面将是某种线,在三维情况下 - 一个平面,更高的维度是人们很难想象的。这就是为什么我们要以二维的情况为例。
在二维情况下,逻辑非常简单:
一组点与另一组点可以通过一条直线分开。但是直线有多种类型,有些直线比其他直线更能完成这项任务。我们的目标是找到最佳路线。
最好 是什么意思?
那么,这一任务该如何正式表述呢?
做好准备,有数学课了!
I. 我想你们中的许多人在上学或一年级的时候就记得标量积是什么。数学家、程序员和物理学家对这个物体了解很多有趣的事情:
让我提醒你一下:如果你和我有两个向量 x ⃗ = ( x 1 , . . . , x N ) ∈ R N \vec{x} = (x_1, ... , x_N) \in R^N x=(x1,...,xN)∈RN y ⃗ = ( y 1 , . . . , y N ) ∈ R N \vec{y} = (y_1, ... , y_N) \in R^N y=(y1,...,yN)∈RN 那么它们的(欧几里得)标量积称为 ( x ⃗ , y ⃗ ) = x 1 y 1 + x 2 y 2 + . . . + x N y N = ∑ x i y i (\vec{x},\vec{y}) = x_{1}y_{1} + x_{2}y_{2} + ... + x_{N}y_{N} = ∑x_{i}y_{i} (x,y)=x1y1+x2y2+...+xNyN=∑xiyi。
那么平面上直线的方程可以写成 w 1 x 1 + w 2 x 2 + w 0 = 0 w_1{x_1} + w_2{x_2} + w_0 = 0 w1x1+w2x2+w0=0(若平面直线公式 y = k x + b y = kx + b y=kx+b 中, x x x 替换为 x 1 x_1 x1, y y y 替换为 x 2 x_2 x2)。
或者,等价地, ( w ⃗ , x ⃗ ) + w 0 = 0 (\vec{w},\vec{x}) + {w_0} = 0 (w,x)+w0=0
向量
w
⃗
\vec{w}
w 被称为我们模型的参数的向量,有时也称为权重向量。
正是这一点定义了我们用来将一个类与另一个类分隔开的特定线。也就是说,选择一条特定的线意味着选择一个特定的参数向量
w
⃗
\vec{w}
w和值
w
0
w_0
w0。我们的任务正是找到这些
w
⃗
\vec{w}
w 和
w
0
w_0
w0
Ⅱ. 让我们回顾一下与直线方程有关的一个有趣细节:让直线由方程 f w ( x ) = ( w ⃗ , x ) + w 0 = 0 f_w(x) = (\vec{w},x) + {w_0} = 0 fw(x)=(w,x)+w0=0 定义。那么函数 f w f_w fw的符号将会改变如下:
-
如果 x ′ x' x′ 位于一条直线上,则 f w f_w fw( x ′ x' x′) = 0
-
如果 x ′ ′ x'' x′′ 位于线的一侧(条件是 - 在右侧),则 f w f_w fw( x ′ ′ x'' x′′) > 0
-
如果 x ′ ′ ′ x''' x′′′ 位于线的另一侧(有条件地 - 在左边),则 f w f_w fw( x ′ ′ ′ x''' x′′′) < 0
也就是说,我们不一定非要用眼睛去看构造的线;我们可以完全忽略我们的模型是一条线的事实。只是现在我们有一个非常具体的分类算法:
如果点 x 位于线的左侧,则
f
w
f_w
fw(
x
′
′
x''
x′′) < 0 - 我们将其分配给类 0。
如果点 x 位于线的右侧,则
f
w
f_w
fw(
x
′
′
x''
x′′) > 0 - 我们将其分配到类 1。
我们面临的最后一个问题是找到最佳参数集来对给定的数据集进行分类。
思考:
现在我们正在讨论一个问题的模型示例,其中存在这样一个超平面,可以将我们的样本分成 2 个类。事实上,没有人向我们保证存在这样的超平面。存在这种超平面的样本称为线性可分。
如果样本不是线性可分的,线性分类器将不会产生完美的结果,但它可能会产生足够好的结果。
优化问题
寻找这个参数向量时应考虑哪些因素?
在回答这个问题之前,让我们先做一些更有趣的观察:
-
想出一个可以显示我们模型的错误的功能并不难:
M ( f w , x , y ) = [ f w ( x ) = y ] M(f_w, x, y) = [f_w(x) = y] M(fw,x,y)=[fw(x)=y]
这样的函数称为指示符,当方括号中的条件不满足时,它返回 0,当满足时,它返回 1。 -
但评估我们的模型有多么错误已经变得更加困难。毕竟,当线路距离分析点很远而将其发送到错误的类别时的情况与线路距离该点很近的情况有很大不同。如果预测正确,我们会倾向于使用那些做出自信预测的模型,如果预测不正确,我们会倾向于使用那些做出不自信预测的模型。
想象一下你是一名老师,你向学生问了一个难题。其中一个学生立刻答错了,并且一脸的自信;第二个学生也答错了,但是努力思考,对自己的错误答案表示怀疑。您会优先考虑第二个,尽管两个答案都给出了错误的答案。
也就是说,仅仅以指标的形式进行错误评估是不够的。我们想了解我们的模型在决策上有多错误。
-
为此我们将使用以下想法:
从几何角度来看,模型的置信度可以解释为从一个点到我们用于分类的线的距离。如果该点距离直线较远,则模型的置信度较高,如果距离直线较近,则模型不确定。我们如何估计这个距离?
事实证明,借助相同的函数 f w ( x ) f_w(x) fw(x)!它的符号表示该点相对于线的位置,而它的模表示该点距离线的距离。- 让我们使用的类标签以 +1 和 -1 的形式指定。然后,当且仅当分类正确时,表达式 M i ( w ⃗ , w 0 ) = f w ( x i ) ∗ y i M_i(\vec{w}, w_0) = f_w(x_i)*y_i Mi(w,w0)=fw(xi)∗yi 才会为正,并且其模量将向我们展示模型的置信度!
让我们仔细看看:
- 让 y i y_i yi = +1。然后,如果 f w ( x i ) > 0 f_w(x_i) > 0 fw(xi)>0,则模型做出正确预测,如果 - f w ( x i ) < 0 f_w(x_i) < 0 fw(xi)<0,则模型做出错误预测。然后,将 y i y_i yi 乘以 f w ( x i ) f_w(x_i) fw(xi),只有当 f w ( x i ) > 0 f_w(x_i) > 0 fw(xi)>0 时,我们才会得到一个正数,即分类正确。正如我们在上一段中发现的那样,结果值将与模型对其正确分类的信心成正比。
- 反之亦然:让 y i y_i yi = -1。然后,如果 f w ( x i ) < 0 f_w(x_i) < 0 fw(xi)<0,则模型做出正确预测,如果 - f w ( x i ) > 0 f_w(x_i) > 0 fw(xi)>0,则模型做出错误预测。如果分类正确,则乘以 y i = − 1 y_i = -1 yi=−1 将得到正结果;如果分类错误,则乘以 y i = − 1 y_i = -1 yi=−1 将得到负结果。该值本身再次显示了模型对其答案的信心。
所以我们希望
M
i
(
w
,
w
0
)
M_i(w, w_0)
Mi(w,w0) 尽可能大!
此功能称为缩进。我们的任务是最大化整个数据集的平均边距!
正是基于这种考虑,我们必须选择模型的参数。因此,我们将二分类问题简化为优化问题,即寻找某个函数的最小值或最大值。在本讲座的最后,我们将讨论如何在机器学习中解决此类问题。
我们将考虑这种方法的两种特殊类型。
SVM(支持向量机)
我们可以从超平面中获取一些额外的属性。假设我们希望分类尽可能的可信。这意味着每个类的对象与绘制的超平面之间的最小距离应该尽可能大,因为我们已经发现,这个距离是“置信度”的正式等价物。让我们想象一个由两个与分割超平面平行的超平面所包围的带状区域,它满足两个要求:
-
没有一个物体落入这个带内(我们首先假设样本是线性可分离的,那么这是可能的)。
-
该条带的边界尽可能靠近两个类的物体(也就是说,如果我们稍微增加该条带的宽度,那么某个物体肯定会落入里面)。
-
构建的分割超平面正好位于该条带的中间。
下图说明了此模型。
在我们的例子中,最大分类置信度的要求意味着我们要构建一条线,使得将一个类与另一个类分开的条带的宽度尽可能大。
这是一个完全自然的要求,因为我们希望上一段中考虑的最小偏移量,即分离超平面到样本最近物体的距离,尽可能大——在这种情况下,分类将最有信心。
这个要求可以写成优化问题的数学公式。以方程和不等式系统形式表述的公式相当繁琐;它的研究超出了我们课程的范围。
让我们继续考虑解决这个问题。
通过求解二次规划问题,我们得到一组系数
λ
i
λ_i
λi和一个决策规则:
a
(
x
)
=
s
i
g
n
[
∑
λ
i
y
i
(
x
i
,
x
)
−
∑
λ
i
y
i
(
x
i
,
x
j
)
−
y
i
]
a(x) = sign\big[∑\lambda_iy_i(x_i,x) - ∑λ_iy_i(x_i,x_j) - y_i\big]
a(x)=sign[∑λiyi(xi,x)−∑λiyi(xi,xj)−yi]
(其中
j
j
j 是
λ
j
λ_j
λj>0 且
M
j
M_j
Mj=1 的对象的索引)。
在这种情况下,
x
i
{x_i}
xi 是我们样本中的第
i
i
i 个对象,
y
i
{y_i}
yi 是该对象的标签,
λ
i
λ_i
λi 是通过分析解决优化问题获得的一组系数。函数
y
=
s
i
g
n
(
x
)
y=sign(x)
y=sign(x) - 符号函数(符号)。
正是这个分类器,在给定一组正确选择的数字 λ i λ_i λi的情况下,为我们提供了最大化带宽所需的决策规则。
为了最大化带宽,我们实际上不需要知道距离该带宽很远的物体的任何信息。总之,我们只需要了解位于这个最佳带边界上的物体的一些情况。形式上,这意味着许多系数 λ j λ_j λj 将等于零,并且只有其中与位于条带边界上的物体相关的一些系数将不为零。这样的对象被称为支持向量。
难的?
没关系,让我们用一个例子来看看这个算法是如何工作的。
"""
考虑一个包含“无神论”和“太空”类别的一组新闻文章的数据集
"""
# 导入必要的库
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import KFold
from sklearn.svm import SVC
import numpy as np
# 加载数据集
newsgroups_data = fetch_20newsgroups(
subset='all',
categories=['alt.atheism', 'sci.space']
)
print(newsgroups_data.data[0])
输出:
任务是将文章归入其中一个类别。出现了一个问题——我们如何将文本表示为向量?毕竟,它是我们必须传递给算法的由一定数量的实数组成的向量。让我们考虑一下文本矢量化的选项之一。
ONE HOT 和 TF-IDF
TF-IDF 是众所周知的文本向量化方法之一,基于词向量化方法(以及任何分类特征),称为独热编码。
我们的想法是,我们掌握的每个单词都可以表示为以下形式的向量
[ 0...010...0 ] [0...0 1 0...0] [0...010...0]
其中 1 1 1代表词典中该单词的序数对应的唯一位置。
也就是说,在最简单的情况下,每个单词都与上面指示的类型的向量相关联。这种方法称为“独热编码”。
让我们以 sklearn 实现为例来考虑独热编码。该方法在 sklearn.preprocessing.OneHotEncoder
类中实现。
from sklearn.preprocessing import OneHotEncoder
import numpy as np
# 为 OneHotEncoder 创建字典
vocabulary = np.array(['I', 'love', 'cats'])
# 初始化和.fit OneHotEncoder
one_hot_encoder = OneHotEncoder(handle_unknown='ignore')
one_hot_encoder.fit(vocabulary.reshape(-1, 1))
输出:
通过简单地将这些文本所含单词的向量相加,就可以得到整个文本的向量。这种文本向量化的方法称为“词袋”(Bag Of Words)。
TF-IDF 是 Bag Of Words 思想的一个轻微修改,它认为词向量不应该随机地加在一起,而应该具有一些重要性系数。一个词对于描述一段文本的重要性是根据两点考虑来确定的:
- 一个词在我们所知的所有文本中出现的频率越高,它的个体性就越差,对于表征我们特定的文本的重要性就越低,它应具有的权重也就越小。
- 一个词在我们的文本中出现的频率越高,它对文本的特征就越大,它的权重就应该越大。
基于这些思想,形成文本中每个词的权重,然后将这些权重加在一起得到词向量。
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.svm import SVC
# 将新闻组数据转换为 TF-IDF 表示
tfidf_vectorizer = TfidfVectorizer()
X_tfidf = tfidf_vectorizer.fit_transform(newsgroups_data.data)
y_target = newsgroups_data.target
# 使用线性核初始化 SVM 分类器(下一讲将介绍核)
svm_classifier = SVC(C=1.0, random_state=241, kernel='linear')
# 分类器训练
svm_classifier.fit(X_tfidf, y_target)
输出:
请注意,在初始化支持向量分类器(SVC)时,我们将参数值C = 1.0
传递给构造函数参数。
C是SVM的重要超参数之一,称为正则化参数。我们在理论上仅考虑了线性可分的[样本]的情况,但并非所有样本都是如此。这并不意味着不可能建立 SVM,我们只是必须接受我们的算法仍然会犯一些错误。这里参数C就是算法对于不可避免的错误的“惩罚”程度。
我们还使用“kernel=‘linear’”参数的值。我们将在下一讲中进一步讨论这个论点和核心。
系数 C 的值过大会导致算法过度适应特定样本、其中存在的噪声和异常值,而系数 C 的值过低会导致算法无法学习数据中所需的依赖关系。
# 从 TF-IDF 向量器获取特征(单词)列表
feature_names = tfidf_vectorizer.get_feature_names_out()
# 按模块确定最重要的分类器系数(前 10 名)
# coef_字段中包含的模型系数
coefficients = np.asarray(svm_classifier.coef_.todense()).reshape(-1)
# 系数模块
abs_coefficients = np.abs(coefficients)
# 十大赔率指数
top_indices = np.argsort(abs_coefficients)[-10:]
print(top_indices)
输出:[22936 15606 5776 21850 23673 17802 5093 5088 12871 24019]
# 我们对于元素索引了解不多。让我们看看哪些词与这些索引直接对应。
np.array(feature_names)[top_indices]
输出:
array([‘sci’, ‘keith’, ‘bible’, ‘religion’, ‘sky’, ‘moon’, ‘atheists’,
‘atheism’, ‘god’, ‘space’], dtype=object)
支持向量机(SVM)的优缺点:
优点:
- 识别多个支持向量
- 具有唯一的解析解
- 构建效率高
缺点:
- 对异常值敏感
- 需要选择超参数 C
逻辑回归
我们还可能需要另一个有趣的属性:让我们的算法不仅返回类号,还返回一个对象属于特定类的概率。然后我们得到一个称为逻辑回归的算法。
我们的想法是,我们的分类器现在不应该产生严格的 1/0 答案,而应该只产生属于类 1 的对象 概率,同时仍然是一个线性分类器。
这种分类方法称为软分类,即算法返回对象属于某个类别的程度的分类。另一种更为熟悉的分类方法是严格分类,其中算法明确地向我们返回其中一个类。
为此,我们将使用一个非常著名的函数,通常称为 Sigmoid:
σ ( x ) = 1 1 + e − x σ(x) = \frac{1}{1 + e^{-x}} σ(x)=1+e−x1
Sigmoid函数有许多有用的特性:
- 很容易看出,Sigmoid函数的值在 0 到 1 的范围内
- Sigmoid函数图的 Y 轴在 0.5 处相交
- 函数在无穷远处趋向于 1,在负无穷远处趋向于 0
让算法如下:
我们并不像往常一样计算函数 ( w , x ) + w 0 (w,x) + w_0 (w,x)+w0(通过其符号来判断它是属于类 0 还是类 1),而是对得到的值应用Sigmoid函数。
那是
a
(
x
)
=
σ
(
(
w
,
x
)
+
w
0
)
a(x) = σ((w,x) + w_0)
a(x)=σ((w,x)+w0)
请注意以下几点:
- 当我们的分类器决定将某个对象归类为第 1 类时, ( w , x ) + w 0 > 0 (w,x) + w_0 > 0 (w,x)+w0>0,即 σ ( ( w , x ) + w 0 ) > 0.5 σ((w,x) + w_0) > 0.5 σ((w,x)+w0)>0.5,而当该对象被归类为第 0 类时, σ ( ( w , x ) + w 0 ) < 0.5 σ((w,x) + w_0) < 0.5 σ((w,x)+w0)<0.5。也就是说,0.5现在是我们决策的门槛。
- 分类器现在给出从 0 到 1 的任意数字
- 缩进越大,即模型越有信心, a ( x ) a(x) a(x)的值就越大。
所有这些都让我们有理由将输出
a
(
x
)
a(x)
a(x) 精确地视为对象属于第 1 类的概率!
当这个概率大于 0.5 时,我们将对象归类为 1 类,但同样的情况对应于常规线性分类器模型给出 1 类的值的情况。0 也是如此。在这种情况下,概率的所有属性都得到满足。
只需添加一个Sigmoid函数即可将我们的线性分类器模型转换为返回概率的模型。这个模型称为逻辑回归
模型训练
对于所有这些模型,我们都需要选择参数 w ⃗ \vec{w} w(和 w 0 {w_0} w0)的最佳向量。在 SVM 的情况下,我们提到可以使用某些分析程序找到该向量,但我们没有深入讨论其细节。对于逻辑回归来说,根本没有确定误差函数精确最小值的程序。
注意:
误差函数(损失函数)是一个取决于模型参数的函数,显示这个模型的错误程度。
损失函数不太取决于模型本身,而是取决于我们正在解决的问题。
在上一讲中,我们在度量方法的背景下研究了回归问题,并讨论了可以基于最小化模型预测误差的均方条件来解决该问题。这是损失函数的经典例子。
在二分类问题中,通常使用二元交叉熵(BCE)作为损失函数。该函数取决于实际标签 y y y 和算法的预测 a ( x ) = p a(x) = p a(x)=p,如下所示:
H ( p , y ) = − ( y ⋅ l n ( p ) + ( 1 − y ) ⋅ l n ( 1 − p ) ) H(p, y) = - (y \cdot ln(p) +(1 - y) \cdot ln(1-p)) H(p,y)=−(y⋅ln(p)+(1−y)⋅ln(1−p))
此函数是根据信息理论的考虑而选择的。
很明显,训练模型的任务简化为选择提供预期损失函数最小值的参数 w ⃗ \vec{w} w,数学符号为 w ⃗ = a r g m i n ( L o s s e x p e c t e d ( x ⃗ , w ⃗ ) ) \vec{w} = argmin(Loss_{expected}(\vec{x}, \vec{w})) w=argmin(Lossexpected(x,w))。这意味着我们需要一些程序来让我们找到这个最小值,即使没有分析方法可以找到这个最小值。这种类型中最流行的算法之一是梯度下降。
梯度下降
寻找函数的最小值可以比作穿越山脉。
想象一下,你是一位在山上行走并试图下山的旅行者。实际上,您会根据对周围区域的概览来选择路径。但在寻找函数最小值的情况下,我们只能计算函数在特定点的特征,因此正确的联想就像你在爬山前蒙住眼睛一样。您知道自己所处的海拔高度,并能感受到所在位置山体表面的坡度。
在这种情况下你会怎么做?每一步你都会朝着地面坡度最陡的方向前进。
这个想法可以扩展到寻找最小值的数学模型。从数学分析中可知,若有一个函数 F = F ( x 1 . . . x n ) F = F(x_1 ... x_n) F=F(x1...xn),则该函数的偏导数向量(称为梯度), g r a d ( F ) ⃗ = ∇ F ⃗ = ( ∂ F ( x 1 ) ∂ x 1 . . . ∂ F ( x n ) ∂ x n ) \vec{grad(F)} = \vec{∇F} = (\frac{\partial F(x_1)}{\partial x_1} ... \frac{\partial F(x_n)}{\partial x_n}) grad(F)=∇F=(∂x1∂F(x1)...∂xn∂F(xn))
针对功能的最快增长。因此,反梯度向量指向函数下降最快的方向。如果我们想一步一步地接近函数的最小值,我们必须每次朝着反梯度的方向迈出一小步。从数学上来说,这个想法可以写成以下公式: x n + 1 ⃗ = x n ⃗ − λ ∇ F ( x ) ⃗ \vec{x_{n+1}} = \vec{x_n} - λ\vec{∇F(x)} xn+1=xn−λ∇F(x) 其中 λ λ λ 表示我们的步长。
通过运用这个想法来找到模型
w
⃗
\vec{w}
w 参数的损失函数的最小值,我们将找到模型参数的最优(或几乎最优)向量,我们将使用它进行分类。让我们记住这个想法!
逻辑回归的优缺点:
优点:
- 最终可得到概率值
- 有多种有趣的调整方式
缺点:
- 只能通过迭代方法进行训练
线性回归模型
线性回归的单变量情况
想象一下你是一名实验者。例如,您是一位物理学家或机械师,刚刚发明了一种新材料。您对自己的发现感到非常兴奋,并期待获得许多奖项以及全世界对您的成就的认可。但在你满足于现状之前,你必须向世人展示你的工作成果,因此要详细描述你所发明的材料的特性。
今天你的任务是测量这种材料的弹性系数。你可能还记得学校里学过的胡克定律,该定律将单轴实验中施加的力与延伸联系起来:
F
=
k
Δ
x
F = kΔx
F=kΔx
k
k
k 就是您要寻找的系数。
看上去一切都非常简单。您需要做的就是取一组已知质量的砝码和一把尺子,固定样品,开始悬挂砝码,然后测量由此产生的伸长率 Δ x Δx Δx。然后,有了一组表示对 ( F i , Δ x i ) ({F_i}, {Δx_i}) (Fi,Δxi) 的测量值,你就可以轻松找到系数 k = F i Δ x i k = \frac{F_i}{Δx_i} k=ΔxiFi。而且,根据理论,你可以取任意 i i i(即任意一对维度),而关系不应由此改变。
这意味着理论上
F
F
F 线性依赖于
Δ
x
Δx
Δx,也就是说,如果你绘制这种依赖关系的图形,该图形将只是一条直线。
但事实上,一切结果都会有些不同。你进行实验的建筑物肯定会位于主要高速公路或地铁线路附近,也许附近有机场,或者外面只是有雷雨天气。外界影响会破坏它,所有这些刺激物的振动都会影响实验的纯度,你会得到与预期略有不同的结果。点对 ( F i , Δ x i ) ({F_i}, {Δx_i}) (Fi,Δxi) 不会完美地位于线上,而是会散布在线周围。
您怎样才能真正知道材料的弹性系数是多少,哪怕是近似值?毕竟,不同的实验会给出完全不同的结果。
答案是我们必须破译隐藏在观察序列中的线性依赖关系,并构建一条近似直线 y = k x + b y = kx + b y=kx+b(在胡克定律 b b b=0 的情况下),这将很好地模拟自然的原始规律。
也就是说,问题又归结为我们必须根据原始标记样本选择线
k
k
k 和
b
b
b 的系数。
也就是说,我们的回归算法具有形式 a ( x ) = k x + b a(x) = kx + b a(x)=kx+b
当有很多标志(>1)时该怎么办?
现在我们考虑只需要预测一个属性的情况,但预测必须基于 m − 1 m-1 m−1 个不同的特征进行。也就是说,我们工作的空间是 m m m 维的( m − 1 m-1 m−1 个特征和 1 1 1 个我们想要预测的属性)。
例如,“苹果”这个对象的属性可能是它在最近的市场的价格,而描述这个苹果的特征则是它的大小和成熟度。如果苹果的价格分别线性依赖于成熟度和大小,那么在这个空间中就会存在一个线性超平面,其中的每个点对应一个三元组(成熟度-大小-价格),并且知道大小和成熟度,我们就可以明确地预测价格。
一般来说,可能有更多的预测属性。
正如我们上次讨论的那样,线性曲面可以在多维空间中表示为满足以下方程的一组点: f w ( x ) = ∑ i = 1 m − 1 x i w i + w 0 = ( x ⃗ , w ⃗ ) + w 0 = 0 f_w(x) = \sum\limits_{i=1}^{m-1}{x_i}{w_i} + {w_0} = (\vec{x}, \vec{w}) + {w_0} = 0 fw(x)=i=1∑m−1xiwi+w0=(x,w)+w0=0
在这种情况下,线性回归算法被推广到多维平面,如下所示。
令变量 x 1 . . . x m − 1 x_1...x_{m-1} x1...xm−1表示物体在 ( m − 1 ) (m-1) (m−1)维空间的特征描述,坐标 m m m表示预测变量。然后该方程可以重写如下: x m = − w 1 w m x 1 − w 2 w m x 2 − . . . − w m − 1 w m x m − 1 − w 0 w m x_{m} = -\frac{w_1}{w_m}{x_1} -\frac{w_2}{w_m}{x_2} - ... -\frac{w_{m-1}}{w_m}{x_{m-1}} - \frac{w_{0}}{w_m} xm=−wmw1x1−wmw2x2−...−wmwm−1xm−1−wmw0
为了方便起见,我们将执行以下重命名: α i : = − w i w m \alpha_i := -\frac{w_{i}}{w_m} αi:=−wmwi
然后所需变量 x m x_m xm 的值可以表示为 x 1 . . . x m − 1 x_1 ... x_{m-1} x1...xm−1 和参数向量 α ⃗ \vec{\alpha} α 的函数 x m ( x 1 . . . x m − 1 , α ⃗ ) = α 1 x 1 + . . . + α m − 1 x m − 1 + α 0 x_m(x_1 ... x_{m-1}, \vec{\alpha}) = \alpha_1x_1 + ... + \alpha_{m-1}x_{m-1} + \alpha_0 xm(x1...xm−1,α)=α1x1+...+αm−1xm−1+α0
然后,给定一个已知的向量
α
⃗
\vec{\alpha}
α,线性回归算法可以写成如下形式:
a
(
x
⃗
)
=
x
m
(
x
1
.
.
.
x
m
−
1
)
=
∑
i
=
1
m
−
1
α
i
x
i
+
α
0
a(\vec{x}) = {x_m(x_1 ... x_{m-1})}= \sum\limits_{i = 1}^{m-1}\alpha_ix_i + \alpha_0
a(x)=xm(x1...xm−1)=i=1∑m−1αixi+α0
这里的 a ( x ) a(x) a(x)表示我们模型的预测,它在几何上表示超平面 x m x_m xm点的第 n n n个坐标的值。
import plotly
import plotly.graph_objects as go
import numpy as np
# 生成数组 x 和 y
apple_maturity = np.outer(np.linspace(0, 1, 30), np.ones(30))
apple_size = apple_maturity.copy().T
# 计算苹果的成本
apple_cost = apple_maturity + 3 * apple_size + 1
normalized_apple_cost = apple_cost / 2
# 设置图形轴
layout = go.Layout(
scene={
"xaxis": {"title": "Apple ripeness"},
"yaxis": {"title": "Apple size"},
"zaxis": {"title": "The cost of an apple"},
}
)
# 创建表面图
figure = go.Figure(data=[go.Surface(x=apple_maturity, y=apple_size, z=normalized_apple_cost)], layout=layout)
figure.show()
输出:
矩阵符号
为了记录方便,我们进行如下操作:
让我们向向量
x
⃗
\vec{x}
x 添加一个坐标,并为其赋值
1
1
1。
在这种情况下,向量 x ⃗ \vec{x} x = ( x 1 , . . . , x m − 1 , 1 x_1, ..., x_{m-1}, 1 x1,...,xm−1,1)
我们将向量 α ⃗ \vec{\alpha} α 替换为向量 ( α 1 , . . . , α m − 1 , α 0 ) (\alpha_1, ..., \alpha_{m-1}, \alpha_0) (α1,...,αm−1,α0)
然后标量积 ( x ⃗ , α ⃗ ) = ∑ i = 1 m − 1 α i x i + α 0 ⋅ 1 (\vec{x},\vec{\alpha}) = \sum\limits_{i=1}^{m-1}\alpha_ix_i + \alpha_0 \cdot 1 (x,α)=i=1∑m−1αixi+α0⋅1,也就是说,在这种情况下我们的算法将采用以下形式 a ( x ⃗ ) = ( x ⃗ , α ⃗ ) a(\vec{x}) = (\vec{x},\vec{\alpha}) a(x)=(x,α)
从现在起我们就照这样写。
令 X = { x i j } X = \{x_{ij} \} X={xij} 为一个矩阵,其元素 x i j x_{ij} xij 表示维度为 N × M N \times M N×M 的第 i i i 个对象的第 j j j 个特征。这样的矩阵 X X X被称为特征对象矩阵。
在这种情况下, N N N 是样本中的对象数量, M M M 是描述每个对象的特征数量。
为了获得第 i i i 个对象的模型预测,需要将该矩阵的第 i i i 行乘以参数向量 α ⃗ \vec{α} α。
在这种情况下,矩阵乘积 X α ⃗ : T X\vec{\alpha}:T Xα:T 定义了模型预测向量: a ( X ) = X α ⃗ T ∈ R N a(X) = X\vec{\alpha}^T \in R^N a(X)=XαT∈RN
这里 α ⃗ T \vec{α}^T αT 是向量 α ⃗ \vec{α} α 的转置,也就是从行向量变成列向量。
参数选择
我们如何为预测模型选择最佳参数?
与往常一样,为了理解寻找最佳参数的策略,我们需要了解我们认为哪些参数是最佳的。或者,用机器学习术语来说,选择一个我们将要优化的损失函数。
让我们讨论一下一维的情况。假设对于对象 x x x,我们模型的预测为 a ( x ) a(x) a(x),而我们要找到的变量的实际值是 y y y。
在这种情况下,算法 a a a 在对象 x x x 上的误差可以表示为差值 ∣ a ( x ⃗ ) − y ⃗ ∣ |a(\vec{x}) - \vec{y}| ∣a(x)−y∣ 或 ( a ( x ⃗ ) − y ) 2 (a(\vec{x}) - y)^2 (a(x)−y)2 的模数或平方。在这种情况下,经验风险函数(即我们想要找到的最小值,该函数表明算法 a a a 在整个数据集 X X X 上的累积误差)可以写成 Q ( a , X ) = 1 N ∑ ( a ( x i ) − y i ) 2 Q(a, X) = \frac{1}{N}∑(a(x_i) - y_i)^2 Q(a,X)=N1∑(a(xi)−yi)2 或 Q ( a , X ) = 1 N ∑ ∣ a ( x i ) − y i ∣ Q(a, X) = \frac{1}{N}∑|a(x_i) - y_i| Q(a,X)=N1∑∣a(xi)−yi∣
当我们考虑使用度量分类器解决回归问题时,我们已经遇到了这样的函数。
简单来说,最小化 Q ( a , X ) Q(a,X) Q(a,X) 就是找到算法 α o p t ⃗ \vec{\alpha_{opt}} αopt 的这样一个参数向量,其中我们的预测的平均误差将最小。
这里我们正在处理二次函数。这意味着我们可以使用简单的学校方法找到它的最小值,对 Q Q Q 求 α ⃗ \vec{\alpha} α 的导数,并将导数等于 0
在一维情况下:
a ( x ) = α 1 x + α 0 a(x) = α_1x + {\alpha}_0 a(x)=α1x+α0
Q ( a , x ) = 1 N ( ( α 1 x 1 + α 0 − y 1 ) 2 + . . . + ( α 1 x N + α 0 − y N ) 2 ) Q(a,x) = \frac{1}{N}((\alpha_1x_1 + \alpha_0 - y_1)^2 + ... + (\alpha_1x_N + \alpha_0 - y_N)^2) Q(a,x)=N1((α1x1+α0−y1)2+...+(α1xN+α0−yN)2)
然后,对最后一个表达式进行微分,我们得到:
∂
Q
(
α
1
,
α
2
,
x
)
∂
α
1
=
1
N
(
2
x
1
(
α
1
x
1
+
α
0
−
y
1
)
+
.
.
.
+
2
x
N
(
α
1
x
N
+
α
0
−
y
N
)
)
(
1
)
\frac{∂Q(α_1, \alpha_2, x)}{∂α_1} = \frac{1}{N}(2x_1(\alpha_1x_1 + \alpha_0 - y_1) + ... + 2x_N(\alpha_1x_N + \alpha_0 - y_N)) (1)
∂α1∂Q(α1,α2,x)=N1(2x1(α1x1+α0−y1)+...+2xN(α1xN+α0−yN))(1)
∂ Q ( α 1 , α 2 , x ) ∂ α 0 = 1 N ( 2 ( α 1 x 1 + α 0 − y 1 ) + . . . + 2 ( α 1 x N + α 0 − y N ) ) ( 2 ) \frac{∂Q(α_1, \alpha_2,x)}{∂α_0} = \frac{1}{N}(2(\alpha_1x_1 + \alpha_0 - y_1) + ... + 2(\alpha_1x_N + \alpha_0 - y_N)) (2) ∂α0∂Q(α1,α2,x)=N1(2(α1x1+α0−y1)+...+2(α1xN+α0−yN))(2)
通过使 ( 1 ) (1) (1)和 ( 2 ) (2) (2)等于零,并求解两个变量的线性方程组,我们得到了精确的解析解。
∂ Q ∂ α 1 = 2 ( ( α 1 x 1 + α 0 ) − y 1 ) x 1 + . . . + 2 ( ( α 1 x n + α 0 ) − y N ) x N = 0 \frac{\partial Q}{\partial α_1} = 2((α_1x_1 + α_0) - y_1)x_1 + ... + 2((α_1x_n + α_0) - y_N)x_N = 0 ∂α1∂Q=2((α1x1+α0)−y1)x1+...+2((α1xn+α0)−yN)xN=0
∂ Q ∂ α 0 = 2 ( α 1 x 1 + α 0 − y 1 ) + . . . + 2 ( α 1 x N + α 0 − y N ) = 0 \frac{\partial Q}{\partial α_0} = 2(\alpha_1x_1 + \alpha_0 - y_1) + ... + 2(\alpha_1x_N + \alpha_0 - y_N) = 0 ∂α0∂Q=2(α1x1+α0−y1)+...+2(α1xN+α0−yN)=0
然后
α 1 ( x 1 2 + . . . + x N 2 ) = x 1 y 1 + . . . + x N y N − α 0 ( x 1 + . . . + x N ) α_1(x_1^2 + ... + x_N^2) = x_1y_1 + ... + x_Ny_N - α_0(x_1 + ... + x_N) α1(x12+...+xN2)=x1y1+...+xNyN−α0(x1+...+xN)
α 1 ( x 1 + . . . + x N ) = y 1 + . . . + y N − N α 0 α_1(x_1 + ... + x_N) = y_1 + ... + y_N - Nα_0 α1(x1+...+xN)=y1+...+yN−Nα0
从这里
α 0 = y 1 + . . . + y N − α 1 ( x 1 + . . . + x N ) N \alpha_0 = \frac{y_1 + ... + y_N - \alpha_1(x_1 + ... + x_N)}{N} α0=Ny1+...+yN−α1(x1+...+xN)
α 1 = x 1 y 1 + . . . + x N y N − 1 N ( y 1 + . . . + y N ) ( x 1 + . . . + x N ) x 1 2 + . . . + x N 2 − 1 N ( x 1 + . . . + x N ) 2 \alpha_1 = \frac{x_1y_1 + ... + x_Ny_N - \frac{1}{N}(y1 + ... + y_N)(x1 + ... + x_N)}{x_1^2 + ... + x_N^2 - \frac{1}{N}(x_1 + ... + x_N)^2} α1=x12+...+xN2−N1(x1+...+xN)2x1y1+...+xNyN−N1(y1+...+yN)(x1+...+xN)
最小二乘法
上面描述的方法称为普通最小二乘法(OLS)。这个名字的原因是显而易见的。
但是为什么我们更喜欢最小化正方形而不是最小化模块呢?
关键在于,对于最小化哪一个,并没有根本的区别。但是最小化均方差有几个优点:与绝对值的平方和不同,它在处处可微,并且其导数可以方便地写出。参数空间中的均方误差定义了旋转抛物球面的表面,而平均模量定义了圆锥的表面。在计算数学中,二次函数通常比模函数更受欢迎(尽管我们会看到也有例外)。
OLS可以扩展到更高维特征描述的情况。
在多维情况下,相同的表达式可以写成矩阵形式。
对于特征对象
X
X
X 矩阵,具有参数
α
⃗
\vec{\alpha}
α 向量的模型的预测可以通过简单的矩阵乘法
a
(
X
)
=
X
α
⃗
T
a(X) = X\vec{\alpha}^T
a(X)=XαT 获得。
如果我们知道正确答案的向量 y ⃗ = ( y 1 . . . y n ) T \vec{y} = (y_1 ... y_n)^T y=(y1...yn)T,则数据集的总误差可以表示如下:
Q ( α ⃗ , X , y ) = 1 N ∑ i = 1 N ( ( x ⃗ i , α ⃗ ) − y i ) 2 Q(\vec{α}, X, y) = \frac{1}{N}∑\limits_{i=1}^N((\vec{x}_i,\vec{α}) - y_i)^2 Q(α,X,y)=N1i=1∑N((xi,α)−yi)2
或者也可以通过预测与正确答案的偏差向量的 norm (长度概念的泛化)来写出相同的内容:
Q ( α ⃗ , X , y ) = 1 N ∣ ∣ X α ⃗ T − y ⃗ ∣ ∣ 2 2 Q(\vec{α}, X, y) = \frac{1}{N}||X\vec{α}^T - \vec{y}||_2^2 Q(α,X,y)=N1∣∣XαT−y∣∣22
在向量情况下:
∣
∣
a
⃗
∣
∣
2
=
a
1
2
+
.
.
.
+
a
n
2
||\vec{a}||_2 = \sqrt{a_1^2 + ... + a_n^2}
∣∣a∣∣2=a12+...+an2
我们将根据参数向量 α ⃗ \vec{α} α 最小化该函数。
在最一般的情况下,我们可以对几个属性做出预测。然后我们需要做如下的转换。
现在
y
i
y_i
yi 可以是任意维度
K
K
K 的向量。这是我们想要预测的所有属性的向量。
K
K
K 是此类属性的数量。
此类向量的数量就是我们样本中对象的数量。向量
y
i
y_i
yi 的集合将为我们提供一个维度为
N
×
K
N × K
N×K 的正确答案
Y
Y
Y 的矩阵。
相应地, x i x_i xi是一个包含对象特征描述的向量,其维度一般与 y i y_i yi的维度不一致
向量 α ⃗ \vec{α} α 将变成一个维度为 M × K M × K M×K 的参数矩阵 A A A。
在这种表示法中,误差函数实际上保持不变:
Q
(
A
,
X
,
y
)
=
1
N
1
K
∑
i
=
1
K
∑
j
=
1
N
(
(
x
⃗
j
,
A
i
T
)
−
Y
j
i
)
2
Q(A, X, y) = \frac{1}{N}\frac{1}{K}∑\limits_{i=1}^K∑\limits_{j=1}^N((\vec{x}_j, A_i^T) - Y_{ji})^2
Q(A,X,y)=N1K1i=1∑Kj=1∑N((xj,AiT)−Yji)2
多元最小二乘解
为了找到极值,需要对 Q Q Q 求导数,并使导数等于 0。由于该函数是二次函数,且向下凸,所以找到的极值必然是该函数的最小值。
线性代数规则告诉我们, ∂ Q ( α ⃗ , x ⃗ ) ∂ α ⃗ = 2 X T ( X α ⃗ T − y ⃗ ) = 0 \frac{∂Q(\vec{α}, \vec{x})}{∂\vec{α}} = 2X^T(X\vec{α}^T - \vec{y}) = 0 ∂α∂Q(α,x)=2XT(XαT−y)=0
使用一系列简单的变换可以找到此矩阵方程的解:
X
T
X
α
⃗
T
=
X
T
y
⃗
X^TX\vec{α}^T = X^T\vec{y}
XTXαT=XTy
α
⃗
o
p
t
T
=
(
X
T
X
)
−
1
X
T
y
⃗
\vec{α}^T_{opt} = (X^TX)^{-1}X^T\vec{y}
αoptT=(XTX)−1XTy
因此,我们找到了一个解析解,表示最优参数向量 α ⃗ o p t \vec{α}_{opt} αopt
这里出现了这种参数搜索算法的数值实现问题:我们看到公式包含矩阵 X T X X^TX XTX 的逆运算(转置和 两个矩阵的乘法)。该操作计算复杂,并且对矩阵 X X X提出了一定的要求,一般来说,它可能无法满足。通常,在实践中,我们不会使用这种方法来寻找函数 Q Q Q 的精确最小值,而是使用梯度下降法。
补充知识
∂ H ∂ ω i \frac{\partial H}{\partial \omega_i} ∂ωi∂H 的导数
在梯度下降算法中,我们需要计算二元交叉熵函数关于模型参数的导数,以执行梯度下降步骤。
让我们展示一下如何计算这个导数。
让我们考虑一个仅需要计算导数的情况。也就是说,我们有一个单一对象 x x x,它有一个真实标签 y y y,以及我们的算法的一个假设 p p p。然后 H ( p , y ) = − ( y ⋅ l n ( p ) + ( 1 − y ) ⋅ l n ( 1 − p ) ) H(p, y) = - (y \cdot ln(p) +(1 - y) \cdot ln(1-p)) H(p,y)=−(y⋅ln(p)+(1−y)⋅ln(1−p))
此外, p = σ ( ω 1 ⋅ x 1 + . . . + ω n ⋅ x n + ω 0 ⋅ 1 ) p = σ(ω_1 \cdot x_1 + ... + ω_{n} \cdot x_n + ω_0 ⋅ 1) p=σ(ω1⋅x1+...+ωn⋅xn+ω0⋅1)
让我们回顾一下数学分析中关于计算复函数导数的一个简单规则:
∂
H
∂
ω
i
=
∂
H
∂
p
⋅
∂
p
∂
ω
i
\frac{∂ H}{∂ ω_i} = \frac{∂ H}{∂ p} \cdot \frac{∂ p}{∂ ω_i}
∂ωi∂H=∂p∂H⋅∂ωi∂p
让我们分别计算第一项和第二项。
- ∂ H ∂ p = − y ⋅ 1 p + ( 1 − y ) ⋅ 1 1 − p \frac{∂ H}{∂ p} = -y ⋅ \frac{1}{p} + (1-y) \cdot \frac{1}{1 - p} ∂p∂H=−y⋅p1+(1−y)⋅1−p1
让我们回顾一下 S 型函数的一个主要性质(它的证明是一个有用的练习,建议自己做一下):
σ
′
=
σ
⋅
(
1
−
σ
)
σ' = σ \cdot (1 - σ)
σ′=σ⋅(1−σ)
- ∂ p ∂ ω i = p ⋅ ( 1 − p ) ⋅ x i \frac{∂ p}{∂ ω_i} = p⋅(1 - p)⋅x_i ∂ωi∂p=p⋅(1−p)⋅xi, 若 i ≠ 0 i \neq 0 i=0
- ∂ p ∂ ω 0 = p ⋅ ( 1 − p ) \frac{∂ p}{∂ ω_0} = p⋅(1 - p) ∂ω0∂p=p⋅(1−p)
让我们引入符号 x 0 ≡ 1 x_0 ≡ 1 x0≡1
然后两个等式都可以写成 ∂ p ∂ ω i = p ⋅ ( 1 − p ) ⋅ x i \frac{∂ p}{∂ ω_i} = p⋅(1 - p)⋅x_i ∂ωi∂p=p⋅(1−p)⋅xi
我们将得到的结果相乘:
∂ H ∂ ω i = p ⋅ ( 1 − p ) ⋅ x i ⋅ ( − y ⋅ 1 p + ( 1 − y ) ⋅ 1 1 − p ) = x i ( ( 1 − y ) ⋅ p − y ⋅ ( 1 − p ) ) \frac{∂ H}{∂ ω_i} = p⋅(1 - p)⋅x_i ⋅ (-y ⋅ \frac{1}{p} + (1-y) \cdot \frac{1}{1 - p}) = x_i((1 - y)⋅p - y⋅(1-p)) ∂ωi∂H=p⋅(1−p)⋅xi⋅(−y⋅p1+(1−y)⋅1−p1)=xi((1−y)⋅p−y⋅(1−p))
缩放
作为数据预处理的一部分,需要进行缩放(将特征带到单一尺度),这是线性(以及许多其他)机器学习模型的一个众所周知的特征。
我们回想一下,任何线性模型通常都是以下形式的函数:
f ( x 1 ω 1 + . . . + x n ω n + ω 0 ) f(x_1ω_1 + ... + x_nω_n + ω_0) f(x1ω1+...+xnωn+ω0)
在这种情况下,以下考虑极为重要:
如果特征 x 1 . . . x n x_1...x_n x1...xn表示不同尺度的变量(比如特征值 x 1 x_1 x1 ~ 1 1 1,而 x 2 x_2 x2 ~ 1000 1000 1000),那么对于大尺度的特征,微小的变化就会导致结果发生明显的变化,而对于小尺度的特征,即使是相当大的变化也几乎不会导致结果发生改变。
当然,你可以说,理论上可以通过仔细选择系数 ω 1 . . . ω n \omega_1 ... ω_n ω1...ωn 来实现平衡,从而平衡这种不平衡。是的,理论上可以,但实际上这种情况几乎无法实现。而且我们的样本量越小,这种情况发生的可能性就越小。该算法需要我们的帮助来解决指定的问题。
当我们谈论度量方法时,这个问题变得更加明显。假设我们正在处理一个二维空间,即其向量描述形式为 x ⃗ = ( x 1 , x 2 ) \vec{x} = (x_1, x_2) x=(x1,x2) 的对象。令 x 1 x_1 x1 ~ 1 1 1,且 x 2 x_2 x2 ~ 1000 1000 1000。让我们考虑三个对象:
x
1
⃗
=
(
1
,
1000
)
\vec{x_1} =(1, 1000)
x1=(1,1000)
x
2
⃗
=
(
0.01
,
1000
)
\vec{x_2} = (0.01, 1000)
x2=(0.01,1000)
x
3
⃗
=
(
1
,
1010
)
\vec{x_3} = (1, 1010)
x3=(1,1010)
在这种情况下,从我们考虑过的大多数指标的角度来看, x 1 ⃗ \vec{x_1} x1 和 x 2 ⃗ \vec{x_2} x2 之间的距离将小于 x 1 ⃗ \vec{x_1} x1 和 x 3 ⃗ \vec{x_3} x3 之间的距离,因为第二个坐标对距离做出了主要贡献。但是我们看到,从 x 1 ⃗ \vec{x_1} x1 到 x 2 ⃗ \vec{x_2} x2 时第一个坐标的相对变化比从 x 1 ⃗ \vec{x_1} x1 到 x 3 ⃗ \vec{x_3} x3 时第二个坐标的相对变化大得多。这个事实可能表明,第一个和第二个物体之间的差异实际上比第一个和第三个物体之间的差异要大得多,也就是说,算法误导了我们。
例如,如果第一个坐标描述的是飞机被雷击中后坠毁的概率,而第二个坐标描述的是最大飞行距离,那么显然,第一个坐标中的显著差异对我们来说比第二个坐标中的微不足道的差异更有意义。任何度量算法都无法考虑到这一点。
因此,我们得出结论:需要将所有特征整合到一个尺度上。有很多方法可以做到这一点。我们将研究最常见的方法。
在课程2 中,我们已经考虑了将样本带到单一尺度的方法之一 - StandardScaling。
回归质量指标
一个不太明显的问题是对线性(实际上是任何)回归的质量的评估。让我们来看看一些流行的质量指标。
平均绝对误差
M A E MAE MAE 指标是对模型预测值与实际值偏差的预期模量的估计。在样本 X X X 上,可以使用以下公式计算该指标
M A E = 1 N ∑ x ∈ X ∣ a ( x ) − y x ∣ MAE = \frac{1}{N}∑\limits_{x \in X}|a(x) - y_x| MAE=N1x∈X∑∣a(x)−yx∣
该度量的值是非负的,并且仅当模型对样本 X X X 的预测完美时才会达到零。因此, M A E MAE MAE 是需要最小化的指标。
均方误差
M S E MSE MSE 指标是模型预测值与实际值的预期平方偏差的估计值。与 M A E MAE MAE不同, M S E MSE MSE便于使用梯度方法进行优化。 M S E MSE MSE 的一个缺点是,如果不仔细分析, M S E MSE MSE 值可能会令人困惑,因为这里的预测误差是平方的。也就是说,例如绝对误差 2 将对应均方根误差 4。
M S E = 1 N ∑ x ∈ X ( a ( x ) − y x ) 2 MSE = \frac{1}{N}∑\limits_{x \in X}(a(x) - y_x)^2 MSE=N1x∈X∑(a(x)−yx)2
M S E MSE MSE的值也是非负的,只有当模型对样本 X X X的预测完美的情况下才会达到零,这意味着 M S E MSE MSE也需要最小化。
均方根误差
对
M
S
E
MSE
MSE 进行简单修改,旨在恢复在对
M
S
E
MSE
MSE 中的绝对误差进行平方时丢失的误差幅度:
R
M
S
E
=
1
N
∑
x
∈
X
(
a
(
x
)
−
y
x
)
2
RMSE = \sqrt{\frac{1}{N}∑\limits_{x \in X}(a(x) - y_x)^2}
RMSE=N1x∈X∑(a(x)−yx)2
代码
import numpy as np
def mae(y_true: np.ndarray, y_pred: np.ndarray) -> float:
"""
计算真实值和预测值之间的平均绝对误差。
Parameters:
- y_true: np.ndarray, 真实值。
- y_pred: np.ndarray, 预测值。
Returns:
- mean_abs_err: float, 平均绝对误差。
"""
err = np.abs(y_true - y_pred)
mean_abs_err = np.mean(err)
return mean_abs_err
def mse(y_true: np.ndarray, y_pred: np.ndarray) -> float:
"""
计算真实值和预测值之间的均方根误差。
Parameters:
- y_true: np.ndarray, 真实值。
- y_pred: np.ndarray, 预测值。
Returns:
- mean_s_err: float, 均方根误差。
"""
s_err = (y_true - y_pred) ** 2
mean_s_err = np.mean(s_err)
return mean_s_err
def rmse(y_true: np.ndarray, y_pred: np.ndarray) -> float:
"""
计算真实值和预测值之间的均方误差的平方根。
Parameters:
- y_true: np.ndarray, 真实值。
- y_pred: np.ndarray, 预测值。
Returns:
- root_mse: float, 均方误差的平方根。
"""
mean_s_err = mse(y_true, y_pred)
root_mse = np.sqrt(mean_s_err)
return root_mse
示例
手写数字的分类
最古老和最完善的机器学习问题之一是识别手写数字的问题。该问题属于多类分类问题。输入数据由手写数字的图像组成,表示为包含每个像素强度的二维数组。在经典的 MNIST 数据集中,这些图像的大小为 8 × 8 8×8 8×8。
我们可以使用“sklearn”中的“load_digits”函数加载 MNIST。
from sklearn.datasets import load_digits
mnist = load_digits()
加载的结构具有字典数据类型。这本词典包含许多字段,您可以在其中找到其所包含数据的描述。
mnist.keys()
输出:dict_keys([‘data’, ‘target’, ‘frame’, ‘feature_names’, ‘target_names’, ‘images’, ‘DESCR’])
我们可以看到,图像以数组的形式呈现。我们可以使用“matplotlib”库从给定的强度数组中获取图像
import matplotlib.pyplot as plt
plt.imshow(mnist.images[0])
以通常的表示形式处理数据要容易得多,因此我们将使用“return_X_y”参数来获取它。在“True”位置,它启动以标准化形式检索数据。
X, y = load_digits(return_X_y=True)
让我们使用 sklearn.linear_model
模块中实现的逻辑回归,使用 LogisticRegression
类
让我们对数据进行以下转换:
- 将样本分为
train
和test
- 使用
StandardScaler
转换train
和test
- 让我们训练逻辑回归
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import StandardScaler
# 将数据分为训练和测试样本
X_train_set, X_test_set, y_train_set, y_test_set = train_test_split(X, y, test_size=0.1, shuffle=True)
# 数据预处理:特征缩放
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train_set)
X_test_scaled = scaler.transform(X_test_set)
# 逻辑回归训练
logistic_regression = LogisticRegression()
logistic_regression.fit(X_train_scaled, y_train_set)
输出:
现在让我们评估分类的质量。 sklearn
中的所有分类器都有一个用于质量评估的特殊函数 .score(x_test, y_test)
。在基本情况下,使用accuracy_score
来评估质量。
score = logistic_regression.score(X_test_scaled, y_test_set)
score
输出:
0.9666666666666667