TowardsDataScience 博客中文翻译 2016~2018(二百六十五)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

寻找神经网络的成本函数

原文:https://towardsdatascience.com/step-by-step-the-math-behind-neural-networks-490dc1f3cfd9?source=collection_archive---------2-----------------------

一步一步:神经网络背后的数学

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Title image: Source

特伦斯·帕尔和杰瑞米·霍华德的论文, 深度学习所需的矩阵演算 *,*提供了很多关于深度学习库(如 Tensorflow 或 PyTorch)如何真正工作的见解。如果不理解深度学习背后的数学,我们所做的只是编写几行抽象代码——建立模型,编译它,训练它,评估它——而没有真正学会欣赏支持所有这些功能的所有复杂的错综复杂之处。

这篇(以及接下来的几篇)文章将是我从 Terence 和 Jeremy 的论文中学到的思考。本文将介绍这个问题,我们将在接下来的文章中解决它。我将解释大部分的数学知识,并加入一些我的见解,但要了解更多信息,请查看原始论文。

这些文章(和论文)都假设了高中水平的微积分基础知识(即导数规则和如何应用它们)。如果你想重温的话,可以看看可汗学院的视频。

这就是我们的问题。我们有一个只有一层(为了简单起见)和一个损失函数的神经网络。这一层是一个简单的全连接层,只有一个神经元,许多权重 w₁,w₂,w₃ …,一个偏置 b ,以及一个 ReLU 激活。我们的损失函数是常用的均方误差(MSE)。知道了我们的网络和损失函数,我们如何调整权重和偏差来最小化损失?

为了减少损失,我们使用梯度下降的概念。正如这里的所解释的(如果你不熟悉梯度下降的工作原理,请阅读此处),梯度下降计算损失函数的斜率,然后根据该斜率将权重和偏差转移到更低的损失。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 1: Shifting the weights and biases of to minimize loss

我们需要找到损失函数的斜率。然而,在此之前,让我们定义一下损失函数。MSE 简单地平方每个网络输出和真实标签之间的差,并取平均值。下面是 MSE 方程,其中 C 是我们的损失函数(也称为代价函数), N 是训练图像的数量, y 是真实标签的向量(y=【目标( x),目标(x)…目标(【t28)(如果你还没有注意到,粗体字中的变量是向量。)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 2: Loss function

我们可以进一步扩展这个等式。网络输出是什么?我们将一个向量输入——姑且称之为x——给我们的全连接层。该层的激活是我们的网络输出。我们的全连接层的激活是什么?向量输入中的每一项都乘以一定的权重。然后,将所有这些产品加在一起,并在此基础上添加一个偏差。最后,该值通过 ReLu 传递,形成全连接层中一个神经元的激活。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 3: Fully-connected layer, expanded. The orange circles are the input values, the blue circle is the output value (the prediction, since our network only has 1 layer), and the gray circles are just intermediate values used in the calculation. Each red line represents multiplication by a certain weight, the pink lines represent summing up all the values, and the green line represents addition with a certain bias.

对每个输入值和每个权重的乘积求和,本质上是输入 x 和一个权重向量(姑且称之为 w )之间的向量点积。ReLU 只是一个将任何负值转换为 0 的函数。让我们将其重命名为 max(0,z) 函数,如果 z 为正,则返回 z,如果 z 为负,则返回 0。

综上所述,我们得到了神经元激活的方程式:

*激活(x)= max(*0,wx+b)

现在让我们把它代入损失函数。因为我们使用多个输入进行训练,所以让我们将 X 定义为所有输入的集合:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 4: X // Source

由于我们只有一层(有一个神经元),这个神经元的激活就是我们模型的预测。因此,我们可以用我们的激活 in 代替损失函数中的 o :

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 5: Loss function with activation substituted in

然后替换激活函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 6: Loss function

这是我们要求斜率的损失函数。

为了找到斜率,我们必须找到损失函数的导数。然而,不是任何导数,它必须是相对于权重和偏差的偏导数(因为这些是我们正在调整的值)。

查看第 2 部分了解如何计算偏导数!

跳到其他文章:

这里下载原论文

如果你喜欢这篇文章,别忘了留下一些掌声!如果您有任何问题或建议,请在下面留下您的评论:)

如何求函数的偏导数?

原文:https://towardsdatascience.com/step-by-step-the-math-behind-neural-networks-ac15e178bbd?source=collection_archive---------4-----------------------

一步一步:神经网络背后的数学

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Title image: Source

第一部分中,我们被给了一个问题:计算这个损失函数的梯度:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 1: Loss function

求梯度本质上就是求函数的导数。然而,在我们的例子中,因为有许多我们可以调整的独立变量(所有的权重和偏差),我们必须找到每个变量的导数。这就是所谓的偏导数,符号是∂.

偏导数:

计算简单函数的偏导数很容易:只需将方程中的其他变量视为常数,然后找到通常的标量导数。以下是一些标量导数规则作为提醒:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 2: Scalar derivative rules // Source

考虑函数 f(x,y) = 3x y 中关于 x 的偏导数(即 y 如何随着 x 的变化而变化)。将 y 视为常数,我们可以求出 x 的偏导数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 3: Partial with respect to x

同样,我们可以找到 y 的偏导数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 4: Partial with respect to y

函数 f(x,y) = 3x y 的梯度是一个水平向量,由两个分向量组成:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 5: Gradient of f(x,y) // Source

这应该很清楚:因为相对于 x 的偏导数是函数在 x 方向上的梯度,相对于 y 的偏导数是函数在 y 方向上的梯度,所以总梯度是由两个偏导数组成的向量。这个可汗学院的视频提供了一个非常简洁的偏导数的图形解释,如果你想形象化我们正在做的事情。

链规则:

对于像 f(x,y) = 3x y 这样的简单函数,我们只需要知道这些。然而,如果我们想要计算更复杂函数的偏导数——例如那些具有嵌套表达式的函数,如 max(0,wX*+b)——我们需要能够利用多元链规则,在本文中称为单变量全导数链规则*。

单变量链规则

我们先来回顾一下单变量链规则。考虑函数 y=f(g(x))=sin(x)。为了得到这个表达式的导数,我们将外部表达式的导数与内部表达式的导数相乘,或者“将各个部分连接在一起”。换句话说:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 6: Single-variable chain rule where u is the intermediate variable for nested subexpressions

对于我们的例子, u=xy=sin(u) 。因此:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 7: Derivatives // Source

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 8: Derivative of the whole expression // Source

把单变量链规则想象成 x 经过的操作图是很好的,就像这样:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 9: Diagram of chain of operations for y=sin(x²)

当处理多变量链式法则时,将方程可视化为图表的概念将会非常方便。此外,如果您使用 Tensorflow(或 Keras)和 TensorBoard,在您构建模型和编写训练代码时,您可以看到与此类似的操作图。

多变量链式法则

多变量链规则,也称为单变量全导数链规则,如文中所称,是标量链规则的变体。与它的名字所暗示的不同,它可以应用于只有一个变量的表达式。但是,表达式应该有多个中间变量。

为了说明这一点,让我们考虑等式 y=f(x)=x+x 。使用标量附加导数规则,我们可以立即计算导数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 10: Derivative of x+x²

让我们试着用链式法则来做。首先,我们引入中间变量: u₁(x) = x 和 *u₂(x,u₁) = x + u₁.*如果我们应用单变量链规则,我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 11: Using the single-variable chain rule

很明显,2x≠1+2x,所以这里有问题。让我们画出方程式的图表:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 12: Diagram of chain of operations for y = x+x² // // Source

图 12 中的图不再是线性的,所以我们必须考虑图中所有导致最终结果的路径。由于 u₂ 有两个参数,偏导数开始起作用。为了计算这个函数的导数,我们必须计算关于 u₁). u₂(xx 的偏导数这里, x 的变化以两种方式反映在 u₂ 中:作为加法的操作数和作为平方运算符的操作数。在符号中,ŷ=(x+δx)+(x+δx)δy = ŷ-y,其中 ŷ 是调整后的 x. 处的 y 值

因此,为了计算 u₂(x,u₁) 的偏差值,我们需要合计从 x 的变化到 y 的变化的所有可能的贡献。 u₂(x,u₁) 的总导数由下式给出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 13: Derivative of y = x+x² // Source

更简单地说,你把 x 的变化直接对 u₂的影响和 x 的变化通过 u₁对 u₂.的影响加起来我发现通过图表更容易形象化:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 14: Graph of y = x+x², with partials included

就是这样!我们得到了正确答案:1+2x。我们现在可以用一个规则来概括这个过程,即多变量链式规则(或单变量全导数链式规则):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 15: Multivariable chain rule // Source

如果我们为 x 引入一个别名,如 x=u(n+1),那么我们可以将公式改写成最终形式,这样看起来更简洁:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 16: Multivariable chain rule // Source

仅此而已!复习一下,我们再做一个例子: f(x)=sin(x+x ) 。我们的 3 个中间变量是: *u₁(x) = x,u₂(x,u₁)=x+u₁,*和 u₃(u₂) = sin(u₂) 。我们可以再次绘制图表:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 17: Graph of y = sin(x+x²), with partials included

计算我们的偏角:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 18: Partials for the function y = sin(x+x²)

因此 f(x)=sin(x+x ) 的导数为 cos(x+x )(1+2x)

这和我们的问题有什么关系?记住,我们需要找到损失函数相对于 w (我们所有权重的向量)和 b (偏差)的偏导数。然而,我们的损失函数并不那么简单——有多个嵌套的子表达式(即多个中间变量)需要我们使用链规则。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 19: Loss function

还有一个问题。如你所见,我们的损失函数不仅仅接受标量作为输入,它也接受向量。如何计算向量方程的偏导数,向量链规则是什么样的?

看看第三部就知道了!

如果你还没有,点击这里阅读第 1 部分!

跳到其他文章:

此处下载原文

如果你喜欢这篇文章,别忘了留下一些掌声!如果您有任何问题或建议,请在下面留下您的评论:)

求向量函数的梯度

原文:https://towardsdatascience.com/step-by-step-the-math-behind-neural-networks-d002440227fb?source=collection_archive---------2-----------------------

一步一步:神经网络背后的数学

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Title image: Source

第一部分中,我们被给了一个问题:计算这个损失函数的梯度:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 1: Loss function

为了求梯度,我们必须求函数的导数。在第二部分中,我们学习了如何计算函数对每个变量的偏导数。然而,这个损失函数中的大部分变量都是向量。当神经网络处理大量数据时,能够找到向量变量的偏导数尤其重要。向量和矩阵运算是一种简单的方法来表示有这么多数据的运算。确切地说,你怎样才能找到一个向量函数的梯度呢?

标量函数的梯度

假设我们有一个函数, f(x,y) = 3x y 。我们的偏导数是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 2: Partial derivatives

如果我们把这些分音组织成一个水平向量,我们得到 f(x,y)梯度,或者 ∇ f(x,y) :

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 3: Gradient of f(x,y)

6yxf(x,y) 相对于 x 的变化,而 3xf(x,y) 相对于 y 的变化。

当我们有两个函数时会发生什么?让我们添加另一个函数, g(x,y) = 2x+y⁸ 。偏导数是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 4: Partials for g(x,y)

所以 g(x,y)的梯度是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 5: Gradient of g(x,y)

表示函数

当我们有一个带有多个参数的函数时,用一种更简单的方式来表示它们通常是有用的。我们可以将函数的多个参数组合成一个向量自变量, x ,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 6: Vector x

因此, f(x,y,z) 会变成 f(x₁,x₂,x₃) 从而变成 f( x )。

我们也可以将多个函数组合成一个向量,就像这样:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 7: Vector y

现在, y=f(x) 其中 f(x) 是【f₁( x 、f₂( x 、f₃( x )…fn( x )】的向量

对于我们前面的两个函数的例子, *f(x,y)f(x)*和 *g(x,y)g(x)。*此处,向量x=【x₁,x₂】,其中 x₁=x ,以及 x₂=y 。为了进一步简化,我们可以将我们的函数组合起来:[f( x )、g( x )] = [f₁( x )、f₂(x)]=f(x)= y .

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 8: Equations within vector function y

通常,函数的数量和变量的数量是相同的,因此每个变量都有一个解。

向量函数的梯度

现在有了两个函数,怎么求两个函数的梯度呢?如果我们把它们的梯度组织成一个单一的矩阵,我们就从向量演算进入了矩阵演算。这个矩阵以及具有多个变量的多个函数的梯度的组织被称为雅可比矩阵

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 9: The Jacobian

有多种方法来表示雅可比矩阵。这种布局,我们垂直堆叠渐变,被称为分子布局,但其他论文将使用分母布局,它只是对角翻转:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 10: Denominator layout of the Jacobian

恒等函数的梯度

我们取恒等式函数, y = f(x) = x ,其中fi(x)= Xi,求其梯度:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 11: Identity function

正如我们创建之前的雅可比矩阵一样,我们可以找到每个标量函数的梯度,并将它们垂直堆叠起来,以创建恒等函数的雅可比矩阵:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 12: Jacobian of the identity function

既然是恒等函数,f₁( x ) = x₁,f₂( x ) = x₂,以此类推。因此,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 13: Jacobian of the identity function

函数对不在函数中的变量的偏导数为零。比如 2x 对 y 的偏导数是 0。换句话说,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 14: The partial derivative of a function with respect to a variable that’s not in the function is zero

因此,不在雅可比对角线上的一切都变为零。同时,任何变量对自身的偏导数都是 1。例如, x 相对于 x 的偏导数为 1。因此,雅可比就变成了:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 15: Jacobian of the identity function

元素式向量函数组合的梯度

基于元素的二元运算符是连续应用运算符的运算(如加法 w + xw > x ,从两个向量的第一项开始获得第一项输出,然后从两个向量的第二项获得第二项输出……依此类推。

本文用以下符号表示元素式二元运算:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 16: Element-wise binary operation with f(x) and g(x)

这里,◯指的是任何元素操作符(比如+),而不是函数的组合。

那么如何找到两个向量的元素运算的梯度呢?

由于我们有两组函数,我们需要两个雅可比矩阵,一个表示相对于 x 的梯度,一个表示相对于 w 的梯度:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 17: Jacobian with respect to w and x

我们需要的大多数算术运算都很简单,所以 f(w) 通常就是向量 w 。换句话说, fi(wi) = wi 。例如,操作 w+x 符合这一类别,因为它可以表示为 f(w)+g(x) ,其中 fi(wi) + gi(xi) = wi +xi。

在这种情况下,两个雅可比矩阵中的每个元素都简化为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 18: Elements in the Jacobian

在对角线上,i=j,所以偏导数存在一个值。然而,离开对角线,i≠j,所以偏导数变为零:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 19: Diagonal jacobian

我们可以更简洁地表示为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 20: The Jacobian with respect to w and x

我们试着求函数 w+x 的梯度。我们知道对角线以外的一切都是 0。对角线上相对于 wx 的分数值为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 21: Partials with respect to w and x

所以两个雅可比行列式的对角线都是 1。这看起来很熟悉…这是单位矩阵!

我们用乘法来试试: w*x 。对角线上相对于 wx 的分数值为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 22: Partials with respect to w and x

因此, w*x 相对于 w 的梯度为diag(x),而 w*x 相对于 x 的梯度为 diag( w )。

用同样的步骤做减法和除法,我们可以总结出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 23: Gradients of common element-wise binary operations

向量和的梯度

深度学习中最常见的运算之一就是求和运算。如何求函数*y = sum(x)*的梯度?

y = sum()x*)*也可以表示为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 24: y=sum(x)

因此,梯度可以表示为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 25: Gradient of y=sum(x)

因为函数对不在函数中的变量的偏导数为零,所以可以进一步简化为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 26: Gradient of y=sum(x)

请注意,结果是一个水平向量。

*y = sum(xz)*的梯度呢?唯一的区别是我们用常数 z 乘以每个偏导数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 27: Gradient of y=sum(xz) with respect to x

虽然这是相对于 x 的导数,但是相对于标量 z 的导数仅仅是一个数字:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 28: Gradient of y=sum(xz) with respect to z

链式法则向量函数组合的梯度

第二部分中,我们学习了多变量链式法则。然而,这只对标量有效。让我们看看如何将它整合到矢量计算中!

让我们取一个向量函数, y = f (x) ,求它的梯度。让我们将该函数定义为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 29: y = f(x)

f₁(x)f₂(x) 都是复合函数。让我们为 f₁(x)f₂(x) 引入中间变量,并重写我们的函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 30: y = f(g(x))

现在,我们可以使用多变量链式法则来计算矢量 y 的导数。简单计算 f₁(x)f₂(x) 的导数,并将它们一个放在另一个上面:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 31: Gradient of y = f(g(x))

瞧啊。我们有梯度。然而,我们已经用标量规则得出了我们的解决方案,仅仅是将数字组合成一个向量。有没有办法表示向量的多变量链式法则?

现在,我们的梯度计算如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 32: Gradient of y = f(g(x))

注意, f₁(x)f₂(x) 的梯度的第一项都包括 g₁x 的部分,而 f₁(x)f₂(x) 的梯度的第二项都包括 g₂x 的部分。这就跟矩阵乘法一样!因此,我们可以将其表示为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 33: Vector representation of the gradient of y = f(g(x))

让我们测试一下向量链规则的新表示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 34: Vector chain rule

我们得到与标量方法相同的答案!如果我们有一个向量参数 x 而不是单个参数 x ,我们只需要稍微改变一下规则就可以得到完整的向量链规则:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 35: Vector chain rule

换句话说:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 36: Vector chain rule

在我们上面的例子中, f 纯粹是 g 的函数;即 figi 而不是 gj 的函数(每个函数 f 恰好匹配 1 个函数 g ) *)。*在这种情况下,对角线以外的一切都变为零,并且:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 37: Special case of vector chain rule

现在我们有了我们开始系列时找到的神经网络梯度的所有部分:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 38: Cost function

查看第 4 部分了解如何计算其导数!

如果您还没有,请阅读第 1 和第 2 部分:

大结局请看第四部

点击下载原文。

如果你喜欢这篇文章,别忘了留下一些掌声!如果您有任何问题或建议,请在下面留下您的评论:)

教程:带随机梯度下降的线性回归

原文:https://towardsdatascience.com/step-by-step-tutorial-on-linear-regression-with-stochastic-gradient-descent-1d35b088a843?source=collection_archive---------0-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Lindsay Henwood on Unsplash

在 JavaScript 中实现反向传播

你可以在这里 找到反向传播演示

这篇文章应该为我们深入研究深度学习提供了一个良好的开端。让我带你一步一步地计算使用随机梯度下降的线性回归任务。

A short YouTube clip for the backpropagation demo found here

内容

  1. 准备1.1数据
    1.2 模型
    1.3 定义损失功能
    1.4 最小化损失功能

2。 实现 2.1正向传播
2.1.1 初始化权重(一次性)
2.1.2 进给数据
2.1.3 计算ŷ2 . 2 . 1

1 准备

1.1 数据

我们有一些数据:当我们观察自变量 x ₁和 x ₂时,我们也观察因变量(或响应变量) y

在我们的数据集中,我们有 6 个例子(或观察)。

 **x1 x2   y**
**1)**   4  1   2
**2)**   2  8 -14
**3)**   1  0   1
**4)**   3  2  -1
**5)**   1  4  -7
**6)**   6  7  -8

1.2 模型

下一个要问的问题是:“₁和₂是如何联系在一起的?”

我们认为它们通过以下等式相互联系:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们今天的工作是找到“最佳”w 和 bb值。

我用过深度学习约定 w b ,分别代表 权重 偏差 。但是注意线性回归不是深度学习。

1.3 定义损失函数

假设在本练习结束时,我们已经算出我们的模型是

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们如何知道我们的模型做得好不好?

我们简单地通过一个损失函数比较预测的 ŷ 和观测的 y 有很多方法来定义损失函数,但在本文中,我们将其定义为 ŷy 的平方差。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一般来说 L 越小越好。

1.4 最小化损失功能

因为我们希望 ŷy 之间的差异很小,所以我们希望努力将其最小化。这是通过随机梯度下降优化完成的。它基本上是使用梯度值迭代更新 w ₁和 w ₂的值,如下式所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 2.0: Computation graph for linear regression model with stochastic gradient descent.

该算法试图通过不断更新来找到正确的权重,记住我们正在寻找最小化损失函数的值。

直觉:随机梯度下降

你是 w 你在一个图上(损失函数)。你现在的值是 w =5。你想移到图中的最低点(最小化损失函数)。

你也知道,用你当前的值,你的梯度是 2。你必须以某种方式利用这个价值继续生活。

根据高中数学,2 意味着你在一个倾斜的斜坡上,你能下来的唯一方法就是向左移动,在这一点上。

如果走 5+2 意味着你要去右边爬上斜坡,那么唯一的方法就是走 5–2,它会把你带到左边,向下。所以梯度下降就是从当前值中减去梯度值。

2.履行

我们的模型的工作流程很简单:前向传播(或前馈或前向传递)和反向传播。

定义:训练 训练简单来说就是定期更新你的权值。

下面是工作流程。单击以跳转到该部分。

— — — —
2.1 正向传播
2.1.1 初始化权重(一次性)
2.1.2 进给数据
2.1.3 计算ŷ2 . 1 . 4计算损耗

2.2 反向传播
2.2.1 计算偏导数
2.2.2 更新权重
— — — — — — — — —

让我们开始吧。

为了跟踪所有的值,我们首先构建一个“计算图”,其中包含了用颜色编码的节点

  1. 橙色 占位符( x ₁、 x ₂和 y ),
  2. 深绿色 重量和偏差( w ₁, w ₂和 b ),
  3. 浅绿色 型号 ( ŷ )连接 w ₁、 w ₂、 bx ₁、 x ₂,以及
  4. 黄色*—*损失函数 ( L )连接 ŷy.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 2.0: Computation graph for linear regression model with stochastic gradient descent.

对于正向传播,您应该从上到下阅读此图,对于反向传播,您应该从下到上阅读。

我采用了“占位符”这个术语,这个术语在tensor flow中用来指代这些“数据变量”。
我也将使用术语“重量”来统称
w b

2.1 正向传播

2.1.1 初始化砝码(一次性)

因为梯度下降是关于更新权重的,我们需要它们从一些值开始,称为初始化权重。

这里我们初始化权重和偏差如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这些反映在下面图 2.1.1 中的深绿色节点中:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 2.1.1: Weights initialised (dark green nodes)

有许多初始化权重的方法(0、1、均匀分布、正态分布、截断正态分布等)。)但我们不会在本帖中涉及它们。在本教程中,我们通过使用截尾正态分布和偏差为 0 来初始化权重。

进料数据

接下来,我们将批量大小设置为 1,并输入第一批数据。

批次和批次大小

我们可以将数据集分成大小相等的小组。每组称为一个**,由指定数量的样本组成,称为* 批量 。如果我们将这两个数字相乘,我们应该可以得到数据中的观察次数。*

在这里,我们的数据集由 6 个示例组成,由于我们在本次培训中将批次大小定义为 1,因此我们总共有 6 个批次。

用于输入模型的当前数据批次在下面以粗体显示:

 ***x1 x2   y**
**1)   4  1   2**
**2)**   2  8 -14
**3)**   1  0   1
**4)**   3  2  -1
**5)**   1  4  -7
**6)**   6  7  -8*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2.1.2: First batch of data fed into model

在图 2.1.2 中,橙色节点是我们输入当前一批数据的地方。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 2.1.2: Feeding data to model with first batch (orange nodes)

2.1.3 计算 ŷ

现在我们已经有了 x ₁、 x ₂、 w ₁、 w ₂和 b 的值,让我们计算 ŷ.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2.1.3: Compute ŷ

ŷ (=-0.1)的值反映在下面的浅绿色节点*中:*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 2.1.3: ŷ computed (light green node)

计算损失

我们预测的 ŷ 与给定的 y 数据有多远?我们通过计算前面定义的损失函数来比较它们。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2.1.4: Compute the loss

您可以在计算图的黄色节点中看到该值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 2.1.4A: L computed (yellow node)

通常的做法是记录训练期间的损失,以及其他信息,如纪元、批次和花费的时间。在我的演示中,您可以在训练进度面板下看到这一点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 2.1.4B: Logging loss and other information

2.2 反向传播

计算偏微分

在我们开始调整权重和偏差 w ₁、 w ₂和 b 的值之前,让我们首先计算所有的偏差值。这些是我们稍后更新权重时需要的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 2.2.1: Indicated partial differentials to the relevant edges on the graph

也就是说,我们只计算通向每个 wb 的所有可能路径,因为这些是我们唯一感兴趣更新的变量。从上面的图 2.2.1 中,我们看到有 4 条边被标上了偏导数。

回想一下模型和损失函数的等式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Model

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Loss function

部分差异如下:

L ( 黄色)——ŷ(浅绿色 ) :

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2.2.1A: Partial differential of L w.r.t. ŷ

ŷ ( 浅绿色)——b(深绿色):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2.2.1B: Partial differential of ŷ w.r.t. b

ŷ ( 浅绿色)——w₁(深绿色):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2.2.1C: Partial differential of ŷ w.r.t. w1

ŷ ( 浅绿色)——w₂(深绿色):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2.2.1D: Partial differential of ŷ w.r.t. w2

注意,偏微分的值遵循当前批次中的值。例如,在等式 2 中。2.2.1C, x ₁ = 4。

更新权重

观察下图 2.2.2 中的深绿色节点。我们看到三样东西:
i) b 从 0.000 变化到 0.212
ii) w ₁从-0.017 变化到 0.829
iii) w ₂从-0.048 变化到 0.164

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig. 2.2.2: Updating the weights and bias (dark green nodes)

还要注意从黄色节点绿色节点的路径的“方向”。他们从下往上走。

这是随机梯度下降-使用反向传播更新权重,利用各自的梯度值。

先重点更新一下 b 。更新 b 的公式为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2.2.2A: Stochastic gradient descent update for b

在哪里

  • b*—当前值*
  • b’更新后的值**
  • η — 学习率,设置为 0.05
  • ∂L/∂b — 梯度,即 L w.r.t. b 的偏微分

为了得到梯度,我们需要使用链式法则将从 Lb路径相乘:**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2.2.2B: Chain rule for partial differential of L w.r.t. b

我们将需要当前批次值 xy、ŷ 和偏差值,因此我们将它们放在下面以便于参考:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2.2.2C: Partial differentials

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn. 2.2.2D: Values from current batch and the predicted ŷ

使用方程中的随机梯度下降方程。2.2.2A 并代入方程中的所有值。2.2.2B-D 为我们提供了:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

更新 b 到此为止!唷!我们只剩下更新 w ₁和 w ₂,我们以类似的方式更新它们。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

批处理迭代结束

恭喜你。处理第一批就这样!

 *****x1 x2   y**
**1)**   4  1   2  ✔
**2)**  ** 2  8 -14
3)   1  0   1
4)   3  2  -1
5)   1  4  -7
6)   6  7  -8*****

现在我们需要将上述步骤重复到其他 5 个批次,即实施例 2 至 6。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Iterating through batch 1 to 6 (apologies for the poor GIF quality! )

时代结束

当模型已经遍历所有批次一次时,我们完成 1 个时期。在实践中,我们将纪元扩展到大于 1。

一个 历元 是当我们的设置已经看到了 所有 在我们的数据集中的观察值一次。但是一个纪元几乎永远不足以让损失收敛。实际上,这个数字是手动调整的。

在这一切结束时,你应该得到一个最终的模型,准备好进行推理,比如说:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们用伪代码来回顾一下整个工作流程:

***initialise_weights()for i in epochs: for j in batches: #forward propagation
        feed_batch_data()
        compute_ŷ()
        compute_loss() #backpropagation
        compute_partial_differentials()
        update_weights()***

改善培训

对于随机梯度下降优化问题,一个历元是远远不够的。记住在图 4.1 中,我们的亏损在 4.48。如果我们增加历元的数量,这意味着增加我们更新权重和偏差的次数,我们可以将其收敛到令人满意的低水平。

以下是您可以在培训中改进的地方:

  • 将培训扩展到一个以上的时代
  • 增加批量
  • 改变优化器(见我关于梯度下降优化算法的帖子这里)
  • 调整学习率(更改学习率值或使用学习率计划程序)
  • 拿出一套火车价值测试装置

关于

我用 JavaScript 构建了一个交互式的可探索的线性回归演示。以下是我使用的库:

  • Dagre-D3 (GraphViz + d3.js ),用于呈现图形
  • 用于呈现数学符号的 MathJax
  • 用于绘制折线图的图表
  • jQuery

点击查看互动演示

您可能还想看看下面的使用 TensorFlow 进行线性回归的一行一行的外行指南,该指南着重于使用 TensorFlow 库对线性回归进行编码。**

*** [## 使用 TensorFlow 进行线性回归的逐行外行指南

线性回归是机器学习之旅的一个良好开端,因为它非常简单明了…

medium.com](https://medium.com/datadriveninvestor/a-line-by-line-laymans-guide-to-linear-regression-using-tensorflow-3c0392aa9e1f)***

参考

*** [## 计算图上的微积分:反向传播——colah 的博客

反向传播是使训练深度模型在计算上易于处理的关键算法。对于现代神经…

colah.github.io](https://colah.github.io/posts/2015-08-Backprop/)

深度学习相关文章

动画版 RNN、LSTM 和 GRU

逐行 Word2Vec 实现(关于单词嵌入)

10 种梯度下降优化算法+备忘单

统计深度学习模型中的参数数量

经办人:图文并茂

图文并茂:自我关注***

感谢 【任杰】德里克 对本文的想法、建议和修正。**

关注我上Twitter@ remykarem 或者LinkedIn。你也可以通过 raimi.bkarim@gmail.com 联系我。欢迎访问我的网站*remykarem . github . io***

Google Dataproc 上的 PySpark 情感分析

原文:https://towardsdatascience.com/step-by-step-tutorial-pyspark-sentiment-analysis-on-google-dataproc-fef9bef46468?source=collection_archive---------5-----------------------

一步一步的教程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Joshua Sortino on Unsplash

我最近有机会通过 Coursera 上的一个专业化课程来体验谷歌云平台;谷歌云平台专业化上的数据工程。总的来说,我通过这些课程学到了很多东西,这是一个在完成作业的同时免费尝试谷歌云平台(GCP)各种服务的好机会。尽管我目前在工作中没有使用 GCP 的任何服务,但如果有机会,我很乐意将我的部分数据工作迁移到 GCP。

然而,这门课程缺少的一点是你自己发挥创造力的空间。这门课的作业与其说是作业,不如说是辅导课。你基本上遵循已经写好的代码。当然,通过尝试阅读每一行代码并详细理解每一行的作用,您仍然可以学到很多东西。尽管如此,如果不把你学到的知识应用到你自己的问题解决中,就很难把这些知识完全变成你的。这也是讲师拉克·拉克什马南在课程结束时的建议。(对 Lak Lakshmanan 大喊,谢谢你们的精彩课程!)

*除了我将附上的简短代码块,你可以在本文末尾找到整个 Git 库的链接。

要求

在 GCP 上创建免费试用账户

所以我决定利用各种 GCP 服务做一些个人迷你项目。幸运的是,如果你还没有尝试过 GCP,谷歌慷慨地提供了一个免费试用,给你 300 美元的信用,你可以使用超过 12 个月。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

You can easily start your free trial by visiting https://cloud.google.com/gcp/

我尝试的第一个项目是 Google Dataproc 上的 Spark 情绪分析模型训练。我选择它作为我在 GCP 的第一个项目有几个原因。在我之前的一篇文章中,我已经写了关于 PySpark 情绪分析的文章,这意味着我可以把它作为一个起点,轻松地把它变成一个独立的 Python 程序。另一个原因是我只是想试试 Google Dataproc!我被在 GCP 上运行一个集群的简单和快速迷住了,忍不住在 Coursera 课程之外尝试了一下。

如果您点击了“免费试用 GCP”,并填写了诸如您的计费帐户(即使您设置了计费帐户,除非您升级到付费帐户,否则不会向您收费)等信息,您将被定向到如下所示的页面。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Home screen of GCP web console

在顶部菜单栏,可以看到谷歌云平台旁边的“我的第一个项目”。在 GCP,“项目”是使用 GCP 服务、启用计费等的基础级实体。在第一次登录时,你可以看到谷歌自动为你创建了一个名为“我的第一个项目”的“项目”。点击它来查看当前项目的 ID,复制或记下它,这将在以后使用。通过在 web 控制台主屏幕上点击左侧菜单中的“帐单”,“我的第一个项目”会自动链接到您收到的免费点数。

启用 API

在 GCP,有许多不同的服务;计算引擎、云存储、BigQuery、云 SQL、云 Dataproc 等等。为了在您的项目中使用这些服务,您首先必须启用它们。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将鼠标放在左侧菜单的“APIs & Services”上,然后点击“Library”。对于这个项目,我们将启用三个 API:clouddataproc、计算引擎和云存储。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在 API 库页面中,通过在搜索框中键入名称,逐一搜索上述三个 API。点击进入搜索结果,并通过点击屏幕上的“启用”按钮来启用 API。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我自己尝试时,我只需要启用 Cloud Dataproc API,因为当我点击它们时,其他两个(计算引擎、云存储)已经启用了。但是如果你不是这样,请启用计算引擎 API,云存储 API。

安装 Google Cloud SDK

如果这是你第一次尝试 GCP,你可能首先要安装谷歌云 SDK,这样你就可以从命令行与 GCP 的许多服务进行交互。你可以从这里找到更多关于如何安装的信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Install Google Cloud SDK by following instructions on https://cloud.google.com/sdk/

按照链接中的说明,您将被提示登录(使用您用来开始免费试用的 Google 帐户),然后选择一个项目和计算区域(项目:选择您从上述步骤中启用 API 的项目如果有多个项目,计算区域:为了减少网络延迟,您可能希望选择一个离您近的区域。您可以从这里查看每个区域的物理位置。).

创建存储桶

因为您已经安装了 Google Cloud SDK,所以您可以从命令行或 web 控制台创建一个 bucket。

Web 控制台

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从左侧菜单中点击“存储”,然后你会看到一个类似上面的页面。点击“创建存储桶”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为方便起见,请输入您在“在 GCP 上创建免费试用帐户”阶段结束时检查的项目 ID。您可以只点击“创建”而不改变任何其他细节,或者选择与您的项目相同的位置。

谷歌云 SDK

用您复制的项目 id 替换您的 _project_id,并在您的终端上运行下面一行,将 BUCKET_NAME 变量设置为您的项目 ID,并使其可用于子流程。(您稍后需要运行的 Bash 脚本将利用这一点)

export PROJECT_ID='your_project_id'

然后通过运行 gsutil mb 命令创建一个 bucket,如下所示。

gsutil mb gs://${PROJECT_ID}

以上命令将使用默认设置创建一个 bucket。如果您想在一个特定的区域或多区域中创建一个 bucket,您可以给它-l 选项来指定区域。您可以从这里看到可用的铲斗位置。

#ex1) multi-region europe
gsutil mb -l eu gs://${PROJECT_ID}#ex)2 region europe-west1
gsutil mb -l europe-west1 gs://${PROJECT_ID}

克隆 Git 仓库

现在,通过在终端中运行下面的命令,克隆我上传的 git 存储库。

git clone [https://github.com/tthustla/pyspark_sa_gcp.git](https://github.com/tthustla/pyspark_sa_gcp.git)

准备数据

一旦您克隆了存储库,它将创建一个名为 pyspark_sa_gcp 的文件夹。进入文件夹,检查有什么文件。

cd pyspark_sa_gcp/
ls

您将在目录中看到三个文件:data_prep.sh、pyspark_sa.py、train_test_split.py。为了下载训练数据并为训练做准备,让我们运行 Bash 脚本 data_prep.sh。下面是脚本的内容,我添加了注释来解释每一行的作用。

用于训练的原始数据集是“Sentiment140”,它源于斯坦福大学。该数据集有 160 万条带标签的推文。
50%的数据带有负面标签,另 50%带有正面标签。关于数据集的更多信息可以从链接中找到。http://help.sentiment140.com/for-students/

在上面的 Bash 脚本中,您可以看到它调用了一个 Python 脚本 train_test_split.py。让我们也来看看它做了什么。

现在我们可以运行 Bash 脚本来准备数据。一旦完成,它就会将准备好的数据上传到您之前创建的云存储桶中。上传数据需要 5~6 分钟。

./data_prep.sh

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

检查上传的数据

Web 控制台

从左侧菜单转到存储,然后单击进入您的存储桶-> pyspark_nlp ->数据。您将看到上传了两个文件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

谷歌云 SDK

或者您也可以通过运行下面的命令从终端检查您的 bucket 的内容。

gsutil ls -r gs://${PROJECT_ID}/**

创建 Google Dataproc 集群

Cloud Dataproc 是一个 Google 云服务,用于运行 Apache Spark 和 Apache Hadoop 集群。我不得不说,它简单易用得可笑,使用 Google Dataproc 只需要几分钟就可以启动一个集群。此外,如果您需要,Google Dataproc 提供了自动缩放,您可以随时调整集群,即使任务正在集群上运行。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Web 控制台

从左侧菜单转到 Dataproc(您必须向下滚动一点。在“大数据”部分下),然后单击“群集”。点击“创建集群”,然后你会看到如下页面。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

给它一个名字(为了方便,我给了项目 ID 作为它的名字),选择 Region 和 Zone。为了减少延迟,最好将该区域设置为与您的 bucket 区域相同。这里您需要稍微更改一下 worker 节点的默认设置,因为免费试用版只允许您运行最多 8 个内核。群集的默认设置是一个主节点和两个工作节点,每个节点有 4 个 CPU,这将超过 8 个核心的配额。因此,将 worker 节点的设置更改为 2 个 CPU,然后单击底部的 create。经过几分钟的配置后,您将看到创建的集群包含一个主节点(4 个 CPU、15GB 内存、500GB 标准持久性磁盘)和两个工作节点(2 个 CPU、15GB 内存、500GB 标准持久性磁盘)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

谷歌云 SDK

因为我们需要稍微改变一下默认设置,所以我们需要在命令中增加一个参数,但是这很简单。让我们创建一个集群,将其命名为与项目 ID 相同的名称,并将 worker 节点设置为每个有 2 个 CPU。

gcloud dataproc clusters create ${PROJECT_ID} \--project=${PROJECT_ID} \--worker-machine-type='n1-standard-2' \--zone='europe-west1-b'

您可以将该区域更改为靠近您的存储桶区域。

提交 Spark 作业

最后,我们准备在 Google Dataproc 上运行培训。用于培训的 Python 脚本(pyspark_sa.py)包含在您之前克隆的 Git 存储库中。因为我在脚本上做了注释,解释了每一行的作用,所以我就不再赘述代码了。该代码是我在 Jupyter Notebook 中为我的上一篇文章所做的稍微重构的版本。下面是我以前的一些帖子,如果你想了解 PySpark 或 NLP 特征提取的更多细节。

让我们看看 Python 脚本是什么样子的。

由于我在脚本中添加了注释来解释每一行的作用,所以我不会详细介绍代码。但简而言之,上面的脚本将采用三个命令行参数:存储训练和测试数据的云存储位置,存储测试数据预测结果的云存储目录,以及存储训练模型的云存储目录。当被调用时,它将首先对训练数据进行预处理->构建管道->拟合管道->并对测试数据进行预测->打印预测的准确性->将预测结果保存为 CSV ->保存拟合的管道模型->加载保存的模型->再次打印测试数据的准确性(以查看模型是否正确保存)。

Web 控制台

为了通过 web 控制台运行该作业,我们需要首先将 Python 脚本上传到我们的云存储中,以便我们可以指向该作业来读取脚本。让我们通过运行下面的命令来上传脚本。(我假设您仍然在您的终端上的 pyspark_sa_gcp 目录中)

gsutil cp pyspark_sa.py gs://${PROJECT_ID}/pyspark_nlp/

现在点击 web 控制台上的 Dataproc,点击“作业”,然后点击“提交作业”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从上面的截图替换模糊的文本部分到你的项目 ID,然后点击底部的“提交”。你可以通过点击查看机器的输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这项工作在 15 分钟后完成,通过查看输出,看起来集群有点挣扎,但尽管如此,预测看起来很好,模型似乎被正确保存。

谷歌云 SDK

如果您从命令行提交作业,您甚至不需要将脚本上传到云存储。它将能够获取一个本地文件并移动到 Dataproc 集群来执行。(我再次假设您仍然在终端上的 pyspark_sa_gcp 目录中)

gcloud dataproc jobs submit pyspark pyspark_sa.py \--cluster=${PROJECT_ID} \-- gs://${PROJECT_ID}/pyspark_nlp/data/ gs://${PROJECT_ID}/pyspark_nlp/result gs://${PROJECT_ID}/pyspark_nlp/model

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

集群似乎又有点挣扎,但仍然正确地保存了结果和模型。(我已经尝试在我的付费帐户上用 4 个 CPUs worker 节点提交相同的作业,然后它没有抛出任何警告)

检查结果

去你的桶,然后进入 pyspark_nlp 文件夹。您将看到上述 Spark 作业的结果已保存到“结果”目录(用于预测数据框)和“模型”目录(拟合管道模型)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,不要忘记删除您已经创建的 Dataproc 集群,以确保它不会耗尽您的信用。

通过这篇文章,我讲述了如何在 Google Dataproc 上训练 Spark ML 模型,并保存训练好的模型以备后用。我在这里展示的只是 GCP 能力的一小部分,我鼓励你探索 GCP 上的其他服务并尝试一下。

感谢您的阅读。您可以从下面的链接中找到 Git 脚本库。

https://github.com/tthustla/pyspark_sa_gcp

走出面向特征工程的正则表达式

原文:https://towardsdatascience.com/step-out-from-regular-expression-for-feature-engineering-134e594f542c?source=collection_archive---------10-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

“woman holding book” by Eliabe Costa on Unsplash

在之前的博客中,我介绍了基于模式的识别方法,它在某些情况下很有帮助。我们有其他方法来解决类似的问题吗?是的,我们也可以使用基于词典的方法。

现在,许多人也提到无词典方法来解决分类问题。如果你有训练数据,你应该选择无词典方法来建立深度学习模型。如果没有训练数据怎么办?您可以使用基于模式的方法(正则表达式)或基于词典的方法来准备初始数据集。

看完这篇文章,你会明白:

  • 什么是基于词典的识别?
  • 我们如何在特征工程阶段利用词典?
  • 谁使用基于词汇的方法?
  • 拿走

什么是基于词典的识别?

词汇在不同的语境下有不同的含义。在自然语言处理上下文中,词典是一个预定义的词汇列表。它可以是任何词汇,如位置、名称等。但是它很少跨越不同类别形成。例如,它可以是位置词典、命名词典,但是除非有某种意义,否则不能将不同类别项目混合在一起。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo: https://pixabay.com/en/planning-housebuilding-pre-project-3536758/

对于位置,它可以是位置列表,例如香港、东京。我们也可以有一个运河词典,其中包括“波罗的海运河”,“巴拿马运河”。不知何故,我们可以使用正则表达式来识别它,但我们不会这样做,因为它可能会引入很多错误,例如它可能很容易与命名组织混淆。

我们如何在特征工程阶段利用词典?

直言特征

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在进行传统的机器学习时,我们必须手动构建大量的特征。在这种情况下,词典确实很有帮助。

根据以前的经验,我必须从文章中提取大洲。代替训练 NER,我可以简单地构建一个预定义的海洋列表,并使用精确匹配来构建特征。由于地球上只有七大洲,所以可以非常快地完成。

当然,也有一定的局限性。如果文章内容涉及旅行,我会有麻烦,因为“欧洲铁路”是一家公司,但它可能会标记为一个大洲。

二元特征

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

另一个著名的用例与情感分类问题有关。我们可以建立一个积极和消极的情绪词典来对评论的意义进行分类。

例如,“好的”和“漂亮的”可以从积极情感词汇中找到,而“坏的”、“无用的”是消极情感词汇。给定一个预定义的列表,我们不需要建立任何模型,只需要对正面和负面情感词汇的总得分进行求和。

同样,有一些限制,即否定和花费大量时间来建立列表。例如,评论可以是“它不好”。有一个否定词,它可以改变意思相反。对于积极和消极情感词典,建立高覆盖率词典并不容易。

谁使用基于词汇的方法?

有时你可能已经使用了基于词汇的方法,但你可能已经意识到了。下面将展示哪个库使用基于词典的方法来处理任务。

在空间上,它使用基于词典的方法来处理一些异常。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Capture from spaCy source code

Ghosh 等人[1]在 2017 年提出使用情感词典来解决情感分类问题。在预处理阶段,它们执行标准任务,包括归一化和去除。该功能建立在手工词典和预定义词典基础上,是 Senti-WordNet 和意见词典。

以下是部分功能:

  • Senti-WordNet 匹配的单词数
  • 与意见词典匹配的单词数
  • 与英语情感词匹配的单词数

拿走

  • 不要认为基于词典的方法是一种肮脏的方法,并努力避免这种方法。在某些情况下,它甚至比其他方法更有效。
  • 初期可以采用,建议尽快用另一种方式替代。
  • 在大多数情况下,你需要有 一个完整的列表(或者接近完整的列表),这样它才能像预期的那样工作。

关于我

我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。你可以通过媒体博客LinkedInGithub 联系我。

参考

[1] Ghosh Souvick、Ghosh Satanu 和 Das Dipankar。“代码混合社交媒体文本中的情感识别”。2017 年 7 月 4 日。https://arxiv.org/pdf/1707.01184.pdf

[2]爱森斯坦·雅各布。“基于词典分类的无监督学习”。2016 年 11 月 21 日。https://arxiv.org/pdf/1611.06933.pdf

[3]科尔奇纳。奥尔加,苏萨·塔西斯,菲利普·C。“Twitter 情感分析:词典方法、机器学习方法及其组合”。2015 年 9 月 18 日。https://arxiv.org/pdf/1507.00955.pdf

Javascript 中的作用域

原文:https://towardsdatascience.com/still-confused-in-js-scopes-f7dae62c16ee?source=collection_archive---------8-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by sergio souza on Unsplash

如果您正在学习 javascript,或者对输出问题感到困惑,甚至难以理解 javascript 的其他核心概念,那么这篇文章将会有所帮助。

什么是示波器?

范围是运行时代码中某个特定部分的变量、函数或对象的可访问性。

当最小特权的原则应用于编程语言设计时,它们就出现了。

我们为什么要学它呢?

它们为你的代码提供了一定程度的安全性,也就是说,只有在真正需要的时候才使用它们。

界定代码的范围有助于提高效率,跟踪和减少错误。

它还解决了不同作用域中同名变量的命名问题,因此减少了命名空间冲突。

范围的类型有哪些?

  1. 全球和本地
  2. 词汇的
  3. 街区
  4. 公共和私人

让我们用实例逐一查看它们。

全局范围和局部范围

任何在函数外部声明的变量都属于全局范围,因此可以从代码中的任何地方访问和修改。

函数内部定义的变量在局部范围内。对于该函数的每次调用,它们都有不同的作用域。这意味着同名的变量可以在不同的函数中使用。这是因为这些变量被绑定到它们各自的函数,每个函数都有不同的作用域,并且不能在其他函数中访问。

新函数=新的局部范围——这是规则。

// Gobal
var mouse = "Mouse";function test1() {
  // Local
  var name = "Cat";
  console.log(name);
}function test2() {
  // Local
  var name = "Dog";
  console.log(name);
}test1();
test2();console.log(name);

词汇范围

当一个函数在另一个函数中时,内部函数可以访问外部函数中的作用域,这称为词法作用域,也称为静态作用域,因为它可能只在定义它的代码块中被调用(引用)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Lexical scope

JavaScript 从最里面的范围开始向外搜索,直到找到它要寻找的变量/对象/函数。

需要记住的重要一点是,词法作用域并不向后工作而不是。也就是说,在上面的例子中,我们不能访问 SocialMedia 函数和 Platform 函数中的注释变量。

块范围

ifswitch条件或者forwhile循环和{}不像函数这样的块语句,不会创建新的作用域。block 语句中定义的变量将保留在它们原来所在的范围内。

// Gobal
var name = "Mouse";{
  // Local
  var name = "Cat";
  console.log(name); // Cat
}console.log(name); // Mouse

让我们看看围绕它的一个面试问题(执行上下文、闭包和范围的混合)

for (var i = 0; i < 3; i++) {
  setTimeout(function() { console.log(i); }, 1000 + i);
}

每次分配相同的变量值时,上面将输出 3,3,3。

在第一次迭代中,console.log(i)将被添加到堆栈中,事件循环检测到它有延迟,它被发送到事件队列,这种情况又发生了 2 次,最后当事件循环开始一个接一个地挑选它们来执行时,由于最后的 i++的缘故,变量 I 的最终值是 3,并且由于变量的范围是相同的,所以当它返回时,每个变量的值都变成 3。

然而,ECMAScript 6 引入了letconst关键字。这些关键字可以用来代替var关键字,而letconst关键字支持在块语句中声明局部作用域。

如果我们把 var i 改成 let i,现在让我们看看区别。

for (let i = 0; i < 3; i++) {
  setTimeout(function() { console.log(i); }, 1000 + i);
}

每当创建一个新的变量范围时,上面的函数将输出 0,1,2。

公共和私有范围

从公共(全局)范围包装函数使它们免受易受攻击的攻击。但是在 JavaScript 中,没有公共或私有范围这种东西。然而,我们可以模仿他们。

(function () {   
    var test = function () {
     // do some stuff here   
    }; 
})(); 
// The parenthesis at the end of the function tells the interpreter to execute it as soon as it reads it without invocation.test(); // Uncaught ReferenceError

称为模块模式的设计模式也可以用来创建这样的功能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Private and public scopes in javascript

modulePattern 的 return 语句包含我们的公共函数。私有函数只是那些不被返回的函数。不返回函数会使它们在 modulePattern 名称空间之外不可访问。但是我们的公共函数可以访问我们的私有函数,这使得它们对于辅助函数来说非常方便。

下一篇文章将讨论什么是 javascript 上下文和关于作用域的执行上下文。

如果您想被添加到我的电子邮件列表中,请考虑在此输入您的电子邮件地址关注我的medium阅读更多关于 javascript 的文章,并关注github查看我的疯狂代码。如果有什么不清楚或者你想指出什么,请在下面评论。

你可能也会喜欢我的其他文章

  1. Javascript 执行上下文和提升
  2. Javascript —生成器-产出/下一个&异步-等待🤔
  3. 理解 Javascript‘this’关键字(上下文)
  4. 带有映射、归约、过滤的 Javascript 数据结构
  5. Javascript- Currying VS 部分应用
  6. Javascript ES6 —可迭代程序和迭代器
  7. Javascript —代理Javascript —作用域

如果你喜欢这篇文章,请随意分享并帮助他人找到它!

谢谢!

带动量的随机梯度下降

原文:https://towardsdatascience.com/stochastic-gradient-descent-with-momentum-a84097641a5d?source=collection_archive---------2-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是我关于用于训练神经网络和机器学习模型的优化算法系列的第 2 部分。第一部分讲的是随机梯度下降。在这篇文章中,我假设关于神经网络和梯度下降算法的基本知识。如果你对神经网络或者如何训练神经网络一无所知,在阅读这篇文章之前,请随意阅读我的第一篇文章。

在这篇文章中,我将讨论经典 SGD 算法的简单加法,叫做动量法,它几乎总是比随机梯度下降法更好更快。Momentum [1]或 SGD with momentum 是一种有助于在正确方向上加速梯度向量的方法,从而导致更快的收敛。它是最流行的优化算法之一,许多先进的模型都是用它来训练的。在跳到算法的更新方程之前,让我们看看动量功的数学基础。

指数加权平均值

指数加权平均值处理的是数字序列。假设,我们有一些有噪声的序列。对于这个例子,我绘制了余弦函数,并添加了一些高斯噪声。看起来是这样的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Out sequence.

请注意,尽管这些点看起来非常接近,但它们都没有共享 x 坐标。对于每个点来说,这是一个唯一的数字。这个数字定义了序列中每个点的索引。

我们想对这些数据做的是,不是使用它,而是想要某种“移动”平均值,这将对数据进行“去噪”,并使其更接近原始函数。指数加权平均值可以给我们一个看起来像这样的图片:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

momentum — data from exponentially weighed averages.

如你所见,这是一个非常好的结果。我们得到的不是有很多噪音的数据,而是更平滑的线,比我们得到的数据更接近原始函数。指数加权平均值用下面的等式定义了新的序列 V:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

序列 V 就是上面标为黄色的那个。 Beta 是另一个超参数,取值从 0 到 1。上面我用了 beta = 0.9。这是一个很好的值,最常用于带动量的 SGD。直觉上,你可以把 beta 想成如下。我们对序列的最后1/(1-β)个点进行近似平均。让我们看看β的选择如何影响我们的新序列 v。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Exponentially weighed averages for different values of beta.

如您所见,beta 值越小,新序列的波动就越大,因为我们对更小数量的样本求平均,因此更接近噪声数据。β值越大,如β= 0.98,我们得到的曲线越平滑,但它会向右偏移一点,因为我们对大量的示例进行了平均(对于β= 0.98约为 50)。 Beta = 0.9 在这两个极端之间提供了一个很好的平衡。

数学部分

这一部分对于在你的项目中使用动量是不必要的,所以可以跳过它。但是它提供了更多关于动量如何工作的直觉。

让我们扩展新序列 v 的三个连续元素的指数加权平均值的定义。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

V — New sequence. S — original sequence.

将所有这些结合在一起,我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后稍微简化一下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从这个等式中我们看到,新序列的第号的值依赖于所有先前的值 1…来自 S 的所有值都被赋予一定的权重。这个权重是 s 的第 (t - i) 个值的betaI的幂乘以 (1- beta) ,因为 beta 小于 1,所以当我们将 beta 取某个正数的幂时,它会变得更小。因此,S 的旧值得到小得多的权重,因此对 v 的当前点的整体值的贡献更小。在某个点上,权重将变得如此之小,以至于我们几乎可以说我们“忘记”了该值,因为它的贡献变得小到无法注意到。当重量变得小于 1 / e 时,这是一个很好的近似值。更大的β值要求更大的功率值小于 1 / e 。这就是为什么β值越大,我们平均的点数就越多。下图显示了与 threshold = 1 / e 相比,较旧的 S 值的权重变小的速度,在 threshold =1/e中,我们通常会“忘记”较旧的值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后要注意的是,前几次迭代将提供一个非常糟糕的平均值,因为我们还没有足够的值来平均。解决方法是不使用 V,我们可以使用 V 的偏差修正版本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中b =β。t 的值很大时,b 的 t 次方与零没有区别,因此根本不会改变 V 的值。但是对于小 t 值,这个等式会产生稍微好一点的结果。有了动量,人们通常不会费心去实现这一部分,因为学习稳定得相当快。

带动量的 SGD

我们已经定义了一种方法来获得一些序列的“移动”平均值,它随着数据一起变化。我们如何将此应用于训练神经网络?可以平均我们的梯度。我将在 momentum 中定义它是如何实现的,然后继续解释为什么它可能会更好。

我将给出 SGD 和动量的两种定义,它们几乎是写同一个方程的两种不同方式。首先,吴恩达在 coursera 上的深度学习专业课程中是如何定义它的。按照他的解释,我们定义了一个动量,它是我们梯度的移动平均值。然后我们用它来更新网络的权重。可以这样写:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 L —是损失函数,三角形物—梯度 w.r.t 权重, alpha —学习率。另一种方法是编写动量更新规则最流行的方法,它不太直观,只是省略了 (1 - beta) 项。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这与第一对等式非常相似,唯一的区别是你需要用 (1 - beta) 因子来衡量学习率。

内斯特罗夫加速梯度

内斯特罗夫 Momentum 是 Momentum 更新的一个略有不同的版本,最近越来越受欢迎。在这个版本中,我们首先看当前动量指向的点,并从该点计算梯度。当你看这幅画时,它变得清晰多了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source (Stanford CS231n class)

内斯特罗夫动量可以用下面的公式来定义:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为什么动量起作用

在这一节中,我想谈一点为什么动量在大多数时候会比经典 SGD 更好。

对于随机梯度下降,我们不计算损失函数的精确导数。相反,我们是在小批量的基础上估算的。这意味着我们并不总是朝着最佳方向前进,因为我们的导数是“嘈杂的”。就像我上面的图表一样。因此,指数加权平均值可以为我们提供更好的估计,比我们嘈杂的计算更接近实际的导数。这就是为什么动量理论可能比经典 SGD 更有效的原因之一。

另一个原因在于沟壑。峡谷是这样一个区域,它的表面在一个维度上比在另一个维度上弯曲得更陡。深谷在深度学习的局部极小值附近是常见的,SGD 在导航它们时有困难。SGD 将倾向于在狭窄的峡谷中振荡,因为负梯度将指向陡峭的一侧,而不是沿着峡谷指向最优值。动量有助于加速正确方向的梯度。这表现在下面的图片中:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Left — SGD without momentum, right— SGD with momentum. (Source: Genevieve B. Orr)

结论

我希望这篇文章能给你一些直觉,让你知道 SGD 如何以及为什么有动力。它实际上是深度学习中最流行的优化算法之一,甚至比更高级的算法使用得更频繁。

下面我提供一些参考,在这里你可以学到更多关于深度学习中的优化。

参考

[1]钱宁。关于梯度下降学习算法中的动量项。神经网络:国际神经网络学会官方杂志,12(1):145–151,1999

【2】提炼,为什么动量真的起作用

[3] deeplearning.ai

[4] 鲁德 (2016)。梯度下降优化算法概述。arXiv 预印本 arXiv:1609.04747

[5] Ruder (2017) 深度学习优化 2017 年亮点

[6] 斯坦福 CS231n 讲义

【7】fast . ai

随机加权平均——一种获得深度学习最新结果的新方法

原文:https://towardsdatascience.com/stochastic-weight-averaging-a-new-way-to-get-state-of-the-art-results-in-deep-learning-c639ccf36a?source=collection_archive---------2-----------------------

更新:你现在可以在我的个人博客上欣赏这篇文章,这里的数学排版要好得多(Medium 不支持数学渲染,尽管有很多请求)。

在这篇文章中,我将讨论两篇有趣的近期论文,它们提供了一种简单的方法,通过使用一种智能的集成方法来提高任何给定神经网络的性能。它们是:

  1. 损失表面、模式连接和 dnn 的快速组装。铝
  2. 伊兹迈洛夫等人的“平均权重导致更宽的最优值和更好的泛化能力”。铝

额外的先决条件阅读将使这篇文章的内容更容易理解:

  • Vitaly Bushaev 的“提高学习率,改进我们的工作方式”

神经网络的传统集成

传统的集成将几个不同的模型结合起来,并使它们对相同的输入进行预测。然后使用某种平均方法来确定系综的最终预测。它可以是简单的投票、平均或者甚至是基于集合中模型的输入来学习预测正确值或标签的另一个模型。岭回归是一种结合几种预测的特殊方法,被获奖的机器学习实践者使用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Snapshot Ensemble is created by saving a model each time the learning rate cycle is at the end. Then the saved models are used together during prediction. Source.

当应用于深度学习时,集成可用于组合几个神经网络的预测,以产生一个最终预测。通常,在集成中使用不同架构的神经网络是一个好主意,因为它们可能会在不同的训练样本上出错,因此集成的好处会更大。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Snapshot ensemble uses cyclical learning rates with annealing. Source.

然而,你也可以用相同的架构集合模型,它会给出令人惊讶的好结果。在快照集成论文中提出了一个利用这种方法的非常酷的技巧。作者在训练相同的网络时拍摄权重快照,然后在训练后创建具有相同架构但不同权重的网络集合。这可以提高测试性能,而且这也是一种非常便宜的方法,因为你只需训练一个模型一次,只是不时地节省重量。

更多细节可以参考这篇牛逼的帖子。如果你还没有使用循环学习率,那么你肯定应该使用,因为它已经成为标准的最先进的训练技术,非常简单,计算量不大,并且几乎不需要额外的成本就可以获得显著的收益。

上面所有的例子都是模型空间中的集合,因为它们组合了几个模型,然后使用模型的预测来产生最终的预测。

然而,在我在这篇文章中讨论的论文中,作者提议在权重空间中使用一个小说集合。这种方法通过组合同一网络在不同训练阶段的权重来产生一个集成,然后使用这个具有组合权重的模型来进行预测。这种方法有两个好处:

  • 当组合权重时,我们最终仍然得到一个模型,这加快了预测的速度
  • 事实证明,这种方法胜过当前最先进的快照集合

让我们看看它是如何工作的。但是首先我们需要了解一些关于损失曲面和广义解的重要事实。

重量空间中的解决方案

第一个重要的见解是,一个经过训练的网络是多维权重空间中的一个点。对于给定的体系结构,每个不同的网络权重组合都会产生一个单独的模型。由于任何给定的架构都有无限多种权重组合,因此会有无限多种解决方案。训练神经网络的目标是找到特定的解决方案(权重空间中的点),该解决方案将在训练和测试数据集上提供损失函数的低值。

在训练过程中,通过改变权值,训练算法改变网络并在权值空间中行进。梯度下降算法在该空间中的损失平面上行进,其中平面高程由损失函数值给出。

窄和宽最优

很难想象和理解多维权重空间的几何形状。同时,理解它是非常重要的,因为随机梯度下降本质上是在训练时遍历这个高维空间中的一个损失面,并试图找到一个好的解——损失面上损失值较低的“点”。众所周知这样的曲面有很多局部最优。但事实证明,并不是所有的都一样好。

辛顿:“要处理 14 维空间中的超平面,想象一个 3 维空间,大声对自己说‘14’。大家都这么干。”(来源)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Narrow and wide optima. Flat minimum will produce similar loss during training and testing. Narrow loss, however, will give very different results during training and testing. In other words, wide minimum is more generalizable than narrow. Source.

一个可以区分好的解决方案和坏的解决方案的度量是它的平坦度。想法是训练数据集和测试数据集将产生相似但不完全相同的损失表面。你可以想象一个测试表面会相对于火车表面移动一点。对于狭窄的解决方案,在测试期间,由于这种偏移,给出低损耗的点可能具有大的损耗。这意味着这种“狭隘”的解决方案不能很好地推广——训练损失低,而测试损失大。另一方面,对于“宽”和扁平的解决方案,这种转变将导致培训和测试损失彼此接近。

我解释了窄解和宽解之间的区别,因为这篇文章的重点是新的方法,它可以产生好的宽解。

快照集成

最初,SGD 将在重量空间进行大的跳跃。然后,随着学习速率由于余弦退火而变得更小,SGD 将收敛到某个局部解,并且算法将通过将模型添加到集成来拍摄模型的“快照”。然后,速率再次被重置为高值,SGD 在收敛到某个不同的局部解之前再次进行大的跳跃。

快照集合方法中的周期长度是 20 到 40 个历元。长学习率周期的想法是能够在权重空间中找到足够不同的模型。如果模型过于相似,那么集合中独立网络的预测将会过于接近,集合的好处将会忽略不计。

快照集合工作得非常好,并且提高了模型性能,但是快速几何集合工作得更好。

快速几何装配(FGE)

快速几何组合与快照组合非常相似,但有一些区别特征。它使用线性分段循环学习率调度代替余弦。其次,FGE 的周期长度要短得多——每个周期只有 2 到 4 个时期。乍一看,短周期是错误的,因为每个周期结束时的模型会彼此靠近,因此将它们组合在一起不会带来任何好处。然而,正如作者所发现的,因为在足够不同的模型之间存在低损耗的连接路径,所以有可能沿着这些路径以小步骤行进,并且沿途遇到的模型将足够不同,从而允许以良好的结果集合它们。因此, FGE 显示出与快照集相比的改进,并且需要更小的步骤来找到模型(这使得训练更快)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LEFT: Traditional intuition is that good local minima are separated by regions of high loss. This is true if we travel along the lines connecting local minima. MIDDLE and RIGHT: However, there exist paths between local minima, such that loss stays low on these paths. FGE takes snapshots along these paths and creates an ensemble out of the snapshots. Source.

为了从快照集成或 FGE 中受益,需要存储多个模型,然后在对最终预测进行平均之前对所有模型进行预测。因此,对于系综的额外性能,需要付出更高的计算量。所以那里没有免费的午餐。还是有?这就是随机加权平均的新论文的用武之地。

随机加权平均法

随机加权平均 非常接近快速几何集合,但计算损失很小。SWA 可以应用于任何体系结构和数据集,并在所有的体系结构和数据集上都显示出良好的效果。这篇论文表明 SWA 导致了更宽的最小值,我在上面讨论了它的好处。SWA 不是传统意义上的合奏。在训练结束时,你得到一个模型,但它的性能胜过快照集,接近 FGE。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LEFT: W1, W2 and W3 represent 3 independently trained networks, Wswa is the average of them. MIDDLE: Wswa provides superior performance on the test set as compared to SGD. RIGHT: Note that even though Wswa shows worse loss during training, it generalizes better. Source.

SWA 的直觉来自经验观察,即在每个学习率周期结束时,局部最小值倾向于在损失值较低的损失表面区域的边界处累积(点 W1、W2 和 W3 位于上图左面的红色低损失区域的边界处)。通过取几个这样的点的平均值,有可能以更低的损失获得广泛的、可概括的解决方案(上图左图中的 Wswa)。

这是它的工作原理。您只需要两个模型,而不是许多模型的集合:

  • 存储模型权重的移动平均值的第一个模型(公式中的 w_swa)。这将是训练结束后用于预测的最终模型。
  • 第二个模型(公式中的 w)将遍历权重空间,通过使用循环学习率时间表来探索它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Stochastic Weight Average weight update equation. Source.

在每个学习率周期结束时,第二个模型的当前权重将用于更新运行平均模型的权重,方法是在旧的运行平均权重和第二个模型的新权重集之间取加权平均值(左图中提供了公式)。按照这种方法,您只需要训练一个模型,并且在训练期间只在内存中存储两个模型。对于预测,您只需要运行平均模型,对其进行预测比使用上述集成快得多,在集成中,您使用许多模型进行预测,然后对结果进行平均。

履行

论文作者提供了他们自己在 PyTorch 中的实现。

此外,SWA 在每个人都应该使用的超棒的 fast.ai 库中实现。如果你还没看过他们的课程,那么跟随链接

感谢阅读!如果你喜欢,点击下面的按钮我的网站上订阅更新!这对我意义重大,鼓励我写更多这样的故事。

可以在 Twitter 上 关注我 。下面我们也连线上LinkedIn

Python 中的股票分析

原文:https://towardsdatascience.com/stock-analysis-in-python-a0054e2c1a4c?source=collection_archive---------0-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用面向对象编程和附加模型探索财务数据

人们很容易被大量的数据和可用于数据科学的免费开源工具冲昏头脑。在花了一点时间在 quandl 金融库先知建模库之后,我决定尝试一些简单的股票数据探索。几天和 1000 行 Python 代码之后,我完成了一个完整的股票分析和预测工具。虽然我没有足够的信心(或愚蠢)用它来投资个股,但在这个过程中,我学习了大量 Python,本着开源的精神,我想分享我的成果和代码,这样其他人也可以受益。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Now more than ever

本文将展示如何使用 Stocker,这是一个基于 Python 类的股票分析和预测工具(这个名称最初是随意取的,但我后来决定它很好地代表了“股票浏览器”)。我曾几次试图攻克类,这是 Python 中面向对象编程的基础,但是和大多数编程主题一样,当我阅读这些书籍时,它们对我来说从来没有什么意义。只有当我深入一个项目,面对一个我以前没有解决的问题时,这个概念才最终实现,这再一次表明经验胜过理论解释!除了探索 Stocker 之外,我们还将触及一些重要的主题,包括 Python 类和附加模型的基础知识。对于任何想使用 Stocker 的人来说,完整的代码可以在 GitHub 上找到,还有使用文档。Stocker 被设计得易于使用(即使对于那些 Python 新手来说也是如此),我鼓励任何人去尝试一下。现在,我们来看看 Stocker 的分析能力!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

储料器入门

在安装了所需的库之后,我们要做的第一件事就是将 Stocker 类导入到我们的 Python 会话中。我们可以从交互式 Python 会话或 Jupyter 笔记本中使用脚本启动目录来完成这项工作。

from stocker import Stocker

现在我们的 Python 会话中有了 Stocker 类,我们可以用它来创建该类的一个实例。在 Python 中,类的实例被称为对象,创建对象的行为有时被称为实例化或构造。为了创建一个 Stocker 对象,我们需要传入一个有效股票代码 ( 粗体表示输出)。

microsoft = Stocker('MSFT')**MSFT Stocker Initialized. Data covers 1986-03-13 to 2018-01-16.**

现在,我们有了一个包含 Stocker 类所有属性的microsoft对象。Stocker 是建立在 quandl WIKI 数据库上的,该数据库让我们可以访问超过 3000 只美国股票的多年每日价格数据。对于这个例子,我们将坚持使用微软的数据。尽管微软可能被视为开源的对立面,但他们最近做出了一些让我乐观的改变,他们正在拥抱开源社区(包括 Python)。

Python 中的类由两个主要部分组成:属性和方法。不涉及太多细节,属性是与整个类或者与该类的特定实例(对象)相关联的值或数据。方法是包含在类中的函数,可以作用于数据。Stocker 对象的一个属性是特定公司的股票数据,当我们构造它时,这个属性与对象相关联。我们可以访问该属性,并将其赋给另一个变量进行检查:

# Stock is an attribute of the microsoft object
stock_history = microsoft.stock
stock_history.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Microsoft Stock Data

Python 类的好处是方法(函数)和它们作用的数据与同一个对象相关联。我们可以使用 Stocker 对象的方法来绘制股票的整个历史。

# A method (function) requires parentheses
microsoft.plot_stock()**Maximum Adj. Close = 89.58 on 2018-01-12.
Minimum Adj. Close = 0.06 on 1986-03-24.
Current Adj. Close = 88.35.**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

绘制的默认值是调整后的收盘价,它考虑了股票的分割(当一只股票分割成多只股票时,比如说 2 只,每只新股票的价值是原价的 1/2)。

这是一个非常基本的情节,我们可以从谷歌搜索中找到,但用几行 Python 代码自己完成也有令人满意的地方!plot_stock函数有许多可选参数。默认情况下,该方法绘制整个日期范围的调整后收盘价,但我们可以选择范围、要绘制的统计数据和绘制类型。例如,如果我们想将价格的每日变化与调整后的交易量(股票数量)进行比较,我们可以在函数调用中指定它们。

microsoft.plot_stock(start_date = '2000-01-03',  end_date = '2018-01-16',  stats = ['Daily Change', 'Adj. Volume'],  plot_type='pct')**Maximum Daily Change = 2.08 on 2008-10-13.
Minimum Daily Change = -3.34 on 2017-12-04.
Current Daily Change = -1.75.

Maximum Adj. Volume = 591052200.00 on 2006-04-28.
Minimum Adj. Volume = 7425503.00 on 2017-11-24.
Current Adj. Volume = 35945428.00.**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

请注意,y 轴是相对于统计平均值的百分比变化。这种规模是必要的,因为每天的交易量最初是以股票为单位的,范围在数亿股,而每天的价格变化通常是几美元!通过转换为百分比变化,我们可以在相似的范围内查看两个数据集。该图显示,交易的股票数量和每日价格变化之间没有相关性。这是令人惊讶的,因为我们可能预计在价格变化较大的日子里会有更多的股票交易,因为人们急于利用波动。然而,唯一真实的趋势似乎是交易量随着时间的推移而减少。2017 年 12 月 4 日的价格也有显著下降,我们可以尝试将这与关于微软的新闻报道联系起来。快速搜索 12 月 3 日的新闻会得到以下结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Not sure about the reliability of these sources Google

当然,似乎没有任何迹象表明微软股票将在第二天出现 10 年来最大的价格下跌!事实上,如果我们根据新闻来玩股票市场,我们可能会被诱惑去买股票,因为与 NFL 的交易(第二个结果)听起来是积极的!

使用plot_stock,我们可以调查任何日期范围内数据中的任何数量,并寻找与现实世界事件的相关性(如果有的话)。现在,我们将转移到 Stocker 更有趣的部分:制造假币!

让我们假设在公司首次公开募股(首次公开募股)时,我们镇定自若地投资了 100 股微软股票。我们现在会有多富有?

microsoft.buy_and_hold(start_date='1986-03-13', 
                       end_date='2018-01-16', nshares=100)**MSFT Total buy and hold profit from 1986-03-13 to 2018-01-16 for 100 shares = $8829.11**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

除了让我们感觉更好,使用这些结果将允许我们及时计划我们的旅行,以实现利润最大化。

如果我们感觉过于自信,我们可以试着调整结果来赔钱:

microsoft.buy_and_hold(start_date='1999-01-05', 
                      end_date='2002-01-03', nshares=100)**MSFT Total buy and hold profit from 1999-01-05 to 2002-01-03 for 100 shares = $-56.92**

出人意料的是,在股市上有可能亏钱!

加法模型

加法模型是分析和预测时间序列的强大工具,时间序列是现实世界中最常见的数据类型之一。这个概念很简单:将时间序列表示为不同时间尺度上的模式和总体趋势的组合。我们知道微软股票的长期趋势是稳步上涨,但也可能存在以年或日为基础的模式,例如每周二上涨,了解这一点将有利于经济发展。由脸书开发的 Prophet 是一个很好的库,用于分析每日观察的时间序列(比如股票)。Stocker 在幕后使用 Prophet 为我们完成所有建模工作,因此我们可以使用一个简单的方法调用来创建和检查模型。

model, model_data = microsoft.create_prophet_model()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

加性模型消除了数据中的噪声,这就是为什么模型线与观测值不完全一致的原因。Prophet 模型还计算不确定性,这是建模的一个重要部分,因为在处理波动的现实生活过程时,我们永远无法确定我们的预测。我们也可以使用先知模型来预测未来,但目前我们更关心过去的数据。注意,这个方法调用返回了两个对象,一个模型和一些数据,我们将它们赋给了变量。我们现在使用这些变量来绘制时间序列的组成部分。

# model and model_data are from previous method call
model.plot_components(model_data)
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

过去三年来,总体趋势是明确的增长。似乎还有一个值得注意的年度模式(下图),价格在 9 月和 10 月触底,在 11 月和 1 月达到峰值。随着时间尺度的减小,数据变得更加嘈杂。在一个典型的月份里,信号比噪音多。如果我们认为可能有一个周模式,我们可以通过更改 Stocker 对象的weekly_seasonality属性将它添加到 prophet 模型中:

print(microsoft.weekly_seasonality)
microsoft.weekly_seasonality = True
print(microsoft.weekly_seasonality)**False 
True**

weekly_seasonality的默认值是 False,但是我们更改了该值,在模型中包含了一个周模式。然后,我们再次调用create_prophet_model,并用图形表示结果组件。以下是新模型的每周季节性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

There was no way I could make this graph look good

我们可以忽略周末,因为价格只在一周内变化(实际上,价格在下班后培训期间有少量变化,但不影响我们的分析)。不幸的是,没有一周的趋势可供我们使用,在我们继续建模之前,我们将关闭每周季节性。这种行为是意料之中的:对于股票数据,随着时间尺度的减小,噪声开始淹没信号。日复一日,股票的走势基本上是随机的,只有缩小到年度规模,我们才能看到趋势。希望这能很好地提醒你为什么不玩每日股票游戏!

变革点

当时间序列从增加到减少或从减少到增加(更严格地说,它们位于时间序列比率的变化最大的地方)。这些时间是非常重要的,因为知道一只股票什么时候会达到顶峰或将要起飞可能会带来巨大的经济利益。识别转折点的原因可能会让我们预测股票价值的未来波动。Stocker 对象可以自动为我们找到 10 个最大的变化点。

microsoft.changepoint_date_analysis()**Changepoints sorted by slope rate of change (2nd derivative):

          Date  Adj. Close     delta
48  2015-03-30   38.238066  2.580296
337 2016-05-20   48.886934  2.231580
409 2016-09-01   55.966886 -2.053965
72  2015-05-04   45.034285 -2.040387
313 2016-04-18   54.141111 -1.936257**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

转折点往往与股价的波峰和波谷一致。Prophet 只在前 80%的数据中找到变化点,但是尽管如此,这些结果还是很有用的,因为我们可以尝试将它们与现实世界的事件联系起来。我们可以重复之前所做的,在这些日期手动搜索谷歌新闻,但我认为如果斯托克为我们这样做会更好。你可能见过谷歌搜索趋势工具,它可以让你看到任何搜索术语在谷歌搜索中的流行程度。Stocker 可以自动检索我们指定的任何搜索项的数据,并在原始数据上绘制结果。为了找到并绘制搜索词的频率,我们修改了前面的方法调用。

# same method but with a search term
microsoft.changepoint_date_analysis(search = 'Microsoft profit')**Top Related Queries: 

                  query  value
0  microsoft non profit    100
1      microsoft office     55
2                 apple     30
3         microsoft 365     30
4  microsoft office 365     20

 Rising Related Queries: 

                   query  value
0          microsoft 365    120
1   microsoft office 365     90
2  microsoft profit 2014     70**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

除了绘制相对搜索频率的图表之外,Stocker 还显示了图表日期范围内排名靠前的相关查询和排名靠前的上升查询。在图中,y 轴通过将值除以其最大值而在 0 和 1 之间标准化,从而允许我们比较不同标度的两个变量。从图中可以看出,搜索“微软利润”和微软股票价格之间似乎没有关联。

如果我们发现了相关性,那么还会有因果关系的问题。我们不知道是搜索还是新闻导致了价格的变化,或者是价格的变化导致了搜索。可能会发现一些有用的信息,但也有许多偶然的关联。(关于这种随机关系的幽默,请看的虚假关联。请随意尝试一些不同的术语,看看您是否能发现任何有趣的趋势!

microsoft.changepoint_date_analysis(search = 'Microsoft Office')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看起来 Office 搜索量的下降导致了股价的上涨。也许应该有人让微软知道。

预言

我们只探索了 Stocker 功能的前半部分。后半部分用于预测,或预测未来的股票价格。虽然这可能是徒劳的(或者至少不会有回报),但在这个过程中仍然有很多东西要学!请继续关注未来关于预测的文章,或者自己开始使用 Stocker 进行预测(查看文档了解详情)。现在,我再给你们看一张图片。

# specify number of days in future to make a prediction
model, future = microsoft.create_prophet_model(days=180)**Predicted Price on 2018-07-15 = $97.67**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

尽管 Stocker 的所有功能可能已经公开可用,但创建这个工具的过程是令人愉快的,更重要的是,它教会了我比任何大学课程都多的关于数据科学、Python 和股票市场的知识。我们生活在一个知识民主化的不可思议的时代,任何人都可以在没有正式指导的情况下学习关于编程的知识,甚至是像机器学习这样的艺术领域。如果你有一个项目的想法,但认为你知道得不够多,或者发现以前有人做过,不要让这阻止你。你可能会开发出一个更好的解决方案,即使你没有,你也会比你从未开始时过得更好,知道得更多!

一如既往,我欢迎建设性的批评和反馈。可以在推特上找到我,电话是 @koehrsen_will

Python 中的股票市场分析

原文:https://towardsdatascience.com/stock-market-analysis-in-python-part-1-getting-data-by-web-scraping-cb0589aca178?source=collection_archive---------2-----------------------

第 1 部分:通过 Web 抓取获取数据

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Staying Invested! What was your gain?

自 2013 年以来,全球股市经历了一轮壮观的牛市。在印度,许多公司增长了 10 倍以上。即使是行业领导者,nifty 50 或印度 50 强公司也增长了两倍以上。2017 年,Nifty 50 的年增长率(或回报率)超过 20%,2018 年的趋势似乎也是如此。人们正在投资共同基金和交易所交易基金来跟随这一趋势。

在这种情况下,我们似乎应该更多地投资股票,但如果你看看新闻,你会发现大多数市场分析师都认为目前的市场投资非常昂贵。那么,我们是相信他们的话,还是自己做一些数据分析来找出答案呢?我们如何在一个被高度高估的市场中找到好公司?这是又一次类似比特币/加密货币泡沫的炒作吗?

在这一系列教程中,我们将使用 python 来找出答案。

在第 1 部分中,我们学习如何获取数据。在第 2 部分中,我们将看看如何进行分析。

在本教程(第 1 部分)中,我们将学习

  • 通过请求库在 python 中发出 http 请求。
  • 使用 chrome 开发工具来查看数据在页面上的位置。
  • 使用 BeautifulSoup 库,当数据无法以结构化形式获得时,从下载的页面中抓取数据。
  • 将表等数据解析为 python 2D 数组。
  • 抓取功能以字典的形式获取数据(键-值对)。

这里需要的 Jupyter 笔记本是这里是

设置

  1. 通过安装蟒蛇来安装 Jupyter 笔记本。关于在 Linux 服务器上安装,参见我的上一篇文章
  2. 确保除了 Anaconda 的默认包集之外,还安装了以下 python 包。
beautifulsoup4
fastnumbers
dill

3.启动一个 python 3 jupyter 笔记本并添加以下导入。

**import** numpy **as** np *# linear algebra*
**import** pandas **as** pd *# pandas for dataframe based data processing and CSV file I/O***import** requests *# for http requests*
**from** bs4 **import** BeautifulSoup *# for html parsing and scraping* **import** bs4**from** fastnumbers **import** isfloat 
**from** fastnumbers **import** fast_float
**from** multiprocessing.dummy **import** Pool **as** ThreadPool 

**import** matplotlib.pyplot **as** plt
**import** seaborn **as** sns
**import** json
**from** tidylib **import** tidy_document *# for tidying incorrect html*

sns.set_style('whitegrid')
%matplotlib inline
**from** IPython.core.interactiveshell **import** InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

现在我们准备好开始了。如果有任何困难,请查看我在 Github 上的 jupyter 笔记本。

我们收集数据时需要的一些实用程序

字符串到浮点的转换

网页中的很多数字都是用逗号和%符号组成的字符串。我们使用 fastnumbers 库中的fast_float函数。

**def** ffloat(string):
    **if** string **is** **None**:
        **return** np.nan
    **if** type(string)==float **or** type(string)==np.float64:
        **return** string
    **if** type(string)==int **or** type(string)==np.int64:
        **return** string
    **return** fast_float(string.split(" ")[0].replace(',','').replace('%',''),
                      default=np.nan)

我们检查输入是否已经是 float/int,然后返回相同的值,否则删除逗号和%,然后转换。

另一个函数来完成字符串列表的转换

**def** ffloat_list(string_list):
    **return** list(map(ffloat,string_list))

从字符串中删除多个空格

当从网页中提取文本时,一些字符串在单词之间有多个空格,以保持一致性。

**def** remove_multiple_spaces(string):
    **if** type(string)==str:
        **return** ' '.join(string.split())
    **return** string

用 Python 发出 Http 请求

为此,我们将使用 python 请求库。您需要知道您将请求的页面的 url。

使用方法requests.get发出请求,我们用response.status_coderesponse.content分别获取 http 状态和页面内容

response **=** requests.get("http://www.example.com/", timeout=240)
response**.**status_code
response**.**content

请注意,requests library 并不在页面上运行 javascript,因此在通过 javascript 加载 html 内容之后获取的任何数据/内容都将不可用。这不是一个问题,因为大多数金融网站通常遵循服务器端脚本,并向客户发送完整的页面。

获取 Json 内容并解析它

要从页面中获取 json 内容,只需做response.json()

url **=** "**https://jsonplaceholder.typicode.com/posts/1**"
response **=** requests.get(url, timeout=240)
response.status_code
response.json()

content **=** page_response.json()
content.keys()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Json Response

为了确保您的请求成功,请务必检查response.status_code

通过解析和遍历 HTML 抓取数据

我们将使用 beautifulsoup4 库将 html 字符串解析成树状表示。

在 Jupyter 笔记本中呈现 HTML 字符串

**from** **IPython.core.display** **import** HTML
HTML("**<b>Rendered HTML</b>**")

使用 Chrome 检查器(开发工具)获取内容的位置

我们将会看到这个网址:https://www . money control . com/India/stockprice quote/auto-2-3-wheelers/hero moto corp/HHM

这是一家在印度生产摩托车的公司的网页。请查看该页面。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Snapshot of the link

现在,要从页面中获取任何内容,您需要知道内容在 HTML 中的位置。所以首先我们会得到标题(“Hero Motocorp Ltd .”)。让我们用 Chrome inspector 检查页面。要在 mac 上使用 chrome inspector,请使用cmd+option+i,在 windows 和 linux 上使用Control+Shift+I

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Using inspector

打开 chrome inspector ->点击元素(1) ->点击光标框项目(2) ->指向“Hero Motocorp Ltd .”然后点击。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Finding element location

如您所见,公司名称在

标签中。接下来,我们看看如何在笔记本中获取这些内容。

使用 BeautifulSoup4 解析和显示内容

为此,我们需要获得响应,然后使用BeautifulSoup类解析内容。最后,我们从< h1 >标签中获取内容并呈现出来。

response **=** requests.get("[**https://www.moneycontrol.com/india/stockpricequote/auto-2-3-wheelers/heromotocorp/HHM**](https://www.moneycontrol.com/india/stockpricequote/auto-2-3-wheelers/heromotocorp/HHM)", timeout=240)
page_content = **BeautifulSoup**(response.content, "**html.parser**")
HTML(**str**(page_content.find("**h1**")))

通过属性获取 HTML 元素

我们将在 id 为“b_changetext”的

中获取当天的价格变化。为此,您只需将一个attrs对象传递给page_content.find

response = requests.get("[**https://www.moneycontrol.com/india/stockpricequote/auto-2-3-wheelers/heromotocorp/HHM**](https://www.moneycontrol.com/india/stockpricequote/auto-2-3-wheelers/heromotocorp/HHM)", timeout=240)
content = BeautifulSoup(response.content, "**html.parser**")price_div = content.find("**div**",attrs={"**id**":'**b_changetext**'})
HTML(str(price_div))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Output of price getter code

find 的一些其他变体如下

content.find_all("p")
content.find_next("p",attrs={"class":"my-id"})

.find_all查找页面中出现的所有给定规格。.find_next查找下一个事件。一旦你有了元素,你可以做.text来获得它的文本内容(浏览器 DOM 的innerText)。

elem = content.find("p",attrs={"class":"my-id"})
text = elem.text

获取子元素

要找到一个元素(通过上述方法找到的元素)的子元素,你需要对这个元素做.children。这将给你一个可以在循环中使用的 iterable。

list(price_div.children)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

getting children of element

正如你在上面看到的,.children给了你 3 个孩子,其中第一个是除了空间什么都没有的元素。我们将创建一个函数来过滤它,只给我们适当的元素。解析后页面上的任何实际元素都由bs4.element.Tag类型表示。我们删除任何只有空格或换行符的字符串,除非它们包含在标签元素中。

**def** get_children(html_content):
    **return** [item **for** item **in** html_content.children **if** type(item)==bs4.element.Tag **or** len(str(item).replace("**\n**","").strip())>0]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Get children filter function output

解析表格

到目前为止,我们已经学会了如何从单个元素中找到我们需要的数据。但是桌子呢?每次一个单元格一个单元格地遍历表格来查找必要的信息将会非常麻烦。注意,可以使用标签创建表格,也可以使用其他标签在 html 中创建类似表格的结构,我们将学习解析这两种类型。

因此,我们将创建一个函数,帮助以 2D 数组格式从表中获取表格数据。

首先,我们创建一个表格并显示它。

html = '''
**<table>
    <tr>
        <td>Month</td>
        <td>Price</td>
    </tr>
    <tr>
        <td>July</td>
        <td>2</td>
    </tr>
    <tr>
        <td>August</td>
        <td>4</td>
    </tr>
    <tr>
        <td>September</td>
        <td>3</td>
    </tr>
    <tr>
        <td>October</td>
        <td>2</td>
    </tr>
</table>**'''HTML(html)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Table to be parsed

在实际实现之前,让我用伪代码解释一下解析过程

Step 1: Initialise final **row_data** as empty list.
Step 2: Get all rows in a list
Step 3: **For** each row in the list of rows
        - Initialise **current_row_data** as empty list
        - Get a list of cells in the row.
        - **For** each cell get its text content
          # **if** no text content present skip to next cell 
          # **else** put the text content into **current_row_data
        -** Put **current_row_data** into **row_data** Step 4: return **row_data**

以下 python 函数实现了这些步骤。我们将使用它来解析前面的表。

**def** *get_table_simple*(table,is_table_tag=**True**):
    elems = table.find_all('tr') **if** is_table_tag **else** get_children(table)
    table_data = list()
    **for** row **in** elems:
        row_data = list()
        row_elems = get_children(row)
        **for** elem **in** row_elems:
            text = elem.text.strip().replace("**\n**","")
            text = remove_multiple_spaces(text)
            **if** ***len***(text)==0:
                **continue**
            row_data.append(text)
        table_data.append(row_data)
    **return** table_data

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Using get_table_simple

让我们看看它是否能解析另一种类型的表。用

而不是标签创建的。

html = '''
<html>
<body>
<div id="table" class="FL" style="width:210px; padding-right:10px">
    <div class="PA7 brdb">
        <div class="FL gL_10 UC">MARKET CAP (Rs Cr)</div>
        <div class="FR gD_12">63,783.84</div>
        <div class="CL"></div>
    </div>
    <div class="PA7 brdb">
        <div class="FL gL_10 UC">P/E</div>
        <div class="FR gD_12">17.27</div>
        <div class="CL"></div>
    </div>
    <div class="PA7 brdb">
        <div class="FL gL_10 UC">BOOK VALUE (Rs)</div>
        <div class="FR gD_12">589.29</div>
        <div class="CL"></div>
    </div>
    <div class="PA7 brdb">
        <div class="FL gL_10 UC">DIV (%)</div>
        <div class="FR gD_12">4750.00%</div>
        <div class="CL"></div>
    </div>
    <div class="PA7 brdb">
        <div class="FL gL_10 UC">Market Lot</div>
        <div class="FR gD_12">1</div>
        <div class="CL"></div>
    </div>
    <div class="PA7 brdb">
        <div class="FL gL_10 UC">INDUSTRY P/E</div>
        <div class="FR gD_12">19.99</div>
        <div class="CL"></div>
    </div>
</div>
</body>
</html>
'''
HTML(html)content = BeautifulSoup(html,"html.parser")
get_table_simple(content.find("div",attrs={"id":"table"}),is_table_tag=**False**)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Parsed 2D table in python

如你所见,它也成功地解析了这个。

把它放在一起

让我们看看页面上我可以获取数据的地方。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

data locations

我使用 chrome 开发工具检查了这些区域,并找到了正确的 id。对于下面的两个大框,我使用了我们之前写的get_table_simple函数。分步过程如下

Step 1: Get page content using requests
Step 2: Parse page content using BeautifulSoup
Step 3: Use chrome dev tool to find id of each highlighted block
Step 4: Get Price and yearly low, high.
Step 5: Get the lower two boxes enclosing tag.
Step 6: 1st box is 1st child, parse it as table.
Step 7: 2nd box is 2nd child, parse it as table.
Step 8: Combine the tables into a single dict named **collector**.
Step 9: Populate the final dict **key_val_pairs.**

最后一个函数如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Final Scrapping Function

为了使用这个函数,我们将页面 url 传递给它。

get_scrip_info("**https://www.moneycontrol.com/india/stockpricequote/auto-2-3-wheelers/heromotocorp/HHM**")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Final Data from Scraping.

我们下一步能做什么?

  • 按 NSE 脚本名做搜索功能查找。(就像苹果是 APPL 一样,印度股票也有简称)
  • 获取过去的价格以分析回报
  • 处理 html 不正确的页面(没有语法正确的 html 的页面,浏览器会纠正它们,然后呈现,但是抓取它们会很困难)。
  • 简单的地图操作并行化,加快抓取速度。
  • 使用 dill 或 pickle 库存储抓取数据的快照。
  • 使用各种图探索股票数据,如年度回报和价格偏差。
  • 比较 Nifty 50、Nifty 100 和 Nifty Mid-cap 50 等指数的相互表现。ETF 跟踪指数,因此如果你投资 ETF,你需要了解指数的表现。
  • 以市盈率、市净率等方式选股。

我将在以后的教程中介绍这些内容。

笔记本链接供参考。

参考

[## 键盘快捷键参考 Web 开发人员工具| Google 开发人员

Chrome DevTools 中所有快捷键的参考。

developers.google.com](https://developers.google.com/web/tools/chrome-devtools/shortcuts) [## 用 Python 进行股票市场数据分析的介绍(第 1 部分)

这篇文章是过时的:这篇文章信息的更新在这里的链接!(我还打赌 WordPress.com…

ntguardian.wordpress.com](https://ntguardian.wordpress.com/2016/09/19/introduction-stock-market-data-python-1/) [## 用于股票的 Python

这是我上一篇文章的延续,这一次我们将做更多的图表来寻找多重…

mapattack.wordpress.com](https://mapattack.wordpress.com/2017/02/14/python-for-stocks-2/)

选股:傻瓜的黄金

原文:https://towardsdatascience.com/stock-picking-fools-gold-part-1-511159825dab?source=collection_archive---------15-----------------------

投资管理中的数据科学

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

首先,我想说,我不认为成为一名成功的选股人是不可能的,但历史表明这是不可能的。

数字

选股难吗,如果难为什么?这些是我希望任何从事投资管理职业的人首先要解决的问题。如果你对这个问题的框架感兴趣,在我们进入为什么它很难之前,让我们从一个事实开始:

“历史回报的分布呈现正偏态”

这只是意味着,我们将全球指数(如罗素 3000 指数)令人难以置信的表现归功于少数“极端赢家”,即少数股票。从 1926 年到 2016 年,在 25300 家公司中,只有 1092 家公司对美国股市的上涨负责。从 1980 年到 2014 年,罗素 3000 指数中有 40%的股票提供了负回报,尽管该指数回报率为 2633.12%,股票中值跑输市场-54%。然而,最有趣的是,这些股票中的~7%可能被归类为极端赢家(图 1)。应该指出的是,即使我们排除技术和生物技术以避免网络泡沫造成的扭曲,我们也观察到了同样的情况。这个观察结果,很明显是一个呈现正偏态的分布,是直观的,有两个原因;首先,多头头寸的亏损被限制在 100%,其次,上行回报是无限的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1

这对崭露头角的积极管理者有什么意义?

为了说明偏度的影响,我们从一个简单的模型开始。让我们构建一个权重相等的指数,包含五只股票,其回报曲线如图 2 所示。图 2 中的分布很明显具有我们想要的特性:正偏度。我们有一个明显的赢家,股票 E,我们的加权指数回报 18%。让我们假设一个积极的投资组合经理构建了一个包含 1 或 2 只股票的投资组合,因此,有 15 种可能的组合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2

这些投资组合有以下可能的回报:

  • 十个投资组合收益 10%;他们不会包括我们的明星,股票 e。
  • 一个包含一只股票的投资组合将获得 50%的收益,因为它只持有股票 e。
  • 两个股票投资组合将获得 30%的收益,其中一个是股票 e。

从我们的基本数字示例来看,由于忽略了股票 e,三分之二的主动管理投资组合的表现低于指数。此外,投资组合经理的中位数仅赚取 10%,平均经理的投资组合回报将等于我们的指数回报。这个基本例子暗示了以下内容:在我们考虑费用和交易成本之前,正偏度阻碍了积极经理的中位数。为什么?

如果主动型经理从指数中随机选择一部分股票,即在选股方面表现不佳,则平均水平的主动型经理的表现很可能会低于指数。

这取决于投资组合的构建

扩展这个简单的数字场景,我们使用蒙特卡罗模型试图更好地理解这一现象。让一只股票的价格,S^i,随着时间的推移,根据:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了简单起见,我们假设所有股票的波动率恒定,𝛔 = 20%。我们在这里所做的,是模拟一个股票世界,这些股票将展现出我们在历史上看到的相同特征。也就是说,我们正在创造一种分布,确保我们产生少量的极端赢家和输家。假设每只股票的起始价格为 1.00 美元,那么我在时间 T 选择的股票价格由下式给出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这个模型中,我们将假设随着时间 T = 5(年),预期指数回报率为 50%,中值回报率为 10%。因此,指数漂移为 4%,波动率为 13%。为了创建我们的投资组合,让我们运行蒙特卡罗模拟来生成 10,000 个模拟股票回报(利用等式 2)。然后,从这一组 10,000 只股票中随机抽样,我们在每个 1-20 只股票的子投资组合中创建 6000 只股票。对于给定的子投资组合规模,我们将跑赢指数的概率定义为随机抽样投资组合中超过指数回报率 50%的比例。绘制出每个子投资组合的优于和劣于表现的概率,我们得到图 3。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3

图 3(左)显示了随机选择的规模为 n 的投资组合优于或劣于基准的概率。图 3(右)显示了当我们考虑一个更极端的阈值(70%和 30%)时,优于和劣于表现的概率。很简单,与更大的投资组合相比,更大比例的高度集中的投资组合表现优异的可能性更低,表现不佳的可能性更高。

传统的主动管理者面临着一个固有的劣势。表现明显不佳的风险总是主导指数表现优于大盘的可能性。

怎样才能克服正偏?

抱怨传统的主动型经理很容易,尤其是考虑到他们的历史表现。然而,更有趣的是确定投资组合结构如何克服正偏度现象,这是我们传说中的选股者(宇宙的主人)的逆风。接下来显而易见的是,为什么量化股票产品不应被忽视。

拆除正偏度

我们看到,随着股票数量的增加,偏态效应下降。为了确定克服这种现象所需的股票数量,我们将通过观察主动经理投资组合回报的均值和中值之间的差异来量化偏度的影响。这些投资组合(代表我们假设的经理)是通过随机抽样标准普尔 500 从 1991 年到 2016 年的历史回报构建的。

我们首先假设:

  • 我们的积极型经理每年年初都会创建买入并持有的投资组合

在构建投资组合时,我们从我们的标准普尔 500 宇宙中随机挑选(不替换)给定年份的固定数量的股票。我们构建了 5000 个这样的投资组合。我们评估的投资组合规模为:15、25、35、50、75 和 150 只股票。为了简单起见,我们还做了以下假设:

  • 从我们所有的股票中选择任何一只股票的概率是相等的
  • 我们创造同等权重的投资组合

在进一步讨论之前,让我们考虑一下为什么我们关心均值——中值分布。由于偏斜度的增加,我们在蒙特卡洛模型中向投资组合经理展示了这一点,我们随机生成的投资组合偶尔会包含极端赢家。这将增加平均经理的回报,而中位数经理将保持相对不受影响。

:随着我们增加投资组合中的股票数量,我们将观察到 1991 年至 2016 年投资组合的中值和平均投资组合经理回报率之间的利差更小。

这似乎很直观,因为我们增加了投资组合中的股票数量;我们增加了纳入少数极端赢家之一的可能性。为了清晰起见,我总结了一下这个模型。从 1991 年到 2016 年,从标准普尔 500 中选择了 5000 个引导投资组合。我们对 7 个不同的投资组合进行了这样的操作,每个投资组合都有不同的规模(15 支股票到 150 支股票)。然后,我们计算 1991 年至 2016 年在 bootstrap 程序中创建的投资组合回报的均值和中值之间的平均差异。

在图 1 中,我们展示了这种差异。我们的观察提供了一些量化股票产品(或低风险主动管理风格)背后的直觉。我们看到,随着持股数量的增加,偏斜度的影响/成本显著非线性下降。在此期间,我们的结果表明,对于持有 15 只股票的投资组合经理,偏差约为 70 个基点。对于拥有约 150 只股票的投资组合,这一偏差低于 20 个基点。尽管对大量股票的影响仍然是可测量的,但我们已经大大降低了由均值-中值差测量的偏斜度相关的成本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1

为了将这一点与我们上面的发现联系起来,我们考虑了每个子投资组合的超越概率。让我们考虑一个同等权重的标准普尔 500;我们假设这一点是为了与我们同等权重的 bootstrap 投资组合进行公平比较。如果我们绘制一段时间内表现优于同等权重基准的子投资组合的平均数,我们会得到图 2。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2

我们已经证明,随着我们纳入越来越多的股票,纳入极端赢家的概率会增加,因此,中等积极投资组合经理有更大的概率跑赢他/她的基准。

那么,这与量化股票产品到底有什么关系呢?

为了确定这种现象如何影响基于因素的量化策略,我应用了之前使用的 bootstrap 投资组合模型,但是,在这种情况下,我们不会对选择的任何给定股票应用相同的概率。相反,我们执行以下操作:

  • 我们根据阿尔法分数来偏向标准普尔 500 成分的选择
  • 指定任何给定成分被选中的概率与其 alpha 分数成比例,即 alpha 分数越高,其被选中的概率越高

我们通过组合三个风险溢价的组成“z 分数”(简单地认为是一个排名)来生成“α分数”:

  • 价值:被低估或便宜的股票
  • 质量:基础资产负债表的实力和管理能力
  • 势头:表现好/差的股票继续表现好/差

具体来说,z 值越高,在给定因素下,该股票相对于同行的排名就越好。因此,通过组合这些 z 分数,我们获得了一个 alpha 分数,其中最高的 alpha 分数表示一只股票相对于它的同行来说最能获得所有三个风险溢价。

此外,在此过程中,我们通过优化器的构建纳入了小盘股偏好,这将我们的投资组合推向相等的权重,以避免股票特定的风险,因此,在此实验中,我们将对 bootstrap 投资组合进行相等的加权,以反映这一点。随机抽样(没有替换),我们为每个投资组合规模形成 1000 个投资组合。跑赢基准的投资组合比例是通过确定超额收益为正的投资组合比例来计算的。从 1991 年 12 月 31 日到 2016 年 12 月 30 日的跑赢大盘的概率中值如图 3(右)所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3

在图 3(左)中,我们看到偏斜度的“成本”大幅降低,正如我们在之前的实验中所做的那样。然而,最有趣的是,当我们应用回溯测试的 alpha 分数时,对于中等假设风险溢价的投资组合经理来说,跑赢的概率大于跑输的概率。我们观察到,在 150 只股票时,表现优异的概率达到峰值,而在 150 只股票时,表现不佳的概率最低。这并不是说 150 是黄金数;然而,它为我们提供了第一步,以确定一个更优化的投资组合构建方法来对抗正偏度。

结束语

这两篇文章旨在描述和说明历史收益的一个经常被忽视但极其重要的性质,正偏度

正偏度的含义是,整体指数回报可以由相对较少的股票驱动,这反过来会给集中投资组合的经理带来很大的阻力。

在主动与被动的辩论中,焦点通常集中在费用、技能和交易成本上。从提供的证据来看,偏态也应该包括在这些讨论中。

我们在一定程度上理解了更大投资组合的好处。量化投资产品,如增强型指数或 smart beta,都包含相对较高数量的股票,以抵消这种影响。

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

参考文献

  1. h . bessembinder(2017 年)。股票表现优于国库券吗?,https://ssrn.com/abstract=2900447.
  2. 图 1 见https://www . chase . com/content/dam/private banking/en/mobile/documents/eotm/eotm _ 2014 _ 09 _ 02 _ agonyescstasy . pdf
  3. 为了简洁起见,省略了推导和进一步的解释。如果读者想更好地理解这些价值观,请参见:https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2673262
  4. 摩根大通。(2014).关注市场,特别版:痛苦与狂喜:集中股票头寸的风险与回报。
  5. 希顿,J.B .和波尔森,尼克和维特,简·亨德里克。(2017 年 5 月 10 日)。为什么索引有效。https://ssrn.com/abstract=2673262 SSRN有售
  6. 伊肯伯里、D.L、R.L .肖克利和 K.L .沃马克。(1992).为什么积极的经理经常跑输 S&P500:规模和偏斜的影响,私人投资组合管理杂志,1(1),13-26。

Python 中的股票预测

原文:https://towardsdatascience.com/stock-prediction-in-python-b66555171a2?source=collection_archive---------0-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

学习真正的蟒蛇时制造(和失去)假财富

试图预测股市对数据科学家来说是一个诱人的前景,他们的动机与其说是为了物质利益,不如说是为了挑战。我们看到市场每天的涨跌,想象一定有我们或我们的模型可以学习的模式,以击败那些有商业学位的日内交易者。自然,当我开始使用可加模型进行时间序列预测时,我必须在股票市场的试验场用模拟资金测试该方法。不可避免的是,我加入了那些试图日复一日战胜市场却失败的人的行列。然而,在这个过程中,我学到了大量的 Python,包括面向对象编程、数据操作、建模和可视化。我也发现了为什么我们应该避免在不损失一美元的情况下玩每日股票市场(我只能说玩长线游戏)!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

One day vs 30 years: which would you rather put your money on?

当我们在任何任务中,而不仅仅是在数据科学中,没有立即获得成功时,我们有三个选择:

  1. 调整结果,让它看起来像我们成功了
  2. 隐藏结果,这样没人会注意到
  3. 展示我们所有的成果和方法,以便他人(和我们自己)可以学习如何把事情做得更好

虽然第三种选择在个人和社区层面上是最好的选择,但实施起来需要最大的勇气。当我的模型带来可观的利润时,我可以有选择地选择范围,或者我可以扔掉它,假装我从来没有花时间在它上面。这似乎太天真了!我们通过反复失败和学习来进步,而不仅仅是促进我们的成功。而且,为一个困难任务写的 Python 代码,不是白写的 Python 代码!

这篇文章记录了我用 Python 开发的“股票浏览器”工具 Stocker 的预测能力。在之前的文章中,我展示了如何使用 Stocker 进行分析,GitHub 上的完整代码可供任何想要自己使用或为项目做出贡献的人使用。

预测用储料器

Stocker 是一个用于股票探索的 Python 工具。一旦我们安装了所需的库(查看文档),我们就可以在与脚本相同的文件夹中启动一个 Jupyter 笔记本,并导入 Stocker 类:

from stocker import Stocker

现在可以在我们的会话中访问该类。我们通过向 Stocker 类传递任何有效的股票行情自动收录器来构造一个对象( bold 是输出):

amazon = Stocker('AMZN')**AMZN Stocker Initialized. Data covers 1997-05-16 to 2018-01-18.**

就像我们有 20 年的每日亚马逊股票数据要探索一样!Stocker 建立在 Quandl 金融图书馆的基础上,有 3000 多种股票可供使用。我们可以使用plot_stock方法绘制一个简单的股票历史图:

amazon.plot_stock()**Maximum Adj. Close = 1305.20 on 2018-01-12.
Minimum Adj. Close = 1.40 on 1997-05-22.
Current Adj. Close = 1293.32.**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Stocker 的分析功能可用于发现数据中的总体趋势和模式,但我们将专注于预测未来价格。Stocker 中的预测是使用加法模型做出的,该模型将时间序列视为不同时间尺度(如每日、每周和每月)上的总体趋势和季节性的组合。Stocker 使用脸书开发的 prophet 软件包进行附加建模。使用 Stocker 可以在一行中创建模型并做出预测:

# predict days into the future
model, model_data = amazon.create_prophet_model(days=90)**Predicted Price on 2018-04-18 = $1336.98**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

请注意,预测中的绿线包含一个置信区间。这代表了模型在预测中的不确定性。在这种情况下,置信区间宽度被设置为 80%,这意味着我们期望这个范围在 80%的时间内包含实际值。置信区间随着时间的推移变得越来越宽,因为估计值随着远离数据而具有更多的不确定性。任何时候我们做预测都必须包括一个置信区间。虽然大多数人倾向于想要一个关于未来的简单答案,但我们的预测必须反映出我们生活在一个不确定的世界中!

任何人都可以进行股票预测:简单地选择一个数字,这就是你的估计(我可能是错的,但我很确定这是华尔街所有人都做的)。为了让我们相信我们的模型,我们需要评估它的准确性。Stocker 中有许多评估模型准确性的方法。

评估预测

为了计算准确度,我们需要一个测试集和一个训练集。我们需要知道测试集的答案——实际的股票价格,因此我们将使用过去一年的历史数据(在我们的例子中是 2017 年)。训练时,我们不让模型看到测试集的答案,所以我们使用测试时间范围(2014-2016)之前三年的数据。监督学习的基本思想是模型从训练集中学习数据中的模式和关系,然后能够正确地为测试数据重现它们。

我们需要量化我们的准确性,因此我们使用测试集的预测和实际值,我们计算指标,包括测试和训练集的平均美元误差、我们正确预测价格变化方向的时间百分比,以及实际价格落在预测的 80%置信区间内的时间百分比。所有这些计算都是由 Stocker 以直观的方式自动完成的:

amazon.evaluate_prediction()**Prediction Range: 2017-01-18 to 2018-01-18.

Predicted price on 2018-01-17 = $814.77.
Actual price on    2018-01-17 = $1295.00.

Average Absolute Error on Training Data = $18.21.
Average Absolute Error on Testing  Data = $183.86.

When the model predicted an increase, the price increased 57.66% of the time.
When the model predicted a  decrease, the price decreased  44.64% of the time.

The actual value was within the 80% confidence interval 20.00% of the time.**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这些都是糟糕的数据!我们还不如抛硬币呢。如果我们用这笔钱来投资,我们可能会更好地购买一些明智的东西,如彩票。然而,不要放弃这个模型。我们通常认为第一个模型相当糟糕,因为我们使用的是默认设置(称为超参数)。如果我们最初的尝试不成功,我们可以调整这些旋钮来制造更好的模型。在 Prophet 模型中有许多不同的设置需要调整,其中最重要的是 changepoint prior scale,它控制模型在数据趋势变化中所占的权重。

变点优先选择

变点表示时间序列从增加到减少或从缓慢增加到快速增加(反之亦然)。它们出现在时间序列中变化率最大的地方。变点先验比例表示模型中变点的强调程度。这用于控制过拟合与欠拟合(也称为偏差与方差权衡)。

更高的先验创建的模型在变点上具有更大的权重和更灵活的拟合。这可能会导致过度拟合,因为模型会紧密地粘着训练数据,而不能推广到新的测试数据。降低先验会降低模型的灵活性,这会导致相反的问题:拟合不足。当我们的模型没有足够紧密地跟踪训练数据,并且未能学习底层模式时,就会发生这种情况。找出适当的设置来实现正确的平衡更多的是一个工程问题,而不是理论问题,在这里我们必须依靠经验结果。Stocker 类包含两种不同的方法来选择合适的先验:直观的和定量的。我们可以从图解法开始:

# changepoint priors is the list of changepoints to evaluate
amazon.changepoint_prior_analysis(changepoint_priors=[0.001, 0.05, 0.1, 0.2])

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这里,我们根据三年的数据进行训练,然后显示六个月的预测。我们在这里没有量化预测,因为我们只是试图理解变点先验的作用。这张图很好地说明了欠拟合和过拟合!最低的先验,蓝线,没有非常紧密地跟随训练数据,即黑色的观察值。它有点像是在做自己的事情,在数据的大致范围内选择一条路线。相比之下,最高的先验(黄线)尽可能接近地坚持训练观察。变点先验的默认值是 0.05,介于两个极端值之间。

还要注意先验不确定性(阴影区间)的差异。最低先验对训练数据的不确定性最大,但对测试数据的不确定性最小。相反,最高先验在训练数据上具有最小的不确定性,但是在测试数据上具有最大的不确定性。先验越高,它对训练数据就越有信心,因为它紧密地跟随每个观察。然而,当涉及到测试数据时,由于没有任何数据点来锚定,过拟合模型会丢失。由于股票有相当多的可变性,我们可能需要一个比默认模型更灵活的模型,以便该模型可以捕捉尽可能多的模式。

既然我们对先验的影响有了一个概念,我们可以使用一个训练和验证集对不同的值进行数值评估:

amazon.changepoint_prior_validation(start_date='2016-01-04', end_date='2017-01-03', changepoint_priors=[0.001, 0.05, 0.1, 0.2])**Validation Range 2016-01-04 to 2017-01-03.

  cps  train_err  train_range    test_err  test_range
0.001  44.507495   152.673436  149.443609  153.341861
0.050  11.207666    35.840138  151.735924  141.033870
0.100  10.717128    34.537544  153.260198  166.390896
0.200   9.653979    31.735506  129.227310  342.205583**

在这里,我们必须小心,我们的验证数据和我们的测试数据是不一样的。如果是这种情况,我们将为测试数据创建最佳模型,但这样我们将会过度拟合测试数据,并且我们的模型不能转化为真实世界的数据。总的来说,正如数据科学中通常所做的那样,我们使用三个不同的数据集:训练集(2013-2015),验证集(2016),测试集(2017)。

我们用四个度量标准评估了四个先验:训练误差、训练范围(置信区间)、测试误差和测试范围(置信区间),所有值都用美元表示。正如我们在图中看到的,先验越高,训练误差越低,训练数据的不确定性越低。我们还看到,更高的先验降低了我们的测试误差,支持了我们的直觉,即紧密拟合数据是股票的一个好主意。作为对测试集更高准确性的交换,随着先验的增加,我们在测试数据上获得了更大范围的不确定性。

“储料器优先验证”还显示了说明这些点的两个图表:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Training and Testing Accuracy Curves and Uncertainty for Different Changepoint Prior Scales

由于最高的先验产生最低的测试误差,我们应该尝试将先验增加得更高,看看我们是否能获得更好的性能。我们可以通过向验证方法传递额外的值来改进我们的搜索:

# test more changepoint priors on same validation range
amazon.changepoint_prior_validation(start_date='2016-01-04', end_date='2017-01-03', changepoint_priors=[0.15, 0.2, 0.25,0.4, 0.5, 0.6])

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Refined Training and Testing Curves

测试集误差在先验值为 0.5 时最小。我们将适当地设置 Stocker 对象的 changepoint prior 属性。

amazon.changepoint_prior_scale = 0.5

我们可以调整模型的其他设置,例如我们期望看到的模式,或者模型使用的数据的训练年数。寻找最佳组合只需要用许多不同的值重复上述过程。请随意尝试任何设置!

评估精炼模型

既然我们的模型已经优化,我们可以再次评估它:

amazon.evaluate_prediction()**Prediction Range: 2017-01-18 to 2018-01-18.

Predicted price on 2018-01-17 = $1164.10.
Actual price on    2018-01-17 = $1295.00.

Average Absolute Error on Training Data = $10.22.
Average Absolute Error on Testing  Data = $101.19.

When the model predicted an increase, the price increased 57.99% of the time.
When the model predicted a  decrease, the price decreased  46.25% of the time.

The actual value was within the 80% confidence interval 95.20% of the time.**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这样看起来更好!由此可见模型优化的重要性。使用默认值提供了一个合理的初步猜测,但我们需要确保我们使用的是正确的模型“设置”,就像我们试图通过调整平衡和渐变来优化立体声的声音一样(很抱歉使用了过时的参考)。

玩股票市场

做预测是一项有趣的工作,但真正有趣的是观察这些预测在实际市场中的表现。使用evaluate_prediction方法,我们可以在评估期内使用我们的模型“玩”股票市场。我们将使用我们的模型提供的策略,然后我们可以将其与在整个期间购买和持有股票的简单策略进行比较。

我们策略的规则很简单:

  1. 模型预测股票每天都会上涨,我们在当天开始时买入股票,在当天结束时卖出。当模型预测价格下降时,我们不买任何股票。
  2. 如果我们买了股票,价格在一天内上涨,我们就把涨幅乘以我们买的股票数量。
  3. 如果我们买了股票,价格下跌,我们损失的是下跌的股票数量。

我们在整个评估期间每天都播放这个,在我们的情况下是 2017 年。若要播放,请将份额数添加到方法调用中。斯托克会用数字和图表告诉我们这个策略是如何实施的:

# Going big 
amazon.evaluate_prediction(nshares=1000)**You played the stock market in AMZN from 2017-01-18 to 2018-01-18 with 1000 shares.

When the model predicted an increase, the price increased 57.99% of the time.
When the model predicted a  decrease, the price decreased  46.25% of the time.

The total profit using the Prophet model = $299580.00.
The Buy and Hold strategy profit =         $487520.00.

Thanks for playing the stock market!**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这给我们上了宝贵的一课:买入并持有!虽然按照我们的策略,我们会赚到一大笔钱,但更好的选择是进行长期投资。

我们可以尝试其他的测试期,看看我们的模型策略是否能战胜买入并持有法。我们的策略相当保守,因为当我们预测市场下跌时,我们不参与,所以当股票下跌时,我们可能期望比持有策略做得更好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Always play with fake money!

我就知道我们的模特能行!然而,我们的模型只有在我们有后知之明选择测试期时才跑赢市场。

未来预测

既然我们对自己有一个像样的模型感到满意,我们可以使用predict_future()方法进行未来预测。

amazon.predict_future(days=10)
amazon.predict_future(days=100)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Predictions for the next 10 and 100 days

该模型总体上看好亚马逊,就像大多数“专业人士”一样此外,随着我们按照预期进行评估,不确定性会越来越大。实际上,如果我们使用这个模型进行积极的交易,我们将每天训练一个新的模型,并对未来最多一天进行预测。

虽然我们可能不会从 Stocker 工具中变得富有,但好处在于开发而不是最终结果!直到我们尝试了,我们才知道我们是否能解决问题,但是尝试过但失败了总比从来没有尝试过好!对于任何有兴趣查看代码或自己使用 Stocker 的人来说,GitHub 上有

一如既往,我喜欢反馈和建设性的批评。我可以通过推特 @koehrsen_will 联系到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值