了解具有 CNN 功能的区域(R-CNN)
R-CNN 物体探测完全指南
R-CNN 的架构细节以及模型设计和论文的关键要点
由 Unsplash 上的 Pietro Jeng 拍摄
在这篇博文中,我解释了关于“用于精确对象检测和语义分割的丰富特征层次”这篇文章的架构细节。虽然这篇文章已经发表了一段时间,但是除了架构之外,还有很多东西需要从这篇文章中学习。我首先简要介绍了过量饮食网络,然后介绍了 RNN 网络。如果你对过食网一无所知,那么不用担心!!你仍然不会错过任何东西。
还有,博客的结构有点不一样。这更像是学生和老师之间的对话(尝试用费曼技巧学习😃).学生端的问题用粗体突出显示(以防你赶时间)。
学生
我精通著名的对象分类算法,比如 VGG、AlexNet、ResNet、InceptionNet、MobileNet(以及它们所有的变体)等等。我对这种方法的架构感到惊讶,并希望进一步扩展我在这一领域的知识。然而,我脑海中有一个问题,这些模型只能判断图像中是否包含物体。然而,我想研究还能判断物体在图像中的位置的模型?
老师
你希望冒险进入的深度学习部分也已经分类如下:图像定位、对象检测和图像分割。
**物体检测:**预测多类多个物体的包围盒。也可以包含许多属于同一类的对象。
**图像定位:**预测图像中单个类别的单个对象的边界框
**图像分割:**为图像中的每个对象创建逐像素的掩模。
在这三者中,我们将讨论对象检测。在深入研究 R-CNN 架构细节之前,我想让您了解一下 Union 上的交集的概念。两个框之间的相交面积除以两个框所占面积的并集,定义为并集上的交集。在下图中,上半部分显示了公式的可视化表示。
并集上的交集(IoU)——作者在 draw.io 的帮助下创作的图片
设上面图像下半部的蓝色方框是物体边界方框的预测,黄色方框是另一个预测。所以,当两个盒子完全重叠时,IoU 为 1,当它们完全不重叠时,IoU 为 0。所有其他情况都在 0 和 1 之间,精确值可以通过使用边界框坐标来确定。在训练和评估性能时,其中一个框可以被标记为基础事实,如果 IoU 低于特定阈值,则预测可以被认为是假阳性。记住这个解释,我们一会儿会需要它。
此外,网络中使用的性能测量是平均精度 (mAP)。平均精度的本质就像准确性一样,地图越多越好。在跳到 R-CNN 之前,我们先来看看 R-CNN 之前流行的一个模型。
使用卷积神经网络进行对象检测的第一篇论文之一是 OverFeat 。他们使用滑动窗口方法来检测图像中不同位置的物体。他们还使用了图像金字塔,以便在放大的图像中检测较小的对象,在较小的图像中检测较大的对象。下面的 gif 将让你对滑动窗口的使用有一个直观的了解。
用于对象检测的滑动窗口方法—作者 gif,照片由 Sonnie Hiles 在 Unsplash 上拍摄
OverFeat 的作者使用 AlexNet 作为他们的基础架构,并提供了两个网络,一个快速,另一个精确。他们用 1 x 1 卷积层取代了 CNN 的全连接层(这是一个好主意),减少了计算量,提高了训练和测试的速度。它们还有一个回归层,从 Pool5 层获取输入,并通过两个密集层传递它们,然后最终输出有 4 个单元来确定边界框。
**注意:**我过度简化了对超喂纸的解释,并且有许多关于架构的微妙细节,这些细节请参考纸
学生
我没有时间深入研究过厚的纸张,但是根据你展示的 gif,看起来是不是窗口选择的图像的许多子部分不会检测到任何对象?像这些区域将被检测器选择,通过整个 CNN 架构发送,并且仍然不产生任何对象并且增加计算成本?如果我们能以某种方式给模型一个提示,这些地方可能有一些物体,而模型只会告诉我在特定的位置是否有物体,这不是更好吗?
老师
你强调的问题确实是过度饮食的警告。R-CNN 的论文做了一些类似于你直觉认为应该做的事情。它使用选择性搜索算法来检测图像中某个对象的可能位置,并只将这些图像部分(大约 2000 个区域建议)发送到 AlexNet 网络。他们用 SVM 层替换了最后一个 Softmax 层,并在 Pascal VOC 2007 上只训练了用于分类的 SVM 层(关于训练的细节将在后面解释)。此外,Pascal VOC 数据集有 20 个类,但他们为 SVM 训练了 21 个类,其中额外的类对应于没有对象的背景类。通过这种方法,他们能够获得 44.7%的 mAP。看看建筑吧!
R-CNN 网络架构— 论文
学生
对于 Pascal VOC 上的对象检测来说,这些确实是很好的结果,因为它们比当时的当代模型好得多。然而,我有这样一个查询,**由于 ImageNet 数据集与 Pascal VOC 数据集相比来自不同的分布,作者难道不应该对模型进行微调吗?**根据我所知的文献,如果数据集分布发生变化,我们通常会对模型进行微调。此外,卷积网络接受固定大小的输入,例如,在 AlexNet 的情况下为 227 x 227,那么它们如何在选择性搜索算法提出的区域上应用约束呢?
老师
作者首先将图像扭曲到 227 x 227 大小,然后将它们传递给输入,这时他们在训练 SVM 后得到了 44.7%的地图。扭曲图像时,图像中的对象可能会被拉伸、拉长、挤压等,它们甚至可能会妨碍性能。因此,作者首先微调整个 AlexNet 网络进行分类。之后,作者用 SVM 层替换了 Softmax 层,只训练这一层。由于这种微调,地图从 44.7%增加到 54.2%。
还有一个关于用于微调和 SVM 训练的数据的细节。在 ImageNet 数据集上训练预训练网络。在微调模型时,作者使用了 Pascal VOC 2007 数据集。在微调过程中,即 softmax 层位于顶部时,包含 IoU ≥ 0.5 的图像被用作地面实况正框,其余图像被用作负类(背景,无对象)。然而,为了训练 SVM,他们仅使用真实的图像作为训练,并带有 IoU < 0.3 as negative class. The remaining grey zone proposals were ignored. The authors also replaced the SVM with 21 way Softmax and the mAP dropped from 54.2% to 50.9%.
**注意:**关于为 Softmax 和 SVM 选择阳性和阴性样本的详细信息在本文的附录 B 中提供
学生
这是我第一次遇到这样的微调方法。RCNN 的论文还有其他特点吗?
老师
是的,有。作者对他们的建筑做了详尽的烧蚀研究。大部分讨论都围绕着密集层和微调网络的必要性。让我们这样来看。
无需微调 作者从网络的 Pool5 层提取特征,然后从 fc6 层,再从 fc7 层提取特征。对于提取的每个要素,他们分别训练 SVM 图层并生成地图。看看下面的图片。
没有微调的地图— 纸
从上图的最后一列中,我们看到删除两个 FC 层并没有对性能造成太大影响。此外,来自 fc6 层的特征比来自 fc7 层的特征是更好的预测器。以下是作者在观察后所说的话。
这意味着 CNN 的 29%,即大约 1680 万个参数可以在不降低 mAP 的情况下被删除。更令人惊讶的是,移除 fc7 和 fc6 产生了相当好的结果 7,尽管 pool5 特征仅使用 6%的 CNN 参数来计算。
作者们现在已经用各种方式对网络进行了微调。首先,当他们直接使用 Pool5 的功能并将其发送到 SoftMax 以微调整个网络时。在这种情况下,他们发现 Pool5 的功能在没有微调的情况下增加了 3%。接下来,他们对 fc6 和 fc7 层也做了同样的事情,分别增加到 53%和 54.2%。
带微调的地图— 纸
您可以将调优后获得的结果图与上图中共享的未调优结果图进行比较。微调大大改善了结果。但是,第四排有一些特殊之处,我们来讨论一下!!
使用包围盒回归器
作者已经添加了一个包围盒回归器到池 5 层的输出中。这样做之后,他们发现 58.5% mAP 的性能有了相当大的提高。这是一个未经微调的模型在地图上几乎 14%的提升。这个包围盒回归用 l2 损失来训练,并且用λ= 1000 来惩罚。
***注:*关于边界框回归器的详细信息见本文附录 C。
作者还尝试用 VGG-16 代替 AlexNet,发现使用边界框回归器时 mAP 增加了 8%。
具有不同模型架构的地图— 论文
我现在建议您阅读这篇文章,以便更深入地了解这篇文章和实现细节。他们还提供了 ILSVRC2013 探测数据集的详细说明,并将他们的模型与其他模型进行了比较。
学生
这是作者做的非常详尽的分析。这篇文章可能有点旧了,但是模型架构的分析方法是值得注意的。这些通过实验验证层对精度提高的贡献的策略,可以在设计任何其他类型的模型时使用,甚至可以用于一些其他任务。
教师
是的,他们已经对他们的模型进行了详细而全面的分析,并与当代模型进行了比较。最后一点,出于定义的原因,像 R-CNN 这样的模型被称为两阶段模型。这种模型具有用于检测物体的可能位置的独立算法/模型(选择性搜索)和用于检测物体存在的独立模型(AlexNet)。并且这个模型(包括包围盒回归器)的训练是一个的三阶段过程,其中第一阶段,模型被微调,第二阶段,SVM 分类器被训练,第三阶段,包围盒回归器被训练。
***注意:*我已经讨论了 R-CNN 论文中 Pascal VOC 2007 数据集的分数和分析。该文件还显示了对其他数据集的深入分析。
参考
R.Girshick,J. Donahue,T. Darrell,J. Malik,用于精确对象检测和语义分割的丰富特征层次,计算机视觉和模式识别,2014 年
X.张,M. Mathieu,R. Fergus,Y. LeCun, OverFeat:使用卷积网络的集成识别、定位和检测,计算机视觉与模式识别,2014
使用新冠肺炎数据集了解回归-详细分析
确诊 COVID 病例的计数是否取决于检测?
每个数字都讲述一个故事(图片由 Unsplash 提供)
希望你们都平安健康!新冠肺炎已经完全改变了 2020 年的进程,使全球经济大幅萎缩。在这篇博客中,我们将深入探讨回归分析,以及我们如何使用芝加哥 COVID 数据集来推断令人难以置信的见解。微积分和线性代数的一些直觉会让你的旅程更容易。欢迎来到我的第一个博客!
概念
线性回归不仅仅是一种机器学习算法,它在统计学中发挥着巨大的作用。来自一个监督学习的家族,这里的每个输入都与一个目标标签相关联。模型的任务是基本理解模式,并找到覆盖每个(输入、目标)对的最佳拟合线。
概括地说,可以根据执行的任务和产出的性质对 ML 模型进行分类:
回归:产量是一个连续变量。
分类:输出是分类变量。
聚类:没有输出的概念。回归和分类属于监督学习,而聚类属于非监督学习。
回归是预测建模技术的一种形式,我们试图找到因变量和一个或多个自变量之间的重要关系。有各种类型的回归技术:线性,逻辑,多项式,岭,套索,Softmax。
线性回归
根据术语本身,您可以猜测模型沿直线运行,其中 y 可以通过输入变量 x 的线性组合来计算。线性回归假设函数可以表示为:
线性回归假设函数(图片作者提供)
θ此处存储输入特征 x 的系数/权重,与 x 的维度完全相同。注意,为了在我们的模型中添加对常数项的支持,我们在向量 x 前面加上了 1 。
对于单个输入和输出变量,该方法称为简单线性回归,而对于多个输入/特征,该方法称为多元线性回归。对于这两者,我们的目标是找到最佳拟合线,使我们的目标变量(y)和所有样本的预测输出之间的误差平方和(SSE)或均方误差(MSE)最小化。
SSE 和 MSE 计算(图片由作者提供)
为了继续,我们需要找到最佳拟合线的参数/系数。有多种方法可以得出直线的几何方程,例如最小绝对偏差(最小化残差绝对值的总和)和 Theil–Sen 估计量(找到一条直线,该直线的斜率是由成对样本点确定的斜率的中值),但是,统计学家通常使用普通最小二乘法(OLS) 。OLS 只不过是一种最小化生产线和实际输出之间距离的方法。如果要手工计算回归线,它用了一个略显吓人的公式,求斜率’ θ1 ‘和线截距’ θ0 '。
使用 OLS 寻找截距和斜率(图片由作者提供)
有两种方法/解决方案使用最小二乘法来实现线性回归模型:
- 封闭解—正规方程
- 优化算法(梯度下降、牛顿法等。)
正态方程
重要的是要明白,θ,在这里基本上可以打破或建立模型。我们的目标基本上是寻找有助于实现模型最低成本的θ。
著名的成本函数(图片由作者提供)
目标/成本函数 J(θ)的选择可以根据手头的问题有很大的不同。一般来说,均方误差最适合回归,交叉熵最适合分类。所以,回到正规方程,它使用一种分析方法来寻找方程的参数。我花了一些时间才明白为什么事情会这样发展。希望这个简短的证明能让你掌握概念。
如果我们取残差向量为 e =Xθ — y ,那么向量形式的成本函数/残差平方和将为:
正规方程推导(图片由作者提供)
对于刚接触线性代数的人来说,请注意我们不能简单地平方**xθ—y。**向量乘法属性声明向量/矩阵的平方不等于其每个值的平方。所以为了得到平方值,我们把向量和它的转置相乘。
现在,为了找到最小化残差平方和的 θ ,我们需要对上面的成本函数求关于 θ的导数。
法方程估计系数 θ向量(图片由作者提供)
这就是正规方程所能提供的一切。一个非常直接和优雅的方法来找到确切的 θ 参数,这将创造奇迹,适合您的数据!然而,这里有一个问题。矩阵反函数不适用于较大的数据集(较大的 X 值)或逆矩阵可能不存在的数据集(矩阵不可逆或奇异)。即使是当今最有效的逆算法也只能给出 T2 的三次方时间复杂度 T3。对于“较小”的数据集,可以首选正规方程解,如果计算“昂贵”的矩阵求逆不是问题,但对于真实世界的数据集,则首选梯度下降或 SGD 等方法。
梯度下降
这里的目标类似于我们对正常方程的目标。梯度下降算法通过对θ0 和θ1 应用各种参数来计算出最小成本函数,直到它达到收敛。它被认为是最小化残差的最佳迭代优化算法之一。
作者图片
直觉
将一个碗或任何凸形物体视为您的成本函数。如果你从碗的四周扔出任何物体,它会走最短的最佳路线,并且会到达底部。该最低点将为我们提供最低成本和 θ 参数,以获得最佳拟合模型。
如果我们有许多局部极小值而不是一个全局极小值,很少会有挑战。成本函数通常不是一个普通的碗。它可能会过早停止,或者需要不确定的时间来收敛。不过还好!线性回归中的代价函数是凸的,因此没有任何经过两点之间的直线与曲线相交。
这是一个非常简单的过程。GD 的过程从初始化一些随机的 θ 值开始。我们通过将这些值代入成本函数来计算成本。成本函数的导数将给出该点的斜率,这样我们就知道为了获得更低的成本,下一步应该朝哪个方向走。这是怎么发生的?我们使用该导数值来更新每一步的所有 θ 系数,直到我们达到最低水平并且不再有成本降低。简单!不是吗?
成本函数的偏导数(图片来自作者)
要一次性计算所有这些参数,我们可以使用包含每个模型参数的偏导数的梯度向量。
成本函数的梯度向量(图片由作者提供)
注意,这个梯度向量指向上坡,所以下坡我们需要反方向走。一旦我们有了梯度向量,我们需要找到学习率 η 来确定下坡台阶的量。
每步后更新权重(图片由作者提供)
在尝试不同的 eta η值时,有一些事情需要记住。 如果学习率太低,可能需要不确定的时间才能收敛到最优值。然而,将它保持在高位可能会让它跳到另一边,并无限振荡。所以, η 应该保持在两者之间。为了找到一个好的学习率,我们可以应用网格搜索。通过这样,我们尝试和测试各种 η 值,保持对迭代次数的限制。收敛较快的将是问题的良好学习速率。该方法被称为批量梯度下降,因为它在整个训练集 x 上执行计算。
还有两种没有太大区别的梯度下降—
随机梯度下降
如果我们有非常大的数据集,批量梯度下降会爆炸。可能要花很长时间才能完成。random 的工作方式与 Batch GD 类似,但是它在训练集中选择一个随机实例,并仅基于该实例计算梯度。所有其他的计算都是一样的。它比批处理更快,因为在操作时我们的数据少了。
然而,这种算法没有被经常使用,因为它随机地获取实例,这使得成本函数反复地变高变低。即使收敛到最优,也会继续反弹。此外,它经常不止一次地选择实例,所以建议继续混排数据。
提示:
所以,最好一开始就有较大的学习率,然后慢慢降低。
小批量梯度下降
它需要小规模的随机实例集。但有时,摆脱局部最小值可能会变得更加困难。就不规则性而言,它优于随机梯度下降。
摘要
三者都接近最小值,但是批量梯度下降实际上在最小值停止。
对于较大的数据集,批量梯度下降将需要较长的时间。如果我们知道如何改变学习速率,随机和小批量将更快地达到最小值。
GD,SGD,Mini GD 的对比(来源:Book[Aur _ lien _ G _ Ron]_ Hands-On _ Machine _ Learning _ with _ Sc)
线性回归模型示例— COVID
让我们首先浏览一下芝加哥的新冠肺炎数据集。你可以从这里下载数据集。
数据集(作者提供的图片)
网上 80%的 COVID 数据集是时间序列格式,显示每天的病例数。因此,只有死亡和测试计数,我只能想象是否已经达到峰值,或者是否还在增加等等。但是为了进行预测,我希望拥有案例计数可以依赖的特性。我们还知道,在许多国家,检测工作做得不充分,因此病例数量较少。因此,我把重点放在可以获得测试和案例特征的数据集上,以弄清楚这两者之间是否存在巨大的相关性。
幸运的是,我找到了这个小型的芝加哥数据集,它具有测试与案例计数等特性。您可以观察到数据如何在散点图上显示略微呈线性的模式,从而显示相关性。
散点图(图片由作者提供)
如你所见,自变量是测试 (x)和因变量是案例(y) 。我们的数据集中还有一些特征,给出了 30 岁以上或更年轻的人以及拉丁人的数量,等等。我个人无法推断出我们可以用这样的特征分析什么。你可以试试看,让我知道我们是否能推断出什么。
开始编码吧:)
- 导入所有需要的库
- pandas & numPy 用于执行科学运算
-线性回归&多项式特征用于构建模型 - train_test_split 用于将数据集划分为训练和测试子集
- MSE & r2_score 度量用于分析模型性能
- seaborn 和 pyplot 用于可视化图形
- pandas & numPy 用于执行科学运算
import pandas as pd
import numpy as npfrom sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.model_selection import train_test_splitfrom sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_scoreimport seaborn as sns
import matplotlib.pyplot as plt
- **使用 pandas 导入 CSV 数据集。**它输出一个数据帧,一个二维标记的数据结构。
data.head() 显示数据集中的前 5 行,让我们了解对象中是否有正确的数据类型。
data = pd.read_csv("COVID-19_Daily_Testing.csv")
data.head()
- 以获得数据集的简明摘要。
Info() 方法打印关于数据帧的信息,如索引数据类型和列数据类型、非空值和内存使用情况。
print(data.info())
- 是时候清理一些数据了! 案例和测试计数是字符串格式,因此我们在千位值中有一个逗号(例如 1,468)
*PD . to _ numeric()*会将类型从 string 转换为 int32。
data['Cases'] = data['Cases'].str.replace(',', '')
data['Tests'] = data['Tests'].str.replace(',', '')data['Cases'] = pd.to_numeric(data['Cases'])
data['Tests'] = pd.to_numeric(data['Tests'])
- 通常,在真实世界的数据集中,有许多要素,很难检查哪对要素显示出良好的相关性。此外,检查是否存在任何多重线性问题。下面的代码基本上绘制了数据集中的成对关系,这样每个变量在 x 轴和 y 轴上都是共享的。
data_numeric = data.select_dtypes(include=['float64', 'int64'])
plt.figure(figsize=(20, 10))
sns.pairplot(data_numeric)
plt.show()
特征对图(图片由作者提供)
大多数情况下,它们都呈现出一种不应该发生的线性模式!这就产生了著名的多重线性问题。
多重线性问题是当回归模型中的独立变量表现出相关性时。自变量应该是独立的。通俗地说,你可以认为几个变量本质上衡量同一件事。没有必要用一个以上的变量来衡量一个模型中的同一事物。这基本上降低了估计系数 θ 的精度,削弱了你的回归模型的统计能力。
为了诊断多重共线性**,**,我们使用一种叫做方差膨胀因子(VIF)的方法。方差膨胀因子(VIF)用于测量与预测变量不线性相关时相比,估计回归系数的方差膨胀了多少。经验法则是,如果我们有 VIF > 10 ,模型具有高度多重线性。
您可以在上图中看到,我们的数据集中存在高度多重线性。好的一面是,我在我的模型中只采用了 2 个特征,但在将来,如果你创建任何回归模型,检查 Vif 并删除彼此相关的独立变量。
- 缩放数据集 特征值可能有不同的比例。因此,为了更好地进行分析和预测,最好将它们转换为相同的比例
X = data['Tests'].values.reshape(-1,1)
y = data['Cases'].values.reshape(-1,1)
- 应用线性回归
reg = LinearRegression()
reg.fit(X, y)
predictions = reg.predict(X)
print("The linear model is: Y = {:.5} + {:.5}X".format(reg.intercept_[0], reg.coef_[0][0]))plt.figure(figsize=(16, 8))
plt.scatter(
X,
y,
c='black'
)
plt.plot(
X,
predictions,
c='blue',
linewidth=2
)
plt.xlabel("Tests")
plt.ylabel("Cases")
plt.show()
我们得到这条直线 Y = 97.777 + 0.18572X
线性回归图(图片由作者提供)
线性回归的均方根误差= > 171.8
正如你所看到的,我们有许多异常值,因为它不能很好地拟合数据。在数据复杂的情况下,我们可以尝试通过应用多项式回归来减少 RMSE。
多项式回归
线性回归的特殊情况,我们试图用一个 n 次多项式方程来拟合数据。它在发现特征间关系的能力上胜过 LR 。在这里,我们为每个特性添加了能力,并将它们添加到我们现有的特性中。将在这个扩展的特征集上进行训练,以获得目标变量和独立变量之间的曲线关系。
poly = PolynomialFeatures(degree =4)
X_poly = poly.fit_transform(X)
poly.fit(X_poly, y)
lin2 = LinearRegression()
lin2.fit(X_poly, y)
pred = lin2.predict(X_poly)
new_X, new_y = zip(*sorted(zip(X, pred)))plt.figure(figsize=(16, 8))
plt.scatter(
X,
y,
c='black'
)
plt.plot(
new_X, new_y,
c='blue'
)
plt.xlabel("Tests")
plt.ylabel("Cases")
plt.show()
Scikit learn PolynomialFeatures 类由一个度数参数组成,我们可以将其添加为应用于数据的最大功率。你需要尝试和测试哪个学位最大程度地减少 RMSE。在尝试了不同的程度值后,我发现程度 4 给了我最好的解决方案。
多项式回归图(图片由作者提供)
多项式回归的均方根误差= > 131.08。 观察这个图如何完美地拟合数据,至少比线性回归好。此外,RMSE 下降了很大程度,这又一次证明了它的善良。要获得模型的性能,还需要更多的概念,比如它是过拟合还是欠拟合,偏差/方差权衡。我们肯定会在下一篇博客中讨论这个问题!
评估指标
RMSE 为 0 意味着你的模型是输出的一个完美的预测器(但是这几乎不会发生)。
回归和分类问题有各种各样的评价标准。如果误差非常大且不理想,可以使用 RMSE,因为它通过平方根进行补偿。
我们拥有的另一个指标是 R 平方(R2) ,它给出了用于预测的回归线的整体模型拟合过程的相对度量。其值介于 0 和 1 之间。值越高,模型越好。R 可以被认为是模型解释的方差的百分比。它有一个更好的版本,叫做调整的 R 平方,甚至考虑到了功能是否被删除或添加。r 的平方要么保持不变,要么增加。调整后的 R 平方将变化考虑在内,这就是为什么当您有许多功能需要试验时,此指标更可靠。
暂时就这样了。
希望你很好地理解了在现实世界中寻找一条完美拟合的线!衰退无处不在,是时候开始注意它了!如果您有任何问题/想法,请在下面的评论区留下您的反馈,或者您可以通过 Linkedin 联系我。到那时,等待下一个职位!😄
参考
[## OLS 回归
假设我们有 m m m个训练示例 ( x i , y i ) (\mathbf x_i,y_i) (xi,yi) n n n个特征,$\mathbf x_i = \big[x_{i1},\ …
mlwiki.org](http://mlwiki.org/index.php/OLS_Regression) [## 简化线性回归—普通最小二乘法与梯度下降法
什么是线性回归?线性回归是一种统计方法,用于找出独立变量之间的关系
towardsdatascience.com](/linear-regression-simplified-ordinary-least-square-vs-gradient-descent-48145de2cf76)
理解逻辑回归中的正则化
如何使用正则化处理过拟合
介绍
在我上一篇帖子中,我只使用了两个特征( x 1, x 2 ),判定边界是 2D 坐标上的一条直线。在大多数真实世界的情况下,数据集将具有更多的特征,并且决策边界更加复杂。有了这么多的特性,我们经常会过度拟合数据。过度拟合是与数据集紧密拟合的函数中的建模错误。它捕获数据集中的噪声,可能不适合新的输入数据。
为了克服这个问题,我们主要有两个选择:1)删除不太有用的特征,2)使用正则化。这里我们将重点讨论正规化。
我们将分类的数据创建如下:
生成的数据无法通过线性方程进行分类,因此我们必须添加高阶项作为特征。然而,更多的特征将允许模型拾取数据中的噪声。
逻辑回归的正则化
以前,为了预测 logit(概率对数),我们使用以下关系:
随着我们添加更多功能,等式的 RHS 变得更加复杂。正则化用于通过施加惩罚来降低预测函数的复杂性。在线性关系的情况下,正则化将以下项添加到成本函数中:
其中 D 为特征尺寸。它惩罚特征的系数(不包括偏差项)。现在成本函数变成了:
利用我们对逻辑回归的先验知识,我们现在可以开始构建带有正则化的模型。
R 中的正则化
同样,我们需要首先创建一些助手函数。注意%*%
是 R 中的点积。如果你想了解更多的模型细节,你可以在这里阅读我以前的文章。
逻辑回归函数,原本以训练数据 X ,标签 y 作为输入,现在需要多加一个输入:正则化强度 λ 。
由于我们希望使用一个包含许多特征的示例来演示过拟合和正则化的概念,因此我们需要通过包含多项式项来扩展特征矩阵。
现在,我们可以像以前一样定义预测函数。
分类和决策边界
接下来,让我们在上面的数据集上训练模型。我使用了 6 次方的多项式特征矩阵。降低功率也有助于过拟合。实际上,我们正在删除不必要的功能。
首先,不使用正则化( λ =0),结果如下。该模型明显过度拟合了数据,并错误地将该区域分类为 11 点钟。另一种模型用正则化( λ =5)训练,更能代表总趋势。
左:无正规化;右图:正则化模型。
结论
正则化对于克服过度拟合非常有用。它允许我们保留甚至稍微有用的特征,并自动降低这些特征的系数。
你可以访问我的 github 获取 R 中的源代码。同样的主题还有一个 Python 版本。
理解机器学习中的正则化
通过防止过度拟合来优化预测模型
杰克逊·乔斯特在 Unsplash 上的照片
W 在训练机器学习模型时,一个主要方面就是评估模型是否过拟合数据。过度拟合通常发生在模型试图拟合所有的数据点时,在此过程中捕获噪声,导致模型的不准确发展。
机器学习模型的性能可以通过成本函数来评估。通常,成本函数由实际值和预测值之差的平方和表示。
这里“y”代表实际值,而“ŷ”代表预测值。
这也被称为“残差平方和或“误差平方和”。预测模型在被训练时试图以最小化该成本函数的方式来拟合数据。
当一个模型通过所有的数据点时,它开始过度拟合。在这种情况下,尽管成本函数的值等于零,但是考虑了数据集中的噪声的模型并不代表实际的函数。在这种情况下,根据训练数据计算的误差较小。然而,在测试数据上,误差仍然很大。
本质上,模型通过使用高度复杂的曲线来过度拟合数据,这些曲线具有自由度大的项以及为每一项提供权重的相应系数。
我们可以从方程中清楚地观察到曲线越来越复杂。
从上图可以看出,对于较高的自由度,测试集误差比训练集误差大。
正则化是一个概念,通过它可以防止机器学习算法过度拟合数据集。正则化通过在成本函数中引入惩罚项来实现这一点,该惩罚项为复杂曲线分配更高的惩罚。
基本上有两种类型的正则化技术
- L1 正则化或拉索回归
- L2 正则化或岭回归
让我们首先从理解 L2 正则化或岭回归开始。
L2 正则化或岭回归
岭回归的成本函数由下式给出:
这里λ(𝜆)是一个超参数,它决定了惩罚的严厉程度。λ的值可以从 0 变化到无穷大。可以观察到,当λ的值为零时,罚项不再影响成本函数的值,因此成本函数降回误差平方和。
为了理解惩罚项的意义,让我们深入研究一个例子。
假设我们仅仅根据“误差平方和”来评估我们模型的性能,我们会得到下图中左侧图形所表示的曲线。
如前所述,惩罚项不再影响成本函数的值。因此,我们得到相同的过拟合曲线。然而,当 lambda 的值增加时,我们会得到一条更简单的曲线,如上图右侧的图表所示。
比较两个模型的均方误差,我们观察到,对于过拟合曲线,训练集上的误差最小,但是对于更简单的曲线,测试集上观察到的误差显著下降。
因此,通过简化我们的曲线,我们在训练集中引入了一些误差,但这使我们能够走向更一般化的模型。
需要强调的一个重要方面是,通过改变λ的值并将我们的复杂曲线转换为简单曲线,我们正在处理相同的 15 次多项式模型。直到 15 度的项仍然存在于简单模型的方程中,但是模型的复杂性已经降低。
这是如何实现的?
答案在于刑罚本身的机制。我们再来看看成本函数。
λ是一个超参数,决定惩罚的严厉程度。随着罚值的增加,系数的值收缩,以便最小化成本函数。由于这些系数也充当多项式项的权重,缩小这些系数将减少分配给它们的权重,并最终减少其影响。因此,对于上述情况,分配给高次多项式项的系数已经缩小到这样的程度,即这些项的值不再像以前那样严重地影响模型,因此我们有一条简单的曲线。
在确定了λ的最佳值后,我们将其应用到模型中,得到下面的曲线。
改变λ值的影响
我们观察到,随着λ值的增加,模型变得更加简单,直到它渐近平行于 x 轴。换句话说,对于很高的λ值,我们有一个高度偏差的模型。
λ的值如何选择?
这让我们左右为难。对于非常低的λ值,获得过拟合曲线,而对于非常高的λ值,获得欠拟合或高度偏差的模型。那么怎样才能达到λ的最佳值呢?
这个问题的答案是交叉验证。通常,10 倍交叉验证可以帮助我们确定最佳λ值。
多维数据集
假设我们试图预测一种动物的身体大小。假设这个尺寸取决于它的体重和年龄。在这种情况下,我们模型的功能可以表示为:-
由于我们有多种取决于尺寸的功能,成本可由下式给出:-
如果我们的训练集中的数据点数量有限,岭回归可以通过减少方差并使模型对“训练数据”分布不太敏感,从而使曲线对噪声不太敏感,来改进根据数据做出的预测。
L1 正则化或套索回归
LASSO 代表最小绝对收缩和选择算子。
Lasso 回归的成本函数由下式给出:
与岭回归相似,lambda 也是一个超参数,它决定惩罚的严厉程度。成本函数的区别在于岭回归采用斜率的平方,而套索回归采用斜率的绝对值。
改变λ的影响
随着λ值的增加,系数的值将越来越接近 0,直到该值最终为 0。
注意,在岭回归中,当λ增加时,系数的值收缩,直到模型渐近平行于 x 轴。在 lasso 回归中,对于较大的λ值,模型实际上会变得与 x 轴平行。
为了理解这一点,让我们举一个例子。
假设动物的大小由以下等式给出
套索回归的工作方式是保留最相关的要素,而缩小其他要素。
上述等式的成本函数可以给出如下
在上面的例子中,“体重”和“食物卡路里含量”与体型最相关,而“星座”和“风速”最不相关。因此,“coeff1”和“coeff2”会缩小一点,而“coeff3”和“coeff4”会一直缩小到零。
因此,我们只剩下等式:-
由于 lasso 回归可以从方程中排除无关紧要的变量,因此在减少包含大量无用变量的模型中的方差方面,它比岭回归稍好一些。换句话说,套索回归有助于特征选择。
相比之下,当大多数变量都有用时,岭回归往往做得更好一点。
套索和岭回归的另一个有趣的区别
前面提到过,随着岭回归中λ值的不断增加,模型曲线变得越来越平坦,直到它渐近平行于 x 轴。
为了理解这一点,为了简单起见,我们将参考线性回归模型。
点代表数据点,线代表回归模型。因为这是一条直线,所以它有一个斜率和一个 y 截距。
随着λ值的增加,线性回归模型的斜率将持续降低。
在较大的λ值下,我们观察到回归模型的以下曲线。
虽然看起来这条线平行于 x 轴,但实际上,线性模型的斜率值略大于零。
这种行为可以通过下图直观地观察到。x 轴表示模型的斜率,y 轴表示模型的成本函数值。每个图的左侧是λ值的范围。
曲线中的蓝点代表模型成本函数的最小值。随着 lambda 值的增加,岭回归模型的成本函数的最低值不断向零斜率值移动,但最低值永远不会与零重合。
相反,在 lasso 回归模型中,随着λ值的增加,我们观察到类似的趋势,其中成本函数的最低值逐渐向零斜率值移动。然而,在这种情况下,对于大的λ值,当斜率的值与零一致时,实现了成本函数的最低值。特别是对于等于 40、60 和 80 的λ值,我们在曲线图中观察到一个明显的拐点,其中斜率值等于零,这恰好也是λ等于 80 时成本函数的最低值。
因此,对于较大的λ值,lasso 回归模型可以具有等于零的斜率。
套索回归对特征选择有什么帮助?
让我们看看每种正则化技术的成本函数。
对于套索回归:-
对于岭回归:-
套索回归的一种解释方式是解一个系数的模之和小于或等于常数“c”的方程。类似地,岭回归可以解释为求解一个系数的平方和小于等于常数“c”的方程。
假设我们的模型结合了两个特征来预测某个实体,并且这些特征的系数由β1 和β2 给出。
在这种情况下,岭回归可以表示为:-
类似地,套索回归可以表示为
岭回归方程类似于圆的方程,因此约束区域位于圆的圆周内和圆周上,类似地,套索回归方程类似于菱形方程,约束区域位于该形状的内部和圆周上。
这些方程在下面的图片中被可视化了。
约束区域由浅蓝色区域表示,而红色椭圆是表示“误差平方和”的轮廓。在任何特定的给定轮廓中,“误差平方和”的值都是相同的。轮廓离中心越远,“误差平方和”的值越高。
资料来源:统计学习导论,作者:加雷斯·詹姆斯,丹妮拉·威滕,特雷弗·哈斯蒂,罗伯特·蒂布拉尼
如果“c”的值足够大,约束区域将包含由β (hat)表示的轮廓的中心,因此岭回归和套索回归的值将与“误差平方和”的最小值相同。这对应于λ= 0 的情况。
岭和套索回归的系数估计由轮廓接触约束区域的第一个点给出。由于岭回归具有圆形约束区域,接触点通常不会出现在轴上。因此,系数估计将主要是非零的。
但是,由于套索回归约束区域有突出的角,所以轮廓与轴上的约束区域相交的可能性更大。在这种情况下,其中一个系数的值将等于零。在高维空间中,我们有两个以上的特征,许多系数估计可能同时等于零。
结论
正则化是防止模型过度拟合的有效技术。它允许我们减少模型中的方差,而不会显著增加模型的偏差。这种方法允许我们开发一个更一般化的模型,即使我们的数据集中只有几个数据点。
在确定模型的参数或特征已知的情况下,岭回归有助于缩小模型的系数。
相反,套索回归可以有效地从模型方程中排除无关紧要的变量。换句话说,套索回归有助于特征选择。
总的来说,这是一项重要的技术,可以极大地提高我们模型的性能。
感谢您阅读这篇博客。我希望听到你对此的想法。
如果你渴望在一群志同道合的人的陪伴下踏上高质量的学习之旅,我强烈推荐你加入最有吸引力的社区: 共同学习休息室 关于 电报 和访问colearninglounge.com了解更多信息。
参考
- Josh Starmer, StatQuest:正则化第一部分:岭回归。https://youtu.be/Q81RR3yKn30
- Josh Starmer, StatQuest:正则化第二部分:Lasso 回归。https://youtu.be/NGf0voTMlcs
- Josh Starmer, StatQuest: Ridge vs Lasso 回归,可视化!!!https://youtu.be/Xm2C_gTAl8T2
- 普拉尚·古普塔,机器学习中的正则化。https://towards data science . com/regulation-in-machine-learning-76441 ddcf 99 a
- 统计学习导论
理解 ML 和 DL 中的正则化技术
洞察正则化技术
对减少计算时间和训练 ML 和 DL 模型投入的工时的技术的简单而全面的展望。
乔·加德纳在 Unsplash 上的照片
概述:
现在,随着各行业开始接受“人工智能”作为预测其公司成功的重要组成部分,机器学习和深度学习技术正在进入公司的职位简介列表。但是我们经常看到,公司的实际决策者(发号施令的人:cxo)对这些技术能做什么以及如何让他们的公司受益有一个非常误导的概念。对于那些不完全理解 ML 真相的人来说,ML 经常被视为一种有潜力解决任何和所有工业问题的技术。下图让 ML 目前的状态变得相当清晰。
这不是讽刺而是对 ML 相当准确的理解。它是计算机在提供一组前兆事件的同时预测事件的非硬编码能力。我会尽量保持这篇博客的非数学性,但是在这里我想包括这样一个事实,ML,本质上,是在给定多个这样的方程的情况下,预测 x 和 y 之间的函数关系 F 的行为。
但是很多时候,我们看到,即使在训练了一个模型并且达到了可接受的训练精度之后,当这个模型被用来处理测试用例时,它还是悲惨地失败了。
这是由于过度拟合或使函数过度逼近训练数据的现象而发生的。这导致模型不是理解如何解决问题的一般想法,而是死记硬背训练数据。下图说的很清楚。
真正的函数是正弦曲线(绿色),我们正试图从给定的数据中预测它。直到第三个数字,我们看到模型学习得很好。即使不是所有的数据点都令人满意,这也是一个近乎完美的函数近似值。但是随着训练的继续,我们看到这个函数塑造了自己来适应所有的数据点,并且采取了与我们期望的完全不同的形式。这太合身了。其中训练损失为零,但是测试损失增加
理解偏差-方差权衡和正则化的需要:
偏差在数学上是函数的期望值和实际值之间的差值。我们不会深入偏见的基本统计数据,但我会负责任地留给你一个看起来很可怕的等式:
为了说明问题,简单的线性模型的偏差较高,而复杂的多维模型的偏差较低。这是因为复杂的模型更适合所有的训练数据。
方差是训练数据和测试数据之间 ML 模型的预测精度的变化。方差导致的误差是一个训练集的预测值与所有训练集的预期值之间的差异量。换句话说,根据模型,不同预测的值彼此相差有多远。另一个等式会让你害怕,伙计们。
简单的模型方差低,而复杂的模型方差高。
下图可以用来清楚地建立偏差和方差的概念。图的左端是具有高偏差的区域,因为训练和测试误差都很高。这是拟合不足的区域,或者是模型学习不够的区域。
模型的右端是一个高方差区域,其中训练误差较低,但测试误差较高。这是过度拟合的区域,在这里我们看到,尽管模型已经达到了很高的训练精度,并且看起来模型接近完美,但它在测试数据上的表现很差。这纯粹是浪费计算能力和工程师的时间。
中间区域,偏差和方差都很低,即使不是最低的也是模型的最佳区域。实现这种模型训练状态的行为被称为偏差-方差权衡。
有多种方法可以实现偏差方差权衡。这些方法或技术被称为正则化技术。
一些常见的有:
- L2 正则化
- 提前停止
- 数据集扩充
- 集成方法
- 拒绝传统社会的人
- 批量标准化
L2 正规化:
为了让事情尽可能简单,我将 L2 正则化定义为“不让模型驱动训练误差为零的技巧”。如果事情有那么简单就好了…
在训练模型期间,我们不断更新各种变量(权重和偏差;试图预测我们的原始函数。这种更新是基于“更新规则”进行的,比如梯度下降(我们不会谈到这一点)。该更新规则取决于“损失函数”,该损失函数是这些变量的函数。如果事情变得复杂,请原谅我。我们的目的是最小化这个“损失函数”。这很直观,不是吗?在任何有利可图的工业情况下,你都努力使损失最小化。简单,初始化?
因此,我们在训练过程中最小化损失函数。L2 技术的特别之处在于,我们不是最小化训练损失,而是最小化它的不同版本。
上面等式中的第一项是“损失项”,即衡量模型与数据拟合程度的项。最后一项是数学专家提出的“权重高斯分布可能性的对数”。这度量了模型的复杂性。对于我们这些外行来说,就是所有特征权重的平方和(w)。在这里,我再次负责任地告诉你们:
这种模型的复杂性通过 L2 技术来量化。在这种情况下,接近零的要素权重不会受到变换的太大影响,但异常值会产生巨大影响。而上述项的值越大,我们看到的偏倚的增加和方差的减少就越多。从上图可以明显看出,在训练结束时,偏差非常低,方差很高。因此,如果我们增加偏差并减少方差,我们将有效地到达图表中“好模型”区域的某处。所以现在,我们有了一个很好的模型!耶!
提前停止:
这是迄今为止最简单的正则化技术(它们都是,但是你不会相信我,对吧)。这个过程包括记录最小损失值下的变量(w & b)值。在整个训练过程中,我们记录 w & b 的值,在该值处我们获得最小的验证误差。当我们看到验证错误再次上升时,我们停止训练。这是一个非常有用的过程,但它的缺点是,在训练非常深的神经网络或非常复杂的模型期间,这在写入和重写最小值期间使用了大量的处理能力。
数据集扩充:
只有当我们有大量数据对模型进行训练时,才有可能将模型训练到良好的预测状态。换句话说,如果数据太少,很容易使训练误差为零。让我们以训练一个关于图像分类的神经网络为例。假设我们有 1000 张图片来训练模型。如果我们有 3000 张图片来训练它不是更好吗?无需获取额外数据,我们可以轻松地“扩充”当前图像并创建“新”图像。事实上,这些对我们来说并不新鲜,但对模型来说,它们是新的。
那么什么是增强?它是一种行为,即通过在现有数据中引入某些差异,同时保留原始标签,从现有数据中人为生成新数据。这些差异取决于我们正在处理的数据类型。对于音频,加速采样或引入一些背景噪声是一种增强技术。这不会改变标签值。对于文本,我们可以用同义词替换一个单词,而不改变其传达的信息。对于图像,我们可以改变视角、缩放、照明和其他改变图像但保留其标签的技术。这里有一些可爱的东西来抵消你阅读这篇博客的无聊,并使图像增强变得清晰。
因此,当我们现在有更多的数据输入到我们的模型中时,这使得它更难记住整个事情,因此,训练误差不会变为零。有点像你的历史考试,init?
合奏方式:
集成方法是一种元算法,它将几种机器学习技术结合到一个预测模型中,以减少方差、偏差或改善预测。
上面这一段是 Google 对系综方法的定义,我试着给你分解一下。在这种技术中,我们使用多个模型架构来预测输出,无论是分类还是回归。假设模型 A、B 和 C 被赋予给一只狗分类的任务:模型 A 说它是一只猫,但模型 B 和 C 说它是一只狗。因此,如果我们相信大多数人所说的,我们会得到正确的输出,但如果我们相信第一个模型的输出,我们就错了。回归或价值预测也是如此。我们对给定的 3 个模型的预测进行加权平均,以得出我们的最终输出。这减少了出错的机会并提高了准确性。
有趣的是,我们也不需要在 3 个型号上花费资源。我们可以用不同批次的数据在同一个模型上训练 3 次。这也能达到目的。但是你明白了,不是吗?
辍学:
辍学也被归类为一个整体方法的类别。但是我,为了好玩,认为它是相反的。在集合方法中,你“询问”其他模型的意见以得出结论,但在这里,它基本上是让其他贡献者保持沉默。让我说清楚。
这是一个非常简单的神经网络,其目的是作为一个真/假分类器。查看输出图层(绿色)。它有两个 blobs,一个给出输出为真的概率,另一个给出输出为假的概率。两个值之和:你猜对了:1!你不聪明吗?XD。
这里的想法是让你明白这些“斑点”被称为节点。每个节点内部都有大量复杂的计算。还记得我在《L2 正规化》中提到的东西吗?一切都发生在这里。所以这些节点是输出的实际贡献者。
退出包括随机关闭某些节点。这改变了模型的体系结构和信息在节点间流动的方式。这样做可以使模型成为更可靠的预测器。该模型必须预测相同的输出,其中一些贡献者被关闭。这就像说你需要在没有你的顶级朋友在身边的情况下完成你的测验。你得学会。明白了吗?XD。
结论:
这总结了我关于正则化技术的博客。我故意没有向您提供关于批处理规范化的信息,因为这将需要我向您提供训练神经网络的整个过程,并且这将违背本博客背后的主要思想:保持事情简单。
如果您想知道如何使用 PyTorch 在 Python 上编写这些代码,请参考 GitHub 上的以下资源库。batchnorm_dropout.ipynb 文件可能会有帮助。我也将在另一个回购上上传 TensorFlow 文件,以便在这两个框架上都有代码。
https://github.com/sreyan-ghosh/pytorch_files
我花了很长时间为你们写下这些,我希望你们能从中有所收获。如果你喜欢,留下掌声。如果你没有,你可能会离开这一页很久了。如果你有任何疑问,请在下面留言。我期待着消除你的疑虑。
我喜欢交新朋友,所以这是我的 LinkedIn ID。如果你想聊天或者不想,请连接。XD。
https://www.linkedin.com/in/sreyan-ghosh-b0722a18b/
理解强化学习实践:马尔可夫决策过程
描述和理解复杂的环境,一次一张图
蒂姆·福斯特在 Unsplash 上的照片
“系列”链接:
欢迎回到我们的强化学习系列。这是第四篇文章,所以我们鼓励你回头看看前面的文章。之前,我们谈到了一个非常基本的情况,叫做多臂强盗场景,这让我们开始思考如何通过互动来学习。
今天,我们将开始探索新的环境,使用一个非常强大的工具,马尔可夫决策过程(MDPs)。我们将为描述环境打下坚实的基础,并建立一些术语来帮助我们更深入地研究 RL。
多臂匪徒的陷阱:
我们已经谈了很多关于多支武装匪徒的情况,并发展了强有力的想法和策略来对付他们。然而,我们周围的世界看起来并不像我们目前所呈现的那样简单。终于到了讨论为什么这种环境被认为是“基本”的时候了,以及我们如何描述更复杂的场景。
多支武装匪徒的场景向我们展示了一个单一的情况:站在许多武装匪徒面前,每支武装匪徒都是我们可以采取的独立行动。这种情况在互动后不会改变;我们仍然面临同样的情况和同样的行动。最复杂的变化是不稳定的情况,但我们的决定仍然只关注相同的情况,我们的行动不会影响未来的任何事情。
在现实世界中,我们总是会遇到新的情况,我们的行为会影响我们未来的定位。如果我们想要开发能够处理真实世界的代理,我们需要为环境做一个更健壮的定义。这里是马尔可夫决策过程来拯救!
马尔可夫决策过程:
为了描述和理解更复杂的场景,引入了 MDP(马尔可夫决策过程的缩写)。MDP 框架在一些基本概念下将环境形式化:状态、行动、奖励和过渡模型。
州
从前面的文章中,我们已经对奖励和行为有了一些了解,所以让我们从状态开始。状态可以理解为描述可以找到代理的情况的任何信息。例如,假设我们在一个赌场处理强盗场景,我们有 5 个行动可以采取。在一些互动之后,我们了解到第二只手会产生最高的回报。如果我们去另一个赌场,我们应该期待这是真的吗?当然不是!改变赌场改变了这种情况,所以我们现在可以说我们有两个州,每个赌场一个。这是到目前为止我们的问题的可视化表示。
有两个州可以找到我们的特工。作者图片
状态不受物理位置或对象的限制。让我们回到餐馆的情况。作为提醒,我们提供了一个相当于多臂强盗的例子,让一个人在餐馆里试图从多个选项中选择一道菜。在这里,如果我们考虑代理人是否饥饿,我们可以定义一个更复杂但更现实的场景。这将再次创建两种状态,一种是代理饥饿时的状态,另一种是代理不饥饿时的状态。
餐馆示例的两个新状态。作者图片
必须注意的一个重要警告是,状态必须包含代理采取行动所需的所有信息。例如,我们的代理人不记得它以前是满足还是饥饿,也不记得他以前是否选择了某道菜。如果这不是状态的一部分,那么我们就不会使用马尔可夫决策过程。这个约束是必需的,因为我们希望能够将每个状态视为一个孤立的情况。如果代理人发现自己处于这种状态,它应该能够采取行动,不管它是否是第一个被访问的国家。
这听起来可能是一个巨大的限制,也是一个不现实的限制,因为我们通常是根据我们以前的轨迹或决策路径来做决定的。例如,餐馆里的人或代理人可能记得他刚刚吃了某道菜,出于无聊不想重复自己。但是,也要考虑状态的数量和状态包含的信息是没有限制的。如果有必要,您可以创建保存以前信息的状态。例如:
状态列表,其中一些状态包含以前选择(或吃)的信息。作者图片
这里,我们根据代理在之前的交互中选择的内容来定义新的状态。这听起来像是一个黑客,但也离现实不远。你可以认为自己处于一种状态,在这种状态下,你处于当前的位置,你持有当前的信念和经历。改变你的信仰或经历会改变你目前的状态。
最后,请记住,尽管对您拥有的状态数量没有硬性限制,但是状态越多,我们的代理就越难学习。我们希望在我们的代理可以从环境(也就是州内)访问的信息量和环境拥有的状态数量之间取得良好的平衡。
行动
行动是我们的代理与环境交互的方式。代理可以采取的操作取决于它发现自己所处的状态,每个状态可以包含一组唯一的操作。让我们看看当我们用状态和动作来表示它时,多臂强盗是什么样子的。
3-有状态和行动的武装匪徒。作者图片
这里,我们用 3 个动作(0,1,2)来表示多臂强盗,每个动作都是一个连接到国家的黑点。任何其他状态都可以有不同数量的操作。在两个赌场的情况下,它可能看起来像这样:
多个赌场的场景,每个赌场都有自己的一套行动
现在,动作不仅允许我们与世界互动,还定义了我们如何从一种状态转移到另一种状态。到目前为止,我们的状态彼此完全隔离,但现在我们可以添加路径,以便在采取特定行动时改变状态。让我们以赌场为例,并修改它,以便我们可以看到如何行动可以推动我们通过国家。
两个赌场场景的几乎完整的 MDP。作者图片
现在,对于每一个动作,我们都有一个指向下一个状态的箭头。对于每个状态,我们有一些动作代表拉一只胳膊,还有另一个动作我们称之为“乘公共汽车”,它把代理从一个状态带到另一个状态。请注意,所有的动作都指向一个状态,但并不是所有的动作都将我们从一个状态转移到另一个状态。
奖励
奖励是代理在采取行动后获得的标量值,它可以被认为是代理在环境中做得好坏的度量。我们在选择一个行动后所走的每一条路都有一个相关的回报,它可以是积极的、消极的或零。代理的目标是通过在正确的状态下采取正确的行动来最大化这个值。让我们把它添加到上面的图表中
赌场场景的 MDP,现在有奖励。作者图片
在上图中,我们为每条路径添加了一个奖励,用每个箭头旁边的数字表示。例如,乘坐公共汽车给予奖励 -2 ,以表示从一个州到另一个州是有成本的。每只手臂也有固定的奖励,虽然我们也可以像最初的多臂强盗一样使用随机分配。
奖励的概念很简单,但是给环境分配奖励是强化学习中最困难和最关键的任务之一。由于奖励塑造了我们的代理人的行为,奖励和潜在目标之间的任何不一致都会导致意想不到的行为,以及奖励黑客行为(也称为规范游戏),即代理人利用环境的一些机制来获得高奖励,而不必完成手头的任务。如果你感兴趣的话,DeepMind 安全研究有一篇很棒的文章,介绍了一些规范游戏的案例。我们稍后将讨论奖励系统或奖励函数,但现在请记住,这不是一个微不足道的赋值问题。
过渡模型
使用之前建立的工具,我们已经可以构建完全描述多个场景的 MDP。最后展示的图表可以被完美地认为是一个完整的 MDP。但是,到目前为止,环境的机制是决定性的。采取行动将总是带你走过同样的路,得到同样多的回报。在许多情况下,情况并非如此。有时,一个主体试图采取行动,希望达到一个特定的状态,因为环境会因不可预见或未知的变量而随机做出反应。例如,假设我们的代理试图“乘公共汽车”去另一个赌场。在真实生活场景中,在采取这样的行动时可能没有公共汽车,或者公共汽车可能是满的。所以,有可能采取这样的行动不会让你达到想要的状态。
为此,我们使用转换模型。这个模型代表了环境对代理交互的响应方式,并决定了从一种状态到另一种状态的可能性。现在,让我们用转换模型表示的总线问题来绘制我们的 MDP。
赌场环境中的完全随机 MDP。作者图片
在这里,我们做了一个小小的改变。现在乘坐公交车的行为有两条相关的路径。一个指向下一个状态,而另一个将代理返回到当前状态。另外,请注意,现在我们在每条路径上都有两个数字。这两个数字分别代表走这条路的可能性和回报。因此,在这种情况下,我们最有可能从赌场 2 的州,而不是从赌场 1 赶上公共汽车。
过渡模型通常被表示为一个名为 p 的函数,最常见的是这样写的:
转换模型方程。作者图片
其中***s’***是下一个状态, r 是奖励, s 是当前状态,是当前状态下采取的动作。这个函数返回到达下一个状态(s ')并获得期望奖励®的概率,假设我们当前处于某个状态(s)并采取了指定的行动(a)。例如,使用我们到目前为止开发的 MDP,我们将从转换模型中获得:
使用转移函数的特定转移及其概率。作者图片
在这里,我们说的是到达赌场 2 (C2)并获得 -2 奖励的概率是赌场 1 和乘车的 0.7 或 70%。另一个例子是:
概率为 0 的转移。作者图片
这里我们问的是同样的情况,但是我们没有乘公共汽车,而是拉手臂 1。现在,转换模型说我们没有机会到达赌场 2,因为我们选择的行动不会以任何方式将我们带到那里。您可以将转换模型视为游戏规则、物理引擎或现实世界机制的准确表示。可悲的是,在大多数情况下,我们无法获得这样一个精确的模型,这使得学习变得复杂。我们稍后将开发能够处理转换模型不可用的环境的策略。
作为一个旁注,我想让你,读者,试着用上面的图表找出在赌场环境中采取的最佳行动。有了这个,如果你发现自己在第一个赌场,最好的行动是什么?如果你只考虑眼前的回报,你会选择这条路吗?这应该让你知道我们的代理必须能够考虑采取最佳行动。
健身房的实施
最后,这里有一个使用 gym 接口的上述 MDP 的实现。为了使文章简短,我们不打算在这里讨论实现的细节,而是在附带的笔记本中讨论。如果你想知道我们是如何将 MDP 图转变成一个可以用于强化学习的完整的工作环境的,我们强烈建议你看看它。话虽如此,下面是完工的环境。
使用这个实现,以及一个在其上随机选择动作的代理,我们获得了这样的交互:
赌场环境和随机代理之间的互动链的图像。作者图片
应该可以看出,MDP 和由此产生的相互作用是相容的。
结论
在本文中,我们提出了一个描述场景的框架,称为马尔可夫决策过程。这个框架允许我们想象一个代理如何使用动作遍历不同的状态,以及每次交互会得到什么样的回报。从那以后,我们开发了一个多臂强盗的变体,在这个变体中,我们现在有两种状态,以及从一种状态到另一种状态的转换动作。最后,我们展示了如何使用 gym 环境实现这样的 MDP。
将问题转化为 MDP 是在现实世界中应用强化学习的第一步,因此鼓励你尝试并思考如何描述你作为 MDP 人在日常生活中所做的不同事情。你可能会惊讶于你可以正式描述的事物的数量。接下来的几篇文章将涉及贝尔曼方程,该方程基于马尔可夫决策过程,以定义代理如何理解环境并对其采取行动。那里涵盖的原则也可以应用到我们的日常生活中,所以即使你对开发 RL 代理不感兴趣,它仍然是一本有趣的读物。到时候见!
“系列”链接:
参考资料:
理解强化学习实践:简介
哈桑·帕夏在 Unsplash 上的照片
“系列”链接:
欢迎光临!这是我将要做的关于强化学习的一系列文章中的第一篇,在这一系列文章中,我们将开发这一人工智能分支背后的核心概念,并涵盖多种技术,以在不同的任务中制定、开发和应用 RL(强化学习的缩写)。我这个系列的目标是记录我在这个主题上的学习过程,并希望为任何阅读它的人提供理解这个研究领域的直观和实用的指导。
这个系列受到 Coursera 的强化学习专业化,以及 Richard Stutton 和 Andrew G .巴尔托的书强化学习:导论(第二版)的巨大影响。如果有兴趣加深您对该主题的了解,我强烈推荐您深入研究这些资源。我在理解强化学习方面失败了很多次,直到我偶然发现了它们。我希望这一系列文章能作为一个额外的资源来加强你的理解。
每篇文章都将涵盖这样的理论和应用。我已经基于专业化提供的笔记本创建了自己的编码资源,使用了更多可用的工具,如 OpenAI 的 gym,而不是 RL-glue,因为我找不到有用的文档。解决了这个问题,让我们开始研究这个系列吧!
什么是强化学习?我们为什么需要它?
随着目前在该领域中发现的所有不同的机器学习领域,问我们自己这些问题是很重要的。看到像监督和非监督学习这样的范例在过去(和现在)工作得多么好,一些人可能会认为强化学习只是一种徒劳的学术追求。其他人可能认为 RL 只能用来炫耀我们玩游戏有多烂。但是,RL 超越了这一点,显然值得与其他研究领域区分开来。
理解强化学习的一个好方法是将其与机器学习的其他框架进行比较。RL 认为学习是一种非常特殊的方式。与监督和非监督学习一样,强化学习依赖于优化数值来实现期望的结果/行为。区别在于算法如何获得这些值。
在监督学习任务中,我们得到了一个包含采样数据的数据集以及它的含义。例如,手写数字及其字母数字表示的图像。该算法的目标是将视觉数据与期望的字符相关联。以这种方式,监督学习可以理解为由该领域的专家教授。问题的答案已经给出,我们使用这些信息将数据映射到结果。正如我们将通过查看分数(我们总共获得了多少个好答案)来衡量我们在测验中的表现一样,监督学习模型将通过查看算法预测的结果与其应该预测的结果之间的误差或差异来衡量其表现。使误差最小化是让我们的模型学习的原因。
图一。监督任务的示例。MNIST 数据集。使用 torchvision 和 matplotlib 生成的图像
在无监督学习任务中,我们得到一个包含采样数据的数据集,我们的目标是找到数据中的模式或隐藏结构。与监督学习不同,我们没有得到任何答案,也不知道从这样的分析中会得到什么样的答案。该模型的设计目的是区分数据中的不同关系,以便我们以后可以在其他任务中使用这些关系。这类模型试图优化的价值很大程度上取决于我们试图从数据中获得什么样的信息。例如,自动编码器会通过算法传递数据,希望这种模型的输出与输入非常相似。在这种情况下,我们测量输入和输出之间的差异,并试图将其最小化。
图二。基于 MNIST 数据训练的自动编码器的潜在空间的可视化。
与前面提到的方法相反,强化学习没有数据集可使用。!).相反,数据是通过与环境交互而生成的。从我们的互动中,我们得到了“奖励”,它指出了我们做得好坏。在一系列长时间的互动后(比如在国际象棋比赛中获胜),我们可以获得有意义的奖励,我们的互动可以极大地改变未来的结果(国际象棋中失败的错误可以一直追踪到比赛开始)。模型的任务是找到与环境互动的正确方式,从而使其获得的回报金额最大化。
图 3。A2C 强化学习代理玩突围。
这里明确的区分是“交互”。强化学习问题通常需要您通过采取行动来生成数据,同时根据您拥有的数据采取行动。这非常重要,因为我们的目标是得到一个尽可能表现最佳的代理。让我们假设一下,我们想要尝试训练一个模型使用强化学习之外的东西来玩突围。为了让我们能够做这样的尝试,我们需要获得一个健壮的数据集,我们的代理可以从这个数据集学习行动。这已经是一项艰巨的任务了!例如,请看下图:
图 4。越狱游戏中的一个特殊状态。
桨接下来应该采取什么动作?球可能向球拍移动,也可能远离球拍。另外,这是我们代理的最佳位置吗?或者有更好的方法来摧毁更多的砖块?为这项任务获得好的数据集的困难不仅是技术上的,也是理论上的。无论我们决定以何种方式收集数据,我们都假设数据显示了完成任务的最佳方式。如果我们用人类的表现作为参考点,那么我们的代理人将永远做得和人类竞争者一样好。在这样的限制下,我们永远不会看到人工智能在这些任务中击败人类的新闻。
强化学习本质上是一种在不断变化的世界中进行交互学习的范式。在我们的模型需要采取行动的情况下,这种行动改变了手头的问题,那么强化学习是实现目标的最佳途径(也就是说,如果要使用一种学习方法)。RL 代理从交互中学习的能力产生了获得超人性能的潜力,无论是在我们真正擅长还是真正不擅长的任务上。我相信,这使得强化学习值得努力。现在,这个领域通常被视为在视频游戏中产生巨大的结果,但在未来,我们可以看到 RL 代理优化真实世界的问题,这些问题在历史上一直困扰着我们!强化学习确实很有前途。
结论
这是对什么是强化学习,它与其他学习框架有何不同,以及为什么我们应该研究它的快速介绍。强化学习是一个非常有趣的领域,我希望这篇文章给您留下了这样的印象。在下一篇文章中,我们将深入探讨武装匪徒的问题,这是一个基本的场景,展示了所有强化学习方法背后的核心思想和复杂性。
“系列”链接:
参考资料:
- 没有引用的图像由作者生成。
- 图二。摘自知识共享署名 4.0 许可下的 Tensorflow 教程。
- 图 3。取自麻省理工学院许可下的稳定基线文档。
- 图 4。取自麻省理工学院许可下的稳定基线文件。
- Coursera 的强化学习专业化由阿尔伯塔大学提供。
- 萨顿和巴尔托(2018 年)。 强化学习:入门 。剑桥(麻省。):麻省理工学院出版社。取自斯坦福档案馆。
理解强化学习实践:多臂强盗
马库斯·斯皮斯克在 Unsplash 上的照片
“系列”链接:
这是强化学习系列的第二篇文章,我们在其中探索和发展了在交互式场景中学习背后的思想。在之前的文章中,我们介绍了什么是强化学习,它与其他学习框架有何不同,以及为什么它值得关注。在本文中,我们将探索一个最基本的场景,从中我们可以开始构建强化学习代理如何从环境中学习和行动的理论。
在本文中,我们将涵盖理论和代码。这里将展示一些代码片段,但是我强烈建议大家跟随我为这篇文章准备的笔记本一起阅读。
多臂强盗场景
我们发现自己身处赌场,希望策略和运气都能给我们带来丰厚的利润。在这个赌场里,我们可以从已知数量的武装匪徒那里试试运气。所有盗匪的行为都是随机的,但平均下来,他们每个人都会返回指定的利润。一些强盗有更高的回报,因此必然有一个强盗会给比其他强盗更高或相等的回报。你怎么去找这样的武装匪徒?假设我们想最大化我们的利润(因此也最小化我们的损失),最好的策略是什么?
武装匪徒或者赌场里的老虎机。你会选择哪一个?Benoit Dare 在 Unsplash 上的照片
让我们从创建这样的场景开始。我们将使用 OpenAI 的健身房来建立一个行为类似于上面解释的赌场的环境。
多武装匪徒环境的实现。
从上面的实现中,我们可以创建一个环境,在这个环境中,我们可以定义我们的赌场拥有的强盗数量,以及他们的平均利润和与平均值的偏差。每当我们与环境交互时,我们都必须指定我们选择拉哪个土匪,并且环境为那个行动返回一个奖励。这里有一个小例子:
互动的结果。我们和所有的强盗一起行动,看看他们的报酬是什么。
从上面的例子中,我们创建了四个强盗,其中第一个强盗的平均利润最高为 5,而最后一个强盗的平均利润最低为-10。我们与每一个强盗互动,看看它给了我们什么奖励。奖励是随机的,但是他们接近每个强盗的平均水平。偏差决定了每个强盗的随机奖励有多远。请注意,第二个 bandit (Bandit 1)的偏差非常小,因此随机值非常接近平均值。第三个 bandit (Bandit 2)具有更高的标准差,这意味着我们可以找到与平均值相差很远的值。
在这种情况下,随机性的影响至关重要。有时我们很幸运,在一个强盗身上获得很高的价值,但有时我们就没那么幸运了。与每个强盗互动一次并不能告诉我们这个强盗总体上有多好。有时,一个平均水平低但方差高的强盗可能会给我们带来幸运的头奖,但其他强盗可能会给我们一个整体更好的结果。
这是一个非常熟悉的情况。即使你不喜欢赌博,你也会发现自己不得不一直做这样的决定。无论何时你在餐馆,你必须决定你想要什么菜。你应该去吃那道你已经尝过并且知道你喜欢的菜吗?还是会用另一道菜来一炮?你有机会找到新的最爱,或者后悔没有选择更安全的食物。这就是所谓的探索-开发困境。
探索与开发的困境
每当代理想要优化与未知(甚至部分已知)环境的交互时,就会出现这种困境。代理人希望尽可能采取最优行动,但不知道哪种行动是最优的,因为他不完全知道哪种行动对他最有利。最佳行动的唯一方法是采取次优行动,以充分了解环境。通过探索,我们更多地了解了我们的环境,但牺牲了获得已知回报的机会。通过开发,我们利用现有的知识来获得最佳结果,但是由于知道得不够多,我们可能会采取次优的行动。这种困境几乎存在于我们在强化学习中遇到的每一个现实生活中。制定良好的应对策略至关重要,这正是我们在这里要做的。
评估我们的行动
在我们开始提出策略之前,我们需要知道如何评估我们的行动。看待这个问题的一个好方法是看我们如何评价一家餐馆的菜肴。
每次我们得到一道菜,我们都会评估我们的选择有多好。好吃吗?我对食物有多满意?对于每一个盘子,我们赋予一些值来表示这个选择对我们有多好。每次我们选择这道菜时,这个值都会更新。我们经常选择的菜肴最终会达到平均满意度。
这也是代理评估其行为的方式。在我们的场景中,对于我们可以从多臂强盗那里得到的每一只手臂,我们都有一个我们期望从这样的行动中得到的价值。起初,我们什么都不知道,因此也不期待什么,但是每次我们采取行动,我们都会更新我们的期望。
例如,假设我们拉第一只手臂 5 次。对于我们的行为,我们收到了这份奖励清单。
拉第一臂 5 次获得的奖励列表
因此,该臂的预期值是我们到目前为止看到的所有值的平均值。
根据以前的知识计算拉第一臂的期望值。这是一个简单的平均数
因此,根据我们之前的互动,我们期望获得奖励 4.954 。如果我们再拉一次手臂,我们需要再次计算平均值。如果我们必须为所有可能的行动存储所有以前看到的奖励,这可能会变得乏味和不切实际。通过将平均函数重新表述为更新规则,我们可以做得更好。经过一些在周围扭来扭去,我们得到:
增量平均更新规则
在英语中,这意味着每当我们想要更新一个行为的值时,我们就取我们之前的期望值,加上我们期望的回报和我们获得的回报之间的差,除以我们实际采取该行为的次数。例如,如果我们第六次拉第一臂,获得奖励 5.18 ,那么我们可以计算我们的新期望值为:
使用平均更新规则获得的新期望值
我们会为所有可能的行动这样做。请注意,随着我们采取行动的次数增加,更新规则将最终收敛。这是因为随着 n 变大,数值变化越来越小。
贪婪的代理人
我们的第一个策略将完全集中在开发上。贪婪的代理人总是会根据其现有的知识选择最佳行动。也就是说,代理将总是选择具有当前最大期望值的动作。例如,如果这是我们的代理为每个操作计算的值列表,那么它将选择操作 1:
显示每项行动的预期值的表格。
这在数学上可以表示为取期望值的 argmax 。如果两个或更多的动作被认为是最佳的(也就是说,它们具有相同的值,并且该值是最大的整体动作),那么代理在这些动作中随机选择。例如,这里它会随机选择动作 1 或动作 3:
显示每项行动的预期值的表格。行动 1 和 3 被认为是最好的。
这个行为对于 argmax 函数来说并不是默认的,所以我们需要自己编写一个可以任意中断联系的函数。
Argmax 任意中断连接
现在,我们需要做的就是实现我们贪婪的代理。为此,我们需要指定代理如何采取行动,以及代理如何从交互中学习。如上所述,代理基于哪个动作产生最大期望值来采取动作。另一方面,它通过使用增量平均更新规则更新每个动作的值来学习。
贪婪代理的实现
在我们进行任何测试之前,我们希望我们的代理在这项任务中表现如何?起初,我们的代理人对这个世界一无所知,因此期望每个动作都是一样的。在采取第一个行动后,有两种情况可能发生:代理人要么赔钱(负回报),要么获利(正回报)。如果代理人赔钱,那么它会认为采取的行动是一个不好的行动,并选择另一个。如果在后一种情况下,它赢了钱,对这种行动的期望增加,并成为所有行动中最大的行动。这意味着,它将继续采取行动,除非他失去足够的钱来看起来不好的行动。
回到我们餐厅的例子,一个贪婪的顾客试了一道菜,如果他喜欢,他一辈子只会点那道菜。只有当顾客有足够的不愉快经历不喜欢这道菜时,他才会尝试另一道菜。
你认为这是获得最佳结果的好策略吗?我们的代理肯定不会做得很差,但也不会做得最好。对我们的代理人来说,能找到最好的行动,而不是另一个看起来不错的行动,这将是非常幸运的。让我们来测试一下!
代理和环境之间交互的简化实现
上面的代码实现了代理和环境之间的交互。代理有 1000 次尝试来获得尽可能多的奖励。让我们看看这种互动是如何进行的。下面你会发现 6 个不同的代理与 6 个不同的环境互动。该环境由代理可以采取的 8 个单独行动(或武装匪徒)组成。红点表示每个操作的真实期望值,而蓝条表示代理的估计值。
6 个不同的贪婪代理与多臂土匪问题互动。有 8 个不同的动作
如你所见,探索不是我们代理人的主要目标。只有当所有其他行为看起来比它更糟糕时,代理人才会探索新的行为。有时候,我们的代理很幸运,并降落在最高价值的行动(如第五代理),但大多数时候,它最终在一个次优的行动。事实上,有时我们的代理是如此不幸,当它与正确的选择进行交互时,它收到了一个糟糕的结果!看看第四个代理,它与动作 0 交互,动作 0 是最好的动作,但从中得到了损失。在那之后,我们的代理人就没有机会再尝试那个行动了,即使它会比其他任何行动带来更高的平均回报!
我们刚刚看到一些代理商使用贪婪策略,这看起来并不好。但整体表现如何?我们实际上可以做很多实验,观察平均行为。
贪婪策略的平均最优性。只会在 40%的情况下落在最佳动作上。
上图显示了 10,000 多次单个实验的平均值,即代理采取最佳行动(即,对环境的最佳行动)的次数百分比。上面的图表明,平均来说,40%的时候我们的贪婪策略会让我们采取最优行动。我们还可以得出结论,经过几次尝试,代理人并没有得到任何改善。只有前十几次尝试对我们的代理人来说很重要,因为之后通常会坚持一次行动。显然,纯粹的开发技术远非最佳。如果我们引入一些探索呢?
ɛ-greedy 代理
这个新策略给动作选择过程增加了一点随机性。一般来说,代理的行为就像上面看到的贪婪代理一样。但是,每隔一段时间,它会随机选择一个动作。我们的代理人采取随机行动的概率是由一个叫做ε(ɛ).)的新参数决定的因此,ε是 0 和 1 之间的值。
其工作方式是,每当我们的代理想要采取行动时,它就“掷骰子”,并根据结果决定是贪婪地行动还是随机地行动。例如,如果ɛ被分配到 1/6,那么这就等于说,每当代理人在骰子上掷出 1,它就会随机行动。这是我们代理的新实现:
ɛ-greedy 代理的实现。
我们实际上是基于贪婪实现的代理,只是改变了代理如何选择要采取的动作。
现在我们的代理将允许一些勘探,但是勘探的数量是基于我们分配给ɛ.的数量如果ε是 0,那么我们的代理将充当贪婪的实现。另一方面,如果ε是 1,那么我们的代理只不过是一个随机机器。现在,我们将使用ε值 0.1,但稍后我们将探索其他值。因此,我们的代理人在 90%的时间里会贪婪地行动,而探索性的时间只有 10%。
让我们来看看这一战略的实施情况:
事情开始有希望了!在上面几乎所有的例子中,我们的代理都能找到最佳行动。事实上,如果有足够的时间,我们的代理最终会为所有的行为找到一个好的估计值。注意蓝色条现在如何显示更接近红点的值?我们的代理现在可以足够自信地知道哪个动作是最佳的。同样,让我们看看这个策略平均起来是什么样的:
ɛ-greedy 代理与贪婪代理的最优性
与贪婪策略相比,ɛ-greedy 代理做得更好!经过 1000 步之后,ɛ-greedy 策略在 80%的情况下都能接近选择正确的行动。此外,我们看到这种策略如何随着时间的推移增加其最优性,这意味着它总是从互动中学习。
那么,我们应该为ɛ选择什么样的价值观呢?好吧,让我们测试ε的多个值,看看它们平均获得多少奖励:
这里,我们看到在这种情况下ε的最佳值是 0.1。原因是因为它足够小,让我们的代理人大多表现贪婪,因此优先考虑高回报,但又足够大,让我们的代理人快速探索环境。更高的ε值将开始妨碍我们的代理人,因为时间探索是不能获得高回报的时间。较低的值意味着我们的代理将需要更长的时间来了解环境,这意味着它可能需要很长时间才能找到最佳行动。
包扎
到目前为止,我们已经呈现了一种在最佳行动和探索性行动之间进退两难的局面。我们已经看到这种困境如何极大地影响我们学习和与环境互动的方式。基于这种情况,我们定义了一些方法,让我们的代理可以评估它的行为,并从环境中学习。本文揭示并比较了解决勘探开发困境的两种策略,即贪婪代理和ɛ-Greedy 代理。这些策略背后的思想将贯穿我们的强化学习之旅,理解它们背后的概念,以及它们的优点和缺点将在以后为我们服务。
在下一篇文章中,我们将探索当我们的策略用于非稳定环境时会发生什么。也就是说,当从我们的行为中获得的平均回报不是静态的,而是在我们的代理人与之互动时发生轻微变化。因此,我们将提出一些修改,可以使我们的代理在这种情况下表现得更好。如果你走到了这一步,给自己一个鼓励。这不是一个容易的阅读,我希望你在这个过程中学到了一些东西。
“系列”链接:
参考资料:
理解强化学习实践:非静态
探索动态世界以及如何应对它们
乔纳森·彼得森在 Unsplash 上拍摄的照片
“系列”链接:
欢迎来到强化学习系列的第三篇文章。在上一篇文章中,我们探索了我们将要应对的一系列场景中的第一个,多臂匪徒。在这种情况下,我们面对的是一个有固定数量行动的环境,我们的任务是找到能产生最大回报的行动。我们提出了一些策略,并测量了它们在这个简单任务中的表现。
在本文中,我们将修改之前呈现的环境,使其更具动态性。我们将看到我们以前的策略如何处理非稳定环境,以及我们如何能做得更好。
静止与非静止:
上次我们在一个赌场开始了我们的故事,那里到处都是供我们支配的强盗。利用这个例子,我们建立了一个简化的环境,并制定了一个强有力的策略来获得高回报,即 ɛ-greedy 代理。使用这种策略,我们能够在足够的时间内找到最佳行动,并因此获得大量奖励。我们的代理表现得很好,因为它在探索环境和利用其知识之间取得了良好的平衡。这种平衡使代理人能够了解环境的行为方式,同时也能获得高回报。但是,有一个小的假设,我们的代理正在做的能够表现得如此最佳,那就是环境是静态的,不变的。我们这么说是什么意思,我们的代理人在哪里做出这样的假设?
静止的
当我们提到“静止”这个词时,我们谈论的是我们环境的潜在行为。如果你还记得上节课,环境被定义为有一组行动,在互动中,产生随机的回报。即使回报是随机的,它们也是由每个行为的中心值或平均值产生的,我们称之为真实值。为了理解我所说的,让我们来看看我们在上一篇文章中看到的一个动画交互。
ɛ-greedy 代理与静态环境交互的示例。作者图片
观察真实值(红点)是如何静态的。尽管环境会产生随机的回报,但是每个行为都有一个真实的期望值,这个期望值永远不会改变。这是一个很大的假设,而且几乎没有有价值的真实世界场景会随之而来。例如,如果我们的赌场类比是静态的,那么赌场将很快倒闭!那么,我们如何在不使问题变得更复杂的情况下描绘出一个更现实的场景呢?
非平稳的
让多臂强盗场景变得不稳定实际上很简单,我们需要做的就是确保我们所有行动的期望值总是变化的。现在,这种变化不应该是完全不稳定的,因为没有任何策略能够处理完全随机的情况。相反,我们希望期望值慢慢远离。这是为了让我们的代理仍然可以考虑以前的经验对未来的决策有意义。下面是我们如何实现这样的环境
有一些微妙的变化。现在,每次我们的代理与环境交互时,每个动作的真实值都会发生微小的随机变化。当我们创造环境时,可以控制它的变化程度。这是为了我们以后可以用它做实验。现在环境表现如何?我们可以像以前一样进行同样的可视化,但是使用我们的新环境。因为我们对代理不感兴趣,所以我们不打算绘制它的交互。
不稳定的环境。每个动作的值随机变化一定的量。作者图片
为了便于说明,前面的图是用大量的非平稳数据生成的。请注意,在某些情况下,最高值的动作会因随机移动而改变。因为我们感兴趣的是一个行为尽可能优化的代理,所以我们希望代理能够观察到这种变化并相应地采取行动。
当前性能
声明了我们的新环境之后,让我们看看ɛ-greedy 代理在这里的表现。知道我们的代理有探索的空间,代理注意到环境改变应该只是时间问题。
ɛ-greedy 智能体与非平稳环境的相互作用。作者图片
为了使可视化更加清晰,我添加了一些颜色来显示哪个动作具有最大值(橙色点)以及代理认为哪个动作最好(蓝色条)。对于这个动画,经过的时间延长到 800 步。起初,代理能够迅速适应环境的变化,但过一会儿,估计值停滞不前,往往移动缓慢。这使得很难赶上未来的变化,并导致代理人停留在次优行动更长时间。像往常一样,让我们通过平均许多实验的性能来绘制这种策略的最优性。
ɛ-greedy 代理在非稳定环境中的一般性能。作者图片
正如我们所看到的,起初我们的代理很快适应了环境,但是随着时间的推移,它的性能开始下降。尽管我们的代理总是在收集经验,并且总是在探索环境,但它似乎不能处理一个动态的世界。我们如何确保我们的代理在未来适应更大的变化?
更新规则问题
回到上一篇文章,我们展示了一种方法,在这种方法中,我们可以很容易地评估对多武器土匪场景采取行动的价值。这个评估是使用一个基本平均值来完成的,这个平均值在给定的时间后会收敛到预期的行动值。如果你曾经处理过取平均值,你应该知道你加起来的项目越多,结果就越稳健。假设我们想要取三个值列表的平均值:
要平均的小数值列表。作者图片
那么平均值将等于 4 。给定这样一个小列表,任何输入的变化都会使结果平均值发生一定程度的变化。
l 的平均值,修改了最后一个值。作者图片
如果我们使用更大的值列表,那么输入中的相同变化将导致输出中的较小变化。
更大列表的平均值,输入的变化量相同。作者图片
总而言之,我们计算平均值的信息越多,结果就越不容易出现异常值或偏差。在我们之前实现的增量平均更新规则中也可以看到这种影响:
增量平均更新规则。作者图片
1/n 的表达式导致相同的效果,假定随着 n 变得更大**,**,那么 Q 值变化越来越小。这就是导致我们的代理停滞不前的原因。一旦积累了足够的经验,就很难让我们的代理人改变主意。要解决这个问题,我们必须修改更新规则,这样以后的体验才不会被丢弃或忽略。
一般更新规则
那些通常对机器学习有一些经验或知识的人可能已经看到了上述更新规则背后的模式。如果你没有,让我简单解释一下:
通常,对于要学习的机器学习模型,我们使用一种称为误差或损失函数的度量。这种测量确定了我们的模型的性能与预期结果相比有多差。为了改进我们的模型,我们通过逆着误差移动参数来更新它的参数。我们应该移动或修改我们的参数多少?那是由**学习率决定的。**下面是上述语句的一个过于简化的演示。
梯度下降更新规则的过于简单的例子。作者图片
看起来很眼熟,对吧? h(x) 代表我们模型的输出,而 α 代表学习率。这是梯度下降的粗略简化版本,梯度下降是大多数机器学习任务中改进模型的标准方法。如果对这个话题感兴趣,我觉得这是一篇很棒的关于梯度下降的文章。
对比增量平均更新规则和梯度下降,我们的直觉会说 1/n 等价于学习率 α ,那就对了。因此,我们可以将我们使用的更新规则修改为更通用的版本。
通用更新规则。作者图片
这是做什么的?好了,现在我们可以将 α 定义为除了 **1/n 之外的任何值。**使用常数作为学习速率是其他机器学习范例中使用的一种简单而有效的方法,因此我们也可以在这里尝试一下。让我们实现我们的新代理!
我们的新实现基于ɛ-greedy 代理。有一些小的变化。首先,我们添加了一个名为 ss_func 的新参数,它允许我们根据需要更改步长函数。默认情况下,该函数返回值 0.1,这将是这里使用的常量步长。此外,在更新估计值时,我们执行 ss_func 函数,并使用返回值作为我们的步长。为了让事情更清楚,下一行代码相当于声明一个使用这个新实现的ɛ-greedy 代理。
像估计值和ε这样的变量以前已经被假定存在。
让我们看看这个新的代理如何在我们的动态多臂土匪场景中表现,与以前的ɛ-greedy 策略相比。
动态环境下ɛ-Greedy 和等步长ɛ-Greedy 策略的比较。图片作者。
就这样,我们的代理现在能够适应一个动态的世界!通过使用恒定的步长(或学习速率),代理将不再停滞不前。相反,每一个新的经历都是同等重要的,所以用新的知识去克服以前的经历是可能的。
步长参数:
最后,我想简要地了解一下这个新参数 α ,它的行为方式以及什么值对它是合理的。我们已经看到, 0.1 的值在这个场景中给出了很好的结果,但是它在其他值下会有什么表现呢?
步长参数可以被认为是对新知识的置信度的度量。α的高值类似于说我们相信我们最近的经验是手头问题的良好代表。因此,步长参数应介于 0 和 1 之间,其中 1 表示完全信任,0 表示不信任之前的交互对理解潜在问题的代表性。让我们看看这两个值是如何影响学习结果的。
置信度为 1 会将我们的更新规则变成这样:
更新学习率为 1 的规则。相当于将我们的估计值分配给最近收到的奖励。作者图片
在这里,我们基本上是说,我们的估计应该等于最近获得的回报,不考虑任何以前的经验。只有当我们知道(或者真的有信心)我们得到的回报是确定的、稳定的时,这才会起作用。由于现实世界中并非如此(因为交互通常是随机的,而不是随机的交互通常不需要学习算法),因此不应考虑步长值为 1。
置信度为 0 将取消更新规则的更新部分:
对我们最近互动的零信心会使我们先前的估计保持不变。作者图片
由于步长为零,我们排除了代理从经验中学习的可能性。因此,恒定的步长 0 对于强化学习来说是没有意义的。
至于 0 和 1 范围内的其他值,它们决定了我们的代理对方差的反应有多快或多慢,以及它的收敛速度有多快。接近 1 的值将快速更新估计值,并试图跟上环境的变化,但它也容易受到噪声的影响。另一方面,较小的值需要更长的时间来收敛,并且对动态环境的反应较慢。让我们比较一下这个场景的一些值。
动态环境下不同步长的多个代理的性能比较。图片作者。
正如预测的那样,极值不太适合这个问题,低值收敛较慢,高值收敛较快。与机器学习的其他领域不同,在其他领域中,学习速率或步长主要影响收敛时间和达到最佳结果的准确性,在强化学习中,步长与环境的动态程度密切相关。一个真正动态的世界(一个经常快速变化的世界)将要求我们的步长有很高的值,否则我们的代理将不能足够快地跟上世界的变化。
包裹
在本文中,我们介绍了非固定的概念,并将其实现到多臂强盗场景中。然后我们探索了我们之前的竞争者,ɛ-greedy 代理商,在这种新的情况下是如何表现的,并揭示了是什么使它的行为次优。然后,通过借用其他机器学习领域的一些概念,我们定义了一种评估我们行为的新方法。这种新的更新规则允许恒定的步长,这是解决非平稳问题的关键。最后,简要说明了步长参数如何影响学习结果。
本文旨在讨论几个主题,这些主题太长,无法添加到上一篇文章中,但是仍然有足够的价值,可以在本系列文章中介绍。通用更新规则将在以后发挥作用,因此必须涵盖它。有了这个,我们就可以告别多臂大盗,开始触及其他话题了。下一篇文章将讨论马尔可夫决策过程,并为著名的贝尔曼方程奠定基础。这两个概念是强化学习的支柱,理解它们可以真正改变对世界的看法。到时候见!
“系列”链接:
参考资料:
理解强化学习实践:贝尔曼方程第 1 部分
了解代理如何评估环境
Javier Allegue Barros 在 Unsplash 上拍摄的照片
“系列”链接:
欢迎来到强化学习系列的第五篇文章。在上一篇文章中,我们介绍了描述复杂环境的 MDP 框架。这允许我们为基本的多武器强盗问题创建一个更加健壮和多样化的场景,我们称之为赌场环境。然后,我们使用 OpenAI 的 gym 实现了这个场景,并制作了一个简单的代理,它随机地展示了在 MDP 框架下交互是如何实现的。
今天,我们将把注意力放回到代理人身上,并展示一种我们可以描述代理人在复杂场景中的行为的方法,在复杂场景中,过去的行为决定了未来的回报。这将通过提出贝尔曼方程来实现,该方程概括了理解代理如何在 MDPs 上行为所需的所有内容。本文的目标是提供推导贝尔曼方程的第一步,贝尔曼方程可以被认为是机器学习这一分支的基石。在接下来的文章中,我们将继续开发这个等式背后的直觉。这篇文章将重点放在理论上,但已经被淡化,使一切都有直观的感觉和意义。
一个特工看待世界的新方式
我们现在面临更复杂的环境。一个包含多种状态的世界,在这个世界中采取某些行动会导致不同的结果。我们的决定不再对我们周围的世界没有影响,目光短浅也不再一定会导致最佳解决方案。我们的特工不再处理简单的多武装匪徒的情况,我们必须适应他们,如果我们想让他们成功。
以前,我们开发了基于确定代理行为价值的策略。知道了每个行为的价值,代理人就可以通过选择价值最高的行为来优化自己的行为。这是可能的,因为采取的每一个动作都是相互独立的,并且无论代理选择什么动作,它总是面临相同的情况。然而,这一次,仅仅选择呈现给代理的最佳动作在将来可能是有害的。让我们看一个例子。
我们将探索生活在两个完全相同的环境中的两个不同的代理人。环境对我们来说是未知的,所以我们能够从中学习的唯一方法是通过观察这些代理所做的交互。我们将一步一步地跟踪他们,并试图确定哪一个表现得更好。
两个特工在同一个环境中迈出了第一步。作者图片
这里,两个代理都从我们称为 S0 的任意状态开始。第一个代理采取行动向上,而第二个向右。到目前为止,第二个代理似乎表现得更好,因为它获得了 +5 的奖励,而第一个代理获得了 +2 。让我们继续追踪。
两个特工开始了他们对环境的第二步。作者图片
现在第二名特工的情况看起来不太妙。尽管正确的行动在第一步看起来是最好的选择,但它会导致一个非常糟糕的状态,我们最终会失去一些之前获得的奖励。另一方面,第一个代理人没有选择眼前的最优行动,而是从长远来看得到了回报。显然,把我们的行为仅仅建立在行动的价值上并不是一个最佳策略。我们怎样才能做得更好?
评估状态
是时候揭示上述互动背后的环境了。这是一个描述所有状态、动作和奖励的 MDP。
MDP 对于前面例子的底层环境。作者图片
注意这个 MDP 后面真的只有一个选择,是在 S0 拍的。每一个其他的状态都为你指明了一条预定的道路。还要注意的是, S4 只有一个动作,既没有任何奖励也没有转换到另一个状态。这种状态被称为终端状态,因为它们表示没有进一步的交互改变代理的情况的地方。
现在假设您可以指定代理开始交互的位置。查看环境图,哪个州是放置我们的代理的最佳位置?哪个会是最糟糕的?很容易得出这样的结论:最糟糕的状态是 S1,因为从长远来看,我们最终会赚多少赔多少。另一方面, S2 似乎是一个很好的起点,因为我们最终会赚到+4。 S0
我们刚才所做的是查看每个状态,并累积如果我们从该状态开始将获得的奖励。我们只是给了 MDP 上的每个位置一个内在的值。我们可以通过绘制所有路径并显示累积奖励来使这一点更清楚。我们将一个状态的值 s 定义为 v(s) 。
每个州的轨迹和累积奖励的图表。作者图片
你注意到我们是从顶部开始的吗?如果您查看每条路径,您可能会注意到许多重复的计算。 S1 的值取决于 S3 的值,后者取决于 S2 的值,后者取决于 S4 的值。我们可以通过陈述每个状态的值取决于下一个状态的值,以及收到的直接奖励来简化这一点。这样,我们可以将每个状态的值定义为:
使用先前计算的值计算每个状态的值。
这个过程可以概括成一个基本公式:
其中 s 是当前状态,**s’是下一个状态, r 是转换到s’**获得的奖励。到目前为止,我们没有做任何不寻常的事情。我们只是给每个状态分配了一个值,表明如果一个代理从那里开始它的交互,我们期望得到多少奖励。有了这个,代理将能够评估它的行为,考虑未来的回报。
延迟奖励和无限互动
我们对价值的定义看起来不错,但仍有一些细节必须涵盖进来,以使其更加稳健。为此,我们将简要介绍其他 MDP,它们会指出我们当前定义的一些问题。别担心,我们稍后会回到前面的例子。
一个基本的 MDP,代理人只在最后一步得到奖励。作者图片
这里我们有一个新的 MDP,其中所有的转换都没有奖励,除了最后一个,我们得到 +5 。这是一个具有延迟回报的 MDP,因为代理人直到最后一刻才收到对其行为的反馈。看上面的图片,哪个州最适合我们的代理?我们的直觉告诉我们 S2 是最好的状态,因为它就在奖励旁边,但是每个状态的值说明了什么呢?
延迟奖励 MDP 的每个状态的值。作者图片
根据我们目前对价值的定义,除了 S3 之外的每一个州都同样有价值,这并没有错……但是为什么会有这种感觉呢?看来我们的代理人没有紧迫感,他不在乎现在或以后是否会收到报酬。让我们看看另一个 MDP:
一个有两个州无限期奖励特工的 MDP。作者图片
这里我们有一个 MDP,我们的代理人将从 S1 州开始。然后代理人可以选择去一个无限期奖励 +2 或者无限期奖励 +1 的状态。你会走哪条路?很明显,走每一步都有更高回报的路会更好。选择 S0 会给我双倍于 S2 的奖励。这似乎是显而易见的,但是价值函数又是怎么说的呢?
无限奖励的自我指向状态的价值。作者图片
这两种状态的价值是相等的,因为它们迟早都会达到无穷大。同样,我们看到我们的代理没有紧迫感,因为它假设它的交互可以无限延长。我们如何解决这个问题?
我们可以改变环境或互动来增强紧迫感。在延迟奖励 MDP 的例子中,我们可以使每一个转变都有一个小的负奖励,这将因此使代理尝试采取尽可能少的步骤来达到最后的状态。在无限相互作用的情况下,我们可以简单地通过强制实施代理可以采取的最大步骤数来将无限从等式中移除。如果代理只能运行 10 个交互,那么很明显哪个选择更好。但是,有一个简单的数学技巧可以解决这两个问题,而不必改变环境或限制其行为。
折扣系数
到目前为止,我们已经看到了代理评估环境的两种极端方式。第一个是着眼于眼前的回报,忽视任何未来的结果。第二个是考虑到所有可能获得的奖励,直到无穷远。在现实生活中,代理人在优先考虑现在和长远的回报之间有一个平衡。我们通常向前看到某一点,看得越远,就越不关心未来的结果。我们需要做什么改变来获得与我们的代理相同的行为?让我们再来看看我们的广义价值函数
我们在这里声明,一个状态的价值是由眼前的奖励 r 和未来的奖励定义的,它们是由**v(s)**捕获的。如果我们告诉我们的代理人少关心一点未来的回报会怎么样?这可以通过简单地简化这个术语来实现,如下所示:
这个小小的改变看似微不足道,却有着级联效应。让我们看看添加这个值如何改变我们的代理看待这两个有问题的例子的方式。
延迟奖励 MDP 及其各州的价值,折扣系数为 0.9。作者图片
看起来很有希望!我们离眼前的回报越远,这种状态就越不受重视。由于我们要求代理人减少对未来奖励的优先考虑,它显示了对即时奖励的偏好,同时仍然考虑未来事件。无限的 MDP 呢?
贴现因子为 0.9 的无限 MDP 及其各州的值。作者图片
没有必要去理解公式,但是要意识到,通过从价值函数中削弱未来的回报,即使是无限的互动也有一个确定的值,我们的直觉是正确的。现在, S0 价值更高(20),因为它产生的回报是 S2 (10)的两倍。
我们添加到公式中的这个数字被称为贴现因子(𝛾) ,可以是 0 到 1 之间的任何值。这就是广义价值函数加上贴现因子后的样子。
带折扣因子的价值函数。作者图片
这个修改之所以有效,是因为加入了贴现因子,把价值函数转化成了一个几何级数,在上一段建立的条件下总会收敛。
你可以把这个数字看作是代理人在做决定时目光短浅和目光远大程度的衡量标准。折扣因子为 0 意味着代理只考虑即时回报,而值为 1 意味着将其决策一直投射到无穷远处。这个值离 0 越近,它越不向前看。我们可以使用比较多个折扣因子的图表来大致了解代理人提前计划了多远。
根据所选折扣系数比较未来奖励相关性的图表。作者图片
这里我们画出了一个代理人对未来观察到的每个奖励的关心程度,这取决于所选择的贴现因子。例如,折扣系数 0.25 (红色)意味着代理人将展望未来 5 步。折扣系数为 0.75 (橙色)时,代理将提前计划大约 20 步。
包裹
在今天的文章中,我们开始分析代理如何使用价值函数评估复杂的环境。这个函数允许代理人给每个状态添加一个内在值,这个值代表代理人长期期望看到多少回报。我们还通过在价值函数中加入一个折扣因子来平衡代理提前计划的能力。这个折扣因子解决了一些在不同 MDP 上可能遇到的问题,比如延迟奖励和无限奖励累积。
到目前为止,我们只研究了简单的 MDP,其中代理基本上别无选择,只能遵循一系列状态,并且每个动作都有确定的结果。下一篇文章我们将考虑这些复杂因素,这将引导我们推导出完整的贝尔曼方程。我们还会回到 MDP 在这里提出的第一个例子,这样我们就可以解决它了。到时候见!
“系列”链接:
参考资料:
理解强化学习数学,面向开发人员
开发人员破译强化学习数学公式的温和方法
在 Unsplash 上由Tine ivani拍摄的照片
更新:学习和练习强化学习的最好方式是去http://rl-lab.com
如果你是一个数学知识不足的开发人员,你可能很难掌握强化学习的基本公式。
对于没有足够数学背景的人来说,理解这个等式可能很有挑战性。然而,除了神秘的符号之外,理解起来并不困难。
归结起来就是问一个问题:在 S 状态下有什么价值?
更具体地说,假设你在一个电视节目中,放在两扇门前,一扇门后面有 5000 美元,另一扇门有 1000 美元,要求你选择一扇门打开。
罗伯特·阿纳施在 Unsplash 上拍摄的照片
你不知道哪个是哪个,所以你有相同的概率打开其中任何一个。现在的问题是,出演这部电视剧值多少钱?答案相当简单。在最坏的情况下,它值 1000 美元(因为你可以赢得最少 1000 美元),在最好的情况下,它值 5000 美元(因为你可以赢得最多 5000 美元)。为了只有一个值,我们计算平均值为 3000 美元。
所以这种情况或状态的价值,就是你可以期望得到的(平均而言)未来的奖励或回报。
让我们稍微修改一下假设。你被告知左边的门包含 5000 美元,右边的门包含 1000 美元,但是要打开其中任何一扇门,你必须用球击中锁,有 20%的机会击中左边门的锁,有 80%的机会击中右边门的锁。
这种情况的价值是什么?
这将是未来的回报乘以获得它们的概率,所以:
.2 * 5000 + .8 * 1000 = 1800 美元
直观上,我们可以把状态 V(S)的价值想象成贴现的未来回报的总和,用得到它们的概率来加权。
需要贴现因子( γ) ,来源于你在遥远的未来得到的一个奖励,比你在下一步得到的奖励更没有价值,所以会按照达到它所需的步数来贴现,例如: **γγ…。γr,**其中 γ 的乘法次数等于达到奖励的步数。
数学细节可以在本文中找到强化学习背后的数学,简单易行的方法
下图显示了状态、行动、奖励和目标状态之间的关系。
状态 S 有 3 个可能的动作(a1,a2,a3)。每个行动将导致一个或多个目标状态(S1、S2、S3)和不同的奖励(r1、r2、r3、r4、r5、r6)。注意,从 s 到 S4 是不可达。每条边(或箭头)代表沿其路径的一种可能性。
你可以看到状态 S 有 3 种可能的行动,每一种都导致一种或多种不同概率和不同回报的状态。值得注意的是,州 S4 从 S 是不可到达的,但是如果采取行动 a1,S1 是可到达的,并且将导致 2 个可能的奖励。如果采取了动作 a2 或 a3,则可以从 S 到达州 S2。实际上 a2 肯定会到达 S2,而 a3 可能以不同的概率到达 S2 或 S3。
一个状态 s 的值 V(s),将是采取一个动作 a ,的概率乘以到达状态***‘s’,乘以获得一个奖励的概率 r ,乘以期限(t)
但是因为在每个阶段我们可能有几个选项,意味着几个动作可供选择,这导致几个可能的状态‘s’***和几个可能的奖励 r 。我们需要总结所有这些不同的选择。
初始公式可以改写如下。
翻译成代码
这个公式如何转化成代码相当简单。
每个 sum(σ)转换成一个循环,如下图所示。
其中 A 是所有动作的集合,S 是所有状态的集合,R 是所有可能的奖励的集合,
代码显示的内容对开发人员来说可能很奇怪。它在动作集合 A 中的所有动作、状态集合 S 中的所有状态以及奖励集合 r 中的所有奖励上循环。然而,我们知道,有时并非所有动作在所有状态下都可用,并且并非所有状态都可以从当前状态到达,当然,并非所有类型的奖励对于每个动作和每个状态都可用。
所以循环遍历所有这些集合纯粹是浪费精力和时间。
有一些方法可以优化代码以提高性能。
最佳化
看上面的图,很容易看出嵌套循环的数量。
从编程角度来说,可以进行一些优化。没有必要循环所有动作、所有状态和所有奖励。但是我们将只遍历可能的选项,忽略不可用的选项。
例如,并不是所有的动作集都出现在所有的状态上,所以我们不是在一个上循环,而是在该状态下可用的动作上循环,例如 state.getAvailableActions()。
同样,代替整个状态集 S,我们循环遍历从当前状态可达的状态,state.getAccessibleStates(),代替所有奖励 R,我们循环遍历与当前状态和所选动作相关的可能奖励,getRewards(state,a)。
下面的伪代码创建了一个描述状态行为的接口(IState)。这个接口将在下面的算法中使用。
interface IState {
// returns list of states accessible from the current state
function getAccessibleStates() // returns list of actions that can be performed in current state
function getAvailableActions()
// return probability of taking action 'a' in the current state
function getActionProbability(IAction a)// returns the probability of arriving at state s' when performing
// action a
function getStateProbability(IState s', IAction a)// get value of the state
function getValue()// set value to the state
function setValue(double v)}
类 R 表示在给定状态 s 和动作 a 的情况下返回奖励的实用程序类。函数 getReward(s,a)只返回一个奖励,而 getPossibleRewards(s,a)返回一个奖励列表。
函数 getrewardpability(r,s,a)返回在状态 s 和执行动作 a 时获得奖励 r 的概率。
在许多情况下,奖励系统很简单,也就是说每个州和每个行动只有一个奖励。所以 getReward(s,a)和 getPossibleRewards(s,a)返回相同的奖励,getrewardpability(r,s,a)返回 1。
class R {// returns the reward when at state s and performing action a static static function getReward(IState s, IAction a)// returns list of rewards when at state s and performing action a
static function getPossibleRewards(IState s, IAction a)// get the probability of getting reward r when at state s
// and performing action a
static function getRewardProbability(IReward r, IState s, IAction a)}
函数 computeStateValue(s)计算一个状态的值在最一般的情况下,我们假设奖励系统可能不简单,对于同一个状态/动作对可能有几种可能的奖励。
*function computeStateValue(IState s){
sum_s = 0
for( a in ){
sum_s' = 0
for(s' in s.getAccessibleStates()){
sum_r = 0
for(r in R.getPossibleRewards(s, a)){
sum_r += R.getRewardProbability(r, s, a) * (r + gamma
* s.getValue())
}
sum_s' += s.getStateProbability(s', a) * sum_r
}
sum_s += s.getActionProbability(a) * sum_s'
}
return sum_s
}*
假设奖励系统很简单,函数 computeStateValueSinpleReward(s)计算状态 s 的值。所以不需要循环遍历可能的奖励,只是我们简单的调用 R.getReward(s,a),得到的概率是 1。
*function computeStateValueSinpleReward(IState s){
sum_s = 0
for( a in s.getAvailableActions()){
sum_s' = 0
for(s' in s.getAccessibleStates()){
sum_s' += s.getStateProbability(s', a) * (R.getReward(s, a)
+ gamma * s.getValue())
}
sum_s += s.getActionProbability(a) * sum_s'
}
return sum_s
}*
不难注意到,上面的代码涉及一个状态的计算。为了计算所有状态的值,我们对所有状态集进行循环,如伪代码函数 computeValueForAllStates()所示
*function computeValueForAllStates(){
for( s in S){
v = computeStateValue(s)
s.setValue(v)
}
}*
结论
该公式的实现非常简单。然而,这本身是不够的,因为许多参数在现实生活中是未知的。出于这个原因,有很多其他技术可以用来帮助估计这个公式的每个组成部分。
相关文章
- 强化学习背后的数学,最简单的方法
- 开发者强化学习政策
- Q vs V 在强化学习中,最简单的方法
- 数学背后的强化学习,最简单的方法
- 动态编程在强化学习中的简便方法
- 蒙特卡洛强化学习中的简单方法
- TD 在强化学习中,最简单的方法
通过多武装匪徒理解强化学习
强化学习
强化学习(RL)是机器学习的一个方向,源于观察人类如何与环境互动。
为了更好的介绍 RL,我们先把它放在人类学习的背景下来理解。当一个孩子进入一个新的环境(即充满玩具的房间),他不知道环境中的目标是什么。相反,他执行基本上是随机的任务,在行动中学习周围环境的新事物。例如,他随机拿起一个尖锐的玩具,并意识到尖锐的玩具会引起疼痛。他选择了一个盒子,发现里面有一份快餐。通过这一集,孩子在学习。孩子知道尖锐的物体会引起疼痛,盒子里可能会有有用的物品,从而发展出一套规则来帮助指导他以后在这个环境中的决定。孩子通过环境的强化来学习。
强化学习的特点是一种学习框架。学习目标是指导代理通过与环境交互来实现目标。强化学习与监督学习的不同之处在于从专家监督者那里获得的信息的指导性。
在监督学习中,我们可以将使用(例如,标签)对的训练视为一个学习代理,向专家监督器提供给定训练示例的预测标签,专家监督器返回真实标签。专家的标签是完整的反馈,其中包含要采取的正确行动(真实标签)。
另一方面,强化学习中的环境 oracle 只提供不完整的反馈。RL 代理不是接收正确的(真实的)动作,而是仅获得与他们选择的动作相对应的奖励。代理不知道是否存在更好的行动,并且必须依赖于过去奖励的一些历史来比较他们收到的奖励,以便获得所选行动是否有利的感觉。完整的信息只有通过与环境的反复互动才能获得。
现在,让我们定义一个强化学习系统的主要元素:政策、奖励函数、价值函数和环境模型。例如,我们将考虑的环境是一盘棋。
作者图解。照片由 stevepb 通过 Pixabay 拍摄。经由公共领域载体的说明。
代理和环境在序列中的离散时间步骤上相互作用。在每一个时间步,代理接收环境的状态的一些表示。
这是国际象棋环境的两种不同状态。这盘棋有 10 个⁰ 不同的状态。截图来自棋牌在线。
基于环境的状态,代理从其可能的动作集中选择一个动作。一个时间步长后,环境会发生变化,以反映所选操作产生的下一个状态。随着环境的变化,代理人从环境中收到一个数字奖励**。**
- 代理是通过强化执行学习的系统的参与者。
- 策略是学习代理的行为方式:它们用来在环境的不同状态下选择动作的一套规则。例如,国际象棋选手选择下哪一枚棋子的算法。
- 奖励函数定义了环境中的目标。它将状态(或状态-动作对)映射到单个实数值。在国际象棋的例子中,当游戏进行时,所有状态的奖励可能是 0,一旦游戏结束(将死),如果代理赢了,奖励是 1,如果他输了,奖励是-1。RL 代理的目标是最大化长期回报。
- 价值函数概括了每个行动对最大化长期回报目标的影响。价值函数将环境的状态映射到单个值——如果从该状态开始游戏,代理可以预期获得的奖励总额。价值函数有助于在博弈过程中指导代理人。在国际象棋中,一些走法(如危及你的国王)通常是不利的,即使它们不会导致输掉比赛,价值函数捕捉这些信息以向学习者提供比简单的奖励函数更多的信息,而奖励函数通常是不够的。
- 环境的模型是代理在与环境交互后对环境如何运行的预测。该模型将状态-动作对映射到状态。在国际象棋的例子中,环境模型可以简单地是选择一个动作移动棋盘上的选定棋子,并且当着陆位置在对手棋子的顶部时消除对手棋子。
图片来自理查德·萨顿和安德鲁·巴尔托的强化学习[1]
多股武装匪徒问题
这导致我们现在的多武装匪徒问题,最简单的强化学习问题的公式。
多臂土匪。(图片来源:微软研究院)
问题如下。考虑一个带 n 操纵杆的老虎机。你会反复面对拉动 n 控制杆的选择。每拉一次杠杆,你就会从基于你选择的杠杆的固定概率分布中得到一些奖励。你的目标是通过杠杆拉动的总次数来最大化你的长期累积回报。这就是 N 臂土匪问题。
强化学习框架中的多武装匪徒问题。形象的灵感来源于[1]。
作为玩家,最好的解决方案是什么?如果你找到一个能提供积极回报的杠杆,那很好,但这是最好的杠杆吗?是否有其他更好的选择能带来更高的平均回报,寻找其他杠杆是否值得?或者你应该坚持你所知道的,拉你知道是体面的杠杆,但可能不会提供最高的回报?这些问题定义了期望-探索的权衡。
期望-探索权衡是在重复决策中的两难问题,在这种情况下,对世界有不完全了解的代理人必须决定是重复以前行之有效的决策(利用)还是选择新的、未探索的决策,以期获得更大的回报(探索)。选择重复过去最有效的决策被称为贪婪行动。
解决期望-探索权衡问题的一种方法是在利用迄今为止的最佳行动和探索其他行动之间交替进行。这些近乎贪婪的方法被称为 ɛ-greedy 方法。大多数时候,代理人的行为是贪婪的,但偶尔,用概率ɛ,我们在所有可能的行为中随机地、均匀地随机选择一个行为。一种变化是基于不确定性从分布中随机选择动作。因此,代理更有可能选择过去不常选择的动作。汤普森采样是另一种解决多武装匪徒问题的算法。这篇帖子的重点不是解决多股武装匪徒的问题,因此我推荐康纳·麦克唐纳的帖子来解决多股武装匪徒的问题。
这篇文章通过强化学习的视角展示了多臂土匪框架。强化学习代理,如多臂强盗,在没有任务先验知识的情况下进行优化,使用来自环境的奖励来理解目标并更新其参数。
参考
[1]理查德·萨顿和安德鲁·巴尔托。强化学习导论。麻省理工学院出版社,美国马萨诸塞州剑桥,第一版,1998 年。
了解 ResNet 及其变体
计算机视觉/深度学习社区中最具突破性的工作概述— ResNets
自从高计算单元的可用性以来,机器学习社区已经见证了向深度学习实践的范式转变,以实现更好的结果,特别是在计算机视觉领域。一种有前途的方法是卷积神经网络。CNN 是传统神经网络的改进版本,它保持了空间维度的完整性。
在图像分类、目标检测等方面,CNN 已经超越了其他各种框架。因此是研究人员非常感兴趣的。为了使这种学习越来越准确,研究人员已经开始实现越来越深的卷积网络。
为训练选择正确的层数的话题已经讨论了很长时间,事实证明,建立一个更深的网络不会提高精度,反而会降低精度。是的,你没听错,当你在网络中堆积越来越多的单元时,网络的学习能力就饱和了,过了一个阈值,它就下降了。
src: 用于图像识别的深度残差学习,测试和训练“普通”网络的错误
这种网络的精度下降而不是上升的两个基本原因是:
- 消失/爆炸渐变
- 退化问题
然而,第一个问题由标准化初始化和中间标准化层解决,这使得具有数十层的网络能够开始收敛于具有反向传播的随机梯度下降(SGD)。
但是当更深层次的网络开始融合时,他们观察到了退化问题。随着网络深度的增加,精度达到饱和,然后迅速下降。有助于消除这种退化问题的一种方法是添加带有身份映射的附加层。
ResNet [1]介绍了这些跳过一层或多层的**【身份映射】或【跳过连接】**,如图所示:
src: 用于图像识别的深度残差学习,具有身份映射的残差块
这个想法是,我们不只是将额外的层堆叠到网络中,而是将它们添加为剩余块(具有身份映射)。为了实现该方案中的结果,该工作的作者调整了底层映射,并使非线性层学习该映射:
src: 用于图像识别的深度残差学习
代替传统的映射 H(x ),并且原始映射被重铸为:
src: 用于图像识别的深度残差学习
引入这些快捷连接的另一个好处是,它们不会添加任何额外的参数,也不会增加计算复杂度,因为它们被用作身份映射。然而,它们确保了较深的网络和较浅的网络表现一样好。
最初提议的 ResNet 结构如下:
src: 用于图像识别的深度残差学习,最初提出 ResNet
这里需要注意的一点是那些虚线,表示线性投影。理想情况下,为了执行身份映射,F(x)和 X 的维数必须相同,但是当情况不是这样时,我们使用投影向量 Ws 来帮助匹配维数。
src: 用于图像识别的深度残差学习
另一项研究旨在确定何时应该引入这些“跳过连接”!
src: 深度剩余网络中的身份映射,各种风格的 ResNet 块
在得到具有完全预激活的剩余块的最终版本,即上图中的(e)之前,测试和尝试了每种可能的组合。
由于其引人注目的结果,ResNet 很快成为各种计算机视觉任务中最受欢迎的架构之一。
resnet 的流行变种
随着 ResNets 越来越受欢迎,人们对其架构进行了大量研究,研究人员提出了最初提出的工作的不同变体。
ResNeXt
在原始工作的基础上,提出了一个名为ResNeXt【2】的替代方案,其构建模块如下:
src: 深度神经网络的聚合残差变换
该模型采用了重复层的重组策略,同时以一种简单、可扩展的方式结合了拆分-转换-合并策略。该块可能看起来类似于 Inception network [3],其中我们执行各种不同的转换(1x1 Conv、3x3 Conv、5x5 Conv、MaxPooling)并将它们堆叠在一起,而这里我们通过将它们相加来合并不同的转换。
这种类型的块引入了另一个维度基数——独立路径的数量,以及现有的高度和深度维度。该维度的重要性已被其作者通过实验证明,“增加基数是比更深或更宽更有效的获得准确性的方式”,尤其是当深度和宽度开始给现有模型带来收益递减时。
提议的构件有三种可能的变化:
src: 深度神经网络的聚合残差变换,ResNeXt 的等效块
作者还指出,该模型比不同数据集上的 Inception [3]网络更容易训练,因为它只有一个超参数要调整,而不像 Inception 中有更多的超参数要调整。
DenseNet
ResNet 的另一个流行变体是dense net【4】,作者试图通过建立额外的连接来解决渐变消失的问题。在 DenseNet 中,它们通过将所有层直接相互连接来确保网络中各层之间的最大信息流。为了保持前馈性质,每一层从所有前面的层获得额外的输入,并将它自己的特征映射传递给所有后面的层。该模型如下所示:
src: 密集连接的卷积网络,相互连接的 DenseNet 层
除了处理消失梯度,作者还认为,这种实现方式可以实现要素重用,使网络具有很高的参数效率。在传统模型中,每一层都充当一个状态,它从前一个状态读取数据,并写入下一层。它改变了状态,但也传递了需要保存的信息。
DenseNet 架构明确区分添加到网络中的信息和保留的信息,最终分类器基于网络中的所有特征图做出决定。除了更好的参数效率,DenseNet 还通过网络提供了改进的信息流和梯度,这使其易于训练。
src: 密集连接卷积网络,三个密集块的深度 DenseNet。
第 l 层接收来自其所有先前层的特征图作为输入:
src: 密集连接的卷积网络
其中[…]表示连接操作。为了便于在网络中进行缩减采样,它被划分为多个部分,如上所示,中间有过渡图层。过渡层由批量标准化层、卷积层和最大池层组成。
由于其紧凑的内部表示和减少的特征冗余,DenseNets 可能是基于卷积特征的各种计算机视觉任务的良好特征提取器。
我希望它能帮助读者加深对这部开创性作品的理解。
这篇文章的所有图表都取自参考文献中的原文。
参考资料:
[1].贺国强,张晓霞,任世荣,孙军。用于图像识别的深度残差学习。arXiv 预印本 arXiv:1512.03385,2015。
[2].谢,吉希克,杜鹏,涂振宇和何国光。深度神经网络的聚合残差变换。arXiv 预印本 arXiv:1611.05431v1,2016。
[3].塞格迪、刘华清、贾庆林、塞尔马内、里德、安盖洛夫、埃汉、万霍克和拉宾诺维奇。用回旋越走越深。IEEE 计算机视觉和模式识别会议论文集,第 1–9 页,2015。
[4].黄,刘,温伯格,马腾。密集连接的卷积网络。arXiv:1608.06993v3,2016。
了解 SARIMA(更多时间序列建模)
我们调查了 ARIMA 的老大哥萨里玛是如何提高我们预测的准确性的
何前途未卜。但仍有一些事情我们可以合理地确定——圣诞节和感恩节每年都会到来,夏天充满了阳光明媚的日子和度假的家庭(至少过去是这样),每年二月健忘的男朋友和丈夫们会争抢巧克力和最后一束长茎玫瑰。
在分析时间序列时,季节很重要。某些事件每年都会发生:
- 假日
- 暑假
- 返校周
- 节日和年会
- 重大体育赛事
- 年度奖金
有些每月发生一次:
- 租金或抵押付款
- 信用卡账单
- 我们的工资支票(有些是双月一次)
甚至每周一次:
- 星期五(是的,像星期五这样普通的日子在模型中可能是一个具有统计意义的因素)
- 玉米卷星期二(开玩笑)
因此,如果我们知道某件事情可能会以固定的节奏发生,并且每次发生时都会以类似的方式影响我们的目标变量,那么我们应该在构建模型时将其考虑在内。在时间序列中,这种有影响的事件以恒定的频率重复出现被称为季节性。
ARIMA 进修
上一次,我写了很多关于 ARIMA 车型的内容(请先阅读),所以今天我只从高层次上介绍一下:
- AR 代表自回归,是指使用我们的目标变量的滞后值进行预测。例如,我们可能使用今天、昨天和前天的销售数字来预测明天的销售。这将是一个 AR(3)模型,因为它使用 3 个滞后值进行预测。
- I 代表集成。这意味着我们不是采用原始目标值,而是对它们进行差分。例如,我们的销售预测模型将尝试预测明天的销售变化(即,明天的销售减去今天的销售),而不仅仅是明天的销售。我们需要这样做的原因是,许多时间序列表现出一种趋势,使得原始值不稳定。取差值会使我们的 Y 变量更加稳定。
- MA 代表移动平均线。移动平均模型将滞后预测误差作为输入。与其他参数不同,它不是一个可直接观察到的参数(并且它不是固定的,因为它随模型的其他参数一起变化)。在高层次上,将模型的误差反馈给它自己有助于将它推向正确的值(实际的 Y 值)。
S:季节性
在简介中,我们提到了为什么季节性很重要——如果我们知道由于假期,每个冬季都会出现销售高峰,那么我们就应该考虑到这一点。在这种情况下,我们肯定不想在没有对这种系统性峰值进行调整的情况下,将 2020 年 Q1 的销售额与 2019 年第四季度的销售额进行比较——如果不考虑季节性,我们会错误地认为销售额已经下降(我们公司陷入了大麻烦),而实际上这只是预期的节后宿醉。
让我们来看一个具有明显季节性的时间序列,天然气消耗量:
天然气消费(资料来源:圣路易斯美联储银行)
这些反复出现的峰值证明了明显的季节性。如果我们尝试绘制月与月之间的变化,我们会得到一个类似的图。同样,我们一遍又一遍地看到相同的近似序列。
天然气消耗量的逐月变化
它总是周期性的,很容易预测,这意味着我们应该超越周期性(换句话说,调整它)。对于那些不熟悉天然气的人来说,定期出现消费高峰和低谷的原因是因为天然气的主要用途之一是供暖,而供暖需求随季节而变化(冬季月份更多):
每月天然气消耗量;寒冷月份消耗更多
让我们花一点时间思考一下,为什么我说我们应该超越这种周期性。如果我们知道天然气消费在每年一月达到高峰,在每年六月达到低谷,这对于一个模型来说还不够吗?如果你正在建立一个非常简单的模型,那么也许。但如果你想真正了解天然气消费背后的因素,那么你需要比“天然气用量每月变化”更深入。
看看下面的情节。我将数据切片,只包含 6 月份的数据点,然后计算变化。因此,这是一个同比变化,但仅在 6 月份——这是一个快速调整季节性的方法(因为我们是在跨年度比较同一个月)。缺点是我们被迫计算 1 年时间范围内的变化,这相当粗略。
天然气消费的年度变化(根据季节性调整的 6 月数据)
上图中的波动可能比之前的更有趣。因为我们比较的只是六月,所以差异一定是由于除了季节变化之外的其他因素造成的,比如经济因素、价格冲击或者异常炎热或寒冷的六月。通过研究该图(或同样经过季节性调整的类似图)并将其涨落与外部因素相关联,我们可以更好地理解天然气消费中超出正常水平变化的关键驱动因素。
在下图中,我绘制了 1 个月和 12 个月的变化,这样我们就可以了解相对幅度。请记住,1 个月的变化包括季节性,而 12 个月的变化,如 6 月至 6 月的变化,不包括:
天然气消耗量 1 个月和 12 个月变化的比较
从前面的图中可以明显看出,橙色线(12 个月的变化)比蓝色线(1 个月的变化)波动性小得多。这是另一个明确的指标,说明季节性驱动了我们数据中观察到的大部分差异。
使用 SARIMA 控制季节性
我们通常希望查看更高频率的数据,如每周或每月的变化。年度变化对于建立长期预测模型非常重要,但使用它们可能会导致我们错过理解此时此地所必需的粒度。
因此,我们不需要将回归的 Y 变量转换为年度变化,而是可以通过将它作为一个特征(X 变量)包含在我们的模型中来直接控制季节性。萨里玛就是这么做的。SARIMA 代表季节性自回归综合移动平均线(相当拗口)。它很像 ARIMA,但更强大。
我们可以使用 statsmodels 对 SARIMA 的实现。SARIMAX 函数的 3 个关键参数是:
- 原始数据(存储在名为 gas_df 的数据帧中)。看起来是这样的:
date values
0 2001-01-01 2677.0
1 2001-02-01 2309.5
2 2001-03-01 2246.6
3 2001-04-01 1807.2
4 2001-05-01 1522.4
- 与 arIMA 相似,order 参数是一个元组,它告诉函数 AR 滞后的数量、计算差值的时间步长的数量以及要包含在回归中的 MA 滞后误差的数量(按照该确切顺序)。
- 参数 search _ order 类似于 order,只是它用于指定季节性。search _ order 中的前 3 个值与 order 中的值相同(AR、差异范围、MA),但最后一个值指定了定义季节性周期的时间长度。因此,如果我们认为重复的模式在一年中发生(就像我们的情况一样,从六月到六月的差异消除了季节性),我们会将其设置为 12(因为我们数据中的每个时间步长为 1 个月)。
因为这是一个展示 SARIMA 的玩具模型,所以我不做火车测试分割,也不做模型的任何样本外压力测试。
from statsmodels.tsa.statespace.sarimax import SARIMAXs_mod = SARIMAX(gas_df['values'],
order=(1,1,0),
seasonal_order=(0,0,0,1))
predictions = s_mod.fit().predict()
首先,让我们看看一个简单的 AR(1)模型是如何处理这些数据的(AR(1)意味着我们只使用 Y 变量的最新滞后值进行 Y 预测)。在前面的代码块中,我将 search _ order 中的最后一个值设置为 1(因此没有特殊的季节性时间步长),这相当于一个 AR(1)模型,因为我删除了 MA 和季节性组件。
请注意预测值(橙色线)似乎总是比实际值(蓝色线)慢一步。这是 AR 模型的一个经典问题——当你只有过去可以继续时,趋势的根本转变几乎不可能预测。
AR(1)预测
既然我们观察到了天然气消费的常规年度周期,让我们看看是否加入季节性因素会有所改善。我们通过将 seasonal_order 参数更改为(1,0,0,12)来实现这一点,这为我们提供了一个季节性滞后,这意味着我们使用一年前的值(12 个滞后)来进行预测。请注意,为了隔离季节性的影响,我删除了订单参数中的 AR 滞后。
from statsmodels.tsa.statespace.sarimax import SARIMAXs_mod = SARIMAX(gas_df['values'],
order=(0,1,0),
seasonal_order=(1,0,0,12))
predictions = s_mod.fit().predict()
这是考虑了季节性因素的萨里玛预测。顺便说一下,相对于 statsmodels 中的 ARIMA,SARIMAX 的一个优点是 predict 方法的输出是目标变量本身的预测值。而对于 ARIMA,预测方法的输出是目标变量的预测变化(因此您需要做额外的调整来获得原始值)。
萨里玛预测
请注意更好的拟合。橙色线不再滞后;它现在紧紧地覆盖在蓝线上。太好了!
出于好奇,我们实际上可以用 AR(12)模型获得类似的结果。AR(12)包括足够的滞后来捕捉时间序列的季节性,但需要我们估计额外的 11 个 beta(滞后 1 到 11 的 beta ),所以它更容易过度拟合。
把所有的放在一起
酷,这些线重叠了(由于包含了季节性,这意味着我们的 SARIMA 预测覆盖了实际情况)。那又怎样?
我们可以做两件事之一。要么我们可以在 SARIMA 模型中加入其他因素来解释剩余(无法解释的)方差,要么我们可以创建一个季节性调整的序列,换句话说,一个新的 Y 变量。这两者在精神上是相似的,但我一般更倾向于第二种方式。喜欢绘图,看时间序列;这有助于我理解他们。
所以让我们采用后一种方法。我们可以通过从实际观察值中减去我们的 SARIMA 模型的输出(蓝线减去橙线)来创建天然气消费的季节性调整版本。
gas_df['adjusted_values'] = gas_df['values'] - predictions
这是可行的,因为我们的 SARIMA 模型的输出(其中唯一的因素是季节性)可以被认为是“天然气消费水平,其中季节性可以变化,但所有其他因素保持不变”。因此,任何偏离这一均衡季节性水平的现象都必定是由其他因素造成的。这是季节性调整后的情况:
实际非季节性平衡天然气消耗量
我们可以通过将调整后的值与我们知道相对不受季节性影响的时间序列(天然气消耗量的年度变化)进行比较来检验这一点。下表显示了 12 个月的变化、1 个月的变化(受季节性影响)和我们的调整值之间的相关性:
gas_chg12 gas_chg1 adjusted_values
gas_chg12 1.000000 0.199713 0.506134
gas_chg1 **0.199713** 1.000000 0.511884
adjusted_values **0.506134** 0.511884 1.000000
请注意调整值和 12 个月变化之间的相关性更高(0.5 比 0.2)。相关性不接近 1 是没问题的,因为 12 个月的变化对于季节性调整来说有点粗糙,所以我们不想精确地重现它。
酷,现在我们知道,如果我们在时间序列数据中发现重复的季节性模式,我们可以使用 SARIMA 来解释它。祝你好运预测!干杯!
如果你总体上喜欢这篇文章和我的写作,请考虑通过我在这里的推荐链接注册 Medium 来支持我的写作。谢谢!
理解信号。没那么复杂。
信号导论。为你的下一个机器学习项目产生信号。
图片由来自 Pixabay 的 Ryan McGuire 拍摄
即使对科学家来说,信号处理似乎也是极其复杂的事情。即使没有完全意识到它的潜在存在,信号处理也是我们日常生活的核心。本文将探讨什么是信号,我们如何生成信号,并在 Numpy 中存储信号以进行机器学习。
声音是一种波,由声波穿过的介质粒子的来回振动产生。这些声波由高压和低压区域的重复模式组成。它们也被称为压力波。
正弦波的一个例子。
当我们听到一些东西时,我们的大脑会将耳朵听到的这些空气分子的运动转化为我们可以识别的东西。无论是歌词还是音乐,鸟鸣声还是汽车喇叭声。
通常,当我们描述声音时,我们指的是它们的频率。我们以赫兹(Hz)为测量单位,通过每秒的周期数来测量这些波。
例如,这是一个 440 Hz 的声波,钢琴上中央 C 以上的 A 音符的声音:
MediaCollege 的 440 Hz 音频音调(右击并在新标签页中打开)
如果我们测量这种声音,并将其转换成时间函数的数字信号。这是我们将得到的曲线图,一个 440 Hz 的正弦波。它在平衡时上下摆动,每秒钟摆动 440 次。
1/10 秒的 440 赫兹。
我们再来看另一个声波,250 Hz,听起来像这样:
MediaCollege 的 250 Hz 音频音调(右键单击并在新标签中打开
250 赫兹的音调比 440 赫兹的音调低。如果我们要绘制它,它将看起来类似于 440 Hz 波,但频率较低。它每秒振荡 250 次。
1/10 秒的 250 赫兹。
单个声波本身并不令人兴奋。但是当我们把几个频率组合起来,按正确的顺序演奏,我们就能产生音乐。我们用声带发出这些声波来说我们用来交流的话。
当我们将两个频率组合在一起播放时,新的声波就是两个声波之和。我们得到的是一个不是纯正弦波的新波。在某些点,峰值相加变得更高,而其他点相互抵消,结果为零。
合并两个正弦波产生一个新的波。
我们可以增加更多的声音频率;声波会越来越复杂。事实上,这些复杂的声波正是我们的麦克风所拾取的。我们的麦克风在任何时候都能拾取许多不同的频率;最终的录音是所有声音频率的总和。除了那些你实际上想要记录的声音,它还拾取背景噪声、回声,甚至一些电信号噪声。
随着频率的增加,波变得更加复杂。
尽管这些例子是关于声波的,但这些概念也适用于其他数字信号,如心电图和脑电图。了解我们如何在脑机接口应用中使用信号:
成为 X 教授,解开我们心灵的秘密
towardsdatascience.com](/decoding-brain-signals-with-machine-learning-and-neuroscience-bee288c1d585)
那么我们如何以数字方式存储信号呢?
由于模拟信号在时间和幅度上都是连续的,我们需要将信号在时间和幅度上都简化为离散时间信号。这个信号减少过程就是呼叫采样。采样率定义了一秒钟内数据点的数量,也就是采样的速度。
采样率决定了信号的保真度。每个信号都有一个最小采样率,以保存信号中包含的信息。根据奈奎斯特–香农采样定理,采样率必须至少是信号最大频率的两倍,才能完全呈现信号。这意味着,如果信号包含高频成分,我们将需要以更高的速率进行采样。
理论上,只要奈奎斯特极限(采样速率的一半)超过被采样信号的最高频率,原始模拟信号就可以无损重建。否则,信号信息可能不会被完全表示,其中一些原始信号频率可能会丢失。这将导致被称为“混叠的听觉假象,这是重构信号中不需要的成分。
让我们来看看当采样率太低时会发生什么。
持续 2 秒钟的 2 Hz 信号,具有不同的采样率(SR)
上图显示了持续 2 秒钟的 2 Hz 信号;它总共有四次振动,每秒两次。当采样率为 50 和 100 时,波形看起来非常好,因为有足够的数据点。我们开始在 10 和 20 采样速率下看到信号边沿,但仍能清楚地看到四个正峰值。当采样率低于 6 时,信号开始丢失一些信息。
因为人类可以听到 20-20,000 赫兹的范围;这就是为什么音频波形和早期专业音频设备制造商选择 44.1kHz 的采样速率,这是许多数字格式的“标准”采样速率。提高采样率通常会提高音质,但也会增加存储所需的磁盘空间。许多电话和对讲机信号在 8,000 Hz 上传输,以减小分组大小来改善传输。
对于机器学习,以更高的频率采样会产生更好的重构信号,从而产生更好的性能。然而,这需要更快的 CPU/GPU 来转换和处理信号,并且需要更大的 GPU 内存,因为随着输入的增加,它也会增加模型的大小。因此,我们必须权衡每个应用程序的优点和缺点,并了解其中的利弊。
到目前为止,我们已经看到了单通道信号。但实际应用中的信号可能有多个通道。例如,我们在音频中有两个声道,左声道和右声道。在脑电图和心电图中,我们可以有十个或更多的通道。Neuralink 旨在建立一个拥有数千个通道的一体化脑机接口平台。
生成一些信号(用 Python)
我们可以用三个参数生成信号,1)信号持续时间、采样率和频率。
因为我们将信号存储为数字序列,所以首先,我们需要信号的数据点数。这可以通过将信号持续时间乘以采样速率来实现。接下来,我们需要一个时间变量,一个随时间变化的函数,它允许我们为每个数据点生成波形。
我们可以用正弦/余弦周期函数产生正弦或余弦波。正弦函数跟踪围绕单位圆运动的点的 y 坐标,而余弦函数跟踪 x 坐标。
展示正弦函数和余弦函数如何被绘制到单位圆上的一点的动画。[摘自维基百科
使用任何一个函数都会产生一个相似但不同的波。
正弦波和余弦波。
为了创建更真实的信号,我们还可以通过向每个数据点添加随机值来给生成的信号添加噪声。这允许我们测试我们的模型从噪声数据集进行归纳和学习的能力。
具有不同噪声水平的 2 Hz 信号。
回顾前面的章节,一个点的值是所有频率的总和。如果我们想要产生一个包含多个频率的信号,我们可以简单地将每个产生的波形相加。下面是一些生成信号的例子;每一波都增加了前一波的频率:
将不同的频率添加到波形中。
最后,多声道信号的一个例子:
向多个通道添加不同的波形。
如果你打算生成一些信号,这里有来自火炬信号包的代码。
使用此代码,您可以生成自己的数据集,其中输入要素是原始信号(带噪声),预测输出是频率。
由于我目前正在攻读博士学位,从事脑机接口的研究,我做了一个包含信号处理常用代码的 repo。该软件包包括清除信号和其他信号处理技术的功能。请随意检查并开始这个回购,火炬信号。
github.com](https://github.com/jinglescode/torchsignal)
寻找合作者来贡献新的特性、实用功能、错误修复和文档。目前,我一个人在做这个。如果您正在从事信号处理或脑机接口方面的工作,并且渴望构建一个高质量的包来将 PyTorch 应用于信号处理领域,那么请联系我。
生成信号有助于创建理想的数据集,以在“实验室环境”中测试模型的性能在下一篇文章中,我将介绍我们如何过滤和清理机器学习模型的信号。
利用美国总统选举了解辛普森悖论
如果数据分析不正确,见解可能会产生误导
本·怀特在 Unsplash 上的照片
数据谬误
数据是决策的一大利器。但是,如果使用不当,它可能是一把双刃剑。从“抽样偏差”到“虚假因果关系”(相关性并不意味着因果关系),有许多可能包含数据和分析的谬误。 【如何不犯错】【如何用统计数字撒谎】【数理统计】 都是教育我们认识这些谬误的好读物。解释数据时要注意这些。
考虑一下这个场景。这是一个星期五的晚上,你打算去看电影。归结为两部电影。电影 P 和电影 x。你决定查看评论。电影 P 说 90%的用户喜欢。电影 X 在同样的指标上有 82%。你决定看电影 P,因为,很明显!但是,如果你得到进一步的信息,电影 P 只有 10 个用户评价,而电影 X 有 10000 个用户评价,那该怎么办呢?这会改变你的决定吗?大概吧!例子还可以继续。关键是,在分析数据时,你需要小心这种不一致,即使是在简单的日常决定中,比如决定一部电影,或者做出更复杂的决定,比如选择什么职业或者搬到哪个城市。永远保持好奇心去深入挖掘!现在让我们试着理解这样一个谬误。
辛普森悖论
唐纳德·特朗普 vs 希拉里·克林顿
在我们进入辛普森悖论的技术定义之前,让我们回到 2016 年 11 月,试着回忆一下美国总统大选。你还记得唐纳德·j·特朗普是如何击败希拉里·克林顿赢得选举的吗?好吧。现在,让我们更深入地了解投票总数(大众投票)及其百分比份额。
请看下表,每一个州的民众投票的百分比。左侧列出的州是拥有较高共和党(REP)选票份额的州,右侧列出的州是拥有较高民主党(DEM)选票份额的州。如果我们看一下,我们会看到近 30 个州共和党占多数,约 20 个州民主党占多数。我们会得出结论,共和党人(红色)显然拥有更高的大众选票,对吗?不这么认为?继续滚动!
每个州和政党的民众投票(来源:《纽约时报》)
也许看看下面的地图会有帮助!红色的州是共和党占多数,蓝色的州是民主党占多数。多数票是根据该州较高的民众投票决定的。与上面的投票表一致,下面的地图加强了我们最初的信念,即共和党(红州)的投票份额更高。
2016 年选举结果图显示各州获胜者(来源:《纽约时报》)
现在,让我们来看看实际的总票数。
***川普(共和党/红色)😗6290 万 (45.9%)
***希拉里(民主党/蓝色)😗6580 万 (48%)
是的,希拉里·克林顿比唐纳德·特朗普更受欢迎。这种数据汇总时趋势反转的现象,基本上就是辛普森悖论。在分析中避免此类问题的关键是寻找不一致或缺失的数据。在这种情况下,每个州的投票人口(样本大小)。
辛普森悖论,也有其他几个名字,是概率统计中的一种现象,一种趋势出现在几组不同的数据中,但当这些组组合在一起时就会消失或逆转。
来源:维基百科
唉!他们用“选举人票”而不是“大众票”来决定获胜者!
如果这引起了你的兴趣,在这篇发表的论文或斯坦福大学的哲学百科全书中阅读更多关于辛普森悖论的内容。我将在本文的后续部分写更多类似的谬误,敬请关注!
非常感谢您的阅读!我希望这能对你有所帮助。如果你有什么建议,请告诉我。请随时在 LinkedIn 或我的网站上与我联系。我将在数据科学中发布类似的数据谬误和有趣的趋势,敬请关注!
参考文献:
* [## 2016 年总统选举结果:唐纳德·j·特朗普战胜希拉里·克林顿
直播总统选举结果和地图。
www.nytimes.com](https://www.nytimes.com/elections/2016/results/president) [## 辛普森悖论
辛普森悖论,也有其他几个名字,是概率和统计中的一种现象,其中…
en.wikipedia.org](https://en.wikipedia.org/wiki/Simpson%27s_paradox)*
理解奇异值分解及其在数据科学中的应用
了解奇异值分解背后的直觉
在线性代数中,矩阵的奇异值分解(SVD)是将该矩阵分解成三个矩阵。它有一些有趣的代数性质,传达了关于线性变换的重要几何和理论见解。它在数据科学中也有一些重要的应用。在本文中,我将尝试解释支持向量机背后的数学直觉及其几何意义。我将使用 Python 库来进行计算,而不是手动计算,稍后我将为您提供一些在数据科学应用程序中使用 SVD 的示例。本文中,粗体小写字母(如 a )指代向量。粗体大写字母(如 A )指矩阵,斜体小写字母(如 a )指标量。
要理解 SVD,我们需要首先理解矩阵的特征值分解。我们可以把矩阵 A 想象成一个变换通过乘法作用于向量 x 产生一个新的向量 Ax 。我们用[ A ]ij 或 aij 来表示矩阵 A 在第 i 行和第 j 列的元素。若 A 为 m×p 基体, B 为 p×n 基体,则基体积 C = AB (为 m×n 基体)定义为:
例如,二维空间中的旋转矩阵可以定义为:
该矩阵将矢量绕原点旋转角度θ(正θ为逆时针旋转)。另一个例子是二维空间中的拉伸矩阵 B ,定义如下:
该矩阵以恒定的因子 k 沿 x 轴拉伸矢量,但在 y 方向上不影响矢量。同样,我们可以在 y 方向上有一个拉伸矩阵:
举个例子,如果我们有一个向量
则 y = Ax 是 x 旋转θ后的矢量,而 Bx 是 x 在 x 方向上以恒定因子 k 拉伸的矢量。
清单 1 展示了如何将这些矩阵应用于 vector x 并在 Python 中可视化。我们可以用 NumPy 数组作为向量和矩阵。
这里,旋转矩阵是针对 θ =30⁰和拉伸矩阵 k =3 计算的。 y 是 x 的变换向量。为了绘制矢量,使用了matplotlib
中的quiver()
函数。图 1 显示了代码的输出。
图 1
矩阵由 NumPy 中的二维数组表示。我们可以使用np.matmul(a,b)
函数将矩阵a
乘以b
,然而,使用@
操作符更容易做到这一点。向量可以用一个一维数组或一个二维数组来表示,其形状为行向量(1,n)
或列向量(n,1)
。
现在我们要尝试一个不同的变换矩阵。假如
然而,我们不仅仅将它应用于一个向量。最初,我们有一个圆,包含所有距离原点一个单位的向量。这些向量的一般形式为
现在我们计算 t = Ax 。所以 t 是 x 中所有经过 A 变换的向量的集合。清单 2 展示了如何在 Python 中实现这一点。
图 2 显示了 x 和 t 的曲线图,以及在 x 中对两个样本向量 x1 和 x2 的变换效果。
图 2
左边的初始向量( x )如前所述形成一个圆,但是变换矩阵不知何故改变了这个圆,把它变成了一个椭圆。
圆内的样本向量 x1 和 x2 分别转换为 t1 和 t2 。所以:
特征值和特征向量
矢量是既有大小又有方向的量。矩阵 A 对 x 中的向量的一般效果是旋转和拉伸的组合。例如,它改变向量 x1 的方向和大小,以给出变换后的向量 t1 。然而,对于矢量 x2 来说,变换后只有幅度发生变化。其实 x2 和 t2 方向一致。矩阵 A 只在同一个方向拉伸 x2 并给出幅度更大的向量 t2 。改变向量的大小而不改变其方向的唯一方法是将它乘以一个标量。因此,如果我们有一个矢量 u ,并且λ 是一个标量,那么 λ u 具有相同的方向和不同的大小。所以对于图 2 中的 x2 这样的向量,乘以 A 的效果就像是乘以 λ这样的标量。
对于 x 中的所有矢量来说,情况并非如此。实际上,对于每个矩阵 **A,**只有部分向量具有这种性质。这些特殊向量称为 A 的特征向量,它们对应的标量λ称为该特征向量的 A 的特征值。因此一个 n×n 矩阵 A 的特征向量被定义为一个非零向量 u 使得:
其中 λ 为标量,称为 A 的特征值, u 为 λ 对应的特征向量。此外,如果你有任何其他形式的向量at【60】u 其中 a 是一个标量,那么通过把它放入前面的等式我们得到:
这意味着与特征向量 u 方向相同的任何向量(或者如果 a 为负,则方向相反)也是具有相同对应特征值的特征向量。
例如,的特征值
是 λ1=-1 和 λ2=-2 ,它们对应的特征向量是:
我们有:
这意味着当我们将矩阵 B 应用于所有可能的向量时,它不会改变这两个向量(或任何具有相同或相反方向的向量)的方向,而只会拉伸它们。所以对于特征向量,矩阵乘法变成了简单的标量乘法。这里我不打算解释特征值和特征向量是如何用数学方法计算出来的。相反,我将向您展示如何在 Python 中获得它们。
我们可以使用 NumPy 中的LA.eig()
函数来计算特征值和特征向量。它返回一个元组。这个元组的第一个元素是存储特征值的数组,第二个元素是存储相应的特征向量的 2-d 数组。事实上,在清单 3 中,u[:,i]
列是特征值lam[i]
对应的特征向量。现在,如果我们检查清单 3 的输出,我们会得到:
lam= [-1\. -2.]u= [[ 1\. -0.7071]
[ 0\. 0.7071]]
你可能已经注意到 λ=-1 的特征向量与 u1 的特征向量相同,但另一个不同。这是因为LA.eig()
返回归一化的特征向量。归一化向量是长度为 1 的单位向量。但在解释如何计算长度之前,我们需要熟悉矩阵的转置和点积。
转置
列向量 u ( 用 u 上标 t 表示)的转置是 u 的行向量(在本文中有时我表示为 u ^T).一个 m×n 矩阵 A 的转置是一个 n×m 矩阵,它的列由 A 的相应行组成。例如,如果我们有
那么 C 的转置为:
所以行向量的转置变成了具有相同元素的列向量,反之亦然。实际上,转置矩阵第 i 行第 j 列的元素等于原矩阵第j 行第I列的元素。如此
在 NumPy 中,你可以使用transpose()
方法来计算转置。例如,为了计算矩阵C
的转置,我们写C.transpose().
我们也可以使用转置属性T
,并写C.T
来得到它的转置。转置有一些重要的性质。一、 A 的转置的转置是 A 。所以:
此外,产品的转座是逆序转座的产品。
为了证明这一点,请记住矩阵乘法的定义:
而根据矩阵转置的定义,左边是:
右边是
所以等式两边是相等的。
点积
如果我们有两个向量 u 和 v :
这些向量的点积(或内积)定义为 u 乘以 v 的转置:
基于这个定义,点积是可交换的,所以:
分块矩阵
当计算矩阵的转置时,将其显示为分块矩阵通常是有用的。例如,矩阵
也可以写成:
在哪里
所以我们可以把 C 的每一列看成一个列向量, C 可以看成一个只有一行的矩阵。现在要写 C 的转置,我们可以简单地把这一行变成一列,类似于我们对一个行向量所做的。唯一的区别是 C 中的每个元素现在都是一个向量,也应该被转置。
现在我们知道了
所以:
现在 C ^T 的每一行都是原矩阵 C 对应列的转置。
现在假设矩阵 A 是分块的列矩阵,矩阵 B 是分块的行矩阵:
其中每列向量 ai 定义为 A 的第 i 列:
这里对于每个元素,第一个下标指的是行号,第二个下标指的是列号。所以 A 是一个 m×p 矩阵。另外, B 是一个 p×n 矩阵,其中 bi ^T 中的每一行向量是 B 的第 i 行:
同样,第一个下标表示行号,第二个下标表示列号。请注意,通过对流,向量被写成列向量。所以要写一个行向量,我们把它写成列向量的转置。所以 bi 是一个列向量,它的转置是一个行向量,它捕获了 B 的第 i 行。现在我们可以计算 AB :
所以 A 的第 i- 第列和 B 的第 i- 行的乘积给出了一个 m×n 矩阵,所有这些矩阵相加得到 AB 也是一个 m×n 矩阵。事实上,我们可以简单地假设我们正在用一个行向量 A 乘以一个列向量 B 。作为特例,假设 x 是列向量。现在我们可以类似地计算 Ax :
所以 Ax 只是 A 的列的线性组合。
要计算 NumPy 中两个向量a
和b
的点积,如果两者都是一维数组,我们可以写np.dot(a,b)
,或者简单使用点积的定义,写a.T @ b
。
现在我们已经熟悉了转置和点积,我们可以将向量 u 的长度(也称为 2 范数)定义为:
为了归一化一个向量 u ,我们简单地将它除以它的长度,得到归一化的向量 n :
归一化向量 n 仍与 **u,**方向相同,但其长度为 1。现在我们可以归一化之前看到的 λ= -2 的特征向量:
这与清单 3 的输出相同。如前所示,如果将一个特征向量乘以(或除以)一个常数,新向量仍然是同一特征值的特征向量,因此通过归一化对应于某个特征值的特征向量,您仍然有该特征值的特征向量。
但是为什么特征向量对我们很重要呢?如前所述,特征向量将矩阵乘法简化为标量乘法。此外,它们还有一些更有趣的性质。让我回到清单 2 中使用的矩阵 A 并计算它的特征向量:
正如您所记得的,这个矩阵将一组形成圆的向量转换成一组形成椭圆的新向量(图 2)。我们将使用LA.eig()
来计算清单 4 中的特征向量。
输出是:
lam= [3\. 2.]
u= [[ 1\. -0.8944]
[ 0\. 0.4472]]
所以我们有两个特征向量:
相应的特征值为:
现在我们在变换后的向量上绘制特征向量:
图 3
图 3 中的这些特征向量没有什么特别的。现在让我试试另一个矩阵:
这里我们有两个特征向量:
相应的特征值为:
现在,我们可以通过替换清单 5 中的这个新矩阵,在转换后的向量上绘制特征向量。结果如图 4 所示。
图 4
这次特征向量有一个有趣的性质。我们看到特征向量沿着椭圆的长轴和短轴(主轴)。椭圆可以被认为是一个沿其主轴拉伸或收缩的圆,如图 5 所示,矩阵 B 通过沿 u1 和U2****B的特征向量拉伸它来变换初始圆。
图 5
但是为什么 A 的特征向量没有这个性质呢?那是因为 B 是一个对称矩阵。对称矩阵是与其转置矩阵相等的矩阵。因此主对角线上的元素是任意的,但是对于其他元素,行 i 和列 j 上的每个元素等于行 j 和列 i 上的元素( aij = aji )。这是一个对称矩阵的例子:
对称矩阵总是一个方阵 ( n×n )。你现在可以很容易地看到和是不对称的。对称矩阵通过沿向量的特征向量拉伸或收缩来变换向量。此外,我们知道所有的矩阵都通过将特征向量的长度(或幅度)乘以相应的特征值来转换特征向量。我们知道圆中的初始向量长度为 1,并且 u1 和 u2 都被归一化,所以它们是初始向量 x 的一部分。现在它们的变换向量是:
因此,沿着每个特征向量的拉伸或收缩量与相应的特征值成比例,如图 6 所示。
图 6
所以当你在一个特征向量的方向上有更多的拉伸,对应于那个特征向量的特征值会更大。实际上,如果一个特征值的绝对值大于 1,圆 x 就沿着它拉伸,如果绝对值小于 1,就沿着它收缩。让我试试这个矩阵:
特征向量和相应的特征值是:
如果我们画出变换后的向量,我们会得到:
图 7
正如你现在看到的,我们沿着 u1 拉伸,沿着 u2 收缩。关于这些特征向量的另一件重要的事情是,它们可以形成向量空间的基。
基础
一组向量{ v1 , v2 , v3 …, vn} 形成了一个向量空间 V 的基,如果它们是线性无关和跨度 V 。向量空间是一组可以用标量相加或相乘的向量。这是一个封闭的集合,所以当向量与一个标量相加或相乘时,结果仍然属于这个集合。向量加法和标量乘法的运算必须满足某些要求,这里不讨论这些要求。欧几里得空间是向量空间的一个例子。
当一组向量线性无关时,这意味着该组向量中没有一个向量可以写成其他向量的线性组合。所以不可能写
当某些 a1 、 a2 、…、和都不为零。换句话说,这个集合中的 vi 矢量都不能用其他矢量来表示。如果空间中每隔一个向量可以写成一个生成集的线性组合,则一个向量集生成一个空间。所以 V 中的每个矢量 s 都可以写成:
一个向量空间 V 可以有许多不同的向量基,但是每个基总是有相同数量的基向量。向量空间 V 的基向量个数称为 V 的维。在欧几里得空间 R 中,向量:
是基的最简单的例子,因为它们是线性独立的,并且 R 中的每个向量都可以表示为它们的线性组合。它们被称为 R 的标准依据。因此 R 的尺寸为 2。它可以有其他的基,但是它们都有两个线性无关的向量,并且跨越它。例如,向量:
也可以构成 R 的基础。寻找向量空间的基的一个重要原因是要有一个坐标系统。如果向量组 B ={ v1 , v2 , v3 …, vn} 形成了向量空间的基,那么该空间中的每个向量 x 可以使用这些基向量来唯一地指定:
现在 x 相对于此基准 B 的坐标为:
事实上,当我们在 R 中写向量的时候,我们已经在表达它相对于标准基的坐标了。那是因为任何矢量
可以写成
现在出现了一个问题。如果我们知道一个向量相对于标准基的坐标,我们如何找到它相对于一个新基的坐标?
等式:
也可以写成:
矩阵:
叫做坐标变换矩阵。这个矩阵的列是基 B 中的向量。方程式
如果知道 x 在 R ^n 中的坐标,则给出其在基准 B 中的坐标。如果我们需要相反的结果,我们可以将这个方程的两边乘以坐标变化矩阵的逆矩阵,得到:
现在,如果我们知道 x 在 R ^n 中的坐标(简单地说就是 x 本身),我们可以将它乘以坐标变化矩阵的逆矩阵,从而得到它相对于基底 B 的坐标。例如,假设我们的基集 B 由向量构成:
我们有一个向量:
为了计算 B 中 x 的坐标,首先我们形成坐标变化矩阵:
现在 x 相对于 B 的坐标为:
清单 6 展示了如何在 NumPy 中进行计算。要计算矩阵的逆矩阵,可以使用函数np.linalg.inv()
。
输出显示了 x 在 B 中的坐标:
x_B= [[4\. ]
[2.83]]
图 8 显示了改变基础的效果。
图 8
为了找到基准 B 中 x 的u1-坐标,我们可以从 x 画一条线,平行于 u2 ,看它与 u1 轴相交的位置。U2-坐标的查找方法如图 8 所示。在一个 n 维空间中,为了找到 ui 的坐标,我们需要画一个从 x 穿过,平行于除 ui 之外的所有其他特征向量的超平面,并查看它与 ui 轴的交点。如图 8(左)所示,当特征向量正交时(像 R 中的 i 和 j ,我们只需要画一条穿过点 x 并垂直于我们想要求其坐标的轴的线。
对称矩阵的性质
如图 5-7 所示,对称矩阵的特征向量 B 和 C 相互垂直,形成正交向量。这不是巧合,是对称矩阵的一个性质。
对称矩阵的一个重要性质是一个 n×n 对称矩阵有 n 个线性无关且正交的特征向量,并且它有 n 个实特征值对应于那些特征向量。重要的是要注意,这些特征值不一定彼此不同,其中一些可以相等。对称矩阵的另一个重要性质是它们可以正交对角化。
特征分解
对称矩阵是正交对角化的。这意味着如果我们有一个 n×n 对称矩阵 A ,我们可以把它分解为
其中 D 是由 A 的 n 个特征值组成的 n×n 对角矩阵。 P 也是一个 n×n 矩阵, P 的列是 A 的 n 线性无关特征向量分别对应D中的那些特征值。换句话说,如果 u1 、 u2 、 u3 …、 un 是 A 的特征向量**、λ1、λ2、…、λn 分别是它们对应的特征值,那么 A 可以写成**
这也可以写成
你应该注意到每个 ui 被认为是一个列向量,它的转置是一个行向量。所以 P 的转置是根据 P 的列的转置写成的。T51A的这种因式分解叫做 A 的本征分解。
我举个例子来说明一下。假如
它有两个特征向量:
相应的特征值为:
所以 D 可以定义为
现在 P 的列是 A 的特征向量分别对应D中的那些特征值。因此
P 的转置为
所以一个可以写成
重要的是要注意,如果你在上面等式的右边做乘法,你不会精确地得到 A 。这是因为我们在 NumPy 中有舍入误差来计算通常出现在特征值和特征向量中的无理数,我们也在这里舍入了特征值和特征向量的值,但是,理论上,两边应该是相等的。但这意味着什么呢?为了更好地理解特征分解,我们可以看看它的几何解释。
特征分解的几何解释
为了更好地理解特征分解方程,我们需要首先简化它。如果我们假设每个特征向量 ui 是一个n × 1 列向量
那么 ui 的转置就是一个 1 × n 行向量
和它们的繁殖
变成了一个n×n 的矩阵。首先,我们计算 DP ^T 以简化特征分解方程:
现在,本征分解方程变为:
所以 n×n 矩阵 A 可以分解成形状相同的 n 矩阵( n×n ),这些矩阵中的每一个都有一个乘数等于对应的特征值 λi 。每个矩阵
被称为投影矩阵。想象我们有一个矢量 x 和一个单位矢量 v 。 v 和 x 的内积等于 v 。 x=v^T x 给出了 x 到 v 的标量投影(这是 x 到 v ) **、**的矢量投影的长度),如果我们再乘以 v ,它给出了一个矢量,称为 x 到 v 的正交投影。这如图 9 所示。
图 9
所以当 v 是单位矢量时,乘
通过 x , 将 x 的正交投影到 v 上,这就是为什么它被称为投影矩阵。所以用 ui ui ^T 乘以 x ,我们得到 x 到 ui 的正交投影。
现在让我来计算前面提到的矩阵 A 的投影矩阵。
我们已经计算了 A 的特征值和特征向量。
使用清单 7 的输出,我们得到了特征分解方程中的第一项(这里我们称之为 A1 ):
如你所见,它也是一个对称矩阵。实际上,特征分解方程中的所有投影矩阵都是对称的。这是因为每个矩阵的行 m 和列 n 中的元素
等于
并且行 n 和列 m 处的元素具有相同的值,这使其成为对称矩阵。这个投影矩阵有一些有趣的性质。首先,我们可以计算它的特征值和特征向量:
lam= [ 3.618 0\. ]
u= [[ 0.8507 -0.5257]
[ 0.5257 0.8507]]
如你所见,它有两个特征值(因为它是一个 2 × 2 对称矩阵)。其中一个为零,另一个等于原矩阵 A 的 λ1 。另外,特征向量与 A 的特征向量完全相同。这不是巧合。假设我们得到本征分解方程中的第 i- 项,乘以 ui 。
我们知道 ui 是一个特征向量,它是归一化的,所以它的长度和它与自身的内积都等于 1。所以:
如果你看特征向量的定义,这个方程意味着矩阵的一个特征值
是 λi 对应的特征向量是 ui 。但是这个矩阵是一个n×n 对称矩阵,应该有 n 个特征值和特征向量。现在我们可以将它乘以 A 的剩余 (n-1) 个特征值中的任何一个,得到:
其中 i ≠ j .我们知道 A 的特征值是正交的,这意味着它们中的每一对都是垂直的。两个垂直向量的内积为零(因为一个向量到另一个向量的标量投影应该为零)。所以 ui 和 uj 的内积为零,我们得到
这意味着 uj 也是一个特征向量,其对应的特征值为零。所以我们得出结论,每个矩阵
特征分解方程中是一个对称的 n×n 矩阵,具有 n 个特征向量*。特征向量与原矩阵 A 相同,分别为 u1,u2,… un 。 ui 对应的特征值为λi* (与 A 相同),但其他特征值均为零。现在,记住对称矩阵是如何变换向量的。它会沿着向量的特征向量拉伸或收缩向量,拉伸或收缩的量与对应的特征值成正比。所以这个矩阵将沿着 ui 拉伸一个向量。但是因为其他特征值都是零,它会在那些方向上收缩到零。让我回到 matrix A 并使用清单 9 绘制出 A1 的转换效果。
图 10
如你所见,最初的圆沿着 u1 被拉伸,沿着 **u2 收缩到零。**所以这个变换的结果是一条直线,而不是一个椭圆。这与 A1 是一个投影矩阵,应该把一切都投影到 u1 上的事实是一致的,所以结果应该是沿着 u1 的一条直线。
排名
图 10 显示了一个有趣的例子,其中 2 × 2 矩阵A1 乘以一个二维矢量 x ,但是变换后的矢量 Ax 是一条直线。这是另一个例子。假设我们有一个矩阵:
图 11 显示了它如何转换单位向量 x 。
图 11
所以它作为一个投影矩阵,将 x 中的所有向量投影到直线 y= 2 x 上。这是因为 F 的列不是线性独立的。其实如果把 F 的列分别叫做 f1 和 f2 ,那么我们就有了 f1 = 2f2 。记得我们把矩阵和向量的乘法写成:
所以不像 x 中的矢量需要两个坐标, Fx 只需要一个坐标,存在于一维空间中。一般来说, m×n 矩阵不一定将一个 n 维向量转换成另一个 m 维向量。如果矩阵的列不是线性独立的,则变换向量的维数可以更低。
矩阵 A 的列空间记为ColA 定义为 A 列的所有线性组合的集合,由于 Ax 也是 A 列的线性组合, Col A 是所有的集合ColA 的基矢个数或者ColA 的维数称为 A 的秩。所以 A 的等级就是 Ax 的尺寸。
A 的秩也是 A 的线性无关列的最大个数。这是因为我们可以把所有的相关列写成这些线性无关列的线性组合,而 Ax 也就是所有列的线性组合可以写成这些线性无关列的线性组合。于是它们跨越了 Ax 并形成了colA 的一个基,这些向量的个数就成为了 A 的 col 的维数或者 A 的秩。
在前面的例子中, F 的排名是 1。另外,在特征分解方程中,每个矩阵的秩
是 1。记住,它们只有一个非零特征值,这不是巧合。可以证明对称矩阵的秩等于其非零特征值的个数。
现在我们再次回到特征分解方程。假设我们将对称矩阵 A 应用于任意向量 x 。现在,本征分解方程变为:
每个特征向量 ui 都是归一化的,所以它们是单位向量。现在在特征分解方程的每一项中
给出一个新的矢量,它是 x 在 ui 上的正交投影。然后这个向量乘以 λi 。由于 λi 是一个标量,将其乘以一个矢量,只会改变该矢量的大小,而不会改变其方向。所以 λi 只改变的幅度
最后所有的 n 个向量
加在一起就是给斧头。这个过程如图 12 所示。
图 12
因此,本征分解从数学上解释了对称矩阵的一个重要性质,我们在之前的图中看到了。对称矩阵通过沿着向量的特征向量拉伸或收缩向量来变换向量,并且沿着每个特征向量的拉伸或收缩量与对应的特征值成比例。
此外,特征分解可以将一个 n×n 对称矩阵分解成形状相同的 n 个矩阵*(n×n)乘以其中一个特征值。特征值在这里起着重要的作用,因为它们可以被认为是一个乘数。投影矩阵只将 x 投影到每个 ui 上,但是特征值缩放了向量投影的长度( ui ui^Tx )。特征值越大,得到的向量( λi ui ui^Tx )的长度越大,赋予其对应矩阵的权重也越大( ui ui^T )。因此,我们可以通过对具有最高特征值的项求和来近似原始对称矩阵 A 。例如,如果我们假设特征值 λi 已经按降序排序,*
那么我们只能取特征分解方程中的前 k 项来很好地近似原始矩阵:
其中 Ak 是 A 与**k的近似术语。如果我们只将前 k 个特征值和特征向量包含在原特征分解方程中,我们得到相同的结果:******
现在 Dk 是由A 的第一 k 特征值组成的 k×k 对角矩阵,Pk 是由A 的第一 k 特征向量组成的 n×k 矩阵,其转置成为 k×n 矩阵。所以他们的乘法仍然给出一个 n×n 矩阵,它与 A 的近似相同。****
如果在原矩阵 A 中,我们略去的其他( n-k) 特征值都很小,接近于零,那么这个近似矩阵和原矩阵很相似,我们就有了很好的近似。[数]矩阵
随着
就是一个例子。这里 λ2 比较小。 W e 调用单位圆内的向量 x ,用原矩阵( Cx )绘制它们的变换。然后,我们用矩阵 C 的特征分解方程中的第一项来近似矩阵C,该方程为:****
并由此绘制出 s 的变换。如图 13 所示,近似矩阵的结果是一条直线,非常接近原始矩阵。
图 13
为什么特征分解方程成立,为什么需要对称矩阵?记住对称矩阵的重要性质。假设 x 是一个 n×1 列向量。T5 如果 A 是一个 n×n 对称矩阵,那么它有 n 个线性无关且正交的特征向量可以作为新的基。所以我们现在可以写出 x 相对于这个新基的坐标:
而基于基的定义,任何向量 x 都可以唯一地写成 A 的特征向量的线性组合。
但是对称矩阵的特征向量也是正交的。所以要找到每个坐标 ai ,我们只需要通过点 x 画一条垂直于 ui 的轴的线,看它在哪里相交(参见图 8)。如前所述,这也可以使用投影矩阵来完成。所以每项 ai 等于 x 和 ui 的点积(参考图 9),可以写成 x
所以我们需要一个对称矩阵将 x 表示为上式中特征向量的线性组合。现在,如果我们将 A 乘以 x ,,我们就可以分解出 ai 项,因为它们是标量。所以我们得到:
由于 ui 向量是 A 的特征向量,我们最终得到:
这就是特征分解方程。在乘以 A 后发生的任何事情对所有矩阵都成立,并且不需要对称矩阵。我们需要一个 n×n 对称矩阵,因为它有 n 个实特征值加上 n 个线性独立和正交的特征向量,可以作为 x 的新基。当你有一个非对称矩阵时,你就没有这样的组合。例如,假设您有一个非对称矩阵:
如果你计算这个矩阵的特征值和特征向量,你得到:
*****lam= [2.5+0.866j 2.5-0.866j]
u= [[0.7071+0.j 0.7071-0.j ]
[0.3536-0.6124j 0.3536+0.6124j]]*****
这意味着你没有真正的特征值来做分解。另一个例子是:
你会得到:
*****lam= [2\. 2.]
u= [[ 1\. -1.]
[ 0\. 0.]]*****
这里,特征向量不是线性独立的。其实 u1 = - u2 。所以你不能像图 11 一样只使用一个特征向量来重建 A 。此外,它没有显示如图 14 所示的该矩阵的拉伸方向。
图 14
最后,请记住
我们有:
*****lam= [ 7.8151 -2.8151]
u= [[ 0.639 -0.5667]
[ 0.7692 0.8239]]*****
这里,特征向量是线性独立的,但它们不是正交的(参见图 3),并且它们没有显示变换后该矩阵的正确拉伸方向。
特征分解法非常有用,但只对对称矩阵有效。对称矩阵总是正方形矩阵,所以如果你有一个矩阵不是正方形的,或者是正方形但非对称的矩阵,那么你就不能用特征分解法用其他矩阵来近似它。SVD 可以克服这个问题。
奇异值
在讨论 SVD 之前,我们应该找到一种方法来计算非对称矩阵的拉伸方向。假设 A 是一个不一定对称的 m×n 矩阵。那么可以证明
是一个 n×n 对称矩阵。记住乘积的转置是逆序转置的乘积。因此
所以a^ta 等于它的转置,而且是对称矩阵。我们想要计算非对称矩阵的拉伸方向。,但是我们如何从数学上定义拉伸方向呢?****
到目前为止,我们只关注了二维空间中的向量,但是我们可以在二维空间中使用相同的概念。在这里,我集中在一个三维空间,以便能够形象化的概念。现在列向量有 3 个元素。最初,我们有一个球体,它包含所有距离原点一个单位的向量,如图 15 所示。如果我们称这些向量为 x ,那么|| x ||=1。现在如果我们把它们乘以一个 3 × 3 对称矩阵, Ax 就变成了一个三维椭圆。拉伸的第一方向可以被定义为在该椭圆中具有最大长度的向量的方向(图 15 中的 Av1 )。实际上, Av1 是|| Ax ||在所有单位向量 x 上的最大值。这个矢量是 A 对矢量 v1 的变换。
图 15
****拉伸的第二方向是沿着向量 Av2 。 Av2 是|| Ax ||在 x 中垂直于 v1 的所有向量上的最大值。所以在 x 中的所有向量中,我们最大化|| Ax ||以此约束 x 垂直于 v1 。最后, v3 是垂直于 v1 和 v2 的向量,并且在这些约束条件下给出了 Ax 的最大长度。 Av3 的方向决定拉伸的第三个方向。所以一般在一个 n 维空间中,第 i 个拉伸方向是矢量 Avi 的方向,它具有最大的长度,并且垂直于前面的( i -1)个拉伸方向。
现在让 A 成为一个 m×n 矩阵。我们证明了 A^T A 是一个对称矩阵,所以它有 n 个实特征值和 n 个线性独立和正交的特征向量,这些特征向量可以构成它可以变换的 n- 元素向量的基础(在 R^n 空间中)。我们称这些特征向量为 v1 , v2 ,… vn ,我们假设它们是归一化的。对于这些特征向量中的每一个,我们可以使用长度的定义和转置矩阵乘积的规则来得到:
现在我们假设 vi 对应的特征值为 λi
但是 vi 是归一化的,所以
因此:
这个结果表明所有的特征值都是正的。现在假设我们按降序给它们贴标签,那么:
现在我们将 A 的奇异值定义为λI(a^t a的特征值)的平方根,我们用 σi 表示。
所以 A 的奇异值就是向量 Avi 的长度。现在我们可以总结一个重要的结果,它构成了奇异值分解方法的基础。可以看出,|| Ax ||的最大值受到约束
是 σk ,并且该最大值在 vk 处达到。对于约束条件,我们使用了这样的事实:当 x 垂直于 vi 时,它们的点积为零。
所以如果 vi 是a^ta 的特征向量(按其对应的奇异值排序),并假设|| x ||=1,那么 Avi 为 Ax 呈现一个拉伸方向,对应的奇异值σi 给出了 Avi 的长度。****
奇异值也可以决定 A 的秩。假设非零奇异值的个数为 r 。因为它们是正的,并按递减顺序标注,所以我们可以把它们写成
这对应于
并且每个 λi 都是 vi 对应的特征值。那么可以表明,秩 A 是形成 Ax 的基础的向量的数量,是 r 。还可以看出,集合{ Av1 , Av2 ,…, Avr }是Ax(ColA*)的正交基。因此矢量 Avi 相互垂直,如图 15 所示。*****
现在我们回到非对称矩阵
我们在图 3 中绘制了 A 的特征向量,并提到它们没有显示 Ax 的拉伸方向。在图 16 中,左侧绘制了 A^T A 的特征向量( v1 和 v2 )。由于 A^T A 是对称矩阵,这些向量显示了它的拉伸方向。在右侧,画出了矢量 Av1 和 Av2 ,很明显这些矢量显示了 Ax 的拉伸方向。
图 16
因此 Avi 显示 A 的拉伸方向,无论 A 是否对称。
现在想象矩阵 A 是对称的,并且等于它的转置矩阵。另外,假设其第 i 个特征向量为 ui ,对应的特征值为 λi 。如果我们将 A^T A 乘以 ui ,我们得到:
也就是说 ui 也是 A^T A ,的一个特征向量但是它对应的特征值是 λi 。所以当 A 对称时,不用计算 Avi (其中 vi 是 A^T A 的特征向量)我们可以简单地使用ui(a的特征向量)来得到拉伸的方向,这正是我们对特征分解过程所做的。既然我们知道了如何计算非对称矩阵的拉伸方向,我们就可以看 SVD 方程了。
奇异值分解
设 A 为 m×n 矩阵,秩 A = r 。所以 A 的非零奇异值个数为 r 。因为它们是正的,并按递减顺序标注,所以我们可以把它们写成
在哪里
我们知道每个奇异值 σi 是 λi 的平方根( A^TA 的特征值),对应一个同阶的特征向量 vi 。现在我们可以把的奇异值分解写成:****
其中 V 是一个 n×n 矩阵,其列为 vi 。所以:
我们称一组正交且归一化的向量为 正交 集合。所以集合{ vi }是一个正交集合。列是正交集合的矩阵称为 正交矩阵 ,并且 V 是正交矩阵。
****σ是一个形式为 m×n 的对角矩阵:
所以我们先做一个 r × r 对角矩阵,对角元素为 σ1,σ2,…,σr 。然后我们用零填充它,使它成为一个 m × n 矩阵。
****我们还知道集合{ Av1 , Av2 ,…, Avr }是 Col A,和σI =|Avi| |的正交基。因此,我们可以通过将向量除以它们的长度来标准化这些向量:
现在我们有一个集合{ u1 , u2 ,…, ur }它是 Ax 的正交基,Ax 是 r 维的。我们知道 A 是一个 m × n 矩阵, A 的秩最多可以是 m (当 A 的所有列线性无关时)。由于我们需要一个 U 的 m×m 矩阵,我们将(m-r)向量添加到 ui 集合中,使其成为一个 m 维空间r^m的归一化基(有几种方法可以用于此目的。例如,我们可以使用*格拉姆-施密特过程。然而,解释它超出了本文的范围)。所以现在我们有了一个标准正交基{ u1 , u2 ,…, um }。这些向量将是正交矩阵 m×m 的 U 的列*********
所以最后,我们可以将 A 分解为
为了更好地理解这个等式,我们需要简化它:
我们知道 σi 是标量;ui 是 m 维列向量, vi 是 n 维列向量。于是每个σIui****VI^t 是一个 m×n 矩阵,SVD 方程将矩阵 A 分解成形状相同的 r 矩阵( m×n )。****
首先,让我来说明为什么这个等式是有效的。如果我们将 SVD 方程的两边乘以 x ,我们得到:
我们知道集合{ u1 , u2 ,…, ur }是 Ax 的一个正交基。所以向量 Ax 可以写成它们的线性组合。
并且由于 ui 向量是正交的,每一项 ai 等于 Ax 和 ui (标量投影 Ax 到 ui )的点积:
但是我们也知道
因此,将它代入前面的等式,我们得到:
我们还知道 vi 是 A ^T A 的特征向量,其对应的特征值 λi 是奇异值 σi 的平方
但是点积是可交换的,所以
注意, vi^Tx 给出了 x 到 vi 的标量投影,长度由奇异值缩放。现在,如果我们将 ai 值代入 Ax 、的方程,我们得到 SVD 方程:
所以每个ai=σIVI*^tx都是 Ax 到 ui 上的标量投影,如果乘以 ui ,结果就是一个向量,是 Ax 到 ui 上的正交投影。奇异值 σi 沿 ui 缩放该向量的长度。记住,在特征分解方程中,每个 ui ui^T 是一个投影矩阵,它给出了 x 到 ui 的正交投影。这里σIVI****^t可以认为是一个取 x 的投影矩阵,但是将 Ax 投影到 ui 上。由于它将所有向量投影到 ui 上,所以它的秩是 1。图 17 总结了 SVD 所需的所有步骤。我们首先从所有长度为 1 的矢量中挑选一个随机的二维矢量 x1 (图 17–1)。然后我们尝试使用 SVD 方法计算 Ax1 。***
图 17
首先我们计算 A^TA 的特征值( λ1 、 λ2 )和特征向量( v1 、 v2 )。我们知道奇异值是特征值的平方根( σi = λi ),如(Figure 17–2)所示。 Av1 和 Av2 表示 Ax 的拉伸方向, u1 和 u2 是 Av1 和 Av2 的单位矢量(图 17-4)。 Ax1 在 u1 和 u2 上的正交投影为
分别(图 17-5),简单地把它们加在一起,我们得到 Ax1
如所示(Figure 17–6)。
下面这个例子展示了如何用 Python 计算矩阵的 SVD。我们想找到的奇异值分解
这是一个 2 × 3 的矩阵。所以x 是三维列向量,但是 Ax 不是三维向量, x 和 Ax 存在于不同的向量空间。首先,我们计算 A^T A 的特征值和特征向量。****
输出是:
*****lam= [90.1167 0\. 12.8833]
v= [[ 0.9415 0.3228 0.0969]
[ 0.3314 -0.9391 -0.0906]
[-0.0617 -0.1174 0.9912]]*****
如你所见,第二特征值为零。由于 A^T A 是对称矩阵,有两个非零特征值,所以它的秩是 2。图 18 从不同角度显示了 A^T 斧的两幅图。由于 A^TA 的秩是 2,所以所有向量 A^TAx 都在一个平面上。
图 18
清单 11 展示了如何构建矩阵σ和 V 。我们首先按降序排列特征值。 V 的列是对应的相同顺序的特征向量。****
然后我们过滤非零特征值,取它们的平方根,得到非零奇异值。我们知道σ应该是一个 3 × 3 矩阵。因此,我们将两个非零奇异值放在一个 2 × 2 对角矩阵中,并用零填充它,得到一个 3 × 3 矩阵。输出是:****
*****Sigma= [[9.493 0\. 0\. ]
[0\. 3.5893 0\. ]]
V= [[ 0.9415 0.0969 0.3228]
[ 0.3314 -0.0906 -0.9391]
[-0.0617 0.9912 -0.1174]]*****
为了构造 V ,我们取与 A 的 r 非零奇异值对应的 vi 向量,并除以它们对应的奇异值。既然 A 是一个 2 × 3 矩阵, U 应该是一个 2 × 2 矩阵。我们有 2 个非零奇异值,所以 A 的秩是 2, r =2。因此,我们已经有足够多的 vi 向量来组成 U 。
输出是:
*****U= [[ 0.4121 0.9111]
[ 0.9111 -0.4121]]*****
最后,我们得到一个对的分解:****
我们真的不需要遵循所有这些步骤。NumPy 有一个名为svd()
的函数可以为我们做同样的事情。清单 13 展示了我们如何使用这个函数轻松计算矩阵 A 的 SVD。
输出是:
*****U= [[-0.4121 -0.9111]
[-0.9111 0.4121]]
s= [9.493 3.5893]
V [[-0.9415 -0.0969 -0.3228]
[-0.3314 0.0906 0.9391]
[ 0.0617 -0.9912 0.1174]]*****
您应该注意到输出中的一些事情。首先,这个函数返回一个奇异值数组,它位于σ的主对角线上,而不是矩阵σ上。另外,它返回 V^T,不是 V ,所以我打印了它返回的数组 VT 的转置。最后,svd()
报告的 ui 和 vi 向量与清单 10-12 中计算的 ui 和 vi 向量符号相反。记住如果 vi 是某个特征值的特征向量,那么(-1) vi 也是同一特征值的特征向量,其长度也是相同的。所以如果 vi 归一化,(-1) vi 也归一化。事实上,在清单 10 中,我们用不同的方法计算了 vi ,而svd()
只是报告(-1) vi ,这仍然是正确的。由于 ui = Avi/ σi,svd()
上报的 ui 的集合也会有相反的符号。
你可以很容易地构造矩阵σ并检查这些矩阵相乘是否得到 A.****
*****Reconstructed A= [[ 4\. 1\. 3.]
[ 8\. 3\. -2.]]*****
在图 19 中,你可以看到一个由 x 和 Ax 组成的图,前者是单位球体中的矢量,后者是由 A 产生的一组二维矢量。矢量 u1 和 u2 表示拉伸的方向。由 Ax 生成的椭圆不像我们之前看到的那样是空心的(例如在图 6 中),变换后的矢量完全填充了它。
图 19
类似于特征分解方法,我们可以通过对具有最高奇异值的项求和来近似我们的原始矩阵 A 。因此,我们可以使用 SVD 方程中的前 k 项,使用 k 最高奇异值,这意味着我们只包括分解方程中的 U 和 V 矩阵中的前 k 向量:
我们知道集合{ u1 、 u2 、…、 ur} 构成了 Ax 的基础。所以当我们从这个集合中选取 k 向量时, Ak x 就写成了 u1,u2,… uk 的线性组合。因此它们跨越 Ak x ,并且由于它们是线性独立的,所以它们形成了 Ak x (或 col A )的基础。所以 Ak 的秩是 k ,通过挑选第一个 k 奇异值,我们用秩- k 矩阵来近似 A 。
举个例子,假设我们要计算矩阵的奇异值分解
同样, x 是单位球中的矢量(图 19 左图)。奇异值为 σ1= 11.97, σ2= 5.57, σ3= 3.25, A 的秩为 3。因此 Ax 在三维空间中是一个椭球体,如图 20(左)所示。如果我们使用第一个奇异值对其进行近似,那么 Ak 的秩将是 1,并且 Ak 乘以 x 将是一条线(图 20 右侧)。如果只使用前两个奇异值, Ak 的秩将为 2, Ak 乘以 x 将为一个平面(图 20 中)。
图 20
值得注意的是,如果我们有一个对称矩阵,SVD 方程简化为特征分解方程。假设对称矩阵 A 具有特征向量 vi 以及相应的特征值 λi 。所以我们
我们已经表明,对于对称矩阵, vi 也是 A^TA 的特征向量,对应的特征值为 λi . 所以 A 的奇异值为 λi 和 σi = λi 的平方根。现在我们可以计算 ui :
所以 ui 是 A 对应 λi (以及 σi )的特征向量。现在我们可以简化 SVD 方程,得到特征分解方程:
最后,可以看出 SVD 是用秩- k 矩阵逼近 A 的最佳方式。一个 m × n 矩阵 A 的 Frobenius 范数 定义为其元素的绝对平方和的平方根:
这就像矩阵向量长度的推广。现在如果矩阵m×nAk 是由奇异值分解逼近的秩- k 矩阵,我们可以认为
为 A 与 Ak 之间的距离。这个距离越小, Ak 越接近 A 越好。现在如果 B 是任意一个 m × n 秩- k 矩阵,可以看出
换句话说,SVD 生成的 A 与其秩- k 逼近之差具有最小的 Frobenius 范数,没有其他秩- k 矩阵能够给出对 A 更好的逼近(就 Frobenius 范数而言距离更近)。****
现在我们已经熟悉了 SVD,我们可以看到它在数据科学中的一些应用。
应用程序
降维
我们可以在矩阵中存储图像。每个图像由一组像素组成,这些像素是该图像的构建块。每个像素代表图像中特定位置的光的颜色或强度。在 PNG 格式的灰度图像中,每个像素都有一个介于 0 和 1 之间的值,其中 0 对应黑色,1 对应白色。所以一个有 m × n 个像素的灰度图像可以存储在一个 m × n 矩阵或者 NumPy 数组中。这里我们使用imread()
函数将 480 × 423 像素的爱因斯坦的灰度图像加载到一个二维数组中。然后我们用 SVD 分解矩阵,用前 30 个奇异值重构。
图 21。图像来源
原始矩阵为 480×423。所以我们需要存储 480×423=203040 个值。在 SVD 之后,每个 ui 有 480 个元素,每个 vi 有 423 个元素。为了能够使用前 30 个奇异值重建图像,我们只需要保留前 30 个σi、 ui 和 vi ,这意味着存储 30×(1+480+423)=27120 个值。这大约是原始图像所需数值的 13%。因此,使用奇异值分解,我们可以很好地逼近原始图像,并节省大量内存。清单 16,并计算对应于前 6 个奇异值的矩阵。每个矩阵σIuiVI****^t的秩为 1,行数和列数与原始矩阵相同。图 22 显示了结果。******
图 22
请注意,与原始灰度图像不同,这些秩 1 矩阵的元素的值可以大于 1 或小于 0,并且它们不应被解释为灰度图像。所以我没有使用cmap='gray'
,也没有将它们显示为灰度图像。当绘制它们时,我们不关心像素的绝对值。相反,我们关心他们相对于彼此的价值。
为了理解图像信息是如何存储在每个矩阵中的,我们可以研究一个简单得多的图像。在清单 17 中,我们读取了一个包含五个简单形状的二进制图像:一个矩形和四个圆形。结果如图 23 所示。
图 23
使用前 2、4 和 6 个奇异值重建图像。现在我们绘制对应于前 6 个奇异值的矩阵:
图 24
每个矩阵(σIuiVI****^t*)的秩为 1,这意味着它只有一个独立列,所有其他列都是该列的标量乘法。所以如果调用独立列 c1 (或者它可以是其他任何一列),这些列的一般形式为:*******
其中 ai 是标量乘法器。另外,这个矩阵把所有的向量都投影到 ui 上,所以每一列也是 ui 的标量乘法。这可以在图 25 中看到。显示了矩阵的两列σ2t39】U2v2^t与 u2 。两列具有相同的 u2 模式,但值不同(列#300 的 ai 为负值)。****
图 25
所以使用 c1 和 ai (或 u2 及其乘数)的值,每个矩阵捕捉原始图像的一些细节。在图 24 中,前两个矩阵可以捕获原始图像中左矩形的几乎所有信息。在图 24 的前两个矩阵中,这四个圆被粗略地捕捉为四个矩形,关于它们的更多细节被添加到后四个矩阵中。这也可以在图 23 中看到,当我们添加更多的奇异值时,重建图像中的圆变得更圆。这些秩为 1 的矩阵可能看起来很简单,但它们能够捕捉图像中重复模式的一些信息。例如,在图 26 中,我们有苏格兰国家纪念碑的图像,它有 6 根柱子(在图像中),对应于第一个奇异值的矩阵可以捕捉原始图像中柱子的数量。
图 26。图像来源
特征脸
在本例中,我们将使用 Scikit-learn 库中的 Olivetti faces 数据集。该数据集包含 400 幅图像。这些照片拍摄于 1992 年 4 月至 1994 年 4 月间,地点是剑桥美国电话电报公司实验室。这些图像显示了 40 个不同主体的面部。对于一些受试者来说,这些照片是在不同的时间拍摄的,改变了光线、面部表情和面部细节。这些图像是灰度图像,每幅图像的像素为 64×64。每个像素的强度是区间[0,1]上的一个数。首先,我们加载数据集:
清单 1 中已经导入了fetch_olivetti_faces()
函数。我们称之为读取数据并将图像存储在imgs
数组中。这是一个(400,64,64)数组,包含 400 个灰度 64×64 的图像。我们可以在这里展示其中的一些例子:
图 27
**在前面的例子中,我们将原始图像存储在一个矩阵中,然后使用 SVD 对其进行分解。这里我们采用另一种方法。我们知道我们有 400 张图片,所以我们给每张图片一个从 1 到 400 的标签。现在我们使用一键编码通过一个向量来表示这些标签。我们使用一个有 400 个元素的列向量。对于每个标签 k,除了第 k 个元素外,所有元素都为零。因此标签 k 将由向量表示:
现在,我们将每个图像存储在一个列向量中。每个图像有 64 × 64 = 4096 个像素。因此,我们可以展平每个图像,并将像素值放入具有 4096 个元素的列向量 f 中,如图 28 所示:
图 28
所以每张标签为 k 的图片都会被存储在矢量 fk 中,我们需要 400 个 fk 矢量来保存所有的图片。现在我们定义一个变换矩阵 M ,它将标签向量 ik 变换为其对应的图像向量 fk 。向量 fk 将是矩阵 M 的列:
这个矩阵有 4096 行和 400 列。我们可以简单的用 y=Mx 找到每个标签对应的图像( x 可以是任意向量 ik , y 会是对应的 fk )。例如,对于该数据集的第三幅图像,标签是 3,并且除了第三个元素是 1 之外, i3 的所有元素都是 0。现在,记住分块矩阵的乘法。当我们将 M 乘以 i3 时,除了第三列 f3 、之外, M 的所有列都乘以零,所以:
清单 21 展示了我们如何构建 M 并使用它来显示数据集中的某个图像。
每个标签向量 ik 的长度是 1,并且这些标签向量形成 400 维空间的标准基础。在这个空间中,每个轴对应于一个标签,其值可以是零或一。向量 fk 存在于 4096 维空间中,其中每个轴对应图像的一个像素,矩阵 M 将 ik 映射到 fk 。现在我们可以用 SVD 分解 M 。请记住,当我们将 M分解为 r 时****
集合{ u1 、 u2 、…、 ur }是 U 的第一个 r 列,将作为 Mx 的基础。每个向量 ui 将有 4096 个元素。由于 y = Mx 是我们的图像向量所在的空间,向量 ui 形成了图像向量的基础,如图 29 所示。在这幅图中,我试图想象一个 n 维向量空间。这在 n ≥3 时当然是不可能的,但这只是一个虚构的图解,帮助你理解这个方法。
图 29
所以我们可以将 ui 重塑成一个 64 ×64 的像素阵列,并尝试像绘制图像一样绘制它。这些向量的元素值可以大于 1 或小于 0,并且当对它们进行整形时,它们不应该被解释为灰度图像。所以我在显示它们的时候没有使用cmap='gray'
。
输出是:
图 30
您可以检查清单 22 中的数组s
有 400 个元素,所以我们有 400 个非零奇异值,矩阵的秩是 400。因此,我们需要 U 的前 400 个向量来完全重构矩阵。我们可以使用基本向量轻松地重建其中一幅图像:
这里,我们采用图像#160,并使用不同数量的奇异值对其进行重建:
图 31
向量 ui 被称为特征脸,可以用于人脸识别。正如您在图 30 中看到的,每个特征脸捕获了图像向量的一些信息。比如 u1 大部分是关于眼睛的,或者 u6 抓住了鼻子的一部分。当重建图 31 中的图像时,第一个奇异值添加了眼睛,但是脸部的其余部分是模糊的。通过增加 k,鼻子、眉毛、胡须和眼镜被添加到脸上。有些人认为眼睛是你面部最重要的特征。似乎 SVD 同意他们的观点,因为具有最高奇异值的第一个特征脸捕获了眼睛。
降低噪音
奇异值分解可以用来降低图像中的噪声。清单 24 显示了一个例子:
图 32
这里,我们首先加载图像,并添加一些噪声。然后,我们使用前 20、55 和 200 个奇异值来重建图像。如图 32 所示,随着重构矩阵的秩增加,噪声量也会增加。因此,如果我们使用像 20 这样的较低等级,我们可以显著降低图像中的噪声。重要的是要理解为什么它在低级别工作得更好。
这里有一个简单的例子来说明 SVD 如何降低噪声。假设我们有清单 25 中定义的 3×15 矩阵:
该矩阵的颜色图如下所示:
图 33
矩阵列可以分为两类。在前 5 列中,只有第一个元素不为零,在后 10 列中,只有第一个元素为零。我们还有一个嘈杂的列(列#12 ),它应该属于第二类,但是它的第一个和最后一个元素没有正确的值。我们可以假设这两个元素包含一些噪声。现在我们用奇异值分解这个矩阵。矩阵的秩为 3,并且只有 3 个非零奇异值。现在我们用前两个和三个奇异值来重建它。
图 34
如图 34 所示,通过使用前两个奇异值,列#12 发生变化,并遵循第二类中列的相同模式。但是,现在它的元素的实际值要低一点。如果我们使用所有 3 个奇异值,我们得到原始的噪声列。图 35 显示了这些列在三维空间中的曲线图。
图 35
**先看 SVD 生成的 ui 向量。 u1 显示第一类列向量的平均方向。类似地, u2 显示了第二类的平均方向。当然方向相反,但这不重要(记住如果 vi 是某个特征值的特征向量,那么(-1) vi 也是同一特征值的特征向量,并且由于ui=Avi/σI,那么它的符号取决于 vi ) 。重要的是拉伸方向,而不是矢量的符号。
噪声列由矢量 n 表示。不沿着 u1 和 u2 走。现在如果我们以 ui 为基础,就可以分解 n ,找到它在 ui 上的正交投影。如你所见,它有一个沿 u3 (反方向)的分量,这是噪声方向。这个方向代表出现在 n 的第三个元素中的噪声。它具有最低的奇异值,这意味着 SVD 不认为它是一个重要的特征。当我们使用前两个奇异值重构 n 时,我们忽略这个方向,第三个元素中存在的噪声被消除。现在我们只有沿着 u1 和 u2 的矢量投影。但是沿着 u1 的标量投影具有高得多的值。这是因为矢量 n 更类似于第一类。
所以 n 在 u1-u2 平面的投影几乎是沿着 u1 的,利用前两个奇异值重构 n 给出了一个更类似于第一类的向量。重要的是要注意,由 u2 表示的第一元件中的噪声没有被消除。此外,尽管重构的 n 的方向几乎是正确的,但是与第一类中的向量相比,其幅度较小。事实上,在重构的矢量中,第二个元素(不包含噪声)现在具有比原始矢量更低的值(图 36)。
图 36
因此,SVD 将大部分噪声(但不是全部)分配给由较低奇异值表示的向量。如果我们重构一个低秩矩阵(忽略较低的奇异值),噪声将会减少,然而,矩阵的正确部分也会改变。结果是一个矩阵,它只是我们正在寻找的无噪声矩阵的近似。这可以在图 32 中看到。图像背景是白色的,噪声像素是黑色的。当我们重建低秩图像时,背景更加均匀,但现在是灰色的。事实上,如果图像中没有噪声,我们得到的是白色背景的一个噪声较少的近似。
我希望你喜欢阅读这篇文章。如果您有任何问题或建议,请告诉我。本文中的所有代码清单都可以从 GitHub 下载,网址是:https://github.com/reza-bagheri/SVD_article
延伸阅读:
特征分解和 SVD 也可以用于主成分分析(PCA)。PCA 对于降维非常有用。要了解更多关于 PCA 中特征分解和 SVD 的应用,您可以阅读以下文章: