TowardsDataScience 博客中文翻译 2019(五百二十六)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

市场行为预测的无监督学习

原文:https://towardsdatascience.com/unsupervised-learning-to-market-behavior-forecasting-ee8f78650415?source=collection_archive---------5-----------------------

这篇文章描述了预测市场行为的技术。第二部分展示了该方法在交易策略中的应用。

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

介绍

市场数据是一个称为时间序列的序列。通常,研究人员仅使用价格数据(或资产回报)来创建预测下一个价格值、运动方向或其他产出的模型。我认为更好的方法是使用更多的数据。这个想法是试图结合多种多样的市场条件(波动性、交易量、价格变化等)。)

第一类潜在特征是价格数据的各种衍生物。第二类是体积导数的集合。

这些特征将描述比原始市场数据或简单回报更复杂的当前市场状况。

您将在本文的下一部分看到这些特性。至于建模,我们将使用隐马尔可夫模型。

隐马尔可夫模型(HMM)是一种统计马尔可夫模型,其中被建模的系统被假设为具有未观察到的(即隐藏的)状态的马尔可夫过程。观察数据是我们的市场特征,隐藏状态是我们的市场行为。

我们的目标是解释建模后的隐藏状态,并基于这些知识创建交易策略。

隐马尔可夫模型的基本图形是这样的

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

Hidden Markov Model

本文以实践为导向。要了解更多信息,你可以阅读由托默·阿米特撰写的这篇文章中的对隐马尔可夫模型的介绍。还有,我推荐从这个视频开始

特征工程和建模

我认为代码和解释的结合是深入研究的好方法。开始编码吧。

我们的图书馆

这段代码从 Quandl 下载 BTC/美元的数据

然后我们可以绘制价格和交易量数据

之后我们得到了这个数字

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

Price for BTC/USD from 01/01/2014

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

Volume for BTC/USD from 01/01/2014

现在我们已经准备好对特征工程和建模功能进行编码了。

让我们将火车时段拆分为 2018 年 1 月 1 日之前的时段。下一段代码运行特性工程并将其可视化。

之后,我们得到了五个新的时间序列和训练好的模型。

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

Feature sequences

在上面的代码中,我们还创建了 future_return 列,它为 last_return 移动了一个滞后。这是了解隐藏状态的第一把钥匙。让我们将这个值绘制成每个状态的累积和。

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

Future return cumulative sum for each state

正如我们看到的,状态#0 有下降的趋势。状态#1 没有明确的趋势。最后一个状态#2 有很强的上升趋势。这个简单的累积和 future_return 的技巧让我们理解每个状态如何对应下一个价格运动。

第二个关键是通过特征研究每个状态。之后,我们可以将这两个事件(未来运动和当前条件)联系起来。让我们为每个状态的特性编写模拟和可视化代码。

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

Feature distributions for each state

现在你可以看到每个状态是如何描述当前状态的。例如,状态#0 和#2 具有高音量偏差,这意味着这些状态经常出现在高音量上,而状态#1 出现在低音量上。此外,状态#0 和#2 通常呈现高波动性。

有趣的事实是状态#0 具有 last_returnma_ratio 的低值。大概是,状态#0 对应下行电流状态(目前)。落后的情况是状态#2。

对这两个结论的解释是

如果市场处于当前状态#0,那么在当前情况下,我们处于最不利的市场条件(第二个关键点),并且这种趋势将继续下去(第一个关键点)。

如果市场有当前状态#1,我们有趋势的不确定性。

如果市场处于当前状态#2,那么在当前情况下,我们有大部分上行市场条件(第二个关键点),并且这种趋势将继续下去(第一个关键点)。

下一行代码将训练好的模型保存到文件中。

应用

让我们试着根据这些知识来制定交易策略。我们应该从 2018 年 1 月 1 日开始测试这一策略,因为这一时期超出了样本范围。

逻辑很简单:状态#0 时短,状态#1 时无位置,状态#2 时长。

我们的战略将使用 Catalyst 框架来实现。在这篇帖子中,我演示了 Catalyst 的快速介绍。该策略将包含在单独的 py 文件中。让我们编写基本函数并包含库

主参数、模型加载都包含在初始化功能中

handle_data 函数包含的基本逻辑。该功能每分钟运行一次。主要活动是获取数据、创建特征、市场行为评估和头寸管理。

最后一个功能是附加的。我们绘制数字并打印结果。

让我们运行策略

正如我们看到的,建议的算法直接击败了基准。这种策略似乎试图抓住趋势并跟随它。策略的不利条件是没有趋势期。

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

Backtesting result

总回报:1.486611137708

索尔提诺系数:1 . 54866 . 38868688661

最大水位下降:-0.30000000001

阿尔法值:0.56725414679740467

贝塔系数:-0.1541654082608784

Alpha 为正,beta 非常接近 0(关于这些标准的定义,参见本)。下降幅度太高,但比基准下降幅度低得多。

结论

  1. 提出了基于多变性价格和交易量特征作为序列的方法。
  2. 对模型的隐藏状态进行了解释。
  3. 利用隐马尔可夫模型对 4 年的数据进行建模。
  4. 创建了简单的交易策略,用样本数据(1.5 年)进行测试,没有再培训,佣金和滑点。
  5. 该策略击败了买入并持有基准,它有正的 alpha,beta 接近于 0。
  6. 研究成果被上传到 GitHub

[## lamres/hmm _ 市场 _ 行为

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/lamres/hmm_market_behavior/tree/master)

如何提高已取得成果的方法:

  1. 向模型中添加新特征。
  2. 尝试窗口长度。
  3. 用不同数量的隐藏状态建立模型。
  4. 尝试为隐藏状态和策略中使用的规则制定新的解释。
  5. 基于一些资产创建投资组合。
  6. 添加简单的交易规则,如止盈、止损等。

这些改进有助于获得更复杂的策略结果:将压降降低到 15–20%,增加 alpha 和 sortino,增加产能。

如果你喜欢这类应用程序,你可以阅读我的文章,基于类似的方法。

最诚挚的问候,

谢尔盖

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

相似性传播算法解释

原文:https://towardsdatascience.com/unsupervised-machine-learning-affinity-propagation-algorithm-explained-d1fef85f22c8?source=collection_archive---------3-----------------------

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

https://www.pexels.com/photo/a-boy-in-beige-hoodie-smiling-beside-the-blackboard-6256070/

2007 年,布伦丹·弗雷和德尔伯特·杜克在《科学》杂志上首次发表了《亲缘关系传播》。与其他传统的聚类方法相比,相似性传播不需要您指定聚类的数量。通俗地说,在亲和力传播中,每个数据点向所有其他点发送消息,通知其目标每个目标对发送者的相对吸引力。然后,每个目标用回复来响应所有发送者,通知每个发送者它可以与该发送者相关联,因为它已经从所有其他发送者接收到消息的吸引力。发送者用消息回复目标,通知每个目标该目标对发送者的修正的相对吸引力,给定它从所有目标接收的可用性消息。消息传递过程继续进行,直到达成共识。一旦发送者与其目标之一相关联,该目标就成为该点的样本。具有相同样本的所有点被放置在相同的簇中。

算法

假设我们有以下数据集。每个参与者被表示为 5 维空间中的一个数据点。

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

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.490.7628&rep=rep1&type=pdf

相似矩阵©

除了对角线上的那些,相似性矩阵中的每个单元都是通过对参与者之间的差异的平方和求反来计算的。

如果这对你来说没有任何意义,不要烦恼,一旦浏览一个例子,它就会变得清晰。对于 Alice 和 Bob 之间的相似性,差异的平方和为(3–4)+(4–3)+(3–5)+(2–1)+(1–1)= 7。因此,相似性值是-7。

还不清楚?让我们看另一个例子。

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

我强烈推荐你自己计算一些。您应该会得到与下表相近的结果。

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

如果为对角线选择较小的值,则该算法将在少量的聚类周围收敛,反之亦然。因此,我们用-22 填充相似性矩阵的对角线元素,这是不同单元格中的最小数字。

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

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.490.7628&rep=rep1&type=pdf

责任矩阵

我们首先构建一个可用性矩阵,所有元素都设置为零。然后,我们使用以下公式计算责任矩阵中的每个单元:

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

其中 I 表示相关矩阵的行,k 表示相关矩阵的列。

比如 Bob(列)对 Alice(行)的责任是-1,就是 Bob 对 Alice 的相似度(-7)减去 Alice 的行的剩余相似度的最大值(-6)。

再次,我强烈建议你试着自己计算一些。

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

在计算完其余几对参与者的责任后,我们得出了下面的矩阵。

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

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.490.7628&rep=rep1&type=pdf

可用性矩阵(a)

我们使用单独的等式来更新可用性矩阵对角线上的元素,而不是可用性矩阵对角线外的元素。

下面的公式用于填充对角线上的元素:

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

其中 I 表示相关矩阵的行,k 表示相关矩阵的列。

本质上,该等式告诉您对该列中所有大于 0 的值求和,除了其值等于所讨论的列的那一行。例如,爱丽丝的自我可用性是爱丽丝专栏的积极责任的总和不包括爱丽丝的自我责任(10 + 11 + 0 + 0 = 21)。

还不明白?让我们再看几个例子。

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

以下等式用于更新非对角线元素:

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

换句话说,假设你试图填写 a(凯里,埃德娜)。考虑到埃德娜一栏的内容,你排除了埃德娜/埃德娜关系和卡里/埃德娜关系,并将所有剩余的积极责任加在一起。例如,Bob(列)对 Alice(行)的可用性是 Bob 的自我责任加上 Bob 的列中除 Bob 对 Alice 的责任之外的剩余积极责任之和(-15 + 0 + 0 + 0 = -15)。

我强烈建议您尝试自己计算一些单元格。

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

在计算完其余部分后,我们得到了下面的可用性矩阵。

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

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.490.7628&rep=rep1&type=pdf

标准矩阵©

标准矩阵中的每个单元只是该位置的可用性矩阵和责任矩阵的总和。

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

Bob(列)对 Alice(行)的标准值是 Bob 对 Alice 的责任和可用性之和(-1 + -15 = -16)。

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

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.490.7628&rep=rep1&type=pdf

每行的最高标准值被指定为样本。共享同一个样本的行在同一个簇中。因此在我们的例子中。Alice、Bob 和 Cary 形成一个集群,而 Doug 和 Edna 构成第二个集群。

值得注意的是,在这个例子中,变量的范围相同。然而,一般来说,变量在不同的尺度上,必须在训练前标准化。

密码

让我们跳到一些代码中。首先,导入以下库。

import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
sns.set()
from sklearn.datasets.samples_generator import make_blobs
from sklearn.cluster import AffinityPropagation

我们使用scikit-learn来生成具有良好定义的集群的数据。

X, clusters = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
plt.scatter(X[:,0], X[:,1], alpha=0.7, edgecolors='b')

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

接下来,我们初始化并训练我们的模型。

af = AffinityPropagation(preference=-50)clustering = af.fit(X)

最后,我们用不同的颜色绘制每个聚类的数据点。

plt.scatter(X[:,0], X[:,1], c=clustering.labels_, cmap='rainbow', alpha=0.7, edgecolors='b')

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

最后的想法

相似性传播是一种无监督的机器学习算法,特别适合于我们不知道最佳聚类数的问题。

使用 Python 实现时间序列异常检测的无监督机器学习方法

原文:https://towardsdatascience.com/unsupervised-machine-learning-approaches-for-outlier-detection-in-time-series-using-python-5759c6394e19?source=collection_archive---------12-----------------------

在这篇文章中,我将介绍一些我最喜欢的检测时间序列数据中异常值的方法。有许多不同的方法来检测异常数据点;为了简洁起见,我在这篇文章中只关注无监督的机器学习方法。

本文涉及的异常/异常值检测算法包括:

  1. 低通滤波器:取时间序列的居中滚动平均值,并基于 Z 分数移除异常
  2. 隔离森林
  3. 季节性极端学生化离差(S-ESD)算法
  4. 一类支持向量机(SVM)

那么什么是时间序列中的“异常”,为什么我们关心检测时间序列序列中的异常?

我经常处理时间序列数据*,数据集经历意想不到的下降或峰值、平线或相移并不罕见。这些情况中的每一种都可以称之为“异常”——与整个序列的行为相比,有些不寻常。*

出于各种原因,检测时间序列中的异常是重要的。有时,异常是某些模式的指示,如特定日期或时间内趋势的峰值或下降。其他时候,异常是“错误的”读数,这是由于仪器或仪表的错误造成的。通常,我们希望从时间序列数据中分离出异常,因为它们扭曲了“平均”行为——平均变化率、平均值、平均分布等。

本文中介绍的所有算法都有二进制输出:时间序列中的数据点要么异常,要么正常。

时间序列示例

在本文中,我们比较了几种不同的异常检测方法在单个时间序列上的结果。我们将使用的时间序列是美国墨西哥湾海岸汽油价格的每日时间序列,它是使用能源信息管理局(EIA) API 检索的。

关于使用 EIA 的免费 API 在 Python 中检索能源相关数据的更多背景知识,请查看本教程***。*****

我们使用以下 Python 代码提取并可视化时间序列:

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

为了增加趣味,我们在时间序列中加入了一些异常值。希望这些点能被异常检测算法发现。

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

Gasoline Price Time Series, with artificially generated anomalies in yellow

既然我们已经选择了我们的时间序列并添加了一些异常值,让我们在其上测试我们的异常检测算法。

简单的低通滤波器:取一个滚动平均值,并根据 Z 分数去除异常

我用来检测异常的一个最简单(但仍然非常有效)的方法如下:

  1. 实现时间序列数据的居中滚动平均
  2. 计算时间序列中每个数据点的单独 Z 值,并与滚动平均值进行比较
  3. 移除偏离滚动平均值超过特定标准偏差数的数据点(通常偏离 2 到 3 个标准偏差,但取决于数据行为)

让我们用一个例子来试试这个方法。

代码示例

如上所述,我们使用美国墨西哥湾沿岸汽油价格的时间序列作为我们的示例时间序列集。

值得注意的是,我们为低通滤波器实现的滚动平均值以为中心。这意味着长度为 x 的滚动平均值是之前 x/2 个数据点和之后 x/2 个数据点的平均值。例如,如果我们在值 t 处实施 60 点滚动平均,那么我们会发现范围在(t-30)和(t+30)之间的数据点的平均值。使用居中的滚动平均值有助于解释时间序列中两端的较大偏移。

我们使用以下代码生成低通滤波器并可视化异常:

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

Gasoline time series, color-coded by detected low-pass filter anomalies. Anomalous data points are in yellow, and normal data points are in purple.

在检查上述结果时,低通滤波器表现相当好。在添加到时间序列中的 9 个异常值中,低通滤波器成功检测到 6 个,加上其他几个看起来异常的数据点。

隔离森林

隔离森林是流行的随机森林算法的无监督扩展。隔离林的构造块是具有二元结果(是/不是离群值)的隔离树。

构建隔离林时,算法会将每个单独的数据点从所有其他数据点中分离出来。空间中的单个点越容易与所有其他点隔离,它就越有可能是异常值(因为它远离所有其他数据点)。如果一个数据点是一个插入点,它将被其他数据点紧密包围,并需要更多的分裂来隔离( 1 )。请参见下图中的插图。

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

Each line represents a split performed by the algorithm to isolate individual data points. In the first figure, X0 is an outlier, and is isolated in ~3 splits. In the second figure, Xi is an in-lier, and requires many more splits to isolate from all other data points. Image courtesy of https://www.semanticscholar.org/paper/Anomaly-Detection-through-on-line-Isolation-Forest%3A-Susto-Beghi/c321685dd03fa1a54e99b4c046950b96c3b0f040/figure/1.

关于隔离森林的更多信息,请查看福特斯的本教程

代码示例

我们再次使用汽油时间序列,但这次我们应用隔离森林算法来检测异常。我们使用 scikit-learn 包中提供的 IsolationForest()模型来构建一个模型,并在我们的数据集上测试它:

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

Gasoline time series, color-coded by detected Isolation Forest anomalies. Anomalous data points are in yellow, and normal data points are in purple.

像低通滤波器一样,隔离林检测到大多数人为产生的异常;但是,它会对更多的误报进行分类(数据点被标记为异常,而实际上并非如此)。该算法特别难以识别大的时间序列偏移(参见 2014 年末时间段作为示例)。

季节性极端学生化离差(S-ESD)算法

Twitter 的一组数据科学家最初开发了 S-ESD 算法。该算法最初的(也是最流行的)实现之一是在的“异常检测”包中。幸运的是,R 包已经被多次修改以用于 Python。

这种算法很容易理解,而且根据所用的时间序列,相当稳健。它的工作原理如下:

  1. 使用 STL(季节-趋势-黄土)分解对时间序列进行分解。
  2. ESD 算法在生成的黄土时间序列上运行,以检测异常。黄土时间序列代表系统中的噪声,在趋势和季节行为被过滤掉之后。

我们来试一个例子来论证。

代码示例

在实现 S-ESD 算法之前,让我们分解汽油价格时间序列,以了解时间序列的趋势、季节性和噪声:

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

STL Decomposition of Gulf Coast Gasoline Price Time Series, 2014-Present

在上面的代码片段中,我们以每年的频率分解时间序列。在检测异常时,我们真正关心的分解时间序列是残差时间序列(或黄土时间序列)。这个时间序列代表序列中的噪声,在考虑了季节性和趋势之后。

在分解之后,我们对剩余时间序列应用极端学生化偏离(ESD)检验来检测异常值。ESD 测试的主要优点之一是,它只需要检测异常值总数的上限;这与 Grubbs 测试形成对比,Grubbs 测试中异常值的数量必须准确声明( 2 )。

有关极端学生化偏离(ESD)算法的更多信息,请查看 此链接

在下面的代码片段中,我们对时间序列执行 S-ESD 异常检测,包括使用 ESD 的 STL 分解和异常值检测:

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

Gasoline Time Series, color coded on S-ESD anomalies, with outliers in yellow and all other data points in purple

基于上述结果,S-ESD 算法的结果并不太乐观。该算法仅成功地识别了九个产生的异常中的一个。我以前使用其他时间序列集成功地使用了这种算法,但在这个特殊的例子中似乎有些困难。

单类支持向量机(SVM)

一类 SVM 是支持向量机的无监督版本,因为它们只在一个类(“正常”类)上训练。由于数据是无标签的,单类支持向量机“推断出正常情况的性质,并从这些性质中预测哪些例子与正常例子不同”( 3 )。一类 SVM 使用一个二元函数来映射平面上的数据概率密度,高概率区域设置为+1,低概率区域设置为-1 ( 4 )。

查看 这篇由 Hsu 等人撰写的文章 提供了关于单类支持向量机的更深入的信息。

代码示例

我们再次求助于 sci kit——学习构建我们的模型;这一次,对于一等 SVM 的。我们生成几个变量插入算法中以提高性能——主要是汽油价格时间序列的中心 6 点滚动平均值。然后,我们通过 one _ class _ SVM _ anomaly _ detection()函数运行原始时间序列及其滚动平均值。在函数中,我们缩放每个变量,并训练无监督模型。最后,我们对每个数据点进行分类,并使用散点图进行可视化:

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

Gasoline time series, color-coded by detected one-class SVM anomalies. Anomalous data points are in yellow, and normal data points are in purple.

单类 SVM 表现相对较好,可以检测出 9 个人工生成的异常值中的 6 个。然而,像隔离林一样,它在序列中检测到几个假阳性。

结论

在本文中,我们比较了各种异常检测技术的结果——隔离森林、低通滤波器、一类 SVM 和 S-ESD 算法。令人惊讶的是,当并排比较结果时,性能最好的算法(至少对于本例来说)是一个简单的低通滤波器。性能最差的算法是 S-ESD 算法。

重要的是要注意,这些算法对每个单独的时间序列执行不同。仅仅因为低通滤波器在这个例子中工作得最好,并不意味着它在所有时间序列中都工作得最好。为了获得最佳结果,在最终决定使用哪种算法之前,请尝试上述所有选项。

我关于时间序列异常检测的无监督机器学习方法的教程到此结束。感谢阅读!

****关于本教程中使用的完整 Python 代码,请查看以下 Github repo:https://Github . com/kperry 2215/unsupervised _ anomaly _ detection _ time _ series

来源

  1. **T.福特斯。2018 年 4 月 4 日。隔离森林:与世隔绝的艺术。https://quantdare.com/isolation-forest-algorithm/
  2. 工程统计手册。异常值的通用 ESD 测试。https://www . ITL . NIST . gov/div 898/handbook/EDA/section 3/EDA 35h 3 . htm
  3. Azure 机器学习工作室。2019 年 5 月 5 日。单类支持向量机https://docs . Microsoft . com/en-us/azure/machine-learning/studio-module-reference/one-class-support-vector-machine
  4. 罗默·弗拉斯维尔德。2013 年 7 月 12 日。单类支持向量机简介。http://rvlasveld . github . io/blog/2013/07/12/introduction-to-one-class-support-vector-machines/

看看我的其他时间系列教程和文章:

** [## 使用 Python - Tech Rando 进行变化点检测简介

我的很多工作都大量涉及时间序列分析。我使用的一个很棒但不太为人所知的算法是…

techrando.com](https://techrando.com/2019/08/14/a-brief-introduction-to-change-point-detection-using-python/) [## 使用 Python 分析电价时间序列数据:时间序列分解和价格…

欢迎来到科技兰多博客!在今天的帖子中,我将使用能源信息管理局的 API…

techrando.com](https://techrando.com/2019/07/19/analyzing-electricity-price-time-series-data-using-python-time-series-decomposition-and-price-forecasting-using-a-vector-autoregression-var-model/)

原载于 2019 年 8 月 23 日https://techrando.com**

无监督机器学习:聚类分析

原文:https://towardsdatascience.com/unsupervised-machine-learning-clustering-analysis-d40f2b34ae7e?source=collection_archive---------0-----------------------

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

无监督学习简介

到目前为止,我们只探索了监督机器学习算法和技术来开发模型,其中数据具有先前已知的标签。换句话说,我们的数据有一些带有特定值的目标变量,我们用它们来训练我们的模型。

然而,在处理现实世界的问题时,大多数时候,数据不会带有预定义的标签,因此我们希望开发能够正确分类这些数据的机器学习模型,通过自己找到特征中的一些共性,用于预测新数据的类别。

无监督学习分析过程

在开发无监督学习模型时,我们将遵循的整个过程可以总结在下表中:

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

无监督学习的主要应用有:

  • 利用共享属性分割数据集。
  • 检测不适合任何组的异常。
  • 通过聚合具有相似属性的变量来简化数据集。

总之,主要目标是研究数据的内在(通常是隐藏的)结构。

这种技术可以浓缩为无监督学习试图解决的两种主要类型的问题。这些问题是:

  • 使聚集
  • 降维

在整篇文章中,我们将关注聚类问题,并将在以后的文章中讨论降维。

聚类分析

基本上,聚类的目标是在数据的元素中找到不同的组。为此,聚类分析算法查找数据中的结构,以便同一个聚类(或组)的元素彼此之间比来自不同聚类的元素更相似。

以一种可视化的方式:想象我们有一个电影的数据集,想要对它们进行分类。我们有以下电影评论:

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

机器学习模型将能够推断出有两个不同的类别,而无需从数据中了解任何其他信息。

这些无监督学习算法具有令人难以置信的广泛应用,并且对于解决现实世界的问题非常有用,例如异常检测、推荐系统、文档分组或者基于购买发现具有共同兴趣的客户。

一些最常见的聚类算法,以及将在本文之外探讨的算法有:

  • k 均值
  • 层次聚类
  • 基于密度的扫描聚类(DBSCAN)
  • 高斯聚类模型

k 均值聚类

K-Means 算法非常容易实现,而且计算效率非常高。这些是解释它们为什么如此受欢迎的主要原因。但是当处理不具有球形分布形状的组时,它们不太适合于识别类。

K-Means 算法的目标是找到彼此之间具有高度相似性的数据点并将其分组。就算法而言,这种相似性被理解为数据点之间距离的反义词。数据点越接近,它们就越相似,并且更有可能属于同一个聚类。

关键概念

  • 平方欧几里德距离

K-Means 中最常用的距离是平方欧几里德距离。在 m 维空间中的两点 x 和 y 之间的距离的一个例子是:

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

这里, j 是样本点 x 和 y的第j维(或特征列)

  • 集群惯性

聚类惯性是聚类上下文中误差平方和的名称,表示如下:

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

其中 μ(j) 是聚类 *j,*的质心,如果样本 x(i) 在聚类 j 中,则 w(i,j) 为 1,否则为 0。

K-Means 可以理解为一种算法,它将尝试最小化聚类惯性因子。

算法步骤

  1. 首先,我们需要选择 k,我们希望被发现的集群的数量。
  2. 然后,该算法将随机选择每个聚类的质心。
  3. 将每个数据点分配到最近的质心(使用欧几里德距离)。
  4. 将计算群集惯性。
  5. 新的质心将被计算为属于上一步质心的点的平均值。换句话说,通过计算每个聚类中心的数据点的最小二次误差,将中心移向该点
  6. 回到步骤 3。

K-均值超参数

  • 簇的数量:要生成的簇和质心的数量。
  • 最大迭代次数:单次运行的算法。
  • Number initial:使用不同质心种子运行算法的次数。就惯性而言,最终结果将是所定义的连续运行次数的最佳输出。

K 均值的挑战

  • 任何固定训练集的输出不会总是相同的,因为初始质心是随机设置的,这将影响整个算法过程。
  • 如前所述,由于欧几里德距离的性质,当处理采用非球形形状的聚类时,它不是合适的算法。

应用 K 均值时需要考虑的要点

  • 必须在相同的尺度上测量要素,因此可能有必要执行 z 分数标准化或最大-最小缩放。
  • 在处理分类数据时,我们将使用 get dummies 函数。
  • 探索性数据分析(EDA)非常有助于对数据进行概述,并确定 K-Means 是否是最合适的算法。
  • 当有大量的列时,minibatch 方法非常有用,但是它不太准确。

如何选择合适的 K 数

选择正确的聚类数是 K-Means 算法的关键点之一。有一些方法可以找到这个数字:

  • 领域知识
  • 商业决策
  • 肘法

由于与数据科学的动机和性质一致,肘方法是首选方法,因为它依赖数据支持的分析方法来做出决策。

肘法

肘方法用于确定数据集中聚类的正确数量。它的工作原理是绘制 K 的递增值与使用该 K 时获得的总误差的关系图。

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

目标是找到对于每个聚类不会显著增加方差的 k

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

在这种情况下,我们将选择弯头所在的 k=3。

K-Means 局限性

虽然 K-Means 是一个很好的聚类算法,但当我们预先知道准确的聚类数,并且处理球形分布时,它是最有用的。

下图显示了如果我们在每个数据集中使用 K-means 聚类,即使我们事先知道准确的聚类数,我们会得到什么:

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

将 K-Means 算法作为基准来评估其他聚类方法的性能是很常见的。

层次聚类

层次聚类是基于原型的聚类算法的替代方法。层次聚类的主要优点是我们不需要指定聚类的数量,它会自己找到。此外,它还能够绘制树状结构。树形图是二进制层次聚类的可视化。

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

融合在底部的观察结果是相似的,而融合在顶部的观察结果则完全不同。对于树形图,结论是根据纵轴的位置而不是横轴得出的。

等级聚类的种类

这种类型的聚类有两种方法:聚合和分裂。

  • Divisive:这种方法首先将所有数据点聚集在一个单独的集群中。然后,它会迭代地将聚类分成更小的聚类,直到每个聚类只包含一个样本。
  • 凝聚:这种方法从每个样本是一个不同的聚类开始,然后通过彼此更接近的样本来合并它们,直到只有一个聚类。

单联动&全联动

这些是用于凝聚层次聚类的最常用算法。

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

  • 单键

作为一种凝聚算法,单链从假设每个样本点是一个簇开始。然后,它计算每对聚类的最相似成员之间的距离,并合并最相似成员之间的距离最小的两个聚类。

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

  • 完全连锁

虽然与它的兄弟(单链)相似,但它的原理完全相反,它比较一对集群中最不相似的数据点来执行合并。

层次聚类的优势

  • 由此产生的层次结构表示可以提供很多信息。
  • 树形图提供了一种有趣且信息丰富的可视化方式。
  • 当数据集包含真正的层次关系时,它们特别有用。

层次聚类的缺点

  • 它们对异常值非常敏感,当异常值出现时,模型性能会显著下降。
  • 从计算角度来说,它们非常昂贵。

基于密度的噪声应用空间聚类(DBSCAN)

带噪声应用程序的基于密度的空间聚类,或 DBSCAN,是另一种对正确识别数据中的噪声特别有用的聚类算法。

DBSCAN 分配标准

它基于多个具有指定半径ε的点,每个数据点都有一个特殊的标签。分配该标签的过程如下:

  • 它是指定数量(最小点数)的相邻点。如果有这个最小点数的点落在ε半径内,将指定一个核心点。
  • 边界点将落在核心点的ε半径内,但其邻域数将少于 MinPts 数。
  • 每隔一个点将是噪声点。

DBSCAN 算法

该算法遵循以下逻辑:

  1. 确定一个核心点,并为每个核心点或每个连接的核心点组(如果它们符合核心点的标准)分组。
  2. 确定边界点并将其分配给各自的核心点。

下图很好地总结了这个过程和注释符号。

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

DBSCAN 与 K 均值聚类

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

DBDSCAN 的优势

  • 我们不需要指定集群的数量。
  • 簇可以采用的形状和大小具有高度的灵活性。
  • 识别和处理噪声数据和异常值是非常有用的。

DBSCAN 缺点

  • 它在处理两个集群可达的边界点时面临困难。
  • 它找不到不同密度的井丛。

高斯混合模型(GMM)

高斯混合模型是一种概率模型,它假设所有样本都是由有限个高斯分布和未知参数混合而成的。

它属于软聚类算法组,其中每个数据点将属于数据集中存在的每个聚类,但是每个聚类具有不同的成员级别。这种隶属关系被指定为属于某一类的概率,范围从 0 到 1。

例如,高亮显示的点将同时属于聚类 A 和聚类 B,但由于其与聚类 A 的接近性,因此属于聚类 A 的成员更高。

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

GMM 是我们将在本系列中学习的最高级的聚类方法之一,它假设每个聚类遵循一个概率分布,该分布可以是高斯分布或正态分布。它是 K-均值聚类的推广,包括关于数据的协方差结构以及潜在高斯中心的信息。

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

一维 GMM 分布

GMM 将在数据集中搜索高斯分布并混合它们。

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

二维中的 GMM

当多元分布如下所示时,对于 de 数据集分布的每个轴,平均中心应为+ σ。

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

GMM 算法

这是一种期望最大化算法,其过程可以概括如下:

  1. 初始化 K 高斯分布。它通过(平均值)和σ(标准差)值来实现这一点。它们可以取自数据集(朴素方法)或通过应用 K-Means。
  2. 对数据进行软聚类:这是“期望”阶段,在此阶段,所有的数据点将被分配给每个具有各自隶属级别的聚类。
  3. 重新估计高斯分布:这是“最大化”阶段,在此阶段检查期望值,并使用期望值计算高斯分布的新参数:new 和σ。
  4. 评估数据的对数似然性以检查收敛性。对数似然性越高,我们创建的模型的混合物就越有可能符合我们的数据集。这是最大化的函数。
  5. 从步骤 2 开始重复,直到收敛。

GMM 的优势

  • 这是一种软聚类方法,它将样本成员分配给多个聚类。这一特性使其成为学习混合模型的最快算法
  • 集群的数量和形状具有高度的灵活性。

GMM 的缺点

  • 它对初始值非常敏感,这将极大地影响它的性能。
  • GMM 可能收敛到局部最小值,这将是次优解。
  • 当每个混合物没有足够的点时,该算法发散并找到具有无限可能性的解,除非我们人工地调整数据点之间的协方差。

聚类验证

聚类验证是对聚类结果进行客观定量评估的过程。我们将通过应用聚类验证指数来进行验证。有三个主要类别:

外部指数

这些是我们在原始数据被标记时使用的评分方法,这在这类问题中并不常见。我们将把一个聚类结构与预先知道的信息进行匹配。

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

使用最多的指数是调整后的兰德指数。

  • 调整后的€兰德指数[-1,1]

为了理解它,我们应该首先定义它的组成部分:

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

  • a:是在 C 和 K 中的同一个簇中的点数
  • b:是在 C 和 k 中不同簇中的点数。
  • n =样本总数

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

ARI 可以得到范围从-1 到 1 的值。该值越高,与原始数据的匹配程度越高。

内部验证指标

在无监督学习中,我们将处理未标记的数据,这是内部索引更有用的时候。

最常见的指标之一是轮廓系数。

  • 轮廓系数:

每个数据点都有一个轮廓系数。

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

  • a =到同一组中其他样品 I 的平均距离
  • b =到最近的相邻聚类中的其他样本 I 的平均距离

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

轮廓系数(SC)的值可以从-1 到 1。值越高,选择的 K 越好。如果我们超过了理想的 K 值,就会比我们低于理想的 K 值受到更多的惩罚。

它只适用于某些算法,如 K-Means 和层次聚类。它不适合与 DBSCAN 一起工作,我们将使用 DBCV。

结论

我们首先介绍了无监督学习和主要的聚类算法。

在下一篇文章中,我们将完成一个实现,作为构建 K-means 模型的示例,并回顾和实践所解释的概念。

敬请期待!

从头开始实现谱聚类算法

原文:https://towardsdatascience.com/unsupervised-machine-learning-spectral-clustering-algorithm-implemented-from-scratch-in-python-205c87271045?source=collection_archive---------1-----------------------

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

https://www.pexels.com/photo/back-view-of-a-student-answering-a-problem-on-the-chalkboard-8197497/

谱聚类是一种流行的无监督机器学习算法,其性能往往优于其他方法。此外,谱聚类实现起来非常简单,并且可以通过标准的线性代数方法有效地解决。在谱聚类中,确定哪些点属于哪个聚类的是相似性,而不是绝对位置(即 k 均值)。后者在处理数据形成复杂形状的问题时特别有用。

算法

该算法可以分为 4 个基本步骤。

  1. 构建相似度图
  2. 确定邻接矩阵 W、度矩阵 D 和拉普拉斯矩阵 L
  3. 计算矩阵 L 的特征向量
  4. 使用第二小特征向量作为输入,训练 k-means 模型并使用它来对数据进行分类

密码

在下一节中,我们将从头开始实现谱聚类。我们将需要以下库。

import numpy as np
float_formatter = lambda x: "%.3f" % x
np.set_printoptions(formatter={'float_kind':float_formatter})
from sklearn.datasets.samples_generator import make_circles
from sklearn.cluster import SpectralClustering, KMeans
from sklearn.metrics import pairwise_distances
from matplotlib import pyplot as plt
import networkx as nx
import seaborn as sns
sns.set()

通常,数据集由样本(行)及其要素(列)组成。但是,谱聚类算法只能应用于连接节点的图。

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

因此,我们必须对数据进行转换,以便从由行和列组成的表格转换成图形。假设我们有以下数据集。我们可以清楚地看到,这些数据可以分成三组。

X = np.array([
    [1, 3], [2, 1], [1, 1],
    [3, 2], [7, 8], [9, 8],
    [9, 9], [8, 7], [13, 14],
    [14, 14], [15, 16], [14, 15]
])plt.scatter(X[:,0], X[:,1], alpha=0.7, edgecolors='b')
plt.xlabel('Weight')
plt.ylabel('Height')

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

首先,我们构造相似性矩阵,一个 NxN 矩阵,其中 N 是样本的数量。我们用每一对点之间的欧几里德距离填充单元格。

然后,我们通过复制相似性矩阵的内容来创建邻接矩阵,并且仅在这一次,我们设置阈值,使得如果距离大于预定义的限制,则我们将值设置为 0,否则设置为 1。

邻接矩阵可以用来构建一个图。如果邻接矩阵的单元格中有 1,那么我们在列和行的节点之间画一条边。

W = pairwise_distances(X, metric="euclidean")
vectorizer = np.vectorize(lambda x: 1 if x < 5 else 0)
W = np.vectorize(vectorizer)(W)
print(W)

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

在本教程的剩余部分,我们将使用networkx库来可视化图形。

def draw_graph(G):
    pos = nx.spring_layout(G)
    nx.draw_networkx_nodes(G, pos)
    nx.draw_networkx_labels(G, pos)
    nx.draw_networkx_edges(G, pos, width=1.0, alpha=0.5)

首先,我们随机生成一个图并打印它的邻接矩阵。

G = nx.random_graphs.erdos_renyi_graph(10, 0.5)draw_graph(G)W = nx.adjacency_matrix(G)
print(W.todense())

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

请注意这些节点是如何形成单个组件的(即,所有其他节点都可以从一个给定的节点到达)。

一旦我们建立了邻接矩阵,我们就建立了度矩阵。对于度矩阵的每一行,我们通过对邻接矩阵中相应行的所有元素求和来沿着对角线填充单元。

然后,我们通过从度矩阵中减去邻接矩阵来计算拉普拉斯矩阵。

# degree matrix
D = np.diag(np.sum(np.array(W.todense()), axis=1))
print('degree matrix:')
print(D)# laplacian matrix
L = D - W
print('laplacian matrix:')
print(L)

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

一旦我们有了拉普拉斯矩阵,我们就可以利用它的一个特殊属性来分类我们的数据。

  • 若图(W)有 K 个连通分量,则 L 有 K 个特征值为 0 的特征向量。

因此,由于在我们当前的例子中,我们只有一个组件,一个特征值将等于 0。

e, v = np.linalg.eig(L)# eigenvalues
print('eigenvalues:')
print(e)# eigenvectors
print('eigenvectors:')
print(v)

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

fig = plt.figure()ax1 = plt.subplot(121)
plt.plot(e)
ax1.title.set_text('eigenvalues')i = np.where(e < 10e-6)[0]
ax2 = plt.subplot(122)
plt.plot(v[:, i[0]])fig.tight_layout()
plt.show()

正如我们所见,在 10 个特征值中,有一个等于 0。

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

让我们看另一个例子。上图由两部分组成。因此,2 个特征值等于 0。

G = nx.Graph()
G.add_edges_from([
    [1, 2],
    [1, 3],
    [1, 4],
    [2, 3],
    [2, 7],
    [3, 4],
    [4, 7],
    [1, 7],
    [6, 5],
    [5, 8],
    [6, 8],
    [9, 8],
    [9, 6]
])draw_graph(G)W = nx.adjacency_matrix(G)
print(W.todense())

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

# degree matrix
D = np.diag(np.sum(np.array(W.todense()), axis=1))
print('degree matrix:')
print(D)# laplacian matrix
L = D - W
print('laplacian matrix:')
print(L)

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

e, v = np.linalg.eig(L)# eigenvalues
print('eigenvalues:')
print(e)# eigenvectors
print('eigenvectors:')
print(v)

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

fig = plt.figure(figsize=[18, 6])ax1 = plt.subplot(131)
plt.plot(e)
ax1.title.set_text('eigenvalues')i = np.where(e < 10e-6)[0]
ax2 = plt.subplot(132)
plt.plot(v[:, i[0]])
ax2.title.set_text('first eigenvector with eigenvalue of 0')ax3 = plt.subplot(133)
plt.plot(v[:, i[1]])
ax3.title.set_text('second eigenvector with eigenvalue of 0')

如果我们仔细看看每个特征向量的图,我们可以清楚地看到,前 5 个节点映射到相同的值,其他 5 个节点映射到另一个值。我们可以利用这一事实将节点分为两类。

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

让我们看一个稍微复杂一点的例子。前面的图是由一个单独的部分组成的。然而,看起来我们有两节课。

G = nx.Graph()
G.add_edges_from([
    [1, 2],
    [1, 3],
    [1, 4],
    [2, 3],
    [3, 4],
    [4, 5],
    [1, 5],
    [6, 7],
    [7, 8],
    [6, 8],
    [6, 9],
    [9, 6],
    [7, 10],
    [7, 2]
])draw_graph(G)W = nx.adjacency_matrix(G)
print(W.todense())

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

# degree matrix
D = np.diag(np.sum(np.array(W.todense()), axis=1))
print('degree matrix:')
print(D)# laplacian matrix
L = D - W
print('laplacian matrix:')
print(L)

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

e, v = np.linalg.eig(L)# eigenvalues
print('eigenvalues:')
print(e)# eigenvectors
print('eigenvectors:')
print(v)

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

fig = plt.figure(figsize=[18, 6])ax1 = plt.subplot(131)
plt.plot(e)
ax1.title.set_text('eigenvalues')i = np.where(e < 0.5)[0]
ax2 = plt.subplot(132)
plt.plot(v[:, i[0]])ax3 = plt.subplot(133)
plt.plot(v[:, i[1]])
ax3.title.set_text('second eigenvector with eigenvalue close to 0')

因为我们只有一个分量,所以只有一个特征值等于 0。然而,如果我们看看第二小的特征值,我们仍然可以观察到两类之间的区别。如果我们画一条横线,我们就能正确地对节点进行分类。

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

让我们看另一个例子。同样,图将由单个组件组成,但这一次,看起来节点应该放在三个容器中的一个。

G = nx.Graph()
G.add_edges_from([
    [1, 2],
    [1, 3],
    [1, 4],
    [2, 3],
    [3, 4],
    [4, 5],
    [1, 5],
    [6, 7],
    [7, 8],
    [6, 8],
    [6, 9],
    [9, 6],
    [7, 10],
    [7, 2],
    [11, 12],
    [12, 13],
    [7, 12],
    [11, 13]
])draw_graph(G)W = nx.adjacency_matrix(G)
print(W.todense())

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

# degree matrix
D = np.diag(np.sum(np.array(W.todense()), axis=1))
print('degree matrix:')
print(D)# laplacian matrix
L = D - W
print('laplacian matrix:')
print(L)

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

e, v = np.linalg.eig(L)# eigenvalues
print('eigenvalues:')
print(e)# eigenvectors
print('eigenvectors:')
print(v)

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

fig = plt.figure(figsize=[18, 6])ax1 = plt.subplot(221)
plt.plot(e)
ax1.title.set_text('eigenvalues')i = np.where(e < 0.5)[0]
ax2 = plt.subplot(222)
plt.plot(v[:, i[0]])ax3 = plt.subplot(223)
plt.plot(v[:, i[1]])
ax3.title.set_text('second eigenvector with eigenvalue close to 0')ax4 = plt.subplot(224)
plt.plot(v[:, i[2]])
ax4.title.set_text('third eigenvector with eigenvalue close to 0')fig.tight_layout()

因为我们只有 1 个分量,所以 1 个特征值等于 0。但是,我们可以再次使用第二小的特征值来计算出哪个节点应该放在哪个类别中。

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

在实践中,我们使用 k-means 根据节点在特征向量中的对应值对节点进行分类。

U = np.array(v[:, i[1]])km = KMeans(init='k-means++', n_clusters=3)km.fit(U)km.labels_

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

接下来,让我们使用 scitkit-learn 的实现来比较 k-means 和谱聚类。假设我们的数据在绘制时采用了以下形状。

X, clusters = make_circles(n_samples=1000, noise=.05, factor=.5, random_state=0)
plt.scatter(X[:,0], X[:,1])

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

当使用 k-means 时,我们得到以下结果。

km = KMeans(init='k-means++', n_clusters=2)km_clustering = km.fit(X)plt.scatter(X[:,0], X[:,1], c=km_clustering.labels_, cmap='rainbow', alpha=0.7, edgecolors='b')

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

相反,当使用谱聚类时,我们将每个圆放在自己的聚类中。

sc = SpectralClustering(n_clusters=2, affinity='nearest_neighbors', random_state=0)sc_clustering = sc.fit(X)plt.scatter(X[:,0], X[:,1], c=sc_clustering.labels_, cmap='rainbow', alpha=0.7, edgecolors='b')

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

最后的想法

与 k-means 相反,谱聚类考虑了数据点的相对位置。

使用 LDA 主题模型作为分类模型输入

原文:https://towardsdatascience.com/unsupervised-nlp-topic-models-as-a-supervised-learning-input-cf8ee9e5cf28?source=collection_archive---------2-----------------------

预测未来 Yelp 评论情绪

主题建模概述

自然语言处理中的主题建模旨在发现文档中隐藏的语义结构。它们是概率模型,可以帮助你梳理大量的原始文本,并以一种无人监管的方式将相似的文档分组在一起。

这篇文章特别关注潜在狄利克雷分配(LDA ),这是一种在 2000 年提出的用于群体遗传学的技术,并由 ML-hero 吴恩达等人在 2003 年独立重新发现。LDA 指出,语料库中的每个文档都是固定数量的主题的组合。一个主题具有生成各种单词的概率,其中单词是语料库中所有观察到的单词。这些“隐藏的”主题随后根据单词共现的可能性浮出水面。形式上,这是贝叶斯推理问题[1]。

LDA 输出

一旦 LDA 主题建模应用于一组文档,您就能够看到组成每个隐藏主题的单词。在我的例子中,我使用 Yelp 数据集[2]在 2016 年从 Yelp 餐馆中提取了 10 万条评论。以下是通过 LDA 发现的两个主题示例:

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

你可以看到,第一个主题组似乎已经识别出负面汉堡评论的单词共现,第二个主题组似乎已经识别出正面的意大利餐馆体验。第三个话题不是很明确,但似乎总的来说是关于可怕的、干咸的食物。

将无监督输出转换为有监督问题

我更感兴趣的是看看这种隐藏的语义结构(非监督生成的)是否可以转换成用于监督分类问题。假设我只训练了一个 LDA 模型来找到上述的 3 个主题。训练后,我可以收集所有 10 万条评论,并查看每条评论的主题分布。换句话说,一些文档可能是 100%的主题 1,其他文档可能是主题 1/2/3 的 33%/33%/33%,等等。该输出只是显示分布的每个评论的向量。这里的想法是测试隐藏语义信息的每次评论的分布是否可以预测积极和消极的情绪。

项目目标

介绍完毕后,我的目标是:

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

具体来说:

  1. 在 2016 年的 100,000 条餐厅评论上训练 LDA 模型
  2. 使用 LDA 模型获取每个评论的主题分布
  3. 将主题分布直接用作监督分类模型(逻辑回归、SVC 等)中的特征向量,并获得 F1 分数。
  4. 使用相同的 2016 年 LDA 模型获得 2017 年的主题分布(LDA 模型没有看到这个数据!)
  5. 对 2017 年向量再次运行监督分类模型,看看这是否一般化。

如果在看不见的数据上的监督 F1 分数一般化,那么我们可以假设 2016 主题模型已经识别了在这个餐馆评论领域中随着时间持续存在的潜在语义结构。

数据准备

更新(9/23/19):我给的 Repo 添加了一个自述文件,展示了如何使用源数据创建一个 MongoDB。我还包含了一个预处理脚本,它将允许你创建我在下面使用的精确的训练和测试数据帧。然而,我意识到这可能需要大量的工作,所以我还在这里的目录中包含了我的训练和测试数据帧的 pickle 文件。这将允许您直接跟踪回购中的笔记本,即这里的和这里的。如果你只想知道重点/要点,我会在这篇博文的剩余部分用代码片段指出所有的关键点。

LDA 预处理

我使用了非常棒的 gensim 库来创建评论的二元表示并运行 LDA。Gensim 的 LDA 实现需要作为稀疏向量进行审查。方便的是,gensim 还提供了将 NumPy 密集矩阵或 scipy 稀疏矩阵转换成所需形式的便利实用程序。

我将展示如何使用 gensim 函数获得必要的表示。我从 pandas DataFrame 开始,它在一个名为'text’的列中包含每个评论的文本,这个列可以被提取到一个字符串列表的列表中,其中每个列表代表一个评论。这是我下面例子中名为words的对象:

from nltk.corpus import stopwords
stop_words = stopwords.words('english')
stop_words.extend(['come','order','try','go','get','make','drink','plate','dish','restaurant','place','would','really','like','great','service','came','got']) def remove_stopwords(texts):
    out = [[word for word in simple_preprocess(str(doc))
            if word not in stop_words]
            for doc in texts]
    return outdef bigrams(words, bi_min=15, tri_min=10):
    bigram = gensim.models.Phrases(words, min_count = bi_min)
    bigram_mod = gensim.models.phrases.Phraser(bigram)
    return bigram_moddef get_corpus(df):
    df['text'] = strip_newline(df.text)
    words = list(sent_to_words(df.text))
    words = remove_stopwords(words)
    bigram_mod = bigrams(words)
    bigram = [bigram_mod[review] for review in words]
    id2word = gensim.corpora.Dictionary(bigram)
    id2word.filter_extremes(no_below=10, no_above=0.35)
    id2word.compactify()
    corpus = [id2word.doc2bow(text) for text in bigram]

    return corpus, id2word, bigramtrain_corpus, train_id2word, bigram_train = get_corpus(rev_train)

为了简洁起见,我在这篇文章中省略了几个额外的预处理步骤(标点、换行等)。

这个代码块中实际上有两个关键项目:

  1. Gensim 的短语类允许您将相关短语分组到 LDA 的一个令牌中。例如,请注意,在这篇文章开头找到的主题列表中, ice_cream 被列为单个标记。因此,bigram = [bigram_mod[review] for review in words]这一行的输出是一个列表列表,其中每个列表代表一篇评论,每个列表中的字符串都是单字和双字的混合。这是因为我们所做的是将bigram_mod短语建模模型应用于每个评审。
  2. 一旦你有了一元和二元的列表,你就可以把它传递给 gensim 的 Dictionary 类。这将为每个评论输出每个单词的词频计数。我发现,当我额外做了一些处理来删除语料库中最常见和最罕见的单词时,我用 LDA 得到了最好的结果,如上面代码块的第 21 行所示。最后,下面是doc2bow() 正在做的事情,来自他们的官方例子【3】:

函数*doc2bow()*简单地计算每个不同单词的出现次数,将单词转换为整数单词 id,并将结果作为稀疏向量返回。稀疏向量*[(0, 1), (1, 1)]*因此读作:在“人机交互”文档中,计算机(id 0)和人类(id 1)这两个词出现一次;其他十个词典单词(隐式地)零次出现。”

上面的第 23 行给出了 LDA 所需的表示中的语料库。

为了举例说明我们正在处理的文本类型,这里有一个 Yelp 评论的快照:

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

选择 LDA 的主题数量

为了训练一个 LDA 模型,你需要在你的语料库中提供一个固定的假设数量的主题。有很多方法可以解决这个问题:

  1. 用不同数量的主题在你的语料库上运行 LDA,看看每个主题的单词分布是否合理。
  2. 检查你的 LDA 模型的一致性分数,并有效地网格搜索以选择最高的一致性[4]。
  3. 创建一些具有不同主题值的 LDA 模型,然后查看这些模型在监督分类模型训练中的表现。这是我的目标,因为我的最终目标是看看主题分布是否有预测价值。

其中:我根本不相信#1 是一种方法。在这种情况下,我有什么资格说什么是明智的,什么是不明智的?我依靠 LDA 来识别 100,000 个文档的潜在主题表示,它可能不一定是直观的。对于#2:我和一些前 NLP 专业人士交谈过,他们劝我不要依赖基于他们行业经验的一致性分数。方法#3 对我的目的来说是合理的,但是现实情况是,即使我使用的是 16GB 的 8 核 AWS 实例,LDA 也需要花费大量的时间来训练。

因此,我想到了一个我认为相当新颖的想法——至少,我还没有在网上或报纸上看到任何人这样做:

Gensim 还提供了一个分层的狄利克雷过程(HDP)类[5]。HDP 类似于 LDA,只是它试图从数据中学习正确的主题数量;也就是说,你不需要提供固定数量的主题。我想我应该在我的 100,000 条评论上运行几次 HDP,看看它正在学习的主题数量。在我的情况下,这总是 20 个主题,所以我去了。

为了对 HDP 有一个直观的感受:我在网上找到了一些资料,说它最类似于中国餐馆的流程。埃德温·陈在这里【6】对此做了精辟的解释,在【7】在这里做了漂亮的形象化处理。这是来自[7]的视觉化图像:

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

在这个例子中,我们需要给一个主题分配 8 分。有 3/8 的概率 8 将到达话题 C1,有 4/8 的概率 8 将到达话题 C2,有 1/8 的概率一个新话题 C3 将被创建。通过这种方式,发现了许多主题。所以一个集群越大,就越有可能有人加入这个集群。我觉得这和其他为 LDA 选择固定主题号的方法一样合理。如果任何有较重贝叶斯推理背景的人对此有想法,请权衡!

更新[2020 年 4 月 13 日] — 爱德华多·科罗纳多通过评论提供了一些关于 HDP 的更精确的信息:

“的确,HDPs 的非参数特性允许我们从数据中学习主题,但是 Dirichlet 过程混合物已经做到了这一点。HDPs 的主要优势是它们允许不同的语料库(组)在建模时共享统计优势——在这种情况下,共享潜在无限主题的公共集合。所以它是狄利克雷过程混合物的一个扩展。”

创建 LDA 模型

下面是用 Gensim 运行 LDA 的代码:

import gensim

with warnings.catch_warnings():
    warnings.simplefilter('ignore')
    lda_train = gensim.models.ldamulticore.LdaMulticore(
                           corpus=train_corpus,
                           num_topics=20,
                           id2word=train_id2word,
                           chunksize=100,
                           workers=7, # Num. Processing Cores - 1
                           passes=50,
                           eval_every = 1,
                           per_word_topics=True)
    lda_train.save('lda_train.model')

通过打开eval_every标志,我们能够以块的形式处理语料库:在我的例子中,100 个文档的块在收敛方面表现得相当好。遍数是对整个语料库的单独遍数。

完成后,您可以查看组成每个主题的单词,如下所示:

lda_train.print_topics(20, num_words=15)[:10]

有了这段代码,你会看到 20 个主题中的 10 个,以及每个主题的 15 个热门词汇。

将主题转换为特征向量

现在有趣的部分来了。我们将使用 LDA 模型来获取每篇评论的这 20 个主题的分布。这 20 个向量将是我们监督分类的特征向量,监督学习的目标是确定积极或消极的情绪。

注意,我认为这种使用主题模型向量的监督分类方法并不常见。当我这么做的时候,我不知道网上有人尝试过这个例子,尽管后来当我完成时,我发现了这篇在 2008 年完成的论文。请让我知道是否有其他的例子!

最终目标不仅是看看这在当前数据的训练/测试 CV 分割中表现如何,而且是这些主题是否触及了一些基本的东西,这些基本的东西转化为未来看不见的测试数据(在我的情况下,是一年后的数据)。

以下是我为每篇评论获取特征向量的方法:

train_vecs = []
for i in range(len(rev_train)):
    top_topics = (
        lda_train.get_document_topics(train_corpus[i],
                                      minimum_probability=0.0)
    ) topic_vec = [top_topics[i][1] for i in range(20)]
    topic_vec.extend([rev_train.iloc[i].real_counts])
    topic_vec.extend([len(rev_train.iloc[i].text)])
    train_vecs.append(topic_vec)

key bit 在第 3 行使用minimum_probability=0.0。这确保了我们能够捕捉到某些主题中某篇评论的呈现率为 0%的情况,而每篇评论的呈现率加起来将达到 100%。

第 5 行和第 6 行是我添加的两个手工设计的特性。

因此,用于监督分类审查的单个观察现在看起来像这样:

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

前 20 个项目代表每个评论的 20 个主题的分布。

训练监督分类器

我们现在准备好训练了!在这里,我使用了 100,000 条 2016 年餐厅评论及其主题-模型分布特征向量+两个手工设计的特征:

X = np.array(train_vecs)
y = np.array(rev_train.target)

kf = KFold(5, shuffle=True, random_state=42)
cv_lr_f1, cv_lrsgd_f1, cv_svcsgd_f1,  = [], [], []

for train_ind, val_ind in kf.split(X, y):
    # Assign CV IDX
    X_train, y_train = X[train_ind], y[train_ind]
    X_val, y_val = X[val_ind], y[val_ind]

    # Scale Data
    scaler = StandardScaler()
    X_train_scale = scaler.fit_transform(X_train)
    X_val_scale = scaler.transform(X_val)

    # Logisitic Regression
    lr = LogisticRegression(
        class_weight= 'balanced',
        solver='newton-cg',
        fit_intercept=True
    ).fit(X_train_scale, y_train)

    y_pred = lr.predict(X_val_scale)
    cv_lr_f1.append(f1_score(y_val, y_pred, average='binary'))

    # Logistic Regression SGD
    sgd = linear_model.SGDClassifier(
        max_iter=1000,
        tol=1e-3,
        loss='log',
        class_weight='balanced'
    ).fit(X_train_scale, y_train)

    y_pred = sgd.predict(X_val_scale)
    cv_lrsgd_f1.append(f1_score(y_val, y_pred, average='binary'))

    # SGD Modified Huber
    sgd_huber = linear_model.SGDClassifier(
        max_iter=1000,
        tol=1e-3,
        alpha=20,
        loss='modified_huber',
        class_weight='balanced'
    ).fit(X_train_scale, y_train)

    y_pred = sgd_huber.predict(X_val_scale)
    cv_svcsgd_f1.append(f1_score(y_val, y_pred, average='binary'))

print(f'Logistic Regression Val f1: {np.mean(cv_lr_f1):.3f} +- {np.std(cv_lr_f1):.3f}')
print(f'Logisitic Regression SGD Val f1: {np.mean(cv_lrsgd_f1):.3f} +- {np.std(cv_lrsgd_f1):.3f}')
print(f'SVM Huber Val f1: {np.mean(cv_svcsgd_f1):.3f} +- {np.std(cv_svcsgd_f1):.3f}')

关于这一点有几点需要注意:

  1. 我找到了标准逻辑回归、对数损失随机梯度下降和修正 Huber 损失随机梯度下降之间的比较。
  2. 我正在运行一个 5 重 CV,因此在每次运行中,1/5 的评论作为验证数据,另外 4/5 是训练数据。每次折叠都重复这一过程,最后对 f1 得分结果进行平均。
  3. 我的班级不平衡。特别是,在 Yelp 评论数据集中,4 星和 5 星评论的数量不成比例。模型中的class_weight='balanced'线近似于欠采样,以对此进行校正。这一选择的理由见[9]。
  4. 我还将分析限制在数据集中总评论数超过 25%的餐馆。这更多是为了加快速度,因为最初的数据集大约有 400 多万条评论。

2016 年培训结果

以下是 f1 得分结果:

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

我将首先使用逻辑回归分析较低的. 53 和. 62 f1 分数。当我开始训练时,我试图预测个人评价:1、2、3、4 或 5 星。如你所见,这并不成功。我对最初的. 53 分有点气馁,所以回去检查我最初的 EDA 图表,看看我是否能注意到数据中的任何东西。我之前运行过这个图表:

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

这显示了单词计数 IQR 评级范围。由于主要的 IQR 范围相当紧凑,我决定尝试重新运行 LDA 预处理和模型仅限于(大致)IQR 范围。进行这一更改后,我的 1、2、3、4、5 星分类的 f1 逻辑回归得分增加到了 0.62。还是不太好。

在这一点上,我决定看看如果我去掉 3 颗星会发生什么,并将 1、2 颗星归类为“差”,4、5 颗星归类为“好”。正如你在上面的图表中看到的,这是一个奇迹!现在逻辑回归得出了 0.869 的 f1 分数。

修正的休伯损失

当我运行这些时,我注意到 SKLearn 的随机梯度下降实现中有一个“修正的 huber”损失选项[10]。在这种情况下,出错的代价比铰链(SVC)或日志丢失要严重得多:

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

我仍然在努力解决为什么这个方法如此有效,但是我最初的想法是这些惩罚性的惩罚使得 SGD(记住,1 比 1 的重量更新)学得很快。正规化在这方面也有很大帮助。上面代码中第 42 行的 alpha 是一个正则化参数(就像在 Ridge 或 Lasso 正则化中一样),这有助于我的 f1 分数达到 0.936。

对看不见的数据应用模型

在这一点上,我对这些结果感到非常兴奋,但想进一步看看在完全看不见的数据上会发生什么。

具体来说:

  1. 从 2016 年的评论中提取 LDA 模型,并获取测试数据的特征向量。需要注意的是,同样的 2016 款可以做到这一点!
  2. 在测试向量上重新运行模型。

所有需要做的就是为测试语料库制作二元模型,然后像以前一样将它投入到测试向量提取方法中:

def get_bigram(df):

    df['text'] = strip_newline(df.text)
    words = list(sent_to_words(df.text))
    words = remove_stopwords(words)
    bigram = bigrams(words)
    bigram = [bigram[review] for review in words]
    return bigram

bigram_test = get_bigram(rev_test)

test_corpus = [train_id2word.doc2bow(text) for text in bigram_test]

test_vecs = []
for i in range(len(rev_test)):
    top_topics = (
            lda_train.get_document_topics(test_corpus[i],
                                          minimum_probability=0.0)
    topic_vec = [top_topics[i][1] for i in range(20)]
    topic_vec.extend([rev_test.iloc[i].real_counts])
    topic_vec.extend([len(rev_test.iloc[i].text)])
    test_vecs.append(topic_vec)

最后,结果是:

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

令我有些震惊的是,这种概括!

我对这个结果感到兴奋,因为我相信这种方法对任何试图以这种方式训练分类器的公司都是可行的。最后我还使用 mlxtend [11]做了一个假设检验,最终结果确实具有统计学意义。

未来的工作

我打算在未来扩展这一点,我留给你:

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

我还在我的 GitHub 这里托管了所有的代码和经过训练的 LDA 模型。

感谢阅读!

来源

[1]https://en.wikipedia.org/wiki/Latent_Dirichlet_allocation
【2】https://www.yelp.com/dataset
【3】https://radimrehurek.com/gensim/tut1.html
【4】https://radimrehurek.com/gensim/models/coherencemodel.html
【5】https://radimrehurek.com/gensim/models/hdpmodel.html
【6】http://blog . echen . me/2012/03/20/infinite-mix-models-with-nonparameter-Bayes-and-the-Dirichlet-process/
SGDClassifier.html
【11】http://rasbt.github.io/mlxtend/user_guide/evaluate/mcnemar/

无监督组学整合

原文:https://towardsdatascience.com/unsupervised-omics-integration-688bf8fa49bf?source=collection_archive---------17-----------------------

生命科学的数理统计和机器学习

将数据投射到跨组学的公共变化轴上

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

The idea behind OMICs integration from Wang et al., Quantitative Biology 4, p.58, 2016, image source

这是专栏 生命科学的数理统计和机器学习 的第十篇文章,我试图在这里涵盖生物信息学、生物医学、遗传学、进化论等常用的分析技术。之前,我对组学集成做了一个介绍,并介绍了监督的 PLS-DA 模型。今天,我们将考虑无监督组学整合,这在没有类别标签(没有明确的表型)可用时尤其方便,但我们仍然希望通过组合不同来源的生物信息来了解数据中样本之间的异质性。

监督与非监督数据集成

比较有监督和无监督的数据分析就像比较披头士和天鹅绒地下音乐。两者都很优秀,但方式不同。虽然监督建模在现代研究中占主导地位,因为它提供了缓慢但有保证的进展,但无监督模型一直被认为是**“高风险-高收益”的方法**。

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

列夫·朗道 (诺贝尔物理学奖获得者)他问正在努力解决数学问题的学生的问题:“你怎么能在不知道答案的情况下解决一个科学问题?”反映了有监督的假设驱动的主流研究的心态。例如,如果一个人胆敢对编辑的评论“我不太理解你的生物学假设”回复“我没有”,这将很可能导致同行评审科学期刊拒绝该论文。这是因为在研究中,我们倾向于用事物如何工作的最初想法来约束自己,而要做的研究只是为了证明我们的假设是正确的。相比之下,无监督方法是一种 解放你的思想 的方法,当你不知道你的数据中有什么,因此可以发现意想不到的现象

多组学因素分析(MOFA)

是典型的无假设数据探索框架。它允许通过从多组学层中提取公共变化轴进行数据整合。给定来自相同或重叠样本的多个组学的数据矩阵,MOFA 根据潜在/隐藏因素推断出数据的低维表示,然后可以对其进行可视化和解释。

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

Idea of unsupervised OMICs integration with Multi-OMICs Factor Analysis (MOFA)

类似于其他整合组学方法,如 DISCO、JIVE 和 O2PLS ,MOFA 推断异质性的潜在轴是否为个体 OMIC 或所独有,表现在多个组学中。此外,MOFA 提供了几个有用的功能,包括:

  • 低维潜在空间中样本的可视化
  • 使用(基因集)富集分析的因子注释
  • 缺失和稀疏数据的插补和支持
  • 非高斯分布的组学支持

后两个优点源于 MOFA 是在贝叶斯T2 框架内实现的,不依赖于大量数据或高斯分布等频繁统计假设。重要的是,MOFA 是一个线性** 集成组学算法,一个更一般的非线性组学集成可以通过例如自动编码器来执行,我在我以前的帖子中描述过。关于 MOFA 要提到的最后一点是,它是一种 因子分析(FA) 算法,尽管 FA 在视觉上可能看起来与 PCA 相同,但这两种线性降维技术不应混淆。PCA 是一种纯粹的矩阵分解技术(除非它是一种概率 PCA ),它将总方差分解成正交的主分量,FA 寻求构造隐藏的潜在变量,这些变量生成观察到的数据,因此因子分析是一种生成模型,类似于隐马尔可夫模型(HMM)、高斯混合模型(GMM)、变分自动编码器(ve)、生成对抗网络(GANs)等。**

多组学数据集的整合

在本节中,我们将 MOFA 应用于单细胞多组学 scNMT 数据集,该数据集描绘了来自相同生物细胞染色质可及性(scATACseq)、DNA 甲基化(scBSseq)和基因表达(scRNAseq)** ,这些细胞属于两种类型:分化小鼠胚胎干细胞(ESCs)和胚胎体(EBs) 。我们将从读取、过滤和对数转换 scNMT 的 scRNAseq 子集开始:**

接下来,我们将读取 scNMT 的 scBSseq 和 scATACseq 子集,并显示它们的分布。因为 CpG 位点可以是甲基化或未甲基化**,并且类似地,使用 GpC 甲基转移酶 标记的位点可以来自开放或封闭染色质区域,所以 scBSseq 和 scATACseq 的分布看起来生物模态指示数据的二元性质就不足为奇了。**

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

Histograms of scBSseq and scATACseq subsets of scNMT

因此,我们将 scBSseq 和 scATACseq 数据建模为来自 Benoulli 分布 。我们将通过将低于 50 的值编码为 0,高于 50 的值编码为 1** 以及移除低方差特征以避免冗余,进一步使 scBSseq 和 scATACseq 数据集成为纯二进制数据集:**

此外,我们将创建 MOFA 对象并设置模型参数,例如 scBSseq 和 scATACseq 的伯努利分布,以及 scRNAseq 组学的高斯分布(由于对数变换):

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

MOFA provides a useful visualization of the dimensions of the data

最后,我们将准备 MOFA 对象并运行 MOFA。事实证明,MOFA 只选择了 3 个隐藏的潜在因素(LFs ),解释了 scNMT 数据集超过 3%的变化。MOFa 的主要成果是下面的个体组学之间协方差的巨大可视化:****

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

我们可以看到,scRNAseq 对总的整合组学 scNMT 数据集贡献了最大的变异( 13% ),scBSseq 和 scATACseq 贡献了约 5% 的变异。在 MOFA 选择的 3 个 LF 中,scRNAseq 对所有 LF 都有贡献,而第二个 LF 主要由 scBSseq 驱动,scATACseq 仅对第一个 LF 有贡献。有趣的是, scRNAseq 在第一个 LF 中与 scATACseq 共变,而 scRNAseq 在第二个 LF 中与 scBSseq 共变。现在让我们通过显示它们的加载来解释 LF,即负责每个 LF 的特征,这里我们考虑 scRNAseq 和 LF1:

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

Visualization of MOFA loadings and heatmap demonstrating separation of ESC and EB cells

在右边的热图上,看起来加载基因在 ESC 和 EB 细胞之间提供了一个很好的分离。最后,我们将显示低维潜在空间中的细胞,这种嵌入是来自 scNMT 多组学数据集的 3 组学整合的结果。****

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

Low-dimensional MOFA representation of scNMT cells

我们的结论是,MOFA 将来自 scNMT 数据集的 3 个组学投影到一个共同的潜在空间,其中技术差异被忽略,仅共同变异被考虑。整合方法能够成功地区分 3 种细胞类型:ESCs、EBs 和对照。

摘要

在这篇文章中,我们了解到多组学因子分析(MOFA)是一种优雅的基于贝叶斯的组学整合算法,通过提取跨模态的共同变化轴。这对于数据探索和理解组学之间的相互作用特别有用。MOFA对缺失数据不敏感,并允许组合来自不同非高斯统计分布的组学。

在下面的评论中让我知道生命科学中的哪些分析对你来说似乎特别神秘,我会在这个专栏中尝试回答它们。在我的 github 上查看帖子中的代码。在 Medium 关注我,在 Twitter @NikolayOskolkov 关注我,在 Linkedin 关注我。下一次我们将讨论如何批量更正单细胞数据**,敬请关注。**

无监督情感分析

原文:https://towardsdatascience.com/unsupervised-sentiment-analysis-a38bf1906483?source=collection_archive---------0-----------------------

如何从没有任何标签的数据中提取情感

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

Photo by Amanda Jones on Unsplash

注意:github repo 中提供了完整的代码:

[## rafaljanwojcik/无监督情感分析

如何从观点中提取情感而不被贴上文章回购的标签…在无监督的情绪上…

github.com](https://github.com/rafaljanwojcik/Unsupervised-Sentiment-Analysis)

NLP 方法的一个常见应用是情感分析,你试图从数据中提取关于作者情感的信息。主要是,至少在开始时,你会试图区分积极和消极的情绪,最终也是中立的,或者甚至仅基于文本检索与给定观点相关的分数。

你可以采取两种主要方法,教一种算法来区分写作中的积极和消极情绪——有监督的和无监督的。

第一个将向你询问以收集标记数据,并以监督的方式教导算法(例如, LSTM 网络)序列中的每个单词(实际上是所有单词一个接一个出现,如果我们谈论 RNNs )如何对应于整个句子是否定还是肯定的结果。这种方法需要手动标记数据,这通常很耗时,而且并不总是可行的。其次,对于在 NLP 方面没有得到很好利用的语言,例如波兰语,没有太多的预训练模型可以使用,所以不可能使用已经预训练了模型的来估计句子中每个单词的情感得分。

后一种方法是一种无人监管的方法,这也是本文关注的对象。无监督学习背后的主要思想是,对于你输入的变量的结果,你不给模型任何预先的假设和定义——你只是插入数据(当然之前进行了预处理),并希望模型学习数据本身的结构。如果您没有带标签的数据,或者您不确定数据的结构,并且您想要了解更多关于您正在分析的过程的性质,而不事先对其结果做出任何假设,那么这是非常有用的。

在我们进入本文的主要部分之前,还有一件事可能很重要。在自然语言处理和计算机视觉的最新突破中,最重要的思想之一是迁移学习的有效利用。在 NLP 领域,大多数迁移学习以某种方式发生,即一些模型(在 Word2Vec 的情况下,让它成为 MLP,或者像 BERT 这样的转换器)首先以无监督的方式(实际上是假监督的)对数据进行训练,然后针对特定任务进行微调,或者只是在另一个模型中使用,以产生更好的质量特征。通常会给它一个假的监督任务,比如根据周围的单词预测单词,或者根据给定的单词预测周围的单词(参见: word2vec ,或者根据前面的单词/句子预测下一个单词/句子( transformer models )。这种训练不应该被认为是直接监督的,因为没有人的因素告诉算法什么答案是正确的(除了人自己写句子)。我提这个是因为 Word2Vec 算法可以作为迁移学习的例子来教。

也就是说,我们到达了这篇文章的主题,即无监督的情感分析。让事情变得更难的是,因为我来自波兰,我选择了分析波兰情感数据集,尽管这种方法也应该适用于任何语言,因为我没有对波兰语做出任何特定的假设,也没有使用预先训练的模型。在本文中,Szymon Pł otka 在监督下收集并分析了该数据集:

[## 使用 Keras 和 Word2vec - Ermlab 软件进行波兰情感分析

博客上的帖子将致力于分析多愁善感的波兰语,这是一个属于…

ermlab.com](https://ermlab.com/en/blog/nlp/polish-sentiment-analysis-using-keras-and-word2vec/)

解决这个问题有不同的方法,我将在本文的底部提到,这些方法可能会更好,但我发现我的方法实际上很令人兴奋,因为它是这些想法中的一个,只是在你的脑海中出现,并在没有投入太多努力的情况下实际工作(这也可能令人担忧)。

1.主要思想

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

Photo by Nicole Honeywill / Sincerely Media on Unsplash

这种方法背后的主要思想是消极和积极的词通常被相似的词包围。这意味着,如果我们有电影评论数据集,单词“boring”将被与单词“derive”相同的单词包围,通常这些单词将与单词“not”(like)接近,这也将使 word 与它们不相似。另一方面,这不太可能发生,单词“乏味”与单词“令人兴奋”的环境更相似,而不是与单词“无聊”的环境更相似。在这样的假设下,单词可以形成具有相似环境的负面单词、具有相似环境的正面单词以及一些结束于它们之间的中性单词的集群(基于它们环境的相似性)。一开始这看起来不太令人信服,我可能不是完美的解释者,但事实证明这是真的。

解决此类问题(拥有与其周围相似的单词)的完美工具是唯一的 word2vec!如果你以前没听说过,这里有一篇关于 word2vec 算法的文章,作者是 Chris McCornick:

[## Word2Vec 教程—跳格模型

本教程涵盖了 Word2Vec 的 skip gram 神经网络架构。本教程的目的是…

medium.com](https://medium.com/nearist-ai/word2vec-tutorial-the-skip-gram-model-c7926e1fdc09)

和 Pierre Megret 的 perfect tutorial,我在本文中使用它来训练我自己的单词嵌入:

[## Gensim Word2Vec 教程

下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…

www.kaggle.com](https://www.kaggle.com/pierremegret/gensim-word2vec-tutorial)

2.数据

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

Photo by Robert Bye on Unsplash

T 他每个数据科学/机器学习项目第一步、唯一一步、也是最重要的一步就是数据准备。如果没有良好的数据质量,最终总是可能得到一个有偏差的模型,要么根据我们选择的一些指标(例如测试集的 F 分数)表现不佳,要么一开始就很难诊断,被告知有偏差的关系,这实际上并不能反映出它区分积极和消极情绪的可用性,而是允许它在给定的数据集上表现良好。

下面的单元格显示了我选择使用的基本文本准备步骤之一,但我没有包括所有步骤,因为所有内容都包含在我的中,我不想降低文章的可读性。坦率地说,我没有在这上面花太多时间,仍然有足够的空间让您自己做准备,特别是如果您想为像英语这样的语言实现它,这些语言有文本规范化的库。对于波兰语来说,使用像 Morfologik 这样的工具来使单词符合其基本结构可能非常重要,因为我们有许多不同的单词后缀来改变模型的单词,但实际上意思完全相同(例如,“beznadziejny”和“beznadziejna”都表示无望,但第一个指的是男人,另一个指的是女人)。

https://gist.github.com/rafaljanwojcik/f00dfae9843dadc0220eba3d36694e27

我选择包括的所有步骤:

  • 删除缺少(NaN)值的行,
  • 删除重复的行,
  • 删除 rate 等于 0 的行,因为它包含一些错误,可能来自数据收集阶段,
  • 使用 unidecode 包替换波兰字母,
  • 用一个空格替换所有非字母数字符号、标点符号和重复的空格
  • 保留所有包含长度至少为 2 个单词的句子的行。

另一个想法可以是实现拼写检查,以防止训练太多的单词嵌入,这实际上意味着完全相同的事情。这里有一篇关于拼写检查器的很棒的文章,它使用 Word2Vec 和 Levenstein 距离来检测语义上最相似的单词:

[## 用 word2vec 数据建立一个拼写检查器(用 python)

在 SubitoLabs,我们正在做一个非常酷的聊天信息分析项目。基本上,我们需要检测一些关键字…

link.medium.com](https://link.medium.com/L6iSZUIov1)

清理完单词后,还有其他几个步骤为 word2vec 模型准备数据,这些都包含在我的 github repo 中。主要步骤包括使用 gensim 的短语模块检测和替换最常见的词的二元模型。所有这些步骤和我使用的 Word2Vec 模型中的大部分超参数都是基于我之前链接的 kaggle 的 Word2Vec 教程

3.Word2Vec 模型

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

Photo by Max Kleinen on Unsplash

在这个练习中,我使用了 gensim 的 word2vec 算法的实现与 CBOW 架构。我训练了 300 个维嵌入,查找窗口等于 4,负采样设置为 20 个词,子采样设置为 1e-5,学习率从 0.03 衰减到 0.0007。

w2v_model = Word2Vec(min_count=3,
                     window=4,
                     size=300,
                     sample=1e-5, 
                     alpha=0.03, 
                     min_alpha=0.0007, 
                     negative=20,
                     workers=multiprocessing.cpu_count()-1)

4.k 均值聚类

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

Photo by Arnaud Mariat on Unsplash

K -means clustering 是数据聚类的基本技术,它似乎最适合于给定的问题,因为它将所需聚类的数量作为输入,并输出计算出的聚类质心(发现的聚类的中心点)的坐标。这是一种迭代算法,在第一步中,选择 n 个随机数据点作为聚类质心的坐标(其中 n 是搜索的聚类的数量),然后在每一步中,基于欧几里德距离,将所有点分配给它们最近的质心。接下来,计算每个质心的新坐标,作为分配给每个质心的所有数据点的坐标的平均值,并且重复迭代,直到达到分配给质心的点和它们的质心坐标之间的距离的平方和的最小值(这仅仅意味着聚类的坐标停止变化),或者迭代次数达到给定的限制。

在给定的问题中,我使用 sklearn 的具有 50 个重复起始点的 K-means 算法的实现,大概是为了防止算法选择错误的起始质心坐标,这将导致算法收敛到非最佳聚类,以及 1000 次将点重新分配到聚类的迭代。

https://gist.github.com/rafaljanwojcik/275f18d3a02f6946d11f3bf50a563c2b

在估计的单词向量上运行之后,我得到了两个质心,它们的坐标可以用下面的方法检索:

model.cluster_centers_

接下来,为了检查哪个聚类是相对正的,哪个是相对负的,使用 gensim 的 most_similar 方法,我检查了哪些词向量在余弦相似性方面与第一个聚类的坐标最相似:

word_vectors.similar_by_vector(model.cluster_centers_[0], topn=10, restrict_vocab=None)

哪些输出:

[('pelen_profesjonalim', 0.9740794897079468),
 ('superszybko_supersprawnie', 0.97325599193573),
 ('bardzon', 0.9731361865997314),
 ('duzu_wybor', 0.971358060836792),
 ('ladne_garnki', 0.9698898196220398),
 ('najlpszym_porzadku', 0.9690271615982056),
 ('wieloma_promocjami', 0.9684171676635742),
 ('cudowna_wspolpraca', 0.9679782390594482),
 ('pelen_profesjonaliz', 0.9675517678260803),
 ('przyzwoicie_cenowo', 0.9674378633499146)]

正如你所看到的(如果你懂波兰语,我鼓励你学习波兰语,如果你想拥有一些超能力来炫耀的话)10 个余弦距离最接近 0 号聚类的单词是那些有积极情绪的单词。一些被分类到聚类 0 的词甚至是上下文积极的,例如,由字面意思为“蜂蜜”和“覆盆子”的词组成的搭配“miod_malina”,意味着某事是惊人的和完美的,并且它获得了+1.363374 的情感分数(与它被分配到的聚类的距离成反比,详细信息请参见库中的代码)。

负面聚类更难描述,因为不是所有最接近其质心的最相似的单词都是直接负面的,但当你检查像“无望”、“差”或“坏”这样的单词是否被分配给它时,你会得到相当好的结果,因为它们都在它们应该在的地方。

temp[temp.words.isin(['beznadziejna', 'slaba', 'zepsuty'])]

给出:

{'zepsuty': -1.2202580315412217,
 'slaba': -1.0219668995616882,
 'beznadziejna': -1.0847829796850548}

这可能看起来很棘手,我使用余弦距离来确定每个聚类的情感,然后使用欧几里德距离将每个单词分配到一个聚类,但这背后并没有动机,我只是使用了两个库中可用的方法,并且它工作了。

5.分配聚类

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

Photo by Guillermo Ferla on Unsplash

上一章中提到的下一步,是根据单词所属的聚类,给每个单词分配一个情感分数,负值或正值(-1 或 1)。为了衡量这个分数,我把它乘以他们离他们的集群有多近(来衡量他们潜在的积极/消极程度)。由于 K-means 算法输出的分数是与两个聚类的距离,为了适当地对它们进行加权,我将它们乘以接近度分数的倒数(情感分数除以接近度分数)。

https://gist.github.com/rafaljanwojcik/865a9847e1fbf3299b9bf111a164bdf9

随着这些步骤的完成,完整的字典被创建(以熊猫数据框架的形式),其中每个单词都有自己的加权情感得分。为了评估这些加权情感系数有多准确,我用获得的系数随机抽样了数据帧。正如你所看到的,对于大多数人来说,可能在谷歌翻译的帮助下,下表中的单词大多出现在正确的簇中,尽管我必须承认许多单词看起来并不那么有前途。也许,纠正它的最佳选择是适当地标准化数据,或者为不应该分配任何情感的词创建第三个中性簇,但是为了不使这个项目变得太大,我没有改进它们,并且它仍然工作得很好,正如你稍后将看到的。

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

sample of words with calculated weighted sentiment coefficients

6.Tfidf 加权和情感预测

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

Photo by Brett Jordan on Unsplash

N 下一步是用 sklearn 的 tfidf 矢量器计算每个句子中每个单词的 tfidf 得分。进行该步骤是为了考虑每个单词对于每个句子有多独特,以及与整个语料库相比,增加与对于给定句子高度特定的单词相关联的肯定/否定信号。

https://gist.github.com/rafaljanwojcik/9d9a942493881128629664583e66fb3a

最后,每个句子中的所有单词一方面被替换为它们的 tfidf 分数,另一方面被替换为它们相应的加权情感分数。

https://gist.github.com/rafaljanwojcik/ec7cd1f4493db1be44d83d32e8a6c6c5

上面和下面的列表给出了用它们相关的 tfi df/情感分数替换句子中的单词的函数,以获得每个句子的 2 个向量

https://gist.github.com/rafaljanwojcik/fa4c85f22cc1fedda25f156d3715ccae

这两个句子向量的点积指示总体情绪是积极的还是消极的(如果点积是积极的,则情绪是积极的,反之则是消极的)。

https://gist.github.com/rafaljanwojcik/9add154cb42b2450d68134a7150de65c

7.模型分数

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

Photo by Markus Spiske on Unsplash

用于评估模型性能的 hosen 指标是 precision、recall 和 F-score,主要是因为数据集中的类高度不平衡,但事实上,数据集是如此的不平衡,以至于我可能应该想出一个指标来更好地惩罚这种不平衡。事实证明,该模型达到了 0.99 的精度,这表明它真的很擅长区分负面情绪观察(它几乎不会将负面观察误认为正面观察)。有人可能会说,很明显,它应该有,因为它只有很少的负面观察,它们可能是与其他模型最不同的,这是部分正确的,但如果你考虑到该模型也实现了近 80%的召回率(这意味着数据集中 80%的正面观察被正确分类为正面),它可能会显示,它也学到了很多东西,而不只是将数据分成两半,负面观察最终出现在正确的聚类中。如果你将这些结果与 Szymon Pł otka 在他的文章中取得的结果进行比较,无监督模型的精度实际上比他的监督模型高,准确率和召回率低大约 17.5 个百分点,尽管很难进行比较,因为我们使用了不同的测试集(我的测试集由完整的数据集组成,而他的测试集来自 20%的原始数据)。

╔════════════════ Confusion Matrix ══════════════╗
╔═══════════╦════════════════════╦═══════════════╗
║           ║         0          ║       1       ║
╠═══════════╬════════════════════╬═══════════════╣
║     0     ║        9523        ║       306     ║
╠═══════════╬════════════════════╬═══════════════╣
║     1     ║       127125       ║     508277    ║
╚═══════════╩════════════════════╩═══════════════╝╔═══════════╦════════════════════╗
║   Scores  ║                    ║
╠═══════════╬════════════════════╣
║ accuracy  ║ 0.802503           ║
║ precision ║ 0.999398           ║
║ recall    ║ 0.799930           ║
║ F1        ║ 0.888608           ║
╚═══════════╩════════════════════╝

总之,无监督方法取得了相当好的结果(在我看来),因为没有使用任何预先训练的模型,并且实际上没有给定文本中正面或负面的先前信息,它取得了相当高的度量,明显高于随机预测。坦率地说,我很想听听你是如何为你的数据集工作的!

8.进一步讨论

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

Photo by Zdeněk Macháček on Unsplash

T 他写这篇文章主要是为了提出一个关于无监督语言处理的想法,而不是为了在此基础上创造出可能的最佳解决方案,因此有足够的空间来改进它。除了我之前提到的改进之外,我想到的改进包括:

  • K-Means 聚类基于余弦,而不是欧几里德距离
  • 包括第三,中性聚类,或者分配一些结束于正和负聚类之间某处的词,情感得分等于零
  • Word2Vec 算法的超参数调整,基于例如在数据集上获得的 F1 分数(尽管它需要将数据集分成训练和测试数据集,因为训练将受到监督)
  • 不考虑单词的双字母组合

这篇短文到此结束——我真的希望你喜欢它,并期待听到你提出的任何改进。我也希望它对你有所帮助,感谢你阅读它!

祝一切顺利,愿 F1 高分与你同在!

拉斐尔

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

用数据科学理清英国政治

原文:https://towardsdatascience.com/untangling-uk-politics-with-data-science-a5afe9a86923?source=collection_archive---------22-----------------------

我们能通过分析问题找到答案吗?

TL;在这篇文章中,我们使用 spaCy、BERT 和新颖的聚类算法提取了英国议会中讨论的关键主题

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

The House of Commons in the early 19th Century, it was around this time (1833) that the practice of giving a Minister notice of a question by printing it in the House’s Notice Paper of future business began

“判断一个人要看他的问题,而不是他的回答。”

伏尔泰

在过去的三年里,英国政治变得令人困惑。除了高度动荡的政治环境之外,误导性信息在网上和社交媒体上的传播显著增加。

在本文中,我们将试图通过分析英国政治引擎源头的数据来“穿透”这种噪音;议会问题。

什么是议会问题?

议会问题是议员用来寻找信息或敦促采取行动的工具。他们要求部长们解释和维护他们部门的工作、政策决定和行动。[1]

这些问题可以使用 http://www.data.parliament.uk/提供的 API 下载。

从 API 下载所有问题、预处理和清理数据后,从 2013 年至今,我们剩下 255,000 个问题:

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

A sample of the data set for analysis

数据显示:

  • 提出问题的议员
  • 它所针对的部门
  • 问题和答案的日期
  • 问题本身的文本。

由于我们需要的大多数信息都包含在问题本身的文本中,我们需要找到一种方法来提取这些问题中传达的关键主题,然后才能更详细地分析这些主题。

输入伯特

模型在 NLP 中的发展速度之快令人惊讶。不仅新的和更强大的模型正在定期开发,开源社区也在不断进步,使得这些模型的使用越来越直接。

在本文中,我们将使用先进的 BERT 模型来帮助我们从问题数据中提取信息。在过去的几个月里,这个模型的部署变得越来越简单,最近它被集成到了 spaCy 库中,使得在 NLP 管道中使用它变得很容易。

我们将使用 BERT 将单词转换为上下文相关的单词向量,然后我们可以对每个问题进行加权,以产生代表每个问题语义的向量。

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

2019, the year that NLP became more popular than the Muppets [2]

1。用 BERT 创建单词向量

spaCy NLP 库为我们做了大量的工作。它最近发布了对许多 transformer 模型的支持,这些模型允许最先进的功能,同时仍然使用简单的 spaCy API,这使得它非常受欢迎。只需几行代码就可以启动并运行 BERT:

!pip install spacy-transformers --quiet!python -m spacy download en_trf_bertbaseuncased_lg #requires the runtime to be restarted if using Colab...import spacy
import torchis_using_gpu = spacy.prefer_gpu()if is_using_gpu: torch.set_default_tensor_type("torch.cuda.FloatTensor")nlp = spacy.load("en_trf_bertbaseuncased_lg")

一旦我们加载了模型,使用张量属性从模型中获取单词向量就非常简单了:

doc = nlp("This is an example question")doc.tensor[0] #returns the vector for the first word (This)

2。使用 TF-IDF 为每个问题创建一个加权向量

我们现在有能力从 BERT 中获取问题中每个单词的向量,但我们现在需要一种方法来将这些向量组合成每个问题的单个向量。有不同的技术来做到这一点,平均和求和向量已被证明工作良好。

然而,我们在这里需要小心。伯特是一个非常强大的模型,但它不能读取我们的思想!从数据来看,回答问题的方式有不同的模式,例如:

  • “他的部门过去采用什么标准…”
  • “她的部门正在采取什么措施来……”
  • “他的部门正在采取什么措施来……”

如果我们不小心,我们的分析会被问题的结构而不是内容所迷惑。我们需要一种方法来过滤掉这些噪音,这样我们就可以把重点放在代表问题本身的单词上。

TF-IDF 前来救援

关于 TF-IDF 与词向量的结合,我之前已经写过了,所以这里就不赘述了。这是一种简单却非常强大的聚合单词向量的方法,同时还能过滤掉噪音。

为了证明这个概念,我们来举个例子:

import IPythontkn = tfidf.build_tokenizer()sent = df.questionText.values[236178].lower()
sent = tkn(sent)html=''for wrd in sent:  
   try:    
      weight = (tfidf.idf_[tfidf.vocabulary_[wrd]])*10
      print(weight/10)  
   except:    
      weight = 1    
      print('{} not found'.format(wrd))  
   html+='<span style="font-size:{}px">{}</span>'.format(weight,wrd) 
IPython.display.HTML(html)

这从我们的数据框架中随机抽取一个问题,并对每个单词进行加权。然后将它添加到 HTML 中,这样我们就可以看到 TF-IDF 对每个单词的影响:

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

The results from TF-IDF. Notice how it is able to reduce the importance of ‘noisy’ words whilst amplifying words which have greater meaning to the question.

由此我们可以看出,这种方法在过滤噪声的同时放大更有见地的单词是非常有效的。

把这个和来自 spaCy 的 BERT 向量放在一起,我们得到下面的,它为每个问题创建一个向量,然后把这个向量保存到一个 numpy 数组中。

import spacy
import torch
from sklearn.feature_extraction.text import TfidfVectorizer
import IPython
from tqdm import tqdmis_using_gpu = spacy.prefer_gpu()
if is_using_gpu:
   torch.set_default_tensor_type("torch.cuda.FloatTensor")nlp = spacy.load("en_trf_bertbaseuncased_lg")vectorizer = TfidfVectorizer(min_df=0.0,lowercase=True)
tfidf = vectorizer.fit(df.questionText.values)
tkn = tfidf.build_tokenizer()print('creating a lookup dictionary') #this speeds up the script significantly...tfidf_lookup = {}
for key,value in tfidf.vocabulary_.items():
   tfidf_lookup[key]=tfidf.idf_[value]vect = []for doc in tqdm(nlp.pipe(df.questionText.values,batch_size=5000)):
   weighted_doc_tensor = []
   try:
      for cnt, wrd_vec in enumerate(doc.tensor):
         word = doc[cnt].text
         try:
            weight = tfidf_lookup[word.lower()]
         except:
            weight = 0.5
         pass
         doc.tensor[cnt] = doc.tensor[cnt]*weight
      vect.append(np.mean(doc.tensor,axis=0))
   except:
      vect.append(np.zeros(768,))#if it is blank...
   passvect = np.vstack(vect)
np.save('question_vects_tfidf.npy', vect)

3。分组问题以确定关键主题

我们现在有了 255,000 个问题的向量,我们可以通过使用降维和聚类的组合从这些向量中识别关键主题:

3.1 降维:UMAP

我以前使用过 TSNE 来降低文档嵌入的维度,但是在本文中我想尝试 UMAP 算法。这类似于 TSNE,但有一个额外的好处,即保持数据的“宏观”结构不变,并识别本地集群。它也适用于大型数据集。一个 Python 库以优秀的UMAP-学习的形式提供。

!pip install umap-learn --quietimport umapreducer = umap.UMAP(n_neighbors=25)y = reducer.fit_transform(vect)

该库以符合数据的方式紧密遵循 Scikit Learn。在该算法中选择的邻居的数量可以用于平衡对局部聚类和数据集的整体结构的强调。为了创建对数据进行聚类的特性,我使用该参数的值 5 和 25 运行了该算法两次。

3.2 聚类:HDBSCAN

HDBSCAN 与 DBSCAN 相关。这两种算法都被设计成基于密度来寻找聚类,并且可以自动识别聚类的数量。此外,它们可以突出不属于任何聚类的离群点。

注意: 在使用基于密度的聚类算法如 HDBSCAN 或 DBSCAN 时,使用 UMAP 或 TSNE 来降维可能是危险的。其原因是原始数据集的密度没有被保留[3]。因此,仔细审查这种方法的结果以确保所创建的集群符合分析的目标是很重要的。

HDBScan 的额外优势是能够处理不同密度的集群。与大多数聚类算法一样,调整参数(min_cluster_size 和 min_samples)更像是一门艺术,而不是科学,您需要检查结果并迭代以找到这些参数的最佳值:

!pip install hdbscan --quietdb = hdbscan.HDBSCAN(min_cluster_size=40, min_samples=1).fit(df[['x_tfidf_umap_5','y_tfidf_umap_5','y_tfidf_umap_25','x_tfidf_umap_25']])labels = db.labels_n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
n_noise_ = list(labels).count(-1)print('Estimated number of clusters: %d' % n_clusters_)
print('Estimated number of noise points: %d' % n_noise_)df['cluster'] = db.labels_

3.3 获取集群标签

我们可以用 TF-IDF(再次!)来更好地理解集群是如何工作的。

通过查找每个聚类的关键词,我们不仅可以了解这些聚类代表什么,还可以为每个聚类生成一些用户友好的标签:

from sklearn.feature_extraction.text import TfidfVectorizervectorizer = TfidfVectorizer(stop_words='english')
tfidf = vectorizer.fit_transform(df.questionText.values)totals = 0for cluster in df.cluster.value_counts()[0:10].index:
   stg = " ".join(df.loc[df.cluster==cluster].questionText.values)
   response = vectorizer.transform([stg])
   count = df.cluster.value_counts().loc[cluster]
   totals += count
   feature_array = np.array(vectorizer.get_feature_names())
   tfidf_sorting = np.argsort(response.toarray()).flatten()[::-1]
   n = 10
   print("Cluster Label: {}, Items in Cluster: {}".format(cluster,count))
   print(feature_array[tfidf_sorting][:n])

这返回(去除噪声后的前 5 个聚类):

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

Success! We can clearly see that each cluster represents a specific political theme.

太棒了,我们已经成功地建立了一种将每一个项目聚集成核心主题的方法。

将这一切结合在一起

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

Viewing the key themes over time we see that these these are very reactive to key events. Brexit (green) dominates from mid 2016 onward.

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

那么,这个练习告诉了我们关于英国政治的什么?随着时间的推移,对 10 大主题进行可视化显示,大多数问题都是针对当天的时事提出的。对 2016 年年中退出欧盟的大量关注并不令人惊讶,但图表显示了这在多大程度上扭曲了议会辩论,使卫生、能源和交通等话题黯然失色。

未来的工作

当然,这只是触及了这个数据集所能做的事情的表面。此数据的其他可能用途包括:

  • 根据议员在议会中提出的问题对他们进行剖析。
  • 理解政府的机构是否反映了下议院辩论的焦点。
  • 在议会提问之前预测问题。

参考资料:

[1]来自 parliment . uk:https://www . parliament . uk/documents/commons-information-office/P01 . pdf

[2]谷歌趋势 2019 年 11 月 24 日

[3]https://umap-learn.readthedocs.io/en/latest/clustering.html

挖掘企业可穿戴物联网的潜力

原文:https://towardsdatascience.com/untapping-the-potential-of-enterprise-wearable-iot-f99cc482821f?source=collection_archive---------47-----------------------

企业可穿戴物联网将在商业 4.0 中全面实现

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

Source: Pixabay

可穿戴技术已经席卷了消费主义——从智能手表、虚拟现实耳机、增强现实眼镜、可穿戴健康等等的发展。自 2015 年以来,美国使用各种可穿戴设备的成年人数量增加了一倍多(3950 万),仅在 2018 年就超过了 8170 万。2019 年,预计可穿戴设备的销售额预计将达到 420 亿美元。

虽然可穿戴设备继续主导消费技术市场的很大一部分,但在企业端使用可穿戴设备的讨论或行动却很少。特别是在公司继续进行数字化转型并变得更加数据驱动的时期,企业需要开始大力投资可穿戴物联网,以帮助提供更多可操作的决策数据,提高员工的工作效率,并提供无与伦比的客户体验。

潜在的使用案例是无限的

Gartner 最近发布了一项研究,展示了企业物联网的增长——预计到 2020 年将达到56 亿个终端。这比 2019 年同比增长了 21%。从现场服务物联网设备到店内零售亭、服务行业平板电脑、制造车间物联网管理等等,各行业的物联网采用正在成为行业规范。

可穿戴物联网可以为这些投资增加一层便利性和互操作性,这是通过传统物联网技术无法实现的。以现场服务管理为例。如今,现场服务技术人员很可能会配备一台平板电脑,用于维护查询简报和日程安排、现场维护以及维护后客户满意度分析。通过为现场服务技术人员提供可穿戴设备,这些技术人员将能够在现场更快地工作并更好地处理多项任务,最终提高客户满意度,并提高工作效率和日常维护完成率。即使节省的时间只有几秒钟——考虑到任何一家互联网或有线电视提供商每天都在与数百万家庭打交道,这几秒钟加起来很快。

可穿戴物联网还可以为车间带来优化的生产力,因为组织正在不断寻找新的方法,为制造车间经理提供所需的工具,以最大限度地减少设备停机时间和优化正常运行时间。通过将可穿戴设备与预测性维护传感器相连接,推送通知可以最大限度地缩短检测到故障零件或设备与对所述零件进行定期维护和修理之间的时间。

在零售领域,商场经理可以利用可穿戴设备为客户服务代表提供产品信息、库存状态等,以提供卓越的店内体验。最近的研究显示大多数零售和消费品公司正在大力投资于产品和服务的个性化——可穿戴技术为这些零售商提供了以前无法想象的个性化店内功能。

医疗保健专业人员可以利用可穿戴设备即时访问病历,简化签到和分诊流程,并普遍改善住院护理。研究显示医疗保健专业人员已经开始在他们的各种流程和治疗中采用数字能力,但仍有增长空间。可穿戴技术的采用可能会成为医疗保健领域广泛采用数字技术的转折点。用例确实是无限的,但设备对用户的直接影响并不是广泛可穿戴实施的唯一好处。

跨工作流优化可穿戴数据

就像任何其他物联网设备一样,可穿戴设备将为企业提供有价值的数据,这些数据可以被聚合并在其他工作流中投入使用。例如,从可穿戴物联网设备收集的现场服务数据可以为库存管理和终端设备耐用性的优先级和最佳实践提供信息。如果某个设备缺陷是现场服务维护的主要原因,那么企业可以对终端产品设计进行更改,以解决这些问题。

同样,如果零售商为其客户服务专家采用可穿戴设备功能,他们将能够实时了解客户的购买趋势。这将有助于优化库存管理和减少不必要的过剩。它还为零售商提供了关于客户如何与其物理空间互动的见解。通过可穿戴和移动支付选项,零售商可能会发现不需要实体销售点。通过非接触式支付或移动钱包集成等方法,可穿戴物联网设备最终也将能够作为一种支付方式(无需大型笨重的 POS 机)。

可穿戴物联网设备为所有不同行业的企业提供了更高的移动性和敏捷性。迄今为止,企业一直明智地在其供应链战略和客户体验能力的各个接触点采用物联网技术。也就是说,技术在不断变化,单靠物联网投资不足以带来竞争优势。虽然可穿戴投资可能不是主流,但早期采用者肯定会受益——能够简化物联网流程,并激活通过这些设备收集的各种工作流的宝贵数据。可穿戴物联网设备不仅仅是支持个人用户,它们还能提供大规模的指数级价值。

用深度显微镜揭示生物学

原文:https://towardsdatascience.com/unveiling-biology-with-deep-microscopy-bcfbc39a02d6?source=collection_archive---------29-----------------------

人工智能引发的生命科学革命

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

Source: Shutterstock

随着历史上最重要的两项发明——望远镜和显微镜的发展,科学革命在 17 世纪初开始了。借助望远镜,伽利略将注意力转向天空,光学的进步促使罗伯特·胡克和安东尼·范·列文虎克在大约 1665 年首次将复合显微镜用作科学仪器。今天,我们正在见证显微镜领域的信息技术时代革命,深度学习算法推动了人工智能改变了一个又一个行业。

深度学习的一个重大突破出现在 2012 年,当时 Hinton 和他的同事[1]在 ImageNet 大规模视觉识别挑战赛( ILSVRC )中揭示了深度卷积神经网络结合 GPU 进行图像分类的性能优势。在人工智能当前的创新和实施阶段,深度学习算法正在推动几乎所有计算机视觉密集型应用,包括自动驾驶汽车(交通、军事)、面部识别(零售、IT、通信、金融)、生物医学成像(医疗保健)、自动武器和瞄准系统(军事)以及自动化和机器人(军事、制造、重工业、零售)。

毫不奇怪,通过人工智能辅助的图像处理、分析和解释,显微镜领域的变革已经成熟。在生物学研究中,显微镜产生大量的图像数据;使用透射电子显微镜进行的一次实验可以生成一个包含超过 100 万亿字节图像的数据集[2]。如今可用的无数仪器和图像处理技术可以解析从单个分子到整个生物体的近 10 个数量级大小的结构,并在飞秒到秒的时间尺度上捕捉空间(3D)和时间(4D)动态。

深度学习算法正在解决广泛的适用于生物图像的计算机视觉问题。这些包括图像分类和图像分割;目标检测和跟踪;图像风格转换、彩色化和重建;图像超分辨率和图像合成。这些任务中有许多非常适合深度学习方法。超分辨率定位显微镜已经取得了惊人的成果,与标准协议相比,新开发的深度学习技术 ANNA-PALM 可以在更少的图像上执行超分辨率图像重建[3]。

生物成像中深度学习的另一个强有力的例子来自冷冻电子显微镜(cryo-EM)的应用,用于为结构生物学家产生 1 到 5 埃分辨率的分子模型。要了解 cryo-EM 技术的价值,只需描绘出病毒、酶和大分子复合物以及超分子组装体的精致 3D 模型。要生成一个原子尺度的模型,需要数万甚至数十万张图像,图像处理工作流程复杂,难以完全自动化。在一个称为粒子拾取的步骤中,需要选择数十万个粒子(用于表示所有方向)来识别分子图像,然后这些图像被共同用于构建结构。人工神经网络(CNN)现在显示出解决工作流程中这一令人生畏的部分的前景[4]。

涉及深度显微镜的研究可以利用商业应用中的架构进行图像分类和分割,这是生物应用中的两个主要用例。目前缺少的是带注释的训练数据集。因此,迁移学习在启动生物数据图像分类器方面发挥了重要作用[5,6]。例如,通过将在另一个(非生物)数据集上训练的图像分类器的最后一层替换为适合于新分类任务的图像分类器的最后一层,随后可以在更小的注释数据集上重新训练该模型。细胞认知浏览器(https://software.cellcognition-project.org/是一个基于 Python 的工具,用于通过深度学习对细胞表型进行分类。

图像分割的新模式正在出现,以预测和识别图像中的不同对象,如细胞、细胞核、细丝和所有类型的细胞边缘和边界。几个例子是:http://www.deepcell.org 的 DeepCell 、http://github.com/vanvalenlab/deepcell-tf 的一个支持深度学习的单细胞分析的软件库【7】和 http://github.com/lmb-freiburg/Unet-Segmentation 的 U-Net 一个用于单细胞图像分割的 ImageJ 插件【8,9】。这两个软件库都将分割作为像素级分类任务,并为一组特征产生像素级预测。基于深度学习的分割正在对癌症研究产生影响,正如一种量化乳腺癌复杂肿瘤微环境中免疫细胞行为的优雅方法所显示的那样[10]。

深度学习的影响在神经科学领域表现得最为显著。许多与神经元电路、突触可塑性模型、网络的实时成像等相关的突出问题,正面临着拥有基于人工智能的方法的研究人员的挑战。

上周发表在《科学》杂志上的一篇具有里程碑意义的论文让人们得以一窥深度显微镜所带来的生物洞察力和发现的可能性。该研究小组的目标是使用 3D 电子显微镜重建位于小鼠皮层第 4 层内的一个小脑组织体积的整个连接模式——轴突、树突、突触前和突触后过程,尤其是突触。从一组总共 194 千兆字节数据的 3,400 幅图像中,分析管道生成了大量的信息,并导致了 89 个神经元的重建,其中连接矩阵由 34,221 个突触前过程和 11,400 个突触后过程组成。这个神经解剖学的杰作需要大约 100 名学生的众包努力,并使用几个人工智能算法来处理和生成结果。管道涉及 SegEM(使用 CNN 和分水岭)从 1500 万个体积片段生成特征;这些被输入连通性分类器 ConnectEM 和对象分类器 TypeEM(轴突、树突、棘头、神经胶质)。SynEM 用于对突触前和突触后片段进行分类。对输出进行的定量分析对神经元回路的形成产生了重要的见解,并描述了学习(即长期增强和长期抑郁)可能如何印在神经网络中。

深度显微镜正在为一个曾经主要由描述性研究驱动的领域提供新的实验范式。除了上面的例子,基于成像的人工智能驱动的协议也开始影响药物发现操作。递归制药(Recursion Pharmaceuticals)等公司正在形态分析中使用深度学习(称为基于图像的分析),以识别与药物反应和疾病相关状况相关的生物特征和变量。

以类似的方式,通过 3D 电子显微镜研究实现的密集大脑区域重建开辟了一种可能性,即现在可以使用基于图像的分析来表征和预测连接组表型。例如,在环境或药物暴露后,在疾病状态下以及作为基因变化的结果,可以跟踪突触水平上神经回路的变化,并产生新的治疗方法。同样显而易见的是,对由此产生的连通性图的进一步探索可以阐明连通性规则,并作为一种测试大脑信息处理操作的数学模型的方法。我们可能会接近一个良性循环,深度显微镜的发现会导致新的人工神经网络架构,从而可以更深入地探索生物学。

参考

[1] A. Krizhevsky、I. Sutskever 和 G. Hinton,使用深度卷积神经网络的 ImageNet 分类(2012),载于 Proc。神经信息处理系统的进展 251090–1098

[2] E. Moen,D. Bannon,T. Kudo 等,细胞图像分析的深度学习(2019),Nature Methods16:1233–1246【https://doi.org/10.1038/s41592-019-0403-1】T4

[3] W .欧阳,a .阿里斯托夫,m .勒莱克等,深度学习大规模加速超分辨率定位显微术(2018)Nat bio technol**36,**460–468https://www.nature.com/articles/nbt.4106

[4] T. Bepler,A. Morin,M. Rapp 等人,用于 cry 电子显微图中粒子拾取的正-无标记卷积神经网络。(2019),自然方法16:1153–1160https://doi.org/10.1038/s41592-019-0575-8

[5] W. Zhang,R. Li,T. Zeng 等,面向生物图像分析的基于深度模型的迁移和多任务学习(2016), IEEE Trans .大数据

[6] N .鲍洛夫斯基、J. C .凯塞多、s .辛格等人,《利用通用深度卷积网络实现形态分析自动化》(2016 年),预印本可在https://www.biorxiv.org/content/early/2016/11/02/085118 获得

[7]达·范·汪妮等,深度学习实现活细胞成像实验中单个细胞的定量分析自动化,(2016), PLoS Comput。Biol 。12,e1005177。doi:10.1371/journal.pcbi

[8] O. Ronneberger,P. Fischer 和 T. Brox,U-net:生物医学图像分割的卷积网络(2015),载于医学图像计算和计算机辅助干预-MICCAI 2015计算机科学讲义,第 9351 卷。瑞士查姆:施普林格。

[9] T. Falk,D. Mai,R. Bensch 等人,U-Net:细胞计数、检测和形态测量的深度学习(2019),Nature Methods16:67–70https://doi.org/10.1038/s41592-018-0261-2

[10] L. Keren,M. Bosse,D. Marquez 等,多重离子束成像揭示的三阴性乳腺癌中的结构化肿瘤免疫微环境(2018)Cell174(6):1373–1387 . e19 . doi:10.1016/j . Cell . 2018 . 08 . 039

[11] A. Motta,M. Berning,K. M. Boergens 等人**,**体感皮层第 4 层的致密连接体重建(2019), Science 366,eaay3134

面向情感分析的文本预处理技术

原文:https://towardsdatascience.com/updated-text-preprocessing-techniques-for-sentiment-analysis-549af7fe412a?source=collection_archive---------17-----------------------

让我们讨论一些技术的缺点以及如何改进它们

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

Photo by Charles 🇵🇭 on Unsplash

人们使用了许多文本预处理技术,但是有多少是真正有用的呢?我从事文本数据工作已经快 6 个月了,我觉得当你开发一个会被很多人使用的产品时会遇到很多挑战。

这里有一些你随处可见的技巧-

  1. 移除数字、标点符号、表情符号等。
  2. 删除停用词
  3. 词汇化或词干化

移除数字后会发生什么?

数字在情感分析中起着重要的作用。怎么会?考虑你提供情绪分析服务的食品交付应用程序,通过文本反馈。现在,如果在文本预处理过程中你删除了所有的数字,那么你将如何区分两个反馈,即“我会给食物打 5 分,满分 5 分”和“我会给食物打 1 分,满分 5 分”。这只是一个例子。数字在很多情况下都发挥了作用。

移除表情符号会发生什么?

表情符号可以帮助你正确评估写评论的人的情绪。怎么会?如果有人写反馈“食物是😋另一个人写道,“食物是😖".在表情符号的帮助下,这个人想说的话清晰可见。还有更多的案例。

当你移除停用字词时会发生什么?

我在以前的文章中讨论过这个问题。如果你想深入了解,那么你一定要阅读这篇文章。

[## 为什么应该避免删除停用词

删除停用词真的能提高模型性能吗?

medium.com](https://medium.com/zykrrtech/why-you-should-avoid-removing-stopwords-aa7a353d2a52)

既然我们在这里,让我们快速讨论当停用字词被移除时会发生什么问题。删除停用词最常见的方法是借助 NLTK 库。NLTK 的停用词表也包含像 not、not、don 等这样的词,出于显而易见的原因,这些词不应该被删除,但这并不意味着你不应该删除任何停用词。

如果你正在使用像 TF-IDF,Count Vectorizer,BOW 这样的方法,那么就有必要删除停用词(不是全部),否则它们会产生很多噪音。使用预训练嵌入的深度学习方法是目前处理所有这些的最佳方法。深度学习方法的好处是它们不需要任何类型的预处理。如果你对深度学习方法更感兴趣,那么你可以看看我的文章

[## 超越传统的情感分析技术

传统方法失败在哪里?

medium.com](https://medium.com/analytics-vidhya/going-beyond-traditional-sentiment-analysis-technique-b9c91b313c07)

当你变元或变干时会发生什么?

Lemmatize 和 stem 都生成单词的词根形式,除了 stem 可能生成字典中不存在的单词。变元化比词干化使用得更广泛,对于本文,我们也考虑变元化。

当您使用 TF-IDF、CountVectorizer 或 BOW 模型时,引理化起着重要的作用。为什么?因为每个单词都会被还原成它的基本形式。例如——“狗”将被简化为“狗”。由于这些方法创建了一个稀疏矩阵,我们需要将所有单词转换成它们的基本形式,以减少唯一单词的数量。问题是,很多时候你会因为把一个单词转换成它的基本形式而失去它的上下文。

具有单词嵌入的深度学习情感分析遵循不同的方法。它将创建一个 n 维向量,而不是稀疏矩阵。所以,在 n 维向量中,像“狗”和“狗”这样的词会彼此更接近。因此,变元化的需要变得不必要。除此之外,矢量嵌入还有很多优点。

到目前为止,我们已经讨论了许多问题。其中一些仍在研究范围内,但我们可以尝试解决一些。

  1. 让我们从停用词问题开始。解决这个问题的最好办法是不要删除每一个在某种程度上有用的单词。然而,最好的方法是使用深度学习方法,像 Glove 一样预先训练嵌入,不需要删除停用词。
  2. 让我们谈谈第二个问题,即表情符号。我认为可行的解决方案是创建一个 python 字典,用一些单词替换所有出现的表情符号。这方面的一个例子是替换“😊“用‘快乐’或者也许别的什么。虽然这种方法看起来很幼稚,实际上也是如此,但它仍然比删除表情符号要好。
  3. 数字呢?深度学习是解决方案。

结论

深度学习方法真的好吗?

是的,他们更强大。DL 方法在预测时考虑词序。如果你把一个句子中的单词混在一起,然后应用 TF-IDF、CountVectorizer 或 BOW,那么得到相同结果的可能性就太高了。

最近,像 BERT,Robert 等预先训练的模型证明了 NLP 任务可以通过深度学习方法更好地完成。这些方法的优点是,它们的工作方式就像迁移学习一样,与从头开始训练它们相比,你实际上需要的例子要少得多。

如果你有兴趣了解更多关于情绪分析的工作原理,你可以在这里阅读—https://monkeylearn.com/sentiment-analysis/

更新非本地客户端缓存中的特定查询并重新呈现数据

原文:https://towardsdatascience.com/updating-apolloclient-cache-and-re-rendering-data-4537c11c6daf?source=collection_archive---------13-----------------------

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

使用 ApolloClient 的最大好处之一是开箱即用的自动内存缓存。当对数据进行分页时,这允许您返回到以前的页面,并且转换非常快。但是有时您不希望这些数据永远被缓存。有时候你希望能够清空缓存,从你的服务器上获取 新的 数据。您还希望这个触发一个 重新呈现 正在呈现该数据的任何组件。

我的问题

这是我最近在为公司开发数据可视化工具时发现自己处于的一种情况。我们有一个网络爬虫,它 24/7 爬行出版商的网页,并更新几个不同的数据库和表格。我们可以使用各种 regex、xpath 和元数据配置来操纵这个爬虫的行为,我们为每个发布者提供了这些配置。

我们面临的问题是,当对这些配置进行更改时,您希望能够看到您的更改在所有这些不同的数据库和表中的效果,这些数据库和表是由 crawler 更新的。以前,我们只是用大量的JOIN语句手动编写大量的 SQL 查询,以便在任何给定的时间点只查看我们需要的数据。这相当麻烦,有时真的会降低我们的速度。

因此,我构建了一个服务器,将所有这些数据库和各种表聚合成一个图(使用 Node.js、GraphQL、ApolloServer 和 MySQL)。然后我构建了一个 web 应用程序,它提供了大量的过滤器,我们可以使用这些过滤器只查看我们想要的数据(使用 Next.js 和 ApolloClient)。

因为我们从出版商那里抓取网站,这款应用被称为酒吧抓取

它处理大量的数据。以下是一个示例查询:

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

前端面临的主要挑战(由于 ApolloClient 出色的内存缓存)是让用户能够随意更新数据*,这样他们就可以检查一些东西,对配置进行更改,然后看看效果如何。*

挑战

搜索“清除阿波罗缓存”的方法并不是解决这个问题的好方法。不幸的是,我就是这么做的。

我了解到这样做是因为 Apollo 允许您访问缓存对象上的一个名为resetStore()的方法。该方法将清空整个缓存,并从服务器重新获取所有查询。我真的希望这能解决我的问题,因为它看起来很简单。

但事实并非如此,这让我很难过。

这不是为用例resetStore()构建的。这里的问题是它不会触发重新渲染,所以即使缓存中充满了新数据,用户也看不到它。我希望用户点击一个按钮,看到一个加载屏幕,然后看到新的数据。我也不想重置整个缓存,因为应用程序中的一些数据不会改变。

以狗为例的解决方案

让我们假设有一个页面向我们展示了一只狗。我们的数据库里有一只狗,但是这只狗变了。也许他洗了个澡,也许他在泥土里打滚。但是他很活跃,他的属性经常变化。

通过最初的查询,Apollo 让事情变得如此简单。您可以访问一些具有类似于loadingerrordata属性的状态。超级好看。它允许您编写这样的代码:

那太好了。可爱的开发者体验。

但是现在我们想用一个按钮刷新我们的狗。让我们给我们的 jsx 添加一个按钮:

那个按钮是做什么的?

事实证明,我们的useQuery()钩子也给了我们一个叫做refetch()的函数。这个功能太赞了。它允许您只刷新这一个查询的结果,或者甚至向它传递新的参数并获得结果。这解决了我之前提出的清除整个缓存的问题,但并没有为我们重新打开那个loading布尔值。因此,只有当数据提取完成时,它才会重新呈现。这对我来说是个问题,因为我需要我的用户知道他们的数据正在被重新加载,而不仅仅是信任这个按钮。有可能数据没有改变,在这种情况下,用户不会看到任何事情发生!

经过大量的黑客攻击,我发现阿波罗给了我们一个工具,当重取开始时触发我们的重渲染。这是由useQuery()钩子返回的networkStatus。要使用它,我们需要向钩子传递一个选项,告诉它在networkStatus改变时提醒我们(在重取时它会改变)。这个选项是notifyOnNetworkStatusChange

现在我们可以说“如果网络状态是重新获取,显示加载组件”。其状态代码为4。因此,我们可以将其添加到我们的loading检查中:

现在让我们为调用refetch()函数的按钮创建一个点击处理程序:

*import { useQuery } from '[@apollo/react-hooks](http://twitter.com/apollo/react-hooks)';
import Loading from './Loading';
import Error from './Error';
import Dog from './Dog';
import { DOG_QUERY } from '../lib/queries';export default () => {
  const { data, error, loading, refetch, networkStatus } = useQuery(
    DOG_QUERY,
    { notifyOnNetworkStatusChange: true }
  ); 

  if (loading || networkStatus === 4) return <Loading />;
  if (error) return <Error error={error} />;

  return (
    <>
      <button 
        type="button" 
        role="button"
        onClick={() => refetch()}
      >
        See what's new with the dog
      </button>
      <Dog dog={data.dog} />
    </>
  );
}*

仅此而已。现在,当我们单击按钮时,我们将看到<Loading />组件,缓存将刷新,然后我们将在<Dog />组件中看到新的狗数据。

就这样

我希望这对你有帮助。我知道我被困在这几个小时仅仅是因为我谷歌了错误的词。希望你不会遇到同样的问题!

欢迎在推特上关注我 @sour_utley

如果你(出于某种奇怪的原因)想看看我为我的公司制作的工具的回购,它住在这里。此外,如果您对 Carbon 的 iframes 有任何问题,页面上的代码如下:

*import { useQuery } from '[@apollo/react-hooks](http://twitter.com/apollo/react-hooks)';
import Loading from './Loading';
import Error from './Error';
import Dog from './Dog';
import { DOG_QUERY } from '../lib/queries';export default () => {
  const { data, error, loading, refetch, networkStatus } = useQuery(
    DOG_QUERY,
    { notifyOnNetworkStatusChange: true }
  ); 

  if (loading || networkStatus === 4) return <Loading />;
  if (error) return <Error error={error} />;

  return (
    <>
      <button 
        type="button" 
        role="button"
        onClick={() => refetch()}
      >
        See what's new with the dog
      </button>
      <Dog dog={data.dog} />
    </>
  );
}*

再见!

免费在 Google Colab 上升级您的内存

原文:https://towardsdatascience.com/upgrade-your-memory-on-google-colab-for-free-1b8b18e8791d?source=collection_archive---------3-----------------------

将 12GB 限制增加到 25GB

oogle Colab 真的是天赐之物,为每个人的深度学习项目提供免费的 GPU 资源。然而,有时我确实发现缺乏记忆。但是不要担心,因为实际上有可能免费增加 Google Colab 上的内存,并为您的机器学习项目增加涡轮增压器!每个用户当前分配有 12 GB 的 RAM,但这不是一个固定的限制,您可以将其升级到 25GB。看来“天下没有免费的午餐”这句话在这种情况下并不成立…

因此,不再拖延,我将介绍如何免费从目前的 12GB 升级到 25GB。这个过程其实很简单,只需要 3 行代码!连接到运行时后,只需键入以下代码片段:

a = []
while(1):
    a.append(‘1’)

Github 上为这段代码片段鸣谢 klazaj!

就是这样——多简单啊!简单地执行代码块,然后坐下来等待。大约一分钟后,您将收到来自 Colab 的通知,说“您的会话崩溃了”(相信我,你真的会很高兴看到这条消息)。

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

You will receive a message on the bottom left side of your screen saying your session has crashed

接下来会出现一个屏幕,询问您是否想切换到高 RAM 运行时。

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

Yes, definitely more RAM please!

点击是,你将获得 25GB 的内存。太棒了!

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

Notice the new 25.51 GB limit. (And yes, Corgi Mode!)

当然,让我们都负起责任,用好谷歌好心为我们提供的这些额外的内存。我非常感谢谷歌为我们提供了这个免费的平台来运行我们的机器学习和深度学习项目。我从这项免费服务中受益匪浅,并将永远感激不尽!

这个帖子到此为止。祝每个人在机器学习的努力中取得巨大成功!

这篇文章也发表在我的博客里。

隆起建模

原文:https://towardsdatascience.com/uplift-modeling-e38f96b1ef60?source=collection_archive---------2-----------------------

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

使用 Python 实现数据驱动的增长

最大化营销活动的增量回报

这一系列文章旨在解释如何以一种简单的方式使用 Python,通过将预测方法应用于您的所有行动来推动您公司的发展。它将是编程、数据分析和机器学习的结合。

我将在以下九篇文章中讨论所有主题:

1- 了解你的衡量标准

2- 客户细分

3- 客户终身价值预测

4- 流失预测

5-预测下一个购买日

6-预测销售额

7-市场反应模型

8-隆起建模

9- A/B 测试设计和执行

文章将有自己的代码片段,使您可以轻松地应用它们。如果你是编程的超级新手,你可以在这里很好地介绍一下 PythonPandas (一个我们将在任何事情上使用的著名库)。但是仍然没有编码介绍,您可以学习概念,如何使用您的数据并开始从中产生价值:

有时候你必须先跑,然后才能走——托尼·斯塔克

作为先决条件,确保你的电脑上安装了 J upyter Notebook 和 P ython 。代码片段只能在 Jupyter 笔记本上运行。

好吧,我们开始吧。

第 8 部分:隆起建模

成长黑客最关键的工作之一是尽可能高效。首先你需要省时。这意味着你必须快速构思、实验、学习和重复。第二,你需要是性价比。它意味着给定的预算/时间/努力带来最大的回报。

细分帮助成长型黑客提高转化率,从而更具成本效益。但是想象一下这样一种情况,你将要发起一个促销活动,并且你知道你想要针对哪个细分市场。你需要把报价发给每个人吗?

答案是否定的。在你目前的目标群体中,无论如何都会有顾客购买。给你升职会让你失去自我。我们可以根据这种方法对细分市场进行如下总结:

  • 治疗响应者:只有收到报价才会购买的顾客
  • **处理无响应者:**无论如何都不会购买的客户
  • **控制响应者:**无报价购买的客户
  • **控制不响应者:**如果客户没有收到报价,他们将不会购买

画面很明显。你需要瞄准治疗反应者( TR )和控制无反应者( CN )。因为除非你出价,否则他们不会购买,所以这些团体正在促销活动中提升你的地位。另一方面,你需要避免针对治疗无反应者( TN )和对照反应者( CR )。你不会从针对 TN 和 CN 中获益,CN 会让你自相残杀。

还有最后一件简单的事情要做。我们需要确定哪些客户属于哪个类别。答案是隆起建模。它有两个简单的步骤:

1-预测所有客户在每个组中的概率:我们将为此建立一个多分类模型。

2-我们将计算提升分数。提升分数的公式为:

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

我们将被 TRCN 的概率相加,减去落入其他桶的概率。更高的分数意味着更高的提升。

好的,让我们看看如何用一个例子来实现它。我们将在上一篇文章中使用相同的数据集,您可以在这里 找到

我们从导入我们需要的库和函数开始:

然后我们将导入我们的数据:

df_data = pd.read_csv('response_data.csv')
df_data.head(10)

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

正如您在上一篇文章中回忆的那样,我们有收到折扣和买一送一优惠的客户的数据,以及他们的反应。我们还有一个对照组,没有收到任何东西。

列描述如下:

  • 最近:自上次购买以来的月数
  • 历史:历史采购的价值
  • used_discount/used_bogo:指示客户是否使用了折扣或先买一送一
  • zip_code:邮政编码的分类,如郊区/城市/农村
  • is_referral:指示客户是否是从推荐渠道获得的
  • 渠道:客户使用的渠道,电话/网络/多渠道
  • 报价:发送给客户的报价,折扣/买一送一/无报价

在构建模型之前,让我们应用我们的calc _ upgrade函数来查看作为基准的该活动的当前提升:

calc_uplift(df_data)

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

折扣的转换提升为 7.66%,买一送一(BOGO)的转换提升为 4.52%。

接下来,我们将开始构建我们的模型。

预测抬升得分的多分类模型

目前,我们的标签是客户是否转换(1 或 0)。我们需要为 TRTN 、 **CR、**和 **CN 创建四个类。**我们知道收到折扣和 bogo 优惠的客户是治疗,其余的是控制。让我们创建一个 campaign_group 列来显示这些信息:

df_data['campaign_group'] = 'treatment'
df_data.loc[df_data.offer == 'No Offer', 'campaign_group'] = 'control'

太好了,现在我们需要创建我们的新标签:

df_data['target_class'] = 0 #CN
df_data.loc[(df_data.campaign_group == 'control') & (df_data.conversion > 0),'target_class'] = 1 #CR
df_data.loc[(df_data.campaign_group == 'treatment') & (df_data.conversion == 0),'target_class'] = 2 #TN
df_data.loc[(df_data.campaign_group == 'treatment') & (df_data.conversion > 0),'target_class'] = 3 #TR

在本例中,类的映射如下:

  • 0 ->控制无响应者
  • 1 ->控制响应者
  • 2 ->治疗无反应者
  • 3 ->治疗响应者

在训练我们的模型之前,有一个小的特征工程步骤。我们将从历史列创建聚类,并应用 get_dummies 将分类列转换为数字列:

#creating the clusters
kmeans = KMeans(n_clusters=5)
kmeans.fit(df_data[['history']])
df_data['history_cluster'] = kmeans.predict(df_data[['history']])#order the clusters
df_data = order_cluster('history_cluster', 'history',df_data,True)#creating a new dataframe as model and dropping columns that defines the label
df_model = df_data.drop(['offer','campaign_group','conversion'],axis=1)#convert categorical columns
df_model = pd.get_dummies(df_model)

让我们拟合我们的模型,并获得每一类的概率:

#create feature set and labels
X = df_model.drop(['target_class'],axis=1)
y = df_model.target_class#splitting train and test groups
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=56)#fitting the model and predicting the probabilities
xgb_model = xgb.XGBClassifier().fit(X_train, y_train)
class_probs = xgb_model.predict_proba(X_test)

变量 class_probs 拥有每个客户的概率。让我们来看一个例子:

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

对于该特定客户,我们可以将概率映射如下:

  • 中国:32%
  • CR: 2%
  • 总人口:58.9%
  • TR: 6.9%

因此,该客户的提升分数为:

0.32+0.069-0.02-0.589 =-0.22

让我们将此应用于所有用户,并计算提升分数:

#probabilities for all customers
overall_proba = xgb_model.predict_proba(df_model.drop(['target_class'],axis=1))#assign probabilities to 4 different columns
df_model['proba_CN'] = overall_proba[:,0] 
df_model['proba_CR'] = overall_proba[:,1] 
df_model['proba_TN'] = overall_proba[:,2] 
df_model['proba_TR'] = overall_proba[:,3]#calculate uplift score for all customers
df_model['uplift_score'] = df_model.eval('proba_CN + proba_TR - proba_TN - proba_CR')#assign it back to main dataframe
df_data['uplift_score'] = df_model['uplift_score']

通过运行上面的代码,我们在主数据帧中添加了一个upgrade _ score列,如下所示:

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

是时候检查拥有这个模型最关键的部分了。模型真的有效吗?评价隆起建模的真实性能有点困难。我们将检查上升分数分位数之间的上升是如何变化的,以查看我们是否可以在现实生活中使用该模型。

模型评估

为了评估我们的模型,我们将创建两个不同的组,并将它们与我们的基准进行比较。组包括:

1-高提升分数:客户的提升分数大于第三个分位数

2-提升得分低:客户的提升得分< 2nd quantile

We are going to compare:

  • Conversion uplift
  • Revenue uplift per target customer to see if our model can make our actions more efficient.

Here is our benchmark for the discount campaign.

Total Targeted Customer Count: 21307
Discount Conversion Uplift: 7.66%
Discount Order Uplift: 1631.89
Discount Revenue Uplift: $40797.35
Revenue Uplift Per Targeted Customer: $1.91

Let’s create the first group and see the numbers:

df_data_lift = df_data.copy()
uplift_q_75 = df_data_lift.uplift_score.quantile(0.75)
df_data_lift = df_data_lift[(df_data_lift.offer != 'Buy One Get One') & (df_data_lift.uplift_score > uplift_q_75)].reset_index(drop=True)#calculate the uplift
calc_uplift(df_data_lift)**results:** User Count: 5282
Discount Conversion Uplift: 12.18%
Discount Order Uplift: 643.57
Discount Revenue Uplift: $16089.36
Revenue Uplift Per Targeted Customer: $3.04

The results are great. Revenue uplift per target customer is 57% 更高,我们很容易看到目标群体的 25% 贡献了 40% 的收入提升。

我们将检查提升分数较低的组的相同数字:

df_data_lift = df_data.copy()
uplift_q_5 = df_data_lift.uplift_score.quantile(0.5)
df_data_lift = df_data_lift[(df_data_lift.offer != 'Buy One Get One') & (df_data_lift.uplift_score < uplift_q_5)].reset_index(drop=True)#calculate the uplift
calc_uplift(df_data_lift)**results:** User Count: 10745
Discount Conversion Uplift: 5.63%
Discount Order Uplift: 604.62
Discount Revenue Uplift: $15115.52
Revenue Uplift Per Targeted Customer: $1.4

正如预期的那样,每个目标客户的收入增长降至 $1.4 。此外,该集团有 50% 的目标客户贡献了 37% 的收入提升。

通过使用这种模式,我们可以通过以下方式轻松提高营销活动的效率:

  • 根据提升分数锁定特定细分市场
  • 根据客户的提升分数尝试不同的优惠

在下一篇文章中,我将解释增长黑客的核心要素之一: A/B 测试 。这将是我们这个系列的最后一篇文章。

你可以在这里找到这篇文章的 Jupyter 笔记本。

需要帮助来发展你的公司吗?在此与我预约免费课程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值