TowardsDataScience 博客中文翻译 2020(四百五十二)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

如何将屏幕日志添加到 Flask 应用程序中,并将其部署在 AWS Elastic Beanstalk 上

原文:https://towardsdatascience.com/how-to-add-on-screen-logging-to-your-flask-application-and-deploy-it-on-aws-elastic-beanstalk-aa55907730f?source=collection_archive---------8-----------------------

提示:不要忘记配置 Nginx 反向代理服务器

2019 年底 Deeplearning.ai 报道称,只有 22%使用机器学习的公司实际部署了模型。大多数公司不会超越概念证明,通常是通过 Jupyter 笔记本中的模型。因此,许多公司正在雇用机器学习工程师,他们可以建立机器学习模型,并将其投入生产。

数据科学家至少应该熟悉一些生产模型的方法。为此,数据科学家工具箱中最重要的工具是 Docker。 Docker 是一个容器服务,使您能够在本地机器之外部署模型或应用程序。例如,在亚马逊网络服务(AWS)或谷歌云平台(GCP)上运行它。有几种框架可以在这些 Docker 容器中构建应用程序并为您的模型提供服务。正如许多数据科学家已经知道 Python 一样, Flask 很容易上手。此外,Flask 为您提供了构建(简单的)用户界面的机会,因此您的用户将能够与您的模型进行交互,而不必学习如何使用命令行界面或发出 API 请求。

在本实践教程中,我将向您展示如何在 AWS Elastic Beanstalk 上的 Docker 容器中部署一个简单的 Flask 应用程序,以及如何添加日志记录功能,以便您的用户能够看到幕后发生的事情。该应用程序不会包含任何机器学习模型,但您可以轻松地自行扩展它。当我第一次部署这个解决方案时,我遇到了一些麻烦,因为我必须在 AWS 上配置(反向)代理服务器。在本教程的最后一部分,我会告诉你如何做到这一点。

基础知识

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

我们的 Flask 应用程序的文件夹结构

首先,我们设置了 Flask 应用程序的基础。它包括一个用于所有 Flask 代码的 app.py 文件,一个用于格式化索引页面结构的静态index.html文件和一个 css 样式表( custom.css)

app.py 只有 7 行代码。我们首先初始化一个 Flask 应用程序类,并定义静态和模板文件夹。然后我们定义一条路线(‘/’),并告诉应用程序它应该呈现**index.html。**最后一行告诉应用程序在端口 5000 上暴露自己。主机参数被设置为 0.0.0.0,以便稍后在 AWS Elastic Beanstalk 上部署。

HTML 和 CSS 文件也很简单,为了完整起见,在下面演示。我们用一些样式选项定义了一个 logging_window 类,稍后将包含日志记录。

我们现在可以第一次运行我们的应用程序,看看它是什么样子的。如你所见,仍然没有什么特别的。

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

应用程序第一个版本的屏幕截图

添加日志记录功能

如前所述,显示 Python 进程的日志将使应用程序的工作变得更加容易。例如,用户可以看到一个进程是停滞还是仍在运行,他们应该有耐心。

将日志添加到我们的应用程序非常简单。它需要一个助手函数 flask_logger,,(在本例中)每秒返回一个编码字符串形式的当前日期时间。此外,我们添加了一个新的路由('/log_stream '),它将使用我们的 flask_logger 函数的输出返回一个 Flask 响应类。另外,不要忘记为这个例子导入 datetime。

如果我们转到新创建的路由(将在https://localhost:5000/log _ stream 公开),,)我们现在将看到以下内容。格式不是很好,但它每秒都返回日期时间。

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

记录您的日志

由于我们现在能够每秒显示一次输出,我们实际上可以显示我们的日志。为此,我们必须改变我们的 flask_logger 函数。首先,我们必须配置我们的记录器。在这个例子中,我将使用来自 loguru 的记录器,但是你可以使用任何你喜欢的记录器。记录器将被配置为将所有日志写入静态文件夹中的 job.log 文件。 flask_logger 将被配置为每秒读取日志文件并返回日志。此外,日志文件将在 25 次迭代后被清除。

这将导致更好的格式化日志记录。请注意,loguru 记录器(在所有 python 进程中)记录的所有信息都将显示出来,因为在配置记录器后,这些信息都将写入 job.log 文件。因此,如果你在训练过程中有一行代码logger . info(’ Model is training '),它也会显示在我们的 logger 中。

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

从 job.log 文件读取的格式化日志记录

包括登录我们的索引页面

部署应用程序之前的最后一步是在我们创建的 index.html 中包含日志记录。这相当简单,但是包含了一点 JavaScript。我们创建一个函数,它在页面加载后启动,向我们的 /log_stream 路由发出 GET 请求,并将响应写入一个 id 为‘output’的 HTML 元素。整个 HTML 文件将如下所示:

如您所见,我们现在有了一个应用程序,它记录了我们所有的 python 进程,并向我们的用户显示它们。

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

我们的 index.html 文件中包含日志流

部署到弹性豆茎

现在我们可以将我们的简单应用程序部署到 AWS Elastic Beanstalk,这样任何人都可以访问它。Elastic Beanstalk 是一个所谓的“编排服务”,它不仅负责我们应用程序的部署,还负责设置服务器实例,负责负载平衡(如果多个实例已被实例化,则在您的计算资源上分配任务,以使整个过程更有效),以及监控您应用程序的健康和状态。

对于这一步,我们需要在我们的项目的根文件夹中添加两个文件:一个 Dockerfile 来封装应用程序,另一个 requirements.txt 包含应该安装在这个容器中的所有包。将 pip 冻结命令的结果复制粘贴到 requirements.txt,并按如下方式设置 Dockerfile。

现在是时候让奇迹发生了。有几种方法可以将您的应用程序部署到 AWS Elastic Beanstalk(假设您已经有一个 AWS 帐户。如果您还没有,请在 aws.amazon.com 上注册 12 个月的免费层访问。最方便的方法就是安装弹性豆茎的命令行接口。安装后,使用终端导航到项目的根文件夹。随后调用 eb initeb create 并回答提示的问题。Elastic Beanstalk 会自动识别您的项目文件夹中有一个 Dockerfile,并开始构建环境。等待几分钟(通过 AWS 的管理控制台检查进度),然后您可以通过在初始化过程中定义的 URL 访问您的应用程序。如果您通过 AWS 管理控制台导航到您的 Elastic Beanstalk 环境,也可以找到这个 URL。

Nginx

但是,如果您访问应用程序的 URL,您将会看到没有日志记录出现。25 秒后,所有日志同时出现。要解决这个问题,我们必须配置 Nginx 反向代理服务器,如果创建了弹性 Beanstalk 环境,默认情况下会实例化这个服务器。配置这个服务器听起来可能很吓人,但实际上非常简单。为了理解我们正在做的事情,我来解释一下问题从何而来。

如前所述,Nginx 反向代理服务器是在创建弹性 Beanstalk 环境时启动的。该代理服务器旨在将您的应用程序映射到您环境的负载平衡器。然而,Nginx 的一个特性是,它缓冲我们的应用程序正在生成的所有响应,直到生成日志的过程完成。因为我们想立即显示所有日志,所以我们必须配置代理服务器停止缓冲它们。

配置 Nginx 可以分两步完成:1)在项目的根文件夹中创建一个. ebextensions 文件夹,2)向该文件夹添加一个配置文件(不管它的名称是什么,只要它有. config 扩展名)。该文件的内容应该是:

现在,我们可以从项目的根文件夹中调用终端中的 eb deploy 来更新我们的应用程序,并等待部署更改。

**注意:如果您已经将项目的根文件夹初始化为 GitHub repo,请确保在部署应用程序的新版本之前提交您的更改。默认情况下,只有已经提交的变更才会通过 eb deploy 调用进行部署。您还可以运行EB deploy—staged;**然后你的 staged changed(所以你必须 git 也添加它们)也将被部署。

部署完成后,访问您的应用程序的 URL,您可以看到日志工作正常!

结论

按照这些步骤,在 AWS Elastic Beanstalk 环境中创建和部署一个具有日志功能的简单 Flask 应用程序是相当容易的。请随意扩展应用程序以服务于您的机器学习模型,并使用这种简单的方法将它们投入生产!

关于作者

Rik Kraan 是一名医学博士,在荷兰数据科学咨询公司 Vantage AI 担任数据科学家。通过rik.kraan@vantage-ai.com取得联系

如何解决过度拟合(初学者友好)

原文:https://towardsdatascience.com/how-to-address-overfitting-beginner-friendly-f26d7e7dd05?source=collection_archive---------49-----------------------

防止过度拟合的三种基本方法

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

图片由 StartupStockPhotos 来自 Pixabay

想象一下,你的老板给你一些数据,让你训练一个分类模型。你非常努力地调整你的模型,最终得到一个训练有素的模型,准确率达到 99%。你把这个模型交给你的老板,并自信地告诉他,这个模型将会运行良好,有助于促进业务。几天后,你的老板来到你面前,愤怒地向你展示了他部署模型时的可怕结果。你对正在发生的事情感到非常困惑,因为当你训练模型时,你获得了 99%的准确率。哦,天哪,那是“过度拟合”。当我们仅使用训练数据训练模型时,会发生过度拟合。它与训练数据非常吻合,但当模型应用于看不见的数据(测试数据)时,它的表现会更差。让我们向前一步,看看我们可以做些什么来处理过度拟合。

如何感知过度拟合?

你可能听过成千上万次的训练数据和测试数据。当我们训练一个模型时,我们通常将数据分成训练集和测试集。然后,我们使用训练集来训练我们的模型,并使用测试集来测试我们的模型的性能,因为我们需要一些看不见的数据来进行测试,以查看它是否能在看不见的数据上很好地工作。通常,如果训练集比测试集具有稍好的准确性,则模型是可接受的。我们会说模型训练得很好。但是,如果训练集的表现比测试集好得多,比如说训练集的准确率达到 90%,而测试集的准确率只有 60%,那么我们可以说这个模型过度拟合了。

如何解决过度拟合?

不幸的是,我们过度训练了模型,但幸运的是,我们有以下解决方案来根除它:

1。交叉验证

这是机器学习中的另一个流行术语,你们很多人可能都很熟悉。以前,我们简单地将数据集分成训练集和测试集。现在,我们将使用我们的训练设备进行锻炼。例如,我们想对训练数据进行 5 重交叉验证。首先,我们将训练数据平均分成 5 个子集。每次我们分离数据时,我们从 5 个子集中依次取出一个作为“测试数据”。

打住打住,为什么我们刚做了测试数据又要做?

交叉验证的想法是,我们用训练数据调整我们的模型,在训练模型时,我们可以使用“作弊”的测试数据来改进我们的模型,以避免过度拟合。

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

五重交叉验证。验证表明“作弊”的测试数据。保持表示测试数据。

2。特征减少

具有更多特征的模型倾向于制造更复杂的模型,并且更复杂的模型倾向于不太通用。有主成分分析(PCA)和特征选择来减少数据的特征数量。减少要素的代价是会丢失数据中的信息,但同时也会提高模型性能。

3。正规化

在知道什么是正则化之前,你需要知道什么是代价函数(又名损失函数)。成本函数是计算生成的误差模型的函数。例如,在线性回归中,我们通常使用均方误差(MSE)作为成本函数。正则化试图减少或增加模型中的权重,以使模型更简单。如果权重接近零,它只是最小化该特征的影响。然而,如果权重下降到零,那么它就完全去掉了这个特性。我们有套索、脊和弹性网来帮助我们这样做。让我们先谈谈套索和山脊,因为它们非常相似,将用于比较。我会根据它的数学公式来解释如何做套索和脊的工作。

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

套索回归和岭回归

第 1 部分是线性回归的原始成本函数。然后,在原代价函数中加入第二部分,组成新的代价函数。当我们训练一个模型时,我们的目标是试图尽可能少地最小化成本函数,因为成本函数代表误差。λ是试图惩罚权重的惩罚参数。例如,如果我选择 lambda = 10000 (lambda 现在相当大),为了使整个成本函数的值尽可能小,所有的权重都被迫变得非常小,大概是 0.0001,那么我们通过减少模型中的一些权重,成功地使我们的模型变得更简单。但是权衡就是,如果 lambda 太大,那么模型就会变得太简单。因此,我们可能最终得到一个不适合的模型,或者整个函数将过于关注惩罚项,并基于惩罚项最小化成本函数。

当我们决定λ时,我们必须小心。套索和山脊的区别在于公式不同。套索的正则化项是绝对值,但山脊是平方值。由于公式的不同,它们的结果也会略有不同。这两种结果都会使权重变小。Ridge 只会惩罚变小的权重,但不会强制它们变为零。Lasso 可以通过在权重不相关的情况下将权重设置为零来克服山脊的缺点,从而减少模型的要素数量。总之,如果模型包含许多无用的变量,而你想去掉一些,那么 Lasso 更适合正则化。如果模型中的大部分变量都是有用的,而你想保留所有的变量,那么岭更适合正则化。

如果你想深入研究数学,看看 lasso 如何将权重设置为零,而 ridge 却不能,请查看 Chetan Patil 的答案,其中有一个很好的数学示例。

Lasso 和 ridge 只在你很了解数据集的情况下才适用,但是如果我们的模型包含大量变量,而你很难知道数据中的所有变量,那该怎么办呢?

模型中的变量可能有用也可能没用。如果你对它们没有想法,那么一个有弹性的网会帮助你。一个弹性网结合了 lasso 和 ridge 的罚项,并为它们分配不同的 lambdas。然而,缺点是计算量很大。

如何用 Python 分析一个量化金融交易假设

原文:https://towardsdatascience.com/how-to-analyse-a-quantitative-finance-trading-hypothesis-in-python-152c0ee3af67?source=collection_archive---------16-----------------------

用 Python 和多边形实现的 SMA200 简单移动平均定量分析。

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

图像由 AdobeStock 授权。

在这篇文章中,我将使用 Python、Jupyter Notebook 和来自 Polygon.io 的数据来分析美国股市的 200 期移动平均线。

选择这种策略的原因是,如果有任何指标可以在交易界产生共识,那就是 200 周期简单移动平均线。人们普遍认为,该指标可以用作动态支撑位/阻力位,它可以决定市场是看涨还是看跌。我们将分析确认或否认资产或工具是否对该水平做出反应。

因此,在这篇文章中:

  1. 我将简单介绍交易策略中的均线和均值回复的概念。我会这样做,因为我知道不是所有的读者都知道均值回归策略的存在,以及均线在这些策略中的作用。
  2. 我将介绍我如何使用 Jupyter 笔记本和来自 Polygon.io 的数据分析和显示信息所需的所有步骤。
  3. 我将分享我所获得的结果——在开始写这篇文章的时候我还不知道这些结果。因此,可以发现三种情况: (a) 证明 200 周期移动平均线起作用的确凿证据, (b) 证明它不按照我们分析的路径起作用的确凿证据, © 非确凿证据。
  4. 任何获得的结果都是正确的,从这个意义上说,评估定量策略意味着肯定的确认,否定的确认和不确定的结果。这一基本方法不会改变。

虽然通常会进行更彻底和详细的研究,但基本流程仍然与这里描述的相同,因此它将有助于那些想了解简单方法来模拟交易策略和想法的人。我将使用 Python 和日常数据使文章更容易理解,但是这里描述的方法可以应用于任何语言和任何其他时间范围。

移动平均线和均值回归

移动平均线有一个合理的逻辑动机,它构成了建立均值回复策略的基本项目。交易策略可以用不同的方法和推理来构建(你甚至可以做相反的事情,比如买入突破— ,因为它们构成了启动运动的开始——或者卖出突破——因为据说大多数突破都是失败的—),这两种策略都将根据条件而有效,但无论你构建哪种策略,几乎所有的策略都可以归类为动量或均值回复。

动量策略操作市场的惯性趋势和爆发,基本概念是趋势倾向于持续,有时由反向者推动,其他由大型参与者发起的运动的强度推动,他们将保持价格上涨(反之下跌)。均值回归策略利用了这样一个事实,即极端的价格波动之后会出现修正,而且总体而言,资产或工具的价格会趋向于其平均水平。说,可以更容易地理解,移动平均线具有充当动态支撑和/或阻力的*【神奇】*属性,因为它是确定资产何时到达其平均点的可量化数字。因此,通常的概念是,在趋势期间,价格倾向于对这个平均价格做出反应,不知何故,这似乎是正确的。

也有完全基于均线的策略。这些策略在经验丰富的交易者中名声不佳,但我个人认为它们对一些专门研究这类系统的交易者来说非常有效。移动平均线策略的问题是,如果没有适当的背景和一些市场机制的解读,很容易机械地实施它们。此外,像任何高度机械化的策略一样,你需要承受巨大的损失。

当市场机制强烈看跌(或强烈看涨)时,均值回归策略也可能产生毁灭性的影响,因为你可能会面临一个点,你所有的条目都丢失了,因为势头如此强大,以至于均值回归被系统地超越。理解战略的本质,正确解读市场机制,对长期战略统计数据(提款、连续亏损等)有良好的理解。)被要求在这项业务中盈利;均值回归也不例外。

有些人也使用 200 周期的日均线作为市场整体趋势的简单指标。因此,人们常说,当资产/工具的交易价格低于该价格时,市场被认为是熊市,当交易价格高于该价格时,市场被认为是牛市。从这个意义上来说,200 周期日均线被用作市场指标或过滤器来排除买卖交易。如果价格高于 200 周期移动平均线,我们可以继续买入,如果价格低于 200 周期移动平均线,我们要么不买,要么卖出。

数据集

Polygon.io 获取数据

第一步是定义模拟条件。在这种情况下,我将分析 S&P500 指数的资产如何对 200 周期的日均线做出反应。有不同的途径来测试这一点。一种选择是直接使用 CME ES E-Mini S&P500 期货合约;另一个是分析跟踪 S&P500 的间谍 ETF,最后一个是分析符合 S&P500 的单个资产。

为了使文章更容易阅读和理解,我们将使用 ETF 方法。使用单个资产是可能的,但需要稍高的努力,CME 期货数据通常更昂贵。使用 SPDR·标准普尔 500 信托基金,通常以其纽约证券交易所的股票代号(SPY)而闻名,似乎是一篇介绍性文章的好方法。

间谍被世界各地的对冲基金广泛交易,因此,通过使用它,我们得到了一个准确反映 S&P500 美国股票指数的可交易资产。使用 SPY 的另一个相关优势是,我们不必像在未来合同中那样处理结算日期。

Polygon.io 可以直接访问美国所有主要交易所,它提供实时(通过 WebSockets)和历史(使用 API Rest)市场数据。对于 Python 来说,GIT 中有一个随时可以使用的访问客户端,它可以使用 pip 安装在您的 Python 发行版中:

pip3 install polygon-api-client

提供的 Python 客户端简化了对数据的访问,使我们能够专注于制定策略。

首先,我将检查我们想要操作的资产,在我们的案例中,正如所讨论的,我们将分析 S & P500 SPDR ETF

API 正确地记录在 polygon.io 中,但是客户端没有。然而,检查源代码非常简单,因为 API 方法和客户端之间存在一对一的对应关系,所以如果您不知道应该调用客户端对象的哪个方法,您可以直接在 git 中查找。

例如,如果您想要检索间谍的历史每日价格——正如我们在本例中打算的那样——我们将在 API 文档中查找,发现我们需要使用的 REST 方法是 Aggregates

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

Polygon.io 的 API 文档是查找需要调用的 REST 方法的地方。

REST 方法提供了检索给定时间范围内的聚合(包括每日)数据的能力。我们将使用过去 20 年的数据进行分析,这是可以检索的最大历史时期。

要调用的客户端方法是:

因此我们的第一个 Jupyter 细胞是:

从 Polygon.io 检索数据

请注意,我们正在对数据进行分割调整,这对股票非常有用。

数据时区

默认情况下,返回的时间戳似乎是复活节时间,这是您通常从数据馈送提供程序获得的时间。

总是计划并仔细检查你的时间戳和时区。时区总是容易引起麻烦,你需要确保没有出错。到目前为止,我发现的最简单的解决方案是始终使用东部时间进行模拟,即使是其他时区,如芝加哥和法兰克福仪器。

对源数据和计算机的本地时区都使用东部时间。这一规则不会对传统市场资产产生任何问题,因为夏令时发生在周六至周日的晚上,市场关闭,因此你可以只使用东部时间,忘记时区和夏令时。对于 24x7 交易加密工具,使用 GMT 可能更好。

因此,我们检查返回的第一个时间戳是(注意,我们从 1980 年就开始请求数据,用简单的英语来说就是:给我你所有的一切—):

728283600000

这对应于:

GMT Friday, 29 January 1993 05:00:00

或者

ET/EST   Friday, 29 January 1993 00:00:00 (GMT -05:00)

这意味着我们在东部时间的第一天接收数据,ETF SPY 的数据是可用的:1993 年 1 月 29 日。间谍在 1993 年 1 月 22 日开始交易,所以看起来我们得到了我们需要的一切,我们可以进一步进行。

将数据转化为可操作的东西

为了快速处理数据,我们将把数据转换成一个 NumPy 数组。我们将:

  1. 计算检索数据的长度。
  2. 为数据分配一个 7 列数组(开盘、盘高、盘低、收盘、成交量、时间戳、SMA200)。

将结果转换成 Numpy 数组

使用 NumPy 有三个原因:

  1. 它提供了向量和数组操作的函数。
  2. 它是一个 C 编译的库,将利用预编译的例程,因此,作为预编译的 C 库比常规的 Python 和 Python 数据类型更快。
  3. 它将使用针对向量运算优化的微处理器汇编指令(使用向量符号的代码通常比使用 for 循环的代码更快)。

这三个原因可以归结为一个好处:减少你需要模拟的时间。这与本例无关,但适用于大参数日内模拟。

使用 SMA200 丰富数据

下一步是为整个数据集填充一个简单的移动平均值。我们将使用 NumPy 提供的一些工具将内部操作(计算收盘价的总和)转移到 NumPy 向量操作中。我怀疑是否可以避免外部循环,但在这种情况下,这是不相关的,因为它不到 5000 次迭代。还可以使用围绕 NumPy 构建的一些辅助库来实现移动平均,这可能会提高性能,但为了使代码和解释尽可能简单,我们将只使用 for 循环。

最后一步,我准备了一个数据集,其中包含了执行分析所需的所有信息。

分析

从假设到可测量的策略

要测试的确切假设是:

  1. 当价格在均线上反弹时(穿过均线,但收盘时在均线上方),均线是动态支撑(与熊市相反)。
  2. 当价格违反移动平均线时(穿过移动平均线并在移动平均线下方收盘),移动平均线无效,因此资产/工具/市场开始了看跌行动(看跌行动可以采用相反的方式)。

为了评估价格是否反弹,我们将检查未来几天的价格是高还是低。如果所谓的反弹存在,那么在均线被穿越后的接下来几天应该会有一个看涨的趋势。我也会分析接近 SMA 但不触及它的价格。

这个标准多少有点武断,当然,还可以(也应该)进行其他一些分析。但作为起点是一样好的。这样做的目的是让分析保持简单,以显示该过程是如何完成的:

  1. 我们根据自己的交易经验/外部想法或行业知识制定直观的方法/策略。
  2. 我们将启发式想法/策略转化为可测量、可量化的策略。
  3. 我们评估这个策略。
  4. 如果结果显示这条研究路径可能会导致可操作的策略,我们会重复不同的参数或想法。

用 Python 实现策略

在这种情况下,我将生成一个类型为 bool 的 NumPy 数组— 对应于底层 C 库中的 bool 类型—。这个数组包含分析和测量假设的条件。

可以使用 Pandas 数据框(通常用于需要不同数据类型的大型策略)。在其他语言中,方法会稍有不同(在 C #中,我使用结构的链表),但是向数据集添加带有条件和中间结果的列的模式是相同的。

SMA200 成为价格反弹的动力支撑

第一个测试将评估跨越 SMA200 的价格。将评估两种不同的情况:价格收盘在移动平均线以上,价格收盘在移动平均线以下。

NumPy 数组由三列填充,如果前一天的价格高于 SMA200,第一列包含 True。当最低价低于 SMA200 但收盘价高于 SMA 200 时,第二列存储 True。当收盘价低于 SMA200 时,第三列存储 True。这三列是独立生成的。稍后将使用 NumPy 选择器合并这些条件,以分析特定的场景。

在这种情况下,为条件/结果定义了一个单独的 NumPy 数组,但是也可以有一个集成了数据和模拟结果的 Pandas 数据框架。在这种情况下,会向模拟数据中添加额外的列。

测试作为动态支撑的 SMA200

结果如下:

There are 59 times when price crosses the 200 period mean but price closes above it.
When that happens:
  21 times the next day is bullish
  38 times the next day is bearish
  35.59322033898305% of times the next day is bullish
  64.40677966101694% of times the next day is bearish

There are 39 times when price crosses the 200 period mean and price closes below it.
When that happens:
  18 times the next day is bullish
  21 times the next day is bullish
  46.15384615384615% of times the next day is bullish
  53.84615384615385% of times the next day is bearish

首先可以注意到的是,每天穿越 SMA200(前一天在 SMA200 上方时)并不常见。自 1993 年以来,这种情况只发生过 98 次。所以每年发生三次。

第二件要注意的事情是,当价格收盘低于 SMA 时,第二天的价格方向是高度不确定的(46%比 53%),所以这不会提供任何统计优势。

第三件可以注意到的事情是,当价格收盘在 SMA 上方时,第二天往往是熊市而不是牛市,因此我们没有注意到任何反弹,至少在移动平均线被穿越后的第二天。SMA200 作为动态支撑的共识——也是口头禅——对于反弹的这个具体定义来说,实际上并不成立。64%对 36%实际上是一个统计优势,在我看来,必须加以考虑。

在这里,我们可能会对不同反弹定义的进一步测试感兴趣。例如,我们可能希望分析第二天的开盘是否高于移动平均线交叉时的收盘价格(这样我们就可以买入/卖出开盘缺口)。这意味着只需将条件更改为:

# RESULT - NEXT DAY IS BULLISH (1) OR BEARISH (0) - USE OPENING GAP
if(dataset[i+1,OPEN] > dataset[i,CLOSE]):
    analysis[i,NEXT_DAY] = True

如果对该标准进行测试,我们会得到以下结果:

There are 59 times when price crosses the 200 period mean but price closes above it.
When that happens:
  30 times the next day opens higher
  29 times the next day opens lower
  50.847457627118644% of times the next day opens higher
  49.152542372881356% of times the next day opens lower

There are 39 times when price crosses the 200 period mean and price closes below it.
When that happens:
  26 times the next day opens higher
  13 times the next day opens lower
  66.66666666666666% of times the next day opens higher
  33.33333333333333% of times the next day opens lower

根据这些标准,当价格收盘在 SMA 上方时,我们对第二天的价格没有任何线索。对于价格收盘低于 SMA 的情况,我们可以确定一个统计优势:价格倾向于高开。

有了这些结果,在日线 SMA200 被突破后的第二天,但价格已经在它上方收盘,我肯定不会寻找多头头寸,这违反了共识。

我们还可以评估第二天的最高价是否高于移动平均线被穿过的当天的最高价。这些是结果:

# RESULT - NEXT DAY IS BULLISH (1) OR BEARISH (0) - USE HIGHS
    if(dataset[i+1,HIGH] > dataset[i,HIGH]):
        analysis[i,NEXT_DAY] = True
---
There are 59 times when price crosses the 200 period mean but price closes above it.
When that happens:
  28 times the next day high is higher
  31 times the next day high is not higher
  47.45762711864407% of times the next day high is higher
  52.54237288135594% of times the next day high is not higher

There are 39 times when price crosses the 200 period mean and price closes below it.
When that happens:
  6 times the next day high is higher
  33 times the next day high is not higher
  15.384615384615385% of times the next day high is higher
  84.61538461538461% of times the next day high is not higher

同样,没有确凿的证据(52%对 47%)表明价格收盘高于 SMA,并且价格收盘低于 SMA 时,价格没有超过前一天的高点(84%对 15%)。如果价格达到前一天的最大值,最新的情况是做空的好时机。然而,值得注意的是,目前的会议低和高价格是不可操作的,因为我们不知道他们提前。

务必要反复检查每个结果,以确保模型准确地代表我们的交易假设。诸如事件发生的次数(为了获得统计上有效的结果)、我们得到哪些统计值以及如何定义模型之类的附加点与找到可操作的边相关。本文未涉及的其他方面,如 MAE、利润/损失比率或参数敏感性也应包括在内。

由于结果没有证实假设,我们将质疑用于定义反弹的模型。用 SMA200 看看 S&P500 的日线图可能会有帮助:

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

S&P500 的未来(续)。带 SMA200 的日线图。

似乎很明显,SMA200 起到了动态支撑/阻力的作用。但是如果对图表进行详细分析:

  1. 价格接近均线,经常反弹,但有时甚至不触及均线。
  2. 反弹并不总是清晰的,有时它在同一个日线蜡烛线出现,有时在下一个蜡烛线出现,有时在第三个蜡烛线出现。

看过图表后,我们可以将反弹定义为第二天的低点高于价格穿过平均线时的低点。如果对这种情况进行分析:

# RESULT - NEXT DAY IS BULLISH (1) OR BEARISH (0) - USE LOWS
    if(dataset[i+1,LOW] > dataset[i,LOW]):
        analysis[i,NEXT_DAY] = True
---
There are 59 times when price crosses the 200 period mean but price closes above it.
When that happens:
  37 times the next day's low is higher than SMA day's low
  22 times the next day's low is lower than SMA day's low
  62.71186440677966% of times the next day's low is higher
  37.28813559322034% of times the next day's low is lower

There are 39 times when price crosses the 200 period mean and price closes below it.
When that happens:
  14 times the next day's low is higher than SMA day's low
  25 times the next day's low is lower than SMA day's low
  35.8974358974359% of times the next day's low is higher
  64.1025641025641% of times the next day's low is lower

使用这种新模型,当价格收盘高于平均价格时,第二天的最低价有 62%比 37%的机会高于当天的最低价。

相反,当价格收盘低于 SMA 时,64%对 35%的情况下第二天的低点会更低。

虽然这符合假设和移动平均线作为动态支撑的概念*,但重要的是要理解这一新定义并没有定义可交易的行为*,因为我们永远不会提前知道低/高价格(我们知道开盘价/收盘价,因为我们总是可以在最后或第一分钟买入/卖出开盘价或收盘价,平均来说,我们将接近开盘价/收盘价)。

我想在这里强调的想法是,虽然一切都是从一个基本和简化的模型开始的,但是迭代通常是需要的。这需要一直做下去,直到找到与我们的经验一致且可行的东西,或者直到这个想法被抛弃。

对于这种特殊情况,可以(并且可能应该)定义更复杂的模型。例如,可以定义移动平均值周围的阈值和范围。还可以定义移动平均线以下的穿透范围和移动平均线以上的反弹范围。通过这样做,可能会模拟出一个更精确的模型。有了范围和值,还可以进行参数模拟,找到可交易的策略。

按照相同的程序,但颠倒符号,SMA200 可以被分析为电阻。对于这种情况,我们得到以下结果:

There are 31 times where crosses the 200SMA but price closes below it.
When that happens:
18 times next day is bullish
13 times next day is bearish
  58.06451612903226% of times the next day is bullish
  41.935483870967744% of times the next day is bearish

There are 40 times where crosses the 200SMA and price closes above it.
When that happens:
15 times next day is bullish
25 times next day is bearish
  34.883720930232556% of times the next day is bullish
  58.139534883720934% of times the next day is bearish

可以用与前几份报告类似的方式进行分析。

作为看涨/趋势市场指标/过滤器的 SMA200

第二个分析评估 SMA200 是否能给我们一些关于市场整体趋势的信息,以及它是否能被用作排除买入或卖出交易的过滤器。

同样,需要定义一个初始的、可操作的和可测量的模型。为了简单起见,我们分析价格收盘低于 SMA200 的影响,并评估这是否会在一周和一个月后产生更低的价格。分析是完全相同的,但是这次我们创建了两个额外的列来测试 7 天和 30 天后的价格。所分析的情况是当前价格和一周/一个月远期价格都很低。

这些是结果:

There are 59 times when price crosses the 200 period mean but price closes above it.
When that happens:
  37 times the next day low is higher
  22 times the next day low is lower36 times the next week low is higher
  23 times the next week low is lower

  43 times the next month low is higher
  16 times the next month low is lower

There are 38 times when price crosses the 200 period mean and price closes below it.
When that happens:
  14 times the next day low is higher
  24 times the next day low is lower21 times the next week low is higher
  17 times the next week low is lower

  23 times the next month low is higher
  15 times the next month low is lower

从长期来看,日价格收于 SMA200 上方的情景更加乐观。43 倍对 16 倍的价格高于 SMA200 交叉时的价格。

当穿过 SMA200 且价格收于其下方时,长期来看仍是看涨的,但强度较小。一个潜在的结果是,当价格穿越并收于 SMA200 下方时,更有可能出现熊市。

不要相信任何东西,质疑一切

理解每一个结果都必须被质疑是很重要的。按照我们的例子,值得一提的是我们最后的结果“证明”了 200 周期的 SMA 起到了动态支撑的作用。当价格收盘在 SMA 之上时,这种偏差更加明显,但当价格收盘在 SMA 之下时,这种偏差也存在(一个月后价格上涨了 23 倍,而价格下跌了 15 倍)。

这是否意味着 200 SMA 均线作为动态支撑?理论上是的,但重要的是,我们分析了一个很大程度上看涨的指数(S&P500)。日线图不允许有那么多的案例和广泛的分析,因为即使像这个例子中那样用了那么多年,数据集也不大。市场机制是相关的,对于日内策略,你可能既要关注熊市,也要关注牛市。这将有助于你理解给定的分析或策略在不同条件下的表现。

另一种选择——对于这种特殊的分析——是对不那么乐观的指数进行同样的分析,比如法兰克福 DAX 指数或悉尼 ASX 指数。在任何情况下,重要的一点是,每个结果都必须进一步质疑,尤其是当我们不处理大型数据集或数据集倾向于有偏差时(如 S&P500 在分析期间表现强劲)。

附加步骤

这里的分析非常简单,主要介绍如何在 Python 中进行定量分析的一般工作流程。在现实生活的分析方面,如进一步的模型定义,风险和参数分析将需要详细涵盖。

如何分析单个时间序列变量

原文:https://towardsdatascience.com/how-to-analyse-a-single-time-series-variable-11dcca7bf16c?source=collection_archive---------19-----------------------

探索时间序列建模

用 Python 代码进行时间序列建模

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

Unsplashtangi bertin 拍摄的照片

欢迎回来!这是专栏的第二篇文章,探索用 Python 代码对时间序列数据进行分析和建模。如果你不熟悉基本的统计学概念,比如估计量、假设检验、p 值等,可以看看我之前的帖子: 用 Python 代码进行时间序列建模:基本面统计

在这篇文章中,我们将开始探索分析一个单一的时间序列变量。给定一个时间序列变量,我们应该从哪里开始分析?我们如何深入了解这些数据?老实说,我第一次被要求对一个. csv 文件格式的时间序列数据进行分析时,没有任何关于数据源和应用程序的进一步信息,我不知道从哪里开始。在这篇文章之后,希望下次你会有一些关于如何开始分析一个时间序列变量的想法。

在这里,我将分析历史苹果股票价格数据。的。csv 文件可以从雅虎财经下载。我下载了去年的 AAPL 数据,从 2019 年 3 月 13 日到 2020 年 3 月 13 日。原始数据包括每日开盘价、最高价、最低价、收盘价、调整收盘价和成交量。在这篇文章中,我将分析 AAPL 的每日收盘价。

import numpy as np
import pandas as pd
import matplotlib.pyplot as pltAAPL_price = pd.read_csv('AAPL.csv',usecols=['Date', 'Close'])
AAPL_price.set_index('Date',inplace=True,drop=True)AAPL_price.plot(legend=False)
plt.title('AAPL Daily Close Price')

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

1.滚动平均值和方差

样本参数不是恒定的,它们也是随时间变化的。单点样本均值或样本方差不会向我们透露太多信息。如果不知道样本参数的方差,我们就无法知道样本参数对总体参数的估计有多好。因此,我们不能依赖点样本均值或样本方差来估计总体参数。

我们将应用滚动窗口方法获得一年期间的多个样本均值和样本方差值,而不是从一年的 AAPL 股票价格数据计算一个点的样本均值和样本方差值。以下代码显示了如何以 10、30 和 50 的不同窗口大小显示样本均值。

import numpy as np
import pandas as pd
import matplotlib.pyplot as pltAAPL_price = pd.read_csv('AAPL.csv',usecols=['Date', 'Close'])
AAPL_price.set_index('Date',inplace=True,drop=True)ax = AAPL_price.plot(legend=False)
ax.set_title('AAPL Daily Close Price')AAPL_price.rolling(window=10).mean().plot(ax=ax)
AAPL_price.rolling(window=30).mean().plot(ax=ax)
AAPL_price.rolling(window=50).mean().plot(ax=ax)ax.legend(['Daily price', 'm=10', 'm=20', 'm=30'])

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

类似地,我们可以用不同的窗口大小来可视化样本方差。

import numpy as np
import pandas as pd
import matplotlib.pyplot as pltAAPL_price = pd.read_csv('AAPL.csv',usecols=['Date', 'Close'])
AAPL_price.set_index('Date',inplace=True,drop=True)ax = AAPL_price.plot(legend=False)
ax.set_title('AAPL Daily Close Price')AAPL_price.rolling(window=10).var().plot(ax=ax)
AAPL_price.rolling(window=30).var().plot(ax=ax)
AAPL_price.rolling(window=50).var().plot(ax=ax)ax.legend(['Daily price', 'm=10', 'm=30', 'm=50'])

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

当选择窗口大小时,总是有一个折衷。以滚动样本均值为例,我们会发现较大的窗口大小会生成更平滑的滚动样本均值图。我喜欢从过拟合和欠拟合的角度来考虑窗口大小的选择。小窗口尺寸倾向于捕捉每个时间点的更详细的信息,而大窗口尺寸包括更长时间段的更全面的信息。这样,小的窗口大小可能会造成过拟合,因为它过于关注每个时间点的移动。而大的窗口尺寸可能导致拟合不足,因为它捕捉了太多的整体趋势,但忽略了每个点的局部运动。因此,应仔细选择合适的窗口大小,以避免过度拟合和欠拟合。

2.平稳性和弱相关性

为了用普通最小二乘法(OLS)来估计生成过程,时间序列数据需要平稳和弱相关。OLS 是线性回归中常用的方法,将在本系列第 4 篇文章中详细讨论: 用 Python 代码进行时间序列建模:如何用线性回归对时间序列数据建模。

平稳性有三个要求。时间序列数据的均值和方差都是常数。此外,具有滞后(h)的两个时间点的协方差是滞后的函数,而不应依赖于时间点(t)。

弱相关性要求当滞后 h 变得无穷大时,两个时间点的相关性变为零。

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

3.自回归过程和移动平均过程

常见的时间序列过程有两种:自回归过程和移动平均过程。我们将详细讨论这两个过程。

3.1 自回归过程性质

对于自回归过程,时间序列数据依赖于自身,具有时滞。当时间序列数据仅依赖于自身且时滞为 1 时,该过程称为 AR(1)。如果时间序列数据依赖于自身,滞后时间为 N,那么这个过程称为 AR(N)。

这里以 AR(1)为例。如果满足两个要求,AR(1)过程是平稳的和弱相关的:第一个时间点的期望值为零,时间序列依赖于前一个时间点,乘法参数位于-1 和 1 之间。

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

AR(1)流程属性

在 AR(1)过程中,ρ的值决定了 AR(1)过程是否平稳。以下是ρ如何影响 AR(1)过程的简单可视化。从结果中我们可以看出,当ρ越接近 1 时,AR(1)过程穿越零线的频率越低。

import numpy as np
import matplotlib.pyplot as pltN = 10000
rho = 1sigma = np.random.normal(loc=0, scale=1, size=N)
x = [0]
for i in range(1,N):
    x.append(rho*x[-1]+sigma[i])plt.plot(x, label='rho=1')
plt.legend()
plt.xlim(0,N)

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

ρ为 0.9,0.99,1 的 AR(1)过程

3.2 移动平均过程属性

MA(1)过程是平稳的、弱相关的。

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

MA(1)流程属性

3.3 自相关函数(ACF)和偏自相关函数(PACF)

根据上述 MA(1)和 AR(1)的性质,我们可以将相关性写为:

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

通过绘制不同时滞的相关性,我们可以清楚地看到 AR(1)过程和 MA(1)过程的区别。这个相关图被称为自相关函数(ACF)。AR 过程的 ACF 图显示指数下降,并且在几个时间点之后相关性下降到几乎为零。然而,MA(1)过程的 ACF 图显示,在前两个时间点之后,相关性迅速下降到零。

import numpy as np
import matplotlib.pyplot as plt
from statsmodels.graphics.tsaplots import plot_acfN = 10000
rho = 0.5sigma = np.random.normal(loc=0, scale=1, size=N)
x = [0]
for i in range(1,N):
    x.append(rho*x[-1]+sigma[i])plot_acf(np.array(x),lags=10)

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

AR(1)过程的 ACF

import numpy as np
import matplotlib.pyplot as plt
from statsmodels.graphics.tsaplots import plot_acfN = 10000
theta = 0.5sigma = np.random.normal(loc=0, scale=1, size=N+1)
x = []
for i in range(1,N+1):
    x.append(sigma[i]+theta*sigma[i-1])plot_acf(np.array(x),lags=10)

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

MA(1)过程的 ACF

虽然 ACF 图可以用来区分 MA 和 AR 过程,但它不能很好地区分 AR(1)过程和 AR(2)过程。偏自相关函数(PACF)可以用来区分 AR(1)和 AR(2)过程。如下例所示,AR(1)过程的 PACF 显示相关性在前 2 个时间点后迅速下降到零,而 AR(2)过程的 PACF 显示相关性在前 3 个时间点后下降到零。

import numpy as np
import matplotlib.pyplot as plt
from statsmodels.graphics.tsaplots import plot_pacfN = 10000
rho = 0.5
rho2 = 0.4sigma = np.random.normal(loc=0, scale=1, size=N)
x = [0,0]
for i in range(2,N):
    x.append(rho*x[-1]+rho2*x[-2]+sigma[i])plot_pacf(np.array(x),lags=10)

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

AR(1)和 AR(2)过程的 PACF

4.整合过程的顺序

4.1 单位根和迪基-富勒检验

如上图,当ρ为 1 时,AR(1)过程是非平稳的。AR 过程中ρ=1 的情况称为单位根。下面是单位根为什么是非平稳的一个简单证明。

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

单位根是非平稳的一个简单证明

单位根可以用扩展的 Dickey-Fuller (ADF)检验。

import pandas as pd
from statsmodels.tsa.stattools import adfullerAAPL_price = pd.read_csv('AAPL.csv',usecols=['Close'])
result = adfuller(AAPL_price.iloc[:,0].values)
print(f'p value is {result[1]}')

输出:

p 值为 0.5961654850033034

由于 p 值大于 0.05 的显著性水平,我们不能拒绝时间序列数据是非平稳的零假设。因此,时间序列数据是非平稳的。

具有单位根的 AR 过程是序列相关的。然而,序列相关的时间序列数据不一定是具有单位根的 AR 过程。

4.2 整合过程的顺序

对于有单位根的 AR 过程,如果时间序列数据的一阶差分是平稳的,那么时间序列数据遵循 I(1)过程。类似地,如果需要二阶差分来获得平稳数据,则该过程遵循 I(2)过程。为了找出整合过程的顺序,需要测试一系列 ADF。

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

如何检验整合过程的顺序

摘要

在这篇文章中,我们讨论了如何分析单个时间序列变量。通常,我们可以通过绘制时间序列数据的滚动平均值和方差来开始分析。然后我们可以用 ACF 检验来看时间序列数据是遵循自回归过程还是移动平均过程。如果数据遵循自回归过程,那么我们可以使用 PACF 检验来寻找自回归过程的阶。此外,我们可以使用 Dickey-Fuller 测试来确定时间序列数据是否遵循积分过程。

在下一篇文章中,我们将继续讨论如何分析多个时间序列变量。敬请关注!

如何分析多个时间序列变量

原文:https://towardsdatascience.com/how-to-analyse-multiple-time-series-variable-5a8d3a242a2e?source=collection_archive---------33-----------------------

探索时间序列建模

用 Python 代码进行时间序列建模

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

照片由 tangi bertinUnsplash 上拍摄

欢迎回来!这是探索用 Python 代码对时间序列数据进行分析和建模的系列文章中的第 3 篇。在第一篇文章中,我们已经讨论了基础统计: 用 Python 代码进行时间序列建模:基础统计 。第二个帖子已经涵盖了单个时间序列变量的分析: 用 Python 代码进行时间序列建模:如何分析单个时间序列变量

在本帖中,我们将继续探讨如何分析多个时间序列变量。

1。滚动协方差

协方差是两个随机变量的联合线性可变性的度量。协方差本身很难解释,因为它取决于变量的大小。为了归一化协方差,通常使用相关系数。两种常用的相关系数是:皮尔逊相关系数和斯皮尔曼排名相关系数。

皮尔逊相关系数值在-1 到 1 之间,其中-1 表示强的负线性关系,0 表示没有线性关系,1 表示强的正线性关系。

斯皮尔曼的排名相关系数值也位于-1 和 1 之间。但 Spearman 的排名相关系数衡量的是两个变量之间的单调性,其中-1 表示强负单调关系,0 表示无单调关系,1 表示强正单调关系。要理解这两个变量之间的单调性,我们可以想到(y₁ -y₁)是如何随(y₂ -y₂)变化的:如果它们同向变化,那么这两个变量就是正单调的;否则,它们是负单调的。

以下模拟显示了皮尔逊相关系数和斯皮尔曼排名相关系数之间的差异。当 y1 和 y2 呈线性关系时,皮尔逊相关系数和斯皮尔曼排名相关系数都接近 1。然而,当 y1 和 y2 呈现单调关系时,皮尔逊相关系数变得小于斯皮尔曼排名相关系数。

import numpy as np
from scipy.stats import spearmanr
from scipy.stats import pearsonr
import matplotlib.pyplot as pltN=20
x = np.linspace(1,N,num=N)
y1 = x*5 + np.random.normal(0, 3, N)
y2 = np.exp(0.3*x) + np.random.normal(0, 3, N)
#y2 = y1 + np.random.normal(0, 3, N)plt.scatter(x,y1,color='r',label='y1 = x*5 + np.random.normal(0, 3, N)')
plt.scatter(x,y2,color='b',label='y2 = y1 + np.random.normal(0, 3, N)')
plt.legend(loc='upper left')
plt.xlabel('x')
plt.ylabel('y')
plt.xlim(0,N)
plt.ylim(min(min(y1),min(y2)),max(max(y1),max(y2)))

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

皮尔逊系数衡量两个变量的线性,而斯皮尔曼系数衡量两个变量的单调性

2.虚假关系与滚动协整

为了使用时间序列数据 x 对时间序列数据 y 建模,我们通常要求 x 和 y 都是平稳的 I(0)过程。如果不熟悉单个时间序列变量的平稳性检验,可以参考我之前的帖子: 用 Python 代码进行时间序列建模:如何分析单个时间序列变量

当两个时间序列变量都是非平稳的时,即使基本的生成过程没有偶然的关系,它们也可能表现出很强的相关性。这种强烈的相关性可能纯粹是由两个时间序列变量具有非常数均值这一事实引起的。这种现象被称为虚假关系。

然而,在特殊情况下,我们可以使用时间序列数据 x 对时间序列数据 y 建模,当 x 和 y 都是 I(1)过程且协整时。基本上,协整意味着 x 和 y 之间存在放大效应,在任何时间点,我们总是可以将 x 乘以同一个参数,得到一个接近 y 的值,这样,残差就是 I(0)过程。

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

x 和 y 之间的协整

使用 statsmodels 库可以很容易地检验协整。

import numpy as np
from statsmodels.tsa.stattools import cointN=20
x = np.linspace(1,N,num=N)
y1 = x*5 + np.random.normal(0, 3, N)
y2 = np.exp(0.3*x) + np.random.normal(0, 3, N)
print(f'P value is {coint(y1,y2)[1]}')

输出:

p 值为 0.9859002580259643

由于 P 值大于 0.05 的显著性水平,我们不能拒绝不存在协整的零假设。

摘要

在这篇文章中,我们讨论了如何分析多个时间序列变量的协方差和协整性。在下一篇文章中,我们将更进一步,探索如何使用线性回归来建模时间序列数据。敬请关注!

如何分析你最喜欢的音乐艺术家的歌词的情感和文字

原文:https://towardsdatascience.com/how-to-analyze-emotions-and-words-of-the-lyrics-from-your-favorite-music-artist-bbca10411283?source=collection_archive---------11-----------------------

使用 Python 对歌词进行文本和情感分析的有趣方式。

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

加布里埃尔·巴西诺在 Unsplash 上的照片

音乐是一种表达我们情感的强大语言,在很多情况下,它被用作处理生活中艰难时刻的一种疗法。音乐中使用的不同声音、节奏和效果能够在一瞬间改变我们的情绪,但当我们听音乐时,有一个成分有时会被忽略;歌曲的歌词。

歌词是强有力的文本,分享了作者创作歌曲时的想法。这就是为什么我决定分析我最喜欢的乐队之一的歌词;金属。

在他们的音乐生涯中,Metallica 的歌词在概念和想法上有了明显的变化,考虑到他们从 80 年代开始演奏音乐到现在,这个乐队是一个很好的学习选择。

在这篇文章中,我将展示和解释我如何使用单词云一个统计表单词频率比较图、 **VADER 情感分析、**和 Genius 提供的一个很酷的数据集来实现这个想法。所以没什么好说的了,让我们开始工作吧!。

必需的库:

  • 熊猫Numpy 进行数据分析。
  • 重新管柱进行数据清洗。
  • MatplotlibWordcloud 来绘制漂亮的图形。
  • 用于情感分析、标记化和词条化。
  • Sklearn 统计词频。
  • Lyricsgenius 提取歌词数据。
  • Genius 凭证访问他们的 API 和数据采集(单击此处了解更多信息)。
  • 脚本 Helpers.py 存储用于提取、清理和转换数据的函数(该脚本由我创建,位于我的 GitHub 存储库中)
#libraries used to extract, clean and manipulate the datafrom helpers import *
import pandas as pd
import numpy as np
import string#To plot the graphsfrom wordcloud import WordCloud
import matplotlib.pyplot as plt
plt.style.use('seaborn')#library used to count the frequency of wordsfrom sklearn.feature_extraction.text import CountVectorizer#To create the sentiment analysis model, tokenization and lemmatizationimport nltk
from nltk.sentiment.vader import SentimentIntensityAnalyzer
from nltk import word_tokenize
import nltk.data
nltk.download('vader_lexicon')
nltk.download('punkt')

完整的代码、脚本、笔记本和数据都在我的 Github 存储库中

(点击这里)

1.获取、清理和转换数据

1.1 创建歌词数据:

第一步是获得艺术家最流行歌曲的信息。为此,我创建了一个名为 search_data() 的函数,该函数有助于自动收集每首歌曲的属性。该函数使用库 lyricsgenius 来获取数据,并且您必须传递参数艺术家姓名要提取的最大歌曲数量,以及您的客户端访问令牌:

#Extracting the information of the 50 most popular songs of Metallica using function created on helpers scriptaccess_token = "your_genius_access_token"
df0 = search_data('Metallica',50,access_token)

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

提取金属乐队最受欢迎的 50 首歌曲(图片由作者提供)

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

提取了信息的数据框(图片由作者提供)。

您可能已经注意到,“歌词”列中有许多单词和符号对于研究并不重要,因为它们用于解释歌曲的结构,所以我使用函数 clean_data()清理了这些信息,并创建了一个新列来按十年对歌曲进行分组。这个新列将帮助我们在分析数据时有更好的理解。最后,我过滤了信息,只使用有歌词的歌曲,因为有些艺术家有器乐歌曲。

#cleaning and transforming the data using functions created on helpers scriptdf = clean_lyrics(df0,'lyric')#Create the decades columndf = create_decades(df)#Filter  data to use songs that have lyrics.df = df[df['lyric'].notnull()]#Save the data into a csv filedf.to_csv('lyrics.csv',index=False)df.head(10)

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

已提取信息的干净数据帧(图片由作者提供)。

现在我们有了一个干净的数据框架来开始创建我们的单词数据框架。您可以点击这里的访问该数据的 CSV 文件。

1.2 创建单词数据:

为了对金属乐队的歌词进行完整的分析,我想看看他们在不同年代是如何使用词汇的。所以我必须根据每首歌的歌词创建一个单词的数据框架。为了做到这一点,首先我考虑了歌词中独特的词,因为一些歌曲在合唱部分重复了相同的词。我定义了一个名为 unique 的函数来完成这个过程,这个参数对应于一个单词列表

def unique(list1):
   # intilize a null list
     unique_list = []
   # traverse for all elements
     for x in list1:
         # check if exists in unique_list or not
         if x not in unique_list:
              unique_list.append(x)
     return unique_list

然后我使用下面的代码来存储歌词的唯一单词,这个函数是上面定义的,另一个函数叫做 lyrics_to_words,你可以在 helpers 脚本中找到。我把这些信息保存在歌词数据框中一个名为单词的新栏目里。

#Stores unique words of each lyrics song into a new column called words#list used to store the wordswords = []#iterate trought each lyric and split unique words appending the result into the words listdf = df.reset_index(drop=True)for word in df['lyric'].tolist():
    words.append(unique(lyrics_to_words(word).split()))#create the new column with the information of words listsdf['words'] = words
df.head()

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

包含新单词列的数据框(图片由作者提供)

正如你可能注意到的,现在我们有一个存储歌词中每首歌的独特单词的栏目。

但这是创建我们的单词数据框架的第一步。下一步是使用这个新单词列,按十年计算一个独特的单词在歌曲歌词中使用的次数,并将所有这些结果存储到一个新的 5 列数据框中,一列用于单词,其他列用于按十年计算的出现频率。

考虑根据每个数据删除自己的停用词很重要,以防 clean 函数不能删除所有停用词。停用词是自然语言中意义不大的词,如“and”、“the”、“a”、“an”以及类似的词。

#Create a new dataframe of all the  words used in lyrics and its decades#list used to store the informationset_words = []
set_decades = []#Iterate trought each word and decade and stores them into the new listsfor i in df.index:
   for word in df['words'].iloc[i]:
       set_words.append(word)
       set_decades.append(df['decade'].iloc[i])#create the new data frame  with the information of words and decade listswords_df = pd.DataFrame({'words':set_words,'decade':set_decades})#Defined  your own Stopwords in case the clean data function does not remove all of themstop_words =
['verse','im','get','1000','58','60','80','youre','youve',
  'guitar','solo','instrumental','intro','pre',"3"]# count the frequency of each word that aren't on the stop_words listscv = CountVectorizer(stop_words=stop_words)#Create a dataframe called data_cv to store the the number of times the word was used in  a lyric based their decadestext_cv = 
cv.fit_transform(words_df['words'].iloc[:])data_cv = pd.DataFrame(text_cv.toarray(),columns=cv.get_feature_names())
data_cv['decade'] = words_df['decade']#created a dataframe that Sums the ocurrence frequency of each word and group the result by decadevect_words = data_cv.groupby('decade').sum().Tvect_words = vect_words.reset_index(level=0).rename(columns ={'index':'words'})vect_words = vect_words.rename_axis(columns='')#Save the data into a csv filevect_words.to_csv('words.csv',index=False)#change the order of columns to order from the oldest to actual decadevect_words = vect_words[['words','80s','90s','00s','10s']]
vect_words

点击这里的可以进入查看代码。

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

金属乐队歌词的数据框架(图片由作者提供)。

这个数据框很有趣也很有用,因为它向我们展示了 Metallica 根据歌曲发行的年代在歌词中使用一个词的次数。例如,年轻这个词在 20 世纪 80 年代的一首歌中出现,在 20 世纪 90 年代的两首歌中出现,在 21 世纪初和 2010 年代出现 0 次。

您可以点击这里访问该数据的 CSV 文件。

2.享受分析数据的乐趣

为了开始分析 Metallica 创作他们的歌词所用的词,我想回答我脑海中的许多问题。这些问题是:

  • 十年来,他们的歌词中最常用的词是什么?
  • 每首歌用了多少词?
  • decade 使用的总词和独特词有哪些?
  • 一个特定十年中使用频率最高的单词与其他十年相比如何?

2.1 按十年划分的词云:

谷歌引用的词云是“由特定文本或主题中使用的词组成的图像,其中每个词的大小表明其频率或重要性”。为此,单词 Cloud 按十年分组,将向我们展示在不同的十年中金属乐队的歌词中使用最频繁的单词。

我使用 Matplotlib 和 Wordcloud 库创建了这个图表,其中有一个函数,您必须根据您想要绘制的年代传递数据框、数字的行数和列数。在我的例子中,我有 4 个十年(80 年代,90 年代,00 年代,10 年代),我想要 2x2 格式的图表。

def plot_wordcloud(df,row,col):
     wc = WordCloud(background_color="white",colormap="Dark2",
                     max_font_size=100,random_state=15)
     fig = plt.figure(figsize=(20,10))

     for index, value in enumerate(df.columns[1:]):
       top_dict = dict(zip(df['words'].tolist(),df[value].tolist()))
       wc.generate_from_frequencies(top_dict)
       plt.subplot(row,col,index+1)
       plt.imshow(wc,interpolation="bilinear")
       plt.axis("off")
       plt.title(f"{value}",fontsize=15)plt.subplots_adjust(wspace=0.1, hspace=0.1)
    plt.show()#Plot the word cloud
plot_wordcloud(vect_words,2,2)

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

按十年列出的最常用单词的单词云(图片由作者提供)

观察在金属乐队音乐生涯的不同时期使用的词汇之间的差异是很酷的。在 80 年代,单词集中在与生与死有关的概念上,而在 10 年代,单词则是关于感情的更深刻的概念。

2.2 文字统计表:

我还定义了一个函数来计算几十年中不同时期的字数统计。您必须将歌词的数据帧和单词的数据帧作为参数传递。我使用了以下代码来创建该表:

def words_stats(df,main_df):
    unique_words = []
    total_words = []
    total_news = []
    years = []

    for value in df.columns[1:]:
        unique_words.append(np.count_nonzero(df[value]))
        total_words.append(sum(df[value]))
        years.append(str(value))
        total_news.append(main_df['decade'    [main_df['decade']==value].count())data = pd.DataFrame({'decade':years,
                          'unique words':unique_words,
                          'total words':total_words,
                          'total songs':total_news})data['words per songs'] = 
         round(data['total words'] / data['total songs'],0)data['words per songs'] = 
         data['words per songs'].astype('int')return data#display the table of statistics
words_stats(vect_words,df)

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

十年词汇统计表(图片由作者提供)。

有了这个表格,我们可以显示很多关于 Metallica 的歌曲和歌词的信息。例如,80 年代有更多的词和歌曲,这是因为最著名的歌曲都是在这十年间发行的。2000 年代每首歌的字数少于其他几十年,也许我们可以推断 2000 年代的歌曲比其他几十年的时间短。

2.3 几十年间一个词出现频率的比较:

另一个可以帮助我们理解这一数据的很酷的分析是看一看十年中使用最频繁的单词与其他十年中相同单词的频率相比的趋势。

使用下面的函数,您可以创建一个线形图,以查看一组常用词在特定十年中的趋势。例如,如果我想将 20 世纪 80 年代的 10 个最常见的单词与其他几十年进行比较,我必须将这些信息和单词的数据帧作为参数传递给函数:

def plot_freq_words(df,decade,n_words):
    top_words_2020 =   
        df.sort_values([decade],ascending=False).head(n_words)fig = plt.figure(figsize=(15,8))plt.plot(top_words_2020['words'],top_words_2020[df.columns[1]])
    plt.plot(top_words_2020['words'],top_words_2020[df.columns[2]])
    plt.plot(top_words_2020['words'],top_words_2020[df.columns[3]])
    plt.plot(top_words_2020['words'],top_words_2020[df.columns[4]])plt.legend(df.columns[1:].tolist())
    plt.title(f"Most frequent words in {decade} compared with other   decades",fontsize=14)
    plt.xlabel(f'Most Frequent Words of {decade}',fontsize=12)
    plt.ylabel('Frecuency',fontsize=12)
    plt.xticks(fontsize=12,rotation=20)
    plt.yticks(fontsize=12)
    plt.show()#Ploting the comparision plot
plot_freq_words(vect_words,'80s',10)

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

比较不同年代单词出现频率的图表

你可能会注意到,在 20 世纪 80 年代,金属乐队歌词中最常用的两个词是“生”和“死”,两个词都出现了 12 次。但是在 20 世纪 90 年代,只有 6 首歌词使用了“公正的生活”,而在接下来的几十年里,只有 1 首歌词使用了“死亡”。

3.歌曲歌词的情感分析

NLKT Python 库的【VADER】(价感知词典和情感推理机)是一个词库和基于规则的情感分析工具 VADER 使用了一个情感词典的组合是一个词汇特征(例如,单词)的列表,这些词汇特征通常根据它们的语义取向被标记为正面或负面。VADER 模型使用 4 种不同的情感指标。

  • 阴性中性阳性度量表示属于这些类别的文本比例。
  • 复合指标计算所有词汇等级的总和,它是介于-1(消极性的最大限度)和 1(积极性的最大限度)之间的标准化值。

如果你想了解更多关于 VADER 指标的信息,请点击这里

我使用下面的代码来计算数据帧的歌曲歌词的 4 个度量。

#Create lists to store the different scores for each wordnegative = []
neutral = []
positive = []
compound = []#Initialize the modelsid = SentimentIntensityAnalyzer()#Iterate for each row of lyrics and append the scoresfor i in df.index:
    scores = sid.polarity_scores(df['lyric'].iloc[i])
    negative.append(scores['neg'])
    neutral.append(scores['neu'])
    positive.append(scores['pos'])
    compound.append(scores['compound'])#Create 4 columns to the main data frame  for each scoredf['negative'] = negative
df['neutral'] = neutral
df['positive'] = positive
df['compound'] = compounddf.head()

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

带有情感指标的歌词数据框(图片由作者提供)

现在,一个很好的方法是使用 Matplotlib 库在散点图上绘制歌曲及其各自的情感指标。在这种情况下,我绘制了每首歌词按十年分组的负得分和正得分。

for name, group in df.groupby('decade'):
    plt.scatter(group['positive'],group['negative'],label=name)
    plt.legend(fontsize=10)plt.xlim([-0.05,0.7])
plt.ylim([-0.05,0.7])
plt.title("Lyrics Sentiments by Decade")
plt.xlabel('Positive Valence')
plt.ylabel('Negative  Valence')
plt.show()

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

歌词正面得分和负面得分散点图(图片由作者提供)

分析这个情节,我可以推断出金属乐队的歌词倾向于更多的负价,因此导致产生更多的负面情绪。

我也想分析这种情绪,但是使用十年分数的平均值。所以我只是把有这个结果的主要数据框架按十年分组。

means_df = df.groupby(['decade']).mean()
means_df

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

按十年分组的歌词数据帧的含义(图片由作者提供)

for name, group in means_df.groupby('decade'):
    plt.scatter(group['positive'],group['negative'],label=name)
    plt.legend()plt.xlim([-0.05,0.7])
plt.ylim([-0.05,0.7])
plt.title("Lyrics Sentiments by Decade")
plt.xlabel('Positive Valence')
plt.ylabel('Negative  Valence')
plt.show()

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

十年平均值的正分数散点图和负分数散点图(图片由作者提供)

我意识到金属乐队 90 年代的歌词比其他几十年更倾向于正面。考虑到主流音乐中最著名的金属乐队是在 90 年代,这真的很有趣。

3.结果和结论的解释

  • 金属乐队的大多数著名歌曲都是在 20 世纪 80 年代发行的。
  • 金属乐队歌曲的第一句歌词使用了与死亡、活在地狱和杀戮主题相关的词,多年来,这句歌词被改为使用恐惧、痛苦和崛起等词来表达最深刻的人类情感。
  • 20 世纪 90 年代发行的歌曲的歌词比其他几十年更有积极的感觉。
  • 在 2010 年代,金属乐队用了 323 个独特的词创作了 6 首歌曲的歌词。
  • 每首歌词的字数在 50 到 70 之间。

总结这篇文章,我们学习了如何使用一种新的技术来分析应用于音乐的文字和文本情感。与过去的几十年相比,生活在这个现代的十年里的人们所拥有的优势是惊人的。我的意思是,在你舒适的家中使用简单的技术来创造惊人的研究和项目,它允许我们随着社会不断发展,利用技术来实现我们的目标,并享受做有趣事情的时间。

这篇文章将有第二部分,我将试着找到金属乐队在他们的歌曲歌词中暴露的主要话题、概念和想法。

我的其他文章:

[## 从电脑的音乐文件夹中自动播放 Spotify 上的播放列表。

将音乐文件导出到 Spotify 播放列表的有趣方式。

medium.com](https://medium.com/datadriveninvestor/automating-playlists-on-spotify-from-the-music-folders-of-your-computer-c79060eadab2) [## 用深度学习预测一首歌的音乐情绪。

一个很酷的方法来预测音乐曲目的情绪与神经网络模型使用 Keras 和 Tensorflow 库对…

towardsdatascience.com](/predicting-the-music-mood-of-a-song-with-deep-learning-c3ac2b45229e) [## 使用 Python 和 K-Means 对音乐进行聚类,在 Spotify 上创建您的个人播放列表。

在 Spotify 播放列表中按相似性对歌曲进行分组的简单方法。

towardsdatascience.com](/clustering-music-to-create-your-personal-playlists-on-spotify-using-python-and-k-means-a39c4158589a) [## 一个在网络上工作的总线和分析的交互格式。

像自动化和可视化一样,这也是 Python 和 Power Bi 的主要用途。

medium.com](https://medium.com/@cristobal.veas.ch/una-forma-interactiva-para-buscar-y-analizar-ofertas-de-trabajo-en-la-web-ef9327b0a8d3) [## 一个友好的公共汽车和分析人员在网上到达部门。

由于自动化的原因,很多时候需要使用 Python 和 Power Bi。

medium.com](https://medium.com/@cristobal.veas.ch/una-forma-genial-para-buscar-y-analizar-arriendos-de-departamentos-en-la-web-e20727390a8c) [## 你用电脑看报纸的新闻

一个有趣的形式分析了帕拉布拉斯和他的感觉,这是一个关于蟒蛇皮的新闻…

medium.com](https://medium.com/@cristobal.veas.ch/c%C3%B3mo-hacer-reflexionar-a-tu-computador-con-las-noticias-del-pa%C3%ADs-dc14d2fc0a67)

参考资料:

如何使用 Plotly Express 在 Mapbox 上制作散点图动画?

原文:https://towardsdatascience.com/how-to-animate-scatterplots-on-mapbox-using-plotly-express-3bb49fe6a5d?source=collection_archive---------23-----------------------

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

COVID19 在全球的传播。乌萨马·汗Github 上生成的图像

Plotly Express 是一个数据可视化库,允许我们快速有效地可视化小数据。在本教程中,我们将学习如何使用 Plotly express 内置的散点图框功能制作动画。

散点图框需要以下参数:

  1. df ,这是你熊猫的数据框。
  2. lat 是包含纬度坐标的列的名称。
  3. lon 是包含经度坐标的列的名称。
  4. 颜色是为单个散射点着色的列的名称。
  5. 大小是决定个体散点大小的柱的名称。

虽然上述论点是基本的,我们可以通过它们创建一个散点图,但这不是全部。Plotly Express 散点图框功能提供了大量的功能,可以在文档中找到这里

有了这些理解,我们现在可以在 Mapbox 上创建一个简单的散点图,稍后可以转换成动画。但在此之前,我们必须看一看并了解我们的数据集。

对于这个例子,我们将使用新冠肺炎数据集,可以在这里找到。它被进一步处理。有关数据预处理的更多信息,请查看这里。

如下面的数据集所示,第一列显示了国家的名称,接下来的两列显示了国家的纬度和经度坐标。“洲”列显示了各个国家的洲。“日期”列显示国家/地区数据的上次更新日期。“已确认”栏代表已确认的 COVID 病例,“死亡”栏代表因 COVID 而死亡的人数,“恢复”栏代表治愈该病毒的人数。

特定国家显示的所有数据代表自记录首例病例以来的累计总数,而非每日增加数。

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

COVID 19 的数据集。乌萨马·汗Github 上生成的图像

了解数据集后,现在是创建散点图的时候了。我们将为已确认的 COVID 病例创建散点图,并将其绘制在地图框上。让我们看看我们如何能做它。

现在,由于我们要可视化已确认的病例,“已确认”列将被转发到 size 和 color 参数。请看看下面的代码:

# Necessary Importing
import pandas as pd
import plotly.express as px#Importing dataset as pandas dataframe
datasets = pd.read_csv('covid-dataset.csv')# Creating and visualizing a scatter plot on Mapbox
fig = px.scatter_mapbox(datasets, lat="Lat", lon="Long",
                  color="Confirmed", size="Confirmed",
                  color_continuous_scale=px.colors.cyclical.IceFire,
                  size_max=70, zoom=0.75, hover_name='Country', 
                  hover_data = ['Confirmed', 'Deaths', 'Recovery'], 
                  title = 'Accumulative COVID-19 Confirmed Cases
                  till 17 June, 2020')
fig.show()

从上面的代码中我们可以看到,这里很少有未知的参数。我们一个一个来破。

  1. “数据集”只是传递到函数中的熊猫数据框的名称。
  2. “lat”和“long”是数据框中带有经纬度坐标的列的名称。
  3. 因为我们对可视化确诊病例感兴趣,所以我们将“确诊”列转发给了 size 和 color 参数。
  4. “color_continuous_scale”询问我们将用于可视化数据的配色方案。可用的选项很少,请参考上面的文档链接。
  5. “size_max”要求地图上绘制的气泡的最大尺寸。而“缩放”是显示地图的默认缩放值。您可以随意使用这两个值,并根据自己的喜好进行优化。
  6. “hover_name”和“hover_data”要求当光标悬停在地图上的特定气泡上时显示列。
  7. 顾名思义,“标题”指定地图的标题。

现在明白了这一点,让我们来看看上面代码片段的输出。

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

Covid19 全球确诊病例。由乌萨马·汗Github 上生成的图像

哇,看起来真棒。您也可以为死亡和恢复列生成类似的映射。你自己试试。

完成后,下一个任务是将数据框中的“日期”列制作成动画,并查看自 1 月份病毒爆发以来确诊病例是如何累积的。

之前使用的数据集被切片以可视化最大记录日期(2020 年 6 月 17 日)的数据。为了创建一个动画,我们需要移除切片器并再次理解我们的数据集。让我们来看看。

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

COVID19 的完整数据集。由乌萨马·汗Github 上生成的图像

该数据集包含 2020 年 1 月 22 日至 2020 年 6 月 17 日记录的冠状病毒确诊病例、死亡和康复。数据库中所有其余的列都与前面解释的相同。

现在,我们需要在散点图上显示日期,并可视化 COVID19 确诊病例如何在世界各地传播。为此,我们需要给 scatter_mapbox 函数一些额外的参数。

fig = px.scatter_mapbox(datas, lat="Lat", lon="Long",
            animation_frame = 'Date', animation_group = 'Country', 
            color="Confirmed", size="Confirmed",
            color_continuous_scale=px.colors.cyclical.IceFire, 
            size_max=70, zoom=0.75, hover_name='Country', 
            hover_data = ['Confirmed', 'Deaths', 'Recovery'], 
            title = 'Visualizing spread of COVID from 22/1/2020 to
            17/6/2020')fig.show()

从上面的代码可以看出,为了创建动画,scatter_mapbox 函数被赋予了两个额外的参数。这些参数是“动画 _ 帧”和“动画 _ 组”。“animation_frame”要求包含要制作动画的时间序列信息的列。完成这些后,我们最终生成了下面的动画:

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

Covid19 的全球传播。乌萨马·汗Github 上生成的图像

本教程到此为止,请看一下这个项目的 GitHub,这里

如何回答一个编码面试问题

原文:https://towardsdatascience.com/how-to-answer-a-coding-interview-question-f3e705bb9fcd?source=collection_archive---------10-----------------------

有效处理编码问题的步骤。

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

图片来自 unsplash.com @丹尼尔·麦卡洛

这篇博客是我的“大型科技公司黑客技术面试 15 天备忘单”的一部分。在这篇博客中,我们关注一步一步解决编码面试问题的方法。

编码面试部分旨在揭示你如何思考、交流和解决问题。因此,对一个问题给出正确和完美的解决方案并不能保证一个积极的结果,人们会根据你如何得出答案来评判你。以下是我通常采取的步骤,这些步骤不仅给了自己正确回答问题的最好机会,也让面试官对我如何处理这个问题有了一个体面的感觉。

第 0 步:面试前

准备一个简短的自我介绍

几乎在每次编码面试中,你都会被要求做一个简短的自我介绍。这是留下第一印象的关键部分,也是唯一可以预测的问题。因此,请按照以下格式准备一份简明扼要的介绍(不超过一两分钟):

  • 关于你的名字和一般背景的一句话。
  • 关于你大学毕业后的职业经历的几句话。如果你是应届毕业生,专注于你的实习和学校项目。否则,选择一个或两个具有挑战性的项目或与你申请的职位相关的技能。
  • 以陈述结束,说明你为什么寻找新的工作机会,以及你为什么对你申请的职位感兴趣。
“Hi, I’m Dinh Tuan and I’m a backend engineer with over six years of experience specialising in designing and implementing high scale and high availability backend system. I started my career in SEA Group, one of the biggest tech company in South East Asia. During 5 years in SEA, I led the backend team implementing a gaming platform which serves 3 millions concurrent users and 500 thousands request per second at the peak time. I also helped to grow a team of 30 engineers in Vietnam after they acquired a Vietnamese startup in food delivery services. In early 2019, I joined Datarobot, a unicorn in Boston, United States. I work under code and architecture team to design and implement the feature to support multiple external compute clusters (including both Kubernetes and Hadoop).I’m interested in the software engineer position in Facebook because I would like to grow my technical skills further in a large scale social platform.”

准备一些在面试结束时要问的问题。

面试结束时,你通常有机会提问。跳过这一部分意味着错过了了解工作性质和组织文化的机会。此外,一个好的问题还可以展示你的沟通技巧,展示你对这个职位的兴趣,并给人留下好印象。我最喜欢的一些问题是:

1\. What technology is the company/ your team currently using?
2\. What is your favourite thing about working for the company?
3\. How much say do developers have regarding the products?
4\. What qualities make a software engineer excel at this company?
5\. How flexible are the working hours?
6\. How will role performance be measured? What metric will role performance be measured with?
7\. How has your role changed since joining the company?
8\. What are the most challenging aspects of the job?
9\. What is the current team composition like?
10\. What resources does the company have for new hires to study its product and processes?

**第一步:**收到问题后

  • 请仔细阅读问题。如果问题没有写下来,一定要重复你从面试官那里听到的内容。
  • 完成给出的例子或想出一些例子。这不仅有助于确保你的理解,还能让你找到模式和概括来回答问题。
  • 澄清您所做的任何假设,例如输入格式或范围。
  • 想出最简单最明显的解决方案。
  • 寻找改进,尝试提出更好的解决方案。
  • 大声说出你的想法,和你的面试官谈谈你的想法。这能让他们参与进来,让他们理解你的思维过程,并给他们一个机会在你浪费太多时间之前给你指出正确的方向或阻止你。
  • 如果你遇到困难,一定要寻求提示。
  • 如果你的解决方案不那么琐碎,请用一些例子来说明。如有必要,您还可以使用白板来完成您的解决方案。
  • 陈述并解释你的方法的时间和空间复杂性。
  • 不要直接开始写代码。只有在你的面试官明白你要做什么并给你开绿灯后,你才应该开始编程。
  • 不要保持沉默太久。如果你被卡住了,试着说出让你困惑的地方。如果你需要安静思考,就告诉面试官(但不要超过一分钟)。
  • 不要忽视来自面试官的信息。每一块都很重要。
  • 当你的面试官在说话时,不要打断他们。
  • 不要灰心丧气。深呼吸,通过遍历更多的样本,思考不同的算法和数据结构,不断尝试。
  • 不要试图虚张声势。如果面试暗示了你不熟悉的东西,就承认它,继续前进。

步骤 2:编码期间

  • 请解释一下你正在写什么或打什么。
  • 遵循好的编码风格(比如使用描述性的变量名)并且组织好你的代码(如果需要的话,使用函数和类)。
  • 请说出你对你所使用的算法、数据结构或内置函数的理解。
  • 是否请求允许使用内置函数或跳过一些输入检查。如果有足够的时间,它们可能允许您摆脱一些琐碎功能的实现,或者稍后再回来。
  • 如果要求你在白板上书写,请注意你的手写。你需要确保它的可读性和良好的组织性(尤其是单词和行之间的空间)。
  • 不要写伪代码。虽然您不需要太担心语法,但是您应该交付无 bug 的生产就绪代码。
  • 不要保持沉默太久。

步骤 3:编码后

  • 考虑如何测试你的代码,列出测试用例。
  • 和你的面试官一起测试你的代码。
  • 用测试用例扫描你的代码时,修复任何出现的错误。
  • 务必寻找可以重构的地方。
  • 评估你写的代码的时间复杂度和空间复杂度。
  • 如果有更好的解决方案,再给点时间,你有什么好的建议吗?
  • 不要和面试官争论。因为面试官对这个问题很熟悉,所以他们不太可能错。接受他们的反馈并仔细考虑。

第四步:结束面试

  • 如果面试给你机会,一定要问一些问题来了解工作和公司文化。
  • 感谢面试官抽出时间。
  • 不要问太多问题,尽量按时结束。
  • 不要询问你的面试表现。
  • 编码问题已经结束,不要再继续讨论了。

参考文献:

  1. 破解编码面试
  2. 技术面试手册

如何将您的工作表附加到云上

原文:https://towardsdatascience.com/how-to-append-your-sheets-on-the-cloud-3cd9e0a2cf39?source=collection_archive---------49-----------------------

在 Colab 中运行 python 笔记本可以显著减轻您的日常任务。以下是如何用 6 个简单的步骤完成其中一项任务。

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

Unsplash 上的 La-Rel Easter 拍摄的照片

谷歌为你提供了一些免费的 CPU,甚至一个小规模的 GPU,非常适合通过其托管的 Jupyter 笔记本应用程序 Google Colab 运行简单的任务。

以前被称为谷歌实验室,现在谷歌实验室不需要设置,如果你有一个谷歌帐户,访问它就像访问的网站一样容易。

一旦你进入,你只需要点击“新笔记本”按钮。然后,您将拥有自己的托管笔记本,可按如下方式使用:

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

截图来自 Google Colab

你的第一个笔记本会在你的 Google Drive 中自动创建一个名为“Colab Notebooks”的文件夹来自动存储你的所有工作。

在对该工具进行简要说明之后,让我们深入研究我们的代码,将位于您的驱动器中的工作表添加到新的 Google 工作表中。整个过程由 6 个简单的步骤组成。

第 1 步-验证 Google 帐户,以便能够在您的 Google 表单中进行更改

为了阅读和修改您的 Google Sheets 文档,您首先需要验证 Google Colab 以访问您的 Google Drive 文档。尽管这两个应用都属于谷歌,但它们之间的访问需要你方的独家认证。

如果您在笔记本的第一个单元格中运行下面的代码,您就可以对 Google Drive 文档进行任何更改。

参见我的 Github 页面中的完整代码

运行该单元将生成一个链接并询问授权码。

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

截图来自 Google Colab

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

截图来自谷歌

单击链接完成登录过程。

如左图所示,这种认证将允许您查看、编辑、创建和编辑 Google Drive 中的所有文件。所以一定要仔细检查你从笔记本上运行的任何代码,以避免不可逆转的错误。

允许在文档中进行更改。

一旦允许,系统将生成一个代码。复制代码并将其粘贴到 Colab 中,以完成身份验证过程。

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

截图来自谷歌

步骤 2 —从 Google Sheet URLs 中读取文件,并将数据放入 pandas 数据框架中

第二步是从 Colab 笔记本中读取你的 Google Drive 中的文件。

这一步包括打开 Google Sheets 来读取数据,选择数据所在的工作表,获取数据,最后将数据放入 pandas dataframe。

参见我的 Github 页面中的完整代码

这里需要注意的是,链接不必是公开的,因为所有的权限都被授予了,所以你可以从你的浏览器中复制你的 Google Sheets 文档的链接。

步骤 3-设置列,并在数据框中指定数据范围

将数据放入 dataframe 后,接下来的步骤是设置列和指定数据范围。

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

截图来自谷歌 Colab

如果您的列是数据的一部分,并且没有位于图像上当前为“0”和“1”的列部分,则需要使用以下代码设置列并指定数据范围。如果已经有了列名,可以跳过这一步。

完整代码见我的 Github 页面

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

截图来自 Google Colab

当执行完成时,可以在这里看到更新的 df1 数据帧。

步骤 4 —从不同的数据帧中选择相同的列名,以便以后追加

append 函数的一个关键点是所选工作表中的列数应该匹配。否则,append 命令将在下一步中生成错误。因此,您需要提前选择具有相同名称的列,以便将正确的值附加到彼此。

在下面的例子中,我选择了存在于两个工作表中的“销售”和“品牌”列。您可以对它们进行重命名,或者添加任意多的列,只要所有这些都可以在两个文件中找到。

参见我的 Github 页面中的完整代码

注意列名前后的空格。

#步骤 5 —追加数据帧

数据集终于可以追加了。因此,我们只需要运行我们的单行代码来完成 append 函数。

参见我的 Github 页面中的完整代码

在这个例子中,我把重点放在了 append 上,但是根据您的需要,您也可以使用“merge”、“join”或“concatenate”函数。你可以查看熊猫文档来发现这些其他功能的细节。

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

截图来自谷歌 Colab

在将新数据写入 Google Sheets 之前,通过运行“df”检查追加是否成功完成很重要。查看最新版本的 dataframe。

第 6 步——打开您想要写入新数据的 Google Sheets 文件,然后使用 set 函数插入数据

最后但同样重要的是,您需要打开一个新的 Google Sheet 文档,选择相关的工作表,用“set_with_dataframe”函数将新的数据帧写入其中。

完整代码见我的 Github 页面

恭喜你。您现在已经添加了 Google 表单,甚至没有将它们下载到您的计算机上。这并不意味着你不能在你的本地计算机上做同样的事情,但是因为这是一个更普遍的做法,所以我没有在这篇文章中讨论它。

此外,这篇文章的目的不仅是向您展示附加表,而且让您意识到您在云中有一种免费的处理能力,称为 Google Colab,并向您展示如何与您的 Google Drive 中的文件进行交互,以便能够在许多其他用例中使用它。

下次见!

同样来自作者:

[## 3 第 2 层区块链扩展对 Gig 经济的潜在好处

让我们一起来看看区块链应该如何扩展,以及第 2 层扩展对 Gig 有什么影响…

medium.com](https://medium.com/@furkansaatcioglu/3-potential-benefits-of-layer-2-blockchain-scaling-on-the-gig-economy-9c24f77489c1)

如何将 PyTorch 中的 CNN 应用到您的图像中?

原文:https://towardsdatascience.com/how-to-apply-a-cnn-from-pytorch-to-your-images-18515416bba1?source=collection_archive---------9-----------------------

您将学习如何在几分钟内将下载的图像上传到 PyTorch。

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

Unsplash 上由Marnhe du ploy拍摄的照片

大家好!今天我想谈谈把你的图片上传到你的 PyTorch CNN。

今天我们将讨论以下内容:

  • 如何正确存储图像,让您可以轻松地将您的数据标记出来。
  • 如何使用 PyTorch 访问数据并在途中做一些预处理?
  • 最后,我们将使用一个非常简单的 CNN 对我们的图像进行分类。

首先,如何存储数据?

我将使用这个数据集,其中包含了猫和狗的图像。

存储图像最简单的方法是为每个类创建一个文件夹,用类的名称命名文件夹。

让我举个例子:

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

作者图片

只需正确命名文件夹,就可以让 PyTorch 知道向哪个类断言图像。

现在,让我们进入代码。

import matplotlib.pyplot as plt
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torchdef get_data():
    data_dir = '/your_path/Data/'

    train_set = datasets.ImageFolder(data_dir + '/training_set')
    test_set = datasets.ImageFolder(data_dir + '/test_set')

    return train_set, test_set

上面的函数从目录中获取数据。您只需指定到您的训练集测试集文件夹的路径。PyTorch 随后会使用指定目录中的文件夹名称自动将标签分配给图像。

然而,您可能想在使用图像之前做一些预处理,所以让我们做吧,此外,让我们马上创建一个数据加载器。为此,让我们在上面的代码中添加一些新行。

def get_data():
    data_dir = '/your_path/Data/'

    **transform** = transforms.Compose([
        #transforms.RandomRotation(20),
        transforms.RandomResizedCrop(128),
        #transforms.RandomHorizontalFlip(),
        transforms.ToTensor()])

    train_set = datasets.ImageFolder(data_dir + '/training_set', **transform=transform**)
    test_set = datasets.ImageFolder(data_dir + '/test_set', **transform=transform**)

    train = **DataLoader**(train_set, batch_size=32, shuffle=True)
    test = **DataLoader**(test_set, batch_size=32, shuffle=True)

    return train, test

在转换过程中,你可能需要对图像进行裁剪、翻转、调整大小、旋转等操作。为此,您可以使用转换在一个地方指定您需要的所有东西。然后,您可以使用上传的图像创建数据加载器

这就是 CNN 发挥作用的地方。

现在,当您准备好数据后,您可能想快速浏览一下。为此,您可以使用这个简单的函数,它将显示前 5 幅图像。

def train_imshow():
    classes = ('cat', 'dog') # Defining the classes we have
    dataiter = iter(train)
    images, labels = dataiter.next()
    fig, axes = plt.subplots(figsize=(10, 4), ncols=5)
    for i in range(5):
        ax = axes[i]
        ax.imshow(images[i].permute(1, 2, 0)) 
        ax.title.set_text(' '.join('%5s' % classes[labels[i]]))
    plt.show()

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

作者图片

让我们来定义我们的卷积神经网络:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(8, 8)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16, 100)
        self.fc2 = nn.Linear(100, 50)
        self.fc3 = nn.Linear(50, 2)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

我使用了这里定义的网络并做了一点修改,现在它可以和我的图片一起工作了。

现在我们可以指定标准、优化器、学习率和训练网络。

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)if torch.cuda.is_available(): # Checking if we can use GPU
    model = net.cuda()
    criterion = criterion.cuda()

def train_net(n_epoch): # Training our network
    losses = []
    for epoch in range(n_epoch):  # loop over the dataset multiple times
        running_loss = 0.0
        for i, data in enumerate(train, 0):
            # get the inputs; data is a list of [inputs, labels]
            inputs, labels = data

            # zero the parameter gradients
            optimizer.zero_grad()

            # forward + backward + optimize
            outputs = net(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()

            # print statistics
            losses.append(loss)
            running_loss += loss.item()
            if i % 100 == 99:  # print every 2000 mini-batches
                print('[%d, %5d] loss: %.10f' %
                      (epoch + 1, i + 1, running_loss / 2000))
                running_loss = 0.0
    plt.plot(losses, label='Training loss')
    plt.show()
    print('Finished Training')

您可以保存和加载您训练过的网络。

PATH = './cat_dog_net.pth'
torch.save(net.state_dict(), PATH)

# Loading the trained network
net.load_state_dict(torch.load(PATH))

让我们把测试图像输入网络。

correct = 0
total = 0
with torch.no_grad():
    for data in test:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the %d test images: %d %%' % (len(test),
    100 * correct / total))

测试集误差为 66% ,这还不错,尽管获得尽可能好的精度并不是本文的目标。

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

干得好!现在你已经准备好使用你的图像来练习深度学习了!

感谢您的阅读!

如何将 BERT 应用于阿拉伯语和其他语言

原文:https://towardsdatascience.com/how-to-apply-bert-to-arabic-and-other-languages-5c3410ddd787?source=collection_archive---------4-----------------------

多语言(XLM-罗伯塔)与单语(阿拉伯伯特)的方法,以及机器翻译如何帮助。

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

迪米特里 B 在 Unsplash 上拍摄的照片

到目前为止,Nick 和我一直在使用英语编写几乎专门关于 NLP 应用程序的教程…虽然通用算法和思想可以扩展到所有语言,但是支持英语 NLP 的大量资源并不能扩展到所有语言。例如,BERT 和类似 BERT 的模型是一个非常强大的工具,但是模型发布几乎总是用英语,可能后面还有中文、俄文或西欧语言的变体。

出于这个原因,我们将关注一个有趣的类伯特模型类别,称为多语言模型,它有助于将大型类伯特模型的功能扩展到英语以外的语言。

克里斯·麦考密克和尼克·瑞安

1.多语言模型

1.1.多语言模型方法

多语言模型采用一种相当奇怪的方法来处理多种语言…

多语言模型不是单独处理每种语言,而是根据来自混合语言的文本进行预训练。

在这篇文章和附带的笔记本中,我们将使用一个来自脸书的名为 XLM-R 的特定多语言模型(“跨语言语言模型—罗伯塔”的简称)。

最初的伯特在英语维基百科和 BooksCorpus(自助出版书籍的集合)上接受过预训练,而 XLM-R 在维基百科和来自 100 种不同语言的通用抓取数据上接受过预训练!不是 100 种不同的模型在 100 种不同的语言上接受训练,而是一个单一的伯特型模型,它是在所有这些文本上预先训练好的。

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

(图片由作者提供)

这里真的没有任何东西试图刻意区分语言。例如,在 XLM-R:

  • 有一个单一的、共享的词汇表(包含 25 万个令牌)来涵盖所有 100 种语言。
  • 输入文本中没有添加特殊的标记来指示它是什么语言。
  • 它不是用“平行数据”(多种语言的同一句话)训练的。
  • 我们没有修改培训目标来鼓励它学习如何翻译。

然而,XLM-R 并没有预测无意义或对其众多输入语言中的任何一种都只有最起码的理解,而是表现得令人惊讶地好,甚至与用单一语言训练的模型相比也是如此!

1.2.跨语言迁移

如果您的应用程序是用另一种语言编写的(从现在开始,我们将使用阿拉伯语作为例子),您可以像使用常规 BERT 一样使用 XLM-R。您可以在您的阿拉伯语培训文本上微调 XLM-R,然后使用它来用阿拉伯语进行预测。

然而,XLM-R 允许你利用另一种更令人惊讶的技术…

假设您正试图构建一个模型来自动识别阿拉伯语中令人讨厌的(或“有毒的”)用户评论。已经有一个很棒的数据集叫做“维基百科有毒评论”,大约有 225,000 条标签评论——只不过都是英文的!

你有什么选择?用阿拉伯语收集类似规模的数据集将会非常昂贵。以某种方式应用机器翻译可能很有趣,但有其局限性(我将在后面的部分中更多地讨论翻译)。

XLM-R 提供了另一种称为“跨语言迁移”的途径。你可以在英文的维基百科有毒评论数据集上微调 XLM-R,然后将其应用于阿拉伯语评论

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

(图片由作者提供)

XLM-R 能够将它在英语中学习到的特定任务知识应用到阿拉伯语中,尽管我们从未向它展示过任何阿拉伯语的例子!这是从一种语言到另一种语言的迁移学习的概念——因此,“跨语言迁移”。

在这篇文章附带的笔记本中,我们将看到纯粹在大约 400k 英语样本上训练 XLM-R 实际上比在(小得多的)阿拉伯数据集上微调“单语”阿拉伯模型产生更好的结果。

这个令人印象深刻的壮举被称为 零距离学习 跨语言迁移

1.3.为什么是多语言?

多语言模型和跨语言转移是很酷的技巧,但是如果脸书只是为这些不同的语言中的每一种训练和发布一个单独的模型不是更好吗?

是的,这可能会产生最准确的模型——如果网上每种语言的文本都像英语一样多就好了!

只对单一语言的文本进行预训练的模型称为 单语 ,而对多种语言的文本进行预训练的模型称为 多语言

下面的柱状图显示了对于一小部分选择的语言,XLM-R 的作者能够为预训练收集多少文本数据。

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

(图片作者,改编自 XLM-R 论文图 1)

请注意,比例是对数的,因此英语数据大约比阿拉伯语或土耳其语多 10 倍,比意第绪语多 1000 倍。

1.4.按资源划分的语言

不同的语言有不同数量的训练数据可用于创建大型的类似 BERT 的模型。这些被称为低资源语言。英语、汉语和俄语等高资源语言在网上有大量免费的文本,可以用作训练数据。因此,NLP 研究人员主要集中于开发大型语言模型和这些语言的基准。

我改编了 XLM-R 论文的图 1 中的柱状图。这是他们的完整条形图,显示了他们为 100 种语言中的 88 种语言收集的数据量。

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

这些语言用两个字母的 ISO 代码标注——你可以在这里的表格中查找。

下面是柱状图中的前十个代码(注意,在德语之后还有另外~10 种语言有类似的数据量)。

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

请注意,这个“数据量”的排名与每种语言在互联网上有多少用户的排名并不匹配。在维基百科上查看这个表格。在柱状图中,中文(代码zh)排在第 21 位,但迄今为止拥有最多的用户(仅次于英语)。

类似地,NLP 研究人员对不同语言付出的努力和关注并不遵循柱状图中的排名——否则汉语和法语会排在前 5 名。

最近有一个名为OSCAR的项目,它为不同语言的类似 BERT 的模型提供了大量的预训练文本——如果你正在寻找未标记的文本来使用你的语言进行预训练,那么绝对值得一试!

1.5.利用机器翻译

也有可能涉及“机器翻译”(自动翻译文本的机器学习模型),以尝试和帮助解决语言资源有限的问题。这里有两种常见的方法。

方法 1——翻译所有内容

您可以完全依赖英文模型,将应用程序中的任何阿拉伯文本翻译成英文。

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

(图片由作者提供)

这种方法与单语模型方法具有相同的问题。最好的翻译工具使用机器学习,对于可用的训练数据也有同样的限制。换句话说,针对中低资源语言的翻译工具还不足以成为我们问题的简单解决方案——目前,像 XLM-R 这样的多语言 BERT 模型可能是更好的选择。

方法#2 —增加训练数据

如果你的任务中已经存在大量带标签的英语文本,那么你可以将这些带标签的文本翻译成阿拉伯语,并用它来扩充你可用的阿拉伯语训练数据。

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

(图片由作者提供)

如果您的语言中有一个不错的单语模型,并且有一个大型英语数据集可用于您的任务,那么这是一个很好的技术。我们在一个附带的笔记本中将这种技术应用于阿拉伯语,它的表现优于 XLM-R(至少在我们的初始结果中——我们没有执行严格的基准测试)。

1.6.XLM R 词汇

正如你可能想象的那样,为了适应 100 种不同的语言,XLM-R 拥有与最初的 BERT 非常不同的词汇。

XLM R 的词汇量为 250,000 个单词,而伯特的词汇量为 30,000 个单词。

我在这里发布了一个笔记本,在这里我浏览了 XLM-R 的词汇,以了解它包含的内容,并收集各种统计数据。

以下是一些亮点:

  • 它包含 13,828 个字符的“字母表”。
  • 其中 62%是全词,38%是子词。
  • 为了统计英语单词,我尝试在 WordNet(一种综合英语词典)中查找所有完整的单词,找到了大约 11,400 个英语单词,这只是 XLM-R 词汇量的 5%。

2.比较方法

2.1.自然语言推理

评估多语言模型最常用的任务叫做自然语言推理(NLI) 。原因是有一个优秀的多语言基准数据集叫做 XNLI

我们将在下一节讨论 XNLI,但是如果您不熟悉的话,这里有一个对基本 NLI 任务的解释。

在 NLI,我们被给予两个句子:(1)一个“前提”和(2)一个“假设”,并被要求确定是否:

  • 1 逻辑上产生 2(这称为“蕴涵”)
  • 2 与 1 矛盾(“矛盾”)
  • 2 对 1 没有影响(“中性”)

以下是一些例子:

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

据我所知,NLI 主要是一个基准测试任务而不是一个实际应用——它需要模型开发一些复杂的技能,所以我们用它来评估和基准测试像 BERT 这样的模型。

2.2.MNLI 和 XNLI 概述

在 NLI 上对多语言模型的基准测试是通过组合两个名为“MNLI”和“XNLI”的数据集来完成的。

MNLI 将为我们提供大量的英语训练实例,以微调 XLM-罗伯塔对 NLI 的总任务。

XNLI 将为我们提供少量不同语言的 NLI 测试示例*。我们将采用我们的 XLM-罗伯塔模型(我们将仅对英语 MNLI 示例进行微调),并将其应用于 XNLI 的阿拉伯语测试用例。*

关于 MNLI

多体裁自然语言推理 (MultiNLI 或 MNLI)语料库于 2018 年发布,是超过 40 万个英语句子对的集合,标注有文本蕴涵信息。

在 MNLI 中,‘多’是指多体裁,而不是多语言。很困惑,我知道!它被称为“多体裁”,因为它旨在成为斯坦福 NLI 语料库(SNLI)的继任者,后者完全由一些取自图像说明的简单句子组成。MNLI 通过添加多种更难的文本“体裁”增加了任务的难度,如转录的对话、政府文件、旅游指南等。

该语料库包含 392,000 个训练示例,20,000 个“开发示例”(开发模型时使用的测试示例),以及 20,000 个“测试示例”(报告基准分数的最终测试集)。

以下是一些随机选择的培训示例

*Premise:
    If I had told you my ideas, the very first time you saw Mr. Alfred
    Inglethorp that astute gentleman would have ”in your so expressive idiom
    ”'smelt a rat'!
Hypothesis:
    In the event that I had revealed my ideas to you, Mr. Alfred would have been
    absolutely oblivious to your knowledge of my ideas.
Label:
    2 (contradiction)----------------Premise:
    Like federal agencies, the organizations we studied must protect the
    integrity, confidentiality, and availability of the information resources
    they rely on.
Hypothesis:
    Some organizations must protect the confidentiality of information they rely
    on.
Label:
    0 (entailment)----------------Premise:
    Well? There was no change of expression in the dark melancholic face.
Hypothesis:
    He just looked at me and said, Well, what is it?
Label:
    0 (entailment)----------------*

关于 XNLI

“XNLI”代表跨语言自然语言推理语料库。论文(此处)于 2018 年 9 月首次提交给 arXiv

该数据集由 MLNI 数据集中已经被人工翻译成 14 种不同语言(如果包括英语,则总共为 15 种语言)的示例的较小子集组成:

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

XNLI 不提供这些不同语言的训练数据,所以它旨在作为我们将在这里采用的跨语言方法的基准。

对于每种语言,有 5000 个测试集句子对和 2500 个开发集句子对。

NYU 大学的 Sam Bowman 负责 MNLI 和 XNLI 数据集。XNLI 是与脸书合作完成的。

这里有几个来自阿拉伯语测试集的随机例子。

*Premise:
    في المسرحية الاجتماعي كذلك، فإن فرص العمل والتنسيق بين الأدوار المختلفة ربما
    تساعد الأطفال على فهم أوجه التشابه والاختلاف بين الناس في الرغبات والمعتقدات
    والمشاعر.
Hypothesis:
    لا يستطيع الأطفال تعلم اى شئ .
Label:
    2 (contradiction)----------------Premise:
    لماذا ، كما كنت  أخبر سيادته هنا ، من فكر مثلك أن وجود الأنسة بيشوب على متن
    السفينة سيجعلنا أمنين ، ليس من أجل أمه ،ذاك النخاس القذر سكت عن ما هو مستحق
    له .
Hypothesis:
    لم أتحدّث إلى سيادته منذ زمن طويل.
Label:
    2 (contradiction)----------------Premise:
    لقد قذفت إعلان عن كوكاكولا هناك
Hypothesis:
    ضع إعلان مشروب غازي.
Label:
    1 (neutral)----------------*

2.3.单语教学法

我们为这篇文章创建了两个笔记本——一个用于应用单语模型,另一个用于应用多语言模型(XLM-R)。

对于单语方法,我使用了一个社区提交的模型,从。该模型的文档显示,它预先接受了大量阿拉伯文本的训练,并且在过去 30 天内有很高的下载量(这意味着它是一个受欢迎的选择)。

我用两种不同的方法微调了这个模型。

方法 1——使用一个小的带标签的数据集

我们可以使用 XNLI 的小型验证集(2500 个人工翻译的阿拉伯语示例)作为我们的训练集。这是一个非常小的训练集,特别是与英语 MNLI 中的大约 40 万个例子相比!我认为这种方法与您自己尝试收集带标签的数据集最为相似。

该方法在阿拉伯语 XNLI 测试集上的准确率为 61.0%。这是我们尝试的各种方法的最低分(在后面的部分有一个结果表)。

方法 2——使用机器翻译的示例

XNLI 的作者还为 14 种非英语语言中的每一种语言提供了大型英语 MNLI 数据集的机器翻译副本。

这将为我们提供充足的训练数据,但想必数据的质量会更低,因为样本是由不完善的机器学习模型而不是人类翻译的。

这种方法在阿拉伯语 XNLI 测试集上给了我们 73.3%的准确率。

2.4.多语言方法

对于多语言方法,我根据完整的英语 MNLI 训练集对 XLM-R 进行了微调。

使用 huggingface/transformers 库,应用 XLM-R 和应用伯特几乎是一样的,你只是使用不同的类名。

要使用单语方法,您可以用以下代码加载模型和标记器:

*from transformers import BertTokenizer
from transformers import BertForSequenceClassification# Load the tokenizer.
tokenizer = BertTokenizer.from_pretrained("asafaya/bert-base-arabic")# Load the model.
model = BertForSequenceClassification.from_pretrained("asafaya/bert-base-arabic", num_labels = 3)*

对于 XLM-R,这就变成了:

*from transformers import XLMRobertaTokenizer
from transformers import XLMRobertaForSequenceClassification# Load the tokenizer. 
xlmr_tokenizer = XLMRobertaTokenizer.from_pretrained("xlm-roberta-base" )# Load the model.
xlmr_model = XLMRobertaForSequenceClassification.from_pretrained("xlm-roberta-base", num_labels=3)*

学习率

代码的其余部分是相同的。然而,我们确实遇到了参数选择的关键差异…我们发现 XLM-R 比伯特需要更小的学习速率-我们使用 5e-6。当我们尝试 2e-5(BERT 建议的最小学习率)时,XLM-R 训练完全失败了(模型的性能从未比随机猜测有所提高)。注意 5e-6 是 2e-5 的四分之一。

跨语言结果

使用这种跨语言转换方法,我们在阿拉伯语 XNLI 测试集上获得了 71.6%的准确率。相比之下,对阿拉伯语例子进行微调的单语模型只得到 61.0%的分数!

XML-RoBERTa 的作者在他们的论文中报告了 73.8%的阿拉伯语分数,见表 1:

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

表格最下面一行的模型更大,它与 BERT-large 的规模相匹配。在我们的例子中,我们使用了较小的“基础”尺寸。

我们较低的精度可能与批量大小、学习速率和过拟合等参数选择有关。

2.5.结果摘要

同样,我使用这些笔记本的目的是提供工作示例代码;不执行严格的基准测试。为了真正比较这些方法,应该进行更多的超参数调整,并且应该对多次运行的结果进行平均。

但是这里是我们用最小的调整得到的结果!

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

对于表中的第 2–4 行,您可以通过对阿拉伯语 XNLI 验证示例进行微调来进一步改进这些结果。(我用 XLM-R 快速尝试了一下,确认分数上升到了 74.2%!)

2.6.使用哪种方法?

考虑到我更容易用arabic-bert-base获得好的结果,并且知道它需要更少的内存(由于更小的词汇量),我想在这种情况下我会选择单语模型。

然而,这仅仅是因为一个团队预先训练并发布了一个很好的阿拉伯语单语模型!

我原本想用印尼语作为这个项目的示例语言,但是

  1. 印尼语不在 15 种 XNLI 语言之列。
  2. 我发现的最好的印度尼西亚型号,CAH ya/Bert-base-Indonesia-522m,是在相对适度的文本量(~0.5GB)上预先训练的,因此我对它的性能持怀疑态度。

对于印度尼西亚人来说,我仍然想尝试这两种方法,但我怀疑 XLM-R 会走在前面。

笔记本示例

这篇文章中提到的两个笔记本(一个实现多语言实验,另一个实现单语实验)可以从我的网站这里购买。我还在 YouTube 这里提供了这些笔记本的演示。

如何对时间序列数据应用 K 均值聚类

原文:https://towardsdatascience.com/how-to-apply-k-means-clustering-to-time-series-data-28d04a8f7da3?source=collection_archive---------0-----------------------

使 k-means 算法适应时间序列的理论和代码

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

图片由 Piqsels 提供

聚类是一种无监督的学习任务,其中算法将相似的数据点分组,而没有任何“基础事实”标签。数据点之间的相似性用距离度量来衡量,通常是欧几里德距离

将不同的时间序列聚类到相似的组中是一项具有挑战性的聚类任务,因为每个数据点都是有序的序列。

时间序列聚类最常见的方法是将时间序列展平到一个表中,每个时间索引(或序列的聚合)有一列,并直接应用标准的聚类算法,如 k-means(K-means 是一种常见的聚类算法,通过将样本分成 K 组并最小化每个聚类中的平方和来构建数据聚类)。

如下所示,这并不总是很好。图表中的每个子图都绘制了一个由具有欧几里德距离的 k 均值聚类生成的聚类。红色的簇形心没有捕捉到系列的形状。

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

来源 : tslearn 文档

直观上,标准聚类算法中使用的距离度量,如欧几里德距离,通常不适用于时间序列。更好的方法是用一个比较时间序列的度量代替默认的距离度量,比如 动态时间扭曲

在本文中,我将解释如何使用动态时间弯曲将 k 均值聚类调整到时间序列。我将提供来自[tslearn](https://github.com/tslearn-team/tslearn)包的简单代码示例。

时间序列的动态时间弯曲距离度量

但首先,为什么常见的欧氏距离度量不适合时间序列?简而言之,它对时间偏移是不变的,忽略了数据的时间维度。如果两个时间序列高度相关,但其中一个移动了一个时间步长,欧几里德距离就会错误地将它们测量为相距较远。点击此处查看详细示例。

相反,最好使用动态时间弯曲(DTW)来比较序列。DTW 是一种测量在时间、速度或长度上不完全一致的两个时间序列之间的相似性的技术。

DTW 解释道

给定系列 X =(x₀、…、xₙ)和系列 Y =(y₀、…、yₘ),从 XY 的 DTW 距离被公式化为以下优化问题:

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

来源: tslearn 文档

总结一下 DTW 方程: DTW 计算为 X 中每个元素与其在 Y 中最近的点之间的平方距离之和的平方根。注意,DTW(X,Y) ≠ DTW(Y,X)。

让我们进一步分析一下。

*DTW 将序列 X 中的每个元素与序列 Y 中的每个元素进行比较(n x m 比较)。比较起来, *d(xᵢ,yⱼ),不过是简单的减法 xᵢ — yⱼ

然后对于 X 中的每个 xᵢ ,DTW 选择 y 中最近的点进行距离计算。

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

上图:说明 DTW 如何将蓝色系列中的每个点与红色系列中最近的点进行匹配。下图:说明欧几里得距离度量如何匹配两个时间序列中的点。请注意,系列长度不同,与欧几里得匹配不同,DTW 能够将蓝色系列中的每个点与红色系列中的一个点进行比较。来源: wikicommons

这在 XY 之间创建了一条扭曲的“路径”,将 X 中的每个点与 Y 中最近的点对齐。该路径是时间序列的时间对齐,可最小化对齐序列之间的欧几里德距离。

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

两个时间序列(蓝色)之间的 DTW 路径(白线)的图像。热度图突出显示了距离值( xᵢ — yⱼ)。 来源 : tslearn 文档

使用复杂度为 O(MN)的动态规划来计算动态时间弯曲。点击此处此处了解具体算法详情。

用 python 中的 DTW 很容易比较两个时间序列:

***from** **tslearn.metrics** **import** dtw
dtw_score = dtw(x, y)*

DTW 的变体:软 DTW

软 DTW 是 DTW 的一个可微分变体,它用一个可微分的soft-min运算代替了不可微分的min运算:

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

来源 : tslearn 文档

根据该函数,软 DTW 依赖于一个超参数 γ 来控制结果度量的平滑。像 DTW 一样,可以使用动态规划在二次时间内计算软 DTW。

脚注:软 DTW 的主要优势源于它处处可微。这允许软 DTW 被用作神经网络损失函数,比较地面真实序列和预测序列。

***from** **tslearn.metrics** **import** soft_dtw
soft_dtw_score = soft_dtw(x, y, gamma=.1)*

具有动态时间弯曲的 k-均值聚类

通过以下修改,k-means 聚类算法可以应用于具有动态时间弯曲的时间序列。

  1. 动态时间弯曲(DTW)用于收集相似形状的时间序列。
  2. 群集质心,或重心*,是相对于 DTW 计算的。A 重心是 DTW 空间中一组时间序列的平均序列。 DTW 重心平均(DBA) 算法最小化重心和聚类中序列之间的 DTW 距离的平方和。软 DTW 算法最小化重心和聚类中系列之间的软 DTW 距离的加权和。权重可以调整,但总和必须为 1。*

结果,质心具有模拟集群成员形状的平均形状,而不管成员之间的时间偏移发生在哪里。

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

顶行:使用 DTW 的 K-均值聚类(DBA 算法)。底部一行:使用软 DTW 的 K-均值聚类。每一列显示了来自不同簇的系列和它们的质心,用红色绘制。源码+代码

使用[tslearn](https://tslearn.readthedocs.io/en/stable/user_guide/clustering.html) Python 包,用 k-means 和 DTW 简单聚类时间序列数据集:

***from** **tslearn.clustering** **import** TimeSeriesKMeansmodel = TimeSeriesKMeans(n_clusters=3, metric="dtw", max_iter=10)
model.fit(data)*

要使用软 DTW 代替 DTW,只需设置metric="softdtw"

注意[tslearn](https://tslearn.readthedocs.io/en/stable/gettingstarted.html#time-series-format)期望一个单一的时间序列被格式化为二维数组。一组时间序列应该被格式化为一个形状为(num_series, max_length, 1)的三维数组。如果集合中的系列长度不等,则较短的系列将增加 NaN 值。tslearn 具有易于使用的实用函数用于正确格式化数据,并且易于与其他时间序列包和数据格式集成。

最后一句话

我希望你喜欢读这篇文章。要了解时间序列机器学习,请查看我的其他文章:

* [## 如何对时间序列应用层次聚类

聚类是一种无监督的学习任务,其中算法将相似的数据点分组,而没有任何“基础事实”…

link.medium.com](https://link.medium.com/1nJUjkUg4bb) [## 时间序列分类算法简介

专门为时间序列分类设计的专用算法

towardsdatascience.com](/a-brief-introduction-to-time-series-classification-algorithms-7b4284d31b97) [## 高度比较的时间序列分析——一篇论文综述

用于比较、聚类、分类和注释的时间序列特征提取分析

medium.com](https://medium.com/towards-artificial-intelligence/highly-comparative-time-series-analysis-a-paper-review-5b51d14a291c)

参考

[## 阅读亚历山德拉·阿米登(以及媒体上成千上万的其他作家)的每一个故事

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

alexandra-amidon.medium.com](https://alexandra-amidon.medium.com/membership)*

如何从始至终接近一个机器学习项目

原文:https://towardsdatascience.com/how-to-approach-a-machine-learning-project-from-beginning-to-end-96c30a029873?source=collection_archive---------53-----------------------

受博士框架启发的循序渐进指南

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

Kolleen Gladden 在 Unsplash 上拍摄的照片

目录

  1. 介绍
  2. 那么为什么框架很重要呢?
  3. 机器学习生命周期

介绍

你有项目想法却不知道从何下手吗?或者也许你有一个数据集,想建立一个机器学习模型,但你不确定如何接近它?

在这篇文章中,我将谈论一个概念框架,你可以用它来接近任何机器学习项目。这个框架受到了理论框架的启发,与你可能在网上看到的机器学习生命周期的所有变体非常相似。

那么为什么框架很重要呢?

机器学习的框架很重要,原因有很多:

  • 它创建了一个标准化的过程来帮助指导数据分析和建模
  • 它允许其他人了解问题是如何处理的,并修正旧的项目
  • 它迫使一个人更深入地思考他们试图解决的问题。这包括要测量的变量是什么,限制是什么,以及可能出现的潜在问题。
  • 它鼓励人们在工作中更加彻底,增加发现和/或最终结果的合法性。

有了这几点,再来说框架!

机器学习生命周期

虽然机器学习生命周期有许多变化,但它们都有四个一般步骤:规划、数据、建模和生产。

1.规划

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

格伦·卡斯滕斯-彼得斯在 Unsplash 上拍摄的照片

在你开始任何机器学习项目之前,有许多事情你需要计划。在这种情况下,术语“计划”包含许多任务。通过完成这一步,你将对你试图解决的问题有更好的理解,并能对是否继续这个项目做出更明智的决定。

规划包括以下任务:

  • **说出你试图解决的问题。**这似乎是一个简单的步骤,但你会惊讶地发现,人们经常试图为一个并不存在的问题或一个实际上并不存在的问题找到解决方案。
  • **定义你为了解决问题而努力实现的商业目标。**目标应该是可衡量的。“成为世界上最好的公司”不是一个可衡量的目标,但“减少欺诈交易”是一个可衡量的目标。
  • 确定目标变量(如果适用)和你可能想要关注的潜在特征变量。例如,如果目标是减少欺诈性交易的数量,您很可能需要欺诈性和非欺诈性交易的标记数据。您可能还需要像交易时间、帐户 ID 和用户 ID 这样的特性。
  • 考虑任何限制、突发事件和风险。这包括但不限于资源限制(缺少资金、员工或时间)、基础设施限制(例如缺少训练复杂神经网络的计算能力)和数据限制(非结构化数据、缺少数据点、无法解释的数据等)
  • 建立你的成功指标。你如何知道你已经成功实现了你的目标?如果你的机器学习模型有 90%的准确率是成功的吗?85%呢?准确性是最适合您的业务问题的衡量标准吗?查看我的文章 数据科学家用来评估他们模型的几个指标

如果你完成了这一步,并对项目有信心,那么你可以进入下一步。

2.数据

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

Markus SpiskeUnsplash 上拍摄的照片

这一步的重点是获取、探索和清理数据。更具体地说,它包括以下任务:

  • 收集并整合您在规划阶段指定的数据。如果您从多个来源获取数据,您需要将数据合并到一个表中。
  • **争论你的数据。**这需要清理和转换您的数据,使其更适合 EDA 和建模。您需要检查的一些内容包括缺失值、重复数据和噪声。
  • 进行探索性数据分析(EDA) 。也称为数据探索,这一步基本上已经完成,因此您可以更好地了解您的数据集。如果你想了解更多关于 EDA 的知识, 你可以阅读我的关于进行探索性数据分析的指南

3.建模

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

照片由 Isaac SmithUnsplash 上拍摄

一旦数据准备就绪,就可以继续构建模型了。这有三个主要步骤:

  • 选择您的模型:您选择的模型最终取决于您试图解决的问题。例如,无论是回归问题还是分类问题,都需要不同的建模方法。如果你想了解各种机器学习模型,请查看我的文章’6 分钟解释所有机器学习模型
  • 训练你的模型:一旦你选择了你的模型并分割了你的数据集,你就可以用你的训练数据来训练你的模型。
  • 评估您的模型:当您觉得您的模型已经完成时,您可以根据您决定的预先确定的成功标准,使用测试数据来评估您的模型。

4.生产

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

亚历山大·杜默在 Unsplash 上拍摄的照片

最后一步是生产你的模型。这一步在课程和网上谈得不多,但对企业来说尤其重要。没有这一步,您可能无法从您构建的模型中获得全部价值。在这一步中,有两个主要问题需要考虑:

  • **模型部署:**部署机器学习模型,称为模型部署,简单地说就是将机器学习模型集成,并将其集成到现有的生产环境中,在那里它可以接受输入并返回输出。
  • **模型监控:**模型监控是机器学习生命周期中的一个操作阶段,在模型部署之后,它需要“监控”您的 ML 模型,例如错误、崩溃和延迟,但最重要的是,确保您的模型保持预定的预期性能水平。

感谢阅读!

特伦斯·申

创始人ShinTwin|我们来连线一下LinkedIn|项目组合这里是

如何在你的下一个深度学习项目中定义问题

原文:https://towardsdatascience.com/how-to-approach-problem-definition-in-your-next-deep-learning-project-9d76960932b4?source=collection_archive---------17-----------------------

人工智能|深度学习|机器学习

失败或成功的深度/机器学习项目之间的区别。

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

沃洛德梅尔·赫里先科Unsplash 上的照片

介绍

和大多数深度学习从业者一样,我总是渴望着手导入 TensorFlow,然后实现和训练模型。

这是我在大多数业余爱好项目中通常采用的方法。

当涉及到在一个涉及实际问题、真实用户、付费客户、时间和金钱投资的项目内进行基于深度学习的解决方案时;那么就必须考虑并实施深度学习项目的常规阶段。这些阶段是:

  1. 问题定义
  2. 数据采集
  3. 模型设计
  4. 模特培训
  5. 模型评估/测试
  6. 质量保证
  7. 部署
  8. 应用程序维护/监控

本文探讨深度学习项目的第一阶段,问题定义。从这篇文章中,您可以期望对如何进行问题分析有一个更好的理解。你还可以期待获得一种直觉,即在理解一个需要基于深度学习的解决方案的问题的关键方面时,应该问什么样的问题。

定义和背景

深度学习项目的主要组成部分通常是一个模型,它接受输入“X”并提供输出“Y”。输出结果与原始输入具有某种形式的相关性。

上面对深度学习模型的一般描述在大多数情况下不满足开始模型实现的最低要求。

在我们深入模型实现或项目生命周期中的任何其他阶段之前,明智的做法是后退几步,系统地进行问题和解决方案分析。这是通过完成与任何深度学习项目中采取的先前动作和过程相关联的任务来实现的。

深度学习项目的第一个重要步骤/过程是问题定义。

**问题定义:**描述待解决问题的初始状态的清晰陈述。该陈述指出了问题的性质,例如要解决的任务、现有系统的当前性能以及对当前系统的体验。

引导性问题

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

卡拉·埃尔南德斯在 Unsplash 上的照片

在深度学习项目中进行成功的问题定义过程涉及对 什么为什么如何 方面与问题相关联的基本分析和评估。

想出一个好的问题定义通常是一个迭代的过程。它可以揭示更多的问题和需要考虑的事项,这些问题和事项在没有经过问题定义过程的情况下会被忽略。

下面包含的问题充当了指路明灯,可以对问题和相关主题进行透彻的分析。

仅仅花点时间回答下面的问题,就可以节省几周甚至几个月的时间来解决那些因为之前看不到的原因而变得不可行的问题。

  1. 需要解决的问题的本质是什么?
  2. 为什么问题需要解决方案?
  3. 应该如何解决这个问题?
  4. 深度学习模型将解决问题的哪个方面?
  5. 如何与问题的解决方案互动?

问题定义/陈述的示例

写得好的问题定义没有模棱两可的陈述,并且由于对问题的清晰和简明的描述而不会被误解。

以下是与通过深度学习技术解决的任务相关联的问题定义的一些示例。

例子 1:“减少与 Instagram 图片帖子相关的创意和原创图片说明的时间。”

示例 2: “基于 SNP 500 中股票的先前记录的 5 年历史价格变动**,为投资者自动生成股票推荐和价格预测**”

分解引导性问题

在这一节中,我们将深入探讨本文前面提出的指导性问题。

对场景的探索揭示了在处理需要基于深度学习的解决方案的问题时需要考虑的事项时,就可以更好地理解指导问题的适用性和重要性。

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

马库斯·温克勒在 Unsplash 上的照片

1。需要解决的问题的本质是什么?

了解问题的本质可以洞察尚未实现的解决方案的组件和属性。

对问题的良好理解会指导未来在项目后期做出决策,尤其是诸如确定深度学习解决方案是否可行之类的决策。

在示例 1 中,人们可以通过查看问题所在的环境来了解问题的本质( *Instagram)。了解任何描述与问题相关的现有流程的技术提及(图像字幕)*或短语也有助于深入了解问题的本质。

例 1 定义的问题主要与完成任务(图像字幕)所需时间的减少(减少时间)有关。

2。为什么问题需要解决方案?

回答这些指导性问题需要的不仅仅是问题陈述。

为了回答 为什么 一个问题需要一个解决方案将涉及与项目利益相关者的对话,更具体地说,是与目前正经历这个问题的个人的对话。

理解为什么一个问题需要一个解决方案将表明一个解决方案的紧迫性和重要性。

了解某个问题需要的解决方案有多紧急,可以指导解决方案的实施方法。深度学习方法因具有大量的训练和评估时间而臭名昭著。

与花费数天或数周时间训练和微调机器/深度学习模型相比,实现基于启发式的方法来解决需要数小时来实现和测试的问题可能更有用。

3.应该如何解决这个问题?

很可能,这个问题的答案已经变得越来越明显,首先是回答“为什么需要一个解决方案”。

有不止一种方法来实现基于深度学习的解决方案。

在高层次上,大多数机器学习实践者理解 ML 模型可以基于以下类别进行分类:监督的、非监督的和半监督的学习方法。

虽然本文关注的是基于深度学习的项目或解决方案,但是探索解决不符合特定领域假设或专业知识的问题的替代方法总是必要且有用的。

有时,用简单的 ML 模型实现一个解决方案,并在用户手中有了一个被提议的解决方案的版本之后迭代地改进模型,这是更实际的。

4。深度学习模型将解决问题的哪个方面?

在探索这个问题时,理解基于深度学习的解决方案的局限性总是有好处的。深度学习是好的,但它不能被用来解决每个问题。

深度学习解决方案非常适合涉及重复模式中可量化数据形式的问题;通常,这些是文本、图像、音频或数字数据的形式。

在许多情况下,深度学习模型只是更全面的解决方案的一小部分。在考虑解决方案时,通常会假设某个应用程序可以解决某个问题。

在更成熟的领域和业务中,通常会发现应用程序和硬件设备的生态系统以同步或异步方式进行通信和操作,以实现特定的任务。

从深度学习的角度来看,了解深度学习技术将解决问题的哪个方面能够确定分配给特定项目的技术和时间资源的范围。

5。问题的解决方案打算如何进行交互?

网站、移动应用、桌面应用,这些都是深度学习解决方案可以驻留的各种软件形式,每种形式都需要不同级别的交互。

在交付和部署 diving 解决方案之前,有必要了解如何与解决方案进行交互。

回答这个问题时,需要重点关注以下几个方面:

  • 用户使用该解决方案的频率如何?在项目生命周期的早期阶段回答这个问题创造了一个机会,可以开始确定与模型部署相关的模型推理成本的范围。
  • 当使用实施的解决方案的功能时,解决方案的用户是否要求立即得到结果?
  • 对实现的解决方案的设计和用户界面给予足够的关注。

问题定义的好处

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

照片由Olav Ahrens rtneUnsplash 上拍摄

在深度学习项目或任何机器学习项目中进行问题定义通常是一个复杂的过程,包含几项任务,如问题范围界定、用户访谈、技术规范等。

拥有一个定义明确的问题以及围绕该问题要解决的所有其他细节的好处是,深度学习项目中的后续过程有更高的成功机会。

下面的要点提供了对定义明确的问题的主要好处的进一步理解:

  • 经过充分探索的问题定义强化了正确的问题将被解决的假设。
  • 问题定义中涉及的过程暴露了实现已识别问题的解决方案所需的领域专业知识和工具。
  • 一个定义良好的问题定义可以作为一个参考点,以确保项目中的后续阶段和过程能够解决已识别的痛点。
  • 问题定义可以提供一种直觉,即对于一个特定的问题,产生期望的结果需要付出什么样的努力。
  • 在深度学习项目开始时进行严格的问题定义过程,可以真正理解问题的本质。

结论

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

安妮·斯普拉特在 Unsplash 上的照片

经历本文中确定的过程可能显得冗长。

尽管如此,在开始实施解决方案之前,确保您自己和团队成员都了解问题的各个方面还是有好处的。

即使是在一个单独的项目中工作,你也可以通过本文中提出的问题和过程进行规划。

我们都听说过无数的创业公司、公司和组织的回忆,它们希望利用深度学习来解决问题,但却发现在解决问题数月甚至数年后,解决方案无法实施。

在项目生命周期中进行一个简短的问题定义阶段可以节省金钱和时间,这是决定大多数项目成功的两个主要资源。

我希望这篇文章对你有用。

要联系我或找到更多类似本文的内容,请执行以下操作:

  1. 订阅我的 邮件列表 获取每周简讯
  2. 跟着我上
  3. 通过 LinkedIn 联系我

[## 2020 年机器学习项目的 10 个阶段(以及你适合的阶段)

了解机器学习相关项目涉及哪些阶段,并深入了解可交付成果和…

towardsdatascience.com](/10-stages-of-a-machine-learning-project-in-2020-and-where-you-fit-cb73ad4726cb)

如何解决复杂的问题

原文:https://towardsdatascience.com/how-to-approach-solving-complex-problems-797cb0f29418?source=collection_archive---------46-----------------------

这是我在处理数据分析需求时学到的一种方法,可以应用于任何复杂的问题。

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

万花筒Unsplash 上拍摄的照片

如何解决一个复杂的问题?有没有简单的方法?

在这篇文章中,我分享了一个我在处理数据分析需求时学到的简单方法,它可以用来解决几乎所有复杂的问题。

一点背景和问题定义

几年前,我最近开始为我们的一个新客户做一个项目。该客户最近在 Oracle EBS 套件中实施了 ERP,当时他们正在进行业务转型。

在这种情况下,他们需要在短时间内完成一些数据处理,以找出对各种业务的业务见解,以便管理层可以决定接下来的几个步骤。

我对所实现的业务和功能了解不多,但是作为一名软件开发人员,我在过去的六年中一直从事 Oracle 电子商务套件的工作,所以我对这类需求的处理非常自如。

举个例子,这是我一开始得到的关于客户试订单业务的一个要求。我们的客户会在试用的基础上免费给他们的客户一些设备,希望试用期过后客户会转化为实际销售。

对我的要求是做一些分析——前十大客户在过去一年中下了多少试订单,其中有多少在下订单后的三个月内转化为实际订单,没有转化的原因,当有更快的转化时,我能发现什么,等等。

这将允许管理层找到模式并提出想法来提高试用转换率,从而增加收入。这是一次性的活动。

解决方案和结果

我看问题的时候,看起来好简单。我想到的解决方案是编写一个 SQL 查询来从 Oracle DB 中提取数据并做进一步的分析。

编写 SQL 查询很容易。您只需要识别存储这些信息的表,识别主键和外键,用一个 where 子句将它们连接起来,该子句包含每条记录需要满足的所有过滤标准,优化以获得最佳性能,然后执行它。就这样,你得到了结果。

我写了 SQL 查询。在此之前,我已经编写了数百个这样的查询,所以即使是简单的查询,我也知道其中的细微差别,而且我会处理好所有这些。我确保优化器使用索引来获得更好的性能,等等。

但是当我在 TOAD 中执行查询时,查询没有产生任何记录。事实上,查询执行没有完成。这需要时间;演出很差,我只能等着。我等了几分钟,然后再等几分钟,再等几分钟。结果不会出来。

过了一会儿,我失去了耐心,取消了查询,并尝试对它进行了一些调整。我再次检查了查询以确保一切都是正确的,并重新执行了它。尽管如此,我还是没有得到结果。

由于我是这个项目的新手,我不知道数据库的大小,不太了解业务场景,不知道它需要处理多少记录。当你为一个新客户工作时会发生这种事,但我需要尽快得到结果。我刚刚从技术上审查了它,我确信我没有遗漏任何东西。执行计划看起来不错,但是,查询继续执行,不会完成。

这是一次性的数据提取要求,他们很快就需要它,而我已经晚了。我试了三四个小时,还是没完成。我挣扎过。

我和我的一个同事一起回顾了这个问题,他在这个项目上花的时间比我多一点,他也说这个问题似乎是正确的。应该是有效的。

我从各个角度回顾了一下,看起来还不错。可能,它必须获取的数据太多,这就是性能差的原因。我试着重写了几次查询,但是直到最后我还是没有得到数据。

我的团队领导要求在今天结束时提供最新情况。我告诉他我已经完成了查询,但也解释了我在获得结果时所面临的挑战。

他把椅子拉过来,就坐在我旁边。他拿起我的键盘,开始检查我写的查询。是的,查询是正确的。但是仔细回顾了五分多钟后,他说,我还记得。

你试图在一个查询中同时做太多的事情。分解一下。”

然后他说,“让我告诉你怎么做。”

改变解决方案和结果

他和我坐在一起,修改了我写的 SQL 查询。这个过程大概是这样的:

  • 首先,他通过根据去年的收入查询账单表来获取前 10 名客户,并创建了一个临时表。那是一张只有 10 张唱片的小桌子。将这些沉重的表(有超过一百万条数据记录)与订单表连接起来以进一步过滤是没有意义的。
  • 然后,他创建了 order 表的副本作为临时表,并在 required、ex-customer ID、order type、converted order 等列上创建了索引。不能直接在基表上创建索引,因此在临时表上创建索引对加快执行速度很有用。
  • 然后,他将客户临时表与订单临时表连接起来,以获取那些顶级客户下的所有订单。这又是一个简单的查询,很少过滤,因此获得结果要快得多。他用这些数据创建了另一个临时表。
  • 在这个临时表上,他应用了后续的过滤器,只获取在过去 12 个月中下的试订单,这些订单被转换为销售订单。有时一个过滤器比其他过滤器花费更多的时间,所以他做了几次迭代,看看哪个过滤器先应用,哪个过滤器后应用。
  • 大约有 10-12 个临时表,最后创建了 7-8 个索引,但是当执行最后一个查询时,结果在几秒钟内就出来了!。整个重写过程只花了大约半个小时。
  • 获得摘录后,他删除了所有的临时表和索引,回收了空间。

一开始我很惊讶,因为我不明白他想做什么,为什么要创建这么多临时表?我没有意识到他把它分解成如此小的部分,然后几乎不需要任何时间来执行。

我们在半小时内取得了惊人的成绩。我意识到分解它的重要性。

最好的学习发生在实践中

那天我学到了一些新东西。这是一个出色的结果,在短短的半小时内,我一整天都做不到。

我的团队领导教会了我一些简单而深刻的东西。这是获取数据的最佳方式吗?大概不会。但这有效吗?是的,完全正确。

当我反思这一天时,我学到了三个关键的教训。

  1. 对于我们需要什么以及如何解决问题,我们需要实事求是。我一开始没花多少时间就直接跳进了解决方案,以为很容易。
  2. 我们需要根据具体情况定制解决方案。对于上述一次性的数据提取需求,一种有效的方法是简化问题,并作为易于管理的部分的小块来执行。当你把所有的部分加起来时,不管每个部分有多简单,整个问题都会变得复杂。相反,任何复杂的问题,只要分解成更小的、更容易处理的部分,我们就能轻松解决。这是一门很大的学问。
  3. 原理很简单。但是申请很困难。即使我知道这个原则,但当问题摆在我面前时,我还是没有申请。我特意提醒自己以后要有解决问题的逻辑方法。

你如何应用这个原则?

这与 Kaizen 的原则相同,它专注于持续的微小改进,通过提出小问题、采取小行动、解决小问题来取得更大的成果。

明白问题出在哪里。问问题,即使是最基本的问题,什么,为什么,什么时候,如何,谁,还有倒装——比如,为什么不。想办法解决。但关键是不要不知所措。试着把问题分解成容易处理的部分。即使在分解之后,如果问题仍然复杂,就进一步分解。当它很小的时候,你可以很容易地解决它,而不是恐惧反应,大脑会产生兴奋的反应。独立解决每一个问题。

我们可以将同样的原则应用于大多数领域的问题:无论是商业、管理、我们的习惯、我们的健康和健身、我们的关系,还是我们的长期目标。

简化一个复杂的问题是困难的,但是一旦我们花时间去做,它会很有效。通常,一步一个脚印可以让我们走得更远。

我通常更喜欢用笔和纸来做这件事。我可以写下来,划掉,放盒子,圈圈,连接,改变,重写。它给了我很多选择,迫使我好好思考。看看什么对你有用。

底线

当我在另一个合并和收购场景中工作时,我使用了同样的方法好几年,在这个场景中,数据清理和数据迁移是客户的关键需求。不仅仅是数据分析问题,我还将这一原则应用于许多复杂的问题,这对我很有用。

有时候,我们只是需要一个提醒来使用简单的方法将我们的技能和效率提升到一个更高的水平——在设计、编程、解决问题、职业和生活中。我希望这篇文章能帮你做到。

所以,下一次当你努力解决一个问题时,想想——“我怎样才能把这个问题分解成更小的部分。“这可能就是你一直在寻找的方法。

如何解决分析/数据科学职位的技术问题

原文:https://towardsdatascience.com/how-to-approach-technical-questions-in-an-analytics-data-science-interview-1dc956eaebc0?source=collection_archive---------23-----------------------

我们将通过两个在分析/数据科学职位面试中被问到的真实例子来讲述如何处理技术问题。

我喜欢和我的读者交流,了解他们在技术面试时所关心的问题。他们经常充满焦虑,在准备的时候不知道从哪里开始。在本文中,我将通过两个真实的 SQL 示例来回答读者提出的最常见的问题,这两个示例说明了面试官在做出招聘决定时希望测试什么。

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

来源:stratascratch.com

读者最常见的问题:公司在技术面试中会问什么类型的技术问题,我该如何准备?

技术技能——容易培养的技能

至于准备,你只需要练习。但更具体地说,编写 SQL 语法和任何其他技术语言的能力绝对需要成为你的第二天性。这要么需要多年的经验,要么需要数百道练习题,才能让你的技能达到行业标准。你可以在我最喜欢的一些平台上查看我的另一篇文章。我会做你能做的所有中级和困难的问题。

实用技能——很难培养的技能

一旦技术部分成为第二天性,真正的工作就开始了。任何面试的第二个重点是测试某人如何思考和分解一个问题。他们在测试某人如何处理问题并提出解决方案。

你可以集中精力学习如何最好地沟通,并用白板演示一个全面的方法来回答业务问题,并涵盖面试官的所有边缘案例。

根据我在技术访谈中的经验,他们的重点是测试对代码正在做什么的理解,你如何考虑各种场景/边缘情况,以及输出的含义是否与业务问题相关。

面试

所以让我们来谈谈在面试中你可能会遇到什么类型的 SQL 问题。与您可能在工作中编写的又长又复杂的查询相比,SQL 问题本身相当简单。在工作中,为了回答问题和构建可伸缩的数据产品,您可能要跨几十个表编写数百行(如果不是数千行的话)代码。但是在面试中,要么给你 1 或 2 个表,要求你创建一个包含不超过 10 行代码的连接或自连接的 SQL 查询。如果幸运的话,您会得到 SQL 代码并被要求调试它(提示:很明显,代码总是有问题)。

就您的技术技能而言,只要您知道如何编写连接并使用像 COALESCE 这样稍微高级的函数,您就没问题。让面试变得困难的是

  • 想象一旦你写完代码,输出会是什么样子。代码几乎不在可执行的平台上。
  • 开发查询,使其回答面试问题
  • 传达所有边缘案例并在 SQL 查询中折叠边缘案例
  • 传达解决方案将提供的业务权衡(例如,这个查询真正回答了什么,盲点是什么?)

有了这四个让面试变得困难的要点,让我们来看几个例子来说明这些要点。

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

来源:theladders.com

以下是技术面试中被问到的两个真实的 SQL 问题:

1。真实面试写 SQL 查询的例子

给你一张表,其中包含用户好友请求、接受和日期。如何编写一个查询,让你的好友在一段时间内获得%的接受率?

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

首先,您可能永远不会得到填充了数据的实际表格。所以你应该问面试官表格包含哪些列,表格中包含什么类型的数据。

这个查询很容易创建(提示:使用自连接将朋友请求与接受分开)。任何懂 SQL 的人都可以编写查询来计算一段时间内朋友接受的百分比。一个可行的 SQL 查询可能如下所示:

SELECT
 (CASE WHEN b.action = ‘Friend_acceptance’ THEN 1 ELSE 0 END) / (CASE  WHEN a.action = ‘Friend_request’ THEN 1 ELSE 0 END) as percentage_acceptance
FROM table a
LEFT JOIN (SELECT * FROM table WHERE action = ‘Friend_acceptance’) b ON a.user_id = b.to_user_id
 WHERE action = ‘Friend_request’

您是否看到这个查询没有解决许多边缘情况,甚至没有真正回答这个问题?此查询评估一生中朋友接受的百分比。但是面试官想让我评估几天、几周、几个月或者几年的百分比吗?此外,你如何处理几天后朋友的接纳?你认为接受的时间是多少?从技术上来说,任何时候一个朋友接受你的请求都应该计入百分比。但是从商业角度来说,如果朋友两年后接受了请求,会有什么好处呢?你正试图打造一款将人们联系在一起的产品,你应该努力尽快实现这一目标/

此外,我在构建问题时会问面试官的另一个问题是——你是从朋友发出请求的那一天开始计算接受度,还是从请求被接受的那一天开始计算?为什么或为什么不?

所有这些问题对于完整地回答这个问题非常重要。你的面试官将测试你是否能发现并理解你的解决方案中的这些差距。这里没有正确或错误的答案,但是您需要确定有多种方法来编写查询,并讨论选择之间的权衡。

2。理解统计和业务含义的真实面试示例:

如果你做了一个 AB 实验,发现由于在试点地区推出了一项新功能,朋友接受度提高了 2 倍(p < 0.05), 你会将它部署到生产中,并向所有地区的所有用户推出吗?

大多数人会说是,但在面试中,最明显的答案可能不是正确的。在这种情况下,正确的答案是——视情况而定。为什么要靠,靠什么?答案是,这取决于特性的行为方式和特性的效果。一切都是一个系统,所以如果你在一个系统中做了一个改变,它会影响到系统的另一部分。在本例中,如果实验部署在平台的登录页面,您可能会问它占用了什么空间。对其他功能有影响吗?

另一个问题可能是算法本身。算法是不是减少了好友请求的数量?因为分母是一个小数字,这会导致朋友接受度的增加吗?为什么或为什么不?

显然,作为一个不了解特性和平台复杂性的人,不可能对你的推荐有信心。但你应该能够识别这些问题,并与面试官一起讨论,这样他们就能理解你是如何思考和处理模糊问题的。

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

来源:stratascratch.com

结论

在准备 SQL 面试时,我给你的主要建议是理解为什么以及如何编写代码来解决特定的问题。

  • 呈现的是什么数据,代码如何回答这个问题?
  • 我的代码中有哪些空白?
  • 我写代码的方式有什么利弊?
  • 我需要哪些额外信息来确保我考虑的是整体情况?

准备好交流你为什么要写特定的代码行,你添加了什么逻辑来解决特定的边缘情况和场景,以及输出会产生什么。你的解释和代码本身一样重要(如果不是更重要的话)。

此外,在你制定解决方案时,一定要和面试官交流,尽可能让他们了解你的思考过程。

SQL 面试不仅是为了测试你的技术能力,也是为了测试你的思维能力。把注意力集中在面试中要用到的技能上,确保尽可能多地做练习题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值