TowardsDataScience-博客中文翻译-2020-九十九-

龙哥盟 / 2024-10-15 / 原文

TowardsDataScience 博客中文翻译 2020(九十九)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

推荐系统——高级矩阵分解

原文:https://towardsdatascience.com/recommender-system-advanced-matrix-factorization-2d484bf11c0b?source=collection_archive---------36-----------------------

隐式数据集的高级矩阵分解遍历推荐系统

照片由freepik.com拍摄

隐式数据集提供用户的行为数据,如购买历史、观看习惯和浏览活动。与来自用户评级数据的显式反馈不同,隐式数据集缺乏对他们偏好的直接指示。因此,很难知道客户不喜欢哪些产品。我们下面工作的模型生成隐式反馈数据集的独特属性。信心水平因积极和消极偏好而异。

在本文中,您将学习推荐系统的高级矩阵分解算法:

(1)邻域模型介绍

(2)潜在因素模型介绍

(3)隐式反馈模型介绍

(python 代码在矩阵分解方面的实践经验

邻域模型简介

邻域模型是协同过滤算法中的一种常用方法。这样的方法是基于历史数据集推荐具有相同兴趣的用户。更好的可伸缩性和改进的准确性使得面向项目的方法在许多情况下更受欢迎。在这些方法中,使用同一用户对类似项目做出的已知评级来估计评级。更好的可伸缩性和改进的准确性使得面向项目的方法在许多情况下更受欢迎。面向项目的方法对用户更有利,因为他们熟悉他们以前偏好的项目,并且推荐的项目基于相同兴趣的用户。

相似性度量被应用于邻域模型,其中 s_ij 表示 I 和 j 的相似性,并且通过皮尔逊相关系数来计算。目标是预测 r _ ui——用户 u 对项目 i. S^k(i 的未观察值;u)由一组 k 个邻居表示,并且 r_ui 的预测值被取为相邻项目的评级的加权平均值。

相似性度量

潜在因素模型介绍

潜在因素模型是一种替代的协作过滤方法,用于揭示解释观察到的评级的潜在特征。奇异值分解(SVD)是潜在因素模型的主要算法。SVD 模型成为一种流行的用户项目观察方法。

SVD 模型由用户因素向量 X_u 和项目因素向量 Y_i 组成。预测由内积 r^ui = X^T_u*Y_i.生成。λ是用于正则化的参数。

正则化奇异值分解模型

隐式反馈模型简介

将信心的概念形式化

  1. 偏好变量:是一个二元变量,表示用户 u 对项目 I 的偏好,当 P_ui =1 时,用户 u 消费了项目 i (R_ui > 0),u 喜欢项目 I,而用户 u 从未消费过项目 I,P_ui =0 时,对项目 I 没有偏好。一般来说,随着 R_ui 的增长,强烈表明用户确实喜欢该物品。
P_ui = { 1, R_ui > 0 ; 0, R_ui = 0}

2。置信变量: C_ui 是通过观察 P_ui 得到的置信测度。对于每个用户-项目对,它在 P_ui 中以某种最小置信度设置。置信测度通过常数α随着积极偏好而增加。

C_ui = 1 + α*R_ui

价值函数

λ项用于正则化模型,以防止对训练数据过度拟合。成本函数中有 m 项和 n 项,其中 m 是用户数,n 是项目数。

价值函数

交替最小二乘法用于在计算用户因素和项目因素时降低成本函数值。这种方法用于显式数据集,并将所有未知值视为缺失值,从而产生稀疏目标函数。提取 P_ui 的另一种方法是从 R_ui 中为 P_ui 的相应非零值设置最小阈值。同样,置信度 C_ui 可以从 R_ui 转换而来。

C_ui = 1 + α log(1 + rui/ε)

对于隐式反馈的独特特征,有两个主要的特性需要解决。

  1. 将参数(R_ui)转换成两个不同的观察值:偏好参数(P_ui)和置信水平(C_ui)
  2. 用户-项目组合(n-m)可以通过代数算法在线性运行时间内执行。

python 代码在矩阵分解方面的实践经验

数据描述:

该数据集包含来自 Last.fm 在线音乐系统的一组 2K 用户的社交网络、标签和音乐艺术家收听信息。总共有 1892 和 17632 位艺术家。有 12717 个双向用户朋友关系,有 25434 (user_i,user_j)对。从用户收听艺术家的历史数据来看,有 92834 个用户收听艺术家关系和平均 5.265 个用户收听每个艺术家。

数据输入:

数据由每一列的制表符分隔,并具有' userID '、 artistID '和' weight '列。我们总共得到了 278502 位艺术家的作品。在我们删除重复的记录后(如果有人听了同样的歌曲两次),数据中有 1892 个用户和 17632 个艺术家。

用户 _ 项目 _ 首选项&用户 _ 项目 _ 交往矩阵

培训、测试和评估矩阵

用于从训练矩阵中屏蔽偏好数据的函数。训练矩阵由用户收听的艺术家创建,并将其掩蔽到训练矩阵。测试矩阵是基于用户的历史数据集创建的。

张量流模型训练

在模型创建之前,偏好矩阵由占位符函数生成,该占位符函数用于构建计算图,而不需要数据。此外,预测偏好矩阵是通过取内积 r \u I = x^t_u*y_i.来完成的。稍后,我们取实际和预测偏好矩阵的平方误差,乘以置信矩阵,并将λ的乘积值与损失函数相加。这是我们从上述方法中最小化成本函数的地方。成本函数如下所述。 Top_k_precision 是通过推荐的艺术家和用户喜欢的艺术家的交集来帮助计算前 k 项平均预测精度的函数。

推荐系统型号
1。获得建议的预测矩阵
2。从用户的历史数据集中锁定最受推荐的艺术家
3。从用户历史数据和推荐艺术家中映射艺术家
4。从上面 K 位顶级艺术家的映射方法中获得交集的结果

价值函数

未来的工作

  1. 偏好和交互矩阵相对稀疏,因为不是每个用户都听数据中的所有艺术家。为了克服这个问题,可以通过人口统计学将用户分类为不同的组。因此,矩阵会更密集
  2. 模型的超参数会影响预测结果。增加 lambda 以增加更多的正则化或增加学习率可以惩罚过拟合模型。

总之:

  1. 偏好变量指示用户确实喜欢该项目。置信度变量在 P_ui 中设置有一些最小置信度。隐式数据集的成本函数是提取 P_ui,是从 R_ui 为 P_ui 的相应非零值设置最小阈值。
  2. Tensorflow 推荐系统模型训练推荐的预测矩阵,并将其屏蔽回用户的偏好和交互数据。每次运行历元后,都会优化精度值。

参考:

  1. http://yifanhu.net/PUB/cf.pdf2009 年 2 月 10 日,胡一帆、耶胡达·科伦和克里斯·沃林斯基“隐式反馈数据集的协同过滤”

2.隐式反馈数据集协同过滤
https://github . com/azg 0404/隐式反馈数据集协同过滤

推荐系统——基于隐式反馈的贝叶斯个性化排序

原文:https://towardsdatascience.com/recommender-system-bayesian-personalized-ranking-from-implicit-feedback-78684bfcddf6?source=collection_archive---------17-----------------------

贝叶斯个性化排序&自适应 K-最近邻的漫游推荐系统

杰夫·谢尔登在 Unsplash 上的照片

更普遍的是看到公司使用推荐系统算法,根据用户以前的购物体验来生产用户喜欢的商品。在线顾客在网上购物时会从易贝、亚马逊、沃尔玛等商店获得推荐商品。这篇文章的重点是项目推荐。项目推荐系统方法为从用户过去的数据集(例如购买历史、观看历史等)中学习的一组项目提供用户特定的排名。如今,推荐系统变化很大,从像评级这样的显式数据集的输入到像监控点击、观看时间、购买等这样的隐式数据集的输入。这些信息比较容易收集,但是很难推荐用户喜欢的项目。

在本文中,你将学习推荐系统的奇异值分解和截断奇异值分解:

(1)个性化排名系统

(2)问题陈述

(3)贝叶斯个性化排序

(4)流程再造优化标准

(5) BPR 学习算法

(6)矩阵分解

(7)自适应 K 近邻

个性化排名系统

个性化排序向顾客提供排序的项目列表的项目推荐。这篇文章将着重于根据用户从过去的购买数据中得出的隐含行为,向客户推荐个性化的商品排序列表。从购买数据中观察,可以获得积极的观察结果,如用户的购买历史,而未观察到的用户-项目对数据很难用于模型输入,如未购买的项目、不感兴趣的项目或对其未来购买感兴趣的项目。

问题陈述

对于隐式反馈系统,它能够检测像购买历史这样的正数据集。对于剩余的数据,它是实际负值和缺失值的混合。然而,机器学习模型无法学习缺失的数据。通常,项目推荐器基于用户对项目的偏好输出个性化得分 X_ui,并且项目从预测得分中排序。项目推荐器的机器学习模型提供训练数据,其中给定对(U,i) ∈ S 作为正类标签,并且(pairs 中的所有其他组合为负类标签。

该模型适合于预测值为 1 和 0 的正类,而对于其余的正类。当模型无法对项目((U × I) \ S)进行排序时,会出现问题,这些项目在训练期间作为负面反馈给出。一种替代方法是将正则化添加到模型中,以防止过度拟合。另一种方法是创建项目对作为训练数据,并优化以正确排列项目对,而不是对单个项目评分,同时忽略缺失值。从下面的照片来看,模型很难只从观察到的数据中学习。因此,所有的负数据都被替换为 0。

Photo0:观察到的 0 值和未观察到的 1 值。

贝叶斯个性化排名(BPR)

为了克服个性化排序任务,贝叶斯个性化排序结合了使用 p(I > u j |θ)的似然函数和模型参数 p(θ)的先验概率的问题的贝叶斯分析。

在这一节中,我们推导出一种解决个性化排序任务的通用方法。它包括个性化排序的通用优化标准 BPR-Opt,该标准将通过使用 p(I > u j |θ)的似然函数和模型参数 p(θ)的先验概率对问题进行贝叶斯分析而得到

BPR 优化标准

贝叶斯方法是对所有项目 i ∈ I 进行排序,以最大化以下后验概率,其中θ表示任意模型类别的参数向量

p(θ| > u)∞p(> u |θ)p(θ)

所有用户因素都是相互独立的,并且对于特定用户,每对项目(I,j)的排序是唯一的。

因此,上述用户特定的似然函数可以用下面的公式再现。

用户的可能性函数

我们将用户确实更喜欢项目 I 而不是项目 j 的个体概率定义为:

用户偏好项目 I 而非项目 j 的概率

对于个性化排序任务的贝叶斯建模方法,引入了广义先验密度 p(θ),它是均值为零且方差-协方差矩阵为σθ的正态分布。

p(θ)∞N(0,σθ)

通过设置σθ=λθI,我们减少了未知超参数的数量。设置最大后验估计量来导出个性化排序 BPR-Opt 的优化准则。

BPR-Opt 数学公式

BPR 学习算法

从上一节可以看出,该标准来自个性化排序,标准梯度下降不适于处理该问题。然后,引入 LearnBPR 作为随机梯度下降算法来优化模型性能。

BPR-Opt 相对于模型参数的梯度为:

梯度 BPR-Opt 数学公式

优化模型中的参数被指定为学习率α和正则化λθ。该模型是一个基于自举的随机梯度下降模型。

Photo2:基于自举的随机梯度下降算法

我们将介绍一种流行的随机梯度下降法。根据下面的等式,对每个三元组(u,I,j) ∈ D_s 执行更新。

随机梯度下降数学公式

训练对上的方法顺序至关重要。当相同的用户-项目对会有许多更新时,遍历数据项或用户-项目会导致较差的收敛性。引入随机梯度下降算法来随机选择三元组(均匀分布)。这种方法可以减少在连续更新步骤中选择相同用户项目组合的机会。带替换的 Bootstrap 抽样方法能够停止用户-项目对的随机选择。在我们的评估中,单个步骤的数量是根据观察到的正反馈数量线性选择的。

BPR 学习模型

矩阵分解和学习的 k-最近邻这两种不同的模型类别将对用户对某个项目的隐藏偏好进行建模。首先,我们分解估计量 x_uij,并将其定义为:

xuij:= xui xuj

接下来,应用标准的协同过滤模型来预测ˇx _ ul。这种方法比原来的方法更好,因为它对两个预测值 x _ ui x _ uj 的差异进行分类,而不是将单个预测值 x_ul 回归为单个数字。

矩阵分解

矩阵 X : U × I 的估计用于处理预测ˇX _ ui 的问题。目标矩阵由矩阵分解得到的两个低秩矩阵 W : |U| × k 和 H : |I| × k 的矩阵乘积生成。

xˇ:= w * h^t

根据下面的等式,有指定的参数。

k:近似的维数/秩
W _ u:W 中的特征向量,指示用户 u,类似地,H 的每一行 hi 描述一个项目 I

预测公式

θ=(W,H):矩阵分解的模型参数。这些参数是潜在变量,用于模拟未观察到的用户和项目对。实现奇异值分解(SVD)以最小平方逼近 Xˇ到 X。通常,SVD 方法会过度拟合数据。然后,还有其他推荐的方法,如正则化最小二乘优化,非负因式分解,最大间隔因式分解。

对于排名任务,我们使用 LearnBPR 来估计用户是否更喜欢某个项目。通过 LearnBPR 方法,我们需要知道ˇx _ uij 相对于每个模型参数θ的梯度。下面,它显示了矩阵分解模型的导数。

对于排序任务,即评估用户是否喜欢某个项目,更好的方法是根据 BPR-Opt 标准进行优化。这可以通过使用我们提出的算法 LearnBPR 来实现。如前所述,使用 LearnBPR 进行优化时,只需知道相对于每个模型参数θ的梯度ˇx _ uij。对于矩阵分解模型,导数为:

矩阵分解模型的导数

此外,还增加了三个正则项。

λW:用户特征 W
λH+:项目特征 H 的 hif 上的正更新
λH——项目特征 H 的 hjf 上的负更新

自适应 K 近邻

在协同过滤中还有另一种流行的方法,叫做 K-最近邻法,来自于项目(基于项目)或用户(基于用户)之间的相似性度量。对于 K-最近邻,我们基于 I 与用户在过去的历史数据中见过的所有其他项目的过去相似性,即 I + u,从用户 u 生成推荐项目 I 的预测。K-最近邻是从 I + u 的 K 个最相似的项目中产生的。c 是对称的项目相关性/项目相似性矩阵。

K 近邻项目预测

kNN 中的模型参数是θ= C。C 通过应用启发式相似性度量来确定,例如余弦向量相似性:I。

K 近邻的余弦向量相似性

当模型学习时,相似性度量 C 将被更新。可以直接应用参数 C。另一方面,当参数 C 过大时,模型从 H : I × k 的因式分解 HHt 产生 C,后来,我们选择适应没有因式分解的 C。为了优化用于排名的 KNN 模型,使用 LearnBPR 算法来更新相对于模型参数 c 的-x _ uij 的梯度

KNN 梯度学习算法数学公式

有两个正则化常数,用于 cil 更新的λ+和用于 cjl 更新的λ。:

python 代码的实践经验

数据描述:

有从 grouplens 网站提取的收视率、用户和电影数据集。这些文件包含来自 6000 名 MovieLens 用户的大约 4000 部电影的大约 100 万个匿名评级。分级数据包括用户 ID、电影 ID 和分级。用户文件包含用户的人口统计信息,如性别、年龄、职业和邮政编码。电影数据集包含电影 ID、标题和类型等基本信息。

基于隐式反馈的贝叶斯个性化排序

对于建模方法,在 Pytorch 模型中实现了个性化排序系统,即来自贝叶斯分析的最大后验估计器。此外,模型的优化是通过一个基于随机梯度下降和 bootstrap 采样的通用学习算法来完成的。

数据预处理

从用户和评级数据集中,我们用唯一用户给出的电影评级创建唯一的 userid 映射。此外,评级数据集中的唯一项目映射。创建 train_user_matrix 和 test_user_matrix 时有两种方法。一个是随机选择的用户,另一个是考虑时间顺序因素。通过训练和测试集列表,我们可以为矩阵输入创建用户和项目对。

对于模型输入数据,我们使用 Pytorch 库中的 DataLoader 对象。DataLoader 从数据集和采样器的组合中遍历数据集。数据加载器通过参数batch_size.批量创建数据。该参数决定每批加载多少个样本。DataLoader 类中还有另一个num_worker参数,它指定了多少个子进程用于数据加载。

系统模型化

首先,我们创建具有用户索引的用户矩阵(u ),具有用户偏好的所有项目的项目索引(I ),以及用户不偏好的项目索引(j)。然后用 u 和 I 相乘生成矩阵 x_ui,用每行求和。并且,矩阵 x_uj 是用 u 和 j 的乘积生成的,并且对每一行求和。矩阵 x_uij:矩阵 x_ui —矩阵 x_uj。概率由矩阵 x_uij 的 sigmoid 函数呈现,并对值求和。正则化增加了权重衰减参数乘以用户和项目矩阵的归一化,并对平方函数求和。数学公式如下。

稍后,预测输出推荐项目的最高概率,并存储在列表中。

数据加载器和丢失的功能

我们生成一个批量为 4096 的 DataLoader 类,并分配 16 个工作线程。由于数据集非常大,我们分配了 16 个子流程来并行处理数据。Adam optimizer 的学习率设置为 0.0001。反向传播有随机梯度下降来优化模型。对于每个批次,我们记录损失、精确率和召回率。

结果

模型输入有两种不同的数据集。一个是带有 userid 和 itemid 的随机数据,另一个是时序数据集。

精度产生如下。左手边是随机数据。从左边的图来看,1 个项目的推荐比 5 个和 10 个电影的推荐产生更好的结果。在右图中,时间顺序输入数据集的结果比随机数据稍差,因为模型很难将时间顺序因素捕捉到模型中。

未来工作:

  • 处理稀疏矩阵。从数据预处理方法上,过滤电影,而不是从用户喜欢的类别。
  • 添加更多的用户矩阵特征,如用户的朋友关系、会员资格、点击率等。
  • 将时间因素纳入模型结构

最后

  • 贝叶斯个性化排序使用 p(I > u j |θ)的似然函数和模型参数 p(θ)的先验概率。贝叶斯方法是对所有项目 i ∈ I 进行排序,以最大化以下后验概率
  • 对于排名任务,我们使用 LearnBPR 从矩阵分解中估计用户是否更喜欢某个项目。通过计算ˇx _ uij 相对于每个模型参数θ的梯度来实现模型的优化。
  • 从项目(基于项目)或用户(基于用户)之间的相似性度量导出的 k-最近邻方法,基于 I 与用户在过去的历史数据中看过的所有其他项目的过去相似性,生成来自用户 u 的推荐项目 I 的预测。

参考

  • BPR:来自隐性反馈的贝叶斯个性化排名
    https://arxiv.org/pdf/1205.2618.pdf

推荐系统——奇异值分解和截断奇异值分解

原文:https://towardsdatascience.com/recommender-system-singular-value-decomposition-svd-truncated-svd-97096338f361?source=collection_archive---------3-----------------------

照片由Unsplash.com拍摄

推荐系统最常用的方法通常是协同过滤(CF ),它依赖于过去的用户和项目数据集。CF 的两种流行方法是潜在因素模型,它从用户和项目矩阵中提取特征,以及邻居模型,它发现产品或用户之间的相似性。

邻居模型是一种面向项目的方法,基于用户对相似项目给出的评级来发现用户偏好。另一方面,诸如奇异值分解(SVD)的潜在因素模型从用户-项目矩阵中提取特征和相关性。例如,当项目是不同类别的电影时。当审视动作与喜剧、好莱坞与宝莱坞或漫威与迪士尼等维度空间时,奇异值分解会产生一些因素。主要地,我们将集中于奇异值分解(SVD)方法的潜在因子模型。

在本文中,您将学习推荐系统的奇异值分解和截断奇异值分解:

(1)奇异值分解介绍

(2)截断奇异值分解简介

(python 代码对矩阵分解的实践经验

奇异值分解简介

谈到降维,奇异值分解(SVD)是机器学习中矩阵分解的线性代数中的一种流行方法。这样的方法将空间维度从 N 维收缩到 K 维(其中 K

Matrix U: singular matrix of (userlatent factors)
矩阵 S:对角矩阵(显示每个潜在因素的强度)
矩阵 U:奇异矩阵(项
潜在因素)

通过矩阵分解,潜在因素显示了项目的特征。最后,产生形状为 m*n 的效用矩阵 A。矩阵 A 的最终输出通过提取潜在因素来降维。从矩阵 A 中,它通过将用户和项目映射到 r 维潜在空间来显示用户和项目之间的关系。向量 X_i 被认为是每个项目,向量 Y_u 被认为是每个用户。用户对项目给出的评级为 R_ui = X^T_i * Y_u。损失可以通过 R_ui 和预期评级的乘积之间的平方误差差来最小化。

正则化用于避免过度拟合,并通过添加惩罚来概化数据集。

这里,我们添加了一个偏差项,以减少实际值与模型预测值之间的误差。

(u,i): 用户-项目对
μ: 所有项目的平均评分
bi: 项目平均评分 i 减去 μ
bu:
用户给出的平均评分 u 减去 μ

下面的等式增加了偏差项和正则项:

截断奇异值分解简介

说到矩阵分解技术,截断的奇异值分解 ( SVD )是一种产生将矩阵 M 分解为三个矩阵 U、σ和 v 的特征的常用方法。另一种常用方法是主成分分析(PCA)。截断的 SVD 与 PCA 具有相似性,而 SVD 是从数据矩阵中产生的,PCA 的因式分解是从协方差矩阵中产生的。与常规 SVD 不同,截断 SVD 产生一种因子分解,其中可以为许多截断指定列数。例如,给定一个 n×n 矩阵,截断 SVD 生成指定列数的矩阵,而 SVD 输出 n 列矩阵。

截断奇异值分解相对于主成分分析的优势

截断 SVD 可以处理稀疏矩阵以生成特征矩阵,而 PCA 将对整个矩阵进行操作以输出协方差矩阵。

python 代码的实践经验

数据描述:

元数据包括完整 MovieLens 数据集中列出的 45,000 部电影,电影在 2017 年 7 月之前上映。演员、工作人员、情节关键词、预算、收入、海报、上映日期、语言、制作公司、国家、TMDB 投票数和平均投票数都在数据集中。评级范围为 1-5,从 GroupLens 官方网站获取。该数据集是从 Kaggle 数据集中引用的。

使用 SVD 推荐电影

奇异值分解是一种用于电影推荐的协同过滤方法。代码实现的目的是从项目-用户矩阵的潜在特征中为用户提供电影推荐。该代码将向您展示如何使用 SVD 潜在因子模型进行矩阵分解。

数据预处理

随机采样分级数据集并生成带有流派的电影特征。然后,labelencode 用各自唯一的 id 对所有电影和用户进行编码。

num of users: 1105
num of movies: 3000

模型性能

通过每个历元的运行,rmse 降低,最终输出达到 rmse 0.57。批量大小的数量会影响每次运行时输入到模型中的输入数据的数量。批量大小、学习速率和正则项是可调的,以优化模型性能。

RMSE 2.1727233
RMSE 2.101482
RMSE 2.0310202
RMSE 1.9610059
RMSE 1.8911659
RMSE 1.8213558
RMSE 1.7515925
RMSE 1.681992
RMSE 1.612707
RMSE 1.543902
RMSE 1.4757496
RMSE 1.408429
RMSE 1.3421307
RMSE 1.277059
RMSE 1.2134355
RMSE 1.1514966
RMSE 1.0914934
RMSE 1.0336862
RMSE 0.9783424
RMSE 0.9257237
RMSE 0.87606686
RMSE 0.82956517
RMSE 0.7863303
RMSE 0.7463626
RMSE 0.7095342
RMSE 0.67563176
RMSE 0.6445249
RMSE 0.6163493
RMSE 0.5914116
RMSE 0.5701855

使用截断奇异值分解推荐电影

通过截断 SVD 生成的用户 x 电影矩阵的前 10 个分量。在重构的矩阵中存在潜在的特征,这些特征示出了与用于评级预测的用户评级的相关性。

由于“流派”列位于字典格式的列表中,因此该列经过预处理,并提取出由|格式分隔的几个流派名称。

对用户和电影矩阵执行截断奇异值分解

从数据集中随机抽取 3000 个用户评级样本,创建索引为 Userid 的数据透视表和带有评级值的 MovieID 列。然后,由用户矩阵生成具有 2921×1739 个用户的用户矩阵。

从数据集中随机抽取 3000 个电影样本,创建数据透视表,索引为 MovieID ,列为 Userid ,评级值为。然后,由电影矩阵生成具有 3000×1105 个用户的电影矩阵。

从用户和评级矩阵来看,80%的数据用于训练数据,其余 20%用于测试数据。对于训练数据,重构矩阵由截断 SVD 的 10 个分量产生。矩阵的行*列长度为 movie_features.shape = (2400,10)和 user_features.shape = (2336,10)。

TSNE 可视化

TSNE 将数据的高维空间转换成数据的低维空间,并将其可视化。困惑是一种可调整的特征,用于平衡局部和全局数据,并建议每个点的近邻数量。

以电影特征的 5 和 2 的组成部分的困惑和情节被生产并且显示电影的群集。通过 TSNE 方法产生的潜在特征对相关的电影进行聚类。

相关电影的 TSNE 情节

准备训练和目标数据

目标数据的标签是平均用户评级,并四舍五入到小数点后 1 位。电影共 501 部,用户评分 1108。火车的大小和目标数据是 data.shape = (3000,1105)和 targets.shape = (3000,)。

在潜在特征上训练梯度增强回归器

用 0.1 的学习率和 200 个估计量训练梯度增强回归器模型。通过均方误差计算损失函数。

最后的预测是由用户产生的所有评级对每部电影的平均评级。最终的 MSE 在 0.51 左右,对于平均评级模型来说是相当优化的。

 Iter       Train Loss   Remaining Time 
         1           0.3735            5.43s
         2           0.3710            5.12s
         3           0.3689            4.89s
         4           0.3672            4.76s
         5           0.3656            4.67s
         6           0.3641            4.64s
         7           0.3628            4.59s
         8           0.3614            4.54s
         9           0.3601            4.52s
        10           0.3589            4.51s
        20           0.3480            4.14s
        30           0.3391            3.83s
        40           0.3316            3.59s
        50           0.3245            3.35s
        60           0.3174            3.14s
        70           0.3118            2.91s
        80           0.3063            2.68s
        90           0.3013            2.45s
       100           0.2968            2.22s
       200           0.2620            0.00sFinal MSE:0.5118555681581297

总之:

  1. 奇异值分解分解三个矩阵,潜在因子表示项目的特征。它通过提取潜在因素来降低维度。通过增加正则化和偏置项,它通过最小化 rmse 误差来优化模型性能。
  2. 截断 SVD 生成指定列数的矩阵,而 SVD 输出 n 列矩阵。它减少了输出的数量,并能更好地处理稀疏矩阵的特征输出。

参考

  1. 利用截断 SVD 降维
    https://subscription . packtpub . com/book/big _ data _ and _ business _ intelligence/9781783989485/1/ch 01 LV 1 sec 21/using-truncated-SVD-to-reduce-dimension
  2. 使用截短的 SVD
    推荐电影 https://github . com/saurabhmathur 96/movie-recommendations/blob/master/notebooks/推荐% 20movies %使用% 20 截短的%20SVD.ipynb

3.奇异值分解及其在推荐系统中的应用 https://analyticsindiamag . com/singular-Value-Decomposition-SVD-Application-Recommender-System/#:~:text = In % 20 the % 20 context % 20 of % 20 the,给定%20to%20items%20by%20users。

4.使用 SVD 矩阵分解推荐电影
https://github . com/saurabhmathur 96/movie-recommendations/blob/master/notebooks/推荐% 20movies %使用% 20 SVD % 20 Matrix % 20 factorization . ipynb

推荐系统解释

原文:https://towardsdatascience.com/recommender-systems-explained-88807e90e144?source=collection_archive---------38-----------------------

哈尔·盖特伍德在 Unsplash 上拍摄的照片

推荐系统如何工作的简单英语指南

我花了很多时间写各种数据科学算法和概念如何在基础层面上工作。但是我们的许多利益相关者不希望或不需要这种程度的细节。所以今天我试图做相反的事情——在一个高层次上清楚地(简明地)解释 推荐系统 ,一个流行的机器学习应用程序,如何做它们所做的事情

匹配用户和商品

在超高层次上,推荐系统试图将用户(也称为潜在客户)与他们可能喜欢的商品或服务匹配起来。很明显,我们希望这种推荐能带来购买。

那么这是怎么做到的呢?如果你曾经在谷歌上搜索过推荐系统,你可能会看到像基于内容协同过滤这样的术语。这是创建推荐的两种主要方法。但是我们先不要去那里。相反,假设我们正在运营一个电子商务网站。我们如何决定(使用数据)向第一次访问我们网站的名为 Jeremy 的特定用户推荐什么商品?

这取决于我们对杰里米了解多少。下图从 30,000 英尺的高度展示了推荐系统正在做的事情。

推荐系统

推荐器是一种算法,它考虑了杰里米的口味,用话题负载的向量来表示(例如,红点可能代表视频游戏、绿色自然和蓝色食物)。它还考虑了所有可用产品的概况,每个产品都被表示为与用于量化 Jeremy 口味的主题相同的主题的负载向量(因此它是一个数组)。

以口味向量和产品档案数组作为输入,推荐器的工作是将 Jeremy 与它预测他最喜欢的产品匹配起来。所以从某种意义上来说,这是一个分类问题,我们试图预测某人是否会喜欢某个给定的产品并购买它。

计算产品配置文件

产品简介

我们如何了解我们每个产品的概况?产品简介应该代表产品的关键潜在特征,尤其是用户关心的特征。

一个非常简单的产品简介就是类别。例如,对于书籍,简介可以是历史、幻想、科幻、非虚构、传记、浪漫、幽默等。从数量上来说,书就像这样:

**Lord of the Rings**
History:    0  *
Fantasy:    1  ----------*
Sci Fi:     0  *
Nonfiction: 0  *
Biography:  0  *
Romance:    0  *
Humor:      0  ***Twilight**
History:    0  *
Fantasy:    0  *
Sci Fi:     0  *
Nonfiction: 0  *
Biography:  0  *
Romance:    1  ----------*
Humor:      0  *

我们会努力找出我们的客户喜欢阅读的类别(流派)。我们可以通过以下几种方式来实现:

  • 直接问他们最喜欢的流派是什么。
  • 索要一份他们最喜欢的书的清单,并从清单中推断出他们喜欢的类型。

假设我们采用方法 2——杰里米给了我们 7 本奇幻书和 3 本浪漫书的清单。那么杰里米最喜欢的类型一定是幻想,对不对?所以我们可以把他送到幻想区然后就完事了?没那么快!他还告诉我们他非常喜欢的 3 本言情书。这也是有用的信息。杰里米看书时似乎更喜欢幻想和浪漫的结合。

我们能否创建更细致的产品简介,而不是全有或全无类别,更符合杰里米的口味?如果你读过《哈利·波特》系列,你会知道这些书是关于魔法和与伏地魔战斗的,因为它们是一个成长的故事。知道了这一点,哈利·波特更好的形象可能是:

**Harry Potter**
History:    0   *
Fantasy:    0.7 -------*
Sci Fi:     0   *
Nonfiction: 0   *
Biography:  0   *
Romance:    0.3 ---*
Humor:      0   *

因此,如果我们希望能够提供更加细致入微的推荐,一个产品的简介不仅应该基于它的一般类别,还应该基于它的内容。观察差异:

  • 当我们纯粹按类别来分类时,哈利波特会被认为是奇幻类的,因为它的奇幻内容得分最高(而且超过了它的浪漫内容)。
  • 但是,当我们允许书籍是类别(或主题)的组合时,我们可以将《哈利·波特》描述为 70%的奇幻和 30%的浪漫(基于其内容文本),这将是向杰里米推荐的最佳书籍。

在我们的例子中,我们将流行书籍类别作为我们的主题。但实际上,想出这些题目的方法有很多。唯一重要的是这些主题可以映射到用户的品味和偏好。如果你想知道我说的主题是什么意思,它们是我们用来描述产品的个人特征或品质。有了它们,我们可以将每个产品建模为主题组合。并且这些话题负载向量成为每个产品(产品简介)的量化表示,推荐系统可以理解并利用它来进行推荐

我们想出主题的一种方式是通过 NLP(自然语言处理)。我们可以对库存中所有书籍的组合文本运行 NLP,或者至少对它们的描述或概要运行 NLP。这种 NLP 分析的输出将是语料库(我们的图书目录)中所有图书覆盖的潜在主题以及每本书的主题负载。关于 NLP 的更多信息,你可以在这里阅读我的帖子。

如果我们想要的不仅仅是主题,我们可以对 NLP 分析的结果进行聚类分析(这给了我们主题)。这将告诉我们网站上的书籍通常属于什么主题组合。例如,我们可能会发现我们的网站主要销售以下 3 种类型的书籍:

***Values below are for the centers of each cluster*****Cluster 1 (Fantasy with a Dash of Romance)**
History:    0   *
Fantasy:    0.7 -------*
Sci Fi:     0   *
Nonfiction: 0   *
Biography:  0   *
Romance:    0.3 ---*
Humor:      0   ***Cluster 2 (Romance with a Dash of Vampires)**
History:    0   *
Fantasy:    0.1 -*
Sci Fi:     0   *
Nonfiction: 0   *
Biography:  0   *
Romance:    0.9 ---------*
Humor:      0   ***Cluster 3 (Funny Biographies)**
History:    0   *
Fantasy:    0   *
Sci Fi:     0   *
Nonfiction: 0   *
Biography:  0.5 -----*
Romance:    0   *
Humor:      0.5 -----*

看到这一点,我们可能会得出结论,我们需要增加我们的图书品种。而且,我们知道要把我们的营销努力集中在那些可能对我们的 3 个利基集群中的至少一个感兴趣的用户身上。但是我们怎么知道谁感兴趣呢?

推断用户的品味和偏好

用户口味向量

如果杰里米之前没有明确告诉我们他最喜欢的 10 本书,我们怎么能推断出他的品味呢?这取决于我们对他了解多少。一般来说,我们有 4 种可能的情况:

  1. 他通过调查或问卷直接告诉我们他喜欢什么(我们设计调查或问卷是为了找出用户喜好的话题负载)。在这种情况下,这很容易,我们只需将调查结果映射到一个主题负载向量或一个特定的集群中(为简单起见,假设我们使用主题负载作为推荐器)。让我们称这个向量为前进的口味向量。
  2. 如果我们知道他的购书历史,那么我们可以查看他购买的所有或部分书籍的主题负载,以计算他的口味向量——这也很容易。如果 Jeremy 有足够多的过去买书的样本,那么这个购买时间序列本身就可以作为一个替代的口味向量。
  3. 我们不知道他的购买历史(他对我们的网站来说是全新的),但我们知道他的一些数据点,如姓名、年龄、工作、教育水平等。然后,我们可以根据我们对 Jeremy 的了解,查看与他相似的其他访问者的购买历史。根据类似用户的购买历史,我们可以猜测一个口味向量,并使用它来进行一些初步的推荐。然后,当他接受或拒绝我们的建议时(并希望进行一些购买),我们可以用真实的杰里米数据来增加我们猜测的口味向量。
  4. 最后,如果我们对他一无所知呢?然后,我们将需要使用我们拥有的数据来提出一些通用的建议。我们可能希望将一些流行的书籍(我们网站的其他用户倾向于喜欢的)与一些更具探索性的推荐(旨在尽可能多地收集关于 Jeremy 的信息)相结合,以便我们可以尽快计算出 Jeremy 的可用口味向量。

一旦我们有了杰里米的品味向量,我们就可以用它做各种很酷的事情:

  • 我们可以用它来向杰里米推荐。
  • 我们可以使用它来找到与 Jeremy 相似的用户,并根据这些用户的购买和行为增加我们对他的推荐。
  • 如果 Jeremy 是我们网站中非常活跃且模型化良好的成员,我们可以使用他的数据和购买历史来更好地建模,并为我们认为相似的其他用户提供建议。

提出建议

推荐是品味与产品简介相交的地方。我们的想法是浏览我们的产品库存,并推荐符合相关用户口味的产品。正如我们上面提到的,有几种流行的方法可以做到这一点:

  • 我们可以根据他们的口味向量或购买历史找到相似的用户,并推荐其他相似用户购买的产品。这种类型的推荐系统叫做协同过滤
  • 我们可以使用用户的口味向量和我们计算的产品简介来模拟用户与产品的交互。我们可以使用生成的模型来预测用户购买我们库存中每种产品的可能性。然后,我们将使用我们的模型来推荐给定用户最有可能购买的产品。这被称为基于内容的 T4。
  • 没有理由为什么这些方法不能结合起来。用户与我们的产品和建议互动得越多,效果就越好。因此,随着交互次数的增加,协同过滤的有效性通常会随着时间的推移而提高。但是当我们第一次遇到一个用户并且对他们知之甚少的时候(特别是在购买和浏览行为方面),我们可以使用基于内容的方法来推荐和了解他们。
  • 我们的最终目标也很重要。如果我们纯粹是为了移动产品,那么将用户建模为产品购买的载体可能就足够了。但是,如果我们希望更多地了解我们的用户,了解是什么让他们产生兴趣,以及他们为什么做他们所做的事情(这样我们就可以提供更多的服务,扩展我们的产品,或者开创一个全新的业务系列),那么分析和模拟他们的品味和偏好就变得至关重要,基于内容的方法开始变得非常有吸引力。
  • 另一个要考虑的实际问题是如何排列我们的结果。我们可以根据相关性、受欢迎程度、评级(用户对产品的满意度)等进行排名。我们选择的排名指标也将取决于我们的最终目标。

在这篇文章中,我比我预想的要深入一些。我最初的目标是用 5 段或更少的篇幅来解释推荐者,但是我失败了。但希望这既有趣又有见地。干杯!

更多数据科学相关帖子由我:

理解交叉验证

QQ 剧情到底是什么?

了解正态分布

熊猫加入 vs 合并

理解贝叶斯定理

基于学习嵌入的推荐系统

原文:https://towardsdatascience.com/recommender-systems-from-learned-embeddings-f1d12288f278?source=collection_archive---------7-----------------------

一种深度神经网络方法

推荐系统是现代消费者网络应用的基本构建模块,其寻求预测用户偏好。有不同的方法来建立推荐系统。我们对基于最近邻的方法特别感兴趣。我们研究一个项目的配对之间的相似性,并推荐给用户

在本文中,我们将在电影数据集上应用深度神经网络,向用户推荐电影。该系统将随着模型训练过程学习电影嵌入。我们将使用这些嵌入来创建最近邻数据库。每当用户点击一部电影,系统就会提取它的嵌入,找到最近邻的电影推荐给用户。

图片来自 Pixabay 的 Thomas Breher

如果你觉得这篇文章很有趣,请随时联系 LinkedIn。

一般建筑

该系统的整体架构如图 1 所示

图 1 —系统架构

我们将使用电影 ID 和用户 ID 来生成它们相应的嵌入。这些嵌入是通过模型训练过程与其他参数一起生成的。一旦我们有了嵌入,我们建立一个 K-最近邻(KNN)模型。那么每当有一个用户,我们就可以从我们的神经网络模型中得到那个用户的嵌入。我们使用这种嵌入在 KNN 数据库中查找并向该用户推荐 top-K 电影。

这里需要注意的一点是,这种方法无法处理未知用户。也就是说,如果用户 ID 在模型训练过程中不存在,我们将无法为该用户推荐电影。解决这个问题有不同的方法。例如基于人口统计或其他特征找到相似的用户,并基于此为新用户进行推荐。但是这种讨论超出了本文的范围。

在这篇文章中,我将使用 Keras (Tensorflow 2.0 作为后端)来构建我们的深度学习模型。

资料组

在这篇文章中,我们将使用 MovieLens 100K 数据集。数据集包含 100K 行和 34 列。各列如下所示。

'user_id', 'movie_id', 'rating', 'unix_timestamp', 'title', 'release_date', 'video_release_date', 'imdb_url', 'genre_unknown','Action', 'Adventure', 'Animation', 'Children', 'Comedy', 'Crime','Documentary', 'Drama', 'Fantasy', 'Film-Noir', 'Horror', 'Musical','Mystery', 'Romance', 'Sci-Fi', 'Thriller', 'War', 'Western', 'year','genre', 'all_genres', 'age', 'sex', 'occupation', 'zip_code'

我不会深入特性工程的细节,因为这超出了这篇文章的范围。数据集有 943 个唯一的users和 1682 个唯一的movies。我们将使用user_idmovie_id作为特征,使用rating作为基于嵌入模型的目标。

关于嵌入的注释

嵌入是实体的向量表示。你可以通过嵌入把任何离散的实体表示成一个连续的空间[2]。向量中的每一项代表该实体的一个特征或特征组合。

例如,您可以将电影和用户 id 表示为嵌入。为了简单起见,让我们假设这些嵌入是二维向量,如图 2 所示。我们将创建电影和用户嵌入,并用我们的神经网络训练它们。目标是将用户和电影放在一个相似的嵌入空间中,这样我们就可以应用基于最近邻的推荐。图 2 显示了一个假设的例子,其中user_1movie_3更接近嵌入空间中的movie_1movie_2。所以我们将推荐movie_1movie_2user_1

图 2 —嵌入空间中的电影和用户

模型

记住上面的概念,让我们定义我们的模型。在本文中,我正在构建一个四层深度神经网络。您将定义EMBEDDING_SIZE为您想要嵌入的向量的维数。一般来说,更高的维度更好,因为这可以捕捉更多的特征,尽管这可能会增加训练时间。本例中NUM_USERS943NUM_MOVIES1682ROW_COUNT表示您的训练集的大小。

正如您在上面的代码中看到的,我们已经为电影(第 4 行)和用户(第 11 行)创建了一个嵌入层。对于一个机器学习工程师来说,了解 Keras 嵌入层是如何工作的是值得的[3][4]。output_dim表示嵌入向量的长度,在我们的例子中是EMBEDDING_SIZEinput_dim表示不同实体的数量——在本例中为NUM_MOVIESNUM_USERSinput_length参数决定每个输入序列的大小。嵌入层根据embedding_initializer参数【3】初始化嵌入权重。如果您将这些嵌入层与网络一起训练,这些层的输出将得到更新。这就是我们模型中发生的情况。

我为50个时期训练模型,将early_stopping设置为在连续 10 个时期内验证损失不变。您可以根据自己的需要调整这些参数。

我们可以绘制模型来可视化它的架构

keras.utils.plot_model(model, show_shapes=True) 

图 3——可视化模型架构

我们可以绘制不同时期的损失曲线

图 4 —历元曲线上的损耗

图 4 示出了训练损失随着时期减少,这意味着训练收敛到最佳点。

您可以使用movie_model.predict(numpy.array([id]))从每个电影 ID 的movie_model中提取电影嵌入。

验证嵌入

你怎么知道这些嵌入是正确的呢?验证它们的一种方法是绘制嵌入图。一旦你画了图,你会看到有相似评级的电影(因为评级是我们的目标)就在嵌入空间附近。让我们看一看。

图 5 —电影嵌入的 t-SNE 图

图 5 有点难以想象。所以我打算绘制前 300 个电影嵌入,看看我是否能得到更清晰的图像。

图 6-电影 ID 300 之前电影嵌入的 t-SNE 图

例如,在图 6 中,电影 ID 5366在嵌入空间上比电影 ID 9更接近。

图 7 —计算平均电影评级

如果您检查数据集的平均评分(图 7),您会发现电影 ID 5366的平均评分分别为3.243.04 ,而电影 ID 9的平均评分为3.83

使用 KNN 的最近邻居

现在我们有了嵌入,我们可以应用最近邻算法向用户推荐电影。我们可以从user_id中得到user_embedding,找出嵌入空间中与user_embedding接近的电影有哪些。为此,我们使用 K-最近邻算法。

这里推荐的 10 部电影列表如图 8 所示。

图 8 —推荐电影列表

这里需要注意的是,如果嵌入发生变化,推荐的电影列表可能会有所不同。嵌入可能会因运行而异。这主要是因为我们使用了一个较小的数据集(100K 行)。更大的数据集(1M+)以及更长的训练时间可能会输出更稳定的嵌入。

本文的完整代码可以在这里找到。

参考:

  1. Youtube 深度神经网络推荐此处
  2. m .库拉(2015 年)。用户和项目冷启动推荐的元数据嵌入。arXiv:1507.08439。
  3. Keras 嵌入层【https://keras.io/api/layers/core_layers/embedding/
  4. Keras 嵌入层如何工作https://stats . stack exchange . com/questions/270546/how-does-Keras-Embedding-layer-work
  5. https://drop . engineering/building-a-recommenders-system-using-embeddings-de 5a 30 e 655 aa
  6. https://www . ka ggle . com/willkoehrsen/Neural-Network-Embedding-recommendation-system # Neural-Network-Embedding-Model

Python:从头开始实现矩阵分解!

原文:https://towardsdatascience.com/recommender-systems-in-python-from-scratch-643c8fc4f704?source=collection_archive---------2-----------------------

基于梯度下降的矩阵分解模型在推荐系统中的应用

信用:Pixabay

你有没有想过网飞是如何确定你可能喜欢什么内容,或者亚马逊是如何让你注意到你可能会购买的产品的?或者,如果你正在阅读这篇文章,你可能非常清楚这些系统的存在,但不确定它们是如何运作的。

基于内容的过滤与协同过滤

一般来说,推荐系统有两种主要的方法:基于内容的和协作的。当然,有混合的方法,并且据称,也存在基于知识的系统。见下图:https://pdfs . semantic scholar . org/7e 41/3d 5661 f 185 B4 f 19825 da 9220535 cc 04388 AE . pdf

没有任何不必要的麻烦,基于内容意味着根据内容与其他内容的相似性向你推荐内容,而不考虑其他用户的偏好。协作是相反的,它不关心项目的非抽象特征,而是利用群体的智慧来产生推荐。前者的一个例子就是潘多拉的推荐系统。他们(煞费苦心地)精心制作了大约 400 个特征的音乐基因组。并且根据歌曲展现这些特征的程度向用户推荐歌曲。(想想流派,歌曲长度,艺人年龄,艺人种族等。)协作过滤发现用户项目偏好中的模式,并利用这些模式来生成推荐。对于本文,我们将只关注协同过滤。

在协作过滤生态系统中,有许多选项可用。例如,奇异值分解(SVD)是第一种这样的技术,它(顾名思义)将用户项目偏好矩阵分解为三个元素:用户特征特征向量、特征项目特征向量和特征值的对角矩阵。将用户条目矩阵分解成潜在特征是非常有用的。用户被理解为他们更喜欢的潜在特征,而项目被理解为潜在特征和它们呈现的程度。换句话说,距离度量,例如余弦相似性,可以用于将用户直接与项目进行比较,并生成最佳匹配。当然,您可以将用户与用户进行比较,将项目与项目进行比较,但是 SVD 要强大得多!

另一种方法是基于梯度下降的矩阵分解,我们将在本文的剩余部分重点介绍这种方法。这里的核心思想是创建参数并迭代更新它们,以最小化某个成本函数。如果这听起来像是神经网络——你就在正确的轨道上;我们朝那个方向去了!注意:基于深度学习的方法确实存在;然而,我们不会使用神经元或非线性,我们肯定不会将多层神经元链接在一起(又名深度学习。)

让我们开始考虑我们将如何处理这个问题,从理解我们的参数、矩阵乘法以及我们如何迭代地更新这些参数开始。让我们考虑下面的情况:

用户特征行和特征项目列的点积是单个用户项目评级

请注意,用户特征矩阵和特征项目矩阵中的每个单元都是一个参数。(在神经网络行话中称为权重)我们需要通过一些成本函数迭代更新这些参数。但是在我们深入研究之前,我们需要知道任何给定的用户特征单元和特征项单元所贡献的用户项单元。比如U1F1U1F2贡献U1I1U1I2U1I3。矩阵乘法被执行为左矩阵的与右矩阵的的点积。正如您将看到的,用户条目矩阵的行和列索引决定了从分解的矩阵中选择的整个行和列。

用户特征单元和它们参与的用户项目单元

让我们考虑另一个例子。请注意,我已经提醒您注意的用户项单元格形成了一个单独的列,而不是一行。这是因为单元格F1I1F2I2构成了用户项矩阵中的三个不同的单元格。

要素项单元及其所在的用户项单元

如果这还不明显,我们需要更新我们的用户特征和特征项参数,但重要的是要注意— 每个参数将由三个不同梯度的平均值更新,每个梯度都与给定的参数相关。

下面的例子显示了更新U1F1所需的三个梯度中的一个;注意另外两个梯度U1I2U1I3,每个(当然)相对于U1F1。当我们更新U1F1时,我们将对这三个梯度进行平均。这里的直觉是,如果一次追逐一个梯度,我们可能永远不会收敛到最佳参数值。通过平均梯度,我们可以同时采取三个步骤来达到最佳决策。

U1I1 的 MSE 和相对于 U1F1 的梯度

信不信由你——我们现在已经拥有了用 python 编写矩阵分解求解器所需的所有构件!让我们看看代码。我在下面附上了一个 Google Colab 笔记本,你可以在那里看到并运行代码来试验结果!我们将在类架构中逐个方法地剖析代码。

[## 谷歌联合实验室

矩阵分解从零开始 colab.research.google.com](https://colab.research.google.com/drive/1X0cFGeY2y8D2OLK4VB8frHkVxCMaBS1s?authuser=1#scrollTo=H5mPYAKPIyfu)

首先,让我们创建一个类对象并初始化它的特性。我已经做出了设计决定,将参数初始化为 0.1 到 0.9 之间的默认值。此外,我们将如前所述定义 MSE 函数。

第二,让我们找到一个单一的梯度。如前所述,这是相对于一个用户特征单元(或一个特征项单元)的一个用户项单元。

但是正如我们已经讨论过的,仅仅找到一个梯度是不够的。在更新给定参数时,我们必须考虑整行(或整列)。

最后,我们需要定义一个训练模型的方法。默认情况下,我们将学习率设置为 0.1,迭代次数设置为 1000 次。这可以在上面提到的 Google Colab 中修改。您会注意到,在每次迭代中,项目特征值都增加了。梯度不是负的吗?是的!但在梯度下降中,使用符号* w -= learning_rate * gradient是标准的。在我们的例子中,双重否定完全抵消了。*

现在,让我们验证我们的代码是否有效!正如你所看到的,只有两个潜在的特征,我们离最优解只有这么近。误差不会减小到超过 3.54。

然而,如果我们再增加一个潜在的特征,我们可以非常接近 0 误差。事实上,当我们将矩阵用户特征和特征项相乘时,我们得到了我们开始时的矩阵。是不是很美!

我希望你喜欢今天的文章。如果你想看到更多这样的内容,请在下面评论!

推荐系统:从零开始的矩阵分解

原文:https://towardsdatascience.com/recommender-systems-matrix-factorization-using-pytorch-bd52f46aa199?source=collection_archive---------8-----------------------

预测动漫收视率

来源

我们每天都会遇到多次推荐——在决定在网飞/Youtube 上看什么的时候,购物网站上的商品推荐,Spotify 上的歌曲推荐,Instagram 上的朋友推荐,LinkedIn 上的工作推荐……不胜枚举!推荐系统旨在预测用户对某个项目的“评分”或“偏好”。这些评级用于确定用户可能喜欢什么,并给出明智的建议。

有两大类推荐系统:

  1. 基于内容的系统:这些系统试图根据物品的内容(类型、颜色等)和用户的个人资料(喜欢、不喜欢、人口统计信息等)来匹配用户和物品。例如,Youtube 可能会基于我是一名厨师和/或我过去看过很多烘焙视频的事实,建议我制作视频,从而利用它所拥有的关于视频内容和我的个人资料的信息。
  2. 协同过滤:他们依赖于相似用户喜欢相似物品的假设。用户和/或项目之间的相似性度量被用来进行推荐。

本文讨论了一种非常流行的协作过滤技术,称为矩阵分解。

矩阵分解

推荐系统有两个实体——用户和项目。假设我们有m个用户和n个项目。我们推荐系统的目标是建立一个mxn矩阵(称为效用矩阵),它由每个用户-项目对的评级(或偏好)组成。最初,这个矩阵通常非常稀疏,因为我们只有有限数量的用户-项目对的评级。

这里有一个例子。假设我们有 4 个用户和 5 个超级英雄,我们试图预测每个用户给每个超级英雄的评分。这是我们的效用矩阵最初的样子:

超级英雄评级的 4x5 效用矩阵(图片由作者提供)

现在,我们的目标是通过找到用户和项目之间的相似性来填充这个矩阵。举例来说,为了获得直觉,我们看到用户 3 和用户 4 给蝙蝠侠的评分相同,所以我们可以假设用户是相似的,他们对蜘蛛侠有相同的感觉,并预测用户 3 会给蜘蛛侠 4 分。然而,在实践中,这并不简单,因为有多个用户与许多不同的项目进行交互。

在实践中,通过将效用矩阵分解(或因式分解)成两个瘦高矩阵来填充矩阵。分解公式如下:

效用矩阵可以分解为两个低维的瘦高矩阵的乘积,这两个矩阵分别代表用户和项目

其中 U 为m x k,V 为n x k。u 是用户在某个低维空间的表示,V 是物品的表示。对于用户 I,uᵢ给出该用户的表示,对于物品 e,vₑ给出该物品的表示。用户-项目对的评级预测简单来说就是:

用户-项目对的评级预测只是用户和项目表示的点积

矩阵分解(为便于说明,数字是随机的)(图片由作者提供)

履行

为了实现矩阵分解,我们可以使用用户和项目嵌入矩阵的嵌入,并使用梯度下降来获得最佳分解。如果您对嵌入不熟悉,您可以查看这篇文章,在这篇文章中我详细讨论了它们:

[## 使用 PyTorch 对表格数据进行深度学习

关于多类分类问题

towardsdatascience.com](/deep-learning-for-tabular-data-using-pytorch-1807f2858320)

密码

我在本文中使用的所有代码都可以在这里找到:https://jovian . ml/aakanksha-ns/anime-ratings-matrix-factorization

资料组

我使用了 Kaggle 的动漫推荐数据集:

[## 动漫推荐数据库

来自 myanimelist.net 76,000 名用户的推荐数据

www.kaggle.com](https://www.kaggle.com/CooperUnion/anime-recommendations-database)

我们总共有 69600 个用户和 9927 部动漫。提供了 6337241 个评级(在 690,919,200 个可能的评级中)。

问题陈述

给定一组动漫的用户评分,预测每对用户动漫的评分。

数据探索

我们看到有许多评级为-1的行,表示缺少评级,我们可以去掉这些行。

我们也可以看看收视率的分布和每个用户的收视率。

预处理

我们需要连续的 id,以便能够索引到嵌入矩阵中,并访问每个用户/项目嵌入。

培养

我们的目标是为每个用户和每个项目找到最佳嵌入。然后,我们可以使用这些嵌入,通过取用户嵌入和项目嵌入的点积,对任何用户-项目对进行预测

成本函数:我们试图最小化效用矩阵的均方误差。这里 N 是效用矩阵中非空白元素的数量。

矩阵分解的代价函数

使用项目和用户嵌入的预测

均方误差(mean square error)

初始化用户和项目嵌入:有很多方法可以初始化嵌入权重,这是一个活跃的研究领域,例如, fastai 使用了一种叫做的截断法线初始化器。在我的实现中,我刚刚在(0,11/K)中用统一的值初始化了我的嵌入(随机地,在我的例子中工作得很好!)其中 K 是嵌入矩阵中因子的数量。k 是一个通常由经验决定的超参数,它不应该太小,因为你希望你的嵌入学习足够的特征,但你也不希望它太大,因为它会开始过度适应你的训练数据并增加计算时间。

创建稀疏效用矩阵:因为我们的成本函数需要效用矩阵,所以我们需要一个函数来创建这个矩阵。

梯度下降:

梯度下降方程为:

我在我的实现中使用了动量,这是一种有助于在相关方向上加速梯度下降并抑制振荡从而导致更快收敛的方法。我还添加了正则化,以确保我的模型不会过度适应训练数据。因此,我的代码中的梯度下降方程比上面提到的稍微复杂一些。

正则化的成本函数是:

培养

验证集预测

因为我们不能对我们在训练集中没有遇到的用户和动画(冷启动问题)进行预测,所以我们需要将它们从我们看不见的数据集中移除。

我们的模型稍微过度拟合了训练数据,因此可以增加正则化因子(λ)以使其更好地泛化。

让我们来看几个预测:

鉴于这些评级仅仅基于用户行为之间的相似性,在 1-10 的评级范围内,均方根值仅为 3.4 就已经非常令人印象深刻了。它展示了矩阵分解是多么强大,尽管它是如此简单。

矩阵分解的局限性

矩阵分解是一种非常简单方便的推荐方法。然而,它也有缺陷,其中一个缺陷我们已经在实施中遇到过:

冷启动问题

我们无法预测在训练数据中从未遇到过的项目和用户,因为我们没有它们的嵌入。

冷启动问题可以通过多种方式解决,包括推荐受欢迎的项目,要求用户对一些项目进行评级,使用基于内容的方法,直到我们有足够的数据来使用协同过滤。

很难包含关于用户/项目的附加上下文

我们只使用用户 id 和项目 id 来创建嵌入。在我们的实施过程中,我们无法使用任何其他关于我们的用户和项目的信息。有一些基于内容的协作过滤的复杂混合模型可以用来解决这个问题。

评级并不总是可用

很难得到用户的反馈。大多数用户只有在他们真的喜欢某样东西或者绝对讨厌它的时候才会给它打分。在这种情况下,我们经常需要想出一种方法来测量隐式反馈,并使用负采样技术来得出一个合理的训练集。

结论

推荐系统确实很有趣,但也很容易变得太复杂,尤其是当在有数百万用户和数百万项目的规模上实现时。如果你想更深入地了解推荐系统,可以看看各种案例研究 Youtube 如何推荐视频、LinkedIn 工作推荐、广告排名。通常,你可以找到与这些案例研究相对应的研究论文/视频/工程博客。以下是一些有用的资源:

  • https://engineering . LinkedIn . com/blog/2019/04/ai-behind-LinkedIn-recruiter-search-and-recommendation-systems
  • https://static . Google user content . com/media/research . Google . com/en//pubs/archive/45530 . pdf
  • https://labs . Pinterest . com/user/themes/pin _ labs/assets/paper/P2P-www 17 . pdf

参考

  • https://developers . Google . com/machine-learning/recommendation/collaborative/matrix
  • https://medium . com/@ pari tosh _ 30025/re commendation-using-matrix-factorization-5223 A8 E1 F4
  • 旧金山大学 MSDS 分校—高级机器学习课程
  • https://www.youtube.com/watch?v=ZspR5PZemcs

推荐系统:机器学习最有价值的应用(下)

原文:https://towardsdatascience.com/recommender-systems-the-most-valuable-application-of-machine-learning-2bc6903c63ce?source=collection_archive---------25-----------------------

为什么推荐系统是机器学习最有价值的应用,以及机器学习驱动的推荐器如何已经驱动了我们生活的几乎每个方面。

推荐系统已经驱动了我们日常生活的几乎每个方面。

这是 5 月 11 日发表的文章的第二部分。在第一部分中,我介绍了:

  • 商业价值
  • 问题定式化
  • 数据
  • 算法

[## 推荐系统:机器学习最有价值的应用(上)

为什么推荐系统是机器学习最有价值的应用,以及成功的科技公司如何使用…

towardsdatascience.com](/recommender-systems-the-most-valuable-application-of-machine-learning-part-1-f96ecbc4b7f5)

在第二部分中,我将讨论以下主题:

  • 评估指标
  • 用户界面
  • 冷启动问题
  • 探索与开发
  • 推荐系统的未来

在整篇文章中,我将继续使用在过去几年中建立了最广泛使用的系统的公司的例子,包括 Airbnb、亚马逊、Instagram、LinkedIn、网飞、Spotify、Uber Eats 和 YouTube。

评估指标

现在我们有了推荐系统的算法,我们需要找到一种方法来评估它的性能。与每个机器学习模型一样,有两种类型的评估:

  1. 离线评估
  2. 在线评估

离线/在线测试框架

一般来说,我们可以将离线评估指标视为低级指标,通常很容易测量。最著名的例子是网飞选择使用均方根误差 (RMSE)作为 Netflix 奖挑战的代理指标。在线评估指标是的高层次业务指标,只有当我们将模型投放到现实世界并与真实用户一起测试时,这些指标才是可衡量的。一些例子包括客户保持率、点击率或用户参与度。

离线评估

由于大多数现有的推荐系统包括两个阶段(候选生成和排序),我们需要为每个阶段选择正确的度量。对于候选生成阶段,例如,YouTube 关注高精度因此“在所有预选的视频中,有多少是相关的”。这是有意义的,因为在第一阶段,我们希望过滤一个较小的视频集,同时确保所有视频都与用户潜在相关。在第二阶段,在列表中呈现几个“最佳”推荐需要精细的表示,以区分具有高回忆的候选人 ( “我们找到了多少相关视频】 ) )。

通常,大多数例子都使用机器学习社区中使用的标准评估指标:从标准化折扣累积增益、平均倒数排名或和谐对的分数等排名措施,到包括准确度、精确度、召回率或 F 分数在内的分类指标。

Instagram 制定了他们最终通过模型的优化函数略有不同:

我们预测人们在每个媒体上采取的个人行动,无论是积极的行动,如喜欢和保存,还是消极的行动,如“少看这样的帖子”(SFPLT)。我们使用多任务多标签(MTML)神经网络来预测这些事件。

尽管离线实验很吸引人,但它们有一个重大缺陷:它们假设,如果被评估的新算法被用来生成推荐,成员们会以同样的方式行事,比如播放同样的视频。这就是为什么我们需要在线评估来衡量我们的模型对更高层次的业务指标的实际影响。

在线评估

这里需要注意的方法是 A/B 测试。有许多有趣而详尽的文章/ 课程很好地涵盖了这一点,因此我不会在这上面花太多时间。我遇到的唯一一个微小的变化是网飞的“消费者数据科学”,你可以在这里读到它。

公司在这里衡量的最流行的高级指标是点击率参与度。Uber Eats 在这里走得更远,设计了一个多目标权衡,即捕捉多个高级指标来说明他们三方市场的整体健康状况(其中包括:市场公平性、总预订量、可靠性、食客满意度)。除了中期参与外,网飞还关注会员保留率,因为他们的在线测试可以持续 2-6 个月。

众所周知,YouTube 优先考虑观看时间,而不是点击率。他们甚至写了一篇文章,解释为什么:

通过点击率排名通常会促进用户没有完成的欺骗性视频(“点击诱饵”),而观看时间更好地捕捉参与度

评估嵌入

如算法部分所述,嵌入是候选生成阶段的关键部分。然而,与分类或回归模型不同,众所周知很难测量嵌入的质量,因为它们经常在不同的环境中使用。我们可以执行的健全性检查是将高维嵌入向量映射到较低维的表示中(通过 PCA、t-SNE 或 UMAP ),或者应用 k-means 等聚类技术,然后可视化结果。Airbnb 通过他们的房源嵌入做到了这一点,以确认来自相似地点的房源被聚集在一起。

用户界面

对于机器学习工程师或数据科学家来说,等式中最容易被忽略的方面是用户界面。问题是,如果您的 UI 不包含展示推荐所需的组件,或者在错误的上下文中展示它们,那么反馈循环就存在固有的缺陷。

我们以 Linkedin 为例来说明这一点。如果我在浏览人们的个人资料,我会在屏幕的右边看到对相似的人的推荐。当我浏览公司时,我看到了对类似公司的推荐。这些推荐符合我当前的目标和背景,鼓励我继续浏览网站。如果相似公司的推荐会出现在一个人的个人资料上,我可能不太愿意点击他们的个人资料,因为这不是我目前正在寻找的。

Linkedin 上类似的用户推荐

Linkedin 上类似公司的推荐

你可以建立世界上最好的推荐系统,但是,如果你的界面不是为满足用户的需求而设计的,没有人会欣赏你的推荐。事实上,用户界面的挑战是如此重要,以至于网飞将他们网站上的所有组件都变成了动态组件,由机器学习算法组装起来,以最好地反映用户的目标。

Spotify 遵循了这一模式,而在主屏幕设计上也采用了类似的布局,如下图所示。

用机器学习个性化 Spotify Home(来源: Spotify

这是一个仍在进行大量实验的领域。例如,YouTube 最近改变了他们的主页界面,使用户能够缩小不同主题的推荐范围:

新的 YouTube 主页

冷启动问题

冷启动问题在推荐系统中经常出现,因为像协同过滤这样的方法严重依赖于过去的用户-项目交互。企业面临的冷启动问题有两种方式:用户冷启动和物品冷启动。根据平台的类型,这两种方式中的任何一种都更流行。

用户冷启动

想象一下,一个新成员注册了网飞。此时,公司对新成员的偏好一无所知。该公司如何通过提供出色的推荐来留住她?

在网飞的情况下,新会员可以获得一个月的免费试用期,在此期间取消率最高,但之后会迅速下降。这就是为什么冷启动问题的任何改善都会为网飞带来巨大的商机,从而在最初的 30 天里增加参与度和保留率。如今,他们的成员在注册过程中会接受一项调查,在此期间,他们会被要求从一组算法填充的视频中选择视频,然后作为他们所有算法的输入。

项目冷启动

当新项目或内容添加到目录中时,公司会面临类似的挑战。像网飞或 Prime Video 这样的平台拥有一个现有的媒体项目目录,这些目录很少改变(制作电影或连续剧需要时间!),因此他们很少为此而挣扎。相反,在 Airbnb 或 Zillow 上,每天都有新的房源被创建,在这一点上,它们没有嵌入,因为它们在培训过程中不存在。Airbnb 通过以下方式解决这一问题:

为了创建新列表的嵌入,我们找到 3 个地理上最接近的列表,它们确实有嵌入,并且与新列表具有相同的列表类型和价格范围,并计算它们的平均向量。

对于 Zillow 来说,这一点尤为重要,因为一些新房房源可能只会在网站上呆几天。他们通过创建从内容空间到嵌入空间的基于神经网络的映射函数,创造性地解决了这个问题,该映射函数在学习阶段由来自用户的参与度数据指导。这允许他们仅仅通过使用其特征就可以将新的住宅列表映射到所学习的嵌入空间。

探索与开发

探索/开发的概念可以被看作是新内容与成熟内容之间的平衡。我本来打算自己来阐述这个概念,但我发现了一段很棒的摘录,这段摘录恰到好处:

“想象你刚刚走进一家冰淇淋店。你现在面临着一个至关重要的决定——在大约 30 种口味中,你只需要选择一种!你可以选择两种策略:要么选择你最喜欢的口味,你已经知道那是最好的;或者探索你从未尝试过的新口味,也许会发现一种新的最佳口味。
这两种策略——开发和探索——也可以在推荐内容时使用。我们可以利用具有高确定性的高点击率的项目——可能是因为这些项目已经向类似用户显示了数千次,或者我们可以探索过去没有向许多用户显示的新项目。将探索融入到你的推荐策略中至关重要——没有探索,新商品就没有机会与更老、更熟悉的商品竞争。”

(来源: 推荐系统:利用不确定性探索未知 )

这种权衡是典型的强化学习问题,常用的方法是多臂 bandit 算法。Spotify 使用它来个性化每个用户的主页,Uber Eats 也使用它来提供针对三方市场优化的个性化推荐。网飞大学的两位科学家做了一个精彩的演讲,讲述了他们如何使用 MAB 电影推荐框架。

虽然我应该提到,这绝不是这个问题的最终解决方案,但它似乎对网飞、Spotify 和 Uber Eats 都有效,对吗?

是的。但是!

网飞大约有 1.6 亿用户和 6000 部电影/节目。Spotify 拥有约 2.3 亿用户和 5000 万首歌曲+ 50 万个播客。

Twitter 的 3.3 亿活跃用户每天产生超过 5 亿条推文 (每分钟 35 万条推文,每秒 6.000 条推文)。还有 YouTube,它的 每分钟上传 300 小时的视频

后两种情况下的探索空间比网飞或 Uber Eats 的情况大一点点,这使得问题更具挑战性。

推荐系统的未来

这是我对推荐系统的小调查的结尾。正如我们所观察到的,推荐系统已经指导了我们生活的许多方面。我们在这两篇文章中讨论的所有算法每天都在争夺我们的注意力。毕竟,他们都在最大限度地利用他们平台上的时间。正如我在评估方法一节中所述,大多数算法都是针对点击率、参与度或 YouTube 的观看时间进行优化的。

作为消费者,这对我们意味着什么?

这意味着,我们不再能控制我们的欲望。虽然这听起来很有诗意,但是仔细想想。我们来看看 YouTube 来到现场时,我们都有目标。我们可能想听音乐,看一些有趣的东西,或者学习一些新的东西。但是所有推荐给我们的内容(无论是通过主页推荐,搜索排名,还是观看下一集)都经过了优化,可以让我们在网站上停留更长时间。

Lex Fridman 和 Franç ois Chollet 在人工智能播客上就这个进行了一次的精彩对话。如果公司让用户负责选择他们自己的目标函数,而不是选择优化的指标,会怎么样?如果他们将用户档案的个人目标考虑在内,并问用户,你想达到什么目标呢?现在,这项技术几乎就像我们的老板,我们无法控制它。利用推荐系统的力量,使其更像一个导师、教练或助手,这难道不可思议吗?

想象一下,作为一名消费者,你可以要求 YouTube 优化内容,以最大限度地提高学习效果。技术当然已经存在了。真正的挑战在于将它与现有的业务模型结合起来,并设计合适的界面,使用户能够做出选择,并随着目标的发展而改变。有了新的界面,YouTube 可能已经在这个方向上迈出了一小步,让用户负责选择她希望看到推荐的类别。但这仅仅是开始。

这是未来的发展方向,还是仅仅是消费者的梦想?

资源

Fran ois Chollet:Keras、深度学习和人工智能的进展|人工智能播客

Airbnb —在搜索排名中列出嵌入内容

Airbnb——基于机器学习的 Airbnb 体验搜索排名

【亚马逊-Amazon.com 推荐商品对商品协同过滤】T2

亚马逊——亚马逊推荐算法的历史

Instagram——由人工智能支持:insta gram 的探索推荐系统

LinkedIn——浏览器地图:LinkedIn 上的协作过滤

网飞—网飞推荐:超越五星(上)

网飞—网飞推荐:超越五星(下)

网飞——网飞推荐系统:算法、商业价值和创新

网飞——学习个性化主页

潘多拉——潘多拉的音乐推荐者

Spotify——探索周刊:Spotify 怎么这么了解你?

Spotify——只给你听:用机器学习个性化 Spotify Home

Spotify——从想法到执行:Spotify 的《发现周刊》

Twitter —嵌入@Twitter

Uber Eats——用 Uber Eats 发现食物:向市场推荐

Uber Eats——用 Uber Eats 发现食物:使用图形学习来增强推荐

YouTube——YouTube 视频推荐系统

YouTube——推荐系统的协作深度学习

YouTube —用于 YouTube 推荐的深度神经网络

Zillow —相似住宅推荐的住宅嵌入

吴恩达的机器学习课程(推荐系统)

谷歌的机器学习速成班——嵌入

范登布鲁克·朱丽叶✍️编辑评论

推荐系统:机器学习最有价值的应用(上)

原文:https://towardsdatascience.com/recommender-systems-the-most-valuable-application-of-machine-learning-part-1-f96ecbc4b7f5?source=collection_archive---------4-----------------------

为什么推荐系统是机器学习最有价值的应用,以及机器学习驱动的推荐器如何已经驱动了我们生活的几乎每个方面。

推荐系统已经驱动了我们日常生活的几乎每个方面。

回顾你的一周:一个机器学习算法决定了你可能喜欢听什么歌,在网上订购什么食物,你在你最喜欢的社交网络上看到什么帖子,以及你可能想联系的下一个人,你想看什么连续剧或电影等等…

机器学习已经指导了我们生活的许多方面,而我们却不一定意识到这一点。上面提到的所有应用都是由一种算法驱动的:推荐系统。

在这篇文章中,我将探索和深入构建一个成功的推荐系统的所有方面。这篇文章的长度有点失控,所以我决定把它分成两部分。第一部分将包括:

  • 商业价值
  • 问题定式化
  • 数据
  • 算法

第二部分将涵盖:

  • 评估指标
  • 用户界面
  • 冷启动问题
  • 探索与开发
  • 推荐系统的未来

在整篇文章中,我将使用在过去几年中建立了最广泛使用的系统的公司的例子,包括 Airbnb、亚马逊、Instagram、LinkedIn、网飞、Spotify、Uber Eats 和 YouTube。

商业价值

《哈佛商业评论》发表了一份强有力的声明,称推荐人是“天生数字化”企业和传统企业之间最重要的算法区别。HBR 还描述了这些可以产生的良性商业循环:使用公司推荐系统的人越多,他们就变得越有价值,而他们变得越有价值,使用他们的人就越多。

推荐系统的良性商业循环(来源: MDPI ,CC)

我们被鼓励关注推荐系统,不是作为一种在线销售的方式,而是将其视为不断提高客户洞察力和我们自己洞察力的可再生资源。如果我们看上面的插图,我们可以看到许多传统公司也有大量的用户,因此也有大量的数据。他们的良性循环没有像亚马逊、网飞或 Spotify 那样迅速,原因是缺乏将用户数据转化为可操作的见解的知识,这些见解可以用来改进他们的产品或服务。

以网飞为例,可以看出这一点有多重要,因为人们观看的 80%的内容都来自某种推荐。2015 年,他们的一篇论文引用了:

“我们认为个性化和推荐的综合效果每年为我们节省了超过$1B。”

如果我们看看亚马逊,顾客在亚马逊购买的 35%来自产品推荐,而在 Airbnb,搜索排名和类似的列表推动了 99%的预订转化。

问题定式化

现在我们已经看到了巨大的价值,公司可以从推荐系统中获益,让我们看看他们可以解决的挑战类型。一般来说,科技公司试图向他们的用户推荐最相关的内容。这可能意味着:

  • 类似的房屋列表(Airbnb、Zillow)
  • 相关媒体,如照片、视频和故事(Instagram)
  • 相关系列和电影(网飞、亚马逊 Prime 视频)
  • 相关歌曲和播客(Spotify)
  • 相关视频(YouTube)
  • 相似的用户,帖子(LinkedIn,Twitter,Instagram)
  • 相关菜品和餐厅(优步吃)

在这里,问题的表述是至关重要的。很多时候,公司希望推荐用户未来最有可能喜欢的内容。这个问题的重新表述,以及算法从推荐“用户最有可能观看什么”到“用户未来最有可能观看什么的变化,使得亚马逊 PrimeVideo 获得了 2 倍的改善,这是他们电影推荐系统的“十年一次的飞跃”。

“亚马逊的研究人员发现,当他们按时间顺序对输入数据进行排序,并使用它来预测未来短期(一到两周)内的电影偏好时,使用神经网络来生成电影推荐的效果要好得多。”

数据

推荐系统通常将两种类型的数据作为输入:

  • 用户交互数据(隐式/显式)
  • 项目数据(特性)

基于协作过滤(被亚马逊、网飞、 LinkedIn 、 Spotify 和 YouTube 使用)的“经典”且仍被广泛使用的推荐系统方法使用用户-用户或项目-项目关系来查找相似的内容。我不打算深入探讨这个问题的内部工作原理,因为有很多关于这个主题的文章——比如这篇文章——很好地解释了这个概念。

**用户交互数据是我们从网络日志中收集的数据,可以分为两组:

:来自我们用户的明确输入(例如,电影评级、搜索日志、喜欢、评论、观看、收藏等。)

隐含数据 :不是有意提供的,而是从可用数据流中收集的信息(如搜索历史、订单历史、点击、互动账户等)。)

项目数据主要由项目特征组成。在 YouTube 的情况下,这将是视频的元数据,如标题和描述。对于 Zillow 来说,这可能是一个家庭的邮政编码、城市地区、价格或卧室数量。

其他数据源可能是 外部数据 (例如,网飞可能添加外部项目数据特征如票房表现或评论家评论)或专家生成的数据(潘多拉的音乐基因组项目使用人类输入来应用每首歌曲在大约 400 个音乐属性中的值)。

这里的一个关键见解是,显然,拥有更多关于你的用户的数据将不可避免地导致更好的模型结果(如果应用正确),然而,正如 Airbnb 在他们的为 Airbnb 体验建立排名模型的 3 部分旅程中所示你已经可以用更少的数据实现相当多的成就:Airbnb 的团队仅用 500 次体验和 50k 的训练数据规模就已经将预订量提高了+13%。

“主要的收获是:不要等到你有了大数据,你可以用小数据做很多事情来帮助你的业务增长和改善。

算法

通常,我们只把推荐系统和协同过滤联系在一起。这很公平,因为在过去,这是许多在实践中部署了成功系统的公司的首选方法。亚马逊可能是第一家利用项目对项目协同过滤的公司。当他们在 2003 年首次在一篇论文中公布他们方法的内部运作时,该系统已经使用了六年。

然后,在 2006 年,网飞紧随其后,发起了著名的网飞价格挑战,奖励任何将他们现有的电影技术系统的精确度提高 10%的人 100 万美元。协同过滤也是 Spotify 和 YouTube 早期推荐系统的一部分。LinkedIn 甚至开发了一个名为 Browsemaps 的横向协作过滤基础设施。该平台支持针对 LinkedIn 上几乎所有用例的协同过滤推荐的快速开发、部署和计算。

如果你想了解更多关于协同过滤的知识,我推荐你去看看 Coursera 上吴恩达机器学习课程的第 16 部分,在那里他深入研究了其背后的数学原理。

现在,我想后退一步,概括一下推荐系统的概念。虽然许多公司过去依赖于协同过滤,但今天有许多其他不同的算法在发挥作用,它们补充甚至取代了协同过滤方法。当网飞从 DVD 运输转向流媒体业务时,他们经历了这一变化。正如他们在一篇论文中所描述的:

“当我们的主要业务是通过邮件运送 DVD 时,我们确实非常依赖这样的算法,部分原因是在这种情况下,星级是我们收到的会员实际观看视频的主要反馈。[……]但明星和 DVD 成为网飞推荐焦点的日子早已过去。[……]现在,我们的推荐系统由各种算法组成,这些算法共同定义了网飞体验,其中大多数都集中在网飞主页上。”

如果我们缩小一点,更广泛地观察推荐系统,我们会发现它们基本上由两部分组成:

  1. 候选生成
  2. 排名

下面我将使用 YouTube 的推荐系统作为例子,因为它们提供了一个很好的可视化效果,但是同样的概念也适用于 Instagram 的“insta gram Explore”中的推荐,优步的菜肴和餐馆推荐系统,网飞的电影推荐以及其他许多公司。

两阶段推荐系统(受 YouTube 启发)

根据网飞的说法,推荐系统的目标是提供大量有吸引力的商品供人们选择。这通常是通过选择一些项目(候选生成)并按照预期享受(或效用)的顺序对它们进行排序(排名)来实现的。

让我们进一步研究这两个阶段:

候选生成

在这一阶段,我们希望找到有资格向我们的用户展示的相关候选人。在这里,我们处理的是整个商品目录,所以它可能非常大(YouTube 和 Instagram 就是很好的例子)。做到这一点的关键是实体嵌入。什么是实体嵌入?

实体嵌入是实体的数学向量表示,使得它的维度可以表示某些属性。Twitter 在一篇关于嵌入@Twitter 的博文中有一个很好的例子:假设我们有两名 NBA 球员(斯蒂芬·库里和勒布朗)和两名音乐家(肯德里克·拉玛尔和布鲁诺·马斯)。我们期望 NBA 球员之间的嵌入距离小于球员和音乐家之间的嵌入距离。我们可以使用欧几里得距离公式来计算两个嵌入之间的距离。

我们是如何想出这些嵌入的?

一种方法是协同过滤。我们有我们的项目和我们的用户。如果我们将它们放在一个矩阵中(以 Spotify 为例),它可能是这样的:

在应用了矩阵分解算法之后,我们最终得到了用户向量和歌曲向量。为了找出哪些用户的口味与另一个最相似,协作过滤将一个用户的向量与所有其他用户的向量进行比较,最终找出最匹配的用户。Y 向量也是如此,歌曲:你可以将一首歌曲的向量与所有其他歌曲的向量进行比较,找出哪些歌曲与所讨论的歌曲最相似。

另一种方法是从自然语言处理领域的应用中获得灵感。研究人员将谷歌在 2010 年代早期开发的 word2vec 算法推广到所有出现在类似上下文中的实体。在 word2vec 中,通过直接考虑词序及其共现来训练网络,这是基于这样的假设,即在句子中频繁出现的词也共享更多的统计相关性。正如 Airbnb 在他们关于创建列表嵌入的博客文章中所描述的:

最近,嵌入的概念已经从单词表示扩展到 NLP 领域之外的其他应用。来自网络搜索、电子商务和市场领域的研究人员已经认识到,就像可以通过将句子中的单词序列视为上下文来训练单词嵌入一样,可以通过将用户动作序列视为上下文来训练用户动作的嵌入。例子包括学习被点击或购买的物品的表示或者被点击的的查询和广告。这些嵌入随后被用于网络上的各种推荐。

除了 Airbnb,这个概念还被 Instagram (IG2Vec)用于学习账户嵌入,被 YouTube 用于学习视频嵌入,被 Zillow 用于学习分类嵌入。

另一种更新颖的方法被称为图形学习,它被 Uber Eats 用于他们的菜肴和餐馆嵌入。他们在一个单独的图中表示他们的每个菜肴和餐馆,并应用 GraphSAGE 算法来获得各自节点的表示(嵌入)。

最后但同样重要的是,我们还可以学习嵌入,作为我们目标任务的神经网络的一部分。这种方法可以为您的特定系统定制一个嵌入,但是可能比单独训练嵌入需要更长的时间。 Keras 嵌入层是实现这一点的一种方式。谷歌在他们的机器学习速成班中很好地涵盖了这一点。

一旦我们有了项目的矢量表示,我们就可以简单地使用最近邻搜索来找到我们的潜在候选对象。
Instagram,例如,定义了几个种子账户(人们过去互动过的账户),并使用它们的 IG2Vec 账户嵌入来寻找类似的账户。根据这些帐户,他们能够找到这些帐户发布或参与的媒体。通过这样做,他们能够过滤数十亿个媒体项目,然后从池中抽取 500 个候选项目,并将这些候选项目发送到下游的排名阶段。

这个阶段也可以由业务规则或用户输入来指导(我们拥有的信息越多,我们就越具体)。例如,正如 Uber Eats 在他们的博客文章中提到的,预过滤可以基于地理位置等因素。

所以,总结一下:

在候选生成(或采购)阶段,我们会从整个内容目录中筛选出用户可能感兴趣的一小部分内容。要做到这一点,我们需要将我们的项目映射到一个称为嵌入的数学表示中,这样我们就可以使用相似性函数来找到空间中最相似的项目。有几种方法可以实现这一点。其中三个是协作过滤、用于实体的 word2vec 和图形学习。

等级

让我们回到 Instagram 的案例。在候选生成阶段之后,我们有大约 500 个潜在相关的媒体项目,我们可以在用户的“探索”提要中显示给用户。
但是哪些会是
最相关的

因为毕竟“探索”版块首页只有 25 个点。如果第一个项目很糟糕,用户就不会留下深刻印象,也不会有兴趣继续浏览。网飞和亚马逊 PrimeVideo 的网络界面只在首页显示与目录中每本书相关的前 6 个推荐。 Spotify 的 Discover Weekly 播放列表只包含 30 首歌曲。
此外,所有这些都取决于用户的设备。当然,智能手机的相关推荐空间比网络浏览器小。

“有许多方法可以构建排名函数,从简单的评分方法到成对偏好,再到整个排名的优化。如果我们要将这个问题公式化为机器学习问题,我们可以从历史数据中选择正面和负面的例子,并让机器学习算法学习优化我们目标的权重。这一系列机器学习问题被称为“学习排名”,是搜索引擎或广告定位等应用场景的核心。在排名阶段,我们的目标不是让我们的项目具有全球概念的相关性,而是寻找优化个性化模型的方法(摘自 【网飞博文 )。

为了实现这一点, Instagram 使用三阶段排名基础设施来帮助平衡排名相关性和计算效率之间的权衡。在 Uber Eats 的案例中,他们的个性化排名系统是“一个成熟的 ML 模型,它根据额外的上下文信息,如用户打开 Uber Eats 应用程序时的日期、时间和当前位置,对预过滤的菜肴和餐馆候选进行排名”。通常,模型的复杂程度实际上取决于特征空间的大小。许多监督分类方法可用于排序。典型的选择包括逻辑回归、支持向量机、神经网络或基于决策树的方法,如梯度推进决策树(GBDT)。另一方面,近年来出现了大量专门为学习排序而设计的算法,如 RankSVM 或 RankBoost。

总结一下:

在为我们的推荐选择初始候选项之后,在排名阶段,我们需要设计一个排名函数,根据项目的相关性对其进行排名。这可以表述为一个机器学习问题,这里的目标是为每个用户优化一个个性化的模型。这一步很重要,因为在大多数界面中,我们推荐项目的空间有限,所以我们需要充分利用空间,将最相关的项目放在最上面。

基线

至于每一个机器学习算法,我们需要一个好的基线来衡量任何变化的改善。一个好的基线是使用目录中最受欢迎的商品,正如 Amazon 所描述的:

“在推荐领域,有一条基本原则。如果我对你一无所知,那么推荐给你的最好的东西就是世界上最受欢迎的东西。”

然而,如果你甚至不知道什么是最受欢迎的,因为你刚刚推出了一个新产品或新项目——就像 Airbnb Experiences 的情况一样——你可以每天随机重新排列项目集合,直到你为你的第一个模型收集了足够的数据。

这是本系列第 1 部分的总结。在这篇文章中,我想强调几点:

  • 推荐系统是机器学习最有价值的应用,因为它们能够创建一个良性的反馈循环:越多人使用公司的推荐系统,它们就越有价值,越有价值,就越有人使用。一旦你进入那个循环,天空就是极限。
  • 正确的问题表述是关键。
  • 在网飞价格挑战中,团队试图建立模型来预测用户对给定电影的评级。在“现实世界”中,公司使用更复杂的数据输入,这些数据可以分为两类:显式数据和隐式数据。
  • 在当今世界,推荐系统不仅仅依赖于协同过滤。

在第二部分,我将介绍:

  • 评估指标
  • 用户界面
  • 冷启动问题
  • 探索与开发

看看下面的第二部分:

** [## 推荐系统:机器学习最有价值的应用

为什么推荐系统是机器学习最有价值的应用,以及机器学习如何驱动…

towardsdatascience.com](/recommender-systems-the-most-valuable-application-of-machine-learning-2bc6903c63ce)**

资源

Airbnb —在搜索排名中列出嵌入内容

Airbnb——基于机器学习的 Airbnb 体验搜索排名

亚马逊—Amazon.com 推荐的单品到单品协同过滤

亚马逊——亚马逊推荐算法的历史

Instagram——由人工智能支持:insta gram 的探索推荐系统

LinkedIn——LinkedIn 的浏览器地图:协同过滤

网飞—网飞推荐:超越五星(上)

网飞—网飞推荐:超越五星(下)

网飞——网飞推荐系统:算法、商业价值和创新

网飞——学习个性化主页

潘多拉——潘多拉的音乐推荐者

Spotify——探索周刊:Spotify 怎么这么了解你?

Spotify——只为你的耳朵:用机器学习个性化 Spotify Home

Spotify——从想法到执行:Spotify 的《发现周刊》

Twitter —嵌入@Twitter

Uber Eats——用 Uber Eats 发现食物:向市场推荐

Uber Eats——用 Uber Eats 发现食物:使用图形学习来增强推荐功能

YouTube——YouTube 视频推荐系统

YouTube——推荐系统的协作深度学习

YouTube——用于 YouTube 推荐的深度神经网络

Zillow —相似住宅推荐的住宅嵌入

吴恩达的机器学习课程(推荐系统)

谷歌的机器学习速成班——嵌入

范登布鲁克·朱丽叶✍️的编辑评论

使用 LinUCB 的推荐系统:一种上下文多臂 bandit 方法

原文:https://towardsdatascience.com/recommender-systems-using-linucb-a-contextual-multi-armed-bandit-approach-35a6f0eb6c4?source=collection_archive---------5-----------------------

推荐系统

使用分离 LinUCB 算法最大化用户交互的推荐系统的上下文多臂 bandit 方法分析

什么是多臂土匪问题?

多武器强盗问题,本质上,只是一个重复的试验,其中用户有固定数量的选项(称为武器),并根据他选择的选项获得奖励。比方说,一个企业主有 10 个特定产品的广告,必须在网站上展示其中一个广告。回报是通过观察广告是否有利可图足以让用户点击并被重定向到产品网站。

企业主为前 1000 个用户运行算法,以从 10 个可用广告中决定最佳广告,并且在他的试运行结束后,决定向其余用户显示最佳广告。该算法基于广告在试运行(前 1000 个用户)中的表现来评估最佳广告

这是我们开始思考的地方。一个广告真的能满足广大多样的受众吗?

这就是语境土匪的用武之地。如果我们对用户有足够的了解,我们可以更准确地预测最适合用户的广告,这就是上下文 MAB 算法的作用。基于用户的特征选择广告(arm)(称为上下文)。在我们继续分析这种算法之前,我们需要思考一些事情。

勘探与开采

在探索和开发之间做出选择的困境存在于生活的各个方面。

比方说,你去街角的冰淇淋店买你最喜欢的口味——巧克力 T21。你不尝试其他口味,因为你害怕你可能不喜欢它们。但是,也有一个小概率,如果你尝试一种新的口味,比如说 r ed velvet ,你可能最终会比巧克力更喜欢它。在尝试新口味(探索)和总是得到你最喜欢的(探索)之间取得平衡是很重要的。

MAB 算法必须在选择随机臂(可能最终成为最佳臂)或利用其历史选择它认为是最佳的臂(可能只是次优臂,因为最佳臂可能还没有被充分探索)之间找到确切的折衷

在线推荐系统试图使用这种算法,根据用户在网站上的活动记录,显示他们认为用户会喜欢的内容。

我们稍后将构建的一个这样的算法被称为置信上限算法

UCB 算法

解决多臂强盗问题的一个非常天真贪婪的方法是,在任意打破平局的情况下,选择给我们最大平均奖励的臂。尽管这种方法试图选择最佳的可能 arm,但是算法失去了探索的范围,并且从长远来看可能选择次优 arm,因为可能有 arm 没有被充分尝试,但是可能是最佳选择。

UCB 算法超越了这种方法,在探索和开发之间找到了平衡。它是这样工作的。

UCB 算法跟踪到目前试验为止每只手臂的平均奖励,并计算每只手臂的置信上限。上界表示中的不确定性,我们评价手臂的潜力。

如果一个 arm 具有非常高的置信上限,并且由于巨大的探索机会而选择该 arm,则该算法对于该 arm 的潜力是高度不确定的。

考虑一个运行中的 UCB 算法,其当前置信界限(虚线轮廓)如下图所示。

对任意试验 x 的 UCB 算法的表示

尽管第 3 组记录的平均奖励较高,但算法选择第 2 组是因为其潜在的的不确定性,并更新其未来试验的置信界限。

UCB 算法不考虑用户的用户和内容特征(上下文),内容特征可能包括用户的历史活动和公开的人口统计信息。

LinUCB

上下文 MAB 问题的开发/探索问题被形式化如下:

来源:https://arxiv.org/pdf/1003.0146.pdf

假设手臂的期望收益在其 d 维特征向量 X 中是线性的,具有某个未知的系数向量θ。

来源:https://arxiv.org/pdf/1003.0146.pdf

这个模型被称为不相交,因为参数不在不同的分支之间共享。为了求解上述方程中的系数向量θ,将岭回归应用于训练数据。

必须为每个臂计算置信上限,以便算法能够在每次试验中选择一个臂。每次试验选择手臂的策略 t 正式确定为:

来源:https://arxiv.org/pdf/1003.0146.pdf

该算法的目标是最大化总回报(从长远来看,总用户点击量)

该算法由其作者形式化如下:

来源:https://arxiv.org/pdf/1003.0146.pdf

我们不详述算法的数学,但我们关注我通过在标准数据集上模拟该算法所获得的结果。

通常,MAB 问题是在遗憾的基础上分析的,遗憾是总是选择最优臂所获得的总报酬与算法所获得的总报酬之差。

下面的甜甜圈图显示了如果我们只选择一只手臂(并将其视为最佳手臂)我们可以获得的最大奖励的比较。该图表明,不管选择的最优策略是什么,如果我们在决策中不表现出灵活性,我们最多可以获得总回报的 20%。这种类型的比较在现实生活中通常是不可能的,因为我们事先无法获得全部数据,但这有助于我们认识到这样一个事实,即我们不能只依赖一个最佳手臂。

当每只手臂分别被选为最佳手臂并用于每次试验时,所获得的总奖励的比较

在每次试验中,LinUCB 算法在决定手臂的选择方面做得非常好,下图也反映了这一点。它将每只手臂可能实现的最大奖励与每只手臂实际实现的奖励进行比较。结果表明,我们能够开发每个手臂高达 90%的潜力。

每只手臂可实现的最大奖励与使用 LinUCB 实现的奖励

推荐系统可以直接建模为上下文 MAB 问题,其中不同的推荐选项是手臂,用户是否喜欢推荐可以转化为奖励,最终目标是能够向每个用户提供个性化推荐。

CMAB 算法与基于用户偏好的各种过滤技术相结合,以实现更加个性化的推荐。

总结

LinUCB 算法使我们能够获得大约 90%的总回报,这比其他 MAB 算法高得多。推荐系统是一个非常重要的用例,其中奖励通常转化为更高的收入,这是企业的最终目标。

参考

  • 萨顿,理查德 s 和巴尔托,安德鲁 g,《强化学习——介绍》http://incompleteideas.net/book/the-book-2nd.html
  • 个性化新闻文章推荐的语境化方法https://arxiv.org/pdf/1003.0146.pdf

推荐系统:价值取向、强化学习和伦理

原文:https://towardsdatascience.com/recommender-systems-value-alignment-reinforcement-learning-and-ethics-625eefaaf138?source=collection_archive---------43-----------------------

推荐是一种游戏——一种危险的游戏(对我们来说)。

这个故事出现在我在 民主化自动化 写的关于让自动化和 AI 变得可及和公平的每周文章中。

这包括对在线推荐系统的简要介绍,这种系统的道德规范,我们可以制定人类奖励的方法,以及将人类推荐视为缓慢更新的批量强化学习问题的观点(在游戏中,我们的奖励甚至不在循环中)。

来源—作者。

推荐系统概述

可以说是新闻反馈系统。推荐系统(维基百科对我来说有最中肯的总结)决定给我们什么内容,这是我们的个人资料数据和我们过去互动的函数。根据界面(移动与桌面)和平台(应用程序、操作系统、网页),交互可以包括许多内容。经常被吹捧为对该技术做出最大贡献的网飞有一个网页描述了他们在该领域的一些研究。

这些系统使用什么样的机器学习?2015 年的一项调查发现,很多应用使用了决策树和贝叶斯方法(因为它们给你可解释性)。仅仅两年后,就有了一项关于专门深度学习方法的调查。我认为许多公司都在使用神经网络,并接受以牺牲可解释性为代价来大幅提高性能的折衷方案— 他们不会告诉客户为什么他们会看到某些内容,对吗?

我画了一个有趣的图表作为你的基线,它将在整篇文章中展开。这是一种不完全的强化学习框架,主体采取行动 a - >环境移动到状态 s - >返回奖励 r

来源—作者。

点击直通 led 以点击诱饵

点击率(一种参与和回报的启发式方法)是早期用于创建推荐的指标。clickbait 问题(打开链接,立即关闭)导致页面停留时间度量。我已经被 clickbait 网站彻底击垮了,所以我创建了这个直接面向读者的博客。这对我来说只是表面效应,我相信还有更多。有一段时间,脸书的衡量标准是“点击分享”按钮的使用——好吧,你说到点子上了。

我在上周的机器学习国际会议上发现了一篇来自研讨会的论文,内容是关于机器学习的参与式方法(当你仔细观察时,会发现有许多很棒的论文可以借鉴,我很可能会重温) 。当你看到块引号时,它们来自 你在优化什么?使推荐系统与人类价值观相一致。阿尔,2020。有一些关于如何使用和部署系统的大背景。

如今大多数大型生产系统(包括 Flipboard (Cora,2017 年)和脸书(Peysakhovich & Hendrix,2016 年))转而在人类标记的 clickbait 上训练分类器,并使用它们来测量和降低系统内 clickbait 的流行率。

当生成的内容超过标记能力时,人工标记的内容是一个瓶颈。此外,在部署时标记分类器会立即过时(不断移动测试集)。也有公司不会描述他们如何操作。关于行业使用,我发现另一个有趣的地方是:

Spotify 以阐述音乐平台面临的公平和多样性问题而闻名。他们的推荐系统本质上是一个双边市场,因为艺术家必须以满足双方的方式与用户匹配,否则双方都不会留在平台上。

下面是显而易见的评论,但却是必不可少的。

尤其是在过滤社交媒体和新闻内容时,推荐者是公众讨论中的关键调解人。Twitter 试图创建“健康对话”指标,目标是“为鼓励更具建设性的对话提供积极的激励”(Wagner,2019)。

我对所学模型的印象是:如果大公司都这么做,那是因为它管用。还是那句话,不要假设 malintent,假设利润。现在我们已经介绍了这些公司如何利用他们的平台让我们沉迷于他们的广告,这里是我们模型的一个小更新——一个反馈回路和双向箭头。

来源—作者。

推荐系统的伦理

我们的计算机正在决定把什么放在我们面前,主要是为了让公司把我们作为可靠的客户。什么会出错?机器人给你推荐什么你没意见?你的社交媒体内容——好的。我如何决定我的职业道路——我不知道。

我不责怪公司制造这些工具并把它们放在我们面前——他们毕竟想赚钱。随着负面影响在未来几年内不断加剧,这些问题将成为人们关注的焦点。以下几点是我认为公司没有达到足够高的标准:

  • 金融科技(Fintech)公司:操纵你的大脑以不同的方式参与金融产品,这对没有一定财务稳定性的人产生了更戏剧性的影响。
  • 高流量媒体平台:除了你每天上网时间的简单点,或者谷歌如何支配你看到的一切,科技公司已经试图在发展中国家成为互联网。点击链接,看看当脸书试图成为印度的互联网时发生了什么(尽管他们很好地包括了维基百科!).
  • 新闻来源:主流新闻编辑室(当然还有边缘网站,以及介于两者之间的一切)使用自动化方法来调整给你的新闻。我看到未来他们会调整写作风格,以更好地符合你的观点。因循守旧不是进步。

我想从 at-scale,面向人类的人工智能中被称为价值对齐问题开始(关于法律合同、人工智能和价值对齐的示例论文哈德菲尔德-梅内尔&哈德菲尔德,2019 )。

与人类受试者一起工作的低级伦理

我在这里将伦理问题定义为短期结果(下面强调)和由算法控制生活的人类的长期精神重组。

对推荐系统的关注包括宣传造谣( 斯托克,2019 )、歧视性或其他不公平的结果( 巴罗卡斯等人,2019 )、成瘾行为( 哈桑等人,2018)(安德瑞森,2015)

流浪 et。al,2020 继续并介绍推荐器对齐问题。由于技术在我们生活中的普及,这是一个特定版本的价值取向问题,它可能会增加出现的机会。如果在这一点上你没有考虑他们如何影响你,你有没有仔细阅读?最后,调整的三阶段方法:

我们观察到一种常见的三阶段对齐方法:1)识别相关的内容类别(例如,点击诱饵);2)这些类别被操作为进化的标记数据集;以及 3)根据该数据训练的模型用于调整系统建议

这可以概括为识别(内容和问题)、操作化(模型和数据)、调整部署。这听起来与机器学习模型的部署方式相对接近,但下面会详细介绍。

高级推荐系统调整:

高层次的想法同样来自报纸,但评论是我自己的。

  1. 有用的定义和衡量标准——公司需要对互联网指标进行研究,以更好地匹配用户期望和累积伤害(或提升!)
  2. 参与式推荐者——让人们参与到内容的循环中,将使人类的回报与模型化的回报更好地匹配,这从长远来看是值得的。
  3. 互动价值学习— 这是最重要的问题,它可能包含所有其他问题。最终,假设奖励函数是一个分布,极端剥削会显著减少(更多见下文)
  4. 围绕知情、审慎的判断进行设计——这对我来说似乎是显而易见的,但请不要假新闻。

让我们继续第三点。

模拟人类奖励

被定义为 的 优化问题和真正的 优化问题 之间的交互是在与人类的安全交互中应用机器学习系统的长期战斗。

现在大多数机器学习工具使用的模型是优化人类给计算机的奖励函数。标准模型(Russell—Human Compatible,2019 )无非是一个优化问题当某个奖励函数上的度量改善时,结果会改善。当我们考虑比较多个人的权衡回报(幅度和方向)时,这一点完全失败了,人工智能将利用未提及的行动途径(我告诉机器人我想要咖啡,但最近的咖啡店是 12 美元,这不是我想要的结果,但它“做到了”),以及更多有害的未建模效应。

更好的方法是什么?更好的方法是再次,互动价值学习。价值学习是一个框架,它将允许我们制造的人工智能永远不要假设它们拥有人类想要的完整模型。如果一个人工智能只认为它有 80%的机会做出正确的行为,那么它在保持高预期效用的行动中会更加胆怯(我认为 20%的机会包括一些非常负面的结果)。推荐系统也需要考虑这一点,否则,我们将在一个我们几乎无法控制的游戏中螺旋上升。

人和计算机在循环中的强化学习

强化学习是一个迭代框架,其中代理通过行动与环境交互以最大化回报。强化学习(RL)在受限游戏中取得了很大的成功。在这种情况下,有两个“游戏”框架。

  1. 应用程序是代理,人是状态空间的一部分(实际上更适合问题的表述)
  2. 人类是代理,计算机,世界是环境,而回报是很难建模的。这个更有说服力,所以我继续。这就是我在标题中提到的游戏

来源—作者。

最终,FAANG 公司将记录所有的流量数据(包括我们之前谈到的对真实人类奖励的启发),并尝试学习您的设备应该如何与您交互。这是一个复杂的系统,在反馈回路中,你与之互动的每个人都有的下游效应。作为一名 RL 研究员,我知道算法是脆弱的,我不希望这种情况发生在我身上(但我经常努力摆脱自己)。上图是最重要的一点——单个实体不可能设计一个优化来“解决”这个网络。

先说数据和建模。据我所知,FAANG 还没有使用 RL,但他们正在获取一个大型数据集来潜在地这样做。从状态、行动和奖励的大型数据集到新政策的过程被称为批量强化学习(或离线 RL)。它试图将无序行为的历史提炼为最优策略。我对科技公司的应用程序的看法是,他们已经在玩这个游戏,但 RL 代理并不决定推荐系统的更新,而是由一组工程师来决定。唯一可能的情况是,也许抖音的黑匣子已经转向优先考虑收视率的 RL 算法。如果推荐系统将成为强化学习的问题,伦理解决方案需要尽快出台。

这里是对批量 RL 课程材料、离线 RL 研究和现实世界 RL 的广泛挑战感兴趣的读者的资源。

* [## 自动化大众化

一个关于机器人和人工智能的博客,让它们对每个人都有益,以及即将到来的自动化浪潮…

robotic.substack.com](https://robotic.substack.com/)*

基于已阅读的文章推荐新闻文章

原文:https://towardsdatascience.com/recommending-news-articles-based-on-already-read-articles-627695221fe8?source=collection_archive---------18-----------------------

Python 中基于内容的推荐

由于在你最喜欢的在线平台上很容易获得大量的商品(服务),如电子商务求职门户送餐音乐或视频流,快速找到你选择的所需商品是非常困难和耗时的。这些平台可以通过分析你过去与系统的互动或行为,根据你的兴趣和偏好推荐商品来帮助你。

亚马逊Linkedin优步吃Spotify网飞脸书推荐系统被最广泛地用于向他们的用户推荐“相似的项目”、“相关的工作”、“喜欢的食物”、“感兴趣的电影”等等。

推荐系统 提供适当的商品建议,有助于促进销售、增加收入、留住客户并增加竞争优势。推荐方法基本有两种。

  1. 基于内容的推荐
  2. 协同过滤

基于内容的推荐 基于通过用户 属性 获得的用户/项目之间的相似度。它使用关于 用户条目 的附加信息(元数据),即它依赖于什么样的 内容 已经可用。该元数据可以是用户的 人口统计信息 ,如年龄性别工作位置技能集、等。同样,对于 项目可以是项目名称规格类别登记日期、等。

所以其核心思想就是根据物品的属性,通过找到与关注的 物品/用户 相似的物品/用户来推荐物品。

在这篇博客中,我们将使用新闻类别数据集来讨论基于内容的推荐。目标是通过使用诸如文章标题类别作者出版日期等属性来推荐与已阅读文章相似的新闻文章。**

那么让我们开始使用 Kaggle 上可用的 新闻类别数据集。数据集包含大约 20 万个对 6 个不同特征的观察,如新闻标题类别作者简短描述出版日期、等。**

附加说明:为了访问完整的 python 代码,请访问 kaggle 内核这里(https://www . ka ggle . com/vikashrajluhaniwal/recommending-news-articles-based-on-read-articles)。

1.数据预处理

  • 仅获取 2018 年 的文章——由于数据集大小相当大,因此处理整个数据集可能会耗费太多时间。为了避免这种情况,我们只考虑 2018 年的最新文章。
  • 移除所有短标题文章****——从标题中移除停用词后,标题非常短的文章可能会变成空白标题文章。所以我们把标题里字数少(< 5)的文章都去掉吧。
  • 检查并删除所有重复的——由于有些文章的标题完全相同,所以让我们删除所有标题重复的文章。**

2。基础数据探索

a .基本统计—文章数量、作者、类别

经过数据预处理后,共有 892 位作者的 8485 篇新闻文章,分属 26 个不同的类别。

b .文章类别分布

从条形图中,我们可以观察到politics类别的文章数量最高文章数量次之entertainment文章数量最高,以此类推。

c .每月文章数量

从柱状图中,我们可以观察到January 月的文章数量最高,然后是March等等。

d. PDF 为标题长度

标题 length概率分布函数几乎类似于高斯分布,其中标题的大部分长度为 58 到 80 个字。**

3.文本预处理

  • 停用词移除 停用词对分析没有太大帮助,而且包含停用词会在处理过程中耗费大量时间,所以让我们移除它们。
  • 引理化— 让我们找到单词的基本形式(引理)来考虑与引理相同的单词的不同屈折。

4.基于标题的新文章相似度

通常,我们根据距离来评估相似度。如果距离最小,则高相似度,如果最大,则低相似度。为了计算距离,我们需要将标题表示为一个 d 维向量。然后我们可以根据向量之间的距离找出相似度

有多种方法将一个文本表示为一个 d 维向量,如单词包TF-IDF 方法Word2Vec 嵌入、等。每种方法都有自己的优缺点。

我们一个一个的通过所有的方法来看头条的特征表现。

a .使用包字法

单词包(BoW) 方法表示单词在文档中的出现。在这里,每个标题可以被认为是一个文档,所有标题的集合形成一个语料库。**

使用的方法,每个文档由一个 向量表示,其中 是语料库中唯一词的总数。这一组独特的单词构成了词典。

以上功能基于标题推荐 10 篇查询(阅读)文章相似的文章。它接受两个参数——已读文章的索引和要推荐的文章总数。

基于欧几里德距离它找出 10 个最近的邻居并推荐。

缺点

  1. 它对语料库不太频繁观察到的单词赋予很低的重要性。在整个语料库中,employerflipfire等被查询文章中的几个词出现的频率较低,因此 BoW 方法不会向推荐 headline 包含这些词的任何文章。由于trump语料库中常见的词,所以它推荐标题包含trump的文章。
  2. **鞠躬方法不保留单词的顺序。

为了克服第一个缺点,我们使用 TF-IDF 方法进行特征表示。

b .使用 TF-IDF 方法

TF-IDF 方法是一种加权方法,它赋予语料库中不太常用的词更多的重要性。它根据术语频率(TF)逆文档频率(IDF)为文档中的每个术语(单词)*分配一个权重。*

因此,如果一个单词在一个文档中出现的次数更多,但在所有其他文档中出现的次数更少,那么它的 TF-IDF 值将会很高。

相比于 BoW 方法,这里 TF-IDF 方法推荐标题的文章中包含类似employerfireflip的词在前 5 位推荐,这些词在语料库中出现频率较少

缺点

  • BowTF-IDF 方法不捕获给定单词与其他单词的语义句法相似性,但这可以使用嵌入 的 单词来捕获。例如,trumpwhite houseofficeemployeetigerleopardUSAWashington D.C等词之间就有很好的联想。使用单词嵌入技术可以捕获这种语义相似性。
    单词嵌入技术像 Word2VecGloVefastText 利用
    语义单词之间的相似性。
    **

c .使用 Word2Vec 嵌入

Word2Vec语义相似度的技术之一,由 Google 于 2013 年发明。对于给定的语料库,在训练过程中,它观察模式,并用一个 d 向量来表示每个单词。为了得到更好的结果,我们需要一个相当大的语料库。

由于我们的语料库规模很小,所以让我们在谷歌新闻文章上使用谷歌的预训练模型。这个标准模型包含通过对数百万篇新文章进行训练而获得的数十亿个单词的向量表示。在这里,每个单词用一个 300 维的密集向量来表示。

由于模型给出了每个单词的矢量表示,但是我们计算了标题之间的距离,因此我们需要获得每个标题的矢量表示。一种方法是首先将标题中所有可用单词的矢量表示相加,然后计算平均值。也被称为平均 Word2Vec* 型号。*

这里,基于 Word2Vec 的表示推荐包含与被查询文章中的trump相关联的white house标题。类似地,它推荐带有与被查询的标题中的employersue具有语义相似性的officialinsist的标题。

注意:到目前为止,我们只推荐使用一个特征,即标题,但是为了使推荐系统更加健壮,我们需要一次考虑多个特征。基于商业利益和规则,我们可以决定每个特征的权重。

让我们来看看不同的型号与不同的功能组合的文章相似性。

d.基于标题和类别的加权相似度

我们先来看看基于标题类别的文章相似度。我们使用一键编码来获得类别的特征表示。

有时根据业务需要,我们可能需要更多地优先考虑来自同一类别的文章。在这种情况下,我们可以在推荐时给类别分配更多的权重。权重越高,意义越大。同样,权重越小,特定特征的重要性就越小。

上述函数采用两个额外的参数 w1w2 作为对应于标题类别的权重。在从 0 到 1 的范围内传递重量始终是一个好的做法,其中接近 1 的值表示重量大,而接近 0 的值表示重量小。

在这里,我们可以观察到推荐的文章与查询的文章类别来自同一个类别。这是由于高值传递到 w2

e.基于标题、类别和作者的加权相似度

现在让我们来看看基于作者以及标题类别计算文章相似度。同样,我们通过一次性编码作者进行编码。

上面的函数为作者多了一个权重参数 w3

在输出中,我们可以观察到,由于对 w3 的高权重,推荐的文章来自与查询的文章作者相同的作者

f.基于标题、类别、作者和出版日期的加权相似度

现在让我们来看看基于发布工作日作者以及标题类别、作者计算文章相似度。同样,我们通过一键编码来编码这个新特性。**

上述函数为日和月额外增加了一个权重参数 w4

在输出中,我们可以看到,由于对 w4 的高权重,推荐的文章与查询的文章来自同一个日和月

结束注释

在本文中,我们讨论了不同类型的单词嵌入技术,以及针对基于内容的推荐特征的不同组合,以及与每种技术相关的常见问题。

推荐苏格兰威士忌

原文:https://towardsdatascience.com/recommending-scotch-whisky-ea440c2eb289?source=collection_archive---------31-----------------------

大约一年前,我在苏格兰参加了苏格兰威士忌体验培训课程,获得了苏格兰威士忌销售证书。由于我有数据科学的背景,这导致我思考如何用数据科学来销售苏格兰威士忌。

苏格兰威士忌体验中的威士忌品尝

背景
威士忌是一种深色酒,每一种都有其独特的风味和特点。像酒和咖啡等其他饮料一样。欣赏饮料是一门主观艺术。消费者通常没有受过表达他们想要什么的训练,当消费者对他们偏好的威士忌(甚至是葡萄酒或咖啡)的词汇或描述有限时,很难理解消费者想要什么:这很难做出推荐。在苏格兰威士忌体验教学中,他们建议销售人员使用讲故事的方式与消费者进行对话。我认为这是一个良好的开端,但我们可以通过利用威士忌风味和特征的量化数据做得更多,并根据这些数据学习一个模型,这样卖家可能会有更好的指南来猜测消费者可能喜欢什么。所以我认为我们可以使用一些机器学习的方法来建立一个苏格兰威士忌的推荐系统。

有人可能会问:苏格兰威士忌与美国和爱尔兰威士忌有什么不同?爱尔兰威士忌和苏格兰威士忌的主要区别在于,爱尔兰威士忌蒸馏三次,而大多数苏格兰威士忌蒸馏两次。蒸馏产生的质地差异就像浓缩咖啡和倒出来的咖啡之间的差异。苏格兰的温度变化低于美国大多数威士忌生产州,这在陈年阶段产生了影响。此外,苏格兰威士忌行业的理念是避免桶的太多影响,大多数苏格兰威士忌酒厂都避免使用原桶(意味着他们倾向于使用二手或三手桶)。因此,我们预计美国威士忌,尤其是波旁威士忌,会比大多数苏格兰威士忌味道更浓郁。

苏格兰威士忌需要在桶中陈酿至少 3 年,才能在法律上被称为苏格兰威士忌

推荐系统
我们可以应用的推荐系统主要有两种:协同过滤推荐系统和基于内容的推荐系统。

协同过滤推荐系统是亚马逊目前正在使用的推荐系统。该模型识别消费者群体并学习他们的购物模式,并基于所识别的使用相似的群体推荐用户可能感兴趣的商品。如果我们对威士忌不是很了解,这是推荐威士忌的一个很好的方法,模型能够根据以前消费者的购物偏好进行推荐。不过,我没有这方面的数据。在我看来,这种方法忽视了理解和欣赏威士忌特性的艺术;它只是简单地推荐威士忌的其他消费者如何行为,而不是了解威士忌本身的特性。所以我不会用这种方法来推荐苏格兰威士忌。

基于内容的推荐系统是一种基于两个商品之间的相似性向用户推荐商品的模型。因此,它基于产品本身的数据而不是用户和消费者之间的行为来推荐威士忌。在这篇文章中,我想探索一种从另一种威士忌的内容中推荐威士忌的系统而科学的方法,这种方法可以简化根据威士忌的内容推荐威士忌的过程。

我从 Kaggle 获得了主要苏格兰威士忌酒厂的数据,以及它们的总体量化风味和特征。我还在数据集中添加了经度、纬度和酿酒厂所属的地区,你可以在帖子底部我的 GitHub 链接中找到数据集。威士忌的地区数据基于 Collins gem —威士忌。在这个数据集中,只有单一麦芽威士忌可用。

数据集中的列包括:
1。酒厂——酒厂名称(串)
2。Body(整数,范围从 0–4)
3。甜度(整数,范围从 0-4)
4。药用(整数,范围从 0–4)
5。烟草(整数,范围从 0-4)
6。Honey(整数,范围从 0–4)
7。辣(整数,范围 0–4)
8。Winey(整数,范围从 0 到 4)
9。Nutty(整数,范围从 0 到 4)
10。Malty(整数,范围从 0 到 4)
11。水果味(整数,范围从 0-4)
12。Floral(整数,范围从 0 到 4)
13。邮政编码—酒厂的邮政编码(字符串)
14。LatitudeUTM—UTM 格式的纬度(整数)
15。LongitudeUTM—UTM 格式的经度(整数)
16。Lat — Latitude (Float)(我手动添加的列)
17。Lon —经度(Float)(我手动添加的列)
18。基于柯林斯宝石威士忌(字符串)的酒厂区域分类(我手动添加的列)

威士忌的风味和特点从 0 到 4 分不等。0 表示无,4 表示最重。例如,Islay & Islands 的 Laphroig 在烟雾弥漫方面获得了 4 分,这并不奇怪,因为 Laphroig 是一种非常烟雾弥漫(泥炭)的威士忌。在这个数据集中,有 86 个酒厂的 12 种风味和特征。

有我手动添加到原始数据集的列,即。纬度、经度和地区。我将 UTM 转换成纬度和经度,因为它有助于在 Tableau 的地图上可视化。在 Region 列中,数据集中有 4 个区域:低地、高地、Speyside 和 Islay & Islands。

苏格兰的四个地区:低地、高地、斯佩塞德、伊斯莱和群岛

目标 我想建立一个服务于两个目标的推荐系统:
1。如果有人喜欢一家酒厂生产的威士忌,我可以推荐一种口味相似的威士忌。
2。如果我们有一种威士忌不在数据集中,我可以找出其他类似的威士忌。

工具
在这个项目中,我将使用以下工具和包:

  • Python,连同 pandas,scikit-learn,Plotly
  • Tableau

基于地区的推荐

我偏爱的威士忌是艾莱岛

以前,我是一个葡萄酒爱好者。我们根据地区来鉴别法国葡萄酒。每个地区的葡萄酒都有自己的风味和特色。例如,你可能会期待来自波尔多的酒体饱满,果香浓郁的葡萄酒。天真地说,如果我喜欢一瓶圣爱美浓的葡萄酒,那么很可能我喜欢喝梅多克的葡萄酒。同样在苏格兰威士忌中,如果我喜欢喝来自 Islay 的 Laphoraig,我很可能会喝 Lagavulin,因为 Lagavulin 是来自 Islay 的威士忌。我认为根据地区推荐苏格兰威士忌比推荐法国葡萄酒更有意义,因为苏格兰威士忌的地区系统远没有法国葡萄酒的 AOC 系统复杂。

所以,开始做一个基于地域的推荐系统是明智的。一旦我们训练了一个模型,我们可以将新的威士忌添加到模型中,并区分新威士忌的地区,并根据相同的地区推荐威士忌。

苏格兰威士忌地区分类

如果我们使用这种方法,我们将使用威士忌的风味和特性来学习一个模型来预测威士忌的产地。我使用了四种分类算法来训练模型:逻辑回归、支持向量分类(SVC)、决策树和随机森林。我使用 Python 和 Scikit-learn 来训练模型,并使用 k-fold 交叉验证来确保每种方法的准确性。

结果在这些方法中,用 logistic 回归训练的模型精度最高。然而,logistic 回归模型的准确率仅为 58.10%。准确性太低,以至于数据集中有近一半的威士忌被归类为错误的地区。

你可能会在下面找到贴有错误地区标签的酿酒厂。颜色代表错误分类的区域。

为什么“最佳模型”的精确度仍然很低? 在我看来,该型号性能低下有几个原因。

理由 1:斯佩赛德威士忌和高地威士忌很相似
当斯佩赛德威士忌被错误地归类为高地威士忌,或者被韵文归类时,我不会感到惊讶。斯贝河位于高地(斯贝赛德和高地的分界线直到最近几十年才被划分出来),所以斯贝赛德威士忌和高地威士忌有着非常相似的风味和特征。如果你看看斯派塞威士忌和高地威士忌之间的特征,这些地区之间的数据非常相似。

原因二:数据不平衡。有趣的是,没有一家酒厂被认定为低地威士忌。当我们查看数据集时,只有 3 家低地酒厂!这意味着地区分布首先是不平衡的,因此任何算法都很难预测低地威士忌。

想到这种方法
看来预测威士忌产地的准确性很低。在实践中,该模型并不是推荐威士忌的理想方法,因为它很难识别同一地区威士忌之间的相似性。不值得花时间来设计数据集以实现更高的准确性。因此,我们应该寻找新的方法来建立推荐系统。

树状图
第二种方法是使用树状图来显示酒厂之间的层级关系。树状图是一种层次聚类,这种方法将数据集中的每个特征视为一个维度,并根据风味和特征的相似性对酒厂进行聚类。

用 Python 生成树状图很容易:一旦有了特性和标签(蒸馏厂),就可以将特性和标签传递给 Plotly 在 figure_factory 中的 create_dendrogram,您会发现下面的输出。

系统树图

树状图的 x 轴是数据集中苏格兰威士忌的列表。y 轴代表威士忌之间量化特征的欧几里德距离。例如,如果威士忌 A 具有[1,1,2,3]的特征,而威士忌 B 具有[2,3,4,3]的特征,则两种威士忌之间特征的欧几里德距离是(2–1)+(3–1)+(2–4)+(3–3)的平方根,因此威士忌 A 特征和威士忌 B 特征之间的欧几里德距离是 3。如果两种威士忌之间的特征的欧几里德距离低,则意味着两种威士忌具有相似的味道或风味;如果它很高,这意味着这两种威士忌没有相似的味道或风味。

阅读树状图并不容易。首先,你必须选择一个威士忌品牌,并从那里进行观察。例如,如果我从 Laphroaig 开始,我将关注绿色的星团。

的每个分支代表一个子集群,如图中的棕色线所示。棕色线将威士忌品牌分为两个子群,分别代表红色和黄色方框。要推荐一款与 Laphroaig 相似的威士忌,你会从 Laphroaig 开始寻找,你可能会发现 Lagavulin 与 Laphroaig 最相似,因为连接两种威士忌品牌的分支高度最低。所以,如果有人喜欢 Laphroaig,你会推荐 Lagavulin。如果他不喜欢 Lagavulin,你将把 Lagavulin 和 Laphroaig 作为一个聚类(用红色方框表示),并找到连接 Laphroaig 聚类的下一个分支,即黄色方框中的聚类,然后你会推荐黄色方框中的一种威士忌。然而,现在的问题是:在 Caol Ila、Ardbeg、Clynelish 和 Talisker 中,基于树状图的下一个最佳推荐是什么?

思考这个方法 使用这个树状图有一个很好的理由来推荐苏格兰威士忌。树状图倾向于把最相似的威士忌放在一起。如果我从 Laphroaig 开始,那么我会找到 Lagavulin 并推荐它。或者从塔利斯克开始,最相似的威士忌是克莱恩利什,我会推荐克莱恩利什。

绘制树状图是推荐苏格兰威士忌的好方法吗?我不这么认为。虽然树状图很好地展示了威士忌之间的等级差异,但我不认为这是推荐苏格兰威士忌的好方法。

首先,树状图只显示了最接近的威士忌的相似性。缺点是,如果最相似的威士忌不是一个很好的选择,那么就很难找到第二相似的威士忌。回到上图,树状图只是总结了 Laphroaig 和 Lagavulin 之间的相似性。然而,它并没有告诉你 Laphroaig 和 Caol Ila 之间有多相似,因为没有分支直接链接到这两个威士忌品牌。我们无法判断黄盒中的哪种威士忌与 Laphroaig 下一个最相似,因为我们只被告知红盒聚类和黄盒聚类相似,但没有信息来比较红盒聚类中的一种威士忌和黄盒聚类中的一种威士忌。

第二,树状图很难解释,因为阅读树状图中的分支来理解威士忌之间的关系是令人困惑的。如果这是苏格兰威士忌销售人员使用的工具,很难训练销售人员阅读,因为解释如何阅读树状图并不容易。

最后,如果数据集越来越大,树状图就没有用了。想象一下,如果我们有 100 多个威士忌品牌添加到数据集中,我们将不得不在 x 轴上再添加 100 个威士忌品牌,这样树状图就必须放大以提高可读性。这种方法的局限性是,如果我们有更多的品牌,情节需要更多的空间来显示威士忌品牌之间的关系。这意味着如果数据集中有更多的威士忌,可视化的大小必须更大。因此,我们必须为我们的目标找到另一种方法。

聚类— K 均值 第三种方法是基于量化特征将相似的威士忌聚类成一组。这种方法将威士忌分成不同的组,而同一组中的每种威士忌通常都具有最接近的总体量化特征和风味的平均值。在苏格兰威士忌推荐系统的应用中,这意味着无论哪种威士忌基于量化特征和风味是相似的,我们都将它们分组到同一个组中。这个想法是,如果消费者在你的脑海中有一个苏格兰威士忌,你可以推荐来自同一组的类似威士忌。

k 均值是无监督学习,这很难确定性能。第一个问题是选择最佳超参数,也就是说使用什么样的 K 值最好。幸运的是,您可以使用肘方法来找到最佳 k。为此,首先选择 k 的范围,比方说 1 到 12 之间,包括 1 和 12。然后,使用 Python 和 Scikit-learn 训练模型并获得误差平方和(SSE)。之后,在形成一个臂的折线图上绘制每个模型的 K 和 SSE 的数量。最后,你可能会在手臂的肘部找到最佳的 k。

用肘法求 K

我们可以看到肘部在 4 到 6 之间。从技术上讲,在 4 和 6 之间选择一个数字就可以了。然而,在选择超参数时,我们还必须考虑这种应用的有用性。我们需要考虑团队的规模——每个团队中酿酒厂的数量不能太多,也不能太少。理想情况下,我们希望小组规模均匀,每个小组应该有 10 到 15 个酒厂。

不同 K 值的团簇的大小

我在 3 个条形字符中可视化,以确定哪个超参数符合我们的预期。当 K 为 4 时,我们可以看到大多数组的规模过大;当 K 为 5 时,组的大小是备用的。最后,当 K 是 6 时,每个组的大小是相似的,更接近我们的预期。因此,6 是我们模型的最佳 K。

K = 6 的 K 均值结果
一旦我们算出 K 是 6,就可以用这个超参数来训练模型了。结果看起来像这样:

K=6 时 K 均值模型的结果

我发现第三组的威士忌非常相似。第 3 组中的威士忌烟雾弥漫,我们可以看到,如果一个人喜欢 Ardbeg,他很可能会喝 Lagavulin 或 Laphroaig,因为所有这些威士忌都很有泥炭味。另一个很好的例子是第 4 组的 Glen Garioch 和 Glenrothes,这两款威士忌都含有香草和淡淡的柑橘风味。这种模式并不完美:在我看来,麦卡伦和格伦罗斯是很好的替代品,因为这两种威士忌都是在雪利酒桶中陈酿的。因此,这两种威士忌都具有非常相似的雪利酒风味,但不属于同一类。幸运的是,我们可以发现来自同一组的达尔莫尔含有丰富的水果,雪利酒是麦卡伦的一个很好的替代品;至少模型是有用的。

阿伯丁郡是格伦·加里奥奇的家乡

与树状图相比,这种方法更容易理解,因为我们只需读取同一组中威士忌的列表。解释和训练苏格兰销售人员阅读清单要容易得多。

苏格兰地图上 K=6 时 K 均值模型的结果

如果我们有更多的威士忌数据,我们可以简单地用原始数据集附加观察值,并重新聚类 K 均值模型。该算法能够将新的威士忌数据与具有相似口味的原始数据进行聚类。

K 均值模型实现了我们的目标:我们能够从一种威士忌中推荐具有相似风味的威士忌,并且这种模型能够用原始数据集识别新的威士忌数据。因此,我们可以将该模型用于我们的苏格兰威士忌推荐系统。

冷启动问题
让我们重新考虑一下我们一开始的场景。我们一直在讨论,如果消费者至少有一种他/她喜欢的威士忌,如何推荐一种威士忌。但是,如果一个消费者以前从未喝过 whisk(e)y,如何向他/她推荐喝什么呢?这是推荐一款威士忌时的经典问题。回答这个问题,考虑两种情况:
1。能够描述他/她喜欢什么的人,如葡萄酒爱好者。
2。这个人不知道从哪里开始。

了解这个人喜欢什么是非常重要的,因为这给了你推荐什么威士忌的方向。例如,根据苏格兰威士忌的经验,南欧人很可能能够描述他/她喜欢什么,因为他们丰富的烹饪和饮料文化提供了描述他们拥有或喜欢的食物或饮料的训练。如果他们喜欢果味葡萄酒,你可能会比他们更喜欢果味威士忌。在我们的应用程序中,如果我们没有最喜欢的威士忌,我们可以使用 choose the desired flavor 并提供一个符合标准的威士忌列表。

没关系,威士忌的清单不属于同一个组。我们的目标是找到人们最喜欢的第一种威士忌。一旦我们有了他/她心目中的第一款威士忌,我们就会推荐与我们推荐的第一款威士忌相似的第二款威士忌。

如果这个人不知道从哪里开始,我们会推荐一种不喝威士忌的人都知道的威士忌,并且不含太多刺激性的味道。在这种情况下,如果他/她想要单一麦芽威士忌(或混合威士忌的约翰尼·沃克),我会建议他/她从麦卡伦开始。有几个原因:首先,麦卡伦非常有名,给了苏格兰威士忌初学者信心。第二,我们必须避免烟雾弥漫的威士忌。苏格兰威士忌的经验分享了这个行业的经验,即除非这个人明确表达了他/她的兴趣,否则绝不建议使用烟熏或泥炭威士忌。许多不喝威士忌的人讨厌威士忌,因为有人向他们推荐了烟熏威士忌或泥炭威士忌,他们就再也不会回来了。虽然这样的风味区分了苏格兰威士忌性格的独特性,但并不是所有人都喜欢它,因为这个性格太咄咄逼人了(意思是没有 Islay 威士忌)。麦卡伦是一种斯佩塞德威士忌,烟味不大。第三,麦卡伦以其雪利酒风味而闻名,这种风味为饮酒者提供了一种水果和甜味的口感,这对于威士忌初学者来说更容易接受(人们通常喜欢更甜和水果味的饮料)。

应用

一旦我们弄清楚使用什么工具和算法,并准备好数据,我们就可以将酿酒厂分成 6 组,并使用结果来推荐威士忌。我们可以构建一个应用程序,允许推荐者获取威士忌列表进行推荐。当我们推荐威士忌时,有三种情况我们必须考虑。消费者有他/她最喜欢的威士忌,并希望找到一种类似的。
2。消费者不知道任何威士忌,但他/她知道他/她喜欢什么口味。
3。消费者什么都不知道。

案例 1:消费者有他/她最喜欢的威士忌,想找一款相似的。

如果我输入 Bowmore,应用程序会列出这样的结果

在这种情况下,我们简单地推荐一种与威士忌消费者喜欢的威士忌非常相似的威士忌。该应用程序将返回同一组威士忌的列表。列表有两种排序方式。

我们假设如果两个酿酒厂彼此靠近,威士忌就有相似的味道。威士忌列表将按照输入的威士忌和类似威士忌之间的物理距离来排序,以反映该假设。

例如,如果我们输入“Bowmore ”,应用程序将返回类似威士忌的列表。因为 Bruichladdich 是离 Bowmore 最近的酿酒厂,所以,Bruichladdich 排在了名单的第一位。

如果我进入鲍莫尔,高地公园的味道和鲍莫尔很像

另一种方法是根据味道的相似性进行分类。相似性通过量化的风味和特征(两种威士忌的风味和特征的标准)的欧几里德距离来计算。

比如我们输入“Bowmore”,列表会按照 Highland Park,Springbank…等进行排序,因为 Bowmore 和 Highland Park 之间的风味和人物欧氏距离最短,其次是 spring bank。这是一个更好的方法,因为列表是按照威士忌的含量排序的。

案例二。消费者不知道任何威士忌,但他/她知道他/她喜欢什么口味。

在对特征进行挑选和评分后返回列表

在这种情况下,我们的目标是找出最符合消费者偏好的威士忌。该应用程序将列出我们在数据集中拥有的所有功能,并要求消费者选择一个,并在 1-4 之间评分(不能选择 0),分数代表:轻,中,强和非常强。

一旦消费者选择了该功能并对其评分,应用程序就会过滤出符合消费者偏好的威士忌列表。

如果我们没有任何符合要求的威士忌,应用程序会降低分数以返回一个味道较淡的列表(我们假设人们更可能接受较淡的味道而不是较重的味道)。例如,在我们的数据集中,没有一种威士忌的烟草得分为 4。如果我们输入这个,应用程序会通知我们它会降低分数,并返回一个烟草分数低于 4 的威士忌列表。威士忌的清单是按字母顺序排列的,很可能不在同一个组中。从这里开始,它需要推荐者和消费者之间的工作,通过推荐者的领域专业知识来找出消费者喜欢哪种威士忌。然而,该应用程序使推荐者的生活变得更容易,因为该应用程序已经从一个更大的选择池中筛选出一个更小的列表。

3.消费者什么都不知道。

如果不知道,选择麦卡伦!

正如我们已经讨论过的冷启动问题,如果消费者对威士忌没有概念,也没有选择口味,那么推荐我们讨论过的麦卡伦!

是的,我没有在 GUI 中构建这个应用程序,我也不打算这样做。该应用可以嵌入到网站或其他应用中。

该模式/应用的缺点和思考

这种模式存在问题。
1。对每个酿酒厂的一个观察

Lore 的味道非常甜,与 10 年的标签不同

数据集只提供了每个酒厂的概况。例如,在 Laphroaig 中有很多标签。我们来对比一下 Laphroiag 10 年和 Laphroaig 绝杀。虽然两种标签都是泥炭味,但 10 年标签提供了一种侵略性的烟熏味以及海藻和梨的味道,而 Lore 标签的味道类似于波特酒,并提供了相对水果味。如果一个人喜欢绝杀的标签,他/她可能不喜欢 10 年的标签;当推荐 Laphroaig 时,这个人可能不喜欢 Laphroaig 中的每个标签。

甚至有人建议你买一瓶 Bowmore,但我该挑哪一瓶呢?

2.数据是如何收集的?
人们关心的是如何获得特征的得分。如果分数是由一个以上的评委投票,我们会担心评委的不同观点可能会导致不准确的评分。但是,即使分数是由一个裁判指定的,我们也会担心裁判在指定分数时可能会有偏差。因此,我们必须意识到数据质量可能达不到我们的预期,从而导致对模型/应用程序性能的担忧。使用模型/应用程序时,用您在苏格兰威士忌领域的专业知识验证结果。

3.只有单一麦芽威士忌可用
数据集中只有单一麦芽威士忌数据可用。如果我们加入混合苏格兰威士忌,我们就没有机会检验其性能。

4.仅限苏格兰威士忌
这是一个基于内容的推荐系统。从根本上说,爱尔兰威士忌与苏格兰威士忌的制作方式不同。因此,不建议添加爱尔兰威士忌、美国威士忌、波旁威士忌或日本威士忌的数据,因为这些威士忌的总体特征与苏格兰威士忌不同。例如,波旁威士忌需要在新桶中陈酿,但苏格兰威士忌很少在新桶中陈酿,因为波旁威士忌和苏格兰威士忌的陈酿理念不同。因此,波旁威士忌具有侵略性的特征,而苏格兰威士忌则具有温和的味道。我认为这个数据集中的合格风味不能反映这种差异(更不用说波旁威士忌和苏格兰威士忌之间有更多不同的特征),因此,建议将数据仅限于苏格兰威士忌。

结论
推荐威士忌从来都不容易。我们已经成功地通过数据科学找到了推荐威士忌的方法。当我在浏览探索推荐威士忌的最佳模式的步骤时,它让我想起了数据科学的三个核心要素——计算机科学、统计学和领域专业知识。即使我们已经使用了大量的量化指标来评估模型,即使模型在统计上有很好的性能,但最终的评估仍然需要我们的领域专业知识,因为我们需要通过领域专业知识来确定模型是否有用。它提醒我们,领域专业知识与数据科学中的计算机科学和统计学一样重要,因为我们经常不重视领域专业知识的重要性。

苏格兰艾莱岛的鲍莫尔酿酒厂

这个项目是一个很好的体验,因为它提供了另一个视角来看待苏格兰威士忌之间的相似性。在做这个项目之前,我认为所有的 Islay 威士忌都非常相似;K 均值模型的结果告诉我,Bowmore 和 Laphroig 的味道并不相似。但如果我回忆起我喝鲍莫尔酒的记忆,我会发现鲍莫尔不像拉弗罗格那样多脂,而且不那么咄咄逼人。有时候,我们需要接受理解威士忌的不同视角,以避免你有的偏见。接受关于威士忌的不同意见和观点,增强你对 whish(ies/eys)的了解,并带来不同的饮用 whish(ies/eys)体验。

[## 雅克·沙姆-旧金山湾区|职业简介| LinkedIn

查看雅克·沙姆在全球最大的职业社区 LinkedIn 上的个人资料。雅克有 4 个工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/jacquessham/)

参考
科林斯威士忌

苏格兰威士忌体验:
https://www.scotchwhiskyexperience.co.uk/

苏格兰威士忌数据集:
https://www.kaggle.com/koki25ando/scotch-whisky-dataset

我的 Github:
https://github.com/jacquessham/ScotchWhiskyT4

树状图使用 Plotly:
https://stack overflow . com/questions/45847791/create-dendrogram-using-Plotly
https://plot.ly/python/dendrogram/

肘方法:
https://blog . Cambridge spark . com/how-to-determine-the-optimal-number-of-k-means-clustering-14f 27070048 f

使用 PyTorch 推荐相似图片

原文:https://towardsdatascience.com/recommending-similar-images-using-pytorch-da019282770c?source=collection_archive---------11-----------------------

resnet 18 的全迁移学习实现

使用 Resnet18 特性找到了相似的图像(来源:M. D. Korzec)

在我的上一篇文章中,我们介绍了一种简单的逻辑,通过使用迁移学习,根据图像内容在大集合中为相似图像创建推荐。

现在让我们使用 PyTorch 中预训练的 Resnet18 卷积神经网络创建一个 Python 原型实现。它将获取图像文件夹的内容,并创建 k 个与输入最相似的图像的 top-k 列表。

将 Resnet18 网络用于一组固定图像的简单推荐器的基本实现将在以下步骤中导出

0。理论倒带:图像推荐逻辑

1。重新调整数据

2。使用预训练的 Resnet18 网络作为特征向量生成器

3。通过计算这些向量的余弦,使用特征阵列计算相似性

4。创建 top-k 列表

5。使用 top-k 列表并可视化建议

如果你已经读过我的前一篇文章,可以跳过第 0 步。

如果你主要对原型实现感兴趣,你可以在这里找到 Jupyter 笔记本。它涵盖了所有步骤,包括一组图像样本和推荐图像的简单可视化

0。 图像推荐器逻辑

我们希望将相似的图像推荐给参考输入,例如在线商店中的推荐者。相似性是基于像素内编码的信息,而不是其元数据。

假设您已经在一个包含 jpg 图像的文件夹中收集了数据。然后,我们对图像进行预处理,以符合所选网络的输入要求(例如,Resnet18 的大小调整为 224x224 RGB 图像),我们使用所选网络计算大小调整后的图像的特征向量,我们基于余弦相似性计算相似性,并存储用于推荐的 top-k 列表。最后,我们使用列表进行推荐。

以下示意图总结了所有步骤

完整的图像推荐系统示意图(来源:M. D. Korzec)

核心步骤将使用 PyTorch 来执行,py torch 是 Python 中的一个开源机器学习框架。它伴随着各种各样的卷积网络和来自对巨大数据集的预训练的权重。

1。 预处理

图像文件夹应位于工作目录中。为了满足 PyTorch 卷积网络的输入要求,独立于网络,我们从 PyTorch 主页了解到,对于所有模型,我们需要以相同的方式归一化输入图像,以正确使用预训练的权重。输入需要

  • 至少具有 224x224 分辨率
  • 是 RGB 图像(即三个颜色通道)
  • 具有在[0,1]范围内的图像值
  • 考虑具有平均值0.485,0.456,0.406和标准偏差[0.229,0.224,0.225]的归一化图像。

为了重新缩放图像,我们可以如下进行:定义变换,迭代输入目录中的所有图像名称,加载图像,应用变换,将变换后的图像与其方向信息一起存储

规范化是在 next 后面的转换类的构造函数中执行的。

2。使用预训练的 Resnet18 网络作为特征向量生成器

为了从重新缩放的图像中生成特征,我们在构造函数中设置了一个包含网络相关信息的类

  • ToTensor 变换在每个通道中取值为 0 到 255 之间的 H x W x C 形式的图像,并将其压缩为 C x H x W 形状的 torch 张量,值为[0,1]。
  • 归一化操作采用图像的每个通道,并计算(图像-平均值)/std
  • 私有方法 getFeatureLayer(self)返回特征层,即平均池层。它是小分类向量之前的最后一个完全连接的层,并且是通过模型获得的。_modules.get('avgpool ')

公共方法 getVec(self,img)从图像输入中创建特征向量。它使用定义的设备(cpu)。一个函数被挂接到网络的转发调用,以从相关层复制数据。因此,最终包含相关信息的嵌入张量需要具有层的格式。

现在,为所有图像创建特征向量已经万事俱备。它们被收集在 allVectors 集合中。

3。使用特征数组通过计算这些向量的余弦来计算相似度

在我们计算完所有的特征向量之后,是时候计算它们之间的余弦值了。因为我们仅通过内积和归一化来计算相似性值,所以这是一个使用基本 NumPy(数字线性代数库)功能的函数调用。矩阵存储为 Pandas DataFrame(二维表格数据结构)

请记住,存储整个相似性矩阵是大规模使用的瓶颈——需要一些更精细的方法。

4。使用最佳建议列表

对于前 k 个(k 个最相似的图像)列表,熊猫数据帧从相似性矩阵创建,该矩阵包含与输入相似的名称和相应的相似性值。

tqdm 用于获得一个进度条,当你想处理许多图像时,这很有用。

5。 使用 top-k 列表并可视化推荐

在最后一步中,您应该能够看到与请求的输入类似的图像。

让我们将它用于存储库中提供的一些图像

资料来源 M. D. Korzec

期末笔记

有了上面的解释和代码,你应该已经掌握了使用 PyTorch 的预训练卷积网络为相似图像创建推荐系统所需的所有基础知识。完整代码可从下载。

如果你想用不同的型号,在 PyTorch 网站上有描述。当你想创建更多的实验时,把代码模块化,只把网络及其层当作参数。当创建具有较大集合的实验时,建议存储中间结果,例如作为 pickle 文件。

如果你问自己如何运营一个包含这种推荐者的网站,你可能想看看我的后续文章。

感谢阅读!喜欢这个话题吗?

如果你觉得这篇文章很有趣,你可能想看看我在这个主题上的其他文章:

[## 轻松推荐相似图片

使用来自训练的卷积神经网络的特征来产生可比性

towardsdatascience.com](/effortlessly-recommending-similar-images-b65aff6aabfb) [## 一个推荐图片的 Flask 应用程序

PyTorch 中基于卷积神经网络的相似图像推荐网站原型

medium.com](https://medium.com/@maciek.korzec/a-flask-app-for-image-recommendations-a865e1496a0d) [## py torch+Flask+PostgreSQL+Heroku 部署的映像建议

用 Flask 封装一个基于 PostgreSQL/ PyTorch 的图像推荐系统,导入数据并在 Heroku 上运行

towardsdatascience.com](/image-recommendations-with-pytorch-flask-postgresql-heroku-deployment-206682d06c6b)

用机器学习推荐川普的下一个朋友

原文:https://towardsdatascience.com/recommending-trumps-next-friend-with-machine-learning-6317cdc640c3?source=collection_archive---------46-----------------------

使用图论链接新闻预测

序文

我们能预测哪些人会出现在明天的新闻报道中吗?可以为名人推荐好友吗?敬请期待一探究竟。

撇开 90 年代美国电影预告片风格的介绍不谈——这篇文章是我上一篇文章的延续,所以我建议浏览一下,以便更好地理解。对于懒惰的数据科学家,这里有一个简短的总结:

  • 我们从一些顶级(最受欢迎的)英国在线报纸上搜集了一些文章
  • 我们使用命名实体识别来识别每篇文章中的人和组织
  • 我们从数据中创建了一个网络结构,如果实体出现在同一篇文章中,就将它们链接起来
  • 我们做了一些其他的很酷的东西,在这里不相关

然而,现在我们将从描述性统计的舒缓运河中冒险,驶向预测性分析的危险海洋。如果你曾经看过顾问最喜欢的数据分析成熟度图,你会知道这不是一个小跳跃。不过没关系,我们会手拉手活着度过难关的,我保证。

我们在成熟度矩阵上的重大飞跃——螺旋诊断

我们将把我们的社交网络中的人和组织放在新闻中,并试图预测我们的数据中正在形成的新链接,以暗示谁可能在明天的新闻中一起出现。

为什么

谁不想扮演马克·扎克伯格呢?谁不会想预测谁会一起出现在新闻上?

虽然,正如我们将看到的,这个消息太过狂野,无法完美预测,但我们可以获得关于一个组织与另一个组织或个人相关联的可能性的有价值的见解,这可以告诉我们,例如,我们的客户可能会将我们与谁相关联——有意识地或无意识地。

除此之外,一般实践链接预测还有广泛的使用案例:

  • 向脸书或 Instagram 等社交网络的用户推荐朋友
  • 向亚马逊或网飞等平台上的用户推荐产品
  • 预测生化网络中的相互作用,如蛋白质-蛋白质相互作用
  • 预测疾病在人群中的传播

什么

链接预测

链接预测是评估图中两个节点形成连接的可能性的分析方法。目标是通过分析图的结构来预测动态网络中形成的下一条边。

网络中形成链路的示例

我们举一个熟悉的例子。给定一个在时间 t(i) 的 4 个人的社交网络,目标是找到该网络在未来某个时间 t(i+1) 的结构。听起来很简单,对吧?事实证明,我们最终使用的算法非常简单——魔鬼总是存在于细节中。挑战在于恰当地表述问题。

分类

让我们从最后开始,倒推。我们想要结束的是一个潜在的新链接正在形成的数据集,我们可以在其上训练一个分类器。我们将取图中所有尚未连接的线对,并检查它们是否在时间 t(i+1)形成了连接。对于上面的示例图,它看起来像这样:

我不知道你怎么想,但在我看来这很可疑,像是一个二进制分类问题。唯一的问题是,我不知道有任何分类器可以在我们上面的 Link 专栏中成功训练,更不用说愿意接受它作为输入了。不,我们需要比这更好的功能。戴上你的工程帽。

特征工程

幸运的是,在为机器学习做准备时,有许多方法可以为图中的边创建特征。也许在最近的时间里,最受欢迎的是 node2vec (Grover 等人,2016) 方法。在名称和思想上与 word2vec 相似,该算法使用图上的随机行走来创建其节点的向量表示。听起来很酷,对吧?太糟糕了,因为我们不会用到它。

注:我对 node2vec 没有任何意见。事实上,我非常希望它能起作用。不幸的是,当在我的图表上训练时,测试数据集上的预测结果非常糟糕。我怀疑我可能需要走更长的路,因为我的图表非常大;但是训练已经花了很长时间,时间是宝贵的。如果你有任何建议,请告诉我。

我们将坚持使用更传统的方法,一个接一个地生成一些特性。从 2004 年的李奔-诺埃尔那里得到灵感,我们将计算我们每个边的一些属性。看看这些老伙计们:

优先连接 ( 于勒,1925 ) —这位 95 岁的老兵听起来很奇特,但在我们的图形世界中,它代表了给定节点对中每个节点的邻居数量的乘积。基本观点是,拥有更多朋友的人更有可能结交更多朋友——因此,两个都有很多朋友的人会有较高的偏好依恋分数,从而有可能彼此建立联系。

Jaccard 系数 ( Jaccard,1901)——记录了 119 岁的高龄,在此过程中几乎没有错过 19 世纪,我们有 Jaccard 先生的指数。Jaccard 系数通过一系列替代应用为许多人所熟悉,但在我们的上下文中,它将表示两个节点之间的公共邻居与这两个节点总共拥有的邻居数量的比率。

Adamic/Adar 指数 ( Adamic,Adar,2003)——和老伙计们一起闲逛,不能在酒吧点啤酒,就是 Adamic/Adar 指数。与 Jaccard 索引类似,该功能通过邻居拥有的邻居数量的倒数来为节点对的每个公共邻居增加权重。

共同邻居 —简单来说就是两个节点拥有的共同邻居的数量。不废话。

收集了一组很好的特征后,我们可以将它们添加到之前的表中:

要素表示例-代表值(大部分)

这开始看起来像是我们可以训练机器学习模型的东西(假设这些值在真实数据上有实际差异)!

但是我们如何建立我们的训练数据集呢?

培训用数据

我们的目标是,给定某一天社交网络的状态,预测网络中正在形成的新链接。我们所要做的就是在第一天检查每一对尚未连接的节点,并计算它们的上述特征。然后,我们将在第二天观察同一个网络,看看它们中是否有人形成了新的联系。因此,我们可以将第二天形成连接的未连接对标记为阳性,其余的为阴性。

我们可以连续几天重复这一过程,感受网络如何随着时间的推移而演变,并将结果串联起来。下图说明了这一想法:

最后,我们将把最后一天的预测分离出来作为一个测试数据集,看看我们的模型在一个看不见的日子里表现如何。

怎么做

我们将用现实生活中的数据来演示我上面概述的概念。这次我们将前后工作。

培训用数据

在我之前的文章中,我已经展示了我是如何通过识别出现在 3 月 26 日同一篇新闻文章中的实体对来构建“社会”链接的。在接下来的 6 天里,我重复了同样的练习,一直到 4 月 1 日。这让我获得了超过 400,000 个(非唯一的)链接,分布在一周内,如下所示:

每天的实体链接总数

我故意没有想象第 7 天,因为我们不会从那创建一个图表,我们将只检查与第 6 天相比新形成的链接。

为了演示起见,我们将在第一天演练一下这个练习。

让我们通过导入包含所有链接的 CSV 来构建训练数据集,在第一天进行过滤,并将相同的链接分组在一起,根据计数为它们分配权重。我还将丢弃任何只出现过一次的链接,将重点放在更突出的链接上:

import pandas as pd
import numpy as npdf_links = pd.read_csv('/content/drive/My Drive/News_Graph/links.csv')date = '2020-03-31'df_links_train = df_links[df_links['date']==date]df_links_train = df_links_train.groupby(['from', 'to']).size().reset_index()df_links_train.rename(columns={0: 'weight'}, inplace=True)df_links_train = df_links_train[df_links_train['weight'] > 1]

接下来,我们将从结果链接中构建一个图结构,然后找到最大的连通子图——这是计算我们的特征的一个要求。我们会发现,无论如何,95%以上的节点全天都是连接的。

import networkx as nxG = nx.Graph()for link in tqdm(df_links_train.index):
  G.add_edge(df_links_train.iloc[link]['from'],
             df_links_train.iloc[link]['to'],
             weight=df_links_train.iloc[link]['weight'])subgraphs = [G.subgraph(c) for c in nx.connected_components(G)]subgraph_nodes = [sg.number_of_nodes() for sg in subgraphs]sg = subgraphs[np.argmax(np.array(subgraph_nodes))]df_links_sg = nx.to_pandas_edgelist(sg)G = nx.Graph()for link in tqdm(df_links_sg.index):
  G.add_edge(df_links_sg.iloc[link]['source'],
             df_links_sg.iloc[link]['target'],
             weight = df_links_sg.iloc[link]['weight'])

上面的步骤产生了一个图, G ,它包含了一个加权的无向图,该图封装了代表 3 月 26 日新闻的“社交网络”的最大连通子图。具体来说,它在 2,183 个节点之间包含 8,045 条边。

3 月 26 日新闻的网络情节

很美,不是吗?虽然不是很有用。让我们看看我们是否能找出这些粉红色的家伙第二天会交朋友。

与之前类似,我们定义了一个按出现次数加权的链接数据集,但这次我们还过滤了前一天两个实体都出现在网络中的链接。之后,我们将从 27 日的网络中移除所有在 26 日已经出现的链接,因此这些链接不是新形成的边。最后,我们将剩余的链接标记为 1,以表示新形成的链接:

date_target = '2020-03-27'df_links_tar = df_links[df_links['date']==date_target]
df_links_tar = df_links_tar.groupby(['from', 'to']).size().reset_index()
df_links_tar.rename(columns={0: 'weight'}, inplace=True)
df_links_tar = df_links_tar[df_links_tar['count'] > 1]
df_links_tar.reset_index(drop=True, inplace=True)# filter to only include nodes which exist in training dataall_nodes = G.nodes()df_links_tar = df_links_tar[(df_links_tar['from'].isin(all_nodes)) & (df_links_tar['to'].isin(all_nodes))]# create edge columns and filter out those who also appear in training datadf_links_tar['edge'] = df_links_tar.apply(lambda x: x['from'] + ' - ' + x['to'], axis=1)df_links_sg['edge'] = df_links_sg.apply(lambda x: x['source'] + ' - ' + x['target'], axis=1)# remove edges which exist in training datadf_links_tar = df_links_tar[~df_links_tar['edge'].isin(df_links_sg['edge'])]# label remaining edges with 1df_links_tar['label'] = 1

通过上述步骤,我们产生了具有 2183 对实体的数据帧,这些实体在 26 日还没有形成链接,但是将在 27 日形成一个链接,并且用 1 标记它们。那些 27 号不会形成链接的呢?

嗯,就我们所知,理论上来说,我们图中的任何一对未连接的对都可能在第二天形成一个连接。因此,我们需要从 26 日开始在图中找到两个节点的所有可能组合,这些组合还没有包括在我们在 27 日确定为形成链接的对中,并将它们标记为 0。

让我们在这里停下来想一想。

我们的图表中有 2382 个实体,我们知道其中的 2183 对将形成一个新的链接。有多少人不会呢?有大量的可能性:确切地说,是 2382-choose-2。这个数字接近 300 万,这意味着阳性样本与阴性样本的比例将低于 1:1000!这是一个非常不平衡的数据集来训练分类器。我们有几个选项来处理这个问题,但是对于这个练习,我选择对我的数据进行下采样,因为我知道当我完成整个星期的时候,我可能会有相当多的行。

注意:这可能不是最佳实践——我主要是出于演示的目的使用下采样,以减少特征工程和模型训练的时间。类似 SMOTE 的东西在这里可能更合适。

我们将找到网络中所有可能的节点组合,去除那些在 26 日有链接的节点和那些将在 27 日形成链接的节点。然后,我们将从这些未连接的对中随机抽取一个 9x2,183 (新形成链接数量的九倍)的样本,给我们一个 1:10 的训练比——好得多。

from itertools import combinationscombs = list(combinations(all_nodes, 2))all_combinations = pd.DataFrame(data=combs, columns=['from', 'to'])all_combinations['edge'] = all_combinations.apply(lambda x: x['from'] + ' - ' + x['to'], axis=1)all_combinations = all_combinations[~all_combinations['edge'].isin(df_links_sg['edge'])]all_combinations = all_combinations[~all_combinations['edge'].isin(df_links_tar['edge'])]all_combinations.reset_index(inplace=True, drop=True)sample_size = 9*len(df_links_tar.index)all_combinations = all_combinations.iloc[np.random.choice(len(all_combinations.index),
     size=sample_size,
     replace=False)]all_combinations['label'] = 0

最后,我们连接两个数据帧:

edges_to_predict = all_combinations.append(df_links_tar[['from', 'to', 'edge', 'label']])

数据帧 edges_to_predict 将包含所有新链接的列表,标记为 1,以及不会形成链接的边对样本,标记为 0。

特征工程

我们还记得,为了创建特征,我们需要计算每对训练数据的共同邻居的数量、JAC card 系数、 Adamic/Adar 指数偏好连接分数。在这方面,NetworkX 库将是我们最好的朋友。我们所需要做的就是创建一个节点对的 bunch ,也就是一个元组列表来标识每个节点对的源和目标:

bunch = [(source, target) for source, target in zip(edges_to_predict['from'].values, edges_to_predict['to'].values)]

特征计算简单得可笑:

# Preferential Attachmentpreferential_attachment = nx.preferential_attachment(G, bunch)pref_attach = []for u, v, p in preferential_attachment:
  pref_attach.append(p)edges_to_predict['preferential_attachment'] = pref_attach# Jaccard Coefficientjaccard_coefficient = nx.jaccard_coefficient(G, bunch)jaccard = []for u, v, p in jaccard_coefficient:
  jaccard.append(p)edges_to_predict['jaccard_coefficient'] = jaccard# Common Neighbourscn = []for source, target in zip(edges_to_predict['from'].values, edges_to_predict['to'].values):
  cn.append(len(list(nx.common_neighbors(G, source, target))))edges_to_predict['common_neighbours'] = cn# Adamic Adar Indexadamic_adar = nx.adamic_adar_index(G, bunch)aa = []for u, v, p in adamic_adar:
  aa.append(p)edges_to_predict['adamic_adar_index'] = aa

最后,我们有真正的功能和真正的目标!数据帧现在看起来像这样:

分类

我们准备好训练我们的机器学习模型了。在屏幕外,我们在随后的 5 天里重复了上述过程,对第 6 天的训练数据做了一点修改:在 3 月 31 日,我没有对数据进行而不是下采样,因为它不是我们训练集的一部分。我们需要假装不知道 4 月 1 日会形成什么联系,因此我们需要使用所有可用的数据。

我们已经在样本训练数据中看到,我们的特征列假设了变化很大的值范围。为了增强我们的学习模型,我们将使用 scikit-learn 将它们调整为平均值为零、标准差为 1 的值:

from sklearn.preprocessing import StandardScalerdf_test = pd.read_csv('/content/drive/My Drive/News_Graph/edges_test.csv')df_train= pd.read_csv('/content/drive/My Drive/News_Graph/edges_train.csv')features = ['preferential_attachment',
            'jaccard_coefficient',
            'common_neighbours',
            'adamic_adar_index']X_train = df_train[features].to_numpy()
Y_train = df_train['label'].to_numpy()X_test = df_test[features].to_numpy()
Y_test = df_test['label'].to_numpy()scaler = StandardScaler()X_train = scaler.fit_transform(X_train)
X_test = scaler.fit_transform(X_test)

提醒一下,我们正在一个稍微不平衡的数据集上训练一个模型,并在一个现实的、非常不平衡的数据集上测试:

训练集中阳性样本的比率:0.1。
测试集中阳性样本的比例:0.00092。

我们准备初始化我们的模型:逻辑回归。

是的,逻辑回归。当我在标题中吹捧机器学习时,这不是你所期望的,是吗?我保证我尽力了——真的尽力了。我测试了一个随机森林模型,一个支持向量机,我花了一周时间调光梯度 Boosting 和 XGBoost 模型。我搜索了一个深层神经网络。他们都不能打败逻辑回归的 ROC。所以你有它。我想这很符合我的老派特征。

from sklearn.linear_model import LogisticRegressionclf = LogisticRegression(class_weight='balanced')clf.fit(X_train, Y_train)lr_prob = clf.predict_proba(X_test)[:, 1]lr_pred = clf.predict(X_test)

class_weight 参数确保模型中的错误惩罚与我们数据中的正/负训练样本的比率成比例,使模型对错误的正预测更加敏感,从而提高整体性能。

让我们看看我们在测试数据上的表现。

逻辑回归模型的 ROC 曲线

我们的 ROC AUC 值非常可观,为 0.9312。让我们画出混淆矩阵。

逻辑回归混淆矩阵

这允许我们计算我们的精度和召回:

精度:0.0076
召回: 0.8394

不错——不是很好,但也不坏。我们设法识别了几乎 84%的未来链接。然而,我们发现了如此多的潜在联系,以至于只有不到 1%的积极预测在第二天变成了现实。

洞察力

恭喜你又完成了一个漫长的练习;我希望这是值得的。让我们回顾一下我们所做的工作:

  1. 我们已经从数千篇文章中为一周中的每一天构建了命名实体的网络表示;
  2. 我们已经建立了一个结构来训练一个模型,通过增量识别将在我们的动态图中形成第二天的链接;
  3. 我们学习了一些图的经典特征并计算了它们;
  4. 我们已经根据我们的数据训练了一个二元分类器,并在一个未知的日子进行了测试。

特朗普的朋友

让我们看看我们可以推荐谁做总统,然后:

包含唐纳德·特朗普的推荐链接

这是我们预测的一个例子,其中链接中的一个实体是 Trump。这些都是模型认为会在第二天的新闻中出现的链接。标签为的列表示它实际发生了(1)还是没有发生(0)。

我们为 Trump 推荐了许多朋友,Trump 在下面“点击”接受;记住,前一天他没有和他们一起出现在新闻上:

  • 福克斯新闻频道
  • 迈克尔·戈夫
  • 马特·汉考克
  • 哈里王子
  • 休·休伊特
  • 拉里·霍根州长
  • 众议院

讨论

我们的结果有多好?嗯,这主要取决于业务环境。不平衡的分类是困难的,您希望从模型中得到的结果决定了您应该关注哪个性能指标。例如,如果这是一个欺诈检测练习(另一个常见的不平衡预测任务),我们会做得很好——如果这意味着你抓住了 84%的欺诈交易,你不会介意向你的客户发送一些假警报文本。然而,我们的目标是什么?

我们的模型非常善于识别第二天不会形成的链接——有很多这样的链接。不太擅长识别发生的环节。如果我是这里的产品负责人,我可能希望专注于精确,而不是回忆;我们的好友推荐大多数时候应该是对的,即使我们没有把所有可能的好友推荐给所有人。为此,我们可以提高肯定分类的概率阈值。这将以回忆为代价,但它将确保我们归类为积极的东西更有可能在现实中发生。

另一件要考虑的事情是朋友推荐在现实中的效果如何。Instagram 上你实际向多少比例的推荐账户发送邀请?你在亚马逊上购买多少你推荐的产品?杰夫·贝索斯将拥有比我们更多更好的数据。在这种情况下,我认为我们做得很好。

总而言之——事实证明,预测新闻是很难的。但是没费多少功夫,我们就设法建立了一个很好的模型来实现这个目标。

事后思考

我做错什么了吗?我能做得更好吗?我做得好吗?

请随时在 LinkedIn 上联系我;如果你对我的工作感兴趣,我总是很乐意接受挑战或者只是聊聊天。

如果你想自己玩代码,请点击链接到我的 Google Colab 笔记本:

[## 谷歌联合实验室

编辑描述

colab.research.google.com](https://colab.research.google.com/drive/1y_fAm4ObJQfIeUsNIWt2izZ4pwxz_9mn?usp=sharing) [## 谷歌联合实验室

编辑描述

colab.research.google.com](https://colab.research.google.com/drive/11Zrpjmkg1_tFvw8DXwdu4-YFCnlolj_a?usp=sharing)

调和因果关系和统计学

原文:https://towardsdatascience.com/reconciling-causality-and-statistics-1dfa4ce1b465?source=collection_archive---------24-----------------------

介绍珀尔的做微积分用商业例子说明

来源:作者

这是由 皮尔明·伦伯格 丹尼斯·奥布林 共同完成的。

  1. 一段风雨飘摇的关系
  2. 概括地说因果革命
  3. 简单商业例子的因果分析
  4. 数据科学家值得了解的东西?

1.风雨飘摇的关系

考虑以下三对伴随事件:“太阳在公鸡第一声啼叫后不久升起”、“当广告横幅出现在某个适当的位置时,某个网站的访问量往往会增加”、“皮肤癌的发病率与法国里维埃拉的冰淇淋销量相当”。

虽然常识告诉我们,通过限制冰淇淋销售来减少癌症或通过挠痒痒让公鸡更早啼叫来加速日出的可能性很小,但尝试优化广告横幅的位置可能确实值得付出努力。因此,似乎我们对世界如何运作的直觉告诉了我们一些关于这些伴随事件的事情,这超出了单纯的统计数据所能描述的范围。统计学实际上只处理相关性,这意味着它量化了假设我们已经观察到另一个事件 a,事件 B 发生的可能性。然而,它没有告诉我们如果我们对系统采取行动会发生什么,它甚至没有提供任何手段来描述对系统的干预是什么。因此结论很简单:一般来说,我们需要的不仅仅是概率和统计来表达和回答因果关系问题。随机对照试验 (RCT)的方法完全建立在统计分析的基础上,并被广泛认为是临床试验的黄金标准,这是一个值得注意的例外,我们将在后面详细介绍。

直到本世纪初,人们才认识到,简单的统计学天生就无法恰当地处理所有普遍性的因果关系[1]。在此之前,一场争论已经持续了近一个世纪。我们不会进入这些冗长的辩论,因为幸运的是现在已经没有争论的理由了!哲学家和统计学家 Judea Pearl 的开创性工作[1,2,3]提供了一个数学上合理的框架,允许以明确的方式阐述因果关系问题,并尽可能系统地回答这些问题,从而彻底结束了这些争论[3]。朱迪亚·珀尔在很大程度上对因果关系辩论的彻底重塑负有责任,从那时起,这场辩论被称为因果革命。为此以及他在人工智能因果推理方面的其他杰出成就,他获得了 2011 年图灵奖。

在我们深入朱迪亚·珀尔的因果关系概念的微妙之处之前,让我们承认,许多使用监督的机器学习作为他们最喜欢的工具的数据科学家从来不关心因果关系问题。事实上,他们可能会因此陷入严重的麻烦,但在我们简单提到的两种常见情况下,这仍然是一种合理的态度。

  • 首先,发现两类事件之间的相关性本身就有价值。例如,了解购买了产品 A 的用户也有可能购买产品 B,可以提供对客户群体的一些洞察。重要的一点是,由这种基于相关性的预测所驱动的任何后续行动都不应该以任何方式对测量变量产生反作用。
  • 第二,在其他情况下,对某个特征 X 的被动观察确实与我们指定该特征的值的干预具有相同的效果(对预测目标变量 Y )。例如,想象一下 X 是气泵的转速,而 Y 是它在一个房间内保持的压力。一旦我们通过被动观察了解了 XY 之间的关系,当我们设定泵的速度时,我们将能够预测空气压力。直观上,从 XY 的因果关系是直接的,不受干扰的。当我们在 2.4 节描述 do 演算时,我们将精确地描述这些情况的特征。

朱迪亚·珀尔的方法真正出彩的地方是在不太明显的情况下,我们想要推断在涉及其他变量 Z 的整个因果关系网络存在的情况下,设置 X = xY 的值的影响。这些其他变量通常被称为伴随变量【4】,可以被观察到,也可以不被观察到。在最简单的版本中,回答因果问题的困难根源如图 1 所示,图 1 说明了混杂** Z 的概念。**

图 1 :假设 X 表示给病人用药的选择,Y 表示病人的健康状况,Z 表示他或她的年龄。如果医生选择他或她管理治疗的对象,那么年龄 Z 可能成为影响治疗选择 X 和健康状态 y 的混杂因素。

用直观的术语来说,混杂因素 Z 是一个变量,它可能会因为是另外两个变量 XY 的原因而阻碍对这两个变量之间因果关系的识别。由 X 的变化引起的 Y 值的观察变化也可以归因于 Z 的变化。然而,如果能够访问混杂因素 Z 的值,我们或许可以调整其影响,从而提取出 XY 的预期影响。在可能的情况下,这样做的程序为统计学家所熟知,并被命名为“控制用于 Z ”。简而言之,Pearl 的机器所实现的是这种控制程序的广泛推广:

Pearl 的图形和代数工具允许我们识别可能消除两个变量 X 和 Y 之间因果关系的情况。只要有可能,这些工具就提供明确的公式,用于计算规定另一个变量 X 的值 X 的干预对变量 Y 的影响。这些公式合并了两种信息。首先,他们使用一些刚刚观察到的伴随 Z 的值。第二,他们利用了一个因果图 G,它概括了我们对一个感兴趣的系统中变量之间的因果关系的了解。

稍后我们将考虑用另一种方式来解释珀尔的作品,即作为 RCT 作品的广泛推广。

Pearl 的概念和计算工具有几个重要的优点:

  • 从实践的角度来看,它们允许预测一个干预对一个系统的影响,而实际上不必对它执行任何动作。显然,这在我们因为道德或经济原因而无法对一个系统采取行动的情况下非常有用。
  • 仍然从实用的角度来看,它们都以完全一致的方式整合了关于系统测量的因果先验知识
  • 从概念的角度来看,它们为因果影响和干预的含义提供了明确的定义,我们很快就会看到这一点。这个解决了长期的因果关系争议,并且调和了统计数据和因果关系。

这篇文章的续篇组织如下。第 2 节介绍了 Pearl 及其同事定义的主要概念和工具。在简要回顾了允许我们引入d–分离概念的贝叶斯网络之后,我们定义了什么是功能因果模型并描述了它可以从数据中推断出来的程度。我们定义了干预可识别性的概念。我们解释了图形后门前门标准,这些标准允许在某些特定情况下识别因果关系。最后,我们引入了更加灵活的做演算的规则。第 3 节讨论了各种业务示例作为说明。最后一节提供了一些总结性的评论,并试图解释为什么在我们看来,这些工具在数据科学家群体中仍然鲜为人知。

2.简而言之,因果革命

在本节中,我们将介绍支撑因果革命的主要定义数学结果。我们定义什么是因果关系,如何以及何时从数据中识别它们。然后,我们定义了什么是干预,并描述了图形和代数工具,这些工具允许确定我们可以使用从纯观察收集的数据计算干预后果的情况。为了证明,我们参考了珀尔关于因果关系的书[2]和原始论文[3]。

2.1 贝叶斯网络概述

我们将在以下小节中介绍的工具非常依赖于一种称为 d - 分离标准的图形方法,这种方法允许回答随机变量组(r.v)之间的一般独立性问题。这些工具是由珀尔开创的,他提出了 T4 贝叶斯网络的概念。关于这个主题有许多好的教科书[9],但是我们提供了一个简短的介绍,既介绍了符号,又使演示合理地自成一体。请熟悉本材料的读者跳到第 2.2 小节。

我们使用大写字母,如 XYZ 来表示 r.v,粗体大写字母表示 r.v X =( X _1、 X _2、…、 X _m)的序列(或集合),较低的索引表示 X 的组件。为简单起见,我们假设每个分量只取有限数量的值。这些 r.v .的相应实现将用相应的小写字母 x =( x _1、 x _2、…、 x _ m )表示。

第一步是将一个图 G 关联到一个概率分布p(x)=p(x_ 1, x _2,…, x _ m )。迭代条件概率的乘积规则,我们有:

其中 j =1 的调节设置为空。现在,如果 X _ j 只以 X _1、…、 X _j-1 的子集为条件,让我们用 PA_j,即 X _ j父代来表示这个子集的最小值,这样我们就可以写出:

(2)的自然表示是使用一个贝叶斯网络,它是一个有向无环图** (DAG),其中图的每个节点对应于一个变量 X _ j ,并且一个有向链接从 PA_ j 的每个成员指向 X _ j ,如图 2 所示**

图 2 :一个唯一的 DAG G 可以关联到一个有序集或 r.v. X_1,…,X_n 上的概率分布 p。

我们说概率分布 p 和图 G相容的。还要注意,根据(1 ),与没有特定因子分解特性的一般分布 p 相关联的 DAG 是完全连通图。因此,DAG 中的所有信息实际上都包含在缺失的链接中。

对于给定的 r.v .顺序,该图 G 是唯一的。然而,如果我们在 p 中为 r.v .选择了另一个订单,我们将获得另一个图表G’。因此,自然产生的问题是确定何时两个 DAG GG’在观测上等价。更准确地说,我们想问,与 G 相容的任何概率分布 p 是否也与另一个图G’相容。可以显示以下内容[2]:

定理 1 (观测等价):如果满足两个条件,则两个 DAG 是观测等价的。首先,从 G 和 G’(它们的骨架)的边上去掉箭头得到的图应该是相同的。第二,G 和 G '应该有相同的 v 型结构,v 型结构是带有收敛箭头的节点,这些箭头的尾部不是由一个箭头连接的。**

X、YZ 为三组 r.v .,其联合分布为 p ( x y z )。特别感兴趣的问题是 X 是否在观察 Z 的条件下独立于 Y ,即

或者,换句话说,是否

如果答案是肯定的,我们用(X‘indep of’Y|Z)来表示。下面的d-分离定理允许我们通过查看与 p 关联的图形 G 来图形化地回答这个问题。为此,我们需要以下图形概念:

定义 1 :当且仅当满足以下两个条件之一时,DAG G 中的一条路径 γ (指向任何方向的一系列连续边)被称为被一组节点 Z 阻塞:

  • 路径 γ 包含一个链条(Imj)或一个(Imj)使得 m 属于
  • 路径 γ 包含一个碰撞器(Imj),这样 m 及其任何后代(如 G 中边上的箭头所定义)都不属于 Z

集合 Z 被称为d——每当 Z 阻塞从 X 中的一个节点到 Y 中的一个节点的每一条路径时,将 XY 分开。

图 3 :观察到的节点用实心圆表示。在(a)中,从 X 到 Y 的路径既没有被 Z_2 阻挡,因为它是碰撞器 Z_1 的可观察后代,也没有被 Z_3 阻挡,Z _ 3 是不可观察的分叉。在(b)中,从 X 到 Y 的路径被 z3 阻断,因为它是一个观察到的分叉。

我们现在可以公式化d-分离准则,该准则将由相容的 DAG G 描述的 p 的因子分解性质和它们隐含的独立性关系联系起来:

定理 2**(d-分离定理): X Y Z 是与一个分布 p 相容的 DAG 中三个不相交的节点集.那么对应的按 p 分布的 r.v .满足Xindep**

反之亦然。定理 2 的一个重要结论是,r.v .之间的条件独立性集合仅由 G拓扑决定,而 r.v .的排序不起作用。当我们将d-分离标准视为 DAG G 的节点上的图形测试时,我们将写出(X' indep of 'Y|Z)_G。使用(4 ),我们可以将定理 2 简洁地改写为**

我们坚持认为,到目前为止还没有因果关系的讨论,只有独立性问题进行了审查。然而,对于 d 分离标准,有一个简单的助记符,如果我们暂时允许自己将因果意义与 G 中的箭头联系起来。事实上,如果我们固定链或叉中的中间节点 m 的值,我们就阻塞了两个末端节点 ij 之间的信息流,这两个末端节点因此变得独立。相反,如果我们观察一个碰撞器节点 m 的值,或者它的一些后代的值,我们实际上观察到一个 ij 的共同结果。例如,知道了 im 将会告诉我们一些关于 j 的事情,从而打开信息流。这种基于 d 分离的独立性分析预示了我们在下一小节中展开的真正的因果分析。**

2.2 功能因果模型和干预措施

结构方程

一个条件概率p(Y|X)告诉我们,观察到 Y = y 的概率是如何受到 X = x 的影响的。然而,它并没有告诉我们当我们指定 X 的值时会发生什么。为了回答这个问题,我们需要比 p 包含的更多的信息,即关于概率模型 p 在外部干预下将如何变化的信息。这正是一个功能因果模型* M 所做的。它被定义为一组函数关系,描述了每个 r.v. X _ j 如何被确定为其他的和一些噪声干扰的函数。因此,它解释了数据是如何产生的。使用符号 PA_ j 来表示直接影响 X _ j 的 r.v .集合,然后将因果模型定义为一组结构方程😗**

其中 f _ j 是双亲变量 PA_ j 和一些噪声干扰ϵ_ j 的确定性函数。重要的一点是,ϵ应该独立。换句话说,假设每一个关系都被一个随机扰动所干扰。如果一个扰动同时影响几个 r.v .,我们应该用一个描述它对其他变量影响的结构方程把它提升到一个不可观测的 X _ j 。因果图 G 可以与因果模型 M 相关联,如图 4 所示,其也定义了混淆弧的概念。**

图 4: 因果图 G,其中观察到的 r.v .如 X、Y 或 Z 表示为实心圆,而未观察到的 r.v .如 U_1 或 U_2 表示为空心圆。混淆弧是连接两个观察到的 r.v .的路径,只包含未观察到的 r.v .并且没有会聚箭头。

r.v. X 集合上的概率分布 p 完全由模型 M 指定,该模型包括确定性函数 f _ j 的集合和扰动ϵ.的分布然而,在实践中,这些仍然是不明确的。注意,图 2 中的链接表示条件依赖关系p(x_j| pa _j),而图 4 中的链接表示确定性依赖关系x_j=f_j(pa _j,ϵ_ j )。**

假设给我们一个与因果模型 M 相关联的因果图 G ,该因果图生成概率分布 p 。这个 p 有什么独立关系?答案和我们想象的一样简单:它们正是由应用于dG 的分离标准决定的。这是从贝叶斯网络意义上的 pG 兼容的事实和d-分离定理得出的。**

do-Operator

因果模型描述的系统上的干预*是结构方程(6)的变更,其中一些关系被其他关系代替。在我们固定值的最简单的情况下,比如说, X _ ia 这相当于用xI=fI(pa I,ϵ i 替换等式x【t21 _I=)因此,如图 5 所示,通过移除将节点连接到 X _ i 到其父 PA_ i 的所有链接,从 G 获得修改模型的相应因果图。***

图 5 :移除变量 X_4 与其父变量 PA_4 之间的链接,定义一个干预。如果(a)表示 p( x ,那么(b)表示 p( x |do(x_4=a))。

干预后,概率分布p(x)被一个新的概率分布代替,我们用p(x| do(x_I=a)表示。这定义了 do 操作符。使用该定义和分布 p 的因式分解(1 ),我们还可以将干预后分布表示为截断因式分解:****

一般来说p(x| do(x_I=a))当然不同于古典条件句p(x*|x【T75 _I=两个表达式确实相同的一个小情况是当 X _ i 没有父代时,即 PA_ i 是空集。当我们在第 2.4 节中介绍微积分时,我们将会准确地回答这样一个一般性的问题:作为一个观察值,对一个变量 X 的作用何时对另一个变量 Y 产生相同的结果。*******

为了更直观地了解 do 运算符,让我们计算干预 do(X_I=a)对单个变量 Y 的影响,该变量不同于 X_i 及其父变量 PA_ i 。堵漏****

into(7)forx_I=a并对除了在 yx_i 上的所有变量进行边缘化,我们得到****

这种对变量 PA_ i 的调节和加权运算(9)来计算p(y| do(X_I=a))被称为 X_i直接原因调整。****

等式(9)表明,当操纵变量 X_i 的双亲 PA_ i 可测量时,那么对 X_i 的干预对 Y 的影响可以仅从被动观察来计算。确实这些决定了 p ( x )和p(x_I| pa _I)。在实践中,我们可以使用机器学习来达到这个目的。****

那么有趣的问题是,当情况并非如此时,即当 PA_ i 中的一些 r . v .可测量时,我们是否可以计算干预的效果?更一般地说,自然产生的问题如下。给定一个因果图 G 和一个可观察伴随物的子集 Z 我们能否仅用观察变量 ZXY 的分布来表示p(Y| do(X=a)?在这种情况下,我们将说 XY 的因果关系是可识别的。让我们简洁地总结一下这个可识别性的概念[11]。****

对变量 X 和 Y 以及一组可观察伴随物的 Z 的被动观察告知我们它们的联合分布 p ( x,Y, z ) ),当然,只要我们有足够的数据。但是,对 X 的干预对 Y 的影响 p(Y |do(X)只编码在生成这个 p 的因果模型 M 中,而不编码在 p 本身中!因此,我们面临的问题是,两个不同的因果模型 M_1 和 M_2 可以生成相同的 p。为了预测干预的效果,我们需要比 p 中包含的更多的信息。与因果模型 M 相关联的因果图 G 有时可以提供这种缺失的信息,而不需要完全了解因果模型 M。在这种情况下,我们说干预 p(y |do(x)可以从 G 中识别出来。****

在 2.3 和 2.4 小节中,我们将描述图形和符号工具来回答这些问题。

用 do 运算符解读随机对照试验

让我们快速联系 do 运算符的定义(7)和随机对照试验 (RCT)程序。考虑这样一种情况,我们想要评估一组患者的治疗效果。假设 X =1 表示我们进行了治疗,而 X =0 表示我们没有进行治疗,而 Y 表示他们健康状况的最终影响(“改善”、“稳定”、“恶化”)。患者的特征包括Z_ 1 =年龄,Z_ 2 =性别,Z_ 3 =患有糖尿病,这些特征也会影响他们的健康状况。****

图 6 : (a)治疗 X 和患者特征 Z =(Z_1 =年龄,Z_2 =性别,Z_3 =“是糖尿病患者”)对其健康 Y 的综合影响的因果图,(b)当实验者自己选择他管理治疗的患者时的因果图,从而潜在地将 Z 转换成混杂因素,(C)通过随机投掷硬币来管理治疗,从而将治疗与任何潜在的混杂因素分离。

相应的因果图如图 6 (a)所示。对于这个图,我们想要计算p(y| do(x))。如果实验者选择她将对哪个患者实施治疗,她可能会无意中将特征 Z 转换成混杂因素,这将同时影响实施治疗的决定 X 和患者的健康 Y 。这表现在图 6 (b)中。RCT 程序将实施治疗的决定从属于抛完美硬币 C 的结果,其结果既不受 Z 的影响,也对 Y 没有任何直接影响。因此,它切断了与测量变量 X 相同的输入链接,这些链接必须被移除以定义(7)中的p(y| do(X))。在这样的情况下p(Y|XC)=p(Y|X),因为 X 挡住了 CY 之间的路径。因此(9)暗示着p(y| do(x)=p(y|x)。换句话说,当使用 RCT 程序时,观察 X 对预测 Y 具有与规定 X 的值相同的效果。****

我们能从原始数据推断出因果图吗?

在 2.3 和 2.4 节中,我们将描述回答上述可识别性问题的工具,假设给我们一个因果图 G 并且它的一些变量 Z 可以测量。但是如果我们首先没有因果图 G 会怎么样呢?我们能直接从数据中推断出来吗?这是一个引发了很多争议的世俗问题。在日常生活中,我们都使用一些线索来确定因果关系,最重要的一个是假设原因总是先于结果。然而,分析这些因果关系的时间方面将很快推动我们讨论过去和未来之间不对称的起源以及物理学中的其他基本问题[8]。尽管这些问题很有趣,但我们不会在这里讨论这些问题,因为这将使我们远离分析数据模式的主题,数据模式可以识别由结构方程(6)定义的函数因果关系。我们参考[1]来了解更广泛的因果关系。

统计学家的共识一直是,从数据中找出一个因果模型是完全不可能的。事实上,一般来说,这是不可能的,因为我们将确认。然而有趣的一点是,与这种普遍的看法相反,在实际相关的情况下,这种对 G 的识别是可能的,至少是部分可能的。同样,对这些问题的彻底讨论超出了这篇短文的范围。因此,我们仅限于总结[2]中的一个重要结果,该结果表明,假设对奥卡姆剃刀的特定解释,当 G 中的所有变量 X 都可测时,可以推断出因果图 G 的一个等价类。

所以我们假设变量 X 都是可测的,它们的概率分布是 p ( x )。在没有进一步假设的情况下,可能存在许多与 p 兼容的不同因果图。因此,我们需要进一步限制我们试图推断的因果模型。我们确实应该提出两个这样的限制。第一个,极小性,符合标准的科学实践,并将我们的搜索限制在最简单的可能因果图 G 上,第二个,稳定性,将是因果模型 M 本身的一个条件。为了精确地将它们公式化,我们假设由(6)定义的因果模型 M 取决于参数 θ ,这些参数定义了确定性相关性 f_j 和噪声变量ϵ_ j 的分布。因此,这种参数化的因果模型 M 实际上定义了一组分布 p ,其可以通过改变 M 的参数 θ 来获得。

  • 给定两个因果图 G _1 和 G _2,考虑与这些图相关联的参数化模型 M _1 和 M _2。每当由M2 生成的分布集合包含由M1 生成的分布集合时,我们说因果图G1 比G2更好。换句话说,与 G _1 兼容的分布集小于与 G _2 兼容的分布集。一个因果图 G 被称为一组图中的极小,当该组中没有其他图优于 G 时。****
  • 给定由具有固定参数值 θ 的因果模型 M 生成的分布 p ,我们应该确保 p 没有仅适用于那些特定参数值集的偶然独立关系。将 θ 的值更改为另一组值 θ 不应破坏任何独立性关系 X 独立于 Y | Z ,这适用于 p 。当这一点成立时,我们说因果模型生成了一个稳定的分布[2]。

关于观察等价的定理 1 暗示如下:

定理 3 :如果一个因果模型 M 生成一个稳定分布 p 那么,直到观察等价,存在一个唯一的最小因果图 Gp相容**

一类观测等价图可以用一种叫做模式【2】的表示法来图形化地表示。模式是部分有向的 DAG,其中一些边是有向的,而其他边不是。有向边对应于模式中所有成员共有的边,而无向边可以指向任何一个方向。珀尔和维尔马[6]开发了一种算法,即 IC 算法(用于推断因果关系),该算法构建了与一组可观察变量上的任何稳定分布 p 相关的模式。关于 IC 算法的详细描述和 IC 对具有潜在变量的因果模型的各种扩展,我们参考[2]。Pearl 获得的其他有趣结果与因果图中某些假设的可证伪性有关[12,13]。

2.3 用图表回答因果关系问题

正如我们前面所看到的,因果关系 p ( y |do(x)一旦因 X 的亲本 PA( X )可测量就可识别。公式(9)通过显示我们应该如何根据直接原因的先验概率 p (pa)调整条件p(y|x,pa)来回答这个问题。在这一小节中,我们描述两个简单的图形标准,它们在更一般的情况下回答这个问题。

后门准则

以下成立[2,3]:

定理 4 : 当一组 Z 可观测的 r.v .满足以下两个条件时

  • 没有变量 Z_i 是 g 中 X 的后代,换句话说,X 应该对 Z 中的任何变量都没有影响。
  • 变量组 Z 应该阻塞 G 中 X 和 Y 之间的任何路径γ,该路径有一个进入 X 的传入箭头(后门路径)。

当两个条件都被验证时,我们得到缩减:

上述缩减公式可以被认为是基本调整公式(9)的推广。定理 4 中的两个条件都可以很容易地进行系统测试。可以尝试各种设置 Z 来优化其测量成本。

图 7 :使 X 对 Y 的干预可识别的一组 r.v. Z =(Z_3,Z_4)的例子。事实上,z3 是一个封闭γ1 和γ2 的测量链,而 Z4 封闭γ3 作为测量链,γ4 作为测量叉。另一方面, Z '=(Z_4)不会,因为路径γ_2 仍然被 Z_4 这个被测量的碰撞体所阻挡。

图 7 给出了一组 Z =( Z _3, Z _4)的例子,使得 XY 的因果影响可识别,而 Z '=( Z _4)不可识别。

前门衡

定理 4 中的条件 1 要求原因 X 不应影响可观察变量 Z 。幸运的是,另一个标准,即前门标准允许我们证明 XY 的影响在其他一些情况下仍然是可识别的。考虑通过将图 7 中的 Z _1 到 Z _5 合并到我们假设未观察到的组 U 中,然后将 Z _6 重命名为 Z 并表示 Z =( Z )而获得的图 8 所示的情况。该变量 Z 直接受 X 的影响,不阻断路径XUY。因此 Z 不符合这两个后门标准。

图 8 :满足前门标准应用条件的因果图。

请注意,在图 8 的示例中,以下三个条件成立:

  • 变量 Z 阻塞了从 XY 的有向路径。
  • XZ 的所有后门路径被阻断。事实上,在示例中,路径XUYZY 处受阻,这是一个无条件碰撞器。
  • ZY 的所有后门路径都被 X 阻断。事实上,在示例中,路径ZXUY被条件链 X 阻挡。

当这三个条件都满足时,我们说变量 Z 满足相对于 XY 的因果影响的前端标准。以下情况成立:

定理 5 : 当变量 Z 满足变量 X 对变量 Y 的影响的前门准则时,那么这种影响是可识别的,由给出

请注意,变量 u 没有出现在上述简化公式中,而未测量变量则应该出现在公式中。因此,这第二个图形工具补充了我们发现可识别因果图的武器库。我们将在 2.4 小节中作为 do 微积分的一个应用例子来证明它。

2.4 用 Do-Calculus 回答因果关系问题

图形工具很好,因为它们允许我们识别因果关系,而不必做任何数学计算。不幸的是,这并不总是可能的。在这一小节中,我们提出了三个简单的代数规则[3],它们可以组合起来转换包含两个普通条件的表达式。| x 和干预措施。|do( x )转化为等价表达式。这些规则是做微积分的规则。当然,我们的目标是找到这些转换的适当顺序,以最终摆脱所有这些。|do( x )以证明干预是可识别的。

假设我们给定了因果图 G 中变量 XYZW 的四个不相交子集。让我们用来表示

G 分别删除进入 X 和离开 X 的链路得到的图形。为了表示输入和输出链接的同时删除,我们使用如下符号

最后, Z ( W )将表示一组Z-节点,它们不是中任何W-节点的祖先

在下面的 3 个规则中, X 总是作为 do( X )干预进入,而 W 作为被动观察出现, Y 作为我们想要预测的结果。给定对 X 的干预和对 W 的观察,我们还定义了对 Y 的混合条件概率:

定理 6 (做微积分规则):假设分布 p 是由与图 g 相关联的因果模型生成的,那么以下成立:**

  • 规则 1 [ 删除观察 ]

  • 规则 2 [ 移除干预 ]

  • 规则 3 [ 用观察代替干预 ]

这些规则概括了基本的d-分离规则(5 ),在此回忆以供比较:

事实上,当 X 为空时,( 13)是规则 1 的特例。
反过来,当我们记得干预 do( x )简单地从 G 中移除所有进入 X 的链接时,我们可以很容易地理解规则 1 作为(13)的结果。结果正是规则 1 中使用的图形。规则 2 和 3 使用该图的子图。规则 3 回答了对变量 Z 的干预是否与其被动观察具有相同效果的重要问题。规则 3 适用的最简单情况是当 G 是描述直接因果关系的双节点图 ZY

减少到两个不连接的节点,从而确保 ZY 与该图 d 分离。

一个例子——推导前门公式

作为 do 演算应用的一个例子,让我们看看我们如何使用它们来推导前门规则(11),参考图 9 中我们需要检查的各种子图。

图 9 :前门规则中考虑的原图 G 以及用于其推导的子图。

让我们跟随[3]一步一步地完成这个过程。

首先,使用求和规则和定义(12),期望的量可以写成:

现在我们可以应用规则 3 来删除(14)的第二个因子中的 x 上的 do 运算符

现在让我们关注(14)中的因子p(y|z**,do( x )。再次使用规则 3,我们可以用 do( z )代替 z**

规则 2 现在允许从(16)的右成员中删除 do( x )动作,因此

让我们这样计算p(y| do(z))。在 x 上应用混合调节和边缘化的定义(12)

我们可以应用规则 2,它隐含着p(x| do(z)=p(x)。我们也可以应用规则 3,它隐含着p(y|x,do(z)=p(y|xz )。总共(18)和这最后两个结果意味着

结合(16)、(17)和(19),我们得到

最终,结合(14)、(15)和(20),我们得到了想要的结果

这与前门规则(11)相同。

如这个例子所示,do 演算允许可识别性情况的优雅推导,但绝不是显而易见的!相反,它需要相当多的直觉和实践。

做微积分的长处和局限

do 演算的规则已经被证明是完全的【10】,在这个意义上,如果一个干预是完全可识别的,那么确实存在这 3 个规则的序列,它们将产生一个没有任何 do 运算符的表达式。不幸的是,没有通用的规则来决定一个表达式是否可识别[2]。事实上,应用 do 演算的一个主要困难是,没有一个通用的指导原则来告诉我们在每一步应用哪个规则。幸运的是,勇敢的人已经在编辑可识别和不可识别的因果图,我们可以重复使用。图 10 显示了可识别的例子。

图 10 :简单因果图的例子,其中 X 对 Y 的影响是可识别的。所有的图都是极大的。

重要的一点是,一旦我们认识到以下两个事实,我们就可以从这些图中生成更多可识别的图:

图 11 :简单因果图示例,其中 X 对 Y 的影响不可识别。

  • ****给任何因果图 G 增加一条边只会降低新图被识别的几率。这是我们一直在讨论的所有规则的直接结果,无论是图形的还是代数的,最终都等于测试在 G 的子集内的一些路径是否被阻塞。添加一条边显然会增加要测试的路径数量,从而降低所有路径都被阻塞的可能性。
  • ****在图形边缘添加观察变量会产生相反的效果。这只会增加新图可识别的机会,因为它增加了一个观察链,这是一个额外的阻塞点,只会增加组或变量之间的 d 分离的机会。

图 10 中显示的所有图都是最大的,在这个意义上,给它们中的任何一个增加一条边都会破坏它们的可识别性。因此,它们是最有用的列表。图 11 显示了不可识别的例子。

3.简单业务示例的因果分析

因果分析的例子通常来自农学、社会科学或经济学等依赖于复杂因果模型的领域。我们选择说明因果分析是如何在最普通的商业例子中自然发生的。

3.1 评估忠诚度活动的有效性

客户对服务的满意度通常可以从他们的可观察行为来判断,例如访问网站的次数或使用该服务所花费的时间。该信息可以帮助服务提供商识别一些客户打算离开服务的早期迹象。然后,营销部门可以决定发起一场忠诚度运动,旨在留住那些信心动摇的顾客。这些活动当然是有成本的,因此能够评估它们的有效性是很重要的。某类忠诚度活动真的对流失率有影响吗?

为了回答这个问题,让我们形式化这个问题。首先,假设 U 是一个二元变量,它对应于客户在成为任何忠诚度活动的目标之前是否离开服务的意图。当然,这将是一个不可测量的变量。这个初心 U 当然对客户的行为有可以衡量的影响,姑且称之为 Z 。该行为 Z 将依次决定服务提供商是否应该将该客户作为忠诚度活动的目标。我们姑且称这个决定为 X 。最终,客户取消服务的最终决定还是一个二元变量,称之为 Y 。客户的最终决定当然取决于他的最初意图 U 以及他是否已经成为活动的目标( X )。因此,从形式上来说,我们的问题可以转化为:当我们测量 Z 时,我们能识别出成为目标 X 对最终决策 Y 的因果影响吗?图 12 显示了相应的因果图。

图 12 :忠诚度活动对流失率影响的因果模型。

该图只是图 10 中可识别图列表中的图(c ),去掉了从 ZY 的直接链接。因此它是可识别的。另一方面 Z 满足定理 4 中后门准则的两个条件。它不是 X 的后代,它阻塞了 XY 之间的后门路径,因为它是一个观察链。因此,( 10)给出了将 XY 的因果影响明确缩减为可观察量。

3.2 保险公司的索赔准备金

当被保险人提出索赔时,保险公司通常会留出一定的金额。当报道人身伤害时尤其如此。最后的赔偿显然取决于损坏的程度。但是,正如保险公司已经意识到的那样,这种补偿也将取决于初始准备金。此处因果分析的目的是确定这一规定对被保险人获得的最终赔偿的影响。

U 为完整的权利要求特征。其价值在报告时未知,但它将决定被保险人的申报 Z 和调查后给予的最终赔偿 Y 。初始评估 Z 直接决定专家的准备 X ,进而影响最终补偿 Y 。因此,因果图与图 12 完全相同,因此,同样的后门简化公式(10)也适用于此。

3.3 销售人员培训对营业额的影响

为了提高销售团队的效率,公司可以投资培训。这有一个很容易衡量的成本 X ,希望这将有助于通过增加销售来增加营业额。因此,因果关系将是直接的,因此可以轻易识别。然而,至少有一个不可测量的混杂变量破坏了这种可识别性,即竞争压力 U 。的确,强大的竞争压力会鼓励对培训工作的投资,但同时也会影响人员流动。不过幸运的是,如果我们能在从 XY 的因果链中找到一个可测量的“去组合”变量 Z ,我们就能恢复可识别性。销售人员的技能和动机由这些培训诱导,并通过调查或民意测验来衡量,可以发挥这一作用。因果图如图 13 所示,与图 8 相同,图 8 是前门规则适用的基本图。因此,我们可以使用前门简化公式(11)。

图 13 :培训投资对销售人员技能和动机评估的影响因果图。

3.4 定价对销售的影响

一家公司在一种产品上的营业额 Y 是该产品价格 X 和销售量 Z 的函数。例如 Y 可以与 X * Z 成比例。现在价格 X 既影响营业额 Y 也影响销售量 Z ,因为较低的价格通常会增加销售量。这样,相应的因果图将是可识别的,因为它对应于来自图 10 的可识别图列表中的图(b ),其中去除了 YZ 之间的混淆链接。不幸的是,作为未知变量的竞争压力 U 是影响价格 X 和销售量 Z 的混杂因素,使得图 14 中的图表无法识别,因为它与图 11 中的无法识别图表列表中的图表(c)相同。

图 14 :由于竞争压力,定价对营业额的影响无法识别。

4.数据科学家值得了解的东西?

一旦一个人完全理解了因果革命所暗示的范式转变的重要性,许多新来者就会产生一个问题。为什么在我学习统计、概率或机器学习的时候,从来没有人告诉过我这些?作为一名数据科学家,我怎么从来没有听说过做微积分呢?在实践中真的有用吗?在哪个地区?这个大概有几个答案。我们在下面列出了其中的一些。

  • 我们看到的第一个原因是文化性质的。例如,在[5]中已经很好地分析了这一点。事实上,“因果关系”这个词在统计学界长期以来几乎是一个禁忌,统计学界仍然忠实于上个世纪这门学科创始人如皮尔逊和费希尔的经典联想主义观点。他们认为数据中不可能有因果关系的证据(RCT 除外)。朱迪亚·珀尔用自己所有的毅力和科学高度扭转了人们对因果关系和统计学关系的看法。显然,这种范式转变还没有渗透到更新的数据科学社区中。
  • 我们在第 2 节中提出的图形和代数机制显然只有在因果图 G 不是平凡的时候才有意义。这解释了为什么社会科学、经济学、医学或农学等领域都发展了丰富的因果模型,并从这种新的因果观中受益最多。然而,对于像 G = XY 这样的基本因果关系,对原因 X 的被动观察和对原因的干预之间没有区别。数据科学家设计的许多用例都属于这一类,也许在某些情况下只是偶然。但是没有这样的运气,忽略观察和干预之间的差异可能会导致预测错误。我们在第 3 节中给出了一些这种情况的例子。
  • 虽然图形规则相当容易理解,但是将 do 演算明智地应用到新的因果图中无疑需要技巧和直觉。正如在[5]中所建议的,对于那些负担不起或不想掌握这种代数机器的人来说,do 微积分肯定可以从一本食谱中受益。
  • 最后一个原因,也是一个更主观的原因,与珀尔的写作风格有关,这种风格有时可能缺乏一点简洁。这肯定会让许多读者气馁,甚至是那些在统计学和概率论方面具备所有先决条件的读者。珀尔用大量的历史轶事、例子和评论来满足他的读者,有时这与关键数学事实的清晰呈现背道而驰。因果关系革命可能仍然缺乏一个简洁的教科书般的主题介绍。

统计学的创始人肯定是对的,他们坚持认为,一般来说,我们不能仅仅从数据中推断出因果关系。但是在他们新生学科的热情中,他们的许多弟子和追随者不知何故变得过分热情。他们忽略了在大多数情况下我们有比数据更多的可用信息!我们对世界如何运转有一些先验知识!也许不是一个完全成熟的因果模型,但至少是一个部分因果图。Pearl 告诉我们的是,在一些有利的条件下(我们在第 2 节中讨论过),我们可以将这两种知识结合起来,以预测干预对系统的影响。如果事实证明这些预测与观测不符,我们只需更加努力,想出一些更好的模型。但是,无论如何,我们不得不放弃仅仅通过观察来自动发现世界如何运转的希望。大自然不会在一些愚蠢的算法面前展示它的魅力。她是一个要求很高的女主人,希望我们能像好奇和有创造力的头脑一样,与她进行一次深思熟虑的谈话。所以,让我们欢呼吧,因为这就是科学如此有趣的原因!

参考

  1. J.Pearl,D. Mackenzie (2018),为什么之书,基础书籍。
  2. J.珀尔(2009),因果关系,剑桥大学出版社。
  3. J.珀尔(1995),实证研究的因果图,生物计量学(1995),82,4,第 669–710 页。
  4. D.R. Cox (1958) 实验计划,约翰威利父子公司,纽约州。
  5. 南鲍威尔(2018),原因之书:因果的新科学,多学科评价杂志
    第 14 卷,2018 年第 31 期。
  6. J.珀尔和 t .维尔马(1990),因果模型的等价和综合,第六届人工智能不确定性会议论文集,第 220-227 页。
  7. J.珀尔和 t .维尔马(1991),一种推断因果关系的理论,《知识表示和推理的原则:第二届国际会议论文集》,第 441-452 页。摩根考夫曼,加州圣马特奥。
  8. H.赖兴巴赫(1956),时间的方向,加州大学出版社,柏克莱。
  9. 栗色 M. Bishop (2016),模式识别与机器学习,斯普林格出版社纽约公司。
  10. Y.黄,M. Valtorta (2006), Pearl 的干预演算完成,06:第二十二届人工智能不确定性会议论文集,第 217–224 页。
  11. D.Galles 和 J. Pearl (1995),测试因果效应的可识别性,UAI-95:第十一届人工智能不确定性会议录,第 185–195 页。
  12. J.Pearl (1994),从贝叶斯网络到因果网络。贝叶斯网络与概率,第 1-31 页。伦敦:阿尔弗雷德·沃尔特。
    推理
  13. J.Pearl (1995),间接实验的因果推断。阿提夫。英特尔。医学。第 7 卷,第 561-582 页。

arXiv 上 LaTeX 排版的 PDF 版本

RecoTour III:使用 Mxnet 和 Pytorch 进行协同过滤的可变自动编码器

原文:https://towardsdatascience.com/recotour-iii-variational-autoencoders-for-collaborative-filtering-with-mxnet-and-pytorch-710c924fa2fd?source=collection_archive---------25-----------------------

这篇文章和这里的代码是一个更大的名为 RecoTour 的报告的一部分,在那里我通常探索和实现一些我认为有趣和/或有用的推荐算法(见 RecoTour 和recotouri)。在每个目录中,我都包含了一个README文件和一系列解释笔记本,我希望它们能帮助解释代码。我一直不定时的加算法,有兴趣的继续关注。

像往常一样,让我首先感谢做了艰苦工作的相关人员。这篇文章和配套的报告是基于论文“协同过滤的变分自动编码器”[1]和“自动编码变分贝叶斯”[2]。这里和回购中的代码部分受到了来自 Younggyo Seo 的实现的启发。我根据自己的编码偏好修改了代码,并添加了一些选项和灵活性来运行多个实验。

深入研究用于协同过滤的变分自动编码器的原因是因为它们似乎是少数基于深度学习的算法之一(如果不是唯一的),比那些使用非深度学习技术的算法获得更好的结果【3】。

在整个练习中,我将使用两个数据集。亚马逊电影和电视数据集【4】【5】和电影镜头数据集。后者用于确保我获得的结果与论文中的一致。亚马逊数据集比 Movielens 数据集更具挑战性,因为它的稀疏度是 movie lens 数据集的 13 倍。

本文中的所有实验都是使用 AWS 上的 p2.xlarge EC2 实例运行的。

越详细, 原文本帖子在我的博客中发表。这是对内容的总结,更侧重于实现/代码和相应的结果,而不是数学。

1.部分正则多项式变分自动编码器:损失函数

在本节中,我假设读者对可变自动编码器(vae)有一些经验。如果不是这样,我推荐阅读金马和韦林的论文、梁等人的论文,或者原帖。在那里,读者将找到我们在实现部分正则化多项式变分自动编码器(多 VAE)时将使用的损失函数的详细推导。这里,我将只包括最后一个表达式,并简要介绍一些我认为有助于理解多 VAE 实现和等式(1)中的损耗的附加信息。

让我首先描述一下记数惯例。继梁等人 2018 之后,我将用 u ∈ {1、…、 }索引用户,用 i ∈ {1、…、 I }索引条目。用户逐项二进制交互矩阵(即点击矩阵)是x∈ℕ^{u×I}并且我将使用小写字母【xᵤ=x_ { u1 },…,x_ { 0

根据这一符号,多 VAE 损失函数定义为:

Eq 1。多 VAE 损失函数

其中 M 为小批量。求和中的第一个元素仅仅是点击历史的对数似然性【xᵤ】【条件反射】到潜在表示zlog((xᵤ||z**)(见下文)。第二个要素是当编码器和解码器分布都是高斯分布时 VAEs 的 kull back-lei bler 散度(见这里的)。

在我们开始写代码之前,我们还需要一些细节。用户的点击历史,定义为:****

Eq 2。点击用户的历史记录 u

其中nᵤ=ᵢnᵤᵢ为用户 u 的点击总数。正如我之前提到的z ,,的潜在表示,并且被假定为从一个标准的高斯先验(z)√在多值的实现过程中, z 需要从一个近似的后验概率(zx)(也假设为高斯)。由于涉及采样时计算梯度是…" 复杂的", Kingma 和 Welling 介绍了所谓的重新参数化技巧(请阅读原始论文、原始帖子或任何多种在线资源.)以了解有关重新参数化技巧的更多细节),以便采样后的 z ******

Eq 3。取样的 z (因此上标有‘s’)将用于多值的实现

方程 3 中的 μσ 是神经网络的函数,ϵn(0,I)是高斯噪声。当我们看到相应的代码时,他们的计算将变得更加清晰。最后,等式(2)中的π( z )是π(z)=soft max(z)。****

在这个阶段,我们几乎拥有了实现等式(1)中的多值及其损失函数所需的所有信息:我们知道什么是【xᵤ】z【ᵤ】,μ** 和 σ 将是我们的神经网络的函数,而π就是 Softmax 函数。从等式(1)讨论剩下的唯一“字母”是 β 。****

在 VAEs 的上下文中查看等式(1)中的损失函数,我们可以看到第一项是“重建损失”,而 KL 散度作为正则项。考虑到这一点,梁等人增加了一个因子 β 来控制正则化的强度,提出了 β < 1。为了更深入地反映 β、的作用,以及更好地解释多 VAE 损失函数的形式,请阅读原始论文或原始帖子。

事不宜迟,让我们来看看代码:

2.准备数据。

正如我在帖子前面提到的,这是对原帖子的总结。考虑到这一点,我将在这里简要描述如何在不包含代码的情况下准备数据。读者可以在原始实现、原始发布或回购中找到与数据准备相关的代码。

基本上,作者将数据分为培训、验证和测试用户及其相应的交互。然后,他们将验证和测试交互分成所谓的“验证和测试训练以及测试集”。**

我知道这听起来很复杂,但并不复杂。“验证 _ 训练和测试 _ 训练集合”在这里包括总验证和测试集合的 80%,将被用于构建我们可以认为是输入二进制“图像”(即点击的二进制矩阵),该输入二进制将由经过训练的自动编码器进行“编码→解码。另一方面,“验证 _ 测试和测试 _ 测试集”包括总验证和测试集的 20%,将用于计算验证/测试时的排名指标。如果您想了解更多细节以及玩具示例,请前往回购中相应的笔记本。****

3.部分正则多项式变分自动编码器:代码

我已经使用MxnetGluonPytorch实现了多重 VAE。在这一节中,我将只关注Mxnet的实现。如果您对Pytorch的实施感兴趣,请前往回购。

与任何自动编码器架构一样,主要的两个元素是(屏住呼吸…)编码器和解码器。在原始出版物中,作者使用一个隐藏层 MLP 作为生成模型。他们说更深层次的架构并不能改善结果,在进行了 60 多次实验后,我发现这是真的。带着这样的想法,我们先来看看模型[ I→600→200→600→I ]其中 I 是项目总数:

图一。多 VAE 建筑。这些颜色是我试图引导眼睛通过重新参数化的技巧过程。

在代码中,图(1)是:

3.1 编码器

片段 1。多 VAE 编码器。注意第 20 行中的 μ分割,作为重新参数化技巧的一部分。这种分离对应于图 1 中的绿色和红色**

3.2 解码器

片段 2。多 VAE 解码器

3.3 完整型号

片段 3。多 VAE 模型。注意第 15–18 行发生的重新参数化。线 18 对应于图 1 中的黄色

在我继续之前,让我提一下(并欣赏)一下MxnetGluon所提供的许多美好的事物中的一个。当我们定义向前传球,或者更准确地说,hybrid_forward传球时,你会注意到HybridBlock和输入F(后端)的使用。人们可以写一个完整的帖子,介绍一下HybridBlocks的乐趣,以及开发Gluon的人是如何将命令式框架(例如Pytorch)的灵活性和声明式框架(例如Tensorflow)的速度完美地结合在一起的。如果你想了解细节,去这里,但是相信我,这很快。**

话虽如此,我们还需要一个完整的模型,即等式(1)中的损失函数。

片段 4。多 VAE 损失的实现(即等式(1))

在论文中,作者还使用了多项式去噪自动编码器(Mult-DAE)。除了没有任何变化之外,其架构与 Mult-VAE 的架构完全相同。我已经实现了 Mult-DAE,并用它进行了多次实验。然而,鉴于它的简单性和已经很长的帖子,我不会在这里讨论相应的代码。

请注意,按照最初的实现,我在多 VAE 和多 DAE 的输入层应用了 dropout,以避免过度拟合。我还包括在整个网络中应用辍学的选项。

还要注意的是,尽管我研究了不同的漏失,解决漏失、权重衰减、 β 等与架构之间相互影响的最佳方式是使用“ proper ”超参数优化。

4.培训、验证和测试

4.1 退火时间表

如前所述,我们可以将 Kullback-Leiber 散度解释为一个正则项。考虑到这一点,在一个受 Samuel R. Bowman 等人 2016【6】启发的程序中,梁和合著者在大量训练步骤中缓慢地线性退火 KL 项(即增加 β )。

更具体地说,作者将 KL 散度一直退火到 β = 1,在该过程中使用的总历元数的大约 80%处达到该值。然后,他们根据峰值验证指标确定表现最佳的 β ,并使用相同的退火计划重新训练模型,但在达到该值后停止增加 β

如果我们去他们的实现,这些是过程的细节:使用 500 的批量,他们设置退火步骤的总数为 200000。假设训练数据集的大小为 116677,每个时期有 234 个训练步骤。它们的anneal_cap值,即训练期间达到的最大退火,被设置为 0.2,并且在训练期间它们使用以下方法:

片段 5。原始退火时间表

其中update_count每训练一步/批次增加 1。他们使用 200 个时期,因此,如果我们做数学计算,当update_count / total_anneal_steps = 0.2 时,即在 40000 个训练步骤之后,或者换句话说,在大约 170 个时期之后,即时期总数的 80%之后,anneal_cap值将停止增加。

考虑到这一点,我的实现如下所示:

片段 6。我稍微调整了一下退火计划。

一旦设定了total_anneal_steps,剩下的唯一事情就是定义培训和验证步骤。如果你熟悉Pytorch,接下来的两个功能你会觉得很熟悉。

4.2 培训步骤

片段 7。使用 Mxnet 的胶子的训练步骤

4.3 验证步骤

代码片段 8。使用 Mxnet 的胶子的评估步骤。

我在这个 repo (以及相应的帖子)中的多个笔记本里广泛讨论过评测指标(NDCG@k 和召回@k)。因此,考虑到这一点,也为了不使这篇文章成为一篇更“无限的帖子”,我将不在这里描述相应的实现。如果您想了解这些评估指标的详细信息,请转到[utils](https://github.com/jrzaurin/RecoTour/tree/master/Amazon/mult-vae/utils)中的[metrics.py](https://github.com/jrzaurin/RecoTour/blob/master/Amazon/mult-vae/utils/metrics.py)模块。这里的代码对最初的实现中的代码做了很小的修改。

4.4。运行过程:

让我们定义模型,准备设置并运行一个小样本(当然,忽略打印的结果。我只想说明如何运行模型)

片段 9。运行模型

再加上一些铃声和铃声(例如可选的学习率计划、提前停止等等),这就是你将在[main_mxnet.py](https://github.com/jrzaurin/RecoTour/blob/master/Amazon/mult-vae/main_mxnet.py)中找到的代码。

在我进入下一个,也是最后一个部分之前,我想简单地评论一下我通常在这些科学出版物中发现的一些东西。通常,一旦他们在验证集上找到了最佳超参数,他们就在测试集上测试模型。

在“现实生活”场景中,会有一个额外的步骤,即合并训练集和验证集,用最佳超参数重新训练模型,然后在测试集上进行测试。无论如何,因为这里我的目标不是构建一个真实的系统,所以我将遵循最初的实现中的相同过程。

现在是时候看看用PytorchMxnet得到的结果了。

5.结果摘要

让我再次提醒一下第 4.1 节中描述的退火时间表。基本上我们逐渐退火到 β =1,在总次数的 80%左右达到,记录最佳退火参数( βbest )。然后,我们应用相同的退火程序,但是使用 βbest ,即,我们退火到 βbest 在总周期数的大约 80%处达到该值。

图二。与梁等人 2018 年的相同的退火时间表,适用于 3 种不同的架构以及使用PytorchMxnet的 Movielens 和 Amazon 数据集。在退火程序中,β= 1 \β= 1β= 1 在 170 个时期达到(200 个时期中的 85%)

表 1。在我运行的所有实验中表现最好的实验(根据 NDCG@10 )(可以在回购的``run_experiment.sh文件中找到)。包含所有实验运行结果的 csv 文件可以在 repo 的all_results.csv`文件中找到。

图 2 使用PytorchMxnet为 3 种不同的架构以及 Movielens 和 Amazon 数据集复制了相同的退火时间表。在退火程序中,在 170 个时期(200 个时期中的 85%)达到 β =1。此外,我还使用了 20 个时期的"耐心"提前停止,这就是为什么没有一个实验达到 200 个时期。图中竖线表示达到最佳NDGC@100的时期,对应的 β 值表示在顶部 x 轴。**

另一方面,表 1 显示了我在所有实验中获得的最佳结果,您可以在文件run_experiments.sh的报告中找到。

乍一看,这两种深度学习框架的行为有多么不同是显而易见的。我发现PytorchMxnet表现得好一点,并且在实验中更加稳定。这是我每次使用这两个框架进行相同练习时不断发现的事情。比如这里的,用的是分层注意力网络。实际上,我认为这是因为我知道(或用过)的PytorchMxnet多。尽管如此,在这个阶段,我很清楚我需要在这两个深度学习库之间进行适当的基准测试。

关注图 1 所示的结果,第一个明显的结果是Mxnet实现在很少或没有正则化的情况下表现得更好。事实上,我已经运行了 60 多次实验,如表 1 所示,使用Mult-VAEMxnet时的最佳结果是在没有正则化的情况下获得的,即使用重新参数化技巧的去噪自动编码器。此外,使用Mult-DAE (NDCG@100 = 0.424)可以获得使用Mxnet的最佳总体指标。

如果我们关注数据集之间的差异,首先显而易见的是,Amazon 数据集的指标明显小于 Movielens 数据集。这当然是意料之中的,因为亚马逊数据集比 Movielens 数据集稀疏 13 倍,也就是说,挑战性更大。此外,我们看到Pytorch实现对数据集和架构都表现出非常稳定的行为,在 Amazon 数据集的情况下,在训练期的后期达到最佳NDCG@10。同样,这与Mxnet实现的情况不同,在这种情况下,我们看到一致性较低,并且在两个数据集的训练期间很早就达到了最大值NDCG@10

图 3。NDCG100(称为n100 in the figure)针对以下架构绘制了解码器的第一维:I)I→150→50→150→I,ii)I→300→100→300→I,iii)I→600→200→600→*I*****

另一方面,梁等人在他们的论文中提到,更深层次的架构并没有带来任何改善。这与我在实验中发现的结果是一致的。事实上,图 3 显示了四种不同架构的 NDCG100(图中标记为n100)与解码器第一维度的关系。正如我们在图中看到的,即使集中在具有相同层数的架构中,每层增加神经元也不会有特别大的帮助(Movilens 和 Amazon 数据集分别为 50 和 200)。

图 4。NDGC@100 (n100)和 Recall@20 (r20)和 Recall@50 (r50)针对我运行的所有实验的损失绘制

在我结束这个练习之前,我想强调一下我过去已经讨论过的一个结果(见这里),如图 4 所示。

图 4 示出,一般来说,最佳排序度量不对应于最佳损失值。即使点击的输入矩阵的重建可能更差,排名度量仍然可能改进。这是一个重要且常见的结果,在构建真实世界的推荐系统时,人们必须记住这一点。当构建推荐算法时,我们对实现最佳分类/回归损失不感兴趣,而是对产生最佳推荐感兴趣,这与信息检索效率更相关,因此与排名度量更相关。关于推荐系统的更多信息,我推荐这本神奇的书。那本书的第 7 章主要关注评估指标。

就这样,我用PytorchMxnet结束了我在Mult-VAE的实验

接下来,我想添加到回购中的最直接的项目是:

  1. 用于协同过滤的顺序变分自动编码器【7】
  2. LightGCN:简化图卷积网络并为其供电,建议 [8]

如果你设法读完了所有这些,我希望你会觉得有用。

参考资料:

[1]达文·梁,拉胡尔·g·克里希南,马修·d·霍夫曼,托尼·杰巴拉,2018。用于协同过滤的可变自动编码器: arXiv:1802.05814v1

[2]迪德里克·P·金马,马克斯·韦林,2014 年。自动编码变分贝叶斯: arXiv:1312.6114v10

[3]毛里齐奥·费拉里·达克雷马、保罗·克雷莫内西、迪特马尔·扬纳克。我们真的取得了很大进展吗?近期神经推荐方法令人担忧的分析: arXiv:1907.06902v3

[4] J .麦考利,c .塔吉特,j .史,a .范登亨格尔。2015.基于图像的风格和替代品建议。 arXiv:1506.04757v1

[5] R .何,j .麦考利,2016。用一类协同过滤对流行趋势的视觉演变建模。 arXiv:1602.01585v1

[6]塞缪尔·r·鲍曼,卢克·维尔尼斯,奥里奥尔·维尼亚尔斯,安德鲁·m·戴,拉斐尔·约泽福维茨,萨米·本吉奥,2016。从连续空间生成句子: arXiv:1511.06349v4

[7]诺维恩·萨克德瓦,朱塞佩·曼科,埃托雷·里塔科,维克拉姆·迪普,2018 年。用于协同过滤的顺序变分自动编码器: arXiv:1811.09975v1

[8]何湘南,邓宽,,,,2020。LightGCN:简化图卷积网络并为其供电的建议 arXiv:2002.02126v2

使用 reactable 在 R 中重新创建出版物质量的交互式表

原文:https://towardsdatascience.com/recreate-publication-quality-interactive-tables-in-r-using-reactable-187407bc9702?source=collection_archive---------35-----------------------

复制《经济学人》的表格,只在 R

《经济学人》最近发布了一系列关于“超额死亡率”的国家级数据集,超额死亡率一词用于描述“死于任何原因的总人数与同一地点同一时间的历史平均值之间的差距。”更简单地说,这种方法捕捉到了发生了多少不该发生的死亡事件。

(免费中!)的文章,我偶然发现了下表:

我以为桌子是干净的,发出了明确的信息。内联条形图的添加不会造成干扰,但仍有助于读者了解数据。这是一张相当漂亮的桌子。最近偶然看到 Greg Lin 的包[reactable](https://glin.github.io/reactable/index.html),我想这可能是一个很好的机会来尝试重新创作上述作品。

(巧合的是,当我在做这个项目的时候,Malcolm Barrett 发布了一个类似的博客帖子,记录了他使用gt重新制作 NYT 桌子的过程。看看吧!)

装载包

我们的过程使用标准的包:reactable(显然),htmltools作为它的伙伴,lubridate用于日期和时间,hrbrthemes用于经济学家的字体,tidyverse用于通用数据争论。

library(reactable)
library(htmltools)
library(lubridate)
library(hrbrthemes)
library(tidyverse)

收集数据

如果您对数据收集和清理过程不感兴趣,您肯定可以跳过这一步。

不幸的是,这个项目中最耗时的步骤之一是获取与《经济学家》杂志文章中使用的格式相同的数据。他们发布的数据以一系列国家级 CSV 的形式出现。虽然这有助于国家级别的分析,但这意味着我们必须将数据修改为连接格式才能创建一个表。

让我们从创建一个函数开始,该函数读入每个单独的 CSV ,选择相关的列,并将特定的数据帧存储在全局环境中。

create_dataframe <- function(country) {
  ## for URL (below)
  country <- str_replace(country, " ", "_")

  ## read in CSV, given country parameter
  data <-
    readr::read_csv(
      paste0(
        '[https://raw.githubusercontent.com/TheEconomist/covid-19-excess-deaths-tracker/master/output-data/excess-deaths/'](https://raw.githubusercontent.com/TheEconomist/covid-19-excess-deaths-tracker/master/output-data/excess-deaths/'), country, '_excess_deaths.csv'
      )
    )

  ## select relevant columns
  data <- data %>%
    select(
      country,
      region,
      start_date,
      end_date,
      population,
      total_deaths,
      covid_deaths,
      expected_deaths,
      excess_deaths,
      non_covid_deaths
    )

  assign(country, rbind(data), envir = .GlobalEnv)
}

创建了这个函数后,我们想对经济学人包含的每个国家进行循环。

为此,我们从 GitHub 获取他们的来源列表,并将每个国家/地区纳入一个列表:

country_names <-
  readr::read_csv(
    '[https://raw.githubusercontent.com/TheEconomist/covid-19-excess-deaths-tracker/master/source-data/list_of_sources.csv'](https://raw.githubusercontent.com/TheEconomist/covid-19-excess-deaths-tracker/master/source-data/list_of_sources.csv')
  ) %>%
  select(country) %>%
  distinct() %>%
  mutate(country = stringr::str_to_lower(country)) %>%
  filter(country != 'all') %>%
  pull()

然后,我们循环!

for (country in country_names) {
  create_dataframe(country)
}

现在,我们有一个数据框架列表,每个框架包含一个国家的超额死亡率数据。

最后,我们将这些新数据帧合并成一个主数据集。这里,我们在dfs中定义了一个全局环境中属于结构化数据框的所有对象的列表。然后,我们一起rbind他们!

dfs = sapply(.GlobalEnv, is.data.frame)data <- do.call(rbind, mget(names(dfs)[dfs]))

但不幸的是,这还不是全部。我们需要过滤我们的数据,只包括在经济学家的表中的地方。更困难的是,该表的标识行被命名为“地区/国家”,并包括来自 CSV 中两个单独的行的数据。

让我们首先根据经济学家所包含的国家和地区进行手动定义和过滤。(这个选择似乎没有一个顺序;因此,它必须是手动的)。

good_countries <-
  c("Britain",
    "Spain",
    "Italy",
    "France",
    "Netherlands",
    "Belgium",
    "Sweden",
    "Austria")good_regions <- c("New York City", "Istanbul", "Jakarta")data_filtered_countries <- data %>%
  filter(country %in% good_countries) %>%
  filter(country == region)

因为表格中只有一行国家/地区,并相应地对它们进行分组,所以我们可以将data_filtered_regions数据框中的country变量替换为region

data_filtered_regions <- data %>%
  filter(region %in% good_regions) %>%
  # replace for the sake of the table
  mutate(country = region)

并合并:

data_filtered <-
  rbind(data_filtered_countries, data_filtered_regions)

接下来,我们注意到表格标题显示“自地区/国家前 50 例 covid 死亡以来的超额死亡率”这意味着我们需要排除在一个地区有 50 例 COVID 死亡之前的超额死亡数。

data_filtered <- data_filtered %>%
  group_by(country) %>%
  mutate(csum = cumsum(covid_deaths))

此时(仅选择相关列后),我们的数据如下所示:

data_filtered %>% 
  select(country, start_date, end_date, covid_deaths, 
         excess_deaths, covid_deaths, csum) %>% 
  reactable()

我们需要根据与新冠肺炎相关的总死亡人数和超额死亡人数对每个国家进行分组。然后,利用这两个数字,我们计算出新冠肺炎造成的超额死亡的百分比。这可以作为一个国家新冠肺炎病例漏报的衡量标准。

data_for_table <- data_filtered %>%
  filter(excess_deaths > 0) %>%
  group_by(country) %>%
  summarise(
    excess_deaths = round(sum(excess_deaths)),
    covid_deaths = round(sum(covid_deaths)),
    perc = covid_deaths / excess_deaths
  ) %>%
  select(country, covid_deaths, excess_deaths, perc)reactable(data_for_table, pagination = FALSE)

此时唯一缺少的是日期范围。为了找到并显示日期,我们需要找到给定国家/地区达到 50 个新冠肺炎病例后的第一个日期和该国家/地区数据中的最后一个日期。

我们如何做到这一点?首先,我们将创建一个名为append_date_suffix的函数,它根据给定的日期添加适当的后缀。

append_date_suffix <- function(dates) {
  suff <- case_when(
    dates %in% c(11, 12, 13) ~ "th",
    dates %% 10 == 1 ~ 'st',
    dates %% 10 == 2 ~ 'nd',
    dates %% 10 == 3 ~ 'rd',
    TRUE ~ "th"
  )
  paste0(dates, suff)
}

然后,我们将按country变量分组,并找到最小和最大日期(最小日期仅在一个国家出现 50 例 COVID 死亡后出现)。然后,我们对单个的日期和月份进行大量的格式化,并以经济学家风格将它们用破折号附加在一起。抱歉,这里发生了很多事。

dates_data <-
  data_filtered %>%
  # only looking at date ranges starting post-50 deaths
  filter(csum > 50) %>%
  group_by(country) %>%
  summarise(start_date = min(start_date),
            end_date = max(end_date)) %>%
  mutate(
    clean_start_day = format(start_date, "%d"),
    clean_start_day = append_date_suffix(as.numeric(clean_start_day)),
    clean_start_month = format(start_date, "%b"),
    clean_end_day = format(end_date, "%d"),
    clean_end_day = append_date_suffix(as.numeric(clean_end_day)),
    clean_end_month = format(end_date, "%b")
  ) %>%
  mutate(
    clean_range = paste0(
      clean_start_month," ", ## Mar
      clean_start_day, "-", ## 6-
      clean_end_month, " ", ## May
      clean_end_day ## 18
    )
  ) %>%
  select(country, clean_range)

这将创建如下所示的日期范围:

将这些日期与我们现有的数据结合起来…

data_for_table <- data_filtered %>%
  filter(excess_deaths > 0) %>%
  group_by(country) %>%
  summarise(
    excess_deaths = round(sum(excess_deaths)),
    covid_deaths = round(sum(covid_deaths)),
    perc = covid_deaths / excess_deaths
  ) %>%
  left_join(dates_data, by = 'country') %>%
  select(country, clean_range, covid_deaths, excess_deaths, perc)

我们得到了最终的数据集:

创建表

最后,我们准备好获取数据集并创建我们的表。我们可以从定义一些参数开始,这些参数使表格更容易使用,更美观。在这里,我们根据超额死亡进行排序(但不包括箭头),使其紧凑,并在一页上显示所有结果。

reactable(
  data_for_table,
  defaultSortOrder = 'desc',
  defaultSorted = 'excess_deaths',
  showSortIcon = FALSE,
  compact = TRUE,
  pagination = FALSE)

样式标题

接下来,让我们使列标题在风格上类似于 The Economist 。我们使用 reactable 的defaultColDef来实现这一点,在这里我们定义了一个带有标题和常规单元格样式的colDef。在这里,我们可以包括 CSS(您可以通过检查手边的表找到它)。在这篇文章中,你会注意到我经常提到font_es。这是来自鲍勃·鲁迪斯的《T4》。它包含经济学人 Sans Condensed 的字体名称,这是经济学人使用的字体!

reactable(
  data_for_table,
  defaultSortOrder = 'desc',
  defaultSorted = 'excess_deaths',
  showSortIcon = FALSE,
  compact = TRUE,
  pagination = FALSE,
  ######## NEW ########
  defaultColDef = colDef(
    ### define header styling
    headerStyle = list(
      textAlign = "left",
      fontSize = "11px",
      lineHeight = "14px",
      textTransform = "uppercase",
      color = "#0c0c0c",
      fontWeight = "500",
      borderBottom = "2px solid #e9edf0",
      paddingBottom = "3px",
      verticalAlign = "bottom",
      fontFamily = font_es
    ),
    ### define default column styling
    style = list(
      fontFamily = font_es,
      fontSize = "14px",
      verticalAlign = "center",
      align = "left"
    )
  )
)

格式化列

现在,我们可以开始适当地格式化特定的列。最简单的三栏是地区/国家时间段新冠肺炎占总数的百分比。在每一列中,我们都创建了一个colDef,它定义了列名以及一些样式。

您会注意到在我们的百分比栏中增加了JS。这允许我们在列和列标题中包含 JavaScript。我用它来做一些简单的事情,比如换行。你可以将 JS 用于许多更复杂的目的,这里记录了其中的一些。

reactable(
  data_for_table,
  defaultSortOrder = 'desc',
  defaultSorted = 'excess_deaths',
  showSortIcon = FALSE,
  compact = TRUE,
  pagination = FALSE,
  defaultColDef = colDef(
    headerStyle = list(
      textAlign = "left",
      fontSize = "11px",
      lineHeight = "14px",
      textTransform = "uppercase",
      color = "#0c0c0c",
      fontWeight = "500",
      borderBottom = "2px solid #e9edf0",
      paddingBottom = "3px",
      verticalAlign = "bottom",
      fontFamily = font_es
    ),
    style = list(
      fontFamily = font_es,
      fontSize = "14px",
      verticalAlign = "center",
      align = "left"
    )
  ),
  ####### NEW #######
  columns = list(
    country = colDef(
      name = "Region / Country",
      style = list(fontFamily = font_es,
                   fontWeight = "400")
    ),
    perc = colDef(
      html = TRUE,
      header = JS("
      function(colInfo) {
        return 'COVID-19 as<br>% of total'
      }"),
      name = "COVID-19 as % of Total",
      align = "right",
      maxWidth = 100,
      format = colFormat(percent = TRUE, digits = 0),
      style = list(fontFamily =  font_es_bold),
      headerStyle = list(
        fontSize = "11px",
        lineHeight = "14px",
        textTransform = "uppercase",
        color = "#0c0c0c",
        fontWeight = "500",
        borderBottom = "2px solid #e9edf0",
        paddingBottom = "3px",
        verticalAlign = "bottom",
        fontFamily = font_es,
        textAlign = "right"
      )
    ),
    clean_range = colDef(
      name = "Time Period",
      style = list(
        color = '#3f5661',
        fontSize = '12px',
        fontFamily = font_es
      )
    )
  )
)

添加条形图

我们现在可以创建包含条形图的“死亡”列。

由于集成了 JavaScript,向表格添加条形图变得非常容易。这里,我从reactable网站上的一个示例中提取,并使用以下代码:

reactable(
  data_for_table,
  defaultSortOrder = 'desc',
  defaultSorted = 'excess_deaths',
  showSortIcon = FALSE,
  compact = TRUE,
  pagination = FALSE,
  defaultColDef = colDef(
    headerStyle = list(
      textAlign = "left",
      fontSize = "11px",
      lineHeight = "14px",
      textTransform = "uppercase",
      color = "#0c0c0c",
      fontWeight = "500",
      borderBottom = "2px solid #e9edf0",
      paddingBottom = "3px",
      verticalAlign = "bottom",
      fontFamily = font_es
    ),
    style = list(
      fontFamily = font_es,
      fontSize = "14px",
      verticalAlign = "center",
      align = "left"
    )
  ),
  columns = list(
    country = colDef(
      name = "Region / Country",
      style = list(fontFamily = font_es,
                   fontWeight = "400")
    ),
    perc = colDef(
      html = TRUE,
      header = JS("
      function(colInfo) {
        return 'COVID-19 as<br>% of total'
      }"),
      name = "COVID-19 as % of Total",
      align = "right",
      maxWidth = 100,
      format = colFormat(percent = TRUE, digits = 0),
      style = list(fontFamily =  font_es_bold),
      headerStyle = list(
        fontSize = "11px",
        lineHeight = "14px",
        textTransform = "uppercase",
        color = "#0c0c0c",
        fontWeight = "500",
        borderBottom = "2px solid #e9edf0",
        paddingBottom = "3px",
        verticalAlign = "bottom",
        fontFamily = font_es,
        textAlign = "right"
      )
    ),
    clean_range = colDef(
      name = "Time Period",
      style = list(
        color = '#3f5661',
        fontSize = '12px',
        fontFamily = font_es
      )
    ),
    ###### NEW ######
    covid_deaths = colDef(
      name = "COVID-19 Deaths",
      cell = function(value) {
        width <- paste0(value * 100 / max(data_for_table$covid_deaths), "%")
        value <- format(value, big.mark = ",")
        value <- format(value, width = 10, justify = "right")
        bar <- div(
          class = "bar-chart",
          style = list(marginRight = "6px"),
          div(
            class = "bar",
            style = list(width = width, backgroundColor = "#F15A3F")
          )
        )
        div(class = "bar-cell", span(class = "number", value), bar)
      }
    ),
    excess_deaths = colDef(
      name = "Total Excess Deaths",
      cell = function(value) {
        width <-
          paste0(value * 100 / max(data_for_table$excess_deaths), "%")
        value <- format(value, big.mark = ",")
        value <- format(value, width = 10, justify = "right")
        bar <- div(
          class = "bar-chart",
          style = list(marginRight = "6px"),
          div(
            class = "bar",
            style = list(width = width, backgroundColor = "#3F5661")
          )
        )
        div(class = "bar-cell", span(class = "number", value), bar)
      }
    )
  )
)

让我们把重点放在covid_deaths上,一步一步地分解它。

首先,我们需要定义一些 CSS。reactable允许您轻松地将 CSS is RMarkdown 文档包含在定义为css的块中。

.bar-cell {
  display: flex;
  align-items: center;
}.number {
  font-size: 13.5px;
  white-space: pre;
}.bar-chart {
  flex-grow: 1;
  margin-left: 6px;
  height: 22px;
}.bar {
  height: 100%;
}

现在,让我们看看我们如何定义covid_deaths:

covid_deaths = colDef(
  ### define the name
  name = "COVID-19 Deaths",
  ### create a 'cell' function
  cell = function(value) {
    ### define the bar width according to the specified value
    width <- paste0(value * 100 / max(data_for_table$covid_deaths), "%")
    ### add a comma to the label
    value <- format(value, big.mark = ",")
    ### justify and provide padding with width
    value <- format(value, width = 10, justify = "right")
    ### create the barchart div
    bar <- div(
      ### with a class of 'bar-chart'
      class = "bar-chart",
      ### give the bar a margin
      style = list(marginRight = "6px"),
      ### create the *actual* bar, with the red economist color
      div(
        class = "bar",
        style = list(width = width, backgroundColor = "#F15A3F")
      )
    )
    ### bring it all together, with the 'value' (number) preceding the bar itself
    div(class = "bar-cell", span(class = "number", value), bar)
  }
)

这将创建一个如下所示的表:

添加标题

最后,我们可以添加表格标题和副标题。我们通过在我们的环境中存储上表来做到这一点。(这是最终的表码!)

table <- reactable(
  data_for_table,
  defaultSortOrder = 'desc',
  defaultSorted = 'excess_deaths',
  showSortIcon = FALSE,
  compact = TRUE,
  pagination = FALSE,
  defaultColDef = colDef(
    headerStyle = list(
      textAlign = "left",
      fontSize = "11px",
      lineHeight = "14px",
      textTransform = "uppercase",
      color = "#0c0c0c",
      fontWeight = "500",
      borderBottom = "2px solid #e9edf0",
      paddingBottom = "3px",
      verticalAlign = "bottom",
      fontFamily = font_es
    ),
    style = list(
      fontFamily = font_es,
      fontSize = "14px",
      verticalAlign = "center",
      align = "left"
    )
  ),

  columns = list(
    country = colDef(
      name = "Region / Country",
      style = list(fontFamily = font_es,
                   fontWeight = "400")
    ),
    covid_deaths = colDef(
      name = "COVID-19 Deaths",
      # align = "left",
      cell = function(value) {
        width <- paste0(value * 100 / max(data_for_table$covid_deaths), "%")
        value <- format(value, big.mark = ",")
        # value <- str_pad(value, 6, pad = "")
        value <- format(value, width = 10, justify = "right")
        bar <- div(
          class = "bar-chart",
          style = list(marginRight = "6px"),
          div(
            class = "bar",
            style = list(width = width, backgroundColor = "#F15A3F")
          )
        )
        div(class = "bar-cell", span(class = "number", value), bar)
      }
    ),
    excess_deaths = colDef(
      name = "Total Excess Deaths",
      # align = "left",
      cell = function(value) {
        width <-
          paste0(value * 100 / max(data_for_table$excess_deaths), "%")
        value <- format(value, big.mark = ",")
        value <- format(value, width = 10, justify = "right")
        bar <- div(
          class = "bar-chart",
          style = list(marginRight = "6px"),
          div(
            class = "bar",
            style = list(width = width, backgroundColor = "#3F5661")
          )
        )
        div(class = "bar-cell", span(class = "number", value), bar)
      }
    ),
    perc = colDef(
      html = TRUE,
      header = JS("
      function(colInfo) {
        return 'COVID-19 as<br>% of total'
      }"),
      name = "COVID-19 as % of Total",
      align = "right",
      maxWidth = 100,
      format = colFormat(percent = TRUE, digits = 0),
      style = list(fontFamily =  font_es_bold),
      headerStyle = list(
        fontSize = "11px",
        lineHeight = "14px",
        textTransform = "uppercase",
        color = "#0c0c0c",
        fontWeight = "500",
        borderBottom = "2px solid #e9edf0",
        paddingBottom = "3px",
        verticalAlign = "bottom",
        fontFamily = font_es,
        textAlign = "right"
      )
    ),
    clean_range = colDef(
      name = "Time Period",
      style = list(
        color = '#3f5661',
        fontSize = '12px',
        fontFamily = font_es
      )
    )
  ),
)

现在,我们可以在表格上方包含一个标题和副标题。我们使用一些htmltools函数来创建 div、标题和段落。

div(
    div(
      h2("Excess mortality since region/country’s first 50 covid deaths"),
      p(
        ### create the 'Updated on ...' and make it dynamic
        paste0(
          "Updated on ", format(Sys.Date(), "%B "),
          append_date_suffix(
            as.numeric(format(Sys.Date(), "%d"))
            ), " ",
          strftime(Sys.time(), format = "%H:%M"), " UCT"
        )
      ),
    ),
    table)

呀!那些字体大小不太符合经济学人的风格。让我们给我们的 div 添加类来匹配它们的风格。

.table {
  margin: 0 auto;
  width: 675px;
}.tableTitle {
  margin: 6px 0;
  font-size: 16px;
  font-family: 'Econ Sans Cnd'
}.tableTitle h2 {
  font-size: 16px;
  font-weight: bold;
  font-family: 'Econ Sans Cnd'
}.tableTitle p {
  font-size: 14px;
  font-weight: 500;
}

现在我们可以重新运行上面的代码:

div(class = "tableTitle",
    div(
      class = "title",
      h2("Excess mortality since region/country’s first 50 covid deaths"),
      p(
        paste0("Updated on ", format(Sys.Date(),"%B "),
          append_date_suffix(
            as.numeric(format(Sys.Date(), "%d"))
            ), " ",
          strftime(Sys.time(), format = "%H:%M"), " UCT"
        )
      ),
    ),
    table)

让我们将它与我们试图复制的表进行比较。请注意,在《经济学家》杂志发表他们的表格和我创建我的表格之间的时间里,有些数据已经改变了。

这篇文章的代码可以在我的 GitHub 上找到。你可以把任何关于复制的问题(或任何其他问题)发送给 me@connorrothschild.com,或者在我的推特上。

https://twitter.com/CL_Rothschild

最初发表在我的博客上。

在 PyTorch 中重新创建 Keras 代码——入门教程

原文:https://towardsdatascience.com/recreating-keras-code-in-pytorch-an-introductory-tutorial-8db11084c60c?source=collection_archive---------13-----------------------

初学者的深度学习

学习在 PyTorch 中创建神经网络的基础知识

作者于 Imgflip 创建

我爱 Keras,我说对了!然而……

作为一名应用数据科学家,没有什么比用三行代码快速构建一个功能性的神经网络更让我高兴的了!然而,随着我开始更深入地钻研神经网络的黑暗网络,我愿意接受 Pytorch 确实让你对你的网络架构有更大的控制权这一事实。

鉴于我们大多数人对 Keras 都相当熟悉(如果不熟悉,请参见这里的 Keras 热情介绍),学习在 Pytorch 中创建一个类似的网络(同时学习 Pytorch 基础知识)一点也不困难。我们开始吧!

注意:我们不会复制 Keras 代码,因为我想在这个入门教程中介绍 PyTorch 的更多特性和功能!

快速回顾一下 Keras 代码的样子:

下面是创建模型架构、编译模型和最终训练模型的代码片段(来自我之前关于 Keras 中神经网络的帖子)。它是一个贷款评估模型,输出贷款应该被接受还是拒绝。

*# Model architecture*
model_m = Sequential([
    Dense(units = 8, input_shape= (2,), activation = 'relu'),
    Dense(units = 16, activation = 'relu'),
    Dense(units = 2, activation = 'softmax') 
])*# Model compilation*
model_m.compile(optimizer= Adam(learning_rate = 0.0001), 
              loss = 'sparse_categorical_crossentropy', 
              metrics = ['accuracy'] 
             )*# Model Training and Validation*
model_m.fit(x = scaled_train_samples_mult, 
          y = train_labels, 
          batch_size= 10, 
          epochs = 30, 
          validation_split= 0.1, 
          shuffle = True,
          verbose = 2 
         )

总结一下,我们构建了一个有三个隐层的网络,都是Dense。三个隐藏层的激活功能分别是relurelusoftmaxinput_shape是一个元组(2,0),意味着我们有两个预测特征。Adam优化器和学习率lr = 0.0001已用于根据训练数据迭代更新网络权重。我们将在每次迭代中监控的损失是sparse_categorical_crossentropyaccuracy将用于判断网络的好坏。对于培训,我们将使用 30 个epochs和 10 个batch_size。如果上述任何术语的含义不清楚,请参见此处的或此处的或。

注:如果你想跟随本教程,请查看 Github 上的笔记本。

让我们从 PyTorch 开始吧

为了与我们之前使用 Keras 构建的网络保持一定程度的一致性,我将使用相同的数据集,即贷款申请数据集。它看起来是这样的:

在对数据集应用一些预处理后,主要是在 0-1 的范围内缩放所有输入特征(agearea)并对结果特征(application_outcome)进行标签编码,这就是我们最终得到的结果:

在 PyTorch 中定义数据集

我们将使用 PyTorch 中的torch.utils.data.Dataset类为贷款申请数据集定义一个Dataset对象。我们将称它为CVSDataset

我们将在我们的CSVDataset类中有四个方法— __init____len____getitem__get_splits

class CSVDataset(Dataset):

    *# reading the csv and defining predictor and output columns*
    def __init__(self):

        # store the input and output features
        self.X = df.values[:,:-1] 
        self.y = df.values[:,-1] 

        # ensure all data is numerical - type(float)
        self.X = self.X.astype('float32')
        self.y = self.y.astype('float32')

    *# number of rows in dataset*
    def __len__(self):
        return len(self.X)

    *# get a row at an index*
    def __getitem__(self, index):
        return [self.X[index], self.y[index]] # split into train and testset - using `random_split`
    def get_splits(self, split_ratio = 0.2):
        test_size = round(split_ratio * len(self.X))
        train_size = len(self.X) - test_size

        return random_split(self, [train_size, test_size])

注意:在非常基础的层面上,你为自己的数据集扩展的Dataset类应该有__init____len__()__getitem__ 方法。

我们首先在__init__()中定义预测器X和输出特征y,并确保类型是浮点型的,因为神经网络只处理数字数据。

__len__返回数据集中的行数,而__getitem__返回数据集中特定索引处的项目。

此外,我们还定义了一个(可选的)方法get_splits,让我们将数据集分成训练集和测试集。我们可以在 Sklearn 中使用train_test_split很好地完成这项工作,但这只是展示如何在 PyTorch 中使用torch.utils.data.random_split完成这项工作的一种方式。

定义模型架构

这是我们定义所有隐藏层在我们的网络中想要什么以及这些层如何相互作用的地方。为此,我们将利用torch.nn.Module类并扩展它。我们将称呼我们的班级为myNeuralNetwork

它包含定义层的__init__方法和解释输入如何通过定义的层向前传播的forward方法。

class myNeuralNetwork(Module):
      def __init__(self, n_inputs):
        .
        .
        . def forward(self,X):
        .
        .
        .

我们先来看一下init方法:

def __init__(self, n_inputs):

        # calling constructor of parent class
        super().__init__()

        # defining the inputs to the first hidden layer
        self.hid1 = Linear(n_inputs, 8) 
        kaiming_uniform_(self.hid1.weight, nonlinearity='relu')
        self.act1 = ReLU()

        # defining the inputs to the second hidden layer
        self.hid2 = Linear(8, 16)
        kaiming_uniform_(self.hid2.weight, nonlinearity='relu')
        self.act2 = ReLU()

        # defining the inputs to the third hidden layer
        self.hid3 = Linear(16, 2)
        xavier_uniform_(self.hid3.weight)
        self.act3 = Softmax(dim=1)

我们首先使用super().__init__()调用父类的构造函数。接下来,我们定义三个隐藏层hid1hid2hid3,以及它们的权重初始化和激活函数——act1act2act3

如果您还记得本文开头对 Keras 模型的总结,我们有三个密集的隐藏层。 Pytorch 相当于 Keras 致密层的是 **Linear**

第一个隐藏线性层hid1采用n_inputs个输入,输出 8 个神经元/单元。

注意:n_inputs粗略地翻译为我们有多少预测列(在我们的例子 2 中)。

第二隐层以 8 个神经元为输入,输出 16 个单元。

第三个隐藏层将 16 个神经元作为输入,并产生 2 个单元作为输出(这是贷款申请为approvedrejected的概率,因为 softmax 激活函数在该层中起作用)。

每个隐藏层的激活函数都存储在act1act2act3中。

注意:Pytorch 中激活函数的常见例子有ReLuSigmoidLogSigmoid等。

此外,PyTorch 允许您初始化每个隐藏层的权重张量。常见的例子有kaiming_uniformxavier_uniformorthogonal。你可以在文档页面上了解更多细节。

现在,让我们看看forward方法:

def forward(self, X):

        #input and act for layer 1
        X = self.hid1(X)
        X = self.act1(X)

        #input and act for layer 2
        X = self.hid2(X)
        X = self.act2(X)

        #input and act for layer 3
        X = self.hid3(X)
        X = self.act3(X)

        return X

每层的输入和激活在该函数中定义。总之,输入X进入hid1,第一激活功能act1应用于此。然后输出被传递到hid2,在此应用第二激活功能act2等等。由于最后一层有一个 softmax 激活函数,返回的X将是一个包含 n 个元素的张量,其中 n 是输出类的数量(在我们的例子中是两个——批准与拒绝)。

张量只不过是 Pytorch 自己的 Numpy 数组。这是一个通用的 n 维数组,用于任意数值计算。

在 PyTorch 中准备数据

在我们训练之前,使用torch.utils.data.DataLoader加载用于训练的数据是很重要的。你会问,为什么需要这样做?它实际上创建了要作为模型输入发送的批次(针对训练和测试集)。它将行的样本、批量大小以及是否重排行作为输入。

注:我们在 *test_dl* 的情况下显式设置 *shuffle = False* 是因为我们需要在末尾添加未混淆的标签来绘制混淆矩阵。

# Preparing the dataset before training the model# load the dataset
dataset = CSVDataset()# get the train and test split
train, test = dataset.get_splits()# prepare dataloaders - 
train_dl = DataLoader(train, batch_size = 32, shuffle = True)
test_dl = DataLoader(test, batch_size= 32, shuffle= False)

训练模型

我们首先通过创建myNeuralNetwork对象并传递 2 作为输入来定义模型。这里的 2 是指输入特征的数量。

我们还将设置epochs = 10,这意味着模型将根据所有数据训练10 次。

对于训练过程,我们将使用随机梯度下降(SGD) optimizer

优化器的选择包括AdamAdaGradSparseAdamSGD等,它们的用例可以在文档中找到。

最后,我们要在训练时监控CrossEntropyLoss

# define the network
model = myNeuralNetwork(2) # 2 because we only have 2 input features# define the number of epochs
epochs = 10# define the optimizer - SGD
optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)# define the loss function
criterion = CrossEntropyLoss()

为了训练网络,我们将使用两个 用于 循环。以下代码中的外循环是训练历元数所必需的,内循环用于迭代train_dl中的样本批次。也就是说,对于train_dl中的每一批样本,我们将清除梯度、计算模型输出、计算损耗并进行反向传播以更新权重。

# iterate through all the epoch
for epoch in range(epochs):
    # go through all the batches generated by dataloader
    for i, (inputs, targets) in enumerate(train_dl):
            # clear the gradients
            optimizer.zero_grad()
            # compute the model output
            yhat = model(inputs)
            # calculate loss
            loss = criterion(yhat, targets.type(torch.LongTensor))
            # credit assignment
            loss.backward()
            # update model weights
            optimizer.step()

评估模型

为了评估模型,我们将再次使用 作为 循环来检查test_dl中的所有批次。对于每个样本,我们将把它传递给模型并得到输出,即y_pred。由于y_pred包含两个概率值(一个用于approved,一个用于rejected,我们将选择概率最高的索引作为最终输出。

最后,我们将实际输出和预测输出存储在两个列表中— actualspredictions

# Evaluate the model
predictions, actuals = list(), list()# loop over all batches in test setfor i, (inputs, targets) in enumerate(test_dl):
    # pass input to the model
    y_pred = model(inputs) 
    # retrieve the numpy array
    y_pred = y_pred.detach().numpy()
    # pick the index of the highest values
    res = np.argmax(y_pred, axis = 1) 

    # actual output
    actual = targets.numpy()
    actual = actual.reshape(len(actual), 1)

    # store the values in respective lists
    predictions.append(list(res))
    actuals.append(list(actual))

actuals = [val for sublist in vstack(list(chain(*actuals))) for val in sublist]
predictions = [val for sublist in vstack(list(chain(*predictions))) for val in sublist]

为了打印准确度分数,我们将使用sklearn.metrics中的accuracy_score

*# evaluating how good the model is!*
from sklearn.metrics import accuracy_scoreprint("The accuracy is" , accuracy_score(actuals, predictions))
*********************
The accuracy is 0.7495

我们成功了!

我们已经使用 PyTorch 创建了一个基本网络。希望这不是太多的信息超载。如果你想获得全部代码,请查看 Github上的笔记本。在下一篇教程中,我们将深入探讨 Pytorch 提供的一些高级功能。

在那之前:)

[## 阅读瓦希塔·谢尔博士的每一家书店(以及媒体上成千上万的其他作家)

作为一个媒体会员,你的会员费的一部分给了你阅读的作家,你可以完全接触到每一个故事…

varshitasher.medium.com](https://varshitasher.medium.com/membership) [## 使用 Python 中的 Keras 构建人工神经网络的初学者指南

创建网络架构、训练、验证和保存模型并使用它进行推理的提示和技巧。

towardsdatascience.com](/beginners-guide-to-building-artificial-neural-networks-using-keras-in-python-bdc4989dab00) [## 在数据科学面试中解释你的 ML 项目的逐步指南。

在结尾有一个额外的样本脚本,让你谨慎地展示你的技术技能!

towardsdatascience.com](/step-by-step-guide-to-explaining-your-ml-project-during-a-data-science-interview-81dfaaa408bf) [## 使用 Scikit、Pandas 和 Numpy 进行时间序列建模

直观地利用季节性来提高模型准确性。

towardsdatascience.com](/time-series-modeling-using-scikit-pandas-and-numpy-682e3b8db8d1)

用 PyTorch 重新创建 Keras 功能 API

原文:https://towardsdatascience.com/recreating-keras-functional-api-with-pytorch-cc2974f7143c?source=collection_archive---------39-----------------------

让我们把喀拉斯的经历带到 PyTorch

作者图片

介绍

Francois Chollet(Keras 的创始人)的书《用 Python 进行深度学习》让我进入了深度学习的世界。从那时起,我就爱上了 Keras 的风格。

Keras 是我的第一个框架,然后跳进一点 Tensorflow 然后进来 PyTorch,剩下的就是历史了。

老实说,我真的很兴奋在 Keras 的模型训练中出现的进度条,这真是太棒了:)

那么,为什么不试着把 Keras 训练模特的经验带到 PyTorch 呢?

这个问题让我开始,我最终用所有花哨的进度条重新创建了 Keras 的密集层、卷积层和平坦层。

可以通过将一层堆叠在另一层的顶部来创建模型,并通过简单地调用 fit 方法来训练模型,这与 Keras 的工作方式类似。

让我们建造它

对于那些没有使用过 Keras 的人来说,在 Keras 中构建和训练一个模型如下所示:

在 keras 培训全连接网络

1。导入所需的库

你可能不熟悉 pkbar 库,它是用来显示进度条的。

导入所需的库

2。输入层和密集层

输入层简单地采用将被传递到神经网络并返回它的数据的单个实例的形状,对于全连接网络,它将类似于(1,784)并且对于卷积神经网络,它将是图像的维度(高度×宽度×通道)。

使用大写字母来命名 python 函数是违反规则的,但我们暂时忽略它(Keras 源代码的某些部分使用了相同的约定)。

输入层

密集类通过传递该层的输出神经元的数量和激活函数来初始化。当密集层被调用时,前面的层作为输入被传递。

现在我们有了前一层的信息。如果前一层是输入层,则会创建 PyTorch 线性层,其中包含从输入层返回的形状以及在密集类初始化期间作为参数提供的输出神经元的数量。

如果前一层是密集层,我们通过添加 PyTorch 线性层和用户提供给密集类的激活层来扩展神经网络。

而如果前一层是卷积或展平层,我们会创建一个名为 get_conv_output() 的效用函数,得到图像经过卷积和展平层后的输出形状。此维度是必需的,因为如果不向 in_features 参数传递值,我们就无法在 PyTorch 中创建线性图层。

get_conv_output() 函数将图像形状和卷积神经网络模型作为输入。然后,它创建一个与图像形状相同的虚拟张量,并将其传递给卷积网络(带有扁平化层),并返回从中输出的数据大小,该大小作为值传递给 PyTorch 的线性层中的 in_features 参数。

致密层

3。展平图层

为了创建展平图层,我们将创建一个名为 flattened layer 的自定义图层类,它接受一个张量作为输入,并在向前传播期间返回张量的展平版本。

我们将创建另一个名为 flatten 的类,当这个层被调用时,前面的层作为输入被传递,然后 flatten 类通过在前面的层上添加我们自定义创建的 flattened layer 类来扩展网络。

因此,所有到达展平层的数据都使用我们自定义创建的展平层类进行展平。

展平图层

4。卷积层

我们将通过传入过滤器数量、内核大小、步幅、填充、膨胀和激活函数来初始化 Conv2d 层。

现在,当调用 Conv2d 层时,前面的层被传递给它,如果前面的层是输入层,则创建一个 PyTorch Conv2d 层,它具有提供的过滤器数量、内核大小、步幅、填充、膨胀和激活函数的值,其中 in_channels 的值取自输入形状中的通道数量。

如果前一层是卷积层,则通过添加 PyTorch Conv2d 层和激活函数来扩展前一层,激活函数的 in_channels 值取自前一层的 out_channels。

在填充的情况下,如果用户需要保留从该层输出的数据的维度,那么填充的值可以被指定为“相同”而不是整数。

如果填充的值被指定为“same ”,则使用一个名为 same_pad() 的实用函数来获取填充的值,以保持给定输入大小、内核大小、步幅和膨胀的尺寸。

可以使用前面讨论过的 get_conv_output() 实用函数获得输入大小。

5。模型类别

在构建了我们的模型的架构之后,通过传入输入层和输出层来初始化模型类。但是我给出了一个额外的参数叫做 device,这是 Keras 中没有的,这个参数接受的值是“CPU”或“CUDA ”,它会将整个模型移动到指定的设备。

model 类的 parameters 方法用于返回要提供给 PyTorch 优化器的模型的参数。

模型类有一个名为 compile 的方法,它接受训练模型所需的优化器和损失函数。model 类的 summary 方法借助 torchsummary 库显示创建的模型的概要。

拟合方法用于训练模型,该方法以输入特征集、目标数据集和历元数为自变量。它显示由损失函数计算的损失和使用 pkbar 库的训练进度。

评估法用于计算试验数据的损失和精度。

当使用 PyTorch 数据加载器加载数据时,将使用 fit_generator、evaluate_generator 和 predict_generator。fit_generator 将训练集数据加载器和时期作为参数。evaluate_generator 和 predict_generator 分别采用验证集数据加载器和测试数据加载器来衡量模型对未知数据的执行情况。

模型类

最后的想法

我已经使用密集层和卷积神经网络在 CIFAR100、CIFAR10 和 MNIST 数据集上测试了代码。它运行良好,但有巨大的改进空间。

这是一个有趣的项目,我工作了 3-4 天,它真正推动了我用 PyTorch 编程的极限。

你可以在这里查看在上述数据集上完成训练的完整代码,或者你可以在 colab 中自由调整代码以适合你的喜好。

在 R 中重建网飞的分位数自举

原文:https://towardsdatascience.com/recreating-netflixs-quantile-bootstrapping-in-r-a4739a69adb6?source=collection_archive---------44-----------------------

我在做一些随意的数据科学阅读,然后嘣!我在网飞的技术博客上重新发现了一篇很棒的文章:马丁·廷利的《网飞流式视频实验:可视化实践和统计意义》。

它有什么酷的?它提供了一种可扩展的方法来探索大规模在线实验中的异构处理效果。心智融化?好的,我再试一次。它描述了一种方式,实验者可以学到更多的东西,而不仅仅是他们是否有整体影响。相反,它让实验者看到他们如何影响不同的群体。此外,它还可以扩展到处理海量数据!

马丁和新合著者最近的文章,分享了一个很好的例子来说明这种方法是如何帮助的。下面您可以看到用户的视频质量如何在现有的流配置(生产,黑色设置为零)和新的(治疗,紫色)之间进行比较。

图来自“大规模流实验的数据压缩”。详细信息:“带阴影置信区间的差异图表明,在分布的最低百分位数处,视频质量有实际和统计上的显著提高”

请记住,特别之处在于看到不同用户的影响如何不同。对质量差的用户有积极的影响(见左边),对其他人没有显著影响。这意味着产品团队可以从说“质量提高了”变成更有用的话,比如“我们为体验最差的用户提高了质量,而不影响已经有高质量体验的用户。”

这对我来说太棒了,我决定剔除细节,边走边编码学习。更好的是,我正在分享我所做的来节省你的时间!

注意:我在本文中粘贴了一些有用的代码片段。可以从我的 GitHub repo 访问完整的代码演练。

入门指南

library(tidyverse)

模拟数据

没有数据我们做不了什么。我将为一组实验对象模拟一个连续的度量标准x。想象一下x对于网飞的每一个用户来说代表着类似“秒延迟”的东西。为了看起来更合理,我们来看看卡方分布数据:

x <- rchisq(n = 200, df = 8)

模拟指标的分布,“x”

获取分位数

提醒: 分位数 是将数据分割成不同大小/百分位数的数值。例如,0.5 分位数将是将数据分成两半的值(因此 50%的值低于该值)。这也是一种叫做中位数的特例。. 25 分位数将是大于数据的 25%的值。要找到特定的分位数,您需要排列数据(从最小到最大)并在 x%位置找到数据点。

r 有一个俏皮的功能,quantile()。让我们用它来得到一个数值范围(用seq()设置),如下所示:

quantile_df <- tibble(percentile = seq(0, 1, by = .2)) %>% 
  mutate(value = quantile(x, percentile))
quantile_df#> # A tibble: 6 x 2
#>   percentile value
#>        <dbl> <dbl>
#> 1        0    1.02
#> 2        0.2  4.08
#> 3        0.4  6.31
#> 4        0.6  8.58
#> 5        0.8 11.0 
#> 6        1   20.0

轻松点。

签到:我们已经可以做一点了

这已经足以产生类似网飞的情节。我们可以模拟两种情况(生产和处理)的数据,并计算每种情况的分位数。

*# Simulate data sets. For treatment, we'll bind two distributions
# skewed either side of production*
x_production <- rchisq(200, 8)
x_treatment  <- c(rchisq(100, 12), rchisq(100, 4))group_quantiles_df <- tibble(percentile = seq(0, 1, by = .2)) %>% 
  mutate(production = quantile(x_production, percentile),
         treatment  = quantile(x_treatment, percentile))
group_quantiles_df#> # A tibble: 6 x 3
#>   percentile production treatment
#>        <dbl>      <dbl>     <dbl>
#> 1        0         1.80     0.180
#> 2        0.2       4.76     2.83 
#> 3        0.4       6.44     5.22 
#> 4        0.6       7.96     8.04 
#> 5        0.8      10.3     13.2  
#> 6        1        27.9     36.2

网飞图显示了与产量(产量= 0)相比的“差异”,对我们来说是这样的:

对于几行代码来说相当不错!好吧,我们的数据和他们的不同,但是概念都是一样的。

自举差异

我们已经走了很远,但是缺少了一些重要的东西:置信区间(原始图中的透明带)。这些告诉我们两组之间是否有显著差异。让我们迎接挑战,开始行动吧。我们需要考虑的第一件事是引导。

提醒:Bootstrapping是一个随机抽取一堆数据进行替换的过程。您可以使用这个新样本计算所有感兴趣的统计数据(例如,分位数)。然后重复多次,每次得到的结果都略有不同,并建立起一种不确定感。

我们可以很容易地用 R 的sample()replace = TRUE创建一个自举。结果将是一个向量,其长度与原始数据相同,但使用替换对其进行采样。

x_bootstrap <- sample(x, replace = TRUE)

对于每个数据集(生产和处理),我们多次这样做,每次都保存自举样本的分位数。

n_bootstraps <- 100
quantile_df_template <- tibble(percentile = seq(0, 1, by = .2))bootstrapped_quantiles <- map_df(seq_len(n_bootstraps),function(i) {
  bootstrapped_production <- sample(x_production, replace = TRUE)
  bootstrapped_treatment  <- sample(x_treatment, replace = TRUE)

  quantile_df_template %>%
    mutate(bootstrap = i,
           production = quantile(bootstrapped_production,
                                 percentile),
           treatment  = quantile(bootstrapped_treatment, 
                                 percentile))
})bootstrapped_quantiles#> # A tibble: 600 x 4
#>    percentile bootstrap production treatment
#>         <dbl>     <int>      <dbl>     <dbl>
#>  1        0           1       1.80     0.180
#>  2        0.2         1       4.84     3.16 
#>  3        0.4         1       6.41     5.58 
#>  4        0.6         1       8.24     7.48 
#>  5        0.8         1      11.0     14.9  
#>  6        1           1      27.9     36.2  
#>  7        0           2       1.80     0.180
#>  8        0.2         2       4.80     2.93 
#>  9        0.4         2       7.14     5.07 
#> 10        0.6         2       8.78     7.79 
#> # … with 590 more rows

这给了我们每个百分点的很多点(每个引导一个点)。下图以红色显示了原始production数据的范围和平均值。

现在,我们真正感兴趣的是两组之间的差异。让我们为生产和处理自举分位数之间的“差异”重复这个过程。然后使用这些数据计算与生产数据相比,围绕处理条件绘制的“范围”。

置信区间

提醒: 置信区间 为可以被认为与我们观察到的数据显著不同的东西设定界限。显著性由一个称为显著性标准的概率阈值决定。

上面我们绘制了自举分位数差异的完整范围,但这不是我们想要的。我们实际上想要置信区间。为了得到这些,我们需要运行一定数量的自举,然后计算出截断最高和最低自举值的点,以给我们自己留下特定百分比的结果。例如,如果我们的显著性标准是 5%,这是非常典型的,我们希望得到砍掉最低和最高 2.5%数据的点。额外收获:这些对应于自举差异的 0.025 和 0.975 分位数!

这段代码可以让我们快速到达目的地:

bootstrapped_cis <- bootstrapped_quantiles %>% 
  mutate(q_dif = treatment - production) %>% 
  group_by(percentile) %>% 
  summarise(lower_bound = quantile(q_dif, .025),
            upper_bound = quantile(q_dif, .975))bootstrapped_cis#> # A tibble: 6 x 3
#>   percentile lower_bound upper_bound
#>        <dbl>       <dbl>       <dbl>
#> 1        0        -2.28       -1.00 
#> 2        0.2      -2.53       -0.984
#> 3        0.4      -2.09       -0.351
#> 4        0.6      -1.19        2.03 
#> 5        0.8       0.825       4.75 
#> 6        1        -4.72       16.3

我们现在可以将这些数据绘制成透明带!

看起来不错!由此,我们可以得出结论,我们的治疗组明显低于较低百分位数的产量,可能高于 80%左右,在其他地方没有不同。

提高数字

你已经得到了提高数字所需的一切。更大的数据集,更多的数量,更多的引导。您可能会得到这样的结果:

现在我们正在谈话!

是时候获得(更多)技术了

好了,该认真了。Martin 继续分享如何处理(1)多重比较和(2)大量数据的“一些技术细节”。让我们按顺序解决它们。

多重比较

当你运行一个实验并比较组平均值时,你做了一个统计测试。你可以使用 95%的置信区间,有 5%的机会错误地说有差异,而实际上没有差异(统计学家说有 5%的假阳性率)。在这里,我们实际上运行了许多测试:每个分位数一个。Lots =倍数;测试=比较。多重比较!这可能不太直观,但请相信我,对所有这些测试使用 95%的置信区间会使你出错的几率大大高于 5%。不酷😬

幸运的是,有一个解决方案。我们可以调整显著性阈值,使出错的总体几率达到期望的水平。这可以通过 Bonferroni 修正来实现,我们可以估计独立测试的数量(而不是因为使用了更多的分位数而受到惩罚)。我先不为新手读者解释这个,让我们看看代码。

PSA:我已经根据我所能读到的拼凑了这些,但我愿意接受修改。

*# Sum of the correlations between bootstrapped
# differences at each quantile*
cor_sum <- bootstrapped_quantiles %>%
  transmute(bootstrap, percentile, 
            q_dif = treatment - production) %>% 
  pivot_wider(names_from = percentile, values_from = q_dif) %>% 
  select(-bootstrap) %>% 
  cor() %>% 
  .[-upper.tri(.)] %>% 
  sum()*# Estimated number of independent tests*
n_tests_estimate <- length(quantile_seq) ^ 2 / cor_sum
n_tests_estimate#> [1] 2.289841# Bonferroni adjusted confidence interval
desired_error_rate  <- 0.05
adjusted_error_rate <- desired_error_rate / n_tests_estimate
adjusted_error_rate#> [1] 0.022

为了处理我们的多重比较并保证只有 5%的错误率,我们应该使用 97.8%的置信区间(从1 — 0.022)而不是 95% ( 1 — 0.05)。因此,我们不是在 0.025 和 0.975 分位数处截断自举数据,而是在 0.011 和 0.989 处截断。

这显示了不同之处:

请注意,经过适当调整的绿色置信区间比原始区间更宽。因此,我们对统计显著性的评估更为保守,将我们的总体误差率保持在 5%。

不错!

基于大数据的快速引导

到目前为止,一切都很酷,但如果你有从数千次实验中产生的大量数据,就会崩溃。聪明的解决方案是通过将数据压缩到均匀大小的桶中来近似计算结果,并引导这些桶而不是原始数据。这意味着无论原始大小如何,数据都可以压缩到设定数量的存储桶。

提示:我发现跟随最近的文章 会更容易理解这个话题。如果你想看一个不同的应用程序,请阅读我之前关于回归的文章。

第一步,获取有序存储桶中的数据,跟踪每个存储桶的计数和汇总统计数据(我将使用中间值)。我们可以在cut_number()(来自 tidyverse 自带的 ggplot2)的帮助下做如下操作。

# Define number of buckets per group
n_buckets <- 100# Compress data into buckets of even counts
compressed_data <- tibble(production = x_production, 
                          treatment = x_treatment) %>% 
  pivot_longer(c(production, treatment),
               names_to = "group", values_to = "x") %>% 
  group_by(group) %>% 
  mutate(x_bucket = cut_number(x, n_buckets)) %>% 
  group_by(group, x_bucket) %>% 
  summarise(count = n(),
            x = median(x)) %>%
  ungroup()compressed_data#> # A tibble: 200 x 4
#>    group      x_bucket    count     x
#>    <chr>      <chr>       <int> <dbl>
#>  1 production (1.53,1.94]    10  1.69
#>  2 production (1.94,2.15]    10  2.06
#>  3 production (10.1,10.3]    10 10.2 
#>  4 production (10.3,10.4]    10 10.4 
#>  5 production (10.4,10.6]    10 10.5 
#>  6 production (10.6,10.8]    10 10.7 
#>  7 production (10.8,10.9]    10 10.8 
#>  8 production (10.9,11]      10 11.0 
#>  9 production (11,11.2]      10 11.1 
#> 10 production (11.2,11.3]    10 11.2 
#> # … with 190 more rows

下一个挑战是获得分位数,因为quantile()不再工作了。没什么大不了的。让我们添加一个累积百分比列,并编写一个函数来根据需要搜索数据框。

# Add cumulative percentile to compressed data for easy search
compressed_data <- compressed_data %>% 
  group_by(group) %>% 
  arrange(x) %>% 
  mutate(cum_percentile = cumsum(count) / sum(count)) %>% 
  ungroup()

compressed_data#> # A tibble: 200 x 5
#>    group      x_bucket       count     x cum_percentile
#>    <chr>      <chr>          <int> <dbl>          <dbl>
#>  1 treatment  [0.0539,0.412]    10 0.223           0.01
#>  2 treatment  (0.412,0.547]     10 0.447           0.02
#>  3 treatment  (0.547,0.769]     10 0.675           0.03
#>  4 treatment  (0.769,0.881]     10 0.812           0.04
#>  5 treatment  (0.881,0.986]     10 0.926           0.05
#>  6 treatment  (0.986,1.08]      10 1.01            0.06
#>  7 production [0.493,1.53]      10 1.08            0.01
#>  8 treatment  (1.08,1.21]       10 1.11            0.07
#>  9 treatment  (1.21,1.33]       10 1.23            0.08
#> 10 treatment  (1.33,1.43]       10 1.38            0.09
#> # … with 190 more rows*# Function we can reuse to get `x` quantile from the compressed data*
x_at_percentile <- **function**(percentile, compressed_df) {
  i <- 1
  **while** (compressed_df$cum_percentile[i] < percentile) {
    i <- i + 1
  }
  **return** (compressed_df$x[i])
}# Test
compressed_data %>% 
  filter(group == "production") %>% 
  x_at_percentile(.5, .)#> [1] 7.361729

最好确保它能工作!下面我用这两种方法从原始数据和压缩数据中得到生产数据的分位数。

quantile_df <- tibble(percentile = seq(0, 1, by = .1)) %>%
  mutate(original = quantile(x_production, percentile)) %>%
  mutate(compressed = map_dbl(
    percentile,
    x_at_percentile,
    filter(compressed_data, group == "production")
  ))

当我们绘制原始和压缩的结果时,我们得到:

看起来是一个很好的近似值,我们没有使用太多的数据或桶。这只会随着更多的原始数据和更多的桶而变得更准确(显然“几千”应该可以做到)。

我们现在可以压缩我们的数据,无论数据有多大,都可以大规模管理!

我们需要知道的最后一件事是如何引导压缩数据集。我们现在对压缩数据帧的行进行采样(包含计数和汇总值)。这可以通过sample_n()(来自 tidyverse 附带的 dplyr)来完成。下面是一个简单的示例,它对压缩的生产数据进行采样,并重新计算累积的百分位数:

# A bootstrap of the compressed data
compressed_data %>% 
  filter(group == "production") %>% 
  sample_n(n(), replace = TRUE) %>% 
  arrange(x) %>% 
  mutate(cum_percentile = cumsum(count) / sum(count))#> # A tibble: 100 x 5
#>    group      x_bucket    count     x cum_percentile
#>    <chr>      <chr>       <int> <dbl>          <dbl>
#>  1 production (1.53,1.94]    10  1.69           0.01
#>  2 production (2.15,2.39]    10  2.19           0.02
#>  3 production (2.39,2.65]    10  2.48           0.03
#>  4 production (2.39,2.65]    10  2.48           0.04
#>  5 production (3.29,3.38]    10  3.31           0.05
#>  6 production (3.38,3.51]    10  3.43           0.06
#>  7 production (3.69,3.82]    10  3.75           0.07
#>  8 production (3.69,3.82]    10  3.75           0.08
#>  9 production (3.92,4.05]    10  4.02           0.09
#> 10 production (3.92,4.05]    10  4.02           0.1 
#> # … with 90 more rows

请注意,正如原始数据一样,引导会导致行被多次采样(例如,行 3 和 4、行 7 和 8 或行 9 和 10)。这就是为什么我们重新计算百分点,一切都应该工作。

注意:如果每行的计数不相等,您需要做一些加权,以确保具有较高计数的行以较高的速率被采样。但是,我们将数据分成大小相等的组,因此可以忽略这一点,并以相等的概率对行进行采样。

那都是乡亲们!

嗯,我们也是。这些都是你开始大规模实施网飞分位数自举技术需要解决的问题。

尽管如此,我还是要给你一个重要的警告。撰写本文和代码是为了帮助理解正在发生的事情。这绝对不是为了表现。所以不要把它扔进任何实验管道,因为 s*!%会出问题。想要启动并运行这项技术吗?使用一个小数据集来试验这些代码,直到您理解发生了什么。然后慢慢地改进性能,反复测试准确性和处理更大数据的能力。完成后,请回到这里分享您的作品:)

在 PowerBI 中重现 Gapminder 情节

原文:https://towardsdatascience.com/recreating-the-gapminder-plot-in-powerbi-2b2eb6061dc6?source=collection_archive---------51-----------------------

COVID19 会改变 2020 年的趋势吗?

在过去的几周里,我看到了许多关于 COVID19 对全球健康和经济影响的分析和可视化。

这不仅仅是一场寻找疾病治疗方法的竞赛,它还激发了人们对数据科学的兴趣,因为它适用于抗击疫情。

我也要加入这股潮流。

对于初学者来说,我认为汉斯·罗斯林教授著名的 Gapminder 图是最好的选择。罗斯林教授做了一件了不起的工作,用这个图讲述了一个故事,从那时起,它已经成为事实上的初学者数据可视化项目。

事不宜迟,我们来做剧情吧!

准备数据

首先,我们必须获得用于可视化的数据。你可以从 Gapminder 网站这里或者我的 GitHub repo 下载数据。

这些数据与以下内容有关

  • 预期寿命(年)
  • 人均收入(国内生产总值/人均,经通货膨胀调整的购买力平价美元)
  • 总人口
  • 世界各地区

打开 CSV 文件,您会注意到它们是“宽”格式(区域除外),如下所示

“宽”格式的数据

我们必须将数据转换为“长”或“整齐”格式,以创建 Gapminder 图。

先说预期寿命数据。

  1. 创建一个新的 PowerBI 文件并转到主页>获取数据> Text/CSV 。选择预期寿命 CSV 文件
  2. 在 PowerQuery 编辑器中,将第一行提升为列标题。
  3. 要变成“整齐”格式,选择geo列并点击转换>取消透视其他列。我们希望年份和值组成新的列。
  4. 将这些列分别重命名为CountryYearLife Expectancy
  5. 为尾随空格修剪Country

数据现在应该如下所示

长格式的预期寿命数据

对收入和人口数据重复上述过程。

这样做之后,收入和人口数据应该如下所示

“长”格式的收入数据

“长”格式的人口数据

区域数据已经是“长”或“整齐”的格式,但我们必须进一步格式化它,以便稍后进行合并。

  1. name列重命名为Country
  2. 删除除Countryregionsub-region列之外的其他列。
  3. 南极洲没有标明区域或次区域。我们只是通过创建条件列将南极洲分配给这些列。举个例子,

上面创建了一个新的列Subregion,如果Country是南极洲,则使用南极洲,否则使用sub-region列的值。对Region栏进行同样的操作。之后去掉旧的regionsub-region列。

4.最后,为尾随空格修剪Country

区域数据现在应该如下所示

组合数据

下一步是结合预期寿命、收入和人口数据。

我们必须这样做有三个原因

  1. 我们的数据没有相同的行数。预期寿命数据有 186 行,收入数据有 193 行,人口数据有 195 行。
  2. 我们将把Years列限制为 5 的倍数。这是为了在我们将数据动画化后使趋势更加明显。

让我们从结合我们的数据开始。

  1. 创建新的合并查询(新查询>将>合并查询合并为新的)
  2. 将预期寿命和收入数据合并如下。

我们首先选择预期寿命数据,因为它的行数最少。通过选择左连接,没有匹配预期寿命的国家将在结果合并中被移除。这是为了确保一旦合并完成,所有国家都有预期寿命、收入和人口。

3.扩展列以包含人均收入数据。

展开合并的数据

对人口数据重复上述过程。数据最终应该如下所示

结果数据有 186 行,我们可以确定所有国家都有所有必需的字段,因为我们前面使用了左连接。

过滤数据

为了在我们将数据制成动画后使趋势更加明显,让我们将Years列过滤为 5 年间隔。我们可以用 PowerQuery 中的Number.Mod函数来实现这一点

1.按如下方式创建新列

2.筛选自定义列以仅包含 0 或可被 5 整除的年份。随后删除自定义列

结果数据应该如下所示

过滤数据

将合并的数据重命名为 Gapminder。

可视化数据

经过所有这些准备,我们现在终于准备好创建我们的可视化。

来绘制 Gapminder 图。
1。将散点图拖放到我们的 PowerBI 窗口。适当调整大小。

2.将字段拖动到绘图中适当的轴上

X-axis — Gapminder[Income Per Person]
Y-axis — Gapminder[Life Expectancy] summarized by Average
Size — Gapminder[Population]
Play Axis — Gapminder[Year]
Details — Gapminder[Country]

3.让我们在Subregion的基础上给Countries着色。为此,让我们首先在 Gapminder(合并)数据和 Regions 数据之间创建一个关系。

转到Modelling > Manage Relationships。按如下方式创建关系

请注意,我选择利用关系,而不是合并数据,因为它不像前面的过程那样混乱。现在,这两个数据的主键只是Country列。

4.让我们格式化我们的图表,使它更清晰。转到格式面板,按如下方式调整轴

X-axis — make it a logarithmic scale, max of 120,000
Legend — put in the Right
Category Labels — turn it on to show Country names
Title — put “How Does Income Relate to Life Expectancy?”

最终的情节现在看起来像这样

最终 Gapmidner 图

你可以在这里下载 T4。

如果你玩这个 1910 年到 1920 年的 PowerBI,你会注意到,与 1910 年和 1915 年相比,1920 年很少有圆点移动得更低。

由于西班牙流感,这些国家在 20 世纪 20 年代移到了左下方

这当然是因为西班牙流感从 1918 年 1 月到 1920 年 12 月持续了 36 个月,感染了 5 亿人——约占当时世界人口的三分之一。

【2020 年,COVID19 也会这样吗?

我们不知道,我也希望不知道。然而,一旦 2020 年的数据出来,我很高兴能重现这个图。

感谢您阅读我的文章。关注我上TwitterLinkedin

退房还我的书PowerQuery 熊猫指南 Leanpub

RecSys 2020:第 14 届推荐系统会议纪要

原文:https://towardsdatascience.com/recsys-2020-highlights-of-the-14th-conference-on-recommender-systems-1bdac5f5ef22?source=collection_archive---------31-----------------------

莱昂纳多·马里尼奥在 Unsplash 上的照片

第 14 届 ACM 推荐系统会议在许多方面都很特别:一个完全虚拟的会议,它在保持社交互动方面做了令人惊叹的工作——即使许多人在位置和时间上都很远。另一方面:偏见和公平从来没有像现在这样普遍和受到重视。这篇博客引导你参加会议,提供了演示文稿、材料和论文的有用链接。所以,(再次)享受这个会议吧。

计划在里约热内卢举行(首次在南美举办)今年的 RecSys 于 9 月 22 日至 26 日举行,其中前三天是主要会议,随后两天是教程和研讨会。第 0 天——一如既往——是为博士研讨会预留的。2019 年 10 月拉丁美洲推荐系统学校率先推出了整个南美和拉丁美洲 RecSys 体验。

RecSys 2020 的几个数字

会议完全是虚拟的。现场论文、海报和辅导会议分两次进行,每次间隔 11 小时,以适应来自全球所有时区的演示者和参与者。然而,会议仍然是单轨制,允许每个人看到和参与所有的事情。

  • 1200 多名参与者:64%来自工业界,36%来自学术界,21%是学生
  • 主会议: 3 场主题演讲,9 场论文会议,12 场社交会议,3 场海报会议
  • 6 教程, 12 工作坊
  • 39/218 长论文提交被接受(18%) —新的提交记录!
  • 26/128 篇短文被接受(20%)
  • 2/7 的论文(29%)通过了新引入的再现性跟踪
  • 25%的提交来自美国
  • 话题焦点从算法(2020 年为 47%对 26%)转移到应用(2020 年为 17%对 39%)
  • 接受 10/20 工业捐款
  • Linus Dietz 跑了 46.6 公里的总距离,获得了最佳跑步者奖

关于操纵、偏见和对话式人工智能代理的主题演讲

每个主要会议日都以主题演讲开始:

菲利普·门策尔:社交媒体让我们容易被操纵的 4 个原因

在第一天,来自印第安纳大学社交媒体观察站的菲利普·门泽尔谈到了“社交媒体让我们容易被操纵的 4 个原因”(在 YouTube 上找到相同的演讲)。考虑到最近美国大选或当前疫情电晕的社交媒体反响,他提出了有趣的模拟和分析,概述了以下四个原因:

  1. 操纵
  2. 平台偏差
  3. 信息过载
  4. 回声室

通过对内容病毒式传播,特别是假新闻传播和社交机器人行为的说明,这次谈话非常有趣,也非常具体。他还展示了在不同的用户注意力和信息过载以及特定的信息共享模式下,质量和受欢迎程度的相关性。门策尔还分享了在他的实验室创造的各种有趣的工具。在他的总结中,他声称“认知、社会和算法偏见的相互作用使我们容易受到错误信息的影响”,并且“社交机器人利用了这些漏洞”。这很好地反映了今年 RecSys 在偏见研究方面的许多贡献。绝对值得笑的是他对成年人批判性思维能力的评论:

孩子们的批判性思维不如成年人,相信我,成年人也没有多少批判性思维。

里卡多·巴埃萨-耶茨:搜索和推荐系统中的偏见

第二天的主题演讲完美地延续了第一天的内容。来自东北大学的里卡多·巴埃萨-耶茨教授发表了“搜索和推荐系统中的偏见”(非常相似的演讲在这里)。他构建了渗透在个性化网络中的各种偏见的复杂相互作用,其中搜索和推荐系统是主导力量。通过活动、算法和认知偏差等总体偏差,他深入研究了这种复杂相互作用中出现的一些恶性反馈循环的复杂性。

图片来自里卡多·巴埃萨-耶茨:搜索和推荐系统中的偏见

图片来自里卡多·巴埃萨-耶茨:搜索和推荐系统中的偏见

幸运的是,他还触及了去偏置技术,不同目标的相关性,如多样性、意外收获或仅次于准确性的新颖性。他还提出了在不损害长期商业目标的情况下进行更多探索的理由。这是一个警告,但仍然是令人鼓舞的谈话。

米歇尔·周:“你真的懂我”——能够真正理解和帮助用户的对话式人工智能代理

还讨论了这些对话代理在现实世界中的应用。不幸的是,网上没有类似的谈话,但你可能会发现最近与她的对话部分的采访很有趣。

最佳论文

会议再次向最佳长篇和短篇论文以及最佳评论者颁奖。

最佳长论文奖由腾讯的唐等人颁发给【渐进式分层抽取(PLE):一种新颖的多任务学习(MTL)个性化推荐模型】),以表彰他们改进腾讯视频推荐系统的方法。他们的解决方案解决了负迁移,负迁移描述了推荐系统中多个松散相关甚至冲突的任务之间不利的折衷。作者将最先进的 MTL 模型中的结果现象描述为跷跷板现象,其中一些任务得到改善,而牺牲了其他任务。他们提出了共享学习结构,以提高共享学习效率,从而缓解跷跷板现象和负迁移。通过工业和公共基准数据集,他们提供了他们的方法优于先前方法的证据。

图片来自唐等:、:一种新颖的多任务学习(MTL)个性化推荐模型)

Gustavo Penha 和 Rodrygo L. T. Santos 的“利用性能评估增加推荐集合”获得了最佳长论文亚军。在他们的工作中,他们提出了一种个性化的方法来组合推荐器集成的基本估计器,以在最先进的集成推荐器结果中实现显著更高的准确性。至此,他们利用历史用户反馈来生成性能估计,当生成集合推荐时,该性能估计用作基本推荐器的个性化权重。

图片来自 Gustavo Penha 和 Rodrygo L. T. Santos: 利用性能评估来扩充推荐集合

最后,最佳短文是米等人的“【ADER:面向连续学习的基于会话的推荐的自适应提取样本重放”。作者提出了一种基于会话的推荐器的连续更新方法,减轻了灾难性遗忘的风险。因此,他们确定并使用一小组有代表性的历史序列数据(样本),以便在对新数据以及蒸馏损失进行训练时进行重放。

图片来自 Mi 等人:自适应提取样本回放,实现基于会话推荐的持续学习

引起我兴趣的其他论文,也是我阅读清单上的下一篇:

  • Afchar 和 Hennequin (Deezer 研究):用属性使神经网络可解释:应用于隐含信号预测
  • Sato 等人(富士施乐):对建议的因果效应进行无偏学习
  • 黄等:将数据集偏差排除在模拟之外:基于强化学习的推荐系统去偏差模拟器
  • Schnabel 等人(微软):用小型注释数据集消除项目间推荐的偏见
  • Rendle 等人(谷歌研究):神经协同过滤与矩阵分解再探
  • 李等:层叠式混血儿土匪:在线学习相关性和多样性排名
  • 戈登堡等人(Booking.com): 免费午餐!投资回报约束内动态促销推荐的追溯提升建模
  • Aridor 等人:解构过滤泡沫——用户决策和推荐系统
  • Saito: 双稳健估计器,用于对点击后转化率指标进行排名
  • 王等:推荐系统的因果推理
  • 郭等(推特):深度贝叶斯盗匪:探索在线个性化推荐

主导主题:偏见,公平,因果关系,强盗和强化学习

在我个人看来,近年来对狭隘地关注准确性的强烈抗议已经被机构群体所听到。会议的主要议题包括承认偏见和发展消除偏见的技术,超越相关性和试图模拟因果关系,以及解决公平和问责问题。我相信,RecSys 研究团体对这些问题的了解比一般社会所认为的要多得多。然而,我的观点偏向于我在会议上看到的,而不是每个系统背后发生的事情。但也有证据表明,解决这些问题可以推动有益的长期商业目标,因此符合行业自身的利益。

这篇博客不能总结所有的发展和趋势,但它应该作为那些不能参加或想重温的人的一个切入点。关于回顾和思考观点,来自网飞的 Justin Basilico 做了一个非常翔实和精心制作的概述:“网飞最近的个性化趋势”

衡量标准的层次(图片来自 Justin Basilico 的网飞最近的个性化趋势

他为网飞确定的趋势似乎很好地反映了整个会议的大部分内容,这就是为什么我强烈建议看一下幻灯片:

  • 因果关系
  • 盗匪
  • 强化学习
  • 目标
  • 公平
  • 体验个性化

练习技能和加强交流的教程和研讨会

第四个会议日安排了 6 个针对 RecSys 实践的高级主题的教程:

  • 对话式推荐系统:视频
  • 推荐系统的特征工程(Nvidia rapids.ai): 视频和代码
  • 在搜索和推荐系统中抵消偏见并增加公平性:视频、幻灯片和参考文献
  • 推荐系统中的土匪简介:视频和代码
  • 基于贝叶斯值的推荐:基于代理和反事实策略的推荐(Criteo)的一种基于模型的替代方案:视频和代码
  • 对抗性学习推荐:安全和生成性任务的应用—概念到代码:视频、幻灯片和代码

在过去的两天里,我们还举办了 12 场有趣的研讨会,以强化 RecSys 研究中的特定主题:

  • CARS :情境感知推荐系统研讨会
  • ComplexRec :关于复杂环境中的建议的研讨会
  • FAccTRec :关于负责任的建议的研讨会
  • 时尚与零售推荐系统研讨会
  • 健康推荐系统研讨会
  • impacters:关于推荐系统影响的研讨会
  • IntRS :关于推荐系统的界面和人类决策的联合研讨会
  • OHARS :在线错误信息和危害感知推荐系统研讨会
  • 在线推荐系统和用户建模研讨会
  • 播客推荐研讨会
  • 揭示:关于从用户交互中学习 Bandit 和强化的研讨会
  • RecSys 挑战 2020 研讨会

请登录rec sys 官方网站链接到您的专用车间。

与去年类似,REVEAL workshop 吸引了最多的关注,共有 900 多名参与者。你一定要去看看。还有开放 bandit 管道的发布——这是一个用于 Bandit 算法和非策略评估的 python 库,被认为是本次研讨会的亮点之一。

关于 RecSys Challenge 2020 Workshop,请查看 NVIDIA 获胜团队的博客帖子,在此处描述他们的解决方案。

社会的

由于完全虚拟的环境以及社交活动在 RecSys 会议中发挥着至关重要的作用,会议的社交方面是迄今为止最具挑战性的。但是,在回顾中,虚拟代孕超出了我所有的期望!Whova event 应用程序提供了一个简单而强大的单一入口:查看议程、与同行联系、开始讨论、观看演示等。使用(网络)应用程序时非常好用。然而,这仅仅是开始。远程个人联系和快乐的主要驱动力是gather . town——一个类似神奇宝贝的 2D 虚拟环境,有你可以导航的小化身。只要碰到一堆其他头像,上面贴着参与者的名字,就可以启动一个即时视频会议,覆盖所有你家附近的人。使用交互式 pdf 覆盖的海报会议,当踩在他们的海报区地毯上时与演讲者建立联系,撞上某人并进行小聊天,或在桌子旁进行私人谈话,或邀请人们到你家或更现实的里约热内卢海滩,一切都真正带来了与你的同伴或结识新朋友建立联系的感觉。这是一个爆炸。这个小工具真的激发了人们的喜悦之情,他们喜欢面对面的交流,因为这感觉就像是真的一样。

作者图片

这使得从 it 部门启动我们的远程卡拉 ok 会议、参加鸡尾酒会或只是听一些现场音乐变得更加令人愉快。亲爱的组委会:你们做了出色的工作!

图片取自https://twitter.com/DrCh0le/status/1309232717272289280

更多有用的链接

  • 所有论文都可以在会议论文集中免费获得
  • 推特上的 RecSys 2020 挑战赛
  • 谷歌大脑发布 TensorFlow 推荐器
  • 在 AIcrowd 上重新发布 Spotify 百万播放列表数据集
  • 更多即将发布的材料将在此处发布,敬请关注!

阿姆斯特丹的 RecSys 2021

带着所有这些信息和美好的经历,全球 RecSys 社区期待着 2021 年的第 15 次聚会。就我个人而言,我希望科罗纳疫情将得到很好的控制,然后允许一个存在的事件。如果是这样的话,全球 RecSys 社区将于 9 月 27 日至 10 月 1 日在阿姆斯特丹举行会议,地点就在阿姆斯特丹会议中心——阿姆斯特丹证券交易所的前身。因此,它的口号不足为奇:“一个聚会和交流的地方”。希望在那里见到你。

图片取自https://recsys.acm.org/recsys21/

基于奇异值分解的推荐系统变体的实现

原文:https://towardsdatascience.com/recsys-implementation-on-variants-of-svd-based-recommender-system-a3dc1d059c83?source=collection_archive---------35-----------------------

由罗马法师在 Unsplash 上拍摄的照片

模型包括 lightFM、RDF SVD 和神经协同过滤

一般来说,推荐算法的发展分为三个领域:基于内容的模型、协同过滤模型和基于深度神经网络的模型。在本文中,我们将重点讨论 CF,尤其是基于 SVD 的算法。我们不仅要练习建立基于奇异值分解的模型,还要练习它的变体,比如一个正则化模型和另一个采用神经网络的模型。

另外,基于 SVD 的分类模型只考虑了用户/iterm 交互。它既不考虑用户与项目交互时的上下文信息(例如:用户在地铁列车上浏览手机上的产品列表),也不利用隐藏在连续动作中的含义。然而,包含这些信息会使我们的模型更加复杂,因此我们不会在本文中讨论这些问题。如果你对应用这些技术感兴趣,欢迎查看 YouTube(2016) 和华为(2017) 发表的论文。这里也有相关的 git repos 供你参考——实现 YouTube 和华为。

熟悉数据集

我们这里使用的数据集来自作者 moorissa 的 github repo 。它由客户的杂货购买记录组成。首先,让我们看看数据是如何构造的。

采购记录的数据布局

显然,这个数据集还不能用于模型训练。products列堆满了物品 id(与|连接在一起)。我们需要对其进行预处理,并将其转换为模型期望接受的内容。

下面,我们将准备两种类型的数据格式,一种是用户-iterm 交互矩阵,另一种是长格式数据帧(见下面的演示)。

预期格式 01:用户-项目互动矩阵

用户-项目矩阵格式

在用户-项目交互矩阵中,每行代表一个用户,每列代表一个产品项目。对应索引(I,j)处的条目是重复购买的次数(或者更广义地解释为交互强度)。这种数据格式通常适用于传统的 SVD 建模。

预期格式 02:长格式数据帧

长格式数据帧

在长格式数据帧中,每一行代表一对(用户、物品)的重复购买次数(或交互强度)。参见上面的演示,我们有第一列为 customerId ,第二列为 productId ,因此是(用户,项目)对。最后一列 purchase_count 填入相应的购买次数。长格式数据帧是非常普遍和广泛使用的。它更适合基于神经网络(NN)的建模。

我们已经为数据预处理和转换设定了目标,现在让我们看看如何实现它。

逐步—数据预处理

步骤 01:转换数据类型和格式转换

下面的代码是从作者moorissa【1】那里借来的,他是这个数据集的同一个回购作者。主要的想法是拆分条目的字符串(最初用|连接),并将其保存为 pd.Series。然后我们使用 pd.melt()将数据从宽格式转换为长格式。最后,我们应用 df.groupby()来聚合每个(用户、商品)购买记录。就是这样。现在,我们手头有了一个干净的长格式数据集。

我们可以直接在数据集上应用trx_transform()来完成任务。

步骤 02:重新缩放数据集

我们知道每个用户去商场的频率不同。最终,每个用户的购买数量是不同的。为了让模型更好地正确、一致地解释每个用户的交互,我们最好将每个用户的购买计数重新调整到范围(0,1)。

data["max_count"] = data.groupby("customerId")["purchase_count"].transform(
    lambda x: x.max())data["purchase_count_norm"] = data["purchase_count"] / data["max_count"]

步骤 03:创建用户-项目互动矩阵

在这一步,我们将应用df2interact_mat()将长格式数据集转换为交互矩阵。代码借用本帖【2】稍作改编。

(可选)一旦我们创建了交互矩阵,我们也可以计算矩阵的稀疏度。当稀疏度大于 99.5%(意味着不到 0.5%的总条目为非零)时,协同过滤模型表现不佳。一种补救方法是删除一些几乎全是零的用户或项目,从而使矩阵变绿。

步骤 04:创建训练/测试集

此外,我们需要为模型评估创建训练/测试集。值得注意的一点是,在推荐建模下,训练/测试分割是相当不同的。在传统的训练/测试分裂中,我们从训练集中分离出行的子集作为测试集。然而,在这种情况下,我们采用类似于屏蔽的方法,对用户部分屏蔽一些项目。这就像假装用户还没有看到该项目。并使用未屏蔽的项目来训练模型。一旦模型准备好,然后我们使用屏蔽的项目作为测试集标签,并查看模型的预测是否正确地将这些项目包括在用户的推荐列表中。

推荐情况下的训练/测试分割

同样,我将它包装在一个函数train_test_split()中,以简化这个过程。

使用该功能时,我们需要提供:

  • 评级:用户-项目交互矩阵。
  • split_count:(整数)每个用户从训练集转移到测试集的项目交互次数。
  • fractions: (float)用户将他们的一些项目交互拆分到测试集中的部分。如果没有,则考虑所有用户。

该函数将返回三个对象。

  1. 列车组:列车交互矩阵
  2. 测试集:测试交互矩阵
  3. user_index:对测试集屏蔽了一些交互的用户索引,存储为索引以备后用

至此,我们手头已经有了训练和测试交互矩阵。然而,我们也可以在这里为神经网络建模准备长格式数据帧。

步骤 05:准备长格式数据帧

幸运的是,Scipy 首席运营官矩阵有一堆方便的方法。我们可以将这个矩阵转换成首席运营官数据类型。然后我们只需简单地调用 coo.row、coo.colcoo.data 来访问各自的索引和数据。最后,我们将这些片段放在一起,创建长格式数据集。

# Ref: [https://stackoverflow.com/a/36587845](https://stackoverflow.com/a/36587845)train_long = train.tocoo(copy=True)
test_long = test.tocoo(copy=True)# Access `row`, `col` and `data` properties of coo matrix.
train_long = pd.DataFrame({
    'user_id': train_long.row,
    'item_id': train_long.col,
    'rating': train_long.data
})[['user_id', 'item_id',
    'rating']].sort_values(['user_id', 'item_id']).reset_index(drop=True)# Apply the same operation on test data.
test_long = pd.DataFrame({
    'user_id': test_long.row,
    'item_id': test_long.col,
    'rating': test_long.data
})[['user_id', 'item_id',
    'rating']].sort_values(['user_id', 'item_id']).reset_index(drop=True)

和在 Unsplash 上拍照

开始建模吧!

恭喜你!我们刚刚完成了所有繁琐的数据预处理步骤。现在我们可以做一些更有趣的事情了。我们将总共测试三种型号。首先是 lightFM 模型,其次是 RDF 模型,最后是 NN 模型。

什么是因式分解机(FM)?

在讨论第二种模型时,我们将提出奇异值分解基本上是调频的一种特殊情况。但在此之前,让我们快速回顾一下什么是 FM,并了解一下 lightFM 模块如何利用这项技术。

正如本帖【3】中所解释的,FM 主要用于简化特征交互系数的估计( θ )。最初,必须逐个估计成对特征交互的系数。然而,FM 玩了一个把戏,定义了具有 K 个潜在嵌入的每个特征,并假设交互作用的系数可以通过这些潜在嵌入的内积来估计。该方法巧妙地将成对系数估计简化为潜在嵌入估计,极大地提高了效率。

下图清楚地展示了不同之处。

之前:

原创模型(鸣谢:陈鸿轩)

  1. FM 将对相互作用系数的估计( θ )简化为对潜在嵌入的估计( V )。
  2. 成对潜在嵌入的内积代替了成对交互系数估计(见下文)。

之后:

从这篇帖子解释因式分解模型

lightFM 丰富了什么?

lightFM 的作者在 FM 方法的基础上做了一点小小的修改,使得 lightFM 模型可以在新用户的推荐下使用。

正如在论文【4】中所述,lightFM 模块非常灵活。如果只提供用户-项目交互矩阵,那么模型只是一个矩阵分解模型。但是,我们也可以从用户和项目提供额外的功能。然后,该模型将合并这些信息,并转而使用因式分解机。下面的过程是 first lightFM 将这些特征以及用户/项目指示符(索引)转换为 K 维嵌入。每个用户或物品的表征是所有潜在嵌入特征的总和。(见下图)这种将用户或项目表示为特征嵌入总和的方式允许模型对新用户进行预测。这解决了协同过滤模型中最棘手的问题之一——冷启动问题。

旁注:冷启动意味着新用户或项目没有过去的用户-项目交互记录,因此不可能向新用户推荐或向现有用户推荐新项目。

lightFM 将用户/项目表示为其内容特征的线性组合。(来自论文)

一旦我们熟悉了 lightFM 背后的概念,让我们试着实现它。

第一个模型:通过 lightFM 模块构建推荐器

A.构建和训练模型

使用 lightFM 构建推荐器非常简单。只需实现下面的代码,并在模型初始化中指定自定义参数。

# Initialize model with self-defined configuration.model = LightFM(no_components=20, 
                learning_rate=0.005, 
                loss='bpr', 
                random_state=12)# Start training.model.fit(train, epochs=50, verbose=True) #train: interaction matrix

B.模型预测和评估

在完成模型训练后,我们可以使用两个指标来评估它。一个是 RMSE,另一个是 Top@K precision。

对于像我们这样的机器学习实践者来说,RMSE 是一个非常常见的指标。它可以衡量实际评分(或在这种情况下的购买强度)和预测评分之间的差异。同时,Top@K 用于衡量用户实际购买推荐的 top k 商品的比例。

现在,让我们使用模型进行预测。

# Ref: [https://
github.com/lyst/lightfm/blob/9ffeacbdc4688e9b58c6e5edfdeb52b037608a6b/lightfm/lightfm.py#L784](https://github.com/lyst/lightfm/blob/9ffeacbdc4688e9b58c6e5edfdeb52b037608a6b/lightfm/lightfm.py#L784)# predict() takes only numpy.array
predictions = model.predict(val_user_ids, 
                            val_item_ids)

这里, val_user_idsval_item_ids 来自长格式测试数据帧。

-计算 RMSE

我们定义了一个名为compute_rmse的函数来帮助完成这项任务。

def compute_rmse(X_test, X_pred):
    # Ref: [https://github.com/ncu-dart/rdf/blob/master/rdf/utils.py](https://github.com/ncu-dart/rdf/blob/master/rdf/utils.py)

    sse = 0.
    for i in range(len(X_test)):
        sse += (X_test[i] - X_pred[i]) ** 2

    return (sse / len(X_test)) ** .5

这个函数有两个参数。

  • X_test: (arr)正常化的真实购买值
  • X_pred: (arr)标准化的预测采购值

-计算 Top@K

在计算 Top@K 之前,我们需要首先将模型的预测转换为交互矩阵。

predict_mat = sparse.csr_matrix(
    (predictions, (val_user_ids, val_item_ids)), 
    shape=(n_users, n_items)
)

然后,我们使用之前保存的 user_index 提取这些测试用户的购买记录。

test_sub = test[user_index] # true user purchase
predict_mat_sub = predict_mat[user_index] # predicted user purchase

最后,我们准备计算 Top@K。假设我们只想计算前 4 个预测项的准确性。我们只是运行下面的代码。

top_k = 4  # hyper-parameterpredict_top_k = []
for i in range(len(user_index)):
    # csr.indices and csr.data only return non-zero entries

    predict_r = predict_mat_sub[i].indices[
        predict_mat_sub[i].data.argsort()[::-1]][:top_k]

    true_r = test_sub[i].indices[
        test_sub[i].data.argsort()[::-1][:top_k]]

    pre = len(set(predict_r) & set(true_r))/ float(top_k)
    predict_top_k.append(pre)np.mean(predict_top_k)

这样,我们可以获得 lightFM 模型的 RMSE 和 Top@K 性能,如下所示:

  • RMSE: 0.721
  • Top@K: 1

第二个模型:使用 RDF 方法构建推荐器

让我们在另一个叫做 RDF-SVD 的模型上进行实验——正则化微分函数。这个方法【5】是由台湾 NCU 的陈鸿轩教授和他的研究助理陈普提出的。

在讲 RDF 之前,我们先来回顾一下 SVD。在 SVD 的损失函数中,我们可以在每个系数估计上包括正则化项( λ )。它用于防止模型中的过度拟合。

具有偏差和正则项的奇异值分解损失函数(来自论文

特别是,\hat{r}(预测评级)等于…

奇异值分解预测额定值方程(来自论文

将上面的等式与第一个模型中的 FM 进行比较,可以清楚地看出 SVD 只是 FM 模型的一个特例。

陈教授的方法(RDF)也是 lightFM 的设计目标,旨在解决冷启动问题。lightFM 试图通过引入特征潜在嵌入来解决这个问题,而 RDF 则侧重于奇异值分解损失函数中的正则项。

总的想法是,对于已经被更多用户评级(或购买)的项目,我们可以对模型的预测有信心。这同样适用于那些比其他人评价更多项目的用户。因为我们从这些受欢迎的项目和活跃用户那里收集了更多的数据,所以建立在此基础上的模型不太可能过度拟合和不准确。尽管如此,对于评分较低的项目和活跃用户,我们没有太多的记录。因此,我们对这些项目或用户的系数估计使用了更大的正则项。这导致我们的损失函数如下:

带有正则化微分函数的损失函数(来自论文

等式中的“*****”代表项目被评分的次数或用户评分的次数。 f() 是一个单调递增的函数。基于本文的实验,采用这种改进的 RDF 的模型在精度上有了很大的提高。在这里,让我们尝试使用这种方法建立一个模型。

A.首先,导入 rdf

陈教授和将这种方法封装在一个叫做 rdf 的模块中。这是源代码链接。我们只需要在使用之前克隆 repo 并安装模块。

B.选择长格式数据帧作为训练/测试数据集

长格式数据帧

我们首先选择长格式数据帧作为输入数据集。然后,我们需要再次将它转换成 rdf 模块要求的格式。对于每条记录,它必须以下列格式存储。

[(客户标识,产品标识,评级),(客户标识,产品标识,评级),…]

下面的代码为我们完成了这项工作。

ll = train_long.apply(lambda x: (x[0], x[1], x[2]), axis = 1)
X = list(ll)# Apply the same operation on test data.
ll = test_long.apply(lambda x: (x[0], x[1], x[2]), axis = 1)
X_test = list(ll)

C.启动和训练模型

rdf 模块能够对各种算法应用微分正则化,包括 SVD、SVD++和 NMF。在本文中,为了简单起见,我们选择了基本的 SVD 模型,并应用了 repo 中的默认超参数。

model = rdf.rdfsvd.RDFSVD(n_users=n_users,
                          n_items=n_items,
                          lr=.005,
                          lmbda_p=500,
                          lmbda_q=500,
                          lmbda_u=.01,
                          lmbda_i=.01,
                          method="linear")model.train(X)

D.模型预测和评估

一旦模型训练完成,我们就可以用它在 RMSE 和 Top@K 上进行预测并评估其性能

# make predictions
X_pred = model.predict(X_test)

测试-(用户标识,项目标识,评级)元组上 RDF-SVD 模型预测的演示

将上述代码应用于 rmse 和 top@k 计算,我们得到如下指标:

  • RMSE: 0.245
  • Top@K: 1

第三个模型:使用神经协同过滤构建推荐器

最后,让我们尝试将深度学习框架整合到我们的推荐器中。这里让我们介绍一个非常通用的框架,叫做神经协同过滤(NCF)。这是报纸的链接【6】。另外,我强烈推荐 Steeve Huang 写的这篇中帖【7】。如果你想节省时间,跳过阅读原文,这是让你快速掌握 NCF 概貌的必读文章。

神经协同过滤模型(来自论文

A.模型算法

在论文中,作者提出了两个框架,一个是广义矩阵分解(GMF),如上图(左)所示,另一个是多层感知器(MLP),如上图(右)所示。在模型的最后一层,来自两个框架的输出将连接在一起,作为最终输出。

如果我们更仔细地观察,我们会发现曼氏金融只是 GMF 的另一个特例。

与 MF 的关系(信用: Steeve Huang )

Eq 1是 GMF 下的用户-物品交互。 L 为激活函数, J_kx1 为输出层的边权重。在 GMF 框架下, L 可以是线性的也可以是非线性的, J_kx1 代表潜在向量中各维度的权重。

假设我们说 L 是一个线性激活函数,而 J_kx1 是一个所有值都为 1 的向量(意味着每个维度具有相同的权重),那么 GMF 将还原为原始 MF,即 pᵤ和qᵢ的内积,如Eq 3所示。

我在此引用教皇的话:

在 NCF 框架下,物流可以很容易地推广和扩展…它将物流推广到一个非线性的设置,这可能比线性物流模型更有表现力。

然而,NCF 并没有就此止步。它还包括多层感知器(MLP)作为模型中的另一个分支,以便捕捉用户和项目之间的高阶非线性交互。我在这里引用:

我们可以赋予模型很大程度的灵活性和非线性,以了解 pᵤ和 qᵢ之间的相互作用,而不是像 GMF 那样只使用它们的固定元素乘积。

在 MLP 框架中,作者也做了几次尝试来测试多少层对模型来说是最合适的。一般来说,模型越深,精度越高。在基本结构中,它有 3 层,每层的节点比上一层减少一半。

还有另外三个有趣的点值得一提。

  1. 进行预培训:我们可以将 GLM 和 MLP 分开,对每个模型进行预培训。然后我们使用这些模型的权重作为 NCF 模型的初始化权重。实验表明,该方法比直接随机初始化 NCF 模型的权重具有更好的性能。
  2. 使用负抽样:对于那些用户没有交互的项目,我们可以进行负(不交互)到正(有交互)抽样。在训练集中添加一部分负样本可以提高模型的性能。但是比例是多少呢?在实验中,1:1 的正负比例并不能达到最佳效果。在训练集中,负样本的比率最好大于 1。作者最后选择了 4:1(阴性:阳性)。
  3. 输出层的加权初始化:这是模型调整的可选步骤。特别是在培训前的情况下。NCF 的输出层是 GMF 和 MLP 输出的拼接。我们可以做得更巧妙的是,给每个输出分配权重(α)和(1-α),以便对一个输出比另一个输出给予更多的重视。权重(α)是自定义的指定超参数。

在下面的实现中,为了简单起见,不包括上面提到的任何实践。我们只是构建 GMP 和 MLP 模型,并将两者结合起来。无负采样,两个输出无加权初始化(α)。

B.建立模型

这里我使用了 tensorflow 2.0 下的 tf.keras API 来构建模型。我主要采用了 Steeve Huang 的回购【8】的模型,只是对超参数做了一些修改,以便与原始论文中的参数保持一致。

建立 NCF 模型

C.训练模型

我们再次需要使用长格式数据集来训练我们的 NCF 模型。

from tensorflow.keras.callbacks import EarlyStopping# early stopping wait for 3 epoch
callbacks = [EarlyStopping(patience=3, restore_best_weights=True)]# train and test set
train_user_ids = train_long["user_id"]
train_movie_ids = train_long["item_id"]
train_ratings = train_long["rating"]val_user_ids = test_long["user_id"]
val_movie_ids = test_long["item_id"]
val_ratings = test_long["rating"]# train for 50 epochs
model.fit([train_user_ids, train_movie_ids],
          train_ratings,
          validation_data=(
              [val_user_ids, val_movie_ids], val_ratings),
          epochs=50,
          batch_size=128,
          callbacks=callbacks)

D.模型预测和评估

最后,下面是 NCF 在 RMSE 和 Top@K 上的表现指标

  • RMSE: 0.231
  • Top@K: 1

最终反射

我们在这里看到三个模型有趣的结果。所有模型在 Top@K 中得到了 1(在 Top 4 的情况下),意味着模型推荐的前 4 件商品实际上都是测试用户在现实中购买的。也许这不是偶然发生的。在数据预处理中,我尽量去除数据集中一些交互记录不多的项目或用户。它导致更致密的相互作用矩阵。手头剩余的项目和用户,大多数都有相当多的交互记录。因此,任何协作过滤模型表现良好都不足为奇。

尽管如此,让我们比较另一个指标,RMSE。我们看到,lightFM 的误差最大(0.72),NCF 的误差最小(0.23),尽管与 RDF-SVD 的误差(0.24)相差不大。

所以总的来说,我们可以说 NCF 仍然有最好的表现。

如果你对整个实现感兴趣,欢迎查看我的回购。希望你喜欢这篇文章,并欢迎提供任何进一步改进的反馈。干杯!

参考

[1] moorissa,如何构建购买数据的推荐系统(循序渐进)(2018)Github

[2]杰西·斯坦威格·伍兹,含蓄反馈推荐系统的温和介绍 (2016),个人博客

[3] Jimmy Wu, Factorization Machines — 稀疏資料的救星 (2019), Medium

[4]马切伊·库拉,用户和项目冷启动的元数据嵌入
建议 (2015),Lyst.com

[5]陈鸿轩和陈普,区分正则化权重——一种减轻推荐系统冷启动的简单机制(2019)美国计算机学会数据知识发现汇刊

[6] X 何等,神经协同过滤 (2017),国大

[7] Steeve Huang,论文综述:神经协同过滤解说&实现 (2018),走向数据科学

[8] Steeve Huang,2019, Github

推荐系统系列第 4 部分:用于协同过滤的矩阵分解的 7 种变体

原文:https://towardsdatascience.com/recsys-series-part-4-the-7-variants-of-matrix-factorization-for-collaborative-filtering-368754e4fab5?source=collection_archive---------2-----------------------

RecSys 系列

矩阵分解的数学深度探究

更新: 本文是我探索学术界和工业界推荐系统系列文章的一部分。查看完整系列: 第一部分 第二部分 第三部分 第四部分 第五部分

协同过滤是任何现代推荐系统的核心,它已经在亚马逊、网飞和 Spotify 等公司取得了相当大的成功。它的工作原理是收集人们对某个特定领域的项目的判断(称为评级),并将具有相同信息需求或相同品味的人匹配在一起。协同过滤系统的用户共享他们对他们消费的每个项目的分析判断和意见,以便系统的其他用户可以更好地决定消费哪些项目。反过来,协同过滤系统为新项目提供有用的个性化推荐。

协同过滤的两个主要领域是(1)邻域方法和(2)潜在因素模型。

  • 邻域法专注于计算项目之间或用户之间的关系。这种方法基于同一用户对相邻项目的评级来评估用户对项目的偏好。一个项目的邻居是由同一用户评价时倾向于获得相似评价的其他产品。
  • 潜在因素法通过从评级模式中推断出的许多因素来描述项目和用户的特征,从而解释评级。例如,在音乐推荐中,发现的因素可能测量精确的维度,如嘻哈与爵士、高音量或歌曲长度,以及不太明确的维度,如歌词背后的含义,或完全无法解释的维度。对于用户来说,每个因素衡量用户有多喜欢在相应歌曲因素上得分高的歌曲。

一些最成功的潜在因素模型是基于矩阵分解。在其自然形式中,矩阵因子分解使用从项目评级模式推断的因子向量来表征项目和用户。项目和用户因素之间的高度对应导致推荐。

Sharmistha Chatterjee —使用 Python 的矩阵分解技术概述(https://towardsdatascience . com/Overview-of-Matrix-Factorization-Techniques-using-Python-8e 3d 118 a9 b 39)

在这篇文章和接下来的文章中,我将介绍推荐系统的创建和训练,因为我目前正在做这个主题的硕士论文。

  • 第 1 部分提供了推荐系统的高级概述,它们是如何构建的,以及它们如何用于改善各行业的业务。
  • 第 2 部分对正在进行的关于这些模型的优势和应用场景的研究计划进行了仔细的回顾。
  • 第 3 部分提供了几个可能与推荐系统学者社区相关的研究方向。

在第 4 部分中,我深入探讨了矩阵分解的数学细节,这可以说是目前推荐系统研究中最常见的基线模型。更具体地说,我将向您展示可以构建的矩阵分解的七种变体——从边特征的使用到贝叶斯方法的应用。

1 —标准矩阵分解

一个简单的矩阵分解模型将用户和项目都映射到一个维度为 D 的联合潜在因素空间,这样用户-项目交互就被建模为该空间中的内积。

  • 因此,每个项目 I 与向量 q_i 相关联,并且每个用户 u 与向量 p_u 相关联
  • 对于一个给定的项目 I,q_i 的元素测量该项目拥有这些因素的程度,积极的或消极的。
  • 对于给定的用户 u,p_u 的元素测量用户对项目的兴趣程度,该项目在相应的正面或负面因素上是高的。
  • 得到的点积(q_i * p_u)抓住了用户 u 和物品 I 之间的交互,是用户对物品特征的整体兴趣。

因此,我们有如下等式 1:

最大的挑战是计算每个项目和用户到因子向量 q_i 和 p_u 的映射。矩阵分解通过最小化已知评级集的正则化平方误差来实现这一点,如下面的等式 2 所示:

通过拟合先前观察到的评级来学习该模型。然而,目标是以预测未来/未知评级的方式来概括那些先前的评级。因此,我们希望通过向每个元素添加 L2 正则化惩罚来避免过度拟合观察到的数据,并同时利用随机梯度下降来优化学习到的参数。

Shay Palachy 的这篇文章很好地解释了直觉,以下是快速注释:

  • 当我们使用 SGD 来将模型的参数拟合到手头的学习问题时,我们在算法的每次迭代中在解空间中朝着损失函数相对于网络参数的梯度前进一步。由于我们推荐的用户-项目交互矩阵非常稀疏,这种学习方法可能会过度适应训练数据。
  • L2(也称为吉洪诺夫正则化或岭回归)是一种正则化成本函数的特定方法,增加了一个表示复杂性的项。该项是用户和项目潜在因素的平方欧几里得范数。添加一个附加参数λ,以允许控制正则化的强度。
  • 加入 L2 项通常会使整个模型的参数变得更小。

让我们看看这在代码中是什么样子的:

这个模型的完整实验可以在这里访问:https://github . com/khanhnamle 1994/transfer-rec/tree/master/Matrix-Factorization-Experiments/Vanilla-MF

2 —有偏差的矩阵分解

协作过滤的矩阵分解方法的一个好处是它在处理各种数据方面和其他应用特定的需求方面的灵活性。回想一下,等式 1 试图捕捉产生不同评级值的用户和项目之间的交互。然而,许多观察到的评分值的变化是由于与用户或项目相关的影响,称为偏差,与任何交互无关。这背后的直觉是,一些用户给出比其他人高的评级,一些项目系统地获得比其他人高的评级。

因此,我们可以将等式 1 扩展到等式 3,如下所示:

  • 总体平均评级中包含的偏差用 b 表示。
  • 参数 w_i 和 w_u 分别表示项目 I 和用户 u 与平均值的观测偏差。
  • 请注意,观察到的评级分为 4 个部分:(1)用户-项目互动,(2)全球平均,(3)项目偏见,和(4)用户偏见。

通过最小化新的平方误差函数来学习该模型,如下面的等式 4 所示:

让我们看看这在代码中是什么样子的:

这个模型的完整实验可以在这里访问:https://github . com/khanhnamle 1994/transfer-rec/tree/master/Matrix-Factorization-Experiments/MF-bias

3 —带辅助特征的矩阵分解

协同过滤中的一个常见挑战是冷启动问题,因为它无法处理新项目和新用户。或者许多用户提供非常少的评级,使得用户-项目交互矩阵非常稀疏。缓解这个问题的一个方法是加入关于用户的额外信息来源,也就是的侧面特征。这些可以是用户属性(人口统计)和隐式反馈。

回到我的例子,假设我知道用户的职业。对于这个侧面特征,我有两种选择:将其作为一种偏见添加(艺术家比其他职业更喜欢电影)和作为一种向量添加(房地产经纪人喜欢房地产节目)。矩阵分解模型应该将所有信号源与增强的用户表示相结合,如等式 5 所示:

  • 对职业的偏好用 d_o 表示,这意味着职业像速率一样变化。
  • 职业的向量由 t_o 表示,意味着职业根据项目(q_i * t_o)而变化。
  • 请注意,必要时项目可以得到类似的处理。

损失函数现在是什么样子的?下面的等式 6 表明:

让我们看看这在代码中是什么样子的:

这个模型的完整实验可以在这里访问:https://github . com/khanhnamle 1994/transfer-rec/tree/master/Matrix-Factorization-Experiments/MF-Side-Features

4-具有时间特征的矩阵分解

到目前为止,我们的矩阵分解模型是静态的。在现实中,项目受欢迎程度和用户偏好是不断变化的。因此,我们应该考虑反映用户-项目交互的动态性质的时间效应。为了实现这一点,我们可以添加一个影响用户偏好的时间项,从而影响用户和项目之间的交互。

为了更复杂一点,让我们用时间 t 的评级的动态预测规则来尝试下面的新等式 7:

  • p_u (t)将用户因素作为时间的函数。另一方面,q_i 保持不变,因为项目是静态的。
  • 我们根据用户的不同有职业的变化(p_u * t_o)。

等式 8 显示了包含时间特征的新损失函数:

让我们看看这在代码中是什么样子的:

这个模型的完整实验可以在这里访问:https://github . com/khanhnamle 1994/transfer-rec/tree/master/Matrix-Factorization-Experiments/MF-Temporal-Features

5 —因式分解机器

推荐系统的一个更强大的技术叫做因式分解机器,它具有强大的表达能力来概括矩阵因式分解方法。在许多应用程序中,我们有大量的项目元数据可以用来进行更好的预测。这是对特征丰富的数据集使用因式分解机的好处之一,对于这种情况,有一种自然的方式可以将额外的特征包括在模型中,并且可以使用维度参数 d 对高阶交互进行建模。对于稀疏数据集,二阶因式分解机模型就足够了,因为没有足够的信息来估计更复杂的交互。

Berwyn Zhang —因式分解机()http://Berwyn Zhang . com/2017/01/22/machine _ learning/Factorization _ Machines/)

等式 9 显示了二阶 FM 模型的情况:

其中 v 代表与每个变量(用户和项目)相关的 k 维潜在向量,括号运算符代表内积。根据 Steffen Rendle 关于因式分解机的原始论文,如果我们假设每个 x(j)向量仅在位置 u 和 I 处非零,我们得到带有偏差的经典矩阵因式分解模型(等式 3):

这两个方程之间的主要区别是因式分解机器在潜在向量方面引入了更高阶的相互作用,潜在向量也受到分类或标签数据的影响。这意味着模型超越了共现,以发现每个特征的潜在表示之间更强的关系。

因式分解机器模型的损失函数就是均方误差和特征集的和,如公式 10 所示:

让我们看看这在代码中是什么样子的:

这个模型的完整实验可以在这里访问:https://github . com/khanhnamle 1994/transfer-rec/tree/master/Matrix-Factorization-Experiments/Factorization-Machines

6-混合口味的矩阵分解

到目前为止,提出的技术隐含地将用户的口味视为单峰的——也就是在单个潜在向量中。这可能会导致在代表用户时缺乏细微差别,在这种情况下,主流口味可能会压倒更多的小众口味。此外,这可能降低项目表示的质量,减少属于多个品味/风格的项目组之间的嵌入空间的分离。

马切伊·库拉提出并评估了将用户表示为几种不同口味的混合物,由不同的口味向量来表示。每个味道向量都与一个注意力向量相关联,描述了它在评估任何给定项目时的能力。然后,用户的偏好被建模为所有用户口味的加权平均值,权重由每个口味与评估给定项目的相关程度提供。

等式 11 给出了这种混合味道模型的数学公式:

  • U_u 是代表用户 u 的 m 个口味的 m×k 矩阵。
  • A_u 是一个 m×k 矩阵,表示来自 U_u 的每一种口味的相似性,用于表示特定的项目。
  • \sigma 是软最大激活函数。
  • \sigma(A_u * q_i)给出混合概率。
  • U_u * q_i 给出了每种混合物成分的推荐分数。
  • 请注意,我们假设所有混合成分的单位方差矩阵。

因此,下面的等式 12 表示损失函数:

让我们看看这在代码中是什么样子的:

这个模型的完整实验可以在这里访问:https://github . com/khanhnamle 1994/transfer-rec/tree/master/Matrix-Factorization-Experiments/MF-Mixture-Tastes

7 —变分矩阵分解

我想介绍的矩阵分解的最后一个变体叫做变分矩阵分解。到目前为止,这篇博文讨论的大部分内容是关于优化模型参数的点估计,而 variable 是关于优化后验估计,粗略地说,它表达了一系列与数据一致的模型配置。

以下是改变的实际原因:

  • 变分法可以提供替代的正则化。
  • 变分法可以度量你的模型不知道的东西。
  • 变分法可以揭示蕴涵以及分组数据的新方法。

我们可以通过以下方式改变等式 3 中的矩阵分解:(1)用来自分布的样本替换点估计,以及(2)用正则化新的分布替换正则化该点。数学是相当复杂的,所以我不会试图在这篇博文中解释它。关于变分贝叶斯方法的维基百科页面是一个有用的入门指南。最常见的变分贝叶斯使用 Kullback-Leibler 散度作为去相似性函数的选择,这使得损失最小化变得容易处理。

让我们看看这在代码中是怎样的:

这个模型的完整实验可以在这里访问:https://github . com/khanhnamle 1994/transfer-rec/tree/master/Matrix-Factorization-Experiments/variation-MF

模型评估

你可以在 this repository 查看我为 MovieLens1M 数据集做的所有 7 个矩阵分解实验。所有模型都经过 50 个时期的训练,结果在 TensorBoard 中捕获。评估指标是均方误差,即预测评分和实际评分之间所有平方差的总和。

结果表位于自述文件的底部,如您所见:

  • 变分矩阵分解的训练损失最小。
  • 具有边特征的矩阵分解具有最低的测试损失。
  • 因式分解机器的训练时间最快。

结论

在这篇文章中,我讨论了矩阵分解的直观意义及其在协同过滤中的应用。我还谈到了它的许多不同的扩展:(1)添加偏见,(2)添加侧面特征,(3)添加时间特征,(4)升级到因子分解机器以利用高阶交互,(5)使用带有“注意”机制的混合口味,(6)使模型变得不同。我希望您已经发现这种深入矩阵分解世界的数学方法是有帮助的。请继续关注本系列未来的博客文章,这些文章将超越矩阵分解的领域,深入探讨协作过滤的深度学习方法。

参考

  • 推荐系统的矩阵分解技术 耶胡达·科伦,罗伯特·贝尔,克里斯·沃林斯基。2009 年 8 月
  • py torch中简单灵活的深度推荐器。克里斯·穆迪。2018

现在继续上 推荐系统第五部分

如果你想关注我在推荐系统、深度学习和数据科学新闻方面的工作,你可以查看我的 中的 GitHub,以及在【https://jameskle.com/】的其他项目。你也可以在 推特 直接发邮件给我 ,或者 在 LinkedIn 上找我 注册我的简讯 就在你的收件箱里接收我关于数据科学、机器学习和人工智能的最新想法吧!

推荐系统系列之五:用于协同过滤的多层感知器的 5 种变体

原文:https://towardsdatascience.com/recsys-series-part-5-neural-matrix-factorization-for-collaborative-filtering-a0aebfe15883?source=collection_archive---------15-----------------------

RecSys 系列

将神经架构引入建议

更新: 本文是我探索学术界和工业界推荐系统系列文章的一部分。查看完整系列: 第一部分 第二部分 第三部分 第四部分 第五部分

协同过滤算法是推荐系统应用中最常用的算法。由于互联网的使用和产生的大量信息,用户找到他们的偏好变成了一项非常乏味的任务。用户对项目的偏好以评分矩阵的形式表示,用于建立用户和项目之间的关系,以找到用户的相关项目。因此,目前的协同过滤算法面临着大数据集和评分矩阵稀疏的问题。

在各种协同过滤技术中,矩阵分解是最流行的一种,它将用户和项目投影到一个共享的潜在空间,用一个潜在特征向量来表示一个用户或一个项目。之后,用户对一个项目的交互被建模为他们潜在向量的内积。

Kiran Shivlingkar—Spotify 发现算法如何工作(https://blog . prototypr . io/How-Spotify-Discovery-Algorithm-Works-fae8f 63466 ab)

尽管矩阵分解对于协同过滤是有效的,但是众所周知,它的性能会受到交互作用函数的简单选择的阻碍:内积。例如,对于对显式反馈的评级预测的任务,众所周知,矩阵分解模型的性能可以通过将用户和项目偏好项合并到交互函数中来提高。虽然对于内积运算符来说,这似乎只是一个微不足道的调整,但它指出了设计一个更好的、专用的交互函数来建模用户和项目之间的潜在功能交互的积极效果。简单地线性组合潜在特征的乘积的内积可能不足以捕获用户交互数据的复杂结构。

在这篇文章和接下来的文章中,我将介绍推荐系统的创建和训练,因为我目前正在做这个主题的硕士论文。

  • 第 1 部分提供了推荐系统的高级概述,它们是如何构建的,以及它们如何用于改善各行业的业务。
  • 第 2 部分提供了关于这些模型的优势和应用场景的正在进行的研究计划的仔细回顾。
  • 第 3 部分提供了几个可能与推荐系统学者社区相关的研究方向。
  • 第 4 部分提供了可以构建的矩阵分解的 7 种变体的本质数学细节:从使用巧妙的侧面特征到应用贝叶斯方法。

阿汉·莫汉提— MLP 真实世界银行数据模型(https://becoming human . ai/multi-layer-perceptron-MLP-Models-on-Real-World-Banking-Data-f6dd 3d 7 e 998 f)

在第 5 部分中,我探索了使用多层感知器进行协同过滤。多层感知器是一种前馈神经网络,在输入层和输出层之间有多个隐藏层。它可以解释为非线性变换的堆叠层,用于学习等级要素制图表达。这是一个简洁但实用的网络,可以将任何可测量的函数逼近到任何期望的精确度(这种现象被称为通用逼近定理)。因此,它是许多高级方法的基础,并被广泛应用于许多领域。

更具体地说,我将浏览 5 篇将多层感知器整合到推荐框架中的论文。

1 —广泛而深入的学习

记忆和归纳对于推荐系统都是至关重要的。谷歌的论文“推荐系统的广泛和深度学习”(2016)提出了一个结合广泛线性模型和深度神经网络的优势的框架,以解决这两个问题。该框架已经在大规模商业应用商店 Google Play 的推荐系统上进行了生产和评估。

如下图所示,宽学习组件是一个单层感知器,可以使用叉积特征变换有效记忆稀疏特征交互。深度学习组件是一个多层感知器,可以通过低维嵌入归纳到以前看不到的特征交互。

Google Inc .—&深度学习推荐系统(https://arxiv.org/pdf/1606.07792.pdf)

从数学上来说,广泛学习被定义为:

其中 y 是预测值,x 是特征向量,W 是模型参数向量,b 是偏差。特征集包括原始输入和转换输入(通过叉积转换来获取特征之间的相关性)。

在深度学习组件中,每个隐藏层执行以下计算:

其中 l 是层数,f 是激活函数,a_l 是激活向量,b_l 是偏差向量,W_l 是第 l 层的模型权重向量。

通过融合这些模型来获得广泛和深度的学习模型:

其中 Y 是二进制类标签,W_{wide}是所有宽模型权重的向量,W_{deep}是应用于最终激活 a_{last}的权重的向量,b 是偏差项。

让我们看看这在代码中是什么样子的:

这种方法的完整 PyTorch 实现可以在这里查看:https://github . com/khanhnamle 1994/transfer-rec/tree/master/multi layer-Perceptron-Experiments/Wide-and-Deep-py torch。

2-深度因子分解机器

作为宽深度学习方法的扩展,由 Huifeng Guo 等人提出的“ DeepFM:一个基于因子分解机的神经网络用于 CTR 预测”(2017)是一个端到端的模型,无缝集成了因子分解机(宽组件)和多层感知器(深度组件)。与宽和深模型相比,DeepFM 不需要繁琐的特征工程。

如下图所示,因式分解机器利用加法和内积运算来捕获特征之间的线性和成对交互。多层感知器利用非线性激活和深层结构来模拟高阶交互。

郭慧峰等——DeepFM:一种基于因子分解机器的 CTR 预测神经网络())

从数学上来说,DeepFM 的输入是一个 m-fields 数据,由(u,I)对组成,它们是用户和项目的身份和特征,以及一个表示用户点击行为的二进制标签 y(y = 1 表示用户点击了项目,否则 y = 0)。这里的任务是建立一个预测模型,以估计用户在给定的上下文中点击特定应用程序的概率。

对于任何特定的特征 I,标量 w_i 用于衡量其一阶重要性,潜在向量 V_i 用于衡量其与其他特征的相互作用的影响。将 V_i 馈入宽分量以模拟二阶特征相互作用,馈入深分量以模拟高阶特征相互作用。包括 w_i、V_i 和网络参数在内的所有参数被联合训练用于组合预测模型:

其中 y_hat 是预测的 CTR(在 0 和 1 之间),y_{FM}是宽因式分解机组件的输出,y_{DNN}是多层感知器组件的输出。

在宽分量中,除了特征之间的线性(一阶)交互之外,因子分解机器将成对(二阶)特征交互建模为各个特征潜在向量的内积。当数据集稀疏时,这有助于非常有效地捕捉二阶特征交互。因式分解机的输出是一个加法单元和几个内积单元的和:

对于给定的特征 I 和 j,加法单位(第一项)反映一阶特征的重要性,内积单位(第二项)表示二阶特征相互作用的影响。

在深层组件中,多层感知器的输出如下所示:

其中|H|是隐藏层的数量,a 是嵌入层的向量输出,W 是模型权重的向量,b 是偏差单元的向量。

让我们看看这在代码中是什么样子的:

这种方法的完整 PyTorch 实现可以在这里查看:https://github . com/khanhnamle 1994/transfer-rec/tree/master/multi layer-Perceptron-Experiments/DeepFM-py torch。

3-极端深度因式分解机器

作为深度因子分解机的扩展,简训廉等人的《 xDeepFM:结合显式和隐式特征交互的推荐系统》(2018)可以对显式和隐式特征交互进行联合建模。显式高阶特征交互通过压缩交互网络 k 学习,而隐式高阶特征违反通过多层感知器学习。该模型也不需要人工特征工程,并且将数据科学家从繁琐的特征搜索工作中解放出来。

压缩交互网络的设计考虑了以下因素:

  1. 交互应用于向量级,而不是位级。
  2. 高阶特征相互作用被明确地测量。
  3. 网络的复杂性不会随着相互作用的程度呈指数增长。

压缩交互网络的结构非常类似于递归神经网络,其中下一个隐藏层的输出依赖于最后一个隐藏层和附加输入。各层嵌入向量的结构保持现状;因此,相互作用应用于向量水平。

简训廉等——xDeepFM:结合显式和隐式特征交互的推荐系统())

  • 看上面的图 4a,中间张量 Z^{k+1}是沿着隐藏层 x^k 和原始特征矩阵 x⁰.的每个嵌入维度的外积计算每个隐藏层 x^k 的过程与计算机视觉中众所周知的卷积神经网络有很强的联系。在这里,Z^{k+1}可以被视为一种特殊类型的图像,而 W^{k,h}是一个过滤器。
  • 如图 4b 所示,作者沿着嵌入维度将过滤器滑过 Z^{k+1},得到了一个隐藏向量 x{k+1}——这在计算机视觉中通常被称为特征图。因此,xk 是 H_k 个不同特征地图的集合。
  • 图 4c 提供了压缩交互网络架构的概述。设 T 表示网络的深度。X^k 的每个隐藏层都与输出单元有联系。作者在隐藏层的每个特征图上应用和池,并为第 k 个隐藏层获得长度为 H_k 的池向量 p^k。隐藏层的所有池向量在连接到输出单元之前被连接:p+ = [p,p,…,p^T]

xDeepFM 通过广度和深度学习框架将上述压缩的交互网络与简单的多层感知器相结合。一方面,该模型既包括低阶特征交互,也包括高阶特征交互;另一方面,它还包含隐式和显式的特征交互。这里显示了架构。

简训廉等 xDeepFM:结合显式和隐式特征交互的推荐系统()

从数学上来说,产生的输出单位是:

其中 a 是原始特征的向量,x_{mlp}是普通多层感知器的输出向量,p+是交叉交互网络的输出向量。w 和 b 是可学习的参数,分别是权重和偏差。

让我们看看这在代码中是什么样子的:

这种方法的完整 PyTorch 实现可以在这里查看:https://github . com/khanhnamle 1994/transfer-rec/tree/master/multi layer-Perceptron-Experiments/xDeepFM-py torch

4-神经分解机器

另一个无缝集成因子分解机器和多层感知机的并行工作是 Xiangnan He 和 Tat-Seng Chua 的“用于稀疏预测分析的神经因子分解机器”(2017)。该模型将线性因式分解机器的有效性与非线性神经网络的强大表示能力结合起来,用于稀疏预测分析。

如下所示,其架构的关键是一种称为双线性交互池的操作,它允许神经网络模型在较低级别学习更多信息的功能交互。通过在双线性交互层上堆叠非线性层,作者能够深化浅层线性因式分解机,有效地建模高阶和非线性特征交互,以提高因式分解机的表达能力。与简单连接或平均低层嵌入向量的传统深度学习方法相比,双线性交互池的这种使用编码了更多信息的特征交互,极大地促进了后续“深度”层学习有意义的信息。

【https://arxiv.org/pdf/1708.05027.pdf】

让我们深入研究神经分解机器模型的数学。给定稀疏向量 x 作为输入,模型估计目标为:

其中第一项模拟特征数据的全局偏差,第二项模拟特征权重的全局偏差,第三项 f(x)是模拟特征交互的多层感知器(如图 2 所示)。f(x)的设计由这些层组件组成:

嵌入层

这是一个完全连通的图层,将每个要素投影到密集矢量表示中。设 v_i 为第 I 个特征的嵌入向量。然后在嵌入步骤之后,作者获得一组嵌入向量来表示输入特征向量 x。

由于 x 的可能的稀疏表示,作者仅包括非零特征的嵌入向量,其中 x_i 不等于 0。

双线性相互作用层

然后,嵌入集 V_x 被馈送到双线性交互层,双线性交互层是将一组嵌入向量转换成一个向量的汇集操作:

其中 v_i.x_j 表示两个向量 v_i 和 x_j 的按元素的乘积,该汇集的输出是 k 维向量,其编码嵌入空间中特征之间的二阶交互。

隐藏层

双线性交互池层之上是一堆完全连接的层,这些层能够学习要素之间的高阶交互。这些隐藏层的定义是:

其中 L 是隐藏层数;W_L、b_L 和 activation_L 分别对应于第 L 层的权重矩阵、偏置向量和激活函数。激活函数的选择可以是 sigmoid、tanh 或 ReLU,以非线性地学习高阶特征交互。

预测层

最后,最后一个隐藏层 z_L 的输出向量被转换成最终预测分数:

其中 h^T 表示预测层的神经元权重。

让我们看看这在代码中是什么样子的:

这种方法的完整 PyTorch 实现可以在这里查看:https://github . com/khanhnamle 1994/transfer-rec/tree/master/multi layer-Perceptron-Experiments/Neural-FM-py torch

5 —神经协同过滤

向南和等人的论文“神经协同过滤”(2018)将多层感知器用于从数据中学习交互函数的应用又推进了一步。这里注意,他们也是上面提到的神经因子分解机器论文的同一作者。他们形式化了一种协作过滤的建模方法,这种方法专注于隐式反馈,它通过观看视频、购买产品和点击商品等行为间接反映用户的偏好。与评分和评论等显性反馈相比,隐性反馈可以被自动跟踪,因此对于内容提供商来说,收集隐性反馈要自然得多。然而,利用它更具挑战性,因为没有观察到用户满意度,并且存在负面反馈的固有稀缺性。

用于模拟用户隐式反馈的用户-项目交互值 y_ui 可以是 1 或 0。值 1 指示在用户 u 和项目 I 之间存在交互,但是这并不意味着 u 喜欢 I。这在从隐式数据中学习时提出了挑战,因为它仅提供关于用户偏好的噪声信号。虽然观察到的条目至少反映了用户对项目的兴趣,但未观察到的条目可能只是缺失的数据,并且负面反馈自然很少。

作者采用多层表示来建模用户-项目交互 y_ui,如下所示,其中一层的输出作为下一层的输入。

  • 底部的输入层由 2 个描述用户 u 和物品 I 的特征向量组成,可以定制以支持用户和物品的广泛建模。特别地,本文仅使用用户和物品的身份作为输入特征,通过一键编码将其转换为二值化的稀疏向量。有了这样一个输入的通用特征表示,通过使用内容特征来表示用户和项目,可以很容易地调整这个框架来解决冷启动问题。
  • 在输入层之上是嵌入层——一个将稀疏表示投影到密集向量的全连接层。在潜在因素模型的上下文中,所获得的用户/项目嵌入可以被视为用户/项目的潜在向量。
  • 用户嵌入和项目嵌入然后被馈送到多层神经架构(称为神经协同过滤层)以将潜在向量映射到预测分数。神经协同过滤层的每一层都可以被定制以发现用户-项目交互的特定潜在结构。最后一个隐藏层 X 的尺寸决定了模型的能力。
  • 最终的输出层为预测得分 y-hat_ui,通过最小化 y-hat_ui 与其目标值 y_ui 之间的逐点损失来进行训练。

【https://www.comp.nus.edu.sg/~xiangnan/papers/ncf.pdf】)

上述框架可以用下面的评分函数来概括:

其中 y-hat_ui 是交互 y_ui 的预测得分,θ表示模型参数。f 是将模型参数映射到预测得分的多层感知器。更具体地,P 是用户的潜在因素矩阵,Q 是项目的潜在因素矩阵,v_u^U 是与用户特征相关联的辅助信息,而 v_i^I 是与项目特征相关联的辅助信息。

本文认为,传统的矩阵分解可以看作是神经协同过滤的一个特例。因此,将矩阵分解的神经解释与多层感知器相结合以形成更通用的模型是方便的,该模型利用矩阵分解的线性和多层感知器的非线性来提高推荐质量。

让我们看看这在代码中是什么样子的:

这种方法的完整 PyTorch 实现可以在这里查看:https://github . com/khanhnamle 1994/transfer-rec/tree/master/multi layer-Perceptron-Experiments/Neural-CF-py torch-version 2。

模型评估

你可以查看我在这个知识库中构建的所有五个基于多层感知器的推荐模型:https://github . com/khanhnamle 1994/transfer-rec/tree/master/Multilayer-Perceptron-Experiments。

  • 数据集是 MovieLens 1M ,类似于我在上一篇文章中的矩阵分解实验。目标是预测用户对特定电影的评分——评分范围为 1 到 5。
  • 唯一的区别是,为了使用基于因式分解机器的模型来预测点击率,我使用了二进制评级。小于等于 3 的评级被视为 0,大于 3 的评级被视为 1。
  • 因此,考虑到这是一个二元分类问题(而不是像上次一样的 RMSE),评估度量是 AUC
  • 所有模型都经过 100 个时期的训练,结果在 权重和偏差 中捕获。对于那些不熟悉的人来说,这是一个出色的工具,它将所有模型超参数和输出指标存储在一个地方,以跟踪实验并毫不费力地再现结果。

结果表位于自述文件的底部,正如您从重量和偏差仪表盘可视化中看到的:

  • 广度和深度学习模型在测试和验证集上都具有最好的 AUC 结果。
  • 另一方面,极深因式分解机分别具有最低的 AUC。
  • 神经协同过滤运行速度最快,极深因式分解机运行速度最慢。

结论

在这篇文章中,我讨论了多层感知器的直观含义及其在协同过滤中的应用。我还浏览了使用 MLP 作为推荐框架的 5 篇不同的论文:(1)广泛和深度学习,(2)深度因子分解机,(3)极端深度因子分解机,(4)神经因子分解机,以及(5)神经协同过滤。这些模型补充了主流的浅层协同过滤模型,从而为基于深度学习的推荐开辟了一条新的研究途径。

请继续关注本系列未来的博文,它们超越了区分模型,进入了协同过滤的生成模型领域。

现在开始阅读 推荐系统系列第六部

参考

  • 针对推荐系统的宽深度学习。Cheng-Tze Cheng、Levent Koc、Jeremiah Harmsen、Tal Shaked、Tushar Chandra、Hrishi Aradhye、Glen Anderson、Greg Corrado、、Mustafa Ispir、Rohan Anil、Zakaria Haque、Hong、Jain、和 Hemal Shah。2016 年 6 月
  • DeepFM:基于因子分解机的神经网络,用于 CTR 预测 。郭慧峰,唐瑞明,叶云明,,何秀强。2017 年 3 月。
  • 神经协同过滤 何湘南,廖,汉王张,聂,,蔡达生。2017 年 8 月
  • 用于稀疏预测分析的神经分解机 。何湘南和蔡达生。2017 年 8 月
  • xDeepFM:结合显式和隐式特征交互的推荐系统 。连建勋、周小欢、张辅政、陈忠霞、谢星和。2018 年 5 月

如果你想关注我在推荐系统、深度学习和数据科学新闻方面的工作,你可以查看我的 中的 GitHub,以及在https://jameskle.com/的其他项目。你也可以在* 推特 直接发邮件给我 ,或者 在 LinkedIn 上找我 注册我的简讯 就在你的收件箱里接收我对机器学习研究和行业的最新想法吧!***

推荐系统系列第 7 部分:用于协同过滤的玻尔兹曼机器的 3 种变体

原文:https://towardsdatascience.com/recsys-series-part-7-the-3-variants-of-boltzmann-machines-for-collaborative-filtering-4c002af258f9?source=collection_archive---------28-----------------------

RecSys 系列

物理符合推荐

更新: 本文是我探索学术界和工业界推荐系统系列文章的一部分。查看完整系列: 第一部分 第二部分 第三部分第四部分第五部分第六部分

我去年读过的最好的人工智能相关书籍之一是特伦斯·塞伊诺夫斯基的《深度学习革命》这本书解释了深度学习是如何从一个模糊的学术领域变成信息时代一项有影响力的技术的。作者 Terry Sejnowski 是深度学习的先驱之一,他与 Geoffrey Hinton 一起创造了 Boltzmann machines :一个与大脑中的学习有着惊人相似之处的深度学习网络。

深度学习革命(【https://mitpress.mit.edu/books/deep-learning-revolution】)

我最近听了一个关于人工智能的播客,特伦斯讨论了机器做梦,玻尔兹曼机器的诞生,大脑的内部运作,以及在神经网络中重建它们的过程。特别是,他和 Geoff Hinton 用物理学启发的架构发明了玻尔兹曼机器:

  • 每个单元有一个概率产生一个随输入量变化的输出。
  • 他们给网络输入,然后跟踪网络内的活动模式。对于每个连接,他们跟踪输入和输出之间的相关性。然后,为了能够学习,他们摆脱输入,让网络自由运行,这被称为睡眠阶段
  • 学习算法很直观:他们从唤醒学习阶段减去睡眠阶段相关性,然后相应地调整权重。对于足够大的数据集,该算法可以有效地学习输入和输出之间的任意映射。

玻尔兹曼机器的类比被证明是一个很好的洞察睡眠期间人类大脑中发生了什么。在认知科学中,有一个概念叫做回放,海马体向皮层回放我们的记忆和经历,然后皮层将其整合到我们关于世界的语义知识库中。

这是一种啰嗦的方式来说,我对探索玻尔兹曼机器感兴趣有一段时间了。看到他们在推荐系统中的应用,我欣喜若狂!

在这篇文章和接下来的文章中,我将介绍推荐系统的创建和训练,因为我目前正在做这个主题的硕士论文。

  • 第 1 部分提供了推荐系统的高层次概述,它们是如何构建的,以及它们如何被用来改善各行各业的业务。
  • 第 2 部分对正在进行的关于这些模型的优势和应用场景的研究计划进行了有益的回顾。
  • 第 3 部分提供了几个可能与推荐系统学者社区相关的研究方向。
  • 第 4 部分提供了可以构建的矩阵分解的 7 种变体的本质数学细节:从使用巧妙的侧面特征到贝叶斯方法的应用。
  • 第 5 部分提供了基于多层感知器的协同过滤模型的 5 个变体的架构设计,这些模型是能够以非线性方式解释特征的判别模型。
  • 第 6 部分提供了基于协作过滤模型的自动编码器的六个变体的主类,这些模型是在学习底层特征表示方面更胜一筹的生成模型。

在第 7 部分中,我探索了使用波尔兹曼机器进行协同过滤。更具体地说,我将剖析三篇将玻尔兹曼机器纳入其推荐架构的原则性论文。但首先,让我们浏览一下玻尔兹曼机器及其变体的初级读本。

玻尔兹曼机及其变体入门

据其发明者:

“玻尔兹曼机器是一个由对称连接的神经元样单元组成的网络,可以随机决定是开还是关。玻尔兹曼机器有一个简单的学习算法,允许它们在由二进制向量组成的数据集中发现有趣的特征。在具有许多层特征检测器的网络中,学习算法非常慢,但是通过一次学习一层特征检测器,可以使学习算法快得多。”

为了进一步揭示这一点,Hinton 指出,我们可以使用 Boltzmann 机器来解决两种不同的计算问题:

  1. 搜索问题:玻尔兹曼机器在连接上具有固定的权重,其被用作优化过程的成本函数。
  2. 学习问题:给定一组二进制数据向量,我们的目标是找到连接上的权重,以优化训练过程。玻尔兹曼机器通过解决搜索问题的多次迭代来更新权重值。

受限玻尔兹曼机 (RBM)是玻尔兹曼机的一种特殊类型,有两层单元。如下图所示,第一层由可见单元组成,第二层包括隐藏单元。在这种受限的体系结构中,层中的单元之间没有连接。

马尼什·纳亚克——RBM 直观介绍(https://medium . com/datadriveninvestor/An-Intuitive-Introduction-of-restricted-Boltzmann-machine-RBM-14f 4382 A0 dbb)

模型中可见的单元对应于观察到的组件,隐藏的单元代表这些观察到的组件之间的依赖关系。目标是对可见和隐藏单元的联合概率建模: p(v,h) 。因为隐藏单元之间没有连接,所以学习是有效的,因为给定可见单元,所有隐藏单元都是有条件独立的。

一个深度信念网络 (DBN) 是一个多层学习架构,它使用一堆 RBM 来提取训练数据的深度分层表示。在这样的设计中,每个子网络的隐藏层充当即将到来的子网络的可见层。

himan Shu Singh-Deep Belief Networks:An Introduction(https://medium . com/analytics-army/Deep-Belief-Networks-An-Introduction-1d 52 bb 867 a 25)

当通过 DBN 学习时,首先通过将原始数据输入到可视单元中来训练底层的 RBM。然后,固定参数,并将 RBM 的隐藏单元用作第二层 RBM 的输入。学习过程继续进行,直到到达堆叠子网络的顶部,最后,获得合适的模型以从输入中提取特征。由于学习过程是无监督的,因此通常会在 DBN 的末尾添加一个新的监督学习网络,以用于分类或回归(上图中的逻辑回归图层)等监督学习任务。

好了,是时候回顾一下不同的基于波尔兹曼机器的推荐框架了!

1-用于协同过滤的受限玻尔兹曼机器

回想一下在经典的协同过滤设置中,我们试图用维度 n x d 对评级(用户-项目交互)矩阵 X 进行建模,其中 n 是用户数量,d 是项目数量。条目 xᵢⱼ (第 I 行,第 j 列)对应于用户 I 对项目 j 的评级。在 MovieLens 数据集中(在我之前的所有帖子中都使用过),xᵢⱼ ∈ 0,1,2,3,4,5(其中 0 代表缺失的评级)。

  • 例如,xᵢⱼ = 2 意味着用户 I 给电影 j 的评分是 2 分(满分 5 分)。另一方面,xᵢⱼ = 0 意味着用户没有评价电影 j
  • X 行编码每个用户对所有电影的偏好,X 列编码所有用户收到的每个项目的评级。

从形式上来说,我们将协同过滤上下文中的预测和推断定义如下:

  • 预测:给定观察评分 X,预测 x_{im}(用户 I 给新查询电影 m 的评分)。
  • 推论:计算概率 p(x_{im} = k | Xₒ)(其中 Xₒ表示 x 和 k ∈ 0,1,2,3,4,5 的非零项)。

RBM 架构中提出的 受限玻尔兹曼机用于协同过滤

Salakhutdinov、Mnih 和 Hinton 将计算 p(x_{im} = k | Xₒ)的任务框定为对具有训练参数的底层 RBM 的推断。数据集被细分为评级矩阵,其中用户的评级被一次性编码到矩阵 v 中,使得如果用户用评级 k 对电影 j 进行评级,则 vⱼᵏ = 1。上图说明了 RBM 图:

  • v 是一个 5×d 矩阵,对应于用户的独热编码整数等级。
  • h 是二进制隐变量的 F×1 向量,其中 F 是隐变量的个数。
  • w 是一个 d x F x 5 张量,它对评级和隐藏特征之间的邻接关系进行编码。它的入口 Wⱼcᵏ对应于电影 j 的等级 k 和隐藏特征 c 之间的边缘电势

整个用户-项目交互矩阵是 V (s)的集合,其中每个 V 对应每个用户的评分。因为每个用户可能有不同的缺失值,所以每个用户都有一个唯一的 RBM 图。在每个 RBM 图中,边连接评级和隐藏功能,但不会出现在缺失评级的项目之间。这篇论文把 W 看作是连接在所有这样的 RBM 图上的一组边势。

训练阶段,RBM 使用条件概率 p(vⱼᵏ = 1 | h)p(hₐ = 1 | V) 来表征评级和隐藏特征之间的关系:

等式 1

等式 2

得到这些概率后,还有两个额外的步骤来计算 p(vₒᵏ = 1 | V) :

  1. 基于观察到的评级 v 和每个 a)的边缘势 W (p(hₐ = 1 | V)计算 h 中每个隐藏特征的分布。
  2. 基于边缘电势 w 和 p(hₐ的分布计算 p(vₒᵏ = 1 | V。

优化阶段,通过 V — p(V) 的边际似然对 W 进行优化。使用对比散度计算梯度∇ Wᵢⱼᵏ,这是基于 Gibbs 抽样的梯度的近似值:

等式 3

期望值<.> _T 代表运行吉布斯采样器得到的样本分布,在数据处初始化,用于 T 个完整步骤。t 通常在学习开始时设置为 1,并随着学习的收敛而增加。当运行 Gibbs 采样器时,RBM 重构(如等式 1 所示)非缺失评级的分布。对比散度的近似梯度然后可以在所有 n 个用户上平均。

为了便于说明,下面给出了 RBM 模型类的 PyTorch 代码:

对于我的 PyTorch 实现,我设计了 RBM 架构,它有一个由非线性 sigmoid 函数激活的 100 个单元的隐藏层。其他超参数包括批次大小 512 和时期 50。

2 —用于协同过滤的可解释的受限玻尔兹曼机器

对建议的解释可以有多种好处,包括有效性(帮助用户做出正确的决定)、效率(帮助用户做出更快的决定)和透明度(揭示建议背后的推理)。在 RBM 的例子中,它将一组低维的特征分配给潜在空间中的项目,很难解释这些习得的特征。因此,一个巨大的挑战是为 RBM 选择一种预测精度适中的可解释技术。

Abdollahi 和 Nasraoui 为一个协同过滤推荐系统设计了一个 RBM 模型,该系统在保持准确性的同时建议可以解释的项目。该论文的范围仅限于在解释中不使用额外数据源的建议,以及仅由活动用户的邻居从对这些项目给出的评级中可以生成对推荐项目的解释。

推荐项目的基于用户的邻居风格解释的例子,如在 可解释的 RBM 用于 CF 中提出的

主要思想是,如果许多邻居已经对推荐的项目进行了评级,那么这可以使用邻居风格的解释机制来提供解释推荐的基础。对于基于用户的邻居风格的解释,如上图所示,用户 u 的项目 I 的可解释性得分被定义为:

等式 4

这里 N_k (u) 是用户 u 的 k 个邻居的集合, r_{x,i} 是 x 对项目 I 的评分, R_max 是 N_k (u)对 I 的最大评分值,余弦相似度定义邻域。在没有信息损失的情况下,对于缺失评分,r_{x,i}为 0,表明用户 x 对于用户 u 对项目 I 的基于用户的邻居式解释没有贡献,因此,可解释性得分在 0 和 1 之间。只有当项目 I 的可解释性得分大于 0 时,项目 I 对于用户 u 才是可解释的。当无法解释时,可解释率为 0。

为了便于说明,下面给出了 RBM 模型等级的张量流代码:

对于我的 TensorFlow 实现,我设计了 RBM 架构,它有一个由非线性 sigmoid 函数激活的 100 个单元的隐藏层。其他超参数包括批次大小 512 和时期 50。我还给一个假设用户展示了一个示例推荐列表,其中包括可解释性得分。

3 —用于协同过滤的神经自回归分布估计器

RBM 模型的一个问题是它遭受不准确和不切实际的长训练时间,因为:(1)训练是难以处理的,和(2)需要变分近似或马尔可夫链蒙特卡罗。 Uria,Cote,Gregor,Murray,Larochelle 提出了所谓的神经自回归分布估计量 (NADE),这是一种对高维二元向量的易处理的分布估计量。估计器计算每个元素的条件概率,给定二进制向量中其左侧的其他元素,其中所有条件共享相同的参数。二元向量的概率可以通过这些条件的乘积得到。通过反向传播可以有效地优化 NADE,而不是像 RBM 那样需要昂贵的推理来处理潜在变量。

如下图 NADE 所示:

  • 在输入图层中,值为 0 的单位显示为黑色,值为 1 的单位显示为白色。虚线边框表示层预激活。
  • 输出 x^_0 给出了向量 x_0 的每个维度的预测概率,以某种顺序给出了前面的元素。
  • 在输出和被预测的值之间,或者在排序中的 x_0 的后面的元素之间,没有连接的路径。
  • 连接的箭头对应于具有共享参数的连接。

一个 NADE 模型的示意图,如图 神经自回归分布估计

郑、唐、丁、周提出 CF-NADE ,其灵感来源于-CF 和模型,对用户评分分布进行建模。假设我们有四部电影:m1(评分为 5)、m2(评分为 3)、m3(评分为 4)和 m4(评分为 2)。更具体地说,过程如下:

  1. 无条件下用户给 m1 五星的概率。
  2. 在给 m1 5 星的条件下,用户给 m2 3 星的概率。
  3. 用户给 m3 4 星的概率,条件是给 m1 5 星,给 m2 3 星。
  4. 用户给予 m4 2 星的概率,条件是给予 m1 5 星、m2 3 星和 m3 4 星。

从数学上讲,CF-NADE 通过链式法则将评级向量 r 的联合概率建模为:

等式 5

  • d 是用户已经评级的项目的数量。
  • o 是(1,2,…,D)排列中的 D 元组。
  • mᵢ ∈ {1,2,…,M}是第 I 个评级项的指标。
  • rᵘ = (rᵘ_{m_{o₁}},rᵘ_{m_{o₂}},…,rᵘ_{m_{oD}})表示用户 u 的训练案例
  • rᵘ_{m_{oᵢ}} ∈ {1,2,…,K}表示用户对项目 m_{oᵢ}.的评价
  • rᵘ_{m_{o

To expand on the process of getting the conditionals in equation 5, CF-NADE first computes the hidden representation of dimension H given rᵘ_{m_{o

Equation 6

  • g is the activation function.
  • Wᵏ is the connection matrix associated with rating k.
  • Wᵏ_{:,j} is the j-th column of Wᵏ and Wᵏ_{i,j} is an interaction parameter between the i-th hidden unit and item j with rating k.
  • c is the bias term.

Using this hidden representation from equation 6, CF-NADE then computes sᵏ_{m_{oᵢ}} (r_{m_{o_{

Equation 7

Vʲ and bʲ are the connection matrix and the bias term associated with rating k, respectively, where k is bigger than or equal to j. Using this score from equation 7, the conditionals in equation 5 could be modeled as:

Equation 8

CF-NADE is optimized via minimization of the negative log-likelihood of p(r) in equation 5:

Equation 9

Ideally, the order of movies (represented by notation o) should follow the timestamps of ratings. However, the paper shows that random drawing can yield good performance.

The Keras code of the CF-NADE model class is given below for illustration purpose:

For 我的 Keras 实现,我设计了一个包含 100 个单元的隐藏层,通过 Adam 优化,学习率为 0.001。其他超参数包括批次大小 512 和时期 50。

模型评估

您可以查看我在这个资源库中构建的所有三个基于波尔兹曼机器的推荐模型:https://github . com/khanhnamle 1994/transfer-rec/tree/master/Boltzmann-Machines-Experiments。

  • 数据集是 MovieLens 1M ,类似于我之前用矩阵分解、多层感知器和自动编码器做的三个实验。目标是预测用户对一部电影的评价,其中评价在 1 到 5 之间。
  • 在该设置中,评估度量是均方根误差(RMSE)* 。换句话说,我希望最小化预测评级和实际评级之间的差值。***

  • 结果表在我回购的自述底部:可解释的 RBM 模型 RMSE 最低,训练时间最短,NADE 模型 RMSE 最高,训练时间最长。

结论

在这篇文章中,我讨论了玻尔兹曼机器的基本原理及其在协同过滤中的应用。我还浏览了 3 篇不同的论文,这些论文使用了受波尔兹曼机器启发的架构作为推荐框架:(1)受限波尔兹曼机器,(2)可解释的受限波尔兹曼机器,以及(3)神经自回归分布估计器。

还有几篇值得一提的论文,我还没来得及细说:

  • 乔尔杰夫和纳科夫使用 RBMs 联合建模:(1)用户投票项目之间的相关性和(2)对特定项目投票的用户之间的相关性,以提高推荐系统的准确性。
  • 胡等在基于群体的推荐系统中使用,通过联合建模集体特征和群体简档来建模群体偏好。
  • Truyen 等人使用 Boltzmann 机器来提取两者:(1)评级项目与其评级之间的关系(由于隐藏层和 softmax 层之间的连接)以及(2)评级项目之间的相关性(由于 softmax 层单元之间的连接)。
  • Gunawardana 和 Meek 不仅使用 Boltzmann 机器来建模用户和项目之间的相关性,还用于整合内容信息。更具体地说,模型参数与内容信息联系在一起。

请继续关注本系列的下一篇博文,它将探讨推荐系统环境中的各种评估指标。

参考

  • 受限玻尔兹曼机协同过滤 。Ruslan Salakhutdinov,Andriy Mnih 和 Geoffrey Hinton。2007 年 6 月。
  • 可解释受限玻尔兹曼机进行协同过滤 贝努什·阿多拉希和奥尔法·纳斯拉维。2016 年 6 月。
  • 一种神经自回归的协同过滤方法 。、唐、丁、周汉宁。2016 年 5 月。

如果你想关注我在推荐系统、深度学习和数据科学新闻方面的工作,你可以查看我的 中的 GitHub,以及在【https://jameskle.com/】的其他项目。你也可以在* 推特 直接发邮件给我 ,或者 在 LinkedIn 上找我 注册我的简讯 就在你的收件箱里接收我关于研究和生产中的机器学习的最新想法吧!***

递归集成学习

原文:https://towardsdatascience.com/recurrent-ensemble-learning-caffdcd94092?source=collection_archive---------46-----------------------

冥想计划

用竞争神经网络提高文本生成质量

塞内卡图像来自 Jean-Pol GRANDMONT 制作的17 世纪匿名雕塑家制作的塞内卡半身像,由 3.0 授权于 CC。背景图片来自银河全景图由 ESO 提供,由 4.0 授权 CC。

我一直在设计几个斯多葛派哲学家——都是用 TensorFlow 构建的。他们中的一些人创造了辉煌的文本,但随后会陷入疯狂的状态(不是一件非常坚忍的事情)并说出类似(!EPLYZzzFxZFKzPZjQYCVS(!C!HZwEL(]SzKz]FXXKHzzzPP[(的话。

其他哲学家会写出可读的文本,但不是特别有趣。但是他们会更加稳定。

这两个问题的解决方案——让这些现在的角斗士哲学家进行生死决斗。场地?体育馆里欢呼的人群已经被没有灵魂的短语排名算法所取代。

因此,在开始之前,我们将介绍:

  • 使用几个竞争的 RNN 模型(我们的哲学角斗士****
  • 评定模型输出(体育馆和****
  • 将这些放在一起产生一些神奇的东西(一个冠军角斗士的哲学名言——或者实际上,我们的几个角斗士)

莫拉莱斯书信

我们的角斗士将学习马可·奥勒留的冥想和鲁契留的书信。我们混合使用了requestsBeautifulSoup库来获取它们。

为了你的兴趣,我不会描述这个过程。但是你可以在这里找到code/data.py中的代码。

全体

使用一个名为gladiator_predict的简单函数来控制模型的集合。

模型名称列表被传递给这个函数——它加载模型,然后遍历每个模型——用generate生成文本,用rate对文本进行评级

然后,我们根据分数对这些输出进行排序,并将获胜的序列传递回generate,就像这样:

完整代码见此处。

当我们生成更多文本时,能够选择最佳序列对我们的输出有巨大的影响。

在之前,模型会产生合理的文本,但经常会陷入无意义的胡言乱语——然后回到雄辩的“斯多葛派的冥想

****现在,一旦一个模特陷入这种胡言乱语的状态,她就输了👎

然后,我们的模型将继续丢失,直到它再次生成英文文本👍****

竞技场

决定哪个哲学家角斗士产生了最好的输出的关键是rate函数。

rate给出一个角斗士的冥想,并根据几个因素进行评分:

  • 冥想是否以正确的标点符号结束?

✔ ️ "this whole world is my country."

"Thy knows what **Z**"

  • 冥想包含多少重复

✔ ️ "About what am I now employing my own soul?"

"But **I know** how many **I know** and **I know**."

  • 这些词存在于词汇中吗?

✔ ️ "Do not act as if thou wert going to live ten thousand years."

"**Turramoly**? When **hishich** is deity, from there is places the **smater**."

综上所述,我们可以根据这个分数生成输出:

谁赢了?

gladiator_predict中的vis参数允许我们可视化我们的角斗士表演:

我们可以看到这是一场戏剧性的战斗。但最终,角斗士哲学家 LSTM_e512_sl250_0414 产生了最好和最一致的哲学。

使用一组模型的优势在这张图片中是显而易见的。 e128 产生了一些得分最高的输出。但是在迭代 3647 时也产生了一些可怕的输出。

****如果没有合奏来支持 e128 ,迭代 3647 中所说的任何胡言乱语都将进入最终输出。

幸运的是,我们有几个更好的选择。

在这次演出中,我们的合奏制作了这篇短文。

Do you ask any man with a book: here you ask these fellows, who indeed make thy thing greater. That which you declared if you consider any man a friend whom you are to distinguish between investigation to every man accordingly.That even in the scholar's abyss in study, and the senses may need desired, but the world walls he should not *abroughly* handle soil, which turn to the fact where the good seeks a fame of living things, and likewise to disease to meet us to other also, that we can come *alood* of it again in all respects, but not boast of his own strength; but what kind out my lot has been broken, it *goan* us generations, and was reached when one fights away upon a period of labour! This is the words of Socrates.

感谢阅读!

如果你对这个项目感兴趣,你可以在这里找到回购协议。我还写了关于初始构建的内容,您可以在这里阅读:

** [## 斯多葛派哲学——由算法构建

再现历史上最有权势的人之一所写的斯多葛派哲学

towardsdatascience.com](/stoic-philosophy-built-by-algorithms-9cff7b91dcbd)**

递归神经网络

原文:https://towardsdatascience.com/recurrent-neural-networks-56e1ad215339?source=collection_archive---------18-----------------------

理解 RNN 背后的直觉!

按作者分列的数字

介绍

本文的目标是深入探讨递归神经网络,这是一种具有不同于前几篇文章(链接)中所见的架构的神经网络。

具体而言,文章分为以下几个部分:

  • 什么是 rnn
  • 长短期记忆(LSTM)网络
  • 时间序列的 RNNs 实现

什么是 rnn?

正如我们在这里看到的,CNN 没有任何记忆,rnn 每次都可以超越“从头开始思考”的限制,因为它们有某种记忆。

让我们用一个非常直观的例子来看看它们是如何工作的:

例子

假设我们住在公寓里,有一个完美的室友,他会根据天气做不同的饭菜,晴天还是雨天。

按作者分列的数字

所以,如果我们用向量来编码这些食物:

按作者分列的数字

我们的神经网络会做以下事情:

按作者分列的数字

如果我们回想一下,神经网络学习一些可以用矩阵表示的权重,这些权重用于进行预测。我们的将如下:

如果是晴天:

按作者分列的数字

如果是雨天:

按作者分列的数字

如果我们看一下我们的权重矩阵,这次是一个图表:

按作者分列的数字

现在让我们看看在这个例子之后添加了什么 rnn:

递归神经网络

比方说,现在我们亲爱的室友不仅根据天气来决定做什么,而且现在只看他昨天做了什么。

负责根据室友今天做的菜来预测她明天会做什么菜的网络是一个递归神经网络(RNN)。

这个 RNN 可以表示为下面的矩阵:

按作者分列的数字

所以我们有一个:

按作者分列的数字

让我们把它变得稍微复杂一点

现在想象一下,你的室友根据她昨天做的菜和天气决定做什么菜。

  • 如果天气晴朗,她会手里拿着一瓶上好的啤酒在阳台上呆一天,所以她不做饭,所以我们吃和昨天一样的东西。但是
  • 如果下雨,她就呆在家里做饭。

大概是这样的:

按作者分列的数字

因此,我们最终有了一个模型,它根据我们昨天吃的东西告诉我们将要吃什么,而另一个模型告诉我们我们的室友是否会做饭。

按作者分列的数字

添加和合并操作如下:

按作者分列的数字

按作者分列的数字

这里你可以看到图表:

按作者分列的数字

这就是它的工作原理!

这个例子来自一个很棒的视频,我建议你根据需要多次查看,深入理解前面的解释。你可以在这里找到视频:https://www.youtube.com/watch?v=UNmqTiOnRfg

rnn 是用来做什么的?

有几种类型:

按作者分列的数字

他们非常擅长做出预测,尤其是当我们的数据是连续的时候:

股市预测

一只股票的价值很大程度上取决于它以前的价值

序列生成
只要数据是序列,数据在一个瞬间 t 取决于数据在瞬间 t-1。

文本生成

比如你手机提示单词的时候。它看着你写的最后一个单词,看着你正在写的字母,暗示下一个字母甚至单词。

语音识别

在这种情况下,我们可以识别出前一个单词,并在那一刻接收到音频。

长短期记忆网络

现在让我们研究一下最流行的 RNN 是如何工作的。它们是 LSTM 网络,其结构如下:

按作者分列的数字

但是首先:为什么他们是最受欢迎的?

原来常规的 rnn 都有内存问题。专门设计的记忆网络无法进行长期记忆。为什么这是一个问题?

好吧,回到我们室友的问题,对于这个例子,我们只需要知道我们昨天吃了什么,所以什么都不会发生。

按作者分列的数字

但是想象一下,如果不是三道菜的菜单,而是 60 道菜。

按作者分列的数字

传统的 rnn 无法记住很久以前发生的事情。然而,LSTM 会!

为什么呢?

让我们来看看 RNN 和 LSTM 的建筑:

RNN

按作者分列的数字

LSTM

按作者分列的数字

事实证明,rnn 只有一层,而 LSTMs 有多层的组合,它们以一种非常特殊的方式相互作用。

让我们试着理解这一点,但首先,让我解释一下术语:

按作者分列的数字

在上图中:

  • 向量沿着每条线传播,从一个节点的输出到其他节点的输入。
  • 粉色圆圈表示元素到元素的运算,例如向量和,而黄色方框是通过训练学习的神经层。
  • 连接的线表示连接,分隔的线表示相同的行内容到达两个不同的目的地。

LSTMs 的核心思想

关键是单元的状态,它在图中表示为穿过顶部的线:

按作者分列的数字

细胞的状态就像一种传送带,它沿着网络的整个结构行进,很少交互作用(并且它们是线性的):这意味着信息只是简单地流动而没有被修改。

巧妙之处在于,LSTM 的各层可以(或不可以)向这条传送带提供信息,而这个决定是由“门”做出的:

按作者分列的数字

这些门只不过是一种小心调节到达传送带的信息的方式。它们由具有 sigmoid 型激活和元素乘法的神经网络组成。

因此,sigmoid 层输出一个介于 0 和 1 之间的数字,这意味着让信息传递到传送带有多重要。0 表示我不在乎,1 表示非常重要。

如图所示,一台 LSTM 有 3 个这样的门,用于保护和控制传送带。

关于这个操作的具体细节,在这里有很大的解释:http://colah.github.io/posts/2015-08-Understanding-LSTMs/

而且这个博客也很有意思:【http://karpathy.github.io/2015/05/21/rnn-effectiveness/】T2

考虑到这一点,让我们看看循环网络可以做什么!

LSTM 实施

LSTM 图像分类

我们将遵循一个可以在此找到的示例:

https://medium . com/the-artificial-impostor/notes-understanding-tensor flow-part-2-f 7 e 5 ECE 849 f 5

from keras.models import Sequential
from keras.layers import LSTM, Dense
from keras.datasets import mnist
from keras.utils import np_utils
from keras import initializers

**# Hyper parameters**
batch_size = 128
nb_epoch = 10**# Parameters for MNIST dataset**
img_rows, img_cols = 28, 28
nb_classes = 10**# Parameters for LSTM network**
nb_lstm_outputs = 30
nb_time_steps = img_rows
dim_input_vector = img_cols**# Load MNIST dataset**
(X_train, y_train), (X_test, y_test) = mnist.load_data()
print('X_train original shape:', X_train.shape)
input_shape = (nb_time_steps, dim_input_vector)X_train = X_train.astype('float32') / 255.
X_test = X_test.astype('float32') / 255.Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')

**# LSTM Building**
model = Sequential()
model.add(LSTM(nb_lstm_outputs, input_shape=input_shape))
model.add(Dense(nb_classes, activation='softmax'))
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()

**# Training the model**
history = model.fit(X_train, 
                    Y_train, 
                    nb_epoch=nb_epoch, 
                    batch_size=batch_size, 
                    shuffle=True,
                    validation_data=(X_test, Y_test),
                    verbose=1)

**# Evaluation**
evaluation = model.evaluate(X_test, Y_test, batch_size=batch_size, verbose=1)
print('Summary: Loss over the test dataset: %.2f, Accuracy: %.2f' % (evaluation[0], evaluation[1]))

用 LSTM 进行时间序列预测

# LSTM for international airline passengers problem with regression framing
# [https://machinelearningmastery.com/time-series-prediction-lstm-recurrent-neural-networks-python-keras/](https://machinelearningmastery.com/time-series-prediction-lstm-recurrent-neural-networks-python-keras/)
!wget [https://raw.githubusercontent.com/lazyprogrammer/machine_learning_examples/master/airline/international-airline-passengers.csv](https://raw.githubusercontent.com/lazyprogrammer/machine_learning_examples/master/airline/international-airline-passengers.csv)import numpy
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error**# convert an array of values into a dataset matrix**
def create_dataset(dataset, look_back=1):
 dataX, dataY = [], []
 for i in range(len(dataset)-look_back-1):
  a = dataset[i:(i+look_back), 0]
  dataX.append(a)
  dataY.append(dataset[i + look_back, 0])
 return numpy.array(dataX), numpy.array(dataY)**# fix random seed for reproducibility**
numpy.random.seed(7)**# load the dataset**
dataframe = read_csv('international-airline-passengers.csv', usecols=[1], engine='python', skipfooter=3)
dataset = dataframe.values
dataset = dataset.astype('float32')**# normalize the dataset**
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)**# split into train and test sets**
train_size = int(len(dataset) * 0.67)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]**# reshape into X=t and Y=t+1**
look_back = 1
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)**# reshape input to be [samples, time steps, features]**
trainX = numpy.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
testX = numpy.reshape(testX, (testX.shape[0], 1, testX.shape[1]))**# create and fit the LSTM network**
model = Sequential()
model.add(LSTM(4, input_shape=(1, look_back)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, epochs=100, batch_size=1, verbose=2)**# make predictions**
trainPredict = model.predict(trainX)
testPredict = model.predict(testX)**# invert predictions**
trainPredict = scaler.inverse_transform(trainPredict)
trainY = scaler.inverse_transform([trainY])
testPredict = scaler.inverse_transform(testPredict)
testY = scaler.inverse_transform([testY])**# calculate root mean squared error**
trainScore = math.sqrt(mean_squared_error(trainY[0], trainPredict[:,0]))
print('Train Score: %.2f RMSE' % (trainScore))
testScore = math.sqrt(mean_squared_error(testY[0], testPredict[:,0]))
print('Test Score: %.2f RMSE' % (testScore))**# shift train predictions for plotting**
trainPredictPlot = numpy.empty_like(dataset)
trainPredictPlot[:, :] = numpy.nan
trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict**# shift test predictions for plotting**
testPredictPlot = numpy.empty_like(dataset)
testPredictPlot[:, :] = numpy.nan
testPredictPlot[len(trainPredict)+(look_back*2)+1:len(dataset)-1, :] = testPredict**# plot baseline and predictions**
plt.plot(scaler.inverse_transform(dataset))
plt.plot(trainPredictPlot)
plt.plot(testPredictPlot)
plt.show()

最后的话

一如既往,我希望你喜欢这篇文章,并且对 rnn 以及如何实现它们有了一个直觉!

如果你喜欢这篇文章,那么你可以看看我关于数据科学和机器学习的其他文章 这里

如果你想了解更多关于机器学习、数据科学和人工智能的知识 请关注我的媒体 ,敬请关注我的下一篇帖子!

递归神经网络

原文:https://towardsdatascience.com/recurrent-neural-networks-b7719b362c65?source=collection_archive---------31-----------------------

由 Sonja Langford 在 Unsplash 上拍摄的照片

了解是什么使 RNNs 在处理序列数据时高效

递归神经网络是非常著名的深度学习网络,应用于序列数据:时间序列预测、语音识别、情感分类、机器翻译、命名实体识别等..
对序列数据使用前馈神经网络提出了两个主要问题:

  • 在不同的例子中,输入和输出可以有不同的长度
  • MLPs 不共享跨数据样本的不同位置学习的特征

在本文中,我们将发现 RNNs 成功背后的数学原理,以及一些特殊类型的细胞,如 LSTMs 和 GRUs。最后,我们将深入研究结合注意力机制的编码器-解码器架构。

注意:因为 Medium 不支持 LaTeX,所以数学表达式是作为图像插入的。因此,为了更好的阅读体验,我建议你关闭黑暗模式。

目录

  1. 符号
  2. RNN 车型
  3. 不同类型的无线网络
  4. 高级细胞类型
  5. 编码器&解码器架构
  6. 注意机制

1.注释

作为示例,我们将考虑命名实体识别的任务,该任务包括定位和识别命名实体,例如专有名称:

我们表示:

当处理非数字数据时,例如文本,将它编码成数字向量是非常重要的:这个操作称为embedding。最著名的文本编码方式之一是由谷歌开发的 Bert。

2.RNN 模型

RNNs 代表神经网络的一种特殊情况,其中模型的参数以及所执行的操作在整个体系结构中是相同的。网络为序列中的每个元素执行相同的任务,该序列的output depends on the input and the previous state of the memory
下图显示了具有单层隐藏记忆的神经元的神经网络:

方程式

架构中的变量包括:

其中:

h(-1)被随机初始化, ϕψ 是非线性函数, UVW 是各种线性回归的parameters,在非线性激活之前。
需要注意的是,它们在整个架构中是相同的

应用程序

递归神经网络显著改进了序列模型,特别是:

  • NLP 任务、建模和文本生成
  • 翻译机
  • 声音识别

我们在下表中总结了上述应用:

学习算法

如同在经典神经网络中一样,在递归网络的情况下,通过优化关于 UVW 的成本函数来进行学习。换句话说,我们的目标是从真实值 yi 的输入 xi 开始,找到给出最佳预测 y^ i 的最佳参数。

为此,我们定义了一个名为loss function的目标函数,记为J,它量化了整个训练集的真实值和预测值之间的距离。

我们通过以下两个主要步骤来最小化 J:

  • **Forward Propagation**:我们通过网络整体或分批传播数据,并计算这批数据的损失函数,该损失函数只不过是不同行的预测输出中的误差之和。
  • **Backward Propagation Through Time**:包括计算成本函数相对于不同参数的梯度,然后应用下降算法对其进行更新。它被称为 BPTT,因为每个输出端的梯度既取决于同一时刻的元素,也取决于前一时刻的记忆状态。

我们多次重复相同的过程,称为epoch number。定义架构后,学习算法编写如下:

(∫)成本函数 L 计算单个点上实际值和预测值之间的距离。

正向传播

让我们考虑通过神经网络预测单个序列的输出。
在每个时刻 t ,我们计算:

直到到达序列的末尾。
同样,参数 UWV 在整个神经网络中保持相同
当处理一个 m 行的数据集时,对每一行分别重复这些操作是非常昂贵的。因此,我们截断数据集,以便在相同的时间线中描述序列,即:

我们可以使用线性代数将其并行化,如下所示:

穿越时间的反向传播

反向传播是学习的第二步,包括在预测(正向)阶段将injecting the error提交到网络中,并将其参数更新为perform better on the next iteration。因此,函数 J 的优化通常通过下降法进行。

我们现在可以应用一个下降方法,在我之前的文章中有详细描述。

记忆问题

我们对基于历史预测时间序列的演变感兴趣的领域有几个:音乐、金融、情感…等等。上面描述的内在循环网络被称为“香草”,具有记忆力差的缺点,在预测未来时不能考虑过去的几个因素。

考虑到这一点,RNNs 的各种扩展被设计来修整内部记忆:双向神经网络、LSTM 细胞、注意力机制等等。记忆放大在某些领域是至关重要的,比如在金融领域,人们试图记住尽可能多的历史,以便预测一个金融序列。

RNN 的学习阶段也可能遭受gradient vanishinggradient exploding问题,因为成本函数的梯度包括影响其记忆能力的 W 的幂。

3.不同类型的 rnn

经典或“普通”递归神经网络有多种扩展,这些扩展旨在增加网络的存储容量以及特征提取能力。
下图总结了不同的扩展:

还有其他类型的 rnn 有一个专门设计的隐藏层,我们将在下一章讨论。

4.高级类型的细胞

门控循环单元

GRU(门控循环单元)单元允许循环网络保存更多的历史信息,以便进行更好的预测。它引入了一个update gate,用于确定要从过去保留的信息量,以及一个reset gate,用于设置要忘记的信息量。下图示意了 GRU 细胞:

方程 我们将 GRU 单元中的方程定义如下:

ϕ 是非线性整数函数,参数 W 由模型学习。

长短期记忆

LSTMs(长短期记忆)也被引入来克服短记忆的问题,它们比普通的 RNNs 多 4 倍的记忆。这个模型使用了门的概念,有三个:

  • 输入门 i :控制输入信息的流动。
  • 遗忘门 f :控制前一存储状态的信息量。
  • 输出门 o:控制输出信息流

下图显示了 LSTM 电池的操作:

当输入和输出门关闭时,存储单元中的激活被阻止。

方程式 我们将 LSTM 单元中的方程式定义如下:

优点&缺点 我们可以把 LSTM 细胞的优点和缺点总结为四个要点:

  • 优点

+他们能够对长期序列依赖性进行建模。
+与“普通”rnn 相比,它们对短记忆问题更具鲁棒性,因为内部存储器的定义从:

  • 缺点

+与 RNN 相比,它们增加了计算复杂性,引入了更多要学习的参数。
+由于存在多个内存单元,所需内存高于“普通”rnn。

5.编码器和解码器架构

它是由两个主要部分组成的顺序模型:

  • Encoder:模型的第一部分处理序列,然后在最后返回整个序列的编码向量,称为context vector,其概括了不同输入的信息。
  • Decoder:上下文向量然后被作为解码器的输入,以便进行预测。

下图说明了该模型的架构:

编码器可以认为是一个降维工具,事实上,上下文向量 en 无非是对输入向量的编码( 0 中的 1 中的inn ),这些向量的大小之和远大于 en 的大小,因此有降维的概念。

6.注意机制

引入注意机制是为了解决记忆限制的问题,主要回答以下两个问题:

  • 编码器的每个输出 ej 赋予什么权重(重要性) αj
  • 我们如何克服编码器有限的内存,以便能够“记住”更多的编码过程?

该机制将其自身插入编码器和解码器之间,并帮助解码器显著选择对解码过程的每个步骤都很重要的编码输入 outi 如下:

数学形式主义

保持与之前相同的符号,我们将 αij 设置为由输出 i 给予向量 ej 的注意力,表示为 outi
注意力通过神经网络来计算,该神经网络将向量( e 0、 e 1、…、 en )和先前的记忆状态 h(i- 1)作为输入,它由下式给出:

应用:翻译机

注意机制的使用使得visualize and interpret模型内部正在做什么成为可能,特别是在预测的时候。
例如,通过绘制翻译系统注意力矩阵的“热图”,我们可以看到第一种语言中的单词,该模型将每个单词翻译成第二种语言:

如上所述,当将单词翻译成英语时,系统特别关注相应的法语单词。

LSTM 叠加与注意机制

结合这两种方法来改善内部记忆是相关的,因为第一种方法允许考虑更多的过去的元素,而第二种方法选择在预测时仔细关注它们。
注意机制的输出 ct 是 LSTM 细胞的新输入,因此方程组变成如下:

ϕ 是非线性整数函数,参数 w 由模型学习。

结论

RNNs 是处理序列数据的一个非常强大的工具,它们提供了令人难以置信的记忆能力,并广泛应用于日常生活中。它们也有许多扩展,能够解决各种类型的数据驱动问题,尤其是讨论时间序列的问题。

不要犹豫,检查我以前的文章处理:

  • 深度学习的数学
  • 卷积神经网络的数学
  • 物体检测&人脸识别算法

参考

  • Z.Lipton,J.Berkowitz,C.Elkan,对用于序列学习的递归神经网络的评论,arXiv:156.00019 v4,2015。
  • H.Salehinejad,S.Sankar,J.Barfett,E.Colak,S.Valaee,递归神经网络的最新进展,arXiv: 1801.01078v3,2018。
  • Y.Baveye,C.Chamaret,E . del andréA,L.Chen,情感视频内容分析:多学科洞察,HAL Id: hal-01489729,2017。
  • A.Azzouni,G.Pujolle,一种用于网络流量矩阵预测的长短期记忆递归神经网络框架,arXiv: 1705.05690v3,2017。
  • Y.g .希纳尔,H .米里萨伊,P .戈斯瓦米,E .高斯希尔,A .艾特-巴奇尔,V .斯特里约夫,利用 RNNs 进行时间序列预测:一种扩展的注意机制对周期进行建模并处理缺失值,arXiv: 1703.10089v1,2017。
  • K.徐,吴,王,冯,维特布洛克,谢宁,Graph2Seq: 基于注意的神经网络的图到序列学习,arXiv: 1804.00823v3,2018 .
  • Rose Yu,,Cyrus Shahabi,Ugur Demiryurek,深度学习:极端条件下交通预测的通用方法,南加州大学,2017 年。

原载于 2020 年 4 月 15 日 https://www.ismailmebsout.com

用于假人的递归神经网络

原文:https://towardsdatascience.com/recurrent-neural-networks-explained-ffb9f94c5e09?source=collection_archive---------19-----------------------

一个有趣的和有插图的指南来理解直觉。

这篇文章温和地介绍了循环单元,它们的内存是如何工作的,以及它们是如何被用来处理序列数据的,比如文本和时间序列。有没有把递归神经网络想象成时光机?

来源

我们为什么关心序列数据?

我们想要一个机器学习模型来理解序列,而不是孤立的
样本。这对于时间序列数据尤其重要,因为数据与时间的概念有着内在的联系。

序列也存在于自然语言中,句子是单词的序列。自然语言处理模型需要上下文信息来理解下面句子中的主语( he )和直接宾语( it )。在提供顺序信息后,模型将理解句子中的主语(乔的兄弟)和直接宾语(毛衣)。

页(page 的缩写)Protopapas,CS109b,哈佛 FAS

为什么神经网络会在序列数据上失败?

在我们之前的文章为什么深度学习有效中,我们展示了几个人工神经网络来预测农民在给定年份可能生产的收获量。这些模型不仅着眼于一年(如 2019 年),而且同时着眼于一系列年份(如 2017 年、2018 年、2019 年),从而提高预测能力。

如下图所示,给定三个连续值,模型将预测第四个值。第一个垂直列显示值的完整序列。下一列显示了预测结果的示例(蓝色)。

页(page 的缩写)Protopapas,CS109b,哈佛 FAS

这被称为重叠加窗数据集,因为我们对观测值加窗以创建新的。我们可以设想建立一个具有三层和 ReLU 激活函数的全连接神经网络,用于在给定三个连续数字时预测下一个数字。

页(page 的缩写)Protopapas,CS109b,哈佛 FAS

这种方法有几个问题。如果我们重新排列输入序列,网络将预测同样的结果。完全连接的网络不会区分顺序,因此会丢失一些信息。

页(page 的缩写)Protopapas,CS109b,哈佛 FAS

此外,完全连接的网络需要固定的输入和输出大小。如果我们决定查看 5 个连续数字来进行预测,我们将不得不建立另一个模型。

全连接网络的另一个缺点是,它不能对多个地方的输入进行分类。例如,当网络被设计为预测 3 个值时,我们不能同时预测接下来的 4 个值。

输入的顺序很重要。对于大多数顺序数据来说都是如此。

记忆游戏

在上一节中,我们提出了使用上下文、历史和未来来进行更好预测的想法。怎样才能让一个神经网络记住?

我们可能都经历过在 Pexeso 游戏中被孩子打败的经历,这是一个关于注意力和记忆力的游戏。

玩 Pexeso 时,目标是用尽可能少的走法找到所有相同的牌对。不知何故,孩子们非常擅长记忆。为什么我们不把这种同样的超人能力赋予人工神经网络中的一个神经元呢?

基本上,我们需要将神经元更新为一个新的计算单元,能够记住它以前看到的东西。我们将这称为单元的状态隐藏状态内存

页(page 的缩写)Protopapas,CS109b,哈佛 FAS

如何建立一个能记住过去的单位?内存或状态可以被写到一个文件中,但是更好的是,我们把它保存在单元内部,在一个数组中或者在一个向量中。当单元读取输入时,它也读取存储器的内容。利用这两种信息,它做出预测,更重要的是,它更新记忆。

我们也可以在 Pexeso 游戏中找到这个原则。一个孩子会打开一张卡片,试着回忆以前打开过的配对卡片的位置,然后决定下一张打开哪张卡片。打开那张卡片后,如果不匹配,孩子会通过记录他刚刚发现的那对卡片的位置来更新他的记忆。在下一轮游戏中,孩子将重复这个过程,如下图所示。

页(page 的缩写)Protopapas,CS109b,哈佛 FAS

循环单元

在数学中,当前值(事件或单词)对先前事件的依赖类型被称为递归,并使用递归方程来表示。

递归神经网络可以被认为是同一节点的多个副本,每个副本都向后继节点传递消息。表示上述递归关系的一种方法是使用下图。黑色的小方块表示所使用的状态是从以前的时间戳获得的,也就是以前的状态进入当前状态的循环。

页(page 的缩写)Protopapas,CS109b,哈佛 FAS

每个单元有三组权重:一组用于输入𝒙(𝑡,另一组用于前一时间步的输出𝒚(𝑡–1,另一组用于当前时间步的输出𝒚(𝑡).这些权重就像我们在正常的人工神经网络中处理的任何其他权重一样,最终它们将由训练过程来确定。

下面的示意图显示了将 3 个数字转换成 4 个数字的装置内部。输入是一个 3 个数字的向量。隐藏状态或记忆是一个 5 个数字的向量。该单元将使用 5 个神经元(A1-5)的内部网络将输入转化为 5 个数字的向量,将其与当前状态相结合,并通过激活函数传递结果。由此产生的 5 个数字的向量将通过另一个由 5 个神经元(B1–5)组成的内部网络来产生新的状态。它将同时通过另一个由 4 个神经元(C1-4)组成的网络,产生一个 4 个数字的输出向量。

页(page 的缩写)Protopapas,CS109b,哈佛 FAS

通过将当前输入与先前状态相结合,并通过激活函数来传递,网络将不仅仅记住先前的输入。国家永远是一个已经被网络看到的事物的更大画面。

在 Pexeso 游戏中,孩子们不是记录桌子上卡片的(x,y)坐标,而是模糊地记得哪些卡片彼此相邻,哪些靠近中心,哪些在棋盘的左边,哪些有更多的颜色,等等。

类似地,一个单元不会只记住一个句子的最后 2 或 3 个单词,而是会找到要记住多少个单词和哪些单词,尤其是这些单词的哪个表示,以便实现最佳预测。

这是一个非常简单的例子,说明了我们人类是如何选择记住一些事情(例如我们的妈妈纪念日)和忘记另一些事情(我们的老板纪念日)的。

穿越时间的反向传播

在我们之前的例子中,整个单元将在训练期间学习 5+5+4=14 个权重和 14 个偏差。我们如何找到这些重量?典型的梯度下降和反向传播在这里也适用吗?

现在来点难看的数学。首先,我们称 V 为应用于输入的权重, U 为应用于状态的权重, W 为应用于输出的权重。姑且称 h 为状态。我们有两个激活函数, g_h 作为隐藏状态的激活, 𝑔_y 作为输出的激活。

页(page 的缩写)Protopapas,CS109b,哈佛 FAS

递归单元由以下两个等式完美描述,其中 bb’分别表示输出神经元和状态神经元中的偏差。

为了通过应用随机梯度下降找到权重,正如我们在另一篇文章中所述,我们需要计算损失函数及其对权重的导数。

下面你可以看到这是如何为输出权重 W 完成的。整个网络的损耗是以循环单位表示的单个损耗的总和。

类似地,我们可以如下计算损失函数相对于状态权重 U 的导数。

还不算太糟。我们现在知道如何训练一个递归神经网络。但是有一个问题。

在上面突出显示的损失函数中,你可以看到一个巨大的数字乘积。已知产生的量变得非常大或非常小,导致爆炸或消失梯度

梯度可能会超过最小值,并撤消许多已经完成的工作。因此,通常的做法是将梯度裁剪在可接受的区间内,并选择不允许梯度过小的激活函数。

实际上,由于这个问题,rnn 不能学习长依赖关系,正如我们将在我们的对真实世界客户评论分类的实际实验中所展示的。如果你想用 Python 从零开始实现你自己的 RNN,查看 Victor Zhou 的这篇优秀文章。

递归神经网络如何处理序列数据?

现在,我们知道了单个循环单元是如何工作的。通过一个接一个地链接几个单元,我们能够处理一系列的输入。

下面,我们将说明递归神经网络如何获取一系列观察结果并预测是否会下雨。

在时间 t 时,网络出现“狗叫声”信息,其存储器为空。因此,预测有 0.3 的可能性会下雨。该网络在其存储器中存储“狗叫声”的表示,用于下一步。

在时间 t+1 ,它接收到新的信息‘白衬衫’,这将下雨的可能性降低到 0.1。现在记忆中有了“狗叫声”和“白衬衫”的代表。

接下来,在时间 t+2 ,网络接收“苹果派”作为信息。这不会改变它的预测,但是通过推出“白衬衫”来更新记忆。

在时间 t+3 时,输入“膝盖疼”将预测值增加到 0.6,并覆盖存储器中的“苹果派”。序列的最终输入是‘get dark’,将最终预测推至 0.9。

页(page 的缩写)Protopapas,CS109b,哈佛 FAS

这个例子直观地说明了当从输入序列中学习时,网络是如何有意识地在记忆中保持和忘记某些信息的。这是一个典型的多对一场景。

在下面描述的不同风格中也发现了递归神经网络。多对多体系结构通常用于将文本从一种语言翻译成另一种语言。

来源

结论

在本文中,我们展示了神经网络如何处理序列数据。如果您有兴趣了解如何实现递归神经网络,并对全连接神经网络或卷积神经网络进行基准测试,请通读我们下面的下一篇文章。包括实际操作的 Python 代码。

[## 情感分析:一个基准

递归神经网络解释。使用 FCNNs、CNN、RNNs 和嵌入对客户评论进行分类。

towardsdatascience.com](/sentiment-analysis-a-benchmark-903279cab44a)

感谢阅读。

电价预测的递归神经网络

原文:https://towardsdatascience.com/recurrent-neural-networks-for-electricity-price-prediction-a26f8411ea44?source=collection_archive---------29-----------------------

具有外生变量的时间序列分析

用于预测这些价格的最终模型可以找到( 此处 )

(ffull GitHub 库 )

什么是需求灵活性?

需求灵活性可以描述为电力终端用户(包括企业和家庭)根据市场信号(如随时间变化的电价)改变其电力消费模式的能力。

电价遵循每日、每周和季节性模式。上面我们可以看到日线模式。早上,每个人醒来,打开所有设备,价格上涨。随着人们去工作,需求和价格下降(太阳能发电开始上网)。下午 5 点左右,人们开始离开办公室,回家,打开电视,洗衣服等,价格再次上涨,直到就寝时间,价格下降。这个循环然后重复。

鉴于电价和碳排放的相关性(见我之前的博客),如果我们能把人们从高峰时间转移到非高峰时间,我们就能节省成本和碳排放。

没有多少公司向他们的客户提供提前一天的价格,但是 章鱼能源公司的灵活关税 正是这样做的。

然而,首先,对价格的准确预测将是有用的。

外变量

通常当进行特征工程时,我们需要确保我们的输入确实有助于(而不是阻碍)模型。幸运的是,神经网络非常善于辨别什么是有益的,什么是无益的,所以我们可以非常慷慨。

电力生产的投入可能对决定价格很有帮助。以下是 2013 年至 2019 年的数据图。

随着时间的推移,每个输入似乎都与电价有某种关联。

最重要的是,考虑到季节变化,包括温度数据是有帮助的。由于空调需求,夏季可能会有更高的价格。

所有这些数据必须来自不同的来源。我用 Nordpools 的提前一天市场来获取价格数据,用 DarkSky API 来获取温度数据,用 Investing.com 来获取商品数据。(这个都可以在这里找到。)

时间序列分析的整形

现在,经过一些清理,我有了一个完整的数据帧(这里)。

因为我正在执行时间序列分析,而我试图预测的变量也在预测中使用,所以我需要将数据重塑为监督学习问题。

data = df.valuesn_steps = 168series_reshaped =  np.array([data[i:i + (n_steps+24)].copy() **for** i **in** range(len(data) - (n_steps+24))])series_reshaped.shape(61134, 192, 6)

取数据帧的值(在对神经网络进行缩放之后),我定义它可以看到 168 个向后的时间步长(1 周),我希望它可以预测未来 24 小时。

它在数据框上创建了一个窗口,这样我就有了一个 192 行 X 6 列的矩阵。此窗口向下移动原始数据框“行我的行”,每小时创建一个新矩阵。如果 2013 年 1 月 1 日中午是第一个矩阵的第一行,那么下午 1 点将是第二个矩阵的第一行。

像这样增加维度将允许神经网络理解时间到来的顺序很重要。

既然数据是这种格式,我将它拆分,这样我们就有了 168 小时(1 周)的输入数据块,对于每 168 小时块,我们有 24 小时的价格输出,所以我们的模型可以“看到”接下来的 24 小时。这将数据转化为监督学习问题。

X_train = series_reshaped[:43800, :n_steps] 
X_valid = series_reshaped[43800:52560, :n_steps] 
X_test = series_reshaped[52560:, :n_steps] 
Y = np.empty((61134, n_steps, 24))  
**for** step_ahead **in** range(1, 24 + 1):     
   Y[..., step_ahead - 1] =   series_reshaped[..., step_ahead:step_ahead + n_steps, 0]

Y_train = Y[:43800] 
Y_valid = Y[43800:52560] 
Y_test = Y[52560:]

现在 X 训练数据是所有商品过去的 168 小时,而 Y 训练数据是未来 24 小时的价格。

训练模型

将数据格式化后输入神经网络,只需要尝试不同的格式。

在尝试了 LSTM 的、GRU 的卷积层以及经典的机器学习(回归树和 ARIMA 预测)之后,一个递归神经网络提供了最好的结果。

np.random.seed(42)
tf.random.set_seed(42)

model6 = keras.models.Sequential([
    keras.layers.SimpleRNN(20, return_sequences=**True**, input_shape=[**None**, 6]),
    keras.layers.SimpleRNN(20, return_sequences=**True**),
    keras.layers.TimeDistributed(keras.layers.Dense(24))
])

model6.compile(loss="mape", optimizer="adam")
history = model6.fit(X_train, Y_train, epochs=20,
                    validation_data=(X_valid, Y_valid))

这里有两个重要的事情需要了解,对于那些更喜欢技术方面的人来说,那就是 return_sequences=True,以及最终的时间分布层 24。第一个确保数据在网络中保持相同的多维(时间序列)格式,第二个是它以相同的结构每小时输出未来 24 小时的数据。

对于预测,我只关心最后的 24 小时,因为一个小时后,将有一个新的输入,这将产生下一个小时的预测。

在 2013 年至 2018 年对模型进行训练后,我用 2019 年来评估模型在看不见的数据上的工作情况。随机选择几天,这样你就能真正看到效果,这是相当准确的。

使用案例

鉴于该模型现在可以提前 24 小时预测电价,我们现在可以调整我们的用电量,使其远离那些高峰时段。这可能意味着设置我们的烘干机和电器在我们睡觉时运行,甚至投资智能插头来自动化我们的循环设备(如冰箱和空调)。

为了简单起见,我模拟了一个家用电池。它大致基于特斯拉 Powerwall 2,容量为 14KW,功率为 5 KW。为简单起见,这意味着它可以容纳近 3 个小时的电荷。它查看模型的 24 小时预测,并选择 3 个最便宜的充电时间和 3 个最贵的放电时间。

然而,你不太可能以这些日前价格将电力卖回给电网,我模拟的估值指标正是如此。在 2019 年的过程中,这种电池将花费 151.02 英镑用于充电,并从出售给电网中“赚取”280.23 英镑,从而获得 85.5%的投资回报率。考虑到这是一个相当初级的电池模型,这是一个不错的结果。

还不错,但是钱也不多。当我们开始考虑灵活需求的真正潜在规模时,真正有趣的场景出现了,事实是,有成千上万个巨大的 1MW +空调机组可以做到这一点,既减少了碳排放,又节省了大量成本。

递归神经网络—第一部分

原文:https://towardsdatascience.com/recurrent-neural-networks-part-1-498230290534?source=collection_archive---------57-----------------------

FAU 讲座笔记关于深度学习

埃尔曼细胞

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎大家来到深度学习的新一期。今天我们想研究顺序学习,特别是递归神经网络。到目前为止,我们只有简单的前馈网络,其中我们基本上有固定大小的输入,然后将生成分类结果,如“猫”、“狗”或“仓鼠”。

背景知识在许多分类问题中是相关的。 CC 下的图片来自深度学习讲座的 4.0 。

如果我们有像音频、语音、语言或视频这样的具有时间背景的序列,那么我们目前看到的技术并不是很适合。所以,我们现在感兴趣的是寻找适用于很长输入序列的方法。递归神经网络(RNNs)正是实际做到这一点的一种方法。在对动机进行第一次回顾之后,我们将继续研究简单的递归神经网络。然后,我们将介绍著名的长短期记忆单位,然后是门控循环单位。之后,我们将比较这些不同的技术,并讨论一下优缺点。最后,我们将讨论我们的 rnn 的采样策略。当然,这对于一个视频来说太多了。所以,我们会在个别短视频中,针对不同的话题进行讨论。所以,我们来看动机。好吧,我们有一个针对单个图像的输入,但对于语音、音乐、视频或其他传感器数据等时序或时间相关信号来说,这就不太好了。你甚至可以谈论测量能量消耗的非常简单的传感器。因此,固定长度的快照通常信息不多。如果你只看一个单词,你可能很难得到正确的翻译,因为上下文很重要。时间上下文非常重要,需要适当地建模。

递归神经网络能够以不同于时间维度的方式对空间维度进行建模。 CC 下的图片来自深度学习讲座的 4.0 。

现在的问题是:“我们如何将这种背景融入网络?”简单的方法是将整个序列输入一个大网络。这可能是个坏主意,因为我们的内存使用效率很低。这很难训练,甚至不可能训练,我们永远也搞不清楚空间和时间维度之间的区别。我们会照样处理。实际上,也许这不是一个坏主意。对于相当简单的任务,正如你在[6]中看到的,因为他们实际上调查了这一点,并用 CNN 发现了相当令人惊讶的结果。当然,你的一个问题是它不是实时的,因为你需要整个序列来处理。因此,我们在本视频和接下来的几个视频中建议的方法是对架构内的顺序行为进行建模,从而产生递归神经网络。

经典埃尔曼单元草图。 CC 下的图片来自深度学习讲座的 4.0 。

所以让我们来看看简单的递归神经网络。主要的想法是,你引入一个隐藏状态 h 下标 t,它会持续一段时间。所以这是可以改变的,但它本质上是连接回原始细胞 A。所以,A 是我们的循环细胞,它有这种隐藏状态,以某种方式允许我们编码当前时间信息带给我们的东西。现在,我们有一些输入 x 下标 t,这将产生一些输出 y 下标 t,顺便说一下,第一个模型来自 20 世纪 70 年代和 80 年代初,像 Hopfield 网络。这里,我们将坚持使用简单的递归神经网络或 Elman 网络,如[5]中所介绍的。

递归网络和前馈网络的比较。 CC 下的图片来自深度学习讲座的 4.0 。

现在,前馈网络只前馈信息。相比之下,有了循环网络,我们现在可以模拟循环,我们可以模拟记忆和经验,我们可以学习顺序关系。因此,随着数据的到来,我们可以提供连续的预测。这使我们能够实时处理一切。

在 RNN 建筑中,隐藏状态随着时间而变化。来自深度学习讲座的 4.0CC 下的图片。

现在,这又是我们的基本递归神经网络,其中我们有一些输入 x 乘以一些权重。然后,我们有了额外的输入,来自先前配置的隐藏状态,我们本质上有了一个反馈回路,在那里你使用来自现在和最近过去的信息。

在输入序列上展开或展开网络是理解网络解码和训练的关键。 CC 下的图片来自深度学习讲座的 4.0 。

为了计算输出 y 下标 t,我们最终得到一个展开的结构。所以,如果你想评估循环单元,你要做的是从你的单元处理的一些 x ₀开始。这产生了新的结果 y₀和新的隐藏状态₀.现在, h ₀被前馈到下一个实例,在那里实质上是权重被耦合。所以在下一个时间状态,我们有相同单元的完全相同的副本,但是当然,h 是不同的。所以现在,我们馈入 x ₁过程产生 y₁并产生一个新的隐藏态 h ₁等等。我们可以这样做,直到我们在序列的末尾,这样每个单元将隐藏状态作为附加输入传递给后继单元。这意味着先前的输入可以对当前的输出产生影响,因为如果我们已经看到了 x ₀和 x ₁,它们可以对 y 下标(t-1)产生影响,只是因为我们已经对我们在隐藏状态中观察到的 x ₀和 x ₁的信息进行了编码。因此,隐藏状态允许我们存储信息,并通过整个网络将信息传递到某个时间段,然后我们想选择特定的行动。

我们如何更新状态,如何计算输出? CC 下的图片来自深度学习讲座的 4.0 。

所以现在,基本问题是“我们如何更新隐藏状态?”第二个问题是“我们如何结合输入和隐藏状态来计算输出?”所以,我们打开牢房往里面看。你在这里看到的是,我们本质上把隐藏状态和新输入连接起来,然后把它输入非线性,这里是双曲正切。这产生了一个新的状态,从这个新的状态,我们用一个 sigmoid 函数产生新的输出。然后,我们将新的隐藏状态传递给同一个单元格的下一个实例。因此,我们有两个激活函数:用于组合先前状态和当前状态的双曲正切函数和用于产生输出的 sigmoid 非线性函数。

更新状态方程。 CC 下的图片来自深度学习讲座的 4.0 。

当然,为了做到这一点,我们需要权重矩阵,这些权重矩阵在这里用红色表示。如果我们想要更新隐藏状态,我们可以更详细地查看它们。这实质上是隐藏状态转移矩阵 W 下标 hh 乘以最后一个隐藏状态加上隐藏状态转换矩阵的输入 W 下标 xh 乘以 x 下标 t 加上偏差。这然后被馈送到非线性,然后产生新的隐藏状态。

产生输出的方程式。 CC 下的图片来自深度学习讲座的 4.0 。

好,那么我们如何计算输出呢?我们产生了一个新的隐藏状态,这意味着我们现在有了另一个转移矩阵,从隐藏状态产生一个初步输出。因此,我们有了这个新的 W 下标 hy,它接受 h 下标 t 和一些偏置,并将其提供给 sigmoid 函数以产生最终输出。

RNNs 有多种输入和输出选择。 CC 下的图片来自深度学习讲座的 4.0 。

如果我们坚持这种架构,我们就可以实现许多不同类型的架构。这是由架构的设置决定的。因此,我们可以进行一对一的映射,我们有一个输入单元和一个输出单元,但你也可以做一个太多,多对一,或者你甚至可以做许多。一对一的例子是图像分类。本质上是经典的前馈。一对多是图像字幕。多对一是情绪分析,你需要观察一个特定的序列,以便找出在这种情况下是什么情绪。多对多是视频分类。

深度 RNNs 可能吗? CC 下的图片来自深度学习讲座的 4.0 。

当然,我们也可以思考深层 RNNS。到目前为止,我们只有一个隐藏层,我们可以只使用我们的循环模型,这就是为什么我们需要更深入。在这种情况下,它更像是“哟,老兄,我听说你喜欢 RNNs,所以我把 RNN 放在你的 RNN RNN 上。”

深度 RNN 的一个例子。来自深度学习讲座的 CC BY 4.0 下的图片。

由此产生了像这样的建筑。对于深度 rnn,我们简单地堆叠多个隐藏单元。所以,我们当然可以把 Elman 细胞堆叠在 Elman 细胞上。然后,我们将使用输入随时间进行解码,使用多个 RNN 单元进行解码,并随时间产生多个输出。所以,这给了我们接触深层元素的机会。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。

好的。所以,这是对深度 RNNs 和递归神经网络的简单介绍。在下一个视频中,我们想更详细地了解一下训练是如何完成的,以及为了执行训练而实际更新的等式。所以,我希望你喜欢这个视频,并看到你在下一个!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

RNN 民间音乐

FolkRNN.org
MachineFolkSession.com
玻璃球亨利评论 14128

链接

人物 RNNs
CNN 用于机器翻译
用 RNNs 作曲

参考

[1] Dzmitry Bahdanau、Kyunghyun Cho 和 Yoshua Bengio。“通过联合学习对齐和翻译的神经机器翻译”。载于:CoRR abs/1409.0473 (2014 年)。arXiv: 1409.0473。Yoshua Bengio,Patrice Simard 和 Paolo Frasconi。“学习具有梯度下降的长期依赖性是困难的”。摘自:IEEE 神经网络汇刊 5.2 (1994),第 157-166 页。
[3]钟俊英,卡格拉尔·古尔希雷,赵京云等,“门控递归神经网络序列建模的实证评估”。载于:arXiv 预印本 arXiv:1412.3555 (2014 年)。
[4]道格拉斯·埃克和于尔根·施密德胡伯。“学习蓝调音乐的长期结构”。《人工神经网络——ICANN 2002》。柏林,海德堡:施普林格柏林海德堡出版社,2002 年,第 284-289 页。
【5】杰弗里·L·埃尔曼。“及时发现结构”。摘自:认知科学 14.2 (1990),第 179-211 页。
[6] Jonas Gehring,Michael Auli,David Grangier,等,“卷积序列到序列学习”。载于:CoRR abs/1705.03122 (2017 年)。arXiv: 1705.03122。亚历克斯·格雷夫斯、格雷格·韦恩和伊沃·达尼埃尔卡。《神经图灵机》。载于:CoRR abs/1410.5401 (2014 年)。arXiv: 1410.5401。
【8】凯罗尔·格雷戈尔,伊沃·达尼埃尔卡,阿历克斯·格雷夫斯等,“绘制:用于图像生成的递归神经网络”。载于:第 32 届机器学习国际会议论文集。第 37 卷。机器学习研究论文集。法国里尔:PMLR,2015 年 7 月,第 1462-1471 页。
[9]赵京贤、巴特·范·梅林波尔、卡格拉尔·古尔切雷等人,“使用 RNN 编码器-解码器学习统计机器翻译的短语表示”。载于:arXiv 预印本 arXiv:1406.1078 (2014 年)。
【10】J J 霍普菲尔德。“具有突发集体计算能力的神经网络和物理系统”。摘自:美国国家科学院院刊 79.8 (1982),第 2554-2558 页。eprint:http://www.pnas.org/content/79/8/2554.full.pdf.T11【11】w . a . Little。“大脑中持久状态的存在”。摘自:数学生物科学 19.1 (1974),第 101-120 页。
[12]赛普·霍克雷特和于尔根·施密德胡贝尔。“长短期记忆”。摘自:神经计算 9.8 (1997),第 1735-1780 页。
[13] Volodymyr Mnih,Nicolas Heess,Alex Graves 等,“视觉注意的循环模型”。载于:CoRR abs/1406.6247 (2014 年)。arXiv: 1406.6247。
[14]鲍勃·斯特姆、若昂·费利佩·桑托斯和伊琳娜·科尔舒诺娃。“通过具有长短期记忆单元的递归神经网络进行民间音乐风格建模”。英语。In:第 16 届国际音乐信息检索学会会议,晚破,西班牙马拉加,2015,p. 2。
[15] Sainbayar Sukhbaatar,Arthur Szlam,Jason Weston 等著《端到端存储网络》。载于:CoRR abs/1503.08895 (2015 年)。arXiv: 1503.08895。
【16】彼得·m·托德。“算法合成的连接主义方法”。在:13(1989 年 12 月)。
【17】伊利亚·苏茨基弗。“训练递归神经网络”。安大略省多伦多市多伦多大学。,加拿大(2013)。
【18】安德烈·卡帕西。“递归神经网络的不合理的有效性”。载于:安德烈·卡帕西博客(2015)。
贾森·韦斯顿、苏米特·乔普拉和安托万·博尔德斯。“记忆网络”。载于:CoRR abs/1410.3916 (2014 年)。arXiv: 1410.3916。

递归神经网络—第二部分

原文:https://towardsdatascience.com/recurrent-neural-networks-part-2-5f45c1c612c4?source=collection_archive---------49-----------------------

FAU 讲座笔记关于深度学习

穿越时间的反向传播

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

同样,对于 RNNs,我们可以采用一次热编码。 CC 下的图片来自深度学习讲座的 4.0 。

欢迎回到深度学习!今天,我们想多谈一点关于递归神经网络,特别是研究训练程序。那么,我们的 RNN 培训是如何进行的呢?让我们看一个简单的例子,我们从字符级语言模型开始。所以,我们想从一个输入文本中学习一个字符概率分布,我们的词汇将会非常简单。这将是字母 h,e,l,和 o,我们将它们编码为一个热点向量,这样我们就可以得到 h 的向量(1 0 0 0)ᵀ.现在,我们可以继续在序列“hello”上训练我们的 RNN,我们应该知道给定“h”作为第一个输入,网络应该生成序列“hello”。现在,当出现 l 时,网络需要知道以前的输入,因为它需要知道它是需要产生 l 还是 o,它是相同的输入,但有两个不同的输出。所以,你得知道语境。

未经训练的 RNN 解码示例。 CC 下的图片来自深度学习讲座的 4.0 。

让我们看看这个例子,你已经可以看到解码是如何发生的。因此,我们基本上再次将输入层作为一个热码编码向量。然后,我们用之前看到的矩阵产生隐藏状态 h 下标 t,并产生输出,你可以看到。现在,我们输入不同的字母,然后产生一些输出,这些输出可以通过一键编码映射回字母。因此,这基本上为我们提供了遍历整个序列并产生所需输出的可能性。现在,对于训练来说,问题是我们如何确定所有这些权重?当然,我们希望最大化这些权重来预测正确的分量。

通过时间的反向传播展开了完整序列的递归解码。来自深度学习讲座的 4.0CC 下的图片。

这都可以通过时间反向传播算法来实现。我们的想法是在展开的网络上训练。这里有一个关于如何做到这一点的简短草图。我们的想法是展开网络。因此,我们计算整个序列的前向路径,然后应用损耗。所以,我们基本上是在整个序列上反向传播,这样即使是发生在最后一个状态的事情也会对最开始产生影响。因此,我们计算整个序列的后向传递,以获得梯度和权重更新。因此,对于一个随时间反向传播的更新,我必须展开这个由输入序列产生的完整网络。然后,我可以将创建的输出与期望的输出进行比较,并计算更新。

让我们重温一下正向路径的更新公式。 CC 下的图片来自深度学习讲座的 4.0 。

那么,让我们更详细地看一下这个问题。当然,正向传递只是计算隐藏状态和输出。因此,我们知道我们有一些输入序列是 x 下标 1 到 x 下标 T,其中 T 是序列长度。现在,我只是重复更新我们的 u 下标 t,它是各自激活函数之前的线性部分。然后,我们计算激活函数来得到新的隐藏状态,然后我们计算下标 t,它本质上是 sigmoid 函数之前的线性部分。然后,我们应用 sigmoid 来产生基本上是我们网络输出的 y 帽子。

rnn 就像五行代码一样简单。图片来源: imgflip 。

如果我们这样做,那么我们可以展开整个网络,并产生我们需要的所有相应信息,然后实际计算权重的更新。

为了得到梯度,我们从损失函数开始。来自深度学习讲座的 4.0CC 下的图片。

现在通过时间的反向传播基本上产生了一个损失函数。现在,损失函数实际上是对我们在之前的讲座中已经知道的损失进行求和,但我们对每个时间 t 的实际观测值进行求和,因此,例如,我们可以取交叉熵,然后我们将预测输出与地面真实值进行比较,并以我们已经知道的类似方式计算损失函数的梯度。我们希望获得参数向量 θ 的参数更新,参数向量由这三个矩阵、两个偏置向量和向量 h 组成。因此,也可以使用学习率来更新参数,方法与我们在整个课程中所做的非常相似。现在的问题是,当然,我们如何得到这些衍生物,现在的想法是通过整个网络回到过去。

在这张幻灯片上,我们推导了隐藏状态的梯度。来自深度学习讲座的 CC BY 4.0 下的图片。

那我们该怎么办?我们从时间 T = T 开始,然后迭代计算 T 的梯度,直到 1。所以只要记住我们的 y 帽子是由这两个矩阵组成的 o 下标 t 的 sigma 产生的。因此,如果我们想要计算相对于 o 下标 t 的偏导数,那么我们需要 o 下标 t 的 sigmoid 函数的导数乘以损失函数相对于 y 下标 t 的偏导数。现在,你可以看到,相对于 W 下标 hy 的梯度将被给出为 o 下标 t 乘以 h 下标 t 转置的梯度。相对于偏差的梯度将被简单地给定为 o 下标 t 的梯度。因此,梯度 h 下标 t 现在取决于两个元素:受 o 下标 t 影响的隐藏状态和下一个隐藏状态 h 下标 t+1。所以,我们可以得到 h 下标 t 的梯度,作为 h 下标 t+1 对 h 下标 t 的偏导数,转置乘以 h 下标 t+1 的梯度。然后,我们仍然需要添加 o 下标 t 相对于 h 下标 t 的偏导数乘以 o 下标 t 的梯度。这可以表示为权重矩阵 W 下标 hh 乘以 W 下标 hh 乘以 h 下标 t 加上 W 下标 xh 乘以**x 乘以 h 下标 t+1 的梯度加上 W 下标 hy 转置乘以 o 下标 t 的梯度,所以,你可以看到我们也可以针对矩阵实现这个梯度。 现在,您已经拥有了隐藏状态的所有更新。**

接下来,我们研究参数来更新状态。来自深度学习讲座的 4.0CC 下的图片。

现在,我们还想计算其他权重矩阵的更新。所以,让我们来看看这是怎么可能的。我们现在已经基本上建立了计算对我们的 h 下标 t 的导数的方法,所以,现在我们已经可以通过时间传播了。所以对于每个 t,我们基本上得到和中的一个元素,因为我们可以计算梯度 h 下标 t,我们现在可以得到剩余的梯度。为了计算 h 下标 t,我们需要 u 下标 t 的 tanh,它包含剩余的权重矩阵。所以我们基本上得到了关于两个缺失矩阵和偏差的导数。通过使用梯度 h 下标 t 乘以 u 下标 t 的 tangens 双曲线导数。然后,根据您想要更新的矩阵,它将是 h 下标 t-1 转置,或 x 下标 t 转置。对于偏差,你不需要乘以任何额外的东西。因此,这些基本上是计算剩余更新所需的要素。我们现在看到的是,我们可以计算梯度,但它们依赖于 t,现在的问题是,我们如何得到序列的梯度。我们看到的是,以展开状态出现的网络本质上是一个共享权重的网络。这意味着我们可以简单地通过所有时间步长的和来更新。这样,我们就可以计算出权重和时间 t 的所有更新,最终的梯度更新将是所有梯度步长的总和。好了,我们已经看到了如何计算所有这些步骤,是的:这可能是五行伪代码,对吗?

反向传播算法截断的天真想法。来自深度学习讲座的 4.0CC 下的图片。

正常的时间反向传播存在一些问题。你需要展开整个序列,对于长序列和复杂的网络,这意味着大量的内存消耗。单个参数更新非常昂贵。所以,你可以做一个分裂的方法,就像我们在这里建议的天真的方法,但是如果你只是将序列分成几批,然后重新开始初始化隐藏状态,那么你可能可以训练,但是你会在长时间内失去依赖性。在本例中,第一个输入永远不会连接到这里的最后一个输出。所以,我们需要一个更好的方法来处理和节省内存,当然,有一种方法可以做到这一点。这被称为通过时间的截断反向传播算法。

截断时间反向传播算法。 CC 下的图片来自深度学习讲座的 4.0 。

现在,通过时间的截断反向传播算法整体上保持对序列的处理,但是它适应更新的频率和深度。所以每个 k₁时间步,你运行一个 k₂时间步的反向传播,如果 k₂很小,参数更新会很便宜。隐藏状态仍然暴露在许多时间步骤中,正如您将在下面看到的。所以,这个想法是从 1 到 t 的时间 t 运行我们的 RNN 一步计算 h 下标 t 和 y 下标 t,然后如果我们在 k₁步骤,那么我们通过时间从 t 向下运行反向传播到 t 减去 k₂.

时间截断反向传播的一个例子。 CC 下的图片来自深度学习讲座的 4.0 。

这在下面的设置中出现:你可以看到,我们实际上跨越了 4 个时间步。如果我们在第四个时间步,那么我们可以通过时间回溯,直到序列的开始。一旦我们这样做了,我们继续前进,我们总是保持隐藏状态。我们不会丢弃它。所以,我们可以模拟这种相互作用。那么,这能解决我们所有的问题吗?不,因为如果我们有一个很长的时间背景,它将无法更新。比方说,第一个元素负责改变序列中最后一个元素的某些东西,然后你会发现它们永远不会被连接起来。所以,我们再也无法了解这种长时间的背景。这是长期依赖和基本 RNNs 的一个大问题。

可以很好地捕捉附近的上下文。 CC 下的图片来自深度学习讲座的 4.0 。

假设你有这种长期依赖。你想预测“云在天上”的下一个词。你可以看到云可能与此相关。这里,上下文信息就在附近。所以,我们可以很容易地把它编码成隐藏状态。现在,如果我们有很长的序列,那么会困难得多,因为我们必须反向传播这么多步骤。你也看到了,我们在深度网络中有这些问题,在那里我们有消失梯度问题。我们无法找到连接相距甚远的网络部分的更新。

长时间的上下文仍然会产生问题。来自深度学习讲座的 CC BY 4.0 下的图片。

你可以在这里看到,如果我们有这样的例子:一句“我在德国长大”然后说别的“我说得很流利”,那很可能是德语。我必须能够记住“我在德国长大”。因此,上下文信息离得很远,这很重要,因为我们必须通过许多层来传播。

rnn 中长期依赖的问题。 CC 下的图片来自深度学习讲座的 4.0 。

这意味着我们必须彼此相乘。正如 Hochreiter 和 Schmidhuber 在[12]中指出的那样,你可以看到这些梯度易于消失和爆炸。现在,你仍然有这个问题,你可能有一个爆炸梯度。嗯,你可以截断梯度,但消失梯度更难解决。还有一个内存覆盖的问题,因为隐藏状态在每个时间步都被覆盖。因此,如果隐藏状态向量中没有足够的空间,检测长期依赖关系将会更加困难。这也是你的递归神经网络可能出现的问题。那么,我们能做得比这更好吗?答案还是:是的。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。

这是我们将在下一个视频中讨论的内容,届时我们将讨论长短期记忆单位以及 Hochreiter 和 Schmidhuber 所做的贡献。

接下来:更多来自 Schmidhuber 毕业论文的秘密。来源: imgflip 。

所以非常感谢你听这个视频,希望在下一个视频中见到你。谢谢你,再见!

如果你喜欢这篇文章,你可以在这里找到更多的文章,在这里找到更多关于机器学习的教育材料,或者看看我们的深度 学习 讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

RNN 民间音乐

FolkRNN.org
MachineFolkSession.comT5玻璃球亨利评论 14128

链接

人物 RNNs
机器翻译 CNN
用 RNNs 作曲

参考

[1] Dzmitry Bahdanau、Kyunghyun Cho 和 Yoshua Bengio。“通过联合学习对齐和翻译的神经机器翻译”。载于:CoRR abs/1409.0473 (2014 年)。arXiv: 1409.0473。Yoshua Bengio,Patrice Simard 和 Paolo Frasconi。“学习具有梯度下降的长期依赖性是困难的”。摘自:IEEE 神经网络汇刊 5.2 (1994),第 157-166 页。
[3]钟俊英,卡格拉尔·古尔希雷,赵京云等,“门控递归神经网络序列建模的实证评估”。载于:arXiv 预印本 arXiv:1412.3555 (2014 年)。
[4]道格拉斯·埃克和于尔根·施密德胡伯。“学习蓝调音乐的长期结构”。《人工神经网络——ICANN 2002》。柏林,海德堡:施普林格柏林海德堡出版社,2002 年,第 284-289 页。
【5】杰弗里·L·埃尔曼。“及时发现结构”。摘自:认知科学 14.2 (1990),第 179-211 页。
[6] Jonas Gehring,Michael Auli,David Grangier,等,“卷积序列到序列学习”。载于:CoRR abs/1705.03122 (2017 年)。arXiv: 1705.03122。亚历克斯·格雷夫斯、格雷格·韦恩和伊沃·达尼埃尔卡。《神经图灵机》。载于:CoRR abs/1410.5401 (2014 年)。arXiv: 1410.5401。
【8】凯罗尔·格雷戈尔,伊沃·达尼埃尔卡,阿历克斯·格雷夫斯等,“绘制:用于图像生成的递归神经网络”。载于:第 32 届机器学习国际会议论文集。第 37 卷。机器学习研究论文集。法国里尔:PMLR,2015 年 7 月,第 1462-1471 页。
[9]赵京贤、巴特·范·梅林波尔、卡格拉尔·古尔切雷等人,“使用 RNN 编码器-解码器学习统计机器翻译的短语表示”。载于:arXiv 预印本 arXiv:1406.1078 (2014 年)。
【10】J J 霍普菲尔德。“具有突发集体计算能力的神经网络和物理系统”。摘自:美国国家科学院院刊 79.8 (1982),第 2554-2558 页。eprint:http://www.pnas.org/content/79/8/2554.full.pdf.T11【11】w . a . Little。“大脑中持久状态的存在”。摘自:数学生物科学 19.1 (1974),第 101-120 页。
[12]赛普·霍克雷特和于尔根·施密德胡贝尔。“长短期记忆”。摘自:神经计算 9.8 (1997),第 1735-1780 页。
[13] Volodymyr Mnih,Nicolas Heess,Alex Graves 等,“视觉注意的循环模型”。载于:CoRR abs/1406.6247 (2014 年)。arXiv: 1406.6247。
[14]鲍勃·斯特姆、若昂·费利佩·桑托斯和伊琳娜·科尔舒诺娃。“通过具有长短期记忆单元的递归神经网络进行民间音乐风格建模”。英语。In:第 16 届国际音乐信息检索学会会议,晚破,西班牙马拉加,2015,p. 2。
[15] Sainbayar Sukhbaatar,Arthur Szlam,Jason Weston 等著《端到端存储网络》。载于:CoRR abs/1503.08895 (2015 年)。arXiv: 1503.08895。
【16】彼得·m·托德。“算法合成的连接主义方法”。在:13(1989 年 12 月)。
【17】伊利亚·苏茨基弗。“训练递归神经网络”。安大略省多伦多市多伦多大学。,加拿大(2013)。
【18】安德烈·卡帕西。“递归神经网络的不合理的有效性”。载于:安德烈·卡帕西博客(2015)。
贾森·韦斯顿、苏米特·乔普拉和安托万·博尔德斯。“记忆网络”。载于:CoRR abs/1410.3916 (2014 年)。arXiv: 1410.3916。

递归神经网络——第三部分

原文:https://towardsdatascience.com/recurrent-neural-networks-part-3-1032d4a67757?source=collection_archive---------40-----------------------

FAU 讲座笔记关于深度学习

向 schmid Huber-LSTMs 致敬

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是讲座视频&的完整文字记录,配有幻灯片。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎回到深度学习!今天,我想向大家展示一种替代方案,来解决递归神经网络中的消失梯度问题。

于尔根·斯密德胡伯的名言。来源: imgflip 。

你已经注意到长时间的上下文是一个问题。因此,我们将讨论长短期记忆单位(LSTMs)。它们是由 Schmidhuber 的一位 Hochreiter 介绍的,并于 1997 年出版。

机器学习领域的两位著名作者。 CC 下的图片来自深度学习讲座的 4.0 。

它们被设计用来解决长期依赖中的消失梯度问题。主要的想法是,你引入门来控制额外状态下的写和访问存储器。

LSTM 细胞概述。 CC 下的图片来自深度学习讲座的 4.0 。

那么,让我们来看看 LSTM 单元。你看这里,一个主要的特征是我们现在有两个可以被认为是隐藏状态的东西:我们有单元状态 C 和隐藏状态 h 。同样,我们有一些输入。然后我们有相当多的激活函数。然后我们将它们组合起来,最后,我们产生一些输出 y 。这个单元比你之前在简单的 RNNs 中看到的要复杂得多。

LSTM 细胞的工作流程。来自深度学习讲座的 4.0CC 下的图片。

好,那么 LSTM 的主要特征是什么:给定一些输入 x 它产生一个隐藏状态 h 。它还有一个单元状态 C ,我们将在接下来的几张幻灯片中更详细地研究它,以产生输出 y 。现在,我们有几个门,这些门本质上是用来控制信息流的。有一个遗忘门,用来遗忘细胞状态中的旧信息。然后,我们有输入门,这实质上是决定细胞状态的新输入。由此,我们然后计算更新的单元状态和更新的隐藏状态。

单元状态处理的路径。 CC 下的图片来自深度学习讲座的 4.0 。

让我们来看看工作流程。我们有每个时间点 t 之后的单元状态,并且单元状态仅经历线性变化。所以没有激活功能。你看到在细胞状态的路径上只有一个乘法和一个加法。所以,细胞状态可以流过这个单位。对于多个时间步长,单元状态可以是恒定的。现在,我们要对细胞状态进行操作。我们用几个门来做这个,第一个门是遗忘门。这里的关键思想是我们想忘记细胞状态的信息。在另一个步骤中,我们要考虑如何将新的信息放入细胞状态,用来记忆东西。

遗忘之门。 CC 下的图片来自深度学习讲座的 4.0 。

因此,遗忘门 f 控制有多少先前的单元状态被遗忘。你可以看到它是由 sigmoid 函数计算的。所以,它介于 0 和 1 之间。它本质上是通过隐藏状态和 x 的串联加上一些偏差的矩阵乘法来计算的。然后乘以单元状态。所以,我们决定忘记状态向量的哪些部分,保留哪些部分。

输入门。 CC 下的图片来自深度学习讲座的 4.0 。

现在,我们还需要输入新的信息。对于新信息,我们必须以某种方式决定将什么信息输入到单元状态中。这里,我们需要两个激活函数:一个我们称之为 I ,它也是由一个 sigmoid 激活函数产生的。同样,隐藏状态的矩阵乘法与输入加上一些偏置和 sigmoid 函数连接,是非线性的。记住,这个值会在 0 和 1 之间,所以你可以说它是在选择什么。然后,我们有一些 C 波浪号,这是一种由双曲正切产生的更新状态。然后,将某个权重矩阵 W 下标 c 作为输入,该权重矩阵 W 下标 c 乘以隐藏向量和输入向量加上某个偏差的串联。所以本质上,我们有这个指数,然后乘以中间细胞阶段 C 代字号。我们可以说双曲正切正在产生一些新的细胞状态,然后我们通过 I 选择这些指数中的哪些应该添加到当前细胞状态。因此,我们用 I 乘以新产生的 C 波形符,并将其添加到单元格状态 C

单元状态更新。来自深度学习讲座的 4.0CC 下的图片。

现在,我们使用与前一状态的遗忘门的逐点乘法来更新我们刚刚看到的完整单元状态。然后,我们用逐点乘法将已经由 I 识别的更新单元状态的元素相加。因此,您可以看到,仅使用乘法和加法,单元状态的更新是完全线性的。

隐藏状态更新和输出。来自深度学习讲座的 4.0CC 下的图片。

现在,我们仍然需要产生隐藏状态和输出。正如我们在 Elman 单元中所看到的,我们网络的输出只取决于隐藏态。因此,我们首先用另一个非线性更新隐藏状态,然后乘以单元状态的变换。这给了我们新的隐藏状态,并且根据新的隐藏状态,我们产生具有另一个非线性的输出。

更新公式。 CC 下的图片来自深度学习讲座的 4.0 。

所以,你看这些是更新方程。我们产生一些 o ,这实质上是一个 sigmoid 函数对新隐藏态的提议。然后,我们将它与细胞状态产生的双曲线正切相乘,以选择实际产生的元素。这给了我们新的隐藏状态。新的隐藏状态可以通过另一个非线性来产生输出。顺便说一下,你可以在这里看到,对于隐藏状态的更新和新输出的产生,我们省略了当然需要的转换矩阵。你可以把网络中的每一个非线性本质上解释为一个通用函数逼近器。所以,我们仍然需要线性部分,当然,在这里减少消失梯度。

记住:rnn 就像五行代码一样简单。图片来源: imgflip 。

如果你想训练所有这些,你可以回去用一个非常相似的方法,就像我们已经看到的 Elman 细胞一样。所以,你用反向传播来更新所有不同的权重矩阵。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。

好吧。这已经把我们带到了这个视频的结尾。你们已经看到了长短期记忆细胞,不同的部分,不同的门,当然,这是这节课非常重要的一部分。所以,如果你正在准备考试,那么我肯定会推荐你看一看如何画出这么长的短期记忆单元。你可以看到 LSTM 有很多优点。特别地,我们可以通过单元状态的线性变换来缓解消失梯度的问题。顺便说一句,值得指出的是,我们在长短期记忆细胞中包含了一些我们从计算机设计中了解到的想法。我们基本上学会了如何操纵记忆细胞。我们可以说,在隐藏状态下,我们现在有了一种程序,一种有限状态机,它对一些内存进行操作,学习存储哪些信息,删除哪些信息,加载哪些信息。因此,这些网络设计如何逐渐接近计算机体系结构是非常有趣的。当然,关于这个还有很多要说的。在下一个视频中,我们将研究门控循环神经网络,它是 LSTM 细胞的一种简化。您将会看到,采用稍薄的设计,我们仍然可以获得 LSTM 的许多优势,但参数要少得多。好了,我希望你喜欢这个视频,下次我们讨论门控循环神经网络时再见。拜拜。

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

RNN 民间音乐

FolkRNN.org
MachineFolkSession.com
玻璃球亨利评论 14128

链接

人物 RNNs
CNN 用于机器翻译
用 RNNs 作曲

参考

[1] Dzmitry Bahdanau、Kyunghyun Cho 和 Yoshua Bengio。“通过联合学习对齐和翻译的神经机器翻译”。载于:CoRR abs/1409.0473 (2014 年)。arXiv: 1409.0473。Yoshua Bengio,Patrice Simard 和 Paolo Frasconi。“学习具有梯度下降的长期依赖性是困难的”。摘自:IEEE 神经网络汇刊 5.2 (1994),第 157-166 页。
[3]钟俊英,卡格拉尔·古尔希雷,赵京云等,“门控递归神经网络序列建模的实证评估”。载于:arXiv 预印本 arXiv:1412.3555 (2014 年)。
[4]道格拉斯·埃克和于尔根·施密德胡伯。“学习蓝调音乐的长期结构”。《人工神经网络——ICANN 2002》。柏林,海德堡:施普林格柏林海德堡出版社,2002 年,第 284-289 页。
【5】杰弗里·L·埃尔曼。“及时发现结构”。摘自:认知科学 14.2 (1990),第 179-211 页。
[6] Jonas Gehring,Michael Auli,David Grangier,等,“卷积序列到序列学习”。载于:CoRR abs/1705.03122 (2017 年)。arXiv: 1705.03122。亚历克斯·格雷夫斯、格雷格·韦恩和伊沃·达尼埃尔卡。《神经图灵机》。载于:CoRR abs/1410.5401 (2014 年)。arXiv: 1410.5401。
【8】凯罗尔·格雷戈尔,伊沃·达尼埃尔卡,阿历克斯·格雷夫斯等,“绘制:用于图像生成的递归神经网络”。载于:第 32 届机器学习国际会议论文集。第 37 卷。机器学习研究论文集。法国里尔:PMLR,2015 年 7 月,第 1462-1471 页。
[9]赵京贤、巴特·范·梅林波尔、卡格拉尔·古尔切雷等人,“使用 RNN 编码器-解码器学习统计机器翻译的短语表示”。载于:arXiv 预印本 arXiv:1406.1078 (2014 年)。
【10】J J 霍普菲尔德。“具有突发集体计算能力的神经网络和物理系统”。摘自:美国国家科学院院刊 79.8 (1982),第 2554-2558 页。eprint:http://www.pnas.org/content/79/8/2554.full.pdf.T11【11】w . a . Little。“大脑中持久状态的存在”。摘自:数学生物科学 19.1 (1974),第 101-120 页。
[12]赛普·霍克雷特和于尔根·施密德胡贝尔。“长短期记忆”。摘自:神经计算 9.8 (1997),第 1735-1780 页。
[13] Volodymyr Mnih,Nicolas Heess,Alex Graves 等,“视觉注意的循环模型”。载于:CoRR abs/1406.6247 (2014 年)。arXiv: 1406.6247。
[14]鲍勃·斯特姆、若昂·费利佩·桑托斯和伊琳娜·科尔舒诺娃。“通过具有长短期记忆单元的递归神经网络进行民间音乐风格建模”。英语。In:第 16 届国际音乐信息检索学会会议,晚破,西班牙马拉加,2015,p. 2。
[15] Sainbayar Sukhbaatar,Arthur Szlam,Jason Weston 等著《端到端存储网络》。载于:CoRR abs/1503.08895 (2015 年)。arXiv: 1503.08895。
【16】彼得·m·托德。“算法合成的连接主义方法”。在:13(1989 年 12 月)。
【17】伊利亚·苏茨基弗。“训练递归神经网络”。安大略省多伦多市多伦多大学。,加拿大(2013)。
【18】安德烈·卡帕西。“递归神经网络的不合理的有效性”。载于:安德烈·卡帕西博客(2015)。
贾森·韦斯顿、苏米特·乔普拉和安托万·博尔德斯。“记忆网络”。载于:CoRR abs/1410.3916 (2014 年)。arXiv: 1410.3916。

递归神经网络——第四部分

原文:https://towardsdatascience.com/recurrent-neural-networks-part-4-39a568034d3b?source=collection_archive---------53-----------------------

FAU 讲座笔记关于深度学习

门控循环单位

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是讲座视频&的完整文本,配有幻灯片。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎回到深度学习!今天我们想谈谈门控循环单位(GRUs),它是 LSTM 细胞的一种简化。

GRUs 为长时间的上下文提供了一种更简单的方法。图片来源: imgflip 。

这又是一个神经网络:门控循环单元。这里的想法是,LSTM 当然很棒,但它有很多参数,很难训练。

gru 的性能与 LSTMs 相当,但参数更少。 CC 下的图片来自深度学习讲座的 4.0 。

因此,Cho 提出了门控循环单元,并在 2014 年将其引入统计机器翻译。你可以说这是一种 LSTM,但它更简单,参数更少。

GRU 细胞的结构。 CC 下的图片来自深度学习讲座的 4.0 。

这是大致的设置。你可以看到我们不像在 LSTM 那样有两个不同的记忆。我们只有一个隐藏状态。与 LSTM 的一个相似之处是隐藏状态只沿着一个线性过程流动。所以,你在这里只能看到乘法和加法。同样,在 LSTM 中,我们从隐藏状态产生输出。

GRU 工作流程的主要步骤。来自深度学习讲座的 CC BY 4.0 下的图片。

所以让我们来看看 Cho 为了提出这个酷细胞的想法。它从 LSTM 中提取概念,并通过门来控制内存。主要区别在于没有额外的单元状态。所以,记忆只直接作用于隐藏状态。状态的更新可以分为四个步骤:有一个重置门,它控制着先前隐藏状态的影响。然后是引入新计算的更新的更新门。因此,下一步提出一个更新的隐藏状态,然后用它来更新隐藏状态。

重置门。 CC 下的图片来自深度学习讲座的 4.0 。

那么,这是如何工作的呢?首先我们确定前一个隐藏状态的影响。这是通过 sigmoid 激活函数来完成的。我们又有一个矩阵类型的更新。我们将输入和之前的隐藏状态用一个矩阵相乘,并添加一些偏差。然后,将其输入这个 sigmoid 激活函数,该函数产生一些复位值 r 下标 t。

更新门首先用来自深度学习讲座的 4.0 计算 CC 下的 z 下标 t. Image。

接下来,我们生产一些 z 。这实质上是对新隐藏状态的更新建议。因此,这又是由一个 sigmoid 函数产生的,其中我们连接了最后一个隐藏状态,输入向量乘以矩阵 W 下标 z 并添加一些偏差。

接下来,计算更新建议。 CC 下的图片来自深度学习讲座的 4.0 。

接下来,我们提议更新。所以我们把输入和复位状态结合起来。这是以如下方式完成的:因此,更新建议 h 波浪号由双曲正切产生,其中我们将复位门乘以最后的隐藏状态。因此,我们基本上从最后一个隐藏状态中删除了我们不想看到的条目,并将 x 下标 t 与某个矩阵 W 下标 h 相乘,并添加一些偏差 b 下标 h。然后,这被提供给 tanh 以产生更新建议。

最后,新状态被计算为旧状态和更新提议之间的混合。下图 CC BY 4.0 来自深度学习讲座。

现在,有了更新建议,我们就进入了更新阶段。更新门控制旧状态和建议状态的组合。因此,我们通过乘以 1 — z 下标 t 来计算新的状态。你记得这是我们之前用旧状态计算的中间变量。进一步,我们添加 z 下标 t 乘以 h 波浪号。这是提议的更新。因此,本质上,产生了一个 z 下标 t 的 sigmoid 函数现在用于选择是保留旧状态的旧信息还是用新状态的信息更新它。这给出了新的隐藏状态。有了新的隐藏状态,我们产生了新的输出,并再次注意到我们在这一步省略了转换矩阵。因此,我们把它写成下标 t 的 sigmoid,但实际上有转换矩阵和偏差。不,我们在这里什么也没发现。所以,这个东西给出了最终输出 y hat 下标 t。

关于 GRUs 的评论。来自深度学习讲座的 4.0CC 下的图片。

一些注释:加法对于保留反向传播中的误差是必要的。这些门允许捕获不同的时标和远程相关性。这些单元能够通过学习限制门来学习短期依赖性。因此,如果我们有一个接近于零的下标 t,它将忽略先前的隐藏状态。我们还可以通过设置限制性更新门来了解长期依赖性。所以,这里我们的 z 下标 t 接近于零,这意味着我们忽略了新的输入门。然后,根据信息的类型出现不同的节奏。现在,你会说“好吧。现在,我们有了 RNN 单位、LSTM 单位和 GRUs。那么,我们该走哪一条?”

重新盖好 RNN 电池。下图 CC BY 4.0 来自深度学习讲座。

所以,让我们简单回顾一下。在简单的 RNNs 中,我们有基于梯度的训练,这很难做到。我们有长期依赖的爆炸梯度和消失梯度问题。短期依赖性很好,但是由于指数小梯度,它们可能隐藏长期依赖性,并且隐藏状态在每个时间步中被覆盖。

来自深度学习讲座的 4.0 的 CC 下的 LSTM 和 GRU. Image 对比。

然后,我们有 LSTMs 和 GRUs。他们两人都引入了对记忆进行操作的门。在 LSTMs 中,我们将其分为单元状态和隐藏状态。在 GRU,我们只有一个隐藏的国家。它们都有完全线性的记忆,这有助于我们理解长期依赖性。

LSTM 和格鲁的相似之处。来自深度学习讲座的 CC BY 4.0 下的图像。

所以,这里的相似之处,当然,是信息由门控制,以及捕捉不同时间尺度的依赖性的能力。状态的加法计算保留了反向传播期间的误差。所以,我们可以做更有效率的训练。

LSTMs 和 GRUs 的区别。 CC 下的图片来自深度学习讲座的 4.0 。

当然,LSTMs 有不同的隐藏和单元状态。因此,它们通过一个输出门、一个输入门和一个遗忘门来控制内存内容的暴露。他们独立工作。所以,他们可能会做不同的事情。新内存内容独立于当前内存。在 GRU,我们将隐藏状态和细胞状态结合在一起。所以,我们完全暴露在没有控制的内存内容中。有一个公共的更新门,它用我们的变量 z 下标 t 产生新的隐藏状态。它本质上决定是使用旧的状态还是使用建议的更新。所以,新的内存内容取决于当前的内存。

经验证据表明,LSTM 和 GRU 都优于埃尔曼细胞。然而,GRU 和 LSTM 的表现不相上下。 CC 下的图片来自深度学习讲座的 4.0 。

您也可以比较应用程序,因为您可能会问应该使用什么。在[3]中,您看到了门控递归神经网络对序列建模的经验评估。他们比较了简单的 RNN、LSTMs 和 GRU 网络。任务是复调音乐建模和语音信号建模。结果表明门控循环单位明显优于常规循环单位。GRU 和 LSTM 之间的比较不是结论性的。他们有相似的表现。

Jürgen Schmidhuber 的至理名言。图片来源: imgflip 。

所以,你可以说它们都非常适合序列建模。一个有较少的参数,但是对于本文中提出的任务,它没有产生很大的差异,所以它们都是可行的选择。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。来自深度学习讲座的 4.0CC 下的图片。

好吧,下一次在深度学习中,我们想谈谈生成序列。我们现在有了递归神经网络,当然,递归不仅可以用来处理长序列,当然,我们也可以生成序列。因此,我们将稍微研究一下序列生成。非常感谢你们的聆听。我希望你喜欢这个视频,并希望在下一个视频中看到你。拜拜。

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

RNN 民间音乐

FolkRNN.org
MachineFolkSession.com
玻璃球亨利评论 14128

链接

人物 RNNs
CNN 用于机器翻译
用 RNNs 作曲

参考

[1] Dzmitry Bahdanau、Kyunghyun Cho 和 Yoshua Bengio。“通过联合学习对齐和翻译的神经机器翻译”。载于:CoRR abs/1409.0473 (2014 年)。arXiv: 1409.0473。Yoshua Bengio,Patrice Simard 和 Paolo Frasconi。“学习具有梯度下降的长期依赖性是困难的”。摘自:IEEE 神经网络汇刊 5.2 (1994),第 157-166 页。
[3]钟俊英,卡格拉尔·古尔希雷,赵京云等,“门控递归神经网络序列建模的实证评估”。载于:arXiv 预印本 arXiv:1412.3555 (2014 年)。
[4]道格拉斯·埃克和于尔根·施密德胡伯。“学习蓝调音乐的长期结构”。《人工神经网络——ICANN 2002》。柏林,海德堡:施普林格柏林海德堡出版社,2002 年,第 284-289 页。
【5】杰弗里·L·埃尔曼。“及时发现结构”。摘自:认知科学 14.2 (1990),第 179-211 页。
[6] Jonas Gehring,Michael Auli,David Grangier,等,“卷积序列到序列学习”。载于:CoRR abs/1705.03122 (2017 年)。arXiv: 1705.03122。亚历克斯·格雷夫斯、格雷格·韦恩和伊沃·达尼埃尔卡。《神经图灵机》。载于:CoRR abs/1410.5401 (2014 年)。arXiv: 1410.5401。
【8】凯罗尔·格雷戈尔,伊沃·达尼埃尔卡,阿历克斯·格雷夫斯等,“绘制:用于图像生成的递归神经网络”。载于:第 32 届机器学习国际会议论文集。第 37 卷。机器学习研究论文集。法国里尔:PMLR,2015 年 7 月,第 1462-1471 页。
[9]赵京贤、巴特·范·梅林波尔、卡格拉尔·古尔切雷等人,“使用 RNN 编码器-解码器学习统计机器翻译的短语表示”。载于:arXiv 预印本 arXiv:1406.1078 (2014 年)。
【10】J J 霍普菲尔德。“具有突发集体计算能力的神经网络和物理系统”。摘自:美国国家科学院院刊 79.8 (1982),第 2554-2558 页。eprint:http://www.pnas.org/content/79/8/2554.full.pdf.T11【11】w . a . Little。“大脑中持久状态的存在”。摘自:数学生物科学 19.1 (1974),第 101-120 页。
[12]赛普·霍克雷特和于尔根·施密德胡贝尔。“长短期记忆”。摘自:神经计算 9.8 (1997),第 1735-1780 页。
[13] Volodymyr Mnih,Nicolas Heess,Alex Graves 等,“视觉注意的循环模型”。载于:CoRR abs/1406.6247 (2014 年)。arXiv: 1406.6247。
[14]鲍勃·斯特姆、若昂·费利佩·桑托斯和伊琳娜·科尔舒诺娃。“通过具有长短期记忆单元的递归神经网络进行民间音乐风格建模”。英语。In:第 16 届国际音乐信息检索学会会议,晚破,西班牙马拉加,2015,p. 2。
[15] Sainbayar Sukhbaatar,Arthur Szlam,Jason Weston 等著《端到端存储网络》。载于:CoRR abs/1503.08895 (2015 年)。arXiv: 1503.08895。
【16】彼得·m·托德。“算法合成的连接主义方法”。在:13(1989 年 12 月)。
【17】伊利亚·苏茨基弗。“训练递归神经网络”。安大略省多伦多市多伦多大学。,加拿大(2013)。
【18】安德烈·卡帕西。“递归神经网络的不合理的有效性”。载于:安德烈·卡帕西博客(2015)。
贾森·韦斯顿、苏米特·乔普拉和安托万·博尔德斯。“记忆网络”。载于:CoRR abs/1410.3916 (2014 年)。arXiv: 1410.3916。

递归神经网络——第五部分

原文:https://towardsdatascience.com/recurrent-neural-networks-part-5-885fc3357792?source=collection_archive---------45-----------------------

FAU 讲座笔记关于深度学习

序列生成

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。 自己试试吧!如果您发现错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

如何使用 RNNs 进行序列生成? CC 下的图片来自深度学习讲座的 4.0 。

欢迎回到我们关于递归神经网络的视频系列的最后部分!今天,我们想谈谈递归神经网络的采样。当我说采样时,我的意思是我们想使用递归神经网络来实际生成符号序列。那么,我们怎样才能做到呢?

如果你用正确的方法训练你的神经网络。你可以用一种方式来创建它们,它们预测下一个元素的概率分布。所以,如果我训练它们来预测序列中的下一个符号,你也可以用它们来生成序列。这里的想法是,从空符号开始,然后使用 RNN 生成一些输出。然后,将这个输出放入下一个状态的输入中。如果你继续这样做,那么你可以看到你实际上可以从你训练过的循环神经网络中生成完整的序列。

贪婪的搜索。 CC 下的图片来自深度学习讲座的 4.0 。

因此,简单的策略是执行贪婪搜索。所以我们从空符号开始。然后,我们只需选择最可能的元素作为下一个状态中 RNN 的输入,并生成下一个、下一个和下一个,这样每次实验都会生成一个样本序列。所以,这将是一个贪婪的搜索,你可以看到,我们得到的是这里构造的一个句子。我们在这里构造的句子是“让我们穿越时间”。当然,缺点是不可能有前瞻性。所以,姑且说“走吧”后面最有可能的词是“走吧”。所以你可能会产生循环,比如"走吧,走吧"等等。所以,你无法察觉“让我们穿越时间”有更高的总概率。所以,它倾向于在讲话中重复一系列频繁出现的词“和”、“这个”、“一些”等等。

光束搜索。来自深度学习讲座的 CC BY 4.0 下的图片。

现在,我们对缓解这个问题感兴趣。这可以通过波束搜索来完成。现在,波束搜索的概念是选择 k 个最可能的元素。k 本质上是波束宽度或大小。所以,在这里你可以推出 k 个可能的序列。你有一个以这 k 个元素为前缀的,取 k 个最可能的。所以,在我们右边展示的例子中,我们从一个空单词开始。然后,我们选择两个最有可能的选项,即“让我们”和“通过”。接下来,如果我们取“through”,我们生成“let's”作为输出。如果我们用“let's ”,我们产生“go ”,我们可以继续这个过程,用我们的两个光束。我们可以在波束搜索中保留两个最可能的序列。所以现在,我们一次生成两个序列。一个是《穿越时空》,一个是《穿越时空》。所以,你可以看到我们可以用这个光束的想法来产生多个序列。最后,我们可以确定哪一个是我们最喜欢的,或者哪一个产生了最大的总概率。因此,我们可以一次生成多个序列,这通常也包含比贪婪搜索更好的序列。我认为这是从 RNN 身上取样的最常见的技术之一。

随机搜索。 CC 下的图片来自深度学习讲座的 4.0 。

当然也有其他类似随机抽样的。这里的思路是,你根据输出概率分布选择下一个。你还记得吗,我们把单词编码成一个热编码向量。然后,我们可以将自动 RNN 的输出解释为概率分布,并从中进行采样。这就允许我们产生许多不同的序列。那么假设“let's”的输出概率为 0.8,那么它作为下一个单词被抽样 10 次中的 8 次。这会产生非常多样的结果,看起来可能太随机了。所以,你可以看到我们得到了非常不同的结果,以及我们在这里生成的序列。你也可以在生成的序列中观察到相当多的随机性。为了减少随机性,您可以增加概率或减少可能或不太可能的单词的概率。这可以通过例如温度采样来完成。这里你可以看到,我们引入了这个温度𝜏,然后我们用它来控制概率采样。这是一种常见的技巧,你已经在本课程的各种实例中看到过。

角色级 RNNs 。来自深度学习讲座的 CC BY 4.0 下的图片。

让我们看一些例子,我发现非常有趣的一件事是用 RNNs 进行基于字符的语言建模。我们这里有一篇 Andrew Kaparthy 的博文。我也把它作为下面描述的链接。在那里,他训练了一个基于莎士比亚文本生成的 RNN。它是在角色层面上训练的。所以,你只有一个字符作为输入,然后你生成序列。它产生了非常有趣的序列。这里,你可以看到已经生成的典型例子。让我读给你听:

唉,我想他将会到来,到那一天,小斯瑞恩将不再被喂养,
他只是一条锁链,是他死亡的主题,
我不会睡去。

除来自 卡帕蒂的博客

诸如此类。所以,你可以看到这是非常有趣的,这种语言的类型非常接近莎士比亚,但是如果你通读这些例子,你可以看到它们本质上完全是胡说八道。然而,有趣的是,这种语言的基调仍然存在,而且对莎士比亚来说非常典型。这真的很有趣。

创作民间音乐。 CC 下的图片来自深度学习讲座的 4.0 。

当然,你可以产生很多很多其他的东西。我今天想给你们看的一个很好的例子是创作民间音乐。所以,音乐创作通常是用 RNNS 来解决的,你可以在文学作品中找到不同的例子,也是尤尔根·施密德胡伯的作品。这里的想法是使用更大更深的网络来产生民间音乐。因此,他们采用的是一个字符级的 RNN 使用 ABC 格式,包括生成标题。我这里有一个例子,这是一小段音乐。是的,正如你所听到的,这真的是民间音乐。这是完全自动生成的。有趣不是吗?如果你仔细听,你会听到民间音乐可能特别适合这个,因为你可能会说这有点重复。尽管如此,整首歌完全是自动生成的,这还是很棒的。实际上,人们会在真实的乐器上演奏计算机生成的歌曲,就像这些人一样。非常有趣的观察。所以,如果你对此感兴趣,我也把链接放在这里供你参考。你可以在这个网站上听到更多的例子。

图像序列生成。来自深度学习讲座的 CC BY 4.0 下的图片。

所以也有针对非顺序任务的 rnn。RNNs 也可用于静态输入,如图像生成。然后,想法是模拟从草图到最终图像的过程。你可以看到一个例子,我们从从模糊到清晰地绘制数字开始。在这个例子中,他们使用一个额外的注意机制来告诉网络在哪里寻找。这就产生了类似于笔触的东西。它实际上使用了一种变分的自动编码器,我们将在讨论无监督深度学习的主题时讨论这种编码器。

RNNs 上的单元总结。 CC 下的图片来自深度学习讲座的 4.0 。

所以我们稍微总结一下。你已经看到递归神经网络能够直接模拟顺序算法。你通过截断的反向传播来训练。简单的单元受到爆炸和消失梯度的极大影响。我们已经看到,LSTMs 和 gru 是改进的 rnn,它们明确地模拟了这种遗忘和记忆操作。我们没有谈到的是,还有很多很多的发展,我们无法在这个简短的讲座中涵盖。所以,谈论记忆网络,神经图灵机也是很有趣的,我们目前只接触了注意力和循环神经网络。在接下来的一个视频中,我们将更多地讨论注意力。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。来自深度学习讲座的 CC BY 4.0 下的图片。

所以,下一次在深度学习中,我们想谈谈可视化。特别是,我们想谈谈可视化架构,培训过程,当然还有网络的内部工作。我们想弄清楚网络内部到底发生了什么,有相当多的技术,老实说,我们已经在本课前面看到过其中一些。在这堂课中,我们真的想深入研究这些方法,了解它们实际上是如何工作的,以便弄清楚深层神经网络内部发生了什么。一个有趣的观察结果是,这也与神经网络艺术有关。另一件值得更多思考的事情是注意力机制,这也将在随后的一个视频中涉及。

综合题。来自深度学习讲座的 4.0CC 下的图片。

因此,我有一些综合性的问题:“与前馈网络相比,RNNs 的优势是什么?”然后当然是:“你怎么训练一只 RNN?”、“挑战是什么?”,“LSTMs 背后的主要思想是什么?”因此,你应该能够描述在培训期间展开 RNNs。你应该能够描述埃尔曼细胞,LSTM 和格鲁。所以,如果你必须在不久的将来参加一些测试,这些真的是非常重要的事情。所以,最好对这种问题有所准备。好了,下面我们有一些进一步的阅读。安德鲁·卡帕西有一篇非常好的博文。有一篇关于 CNN 的机器翻译的非常酷的博文,我非常推荐阅读,还有一篇关于音乐一代的很酷的博文,你也可以在下面找到。当然,我们也有大量的科学参考。所以,我希望你喜欢这个视频,并看到你在下一个。拜拜。

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中获得文字记录,试试自动博客。

RNN 民间音乐

FolkRNN.org
MachineFolkSession.com
玻璃亨利评论 14128

链接

人物 RNNs
CNN 用于机器翻译
用 RNNs 作曲

参考

[1] Dzmitry Bahdanau、Kyunghyun Cho 和 Yoshua Bengio。“通过联合学习对齐和翻译的神经机器翻译”。载于:CoRR abs/1409.0473 (2014 年)。arXiv: 1409.0473。Yoshua Bengio,Patrice Simard 和 Paolo Frasconi。“学习具有梯度下降的长期依赖性是困难的”。摘自:IEEE 神经网络汇刊 5.2 (1994),第 157-166 页。
[3]钟俊英,卡格拉尔·古尔希雷,赵京云等,“门控递归神经网络序列建模的实证评估”。载于:arXiv 预印本 arXiv:1412.3555 (2014 年)。
[4]道格拉斯·埃克和于尔根·施密德胡伯。“学习蓝调音乐的长期结构”。《人工神经网络——ICANN 2002》。柏林,海德堡:施普林格柏林海德堡出版社,2002 年,第 284-289 页。
【5】杰弗里·L·埃尔曼。“及时发现结构”。摘自:认知科学 14.2 (1990),第 179-211 页。
[6] Jonas Gehring,Michael Auli,David Grangier,等,“卷积序列到序列学习”。载于:CoRR abs/1705.03122 (2017 年)。arXiv: 1705.03122。亚历克斯·格雷夫斯、格雷格·韦恩和伊沃·达尼埃尔卡。《神经图灵机》。载于:CoRR abs/1410.5401 (2014 年)。arXiv: 1410.5401。
【8】凯罗尔·格雷戈尔,伊沃·达尼埃尔卡,阿历克斯·格雷夫斯等,“绘制:用于图像生成的递归神经网络”。载于:第 32 届机器学习国际会议论文集。第 37 卷。机器学习研究论文集。法国里尔:PMLR,2015 年 7 月,第 1462-1471 页。
[9]赵京贤、巴特·范·梅林波尔、卡格拉尔·古尔切雷等人,“使用 RNN 编码器-解码器学习统计机器翻译的短语表示”。载于:arXiv 预印本 arXiv:1406.1078 (2014 年)。
【10】J J 霍普菲尔德。“具有突发集体计算能力的神经网络和物理系统”。摘自:美国国家科学院院刊 79.8 (1982),第 2554-2558 页。eprint:http://www.pnas.org/content/79/8/2554.full.pdf.T11【11】w . a . Little。“大脑中持久状态的存在”。摘自:数学生物科学 19.1 (1974),第 101-120 页。
[12]赛普·霍克雷特和于尔根·施密德胡贝尔。“长短期记忆”。摘自:神经计算 9.8 (1997),第 1735-1780 页。
[13] Volodymyr Mnih,Nicolas Heess,Alex Graves 等,“视觉注意的循环模型”。载于:CoRR abs/1406.6247 (2014 年)。arXiv: 1406.6247。
[14]鲍勃·斯特姆、若昂·费利佩·桑托斯和伊琳娜·科尔舒诺娃。“通过具有长短期记忆单元的递归神经网络进行民间音乐风格建模”。英语。In:第 16 届国际音乐信息检索学会会议,晚破,西班牙马拉加,2015,p. 2。
[15] Sainbayar Sukhbaatar,Arthur Szlam,Jason Weston 等著《端到端存储网络》。载于:CoRR abs/1503.08895 (2015 年)。arXiv: 1503.08895。
【16】彼得·m·托德。“算法合成的连接主义方法”。在:13(1989 年 12 月)。
【17】伊利亚·苏茨基弗。“训练递归神经网络”。安大略省多伦多市多伦多大学。,加拿大(2013)。
【18】安德烈·卡帕西。“递归神经网络的不合理的有效性”。载于:安德烈·卡帕西博客(2015)。
贾森·韦斯顿、苏米特·乔普拉和安托万·博尔德斯。“记忆网络”。载于:CoRR abs/1410.3916 (2014 年)。arXiv: 1410.3916。

Python 中的递归,探索

原文:https://towardsdatascience.com/recursion-in-python-an-exploration-bfaa452d3260?source=collection_archive---------21-----------------------

图片来源,牌照

递归是那些看起来遥不可及的想法之一,可能来自编程存在的更高层次。a .你不知道它为什么是一个东西,b .你不认为你会需要利用它。毕竟,在撰写本文时, TIOBE 指数的前 10 名中还没有函数式编程语言。再想想,再想想…

也许你是对的,递归只对编码面试有用,否则就算了。然而,我认为学习不同的编程范例,以及它们解析问题的方式,最终会让你成为一名更好的数据科学家/程序员。学习一个新的范例会让你接触到新的思维方式和不同的代码结构。“这是我们一贯的做法”不会成为你这种态度的口头表达的一部分。因此,您将学到更多知识,并能更好地解决遇到的数据挑战。另外,如果你像我一样喜欢数学,让我们面对它,如果你在做数据科学,不喜欢数学,那么现在就离开(抱歉的语气,我爱你),然后你会发现这项练习本身就是令人愉快的。

什么是递归?

为了介绍递归,让我们做一个简单的、假设的例子来比较解决方案。您有一个数组或一个数字列表,在被程序的其余部分使用之前,需要对它们求平方。我们可以使用 python 中的循环或列表理解来创建平方版本。

# Set array
my_array = [10,11,12,13,14,15]# Method 1
# Create a new squared array with for loop (can be considered an anti-pattern)
squared_array = []
for num in my_array:
   squared_array.append(num*num)# Method 2
# Create a new squared array with list comprehension, a bit more beautiful and concise
my_squared_array = [x*x for x in my_array]

通常,当我们在 Python 这样的命令式语言中循环值时,我们使用 for 循环或 while 循环。这些是我们已经习惯的概念,我们经常使用它们,它们是我们的第二天性。但是如果 for 和 while 循环明天被 python 砍掉了呢?除了世界上大部分停止运作,我们还有更紧迫的问题…现在如何使用递归??

递归简介:平方数组

我们不能使用列表理解,所以让我们使用新的 pal 递归来平方我们的数组。为此,我们需要编写一个新的函数。

# Set array
my_array = [10,11,12,13,14,15]# Define our recursive, squared function that returns a new array
def squares(an_array, n=None, ret_array=None):
   if n == None:
      n = len(an_array)
      ret_array = []
   pos = len(ret_array)
   squared = an_array[pos] ** 2
   ret_array.append(squared)
   if n-1 == 0:
       return ret_array
   else:
       return squares(an_array, n-1, ret_array)

好吧,当一个列表理解就足够了的时候,这有点丑陋和冗长,但是它表明我们可以使用递归来代替 for 循环。该函数首先初始化一个保存平方值的新数组,使用 n 作为计数器来确定我们在按位置遍历数组时的位置,然后它调用自己,直到我们遍历了整个数组,随后得到新的平方数组。

有用的提示

把递归函数想象成一段代码,它不仅仅驻留在内存中的一个地方。当然,函数是在一个地方定义的,但是当数据传入时可以多次调用。这被称为调用堆栈。不要把它想成一条蟒蛇在吃自己的尾巴,尽管许多 R 用户会欢呼。想象一下,一群克隆人传递一个小盒子,每个人放入一枚硬币,然后将盒子传递给下一个克隆人。好吧,也许现在你更困惑了。回顾以下三个案例将有助于你理解这一点,并消除你可能有的任何困惑。

递归案例 1:标准阶乘

让我们用递归来做每个接触过递归的人都做过的事情,计算一个阶乘。还有谁爱离散数学!?

def factorial(num):
    if num == 1:
        return 1
    return num*factorial(num-1)

n 的阶乘(记为 n!)是所有小于 n 的正整数的乘积,是对定义为 n 的任意数的运算!= n (n-1)(n-2)……(1!),其中 1!= 1.这就是我们代码中所说的停止条件。这个想法对递归非常重要,因为没有它,我们的代码可能会进入无限循环,导致“时间悖论,其结果可能会引起连锁反应,破坏时空连续体的结构并摧毁整个宇宙。”—布朗博士

S ay 什么?

这里有一个有用的方法来形象化 4 的阶乘函数。。

阶乘(4)= 4 阶乘(3)= 4 * 3 阶乘(2)= 4 * 3 * 2 阶乘(1) = 4321 = 24

factorial 函数的每个实例都与我们在 def factorial() 中定义的相同,但它是一个新的实例,接受前一个 factorial 函数实例的结果并传递一个新的结果,所有这些都从基本情况 1 开始,在这种情况下,所有这些都将累积到最终计算中。

递归情况 2:前 N 个整数的和

下面是如何使用递归对 0 和 n 之间的整数求和

def sum_n(n):
    if n == 0:
        return 0
    return n + sum_n(n-1)sum_n(1000)Outputs: 
500500

让我们用相同操作的封闭形式来检查我们的结果,以确保我们正确地定义了递归函数。抽查总是一个好主意,因为正如理查德·费曼所说:“首要原则是你不能欺骗自己——而你是最容易被欺骗的人。”在报价中插入我和我自己,使其个性化。

def check_sum(n):
    return int(n*(n+1)/2)check_sum(1000)Outputs:
500500

递归案例 3:复利

你可能以前见过复利的公式。

因为我们有一个指数的数字(1+r ),那么我们可以使用递归来计算我们的未来值 FV。

def future_val(pv, rate, t):
    if t == 0:
        return pv
    pv = pv*(1+rate)
    return future_val(pv, rate, t-1)

前面的函数假设复利 n=1。这意味着我们每个周期 t 只复利一次,这里 t 通常是指一年的时间。让我们扩展我们的例子,以包括不同的复合利率,如每月。

def future_val_n(pv, rate, t, n):
    if t == 0:
        return pv
    pv = future_val(pv, rate/n, n)
    return future_val_n(pv, rate, t-1, n)

我们已经能够回收我们的 future_val 函数,并扩展它,使我们在每个时间段 t 内复利 n 次,我们的函数起作用吗?

future_val_n(1000, 0.07, 20, 12)Outputs:
4038.73# Now we check our value from future_val_nprint(1000*(1+0.07/12)**(20*12))Outputs:
4038.73

最后的话

记住一些事情

  1. 我们不一定要有一门纯函数式语言才能开始在我们的代码中使用函数式编程技术
  2. Python 不是一种纯粹的函数式语言(当然),但借鉴了它们的许多特性,比如作为第一类对象的函数和命名一对夫妇的列表理解。

考虑到这两点,我们意识到 python 对函数的递归调用次数有限制。此限制定义如下:

sys.getrecursionlimit()Outputs:
3000

如果我们在 n>3000 的情况下运行 sum_n 函数,它将抛出一个 RecursionError ,即使该函数适用于小于限制的递归深度。这是在将这些类型的函数合并到 python 代码库时需要考虑的事情。

既然你已经知道了递归,你将开始用不同的方式看待事物,也许你的下一个项目会有一些创造性的解决方案。我希望这是对递归和函数式编程范例的有趣而有启发性的介绍!

Python 中的递归

原文:https://towardsdatascience.com/recursion-in-python-b026d7dde906?source=collection_archive---------32-----------------------

理解 Python 中的递归

来源

在计算机科学中,递归是一种使用同一问题的较小解来寻找问题的解决方案的方法。递归算法在列表排序、二叉树遍历、路径查找等等方面都有应用。在本帖中,我们将讨论一个用于寻找自然数阶乘的经典递归过程。

我们开始吧!

因为我们将编写一个算法来寻找阶乘,所以有必要回顾一下阶乘的定义。自然数的阶乘, n ,是所有小于或等于 n 的自然数的乘积:

例如,如果 n =6:

让我们递归地思考这个问题。如果我们有一个递归函数 f ,我们想用 f 来计算 6!以下面的方式:

6!= f (6)

f (6) = 6* f (5)

f (5) = 5* f (4),所以f(6)= 6 * 5 **f*(4)

f (4) = 4* f (3),所以f(6)= 6 * 5 * 4 **f*(3)

f (3) = 3* f (2),所以f(6)= 6 * 5 * 4 * 3 **f*(2)

f (2) = 2* f (1),所以f(6)= 6 * 5 * 4 * 3 * 2 **f*(1)

f (1) = 1,所以 f (6) = 65432*1。

为了在 python 中实现这一点,我们需要定义一个函数,我们将调用“recursive_factorial”,它接受输入 n ,并返回n** recursive _ factorial(n*-1)。此外,我们希望函数不断返回自身,直到输入等于 1。此时,我们返回 1,递归终止。为了实现这一点,我们执行以下操作:

def recursive_factorial(n):
    if n == 1:
        return 1
    else:
        return n*recursive_factorial(n-1)

另外,我们应该处理 n =0 的情况,给定 0!=1.让我们适当地改变 if 语句:

def recursive_factorial(n):
    if n <= 1:
        return 1
    else:
        return n*recursive_factorial(n-1)

另一件值得注意的事情是,我们的函数不处理负数。这个方法只对自然数和零有效。

我们来考虑一下这个函数对于 4 来说是做什么的!:

We have to calculate recursive_factorial(4).The function asks, is n = 1? No, n=4, so let's return 4*recursive_factorial(4 - 1), which is 4*recursive_factorial(3).Now we have to calculate recursive_factorial(3). Is n = 1? No, n=3, so let's return 4*3*recursive_factorial(3 - 1), which is 4*3*recursive_factorial(2).Now we have to calculate recursive_factorial(2).Is n = 1? No, n=2, so let's return 4*3*2recursive_factorial(2 - 1), which is 4*3*2recursive_factorial(1).Now we have to calculate recursive_factorial(1).Is n = 1? yes, n=1, so let's return 4*3*2*1.

其中 n > 1 的情况称为递归情况,当 n < = 1 时,我们有基本情况。

根据这一逻辑,recursive _ factorial(4)= 4 * 3 * 2 * 1 = 24。让我们验证一下:

def recursive_factorial(n):
    if n <= 1:
        return 1
    else:
        return n*recursive_factorial(n-1)
print("4! =", recursive_factorial(4))

让我们试试前面的例子,6!:

print("6! =", recursive_factorial(6))

我将在这里停下来,但是您可以随意摆弄代码。如果你有兴趣学习更多关于递归的知识,python-course.edu 是一个很好的资源。

总之,在这篇文章中,我们讨论了如何编写一个递归算法来寻找一个自然数的阶乘。递归算法的其他经典应用包括汉诺塔问题和第 N 个楼梯问题。我希望你觉得这篇文章有用/有趣。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

Python 中的递归函数

原文:https://towardsdatascience.com/recursive-function-in-python-36f8b833c847?source=collection_archive---------22-----------------------

数据科学

数据科学领域的例子

照片由Tine ivani在 Unsplash 上拍摄

目录

  • 什么是递归?
  • 程序设计中的递归
  • 来自数据科学世界的例子
  • 结论

什么是递归?

递归是一个在操作中引用自身的概念。这在所有艺术领域都可以找到:文学(mise en abyme)、绘画、摄影……
一个物理世界的例子是将两个平行的镜子面对面放置。它们之间的任何对象都将被递归反射。
我们每天在定义词的时候都会用到递归!事实上,我们用词来定义他人,而他人也被其他词所定义!

程序设计中的递归

在编程中,它是一个引用自身的函数。两个函数可以互相调用,这叫相互递归。让我们用一个数学界的例子:阶乘。自然数n的阶乘是小于等于n的严格正整数的乘积。记为n!,计算如下:n! = (n-1)!*n

在你的头脑中运行这个算法,你会发现它永远不会停止,它会无休止地运行。的确,如果我们用n = 3执行函数,T5 会被n = 3调用,然后n = 2,然后n = 1,然后n = 0,然后n = -1,等等。

一个永不停歇的算法是个问题,可想而知!

因此,解决方案是指定一个停止条件,这将始终取决于我们的问题。在我们的例子中3! = 3*2*1。您会注意到不同的因子(3、2 和 1)从不为负,甚至不等于 0。正是这个条件为我们提供了一个停止条件:“因子决不能小于或等于 0”。所以,我们添加一个条件语句:

在函数内部调用函数被称为递归调用。

递归调用必须在条件语句中。

注:每一次递归都可以转化为迭代。

来自数据科学世界的例子

1.二叉树结构的表示:

二叉树是由称为节点的元素层次结构形成的数据结构。节点由两类信息表征:

  • 节点特定信息
  • 描述与其后代节点的链接的信息

二叉树总是由一个节点指定:它的初始节点叫做根节点。
每个节点最多有两个子节点:

  • 如果该节点正好有两个子节点,它们被称为 t 左子节点右子节点
  • 如果该节点只有一个子节点,这是左子节点或右子节点。**
  • 如果节点没有子节点,它被称为叶节点

树枝是从树根到树叶的路径。

因此,二叉树是一个递归结构,因为左子树和右子树本身就是节点(依次代表树)。

二叉树图。源作者

这个图表示一个二叉树,它的节点 A 是根,B 是它的左孩子,C 是它的右孩子。节点 C 只有一个子节点 F(右子节点)。d、E 和 F 是叶节点。
【A,B,D】,【A,B,E】,【A,C,F】是树的分支。

让我们创建类节点:

属性:

  • 标签 :表示观察的字符串。
  • :表示左子的类的实例。
  • right :代表右孩子的类的实例。

方法:

  • init: 构造函数。
  • str: 根据以下示例返回表示树的字符串
  • 线性化: 递归方法返回一个树形分支列表。
NodeFigure = Nd = Node('A',Node('B', Node('D'), Node('E')), Node('C',None,Node('F')))**>>> print(NodeFigure)**
Node(A,Node(B,Node(D),Node(E)),Node(C,None,Node(F)))

2.决策模型的表示

数据集表的切片

决策规则可以用二叉树来表示,称为二叉决策树。例如,对于下表中的数据集,可以构建下图所示的二元决策树。

在这一部分中,我们将创建 DecisionNode 类,它从 Node 类继承并表示一个二叉决策树。

属性:

  • 标签 :表示观察的字符串,继承自 Node 类。
  • distr :代表每个决策概率的字典:
    ——每个代表一个可能的决策 0 或 1。
    -每个都是一个代表决策概率的实数。
  • threshold: 一个实数代表测试阈值,用来推导要跟随的分支。
  • left :表示左侧子节点的类的实例,继承自 Node 类。
  • right :代表右子的类的实例,继承自 Node 类。

方法:

  • init: 构造函数(从节点继承)
  • str: 根据以下示例返回表示树的字符串
#Create the instance
left = DecisionNode('Decision', {0:0,1:1}, 0.5)
right = DecisionNode('Age',{0:0.5, 1:0.5},62,
                     DecisionNode('Decision', {0:0.2, 1:0.8},0.5),
                     DecisionNode('Tachycardia',{0:0.4,1:0.6},0.5,
                         DecisionNode('Decision',{0:0.1, 1:0.9},0.5),
                         DecisionNode('Decision',{0:0.9, 1:0.1},0.5)) )
DecisionNd = DecisionNode('Blood Pressure', {0:0.3,1:0.7},91, left, right)**>>> print(DecisionNd)**IF Blood Pressure >= 91  THEN Decision = {0: 0, 1: 1}
IF Blood Pressure < 91 AND Age >= 62  THEN Decision = {0: 0.2, 1: 0.8}
IF Blood Pressure < 91 AND Age < 62 AND Tachycardia >= 0.5  THEN Decision = {0: 0.1, 1: 0.9}
IF Blood Pressure < 91 AND Age < 62 AND Tachycardia < 0.5  THEN Decision = {0: 0.9, 1: 0.1}

简而言之:如何编程一个递归函数?

  1. 将问题分解成一个或多个同类型的子问题。子问题通过递归调用解决。
  2. 子问题应该比原问题小。
  3. 最后,分解必须产生一个不分解成子问题的基本问题(这是停止条件)。

资源:

  • http://www.ipeis.rnu.tn/concours_nationaux/concours.htm
  • https://www.geeksforgeeks.org/recursive-functions/

感谢阅读!😄

查看我的其他文章,并在媒体上关注我

哈利菲·艾哈迈德·阿齐兹

使用 PostgreSQL 的递归 SQL 查询

原文:https://towardsdatascience.com/recursive-sql-queries-with-postgresql-87e2a453f1b?source=collection_archive---------2-----------------------

公共表表达式是 SQL 的一个鲜为人知的特性,它使得编写递归查询成为可能。让我们用 PostgreSQL 来探索一下吧!

照片由卢德·洛伦兹在 Unsplash 上拍摄

在使用数据库时,大多数时候,你需要的只是SELECTUPDATE (CRUD 操作)、几个JOINWHERE子句,仅此而已。但是,有时您会遇到数据集和任务,这将需要您使用更高级的 SQL 功能。其中之一是 CTE 或公共表表达式,更具体地说是递归 CTE ,我们可以用它来进行递归 SQL 查询。让我们看看它是如何工作的,我们可以用它做什么!

为什么是递归查询?

首先,为什么这实际上是一件事?递归查询有什么好处?—通常,当处理自引用数据或类似图形/树的数据结构时,递归查询很方便。这些使用案例的几个例子是:

自参考数据:

  • 经理- >下属(员工)关系
  • 类别- >子类别- >产品关系
  • 图表—飞行(飞机旅行)地图

树木:

  • 任何分类系统——书籍、动物、遗传学…
  • 文章之间的链接——例如在维基百科上
  • 评论部分—例如 Reddit 上的主题

对于这些示例中的任何一个,都需要您构建临时表或使用游标来从这样的数据集中获取有用的数据。现在,我希望让您相信递归查询非常有用,让我们看看它们是什么以及如何使用它们。

我们需要什么?

递归查询利用了一种叫做 CTE 的东西——公共表表达式,它是 SQL WITH子句,更常用于简化非常复杂的查询(子查询)。让我们来看一个例子:

这是一个非常简单的例子,但是您可以想象如何使用它来使包含多个子查询的非常复杂的查询更具可读性。

除了上面的语法,我们还需要一些可以用于递归查询的数据。为此,我们将使用经理-下属层级,使用一个自引用表,定义如下:

员工表

下面的 SQL 创建了这样一个表,其中包含一些要使用的数据:

所以,现在我们来构建一些递归查询吧!

重复是人类的,重现是神圣的——l·彼得·多伊奇

递归

让我们从递归 SQL 查询的正式结构开始:

它看起来很简单,但并没有告诉我们太多,所以让我们看一个人类可读的例子:

该查询的输出是:

在这个例子中,我们的非递归基本情况只是SELECT 1,递归部分是SELECT n+1 FROM nums WHERE n+1 <= 10。这部分通过引用 CTE ( nums)的名字并联合所有结果来创建递归。最后,我们有WHERE子句来终止递归,这样我们的查询就不会无限地运行。

真实世界的例子

前一节展示了一个非常基本的例子,解释了它是如何工作的,但并没有真正展示递归 CTE 如何帮助我们。因此,让我们使用上面的经理-下属层级数据来看一些例子:

为某些员工获取【经理树】:

这个查询可以用来生成某个经理的所有下属的列表,它实际上是从某个特定雇员开始的子树。作为这里的一个基本案例,我们通过 ID 选择一个员工(经理),我们还包括了level,以表明我们在树中向下走了多少层。在递归部分,我们使用经理 id 将雇员表从 T5 转到 CTE。同样,我们通过增加上一步递归的结果级别来包含level。这是输出:

为了更好地想象那里发生了什么,请看下面的树。突出显示的部分是查询返回的内容:

另一个使用相同数据的实际例子是计算两名员工的离职程度:

递归 CTE 与前一个例子非常相似。为了简单起见,我们只选择 ID 和degree(而不是等级)。接下来,我们需要一个查询来查找并告诉我们两个雇员的离职程度——为此,我们将employees表连接到我们之前构建的包含 id 的rec表,并在各自的表中使用 id 连接degrees。在最后的SELECT部分,我们做了一些格式化以获得更好的输出,在WHERE子句中,我们可选地指定另一个(第二个)员工,我们希望得到他们的离职程度。输出:

同样,用同样的数据,让我们来看看在假设的公司里工作进展可能是怎样的:

这次我们从下往上运行递归。与前面的例子相比,这是通过翻转ON子句来实现的。为了创建可读的输出,我们使用了STRING_AGG函数,它从SELECT上面获取行,并使用>作为分隔符将它们连接起来。这是查询给我们的结果:

图的递归

足够多的雇员数据集,让我们探索一下我们能用图做什么——图作为一种数据结构是使用递归进行遍历的理想选择。因此,让我们首先定义一个简单的表并插入一些数据,这样我们就有东西可玩了:

图表

作为一个例子,我们将做一件显而易见的事情——用图的形式寻找路径。为此,我们将需要一个特殊的数据类型PostgreSQLARRAY。数组不是常见的关系数据库特性,但在这里存储路径非常方便。如果您不熟悉这种数据类型,下面是理解 SQL 所需的一些东西:

  • 创建阵列— ARRAY[value_1, value_2]
  • 串联数组— ARRAY[value_1, value_2] || ARRAY[value_3]
  • ALL函数- "x" != ALL(ARRAY["a", "b", "c"]) -将"x"与数组中的每个值进行比较,如果所有比较的结果为true,则结果为true

好了,现在是问题:

上面的查询首先选择非递归情况下的所有直接邻居。然后在递归部分,我们建立在基础情况上(并且在随后的迭代过程中在先前的递归情况上),并且将可用的边附加到现有的路径上,并且用相同的边替换目的地。我们对现有路径的终点(dest)与所选边的起点相同且新目的地尚未在路径中的每一行都这样做(以防止循环)。这是全部输出:

除了上面有用的东西,你还可以对无限数据流使用递归 CTE :

递归表是通过每一步迭代构建的,每一步产生有限数量的行,因此可以使用LIMIT从无限查询中检索第一个n行!

额外收获:递归视图

作为一个小奖励,我还想展示一下(从 PostgreSQL 9.3 开始)甚至可以创建递归视图:

尽管这只是语法上的好处,但在处理一些递归查询和数据时,它会让您的生活变得更加轻松。

结论

递归是一个非常强大的工具,它能以一种非常优雅的方式解决一些问题。不过,在 SQL 中使用它并不常见,所以希望本文向您展示了如何利用它的一些方法,以防您遇到只能递归处理的数据。

然而,递归会降低代码的可读性,所以要谨慎使用,尤其是在 SQL 中,因为即使没有递归,解析和理解也不是那么容易。

本文原帖martinheinz . dev

红色标记!!一个简单的分数如何影响你的一生。

原文:https://towardsdatascience.com/red-flagged-how-a-simple-score-can-affect-your-life-e6bc2d6b76ec?source=collection_archive---------39-----------------------

欺诈和数字支付的问题

Yaneev 由 Pixabay 提供

在过去的学生时代,当人们用现金支付工资时,在借记卡、信用卡或在线商务出现之前,装甲卡车在街上游荡,将现金送到工资发放办公室,在那里,钱会被及时清点并装入棕色的小信封,然后发给工人。

现金仍然与数字支付流分层,但政府打击黑市经济、避税和犯罪洗钱,以及打击恐怖主义融资,意味着一个越来越西方化的无现金社会。

当然,这样做的问题是,不是现金所有者的人可能会欺诈性地获得资金。由于商品供应和支付之间的数字距离,识别资金操作者是否实际上是所有者的核心问题,这个问题在现金中不存在,因为资金与支付令牌是分开的,现在变成了一个问题。

银行如何努力消除信用卡欺诈是我们得分的开始

因此,接下来发生的是,每个卡支付事件都应该经过两级验证:

  1. 支付事件本身及其与客户账户主记录以及地理位置、数量、终端 IP、时间、购买模式的关系;和
  2. 通过“弹出框”、手机应用程序或输入全名、出生日期和地址,对账户持有人的身份进行强有力的支付事件认证;例如,还匹配送货和帐单地址。

所以,如果我住在澳大利亚,但一组来自保加利亚的欺诈性信用卡交易被阻止了?公平的决定。但那会留在我的记录里。

由于澳大利亚一家典型的大型银行每月处理高达 1.3 亿笔支付,因此根据公开的 Kaggle 信用卡欺诈训练数据集可以粗略推断,只有 0.172%的交易被确认为欺诈。如果 1.3 亿笔支付中有一半涉及银行卡,那么一家银行每月仍有约 11.2 万笔潜在的欺诈性银行卡交易。

尽管信用卡和借记卡号码内置了使用 Luhn 支票进行验证的功能,CVV 号码也有所帮助,但通过黑客、ATM 盗用、在线盗用和社交工程非法获取的大量卡号在网上随处可见,这意味着这是电子商务领域最大的问题之一。

在大多数在线欺诈案例中,如果欺诈不是由客户实施的,那么如果信用卡存在(CP),作为发卡机构的银行将承担损失。在使用 EFTPOS 商户终端而没有卡(CNP)的在线交易中,损失由商户承担。澳大利亚的商户每年花费大约 5 亿澳元来解决无卡欺诈。因此,这是一个很大的问题,它会侵蚀商家的利润空间,还会导致废弃的购物车,商家会理所当然地说“我不能确定你就是你”。也是发卡方在冻结后重新发卡的成本。

虽然 1 级和 2 级验证是绝对有保证的,以防止有动机和机会的预谋的匿名黑客,但这变得有些复杂的是“风险分数”的概念,它基于客户自己实施欺诈或实际上成为欺诈受害者的倾向。

分数(满分为 100 分)类似于信用评分。日常客户实施的典型欺诈是应用程序欺诈。比如在申请增加信贷时虚报收入。“分数”会根据你的生活事件而变化,尤其是失业、关系破裂或破产…

澳大利亚犯罪学研究所,趋势与问题№2019 年 4 月 577 日

…此外,账户持有人同事的行为——已知同事的网络和他们的“分数”——会影响账户持有人的倾向“分数”,反之亦然。也就是说,如果一个已知的合作伙伴被证实从事欺诈活动,它会影响到你。

他们怎么会认识你的同事?很容易,通过脸书或推特。通过你付钱给的人,或者他们付钱给你的人,你的联系人。通过他们自己的 CRM 系统主数据层次结构。

这些分数也适用于那些被发现以低评级或高回报为基础欺骗顾客的商家。

不仅仅是银行用这种方式跟踪我们。

2020 年

Airbnb 显然不以执行自己的政策而闻名,在收购在线背景调查公司“Trooly”后,它正在应用类似的自动化方法对客户和主人的“特质”进行描述和评分,如精神变态或自恋:

该专利称,博客和新闻网站上的帖子也被考虑在内,以形成“人物图”

使用 NLP 技术的特质分析是一种语言分析形式,它要么使用单词的分类法及其上下文来对情绪进行分类,这种情绪被映射到性格模型,在基本级别上类似于 Myers-Briggs,甚至是自动编码。这是更进一步,使用 ML 技术来判断你的在线“个性”,并标记和过滤掉危险行为属性的申请人。还有一个事实是,现在很容易识别发布的不当图片,并将其计入信任“得分”。

因此,如果 Airbnb 可以这样做,从而终身禁止顾客,那么拼车平台也可能这样做,或者易贝或亚马逊等。

为什么这有问题?

以这种方式将 ML/AI 技术应用于风险/信任评分人员的问题在于:

  1. 出错的倾向;
  2. 人类个性的浅薄模型被用来对人进行自动分级和评判;
  3. 缺乏赎罪的机会;和
  4. 强化学习居然漏进社会培训美国

在出现错误的情况下,银行有可能为你的情况辩护,事实上,你可以去找调查官并花费精力来纠正这种误解。信不信由你,在这些事情上,银行实际上是高度诚信的。对于像 Airbnb 这样的私人组织,投诉可能会被置若罔闻。

因为可能给我们打分的模型是基于数据的,并且在后台自动运行,所以对它们和它们的理论基础(如大脑的计算理论)进行争论将变得几乎不可能。

此外,一些用于做这件事的 DNN 技术由于它们的黑盒性质而无法解释。这意味着,一旦被标记,不管是对是错,那面旗帜就好像我们衬衫背后的一个污点,可能永远不会被发现;由于许多非政府组织不受信息自由或监察员的监督,国旗可能会禁止赎回的可能性。

当我们凭经验学习这些评分“游戏”的规则时,这些规则在获得资金、住宿或交通的可用性方面对我们产生了真正的影响,我们是否会自己受到训练和约束,以双向机器-人类模式的性质来缓和曾经被视为普通的自由言论?

现在自动获得的言论自由,以及在我们同意下被评分算法断章取义的【1】限制了我们现在拥有的令人惊叹的社交工具的潜力。如果我们的同事被发现有所欠缺,他们自己的分数会影响我们的分数,这是因为像脸书这样的社交媒体所依赖的网络或图表的性质。

使用这些评分技术的公司的权衡是,如果他们过于积极地训练模型,以最大限度地降低风险,假阳性率将增加到这样的程度,即受到不当惩罚的客户将流失并找到替代方案,从而降低品牌资产和股东价值。

这里的一个解决方案是进行人工调查审查,但这很昂贵,而且使用 Keras 和 CloudML [2]等技术的 DNN 技术自动编码分数,无论如何都不可能,而且数量非常大。

随着这些评分型方法渗透到日常生活的更多方面,试图消除风险并增加未知参与者之间的信任,我认为我们将开始看到评分模型本身的强化奖励和惩罚成为我们必须遵守的政治正确性的一个方面,因为社交媒体表达中的语言变得越来越狭隘,基于互联网的对话的新私人渠道越来越多地出现在主流的审查之外【3】。

脚注

[1]通过服务的隐私条款,您可以了解他们在法律上有权以“研究”为目的共享数据。例如:https://policies.google.com/privacy?hl=en#infosharing

[2]尽管可以使用修改的随机森林模型作为分类器。

【3】类似茧的私人微网。

红色或蓝色标志:切断正确的电线。

原文:https://towardsdatascience.com/red-or-blue-flag-cut-the-right-wire-7a19f57c85b5?source=collection_archive---------34-----------------------

旗帜图案的阴暗面带来了数据库噩梦。看了才信。

你记得九十年代的动作电影吗?其中一半有炸弹,英雄必须拆除它。我在 IT 环境中看到了同样的情况。睡不好的次数太多了。你不相信吗?嗯,有一种炸弹进入了软件,它的名字叫做 flag。我会解释原因。

旗帜和独角兽的故事

曾经有一段时间,软件躺在旗子上。我们可以称这个时代为“旗帜时代”。那是它的中世纪时代。那时没有任何团队或开发流程。你是开发人员(与“印刷工人”没有太大区别),有人拍拍你的肩膀开始一项任务或解释一项业务需求。好吧,如果你太年轻不知道,或者太老不记得,我会试着告诉你。想象一下这种情况。像往常一样,你是开发者。你开发了一个订单输入表单。那时,后端和前端之间没有任何区别。你必须完成工作,而不仅仅是一部分。幸运的是,您的应用程序工作正常,许多用户可以使用您编写的程序完成销售订单,没有任何限制,除了它是一个控制台应用程序这一事实。有一天老板来找你,拍拍你的肩膀(可能他不知道什么是电子邮件!)而责怪软件是因为有人在订单关闭后更改了销售订单。所以,你浪费了五分钟来解释软件是好的 bla,bla bla…但最后,你不得不改变软件。更简单的解决方案是什么?只需在销售订单表中添加一个布尔列,称之为“已发送”,如果它是真的,则不能更改销售订单。真或假足以定义程序的行为。好吧,你完成了工作,然后高高兴兴地回家。上任的第二天简直是地狱。流向 WMS(仓库管理系统,或者新手的“谁把你的产品送到商店”)的数据流失败了,你有数千个订单因此而受阻。老板在尖叫,所以你必须跑到 BI 办公室,明白桌子上新的血淋淋的柱子把一切都打碎了。世界得救了,老板却又来找你。他非常愤怒,因为有人能够在订单已经包装但尚未发货的情况下更改销售订单。好吧,接下来呢?您是否会向表中添加另一个布尔标志,这可能会导致 ETL 的另一个中断?绝对没有。在那个时候,改变数据库中的某些东西是相当昂贵的,并且许多应用程序共享同一个数据库。此外,公司像筒仓一样工作,改变一个数据库中的一点可能会中断到其他系统的数据流,通过 ETL 在一夜之间严格地移动。你迟早会从皮肤上学会的。

解决方案很简单,您将列从 boolean 改为 char(一个 char 允许使用英语字母表的 26 种可能性,并且您可能有很多机会获得有意义的字母)。您跑到 BI 办公室请求更改,给出的规则是:“只考虑州‘S’中的行,因为‘S’代表‘shipped’”。你没有在代码中对此写任何评论。你没有写任何文档。很明显。“S”代表“已装运”。为什么我应该忘记它?

但是随着时间的推移,你使用了几乎所有的字母来满足所有的业务需求。您引入了如此多的订单状态,以至于每次有人问您销售订单状态时,您都会感到头疼。即使在家里,当你在亚马逊上购物并收到确认邮件时。您在 BI 的同事已经退休,新同事不知道他必须接受标有 S、R、T、L 的销售订单,但不能接受日期比昨天早的 X 状态。很多人都在问为什么“特殊”状态是 X,而你不能回答“S”已经取自“发送”或者“X 在开始时听起来很酷”。但是最坏的情况是,当你有了一个新同事,他对你的销售订单状态编码一无所知,所以他创建了一个新的列。他不能称之为状态,因为已经有另一个人用了这个名字,所以他用了“进步”这个词。这意味着现在 BI 需要知道可以接受状态为 S、R、T、L 的订单,但不能接受日期早于昨天的 X 状态的订单,更不能接受进度标志设置为 28 的销售订单。(刚刚校对完最后一句,我有点头疼..).因为您的同事是第三范式的数据库纯粹主义者,所以他使用了一个外部表来列出所有可能的进度值。偶尔,一些订单没有发货或有一些延迟,当你想到销售订单时,你仍然有些头痛。一切都很正常,就像过去 30 年里一样。你微笑。明天你就要退休了,所有的麻烦都会流向你的新同事和它的第三人称数据库。

带什么回家

我希望你在读这个故事的时候笑一笑。任何与事实或你可能认识的人的相似之处完全是巧合😃标志是操纵应用程序业务逻辑的一个很好的选择。一切都是通过改变数据发生的。确实如此。

与旗帜相关的问题有哪些

标志的问题在于,它并不总是清楚标志的改变对应用程序的影响是什么,或者你需要什么样的改变来获得期望的行为。这是因为应用程序的逻辑在源代码内部。源代码可能有数吨行,可能由许多人花费大量时间编写。此外,事实上,在大多数情况下,开发人员都很匆忙,没有时间处理文档……嗯,标志管理可以在几分钟内变成地狱。

穷人旗帜规则

以下是一般规则的简短列表:

  • 并不总是有参考的表格才是解决方案。一个标志仅仅是一个字母,你可能会被要求使用一个表格来增加更多的信息。这是真的,但是…谁来补充这个描述呢?我见过太多的解码表,有 PK、简短描述、详细描述和注释,其中的列是空的,或者只有无意义的文本,这让我感到厌烦。这让我实现了一个简单的咒语。以正确的方式做事,但要从头到尾。如果管理不当,引入空表只会增加开销。
  • 记录下来。每个概念只使用一面旗帜,清楚地列出可能的价值和结果。数据库中的表是一个很好的解决方案,但是隐藏了一些问题。首先,只有开发人员可以看到它,但分析师或项目经理也可能想知道 flags 是如何工作的。例如,哪些销售订单状态适合发送。第二,与没有任何格式的 1000 个字符的数据库字段相比,word 文档中有更多的空间来描述所有可能的场景。
  • 切勿剪断红色电缆。更换旗帜时,不能剪错线。先看文档。如果没有任何文档,请询问您的同事并仔细检查源代码。你发现的一切都必须记录在案,否则,我们将重新开始!

当标志起作用时

如果我让你相信旗子是邪恶的,请原谅我。可能我对这个工具的印象不好。基本上,数据库上的标志列只是一个枚举。当枚举足够好(完整且稳定)时,一切都会变好。这里有一些你需要满足的条件:

  • 标志必须只在一个地方定义一次。你需要一个完整的枚举,每个值都必须有解释
  • 标志必须只在一个地方定义一次。
  • 不能更改标志。如果在代码中定义,请将它们设为只读。枚举是一个不错的选择。
  • 每个标志值必须有一个含义。不要有一个“shipped”标志,如果填写了装运日期,则表示“Shipped ”,如果数据为空,则表示“Shipping”。
  • 使用有意义的名字。你不需要为角色付费,只需要使用它们。
  • 小心你赋予旗帜的角色。它是一行的状态还是驱动代码的一部分?

礼貌的结论

我们总是认为架构、基础设施和技术是软件成功的关键因素。有时候威胁来自内部。我的愚蠢的故事解释了一个糟糕的开发过程,糟糕的管理和沟通(书面和口头)的泄漏如何在噩梦中改变一个工作软件。

编辑医生病历中的敏感信息

原文:https://towardsdatascience.com/redacting-sensitive-information-from-doctors-patient-notes-51773a9c494b?source=collection_archive---------41-----------------------

从意大利案例看新冠肺炎 GCP 公共数据集(下)

本文是关于发布由医生关于受 COVID19 影响的患者的医疗记录组成的公共数据集的系列文章的第二篇。您将了解到用于编辑医疗记录中敏感信息的 Google Cloud DLP API。如果你还没有看过,你可以在这里找到第一篇文章。

向意大利医学放射和介入学会(图片鸣谢)

为了重申我对社区的承诺,我将通过意大利医学和介入放射学协会(ISMIR)发布的最新病例来更新公共数据库。如果,作为一个副作用,你可以学到一些关于 GCP 的东西,那么这个系列将会超出我的预期💪 🙏。这个管道中使用的代码可以在我的 Github repo 中获得。

顺便说一下,我非常自豪地看到社区正在考虑利用这些数据的方法。jérme mass ot提出的一种方法是利用该数据集并执行:

"用于知识图框架构建的抽取实体间的共现分析."

管道

谷歌云管道架构 v2

当涉及到编排管道时,Google Cloud 提供了几个选项,包括但不限于:

  • 云功能 (已实现):
    在本版本中,管道将由医生笔记 pdf 文档的上传触发。随后,Vision API 和 DLP API 将分别提取和编辑文本(意大利语)。然后结合 DLP API 的翻译 API 会被之前云函数发布的一条 pubsub 消息触发。最后,医疗实体的提取将从 GCE 上的虚拟机中进行(尚未实现自动化)。
  • Cloud Composer :(下一版本)
    该服务符合利用完全托管服务的愿望,Composer 将帮助在环境上更灵活地编排和调度该管道。
  • 云运行 :
    该选项也符合通过使用托管服务和自动扩展无状态容器来降低拥有成本的目标。一旦我们确定了所有的基础设施和环境细节,我们将把流程容器化。只有这样,我们才能准备好使用云运行。

云函数触发函数

当涉及到去识别(即屏蔽、编辑、替换)敏感信息时,在 GCP 上你实际上有两个选择:

1.医疗保健 API:
该服务专注于 DICOM 图像和 FHIR 资源中受保护的健康信息(PHI)【目前😉).由于管道从 pdf 中提取原始文本,这个 API 在这种情况下并不真正适用。

2.数据丢失防护(DLP) API(已实施): 根据您的使用情形,您将通过屏蔽、替换或加密数据来取消数据标识。在医疗记录的情况下,我选择使用(CryptoDeterministicConfig 转换)加密数据,这样,如果出于其他目的需要,我可以重新标识该数据(前提是我保留了最初用于取消标识数据的密钥)。

假设数据由来自意大利的医疗记录组成,它可能包含人们的个人信息,使得以下信息类型相关:
["名字"、"姓氏"、"女性名"、"男性名"、"个人名"、"街道地址"、"意大利财政代码"]

去识别码片段

数据集:

修订的数据集现在出现在 ISMIR _ redacted 表下的 publicbig query 数据集中。它对所有研究人员和贡献者公开。

查询公共数据集

查询公共数据集(修订的和原始的)的 Python 代码片段

观察:
1。我运行的一个实验是用相同的 INFO_TYPES 编辑意大利语和英语的相同文本,看看 DLP API 是否会编辑相同的字段。令我惊讶的是,这并不一定。挺惊讶的!不确定去识别在 DLP 背景中如何工作,但是从该实验中产生的一个假设是文本的语言可能导致候选人名字、姓氏…

2.根据第一项观察,当名称的来源不同于它们出现的文本语言时,DLP API 似乎显示出性能差异。以 67 号案例为例。当编辑来自亚洲的名字时(例如,陈、简谱和王、向和张…),DLP API 无法在意大利语文本中识别它们,而在英语文本中却能成功识别。

3.如果您使用加密转换:CryptoReplaceFfxFpeConfig,您将需要确保您使用的“alphabet”(参数)包含您试图修订的字段的所有字符。使用“字母数字”将涵盖[0–9A-Za-z]范围内的字符。如果您试图修订的文本包含符号$,您将需要创建一个自定义字母表。

学习内容:

  • DLP 😡:我不确定当前的世界形势是在考验我的耐心,还是因为民主党不太合作,但我确实在与它斗争。我遇到的一个困难是在 CryptoReplaceFfxFpeConfig 中使用“kms_wrapped”功能。它总是抱怨一些无效的输入。最近的几个开放 stackoverflow 问题(开放线程 1 和开放线程 2 )和 github 问题让我对自己的奋斗感觉更好。我最终屈服了,转而选择使用“解包”,生成了一个 AES 密钥,并用 base64 编码。
    一个建议是确定您的用例需要哪种转换(有用链接)。
  • 云功能😃:通过云功能实现自动化相当顺利。然而,为这条管道使用云函数是一个明显的考虑不周的错误。事实上,部分管道需要从 scispacy 下载和安装模型。然而,云功能只允许对每个实例化的环境进行有限的操作。因此,流水线是自动化的,直到必须使用 scispacy 模型提取实体并将其存储在数据存储中的步骤。
    一个建议是评估您的管道是否需要一些定制安装/环境。如果是这样的话,将其打包到一个容器中并使用 Cloud Run 可能是一个更好的选择。

就这样结束了!

我希望你喜欢这个系列的续集!如果你有什么改进的建议,请告诉我。此外,请分享您对 Google Cloud 面临的任何问题的反馈或意见。

我希望听到任何能够利用这个数据集和/或代码的人的意见。对你正在做的事情发表评论。

在家重新编辑—探索数据

原文:https://towardsdatascience.com/redditing-from-home-exploring-the-data-2303bcf5c58c?source=collection_archive---------64-----------------------

由 Unsplash 上的 chuttersnap 拍摄

【Redditors 熬夜的时间越来越晚了吗?用 Python 来了解一下吧。

毫无疑问,这个疫情打乱了我们的计划。我现在正在 12 点写这篇介绍,时不时地,我必须提醒自己今天是日历上的哪一天。

这个问题激起了我的好奇心——还有多少人经历过这个问题?作为一个长期的 Redditor,我想知道在这个非常时期,像 Reddit 这样的网站的使用模式是否会有所不同。毫无疑问,人们醒得更晚,睡得更晚——他们白天的作息略有改变,甚至被打乱。WFH,即学生在家学习,消除了通勤时间,这是社交媒体消费的重要黄金时间。

发现我的祖国 subreddit r/singapore 上的用户将如何改变他们的习惯肯定会很有趣。人们将如何着手分析这一点?

1.我们从一个假设开始

可以提出一个简单的假设:新加坡 Redditors 会熬夜到更晚,在晚上参与更多,而工作日早上的活动会减少。

我们还可以提出第二个假设:在新冠肺炎疫情期间,工作日和周末之间的使用模式差异将会缩小。本质上,工作日和周末将开始看起来一样。

假设

考虑到起作用的各种因素,我们可以做一些假设:

  1. 在此期间,大部分 Redditors 将呆在家里。
  2. 在选定的时间段内,由于新冠肺炎病毒引起的习惯变化将保持不变,假设封锁措施没有发生剧烈变化。

选择我们的数据集

Reddit 是巨大的。考虑到 r/Singapore subredit 上的大量每日提交内容,以及数据收集的限制,我们需要一个良好的数据分析范围。一个理想的选择:每日线程钉在子编辑的顶部。

你看,每天早上 6 点,会自动创建一个每日主题供用户发表评论。用户被允许分享他们生活中的任何事情:从他们的通勤,到他们的人际关系,甚至他们工作中的老板。

在这里,这些对话的性质是无忧无虑的,如果在网上看到一条【早上好】的信息,也不会令人惊讶。这些对话在一天内轻松积累了 1000 多条评论。

现在,如果我们收集新冠肺炎时期的所有这些帖子,并与之前的时期进行比较,看看评论的分布有什么不同,也许会出现一些有趣的模式。

2.数据收集

让我们首先决定调查的时间段。鉴于锁定措施在 2020 年 4 月初开始实施,如果我们认为用户习惯的改变需要一些时间才能生效,我们可以提前一周到 4 月中旬。我们比较了以下时间段:

  1. 2020 年 4 月 13 日至 2020 年 5 月 24 日【6 周】
  2. 2019 年 4 月 15 日至 2019 年 5 月 26 日 (6 周)

6 周的时间应该是一个足够大的数据集。我们将其与一年前的同一时间段进行比较,节省了几天的差异,因为我们希望该数据集也从周一开始。选择使用 2019 年的数据而不是 2020 年的开始月份是因为评论模式中可能存在季节性。这种季节性的一个例子是:学生由于年中考试而熬夜。

为了收集数据,我们需要某种 API 来提取数据。为此,我们可以使用 Reddit API 或 Pushshift API。

用 PRAW 刮螺纹

就个人而言,我更喜欢 Reddit API 提取线索的搜索功能。Python Reddit API 包装器(PRAW)易于使用,同时允许每分钟多达 30 个请求。

导入 PRAW 之后,我们在使用每个月各自的线程标题进行搜索之前,定义了 r/singapore 子编辑。下面是我们第一次搜索的例子:

import praw**#define subreddit**
subreddit = reddit.subreddit('singapore')**#make a search**
apr2019 = subreddit.search('random discussion and small questions April 2019')

在进行了所有相关的搜索之后,我们创建了一个字典来存储每个线程的细节。然后,我们开始添加到这本字典。

:我在代码中把每个 线程 称为一个 submission 。它们的意思是一样的。

submissions_dict = { 'title':[], 'created_utc': [], 'comms_num': [], 'id':[]}for submission in generator:
      submissions_dict['title'].append(submission.title)
      submissions_dict['created_utc'].append(submission.created_utc)
      submissions_dict['comms_num'].append(submission.num_comments)
      submissions_dict['id'].append(submission.id)

最后,我们将这个字典存储在一个熊猫数据帧中:

import pandas as pd
submissionsRaw = pd.DataFrame(submissions_dict)

是时候使用我们的数据框架了!以下是对新增栏目的简要总结:

  1. **timestamp** : 我们使用fromtimestamp方法来获得实际的日期时间
  2. **year** : 来源于我们新的timestamp栏目
  3. **dayOfWeek** : 使用weekday方法导出
  4. **typeOfDay** : 使用dayOfWeek,我们将日子分为工作日/周末。我们也可以通过假设工作日的公共假日本质上和周末一样来做一些调整。耶稣受难日就是一个例子。

我们将看到一个大致的数据框架,如下所示:

第一眼:周末的评论比工作日少

在排除了不在我们分析时间范围内的帖子后,我们最终会有一个名为submissions.的数据框架。让我们快速浏览一下数据透视表,按照yeardayOfWeek列对进行分组,并找出一周中每天的平均评论数:

似乎平均来看,2020 年的评论数有所增加。从我们制作的突出显示中,我们可以看出评论在一周的开始是最高的,而周末的评论数量最低。

有意思!你可能会认为情况正好相反…..

使用 Pushshift API 抓取注释

如果你认为我们结束了…不,还没有。我们仍然需要每个评论被写的确切时间!

我们将使用 Pushshift API 来收集评论。现在,Reddit API 可以做同样的事情,但是每个线程提取接近 1000 条评论(我们有大约 80 条)会相当慢。使用 Pushshift,您需要的只是惟一的线程 ID,它会在一个 JSON 文件中返回所有的注释:

在检查是否有空值之后,我们总结并在数据集中找到了超过 83,000 条评论。

3.让我们开始吧!

恭喜你坚持住了!最艰难的部分已经过去了。收集数据总是花费最长的时间,但这确实是最重要的部分。现在更有趣的部分来了:让我们观察一下我们的数据的分布。

我们将实验三种不同类型的图表,探索它们的优缺点。

小提琴情节

Violin 图是查看数据集中多个分布的好方法。我们将通过按照一天的类型来分离我们的数据,并查看一天中几个小时的数据分布来了解如何做到这一点。我们将使用 Seaborn 绘图:

sns.violinplot(x='subm_typeOfDay', y='comment_hour', hue='subm_year', data=commentsDf, split=True)

似乎我们的小提琴看起来更像鱼,而不是!但这并不奇怪。很自然,在凌晨 3 点到 6 点之间几乎没有人会醒着发表评论(也许除了我)。

以上信息并不像我们希望的那样丰富。这是因为 violin 图是平滑的,只是为了给出数据的整体形状,并给我们一个粗略的想法。然而,我们可以比较这些峰值,以查看哪些时间具有更高的概率密度,我们可以看到 2020 工作日似乎在午夜具有更高的峰值。

但即使知道了这一点,还是很难给出一个数字。精确的点被添加,并使用一个你可以轻松操作的带宽进行平滑。通过添加一个参数bw,您可以看到如果将带宽降低到默认值以下会发生什么:

sns.violinplot(x='subm_typeOfDay', y='comment_hour', hue='subm_year', data=commentsDf, split=True, **bw =0.05**)

这几乎没有任何帮助。

不过,我还是有点喜欢下面的情节:

sns.violinplot(x='subm_year', y='comment_hour', hue='subm_typeOfDay', palette='Set2', data=commentsDf, split=True)

你可以看到 2019 年的数据在工作日和周末之间有相对不同的形状。工作日午夜的活动比周末少。

而 2020 年的数据看起来更加对称。我们鱼的尾巴看起来几乎 完美。我们的第二个假设是 Redditors 几乎分辨不出工作日和周末的区别,这个假设可能是正确的。

但形状只是形状。让我们潜得更深!

直方图

直方图在查看单个条柱时更好,在本例中,条柱是一天中的小时。如果你没有注意到,我们之前的图中的小提琴实际上超过了 0-24 小时,这发生在我们使用概率密度的时候。所以这并不是最理想的表现,但也够烦人的了。

我们现在将使用 Matplotlib 的直方图,同时使用“seaborn”样式使其不那么难看:

**plt.hist**(comments19['comment_hour'], bins = bins, alpha = 1, edgecolor = 'white', label = '2019')
**plt.hist**(comments20['comment_hour'], bins = bins, alpha = 0.66, edgecolor = 'white', label = '2020')

为了让眼睛更容易看到,我们可以将 2020 年的数据叠加在 2019 年的数据上,降低其不透明度以进行比较。我们注意到,2019 年只有早上 6 点到 9 点有更多的评论。一天其他区间,2020 评论较多。然而,有些事情不太对劲。如果评论的增长是由用户的增长推动的会怎样?

让我们通过比较每个区间的相对频率来使其更加公平:

plt.hist(comments19['comment_hour']/3, bins = bins, alpha = 1, edgecolor = 'white', label = '2019', **density = True**)
plt.hist(comments20['comment_hour']/3, bins = bins, alpha = 0.66, edgecolor = 'white', label = '2020', **density = True**)

现在,我们可以更有信心地说:2020 年,Redditors 在早上 6 点到下午 3 点之间的评论会更少。

他们也在晚上发表更多评论!让我们一小时一小时地深入研究这个问题:

趋势随之而来。2020 年夜间评论增多,早起鸟评论减少。同样令人着迷的是,从上午 11 点到下午 12 点仍然存在一个间隙!2020 年的人是不是醒的越来越晚,甚至过了晚上 12 点?或者午餐时间重新编辑不再是一件事,因为我们可以在家里任何时候休息?

不过有一点是不变的,那就是从下午 3 点到 12 点的评论频率。我想那里的习惯并没有真正改变,因为那时几乎每个人都已经醒了。

我们现在可能忽略的一件事是,我们用一周中的所有日子来比较 2019 年和 2020 年。这不太公平。人们应该被允许在周末睡懒觉(不做判断)

让我们只比较工作日:

差异仍然存在!

好吧,那么我们的第二个假设呢?通过我们的小提琴图,我们注意到 2020 年的数据在工作日和周末的分布更加对称。让我们试着用直方图来证明这一点,把 2019 年和 2020 年放在一起:

fig,ax = plt.subplots(1,2, figsize = (18,8), sharey= True)

我已经讲了一天的后半部分,重点是从午夜到 12 点。让我们仔细看看每年的工作日和周末有什么不同。当我们将周末叠加在工作日之上时,我们会注意到:

  1. 在 2020 年的凌晨,工作日和周末模式之间的差距更短。注意 2019 年午夜的评论几乎是两倍。现在的情况并非如此。
  2. 在 2020 年的早晨,差距也在缩小。
  3. 2019 年的峰值频率大约在中午 11 点至 12 点之间,2020 年的工作日没有明显的峰值。

简而言之,工作日和周末的差别已经缩小了。

内核密度图

作为一个额外的视角,让我们以曲线的形式探索直方图的变化。我们将使用 Seaborn 来绘制内核密度图:

**sns.distplot**(comments19[comments19['subm_typeOfDay'] == 'weekday']['comment_hour'], hist = False, kde = True, kde_kws = {'linewidth': 3}, label = '2019')
**sns.distplot**(comments20[comments20['subm_typeOfDay'] == 'weekday']['comment_hour'], hist = False, kde = True, kde_kws = {'linewidth': 3}, label = '2020')

我们的观察仍然有效,现在我们有了数据的鸟瞰图。请注意午夜的差距,以及随后 2020 年曲线如何在凌晨 5 点后稍微向右移动,因为它在中午慢慢攀升到一个平台。

如果我们只看 2020 年:

工作日和周末之间的差距也变小了,尤其是在午夜。

4.结束的

我们用 Python 抓取了数据,并使用了 3 种不同类型的图表来查看 Reddit 评论的分布。

结论

  1. 假设 1:确实现在新加坡 Redditors 晚上评论多,早上评论少。
  2. 假设 2:工作日和周末的差别在午夜后最小!

走向

我们如何改进这一分析?以下是我们未来可以做的事情:

  • 分析变化率。随着时间的推移,周末和工作日之间的差距是否在慢慢缩小?
  • 有多少独立用户熬夜越来越晚?每晚的附加评论都来自同样的几个人吗?
  • 刮掉子编辑上除每日线程之外的其他来源
  • 文本挖掘评论,生成最频繁的词和二元模型,比较 2019 年和 2020 年。

感谢您的阅读!

使用聚类重新定义 NBA 球员分类

原文:https://towardsdatascience.com/redefining-nba-player-classifications-using-clustering-36a348fa54a8?source=collection_archive---------23-----------------------

篮球分析/机器学习

用层次聚类定义 NBA 球员

资料来源:unsplash.com

篮球已经存在了一百多年,随着这项运动的发展,新的规则和条例也随之而来,球员们也是如此。NBA 现在已经到了这样一个时代,控球后卫抢下 10 个以上的篮板,中锋在三分线上有效地投篮,7 英尺高的球员擅长成为主要的控球者,而低于 6 英尺 6 的球员作为中锋获得上场时间。球员们已经开始扩展他们的技能组合,以在整个球场上保持统治地位。这些球员已经不能用他们踢哪个位置来定义了。然而,在这个篮球的无位置时代,球队仍然局限于将球员归类到传统位置,将他们限制在过去球员的角色上。本文旨在提供一种新的方法,使用无监督学习方法将球员定义到某些类别中。

数据

所有使用的数据来源于 NBA.com 的,由 2018-2019 NBA 赛季各种记录的游戏内球员统计数据组成。总共收集了 530 个数据点和 336 个特征,包括球员数据、一般统计、高级统计、防守统计、争抢统计、打法统计和传球统计。少于 12 分钟/场和少于 10 场比赛的球员被淘汰,这使得数据点数量减少到 388。

降维

维度的诅咒可能是一件令人畏惧的事情。这不仅使模型更难解释,还会导致过度拟合。合理的假设是,并非所有的特征都给出了关于数据的有价值的信息,而一些特征给出了由另一个特征给出的类似信息。这里的数据集有 336 个要素,当然不是所有要素都与本项目相关。

特征选择/降维是任何数据科学管道中的重要一步。这里皮尔逊相关和方差膨胀因子用于将特征数量从 336 减少到 87。

主成分分析

主成分分析是另一种流行的降维方法,一种在不丢弃任何特征的情况下设法保留所有信息的方法。特征选择已经将 336 个特征减少到 87 个,丢弃更多的特征可能对模型有害。PCA 的使用在保留所有信息和简化模型之间取得了完美的平衡。这里使用 Sci-Kit 学习库进行 PCA。下表显示了每个主成分解释的差异。

作者图片

PC1、PC2 和 PC3 加起来解释了数据产生的总变化的将近一半。用数据解释大约 60%的方差是一个很好的分界点,是模型复杂性和可解释性之间的完美平衡。前 6 个主成分成功解释了数据产生的约 61%的方差。后续组件的影响可以忽略不计,因为这些特征解释的差异较小。

解读主成分

主成分通过使用它们的特征值来解释。具有高正特征值的特征意味着该组件与该特征具有高度正关联。具有高负特征值的特征意味着该组件与该组件具有高负关联。

PC1

PC1 解释了数据产生的 25%的方差,因此在球员聚类中非常重要。下表显示了具有最高绝对特征值的前 20 个特征。

作者图片

PC1 似乎会奖励以下玩家:

  • 抢很多篮板,
  • 在拾取&滚动期间创建屏幕并向篮筐滚动,
  • 在离篮筐 6 英尺的地方有很强的防守冲击力,
  • 争夺 2 分的尝试,
  • 冲向篮筐,
  • 做很多积木,
  • 而且有很高的投篮命中率。

PC1 似乎会惩罚以下玩家:

  • 在三分线附近防守频率高
  • 并在挡拆时处理球。

高 PC1 值表明球员主要在篮筐附近打球。假设中心的 PC1 值较高是安全的。

PC2

PC2 对方差有很大的贡献。下表显示了具有最高绝对特征值的前 20 个特征:

作者图片

PC2 与几乎所有形式的进攻都有积极的联系。特别是,高度评价以下玩家:

  • 得了很多分,
  • 具有高玩家冲击效率,
  • 具有高使用率,
  • 并通过隔离战术得分

高 PC2 值表明玩家是精英且高效的。人们可以假设全明星球员的 PC2 值会很高。PC2 重视进攻和防守的影响

PC3

从 PC3 开始,与 PC1 和 PC2 相比,主成分在解释数据集产生的差异方面做得不太好,因此在区分玩家方面没有太大影响。下表显示了具有最高绝对特征值的前 20 个特征:

作者图片

PC3 似乎会奖励那些:

  1. 做很多定点投篮,
  2. 拍了很多屏幕外的照片,
  3. 投篮距离篮筐超过 20 英尺,
  4. 争夺 3 分的尝试,
  5. 并且有很高的 3 分率

PC3 惩罚有下列行为的运动员:

  1. 助攻很多,
  2. 犯了很多错误,
  3. 并在挡拆时处理球

高 PC3 值表明该球员投篮次数多,投篮距离超过 20 英尺,是高效的 3 分射手。

PC4

下表显示了具有最高绝对特征值的前 20 个特征:

作者图片

PC4 似乎奖励那些:

  1. 贴了很多,
  2. 具有高使用率,
  3. 得分距离篮筐超过 5 英尺,
  4. 在挡拆时朝篮筐滚过去,
  5. 并且有很高的 3 分率

PC4 似乎对以下玩家不利:

  1. 通过过渡得分,
  2. 冲向篮筐,
  3. 投篮命中率和命中率高,
  4. 产生偏转,
  5. 后退,
  6. 并且具有高+/-

高 PC4 值表明球员可以从篮下突破 5 英尺。拥有高 PC4 的球员可以在任何地方得分,无论是靠近篮筐,中距离还是三分线。

PC5

下表显示了具有最高绝对特征值的前 20 个特征:

作者图片

PC5 似乎奖励那些:

  1. 从移交和屏幕外得分,
  2. 在距离篮筐 6 英尺以外有很高的防守频率,
  3. 且具有高投篮命中率和真实投篮命中率

PC5 似乎惩罚那些:

  1. 制造偏差和抢断
  2. 争夺三分球,
  3. 在三分线附近有防守冲击,
  4. 拍摄特写镜头,
  5. 回收松散的球,
  6. 并通过过渡得分

高 PC5 值表明该球员主要在远离篮筐的地方打球,投篮命中率高,防守影响力低。PC5 高的玩家是占优势的射手,对游戏的其他方面没有正面影响。

PC6

下表显示了具有最高绝对特征值的前 20 个特征:

作者图片

PC6 似乎会奖励那些:

  1. 在距离篮筐 6 英尺以外有很高的防守冲击力,
  2. 提起诉讼,
  3. 多传球

PC6 惩罚进攻冲击力大的球员。高 PC6 值意味着球员在外线有巨大的防守影响力。

层次聚类

这里的目标是重新定义玩家的分类。根据球员的位置对他们进行分类是一个过时的系统,在现代游戏中不应该有一席之地。但是,如果不是位置,那么应该用什么来分类那些玩得相似的球员呢?聚类是一种流行的方法,用于对标签未知的相似数据进行分组。这里,层次聚类用于根据可用数据对玩家进行分组。

霍普金斯试验

在对数据进行聚类之前,进行了 Hopkins 测试来验证数据的空间随机性。这样做是为了确保我们的数据实际上是否显示出聚类趋势。(随机生成的数据点没有聚类倾向)。

H0:数据点由非随机、均匀分布产生

H1:数据点随机生成

通过进行霍普金斯试验,观察到 p 值为 0.3。因此,有一些证据来拒绝零假设,因此,有证据来推断数据点具有聚类趋势。

联动

在尝试了不同的链接方法后, Ward linkage 似乎在对手头数据进行聚类方面做得最好。下面是可视化聚类方法的树状图。

作者图片

作者图片

直觉思维和启发式方法用于确定对数据进行分组所需的合适的聚类数。下面是肘图。

肘图(图片由作者提供)

从肘图中可以观察到,2、6 和 9 个集群在创建好的集群方面做得很好。只有 2 或 6 个集群胜过了对我们的数据进行精心分组的努力。因此,数据被分为 9 类。

在三维平面上可视化集群(图片由作者提供)

解释集群

每个聚类中主成分的平均值(图片由作者提供)

每个集群中主要组件的热图。(图片由作者提供)

集群 1——精英现代大人物

集群 1 具有高 PC1、PC2 和 PC4,以及负 PC5。这意味着集群 1 中的球员大多在距离篮筐 6 英尺内打球,效率高,得分多,可以伸展地板,投篮距离篮筐 6 英尺以上。该集群中值得注意的参与者:

作者图片

集群 2——传统的大人物

簇 2 的平均 PC1 值最高,PC4 值最低。集群中的球员在离篮筐 6 英尺以内打球,有很高的防守冲击力。然而,他们不能伸展地板,投篮距离篮筐超过 6 英尺。该集群中值得注意的参与者:

作者图片

第三组——精英三分射手

聚类 3 具有最高的平均 PC5 值、高 PC3 和最低的平均 PC1 值。集群 3 的球员在外围活动,是高效的射手。他们很少靠近篮筐抢篮板。该集群中值得注意的参与者:

作者图片

集群 4——角色扮演者

聚类 4 在所有主成分中具有非常低的值。这个集群中的玩家不是任何特定类别的精英。他们只有在 PC3 有正的平均值,这可能表明他们在外线打球,是不错的射手。他们的平均 PC2 值最低,表明他们得分较低,效率不高。该集群中值得注意的参与者:

作者图片

集群 5–3 和 D 玩家

聚类 5 具有高的平均 PC3 和 PC6 值以及最低的平均 PC5 值。这个集群中的球员是高效率的射手,他们在外线有很高的防守影响力。该集群中值得注意的参与者:

作者图片

集群 6–3 级计分器

聚类 6 具有最高的平均 PC3 值。除了 PC2 和 PC3,该聚类中的平均主成分值为负。这个集群中球员都是射手,对得分有一定的影响。他们不一定只在三分线外得分。该集群中值得注意的参与者:

作者图片

第 7 组——得体的控球者

聚类 7 具有最低的平均 PC3 和非常低的平均 PC2 值。它具有高平均 PC4 值。这个集群中的球员效率很低,在三分线内打球,但远离篮筐,使用率很高。这可能表明他们手中有很多球,但并没有真正得分。该集群中值得注意的参与者:

作者图片

集群 8 — 精英全明星

聚类 8 具有最高的 PC2 值和最低的 PC6 值。集群 8 中的玩家获得大量的分数,并且效率最高。他们在一场比赛中负责得分。该集群中值得注意的参与者:

作者图片

集群 9 — 双向外线球员

聚类 9 具有高的平均 PC6 值和相当高的平均 PC2 值。这些球员在进攻和防守上都是高效的球员。他们得分很多,加强了外围防守。该集群中值得注意的参与者:

作者图片

检查集群的有效性

作者图片

作者图片

作者图片

比较聚类中的各种统计数据(图片由作者提供)

集群 1

集群 1 具有以下特征:

  • 第二高的分数/游戏
  • 场均最高篮板数
  • 每场比赛最高平均盖帽数
  • 平均投篮命中率第二高
  • 第二高的投篮命中率
  • 防守投篮得分/比赛得分最高
  • 集群 1 的大部分进攻来自挡拆、补位和定点投篮

所有这些特征在精英大人物中非常普遍

集群 2

集群 2 具有以下特征:

  • 第二高的篮板数/场
  • 第二高的区块/游戏
  • 最高投篮命中率
  • 最低 3 个百分点
  • 每场比赛投篮命中率高
  • 每场比赛第二高的防守投篮命中率
  • 集群 2 的大部分进攻来自挡拆和切入

所有这些特征在传统的大人物中非常普遍。

集群 3

聚类 3 具有以下特征:

  • 最高 3 个百分点
  • 每场比赛第二高的外围投篮命中率
  • 集群 3 的大部分进攻来自于传球、场外投篮、处理挡拆和定点投篮。

所有这些特征在精英三分射手中非常普遍。

集群 4

聚类 4 具有以下特征:

  • 每场比赛得分最少
  • 场均进球总数第二低
  • 集群 4 的大部分进攻来自定点投篮

所有这些特质在角色扮演者中非常普遍。

集群 5

聚类 5 具有以下特征:

  • 高 3 个百分点
  • 高抢断/比赛
  • 高周界投篮/比赛
  • 高位和外围防守投篮/比赛
  • 集群 5 的大部分进攻来自定点投篮

所有这些特征在 3 号和 4 号球员(3 分和防守球员)中非常普遍

集群 6

聚类 6 具有以下特征:

  • 高分/游戏
  • 高篮板/比赛
  • 高场和 3 分百分比
  • 每场比赛相对较高的内线和外线投篮命中率
  • 与其他集群相比,高定位投篮、持球、挡拆、离屏、隔离、交接、切入和过渡投篮得分

所有这些特质在 3 级评分者中非常普遍。

集群 7

聚类 7 具有以下特征:

  • 非常低的分数/游戏
  • 相对较高的助攻/场
  • 最少的投篮命中率
  • 每场比赛的最低投篮命中率
  • 每场比赛防守投篮得分最低
  • 集群 7 的大部分进攻来自于处理挡拆和定点投篮。

所有这些特征在正派的控球者中非常普遍。

集群 8

聚类 8 具有以下特征:

  • 最高分/游戏
  • 最高助攻/场
  • 高篮板/比赛
  • 高投篮命中率
  • 最高抢断/场
  • 每场比赛的最高投篮命中率
  • 高防守投篮得分/比赛
  • 集群 8 的大部分进攻来自于隔离和挡拆。

所有这些特征在精英全明星中非常普遍。

第九集群

聚类 9 具有以下特征:

  • 高分/游戏
  • 第二高的助攻数/场
  • 高 3 个百分点
  • 场均抢断第二高
  • 每场比赛最高的外围防守投篮得分
  • 集群 9 的大部分进攻来自于挡拆

所有这些特质在周边双向玩家中非常普遍。

解说

通过层次聚类,得到了 9 个聚类,用一种新的眼光来描述球员。每个集群都有来自传统位置的玩家组合。有了这样的分类,球队不再局限于根据位置选择球员,而是可以扩大选择互补球员的范围。团队也可以通过让某些球员根据他们所属的群体打不同的位置来进行试验。

潜在的改进

把玩家仅仅归为一类有点不合理。为每个玩家建立一个二级集群对于团队来说非常有帮助,同时可以创建一个协作良好的团队。

希望你喜欢这本书。你可以在我的 GitHub 上找到所有数据和脚本。请随时通过 LinkedIn 联系我。为了获得更多有趣的 NBA 分析阅读,尝试使用机器学习分析 NBA 自由球员。

红移还是雪花!

原文:https://towardsdatascience.com/redshift-or-snowflake-e0e3ea427dbc?source=collection_archive---------32-----------------------

需要知道的重要事情…

毛里西奥·古铁雷斯在 Unsplash 上拍摄的照片

当谈到在云上建立数据仓库时,nowflake 和 Redshift 是数据库的两个明显选择。在本文中,我试图展示我在使用这些领先的云数据库时所学到的东西。

1.体系结构

红移的核心成分是星团。群集可以有一个或多个存储数据的计算节点。领导者节点将任务分解为多个任务节点,每个任务节点并行工作。每个任务节点都有自己的存储和计算单元。

另一方面,雪花保持存储和计算独立,并集中存储数据,所有计算单元都可以访问。每个计算集群都在本地存储一部分数据以供处理。将存储与计算分开的优势在于,在性能瓶颈期间,可以添加更多计算,而不会影响现有工作负载。

架构比较

使雪花脱颖而出的关键架构差异之一是,雪花将其数据作为微分区文件(大小为 16 MB)存储在由雪花管理的 AWS S3(如果选择 AWS 云)上。它的元数据跟踪所有的微分区文件,并使雪花能够提供像时间旅行这样的功能,在几秒钟内克隆一个 TB 大小的表。所有这些都是可能的,因为底层数据(即文件)不会受到影响,而是完全由元数据控制,元数据包含逻辑模式与物理存储的映射。

2.表演

两个数据库共享以下功能:

a. 列式数据存储 减少了从表中读取的数据量,显著减少了磁盘 I/O

b .MPP(大规模并行处理)架构

c .将压缩后的数据存储到reduce disk I/O,在查询执行过程中得到解压缩

d .查询结果得到 在 leader 节点缓存 以防红移,雪花在 compute 节点(本地磁盘)缓存查询结果。这避免了对数据执行重复查询

e. Redshift 提供了多种 技术来优化 数据库性能,如分布/排序键、分区和数据分布风格。然而,雪花没有提供任何优化技术。这可能对人们有好处,他们发现这很复杂,但也夺走了专家的机会。

3.可量测性

通过在现有集群中添加或删除节点,可以增加或减少红移。在调整大小操作期间,集群将以只读模式可用。但是,自动缩放功能在 Redshift 中不可用

红移调整大小选项

雪花可以无缝地自动扩展其计算单元,而不会对现有工作负载产生任何影响。这是可能的,因为数据存储在计算集群之外。因此,数据不需要在群集间混洗,扩展速度很快,不会出现任何写入中断。

雪花大小调整选项

4.定价

雪花将“存储”和“计算”分开,用于成本计算。它以“信用”为单位来衡量计算成本。$积分值因计算规模和使用情况而异。

下表解释了成本是如何计算的。

雪花定价图

例如,一个中型虚拟仓库(企业版)1 小时的使用将花费 4 个信用点 $3.30= $13.2*

存储成本有两种变化,即按需容量和预购容量。预购容量是经济高效的,因为它需要提前承诺使用量。下图显示 1 TB 存储按需存储的月成本几乎是预购存储的两倍

存储成本选项

Redshift 还提供按需和保留实例定价,根据实例类型和规模,1 年期可获得 20%-40%的折扣,3 年期可获得 50%-75%的折扣

红移群集节点有最大存储限制,这意味着应该添加一个节点来满足更多的存储需求。

红移价格图表

很难比较红移和雪花的成本,因为雪花不公开其服务器的配置。在下表中,对雪花中型 DW 和红移 DC 2.8 XL large 进行了指示性成本比较。但是,实际成本取决于使用情况和计划。红移提供保留实例,可以节省大量成本,而雪花自动暂停功能优化了服务器的使用,非常划算。

红移和雪花的价格比较

*红移有保留实例价格

结论

红移和雪花都反映了云构建架构,并提供云数据平台。如果你计划采用一个,有几个参数你需要考虑的基础上短期或长期使用。

如果生态系统是 AWS 的重磅产品,并且您希望利用与其他 AWS 服务(如 CloudWatch、Cloud Trail、Glue Catalog 等)的无缝集成,那么 Redshift 会获得额外的积分。红移光谱是一个附加功能,可以帮助查询 S3 数据,而无需加载到红移中。虽然雪花通过“外部表”提供了同样的功能,但它在刷新元数据方面有一些限制。

如果您是一个拥有多个部门的大型组织,并且需要临时读取数据,那么雪花可以提供更加灵活和经济高效的工作负载管理。由于其架构,不同的用户群体可以拥有单独的计算单元,其中一个计算单元的性能问题不会影响其他计算单元。此外,自动挂起功能可以将未使用的集群置于睡眠状态。

如果您的组织经常遇到意想不到的峰值,并且需要频繁地扩大/缩小规模,那么雪花最适合,因为您可以在几秒钟内调整集群的大小或添加/删除集群,而不会影响任何正在运行的进程。

谈到 维护 ,红移需要一些内务处理活动,如“分析”来更新统计数据,以及“清空”来重新排序行和回收空间,以保持性能完好。但是,Snowfla ke 不需要这样的维护任务。

深入探究红移光谱及其内部结构

原文:https://towardsdatascience.com/redshift-spectrum-f7ad968db6ef?source=collection_archive---------20-----------------------

完整的图片

红移光谱的内部功能以及何时在 Athena、Spectrum 或 s3 之间选择-选择通过 s3 查询数据

卡斯帕·卡米尔·鲁宾在 Unsplash 上的照片

AWS 在 2013 年推出了红移,在红移成功后,出现了清理被冷数据占据的簇的需求。但是,如果您也想访问您的冷数据呢?不经常,但可能一年一次。但是,您愿意为在您的集群中保存冷数据而支付集群空间费用吗?您很少使用这些冷数据,而且这些冷数据的大小会随着时间的推移而不断增加。

不,没错,没有人想用冷数据填满他们的集群。因此,红移星团最大的问题是以最小的代价查询冷数据。为了解决这个问题,AWS 在 2017 年推出了红移频谱,允许您查询存储在 s3 上的数据,并提供将 s3 数据(即冷数据)与红移数据(即热数据)连接起来的功能。

这节省了大量的集群空间,可以帮助您节省集群的总体成本,并且有了更多的可用空间,您可以提高查询性能,并为查询的执行提供更多的空间。

红移光谱的内部结构:

AWS Redshift 的查询处理引擎对于内部表(即位于 Redshift 集群或热数据中的表)和外部表(即位于 s3 存储桶或冷数据上的表)的工作方式是相同的。

要使用频谱访问驻留在 S3 的数据,我们需要执行以下步骤:

  1. 创建胶水目录。
  2. 创建指向 s3 数据的外部表。

没有必要运行爬虫,如果你想更新分区信息,只需运行 msck 修复表 table_name。

当我们使用 spectrum 查询外部表时,查询的生命周期是这样的:

  1. 查询在集群的领导者节点中被触发,在该节点中查询被优化,并且领导者节点确定是否在本地运行哪个部分来访问热数据,以及什么进入频谱。
  2. 查询计划被发送到计算节点,其中的表对信息和元数据进行分区(如果从粘合目录中提取的话)。
  3. 称为 Spectrum Fleet 的多个受管计算节点与集群相关联,用于对外部数据集执行查询。
  4. Spectrum fleet 处理数据并将其发送回 leader 节点,在那里与热数据进行连接。
  5. leader 节点为我们提供了所需的输出。

红移谱中的查询生命周期

光谱车队

Spectrum fleet 有点棘手,我们需要了解它,以便为我们的工作负载管理选择最佳策略。

spectrum 机群由位于 VPC 内的多个托管计算节点组成,仅当您对外部数据执行查询时才可用。因此,这些计算节点完全由 AWS 在幕后管理。

现在问题来了,有多少计算节点可用于运行查询?如果您有 2 个节点红移集群,您能运行超过 10 TB 数据的频谱查询吗?对于外部表,计算节点的数量是无限的吗?

所以答案是

你没有得到无限的计算,但分配给特定频谱查询的节点数等于你的红移集群大小的 10 倍。

如果您使用 2 节点红移集群,那么 AWS 将分配不超过 20 个节点来运行您的光谱查询。同样,对于 20 个节点的集群,您最多可以获得 200 个节点。

节点数量的分配通过以下方式确定:

  1. 当我们查询外部数据时,leader 节点将生成一个优化的逻辑计划,并由此生成一个物理计划。
  2. 现在,基于这个物理计划,redshift 确定处理结果所需的计算量,并分配必要的计算节点来处理查询。
  3. 如果您的查询需要的节点数超过最大限制,redshift 将分配允许的最大节点数,如果这不能满足您的计算要求,查询将失败。

S3 文件格式和压缩

红移谱可以查询超过 orcrcavrojsoncsvsequencefileparquet,的数据 Amazon 建议使用分栏文件格式,因为它占用的存储空间更少,处理和过滤数据的速度更快,我们可以始终只选择所需的栏。要了解有关支持的文件格式、压缩和加密的更多信息,请访问此处。

查询优化

要优化查询性能,您应该考虑以下几点:

  1. 使用分栏文件格式,这将防止对分栏进行不必要的扫描。
  2. 用正确的分区数量更新您的 glue 目录。
  3. 编写您的查询以使用有资格被推送到红移光谱图层的过滤器和聚合。下面是一些可以通过子句、比较条件和模式匹配条件推送到红移谱层的操作的例子,比如 LIKE聚合函数,比如 COUNT、SUM、AVG、MIN、MAX。
  4. 避免无法推至红移光谱图层的操作,包括 DISTINCT 和 ORDER BY。

要了解更多关于查询优化的信息,请访问这里。

监视

redshift 提供了两种系统视图来查看外部查询的性能:

  1. SVL _ S3 查询:提供段和节点切片级别的频谱查询细节。
  2. SVL_S3QUERY_SUMMARY :跟踪集群上迄今为止触发的所有频谱查询,包括处理的文件数、扫描的字节数(有助于确定查询产生的成本)

要了解更多关于查询优化的信息,请访问这里。要解决查询错误,请访问此处的。

费用

根据扫描的数据量收取频谱费,即每 TB 数据 5 美元。

欲了解红移光谱性能详情,请访问本博客https://AWS . Amazon . com/blogs/AWS/Amazon-Redshift-Spectrum-exabyte-scale-in-place-queries-of-S3-data/

选择光谱,雅典娜和 S3-选择

雅典娜:

当没有红移集群正在运行,并且您想要对驻留在 s3 中的数据执行分析查询时,应该考虑 Athena。或者您的数据与红移集群中的数据不相关,并且您不想对集群数据执行任何连接。与雅典娜相关的一些要点是:

  1. 雅典娜是无服务器的。
  2. Athena 使用 Presto 查询引擎来优化查询。
  3. Athena 要求首先使用 glue 爬虫对数据进行爬行,这增加了它的总体成本。
  4. Athena 的总成本为每 TB 扫描的数据 5 美元+使用 glue crawlers 对数据进行爬行的每小时每 DPU 0.44 美元。

S3-选择:

如果您只想过滤掉一个 s3 对象的数据,S3 选择非常有用。这提供了仅查询单个 s3 对象的功能,并且能够过滤数据。S3 选择功能包括:

  1. 不需要服务器来运行对 s3 对象的查询。
  2. 一次只能查询一个对象。
  3. 可以在 Spark 应用程序中使用,以应用谓词下推。(相信我,如果您正在读取 csv 数据,这将提高您的速度)
  4. 费用为返回数据 0.8 美元/TB,扫描数据 2.23 美元/TB。

红移光谱:

红移光谱只有在你已经是红移用户的情况下才应该考虑。如果您已经在红移集群上运行工作负载,那么应该使用红移频谱。红移谱填补了查询驻留在 s3 上的数据以及集群数据的空白。

Spectrum、Athena 和 s3-select 之间的比较

摘要

如果您希望查询驻留在 s3 上的数据并在 s3 和红移集群数据之间建立关系,红移光谱是一个很好的选择。它速度快、功能强大,而且非常经济高效。可以使用 BI 工具或 SQL workbench 查询 s3 数据。

红移光谱是一个非常强大的工具,但却被每个人忽略了。

我希望你喜欢这篇文章。

敬请关注更多内容。

参考资料:

[1] 红移光谱文档

利用基于拒绝选项的分类减少人工智能偏差

原文:https://towardsdatascience.com/reducing-ai-bias-with-rejection-option-based-classification-54fefdb53c2e?source=collection_archive---------51-----------------------

后处理阶段中偏差减轻的一个例子

斯蒂夫·约翰森在 Unsplash 上拍照

最近,我开始撰写一系列文章,探索人工智能中的偏见,以及在工作流程中更详细地减轻偏见的不同方法。在我的前两篇博客中,我介绍了在建模的预处理阶段中作为一种缓解技术的重新加权,以及在机器学习工作流的处理中(模型训练)阶段中的对抗性去偏置。

机器学习(ML)管道中的第三个阶段称为后处理,我们可以在其中进行干预以减少偏差。后处理算法是可应用于模型预测的缓解步骤。关于公平性和校准[1],监督学习中的机会均等[2]和区分感知分类的决策理论[3]是学术文献中提出的不同后处理偏差缓解技术。

在这篇文章中,我将重点探讨基于拒绝选项分类(ROC)的歧视感知分类技术的决策理论。在这种方法中,假设当模型对预测最不确定时,即在决策边界(分类阈值)附近,会发生最大的区分。因此,通过利用分类器的低置信区域来减少区分并拒绝其预测,我们可以减少模型预测中的偏差。

例如,对于 0.5 的分类阈值,如果模型预测是 0.81 或 0.1,我们将认为模型确定其预测,但是对于 0.51 或 0.49,模型不确定所选择的类别。在 ROC 中,对于在决策边界周围具有最高不确定性的模型预测,当有利的结果被给予特权群体或不利的结果被给予非特权群体时,我们修改它们。

这种方法的优点是您可以在建模工作流的最后阶段直接介入。这对于在预测时(或在部署环境中),受保护的或敏感的属性可用的情况是有价值的。此外,这种方法以及一般的后处理技术提供了在不修改学习阶段的情况下进行缓解的选项,因此不受任何特定学习算法的限制。此外,这种方法也适用于不同的公平性定义。

像以前一样,为了证明这项技术可以用来减少偏差,我使用了成人数据集[4]。该数据集中的二元目标是个人收入是高于还是低于 5 万美元。它包含了几个在美国受法律保护的特征,但是为了简单起见,在这篇文章中,我将把重点放在性上。从下表中可以看出,男性是享有特权的群体,有 30%的可能性获得积极的结果(>50k),而女性群体有 11%的可能性获得积极的结果。

如前一篇博客中所述,不同的影响度量(DI)是对数据中歧视的一种度量。分数为 1 表示数据集是无歧视的。当在成人数据集上计算男性和女性时,得分为 0.36。

为了评估效果,我在测试数据的模型预测上应用了 IBM 工具包【5】中 ROC 技术的可用实现。对于这个例子,我使用了统计平价差(这个指标与 DI 相同,但不是一个比率,而是两个概率之间的差)。为了简化与我之前的博客的比较,除了 DI 之外,我还将平均优势差作为另一个指标来进一步分析这些模型预测中的偏差。如前所述,平均优势差计算了非特权群体和特权群体预测的假阳性率和真阳性率的平均值之差。

实验结果表明了重新称重方法在减少歧视方面的有效性,如下表所示:

正如我们所看到的,模型准确性下降了 0.07,但这种技术能够显著提高 DI 得分,并将平均优势差几乎降至零。为了减少偏差,决策者应该考虑准确性和公平性之间的权衡。

与对抗性去偏置等内处理方法相比,实验表明,内处理技术比 ROC 等后处理技术在减少偏置方面更有效。然而,如果我们将 ROC 技术应用于招聘算法,并以与我们实验中相同的 DI 得分 1.0 结束,它将满足美国就业法规定的 4/5 规则(DI 得分至少为 0.8)。

参考资料:

[1] Pleiss,g .,Raghavan,m .,Wu,f .,Kleinberg,j .,和 Weinberger,K. Q. (2017)。论公平与校准。神经信息处理系统进展,5680-5689 页。

[2]莫里茨·哈特、埃里克·普莱斯和纳蒂·斯雷布罗。监督学习中的机会均等。神经信息处理系统进展,2016 年。

[3]卡米兰,f .,卡里姆,a .,张,X. 2012。区分感知分类的决策理论。在IEEE 数据挖掘国际会议论文集(ICDM 2012) 中,Zaki M. J .,Siebes A .,Yu J. X,b .,Webb G. I. & Wu X .(编辑)。IEEE 计算机学会,924–929

[4]“成人——UCI 机器学习。”5 月 1 日。1996 年,【http://archive.ics.uci.edu/ml/datasets/Adult】T2。

[5] R. K. E .贝拉米等人。“AI Fairness 360:一个用于检测和减轻算法偏差的可扩展工具包”,载于 IBM 研发杂志,第 63 卷,第 4/5 期,第 4:1-4:15 页,2019 年 7 月 1 日-9 月。

用合成数据减少人工智能偏差

原文:https://towardsdatascience.com/reducing-ai-bias-with-synthetic-data-7bddc39f290d?source=collection_archive---------58-----------------------

公平和偏见

生成人工记录以平衡有偏差的数据集并提高整体模型准确性

在这篇文章中,我们将探索使用合成数据来增强 Kaggle 上一个受欢迎的健康数据集,然后训练表现和概括更好的 AI 和 ML 模型,同时减少算法偏差。

来源:Kubkoo,via iStockPhoto

由加州大学欧文分校发布的心脏病数据集是数据科学竞赛网站 Kaggle 上排名前 5 的数据集之一,列出了 9 个数据科学任务和 1014+个由数据科学家创建的笔记本内核。它是一系列健康 14 属性,并标有患者是否患有心脏病,使其成为一个很好的预测数据集。

Kaggle 上的 UCI 心脏病数据集概述

快速浏览数据集显示,男性患者记录占整个数据集的 68%,女性患者记录仅占 32%。由于男性与女性患者的比例为 2 比 1,这可能导致数据集上训练的算法过度索引男性症状,并对女性患者进行不良诊断。在训练数据中,没有什么可以替代平等的群体代表性,尤其是在医疗保健领域。如果没有这些,我们如何尽可能减少输入数据中的偏差?

"通过用合成记录扩充训练集,我们能减少性别偏见并提高 ML 的准确性吗?"

为了测试我们的论文,我们将使用 Gretel.ai 的开源合成数据库来生成额外的女性患者记录,以尝试补偿有偏差的训练数据。我们希望这将有助于分类器提高对男性和女性患者心脏病的预测,并更好地推广未知数据。然后,我们可以在 Kaggle 上通过 ML 算法运行合成数据集,将结果与训练集进行比较。

Kaggle 上的一个顶级数据科学笔记本(由 forks 开发,链接如下)在 UCI 数据集上运行了一系列 6 种分类算法,并比较了所得模型的准确性。笔记本将原始数据集分割成训练(80%)和测试(20%)分割,我们将它们保存到磁盘上作为[train.csv](https://gretel-public-website.s3-us-west-2.amazonaws.com/datasets/uci-heart-disease/train.csv)[test.csv](https://gretel-public-website.s3-us-west-2.amazonaws.com/datasets/uci-heart-disease/test.csv)。我们将使用 train.csv 来训练我们的合成模型,并使用 test.csv 来验证笔记本中的 6 种分类算法的结果。

[## 心脏病-分类(机器学习)

使用 Kaggle 笔记本探索和运行机器学习代码|使用来自 UCI 心脏病研究中心的数据

www.kaggle.com](https://www.kaggle.com/cdabakoglu/heart-disease-classifications-machine-learning)

训练合成数据模型

要生成自己的合成记录,请通过谷歌合作实验室(点击此处)启动 Gretel-synthetics,或者直接在我们的 Github 上查看笔记本。单击 Colaboratory 中的“Run all”下载从 Kaggle 导出的训练数据集,训练模型,并生成新的患者记录以扩充原始训练数据。

为您的合成数据模型配置以下设置-请注意,我们通过 15 个时期的训练和 256 个隐藏单元找到了泛化与模型准确性之间的良好平衡。请注意,在此配置中,不需要使用差异隐私进行培训,因为数据集已经被取消标识。

UCI 数据集的最佳合成数据模型配置

为了测试关于算法偏差的理论,我们在笔记本上添加了一个非常简单的自定义验证器,它只接受由我们的合成模型生成的女性记录(第 1 列-性别等于 0)。

简单的合成记录验证器,只接受由模型生成的“女性”患者数据记录

我们现在准备在我们的输入数据上训练一个合成数据模型,并使用它来生成 111 个女性患者数据记录,以增加我们的训练集。

创建合成的女性患者记录以添加到训练数据集(点击此处在 Google Colab 中运行!)

合成模型很快学会了数据的语义,并在 10 个时期内训练到 95%以上的准确度。接下来,下载生成的数据集,让我们在 Kaggle 上运行它!

进行实验

现在,让我们转到 Kaggle 并运行分类笔记本(进行最少的编辑以允许原始模型和我们的增强模型运行)。为了方便起见,您可以在此处加载修改后的笔记本。默认情况下,它将与我们生成的测试集一起运行。要使用您自己的数据集,请将上一步生成的数据集上传到 Kaggle 笔记本。

[## 心脏病-分类(机器学习)

使用 Kaggle 笔记本探索和运行机器学习代码|使用来自多个数据源的数据

www.kaggle.com](https://www.kaggle.com/redlined/heart-disease-classifications-machine-learning)

结果

正如我们在下面看到的,创建并向训练集添加合成生成的患者记录提高了 6 种分类算法中 5 种算法的准确性,实现了KNN 96.7%的总体准确性(高于 88.5%) ,随机森林 93%,决策树分类器相对于非合成数据集上训练的模型提高了 13%。由于算法强烈假设所有特征都是独立的(因此是朴素的),并且合成数据模型可能学习并重放了训练数据中的相关性,因此朴素贝叶斯的准确性可能会下降。

合成的平均准确率:90.16%,原始的:85.79%。平均改善率:4.37%

整体模型性能(基线与基线+综合)

最后,查看按性别划分的模型准确性结果,女性的原始模型准确性平均值为 84.57%。通过增加女性患者数据记录和训练相同的模型,准确率提高到 90.74%。有趣的是,男性患者数据预测准确率也从 86.61%提高到 90.71%。

6.17%的女性心脏病患者现在可以被准确诊断!

结论

在 Gretel.ai ,我们对使用合成数据来增强训练集以创建 ML 和 ai 模型的可能性感到非常兴奋,这些模型可以更好地概括未知数据,并减少算法偏差。我们很乐意听到你的用例——欢迎在评论中联系我们进行更深入的讨论, twitter 或 hi@gretel.ai 。关注我们,用合成数据跟上最新趋势!

有兴趣在自己的数据集上进行训练吗?Gretel-synthetics 是免费开源的,你可以通过合作实验室在几秒钟内开始实验。

使用对抗性去偏差减少模型偏差

原文:https://towardsdatascience.com/reducing-bias-from-models-built-on-the-adult-dataset-using-adversarial-debiasing-330f2ef3a3b4?source=collection_archive---------22-----------------------

处理阶段偏差缓解的一个例子

玛丽安·博斯在 Unsplash 上的照片

最近,我开始撰写一系列文章,探索人工智能中的偏见,以及在工作流程中更详细地减轻偏见的不同方法。在之前的博客中,我们讨论了一种在机器学习工作流程的预处理阶段使用重新加权示例来减轻偏差的技术。

机器学习(ML)管道中的第二个阶段是我们可以干预以减少偏差的阶段,称为处理中。处理中描述了算法学习过程中的一组干预和强制约束。带有公平性约束的分类[1]、偏见消除器正则化[2]和对抗性去偏置[3]是目前从学术文献中提出的不同的处理中偏见减轻技术。

在这篇文章中,我将重点探讨对抗性去偏见。在对抗性去偏置中,你建立了两个模型。首先是预测你的目标,基于你已经对训练数据采取的任何特征工程和预处理步骤。第二个模型是对手,它试图根据第一个模型的预测来预测敏感属性。理想情况下,在没有偏见的情况下,这种对立模型不应该能够很好地预测敏感属性。因此,对抗模型引导原始模型的修改(通过参数和加权),这削弱了对抗模型的预测能力,直到它不能基于结果很好地预测受保护的属性。

这种方法的第一个优点是,您可以在建模工作流的学习阶段直接介入。此外,它可以应用于分类和回归,与重新加权不同,我们上周探讨了重新加权,并将您的建模选项限制为可以处理权重的方法,这可以应用于任何建模方法,包括基于梯度的学习模型。此外,这种方法也适用于不同的公平性定义。

像以前一样,为了证明这项技术可以用来减少偏差,我使用了成人数据集[4]。该数据集中的二元目标是个人收入是高于还是低于 5 万美元。它包含了几个在美国受法律保护的特征,但是为了简单起见,在这篇文章中,我将把重点放在性上。从下表中可以看出,男性是享有特权的群体,有 30%的可能性获得积极的结果(>50k),而女性群体有 11%的可能性获得积极的结果。

如前一篇博客中所述,不同的影响度量(DI)是对数据中歧视的一种度量。分数为 1 表示数据集是无歧视的。当在成人数据集上计算男性和女性时,得分为 0.36。

为了评估对抗性去偏置技术的效果,我训练了两个 Tensorflow (TF)模型,一个没有任何缓解,另一个使用了该技术在IBM toolkit【5】中的可用实现。除了 DI 之外,我还将平均优势差作为另一个指标来进一步分析这些模型预测中的偏差。平均优势差计算非特权组和特权组预测的假阳性率和真阳性率的平均值之差。

实验结果表明了重新称重方法在减少歧视方面的有效性,如下表所示:

在模型准确性仅下降 2%的情况下,这种技术能够显著提高 DI 评分,并将平均优势差几乎降至零。

与从训练数据中移除敏感属性或预处理技术等简单方法相比,实验表明,处理中技术在减少偏差方面更有效。然而,如果我们将对抗性去偏置技术应用于招聘算法,并以与我们实验中相同的 DI 得分 0.42 结束,它仍将远远低于美国就业法规定的 4/5 规则(DI 得分至少为 0.8)。

参考资料:

[1] L. Elisa Celis、Huang、Vijay Keswani 和 Nisheeth K. Vishnoi。具有公平性约束的分类:一种具有可证明保证的元算法。《公平、问责和透明会议论文集》,FAT* '19,2019 年。

[2] T. Kamishima、S. Akaho、H. Asoh 和 j .佐久法史。带有偏见消除器正则化器的公平感知分类器。数据库中的机器学习和知识发现,第 35–50 页,2012。

[3] B. H. Zhang,b .,M. Mitchell,“用对抗性学习减少不必要的偏见”,ACM 人工智能与社会会议,2018 年

[4]“成人——UCI 机器学习。”5 月 1 日。一九九六年,http://archive.ics.uci.edu/ml/datasets/Adult。

[5] R. K. E .贝拉米等人。“人工智能公平 360:一个用于检测和减轻算法偏差的可扩展工具包”,载于 IBM 研发杂志,第 63 卷,第 4/5 期,第 4:1-4:15 页,2019 年 7 月 1 日-9 月。

将 Tensorflow 调试时间减少 90%

原文:https://towardsdatascience.com/reducing-tensorflow-debugging-time-by-90-percent-41e8d60f9494?source=collection_archive---------19-----------------------

介绍可应用于 Tensorflow 代码的 VeriTensor 代码方法,以提高调试效率。

来自 Pixabay 的图片

如果你被困在付费墙前,使用好友链接。

Tensorflow 代码很难调试。我过去常常花数周时间调试我的代码。更糟糕的是,大多数时候,我不知道如何继续——我可以看到我的代码没有学习,但我不知道这是因为模型没有学习能力,还是因为实现有 bug。如果是后者,bug 在哪里?

这是很多机器学习从业者面临的挫败感。本文介绍了我为调试张量流代码而设计的 VeriTensor 方法。VeriTensor 基于合同方法的设计。它包括三种技术。这种方法将我的调试时间从数周减少到数小时,提高了 90%以上。更好的是,在我完成调试后,我知道代码中没有错误。多棒的感觉啊!

通过断言的规范

有效调试的关键是编写规范来定义代码的正确性。规格说明描述了代码应该做什么,实现描述了代码如何做。一段代码只有在其规格说明方面才是正确的。在 Python 中,使用断言来编写规范,如下面清单中的第 2 行和第 4 行所示。

但是你说,写断言是非常困难的。我同意你的观点。我花了 15 年时间用断言验证代码。我开发了基于断言的技术,微软将其包含在必应搜索引擎中。我知道规格有多复杂。这就是为什么当我开发 VeriTensor 时,我确保它是实用的。

有效调试的关键是通过断言告诉调试器代码应该做什么。

绝对张量方法

VeriTensor 包括 3 种技术。您可以在编写 Tensorflow 代码后应用它们。这意味着这些技术是现成的,你不需要从头开始使用它们。

技术 1:张量形状断言

当你引入张量时,你需要写断言来检查它们的形状。关于张量形状的不正确假设经常会导致棘手的错误。而 TensorFlow 的广播机制可以把它们隐藏的很深。

例如,在一个回归算法中,比如深度 Q 网络(DQN),你有一个来自神经网络的预测张量,一个目标张量和一个损失张量:

预测代表预测值。目标张量代表期望值,由奖励张量和自举 _q 张量计算得出, gamma 为浮点数。损失张量将我们的训练损失表示为均方误差。

现在我们为引入的张量添加断言,如下面的清单所示。这些断言检查预测目标的形状在批量大小动作尺寸方面必须相同。这些是 DQN 算法中使用的一些量。如果你不熟悉他们,不要担心。这里重要的是,我们编写断言来检查张量形状。最后,由于损失评估为一个数字,断言声明其形状为[]。

如果张量的形状与期望值不匹配,你会得到断言违反。你不会相信你的形状断言经常被违反!

技巧 2:张量依赖性

Tensorflow 程序是一个计算图。所以你需要确保你正确地构建了张量图。如果张量 B 的值依赖于张量 A 的值(例如 B=A+1),那么在图中应该有一条从节点 B 到节点 A 的边。

您可以使用 TensorBoard 可视化您的张量流图。然而,理解这个图是困难的,因为现实的张量图通常有数百个节点和边。下图显示了典型的张量板可视化。

这里的关键见解是:要检查你的张量图的结构,你只需要可视化你引入的张量之间的关系。你可以把许多张量组合成一个节点。例如,在具有许多变量的多层神经网络中,每个变量都是一个张量。但是你只需要把整个网络想象成一个单独的节点。

我开发了一个 Python 包, VeriTensor,来简化张量图可视化。我将很快对这个包进行开源。它包含一个类 TensorGroupDependency。这个类允许你只注册你想要可视化的张量。它为注册的张量生成一个新的、小得多的可视化。

下一个清单显示了如何使用 TensorGroupDependency。您首先调用 add 方法来注册张量。然后调用generate _ dot _ re presentation方法给你一个可视化。该可视化仅显示了已注册的张量及其相关性。

第 1 行到第 5 行创建了一个张量依赖图对象,并注册了要可视化其关系的张量。第 8 行和第 9 行用点语言生成并打印这些张量依赖关系,可以用图形方式呈现:

让我们来理解上面的依赖关系图:

  • 图中的节点代表一个张量或一组张量(例如神经网络中的所有变量)。
  • 如果 B 中至少有一个张量依赖于 A 中的一个张量,那么从节点 B 到节点 A 就有一条有向边。在我们的例子中,损失张量依赖于预测目标张量。所以从预测节点和目标节点到丢失节点有两条有向边。
  • 在每个节点中,你看到它的种类,比如【张量】、【占位符】、【变量】。
  • 在每个节点中,您还可以看到张量形状,例如(None,1),这意味着二维张量,第一维是动态长度 None,第二维是长度 1。而损失张量有 shape(),因为它是标量。

为了检查图结构的正确性,你需要解释为什么每条边都存在。这意味着解释那些张量之间的依赖关系。如果你无法解释某些边的存在,那么你脑海中的想法和你构建的实际图形之间就存在差异。这通常意味着一个错误。

一旦解释了所有的边,就可以通过调用 generate_assertions 方法来生成描述图的断言,如上面代码片段中的第 12 行所示。下面的清单显示了生成的断言。它们描述了相同的依赖图。它们将成为您代码的一部分,并将在所有未来的执行中被检查:

顺便说一下,如果您在 Tensorflow 代码中仔细设计了名称作用域,并在 TensorBoard 可视化中执行了严格的折叠,您可以得到与上面的库相同的东西。但是我认为图书馆很好,因为:

  1. 最有可能的是,你没有仔细设计你的名字范围——我说的对吗?
  2. 有了这个库,您可以生成那些张量依赖断言,这将有助于您在所有未来的执行中进行调试。

技术 3:张量方程评估

到目前为止,您已经验证了您定义的张量之间的依赖关系。最后一步是检查张量是否执行了正确的数值计算。例如,方程 B = A +1 和 B = A -1 都引入了从 B 到 A 的依赖关系,因此它们的依赖图是相同的。但是你需要指定 B=A+1 是正确的实现。使用张量方程评估对算法中的每个方程执行此操作:

  • 在每个优化步骤中,通过在会话中添加张量来评估所涉及的张量。
  • 在 numpy 中用那些张量求值写出相同的等式,以计算所需的值。然后断言期望值与实际值相同。

下一个列表显示了对损失张量的张量方程评估。 session.runparameter_update_operations,这是你通常拥有的东西,就像梯度下降步骤。除了这些通常的工作,现在 session.run 还评估预测目标损失张量。你可以从这三个张量计算出期望的损失。最后,您在第 4 行和第 5 行断言实际损失等于期望损失。注意,第 4 行和第 5 行是在 Python 世界中。在 Python 世界里,你可以使用循环,调用任意函数;这比在张量流世界里容易多了。

这些技术是否有效和实用?

我们已经将这些技术应用于我们所有的张量流学习者。下表报告了我们验证五个模型所花费的时间以及我们发现的错误数量。

表 1。使用断言技术检测到的错误

“学习模块”列列出了机器学习模型的名称。这些是深度强化学习中的演员-评论家算法。

“编码时间”列报告了我们为这些学习者编写代码所花费的时间,以小时为单位。我们总共花了 24 小时。

“验证时间”列报告了我们在验证中花费的时间。这包括编写断言、运行代码、观察断言违规和修复检测到的错误。我们总共花了 5 个小时。换句话说,验证需要多付出 20%的努力。

“Bugs detected by”列是对每种断言技术的细分。它显示了花费在每项技术上的时间百分比以及检测到的 bug 数量。总的来说,我们仅在 5 小时内就发现了 23 个错误。更重要的是,在应用了这些技术之后,我们知道我们的代码是正确的。

我们可以清楚地看到 VeriTensor 在检测 bug 方面是有效的。

为什么 VeriTensor 对检测 bug 有效?

首先,它们要求您通过断言来定义代码的正确性。编写规范并不是一个新想法,但 VeriTensor 使它变得切实可行:

  • 形状断言要求你写下你引入的张量的形状——很简单!
  • 张量依赖只需要你关注你引入的张量。这个阶段不需要检查数值运算。这将图形从数百个节点减少到十几个,使人类调查变得切实可行。自动生成断言减少了写下断言所需的时间。
  • 在张量方程求值中,你检查 Python 世界中的每一个方程。Python 世界比 Tensorflow 世界简单多了。

第二,在 Tensorflow 中找到 bug 的来源是一件令人畏惧的事情。人们花大部分时间定位错误的来源。一旦我们知道了根源,修复 bug 通常就很容易了。当按顺序应用时,绝对张量技术可以帮助你定位断层。当你在张量依赖阶段遇到问题时,你知道所有涉及的张量都有正确的形状。当你对一个张量方程有问题时,你知道依赖结构是正确的。简而言之,你可以更好地关注和定位每一个问题。

第三,VeriTensor 将 Tensorflow 代码调试从一门艺术变成了一个软件工程过程。如果您遵循一个简单的待办事项列表,该过程将确保代码是正确的:

  1. 为你引入的所有张量写一个形状断言。
  2. 解释这些张量之间的所有依赖边,并自动生成结构化断言。
  3. 写一个断言来检查算法中的每个等式。

验证和/或测试代码时的一个常见问题是知道如何进行以及何时停止。你从代码的哪一部分开始?应该检查哪些方面?你怎么知道你已经测试够了呢?

我们的三项技术消除了这些疑虑。你一个一个地应用它们,每种技术都有有限的和可管理的步骤。步骤的数量受到你在代码中引入的张量和方程的数量的限制——通常在十几个左右。最后,你知道你的代码是正确的。这是一个工程过程,不是一门艺术,不要忽视这样一个工程过程的力量。当人们知道确切的步骤时,他们会更有效率。

不要忽视这样一个工程过程的力量。当人们知道确切的步骤时,他们会更有效率。

验证代码正确性,而不是性能

我需要说明的是,VeriTensor 验证代码的正确性。它不评估代码的性能。正确性意味着你实现的代码符合你的想法。性能是它学习有意义模型的能力。性能通常通过绘制损失、交叉验证、测试数据来衡量。

只有在确定了代码的正确性之后,您才应该查看代码的性能。我称之为先正确后性能原则。否则,你需要担心糟糕的性能是因为学习算法不够好还是代码中存在一些 bug。显然你想要后者,但是你将很难证明你的代码没有错误。

先正确后性能原则:只有在确定了代码的正确性之后,才考虑代码的性能。

可悲的是,我看到许多人使用的模式是使用性能指标来驱动调试。当他们的代码没有学习时,他们通过绘制损失函数来开始调试。这违反了先正确后性能的原则,因此无法有效地发现 bug。这是因为:

  1. 性能指标是渐进定向的,而不是单调的。例如,损失函数应该随时间而降低。但是在任何时间点,包括你正在调试的时间点,这些数字都可能上升或下降。没有一个正确的值会让你很难识别出是否有问题。将这与断言进行比较:当存在断言违规时,您知道事情是错误的。
  2. 即使您可以看到性能指标明显是错误的,它们也不会告诉您错误源自哪里。将其与 VeriTensor 的故障定位支持进行比较。你分阶段发现 bugs 张量形状阶段、张量依赖阶段、张量值阶段。在每个阶段,你都可以专注。
  3. 在您修复了 bug 之后,很难为该 bug 编写回归测试。这是因为 bug 的起源和性能度量的症状离得很远。将这与使用断言的测试用例编写体验进行比较。你只需要把主学习循环变成一个学习时间步长更小的单元测试,就可以使测试更快地终止。您可以使用真实输入或随机输入。

支持我

如果你喜欢我的故事,如果你考虑通过这个链接成为一名灵媒会员来支持我,我将不胜感激:https://jasonweiyi.medium.com/membership。

我会继续写这些故事。

视频演示

一年半前,我在 Tensorflow 深潜活动上展示了 VeriTensor。这个演讲很受欢迎。这是演示文稿。

在那之后的 20 个月里,我将 VeriTensor 应用于我所有的机器学习代码,它一次又一次地工作。希望对你也有帮助。

通过转换数据来降低人工神经网络的复杂性

原文:https://towardsdatascience.com/reducing-the-artificial-neural-network-complexity-by-transforming-your-data-37ff50d94562?source=collection_archive---------37-----------------------

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

难以分类的数据集中的一个实际例子

介绍

降低模型复杂性的需求可能源于多种因素,通常是为了降低计算要求。然而,复杂性不能任意降低,因为经过多次反复的训练和测试,这是一个提供良好结果的模型。关于这一主题的研究非常活跃,例如,[Koning 等人,2019 年]针对用于系外行星探测的 CNN 提出了一个解决方案:

卷积神经网络(CNN)的可训练参数太多,影响了计算性能…我们提出并检验了两种降低 AstroNet 复杂性的方法…第一种方法只对 AstroNet 的层数进行了战术性减少,而第二种方法也通过高斯金字塔修改了原始输入数据

第二种方法(修改或转换输入数据)很常见。根据谷歌的机器学习速成班,完成转换主要有两个原因:

  1. 强制转换:使数据与算法兼容,例如将非数字特征转换为数字特征。
  2. 质量转换:帮助模型更好的执行,例如归一化数字特征。

[Koning et al .,2019]提出的这种转型,以及本文提出的这种转型,就属于第二类。

目标

我为扑克手数据集【Cattral 等人,2007】提供了一种线性数据转换,并展示了这种转换如何帮助降低多层感知器 (MLP)神经网络的模型复杂性,同时保持分类器的准确性并减少高达 50%的训练时间。扑克手数据集是公开可用的,并且在 UCI 机器学习知识库【Dua 等人,2019】中有非常好的记录。

在之前的故事中,我谈到了扑克手数据集。3 层 MLP 表现相对较好。今天,我向大家展示,通过理解我们正在处理的数据并对其进行转换,使其更适合我们试图解决的问题,用一个不太复杂的模型实现同等的准确性是可能的。

数据集描述

这个特殊的数据集对人类非常友好。它使用 11 维描述扑克手牌,明确列出每张牌的花色和等级,以及相关的扑克手牌。每个数据实例包含 5 张卡片。

编码

以下是数据集编码描述。详情请点击链接。

组曲 : 1 :红心、 2 :黑桃、 3 :方块、 4 :梅花
排位 : 1 : Ace、 2 :2、…、 10 :十、 11 :千斤顶、12

示例

红桃同花顺的一种编码(使用该模型可以有多种表示法)是:
数据 : 1,1,1,10,1,11,1,12,1,13,9
解释 :红桃-Ace、红桃-10、红桃-Jack、红桃-皇后、红桃-王、红桃-同花顺

皇家同花顺照片:格雷姆 Main/MOD

转换

这种变换是基于这样的事实,即牌(在一手牌中)出现的顺序并不重要(对一手牌进行分类),并且对一手牌进行分类的一个更重要的属性是出现在一手牌中的具有相同等级或花色的牌的数量(即基数)。原始数据集模型人为地强调了卡片出现的顺序(样本是 5 张卡片的有序列表),并且它没有显式地编码每个套件或等级的基数。前提是,通过使该属性在数据中显式可用,与使用隐藏了该属性的原始模型时的相同神经网络相比,神经网络能够更好地对数据集进行分类。

线性变换

下面是从原来的 11D 空间到新的 18D 空间的线性变换。线性变换是优选的,因为它降低了计算要求。新的维度和描述包括:

****属性 1 到 13:13 个等级,即 1:王牌,2:二,3:三,…,10:十,11:杰克,12:女王,13:国王。
属性 14 到 17:4 组,即 14:红心,15:黑桃,16:方块,17:梅花
:【0–5】。每个维度代表手中的级别或套件基数。
最后一个维度:扑克手0–9。

编码和示例

以下是皇家同花顺的转换示例。

以原始尺寸表示(11D):

数据 : 1,1,1,10,1,11,1,12,1,13,9
编码 :红心-Ace,红心-10,红心-杰克,红心-皇后,红心-国王,皇家-同花顺

新维度中的表示(18D):

数据 : 1,0,0,0,0,0,0,0,1,1,1,5,0,0,0,9
编码 : 第 1 列= 1 Ace ,第 2 至第 9 列=无(无该套牌),第 10 至第 13 列= 1 十张,.

下图显示了这个特定示例的视觉转换。

从 11D 到 18D 的线性变换(作者图片)

新模型以相同的方式表示任何给定的 5 张牌的组合,而不管顺序如何,并且明确地公开了对扑克手有用的信息,例如相同等级的牌的数量。****

工具

Scikit-learnNumpySeaborn 分别用于机器学习、数据处理和可视化。

代码在哪里?

一个带有 MLP、可视化和线性变换的 Jupyter 笔记本在这里是。每个实验的分类报告混淆矩阵也包含在 Jupyter 笔记本中。

结果

在我的之前的故事中,我展示了一个 MLP,它有个 100 个神经元的 3 个隐藏层alpha=0.0001学习率=0.01** 使用原始数据集,达到了 ~78%的准确率。这些超参数是在对大范围的值进行广泛的网格搜索后发现的。因此,将基于这些相同的值进行以下测量。**

韵律学

MLP 精度用F1宏平均度量来测量。对于扑克手数据集来说,这是一个合适的指标,因为它很好地处理了这个数据集极度不平衡的事实。sci kit-了解的文档:

F-measure 可以解释为精度和召回率的加权调和平均值……在不经常出现的类仍然很重要的问题中,宏平均可能是突出其性能的一种方法

分类报告 显示不同的实验。它包含宏观平均 F1 指标等。

此外,测量并报告 MLP 训练时间

原始数据的 3 个隐藏层 MLP

****复杂度:每个隐层有 100 个神经元。

****精度:对于 3 层 MLP 和原始数据(还没有应用转换),在 F1-score 宏观平均中得到一个 ~80%的精度。参考之前的帖子,了解这个结果是如何实现的。

训练时间 : 20+秒

分类报告

 precision    recall  **f1-score**   support
           0       1.00      0.99      0.99    501209
           1       0.99      0.99      0.99    422498
           2       0.96      1.00      0.98     47622
           3       0.99      0.99      0.99     21121
           4       0.85      0.64      0.73      3885
           5       0.97      0.99      0.98      1996
           6       0.77      0.98      0.86      1424
           7       0.70      0.23      0.35       230
           8       1.00      0.83      0.91        12
           9       0.04      0.33      0.07         3
    accuracy                           0.99   1000000
   **macro avg       0.83      0.80      0.78   1000000**
weighted avg       0.99      0.99      0.99   1000000

具有转换数据的 2 个隐藏层 MLP

在这个实验中,通过丢弃一个 100 个神经元的隐藏层来降低模型的复杂性,并且使用转换的(18D)数据。其他一切都保持不变。

****精度:对于数据转换后的二层 MLP,可以观察到 ~85%的精度

****训练时间:10-15 秒

 precision    recall  **f1-score**   support 0       1.00      1.00      1.00    501209
           1       1.00      1.00      1.00    422498
           2       1.00      1.00      1.00     47622
           3       0.97      1.00      0.98     21121
           4       1.00      0.99      1.00      3885
           5       1.00      0.98      0.99      1996
           6       0.83      0.48      0.61      1424
           7       1.00      0.41      0.58       230
           8       0.38      0.75      0.50        12
           9       0.50      1.00      0.67         3 accuracy                           1.00   1000000
 **macro avg       0.87      0.86      0.83   1000000**
weighted avg       1.00      1.00      1.00   1000000

1 个隐藏层 MLP,包含转换后的数据和原始数据

精度: 单层 100 个神经元,经过变换数据的 MLP 达到了 ~70%的精度。使用原始数据集,它达到了 ~30%的准确率

训练时间 :
对于转换后的数据集约 10 秒,对于原始数据约 12 秒。

其他实验

随意看看 Jupyter 笔记本,里面有这些和其他实验的代码和结果。

结论

通过应用一个简单的线性变换,使数据集对人类不太友好,但对 ML 更友好,我证明了一个更简单的 MLP 模型在更少的计算时间内提供了等效的结果。具体来说,100 个神经元的隐藏层被移除,而不损害分类器的性能。结果表明,神经网络的精度与更复杂模型的精度相当或更好,训练时间减少了 25%到 50%。

参考

卡特拉尔和奥帕彻(2007 年)。扑克手数据集https://archive.ics.uci.edu/ml/datasets/Poker+Hand
卡尔顿大学计算机科学系。
智能系统研究小组

Dua d .和 Graff c .(2019 年)。http://archive.ics.uci.edu/mlUCI 机器学习资源库。加州欧文:加州大学信息与计算机科学学院。

塞巴斯蒂安·科宁,卡斯帕·格里芬,埃里克·波斯特马 (2019) 降低人工神经网络复杂性:系外行星探测案例研究。https://arxiv.org/abs/1902.10385

以交互作用为代价减少细胞神经网络的碳足迹——深度方向和点方向卷积

原文:https://towardsdatascience.com/reducing-the-carbon-foot-prints-of-cnns-at-the-cost-of-interactions-depthwise-pointwise-conv-5df850ea33a4?source=collection_archive---------37-----------------------

作者:sour adip Chakraborty&Rajesh Shreedhar Bhat

图 1:对手写数字进行分类的 CNN 序列

卷积神经网络 (CNN 的)在图像分类任务中极其成功,甚至在几个复杂的视觉分类领域中超过了人类的表现。

强大的 CNN 的成功之旅始于 ImageNet 大规模视觉识别挑战 2。ImageNet 大规模视觉识别挑战赛,或 ILSVRC ,是一项年度比赛,使用来自 ImageNet 数据集的子集,该数据集由超过 20,000 个类别的图像组成,这些类别包括“车辆”、“果实”、“动物”等。拥有超过数百张图片。

ILSVRC 挑战导致了深度卷积神经架构的发展(图 1 ),该架构在庞大的 Imagenet 数据集中产生了最先进的结果。我们非常熟悉的 Imagenet 模型以及我们使用 迁移学习 在各种任务中使用的 Imagenet 模型都是 ILSVRC 挑战赛的直接产物,如 AlexNet、VGGNet、ResNet、GoogleNet、等。

图 2: AlexNet CNN 标准架构

话虽如此,但不容忽视的事实是,这种高精度是以非常复杂的深层架构和大量参数为代价的。

图 3: AlexNet CNN 图层&参数表

如图 2 和图 3 所示,像 AlexNet 这样的架构需要数百万个参数来训练,以给出最先进的结果。尽管考虑到我们现在拥有的计算资源,这看起来没什么大不了的,但从环境的角度来看,这是危险的。

此外,迁移学习的出现大大减少了可训练参数的数量,尽管乘法的数量保持不变。此外,在涉及新域或与训练分布完全不同的域的任务中,我们需要微调整个网络的参数,这是一个大问题。

深度神经模型的能量和策略考虑

Emma Strubell,Ananya Ganesh 和 Andrew McCallum 发表的论文《@ ACL’2019中关于 NLP 中深度学习的能源和政策考虑》受到了很多关注,从那以后,在监测和减少深度神经模型的碳排放方面发生了重大的研究工作。

图 4:图表:麻省理工技术评论,来源:Strubell 等人。铝

马萨诸塞大学阿姆赫斯特分校的研究人员观察到,训练深度神经模型排放的碳相当于五辆汽车,这在深度学习社区引起了深切关注。在博客“单个人工智能的碳排放量是一辆汽车的近 5 倍”中,作者提到了运行非常深的网络对环境的其他一些担忧和影响。

话虽如此,尽管神经模型的总碳排放量现在可能不是一个大问题,但随着模型的复杂性和模型参数的数量呈指数增长,它将在未来成为一个大问题。

图 5a: ImageNet CNN 模型及参数总数

图 ImageNet 模型的准确性&复杂性可视化

从图 5a 和 5b 可以清楚地看出,在 ImageNet CNN 模型中有大量的参数,这些参数以百万计,并且需要大量的时间和计算来从零开始训练模型。因此,在下一节课中,我们将讨论如何使用深度方向可分离卷积来降低 CNN 模型中卷积运算的计算量,这种卷积已在现代 CNN 架构中使用,以降低模型的复杂性。

减少卷积层的计算——深度方向可分离卷积

在深入研究深度可分卷积之前,让我们先了解并计算正常卷积运算的计算。

图 6:普通卷积运算,输入&输出尺寸&滤波器

假设输入特征图的尺寸为 Df *Df *M,,其中 M 是滤波器的数量/深度, *Df Df 是特征图的宽度和高度。让我们假设,我们正在用大小为 DkDkMN 个滤波器进行卷积,因此输出特征图将具有 DgDgN. 的形状

因此,现在我们将通过估计乘法的次数来估计卷积运算的计算复杂度。由于乘法是一种比加法更昂贵的运算,它可以告诉我们模型的复杂性。因此,让我们估计一下这个例子的乘法次数(图 6)

一个实例的乘法次数= Dk * Dk * M = Dk * M . 现在,我们需要在整个输入上滑动滤波器,从输出维度可以清楚地看出,已经执行了沿宽度的 Dg 卷积和沿高度的 Dg 卷积,结果乘法总数为: Dg * Dk * M.

因为有 N 个这样的滤波器,所以整个输入的乘法总数=Dg * Dk * M * N———(1)

深度方向可分离卷积-减少计算:

现在让我们深入研究深度可分卷积的架构和计算,以及它如何减少乘法次数。因此,深度方向的可分离卷积可以分成两个部分:

  1. 深度方向卷积:滤波阶段

在这种情况下,卷积最初应用于单个输入通道,而不是像正常卷积那样跨越深度。

图 7:深度方向卷积中的卷积运算

如图 7 所示,卷积滤波器的尺寸为 DkDk1,应用于相同的输入,但是一次仅应用于一个通道,因此需要 M 这样的内核/滤波器,而每个内核的卷积数量沿着输入的宽度保持相同的 Dg ,沿着输入的高度保持相同的 Dg

所以,一个滤波器的乘法次数=Dk * Dk * Dg * Dg=Dk * Dg。由于有 M 个这样的滤波器,所以乘法总数将是 **Dk Dg M.

最后,与每个核卷积后的输出将具有尺寸 *Dg Dg ,并且有 M 个这样的核,它们将使得最终输出具有形状 DgDgM.

2。逐点卷积:组合阶段

图 8:逐点卷积中的卷积运算

深度方向可分离卷积的下一阶段是通过逐点卷积的组合阶段。因此,这里的输入是来自前一阶段的输出,其形状为 DgDgM. 。在这种情况下,每个内核的形状为 11M ,其应用于整个输入,并保持输入的高度和宽度,如图 8 所示。因此,来自这样一个内核的输出将是 Dg*Dg 的形状。应用 N 这样的内核将导致期望形状的输出,即 DgDgN.

因此,输入维上一个内核的乘法次数为。=Dg * Dg * M=Dg * M .既然有 N 个这样的核,那么乘法的总数= Dg MN

因此,在深度方向和点方向卷积之后,我们获得了所需的输出,乘法总数为:

Dk * Dg * M+Dg * M * N = M * Dg(Dk+N)————( 2)

现在让我们比较深度方向可分离卷积和标准卷积中的乘法:

标准卷积中的乘法/深度方向可分离卷积中的乘法= rho

ρ=(Dg * Dk * M * N)/(M * Dg(Dk+N))

ρ****=(Dk * N)/(Dk+N)—————( 3)

因此,在正常情况下,让我们取一个非常标准的值 DkN 来理解乘法运算的减少。对于 N = 1024,Dk = 3,rho = (9*1024)/(1024+9) = 8.9 ~ 9。

因此,它几乎将计算量减少了 9 倍,这在参数数以百万计时是非常巨大的,并且这仅仅是一次卷积运算。现在,想象一下,当卷积层数更多时(任何标准 ImageNet 模型都是如此),效果会有多好。这已经在 MobileNets 中非常成功地实现了,mobile nets 是一类用于移动和嵌入式视觉应用的快速有效的模型。

图 9:对 MobileNets 使用深度方向卷积前后的比较

从图 9 中可以清楚地看出,模型参数的数量已经显著减少,而精度没有太大下降,这使得该架构如此特别。现在,让我们来理解和讨论通过深度方向可分离卷积以减少计算为代价而导致的信息损失。

以减少计算为代价的信息损失——深度方向可分卷积

基本上,深度方向卷积与标准卷积的主要区别在于,在深度方向,滤波器应用于特征图的高度和宽度,而不是深度。随后使用逐点卷积,进行深度范围内的特征组合。

而在标准卷积中,核同时在所有维度上操作,因此它们被联合学习,这有助于它们有效地捕捉所有可能的信息和交互。

因此,我们可以推断,在深度方向可分离卷积中,可能存在某些未被有效捕获的相互作用。(因为卷积运算是对每个维度分别进行的,然后再进行组合,所以在这个过程中可能无法准确地捕捉到跨维度的相互作用。)

图 10:联合和边际概率分布

让我们从二元分布的角度来理解这种情况。假设我们有两个变量 x1 & x2 ,pdf 为 P(x1) & P(x2)。 因此,如果我们必须理解变量的联合行为,我们应该研究变量的联合分布【P(x1,x2) 从而能够捕捉所有可能的变异来源。但是,如果我们用边边角角即【P(x1)&【P(x2)后来的结合边边角角的信息来评论联合行为,那就不准确了。

因此,我们知道,由于设计深度方向可分离卷积的方式,可能会丢失一些相互作用。但是,正如我们在图 9 中观察到的,尽管丢失了信息,但准确性并没有显著降低,这表明相互作用可能对解释响应变量(y)没有多大帮助。

最终想法:

我们希望这篇文章能够让你理解减少计算和减少碳足迹的重要性,同时从环境的角度训练深度模型。

我们还解释了深度方向可分离卷积如何在模型复杂性和准确性之间有效地折衷。

* [## Souradip Chakraborty —数据科学家—沃尔玛印度实验室| LinkedIn

我是一名有抱负的统计学家和机器学习科学家。我探索机器学习、深度学习和…

www.linkedin.com](https://www.linkedin.com/in/souradip-chakraborty/) [## 专家|谷歌开发者

机器学习我是 Souradip Chakraborty,目前在沃尔玛实验室担任数据科学家(研究)

developers.google.com](https://developers.google.com/community/experts/directory/profile/profile-souradip_chakraborty) [## Rajesh Shreedhar Bhat —中等

阅读 Rajesh Shreedhar Bhat 在媒体上的文章。数据科学家—沃尔玛实验室| Kaggle 竞赛专家|…

medium.com](https://medium.com/@rajesh_bhat)

参考资料:

  1. Emma stru bell Ananya GaneshAndrew McCallum的论文'NLP'中深度学习的能源和政策考虑,ACL'2019。
  2. Zayan Guedim 的博客“ 单个人工智能的碳排放量比一辆汽车 ”高出近 5 倍。
  3. 博客' 卷积神经网络中的参数数量和张量大小(CNN) ' 作者Satya mal lick&Sunita Nayak。
  4. Andrew G. Howard 等论文' MobileNets:用于移动视觉应用的高效卷积神经网络 '
  5. 关于 深度可分卷积 的精美视频讲座。
  6. 博客'对监督学习问题应用 PCA 的风险和注意事项'。*

QuickSight 中的参考线

原文:https://towardsdatascience.com/reference-lines-in-quicksight-9e09bd97910c?source=collection_archive---------49-----------------------

快视提示公司

一步一步的过程

Miguel A. Amutio 在 Unsplash 上拍摄的照片

前几天,我在 AWS QuickSight 的仪表板上工作,创建了一个条形图。当我打开我的视觉设置标签,我看到一个新的部分:“参考线”。

我真的很兴奋,因为我过去喜欢画面上的参考线,所以我试了一下。您将在这里找到一个逐步的过程,以及对该功能在此阶段的局限性的一些想法。

我将在本文的所有例子中使用超级商店数据集。

什么是参考线?

参考线是图形中用户定义的垂直线或水平线。它用于轻松地将数据点与该参考进行比较。

例如,您可以查看季度至今的销售额,并有一个显示季度目标的参考线。你将能够快速评估你是否已经完成了目标。

另一个例子是,如果您查看跨团队的收入,将参考线设置为平均值,这样您就可以很容易地知道哪个团队高于/低于平均值。

用于参考线的数据可以是一个固定的数字(例如:一个目标),也可以是一个计算出来的数字(例如平均值、中值、最大值、最小值……)。

如何在 AWS QuickSight 中创建参考线?

在 QuickSight 中,参考线可用于 3 种视觉类型:

  • 折线图
  • 条形图
  • 组合图表

创建图表后,单击图表右上角的“Format Visual”图标,这将打开屏幕左侧的“Format Visual”窗格。

来自作者的 QuickSight 截图。

来自作者的 QuickSight 截图。

“格式可视化”窗格允许您格式化标题、X 和 Y 轴以及数据标签。现在…创建参考线!

点击参考线菜单,然后点击“添加新线”打开创建一条线。

然后提示您选择线路设置。

第一部分包含您想要显示的数据:常数行或计算行。

  • 对于常量,将要求您输入一个值
  • 对于计算,将要求您提供哪一列(即字段)和哪一级别的汇总以及您要计算的计算(平均值、最小值、最大值或百分位数)。

请注意,您可以根据图表中没有的字段添加计算线!

菜单的其余部分包括线条样式(全、点或虚线以及颜色);以及标签类型、位置、值格式和字体大小。

最后,我得出了这样一个条形图。在此过程中,我还格式化了轴和数据标签。

来自作者的 QuickSight 截图。

第一印象

你可能会在上面的图表中注意到的第一件事是,自动定位不是很好;文本和值离 x 轴太近。没什么大不了的,但是可读性可以更好。

解决这个问题的一个方法是对这个图形使用垂直布局。我不喜欢因为那样的原因而不得不改变我的 viz 选择,但是嘿——读起来更好。所以由你来决定在你的用例中什么是最重要的。

来自作者的 QuickSight 截图。

然后,我尝试在选项卡上添加一个参数,看看平均值是否会自动重新计算。确实如此。那很酷。

来自作者的 QuickSight 截图。

我认为这个功能是对 AWS QuickSight 的一个很好的补充。我曾经是 Tableau 中参考线的忠实粉丝,所以我很高兴看到 QuickSight 团队的崛起!

当然,我希望能够在线上或线下着色,或者创建像 Tableau 一样的乐队,但我相信有一天我会发现它在 QuickSight 中直播。它总是充满惊喜。

享受使用参考线的乐趣。

提炼数据是训练机器学习的关键

原文:https://towardsdatascience.com/refined-data-is-the-key-to-train-machine-learning-29f863e671f1?source=collection_archive---------48-----------------------

预测模型的好坏取决于为其提供燃料的数据,这意味着它们需要精确、标准化的数据才能获得有意义的结果。

所有的机器智能都是由数据驱动的。这不是突破性的,甚至不是新闻——我们几十年前就知道数据的价值了。然而,并不是所有的数据都是平等的,我们将从优先考虑流入数据质量的角度来看待执行机器学习产品。

机器学习(ML)是人工智能的一个特定子集,在图像识别、自然语言处理和专家系统等广泛的关键应用中发挥着关键作用。

ML 解决了单纯用数值手段无法解决的问题,主要是通过有监督或无监督的学习:

  • 在监督学习中,使用一组带标签的输入数据和对数据的已知响应(输出)来训练算法。它通过比较实际输出和正确输出来发现错误。
  • 在无监督学习中,该算法使用一组未标记的输入数据来探索数据并找到其中的一些结构。

机器学习工作流程概述:

机器学习工作流程示例,从原始数据到预测

第一步涉及数据收集,但这只是构建预测性解决方案的一部分,下一步是数据准备,这一步常常被忽视。

机器学习发展的阶段包括:

  1. 数据收集
  2. 数据准备
  3. 发展假设
  4. 模型构建
  5. 模型部署
  6. 模型评估

机器学习的现状

IDC 发布了他们的AI in 2020 and beyond predictions,其中他们假设智能自动化的有效使用将需要在 it 需要支持的数据清理、集成和管理方面做出巨大努力。

数据清理是一项费力的手动任务,一直困扰着数据专业人员。如果没有使用自动化高效清理数据的有效方法,组织将无法实现其数字化转型目标。IDC future escape报告指出,解决遗留系统中过去的数据问题可能是一个巨大的进入障碍,尤其是对大型企业而言,这显示了采用数字战略中普遍存在的困难。

根据晨星公司的数据,仅去年一年,组织 预计在数字化转型项目中投资 1.3 万亿美元 。麦肯锡后来宣布 这些项目中有 70%失败 。对于那些在家里记账的人来说,这些失败给企业造成了超过 9000 亿美元的损失。无论投资损失有多大,组织都无法承受数字化转型的持续失败。干净、标准化的数据对于释放数字化转型工作的价值至关重要,但是以您需要的状态获得您想要的数据是繁琐、耗时且昂贵的。

上图中突出显示了一个常见的误解,即一旦所有数据都在一个公共位置,我们就可以将它插入任何我们想要的位置。但是这个过程并没有那么简单。来自不同来源的数据缺乏一个共同的标准,位于数据之上的应用程序无法完全实现,因为在数据(有湖或没有湖)和企业应用程序之间存在巨大的障碍。细化的数据需要以可靠、可重复、可预测的格式出现。

在基层,为了释放这种价值,需要克服的操作障碍使创新慢如蜗牛。在许多组织中,数据专业人员将 80%的时间花在清理和准备数据上,而不是花在分析和建模上。数据专业人员不应承担数据准备的保管任务。没有自动化层,有些任务很难,有些更难,其余的几乎不可能。

"数据专业人员不应该承担数据准备的保管任务."

预测模型的好坏取决于它们所基于的数据,因此它们需要由精炼、标准化的数据推动,以产生既实用又代表现实的结果。

典型的数据提炼过程是复杂的

当我们看到提炼野外发现的数据的过程时,这并不像将数据插入 BI 层或可视化工具那样简单。通常有许多步骤,如下图所示:

一旦数据最终变得干净且可用,下一步就是选择一种算法。算法的几个特征之间存在权衡,例如训练速度、预测准确性和内存使用。随着 AutoML 的兴起,算法选择也趋向于自动化。如果你不熟悉自动化机器学习系统,你可以在这里阅读,但一般来说,有了一个精确的数据集,AutoML 系统可以为你设计和优化机器学习管道。

现在我们已经介绍了 ML 工作流,让我们通过构建一个由精化数据和 AutoML 支持的简单产品推荐系统来尝试应用一些讨论的概念。

战略必须赶上人才

许多组织担心数据方面的人才短缺,但问题的根源通常是战略短缺。无论团队有多大,数据多样性对每个人来说都是一个障碍。有很多平台,你可以在那里找到构建机器学习系统的资源,还有很多地方可以找到一些最常用的数据集。数据管理平台通过自动化大部分保管工作,包括数据集细化,允许更快的模型就绪部署( 以及其他优势 )。

简化的数据准备和处理

通过 Namara 输入数据处理与将原始数据转化为可用资产相关的保管任务。工作流程再次简化,如第一幅图所示:

在这个例子中,我们将检查一个使用 Namara 提炼的亚马逊客户评论数据集样本。对于协同过滤方法,精确的历史数据足以进行预测。上图中突出显示的步骤,ETL、丰富、搜索、角色管理和 API,都是由平台处理的。

现在我们有了现成的数据,让我们选择一个算法。我们有很多方法可以解决这个问题。不过,现在让我们保持简单,使用 Turi Create 来简化 Python 中机器学习模型的开发。

AutoML —代码

一旦构建完成,就可以进行模型评估和部署了。我们还可以绘制图表和可视化来描述数据——如您所见,在进行分析时,我们看到的只是冰山一角。

总结一下

如前所述,70%的数字化转型努力失败了,这表明在预测性解决方案和数据策略方面存在严重的错位问题。预测模型的好坏取决于为其提供燃料的数据,因此它们需要精确、标准化的数据,以获得有意义的结果。组织必须采用并利用数据管理策略( think DataOps )以及 AutoML 系统来释放数据的价值。这将使我们能够更高效、更准确、更大规模地提供见解。

原载于https://blog.thinkdataworks.com

多年来的精炼利润

原文:https://towardsdatascience.com/refining-margins-over-the-years-21827d04b9a4?source=collection_archive---------42-----------------------

多年来,原油加工和精炼燃料的价格如何变化,它们之间的关系如何?

斯科特·罗杰森在 Unsplash 上拍摄的照片

在我的上一篇文章中,我们看到墨西哥湾沿岸在很大程度上负责美国的炼油加工。那么,为什么炼油厂将原油加工成成品油?认识产品和原油之间的利润。

与往常一样,请注意,以下可视化中使用的所有数据均可从美国能源信息管理局公开获得。

一家炼油厂的毛利追踪“价差”,即成品油价格和原油价格之间的差额。让我们将常用的 3–2–1 价差定义为((2 *汽油价格)+(1 *柴油价格)—(3 *原油价格))/ 3

下面的代码计算裂纹扩展,然后创建一个随时间变化的散点图,以及计算的平均值—见代码后的图表

# Calculate 3-2-1 spread, using Conventional Gas, ULSD, and West Texas Intermediate crude pricesPost2006['3-2-1, WTI-base'] = (2*Post2006['Conv Gas, $/gal']*42 
+ Post2006['ULSD, $/gal']*42 
- (3*Post2006['WTI mo. avg, $/bbl'])) / 3# Plot spread and average over timeplt.figure(figsize=(10,10))plt.scatter(Post2006['Date'],Post2006['3-2-1, WTI-base'], c='b', marker='x', label='3-2-1 spread, $/bbl')y_mean = [np.mean(Post2006['3-2-1, WTI-base'])]*len(Post2006['Date'])plt.plot(Post2006['Date'],y_mean, c='black, marker='x', label='Avg')plt.legend(loc='upper left', fontsize=12)
plt.xticks(np.arange(0, 100, step=12), rotation=80, fontsize=12)
plt.yticks(fontsize=12)
plt.show()

作者使用 EIA 的公开数据得出的利润率的改进趋势

上面的图表告诉我们什么?提炼 3 桶原油以生产和销售 2 桶汽油和 1 桶柴油的净利润平均为每桶原油 17.50 美元。

什么是关于允许炼油厂制造燃料的原油?原油可以被认为是轻质和重质化学成分的混合物——在极端情况下,轻质成分最终成为点燃我们烧烤炉的液化石油气,而重质成分最终成为道路焦油中的沥青。

在两种极端情况的中间,重组分和轻组分被混合以制造发动机燃料,如汽油、柴油和喷气燃料。

原油混合物中的轻组分越多,原油就越“轻”。原油越轻,其 API 比重就越高。同样:原油中重质成分越多,API 比重越低。

这些年来,美国炼油厂的原油 API 比重如何变化?下面的代码用于生成下图

*# 1st, create two separate scatter plots on two separate axesAPI = pg.Scatter(x=crudesulfurandAPI['Date'], y=crudesulfurandAPI['Crude sulfur, %'], name = 'Sulfur, %')Sulfur = pg.Scatter(x=crudesulfurandAPI['Date'], y=crudesulfurandAPI['API'],
                        # Specify axis
                        yaxis='y2', name = 'API, deg F')# 2nd, define layout with axis titles, figure title, and image dimensions.layout = pg.Layout(height=500, width=900,
                   title='Crude sulfur and API since 1985',
                   # Same x and first y
                   xaxis=dict(title='Date'),
                   yaxis=dict(title='Sulfur, %', color='blue'),
                   # Add a second yaxis to the right of the plot
                   yaxis2=dict(title='API, deg F', color='red',
                               overlaying='y', side='right'),
                   )# Last, attribute layout to figure and add annotation
fig = pg.Figure(data=[API, Sulfur], layout=layout)fig.add_annotation(
            x=200,
            y=1.45,
    font=dict(
            family="Courier New, monospace",
            size=18,
            color="black",
            ),
            text="29.78 API, 1.48% Sulfur")# Finally, update location of legendfig.update_layout(legend=dict(x=0.15, y=0.9), title=dict(x=0.15, y=0.9))*

1985 年以来原油比重和含硫量的变化趋势。由作者使用 EIA 数据创建

从 80 年代中期到 2008 年中期,美国炼油厂原油的红色 API 比重一直在下降,当时达到 29.8。此时,美国炼油厂开始看到北达科他州巴肯页岩油田的高 API 比重轻质原油涌入。

你会观察到硫的蓝色趋势。我们将在另一篇文章中关注这一点,但就目前而言,原油中的高硫意味着炼油厂需要去除更多的硫,以最大限度地减少有害的毒素释放。一般来说,重质和酸性原油比轻质和低硫原油便宜。

3–2–1 的差价取决于原油价格和成品油价格。就我们的目的而言,让我们考虑精炼产品:汽油、喷气燃料和超低硫柴油(ULSD)。将这些价格追溯到 2006 年,并与原油价格进行对比,得出了以下双图。

Seaborn pairplot 由作者创建,使用 EIA 的公开数据。

那真是令人大饱眼福!底线:**

汽油、喷气燃料和 ULSD 价格都显示出与原油价格有很强的线性相关性。它们也彼此线性相关,即所有燃料价格通常一起变化。

汽油、ULSD 和喷气燃料的直方图都显示了两个峰值——表明出现了两个常见的峰值。这些是夏季(四月中旬到八月)和冬季(每隔一个月)的价格点。

在继续之前,有一点需要注意:WTI 或西德克萨斯中质油是原油的两个主要价格标志之一,另一个是布伦特原油。关于这一点的更多信息,请见本文末尾。

从上面我们学到的一切,加工原油的 API 可以通过汽油价格来预测吗?毕竟,较轻的原油——即较高的 API——有助于生产更多的汽油。因此,油价上涨难道不会导致炼油厂加工更多高 API 原油吗?如果我们将数据追溯到 2006 年,我们会发现什么?

Woah …没有关联。这表明炼油厂能够处理不同类型的原油原料,以维持其目标气体、柴油和喷气发动机产量。在下一篇文章中,让我们使用数据可视化进一步评估炼油厂配置。

在我离开之前,这里有一张 WTI 原油价格对比布伦特原油价格的图表,可以追溯到 80 年代中期。现在你理解的关键点是:从历史上看,这些标记相互接近,所以我目前并不关心在分析中使用哪个标记。

这里有一个有趣的地方。你会注意到,从 2011 年开始,价格出现了背离。这是怎么回事?随着页岩原油涌入市场——还记得原油 API 如何在上述趋势中开始向上发展吗——美国原油价格标志跌至国际基准布伦特原油以下。

为什么布伦特也不蘸呢?难道所有原油价格都不应该因供应过剩而下跌吗?不会,因为美国以外的市场最初不允许进口美国原油,直到 2014 年出口禁令取消。

这里是完整的回购的链接。

下期帖子再见!一如既往,欢迎任何反馈。

反映和比较餐馆评论的不同情感分类模型

原文:https://towardsdatascience.com/reflecting-and-comparing-different-sentiment-classification-models-for-restaurant-reviews-d109105b2cb7?source=collection_archive---------56-----------------------

各种用于情感分类的预处理模型和技术将会在之前文章的实验基础上进行讨论和比较

反映和比较餐馆评论的不同情感分类模型

在这篇文章中,我将比较以前用于情感分类的模型,并讨论基于手头的数据,结果可能会有什么不同。我将使用在我以前的帖子中使用的情感分类方法的结果,如下所示:

  1. 带弓的情感分类
  2. 使用 TF-IDF 对餐馆评论进行情感分类
  3. 使用单词嵌入的情感分类(Word2Vec)
  4. 使用 Doc2Vec 对评论进行情感分类
  5. 使用 PyTorch 中的逻辑回归进行情感分类
  6. 使用 PyTorch 中的前馈神经网络进行情感分类
  7. 在 PyTorch 中使用 CNN 对餐馆评论进行情感分类

在所有这些帖子中,Yelp 餐馆评论数据集被用作输入数据,只有部分数据集被用于实验,以更快地获得结果并快速建立模型原型。在情感分类中,模型被训练来检测三种情感——积极的、中性的和消极的。

由迪皮卡·巴德提供的按情感分类的餐馆评论示例

预处理技术

在弓的第一篇帖子中,我已经详细解释了可以用于预处理的各种方法。解释了删除停用词,但没有使用。对于情感分类问题,这是非常重要的,因为像“not”这样的停用词如果被移除,会改变句子的情感。

I did not like the food.--- After Stop words removalI like food.

停用词起重要作用的情况应在分析期间保留,并应用作特征输入。

对于标记化,我们使用 Gensim 的[simple_preprocess](https://radimrehurek.com/gensim/utils.html),它易于使用,并以一种干净的方式给出了更快的句子标记化方法,其中它删除了标点符号,并将大小写改为小写并返回标记。构建原型更快,但是在标点符号可以添加重要信息(如表情符号或单词的大写字母)来强调感觉的情况下。这可以在模型中使用,在这种情况下,可以使用 BOW post using regex 中提到的自定义标记化。这可以改进你试图在更大范围内预测情绪水平的模型,比如从 1 到 10 的评分。

我们知道,语言是由互相派生的词组成的,或者由于语法上的不同原因,经常与不同的后缀或前缀结合在一起。获得词根,以便在创建唯一单词的字典时,其大小更小,这对抗了机器学习模型的维数灾难。这样做的目的是在保留模型所需的所有基本信息的同时,最大限度地减少特征的数量。词干化和词汇化是实现这一目标的常用方法。

波特词干分析器用于所有这些方法中的词干分析。词干提取确实得到了词根,但是忽略了它在语言中的实际存在。另一方面,词汇化是将单词简化为其规范形式或词典形式或一组单词的引用形式(词汇)。

are, is -> bestood -> stand

这需要更多的步骤,但是可以看出,它可以减少唯一单词的数量,因为它可以适当地将其简化为词根形式。下面的代码展示了如何实现词汇化。词性标注有助于获得更好的词根,因为它可以相应地应用语法规则。

输出:

模型比较

使用的模型从简单的机器学习技术到用于情感分类的深度学习方法。以 BOW 为输入特征的前向神经网络得到的结果最好。就平均准确度而言,CNN 和逻辑回归也非常接近。这是一种很好的测试方式,我们发现使用复杂的方法,如 CNN,可以有效地提取复杂的特征,但对于情感分类来说,在句子中存在一些单词集表示评论的情感。因此,CNN 并没有给这个模型增加更多的价值。如果数据集包括许多描述情绪的复杂短语,那么 CNN 将有助于提取这些短语。像复杂方法一样使用更多的 CNN 资源可能不是这种情况下的最佳解决方案。最好对它进行测试,看看较小数据集的结果如何,也可以在完整的数据集上进行测试。如果它比其他简单的方法更好,那么我选择它用于生产,否则我通常更喜欢一个资源较少的方法,它可以给出足够好的结果。

在下面的图表中,我列出了在以前的文章中使用的情感分类的不同方法的平均准确率。

迪皮卡·巴德之前的情感分类实验结果

就准确性改进而言,与使用简单的 BOW 或 TF-IDF 相比,Word2Vec 嵌入捕获语义并不那么有用。正如你所看到的,它可以极大地减少用于机器学习模型的特征数量。在所用的例子中,BOW/TF-IDF 的特征尺寸为30056,而 Word2Vec 的特征尺寸为1000。简单的 Word2Vec 平均向量被用于评论的分类,与使用 Doc2Vec 相比,这被证明给出了更好的结果。这种情况可能并不总是如此,因为 Doc2Vec 在算法方面更胜一筹,可以对整个文档进行归纳。Doc2Vec 生成高效且高质量的分布式向量,该向量捕获精确的句法和语义单词关系(参考)。因此,测试这两种方法并比较结果总是一个好的决定。

在 BOW 和 TF-IDF 之间,结果表明 BOW 比 TF-IDF 表现得更好,虽然不显著,但显然使用 TF-IDF 模型并没有改善分类模型。TF-IDF 比 BOW 涉及更多的计算,因此在选定一种方法之前最好先测试一下。TF-IDF 降低了在整个语料库中频繁出现并且不是文档所独有的单词的权重。这种方法似乎不能很好地解决与评论相关的情感分类问题,其中正面和负面的词出现在大多数文档中。当用作前馈神经网络或逻辑回归的输入时,如果您已经使用简单的分类模型测试和比较了 BOW、TF-IDF、Word2Vec 或 Doc2Vec 等多种方法,则可以节省一些训练时间。如果您想做进一步的实验,可以尝试将这些作为 PyTorch 中模型的输入。

前馈神经网络对于给定的数据表现良好。对于神经网络,可以测试前面帖子中提到的不同的激活、优化、损失函数,看看这个结果是否有所改善。你可以试着用不同的学习速率、时期、其他非线性激活函数如tanhsigmoid等进行测试。、其他优化算法如AdamRMSProp等。有很大的空间进行实验,并获得比以前的帖子更好的结果。

我已经在实验中展示了如何快速为情感分类问题建立模型。在这篇文章中,我展示了我是如何比较并计划以不同的顺序使用不同的方法来获得可能的最佳结果的。

情感分类系列到此结束。我的目标是将相关的主题分组,这是我的第一个系列。我将继续出版,因为我正在探索新的主题。看好这个空间!😃

一如既往——愉快的实验和探索!

什么是 API,你能给我演示一下吗?

原文:https://towardsdatascience.com/reflection-on-my-first-api-project-67d6cee31ce4?source=collection_archive---------67-----------------------

数字世界的搭便车指南

反思我的第一个 API 项目

迈克尔·布朗宁在 Unsplash 上拍照

作为一个新手,API 对我来说一直很神秘。我看过多个定义,也看过多个 Youtube 视频,但还是很抽象。

常见的解释总是类似于“允许两个应用程序相互对话的软件中介”或者“我们可以向它发送一个接收信息的请求…”等等…

但是,这是一个物理问题吗?我可以导入并使用的包?或者类似于编程语言的东西?我知道,它允许应用程序互相交谈,但是,那是什么东西?

如果你有同样的问题,请继续阅读。我希望这个博客能有所帮助。

应用程序接口

API 是一组代码。在这里,你现在正看着一个。

这是我最近项目的一个 API。该项目是一个网络应用程序,允许人们玩一个琐事游戏。这个 API 允许 web 应用程序显示所有问题,问题也可以按类别显示。

是什么让这段代码成为 API?

在我看来,它通常可以分为两大部分。

第一部分是第 1 部分:URL 和方法。这部分有两个目的。首先, @app . route(…)``是一个明显的信号,告诉你,你正在查看一个 API。其次,在这一部分,API 监听来自客户端的请求,即传入的 URL 地址。

如果你想知道为什么*@app.route()* `工作以及为什么每个 API 都以这种方式启动,这里有两个有用的资源。

[## Flask:为什么 app.route() decorator,应该总是在最外面?

比方说,我有一个手工制作的@ log in-required decorator:from func tools import wraps def…

stackoverflow.com](https://stackoverflow.com/questions/47467658/flask-why-app-route-decorator-should-always-be-the-outermost) [## 非魔法事物- Flask 和@app.route -第 1 部分

我已经有一段时间没有发博客了,所以我想是时候在我的博客上开始一个新的系列了。这是第一个…

ains.co](https://ains.co/blog/things-which-arent-magic-flask-part-1.html)

第二部分和第三部分是 API 的本质或工作。这就是我们需要 API 的原因。在第 2 部分中,API 从数据库中检索客户机请求的信息。在第 3 部分中,API 告诉服务器应该如何响应客户机,以便客户机能够理解。

如果以上段落比较抽象。看看下面的代码。这些是我的前端代码。看它们是如何相互对应的。只是一个脚注,我用 React 和 Flask 和这个应用程序。

让我从另一个角度向你展示 API 是如何允许后端和前端相互对话的。

由 Unsplash 上的 Dhruv 拍摄的照片

对于我的前端,我使用了 React。因此,我去: localhost:3000 查看我的网页。如果我做的一切都正确,网页上的所有按钮都应该工作。每当我点击一个按钮,相应的信息,存储在数据库中,应该显示在网页上。

假设现在我用不同的方式命名了一个变量。在我的后端,我把变量“total_questions”改成了“all_questions”,但是在我的前端,还是“result.total_questions”。会发生什么?

不出所料,当我单击网页上的一个按钮来检索所有问题时,我会遇到一个错误。

但是,如果我去 localhost 5000,即 http://127.0.0.1:5000/ 。这是允许我访问我的服务器的 URL,只要我键入 write URL:http://127 . 0 . 0 . 1:5000/questions不会出现任何错误,我仍然可以看到所有的问题完美地显示出来。

这意味着服务器确切地知道如何从数据库中获取信息。我的功能完全正常。只是由于名称不匹配,它无法将此信息传输到前端。

如果你有一个不同的 URL 地址,同样的事情也会发生。您的后端 URL 地址可以在端口 5000 上很好地工作,但是您的前端会有错误。

我希望现在能更清楚什么是 API,以及 API 如何连接前端和后端。

当我第一次开始学习计算机网络时,我对“服务器”和“客户机”这两个术语与餐馆的比喻如此吻合而着迷。前台/客户是走进餐厅的客户。服务员就像餐馆里的服务员,他们端上菜肴,满足顾客的任何需求。数据库就像厨房。

如果我们用这个比喻,API 就是一个菜单。当顾客点“玛格丽塔比萨饼”时,他/她知道会发生什么。服务员也很清楚什么是“玛格丽塔披萨”。没有人需要解释:这是马苏里拉奶酪,罗勒,橄榄油等…这就是 API 的力量。

照片由迈克尔·布朗宁在 Unsplash 上拍摄

其他要点:

除了对 API 有非常清晰的理解之外,我还学到了关于 if 语句的惨痛教训。

我在看我卡了很久的两个端点。我在思考为什么他们花了我这么长时间来调试。我意识到一件事,在两次中,我都写了一个 if 语句,试图抓住一个特殊的场合。然而,因为我没有意识到我的 if 语句有问题,所以我不知道这两个 if 语句都是无用的。

这个特殊场合只是跳过了 if 语句并像普通场合一样进入了其他代码行。我以为是我逻辑有问题,所以花了那么多时间查也没有结果。

现在我知道了:反复检查 if 语句。仅仅因为它们在那里并且没有引起任何错误消息,并不意味着它们正在工作。它们是 if 语句,因此可以轻松跳过。

关于我的问题的更多细节,我把:

>> if x is None:
do y

但应该是

>> if x == []:
do y

我试图捕捉从用户那里接收到一个空输入的情况,这个输入碰巧是空字符串格式的。在 Python 中,null 或 none 不同于空字符串。这就是为什么我的两个 if 语句都没用。

None 不是空字符串,none 不是 0,none 就是 none…懂了吗?

GIF via GIPHY

我仍然觉得这种差异非常有趣。对于那些想知道的人,下面有一个关于区别的很好的解释。简单来说,在 Python 中把“无”解释为“我不知道”比“什么都没有”更好。

[## Python 中 Null 和空字符串有什么区别?

回答(20 个中的 1 个):Python 根本没有空字符串。Python 确实有一个 None 值,但它不是一个字符串,而是一个…

www.quora.com](https://www.quora.com/What-is-the-difference-between-Null-and-empty-string-in-Python#:~:text=All objects in Python are,of the string is zero.)

这些是我从这个项目中学到的详细而艰难的经验。

你看,这就是为什么你需要项目。

干杯,继续编码。

GIF via GIPHY

其他资源:

另一篇解释 API 的文章。我喜欢这个图,但是把 API 画成一个盒子会让它有点混乱。

[## API 到底是什么?

你有没有听说过“API”这个词,并想知道这到底是什么?你是否有一个模糊的想法,但是…

medium.com](https://medium.com/@perrysetgo/what-exactly-is-an-api-69f36968a41f)

从 2020 年达沃斯世界经济论坛看人工智能

原文:https://towardsdatascience.com/reflections-on-ai-from-davos-2020-world-economic-forum-49a3964e08d?source=collection_archive---------28-----------------------

人工智能叙事正从问题走向行动,并找到解决方案来管理人工智能的潜在风险和伦理

2020 年 1 月 22 日,世界经济论坛全球人工智能委员会的一些成员在达沃斯开会

在讨论如何在超十亿参数的深度神经网络中让 AI 变得可解释时,你对一个诺贝尔奖得主说什么?这是我第一次去达沃斯,恰逢世界经济论坛(WEF)庆祝其第 50 届年会。这里的环境非常完美:一个田园诗般的山城,周围是白雪皑皑的群山,天空清澈湛蓝。世界上的精英们戴着他们设计的太阳镜成群结队地出来了。我在一个小时内发现了高级政府部长、亿万富翁、科技巨头和摇滚明星。在这里,我与诺贝尔奖得主约瑟夫·斯蒂格利茨(Joseph Stiglitz)进行了交谈,并确保我们的精品人工智能管理咨询公司最佳人工智能实践得到了最高级别的代表。我们讨论了人工智能的可解释性,这是每个人都在谈论的话题。虽然斯蒂格利茨教授从学术角度提出了担忧,但我从不同的角度处理这个问题:为正在努力解决人工智能道德问题的董事会带来实用工具,以及如何证明人工智能风险的管理。

经济学奖得主约瑟夫·斯蒂格利茨与作者西蒙·格林曼

世界经济论坛全球人工智能委员会

我是 WEF 全球人工智能委员会的成员。我参加了由谷歌中国前首席执行官、投资人、《人工智能的超能力》一书的作者李开复博士和微软总裁布拉德·史密斯主持的理事会会议。该委员会由高级政府代表、全球机构如联合国和联合国儿童基金会、行业机构如 IEEE、科技巨头如 IBM 、 Salesforce 和埃森哲、领先的人工智能学者、杰出的 Will.i.am 以及少量人工智能初创公司组成。

利益相关者资本主义

今年达沃斯的主题是利益相关者资本主义,推动企业超越单一的成功指标(股东回报),将客户、员工、合作伙伴和整个社会纳入考量。这发生在我们都面临财富不平等、政治不稳定和全球可持续发展挑战的时候。虽然美国总统特朗普在达沃斯的演讲中忍不住挖苦了 17 岁的格里塔·图恩伯格,但毫无疑问,可持续发展和气候变化是世界上最强大的议程的首要问题。这是那些真正控制这个星球的人的一次不可思议的聚会。尽管人们抱怨停在机场的私人飞机数量创纪录的虚伪,但我不禁感到一种乐观,即那些能够改变世界的人正围绕正确的议程凝聚起来。

讨论的重点是技术在帮助实现许多联合国可持续发展目标(SDG)方面可以发挥的作用,包括气候行动、良好的健康、优质教育、性别平等和减少不平等。Alphabet-Google 的首席执行官桑德尔·皮帅指出了人工智能技术的重要性,并说道:

“人工智能是我们人类正在研究的最深刻的事情之一。它比火或电更深刻。

虽然可能有点夸张,但毫无疑问,人工智能将融入社会结构,影响国家、政府、机构、公司和人民。据埃森哲称,未来三年全球人工智能支出预计将达到 520 亿美元,并将在未来十五年内帮助主要经济体的 GDP 增长率翻一番。

平衡人工智能的机会与风险

但正如皮查伊也说的,“毫无疑问”人工智能需要被监管。与任何新技术的引入一样,机会需要与风险相平衡。例如,面部识别技术现在是一种站在变得无处不在的风口浪尖上的商品。它给社会带来了巨大的好处。通过识别已知的罪犯和恐怖分子,它可以使我们更加安全。它可以通过加快机场的身份识别来简化我们繁忙的生活。但这也会危及我们的隐私权。它可以被坏人用来挑出个人或种族群体进行迫害。政府和非营利组织在识别和管理这些风险方面可以发挥作用。企业可以发挥作用。学者可以发挥作用。公民领袖可以发挥作用。这需要在多边基础上进行。我们需要在全球范围内赋予人工智能领导力,以帮助解决这些风险。

人工智能的大部分叙事都被恐惧所主导。对人工智能的存在主义恐惧。对我们工作的恐惧。担心人工智能从根本上来说是不公正的,缺乏道德和内在偏见。随着面部识别变得无处不在,人工智能将意味着我们隐私的丧失。这种说法在达沃斯的许多会议上被重复。但不是每个人都简单地问问题,讨论最终转向了潜在的解决方案。

在过去的一年里,世界已经发生了变化。人工智能也(终于)在前进,从实验走向实际应用。汇丰全球商业银行首席执行官 Barry O'Bryne 谈到了该公司如何拥有 300 多个人工智能用例,重点是改善客户旅程。扩大人工智能规模的举措迫使我们所有人都要解决这样的问题:我们如何在现实世界中最好地管理人工智能。

赋能人工智能领导委员会工具包

为此,WEF 在达沃斯推出了授权人工智能领导委员会工具包。正如WEF 人工智能和机器学习负责人凯·弗斯-巴特菲尔德所说

“我们的研究发现,许多高管和投资者不了解人工智能可以为他们做什么,以及他们可以设置什么参数来确保技术的使用是道德和负责任的。”

该工具包旨在帮助公司董事会了解人工智能的价值,并确保负责任地使用人工智能,在其治理和合规实践中提供风险管理的实用工具。我们,在最佳实践人工智能,与 IBM、埃森哲和 BBVA 等其他公司一起,是这个工具包的主要贡献者。工具包可以在这里免费获得。

AI 治理框架

WEF 还推出了更新的人工智能治理框架,为组织提供实施和自我评估指南。该框架的实施由新加坡政府牵头。大赦国际很荣幸被邀请为这项工作提供投入。

人工智能健康检查和合规性框架

我们还在达沃斯宣布与律师事务所 Simmons & Simmons 和 Jacob Turner 合作,推出最全面的人工智能健康检查和合规服务之一,Jacob Turner 是 Fountain Court Chambers 的律师,也是《Robot Rules:Regulating Artificial Intelligence的作者。这将有助于组织确保负责任和值得信赖地使用人工智能。更多信息可在这里找到。

最佳实践 AI 与喷泉法庭的西蒙斯&西蒙斯 LLP 和雅各布特纳合作,提供一个健康检查和合规框架

Workday 和道德人工智能指南

我喜欢总部位于加州 SaaS 的财务、人力资源和规划公司 Workday 与 WEF 联合发布的关于如何让你的公司合乎道德的内容。正如他们所说:

1.定义“人工智能伦理”的含义

2.将道德人工智能构建到产品开发和发布框架中。

3.创建跨职能专家小组

4.将客户协作引入负责任的人工智能的设计、开发和部署。

5.对机器学习中的偏差采取生命周期方法。

6.要透明。

7.授权你的员工设计负责任的产品

8.分享你所知道的,向业内其他人学习。

WEF 全球人工智能委员会在达沃斯召开会议,继续关注如何平衡人工智能带来的机遇和风险管理。我们回到了人工智能伦理的重要性,以及超越高级原则到实际政策和实施的需要。

总而言之,现在的问题是,我们如何让人工智能在规模上变得真实可信。我期待着看到人工智能叙事弧如何在明年取得进展。

关于西蒙·格林曼

西蒙·格林曼(Simon Greenman)是最佳实践人工智能公司(Best Practice AI)的合伙人,这是一家人工智能管理咨询公司,帮助公司利用人工智能创造竞争优势。西蒙是世界经济论坛全球人工智能委员会的成员;AI 专家常驻seed camp;并担任伦敦哈佛商学院校友天使会主席。他在欧洲和美国的数字化转型领域拥有 20 年的领导经验。请通过直接给他发邮件或联系,在 LinkedIn 或 Twitter 上找到他,或在媒体上关注他。

改革家:高效的变压器

原文:https://towardsdatascience.com/reformer-the-efficient-transformer-dd9830164703?source=collection_archive---------37-----------------------

了解基于变压器的自监督架构

Denys Nevozhai 在 Unsplash 上拍摄的照片

变压器 ( 瓦斯瓦尼等人。艾尔。)很棒,它关注更长的上下文,它提供了 rnn 没有的并行计算,最重要的是,它们拥有最先进的结果。

在这篇文章中,我们将讨论改革者模型,它是由 Google Research 在论文Reformer:The Efficient Transformer中提出的。该模型本质上解决了转换器模型的一些效率约束,并提出了转换器的改进版本,该版本实现了位置敏感散列(LSH) 和可逆层以使模型更加高效。我们将在本帖接下来的部分更详细地讨论这些。

变压器的低效率

尽管是最先进的,变压器非常昂贵(w.r.t .内存)。其中最著名的变形金刚是伯特 ( 德夫林等人。艾尔。),也是针对最大允许序列长度 512 进行训练的。为了进一步说明这一点,我们举一个与本文中相同的例子:

报道的最大变压器配置有 64 层,每层有 0.5B 个参数。假设我们想为一个长度为 64K 的序列训练一个转换器。这里,0.5B 参数占 2GB 内存。此外,批量大小为 8 的 1024 维嵌入权重占 64K x 1K x 8 = 0.5B 个浮点,这也是 2GB 的内存。现在,如果我们要为单个层训练这个模型,我们可以很容易地在单个 GPU 上训练它,但是,还有 63 层要附加。此外,训练 BERT 的语料库需要 17GB 来存储。

鉴于上述情况,以下是原始变压器中解决的问题:

  1. N 层需要比单层多 N 倍的内存,这是因为每层的输入都需要存储用于反向传播
  2. d _ ff(中间前馈层的深度)与d _ model相比相当大****,因此占用大量内存。**
  3. 长度为 L 的序列的注意力计算在计算和空间复杂度中都考虑了 O(L )

在接下来的章节中,我们将看到 Reformer 如何克服这些问题。

区分位置哈希(LSH)注意

Vaswani 等人。艾尔。”

这是原始 Transformer 模型中按比例缩放的点积注意力。这里,实际的嵌入首先被激活到 3 个不同的向量中,即查询(Q)、密钥(K)和值(V)(对于每个令牌)。然后获得查询和键的矢量点积,告诉每个矢量对获得给定矢量有多大贡献(基本上是注意)。关于自我关注的更多内容,你可以阅读我关于变形金刚的博客。

记忆有效注意

主要问题在于 QKᵀ的任期。假设查询和键的形状分别为 ( batch_size,seq_length,d_model ) 。现在,QKᵀ会产生一个 ( batch_size,seq_length,seq_length ) 的形状。因此,即使批量大小为 1,64K 长度的序列将具有 64k×64k 大小的矩阵(16GB 内存)的 QKᵀ项。

好吧,这个问题的解决方法是,我们可以分别计算每个查询 q_i 的关注度,而不是整个 Q 项,即

通过重整器文件进行内存高效关注

这听起来效率很低,因为这在某种程度上剥夺了变压器的并行处理能力。然而,你会惊讶地知道,LSH 的注意力(我们即将看到)补偿了这一部分。

Q = K

在变压器的原始实现中,使用 3 组不同的权重(线性层)来激活 Q、K 和 V。相反,作者建议对查询和键使用相同的权重。这被称为共享 QK 模式。

事实证明,共享 QK 并不影响变形金刚的性能

— 重整器纸

LSH 注意了

因此,我们讨论了分别计算每个查询的关注度,这似乎很低效,因为它不是并行的。但是如果我们从长度为 64K 的完整序列中取出 32 或 64 个最接近给定查询的键,然后由 T2 计算它们的关注度,会怎么样呢?这正是 LSH 注意力所做的。让我们看看 LSH 是如何工作的:

为了清楚地了解这一点,我们先来快速讨论一下向量空间的作用。因此,在转换器的第一层,我们本质上将给定序列中的每个记号映射到一个“向量”。这表明我们正在将所有的标记映射到一个公共的向量空间,其中词汇表中所有标记的向量表示共存。现在,在一种语言上训练这些映射,使得相似或相关标记的向量表示彼此更接近,而不相关的标记彼此远离(参考消息,我们可以使用距离度量来测量这些向量的相关性;例如余弦距离)。

通过重整器纸进行角度位置敏感散列

将我们之前讨论的向量空间中的任意两个向量视为两点 x 和 y。我们认为这个假想的圆(实际上是球体)包含这些点(比如说,这个圆就是向量空间)。然后,我们将圆分成 4 部分(4 个散列桶),并随机旋转该分区,即随机旋转圆。我们在这里有两个观察结果(参考图):

  1. 在第一种情况下(向上),向量(点)彼此相对。因此,在随机旋转时,向量很可能以高概率在不同的桶中结束。
  2. 而在第二种情况下(向下),向量彼此明显地更接近。所以你可以看到,他们更有可能以高概率结束在同一个桶里。

如果附近的向量很有可能获得相同的散列,而远处的向量则不会,则将每个向量 x 分配给散列 h(x)的散列方案被称为位置敏感的。

— 重整器纸

在重整器中,这是通过取大小为( d_k,b/2 )的随机矩阵 R 来实现的,其中 d_k 是密钥向量的大小, b 是桶的数量。并且向量 x 的散列函数 h 被给定为:

h(x)= arg max([xR;-xR ])

其中【a;b ] 是串联。所以通过拥有 xR-xR ,我们实质上是在 x 上进行随机投影。直观来说,我们是取 b 大小为 d_k的向量(桶)评估 x 所属的桶

LSH 通过关注改革家论文

上图描述了在转化炉中实现的 LSH 注意的流程。

  1. 使用我们刚刚讨论的 LSH 方案,将查询/键(查询=键)向量分配给它们各自的桶。
  2. 我们根据它们的桶对查询/关键向量进行排序。
  3. 由于哈希桶的大小可能不均匀,因此很难进行批处理。因此,采用的方法是,取固定大小的加偏移量 1;即,我们取大小为 m 的块来计算来自相同桶和相同块以及一个块回的向量的关注度。通常,块的大小是 2l / b ,其中 l 是序列长度。
  • 对于因果屏蔽(或前瞻屏蔽),首先,获取查询/关键向量的位置 id,根据桶式排序顺序进行排序,然后通过比较这些位置 id,计算屏蔽。
  • 此外,相似的向量有可能落在不同的桶中。为了解决这个问题,我们可以用不同的散列函数执行 n 轮 轮散列。****

通过改革者论文LSH 注意的每一步上的注意向量的行为和稀疏性

可逆变压器

Gomez 等人的常规剩余连接(a) v/s RevNets (b)、(c)的比较。艾尔。通过谷歌人工智能博客

我们利用前面讨论过的 LSH 注意解决了注意计算中的记忆问题。然而,当涉及到变形金刚消耗的内存时,还有另一个主要的关注点。在前馈层中,通常有一个变压器,其 d_ff 值为~4K,层数为~16。此外,每层的输入需要被存储用于反向传播。在这样的设置中,序列长度为 64K,我们最终仍然会得到不切实际的 16GB 内存范围。

因此,为了解决这个问题,Reformer 借用了 RevNets(可逆残差神经网络)的思想,这是 Gomez 等人在中提出的。艾尔。为了理解这种架构,请看上图:

(A)ResNet 中的常规跳过连接:我们获取输入,计算层值(实际上是一个函数),并将其添加到原始层输入中。在图中,x 和 y 的值需要存储在内存中用于反向传播。所以:

y = x + F(x)

z = y + G(y)

(b)RevNet 中的前向传递:其思想是允许从下一层的输入中恢复任一层的输入;即

y1 = x1;

y2 = z2 = x2 + F(x1)

z1 = y1 + G(y2)

(c)RevNet 中的反向传递:现在,我们可以使用以下公式轻松地重建各层的输入:

x1 = y1 = z1g(y2)

x2 = y2 F(x1)= z2f(x1)

因此,很明显,我们可能会重建输入值,而不是存储它们用于反向传播和节省内存。

最后,可逆变压器实现如下:

Y1 = X1 +注意(X2)

Y2 = X2 +前馈(Y1)

拆分 d_ff

最后,我们处理具有 d_ff 输出单元的中间前馈层,其中 d_ffd_model 相比相当大(一般为~4K)。

考虑具有 64K 令牌的序列,在标准转换器中,所有输出都是并行计算的,因此权重占用更多内存。虽然前馈输出是针对整个序列并行计算的,但它不一定是,因为任何给定令牌向量的输出都独立于其他向量。

因此,重整者建议分块处理该层:

通过重整器纸在中间前馈层分块处理序列

利用分块+可逆层,重整器模型的层输入记忆与层数无关。

总结一下

  1. 注意力计算-记忆问题通过使用 LSH 注意力来克服。
  2. 通过使用可逆层解决了层输入存储问题。
  3. 具有 d_ff 输出单元的高维前馈层可以通过分块处理输入序列来中和。

结果

通过重整器论文比较各种变压器架构的复杂性

在哪里,

b = >批量, l = >序列长度, d_ff = >中间前馈的尺寸, n_h = >头数, n_l = >层数,【T20

重整器可以用于从部分图像生成完整的图像:

****顶部:用作重整器输入的图像片段。下图:“已完成”的全帧图像。原始图像来自 Imagenet64 数据集通过谷歌人工智能博客。

有趣的事实:这个重整器非常高效,它可以在一个只有 16GB 内存的 GPU 上处理长达 100 万字的文本序列。

有趣的事实:Reformer 可以在一台设备上一次性处理整部小说。

结论

在这篇(很长的)文章中,我们深入讨论了重整器模型。我们看到了它在变压器中解决了哪些效率缺陷,以及如何克服这些缺陷。

这里是 Google trax 提供的重整器代码的 Github 库的链接。

这是一个 Colab 笔记本,用于谷歌的图像生成演示,另一个用于文本生成演示。

这里是 huggingface 的 API 文档的链接,用于重整器实施和预训练重量。

参考

重整器纸:https://arxiv.org/abs/2001.04451

RevNets 论文:https://arxiv.org/abs/1707.04585

变压器纸:https://arxiv.org/abs/1706.03762

** [## 改革家:高效的变压器

理解连续数据——如语言、音乐或视频——是一项具有挑战性的任务,尤其是当有…

ai.googleblog.com](https://ai.googleblog.com/2020/01/reformer-efficient-transformer.html) [## 变形金刚解释

对谷歌 Transformer 模型的详尽解释;从理论到实施

towardsdatascience.com](/transformers-explained-65454c0f3fa7)**

使用 Python 自动刷新 Tableau 数据源

原文:https://towardsdatascience.com/refresh-tableau-server-data-source-and-workbooks-using-python-4baa99cc3b93?source=collection_archive---------13-----------------------

了解如何使用 Tableau 服务器客户端(TSC)更新数据源和工作簿

假设您希望您的仪表板在数据可用的正确时刻准备好。在这种情况下,您会发现使用一个计划任务是不够的,因为您不知道填充过程何时结束!

唯一缺失的部分是一个在触发事件发生后刷新仪表板的自动化过程,比如在执行了 ETL 的最后一步之后,或者当你把新文件加载到亚马逊 S3 桶中时。

我将解释如何使用 Python 刷新或更新现有的 Tableau 数据源工作簿来解决这些问题。我建议查看这个以前的帖子来看看其他用例。

下面的代码显示了如何获取 ID 并执行数据源或工作簿刷新。

如果没有安装 Python,我推荐使用 Miniconda。你可以在这篇文章中看到更多细节。

为 Python 安装 REST API 库

首先,您需要使用 pip 安装 Tableau 服务器客户端(TSC ),这是位于https://Tableau . github . io/Server-Client-python/docs/# install-TSC的文档中推荐的

pip install tableauserverclient
pip install tableauserverclient --upgrade

配置个人访问令牌

我们将使用个人访问令牌或 PAT 进行连接。下一步是到右上角的 Tableau 服务器,选择我的帐户设置。

向下滚动并复制个人访问令牌的令牌密码

如果您没有看到个人访问令牌选项,您可以尝试使用链接激活,用您的站点替换:

[https://10ax.online.tableau.com/?personalAccessTokensEnabled=true#/site/<site>/home](https://10ax.online.tableau.com/?personalAccessTokensEnabled=true#/site/cristiansaavedradev226290/home)

关系

为了简化,我用变量创建了类TableauServerConnection:

  • 【服务器 _ 网址】https://10ax.online.tableau.com/,完整的 HTTP 地址如一样
  • token_name 是之前制作的令牌的标识名
  • 令牌 _ 秘密。这是尚未创建的令牌的秘密文本
  • 地点。它的是站点名称。如果需要连接到缺省值,则让它为空。

您的连接将如下所示:

tsConn = TableauServerConnection('https://10ax.online.tableau.com/','APIToken','copyHereTheTokenSecret')

数据源

下一步是连接到 Tableau 服务器并刷新现有的数据源。要做到这一点,你需要身份证。因为不容易找到它,所以我创建了函数getdatasourcestableuserver,它列出了使用先前连接的所有数据源。

我将使用 Python Pandas 来搜索 ID,用返回的列表创建一个数据框函数:

那么你可以得到过滤数据帧的 ID 如下:

然后您可以使用refreshdatasourcetableuserver按 ID 刷新数据源,如下所示:

接下来的几行是有魔力的。如果你想知道更多关于正在做的事情,你可以在文档页面 找到信息。

refresh datasource = server.datasources.get_by_id(datasource_id)
refreshed_datasource = server.datasources.refresh(datasource)

工作簿

在某些情况下,您有一个工作簿连接到数据源,同时,他的数据源也需要刷新。

与上一步一样,工作簿需要 ID 来执行刷新。为了便于 ID 的搜索,以与上一步相同的方式使用函数getWorkBooksTableauServer

要刷新工作簿,请按 ID 使用refreshdatasourcetableuserver函数,如下所示:

谢谢

最后,我要感谢 Carlos Lobera,他把我介绍给了 Evan SlotnickAnir AgarwalElliott Stam ,他们打开了 Tableau Server 日常任务自动化的大门。

特别感谢 Timothy VermeirenFrancisco Pagliaricci 使用 URL 激活个人访问令牌。

快乐万岁!

有用的资源

[## 开始

使用 Tableau 服务器客户端(TSC)库来提高您在与 Tableau 服务器 REST 交互时的工作效率…

tableau.github.io](https://tableau.github.io/server-client-python/docs/) [## Tableau 服务器 REST API

通过 Tableau Server REST API,您可以使用 HTTP 以编程方式管理和更改 Tableau 服务器资源。的…

help.tableau.com](https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api.htm) [## 个人访问令牌

个人访问令牌为 Tableau 服务器用户提供了创建长期身份验证令牌的能力。代币…

help.tableau.com](https://help.tableau.com/current/server/en-us/security_personal_access_tokens.htm)

正则表达式备忘单— Python

原文:https://towardsdatascience.com/regex-cheat-sheet-python-3dd0c4b5b4c6?source=collection_archive---------17-----------------------

终极指南

用正则表达式升级你的搜索方法!

你有没有发现自己感到困惑,试图从一串字符中提取一些有价值的信息?我应该承认这和“大海捞针”差不多,除非你懂 regex!

布莱克·康纳利在 Unsplash 上拍摄的图片

假设您想从数据库 log.txt 中提取公司客户的电话号码,如下所示:

1\. Ema Dough (+1-202-555-0189) - 915 Ridge Street Corpus, TX 78418
2\. Tom Hitt (+33-93-751-3845) - 9190 Berkshire Ave. Wayne, NJ 07470
3\. Maya Raine (+49-30-833-931-313) - 18 SW. Sage Ave. Ride, CA 95993

遍历所有的句子并定位括号之间的数字需要做大量的工作。这确实是真的,直到我们的救世主正则表达式(regex)的到来!

什么是正则表达式?

正则表达式是一种高级字符串搜索方法,允许用户在文本中搜索某些内容。这是通过创建一个匹配我们想要检索的信息的模式来实现的。正则表达式具有如此强大的功能,以至于它已经被包含在许多编程语言中,如 Python、Pearl、JavaScript、PHP 和 Java。

所以,让我们回到我们的问题上来!

我们可以通过首先创建一个模式来获取用户的电话号码。请注意,电话号码位于括号“()”之间。这是一个有用的信息,我们可以利用它。为了使用 Python 中的正则表达式,我们需要导入re 库

import re phone_numbers = [] 
pattern = r"\(([\d\-+]+)\)"with open("log.txt", "r") as file: 
    for line in file: 
        result = re.search(pattern, line)
        phone_numbers.append(result.group(1))print(phone_numbers)

输出:

['+1-202-555-0189', '+33-93-751-3845', '+49-30-833-931-313']

我将一个接一个地检查这段代码:

  1. 导入重新导入 Python 中的正则表达式库。
  2. phone_numbers = [] —准备存储电话号码的列表。
  3. pattern = r"(([\d-+]+))" —我们用来定位电话号码的模式,我们将在本文后面讨论每个符号的作用!
  4. 用 open("log.txt "," r ")作为文件:—打开我们要处理的文件。
  5. 对于文件中的行:—迭代(遍历)log.txt 中的每一行
  6. result = re.search(pattern,line)-在该行中搜索电话号码
  7. phone _ numbers . append(result . group(1))-将客户的电话号码添加到电话号码列表中
  8. print(phone_numbers) —打印电话号码列表。

re 库中有许多有用的函数和字符,然而学习所有的东西可能会让人不知所措。因此,我选择了最有用的函数和字符,它们将帮助您开始在 Python 脚本中实现 RegEx。

让我们在 re 图书馆开始潜水吧!

正则表达式原始字符串

在我们的例子中,我们在 log . txt:r“(([\ d -]+))”中使用这种模式

你想知道为什么我们要在字符串前输入“r”吗?这里的“r”代表原始字符串。Python 正则表达式使用反斜杠()来表示特殊序列或作为转义字符。这与 Python 在 string lateral 中出于相同目的使用反斜杠()相冲突。因此,这里的原始字符串用于避免两者之间的混淆。除此之外,它还帮助我们使我们的模式更短。如果不键入“r”,可能需要键入“\\”来表示反斜杠()。

所以,别忘了你的“r”!

正则表达式特殊序列

我们将从正则表达式中最简单的语法开始,即特殊序列。RegEx 中的特殊序列以反斜杠()开头。因此,如果您在正则表达式模式中遇到反斜杠,那么它很可能是特殊序列的语法。

**\d**               matches a single digit character [0-9]**\w**               matches any alphabet, digit, or underscore**\s**               matches a white space character (space, tab, enter)

这些序列的否定也可以用大写字母来表示。例如,\D 是\d 的否定。

**\D**               matches a single non-digit character

正则表达式元字符

然后我们将通过元字符,这将有助于我们达到我们的目标。这些字符中的每一个都有其特殊的含义。

**.**                matches any character(except for newline character)^                the string starts with a character$                the string ends with a character*                zero or more occurrences +                one or more occurrences?                one or no occurrence {}               exactly the specified number of occurrences|                either or

示例:

"c.t"            will match anything like "cat", "c*t", "c1t", etc"^a"             will match "a" from "a cat" but not "eat a cake""cat$"           will match "a cat" but not "cat party""a*b"            will match "b", "ab", "aab", "aaab", ..."a+b"            will match "ab", "aab", "aaab", ..."a?b"            will match "b" or "ab""a{1}b"          will match "ab""a{1,3}b"        will match "ab", "aab", or "aaab""cat|dog"        will match "cat" or "dog"

正则表达式集

集合可以用来匹配方括号内的一个字符。

**[abcd]**           matches either a, b, c or d

您也可以使用我们之前讨论过的特殊序列。除此之外,还有一个破折号,我们很快就会讲到。

**[a-z0-9]**         matches one of the characters from a-z or 0-9**[\w]**             matches an alphabet, digit, or underscore

脱字符号 character(^)代表除了。

**[^\d]**            matches a character that is not a digit [0-9]

要在集合中包含具有特殊含义的字符,如反斜杠()和破折号(-),您需要在前面添加一个反斜杠(\)和(-)-第一个反斜杠代表转义字符。转义字符使得具有特殊含义的字符可以按字面意思理解。

然而,没有任何特殊含义的字符,如?_+*.|()${}可以直接使用。

正则表达式函数

最后,我们将通过使用可用的函数来完成 RegEx 所能做的事情!

**findall()** Returns a list that contains all matches**search()** Returns a 'match object' if there is a match in          the string**split()** Returns a list of string that has been split at each match**sub()** Replaces the matches with a string

在所有这些函数中,自变量都是相同的,分别是

示例:

  1. findall()
import repattern = r".at"
line = "The big fat cat sat on a cat"
result = re.findall(pattern, line)print(result)

输出:

['fat', 'cat', 'sat', 'cat']

2.搜索()

import repattern = r".* .*"
line = "Ada Lovelace"
result = re.search(pattern, line)print(result)
print(result.group())
print(result.group(0))

输出:

<_sre.SRE_Match object; span=(0, 12), match='Ada Lovelace'>
Ada Lovelace
Ada Lovelace

3.拆分()

import repattern = r"cat"
line = "The big fat cat sat on a cat"
result = re.split(pattern, line)print(result)

输出:

['The big fat ', ' sat on a ', '']

4.sub()

import repattern = r"Ada"
line = "Ada Lovelace"
result = re.sub(pattern, r"Tom", line)print(result)

输出:

Tom Lovelace

正则表达式捕获组

当我们想要从匹配中提取信息时,捕获组非常有用,就像我们的例子 log.txt 一样。

我们在 log.txt 中使用这种模式:r“(([\ d -]+))”

这里,我们使用捕获组只是为了提取电话号码,不包括括号字符。

我们想要提取的电话号码可以通过 result.group(1)来访问。

通过例子理解捕获组会更容易。

示例:

  1. 搜索()
import repattern = r"(.*) (.*)"
line = "Ada Lovelace"
result = re.search(pattern, line)print(result)
print(result.groups())
print(result.group(0))
print(result.group(1))
print(result.group(2))

输出:

<_sre.SRE_Match object; span=(0, 12), match='Ada Lovelace'>
('Ada', 'Lovelace')
Ada Lovelace
Ada
Lovelace

2.拆分()

import repattern = r"(cat)"
line = "The big fat cat sat on a cat"
result = re.split(pattern, line)print(result)

输出:

['The big fat ', 'cat', ' sat on a ', 'cat', '']

3.sub()

import repattern = r"(.*) (.*)"
line = "Ada Lovelace"
result1 = re.sub(pattern, r"\2 \1", line)
result2 = re.sub(pattern, r"Tom", line)print(result1)
print(result2)

“\1”和“\2”分别代表第一个和第二个捕获组。

输出:

Lovelace Ada
Tom

最后一个想法…

正则表达式将是你编程工具箱中的一个强大工具,尤其是在 Python 中。现在您可能已经意识到 RegEx 的潜力是无穷的。绝对值得花时间和精力去学习 RegEx。回报会比你想象的多。请记住:

努力永远不会让你失望。—匿名

如果这些概念没有在一开始就被接受,不要担心,我们都经历过,你也可以做到!经过几次练习,你会掌握它的。如果你想了解更多关于 RegEx 的知识,我推荐你去看看这个数据营课程。

** [## Python 中的正则表达式

作为一名数据科学家,您将会遇到许多需要从大量数据中提取关键信息的情况

www.datacamp.com](https://www.datacamp.com/courses/regular-expressions-in-python)

不要浪费任何时间。准备好,让我们征服正则表达式库!

问候,

弧度克里斯诺**

Python 正则表达式简介

原文:https://towardsdatascience.com/regex-with-python-b4c5ca7c1eba?source=collection_archive---------42-----------------------

罗曼·维涅斯在 Unsplash 上的照片

从概念到应用

假设您想基于给定的查询搜索某样东西。如果只靠一根弦,是得不到想要的。那么,如何在海量信息中寻找你需要的东西呢?

当然,你需要一个能识别你想找的字符串的模式。为此,我们可以使用正则表达式(Regex)。

在本文中,我将向您展示它的概念和应用,以解决数据科学中的问题,特别是使用 Python 预处理文本。

概述

我将这篇文章分为两个部分:

  • 正则表达式的概念
  • 正则表达式的应用

正则表达式的概念

正则表达式是一种特殊类型的字符串,可以用来匹配字符串中的术语或单词。

它由特殊字符序列组成,因此我们可以根据需要使用它来匹配任何术语。这里有几个您可以使用的特殊字符,

  • 点号(。)匹配字符串中的任何字符,
  • 脱字符号(^)匹配字符串的开头,
  • 美元符号($)匹配字符串的结尾,
  • 星号(*)匹配零个或多个重复的前一个字符的模式,
  • 加号(+)匹配前一个字符的一次或多次重复,
  • 问号(?)匹配前一个字符的 0 次或 1 次重复,
  • 花括号{m,n}将匹配前一个字符的 m 或 n 个重复,
  • 如果要使用标点符号,将使用反斜杠(),但它也是一个特殊字符。例如,要匹配$,您应该在字符前添加一个反斜杠,如“$ ”,
  • 方括号([ ])可用于仅包含与字符串匹配的某些字符。假设你想找到包含 a、I 和 r 的单词,你可以使用像[air]这样的模式。

回想一下反斜杠有几个特殊的序列。如果你想包含所有的单词或数字,而不是把它们都写在方括号内,这是非常有用的。你可以使用这些序列,例如,

  • \d 将匹配任何数字
  • \s 将匹配空白字符
  • \w 将匹配任何字符
  • \D 将匹配除数字以外的内容
  • \S 将匹配除空白以外的内容
  • \W 将匹配除字符以外的内容

对于这些特殊字符,您可以根据想要提取的术语来组合它们。例如,您想要从 tweets 列表中检索标签,您可以使用类似“#\w+”的模式。

组合模式是可能的,因为有一条规则说,

如果一个模式与另一个模式结合,就会产生另一个模式。

正则表达式的应用

在您了解了正则表达式的概念之后,现在让我们看看如何应用它来操作文本。

第一个是删除我们不用于处理文本的术语。假设您想要对 tweets 集合进行文本挖掘。因此,在挖掘推文之前,你必须首先对它们进行预处理,因为我们希望高效地进行计算,并避免其中任何无意义的信息。例如,你有一条这样的推文,

**#Nasional Wapres: Jumlah Orang Miskin Bertambah Gara-Gara Pandemi Covid-19 https://t.co/sJvig4w7LL**

有几个术语你想删除,如提及,标签,链接等。在 Python 中,我们可以使用 re 库中的一个名为 sub 的方法来删除它们。

我们可以在函数中设置参数,比如正则表达式格式的模式,用来替换术语的字符串,以及我们想要处理的最后一个字符串。这是关于这个功能的一瞥,

**re.sub(pattern, replacement, data)** 
**- pattern: the pattern on regex format 
- replacement: the replacement string for terms that suits the pattern 
- data: a variable or a string that want to process**

通过使用这个函数,我们可以像这样使用它,

import re**# The raw tweet**
tweet = "#Nasional Wapres: Jumlah Orang Miskin Bertambah Gara-Gara Pandemi Covid-19 [https://t.co/sJvig4w7LL](https://t.co/sJvig4w7LL)"**# Preprocessing using Regex**
tweet = re.sub("#\w+", "", tweet)
tweet = re.sub("https*.+", "", tweet)print(tweet)
**# Here is the result,
#  Wapres: Jumlah Orang Miskin Bertambah Gara-Gara Pandemi Covid-19**

我想展示的另一个例子是在 string 中搜索和检索一个子串。在这种情况下,我将从数据科学中被称为“hello world”的数据集中选取一个示例。这是泰坦尼克号数据集。

对于那些不知道的人来说,这是一个用作 Kaggle 比赛介绍的数据集。这个竞赛的目标是根据与一名乘客相对应的数据来预测该乘客是否幸存。数据集看起来像这样,

它由几列组成,描述乘客的人口统计数据、票价、姓名,还有“幸存”列,描述乘客是否幸存。在这种情况下,让我们关注“名称”列。让我们来看几个例子,

**0                               Braund, Mr. Owen Harris
1     Cumings, Mrs. John Bradley (Florence Briggs Th...
2                                Heikkinen, Miss. Laina
3          Futrelle, Mrs. Jacques Heath (Lily May Peel)
4                              Allen, Mr. William Henry
5                                      Moran, Mr. James
6                               McCarthy, Mr. Timothy J
7                        Palsson, Master. Gosta Leonard
8     Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)
9                   Nasser, Mrs. Nicholas (Adele Achem)
10                      Sandstrom, Miss. Marguerite Rut
11                             Bonnell, Miss. Elizabeth
12                       Saundercock, Mr. William Henry
13                          Andersson, Mr. Anders Johan
14                 Vestrom, Miss. Hulda Amanda Adolfina
15                     Hewlett, Mrs. (Mary D Kingcome) 
16                                 Rice, Master. Eugene
17                         Williams, Mr. Charles Eugene
18    Vander Planke, Mrs. Julius (Emelia Maria Vande...
19                              Masselmani, Mrs. Fatima
Name: Name, dtype: object**

根据上面的样品,你发现了什么规律吗?如果细看,每个名字都有自己的称谓,比如先生、太太、小姐。,师傅。等。我们可以提取这些作为一个新的特征,称为“标题”。这个标题与其他术语的不同之处在于,它包含了点标点符号。因此,我们可以使用模式提取它。

我们如何从每个名字中提取标题?我们可以使用 re 库中一个名为 search 的函数。使用该函数,我们可以根据给定的模式提取术语。它需要模式和字符串列表。代码看起来像这样,

**def get_title(x):
  # Searching matched patterns
  x = re.search('\w*\.', x).group()
  # Removing dot punctuation to ease the analysis process
  x = re.sub('\.', '', x)
  return x****train['Title'] = train['Name'].apply(get_title)
train = train.drop('Name', axis=1)
train.head()**

确保在字符串中搜索完一个术语后,用一个名为 group 的方法将函数链接起来。或者看起来像这样,

**# If you don't use group method, it will show this**
<_sre.SRE_Match object; span=(8, 11), match='Mr.'>

如果你做的正确,结果会是这样的,

下面是搜索功能及其方法的摘要,

**re.search(pattern, data)
parameters:
 - pattern: The pattern that suits what we want to find
 - data: The data that we used. It could be string or list of strings
methods:
 - group: it returns a string or more.**

结论

这就是我们如何使用 Python 使用正则表达式来处理文本,因此我们可以通过删除无意义的信息来获得更有意义的见解。我也向你展示了它的概念和一些应用。我希望这篇文章对你有用,如果你有任何意见,请写在下面的评论区。

还有一件事,回想一下我上面的代码,我写的模式就像一个普通的字符串。但是为了确保您已经编写了一个正则表达式模式,请在引用的模式前添加“r”字符,就像这样,

**# You can write like this
re.sub("#\w+", "", tweet)****# Or like this (Focus on the r)
re.sub(r"#\w+", "", tweet)**

就这样,谢谢你。

参考

[1]https://docs.python.org/3/library/re.html
【2】https://www.kaggle.com/c/titanic

区域优先排序算法:帮助企业确定要服务的顶级区域

原文:https://towardsdatascience.com/region-prioritisation-algorithm-helping-business-identify-top-regions-to-serve-20864133cc51?source=collection_archive---------37-----------------------

使企业能够将服务划分为高、中、低优先级区域,以提供更智能、更好的服务

图片由瓦尔德马·布兰德在 Unsplash 上拍摄

目前,由于疫情,许多供应商和在线服务服务于选定的地区,这些地区可能是主要的销售贡献者。此外,当有人开始一项新业务时,他们希望专注于几个可以获得最大利润的地区,并考虑以后的扩张。很多时候,供应商会关闭低利润地区,那里的 T4 投资回报率很低。

所有上述情况都需要根据区域的重要性/优先级/对业务的贡献来确定区域。通过这篇博客,我打算提出一个简单、直观、可扩展的算法,并且很好地按照重要性划分区域。我还将提出一个度量标准,可以量化算法在区分区域优先级方面的有效性。

区域优先算法

所提出的算法包括三个步骤:

1.频率计数

第一步包括统计来自每个地区的订单频率。根据业务类型和运营方式,可以根据邮政编码、城市或州来定义区域。

同样,根据业务类型和运营方式,频率可以是每天、每周或每月。

图:供应商和服务区域的位置图

蓝线表示图中的路线。圆圈代表不同的地区,并用圆点表示订单。

在上图中,我们有一个供应商和 10 个地区(A-J)。下表总结了每周的订单频率:

图:各地区每周平均订单频率

2.分类为高、中或低频率区域

按订单频率(从步骤 1 开始)对区域进行排序,并将它们分为高、中和低频区域。

Normally, my selection criteria goes like90-100th percentile of Frequency ~ High-frequency region
75-90th percentile of Frequency ~ Medium-frequency region
<75th percentile of Frequency ~ Low-frequency region**This percentile used for region selection is a hyperparameters which can be tuned as per the Business, its type and needs.**

图:基于供应商位置图频率的区域分类

3.重新安排区域的优先次序

这最后一步是算法的核心。在这里,我们根据优先级对区域进行聚类,然后将一些区域从一个聚类移到另一个聚类,以得出最终的排名。

A.初始化

  • 用步骤 2 中的所有高频区域初始化高优先级区域。
  • 用步骤 2 中的所有中频率区域初始化中优先级区域。
  • 用步骤 2 中的所有低频区域初始化低优先级区域。

B.更改区域优先级

对于所有高优先级区域存储路线中的中间点(以某个间隔),有地图 API提供了这一点。找出属于中低优先级区域的区域与所有这些中间点的距离。如果最短距离小于阈值(< 5 英里~示例),则将该区域移动到高优先级聚类中。该距离可以是地图距离(道路距离)或其他距离,如哈弗森。

主要原因是,如果在高优先级区域的路由中或附近存在中或低优先级区域,则可以在服务高优先级区域的同时以最小的努力来服务它。

同样,将位于路径上或中等优先级区域附近的区域从低优先级聚类移动到中等优先级聚类。

作为该步骤的结果,区域‘E’、‘H’和‘F’移动到高优先级区域,因为它们在高优先级区域‘G’的路线中或附近。直觉是‘E’、‘H’、‘F’可以用最小的努力与高优先级区域‘G’一起服务。最终的供应商位置图如下所示:

订单优先排序后的最终供应商位置图

量化算法的有效性

为了量化所提出的算法的有效性,我们设计了一个度量“优先化增益”。优先化收益被定义为销售覆盖率与距离覆盖率的比率。

比方说,在对区域进行优先排序并只为高优先级区域提供服务后,我们将与实际值的差距缩小到了 40%,销售额与实际值的差距缩小到了 80%。在这种情况下,“优先化收益”将是:

Prioritization Gain = 0.80/0.40 = 2.28

“优先级增益”值越高,算法的性能越好。

结论

在这篇博文中,我们设计了一个简单且可扩展的区域优先级算法,来帮助企业识别最优先(最有利可图)的区域,以便更好地服务。此外,我们直观地分析了它是如何工作的,并定义了一个度量标准来衡量它的有效性。

如果你有任何疑问,请联系我。我很想知道你是否正在研究一些路线优先排序或基于图的算法,这篇博文很有帮助。

我的 Youtube 频道更多内容:

[## 阿布舍克·蒙戈利

嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…

www.youtube.com](https://www.youtube.com/channel/UCg0PxC9ThQrbD9nM_FU1vWA)

关于作者-:

Abhishek Mungoli 是一位经验丰富的数据科学家,拥有 ML 领域的经验和计算机科学背景,跨越多个领域并具有解决问题的思维方式。擅长各种机器学习和零售业特有的优化问题。热衷于大规模实现机器学习模型,并通过博客、讲座、聚会和论文等方式分享知识。

我的动机总是把最困难的事情简化成最简单的版本。我喜欢解决问题、数据科学、产品开发和扩展解决方案。我喜欢在闲暇时间探索新的地方和健身。在 Linkedininsta gram关注我,查看我以前的帖子。我欢迎反馈和建设性的批评。我的一些博客-********

  • 每个数据科学家都应该避免的 5 个错误
  • 以简单&直观的方式分解时间序列
  • GPU 计算如何在工作中真正拯救了我?
  • 信息论& KL 分歧第一部分和第二部分
  • 使用 Apache Spark 处理维基百科,创建热点数据集
  • 一种基于半监督嵌入的模糊聚类
  • 比较哪种机器学习模型表现更好
  • 分析 Fitbit 数据,揭开疫情封锁期间身体模式变化的神秘面纱
  • 神话与现实围绕关联

LSTM 网络和时间序列数据预测未来价格

原文:https://towardsdatascience.com/regression-analysis-lstm-network-to-predict-future-prices-b95dc0db6fcc?source=collection_archive---------18-----------------------

加密货币和神经网络

使用每小时数据的神经网络和时间序列价格预测

作者图片

https://sarit-maitra.medium.com/membership

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

T21:由于时间序列的高波动性以及随机运动的非线性,股票价格的预测是一项相当具有挑战性的工作。这里,我们手头的问题是一个价格预测问题,我们试图预测一个范围内定义的数值(大约从 9000 到 12500)。这个问题符合回归分析框架。我们将使用神经网络架构来尝试解决这里的问题。

我们将在这里建立一个深度神经网络,为我们做一些预测,并使用它来预测未来的价格。让我们加载每小时的频率数据。

数据加载:

我们总共有 2001 个数据点用美元表示比特币。我们对预测未来日期的收盘价感兴趣。

当我们看到一个时间序列时,我们总是想知道当前时间步长的值是否会影响下一个时间步长。

plt.figure(figsize = (15,5))
plt.plot(btc.close)
plt.title('BTC Close price (Hourly frequency)')
plt.xlabel ('Date_time')
plt.ylabel ('Price (US$')
plt.show()

这里我们将使用 LSTM 网络,它有能力捕捉序列中的长期相关性(例如,今天的价格和两周前的价格之间的相关性)。此外,这里使用的单变量系列仅考虑该系列的接近价格。

让我们使用 MinMax scaler 将价格数据标准化。

数据缩放:

scaler = MinMaxScaler() 

close_price = btc['close'].values.reshape(-1, 1) # The scaler expects the data to be shaped as (x, y)
scaled_close = scaler.fit_transform(close_price)
scaled_close = scaled_close[~np.isnan(scaled_close)] # reshaping data after removing NaNs
scaled_close = scaled_close.reshape(-1, 1) 
# reshaping data after removing NaNs

LSTM 的数据处理:

LSTMs 需要三维数据形状;所以我们需要把数据拆分成:[batch_size,sequence_length,n_features]的形状。我们还想保存一些数据用于测试。

让我们建立一些序列。序列的工作方式类似于向前行走验证方法,其中将定义初始序列长度,随后将向右移动一个位置以创建另一个序列。这样,重复该过程,直到使用了所有可能的位置。

SEQ_LEN = 100 
# creating a sequence of 100 hours at position 0.
def to_sequences(data, seq_len):
d = []
for index in range(len(data) - seq_len):
d.append(data[index: index + seq_len])
return np.array(d)
def preprocess(data_raw, seq_len, train_split):
data = to_sequences(data_raw, seq_len)
num_train = int(train_split * data.shape[0])
X_train = data[:num_train, :-1, :]
y_train = data[:num_train, -1, :]X_test = data[num_train:, :-1, :]
y_test = data[num_train:, -1, :]return X_train, y_train, X_test, y_test"""Walk forward validation: 
Initial SEQ_LEN is defined above, so, walk forward will be shifting one position to the right and create another sequence.
The process is repeated until all possible positions are used."""X_train, y_train, X_test, y_test = preprocess(scaled_close, SEQ_LEN, train_split = 0.95) 
# 5% of the data saved for testing.print(X_train.shape, X_test.shape)"""Our model will use 1805 sequences representing 99 hours of Bitcoin price changes each for training. We shall be predicting the price for 96 hours in the future"""

偏差方差:

如果模型在训练和测试数据集中的误差都很高,这将表明模型对两个数据集都拟合不足,并且具有很高的偏差。如果模型在训练集中具有低误差,但在测试集中具有高误差,这表示高方差,因为模型未能推广到第二组数据。

因此,目标是生成一个在训练和测试数据集中总体误差较低的模型,并平衡正确的偏差和方差水平。

构建 LSTM 模型:

我们将创建一个 3 层 LSTM 网络,使用 20%的退出率来控制训练期间的过拟合。

DROPOUT = 0.2 
# 20% Dropout is used to control over-fitting during training
WINDOW_SIZE = SEQ_LEN - 1
model = keras.Sequential()# Input layer
model.add(Bidirectional(LSTM(WINDOW_SIZE, return_sequences=True), input_shape=(WINDOW_SIZE, X_train.shape[-1])))"""Bidirectional RNNs allows to train on the sequence data in forward and backward direction."""model.add(Dropout(rate=DROPOUT))# 1st Hidden layer
model.add(Bidirectional(LSTM((WINDOW_SIZE * 2), return_sequences = True)))
model.add(Dropout(rate=DROPOUT))# 2nd Hidden layer
model.add(Bidirectional(LSTM(WINDOW_SIZE, return_sequences=False)))# output layer
model.add(Dense(units=1))model.add(Activation('linear'))"""Output layer has a single neuron (predicted Bitcoin price). We use Linear activation function which activation is proportional to the input."""BATCH_SIZE = 64
model.compile(loss='mean_squared_error', optimizer='adam')
history = model.fit(X_train, y_train, epochs=50, batch_size=BATCH_SIZE, shuffle=False, validation_split=0.1) 
# shuffle not advisable during training of Time Series

我们可以在训练期间使用回调选项来防止我们的模型过度拟合;我没有使用过回叫,但在模型拟合阶段也可以使用。

模型评估:

了解培训过程的一个简单方法是查看培训和验证损失。

# history for loss
plt.figure(figsize = (10,5))
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

在这里,我们可以看到训练错误和验证错误都有所改善。

测试:

我们还剩下一些额外的数据用于测试。让我们使用这些数据从模型中获得预测,以验证我们的模型的拟合度。

# prediction on test data
y_pred = model.predict(X_test) 
# invert the test to original values
y_test_inverse = DataFrame(scaler.inverse_transform(y_test)) 
# assigning datetime
y_test_inverse.index = btc.index[-len(y_test):] 
print('Test data:',)
print(y_test_inverse.tail(3)); print();# invert the prediction to understandable values
y_pred_inverse = DataFrame(scaler.inverse_transform(y_pred)) 
# assigning datetime
y_pred_inverse.index = y_test_inverse.index 
print('Prediction data:',)
print(y_pred_inverse.tail(3))

准确性指标:

print(f'MAE {mean_absolute_error(y_test, y_pred)}')
print(f'MSE {mean_squared_error(y_test, y_pred)}')
print(f'RMSE {np.sqrt(mean_squared_error(y_test, y_pred))}')
print(f'R2 {r2_score(y_test, y_pred)}')

RMSE 允许我们处罚远离平均值的分数。虽然错误分数很低,但看看 R2 分数,这里肯定有改进的空间。可以调整模型以获得更好的输出。

性能可视化:

plt.figure(figsize = (15,5))
plt.plot(y_test_inverse)
plt.plot(y_pred_inverse)
plt.title('Actual vs Prediction plot (Price prediction model)')
plt.ylabel('price')
plt.xlabel('date')
plt.legend(['actual', 'prediction'], loc='upper left')
plt.show()

看起来我们的基本和简要模型已经能够捕捉数据的一般模式。然而,它未能捕捉随机运动,这可能是一个好迹象,因为我们可以说,它概括得很好。

结论和未来范围:

预测股票市场回报是一项具有挑战性的任务,因为股票价值不断变化,取决于形成复杂模式的多个参数。

未来的方向可能是:

  1. 分析不同加密货币之间的相关性,以及这将如何影响我们的模型的性能。
  2. 使用技术分析添加特征以检查模型性能。
  3. 添加基本面分析的特征,检查这些特征如何影响模式。
  4. 添加来自社交网络(如 twitter 和新报告)的情感分析,以检查模型性能。
  5. GRU 网络也可以尝试不同的激活方式,如“软签名”来检查性能。

这种性质的多变量分析需要在特征工程、数据分析、模型训练等方面投入大量的精力和时间。

接我这里

参考文献:

  1. Vijh,m .,Chandola,d .,Tikkiwal,V. A .,& Kumar,A. (2020)。使用机器学习技术预测股票收盘价。Procedia 计算机科学,167,599–606。
  2. 瓦内琳·瓦尔科夫(2015 年)。黑客机器学习指南

注意:此处描述的程序是实验性的,在用于任何商业目的时都应谨慎使用。所有此类使用风险自负。**

回归及其变体:简单、多重、套索、岭和逐步回归

原文:https://towardsdatascience.com/regression-and-its-variants-simple-multiple-lassso-ridge-and-stepwise-regression-9c144fd7a7b2?source=collection_archive---------14-----------------------

各种回归类型之间的相似性和差异

在 Unsplash 上由 Vesela Vaclavikova 拍摄的照片

假设作为一名数据科学家,您想要分析一个学生数据集,该数据集记录了他们的身高和体重。您注意到 weight 列中缺少一个值。你能预测这个丢失的值吗?

假设的学生数据集

回归有助于解决这类问题。在现实世界的机器学习应用中,回归模型经常用于根据已知特征预测未知值(例如,根据品牌、型号、里程等确定二手车的价格)。)并通过在未知变量(也称为因变量)和已知特征(也称为自变量)之间建立统计关系来实现。这种关系可以表示为:

因变量= f(自变量 1,自变量 2 …)

这种统计关系可以采取许多不同的形式,取决于预测因素的类型、结果和用于建立关系的函数。下面是经常遇到的五种回归模型。我以一种明确地将一种类型与下一种类型联系起来的方式来描述它们,这样就很容易理解它们的相似之处和不同之处。

1)简单线性回归

顾名思义,简单回归是所有回归中最简单的形式。它只有一个因变量,用一个自变量来解释,两者都用二维散点图表示。上面的例子——身高和体重之间的关系——是简单线性回归的经典例子。简单线性回归模型的数学公式采用以下形式:

*体重= B0+B1 身高+ e

其中, b0 =截距, b1 =系数, e =误差项

2)多元回归

多元回归类似于简单的线性回归,但在这种情况下,将有多个独立变量,而不是一个。如果我们再次遵循上面的例子,假设体重不仅仅是由身高预测的,而是由一个额外的变量——比如年龄——预测的,那么这就是多元回归。在数学公式中,我们只需添加额外的变量:

*体重= B0+B1 *身高+B2 年龄+ e

3)拉索回归

所以,多元回归比简单线性回归好,对吧?因为有更多的预测因素,所以预测必须更加准确!不完全是,不总是。有时简单的模型比复杂的模型表现得更好。上面的多元回归有 2 个自变量,还是挺简单的,但是如果数据集中有 20 个或者 200 个变量呢?这就是数据科学家需要努力思考的问题:保留多少功能,放弃哪些功能。

在机器学习中,特征选择是消除过拟合的重要步骤,回归中也是如此。所以在 LASSO 中,如果有太多的特征,有些特征会被完全消除。这是通过将系数设置为零来实现的。这个过程在机器学习 vocab 中被称为“ L1 正则化”。

4)岭回归

在 LASSO 回归中,我们简化了包含太多特征的回归方程,并通过完全消除其中一些特征来实现这一点。岭回归用于相同的目的,即简化模型,但不是完全消除特征,而是最小化它们的影响。

所以在岭回归中,特征系数被缩小到接近零,但不完全是零(这个过程被称为 L2 正则化)。在机器学习岭回归模型中,称为λ的超参数用于控制与损失函数相关联的惩罚的权重。

因为没有特征被完全消除,所以岭回归不用于特征选择。

5)逐步回归

到目前为止,我们已经研究了各种操纵特征以增强模型性能的方法。有一个古老的,但同样有效的方法来寻找更好的模型,被称为“逐步回归”。

顾名思义,在逐步回归中,您从最简单的模型开始(如 1 个因变量和 1 个自变量),然后评估其性能。然后,您添加另一个变量,再次评估性能,并比较两个模型,以找到更好的一个。重复该过程,直到找到最佳执行模型。

称为赤池信息准则(AIC) 的估计量用于比较逐步回归中的模型性能。

摘要

回归量化了因变量和一个或多个自变量之间的关系,有许多不同的方法来建立和量化这种关系。在本文中,我重点介绍了作为一名数据科学家最常遇到的 5 种回归。有一点要记住,他们之间虽然有区别,但也不是完全不同的阶层。相似之处多于不同之处。因此,当学习回归(或任何建模家族)时,一起学习比一次学习一个更好。

基于回归的决策树:预测酒店的平均每日房价

原文:https://towardsdatascience.com/regression-based-decision-trees-predicting-average-daily-rates-for-hotels-857567d5168e?source=collection_archive---------65-----------------------

决策树的目的是通过树形图的方式可视化模型的特征,并推断每个特征在影响输出变量中的重要性(或缺乏重要性)。

决策树结构包括:

  • 节点:每棵决策树由所谓的根节点决策节点组成。
  • 分支:表示跨节点做出的每个决策的结果。

来源:图片来自 Pixabay 。

在这个例子中,基于回归的决策树被公式化以预测给定特定客户属性的酒店的 ADR(平均每日房价)。

背景

本研究侧重于酒店预订分析。谈到酒店预订,平均每日房价(ADR) 是一个特别重要的指标。这反映了特定客户在整个逗留期间每天支付的平均费用。

该分析基于 2016 年 Antonio、Almeida 和 Nunes 的原始研究。

衡量 ADR 可以让酒店更准确地识别最有利可图的客户,并相应地调整营销策略。

形成该神经网络输入的所选特征如下:

  1. 取消
  2. 原产国
  3. 细分市场
  4. 存款类型
  5. 客户类型
  6. 所需的停车位
  7. 到达日期:年
  8. 抵达日期:月
  9. 到达日期:周数
  10. 到达日期:当月的某一天

数据操作

定义了区间(或连续随机变量)。举两个例子:

leadtime = train_df['LeadTime']
adr = train_df['ADR']

使用'''类别代码' ' '定义具有分类成分的变量。

作为另外两个例子:

deposittypecat=train_df.DepositType.astype("category").cat.codes
deposittypecat=pd.Series(deposittypecat)
customertypecat=train_df.CustomerType.astype("category").cat.codes
customertypecat=pd.Series(customertypecat)

numpy 列堆栈是为独立变量(连续变量和分类变量)制定的:

x1 = np.column_stack((IsCanceled,countrycat,marketsegmentcat,deposittypecat,customertypecat,rcps,arrivaldateyear,arrivaldatemonthcat,arrivaldateweekno,arrivaldatedayofmonth))
x1 = sm.add_constant(x1, prepend=True)

然后,数据被分成训练集和验证集:

X_train, X_val, y_train, y_val = train_test_split(x1, y1)

决策树公式

使用 sklearn 导入决策树回归器:

from sklearn.tree import DecisionTreeRegressor

决策树被拟合。使用 max_depth ,确定树的大小。在这种情况下,它被设置为 4。当将预测精度与测试数据(我们将在下面详细讨论)进行比较时,我发现使用四棵树时均方根误差最小。使用较少的树会有大量信息丢失的风险,而过多的树会增加过度拟合的风险。

>>> tree_reg = DecisionTreeRegressor(max_depth=4)
>>> tree_reg.fit(X_train, y_train)DecisionTreeRegressor(ccp_alpha=0.0, criterion='mse', max_depth=4,
                      max_features=None, max_leaf_nodes=None,
                      min_impurity_decrease=0.0, min_impurity_split=None,
                      min_samples_leaf=1, min_samples_split=2,
                      min_weight_fraction_leaf=0.0, presort='deprecated',
                      random_state=None, splitter='best')

以下是使用验证数据时生成的预测:

>>> predictions = tree_reg.predict(X_val)
>>> predictions
array([ 96.25317435, 184.46591454,  70.97877619, ...,  56.187318  ,
        53.58241309,  70.97877619])

为了可视化决策树,可以使用一个名为 graphviz 的库。

>>> from sklearn.tree import export_graphviz
>>> export_graphviz(tree_reg,out_file="tree.dot")

可通过终端生成树形视图的 PDF,如下所示:

dot -Tpdf tree.dot -o tree.pdf

然后,可以导入树图像:

>>> import graphviz
>>> with open("tree.dot") as f:
>>>     dot_graph = f.read()>>> graphviz.Source(dot_graph)

以下是决策树的示例:

来源:Jupyter 笔记本输出

让我们在平均绝对误差均方根误差的基础上评估模型预测在验证数据上的表现。

>>> mean_absolute_error(y_val, predictions)
27.39342405758301>>> mean_squared_error(y_val, predictions)
1531.417860233403>>> math.sqrt(mean_squared_error(y_val, predictions))
39.13333438685493

测试数据

为了确定模型是否能够在未知数据集上保持其准确性,我们现在将测试模型预测在 H2 数据集上是否也显示出类似的准确性。

如前所述,分类变量和连续变量是这样定义的,并且其值也有适当的定义:

atest = np.column_stack((t_IsCanceled,t_countrycat,t_marketsegmentcat,t_deposittypecat,t_customertypecat,t_rcps,t_arrivaldateyear,t_arrivaldatemonthcat,t_arrivaldateweekno,t_arrivaldatedayofmonth))
atest = sm.add_constant(atest, prepend=True)
btest = t_adr
btest=btest.values

现在,决策树用于对测试数据的特征进行预测。

>>> bpred = tree_reg.predict(atest)
>>> bpred
array([141.51432277, 141.51432277, 141.51432277, ..., 184.46591454,
       184.46591454, 184.46591454])

现在,让我们评估一下平均绝对误差均方根误差

>>> mean_absolute_error(btest, bpred)
41.71191007286715>>> print('mse (sklearn): ', mean_squared_error(btest,bpred))
mse (sklearn):  3115.6311827256595>>> math.sqrt(mean_squared_error(btest, bpred))
55.817839287504306

MAE 和 RMSE 比在验证数据中测试时要高一些。鉴于这个数据集是不可见的,这与预期相符。然而,就最大化精度而言,具有 ELU 激活函数的基于回归的神经网络显示出较低的误差,MAE 在 33.56 而 RMSE 在 47.55

如果你感兴趣,关于这个例子的基于回归的神经网络的文章在这里是。

结论

在本例中,我们看到了如何:

  • 构建决策树
  • 正确配置决策树
  • 评估验证和测试集的模型准确性

本例的数据集和笔记本可在 MGCodesandStats GitHub 存储库获得,以及关于该主题的进一步研究。

免责声明:本文是在“原样”的基础上编写的,没有任何担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。

基于回归的神经网络:预测酒店的平均日房价

原文:https://towardsdatascience.com/regression-based-neural-networks-with-tensorflow-v2-0-predicting-average-daily-rates-e20fffa7ac9a?source=collection_archive---------1-----------------------

谈到酒店预订,平均每日房价(ADR) 是一个特别重要的指标。这反映了特定客户在整个逗留期间每天支付的平均费用。

Keras 是一种用于运行高级神经网络的 API——该 API 现在作为默认 API 包含在 TensorFlow 2.0 下,由 Google 开发。

目前,Keras 的主要竞争对手是脸书开发的 PyTorch。虽然 PyTorch 有更高级别的社区支持,但它是一种特别冗长的语言,我个人更喜欢 Keras,因为它在构建和部署模型时更加简单易用。

在这个特殊的例子中,Keras 建立了一个神经网络来解决一个回归问题,即我们的因变量(y)为区间格式,我们试图尽可能准确地预测 y 的数量。

什么是神经网络?

神经网络是一种基于现有数据创建预测的计算系统。让我们使用 r。

神经网络包括:

  • 输入图层:基于现有数据获取输入的图层
  • 隐藏层:使用反向传播来优化输入变量的权重以提高模型预测能力的层
  • 输出层:基于输入层和隐藏层数据的预测输出

来源:作者创作

背景

本研究侧重于酒店预订分析。说到酒店预订,【日均房价(ADR)】是一个特别重要的指标。这反映了特定客户在整个逗留期间每天支付的平均费用。

衡量 ADR 可以让酒店更准确地识别最有利可图的客户,并相应地调整营销策略。

原始数据集可从 Antonio,Almedia 和 Nunes (2019),酒店预订需求数据集获得。

对于这个例子,我们使用 keras 库中的线性激活函数来创建基于回归的神经网络。这个神经网络的目的是为每个客户预测一个 ADR 值。形成该神经网络输入的所选特征如下:

  • 取消
  • 原产国
  • 细分市场
  • 存款类型
  • 客户类型
  • 所需的停车位
  • 到达日期:周数

首先,导入相关的库。请注意,您需要在系统上安装 TensorFlow 才能执行以下代码。

import math
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import seed
seed(1)
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smfimport tensorflow
tensorflow.random.set_seed(1)
from tensorflow.python.keras.layers import Dense
from tensorflow.keras.layers import Dropout
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.wrappers.scikit_learn import KerasRegressorfrom sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler

数据准备

在这个实例中,ADR 被设置为 y 变量,因为这是我们试图预测的特征。变量存储为 numpy 数组。

y1 = np.array(adr)

数字变量和分类变量是有区别的。例如,诸如原产国的分类变量被定义为一个类别(为了防止神经网络给代码分配顺序,例如,如果 1 =葡萄牙,2 =德国,我们不希望出现德国的排名比葡萄牙“高”的情况)。

countrycat=train_df.Country.astype("category").cat.codes
countrycat=pd.Series(countrycat)

创建所选特征的 numpy 堆栈:

x1 = np.column_stack((IsCanceled,countrycat,marketsegmentcat,deposittypecat,customertypecat,rcps,arrivaldateweekno))
x1 = sm.add_constant(x1, prepend=True)

与任何神经网络一样,数据需要进行缩放,以便网络进行正确的解释,这一过程称为标准化。最小最大缩放器用于此目的。

然而,这伴随着一个警告。必须在将数据分成训练集、验证集和测试集之后进行缩放,每个测试集都单独进行缩放。

配置神经网络时的一个常见错误是,在拆分数据之前先对数据进行规范化。

这是错误的,因为归一化技术将使用来自验证和测试集的数据作为整体缩放数据时的参考点。这将无意中影响训练数据的值,本质上导致验证和测试集的数据泄漏。

因此,数据首先被分成训练和验证数据:

X_train, X_val, y_train, y_val = train_test_split(x1, y1)

然后使用最小最大缩放器:缩放训练和验证数据

y_train=np.reshape(y_train, (-1,1))
y_val=np.reshape(y_val, (-1,1))scaler_x = MinMaxScaler()
scaler_y = MinMaxScaler()print(scaler_x.fit(X_train))
xtrain_scale=scaler_x.transform(X_train)
print(scaler_x.fit(X_val))
xval_scale=scaler_x.transform(X_val)print(scaler_y.fit(y_train))
ytrain_scale=scaler_y.transform(y_train)
print(scaler_y.fit(y_val))
yval_scale=scaler_y.transform(y_val)

神经网络配置

训练神经网络时,最重要的考虑因素之一是选择输入层和隐藏层中包含的神经元数量。假设输出层是结果层,默认情况下,该层有 1 个神经元。

正如法尔哈德·马利克在本文中所解释的,每层中神经元的数量配置如下:

  • 输入层:输入层的神经元数量计算如下:

Number of features in the training set + 1

在这种情况下,由于开始时训练集中有 7 个特征,因此相应地定义了 8 个输入神经元。

  • 隐藏层:定义一个隐藏层,因为单个层适用于大多数数据集。隐藏层中神经元的数量确定如下:
Training Data Samples/Factor * (Input Neurons + Output Neurons)

在这种情况下,将因子设置为 1,该因子的目的是防止过度拟合。因子可以取 1 到 10 之间的值。输入层中有 8 个神经元,输出层中有 1 个神经元,训练集中有 24036 个观察值,隐藏层被分配了 2,670 个神经元。

  • 输出层:由于这是结果层,输出层默认取值 1。
model = Sequential()
model.add(Dense(8, input_dim=8, kernel_initializer='normal', activation='relu'))
model.add(Dense(2670, activation='relu'))
model.add(Dense(1, activation='linear'))
model.summary()

均方误差(mse)和平均绝对误差(mae)是我们的损失函数,即神经网络预测测试数据的准确度的估计值。我们可以看到,当 validation_split 设置为 0.2 时,80%的训练数据用于训练模型,而剩余的 20%用于测试目的。

model.compile(loss='mse', optimizer='adam', metrics=['mse','mae'])
history=model.fit(xtrain_scale, ytrain_scale, epochs=30, batch_size=150, verbose=1, validation_split=0.2)
predictions = model.predict(xval_scale)

该模型配置如下:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 8)                 72        
_________________________________________________________________
dense_1 (Dense)              (None, 2670)              24030     
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 2671      
=================================================================
Total params: 26,773
Trainable params: 26,773
Non-trainable params: 0

现在让我们来拟合我们的模型。

Epoch 1/30
161/161 [==============================] - 1s 4ms/step - loss: 0.0133 - mse: 0.0133 - mae: 0.0878 - val_loss: 0.0096 - val_mse: 0.0096 - val_mae: 0.0714
Epoch 2/30
161/161 [==============================] - 0s 3ms/step - loss: 0.0083 - mse: 0.0083 - mae: 0.0672 - val_loss: 0.0070 - val_mse: 0.0070 - val_mae: 0.0609
...
Epoch 28/30
161/161 [==============================] - 0s 2ms/step - loss: 0.0047 - mse: 0.0047 - mae: 0.0481 - val_loss: 0.0044 - val_mse: 0.0044 - val_mae: 0.0474
Epoch 29/30
161/161 [==============================] - 0s 2ms/step - loss: 0.0047 - mse: 0.0047 - mae: 0.0482 - val_loss: 0.0044 - val_mse: 0.0044 - val_mae: 0.0470
Epoch 30/30
161/161 [==============================] - 0s 2ms/step - loss: 0.0047 - mse: 0.0047 - mae: 0.0484 - val_loss: 0.0044 - val_mse: 0.0044 - val_mae: 0.0467

在这里,我们可以看到,训练损失和验证损失都在计算中,即预测 y 和实际 y 之间的偏差,由均方误差测量。

已经为我们的模型指定了 30 个时期。这意味着我们实际上是在 30 次向前和向后传递中训练我们的模型,期望我们的损失将随着每个时期而减少,这意味着随着我们继续训练模型,我们的模型正在更准确地预测 y 的值。

让我们来看看当绘制各自的损失时会是什么样子:

print(history.history.keys())
# "Loss"
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()

来源:Jupyter 笔记本输出

随着时代数量的增加,训练和验证损失都以指数方式减少,这表明随着时代(或向前和向后传递的数量)的增加,模型获得了高度的准确性。

现在可以将使用来自验证集的特征生成的预测与来自该验证集的实际 ADR 值进行比较。

预测将按比例缩小到原始比例:

predictions = scaler_y.inverse_transform(predictions)
predictions

来源:Jupyter 笔记本输出

与验证集中平均 ADR 值 94 相比,MAE 为 26,RMSE 为 38,该模型显示出显著的预测能力。然而,真正的测试是对以前未见过的数据进行预测,并将结果与新数据集中的实际 ADR 值进行比较。H2 数据集用于此目的。

预测—测试集(H2)

使用在 H1 数据集上生成的神经网络模型,来自 H2 数据集的特征现在被输入到网络中,以便预测 H2 的 ADR 值并将这些预测与实际 ADR 值进行比较。

计算出的平均绝对误差均方根误差如下:

>>> mean_absolute_error(btest, bpred)
44.41596076208908>>> mean_squared_error(btest, bpred)
>>> math.sqrt(mean_squared_error(btest, bpred))
57.899202401480025

H2 数据集的平均 ADR 为 105.30。

时期与批量大小

在构建神经网络时,一个关键的权衡是关于用于训练模型的次数批量

  • 批量:指每一个正向/反向传递的训练样本数。
  • 历元:所有训练实例一次正反向传递。

这份关于堆栈溢出的精彩总结对上述定义进行了更详细的阐述。

构建神经网络时面临的关键权衡是批量大小和迭代次数。

例如,训练数据包含 24,036 个样本,批量大小为 150。这意味着需要 160 次迭代来完成 1 个时期。

因此,可以增加批量大小以使每个时期具有更少的迭代,或者减小批量大小,这意味着每个时期需要更多的迭代。

这意味着,在其他条件相同的情况下,神经网络要么需要较高的批量来训练固定数量的时期,要么需要较低的批量来训练更多数量的时期。

150 个历元,batch_size = 50

这是测试集上的模型性能,此时历元数增加到 150,批量减少到 50。

>>> mean_absolute_error(btest, bpred)
45.20461343967321>>> mean_squared_error(btest, bpred)
>>> math.sqrt(mean_squared_error(btest, bpred))
58.47641486637935

当使用 30 个时期和 150 个批次时,平均事件发生率和 RMSE 稍低,这表明在预测 ADR 时,具有较大批次的较少时期更有优势。

150 个历元,batch_size = 150

但是,如果时期数和批处理大小都设置为 150,会怎么样呢?成绩有进一步提高吗?

>>> mean_absolute_error(btest, bpred)
45.030375561153335>>> mean_squared_error(btest, bpred)
>>> math.sqrt(mean_squared_error(btest, bpred))
58.43900275965334

当与 30 个时期的 150 个批量相比时,结果实际上是相同的,当使用 30 个时期时,RMSE 略低。

在这点上,增加批次大小和历元数并没有导致测试集上模型性能的改善。

激活功能

当形成神经网络时,还必须考虑所选择的激活函数。

在这种情况下,激活函数的目的是将非线性引入输入层和隐藏层,以便产生输出层所产生的更精确的结果。当我们处理回归问题时,即输出变量是数字而不是分类的,ReLU 激活函数(修正的线性激活函数)非常流行。

具体而言,该激活函数解决了所谓的消失梯度问题,由此神经网络将无法将重要的梯度信息从输出层反馈回输入层。关于消失梯度问题的更多信息可以在机器学习大师的教程中找到。

ReLU 在上面的例子中被使用,并且在 30 个时期和 150 个批量中表现出最好的准确性。

然而,对于这个特定的问题,是否存在更合适的激活函数呢?

作为一个例子, ELU 激活函数(代表指数线性单位)的功能与 ReLU 非常相似,但主要区别是 ELU 允许负输入,也可以产生负输出。

从技术上讲,我们的数据集没有负输入。但是,数据集中的许多 ADR 值都是 0。毕竟,如果客户取消了酒店预订,那么酒店就不能向他们收费(在绝大多数情况下)。

因此,ADR 有大量的 0 条目,事实上,也有一个实例记录了该变量的负面观察结果。

在这方面,神经网络再次运行 30 个时期,这一次使用 ELU 激活函数代替 ReLU。

model = Sequential()
model.add(Dense(8, input_dim=8, kernel_initializer='normal', activation='elu'))
model.add(Dense(2670, activation='elu'))
model.add(Dense(1, activation='linear'))
model.summary()

以下是模型配置:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 8)                 72        
_________________________________________________________________
dense_1 (Dense)              (None, 2670)              24030     
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 2671      
=================================================================
Total params: 26,773
Trainable params: 26,773
Non-trainable params: 0

这是训练和验证的损失。

来源:Jupyter 笔记本输出

>>> mean_absolute_error(btest, bpred)
28.908454264679218>>> mean_squared_error(btest, bpred)
>>> math.sqrt(mean_squared_error(btest, bpred))
43.66170887622355

与 ReLU 相比,使用 ELU 时,平均绝对误差和均方根误差较低。这表明改变激活函数已经导致精度的提高。

结论

此示例说明了如何:

  • 用 Keras 构造神经网络
  • 使用 MinMaxScaler 适当缩放数据
  • 计算培训和测试损失
  • 使用神经网络模型进行预测
  • 选择正确激活功能的重要性
  • 考虑迭代次数和批量之间的权衡

你可以在这里找到原始文章,它包含了一个到 GitHub 知识库的链接,这个知识库包含了与上述例子相关的笔记本和数据集。

免责声明:本文是在“原样”的基础上编写的,没有担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。

回归基础:代码演练

原文:https://towardsdatascience.com/regression-basics-code-walk-through-c2eac24da2e9?source=collection_archive---------42-----------------------

通过预测汽车销售价格发现回归的基本原理

照片由丹金在 Unsplash 上拍摄

本文通过使用一个 Kaggle 二手车数据集展示完整数据项目的代码和全面解释,引导您了解回归的基础知识。该项目利用线性回归、岭 CV、套索 CV 和弹性净 CV 模型来预测销售价格。Github 上有完整的代码。

正在设置

二手车数据集可从 Kaggle 下载,格式为 CSV 文件。信息由印度二手车网站 cardekho 提供。一旦您下载了 CSV 文件,您就可以利用 Pandas 库来查看和分析数据。

引号内的文件路径会因保存文件的位置而异。在 Mac 上,你可以通过右击文件并按住 Option 键来找到文件路径。应该会出现一个“复制”file.csv“作为路径名”的选项,然后你可以将它粘贴在括号中,就像我下面这样。

import pandas as pd# upload data from csvcar = pd.read_csv('/Users/Jewel/Desktop/Car-Price-Prediction/car details.csv')

现在 CSV 被保存为熊猫数据帧。要查看我们正在处理的数据类型,我们可以使用下面的代码来查看我们刚刚创建的数据框的前 5 行。如果我们想要查看特定数量的行,我们可以在括号中输入一个数字来查看这些行(cars.head(10)将显示前 10 行)。

car.head()

这使我们能够看到数据框包含的内容、列以及包含的二手车详细信息的一些示例。每一行都是一辆独一无二的汽车,每一列代表汽车的不同特征。在这个项目中,我们将使用这些特性来预测每辆车的“销售价格”。为此,我们将使用回归,但首先我们应该探索数据,并根据需要清理数据。

探索性数据分析和清理

1.检查缺少的值

car.isnull().sum()

没有任何丢失的值!耶。如果存在缺失值,则很难对信息进行正确建模。通常数据集中有许多缺失值,为了对数据建模,我们要么删除缺失值的行,要么用另一个值(平均值、前一个值……)替换该实例。

2.检查数据类型

探索数据的下一步是查看哪些类型的数据存储在列中。这有助于注意看起来被数字填充的列是否被错误地编码为“对象”。如果是这种情况,您可以轻松地更改数据类型,以便计算机正确理解您提供的信息。

car.dtypes

float =带小数的数字(1.678)
int =不带小数的整数或整数(1,2,3)
obj =对象、字符串或单词(' hello')
这些数据类型后的 64 是指该值占用多少位的存储空间。你会经常看到 32 或 64。

根据我们到目前为止看到的数据框的前几行,数据类型看起来都是正确的。

4.数据概述

car.describe()

此表为我们提供了有关数字数据列的统计信息的概述。因为只有三列是整数或浮点数,所以我们在图表上只看到这三列。如果数字数据被错误地编码为“对象”,我们将无法查看列上的统计信息。

使用此表,我们可以看到不同的值,如平均值、最小值、最大值和标准偏差。该表有助于快速概述列中的数据,并允许我们识别异常值。例如,当我第一次看到这张表时,我认为二手车 50 万美元的平均价格高得令人难以置信。但后来我看了看数据源,才知道数据是一家印度公司的,50 万卢比约合 6600 美元。合理多了!

此表中另一个突出的地方是 km_driven 的最小值是 1 千米。对于一辆二手车来说,这个价格似乎很低,所以我想进一步调查这辆车。为此,我们可以按照行驶公里数从低到高对数据框进行排序。

car.sort_values(by = 'km_driven')

顶部的那辆车行驶了 1 公里,由于这辆车至少有过两个主人,而且是 2014 年的,所以它只有 1 公里似乎不太现实。这可能是一个异常值,或者数据可能输入错误,所以为了安全起见,我将删除这一行。

car.drop([1312], inplace = True)
#1312 is the index of the row (which can be seen all the way on the left of the first row

5.可视化相关性

使用 Seaborn 库,我们还可以可视化不同特性之间的相关性。相关性将只记录具有数字数据的列,但是研究这些特征之间的关系仍然是有帮助的。

import seaborn as snssns.heatmap(car.corr(), annot= True);#annot = True shows the correlation values in the squares

接近 1 的正相关性告诉我们,这两个特征具有正线性关系(随着一个特征上升,另一个特征也上升)。负相关接近-1 表示两者具有负线性关系(一个增加,另一个减少)。

我们从这个关联图中获得的信息直观上是有意义的,并且可能证实我们的一些信念——这总是令人高兴的。年份和售价是相对正相关的,所以随着年份的增加,售价也会增加。年份和行驶的公里数是负相关的,所以随着车越来越旧,行驶的公里数也会越来越多。

特征工程

既然我们已经仔细查看了数据及其周围的统计数据,我们就可以为建模准备数据了。

数据框中的“名称”列非常具体,当我们在相对有限的数据集上建模时,有时更模糊一些会更好。这允许模型基于更多过去的样本进行预测。为了研究数据中汽车名称的多样性,我们可以使用下面的代码来计算每种汽车名称的数量。

car['name'].value_counts()

有超过 1400 个不同的汽车名称包括在内,许多例子不到 30 个。如果每辆车只有几个例子,我们的模型将很难预测销售价格。为了使这成为一个更普遍的特征,我们可以只包括汽车的品牌。幸运的是,品牌名称是每一行的第一个单词,所以我们可以创建一个只包含汽车品牌名称的新特性。

#make an empty list to append new names tobrand_name = []
for x in car.name:
    y = x.split(' ')
    brand_name.append(y[0]) #append only the first word to the list#we can drop the previous column that had the full name
car = car.drop(['name'], axis = 1)#and add the new column that just has the brand name
car['brand_name'] = brand_name#now let's check how many of each brand is in the column
car.brand_name.value_counts()

因为这个专栏现在只有品牌名称,所以有少于 1400 个不同的值,许多有超过 30 种不同的汽车。此时,您仍然可以选择删除只有 1 或 2 辆汽车的汽车品牌行(Force、Isuzu、Kian、Daewoo…),但我现在会保留这些。我们已经极大地限制了品种,所以我们的模型现在应该更强大。

将特征二值化

在我们可以对特性建模之前,最后一步是为非数字特性创建二进制列。计算机很难理解所有汽车名称之间的含义差异,因此二进制化只是告诉计算机“是的,这是一辆沃尔沃,”或“不,这不是一辆沃尔沃。”

二进制化为每个汽车品牌创建一个特定的列,然后每行将有一个 0(不是那个汽车品牌)或 1(是那个汽车品牌)。为每个特性创建二进制列的过程也称为“虚拟化”变量,可以用 Pandas 中的代码轻松完成。

car_dummies = pd.get_dummies(car, drop_first = True)
#set this equal to a new variable since it will be a different data set
#dropping the first column just removes the redundancy of having all the columns therecar_dummies.head()

对于虚拟/二进制列,数据框现在看起来像这样-填充了 0 和 1 的列,但三个数字列除外。尽管有更多的列,但是这个过程使得模型能够理解您提供给它的信息。

建模

现在(终于)我们可以对我们的数据建模来预测这些二手车的销售价格。

分割目标和预测变量

首先,我们需要定义 X 和 y 变量。y 是我们预测的价格(销售价格), X 是我们用来帮助我们做出预测的一切。

X = car_dummies.copy()y = X.pop('selling_price')
#.pop() removes the column/list from X and saves it to the new variable

训练和测试分割

接下来,我们需要为我们的模型创建一个训练和测试组。我们可以使用下面的代码随机选择 70%的数据作为我们模型的训练组,30%将作为我们测试模型质量的测试组。

from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=1)

标准化 X 值

最后,我们将需要标准化所有的 X 值,使它们在一个一致的范围内。这不会改变数字之间的比例关系。

from sklearn.preprocessing import StandardScalerscaler = StandardScaler()
X_train = pd.DataFrame(scaler.fit_transform(X_train), columns=X_train.columns)
#you fit_transform on your train data only because you don't want your model to be influenced in any way by the test data. The test data acts as unseen, brand new data to test the quality of the model.X_test = pd.DataFrame(scaler.transform(X_test), columns=X_test.columns)
#you only transform the test data so you can conform it to the parameters set with the mean from the training data

线性回归

我们将尝试的第一个模型是简单的线性回归。评估交叉验证分数、训练分数和测试分数以反映模型的表现是很重要的。

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score#create a model instance
lr_model = LinearRegression()#fit the model on the training data
lr_model.fit(X_train, y_train)# get cross validated scores
scores = cross_val_score(lr_model, X_train, y_train, cv=5)
print("Cross-validated training scores:", scores)
print("Mean cross-validated training score:", scores.mean())

#training score
print("Training Score:", lr_model.score(X_train, y_train))
# evaluate the data on the test set
print("Test Score:", lr_model.score(X_test, y_test))

线性回归分数

由于训练分数比测试分数好得多,这表明模型过度拟合了训练数据。这意味着该模型很难对看不见的数据进行预测——这可不好!此外,平均交叉验证分数是一个非常大的负数。理论上,我们希望这三个分数都尽可能接近 1.0,但是由于分数对于这个模型来说非常糟糕,我们可以尝试其他一些回归模型,这些模型也可以调整数据。

山脊 CV

岭回归是正则化变量的一种方法,在处理共线性时通常很有用。当存在大量特征,并且许多/所有特征以相似的强度影响目标变量时,岭通常是有用的。在处理任何回归问题时,最好尝试所有这些模型,看看哪种模型表现最好。使用 RidgeCV 模型,我们还可以设置一系列阿尔法值来尝试,模型会选择最好的。

from sklearn.linear_model import RidgeCV
import numpy as np# create a RidgeCV model instance
ridge_model = RidgeCV(alphas=np.logspace(-10, 10, 30), cv=5)
# fit the model
ridge_model.fit(X_train, y_train)#mean cv score on training data
scores = cross_val_score(ridge_model, X_train, y_train, cv=5)print("Cross-validated training scores:", scores)
print("Mean cross-validated training score:", scores.mean())

#training score
print("Training Score:", ridge_model.score(X_train, y_train))
# evaluate the data on the test set
print("Test Score:", ridge_model.score(X_test, y_test))

岭简历分数

现在三个分数都大致相同,在几个小数以内。因为这些分数比线性回归分数好得多,所以我们可以假设正则化对建模有帮助。

拉索 CV

另一种方法,我们可以调整我们的特点是使用套索。当有许多要素对目标变量几乎没有影响时,这种正则化通常有助于减少共线性。Lasso 会将这些变为零,只保留对预测有重大影响的要素。同样,最好尝试所有模型,看看哪种模型最适合您的模型。

from sklearn.linear_model import LassoCV# create a LassoCV model instance
lasso_model = LassoCV(eps= [.0001, .001, .01, .1], alphas=np.logspace(-8, 8, 20), max_iter = 1000000, cv=5)
# fit the model
lasso_model.fit(X_train, y_train)# evaluate on the training set
training_score = lasso_model.score(X_train, y_train)
# evaluate on the test set
test_score = lasso_model.score(X_test, y_test)#mean cv score on training data
scores = cross_val_score(lasso_model, X_train, y_train, cv=5)print("Cross-validated training scores:", scores)
print("Mean cross-validated training score:", scores.mean())

#training score
print("Training Score:", lasso_model.score(X_train, y_train))
# evaluate the data on the test set
print("Test Score:", lasso_model.score(X_test, y_test))

拉索 CV 评分

Lasso 得分与 Ridge 非常相似,但平均 CV 得分略高。比较模型的一个好指标是平均 CV 或测试分数。

弹性网 CV

我们将测试的最后一个模型是弹性网络 CV,它创建了套索和脊正则化的组合。

#Elastic net model with scores
from sklearn.linear_model import ElasticNetCVenet_model = ElasticNetCV(alphas=np.logspace(-4, 4, 10), 
                     l1_ratio=np.array([.1, .5, .7, .9, .95, .99, 1]),
                     max_iter = 100000,
                     cv=5)
# fit the model
enet_model.fit(X_train, y_train)# evaluate on the training set
training_score = enet_model.score(X_train, y_train)
# evaluate on the test set
test_score = enet_model.score(X_test, y_test)#mean cv score on training data
scores = cross_val_score(enet_model, X_train, y_train, cv=5)print("Cross-validated training scores:", scores)
print("Mean cross-validated training score:", scores.mean())
print()
#training score
print("Training Score:", enet_model.score(X_train, y_train))
# evaluate the data on the test set
print("Test Score:", enet_model.score(X_test, y_test))

弹性净简历分数

所有三个正则化模型的得分相对相似,但在比较平均交叉验证得分时,Lasso CV 表现最好,相差很小(. 001)。让我们仔细看看套索模型以及它是如何做出预测的。

寻找最好的模型

特征重要性

查看系数可以向我们显示哪些特征对模型如何进行预测影响最大(或最小)。下图显示了对汽车销售价格产生最大积极影响的特性。例如,成为宝马、奔驰或奥迪会导致销售价格上涨——就像成为一辆新车一样。通过将 ascending 更改为“False ”,我们还可以查看对价格有负面影响的特性。

fi = pd.DataFrame({
    'feature': X_train.columns,
    'importance': lasso_model.coef_
})fi.sort_values('importance', ascending=True, inplace=True)#sns.set_style('ticks')
sns.set(font_scale = 2)
fig, ax = plt.subplots()
# the size of A4 paper
fig.set_size_inches(16, 12)
sns.barplot(x='importance', y='feature', data=fi[-15:], orient='h', palette = 'rocket', saturation=0.7)  
ax.set_title("Feature Importance", fontsize=40, y=1.01)
ax.set_xlabel('Importance', fontsize = 30)
ax.set_ylabel('Feature', fontsize = 30)

套索正特征重要性

预测和残差

我们可以评估模型的另一种方式是通过将模型预测的值与实际值进行比较。这向我们展示了我们的模型在哪里出错,以及它的预测有多错误。我们可以在数据框中查看这些信息,也可以将这些信息转换成图表,对比实际值和预测值。

predictions = lasso_model.predict(X_test)
residuals_df = pd.DataFrame(predictions, y_test)
residuals_df.reset_index(inplace = True)
residuals_df.rename({'selling_price': 'actual', 0: 'predictions'}, axis = 1, inplace = True)
residuals_df['residuals'] = residuals_df.actual - residuals_df.predictions
residuals_df

实际值和预测值的数据框架,以及残差(实际值-预测值)

#predicted y values
predictions = lasso_model.predict(X_test)#residuals (or error between predictions and actual)
residuals = y_test - predictionssns.axes_style(style='white')sns.set(font_scale = 2)
fig, ax = plt.subplots()
fig.set_size_inches(16, 12)
ax = sns.regplot(x="predictions", y="actual", data= residuals_df,  scatter_kws = {'color': 'lightsalmon'}, 
                 line_kws = {'color': 'darksalmon'})
ax.set_xlabel('Predicted', fontsize = 30)
ax.set_ylabel('Actual', fontsize = 30)

从这些值中,我们可以看到我们的模型在创建准确预测方面做得不错,但是有许多异常值似乎不符合我们的模型。

均方根误差

最后一种评估模型性能的方法是计算均方根误差。这是所有残差平方和,然后是该值的平方根。这告诉我们我们的预测平均有多远。

from sklearn.metrics import mean_squared_error
(mean_squared_error(y_test, predictions))**0.5

这个模型的根 MSE 是 327,518.584,相当于 4,370 美元。虽然我们总是想最小化这个值,但能够预测一辆二手车的价格在 4000 美元以内也是一项不错的成就。使用这种模型,汽车公司可以只根据品牌、行驶公里数、燃料类型和年份等细节合理地给汽车定价。

结论

希望这是一个有帮助的数据项目演练,引导您了解 EDA、回归和 Python 建模的一些基础知识。查看 Github 上的完整代码了解更多细节。

如果你准备好进行下一步,查看虹膜数据集的引导走查,学习分类的基础知识。

回归的数据科学方法

原文:https://towardsdatascience.com/regression-data-case-study-e45d915c8cf2?source=collection_archive---------47-----------------------

深度剖析

数据科学工作流中的数据处理、数据清理和探索性数据分析步骤概述。

照片由米卡·鲍梅斯特在 Unsplash 上拍摄

D 数据科学、机器学习和深度学习是最近的研发热点。这些并不新鲜,但由于工具、技术和系统计算能力的进步,目前已经获得了高度重视和高度关注。但是主要部分是数据。大部分时间花在数据角力、特征提取、数据清洗等方面。你可能听说过,

大约 80%的时间用于查找、清理和重组大量数据,剩下的 20%用于实际的数据分析或其他目的。

因此,花在数据上的时间很重要。随着更多的时间被用来建造某物,它会产生更好的结果。为了更好地了解数据并进行深入的数据分析,我们可以将案例研究分为以下几个部分:

  1. 收集数据
  2. 了解特征的类型
  3. 处理特征中的问题
  4. 模型要求
  5. 列车测试数据处理
  6. 机器学习/深度学习任务

收集数据

可以从在线资源收集数据,如 Kaggle、UCI、谷歌数据集搜索等。使用真实世界的数据集可以更好地理解上面的概念(虽然不是真的!😋真实世界的数据要混乱得多😥)我选择了 Kaggle 提供的房价数据,

[## 房价:高级回归技术

预测销售价格并实践特征工程、RFs 和梯度推进

www.kaggle.com](https://www.kaggle.com/c/house-prices-advanced-regression-techniques)

了解数据类型

特征是被观察现象的数据点或可测量的属性。我们使用标准库进行数据分析(pandas、NumPy、matplotlib、plotly 和 seaborn ),并将它们作为,

import pandas as PD
import matplotlib . py plot as PLT
import plotly . express as px
import numpy as NP
import seaborn as SNS

我们定义了一个提取变量类型的函数,

提取变量类型

数据类型大致分类如下:

数据类型分类

上述函数对训练数据产生以下输出,

Numerical : 38, Categorical 43, Continuous: 18, Discrete: 14

1.数字的

数字数据是可测量的信息,它是用数字表示的数据。我们的数据包含大约 38 种数值数据类型。进一步的数值细分为:

(a)离散为变量,其值为整数(计数),例

  1. 一个家庭的孩子数量
  2. 一个人会说多少种语言
  3. 在统计课上睡觉的人数

(b)连续代表测量值,在特定范围内有一定的值,例如,

  1. 人的身高
  2. 人的重量
  3. 早上该起床了
  4. 火车的速度

2.分类:

分类变量代表可以分组的数据类型。分类变量的例子有种族、性别、年龄组和教育水平。我们的数据包含大约 43 个分类值。分类数据细分为:

(a)二进制数据是离散数据,只能是两类中的一类:是或否、1 或 0、关或开等。

(b)序数数据是类别变量,其中类别可以有意义地排序,例如,

  1. 学生的考试成绩(A、B、C 或不及格)
  2. 一周中的几天(星期一= 1,星期日= 7)

(c)名义数据没有显示标签的内在顺序,例如,

  1. 出生国(阿根廷、英国、德国)
  2. 邮政编码

3.日期时间:

日期和时间或日期时间变量,它们将日期和/或时间
作为值。例子,

  1. 出生日期(“1867 年 1 月 19 日”、“2010 年 10 月 1 日”)
  2. 申请日期(“2020 年 5 月”、“2018 年 3 月”)
  3. 事故发生时间(01:20)

我们的数据包含以下特征:

['YearBuilt', 'YearRemodAdd', 'GarageYrBlt', 'YrSold']

处理变量中的问题

数据包含错误,例如,

(a)遗漏数据可能因忘记存储、数据处理不当、基层数据录入效率低下等原因而发生。我们的训练数据具有以下缺失值分布:

缺失值图(来源:来自代码)

这是从以下函数中获得的,

用此函数绘制缺失数据

使用 Scikit 学习插补方法处理缺失数据,

[## 6.4.缺失值的插补-sci kit-学习 0.23.1 文档

由于各种原因,许多现实世界的数据集包含缺失值,通常编码为空白、NaNs 或其他…

scikit-learn.org](https://scikit-learn.org/stable/modules/impute.html)

(b)高基数意味着分类数据中不同标签的数量非常多,这给模型学习带来了问题。我们用下面的函数检查我们的数据,

(c)异常值是可能由误差引起的极端情况,但不是在所有情况下。我们可以通过查看数据来发现异常值,

极值(异常值)(来源:由代码生成)

模型要求

模型需求是机器学习算法所期望的数据行为。在我们的例子中,我们对线性模型有以下假设,

  1. 变量和目标之间的线性关系
  2. 多元正态性
  3. 没有或很少共线
  4. 同方差性

在这里可以更好地理解这些,

[## 多元线性回归的假设-统计解决方案

多元线性回归分析作出了几个关键的假设:必须有一个线性关系之间的…

www.statisticssolutions.com](https://www.statisticssolutions.com/assumptions-of-multiple-linear-regression/)

除了假设之外,建模步骤还包括遵循统计概念的数据,例如正态分布。我们的数据必须标准化。使用以下函数中的 scipy 统计模块来修正数据的偏斜度,

固定偏斜度

偏斜度指一组数据中对称钟形曲线或正态分布的扭曲或不对称。如果曲线向左或向右移动,就称之为偏斜。变量的偏斜度可以理解为,

修正偏斜度(源代码)

接下来,我们有回归任务,因此分类数据可以通过将它们转换成数字来处理,通过一键编码,这是使用 sklearn 模块完成的。

**from** **sklearn.preprocessing** **import** OrdinalEncoder
ordinal_encoder = OrdinalEncoder()data[cat] = ordinal_encoder.fit_transform(data[cat])
test[cat_test] = ordinal_encoder.fit_transform(test[cat_test])num, cat, cont, disc, yr = train_pre.extract_var()print("Numerical : "+str(len(num))+", Categorical "+
      str(len(cat)) + ", Continuous: " + 
      str(len(cont))+ ", Discrete: " + str(len(disc)))

这导致:

Numerical : 76, Categorical 0, Continuous: 18, Discrete: 52

列车测试分离

机器学习/深度学习任务需要将数据分解成训练、验证和测试任务。因此,使用 sklearn 等模块,我们将数据分为训练、验证和测试数据。下面的代码将数据分为定型数据集和测试数据集。

X_train, X_test, y_train, y_test =  train_test_split(data.drop('SalePrice', axis=1), 
data['SalePrice'], test_size=0.2, random_state=42)

拆分数据

机器学习/深度学习

最后,我们到达的部分,一切都是关于,因为你可以观察出 6 个步骤,这是最后一步,证明了多少时间投入在数据处理。没有干净的数据干净的代码,你根本无法应用机器学习算法。

在我们的机器学习任务中,我们选择 scikit-learn 的线性回归模型。

**from** **sklearn.linear_model** **import** LinearRegression
regr = LinearRegression()
*# Train the model using the training sets*
regr.fit(X_train, y_train)*# Make predictions using the testing set*
y_test_pred = regr.predict(X_test)
y_train_pred = regr.predict(X_train)**from** **sklearn.metrics** **import** r2_score
**from** **sklearn.metrics** **import** mean_squared_errorprint('MSE train: **%.3f**, test: **%.3f**' % (
        mean_squared_error(y_train, y_train_pred),
        mean_squared_error(y_test, y_test_pred)))
print('R^2 train: **%.3f**, test: **%.3f**' % (
        r2_score(y_train, y_train_pred),
        r2_score(y_test, y_test_pred)))

首先导入线性回归模型,然后对数据进行拟合。最后,我们预测分割测试数据集。最后,我们使用 R-Square 和 MSE 等指标来验证我们的模型。这些是显示我们的模型如何执行的误差计算函数。

结论

完整的代码可以在这里找到,

[## pr 2 tik 1/ml-dl-项目

github.com](https://github.com/pr2tik1/ml-dl-projects/blob/master/regression/adv-reg-house-price/houseprice_predicion.ipynb)

最后,你学会了如何预处理数据集,分析数据来预测房价。我们对回归数据进行了案例研究,并对其进行了预测分析。您可以进一步尝试使用数据可视化库(如 plotly 和 seaborn)找出变量之间的关系。

谢谢大家!欢迎您的宝贵建议!你的反馈对我很有价值。

要进行连接,请查看我的投资组合网站以了解更多关于我的详细信息,此处。

其他发布的帖子:

[## 了解卡普兰-迈耶估计量

一种生存分析技术的介绍。

towardsdatascience.com](/understanding-kaplan-meier-estimator-68258e26a3e4) [## 2020 年的开发者会怎样?

使用调查数据对过去两年的开发者洞察。

towardsdatascience.com](/what-happens-to-developers-in-2020-5bdb59e09f84) [## 探索神经网络(第一部分)

理解深度学习的概念以及使用 Python 和它的神经网络的实现…

medium.com](https://medium.com/towards-artificial-intelligence/neural-networks-from-scratch-a-brief-introduction-for-beginners-d3776599aaac) [## 如何创建令人敬畏的 Github 个人资料-自述文件!

探索展示你作为开发者或开源贡献者的“GitHub 简历”的新方法。每一个开源…

towardsdatascience.com](/explore-new-github-readme-feature-7d5cc21bf02f)

不平衡数据的回归及其应用

原文:https://towardsdatascience.com/regression-for-imbalanced-data-with-application-edf93517247c?source=collection_archive---------14-----------------------

由 Unsplash 上的 Loic Leray 拍摄的图像

简介和动机

不平衡数据是指主要关注数据中代表性较低的观察值的情况。在某些情况下,它们被表示为“离群值”,这是相当危险的。作为“异常值”表达式的结果,这种观察结果被从数据中排除或去除。这最终会导致没有代表性的分析和误导性的结果。

在当今世界,森林火灾、疫情病和经济危机等极端事件层出不穷,很容易发现不平衡数据的不同应用领域,如气象/生态灾难、银行欺诈、高风险保险组合、窃电等。

作者图片

解决不平衡数据的分类问题是非常著名的,在许多论文和文章中都可以找到。而回归问题几乎每次都会被忽略,尽管处理它们的方式有很大的不同。基本上大部分的分类问题原本都是来自于连续变量,都被转移到了分类上进行分类分析!。在转换过程中,由于数据类型的变化,模式和依赖关系被忽略。

概观

本文涵盖了:

  • 处理回归不平衡数据的一般直觉和技巧
  • 数据预处理技术
  • 使用 UBR 技术的模型处理
  • 不平衡回归的评价指标
  • 不平衡数据在 UBR 中的应用
  • 结论

回归中不平衡数据的处理技术

现有的用于回归的机器学习模型主要是基于平衡或几乎平衡的数据构建的。这导致这种模型在处理不平衡数据时出现误导和非常糟糕的性能。为了能够使用这些模型处理不平衡的数据,您有两个选择:第一,相对于其他观察,增加感兴趣的观察的表示(或者反之亦然)。第二,通过基于定制标准的参数调整来调整模型本身。我将讨论处理不平衡数据的两个主要策略,即数据预处理和模型处理。还有另外两种策略:后处理和混合,但我不会在本文中讨论它们。

预处理技术

预处理技术主要集中于在应用传统的机器学习回归模型之前,对数据应用过采样、欠采样或它们之间的混合。

"预处理技术迫使模型学习数据中的稀有观察值."

对于分类,由于类之间的清晰分离,预处理有一个更容易的任务,这从一开始就已经定义了。但是在连续随机变量的情况下,在几乎所有的参考文献中,所谓的【关联函数】都是用来处理这样一个困难的任务。相关性函数取 0 和 1 之间的值,每当相关性更趋向于 1 时,这更多地表示具有高度不平衡的数据。

抬头!在连续的情况下,不平衡数据更多地被称为偏斜数据。关联函数的定义根据数据和关于其分布的可用信息而变化,稍后我将给出一个使用的定义的例子。

对连续变量的预处理技术很少,如随机欠采样、SMOTE 回归、高斯噪声、SMOGN 算法。简而言之,SMOTE for regression 被认为是一种过采样技术。高斯噪声和 SMOGN 算法是欠采样/过采样技术的混合。

作者图片

模型处理

模型处理是处理不平衡数据的另一种策略,尽管它在许多应用程序中非常重要和有效,但却很少被提及。。基于效用的回归(UBR) 是一种罕见的技术,可以有效地处理不平衡或非均匀权重的整体数据。这种技术最初用于数据挖掘领域。UBR 的基本思想是为错误估计增加一个代价惩罚,代价惩罚根据关联函数而变化。如果相关性函数接近 1(这是指非常罕见的观察,对数据的不平衡或偏斜有很大影响),则成本损失增加,并可能达到最大值。

关联函数如前所述有很多定义,比如它可以定义成与概率密度函数成反比(如果密度定义得很好,你需要去做不同的定义)。用于不平衡回归的 UBR 的工作方式如下:首先,选择一个传统的机器学习模型进行工作,如随机森林回归,梯度推进回归,..等等。其次,定义相关性和效用函数来评估模型的性能。第三,调整给出最佳评估的模型参数。

|评估指标

最后,在接触数据之前,我将讨论使用 UBR 进行不平衡回归时的评估技术。

“通常对于回归来说,模型性能是用 MSE 或 RMSE 来衡量的。对于不平衡的数据,这样的措施是无效的。”

还有其他已经用于分类的方法(即:召回率、精确度和 F1 分数),使用效用函数对其进行调整以评估不平衡的性能。与 MSE 和 RMSE 相比,我们寻找召回率、精确度和 F1 分数的最大值(接近 1)来反映更好的性能。

应用程序

下面,我展示了 UBR 在不平衡回归和模型评估中的应用。我使用在不平衡数据的多重引用中使用的回归数据。下图显示了一些极端情况下的数据,这些情况会显著影响传统机器学习模型的回归性能。

图 1:回归因变量以蓝色显示了一些罕见的情况

图 1 显示了不平衡数据的清晰模式,您可以点击这里的来检查数据和代码。如果我们考虑阈值 4,则数据包含 31 个(15.7%)罕见病例。

我使用 XGBoost(极端梯度推进)机器学习技术进行回归。我用 5 重交叉验证评估了 360 个回归模型的性能。我根据最低的 MSE 和最高的 F1 分数选择最好的两个模型。我关注 F1 分数,而不是精确度和回忆,因为它是两者的加权平均值,但你可以根据你的研究目标选择关注其他标准。

最终模型的结果是

表 1:评估指标结果

在表 1 中,很明显,两个最佳模型的 MSE 和 RMSE 变化不大,而且都很高。而具有最小 MSE 的 F1 分数变为几乎是具有最大 F1 分数的模型的两倍。使用这两个模型的优化参数,我现在对测试数据运行 XGBoost 并检查最终性能。

最佳两个模型的参数

使用这些参数,对测试数据的两个模型的评估是

基于第一个模型的评估指标

基于第二个模型的评估指标

同样清楚的是,两种模型的 MSE 没有显著差异(30.12 对 32.04),而 F1 分数有显著变化(0.000020 对 0.431667)。这些结果证实了在不平衡数据的情况下,使用传统的评价指标是没有用的。

结论

不要忽略数据中的罕见案例!。在短期内,你可以看到令人印象深刻的结果,但这与现实中实际发生的事情无关。

即使在识别出罕见的模式后,传统的平衡数据工具对不平衡/偏斜的数据情况没有帮助。最后,尝试不同的机器学习模型可能会导致更好/更差的结果,所以你需要根据你的数据找到一个合适的模型。

参考资料:

  • 布兰科,p .,托尔戈,l .,,里贝罗,R. P. (2017 年 10 月)。SMOGN:不平衡回归的预处理方法。在第一届不平衡领域学习国际研讨会:理论与应用(第 36-50 页)。
  • 北卡罗来纳州莫尼斯、北卡罗来纳州布兰科和北卡罗来纳州托戈(2017 年 10 月)。不平衡回归任务中集成方法的评估。在第一届不平衡领域学习国际研讨会:理论与应用(第 129-140 页)。
  • 托尔戈和里贝罗(2007 年 9 月)。基于效用的回归。在关于数据挖掘和知识发现原理的欧洲会议(第 597-604 页)。施普林格,柏林,海德尔

衣阿华州埃姆斯市最优房屋销售价格预测的回归模型

原文:https://towardsdatascience.com/regression-modeling-in-predicting-optimal-house-sales-price-in-ames-iowa-d5e63f6d44e2?source=collection_archive---------25-----------------------

这一分析是我的团队在杜克大学富卡商学院 MQM 商业分析项目的应用概率和统计课程项目的一部分。我要特别感谢夏嫣·亚伯拉罕森、迈克尔·鲁奇、孙欣莹(西尔维娅饰)和曹亚琼(朱诺饰)所做出色工作。

照片由菲尔在 Unsplash 上听

商业理解

在住房市场中,经纪人利用比较市场分析(CMA)向卖方提供建议的销售价格和该价格的综合理由(Miller 2018)。虽然许多经纪人利用软件来完成 CMA,但个人经验和直觉也被用来决定提议的价格。我们的分析旨在创建一个回归模型,用于对爱荷华州艾姆斯市的住房市场进行定价。理论上,房屋定价接近其“真实价值”(基于一个具体的模型)将导致经纪人/代理机构使用更少的资源,从而实现更快(更有利可图)的销售。有各种各样的模型,网站,例如 Zillow.com,应用于提供特定房屋的市场价值的估计(麦克唐纳 2006)。我们的分析将专门为爱荷华州的 Ames 构建一个模型,房地产经纪人可以利用该模型编写 CMA 报告,从而对其提议的价格更有信心。

数据理解

我们的分析将使用 Dean DeCock 在 2011 年编制并由 Mehdi 在 2018 年发表在 Kaggle 上的数据集。该数据集包含爱荷华州埃姆斯市 2930 处房产的 80 个变量记录(DeCock 2011)。这些数据将允许我们创建一个线性回归模型,以找出不同的自变量如何影响我们的因变量,销售价格。了解每个变量将如何影响房价,将有助于房地产经纪人更好地评估爱荷华州埃姆斯市房屋的适当销售价格。

我们的第一步是清理和准备用于分析的数据。我们删除了无关的“订单”和“PID”列,因为它们与我们的研究无关。我们选择将子类从数值型改为分类型,以简化相关性的计算和可视化。我们移除了所有不适用值,并在适当的情况下使用抽样方法估算缺失值(Buuren & Groothuis-Oudshoorn,2011 年)。我们还删除了丢失 85%以上值的列。在某些情况下,我们用模态值替换所有缺失的分类值。对于我们的分类变量,我们创建了虚拟变量,以允许相关性的数值计算。

数据探索和转换

为了了解哪些变量最有可能影响爱荷华州埃姆斯市的房价,我们对自变量和因变量销售价格进行了相关性分析。完成后,我们选择保留价格相关性最高的前 10 个感兴趣的变量。

作者图片

查看因变量 SalePrice 的分布,我们得出结论,我们的数据不是正态分布的。运行 QQ 图后,很明显我们需要转换数据,使其呈正态分布。新的 QQ 图表明我们的 log(销售价格)值更符合正态分布,使我们能够继续分析。

接下来,我们绘制了感兴趣的关键分类变量的边际分布,并展示了它们与价格的关系。毫不奇怪,我们发现厨房质量和价格之间以及地下室质量和价格之间有明显的正相关关系。对于数值变量,进一步分析与因变量的关系的第一步是创建密度图,可视化数据的分布。在分析了密度图之后,我们绘制了感兴趣的数字变量和价格因变量之间的相互作用。底层、居住面积、车库面积、一层建筑面积、地下室总建筑面积和建造年份等变量显示了与总体质量图相似的模式。

作者图片

我们发现了一些不符合预期的相关性。当检查变量车库汽车和全浴(以及它们各自与价格的关系,我们看到预期的正相关在一定程度上,但随后下降。例如,有四个车库的房子通常比有三个车库的房子价格低。同样,有四个全套浴室的房子通常比有三个全套浴室的房子价格低。我们假设寻找这些属性的买家越来越少,因此,四车车库只需要更低的价格。也有可能是市场上的这种房屋更少,其他变量只是对相对较小的四个车库/四个全浴室房屋样本的价格有更显著的影响。

最后,我们考虑了在我们的分析中是否存在共线性问题。计算我们的自变量之间的不同相关性,我们发现两个变量之间的高相关性(0.8461):车库。Cars 和 Garage.Area。除了我们之前分析的结果之外,这也是移除 Garage 的动力。回归模型中的汽车。

建模

从探索性数据分析中,我们知道销售价格与许多变量高度相关(我们的“前 9 个”)。我们现在将采用线性回归来建立一个最优的价格模型,为这个市场的房屋,其中包括四个对数转换:整体。Qual,log(Gr.Liv.Area),log(车库。面积)、日志(X1st。日志(总计。Bsmt.SF),Bsmt。Qual _ 优秀,饱满。浴室,厨房。Qual_Excellent,年份制造

我们创建了四个多元回归模型。我们的第一个模型(“模型 1”)包括我们的“前 9 个”解释变量(与价格高度相关的变量)。我们开发了第二个模型(“模型 2”)。浴槽变量,其 p 值> 0.05,无统计学意义。为了比较,我们开发了模型 3,它包括了原始数据集中的所有解释变量。在模型 4 中,我们从这个更全面的模型中移除了非显著变量(p 值> 0.05)。

基于 p 值和 R 平方性能(不想过度拟合模型),我们选择了模型 2 作为我们的最终模型,它包括所有重要的独立变量,但没有相关的高 p 值。

作者图片

在模型 2 中,所有确定的变量都与我们的目标变量(销售价格)高度相关,并显示出统计显著性。所有变量都与销售价格成正相关。更具体地说,我们预计 Gr. Liv 每增长 1%,销售价格平均增长 0.4%。面积,保持其他变量不变。从两个变量可以看出另一种解读:厨房。Qual 和 Bsmt.Qual。只有当价值为“优秀”时,这两项才会对销售价格产生积极影响。为了更深入地进行回归分析,我们还试图找到自变量之间的相互作用,但没有发现有意义的见解。

评价

在运行了我们的两个模型:模型 1 和模型 2 之后,我们使用 R 平方和 AIC 来评估我们的模型性能。正如我们所料,模型 2 最适合我们的业务用例。我们比较了模型 1 和模型 2 的 R 平方和 AIC。两个模型中的评价因子相当接近。移除第一个模型中的高 p 值变量后,模型性能仍然很高。由于我们使用更少的变量来预测销售价格,并且在移除所述高 p 值变量后没有损害模型性能,因此我们确定模型 2 是迄今为止性能最高的模型,它包括高度相关的变量而没有大 p 值。

含义、局限性和结论

通过分析在爱荷华州艾姆斯房地产市场收集的数据,我们创建了一个模型,可以帮助未来的卖家在市场上为他们的房屋定价,以便在快速出售的同时仍能产生利润。根据我们的分析,决定价格的最重要因素是建造年份、卓越的厨房和地下室质量、地下室和一楼的面积、地上生活区和车库区的面积,以及房屋的整体质量(由材料和装修决定)。因为我们的模型是基于这些变量的,我们相信它是房地产经纪人在爱荷华州艾姆斯市场使用的有用工具。

然而,由于我们使用 2011 年的数据集来构建模型,而房地产市场在不断变化,因此我们的最佳模型可能不适合当前的市场。展望未来,我们建议经常记录 Ames 地区的房屋规格和销售价格,并维护一个包含相关信息的数据库,以不断提高模型预测销售价格的能力,即使面对不断变化的市场形势。除了考虑使用我们的模型的时间效率,我们还必须考虑一种更好的方法来处理缺失值。此外,回归建模有其局限性。因此,我们建议在未来探索更全面的机器学习模型和不同的评估方法。

你可以访问我的 GitHub 来查看更多关于这个分析的信息。

Sparks MLlib 上的回归

原文:https://towardsdatascience.com/regression-on-sparks-mllib-8107e8390253?source=collection_archive---------51-----------------------

使用 MLlib API 的简短示例

照片由 ThisisEngineering RAEng 在Unsplash【1】上拍摄

我想分享一个关于在 Spark + Scala 上使用 MLlib 的 PoC(概念验证)的(非常)小的开发。在这种情况下,我们希望使用 MLlib 对一些数据执行一些机器学习算法。我们将使用一个(非常)小的数据集,例如,kaggle.com 上列奥纳多的数据集。有了数据和目标(在 Spark + Scala 上使用 MLlib),让我们创建这个 PoC。

快速查看数据后,结论是:大多数列都是数字。所有这些数字栏都可以预测,但是有一个,它的名字使它成为被选中的一个:受欢迎程度。我们可以“执行”那个“机器学习例子”来预测受欢迎程度的值。

流行度是一个结果(目标变量),它独立于其他结果,但(很可能)依赖于某些特性(变量/特征)。为了预测(未来)受欢迎程度的结果,受欢迎程度是一个数字目标,使用接收到的特征,也是数字的,我们可以使用线性回归。

Kenneth Jensens 图片描述 CRISP-DM 的步骤[2]

让我们来一点理论,这样我们可以用一个潮流来装扮这些断言。我们需要一种简短、实用的方法来从某个事物的示例(PoC)中得出可验证的结果。而且兴趣在需求量很大的 TIC 领域,大数据(以数据工程师为代表)和数据科学(以数据科学家为代表)。

有了这个框架,并在选定的数据集上采用 CRIPS-DM 的前两步 [3],我们构思了一个假设,即:“一首歌的流行程度在某种程度上是这首歌的其他特征的结果”。当你有指示目标变量的(先前)数据时,从其他特征中预测目标变量,被称为监督学习。

正如数据理解步骤向我们展示的,大多数列没有分类值,而是连续数值,包括目标变量。这支持了使用算法(CRIPS-DM 的建模步骤)如线性回归来预测(计算)一首歌的流行度的想法。

线性回归公式由以色列罗德里格斯

在线性回归中,我们通过以下方式计算因变量(目标值/结果):将特定(计算)系数乘以与该系数相关的自变量(特征/变量)的结果相加(B1 * X1+B2 * X2+……),加上截距点,再加上随机误差。所有这些都是数值。

总的来说,我们已经以非正式的日常方式和技术性的方式提到了什么是动机、目标以及我们将如何实现这些目标。让我们开始吧。

MLlib 中的线性回归算法接收 libsvm 数据作为参数。所以第一步是将 CSV 文件转换成 libsvm。这一步被称为 CRIPS-DM 方法论的数据准备。

我们将删除 string(几个字母的数据类型)列和 id 列,这样做时,我们将面临这样的问题:列名中的点需要在 Spark[4]中进行特殊处理。因此,我们首先删除点,然后删除列,最后使用 MLlib 的汇编器. transform 函数将数据转换为 libsvm 格式。

现在是创建模型的时候了,只有很少的几行。但在此之前,我们先把数据随机分为训练和测试,然后,用训练数据来拟合模型。

飞度造型由伊斯罗德里格

我们将来自 model_data 函数的模型保存在 val 中,并使用它在我们的测试数据上创建一个预测列。我们的第一个模型的 RMSD 为 4(受欢迎程度),它对测试数据的预测如下:

以色列罗德里格斯对比预测值与实际值

定义 CRISP-DM 评估步骤是为了确保模型的正确性。根据业务情况和误差大小,这些结果可能被视为可接受的结果,也可能不被视为可接受的结果。

为了改善这一结果,我们可以:标准化(均值为 0,标准差为 1)我们的数据,我们可以将分类值转换为因子(摇滚= 1,流行= 2,…),我们应该使用更大的数据集,我们可以丢弃异常值,我们可以对判别变量(例如音乐流派流行度模型)进行特定研究,等等。

按以色列罗德里格斯分割数据

但是,为了评估,有一些重要的事情需要考虑:实验应该是可复制的。

用于将数据分割成测试和训练数据集的命令不允许我们在每个实验中为每一侧获取完全相同的行。所以每次我们执行实验,我们都会有(稍微)不同的结果。这是不可取的,因为我们将不能正确地度量模型的改进,或者缺少改进。

我们能做的是:降低模型的(平均)RMSD。要减少模型的 RMSD,最好的办法是移除数据集的异常值(在这种情况下)。

我们必须考虑到:我们可以通过减少 RMSD 来改善结果,但我们不能将其减少到零,因为这将意味着模型过度拟合。

当模型对于给定的数据集是完美的时,就会发生过度拟合,这通常意味着与没有过度拟合的模型相比,与任何其他数据集的误差水平都会更大。

Gufosowa 图为 k 倍交叉验证图[5]

评估模型是否过度拟合的一个好方法是检查训练和测试数据集之间的误差水平,并通过不同的数据样本交叉验证误差。

当然,我们会接受一定程度的误差以避免过度拟合,但也不接受欠拟合。很难找到一个好的中间点。我们可以继续寻找完美的中间点,但我们不会在这个故事中这样做,因为目标是“在 Spark + Scala 上使用 MLlib”,并且已经实现了。

感谢阅读这个故事:)。

你可以在 Prezi 上找到这个故事的一个(非常)小的演示:【https://prezi.com/tozutehrcojn/?utm_campaign=share】T2&UTM _ medium = copy

参考资料:

[1]this is engineering RAEng,女航天工程师写方程(2020),网址:https://unsplash.com/photos/GzDrm7SYQ0g

[2] Kenneth Jensens,显示 CRISP-DM (2012)不同阶段之间关系的流程图,URL:https://es . Wikipedia . org/wiki/Cross _ Industry _ Standard _ Process _ for _ Data _ Mining #/media/Archivo:CRISP-DM _ Process _ diagram . png

[3] Israel Rodrigues ,CRISP-DM 方法论在数据挖掘和大数据领域的领导者(2020),网址:https://towardsdatascience . com/CRISP-DM-methodology-leader-in-data-mining-and-big-data-467 EFD 3d 3781

[4]贾亚德万·issues.apache.org,“当试图从包含列的数据帧中进行选择时。在它里面,是抛出异常”(2016),网址:【https://issues.apache.org/jira/browse/SPARK-13197

[5] Gufosowa ,k 倍交叉验证图。(2019),网址:https://es . Wikipedia . org/wiki/Cross _ Industry _ Standard _ Process _ for _ Data _ Mining #/media/Archivo:CRISP-DM _ Process _ diagram . png

熊猫和熊猫的回归图

原文:https://towardsdatascience.com/regression-plots-with-pandas-and-numpy-faf2edbfad4f?source=collection_archive---------5-----------------------

数据可视化

向 Python 图中添加回归线可以揭示可能被忽视的趋势

艾萨克·史密斯在 Unsplash 上拍摄的照片

我喜欢熊猫自带的绘图工具。是的,有许多其他绘图库,如 Seaborn,Bokeh 和 Plotly,但对于大多数用途,我很高兴熊猫绘图的简单性。

但是有一件事我不喜欢,那就是在复杂的线或散点图上绘制回归线的能力。

但是,我发现,这很容易解决。使用 Numpy 库,您可以在几行代码中生成回归数据,并将其绘制成与原始线形图或散点图相同的图形。

这就是我们在这篇文章中要做的。

首先,我们来获取一些数据。如果你读过我以前写的关于数据可视化的文章,你就会知道接下来会发生什么。我将使用一组天气数据,您可以从我的 Github 帐户下载。它记录了英国伦敦几十年来的温度、日照水平和降雨量,并存储为 CSV 文件。该文件由英国气象局记录的公共领域数据创建。

伦敦的夏天越来越热了吗

我们将检查伦敦的气温是否随着时间的推移而上升。从原始数据来看并不明显,但是通过在数据上画一条回归线,我们将能够更好地看到趋势。

因此,首先我们需要导入我们将需要的库。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

这没什么不寻常的,我们正在导入 Pandas 来帮助数据分析和可视化,Numpy 将为我们提供创建回归数据所需的例程,Pandas 使用 Matplotlib 来创建地块。

接下来,我们下载数据。

weather = pd.read_csv('https://raw.githubusercontent.com/alanjones2/dataviz/master/londonweather.csv')

(你可能已经猜到了,这应该在一行中。)

我们已经将 CSV 文件读入熊猫数据帧,这是它的样子——一个包含月数据的表格,记录了最高和最低温度,降雨量和日照时数,从 1957 年开始,到 2019 年结束。

我提出了夏季是否会变得更热的问题,因此我将对数据进行过滤,只给出通常记录最热温度的 7 月份的数据。为了方便起见,我将添加一个列,从第 0 年开始对年份进行编号(稍后您将看到这是如何使用的)。

july = weather.query('Month == 7')
july.insert(0,'Yr',range(0,len(july)))

上面的代码将一个查询应用于天气数据帧,该数据帧仅返回月份等于 7(即七月)的行,并根据结果创建一个名为七月的新数据帧。

接下来,我们插入一个名为 Yr 的新列,它从 0 到表的长度对行进行编号。

七月长这样:

现在我们可以画出自 1957 年以来 7 月份的最高气温。

july.plot(y='Tmax',x='Yr')

那里有很多变化,高温不仅限于最近几年。但是似乎确实有一种趋势,随着时间的推移,气温似乎确实在上升。

我们可以尝试通过线性回归来使这一点变得更明显,我们试图找到一个代表温度上升趋势的直线图。为此,我们使用 Numpy 的 polyfit 函数。 Polyfit 对给定的数据进行最小二乘多项式拟合。我们希望对列 YrTmax 中的数据进行线性回归,因此我们将它们作为参数传递。最后一个参数是多项式的次数。对于线性回归,阶数为 1。

然后,我们使用方便的函数 poly1d 为我们提供一个函数来进行拟合。

d = np.polyfit(july['Yr'],july['Tmax'],1)
f = np.poly1d(d)

我们现在使用函数 f 来生成线性回归数据,并将其插入到名为 Treg 的新列中。

july.insert(6,'Treg',f(july['Yr']))

接下来,我们创建一个 YrTmax 的线形图(我们在上面看到的摆动图)和另一个 YrTreg 的线形图,这将是我们的直线回归图。我们通过将第一个图赋给变量 ax 来组合这两个图,然后将其作为附加轴传递给第二个图。

ax = july.plot(x = 'Yr',y='Tmax')
july.plot(x='Yr', y='Treg',color='Red',ax=ax)

就这样,搞定!

我们现在可以更清楚地看到这些年来气温的上升趋势。

这是用散点图做的同样的事情。

ax=july.plot.scatter(x='Yr', y='Tmax')
july.plot(x='Yr',y='Treg',color='Red',legend=False,ax=ax)

我认为这相当简单,我希望你觉得有用。

关于用熊猫绘图的介绍,请看这个:

[## 用熊猫绘图:数据可视化导论

如果您是一名初露头角的数据科学家或数据记者,能够可视化您的数据会让您有能力…

towardsdatascience.com](/plotting-with-pandas-an-introduction-to-data-visualization-8bd7c0831650)

回归均值及其含义

原文:https://towardsdatascience.com/regression-to-the-mean-and-its-implications-648660c9bf76?source=collection_archive---------18-----------------------

一种无处不在的统计现象,影响着我们的日常生活,但我们大多数人都没有意识到。

洛杉矶的常驻棒球队洛杉矶道奇队(LA Dodgers)在经历了一场精彩的比赛后,出现在了《体育画报》2017 年 8 月 28 日的封面上。他们赢得了 71%的比赛,并有望追平一个赛季中最多胜利的记录。封面配有“最佳”的标题。团队。从来没有?”

该队随后在接下来的 22 场比赛中输掉了 17 场,并最终在世界大赛中输给了休斯顿太空人队。这只是臭名昭著的《体育画报》封面厄运的一个例子,这是一个城市传说,显然会导致出现在封面上的球队和运动员立即经历一连串的糟糕表现。

厄运可以追溯到《体育画报》的第一期,主角是埃迪·马修斯。在他出现在封面上之前,他的球队取得了 9 连胜,但他们继续输掉了下一场比赛,他很快就受伤,导致他错过了 7 场比赛。然而,厄运并不仅限于棒球——它折磨着所有运动项目的运动员。最近倒霉的受害者包括塞雷娜·威廉姆斯、康纳·麦格雷戈、路易斯·苏亚雷斯、林赛·沃恩和汤姆·布拉迪。

对此有许多可能的解释。例如,这可能是一种心理影响——出现在封面上会让团队或运动员感到更大的压力,并可能导致他们失去注意力。然而,最近霉运有了一个有趣的变化,在 2019 年 11 月的一期上,SF 49ers 成为了主角。当这个故事被写出来时,49 人队正处于 8 比 0 的连胜,他们继续输掉了他们的下一场比赛。然而,这一损失发生在这期杂志出版的前两天。这表明可能有更多的厄运。

事实上,霉运只是一种非常简单但意义深远的统计现象的结果,这种现象被称为均值回归。当一个随机变量在第一次测量时是极端的,但在第二次测量时更接近平均值(因此是“回归”)时,就会发生这种情况,反之亦然。但是这和体育出版物的世界有什么关系呢?

本质上,这只是说一个团队或运动员在任何时间点的表现都是一个随机变量——潜在的技能无疑是一个非常重要的因素,但它至少部分取决于我们无法预测的噪音或运气的概念。一个团队只有在随机变量的第一次测量(该团队在封面前的表现)达到极限后才会出现在封面上。在第二次测量中,封面出版后,团队更有可能“回归”到平均值,看起来封面的外观让他们倒霉。

高尔顿的原始解释

著名统计学家弗朗西斯·高尔顿爵士在 19 世纪末首先发现了回归均值法。1886 年,他进行了一项研究,调查孩子的身高和他们父母之间的关系。他测量了 928 名成年子女和相应的 205 对父母夫妇的身高,在考虑男女身高差异(将每个女性的身高乘以 1.08)后,他注意到了一些有趣的事情。孩子们的身高比他们父母的平均身高更接近平均值。因此,如果父母非常高,孩子通常会比较矮。如果父母都很矮,孩子往往会更高。您可以在下图中看到这一点,虚线没有等位线陡:

来源:斯蒂芬·森在皇家统计学会的《重要性》杂志上发表的文章

人们很容易想到对此的基因解释,事实上这也是高尔顿所建议的。他说,一个孩子的基因构成是他们所有祖先的某种指数平均值。由于更多的人分享了远祖,你最终会向平均人口身高靠拢,而不是纯粹根据你父母的遗传基因来决定你的身高。但是我们现在知道这不是真的——人们只从他们的父母那里获得他们的基因构成。在高尔顿的实验中还有另一个不寻常的效应。不仅孩子的身高没有父母那么极端,反之亦然!正如我们在下图中看到的,极端身高的孩子的父母身高更接近平均水平。这使得基因争论更难被证明,事实上这种影响纯粹是统计学上的。

来源:文章由斯蒂芬·森在皇家统计学会的《重要性》杂志上发表

回归均值背后的直觉

当你比较两个不完全相关的变量时,就会回归到平均值。这里有一个例子来理解这是什么意思。

假设我们选择了 100 个人,让他们每人抛 10 次硬币。基本概率表明,在所有 1000 次翻转中,我们预计大约有一半是正面。

现在,假设我们选择了第一轮中头数最多的 20 个人,让他们进入第二轮,在第二轮中,他们必须再次投掷硬币 10 次。在这 200 次翻转中,我们会期待什么?我们会期望这些人(他们“擅长”获得正面)获得正面多于反面吗?一点也不!在新的 200 次翻转中,我们预计大约有一半会再次成为正面。这组异常值的平均值现在已经“回归”到平均值。

这是一个极端的例子,其中被测量的两个变量(第一轮中的人数和第二轮中的人数)根本不相关。让我们考虑另一个极端,两个变量完全相关。假设我们用摄氏度测量了世界上 100 个地方的温度。然后我们挑选出前 20 个最热的地方,再用华氏温度测量它们的温度。在这种情况下,我们会看到什么?这些地方将继续比平均华氏温度更热,而且不会回归到平均值!这种变量之间完全相关的情况(给定摄氏温度,我们知道华氏温度的确切温度)是我们不会看到回归平均值的唯一情况。

这两个例子可能看起来非常明显,可能不清楚与 SI cover jinx 或 Galton's heights 有什么联系,但这只是因为大多数回归均值的实例发生在变量不在我们看到的两个极端中的任何一个的情况下——它们会有某种程度的相关性。

父母的身高和孩子的身高当然不是完全相关的。很明显,除了父母的身高,孩子的身高还取决于其他因素。所以回归到平均值是肯定会发生的。然而,身高也不是完全独立的——由于潜在的遗传因素,可能有一些相关性。因此,这种影响不会像掷硬币的例子那样极端,因为在掷硬币的例子中,回归实际上一直回到总体均值。所以在这种偏相关的情况下,会有对均值的偏回归。

我们在现实生活中看到的大多数情况都与此类似,其中有一个潜在的固定因素使两个变量部分相关,一些未知的影响或噪音或运气使它们不那么相关。这就是为什么回归均值在现实生活中如此难以发现的原因。

现实世界中的例子

回归均值不仅仅是影响运动员的奇怪统计现象。它对现实世界的政策决策有着非常现实的影响。一个例子——对减少交通事故的不同方法进行优先排序。英国执法部门考虑的一个方法是在最近事故高发的十字路口安装测速摄像头。这样做之后,他们注意到事故发生的频率下降了,大概是因为人们因为摄像头的存在而放慢了速度。但这是唯一的原因吗?就事故而言,安装摄像头的地方可能比平时更极端,因为十字路口是根据最近的事故选择的。所以这些回归平均值的十字路口至少是事故减少的部分原因。在决定是设置更多的高速摄像机还是尝试不同的方法时,区分这两种效果是很重要的。

另一个有趣的例子是 1999 年马萨诸塞州 T2 学校提高分数的案例。从 1999 年到 2000 年,学校设定了旨在提高学生成绩的目标。当他们第二年查看结果时,他们注意到 1999 年以来表现最差的学校达到了他们的改进目标——但是一些表现最好的学校却失败了!这可能是又一个回归平均数的例子,最差和最好的学校都回归到平均数,似乎最差的学校有进步,最好的学校失败。

这实际上提出了一个关于人性和社会的深刻哲学观点,《思考,快与慢》的作者丹尼尔·卡内曼对此做了最好的总结:

“这是一个欢乐的时刻,在这一时刻,我明白了关于世界的一个重要真理:因为我们倾向于在别人做得好的时候奖励他们,在别人做得不好的时候惩罚他们,而且因为存在回归均值的现象,这是人类条件的一部分,我们因为奖励别人而受到统计上的惩罚,因为惩罚别人而受到奖励。”—丹·卡尼曼

回归均值的计算

回归均值很难被注意到,甚至更难量化,但很明显,它不能被忽视。这种影响在医学研究中可能特别危险。医学试验的参与者必须满足某些标准,这是很常见的——例如,如果你想测试一种新药治疗特定疾病的疗效,那么参与者可能会从已经患病一段时间的人群中选择。可能这些人目前是“极端”的例子,不管他们的治疗如何,他们平均会回归到平均水平并有所改善。

医学研究和其他类似的实验通常有对照组来解释这一点。对照组不接受治疗(通常以安慰剂的形式),而治疗组实际上接受了新药。现在,只要这两组患者来自同一人群(比如,患病至少 2 年的人),两组患者的平均效应都将回归,两组患者之间的差异将取决于药物的实际影响!

这其实提出了一个有趣的问题。存在对照组的至少部分原因是考虑到安慰剂效应——对照组可能在没有实际接受治疗的情况下有所改善,只要患者相信他们得到了治疗。对照组的任何改善实际上都可能是由于安慰剂效应和回归平均值。那么安慰剂效应真实到什么程度呢?这篇论文谈到了在此类研究中考虑回归均值的重要性,并提到在某些情况下,我们认为的安慰剂效应实际上可能只是回归均值。这就是为什么一些研究分成 3 组——A 组不做任何治疗,B 组服用安慰剂,C 组接受实际治疗。A 组内的任何变化都有可能是因为回归到均值,A 组和 B 组的差异显示的是安慰剂效应,B 组和 C 组的差异是因为药物本身!

结论

回归均值作为一个概念我们已经知道了一百多年,但由于它的普遍性和背后微妙的推理,当它发生在现实生活中时,很容易被忽略。我说的只是几个例子,但还有很多,包括大二暴跌、马登魔咒、有机玻璃原理、月度经理魔咒等等。正如我们所见,忽视它的后果可能是深远的。我们所能做的就是记住这种效应的存在,并训练自己在现实世界中发现它!

用 30 行 Python 从头开始构建回归树

原文:https://towardsdatascience.com/regression-trees-from-scratch-in-30-lines-of-python-8196e0ab29b2?source=collection_archive---------24-----------------------

我们描述并实现回归树来预测波士顿的房价。

介绍

流程图用于通过视觉媒介清晰地表达决策过程。它们的设计需要对整个系统的全面了解,因此也需要人类的专业知识。问题是:“我们能否自动创建流程图,以使他们的设计更快、更便宜,并且相对于过程的复杂性更具可扩展性?”答案是决策树!

决策树可以自动推导出最能表达决策内部运作的规则。当在标记数据集上训练时,决策树学习规则树(即,流程图)并遵循该树来决定任何给定输入的输出。它们的简单性和高度可解释性使它们成为您 ML 工具箱中的一笔巨大资产。

在这个故事中,我们描述了回归树——具有连续输出的决策树——并实现了用于学习和预测的代码片段。我们使用波士顿数据集来创建一个用例场景,并学习定义房屋价格的规则。您可以在参考资料中找到完整代码的链接。

用来对付新冠肺炎的流程图。[1]

学习规则

我们寻找一个类似于流程图规则树,它能最好地解释房子的特征和价格之间的关系。每个规则将是这棵树中的一个节点,并将房屋划分为不相交的集合,例如有两个房间的房屋、有三个房间的房屋和有三个以上房间的房屋。规则也可以基于多个要素,例如有两个房间并且靠近查尔斯河的房子。因此,所有可能的树的空间是巨大的,我们需要简化来计算处理学习。

作为第一个简化,我们只考虑二元规则:将房子分成两部分的规则,例如“房子是否少于三个房间?”。第二,我们省略了特征的组合,因为组合的数量可能很大,并且只考虑基于一个特征的规则。在这些简化下,规则是具有两个部分的“小于关系”:一个特征,例如房间的数量和划分阈值,例如三个。

基于这个规则定义,我们通过递归地寻找将数据一分为二的最佳规则来构建规则树。

换句话说,我们首先尽可能地将数据分成两部分,然后再分别考虑每个部分。我们继续分割分割,直到满足预定义的条件,例如最大深度。由于简化和贪婪的规则搜索,构造的树只是最佳树的近似。下面你可以找到实现学习的 Python 代码。

用 Python 实现的递归分裂过程。

我们将拆分过程实现为一个函数,并用训练数据(X_train,y_train)调用它。该函数找到将训练数据一分为二的最佳规则,并根据找到的规则执行拆分。它通过使用左右分割作为训练数据来不断调用自己,直到达到预先指定的最大深度或者训练数据太小而无法分割。当满足停止条件时,它停止分割,并预测房价作为当前分割中训练数据的平均价格。

split 函数中,划分规则被定义为一个字典,其关键字为 left、right、feature、threshold 。最佳划分规则由另一个函数返回,该函数通过遍历训练集中的每个特征和阈值来彻底扫描可能的规则。对某个要素进行尝试的阈值由该要素在整个数据集中取的值决定。代码如下:

寻找分割现有训练数据的最佳规则的函数。

该函数通过测量规则建议的拆分质量来跟踪最佳规则。质量通过一个名为残差平方和(RSS) 的“越低越好”度量标准来衡量(有关 RSS 的更多详细信息,请参见参考资料中的笔记本)。最后,最佳规则作为字典返回。

解释规则

学习算法自动选择特征和阈值,以创建最佳解释房屋特征和价格之间关系的规则。下面我们可视化了从波士顿数据集中学习到的最大深度为 3 的规则树。我们可以观察到提取的规则与人类的直觉重叠。此外,我们可以像画流程图一样简单地预测房子的价格。

从波士顿数据集中学习到的最大深度为 3 的规则树。

现在让我们描述一个自动使用上述流程图进行预测的过程。给定具有数据集中的特征的房屋,我们在节点中提出问题,并根据答案进行传播,直到我们到达预测,即叶节点。

例如,位于(I)较低地位百分比为 5.3,(ii)每所住宅的平均房间数为 10.2,以及(iii)人均犯罪率为 0.01 的位置的房子将回答第一个问题为,第二个问题为,第三个问题为。因此,我们将预测其价格为 45.80K 。下面你可以看到它所走路线的图像。

树规则中的示例预测路径。

使用 split 函数返回的字典对预测过程进行编码相当简单。我们通过比较规则指定的特征值和阈值来遍历规则字典。我们根据答案向左或向右移动,直到遇到带有预测关键字的规则,即叶节点。下面是预测的代码片段。

函数使用学习到的树来预测房价。

结论

回归树是用作回归模型的快速而直观的结构。对于波士顿数据集,当最大深度被适当调整时,他们可以获得大约 0.9 的 R 分数,这是相当高的。然而,对于数据集中的微小变化,它们可能是脆弱的,这使得它们作为单一预测器是不可靠的。提出了随机森林和梯度增强树来解决高敏感性,并且它们可以产生与深度模型相当的结果。

参考文献

[1] 待在家里流程图

[2] 波士顿数据集

【3】完整代码

有 ARIMA 误差的回归

原文:https://towardsdatascience.com/regression-with-arima-errors-3fc06f383d73?source=collection_archive---------10-----------------------

图片来自 Pixabay 的像素

它是什么,我们为什么需要它,何时使用它,如何使用 Python 和 statsmodels 构建它

带 ARIMA 误差的回归将两个强大的统计模型(即线性回归和 ARIMA(或季节性 ARIMA))结合成一个超级强大的回归模型,用于预测时间序列数据。

下图说明了如何将线性回归、ARIMA 和季节性 ARIMA 模型相结合来生成带有 ARIMA 误差的回归模型:

ARIMAX 和 SARIMAX 模型(图片由作者提供)

在本文中,我们将看看这些模型中最通用的,称为带有季节性 ARIMA 误差的回归,简称 SARIMAX

SARIMAX——概念

假设您的时间序列数据集由一个响应变量和一些回归变量组成。还假设回归变量包含在矩阵 X 中,响应变量也称为因变量包含在向量 y 中。在每个时间步 iy 取某个值 y_i ,在 X 中有一个对应的行向量 x_i ,包含时间步 i 的所有回归变量的值。下图说明了这种情况:

带有回归变量 X 和因变量y的时间序列数据集(图片由作者提供)

使用线性回归模型对此数据建模的简单方法如下:

一个线性回归模型(图片由作者)

在上面的模型规范中,【β(cap)是存储拟合模型的回归系数的(m×1)大小的向量。

ε ,回归的残差是实际的 y 与模型预测的值 y(cap) 之差。所以在每个时间步I: ε_ I = y _ I—y(cap)_ I . ε是一个大小为(n×1)的向量,假设一个数据集跨越 n 个时间步。

但是,唉,我们优雅的线性回归模型对时间序列数据不起作用,原因很简单:时间序列数据是自动的,即自相关的。y_i 的给定值受 y 的先前值影响,即 y_(i-1)、y_(i-2) 等。线性回归模型无法“解释”这种自相关性。**

因此,如果对( y, X )数据集拟合直线线性回归模型,这些自相关会漏入回归残差( ε ),使 ε 自相关!

我们在我的文章《线性回归的 假设》中已经看到 线性回归模型假设回归的残差是独立的随机变量,且服从相同的正态分布。但是如果残差是自相关的,它们就不可能是独立的,从而导致许多问题。自相关残差引起的一个主要问题是,不能使用显著性统计检验(如 f 检验或学生 t 检验)来确定回归系数是否显著。也不能依赖回归系数的标准误差。这反过来使得回归系数的置信区间以及模型预测的置信区间变得不可靠。仅仅是残差中的这一个自相关问题,就导致了线性回归模型的一连串问题,使其实际上对时间序列数据建模无用。

但是,人们可以通过引入另一个强大的模型,即 ARIMA(或季节性 ARIMA),来解决自相关残差的问题,而不是抛弃强大的线性回归模型。(S)ARIMA 模型非常适合处理自相关数据。我们利用 SARIMA 的这种能力,使用 SARIMA 模型对线性回归的残差进行建模。

萨里玛模型

SARIMA 模型由以下 7 个部分组成:

AR: 自回归(AR)分量是时间序列过去值的线性组合,达到一定数量的滞后 p 。即 y_iy_(i-1)y_(i-2) ,… y_(i-p) 的线性组合如下:

AR(p)模型(图片由作者提供)

y_i 为第 I 个时间步观察到的实际值。 phi(cap)_i 是拟合模型的回归系数。 ε_i 为第 I 个时间步的回归残差。AR(p)模型的阶次“p”是结合众所周知的规则和建模者的判断来确定的。

****MA:SARIMA 的移动平均(MA)成分是模型过去误差的线性组合,达到一定数量的滞后 q 。模型过去的误差是通过从过去的实际值中减去过去的预测值来计算的。MA(q)模型表示如下:

马(q)模型(图片由作者)

y_i 为第 I 个时间步观察到的实际值。 theta(cap)_i 为拟合模型的回归系数。 ε_i 为第 I 个时间步的回归残差。负号符合指定 MA 型号的惯例。MA(q)模型的阶数“q”是通过结合众所周知的规则和建模者的判断来确定的。

组合 ARMA (p,q)模型是 AR(p)和 MA(q)模型的简单组合:

ARMA(p,q)模型(图片由作者)

差分的顺序(d): 如果时间序列有趋势,则不能使用 ARMA 模型。趋势的常见例子有线性趋势、二次趋势和指数或对数趋势。如果时间序列表现出一种趋势,可以对时间序列应用一阶或多阶差分,以消除该趋势。一阶差分将移除类型为 y = mx + c. 的线性趋势,二阶和更高阶差分将移除类型为 y = mx + cy = mx + c* 等的多项式趋势。**

具有线性趋势的时间序列,以及应用一阶差分后的去趋势时间序列: y_i-y_(i-1) (图片由作者提供)

ARIMA 车型中的差分运算用 I 字母表示。在 ARIMA, I 代表Iintegrated。在 AR 和 MA 项发挥作用之前,ARIMA 模型应用了差异。差分的阶由 ARIMA(p,d,q)模型规范中的 d 参数表示。

SAR、SMA、D 和 m: 季节性 ARIMA 或 SARIMA 模型通过引入 P 阶季节性 AR (SAR)项、Q 阶季节性 MA (SMA)项和 D 阶季节性差异,将上述 AR、MA 和差异概念简单地扩展到季节性领域。SARIMA 模型中的最后一个参数是“m ”,即季节性周期。例如,对于显示年度季节性的时间序列,m=12 个月。正如 P、D 和 Q 一样,估算 P、D、Q 和 m 的值也有既定的规则。

完整的萨里玛模型规格是 ARIMA(p,D,q)(P,D,Q)m

现在让我们回到自相关残差这个小难题上来。

如前所述,(S)ARIMA 模型非常适合预测时间序列数据,尤其适合处理自相关数据。我们将 SARIMA 模型的这一特性应用于线性回归模型拟合到时间序列数据集后的自相关残差建模。

由此产生的模型被称为带有季节性 ARIMA 误差的回归或简称为 SARIMAX 。它可以大致定义如下:

SARIMAX(图片由作者提供)

如果(P,D,Q),(P,D,Q)和 m 选择正确,人们会期望 SARIMAX 模型的残差是而不是自相关的。事实上,它们应该是独立的,同分布的随机变量,均值为零,方差恒定。

在本文中,我不会详细介绍估算 P、D、Q、P、D、Q 和 m 的规则,而是将重点放在使用 Python 和 Statsmodels 为真实数据集构建 SARIMAX 模型上。在此过程中,我们将应用各种规则来修正 SARIMAX 的参数。

为了更好地理解整套规则是什么,请参考以下关于该主题的优秀链接:

** [## 识别 ARIMA 模型的规则

非季节性 ARIMA 模型说明(pdf 文件)季节性和非季节性 ARIMA 模型幻灯片(pdf 文件)介绍…

people.duke.edu](http://people.duke.edu/~rnau/arimrule.htm)

为了深入理解 ARIMA 和萨里玛模型,请务必阅读瑙教授关于 ARIMA 的其余课堂讲稿:

[## ARIMA 模型介绍

非季节性 ARIMA 模型说明(pdf 文件)季节性和非季节性 ARIMA 模型幻灯片(pdf 文件)介绍…

people.duke.edu](http://people.duke.edu/~rnau/411arim.htm)

使用 Python 和 statsmodels 构建带有季节性 ARIMA 误差的回归模型

我们将运用到目前为止所学的知识。我们将为真实世界的数据集设计一个 SARIMAX 模型。我们将使用的数据集包含了从 2004 年到 2005 年在一个意大利城市繁忙的十字路口每小时测量的各种空气污染物的读数。以下是原始数据集的链接:

https://archive.ics.uci.edu/ml/datasets/Air+quality

我已经为我们的 SARIMAX 实验修改了这个数据集。修改后的数据集可以从这里 下载

让我们从导入我们将使用的所有 Python 包开始:

**import** pandas **as** pd
**from** statsmodels.regression **import** linear_model
**from** patsy **import** dmatrices
**import** statsmodels.graphics.tsaplots **as** tsa
**from** matplotlib **import** pyplot **as** plt
**from** statsmodels.tsa.seasonal **import** seasonal_decompose
**from** statsmodels.tsa.arima.model **import** ARIMA **as** ARIMA
**import** numpy **as** np

我们将使用 pandas 将数据加载到 DataFrame 中:

df = pd.**read_csv**(**'air_quality_uci.csv'**, header=0)

让我们打印出前 10 行:

df.**head**(10)

空气质量数据集的前 10 行(图片由作者提供)

回归目标

我们将建立一个回归模型来预测 PT08_S4_NO2 变量的小时值。

回归策略

我们模型的变量如下:

因变量 yPT08_S4_NO2

回归变量矩阵 X 将包含两个变量:
温度 T 绝对湿度 AH

我们将使用带有(季节性)ARIMA 误差的回归,即(S)ARIMAX 模型,通过每小时测量温度绝对湿度来预测 PT08_S4_NO2 的每小时值。

由于我们使用(S)ARIMAX,我们也可以隐式使用因变量 PT08_S4_NO2 的过去值和模型的过去误差作为额外的回归变量

我现在把(季节性的)或(S)放在括号里,因为我们还不知道回归的残差中是否存在季节性。我们很快就会知道了。

我们将使用以下逐步过程来构建(S)ARIMAX 模型:

步骤 1:准备数据

将数据框中的日期时间列转换为 pandas 日期时间列,并将其设置为数据框的索引。

df[**'DateTimeIndex'**]= pd.**to_datetime**(df[**'DateTime'**])
df = df.**set_index**(keys=[**'DateTimeIndex'**])

将索引的频率属性设置为每小时。这将创建几个空行,对应于原始数据集中丢失的每小时测量值。用相应列的平均值填充所有空白数据单元格。

df = df.**asfreq**(**'H'**)
df = df.**fillna**(df.**mean**())

验证任何列中没有空单元格。输出应该全为零。

df.**isin**([np.**nan**, np.**inf**, -np.**inf**]).**sum**()

创建训练和测试数据集。将测试数据集长度设置为训练数据集的 10%。我们实际上并不需要那么大,但我们现在就用 10%吧。

dataset_len = **len**(df)split_index = **round**(dataset_len*0.9)train_set_end_date = df.**index**[split_index]df_train = df.**loc**[df.**index** <= train_set_end_date].**copy**()df_test = df.**loc**[df.**index** > train_set_end_date].**copy**()

步骤 2:创建线性回归模型

现在,我们将在训练数据集上拟合一个普通的最小二乘线性回归模型,并获取它的残差向量。

让我们用 Patsy 语法创建模型表达式。在下面的表达式中,我们说 PT08_S4_NO2 是因变量,而 TAH 是回归变量。默认情况下,假设有一个截距项。

expr = **'PT08_S4_NO2 ~ T + AH'**

我们来雕刻出 yX 矩阵。Patsy 让这变得非常简单:

y_train, X_train = **dmatrices**(expr, df_train, return_type=**'dataframe'**)y_test, X_test = **dmatrices**(expr, df_test, return_type=**'dataframe'**)

在训练数据集上拟合 OLSR 模型:

olsr_results = linear_model.**OLS**(y_train, X_train).**fit**()

打印出 OLSR 模型的培训结果:

olsr_results.**summary**()

我们看到以下输出。我强调了输出中的几个重要区域:

OLSR 模特的模特训练总结(图片由作者提供)

我们看到,回归变量 T 和 AH 的回归系数在 99.99%的置信水平下是显著的,如它们的 P 值(P > |t|列)所示,P 值基本上为 0。

这些结果中需要注意的第二件事是 Durbin-Watson 测试的输出,该测试测量回归残差中 LAG-1 自相关的程度。值为 2 意味着没有滞后-1 自相关。在残差误差 ε 中,接近 0 的值意味着强正自相关,而接近 4 的值意味着在滞后-1 处强负自相关。

在上面的输出中,我们看到 DW 检验统计量是 0.348,表明在滞后-1 时回归的残差之间有很强的正自相关。这完全在意料之中,因为基础数据是一个时间序列,而线性回归模型未能解释因变量的自相关性。DW 测试统计正好证实了这一点。

步骤 3:估计 ARIMA 参数(P,D,Q),(P,D,Q)和 m

我们现在开始对 OLSR 模型的回归残差 ε估计萨里玛模型的参数的过程。 回归误差存储在变量olsr_results.resid中。

让我们从绘制残差的自相关图开始:

tsa.**plot_acf**(olsr_results.**resid**, **alpha**=0.05)
plt.**show**()

我们得到如下的情节:

残差的 ACF(图片由作者提供)

ACF 告诉我们三件事:

  1. 有很强的自相关延伸到多个滞后,表明残差时间序列有一个趋势。我们需要通过使用一阶或可能两阶差分来去除这个时间序列的趋势。因此,参数 d 可能是 1,也可能是 2。
  2. ACF 中的波状图案证明了数据中的季节性变化。
  3. 滞后= 24 时的峰值表明季节周期可能是 24 小时。即 m 很可能是 24 。对于包含车辆污染测量的数据,这似乎是合理的。我们将很快使用时间序列分解图来验证这个猜测。

快速注意:滞后-0 自相关将始终是一个完美的 1.0,可以被忽略,因为一个值是完全相关的。

在我们估计剩余的(S)ARIMA 参数之前,让我们对时间序列求一次差,即 d=1:

olsr_resid_diff_1 = olsr_results.resid.**diff**()
olsr_resid_diff_1 = olsr_resid_diff_1.**dropna**()

让我们重新绘制残差的差分时间序列的 ACF:

tsa.**plot_acf**(olsr_resid_diff_1, **alpha**=0.05)
plt.**show**()

残差差(1)的 ACF(图片由作者提供)

我们现在在 ACF 中看到一幅非常不同的画面。自相关在所有滞后处都显著降低。波状模式仍然存在,但这是因为我们没有采取任何措施来消除可能的季节变化。滞后-24 自相关再次特别突出。

我们看到,在差分时间序列中,在滞后-1 时仍有显著的自相关。我们可以尝试通过再取一个差值(即 d=2)并绘制结果时间序列 ACF:

olsr_resid_diff_2 = olsr_resid_diff_1.**diff**()
olsr_resid_diff_2 = olsr_resid_diff_2.**dropna**()
tsa.**plot_acf**(olsr_resid_diff_2, **alpha**=0.05)
plt.**show**()

我们得到如下的情节:

残差差(2)的 ACF(图片由作者提供)

不幸的是,第二次对时间序列求微分在 LAG-1 产生了严重的负自相关。这是不好的迹象。我们似乎夸大了差异。我们应该坚持 d=1。

让我们再来看看 DIFF(1)时间序列的 ACF:

DIFF(1) ACF 在 LAG-1 处显示单一正自相关(图片由作者提供)

在滞后-1 处的单个正自相关表明我们可能想要将 AR 阶数 p 固定为 1。即 AR(1)模型

由于我们已经将 p 固定为 1,现在,我们将省去模型中的 MA 部分。即我们将 q 固定为 0。也就是说,我们的 SARIMA 模型没有 MA 组件。

到目前为止,我们有如下结果:p=1,d=1,q=0

让我们验证季节周期 m 是 24 小时。为此,我们将使用 statsmodels 提供的seasonal_decompose() 函数将回归的残差分解为趋势、季节性和噪声:

components = **seasonal_decompose**(olsr_results.**resid**)
components.**plot**()

我们得到如下的情节:

回归残差分解(图片由作者

让我们放大一下季节性因素:

24 小时季节性周期的证据(图片由作者提供)

季节成分证实 m=24。

强季节分量保证差分的单个季节顺序,即我们设置 D=1。

让我们将单个季节差异应用于我们已经差分的残差时间序列:

olsr_resid_diff_1_24 = olsr_resid_diff_1.**diff**(**periods**=24)

季节性差异时间序列的 ACF(图片由作者提供)

滞后 24 点的强负相关表明具有 1 阶的季节性 MA (SMA)信号。即 Q=1 。此外,滞后-1 处正相关的缺失表明季节性 AR 成分的缺失。即 P=0。

我们固定 P=0,D=1,Q=1,m=24 小时

就是这样。

我们已经设法估计了 SARIMA 模型的所有 7 个参数如下: p=1,d=1,q=0,P=0,D=1,Q=1,m=24,即 SARIMAX(1,1,0)(0,1,1)24

步骤 4:建立并拟合带有季节性 ARIMA 误差的回归模型

让我们使用上述参数在训练数据集(y _ trainX _ train)上拟合 SARIMAX 模型。在此之前,我们需要删除 Patsy 自动添加到 X_train 的截距,并将 X_trainy_train 上的时间序列索引频率重置为每小时一次。

X_train_minus_intercept = X_train.**drop**(**'Intercept'**, **axis**=1)X_train_minus_intercept = X_train_minus_intercept.**asfreq**(**'H'**)y_train = y_train.**asfreq**(**'H'**)

让我们构建并测试 SARIMAX 模型:

sarimax_model = **ARIMA**(**endog**=y_train, **exog**=X_train_minus_intercept,**order**=(1,1,0), **seasonal_order**=(0,1,1,24))sarimax_results = sarimax_model.**fit**()sarimax_results.**summary**()

以下是培训总结:

SARIMAX(1,1,0)(0,1,1)24 训练结果(图片由作者提供)

在训练总结中首先要查看的数字是永盒测试的统计数据及其 p 值。Ljung-Box 帮助我们确定回归的残差是否在统计意义上是自相关的。在这种情况下,p 值为 0.4,显著高于 0.05 (95%置信阈值)。所以我们接受永盒检验的零假设,即残差不是自相关的

结果中需要注意的另外两件事是:Jarque-Bera 正态性检验产生了一个非常小的 p 值,这意味着在> 99.99%的置信水平上拒绝了零假设。假设回归误差是正态分布的。这可能是因为误差是高度峰度的(注意峰度=7.49,而不是正态分布的 3.0)。还要注意,误差根本没有偏斜(偏斜度=0.04,而正态分布误差为 0.0)。

回归误差也是异方差的,即它们具有非常数方差。H-test 的 p 值小得几乎为零就证明了这一点,但是您可以做一些事情来解决这个问题。

我们还可以对 P、D、Q、P、D、Q 和 m 的不同参数组合进行试验。事实证明,这种使用不同 SARIMAX 模型的迭代在 SARIMAX 世界中并不罕见。

我们要做的是通过将 Q 设为 0 来简化我们的模型。也就是说,我们将尝试 SARIMAX(1,1,0)(0,1,0)24 模型:

sarimax_model = **ARIMA**(**endog**=y_train, **exog**=X_train_minus_intercept,**order**=(1,1,0), **seasonal_order**=(0,1,0,24))sarimax_results = sarimax_model.**fit**()sarimax_results.**summary**()

以下是培训总结:

SARIMAX(1,1,0)(0,1,0)24 训练结果(图片由作者提供)

在这个修正的模型中,我们看到 Ljung-Box 检验统计量的 p 值已经从早期的 0.4 降低到 0.1,这意味着这个模型的回归误差与早期模型相比不相关的可能性要小得多。与以前的模型相比,新模型似乎并没有使误差变得更不异方差或更正态分布。

我们将接受模型的早期版本,即 SARIMAX(1,1,0)(0,1,1)24 模型。

(感谢 蒂亚戈·里巴斯 在本节早期版本中发现错误)

第五步:预测

SARIMAX 传奇的最后一步是使用选择的模型生成一些预测。我们将要求模型生成 24 个样本外预测,即预测训练数据集结束后未来 24 小时的 y (污染物 PT08_S4_NO2)值。我们将使用我们在步骤 1 中划分出的测试数据集( y_testX_test )。回想一下,模型在训练期间从未见过测试数据集。

让我们为预测准备测试数据集:

X_test_minus_intercept = X_test.**drop**(**'Intercept'**, **axis**=1)X_test_minus_intercept = X_test_minus_intercept.**asfreq**(**'H'**)y_test = y_test.**asfreq**(**'H'**)

调用get_forecast方法获得样本外预测:

predictions = sarimax_results.**get_forecast**(**steps**=24, **exog**=X_test_minus_intercept[:24])predictions.**summary_frame**()

我们得到以下输出:

PT08_S4_NO2 的 24 个样本外预报(图片由作者提供)

让我们将测试数据集中的实际值 y_test 与 summary _frame 的“平均值”列中提到的预测值一起绘制出来。我们将绘制每个预测值的置信下限和置信上限:

predicted, = plt.**plot**(X_test_minus_intercept[:24].**index**, predictions.**summary_frame**()[**'mean'**], **'go-'**, **label**=**'**Predicted**'**)actual, = plt.**plot**(X_test_minus_intercept[:24].**index**, y_test[:24], **'ro-'**, **label**=**'**Actual**'**)lower, = plt.**plot**(X_test_minus_intercept[:24].**index**, predictions.**summary_frame**()[**'**mean_ci_lower**'**], **color**=**'**#990099**'**, **marker**=**'**.**'**, **linestyle**=**'**:**'**, **label**=**'**Lower 95%**'**)upper, = plt.**plot**(X_test_minus_intercept[:24].**index**, predictions.**summary_frame**()[**'**mean_ci_upper**'**], **color**=**'**#0000cc**'**, **marker**=**'.'**, **linestyle**=**':'**, **label**=**'**Upper 95%**'**)plt.**fill_between**(X_test_minus_intercept[:24].**index**, predictions.**summary_frame**()['mean_ci_lower'], predictions.**summary_frame**()['mean_ci_upper'], **color** = **'**b**'**, **alpha** = 0.2)plt.**legend**(**handles**=[predicted, actual, lower, upper])plt.**show**()

我们得到如下的情节:

预测、实际和 95%置信区间(图片由作者提供)

关键要点

  • 带有(季节性)ARIMA 误差的回归(SARIMAX)是一种时间序列回归模型,它结合了两种强大的回归模型,即线性回归和 ARIMA(或季节性 ARIMA)。
  • Python Statsmodels 库通过 Statsmodels 的 v0.12.0 中的statsmodels.tsa.arima.model.ARIMA类或 v0.13.0 中的statsmodels.tsa.statespace.sarimax.SARIMAX为构建 ARIMAX 模型提供了强大的支持。
  • 在配置(S)ARIMAX 模型的(S)ARIMA 部分时,使用一组众所周知的规则(结合个人判断)有助于确定(S)ARIMAX 模型的 P、D、Q、P、D、Q 和 m 参数值。
  • 设计良好的(S)ARIMAX 模型的回归残差几乎没有自相关。这由永氏盒试验的 p 值表示。
  • 此外,您可能希望残差是等方差的,并且(最好)是正态分布的。因此,您可能需要尝试 P、D、Q、P、D、Q 的不同组合,直到您获得具有最佳拟合度特征的模型。

相关阅读

[## 线性回归的假设

以及如何使用 Python 测试它们。

towardsdatascience.com](/assumptions-of-linear-regression-5d87c347140) [## 什么是时间序列分解,它是如何工作的?

另外,首先深入研究使用 Python 的强大的时间序列分解算法

towardsdatascience.com](/what-is-time-series-decomposition-and-how-does-it-work-9b67e007ae90) [## 当回归模型的误差包含两个峰值时

关于处理双峰残差的 Python 教程

towardsdatascience.com](/when-your-regression-models-errors-contain-two-peaks-13d835686ca) [## 异方差没有什么可怕的

使用 Python 的原因、影响、测试和解决方案

towardsdatascience.com](/heteroscedasticity-is-nothing-to-be-afraid-of-730dd3f7ca1f) [## 使用偏度和峰度检验正态性

…以及使用综合 K 平方和 Jarque–Bera 正态性检验的分步指南

towardsdatascience.com](/testing-for-normality-using-skewness-and-kurtosis-afd61be860)

参考文献、引文和版权

空气质量测量的数据集来自 UCI 机器学习库,可用于研究目的。

论文链接: S. De Vito,E. Massera,M. Piga,L. Martinotto,G. Di 法兰克王国,关于在城市污染监测场景中用于苯估计的电子鼻的现场校准,传感器和致动器 B:化学,第 129 卷,第 2 期,2008 年 2 月 22 日,第 750-757 页,ISSN 0925-4005, 【网页链接】 ( 【网页链接】)

本文中的所有图片版权归 Sachin Date 所有,版权归 CC-BY-NC-SA 所有,除非图片下面提到了不同的来源和版权。

感谢阅读!如果您喜欢这篇文章,请 关注我 获取关于回归和时间序列分析的提示、操作方法和编程建议。**

PyCaret 回归:一个更好的机器学习库

原文:https://towardsdatascience.com/regression-with-pycaret-a-better-machine-learning-library-e02762a0615c?source=collection_archive---------20-----------------------

让我们看看用 PyCaret 解决回归问题有多简单。包括源代码。

几天前,我介绍了 PyCaret 库的基础知识,并展示了它如何在易用性方面击败众所周知的 Scikit-Learn。今天我们将更具体一点,并介绍如何处理回归任务。阅读前一篇文章不是先决条件,但是如果你以前没有使用过这个库,可以随意浏览一下。

由 HARALD PLIESSNIG 在 Unsplash 上拍摄的照片

回归问题在我们周围无处不在——最明显的是任何种类的价格预测。这就是为什么我们必须知道如何解决回归任务,以及如何高效地解决它们。

如果你更喜欢视频,或者只是想巩固你的知识,请随意观看我们关于这个主题的视频。源代码包括:

在开发时间方面,PyCaret 比 Scikit-Learn 更适合回归任务。这一切都归结为几个函数调用。不需要在几个学习算法之间进行测试,也不需要花费几天时间来调整超参数。PyCaret 为您做了所有这些(甚至更多)。

这篇文章的目标读者是熟悉机器学习中回归概念的人。熟练的知识不是必需的,因为我们将简要回顾回归理论。

这篇文章的结构如下:

  1. 高级回归概述
  2. 模型选择、训练和优化
  3. 模型可视化
  4. 预测和模型保存
  5. 结论

所以事不宜迟,让我们开始吧!

高级回归概述

我假设你已经知道什么是回归。Investopedia的一段话比我更好地总结了这一点:

回归是一种用于金融、投资和其它学科的统计方法,它试图确定一个因变量(通常用 Y 表示)和一系列其它变量(称为自变量)之间关系的强度和特征

用最简单的术语来说——我们希望通过数据点拟合一条线(或超平面),以获得最佳拟合线。后面的算法旨在找到最小化成本函数的线,通常是 MSE 或 RMSE。

这是线性回归,但也有其他类型,如多项式回归。与它的弟弟不同,多项式回归不假设线性关系,有时可以产生更好的结果。只是不要疯狂地使用多项式次数——因为模型往往会过度拟合。

我们还有更复杂的回归算法,比如:

  • 随机森林回归
  • XGBoost 回归

在大多数情况下,这些将优于线性回归,代价是模型的可解释性。不需要考虑算法选择,因为 PyCaret 会自动选择算法。让我们在下一节看看如何实现。

模型选择、训练和优化

现在有趣的部分来了。我们将使用来自 Kaggle 的房地产数据集。它看起来是这样的:

它需要清理一下,但不要太大。这是代码

df.drop([‘No’, ‘X1 transaction date’], axis=1, inplace=True)
df.columns = [‘Age’, ‘DistanceToMTR’, ‘NumStores’, ‘Latitude’, ‘Longitude’, ‘UnitPrice’]

现在情况好些了,但我们还有一个“问题”。如果说这些年来我学到了什么,那就是定价数据集通常是有偏差的。这意味着目标变量不遵循正态分布。

就预测而言,这是一个问题,因为它会影响模型的性能。下面是目标变量的直方图:

怀疑得到证实。为了解决这个问题,我们将使用一种非常科学的目测方法,删除所有单价大于 70 的记录。当然,有更好的方法来处理这个问题,但是我想尽快开始建模。

df = df[df[‘UnitPrice’] <= 70]

我们现在有了一些看起来更正常的东西,可以继续建模过程了。如果你读过之前的文章,你就知道这部分不能再简单了。首先,让我们从 PyCaret 库中导入回归模块并执行基本设置:

from pycaret.regression import *exp_reg = setup(df, target=’UnitPrice’)

几秒钟后,您将看到一条成功消息和一个数据框,其中包含大量数据信息。请随意通读。接下来,我们可以比较一堆机器学习模型的性能,看看哪一个做得最好。就像函数调用一样简单:

compare_models()

似乎随机森林算法总体上做得最好,所以我们将使用它来创建模型:

model = create_model(‘rf’)

模型调整现在也是一个简单的过程:

tuned_model = tune_model(‘rf’)

下面是原始模型和调整后的模型之间的性能比较:

所以是的,超参数调整,尽管只持续了几秒钟,将 RMSE 从 6.17 降低到了 5.82。现在,让我们从这个调整后的模型中进行一些可视化处理。

模型可视化

首先,让我们绘制调整模型的残差图:

plot_model(tuned_model)

火车片场的表现更好,但那是意料之中的。训练集和测试集残差都是正态分布的。接下来,让我们用 SHAP 值来解释我们的模型。

SHAP,或沙普利附加解释,是一种解释机器学习模型输出的方式。通过绘制每个样本的每个特征的 SHAP 值,我们可以使用它来查看哪些特征最重要。

interpret_model(tuned_model)

到 MRT 的距离更远(图表上的错别字,抱歉),导致单价下降。房产的年限也是如此。位置(纬度和经度)正好相反。我们还没有用地理图可视化这些数据,所以我提供一些推理是没有意义的。

接下来,让我们进行预测并保存我们的回归模型。

预测和模型保存

好的,假设我们对模型的表现很满意,我们想对测试集做一个最终的评估。方法如下:

predictions = predict_model(tuned_model)

您可能不知道的是,PyCaret 在数据集加载时进行了 70:30 的训练测试分割,因此我们不必手动完成这一步。您可以更改这个百分比,但是 70:30 是一个很好的起点。

我们在测试集上看到了一点糟糕的结果,但这是意料之中的。在将模型保存到 pickle 文件之前,我们需要完成它:

finalize_model(tuned_model)

现在可以在您选择的环境中保存模型以备后用:

save_model(tuned_model, ‘realestate_rf’)

这就是 PyCaret 的回归任务。让我们在下一部分总结一下。

结论

这是一篇有趣的文章。如果您一直在跟进,我希望您已经花了一些额外的时间来准备数据,并在建模中获得了更好的结果。因为我们有纬度和经度信息,所以制作这个数据集的地理图也是很好的。这样我们就能更好地解释为什么经度和纬度的增加会导致价格上涨。

无论如何,我希望你已经设法得到一些有用的东西。当然,还有更多的东西需要探索,但是 PyCaret 使我们能够将更多的时间花在重要的事情上——比如数据准备和模型解释,而不是花费数周的时间来训练和调整模型。

感谢阅读。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership)

Python 中的正则表达式

原文:https://towardsdatascience.com/regular-expressions-in-python-2f79e37f8dff?source=collection_archive---------45-----------------------

在 re 模块中搜索并拆分功能

简介

正则表达式或 regex 是一个字符序列,用于检查每个文本(字符串)中是否存在模式,例如,找出“123”是否存在于“Practical123DataScie”中。regex 解析器将“123”解释为在字符串中只匹配自身的普通字符。但是正则表达式的真正威力在于当一个模式包含称为 元字符 的特殊字符时。这些对于正则表达式匹配引擎有着独特的意义,并极大地增强了搜索能力。

Regex 功能驻留在一个名为*re*的模块中。因此,像 Python 中的所有模块一样,我们只需要如下导入它就可以开始工作了。

import re

本教程涵盖了 re 模块中非常有用的函数,例如分别用于搜索和替换的 search()split() 。您还将学习用元字符创建复杂的匹配模式。

我)。搜索()功能

正则表达式搜索通常被写成:

re.search(*pattern*, *string*)

这个函数遍历字符串,找到与模式匹配的第一个位置。如果不匹配,则返回 None。让我们看看下面的例子:

s1= "Practical123DataScie"
re.search("123", s1)Output: <re.Match object; span=(9, 12), match='123'>

输出为您提供了大量信息。它告诉你有一个匹配,并位于字符串的 s[9:12]。这是一个简单的例子,我们可能需要搜索复杂的模式。现在想象一下,你想找三个类似“456”或者“789”的连续数字。在这种情况下,我们需要使用模式,因为我们在寻找连续的数字,而我们不知道这些数字到底是什么。它们可能是“124”、“052”等等。我们如何做到这一点?

s2 = “PracticalDataScie052”
re.search(‘[0–9][0–9][0–9]’, s2)Output: <re.Match object; span=(17, 20), match='052'>

这里有很多概念要讲。这里用的图案是‘[0-9][0-9][0-9]’. 先来说说方括号 ([]) 。正则表达式或模式 […] 告诉你匹配方括号中的任何单个字符。例如:

re.search(‘[0]’, s2)Output: <re.Match object; span=(17, 18), match='0'>

这个模式'[0]'告诉在 s2 字符串中定位字符 0,如果匹配就打印出来。如果我需要定位更多字符,比如三个数字,我可以写:

re.search(‘[0][5][2]’, s2)Output: <re.Match object; span=(17, 20), match='052'>

好吧,你是对的。我可以只输入' 052 '作为一个模式,在 s2 字符串中定位它,但是现在事情变得有趣了。我可以在方括号内创建另一个正则表达式,例如用于范围。我这么说是什么意思?这意味着使用 (-) ,我可以定位一系列字符。例如:

re.search(‘[0–9]’, s2)Output: <re.Match object; span=(17, 18), match='0'>

意思是找出 s2 内从 0 到 9 的任意一个数字。现在,让我们回到定位三个连续数字的问题上来。为此,我可以简单地写:

re.search(‘[0–9][0–9][0–9]’, s2)Output: <re.Match object; span=(17, 20), match='052'>

每个方括号内的每个范围告诉你在 s2 字符串中找出一个数字。我也可以使用字母范围。例如:

re.search(‘[a-z][0–9]’, s2)Output: <re.Match object; span=(16, 18), match='x0'>

这个例子告诉我们定位两个字符。第一个,任何小写字母,第二个字符应该是数字。输出(' x0 ')正是我们期望得到的。正则表达式 '\d' 等于' 0–9 '。所以,对于前面的例子,我也可以用:

re.search(‘[a-z][\d]’, s2)Output: <re.Match object; span=(16, 18), match='x0'>

二世)。split()函数

与搜索函数类似,正则表达式拆分通常写成:

重新拆分(图案)

这个函数使用模式作为分隔符分割字符串,并将子字符串作为列表返回。让我们看看下面的例子:

re.split(‘[;]’, ‘Data;Science and; Data Analysis;courses’)Output: ['Data', 'Science and', ' Data Analysis', 'courses']

在这个例子中,模式是[;],这意味着我们有分号(;)作为分隔符。只要字符串中有分号,它就会在那个位置被拆分并保存在一个列表中。我们可以有不止一个分隔符。让我们看一个更复杂的例子。

string = “Data12Science567programbyAWS025GoogleCloud”
re.split(‘\d+’, string)Output: ['Data', 'Science', 'programbyAWS', 'GoogleCloud']

在这个例子中,我们的模式是' \d+',我们都知道' \d '模式表示任何数字(0 到 9)。通过在末尾添加一个“+”符号,将使模式匹配至少一个或多个数字。因此,在这种情况下,我们看到任何连续的数字都将被认为是分隔的,并且子字符串在列表中返回。

让我们考虑下面的字符串。我有两门【课程号】【编程语言】【课程名称】格式的课程。字符串写在两个不同的行中,单词之间的间距不相等。

string = ‘’’101              Python       DataScience 
                  102           R      DataAnalysis’’’
re.split(‘\s+’, string)Output: ['101', 'Python', 'DataScience', '102', 'R', 'DataAnalysis']

在本例中,' \s '模式匹配任何空白字符。通过在其末尾添加加号“+”,该模式将匹配至少 1 个或更多空格。

III)结论

本教程中已经讨论了 re 模块中的搜索和分割功能。使用元字符创建不同的模式,在文本挖掘中会非常有益。

Python 中的正则表达式

原文:https://towardsdatascience.com/regular-expressions-in-python-7c991daab100?source=collection_archive---------25-----------------------

数据科学的正则表达式

来源

正则表达式是定义文本中搜索模式的特殊字符序列。在这篇文章中,我们将讨论如何使用 python 中最基本的正则表达式方法之一“re.findall()”来提取字符串表达式的开头。

我们开始吧!

首先,让我们导入 python 正则表达式模块“re”:

import re

假设我们有以下字符串:

test_string1 = 'Python is Amazing!'

我们可以将表达式 r "^\w+ "传递给' re.findall()',以及我们的字符串,这将返回我们的输入字符串的开头:

regex_1 = re.findall(r"^\w+",test_string1)
print(regex_1)

在表达式 r“\w+”中,字符''对应于字符串的开头,而' \w+'在字符串中查找字母数字字符。

如果我们去掉'^',我们会得到:

regex_1 = re.findall(r"\w+",test_string1)
print(regex_1)

让我们试着拉另一个字符串示例的开头:

test_string2 = 'Java is Amazing!'

现在,让我们应用' re.findall()'来查找该字符串的第一个单词:

regex_2 = re.findall(r"^\w+",test_string2)
print(regex_2)

接下来,让我们考虑一个更现实的场景,在这个场景中,这个方法可能是有用的。假设我们有一个 YouTube 视频标题和相应的 YouTube 视图的列表。我们可能对分析视频标题的第一个单词和相应的视频观看次数之间的关系感兴趣。考虑下面的标题/视图元组列表:

youtube_titles = [("How to Tell if We're Beating COVID-19", 2200000), ("Extreme Closet Clean Out",326000), ("This is $1,000,000 in Food",8800000), ("How To Tell If Someone Truly Loves You ", 2800000), ("How to Tell Real Gold from Fake", 2300000), ("Extreme living room transformation ", 25000)]

我们可以用下面的方法找到每个标题的第一个单词:

for title in youtube_titles:
    print(re.findall(r"^\w+",title[0])[0])

我们可以将这些值追加到列表中:

first_words = []
for title in youtube_titles:
    first_words.append(re.findall(r"^\w+",title[0])[0])
print(first_words)

我们还可以将视图附加到列表中:

first_words = []
views = []
for title in youtube_titles:
    first_words.append(re.findall(r"^\w+",title[0])[0])
    views.append(title[1])

然后,我们可以创建首字值和视频视图的数据框:

import pandas as pd
df = pd.DataFrame({'first_words': first_words, 'views':views})
print(df)

然后,我们可以执行分组,并计算每个第一个词的平均浏览量:

df = df.groupby('first_words')['views'].mean()
print(df)

让我们也按降序对这些值进行排序:

df = df.groupby('first_words')['views'].mean().sort_values(ascending = False)
print(df)

假设这些结果来自足够大的数据集,比如有数千个标题和观看次数,这种类型的分析可以帮助我们选择最佳的 YouTube 视频标题。

我将在这里停下来,但是我鼓励您自己尝试使用“re.findall()”方法。

结论

总之,在这篇文章中,我们讨论了如何使用 python 中正则表达式模块的“re.findall()”方法。我们将该方法应用于两个简单的字符串,以提取每个字符串的第一个单词。然后,我们考虑了一个更现实的用例,我们使用该方法提取 YouTube 视频标题的第一个词,并计算每个第一个词对应的平均视频浏览量。我希望你觉得这篇文章有趣/有用。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

正则表达式(RegEx):用备忘单清楚地解释它们

原文:https://towardsdatascience.com/regular-expressions-regex-dont-fear-them-it-is-simpler-than-you-think-3a4d6de77058?source=collection_archive---------29-----------------------

正则表达式(或 regex )是用来表示字符串模式的工具。它们用于检测、检查、修改和操作字符串。基本上,如果你想在一个文本中找到所有的专有名词,你可以使用正则表达式。我们知道名称只包含字母,并且以大写字母开头。Regex 允许我们将自然的人类短语转录成计算机表示。他们精通 Python 或 Java,甚至 Excel,对于工程师、营销人员或其他人来说非常有用。

但是正则表达式,乍一看,毫无魅力。一个人可以害怕他们,但是错误地害怕他们。除了少数例外,它们在所有平台上都以相同的方式使用。因此,我将展示使用 Python 了解 regex 的要点。

我为你准备了一张 小抄,你可以下载 来总结这篇文章中会看到的内容。

准备一个 Python 脚本,自己进行可视化测试

(非强制性)

为了让这篇文章尽可能的有用和互动,我很快为你创建了一个小的 python 脚本。你将能够用清晰的视觉实时地自己测试任何你想要的东西。

如果你没有 python 或者只是想看帖子那么 你可以去下一节 没有任何问题。本帖中的图片展示了结果

首先,您将要做的所有测试都将位于一个您将命名为file.jsonJSON 文件中。你可以把你的正则表达式写在引号内"Regular expressions" :之后。注意,在 JSON 格式中,\是一个叫做转义符的特殊字符。所以你必须写一个双反斜杠\\

动态结果将自动在控制台中显示。因此,为了格式化我的文本,我创建了一个class SGR,代表“选择图形再现”。你可以在这里找到更多关于如何格式化你的文本的信息。

最后一段代码用于提取并在控制台中显示从测试句子的正则表达式中编译的数据。这允许你有你在上面看到的渲染。有必要了解什么是 regex 才能更好的理解这个脚本。我对代码做了注释,所以你可以在读完这篇文章后再来看。

让我们从基础开始

假设我们正在寻找所有的字母 "e " 。那么关联的正则表达式就是简单的e。如果我们寻找所有出现的字符串“el”,那么相关的正则表达式就是el。注意,正则表达式是区分大小写的。换句话说,e不同于E

如果你同时使用了我上面的脚本或其他工具来测试,我邀请你尽可能多地自己尝试这个概念,例如,正则表达式hello或正则表达式Welcome。只有Welcome正则表达式会给出结果,因为它区分大小写。

范围

到目前为止,没什么复杂的,我们甚至可以不用正则表达式。正是从这一点开始,正则表达式引起了他们所有的兴趣。让我们想象一下,我们想要捕捉文本中所有的元音。我们不能编写 regex aeiouAEIOU(记住它是区分大小写的)来完成这个任务。所以我们不得不引入区间的概念。音程写在方括号内[…] 。为了匹配所有的元音,我们需要正则表达式[aeiouAEIOU]。如果我们必须对它进行人工解读,我们会说我们在寻找所有的字符“a”或“e”或“I”或“O”或“U”。

如果我们希望所有大写字母(大写)从“D”到“W”,我们将使用正则表达式[D-W]

为了熟悉这个区间(或范围)的概念,你可以使用 附带的备忘单 中的区间尝试出新的正则表达式。

字符类别

要用大写和小写说出字母表中的每个字母,必须写[a-zA-Z]。我承认付出了很多努力,但收效甚微。这就是为什么有不同的可用于构建正则表达式:

  • 为了替换[a-zA-Z],(所有的字母)我们有\w,这相当于说我们想要的任何单词字符
  • 对于任何数字字符,我们有 T2 类。
  • \s相当于一个空格字符。
  • 换行\n.给出
  • .意味着我们希望占位符中的任意字符(除了换行符\n)。

因此,如果我们想找到所有由空格包围的双字单词,我们有正则表达式\s\w\w\s

注意每个类都有它的否定。否定是用大写格式写的。也就是说,如果我们想要除了字母以外的所有东西,我们就必须写\W (注意\W也表示没有数字)。如果我们想捕捉除了数字以外的所有东西,我们可以使用\D类。同样适用于\S

为了捕捉三次任何不是单词或数字字符的东西,我们可以选择...\W

量词

在前面的例子中,我们使用 regex ...\W来获取不以字母结尾的 4 个字符的字符串。假设我们想要同样的东西,但是有 8 个字符。我们可以写.......\W,但是很明显你看到了其中的问题。最好的方法是能够选择我们想要的重复次数。这正是量词的作用。

给定在括号{…} 之间,量词应用于其后的字符。因此,为了让每个空格后跟 4 个字的字符,我们可以使用\s\w{4}

你也可以更进一步,选择最小或最大重复次数,或者询问重复间隔。对于两个到七个字母之间的单词,我们有正则表达式\w{2,7}

还有其他的量词:

  • +允许我们指定 1 个或多个等同于{1,}
  • *可以表示 0 或更多的,相当于{0,}
  • 最后,?表示 0 或 1 乘以,与{0,1}相同。

为了演示它,让我们想象一下,由于某种原因,我们需要捕捉每个空格,后跟最多 2 个任意字符,后跟另一个空格,然后是一个单词。一个词当然包含至少一个字符(+量词),所以我们必须检查所有对应于\s.{,2}\s\w+的模式。(直写但不一定要读)

大量信息堆积起来。熟能生巧,所以你需要一开始就把小抄带在身边。在进入下一部分之前,让我们稍微休息一下,看看这只猫。我保证这一跳看起来很难,但其实并不难。

资料来源:GIPHY

接下来的部分将详细介绍 python 能做些什么。如果你看了我提供的代码,你会注意到有一个的概念。为了简单起见,让我们假设我们想要提取问候“Hello”、“Welcome”和“Hey”。我们可以一个接一个地做 3 个正则表达式[Hh]ello[Ww]elcome[Hh]ey、T23。(注意,在这些正则表达式中,我们考虑到 a 可以以大写字母开头)。
但是我们可以
通过在括号(…) 之间建立一个所谓的组,并用一个竖线| 分隔,将这三个正则表达式聚集成一个。我们得到正则表达式([Hh]ello|[Ww]elcome|[Hh]ey)。****

你可以在上面的图片上看到组可以被 python 检测到并返回。所以最大的好处就是组可以作为变量返回。你也可以使用字典组。也就是说,在 python 字典中返回给我们的组。只需更改组的开头,如斜体所示(*?P<greetings>*[Hh]ello|[Ww]elcome|[Hh]ey)
所以你最终得到一个带有
问候语** 的字典,从你的脚本中访问这场比赛,如下图所示。注意所有的字典组都包含在组中。**

您也可以决定不使用(*?:*[Hh]ello|[Ww]elcome|[Hh]ey)格式返回组。但我再次邀请你用这张纸自己试一下

断言

您还可以使用许多可能的断言,包括:

  • ^表示一个字符串的开始
  • $为结尾或一串
  • \b象征一个字的边界

如果你现在想抓住所有以感叹号结尾的句子。然后就和要求一句话从头到尾结尾带感叹号且不管中间是什么一样。此处节录**^.*!$**

我刚发现做这个截图很有趣:)

还有其他一些需要更多关注的断言

为了总结正则表达式可以做的事情,我想通过一个例子来介绍其中的一个。这一部分的目的是复制下面的正则表达式。不要慌,它又长又丑。但是我敢打赌,我可以告诉你,一个正则表达式,从一部分来看,实际上并没有那么复杂。

本部分的目的是回答以下问题:“您与谁会面”?
所以要回答这个问题,我们需要提取出
直接放在前面的名字“with”。这是一个断言。从字面上来看,它是一个正向后视标记为(?< =…)** 。积极是因为“是”而不是“不是”,回顾是因为“在前”而不是“在后”。**

为了提取单词“with”(和一个空格字符)前面的内容,我们以 regex (?<=with\s).*结束。

因此,我们摘录了直接跟在“with”后面的内容。但是我们想知道这个人的名字。

那么让我们想象一个困难的情况,其中有一个“迈克尔-菲利普·约翰逊”。他的名字也可以写成:“M.-P”。或者“MP”或者“M”或者“M-P”。为了让只有** **个大写字母或一个点或连字符,后面可能跟着小写字母,我们使用了正则表达式[A-Z\.\-]+[a-z]*。(注意.是留给“任意字符”的。如果你真的想要一个点,你必须在前面加上转义字符\。对于-来说也是同样的想法。)

然后在 dictionary 中将这个组作为返回,这个步骤很简单,我们可以在末尾添加一个?,因为名字也可以不写。并且加一个\s保证字尾。

我们得到(?P<firstname>[A-Z\.\-]+[a-z]*)?\s与我们已经拥有的东西串联起来:
我们得到(?<=with\s)(?P<firstname>[A-Z\.\-]+[a-z]*)?\s

那么很容易!姓氏由一个大写字母和几个小写字母定义,因此我们可以编写[A-Z][a-z]+正则表达式。通过在 python 字典中添加 return,它变成了(?P<lastname>[A-Z][a-z]+)
如果姓氏和“with”之间没有名字,则没有额外的空格。我们加一个?来保证这种情况。串联一切和 Tadam! (?<=with\s)(?P<firstname>[A-Z\.\-]+[a-z]*)?\s?(?P<lastname>[A-Z][a-z]+)

旗帜

最后还有多面旗。我不会解释如何使用它们,因为它们在不同的编程语言中有不同的用法。它们当然会出现在备忘单中。例如,如果您想要:

  • 忽略区分大小写你可以使用 I 标志
  • 允许注释和空格在正则表达式中你可以使用 X 标志
  • 允许多线M

(python re 包中的例子)。

知识就是分享。
支持我,一键获得访问 中我所有文章的

来源

正则表达式操作,Python 文档

所有的图片和脚本都是自制的,可以免费使用。

这里是 github 库你可以在那里找到脚本

我的小抄又来了,免费的时候总是更好!🆓 🆓 🆓

深度学习中的正规化和退出

原文:https://towardsdatascience.com/regularization-dropout-in-deep-learning-5198c2bf6107?source=collection_archive---------28-----------------------

编码,这样你就能理解了

在上一篇帖子中,我们已经编码了一个深度密集的神经网络,但是为了拥有一个更好、更完整的神经网络,我们需要它更加健壮,能够抵抗过拟合。你可能听说过,深度神经网络中常用的方法是正则化和丢弃。在本文中,我们将一起理解这两种方法,并用 python 实现它们。

(我们将在下面直接使用上一篇文章中创建的函数,如果你对一些代码感到困惑,你可能需要查看上一篇文章)

法比奥在 Unsplash 上拍摄的照片

正规化

正则化通过在损失函数的末尾增加一个额外的惩罚项来帮助防止模型过度拟合。

其中m是批量大小。所示的正则化称为L2 regularization,而L2将平方应用于权重,L1 regularization应用绝对值,其形式为|W|。

当有太多的重量或重量变得太大时,附加的额外项会扩大损失,并且可调因子λ强调了我们想要对重量进行多少惩罚。

1.为什么惩罚重量有助于防止过度拟合?

直观的理解是,在最小化新的损失函数的过程中,一些权重将降低到接近零,使得相应的神经元对我们的结果具有非常小的影响,就好像我们在具有更少神经元的更小的神经网络上训练一样。

向前

在正演过程中,我们只需要改变损失函数。

向后的

L2 regularization的后向传播实际上是直接向前的,我们只需要加上 L2 项的梯度。

培养

像往常一样,我们在一个二元分类案例上测试我们的模型,并比较有正则化和没有正则化的模型。

没有正则化的模型

正规化模型

实际上,当我们让iteration上升时,模型会继续过拟合,这导致除法运算中的错误,怀疑在前进过程中,结果A太接近 0。

相比之下,正则化模型不会过拟合。有关完整的实施和培训流程,请查看我的 Github Repo 。

拒绝传统社会的人

Dropout 通过随机关闭一些输出单元来防止过拟合。

  • [来源] *:https://github.com/enggen/Deep-Learning-Coursera

在上述过程中,在每次迭代中,层[2]上的一些单元将被随机静音,这意味着在正向过程中工作的神经元将减少,从而简化了神经网络的整体结构。

同时,经过训练的模型将更加健壮,因为该模型不再依赖于任何特定的神经元(因为它们可能在此过程中被抑制),所有其他神经元都需要在训练中学习。

向前

你可以把辍学看作是在前进的过程中增加了额外的一层。

在前面的课程中,我们有如下的正向方程式:

无脱落

其中g是激活函数。现在辍学的一个额外的层是适用于 A[1].

辍学

其中D是漏失层。辍学层的关键因素是keep_prob参数,它指定了保持每个单位的概率。假设keep_prob = 0.8,我们有 80%的机会保持每个输出单元不变,20%的机会将它们设置为 0。

这个实现将会给结果A添加一个额外的遮罩。假设我们有一个包含如下四个元素的输出 A^{[l]},

我们想让第三个单元静音,同时保留其余的单元,我们需要的是一个相同形状的矩阵,并做如下的元素乘法,

向前

下面有些模块是预导入的,要查看完整代码,请去我的 Github Repo 。

这里我们将D初始化为与A's相同的形状,并基于keep_prob将其转换为 0 和 1 矩阵。

注意,退学后,成绩 **A** 需要重新标度!因为一些神经元在此过程中被抑制,相应地,左侧神经元需要被增强以匹配期望值。

向后的

反向过程是将同一个函数D屏蔽到对应的dA

反向传播等式与我们在深度密集网络实施中介绍的等式相同。唯一的区别在于矩阵D。除了最后一层,所有其他有缺失的层将应用相应的蒙版DdA

注意,在反向传播中, **dA** 也需要重新缩放。

培训和评估部分与辍学,如果你有兴趣,请检查我的 Github 上面的链接。

结论

正则化和丢失都是广泛采用的防止过拟合的方法,正则化是通过在损失函数的末端增加一个额外的惩罚项来实现的,而丢失是通过在正向过程中随机静音一些神经元来实现的,以使网络更加简洁。

深度学习中的正规化——L1、L2 和辍学

原文:https://towardsdatascience.com/regularization-in-deep-learning-l1-l2-and-dropout-377e75acc036?source=collection_archive---------0-----------------------

深度学习中最重要的正则化技术的理论和实践指南

https://www.spacetelescope.org/images/heic0611b/

正则化是一套技术,可以防止神经网络中的过拟合,从而提高深度学习模型在面对来自问题域的全新数据时的准确性。 在本文中,我们将讨论最流行的正则化技术,它们被称为 L1、L2 和辍学。

目录

  1. 重述:过度拟合
  2. 什么是正规化?
  3. L2 正规化
  4. L1 正规化
  5. 为什么 L1 和 L2 的正规化会奏效?
  6. 辍学
  7. 带回家的信息

1.回顾:过度拟合

训练神经网络时最重要的一个方面是避免过度拟合。我们已经在这篇文章中详细讨论了过度拟合的问题。

然而,让我们快速回顾一下:过度拟合是指神经网络对训练数据建模非常好,但当它看到来自同一问题领域的新数据时失败的现象。过度拟合是由神经网络在训练期间拾取的训练数据中的噪声引起的,并将其作为数据的基本概念来学习。

www.memegenerator.net

然而,这种习得的噪声对于每个训练集是唯一的。一旦模型看到来自同一问题域的新数据,但不包含这种噪声,神经网络的性能就会变得更差。

“为什么神经网络首先会拾取噪音?”

之所以这样,是因为这个网络的复杂程度太高了。右边的图像显示了更高复杂度的神经网络拟合。

图表 1。具有良好拟合和高方差的模型。来源:https://www.researchgate.net/publication/332412613

具有较高复杂性的模型能够拾取和学习数据中由一些随机波动或误差引起的模式(噪声)。该网络将能够逐个模拟分布的每个数据样本,而不识别描述该分布的真实函数。

用真函数生成的新的任意样本将具有与模型拟合的高距离。我们也说这个模型有很高的方差。

另一方面,左侧复杂度较低的网络对分布的建模要好得多,因为它没有太努力地对每个数据模式进行单独建模。

在实践中,过度拟合导致神经网络模型在训练期间表现得非常好,但是当面对全新的数据时,在推理时间期间性能变得更差。

简而言之:不太复杂的神经网络不太容易过度拟合。为了防止过度拟合或高方差,我们必须使用所谓的正则化。

2.什么是正规化?

简单来说:正则化是指在训练过程中降低神经网络模型复杂性的一套不同技术,从而防止过拟合。

有三种非常流行和有效的正则化技术叫做【L1】和我们将在下面讨论的辍学。

3.L2 正则化

L2 正则化是所有正则化技术中最常见的类型,通常也被称为权重衰减或乘坐回归。

这个正则化的数学推导,以及为什么这个方法在减少过拟合方面起作用的数学解释,是相当长且复杂的。由于这是一篇非常实用的文章,我不想过多地关注数学。相反,我想传达这项技术背后的直觉,最重要的是如何实现它,以便您可以在深度学习项目中解决过度拟合问题。

在 L2 正则化期间,神经网络的损失函数由所谓的正则化项扩展,这里称为ω

情商。1 正则项

正则项ω被定义为权重矩阵的欧几里德范数(或 L2 范数),其是权重矩阵的所有平方权重值的总和。正则项由标量α除以 2 进行加权,并添加到为当前任务选择的正则损失函数中。这导致损失函数的新表达式:

Eq 2。L2 正则化过程中的正则化损失。

Alpha 有时被称为正则化率,是我们引入神经网络的一个额外的超参数。简单地说,alpha 决定了我们正则化模型的程度。

在下一步中,我们可以计算新损失函数的梯度,并将梯度放入权重的更新规则中:

**

情商。3 L2 正则化过程中的梯度下降。

更新规则的一些重新表述导致了非常类似于规则梯度下降期间权重的更新规则的表达式:

方程 4 L2 正则化期间的梯度下降。

唯一的区别是,通过添加正则化项,我们从当前权重中引入了额外的减法(等式中的第一项)。

换句话说,独立于损失函数的梯度,我们在每次执行更新时使我们的权重变小一点。

4.L1 正则化

在 L1 正则化(也称为 Lasso 回归)的情况下,我们简单地使用另一个正则化项ω。该项是权重矩阵中权重参数绝对值的总和:

情商。5 L1 正则化的正则化项。

与前一种情况一样,我们将正则项乘以α,然后将全部内容添加到损失函数中。

情商。6 L1 正则化过程中的损失函数。

新损失函数的导数导致以下表达式,旧损失函数的梯度和权重值的符号乘以α。

情商。7 L1 正则化期间损失函数的梯度。

5.为什么 L1 和 L2 的正规化会奏效?

你现在可能会问自己的问题是:

“为什么所有这些有助于减少过度拟合问题?”

让我们来解决这个问题。

请考虑和函数的图,其中表示在 L1 期间执行的运算和在 L2 正则化期间执行的运算。

图表。2 L1 函数(红色),L2 函数(蓝色)。来源:自制。

在 L2 正则化的情况下,我们的权重参数减小,但不一定变为零,因为曲线在零附近变得平坦。另一方面,在 L1 正则化期间,权重总是被强制向零。

我们也可以对此采取不同的、更加数学化的观点。

在 L2 的情况下,你可以考虑解一个方程,其中权重值的平方和等于或小于一个值 ss 是正则项 α 的每个可能值的常数。对于仅仅两个权重值 W1W2 ,该等式看起来如下: W1 + W ≤ s

另一方面, L1 正则化可以被认为是一个等式,其中权重值的模之和小于或等于值 s 。这看起来像下面的表达式: |W1| + |W2| ≤ s

基本上,引入的 L1 和 L2 正则化方程是约束函数,我们可以将其可视化:

资料来源:统计学习导论,作者:加雷斯·詹姆斯,丹妮拉·威滕,特雷弗·哈斯蒂,罗伯特·蒂布拉尼

左图显示了 L1 正则化的约束函数(绿色区域),右图显示了 L2 正则化的约束函数。红色椭圆是梯度下降过程中使用的损失函数的轮廓。在轮廓的中心,有一组最优权重,对于这些权重,损失函数具有全局最小值。

在 L1 和 L2 正则化的情况下,W1 和 W2 的估计值由椭圆与绿色约束区域相交的第一个点给出。

由于 L2 正则化具有圆形约束区域,所以相交通常不会出现在轴上,并且这对于 W1 和 W2 的估计将完全是非零的。

在 L1 的例子中,约束区域是带角的菱形。因此损失函数的轮廓通常会在轴上与约束区域相交。那么这种情况发生时,估计值之一(W1 或 W2)将为零。

在高维空间中,许多权重参数将同时等于零。

5.1 正规化实现了什么?

  • 执行 L2 正则化促使权重值趋向于零(但不完全为零)
  • 执行 L1 正则化促使权重值为零

直观地说,较小的权重减少了隐藏神经元的影响。在这种情况下,这些隐藏的神经元变得可以忽略,神经网络的整体复杂性降低。

如前所述:不太复杂的模型通常会避免对数据中的噪声进行建模,因此不存在过度拟合。

但是你必须小心。当选择正则项 α时。我们的目标是在模型的低复杂性和准确性之间取得适当的平衡

  • 如果你的阿尔法值太高,你的模型会很简单,但是你会冒对数据拟合不足的风险。您的模型无法从训练数据中获得足够的信息来做出有用的预测。
  • 如果你的 alpha 值太低,你的模型将会更复杂,你将会面临数据过度拟合的风险。您的模型将会了解太多有关训练数据的特殊性,并且无法推广到新数据。

6.拒绝传统社会的人

除了 L2 正则化和 L1 正则化,另一个著名的和强大的正则化技术是所谓的辍学正则化。辍学调整背后的程序非常简单。

简而言之,辍学意味着在训练期间,神经网络的一个神经元以某种概率在训练期间被关闭。让我们看一个直观的例子。

图表 3。有脱失(右)和无脱失(左)的神经网络。来源:机器学习研究杂志 15 (2014)

假设在左侧,我们有一个无丢失的前馈神经网络。假设一个随机神经元在训练过程中被关闭的概率为 P=0.5 ,使用 dropout 将导致神经网络位于右侧。

在这种情况下,您可以观察到大约一半的神经元是不活跃的,并且不被视为神经网络的一部分。如你所见,神经网络变得更简单了。

神经网络的更简单版本导致复杂性降低,从而可以减少过拟合。在每个前向传播和权重更新步骤应用具有一定概率 P 的神经元的去激活。

6.带回家的信息

  • 过度拟合发生在更复杂的神经网络模型中(许多层、许多神经元)
  • 通过使用 L1 和 L2 正则化以及丢弃,可以降低神经网络的复杂度
  • L1 正则化迫使权重参数变为零
  • L2 正则化迫使权重参数趋向于零(但从不精确为零)
  • 较小的权重参数使一些神经元可以忽略→神经网络变得不太复杂→较少过拟合
  • 在退出期间,一些神经元以随机概率 P →神经网络变得不那么复杂→更少的过拟合

最初发表于https://www.deeplearning-academy.com

机器学习中的正则化

原文:https://towardsdatascience.com/regularization-in-machine-learning-7f85f64ff8e8?source=collection_archive---------48-----------------------

灯塔和大海,由戈克图·古韦尔辛拍摄

介绍

在这篇文章中,我们主要关注机器学习中正则化的四个基本方面。

  • 什么是正规化?
  • 正规化是用来做什么的?
  • 正则化如何解决过拟合问题?
  • 关于偏差和方差误差的背景信息,以理解前面的三个要点。

本文从理论层面分析了正则化的这四个不同方面,并对它们进行了概述。在下一篇文章中,我们将探讨应用于线性回归的三种常见正则化技术,并展示正则化项如何影响空间世界中的优化算法,以提供关于它的几何直观。

1)背景信息

在训练标准的机器学习模型时,我们试图做的是使数据集的基础事实标签和模型对它们的预测尽可能彼此接近。这个操作是在我们为我们的问题选择的损失函数上执行的,它倾向于增加模型在训练集上的准确性,同时最小化总误差中的偏差

机器学习模型对其预测能力产生的总误差由三个值组成,分别是偏差方差不可约误差。偏差定义为预测值与正确标签的差异程度。

然而,这种趋势有时会导致 ML 模型记住数据集分散在多维空间中的模式,而不是理解并由此推广到该模式,这被称为过拟合。这是完全不理想的情况,因为模型实际上不会从数据中学习必要的东西,当我们在看不见的数据集上测试它时,它很可能会失败。此外,经历过拟合的 ML 模型变得如此复杂,因此;它们的方差在总误差上最大化。

方差是我们总误差中的第二项,它指的是模型对数据集的敏感度的大小。换句话说,如果一个模型的性能很容易受到数据集微小变化的影响,那么这个模型将会高度适应它。这是过度拟合的模型在未知测试集中失败而在训练集中成功的主要原因。

下图实际上是上面给出的所有解释的总结,它旨在提供关于上下文的洞察力。

模型的训练过程,作者:goktu gu vercin

2)正规化

在这一点上,正规化进入画面。正则化能够消除过度拟合,因此;提高模型质量。尽管其最常见的实践是在线性回归上观察到的,但它也适用于逻辑回归模型,以及遭受过拟合的人工神经网络。

正则化意在给目标 ML 或 DL 模型的代价函数增加额外的项。这个附加项的确切作用是防止优化算法(如梯度下降)达到最小化偏差误差的权重值。换句话说,它会给模型增加额外的偏置误差。这样,大量的方差误差被消除,模型摆脱了过拟合,并获得了超过其预测能力的泛化能力。下图也展示了这一过程。

规则化图,作者:goktu gu vercin

如正则化图中所示,为了最小化偏差误差,该模型倾向于放弃观察到总误差量最低的最佳点,并落入过拟合区域。正则化牺牲了少量的偏差;然而,在这种方式下,它通过减少大量的方差来实现将模型重新定位在最佳点。换句话说,在训练过程中,加入到代价函数中的正则项总是使模型保持在最佳状态;然而,如果我们在损失函数中不使用该项,模型可能会在过拟合区域结束。

正则项通常有两种不同的类型,称为 L2 和 L1。L2 项是多维空间中模型权重所在的原点和位置之间的欧氏距离,而 L1 项指的是同一事物,只是距离的计算方法不同,实际上是曼哈顿距离。在下图中,L2 和 L1 正则化项分别用逻辑回归和线性回归的损失函数进行了演示。

正规化术语,作者:goktu gu vercin

当优化算法试图达到损失曲线上的全局最小点时,它们实际上减少了这些损失函数中的第一项,即求和部分的值。然而,与此同时,权重向量的长度有增加的趋势;因此,正则项的值上升。优化算法必须在求和项和正则项之间建立平衡;不可能同时降低这两个值。超参数 lambda (λ)用于调整这种平衡,并决定哪一个更占优势。这种平衡,实际上也指上面提到的偏差-方差权衡。换句话说,正则化项表现得像手刹,正因为如此,正则化还能够缩小学习模型的权重,从而减少由于大权重的存在而在模型上观察到的不稳定性。

在这篇文章中,我们必须涵盖的最后一个要点是,为什么正则化项没有 bias ( b )参数,并且只在权重上定义。事实上,我们也可以通过偏差( b )参数来正则化我们的学习模型;没有限制,它必须进行公正的重量。然而,没有必要这样做,因为学习模型通常容纳大量的权重,并且与权重向量相比,在参数 b 上正则化模型对模型的贡献非常小。

结论

我希望我能提供关于正规化运作的有益信息。如果帖子里有不清楚的地方,可以在评论里提一下。应用于线性回归和几何直觉的最常见的正则化技术将在下一篇文章中讨论。

机器学习中的正则化

原文:https://towardsdatascience.com/regularization-in-machine-learning-b73bc486162a?source=collection_archive---------69-----------------------

让深度神经网络泛化的关键。

在 Unsplash 上由 Daiga Ellaby 拍摄的照片

在本文中,我将讨论正则化的概念、正则化方法的分类以及正则化策略的具体例子。

本质上,正则化增加了模型拟合过程的偏差,以防止过度拟合。正则化背后的直觉是,如果我们有一个非常丰富的模型类,例如大型神经网络,我们希望将我们的学习过程限制为仅在该类的子集上搜索,该子集包含具有所需属性(例如某种程度的简单性)的模型。这种限制是一种偏见。希望是,如果我们明智地选择子集(我们通过适当的正则化来做到这一点),我们将找到一个比我们查看整个模型类更好的模型。

假设我们考虑的模型类是线性回归类,并且我们正在尝试拟合样本数少于输入要素数的数据集。因为我们想要拟合的参数数量(=特征数量)大于样本数量,所以我们有一个不适定的问题,我们的类中可能有许多模型可以解决回归问题。我们可以通过施加 L2 正则化来限制这一类,即在误差项中添加 w ,其中 w 是我们的回归权重。通过这种方式,我们将在任何同等精确的权重集合中选择权重最小的解决方案。

正则化是一个比深度学习古老得多的概念,也是经典统计学不可或缺的一部分。它可以说是推动最近机器学习热潮的最重要的技术集合之一。尽管如此,当使用术语“正则化”时,我们通常并不完全清楚我们的意思,并且存在几个相互竞争的定义(例如 Goodfellow 等人的)。在本文中,我将采用可能是最广泛的一种方法——kuka ka 等人的方法:

定义 1:正则化是任何旨在使模型更好地泛化的补充技术,即在测试集上产生更好的结果。

乍一看,这似乎太笼统而没有用,但是作者也提供了一个分类法来理解这个定义所包含的大量正则化方法。这种分类法的概述如下。

正则化分类法

在查看模型拟合过程时,kuka ka 等人确定了以下部分,每个部分都与偏置学习的方式相关联,即,调整。

经验风险最小化。可正则化的部分是-紫色:优化,红色:训练集,绿色:误差项,棕色:模型族,蓝色:正则化项。

基于上面的经验风险优化公式,我们可以正则化:
1。训练设置
2。模范家庭
3。误差项
4。正则项
5。优化程序

训练集

满足上述定义 1(即有助于实现更好的测试误差)的我们的数据的任何预处理或增加(随机的或确定的)都属于这一类。突出的例子是不平衡数据集的过采样或欠采样、图像识别中的数据增强,以及具有对立例子、退出和批处理形式的训练。后两种可能看起来令人惊讶,但它们可以被视为中间网络层创建的表示空间中的数据转换。

扩大训练集是一种简单的方法,可以消除数据中的特定偏差,而不必提出更复杂的模型——图像识别文献表明它确实有效!缺点是,这些技术通常会增加训练集的大小,这意味着需要在训练上花费更多的资源,并且必须小心不要创建与任务无关的样本。

模范家庭

选择我们模型的正确结构可能通常不被称为正则化,但它也是一种提高泛化能力的方法,因此它符合定义。

如果你曾经使用过神经网络,你会知道超参数调整可能是得到一个好模型的最乏味的部分。选择层数和每层神经元的数量,甚至只是定义搜索哪些不同的设置都可以被视为正则化。你实际上是将所有可能的神经网络的搜索空间限制在对你有意义的配置上。人类的直觉在这里发挥作用,这或许是深度学习有时被比作艺术或黑魔法的原因。

比调整网络中的元素数量更令人兴奋的是定义网络的结构:卷积层、LSTMs、T2、softmax 层、T4、注意力层、T5 等等,不胜枚举。我们不要忘记 convnets 在使 DNNs 适用于图像识别中发挥了至关重要的作用!

误差项

当然,选择正确的误差项也会影响模型在测试集上的性能。均方误差可能是最流行的误差项,但是交叉熵也很流行,例如对于自然语言任务 s,或者某些类不平衡独立损失。这些错误术语概括了关于任务、数据以及好的解决方案是什么样子的假设。

正则项

正则化术语大概就是大多数人说正则化的意思。这是一个修正误差项而不依赖于数据的项。数据的这种独立性意味着正则项仅用于偏置模型参数的结构

可能最流行的正则化术语是网络上的 L2 范数或回归权重,也就是深度学习中的 权重衰减 和经典统计学中的岭回归的定义特征。这种 L2 正则化是吉洪诺夫正则化的一种特殊形式,实际上是模型权重的零均值高斯先验,这意味着我们倾向于使用较少而不是较多特征的解决方案,并且不会过度依赖任何特征。这潜在地消除了冗余特征,并产生了更简单的模型。为了进一步增加权重的稀疏性,可以使用 L1 范数(套索回归)。

其他正则化项针对例如输入上的梯度,或者输入-输出映射的函数属性。

正则化术语通常是一种定义模型外观的优雅方法,因为它们可以以即插即用的方式使用,并且对任何数据集都一样。它们通常会稍微增加超参数调整的工作量,因为通常需要定义一个参数来衡量正则项和误差项的贡献。

优化程序

优化过程是一种有趣的,但经常被忽视的正则化方法。改变优化器和学习速率显然对学习什么模型有影响,但是这种影响是什么通常不直观地清楚。一些有趣的最近结果显示 SGD 实际上可能是一个重要的正则化子,这可能有助于解释为什么深度神经网络像它们一样泛化(尽管被极大地过度参数化)。

本文到此为止,希望你学到有用的东西!请务必查看 Kukač ka 等人介绍分类学的论文,如果您对泛化和正则化感兴趣,也可以看看张等人非常容易理解的“理解深度学习需要重新思考泛化”。

正则化:机器学习

原文:https://towardsdatascience.com/regularization-machine-learning-891e9a62c58d?source=collection_archive---------8-----------------------

照片由 Alex wong 在 Unsplash 上拍摄

过度拟合模型、模型类型、数学和执行的解决方案。

简介:

为了理解正则化的概念及其与机器学习的联系,我们首先需要理解我们为什么需要正则化。我们都知道机器学习是用相关数据训练一个模型,并使用该模型预测未知数据。“未知”一词意味着模型尚未看到的数据。我们已经训练了这个模型,并且在使用训练数据时取得了不错的成绩。但是在预测的过程中,我们发现该模型与训练部分相比表现不佳。现在,这可能是一种过度拟合的情况(对此我将在下面解释),这导致了模型的不正确预测。在这种情况下,规范化模型有助于解决问题。

背景:

在本文中,我们将讨论以下主题:

  1. ML 中欠拟合和过拟合是什么意思?
  2. 如何解决不合身的问题?
  3. 正则化及其背后的数学介绍。
  4. 正规化的类型(L1 和 L2)。
  5. 正规化和交叉验证。

欠配合和过配合的问题:

这里是贯穿本文的 Jupyter 笔记本 的 链接。请并排浏览以彻底理解这篇文章。

考虑线性回归的情况。我们将生成一些数据来处理。然后,数据将被分成训练和测试数据。

生成的数据如下所示:

图一。生成的数据

我们已经将生成的总数据的 20%分割成测试数据。真实拟合函数是我们生成数据所基于的函数。添加噪声是为了模拟真实世界的数据(因为实际上没有数据会完全符合函数)。

了解欠拟合和过拟合涉及在具有不同程度的假设方程的模型上训练数据。让我们从一个具有 1 次的假设方程的模型开始,它将是:

这是回归线的样子:

图二。使用一次方程式。

这是欠拟合的一个例子,因为我们可以看到,这条线对数据的拟合程度不足以让我们使用模型进行未来预测。训练和测试精度和误差值如下:

train accuracy 0.9276025053551601
test accuracy 0.9259414382942455
Training MSE: 0.040338393489346015
Test MSE: 0.04068556089245825

欠拟合问题也称为‘高偏差’问题。这两者都意味着该模型不太适合训练数据。偏差一词指的是模型有一个强烈的先入为主的观念,即 y 随 x 线性变化,尽管事实并非如此。

现在,我们可以尝试用二次函数来拟合数据。假设是这样的:

该模型可以被可视化为:

图三。使用二次方程

我们可以看到,该模型在拟合训练数据方面工作得非常好。训练和测试精度和 MSE 值为:

Train accuracy: 0.9541558552139953
test accuracy 0.9421659027644554
Training MSE: 0.02554341363098832
Test MSE: 0.031772324908036456

与以前的模型相比,精确度有所提高。这意味着更加合适。

由于增加阶数似乎会提高模型的性能,因此让我们尝试使用一个假设方程阶数为 20 的模型。这将是结果:

图 4。使用 20 次方程

哎呀!模型函数似乎被扭曲了。这是因为高度使其更灵活,从而允许其在拟合时将噪声纳入数据中。模型函数试图通过所有点,因此看起来失真。

我们把这个问题叫做【过拟合】,它有【高方差】。术语“高方差”背后的原因是,如果我们要拟合这样一个高阶多项式,那么该假设几乎可以拟合任何函数,即不同类型的可能假设非常大且变化太大,以至于我们没有足够的数据来约束它以得到一个完美的假设。

我们可以通过检查交叉验证分数或 MSE 值来决定过度拟合的问题。我绘制了上述数据的精确度和 MSE 值,这些数据的假设方程的度数从 1 度到 40 度。

图五。精确度和 MSE 值。

我们可以看到,在一定程度(具体来说是 9)之后,测试 MSE 似乎增加了,而训练 MSE 继续减少。当模型由于过度拟合而无法预测看不见的数据时,就会发生这种情况。

使用 9 次方程,我们得到以下模型函数:

图六。用一个 9 次方程。

如果我们有太多的特征,过度拟合也会发生,这是当我们增加函数的次数时间接发生的。已学习的假设可能非常适合训练集(在某种程度上,成本值将为零),但无法预测新的示例。同样的概念也适用于逻辑回归,这里考虑的是决策边界而不是回归线。

解决过度拟合问题:

大多数真实世界的数据集将具有大量的要素。如果我们有很多特征,但只有很少的训练数据,那么就会出现过度拟合。解决过度拟合有两种主要方法:

  1. 减少特征数量:这可以通过手动减少特征数量来实现。我们可以在训练数据之前做一些 EDA 和特征选择,以知道哪些特征要保留,哪些要丢弃。我们还可以使用自动选择特征的模型选择算法。这种方法的缺点是,通过删除某些特征,我们删除了关于问题的信息。
  2. 正则化:该方法保留了所有特征,但降低了假设参数的幅度。当所有参数都对标签的预测有贡献时,这种方法工作良好。

正规化介绍:

考虑一下我们上面看到的数据拟合 10 次函数的情况。假设是这样的:

如果我们惩罚θ_ 10 并使其非常小(几乎等于零),那么假设将被简化为 9 次方程,这将是如上所示的数据的最佳拟合。

这是正则化背后的一般思想。我们不是减少一个参数,而是惩罚所有的参数。这将产生一个更简单的假设,它不容易过度拟合。

线性回归的正则化成本函数;

对于任何不熟悉线性回归背后的数学的人,请参考下面我以前发表的故事。它还会让你对以后要用到的术语和变量有所了解。

[## 一元线性回归-理论与实践

简介:这篇文章解释了一元线性回归的数学和执行。这将包括数学…

towardsdatascience.com](/univariate-linear-regression-theory-and-practice-99329845e85d)

任何回归模型的成本函数由下式给出:

为了将正则化添加到模型中,成本函数被稍微修改为:

在哪里

Lambda 的目的是在限制参数值的同时为训练数据提供良好的拟合,从而保持假设相对简单,以避免过度捕捞。换句话说,我们正在给过度拟合的成本函数(趋于零)添加一个小的偏差,以防止它过度捕捞。通过增加少量的偏差,我们得到了方差的显著下降。

考虑 10 度假设的情况。如果我们把λ的值设得很高,比如说λ=⁰⁰.,会发生什么所有的参数 theta_1 到 theta_10 将被高度减少到假设将是:

该曲线在绘制时将是一条水平直线,因此与我们的数据拟合不佳。因此,为了使正则化工作良好,还应该小心选择λ的值。

线性回归的正则梯度下降;

没有正则化的线性回归的梯度下降由下式给出:

成本函数的偏导数将由于包含正则化而改变,正则化产生如下梯度下降方程:

我已经单独写了θ_ 0,因为它不包括在正则化参数的总和中。这可以简化为:

因为α、λ和 m 是正的:

因此,当应用梯度下降时,每次θ_ j 的值将从θ_ j 的较低值减小,比如 0.99 *θ_ j。这有助于在梯度下降的每次迭代之后收缩θ的值。

正规化的类型:

主要有两种类型的正则化技术:

  1. L1 正则化或套索回归。
  2. L2 正则化或岭回归。

岭回归:

我们上面讨论的所有数学都与岭回归有关。它的成本函数是

下面的图是通过用不同的λ值将 20 次方程拟合到我们上面使用的数据而得到的。

图七。λ= 0 的岭回归

我们可以看到,对于λ= 0,使用 20 次方程的过拟合线性回归没有变化。

图八。λ= 0.5 的岭回归

图九。λ= 1 的岭回归

图 10。λ= 10 的岭回归

图 11。λ= 100 的岭回归

图 12。λ= 1000 的岭回归

我们可以看到,随着λ值的增加,这条线逐渐平行于 x 轴。这是对上述论点的直观证明,其中λ的值很大,从而将假设减少到只有θ_ 0。获取 lambda = 10000 的参数值。

图 13。λ= 10000 的岭回归

Parameters: [ 7.59298747e-05 -1.59864470e-03 -1.48732636e-03 -1.24979159e-03
 -1.04968203e-03 -8.94986923e-04 -7.75465974e-04 -6.81440074e-04
 -6.05849341e-04 -5.43793075e-04 -4.91877768e-04 -4.47723687e-04
 -4.09631866e-04 -3.76365596e-04 -3.47007135e-04 -3.20862795e-04
 -2.97399119e-04 -2.76199260e-04 -2.56932649e-04 -2.39333548e-04
 -2.23185647e-04]

我们可以看到参数趋向于零,并且有不同的值。

岭回归用于训练样本的大小小于的情况,从而通过减少方差来防止模型过度拟合训练数据。

套索回归:

套索回归与岭回归非常相似。在成本函数中有一个微小的修改,它将是:

我们将使用参数的模之和,而不是正则项中参数的平方和。

下面的图是通过用不同的λ值将 20 次方程拟合到我们上面使用的数据而得到的。

图 14。lambda=1 的套索回归

我们可以看到,对于λ= 0.1,模型是一条平行于 x 轴的直线,这与数据拟合得不好。因此,很明显,我们必须进一步降低λ的值。

图 15。lambda=0.1 的套索回归

图 16。lambda=0.01 的套索回归

图 17。lambda=0.001 的套索回归

图 17。lambda=0.0005 的套索回归

随着λ值的增加,模型变成平行于 x 轴的直线。这里,对于较大的λ值,参数等于零。这是岭回归和套索回归的主要区别。

在大λ值的岭回归中,参数趋向于零,而在拉索回归中,参数可以等于零。

λ= 1 的参数为:

Parameters: [-0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563
 -0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563
 -0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563
 -0.00227563 -0.00227563 -0.00227563]

我们可以看到所有的值都相等,并且近似等于零。进一步增加 lambda 的值不会改变参数的值,如下所示。

图 18。λ= 10 的套索回归

Parameters: [-0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563
 -0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563
 -0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563 -0.00227563
 -0.00227563 -0.00227563 -0.00227563]

当参数减少到零时,与这些参数相关联的特征将不会对成本函数有任何影响。通过这样做,我们将执行一种类型的特征选择,其中我们省略了所有对模型没有太大贡献的无用特征。

正则化系数的取值如何选择?

模型表现最佳的正则化系数或λ的值可以通过交叉验证获得。sklearn 的岭回归器中有内置的交叉验证技术。我们可以直接使用它,也可以执行单独的交叉验证过程。

我们将使用与上述 20 次方程相同的数据。我们必须输入一个包含不同 lambda 值的数组来执行交叉验证。

lambdas 的第一个输入是:

[0.0005, 0.001, 0.01, 0.1, 1, 10, 100]

λ的最佳值及其对应的 CV 值为:

Best lambda: 0.0005
CV score: 0.983912496818687

我们可以通过输入 0.0005 左右的值来进一步放大λ值。类似地,交叉验证的方法可以使用 sklearn 的 LassoCV 对象。

正则化方法也可用于防止逻辑回归中的过拟合。我们将使用 sklearn 的岭分类器在逻辑回归中实现 L2 正则化。

结论:

我们在本文中看到了以下内容:

  1. 欠拟合和过拟合如何影响模型。
  2. 解决过拟合的方法。
  3. 正规化的概念。
  4. 正则化代价函数和梯度下降。
  5. L1 正则化或套索回归。
  6. L2 正则化或岭回归。
  7. 使用交叉验证来确定正则化系数。

推论:

  1. 关于机器学习概念背后的数学问题,你可以参考 Youtube 上的这个播放列表。

2.这是 Youtube 上的另一个播放列表,它简单地解释了所有的机器学习基础,没有涉及太多的术语。

请点击这里查看我关于数据科学和机器学习的其他文章。欢迎在评论中和 LinkedIn 上进行更深入的讨论。

正规化—第一部分

原文:https://towardsdatascience.com/regularization-part-1-db408819b20f?source=collection_archive---------43-----------------------

FAU 讲座笔记关于深度学习

偏差-方差权衡

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎回到深度学习!所以今天,我们想谈谈正则化技术,我们先简单介绍一下正则化和过拟合的一般问题。所以,我们先从背景说起。问问题“正规化的问题是什么?”然后,我们谈论经典技术,规范化,辍学,初始化,迁移学习和多任务学习。那么,为什么我们如此频繁地谈论这个话题呢?

将函数拟合到数据可能会导致过度拟合或拟合不足。 CC 下的图片来自深度学习讲座的 4.0 。

嗯,如果你想拟合你的数据,那么像这样的问题很容易拟合,因为它们有明确的解决方案。通常,您会遇到这样的问题:您的数据有噪声,并且您无法轻松地将这些类分开。所以,如果你有一个容量不是很大的模型,你就会遇到不合适的问题。那么你可能会有类似这条线的东西,它不是很适合描述类的分离。反之就是过拟合。这里,我们有容量非常高的模型,它们试图对训练数据中观察到的一切进行建模。这可能会产生不太合理的决策界限。我们真正感兴趣的是一个合理的边界,它是观测数据和实际分布之间的折衷。

偏差-方差权衡与预期模型误差及其方差有关。 CC 下的图片来自深度学习讲座的 4.0 。

因此,我们可以通过所谓的偏差-方差分解来分析这个问题。在这里,我们坚持回归问题,我们有一个理想的函数 h( x )来计算一些值,它通常与一些测量噪声有关。所以,有一些附加值ϵ被加到 h( x )上。它可以正态分布,平均值为零,标准差为σ。现在,你可以继续使用一个模型来估计 h 。这表示为 f hat,它是从一些数据集 d 中估计出来的。我们现在可以将单点的损失表示为损失的期望值。这将只是 L2 的损失。所以,我们取真实函数减去估计函数的 2 次方,计算期望值。有趣的是,这种损失可以分解成两部分:一部分是偏差,本质上是我们的模型的期望值与真实模型的偏差。所以,这基本上衡量了我们离真相有多远。另一部分可以用数据集的有限大小来解释。我们总是可以尝试找到一个非常灵活的模型,并尝试减少偏差。结果我们得到的是方差的增加。因此,方差就是 y hat 的期望值——y hat 的当前值的 2 次方。这就是我们在 y hat 中遇到的变化。然后,当然,有一个小的不可再现的误差。现在,我们可以对 x 中的每个数据点进行积分,从而得到整个数据集的损失。顺便说一下,使用 1–0 损失的分类存在类似的分解,您可以在[9]中看到。略有不同,但有相似的含义。因此,我们了解到,随着方差的增加,我们可以从根本上减少偏差,即我们的模型对训练数据集的预测误差。

由偏差和方差引起的误差的可视化。 CC 下的图片来自深度学习讲座的 4.0 。

让我们把它形象化一点:在左上角,我们看到一个低偏差、低方差的模型。这本质上总是正确的,并且在预测中没有太多的噪音。在右上方,我们看到一个非常一致的高偏差模型,即方差很低,并且始终处于关闭状态。在左下方,我们看到一个低偏差高方差模型。这有相当程度的变化,但平均来说,它非常接近它应该在的地方。在右下角,我们有我们想要省略的情况。这是一个高偏差、高方差的模型,有很多噪音,甚至不在它应该在的地方。因此,我们可以为给定的数据集选择一种模型,但同时优化偏差和方差通常是不可能的。偏差和方差可以作为模型容量一起研究,我们将在下一张幻灯片中看到。

模型容量是对一个函数有多少变化可以近似的度量。 CC 下的图片来自深度学习讲座的 4.0 。

模型的容量描述了它可以近似的各种函数。这和参数的个数有关,所以经常有人说:“那就是参数的个数。增加参数的数量,然后你就可以摆脱你的偏见。”这是真的,但它远远不平等。确切地说,你需要计算 Vapnik-Chervonenkis (VC)维度。这是对容量的精确测量,它基于计算模型可以分离多少个点。因此,与经典方法相比,神经网络的 VC 维数非常高,并且它们具有非常高的模型容量。如果你看一下[18],他们甚至设法记住了随机的标签。这又是那篇研究带有随机标签的学习图像网络的论文。顺便说一下,VC 维在判断神经网络的真实能力方面是无效的。尽管如此,我们总是可以通过增加模型容量来减少偏差。因此,如果您增加模型容量,请记住这一点。你可能会遇到过度拟合的问题。

您拥有的数据越多,就越有可能接近未知的测试集。来自深度学习讲座的 CC BY 4.0 下的图片。

那么我们来看看数据的作用。这里,我们绘制了损失与训练样本数量的关系图,您可以看到,训练损失随着训练样本数量的增加而增加。学习大数据集比学习小数据集更难。如果你有一个非常小的数据集,完全记住它可能非常容易。小数据集的问题在于,它不能很好地代表您真正感兴趣的数据。所以,小数据集模型,当然会有很高的测试损失。现在,通过增加数据集的大小,你也增加了训练损失,但是测试误差下降了。这是我们感兴趣的。我们想建立通用模型,真正对看不见的数据起作用。这是一个非常重要的属性。这也是我们需要如此多数据的原因,也是大公司对获取如此多数据并将其存储在服务器上感兴趣的原因。从技术上讲,我们可以通过使用更多的训练数据来优化方差。因此,我们可以创建更高容量的模型,但我们也需要更多的训练数据,但从长远来看,这可能会给我们带来非常低的测试误差。此外,模型容量必须与训练数据集的大小相匹配。如果你有一个太高的容量,它只会产生一个非常糟糕的过度拟合,你的模型在看不见的数据上不会很好。现在的问题是,当然,如果我们不能得到更多的数据呢?

有限的数据集是过度拟合的常见原因。 CC 下的图片来自深度学习讲座的 4.0 。

假设你在一个数据有限的领域。那么,当然,你有麻烦了。让我们用固定的数据集大小来研究这些影响。所以,在一个有限的数据集上,你做出如下观察:如果你增加模型容量,你的训练损失会下降。当然,有了更高的容量,你可以记忆更多的训练数据集。这是通过记忆所有东西来解决学习问题的蛮力方式。问题是你在某些时候产生了一个糟糕的过度配合。开始时,增加模型容量也会减少测试损失。在某些时候,当你进入过度拟合,测试损失将增加,如果测试损失增加,你基本上是在你过度拟合的点。在这堂课的后面,我们将研究使用从训练数据集中提取的验证数据集的想法,以产生测试损失的替代数据。所以,我们会在几节课中讨论这个问题。我们可以看到,我们可以用偏差的增加来换取方差的减少。

所有正则化技术都旨在减少过拟合问题。 CC 下的图片来自深度学习讲座的 4.0 。

对于一个特定的问题,可能会有有利的权衡。一般现在正则化的思路是减少过拟合。这个想法从何而来?我们本质上是在强化先验知识。一种方法是数据扩充。你可以调整架构,因为你对问题有所了解,你可以调整训练过程,你可以做预处理,等等。为了结合先前的知识,可以采取许多额外的步骤。也可以使用实际的正则化,然后将正则化扩充到损失函数中,并且它们通常将解约束到等式约束或不等式约束。因此,我们还将简要了解一下这些解决方案。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。来自深度学习讲座的 CC BY 4.0 下的图片。

这已经把我们带到了这节课的结尾。下一次,我们将研究神经网络和机器学习中使用的经典正则化方法。我期待着在下一次会议中再次见到你!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

链接

链接 —关于最大后验概率估计和偏差-方差分解的详细信息
链接 —关于正则化实用建议的综合文本
链接 —关于校准方差的论文

参考

[1]谢尔盖·约菲和克里斯蒂安·塞格迪。“批量标准化:通过减少内部协变量转移加速深度网络训练”。《第 32 届机器学习国际会议论文集》。2015 年,第 448–456 页。乔纳森·巴克斯特。“通过多任务抽样学习的贝叶斯/信息论模型”。摘自:机器学习 28.1(1997 年 7 月),第 7-39 页。
【3】克里斯托弗·m·毕晓普。模式识别和机器学习(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
[4]理查德·卡鲁阿纳。多任务学习:归纳偏差的知识来源。收录于:第十届机器学习国际会议论文集。摩根·考夫曼,1993 年,第 41-48 页。
【5】Andre Esteva,Brett Kuprel,Roberto A Novoa,等《深度神经网络的皮肤癌皮肤科医生级分类》。载于:自然 542.7639 (2017),第 115–118 页。
[6]丁俊钦、徐俊卿、陶行知。“多任务姿态不变人脸识别”。载于:IEEE 图像处理汇刊 24.3(2015 年 3 月),第 980–993 页。
[7]李万,马修·泽勒,张思欣,等,“用下降连接实现神经网络的正则化”。载于:《第 30 届机器学习国际会议论文集》(ICML,2013 年),第 1058-1066 页。
[8] Nitish Srivastava,Geoffrey E Hinton,Alex Krizhevsky,等人,“辍学:防止神经网络过度拟合的简单方法。”载于:《机器学习研究杂志》15.1 (2014),第 1929–1958 页。
[9]r . o .杜达、P. E .哈特和 D. G .施托克。模式分类。约翰威利父子公司,2000 年。
[10]伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔。深度学习。http://www.deeplearningbook.org。麻省理工学院出版社,2016 年。
【11】与何。“群体常态化”。载于:arXiv 预印本 arXiv:1803.08494 (2018)。
【12】何,,任等,“深入挖掘整流器:在 imagenet 分类上超越人类水平的表现”。IEEE 计算机视觉国际会议论文集。2015 年,第 1026–1034 页。
【13】D 乌里扬诺夫,A 韦达尔迪,以及 VS 伦皮茨基。实例规范化:快速风格化缺少的要素。CoRR ABS/1607.0[14]günter Klambauer,Thomas Unterthiner,Andreas Mayr 等,“自规范化神经网络”。在:神经信息处理系统的进展。abs/1706.02515 卷。2017.arXiv: 1706.02515。吉米·巴雷、杰米·瑞安·基罗斯和杰弗里·E·辛顿。“图层规范化”。载于:arXiv 预印本 arXiv:1607.06450 (2016)。
【16】Nima Tajbakhsh,Jae Y Shin,Suryakanth R Gurudu,等,“用于医学图像分析的卷积神经网络:完全训练还是微调?”载于:IEEE 医学成像汇刊 35.5 (2016),第 1299–1312 页。
【17】约书亚·本吉奥。“深度架构基于梯度训练的实用建议”。《神经网络:交易的诀窍》。斯普林格出版社,2012 年,第 437-478 页。
[18]张,Samy Bengio,Moritz Hardt 等,“理解深度学习需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。
[19]什巴尼·桑图尔卡,迪米特里斯·齐普拉斯,安德鲁·易勒雅斯等,“批处理规范化如何帮助优化?”在:arXiv e-prints,arXiv:1805.11604(2018 年 5 月),arXiv:1805.11604。arXiv:1805.11604[统计。ML】。
[20]蒂姆·萨利曼斯和迪德里克·P·金马。“权重标准化:加速深度神经网络训练的简单重新参数化”。神经信息处理系统进展 29。柯伦咨询公司,2016 年,第 901–909 页。
【21】泽维尔·格洛特和约舒阿·本吉奥。“理解训练深度前馈神经网络的困难”。载于:2010 年第十三届国际人工智能会议论文集,第 249-256 页。
【22】,罗平,陈改来,等,“基于深度多任务学习的人脸标志点检测”。载于:计算机视觉— ECCV 2014 年:第 13 届欧洲会议,瑞士苏黎世,Cham: Springer 国际出版公司,2014 年,第 94–108 页。

正规化—第二部分

原文:https://towardsdatascience.com/regularization-part-2-5b729698d026?source=collection_archive---------42-----------------------

FAU 讲座笔记关于深度学习

古典技术

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎回到深度学习!我们想继续分析正则化方法,今天我想谈谈经典技术。

您将无法在训练数据上观察到过度拟合。 CC 下的图片来自深度学习讲座的 4.0 。

这是一个典型的训练集迭代损失曲线的例子。我在右边展示的是测试集上的损耗曲线。你可以看到,虽然培训损失下降了,但测试损失却上升了。因此,在某种程度上,训练数据集是过度拟合的,它不再产生代表数据的模型。顺便说一句,永远记住,测试集决不能用于训练。如果你在你的测试集上接受训练,那么你会得到非常好的结果,但是很有可能完全高估了性能。典型的情况是,有人跑进我的办公室说:“是的!我有 99%的识别率!”。当模式识别或机器学习领域的人读到“99%的识别率”时,他做的第一件事是问:“你用你的测试数据训练过吗?”这是你首先要确保的事情。当你犯了一些愚蠢的错误,有一些数据集指针没有指向正确的数据集,你的识别率突然上升。所以,如果你有非常好的结果,一定要小心。始终仔细检查它们是否真的合适,它们是否真的通用。因此,如果你想产生像我在这里展示的曲线,你可能想使用一个验证集,你从训练数据集。你从来没有在训练中使用过这个集合,但是你可以用它来估计你的模型过度拟合。

当验证损失再次上升时,验证集有助于发现过度拟合。来自深度学习讲座的 CC BY 4.0 下的图片。

所以,如果你这样做了,我们就可以使用第一个技巧了。您使用验证集。我们观察在什么点上我们在验证集中有最小的误差。如果我们在这一点上,我们可以使用它作为一个停止标准,并使用我们的测试评估模型。因此,使用具有最小验证结果的参数是一种常见的技术。

数据扩充实际上可以增加训练集的大小。来自深度学习讲座的 4.0CC 下的图片。

另一个非常有用的技术是数据扩充。所以,这里的想法是人为地扩大数据集。标签上有一些变换,这些变换对于类应该是不变的。假设你有一只猫的图像,你把它旋转 90 度,它仍然显示一只猫。显然,这些增强技术必须小心谨慎。因此,在右边的例子中,您可以看到旋转 180 度可能不是增加数字的好方法,因为它可能会转换标签。

数据扩充的常见转换。 CC 下的图片来自深度学习讲座的 4.0 。

这里有非常常见的变换:随机空间变换,如仿射或弹性变换。然后,还有像素变换,如改变分辨率、改变噪声或改变像素分布,如颜色亮度等。这些是图像处理中典型的增强技术。

利用贝叶斯定理,我们可以得到所谓的最大后验估计。来自深度学习讲座的 CC BY 4.0 下的图片。

还有什么?我们可以正则化损失函数。这里,我们可以看到,这基本上导致了最大后验概率(MAP)估计。我们可以用贝叶斯方法来做到这一点,我们希望考虑不确定的权重。它们遵循先验分布 p( w )。如果你有一些带有一些关联标签 Y 的数据集 X ,我们可以看到联合概率 p( wYX )是概率 p( w | Y,X )乘以概率 p( Y,X )。我们可以将其重新表述为概率 P( Y | Xw )乘以概率 p( Xw )。从这些等式可以推导出条件概率 p( w | YX )可以表示为概率 p( Y | X,w )乘以概率 P( X,w )除以概率 p( Y,X )的贝叶斯定理。因此,我们可以进一步重新排列,这里你可以看到概率 p( X )概率 p( Y | X )弹出。通过移除与 w 无关的项,这产生了 MAP 估计。所以,我们实际上可以通过最大化条件概率 p( Y | Xw )乘以概率 p( w )来寻求最大化联合概率。因此,通常情况下,我们将这个问题作为最大似然估计量来解决,即左边的问题乘以右边部分 w 的先验。我们可以说这是一个最大似然估计量,但我们用一些额外的先验信息来扩充它。这里,先验信息是我们对 w 的分布有一些了解,例如 w 可能是稀疏的。我们也可以使用其他的知识来源,在那里我们知道一些关于 w 的事情。在图像处理中,经常使用的是例如自然图像相对于梯度是稀疏的,因此这种先验可以使用各种稀疏度。

MAP 估计在损失函数中产生正则化项。 CC 下的图片来自深度学习讲座的 4.0 。

现在有趣的部分是,这个 MAP 估计器可以被重构,如果你参加过模式识别,你就知道我在说什么。我们已经看到,最大似然估计的最大化导致负对数似然的最小化。我们讨论的典型损失函数具有这种形式。现在,如果你从地图估计开始,你基本上以一个非常相似的估计结束,但是损失函数的形状稍微改变了。所以,我们得到了一个新的损失函数。这就像 L2 损失或交叉熵损失加上一些λ和一些对权重的约束 w 。所以在这里,我们实施了一个最小 l2 规范。现在,对于正λ,我们可以将其识别为最小化损失函数的拉格朗日函数,其受限于小于α的约束 L2 范数 w ,其中α依赖于某些未知数据。所以这是完全相同的公式。我们现在可以把这一点引入到增加损失的反向传播中去。这通常是如何实现的?你跟踪梯度的损失。这是损失的右边部分,我们已经用学习率η计算过了,另外,你把这种收缩应用到 w 上。因此,这里的收缩步骤可以用于实现额外的 L2 正则化。好消息是现在我们可以像以前一样简单地计算反向传播。然后,另外,我们在权重更新中使用收缩。因此,我们也可以获得非常简单的权重更新,它们允许我们涉及那些正则化。如果我们选择不同的正则项,收缩函数会发生变化。如果我们现在为λ优化训练损失,我们通常会得到λ = 0,因为每次我们引入正则化,我们都在做一些关于训练损失不是最优的事情。当然,我们引入它是因为我们想减少过度拟合。因此,这是我们无法在训练数据中直接观察到的东西,但我们希望在一个看不见的测试集上获得更好的属性。这甚至会增加我们训练数据的损失值。所以要小心。同样,我们增加偏差以减少方差。

L2 规范强制实施具有较低权重量值的解决方案。 CC 下的图片来自深度学习讲座的 4.0 。

这里,我们有一个可视化的 L2 正则化的效果。不规则损耗当然会导致椭圆的中心变成红色。但是现在你做了额外的调整,使你的 w 变小。这意味着你离原点越远,你的 L2 损耗就越高。因此,l2 损失会使您偏离关于训练数据集的数据最佳损失。希望它描述了一些我们在训练数据集中没有看到的先验知识。因此,它将产生一个更适合未知测试数据集的模型。

使用 L1 项会导致不同形式的重量收缩。来自深度学习讲座的 4.0CC 下的图片。

我们也可以使用其他规范,例如,L1 规范。因此,在这里,我们再次以拉格朗日公式结束,其中我们有服从 L1 范数的原始损失函数,该损失函数小于某个值α,且α未知,取决于数据。这里,我们简单地得到一个不同的收缩操作,它现在涉及到符号函数的使用。所以这又是次梯度的一个暗示。这里,为了使这种优化可行,必须采用不同的收缩方式。同样,我们对损失函数使用了与之前完全相同的梯度。所以只有收缩被取代。

来自深度学习讲座的 4.0 在 CC 下的二维图像中 L1 范数为菱形。

现在,我们也可以在我们的小图中看到这一点。L1 标准的形式当然是不同的。用 L2,我们有这个圆,用 L1 范数,我们得到一个菱形。现在,你可以看到选择的最小值可能位于坐标轴上。因此,如果你试图找到这个 L1 范数和非正则化损耗的最小位置,你会看到与这个 L1 损耗相交的最小非正则化损耗点基本上在这个图中的 y 轴上。这是一个非常稀疏的解决方案,意味着在我们的权重向量中只有 y 的条目,在这种情况下,x 的条目非常接近 0 或等于 0。因此,如果您希望权重稀疏,或者如果您希望创建连接较少的网络,您可能希望对权重引入额外的 L1 正则化。这样会造成权重稀疏。

来自深度学习讲座的 4.0CC 下 w. Image 中的一个最大范数极限高值。

还有什么?还有更多已知的约束,例如我们可以对权重的范数设置限制。在这里,我们只是强制它们低于某个最大值。我们希望 w 的大小低于α,其中α是一个正常数。如果你这样做,我们基本上必须在每次参数更新时投影到单位球上,这又是一种收缩,基本上禁止爆炸梯度。小心,它也可能只是隐藏它们,这样你就再也看不到它们了。

规则化损失还有许多其他变体。来自深度学习讲座的 4.0CC 下的图片。

还有许多改变损失的其他方法。每个层都可以有一个约束和一个单独的λ。所以你可以不同地约束每一层,但是我们还没有在文献中看到任何增益。代替权重,激活也可以被约束。这导致不同的变体,例如在稀疏自动编码器中。我们将讨论他们是如何不正则化权重,而是通过激活来形成特定的分布,从而产生稀疏的激活。这也是一个非常有趣的问题,当我们谈到自动编码器和无监督学习时,我们会对此进行更多的讨论。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。

所以下次在深度学习中,我们想继续讲正则化方法。我们将研究特别为深度学习设计的非常典型的工具。非常有趣的方法,和你们在这节课上看到的略有不同。非常感谢您的收看,再见!

如果你喜欢这篇文章,你可以在这里找到更多的文章,在这里找到更多关于机器学习的教育材料,或者看看我们的深度 学习 讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 或 T21 上的掌声或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

链接

链接 —关于最大后验概率估计和偏差-方差分解的详细信息
链接 —关于正则化实用建议的综合文本
链接 —关于校准方差的论文

参考

[1]谢尔盖·约菲和克里斯蒂安·塞格迪。“批量标准化:通过减少内部协变量转移加速深度网络训练”。载于:第 32 届机器学习国际会议论文集。2015 年,第 448–456 页。乔纳森·巴克斯特。“通过多任务抽样学习的贝叶斯/信息论模型”。摘自:机器学习 28.1(1997 年 7 月),第 7-39 页。
【3】克里斯托弗·m·毕晓普。模式识别和机器学习(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
[4]理查德·卡鲁阿纳。多任务学习:归纳偏差的知识来源。收录于:第十届机器学习国际会议论文集。摩根·考夫曼,1993 年,第 41-48 页。
【5】Andre Esteva,Brett Kuprel,Roberto A Novoa,等《深度神经网络的皮肤癌皮肤科医生级分类》。载于:自然 542.7639 (2017),第 115–118 页。
[6]丁俊钦、徐俊卿、陶行知。“多任务姿态不变人脸识别”。载于:IEEE 图像处理汇刊 24.3(2015 年 3 月),第 980–993 页。
[7]李万,马修·泽勒,张思欣,等,“用下降连接实现神经网络的正则化”。载于:《第 30 届机器学习国际会议论文集》(ICML,2013 年),第 1058-1066 页。
[8] Nitish Srivastava,Geoffrey E Hinton,Alex Krizhevsky,等人,“辍学:防止神经网络过度拟合的简单方法。”载于:《机器学习研究杂志》15.1 (2014),第 1929–1958 页。
[9]r . o .杜达、P. E .哈特和 D. G .施托克。模式分类。约翰威利父子公司,2000 年。
[10]伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔。深度学习。http://www.deeplearningbook.org。麻省理工学院出版社,2016 年。
【11】与何。“群体常态化”。载于:arXiv 预印本 arXiv:1803.08494 (2018)。
【12】何,,任等,“深入挖掘整流器:在 imagenet 分类上超越人类水平的表现”。IEEE 计算机视觉国际会议论文集。2015 年,第 1026–1034 页。
【13】D 乌里扬诺夫,A 韦达尔迪,以及 VS 伦皮茨基。实例规范化:快速风格化缺少的要素。CoRR ABS/1607.0[14]günter Klambauer,Thomas Unterthiner,Andreas Mayr 等,“自规范化神经网络”。在:神经信息处理系统的进展。abs/1706.02515 卷。2017.arXiv: 1706.02515。吉米·巴雷、杰米·瑞安·基罗斯和杰弗里·E·辛顿。“图层规范化”。载于:arXiv 预印本 arXiv:1607.06450 (2016)。
【16】Nima Tajbakhsh,Jae Y Shin,Suryakanth R Gurudu,等,“用于医学图像分析的卷积神经网络:完全训练还是微调?”载于:IEEE 医学成像汇刊 35.5 (2016),第 1299–1312 页。
【17】约书亚·本吉奥。“深度架构基于梯度训练的实用建议”。《神经网络:交易的诀窍》。斯普林格出版社,2012 年,第 437-478 页。
[18]张,Samy Bengio,Moritz Hardt 等,“理解深度学习需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。
[19]什巴尼·桑图尔卡,迪米特里斯·齐普拉斯,安德鲁·易勒雅斯等,“批处理规范化如何帮助优化?”在:arXiv e-prints,arXiv:1805.11604(2018 年 5 月),arXiv:1805.11604。arXiv:1805.11604[统计。ML】。
[20]蒂姆·萨利曼斯和迪德里克·P·金马。“权重标准化:加速深度神经网络训练的简单重新参数化”。神经信息处理系统进展 29。柯伦咨询公司,2016 年,第 901–909 页。
【21】泽维尔·格洛特和约舒阿·本吉奥。“理解训练深度前馈神经网络的困难”。摘自:2010 年第十三届国际人工智能会议论文集,第 249-256 页。
【22】,罗平,陈改来,等,“基于深度多任务学习的人脸标志点检测”。载于:计算机视觉— ECCV 2014 年:第 13 届欧洲会议,瑞士苏黎世,Cham: Springer 国际出版公司,2014 年,第 94–108 页。

正规化——第 3 部分

原文:https://towardsdatascience.com/regularization-part-4-2ee8e7aa60ec?source=collection_archive---------26-----------------------

FAU 讲座笔记关于深度学习

正常化和辍学

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎来到我们的深度学习讲座。今天我们想谈谈更多的正规化。我想介绍的第一个话题是标准化的概念。那么为什么正常化会是一个问题呢?

数据的规范化有助于将原始数据带到一个统一的空间。 CC 下的图片来自深度学习讲座的 4.0 。

这里我们来看一些原始数据。一种典型的方法是减去平均值,然后也可以归一化方差。这非常有用,因为这样我们就在输入的预期范围内。当然,如果你做这些标准化,然后你想估计他们只对训练数据。另一种方法不仅是在网络前进行归一化,还可以在网络内进行归一化。这就引出了批处理规范化的概念。

批量标准化能够作为可训练层自动执行标准化。 CC 下的图片来自深度学习讲座的 4.0 。

想法是引入一个新的层,参数为γ和β。γ和β用于重新调整图层的输出。在层的输入端,开始测量批次的平均值和标准差。你要做的是计算小批量的当前均值和标准差,然后用它来归一化输入的激活。因此,你有一个零均值和单位标准差。因此,这是在整个训练过程中动态计算的,然后使用可训练权重β和γ对层的输出进行缩放。您可以根据下一层的需要适当地缩放它们。因此,这个不错的功能当然只能在培训期间实现。如果您想继续进行测试,那么在完成训练后,您可以在批处理标准化层中为整个训练集计算一次平均值和标准差,并在网络的所有未来应用中保持不变。当然, μσ 是向量,它们与激活向量的维数完全相同。通常,这与卷积层成对出现。在这种情况下,通过对每个通道使用标量μ和σ,批次归一化略有不同。所以如果在卷积中使用,会有一点点不同。

批处理规范化为什么有帮助? CC 下的图片来自深度学习讲座的 4.0 。

你可能会争论为什么批处理规范化真的有帮助?有压倒性的实际证据表明,它确实是一个有用的工具,这最初是由内部协变量的变化所推动的。因此,确定了 ReLU 不在零中心的问题。因此,初始化和输入分布可能无法正常化。因此,输入分布会随时间而变化。在更深的网中,你甚至会得到放大的效果。因此,各层必须不断适应,这导致学习缓慢。现在,如果你仔细观察这些观察,很少有具体的证据来支持这个理论。

可以看出,批量标准化能够平滑损失情况。 CC 下的图片来自深度学习讲座的 4.0 。

在 NeurIPS 2018 上,有一篇论文展示了批处理规范化如何帮助优化。他们表明,即使在批处理规范化层之后再次引入内部协变量移位,批处理规范化也是有效的。所以在这种情况下,批量规范化还是有帮助的。他们可以通过实验证明,这种方法平滑了损失景观。这支持优化,也有助于降低损失函数的 Lipschitzness。Lipschitz 常数是函数中出现的最高斜率。如果你改善了 Lipchitzness,这基本上意味着不再出现高斜率。因此,这符合平滑损失的原则。他们甚至可以在论文中为这个性质提供证明。因此,批处理规范化提高了超参数、初始化、收敛和类似属性的稳定性。顺便说一下,这也可以在 Lp 规范化中观察到。

批处理规范化有许多变体。来自深度学习讲座的 CC BY 4.0 下的图片。

所以这是一种方法。批量标准化有一些概括:您可以计算批量激活、层、空间维度、组、层权重的μ和σ,我们可能会遗漏一些变化。所以它是一个非常强大的工具。

自规范化神经网络是批处理规范化的替代方法。 CC 下的图片来自深度学习讲座的 4.0 。

另一个非常有效的工具是自归一化神经网络。它还解决了随机梯度下降的稳定性问题,这里的关键元素是我们已经在激活函数中讨论过的缩放指数线性单元。所以,这里我们又有了定义。通过λ和α的特定设置,我们可以确保零均值和单位标准差输入在数据输出时具有相同的均值和标准差。所以这保证了保持这些性质。那么结果是稳定的激活也导致稳定的训练。必须改变的一件事是我们将在下一段看到的退学程序。这里不是降到零,而是降到负λ乘以α。此外,他们使用仿射变换来恢复方差和均值。因此,这种自规范化神经网络概念在某种程度上也类似于批量规范化。有趣的是,它还会增加稳定性,这也是你在构建神经网络时可能需要考虑的一个好方法。

辍学及其推广下降连接。来自深度学习讲座的 CC BY 4.0 下的图片。

现在我们已经谈到了辍学。这也是一项非常重要的技术,正在深度网络中使用。你可能要考虑的一件事是,训练中的所有因素,当然,它们是相互依赖的。因此,如果您有相关的输入,那么自适应也将以类似的方式运行。但是,如果你想要有独立的特征,让你能够识别不同的东西,那么你必须打破特征之间的相关性,这实际上可以通过辍学来实现。它的基本思想是,你随机杀死一些神经元,并把它们设置为零。因此,您选择一个概率 p,并将随机激活设置为零,概率为 1 — p。然后,在测试期间,您必须将所有激活乘以 p,否则,下一层的激活会过高。所以你必须在测试时补偿这种下降效应。在这个例子中,假设 y₁和 y₂是相关的,所以它们携带相同的信息和权重。现在,如果我使用它们并试图训练它们,它们将永远学不到别的东西,因为它们总是产生相同的输出。因此,在反向传播中,它们将获得相同的更新项。因此,它们将始终保持关联。现在如果你引入这个退出程序,你会随机杀死一些神经元。这意味着在训练过程中,重量被拉向不同的方向。因此,它们将不再相关。因此,你可以使用 dropout 来打破这些内部相关性,这已经证明可以减少过度拟合的问题。这确实是一个非常重要的概念,在深度学习中经常使用。还有一个有趣的概括是 dropconnect。这里,你没有杀死单个神经元的所有激活,但是你杀死了单个的连接。因此,您可以随机确定设置为零的连接。这可以被视为辍学的一种概括,因为你有更多不同的方式来调整它。通常,这种实现效率不高,因为您必须像屏蔽一样实现它。更简单的方法是将其中一个激活设置为零。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。

好了,我们已经讨论了这些常见的概念和规范化,但这并不是所有的技巧。我们袖子里还有几张牌。所以这些技巧我会在下节课展示给你们。非常感谢您的收听,再见!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

链接

链接 —关于最大后验概率估计和偏差-方差分解的详细信息
链接 —关于正则化实用建议的综合文本
链接 —关于校准方差的论文

参考

[1]谢尔盖·约菲和克里斯蒂安·塞格迪。“批量标准化:通过减少内部协变量转移加速深度网络训练”。《第 32 届机器学习国际会议论文集》。2015 年,第 448–456 页。乔纳森·巴克斯特。“通过多任务抽样学习的贝叶斯/信息论模型”。摘自:机器学习 28.1(1997 年 7 月),第 7-39 页。
【3】克里斯托弗·m·毕晓普。模式识别和机器学习(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
[4]理查德·卡鲁阿纳。多任务学习:归纳偏差的知识来源。收录于:第十届机器学习国际会议论文集。摩根·考夫曼,1993 年,第 41-48 页。
【5】Andre Esteva,Brett Kuprel,Roberto A Novoa,等《深度神经网络的皮肤癌皮肤科医生级分类》。载于:自然 542.7639 (2017),第 115–118 页。
[6]丁俊钦、徐俊卿、陶行知。“多任务姿态不变人脸识别”。载于:IEEE 图像处理汇刊 24.3(2015 年 3 月),第 980–993 页。
[7]李万,马修·泽勒,张思欣,等,“用下降连接实现神经网络的正则化”。载于:《第 30 届机器学习国际会议论文集》(ICML,2013 年),第 1058-1066 页。
[8] Nitish Srivastava,Geoffrey E Hinton,Alex Krizhevsky,等人,“辍学:防止神经网络过度拟合的简单方法。”载于:《机器学习研究杂志》15.1 (2014),第 1929–1958 页。
[9]r . o .杜达、P. E .哈特和 D. G .施托克。模式分类。约翰威利父子公司,2000 年。
[10]伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔。深度学习。http://www.deeplearningbook.org。麻省理工学院出版社,2016 年。
【11】与何。“群体常态化”。载于:arXiv 预印本 arXiv:1803.08494 (2018)。
【12】何,,任等,“深入挖掘整流器:在 imagenet 分类上超越人类水平的表现”。IEEE 计算机视觉国际会议论文集。2015 年,第 1026–1034 页。
【13】D 乌里扬诺夫,A 韦达尔迪,以及 VS 伦皮茨基。实例规范化:快速风格化缺少的要素。CoRR ABS/1607.0[14]günter Klambauer,Thomas Unterthiner,Andreas Mayr 等,“自规范化神经网络”。在:神经信息处理系统的进展。abs/1706.02515 卷。2017.arXiv: 1706.02515。吉米·巴雷、杰米·瑞安·基罗斯和杰弗里·E·辛顿。“图层规范化”。载于:arXiv 预印本 arXiv:1607.06450 (2016)。
【16】Nima Tajbakhsh,Jae Y Shin,Suryakanth R Gurudu,等,“用于医学图像分析的卷积神经网络:完全训练还是微调?”载于:IEEE 医学成像汇刊 35.5 (2016),第 1299–1312 页。
【17】约书亚·本吉奥。“深度架构基于梯度训练的实用建议”。《神经网络:交易的诀窍》。斯普林格出版社,2012 年,第 437-478 页。
[18]张,Samy Bengio,Moritz Hardt 等,“理解深度学习需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。
[19]什巴尼·桑图尔卡,迪米特里斯·齐普拉斯,安德鲁·易勒雅斯等,“批处理规范化如何帮助优化?”在:arXiv e-prints,arXiv:1805.11604(2018 年 5 月),arXiv:1805.11604。arXiv:1805.11604[统计。ML】。
[20]蒂姆·萨利曼斯和迪德里克·P·金马。“权重标准化:加速深度神经网络训练的简单重新参数化”。神经信息处理系统进展 29。柯伦咨询公司,2016 年,第 901–909 页。
【21】泽维尔·格洛特和约舒阿·本吉奥。“理解训练深度前馈神经网络的困难”。摘自:2010 年第十三届国际人工智能会议论文集,第 249-256 页。
【22】,罗平,陈改来,等,“基于深度多任务学习的人脸标志点检测”。载于:计算机视觉— ECCV 2014 年:第 13 届欧洲会议,瑞士苏黎世,Cham: Springer 国际出版公司,2014 年,第 94–108 页。

正规化——第 4 部分

原文:https://towardsdatascience.com/regularization-part-4-3518ec44ed85?source=collection_archive---------62-----------------------

FAU 讲座笔记关于深度学习

初始化和迁移学习

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

在凸问题中,初始化不起作用。 CC 下的图片来自深度学习讲座的 4.0 。

欢迎回到深度学习!所以今天,我们想看看一些初始化技术,它们将在你使用深度学习网络的整个工作中非常方便。所以,你可能会想,如果你有一个凸函数,为什么初始化很重要,实际上,这一点都不重要,因为你沿着负梯度方向,你总是会找到全局最小值。所以,凸优化没有问题。

在非凸问题中,初始化可以起到很大的作用。 CC 下的图片来自深度学习讲座的 4.0 。

然而,我们正在处理的许多问题是非凸的。非凸函数可能有不同的局部最小值。如果我从这一点开始,你可以看到我通过优化得到了一个局部最小值。但是如果我从这里开始,你可以看到,我会得到一个非常不同的局部最小值。所以对于非凸问题,初始化其实是一件大事。具有非线性的神经网络通常是非凸的。

初始化的简单思路。来自深度学习讲座的 CC BY 4.0 下的图片。

那么,有什么办法呢?当然,你必须做一些初始化工作。对于偏差,您可以很容易地开始并将它们初始化为 0。这是非常典型的。请记住,如果您正在处理一个 ReLU,您可能希望从一个小的正常数开始,这样会更好,因为会出现 ReLU 问题。对于权重,你需要随机打破对称。我们已经有这个问题了。在辍学,我们看到我们需要额外的正规化,以打破对称性。同样,用零初始化它们也是非常糟糕的,因为这样梯度也是零。所以,这是你不想做的事情。类似于学习率,它们的方差影响学习过程的稳定性。小的均匀高斯值有效。

如何校准差异? CC 下的图片来自深度学习讲座的 4.0 。

现在,你可能想知道我们如何校准这些差异。让我们假设我们有一个单线性神经元,其权重为 W ,输入为 X 。记住这里的大写字母把它们标为随机变量。然后,你可以看到输出是 W 乘以 X 。这是各个输入加上一些偏置的线性组合。现在,我们对 Y 的方差感兴趣。如果我们假设 WX 是独立的,那么每个产品的方差实际上可以被计算为 X 的期望值是 W 方差的 2 次幂加上 W 的期望值是 X 方差的 2 次幂,然后你将两个随机变量的方差相加。现在,如果我们要求 WX 的平均值为 0,那么这将简化整个问题。平均值是 0,所以期望值抵消了,我们的方差就是两个方差的乘积。现在,我们假设 X 下标 n 和 W 下标 n 是独立同分布的。在这种特殊情况下,我们可以看到,这里的 N 代表了我们的方差。因此,它实际上取决于您对图层的输入数量。这是方差与 W 下标 n 的比例,所以,你看到权重非常重要。实际上,你拥有的权重越多,方差就越大。

Xavier 初始化会考虑重量的变化。 CC 下的图片来自深度学习讲座的 4.0 。

因此,我们可以使用 Xavier 初始化。因此,我们校准向前传递的方差。我们使用零均值高斯函数进行初始化,只需将 fan_in 上的标准差设置为 1,其中 fan_in 是权重的输入维度。因此,我们简单地将输入维数的方差缩放为 1。然而,在向后传递中,我们需要同样的向后效果。因此,我们必须用 1 除以 fan_out 来调整标准差,其中 fan_out 是权重的输出维度。所以,你只要把这两个平均,然后计算一个新的标准差。这个初始化是在[21]的第一个作者之后调用的。好吧,还能做什么?

有了 ReLUs,初始化就有优势了。 CC 下的图片来自深度学习讲座的 4.0 。

还有初始化,然后也考虑到线性神经元的假设是一个问题。所以在[12]中,他们表明对于 ReLUs,实际上最好用 2 的平方根除以 fan_in 作为标准差。因此,这是一个非常典型的随机初始化权重的选择。

初始化时的其他常规选择。来自深度学习讲座的 CC BY 4.0 下的图片。

然后,其他常规的初始选择是进行 L2 正则化,对完全连接的层使用概率为 0.5 的下降,并在卷积神经网络中选择性地使用它们。你的意思是减法,批量标准化,和初始化。这是非常典型的设置。

迁移学习试图重用以前培训设置中的知识。 CC 下的图片来自深度学习讲座的 4.0 。

那么我们还剩下哪些技巧呢?一个重要的技巧是迁移学习。现在,迁移学习通常用在所有数据很少的情况下。一个例子是医疗数据。在那里,你通常只有很少的数据。因此,这个想法是重用模型,例如,在 ImageNet 上训练的模型。您甚至可以针对相同的数据重用在不同的任务中训练过的东西。您也可以在同一任务中使用不同的数据,甚至可以在不同的任务中使用不同的数据。

权重迁移是迁移学习的常见选择。来自深度学习讲座的 4.0CC 下的图片。

所以现在的问题是我们应该转移什么?好吧,卷积层提取特征,现在的期望是较少的特定于任务的特征在较早的层中。我们在几篇论文中看到过。我们还可以在中看到我们的可视化视频。所以通常情况下,那些有更多的基本信息,并可能包含值得传输的信息。我们在特征提取部分对网络进行一定深度的切割。对于那些提取出来的部分,我们可以把学习率固定为零。所以,如果我们把它设置为零,它们不会改变。到时候就可以开始微调了。

迁移学习的一个例子见[5]。来自深度学习讲座的 CC BY 4.0 下的图片。

这里的一个例子是皮肤癌分类。他们使用基于 Inception V3 的深度卷积神经网络。他们有一个在 ImageNet 上预先训练过的最先进的架构。然后,他们根据皮肤癌数据对其进行微调。因此,它们本质上是网络,而你要替换的本质上是右边的部分。这些课程的培训是你在 ImageNet 上找不到的。所以,你必须替换整个网络,因为你想预测非常不同的类。然后,您可以使用两个完全连接的图层将您学习到的要素制图表达映射到不同的空间。然后,你可以从那里做一个分类。

许多其他转移也是可能的。来自深度学习讲座的 4.0CC 下的图片。

还有模态之间的转换。这也被发现是有益的。现在,您可以从彩色转换到 x 射线,这里只需简单地复制输入三次就足够了。那么,你就不需要那么多微调了。所以,这个效果很好。一种替代方法是使用其他网络的要素制图表达作为损失函数。这就导致了知觉的丧失。我们将在另一个视频中讨论感知损失。在任何情况下,迁移学习通常是一个非常好的主意。有许多应用和论文都使用了迁移学习。很久以前他们不说迁移学习而是说适应。特别是在语音处理方面,他们有说话人和噪声适应等等。但是现在你说迁移学习。本质上是同一个概念。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。来自深度学习讲座的 CC BY 4.0 下的图片。

下一次在深度学习中,我们将讨论交易和正规化的剩余技巧。我期待着在下一次讲座中见到你。非常感谢您的收听,再见!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

链接

链接 —关于最大后验概率估计和偏差-方差分解的详细信息
链接 —关于正则化实用建议的综合文本
链接 —关于校准方差的论文

参考

[1]谢尔盖·约菲和克里斯蒂安·塞格迪。“批量标准化:通过减少内部协变量转移加速深度网络训练”。载于:第 32 届机器学习国际会议论文集。2015 年,第 448–456 页。乔纳森·巴克斯特。“通过多任务抽样学习的贝叶斯/信息论模型”。摘自:机器学习 28.1(1997 年 7 月),第 7-39 页。
【3】克里斯托弗·m·毕晓普。模式识别和机器学习(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
[4]理查德·卡鲁阿纳。多任务学习:归纳偏差的知识来源。收录于:第十届机器学习国际会议论文集。摩根·考夫曼,1993 年,第 41-48 页。
【5】Andre Esteva,Brett Kuprel,Roberto A Novoa,等《深度神经网络的皮肤癌皮肤科医生级分类》。载于:自然 542.7639 (2017),第 115–118 页。
[6]丁俊钦、徐俊卿、陶行知。“多任务姿态不变人脸识别”。载于:IEEE 图像处理汇刊 24.3(2015 年 3 月),第 980–993 页。
[7]李万,马修·泽勒,张思欣,等,“用下降连接实现神经网络的正则化”。载于:《第 30 届机器学习国际会议论文集》(ICML,2013 年),第 1058-1066 页。
[8] Nitish Srivastava,Geoffrey E Hinton,Alex Krizhevsky,等人,“辍学:防止神经网络过度拟合的简单方法。”载于:《机器学习研究杂志》15.1 (2014),第 1929–1958 页。
[9]r . o .杜达、P. E .哈特和 D. G .施托克。模式分类。约翰威利父子公司,2000 年。
[10]伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔。深度学习。http://www.deeplearningbook.org。麻省理工学院出版社,2016 年。
【11】与何。“群体常态化”。载于:arXiv 预印本 arXiv:1803.08494 (2018)。
【12】何,,任等,“深入挖掘整流器:在 imagenet 分类上超越人类水平的表现”。IEEE 计算机视觉国际会议论文集。2015 年,第 1026–1034 页。
【13】D 乌里扬诺夫,A 韦达尔迪,以及 VS 伦皮茨基。实例规范化:快速风格化缺少的要素。CoRR ABS/1607.0[14]günter Klambauer,Thomas Unterthiner,Andreas Mayr 等,“自规范化神经网络”。在:神经信息处理系统的进展。abs/1706.02515 卷。2017.arXiv: 1706.02515。吉米·巴雷、杰米·瑞安·基罗斯和杰弗里·E·辛顿。“图层规范化”。载于:arXiv 预印本 arXiv:1607.06450 (2016)。
【16】Nima Tajbakhsh,Jae Y Shin,Suryakanth R Gurudu,等,“用于医学图像分析的卷积神经网络:完全训练还是微调?”载于:IEEE 医学成像汇刊 35.5 (2016),第 1299–1312 页。
【17】约书亚·本吉奥。“深度架构基于梯度训练的实用建议”。《神经网络:交易的诀窍》。斯普林格出版社,2012 年,第 437-478 页。
[18]张,Samy Bengio,Moritz Hardt 等,“理解深度学习需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。
[19]什巴尼·桑图尔卡,迪米特里斯·齐普拉斯,安德鲁·易勒雅斯等,“批处理规范化如何帮助优化?”在:arXiv e-prints,arXiv:1805.11604(2018 年 5 月),arXiv:1805.11604。arXiv:1805.11604[统计。ML】。
[20]蒂姆·萨利曼斯和迪德里克·P·金马。“权重标准化:加速深度神经网络训练的简单重新参数化”。神经信息处理系统进展 29。柯伦咨询公司,2016 年,第 901–909 页。
【21】泽维尔·格洛特和约舒阿·本吉奥。“理解训练深度前馈神经网络的困难”。摘自:2010 年第十三届国际人工智能会议论文集,第 249-256 页。
【22】,罗平,陈改来,等,“基于深度多任务学习的人脸标志点检测”。载于:计算机视觉— ECCV 2014 年:第 13 届欧洲会议,瑞士苏黎世,Cham: Springer 国际出版公司,2014 年,第 94–108 页。

正规化—第 5 部分

原文:https://towardsdatascience.com/regularization-part-5-b4019720b020?source=collection_archive---------54-----------------------

FAU 讲座笔记关于深度学习

多任务学习

FAU 大学的深度学习。下图 CC BY 4.0 来自深度学习讲座

这些是 FAU 的 YouTube 讲座 深度学习 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学习技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

多任务学习的概念。 CC 下的图片来自深度学习讲座的 4.0 。

欢迎大家来深度学习!所以今天,我们想结束谈论不同的正则化方法。我们想特别谈谈另一种叫做多任务学习的技巧。在多任务学习中,我们希望扩展前面的概念。以前,我们只有一个网络用于一项任务。然后,我们通过迁移学习来重用网络。问题是我们能做得更多吗?我们能以更好的方式做它吗?有一些真实世界的例子。例如,如果你学习弹钢琴和小提琴,那么在这两项任务中,你都需要良好的听力,对音乐符号的节奏感,等等。所以,有些东西是可以分享的。此外,足球和篮球训练都需要耐力、速度、身体意识和眼-身协调。所以,如果你学会了其中一个,那么你通常也会从另一个中受益。因此,这甚至比在您同时学习时重用更好,然后提供对共享基础概念的更好理解。

多任务学习旨在使用几个任务同时进行训练。 CC 下的图片来自深度学习讲座的 4.0 。

现在的想法是,我们在多个相关的任务上同时训练我们的网络。因此,我们采用损失函数来评估多任务的表现,然后这导致多任务学习,这引入了所谓的归纳偏差。因此,我们更喜欢一个能解释多项任务的模型。此外,这降低了在一个特定任务上过度拟合的风险,并且我们的模型概括得更好。

硬参数共享。来自深度学习讲座的 CC BY 4.0 下的图片。

那么,让我们来看看设置。因此,我们有一些共享的输入图层,它们类似于要素提取图层或制图表达图层。然后,我们在某个点进行划分,进入特定于任务的层,对任务 A、任务 B 和任务 c 进行评估。它们可能非常不同,但却有某种联系,否则,共享之前的层就没有意义。因此,所有任务共享几个隐藏层。正如 Baxter 在[2]中已经表明的,N 个任务的多任务学习将过度适应的机会减少了 N 个数量级。

软共享只是使用约束松散地耦合权重。 CC 下的图片来自深度学习讲座的 4.0 。

除了硬共享,还可以做软参数共享。它引入了额外的损失。因此,您将各个层中的激活约束为相似。因此,每个模型都有自己的参数,但我们将它们连接在一起,以在受约束的层中执行相似但不同的提取步骤。举例来说,你可以用一个 L2 规范或者其他使它们相似的规范来做。

面部标志检测的辅助任务是面部姿态估计和性别、眼镜和微笑检测。来自深度学习讲座的 CC BY 4.0 下的图片。

现在,还是要说说辅助任务。所有这些任务都应该有自己的目的。你也可以只是包括辅助任务,只是因为你想创建一个更稳定的网络。因此,这里的一个例子是张等人的面部标志检测[22]。他们本质上想要检测面部标志,但是这受到遮挡和后置变化的阻碍。因此,他们同时开始学习地标和微妙相关的任务,如面部姿势,微笑与不微笑,戴眼镜与不戴眼镜,以及性别。他们提供了这些信息,然后您可以在多任务学习框架中进行设置,就像您在网络架构中看到的那样。

张等人[22]的定性结果。 CC 下的图片来自深度学习讲座的 4.0 。

在结果中,您可以看到辅助任务如何支持面部标志的检测。他们把这比作 CNN,级联 CNN,以及他们的带有辅助任务的多任务网络。通过引入这些辅助任务来改进界标检测。因此,对于一个任务来说,某些特征可能很难学,但是对于一个相关的任务来说,可能就比较容易了。辅助任务有助于将训练引向特定的方向,我们通过选择适当的辅助任务,以某种方式包含了先验知识。当然,任务可以有不同的收敛速度。为了缓解这个问题,您还可以引入基于任务的早期停止。一个公开的研究问题是什么任务是合适的辅助任务。所以这是我们通常无法回答的问题,但通常是由实验验证决定的。

在这个深度学习讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学习讲座的 4.0 。

因此,下一次关于深度学习,我们将从一个新的主题开始,在这个主题中,我们将研究一些实用的建议,以使事情真正发挥作用。所以你已经看到了,我们已经很远了,但是有一些提示会让你的生活变得更容易。所以,我强烈建议观看接下来的几节课。我们将研究如何评估绩效,以及如何处理每个人在开始时都必须面对的最常见的问题。此外,我们还会查看具体的案例研究,包括您到目前为止所学的所有内容。

这些问题可能有助于备考。来自深度学习讲座的 CC BY 4.0 下的图片。

我有几个综合性的问题,比如:“什么是偏差-方差权衡?”“什么是模型容量?”"描述解决过度拟合的三种技术.""协变量移位问题和 ReLU 之间有什么联系?""我们如何解决协变量转移问题?",等等。进一步的阅读,你可以在我贴在这篇文章下面的链接上找到。非常感谢您的阅读,下次讲座再见!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

链接

链接 —关于最大后验概率估计和偏差-方差分解的详细信息
链接 —关于正则化实用建议的综合文本
链接 —关于校准方差的论文

参考

[1]谢尔盖·约菲和克里斯蒂安·塞格迪。“批量标准化:通过减少内部协变量转移加速深度网络训练”。载于:第 32 届机器学习国际会议论文集。2015 年,第 448–456 页。乔纳森·巴克斯特。“通过多任务抽样学习的贝叶斯/信息论模型”。摘自:机器学习 28.1(1997 年 7 月),第 7-39 页。
【3】克里斯托弗·m·毕晓普。模式识别和机器学习(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
[4]理查德·卡鲁阿纳。多任务学习:归纳偏差的知识来源。收录于:第十届机器学习国际会议论文集。摩根·考夫曼,1993 年,第 41-48 页。
【5】Andre Esteva,Brett Kuprel,Roberto A Novoa,等《深度神经网络的皮肤癌皮肤科医生级分类》。载于:自然 542.7639 (2017),第 115–118 页。
[6]丁俊钦、徐俊卿、陶行知。“多任务姿态不变人脸识别”。载于:IEEE 图像处理汇刊 24.3(2015 年 3 月),第 980–993 页。
[7]李万,马修·泽勒,张思欣,等,“用下降连接实现神经网络的正则化”。载于:《第 30 届机器学习国际会议论文集》(ICML,2013 年),第 1058-1066 页。
[8] Nitish Srivastava,Geoffrey E Hinton,Alex Krizhevsky,等人,“辍学:防止神经网络过度拟合的简单方法。”载于:《机器学习研究杂志》15.1 (2014),第 1929–1958 页。
[9]r . o .杜达、P. E .哈特和 D. G .施托克。模式分类。约翰威利父子公司,2000 年。
[10]伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔。深度学习。http://www.deeplearningbook.org。麻省理工学院出版社,2016 年。
【11】与何。“群体常态化”。载于:arXiv 预印本 arXiv:1803.08494 (2018)。
【12】何,,任等,“深入挖掘整流器:在 imagenet 分类上超越人类水平的表现”。IEEE 计算机视觉国际会议论文集。2015 年,第 1026–1034 页。
【13】D 乌里扬诺夫,A 韦达尔迪,以及 VS 伦皮茨基。实例规范化:快速风格化缺少的要素。CoRR ABS/1607.0[14]günter Klambauer,Thomas Unterthiner,Andreas Mayr 等,“自规范化神经网络”。在:神经信息处理系统的进展。abs/1706.02515 卷。2017.arXiv: 1706.02515。吉米·巴雷、杰米·瑞安·基罗斯和杰弗里·E·辛顿。“图层规范化”。载于:arXiv 预印本 arXiv:1607.06450 (2016)。
【16】Nima Tajbakhsh,Jae Y Shin,Suryakanth R Gurudu,等,“用于医学图像分析的卷积神经网络:完全训练还是微调?”载于:IEEE 医学成像汇刊 35.5 (2016),第 1299–1312 页。
【17】约书亚·本吉奥。“深度架构基于梯度训练的实用建议”。《神经网络:交易的诀窍》。斯普林格出版社,2012 年,第 437-478 页。
[18]张,Samy Bengio,Moritz Hardt 等,“理解深度学习需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。
[19]什巴尼·桑图尔卡,迪米特里斯·齐普拉斯,安德鲁·易勒雅斯等,“批处理规范化如何帮助优化?”在:arXiv e-prints,arXiv:1805.11604(2018 年 5 月),arXiv:1805.11604。arXiv:1805.11604[统计。ML】。
[20]蒂姆·萨利曼斯和迪德里克·P·金马。“权重标准化:加速深度神经网络训练的简单重新参数化”。神经信息处理系统进展 29。柯伦咨询公司,2016 年,第 901–909 页。
【21】泽维尔·格洛特和约舒阿·本吉奥。“理解训练深度前馈神经网络的困难”。摘自:2010 年第十三届国际人工智能会议论文集,第 249-256 页。
【22】,罗平,陈改来,等,“基于深度多任务学习的人脸标志点检测”。载于:计算机视觉— ECCV 2014 年:第 13 届欧洲会议,瑞士苏黎世,Cham: Springer 国际出版公司,2014 年,第 94–108 页。

正则化技术及其在 TensorFlow(Keras)中的实现

原文:https://towardsdatascience.com/regularization-techniques-and-their-implementation-in-tensorflow-keras-c06e7551e709?source=collection_archive---------6-----------------------

技术(包括代码)

理解用于减轻深度神经网络中过拟合问题的传统技术。

由 Unsplash 上的 Clarisse Croset 拍摄的照片

正规化

深度神经网络(DNN)具有大量的架构内部权重参数,可以学习一系列值。这些数值范围是使神经网络能够解决巨大复杂函数的关键。

神经网络越深,其具有的代表能力就越强,但是,随着权参数数量的增加,会出现一个缺点。这个缺点是神经网络更容易过拟合训练数据集。

过拟合:这个问题涉及到算法预测呈现给它的模式的新实例,基于太接近于它在训练期间观察和学习的模式的实例。这可能导致机器学习算法无法准确地推广到看不见的数据。如果训练数据没有准确地表示测试数据的分布,则会发生过度拟合。可以通过减少训练数据中的特征数量以及通过各种技术降低网络的复杂性来修复过度拟合

正则化技术通过限制网络中权重值的范围来降低神经网络过拟合的可能性(稍后将详细介绍)。

本文介绍了两种正则化策略,对损失函数的结果施加约束条件。

损失函数是一种量化机器学习模型表现有多好的方法。量化是基于一组输入的输出(成本),这些输入被称为参数值。参数值用于估计预测,而“损失”是预测值和实际值之间的差异。

本文不会关注正则化的数学。相反,本文介绍了一些标准的正则化方法,以及如何使用 TensorFlow(Keras)在神经网络中实现它们。

关于数学的更多细节,这些由莱米·卡里姆和雷努·汉德尔瓦尔撰写的文章合理地展示了 L1 和 L2 的正则化数学。

[## L1 L2 正则化

在这篇文章中,我们将了解为什么我们需要正规化,什么是正规化,什么是不同类型的…

medium.com](https://medium.com/datadriveninvestor/l1-l2-regularization-7f1b4fe948f2) [## 对 L1 和 L2 正则化的直觉

他们如何防止过度拟合?

towardsdatascience.com](/intuitions-on-l1-and-l2-regularisation-235f2db4c261)

正规化的类型

从上一节中,我们可以理解正则化技术作用于神经网络中的权重参数。更具体地说,它修改结果损失函数,进而修改产生的权重值。

l1 正则化

L1 正则化对神经网络权重值的影响在于,它通过使权重值等于 0 来惩罚接近 0 的权重值。负权重值也取值为 0;所以如果一个权值是-2,在 L1 正则化的作用下,它变成 0。

L1 正则化的一般直觉是,如果权重值接近 0 或非常小,那么它对于模型的整体性能来说是可以忽略的,因此使其为 0 不会影响模型的性能,并且可以减少模型的内存容量。

  • L1 对权重的绝对值之和(|weight|)进行惩罚

我知道我说过我不会涉足数学,但是下面的数学符号应该相对容易理解。

我们有损失函数,在这种情况下,均方差。

然后我们加上权重绝对值之和与正则化超参数值的乘积,用λ符号()表示。

数学符号中的 i 表示当前权值的索引, n 表示层内权值的总数。 W 代表重量值。

L1 正则化

l2 正则化

L2 正则化也惩罚权重值。对于较小的权重值和相对较大的权重值,L2 正则化将这些值转换为接近 0 但不完全 0 的数字。

  • l2 惩罚权重的平方和(权重)

L2 正则化

如果你要结合 L1 和 L2 正则化技术的效果,那么你将得到‘弹性网正则化’。

正则化技术在训练过程中对神经网络产生影响,而不是进行推理。

现在我们对正则化有了一些基本的理解(随意探索两种方法的数学)和一些例子,让我们看看它们是如何实现的。

实施正规化

第一步是导入用于实现或支持神经网络实现的工具和库。

  • TensorFlow :机器学习模型实现、训练、部署的开源平台。
  • Keras :一个开源库,用于实现运行在 CPU 和 GPU 上的神经网络架构。
import tensorflow as tf
from tensorflow import keras

我们将利用的数据集是普通的时尚-MNIST 数据集。

时尚-MNIST 数据集包含 70,000 幅服装图像。更具体地说,它包括 60,000 个训练样本和 10,000 个测试样本,这些样本都是尺寸为 28×28 的灰度图像,分为十类。

数据集的准备包括通过将每个像素值除以 255.0 来归一化训练图像和测试图像。这将像素值置于范围 0 和 1 之间。

数据集的验证部分也在此阶段创建。这组数据集在训练期间被用来评估网络在各种迭代中的性能。

(train_images, train_labels),(test_images, test_labels) = keras.datasets.fashion_mnist.load_data()
train_images = train_images / 255.0
test_images = test_images / 255.0validation_images = train_images[:5000]
validation_labels = train_labels[:5000]

接下来,我们使用 Keras Sequential API 实现一个简单的模型。我们模型中的隐藏层使用了多种正则化技术。

要添加一个正则化到一个层,你只需要把首选的正则化技术传递给层的关键字参数' kernel _ regularizer '。

Keras 正则化实现方法可以提供代表正则化超参数值的参数。这显示在下面的一些层中。

Keras 提供了 l1 和 l2 正则化的实现,我们将在下面的代码片段中的一些隐藏层中使用它。此外,我们包括一个利用 l1 和 l2 正则化的层。

这就是在神经网络中实现各种正则化技术的全部内容。不太难。

model = keras.models.Sequential([
    keras.layers.Flatten(input_shape=[28,28]),
    keras.layers.Dense(200, activation='relu', kernel_regularizer=keras.regularizers.l1()),
    keras.layers.Dense(100, activation='relu', kernel_regularizer=keras.regularizers.l2(0.001)),
    keras.layers.Dense(50, activation='relu', kernel_regularizer=keras.regularizers.l1_l2(0.01)),
    keras.layers.Dense(10, activation='softmax')
])

在下一段代码中,我们设置并指定用于训练已实现的神经网络的优化算法;以及损失函数和超参数,例如学习速率和时期数。

sgd = keras.optimizers.SGD(lr=0.01)
model.compile(loss="sparse_categorical_crossentropy", optimizer=sgd, metrics=["accuracy"])model.fit(train_images, train_labels, epochs=60, validation_data=(validation_images, validation_labels))

使用先前搁置的测试数据进行模型性能的评估。

通过评估结果,您可以在观察测试数据集评估的准确性后,决定微调网络超参数或继续生产。

model.evaluate(test_images, test_labels)

结论

如果损失函数上的正则化项被从层中排除并被训练相同数量的历元,则实现的模型可能在测试数据集上具有更好的性能。

正则化更常用于具有数百万个参数和更多特征的更深层次的神经网络中。

我希望读者现在对各种各样的正则化技术以及如何实现它们有一个直觉。

探索神经网络实现和训练中的其他正则化方法可能是令人感兴趣的,例如退出或提前停止。

下面是本文包含的代码的 GitHub 存储库。

[## Richmond alake/tensor flow _ 2 _ 教程

github.com](https://github.com/RichmondAlake/tensorflow_2_tutorials/blob/master/09_regularization.ipynb) [## 神经网络中的批量标准化(代码)

通过 TensorFlow (Keras)实施

towardsdatascience.com](/batch-normalization-in-neural-networks-code-d7c9b88da9f5) [## 作为机器学习工程师你需要的 5 个软技能(以及为什么)

包括成为任何劳动力的有用组成部分的提示

towardsdatascience.com](/5-soft-skills-you-need-as-a-machine-learning-engineer-and-why-41ef6854cef6)

正规化。什么,为什么,什么时候,怎么做?

原文:https://towardsdatascience.com/regularization-what-why-when-and-how-d4a329b6b27f?source=collection_archive---------14-----------------------

在这篇文章中,我想深入探讨一下正规化。

什么?

什么是正规化?

正则化是一种约束模型的方法,以准确地拟合我们的数据,而不是过度拟合。它也可以被认为是惩罚我们模型中不必要的复杂性。深度学习实践者主要使用 3 种类型的正则化技术。它们是:

  1. L1 正则化或拉索正则化
  2. L2 正则化或岭正则化
  3. 拒绝传统社会的人

侧栏:其他技术也可以对我们的模型产生正则化效果。你可以通过更多的数据来限制我们函数的搜索空间,从而防止过度拟合。这可以通过数据扩充等技术来实现,这些技术可以创建更多的数据来训练,从而减少过度拟合。
有许多其他解决过度拟合的方法,如集合和提前停止,它们可以帮助防止过度拟合,但不被视为正则化,因为它们不限制搜索空间或惩罚复杂性。尽管你应该记住这些,因为调整并不是解决过度拟合的唯一方法。

为什么?

我们为什么需要正规化?

图 1:欠适与过适。图片由作者提供。灵感来自吴恩达

在图 1 中,我们看到 3 条曲线。左边的预测分数做得很差,右边的预测分数做得【太好】。我们可以直观地看出左边的图不对,但是为什么右边的不好呢?我们的模型准确预测点的位置,这不好吗?

答案是,原因如下。我们的数据包含一些噪音,我们不希望我们的模型预测噪音,因为噪音是随机的。所以右边的图也不理想,我们想要像中间的图一样的东西。

拟合不足是由于我们的模型过于简单,或者训练时间不够长造成的。过度拟合是一个更难的问题。
过度拟合可能是由于过于复杂的模型(学习噪音)造成的,或者是我们的模型函数的搜索空间太大,我们没有足够的数据来限制搜索。

所以正则化是一种停止过度拟合的方法。

什么时候?

我们什么时候使用正规化?

每当我们怀疑我们的模型过度拟合时,我们就使用正则化。过度拟合的最大迹象是验证指标的糟糕表现。验证集是模型尚未看到的数据集的一部分。

因为我们想检测我们的模型是仅从数据中学习,还是受到噪声的严重影响,所以我们使用噪声与训练集不同的验证集。因此,如果我们的模型过度拟合训练数据,它将在我们的验证集上预测不佳。

在培训期间,我们还会不断测量验证指标。如果我们看到验证指标没有显著提高,或者恶化,这是我们的模型过度拟合的警告信号。然后我们需要应用正则化技术。

注意:有些规则化技术没有缺点,应该一直使用。这方面的一个例子是数据扩充。使用数据扩充没有坏处,无论模型是否过度拟合都应该使用。

怎么会?

L1 正规化

L1 正则化通过添加基于由某个值 l(通常称为λ)缩放的参数的绝对值的惩罚来工作。

最初我们的损失函数是: Loss = f(preds,y) 其中 *y 是目标输出,preds 是预测preds = WX+b,其中 W 是参数,X 是输入,b 是偏差。*

对于 L1 正则化,我们添加了 l*|W|的额外项,其中 W 是权重矩阵(参数)。因此,L1 正则化后的损失函数为

损失= f(preds,y) + l*abs(W)

L2 正规化

L2 正则化非常类似于 L1 正则化,除了罚项是由某个因子 l(λ)缩放的参数的平方

损失= f(preds,y) + l*(W)

L1 与 L2 正规化的区别

L1 正则化和 L2 正则化之间的区别在于,损失函数相对于 L1 正则化的参数的梯度与参数的无关,因此一些参数可以一直设置为零,因此完全被忽略。****

但是在 L2 正则化中,损失函数的梯度线性地依赖于参数,因此参数不可能为零。它们只是渐近地接近零。这意味着没有一个参数被完全忽略,每个参数对预测的影响总是最小的。

这种差异是选择正规化类型的关键,如果你知道你有无用的功能,L1 可能是一个更好的选择。如果你想考虑所有的功能,L2 可能是一个更好的选择。

细微差别:深度学习中有一个细微差别,通过使用 L1 和 L2 正则化,可以使用两全其美的方法。这被称为弹性网正则化。

辍学

Dropout 是一种神奇的正则化技术,只对神经网络有效(据我所知)。dropout 的惊人想法是以概率 p (p 是超参数)随机地将输入张量的一些元素归零。

这背后的直觉很简单,当我们的模型太复杂时会出现过度拟合,那么我们如何简化模型呢?只是不要用一些神经元然后嘭!!实现了一个更简单的模型。

我们发现辍学在实践中非常有效,并且易于实施。我绝对推荐试一试。

数据扩充

数据扩充是我们正规化的最终“方法”。数据扩充背后的想法非常简单,但极其优雅。

我们知道过度拟合是由于在我们的最优函数的搜索空间中缺乏约束而引起的。我们如何添加更多约束?更多数据。
但是为我们的问题收集更多的数据可能是一项耗时且艰巨的任务。这就是数据增强的用武之地。

数据扩充的想法是从我们已经拥有的数据中创造更多的数据。方法是对我们的图像进行一些变换,改变图像,使同一图像有不同的多个版本。神奇的是,我们有了更多的数据。

我最喜欢的深度学习库( fastai )提供的数据增强列表可以在这里看到。

结论

检查你的模型是否过度拟合,使用上述正则化方法之一来避免过度拟合。始终使用数据增强!!鳍。

正则贪婪森林

原文:https://towardsdatascience.com/regularized-greedy-forest-a17cd0c85f06?source=collection_archive---------32-----------------------

梯度助推器

修改赢得许多卡格尔比赛的 GBM

来源: Unsplash

2011 年,Rie Johnson 和张彤提出了对梯度推进模型的修改。他们称之为正规化的贪婪森林。当他们进行修改时,GBDTs 已经在某种程度上统治了表格世界。他们测试了各种数据集的新修改,包括合成和真实世界,并发现他们的修改比标准 GBDTs 实现了更好的性能。他们还参加了一些 Kaggle 类型的比赛(债券价格挑战、生物反应预测和遗产提供商网络健康奖),并在比赛中击败了其他 GBDT 模特。

他们建议的核心 GBDT 算法的关键修改如下:

完全正确的贪婪更新

根据 Friedman[1]的说法,标准梯度提升的缺点之一是收缩/学习率需要很小才能实现收敛。事实上,他主张无限小的步长。他们建议进行修改,使收缩参数变得不必要。

在标准梯度推进中,该算法在每次迭代中执行部分校正步骤。该算法仅在当前迭代中优化基础学习器,而忽略所有先前的学习器。它为当前时间步长创建最佳回归树,并将其添加到集合中。但是他们建议在每次迭代中,我们更新整个森林( m 基础学习者用于迭代 m )并且在每次迭代中重新调整比例因子。

结构化稀疏正则化

虽然完全校正的贪婪更新意味着算法将更快地收敛,但也意味着它过拟合得更快。因此,结构化稀疏正则化被用来解决这个问题。结构化稀疏性的一般思想是,在假设稀疏解的情况下,可以利用任务背后的稀疏结构。在这个特定的设置中,它被实现为在森林结构中对决策规则的稀疏搜索。

显式正则化

除了结构化稀疏正则化,他们还包括一个损失函数显式正则项。

其中 l 是可微凸损失函数,ω是惩罚树结构复杂性的正则化项,ϕ是森林结构。

本文介绍了三种类型的正则化选项:

树叶的 L2 正则化

其中ϕ是森林结构,λ是用于控制正则化强度的常数,αᵥ是节点 v 的权重(其被限制为叶节点),Lₜ是树 t 的叶,𝒯是森林中所有树的集合。

实现中超参数: l2

最小惩罚正则化

最小惩罚正则化惩罚树的深度。这是一种正则化,它作用于所有节点,而不仅仅是树叶。这使用了任何叶节点都可以根据其祖先节点来编写的原则。正则化背后的直觉是它惩罚深度,这在概念上是一个复杂的决策规则。

确切的公式超出了我们的范围,但是这里的关键超参数是 l2 ,它控制正则化的整体强度,以及 reg_depth ,它控制惩罚树的深度的严厉程度。 l2 的建议值为 1、0.1、0.01,而 reg_depth 应为大于 1 的值

兄弟和为零的最小惩罚正则化

这非常类似于最小惩罚正则化,但是增加了一个条件,即兄弟节点的权重总和应该为零。总和为零约束背后的直觉是,冗余较少的模型是优选的,并且当内部节点处的分支导致完全相反的动作时,模型是最不冗余的,例如将“x”加到输出值而不是从输出值中减去“x”。所以这不利于两件事——树的深度和树的冗余度。这里没有额外的超参数。

注意:这里要注意的一个有趣的花絮是,论文和竞赛中的所有 bechmarks 都只使用了简单的 L2 正则化。

算法

总的概念仍然类似于梯度推进,但是关键的区别在于每次迭代中的树更新。并且由于目标函数中的正则化项,简单方便的均值或中值导数或梯度不再起作用。

让我们看看新的算法,尽管是在一个高层次上。

  1. 重复

1.1 ϕ是通过对当前森林ϕ应用一步结构改变操作可获得的所有森林中最小化ℒ(ϕ的最佳森林)

1.2 优化ϕ的叶片重量以最小化损失(ℒ(ϕ)

2.直到满足一些退出标准

3.优化ϕ的叶子重量以最小化损失ℒ(ϕ)

4.返回ϕ

树构建策略

在规则贪婪森林中,树的建造方式有一个关键的不同。在经典的梯度推进中,在每个阶段都会建立一棵新树,并有一个特定的停止标准,比如深度或叶子的数量。一旦你通过了一个阶段,你不能碰那棵树或与之相关的重量。相反,在 RGF,在任何 m 次迭代中,更新任何先前创建的 m-1 树或开始一个新树的选项是开放的。对森林的确切更新由最小化损失函数的动作来确定。

让我们看一个例子来理解梯度增强和正则化贪婪森林在树构建上的根本区别

梯度推进的树构建过程(来源:自有图解)

正则化贪婪森林的树构建过程(来源:自己的插图灵感来自论文[2])

标准的梯度提升建立连续的树,并将这些树相加成为近似期望函数的加法函数。

RGF 采取了稍微不同的路线。对于树结构中的每一步变化,它评估在现有树中生长新叶与借助损失函数开始新树的可能性,然后采取贪婪的方法来选择损失最小的路线。所以在上图中,我们可以选择在 T1,T2 或 T3 种植树叶,或者我们可以开始一个新的 T4 树,这取决于哪一个给你最大程度的减少损失。

但实际上,这样做在计算上是有挑战性的,因为随着我们越来越深入森林,要评估的可能分裂呈指数增长。因此,在实现中有一个超参数, n_tree_search ,它将树的回溯更新限制为仅那些最近的树。默认值设置为 1,以便更新总是查看一个先前创建的树。在我们的例子中,这降低了在 T3 长出叶子或在 T4 长出新树的可能性。

从概念上讲,与森林中树木的加法函数相比,这变成了森林树叶的加法函数,因此,在 RGF 中没有 max_depth 参数,因为树的深度自动受到对树结构的增量更新的约束。

下一步是被选为最佳结构变化的新叶的权重。这是一个优化问题,可以使用多种方法中的任何一种来解决,如梯度下降法或牛顿-拉夫森法。因为我们正在寻找的优化更简单,所以本文使用了比梯度下降更精确的牛顿步来获得新叶的近似最优权重。如果你对我们如何以及为什么需要牛顿步来优化这些函数感兴趣,请参考附录 A。

重量优化

在基础学习器或基础函数固定的情况下,我们需要优化森林中所有叶子的权重。这又是一个优化问题,使用坐标下降法来解决,坐标下降法迭代遍历每片叶子,并以较小的步长通过牛顿步长来更新权重。

因为已经设置的初始权重是近似最优的,所以我们不需要每次迭代都重新优化权重。如果我们这样做,计算成本会很高。这是实现中的另一个超参数,称为 opt_interval 。根据经验,观察到除非 opt_interval 是极值,否则 opt_interval 的选择并不重要。对于他们赢得的所有比赛,他们只是简单地将值设置为 100。

关键超参数和调整

以下是论文作者建议的关键超参数列表。它几乎是直接取自他们的 Github 页面,但是被采用到 Python 包装器中。

附录 A

泰勒近似和牛顿-拉夫逊最优化方法

Youtube 频道 3Blue1Brown(如果你想要对数学有基本的直觉,我强烈推荐它)有另一个精彩的视频来解释泰勒展开/近似。请务必至少观看视频的前 6 分钟。

泰勒近似法让我们通过使用函数的导数来近似一个接近于一点的函数。

假设我们进行二阶近似,并找到一个局部最小值,我们可以通过设置导数为零来实现

将其设置为零,我们得到:

这(x-a)是最小化该点函数的最佳步骤。所以,这个最小值更像是朝向最小值的步进方向而不是实际的最小值。

为了优化不可微函数,我们需要在步长方向上采取多步,直到我们对损失相对满意,或者从技术上来说,直到损失低于我们的容差。这被称为优化的牛顿-拉夫森方法

梯度助推器中的其他文章

  • 良好的旧梯度增强
  • 正规化的贪婪森林(你在这里)

参考

  1. 贪婪函数近似:一种梯度推进机器。安。统计学家。29 (2001 年),第 5 号,1189-1232。
  2. Johnson,Rie & Zhang,Tong,“利用正则化贪婪森林学习非线性函数”,《IEEE 模式分析与机器智能汇刊》 (卷:36, 期:5 ,2014 年 5 月

原载于 2020 年 2 月 9 日 http://deep-and-shallow.com

用 JavaScript 重新实现流行的 Python 功能

原文:https://towardsdatascience.com/reimplementing-popular-python-functionalities-in-javascript-b3cfe8e7849f?source=collection_archive---------20-----------------------

学习如何应对一个新的世界,并充分利用现有的工具。

照片由艾蒂安·德洛里欧在 Unsplash 上拍摄

我的第一语言是 Python。我喜欢 Python 的多功能性、易用性和精彩的社区。

几个月前,我开始冒险深入 JavaScript 丛林,因为我已经开始构建 ViTeach (目前只有德语版本)。ViTeach 是一个数学平台,旨在使用机器学习和自然语言处理来快速跟踪和个性化数学学习。但是这篇文章不是为了宣传我的项目。这篇文章是关于我在使用 JavaScript 时错过的一些基本的 Python 功能。但不要担心,经过一段时间的语言适应后,事情开始变得非常相似。

在本文中,我们将讨论三种常见的模式/功能,对于来自 Python 的人来说,它们在 JavaScript 中并不十分明显:

  • 范围
  • 列出理解
  • 字典理解(并使用结果来获得大型数组操作的性能提升)

①范围

Ashkan Forouzani 在 Unsplash 拍摄的照片

让我感到惊讶的第一件事是 JavaScript 没有 Python 钟爱的range的实现。Python 中的 range 函数返回一个所谓的 sequence 对象,这就是为什么我们必须将它解析为一个列表(或者循环遍历它)来打印出值(例如,在 Jupyter 笔记本中)。但是大多数情况下,您无论如何都只是迭代这些值,因此很少需要 step。range为 0 索引,取:

  • 一个(最大),
  • 两个(最小和最大),
  • 或者三个参数(最小值、最大值和步长)。

请注意,range的参数是位置参数 (args),而不是关键字参数 (kwargs)。

计算机编程语言

**IN: (One Argument - only max value)** list(range(10))
**OUT:** [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]**IN: (Two Arguments - min and max value)** list(range(3,11))
**OUT:** [3, 4, 5, 6, 7, 8, 9, 10]**IN: (Three Arguments - min, max and step value)** list(range(7,34,3))
**OUT:** [7, 10, 13, 16, 19, 22, 25, 28, 31]

Java Script 语言

尤普,JavaScript 中没有range函数。对于第一种情况(仅 max ),我们可以得到最接近的结果如下:

**IN:** [...Array(5).keys()]
**OUT:** [0,1,2,3,4]

真的吗?!?这里到底发生了什么?让我们仔细分析一下。首先,我们实例化一个长度为 5 的数组(Array(5))。此时,数组的每个值都是undefined。然后我们通过.keys()得到每个元素的索引(即在数组中的位置),最后通过destructuring ( )操作符destructure将索引列表放到一个新的数组中,从而创建一个浅层副本。哇,那确实是一把。

第二种情况(min 和 max)和第三种情况(min、max 和 step)需要更多的自定义逻辑,这就是为什么我决定编写我的实现,并在此后的几乎每个项目中使用它。

const range = (min, max, steps = 1) => {**// Step 1)**
  const arr = Array.from(
    new Array(max - min), 
    (_, idx) => idx + min
  );**// Step 2)**
  return arr.filter((_, idx) => idx % steps === 0);
};**IN:** range(3,11)
**OUT:** [3, 4, 5, 6, 7, 8, 9, 10]**IN:** range(7,34,3)
**OUT:** [7, 10, 13, 16, 19, 22, 25, 28, 31]

让我们快速解释一下这是干什么的:

  1. Array.from()接受一个数组和一个映射函数,并将该函数应用于一个类似数组或可迭代对象的每个元素,想想 Python 中的[func(idx,val) for (idx,val) in enumerate(arr)]。我们给每个值加上最小值,现在有了一个从最小值到最大值的列表。注意,除了new Array(max-min),我们还可以使用之前使用的函数([...Array(max-min).keys()]),但是正如我提到的,我发现语法有点奇怪。
  2. arr.filter()过滤我们的数组,使得结果数组只包含符合过滤标准的元素。在我们的例子中,idx,即数组模步长中的位置必须是 0(即该数必须是没有余数的整除数)。因此只取每第 n 个元素(其中 n =步长)

②列表理解

尼克·希利尔在 Unsplash 上拍摄的照片

对我来说,列表理解是 Python 的主要特征之一,也是 Python 编码方式的象征。它们允许去掉 for 循环,这通常会使代码更加易读和简洁。让我们看看一些常见的使用案例。

计算机编程语言

典型的情况是从数组中过滤元素,然后返回一个只包含满足条件的元素的数组(例如,类型检查)。

**IN:**
values = [1,2,3,5,"x",10]
[_ for _ in values if isinstance(_,int)]**OUT:** [1, 2, 3, 5, 10]

另一个主要用例是对列表中的每个元素应用一个函数,返回一个包含更新值的新列表,如下所示:

对列表中的每个元素应用一个函数

额外收获:你甚至可以像这样做嵌套列表理解:

**IN:**
matrix = [
  [1, 2], 
  [3, 4], 
  [5, 6], 
  [7, 8]
]multiply_by_two = [
  [cell * 2 for cell in row] for row in matrix
]**OUT:** [
  [2 , 4 ], 
  [6 , 8 ], 
  [10, 12], 
  [14, 16]
]

Java Script 语言

pythonic 列表理解语法确实存在于 JavaScript 中,尽管只是在实验版本中。ECMAScript 4 曾讨论过这个问题,但在 ECMAScript 6 中被永久放弃了。他们可能会在未来带回某种形式的一般理解(即适用于所有可重复的作品)。但是现在,箭头函数和**map, filter and find** 就可以了。让我们回顾一下前面的例子。我将使用_作为标记“丢弃变量”的一种方式(因为下划线不会占用太多空间)。让我们从过滤开始:

**IN:**
const values = [1,2,3,5,"x",10]
values.**filter**(_ => Number.isInteger(_))**OUT:** [1, 2, 3, 5, 10]

filter的一个特例是find,我发现它非常有用。Find 返回匹配条件的第一个元素。

**IN:**
const values = [1,2,3,5,"x",10]
values.**find**(_ => _ > 4)**OUT:** 5

注意:如果没有元素满足条件:

  • **find** 将返回**undefined**(falsyvalue)
  • **filter**将返回**[]**(truthy value)这在 Python 中尤其奇怪,在 Python 中空数组肯定是错误的——我提到过 JavaScript 有时很奇怪吗?)****

接下来是对列表中的每个元素应用函数。通过**map**可以轻松实现该功能。

对数组中的每个元素应用 JavaScript 函数

③词典理解

照片由粘土堤在 Unsplash 拍摄

比列表理解稍微不常见的是字典理解,我发现它在构建映射对象时非常强大。假设有一个场景,在这个场景中,你有一个列表中的 lot 个对象,假设所有的对象都有个唯一的 id和其他一些数据,如下所示:

**{
  '_id': '850f200c0b8f4b0ea80513e71fad93a0',
  'name': 'qHvbtkRxrj',
  'net_worth': 32000
}**

假设您从数据库中获得了这个列表,并希望进行一些基于 id 的操作。然后你将不得不无数次地遍历这个列表。更简单的方法是将列表转换成哈希表,其中_id成为键,对象本身成为值。

**hash_table = {
...,
'**850f200c0b8f4b0ea80513e71fad93a0**': {
  '_id': '**850f200c0b8f4b0ea80513e71fad93a0**',
  'name': 'qHvbtkRxrj',
  'net_worth': 32000
},
...
}**

现在,当我们想要改变一个特定条目的净值时,我们可以通过它的 _id 快速查找,改变对象,因为对象的条目是通过引用存储的,因此改变了原始列表。

巨蟒

Python 中的字典理解

当然,您也可以使用新生成的 hash_table 来快速检索特定 _id 的net_worth。与一次又一次地查找 _ids 相比,使用散列表带来了巨大的性能提升 (10⁵)

通过使用哈希表提高因子 1⁰⁵的性能

Java Script 语言

JavaScript 中的字典理解比 Python 中的稍微复杂一点,但实现起来仍然相当简单。我们将使用reduce来达到预期的结果。Reduce取一个初始值,然后遍历数组中的所有值,不断更新初始值。

JavaScript 中的字典理解

在这篇文章中,你学习了如何在冒险进入一个新的、看似可怕的世界时找回一些工具。

使用 TensorFlow2.x(加强)策略梯度

原文:https://towardsdatascience.com/reinforce-policy-gradient-with-tensorflow2-x-be1dea695f24?source=collection_archive---------14-----------------------

使用 TensorFlow 2.x 实施增强(PG)

在本文中,我们将尝试理解称为加强的策略梯度算法背后的概念。然后,我们将查看 TensorFlow 2.x 中算法的代码。让我们首先了解什么是策略梯度,然后我们将了解一种特定的策略梯度方法,也称为增强。

什么/为什么是政策梯度?

到目前为止,我们一直在学习状态-动作对的 Q 值。策略梯度算法不是先学习 Q 值再找一个策略,而是直接学习一个策略。但是为什么呢?让我们找出答案

  1. 学习策略导致更好的收敛,同时遵循梯度。而基于价值的方法在行动选择上可能会有很大的变化,即使在价值评估上有很小的变化。
  2. 这些算法对于像自动飞行无人机或自动驾驶汽车这样的大量动作非常有用。
  3. 可以学习随机政策。

算法和实现

加强是一种蒙特卡罗策略梯度方法,它在每一集之后进行更新。我们的神经网络将当前状态作为输入,输出所有动作的概率。我们可以通过调整代理网络的权重来优化我们的策略,以便在某个状态下选择更好的行动。通过对我们的目标函数执行梯度上升来调整这些权重。

让我们看看代码。

神经网络:

我们的模型实现如下。 注意最后一层包含 softmax 激活,输出每个动作的概率。

动作选择:

  1. 通过输入状态数组获得预测概率。
  2. 我们利用 TensorFlow 概率库将概率转化为分布。
  3. 然后我们从分布中抽取行动样本。
  4. 然后我们作为一个整体回到行动。

为了更好地理解,让我们先来看看主要的训练。

主训练循环:

  1. 我们维护了三个记录状态、奖励和行动的列表。
  2. 每集之后都要训练模型。

学习功能:

  1. 该函数将状态、动作和奖励列表作为参数。
  2. 我们将从奖励列表的最后一个元素开始循环。
  3. 然后,我们将计算每个州的预期累积奖励,就像我们在表格蒙特卡罗方法中所做的那样。
  4. 然后,我们计算损失的梯度和应用优化。

损失函数:

  1. 损失是所选行动的对数概率乘以该州的折现回报的负数。
  2. 请注意,这里的负号意味着我们正在执行梯度上升。

代码就这么多了,你可以在这里找到完整代码。让我们讨论一下政策梯度的一些弊端。

缺点:

  1. 很多时候,政策梯度收敛于局部极大值。
  2. 政策梯度法需要很长时间的训练。

所以,本文到此结束。谢谢你的阅读,希望你喜欢并且能够理解我想要解释的东西。希望你阅读我即将发表的文章。哈里奥姆…🙏

参考资料:

[## 强化学习

由阿尔伯塔大学提供。强化学习专业化包括 4 门课程探索权力…

www.coursera.org](https://www.coursera.org/specializations/reinforcement-learning) [## 强化学习,第二版

显着扩大和更新的广泛使用的文本强化学习的新版本,最…

mitpress.mit.edu](https://mitpress.mit.edu/books/reinforcement-learning-second-edition) [## 关于政策梯度的介绍

托马斯·西蒙尼尼对政策梯度的介绍

www.freecodecamp.org](https://www.freecodecamp.org/news/an-introduction-to-policy-gradients-with-cartpole-and-doom-495b5ef2207f/) [## 机器学习的冒险——学习和探索机器学习

由 admin |深度学习、策略梯度、强化学习、TensorFlow 2.0 在最近的一系列帖子中,我…

adventuresinmachinelearning.com](https://adventuresinmachinelearning.com)

强化吃豆人

原文:https://towardsdatascience.com/reinforced-pac-man-8e51409f4fc?source=collection_archive---------23-----------------------

趣味语境下的 AI 深度解析。

逃避 2020 年的严酷现实有多种形式。对一些人来说,2020 年已经充斥着阅读、听播客或深夜狂欢最新的网飞系列。对我来说,没有什么比建立一个人工智能代理来胜过阿朵的鬼谁是死心塌地吃它更好的背离现实了。是的,你猜对了,我说的是吃豆人,我说的是 AI。我们开始吧!

游戏设置

游戏将在包含我们的角色和物品的平铺游戏板上进行。在这种情况下,时间以离散的方式工作,而不是连续的,因此,下面的讨论将涉及时间步长(例如第 k 个时间步长)。在这个世界里,存在着:

  • 吃豆人——主角
  • 恩奇和克莱德——对立方
  • 颗粒——我们饥饿朋友的食物来源
  • 能量球——能让吃豆人的对手变得可食用的物体。

图 1:吃豆人游戏板(图片由作者提供)。

这些角色和他们周围的世界之间的互动被封装在一个完整的游戏棋盘表示中,也就是所谓的状态。每个状态代表特定时间点的世界,吃豆人或幽灵的任何动作都会导致状态的改变。Pac-man 或 ghosts 可用的动作是基于移动的动作,指示实体是向上、向下、向左还是向右移动。此外,像任何好的游戏一样,存在一个与传统游戏略有不同的积分系统。

  • 每吞噬一个小球,分数增加 10。
  • 状态每改变一次,就会招致 1 的生存惩罚。这是专门为了防止人工智能代理发现自己处于一种永远逃避墨奇和克莱德的模式中,从而不可能完成游戏。
  • 如果 AI 代理能够完成游戏,那么将会增加 500。可观的增长激励代理人完成游戏。
  • 类似地,死刑是用来阻止代理人被幽灵吃掉而退出游戏。
  • 吞噬一颗能量丸后吃掉任一个幽灵,会得到 200 的奖励。

在这个版本的吃豆人中,Inky 和 Clyde 并不特别聪明,并以随机行为遍历游戏棋盘。虽然这确实让吃豆人更容易赢得游戏,但目的是双重的:

  1. 吃豆人的主要动机是不被因基或克莱德吃掉而赢得游戏。
  2. 随着时间的推移,吃豆人必须学会如何在活着的时候最大限度地增加点数。

下面的解决方案将在不运行单一搜索算法的情况下处理这两个目标。

马尔可夫决策过程

马尔可夫决策过程(MDP)是一种对存在一组状态和动作的场景进行建模的正式方式。提交一个动作会以某种特定的概率导致不同的状态。也就是说,在给定先前状态 s 和所选动作 a 的情况下,存在描述到达状态s’的概率的转移函数。

每个状态也有与之相关联的奖励,因此有奖励功能。奖励值取决于先前的状态、动作和结果状态。

为了能够描述这个过程的开始和结束,还有一个开始和结束状态。不需要总是有终止状态,但这是对不同上下文的构造。

顾名思义,MDP 具有马尔可夫性质,即未来状态的条件概率严格依赖于当前状态。在这个结构中,这可以写成:

这类流程的目标是找到最佳策略。策略是 AI 代理在任何给定状态下遵循的一组指令。这是通过一种称为值迭代的迭代方法来完成的。该算法是搜索问题的一个非常好的解决方案,因为它保证收敛到一个最优策略。该算法取决于贝尔曼方程的计算:

对上述等式的解释比看起来要简单得多。正在计算的是在第 (k+1) 时间步的状态值 s 。状态的值是与到新状态的转变相关联的奖励,s’,以及将从新状态接收的随之而来的奖励。然而,由于这些奖励是未来的奖励,它们现在对吃豆人来说价值较低,因此它使用了一个贴现因子 𝛾 来表示收益递减。因为新状态s’是不确定的,所以该等式取每个可能的新状态的平均值,并基于转移概率对它们进行加权。最后,在每一个可能的行动中取最大值的原因是,存在一种乐观的观点,即不是通过最坏的结果,而是通过最好的结果来定义一个国家的价值。

数值迭代算法

该算法源于上述解释,给出如下:

  1. 从所有值为 0 的状态开始。
  2. 使用贝尔曼方程迭代并更新每个状态。
  3. 重复直到收敛。

随着时间的推移,行动的最优选择将收敛到确定每个国家的最优政策。

MDPs 和 Pac-man

所以你可能会问自己,这和吃豆人有什么关系?吃豆人游戏的设置类似于 MDP。在任何给定的时间点,存在封装游戏的状态,Pac-man 可以选择采取的行动,以及当代理到达新的状态时以点数形式的奖励。然而,上述迭代寻找最优策略的构造并不是真正的学习,而是一种模拟场景和寻找最佳计划的方法。从这个意义上来说,它与搜索算法并没有太大的不同,我也不会违背自己不进行搜索的承诺。所以,建筑需要多一点…

Q-学习

上面所描述的被称为“离线”解决方案,它在给定一个转移函数和奖励的情况下制定一个最优策略。通常,准确定义是不可能的或非常困难的,因此,代理需要了解真实的分布,而不是不切实际地提供它。因此,需要一种“在线”解决方案,除了它所处的状态和它可以采取的行动之外,它一无所知。

与上面的值迭代相反,优化 Q 函数是对所述问题的解决方案。为什么?价值迭代的等式是期望的成本和回报对等状态。另一方面,Q 函数是当你处于一个状态 s 并应用一个动作 a 时的预期成本和回报。通过这样做,当代理探索每个状态下可用的动作时,下一次将理解随之而来的回报。该实现采用其值符合贝尔曼方程的新样本,并将先前的 Q 值推向新的经验值。这在数学上描述如下:

在实现中,⍺是学习率,并且该值可以被解释为模型对新样本的存在有多敏感。学习速率越高,新信息的价值就越大,因为当观察到新样本时,新信息的价值会发生相当大的变化。

虽然这种方法在足够高的重复次数后确实能很好地逼近转移概率,但一个明显的问题是在勘探和开采之间的选择。如果主角在状态 s 决定了一个动作 a,并实现了一个积极的回报,那么什么会阻止 Pac-man 在稍后的时间点重复同样的动作。在目前的结构中,什么都没有。这就是引入勘探率的原因。它迫使吃豆人在每次ϵ的时候选择一个随机的移动。最初, ϵ=1 ,这意味着吃豆人将总是随机选择一个动作,因为它对游戏板一无所知,因此它将允许吃豆人做出相当数量的好和坏的决定。随着时间的推移, ϵ 将收敛到 0,以反映周围游戏知识的增长和探索新动作的需求的缺乏。重要的是要警惕ϵ收敛过快或过慢的影响。收敛太快将导致 Pac-man 在特定状态下不采取足够的行动,结果,估计的转移函数将是不准确的。另一方面,收敛太慢将导致次优决策,即使在多次学习迭代后也是如此,这是随机决策的结果。

Q-Learning 和 Pac-man

在一个典型的固定状态场景中,每个状态都有一个固定的奖励,并且终端状态也是固定的,上述结构将足以遍历棋盘并随着时间优化奖励。然而,吃豆人是一个更有活力的游戏。总共有 3 种终端情况:

  • 因基的好意,游戏结束
  • 克莱德的好意,游戏结束了
  • 吞噬最后一颗子弹

此外,一旦吃豆人吃了一个小球或能量球,并意识到这种行为的回报,它就不能再吞噬同样的小球或能量球。这些事实给了吃豆人一个更加动态的本质,因此要求我们将游戏的这些“特征”编码到学习模型中。这样做还可以降低从基于状态的学习模型到基于特征的学习模型的模型复杂度。

用于简化游戏的功能:

  • 一步之遥的幽灵数量(该特征赋予附近有 1 或 2 个敌人的状态以重要性)
  • 吃食物(强调吃食物行为的特征)
  • 最接近的食物(赋予最接近的颗粒重要性的特征)
  • 偏差(包含其他可能情况的偏差术语)

在这样做的时候,近似 Q 学习是近似的,并且将所有可能的情况总结为 4 个特征。

因此,对算法进行适当的修改,以学习每个特征的每个 β 权重。重量代表了吃豆人对每个功能的重视程度。结果,我们对算法进行了适当的修改,使得每个特征的重要性 β 被学习。

结果呢

最后,我们现在有了一个主角,他穿越周围的世界,建立直觉来躲避对手,同时最大化其一生的回报。

假设我们用 1000 次迭代和以下参数训练这个模型:

  • 𝛾 = 0.7
  • ⍺ = 0.1

认可和改进

我希望我们的黄种朋友的上述示范对你和对我一样令人满意。如果没有加州大学伯克利分校的 Pac-man 游戏引擎,这一切都是不可能的,该引擎已经被修改为与 Python 3 兼容。构建和解释我的解决方案的过程是非常宝贵的,尽管还有很多后续步骤。其中包括:

  1. 通过为每个幽灵引入传统的目标逻辑使 Pac-man 变得困难。
  2. 从 Q-learning 开始,下一个增加的复杂性层可能是深度 Q-Learning 模型。
  3. 使用包来优化实现(Github 源代码将很快推出)。
  4. 能量球被吞噬而鬼魂可以食用的情况很少发生,因此吃豆人不知道如何瞄准鬼魂。

我希望读者已经被我的第一篇博客吸引住了,并且能够理解强化学习的整体思想和细节。请留下您的评论和反馈。谢谢大家!

Unity 中自动驾驶汽车人工智能的强化学习

原文:https://towardsdatascience.com/reinforcement-learning-a-self-driving-car-ai-in-unity-60b0e7a10d9e?source=collection_archive---------11-----------------------

自动驾驶汽车的时代几乎就要降临在我们身上,至少 据埃隆马斯克 。因此,大概是时候学习如何为自己做一个了。虽然这篇文章没有深入到这种深度,但它足以制作出精通任何赛道的模拟汽车。

编辑:本故事已于 2021 年 1 月 1 日更新,以匹配 ML-Agents 的发布(1.0)版本。

注:本文面向已经对使用Unity有基本概念,并且对神经网络和 强化学习 感兴趣的人。不需要神经网络和/或博士学位的经验!本文提供了获得以下结果所需的一切:

上面三辆车都是用本文的代码训练出来的,一辆是作者控制的,你能猜到是哪一辆吗?

所有必要的代码都可以在 GitHub 的 资源库 中找到。

最基本的乘坐方式

我们首先构建一个赛车游戏的基本功能——为此你只需要一个 Unity 的功能版本(用 20 20.1 测试)。因为我们并不是要制造一场有趣或真实的比赛,这可以用几行代码来完成。

赛道

为了创建一个轨道,我创建了一组 3 块瓷砖(直行、左转、右转),我们可以以任何方式组合它们来创建一个轨道。

直走,左转,右转。每个瓷砖都由三个网格组成—一个正方形地板(带箭头的黑色)和两个边界。每个对象都是静态的,在所有三个网格上都有一个碰撞器。边界块必须标记为“”。

如您所见,每个瓷砖都有一个箭头。这个箭头显示了瓦片的退出方向,并匹配每个瓦片的forward向量,我们将在后面使用。

通过将瓷砖放置在彼此相距 10 米的位置(我建议将捕捉设置设置为 10),我们可以构建任何自定义轨道。这是我们将用于培训的工具:

训练跑道。注意,它与文章开头的赛道不同——在这条赛道上训练的 AI 可以很容易地在赛道瓷砖的任何组合上使用。

汽车

第二,我们制造汽车。我提供了一个 b̶e̶a̶u̶t̶i̶f̶u̶l 方便的三维模型作为这个项目的基础。

汽车是一个单独的物体,带有一个箱式碰撞器和一个动态刚体。由于我们只对平面上的运动感兴趣,所以可以关闭围绕 Y(绿色)轴的运动以及围绕 X、Z(红色、蓝色)轴的旋转。

同样,汽车的前进矢量指向它的运动方向。我们现在可以让我们的汽车移动了,这是使用下面的脚本完成的。

public class Car : MonoBehaviour
{
    public float speed = 10f;
    public float torque = 10f;

    private void Update()
    {
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        float dt = Time.deltaTime;
        MoveCar(horizontal, vertical, dt);
    }

    private void MoveCar(float horizontal, float vertical, float dt)
    {    
        // Translated in the direction the car is facing
        float moveDist = speed * vertical;
        transform.Translate(dt * moveDist * Vector3.forward);

        // Rotate alongside it up axis 
        float rotation = horizontal * torque * 90f;
        transform.Rotate(0f, rotation * dt, 0f);
    }
}

就是这样。如果你一直跟着,你可以开车去兜风。

请注意,该脚本仅基于向上或向下箭头键向前/向后移动,并向左或向右旋转。

我们完成了,我们的单人赛车游戏现在完成了!自己做一些测试,然后让我们看看人工智能在上面会有什么表现。

训练汽车

现在我们将转移到项目的 ML 代理部分。为此,如果您还没有安装 ML-agents 插件,您需要安装它。详情请参考 ML-Agents 安装说明。

为了让代理进行自我培训,我们需要执行以下操作:

  1. 观察代理的状态(位置、方向等)。)
  2. 根据状态决定行动。
  3. 评估该行动的结果。

为此,我们创建了一个名为CarAgent.cs的新类,它扩展了Car.cs并赋予我们从环境中学习的能力。这个类需要从一个Agent而不是MonoBehaviour继承,以便连接到底层的 ML-Agents 机器。

通晓人情世故

首先我们将比较代理的方向和轨迹的方向。为此,我们将在一个全局变量_track中存储当前的轨迹。我们使用以下函数获得当前音轨:

private Transform GetTrackTile()
{
    var carCenter = transform.position + Vector3.up;Physics.Raycast(carCenter, Vector3.down, out var hit, 2f);
    return hit.transform;
}

带符号的角度是沿着当前图块的黄色箭头和定义汽车前进方向的蓝色箭头之间的向上(Y 轴)方向获得的。

然后我们可以比较瓷砖和汽车方向的差异,如上图所示。这给了我们最初的观察——从逻辑上来说,赛车会尽量减小这个角度,以便跟随赛道。我们还使用一个带符号的角度(在-180 度和 180 度之间)来告诉汽车是向左还是向右转向。

public override void CollectObservations(VectorSensor vectorSensor)
{
    _track = GetTrackTile();
    float angle = Vector3
         .SignedAngle(track.forward, transform.forward, Vector3.up);
    vectorSensor.AddObservation(angle / 180f); // Map to (-1,1)
}

注意,该方法扩展了Agent 类的CollectObservations()方法,确保观察结果得到正确解释。

其次,我们需要判断汽车离障碍物的距离。在真正的自动驾驶应用中,经常使用的技术是激光雷达——一种利用光线反弹测量距离的方法。这里我们用光线投射来观察周围固体物体的距离。

这些射线被可视化为黄线。可以看到施法距离限制在 5m 以内。

为了投射光线,我们使用下面的辅助函数,它获取相对于汽车的位置和角度,并检查碰撞。如果有,我们将信息存储为[0,1]之间的正值,如果没有,我们返回-1

// Casts a ray from a point in a direction based on the car position
// z: offset of the ray origin from the car centre on the z axis
// x: as above but on the x
// angle: direction of the ray from its origin
private float ObserveRay(float z, float x, float angle)
{
    var tf = transform;

    // Get the start position of the ray
    var raySource = tf.position + Vector3.up / 2f; 
    const float **RAY_DIST** = 5f;
    var position = raySource + tf.forward * z + tf.right * x;

    // Get the angle of the ray
    var eulerAngle = Quaternion.Euler(0, angle, 0f);
    var dir = eulerAngle * tf.forward;

    // See if there is a hit in the given direction
    Physics.Raycast(position, dir, out var hit, **RAY_DIST**);
    return hit.distance >= 0 ? hit.distance / **RAY_DIST** : -1f;
}

要投射所有四条光线,我们只需向AddObservation()方法添加以下调用。

vectorSensor.AddObservation(ObserveRay(1.5f, .5f, 25f)); // FrontR
vectorSensor.AddObservation(ObserveRay(1.5f, 0f, 0f)); // Front
vectorSensor.AddObservation(ObserveRay(1.5f, -.5f, -25f)); // FrontL
vectorSensor.AddObservation(ObserveRay(-1.5f, 0, 180f)); // Back

艾掌握方向盘

这也是定义代理人大脑的时候。我们从BehaviourParameters开始,这将允许我们在培训前测试我们的代理:

我们使用 a5 观察和 2 个连续动作。这些动作分别映射到水平轴和垂直轴,与我们在非自主汽车上测试的输入相匹配。

现在我们只缺少一个DescisionRequester——一个控制人工智能应该多久做一次决定的脚本:

我们将决策周期设置为 1,即每一步都做出决策。

我们现在将输入动作到我们的学院。现在我们只把Update函数替换为AgentAction,它为代理定义了基本的事件循环。

public override void OnActionReceived(float[] vectorAction)
{      
    float horizontal = vectorAction[0];
    float vertical = vectorAction[1];
    float dt = Time.fixedDeltaTime;
    MoveCar(horizontal, vertical, dt);
}

注意,由于AgentAction发生在固定时间,我们必须改变单个移动动作之间的时间差。

现在,您可以用Car.cs替换CarAgent.cs并继续使用键盘驾驶。

奖励时间到了

最后,为了让代理能够自学,我们需要添加什么是好结果和坏结果的概念。我们特别要做到以下两点:

  1. 奖励沿着轨道前进。
  2. 处罚碰撞。

第一个更复杂,所以我们从它开始。这将在我们的OnActionReceived方法中完成。我们首先通过比较移动前后的位置来获得移动矢量。这让我们知道我们“沿着”轨道移动了多少。然后,这从范围(180,0)映射到(-1,1)-角度越大,奖励越低,角度> 90 是一个惩罚。请注意,这是一个与CollectObservation不同的地图。为了促进高速运动,我们将运动方向与垂直速度结合起来

var moveVec = transform.position - lastPos;
float angle = Vector3.Angle(_track.forward, moveVec);
float dirReward = 1f - (angle / 90f);
AddReward((dirReward + vertical) * dt);

注意,我们乘以时间步长(通常是 1/60 ),这样我们每秒最多得到 1 的回报。这与我们移动一个方块的速度相匹配——最多每秒 1 个,并确保奖金和奖励值以类似的方式贡献。当与前面的代码结合使用时,我们

public override void OnActionReceived(float[] vectorAction)
{
    var lastPos = transform.position;float horizontal = vectorAction[0];
    float vertical = vectorAction[1];
    float dt = Time.fixedDeltaTime;
    MoveCar(horizontal, vertical, dt);

    var moveVec = transform.position - lastPos;
    float angle = Vector3.Angle(_track.forward, moveVec);
    float dirReward = 1f - (angle / 90f);
    AddReward((dirReward + vertical) * dt);
}

其次,我们希望避免与墙壁碰撞——这是通过将奖励设置为-1f并结束当前训练集来惩罚的。

private void OnCollisionEnter(Collision other)
{
    if (other.gameObject.CompareTag("wall"))
    {
        SetReward(-1f);
        EndEpisode();
    }
}

最后润色

为了完成我们的代码,我们只需要添加代码进行重置。当汽车撞到墙时,我们希望将汽车重置到它的起始位置——结合负面奖励,这有助于训练避墙行为(如果汽车沿着墙卡住,我们可能会以许多小插曲结束)。这是在从代理继承的最后一个函数中完成的:

public override void OnEpisodeBegin()
{
    if (resetOnCollision)
    {
        transform.localPosition = Vector3.zero;
        transform.localRotation = Quaternion.identity;
    }
}

请注意,我们使用了resetOnCollision参数,这意味着冲突并不总是以重置结束——事实上,在玩游戏时,代理应该处理冲突,而不是重新开始。

驾校

我们终于拥有了运行培训流程的所有组件。

由于 Unity 支持多代理强化学习,所以最好一次使用多个代理。为此,我们将复制粘贴曲目。这些需要简单地在 x-z 平面上隔开,以便它们不重叠:

我们把轨道和汽车放在一个父对象中来创建一个训练实例。然后,15 个实例在两个方向上彼此等距 100 米。

最后,我们需要为培训过程设置参数。我们保留当前的默认参数,只是增加了报告频率。为此,我们在项目文件夹中创建以下名为trainer_config.yaml的配置文件:

behaviors:
    CarDrive:
        trainer_type: ppo    
        summary_freq: 10000

现在一切都准备好了。如果你遵循了 ML-Agents 安装说明,你应该有 python 和 mlagents 包。打开命令行,导航到放置trainer_config.yaml 的位置,然后运行以下命令:

mlagents-learn trainer_config.yaml --train --run-id=CarDrive

您应该得到一个响应,描述 ml-agents 版本并要求您按下 play 按钮。切换到 Unity,按 play,训练应该开始了。该过程需要几分钟时间,具体取决于您的 CPU(或 GPU,如果您安装了 TensorFlow 的 GPU 版本)。

你的训练现在完成了

强化学习——梯度时间差分学习算法介绍

原文:https://towardsdatascience.com/reinforcement-learning-an-introduction-to-gradient-temporal-difference-learning-algorithms-4a72ce5ab31e?source=collection_archive---------17-----------------------

对政策评估中一些最新算法的全面介绍,包括 GTD 和 GTD2。

Rafif Prawira 在 Unsplash 上拍摄的照片

目录:

  • 介绍
  • 线性函数逼近
  • 推导 GTD2 算法
  • 结论
  • 鸣谢和资源

介绍

强化学习是目前最热门的领域之一,具体的应用正在以令人难以置信的速度增长,从击败视频游戏到机器人。从本质上来说,强化学习(RL) 处理的是决策——也就是说,它试图回答一个主体在给定环境中应该如何行动的问题。

强化学习处理决策

不严格地说,所有的 RL 都归结为发现或评估一个策略,这只是一种行为方式。例如,策略可以是下棋的策略。

策略接受一个状态(在国际象棋的例子中,是棋盘上所有棋子的位置)并为其分配一个动作。

例如,给定你的棋盘的状态,你的策略可能要求你向前移动你的皇后。当你退出一个状态,你会得到一些奖励。这个很直观。例如,如果我们用快乐/痛苦来衡量我们作为人类的回报,那么把我们的手放在沸水中(退出之前手很冷的状态)会产生一些痛苦(因此,会有回报)。

在本文中,我们将关注一个叫做策略评估的东西,它可以归结为评估策略。这是什么意思?给定一个策略,我们希望找到其关联的值函数。这意味着如果我们遵循一些给定的策略,就能够给每个状态赋值。但是我们所说的是什么意思呢?如果我们处于某种状态,那种状态的值就是我们从这种状态中得到的预期回报。

TD 不一定在非政策环境下收敛

由 Richard Sutton 在 20 世纪 80 年代提出的 TD 学习的变体是一些最健壮和最常用的策略评估算法,尤其是在 on-policy 设置中,即当您遵循您正在评估的策略时。然而,在非策略设置中——当遵循不同于您正在评估的策略时——TD 学习算法的收敛性在某些情况下无法保证(例如,当使用线性近似时,我们将在下一节中讨论)。这使得萨顿等人在 2009 年引入了 GTD 和 GTD 2(GTD 的改进版本),以保证在非政策设置下的收敛性[1] [2]。

线性函数逼近

当你第一次开始学习 RL 时,你可能会开始学习马尔可夫链、马尔可夫奖励过程(MRP),最后是马尔可夫决策过程(MDP) 。然后,您通常会转到典型的策略评估算法,如蒙特卡罗(MC)和时间差异(TD)学习,然后是控制算法,如 SARSA 和 Q-learning。

对于大多数 RL 应用程序来说,表查找并不实用

在所有这些情况下,您可能一直在使用状态值和动作值函数的表格表示。这意味着您直接更新了每个状态的值。实际上,这对于具有大量状态的 MDP 或者在我们使用连续状态空间的情况下是非常不切实际的。例如,如果你试图在三维空间中引导一架直升机,你的状态可能是它的当前位置、速度、角速度、加速度等。正如您所猜测的,状态的数量是无限的,这意味着没有办法在一个表中存储所有的东西。

这个问题的解决方法是什么?我们将使用一个函数(由某个权重向量 θ 参数化)来逼近真实值函数,而不是直接更新每个状态。这个函数可以是任何东西(例如,您可以使用神经网络),但我们将重点关注线性函数逼近。数学上,我们在寻找一个函数

其中 ϕ(s) 是包含给定状态信息(例如:速度、加速度等)的特征向量。)和 θ 是我们正在努力学习的权重向量。在某些状态下,价值函数的估计就是ϕ(sθ 之间的点积。上式中, γ ∈ (0,1)称为折现率;直觉上,这意味着我们更重视获得短期回报,而不是长期回报——这与我们人类的工作方式是一致的,除了数学上的便利。

我们的目标是找到权重向量 θ ,这将允许我们的价值函数逼近尽可能精确。

如果我们用s’表示下一个状态,我们可以用贝尔曼方程写出 TD 误差如下:

我们记得,我们将在后面使用的贝尔曼算子被定义为 TV = R + γ PV,其中 P 是转移矩阵。任何给定值函数 V 必须满足贝尔曼方程,即 V = TV 。利用 TD 误差,我们可以获得传统的 TD 更新:

对于某些学习率 α(k) 。如果这对你来说是新的,这可能看起来很复杂,但这并不新奇!的确,这只是一个简单的随机梯度下降!在线性近似器的情况下,我们注意到梯度减少到 ϕ(k) ,这使得一切都变得美好而简单。

目标函数

现在我们有了一个价值函数逼近器,问题就变成了:我们如何让这个逼近器尽可能好?为此,我们首先需要定义某种误差函数。

一个目标函数只是一个 θ 的函数,我们将努力使其相对于 θ 最小化。

在做 TD 学习的时候,最自然的测量误差的方式就是通过测量 V(θ) 符合贝尔曼方程的程度。这被称为均方贝尔曼误差(MSBE) ,其定义为

其中 D 是一个对角矩阵,包含衡量每种状态出现频率的权重

对于某些矢量 v

对于任何 θ ,TV(θ)通常不能表示为 V(θ)

这个目标函数在许多先前的研究中被使用,但是大多数 TD 算法不收敛到 MSBE 的最小值。这是由于贝尔曼算子遵循马尔可夫链的基本状态动力学,这意味着对于任何 θ ,通常不能用 V(θ) 来表示 TV(θ) (例如,如果我们考虑线性函数逼近器,我们不能精确地表示非线性函数是有意义的)。然后,通常所做的是将最优解投影到最近的可表示值函数,其中运算符π定义为

如果我们考虑一个线性架构,其中对于某个矩阵φ,其行是 ϕ(s) ,我们可以独立于 θπ写成

到目前为止,所有的 TD 算法都收敛到值θ(TD 固定点),使得

GTD2 的推导使用了不同的目标函数,即均方投影贝尔曼误差(MSPBE) ,它考虑了投影π

MSBE 和 MSPE 之间有一种非常简洁的几何关系,我们可以在下图中看到(摘自萨顿关于 GTD2 的原始论文):

两个贝尔曼误差目标函数之间的几何关系[1]

有趣的是,对于 GTD 来说,使用的目标函数是预期 TD 更新(NEU)的标准,

我们很快就会看到,这两个方程确实非常相似。

推导 GTD2 算法

我们现在将推导 GDT2 算法,这是由 Sutton 等人在 2009 年引入的算法,它在偏离策略的情况下收敛。我们首先承认下列重要的关系,这将有助于以后简化某些方程。

现在,我们可以根据期望将 MSPBE 写成

我们应该在这里看到一些有趣的东西!

我们看到,MSPBE 与 NEU 的不同之处仅在于包含了特征协方差矩阵的逆。

为了避免需要两个独立的样本,我们可以使用一个可修改的参数 w ∈ Rⁿ 来形成目标函数梯度中除了一个期望之外的所有期望的准平稳估计

利用这一点,我们得到

其可以被直接采样。由此,我们得到 GTD2 算法:

GTD2 算法的θ更新

现在,我们想为 w 找到一个迭代更新。首先,我们意识到

我们看到上面的右边是下面最小二乘问题的解决方案:

这可以通过具有以下更新的随机梯度下降来解决:

w 为 GTD2 算法更新

θw 更新一起组成了 GTD2 算法,可以很容易地用你喜欢的编程语言实现。注意,为了让算法收敛,我们需要

结论

谢谢你走了这么远!我希望您现在对策略评估有了更好的理解,更具体地说,对强化学习中的一些新算法有了更好的理解,比如梯度时间差异学习。此外,我希望你对算法背后的数学有所了解,并对它们是如何推导出来的有更多的直觉。

鸣谢和资源

这篇文章主要依赖于 Sutton 等人在 2009 年发表的 GTD2 论文,以及最初的 GTD 论文。艾尔。

[1] Sutton,R. S .,Maei,H. R .,Precup,d .,Bhatnagar,s .,Silver,d .,Szepesvari,Cs .和 Wiewiora,E. (2009 年)。线性函数逼近的时差学习快速梯度下降法。在第 26 届机器学习国际会议记录中,第 993–1000 页。全媒体。

[2]萨顿、塞佩瓦里、Cs。,Maei,H. R. (2009 年)。线性函数逼近的非策略时差学习收敛 O(n)算法。神经信息处理系统进展 21 。麻省理工出版社。

基于强化学习的工厂能源优化

原文:https://towardsdatascience.com/reinforcement-learning-based-energy-optimization-dea8fb687cda?source=collection_archive---------10-----------------------

面向可持续未来的工厂暖通空调优化

摘要。 供暖、通风和空调(HVAC)单位负责维持建筑物内的温度和湿度设置。研究表明,暖通空调占建筑能耗的近 50%,占全球用电量的 10%。因此,暖通空调优化有可能为我们的可持续发展目标做出重大贡献,减少能耗和二氧化碳排放。在这项工作中,我们探索优化工厂 HVAC 控制的方法。不幸的是,这是一个复杂的问题,因为它需要考虑多个可变因素来计算最佳状态,例如,占用、制造进度、运行机器的温度要求、建筑物内的气流动态、外部天气条件、节能等。我们提出了一种基于强化学习(RL)的能源优化模型,该模型已在我们的工厂中得到应用。我们表明 RL 是一个很好的选择,因为它能够实时学习和适应多参数系统动力学。它比以前使用的比例-积分-微分(PID)控制器节能约 25%。

这篇论文的发表版本如下,发表在 2020 年 6 月第 11 届美国计算机学会电子能源会议论文集(PPT)https://dl.acm.org/doi/10.1145/3396851.3402363

图一。可持续发展的能源优化(来自 Pexels 的 Pixabay 摄影)

1 导言

供暖、通风和空调(HVAC)装置负责维持建筑物内的温度和湿度设置。在这项工作中,我们特别考虑了它们在工厂中的使用,其中 HVAC 装置的主要目标是将温度和(相对)湿度保持在规定的制造公差范围内。这需要与节能和减少二氧化碳排放相平衡,以抵消运行它们对环境的影响。

因为它们不仅普遍存在于工厂,而且存在于家庭和办公楼中;任何有效的控制逻辑都有可能对环境影响做出重大贡献。不幸的是,考虑到 HVAC 单元的复杂性,设计有效的控制逻辑是一个困难的优化问题。

控制逻辑需要考虑多个可变因素,例如,占用、制造进度、运行机器的温度要求、建筑物内的气流动态、外部天气条件、节能等。;以便决定该区域的加热、冷却或湿度。

HVAC 优化文献可以大致分为两类:(I)了解优化参数之间的循环模式,以更好地调度 HVAC 功能,以及(ii)建立 HVAC 单元的模拟模型,并评估模型上的不同控制策略,以确定最有效的策略。

第一类的例子包括[1,2],其采用建筑热力学模型来预测建筑的温度演变。不幸的是,这并不真正适用于我们的工厂,那里的制造工作量每天都在变化,而且没有可以预测的时间表。另外值得一提的是,大多数此类模型每次只考虑一个优化参数,即控制加热/冷却来调节温度;而在我们的情况下,我们需要同时调节温度和(相对)湿度,以保持最佳的制造条件。

第二类基于模型的方法适用于 PID 和 RL 控制器。PID(比例积分微分)控制器[3]使用控制回路反馈机制来控制过程变量。不幸的是,基于 PID 的控制器需要相对于基础 HVAC 单元进行大量的校准,以便能够有效地控制它们。[4]概述了一种基于模拟工具组合的 PID 校准方法。

基于强化学习(RL) [5]的方法[6,7]最近被提出来解决这些问题,因为它们能够实时学习和优化多参数系统。基于 RL 的方法需要初始(离线)训练阶段,因为在实时设置(在线)中训练 RL 算法可能需要时间来收敛,从而在 RL 代理探索其状态空间时导致潜在的危险违反。[6,7]根据基于暖通空调装置模拟模型的 EnergyPlus,概述执行该离线培训的解决方案。EnergyPlus [8]是美国能源部的一款开源 HVAC 模拟器,可用于模拟能耗(供暖、制冷、通风、照明、插头和过程负载)和建筑用水。不幸的是,开发 HVAC 单元的精确的基于能量+的仿真模型是一个重要的、耗时且昂贵的过程;因此是他们在离线训练中使用的一个障碍。

在这项工作中,我们提出了一个有效的基于 RL 的 HVAC 优化算法,它能够在几周内学习并适应一个实时 HVAC 系统。该算法可以独立部署,或作为“训练模块”来生成可用于执行 RL 模型离线训练的数据,以进一步优化 HVAC 控制逻辑。这使得所开发的 RL 模型的部署快速且具有成本效益。

此外,[6,7]中的模型输出是最佳温度和湿度设定值,这些设定值依赖于 HVAC 控制逻辑,以确保以有效的方式达到规定的设定值。在这项工作中,我们提出了一个更细粒度的 RL 模型,其输出是加热、冷却、再加热和加湿器单元的实际阀门打开百分比。这实现了一种更加自给自足的方法,RL 输出绕过任何内置的 HVAC 控制逻辑(消除任何依赖性并使其冗余),从而实现更加独立于供应商(平台)的解决方案。

文章的其余部分组织如下:第 2 节介绍了基础知识,提供了暖通空调优化问题的 RL 公式。第 3 节概述了 RL 逻辑,其最初被部署来生成用于离线训练的训练数据,从而导致第 4 节中的(训练的)RL 模型实时提供推荐的阀门打开百分比。在第 5 节中,我们提供了已开发的 RL 模型的一些基准测试结果,该模型已部署在我们的一个工厂区域中。初步研究表明,我们能够在现有 PID 控制器逻辑的基础上实现 25 %的能效。第 5 节对论文进行了总结,并为未来的工作提供了方向。

2 问题场景

2.1 暖通空调

图 2 显示了 HVAC 装置的能量平衡。简而言之,HVAC 装置必须使再循环空气和新鲜空气的混合达到将区域温度和(相对)湿度保持在所需水平所需的温度和湿度。通过计算流出空气和流入空气的能量之差,很容易监控所需的理论能量,将该量与机组所需的能量进行比较,即可得出 HVAC 机组的能效。

能量流可以根据介质(空气、热水、冷水、蒸汽)的流量以及介质供应和回流之间的温差来确定。和消耗的电能。

图二。暖通空调控制(图片由作者提供)

2.2 强化学习

RL 指的是人工智能(AI)的一个分支,它能够通过实时最大化一个奖励函数来实现复杂的目标。奖励功能的工作原理类似于用糖果和打屁股来激励孩子,这样算法在做出错误决定时会受到惩罚,在做出正确决定时会受到奖励——这就是强化。有关 RL 框架的详细介绍,感兴趣的读者可以参考[5]。

2.3 RL 公式

我们现在将场景映射到我们的 HVAC 设置。在任何时间点,工厂区域都处于以区域内外观察到的温度和(相对)湿度值为特征的状态。

在这种情况下,游戏规则对应于温度和湿度的容许水平,其基本要求区域温度和湿度值应分别在:19–25度和45–55%的范围内。在这种情况下,可用的动作集是冷却、加热、再加热和加湿器阀门打开百分比(%)。

总的来说,根据(内部和外部)温度和湿度值给定区域状态,RL 模型需要决定将冷却、加热、再加热和加湿器阀门打开多少。为了在这种情况下做出明智的决定,RL 模型需要首先了解 HVAC 系统的行为,例如通过将冷却阀打开到 X %,可以预期区域温度下降多少?

一旦 RL 模型理解了 HVAC 系统的行为,最后一步是设计控制策略,或 RL 术语中的“策略”。例如,RL 模型现在必须选择是否在区域温度达到 23 度时将冷却阀打开至 25%,或者等到区域温度达到 24 度时再将冷却阀打开至 40 %。注意,在打开阀门之前等待的时间越长,对降低能耗有积极的作用;然而,由于外部天气条件总是不可预测的,这就有违反温度/湿度耐受水平的风险。因此,如果等待时间更长,它可能实际上不得不将冷却阀打开到更高的百分比,从而消耗更多的能量。上述概率由 RL 术语中的奖励函数(等式 1)量化,该函数基于以下三个参数为每个可能的行为分配奖励:

控制策略是决定三个参数的权重:设定点接近度(SC)、能量成本(EC)、公差违反(TV)。能源成本体现在电力消耗和二氧化碳排放方面。例如,“安全”控制策略会为违反容差的行为分配非常高的负权重(惩罚),确保它们永远不会发生,尽管会付出更高的能源成本。同样,“能源优化政策”会将节能置于其他两个参数之上。设定值接近度鼓励“商业友好”政策,RL 模型试图将区域温度保持在尽可能接近温度/湿度设定值的水平,这无疑降低了违规风险,但能源成本较高。

我们选择“平衡”控制策略,最大化节能和设定值接近度,同时最小化违反公差的风险。

图 3 中示出了上述 RL 公式。

图 3。暖通空调强化学习公式(图片由作者提供)

基于 3 RL 的暖通空调优化

我们概述了 RL 算法,该算法基于当前室内温度和湿度(在时间 t )以及先前的加热、冷却、加湿器、再加热阀打开百分比值、时间 t-1 的室内温度和湿度值,输出在时间 t 打开加热、冷却、加湿器和再加热阀的程度。

rl_hvac 功能运行,每隔 1 分钟实时计算新的阀门开度值。

**#input values:**
i_tl #Indoor Temp (previous, at time t-1)
i_hl #Indoor Humidity (previous)
i_t  #Indoor Temp (current, at time t)
i_h  #Indoor Humidity (current)
y_hl #Heating Valve Opening (previous, at time t-1)
y_ul #Humidifier Valve Opening (previous)
y_rl #Re-heating Valve Opening (previous)
y_cl #Cooling Valve Opening (previous)**#output values:** y_h  #Heating Valve Opening (current, at time t)
y_u  #Humidifier Valve Opening (current)
y_r  #Re-heating Valve Opening (current)
y_c  #Cooling Valve Opening (current)**#static variables:** hiW  #Heating step increment
uiW  #Humidifier step increment
riW  #Re-heating step increment
ciW  #Cooling step increment*#invoked every 1 min* ***rl_hvac*** *(i_tl, i_hl, i_t, i_h, y_hl, y_ul, y_rl, y_cl)***# Heat and Humidify**
if (i_t < 22.0) and (i_h < 50.0):    
    if (i_t < i_tl):
        inc = hiW + abs((i_t - i_tl) / 0.1)
        y_h += inc
    if (i_h < i_hl):
        inc = uiW + abs((i_h - i_hl) / 0.1)
        y_u += inc
    y_r = 0.0
    y_c = 0.0
**# Cool and Reheat**
if (i_t > 22.0) and (i_h > 50.0):
    if (i_t > i_tl):
        inc = ciW + abs((i_t - i_tl) / 0.1)
        y_c += inc
    if (i_h > i_hl):
        inc = riW + abs((i_h - i_hl) / 0.1)
        y_r += inc
    y_h = 0.0
    y_u = 0.0
**# Heat, Cool and Reheat**
if (i_t < 22.0) and (i_h > 50.0):
    if (i_t < i_tl):
        inc = hiW + abs((i_t - i_tl) / 0.1)
        y_h += inc
    if (i_h > i_hl):
        inc = ((ciW + riW) / 2.0) + abs((i_h - i_hl) / 0.1)
        y_c += inc
        y_r += inc
    y_u = 0.0
**# Cool and Humidify**
if (i_t > 22.0) and (i_h < 50.0):
    if (i_t > i_tl):
        inc = ciW + abs((i_t - i_tl) / 0.1)
        y_c += inc
    if (i_h < i_hl):
        inc = uiW + abs((i_h - i_hl) / 0.1)
        y_u += inc
    y_h = 0.0
    y_r = 0.0***return*** *(y_h, y_u, y_r, y_c)*

RL 逻辑可以解释如下:回想一下,我们希望保持的温度和(相对)湿度设定值是 22 度和 50 %;允许公差范围分别为 35 。在每次迭代( 1 分钟)时, rl-hvac 功能根据以下控制逻辑确定打开哪个阀门:

知道打开哪个(些)阀,每个阀打开多少取决于奖励值,该奖励值作为先前(输出)阀打开的“有效性”的度量来计算。例如,假设室内温度目前为 20.5 度(低于温度设定值),这意味着需要打开供暖阀。在前一次迭代期间,室内温度也低于设定值,比如说 21.0 度,导致 rl_hvac 功能建议在比如说 15 %时打开加热阀。考虑到当前的室内温度甚至更低( 20.5 度),我们推断先前的加热阀打开不够有效——赋予其负奖励——并且加热更多,其量与当前和先前的室内温度之间的差成比例。其他阀门的行为可以类似地解释。这是一种强化,确保阀门能够有效地平衡奖励函数(等式 1)的“设定点接近度”和“能量成本”参数。

奖励函数的剩余参数是“公差违反”,其中如果室内温度/湿度违反了允许的公差范围,则需要施加惩罚。在我们的情况下,违规意味着相应的阀门需要更快地反应。这由步进增量常数调节: hiW,ciW,uiW,riW 。我们以离线方式调整它们,以便在给定时间段内,如果公差违反的数量超过某个阈值,则调整它们的值。

**# Check tolerance violations and adapt respective increment values**
if (count (i_t > 25.0) > n):    
    ciW += 1.0
if (count (i_t < 20.0) > n):    
    hiW += 1.0
if (count (i_h > 55.0) > n):    
    riW += 1.0
if (count (i_h < 45.0) > n):    
    uiW += 1.0

4 连续 RL 优化

在本节中,我们扩展了 RL 模型,以适应“长期回报”,用 RL 术语中的 Q 值来量化。(回想一下,上一节中概述的 RL 算法中的奖励函数是随机的,在某种意义上,它仅取决于最后的状态。)状态-动作对 (s,a) 的 Q 值被定义为从当前状态 s 开始的所有未来步骤的期望回报值的加权和,假设在状态 s 采取动作 a

为了适应“长期回报”,我们将原来的问题扩展到一个连续的空间设置。该设置中的每个事件对应于室内温度和(或)湿度开始偏离其各自设定值的时间,以及室内条件返回其各自设定值的时间——这是打开相关阀门的结果。

图 4。阀门倾点计算(图片由作者提供)

现在让我们来关注一个这样的插曲(在一个连续的空间设置中)。假设随机 RL 算法(第 3 节)总是在 0.0% 开始打开阀门,温度和(或)湿度与设定值的偏差持续增加,直到阀门打开百分比达到临界点,之后偏差再次开始减小,直到变为 0 。这种阶段性行为如图 4 所示。为了简单起见,我们只显示了温度——冷却曲线,但是对于其他情况,包括那些涉及湿度的情况,可以预期类似的行为。图 4 中的能量成本对应于阴影区域。鉴于这种行为,很容易看出,如果我们事先知道冷却临界点是 22.3 度,我们可以更早地将冷却阀打开到临界点——导致更低的能量成本(由虚线阴影区域描绘)。这里需要注意的是,需要正确估计所有阀门的临界点,否则打开阀门超过临界点的百分比实际上可能会导致更高的能源成本。

接下来,我们将展示如何将第 3 节中 RL 算法生成的数据用作训练数据,以开发一个模型来预测工厂区域每个状态的阀门“临界点”。

对于每个时间点 t ,(第 3 部分)RL 算法数据可被认为由以下输入和值组成:(室内温度、室内湿度、加热阀开度%、冷却阀开度%、加湿器阀开度%、再加热阀开度%)。我们对该数据应用以下过滤标准(仅针对湿度)来提取训练数据:

**# Extraction filter (for humidity) — to extract the training data** # loop through rows of the generated data
for i in range(1, dataset.shape[0]):
   cRow = dataset.iloc[i] #current row
   pRow = dataset.iloc[i-1] #previous row

   if cRow['Indoor Humidity'] > 50.0 and cRow['Indoor Humidity'] < pRow['Indoor Humidity']:
       ctr = ctr + 1
       #write row to training data

   if cRow['Indoor Humidity'] < 50.0 and cRow['Indoor Humidity'] > pRow['Indoor Humidity']:
       ctr = ctr + 1
       #write row to training data

通过这一更新(粗体),RL 算法能够引导阀门开启百分比,因此每次事件将以训练模型提供的相应“临界点”值开始(而不是从 0.0% 开始),从而降低能源成本,如图 4 所示。

**# Heat and Humidify**
if (i_t < 22.0) and (i_h < 50.0):
    if (y_h == 0.0):
        y_h = **loaded_h_model.predict(Xnew)**
    elif (i_t < i_tl):
        inc = hiW + abs((i_t - i_tl) / 0.1)
        y_h += inc
    if (y_u == 0.0):
        y_u = **loaded_u_model.predict(Xnew)**
    elif (i_h < i_hl):
        inc = uiW + abs((i_h - i_hl) / 0.1)
        y_u += inc
    y_r = 0.0
    y_c = 0.0

5 基准测试 RL 与 PID

提出的 RL 模型已经部署在我们罗马尼亚工厂的一个区域中。指定区域有五个(类似的)HVAC 单元,其中 HVAC 单元的示意图如下图 5 所示。

图 5。暖通空调示意图(图片由作者提供)

对于该区域,我们首先给出(图 6)一周内运行带 PID 控制器的 HVAC 的室内条件和 HVAC 阀门开启百分比(约 10,000 个读数,相当于每分钟一个读数)。

图 6。基于 PID 的 HVAC 控制读数(图片由作者提供)

对于同一个区域,我们随后运行了由 RL 模型控制的 HVAC 单元的基准测试。我们确保两种情况下的制造工作负载相似。我们首先运行第 3 节中概述的 RL 算法一周。接下来,应用第 4 节中概述的过滤器来生成训练数据。然后使用 AWS Sagemaker Autopilot [9]训练四个模型: h_model、u_model、r_model、c _ model,以产生基于 XGBoost 的回归模型,其验证误差(来自超参数调整的 MSE)约为 25.0 。训练好模型后,我们又运行了一周第 4 节中介绍的 RL 算法(同样,使用类似的生产工作负载)。结果显示在图 7 中。

图 7。基于 RL 的 HVAC 控制读数(图片由作者提供)

比较平均阀门开启百分比(由图 6 和图 7 中的红色边界框突出显示),我们可以看到所有基于 RL 的阀门开启百分比较低;从加热阀的 10 %节约到再加热阀的几乎 45 %节约—平均节约 25 %。

6 结论

在这项工作中,我们考虑了工厂中的暖通空调能源优化问题,这有可能在节能和减少二氧化碳排放方面产生重大的环境影响。为了解决问题的复杂性,我们概述了一种基于 RL 的 HVAC 控制器,它能够学习并适应现实生活中的工厂设置,而无需任何离线培训。据我们所知,这是在实际工厂中报告 RL-HVAC 模型现场部署的首批作品之一。我们提供的基准测试结果显示,在能效方面有可能节省高达 25 %。

请注意,我们认为节能与阀门开启百分比成正比(越低越好)。实际上,不同阀门的能量消耗和 CO2 排放可能不成比例,即根据基本机制,打开相同百分比的加热和冷却阀门可能消耗不同数量的能量。我们将此作为将来的工作来调整 RL 逻辑,以适应能耗和 CO2 排放方面。

参考

[1] F. Oldewurtel 等人使用随机模型预测控制和天气预测进行节能建筑气候控制。事故赔偿委员会,2010 年。

[2] Y. Ma 等建筑制冷系统运行的模型预测控制。IEEE 控制系统技术汇刊,20(3):796–803,2012。

[3] F .皮科克。PID 算法的白痴指南。https://www.pidcontrol.net/index.html

[4] C .布拉斯科等人根据能效和舒适度标准对暖通空调系统进行建模和 PID 控制。In:能源和建筑的可持续性。智能创新,系统和技术,第 12 卷(2012)。

[5] Harmon,m . e . Harmon,S.S.: 强化学习:教程。http://www . cs . Toronto . edu/~ zemel/documents/411/rl tutorial . pdf

[6] T. Weiand 等人.."建筑暖通空调控制的深度强化学习 l "第 54 届年度设计自动化会议论文集,第 22 页,2017。

[7] T. Moriyama 等人用于功耗优化的强化学习试验台。《第 18 届亚洲模拟会议(AsiaSim)论文集》,第 45–59 页,2018 年。

[8] EnergyPlus,https://energyplus.net

[9]亚马逊 SageMaker 自动驾驶,https://aws.amazon.com/sagemaker/autopilot/

基于强化学习的推荐系统

原文:https://towardsdatascience.com/reinforcement-learning-based-recommender-systems-492a2674fcc?source=collection_archive---------25-----------------------

理解大数据

结合强化学习和 NLP/聊天机器人开发个性化应用

摘要。 我们提出了一种基于强化学习的方法来实现推荐系统。这些结果是基于一个现实生活中的健康应用程序,该应用程序能够以互动的方式向用户提供个性化的健康/活动相关内容。不幸的是,当前的推荐系统无法适应不断发展的特征,例如用户情绪,以及需要基于多个不可靠的反馈通道(例如传感器、可穿戴设备)来计算 RL 奖励的场景。为了克服这一点,我们提出了三个构造:(I)加权反馈通道,(ii)延迟奖励,和(iii)奖励提升,我们认为这对于 RL 用于推荐系统是必不可少的。

这篇论文发表在 AAI4H —医疗保健人工智能进展研讨会的会议录上,与第 24 届欧洲人工智能会议( ECAI 2020),2020 年 9 月 ( 论文 pdf)(PPT)

基于强化学习的推荐系统:基于来自 Pexels 的 Andrea Piacquadio 的 pic

1 导言

健康/保健应用程序的采用率一直很低。通过向用户提供越来越相关和及时的建议,个性化推荐有可能提高采用率。虽然推荐引擎(以及基于它们的应用程序)已经成熟,但它们仍然受到“冷启动”问题的困扰,事实上它基本上是一种基于推送的机制,缺乏使这种应用程序吸引千禧一代所需的交互性。

我们展示了一个健康应用案例研究,其中我们应用了强化学习(RL)和自然语言处理(NLP) /聊天机器人的组合,以向用户提供高度个性化的交互式体验。我们专注于应用程序的交互方面,应用程序能够实时描述用户并与用户交谈,提供适应用户当前情绪和过去偏好的相关内容。

这种聊天机器人的核心是一个意图识别自然语言理解(NLU)引擎,它通过问题变体的硬编码示例进行训练。当没有符合 30%以上置信度的意图时,聊天机器人会返回一个后备答案。基于(显式的)用户响应和(隐式的)环境方面来计算用户情绪,例如位置(住宅、办公室、市场……)、温度、照明、一天中的时间、天气、附近的其他家庭成员等等;来进一步适应聊天机器人的反应。

RL 指的是人工智能(AI)的一个分支,它能够通过实时最大化一个奖励函数来实现复杂的目标。奖励功能的工作原理类似于用糖果和打屁股来激励孩子,这样算法在做出错误决定时会受到惩罚,在做出正确决定时会受到奖励——这就是强化。强化方面还允许它更快地适应用户情绪的实时变化。有关 RL 框架的详细介绍,感兴趣的读者可以参考[1]。

以前的工作已经在推荐系统的背景下探索了 RL[2,3,4,5],并且随着云 API(例如 Azure Personalizer [6,7])和 Google 的 RecSim [8]的最近可用性,企业采用也似乎正在获得动力。然而,它们仍然像典型的推荐系统一样工作。给定用户简档和分类推荐,系统基于流行度、兴趣、人口统计、频率和其他特征来做出推荐。这些系统的主要新颖之处在于,它们能够识别推荐的特征(或特征的组合),从而为特定用户获得更高的回报;然后可以为该用户定制以提供更好的推荐[9]。

不幸的是,这对于现实生活中的系统来说仍然是低效的,这些系统需要适应不断发展的功能,例如用户情绪,并且需要根据多个不可靠的反馈渠道(例如传感器、可穿戴设备)来计算奖励。

本文的其余部分组织如下:第 2 节概述了问题场景,并将其表述为 RL 问题。在第 3 节中,我们建议

需要三种 RL 结构来克服上述限制:(I)加权反馈通道,(ii)延迟奖励,以及(iii)奖励提升,我们认为这是 RL 用于推荐系统的基本结构。

在这种情况下,“延迟回报”不同于延迟 RL [10]的概念,在延迟 RL 中,遥远未来的回报被认为不如即时回报有价值。这与我们的“延迟奖励”概念有很大不同,在延迟奖励中,只有在后续行动验证了奖励的一致性后,才会应用奖励。第四部分总结了本文,并提出了未来研究的方向。

2 问题场景

2.1 健康应用

该应用程序支持基于推送的通知,其中个性化的健康,健身,活动等。向用户推送相关推荐;以及应用程序响应用户查询的交互式聊天。我们假设存在一个知识库 KB 的文章、图片和视频,根据它们与不同用户简档/情感的相关性对工件进行排序。

图 1 中描述了健康应用架构,其示出了用户和环境条件(包括用户反馈)如何:

1.使用可用传感器收集以计算“当前”反馈,包括环境背景(例如,用户的网络摄像头 pic 可用于推断用户对聊天机器人响应/通知的情绪、房间照明条件和附近存在的其他用户),

2.其然后与用户对话历史相结合,以量化用户情感曲线,并排除由于不相关因素引起的情感的任何突然变化;

3.导致与提供给用户的最后聊天机器人响应/应用通知相对应的合计奖励值。

然后,该奖励值作为反馈提供给 RL 代理,以从知识库中选择下一个最佳聊天机器人响应/应用程序通知。

图一。健康应用架构(图片由作者提供)

2.2 互动聊天— RL 公式

我们将上述场景的 RL 引擎公式化如下:

动作 ( a ):在这种情况下,动作 a 对应于一篇知识库文章,该文章作为推送通知或者作为对用户查询的响应或者作为正在进行的对话的一部分被传递给用户。

Agent ( A ):是执行动作的一方。在这种情况下,代理是向用户交付操作的应用程序,其中操作是基于其策略选择的(如下所述)。

环境:指智能体与之交互的世界,它响应智能体的动作。在我们的例子中,环境对应于与应用程序交互的用户。 UA 的行为做出反应,提供不同类型的反馈,既有显性的(以聊天反应的形式),也有隐性的(如面部表情的变化)。

策略 (𝜋):是代理用来选择下一个基于动作的策略。给定一个用户简档 Up 、【当前】情绪 Us ,并查询Uq;策略功能计算分别由 NLP 和推荐引擎返回的文章分数的乘积,选择具有最高分数的文章作为下一个最佳动作:(a)NLP 引擎( NE )解析查询,并基于文章与用户查询的“文本相似性”输出每个知识库文章的分数。(b)类似地,推荐引擎( RE )基于与每篇文章相关联的奖励,针对用户简档和情感,为每篇文章提供分数。策略函数可以形式化为如下形式:

奖励 ( r ):是指我们用来衡量代理推荐行为的成败的反馈。反馈可以例如指用户阅读推荐文章所花费的时间量。我们考虑两步奖励函数计算,其中接收到的关于推荐动作的反馈 fa 首先被映射到情感分数,然后情感分数被映射到奖励。

其中 rs 分别指奖励和情感函数。图 2 中示出了上述 RL 公式。

图二。RL 公式(图片由作者提供)

3 RL 奖励和政策扩展

3.1 加权(多个)反馈通道

如图 1 所示,我们考虑一个多反馈渠道,从用户(边缘)设备/传感器捕获反馈,例如网络摄像头、恒温器、智能手表,或者嵌入在托管应用的移动设备中的摄像头、麦克风、加速度计。例如,捕捉用户面部表情的网络摄像头帧、用户智能手表提供的心率,可以与用户提供的文本响应“谢谢你的好建议”一起考虑;在计算用户对推荐动作的情绪时。

{fa1,fa2,… fan} 表示行动 a 收到的反馈。回想一下 s(f) 表示基于各自的感官反馈 f 独立计算的用户情绪。用户情感计算可以被认为是输出在1–10之间的值的分类器。然后,可以将奖励计算为情感分数的加权平均值,如下所示:

其中权重 {wa1,wa2,… wan} 允许系统协调接收到的反馈,因为一些反馈信道可能遭受低可靠性问题。例如,如果 fi 对应于用户键入的响应, fj 对应于网络摄像头快照;则给予 fi 更高的权重。这里的理由是,用户可能在快照中“微笑”,然而“微笑”是由于他的孩子进入房间(也在帧中被捕捉),而不一定是对所接收的推荐/动作的响应。同时,如果基于用户文本响应计算的情感指示他“有压力”,那么在这种情况下,我们给予用户明确(文本响应)反馈更高的权重。

3.2 延迟奖励

在奖励不一致的情况下应用“延迟奖励”策略,其中(当前)计算的奖励对于已知用户积极响应的行为(对于历史上相同类型的行为)是“负面的”;反之亦然。给定这种不一致,延迟奖励策略缓冲在时间 t 的行动的计算的奖励比率;并且向 R1 代理策略(𝜋)提供指示,以在更新时间 t 和 t+1 的行为奖励之前尝试相同类型的另一个推荐,从而验证用户情绪。

为了适应“延迟奖励”策略,奖励功能扩展了一个内存缓冲区,允许从时间( t+m)到 t 的最后 m 个动作的奖励被聚集并在时间( t+m )追溯应用。延迟奖励功能 dr 表示如下:

其中,|𝑡+𝑚暗示对行动的报酬从时间( t+m)到 t 行动,尽管是单独计算的;只能在时间( t+m )应用。如前所述,各自的权重允许我们协调不一致的反馈的影响,其中对𝑎t 时间𝑡𝑖的行为的奖励是基于在时间(𝑡+1)𝑖.

为了有效地执行“延迟奖励”策略,策略𝜋也被扩展为推荐与先前推荐的动作相同类型的动作;如果延迟标志 d 置位(d = 1);则“延迟”策略𝜋𝑑𝑡表示如下:

图 3 示出了用延迟奖励/策略扩展的 RL 公式。

图 3。延迟奖励——基于政策的 RL 公式(图片由作者提供)

3.3 奖励提升

奖励增加,或者说奖励正常化,主要适用于持续的聊天互动。在这种情况下,如果用户对推荐动作的情绪是“负面的”;这可能不仅仅是上一个动作的错。可能对话情绪已经在下降,最后推荐的操作只是跟随下降趋势。另一方面,在对话情绪恶化的情况下,对推荐行为的“积极”情绪意味着它对用户产生了非常积极的影响;因此相应的回报应该增加。

对于在时间 t 的处的动作的提升的奖励𝑟𝑏𝑎𝑡计算如下:

我们把它作为将来的工作来扩展‘boost’函数到最后的 n 动作(而不仅仅是上面的最后一个动作)。在这个扩展场景中,系统维护最后 n 个动作的情绪曲线,并且相对于曲线而不是离散值来计算偏差。这里预期的好处是,它应该允许系统对用户情绪趋势做出更好的反应。

4 结论

在这项工作中,我们考虑在现实生活中的健康应用程序的背景下实现基于 RL 的推荐系统。RL 是解决此类问题的强大原语,因为它允许应用程序实时学习和适应用户偏好/情绪。然而,在案例研究中,我们意识到当前的 RL 框架缺乏应用于这种推荐系统所需的某些结构。为了克服这个限制,我们引入了三个 RL 构造,我们必须为我们的 Wellness 应用程序实现它们。建议的 RL 结构在本质上是基本的,因为它们影响奖励和政策功能之间的相互作用;我们希望将它们添加到现有的 RL 框架中会增加企业的采用。

参考

[1]巴尔托,a .,萨顿,R.S.: 强化学习:导论。麻省理工学院出版社,麻省剑桥,2018 年,http://incompleteideas.net/book/RLbook2018.pdf

[2]崔顺实,哈,h,黄,U..Kim,c .,Ha,j .,Yoon,S.: 使用双聚类技术的基于强化学习的推荐系统。arXiv:1801.05532,2018。

[3]刘,李,李,叶,陈,郭,张,杨:基于深度强化学习的推荐与显式用户-项目交互建模。arXiv:1810.12027,2018

[4] Taghipour,n .,Kardan,a .,Ghidary,S.S.: 基于使用的网络推荐:强化学习方法。摘自:美国计算机学会推荐系统会议,第 113-120 页(2007)。

[5] Ricciardelli,e .,Biswas,D.: 基于强化学习的自我改进聊天机器人。In:第四届强化学习与决策制定多学科会议(2019)。

[6] 微软 Azure Personalizer
https://Azure . Microsoft . com/en-us/services/cognitive-services/Personalizer/

[7]李,李,朱,w,兰福德,J.C .,沙皮雷,R.E.: 一种语境强盗式的个性化新闻文章推荐方法。摘自:第 19 届万维网国际会议,第 661–670 页(2010 年)。

[8] 谷歌 RecSim
https://ai . Google blog . com/2019/11/rec sim-configurable-simulation-platform . html,最后访问时间 2019/02/03。

[9]用于更好的推荐系统的强化学习。https://analyticsindiamag . com/reinforcement-learning-recommender-system-recsim-Google-ai/

[10] 延迟强化学习。http://heim . ifi . uio . no/~ mes/INF 1400/COOL/REF/Standford/ch11 . pdf

强化学习、大脑和心理学:经典和工具性条件作用

原文:https://towardsdatascience.com/reinforcement-learning-brain-and-psychology-part-2-classical-and-instrumental-conditioning-217a4f0a989?source=collection_archive---------18-----------------------

强化学习、人工智能和人类

心理学研究如何启发强化学习中的主体训练?

"一个人相信事物是因为他已经习惯于相信它们。"—阿尔多斯·赫胥黎,美丽新世界。

在强化学习领域,有两大类算法:用于预测的算法和用于控制的算法
对于稍微熟悉题目的人来说,预测算法通常是基于值的算法,也就是说它们的目的是预测一种情况的结果(奖励)。而控制算法大多是基于策略的算法,应该引导你度过难关。

同样,这些类别对应着心理学的两项研究:经典(巴甫洛夫) 条件反射工具(操作)条件反射预测算法经典条件作用之间的对应关系取决于它们预测即将到来的刺激的共同特性,无论这些刺激是奖励还是惩罚。有了工具性条件作用,一个主体根据它所做的得到奖励或惩罚,因此它学会增加产生奖励行为的倾向,减少产生惩罚行为的倾向。当然,这种对应不是偶然的,因为心理学对 RL 的影响很大。

这是灵感来源系列的第二部分,所以让我们跳进兔子洞,看看如何让人们相信。

经典条件作用

我敢肯定,你们所有人都听说过伊凡·巴甫洛夫和他用狗做的实验,这是经典条件反射的最好例子,尽管在这个领域还有许多其他作品,让我们坚持到底。

巴甫洛夫博士正在研究一只狗对无条件刺激 (US)的无条件反应 (UR),分别是流涎和食物演示。当给狗一些食物时,它几乎立刻开始分泌唾液。这个过程对我们来说非常简单和直观,但这引发了一个想法,即是否可以训练狗对其他刺激做出类似的反应。

条件刺激 (CS)是狗以前不关心的东西,它可以是声音、光或基本上任何其他最初是中性刺激的东西。在巴甫洛夫的实验中,这是节拍器的声音。对 CS 的反应被称为条件反应 (CR),它有时类似于 UR,但通常开始得更早,通常更强烈。

回到巴甫洛夫的实验,在重复播放了几次节拍器的声音(CS)之后,就在展示食物(US)之前不久,狗学会了对节拍器的声音(CR)分泌唾液,就像它对食物(UR)分泌唾液一样。美国被称为“强化者”,因为它强化了铬的产生以回应铯。

巴甫洛夫实验管道

最初的中性刺激变成了条件刺激,因为狗知道它预测到了美国,所以开始产生条件刺激。

关于这个项目还有许多其他有趣的细节,但这对我们来说已经足够了。

强化学习和经典条件作用

狗的学习过程有点类似于我们如何训练一个 RL 代理。如我所说,经典条件对应于预测算法,该算法在给定的状态下预测奖励这与狗身上发生的事情非常相似(一个代理)。

状态中,当食物出现时,狗开始分泌唾液,这意味着它期待奖励。所以我们以这样一种方式构建我们的训练循环,当我们在食物演示之前引入 CS 时,有另一个状态。经过几个训练时期后,狗学会了 CS 的状态和食物之间的依赖性,因此它开始分泌唾液(表明它期待 CS 的奖励)。

就强化学习而言,我们可以把这个问题写成如下。

吃的过程本身可以设定为 RL 奖励(食物美味营养),动作会流口水,或者不流口水,̶t̶h̶a̶t̶̶i̶s̶̶t̶h̶e̶̶q̶u̶e̶s̶t̶i̶o̶n̶,即使狗不是故意的,状态是食物演示过程和节拍器的声音。

现在你知道了,当状态包括节拍器的声音时,我们的代理将会预测(垂涎)奖励

让我们引用这一领域之父的话来结束这一部分:

“很明显,在自然条件下,正常的动物不仅必须对自己带来直接利益或伤害的刺激做出反应,而且还必须对其他物理或化学机构——声波、光波等——做出反应,这些反应本身只标志着这些刺激的接近;虽然对小动物有害的不是猛兽的视觉和声音,而是它的牙齿和爪子。”——伊凡·巴甫洛夫博士。

工具性学习

与经典的条件反射实验不同,在 T2,仪器条件反射实验依赖于动物的具体行为。在经典条件反射中,无论动物的行为如何,它都会被呈现一个强化物(我们)。而这也是为什么乐器调理远比大家都知道的更接近 RL。

工具性条件反射*通常被认为与操作性条件反射**相同,后者是由 B. F .斯金纳引入的术语,但我们不打算深究差异,而是将它视为一个单一的事物。*

爱德华·桑戴克是这个领域的先驱,他用被放进“拼图盒子”*的猫做实验。这些盒子有多种变化,但理念是相同的。猫要完成一系列动作才能从盒子里出来取食物。*

桑代克对猫的实验

看,又回到食物上了。这是我们的代理人 T21 的增强剂,对所有这些实验都至关重要。正所谓“没钱没蜜”。你必须为你的代理提供某种奖励(积极的或消极的),因为没有它就无法工作。

所有这一切真正有趣的是,在几次连续的经历后,猫学会了如何更快地逃离,它们不再凭直觉(随机)行动。桑代克是这样描述的:

“在她冲动的挣扎中在盒子里到处抓的猫可能会抓绳子、环或按钮来开门。逐渐地,所有其他不成功的冲动将被消除,导致成功行为的特定冲动将被由此产生的快乐所取代,直到经过多次尝试后,猫在被放入盒子后,会立即以确定的方式抓住按钮或环。”爱德华·桑戴克博士。

所以,简单地说,猫会想出一系列的动作,引导它们走出盒子,最终它们会得到食物。但对我们来说重要的是,他们是通过桑代克发现并称之为效果法则也就是试错法来学习的。

现在让我们更关注强化学习部分,因为它有一些令人兴奋的方面。

强化学习和仪器条件作用

效果法则 描述了反映在 RL 算法中的动物学习的两个基本特征。首先,一个算法必须是选择的,,这意味着它尝试不同的动作,并通过比较它们的结果在其中进行选择。第二,算法必须是关联的,这意味着它将特定情况(状态)与在选择阶段发现的动作相关联。

**效果定律说,重要的是不仅要找到给予大量奖励动作,还要将那些动作状态联系起来。

选择过程最臭名昭著的例子是进化中的自然选择——最强的生命——但它不是相关的。关联方法的一个例子可以是监督学习,但它不是选择,因为它需要直接指令来改变它的行为。

对于 RL 算法来说,选择过程就是探索,有很多方法可以实现。例如,ε-贪婪策略,它声明一个代理以ε 的概率挑选一个随机的动作,它以 1-ε的概率挑选贪婪(选择给予最大即时奖励动作)。通过在训练期间逐渐减少ε,我们试图解决探索-开发困境,简单地说,就是什么时候应该停止探索,开始开发。

另一个好奇的事情是动机。对于工具性条件反射来说,它影响行为的强度和方向。在桑代克的实验中,是放在盒子外面的食物。每当我们的猫逃出盒子,它就会得到食物,这加强了它逃跑的行动。

当然,它并不直接对应于 RL,但奖励信号基本上就是我们所说的动机,整个技巧就是让代理人的体验获得奖励。尽管我们自己的动机是非常复杂和高度等级化的东西,我们可以得到一些想法。例如,当我们饿的时候,我们更有动力去获取食物,而当我们刚吃东西的时候,我们就没有动力了,也许我们可以把这种行为转移到强化学习中。然而,关于这一主题的作品却很少。至少据我所知,最近的一本是 Nathaniel D. Daw 和 Daphna Shohamy 的《动机和学习的认知神经科学》。

如你所见,工具性条件作用的抽象与强化学习非常相似,但它们在任何方面都不是等同的陈述。将动物行为这样复杂的东西映射到计算问题上,就像用棍子和石头解释弦理论一样。

结论

我希望这种相似性现在对你来说已经很清楚了,但是请记住 RL 方法只是受到心理学的启发,它们从来不应该严格地反映动物和人类的行为。

可能不清楚为什么所有的东西都是关于动物而不是人类的,首先,这是因为我们人类和我们的狗和猫一样都是动物。第二,我们的行为模式非常相似,但难度成倍增加,所以在我们的宠物身上做实验更容易。但是仍然有可能使用操作性条件反射来训练人,例如,谢尔顿在《生活大爆炸》中对佩妮所做的。

我们仍然有太多关于自己的探索,加入这项研究永远都不晚。也许我们,人类,真的在我们的生物学和心理学上有一些特别之处,这让我们成为了优势物种,或者也许我们只是运气好。重要的是我们学习的方式中有一个谜,我们试图用棍子和石头解释弦理论,这可能是解释我们为什么在这里的重要一步吗?

P.S. Pavlov 实际上是个好人,他养了所有的狗,并在实验后照顾它们。

TwitterLinkedIn 脸书 上与我连线并关注GitHub*!*

强化学习、大脑和心理学:延迟强化、认知地图和行为

原文:https://towardsdatascience.com/reinforcement-learning-brain-and-psychology-part-3-delayed-reinforcement-cognitive-maps-and-7d304747e62c?source=collection_archive---------29-----------------------

强化学习、人工智能和人类

延迟强化是如何工作的,通过认知地图进行知识优化,以及为什么我们的行为会随着时间而改变。

在强化学习中,以及在一般的机器学习中,特别是深度学习中,通常很难甚至不可能解释为什么事情会以这种方式发生。这被称为信用分配问题,研究人员正在努力解决这个问题,他们试图为算法开发某种推理,但到目前为止还没有运气。但是我们,人类,更好吗?我们真的知道为什么我们会做出这样的决定,为什么我们会这样做吗?

让我们设法解决它。这是 RL 灵感来源系列的第三部分,让我们深入探讨一下。

延迟强化

"拖延是不可避免的."——埃斯库罗斯。

信用分配问题在 RL 领域大放异彩。简而言之,在训练期间,一名特工多次问自己“我到底做了什么才来到这里?”。实际上,这就是他学习的方式,他捕捉到了什么样的行为会导致最高的奖励。但是当有上百个行为而你最后只得到奖励时,如何理解哪些行为是好的?而当有几十万而没人给你奖励的时候,就像发生在我们身上一样,人呢?

在强化学习中,有一种叫做资格追踪的技术,你可能已经猜到了,它是受动物研究的启发。

巴甫洛夫指出,刺激必须在神经系统中留下痕迹,资格痕迹很像我们大脑中的刺激痕迹。很难想出一个好的例子,但是让我们想象一下你的一生。关于你的童年,你能说些什么?年纪越大,记忆越淡,对吗?

为了描绘它,让我们想象你生活在̶ ̶F̶l̶a̶t̶l̶a̶n̶d̶ ̶网格区。对你来说,整个人生就是从左下角的细胞,你出生的地方,移动到右上角,你将要死去的地方。

你的整个人生轨迹

当你接近终点时,对你早期生活的记忆正在消退,但你至少还能回忆起一些事情。这是你独特的经历,这是我们知识的积累,只有最重要的部分,这就是为什么你是特别的,这就是资格痕迹是什么。

在生物层面上,在完成一个动作并收到一个奖励后,突触,即我们大脑中神经元之间的连接,具有那些随着时间流逝而衰减的临时刺激痕迹。因此,当强化被引入时,例如,在一次精彩的演讲后鼓掌,我们的大脑会对最近的行为给予更多的信任,因为对于你演讲的当前成功来说,你小时候穿什么 t 恤并不重要。

我们将在本系列的稍后部分探索神经科学,敬请关注。

但是它和延迟强化有什么关系呢?人们可以为了一份薪水工作几天,为了升职工作几年,但是我们的记忆会告诉我们为了达到这个目标我们做了什么。RL 代理也是一样,资格痕迹是他的记忆,它们告诉他重复什么动作才能获得奖励

处理信用分配问题的方法还有很多,但这个方法是最“人性化”的。如果你感兴趣,我强烈推荐你阅读关于 AlphaZero 的论文。它展示了计算机如何利用它们完美的记忆来解决信用分配问题。

认知地图

“在磁盘世界里,地图制作从来就不是一门精确的艺术。人们倾向于以良好的意图开始,然后被喷出的鲸鱼、怪物、海浪和其他无聊的制图家具弄得晕头转向,以至于经常忘记把无聊的山脉和河流放进去。”—特里·普拉切特,电影

我们还没有谈到的是无模型基于模型的算法。这一次不是关于机器学习模型之类的模型而是关于环境 s 的模型,它们是状态之间的所有转换,所有奖励动作导致那些奖励。这是非常重要的,你不应该被这些术语所迷惑。

有了无模型的,你的代理其实对他所处的环境一无所知。他在训练过程中通过试错(或者通过效果定律如果你看过我之前的文章)获得世界的所有动态。

另一方面,利用基于模型的算法,智能体从一开始就拥有关于世界的所有信息,或者他可以在与世界的交互过程中学习这些信息。所以他有一张环境的地图,明白我要去哪里吗?

向左走,你会变得富有,向右走,你会发现死亡

这种关于转场的知识和认知图谱非常相似,对于我们人类来说,是生活经验、教育等知识的积累。它们是在日常基础上下意识形成的,目的是减少记忆的使用,增强回忆和学习。但是,当然,你也可以利用思维导图、记忆宫殿等技术来有意应用它们。如果你对记忆术感兴趣的话,读一读吧。

心理学家爱德华·托尔曼在 20 世纪 40 年代对老鼠进行的实验表明,老鼠能够形成它们穿过的迷宫的潜在表征,这与 RL 特工非常相关。利用无模型算法,一个代理以及一只老鼠,必须弄清楚环境的转变,或者用我们的新术语来说,创建一个认知地图。抓住世界上发生的事情有助于他表现得更好。

所以再一次,一个环境的模型是在那个环境里面的所有转换。过渡被优化并服务于特定的目标,很像认知地图。那些过渡可以由代理自己学习(无模型算法)或者交给他(基于模型算法),他要么画地图,要么买地图。

行为

"她通常给自己很好的建议,尽管她很少遵循。"—刘易斯·卡罗尔,《爱丽丝漫游奇境记》

无模型基于模型的强化学习算法之间的区别对应于心理学家对习惯性目标导向行为模式之间的区别。习惯是由适当的刺激触发的行为模式,然后或多或少地自动执行。根据心理学家如何使用这个短语,行为是有目的的,因为它是由对目标的价值以及行动和结果之间的关系的了解所控制的。

让我们看看例子。这里我们有一个迷宫赛跑者,他正试图逃离迷宫,同时也变得富有。

迷惑

无模型算法依赖于通过多次试验获得的经验。在几次尝试后,我们的跑步者利用他的额外生命猜出了迷宫,现在知道该做什么了。我们甚至可以说,他为这个迷宫学会了一种习惯。

正如我们现在所知,使用基于模型的算法,跑步者有一张迷宫地图。通过看着它,他计划他的行动去得到最大的宝藏,然后逃跑。这里我们要说的是,利用过渡的知识和应用逐步计划,跑步者的行为目标直接

现在让我们稍微改变一下迷宫。我们会交换最大的宝藏和死亡屋的位置。

改变迷宫

如果跑步者正在应用无模型算法,他会死,因为他是在不同的环境中训练的,并且在某种程度上过度适应了它。为了解决这个变化了的迷宫,他需要再花一些时间通过试错来学习,探索这个勇敢的新世界。

但是基于模型的算法却不是这样。跑步者将会得到一张改变后的迷宫地图,并很容易找到宝藏。那就是习惯性目标导向的行为与无模型基于模型的算法之间的关系。
然而,形象地说,我们人类并没有一个离散的世界地图,所以我们应用我们的认知地图(对周围发生的事情的理解)来规划和行动,但这并不重要,因为我们只直接针对目标行事

克里斯托弗·亚当斯(Christopher Adams)在 1982 年对老鼠进行的实验表明,将老鼠放在一个有杠杆的房间里,当按下杠杆时,会释放少量食物,可以过度训练,并学会按杠杆的习惯。

将大鼠分成两组,一组训练 100 次迭代,另一组训练 500 次迭代。在第二阶段,两组人每次得到食物时,都会被注射引起恶心的毒药,因为早期的实验表明,这应该会降低他们按下操纵杆的兴趣。

未过度训练的老鼠确实开始显示出杠杆按压率的下降,这意味着它们的行为目标是直接的。相比之下,过度训练的老鼠几乎没有效果,事实上,它使它们更有活力。就好像他们忘记了食物是善意的,而现在却要求得到它。

这就是这两种行为的联系。过了一会儿,有目标的行为变成了习惯性的行为。这让我想起了我们生活中类似的时刻,当我们开始认为事情是理所当然的:金钱,健康,食物,甚至我们爱的人。

结论

我们是地球上最聪明的生物,然而我们却无法评估自己的大部分行为。我们给别人建议和教训,却不知道自己该做什么。我们说我们专注于我们的目标,惩罚坏习惯的代理人,然而我们每天都在做蠢事。然而,我们在有史以来最复杂的环境中工作,而电脑只能玩游戏。怎么会?

联系我上 推特 领英 脸书 并关注GitHub

强化学习:动态编程

原文:https://towardsdatascience.com/reinforcement-learning-dynamic-programming-2b89da6ea1b?source=collection_archive---------14-----------------------

利用动态规划在网格世界中寻找最优策略

在之前的两篇文章中,我分解了大多数人在钻研强化学习时遇到的第一件事:多武装土匪问题和马尔可夫决策过程。大多数游戏都满足马尔可夫决策过程的要求,特别是我们将要使用的游戏叫做网格世界。对于那些不熟悉的人来说,环境是一个二维网格,每个瓦片/节点要么有一个值(通常为 0,但有些变化有负值),一个死空间,或者一个结束游戏的奖励(称为终端状态)。代理能够向任何方向移动,它的目标是最大化它的报酬。我们用来估算这些回报的算法叫做动态规划。

在我们深入研究算法如何工作之前,我们首先需要构建我们的游戏(这是我的 Github 的链接,里面有我构建的所有其他算法)。要做到这一点,我们只需要 Python。我们可以使用一个类结构来创建网格世界,所以我们要做的第一件事就是建立我们需要的属性。要将一个变量实例化为网格类,我们需要给它传递三个参数,高度和重量都是控制网格大小的整数;start 是一个包含 2 个整数的元组,用于控制代理的起始位置。

从这里开始,我们需要建立一些方法,允许我们为网格设置/更新奖励、动作和状态,这样我们就可以在游戏开始和中间都使用这些值。在这之后我们只需要五个方法,我们的类就完成了。我们使用三个来简单地返回信息,例如:当前状态、状态是否结束以及游戏是否结束。在这之后,剩下的就是给我们的代理移动的能力,并在我们的游戏中创建一组所有可能的状态。

下面是我的网格布局。右角有两个终端瓷砖,中间有一个死角。您可以做的一些事情来个性化您的网格是改变大小,网格布局,或添加一个非终端的所有国家的负奖励,以激励代理人移动最少的步骤。你不应该让惩罚变得那么大,但是你可以用它来观察代理如何改变它的行为。

来源:走向数据科学

最后,我们创建了一个最终的函数网格,我们将在以后学习动态编程时导入它。这个函数简单地创建了我们的网格类对象,然后建立了哪些位置有奖励,以及如果我们不使用策略,而只是出于探索目的随机移动,可能会采取什么行动。

贝尔曼方程

正如我在之前关于马尔可夫决策过程的博客中所说,为了估计每个状态和行动的回报,我们需要求解贝尔曼方程。

来源:萨顿和巴尔托

我们可以将上面的等式分成三部分:

  • 第一个片段π(a|s),实际上并不指任何值,而是指一个策略。策略仅仅是在状态下执行动作的概率,我们的目标是调整策略以最大化代理的回报。
  • P(s ',r|s,a)是指在给定当前状态和动作的情况下,以特定状态-奖励对结束的概率。例如,网格世界有一个变种叫做风网格世界,每次你做一个动作,有 50%的概率你会采取另一个随机动作。这在现实世界中的一个应用是在信息不完全的游戏中,我们并不总是在我们想要或期望的地方结束。
  • 最后一部分[r + GAMMA * Vπ(s')]是当前奖励和给定策略π的未来状态 s '的指数衰减奖励的组合。

由于这是一个依赖于未来值的递归方程,我们需要使用动态规划来收敛到值函数的解。我们面临的另一个问题是优化我们的政策。如果 Vπ2 >Vπ1,一个策略比另一个策略“更好”,我们的最优策略标记为π*。

动态规划

动态编程实际上由两种不同的实现方式组成:

  • 策略迭代
  • 价值迭代

我将简要介绍策略迭代,然后展示如何在代码中实现值迭代。策略迭代由一个内部和外部循环组成,但在此之前,第一步是随机初始化策略,并将每个状态的值函数设置为 0。然后,我们执行被称为迭代策略评估的内部循环,在该循环中,我们遍历并迭代地更新价值函数,直到变化低于某个阈值,然后我们可以中断并继续前进。一旦发生这种情况,我们进入外部循环,在这里我们遍历每个状态,看看更新政策是否会增加我们的奖励。如果我们的策略改变,我们回到迭代策略评估,并重复这个过程,直到我们不再改变策略。

值迭代是策略迭代的替代技术,它运行起来更简单、更快,因为它只需要一个循环,而不是两个。此外,在策略迭代的前半部分,我们必须等待策略评估收敛,但在现实中,我们不需要等待这种情况发生,我们可以在策略评估步骤完成之前估计价值函数。值迭代将策略评估和迭代合并到一个步骤中,在所有可能的操作中取最大值,策略迭代使用 argmax。

资料来源:萨顿和巴尔托

代码中的值迭代

对于值迭代,我们只需要 Python、我们之前的 Grid-World 文件和 Numpy。在下面的代码中,我们的游戏是确定性的,所以我们不用担心 P(s ',r|s,a)。我们首先需要设置一个打破循环的阈值,一个惩罚未来奖励的折扣因子 Gamma,以及一个我们可以采取的所有可能行动的元组。

接下来,我们进入要运行的主代码块,开始创建网格世界对象。然后为策略随机选择动作,并为所有可能的状态初始化 0 到 1 之间的值函数。唯一的例外是始终没有策略且值为 0 的终端状态。

重复下一个代码块,直到我们的值函数收敛。

如您所见,我们浏览了所有我们有政策的州,并为最大化奖励的行动设定了价值。与策略迭代一样,我们重复这一过程,直到值函数收敛,但是,没有我们必须满足的第二个循环,所以我们可以直接进入优化我们的策略。我们只需遍历所有状态,并将策略设置为使价值函数最大化的动作。

后续步骤

虽然动态编程比暴力要有效得多,但它仍然需要一个完整的环境模型才能使用。在现实世界的场景中,甚至在更复杂的游戏中,这并不总是能实现的。在这之后,我将转向一种被称为蒙特卡罗的无模型方法,看看它如何采用不同的方法来解决网格世界,以及代理如何更接近于真正“玩”游戏。

引用作品:

https://www . udemy . com/course/artificial-intelligence-reinforcement-learning-in-python/

可视化解释强化学习(第 3 部分):无模型解决方案,循序渐进

原文:https://towardsdatascience.com/reinforcement-learning-explained-visually-part-3-model-free-solutions-step-by-step-c4bbb2b72dcf?source=collection_archive---------1-----------------------

直观强化学习系列

用简单的英语为基于价值和基于政策的解决方案所使用的技术提供可视化指南。

照片由艾丹·豪在 Unsplash 上拍摄

这是我关于强化学习(RL)系列的第三篇文章。现在我们已经了解了什么是 RL 问题,以及可用的解决方案的类型,我们现在将了解所有解决方案使用的核心技术。使用迭代算法作为框架来逐步改进预测,我们将理解基于价值和基于策略的解决方案之间的基本相似性和差异。

这里是对本系列之前和之后文章的一个快速总结。我的目标是不仅要理解事物是如何工作的,还要理解它为什么会这样工作。

  1. 基本概念和术语介绍 (什么是 RL 问题,以及如何使用马尔可夫决策过程的技术和概念(如回报、价值和政策)将 RL 问题解决框架应用于该问题)
  2. 解决方案方法 (热门 RL 解决方案概述,并根据这些解决方案之间的关系进行分类。贝尔曼方程的重要提示,它是所有 RL 算法的基础。)
  3. 无模型算法 —本文 (基于价值和基于政策的解决方案的异同使用迭代算法来逐步提高预测。剥削、探索和贪婪的政策。)
  4. Q-Learning 发展直觉,了解为什么这个算法会收敛到最优值。)
  5. 深度 Q 网络 (我们的第一个深度学习算法。一步一步地演示它是如何工作的,以及为什么做出那些架构选择。)
  6. 策略梯度 (我们第一个基于策略的深度学习算法。)
  7. 演员评论家(复杂的深度学习算法,结合了深度 Q 网络和政策梯度的最佳效果。)
  8. 惊喜话题😄(敬请期待!)

无模型算法可以是基于策略或基于值的

使用值函数来比较两个策略

正如我们在第一篇文章中所讨论的,每个策略都有两个相应的价值函数,即状态价值(或 V 值)和状态动作价值(或 Q 值),我们可以使用一个策略的价值函数来比较两个策略。如果政策 Y 的价值函数比政策 X 的高,那么政策 Y 就比政策 X 好。

通过比较策略各自的价值函数来比较策略(图片由作者提供)

最优策略

我们还讨论过,如果我们不断寻找越来越好的政策,我们最终将能够找到比所有其他政策都更好的“最佳”政策。这是最佳策略。

最优策略优于所有其他策略(图片由作者提供)

最佳政策与最佳价值密切相关

最优策略有两个相应的价值函数。根据定义,这些价值函数优于所有其他价值函数。因此这些价值函数也是最优的。最佳状态值和最佳状态-动作值。

对应于最优策略的价值函数是最优价值函数。(图片由作者提供)

这就告诉我们,找到一个最优的政策就相当于找到了最优的国家-行动值,反之亦然。通过找到一个,我们也得到了另一个,如下所示。

基于策略与基于值的算法

因此,无模型算法可以直接或间接地找到最优策略。它们是:

  • 基于状态-动作值(间接)。为了简单起见,我们将这些简单地称为“基于价值的”
  • 基于策略(直接)

无模型解决方案直接或间接找到最优策略(图片由作者提供)

基于值的算法找到最佳状态-动作值。然后可以从中得出最优策略。基于策略的算法不需要最优值,直接找到最优策略。

从最佳状态-动作值导出最佳策略

一旦基于值的算法找到了最优的状态-动作值,它如何从中找到最优的策略呢?

一旦我们找到了最优的状态-动作值,我们就可以通过挑选具有最高状态-动作值的动作来容易地获得最优策略。

我们可以从最优状态-行为值中获得最优策略(图片由作者提供)

考虑上面的例子。如果 Q1* > Q2*,那么最优策略将选择 S1 的行动 a1。

因此,π1* = 1,π2* = 0

这给了我们一个确定性的最优策略

一般来说,最优策略是确定性的,因为它总是选择最佳行动。

然而,如果两个 Q 值之间存在联系,那么最优策略可能是随机的。在这种情况下,最优策略以相等的概率选择两个相应动作中的任何一个。这通常是代理与对手进行博弈的问题。随机最优策略是必要的,因为确定性策略会导致代理人采取其对手可以轻易击败的可预测的行动。

基于状态值的预测问题算法

除了上面提到的用于解决控制问题的基于状态-动作值的算法之外,我们还有用于预测问题的基于状态-值的算法。换句话说:

  • 预测算法是基于状态值的
  • 控制算法要么基于状态-动作值,要么基于策略

无模型算法类别

查找表与函数

较简单的算法将策略或值实现为查找表,而更高级的算法使用函数逼近器(如神经网络)来实现策略或值函数。

因此,我们可以将无模型算法分为以下几类:

(图片由作者提供)

无模型算法使用迭代解决方案

RL 问题不能用代数方法解决。我们需要使用迭代算法。

有几种这样的基于值和基于策略的算法。当我开始深入研究这些算法的细节时,一开始我觉得很困惑。然而,过了一段时间,我开始意识到所有这些算法都可以归结为它们都采用的一些基本原则。

因此,相反,如果我们专注于学习这些原则是什么,那么理解这些算法如何相互关联以及它们的相似之处和不同之处将变得非常容易。

然后,当我们在后面的文章中深入每个算法的细节时,您将能够很快地看到这些共同的原则是如何被应用的,而不会迷失方向。

在一个高层次上,所有算法,包括基于值和基于策略的算法,都有四个基本操作要执行。他们从对想要寻找的数量的任意估计开始,然后通过从环境中获取数据来逐步改进这些估计。

基于值算法(以及基于策略的算法)执行这四个基本操作。(图片由作者提供)

让我们来看看这四种操作中的每一种,并比较基于价值和基于策略的方法。

1.初始化评估

第一步是初始化我们的估计。基于值的算法使用估计的最佳状态-动作值表,而基于策略的算法使用估计的最佳策略表,该表具有每个状态中每个动作的概率。

(图片由作者提供)

开始时,因为它不知道什么是正确的值,所以它简单地将所有值初始化为零。

2.采取行动

接下来,代理需要从当前状态中选择一个要执行的操作。

(图片由作者提供)

代理希望确保充分尝试所有可用路径,以便发现最佳路径,并且不会错过最佳选项。它是怎么做到的?

(图片由作者提供)

为了解决这个问题,我们需要理解探索和开发的概念。

探索与开发

探索 —当我们刚开始学习时,我们不知道哪些行为是“好”的,哪些是“坏”的。因此,我们经历了一个发现的过程,在这个过程中,我们随机尝试不同的行动,并观察回报。

探索:通过随机选择一个动作来发现新的路径(图片由作者提供)

开发 —另一方面,当模型被完全训练时,我们已经探索了所有可能的行动,因此我们可以选择将产生最大回报的最佳行动

剥削:选择最佳行动以获得最大回报(图片由作者提供)

代理需要在探索和开发之间找到正确的平衡。基于策略的代理和基于价值的代理使用不同的方法来实现这一点。

基于策略使用自己的估计来选择操作

基于策略的代理的策略表已经有了对最佳策略的持续估计,它告诉您在任何给定状态下可以采取的所有操作的期望概率。所以它只是根据估计的最优策略的概率来选择行动。行动的概率越高,就越有可能被选中。

基于政策的方法来选择最佳行动(图片由作者提供)

基于价值使用ε-贪婪策略来选择动作

基于价值的代理采用一种称为ε-贪婪的动态策略。它使用一个探索率ε,随着训练的进行而调整,以确保在训练的早期阶段进行更多的探索,并在后期阶段转向更多的开发。

基于价值的方法使用ε贪婪策略(图片由作者提供)

我们最初将ε设为 1。然后,在每集的开始,我们以一定的速率衰减ε。

(图片由作者提供)

现在,每当它在每个状态中选择一个动作时,它选择一个随机动作(即探索)与概率ε。由于ε在早期较高,代理人更有可能探索。

(图片由作者提供)

同样,以概率‘1—ε’,它选择最佳行动(即 exploit)。随着ε下降,探索的可能性变小,代理人变得“贪婪”,越来越多地利用环境。

(图片由作者提供)

3.从环境中获得反馈

代理采取它所选择的动作,并从环境中获得反馈。

(图片由作者提供)

代理以奖励的形式接收来自环境的反馈。

(图片由作者提供)

4.改进估计

代理如何使用奖励来更新它的估计,使它们变得更准确?

(图片由作者提供)

基于策略的代理使用该反馈来改进基于该回报的估计最优策略。基于价值的代理使用该反馈来改进基于该回报的估计最优值。这样,下次他们必须决定从该状态采取何种行动时,该决定将基于更准确的估计。

基于策略更新动作的概率

代理说,“如果我得到了积极的奖励,那么我将更新我的策略表,以增加我刚才采取行动的概率。”。这样,下次我就更有可能采取行动

(图片由作者提供)

基于值根据贝尔曼方程更新其值

一位基于价值的经纪人说,我之前的估计告诉我,这次行动会带来这么大的价值。基于我刚刚得到的奖励,贝尔曼方程告诉我,我的价值应该更高(或更低)。我将更新我的价值表以缩小差距。

(图片由作者提供)

我们将更深入地探讨基于价值的代理如何使用贝尔曼方程来改进它的估计。我们在第二篇文章中深入讨论了贝尔曼方程,所以最好回去复习一下。

该等式描述了计算 Q 值的递归关系。由此得出的第一个重要见解是,如果我们知道下一个状态-行动对的 Q 值,那么我们就可以利用它,而不必遍历除此之外的整个事件。

(图片由作者提供)

第二个重要的观点是,贝尔曼方程认为有两种方法可以计算状态-动作值:

  1. 一种方式是来自当前状态的状态-动作值
  2. 另一种方式是采取一个步骤的直接回报加上下一个状态的状态行动值

(图片由作者提供)

这告诉我们,我们可以通过两种不同的方式获得状态值。如果这些都是非常精确的值,这两个量就会完全相等。

但是,由于算法使用的是估计值,我们可以通过比较这两个量来检查我们的估计是否正确。

如果它们不相等,“差异”告诉我们估计中的“误差”量。

(图片由作者提供)

第一项包含一个实际奖励加上一个估计,而第二项只是一个估计。

该算法以减少误差的方式递增地更新其 Q 值估计。

(图片由作者提供)

把所有的放在一起

代理现在已经改进了估计。这就完成了四个操作的流程。该算法继续执行该流程,直到剧集结束。然后,它重新开始一个新的插曲,并重复。

(图片由作者提供)

改进估算的不同方法

该算法的核心是如何改进它的估计。不同的算法使用的技术略有不同。这些变化主要与三个因素有关:

  • 频率 —更新前前进的步数。
  • 深度 —传播更新的后退步数。
  • 用于计算更新估算值的公式

让我们简要回顾一下这些因素,了解一下这些变化是什么。

频率

在更新我们的估计之前,代理可以采取的前进步骤数有三个选项:

  • 最简单的想法是,它采取一个行动,观察奖励,保存它们,然后采取另一个行动,观察这些奖励,保存它们,并一直这样做,直到这一集结束。最后,在这一集的结尾,算法会获取所有这些奖励,并使用它们来更新我们的估计。
  • 一步——或者,我们可以只走一步,观察那些奖励,然后马上更新,而不是一直等到这一集结束。
  • N 步 —以上两个选项是谱的两端。在这之间,我们可以在 N 步之后进行更新。

(图片由作者提供)

在一般情况下,代理采取一些前进的步骤。这可能是一步,N 步,或者直到这集结束。

深度

在采取了一些前进的步骤之后,下一个问题是该算法应该在多远之前传播它的更新估计?同样,有三种选择:

  • 插曲 —如果代理向前迈出一步,直到插曲结束,算法可以更新它在此过程中采取的每个状态-动作对的估计。
  • 一步 —或者,它可以只更新当前状态-动作对的估计。
  • N 步 —以上两个选项是谱的两端。在这之间,我们可以一路更新 N 步

(图片由作者提供)

在采取一些向前的步骤之后,算法更新它所采取的状态和动作的估计。这可以是当前状态-动作对的单个步骤,N 个步骤,或者直到情节开始。

更新公式

用于更新估计值的公式有许多变化,例如:

  • 基于值的更新使用某种形式的贝尔曼方程来用“误差”值更新 Q 值。例如,这个公式用一个称为 TD 误差的误差值来递增地更新 Q 值估计。

(图片由作者提供)

  • 基于策略的更新增加或减少了代理采取行动的可能性,这取决于我们是否收到了好的奖励。

无模型算法之间的关系

如果你研究不同的算法,每个算法看起来都非常不同。然而,正如我们刚刚看到的,它们都遵循一些相似的模式。

在本系列中,我们不会深入研究每一种算法,而是将重点放在深度强化学习中常用的几种算法上。

然而,为了完整起见,我整理了一个表格,总结了这些算法之间的关系。当我学习的时候,它帮助我把事情看得更清楚了。所以我希望它对你也有帮助。

(图片由作者提供)

结论

在本文中,我们对 RL 问题的解决方案进行了概述,并探讨了一些流行算法使用的常见主题和技术。我们主要关注用于解决大多数现实问题的无模型控制算法。

我们现在准备深入研究基于神经网络的深度学习算法的细节。它们是最令人感兴趣的,因为在过去几年中,它们在解决复杂和以前难以解决的问题方面取得了巨大进展。

我们将在接下来的几篇文章中选择一种算法,从 Q 学习开始,Q 学习是深度学习算法的基础。

最后,如果你喜欢这篇文章,你可能也会喜欢我关于变形金刚和音频深度学习的其他系列。

** [## 直观解释的变压器(第 1 部分):功能概述

NLP 变形金刚的简明指南,以及为什么它们比 rnn 更好,用简单的英语。注意力如何帮助…

towardsdatascience.com](/transformers-explained-visually-part-1-overview-of-functionality-95a6dd460452) [## 音频深度学习变得简单(第一部分):最新技术

颠覆性深度学习音频应用和架构世界的温和指南。以及为什么我们都需要…

towardsdatascience.com](/audio-deep-learning-made-simple-part-1-state-of-the-art-techniques-da1d3dff2504)

让我们继续学习吧!**

每个人的强化学习

原文:https://towardsdatascience.com/reinforcement-learning-for-everyone-9c1163f61440?source=collection_archive---------36-----------------------

RL 已经在 AI 社区流行起来,但是大多数人还不知道它是关于什么的。来读吧,不管你是什么背景!

如果你在技术领域工作,尤其是在人工智能/机器学习领域,你可能已经习惯了人们不理解你的工作。这就是我的生活,我不得不说我为此感到有点自豪:因为这意味着我学到了许多大多数人不知道的东西,而且我对这个话题足够深入,能够理解对大多数人来说非常复杂的事情。然而,每当你想与你关心的人分享一项成就时,这也有点令人沮丧,因为他们无法理解所有这些模糊之处。

这就是我决定写这篇文章的原因,希望我能把我的观点传达给任何对 ML 特别是强化学习感兴趣的人,不管你的背景如何。

不,机器学习无法像电影中那样建造终结者——然而[图片来自 PublicDomainPictures 。]

巴甫洛夫条件反射

尽管当你想到人工智能时,你会想到未来,但我们的故事始于 100 多年前,19 世纪 90 年代,在伊凡·巴甫洛夫的实验室里。他在研究狗的唾液分泌,为此,他测量了狗看到食物时唾液分泌的多少,在吃食物之前是 T4。他已经对这些实验感到兴奋,但他意识到一些意想不到的事情:狗甚至会在看到任何食物之前分泌唾液。当他们注意到巴甫洛夫的助手向他们走来时,他们会开始垂涎三尺。注意到这一点后,他测试了如果在喂狗之前,他会按铃会发生什么(或者实际上是根据维基百科的节拍器),你可能猜到了:它们也开始垂涎三尺,因为它们已经知道铃响后,食物就会来了。这种铃声被称为条件刺激,因为狗不会因为铃声响而流口水,而是因为它知道食物会跟着铃声走。

最终,巴甫洛夫也受到了狗的影响。]

不错!但是我来这里是为了学习…

事实证明,RL 是基于心理学的基本原理。在 RL 中,一个智能体基于一个被称为奖励的“条件刺激”来学习如何行为。RL 的设置如下:

RL 的框架及其元素【自制。]

我们有一个代理,它位于一个环境中并与之交互,在这个环境中,它可以执行动作,同时观察环境的状态并接收对其动作的奖励。此外,我们在离散时间中解决我们的问题,所以我们的时间线是由步骤构成的;在每一步中,代理观察环境的状态,对环境执行改变环境状态的动作,并接收对其动作的奖励。

为了使它更简单,让我们考虑一个例子:我们的代理将是一个机器人,我们希望它学会走路,直到一个目标区域,所以当它到达这个区域时,我们会给它一些不错的奖励。为了到达这个目标区域,机器人可以使用不同的动作,例如:右转、左转、前进和后退。机器人将在每一步开始尝试随机的动作组合,直到它到达我们希望它到达的位置。一旦发生这种情况,我们改变它的位置并重新开始,这就像一个“的游戏”,因为机器人已经实现了它的目标,没有其他动作是可能的。这段时间从机器人处于随机位置开始,直到它到达目标区域,这被称为一个,我们将重复这些集,直到机器人知道它需要做什么才能获得好的奖励。在这之后,机器人会一直做同样的事情:导航到目标区域,因为它知道这样做,它会得到很好的回报。

但是,代理如何学习

你可能已经朝着正确的方向思考了:数学!代理的行为是由它的策略定义的,根据我们使用的方法,它可以用不同的方式来表示:一个表,一个函数,甚至是神经网络。

在 RL 最基本的情况下,称为表格 Q-learning,代理保存一个表,其中每个状态一行,每个动作一列,如图所示。该表告诉代理在给定状态下执行某个操作的预期结果,因此当环境状态发生变化时,代理会检查与给定状态对应的行,并可以选择过去回报最高的操作。每个动作和状态的值称为 Q 值。

使用表格 Q-learning 时的策略。

该表是表格 Q-learning 中的一个策略。每个 Q 值被初始化为 0,然后在每一步之后用更新规则更新其值,该更新规则基于采取行动之后收到的奖励和新状态的“有多好”。我在这篇文章中跳过了数学,以避免你们中的许多人可能不感兴趣的技术问题,但是如果你想看数学和这些值如何更新的所有细节,你可以在这里看到它们。

代理将重复情节几次,用它的新体验(状态、动作、新状态、奖励)更新它在每个步骤中的策略。一段时间后,代理人将学会一种策略,这种策略会在一集里产生很好的回报,就像一个人将学会如何玩视频游戏以获得高分一样。

事实上,视频游戏是尝试 RL 代理的非常好的环境,这就是为什么它们是 RL 最常见的用例之一。然而,视频游戏的状态通常被定义为游戏的每一帧,所以我们处理的状态空间太大,无法用表格 Q-learning 来管理,所以这是使用神经网络而不是 Q-table 的地方。这就是我们所说的深度 RL 或者深度 Q 学习,因为使用了深度神经网络。在接下来的视频中,从两分钟的论文中,你可以看到谷歌的 DeepMind 的 Deep Q-learning 的代理在玩雅达利游戏。

DeepMind 的深度 Q 学习

就是这样!

还不算太糟糕,对吧?我希望您现在对 RL 是什么以及它是如何工作的有一个(非常)宽泛的概念。如果您仍然对 RL 感兴趣,并且想要更深入地了解它,那么网上有一些令人惊奇的资料可以帮助您正确地理解它,并在代码中实现它!这些是我最喜欢的资源:

  • RL 圣经:《强化学习:导论》出自萨顿&巴尔托(在亚马逊 纸面上得到美国英国ITFR这本神奇的书包含了你需要理解和开始使用 RL 的所有信息,包括代码示例。********
  • 如何用 Python 和 OpenAI Gym 实现 RL 的教程 。如果你想实现你的第一个 RL 解决方案,这是一个很好的教程。
  • 你还在怀疑 RL 是不是适合你的方法吗?我也许能帮你解决问题。

感谢您的阅读!

一级方程式赛车策略的强化学习

原文:https://towardsdatascience.com/reinforcement-learning-for-formula-1-race-strategy-7f29c966472a?source=collection_archive---------19-----------------------

了解深度 Q-Networks 如何像 AlphaGo 学习下围棋一样学习决定进站。

本文介绍了我的实验原型一个深度强化学习代理,以帮助 f1 车队在比赛中实时优化他们的策略决策。神经网络被设计为从观察到的圈数据到控制动作和即时奖励信号的映射函数。这里介绍的概念框架是在摩纳哥大奖赛的背景下分析的,但同样的方法可以改进并推广到所有的大奖赛活动。

为什么重要?

f1 是一场没有子弹的战争,这场战争的主要武器是创新。决定比赛策略是这项运动中的黑暗艺术。车迷们通常喜欢在电视上看到的由优秀车手表演的高速机动。他们看不到的是,要获得更好的结果,需要事先做多少准备,包括使用数学模型和概率论。对于比赛策略,我们主要指以下两个关键决策:

  • 车手应该什么时候去维修站换轮胎?
  • 车队应该给赛车安装哪种轮胎?

古斯塔沃·坎波斯在 Unsplash 上的照片

轮胎在比赛中会老化,这可能会导致圈速变慢。这个过程是不可避免的,根据化合物(软、中、硬等)可以更快或更平滑。)和举行比赛的赛道。
如果圈速慢到赛车在几圈后损失的时间比停站花费的时间还多,那么轮胎可能需要更换。

如今,f1 车队使用蒙特卡洛模拟,他们在比赛前运行数小时,以便为他们的两位车手确定策略。这些模拟的工作方式是通过在不同的配置(进站圈、轮胎配方、位置等)下逐圈数千次地对比赛事件进行采样。)对有问题的车手,也对所有其他对手。由于可能情景的空间很大,他们只能运行有限数量的模拟,并且他们在这些模拟中选择能够产生最佳平均结果的策略。

国际汽联 2019 & 2020 干轮胎化合物(软、中、硬)

在赛事期间,可能会发生许多新的情况,比赛策略师有时会发现自己不得不根据人类的判断来调整他们的决策。有时这些决定很有效,并导致获得更多的冠军积分。在其他情况下,它会导致挫败感——将重要的职位让给其他做出更好决策的竞争者。

这种情况促使我思考如何教会人工智能系统玩种族策略游戏。我们的目标是帮助一级方程式车手跨越终点线,在与其他竞争团队的竞争中赢得名次(或不失去任何名次)。

RL 问题公式

强化学习(RL)是一种先进的机器学习(ML)技术,它采用了与其他机器学习方法非常不同的方法来训练模型。它的超能力在于,它可以学习非常复杂的行为,而不需要任何标记的训练数据,并且可以在为长期目标优化的同时做出短期决策。

一级方程式赛车背景下的 RL

在 RL 中,智能体通过直接与环境交互并最大化其获得的总回报来学习执行特定任务的最佳行为。在一级方程式赛车中,总奖励(回报)可以被认为是特定车手在比赛结束时获得或失去的名次。因此,如果代理认为车手在比赛结束时会获得更好的位置,它可以决定在某一圈进站并失去一些位置。

为简化起见,我们将考虑每一圈可能采取的行动如下:

  • 行动 0:软化合物的进站
  • 行动 1:中间化合物的进站
  • 行动 2:硬质化合物的进站
  • 行动 3:继续(没有中途停留)

预测与控制

将 RL 应用于 f1 比赛策略的第一个有趣想法是“控制”的概念。

强化学习中的预测任务是给出一个策略,目标是衡量它在任何给定状态下的表现。这在某种程度上类似于 F1 车队试图实现的模拟。在比赛前,他们想预测某个策略如果从第一圈就开始应用会有多好。

但是,当我们开始执行控制时,RL 中的事情变得非常有趣!控制任务是当策略不固定时,目标是找到最优行为。也就是说,在给定任何状态的情况下,寻找最优策略,总是提供使期望总回报最大化的最佳决策。在 f1 中,这将非常有趣,因为它提供了一种方法来学习如何利用非常复杂的模式,并提出实时适应每一圈的策略,并有望击败竞争中最好的策略专家。

MDP &无模型控制

让我们考虑一级方程式赛车环境中的一个状态对应于我们在下面的电视屏幕上获得的信息。

F1 电视数据频道

一个状态主要由圈数、车手排名、车手之间的时间间隔和他们的速度(最后一圈时间)以及他们的轮胎成分(软、中或硬)和年龄(圈数)来表示。也可以考虑安全车标志。此外,有一条规则要求每辆车在比赛中至少使用两种不同的干化合物。因此,我们可以为每个司机设想一个标志,表明是否使用了第二种干化合物。

一级方程式赛车可以被公式化为马尔可夫决策过程(MDP ),其中从一个状态转移到另一个状态的概率仅取决于最后观察到的状态。在第 11 圈,我们需要为下一圈做的就是我们在第 11 圈观察到的情况(第 1 圈到第 10 圈变得不那么重要了)。

"鉴于现在,未来独立于过去."

规划比赛中接下来几圈的策略可能需要一个完美的环境模型,其中我们确切地知道在状态 s 时采取行动 a 会得到什么回报,以及在行动 a 下从状态 s 转换到状态 s’的概率。但实际上,完美的环境模型很难获得,比赛期间发生的许多事件可能是随机的。想想奖励是如何依赖于其他赛车的行为,单圈时间和车手位置的不断变化。所以,我们不能使用像动态编程这样的方法。根据定义,状态值 V(s)是处于状态 s 并遵循向前发展的策略所估计的累积奖励。动态编程是一种迭代方法,依赖于这些状态值的全宽度备份。当可能状态的数量太大时,就像 f1 赛车的情况一样,成本太高。

出于这些原因,我们将依靠无模型强化学习,其主要思想是从一个状态中采样特定轨迹,通过与环境的交互来评估试错设置中的动作。

设计一级方程式赛车模拟器

最先进的强化学习通常在雅达利、国际象棋或围棋等经典游戏中演示。这些是完全可以观察到的环境,我们喜欢研究它们,因为它们可以用简单的规则来表达。它们还允许轻松地将人工智能性能与人类水平的性能进行对比。

然而,一级方程式赛车是一个现实世界的问题。这是一个不完全信息博弈,因为部分可观察。主要的挑战在于建立一个能尊重游戏逻辑和复杂规则的模拟器。

我们之前讨论了一系列可能的行动(进站和轮胎胶料)和环境状态(我们在电视上看到的信息)。这些信息可以通过 F1 转播中心和像 SBG 体育软件这样的平台提供给所有车队。我们将使用熊猫数据帧来表示环境中的每个状态。还包括进一步的信息,例如汽车的潜在步速[potential_pace]和指示第二干化合物是否已经被使用的标记[second_dry]。

f1 比赛环境中的状态示例

潜在速度是对自由空气中未被其他汽车阻挡时汽车速度的估计。它是用一个特定的函数计算出来的,考虑到了燃油质量、轮胎成分和轮胎的使用年限。

每一圈都是环境中的一个新的步骤,引入了可观察到的测量(速度、轮胎年龄、间隔等)的变化。)并能导致新的驱动程序排名。代理决定一次只对一辆车的策略。在环境中的每一步之后,奖励被计算为特定汽车获得或失去的位置的数量。

计算步长所需的一些重要工具是超越模型。这个模型为每个驾驶员提供了超车的可能性。它考虑了与前方车手的间隔、前方车手的潜在速度、相关车手的潜在速度以及一个表示赛道超车难度的参数。另一个重要的工具是花在进站上的时间,这可以从过去的比赛中学到,也可以在周末估计,这对停站后赛车的最终位置有很大的影响。

Open AI Gym 是一个开源框架,为构建和实现定制环境提供了重要帮助。建立一个能够很好地模拟 f1 比赛动态的强化学习环境是非常重要和具有挑战性的。这需要对这项运动有深刻的理解,并在编码和测试实现方面付出很多努力。为了开发和评估这种方法,我们决定像摩纳哥大奖赛一样对模拟器进行参数化,这是一条众所周知超车困难的赛道。我们使用了摩纳哥 2019 的排位赛结果来初始化发车区,并为这场特殊的比赛训练系统。

设计代理(深度 Q 网络)

在实现了环境之后,我们需要设计一个负责在每一圈推荐进站决定的代理。当与一辆特定的汽车相关联时,代理人有一个最终目标,那就是最大化该汽车可以获得的总回报。请记住,总奖励是指在整个比赛中获得或失去的名次。

Q-learning 是强化学习中使用的技术之一,用于寻找代理应该根据其调整其行为的最佳策略。对于每个州来说,通过采取特定的行动并持续遵循该政策,可以估计出总的回报。从(状态,动作)对获得的总回报被称为 Q 值。如果我们可以估计每个(状态,动作)对的 Q 值,代理将在每个状态下通过决定具有最大估计 Q 值的动作来优化行为,从而最大化总回报。

因为 Formula1 race 中可能状态的空间是无限的,所以我们无法将所有状态存储在内存中,也无法计算每个(状态、动作)组合的 Q 值。我们需要一个神经网络来逼近 Q 值函数。通常,它被称为深度 Q 网络(DQN),这个想法首先由 DeepMind 用于建立一个人工智能系统,能够比最好的人类专家更好地玩雅达利游戏。如果没有这种方法,保持计算和内存效率将变得非常困难,特别是在像 f1 赛车这样的情况下,它具有连续和高基数的特征空间。

深度 Q 网络

我们在 TensorFlow 中实现了一个密集神经网络。它将环境状态的矢量化表示作为输入,并输出每个动作的估计 Q 值。下一步行动由该网络的最大输出决定。

与简单的 Q 学习相比,有两个主要的想法使这种方法稳定:经验重放和固定的 Q 目标。

体验回放:我们将代理的体验(状态、动作、奖励、下一个状态)存储在回放存储器中,以便我们可以随机抽样成批的转换,并将它们用作训练数据。应用这种技术的主要优点是它稳定了 Q 学习方法,因为它去相关轨迹并使用神经网络的有效更新。通常在文献中,建议使用大小约为 1M 跃迁的重放存储器。然而,这个用例的最佳结果是通过使用约 15000 个转换的重放存储器的缩减尺寸和 32 个转换的批量尺寸获得的。这迫使网络在短时间内频繁且更快地从每个转变中学习,直到它明确地从重放存储器中消失,并被通过遵循改进的策略采样的新的看不见的转变所取代。

固定 Q 目标:通过使用目标网络获得用于训练该模型的目标值,该目标网络是主要行为网络的过去版本。我们在小批量学习过程中的一定数量的步骤中保持这个目标网络冻结,并教导行为网络估计这些冻结目标的 Q 值。通过选择正确的步数,然后我们更新目标网络~760 步,我们可以实现稳定的训练。

q-估计量 MSE 损失

优化的目标是最小化使用目标网络生成的目标值和使用行为网络生成的估计值之间的 MSE 损失。

我们可能认为网络将学习它自己的预测,但是因为回报 r 是无偏的真实回报,所以网络将使用反向传播来更新它的权重,以最终收敛到最优 Q 值。

在下面的例子中,我们可以观察应用于 Pierre Gasly 的汽车(气体)的 Q 网络的行为。它估计了给定状态(第 3 圈)和所有可能动作(动作 0:软坑,动作 1:中坑,动作 2:硬坑,动作 3:继续)的每个组合的总奖励。代理人估计,如果实施行动 3(继续),到比赛结束时,总奖励为+0.69 个名次。因为这个 Q 值是最高的结果,所以它将推荐动作 3 作为该特定状态的决定。根据下面估计的 Q 值列表,如果加斯利在那一圈为软化合物进站,这将使他在比赛结束时面临失去 3 个位置的风险。

多代理设置中的培训

2017 年,DeepMind 推出了 AlphaGo Zero ,这是一种强化学习算法,它在没有看到任何先前人类下棋的情况下,学会了掌握围棋的游戏。该系统开始时不知道任何技术,只通过玩自己来学习提高能力。这个想法的本质是,为了击败人类水平的性能,人工智能系统不应该受到人类知识限制的约束。

以此类推,我们可以将一级方程式赛车视为一场涉及 20 辆汽车的多人游戏,其中每辆汽车都试图在比赛结束时最大化自己的排名,并击败其他对手。如果所有其他参与者都修正了他们的策略,那么最佳对策就是针对这些策略的最优策略。因此,朝着纳什均衡优化系统是有趣的,纳什均衡是所有参与者的联合策略,使得每个参与者的策略都是最佳对策。最佳对策是解决单个代理人的 RL 问题,其中其他参与者成为环境的一部分。我们通过生成 RL 体验来填充重放存储器,其中代理正在播放其自身的旧版本。除了行为网络和目标网络之外,我们决定使用第三个网络,负责在针对特定汽车进行优化时为其他汽车做出决策。就像目标网络一样,这个对手网络是行为网络的过去版本,但是更新频率比目标网络低 10 倍(每~7600 步)。

奖励 15000 集(纳什均衡)

当训练系统与自己进行 15000 场比赛时,我们可以注意到向纳什均衡的收敛,因为对于不同的赛车和比赛轨迹,每集获得的总奖励在零附近波动。在这个过程中,该系统正在学习设计一个比赛策略,并通过自我发挥来提高自己的能力!

该图显示了在学习过程的早期阶段,系统在每圈为每辆车做出的决定。我们可以看到,这是太频繁的点蚀,这不是一级方程式中的常识,因为浪费了太多的时间。

然而,下面的图表准确地显示了系统如何学习它应该更经常地继续和优化轮胎的使用。对于每一集,我们计算除了前两圈(用于环境初始化)之外的每一个动作的圈数。请注意,系统正在学习如何增加继续决策的频率(动作 3),以及与其他更快的复合(中复合和软复合)相比,如何更少地使用硬复合(动作 2)。

在多智能体训练过程之外评估最终系统的一个好方法是将它用于一辆特定的汽车,并让它与应用于其他汽车的旧版本进行竞争。我们将使用训练了 15000 集的代理作为佩雷斯(PER)的控制代理,并使用只训练了 12000 集(80%)的同一代理来决定所有其他汽车的对手策略。知道佩雷斯在第 16 位开始了摩纳哥 2019 比赛,有趣的是看到他如何在比赛结束时按照最新的代理人行为政策获得+1 位。

基于最优代理的 PER 竞争模拟

在这种情况下,我们将代理的性能与它自己的老版本进行比较,老版本看起来也是一个强大的战略家。注意对手策略系统是如何学会为许多没有先验知识的驾驶员决定一站式策略的。它根据自己控制的每辆赛车的具体情况来决定进站圈和轮胎的选择,并设法保持车手的位置,作为纳什均衡的一部分。

对于莱科宁(RAI)来说,它决定在最快的软胎上进行两次冲刺,然后在比赛结束时停在硬胎上。这最后一次进站的原因是为了遵守在同一场比赛中使用两种不同干化合物的规则。它清楚地展示了智能体在自主学习游戏规则的同时优化其决策的能力。

更有趣的是,在与真实的比赛事件进行交互时,将代理的性能与 f1 车队决定的预定义策略进行比较。

摘要

在这项工作中,我们引入了一种深度强化学习方法,这种方法具有在比赛期间实时优化 f1 比赛策略的优势。该解决方案与经典模拟方法有一些显著的不同:

  • 比赛前采样的蒙特卡洛模拟不适应比赛期间发生的事件的现实,并且它们不能保证找到最佳策略。介绍的方法收敛到一个最佳的政策,并可以在比赛中的每一个特定圈应用,以决定最佳的可能行动。
  • 通过神经网络和函数逼近,我们大大降低了估计环境中极大量可能(状态、动作)对的值所需的计算和存储复杂性。不像传统的蒙特卡罗方法只在小的和有限的 MDP 上工作,这种方法具有可伸缩性的优点。
  • 由神经网络组成的代理被训练成在没有预先假设的情况下跨越许多代表环境状态的特征。这可能有助于了解人类难以识别的非常复杂的种族动态模式。
  • 通过一个单一的神经网络,我们可以为网格上的任何驾驶员定义一个最佳策略。这提供了控制同一个车队的两位车手和评估由比赛决定的所有行动的可能性。

RL 令人兴奋的是,该系统并不主要依赖历史数据来改善决策。它通过与环境的互动直接学习。令人惊讶的是,对于许多现实世界的应用程序来说,与环境交互是可能的。我们定义了一组行动,观察空间,并集中精力设计最方便的回报函数。一级方程式赛车策略的人工智能框架可以通过考虑安全车的概率和可能改变比赛进程的天气条件来增强。

强化学习框架

原文:https://towardsdatascience.com/reinforcement-learning-frameworks-e349de4f645a?source=collection_archive---------16-----------------------

深度强化学习讲解— 20

在 Ray 框架上使用 RLlib 解决 CartPole 环境

欢迎来到这第 20 篇文章,它总结了 " 深度强化学习讲解 " 系列,该系列提供了一种实用的方法来开始令人兴奋的深度强化学习世界。

到目前为止,在之前的帖子中,我们已经看到了相对容易编程的 RL 算法集的基本表示(尽管我们跳过了几个)。但是从现在开始,我们需要考虑 RL 算法的规模和复杂性。在这种情况下,从头开始编写强化学习实现可能会变得单调乏味,并且存在很高的编程错误风险。

为了解决这个问题,RL 社区开始构建框架和库来简化 RL 算法的开发,既通过创建新的部分,又特别是通过涉及各种算法组件的组合。在本帖中,我们将对那些强化学习框架做一个大致的介绍,并使用rl lib(Python 中的一个开源库)基于 Ray 框架解决前面的 CartPole 问题。

本出版物的西班牙语版本

[## 11.难民保护框架:Ray+RLlib

请访问第 11 页的自由介绍

medium.com](https://medium.com/aprendizaje-por-refuerzo/11-frameworks-de-aprendizaje-por-refuerzo-ray-rllib-1329e93f14ee)

强化学习框架

动机

但是在继续之前,作为一个激励的例子,让我们记住在之前的帖子中,我们提出了加强及其局限性。研究界创造了许多训练算法来解决它:、A3C、DDPG、TD3、SAC、PPO 等等。但是从头开始编写这些算法比 REINFORCE 更复杂。此外,你在这个领域参与得越多,你就越会意识到你在一遍又一遍地写同样的代码。

与深度学习等其他领域相比,强化学习的实际应用相对年轻,在深度学习中,TensorFlow、PyTorch 或 MXnet 等成熟的框架简化了 DL 实践者的生活。然而,RL 框架的出现已经开始,现在我们可以从几个项目中进行选择,这些项目极大地促进了高级 RL 方法的使用。

在介绍这些 RL 框架之前,让我们先了解一下它们的背景。

从互动中学习,而不是从例子中学习

在过去的几年中,模式识别一直是深度学习社区中许多工作和讨论的焦点。我们正在使用强大的超级计算机处理大型标记数据集(专家为训练集提供输出),并应用基于梯度的方法在这些数据集中找到模式,这些模式可用于预测或试图找到数据内部的结构。

这与我们对世界的知识的重要部分是通过互动获得的事实形成对比,没有外部老师告诉我们我们采取的每一个行动的结果会是什么。人类能够从互动和经验中发现新问题的解决方案,通过积极探索获得关于世界的知识。

由于这个原因,当前的方法将通过深度强化学习(DRL)的镜头研究从模拟环境的交互中学习的问题,这是一种从交互中进行目标导向学习的计算方法,不依赖于专家的监督。即,强化学习代理必须与环境交互以生成其自己的训练数据。

这激发了与一个环境的多个实例的并行交互,从而更快地产生更多可以学习的经验。这导致了越来越大规模的分布式和并行系统在 RL 训练中的广泛使用。这带来了许多工程和算法上的挑战,我们正在谈论的这些框架可以解决这些挑战。

开源拯救世界

近年来,TensorFlow 或 PyTorch ( 我们在本博客中广泛讨论了这两种框架)等框架已经出现,有助于将模式识别转化为商品,使深度学习更容易被实践者尝试和使用。

类似的模式也开始在强化学习领域上演。我们开始看到许多开源库和工具的出现,通过帮助创建新的部分(而不是从头开始编写),以及最重要的,涉及各种预构建算法组件的组合来解决这一问题。因此,这些强化学习框架通过创建 RL 算法核心组件的高级抽象来帮助工程师。总之,这使得代码更容易开发,阅读起来更舒服,并提高了效率。

接下来,我提供了一个最流行的 RL 框架列表。我认为读者会从使用已经建立的框架或库的代码中受益。在写这篇文章的时候,我可以提到最重要的几个(我肯定我漏掉了其中的一些):

  • Keras-RL
  • RL 蔻驰
  • 试剂
  • 射线+RLlib
  • 多巴胺
  • 张量力
  • RLgraph
  • 车库
  • 鹿
  • 极致
  • 基线
  • PFRL
  • 稳定基线

决定使用这里列出的 RL 框架中的哪一个,取决于您的偏好以及您想用它做什么。读者可以通过链接了解更多信息。

我们在研究中心使用 Acme 进行研究。但是为了描述这些环境中的一个,以便读者可以看到它们提供的可能性,我个人选择了基于 Ray 的 RLlib ,原因我将在下面解释。

RLlib:使用 Ray 的可扩展强化学习

我们使用 Acme 在我们的研究中心做研究。但是为了描述这些环境中的一个,以便读者可以看到它们提供的可能性,我选择了基于 Ray 的 RLlib ,原因我将在下面解释。

计算需求的增长

深度强化学习算法涉及大量模拟,这给深度学习本身的计算复杂性增加了另一个倍增因素。大多数情况下,这是我们在本系列中尚未看到的算法所需要的,例如分布式行动者-批评家方法或多代理方法等。

但是,即使找到最佳模型,也常常需要超参数调整和在各种超参数设置中搜索;这可能很昂贵。所有这些都需要由基于异构服务器的分布式系统(具有多核 CPU 和硬件加速器,如 GPU 或 TPU)的超级计算机提供高计算能力。

两年前,当我作为一名作者在 Medium 上首次亮相时,我已经在文章“超级计算”中解释了这种类型的基础设施是什么样的。在巴塞罗那,我们现在有一台超级计算机,名为 Marenostrum 4,计算能力为 13 Petaflops。

巴塞罗那超级计算中心明年将托管一台新的超级计算机 Marenostrum 5,它将把计算能力提高 x17 倍。

目前的超级计算机 MareNostrum 4 分为两个不同的硬件模块:一个通用模块和一个基于 IBM 系统的模块,专为深度学习和人工智能应用而设计。

在硬件方面,Marenostrum 的这一部分包括一个 54 节点集群,基于 IBM Power 9 和 NVIDIA V100,采用 Linux 操作系统,通过 Infiniband 网络以每秒 100 千兆位的速度互连。每个节点都配备了 2 个 IBM POWER9 处理器,每个处理器有 20 个物理核心和 512GB 内存。这些 POWER9 处理器中的每一个都连接到两个 16GB 内存的 NVIDIA V100(Volta)GPU,每个节点共有 4 个 GPU。

如何有效管理这种硬件结构?

系统软件堆栈

用分布式和并行系统加速强化学习在管理程序执行的并行化和分布方面引入了几个挑战。为了解决这种日益增长的复杂性,已经开始提出新的软件层,我们在现有的软件层上进行堆叠,试图在逻辑上保持系统的分层软件栈的不同组件的分离

由于这个关键的抽象,我们可以专注于不同的软件组件,今天的超级计算机合并,以执行复杂的任务。我想提一下丹尼尔·希利斯,他是开发并行连接机器的思维机器公司的联合创始人,他说抽象的层次结构是我们理解复杂系统最重要的工具,因为它让我们一次专注于问题的一个方面。

我选择的框架 RLlib 就是这种情况,它遵循分而治之的理念,对软件堆栈进行分层设计。

RLlib 的软件栈(来源: docs.ray.io )

允许这种功能抽象的这种抽象层次结构是基本的,因为它将让我们操纵信息而不用担心它的底层表示。丹尼尔·希利斯说一旦我们知道如何完成一个给定的功能,我们就可以把这个机制放在一个“积木”的“黑匣子”里,不再去想它。积木体现的功能可以反复使用,不用参考里面的细节。

光线

简而言之,并行和分布式计算是强化学习算法的主要内容。我们需要利用多核和加速器(在多台机器上)来加速 RL 应用,Python 的多处理模块不是解决方案。一些 RL 框架,像 Ray 可以很好地处理这个挑战。

在官方项目页面上,Ray 被定义为构建和运行分布式应用的快速简单框架:

  1. 为构建和运行分布式应用程序提供简单的原语。
  2. 支持最终用户并行处理单个机器代码,几乎不需要修改代码。
  3. 包括应用程序、库和工具的大型生态系统,以支持复杂的应用程序。

Ray Core 为应用程序构建提供了简单的原语。在 Ray Core 之上,除了 RLlib 之外,还有其他解决机器学习问题的库: Tune(可扩展超参数调优)、 RaySGD(分布式训练包装器)、 Ray Serve(可扩展可编程服务)。

RLlib

RLlib 是一个用于强化学习的开源库,它为各种应用程序提供了高可扩展性和统一的 API。RLlib 原生支持 TensorFlow、TensorFlow Eager 和 PyTorch,但它的大部分内部是框架不可知的。

目前,这个库已经有了大量的文档( API 文档),除了允许创建自定义算法之外,还提供了大量的内置算法。

RLlib 中的关键概念是策略、样本和训练器。简而言之,策略是定义代理在环境中如何行为的 Python 类。RLlib 中的所有数据交换都是以样本批次的形式进行的,这些样本对轨迹的一个或多个片段进行编码。训练器是将上述组件放在一起的样板类,管理算法配置、优化器、训练指标、执行并行组件的工作流等。

在本系列的后面,当我们在分布式和多代理算法方面取得更多进展时,我们将更详细地介绍 RLlib 的这些关键组件。

TensorFlow 或 PyTorch

在之前的一篇帖子中, TensorFlow vs. PyTorch:战斗仍在继续,我展示了深度学习重量级公司 TensorFlow 和 PyTorch 之间的战斗正在全面展开。而在这方面,RLlib 采取的选项,允许用户在 TensorFlow 和 PyTorch 之间无缝切换,用于他们的强化学习工作,似乎也非常合适。

为了允许用户在 RLlib 中作为后端在 TensorFlow 和 PyTorch 之间轻松切换,RLlib 包含了“框架”训练器配置。例如,要切换到 PyTorch 版本的算法,我们可以指定{"framework":"torch"}。在内部,这告诉 RLlib 尝试对算法使用策略的 torch 版本(查看 PPOTFPolicy 与 PPOTorchPolicy 的示例)。

用 RLlib 解决磁极环境问题

现在,我们将展示一个玩具示例来帮助您入门,并向您展示如何使用 RLlib 使用 PPO 算法解决 OpenAI Gym 的 Cartpole 环境。PPO 是解决增强的局限性的建议之一,由 John Schulman 等人(2017)在 OpenAI 的论文“近似策略优化算法”中介绍。但是读者可以使用本节中提出的代码来测试任何已经在这个框架中编程的算法。

这篇文章的完整代码可以在 GitHub 上找到,并且可以使用这个链接作为一个 Colab google 笔记本运行。

警告:鉴于我们正在 Colab 中执行我们的示例,我们需要在安装 ray 包并卸载 pyarrow 后重新启动运行时。

您可以通过ray.rllib.agents访问各种算法。在这里,您可以在 PyTorch 和 Tensorflow 中找到一长串不同的实现来开始使用。

如果您想使用 PPO,您可以运行以下代码:

import ray
from ray.rllib.agents.ppo import PPOTrainer, DEFAULT_CONFIGray.init()

ray.init()命令启动所有相关的光线进程。这必须在我们实例化任何 RL 代理之前完成,例如我们示例中的PPOTrainer对象:

config = DEFAULT_CONFIG.copy()
config["num_gpus"] = 1 # in order to use the GPU
agent = PPOTrainer(config, 'CartPole-v0')

我们可以在一个config对象中传递许多指定网络和训练过程应该如何配置的超参数。更改超参数就像将它们作为字典传递给config参数一样简单。查看可用内容的一个快速方法是调用trainer.config来打印出适用于您选择的算法的选项:

print(DEFAULT_CONFIG){
‘num_workers’: 2, 
‘num_envs_per_worker’: 1, 
‘rollout_fragment_length’: 200, 
‘num_gpus’: 0, 
‘train_batch_size’: 4000, .
.
.}

一旦我们指定了我们的配置,调用我们的trainer对象上的train()方法将更新并发送输出到一个名为results的新字典。

result = agent.train()

所有算法都遵循相同的基本结构,从小写缩写到大写缩写,后跟Trainer。例如,如果您想尝试 DQN,您可以拨打:

from ray.rllib.agents.dqn import DQNTrainer, DEFAULT_CONFIG
agent = **DQNTrainer**(config=DEFAULT_CONFIG, env='CartPole-v0')

从一个训练有素的代理程序计算动作的最简单方法是使用trainer.compute_action():

action=agent.compute_action(state)

该方法在将观察结果传递给代理策略之前对其进行预处理和过滤。下面是一个如何观察使用compute_action()的代理的简单示例:

def watch_agent(env):
   state = env.reset()
   rewards = []
   img = plt.imshow(env.render(mode=’rgb_array’))
   for t in range(2000):
       action=agent.compute_action(state) img.set_data(env.render(mode=’rgb_array’))
       plt.axis(‘off’)
       display.display(plt.gcf())
       display.clear_output(wait=True)

       state, reward, done, _ = env.step(action)
       rewards.append(reward)
       if done:
          print(“Reward:”, sum([r for r in rewards]))
          break
       env.close()

使用watch_agent函数,我们可以比较代理在被训练运行多个更新之前和之后的行为,为给定的数字调用train()方法:

for i in range(10):
   result = agent.train()
   print(f'Mean reward: {result["episode_reward_mean"]:4.1f}')

最后一行代码显示了我们如何监控包含在方法train()的返回中的训练循环打印信息。

训练前

训练后

这是一个简单算法的玩具实现,非常简单地展示了这个框架。RLlib 框架的实际价值在于它在执行固有并行的大型基础设施中的使用,同时,从头开始编写代码的复杂算法是完全不可行的。

正如我所说的,在看了上面提到的所有其他框架之后,我选择了 RLlib。原因是多样的;有些已经在本帖中介绍过了。给我加上那个;相关的是,它已经被包括在主要的云提供商中,如 AWS 和 AzureML 。或者有一个像 ANYSCALE 这样的推动公司已经筹集了2000 万并组织了 射线峰会 会议,该会议将于本周(9 月 30 日至 10 月 1 日)在网上举行,并有伟大的演讲者(如我们的朋友Oriol Vinyals;-).也许可以添加更多的背景细节,但对我来说,与上述原因同样重要的是,有来自加州大学伯克利分校的伟大研究人员参与其中,包括有远见的扬·斯托伊察,我在 Spark 的问题上见过他,他们显然是对的!

从这里去哪里

我希望这些帖子能够鼓励读者了解这项令人兴奋的技术,它是人工智能领域最新突破性进展的真正推动者。我们真的没有看到太多,只是最基本的,让你继续自己发现和享受这个神话般的世界。以下参考资料可能有用。

  • 理查德·萨顿和安德鲁·巴尔托。 强化学习:导论 ,麻省理工出版社,2018。【incompleteideas.net 在线】。Python 代码的相关独立回购。
  • 米格尔·莫拉莱斯。 摸索深度强化学习 。曼宁,2020。
  • 亚历山大·宰和布兰登·布朗。 深度强化学习在行动 。曼宁,2020。
  • 马克西姆·拉潘。 深度强化学习 。帕克特出版有限公司,第二版,2020 年。
  • 迈克尔·兰哈姆。 游戏动手强化学习 。帕克特出版社,2020 年。
  • 菲尔·温德。 强化学习、工业应用和智能代理 。奥瑞丽媒体公司,2020 年。
  • Sudharsan Ravichandiran。 深度强化学习用 Python 。帕克特出版有限公司,第二版,2020 年。

在线资源

  • 大卫·西尔弗在 RL 上的 UCL 课程
  • 由谢尔盖·莱文创作的加州大学伯克利分校 CS 285
  • 哈多·范·哈瑟尔特的《UCL》
  • 斯坦福 CS234,作者艾玛·布伦斯基尔
  • 马里奥·马丁的 UPC 巴塞罗那理工学院
  • 滑铁卢大学 CS 885,作者帕斯卡·普帕特
  • 彼得·阿比尔等人的伯克利 DRL 训练营
  • Xavier giróI-Nieto 等人的 UPC 巴塞罗那技术公司
  • Josh Achiam 的 OpenAI
  • 莉莲翁:一(长)窥强化学习
  • 证件代码
  • Alex Irpan:有点见地:深度强化学习还没起作用
  • Andrej Karpathy 博客:从像素进行深度强化学习

深度强化学习讲解系列

UPC 巴塞罗那理工 巴塞罗那超级计算中心

一个轻松的介绍性系列以一种实用的方式逐渐向读者介绍这项令人兴奋的技术,它是人工智能领域最新突破性进展的真正推动者。

[## 深度强化学习解释-乔迪托雷斯。人工智能

本系列的内容](https://torres.ai/deep-reinforcement-learning-explained-series/)

关于这个系列

我在五月份开始写这个系列,那是在巴塞罗那的封锁期。老实说,由于封锁,在业余时间写这些帖子帮助了我 #StayAtHome 。感谢您当年阅读这份刊物;它证明了我所做的努力。

免责声明 —这些帖子是在巴塞罗纳封锁期间写的,目的是分散个人注意力和传播科学知识,以防对某人有所帮助,但不是为了成为 DRL 地区的学术参考文献。如果读者需要更严谨的文档,本系列的最后一篇文章提供了大量的学术资源和书籍供读者参考。作者意识到这一系列的帖子可能包含一些错误,如果目的是一个学术文件,则需要对英文文本进行修订以改进它。但是,尽管作者想提高内容的数量和质量,他的职业承诺并没有留给他这样做的自由时间。然而,作者同意提炼所有那些读者可以尽快报告的错误。

我们在 DRL 的研究

我们在 UPC 巴塞罗那理工巴塞罗那超级计算中心 的课题组正在做这个课题的研究。我们在这一领域的最新论文是在第 37 届国际机器学习会议(ICML2020) 上发表的“探索、发现和学习:状态覆盖技能的无监督发现”。提出了一种新的强化学习无监督技能发现范式。是我们博士生之一的 @vcampos7 和 @DocXavi 共同建议的最后一篇投稿。本文由来自 Salesforce Research 的 @alexrtrott 、@蔡明雄、 @RichardSocher 共同撰写。

几行代码中的强化学习

原文:https://towardsdatascience.com/reinforcement-learning-in-a-few-lines-of-code-d6c8af1e0fd2?source=collection_archive---------13-----------------------

强化学习

使用稳定基线和 Gym 训练 SOTA RL 算法

从 Procgen 检索

强化学习在过去的一年里有了很大的改进,最先进的方法每两个月出现一次。我们已经看到 AlphaGo 击败世界冠军围棋手柯洁,多智能体玩捉迷藏,甚至 AlphaStar 在星际中也竞技性地守住了自己。

实现这些算法可能非常具有挑战性,因为它需要对深度学习和强化学习有很好的理解。本文的目的是给你一个使用一些简洁的包的快速入门,这样你就可以很容易地开始强化学习。

关于如何实现 SOTA 深度强化学习算法的深入教程,请参见本和本。强烈推荐他们!

环境

在我们开始实现这些算法之前,我们首先需要创建一个工作环境,即游戏。对于算法来说,理解什么是动作和观察空间是很重要的。为此,我们将进入几个可用于选择有趣环境的包。

体育馆

Gym 是一个开发和比较强化学习算法的工具包。它通常用于实验和研究目的,因为它提供了一个简单易用的环境工作界面。

简单地用pip install gym安装包。完成后,您可以使用以下代码创建一个环境:

import gym
env = gym.make(‘CartPole-v0’)

推车环境中,你的任务是防止通过未启动的接头连接到推车上的杆子翻倒。

env变量包含关于环境(游戏)的信息。要了解侧手翻的动作空间是什么,只需运行env.action_space就会产生Discrete(2)。这意味着有两种可能的独立动作。要查看观察空间,您运行env.observation_space,这将产生Box(4)。这个方框表示 n (4)个闭区间的
笛卡儿积。

要渲染游戏,请运行以下代码:

我们可以看到,如果我们选择采取随机行动,购物车就会不断失灵。最终,目标将是运行一个强化学习算法,学习如何解决这个问题。

有关健身房环境的完整列表,请参见本。

注意:如果您在运行雅达利游戏时遇到问题,请参见本。

重新流行

创造有趣环境的另一个选择是使用复古。这个包是由 OpenAI 开发的,允许你使用 ROMS 来模拟游戏,如空袭者-创世纪。

只需用pip install gym-retro安装软件包即可。然后,我们可以通过以下方式创建和查看环境:

import retro
env = retro.make(game='Airstriker-Genesis')

再次,为了渲染游戏,运行下面这段代码:

要安装 ROMS,你需要找到相应的。sha 文件,然后运行:

python3 -m retro.import /path/to/your/ROMs/directory/

注意:要获得可用环境的完整列表,运行retro.data.list_games()

宝洁公司

强化学习的一个典型问题是,产生的算法通常在特定环境下工作得很好,但无法学习任何通用的技能。例如,如果我们要改变一个游戏的外观或者敌人的反应呢?

为了解决这个问题,OpenAI 开发了一个名为 Procgen 的包,它允许创建程序化生成的环境。我们可以用这个包来衡量强化学习代理学习一般化技能的速度。

渲染游戏很简单:

这将生成一个可以训练算法的单一级别。有几个选项可用来有步骤地生成同一环境的许多不同版本:

  • num_levels -可以生成的独特级别的数量
  • distribution_mode -使用哪种级别,选项为"easy", "hard", "extreme", "memory", "exploration"。所有游戏都支持"easy""hard",而其他选项则是游戏特有的。

强化学习

现在,终于到了实际强化学习的时候了。虽然有许多可用的软件包可以用来训练算法,但由于它们的可靠实现,我将主要进入稳定的基线。

请注意,我不会在这篇文章中解释 RL 算法实际上是如何工作的,因为这需要一篇全新的文章。有关 PPO、SAC 和 TD3 等最新算法的概述,请参见本或本。

稳定基线

稳定基线 (SB)基于 OpenAI 基线,旨在使研究社区和行业更容易复制、提炼和识别新想法。他们在基线的基础上进行改进,以制作一个更加稳定和简单的工具,允许初学者在不被实现细节所困扰的情况下尝试强化学习。

由于 SB 能够简单快速地应用最新的强化学习算法,因此经常被使用。此外,创建和训练 RL 模型只需要几行代码。

安装可以简单地通过pip install stable-baselines完成。然后,为了创建和学习一个 RL 模型,例如, PPO2 ,我们运行下面几行代码:

有几件事可能需要一些解释:

  • total_timesteps -用于训练的样本总数
  • MlpPolicy -实现 actor-critical 的策略对象。在这种情况下,一个多层感知器有 2 层 64。还有针对视觉信息的策略,例如CnnPolicy甚至CnnLstmPolicy

为了将这个模型应用到 CartPole 示例中,我们需要将我们的环境包装在一个假人中,以使它对某人可用。在 CartPole 环境中训练 PPO2 的完整示例如下:

正如我们在上面的图片中看到的,仅用了 50,000 步,PPO2 就设法找到了保持杆子稳定的方法。这只需要几行代码和几分钟的处理时间!

如果要将其应用于 Procgen 或 Retro,请确保选择允许基于卷积的网络的策略,因为观察空间可能是环境当前状态的图像。

最后,横翻筋斗的例子非常简单,只需 50,000 步就可以完成。大多数其他环境通常需要数千万个步骤才能显示出显著的改进。

注意:稳定基线的作者警告初学者,在产品中使用这个包之前,要很好地理解强化学习。强化学习有许多至关重要的组成部分,如果其中任何一个出错,算法就会失败,并可能留下很少的解释。

其他包

还有其他几个常用于应用 RL 算法的软件包:

  • [TF-Agents](https://github.com/tensorflow/agents) -比稳定基线需要更多的编码,但通常是强化学习研究的首选包。
  • 用 Pytorch 用最少的代码实现了最先进的 RL 算法。这无疑有助于理解算法。
  • [DeepRL](https://github.com/p-christ/Deep-Reinforcement-Learning-Algorithms-with-PyTorch) -另一个 Pytorch 实现,但是这个版本还实现了额外的环境来使用。
  • [MlAgents](https://github.com/Unity-Technologies/ml-agents) -一个开源的 Unity 插件,支持游戏和模拟作为训练代理的环境。

结论

强化学习可能是一个棘手的问题,因为如果代码中出现问题,很难调试。希望这篇文章能帮助你开始强化学习。

所有代码都可以在以下位置找到:

[## MaartenGr/强化学习

使用 Stable-baselines、Gym、Retro 和 Procgen 在动态环境中创建最先进的强化学习算法。

github.com](https://github.com/MaartenGr/ReinforcementLearning)

如果你和我一样,对人工智能、数据科学或心理学充满热情,请随时在 LinkedIn 上添加我。

自主赛车中的强化学习

原文:https://towardsdatascience.com/reinforcement-learning-in-autonomous-race-car-c25822def9f8?source=collection_archive---------25-----------------------

“邀请所有有志 RL 从业者”系列第 2 集

菲利普·维特在 Unsplash 上拍摄的照片

在本系列的第一部分中,我们已经了解了强化学习(RL)中的一些重要术语和概念。我们还学习了 RL 在高层是如何工作的。

在我们深入研究 RL 背后的理论之前,我邀请你和我一起了解基于其超级酷的应用程序 AWS DeepRacer 的 RL。

什么是 AWS DeepRacer?

AWS DeepRacer 是一款 1/18 比例的自主赛车,旨在通过在物理赛道上比赛来测试 RL 模型。AWS DeepRacer 中有三种比赛类型:

  1. 计时赛——代理在没有固定障碍物或移动竞争者的标记清晰的跑道上与时间赛跑。
  2. 物体回避——车辆在双车道轨道上行驶,轨道上放置了固定数量的固定障碍物。
  3. 短兵相接的比赛——车辆在双车道赛道上与其他行驶中的车辆进行比赛。

AWS DeepRacer 中的强化学习

我假设你熟悉 RL 在高层是如何工作的。如果您不知道,请查看本系列的第一篇文章以了解更多信息。

RL 如何在 AWS DeepRacer 中工作的基本想法。[图片由作者提供]

在 AWS DeepRacer 中,我们希望我们的车辆( agent )在赛道(环境)中独自比赛,同时获得最大的累计总奖励,以便我们可以实现我们的目标——赢得与时间的比赛,或避开所有障碍,或赢得与另一辆车的比赛。

因此,它被归类为一个阶段性任务,其最终状态可能是终点线或脱离轨道。

国家呢?这里,状态是由车辆上的前置摄像头捕获的图像。车辆将以大约 15 fps 的速度拍摄图像(160x120)。

杰克·布吕克在 Unsplash 上拍摄的照片

在现实驾驶体验中,我们可以“平稳”地控制速度和转向角度,而在这里,我们只能“艰难”地控制它们。换句话说,动作空间是一组离散的动作。

需要注意的是:动作空间越细,模型收敛的时间就越长。

AWS DeepRacer 行动空间示例。[图片来自 AWS DeepRacer 控制台]

至于奖励,它是由一个奖励函数返回的,这个函数只是一个 Python 函数,它将基于捕获图像的一些参数(状态)作为输入。AWS DeepRacer 中有几个重要参数:

  1. 轨道上的位置
  2. 标题
  3. 航点
  4. 磁迹宽度
  5. 离中心线的距离
  6. 所有车轮都在轨道上
  7. 速度
  8. 转向角度。

我们可以利用这些参数作为我们自己定义的奖励函数的输入。请参见文档以了解所有可用参数的更多信息。

培训过程怎么样?

培训的目标是找出在所有可能的未来驾驶决策中,哪种状态下的哪种行动将导致最大的预期累积奖励。

换句话说,网络必须计算出车辆在每种状态下应该获得多少速度转向角,这样我们才能获得最大预期累积回报

杰克·吉文斯在 Unsplash 上的照片

但是……网络是什么?

在 MDP(马尔可夫决策过程)中,政策是在开始时给我们的,而在 RL 中不是。这里,我们利用神经网络(NN)来帮助我们创建一个策略网络。神经网络的输出是每个可能动作的概率。

在 AWS DeepRacer 中,NN 模型基本上是 CNN +前馈 NN,它接收来自特定剧集的经验(超参数)作为输入。一旦模型被训练,它将结果发送回代理以收集更多的经验。

神经网络架构。[图片由作者提供]

在训练过程中,网络将发现哪种行为更有可能给予更多奖励,这取决于熵超参数。熵(随机程度)告诉代理探索更多的动作,或者只利用已经被理解的动作。

熵越大,代理采取的行动就越随机。

根据探索-开发策略,车辆仍可能有小概率采取随机行动来探索环境。RL 这里有一篇关于熵的好文章。

关于 AWS DeepRacer 的更多信息

AWS DeepRacer 令人兴奋的部分之一是车库。我们可以定义我们的车辆配置:要使用的传感器、动作空间(速度和转向旋转可变性)、车辆的颜色和车辆的名称!

最后的话

照片由安东·大流士在 Unsplash 拍摄

恭喜你坚持到这一步!!

看完这篇文章,你应该知道 RL 是如何应用在自主赛车上的。请记住,我们的 RL 之旅仍处于早期阶段!我还有很多材料要和大家分享。所以,如果你喜欢这些内容,并想在接下来的两个月里继续和我一起学习,请关注我的媒体账号,以获得关于我未来帖子的通知!

我们将在下一篇文章中了解更多关于 RL 算法分类的鸟瞰图。来看看!

关于作者

Louis Owen 是一名数据科学爱好者,他总是渴望获得新知识。他在印度尼西亚最好的大学之一Institut Teknologi Bandung攻读数学专业,并获得了最后一年的全额奖学金。最近,2020 年 7 月,他刚刚以优异的成绩毕业。

Louis 曾在多个行业领域担任分析/机器学习实习生,包括 OTA()、电子商务( Tokopedia )、FinTech ( Do-it )、智慧城市 App ( Qlue 智慧城市 ),目前在 世界银行 担任数据科学顾问。

去路易斯的网站了解更多关于他的信息吧!最后,如果您有任何疑问或需要讨论的话题,请通过 LinkedIn 联系 Louis。

约翰·康威的强化学习

原文:https://towardsdatascience.com/reinforcement-learning-in-honor-of-john-conway-5d15fb394c63?source=collection_archive---------49-----------------------

照片由肯尼·罗在 Unsplash

为哲学家的足球创造一个人工智能球员

哲学家的足球是由已故的传奇数学家约翰·康威(病毒的另一个受害者)发明的棋盘游戏。为了纪念他,我建了一个网站,你可以在这里玩游戏,了解更多关于这个游戏的信息。

你可以在网上或本地找其他人一起玩,你也可以和一个人工智能玩家对战来感受游戏。虽然在写这篇文章的时候,人工智能还在训练中——可能需要几个星期才能有所进步。

我今天的目标是快速解释这个游戏,并涵盖足够的强化学习基础知识,以解释我正在使用的 TD(λ)算法的定制修改,我称之为交替 TD(λ)。顺便说一下,TD 的意思是“时间差异(学习)”,而λ是一个超参数,用于设置“资格轨迹”的衰减(类似于动量)。这些将在下面解释。

在 PyTorch 中实现是从零开始的,你可以在 Github 上找到代码。我选择不使用像 OpenAI Gym 这样的强化学习框架,因为算法相对简单。对于一个定制的“环境”(例如游戏)和修改的算法,框架增加了比它们解决的更多的复杂性。

作为背景,我假设你熟悉 PyTorch 和神经网络的一些基础知识,特别是它们是什么以及在随机梯度下降(SGD)(带动量)中使用的反向传播。当前的实现使用了残差(卷积)神经网络,本质上是一个较小版本的 ResNet ,但这对理解本文并不重要。没有强化学习的先验知识。

本文的其余部分简要介绍了这个游戏,然后进入强化学习的基础。从那里,它涵盖了时间差异学习和资格跟踪的基础。最后,它涵盖了我在一个对称的双人棋盘游戏中使用的修改,我称之为交替 TD(λ)。

哲学家的足球

我在哲学家.足球为这个游戏建了一个网站,所以你可以亲自体验一下。言语不能公平对待一切。要有感觉,你可以阅读规则,然后在沙盒模式下玩(对自己),或者对像 RandoTron 这样的基线机器人,他总是随机玩。

否则,这里有一个精简版的规则,删除了一些细节。在一个像围棋棋盘一样的 19x15 的棋盘上(通常用于游戏),放置石头。只有一块白色的石头,球。黑石是“玩家”。两个对手传统上被称为 X 和 O。X 和 O 都可以放置一个球员或在他们移动时将球跳过一些球员。如果球停在或越过最右边的一栏,x 获胜;o 赢在左边。

这个游戏是约翰·康威在剑桥玩的,并在一本名为 的书中描述了数学游戏 的获胜方式。它是以一个搞笑的巨蟒剧团的小品命名的。康威最出名的可能是他的生命游戏和有限单群的分类工作,但是他一生中还做了许多其他有趣的事情!

当我读到康威的病毒消亡时,在考虑强化学习问题之前,我选择了这个游戏。但是这个游戏后来被证明有一个非常有用的对称性,这将大大简化下面讨论的强化学习。

考虑这样一种情况,你扮演 X,该你走了。你要考虑 O 对你的行动的反应。在你移动之后,轮到 O。现在,如果我们将棋盘转到的位置,又轮到你了,你向右打(如 X)。因为两个玩家使用完全相同的棋子,所以理解如何评估你作为 X 面对的位置与理解你作为 o 面对的位置是完全相同的。

这与井字游戏、国际象棋或围棋等游戏略有不同,例如,在这些游戏中,你可能想在你移动之后使用你对位置的评估来告知你有多喜欢在你移动之前的位置(反之亦然)。有其他方法来解决这个问题,但哲学家的足球有这个很好的对称性,消除了它。

强化学习基础

我在这一节的目标不是写一篇关于强化学习的完整介绍。相反,我的目标是“尽可能简单,但不要更简单”,因为我们解释(交替)TD(λ)算法的目的有限。特别是(对于那些了解内情的人来说),一个两人输赢的游戏不需要奖励( R )或者折扣率(γ),所以我会假装这些不存在。游戏不是随机的,所以只处理确定性的情况。我们也不会谈论 Q 学习或政策梯度。

国家(年代)

这是设置。对我们来说有状态 S. ,每一个都是假设 X 要移动的棋盘位置。我们可以假设 X 按照上面讨论的对称性移动。如果只计算游戏还没有结束的状态,可能的状态(#S ≈ 10⁸⁸)比宇宙中的原子要多得多。当然,大多数状态在实际游戏中是不太可能出现的。

还有两种游戏结束的“终结”状态。一个用于 X 获胜的情况,一个用于 o。导致两者之一的所有位置(分别)是相同的。

时间(吨)

现在一个游戏由不同时间的一系列状态组成。将时间标记为 t ,游戏开始时 t=0,第一步棋后 t=1,依此类推。此外,让 t=∞表示游戏的结束(尽管它实际上并不花费无限的时间)。

我们将用下标表示不同时刻的状态。例如,Sₒ是游戏开始时的状态。同样,下标 1、t 或∞。

行动(一)

给定一个状态 S,有一组可能的行动(移动)可以由轮到它的玩家采取(再次,我们将总是考虑 X 来玩)。表示这组动作 A(S) ,因为它取决于状态。单个动作将用小写字母表示为 a.

在上下文中,一个动作或者是放置一个棋子(最大可能的 19⨉15–1=284),或者是一个可用的跳转(如果你适当地安排棋子,可能有很多可能的跳转)。对于一个终端状态(游戏结束),动作集合将被视为空。

和以前一样,我们将使用下标来表示给定时间的动作集,或在给定时间采取的动作。例如,Aₒ = A(Sₒ)是开始时可能的动作的集合(284 个可能的位置,没有可能的跳跃)。同样, a ₒ是在时间 0 采取的动作,即第一步动作。

政策(π)

政策 π 是玩游戏的核心意义。给定一个状态 S,你必须选择一个要采取的行动!

现在,即使在像“哲学家的足球”这样确定的完美信息游戏中,政策也可能是随机的(有点随机)。考虑一下“约翰·康威会演奏什么”的政策。换句话说,给定一个状态 S,X 要移动,约翰·康威会怎么移动?不管是什么,放那个。

现在,这个康威政策并不简单(祝你在电脑上评估它好运)。但这肯定是一项政策。⁴:它也不是决定性的。(大多数)人并不总是在相同的位置做出相同的动作。这首先会很难记住,其次会很无聊。

因此,我们将认为该策略是一个函数 π(a|S) 给出采取行动 a概率,给定状态 S。注意,我们必须知道行动 a 是合法的行动( a∈ A(S))。此外,不会为终端(游戏结束)状态定义策略功能。

现在做事情,非确定性往往会让事情变得更复杂,而不会更有启发性。因此,请随意考虑策略函数只是将一个状态作为输入,并将一个动作作为输出的情况。

价值函数

有一个值函数 v(S) 将状态 S 作为输入并返回“值”在我们的例子中,这个值将是玩家获胜的概率。它的值介于 0 和 1 之间。

我们还必须加上一个限制,即在两个终端(游戏结束)状态下评估的价值函数在 O 获胜时总是 0,在 X 获胜时总是 1。(这是因为我们可以假设我们总是根据对称性来计算 X)。

现在,价值函数有几种风格(在左边)。在确定性完全信息博弈中的完美博弈中,博弈必然以 X 赢、输或无限循环结束,我们称之为有价值的平局。出于我们的目的,我们可以假设第三种情况永远不会发生。

给定一个策略π,假设对手也在玩同样的策略,有一个“理想”函数,正好决定了获胜的概率,一个 0 到 1 之间的数。如果策略是确定性的,获胜的概率要么是 0,要么是 1(忽略平局情况)。

不幸的是,如果我们知道如何完美地演奏,就没有必要训练计算机来演奏了。此外,理想函数在计算上很难处理:

  1. 如果它是一个有输入/输出值的简单表格,那么每个状态都必须有一个条目,其中大约有 10⁸⁸——比宇宙中的原子还多。
  2. 没有任何已知的数学函数可以简化计算(尽管你可以试着找到一个)。
  3. 最后,我们可以通过模拟(玩游戏)精确地计算出理想函数。但是如果π是随机的,这将花费太长时间来得到一个精确的答案。
  4. 如果π是确定性的,那么理想函数仍然不会有用,因为它不会告诉我们如何学习,也就是让π变得更好。

因此,取而代之的是,我们将使用近似值函数,此后我们仅将其称为 v 。最常见的是,近似值函数可以用神经网络来实现,这就是我们要做的。

学问

到目前为止,我们所做的就是建立一个上下文和一些符号。我们还没有描述我们的 AI 玩家将如何学习来玩一个更好的策略。(当然)有多种算法可以做到这一点。粗略地说,学习算法可以尝试直接学习策略函数π(策略梯度)。它可以尝试学习决定哪些行动是最好的(Q-learning)。或者它可以只学习价值函数——简单地学习一个职位有多好。我们只讨论最后一种情况。

在这种情况下,给定一个价值函数 v ,我们可以让我们的政策“选择一个我们认为对我们最有利的结果。”特别是,由于我们的博弈是确定性的,选择一个动作 a 就相当于在时间 t+1 选择下一个状态 S。因此,稍微滥用符号,将π视为从状态到动作的简单函数:

在π(a|S)符号中,如果 a 是最佳移动,则π为 1,否则为 0。

注意,我们暂时忽略了处理在 X 之后是 O 的事实,我们说过所有的状态都假设 X 是 0。目前,价值函数在概念上是 X 对他们获胜可能性的估计,给定状态 S 包括关于谁要移动的信息。

概述

我们的 AI 玩家遵循某种策略π,它在时间 t 采取状态 S 并确定一个动作(移动)a–或者给出单个移动或者每个移动的概率还有一个价值函数 v 来估计我们在给定状态下,遵循策略π时获胜的概率。反过来,如果π是“选择最佳移动”(或几个最佳移动的概率分布),那么我们可以将 v 视为一等对象,并从中导出π。我们的学习问题简化为一个很好的估计

以下是我们定义的符号及其简要解释。

时间差异学习:TD(0)

所以我们已经建立了强化学习的基本环境。我们的目标是估计一个价值函数 v. 在每一步,人工智能玩家只需选择产生最佳结果值(即获胜概率)的一步。这是一种确定性策略,但是我们可以通过给出前 3 或 5 步的概率分布或其他方法来使它变得随机(不那么无聊)。

现在我们要如何学习 v ?现在,让我们考虑这样一种情况,即 v 仅仅是一个巨大的表,其中包含所有可能的状态及其值。这里在计算上是不可能的,但是概念上很简单。

下面是我们可以对学习算法进行升级的列表,从显而易见的开始,向聪明的方向前进。

  1. 评估 v(S) 的最简单方法是采用确定性策略。给定一个状态,玩游戏,看看谁赢。
  2. 如果策略不是确定性的,我们可以模拟一些游戏,从每一步的概率分布中取样。总的来说,我们将产生一个可能的游戏样本,我们可以用它来估计获胜的概率。这些被称为蒙特卡罗方法。
  3. 我们可以利用这样的事实:在从状态 S 移动 a 导致新的状态 Sʹ 之后,我们已经知道了新的值 v(Sʹ).为了保持一致,如果我们做出最佳选择,我们希望 v(S) = v(Sʹ).这被称为自举(见下面的等式)。不要与来自统计学或 web 框架的术语相混淆。
  4. 一般来说,我们可以混合搭配选项(2)和(3):我们可以模拟出 3 个步骤,然后自举,或做两者的线性组合。

用 TD(0)自举价值函数估计

选项 3,时间差异学习也称为 TD(0),是学习真正发挥作用的地方。我们经历了一系列的状态,每一步我们都更新我们对 v(S)的估计,以匹配我们对 v(Sʹ).的估计一般来说,我们从一个用随机数或零初始化的表开始,并用学习速率α进行更新。我们引入一个时间差δ 并进行如下更新:

用学习率α更新时间差

仔细注意下标。我们的价值函数 v 现在在每个时间步都发生变化,所以我们必须跟踪我们在哪个时间步进行评估。

政策外学习

如果我们的机器人只是一遍又一遍地玩同样的动作,所有这些都会很无聊。它需要尝试不同的动作,看看他们是否有任何好处。这被称为勘探-开发权衡,涉及的内容很多,所以我就不多谈了。

我们的 TD(0)算法的一个好处是,当我们与机器人对弈并学习近似值函数 v 时,我们可以随机移动而不进行更新。这使得尝试新动作变得非常简单。蒙特卡罗方法遇到了问题,因为你必须在政策下模拟整个游戏来了解它们。如果你在中间做了一个随机的(很可能是坏的)移动,你必须试着弄清楚它如何影响你对早期移动的估计。这是可能的,但也有不好的一面(主要是高方差)。

使用神经网络

上面我们考虑了函数 v 只是一个数值表的情况。为了更新 v(S) ,我们只需改变表中的值。如上所述,这种表格方法在计算上对于哲学家的足球是不可能的。所以我们需要将 v 升级为神经网络。它将把状态的某种表示作为输入,如一个张量或一列张量。并且它将产生 0 和 1 之间的数字作为输出。我们需要在每次 t. 时添加一组参数(网络权重) w ,因此我们将 v 的定义阐明为如下所示:

我们需要修改我们的更新算法以使用反向传播:

基于神经网络的时间差分学习

请注意以下几点:

  • 我们使用梯度上升。我们想要使 v(S) 更接近v(sʹ),而不是最小化它的值(如在标准随机梯度下降中)。这一更新的结果是:

  • 如往常一样,梯度∇v 是 v 在时间 t 相对于参数 w 的(分量)导数,在预先存在的 wS 处评估。
  • 在更新之后,不能保证在任何其他状态下评估 v。希望神经网络学习一种状态表示,使其能够概括,就像在任何其他应用中一样。

合格痕迹:TD(λ)

在随机梯度下降中,资格轨迹本质上是动量,但在强化学习中,它们被不同地激发并有不同的解释。它们允许我们保持 TD(0)算法的简单性,但获得使用蒙特卡罗方法的好处。

具体来说,TD(0)受到我们同时学习整个值函数的问题的困扰。所以 v(Sʹ)可能不是对 v(S)的一个好的估计。特别是,在移动到 Sʹ后,人工智能玩家移动到另一个州,称之为 Sʹʹ.如果 v(Sʹ)不是对 v(Sʹʹ)的好估计,那么它也不是对 v(S)的好估计。蒙特卡洛方法通过在整个游戏结束后进行更新来解决这一问题,但在处理不符合政策的移动时又会受到影响。

资格追踪是解决方案。类似于随机梯度下降中的动量,我们将轨迹 z ( 初始化为 0)添加到我们的算法中,并且具有衰减参数λ < 1。我们在时间 t: 得到更新

轨迹匹配组件的参数 w 组件。所以如果 w 是一个向量,那么 z 就是一个长度相同的向量。同样,用“张量”代替矢量,用“形状”代替长度。同样的还有“张量列表”和“相应的形状列表”

值得考虑一步步会发生什么。让我们从时间 t=0 开始进行更新。仔细理解我们的衍生品是基于当前状态评估的

在我们的第一步中,我们得到以下更新(z 被初始化为 0):

TD(λ)在时间 0 更新

与之前一样,更新 v(S) 以匹配 v(Sʹ) 。差异出现在下一步:

时间 1 的 TD(λ)更新

这就好像我们回到过去,在时间 0 更新未来,还不知道, v(Sʹ)v(Sʹʹ) 的区别!适当地用因子λ折现。

请注意,这两个导数是在不同的时间用不同的参数和输入进行评估的。这意味着我们无法为由此产生的 v(Sₒ).写下任何有启发性的表达

我们算法的最后一点是,如果我们做出一个关闭策略动作,我们应该将跟踪清零。未来头寸的价值不再能为我们过去的行动提供信息。

概述

我们引入了更多新的符号。通过对标准内容的简单重复,我们得到了以下总结:

交替 TD(λ)

这篇文章的要点是需要对 TD(λ)稍加修改,以说明这个游戏是一个双人游戏。有各种各样的方法来处理这个问题,但哲学家足球的对称性使它非常干净。

具体来说,让我们将状态 S 解释为代表棋子的排列,并假设 X 将要出牌。然后 v 评估 X 获胜的概率。使用 a 表示电路板已经翻转。现在忽略参数更新,当 AI 玩家移动时,我们有以下的转换

状态和获胜概率的变化

特别是,在游戏之后,如果我们将棋盘转过来,那么获胜的概率就变成了 1- v. 这就需要对算法进行一些修改。

另一个变化是必须考虑到,在评估完成的同时计算导数是可取的。在教科书 TD(λ)算法中,我们隐含地首先对状态进行正向评估以选择一个移动,然后计算相对于旧状态的导数。这显然是浪费。我们一个步骤的完整算法现在变成了:

棘手的部分是第 6 步中的减号!这就是我称之为交替 TD(λ)的原因。我们基于时间 t+1 和 t 之间的值差在时间 t 进行更新。如果在时间 t+2,我们意识到我们的 t+1 值被低估(因此δ为负),我们需要增加我们在时间 t 对状态 S 的值估计。因此梯度的交替符号说明交替的参与者。

结论

希望你已经很好地了解了强化学习以及双人游戏的额外复杂性。如果你还没有,在哲学家.足球玩这个游戏。人工智能玩家仍在训练,但你可以和另一个人类对战。

[1]我不确定算法是否原创。我根据教科书上的描述在萨顿和巴尔托。

[2]爱因斯坦的释义。

[3]首先,因为不可能有足够多的游戏来达到所有这些状态。第二,因为任何一个稍有能力的玩家早在达到这些状态之前就已经赢了。

[4]从技术上来说,要很好地定义这个策略,我们应该在状态变量中包含人类所必需的所有信息:一天中的时间,他们是否饥饿,水星是否逆行,房间里有多少只猫,他们的对手是否戴着黑帽子,他们是否相信此刻的选择公理,等等。但这种技术性不会影响主要论点。

强化学习变得简单(第 1 部分):基本概念和术语介绍

原文:https://towardsdatascience.com/reinforcement-learning-made-simple-part-1-intro-to-basic-concepts-and-terminology-1d2a87aa060?source=collection_archive---------1-----------------------

入门,直观强化学习系列

简明易懂的马尔可夫决策过程应用指南

由 Philippe Murray-Pietsch 在 Unsplash 上拍摄的照片

在过去的几年里,你可能已经开始听到更多关于强化学习的事情,自从 AlphaGo 模型在复杂的围棋比赛中击败当时的世界冠军,震惊世界以来,alpha Go 模型就是使用强化学习训练的。

在一系列文章中,我将回顾强化学习(RL)的基础知识以及一些用于解决 RL 问题的最流行的算法和深度学习架构。我们将努力以尽可能直观的方式来理解这些原理,而不要过多地探究数学理论。

以下是本系列文章的简要总结。我的目标是不仅要理解事物是如何工作的,还要理解它为什么会这样工作。

  1. 基本概念和术语介绍—本文 (什么是 RL 问题,以及如何使用马尔可夫决策过程和概念(如回报、价值和政策)中的技术将 RL 问题解决框架应用于该问题)
  2. 解决方案方法 (热门 RL 解决方案概述,并根据这些解决方案之间的关系进行分类。贝尔曼方程的重要提示,它是所有 RL 算法的基础。)
  3. 无模型算法 (基于价值和基于政策的解决方案的异同,使用迭代算法逐步提高预测。剥削、探索和贪婪的政策。)
  4. Q-Learning(深入分析这个算法,这是后续深度学习方法的基础。发展直觉,了解为什么这个算法会收敛到最优值。)
  5. 深度 Q 网络 (我们的第一个深度学习算法。一步一步地演示它是如何工作的,以及为什么做出那些架构选择。)
  6. 策略梯度 (我们第一个基于策略的深度学习算法。)
  7. 演员评论家(复杂的深度学习算法,结合了 Deep Q 网络和策略梯度的优点。)**
  8. 惊喜话题😄(敬请期待!)**

RL 概述

RL 在机器学习的世界中处于什么位置?

通常,当人们提供 ML 的概述时,他们首先解释的是它可以分为两类,监督学习和非监督学习。然而,还有第三类,即。虽然它不像它的两个更迷人的兄弟姐妹那样经常被提及。

机器学习可以分为监督学习、非监督学习和强化学习(图片由作者提供)

监督学习使用标记的数据作为输入,并预测结果。它接收来自作为“监督者”的损失函数的反馈。

无监督学习使用未标记的数据作为输入,并检测数据中的隐藏模式,如聚类或异常。它不接受来自主管的反馈。

强化学习通过与外部世界互动来收集输入和接收反馈。它输出与世界互动时需要采取的最佳行动。

RL 与监督(或无监督)学习有什么不同?

  • 没有监督人指导训练
  • 你不用一个大的(有标签的或无标签的)预先收集的数据集来训练。相反,你的“数据”是通过你与之互动的真实世界环境的反馈动态提供给你的。
  • 你在一系列的时间步骤上迭代地做出决策,例如,在一个分类问题中,你在数据输入上运行一次推理来产生一个输出预测。通过强化学习,你可以反复进行推理,在真实世界的环境中导航。

RL 是用来解决什么问题的?

RL 不是典型的 ML 问题,如分类、回归、聚类等,而是最常用于解决不同类别的现实世界问题,如控制任务或决策任务,其中您操作与现实世界交互的系统。

  • 例如,机器人或无人驾驶飞机必须学会从一个盒子中取出一个设备并将其放入一个容器中

它适用于各种应用,例如:

  • 操作无人驾驶飞机或自动驾驶车辆
  • 操纵机器人在环境中导航并执行各种任务
  • 管理投资组合并做出交易决策
  • 玩游戏,如围棋、象棋、视频游戏

强化学习是通过反复试验实现的

在 RL 中,学习是通过反复试验从经验中进行的,就像人类一样。例如,婴儿可以触摸火或牛奶,然后从消极或积极的强化中学习。

  • 婴儿采取一些行动
  • 接收来自环境的关于该动作结果的反馈
  • 重复这个过程,直到它知道哪些行动产生有利的结果,哪些行动产生不利的结果。

婴儿从正负强化中学习(图片由作者提供)

要使用 RL,请将您的问题构建为马尔可夫决策过程

假设你想训练一个机器人。你会如何使用 RL 来解决这样的问题?

要应用 RL,第一步是将问题构建成一个叫做马尔可夫决策过程(MDP)的东西。如果你以前没有和 RL 合作过,很可能你对 MDP 的唯一了解就是它听起来很吓人😄。

所以让我们试着理解什么是 MDP。MDP 有五个组件,它们以明确的方式协同工作。

代理人:这是你操作的系统,比如机器人。这是您希望使用 RL 构建和训练的模型。

环境:作为操作的一部分,代理与之交互的真实世界环境。例如,机器人必须导航的地形、其周围环境、诸如风、摩擦、照明、温度等因素。

一个 MDP 有一个代理人,环境,状态,行动和奖励(图片由作者提供)

状态:这代表当前任何一点的‘世界状态’。它可以捕捉机器人相对于其地形的位置,周围物体的位置,也许还有风向和风速。

可能有一组有限或无限的状态。

动作:这些是代理在与环境交互时采取的动作。机器人可以右转、左转、前进、后退、弯腰、举手等等。

可能有一组有限或无限的可能动作。

奖励:是行动者因其行动而从环境中获得的正面或负面强化。这是一种评估特定行为“好”或“坏”的方式。

如果向一个特定的方向移动导致机器人撞到墙上,那将会有负面的回报。另一方面,如果向左转使机器人找到了它需要捡起的物体,它会得到积极的回报。

在定义您的 MDP 时,您应该记住什么?

代理和环境:显然,第一步是决定您的代理的角色和范围,以及您试图解决的问题的环境。

状态:接下来,您必须定义状态包含哪些数据点,以及它们是如何表示的。

重要的是,它捕获了解决您的问题所需的一切,以表示当前的世界形势,以便代理可以在不需要关于过去的信息或任何其他知识的情况下对未来进行推理。

换句话说,国家的定义应该是独立的。因此,举例来说,如果您需要了解一些关于您如何到达这个状态的信息,那么这个历史应该封装在您的状态定义本身中。

行动:您的代理可以采取的一系列潜在行动是什么?

奖励:这是代理人从经验中学习的方式。因此,这是您需要认真考虑的事情,因为以一种真正反映您希望代理学习的行为的方式来定义奖励是至关重要的。

MDP 是如何工作的?

现在我们已经看到了什么是 MDP,我们将进入它是如何工作的。让我们用井字游戏作为一个简单的例子。两个玩家通过将他们的代币放在一个 3x3 的格子上来玩这个游戏。一个玩家放置零(甜甜圈形状),而其他玩家放置十字。目标是通过将三个代币排成一行来赢得游戏。

(图片由作者提供)

您可以按如下方式定义 MDP:

  • 代理人与环境对抗,所以环境充当它的对手。
  • 任何一点的状态都是棋盘上所有标记的当前位置,包括代理和环境的标记。
  • 有 9 种可能的操作,代理可以将令牌放在网格中 9 个可用方格的每一个上。
  • 如果代理赢了,它会得到+10 点的正奖励,如果它输了,它会得到-10 点的负奖励。每一个中招给中性奖励 0 分。

现在让我们来看看 MDP 在玩游戏时的操作。

代理在一系列时间步骤内与其环境进行交互。在每个时间步骤中出现一组操作流程,然后在每个时间步骤中重复该流程。

该序列从初始状态开始,该初始状态成为当前状态。例如,你的对手,环境已经把他们的令牌放在一个特定的位置,这就是游戏的开始状态。

MDP 是如何工作的(图片由作者提供)

现在,从第一个时间步开始,每个时间步发生以下步骤:

  1. 环境的当前状态被输入到代理。
  2. 代理使用该当前状态来决定它应该采取什么动作。它不需要记住在它之前的国家和行动的全部历史。代理决定将其令牌放在某个位置。有许多可能的动作可供选择,那么它是如何决定采取什么动作的呢?这是一个非常重要的问题,但我们以后会谈到这个问题。
  3. 该动作作为输入传递给环境。
  4. 环境使用当前状态和选择的动作,并输出两件事——它将世界转换到下一个状态,并提供一些奖励。例如,它通过将令牌放在某个位置来采取下一步行动,并为我们提供奖励。在这种情况下,由于还没有人赢得游戏,它提供了 0 点的中性奖励。环境如何做到这一点对代理来说是不透明的,并且不在我们的控制之下。
  5. 这种来自环境的奖励随后作为先前行动的结果被提供给代理人。

这完成了一个时间步骤,并使我们进入下一个时间步骤。这个下一个状态现在变成当前状态,然后作为输入提供给代理,并且循环重复。

在整个过程中,代理人的目标是最大化在给定状态下采取行动所获得的总回报。它不仅想最大化眼前的回报,还想最大化长期累积的回报。我们将很快回到这个话题。

MDP 在一系列时间步长上迭代

这是 MDP 操作的另一个视图,显示了时间步骤的进展。

MDP 迭代一系列时间步骤(图片由作者提供)

在每个时间步骤中,会发生三件事——状态、行动和奖励,它们充分描述了在该时间步骤中发生的事情。

轨迹描述了多个时间步的执行情况

因此,MDP 的执行可以描述为在一系列时间步骤上发生的轨迹(根据状态、动作、奖励),如下所示。

(s3、a3、r4、s4、a4、r5、s5、a5、r6、s6)

偶发任务以终止状态结束

对于具有明确定义的结束或终止状态的 RL 任务,从开始状态到结束状态的完整序列被称为情节。游戏的每一轮都是一集。

  • 因此,在一集结束时,您可以重置到一个开始状态(或从一组开始状态中随机选择一个)并播放另一个完整的集,并重复。
  • 每一集都独立于下一集。

因此,RL 系统的操作在多个事件中重复。在每一集里,它会重复多个时间点。

每集都以终结状态结束(图片由作者提供)

持续的任务永远继续下去

另一方面,没有结束的 RL 任务被称为持续任务,可以永远继续下去(或者直到你停止系统)。持续管理生产或仓库自动化的机器人。

主体和环境控制状态-动作转换

正如我们刚刚看到的,在每个时间步中,MDP 通过在代理做某事和环境做某事之间交替来运行:

给定一个状态,代理决定动作。给定一个动作(和状态),环境决定下一个状态。(图片由作者提供)

  • 给定当前状态,下一个动作由代理决定。事实上,那是代理的唯一工作。例如,从当前状态,代理可以选择动作 a₁a₂ 来放置其令牌。
  • 给定当前状态和代理选择的下一个动作,到下一个状态的转换和奖励由环境控制。例如,如果代理人选择了动作 a₁ ,环境可以通过玩不同的移动转换到状态 S₂S₃ 。另一个视频游戏的例子可能是,从一个给定的状态(例如,角色站在屋顶上)开始,同一个代理动作(角色跳跃)可能以某种概率在一个以上的下一个状态中结束(例如,落在相邻的屋顶上,或掉到地上),这是由环境控制的。

环境如何过渡到下一个状态?

给定一个当前状态,以及代理选择的动作,环境如何计算出结果。下一个状态和奖励?

对于我们将要处理的大多数现实的 RL 问题,答案通常是“它就是这样”。大多数环境都有复杂的内部动态,当从特定状态采取行动时,这些动态控制着环境的行为。

例如,在股票交易 RL 应用程序中,股票市场环境有一系列看不见的因素决定股票价格如何变动。或者无人机导航 RL 应用中的环境取决于物理定律,这些定律控制各种地形和微天气条件下的气流、运动、热力学、能见度等。

我们的重点是培训代理,我们通常可以将环境视为外部黑盒。

注意,这个外部黑匣子可能是环境的模拟器。在许多情况下,建立一个模拟器可能是不实际的,我们将直接与真实环境进行交互。

然而,为了完整起见,让我简单地提一下,如果我们确实建立了这样一个环境模型,MDP 将把它表示为一个大的转移概率矩阵或函数。

(图片由作者提供)

该矩阵将给定的状态和动作对映射到:

  • 下一个状态,有一定的概率,因为我们可能以不同的概率结束。这就是所谓的转移概率。
  • 奖励。

代理如何选择动作?

另一方面,我们对代理如何决定在给定状态下选择什么动作非常感兴趣。事实上,这正是我们想要解决的 RL 问题。

为此,它使用了三个概念,我们将在下面探讨:

  • 返回
  • 政策
  • 价值

回报是所有时间步的总回报

当代理执行时间步长时,它会在每个时间步长累积奖励。

然而,我们真正关心的不是任何个人奖励,而是累积奖励。

我们称之为回归。它是代理在任务持续时间内累积的总奖励。

回报是在每个时间点收到的奖励的总和(图片由作者提供)

使用折扣奖励计算回报

当我们计算回报时,我们不是简单地将所有的奖励相加,而是应用一个折扣因子γ来加权随时间推移的后续奖励。这些被称为折扣奖励。

返回= r₀ +γ r₁ + γ r₂

更一般地说:

Return = r₀ +γ r₁ + γ r₂ + …+ γr

这样,当时间步数变得很大时,累积奖励不会无限增长(比如连续的任务,或者很长的情节)。

这也鼓励代理人更关心眼前的回报,而不是以后的回报,因为以后的回报会大打折扣。

代理人的最终目标是获得最大的回报,不仅仅是超过一集,而是超过很多很多集。

基于这个折扣,我们可以看到代理在评估奖励时考虑了两个因素。

眼前的奖励比以后的奖励更有价值

第一点是,如果代理人必须在现在和以后获得一定数量的奖励之间做出选择,即时奖励更有价值。由于折扣系数γ小于 1,我们将对以后的奖励给予比直接奖励更多的折扣。

即时奖励比后期奖励更有价值(图片由作者提供)

给我们最高总回报的奖励更好

第二点是,如果代理人必须在现在获得一些奖励和以后获得更大的奖励之间做出选择,更大的奖励很可能是更可取的。这是因为我们希望代理人关注总回报,而不是个人回报。在一盘棋中,代理人必须从两条路径中选择较好的一条。在第一个游戏中,它可以通过激进的打法在早期杀死一些棋子。这给了它一些直接的回报。然而,从长远来看,这使它处于不利地位,并失去了游戏。因此它最终会得到一大笔负回报。或者,它可以玩一套不同的走法,一开始回报较低,但最终赢得游戏。从而获得大量的积极回报。显然,第二种方法更好,因为它给出了更高的总回报,而不是更大的直接回报。

我们想获得更高的总奖励(图片由作者提供)

策略是选择行动所遵循的策略

我们要讨论的第二个概念是政策。早些时候,我们推迟了一个非常重要的问题,那就是,在给定的状态下,代理如何决定选择哪个动作。代理可能会使用许多不同的策略:

  • 总是随机选择下一步行动
  • 总是选择已知奖励最高的下一个州
  • 抓住机会,探索新的状态,希望找到一条更好的道路。
  • 总是谨慎行事,避免负面回报的机会。

代理为决定在给定状态下选择哪个动作而遵循的任何策略都称为策略。虽然这听起来很抽象,但策略只是将给定的状态映射到要采取的操作。

策略告诉代理从任何状态中选择哪个动作(图片由作者提供)

政策就像一个(巨大的)查找表

您可以将策略视为一个(巨大的)查找表,它将状态映射到操作。

(图片由作者提供)

因此,给定当前状态,代理在表中查找该状态,以找到它应该选择的动作。

该政策就像一个(巨大的)查找表(图片由作者提供)

在实践中,对于真实世界的问题,有如此多的状态和如此多的动作,以至于使用一个函数,而不是一个查找表,来将状态映射到动作。

然而,直觉是一样的——把一个函数想象成一个“巨大的查找表”。

确定性和随机性策略

策略可以是确定性的,也可以是随机的。

确定性策略是代理在达到特定状态时总是选择相同的固定动作的策略。

(图片由作者提供)

或者,随机策略是一种策略,其中代理人根据每个动作的某种概率,改变它为一个状态选择的动作。

例如,它可能会在玩游戏时这样做,这样它就不会变得完全可预测。在玩石头剪子布的时候,如果它总是玩同一个动作,对手可以发现这一点并轻松击败它。

(图片由作者提供)

代理如何获得保单?

我们一直在讨论这个策略,就好像代理已经有一个现成的策略可供使用一样。但事实并非如此。

就像人类婴儿一样,代理在开始时并没有真正有用的策略,也不知道在任何给定的状态下应该采取什么行动。然后,通过使用强化学习算法,它会慢慢地学习一个有用的策略。

有这么多可能的策略,代理应该使用哪一个?

代理人从给定状态采取的行动决定了它获得的回报,因此随着时间的推移,最终的总回报。因此,代理人的目标是选择最大化其回报的行动。

换句话说,代理人的目标是遵循一个使其回报最大化的政策(这是它选择行动的方式)。

因此,在代理可以遵循的所有策略中,它想要选择最好的一个。回报最高的那个。

为了做到这一点,代理需要比较两个策略来决定哪一个更好。为此,我们需要理解价值的概念。

这个值告诉你遵循一些政策的预期回报

假设代理处于特定状态。此外,假设代理不知何故得到了一个策略,π。现在,如果它从那个状态开始,并且总是根据那个策略选择行动,它能期望得到什么回报?

这就好比说,如果代理人从那个状态开始,并且总是根据那个政策选择行动,那么在很多很多集里,它的平均回报会是多少?

这种平均长期回报,或预期回报,被称为特定国家的价值,在政策π下。

状态值(V)或状态-行动值(Q)是通过在许多情节中遵循给定的策略,分别从特定的状态或状态-行动获得的预期回报(图片由作者提供)

或者,代理可以从状态-动作对开始。它已经从一个特定的州采取了一个特定的行动。如果从那个状态-动作开始,它总是根据给定的策略π选择动作,那么它期望得到的回报是什么?

正如前面针对策略表所讨论的,我们可以将 Value 视为一个(巨大的)查找表,它将一个状态或状态-动作对映射到一个值。

因此,我们有两种价值:

  • 状态值—通过执行基于给定策略π的操作,从给定状态开始的预期回报。换句话说,状态值函数将状态映射到它的值。

状态值函数将状态映射到其值(图片由作者提供)

  • 状态-行动值(也称为 Q 值)—从给定状态采取给定行动,然后根据给定策略π执行行动的预期回报。换句话说,状态-动作值函数将状态-动作对映射到它的值。

状态-动作值函数将状态-动作对映射到它的值(图片由作者提供)

报酬、回报和价值之间的关系

  • 奖励是单个行动获得的直接奖励。
  • Return 是该集结束前获得的所有折扣奖励的总和。
  • 价值是许多集的平均回报(又名预期回报)。

把奖励看作是即时的快乐,把价值看作是长久的幸福😃。

人们可以直观地认为价值如下。像人类一样,代理从经验中学习。当它与环境互动并完成剧集时,它会获得每集的回报。

随着它积累更多的经验(即获得越来越多的剧集的回报),它了解哪些状态以及这些状态中的哪些动作产生最多的回报。

它将这种“体验”存储为“价值”。

为什么价值取决于我们遵循的政策?

显然,我们得到的回报(以及回报和价值)取决于我们在特定状态下采取的行动。由于操作取决于所选择的策略,因此值也取决于策略。

如果我们的政策是选择完全随机的行动(例如,从均匀分布中抽取行动样本),那么一个状态的价值(预期回报)可能会很低,因为我们肯定没有选择最好的行动。

相反,如果我们的政策是从抽样时产生最大回报的概率分布中选择行动,那么一个状态的价值(预期回报)会高得多。

使用值函数来比较策略

既然我们已经理解了价值,那么让我们回到我们之前关于比较两种策略来看看哪种更好的讨论。我们如何评价“更好”的含义?

给定两个策略,通过遵循策略并评估回报,我们可以为每个策略确定相应的状态值或状态动作值函数。

(图片由作者提供)

一旦我们有了各自的价值函数,我们就可以使用这些价值函数来比较策略。价值函数更高的政策更好,因为这意味着它将产生更高的回报。

“最佳”策略被称为最优策略

因为我们现在可以比较策略来找出哪些是“好”的,哪些是“坏”的,所以我们也可以使用它来找到“最佳”策略。这就是所谓的最优策略。

最优策略是能给代理人带来比其他策略更多回报的策略。

最优策略是优于所有其他策略的策略(图片由作者提供)

通过寻找最优策略来解决 RL 问题

现在我们有了解决 RL 问题的方法。

我们把我们的问题构造成一个 MDP,然后我们可以通过构建一个代理来解决这个问题。MDP 的大脑,这样它就能决定采取什么行动。它应该以回报最大化的方式来做这件事。

换句话说,我们需要为代理人找到最优策略。一旦有了最佳策略,它就简单地使用该策略从任何状态中选择动作。

我们将应用强化学习算法来建立一个代理模型,并训练它找到最佳策略。找到最优策略实质上解决了 RL 问题。

(图片由作者提供)

在本系列的下一篇文章中,我们将研究这些 RL 算法使用的解决方案。

最后,如果你喜欢这篇文章,你可能也会喜欢我关于变形金刚和音频深度学习的其他系列。

* [## 直观解释的变压器(第 1 部分):功能概述

NLP 变形金刚的简明指南,以及为什么它们比 rnn 更好,用简单的英语。注意力如何帮助…

towardsdatascience.com](/transformers-explained-visually-part-1-overview-of-functionality-95a6dd460452) [## 音频深度学习变得简单(第一部分):最新技术

颠覆性深度学习音频应用和架构世界的温和指南。以及为什么我们都需要…

towardsdatascience.com](/audio-deep-learning-made-simple-part-1-state-of-the-art-techniques-da1d3dff2504)

让我们继续学习吧!*

强化学习变得简单(第 2 部分):解决方法

原文:https://towardsdatascience.com/reinforcement-learning-made-simple-part-2-solution-approaches-7e37cbf2334e?source=collection_archive---------4-----------------------

直观强化学习系列

RL 解决方案的概述,以及如何对它们进行分类。用简单的英语从贝尔曼方程式中得出的重要结论

照片由张秀坤镰刀在 Unsplash 上拍摄

这是我关于强化学习系列的第二篇文章。既然我们已经了解了什么是 RL 问题,那么让我们来看看用来解决它的方法。

这里是对本系列之前和之后文章的一个快速总结。我的目标是不仅要理解事物是如何工作的,还要理解它为什么会这样工作。

  1. 基本概念和术语介绍 (什么是 RL 问题,以及如何使用马尔可夫决策过程和概念(如回报、价值和政策)中的技术将 RL 问题解决框架应用于该问题)
  2. 解决方案方法 —本文 (概述流行的 RL 解决方案,并根据这些解决方案之间的关系进行分类。贝尔曼方程的重要提示,它是所有 RL 算法的基础。)
  3. 无模型算法 (基于价值和基于策略的解决方案的异同,使用迭代算法逐步提高预测。剥削、探索和贪婪的政策。)
  4. Q-Learning 发展直觉,了解为什么这个算法会收敛到最优值。)
  5. 深度 Q 网络 (我们的第一个深度学习算法。一步一步地演示它是如何工作的,以及为什么做出那些架构选择。)
  6. 策略梯度 (我们第一个基于策略的深度学习算法。)
  7. 演员评论家(复杂的深度学习算法,结合了 Deep Q 网络和策略梯度的最佳技术。)
  8. 惊喜话题😄(敬请期待!)

RL 解决方案类别

解决强化学习问题基本上等于找到最优策略(或最优值)。有许多算法,我们可以把它们分成不同的类别。

基于模型与无模型

非常宽泛地说,解决方案是:

  1. 基于模型(又名计划)
  2. 无模型(又名强化学习)

当环境的内部操作已知时,使用基于模型的方法。换句话说,当从某个当前状态执行某个动作时,我们可以可靠地说出环境将输出什么下一个状态和奖励。

基于模型:环境的内部操作是已知的(图片由作者提供)

当环境非常复杂并且其内部动态未知时,使用无模型方法。他们将环境视为黑箱。

无模型:环境是一个黑匣子(图片由作者提供)

预测与控制

另一个高层次的区别是预测和控制。

对于一个预测问题,给我们一个策略作为输入,目标是输出相应的值函数。这可以是任何策略,不一定是最优策略。

预测与控制问题(图片由作者提供)

对于控制问题,不提供输入,目标是探索策略空间并找到最优策略。

大多数实际问题都是控制问题,因为我们的目标是找到最优策略。

流行 RL 算法分类

最常见的 RL 算法可分类如下:

知名 RL 解决方案分类(图片由作者提供)

最有趣的真实世界 RL 问题是无模型控制问题。因此,在本系列中,我们不会进一步探讨基于模型的解决方案,只是在下面简单地介绍一下。从现在开始,我们讨论的一切都只与无模型控制解决方案有关。

基于模型的方法

因为基于模型的方法可以产生每个状态和动作交互的精确结果,所以它们可以在不与环境实际交互的情况下通过分析找到解决方案。

举个例子,用基于模型的方法下国际象棋,你可以在国际象棋的所有规则和策略中编程。另一方面,无模型算法对象棋游戏本身一无所知。它唯一的知识是一般性的信息,例如状态是如何表示的以及可能采取什么行动。它只是在抽象的意义上通过观察当它尝试一些动作时获得的奖励来学习象棋。

大多数现实世界的问题都是无模型的,因为环境通常太复杂而无法建立模型。

无模型方法

相比之下,无模型解决方案只能通过与环境的实际交互来观察环境的行为。

与环境互动

既然环境的内部运行是我们看不到的,那么无模型算法是如何观察环境的行为的呢?

我们通过与它互动,一次一个动作,来了解它的行为。算法充当代理,采取一个动作,观察下一个状态和奖励,重复。

无模型算法通过与环境交互来了解环境,一次一个动作。(图片由作者提供)

代理人通过反复试验获得经验。它尝试步骤并接收正面或负面的反馈。这与人类学习的方式非常相似。

互动轨迹

当代理走每一步时,它遵循一条路径(即轨迹)。

互动轨迹(作者图片)

代理的轨迹成为算法的“训练数据”。

贝尔曼方程是所有 RL 算法的基础

在我们进入用于解决 RL 问题的算法之前,我们需要一点数学知识来使这些概念更加精确。

数学实际上非常直观——它完全基于一个简单的关系,即贝尔曼方程。

这种关系是所有 RL 算法的基础。这个方程有几种形式,但它们都是基于相同的基本思想。让我们一步一步来建立对它的直觉。

从终端状态往回工作(这样更容易理解)

通过从一个状态采取行动达到一个终端状态来考虑奖励。

达到终极状态时的奖励(图片由作者提供)

从那种状态得到的回报和采取那种行动得到的回报是一样的。请记住,奖励是为单个行动获得的,而回报是从该状态向前(直到该集结束)获得的累积折扣奖励。

(图片由作者提供)

现在考虑先前的状态 S6。来自 S6 的回报是通过采取行动到达 S7 获得的奖励加上我们将从 S7 获得的任何贴现回报。重要的是,我们不再需要知道 S7 之后的各个步骤的细节。

(图片由作者提供)

回报的贝尔曼方程

一般来说,任何状态的回报都可以分解为两部分——达到下一个状态的行动的直接回报,加上通过对所有后续步骤遵循相同的政策从下一个状态获得的贴现回报。这种递归关系被称为贝尔曼方程。

(图片由作者提供)

状态值的贝尔曼方程

回报是单个路径的贴现回报。状态值是通过对多条路径(即回报的预期)。

因此,状态值可以类似地分解为两部分——达到下一个状态的下一个行动的直接回报,加上通过遵循所有后续步骤的策略而得到的下一个状态的贴现值。

(图片由作者提供)

状态-动作值的贝尔曼方程

类似地,状态-行动值可以分解为两个部分——达到下一个状态的行动的直接回报,加上通过遵循所有后续步骤的策略得到的下一个状态的贴现值。

(图片由作者提供)

为什么贝尔曼方程有用?

从贝尔曼方程中我们可以得出两个关键的观察结果。

Return 可以递归计算,而不需要转到剧集的结尾

第一点是,为了计算回报,我们不必一直走到这一集的结尾。剧集可能会很长(穿越成本也很高),也可能永无止境。相反,我们可以使用这种递归关系。

如果我们知道下一步的回报,那么我们就可以利用它。我们可以只走一步,观察回报,然后重复使用随后的回报,而不用遍历整个事件。

我们可以使用估计值,而不是精确值

第二点是有两种方法来计算同一件事:

  • 一个是从当前状态的返回。
  • 其次是一步的回报加上下一步的回报。

为什么这很重要?

由于衡量某个州(到本集结束)的实际回报非常昂贵,我们将使用估计回报。然后,我们用两种方法计算这些估计值,并通过比较两个结果来检查我们的估计值有多正确。

由于这些是估计值,而不是精确的测量值,所以这两种计算的结果可能不相等。这种差异告诉我们,我们在估算中犯了多少“错误”。这有助于我们通过修正估计值来减少误差,从而提高我们的估计值。

坚持这两个想法,因为所有的 RL 算法都会用到它们。

结论

现在我们对 RL 问题有了一个总体的概念,以及用来解决它们的方法的广阔前景,我们准备更深入地研究用来解决它们的技术。由于现实世界中的问题通常是用无模型方法解决的,这就是我们要关注的。它们将是下一篇文章的主题。

最后,如果你喜欢这篇文章,你可能也会喜欢我关于变形金刚和音频深度学习的其他系列。

[## 直观解释的变压器(第 1 部分):功能概述

NLP 变形金刚的简明指南,以及为什么它们比 rnn 更好,用简单的英语。注意力如何帮助…

towardsdatascience.com](/transformers-explained-visually-part-1-overview-of-functionality-95a6dd460452) [## 音频深度学习变得简单(第一部分):最新技术

颠覆性深度学习音频应用和架构世界的温和指南。以及为什么我们都需要…

towardsdatascience.com](/audio-deep-learning-made-simple-part-1-state-of-the-art-techniques-da1d3dff2504)

让我们继续学习吧!

(强化)学习非惯性系、伪力和爱因斯坦等效原理

原文:https://towardsdatascience.com/reinforcement-learning-non-inertial-frames-pseudo-force-and-einsteins-equivalence-principle-7d9e94b8297c?source=collection_archive---------65-----------------------

对一个经典控制问题的强化学习学到了一类不明显且不平凡的解决方案。

几周前,我在解决强化学习中的翻跟斗问题时,发现了一些非常有趣的事情。实际上这是一种保守的说法。我真的很惊讶,AI algo 在我想到它之前就找到了我要描述的解决方案(我是 Lore AI 的高级机器学习工程师,也是量子信息和黑洞专业知识的弦理论学家,所以我不知道以上是对 AI 的赞美还是我只是变得生疏了。读者可以自己判断。)

OpenAI Gym 为人们提供了几个环境来训练他们的强化学习算法,而 cartpole 由于其简单性而成为一个非常受欢迎的选择。

问题陈述:如上图所示,在一个无摩擦的表面上有一个物体,物体上有一根绕无摩擦铰链旋转的杆。“环境”因此由 4 个数字表征:质心的水平位置和速度以及杆的角位置和速度。代理采取的“动作”只能是左推或右推。学习任务的目标是保持系统运行 200 步(系统保持运行的每个时间步有+1 的奖励)。跑步本身定义为质心保持在(-2.4,2.4)以内,角度在(-12,12)度之间。

正如你所看到的,这是一个非常简单的经典力学问题,但是当然,这个模型对经典力学一无所知,必须学会完成这个任务。一些人已经写了一般的强化学习,特别是这个问题,所以我不会深入研究它,只是说我将使用策略梯度。

我想讲的是问题的物理学,以及机器如何学习一类有趣的解。

惯性框架解决方案

思考一下的解决方案应该是什么。如果你对物理学不是很感兴趣,你会认为质心应该是静止的,而极点应该是垂直的。这确实是人工智能算法找到的解决方案,我们可以看到该解决方案的视频

最直观的解决方案是重心几乎不动,杆子保持垂直。

以及脉冲、位置和角度位置的曲线图

惯性坐标系解中的冲量(左右推力)、质心位置和杆的角位置。

现在,你们中稍微懂点物理的人会发现,这是一系列解中的一部分,在这个解中,质心的速度是均匀的,在这个例子中是零速度。通过将参考系转换到另一个惯性系,其他解决方案与这个解决方案简单相关。从一辆匀速行驶的汽车来看,想象与上述相同的解决方案。

如果你们不记得什么是惯性系,在牛顿第一定律中,惯性系被定义为没有外力的情况下,物体以恒定速度运动。

人工智能算法也可以找到这样的解决方案,但这不是本文的重点。

非惯性系解

在这一节中,我描述了人工智能发现的让我惊讶的有趣的解决方案,但在我到达那里之前,我需要给读者一个物理入门,以欣赏人工智能系统发现的解决方案。

物理学入门——非惯性系、赝力和爱因斯坦等效原理

牛顿第一定律将惯性系定义为物体在没有力的情况下保持其速度的坐标系。另外两个定律告诉我们在这种框架下的动力学定律。但是不遵守第一定律的框架,也就是非惯性系呢?加速中的汽车就是这样一个例子,尽管没有外力作用在你身上,但你“感觉”到自己正在加速。物理学家已经找到了一种方法来简化非惯性系中的计算,并且通过发明赝力的概念,甚至可以在非惯性系中使用另外两个定律。

简而言之,这个想法是假设非惯性系是惯性的,并且该惯性系中的所有物体都受到一个(伪)力的作用,该力等于质量乘以加速度的负值(回想一下,加速度是一个矢量,因此负值意味着方向相反的矢量)。

汽车中的钟摆向右加速时会向左倾斜。这个解是相同的,就好像重力在θ= arctan(A0/g)旋转的方向上作用。图片来源:https://www . toppr . com/ask/question/a-单摆悬吊汽车加速匀加速 a/

伪力可以用来解释为什么当悬挂在天花板上的汽车向前加速时,钟摆会向后摆动。有一个伪力向后作用在钟摆上。那么作用在摆锤上的总“力”是向下的重力和以角度θ= arctan(a/g)向后作用的伪力之和。

我们甚至可以说,有一个“有效引力”作用在上述方向,大小为 Sqrt(a +g)。

与上述相同的系统,其中加速框架被视为添加了适当伪力的惯性系。如图所示,伪力和重力一起作为有效重力。图片来源:https://www . toppr . com/ask/question/a-单摆悬于车顶-匀加速-上/

事实上,爱因斯坦的 广义相对论 正是基于这样一种想法,即没有局域方式来区分真实重力和赝力,这种东西被称为 等效原理

爱因斯坦的等效原理指出,在重力开启的情况下,加速框架和非加速框架之间的差异无法仅通过局部实验来确定。图片来源:https://claesjohnsonmathscience . WordPress . com/2012/01/17/questioning-relativity-3-the-equivalence-principle/

强化学习伪力解

那么这一切和强化学习以及我们的横竿问题有什么关系呢?我看到的是,人工智能在非惯性系中学习解!也就是说,它学会了一种解决方案,其中杆保持倾斜一个角度,代理不断将系统推向该方向,以保持恒定的加速度,使杆不会进一步下落。

非显而易见的非平凡解,其中小车以恒定加速度加速,而杆子保持恒定角度倾斜。

该系统学习让杆倾斜到一个角度,然后不断地加速它(这不像只在一个方向上给予脉冲那么简单,这会导致杆很快倒下)。

在上面的视频中可能很难看到加速度,但我们可以看到质心位置非常接近地遵循恒定加速度轨迹(使用 MSE 在轨迹上拟合 a 的 1/2 处)。

冲量(左右推动),质心位置,非惯性系解的杆的角位置。

技术细节

使用标准的体育馆环境来解决横拉杆问题并不容易。当我第一次看到上面的解决方案时,我很惊讶 AI 系统学会了这一点,但它不是这么干净,因为标准问题要求杆保持在 12 度倾斜和中心的 2.4 个单位内,这与 200 步的恒定加速度不兼容。因此,我用自己的代码包装了标准环境,还必须修改渲染函数,以便购物车在 200 步的持续时间内保持在可见区域。这一切的代码都可以在 my github repo 中找到。


  1. l ↩︎