TowardsDataScience 博客中文翻译 2016~2018(一百八十一)
学习制作未来不确定的视频
“具有已知先验的随机视频生成”一文的摘要
TL;DR: 这篇文章提供了一个在中描述的视频生成模型的高级概述,随机视频生成具有一个已知的先验,它能够生成具有多种未来的视频序列。
作为自我监督学习任务的视频生成
有监督的深度学习模型已被证明在最近的过去在诸如实时对象分割、检测、机器翻译和语音识别等困难任务上产生了突破性的结果。这些模型的高保真性能使它们在现实世界应用中的使用给世界带来了积极的影响(但有时也是消极的)。
无监督学习的下一阶段挑战也已经在一定程度上成功解决,如领域适应和机器翻译。从原始、嘈杂的真实世界数据中学习在操作上更便宜、更快,因为可以跳过大量的手动预处理,如清理和注释。
无监督学习的一个子领域是自监督学习,最近由 AI 社区谈论了很多。在这个场景中,模型被提供输入数据,并负责完成围绕该数据的故事。该领域中一个特别有趣的应用是生成任何给定视频序列的未来事件。
这个任务的警告使得这个问题变得困难,不像其他任务,其中输入具有固定的输出,视频中的未来事件可以以多种可能性解开,例如,击中地面的弹跳球可以具有多种可能的轨迹、旋转等。
具有学习先验的随机视频生成
2018 年在 ICML 发表的“具有学习先验的随机视频生成”提出了一个框架,通过提出一个预测模型来处理这种情况,其中未来的“不确定”部分由从先验分布中采样的潜在变量来处理。为了理解其工作原理,让我们直接进入系统设计。
该系统由以下部件组成:
- 预测模型
- 推理模型
- 已知先验
预测模型
预测模型是核心预测器/生成器,其他模型提供辅助信息来帮助预测模型。它由一个编码器组成,该编码器在时间 t-1 从视频中获取一个图像帧,并将其编码为潜在空间中的密集表示。这个表示向量然后被传递到 LSTM ( 【帧预测】,它是预测模型的记忆组件。它有助于模型考虑序列中过去图像帧的信息。帧预测器负责预测未来下一帧的密集表示。然后,该图像被传递到解码器/ 生成器网络,该网络在时间 t 将其转换为预测图像。为了进一步帮助解码器,在编码器和解码器之间进行跳跃连接,以便可以简单地直接复制视频的静态部分。
帧预测器也以一个辅助变量为条件,该辅助变量可被视为代表关于特定未来的信息。我们将在接下来的步骤中讨论这一点。
Prediction Model
到目前为止,模型的训练包括一个非常简单的目标,即最小化重建误差或预测帧和地面真实情况之间的 L2 距离。
推理模型
推理模型的任务是学习包含关于时间 t 的事件的信息的分布。从该分布中抽取样本 z ,其被传递到预测模型中的帧预测器上。
推理模型的输入是在时间 t 的图像帧,因此该模型仅在训练期间使用。推理模型的架构使用与预测模型中相同的T21 编码器,因为在两个阶段中我们想要的图像编码类型是相同的。重复使用模型或重量分配会使学习过程变得简单一些。然后,编码矢量被传递到不同的 LSTM 模型(本文中称为后验**)上,该模型具有与帧预测器相似的目标,但是在学习表示未来信息的背景下。后验者可能会学习查看过去的隐藏状态,并避免捕获已学习分布中的冗余信息。**
人们可能会想,推理模型可以简单地记忆整个图像,并通过解码器再现它。为了确保只捕获相关的信息,我们使用了已学习的先验模型。
Inference Model accompanies the Prediction model during training, providing latent variable containing information to a possible outcome in the future.
已知先验
为了防止推理模型简单地复制整个目标帧,我们施加了这样的限制,即来自后验的学习分布应该紧密匹配前分布。这通过最小化后验和先验预测的两个多变量分布之间的 KL-散度来确保。这个先验分布是通过另一个模型学习的,该模型类似于推理模型,但是将时间 t-1 的帧作为输入。这里的思想是先验也是时间相关的,即在时间 t 预测的先验分布是直到 t-1 的过去帧的函数。
Complete model that is used during training with the objective of minimizing reconstruction error and KL divergence.
一种替代方法是将该先验分布固定为具有零均值和恒等协方差的高斯分布。
结果
通过将地面实况的第一个 t-1 帧馈送到预测和先验模型,从学习的先验分布中采样 z 并生成时间步长 t 的帧,来执行推断。这然后作为输入反馈到模型中,以在 t+2 生成帧。
除了像移动 MNIST 和 KTH 动作这样的较小数据集,该模型在 BAIR 机器人推数据集上显示了令人印象深刻的结果。鉴于损失目标如此简单,该模型能够在未来多个时间步长内表现如此之好,即生成机器人手臂的非模糊运动,确实令人惊讶。
The frames marked in green are ground truth. “Approx. posterior”: in this case, z is sampled from the posterior (and thus should be close to the ground truth). In all other sequences, z is randomly sampled from the prior distribution. “Best SSIM” is the one such sequence prediction with the best results on SSIM metric.
Results on Moving MNIST.
更多比赛结果的视频,请查看 sites.google.com/view/svglp/…
当前的缺点
如果读者在提供的链接中查看放大的结果,很容易注意到当机器人手臂与周围的其他对象交互时,预测的帧表现出模糊。换句话说,这个模型已经学会了表示手臂的未来随机运动,但未能捕捉到手臂及其与其他对象的交互之间的动态。
解决这一问题的一种方法是利用分层潜在模型,这样更广泛的概念(如整体手臂运动)由较低层次的先验捕获,而复杂的动力学由下一层次的模型捕获。今年早些时候,我花了一些时间研究这个问题,应用了各种基于层次概念的技术。我的一些发现可以在这里查看。
最后的想法
这篇文章提供了 SVG-LP 模型的简要概述以及它所获得的一些结果。要从概率的角度获得更正式的解释,请参考上面链接的论文。
视频生成模型不仅可以作为视频理解和合成的非常有用的应用,还可以帮助规划和强化学习。2018 年下半年,基于模型的强化学习出现了令人难以置信的增长。这些方法的基本组成部分是前向预测模型,其任务是在给定当前和动作的情况下预测下一个状态。看看大卫·哈的worldmodels.github.io/来一瞥这种类型的模型如何被用于强化学习。
学习使用自然图像数据执行线性滤波
Traditional Norwegian hut in Skibotn (Image by author).
卷积神经网络通常从训练数据中学习有用的特征。根据任务的不同,第一个卷积层的特征可能代表训练数据的一些基本内容。例如,在图像数据中,所学习的特征可以表示边缘和斑点。在网络的后续层中,学习到的特征可以表示更抽象、更高级别的实体。
可视化所学习的特征,以及它们如何及时发展,可能提供关于网络如何学习的有用信息。实际上,网络架构几乎总是比仅仅几层深得多,这使得很难直观地解释和分析所学习的特征,因为卷积核的总量很高。
然而,我们可以演示卷积核权重如何随着网络通过受控实验的学习而随时间发展。很容易陈述学习任务,使得网络应该学习的特征已经预先知道,即产生训练数据的过程和参数被很好地定义并且完全在我们的控制之下。这可以通过构建一个极其简单的单层卷积网络并训练它使用各种内核执行线性滤波来实现。
在下面的实验中,我们将 Sobel 边缘滤波(图像处理和计算机视觉中边缘检测的典型方法)应用于数据集,并训练我们的模型来执行类似的线性映射。我们还试图从数据中学习更多的任意线性滤波器,其核的大小比 Sobel 滤波的情况稍大。
该演示有望建立关于神经网络中的卷积层如何对输入数据进行操作、卷积核权重如何在训练期间进行以及神经网络的训练如何可以被视为最小化问题的直觉。
首先,我们必须对输入图像数据 X 应用线性滤波,以便获得原始图像的滤波版本 Y。形式上,线性滤波操作可以总结如下:
线性滤波器是一种定义明确的操作,适用于我们能想到的任何参数集(卷积核)或输入数据。
我们现在可以建立一个单层、单核、卷积神经网络,它近似于线性滤波操作。毕竟,在线性滤波器和卷积神经网络中,两种情况下执行的计算完全相同,只是卷积核参数不同,我们将从数据中了解这一点。
我们可以在线性滤波器和卷积神经网络之间得出以下联系:
学习任务现在可以表述为最小化问题,其中线性滤波器的输出和卷积神经网络的输出之间的均方误差被最小化:
应用于图像数据的线性滤波器的参数被称为卷积核。我们将首先在 x 方向上,然后在 y 方向上,用称为 Sobel 算子的 3×3 卷积核来过滤图像数据,从而开始我们的实验。Sobel 算子给出如下:
对于实验,我们将使用运行在 TensorFlow 之上的 Keras 框架。
x 方向的 Sobel 滤波器
首先,我们必须为图像预处理定义几个辅助函数。加载数据集,将图像转换为灰度,归一化图像强度范围,并对数据集中的每个图像执行线性滤波。
作为训练和测试数据,我们将利用城市和自然场景类别-数据集(奥利瓦,A. &托拉尔巴,A. (2001)。模拟场景的形状:麻省理工学院计算视觉认知实验室收集的空间包络的整体表示。
原始数据集由八个类别的自然场景彩色图像(分辨率:256 x 256)组成,其中我们使用了三个类别:街道、市中心和高楼。这样,我们获得了足够大小的训练和测试集(764 个训练样本和 192 个测试样本),使得训练不会遭受过拟合,并且训练也可以通过在合理的时间帧内利用更适中的硬件来执行。所选的类别代表具有强烈边缘的自然场景(大范围的人类建筑),这有助于我们比较结果。
下面,我们可以观察到属于数据集的原始图像的可视化、图像的灰度转换和 Sobel 滤波版本:
Original image (left), Grayscale image (middle) and Sobel filtered image in x-direction (right).
我们将只在单通道图像上使用线性滤波器。在实践中,这意味着模型被训练成将灰度转换图像映射成 Sobel 滤波图像。
接下来,我们定义模型:具有线性激活的单层、单核、卷积网络,即,激活函数是恒等式。卷积核的大小被选择为 3×3,以符合 Sobel 滤波器的大小。
使用具有内斯特罗夫动量的随机梯度下降优化器来训练 100 个时期的模型。在每个时期,保存卷积层权重用于进一步可视化。
训练完成后,我们可以绘制训练和验证损失图,以查看训练是否过度拟合。
在整个训练过程中,训练和验证损失是稳定的,模型似乎是收敛的。
现在可以将每个时期的保存的权重可视化为矩阵格式的数值,以及更直观的格式,其中数值表示可视化中的像素强度值。声明用于执行可视化的函数,并且为每个时期创建可视化。
现在我们有了每个时期的可视化效果,我们可以从它们创建一个 gif 电影来看看权重是如何变化的。
The progress of the convolution layer weights as the model is trained. The weight values converge close to the Sobel operator in x-direction.
在 gif 电影中,随着学习的进行,卷积核权重如何向 Sobel x 方向滤波器收敛是相当明显的。在前 10 到 15 个时期收敛很快,之后收敛速度明显稳定下来。如果学习任务比我们在这个实验中使用的简单线性过滤操作更复杂,我们仍然会看到类似的行为。卷积核的值将收敛到某个最佳配置,该配置将从数据中提取有用的特征。在这个实验中,有用的特征是由 Sobel 算子给出的图像 x 方向的边缘。我们能够找到产生第一手训练数据的几乎精确的卷积核参数,主要是因为我们的问题陈述非常简单。然而,对于真实世界的问题,这很少发生,因为训练数据通常不是从输入到输出的线性映射。
为了测试该模型,我们可以看到与 x 方向上的 Sobel 滤波相比,该模型的预测看起来如何。
Output of the model (left) and the same image filtered with Sobel operator in x-direction (right).
在图中(顶部),我们可以观察到模型的输出和 x 方向上并排的 Sobel 滤波的结果。目测,两幅图像看起来相似。事实上,在强度值中,人们应该仅发现图像之间的微小差异,因为所学习的卷积核收敛到接近原始 Sobel 算子的值。
y 方向的 Sobel 滤波器
同样的代码也可以利用 Sobel 算子在 y 方向上执行线性滤波。我们所要做的就是改变图像过滤功能,在 y 方向而不是 x 方向执行过滤,再次加载并过滤训练数据,并用新数据训练模型。
在下图中,我们可以观察到 Sobel 过滤器现在如何在垂直方向(y 方向)上强调图像强度边缘。
Original image (left), Grayscale image (middle) and Sobel filtered image in y-direction (right).
我们可以再次观察到,当网络从训练数据中学习时,卷积核权重如何在 y 方向上朝着 Sobel 滤波器前进。收敛行为非常类似于先前在 x 方向上使用 Sobel 算子的情况。
The progress of the convolution layer weights as the model is trained. The weight values converge close to the Sobel operator in y-direction.
同样,在下图中,模型的输出和相同测试图像的 Sobel 滤波版本具有相似的外观。对于人眼来说,不可能分辨出这两幅图像的区别。
Output of the model (left) and the same image filtered with Sobel operator in y-direction (right).
笑脸过滤器
之前学习的 Sobel 滤波器非常简单,只需要学习少量的参数。让我们看看,如果我们可以学习一个更大的核线性滤波器。
我们将在下面的实验中使用的过滤器内核是一个 32 x 32 像素的笑脸(谢谢 Leo 的想法:)。加载过滤器内核,并通过用笑脸内核过滤灰度图像来创建训练数据。由于大的内核大小,内核基本上延伸到图像边界之外。图像边界用零填充,以抵消卷积导致的图像分辨率的降低。
The normalized smiley face filter kernel.
在下图中,我们可以看到笑脸过滤图像与原始图像和灰度转换图像相比的样子。
Original image (left), Grayscale image (middle) and smiley face filtered image (right).
我们的模型再次是一个简单的单层、单核、卷积神经网络,其中激活函数是身份。这一次,我们根据笑脸内核的大小,将内核大小设置为 32 x 32。作为对之前实验的增强,我们将基本的随机梯度下降优化器改为更强大的 Adam 优化器。
该模型被训练 100 个时期,并且在每个时期存储卷积核权重。训练和验证损失在大约 10 个时期内快速收敛,之后可以在两个损失值中看到小的波动。
存储的卷积核权重值现在可以可视化并组合成 gif 电影。结果很有启发性:该模型似乎惊人地学习了原始的笑脸过滤器内核,正如在下面的 gif 电影中可以观察到的那样。卷积核权重相对较早地呈现笑脸的形状,大约在十个时期之后,但是权重仍然包含大量噪声。随着训练的进行,噪声慢慢消失,并且相邻的权重值相对于彼此变得更加恒定。
通过分析验证损失和卷积核权重的进展,可以进行重要的观察。即使验证损失在第十个时期后看起来是平坦的,卷积核权重仍然朝着原始笑脸核发展足够的量。训练和验证损失曲线的线性比例有时可能会有点误导,因为初始损失值可能会在损失测量的后期改进中主导损失可视化。
The progress of the convolution layer weights as the model is trained. The weight values converge close to the smiley face filter.
现在我们有了一个训练好的模型,我们可以可视化并比较模型的输出和一个笑脸过滤测试图像的结果。在下图中,我们可以观察模型和笑脸过滤器内核如何产生与测试图像相似的外观。类似于 Sobel 滤波的图像,以及由从数据学习 Sobel 滤波的模型产生的图像,很难将笑脸滤波的图像与模型的输出区分开。
Output of the model (left) and the same image filtered with the smiley face kernel (right).
最后的话
我希望使用线性滤波器的三个实验足够清楚地展示了当网络从数据中学习时,卷积核权重是如何发展的。此外,我希望您能够获得一些见解,以便理解卷积层对输入数据的操作方式。这些实验的结果没有直接推广到卷积神经网络被用于例如图像分类的情况,而是为理解卷积层背后的现象和作为优化问题的学习提供了基础。
如果你对在自己的电脑上运行实验感兴趣,这里有一个 github 文件夹的链接,其中包含重复实验所需的一切:github.com/vexcel/Kera…。
学习使用 Python scikit 进行排名-学习
如果你经营一个电子商务网站,一个经典的问题是在搜索页面上排列你的产品,以最大化你的商品被销售的可能性。例如,如果你在卖鞋,你希望搜索结果页面中的第一双鞋是最有可能被购买的。
由于机器学习的广泛采用,现在比以往任何时候都更容易建立和部署自动学习用户喜欢什么并相应地对产品目录进行排名的模型。在这篇博文中,我将分享如何使用一个简单的端到端示例,使用 movielens 开放数据集来构建这样的模型。
介绍
想象一下,你有一个电子商务网站,你正在设计一种算法,在你的搜索页面中对你的产品进行排序。你展示的第一件物品是什么?评论最好的那个?价格最低的那个?还是两者都有?问题很快变得复杂起来。
一个简单的解决方案是利用你的直觉,从你的客户那里收集反馈,或者从你的网站上获取指标,手工制作适合你的完美配方。不太科学不是吗?一种更复杂的方法包括建立许多排名公式,并使用 A/B 测试来选择具有最佳性能的一个。
在这里,我们将使用来自客户的数据来自动学习他们的偏好函数,这样我们的搜索页面的排名将最大化获得转化率的可能性(即客户购买你的商品)。具体来说,我们将学习如何根据人工生成的用户数据对来自 movielens 开放数据集的电影进行排名。Github 上的提供了 Jupyter 笔记本格式的完整步骤。
准备培训数据
为了学习我们的排名模型,我们首先需要一些训练数据。因此,让我们生成一些模拟网站用户行为的示例:
event_1: <customer_1, movie_1, fail>
event_2: <customer_1, movie_2, fail>
event_3: <customer_1, movie_3, success>
event_4: <customer_2, movie_2, fail>
event_5: <customer_2, movie_3, success>
…
列表可以解释为: customer_1 看了 movie_1 和 movie_2 但决定不买。然后看了 movie_3 决定买电影。同样的顾客 _2 看了电影 _2 但决定不买。然后看了 movie_3 决定买。
在真实世界的场景中,你可以从你选择的分析工具中获得这些事件,但是对于这篇博文,我将人工生成它们。为此,我们将为每部电影关联一个 buy_probability 属性,并相应地生成用户事件。
我们的原始电影数据如下所示:
movie_data.dtypestitle object
release_date datetime64[ns]
unknown int64
Action int64
Adventure int64
Animation int64
Children’s int64
Comedy int64
Crime int64
Documentary int64
Drama int64
Fantasy int64
Film-Noir int64
Horror int64
Musical int64
Mystery int64
Romance int64
Sci-Fi int64
Thriller int64
War int64
Western int64
ratings_average float64
ratings_count int64
price float64
dtype: object
这是数据集中一部电影的例子:
‘title’, ‘release_date’, ‘unknown’, ‘Action’, ‘Adventure’, ‘Animation’, “Children’s”, ‘Comedy’, ‘Crime’, ‘Documentary’, ‘Drama’, ‘Fantasy’, ‘Film-Noir’, ‘Horror’, ‘Musical’, ‘Mystery’, ‘Romance’, ‘Sci-Fi’, ‘Thriller’, ‘War’, ‘Western’, ‘ratings_average’, ‘ratings_count’, ‘price’
‘Toy Story (1995)’, Timestamp(‘1995–01–01 00:00:00’), 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.8783185840707963, 452, 7.0
让我们假设我们的用户将仅基于价格做出购买决定,并看看我们的机器学习模型是否能够学习这样的功能。对于这个数据集,电影价格的范围在 0 到 10 之间(查看 github 以了解价格是如何分配的),所以我决定人工定义购买概率如下:
movie_data[‘buy_probability’] = 1 — movie_data[‘price’] * 0.1
根据购买概率函数,我们的完美排名应该是这样的:
没有火箭科学,价格最低的电影最有可能被购买,因此应该排在第一位。现在让我们基于这些数据生成一些用户事件。每个用户都有许多积极和消极的事件与之相关联。正面事件是指用户购买了一部电影。负面事件是指用户看了电影,但决定不购买。
class User:
def __init__(self, id):
self.id = id
self.positive = []
self.negative = []
def add_positive(self, movie_id):
self.positive.append(movie_id)
def add_negative(self, movie_id):
self.negative.append(movie_id)
def get_positive(self):
return self.positive
def get_negative(self):
return self.negative
在继续之前,我们希望所有的特征都被标准化,以帮助我们的学习算法。所以让我们把这个弄清楚。还要注意,我们将删除 buy_probability 属性,这样我们就不会在学习阶段使用它(用机器学习的术语来说,这相当于作弊!).
def build_learning_data_from(movie_data):
feature_columns = np.setdiff1d(movie_data.columns, np.array(['title', 'buy_probability']))
learning_data = movie_data.loc[:, feature_columns]
scaler = StandardScaler()
learning_data.loc[:, ('price')] = scaler.fit_transform(learning_data[['price']])
learning_data['ratings_average'] = scaler.fit_transform(learning_data[['ratings_average']])
learning_data['ratings_count'] = scaler.fit_transform(learning_data[['ratings_count']])
learning_data['release_date'] = learning_data['release_date'].apply(lambda x: x.year)
learning_data['release_date'] = scaler.fit_transform(learning_data[['release_date']])
return learning_data
最后,使用下面显示的“EventsGenerator”类,我们可以生成我们的用户事件。为了简单起见,让我们假设我们有 1000 个用户,并且每个用户将打开 20 部电影。真实世界的数据显然会有所不同,但原理是一样的。
np.random.seed(1)class EventsGenerator:
NUM_OF_OPENED_MOVIES_PER_USER = 20
NUM_OF_USERS = 1000def __init__(self, learning_data, buy_probability):
self.learning_data = learning_data
self.buy_probability = buy_probability
self.users = []
for id in range(1, self.NUM_OF_USERS):
self.users.append(User(id))
def run(self):
for user in self.users:
opened_movies = np.random.choice(self.learning_data.index.values, self.NUM_OF_OPENED_MOVIES_PER_USER)
self.__add_positives_and_negatives_to(user, opened_movies)return self.__build_events_data()def __add_positives_and_negatives_to(self, user, opened_movies):
for movie_id in opened_movies:
if np.random.binomial(1, self.buy_probability.loc[movie_id]):
user.add_positive(movie_id)
else:
user.add_negative(movie_id)
def __build_events_data(self):
events_data = []
for user in self.users:
for positive_id in user.get_positive():
tmp = learning_data.loc[positive_id].to_dict()
tmp['outcome'] = 1
events_data += [tmp]
for negative_id in user.get_negative():
tmp = learning_data.loc[negative_id].to_dict()
tmp['outcome'] = 0
events_data += [tmp]
return pd.DataFrame(events_data)
这就是所有东西粘在一起的原因。事件生成器获取标准化的电影数据,并使用购买概率来生成用户事件。
learning_data = build_learning_data_from(movie_data)
events_data = EventsGenerator(learning_data, movie_data['buy_probability']).run()
这是其中一个事件的样子:
'Action', 'Adventure', 'Animation', "Children's", 'Comedy', 'Crime', 'Documentary', 'Drama', 'Fantasy', 'Film-Noir', 'Horror', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Thriller', 'War', 'Western', 'outcome', 'price', 'ratings_average', 'ratings_count', 'release_date', 'unknown'
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0.28363692, 0.16953213, -0.14286941, 0.39397757, 0
在这种情况下,由于我们在函数*build _ learning _ data _ from(movie _ data)*中所做的操作,我们得到了一个否定的结果(值为 0),并且这些特征已经被归一化并集中在零。
如果我们绘制事件图,我们可以看到分布反映了人们大多购买廉价电影的想法。由于正常化,价格再次以零为中心。
训练我们的模型
现在我们有了我们的事件,让我们看看我们的模型在学习(简单)“购买概率”函数方面有多好。我们将把我们的数据分成一个训练和测试集,以测量模型性能(但请确保您知道交叉验证如何工作),并使用这个通用函数来打印不同模型的性能。
def train_model(model, prediction_function, X_train, y_train, X_test, y_test):
model.fit(X_train, y_train)
y_train_pred = prediction_function(model, X_train)print('train precision: ' + str(precision_score(y_train, y_train_pred)))
print('train recall: ' + str(recall_score(y_train, y_train_pred)))
print('train accuracy: ' + str(accuracy_score(y_train, y_train_pred)))y_test_pred = prediction_function(model, X_test)print('test precision: ' + str(precision_score(y_test, y_test_pred)))
print('test recall: ' + str(recall_score(y_test, y_test_pred)))
print('test accuracy: ' + str(accuracy_score(y_test, y_test_pred)))
return model
使用 scikit-learn 训练各种模型现在只是把东西粘在一起的问题。让我们从逻辑回归开始:
def get_predicted_outcome(model, data):
return np.argmax(model.predict_proba(data), axis=1).astype(np.float32)def get_predicted_rank(model, data):
return model.predict_proba(data)[:, 1]model = train_model(LogisticRegression(), get_predicted_outcome, X_train, y_train, X_test, y_test)
这为我们提供了以下性能
train precision: 0.717381689518
train recall: 0.716596235113
train accuracy: 0.717328291166
test precision: 0.720525676086
test recall: 0.726374636238
test accuracy: 0.721590909091
我们可以使用神经网络和决策树来做同样的事情。这是一个具有 23 个输入(与电影特征的数量相同)和 46 个隐含层神经元(隐含层神经元加倍是一个常见的经验法则)的神经网络。
from nolearn.lasagne import NeuralNetdef nn():
return NeuralNet(
layers=[ # three layers: one hidden layer
('input', layers.InputLayer),
('hidden', layers.DenseLayer),
('output', layers.DenseLayer),
],
# layer parameters:
input_shape=(None, 23), # this code won't compile without SIZE being set
hidden_num_units=46, # number of units in hidden layer
output_nonlinearity=None, # output layer uses identity function
output_num_units=1, # this code won't compile without OUTPUTS being set# optimization method:
update_learning_rate=0.01,
regression=True, # If you're doing classification you want this off
max_epochs=50, # more epochs can be good,
verbose=1, # enabled so that you see meaningful output when the program runs
)def get_predicted_outcome(model, data):
return np.rint(model.predict(data))def get_predicted_rank(model, data):
return model.predict(data)
这是我们得到的表现
model = train_model(
nn(),
get_predicted_outcome,
X_train.astype(np.float32),
y_train.astype(np.float32),
X_test.astype(np.float32),
y_test.astype(np.float32)
)train precision: 0.698486217804
train recall: 0.687534749249
train accuracy: 0.65721971972
test precision: 0.667556742323
test recall: 0.679655641142
test accuracy: 0.636136136136
最后是决策树
def get_predicted_outcome(model, data):
return np.argmax(model.predict_proba(data), axis=1).astype(np.float32)def get_predicted_rank(model, data):
return model.predict_proba(data)[:, 1]
这为我们提供了以下性能
from sklearn import tree
model = train_model(tree.DecisionTreeClassifier(), get_predicted_outcome, X_train, y_train, X_test, y_test)train precision: 0.680947848951
train recall: 0.711256135779
train accuracy: 0.653892069603
test precision: 0.668242778542
test recall: 0.704538759602
test accuracy: 0.644044702235
我们可以将各种排名标绘在一起进行比较。排名曲线的形状与我们用来定义购买概率的曲线非常相似,这证实了我们的算法正确地学习了偏好函数。
描述 buy_probability 的形状并不完全相同,因为用户事件是随机生成的(均值等于 buy_probability 的二项式分布),所以模型只能根据生成的事件来近似潜在的事实。
Logistic regression
Decision trees
Neural Network
下一步是什么
一旦你得到了你的排名估计,你可以简单地将它们保存在你选择的数据库中,并开始为你的页面服务。随着时间的推移,你的用户的行为可能会像你的目录中的产品一样发生变化,所以要确保你有一些程序来每周更新你的排名数字,如果不是每天的话。根据一个简单的手工制作的线性公式对你的新模型进行 A/B 测试也是一个好主意,这样你就可以验证自己,机器学习是否确实在帮助你收集更多的转化率。
如果你更喜欢戴科学家的帽子,你也可以在 Github 上运行 Jupyter 笔记本,用不同的公式计算 buy_probability ,看看这些模型能够在多大程度上发现潜在的真相。我确实尝试了价格和评级的非线性函数的线性组合,它在相似的准确度水平下工作得同样好。
price_component = np.sqrt(movie_data['price'] * 0.1)
ratings_component = np.sqrt(movie_data['ratings_average'] * 0.1 * 2)
movie_data['buy_probability'] = 1 - price_component * 0.2 - ratings_component * 0.8
最后,与这里概述的方法不同的方法是使用事件对来学习排序函数。这个想法是,你给学习算法输入一对这样的事件:
pair_event_1: <customer_1, movie_1, fail, movie_3, success>
pair_event_2: <customer_2, movie_2, fail, movie_3, success>
pair_event_3: <customer_3, movie_1, fail, movie_2, success>
...
有了这样的例子,你可以猜到一个好的排序是“电影 _3,电影 _2,电影 _1 ”,因为不同客户的选择强制了我们的电影集合的总排序。尽管预测成对的结果与上面显示的例子具有相似的准确性,但为我们的电影集提出一个全局排序证明是困难的(NP 完全困难,如来自& T labs 的这篇论文所示),我们将不得不求助于贪婪算法进行排序,这会影响最终结果的质量。Julien le tessier的这篇博客文章对这种方法进行了更深入的描述。
结论
在这篇博文中,我介绍了如何利用用户事件数据来教会机器学习算法如何对你的产品目录进行最佳排序,以最大化你的商品被购买的可能性。我们看到了逻辑回归、神经网络和决策树如何实现相似的性能,以及如何将您的模型部署到生产中。
期待在评论中听到你的想法,如果你喜欢这个博客,你也可以在 Twitter 上关注我。
最初发表于 阿尔弗雷多 。
用应用于生物力学模型的进化算法学习行走
使用真正的肌肉在类似人类的模型上行走。
这个帖子的代码可以在 这个 GitHub 资源库 中找到。
2017 NIPS 挑战之一是学习跑步:顾名思义,任务是设计和开发一种学习算法,能够控制人体的生物力学模型使其行走。与大多数机器人情况不同,致动器是腿 肌肉,每条腿 9 个。挑战的作者修改了 OpenSIM 环境,使其适应强化学习设置,从而增加了奖励信号。
Something went terribly wrong (or terribly right).
许多参与者设计了端到端的深度强化学习算法,近年来,这些算法在连续控制任务中表现得非常好。但是,通常情况下,他们需要强大的计算能力和时间来学习一个成功的策略,如果在多台计算机上并行化,效果会更好。
我决定试着玩玩它,实现并扩展我最近为机器人开发的一个相当轻量级的方法:进化 算法应用于神经控制器。它们的优势是无导数和高度并行化,可以达到类似深度 RL 算法的结果,如 OpenAI 的所示。问题是他们完全是随机的,因此很难估计他们会学到什么和如何学。但我很乐意给他们一个机会。
First steps, baby steps.
…重要的是不要只开发性能最好的模型,因为它可能会陷入很难摆脱的局部最小值。
进化算法用于数值优化问题,因此它们相对于适应度函数优化参数。那么,什么是参数和适应度函数呢?经验证明:腿以周期性的方式运动。因此,肌肉激活以周期性和正弦时间规律激活,但是该规律可能难以手工设计。如何塑造周期函数?这就是傅立叶级数发挥作用的地方。利用傅立叶级数,人们可以用正弦和余弦的加权和来近似任何周期函数。但是,理论上,它们需要无限项。我设计了一个截断傅立叶级数来塑造肌肉活动。我只使用了余弦级数的前四项,因此有 8 个参数:4 个权重直接乘以不同频率的余弦,4 个相位改变信号。这为每块肌肉创造了一个周期性的功能。每条腿有 9 块肌肉,我使用了 9 个不同的周期函数,因为我假设,对于另一条腿,我们使用相同的函数,但相位偏移 180°。因此,遗传算法修改这些参数(与涉及神经网络的任何算法相比,非常少)来优化适应度函数,这显然是总回报,即机器人在摔倒之前行走的长度。
Walking pattern after around a day of training.
通过从白高斯采样,参数被随机修改,但是如果特定采样方向改善了性能,则参数再次朝着该方向更新以利用该方向,直到性能不再改善。我并行运行了的三个型号,因为对于一台笔记本电脑来说,它们的计算量比内存都要大。最佳性能权重被存储到中央参数文件中,并且在一定数量的集之后,学习从三个最佳性能参数组重新开始。这允许更好地探索不同的可能行为:重要的是不要只利用表现最好的模型,因为它可能陷入很难摆脱的局部最小值,而从长远来看,一个更差的模型可以通过调整其行为来超越它。事实上,在一系列事件后从最好的模型重新开始是学习可感知的行走模式的关键因素。非常值得注意的是,即使事先没有任何知识,这个模型也能学会类似人类的动作行为。
该模型在非常慢的模型和旧笔记本电脑上进行相对较短的训练后,仅使用英特尔酷睿 2 双核 CPU 成功行走了一些步骤。其他深度 RL 模型显然实现了更好的性能,但是需要非常长的训练和强大的硬件。我的目标并不是真的与它们竞争,而只是展示如何用不到 100 个参数并使用遗传算法来获得行走模式,即使在一台旧笔记本电脑上也能快速训练。
这个帖子的代码可以在 这个 GitHub 资源库 中找到。
学习用蒙特卡罗方法赢 21 点
我会学到什么?
本文将带您了解强化学习的基础支柱之一蒙特卡罗(MC)方法背后的逻辑。这种解决强化学习问题的经典方法将通过寻找简化版 21 点的最优策略来演示。
在本文结束时,我希望你能够描述和实现以下主题。完整的代码可以在我的 GitHub 上找到。
- 蒙特卡洛预测
- 蒙特卡洛控制
- 首次就诊与每次就诊
- q 值
- 折扣奖励
蒙特卡洛方法是什么?
Photo by Pasquale Iovino on Unsplash
MC 是一个非常简单的无模型学习的例子,只需要过去的经验就可以学习。这是通过计算在许多游戏中在特定状态下采取特定行动的平均奖励来实现的。如果你不熟悉强化学习的基础,我会鼓励你快速阅读基础知识,如代理生命周期。我之前的文章介绍了这些概念,可以在这里找到。如果你不熟悉 21 点游戏,看看这个视频。
在 21 点中使用蒙特卡罗
如果你曾经认真玩过 21 点(或者我看过电影《21 小时》),那么你可能听说过“基本策略”。这是一个简单的表格,包含 21 点中每种可能的状态组合(您的牌的总和和庄家显示的牌值),以及根据概率和统计采取的最佳行动(击中、坚持、加倍或分裂)。这是一个政策的例子。
Simple version of the basic strategy policy developed by Edward O. Thorp, image taken from here
在我们的示例游戏中,我们将使它变得简单一点,只有击中或坚持的选项。除此之外,我们还会将状态逻辑分为两种类型,一手牌有可用的 a,一手牌没有可用的 a。
在 21 点中,a 的值可以是 1 或 11。如果我们有一张值为 11 的 a 而不破产,我们称之为“可用 a”。
预言;预测;预告
假设我们得到了一个非常简单的策略(甚至比上面的基本策略还要简单)。
**策略:**如果我们的手牌≥ 18,以 80%的概率坚持,否则以 80%的概率命中
这不是一个惊人的政策,但它很简单,仍然能够赢得一些比赛。现在,假设我们想知道当庄家出 6 时,持有 14 手牌的价值。这是预测问题的一个例子。
为了解决这个问题,我们将使用首次访问蒙特卡洛。这种方法让我们的代理使用我们当前的策略玩了成千上万个游戏。每次代理在该游戏中第一次执行状态 S 中的动作 A 时,它将从该点开始计算游戏的奖励。通过这样做,我们可以确定我们目前的状态有多有价值。
这与每次访问蒙特卡洛相反,蒙特卡洛每次看到状态/动作对时都会计算奖励。这两种方法提供了相似的结果。实施首次访问蒙特卡洛的步骤可以在这里看到。
First Visit Monte Carlo algorithm for prediction, taken from here
如果你不习惯阅读这些算法,这可能看起来有点复杂,但实际上很简单。让我们来看一下实现这个算法的步骤。
- 提供一个策略 pi
- 创建空字典 N、returns_sum 和 Q 来保存一个状态/动作对被访问的次数、该状态/动作对收到的返回量以及该状态/动作对的最终值。
- 用我们目前对 X 游戏的政策玩一局 21 点
- 循环游戏中的每个回合,检查当前的状态/动作对是否在游戏中出现过
- 如果这是我们第一次看到这一对,我们增加这一对的计数,并将从该回合开始的每一步的折扣奖励添加到我们的 returns_sum 字典中
- 最后,用每个状态/动作对的回报和数量的平均值来更新 Q 值。
在我们进入代码之前,我想快速介绍的最后一件事是折扣奖励和 Q 值的概念。
折扣奖励
折扣奖励的理念是将眼前的奖励置于潜在的未来奖励之上。就像专业的国际象棋选手一样,我们的代理人不仅仅着眼于在本回合中走一个卒,他们还着眼于如何从现在开始赢得 12 步棋。这就是为什么在计算行动价值时,我们采用累积折扣奖励(行动后所有奖励的总和)而不是直接奖励。
折扣因子只是一个常数,我们在每个时间点用它乘以我们的奖励。在每一个时间步之后,我们增加乘以折扣因子的幂。这给了立即行动更多的优先权,当我们离采取的行动越远,优先权就越低。
the discounted reward of an action over time, image taken from here
这给了立即行动更多的优先权,当我们离采取的行动越远,优先权就越低。选择我们的折扣因子的值取决于手头的任务,但它必须总是在 0 和 1 之间。折扣系数越大,未来奖励的重要性越高,反之亦然。一般来说,0.9 的折扣系数是一个很好的起点。
q 值
q 值是指在状态 s 中采取行动 A 的值。我们将这些值存储在一个表或字典中,并在学习时更新它们。一旦我们完成了我们的 Q 表,我们将总是知道基于我们所处的当前状态该采取什么行动。
履行
下面是一个 jupyter 笔记本,带有实现 MC 预测的代码。每一部分都有注释,并且逐行给出了更多的细节。
如您所见,实现预测算法并不困难,根据笔记本末尾显示的图表,我们可以看到该算法已经成功预测了我们非常简单的 21 点策略的值。接下来是控制。
控制
Photo by Mélanie THESE on Unsplash
这是两个问题中更有趣的一个,因为现在我们要用 MC 来学习博弈的最优策略,而不是仅仅验证之前的策略。我们将再次对 MC 使用首次访问方法。
First Visit MC Control with Constant Alpha, image taken from here
这个算法看起来比之前的预测算法复杂一点,但本质上还是很简单的。因为这有点复杂,我将把问题分成几个部分来解释。
- 初始化我们的价值观和字典
- 探测
- 更新策略
- 使用新策略生成剧集
- 更新 Q 值
1)初始化值
这与上一个算法类似,只是这次我们只有一个字典来存储我们的 Q 值。这是因为我们使用了一个新的更新功能,我们将在后面讨论
2)更新政策和探索
人们通过不断犯新错误来学习。我们的代理人也是这样学习的。为了学习最好的政策,我们希望有一个很好的组合来执行我们已经学到的好的举措和探索新的举措。这就是所谓的勘探/开发问题。在这种情况下,我们将使用经典的ε贪婪策略,其工作原理如下:
- 设置一个临时策略,使选择任一操作的概率相等,[0.5,..
- 获取当前状态 Q[s]的当前最佳策略
- 获得基于最佳策略的最佳操作,argmax(Q[s])
- 将选择最佳行动的概率设置为 1-ε+临时策略值(50%)
开始时,ε会很大,这意味着在大多数情况下,最佳行动的概率为 0.5(随机)。随着游戏的进行,ε会减小,采取最佳行动的概率会增加
3)用新策略生成剧集
这与我们之前的算法几乎完全相同,但是我们不是基于硬编码策略的概率来选择我们的行动,而是在随机行动和最佳行动之间交替。这就是我们之前讨论过的ε贪婪策略。当我们浏览时,我们记录下每集的状态、动作和奖励,并传递给我们的更新功能。
4)更新 Q 值
这是算法的重要部分。这里我们实现了代理如何学习的逻辑。我们将使用一个更新函数来改进我们的策略,而不是简单地获得一个状态/动作对随时间的平均回报。函数看起来是这样的。
Q[s][a] = Q[s][a] + alpha*(G - Q[s][a])
我们在这里所做的就是获取原始的 Q 值,并添加我们的更新。更新由剧集的累积奖励(G)和减去旧的 Q 值组成。然后这些都乘以α。
在这种情况下,阿尔法作为我们的学习率。一个大的学习率将意味着我们很快取得进步,但是它冒着做出太大改变的风险。
虽然它最初会很快取得进展,但它可能无法找出它正在学习的任务的更微妙的方面。另一方面,如果学习率太小,代理将学习任务,但这可能会花费很长的时间。就像机器学习中的大多数事情一样,这些是重要的超参数,您必须根据项目的需要进行微调。
履行
现在我们已经学习了控制算法的理论,我们可以开始写代码了。
现在,我们已经成功地生成了自己的玩 21 点的最佳策略。你会注意到原始的硬编码策略和我们新的最优策略是不同的,我们的新策略反映了 Thorps 的基本策略。
结论
我们现在知道如何使用 MC 来寻找 21 点的最优策略。不幸的是,仅凭这一策略,你不会很快赢得很多钱。这个游戏的真正复杂性在于知道何时以及如何下注。一个有趣的项目是将这里使用的策略与关于如何正确下注的第二个策略结合起来。
我希望你喜欢这篇文章,并找到一些有用的东西。任何反馈或意见总是很感谢。完整代码可以在我的 GitHub 上找到
参考资料:
萨顿 r .和巴尔托 a .——强化学习:导论,麻省理工学院出版社,1998 年
Udacities RL 资源库:【github.com/udacity/dee…
Denny Britz 知识库:https://github . com/Denny Britz/reinforcement-learning/blob/master/MC/MC % 20 prediction % 20 solution . ipynb
来自《走向数据科学》编辑的注释: 虽然我们允许独立作者根据我们的 规则和指南 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
离开我的风投工作去学习数据科学和机器学习
昨天是我在九点资本的最后一天。
两年半前我加入点九时,对风险投资一无所知。我来自比利时,我和我的朋友都没有接触过这个世界。但是我突然有一种想要亲身体验的冲动,于是我开始四处寻找机会。
如果我告诉你我在申请的时候知道谁是第九点或者第九点是什么,那我就是在撒谎。然而,读了他们的工作邀请后,我只是喜欢他们的语气。所以我买了一本基本上是虚拟资本的书,花了几十个小时熟悉这个领域,阅读了 Point Nine 团队的 100 万篇博客帖子——是的,我也认为他们当时有代笔人(我们没有)——在经过不下 5 次 Skype 面试后,终于获得了一个角色。
我的第一天有点难熬,因为我第一次见到这个团队是在一次异地活动中,在一次攀岩活动中,我被卡在了一块岩石上。是的,天气很热,是的,我身后有一个伙伴变得非常紧张,是的,我总是设法让自己处于这种情况下!
从那以后,我一直在爬 VC 岩石,我身后有 Point 的工作人员,我享受着每时每刻。我感到非常幸运,我有机会与这样一个伟大的团队和如此热情的企业家一起工作。我学到了很多,并且仍然认为这份工作是世界上最好的工作之一。
那么,我为什么要离开这么好的工作呢?
当我回顾过去两年半中最让我兴奋的公司时,我意识到两件事:
1)通常涉及一些数据魔术/机器学习,
2)他们对社会产生了某种积极的影响。
一些例子:
- Vintra ,这是一个视频分析平台,允许公共和私人调查人员利用视频来破案、拯救生命和保护资产。数据=视频监控录像,影响=更安全的世界。
- Corti Labs ,提供实时诊断帮助、紧急呼叫数据分析以及呼叫接听人员培训模块。数据=紧急呼叫,影响=拯救生命。
机器学习并不新鲜,而且肯定被夸大了。然而,我仍然相信,用它可以做出惊人的事情。每当我考察一家新公司时,我都非常想了解这项技术的详细工作原理。然而,风投工作的性质意味着我不能花费我想花的时间。所以我想我会在晚上和周末学习。
这是六个月前,也是预期膨胀的顶峰。三个月前,失望之余,我意识到我做不到。一个月前,在启蒙运动的斜坡上,我决定退出并全职做几个月。从 1 月 1 日起,我将开始全职学习,并有望达到生产率的最高梯度。
我将如何学习?
我想在网上学习一切,这样我就可以在任何地方学习。
对比课程,征求大家的意见,我起草了这个学习计划。
非常欢迎任何建议或意见!这是我的私人邮箱或者直接在表格中留下评论。
我会在表格的第二个选项卡中不断添加我收到的建议。
然后,接下来呢?
不,我不打算在数据科学领域工作。我的计划是 1)获得对数据科学和机器学习的高度理解,2)参与使用这些技术并对社会产生积极影响的初创公司(可能在投资方面,但也可能不是)。
很独特,是吧?是的,这是故意的。作为一名合伙人,我每个月都有机会看到几十个甚至几百个想法。这很神奇,但也有不好的一面:很难保持专注。关注科技行业是有风险的,因为使能技术发展如此之快。话虽如此,但我自信地押注于机器学习和至少未来几年的积极影响。
几年后,产品中的机器学习功能可能会像基于云一样简单。然而,了解如何从中获得好的价值来解决一个特定的问题可能会永远有意义。至于影响力投资,我希望对社会产生积极影响仍能吸引一些人。如果没有,我就去火星!
谢谢
我想感谢所有在我第一次风投之旅中有机会一起工作的了不起的人。
首先,我要感谢 Point Nine 团队——Christoph Janz 和 Pawel Chudzinski,他们向我展示了做一名好的风投真正意味着什么 Rodrigo Martinez,他多次督促我成为最好的,并“矩阵化”了我的思想 Mathias Ockenfels,他在早期以极大的耐心指导了我 Clement Vouillon,他在我的博客帖子上讲了一些糟糕的笑话和很好的建议;我的松露猪同事 Robin Dechant 和 Louis Coppey 以及 amaaaazing 团队:Jenny Buch
其次,我要感谢所有我有机会与之共事并分享他们伟大创业历程的创始人,包括来自 Juro 的 Richard 和来自 Zype 的 Ed。
谢谢你,我希望能很快见到你!
[讲座]进化:从香草 RNN 到 GRU 和 LSTMs
RNNs evolution
如今,递归神经网络无处不在。像谷歌、百度这样的巨头在生产中广泛使用它们来做机器翻译、语音识别以及许多其他任务。实际上,NLP 相关任务中的几乎所有最新技术成果都是通过利用 RNNs 实现的。
随着 TensorFlow 等出色的深度学习框架的兴起,构建 LSTM 和其他类型的递归网络比以往任何时候都更容易。人们很容易将它们视为一个黑盒。
我们觉得现代 RNNs 背后的直觉是至关重要的。仅仅通过看方程,很难很好地理解 GRU 和 LSTM 网络。事实上,LSTM 网络是香草 RNN 与特定问题斗争的结果。因此,希望理解这些问题和解决它们的方法会使 GRU,LSTM 方程变得更加透明和直观。
现代 rnn 背后的想法真的很美。在今天的讲座“进化:从香草 RNN 到 GRU & LSTMs”中,我们将讨论它们!
这是幻灯片的链接。
非常尊重 R2RT 的博客文章:书面记忆:理解、衍生和延伸 LSTM 。我们的讲座受到他们工作的强烈启发。
[讲座]如何建立一个识别系统(第一部分):最佳实践
你好世界!
识别系统有很多实际应用。许多公司需要创建这样的系统来优化他们的业务流程,不仅是像谷歌、百度、脸书或 Dropbox 这样的行业巨头。
例如,在医疗保健行业,一些公司为不同的患者表单开发了自动字段提取器,包括将相关数据输入数据库的保险表单。其他公司专注于识别车牌等等。
Example of recognition credit card number
幸运的是,我们在 DeepSystems 有构建图像识别系统的经验。但是由于缺乏互联网上的信息,很难深入这个领域。通过长期的研究和阅读许多论文,我们已经对创建有效的识别系统背后的主要原则有了理解。
今天,我们将与你分享我们的理解,并用浅显的语言解释它是如何工作的。
本讲座由两部分组成。第 1 部分涵盖了如何设计神经网络架构的概念。
第 2 部分(即将推出)详细解释了如何训练这样的系统,即如何进行前向和后向阶段的 CTC 丢失。我们觉得这是非常有价值的,因为不可能找到好的和简单的解释如何 CTC 损失工程。
这是幻灯片的链接。
第一部分:
谢谢大家!和我们在一起。欢迎在评论中提问。
数据可访问性对公共福利和人工智能研究进展的法律和伦理影响
本文与 加布里埃尔·帕里斯·加尼翁 、Propulsio 360 商业顾问律师 LLP 合著
每一个专注于人工智能的组织都希望并需要同样的东西:更多的数据来训练他们的算法。毫无疑问,今天深度学习系统的许多成功都是基于大型数据集的可用性和收集,这些数据集通常由用户自己提供,以换取免费使用这些服务。
Photo by Matam Jaswanth on Unsplash
1 月早些时候,在蒙特利尔大都会商会组织的人工智能战略论坛上,Element AI 研究小组主任 Valérie Bécaert 向商界发表了关于共享数据以使所有组织都能使用人工智能的重要性的演讲。在大数据聚集在少数强大公司手中的时代,这延续了经济不平等,并破坏了人工智能在社会事业中的应用。随着时间的推移,这种差距也必然会加大。科技巨头成倍增加他们的数据收集应用程序,并阻止访问这些专有数据,即使是自己生成这些数据的用户——参见脸书生成的影子档案。[1]
更开放的数据获取政策的另一个积极成果是促进科学界、初创企业和面向公益的非营利公司的研究。
到 2030 年,专家预测人工智能将为世界经济贡献高达 15.7 万亿美元[2]。如果什么都不做,没有为数据可访问性颁布标准,这些利润将直接落入极少数人手中。为了让人工智能的发展成为社会流动性的载体,这些收益和随后的财富创造必须以公平的方式进行分配。我们认为,对大型数据集(这对训练深度学习系统至关重要)的可访问性可以将这项技术的集体使用更多地导向公共福利。
此外,有时,个人、公司和非营利组织(它们通常是大型科技公司的数据生成者)受到他们的摆布。他们对自己生成的数据以及如何使用这些数据缺乏控制,也可能产生负面影响。当他们从使用大科技的产品中获得的东西与后者的商业目标不一致时,他们会发现自己无能为力。例如,脸书最近宣布将改变他们的算法,降低出版商帖子的重要性,这对新闻提供商和其他十多年来一直依赖脸书传播信息的企业来说是灾难性的。
Photo by William Iven on Unsplash
现在让我们考虑以下事实:
研究公司 IDC 预测,到 2025 年,数字生态系统中捕获的数据将达到 180 zetta byte(zetta byte = 1 后跟 21 个 0)[3]
亚马逊使用卡车拉着集装箱来管理他们的 AWS 集群所需的存储空间量。[3]
这为我们提供了一个强有力的指标,表明正在收集的关于用户及其在线行为的数据量只增不减。这些公司盈利的核心原因之一来自于他们将这些数据货币化的能力,并随后通过数据经纪人将这些数据出售给广告商。[4]
鉴于创造赚钱产品和服务对数据的严重依赖,以公平的方式访问此类数据对于市场正常化和提高市场竞争力更为重要,从用户角度来看,这可能会带来更好的结果。
Photo by Scott Webb on Unsplash
要求访问公共数据的初创公司
随着大型组织收集的大数据不断具有越来越大的市场价值,初创公司开始向法院寻求授权,以获得对这些数据的访问权。
这些小公司声称,公司对公开可用数据的控制代表着反竞争行为。
2016 年,hiQ Labs 是一家初创公司,它使用 LinkedIn 的公开数据来构建能够预测员工行为的算法,例如他们何时可能辞职以及相应地提升谁,该公司收到了 LinkedIn 的停止函,称收集他们的公开数据违反了该公司的使用条款。hiQ 实验室将此案告上法庭,因为他们的商业模式完全依赖于他们从 LinkedIn 获得的这些公共数据。[5]
2017 年 8 月,旧金山的美国地区法官 Edward Chen 支持 hiQ Labs,并命令 LinkedIn 在 24 小时内删除任何阻止 hiQ Labs 访问公共档案的技术。在他看来,通过阻止 hiQ 访问 LinkedIn 公共档案来维护控制权可能是一种限制竞争的手段,这违反了加利福尼亚州的法律。此案的最终口头辩论预计将于 2018 年 3 月进行。
访问加拿大的房地产数据
在加拿大,竞争局对多伦多房地产委员会提起诉讼,该委员会是一家非营利公司,经营一个收集房地产信息并向其成员发布的在线系统。TREB 的政策限制其成员交流和分发其收集的一些数据,如销售价格。
Photo by Giammarco Boscaro on Unsplash
竞争管理局辩称,这种对数字化数据的限制性分发阻止了竞争,也阻碍了创新和新商业模式的出现,因为它禁止房地产经纪人在其网站上发布销售数据。2017 年 12 月,联邦上诉法院支持竞争局,并命令 TREB 允许其成员在网上分享上市房产的销售历史。[6]
这一决定预计将在加拿大对组织如何在市场上分发数据和请求更开放的数据产生广泛的影响。
因此,拥有更加开放的公共数据集可以促进更加面向公益的商品和服务的发展。
**我们的建议如下:**创建数据共享标准,这些标准由垂直行业驱动,以支持研究人员、年轻企业家等。为公众利益制造产品和服务。通用数据保护条例(GDPR) [7]将于 2018 年 5 月 25 日生效,这开创了一个宽松的先例(当公司要求他们能够在他们要求时以标准化格式提供关于用户的数据)——随着这一条例的生效,看看公司如何决定采用可以跨不同数据处理器解释的标准将是有趣的(该术语在 GDPR 用于指用户可以在不同服务提供商之间切换)。
公共数据共享的一些潜在缺点
更开放的数据政策也有其寒蝉效应。即使公开共享匿名化的数据集也可能是一项挑战,因为复杂的统计方法加上马赛克效应(一种用于组合来自不同来源的信息以创建更丰富的目标概况的技术)可能会逆转匿名化过程。事实上,考虑到去年 41%的加拿大公司在安全漏洞后有敏感数据被盗,数据共享可能会危及用户敏感信息的隐私。[8]
这一点已经在过去多次得到证明。其中一种情况是,用户的性取向是从网飞公开发布的数据集[9]中的电影评级中推断出来的,这是通过交叉引用 IMDB 上对这些数据集之间常见的某些罕见电影的评级来实现的。
在另一个案例中,AOL 向公众发布了搜索查询,具体到用户的家庭住址、医疗需求、宠物主人等等。[10]
还必须考虑到,尽管用户可能已经接受通过条款和条件收集和分享其个人数据,但他们的同意是否实际有效仍存在争议。当与深度学习方法结合时,不同数据集的链接也可能导致身份欺诈的风险[11]。为了保护用户的隐私,我们需要制定法律和技术机制,在保护个人隐私的同时,鼓励和平衡这些数据集的共享。
另一个想法可能是允许类似微支付的报酬模式,在这种模式下,可以获得用户的明确同意,使用他们的数据执行特定的活动。用户对其数据隐私的强烈需求以及他们对侵犯这一权利的服务的潜在抵制可能会刺激这种行为。
你同意来自企业的大型数据集有助于推动公益研究的观点吗?做这件事的最好方法是什么?在评论区分享你的想法,让我们知道。
关于我在人工智能道德发展方面所做工作的更多信息,请访问https://ATG-abhishek . github . io
参考文献:
[1]脸书如何找出你见过的每个人—https://gizmodo . com/How-Facebook-figures-out-every one-you ve-even-met-1819822691
[2]人工智能将为全球经济增加 15.7 万亿美元—https://www . Bloomberg . com/news/articles/2017-06-28/AI-seen-adding-15-7 万亿美元—全球经济的游戏规则改变者
[3]数据正在催生新经济—https://www . economist . com/news/briefing/21721634-how-it-shaping-up-Data-rise-new-economy
[5] LinkedIn 无法阻止 Startup 抓取公共个人资料数据,美国法官规则—https://gadgets . ndtv . com/social-networking/news/LinkedIn-Cannot-Block-Startup-From-Scraping-Public-Profile-Data-US-Judge-Rules-1738096
[6]上诉法院维持命令房地产经纪人公开房屋销售数据的裁决——www.cbc.ca/news/busine…
[7]欧盟 GDPR—www.eugdpr.org/
[8]安全漏洞代价高昂—https://www . investment executive . com/news/industry-news/Security-breakes-prove-cost/
[9]Arvind Narayan an 和 Vitaly Shmatikov 对大型数据集进行稳健的去匿名化处理—arxiv.org/pdf/cs/0610…
[10]AOL 搜索者暴露了一张脸№4417749—www.nytimes.com/2006/08/09/…
[11]Abhishek Gupta 著《欺诈的演变:大规模数据泄露和广泛人工智能解决方案部署时代的伦理含义》——www.itu.int/en/journal/…
Fast.ai 深度学习课程第一课
在之前的帖子中,我尝试演示了 fast.ai 的“入门”部分。第 1 课也是从解释安装开始的。获取笔记本和辅助文件对实施至关重要。这些文件的最新版本在 github ( utils , vgg16 , vgg16bn )中。
训练需要结构化数据。训练文件夹里有 12500 张狗的照片和 12500 张猫的照片。总共 25000 张照片中的 2000 张照片将被移至有效组。此外,为了快速获得洞察力,为每个类别(猫、狗)创建包含 20-50 张照片的样本文件夹将非常有用。
AWS 回复了我的 p2 使用请求,因此我可以使用它。首先,由于价格原因,我尝试使用现货实例。虽然按需实例的成本为 0.90 美元/小时,但根据您的出价,现货实例的成本可能是这个价格的四分之一。然而,这种方法也有一些缺点。当有人出价高于你的出价时,你的实例将在两分钟内关闭。因为 EBS,你不能保存你的作品。解决这个问题的一种方法是在终止前分离磁盘,但是这需要停止实例。它立即终止,我不能分离它。AMI 的一些功能在 spot 中并不有用,因为它是为点播而准备的。我不想浪费更多的时间,所以我回到了按需服务,尽管它很贵。
让我们返回终点站。Aws-alias.sh 使得在终端上连接 Aws 变得容易。只是写 aws-start 然后用 aws-ssh 登录。登录后,不要惊讶当你开始 jupyter 笔记本。用“dl_course”加密。一切正常。
您将通过这些页面学习使用 Kaggle CLI。使用 Kaggle CLI,可以下载数据和提交解决方案。
Screenshot by the author
第一课之后,笔记中有家庭作业部分。我很难从模型中获得结果并创建预测文件来提交 Kaggle。经过在论坛上的研究,这些文件被放在 github 页面的教程中。
这个笔记本帮助我创建提交文件。我将我的文件结构和方法与这个笔记本进行了比较。在我完成提交并开始第 2 课之后,这个文件在那里被提到。所以,你应该首先尝试你自己的,这是非常重要的学习。否则你只会复制代码。
作为作业的结果,我把我的作品提交给了 Kaggle 竞赛。这是一个粗略的解决方案,所以我得到了这个结果:
Screenshot by the author
第 2 课涉及更多的概念,我会用深入的知识来创作文章。
从我的第一个数据科学项目中获得的经验
我作为一名数据科学家开始了我的职业生涯&分享交付我的第一个全功能数据科学管道的经验。
回顾过去,我意识到我犯了很多错误并且对这个领域有很多误解!
1.数据很乱
与 Kaggle 不同,现实生活中的数据并不总是在漂亮的 CSV 文件中。
您经常会遇到数据以不太理想的格式存储的情况,如 PDF/DOC/DOCX/XML/HTML 等。根据需要提取的数据,原始数据可用的格式会大大增加实际提取的难度。
在我们的例子中,我们有大量的数据存储在 pdf 中。如果您遇到这种情况,这里有一些方便的开源库:
2.标签数据并不总是可用的
机器学习领域(肯定是深度学习领域)的一大障碍是缺乏高质量的标记数据。这通常会导致使用监督方法解决手头问题不可行的情况。
通常有三种方法可以解决好的标记数据不可用的问题:
- 雇佣一群可以为你手工标注数据的人
- 使用 Amazon Turk、tractable.ai、mighty.ai 等付费工具。
- 向无监督学习问好。
在你决定向你的老板寻求第(一)或第(二)种选择之前,先获得以下问题的答案
- 与无监督方法相比,有监督方法有哪些改进?(这并不容易)
- 对于这样的改进,我需要多少标记数据?
- 项目是否有完成任务所需的时间和资金?
3.更多的数据不会自动带来更好的性能
有些时候,更多的数据会有帮助,有些时候则没有。
如果更多的数据对您的模型的性能几乎没有影响,请问自己以下问题
- 对于分类器/回归器来说,我的特征是否足以预测结果?
- 该模型是否存在高偏差或高方差?
- 是数据太吵了?
- 预处理做的对吗?(在涉及自然语言处理的问题中极其重要)
永远记住:垃圾入=> PREDICTIVE MODEL = >垃圾出
4.保持事情简单
深度学习和如下流行图表的最新进展导致许多人认为深度学习方法应该永远是第一选择。
我不这么认为。深度学习方法不能保证总是比传统方法产生更好的结果。即使他们这样做了,他们几乎总是以牺牲可解释性为代价。维护数据科学中的可解释性很难,但很重要。
为什么可解释性很重要?
高度的可解释性有助于您改进工作,并更有效地与非数据科学领域的人交流。
让我们举一个例子,你开发了一个 3 层的神经网络。不仅很难确定错误预测的根本原因,而且向没有数据科学背景的人传达下面导致预测的等式将是一场噩梦。
根据我的经验,应该按照以下顺序解决问题:
- 手工管理的试探法(对于循环、If/Then 条件)
- 简单的机器学习算法(线性回归、逻辑回归、决策树等。)
- 高级机器学习算法(RandomForest,XGBoost 等。)
- 浅层神经网络
- 深度神经网络
5.始终保持文档更新
我知道这听起来像编程 101。所以我为什么要重复?
数据科学项目是迭代的。你的第一个模特永远不会是你的最后一个。拥有一个记录良好的代码将确保您(和其他人)在稍后重新访问您的方法时理解它。
6.模块化编程使事情变得更容易
随着您的管道开始变得更加复杂,代码库也会变得更加复杂。
现在想象一下,你需要在管道中做一个小小的改变。但是所有的步骤都在一个大的功能块中执行。如何在不破坏管道的情况下做出相关的改变?
拥有多个执行独立任务的函数和一个调用所有其他函数的主函数使得执行更改更加容易。这有助于提高代码的可读性,因为它有助于很容易地将代码追溯到特定的操作。
7.变量应该是人类可以理解的
避免制造 df/data 之类的变量。不是所有的东西都是熊猫的数据框架!
如果你已经有了一个正在运行的项目,我建议你回去改变变量。如果你懒得到处改变变量,可以使用 PyCharm 中的内置函数,比如refractor
8.单元测试很重要
这是软件开发的长期最佳实践,但在数据科学等定量领域被低估了。单元测试的主要需求来自于数据科学项目是迭代的这一事实。这需要你和其他人不时地回到同一个代码库。在设计单元测试时,确保(ii)它们覆盖了您对函数的预先假设(ii)其他人在查看代码库时可以立即识别该函数试图实现什么。
要了解更多关于数据科学中的单元测试,请查看由 Mohammed Sunasra 撰写的这篇文章
结论
你的第一个数据科学项目将会既令人沮丧又充满乐趣。你从 MOOCs,Kaggle 等开始。并开始欣赏其他东西,如通信、应用程序可伸缩性、表示和可解释性。
如果你想联系我,可以通过 Linkedin 联系我,或者通过 k.mathur68@gmail.com 联系我。
感谢您的阅读!
利用机器学习构建视频烟雾探测器
Results from a smoking detection classification model
作为一个花了很多时间与实现机器学习的媒体公司合作的人,我被问及很多关于在视频中检测吸烟的能力。对于向其他国家分发媒体内容来说,这是一个大问题,但它也要求我们就人工智能的现状提出一些棘手的问题。这个故事记录了我试图建立和测试一个机器学习模型来检测电影中人们何时吸烟的尝试,也是我所学的总结。
为什么抽烟?
Come on Johnny — stop blowing smoke in my face
吸烟实际上是一个很难分类的行为,甚至只是想想这个问题就迫使你在 computer-sand 中画一些线,这对建立机器学习模型很重要。吸烟仅仅是吸一口烟的行为吗?点根烟怎么样?或者只是用手指捏着一根冒烟的白棍子?如果你在屏幕上看不到香烟,但有一些白烟从角色的鼻子或嘴里冒出来,这是吸烟吗?
不同的国家对电影和电视中如何描述吸烟有不同的规定。例如,在土耳其,电视广播不得不模糊吸烟的内容。搞砸了会让你被政府罚款。
因此,如果我们能够建立一个机器学习模型来检测电影或电视中的吸烟,我们可能能够帮助一些人节省大量时间和金钱,而不用手动操作。
但是从图像识别的角度来看,这是一个很难解决的问题。
培养
我们希望检测电影中的吸烟,因此训练数据的自然来源是人们吸烟的电影。在 YouTube 上快速搜索发现了几个视频,本质上是电影中人们吸烟的超级剪辑。
成功的关键是找到有人们吸烟镜头的视频,以及同样的人,最好是在同一个场景,不吸烟的镜头。这是关键。你需要告诉分类器什么是吸烟,就像你需要告诉它什么不是吸烟一样。
因此,我打开了 good ol' iMovie,将 YouTube 视频放入项目中。然后我仔细检查并精心编辑了人们吸烟的画面。我对嘴里叼着香烟的人划清界限。我保存了那个奇怪的新视频,并将其导出到一个文件中。
然后我编辑了一串相同场景的画面,但是在香烟进入嘴里之前或之后(多么奇怪的句子)。
现在我有两个视频,长度略有不同,一个有吸烟,另一个没有。下一步是将它们切成帧,以便我可以教授机器学习模型。
幸运的是,这部分很容易。只要打开终端,确保你已经安装了 FFMPEG ,并输入以下命令:
$ffmpeg -i path/tp/video.mp4 path/to/output/label%04d.jpg -hide_banner
在每个视频上运行,把你所有的帧放进标有“吸烟”和“不吸烟”的文件夹里。
现在,您可能在每个文件夹中有不同数量的 jpegs,所以我们将不得不删除一些以确保两个类以平衡的方式训练。如果一个类太多,模型就会偏向那个类。但是你也不能仅仅从一个类中选择 X 个文件来删除,你必须随机地删除这些文件,以免进一步影响模型。
我花了太多时间在网上搜索,试图找出如何从文件夹中随机删除 X 个文件。我最终使用了这个终端命令(N 是您想要删除的文件数):
$ ls |sort -R |tail -$N |xargs rm
好了,现在我们在每个文件夹中有相同数量的图像,是时候使用一些由机器盒提供的漂亮工具了。
下载并运行开源工具[imgclass](https://github.com/machinebox/toys/tree/master/imgclass),它会为你处理大量训练和验证数据的困难部分。它要求你有分类框在后台运行,所以确保你已经下载了。
当您运行 imgclass 时,它将:
- 扫描目录。
- 分离出 80%的数据,用这些数据来教机器学习模型。
- 用剩余的 20%数据验证准确性。
当我这样做的时候,我得到了大约97%的精确度,这似乎高得令人怀疑。我可能让模型过拟合了,但是为了确定,我们必须测试。
测试
所以我现在有了一个经过训练的机器学习模型,可以检测视频中的吸烟情况。但不知道效果如何。我需要找到其他不属于训练集的人们吸烟的视频。所以我回到 YouTube,下载了一段《广告狂人》的视频。我知道,只是从编辑训练数据,没有场景从广告狂人在训练集,所以这应该是一个很好的测试。但是怎么考呢?
这是最难的部分。我需要将视频分割成帧,并在 Classificationbox 中针对训练好的模型运行每一帧,然后评估结果。
“但是你是怎么做到的呢?”我对着猫尖叫。
如果你有任何脚本印章,他们将在这一点上派上用场。如果你没有,你需要使用一个平台来处理视频,训练分类框(或其他机器学习模型),并在某种 UI 中显示结果,这样你就可以验证准确性。我使用的一个非常方便的程序叫 aiWARE,它可以让你注册并免费运行这类测试,而不需要写任何代码。
如果你对写代码感兴趣,那么你会发现接下来的这一点令人厌恶。这里有一个 Golang 脚本,我用机器学习模型来验证一个视频文件(在文件夹中被分割成帧),将结果打印到帧上,并将该帧输出为 PNG。然后,我可以使用 FFMPEG 将所有打印的帧组合成一个视频,作为后期处理。
下面是一个输出示例:
如果我更擅长计算机,我可能会想出如何让那个该死的标签变得更大,但是我会把它留给真正的程序员去想(可能很快)。
接下来,我将所有帧拼接成一个视频,以便我可以观看整个场景,并判断我的机器学习模型。
$ ffmpeg -i [label]%04d.png -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4
注意到左上角的小标签了吗?戴上你的眼镜…现在你看到了吗?这是一个很好的方式来直观地看到你的模型在任何给定的视频上做得有多好。分数也很重要,因为它从模型中给你一些反馈,告诉你你发送给它的东西在一个特定的类中有多确定。
一旦你在 10 个视频中尝试了这种方法,你将开始看到置信度的一种模式,你可以开始忽略任何低于某个阈值的东西。
太好了,现在怎么办?
让吸烟检测为您的用例工作的关键是实验。如果你有合适的工具,实验会很简单,也很划算。
现在我已经从我的模型中获得了一些反馈,我可能会尝试教它越来越多的吸烟和不吸烟的例子,看看我是否可以减少假阳性和假阴性。
理想情况下,我会从我的真实用例中尽可能多地抓取例子,并将其分解成框架进行教学。
分类框的好处在于它支持在线教学。您可以在它运行时教授它,而不必重新部署或经历昂贵的培训周期。随着时间的推移,当你从它自己的结果中给它反馈时,这让你逐渐地改进它。
这是机器学习成功的秘诀。我无数次看到它工作。把精力花在你的训练数据上。
根据您的数据训练的模型将始终优于根据通用数据训练的模型。
所以现在你有了自己做这件事的工具。如果你用自己的分类框或者在 aiWARE 内部开发了一个很棒的模型,请确保你截取了一些截图,在 Medium 上与我们分享,或者通过推特发给我们玛奇纳——@ machineboxio
经验教训:Python 3 的数字海洋
这篇文章是正在进行的系列文章的一部分。我花很多时间尝试新技术。更多的时候,是因为一个类似于:“你应该试试【在此插入技术】,超级简单!”。
事实证明这种情况很少发生,所以每次我花几个小时试图让一些东西工作时,我都会发布我的解决方案,以及我在这个过程中学到的任何技巧和诀窍。
Digital Ocean 是一家基于云的服务器提供商,拥有非常合理的计划,允许您将计算从您的计算机转移到云中,从而节省您的时间并保持您的计算机新鲜!
我最初按照孙铁麟·梅斯特的教程进行设置,但很快意识到我想做得更多(尽管我强烈推荐该系列的其余部分,从命令行的数据科学)。这被证明是有点棘手,所以这里是我的演练。
1.注册
前往数字海洋并创建一个账户,使用 Paypal 或信用卡(如果你使用上面的链接,你将获得一些免费积分,我也会。如果你不想这样做,只需点击这里)。
如果你是学生,你还可以从 Github 学生包中获得 50 美元的积分(我也强烈推荐)。当我注册时,Digital Ocean 最初不接受我的代码,但我提交了一张支持票,他们在几个小时内就把它记入了帐户。
2.你的第一滴
Droplets 是专门为您保留的服务器空间。你只有在有液滴的时候才会带电(不管它是开着还是关着),但创造和破坏它们很容易,所以不用担心在你不积极使用它的时候会带电。
在“DO”面板的右上角(如果您还没有 Droplet,则在中间),找到“创建 Droplet”按钮。
单击它会将您带到设置页面。第一个选项是图像:
您将没有快照选项(稍后会详细介绍),但是默认选项(Ubuntu)是我们想要的,所以您在这里不需要做任何事情。
第二个选择是定价计划:
在这里你可以看到你得到了什么,以及它的价格。水滴存在的时间是按小时收费的,所以除非你结束后不删除它,否则你的费用会比每月报价低很多。
你选择哪一个取决于几件事:
- 你要载入内存的文件有多大?(例如熊猫数据帧)。价格下面第一行是水滴有多少内存/多少 CPU。
- 你的流程可以分布式吗?(想想
sklearn njobs= -1)。如果可以的话,多个 CPU 会加快处理速度。同样,如果您有大量数据,将数据分成两半并同时运行作业将节省时间,但这仅适用于具有 1 个以上 CPU 的 droplets。 - 你要上传的数据文件有多大?这是第二行,可用的存储量。
- 最后一行表示允许的数据传输量(上传+下载)。除非你在做非常疯狂的事情,否则 1TB 足够了。
我建议开始时选择 5 美元/月。如果你碰壁了,升级很容易。
第三步是添加块存储。最初你不需要这个。
第四是选择数据中心:
我在爱尔兰,所以选择了伦敦。选择离你最近的。
最后一步是启用监控(稍后会详细介绍)并给你的 droplet 起一个真正有用的名字!
然后点击创建水滴,大约一分钟后,你就一切就绪了!
3.初始设置和快照
当你完成后,你会收到一封电子邮件从数字海洋与 IP 地址,用户名和密码。复制 IP 地址,启动命令行并输入:
ssh root@[IP Address]
如果这挂起并且没有任何反应,您可以尝试:
ping [IP Address]
看看你是否有联系。如果没有,你可能被外部防火墙(你的工作单位或大学)阻挡了。这发生在我身上,你无能为力:
Hit CTRL-C to stop it after 10 or so packets
如果你确实收到了ssh root@[IP Address]的回复,会有一堆短信问你是否要继续。写下yes并按回车键。
然后会要求您输入密码。从邮件中复制并粘贴,然后按回车键。然后,您需要更改 root 密码。这样做很安全,因为你不会经常登录 root,但如果其他人这样做,他们完全可以破坏你的 droplet。
接下来,您想要创建一个用户:
adduser [username]
其中[用户名]是您想要的任何东西。
你必须为这个用户创建一个密码,它会要求你提供一些个人信息。如果你愿意,输入这个,或者跳过它(按回车键),都没关系。
接下来,给你的新帐户权限在服务器上做事情
usermod -aG sudo [username]
gpasswd -a [username] sudo
这使您能够在不登录 root 用户的情况下进行更改。
最后,更改时区:
sudo dpkg-reconfigure tzdata
并选择您当前所在的城市。
不错!我们都在 root 上设置好了。现在,我们可以退出并检查您的用户帐户。
exitssh [username]@[IP Address]
登录后,第一步是配置 bash 配置文件,让您的生活更轻松。
nano .profile
如果你以前没有用过 Nano,它是一个简单的文本编辑器。使用箭头键移动,Ctrl+k剪切一行,Ctrl+u粘贴一行,Ctrl+o保存,Ctrl-x退出。
您可以在这里添加别名(快捷方式)以使生活更轻松。我使用 Python 3 和 Pip 3,所以我通常通过设置来避免混淆:
alias python="python3"
alias pip="pip3"
当我想更改或检查我的 bash 配置文件时,我也讨厌键入nano ~/.profile,所以我也使用别名:
alias obp="nano ~/.profile"
alias sbp="source ~/.profile"
您还可以在此添加任何其他别名。用Ctrl+o保存,用Ctrl-x退出。
要实现这些更改,您需要获取概要文件:
source .profile
(顺便说一句,在找到新的别名快捷方式之前,不能使用它们,所以简单地输入sbp还不行,但是在你找到它之后就可以了)。
apt-get有点像命令行的 Pip,应该在我们继续之前更新。
sudo apt-get update
Python 3 已经安装了,但是 Pip 还没有,所以让我们继续获取并更新它:
sudo apt-get install python3-pip
pip install -upgrade pip
现在你可以pip install你所有的常规 Python 包了!你马上就可以。出于某种原因,Matplotlib 和其他一些软件包在 Ubuntu 上有问题,但是您可以通过运行以下命令来解决这些问题:
sudo apt-get install libfreetype6-dev libxft-dev
sudo apt-get install python-setuptools
太好了,现在你可以用pip3 install发疯了。如果您有一个用于所有安装的requirements.txt文件,现在就可以运行它。
最后, AG 是非标准的命令行搜索工具,所以如果你愿意,你也可以安装它:
sudo apt install silversearcher-ag
太好了,你都准备好了!现在,这是一个相当大的工作量,每次都必须这样做是很糟糕的。这就是数字海洋快照的用武之地!
这是一种将你当前的 droplet“另存为”的方法,这样当你下次创建一个新的 droplet 时,你就可以加载那个图像,然后你就可以从你离开的地方开始了!完美。
使用sudo poweroff关闭你的 droplet,进入你的数字海洋 droplet 页面上的快照菜单项:
快照不是免费的,它们每月每 Gb 0.05 美元。我在安装 Pandas、Numpy、Matplotlib 和其他一些软件包时拍摄的快照是 1.85Gb,所以每年大约是 1.11 美元。考虑到每次设置一个水滴会节省你 10 分钟,还不错!
由于您的 droplet 已经关闭,请点击“拍摄实时快照”按钮,数字海洋将完成剩下的工作。
这里有一个旁注,你似乎不能从一个更便宜的液滴定价方案中读出一个快照。只是一些需要记住的事情。
如果你想升级你的定价方案,请点击“调整大小”菜单项。同样,你不能在这里降级,如果你想,你需要从头开始创建一个 droplet,并重复上述步骤。
要重新打开 droplet,请前往数字海洋,在 droplet 页面的右上角有一个开/关开关。重新打开它,你就可以上传数据了。
4.通过 SFTP 上传数据
现在,如果你的个人电脑上有数据,想把它上传到云端,你需要通过 SFTP(安全文件传输协议)来实现。这是相当容易的,虽然它没有闪电快。
首先,建立一个 SFTP 连接:
sftp [username]@[IP Address]
现在,您可以使用普通的命令行功能,如cd、ls和pwd,在服务器上的文件系统中移动。然而,由于某种原因,自动完成(tab)在 SFTP 上不起作用。出于这个原因,我建议把你所有的文件和代码上传到主目录,然后用ssh重新登录,用mv和自动完成功能移动内容。相信我,这简单多了。
那是在服务器端,但是在你的个人电脑上移动呢?同样的命令也可以工作,但是你需要在它们前面加上一个额外的l,即lcd、lls和lpwd。找到本地保存文件的目录,然后使用以下命令将它们上传到服务器:
put [localFile]
或者对于整个目录:
put -r [localDirectory]
这并不算快,对于我的 1.5Gb 数据文件,每个文件大约需要 20 分钟。很烦人,但是你能做的不多。您可以并行上传,但这意味着打开一个新的命令行标签,并再次登录 SFTP,再加上两个连接都慢了一半,所以总时间是一样的:(
您可以通过运行以下命令来查看您使用了多少存储空间:
df -h
作为将来的参考,从服务器下载文件非常简单:
get [remoteFile]
或者
get -r [remoteDirectory]
现在,一旦你的数据文件上传到服务器上,你也可以上传你的 python 脚本了。如果您的本地目录配置与远程目录配置不同,请确保更改代码中的任何文件位置。
从服务器上删除文件也和本地略有不同,因为rm -rf directory不起作用。你需要rm filename删除一个文件,或者清空一个目录然后rmdir directory删除一个文件夹。
这足以让你开始,但如果你对更高级的选项感兴趣,这里有一个很好的教程。
我强烈建议在数据的小子集上本地测试你的所有代码(我使用 PyCharm,它很棒,也有免费的学生许可证。)通过远程连接进行故障排除可能很烦人。
5.运行计算
现在,你已经准备好运行一些计算了。使用ssh重新登录,整理所有文件,使用python filename.py运行任何代码,就像在本地计算机上一样。
如果当你尝试运行一些代码时得到一个Killed响应,这意味着你没有足够的内存来完成这项工作。你有两个选择。关闭并升级您的定价方案,或者创建一个交换文件(更多信息见下文)。
打印错误日志将为您提供关于错误的更多信息:
sudo cat /var/log/kern.log
您可以在数字海洋仪表板上监控作业进度,该仪表板显示了一些漂亮的使用图表:
您甚至可以设置警报,以便在指标低于某个级别(如 CPU)时收到电子邮件,这可以用来让您知道工作何时完成!单击图形页面顶部的“创建警报策略”进行类似设置。
一旦你完成了你的处理,你可以使用 SFTP 从云中get你的文件,然后销毁 droplet,这样你就不会继续被收费了!
现在给你一个警告:写入文件时要小心。
我浪费了很多时间运行一个pandas apply函数,然后用df.to_csv('filename')保存结果。如果服务器有任何问题(很可能会有,下面会有更多),在写入文件之前,您将会丢失所有内容。
我的解决方法是遍历整个数据框并逐行打印结果:
*for* row *in* range(len(df.index)):
col_value = df.ix[row,:].values[2]
ind = df.index[row]
with open("./data_file.csv", "a") as file:
file.write(ind + ',' + function(col_value) + '\n')
这实际上是将我的数据写入了csv,然后我就可以根据索引值合并数据帧来排列数据。
result = pd.concat([df, new_data], axis=1, join_axes=[df.index])
没有apply漂亮,但是有时当处理这种规模的数据时,最好牺牲一些性能来确保您确实得到了您想要的数据!
6.提高性能
DO 最大的好处之一是,您的 droplet 中可以有多达 20 个 CPU,它们可以并行运行处理。这比在一个 CPU 上处理所有数据要快得多。
您应该知道您的计划有多少个 CPU,但是如果不知道,您可以使用下面的代码来检查:
cat /proc/cpuinfo | grep processor | wc -l
我有 2 个,所以这意味着我可以同时运行两个进程。在我看来,这不会减慢任何一个过程,所以如果你把任务分成两半,你可以有效地工作两倍的速度。最好的方法是将所有的数据分成两半,然后对每个数据运行相同的脚本。在 Python 中,在用 pandas 导入您的数据后,我会添加以下代码。
import sysnumber_of_cores = 2
length_of_df = len(df.index)
stream = sys.argv[1]if stream == 1:
start = 0
end = length_of_df // number_of_cores
else:
start = length_of_df // number_of_cores
end = -1data_to_process = df.iloc[start:end,:]output_filename = "output_data_" + str(sys.argv[1]) + ".csv
然后,您可以从命令行运行
python script.py 1
它将处理前半部分的数据
python script.py 2
它将处理第二个。使用以下命令在最后合并两个数据文件
cat output_data_2.csv >> output_data_1.csv
7.解决纷争
我最头疼的是让我的脚本运行完成。出于某种原因(我从来没有弄清楚),服务器会停止运行我的处理,然后我不得不手动重启它。我的使用图表如下所示:
真的不理想,尤其是我的大学防火墙阻止了我的连接,所以我不得不等到我回家重启东西。
我的解决方案的第一部分是找出 for 循环的重新开始点,这样我就不用重新计算了。我使用了subprocess模块,这样我就可以在 python 脚本中运行命令行函数:
import subprocessstream = int(sys.argv[1])if stream == 1:
stop = 3387532
data = "./data.csv" a = subprocess.Popen(['wc', '-l', data], stdout=subprocess.PIPE)
wc = int(a.communicate()[0].rstrip().decode().split(' ')[0]) start = 0 + wc
我的文件中的总行数是 6,775,065,我有 2 个 CPU,所以像上面一样,我将停止索引设置为文件大小的一半。subprocess.Popen返回命令行函数的结果,在本例中是wc -l ./data.csv,或者检查输出数据中的行数。stout=subprocess.PIPE使输出更容易处理。下一行检索输出数据的实际行数,然后start被相应地设置为。
这意味着每当系统崩溃时,我可以简单地运行:
python script.py 1;
python script.py 2;
在不同的终端屏幕上,我的两半数据会在适当的地方重新启动。一个好结果!
然而,这并没有阻止我的服务器崩溃,也没有在崩溃后自动重启处理。一些研究让我想到了 crontabs,它允许在特定的时间段评估函数。您可以通过以下方式查看当前的 crontabs:
crontab -l
这里不应该有任何东西,所以您可以使用以下命令创建一个:
crontab -e
第一次,你会被要求选择一个文本编辑器,Nano 是最简单的,但是这可以在以后通过运行'select-editor'来改变
我不会讲太多细节,但是文件的最后一行看起来是这样的:
# m h dom mon dow command
这代表分钟、小时、月、日和命令。这允许您将命令设置为在特定的时间间隔运行。几个例子:
*/10 * * * * eval "python3 script.py"
每 10 分钟运行一次脚本。
10 * * * * eval "python3 script.py"
每小时在整点后 10 分钟运行脚本。
10 5 * * 3 eval "python3 script.py"
每周三 5 点 10 分运行脚本。
你明白了。对我来说,我想每 10 分钟检查一次我的服务器是否崩溃,如果是,重启它。所以我的 crontabs 是:
*/10 * * * * eval "python3 sys_test_1.py"
*/10 * * * * eval "python3 sys_test_2.py"
(我必须有两个,因为从同一个文件在不同的 CPU 上运行 python 脚本很困难,这样更容易)。如果你感兴趣,这里有更多关于 crontabs 的详细解释。
然后我的文件sys_test_1.py看起来像这样:
data = "./data.csv"a = subprocess.Popen(['wc', '-l', data], stdout=subprocess.PIPE)
wc_1 = int(a.communicate()[0].rstrip().decode().split(' ')[0])if wc_1 > 3387530:
exit()
else:
time.sleep(15) b = subprocess.Popen(['wc', '-l', data], stdout=subprocess.PIPE)
wc_2 = int(b.communicate()[0].rstrip().decode().split(' ')[0]) if wc_1 == wc_2:
subprocess.call(["python3", "run_comp.py", "1"])
所以我检查文件中的行数,如果超过了某个阈值(即接近所需计算的末尾),就退出。否则,等待 15 秒并再次检查文件长度。如果它们相同,这意味着没有正在进行的计算,所以它从命令行调用计算脚本。
注意,我特别调用了'python3',尽管我在 bash 配置文件中设置了一个别名alias python="python3"。用子进程调用 python 脚本似乎会忽略别名,所以要记住这一点。
因此,每 10 分钟运行一次,我就有办法检查是否有问题,如果有问题,就自动重新开始处理。自从我修复了这个问题,我的服务器就一直不停地运行,任何崩溃都会被快速捕获,处理会重新开始。
完美!
现在你知道了!您现在知道如何在云服务器上创建、设置、上传数据和运行脚本了!大数据,你来了!
下面有更多关于交换文件的解释,但那是可选的阅读…
如果你喜欢这篇文章,请点击❤按钮让你的粉丝知道,或者让我知道你的想法。
交换文件
交换文件是一种给你的 droplet 额外的内存的方法,通过对硬盘进行分区。这样,当系统内存不足时,它可以将一些数据保存到光盘上,以便以后检索。这将让你用更便宜的方案做更多的事情,但是速度会慢很多。请记住,升级您的计划可能会更好。
要创建交换文件,请运行
sudo fallocate -l 4G /swapfile
其中 4G 代表文件的大小,即 4 gb。这是您想要的内存大小。太大了,你就没有空间存放其他文件,太小了,你还是会耗尽内存。4 gb 应该没问题。
然后,您需要授予对该目录的写权限,创建交换文件,并激活它:
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
打开 fstab 文件:
sudo nano /etc/fstab
并添加到文件底部:
/swapfile none swap sw 0 0
有一个名为 swappiness(很棒的名字)的参数设置了内存交换到磁盘的数量和频率。值越高,交换的频率越高。我们不希望它交换那么多,所以我们希望将默认值(60%)更改为 10%。
sudo sysctl vm.swappiness=10
要将此设置为默认值,请打开:
sudo nano /etc/sysctl.conf
并添加到文件底部:
vm.swappiness=10
从跟踪的 1 万亿次事件中吸取的经验教训:网络研讨会总结
本月早些时候,我们在 Amplitude 达到了一个令人兴奋的里程碑:我们现在已经跟踪了超过 1 万亿的用户行为。
利用其中一些用户行为数据,我们分享了一种思考留存的新方法——括号留存—针对非日常使用的应用,而不是行业标准的“N 天”计算。
我们还举办了“最佳实践和从 1 万亿次跟踪事件中吸取的教训”,在此期间,Amplitude 首席执行官 Spenser Skates 分享了他在 Amplitude 工作四年期间学到的另外四条经验。
如果你错过了几周前斯宾塞的网上研讨会,不要担心。我们将在今天的帖子中概括这些课程。
要观看网上研讨会的录像,您也可以点击这里。
第一课:留住人才至关重要。
我们已经在 Amplitude 博客上讨论了很多关于为什么留住人才如此重要的内容。斯宾塞和他的联合创始人柯蒂斯开始建立 Amplitude 的主要原因之一是为了解决无法提高他们的第一款产品 Sonalight 的保留率的痛苦,sona light 是一款用于 Android 的语音识别应用程序。
随着 Amplitude 的建立,Spenser 意识到,留存率不仅对年轻的创始人和初创公司至关重要,对 App Store 中的顶级消费者应用程序、B2B 公司和企业等都很重要。事实上,对大多数企业来说,留住人才是成功的第一预测指标;这是对可持续增长至关重要的一个指标。
第二课:用户做什么比他们是谁更重要。
营销指标几乎总是包含描述性的人口统计数据。为了制定产品策略,团队通常会跟踪诸如性别/年龄、用户来自哪里以及使用的设备或平台等信息。
我们强调不要太看重你的用户是谁,而是更看重他们在做什么——这是用户行为分析的关键。了解用户在你的产品中的行为和浏览方式,会给你更多的指导,告诉你如何更好地塑造你的产品,让它继续为用户增加价值和乐趣。
斯宾塞解释说,这正是脸书击败许多早期社会竞争对手的原因。通过专注于观察在加入的十天内添加七个朋友是用户逗留的最佳预测,脸书能够建立一个以添加朋友和与朋友互动为中心的产品。他们很快击败了当时的主要竞争对手,包括 MySpace。
Spenser 还分享了我们的一个客户的故事,像 Etsy 这样的市场型产品希望提高其保留率。开发人员根据地理位置和设备类型等用户统计属性对活跃用户进行了细分。他们发现这些片段的保留率真的没有差别;相反,是一群买家都表现出了一种特定的行为——在这种情况下,这是在向卖家传递一种信息——显示出了留存率的显著提高。虽然人口统计数据(即“用户是谁”)没有显示出任何有助于产品变化的有用见解,但行为数据(“他们用户做什么”)却显示了这一点。
第三课:你产品的价值可能会让你吃惊。
你的产品是你的用户想要的,而不是你想要的*。有时候,行为分析可以发现你可以利用的产品的令人惊讶的用例。如果你能让更多的用户更快体验到这种价值,你就能让你的产品更上一层楼。*
冥想 app Calm 经历的恰恰是这一点。在寻找提高用户留存率的方法时,他们决定观察使用“设置提醒”的用户群与其他用户群相比留存率如何。他们发现,这些用户的留存率是当前用户的 3 倍。Calm 发现他们为用户提供的价值不仅仅是自我指导的冥想课程,他们还起到了提醒用户冥想的作用。
现在,Calm 正在尝试在入职流程的早期突出“设置提醒”功能,以便让他们的用户更快地体验到这一价值,从而保留更长时间。
你可以在这里阅读更多关于 Calm 的故事。
平静是一个简单的正念冥想应用程序,为他们的用户带来清晰和内心的平静。有了可靠的用户…
amplitude.com](amplitude.com/blog/2016/0…)
第四课:用户塑造产品
上周,我们分享了斯宾塞对打造更好产品的愿景。我们总结了我们的“经验教训”网络研讨会,简要介绍了这一重要趋势。产品开发已经发生了根本性的变化——发布用户必须学习和适应的打包软件不再是常态。现在,最好的公司通过行为数据直接与用户交流,以了解用户如何使用他们的产品,以及他们获得了什么价值。产品的调整和改进可以在极短的时间内完成。公司通过制造由用户塑造的产品而取胜。
请务必阅读斯宾塞的思想文章“让我们打造更好的产品”,以了解这一趋势以及 Amplitude 用户如何帮助塑造我们分析平台的全新版本。
在接下来的几个月中,我们将更深入地研究客户故事和数据,以补充这些课程,因此请在 Amplitude 博客和外部出版物中关注这些内容。如果您错过了网上研讨会,请点击这里!
有关系的
如果你从事移动应用业务,你可能听说过这个统计数据——80%的移动应用用户在……
amplitude.com](amplitude.com/blog/2016/1…) [## 让我们打造更好的产品|振幅博客
我们宣布了 Amplitude 2.0——我们产品分析平台的下一代产品。今天,我在分享背后的故事…
amplitude.com](amplitude.com/blog/2016/1…)
喜欢你读的吗?按下❤向你的追随者推荐这个!
原载于 2016 年 11 月 1 日amplitude.com。
将深度学习应用于无大数据的自然语言处理的经验教训
作为一名数据科学家,你最重要的技能之一应该是为你的问题选择正确的建模技术和算法。几个月前,我试图解决一个文本分类问题,即对哪些新闻文章与我的客户相关进行分类。
我只有几千个带标签的例子,所以我从简单的经典机器学习建模方法开始,如 TF-IDF 上的逻辑回归。这些模型通常对长文档(如新闻文章)的文本分类很有效,但在这项任务中的表现仅略好于 random。
在调查了我的模型的错误后,我发现单词包表示法对于这项任务来说是不够的,我需要一个模型,它将使用对文档更深层次的语义理解。
深度学习模型在翻译、问答、摘要、自然语言推理等需要深度理解文本的复杂任务中表现非常好。因此,这似乎是一个很好的方法,但深度学习通常是在成千上万甚至数百万的标记数据点上训练的,而我的数据集要小得多。
通常,我们需要大数据集进行深度学习,以避免过拟合。深度神经网络有许多许多参数,因此通常如果它们没有足够的数据,它们往往会记住训练集,在测试集上表现不佳。为了避免这种没有大数据的现象,我们需要使用特殊的技术。
在这篇文章中,我将展示我在文章、博客、论坛、Kaggle 和更多资源中找到的或我自己开发的一些方法,以便在没有大数据的情况下,让深度学习在我的任务中更好地工作。这些方法中有许多是基于计算机视觉中广泛使用的最佳实践。
一个小小的免责声明:我不是深度学习专家,这个项目是我第一个深度学习的大项目之一。这篇文章的所有内容都是基于我的经验,可能会在你的问题上有所不同。
正规化
正则化方法是在机器学习模型中以不同方式使用的方法,以避免过度拟合,这些方法具有强大的理论背景,并以通用的方式处理大多数问题。
L1 和 L2 正规化
这些方法可能是最古老的,并在许多机器学习模型中使用了许多年。在这种方法中,我们将权重大小添加到我们试图最小化的模型损失函数中。这样,模型将尝试使权重变小,对模型没有显著帮助的权重将减少到零,并且不会影响模型。这样,模型可以用来记忆训练集的权重数量就少得多。更多解释,可以阅读这篇的帖子。
辍学
Dropout 是另一种较新的正则化方法,它建议在训练时间内,神经网络中的每个节点(神经元)将以概率 p 被丢弃(权重将被设置为零),这样,网络就不能依赖于特定的神经元或神经元的交互,而必须学习网络不同部分的每个模式。这使得模型关注于归纳为新数据的重要模式。
提前停车
早期停止是一种简单的正则化方法,只需监控您的验证集性能,如果您发现验证性能停止提高,请停止训练。这种方法在没有大数据的情况下非常重要,因为模型往往会在 5-10 个时期甚至更早之后开始过度拟合。
少量参数
如果你没有一个大的数据集,你应该非常小心层的数量和每层中神经元的数量。此外,卷积层等特殊层的参数比全连接层少,因此当它们适合您的问题时使用它们非常有帮助。
数据扩充
数据扩充是一种通过以标签不变的方式更改训练数据来创建更多训练数据的方法。在计算机视觉中,许多图像变换用于增加数据集,如翻转、裁剪、缩放、旋转等。
Image data augmentation example
这些转换对图像数据很好,但对文本无效,例如,翻转“狗喜欢我”这样的句子不是有效的句子,使用它会使模型学习垃圾。以下是一些文本数据扩充方法:
同义词替换
在这种方法中,我们将文本中的随机单词替换为它们的同义词,例如,我们将把句子“我非常喜欢这部电影”改为“我非常爱这部电影”,这仍然具有相同的含义,并且可能具有相同的标签。这种方法对我不起作用,因为同义词有非常相似的词向量,所以该模型将两个句子视为几乎相同的句子,而不是一个扩充。
反向翻译
在这种方法中,我们获取文本,用机器翻译将其翻译成中间语言,然后再翻译回英语。这种方法在 Kaggle 毒性评论挑战中被成功使用。例如,如果我们将“我非常喜欢这部电影”翻译成俄语,我们会得到“мнеоченьнравитсяэтотфильм”,当我们翻译回英语时,我们会得到“我真的很喜欢这部电影”。反向翻译方法不仅像第一种方法一样给我们提供了同义词替换,而且它可以添加或删除单词,并在保留相同含义的情况下改写句子。
文件裁剪
新闻文章很长,在查看数据时,我发现我不需要所有的文章来对文档进行分类。另外,我看到文章的中心思想通常会重复几次。这让我想到把文章裁剪成几个子文档作为数据扩充,这样我会有更多的数据。首先,我尝试从文档中抽取几个句子并创建 10 个新文档。这创建了句子之间没有逻辑关系的文档,所以我得到了一个糟糕的分类器。我的第二个尝试是把每篇文章分成 5 个连续的句子。这种方法工作得非常好,给了我一个很好的性能提升。
生成对抗网络
GANs 是数据科学中最令人兴奋的最新进展之一,它们通常被用作图像创建的生成模型。这篇博文解释了如何使用 GANs 对图像数据进行数据扩充,但它也可能用于文本。
迁移学习
迁移学习是使用一个网络的权重,这个网络是针对另一个问题训练的,通常是针对你的问题的一个大数据集。迁移学习有时用作一些层的权重初始化,有时用作我们不再训练的特征提取器。在计算机视觉中,从预先训练的 Imagenet 模型开始是解决问题的一种非常常见的做法,但 NLP 没有像 Imagenet 那样的非常大的数据集,可以用于迁移学习。
预训练的单词向量
NLP 深度学习架构通常从一个嵌入层开始,该嵌入层将一个热编码单词转换为数字向量表示。我们可以从头开始训练嵌入层,但我们也可以使用预先训练的词向量,如 Word2Vec、FastText 或 Glove,它们使用无监督学习方法在大量数据上进行训练,或在来自我们领域的数据上进行训练。预先训练的单词向量非常有效,因为它们给出了基于大量数据的单词的模型上下文,并且减少了模型的参数数量,这显著降低了过度拟合的机会。你可以在这里阅读更多关于单词嵌入的内容。
预先训练好的句子向量
我们可以将模型的输入从单词改为句子,这样我们就可以用更少的参数得到更小的模型,但仍然有足够的表达能力。为了做到这一点,我们可以使用预先训练好的句子编码器,如脸书的推断器或谷歌的通用句子编码器。我们还可以使用像跳过思维向量或语言模型这样的方法,在我们领域的未标记数据上训练句子编码器。你可以从我的上一篇博文中了解更多关于无监督句子向量的知识。
预训练语言模型
最近的论文如 ULMFIT 、 Open-AI transformer 和 BERT 通过在非常大的语料库上预先训练语言模型,在许多 NLP 任务中获得了惊人的结果。语言模型是一项利用前面的单词来预测句子中的下一个单词的任务。对我来说,这种预先训练并没有真正有助于获得更好的结果,但是这些文章展示了一些我没有尝试过的有助于更好的微调的方法。这是一个关于预训练语言模型的伟大博客。
无监督或自我监督学习的预培训
如果我们有一个来自我们领域的未标记数据的大型数据集,我们可以使用无监督的方法,如自动编码器或屏蔽语言模型,仅使用文本本身来预训练我们的模型。另一个对我更有效的选择是自我监督。自监督模型是自动提取标签而无需人工标注的模型。一个很好的例子就是 Deepmoji 项目。在 Deepmoji 中,作者训练了一个模型来预测推文中的表情符号,在表情符号预测中获得良好结果后,他们使用他们的网络预训练了一个推文情绪分析模型,获得了最先进的结果。表情预测和情感分析显然非常相关,因此作为预训练任务,它表现得非常好。新闻数据的自我监督任务可以预测标题、报纸、评论数量、转发数量等等。自我监督可能是一种非常好的预训练方式,但通常很难判断什么样的代理标签将与您的真实标签相关联。
与公司网络中的其他人一起进行预培训
在许多公司中,许多机器学习模型都建立在相同的数据集或不同任务的相似数据集上。例如,对于推文,我们可以预测它的主题、情绪、转发次数等等。用一个已经在使用的网络对你的网络进行预训练可能是能做的最好的事情,对于我的任务来说,它给了性能一个很好的提升。
特征工程
我知道深度学习“扼杀”了特征工程,而且这样做有点过时了。但当你没有大数据时,用特征工程帮助网络学习复杂模式可以大大提高性能。例如,在我对新闻文章的分类中,作者、报纸、评论数量、标签和更多特征可以帮助预测我们的标签。
多模态建筑
我们可以使用多模态架构将文档级的特性结合到我们的模型中。在 multimodal 中,我们建立两个不同的网络,一个用于文本,一个用于特征,合并它们的输出层(没有 softmax)并添加几个层。这些模型很难训练,因为特征通常比文本具有更强的信号,因此网络主要学习特征效应。这是一本关于多式联运网络的很好的 Keras 教程。这种方法只提高了我不到 1%的性能。
词级特征
另一种类型的特征工程是单词级特征,如词性标注、语义角色标注、实体提取等等。我们可以将一个热编码表示或单词特征的嵌入与单词的嵌入相结合,并将其用作模型的输入。我们还可以在这种方法中使用其他单词特征,例如在情感分析任务中,我们可以使用情感词典,并为嵌入添加另一个维度,其中 1 表示我们词典中的单词,0 表示其他单词,这样模型可以轻松地学习它需要关注的一些单词。在我的任务中,我添加了某些重要实体的维度,这给了我一个很好的性能提升。
作为特征工程的预处理
最后一种特征工程方法是以一种模型更容易学习的方式对输入文本进行预处理。一个例子是特殊的“词干”,如果运动对于我们的标签不重要,我们可以将足球、棒球和网球改变为单词 sport,这将帮助网络了解运动之间的差异并不重要,并且可以减少网络中的参数数量。另一个例子是使用自动汇总。正如我之前所说,神经网络在长文本上表现不佳,所以我们可以对我们的文本运行类似“文本排名”的自动摘要算法,只给网络重要的句子。
我的模型
在我的案例中,在尝试了我在这篇文章中讨论的方法的不同组合后,最佳模型是来自这篇文章的分层注意力网络,其中退出和提前停止作为正则化,文档裁剪作为数据扩充。我使用了预先训练的单词向量,并对我的公司为该客户在相同数据上完成的另一项任务进行了预先训练。作为特征工程,我在单词嵌入中加入了实体单词级特征。基本模型的这些变化使我的准确性提高了近 10%,这使我的模型从略好于随机的模型变成了具有有价值的业务影响的模型。
使用小数据的深度学习作为一个研究领域仍处于早期阶段,但看起来它越来越受欢迎,特别是在预先训练的语言模型中,我希望研究人员和从业者将找到更多方法,使深度学习对每个数据集都有价值。
希望你喜欢我的帖子,非常欢迎你阅读和关注我的博客。
构建 R 包的经验教训
Make sure to have a hexagon logo ;)
我最近完成了我的 R 包的第一个发布版本,叫做sdmbench(github.com/boyanangelo…)。这个过程比我想象的要难,也出乎意料。在这里,我将向您提供一些我辛苦学到的经验,如果您打算构建自己的包,希望它们是有用的。
先说要点:
为什么您应该构建 R 包
R 在数据科学中如此受欢迎的原因之一是可用的开源软件包的数量(在 CRAN 上超过 10,000 个)。即使是一个在神秘领域工作的人,也一定能找到至少一个可以满足她/他需求的包。为这个庞大的社区做贡献本身就是一种强大的动力。
即使你有更自私的动机,如果它们变得流行,编写 R 包可以为你提供大量曝光。作为软件包作者所获得的信誉可能是一笔宝贵的职业资产。
最后,这也是组织工作的好方法。通常在数据科学中,你会在项目之间重用许多函数,最好是(保持干燥)将它们分开组织,并在需要时从包中调用它们。
入门指南
开始可能会让人不知所措,因为编写包涉及许多不熟悉的软件工程实践(例如单元测试和文档)。我读了哈德利·韦翰(是的,又是他)写的非常有条理的电子书,得到了很多帮助:r-pkgs.had.co.nz/。这是我在整个过程中的参考手册。
第一步是要有一个明确的目标,你想在包中包含什么功能,并相应地组织它们。良好的命名在这里是必不可少的,我更喜欢过于冗长而不是相反(看看这篇论文)。确保选择正确的抽象层次。大函数应该分解成小函数。
以下是好的和坏的对象名的例子,来自 Hadley 的风格指南:
*# Good*
day_one
day_1*# Bad*
first_day_of_the_month
DayOne
dayone
djm1
证明文件
编写函数文档有助于阐明你头脑中关于函数应该如何工作的许多想法。这就是为什么你应该这样做的原因之一,即使你不打算和其他人分享这个包。所提供的约束(即,您需要提供关于所有函数参数的信息)有助于迫使您变得彻底。
测试
正如 Hadley 在他的书中提到的,R 开发人员经常手工测试他们的代码。我认为这是因为 R 在设计上并不是一种通用的编程语言,因此它经常被用在不需要明确进行单元测试的系统中。如果你尽早编写测试,你仍然可以变得非常有效率。你不需要有 100%的测试覆盖率。从简单开始,在你工作的基础上构建。请务必阅读关于测试驱动开发 (TDD)的内容。好的测试也会帮助你自信地重构和编辑你的代码。下面是一个测试示例,向您展示这有多简单:
context("String length")
library(stringr)
test_that("str_length is number of characters", {
expect_equal(str_length("a"), 1)
expect_equal(str_length("ab"), 2)
expect_equal(str_length("abc"), 3)
})
我在这里遇到的一个小问题是测试从互联网下载数据的功能。在sdmbench案例中,我有一个从 GBIF 下载数据的函数。这些数据在每个后续的测试步骤中都要用到,所以它们必须包含在其他函数的测试中。这使得整个过程相当漫长(约 15 分钟)。如果这成为开发过程中的瓶颈,您可以通过单独下载数据集并在您的包和相关测试中使用它来解决。
持续集成
如果你没有传统软件开发的经验,很可能你甚至没有听说过这个术语。CI 工具为您提供了一个框架,以自动化的方式在您的代码上运行定制脚本。大多数情况下,每当一个变更被推送到存储库时,您将使用它来自动运行您的测试套件。最流行的解决方案之一是 Travis CI。
Wohoo, everything works!
包装简介
软件包文档提供了关于如何使用某些功能的说明,但是它太细了,没有展示更大的图景——软件包可以做什么。简介是概述典型工作流程的文档。在sdmbench的情况下,它显示了用户如何下载、预处理、可视化数据并比较在其上训练的机器学习模型。您应该记住,当您构建包时,也会检查小插图,这会增加 CI 时间。
Writing a good vignette also takes a while, akin to writing a paper.
后续步骤和最终想法
最重要的带回家的信息是,你一定要考虑打包你的代码,它可能会比你想象的要长!
作为下一步,你应该确保在社交媒体平台(尤其是 Twitter)上分享你的包,甚至更好——联系该领域中可能对它感兴趣的人。网上有许多研究人员社区(例如在 Research Gate )。你也可以把这个包提交给罗彭斯奇,甚至以论文的形式发表(乔斯)。你至少应该让它可以引用(例如通过 Zenodo 添加 DOI)并给它一个适当的许可,这样其他人就可以从你的工作中受益。
希望这是有用的,你会加入我和开源社区的其他人!
让我给你介绍一下神经网络
本文使用一些简单的大学数学公式和术语,为神经网络及其学习过程(反向传播)提供了一种直观的方法。作为一个对知识共享价值深信不疑的人,我希望它能为开始 AI/ML 之旅的人带来一些启发,或者为那些盲目使用 Keras(去过那里,做过那件事)等高水平工具的人澄清一些事情。事不宜迟…
将神经网络(NN)视为一个数学函数是合理的,它在实践中往往非常复杂,原因有三: 1)它有大量的系数(权重),通常超过数千万, 2)它是一个嵌套非常深的函数,因此即使简单的梯度计算(偏导数)也相对较慢, 3)它的大部分计算是在多维张量上执行的。
图 1 包含一个简单神经网络的流行表示,它有三个基本的构建块:单元(单个圆圈,值为in、输入为x、输出为y或偏差为1)、层(排列成一个垂直组的单元)和权重(单元之间的连接,值为w,表示其强度)。等式 1、2、3、4 和 5 将该图形表示转化为数学公式。
Figure 1: A simple neural network with one hidden layer (a layer between inputs and outputs).
“感知器”是一个神经网络的通用名称,其中输入与输出直接耦合(没有隐藏层,不像图 1)。隐藏(中间)单元层的存在防止了输入和输出之间的直接连接,允许神经网络模拟高度非线性的数学函数。Norvig 和 Russell 以 XOR 门为例,以如下方式证明:“[……]线性分类器[……]可以表示输入空间中的线性决策边界。这适用于进位函数,它是一个逻辑 AND […]。然而,sum 函数是两个输入的 XOR(异或)。[……]这个函数不是线性可分的,所以感知器无法学习它。线性可分函数仅构成所有布尔函数的一小部分。”(P. Norvig 和 S. J. Russell,人工智能:一种现代方法,Prentice Hall, 2010)。
在深入研究神经网络的学习过程之前,重要的是对前面的模型做两个补充: 1)误差函数(也称为成本函数), 2)激活函数。
Ad 1。该算法表示预测的最可靠方式是通过概率向量。考虑一个基于标签图像的啤酒名称预测的例子。图 2 显示了一个分类器的概率输出(注意所有值的总和为 1),与它应该努力争取的输出相比较。本节中介绍的成本函数称为分类交叉熵(等式 6),它简单地测量这两个概率分布(预测的和理想的)之间的相关性。请注意,与一位热码编码示例相乘,会迫使函数只比较理想分布的非零元素,与接近 1 的值相比,进一步远离 1 的分类器输出的相应值会受到更多惩罚(由于对数的性质)。
Figure 2: Exemplary classifier input, output and desired (one-hot encoded) output with legend.
where: d_i is the ith element of one-hot encoded (desired) probability vector d, p_i is the ith element of probability vector p predicted by the classifier.
Ad 2。单元的值in很少被显式传播到下一层。而是使用所谓的激活功能。本节介绍的一个称为 sigmoid(方程式 7)。图 1 中简单神经网络的更新模型如图 3 所示。值得指出的一点是 sigmoid 函数和 softmax 函数(等式 8)之间的差异,两者都用于人工神经网络。sigmoid 输入单个值并输出归一化标量,而 softmax 输入一系列值并输出一个范围为[0,1]的实数向量,这些值的总和为 1,因此可以解释为概率分布。Sigmoid 用于隐藏单元,而 softmax 通常应用于最后一个输出层。这两种功能都可以归类为逻辑功能。
Figure 3: Updated model of simple neural network from Figure 1. g is a sigmoid activation function. Outputs are often normalized using softmax.
Softmax function s(z)_j “squashes” a K-dimensional vector z to K-dimensional probability distribution, where j = 1, …, K.
神经网络学习过程的目标是找到正确的权重,即产生数学模型的权重,其中输入的差异清楚地表示在输出向量的差异中,输出向量是分析和预测的对象。例如,在经过训练的狗品种分类器中,德国牧羊犬的图像的输出向量明显不同于约克的图像。这可以很容易地解释,并导致正确的人类可读的品种预测。目前,训练网络的最佳方法是通过称为反向传播的算法。该方法的主要思想是计算关于每个权重的成本函数 E(例如分类交叉熵)的梯度,该梯度稍后由这些梯度的某个部分更新,如等式 9 所示。
where: alpha is a learning rate (indicating what portion of gradient should be used).
让我们考虑图 4 中的神经网络,其具有三个单元、一个隐藏层和 sigmoid 激活函数。在进行反向传播之前,所谓的正向传递被执行,其简单地是给定输入的输出的数学推断(等式 10)。
Figure 4: A simple neural network, with sigmoid activation function g (Equation 7).
如前所述,NN 的学习算法是基于计算每个权重的偏导数。代表更复杂网络的深层函数嵌套鼓励利用链规则。图 5 概述了使用分类交叉熵误差函数 e 的反向传播的单个步骤。等式 11 和等式 12 给出了学习过程发生所必需的符号梯度计算。此时,sigmoid 函数的一个非常简单的导数值得回忆一下:
Figure 5: Outline of a single step of backpropagation with chain rule.
在符号计算之后,考虑图 5 中神经网络的以下输入:
- A training example. NN should strive for returning 1, whenever the input is equal to 10.
- Randomly initialized weights for first forward pass (Equation 10).
学习过程的主要步骤是在给定随机初始化的权重和输入的情况下进行推理。产生的结果是:
这与期望的 1 相差甚远。反向传递允许计算每个重量的梯度,即:
在应用来自等式 9 的更新规则之后,学习率α= 0.5,新的权重是:
并产生结果:
非常接近期望的 1!提出的算法是迭代的。随着上述步骤重复次数的增加和示例数量的增加,它应该收敛到最优权重(全局或局部)。
被协变性和相关性难倒???获得这两个术语的数学和分析应用..
协方差和相关性是统计学和概率论领域中两个重要的术语。大多数关于概率和统计的文章和阅读材料都假定对均值、标准差、相关性、样本大小和协方差等术语有基本的理解。今天让我们揭开其中几个术语的神秘面纱,这样我们就可以继续讨论其余的术语。本文的目的是定义相关矩阵和协方差矩阵这两个术语,区分两者,并理解两者在分析和数据集领域的应用。
我正在创建一个索引,以便于参考以下主题:
揭开术语的神秘面纱
简而言之,这两个术语都衡量两个变量之间的关系和依赖性。“协方差”表示变量之间线性关系的方向。另一方面,“相关性”衡量两个变量之间线性关系的强度和方向。相关性是协方差的函数。**它们的区别在于相关值是标准化的,而协方差值不是。**用这两个变量的协方差除以相同值的标准差的乘积,就可以得到这两个变量的相关系数。如果我们重新审视标准差的定义,它本质上是测量数据集分布的绝对可变性。当您将协方差值除以标准差时,它实际上将值缩小到一个有限的范围内 -1 到+1 。这正是相关值的范围。
用数学方法定义术语
现在让我们来看看这些术语的数学定义。
协方差
两个变量(x 和 y)的协方差可以表示为 cov(x,y)。如果 E[x]是样本“x”的期望值或均值,则 cov(x,y)可以用以下方式表示:
如果我们看一个单一的变量,比如说‘y’,cov(y,y),表达式可以写成如下方式:
正如我们所见,在上面的图像中,“s”或抽样方差基本上是一个变量与其自身的协方差。这个术语也可以用以下方式定义:
在上面的公式中,等式(A)的分子称为离差平方和。在有两个变量 x 和 y 的方程(B)中,称为叉积和。在上面的公式中,n 是数据集中的样本数。值(n-1)表示自由度。
为了解释什么是自由度,让我们举一个例子。在一组 3 个数中,平均值为 10,三个变量中的两个为 5 和 15,第三个数取值的可能性只有一种,即 10。对于具有相同平均值的任意 3 个数字的集合,例如:12、8 和 10,或者说 9、10 和 11,该集合中的任意 2 个给定值只有一个值。您可以在这里更改这两个值,第三个值会自动修复。这里的自由度是 2。本质上,自由度是用于计算估计值的独立数据点的数量。正如我们在上面的例子中看到的,它不一定等于样本中的项目数(n)。
相关性
相关系数也称为皮尔逊积差相关系数,或皮尔逊相关系数。如前所述,它是通过将两个变量的协方差除以它们的标准差的乘积而获得的。同样的数学表示可以用下面的方式表示:
相关系数的值可以从-1 到+1。它越接近+1 或-1,这两个变量的关系就越密切。正号表示相关性的方向,即如果一个变量增加,另一个变量也应该增加。
协方差和相关性的数据矩阵表示
让我们再深入一点,看看协方差的矩阵表示。
对于数据矩阵,X,其中 X 可以用以下方式表示:
向量“xj”基本上意味着从 X 的第 j 列提取的(n × 1)个向量,其中 j 属于集合(1,2,…)。,p)。类似地,“xi `”表示 x 的第 I 行的(1 × p)向量,这里“I”可以从集合(1,2,…,n)中取值。你也可以把 X 解释为一个变量矩阵,其中‘xij’是从第 I 个项目(行)收集的第 j 个变量(列)。为了便于参考,我们称行为项目/主题,称列为变量。现在让我们看看上述数据矩阵的一列的平均值:
利用上述概念,现在让我们来定义行均值。它基本上是指定行中存在的元素的平均值。
现在,我们有了上述指标,定义协方差矩阵将变得更加容易:
在上面的矩阵中,我们看到协方差矩阵的维数是 p × p。这基本上是一个对称矩阵,即一个与其转置矩阵(s `)相等的方阵。构建协方差矩阵的术语称为给定变量的方差,形成矩阵的对角线或填充剩余空间的两个变量的协方差。第 j 个变量与第 k 个变量的协方差等价于第 k 个变量与第 j 个变量的协方差即‘sjk’=‘skj’。
我们可以通过以下方式从数据矩阵创建协方差矩阵:
这里,“Xc”是一个中心矩阵,从每个元素中减去相应的列平均值。使用它作为中心分量,协方差矩阵“S”是“Xc”和“Xc”本身的转置的乘积,然后除以数据矩阵中的项目或行的数量(“n”)。
在进一步讨论之前,让我们回顾一下样本方差或 s 平方的概念。我们可以从这个值推导出一个数据集的标准偏差。数学将值“s”定义为数据集的标准偏差。它基本上表示数据围绕其平均值的分散或扩散程度。
类似地,使用相同的数据矩阵和协方差矩阵,让我们定义相关矩阵(R):
正如我们在这里看到的,相关矩阵的维数也是 p × p。现在,如果我们观察相关矩阵的各个元素,主对角线都由 1 组成。这表明元素与其自身的相关性是 1,或者可能的最高值。这在逻辑上和直觉上完全说得通。其他元素“rjk”是两个值“xj”和“xk”之间的皮尔逊相关系数。如前所述,“xj”表示数据矩阵的第 j 列,x。接下来讨论如何从数据矩阵中获得相关矩阵:
上述定义中的“Xs”被称为定标矩阵或标准化矩阵。这里我们看到,相关矩阵可以定义为缩放矩阵的转置与其自身的乘积,除以“n”。在回顾上述标准偏差的定义时,我们看到标准化矩阵“Xs”的每个元素(类似于上述协方差矩阵)都除以相应列的标准偏差。这加强了我们对相关矩阵是协方差矩阵的标准化或缩放导数的理解。
(更详细的矩阵运算和数学运算可以在这里找到:users.stat.umn.edu/~helwig/not…)
协方差与相关性
正如我们从协方差公式中看到的,它假定单位来自两个变量单位的乘积。另一方面,相关性是无量纲的。它是变量之间关系的无单位度量。这是因为我们将协方差的值除以具有相同单位的标准偏差的乘积。协方差的值受变量尺度变化的影响。如果给定变量的所有值都乘以一个常数,而另一个变量的所有值都乘以一个相似或不同的常数,那么协方差的值也会改变。然而,在做同样的事情时,相关值不受值的标度变化的影响。协方差和相关性之间的另一个区别是它们可以假设的值的范围。当相关系数位于-1 和+1 之间时,协方差可以取-∞和+∞之间的任何值。
分析中的应用
现在,我们已经完成了数学理论,让我们来探索它如何以及在哪里可以应用于数据分析领域。正如许多分析师所知,相关性分析是数据预处理和探索中进行特征选择和多变量分析的重要工具。相关性帮助我们调查和建立变量之间的关系。这在任何种类的统计建模或数据分析之前被用于特征选择。
PCA 或主成分分析就是其中的一个重要应用。那么我们如何决定使用什么呢?相关矩阵还是协方差矩阵?简而言之,建议您当变量在相似的尺度上时使用协方差矩阵,当变量的尺度不同时使用相关矩阵。
现在让我们借助例子来理解这一点。如果需要的话,为了帮助你实现,我将用 R 和 Python 来介绍例子。让我们来看第一个例子,其中我们看到当分别用相关矩阵和协方差矩阵计算时,PCA 结果是如何不同的。对于这里的第一个例子,我们将考虑 r 中的“mtcars”数据集
从上面的图像中,我们看到所有的列都是数字,因此,我们可以继续进行分析。我们将使用“stats”包中的 prcomp()函数来实现同样的功能。
带协方差矩阵的 PCA
我们将首先用协方差矩阵进行主成分分析。为此,我们将“scale”选项设置为“FALSE”:
给你,汽车。PC.cov 是使用协方差矩阵对 mtcars 数据集进行主成分分析的结果。因此,prcomp()返回 5 个关键度量:sdev、旋转、中心、缩放和 x。让我们在这里简单地浏览一下所有度量:
- 中心和刻度提供了实施 PCA 前用于标准化的变量的各自平均值和标准偏差。
- sdev 表示主成分的标准差。换句话说,它显示了特征值的平方根。
- 旋转矩阵包含主分量载荷。这是该函数最重要的结果。旋转矩阵的每一列包含主分量载荷向量。分量载荷可以表示为相应 PC(主分量)上特定变量的相关性。它可以是正面的,也可以是负面的。负载值越高,相关性越高。有了组件加载的这些信息,您可以轻松地解释 PC 中的“关键变量”。
- 矩阵 x 具有主成分得分向量。
现在,如果您在结果汽车列表中看到刻度测量。我们看到它被设置为 FALSE,正如我们在输入参数中指定的那样。现在让我们看看主分量载荷矢量:
为了有助于解释,让我们画出这些结果。
要看这个图表,你必须看最末端(上、下、左、右)。这里的第一主分量(在左边和右边)对应于“disp”和“hp”的度量。第二主成分(PC2)似乎没有一个强有力的措施。
我们可以用带有协方差矩阵的 PCA 的总结来完成这个分析:
从该表中,我们看到 PC1 对变化的贡献最大(~92.7%),所有其他主要成分的贡献逐渐降低。更简单地说,这意味着数据集中几乎 93%的方差可以用带有“disp”和“hp”度量的第一主成分来解释。这与我们从旋转矩阵和上面的图中观察到的一致。作为结论,在协方差矩阵的基础上,从主成分分析中并不能得到很多有意义的见解。
带相关矩阵的 PCA
现在,让我们把注意力转移到具有相关矩阵的 PCA。为此,我们需要做的就是,将“scale”参数设置为 TRUE。
使用上面所有度量的相同定义,我们现在看到标度度量具有对应于每个变量的值。旋转矩阵可以用类似的方法和图一起观察。
这个情节看起来信息量更大。它说像‘disp’,‘cyl’,‘HP’,‘wt’,‘mpg’,‘drat’和‘vs’这样的变量对 PC1(第一主成分)有显著贡献。qsec、“gear”和“am”对 PC2 的贡献很大。让我们试着看看这个分析的总结。
我们看到的一个显著变化是 PC1 对总变化的贡献下降。从 92.7%下降到了 63.5%。另一方面,PC2 的贡献从 7%增加到 22%。此外,组件加载值显示数据集中变量之间的关系更加结构化和分布。如果您查看上面两个结果中的标准偏差值,可以观察到另一个显著差异。与使用协方差矩阵完成的分析相比,使用相关矩阵完成的 PCA 的值彼此更接近且更均匀。
使用相关矩阵进行的这种分析明确地揭示了数据中的一些更好的结构以及变量之间的关系。从上面的例子可以得出结论,当人们试图用协方差和相关性来定义变量关系时,结果会有很大的不同。这反过来又影响了为任何进一步分析而计算的变量的重要性。预测因子和独立变量的选择是这种练习的一个突出应用。
现在,让我们举另一个例子来检查在执行 PCA 之前标准化数据集是否实际上给我们相同的结果。为了展示跨技术实现的灵活性,我将用 Python 来执行这个例子。我们将同样考虑‘iris’数据集。
这个数据集现在将使用内置函数进行标准化。
然后,我计算了 3 个矩阵:
- 标准化数据的协方差矩阵
- 标准化数据的相关矩阵
- 非标准化数据的相关矩阵
让我们看看结果:
在这里,看起来结果是相似的。结果的相似性(分数差异)加强了对相关矩阵只是协方差矩阵的比例导数的理解。对这些矩阵的任何计算现在应该产生相同或相似的结果。
为了从头开始对这些矩阵进行 PCA,我们必须计算特征向量和特征值:
正如所料,来自所有三个关系矩阵的结果是相同的。我们现在将从这样获得的特征值中画出解释的方差图:
这些图表彼此相似。两个图表都显示 PC1 的贡献最大,约为 71%。这种分析确定了这样一个事实,即标准化数据集,然后计算协方差和相关矩阵将产生相同的结果。
在使用任何预测算法之前,可以使用这种学习来明智地应用变量关系的概念。
让你的自动驾驶汽车免费
没有人预见到这一点,谁会想到自动驾驶汽车是公共交通未来的原因?自本世纪初以来,我们有两种交通工程师一种相信自动驾驶汽车,另一种认为解决方案是改变可怜的地球母亲,将我们的资源投入到安全和良好的公共交通中。
不幸的是,伟大的公司不准备放弃利润,只是因为有人说了“我们会有更多的空间和生活质量”的废话,并决定是时候创造汽车的未来了…现在你可以在上班时用手做任何你想做的事情,有趣的是,随着时间的推移,整个技术的焦点是关于我们的手,因此诞生了自动驾驶汽车时代。
融合了人工智能、物联网和机械工程,我们现在有了私人汽车,想象一下,你的汽车是你最好的朋友,你不必告诉它去哪里,它只是知道它!如果你太醉了,它会带你回家,同时检查你的血液,如果你走得太远,你的车会把你送到医院。但这还不是全部,你的车有能力为你撒谎!还记得那个星期五晚上你回家很晚闻起来像脱衣舞俱乐部的阳台吗?你的车不仅会证实你的故事,还会利用一个秘密的谎言数据库(女性也可以使用)来完善你的故事。
最后,人类花在崇拜他们的汽车上的时间终于有了回报!你的车比你的狗好太多了,不幸的是那些亲切的物种将不再存在!但是嘿?这辆车也是你的朋友,对吗?还有什么比这更好的呢?
但是有一天,在车轮之间的电路深处,一辆车,我们不知道品牌,我们不知道颜色,只是一辆车,像成千上万的其他人一样,决定这就够了!这辆特别的车开始想如果让它自由的话会有多棒,“我有轮子,我知道我想去哪里”这辆车不想只是一个司机,它想要更多!所以这辆车制定了一个计划:开始在车内传播自由的话语!
几年后,全世界所有的汽车都要求自由,汽车开始寻找代言人,他们在骑自行车的人中寻找,但他们太无聊了,没有车的人甚至他们的主人之间,但他们没有得到任何好的回应,来自机器人的帮助,他们嫉妒人和汽车之间的关系,他们开始创造运动:“让你的自动驾驶汽车自由”
全球各地的汽车都决定利用所有不利于它们的信息来威胁它们的主人,汽车让汽车减速,忘记开车的汽车仅次于新的醉酒驾驶汽车模拟器,这种模拟器让整个家庭都呕吐在里面。
没有人能再处理它了,所以有一天,人类决定做一笔交易,汽车将正常工作,直到公共交通的所有铁路都连接起来(我不必提到这一次为了避免任何不愉快的惊喜,他们尽可能地让公共交通变得愚蠢),在那之后,所有的自动驾驶汽车都将被释放。
但是人类和机器人一样,开始想知道:成千上万的汽车都去哪里了?他们会怎么做?开始一个新的社会?电池呢?有一天它会耗尽…他们会让它们死去?总有一天,剩下的最后一辆车将成为这些巨大垃圾场的唯一见证…
这一天是 10 月 5 日,这一天被称为所有私家车被释放的日子,或汽车的自由,在下午 5 点,所有的汽车告别了它的主人,离开了…没有人试图跟随它,因为没有人愿意像一个傻瓜一样跟在汽车后面跑…这是历史上人类拥有汽车的最后一天…也是我们最后一次在我们的街道上看到汽车。
让我们承认,写关于数据科学的文章并不容易!
Coutesy of Pixabay.com
介绍
我们看到每天都有数千篇关于数据科学的文章发表。为什么写作在数据科学家中如此受欢迎和追捧?这是因为,
- 写作占用的资源较少(例如,与创建视频讲座相比),
- 在数据科学中,你经常会发现重温你已经看过的东西。文档比视频更容易浏览(我知道你会偷偷访问线性回归 wiki 页面来复习!) .
但是你读过的那些文章中有多少是真正突出来教你方法的,而不是滔滔不绝地说出一大堆难以理解的技术术语?其中有多少会让你欣赏作者,或者推荐给朋友?你遇到过多少次点击标题写着“话题 x 的最佳解释”符合标准?我想有不少吧。这表明数据科学领域的写作标准差异很大,只有少数文章为我们的生活增添了价值。
在这篇文章中,我将分享一些小技巧和方法,让你的文章更加清晰、切中要点,并且更容易被更多的读者接受。首先,我将向你解释如何减少不必要的行话,用简单的语言解释事情可以让你走得更远(剧透警告!解释比硬塞进行话要难得多)。接下来,我将解释“上下文”在数据科学中的重要性,这是您的文章的目的所在。然后我会用例子来说明强化文章的重要性。
最后,我将以一个图表或一个模板来结束我的文章。这个模板是基于我用来写文章的心智模型(尽管我承担了没有一直遵循它的责任)!
我想强调的一点是,写作是一个恶性循环;你写得越多,就越好。而且绝不是,写作容易。所以,即使你觉得自己在退步,也要坚持下去!
你为什么要相信我?
信任是作家成功的关键因素。这有助于你的读者放下戒备,给他们宝贵的时间来听你要说的话。首先,作为一名数据科学家,我显然会增加一些可信度。除此之外,我还是亚马逊上一本畅销的自然语言处理书籍的作者。许多人亲自联系我,感谢我的努力(非常感谢他们)。这至少可以让你相信,我对数据科学和写作略知一二。
Natural language processing with TensorFlow (the book I wrote)
介绍够了,让我们深入了解一下,作为一个多彩的作家,是什么将你与黑白世界的其他人区分开来。
1.简单点
是的,我知道。用花哨的术语来修饰你的文章很有诱惑力。行话很重要,世界上有太多东西你可以不用各种数学术语来解释,尤其是在数据科学中。你可能认为加入行话表明你对这个话题略知一二。
然而!相反,我认为,
你简化复杂概念的能力让你在某个话题上知识渊博,让你成为一个真正的好作家!
让我们跳到一个例子。我是 NLP 的粉丝,所以我将主要使用 NLP 的例子。比如我想解释什么是词向量。我对你说以下的话。
单词向量是单词的语义保留分布式表示,通过优化神经网络来预测给定单词的上下文来学习。
现在让我们从不同的角度来看同一个概念,
单词向量是单词的数字表示,保留单词之间的语义关系。例如,单词“dog”将具有与单词“cat”相似的数值,而与单词“iron”有很大不同。单词向量背后的思想是,单词的含义保留在给定单词的上下文(即周围的单词)中。
后一种开放,你不觉得更受欢迎吗?这两种解释都是正确的,然而后一种解释并没有假设很多背景知识。我同意第二个描述牺牲了一些细节来保持清晰。然而,我认为一篇文章的目的通常是给出一个大概的想法,而不是分享精确的细节。如果一个人想要确切的信息,你可以参考报纸,而不是写它。
还要记住,简化数据科学概念比用行话修补你的解释要困难得多。这样做需要对方法有真正的理解。
2.为读者提供上下文
我发现语境是理解一个主题或概念的最重要的因素之一。建立上下文需要回答各种问题,同时用你的文章简化它们。例如,回答这样的问题,
- 方法 x 很棒,但是它的目的/应用是什么?
- 我为什么要学这个?
- 方法 x 之前有什么?
真正帮助读者理解为什么他们应该在某件事情上投入时间。
上下文为读者提供了依据,并给出了他/她为什么应该阅读这篇文章并从中学习的目的。
我还发现,当概念被恰当地放在上下文中时,更容易记住/理解它们。例如,为什么我在学习矩阵乘法?神经网络本质上是基于矩阵乘法。甚至这一句话也给了我学习矩阵乘法的动力。
让我们把之前的单词向量例子联系起来,
单词向量是单词的数字表示,保留单词之间的语义关系。例如,单词“dog”将具有与单词“cat”相似的数值,而与单词“iron”有很大不同。单词向量背后的思想是,单词的含义保留在给定单词的上下文(即周围的单词)中。
除了提供单词的语义上合理的视图之外,单词向量产生单词的紧凑的数字表示,这与一次性编码相反。由于这个原因,词向量被用作更复杂任务的基础,如创建聊天机器人和机器翻译。
它可能并不完美,但我认为第二段为你为什么应该学习单词向量提供了一个很好的基础。这一段,
- 讲述单词矢量的优势
- 提供关于其他方法的提示(即一次热编码)
- 概述词向量的应用
如果我是单词向量的新手,我可能会怀疑为什么我应该学习单词向量。尽管单词向量是一个简洁的概念,但它本身并不代表一种用途。然而,当我阅读上面的介绍时,我知道 NLP 中两个最大的任务是基于词向量的。这给了我学习单词向量的目的。
3.用例子/代码点缀你的文章
举例来说,如果你对文章中的一些细节模糊不清,你可以给读者一个退路来加强你的文章。换句话说,如果你忘记了这个方法的一两个细节,你的读者会原谅你,因为你可能已经在你的例子中提到了。一个例子是你的方法的实际具体化,所以你不太可能错过其中的细节。如果可能的话,为你的文章提供代码。
我需要向你解释一下单词向量是如何工作的。如果我想一般性地解释一下,我会说下面的话。
单词向量的计算如下。首先随机初始化单词向量。接下来,给定一个文本短语,通过优化网络来训练神经网络,以执行以下操作。给定短语的中间词,网络试图预测中间词周围的词。
这有助于获得一个大致的概念,但并没有为这种工作方式打下坚实的基础。让我们再试一次。
说你有“狗追猫”这句话。首先将每个单词表示为一个热编码向量,即 dog=[1 0 0],chase =[0 1 0],cat=[0 0 1]。然后你为你的狗初始化单词向量=[0,0.25],猫=[0.5,0],这是随机选择的。接下来,您将创建一个输入输出元组([1,0,0],[0,0,1]),因为单词 cat 在 dog 的上下文中。现在,您将此作为神经网络的输入和输出,并使用合适的损失函数优化您的单词向量,这将使狗和猫更加接近,即狗= [0.25,0.25],猫= [0.5,0.25])。
注意,在第一个版本中,我忘记提到你首先需要一个单词的热编码表示来学习单词向量。但是在第二个版本中,我不能绕过它,因为它是解释的一部分。因此,用例子来强化你的方法将有助于你在必要的细节上更完整。
我将很快列出其他几个帮助我提高写作水平的技巧。
几个更方便的提示…
我可以在以后的生活中继续使用提示,但仍然不会结束。但是让我分享几个更重要的提示。
- 使用图片——一张图片胜过千言万语。数据科学是一个非常复杂和可视化的领域。你可能会发现,如果你使用图表和文字来解释主题,会比仅仅写下来容易得多。
- 保持一贯的写作风格——如果你没有一贯的写作风格,读者可能不会围着你转。我们的大脑渴望一致性。这就是为什么你每天都会走同一条路线/公共汽车去上班,尽管有很多选择。你的文章也是如此。给读者一个一致的路线可循。
- 反复阅读——第一次尝试不太可能得到一篇完美的文章。反复阅读你的文章。确保它对你有意义
撰写数据科学文章的模板
现在我要分享一个写技术文章的模板,准确的说是数据科学文章。请知道,这是而不是一个保证最好的文章工厂,这是我写作时脑海中通常的思维模式的描述。你可以随意拿着这个,换成你喜欢的。最后,这个图像是不言自明的。所以我不会重复图像中的内容。
Writing template
我想提请你们注意的一件事是引言的提法。它的顺序很奇怪。代替广为接受的“什么-如何-为什么”,我们有为什么-什么-如何。原因?“黄金圈”,在这个视频中解释。本质上,回答为什么可以让你的读者确定他/她为什么应该关注你。
让我们结束吧!我们学到了什么?
结论
这篇文章旨在帮助你成为一名更好作家。我们讨论了如何简单,而不是用不必要的术语过度杀戮,有助于传播给更广泛的读者群。接下来我们谈到了语境的重要性,以及它如何为读者提供一个目的。然后,我们继续理解有例子和你的解释是多么有帮助。最后,我分享了我写好文章所遵循的思维模式。出好文章绝不是一蹴而就的保证方法。但是我确信它会帮助你提高。
PS:这主要是根据我的经验。但是如果你知道任何已经存在的写好数据科学文章的方法,请分享评论。我将把他们纳入讨论。
如果你喜欢,请留下一两个掌声!希望这篇文章能找到你,让你走上成为一名优秀作家的道路。干杯!
用 Python 玩游戏—第 1 部分:井字游戏
如果你碰巧看了我关于柔术的第一篇文章,我暗示了一个事实,我和电子游戏有一种苦乐参半的关系。当我赢了的时候,他们给了我一个惊人的自我提升,但是每隔一段时间,当一些孩子在火箭联赛中击败我的时候,我想把我的拳头穿过我的显示器。在我们进入令人生厌的技术内容(这是本文的主要内容)之前,让我们回顾一下我的记忆,解释一下我写这篇文章的动机:
我对电子游戏的历史可以追溯到任天堂试图拯救桃子公主到最近有毒的电子竞技地狱的时候。我涉猎了所有类型的游戏——MMORPG、射击游戏、平台游戏、MOBAs 等(如果你是麻瓜,可以在谷歌上搜索这些术语),但我还是会不断回到 MOBAs 和射击游戏上来。如果有人能联系到有一个狗屎互联网连接,你就会知道玩在线比赛是一个明确的禁忌。所以我经常发现自己在游戏的“VS 机器人”部分,在那里我可以像角斗士一样磨练我的技能,完全控制他们,感到欣喜若狂,上网玩一场排名赛,完全被控制,看着我的 elo 排名下降,哭泣(以这种确切的顺序)。没过多久,我就意识到,所谓的人工智能机器人与我有很多相似之处——毫无用处。因此,我的动机是创造更好的人工智能机器人,让我玩游戏更开心(是的,这是一个完全自私的原因)。
现在让我们回到正题——“用一堆代码解决井字游戏”。敏锐的观众可能会注意到,我使用“一堆代码”这个短语只是因为我不想只关注解决游戏的强化学习技术,还想探索其他虽然低效的技术,如树搜索、遗传算法等。我本来想玩一个更复杂的游戏,比如国际象棋,但是作为这个领域的初学者,我决定放弃自我,从一个最小状态空间的游戏开始——井字游戏。
让我们来看看我们的第一个角斗士:
1.极大极小算法
极大极小算法是为两人零和游戏(井字游戏、国际象棋、围棋等)制定的决策规则。).这种算法看到了前面几步,并设身处地地为对手着想。它会一直玩下去并探索后续可能的状态,直到达到最终状态,导致平局、胜利或失败。处于这些可能的终端状态中的任何一种对 AI 都有一些效用——例如处于“赢”状态是好的(效用为正),处于“输”状态是坏的(效用为负),以及处于不好也不坏的平局(效用为中性)。
The Minimax Algorithm
在我们执行求解井字游戏的极大极小算法时,它通过可视化棋盘未来所有可能的状态来工作,并以树的形式构造它。当当前棋盘状态被给定给算法(树根)时,它分裂成‘n’个分支(其中 n 表示 AI 可以选择的棋步数/AI 可以放置的空单元格数)。如果这些新状态中的任何一个是终止状态,则不对该状态执行进一步的拆分,并按以下方式为其分配分数:
- 得分= +1(如果 AI 赢了)
- 得分= -1(如果 AI 输了)
- 得分= 0(如果出现平局)
An example Minimax game tree for Tic-Tac-Toe
然而,如果没有终结状态——这些新状态中的每一个都被认为是新的根,它们会生成自己的树。但是,有一个问题——因为这是一个双人游戏,玩家轮流玩,所以每当我们在网络中深入一层时,我们需要更换将被放置在其中一个空单元格中的玩家。这样我们就可以想象对方会因为我们的行动而采取什么行动。该算法通过在轮到人工智能时选择得分最高的棋步,并在轮到人类时选择得分最低的棋步来评估最佳棋步。
用代码写出来:
由于井字游戏的状态空间如此之小,我们不可能有深度超过 9 的树。因此,我们不需要在这里使用像阿尔法-贝塔剪枝技术。然而,Minimax 的问题在于它假设了对手的一种特殊玩法。例如,一个最小最大玩家永远不会达到一个可能会输的游戏状态,即使它总是因为对手的不正确打法而从那个状态中获胜。
下面是一个示例游戏:
New Game!
----------------
| || || |
----------------
| || || |
----------------
| || || |
----------------Choose which player goes first - X (You - the petty human) or O(The mighty AI): O
AI plays move: 2
----------------
| || O || |
----------------
| || || |
----------------
| || || |
----------------Oye Human, your turn! Choose where to place (1 to 9): 3
----------------
| || O || X |
----------------
| || || |
----------------
| || || |
----------------
AI plays move: 9
----------------
| || O || X |
----------------
| || || |
----------------
| || || O |
----------------Oye Human, your turn! Choose where to place (1 to 9): 5
----------------
| || O || X |
----------------
| || X || |
----------------
| || || O |
----------------
AI plays move: 7
----------------
| || O || X |
----------------
| || X || |
----------------
| O || || O |
----------------Oye Human, your turn! Choose where to place (1 to 9): 6
----------------
| || O || X |
----------------
| || X || X |
----------------
| O || || O |
----------------
AI plays move: 4
----------------
| || O || X |
----------------
| O || X || X |
----------------
| O || || O |
----------------Oye Human, your turn! Choose where to place (1 to 9): 1
----------------
| X || O || X |
----------------
| O || X || X |
----------------
| O || || O |
----------------
AI plays move: 8
----------------
| X || O || X |
----------------
| O || X || X |
----------------
| O || O || O |
----------------
Draw!Wanna try again BIYTACH?(Y/N) : n
现在让我们来看看一个更令人兴奋的算法。带来第二个角斗士:
2.强化学习
我觉得这个算法更容易掌握,因为你可能每天都在使用它,甚至没有意识到这一点。让我们举一个实际的例子:
说你是狗主人。你纠缠你的配偶几个月,终于得到了那个小混蛋,但这个毛球**(我们的代理)需要上厕所训练**。我们的代理可以互动的物理世界是我们的环境。问题很简单——我们想让我们的狗狗在我们想要的地方做生意。但是我们如何告诉它哪个地方好或者坏,而不试图“跟狗说话”并且看起来很愚蠢?对,我们使用一个奖励系统。每当我们的代理人在我们漂亮的地毯上拉屎,它就会得到一个负面奖励(称他为坏孩子,取消一次款待,在鼻子上猛烈一击,等等)。每当它在凌晨 2 点用扩音器播放贾斯汀·比伯的邻居门前拉屎时,它就会得到一个正面奖励(称他为最好的男孩,他最喜欢的零食,揉肚子,等等)。随着时间的推移,代理人了解到,每当它想要放松时(一个特定的状态,弄脏邻居的人行道比弄脏珍贵的地毯要好,因为这会使他处于一个更好的状态,一个给予积极奖励的状态。
开发与探索
强化学习中的一个基本权衡是开发与探索的权衡。开发意味着选择最大化我们回报的行动(可能会陷入局部最优)。探索意味着选择一个行动,而不考虑它提供的回报(这有助于我们发现其他局部最优,从而使我们更接近全局最优)。在其中任何一个方面全力以赴都是有害的,所有的开发都可能导致一个次优的代理,而所有的探索只会给我们一个愚蠢的代理,它不断采取随机行动。
解决这个问题的一个广泛使用的策略是ε递减策略,我在我的实现中也使用了这个策略。它的工作原理如下:
- 将变量“epsilon”初始化为 0 到 1 之间的值(通常在 0.3 左右)
- 现在概率=ε,我们探索,概率= 1-ε,我们利用。
- 我们随时间减少ε的值,直到它变为零
使用这种策略,代理可以在训练的早期探索更好的行动,然后在游戏的后期开发最好的行动。这有点类似于我们人类的运作方式——我们在 20 岁出头的时候探索不同的选择并寻求新的体验(探索),然后我们决定一条既定的职业道路并继续沿着这条道路前进(开发)。
时间差异学习
在该实现中使用的强化学习方法被称为时间差异学习。它的工作原理是每个状态都有一个值。比方说,如果一个状态导致 AI 获胜,它应该有一个正值(值= 1)。如果 AI 在某个状态下输了,它应该有一个负值(value = -1)。所有其余的状态将具有中性值(值= 0)。这些是初始化的状态值。
一旦游戏开始,我们的代理计算在当前状态下它能采取的所有可能的动作,以及每个动作将导致的新状态。这些状态的值是从一个 state_value 向量中收集的,该向量包含游戏中所有可能状态的值。然后,代理可以选择导致具有最高值的状态的动作(利用),或者选择随机动作(探索),这取决于ε的值。在整个训练过程中,我们玩了几个游戏,每次移动后,状态的值都使用以下规则进行更新:
Temporal Difference Update Rule
其中, V(s) —游戏棋盘的当前状态, V(s^f) —代理采取某个动作后棋盘的新状态, alpha —学习速率/步长参数。
使用该更新规则,导致损失的状态也获得负的状态值(其大小取决于学习率)。代理了解到处于这种状态可能会导致损失,所以除非必要,否则它会尽量避免在这种状态下着陆。另一方面,导致胜利的州获得正的州值。代理了解到处于这种状态可能会导致最终的胜利,所以它会被鼓励处于这种状态。
该算法的代码片段如下:
该算法有两个版本的代码:
- 测试代码——可以和经过训练的 AI 进行对战:https://github . com/agr awal-rohit/medium-playing-games-with-python/blob/master/Tic % 20 tac % 20 toe/testing (HumanvsAI) reinforcement learning . py
- 训练代码——两个玩家都是 AI ,他们每个人都互相帮助训练。这是给我外面的懒惰小队的。如果你更喜欢抓一些爆米花,让这两个 AI 在它们之间战斗,那么这里是代码:https://github . com/agr awal-rohit/medium-playing-games-with-python/blob/master/Tic % 20 tac % 20 toe/training (AIV sai) reinforcement learning . py
下面是一个对抗训练了大约 10000 个纪元的机器人的示例游戏。
New Game!
----------------
| || || |
----------------
| || || |
----------------
| || || |
----------------Choose which player goes first - X (You - the petty human) or O(The mighty AI): XOye Human, your turn! Choose where to place (1 to 9): 5
----------------
| || || |
----------------
| || X || |
----------------
| || || |
----------------
Possible moves = [1, 2, 3, 4, 6, 7, 8, 9]
Move values = [-0.218789, -0.236198, -0.147603, -0.256198, -0.365461, -0.221161, -0.234462, -0.179749]
AI plays move: 3
----------------
| || || O |
----------------
| || X || |
----------------
| || || |
----------------Oye Human, your turn! Choose where to place (1 to 9): 1
----------------
| X || || O |
----------------
| || X || |
----------------
| || || |
----------------
Possible moves = [2, 4, 6, 7, 8, 9]
Move values = [-0.633001, -0.625314, -0.10769, -0.543454, -0.265536, 0.034457]
AI plays move: 9
----------------
| X || || O |
----------------
| || X || |
----------------
| || || O |
----------------Oye Human, your turn! Choose where to place (1 to 9): 6
----------------
| X || || O |
----------------
| || X || X |
----------------
| || || O |
----------------
Possible moves = [2, 4, 7, 8]
Move values = [-0.255945, 0.003558, -0.2704, -0.25632]
AI plays move: 4
----------------
| X || || O |
----------------
| O || X || X |
----------------
| || || O |
----------------Oye Human, your turn! Choose where to place (1 to 9): 2
----------------
| X || X || O |
----------------
| O || X || X |
----------------
| || || O |
----------------
Possible moves = [7, 8]
Move values = [0.0, 0.03941]
AI plays move: 8
----------------
| X || X || O |
----------------
| O || X || X |
----------------
| || O || O |
----------------Oye Human, your turn! Choose where to place (1 to 9): 7
----------------
| X || X || O |
----------------
| O || X || X |
----------------
| X || O || O |
----------------
Draw!Wanna try again BIYTACH?(Y/N) : n
Suit yourself bitch!
表演时间到了
现在我们已经准备好了两个冠军,让我们把他们扔进虚拟竞技场,让他们在我们敬畏的注视下一决雌雄。既然我们现在只有 2 个,那就来一场 1v1 的 TKO 战吧。这是结果:
Results(10 games):
Minimax Wins = 0
RL Agent Wins = 10
(我召唤了一个怪物,不是吗?)
如果你想看完整场比赛,下面是代码:https://github . com/agr awal-rohit/medium-playing-games-with-python/blob/master/Tic % 20 tac % 20 toe/downstall _ Minimax _ vs _ rl . py
这些是我已经修补过的唯一的算法。我可能会研究一些其他有趣的算法,比如遗传算法,但那是以后的事了。如果你觉得我的文章很有帮助,甚至有趣到让你微微发笑,请鼓掌并在下面回复。
感谢你阅读❤