TowardsDataScience-博客中文翻译-2019-五十二-
TowardsDataScience 博客中文翻译 2019(五十二)
用机器学习预测 NBA 新秀数据

Photo by NeONBRAND on Unsplash
每年,来自世界各地的数百万篮球迷都会收看 NBA 选秀,希望他们最喜爱的球队能够夺金,发现下一个 NBA 巨星。这些 NBA 球队前台办公室的人花费数千小时来寻找和评估大学和国际人才,试图找到能够在职业水*上取得成功并为球队做出贡献的球员。随着数据科学领域的发展,尝试超越传统方法来评估人才是有意义的。这篇文章记录了一个项目,试图通过预测最新一批 NBA 新秀的统计数据来做到这一点。
数据准备
这个项目的总体目标是预测某些球员在 NBA 的第一年在得分、助攻、篮板、抢断和盖帽方面的表现,实现这一目标的第一步是创建正确的数据集。有很多变量有助于 NBA 球员的成功,但对于这个项目,我决定专注于这些不同的球员在大学水*上的表现。为了创建这个数据集,BeautifulSoup 被用来收集 2000 年至 2018 年期间从www.basketball-reference.com选秀的 NBA 新秀数据。在那之后,所有那些被选中的球员的*均大学统计数据都是从 www.sports-reference.com/cbb 的 T2 收集来的,所有的数据都被很好地格式化成 python 上的熊猫数据框。所有为这个项目而创建的数据集现在都可以在这里找到。csv 文件。
分析
在进入机器学习模型之前,最好先检查数据集,寻找任何基本/有趣的模式和异常。
统计趋势
通过创建不同年份的各种统计数据的箱线图,对大学篮球和职业篮球的演变进行了可视化。

Box plot distribution of the average points scored in college of players drafted by Year.
今年的草案类别(由 2020 年的方框图表示)在任何统计类别中都不突出。这应该转化为今年的选秀班是一个非常典型的选秀班,因为它将遵循前几年设定的模式,即有几个超级明星,有太多中等或中等以下的角色球员..

Box plot distribution of the average 3 pointers attempted by NBA Rookies by Year
NBA 新秀方框图被证明是更有趣的,虽然有很多更重要的趋势和模式。这里最吸引人的模式是关于三分球的演变以及它是如何在最*几年变得越来越流行的。与*年来*均三分球命中率的上升一样有趣的是,这一三分球趋势的支点最*出现了。在 2010 年之前,看起来没有任何一个新秀赛季场均 1 3 分,而在 2010 年之后,几乎每个新秀赛季都超过了这个数据。
簇
除了从寻找历史统计趋势的角度分析数据之外,还从具有两个主要目标的聚类分析角度分析数据。生成的聚类透视了这个选秀职业中的球员如何相互堆叠,以及这个选秀职业中的球员如何堆叠前几年的新秀。

Agglomerative Clustering on college stats of 2019 draft class
三种不同的聚类算法(K-Means 聚类、凝聚聚类和相似性传播)在今年选秀班的大学统计数据集中运行。锡安·威廉姆森(Zion Williamson)是一位受到体育媒体界大量炒作的下一位超级巨星,所有聚类算法都将他的大学表现与布兰登·克拉克(Brandon Clarke)和波尔·波尔(Bol Bol)进行比较。

Affinity Propagation Clustering on college stats of 2000-2019 draft class
同样的三个聚类算法在由过去 20 个 NBA 选秀班的球员的大学统计数据组成的数据集上运行,并且获得了一些有趣的结果。亲和力传播模型在这里将锡安描述为布雷克·格里芬和迪安卓·艾顿的混血儿,它相应地估计他每场比赛将得到令人印象深刻的 19.4 分,11.2 个篮板,2.8 次助攻,0.85 次抢断和 0.7 次盖帽。
特征工程
创建强大的机器学习模型的三个主要步骤来自于选择/操纵输入特征,选择最成功的算法,以及微调该算法的超参数。这就是为什么在通过所有的 ML 算法运行数据之前,需要对数据集进行一些调整。
分类变量,例如学院的名称和选拔球员的球队的名称,最初被分解成一系列虚拟变量,唯一地代表每个学院/球队。这项技术最终没有成功,因为在这个修改的数据集上运行的算法往往比在没有团队或学院的原始数据集上运行的算法产生更低的指标。
团队变量不是很强,因为团队每年都会发生根本性的变化。例如,将 2010 年赢得 74%比赛的克利夫兰骑士队与 2011 年赢得 23%比赛的克利夫兰骑士队相提并论似乎不太正确。这就是为什么球队变量在球员被选中前一年被替换为一些关于球队成功的元数据特征。获胜、每场比赛的点数差异等)。结果在一定程度上验证了这种功能扩展,因为在修改的数据集上运行的算法比在只有 team 的原始数据集上运行的算法产生了更好的度量。

Correlation matrix between various features
除了用虚拟变量进行实验之外,还构建了一个相关矩阵,以更好地理解输入变量和目标变量之间的关系强度。例如,如上图所示,在大学里每场比赛的投篮次数和 NBA 里每场比赛的实际得分之间似乎有很强的相关性。
循环特征消除也用于确定要考虑的最佳变量子集。这种方法的工作原理是从线性回归模型中重复检索特征重要性,并删除重要性最低的特征。根据实验,发现使用 RFE 将输入变量从 37 个减少到 30 个产生了最好的结果。
模型
在整个实验过程中运行了许多不同的算法,下面描述的所有算法的原始代码可以在这里找到。
线性回归

Linear Regression via the Method of Least Squares in 2 dimensions
在进入所有花哨的算法之前,运行一个基本的回归模型来设置一些基线基准。线性回归被选为基准模型,该算法的工作原理是尝试绘制一条直线,穿过 N 维训练集中提供的所有点(其中 N 是数据集中的要素数量)。这条线的方程是按照最小二乘法计算的,其目标是使误差的*方和最小。
随机福里斯特

A simple Decision Tree example
使用的第一个主要算法是随机 Forrest 回归器,该算法通过挑选位于 N 个随机输入要素和 M 个随机列的交集中的数据的过程,从原始训练数据集中随机提取各种子集。接下来,对所有这些不同的子集运行上面说明的基本决策树算法。一旦创建了所有的树,就通过对每个决策树运行输入特征所产生的结果取*均值来计算测试集中元素的预测。
额外的树

The process of creating multiple decision trees to make a prediction
第二次运行的算法是额外树回归器,该算法的行为方式与随机 Forrest 回归器非常相似。就像 Random Forrest 一样,Extra Trees 对从训练数据集生成的各种随机子集运行决策树算法来创建预测。这两种算法的最大区别在于决策树在子集上运行的方式。随机森林算法使用传统的决策树方法,其中在分割点使用的特征和值是基于在该步骤获得的信息来确定的。额外树算法使用一种更宽松的决策树方法,其中在分割点使用的特征和值是随机选择的。
XGBoost

Process behind the Gradient Boosting technique
下一次运行的算法是 XGBoost,该算法使用一种称为梯度增强的技术来创建一个强大而准确的模型。梯度推进的工作原理是递归地在彼此之上构建不同的模型,以最小化误差值。由于 XGBoost 的整个目标是最小化在训练集上发现的错误,所以该算法偶尔会过度拟合数据,并在测试集上执行 subpar。
神经网络

Example of a simple feed forward Neural Network
接下来的挑战是设计有效和适当的神经网络来理解提供的数据。神经网络的工作方式与上述所有算法完全不同,但神经网络的核心组成可以描述为一系列由节点组成的层,这些节点通过权重和激活函数连接到下一层的节点。更具体地说,某个隐藏层 N 的节点中的值由前一层的节点内部的值定义,这些值与初始随机化的权重进行线性组合,并通过某个激活函数运行。神经网络背后的算法试图不断地修改这些最初随机的权重,目的是产生接*于所提供的目标输出的输出。
TPOT

The automated pipeline process behind TPOT
最终运行的算法是 TPOT,这个算法本质上与前面提到的算法有很大的不同,因为它实际上是一个用来寻找好的算法和模型的工具。它的本质是利用遗传编程不断淘汰效果不佳的模型,从而返回最成功的模型。
结果
归根结底,机器学习实际上是一个结果驱动的游戏,产生更高指标的模型比不产生更高指标的模型更有价值。就本项目而言,有 5 个主要指标用于比较不同模型的成功性。
- 调整后的测试 r:该统计测量测试集上调整后的 r 值。该统计值的范围从-inf 到 1,值越大表示结果越好。
 - 交叉验证得分:该统计数据是通过将 100 乘以在数据集内不同的训练测试分割上运行算法所产生的原始 r 的*均值而得到的。该统计值的范围从-inf 到 100,值越大表示结果越好。
 - 百分比非常准确:如果预测与实际结果相差在 20%以内,则认为预测“非常准确”。这个统计数据查看测试集中被标记为“非常准确”的百分比。
 - 准确百分比:如果预测与实际结果相差 20%到 50%,则认为预测是“准确的”。这个统计数据查看测试集中被标记为“准确”的百分比。
 - 点差误差:该统计信息查看测试集中有多少百分比的预测与实际结果相差不到 2 个点。
 

Result metrics from the different algorithms
创建了一个基本网站,以更深入和互动的方式显示上表中的结果。
预言
这个项目的最后一步是通过使用上述见解来预测即将到来的新秀职业的统计数据,从而完成最初的目标。
在所有预期的算法中,随机福里斯特回归器被选中来分析即将到来的新秀班的大学数据,并预测这些球员一旦进入 NBA 会有什么样的统计数据。随机福里斯特被选中是因为它有最高的点差错误分数,它有第二高的 CV 分数。Extra Trees 可以说是更好的算法,因为它比 Random Forrest 具有更高的 CV 分数和更高的调整后 r,但经过更仔细的检查,Extra Trees 在分析“精英”球员时的表现不如 Random Forrest。Random Forrest 将“精英”球员定义为在新秀年*均每场比赛超过 10 分的球员,他非常准确地识别了 14 名球员中的 5 名,并准确地识别了 14 名球员中的 2 名。另一方面,额外的树只能非常准确地识别 14 个玩家中的 3 个,并准确地识别 14 个玩家中的 2 个。
下面的表格在左边显示了按照他们被选中的位置排序的新人,在右边显示了按照总价值排序的预测数据的新人。总价值是根据这些指导方针预测的每场游戏的幻想点数输出。表格也按照位置进行了划分,以便读者能够容易地理解在这个特定的选秀职业中,一个玩家如何与其他类似的玩家进行较量。
控球后卫:

得分后卫:

小前锋:

大前锋:

中心:

生成的结果的完整表格可以在这里找到。创建了一个简单的网站,以更具交互性的方式显示上表中的结果。
This module displays the predicted stats of individual prospective players. The full website is available here.
未来的工作
“数据科学家的天性就是永远不会对自己的工作感到完全满意”。— 尼拉布·潘特博士
这个项目有很大的潜力,可以帮助 NBA 球探在 NCAA 找到能够在下一阶段茁壮成长并取得成功的球员。尽管如此,这个项目还远远没有真正结束。以上所有模型仍可进一步调整和试验,以提供更好和更准确的结果。
关于这个项目的更多信息,你可以参考我的 GitHub ,如果你有任何意见或问题,欢迎在下面发帖或在 siddhesvark@gmail.com 给我发邮件。
预测下一个购买日

使用 Python 实现数据驱动的增长
机器学习模型预测顾客下次购买的时间
这一系列文章旨在解释如何以一种简单的方式使用 Python,通过将预测方法应用于您的所有行动来推动您公司的发展。它将是编程、数据分析和机器学习的结合。
我将在以下九篇文章中讨论所有主题:
1- 了解你的衡量标准
2- 客户细分
3- 客户终身价值预测
4- 流失预测
5-预测下一个购买日
文章将有自己的代码片段,使您可以轻松地应用它们。如果你是编程的超级新手,你可以在这里很好地介绍一下 Python 和 Pandas (一个我们将在任何事情上使用的著名库)。但是仍然没有编码介绍,您可以学习概念,如何使用您的数据并开始从中产生价值:
有时候你得先跑,然后才能走——托尼·斯塔克
作为先决条件,确保你的电脑上安装了 J upyter Notebook 和 P ython 。代码片段只能在 Jupyter 笔记本上运行。
好吧,我们开始吧。
第 5 部分:预测下一个购买日
我们在“数据驱动增长”系列中解释的大多数行动背后都有相同的思路:
在客户期望之前,以他们应得的方式对待他们(如 LTV 预测),在不好的事情发生之前采取行动(如流失)。
预测分析在这一点上对我们帮助很大。它可以提供的众多机会之一是预测客户的下一个购买日。如果您知道客户是否可能在 7 天内再次购买,该怎么办?
我们可以在此基础上构建我们的战略,并提出许多战术行动,例如:
- 此客户没有促销优惠,因为她/他无论如何都会购买
 - 如果在预测的时间窗口内没有购买,用集客营销来推动客户(或者解雇预测🦹♀️ 🦹♂️的人)
 
在本文中,我们将使用在线零售数据集,并遵循以下步骤:
- 数据争论(创建上一个/下一个数据集并计算购买日差异)
 - 特征工程
 - 选择机器学习模型
 - 多分类模型
 - 超参数调谐
 
数据争论
让我们从导入数据开始,并做初步的数据工作:
导入 CSV 文件和日期字段转换
我们已经导入了 CSV 文件,将日期字段从字符串转换为日期时间以使其可用,并过滤掉了除英国以外的国家。
为了构建我们的模型,我们应该将数据分成两部分:

Data structure for training the model
我们使用六个月的行为数据来预测客户未来三个月的首次购买日期。如果没有购买,我们也会预测。假设我们的截止日期是 2011 年 9 月 9 日,然后分割数据:
tx_6m = tx_uk[(tx_uk.InvoiceDate < date(2011,9,1)) & (tx_uk.InvoiceDate >= date(2011,3,1))].reset_index(drop=True)tx_next = tx_uk[(tx_uk.InvoiceDate >= date(2011,9,1)) & (tx_uk.InvoiceDate < date(2011,12,1))].reset_index(drop=True)
tx_6m 代表六个月的业绩,而我们将使用 tx_next 来找出 tx_6m 中最后一次购买日期和 tx_next 中第一次购买日期之间的天数。
此外,我们将创建一个名为 tx_user 的数据帧,以拥有预测模型的用户级特征集:
tx_user = pd.DataFrame(tx_6m['CustomerID'].unique())
tx_user.columns = ['CustomerID']
通过使用 tx_next 中的数据,我们需要计算我们的标签(截止日期前最后一次购买和之后第一次购买之间的天数):
现在,tx_user 看起来如下:

正如你很容易注意到的,我们有 NaN 值,因为那些客户还没有购买。我们用 999 填充 NaN,以便稍后快速识别它们。
我们在数据帧中有客户 id 和相应的标签。让我们用我们的功能集来丰富它,以建立我们的机器学习模型。
特征工程
对于这个项目,我们选择了如下候选功能:
- RFM 分数和聚类
 - 最*三次购买的间隔天数
 - 购买天数差异的均值和标准差
 
添加这些特征后,我们需要通过应用 get_dummies 方法来处理分类特征。
对于 RFM,为了不重复第 2 部分,我们共享代码块并继续前进:
RFM Scores & Clustering
让我们来关注如何添加接下来的两个特性。在这一部分我们将会大量使用 shift() 方法。
首先,我们用客户 ID 和发票日期(不是日期时间)创建一个 dataframe。然后,我们将删除重复的,因为客户可以在一天内多次购买,差异将成为 0。
#create a dataframe with CustomerID and Invoice Date
tx_day_order = tx_6m[['CustomerID','InvoiceDate']]#convert Invoice Datetime to day
tx_day_order['InvoiceDay'] = tx_6m['InvoiceDate'].dt.datetx_day_order = tx_day_order.sort_values(['CustomerID','InvoiceDate'])#drop duplicates
tx_day_order = tx_day_order.drop_duplicates(subset=['CustomerID','InvoiceDay'],keep='first')
接下来,通过使用 shift,我们创建包含最* 3 次购买日期的新列,并查看我们的数据帧看起来是什么样的:
#shifting last 3 purchase dates
tx_day_order['PrevInvoiceDate'] = tx_day_order.groupby('CustomerID')['InvoiceDay'].shift(1)
tx_day_order['T2InvoiceDate'] = tx_day_order.groupby('CustomerID')['InvoiceDay'].shift(2)
tx_day_order['T3InvoiceDate'] = tx_day_order.groupby('CustomerID')['InvoiceDay'].shift(3)
输出:

让我们开始计算每个发票日期的天数差异:
tx_day_order['DayDiff'] = (tx_day_order['InvoiceDay'] - tx_day_order['PrevInvoiceDate']).dt.daystx_day_order['DayDiff2'] = (tx_day_order['InvoiceDay'] - tx_day_order['T2InvoiceDate']).dt.daystx_day_order['DayDiff3'] = (tx_day_order['InvoiceDay'] - tx_day_order['T3InvoiceDate']).dt.days
输出:

对于每个客户 ID,我们使用。agg() 找出购买天数差异的*均值和标准差的方法:
tx_day_diff = tx_day_order.groupby('CustomerID').agg({'DayDiff': ['mean','std']}).reset_index()tx_day_diff.columns = ['CustomerID', 'DayDiffMean','DayDiffStd']
现在我们要做一个艰难的决定。上面的计算对于有很多采购的客户来说相当有用。但是我们不能对那些购买 1-2 次的人说同样的话。例如,将一个客户标记为 频繁 还为时过早,他只有两次购买,但却是连续购买。
我们只保留购买次数超过 3 次的客户,使用以下热线:
tx_day_order_last = tx_day_order.drop_duplicates(subset=['CustomerID'],keep='last')
最后,我们删除 NA 值,将新数据帧与 tx_user 合并,并应用。get_dummies() for 转换分类值:
tx_day_order_last = tx_day_order_last.dropna()tx_day_order_last = pd.merge(tx_day_order_last, tx_day_diff, on='CustomerID')tx_user = pd.merge(tx_user, tx_day_order_last[['CustomerID','DayDiff','DayDiff2','DayDiff3','DayDiffMean','DayDiffStd']], on='CustomerID')#create tx_class as a copy of tx_user before applying get_dummies
tx_class = tx_user.copy()
tx_class = pd.get_dummies(tx_class)
我们的特征集已准备好构建分类模型。但是有很多不同的型号,我们应该使用哪一种呢?
选择机器学习模型
在开始选择模型之前,我们需要采取两个行动。首先,我们需要识别标签中的类。一般来说,百分位数给出了这个权利。还是用吧。describe() 方法在 NextPurchaseDay: 中看到它们

决定边界是一个统计和商业需求的问题。就第一点而言,它应该是有意义的,并且易于采取行动和沟通。考虑到这两个,我们将有三个类:
- 0–20:将在 0–20 天内购买的客户— 类别名称:2
 - 21–49:将在 21–49 天内购买的客户— 类别名称:1
 - ≥ 50:将在 50 天以上购买的客户— 类别名称:0
 
tx_class['NextPurchaseDayRange'] = 2
tx_class.loc[tx_class.NextPurchaseDay>20,'NextPurchaseDayRange'] = 1
tx_class.loc[tx_class.NextPurchaseDay>50,'NextPurchaseDayRange'] = 0
最后一步是查看我们的特征和标签之间的相关性。相关矩阵是展示这一点的最简洁的方式之一:
corr = tx_class[tx_class.columns].corr()
plt.figure(figsize = (30,20))
sns.heatmap(corr, annot = True, linewidths=0.2, fmt=".2f")

看起来总分正相关度最高(0.45),而新*度负相关度最高(-0.54)。
对于这个特殊的问题,我们希望使用精度最高的模型。让我们分开训练和测试测试,并测量不同模型的准确性:
Selecting the ML model for the best accuracy
每个型号的精度:

从这个结果中,我们看到朴素贝叶斯是性能最好的一个(大约 64%的准确率)。但在此之前,让我们看看我们到底做了什么。我们应用了机器学习中的一个基本概念,那就是交叉验证。
我们如何确定我们的机器学习模型在不同数据集之间的稳定性?此外,如果我们选择的测试集中有噪声怎么办。
交叉验证是衡量这一点的一种方式。它通过选择不同的测试集来提供模型的得分。如果偏差较低,则表示模型稳定。在我们的例子中,分数之间的偏差是可以接受的(除了决策树分类器)。
通常,我们应该用朴素贝叶斯。但是对于这个例子,让我们用 XGBoost 来展示我们如何用一些先进的技术来改进一个现有的模型。
多分类模型
为了构建我们的模型,我们将遵循前面文章中的步骤。但是为了进一步改进,我们将进行超参数调整。
从程序上讲,我们将找出我们的模型的最佳参数,以使它提供最佳的准确性。
让我们首先从编码我们的模型开始:
xgb_model = xgb.XGBClassifier().fit(X_train, y_train)print('Accuracy of XGB classifier on training set: {:.2f}'
       .format(xgb_model.score(X_train, y_train)))
print('Accuracy of XGB classifier on test set: {:.2f}'
       .format(xgb_model.score(X_test[X_train.columns], y_test)))
在这个版本中,我们在测试集上的准确率是 58%:

XGBClassifier 有许多参数。你可以在这里找到他们的名单。对于这个例子,我们将选择最大 _ 深度和最小 _ 子 _ 重量。
以下代码将为这些参数生成最佳值:
from sklearn.model_selection import GridSearchCVparam_test1 = {
 'max_depth':range(3,10,2),
 'min_child_weight':range(1,6,2)
}
gsearch1 = GridSearchCV(estimator = xgb.XGBClassifier(), 
param_grid = param_test1, scoring='accuracy',n_jobs=-1,iid=False, cv=2)
gsearch1.fit(X_train,y_train)
gsearch1.best_params_, gsearch1.best_score_

该算法认为最大深度和最小子权重的最佳值分别为 3 和 5。了解它如何提高精确度:

我们的分数从 58%上升到 62%。这是相当大的进步。
知道下一个购买日也是预测销售的一个很好的指标。我们将在第 6 部分中深入探讨这个话题。
你可以在这里找到这篇文章的笔记本。
享受数据驱动增长系列?给我买杯咖啡这里 …
用 Julia 中的车床预测纽约市的拍品价格

没错女士们先生们,介绍:第一个车床. jl 模型,并不意外;是线性回归。
Julia 是一种奇妙的、强大的语言(尤其是如果你喜欢编程 arduino 板。也就是说,鉴于 Julia 是一种非常函数式的语言,它几乎与生俱来的基础结构使得它非常适用于传统上被认为是面向对象的编程。然而,Julia 相对缺乏的目标受众是数据科学家。
虽然很多 Julia 的老手可能对 pkg . add()-为 3 个不同的模型提供 7 个不同的包没有问题,但这却是我对 Julia 最大的不满。Julia 有一个绝对神奇(更不用说简单)的包,Flux.jl 用于渐变、图像识别,所有这些有趣的东西,但不幸的是,我觉得这些包在预测性机器学习方面存在不足,特别是无监督学习。随着我计划改变这一点,通过为 Julia 数据科学家(包括我自己)将大量数据科学工具放在一个地方,我最终开始了一个小的包,起初是几个标量,t 测试,f 测试,在某一点上,我开始考虑创建我自己的模型模块,这已经发生在过去的两个月里。

虽然我不认为我的包会改变生活(只是暂时的),但我认为即使在预发布状态,我仍然选择使用它,而不是 Julia 提供的更传统的选项(主要得益于我的本地存储)。)所以今天,我很自豪地向大家呈现 Lathe.jl 的官方 SimpleLinearRegression。

Lathe.jl
如果你有兴趣尝试目前状态的车床. jl,这里是。我适合这个型号的笔记本在这里。我决定用缩放后的数据开始这个项目。虽然有人强烈反对创建和使用缩放数据来测试模型(因为它的发明是泄漏),但这是一个很好的方式来看看你的线性模型是否可以找到一个简单的斜率。对于我的斜率,我选择了 250,我生成了一串随机数,并在 For 循环中将所有迭代乘以 250。
当然,生成的数据总是干净的,所以我直接为我的模型获取基线:
using Lathe: models
# Our y is going to be Price,
#    Our x is going to be Doors:
# Fitting our model:
model = models.meanBaseline(traindf.Price)
嘣,就这样,一个合身的模特。当然,下一步是我们的列车预测:
# Put our model, and our xtrain into our predict method
testdf.Baseline = models.predict(model,testdf.Doors)
简单,那么我们能期望什么样的精度呢?
accuracy = Validate.mae(testdf.Price,testdf.Baseline)
println("Baseline accuracy: ",accuracy)Baseline accuracy: -41321.739130434784
我们的*均绝对误差约为 41000,相当糟糕。但这当然是意料之中的,这让我对实际模型的验证更加兴奋。让我们开始吧!:
# Fitting our model:
linreg = models.SimpleLinearRegression(traindf.Doors,traindf.Price)
# Put our x and y into the predict method:
testdf.Prediction = models.predict(linreg,testdf.Doors)
你可能想知道我们的*均绝对误差怎么样了?
linaccuracy = Validate.mae(testdf.Price,testdf.Prediction)
println("Linear Regression Accuracy: ",linaccuracy)Linear Regression Accuracy: 0.0
没错,0.0。如果你是数据科学的杰出人士,你可能会理解为什么它是 0。还记得我说过这是缩放数据吗?不管怎样,这个例子表明,我们的模型能够计算出线性方程的斜率。当然,这太好了!这在现实世界中基本上是没有用的,但至少我有理由做一些很酷的可视化!

The Original Door Data

The slope prediction of the door data
线的斜率几乎相同,这是预期的,*均绝对误差为零。当然,这是我们非常搞笑的基线模型:

Baseline door price prediction
真实世界的数据
现在终于到了将该模型应用于一些真实世界数据的时候了。这是我既喜欢又讨厌做的事情,因为有些数据集真的需要你跳出框框思考,而其他的数据集则很乏味。对于我的数据,我最终选择了来自 Kaggle 的纽约数据集。奇怪的是,由于某种原因,这个数据集看起来有点熟悉,我觉得好像我以前用过它。然而,我认为事实并非如此。我认为我脑海中的数据集只是关于同一主题的数据集。
我最小化了数据集,并检查是否有丢失的值,但没有发现任何丢失的值。
df = DataFrame(:LotArea => df.LotArea, :SalePrice => df.SalePrice, 
    :YearBuilt => df.YearBuilt,:YearSold => df.YrSold, :Rooms => df.TotRmsAbvGrd)
手里只拿着我喜欢的功能,我跳入了数据探索的奇妙世界。我认为基本的可视化对于更好地理解数据是不可或缺的,这一点我怎么强调都不为过。统计学也很棒,但是一些可视化通常可以用来证明同样的想法,只需要一半的时间,而且在我看来更有趣。


Sale Price and Year Built ; Sale Price and Area (left to right)
有两个特点非常突出,与我的销售价格直接相关。建造年份和地段面积,所以我把数据分开,对它们都进行了 f 检验。它们都显示了很强的统计显著性,我最终选择了 Lot Area,最初是因为我的 x 特征进入了模型。我认为将两个都拟合并比较结果比只拟合一个更有趣(这是拟合的两倍!)
我很兴奋去适应我的模型,但控制和冷静下来是一件好事,首先去获得一个基线。所以,我做了:
# Fit our model once again:
using Lathe: models
model = models.meanBaseline(df.SalePrice)
然后,我创建了一个空的数据框架来处理来自各种预测方法的所有输入数据。
# we'll have a new dataframe for our predictions
using DataFrames
predictions = DataFrame()predictions.Baseline = models.predict(model,testdf.SalePrice)
之后,我们当然会验证:
using Lathe: Validate
baseline_accuracy = Validate.mae(testdf.SalePrice,predictions.Baseline)
println("==========>")
println("Baseline Accuracy - ",baseline_accuracy)
println("==========>")==========>
Baseline Accuracy - 1.9455711319021984e-11
==========>
哇哦!这是一些可怕的准确性!我当然跳出来拟合一个模型,比较这些分数。
# Fit our new model!
model = models.SimpleLinearRegression(testdf.LotArea,testdf.SalePrice)
# And we'll check out what that looks like:
predictions.Prediction = models.predict(model,testdf.LotArea)
我开始验证:
BasePredAccuracy = Validate.mae(testdf.SalePrice,predictions.Prediction)
println("=========>")
println("Baseline Accuracy: ",baseline_accuracy)
println("-------------------")
println("Model Accuracy: ",BasePredAccuracy)
println("=========>")=========>
Baseline Accuracy: 1.9455711319021984e-11
-------------------
Model Accuracy: 173848.28232265453
=========>
如此之大,模型的准确性比基线有了显著的提高。
我尝试用一个重标量进行一些预处理,但是看起来 Z 标量对于大幅度提高精度是必要的。但是当然,如果没有更多的视觉化,我不能结束。



Visualizing my model, room frequency, and lot area.
最后,我对车床的未来感到非常兴奋。这个模型是许多的开始,并且当前的统计是更多的开始。对我来说,在 Julia 中,车床使机器学习变得容易得多。我希望它在未来对其他人也是如此,如果你想做任何改进,请随意在这里发表。
使用线性回归预测 PewDiePie 的每日订户。
让我们了解一下如何使用线性回归来预测 PewDiePie 的日订阅人数。

Credits: Fandom
PewDiePie 是瑞典的 YouTube,在 YouTube 上拥有 1 亿订户(他是我的最爱)。他每天都有成千上万的用户,所以我想写一篇关于他的用户增长的教程。所以我想给你们展示一个机器学习的线性回归算法的实际实现。这里我们可以应用线性回归来预测他的 YouTube 日订阅量。我将在本教程中指导你们如何去做。本教程的完整代码可以在我的 GitHub 上找到。我不会解释线性回归算法背后的理论,因为根据我的说法,理论并不重要,只有实现才是非常重要的,因为你需要知道如何以及在哪里应用算法。不过,我会鼓励你在网上浏览一些理论,其中一篇最好的文章如下所示:
线性回归通常是每个数据科学家遇到的第一个机器学习算法。这是一个…
towardsdatascience.com](/linear-regression-using-python-b136c91bf0a2)
让我们开始吧:
我们将遵循以下步骤来完成此实施:
- 导入必要的库。
 - 从 CSV 文件中读取数据集。
 - 将数据集分成独立变量(x)和因变量(y)。
 - 将完整数据集划分为训练数据集和测试数据集。
 - 基于简单线性回归实现我们的分类器。
 
1.导入必要的库。
在本教程中,我将使用一些重要的库,如:
- numpy
 - 熊猫
 - sklearn.linear
 - sklearn.model_selection
 
Numpy: 我使用 Numpy 库的原因是,在本教程的结尾,我对一些值进行了四舍五入,以获得更准确的结果。为了调用 round 方法,我需要导入 numpy 库。要阅读 numpy 库的官方文档,请访问下面的链接:
欢迎光临!这是 NumPy 1.18.0.dev0+07a5753 的文档,最后更新于 2019 年 9 月 25 日。部分…
numpy.org](https://numpy.org/devdocs/)
如你所知,我正在使用 YouTube 上的 PewDiePie 的数据,我需要将它们存储在某种形式的数据框中,为了将数据存储在数据框中,我正在使用 pandas 数据框,使用 Pandas 数据框非常简单和有趣。要阅读熊猫图书馆的官方文件,请访问下面的链接:
[## pandas:强大的 Python 数据分析工具包- pandas 0.25.1 文档
是一个开源的、BSD 许可的库,提供高性能、易于使用的数据结构和数据分析工具…
pandas.pydata.org](https://pandas.pydata.org/pandas-docs/stable/)
Sklearn.linear: 如你所知,现在我正在使用线性回归算法来预测数据,我需要导入线性回归库,但是你不能直接导入线性回归库,虽然你需要导入 sci-kit learn 来帮助你访问线性回归库。这就是我使用 sklearn.linear 的原因。要阅读该库的官方文档,请访问下面的链接:
[## sklearn.linear_model。线性回归-sci kit-学习 0.21.3 文档
当 fit_intercept 设置为 False 时,此参数将被忽略。如果为真,回归量 X 将在…之前被标准化
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html)
sklearn.model_selection: 如果您正在实施线性回归来预测数据,那么将数据分为训练数据和测试数据通常是一个好的做法,只有这样,您预测的数据才会更加准确。为此,您需要从 scikit learn 导入 model_selection 库。要阅读官方文档,请访问以下链接:
[## 模型选择:选择估计量及其参数-sci kit-学习 0.21.3 文档
Scikit-learn 有一个类集合,可以用来为流行的
scikit-learn.org](https://scikit-learn.org/stable/tutorial/statistical_inference/model_selection.html)
在 python 中导入任何库的快速注意事项你所要做的就是说“导入库名”,库名如 pandas,numpy 等等。
导入本教程所需的库如下所示:
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
2。从 CSV 文件中读取数据集。
我已经将 PewDiePie 的订户数据以 CSV 格式存储在 Kaggle 中。Kaggle 是世界各地的人们发布和存储数据集的地方。在这里,我将数据存储为 CSV(逗号分隔值)格式。要下载数据集,请查看以下链接:
下载数千个项目的开放数据集+在一个*台上共享项目。探索热门话题,如政府…
www.kaggle.com](https://www.kaggle.com/tanuprabhu/pewdiepies-subscribers)
您可以通过单击下载选项下载数据集。要将数据转换成 python 中的格式,您必须使用 pandas 数据框。在此之前,你必须将数据加载到你的笔记本中(我正在使用 Google Colab 来键入我所有的 python 代码),在线上有多种方法可以将数据加载到笔记本中,但最简单的方法是在笔记本左侧的 Google Colab 中,你会发现一个“>”(大于符号)。当你点击它时,你会发现一个有三个选项的标签,你只需要选择文件。然后你可以在上传选项的帮助下轻松上传你的文件。无需安装到 google drive 或使用任何特定的库,只需上传数据集,您的工作就完成了。在这一步要记住的一点是,当运行时被回收时,上传的文件将被删除。这就是我如何把数据集放进笔记本的。
**# Storing the data in a pandas data frame.** 
df = pd.read_csv(“PewDiePie.csv”)
df.head(5)

如您所见,上面的数据集包含两列,data 和 subscribers。我知道日期列看起来很混乱,不要担心,多想想,它只是存储了 2019 年 5 月的第一天(像 5 月 1 日、5 月 2 日等等)。订户列包含 PewDiePie 的所有订户。
3。将数据集分成独立变量(x)和因变量(y)。
在将数据集划分为训练数据和测试数据之前,您需要区分哪些是因变量,哪些是自变量,然后才能进行划分。这可以通过以下方式完成:
x = df.iloc[:, :-1]
y = df.iloc[:, 1]
这里,“x”值包含数据,“y”值包含用户,iloc 用于从数据帧中获取值。我使用[:,:-1]的原因是因为我需要数据帧的倒数第二列,而[:1]给出了数据帧的最后一列。您可以打印该值进行确认。
4。将完整数据集划分为训练数据集和测试数据集。
为了得到一个好的预测,将数据分为训练和测试数据,这是因为顾名思义,你将训练几个数据点和测试几个数据点,并继续这样做,除非你得到好的结果。
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 0)
这里,“x”和“y”变量被分为训练和测试数据,如上面的代码片段所示,测试数据的大小为 0.3 或 30%,其余为 70%(训练数据),random_state 是随机数生成器使用的种子。
注意:试着把 x 和 y 的训练值都打印出来,你就明白我在说什么了。
**HINT:** print(x_test)
5。基于简单线性回归实现我们的分类器。
这是最重要的一点,因为这是我们应用线性回归算法的地方,要做到这一点,我们必须将经过训练的测试值提供给实际算法,这样我们就可以预测订户。为此,请遵循以下代码:
simplelinearRegression = LinearRegression()
simplelinearRegression.fit(x_train, y_train)**LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)**
在上面的代码中,我们调用了线性回归函数,然后试图绕过训练值来拟合模型。
y_predict = simplelinearRegression.predict(x_test)
predict = pd.DataFrame(y_predict)
predict.apply(np.round)
然后我们需要使用 then predict 方法来预测这些值,为此我们需要传递“x”变量的测试值,这样我们就可以获得预测值(订户)。下一行代码只是转换,这是因为 y_predict 是 numpy 数组类型,所以我们需要将其转换为数据帧,然后才能应用 round 函数。现在,变量 predict 包含所有预测的订户,如下所示:

稍后,我会将数据放入 while 循环中,以实际格式获取它,不要担心,这只是一个带有预测值的打印语句,一旦您跟踪它,就会得到它:
while i <= 28:
 print(“Total number of increase in subscribers on May %d ==>” %(i) , int(simplelinearRegression.predict([[i]])))
 i= i+1 **Total number of increase in subscribers on May 21 ==> 29154 
Total number of increase in subscribers on May 22 ==> 28210 
Total number of increase in subscribers on May 23 ==> 27266 
Total number of increase in subscribers on May 24 ==> 26322 
Total number of increase in subscribers on May 25 ==> 25378 
Total number of increase in subscribers on May 26 ==> 24434 
Total number of increase in subscribers on May 27 ==> 23491 
Total number of increase in subscribers on May 28 ==> 22547**
这就是 predict 函数预测订户的方式,predict 函数返回的订户是准确的。下面给出的是社会刀片统计,你可以比较其余的。

Credits: Social Blade
如下图所示,当您将预测值的结果与上面由 Social Blade 获得的实际订户进行比较时,结果几乎相同,除了这里或那里可以找到一些或多或少的订户,但没关系,机器学习无法 100%准确地预测。因此,这就是你如何使用机器学习算法来预测 PewDiePie 的每日订户。如果你对代码有任何疑问,评论区都是你的。如有疑问,请联系我。此外,代码可以在我的 GitHub 库中找到。谢谢你们阅读我的文章。再见,开始练代码,下次见。
用确定性模型预测药代动力学
临床数据科学
精准医疗之路。

Photo by Myriam Zilles on Unsplash
介绍
药物动力学
【药代动力学】 处理 异生素 在生物体内的分布和代谢。在药物开发和临床研究中,人们会遇到 药理学家 ,他们的工作是建议医生给病人提供药物的剂量。为此,他们经常运行所谓的药代动力学模型的模拟,这些模型是确定性的,即它们由关于时间变量的 常微分方程 组成,并描述以下过程(称为 LADME):
- ****:药物从药物配方中释放出来的过程****
 - 吸收 : 物质进入血液循环的过程
 - 分布 : 物质在身体的体液和组织中的扩散或散布
 - 代谢 : 生物体对存在外来物质的识别以及母体化合物向子代谢物的不可逆转化
 - 清除 :从体内清除物质
 
这种模型有助于确定药物的最佳剂量,作为患者属性的函数,如体重、身高、年龄或性别。此外,可以预测药物在血浆中随时间的浓度分布。此外,可以监测 药物相互作用 。这样,可以为单个患者定义给药间隔,为 个性化治疗 铺*道路(更多信息请访问 openPK )。
确定性建模
通常,作为确定性模型一部分的这些方程组具有未知的参数,并且必须根据实验数据进行估计。身体本身被描述为一个 多隔室 系统(器官是隔室),在其中发生所述过程的子集,并且药物/代谢物分子从一个隔室(器官)流向另一个隔室。通常假设所述隔室是理想混合的,即进来的分子立即混合。请注意,依赖于时间的实验数据通常并不适用于所有的房室,尤其是人类。**

Plasma concentration of paracetamol for a 50-kg patient and a dose of 1 g as it can be encountered on openPK. (image by author)
模型开发
模型组成
开发这样一个模型的方法是制定一组微分方程(在我的 GitHub 上可以找到一个在 MATLAB 中编程的处理 乙醇 代谢的例子)。下面的等式是对隔室 k 中的化合物 i 具有流量 Q 和体积 V 的质量*衡的一般公式。 P 是一个分配系数,表示某一组织中保留了多少化合物。 Q 和 V 取决于患者的体重、身高、年龄和性别(用 异速生长标度 建模)。
**dc_dt_i_k = (Q_k/V_k)*(c_in_i_(k-1)-c_i_k/P_i_k)**
每个隔间的 Q 、 V 、和 P 的值可在文献中找到。此外,药物在肝脏部分代谢,在肾脏部分排泄。在这种情况下,肝脏和肾脏的方程被修改。**
**dc_dt_i_liver = (1/V_liver)*(Q_liver*(c_in_i-c_i_liver/P_i_liver)-**v_max_i*c_i_liver/(K_m_i+c_i_liver)**)dc_dt_i_kidney = (1/V_kidney)*(Q_kidney*(c_in_i-c_i_kidney/P_i_kidney)-**k_r_i*c_i_kidney****
肝方程式中的粗体术语代表由酶催化的反应的所谓的 米氏-门滕 表达式。它将反应限制到最大反应速度 vmax ,因为用于反应的活性位点的数量是有限的。但是 vmax 和 Km 在文献中并不容易得到,必须从实验数据中估算(间隙项 kr 也是如此)。此外,可能发生与其他分子竞争活性位点的情况,并且反应项可能需要通过包括抑制表达来修改。先验地不清楚哪些过程包括在哪些区间中。例如,药物在胃肠道内被吸收到血液中,但它也可能在那里分解。要走的路是制定一个初始模型,估计其参数,并在测试集上评估其性能。如果模型性能不足,则通过添加或删除一些项来改进模型,并重复该过程直到收敛。
参数估计
有不同的目标函数用于参数估计。首先,常规的 最小二乘问题 可以被最小化(浓度是参数 p 的函数,目标函数 J 也是如此)。为此,所有隔室 k 中的所有化合物 i 的浓度堆叠在一列中(使用整形功能以避免 for 循环)。变量 c_m 是指测量的浓度,而 c_ p 是预测的浓度。**
**J = (1/N)*(c_m-c_p)'*(c_m-c_p)**
这个函数的缺点是,它比低浓度的分子更适合高浓度的分子,因为它们对目标的贡献小得多。另一种可能性是用一个协方差矩阵的逆来缩放点积,并将其重新表述为一个 最大似然 问题。当然,方差矩阵 E 也得知道。
**J = (1/N)*(c_m-c_p)'***inv(E)***(c_m-c_p)**
E 可以例如从每个隔室中每种化合物的 变异系数 cv 中估算。
**E = cv'*c_m**
最后,模型必须包含在目标函数中。利用这些参数,使用微分方程求解器(例如, ode15s 处理 刚度 )评估模型并计算预测浓度,即通过 龙格-库塔法 。使用基于实现的 fminunc 之类的解算器来最小化目标函数(类似于 梯度下降 ,但是梯度是围绕当前参数点*似的,并且与目标函数的二阶导数的幅度成比例缩放,这通过允许*坦区域中的更大的步长来增强性能)。执行多起点(参数 p 的不同起点)很重要,以便找到全局最优,而不是以局部最优结束。(注意,最小二乘法可以作为更复杂方法的起点。)********
模型验证
该模型最好使用测试集来验证,即该模型没有被训练的数据。*均相对/绝对(*方)误差可以用作度量。另外,重要的是执行一次 灵敏度分析 。为此,计算所有浓度(每个隔室中的每种化合物)相对于所有参数的偏导数。注意,它们是时间相关的,因为浓度是时间相关的。因此,一个参数对输出变量的影响会随时间而变化。必须进一步研究非常敏感的参数和它们所描述的过程。
灵敏度矩阵的 秩 揭示了所有参数是否相互独立( 结构可辨识性);如果秩低于参数的数量,则必须通过移除或重新调整从属参数来重新定义模型。
**R = rank(S)**
此外,应计算参数的置信区间,以检验的实际可识别性。可以使用 费希尔信息 和 克拉美罗界限 来计算参数的方差。****
**E_p = inv(S'*inv(E)*S)**
置信区间通过单变量方法计算,仅使用参数协方差矩阵的对角元素和 学生 t 分布 的分位数。
**sigma = sqrt(diag(E_p))CI_lb = p_fit-sigma*tinv(0.95, number_points-number_parameters)CI_ub = p_fit+sigma*tinv(0.95, number_points-number_parameters)**
如果置信区间包括零,那么参数也可以是零,即不参与方程,因此模型应该被改进。请注意,所有参数都应该是正数。
经过几次迭代的拟合和精化,构建过程当然就完成了,得到了合理的测试集性能,模型就可以用于预测了。

Photo by Marcelo Leal on Unsplash
预测英超联赛排名——让数学派上用场

Photo by Abigail Keenan on Unsplash
我最*遇到了一个有趣的问题任务,这是一个基于数学和其他有趣主题的在线地穴搜索的最终挑战(数学和有趣通常不在一起:P),我试图在短时间内找到一个解决方案,这并不坏。在本文中,我试图描述我采用的解决方法,并讨论一些可能的改进。
简单来说,问题任务是:
预测曼联足球俱乐部在英超本赛季(18-19 赛季)积分榜上的最终排名
一些背景
超级联赛是英国足球联赛体系的最高级别,也是世界上收视率最高的体育联赛,潜在电视观众达 47 亿人(是的,它很受欢迎!).20 个俱乐部在一个赛季中比赛,每个俱乐部与其他俱乐部比赛两次(双循环制),一次在他们的主场体育场,一次客场,在他们对手的体育场,每队总共 38 场比赛。
总部位于老特拉福德的足球俱乐部曼彻斯特联队是最成功的俱乐部,创下了 20 个联赛冠军的记录,也是世界上最受支持的足球俱乐部之一。然而,起飞晚了,俱乐部一直遭受着一个混合了 管理 和 投资 的问题,这使得它(几乎)自上次举起这个有声望的头衔以来已经六年了。
谈到足球,我只是一个普通的球迷,但建立一个可以应用于现实世界问题的数学模型的想法似乎足够令人兴奋,值得一试。那我们开始吧,好吗?⚽️)
分解问题
联赛排名主要由每支球队的积分决定,*局则由净胜球打破。因此,为了预测曼联的最终排名,有必要估计所有球队的总积分。然后问题就变成了预测所有比赛的结果。
为了简单起见,可以假设每个匹配结果彼此独立,即任何匹配 X 的结果独立于任何其他匹配 y
两支球队之间的比赛可能有 3 种结果:主队获胜(H),客场获胜(A)或*局(T)。获胜的队伍得 3 分,*局得 1 分。
我们可以随机挑选结果,但那是而不是适合真实世界场景的好模型。实际上,顶级球队战胜低级弱队的机会更大。因此需要一些参数来衡量团队的实力
获取数据和选择参数
有什么比查看团队过去的数据更好的方法来衡量团队的表现呢?我使用了 http://www.football-data.co.uk/data的数据集,其中包括自 1992 年英超联赛成立以来的所有比赛结果,它们被整齐地编译成 CSV 文件。下一步是确定与团队实力密切相关的主导因素。我不得不提到 这篇 出色的博文,它在理解变量方面提供了一些很好的见解,以及非常整洁的 可视化 。可以总结出以下几点:
- 角球、犯规、红黄牌等因素与积分以及球队实力的关系很弱。
 - 正相关性最高的最显著因素是净胜球,它基本上转化为一支球队的进攻和防守实力的*衡。**
 - 有趣的是,拍摄的数量是成反比的!这意味着一支球队投篮次数越多,得分就越少😮。虽然乍一看似乎有悖逻辑,但事后看来,每一次没有转化为进球的射门尝试都不可避免地将控球权交还给对手,并让他们占据上风,因此出现了负相关。
 
坚持一个简单的模型,然后我决定使用主客场球队的全职进球数作为参数。
给我看看数学
有效地说,比赛的结果取决于双方的进球数。因此,我们需要对进球的概率分布进行建模。最常见的方法之一是通过泊松分布。( 来源 )
泊松分布测量给定数量的事件在固定时间间隔内发生的概率,前提是这些事件以已知的恒定速率发生,并且与上次事件后的时间无关。

Poisson distribution for x occurrences of the event, λ is the average rate and e is the Euler’s constant
为了理解为什么这个模型适合我们的情况,我们可以认为一个进球得分是一个事件。那么在 90 分钟的比赛时间内,每个这样的事件可以独立地发生任意次。
举个例子,让我们试着预测阿森纳和莱斯特城的比赛以 2-1 的比分结束的概率。

剩下的就是计算出恒定速率(λ)* 😗
可以直观地看出,该参数反映了球队的表现,越好的球队*均进球率越高。此外,这个比率取决于两个因素,球队的进攻实力和对手的防守实力。最后,我们还必须考虑到主场优势,也就是说,要考虑到一支球队通常在主场打得更好。
基于上面的讨论,我们可以将参数λ定义为一个队在特定场地的*均进球数,它可以使用过去的数据来计算。**
构建模型
那么让我们建立一些统计数据:

使用上述统计数据,我们现在可以将 λ 参数公式化为 :

模拟比赛
如前所述,两支球队之间的比赛可能有 3 种结果:主队获胜(H),客场获胜(A)或*局(T)。让主队进 X 球,客场进 Y 球。然后:

我们已经看到了如何计算比赛以比分 X-Y 结束的概率。此外,我们可以为一个球队的进球数设定一个实际的上限,比如说 10 个。最后,由于所有得分线都是相互独立的,因此可以简单地将概率相加:

因此,我们可以模拟主队(H)和客场队(A)之间的比赛,并预测各队的得分:
把所有的放在一起
为了预测最终的排名,我们简单地使用模型模拟所有的联赛比赛,并将预测的分数加到积分表中。
最终获得的结果:

所以看起来利物浦和曼城将会获得冠军,而切尔西将会超越热刺。预计曼联将获得第五名,阿森纳紧随其后。结果似乎与当时的普遍舆论一致— 让我们把弗格森带回来吧
点击 找到 的完整代码
结论
一如既往,还有很大的改进空间。一些想法可以尝试:
- 将时间作为一个因素考虑:一个团队的形式可以发挥重要作用,并且时间加权*均值可以被认为赋予最*的比赛更多的重要性
 - 看看经理当时的排名作为一个参数是否能提高效率,这可能会很有趣
 - 改善模型对*局的低估,一般的想法是现实世界中的*局机会碰巧比模型对*局的*均估计要多
 
尽管有缺点,这个模型是一个很好的起点,具有相当的准确性。这个练习很有趣,毕竟,它让我在:D 获得了第一名
使用机器学习预测心脏病的存在

机器学习在世界各地的许多领域都有应用。医疗保健行业也不例外。机器学习可以在预测运动障碍、心脏病等疾病的存在/不存在方面发挥重要作用。如果提前预测,这些信息可以为医生提供重要的见解,然后医生可以针对每个患者调整他们的诊断和治疗。
在这篇文章中,我将讨论一个项目,在这个项目中,我使用机器学习算法来预测人们潜在的心脏病。这些算法包括K Neighbors Classifier、Support Vector Classifier、Decision Tree Classifier和Random Forest Classifier。数据集取自 Kaggle 。我的完整项目可在心脏病预测获得。
导入库
我为这个项目导入了几个库:
- numpy :使用数组
 - pandas :处理 csv 文件和数据帧
 - matplotlib :用
pyplot创建图表,用rcParams定义参数,用cm.rainbow着色 - 警告:忽略笔记本中可能出现的所有警告,这些警告可能是由于某项功能过去/未来的折旧
 - train_test_split :将数据集拆分成训练和测试数据
 - StandardScaler :对所有特征进行缩放,使机器学习模型更好地适应数据集
 
接下来,我导入了所有必要的机器学习算法。
导入数据集
从 Kaggle 下载数据集后,我将它保存到我的工作目录中,命名为dataset.csv。接下来,我使用read_csv()读取数据集并将其保存到dataset变量中。
在做任何分析之前,我只想看一看数据。所以,我用了info()的方法。
从上面的输出可以看出,总共有 13 个特性和 1 个目标变量。此外,没有丢失的值,所以我们不需要关心任何空值。接下来我用了describe()的方法。

dataset.describe()
该方法揭示了每个变量的范围是不同的。age的最大值是 77,而chol的最大值是 564。因此,必须对数据集执行要素缩放。
理解数据
相关矩阵
首先,让我们看看特征的相关矩阵,并尝试分析它。使用rcParams将图形尺寸定义为 12 x 8。然后,我用 pyplot 展示了相关矩阵。使用xticks和yticks,我将名字添加到关联矩阵中。colorbar()显示矩阵的颜色条。

Correlation Matrix
很容易看出,没有一个单一的特征与我们的目标值有非常高的相关性。此外,一些特征与目标值负相关,一些特征与目标值正相关。
柱状图
这种类型的图最好的部分是,它只需要一个命令来绘制图,并提供如此多的信息作为回报。用dataset.hist()就行了。

dataset.hist()
我们来看看剧情。它显示了每个要素和标注在不同范围内的分布情况,这进一步证实了缩放的必要性。接下来,无论你在哪里看到离散的条,它基本上意味着这些实际上是一个分类变量。在应用机器学习之前,我们需要处理这些分类变量。我们的目标标签有两类,0 表示无疾病,1 表示有疾病。
目标类的条形图
我们正在处理的数据集应该大致*衡,这一点非常重要。一个极度不*衡的数据集会使整个模型训练变得无用,因此是没有用的。我们用一个例子来理解一下。
假设我们有一个 100 人的数据集,其中有 99 名非患者和 1 名患者。甚至不需要训练和学习任何东西,该模型总是可以说任何新人都将是非患者,并且准确率为 99%。然而,由于我们更感兴趣的是识别患者,我们需要*衡的数据集,以便我们的模型实际学习。
对于 x 轴,我使用了来自target列的unique()值,然后使用xticks设置它们的名称。对于 y 轴,我使用value_count()来获取每个类的值。我把条形涂成绿色和红色。

从图中,我们可以看到,类几乎是*衡的,我们很好地进行数据处理。
数据处理
为了处理分类变量,我们应该将每个分类列分成包含 1 和 0 的伪列。
假设我们有一个列Gender,值 1 表示男性,值 0 表示女性。它需要被转换成两列,其中值 1 表示该列为真,值 0 表示该列为假。看看下面的要点。
为了做到这一点,我们使用熊猫的get_dummies()方法。接下来,我们需要缩放数据集,我们将使用 StandardScaler。缩放器的fit_transform()方法缩放数据,我们更新列。
数据集现在准备好了。我们可以从训练我们的模型开始。
机器学习
在这个项目中,我采用了 4 种算法,改变了它们的各种参数,并比较了最终的模型。我将数据集分为67% training data和33% testing data。
k *邻分类器
该分类器寻找给定数据点的 K 个最*邻的类别,并且基于多数类别,它将类别分配给该数据点。然而,邻居的数量可以变化。我让他们从 1 到 20 个邻居变来变去,计算每种情况下的测试分数。
然后,我绘制了邻居数量和每种情况下的测试分数的线图。

如您所见,当邻居数量选择为 8 时,我们获得了 87%的最高分数。
支持向量分类器
该分类器旨在通过调整数据点和超*面之间的距离来形成一个能够尽可能多地分离类别的超*面。基于几个kernels来决定超*面。我试了四个内核,分别是,线性, poly , rbf ,和 sigmoid 。
一旦我得到了每个人的分数,我就使用rainbow方法为每个条选择不同的颜色,并绘制出每个人所获得分数的条形图。

从上面的图中可以看出,
linear内核在这个数据集上表现最好,获得了 83%的分数。
决策树分类器
该分类器创建一个决策树,并基于该决策树将类值分配给每个数据点。在这里,我们可以改变创建模型时要考虑的最大特征数。我将特征的范围从 1 到 30(添加虚拟列后数据集中的全部特征)。
一旦我们有了分数,我们就可以绘制一个线图,看看特征的数量对模型分数的影响。

从上面的线形图中,我们可以清楚地看到,最高得分为 79%,并且是在最大特征被选择为 2、4 或 18 的情况下实现的。
随机森林分类器
这个分类器将决策树的概念带到了下一个层次。它创建了一个树的森林,其中每棵树都是由从所有要素中随机选择的要素组成的。在这里,我们可以改变用于预测类别的树的数量。我计算了 10、100、200、500 和 1000 棵树的测试分数。
接下来,我将这些分数绘制在一个条形图上,看看哪个给出了最好的结果。您可能会注意到,我没有直接将 X 值设置为数组[10, 100, 200, 500, 1000]。它将显示从 10 到 1000 的连续图,这将是不可能破译的。所以,为了解决这个问题,我首先使用 X 值作为[1, 2, 3, 4, 5]。然后,我用xticks给它们重新命名。

看一下条形图,我们可以看到 100 和 500 棵树都达到了 84%的最高分数。
结论
该项目涉及通过适当的数据处理对心脏病患者数据集进行分析。然后,对 4 个模型进行训练和测试,最高得分如下:
- k *邻分类器:87%
 - 支持向量分类器:83%
 - 决策树分类器:79%
 - 随机森林分类器:84%
 
k 个邻居分类器在 8 个邻居的情况下取得了 87%的最好成绩。
感谢您的阅读!请随意分享你的想法和主意。
我试图用机器学习来预测比特币的价格
使用时间序列模型预测加密货币价格

Photo by André François McKenzie on Unsplash
更新:点击下方查看下一篇描述用深度学习预测比特币价格过程的文章
利用神经网络预测加密货币价格
towardsdatascience.com](/predicting-bitcoin-prices-with-deep-learning-438bc3cf9a6f)
预测未来不是一件容易的事。许多人尝试过,许多人失败了。但是我们中的许多人都想知道接下来会发生什么,并竭尽全力去弄清楚。想象一下知道未来会发生什么的可能性!想象一下,回到 2012 年,当比特币不到 15 美元,知道它将超过 18000 美元时,你会怎么做!许多人可能会后悔当时没有购买比特币,但他们一开始怎么会知道呢?这是我们现在在加密货币方面面临的困境。我们不想错过下一次价格上涨,但我们不知道这何时会发生或不会发生。那么,我们怎样才能潜在地解决这个困境呢?也许机器学习可以告诉我们答案。
机器学习模型可能会给我们提供了解加密货币未来所需的洞察力。它不会告诉我们未来,但它可能会告诉我们价格移动的一般趋势和方向。让我们尝试使用这些机器学习模型,并通过用 Python 编码来预测比特币的未来!
建模时间序列
我们要实现的机器学习模型叫做 时间序列 模型 。这些模型将研究过去,寻找预测未来的模式和趋势。如果没有这些模型,我们将不得不自己做所有这些分析,这将花费太多的时间。幸运的是,我们可以用 Python 编写这些时间序列模型来为我们做所有的工作,这就是我们今天要做的!
我们今天要用的时间序列模型有: 萨里玛 和一个由 脸书先知 实现的加法模型。萨里玛或 ARIMA 是一个相对基本的时间序列模型,我们将在必要时对其进行编码和解释。脸书 Prophet 使用一种快速可调的加法模型来预测时间序列数据。建模后,我们将比较每个模型对比特币未来的独特见解。
对 SARIMA 建模的步骤如下:
- 收集、探索和可视化数据。
 - 对数据求差并检查*稳性。
 - 绘制差异数据的 ACF 和 PACF。
 - 通过搜索最佳参数开始建模。
 - 用优化的参数训练和测试模型。
 - 预测未来!
 
这些描述非常简单明了,但我们很快会更详细地介绍每个步骤。以下代码片段摘自文末分享的 Github。
比特币价格数据
我们要做的第一件事是检索比特币的历史数据,这些数据可以从雅虎财经下载为一个方便的 CSV 文件。一旦我们有了这些,我们就可以开始将 CSV 文件格式化为一个熊猫数据帧。然后,我们使用相同的数据帧进行其余的绘图和计算。
另一种选择是使用财务数据 API,如 EOD 历史数据 。注册是免费的,你可以获得大量的金融数据。披露:我通过上面的链接从任何购买中赚取一小笔佣金。
Formatting/Organizing the Dataset
接下来,我们绘制数据图表,看看过去两年比特币的价格走势。选择过去两年是因为比特币和加密货币总体上变得非常受欢迎,并且更好地代表了当前的市场趋势。

*稳性
让我们通过使数据静止来为建模准备数据。我们通过简单地对数据进行差分并使用所谓的 迪基-富勒测试 来测试*稳性。我们的目标是使 P 值小于临界值 5%,或者只是尽可能接*零。对于更低的 P 值,我们取价格的对数,然后求对数的差,而不仅仅是求价格的差。
This gives a P-Value of 5.879487529183016e-25
你可能想知道为什么我们关心*稳性。简而言之,*稳性从数据集中移除趋势,这可能会极大地干扰我们的模型。基本上,*稳性使我们的模型表现和预测更好。

Our stationary differenced log of BTC.
ACF 和 PACF
接下来,我们必须绘制出自相关函数(ACF) 和部分自相关函数(PACF) 。由于我们处理的是每日数据,ACF 向我们展示了过去的哪一天与当前日期的相关性最大。PACF 通过忽略中间的日子,向我们展示了过去的哪一天与今天直接相关。

The ACF and PACF for the Log of BTC
萨里玛造型
通过了解 PACF 和 ACF,我们现在可以更好地理解我们的数据集和可能选择的参数。现在,我们可以继续使用 SARIMA 模型来建模我们的数据。
优化参数
为了获得模型的最佳性能,我们必须找到最佳参数。我们通过尝试许多不同的参数组合并选择具有相对最低的 AIC 分数 的组合来实现这一点。别担心,我们已经写了一个函数来完成这个任务。
According to this function, our best parameters are (1,0,0) for pdq and (0,0,0,0) for pdqs
根据您的电脑,寻找最佳参数的过程可能需要一段时间。对于像我们这样的人来说,我们将不得不满足于受计算机规格限制的最佳参数。不幸的是,并不是所有的计算机都是一样的,有些型号会根据运行它们的计算机而表现得更好。
装配和培训
现在我们有了参数,让我们继续训练并使模型适合比特币的价格。
为了进一步测试该模型的性能,我们可以通过绘制它们来看看它的预测与我们已经知道的值是如何一致的。

模型测试还可以,因为实际值仍然在我们的置信区间内(灰色阴影部分),价格也如预测的那样上涨。其余的训练数据似乎很好地符合我们的区间(绿色阴影),并与模型的预测值一致。
预测未来价格
现在我们可以进入我们真正想知道的部分了——预测比特币的未来价格!我们通过对今天的预测来做到这一点,并观察它在未来可能的走向。

General forecast of BTC
我们可能需要仔细看看。。。

根据该模型,比特币似乎将在未来一个月继续小幅上涨。但是,不要把这当成事实。阴影区域向我们展示了比特币价格在未来一个月的潜在走向,但它也碰巧显示了比特币可能会下跌。虽然,模型似乎在向价格上升而不是下降倾斜。
萨里玛的预测不应该是唯一需要考虑的预测。还有其他时间序列模型和程序需要考虑,其中一个实际上是由脸书的数据科学团队创建的!
脸书先知
使用脸书先知将比使用萨里玛建模相对容易。这是由于 FB Prophet 的简单易用。你将会看到与萨里玛相比,这要容易得多。
使用脸书先知的步骤是:
- 为 Prophet 格式化数据。
 - 根据数据拟合和训练模型。
 - 创建要预测的未来日期。
 - 预测和想象未来!
 
下面是对脸书先知使用上述步骤的代码:
脸书先知崩溃
在第一步中,我们通过为日期和价格创建两列来格式化之前的数据。然后,我们可以通过拟合和训练数据直接进入建模!无需调整参数或检查稳定性!
建模之后,我们现在可以前进到预测未来,首先创建我们希望 Prophet 为我们预测价格的未来日期。我们还可以绘制这些日期,这也将向我们展示模型如何与过去的价值相比较,以及价格接下来可能会走向哪里。

放大以*距离观察未来预测。。。

FB Prophet zoomed in
- 蓝线=预测值
 - 黑点=观察值(实际值)
 - 蓝色阴影区域=不确定性区间
 
据 FB Prophet 报道,比特币将在未来一个月内上涨。但还是那句话,这不是事实。相比萨里玛,FB Prophet 有更清晰的预测和方向。FB Prophet 有更多的特性和参数可以实验,但是我们在这里没有一一介绍。如果你觉得你需要改变模型,然后点击这里FB Prophet 的文件。
结束语
现在我们对比特币的未来有了两种预测,请随意对两者做出自己独特的观察,以确定比特币的未来。除了 SARIMA 和 FB Prophet,还有更多时间序列模型可以学习和实验。不要觉得仅限于这两个!我们刚刚做了时间序列、建模和机器学习的简要概述。还有更多的话题可以覆盖和研究!
预测比特币的未来几乎是不可能的,但通过机器学习,我们可以高度自信地理解它可能会走向何方。我们不建议使用这些机器学习模型来做出所有的投资决策,但很高兴看到比特币和加密货币的未来可能会发生什么!
资源:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/marcosan93/BTC-Forecaster) [## 我尝试了深度学习模型来预测比特币价格
towardsdatascience.com](/predicting-bitcoin-prices-with-deep-learning-438bc3cf9a6f)
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
用机器学习预测衰退
收益率曲线反转真正告诉我们什么

“这是最好的时代,这是最坏的时代,这是智慧的时代,这是愚蠢的时代,这是信仰的时代,这是怀疑的时代,”
这是一部经典文学作品的开场白,它在两个半世纪前的今天同样适用。在《双城记》中,查尔斯·狄更斯描述了法国大革命时期字面意义和隐喻意义的对立。虽然没有那么极端,但我们可以从它的段落中找到与当前环境的相似之处;当我们看到股市飙升至历史高点,收益率跌至历史低点时,全球经济的经济基本面仍然受到顽固的抑制。
众所周知,为了应对大衰退(GFC ),世界各地的中央银行同步向市场提供流动性,希望重新点燃增长和通胀。然而,这几乎是真正的狄更斯式的风格,对刺激工资增长和消费几乎没有什么作用。相反,较低的利率只会将资产推高到前所未有的估值水*,这对资产所有者非常有利,但却让普通人懊恼不已。简言之,富人变得更富了。
经济和定价的潜在驱动因素之间的这种错位,揭示了一种深刻而反常的动态绑定货币政策和市场预期。市场已经开始预期央行会继续放松货币政策,事实上,即使是也需要放松货币政策,以保持同样的上升势头。任何挑战这一共识的信息都引起了强烈的负面膝跳反应。值得注意的是,两周前,美联储十年来首次降息,这在理论上正是保持积极表现所需要的,但是降息的幅度(小于最初的预期)和鲍威尔主席的会后评论不利于持续的资产通胀叙事。因此,冒险行为会受到惩罚。
更*的是发生了收益率曲线反转现象。在过去 7 次美国经济衰退之前,两年期和十年期美国国债收益率之间被广泛关注的利差已被视为负值,导致许多市场评论员和从业者密切关注这一数据点作为领先指标。许多人已经注意到,经济逆转和衰退之间的历史时滞可能从几个月到*两年不等。作为注重数据的观察者,这为我们的调查奠定了完美的基础;鉴于市场对这一指标的持续和不相称的关注, 我们可以通过仅使用 10 年期和 2 年期美国国债之间的利差来实现机器学习以预测美国经济衰退吗?
设置

Photo by Todd Quackenbush on Unsplash
技术性衰退被定义为连续两个季度的负增长(GDP),因此我们可以从圣路易斯联邦研究经济数据库 这里 获得符合这一描述的日期。该时间序列采用二进制形式,1 表示衰退期,0 表示衰退期。

Source: St Louis Fed, Hamilton, James
接下来我们从同一个数据库 这里 获取收益率曲线利差数据。计算方法为月末 10 年期国债收益率减去 2 年期国债收益率。

Source: St Louis Fed
我们选择的机器学习工具是 逻辑回归 ,这是经济学家和数据科学家都喜欢的工具。我们使用这种特殊算法有三个原因:
- 该模型相对简单且易于理解,
 - 该分析相对简单且本质上是单变量的,
 - 市场修辞暗示了曲线反转和衰退之间的线性决策边界。
 
由于美国 GDP 数据的季度报告频率,需要进行两项调整:
- 我们将衰退数据集从季度数据集扩展到月度数据集,方法是隐含假设衰退季度内所有月份的增长都是负的。
 - 我们将收益率曲线利差数据后移四分之一,这是必要的,因为我们对 2y 和 10y 利差的预测能力感兴趣,在其原始形式中,两个数据点同时出现。使用一个数据点来预测同时可用的另一个数据点是一项毫无意义的任务。
 
结果
借助广义线性模型(glm)函数和 R 中的 Caret 包,我们将时间序列分成 70%的训练集和 30%的测试集。我们在训练集上拟合了 logit 模型,并根据测试进行了验证,结果如下:

Evaluation Metrics
预测精度简直太棒了! 87% !收益率曲线反转肯定是衰退的一个很好的预测指标!但是,等等,这里有些不对劲,让我们仔细看看评估指标。虽然准确率很高,但流行率、灵敏度和检出率都低得惊人。对混淆矩阵的检查可以提供一些额外的见解。

Confusion Matrix
我们可以立即看到,该模型非常擅长预测真正的否定(130 个正确预测),坦率地说,其他方面并不多。这说明了这个特定数据集的一个重要问题。虽然有数百个非逆转/非衰退的例子,但逆转/衰退的例子要少得多。这实际上是一个非常不*衡的数据集,如果我们预测测试集中的每一个实例都是非衰退的,我们仍然可以得到 85%的准确率。如果我们在评估指标中查看*衡的准确率(调整了不*衡),我们会发现该模型比掷硬币好不了多少(58%)。这似乎与评论和新闻会让我们相信的相矛盾,那么,收益率曲线反转到底告诉了我们什么?
结论
虽然收益率曲线的期限结构中有关于经济增长前景的信息,这得到了大量学术文献和理论的支持(见 FRB 文章 此处 和 Ang,Piazzesi and Wei,2003 ),但我们不应通过孤立地查看一个数据点来设计错误的精确度。经济作为一系列不断相互作用的运动部分而存在,因此需要被视为一个整体。与未来前景同样相关的是通胀机制和货币政策方向。仅使用曲线反转作为衰退的预测指标,是一个精选数据来拟合预先构建的描述的典型例子。这种类型的行为偏见并非没有先例,诺贝尔奖获得者丹尼尔·卡内曼和阿莫斯·特沃斯基推测,当面临不确定性时,人类会求助于启发法/经验法则来帮助我们做出决定。虽然我们都只是人类,但我们仍然有独特的能力使用机器学习等定量工具来客观验证未经证实的说法,如果有机会,我们应该行使这一权利。虽然没有提供代码,但如果有兴趣的话,我很乐意在另一篇文章中用 R 代码完整地讨论这种方法。
参考文献
安,皮亚泽西,米和魏,米(2003)。关于 GDP 增长,收益率曲线告诉了我们什么?。 SSRN 电子杂志。
免责声明:本帖纯属个人观点和看法的表达。它不代表任何建议,也不反映我的雇主的观点。
使用 Fastai 预测房地产图像中的丰富属性
大卫·塞缪尔和纳文·库马尔

概观
视觉属性搜索可以极大的提升用户体验,针对家居房源和旅游网站的 SEO。尽管 Zillow、Redfin、Airbnb 和猫途鹰已经有了一些关于房产设施的元数据,但他们可以通过用视觉模型分析房产图像来扩展可搜索的属性。
在本帖中,我们分享了我们对预测房产属性(如景观、厨房岛、游泳池、高天花板、硬木地板、壁炉等)的几个镜头模型的初步方法。由于这些属性通常依赖于房间和环境,我们从一个精确的分类模型开始,将我们的图像分组到酒店的内部和外部设置中。
在训练我们最初的房间类型模型的过程中,我们注意到这些丰富的属性中的一些很容易在 platform.ai 中分离。
背景
以前的工作集中在使用图像来改善价格估计[1],但是将图像特征添加到定价模型的增量收益很小;与使用一些传统属性(如位置和物业大小)相比,性能提高了 2.3%。虽然构建这些模型的价格数据已经很容易获得,但预测丰富属性(如景观、厨房岛、游泳池、高天花板、硬木地板、壁炉等)的数据集却很稀缺。
我们的初始数据集,以前用于价格估算[1],由 146,791 张图片和七个类别组成:客厅、餐厅、卧室、浴室、厨房、室内和室外。

Fig 1. Class count of real estate images
浴室是最缺乏代表性的一个类别,其图片数量比任何其他类别都少*一半。我们使用 fastai 的 vision.transform 方法【4】解决了这种类别不*衡,使用默认图像增强对数据进行过采样。

Fig 2. Example image augmentation of the classes: bathroom, dining room, kitchen, living room, bedroom, interior, and exterior.
这些图像是使用 fast.ai 的内置变换进行预处理的。数据被随机分成 60%训练、20%验证和 20%测试。
该模型用 ImageNet-ResNet34 权重初始化。网络的定制头被训练 3 个时期,随后解冻整个网络,并使用区别性学习速率微调另外 10 个时期。微调提高了模型拟合度,实现了 97%的总体测试集精度。
通过将网络容量增加到 ResNet50,实现了 98%的最终准确性——比之前结果的 91%准确性有了显著提高[1]。
构建丰富的属性数据集
我们通过抓取房产列表网站构建了一个丰富的属性数据集。爬行器捕获了图像和感兴趣的属性。总共获得了 18,790 个列表和 350,000 张图片。
要素类分布
我们的 web scraper 捕获了非结构化的 html,并提取了清单的 details 表中包含的丰富属性。

Fig 3. Example scraped listing text metadata

Figure 4. Feature class distribution from crawled data
最终的数据集由 18,790 个单独的列表组成,每个列表*均包含 21 张图片。我们已经确定了照片中可见的几个特征,如水池、天井、厨房岛和壁炉。在我们的数据集中,*一半的房源有游泳池或露台,只有大约 25 个房源有酒窖。此外,可以在不同的空间中看到属性的外观;现代酒窖倾向于在地面上。

Fig 5a. Example feature from listings dataset: wine cellar

Fig 5b. Example feature from listings dataset: wine cellar

Fig 5c. Example feature from listings dataset: wine cellar

Fig 5d. Example feature from listings dataset: wine cellar
预测
我们将我们的模型和来自我们数据集的 20,000 张图像的样本上传到 platform.ai ,以便将其性能与预先构建的 ImageNet 模型进行比较。我们的模型形成了整齐的集群,很容易用眼睛分开,具有相似的兴趣属性,如壁炉、水池和厨房岛。相比之下,ImageNet 倾向于形成具有不同属性的更宽的集群。

Fig 6. Pictured: Our Model’s Projection

Fig 7. Pictured: ImageNet Projection

Fig 8. Zoomed in projections show a fireplace cluster.

Fig 9. Zoomed in projections show a kitchen islands cluster.

Fig 10. Zoomed in Projections, and selected images from our model show an outdoor swimming pool cluster.
使用投影作为视觉辅助,感兴趣的集群被突出显示,并使用 platform.ai 选择性地过滤。我们的模型投影的放大视图显示了我们通过模型识别的三个丰富的特征:壁炉、厨房岛和游泳池。与 ImageNet 相比,我们可以看到更多与丰富属性紧密相关的群集,而不是标记的房间类别功能。
聚类分析
下载我们的投影后,我们能够评估一个聚类解决方案,将我们的模型的轮廓分数与 ImageNet 进行比较。结果表明,我们的侧影得分明显大于 ImageNet 在 K = 5k-均值聚类侧影得分上的 t-检验结果。因此,我们的模型比 ImageNet-ResNet 更一致地产生相似的聚类。

Fig 9. Similarity “Silhouette” scores for k=5 K-Means clusters.

Table I. Silhouette Score summary statistics
结论
应用现代机器学习实践,我们开发了一个计算机视觉模型,它不仅可以预测房间类别,还可以预测我们居住的房屋的深层属性。通过将我们的嵌套属性更紧密地聚集在一起,它比 ImageNet 表现得更好,允许视觉上可分离的组被提取和标记。开发一个精确的属性搜索模型可以作为一个重要的搜索工具来找到合适的房屋或出租。
我们计划进一步开发我们的模型,使用来自我们数据集的有限标记数据和关系网络(RN) [2]来分类图像中的多个属性。
承认
我们要感谢 Arshak Navruzyan 在这个项目中给予的支持和指导。我们还要感谢 fastai 团队提供了一个方便的深度学习库。
参考
- Poursaeed,Omid 等基于视觉的房地产价格估算。机器视觉与应用 29(2018):667–676。
 - 桑托罗、亚当等人一个用于关系推理的简单神经网络模块。NIPS (2017 年)。
 - 何,等.【深度残差学习用于图像识别】。2016 年 IEEE 计算机视觉和模式识别大会(CVPR)(2016):770–778。
 - 霍华德、杰瑞米等人法斯泰图书馆。2019.
 - Clarke,Adrian 等人在 fastai 中优化图像数据集的超参数。2019
 
预测销售额

使用 Python 实现数据驱动的增长
与 LSTM 一起预测月销售额
这一系列文章旨在解释如何以一种简单的方式使用 Python,通过将预测方法应用于您的所有行动来推动您公司的发展。它将是编程、数据分析和机器学习的结合。
我将在以下九篇文章中讨论所有主题:
1- 了解你的衡量标准
2- 客户细分
3- 客户终身价值预测
4- 流失预测
6- 预测销售额
文章将有自己的代码片段,使您可以轻松地应用它们。如果你是编程的超级新手,你可以在这里很好地介绍一下 Python 和 Pandas (一个我们将在任何事情上使用的著名库)。但是仍然没有编码介绍,您可以学习概念,如何使用您的数据并开始从中产生价值:
有时候你得先跑,然后才能走——托尼·斯塔克
作为先决条件,确保你的电脑上安装了 J upyter Notebook 和 P ython 。代码片段只能在 Jupyter 笔记本上运行。
好吧,我们开始吧。
第 6 部分:预测销售额
在本节之前,我们几乎所有的预测模型都是基于客户层面的(例如,流失预测、下一个购买日等)。).缩小视野,看看更广阔的图景也是有用的。通过考虑我们在客户方面的所有努力,我们如何影响销售?
时间序列预测是机器学习的主要组成部分之一。文献中有许多方法可以实现这一点,如自回归综合移动*均(ARIMA)、季节自回归综合移动*均(SARIMA)、向量自回归(VAR)等。
在本文中,我们将重点关注长短期记忆(LSTM)方法,如果你想使用深度学习,这是一种非常流行的方法。我们将在我们的项目中使用 Keras 来实现 LSTM。
最后,了解未来销售对我们的业务有什么帮助?
首先,它是一个标杆。如果我们的战略没有任何变化,我们可以将它作为我们将要实现的业务照常水*。此外,我们可以在这个基准之上计算我们新行动的增量价值。
第二,它可以用于规划。我们可以通过查看预测来计划我们的需求和供应行动。这有助于了解在哪些方面投资更多。
最后但同样重要的是,它是一个规划预算和目标的优秀指南。
现在是时候跳入编码,建立我们的第一个深度学习模型了。我们模型的实施将有 3 个步骤:
- 数据争论
 - 数据转换,使其稳定并受到监督
 - 建立 LSTM 模型和评估
 
数据争论
在这个例子中,我们使用来自 Kaggle 竞赛的数据集。它表示每个商店和商品的每日销售额。
像往常一样,我们从导入所需的库和从 CSV 导入数据开始:
我们的数据如下所示:

我们的任务是预测每月的总销售额。我们需要按月汇总我们的数据,并对销售列求和。
#represent month in date field as its first day
df_sales['date'] = df_sales['date'].dt.year.astype('str') + '-' + df_sales['date'].dt.month.astype('str') + '-01'
df_sales['date'] = pd.to_datetime(df_sales['date'])#groupby date and sum the sales
df_sales = df_sales.groupby('date').sales.sum().reset_index()
应用上面的代码后, df_sales 现在显示了我们需要的总销售额:

数据转换
为了更容易、更准确地模拟我们的预测,我们将进行以下转换:
- 如果不是,我们将把数据转换成静态的
 - 从时间序列转换为受监督的,以获得我们的 LSTM 模型的特征集
 - 缩放数据
 
首先,我们如何检查数据是否不稳定?让我们画出来看看:
#plot monthly sales
plot_data = [
    go.Scatter(
        x=df_sales['date'],
        y=df_sales['sales'],
    )
]plot_layout = go.Layout(
        title='Montly Sales'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)
月度销售图表:

Monthly Sales — not stationary
显然,它不是静止不变的,在几个月内有增加的趋势。一种方法是获得与前一个月相比的销售差额,并在此基础上建立模型:
#create a new dataframe to model the difference
df_diff = df_sales.copy()#add previous sales to the next row
df_diff['prev_sales'] = df_diff['sales'].shift(1)#drop the null values and calculate the difference
df_diff = df_diff.dropna()
df_diff['diff'] = (df_diff['sales'] - df_diff['prev_sales'])df_diff.head(10)
现在我们有了建模差异所需的数据框架:

让我们画出它并检查它现在是否是静止的:
#plot sales diff
plot_data = [
    go.Scatter(
        x=df_diff['date'],
        y=df_diff['diff'],
    )
]plot_layout = go.Layout(
        title='Montly Sales Diff'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)

Monthly Sales Difference — stationary
完美!现在我们可以开始构建我们的特性集了。我们需要用以前的月度销售数据来预测下一个月。每个型号的回顾期可能会有所不同。在这个例子中,我们的将是 12。
所以我们需要做的是创建从 lag_1 到 lag_12 的列,并通过使用 shift() 方法赋值:
#create dataframe for transformation from time series to supervised
df_supervised = df_diff.drop(['prev_sales'],axis=1)#adding lags
for inc in range(1,13):
    field_name = 'lag_' + str(inc)
    df_supervised[field_name] = df_supervised['diff'].shift(inc)#drop null values
df_supervised = df_supervised.dropna().reset_index(drop=True)
查看我们名为 df_supervised 的新数据框架:

我们现在有了自己的功能集。让我们再好奇一点,问这个问题:
我们的特征对预测有多大用处?
调整后的 R *方就是答案。它告诉我们我们的特征如何很好地解释了我们标签中的变化(在我们的例子中,对于 diff,从 lag_1 到 lag_12)。
让我们看一个例子:
# Import statsmodels.formula.api
import statsmodels.formula.api as smf# Define the regression formula
model = smf.ols(formula='diff ~ lag_1', data=df_supervised)# Fit the regression
model_fit = model.fit()# Extract the adjusted r-squared
regression_adj_rsq = model_fit.rsquared_adj
print(regression_adj_rsq)
那么上面发生了什么?
基本上,我们拟合一个线性回归模型(OLS——普通最小二乘法),并计算调整后的 R *方。对于上面的例子,我们只是使用了 lag_1 来看看它在多大程度上解释了列 diff 中的变化。这个代码块的输出是:

lag_1 解释了 3%的变异。让我们看看其他的:

再增加四个功能,得分从 3%增加到 44%。
如果我们使用整个功能集,得分如何:

结果令人印象深刻,因为分数是 98%。现在,我们可以在扩展数据后自信地构建我们的模型。但是在缩放之前还有一个步骤。我们应该将数据分成训练集和测试集。作为测试集,我们选择了过去 6 个月的销售额。
#import MinMaxScaler and create a new dataframe for LSTM model
from sklearn.preprocessing import MinMaxScaler
df_model = df_supervised.drop(['sales','date'],axis=1)#split train and test set
train_set, test_set = df_model[0:-6].values, df_model[-6:].values
作为缩放器,我们将使用 MinMaxScaler,它将在-1 和 1:
#apply Min Max Scaler
scaler = MinMaxScaler(feature_range=(-1, 1))
scaler = scaler.fit(train_set)
# reshape training set
train_set = train_set.reshape(train_set.shape[0], train_set.shape[1])
train_set_scaled = scaler.transform(train_set)# reshape test set
test_set = test_set.reshape(test_set.shape[0], test_set.shape[1])
test_set_scaled = scaler.transform(test_set)
建立 LSTM 模式
一切准备就绪,构建我们的第一个深度学习模型。让我们从缩放数据集创建要素和标注集:
X_train, y_train = train_set_scaled[:, 1:], train_set_scaled[:, 0:1]
X_train = X_train.reshape(X_train.shape[0], 1, X_train.shape[1])X_test, y_test = test_set_scaled[:, 1:], test_set_scaled[:, 0:1]
X_test = X_test.reshape(X_test.shape[0], 1, X_test.shape[1])
让我们来拟合我们的 LSTM 模型:
model = Sequential()
model.add(LSTM(4, batch_input_shape=(1, X_train.shape[1], X_train.shape[2]), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(X_train, y_train, nb_epoch=100, batch_size=1, verbose=1, shuffle=False)
上面的代码块显示了模型如何自我改进并减少每个时期的误差:

让我们做预测,看看结果是什么样的:
y_pred = model.predict(X_test,batch_size=1)#for multistep prediction, you need to replace X_test values with the predictions coming from t-1


y_pred vs y_test
结果看起来相似,但它并没有告诉我们太多,因为这些是显示差异的缩放数据。我们如何能看到实际的销售预测?
首先,我们需要进行缩放的逆变换:
#reshape y_pred
y_pred = y_pred.reshape(y_pred.shape[0], 1, y_pred.shape[1])#rebuild test set for inverse transform
pred_test_set = []
for index in range(0,len(y_pred)):
    print np.concatenate([y_pred[index],X_test[index]],axis=1)
    pred_test_set.append(np.concatenate([y_pred[index],X_test[index]],axis=1))#reshape pred_test_set
pred_test_set = np.array(pred_test_set)
pred_test_set = pred_test_set.reshape(pred_test_set.shape[0], pred_test_set.shape[2])#inverse transform
pred_test_set_inverted = scaler.inverse_transform(pred_test_set)
第二,我们需要建立一个有日期和预测的数据框架。转变后的预测显示了不同之处。我们应该计算预测的销售数字:
#create dataframe that shows the predicted sales
result_list = []
sales_dates = list(df_sales[-7:].date)
act_sales = list(df_sales[-7:].sales)
for index in range(0,len(pred_test_set_inverted)):
    result_dict = {}
    result_dict['pred_value'] = int(pred_test_set_inverted[index][0] + act_sales[index])
    result_dict['date'] = sales_dates[index+1]
    result_list.append(result_dict)
df_result = pd.DataFrame(result_list)#for multistep prediction, replace act_sales with the predicted sales
输出:

太好了!我们已经预测了未来六个月的销售数字。让我们在图中检查它们,看看我们的模型有多好:
#merge with actual sales dataframe
df_sales_pred = pd.merge(df_sales,df_result,on='date',how='left')#plot actual and predicted
plot_data = [
    go.Scatter(
        x=df_sales_pred['date'],
        y=df_sales_pred['sales'],
        name='actual'
    ),
        go.Scatter(
        x=df_sales_pred['date'],
        y=df_sales_pred['pred_value'],
        name='predicted'
    )
]plot_layout = go.Layout(
        title='Sales Prediction'
    )
fig = go.Figure(data=plot_data, layout=plot_layout)
pyoff.iplot(fig)
实际与预测:

对于一个简单的模型来说看起来相当不错。
我们可以对这个模型做的一个改进是添加假期、休息和其他季节性影响。它们可以简单地作为新功能添加。
通过使用这个模型,我们有了基线销售预测。但是我们如何预测促销对销售的影响呢?我们将在第 7 部分对此进行研究。
你可以在这里找到这篇文章的 Jupyter 笔记本。
需要帮助来发展你的公司吗?点击这里,与我一起预订免费课程。
利用深度学习和卫星图像预测融雪模式
听完整的播客插曲:苹果 | 谷歌 | SPOTIFY | 其他
与 Kaggle 数据科学家 Jessica Li 的对话

大家好!
前几天,我在走向数据科学播客中采访了 Kaggle 的数据科学家 Jessica Li。在这篇文章中,我想呈现一些采访中的亮点。
下面,我将分享一些我问她的问题,以及她回答的摘要。
注:您可以在Twitter @ Jessica Li 9530上关注 Jessica,了解她未来的更新。
问:你是如何从学习地理变成一名数据科学家的?
地理过去更多的是制作地图,但现在不是了。
随着越来越多的卫星/空间图像变得可用,并且随着计算大量数据变得更加高效,对地理空间数据运行机器学习模型变得可能。这也是我在学校学到的。
当我开始申请数据科学工作时,我注意到肯定有一些重叠。这些技能包括 Python、R,显然还有数据科学和机器学习。
问:所以你在学校学到了这些技能?
是的,但是大学对我来说是一段有趣的时光,因为我有 4 年没有单一的专业。我经常跳来跳去,从医学预科到会计学,再到我喜欢的地理。我大学只学了两年地理。
这也是为什么我说我还在学习。大学毕业才 1.5 年,和很多人一样,我非常自学数据科学。所以,我的学习之旅还在继续。
问:你是如何在 Kaggle 获得数据科学工作的?
就像他们说的,人脉是关键。我搬到了纽约,在完成学位后的 2-3 个月里,我没有找到工作。所以,不知道我的工作将会是什么会有一些不确定性。
在我第三个月的时候,我去了一个在 meetup.com 上找到的聚会。如果你在找工作,我强烈推荐你去看看这个网站。
我去的聚会叫做 Geo NYC。在那里,人们分享他们在工作或闲暇时所做的大量地理空间分析。我在那里遇到了一个人,他把我介绍给了车队,剩下的就是历史了。
问:所以你搬到了纽约,却没有得到那里的工作机会?
是的,我会说这是我做过的最冒险的举动之一。我以前搬过几次家。我是澳大利亚人,但我在中国住过一段时间,为了上学我搬到了洛杉矶。所以,搬家本身并不可怕,但是搬到一个我不认识很多人的城市绝对是一个冒险的举动。
然而,当我想到让我走到今天的重要时刻时,所有这些都是冒险的决定。所以,我觉得如果我谨慎行事,我就不会有今天。
问:我今天想采访你的原因之一是因为你与美国宇航局合作的项目。你能给我们讲讲吗?
当然可以!这是一个与美国宇航局合作的为期 10 周的独立研究项目。这是 2018 年的夏天。我和另外两个队友一起工作。
该项目的范围是预测犹他州弗里蒙特河流域的水资源可利用性。那里的国家公园管理局想要一种工具来评估每年融雪季节后他们从流域获得的水量。河流流量评估很糟糕,他们也没有得到关于他们每年将得到多少水的准确预测。
这对他们来说是一个重要的项目,因为弗里蒙特河流域提供了大约 16,000 英亩的农业灌溉面积。因此,对于核电厂来说,知道他们将得到多少水,以便他们能够做出正确的水资源管理决策,这是非常重要的。然而,情况并不乐观。这就是为什么美国宇航局希望我们的团队建立一个模型,可以更好地预测这一点。
NASA’s explainer video on the project
问:为了预测这些水资源,你是预测降雪还是仅仅预测融雪?
好问题。花了一些时间来思考目标变量是什么。在这种情况下,我们感兴趣的是降雪后会发生什么。换句话说,我们决定将 streamflow 作为我们的目标变量。Streamflow 就是在给定的点流入河流的水量。
问:所以,基本上,你知道给定年份有多少雪,你想预测你会得到多少流量?
没错。现在,在一个典型的机器学习项目中,您开始探索您的数据,以确定哪种信息与您的项目相关。然后,您将想要识别您的目标变量——在本例中是 streamflow。下一部分将是数据收集和特征工程。在这一部分,你需要收集所有你认为会影响或有助于预测目标变量的预测变量。
我认为让这个项目更合适的是我们有卫星图像作为预测变量。
所以,美国宇航局有一套地球观测和卫星图像。最后,我们需要进行大量的计算,因为这些数据由许多像素组成。这是很多数据,但它们被证明是预测河流流量的很好的预测变量。
问:有多少数据?
我们有 MODIS,它给了我们两种不同的信息——这是两个变量。PERSIANN-CDR——这些都是卫星名称——是指降水量,所以是三个。再加上一些数据源,我们总共有 8 或 9 个变量。这些都是日常信息,我们有超过 2-3 年的时间。所以,你可以想象这是一个很大的数据。我们最终的数据集是 13-14 列数据,包含大约 3 年的观察值。
问:那可能是几百兆字节或几千兆字节?
绝对成千兆字节。卫星将信息记录为地球某一部分的图像。例如,卫星可以每天一次测量美国的地表温度。所以,这将是一幅图像,每一个像素代表地球上一个特定位置的温度。
由于这是大量的数据,我们决定对其中一些进行*均。我们想得到不同地区的粗略地表温度,最后,我们将流域地区分成三个不同的区域,并计算每个区域的日*均温度。
我们也为被雪覆盖的地区做了同样的事情。对于这一个,我们想计算总面积,而不是取*均值。就像我们对温度所做的一样,我们将所有对应于雪的像素相加,并找到总面积。
问:你的数据中有哪些像素是雪,哪些不是雪的信息?
是的,我要研究一下卫星图像是如何工作的。这真的是地理吸引我去学这个专业的部分。
现在,当我们给任何东西拍照时,我们实际上是在记录某种信息。
这对卫星图像和数码摄影来说意味着每个像素都有某种电磁波谱信息。
因此,地球上的每样东西都以某种方式反射电磁波谱中的光。一种你可以数字化识别雪的方法是通过它独特的反射光谱。雪是白色的,它的化学成分使它具有独特的特征。
记住这一点,你遍历每个像素,寻找一条特定形状的曲线。通过这种类型的计算,您将能够识别哪些像素是雪,哪些不是。
在这里,重要的是要记住,这不是一个二元的事情。你会得到一个连续的光谱,显示每个像素与电磁信号的相似程度。例如,一个给定的区域可能有 80%与之匹配。因此,您最终会得到一个置信度,例如,“这更有可能是雪”,以及“这不太可能是雪。”在此基础上对每个像素进行重新分类后,你将能够更清楚地了解给定图片中的实际降雪量。
问:好,回到这个分析。我记得你提到过你有 7 或 8 个预测变量?
我们有 10-11 个预测变量,其中 4 个是卫星图像。
问:有像图像一样的数据,也有非像图像一样的数据?
没错。非图像类数据基本上是表格。一个例子是每天的雪水当量,我认为这与雪中所含的水量有关——本质上是雪能制造多少水。那是以表格形式给出的信息。
目标变量也是表格形式——日流量。
所以,本质上,我们有一堆图像式的数据和表格数据。
然后,我们将它分成训练数据和测试数据。
如果我们有,比如说,2-3 年的数据,只有最* 6 个月的数据才算测试数据。其余的被当作训练数据。
问:你最后用的是什么型号?
我们最终使用了 LSTM 模型,它代表长短期记忆模型。
问:我听说过它,但我对它不太熟悉——你能解释一下它是如何工作的吗?
神经网络有许多变量,LSTM 是其中之一。这是一种循环神经网络。我可能不是解释这件事的最佳人选,但我会尽力而为!
从很高的层面来看,递归网络就像神经网络一样,但问题是它们有循环。它们适用于时间预测问题,在这种情况下,您会发现之前发生的一些事情会影响以后的分析。
例如,在我们的项目中,融雪肯定有时间滞后因素。仅仅因为我们的卫星图像显示我们那天有这么多雪,这并不意味着我们在同一天会有一些水流。所以,我们需要考虑一些时间因素。递归神经网络有很好的记忆成分来捕捉这些信息。它使我们能够将昨天的变量与明天的流量联系起来。
有一篇很好的 TDS 文章解释了 LSTM 神经网络的数学原理。我认为文章中使用的比喻是一个人在阅读一篇文章。当你读一个句子时,你是基于你在句子中读到的更早的单词来理解它的。这里有一些连续性,你必须着眼于大局来理解正在发生的一切。传统的神经网络无法捕捉这种类型的信息。另一方面,RNN 氏症可以。
问:在你的分析中,你尝试过使用其他模型吗?
对于任何类型的问题,我喜欢做的是首先尝试所有的标准模型。因此,你也许能够考虑你的问题的范围,并开始对你的问题进行分类。比如是不是二元分类问题?是多分类问题吗?就是这个时间序列,表格,情绪分析等。?对于这个问题,它显然看起来像一个时间预测问题。
基于此,我上了 scikit-learn 并尝试了一些行业标准模型。尝试简单回归总是好的,我们尝试了。然后,我们把它喂给了 SVM。当然,我们尝试了 XGBoost。
问:我明白了。所以你尝试了回归、SVM、XGBoost 和 LSTM。
在我们尝试 LSTM 之前,我们先尝试了一个 ARIMA 模型。在 LSTM 变得流行之前,ARIMA 曾经更主流。众所周知,它能够考虑到我前面提到一些时间关系。然而,它没有产生非常准确的结果。
帮助我选择 LSTM 作为我们预测模型的是和一个解决过类似问题的人交谈。我在网上找到了一篇类似的论文,也是关于使用卫星图像数据进行预测的。
我联系了这个人,他能够倾听我的问题,并建议我使用 LSTM。结果成功了,这给他带来了很大的荣誉。
问:和 ARIMA 相比怎么样?LSTM 超过它了吗?
是的,LSTM 的表现远远超过了其他任何一个国家。我们要么经历了不准确的预测,要么经历了太多的 ARIMA。当我们对测试数据进行测试时,预测是错误的——感觉预测非常静态。
融雪有潮起潮落的现象,虽然所有的模型都能够理解它,但它们不一定能捕捉到多年来融雪速度的差异。在过去的 17 年里,该地区的融雪时间越来越早,径流量也在减少。许多模型无法捕捉这种长期趋势,即使它们可以捕捉基本的上下波动。
问:LSTM 模型能够捕捉到这一点吗?
是的,那很棒。我记得,去年的数据里,streamflow 肯定是有减少的,但是很微妙。LSTM 是唯一能够抓住它的人。
问:当你着手解决这个问题时,有没有遇到什么特别的挑战?
这里有许多挑战,功能工程是其中之一。在这方面,让这个问题变得特别困难的一点是,人们需要了解像温度趋势这样的事情。一个特别具有挑战性的方面是理解雪是如何工作的。
在学校,我的专业是研究水资源,在这个项目中,水和雪的不同表现令人惊讶。我不得不学习许多关于雪的随机知识。例如,有人可能会说,我们应该考虑一个捕捉融雪下山速度的参数。也就是说,雪可能在某些天融化得更快,而在另一些天融化得更慢。我们试图找到一个参数来捕捉这一点,这涉及到学习大量的水科学。
问:还有其他挑战吗?
是的。本来这个项目的推荐范围并没有建议在任何地方使用机器学习。我们进来了,问题是简单地预测水流。有一些推荐的论文可以阅读,NASA 也有一些他们认为我们可以在其上工作的框架。
作为项目领导,这是一个挑战,因为看起来建议的方法可行,但这并不是我们真正想要做的。我认为这说明了从传统编程到数据科学的范式,以及尝试将其应用于我们周围更多事物的努力。
这个模型是以传统方式构建的,这意味着许多值和算法都是硬编码的,专门用于构建它的目的。
我记得这个模型是为智利的一个水资源项目建造的,所以我们必须重新创建这个模型。所有的权重和算法都适合那个特定的项目。
总而言之,这是这个项目中的一个压力点。我们已经进行了 10 周的 3 周。我很快学会了 MATLAB 来查看模型,感觉这不是我的团队想要采取的方法。在那种情况下,我不得不上报给我的经理和其他人,告诉他们我们想尝试其他方式。
很自然,如果你想改变项目的范围,你必须提出一个建议。当我们与这些人交谈时,我们已经想到用机器学习来代替。因此,我们提出了一个新的范围,指定了我们想要尝试的数据和模型的类型。
这需要一些说服力,因为机器学习仍然是一个相对较新的领域。即使这是每个人都在谈论的技术,当你推断到政府和 NPS 之类的东西时,许多人仍然不熟悉它。这将是一个过程,可能需要几年或几代人才能让他们理解它是如何工作的。
机器学习的倡导对我来说非常重要,在这个项目中,我们能够倡导这一点。最后,他们让我们做了,对此我也很高兴。
使用分类预测启动失败

这个项目是名为 Metis 的沉浸式数据科学项目的一部分。你可以在我的 GitHub 和幻灯片 这里 找到这个项目的文件。最终的模型在这里是可访问的
一点背景知识
最*,我测试了一系列分类算法,看看我能否使用 CrunchBase 数据集预测一家初创公司是否会失败。通常,有人需要一个企业帐户来访问这些数据,但我能够在不久前找到一个副本。CrunchBase 是风险投资公司了解他们可能投资的公司的绝佳资源。他们中的许多人为企业访问支付额外费用,以获得高级搜索等附加功能。
对于这些公司来说,使用这些数据和机器学习工具来预测潜在投资在未来可能会如何发展将是有利的。这是因为风险投资会接触大量不同的公司,但只投资其中的一小部分,审查所有公司真的很乏味。拥有相关的领域知识会有所帮助,但是,有了 CrunchBase 上的所有可用数据,应该可以在没有太多先验知识的情况下做出一些决策。
此外,随着初创公司保持更长时间的私有,后期投资最*变得越来越受欢迎。这产生了更多关于早期业绩的数据,我用这些数据构建了一个工具(将在 CrunchBase Enterprise 等*台上使用),以帮助比较公司并预测它们的成功机会。
该过程
CrunchBase 数据集提供了一个全面的公司列表,其中包含大量关于它们的信息,以及它们每一轮融资和单个投资的明细。由于创业环境不断变化,我只研究了过去 10 年内成立的公司。我也排除了那些只进行了一轮融资就失败的公司。成千上万的公司被分为两组:失败的公司和成功的公司(仍处于早期阶段的公司也被排除在外)。这给我留下了大约 10000 家公司。
清理完所有数据后,我就可以设置所有感兴趣的特性了。这些信息包括每家公司的融资轮次、行业和地点。一旦我做好了所有这些准备,我测试了相当多的分类模型,以找到最好的一个。下面是每个基线模型的 ROC 曲线图。

ROC Curves for each baseline classification model
我用它和另一个指标来比较每个模型:f_beta,它是召回率和精确度之间的加权调和*均值。我将 beta 值设置为 3,这意味着召回比精确更重要。当考虑风险资本投资时,大部分回报通常来自不到 20%的投资。更重要的是抓住所有潜在的独角兽,即使是以投资相当多的废物为代价。考虑到一只独角兽可以轻松获得超过原始投资 100 倍的回报,取消其中一项需要相当多的“哑弹”。
结果
在建立了最初的模型后,我挑选了最有希望的模型,并调整了它们的各种超参数,以找到预测能力最强的模型。(为了简单起见,这个我就不赘述了。如果对这个过程有任何疑问,请随时联系我们。)考虑到用例,可解释性对我来说也是一个优先考虑的问题,所以我更关注逻辑回归和基于树的模型,它们具有很高的可解释性。
选择的模型是逻辑回归,它将公司的成功几率作为前面描述的特征的函数来计算。这款车型的 f_beta 评分是 0.85 分满分 1 分,相当不错。
作为一个基线,任何拥有超过一轮融资的公司都有 31%的成功机会,其自身的一系列功能可以提高或降低这个数字。下面是这些特征系数的细目分类。如果条形向左延伸,会增加失败的几率,向右延伸会增加成功的几率。

Logistic Regression Coefficients in terms of Log Odds
不足为奇的是,一家公司筹集的资金越多,就越有可能成功。我发现,一家公司每轮融资额外增加 100 万美元(*均而言),他们成功的几率就会增加 16%。我对两轮融资之间的时间间隔感到惊讶。一般来说,一家公司在两轮融资之间的时间越长,对他们越有利;融资周期之间每增加一个月,成功几率就会增加 5%。种子期和首轮融资之间的情况不同,每增加一个月,这些几率实际上会降低 3%。
我发现的另一个特别有趣的特征是在行业内部。所有最受欢迎的硬件行业(包括制造业、清洁技术和生物技术)中的公司更有可能失败。这很可能是因为在寻找可随公司发展而扩展的可靠供应商时,成本和复杂性增加了。
如果你想亲自尝试一下,请访问我通过 Heroku 这里部署的应用程序。有任何问题,请随时联系和。
预测股市崩盘
统计机器学习技术和神经网络的尝试

在这篇博文中,我将介绍一种机器学习算法的设计,该算法旨在仅基于过去的价格信息来预测股市崩盘。我从这个问题的背景开始,详细阐述我的方法和发现。所有的代码和数据都可以在 GitHub 上找到。
股市崩盘是指市场总价值急剧快速下跌,价格通常在几天内下跌超过 10%。股市大崩盘的著名例子是 1987 年的黑色星期一和 2008 年的房地产泡沫。崩盘通常归因于价格泡沫的破裂,是由于大多数市场参与者试图同时出售其资产时发生的大规模抛售。
价格泡沫的出现意味着市场不是有效的。在低效市场中,价格并不总是反映基本资产价值,而是根据交易者的预期而上涨或下跌。这些预期被交易者随后进一步抬高(或压低)价格的行为所强化。这导致正(或负)价格泡沫最终破裂。这种现象被乔治·索罗斯描述为反身性,是技术分析中预测方法的基本假设。
如今,对于金融市场是否存在泡沫,已经没有太多争论。然而,理解这些低效率并预测价格泡沫何时破裂是一项非常困难的任务。想象一下,你可以识别一个即将形成的泡沫,并预测市场何时崩溃。你不仅可以在价格上涨时获利,还可以在合适的时机卖出以避免损失。
一些数学家和物理学家试图通过研究价格结构背后的数学来解决这个问题。其中一位物理学家是 Didier Sornette 教授,他成功预测了多次金融危机。Sornette 使用对数周期幂定律(LPPLs)来描述价格泡沫是如何形成和破裂的。本质上,LPPL 将导致崩盘的价格运动拟合为一个比指数增长更快的函数,该函数具有对数周期成分(反映价格波动幅度和频率的增加)。
这就是这个项目的灵感来源。如果研究人员发现的循环价格结构存在,那么机器学习算法是否有可能学习这些模式并预测崩溃?这种算法不需要知道潜在的数学规律,而是根据预先识别的崩溃数据进行训练,并自行识别和学习这些模式。
数据和崩溃
第一步是收集财务数据和识别崩溃。我在寻找低相关性主要股票市场的每日价格信息。低互相关对于模型的有效交叉验证和测试很重要。下面的矩阵显示了 11 个主要股票市场日收益率的交叉相关性。

Correlation matrix of daily price returns for 11 major stock market indices
为了避免任何两个数据集的交叉相关性大于 0.5,我只收集了标准普尔 500(美国)、日经(日本)、恒指(香港)、上交所(上海)、BSESN(印度)、SMI(瑞士)和 BVSP(巴西)的数据。
为了识别每个数据集中的崩溃,我首先计算了价格下降。跌价是指连续几天内价格从上一个最高价到下一个最低价的持续下降。下面的例子显示了 2018 年 7 月底至 8 月中旬期间标准普尔 500 的三次提款。

Example of three drawdowns. The first one shown lasted from July 25th to July 30th 2018 and has a total loss of approximately (2846–2803)/2846 = 1.5%
我考虑了两种不同的方法来识别崩溃。第一个是根据 Emilie Jacobsson [2]的建议,他将每个市场的崩溃定义为 99.5%分位数的下降。用这种方法,我找到了划分崩盘的提款阈值,从波动性较小的市场(如标准普尔 500)的 10%左右,到波动性较大的市场(如巴西)的 20%以上。第二种方法遵循 Johansen 和 Sornette [3]的建议,他们将崩溃确定为异常值,即当绘制数据集中压降等级的对数与压降幅度时,压降远离拟合的威布尔分布。

Distribution of drawdowns by rank as an example for the Shanghai index since 1996.
我用两种碰撞识别方法测试了我的算法,并得出结论,第一种方法(雅各布森)是有利的,原因有二。首先,Sornette 没有明确说明偏离威布尔分布的程度如何才能将压降归类为崩溃,因此需要人工判断。第二,他的方法导致识别更少的碰撞,这导致严重不*衡的数据集。这使得为机器学习算法收集足够多的数据进行训练变得更加困难。
通过收集上面提到的七个数据集,我总共收集了 59,738 行每日股票价格,并确定了总共 76 次崩盘。
问题陈述和功能选择
我制定了一个分类问题,目标是预测每个时间点(例如每个交易日)在未来 1 个月、3 个月或 6 个月内是否会发生崩盘。
如果过去的价格模式是未来价格事件的指示,则在某一天做出预测的相关信息包含在该天之前所有天的每日价格变化中。因此,为了预测在第 t 天的崩溃,从第 t 天之前的每天的每日价格变化可以被用作特征。然而,由于模型提供了太多的特征,确实会变得更慢、更不准确(“维数灾难”),因此提取一些特征来捕捉任何时间点上过去价格运动的本质是有意义的。因此,我定义了 8 个不同的时间窗口来衡量过去一年(252 个交易日)每天的*均价格变化。我使用了从 5 天(直到第 t 天)到 126 天(对于 t-₁₂₆ 到 t-₂₅₂ )的递增窗口大小来获得最*时间价格变化的更高分辨率。因为在对多日价格变化进行*均时,没有捕捉到价格波动,所以我为相同时间窗口内的*均价格波动添加了 8 个特征。对于每个数据集,我将*均价格变化和波动性标准化。
为了评估特征选择,我进行了逻辑回归并分析了回归系数。逻辑回归系数对应于相关特征的对数概率的变化,意味着当所有其他特征保持不变时,概率(碰撞概率与非碰撞概率的比率)如何随着该特征的变化而变化的对数。对于下图,我将对数赔率转换为赔率。赔率大于 1 表示碰撞概率随着相应特征的增加而增加。

Logistic regression coefficients indicating the influence of the features on the predictive variable
系数分析显示,过去几天的波动性是即将发生崩盘的最强指标。然而,最*的价格上涨似乎并不意味着崩盘。乍一看这很令人惊讶,因为泡沫的典型特征是价格的指数增长。然而,许多发现的崩盘并不是在价格见顶后立即发生的,相反,价格在一段时间内下降导致崩盘。过去 6 至 12 个月的高价格增长增加了预测崩盘的可能性,这表明长期价格的普遍上涨使崩盘的可能性更大,更长时期的价格变动包含了对崩盘预测有价值的信息。
培训、验证和测试集
我选择了标准普尔 500 数据集进行测试,剩下的 6 个数据集用于训练和验证。我选择标准普尔 500 进行测试,因为它是最大的数据集(自 1950 年以来的每日价格信息)并且包含最大数量的崩溃(20)。对于培训,我进行了 6 重交叉验证。这意味着每个模型运行六次,使用五个数据集进行训练,剩下的一个用于验证。
得分
为了评估每个模型的性能,我使用了 F-beta 分数。F-beta 分数是精确度和召回率的加权调和*均值。beta 参数决定了精确度和召回率的权重。大于 1 的β优先考虑召回,小于 1 的β优先考虑精确度。

我选择的β值为 2,它更强调回忆,这意味着未被发现的碰撞比预测的未发生的碰撞受到更严厉的惩罚。在风险厌恶方法下,这是有意义的,假设不预测发生的崩溃比预期不发生的崩溃(错过潜在利润)有更严重的后果(金钱损失)。
回归模型、支持向量机和决策树
我从线性和逻辑回归模型开始。回归模型通过最小化所有训练样本上的预测和实际目标变量的差异来寻找函数的最佳系数。线性回归估计连续的目标变量,而逻辑回归估计概率,因此通常更适合于分类问题。然而,当我比较两种模型的预测结果时,逻辑回归仅在某些情况下优于线性回归。虽然这令人惊讶,但重要的是要注意,即使逻辑回归可能为估计碰撞概率提供更好的拟合,如果选择的阈值有效地分离二元预测,线性回归的次优拟合在实践中不一定是缺点。该阈值被优化以最大化训练集上的 F-beta 分数。
接下来,我测试了支持向量机。支持向量机使用核函数将输入特征投影到多维空间中,并确定一个超*面来分离正样本和负样本。要考虑的重要参数是惩罚参数 C(应避免多少误分类的度量)、核函数(多项式或径向基函数)、核系数γ(确定核函数的维数)和类权重(确定如何*衡正面预测和负面预测)。最好的 SVM 模型获得了与回归模型相似的分数。这使得回归模型更受欢迎,因为它们的训练速度更快。决策树无法与任何其他测试模型在同一水*上运行。
递归神经网络
下一步是实现递归神经网络(RNNs)。与传统的机器学习算法和传统的人工神经网络相反,递归神经网络能够考虑它们接收输入数据序列的顺序,从而允许信息持续存在。这似乎是处理时间序列数据(如每日股票回报)的算法的一个重要特征。这是通过连接单元的循环来实现的,以便在时间步长 t 时,输入不仅是特征 xₜ 而且是来自先前时间步长 hₜ-₁ 的输出。下图说明了这个概念。

Recurrent Neural Network
然而,常规 rnn 的一个主要问题是它们在学习长期依赖性方面存在问题。如果在 xₜ-ₙ 和 hₜ 、 hₜ 之间有太多的步骤,可能从 xₜ-ₙ 那里学不到任何东西。为了帮助解决这个问题,长短期记忆网络(LSTMs)已经被引入。基本上,lstms 不仅将来自前一个单元 hₜ-₁的输出,而且将“单元状态” cₜ-₁ 传递到下一个单元。单元状态基于输入( xₜ 和 hₜ-₁ )在每一步得到更新,并且反过来更新输出 hₜ 。在每个 LSTM 单元中,四个神经网络层负责输入 xₜ 、 hₜ-₁ 、 cₜ-₁ 和输出 hₜ和 cₜ 之间的交互。有关 LSTM 单元架构的详细描述,请参考 colah 的博客【4】。

Recurrent Neural Network with Long Short Term Memory (LSTM)
具有 LSTM 的 rnn 具有检测简单回归模型不能发现的关系和模式的能力。因此,如果 RNN LSTM 能够学习崩溃前的复杂价格结构,这样的模型难道不能胜过之前测试过的模型吗?
为了回答这个问题,我用 Python 库 Keras 和 LSTM 实现了两个不同的 rnn,并进行了严格的超参数调整。第一个决定是每层输入序列的长度。每个时间步 t 的输入序列由从 t 开始的一系列日子的每日价格变化组成。必须小心选择这个数字,因为较长的输入序列需要更多的内存,并且会降低计算速度。理论上,RNN LSTM 应该能够找到长期依赖关系,然而,在 Keras 的 LSTM 实现中,如果参数 stateful 设置为真,则单元状态仅从一个序列传递到下一个序列。实际上,这种实现很麻烦。为了避免网络在训练期间识别不同数据集和时期的长期依赖性,每当训练数据切换数据集时,我实现了状态的手动重置。这种算法没有提供很好的结果,所以我将 stateful 设置为 false ,但是将序列长度从 5 个时间步长增加到 10 个时间步长,并为网络提供了从 10 天之前的时间窗口到 252 个交易日之前的*均价格变化和*均波动率的附加序列(类似于为之前测试的模型选择的特征)。最后,我调整了超参数,并尝试了不同的损失函数,层数,每层神经元的数量以及辍学与不辍学。性能最好的 RNN LSTM 具有顺序层,其后是两个 LSTM 层,每个层具有 50 个神经元,使用 adam 优化器、二元交叉熵损失函数和用于最后一层的 sigmoid 激活函数。
估价
虽然超参数调整和增加序列长度以及添加长期特征导致更快的训练(大约 10 个时期后验证集的最佳结果),但没有一个 RNN LSTM 模型能够胜过之前测试的模型。

Recall vs precision for all models
上图显示了不同模型的精度和召回性能。不同的颜色表示不同的模型,不同的形状表示不同的预测变量(1 个月、3 个月或 6 个月的崩盘)。下面的柱状图展示了所有模型在 1 个月、3 个月和 6 个月的碰撞预测中的 F-beta 分数。 Random 代表没有预测能力的模型的预期性能,该模型预测崩溃的频率与测试模型一样高。

F-Beta score for all models
最好的结果显示,预测 6 个月、3 个月和 1 个月内发生崩溃的 F-beta 值分别为 41、37 和 29。准确率在 12-16%之间,召回率在 45-71%之间。这意味着,虽然大约 50%的碰撞被检测到,但大约 85%的碰撞信号是“假警报”。
结论
首先是坏消息。RNN LSTM 似乎无法学习复杂的价格模式,而复杂的价格模式能让它超越简单的回归模型。这表明,没有任何复杂的价格模式会在所有(或几乎所有)崩盘之前出现,但不会在其它时候出现。这并不意味着 Sornette 的假设,崩溃之前的某些价格模式符合对数周期幂定律是无效的。然而,这意味着,如果这样的模式存在,(1)这些模式也发生在没有跟随它们的碰撞的情况下,(2)有许多碰撞没有跟随这些模式,或者(3)没有足够的数据供 RNN 学习这些模式。虽然更多的数据肯定会提供更多的清晰度,部分问题可能是(1)和(2)的组合。Sornette 将对数周期幂律拟合到某些被识别为异常值的崩溃,但并不是对所有下降幅度相似的崩溃都是如此。为了提供一个找到 Sornette 所描述的崩溃的算法,训练数据将需要被特别地标记为仅符合这些模式的崩溃。这可能会提高对这些碰撞的识别,但对(2)没有帮助,因为不同类型的碰撞不会被检测到。然而,如果有足够的数据和足够多的已识别事故清单,重新运行 RNN LSTM 模型肯定是值得的。
好消息是,简单的价格模式,通过价格的长期变化和波动性的变化来定义,似乎在崩溃前定期发生。最好的模型能够学习这些模式,并比可比较的随机模型更好地预测崩盘。例如,对于 3 个月内的崩溃预测,最佳回归模型在测试集上实现了 0.15 的精度和 0.59 的召回率,而不具有预测能力的可比较随机模型预期将实现 0.04 的精度和 0.16 的召回率。对于 1 个月和 6 个月的崩溃预测,结果看起来相似,F-beta 分数对于 6 个月的预测最好,对于 1 个月的预测最差。这些结果是否足以优化投资策略仍有争议。然而,如果讨论的回归崩溃指标持续警告即将到来的崩溃,风险厌恶型投资者肯定会更加保守地分配他们的投资组合头寸。

Prediction for a crash in 3 months by the logistic regression model for the S&P 500 from 1958 to 1976
查看碰撞时的测试数据价格指数图表和碰撞预测指标表明,虽然一些碰撞被检测得非常好,但其他碰撞发生时没有或几乎没有来自碰撞预测的警告。上图显示了一个没有预测到的崩溃(在 1962 年)和连续三次预测很好的崩溃(在 1974 年)的例子。一些崩盘比其他崩盘被更好地检测出来,这与以下假设是一致的:某些典型的价格模式确实先于一些崩盘,但不是所有崩盘。不同的算法大部分都与相同的崩溃作斗争,这就是为什么我没有试图结合不同的模型。
通过对过去 21 天的二元崩溃预测进行加权*均,(最*的预测加权更强),逻辑回归模型预测截至 2018 年 11 月 5 日标准普尔 500 在 6 个月内崩溃的可能性为 98.5%,3 个月内为 97%,一个月内为 23%。读完这项研究后,我让你来决定如何处理这些信息。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
参考
[1]为什么股票市场崩溃,迪迪埃·索尔内特。此处有书可用。
[2]如何用对数周期幂定律预测金融市场的崩溃,Emilie Jacobsson。在这里找到论文。
[3]股票市场价格大幅下跌是异常值,(2001) Anders Johansen 和 Didier Sornette。在这里找到论文。
[4]理解 LSTM 网络,colah 的博客。链接此处。
用 LSTM 预测股票价格

*年来,机器学习在许多有趣的领域得到了应用。驯服股市就是其中之一。很长一段时间以来,我一直想试一试。主要是为了巩固我对 LSTMs 的工作知识。最后,我完成了这个项目,非常兴奋地分享我的经验。
动机和目标受众
我将在一系列博客上写下我的经历。本系列的目的不是解释 LSTM 或机器学习概念的基础。因此,我会假设读者已经开始了他/她的机器学习之旅,并具备 Python 等基础知识,熟悉 SkLearn、Keras、LSTM 等。原因是已经有关于“LSTMs 如何工作?”更有资格解释其背后的数学原理的人。但是我会分享这些文章的链接,只要我觉得缺少背景知识。虽然有很多文章告诉你如何在给定数据集的情况下预测股票价格,但大多数作者都没有揭示/解释他们如何达到神经网络的特定配置,或者他们如何选择特定的超参数集。所以这篇文章的真正目的是分享这样的步骤,我的错误和一些我觉得很有帮助的步骤。因此,本文不限于股票价格预测问题。
以下是我们将关注的内容:
- 读取和分析数据。(熊猫)
 - 标准化数据。(SkLearn)
 - 将数据转换为时间序列和监督学习问题。
 - 创建模型(Keras)
 - 微调模型(在下一篇文章中)
 - 训练、预测和可视化结果。
 - 我发现非常有用的提示和工具(系列的最后一篇文章
 
请注意,第一篇文章讨论的是 LSTM 的预处理步骤和术语。如果你对这些步骤相当有信心,你可以跳到下一篇文章。
我们开始吧!
读取和分析数据
在这篇文章中,我将使用通用电气的历史股价数据。你可以在我的网站这里找到数据。我不记得数据的来源了,因为我很久以前就下载了。我们可以将数据读入如下所示的帧:
df_ge = pd.read_csv(os.path.join(INPUT_PATH, "us.ge.txt"), engine='python')
df_ge.tail()

如您所见,大约有 14060 个项目,每个项目代表该公司一天的股票市场属性。让我们看看它在图上的样子:
from matplotlib import pyplot as pltplt.figure()
plt.plot(df_ge["Open"])
plt.plot(df_ge["High"])
plt.plot(df_ge["Low"])
plt.plot(df_ge["Close"])
plt.title('GE stock price history')
plt.ylabel('Price (USD)')
plt.xlabel('Days')
plt.legend(['Open','High','Low','Close'], loc='upper left')
plt.show()

看起来价格——开盘价、收盘价、最低价、最高价——彼此之间没有太大的差异,除了偶尔的小幅低价下跌。
现在让我们来看看体积图:
plt.figure()
plt.plot(df_ge["Volume"])
plt.title('GE stock volume history')
plt.ylabel('Volume')
plt.xlabel('Days')
plt.show()

哼。你看到有趣的东西了吗?时间线上 12000 天左右交易数量出现相当大的激增,恰好与股价的突然下跌相吻合。也许我们可以回到那个特定的日期,翻出旧的新闻文章,找出是什么原因造成的。
现在让我们看看是否有任何 null/Nan 值需要担心。事实证明,我们没有任何空值。太好了!
print("checking if any null values are present\n", df_ge.isna().sum())

标准化数据
数据没有标准化,每一列的范围各不相同,尤其是数量。标准化数据有助于算法收敛,即有效地找到局部/全局最小值。我将使用 Sci-kit Learn 中的 MinMaxScaler。但在此之前,我们必须将数据集分为训练数据集和测试数据集。在这个过程中,我还会将 DataFrame 转换为 ndarray。
将数据转换为时间序列和监督学习问题
这很重要,也有点棘手。这就是知识 LSTM 需要的地方。我将简要描述这里需要的关键概念,但我强烈建议阅读 Andre karpathy 的博客这里,它被认为是关于 LSTM 和这个的最佳资源之一。或者你也可以看看吴恩达的视频(顺便提一下,其中也提到了安德烈的博客)。
LSTMs 以格式[ batch_size,time_steps,Features ]消耗输入;三维数组。
- 批量大小表示在更新权重之前,您希望您的神经网络看到多少个输入样本。假设您有 100 个样本(输入数据集),并且您想在每次 NN 看到输入时更新权重。在这种情况下,批量大小为 1,总批量为 100。就像 wise 一样,如果您希望您的网络在看到所有样本后更新权重,批次大小将为 100,批次数量将为 1。事实证明,使用非常小的批量会降低训练速度,另一方面,使用太大的批量(如整个数据集)会降低模型归纳不同数据的能力,并且还会消耗更多的内存。但是找到目标函数的最小值需要更少的步骤。所以你必须在你的数据上尝试不同的值,并找到最佳点。这是一个相当大的话题。我们将在下一篇文章中看到如何更智能地搜索这些内容。
 - 时间步长定义你想让你的网络看到多少时间单位。例如,如果您正在处理一个字符预测问题,您有一个文本语料库要训练,您决定一次向您的网络输入 6 个字符。那么你的时间步长就是 6。在我们的例子中,我们将使用 60 作为时间步长,即我们将研究 2 个月的数据来预测第二天的价格。稍后将详细介绍。
 - 特征是用来表示每个时间步的属性数。考虑上面的字符预测示例,并假设您使用大小为 100 的独热编码向量来表示每个字符。那么这里的特征尺寸是 100。
 
现在我们已经弄清楚了一些术语,让我们将股票数据转换成合适的格式。为简单起见,假设我们选择 3 作为时间步长(我们希望我们的网络回顾 3 天的数据来预测第 4 天的价格),然后我们将像这样形成数据集:

样本 0 到 2 将是我们的第一个输入,样本 3 的收盘价将是其相应的输出值;两者都被绿色矩形包围。类似地,样本 1 到 3 将是我们的第二个输入,样本 4 的收盘价将是输出值;用蓝色矩形表示。诸如此类。所以到目前为止,我们有一个形状矩阵(3,5),3 是时间步长,5 是特征的数量。现在想想上图中有多少这样的输入输出对?4.
也把批量和这个混在一起。假设我们选择批量为 2。那么输入输出对 1(绿色矩形)和对 2(蓝色矩形)将构成第一批。诸如此类。下面是实现这一点的 python 代码片段:
“y_col_index”是输出列的索引。现在,假设在将数据转换为监督学习格式后,如上所示,您的训练数据集中有 41 个样本,但您的批量大小为 20,那么您将必须调整您的训练集,以删除遗漏的奇数样本。我会寻找一个更好的方法来解决这个问题,但现在我已经这样做了:
现在使用上述函数,让我们形成我们的训练,验证和测试数据集
x_t, y_t = build_timeseries(x_train, 3)
x_t = trim_dataset(x_t, BATCH_SIZE)
y_t = trim_dataset(y_t, BATCH_SIZE)
x_temp, y_temp = build_timeseries(x_test, 3)
x_val, x_test_t = np.split(trim_dataset(x_temp, BATCH_SIZE),2)
y_val, y_test_t = np.split(trim_dataset(y_temp, BATCH_SIZE),2)
现在我们的数据已经准备好了,我们可以专注于构建模型。
创建模型
我们将使用 LSTM 来完成这项任务,它是递归神经网络的一种变体。创建 LSTM 模型就像这样简单:
既然您已经编译了模型并准备好进行训练,就像下面这样训练它。如果您想知道使用什么值作为参数,如时期、批量大小等。别急,我们将在的下一篇文章中看到如何解决这些问题。
训练该模型(具有微调的超参数)给出了 3.27e-4 的最佳误差和 3.7e-4 的最佳验证误差。以下是培训损失与验证损失的对比情况:

Training error vs Validation error
这是上述模型的预测结果:

prediction vs real data
我发现 LSTM 的这种配置是我尝试过的所有组合中最好的(对于这个数据集),和我已经尝试了 100 多种!所以问题是你如何为你的神经网络找到完美的(或者在大多数情况下,接*完美的)架构?这将引导我们进入下一个重要的部分,在的下一篇文章中继续。
你可以在我的 Github 简介这里找到所有完整的程序。
注意:向读者提出一个小小的请求——欢迎你们在 LinkedIn 或 Twitter 上与我联系,但是如果你们对我的博客有任何疑问,请在各自博客的评论区而不是个人信息区发表,这样,如果其他人有同样的疑问,他们也可以在这里找到,我就不必单独解释了。然而,仍然欢迎你向我个人发送与博客或一般技术问题无关的问题。谢谢:-)
2019 年 13 月 4 日更新
- 据我所知,自从我写了这篇文章,我的博客使用的模型可能已经过度拟合了。虽然我还没有确认,但很有可能。所以在你的项目中实现时请小心。你可以尝试更少的时代,更小的网络,更多的辍学等等。
 - 我对最后一层使用了 Sigmoid 激活,这可能会受到无法预测数据集中高于“最高”价格的价格的限制。你可以尝试“线性”激活最后一层来解决这个问题。
 - 修复了“将数据转换为时间序列”部分的一个拼写错误。
 
感谢读者让我注意到这些。
2020 年 1 月 21 日更新
正如在一些评论中提到的,我正在探索解决股票预测问题的其他方法。我终于让它工作了。感兴趣的读者可以在这里阅读。
机器学习预测股票价格
金融中的人工智能
利用 LSTM 模型预测股票趋势

随着金融机构开始接受人工智能,机器学习越来越多地被用来帮助做出交易决策。虽然有大量的股票数据供机器学习模型训练,但高信噪比和影响股票价格的众多因素是预测市场困难的几个原因之一。同时,这些模型不需要达到很高的精确度,因为即使 60%的精确度也能带来稳定的回报。预测股票价格的一种方法是使用长短期记忆神经网络(LSTM)进行时间序列预测。
LSTM:简要说明

LSTM diagram (source)
LSTMs 是递归神经网络(RNNs)的改进版本。rnn 类似于人类的学习。当人类思考时,我们并不是每秒钟都从零开始思考。例如,在句子“鲍勃打篮球”中,我们知道鲍勃是打篮球的人,因为我们在阅读句子时保留了过去单词的信息。类似地,rnn 是具有环路的网络,这允许它们在到达最终输出之前使用过去的信息。然而,随着时间间隔的增长,RNNs 只能连接最*的先前信息,而不能连接信息。这就是 LSTMs 发挥作用的地方;LSTMs 是一种 RNN,可以长时间记忆信息,这使它们更适合预测股票价格。有关 LSTMs 的技术解释,请点击此处。
导入/初始数据
为了开始我们的项目,我们导入 numpy 来进行科学计算,导入 pandas 来加载和修改数据集,导入 matplotlib 来绘制图形。
import numpy as npimport matplotlib.pyplot as pltimport pandas as pd
在进行必要的导入后,我们加载 Tata Global Beverage 过去股价的数据。从数据中,我们选择第一列和第二列的值(分别为“Open”和“High”)作为我们的训练数据集。“开盘价”栏代表当天股票的开盘价,“高价”栏代表当天股票的最高价格。
url = 'https://raw.githubusercontent.com/mwitiderrick/stockprice/master/NSE-TATAGLOBAL.csv'dataset_train = pd.read_csv(url)training_set = dataset_train.iloc[:, 1:2].values
为了查看我们正在使用的数据集,我们可以检查头部,它向我们显示了数据集的前五行。
dataset_train.head()

“低”代表当天的最低股价,“最后”代表股票最后一次交易的价格。“收盘”代表股票当天的收盘价。
数据标准化
规范化是将数据集中的数值列的值更改为通用的比例,这有助于提高模型的性能。为了缩放训练数据集,我们使用 Scikit-Learn 的 MinMaxScaler,其数字介于 0 和 1 之间。
from sklearn.preprocessing import MinMaxScalersc = MinMaxScaler(feature_range=(0,1))training_set_scaled = sc.fit_transform(training_set)
将时间步长并入数据
我们应该将数据以 3D 数组的形式输入到 LSTM 模型中。首先,在使用 numpy 将数据转换成数组之前,我们用 60 个时间步长创建数据。最后,我们将数据转换成一个 3D 数组,其中包含 X_train 样本、60 个时间戳以及每步一个特征。
X_train = []y_train = []for i in range(60, 2035):X_train.append(training_set_scaled[i-60:i, 0])y_train.append(training_set_scaled[i, 0])X_train, y_train = np.array(X_train), np.array(y_train)X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))
创造 LSTM 模式
在开发 LSTM 之前,我们必须从 Keras 进行一些导入:Sequential 用于初始化神经网络,LSTM 用于添加 LSTM 层,dropout 用于防止与 Dropout 层过度拟合,Dense 用于添加密集连接的神经网络层。
from keras.models import Sequentialfrom keras.layers import LSTMfrom keras.layers import Dropoutfrom keras.layers import Dense
添加 LSTM 图层时使用了以下参数:50 个单位是输出空间的维度,return_sequences=True 是堆叠 LSTM 图层所必需的,因此后续的 LSTM 图层具有三维序列输入,input_shape 是训练数据集的形状。
在 Dropout 层中指定 0.2 意味着 20%的层将被丢弃。在 LSTM 和下降图层之后,我们添加了指定一个单位输出的密集图层。为了编译我们的模型,我们使用 Adam 优化器,并将损失设置为均方误差。之后,我们将模型拟合为运行 100 个时期(时期是学习算法将通过整个训练集工作的次数),批次大小为 32。
model = Sequential()model.add(LSTM(units=50,return_sequences=True,input_shape=(X_train.shape[1], 1)))model.add(Dropout(0.2))model.add(LSTM(units=50,return_sequences=True))model.add(Dropout(0.2))model.add(LSTM(units=50,return_sequences=True))model.add(Dropout(0.2))model.add(LSTM(units=50))model.add(Dropout(0.2))model.add(Dense(units=1))model.compile(optimizer='adam',loss='mean_squared_error')model.fit(X_train,y_train,epochs=100,batch_size=32)
对测试集进行预测
我们从导入测试集开始
url = 'https://raw.githubusercontent.com/mwitiderrick/stockprice/master/tatatest.csv'dataset_test = pd.read_csv(url)real_stock_price = dataset_test.iloc[:, 1:2].values
在预测未来的股票价格之前,我们必须修改测试集(注意我们对训练集所做的编辑的相似之处):合并 0 轴上的训练集和测试集,再次将 60 设置为时间步长,使用 MinMaxScaler,并重塑数据。然后,inverse_transform 将股票价格转换成正常可读的格式。
dataset_total = pd.concat((dataset_train['Open'], dataset_test['Open']), axis = 0)inputs = dataset_total[len(dataset_total) - len(dataset_test) - 60:].valuesinputs = inputs.reshape(-1,1)inputs = sc.transform(inputs)X_test = []for i in range(60, 76):X_test.append(inputs[i-60:i, 0])X_test = np.array(X_test)X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))predicted_stock_price = model.predict(X_test)predicted_stock_price = sc.inverse_transform(predicted_stock_price)
绘制结果
完成所有这些步骤后,我们可以使用 matplotlib 来可视化我们预测的股价和实际股价的结果。
plt.plot(real_stock_price, color = 'black', label = 'TATA Stock Price')plt.plot(predicted_stock_price, color = 'green', label = 'Predicted TATA Stock Price')plt.title('TATA Stock Price Prediction')plt.xlabel('Time')plt.ylabel('TATA Stock Price')plt.legend()plt.show()

虽然我们的预测价格的准确价格点并不总是接*实际价格,但我们的模型仍然表明了整体趋势,如上涨或下跌。这个项目告诉我们 LSTMs 在时间序列预测中可以有些效果。
点击此处查看完整代码
参考
[1]德里克·姆维蒂,股票价格预测数据与笔记本教程 (2018),Github
先别走!
我是 Roshan,16 岁,对人工智能和金融的交叉领域充满热情。关于人工智能在金融中的广泛观点,请查看这篇文章:https://becoming human . AI/artificial-intelligence-and-its-application-in-finance-9f1e 0588 e 777。
在 Linkedin 上联系我:https://www.linkedin.com/in/roshan-adusumilli-96b104194/
用回声状态网络预测股票价格
几十年来,人们一直试图可靠地预测股市看似混乱的本质,但都失败了。神经网络是关键吗?
“在看似完全混乱的事物中,有秩序,甚至是伟大的美。如果我们足够仔细地观察我们周围的随机性,模式就会开始出现。” ― 阿伦·索尔金
编辑:由于对本文中概述的方法的怀疑和批评,本教程中使用的所有代码和数据以及结果都在相关的 GitHub 资源库中提供,可以在这里找到。

时间序列预测的动机
股票市场通常被视为一个混沌的时间序列,公司经常应用先进的随机方法来尝试并做出合理准确的预测,以便他们能够占上风并赚钱。这本质上是所有投资银行背后的想法,尤其是那些市场交易者。
我并不自称对股票市场了解很多(毕竟,我是科学家,不是投资银行家),但我确实对机器学习和随机方法有一定的了解。这一领域最大的问题之一是试图以可靠的方式准确预测混沌时间序列。预测混沌系统动态的想法有点违反直觉,因为根据定义,混沌的东西不会以可预测的方式表现。
对时间序列的研究在股票市场出现之前就有了,但随着个人试图利用股票市场来“击败系统”并变得富有,时间序列的研究变得越来越受欢迎。为了做到这一点,人们不得不开发可靠的方法,根据先前的信息来估计市场趋势。
首先,让我们谈谈时间序列的一些属性,这些属性使时间序列易于分析,这样我们就可以理解为什么当我们观察股票市场时,时间序列分析会变得相当困难。
所有相关代码都可以在我的 GitHub 资源库中找到:
[## GitHub-mpstewart 1/EchoStateNetworks:与媒体文章“预测股票…
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/mpstewart1/EchoStateNetworks)
时间序列属性
时间序列最重要的属性之一就是它是*稳的。如果一个时间序列的统计属性如均值和方差随时间保持不变,则称该时间序列为*稳。但是为什么重要呢?
大多数模型都假设时间序列是*稳的。直观上,我们可以说,如果一个时间序列在一段时间内具有特定的行为,那么它很有可能在未来也会遵循相同的行为。与非*稳序列相比,*稳序列的相关理论更加成熟,也更容易实现。
使用非常严格的标准来定义*稳性。然而,出于实际目的,如果该序列在一段时间内具有恒定的统计特性,即以下特性,我们可以假设该序列是*稳的:
- 恒定*均值。这应该是直观的,因为如果均值在变化;那么时间序列可以被看作是移动的,通过对比下面两个图可以看出。
 

2.恒定方差。这种性质称为同质性。下图描述了违反此属性的静态与非静态示例。

3.不依赖于时间的自相关。在下图中,你会注意到随着时间的增加,传播变得越来越*。因此,对于非*稳情况,协方差不随时间恒定。

为什么我关心一个时间序列的*稳性?
我首先讨论这一部分的原因是,您需要您的时间序列是*稳的,以便构建一个时间序列模型。如果违反了*稳时间序列的标准,首先要做的是转换时间序列,使其*稳,然后尝试随机模型来预测该时间序列。有多种方法可以实现这种稳定性。其中一些是去趋势、差分等。
对于不熟悉时间序列分析的人来说,这可能有点愚蠢。然而,它比第一次出现时要复杂一点(不总是这样吗..).事实证明,处理时间序列的最佳方式是首先将其“固定化”,并将其解耦为几个不同的特征,如线性趋势,分离出具有不同季节性的时间序列,然后在最后将它们重新加在一起。

An example of decoupling a time series into multiple series with desirable properties.
对于任何熟悉傅立叶变换的人来说,这是一个非常相似的类比。傅立叶变换的作用是分离出时间序列中的不同频率特性,并将它们转换到频域,以便更简单地表示。然后,在将这些信号转换回时域之前,可以更容易地对其进行处理或分析。
我如何测试*稳性?
从视觉观察来看,时间序列是否*稳并不总是显而易见的。因此,更正式地说,我们可以使用下面的方法来检查*稳性:
- 绘制滚动统计:我们可以绘制移动*均线或移动方差,看它是否随时间变化。移动*均值/方差是指在任何时刻' t ',我们将取去年的*均值/方差,即过去 12 个月。但是这更多的是一种视觉技术。
 - Dickey-Fuller 检验:这是检验*稳性的统计检验之一。这里的零假设是 TS 是非*稳的。测试结果包括一个测试统计和一些临界值用于不同的置信水*。如果“检验统计量”小于“临界值”,我们可以拒绝零假设,说序列是*稳的。详见本文。
 
现在我们对时间序列有了更多的了解,我们可以看看人们研究时间序列的传统方式,他们如何开发他们的模型,以及为什么他们不适合研究股票市场。
时间序列预测的基本方法
最基本的方法非常简单,我认为大多数人不用上时间序列分析课就能想出这些方法。有些用处的最简单的模型是移动*均线。本质上,移动*均采用最后的 t 值,并将这些值的*均值作为下一点的预测值。
移动*均惊人地准确,对异常值和短期波动的稳健性可以通过改变*均过程中使用的先前点的数量来控制。
更复杂的程序自然地从这里开始,例如指数*滑。这类似于移动*均,只是它是一个加权过程,对最*的数据点给予更高的重要性。指数*滑中使用的特定加权函数(不奇怪)是一个指数函数,但是可以使用不同的方法对该过程进行加权。
这些方法适用于相对一致和周期性的时间序列,但那些表现出季节性和持续线性趋势或任何显著随机性或混沌性质的方法很难用于此。例如,如果我有一个周振荡,并且我使用的是移动*均模型,该模型对上周的数据进行*均,那么我的模型将完全忽略这种振荡行为。
一种用于分析具有不同自相关水*的时间序列(例如,每周趋势与每月和每年趋势相结合)的非常流行的方法被称为霍尔茨线性模型。Holt 扩展了简单的指数*滑法,允许用趋势预测数据。它只不过是应用于水*(系列中的*均值)和趋势的指数*滑。为了用数学符号来表达这一点,我们现在需要三个等式:一个用于水*,一个用于趋势,一个用于结合水*和趋势来获得预期的预测 ŷ。

另一种最流行的技术是使用 ARIMA。这代表自回归综合移动*均线。正如你可能猜到的,它结合了移动*均值和自回归特性(查看后续时间步长之间的相关性)。ARIMA 模型遵循一种特定的方法。

本质上,我们获取原始数据,对时间序列进行解耦,使其成为*稳和非*稳的组成部分。然后,我们可以研究被称为自相关或部分自相关图的图表,这些图表查看特定值与其前身相比的相关性有多强。由此,我们可以确定如何建立 ARIMA 模型来进行预测。
所有这些方法都依赖于具有某种自相关和/或周期性的*稳时间序列。这是股票市场固有的特征。股票市场确实有波动的时候,这些在大学的任何经济学课上都有详细的研究。它们是基钦周期(3-5 年的周期)朱格拉周期(7-11 年的周期)库兹涅茨摆动(15-25 年的周期)和康德拉季耶夫波(45-60 年的周期——尽管这个周期经济学家还在争论)。但是,个别公司的股票一般不会遵循这种趋势,有些人赢了,有些人输得比别人多。从时间序列模型的角度来看,它们受政治、社会经济和社会因素的影响,这些因素本质上是随机和混乱的。此外,人们对这些波动的理解还不够准确,无法根据它们的存在对经济市场的未来做出有用的预测——这是有道理的,因为否则的话,每个人都会这么做。
神经网络怎么样?
神经网络似乎适用于任何涉及非线性特征空间的事物。事实上,递归神经网络可以并且已经被用于预测股票市场。然而,在预测股票价格方面,递归神经网络(RNNs)面临着几个挑战,最明显的是与 RNNs 相关的消失梯度问题,以及非常嘈杂的预测。点击这里可以找到一个全面的演示,展示如何实现一个叫做 LSTM 的基本类型的 RNN 来预测股票价格。
到目前为止,RNNs 最重要的问题是消失梯度问题。这个问题源于这样一个事实,即通过称为反向传播的程序优化的非常深的神经网络使用每层之间的导数来“学习”。这些导数可以相对较小,也可以相对较大。如果我的网络有 100 个隐藏层,我将一个小数字乘以 100 次,这个值基本上就消失了。这是一个问题,如果我所有的梯度都是零,我的网络什么也学不到,所以我能做什么?
对此有 3 种解决方案:
- 剪切梯度法
 - 具有漏单元的特殊 RNN,如长短期记忆(LSTM)和门控循环单元(GRU)
 - 回声状态 RNNs
 
渐变裁剪阻止我们的渐变变得太大或太小,但是这样做我们仍然会丢失信息,所以这不是一个理想的方法。具有泄漏单元的 rnn 是好的,并且是大多数将 rnn 用于商业目的的个人和公司使用的标准技术。这些算法通过某种形式的梯度下降来适应所有连接(输入、循环、输出)。这使得这些算法很慢,更麻烦的是,这使得学习过程容易被分叉打断;不能保证收敛。因此,rnn 很少在实际工程应用中使用。
这就是回声状态网络的用武之地。回声状态网络是一个相对较新的发明,它本质上是一个递归神经网络,具有一个松散连接的隐藏层,称为“水库”,在存在混沌时间序列的情况下工作得非常好。在回声状态网络中,我们只需训练网络的输出权重,这样可以加快神经网络的训练速度,通常可以提供更好的预测,并解决我们之前用时间序列分析讨论过的所有问题。与其他方法相比,ESN 训练速度快,不会出现分叉,并且易于实现。在一些基准任务上,ESNs 明显优于所有其他非线性动力学建模方法。
回声状态网络是被称为水库计算的计算科学类别的一部分,我们将在下一节更详细地研究它。
回声状态网络
因此,我们已经证明,没有任何方法可以处理混乱的时间序列,不幸的是,这恰好是我们对股票市场建模的方式。避免这种困难的一种方法是固定递归和输入权重,并且只学习输出权重:回声状态网络(ESN)。隐藏单元形成了从历史输入中捕获不同方面的时间特征的“库”。
ESN 背后的数学论证相当复杂,因此为了本文的缘故,我将尽量避免它。相反,我们将讨论 ESN 背后的概念,并看看如何使用 Python 相对简单地实现它。
原始论文中概述为什么它被称为“回声”网络的描述是
贯穿所有这些变化的统一主题是使用固定的 RNN 作为随机非线性可激发介质,其对驱动输入(和/或输出反馈)的高维动态“回声”响应被用作非正交信号基础,以通过线性组合重建期望的输出,从而最小化一些误差标准
ESN 取任意长度的序列输入向量( u )并且(1)将其映射到高维特征空间(即,递归的储层状态 h ),并且应用线性预测器(线性回归)来找到 ŷ.

Schematic diagram of an echo state network.
我们基本上只训练输出权重,这大大加快了训练的速度。这就是油藏计算的巨大优势。通过设置和固定输入和循环权重来表示丰富的历史,我们获得:
- 作为接*稳定性的动力系统的循环状态——稳定性意味着雅可比矩阵都接* 1(没有消失或爆炸梯度)
 - 部分记忆先前状态的泄漏隐藏单元——它们避免爆炸/消失梯度,同时不需要训练。
 
回声状态属性
为了使 ESN 原理工作,储层必须具有回波状态属性 (ESP),这将受激储层动态的渐*属性与驱动信号相关联。直观地说,电潜泵表明储层将从初始条件中逐渐洗去任何信息。如果储层权重矩阵(和泄漏率)在奇异值方面满足某些代数条件,则对于附加 sigmoid 神经元储层,ESP 是有保证的。
培训
所以你可能想知道,首先我们如何选择隐藏状态的值?输入和递归权重被随机初始化,然后被固定。所以,我们没有训练他们。我们应该如何修正它们以优化预测?
训练非常容易和快速,但是存在超参数,例如控制权重的随机生成、储层节点的程度、储层节点的稀疏性、谱半径的超参数。不幸的是,不存在优化超参数的系统方法,因此这通常是使用验证集来完成的。由于特征空间中存在固有的自相关,交叉验证对于时间序列数据是不可行的。

概括一下:
- 每个网络节点都有不同的动态行为
 - 信号的时间延迟可能沿着网络链路出现
 - 网络隐藏部分具有循环连接
 - 输入和内部权重是固定的,并且是随机选择的
 - 在训练期间,仅调整输出权重。
 
编码回声状态网络
现在到了你们期待已久的时刻,你们实际上是如何对这些神秘的网络进行编码的?我们使用一个 Python 库,它可以从这个 GitHub 库中获得。这个库叫做 PyESN 。为了安装这个库,您必须克隆这个库并将pyESN.py文件放在您当前的 Jupyter 笔记本文件夹中。然后,当你在 Python 3 笔记本中时,你可以简单地称之为import pyESN。
你称 RC 为:
有关参数的简要说明:
n_inputs:输入维数
n_outputs:输出尺寸的数量
n_reservoir:水库神经元的数量
ranodom_state:种子为随机发生器
sparsity:将经常性权重的比例设置为零
spectral_radius:递归权重矩阵的谱半径
noise:添加到每个神经元的噪声(正则化)
预测亚马逊股票价格
现在,我将介绍一个使用 echo state networks 预测未来亚马逊股票价格的示例。首先,我们导入所有必要的库,并导出数据(在本例中,数据是从互联网上搜集来的)。
然后,我们使用 pyESN 库中的 ESN 来部署 RC 网络。这里的任务是通过使用之前的 1500 点预测未来两天,并对未来的 100 点进行预测(查看下图)。所以,最后你会有一个 100 时间步的预测,预测窗口= 2。我们将使用它作为验证集。

首先,我们使用一些合理的值创建我们的回声状态网络实现,并指定我们的训练和验证长度。然后,我们创建函数来计算均方误差,并针对频谱半径、噪声和窗口长度的特定输入参数运行回声状态网络。
现在,我们可以简单地运行一个函数,获得我们的预测,然后我们可以绘制这个图,看看我们做得有多好。
上面的代码产生了下面的情节。

如果我们放大这个图,我们可以看到这个预测实际上是多么令人印象深刻。

不错吧?唯一的警告是,它似乎在短时间内(大约 1 或 2 天)工作得很好,具有合理的准确性,但随着估计值的进一步外推,误差会变得越来越大。上面的模型是用两天的预测窗口制作的,这意味着我们在任何给定的时间只能预测未来的两天。
我们可以通过增加窗口长度来说明这一点。对于 10 天的窗口长度,预测仍然惊人地准确,尽管它明显比两天的预测窗口差。

为了获得这么好的结果,我们必须进行大量的超参数优化;以下是获得上述结果中使用的超参数的步骤。
上面的代码需要一段时间来优化,这只是针对两个参数。当在热图上绘制 MSE 时,我们得到以下结果。

然而,当窗口函数很小时,它在我们的验证集上给了我们一个相当好的结果。这使得 ESN 有利于股票价格的短期预测,但如果你试图推断结果,事情会变得更加不确定和有风险。
在未来预测中,误差随时间传播,因此它随时间增加。这就是当窗口长度增加时精度降低的原因。我们可以在下图中看到这种行为,其中 MSE 是预测窗口的单调递增函数,因此预测越长意味着 MSE 越大。

最后一句话
回声状态网络分析混沌时间序列的能力使其成为数据高度非线性和混沌的金融预测的有趣工具。但是,除了预测股票市场,我们还可以利用这些网络做更多的事情。我们还可以:
- 预报天气
 - 控制复杂动力系统
 - 执行模式识别
 
预计未来会听到更多关于这类网络的信息,尤其是随着人们进入 DeepESN 模型的开发阶段,这些模型能够在更高维度的潜在空间中工作,具有时间特征,能够处理一些最困难的时间序列问题。
如果你对这些网络感兴趣,有更多讨论这些的文章和研究论文可以免费获取。
回声状态网络(ESN)为递归神经网络提供了架构和监督学习原理
www.scholarpedia.org](http://www.scholarpedia.org/article/Echo_state_network) [## 深度回声状态网络(DeepESN):简要综述
深层递归神经网络(RNNs)的研究,特别是深层油藏计算(RC)的研究,正在获得越来越多的关注
arxiv.org](https://arxiv.org/abs/1712.04323)
所有上述工作都在我的 GitHub 资源库中列出,可以在这里找到。
机器学习快乐!
用机器学习预测股票
需要注意的 3 件重要事情

Photo by Aron Visuals on Unsplash
机器学习的激增是前所未有的。需要基于数据的决策制定的领域很少没有得到广泛应用。投资领域也不例外。人们只需在谷歌上联合搜索“ML”和“股票预测”,就会看到大量的时间序列预测和递归神经网络相关内容。尽管股票价格数据可能看起来是这些类型算法的完美候选,但我们应该谨慎从事,小心处理这项任务(尤其是如果涉及到您辛苦赚来的现金)。
那些开始接触机器学习的神秘预测艺术的人会回忆起他们在这个主题中的第一堂课,是下面维恩图的一些迭代:

这一点很清楚。机器学习(或数据科学)跨越了技术技能(如编程和数学)与领域专业知识形式的主题知识的融合。如果没有这三种形式,我们只是简单地回归到各自领域中更纯粹的形式之一。
这种描述对于金融机器学习尤其适用。时间序列金融数据极其微妙,将现成的算法应用于未处理的价格数据是错误发现或更糟的资本损失的完美方法。因此,使用这些数据需要一些特殊的考虑,最重要的是应用领域知识。因此,这篇文章旨在传授一些直觉,这些直觉经常被该领域的新手所忽视。我们将主要关注问题的讨论方面,因为相关的数学和编码资源已经非常丰富。
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
1。数据,数据,数据

Photo by Markus Spiske on Unsplash
这可能不足为奇,因为数据是任何 ML 模型的关键因素,股票预测也不例外。为了理解我们的谨慎,我们需要首先理解数据生成过程。用于股票预测的常用分析领域数据集,如宏观经济、基本面和价格数据,都是时间序列数据的例子。这类数据有一种现象叫做****。简单来说,每次观测的值锚定到前一个时间间隔观测的值。
为了在实践中说明这一点,让我们以价格为例。如果我们观察任何一只股票,并每天跟踪它的价格变动,我们会发现每只股票的收盘价都与前一天的收盘价紧密相连,只有一些“微小的”偏差,但这是为什么呢?最简单的形式是,股票是基础公司的所有权份额,其价值由永恒的会计等式决定, 资产减去负债等于权益 。股权是公司的基本价值,占股价的大部分,投资者情绪、交易行为和噪音驱动着每日偏离。公司资产即机器、土地、建筑物和存货的价值不会在一夜之间发生重大变化,其负债也不会发生重大变化(并不总是如此),因此,除了重大会计丑闻之外,公司的基本价值每天都应该相对稳定。****
这对机器学习意味着什么?这意味着一个模型可以通过“博弈”其损失函数并选择前一天的价格作为当天价格的预测来表现得相当好。当许多“表现良好的预测模型”的预测输出非常类似于实际股票价格的滞后移动*均值时,可以清楚地观察到这一点。任何这样的模型都会不断追逐真实价格。
类似的,是*稳性的问题。许多最大似然模型和预处理技术的基础是假设生成数据的分布参数是恒定的。或者,这可以解释为特征的均值和标准差不随时间变化,并且数据中没有趋势。随着时间的推移,看看常用的美国季度 GDP 数据就会很快打消这种想法。这些数据中显然有一个趋势,也应该有,如果一个经济体在增长,你会预期它的产出(以及这些产出的价格)会随着时间的推移而增长。

Source: BEA, US Nominal GDP over time
资料来源:BEA,美国一段时间的名义 GDP
该数据中的*均值和标准偏差是时变的,并且在盲目应用诸如回归的算法和诸如标准化和主成分分析的普通预处理技术时造成一些不便。
在(投资)文献和实践中,应对时间序列数据异常的一种常用技术是采用两个时期之间的股票价格回报(或其他数据的变化率),而不是绝对值。这背后的直觉类似于时间序列预测中的去趋势或差分,旨在使数据*稳。如果我们将此应用于美国 GDP 数据,我们会得到一些开始类似于正常 iid 变量的东西。

Source: BEA, GDP % change from prior period
这种方法并不完美,并且会引入各种其他问题,但是它是被广泛接受的方法。
尽管用户需要了解财务数据的许多其他方面,但为了简洁起见,我将在以后的帖子中更全面地讨论这些方面。
2。任意误差项-现实世界的后果

Photo by Emily Morter on Unsplash
大多数有监督的机器学习方法是通过估计或优化一组权重来拟合的,这些权重使一些目标函数最小化。在回归问题中这个函数常常是 【均方根误差】【RMSE】和在分类中的 【交叉熵】 。对于许多经典的基准数据集,如 ImageNet 大规模视觉识别挑战赛(【ils vrc】),这已经成为一场“逐底竞赛”,高素质的团队成功地(并成功地)年复一年地大幅降低错误率。虽然这对于推进研究的目的来说可能是合适的,但是 ML 对强制减少一些任意误差项的关注鼓励了对现实世界问题的抽象。****
在投资中,找到一个能够以 95%的准确率对何时买入或卖出股票进行分类的模型似乎是一个很好的结果,但通常这个模型不会模仿真实的投资组合行为,最重要的是不会考虑错误的成本。市场变化无常,尽管看似有利的投资环境可能持续数年,但调整或“ 黑天鹅 ”事件(由 纳西姆·塔勒布 杜撰)可能在几分钟内展开。
如果表征你 5%错误率的实例之一与这些罕见但灾难性的事件之一同时发生,几乎可以肯定的是,你的投资组合将遭受损失,可能会达到 95%的正确率(假设没有泛化错误)所带来的累积回报完全消失的程度。对于专业投资经理来说,这个问题更加严重,因为 10%的提款就足以引发投资者大规模撤离他们的基金。由收益和痛苦的不对称产生的后果在经验丰富的从业者心中根深蒂固。这就是为什么该行业既关注创造回报,也关注管理风险。
对于机器学习者/数据科学家来说,这里的课程是理解他们的模型的含义,不要只知道错误率和损失函数,执行 向前走测试 ,就好像你一直持有你预测的交易,并引入成本敏感的措施,这些措施是惩罚你的模型是错误的。
3。战胜市场——比你想象的要难

Photo by Inactive. on Unsplash
要理解为什么我们需要引入机会成本的概念,仅仅有一个能获得正回报的好的 ML 模型是不够的。这个关键的经济原则说明了放弃下一个最佳机会的代价。如果我们不使用提议的 ML 模型投资我们的钱,下一个最好的机会和一个需要很少技巧的机会是购买市场,大概是通过购买 ETF。这些产品以相对较低的成本给你带来类似标准普尔 500 指数的回报。因此,我们必须问一个问题,如果你的模型的表现,在调整交易成本后,没有明显超过标准普尔 500 指数的 18.74%&【你真的把钱用好了吗?专业投资经理几乎总是被某种基准所束缚,他们的技能是通过超越基准的能力来衡量的,这与机器学习者/数据科学家形成了对比,他们通常会孤立地评估自己的财务预测。
结论
虽然这个列表既不完整也不全面,但我希望我已经给了你一些直觉,告诉你在构建股票预测的 ML 模型时需要考虑的关键问题。与任何其他与数据相关的任务一样,ML 可能会给你一套工具来利用,但是找到解决方案仍然需要对问题有深入的了解。
免责声明:本帖纯属个人观点和看法的表达。它不代表任何建议,也不反映我的雇主的观点。
使用谷歌云人工智能*台预测纽约市的出租车价格(十亿多行)第 1 部分

Taxis | Photo by Francesco Ungaro on pexels.com
该项目旨在创建一个机器学习模型,使用 BigQuery 中托管的出租车乘坐数据集来估计纽约市的出租车费用。有超过 a 十亿行的大小为 130 GB。你可以在这里找到。这篇文章是基于我在谷歌云*台专业化上使用 TensorFlow 进行机器学习的经验。
首先,我们必须在 Google 云*台上建立一个项目,并启动一个笔记本实例。

这个实例将花费我们大约每小时0.14 美元。我们还需要启用计算引擎 API 并创建一个存储桶。

数据准备
安装 BigQuery 库并预览数据


我们使用 RAND() 函数从这个庞大的数据集中抽取一个小样本。
缺点是我们每次运行这个查询都会得到不同的样本。因此,我们将使用散列函数。
MOD(ABS(FARM_FINGERPRINT(CAST(pickup_datetime AS STRING))), 5000)= 1
此功能使我们能够获得原始数据的 0.02% 的恒定样本。利用整个数据集进行探索需要巨大的计算能力。我计划将来使用整个数据集建立一个模型。
将数据加载到熊猫数据框架中


我们肯定需要清理我们的数据。比如经纬度值关(纬度应该在-90°到 90°之间;经度应该在-180 到 180 之间)。有些行程的票价为负数,有些行程的乘客数为零。
让我们画出行程 _ 距离 vs 车费 _ 金额

一些坏数据被编码为零。此外,我们不打算在预测中包括小费,因为他们往往是不可预测的。我们的目标变量将是票价 _ 金额+通行费 _ 金额
我们的预测值是:
拾取日期时间
收件人 _ 经度
皮卡 _ 纬度
经度下降
下降纬度
我们选择这些是因为它们最符合我们的目标。有人可能会争辩说, trip_distance 可以帮助我们确定费用,但是我们排除了它,因为它并不总是可以提前知道的。我们的项目可能会应用于打车行业,我们可以提前预测出行成本,为了准确起见,应该选择源/目的地的位置坐标而不是 trip_distance。
数据清理
我们遵循以下原则来过滤不合理的数据:
- 票价金额应大于 $2.5
 - 出发地/目的地位置坐标应在纽约市限制范围内
 - 乘客数量不能为零
 - 行程距离不能为零
 
SELECT
  (tolls_amount + fare_amount) AS fare_amount, -- label
  pickup_datetime,
  pickup_longitude, 
  pickup_latitude, 
  dropoff_longitude, 
  dropoff_latitude
FROM
  `nyc-tlc.yellow.trips`
WHERE
  -- Clean Data
  trip_distance > 0
  AND passenger_count > 0
  AND fare_amount >= 2.5
  AND pickup_longitude > -78
  AND pickup_longitude < -70
  AND dropoff_longitude > -78
  AND dropoff_longitude < -70
  AND pickup_latitude > 37
  AND pickup_latitude < 45
  AND dropoff_latitude > 37
  AND dropoff_latitude < 45
  -- repeatable 1/5000th sample
  AND MOD(ABS(FARM_FINGERPRINT(CAST(pickup_datetime AS STRING))),5000) = 1
让我们通过从 pickup _datetime 中获取 dayofweek 和 hourofday 来创建一些分类特征
SELECT
  (tolls_amount + fare_amount) AS fare_amount, -- label
  EXTRACT(DAYOFWEEK from pickup_datetime) AS dayofweek,
  EXTRACT(HOUR from pickup_datetime) AS hourofday,
  ------------------
  ------------------
将数据分为训练集、验证集和测试集
我们将我们的1/5000样本分成 70–15–15

将数据写入 CSV
在接下来的步骤中,我们将使用 TensorFlow 创建一个机器学习模型,它直接从 BigQuery 读取文件很慢。因此,我们将数据写成。csv 文件

假设我们只使用了总数据的一个样本(0.02%),我们还有 151k 行可以训练,这已经很不错了。
我们讨论模型创建的下一篇文章可以在这里找到。
在 LinkedIn 上和我联系。你可以在这里找到完整的代码。
干杯!!
使用谷歌云人工智能*台预测纽约市的出租车价格(十亿多行)第 2 部分

Taxis | Photo by Life of Pix on pexels.com
在这一系列文章中,我们正在处理一个真实世界的纽约出租车乘坐数据集,该数据集托管在 BigQuery 中,以便能够估计车费金额。
在上一篇中,我们在 Google 云*台上建立了一个项目,启动了一个预装 TensorFlow 的 AI 笔记本实例,并准备/清理/采样了数据。现在到了我们建立一个模型来预测目标变量的部分。
我们将使用 tf.estimator ,一个高级 TensorFlow API 来构建我们的模型。详细信息可以在这里找到。
使用这个 API 有四个主要步骤。
- 创建一个函数来导入数据集
 - 定义特征列
 - 实例化评估者
 - 培训/评估
 
创建一个函数来导入数据集

另一种方法是使用tf.data.experimental.make_csv_dataset 函数来读取数据集。
对于较小的数据集,我们可以将它们加载到 pandas 数据帧中,因为它们适合内存。我们可以使用tf.data.Dataset.from_tensor_slices读取这些数据帧
导入训练和验证集的函数

定义特征列
任何预测分析项目中最重要的步骤之一是特征工程。有了一些经验、领域专业知识和良好的老式尝试和错误,您可以设计出显著改善最终结果的特性。
存储纬度和经度

一个热编码

TF . feature _ column . crossed _ column
使用 TF . feature _ column . crossed _ column 创建一个为我们提供时间和星期组合信息的要素。例如,周五晚上和周日晚上的票价可能会有很大不同。
fc_crossed_day_hr = tf.feature_column.crossed_column(keys = [fc_dayofweek, fc_hourofday], hash_bucket_size = 24 * 7)
创建一个函数,以便我们可以在读取数据的同时创建新的功能。

我们创建坐标之间的欧几里德距离作为一个特征,以及单独的纬度差和经度差,这将为我们提供关于行驶方向的信息。
最后,创建我们决定用来训练模型的特征列的列表,并创建服务输入接收器函数
培训/评估
线性模型

RMSE 是 7.4
现在,让我们使用 DNN 回归器来训练我们的模型,这将更好地理解非线性关系。


我们得到的均方根误差为 4.13
在下一篇文章中,我们将调整超参数来改进这个结果,并对包含 10 亿次以上乘坐的整个数据进行训练。正如你所猜测的,我们不能在我们的笔记本电脑上这样做。是时候转向云计算了。
资源:Google 云*台上 TensorFlow 的机器学习
在 LinkedIn 上与我联系。你可以在这里找到完整的代码。
干杯!!
使用谷歌云人工智能*台预测纽约市的出租车价格(十亿多行)第 3 部分

Taxis | Photo by Nout Gons on pexels.com
这一系列文章的目标是创建一个机器学习模型,能够在乘坐开始之前估计纽约市的出租车费用。这种模式的一个版本已经应用于拼车行业,用户喜欢在选择目的地后立即知道乘车的费用。
在前两篇帖子中,我们在谷歌云*台上创建了一个项目,清理了数据,创建了功能,并最终在本地这个庞大数据集的一个小样本上训练了一个模型。我们能够达到 4.13 的 RMSE。
[## 使用谷歌云人工智能*台预测纽约市的出租车价格(十亿多行)第 1 部分
这个项目旨在创建一个机器学习模型,使用数据集来估计纽约市的出租车费用…
towardsdatascience.com](/predicting-taxi-fares-in-nyc-using-google-cloud-ai-platform-billion-rows-part-1-ac121832babf) [## 使用谷歌云人工智能*台预测纽约市的出租车价格(十亿多行)第 2 部分
在这一系列文章中,我们正在处理一个真实世界的纽约出租车乘坐数据集,该数据集由 BigQuery 托管,以…
towardsdatascience.com](/predicting-taxi-fares-in-nyc-using-google-cloud-ai-platform-billion-rows-part-2-f0191a70dea8)
在这篇文章中,我们对整个数据集进行训练,并执行超参数调整。我们开始吧。
我已经将来自 Bigquery 的整个 130 GB 数据集作为分片 CSV 文件存储到我在 GCP 的存储桶中。TensorFlow 可以直接从 BigQuery 中读取,但这个过程非常慢,而且最好是使用 CSV 文件,就像我在之前的帖子中使用示例所做的那样。
云人工智能*台
在云上训练有两个主要步骤:
- 把代码做成 Python 包(创建 init)。py、task.py、和 model.py 文件)
 - 将使用 gcloud 的 Python 包提交到云 AI *台
 
创建 task.py
%%writefile your_path/task.py
import argparse
import json
import osfrom . import modelif __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--hidden_units",
        help = "Hidden layer sizes,
        type = str,
        default = "16,16"
    )
    parser.add_argument(
        "--train_data_path",
        help = "Path to training data",
        required = True
    )
    parser.add_argument(
        "--train_steps",
        help = "Training steps",
        type = int,
        default = 1000
    )
    parser.add_argument(
        "--eval_data_path",
        help = "Path to evaluation data",
        required = True
    )
    parser.add_argument(
        "--output_dir",
        help = "Output Directory",
        required = True
    )
    parser.add_argument(
        "--job-dir",
        help="Required by gcloud",
    )
    args = parser.parse_args().__dict__
    # Append trial_id r
    args["output_dir"] = os.path.join(
        args["output_dir"],
        json.loads(
            os.environ.get("TF_CONFIG", "{}")
        ).get("task", {}).get("trial", "")
    ) 
    # Run
    model.train_and_evaluate(args)
创建 model.py
需要优化的超参数需要作为命令行参数传入
%%writefile your_path/model.py
import tensorflow as tf
import numpy as np
import shutil
print(tf.__version__)CSV_COLUMN_NAMES = ["fare_amount","dayofweek","hourofday","pickuplon","pickuplat","dropofflon","dropofflat"]
CSV_DEFAULTS = [[0.0],[1],[0],[-74.0],[40.0],[-74.0],[40.7]]def read_dataset(csv_path):
    def _parse_row(row):
        # Every row into a list of tensors
        fields = tf.decode_csv(records = row, record_defaults = CSV_DEFAULTS)# All the features into a dictionary
        features = dict(zip(CSV_COLUMN_NAMES, fields))
        # Feature Engineering
        features = add_engineered_features(features)
        # Pop the fare_amount 
        label = features.pop("fare_amount")return features, label
    # Create a dataset
    dataset = tf.data.Dataset.list_files(file_pattern = csv_path) # (i.e. data_file_*.csv)
    dataset = dataset.flat_map(map_func = lambda filename:tf.data.TextLineDataset(filenames = filename).skip(count = 1))
    dataset = dataset.map(map_func = _parse_row)
    return datasetdef train_input_fn(csv_path, batch_size = 128):
    # Create the training dataset
    dataset = read_dataset(csv_path)
    # Shuffle
    dataset = dataset.shuffle(buffer_size = 1000).repeat(count = None).batch(batch_size = batch_size)
    return datasetdef eval_input_fn(csv_path, batch_size = 128):
    # Create the Validation dataset
    dataset = read_dataset(csv_path)# Shuffle and batch 
    dataset = dataset.batch(batch_size = batch_size)
    return dataset
# One Hot Encoding
fc_dayofweek = tf.feature_column.categorical_column_with_identity(key = "dayofweek", num_buckets = 7)
fc_hourofday = tf.feature_column.categorical_column_with_identity(key = "hourofday", num_buckets = 24)# Bucketize latitudes and longitudes
NBUCKETS = 16
latbuckets = np.linspace(start = 38.0, stop = 42.0, num = NBUCKETS).tolist()
lonbuckets = np.linspace(start = -76.0, stop = -72.0, num = NBUCKETS).tolist()
fc_bucketized_plat = tf.feature_column.bucketized_column(source_column = tf.feature_column.numeric_column(key = "pickuplon"), boundaries = lonbuckets)
fc_bucketized_plon = tf.feature_column.bucketized_column(source_column = tf.feature_column.numeric_column(key = "pickuplat"), boundaries = latbuckets)
fc_bucketized_dlat = tf.feature_column.bucketized_column(source_column = tf.feature_column.numeric_column(key = "dropofflon"), boundaries = lonbuckets)
fc_bucketized_dlon = tf.feature_column.bucketized_column(source_column = tf.feature_column.numeric_column(key = "dropofflat"), boundaries = latbuckets)# Crossed Column
fc_crossed_day_hr = tf.feature_column.crossed_column(keys = [fc_dayofweek, fc_hourofday], hash_bucket_size = 24 * 7)def add_engineered_features(features):
    features["latdiff"] = features["pickuplat"] - features["dropofflat"] 
    features["londiff"] = features["pickuplon"] - features["dropofflon"] 
    features["euclidean_dist"] = tf.sqrt(x = features["latdiff"]**2 + features["londiff"]**2)
    features["dayofweek"] = features["dayofweek"] - 1return features#1\. Created using tf.feature_column module
    tf.feature_column.indicator_column(categorical_column = fc_crossed_day_hr),
    fc_bucketized_plat,
    fc_bucketized_plon,
    fc_bucketized_dlat,
    fc_bucketized_dlon,
    #2\. Created in the input functions
    tf.feature_column.numeric_column(key = "latdiff"),
    tf.feature_column.numeric_column(key = "londiff"),
    tf.feature_column.numeric_column(key = "euclidean_dist") 
]def serving_input_receiver_fn():
    receiver_tensors = {
        'dayofweek' : tf.placeholder(dtype = tf.int32, shape = [None]), # shape is vector to allow batch of requests
        'hourofday' : tf.placeholder(dtype = tf.int32, shape = [None]),
        'pickuplon' : tf.placeholder(dtype = tf.float32, shape = [None]), 
        'pickuplat' : tf.placeholder(dtype = tf.float32, shape = [None]),
        'dropofflat' : tf.placeholder(dtype = tf.float32, shape = [None]),
        'dropofflon' : tf.placeholder(dtype = tf.float32, shape = [None]),
    }
    features = add_engineered_features(receiver_tensors) # 'features' is what is passed on to the model
    return tf.estimator.export.ServingInputReceiver(features = features, receiver_tensors = receiver_tensors)
def train_and_evaluate(params):
    OUTDIR = params["output_dir"]model = tf.estimator.DNNRegressor(
        hidden_units = params["hidden_units"].split(","), 
        feature_columns = feature_cols, 
        model_dir = OUTDIR,
        config = tf.estimator.RunConfig(
            tf_random_seed = 1, # for reproducibility
            save_checkpoints_steps = max(100, params["train_steps"] // 10)
        ) 
    )def my_rmse(labels, predictions):
        pred_values = tf.squeeze(input = predictions["predictions"], axis = -1)
        return {"rmse": tf.metrics.root_mean_squared_error(labels = labels, predictions = pred_values)}
    model = tf.contrib.estimator.add_metrics(model, my_rmse)train_spec = tf.estimator.TrainSpec(
        input_fn = lambda: train_input_fn(params["train_data_path"]),
        max_steps = params["train_steps"])exporter = tf.estimator.FinalExporter(name = "exporter", serving_input_receiver_fn = serving_input_receiver_fn)eval_spec = tf.estimator.EvalSpec(
        input_fn = lambda: eval_input_fn(params["eval_data_path"]),
        steps = None,
        start_delay_secs = 1, 
        throttle_secs = 1, 
        exporters = exporter)tf.logging.set_verbosity(v = tf.logging.INFO) # so loss is printed during training
    shutil.rmtree(path = OUTDIR, ignore_errors = True) # start fresh each timetf.estimator.train_and_evaluate(model, train_spec, eval_spec)
创建超参数调整配置
云 AI *台默认使用贝叶斯优化。当只调整几个参数时,我们也可以使用网格搜索或随机搜索。
这里我们只调整一个参数,即隐藏单元的数量。所有试验都是*行进行的。

启用 AI *台 API

运行培训作业

我们可以在数据集的一部分上运行这个来获得更好的想法,然后在整个数据上尝试最佳组合。
我发现隐藏单元的最佳配置是“ 64,64,64,8 ”,RMSE 为 3.98。
我们的三部分系列到此结束。通过采用不同的方法,如设计新功能、选择不同的模型、调整更多的超参数等,可以实现许多改进。创造最好的模型需要耐心和大量的尝试和错误。
资源:Google 云*台上 TensorFlow 的机器学习
在 LinkedIn 上与我联系。你可以在这里找到完整的代码。
干杯!!
使用更少的数据预测更多训练数据的效果
使用地理空间深度学习的案例研究,一步一步地估计增加的训练数据的价值

A satellite image and its building footprint ground truth mask from our geospatial case study.
场景是这样的:你付出了巨大的困难和代价来收集一些训练数据,并使用这些数据来训练一个深度神经网络。然而,你发现自己在想,“我有足够的钱吗?”更多的训练数据会带来有意义的性能提升吗,或者只是为了无关紧要的收益而浪费时间和金钱?起初,这看起来几乎是矛盾的:如果不知道收集更多数据会有多大帮助,你就无法做出明智的决定,但除非你已经做出决定并获得了额外的数据,否则你无法衡量它会有多大帮助。
然而,有一个解决办法。通过用现有的不同大小的训练数据子集重复训练深度神经网络,有可能将性能外推至超出目前可用的训练数据量。
我们将使用计算机视觉领域的一个重要的测试案例来完成这个过程:在卫星照片中描绘出建筑物的轮廓。自动绘制建筑物地图的能力,而不是每次事情发生变化都依赖大量的人工劳动,其应用范围从救灾到城市规划。
我们的案例研究:在卫星图像中构建足迹
数据
要对卫星图像进行研究,我们需要从获取一些图像开始!为此,我们求助于 SpaceNet ,它维护着一个免费、开源、随时可用的数据存储库,存储了数千*方公里的带标签的高分辨率卫星图像。
我们将使用 SpaceNet 的最新(截至本文撰写时)数据发布:Maxar 的 WorldView-2 卫星在佐治亚州亚特兰大上空采集的一系列数据。影像中包含高质量的建筑物覆盖区(轮廓)标注。这个数据集是现在已经完成的 SpaceNet4 挑战的基础。这些影像从 27 个不同的视角显示了同一区域,这使得它非常适合研究视角如何影响地理空间深度学习算法的性能。为了简单起见,我们将我们的结果分为三类:“天底”,视角在天底 25 度以内(垂直向下),“离天底”,视角从天底 26 度到 40 度,以及“远离天底”,视角超过天底 40 度。我们还将“总体”绩效定义为三个类别绩效的简单*均值。图 1 示出了从不同角度成像的例子。

Fig. 1: Different viewing angles for the same physical location, including (a) an on-nadir view, (b) an off-nadir view from the north, and © a far-off-nadir view from the south. Image (d) shows the corresponding building footprint mask, used in training to tell the model what is or isn’t a building.
模型
我们将训练的寻找建筑物的模型也来自 SpaceNet。我们将使用第五名提交的 SpaceNet4 挑战赛。虽然其他一些提交稍微优于这个模型,但这个模型由于其快速的推理时间和简单的架构而更受欢迎。该模型的推理速度比顶级 SpaceNet4 获胜者快十倍以上。它使用带有 VGG-16 编码器的 U-Net 进行像素分割,然后根据像素图生成建筑物覆盖区多边形。为了加快训练,最初提交的三个神经网络的集合被削减为一个网络,仅导致适度的性能下降,这在别处讨论过。
为了量化模型性能,为模型识别的建筑足迹计算 F1 分数。出于计算目的,如果一个占地面积与地面真实建筑占地面积的 IoU (交集/并集)至少为 0.5,则认为该占地面积是正确的。
结果呢
若要了解模型性能如何依赖于训练数据量,请使用不同的数据量对同一模型进行训练。
数据被切割成 900 像素的方块,每个方块显示 450 米的面积。*均每个瓦片有 63 个建筑。在训练数据中有 1064 个独特的图块位置,每个位置有 27 个视图。由于我们的算法留出了四分之一的数据用于验证,因此对完整数据集的训练给了我们 1064 * 27 * (3/4) = 21546 幅图像。图 2 显示了如果我们用更少的数据训练会发生什么。训练和评估过程重复十次。但是每一次,我们从零开始,使用的数据只有上次的一半。当数据不足时,性能会随着新数据的增加而迅速提高,但当数据充足时,回报会逐渐减少。

Fig. 2: Model performance, as measured by F1 score, versus number of training images. Images are 900x900 pixel regions of satellite photos with 0.5m resolution.
既然我们都同意我们的案例研究,是时候把它作为解决我们主要问题的环境了:在数据可用之前,我们如何用大量数据对模型性能做出有根据的猜测?要做到这一点,有几个步骤。
第一步:知道何时停止训练
对于这个过程,我们将需要使用不同数量的数据从头开始多次训练模型。如果模型是硬编码的,以训练一定数量的时期或一定数量的时间(无论是使用该时期后的最终权重还是最佳中间权重),则值得努力研究所有这些时间是否真的有必要。图 3 示出了对于不同数量的数据,作为训练时间的函数的模型性能。最上面的一行使用完整的数据集,随后的每一行使用其上一行的大约一半的训练数据。

Fig. 3: Model performance, as measured by F1 score, versus amount of training time. Training time is expressed as number of image views and also approximate GPU-days on Nvidia Titan Xp GPUs.
回想一下,当训练数据集大小减半时,训练时期的数量必须加倍,以获得相同的图像视图总数。但是,达到最高性能所需的图像视图数量可能会随着数据的减少而减少。对于我们的地理空间案例研究,使用 21546 幅图像的完整训练数据集,需要大约 60 个历元才能达到最佳性能。但是当只使用了几百个图像时,必要的图像视图的数量下降到低于全部训练数据集的 5 个时期的当量。使用完整的数据集进行训练大约需要四个 GPU 日(在 Nvidia Titan Xp 上)。虽然这是不可避免的,但知道我们至少可以在减少数据的情况下进行较少的培训,这带来了一些值得欢迎的时间节省。
一旦我们用不同数量的数据进行了训练,并评估了模型的每个版本,我们就可以在图 2 中绘出这些点。但是我们还没有准备好去拟合一条曲线。
步骤 2:生成误差线
许多深度学习论文引用性能数据时没有误差线。然而,在没有误差线的情况下,不清楚观察到的性能改进是否具有统计意义,或者结果是否可重复。对于我们的外推任务,误差线是必要的。在案例研究中,我们有十个数据点,每个数据点代表不同数量的训练数据。为了节省时间,我们将只计算其中四个的误差线,并对其余的进行对数插值。为了计算误差线,我们只需用给定数量的数据多次重复模型训练/测试过程,并取结果的标准偏差。图 4 示出了与图 2 相同的信息,但是具有对数 x 轴以更好地显示少量数据的误差条。

Fig. 4: Identical to Fig. 2, but with a logarithmic x-axis.
我将在后续研究中使用的一种更好的方法是,针对所考虑的每个训练数据量重复训练模型,然后绘制一个不是单个结果而是每个训练数据量的结果*均值的图。
第三步:拟合曲线
接下来,为了理解 F1 分数对训练数据量的依赖性,我们希望能够对这些变量的关系进行建模,最好是用一条简单的曲线。
为了获得灵感,我们求助于文献。关于我们特定类型的案例研究(地理空间环境中语义分割的 F1 分数的数据大小依赖性)还没有太多的著述。但是深度学习分类问题已经有了很多工作[ 1 、 2 、 3 、 4 ]。对于这些,发现精度的数据集大小依赖性与常数减去逆幂律项成比例(图 5)。令人高兴的是,相同的函数形式非常适合我们的测试用例,尽管这不是一个分类问题。事实上,图 2 和图 4 中虚线所示的拟合曲线是使用这种函数形式生成的。

Fig. 5: A constant minus an inverse power law. The variable x is the amount of training data; y is the estimated F1 score; and a, b, and c are positive free parameters.
一旦我们有了一条拟合曲线,我们就可以用它来推断给定的大量数据的性能。总结一下这个过程:用不同数量的数据训练同一个模型,估计每个数量的误差线,并使用加权回归来生成一个简单的模型,说明性能如何随训练数据的数量而变化。现在是时候尝试这个过程了,看看在训练数据量有限的情况下它的表现如何。
对方法进行测试
假设我们没有完整的训练数据集,只有它的十六分之一。只有 1,323 张图像需要训练,而不是 21,546 张,我们希望通过获取 16 倍的训练数据来评估改进。图 6 显示了当我们遵循上面的三个步骤时会发生什么。这里,我们在拟合曲线时简单地忽略了超过 1,323 个图像的点。这种测试有些人为,因为低训练数据样本并不局限于从全部数据集的十六分之一中抽取。然而,预计这不会实质性地改变结果。

Fig. 6: F1 score vs. amount of training data (solid lines), along with fitted curves (dotted lines) that are based on only the points with 1,323 training images or fewer.
从 1,323 幅图像开始,表 1 显示了将训练数据增加一倍和将其增加 16 倍后的实际和预测性能提高。在每一种情况下,预测都是正确的,误差在 2 倍以内,在大多数情况下,误差在 25%以内。这些数字指的是 F1 分数中的估计改进,而估计 F1 分数本身的百分比误差要低得多。随着训练数据的增加,测量和预测的结果往往会逐渐偏离。然而,F1 分数随着更多的数据而增加,这限制了百分比误差的增长。因此,在这个案例研究中,该方法给出了训练数据增长 16 倍的估计值,这与其仅增长 2 倍的估计值相当。作为比较,用简单的对数曲线拟合数据,而不是常数减去幂律,会产生最大百分比误差,几乎是这里看到的两倍。

Table 1: Comparison of measured and estimated improvement with a 2-fold data increase and a 16-fold data increase. “Measure” is the actual increase in F1 score, “predict” is the increase predicted by the model, and “% Error” is the percentage error between them.
结论和警告
在这个建筑物占地面积案例研究中,我们可以预测训练数据从 16 倍增长到 2 倍以内的性能改善。虽然在数据科学中没有放之四海而皆准的解决方案,但这种方法可以帮助您在下一次发现自己不知道是否要获取更多训练数据时做出决定。
有几个警告值得一提。在这种外推方法中隐含了一种假设,即我们已经拥有的训练数据和我们可能获得的新训练数据来自同一分布。例如,如果我们试图获取的新的训练数据来自不同的城市,或者来自同一城市的不同部分,它们在整体外观上与我们已经可用的数据源不同,那么这就不成立。即使假设成立,也不能保证 F1 分数对训练数据集大小的依赖性与本案例研究中看到的一样。没有一种方法可以取代深思熟虑的判断和对数据独特性的深刻理解。然而,这可能是为您的数据科学项目做出最佳决策的建设性起点。
用泊松过程预测小行星撞击的频率

泊松过程和泊松分布在模拟地球小行星撞击中的应用
这里有一些好消息:如果你花了几个小时通过阅读理论书籍和课堂笔记来研究一个概念,但你似乎无法理解,有一种更好的学习方法。从理论开始总是困难和令人沮丧的,因为你看不到一个概念最重要的部分:如何用它来解决问题。相比之下,边做边学——解决问题——更有效,因为它给你背景,让你把技巧融入你现有的思维框架。此外,对于那些被解决问题的内在愿望所驱动的来说,通过应用程序学习更令人愉快。
在本文中,我们将应用泊松过程和泊松分布的概念来模拟地球小行星撞击。我们将在中介绍的原则基础上构建泊松过程和泊松分布解释,用真实世界的数据将想法付诸实践。通过这个项目,我们将了解如何使用统计概念来解决问题,以及如何将观察到的结果与理论上的预期结果进行比较。
本文的完整代码(包括交互式应用)可以通过点击图片在 mybinder.org 上运行。Jupyter 笔记本在 GitHub 上。
Click to launch a Jupyter Notebook on mybinder.org for this article.

Probability Mass Function of Number of Asteroid Impacts
泊松过程和泊松分布基础
我们不会涵盖全部细节(见此处),但这些是我们需要的基本信息:泊松过程是一个罕见事件的模型——比如小行星撞击——其中我们知道事件之间的*均时间,但任意两个事件之间的实际时间是随机分布的(随机)。每个事件都是独立于所有其他事件的,这意味着我们不能使用自上一个事件以来的时间来预测下一个事件将在何时发生。泊松模型是二项式模型的扩展,适用于预期成功次数远少于试验次数的情况。
泊松过程中的每个子区间都是伯努利试验,事件要么发生(成功),要么不发生。在我们的小行星例子中,事件是小行星撞击,子间隔是一年,所以每年,撞击要么发生,要么不发生(我们假设每年最多一次撞击,并且撞击是独立的)。幸运的是,小行星撞击很少发生,所以与我们将要考虑的年数(试验)相比,成功的总数很低。此外,我们知道撞击的*均间隔时间(我们从数据中获得),但不知道撞击发生的确切时间。
为了计算在一个时间间隔内发生的大量泊松过程生成事件的概率,我们使用泊松分布和概率质量函数(PMF):

Poisson Probability Mass Function (PMF) Distribution
其中事件/时间是频率,如影响/年。这个公式有些复杂,所以我们将(事件/时间)*时间简化为一个参数, λ。 Lambda 是分布的速率参数,也是我们定义泊松所需的唯一参数:

Poisson PMF
Lambda 是时间段内事件的预期(最有可能)数量。当我们改变λ时,不同数量的事件的概率改变:

Poisson PMF Distribution with differing values of lambda (rate parameter)
最后,事件之间的时间分布(等待时间)是一个指数衰减。事件之间等待时间超过 t 的概率为:

Probability of waiting longer than t in a Poisson process
泊松过程中的等待时间是无记忆的,意味着它们彼此不依赖。事件之间的*均等待时间为 1 /频率。泊松分布很容易理解,因为它只需要一个参数,即频率参数,即间隔内事件的预期数量,或频率*时间。
小行星撞击数据
为了使用泊松过程和小行星撞击的分布,我们需要的是小行星撞击的*均频率。坏消息是没有足够的数据来精确地确定利率。好消息是,科学家们已经根据我们现有的数据(如*地小行星的数量)和稳健的模拟得出了一些估计。我们将使用*地天体科学定义小组的 NASA 2017 年报告中的数据,在大量有趣的信息中,这些数据提供了对不同大小的小行星撞击频率的估计。
一旦我们加载了数据并清理了列,我们就有了这些数据:

Data from NASA 2017 NEO SDT (5 of the 27 rows)
每一行都是不同大小的小行星(*均diameter公里),关键列是impact_frequency。这给出了每年撞击的*均次数,我们可以通过取倒数将其转换成time_between_impacts。impact_frequency随着体积的增大而减小,因为大的小行星较少(由number指定)。
虽然这不是必须的,但我喜欢从数据分析开始,比如按直径查看撞击能量或按直径查看撞击间隔时间:


请注意,这两个图都是对数标度,撞击能量以百万吨当量 TNT 表示。作为比较,最大的人体炸弹大约是 100 兆吨,而最大的小行星是 1000 万兆吨(在地球附*只有两个)。从撞击间隔时间图来看,随着小行星的大小增加到撞击间隔超过 1 亿年,撞击的频率迅速降低。
为了探索数据,笔记本中有一个交互式探索工具。

Interactive data exploration tool in notebook.
根据数据探索,我们应该预计来自较大小行星的撞击较少,因为它们的撞击频率较低。如果我们的建模结果与这个结论不一致,那么很可能有问题!
模拟小行星撞击
我们的目标是确定每个大小类别中预期影响数量的概率分布,这意味着我们需要一个时间范围。为了保持客观,我们从 100 岁开始,大约是一个人的寿命。这意味着我们的分布将显示人类一生中撞击次数的概率。因为我们使用的是概率模型,所以我们进行了多次试验,然后得出结果的分布,而不是使用一个数字。对于一个大样本,我们将对一个人的一生模拟 10,000 次。
在 Python 中使用np.random.poisson函数模拟泊松分布很简单,该函数根据给定速率参数lam的泊松分布生成大量事件。为了运行 10,000 次试验,我们将其设置为size。下面是运行最小小行星类别撞击频率模拟的代码。
# Simulate 1 lifetime 10,000 times
years = 100
trials = 10_000# Extract the first frequency and calculate rate parameter
freq = df['impact_frequency'].iloc[0]
lam = freq * years# Run simulation
impacts = np.random.poisson(lam, size=trials)
结果在直方图中最直观:

Simulation results showing frequency of each number of impacts
我们看到,在 10,000 次模拟寿命中,最常见的撞击次数是 0。鉴于 rate 参数的值(这是最有可能的结果),这是意料之中的:
print(f'The most likely number of impacts is {lam:.2f}.')**The most likely number of impacts is 0.47.**
(由于泊松分布仅在离散数量的事件中定义,我们应该将其四舍五入为最接*的整数)。
为了将模拟结果与理论预期结果进行比较,我们使用泊松概率质量函数和速率参数计算了每次撞击的理论概率:
from scipy.special import factorial# Possible number of impacts
n_impacts = np.arange(0, 10, 0.25)# Theoretical probability of each number of impacts
theoretical = np.exp(-lam) * (
               np.power(lam * n_impacts) / factorial(n_impacts))
(我们使用分数事件来获得*滑曲线。)
然后,我们将它绘制在条形的顶部(在归一化以获得概率之后):

Observed and theoretical number of impacts over 100 years for the smallest asteroids.
当观察到的(在这种情况下是模拟的)结果与理论相符时,感觉真好!我们可以使用相同的poisson函数和矢量化numpy运算将我们的分析扩展到所有大小的小行星:
# Each trial is a human lifetime
trials = 10000
years = 100# Use all sizes of asteroids
lambdas = years * df['impact_frequency'].values
impacts = np.random.poisson(lambdas, size=(10000, len(lambdas)))
impacts.shape**(10000, 27)**
这给了我们 27 种大小的小行星中每一种的一万次生命模拟。为了直观显示这些数据,我们将绘制每个尺寸范围的*均冲击次数以及预期冲击次数(速率参数)。

Average observed and theoretical number of impacts for all asteroid sizes.
同样,结果与理论相符。对于大多数小行星来说,一生中观察到一次撞击的机会微乎其微。
对于另一个可视化,我们可以绘制所有小行星大小的泊松 PMF:

Poisson PMF for all asteroids
在超过 100 年的时间里,最有可能的影响次数是 0。对于我们这些生活在 2013 年的人来说,我们已经经历了一次小行星事件(尽管不是撞击),当时一颗直径 20 米(0.02 公里,此处使用的单位)的*地小行星在车里雅宾斯克州上空爆炸。然而,因为泊松过程的等待时间是无记忆的,所以得出现在看到另一次小行星撞击的可能性较低的结论是错误的,因为最*就有一次。
增加模拟长度以获得更多影响
为了看到更多的影响,我们可以在更长的时间内运行模拟。由于属人(我们的属)已经存在了 200 万年,让我们运行 200 万年的 10000 次模拟,看看小行星撞击的预期次数。我们所要做的就是改变年数,这反过来会影响速率参数。
# Simulate 2 million years 10,000 times
years = 2_000_000
trials = 10_000# Run simulation for all asteroid sizes
lambdas = years * df['impact_frequency'].values
impacts = np.random.poisson(lambdas, size=(10000, len(lambdas)))
绘制模拟的和理论的*均撞击次数,这次是以对数标度,我们得到以下结果:

Observed and theoretical asteroid impacts over 2 million years.
现在我们观察到更多的影响,这是有意义的,因为我们正在考虑一个更长的时间段。
超过 200 万年的所有小行星的泊松 PMF 是:

Poisson PMF for all asteroid sizes over 2 million years.
同样,预期(*均)撞击次数将是每个小行星大小的速率参数 λ 。
对于长期的模拟,我们确实观察到了较大小行星的撞击。

Observed and theoretical impacts for larger asteroids over longer time period
记住,在俄罗斯上空爆炸的车里雅宾斯克流星直径是 20 米(0.020 公里)。我们正在谈论这张图表中的一些大质量小行星。
撞击间隔时间
我们可以使用泊松过程模型的另一种方法是计算事件之间的时间。事件之间的时间超过 t 的概率由以下等式给出:

计算理论值非常简单:
# Frequency for smallest asteroids
freq = df['impact_frequency'].iloc[0]# Possible waiting times
waiting_times = np.arange(0, 2500)
p_waiting_times = np.exp(-freq * waiting_times)
这种关系遵循指数衰减规律:

Probability distribution for waiting time between asteroid impacts.
为了使用实际数据模拟等待时间,我们可以将 1 亿年建模为单独的伯努利试验(影响或不影响)。每一年成功的概率只是频率。等待时间就是两次撞击之间的年差(对最小的小行星进行研究):
years = 100_000_000# Simulate Bernoulli trials
impacts = np.random.choice([0, 1], size=years, p=[1-freq, freq])# Find time between impacts
wait_times = np.diff(np.where(impacts == 1)[0])
将其绘制成直方图,得出以下结果:

Observed waiting time between asteroid impacts for smallest asteroids.
为了确保观察到的数据与理论相符,我们可以将这两者绘制在彼此之上(归一化和宁滨后):

Waiting time observed and theoretical for smallest size of asteroids.
作为最后一幅图,我们可以看看所有小行星大小的*均撞击间隔时间,包括观察到的(模拟的)和理论上的:

Average observed and theoretical waiting time between impacts for all asteroid sizes.
即使超过 1 亿年,最大的小行星也没有受到撞击(或者只有一颗,这意味着我们无法计算等待时间)。这是有道理的,因为撞击之间的预期时间超过 1 亿年!
交互作用分析
笔记本的最后一部分是一个交互式分析,您可以使用参数来观察效果。您可以更改运行模拟的时间长度、要检查的直径以及试验次数。

Interactive asteroid impacts analysis in Jupyter Notebook.
我鼓励你亲自进行分析,看看这些参数如何改变结果,方法是到mybinder.org的 Jupyer 笔记本上。
结论
在学校的时候,我有过很多次这样的经历:在课堂上,我认为我对一个主题的理解是完整的,但却打开了作业,不知道从哪里开始。这种理论与应用的不匹配在家庭作业中已经够糟糕了,当涉及到现实世界的问题时甚至更糟。直到我大学的最后两年,当我开始通过做问题来学习时,我应用概念的能力(同样重要的是,我在学习中的快乐)才得到发展。虽然理论仍然很重要(我通常会在看到使用中的概念后再回去研究),但仅仅通过严格的推导很难掌握一个概念。
任何时候你遇到一个你难以理解的话题,寻找真实世界的数据,并开始尝试用这种技术解决问题。在最坏的情况下,你仍然会被卡住(记住寻求帮助是好的),但在最好的情况下,你会掌握方法,并享受学习过程。
在本文中,我们看到了如何将统计概念(泊松过程模型和泊松分布)应用到现实世界中。虽然小行星可能不会影响我们的日常生活,但这个项目显示了我们可以应用于其他类似问题的方法的潜在用途。由于问题的多样性,数据科学需要不断扩展自己的技能。每当我们学习一项新技术时,我们会变得更有效,如果我们能通过将一个概念应用到新数据中来享受这个过程,那就更好了。
一如既往,我欢迎反馈和建设性的批评。你可以在推特上找到我。
预测(音乐的)未来
利用 Python 和线性回归预测音乐流行度
泰勒·福格蒂,彼得·伍斯特,拉塔·古德尔
在大数据时代,我们在预测方面拥有空前的优势。有了像 Kaggle.com 和 OurWorldinData.org 这样的网站,我们手头有无穷无尽的数据——我们可以用这些数据来预测 2020 年谁会赢得 NCAA 锦标赛,下个月全球会卖出多少鳄梨,或者 10 年后芝加哥的犯罪率。当然这些都还是预测,但是这些预测没有合适的数据是做不出来的。
例如,我们花了一个美丽的夏日进行测试,看看你能否根据一组给定的指标预测一首歌在 Spotify 百强排行榜上的排名。

https://variety.com/2018/music/news/spotify-reveals-its-top-songs-of-the-summer-1202917332/
目标和数据描述
重要提示:在评估和比较模型时,应该使用所有这 3 个指标。就我们的目的而言,它们被分成“方法”,但是为了最好地评估一个模型的准确性,应该结合使用。

方法 1:误差分析
一旦开发出一个模型,下一步就是看它的表现如何。为了衡量模型的成功,数据科学家开发了误差指标来判断预测值和实际值的匹配程度。我们的预期值和预测值之间的差异被称为残差集,本质上是数据与我们用来预测的拟合回归线有多远的度量。虽然我们可以检查每个数据点的残差来衡量模型的有用性,但对于大型数据集来说,这可能特别繁琐。有许多统计数据总结了残差,但我们将坚持使用均方误差、*均绝对误差、均方根误差和*均绝对百分比误差。
为了解释这些,让我们来看一下我们的简化模型,它是通过逐步选择过程建立的*:
人气=响度+活跃度+节奏+关键
均方差和均方根误差是目前最常用的误差指标。MSE 是残差*方的*均值,通常被称为模型的方差。RMSE 是 MSE 的*方根,或模型的标准差,最适用于比较不同模型之间的差异,因为 RMSE 的单位与目标变量相同。使用 scikit-learn 库可以很容易地找到这两者:
mse = mean_squared_error(test_act,predicted)
print(mse) #Mean Square Error
math.sqrt(mse) #Root Mean Square Error
该模型的均方误差和 RMSE 分别为 2196.52 和 46.87。这意味着当你记住我们的目标只是从 1 到 100 时,数据是非常分散的。然而,如果你看看下面的残差图,虽然预测的流行度与实际排名相差甚远,但似乎有一个异常值,或者至少是一个意想不到的值。我们应该记住,MSE 和 RMSE 可能会受到异常值的严重影响,因为残差是*方的,并查看其他指标。

我们还可以使用*均绝对误差,它可以更好地解释异常值,因为它采用残差的绝对值,而不是对它们求*方。这也可以通过*均绝对百分比误差来报告,即百分比当量。也可以使用 scikit 找到 MAE 学习起来非常容易:
mae = mean_absolute_error(test_act,predicted)
print(mae) #Mean Absolute Error
同样,考虑到我们所拥有的数据,这个值 46.42 是很高的,所以我们可以得出结论,在给定这些参数的情况下,该模型很难准确预测一首歌的流行度。然而,我们仍然希望找到一个模型来估计一首歌的受欢迎程度,所以我们将继续使用一些不同的预测方程和一些不同的评估指标。
方法二:测定
相反,我们可以通过查看 R *方和调整后的 R *方值来评估基于确定的模型。前者通常称为决定系数,是模型解释的可变性的百分比,或数据与回归线的拟合程度。目标是使 R 的*方为 1,这意味着模型可以解释 100%的变化,但由于随机误差,这种情况很少发生。大多数统计分析会查看 R *方值来评估模型的准确性,因此使用 scikit-learn 也很容易找到:
model = LinearRegression()
model.fit(X, y)
R = model.score(X, y)
print(R)
不幸的是,完整模型的 R *方并不高,为 0.164。该模型仅解释了 16.4%的变化,这意味着大约 84%的变化来自其他地方,无论是来自我们没有的第 14 个变量,还是来自歌曲的流行程度是随机的。为了更好地理解这个模型有多精确,我们还应该看一下调整后的 R *方,它惩罚了一个模型,因为它包含了没有添加到变异解释中的变量。本质上,如果我们有一个非常简化的流行度=节奏的模型,并决定看看是否增加能量,流行度=节奏+能量,并且增加能量并没有使预测更接*,调整后的 R *方会减少。这一点很重要,因为未调整的 R *方总是会随着更多参数的增加而增加,但这可能会导致模型过度拟合。我们可以在下面看到这出戏,我们从除了响度和持续时间之外的所有参数的简化模型开始。通过重新加入这些变量,未调整的 R *方增加很少,但调整后的 R *方明显减少。

model = LinearRegression()
model.fit(X, y)
aR = 1 - (1-model.score(X, y))*(len(y)-1)/(len(y)-X.shape[1]-1)
print(aR)
正如你所看到的,调整后的 R *方比未调整的 T2 低得多,这表明该模型包含了无助于预测的参数。所以,让我们回头看看我们的预测方程:
人气=速度+基调+活跃度+响度
X = data.iloc[:100,3:16]
y = data.iloc[:100,16:]
X = X[['liveness','loudness','key','tempo']]model = LinearRegression()
model.fit(X, y)
print(str(model.score(X, y))) #R-squared
print(str(1 - (1-model.score(X, y))*(len(y)-1)/(len(y)-X.shape[1]-1))) #adjusted R-squared
虽然未调整的 R *方下降到 13.3%,但调整后的 R *方增加到 9.6%,这使我们有信心这是一个比完整模型更好的模型。可悲的是,它仍然是一个可怜的模型。我们不能用这个模型准确地做出预测,但这是我们最好的…
方法 3:信息标准
现在,假设我们想要比较这个模型比完整模型好多少。为此,我们将使用两个指标:赤池信息标准(AIC)和贝叶斯信息标准(BIC) 。与误差统计和决定系数相比,这两个评估器的使用频率较低,但在比较模型时非常有用。
AIC 和 BIC 都衡量模型的质量,并解释过度拟合和欠拟合的模型。两者之间的主要区别是 BIC 倾向于简约的模型,惩罚复杂性或添加更多类似于调整后的 R *方的参数。
#function to calculate the Akaike Information Criterion
def AICcalc(X):
  y = X['popularity']
  del X['popularity']
  X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1) #takes training set
  model = LinearRegression()
  model.fit(X_train, y_train) #fits linear regression line to training data
  inter = model.intercept_
  betas = model.coef_
  y_pred = model.predict(X_test) #predicts popularity of test data
  residuals = y_test - y_pred #finds difference between actual popularity and predicted popularity
  K= len(betas)
  n= len(X_test)
  AIC = float(n*math.log(sum(residuals**2)/n) + 2*K) #calculates AIC
  X['popularity'] = popularity
  return AICdef BICcalc(X):
  y = X['popularity']
  del X['popularity']
  X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1)
  model = LinearRegression()
  model.fit(X_train, y_train)
  inter = model.intercept_
  betas = model.coef_
  y_pred = model.predict(X_test)
  residuals = y_test - y_pred
  K= len(betas)
  n= len(X_test)
  BIC = float(K*math.log(n) + n*math.log(sum(residuals**2)/n)) #calculates BIC
  X['popularity'] = popularity
  return BIC
对于具有取自数据的随机训练集的完整模型,AIC 和 BIC 分别是 94.446 和 100.373。正如您所猜测的,由于更多参数的惩罚因子,BIC 略高。然而,AIC 和 BIC 经常被报道与最佳车型相比较。
为了比较这些模型,我们对每个模型进行了 10,000 次迭代计算,以找出 AIC 和 BIC 的*均值。这一点很重要,因为我们的样本量很小,其值很大程度上取决于为训练集选择的观察值。
def find_crit(X):
  rep = 10000
  totalA = 0
  totalB = 0
  for i in range(rep):
    totalA += AICcalc(X)
    totalB += BICcalc(X)
    return [totalA,totalB]
  avgAIC = totalA/rep
  avgBIC = totalB/rep
  return [avgAIC,avgBIC]

从图中可以清楚地看到,参数的增加增加了 AIC 和 BIC,但是可能的最佳模型具有 3 个参数(活跃度、响度和速度)。该模型的 AIC 为 78.04,BIC 为 75.97,R *方为 0.105,调整后的 R *方为 0.077,*均相对误差为 43.9,均方误差为 1933.7。
print(criterion[3:4]) #AIC and BIC for modelX= data.iloc[:100,3:16]
y=data.iloc[:100,16:]
X= X[['liveness','loudness','tempo']]model= LinearRegression()
model.fit(X,y)
print(model.score(X,y)) #R-squared
print(str(1-(1-model.score(X,y))*(len(y)-1)/(len(y)-X.shape[1]-1)))train_exp = X.iloc[:95,:]
train_res = y.iloc[:95,:]
test_exp = X.iloc[95:,:]
test_act = y.iloc[95:,:]matr_exp = MLR(train_exp,train_res, test_exp, test_act)
predicted = matr_exp.fit_pred()mae = mean_absolute_error(test_act,predicted)
print(mae) #Mean Absolute Error
mse = mean_squared_error(test_act,predicted)
print(mse) #Mean Squared Error
结论
总的来说,我们可以得出结论,使用数据集中的这些变量,我们无法准确预测一首歌的受欢迎程度。我们甚至不能真正靠*。即使最好的模型也预测在点 100 的歌曲在点 50 附*上升。

Residual plot for final model

从数据来看,任何变量都没有明显的趋势。这令人惊讶吗?不。音乐流行是一件非常复杂的事情,艺术家的声誉、歌词的含义、流派以及一首歌曲在一年中的发布时间等变量都会影响它的流行程度,而不仅仅是人类对已经在文化上流行的歌曲的快速痴迷。
*逐步选择程序以 0.1 的进入水*和 0.1 的停留水*进行。这些是比大多数程序更高的α水*,但是由于变量通常是弱预测器,标准程序产生了包含零变量的模型,这不是很有帮助。
关键词汇:
- 逐步选择:特征选择的方法,根据变量在帮助预测响应变量中的重要性来删除和添加变量
 - 残差:实际响应减去预测响应
 - 参数:用于预测目标变量的值
 - 过度拟合:用过多的变量拟合模型,导致模型只适合你训练的数据
 - 欠拟合:用比所需更少的变量拟合模型,导致模型不适合或预测不佳
 - 均方误差(MSE) :残差*方的*均值;差异
 - 均方根误差(RMSE) :以响应变量为单位的 MSE 的*方根,使其在模型之间具有可比性;标准偏差
 - *均绝对误差(MAE) :残差绝对值的*均值
 - *均绝对百分比误差(MAPE) :以百分比表示的*均误差
 - R *方:又名决定系数,模型解释的方差的百分比
 - 调整后的 R *方:修改后的 R *方,对添加无关紧要的参数进行惩罚
 - 赤池信息标准(AIC) :模型的相对质量,通常报告为与最佳模型的差异
 - 贝叶斯信息标准(BIC) :修改后的 AIC,对增加参数进行处罚
 
预测编程语言的未来流行程度

堆栈溢出数据用于此分析。数据集是从堆栈交换数据浏览器下载的。处理后的文件也可以在这里下载。它被大卫·罗宾逊用于一个数据营项目。
每个堆栈溢出问题都有一个标签,标记一个问题来描述它的主题或技术。该数据对每一对标签和年份都有一个观察值,显示了该标签在该年提出的问题数量以及该年提出的问题总数。例如,有 54 个问题是关于。在 2008 年的 58390 个问题中。

我们不使用一年中每个标记问题的数量,而是计算和使用该年中每个标记问题和所有问题的分数。现在进行比较更方便。

随着时间的推移,流行的编程语言发生了怎样的变化?
看看顶级编程语言的流行程度会很有趣。具体而言,包括以下编程语言:
- Java 语言(一种计算机语言,尤用于创建网站)
 - Java Script 语言
 - c#
 - c++
 - 大蟒
 - 服务器端编程语言(Professional Hypertext Preprocessor 的缩写)
 - 红宝石
 - r
 
用于此比较的每个标记问题(在一年的所有问题中)所占的比例。

我们可以看出,一些语言的受欢迎程度在上升,而另一些则在下降。特别是 javaScript、Java、c#、c++、ruby 正在衰落,而 python 和 R(用于分析的语言)正在崛起。虽然这是事实,但我们应该检查问题总数是否在显著增长。

很明显,自 2013 年以来,问题总数没有显著增长。因此,我们可以说,编程语言的趋势可能是显著的,尤其是从 2013 年开始。
预测编程语言的未来流行程度
预测编程语言未来的流行程度会很有趣。我将使用预测包来生成预测。特别是,我结合了主要预测方法的力量,&ARIMA指数*滑法。特别是对于每个时间序列(每种编程语言),使用 ARIMA* &指数*滑法创建 2 个独立的模型,并选择最佳模型进行预测。选择 MAPE(*均绝对百分误差)**对预测模型进行评估。
— ARIMA(自回归积分移动*均)是一种非常流行的时间序列建模技术。它描述了数据点之间的相关性,并考虑了值的差异。
—指数*滑法包括简单指数*滑法(较大的权重分配给最*的观测值,而不是遥远过去的观测值)、双指数*滑法或霍尔特线性趋势模型(也考虑序列的趋势)和三指数*滑法或 Host 的温特斯法(也考虑时间序列的趋势和季节性)

正如你在上面看到的,应用指数*滑法时,R & C++的预测比 ARIMA 更好。对于其余的编程语言,ARIMA 似乎是最好的方法。
下面是一个表格,其中使用了性能最佳的模型,对未来进行了预测

下面是一个对未来预测的图表

摘要
为了比较编程语言的受欢迎程度,我们使用了过去 10 年中每种语言所涉及的全部问题的分数(关于堆栈溢出)。到目前为止,栈溢出是计算机编程中最受欢迎的问题和答案*台。
当然,还有很多其他的指标可以用来衡量受欢迎程度。此外,像所有模型一样,预测模型并不完美,可能会比预测的偏差更大。但是,考虑到所有时间序列的 MAPE 相对较小(不到 9 %),这些预测应该是编程语言未来受欢迎程度的良好迹象。
总的来说,结果如下:
—分析编程语言 (Python & R) 将继续流行
— Java 将稍有增长,然后保持持续的流行
— JavaScript,C# & C++ 将失去显著的流行
— PHP & Ruby 可能会失去几乎所有的流行,并在未来 5 年内过时
最初发表于【https://www.manosantoniou.com】。
使用深度学习对澳大利亚证券交易所(ASX)的股票市场进行预测:使用技术指标和长短期记忆(LSTM)模型

最*,我开始着手建立一个预测模型的任务,该模型预测第二天在澳大利亚证券交易所 (ASX)的股票价格的变动。我写这篇文章是为了分享我发现一个更可靠的策略的旅程,这个策略基于一个长期短期记忆 (LSTM)模型,这个模型建立在大约 2.5 年的 ASX(T7)【EOD】金融市场数据的基础上。Jupyter 笔记本可以从我的资源库这里下载。
1。数据导出
第一项任务是将 EOD 数据转换成五个独立的时间序列数据帧;o 笔,h 高,l 低,c 输和量 (OHLCV)各一个。在每个数据框中,行按日期索引,列按股票代码索引。超过 883 天的观察有 2773 个跑马灯。
接下来,创建了三个额外的数据框架:退货、第二天退货和高/低(这些是在给我的任务中要求的)。这些指标是除 OHLCV 值之外的潜在特征。
2.探索性数据分析
2.1 假设、动机、方法和策略
截至 2019 年 11 月 22 日,根据 ASX 的网站,目前共有 2195 个独特的报价机上市。然而,数据集有 2773 个独特的跑马灯;这意味着它有已被摘牌公司的股票代码。
在分析覆盖率和质量之前,应该讨论这个任务的假设、范围、动机和策略。
假设:
- 根据研究[1-3],从特定股票(或公司)的 OHLCV 得出的技术指标模式对其未来走势具有预测能力。
 - 此外,对综合指数有贡献的公司的技术指标,如 ASX 通用指数、S&P/ASX 50 指数等。可以用来预测它们所属的综合指数的走势。
 
范围:这项工作将其范围限制在假设 1,并做了扩展。
动机:这项工作扩展了假设 1,使其更加通用:与[1–3]中的假设不同,任何股票价格的未来运动都可以通过技术指标的运动和模式来预测;而同样的从运动和形态的预测可以适用于任何公司的股价。换句话说,机器学习模型可以仅基于技术指标中的内在模式被训练成不可知的。
根据研究[1–4],数据的时间序列性质建议使用神经网络的 LSTM 范式,该范式已被证明优于集成方法,如随机森林和其他分类技术,如支持向量机。
策略:策略是利用过去 60 个(交易)日的 OHLCV 数据和技术指标,建立一个通用的预测模型,从而能够预测任何一家公司的股价走势。请注意,这不包括在 ASX 上市的所有综合指数(因为这属于假设 2)。
为此,将使用训练、验证和测试数据来训练 LSTM 模型,以预测以下指标:向上或向下第二天股票价格的运动。
2.2.覆盖面和质量
现在,让我们首先基于下面的直方图来可视化非缺失值的数量分布。

上面的直方图显示,在收盘价中大约有 196 个报价器没有缺失值。
所有缺失的值都来自当天没有登记的价格。经过与 ASX 官网数据的交叉核对,发现这主要是因为该交易并未在当天发生,公司在 2015-01-02 之后上市,或者公司在 2018-06-29 之前退市。
由于干净的结果是至关重要的,有很多缺失值的 tickers 将被忽略。在这种情况下,只考虑具有超过 800 个非缺失值的报价机。
其次,对于良好的可预测性,重要的是只考虑与标签具有良好相关性的公司,在这种情况下,这是未来的回报运动。此外,由于综合指数不在假设的范围内,它们被删除了——在与 ASX 的网站核对后,它们是没有交易量信息的报价机。

根据上面的直方图,可以观察到很少有与未来回报有相对较好相关性的报价机。为了获得良好的可预测性,只使用具有预测能力的报价机。因此,这里考虑*均相关值大于第 75 百分位的跑马灯;他们有 150 人。
现在,丢失的值被处理。在交易没有发生的当天,有几种方法可以处理缺失值:
- 将交易量设置为 0,将开盘、盘高、盘低和收盘值设置为前一天的收盘值,并假设当天该股票没有交易。这种方法可能会在体积中引入异常值,从而在数据中引入噪声。
 - 使用前一个和后一个可用值对数据 OHLCV 数据进行插值,以实现*滑过渡。另一种方法是将缺失值填入列的*均值和中值。另一方面,这引入了错误的信息。
 
这里,采用第一种方法,因为它在理论上更正确。
2.3.附加转换
在进行一些可视化和分析之前,先检查一些技术指标。文献中有许多这样的转换[1–3]。Borovkova 等人[1]的工作整合了一些关键技术指标,可用于其他转换。通常,它们可以分为四类:(1)动量;(2)趋势;(3)体积;以及(4)易变性。一些常用的指标是:
- 资金流动指数
 - 相对强度指数
 - 随机振荡器(%K)
 - 威廉%R
 - 指数移动*均线
 - 移动*均收敛-发散
 - 商品渠道指数
 - 市目指示器
 - 积累/分配指数
 - 布林线
 
所有的转换都是使用开源 Python 包完成的[5]。
2.4.数据分析
在执行一些数据分析之前,数据被分为训练集、验证集和测试集,如下所示:
- 火车:2015 年 2 月 1 日至 2017 年 6 月 30 日
 - 验证:2017 年 7 月 1 日至 2017 年 12 月 31 日
 - 测试时间:2018 年 1 月 1 日至 2018 年 6 月 29 日
 
首先,所有数据帧之间的相关性,或者换句话说,特征之间的相关性被可视化。因为在一个数据帧中有许多分笔成交点,所以很难可视化所有分笔成交点的相关矩阵。因此,在这里,取*均相关值,并使用热图可视化相关。

除了相关矩阵热图之外,还绘制了数据的直方图来寻找异常值。在此之前,每个跑马灯的数据都从 0 到 1 进行了规范化,以便可以对它们进行可视化和适当的基准测试。

从上述相关热图和直方图中观察到的情况可总结如下:
- 开盘价、最高价、最低价和收盘价彼此高度相关。这是意料之中的,因为这些值彼此非常接*。由于技术指标是使用这些值计算的,并且本质上保留了其信息,因此可以从特征列表中删除开盘价、盘高和盘低值。
 - 除了 h/l 和体积之外,上面的大多数分布要么是正态的,要么是均匀的。这表明这两个特征中会有大量的异常值。虽然具有正态分布的其他特征在尾部可能有异常值,但是它们可以被认为是可以忽略的。此外,观察相关矩阵,它们似乎与未来回报的相关性较低,这是我们将要预测的指标。因此,将 h/l 和 volume 从特性列表中删除是合理的。
 - 同样,根据关联矩阵热图,一些值似乎与未来回报没有太大关联。它们是资金流动指数和积累/分配指数。为了保持预测模型简单,这些特征也可以被认为是无用的。
 - 最后,随机振荡指标似乎与 William %R 高度相关。这是意料之中的,因为两个指标的数学表达式是相似的。在这里,威廉%R 将从功能列表中删除。
 
基于上面的讨论,最终的特征列表将是:收盘,回报,指数移动*均线,相对强度指数,随机振荡器,移动*均线收敛-发散,商品通道指数,Ichimoku 指标,上下布林线。
如前所述,策略是预测股票的涨跌。根据经验,与预测未来回报的(正或负)百分比变化相比,这是一个更好的策略,因为基于标签的业绩指标可能会产生误导。例如,建立了一个模型,使得均方误差最小化,这仍然不意味着运动的方向是正确的。如果实际移动是 0.1%,那么基于 0.5%预测的投资比-0.1%预测更好,尽管前者具有相对更高的误差值。
注册标签的另一个数据帧是用 1 和 0 创建的:1 表示向上,0 表示向下;并且绘制出值的分布。

根据上述分析,下降趋势似乎多于上升趋势。因此,在发送用于机器学习的数据之前,需要进行一些*衡。
3.预测
3.1.长短期记忆(LSTM)模型
预处理 :基于上一节的分析,本节建立 LSTM 神经网络模型,用于次日股价时刻的预测;不管是向上还是向下。
训练集和验证集将在 LSTM 网络训练中使用,而测试集将用于交易策略实施和最终模型的附加测试。
接下来,对数据进行预处理。使用 MinMaxScaler 将数据归一化为 0 到 1 之间的值。注意,最大值和最小值是针对每个列车数据帧中的每个跑马灯的。
然后,对数据进行缩放,使其具有*均值 0 和单位方差。这种缩放是通过使用整个标准化训练数据帧的数据来训练标准缩放器来完成的。这将用于转换训练集、验证集和测试集。
接下来,数据被排序。过去 60 天的数据按顺序用于所有训练、验证和测试数据集的第二天预测。
一旦测序完成,数据就*衡了。这是为了确保 LSTM 模型不偏向于下降趋势,正如之前在数据分析中观察到的那样。
构建和训练 LSTM 模型 :使用 64 个批次大小和 40 个历元的 LSTM 模型被编译(使用 Tensorflow 中的 Keras)。该模型的摘要如下:
Layer (type)                 Output Shape              Param #   
=================================================================
lstm_3 (LSTM)                (None, 60, 128)           72192     
_________________________________________________________________
dropout_4 (Dropout)          (None, 60, 128)           0         
_________________________________________________________________
batch_normalization_3 (Batch (None, 60, 128)           512       
_________________________________________________________________
lstm_4 (LSTM)                (None, 60, 128)           131584    
_________________________________________________________________
dropout_5 (Dropout)          (None, 60, 128)           0         
_________________________________________________________________
batch_normalization_4 (Batch (None, 60, 128)           512       
_________________________________________________________________
lstm_5 (LSTM)                (None, 128)               131584    
_________________________________________________________________
dropout_6 (Dropout)          (None, 128)               0         
_________________________________________________________________
batch_normalization_5 (Batch (None, 128)               512       
_________________________________________________________________
dense_2 (Dense)              (None, 32)                4128      
_________________________________________________________________
dropout_7 (Dropout)          (None, 32)                0         
_________________________________________________________________
dense_3 (Dense)              (None, 2)                 66        
=================================================================
Total params: 341,090
Trainable params: 340,322
Non-trainable params: 768
_________________________________________________________________
本质上,LSTM 模型将具有 3 个 LSTM 层和激活的密集层,最后是具有 softmax 激活函数的密集输出层,因为这是一个分类问题。softmax 激活函数将输出分类的概率。
为了避免过度拟合,增加了漏失层。作为额外的措施,如果认为有必要,也可以添加正则化,使得在训练期间优化的权重不会变得太大。然而,在这种情况下,它们是不必要的。
称为 Adam 的自适应一阶基于梯度的优化用于优化模型。另一个著名的优化器是被称为 SGD 的随机梯度下降。由于这是一个分类问题,使用稀疏分类交叉熵和损失函数计算的准确度被用作性能度量。
上面指定的所有指标都是该模型的超参数。可以使用批次大小、时期、单位值和优化方法的网格进行超参数搜索,但是由于硬件限制,仅使用这些初始超参数。
分析模型性能 :优化后的损失函数历史如下图所示。从该图中,我们可以看到来自训练和验证数据的损失函数被最小化,并且它们彼此非常接*。这表明模型没有过度拟合或拟合不足。然而,可以做出的一个改进是调整学习速率,使得跳跃更小。

下面的准确度图还显示了基于训练集和验证集的 LSTM 模型的改进。

还生成了基于测试数据集的精度,以及基于模型在训练期间从未见过的 2018 年数据的分类报告,如下所示。
Test loss: 0.6752472768227259
Test accuracy: 0.5605208333333334
Classification report:
             precision    recall  f1-score   support
        0.0       0.72      0.50      0.59      6038
        1.0       0.44      0.66      0.53      3562
avg / total       0.61      0.56      0.57      9600
基于测试集的准确度分数显示,结果与研究[4]一致,其中测试集的准确度低于训练和验证集的准确度。与下降趋势相比,上升趋势的预测精度较低,这意味着在预测上升趋势时会有更多的假阳性。通常,召回分数与精确度成反比。因此,最好的衡量标准是 f1 分数,这对于制定交易策略来说是可以接受的。
交易策略 :这里定义了一个简单的交易策略。在使用的所有 150 个报价机中,基于 LSTM 网络的预测运动,使用每个报价机 1 澳元建立头寸,并在第二天*仓。这意味着每天投资 150 澳元,第二天*仓。
请注意,由于 LSTM 网络需要过去 60 天的数据,因此交易是从 2018 年 3 月 27 日模拟的。将绘制累计损益 (PnL)图。

按照简单的策略,基于 64 天的交易和每天 150 澳元的投资,总利润约为 25 澳元。*均而言,这是 0.26%的每日投资回报率(ROI)。下图显示了基于 64 天回溯测试数据的 ROI 值分布。基于直方图,80%的信心,LSTM 模型将提供一个积极的每日投资回报率。

考虑到累积 PnL 的置信区间和线性趋势,这可以认为是一个 成功的策略 。
结论
澳大利亚证券交易所 (ASX)的所有公司的历史数据被给出,用于预测证券第二天的运动,并随后通过仅使用 2773 只股票的 883 天的当天结束信息来提出交易策略。
首先对数据进行提取、分析、清理和特征设计。随后,为具有良好可预测性的证券建立了一个长短期记忆 (LSTM)网络模型。
结果表明,LSTM 模型为 150 家澳大利亚公司股票价格的成功交易策略提供了合理的准确度,具有良好的预测性。此外,结果显示,在 80%的置信度下,基于测试数据,LSTM 模型提供了正的每日投资回报。
未来的改进
基于这种尝试,可以进行一些改进来进一步提高预测或交易性能。它们是:
- 更精细的分类。货币运动的标签可以分为三类。例如,在当前版本中,未来回报率为 0.00 的股票被归类为 0,这是一种向下的变动。也许它们可以被分为-1,0 和 1,并根据这些类别建立交易策略。
 - 尝试解决假设 2 。第二个假设是综合指数依赖于它的成分证券。因此,这些证券可以用来预测综合指数的走势。
 - 使用 LSTM 模型的概率。来自 LSTM 模型的 softmax 激活函数实际上输出了类别的概率。需要进一步调查以将可能性纳入交易策略。
 - 使用卷积神经网络。研究[6–7]和[4]分别表明,使用 CNN 和 CNN-LSTM 混合方法可以提高预测精度。这可能是一个有趣的改进。
 - 超参数搜索。随着计算能力的提高,可以部署超参数搜索来找到 LSTM 和模型的最佳参数。
 - 新闻数据。其他类型的数据,如与证券相关的新闻,可以作为特征之一添加,如研究所示[2,8]。例如,[2]表明添加新闻信息(例如,情感)可以将预测准确度提高 10% (58%到70%)。
 
参考
[1] Borovkova S,Tsiamas I .一个用于高频股票市场分类的 LSTM 神经网络集成。预测杂志。2019;1–20.https://doi.org/10.1002/for.2585
[2]翟 Y,许 A,哈尔格木格 SK .在每日股价趋势预测中结合新闻和技术指标。计算机科学讲义。2007;https://link . springer . com/chapter/10.1007/978-3-540-72395-0 _ 132
[3]赫加齐 O,索利曼 OS,萨拉姆 MA。股票市场预测的机器学习模型。国际计算机科学与电信杂志。2013;17–23.https://www.ijcst.org/Volume4/Issue12/p4_4_12.pdf
[4]巴尔加斯先生、多斯安茹斯·CEM、比沙拉·GLG、埃夫苏科夫股份公司。使用技术指标和金融新闻文章进行股市预测的深度学习。2018;https://doi.org/10.1109/IJCNN.2018.8489208
[5]帕迪亚尔·DL。Python 中的技术分析库。2019;https://github.com/bukosabino/ta
[6]塞尔温 S,维纳雅库马尔 R,戈帕拉克里什南 E.A,梅农 VK,索曼 K.P .利用 LSTM,RNN 和 CNN 的股票价格预测-滑动窗口模型。2017 年国际计算、通信和信息学进展会议(ICACCI)。2017;https://doi.org/10.1109/ICACCI.2017.8126078
[7]陈,何.利用卷积神经网络进行股票预测.IOP 会议系列:材料科学与工程。2018;https://doi.org/10.1088/1757-899X/435/1/012026
[8]翁 B,陆 L,王 X,Megahed FM,Martinez W .使用集合方法和在线数据源预测短期股票价格。专家系统及其应用。2018;https://doi.org/10.1016/j.eswa.2018.06.016
使用随机森林预测亚马逊雨林的野火数量

之前,我们分析了巴西野火数据集。我们查看了数据集的特征,例如每个州野火的*均数量、每个州野火数量的标准偏差以及所有州野火数量的分布。我们还观察了每个州在特定月份的野火数量与全年的对比。
在这篇文章中,我们将建立一个机器学习模型,我们将使用它来预测任何给定年份一个州的野火数量。
构建我们的机器学习模型的工作流程如下:
- 数据准备和清理
 - 功能选择和工程
 - 型号选择
 - 模型调整和测试
 
幸运的是,巴西数据集是结构化的,经过清理和标记的,因此我们基本上完成了第一步(在许多情况下,您将不得不处理非结构化和未标记的数据,这印证了一句谚语“数据科学家花费 80%的时间来寻找、清理和结构化数据”)。
现在让我们建立这个模型!
我们需要做的第一件事是导入必要的 python 包:
import numpy as np
import pandas as pd
from sklearn.metrics import mean_absolute_error
from sklearn.ensemble import RandomForestRegressor
接下来我们可以写一个函数来初始化我们的数据。您可以自由选择如何预处理数据。对于这个例子,我们将保持简单,说我们根据感兴趣的特定状态初始化数据。我们还设计了一个月类别功能,我们将在我们的模型中包括:
def initialize_data(state):
    df = pd.read_csv("amazon.csv",  encoding = "ISO-8859-1")
    df['month_cat'] = df['month'].astype('category')
    df['month_cat'] = df['month_cat'].cat.codes    
    df = df[df['state'] == state]
    return df
接下来,我们定义一个函数,该函数允许我们分割数据用于训练和测试:
def train_test_split(year, df):    
    df_train = df[df['year'] < year]
    df_test = df[df['year'] == year]
    X_train  = np.array(df_train[['year', 'month_cat']])
    y_train  = np.array(df_train['number'])
    X_test  = np.array(df_test[['year', 'month_cat']])
    y_test  = np.array(df_test['number'])    
    return X_train, X_test, y_train, y_test
函数“train_test_split”使用“year”来拆分模型训练和测试的数据。例如,如果“year”= 2015,则训练集被定义为 2015 年之前的所有 wildfire 数据,测试集被定义为 2015 年期间的所有 wildfire 数据。接下来,我们定义特征和目标变量,其中特征是年份和月份类别,输出是野火的数量。
我们现在定义一个函数,它指定随机森林算法的模型参数。该函数可用于在测试过程中优化模型参数,从而将误差降至最低。我们通过改变 N_ESTIMATORS 和 MAX_DEPTH 值来做到这一点,直到我们最小化误差度量。这个过程称为超参数调整:
def model_tuning(N_ESTIMATORS, MAX_DEPTH):
    model = RandomForestRegressor(n_estimators = N_ESTIMATORS, max_depth = MAX_DEPTH, random_state = 42)
    return model
我们接下来要做的是定义一个函数,使模型符合训练数据,并预测野火的数量:
def predict_fire(model, X_train, X_test, y_train, y_test):
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test).astype(int)
    mae = mean_absolute_error(y_pred, y_test)
    print("Mean Absolute Error: ", mae)   
    df_results = pd.DataFrame({'Predicted': y_pred, 'Actual': y_test})
    print(df_results.head())
最后,我们定义一个“主”函数,用不同的输入值来测试模型。下面,我们对“初始化数据”、“模型调整”和“预测火灾”函数进行了两次调用。我们对 2017 年的“Sergipe”和“Distrito Federal”州进行预测,并计算*均绝对误差(MAE):
def main():
    df = initialize_data('Sergipe')
    X_train, X_test, y_train, y_test = train_test_split(2017, df)
    model = model_tuning(50, 50)
    predict_fire(model, X_train, X_test, y_train, y_test)
    df = initialize_data('Distrito Federal')
    X_train, X_test, y_train, y_test = train_test_split(2017, df)
    model = model_tuning(50, 50)
    predict_fire(model, X_train, X_test, y_train, y_test)if __name__ == "__main__":     
    main()
输出是:

我们还可以分析模型在所有状态下的性能,如下所示:
def main():
    df = pd.read_csv("amazon.csv",  encoding = "ISO-8859-1")
    for i in list(set(df['state'].values)):   
        df = initialize_data(i)
        X_train, X_test, y_train, y_test = train_test_split(2017, df)
        model = model_tuning(50, 50)
        predict_fire(model, X_train, X_test, y_train, y_test)  
        print(i)if __name__ == "__main__":     
    main()
这将输出每个状态的预测值、实际值、状态名称和 MAE 值。可以通过超参数调整、尝试其他基于树的方法(XGBoost、lightgbm、catboost)和尝试神经网络时间序列模型( LSTM 、 RNN 、 CNN 、 WaveNet CNN )来改进模型。我鼓励你尝试一下这个模型,看看随机森林的 MAE 有多低。然后尝试应用我建议的一些其他方法,看看你是否在准确性上有所提高。所有的代码都可以在 GitHub 上找到。祝好运,机器学习快乐!
用数据预测奥斯卡奖
只有女强人的电影表现更差,获得奥斯卡最佳影片四项提名的可能性更大。
我和我的搭档都是奥斯卡的超级粉丝,我们也喜欢涉足数据可视化——去年我们在使用慈善数据的比赛中获得了三等奖。所以今晚的奥斯卡颁奖典礼,是时候把我们的注意力转向电影界的奥林匹克了。
就像其他人一样,我们想回答的问题是哪部最佳影片提名最有可能获奖,以及是否有某种预测它的公式。

神奇的四项提名
我们查看了过去 90 年的最佳影片获奖者,并分析了他们在那一年获得的其他奥斯卡奖项的提名数量(提名,而不是必要的奖项)。我们仔细分析了这些数字,得出了如下数据。
93%的最佳影片得主还获得了最佳导演提名
在我们的数据中,11 个奥斯卡图像的行用金色填充不同的百分比,即。这些显示了最佳影片获奖最多的提名类别的顺序。例如,93%的最佳影片获奖者也获得了最佳导演提名,而只有 14%的最佳影片获奖者获得了最佳视觉效果提名——这就解释了为什么我们没有看到许多夏季大片获奖。
左边圆点多的人更有可能获胜
下半部分的点,将今年的八部最佳影片与上面的奥斯卡奖项相对照。数据告诉我们,左边圆点多的人赢的可能性大得多。那些集导演、编剧、表演和剪辑于一身的人最有机会。
没有一部电影在没有这四项提名中的至少一项的情况下获奖
BlackKklansman 有五个点在一排,但最受欢迎的和副也有'神奇的四'。《罗马》只有四部中的三部(这是一部不需要大量剪辑的电影)。没有一部电影在没有这四项提名中的至少一项的情况下获奖——这对黑豹来说是个坏消息。
只有女演员提名的电影明显不太可能获奖
虽然获得表演提名是“四大奇迹”(包括男演员或女演员、配角或主角)之一,但当性别发挥作用时,情况就不同了。

只有 8%的电影获得了最佳女演员提名
48%的电影获得最佳影片提名,包括男演员和女演员两个类别,这反映了强大的全面演员阵容。但只有 8%的电影获得了最佳影片,只有女演员提名(相比之下,只有男演员提名的电影有 32%)。令人惊讶的是,没有男演员或女演员提名的最佳影片获奖者(12%)比只有女演员提名的更多。这告诉我们关于社会的什么,我将留给你来决定。
今晚,无论是《罗马的墨西哥女仆》还是《最受欢迎的英国女王》,都只有女演员提名,没有男演员提名。他们有机会成为继 1997 年的《泰坦尼克号》和 1965 年的《音乐之声》之后,第八部获得最佳女演员提名的电影。
我们如何创建我们的数据,即
我们从 datahub 和 Kaggle 下载了数据。然后,我们使用 React 对这些数据进行编码,以快速找到以前获奖图片的提名。有了这个,我们就可以计算出百分比,通过将其他最佳影片提名的数量除以该奖项类别一直有效的年份来相应地对它们进行加权。然后,我们使用矢量图形编辑器 Sketch 来设计数据,即
最佳影片获奖的可能性也可以通过许多其他方式来“预测”,例如在奥斯卡奖之前评论界的好评和颁奖典礼上的成功。但我们承认,我们也喜欢在晚上打开信封时受到巨大的冲击。
奥利弗·卡林顿
预测深度学习模型的性能
幂律标度解释了模型的性能如何随着我们输入更多的数据而改变
众所周知,深度学习最*的成功在很大程度上依赖于大量数据的可用性。视觉是第一个实现数字图书馆承诺的领域,这可能是因为大型数据集的可用性,如 ImageNet 。最* RL 的模拟器的激增进一步说明,随着我们进一步将这些技术应用于现实世界的问题,数据稀缺很快成为瓶颈。
但是多少数据才够呢?
在商业环境中,这个问题经常出现。当时间和金钱岌岌可危时,能够对模型架构的改进如何与简单地收集更多数据相权衡做出一些具体的陈述将是有用的。我们应该付钱给一个工程师团队 6 个月来完善我们的模型,还是应该付钱给一个众包助手团队 6 个月来整理我们需要的数据?
我们无法轻松回答这个问题的事实反映了深度学习作为一个领域的不成熟,这一缺点导致阿里·拉希米在他的 2018 年 NIPS talk 中宣布‘机器学习已经成为炼金术’(他至少在某种意义上是错的;炼金术从未让任何人赚到钱,而深度学习却让一些人变得非常富有。Yann LeCunn 广为宣传的《脸书邮报》的回应发出了挑战:“如果你不满意我们对你日常使用的方法的理解,那就改正它”。
Ali Rahimi putting the cat amongst the pigeons by suggesting that deep learning is ‘alchemy’
来自百度的一篇名为“深度学习规模是可预测的,从经验上来看”的论文在一定程度上回答了这一挑战。如题所示,他们对这个问题的答案是经验的,而不是理论的。这篇论文附有一篇精彩的博文,我想让你参考这篇博文,以获得关于这些发现的更详细的讨论,我将在这里总结一下。
在我们深入研究之前,有一个小小的题外话:对标度律的研究已经让生物学家着迷了很长时间。这张图来自 Max Kleiber 于 1947 年绘制的图,显示了动物的新陈代谢率(每天产生的热量)与该动物的体重成对数比例关系(更多细节见下文)。

事实上,它似乎可以扩展为

这就是为什么红线比标有表面的线更陡的原因

但是比标有重量的要浅。有趣的是,没有人真正知道为什么这个定律成立,尽管它看起来非常强大。
回到百度和人工智能的世界,70 年后我们正在制作类似的情节:

从本质上来说,论文记录了数据的增加导致测试集损失的减少,具有相同的幂律关系,当在双对数标度上绘制时,最终为一条直线。有趣的是,这种关系的指数——线性标度上直线的斜率——对于你手头的任何一个架构来说都差不多。因此数据集本身定义了这个指数:模型仅仅改变了截距。为了强调这一点:在给定数据集的情况下,添加更多数据的效果对于任何模型本质上都是一样的。这太不寻常了。
他们没有为这篇论文提供任何代码,所以我在 PyTorch 中拼凑了一些实验来探索他们的结论。
代码
你可以在这里下载完整的 Jupyter 笔记本或者继续阅读一些要点。
我在 PyTorch 教程中提供的代码基础上构建了一个简单的 CNN 来测试 CIFAR 数据集(一个包含 10 个类的小型图像分类任务)。我用超参数字典配置它,因为最佳超参数对数据集大小非常敏感——正如我们将看到的,这对复制百度结果非常重要。
我将训练数据分为训练集和验证集,并按照论文中的建议对训练集进行子采样。
然后,我训练了 9 个模型,每个数据集大小一个,停止条件是通过连续 3 个时期增加验证误差来定义的(原始论文在验证的细节上有点模糊)。然后,我根据测试集对它们进行了评估。
如您所料,测试集的准确性随着训练集大小的增加而增加。此外,它看起来有点像权力法则。

损耗以类似的方式减少。

然而,无论是准确度还是损失的对数图看起来都不如百度论文中的那张可爱。实际上,它们各自都表现出某种模糊的对数形式,暗示着我们之间存在着次幂律关系。
原因很明显:我没有像他们那样在每个训练集上进行详尽的超参数搜索。因此,我们没有找到每个数据集大小的最佳模型。最有可能的是,我们的模型缺乏完全捕捉更大数据集的能力,因此我们没有充分利用数据。
添加超参数调谐
你会记得,在模型定义中,我们使用一个超参数字典来设置层的大小,这样就可以很容易地通过超参数调整来改变网络的形状。因此,对我们来说,实现一些随机搜索相对简单:
我们现在可以针对每个数据集大小重复训练循环,随机采样参数:
并使用它为每个数据集大小训练一组网络,保留在验证集上表现最好的网络。我是在没有 GPU 的 MacBook 上执行这一调优的,所以我限制自己对每个数据集大小进行 10 次搜索,希望我可以证明这一点,而无需请求 AWS 实例。
然后,我们可以再次寻找我们的幂律,果然,它们看起来更整洁了:


没有克莱伯的好,但也不错。
结论
原始论文在各种任务中测试了各种模型——这里执行的最接*的一个是带有 ResNets 的 ImageNet。令人高兴的是,这些结果很容易在不同的网络、不同的数据集上复制。
在他们的讨论中,作者指出:
我们还没有找到影响幂律指数的因素。随着数据集规模的增加,为了打破幂定律,模型需要用越来越少的数据学习更多的概念。
这正是你在人类身上看到的那种伸缩;你知道的越多,就越容易获得新知识。
我之前写过关于量化超智能进程的困难。似乎超越幂律指数的模型的出现——随着它们的学习,使的数据效率更高——可能是这条道路上一个重要的经验主义里程碑。
原载于 2019 年 4 月 14 日deberker.com。
预测 Instagram 帖子的受欢迎程度
使用混合输入神经网络实现对 Instagram 受欢迎程度的巨大预测。

在本文中,我们将讨论我们试图预测 Instagram 帖子受欢迎程度的方法和结果。首先,我们将描述我们的数据收集方法以及数据本身。然后,我们将描述我们用于图像和自然语言处理的技术。在这一步之后,我们使用一个 XGBoost 回归模型来获得一个基准均方根误差分数,我们将努力提高这个分数。最后一步,将使用混合输入神经网络,接受分类/数字数据和图像数据。
本文讨论的主题的所有代码都可以在这里找到:https://github.com/GuiZamorano/Instagram_Like_Predictor
动机
在现代,趋势和流行很大程度上是由社交媒体驱动的。如今 Instagram 上有超过 10 亿用户。这是一个大规模的市场,有潜力进行优化,以增加知名度,收视率,甚至收入。我们希望通过创建一个项目来利用这个市场,该项目可以确定关键变量,以增加一个帖子的点赞数与用户在一个帖子上获得的*均点赞数的比率。使用这些功能,我们希望能够对这一比率进行估计,以便优化帖子,为高知名度影响者和日常用户收集最多的曝光率。
收集数据
收集 Instagram 用户名:
为了预测 Instagram 帖子的受欢迎程度,我们首先需要大量数据来训练我们的模型。我们的第一项工作是收集 Instagram 用户名,我们可以使用这些用户名来收集帖子数据。幸运的是,我们找到了一个网站,上面列出了 Instagram 影响者的前 1000 名(不一定是拥有最多粉丝的人)。网站可以在这里找到:https://hypeauditor.com/en/top-instagram/.
使用 urllib 和 BeautifulSoup Python 包,我们浏览了该网站的页面,收集了 1000 个 Instagram 用户名。然而,我们仍然需要更多的数据,所以通过查看涉及 Instagram 用户的其他项目,我们能够将我们的列表增加到总共 1897 个用户名。所有这些用户都有各种各样的人气和追随者。
刮 Instagram 帖子:
现在我们已经有了一个很长的用户名列表,我们的下一个挑战是从他们的帖子中收集数据。我们的第一个想法是使用脸书的 Instagram Graph API。通过向这个 API 发出请求,您可以从一个概要文件和一篇文章中收集大部分信息。不幸的是,Instagram 的 Graph API 限制一年比一年严格。目前的限制是每小时 200 个请求。这种限制使得利用 Instagram Graph API 变得非常困难和乏味。因此,通过研究,我们创造了自己的铲运机,其工作原理如下:
- 向https://www.instagram.com/+{用户名}发出 URL 请求。
 - 通过将响应转换成 JSON 对象,从响应中提取 Javascript 元数据。
 - 使用 urllib 下载用户的个人资料图像和每个帖子图像。
 
使用这个直接调用用户 Instagram 页面的 scraper,可以为您提供每个用户的 12 个最新帖子。我们试图使用 Selenium 来加载整个页面,但是这样做只是将可视信息附加到页面的 HTML 中,而不是我们需要的元数据。因此,我们决定坚持每个用户(最多)发 12 篇帖子,并从我们的数据集中删除了最*的帖子,因为我们认为这可能是一个不准确的流行度显示,因为它是最*的。现在我们有了 1897 个 JSON 对象和一个包含所有图片的文件夹,我们准备构建一个数据集。

Figure 1: JSON of user profile data

Figure 2: Last key-value pair of JSON is array of posts
数据探索与可视化
在搜集现成可用的特性后,我们的第一个目标是看看我们是否能找到它们之间的任何关系。这包括寻找预期或假设以及意外的关系。除了原始刮刀数据之外,这种探索还包括我们自己生成的一些基本特征,稍后将更详细地讨论。我们首先探索了每个功能与我们最终试图预测的功能的相关性:帖子的点赞数除以帖子帐户的*均点赞数(number_of_likes_over_mean)。我们专注于与 number_of_likes_over_mean 最相关(或反向相关)的特征,以便进一步研究。下面描述了这些特征之间的相互关系。

Figure 3: Top features correlated with number_of_likes_over_mean
出于可解释的原因,一些特性与其他特性有相当大的相关性,例如 hr_of_day 或 hour buckets(例如(16,20),这意味着下午 4 点到 8 点)和 hr_sin,因为它们都处理小时间隔。下面列出了最重要的相关性,尽管相关性非常小。

Figure 4: Some of the most significant feature correlations
我们发现的一些关系是,在较晚清醒时间的帖子比深夜或清晨的帖子做得好一点。如图 5 所示,周中(周二、周三、周四)的帖子比一般的帖子稍差,我们发现视频帖子和带有禁用评论的帖子也是如此。

Figure 5: Each day, one-hot-encoded vs. number_of_likes_over_mean
我们还将我们的点赞数除以用户的*均点赞数可视化为分布图和散点图。散点图具有大约 1.6 的偏斜度和大约 6 的峰度。它有一个比正态曲线更大的倾向于分布右侧的尾部。

Figure 6: Distribution of likes divided by mean

Figure 6: Scatter plot of likes divided by mean
特征生成
在熟悉了我们的数据集之后,我们决定生成一些我们认为在预测给定帖子的表现时有用的特征。这些特征包括从帖子图像本身提取的特征,以更有用的方式描述原始文本数据(如标题)的 NLP 特征,以及可能有助于帖子成功的更一般的特征,如一天中的时间和一周中的日期。生成这些特征后,我们希望在开始训练最终模型时利用它们,并通过比较具有和不具有这些特征的基本回归模型的性能来确定它们的重要性。
一般特征:
从 Instagram 抓取数据后,我们有了大量的元数据,包括帐户关注者和关注,企业/类别信息,以及时间和日期信息。虽然有些元数据与账户相关,而不仅仅是帖子,但我们认为包含它将有助于为帖子提供上下文信息,并帮助我们获得更多特定于帖子本身的功能。
因此,除了从 Instagram 收集数据,我们还执行了一些基本的特征工程,以在进行更复杂的特征生成之前扩充数据集。我们认为用下面的一些内容来补充搜集到的数据可能是有用的。衡量一个账户的“活跃程度”可能代表一篇帖子的受欢迎程度,因此我们计算了两次帖子之间的时间,并将其作为一个特征添加到数据集。此外,我们计算了时间正弦和余弦特征,以编码时间的循环性质(即 11:55pm 应该接* 12:05am,但 23 小时离 00 小时非常远)。我们还将帖子分成时间段,例如从午夜到凌晨 4 点,凌晨 4 点到 8 点,等等,因为我们认为特定的每日时间段(不仅仅是时间)将有助于帖子的受欢迎程度。最后,因为在不了解用户的情况下很难衡量一篇帖子的点赞数,所以我们计算了相关账户的*均评论数和*均点赞数,为预测一篇帖子的相对受欢迎程度做准备。接下来,我们来看看更复杂的特征,比如图像和文本中的特征。
图像特征:
我们有很多关于图像以及如何对待它们的想法。我们最初的想法是,有人类主题的帖子比没有人类主题的帖子表现得更好。此外,我们假设有许多人在其中的图像,如团体照片,不会像只有一个清晰主题的图像那样获得很多喜欢。我们还想测试图片中的微笑是否会影响帖子的赞数。因此,我们决定创建一个模型来确定给定图像中的脸的数量和微笑的数量。该模型将应用于我们的数据集以生成这些特征。
经过一些初步的研究,我们决定利用 OpenCV 现有的面部识别分类器来完成这项任务。使用我们下载的图像,我们能够从 OpenCV 的文档中找到的 XML 文件中加载预先存在的面部和微笑检测器,这些文件是我们用来生成的。包含要添加到现有数据集中的新生成要素的 csv 文件。
自然语言处理功能:
数据集中有许多利用文本的不同要素,包括传记、标签、位置和标题。出于我们项目的目的,我们选择关注标题,因为我们正在分析独立的帖子,并希望尽可能多地使用关于帖子的信息,而不是海报。
NLP 的第一步是清理数据集。我们专注于单词本身,因此必须删除数字、标点符号、表情符号和空值。因为我们的数据集包括来自世界各地的热门 Instagram 用户,我们面临着处理的挑战,因为有太多不同的语言。我们决定使用谷歌翻译功能调用,以便将所有的文本翻译成英语,因为为了处理这似乎是最好的。将字幕翻译成英语后,我们删除了停用词,以消除诸如“the”或“is”之类的词,从而给其他词更多的权重。
在我们清理数据集之后,第一次分析是在文本情感上进行的。使用 TextBlob API,我们传递每个标题并接收一个情感分数。高达+1 的正分数表示正面单词,高达-1 的负分数表示负面单词。除了这个数字特征,我们把原始语言变成了一个分类变量,以观察不同的语言在喜欢率上是否有不同的波动。
我们尝试的另一种 NLP 方法利用了词袋。在这种方法中,我们创建了一个给定标题中所有单词的计数向量,并在所有标题中找到了 100 个最常用的单词。这些单词然后被转换成二元特征,1 表示它在字幕中,0 表示它不在字幕中。这种方法在很大程度上依赖于标题完全是英文的,因为拥有多种语言会产生不同的热门词,这些词在所有标题中并不常见。
现在我们已经生成了所有的特性,我们准备开始制作一个初始模型。
回归分析
我们建立模型的第一步是尝试各种回归模型,包括喜欢和评论的数量。显然,这些信息是我们试图预测的,但看看回归模型对这些数据的处理效果会给我们一个基准分数。我们最好的模型是 XGBoost 和梯度推进,所以我们决定坚持使用这些回归模型。他们获得了大约 0.032–0.034 的测试均方误差,即大约 0.18 的均方根误差。

Figure 7: Mean squared error scores for models already including the information we are attempting to predict
这给了我们一个目标,那就是获得比 0.18 均方根测试误差更好的分数。
现在,我们删除了图片发布前不可用的功能,如赞数和评论数,以继续测试我们的实际预测模型。均方误差急剧上升到大约 0.26–0.27,这是大约 0.52 的均方根误差。

Figure 8: Mean squared error scores for true model
我们的下一步是看看哪些生成的特性在 XGBoost 上工作得最好。我们决定在模型上尝试的生成特征是脸的数量、微笑的数量和自然语言特征。XGBoost 在添加了面数特征的原始特征下表现最佳。均方根误差为 0.51。
通过这种回归分析,我们能够确定使用具有多个面的原始特征通过 XGBoost 和梯度增强产生最佳预测。然而,即使在校准了我们的 XGBoost 回归器之后,这些新特性还是略微改进了模型。因此,我们的最后一步是用神经网络测试新功能。

Figure 9: Mean squared error scores after adding image and natural language features.
神经网络
因为 XGBoost 的表现远不如我们的目标 RMSE 分数 0.18 左右,所以我们决定尝试使用神经网络来解决我们的问题。这将允许我们直接使用我们最初下载的个人资料和帖子图片,并确定它们是否能在帖子的受欢迎程度中发挥作用。有趣的是,我们发现大多数神经网络都是用于分类问题,而不是回归。尽管如此,我们决定继续使用神经网络进行回归,即预测连续值。
我们的第一步是在神经网络中只使用分类数据和数值数据,看看它与 XGBoost 结果相比如何。接下来,我们在图像上使用卷积神经网络,包括侧面图像和背面图像。最后,我们将两者结合成一个双分支神经网络。所有的训练都是使用支持免费 GPU 的 Google Colab 完成的。
1。多层感知器(MLP):
多层感知器是一种深度的人工神经网络,由输入层、输出层和至少一个执行计算的隐藏层组成。与线性回归相比,隐藏层和激活函数为我们提供了一个更强大的模型。我们做的第一件事是使用 scikit-learn 的 MinMaxScaler 将我们的特征缩放到范围[0,1]。我们还将产出目标调整为[0,1],以缩小我们的产出预测范围。这大大改善了神经网络的结果。这是因为神经网络通过添加乘以学习速率的梯度向量来学习,并且如果特征的分布范围都不同,则该学习速率可能过度补偿(或补偿不足)其校正。我们使用的简单 MLP 架构如下所示,并为最终的密集层使用了线性激活函数。

Figure 10: MLP architecture
结果:这种 MLP 架构比以前的任何方法都要好得多!RMSE 比 XGBoost 低得多,我们能够达到并远远超过我们的基准分数 0.18。使用 Adam 优化器训练 30 个时期后的结果如下所述。
*均绝对百分比差异:55.40%
均方根误差:0.0807

Figure 11: Line of best fit by MLP model
2.卷积神经网络(CNN):
处理图像:
现在使用 CNN 让我们有能力把所有这些千兆字节的下载图像好好利用起来。然而,这确实带来了一些问题。
图像大小:下载的图像在大小上没有标准化,大多数对于理想的计算时间来说太大了。通过分析我们的图像形状,似乎大多数都在 960 像素 x 1200px 像素左右。理想情况下,我们会调整图像的大小以保持它们的纵横比,但这样它们的大小就会不同。我们的解决方案是将图像尺寸调整为 100 像素 x 128px 像素。这似乎比正方形图像更好地保持了图像特征,因为大多数图像都包含人脸或身体。此外,它不需要 CNN 学习不必要的信息,就像填充的情况一样。
两幅图像:我们处理的下一个问题是决定如何在 CNN 中处理我们的图像。每个数据条目由两张图片组成,一张个人资料图片和一张帖子图片。我们考虑了处理这个问题的两种选择。
- 使用两个 CNN,一个用于帖子图片,一个用于个人资料图片,并使用帖子的受欢迎程度作为每个图片的标签
 - 创建一个并排的个人资料图像和文章图像的新图像。
 
第一个选择似乎是个糟糕的选择。首先,我们将有一个帖子图像和一个个人资料图像,它们共享同一个标签。第二,我们将有一个不同的标签为每一个单一的个人资料图片,因为受欢迎程度只有不同的职位。因此,这种选择可能会让 CNN 更难通过图片了解受欢迎程度。
出于许多原因,选项二似乎是理想的。人气的一大指标是发帖的人。想象一下在一家高级餐厅里的一盘食物的完全相同的图像。一个是我贴的,一个是金·卡戴珊贴的。你觉得哪个会得到更多的喜欢?因此,并排组合个人资料图像和帖子图像可以是帖子受欢迎程度的重要指标。此外,这允许 CNN 同时从个人资料和发布图像中学习特征。

Figure 12: Final image example input into CNN
CNN 架构:
构建 CNN 架构来自经验和数小时的修改。考虑到您试图解决的问题,没有黑盒方法可以为您的数据获得最佳架构。因此,我们花了很长时间测试不同的架构,包括不同数量的卷积层、最大池层和全连接层。我们还试验了批量标准化和退出。最后,我们决定了回归问题的最佳架构,如下所示。

Figure 13: CNN architecture
该架构是一个深度网络,由四个卷积层、四个最大池层和五个全连接层组成。使用这个架构,我们尝试了两种预测流行度的方法。
梯度增强 CNN :
最初,我们试图在输出之前获取 CNN 的最终特征层,并使用这些特征来训练我们的 XGBoost 模型。我们推断,由于这将包括图像特征以及我们的分类和数字数据,这将显著改善我们的结果。我们在“4”节点层和“25”节点层都尝试了这种方法,但没有发现任何明显的改进。RMSE 仍然在 0.52 左右,比我们在 MLP 的结果差得多。
影像回归:
回想一下,CNN 主要用于分类。为了使用 CNN 进行回归,只需用单个节点(具有线性激活函数)替换完全连接的 softmax 层。此外,确保您的误差度量是针对连续值的。例如,我们使用均方根误差。我们这样做了,并传递了并排的图像,以获得每个帖子的预测流行度值。结果优于 XGBoost,但次于 MLP。结果总结如下。正如你可以告诉线的最佳拟合恶化了很多相比,MLP。
*均绝对百分比差异:66.78%
均方根误差:0.0850

Figure 14: CNN results
3。二分支神经网络:混合数据:
我们最终的想法是将这两个神经网络结合在一起。这是一个混合数据的机器学习问题,我们的模型必须能够使用我们所有的数据(图像、分类、数字)来进行预测。混合数据仍然是机器学习研究的一个非常开放的领域,所以我们非常渴望尝试一下。我们一直将 Keras 用于我们的神经网络,Keras 模型可以处理多种输入。我们已经有了上面显示的两个模型,所以下一步是将它们组合成一个双分支神经网络。每个分支机构将接受每种类型数据的培训。在此之后,分支将被连接起来以进行最终预测。

Figure 15: How to combine mixed inputs
为了创建一个多输入神经网络,我们首先需要创建两个分支。每个分支将是我们在前两部分描述的神经网络:MLP 和 CNN。但是有一个变化,因为这两个模型将被连接,我们删除了每个模型的最终输出层。我们希望实际的回归最终由多分支神经网络计算,而不是由单个分支计算。最终的架构如下所示:

Figure 16: Mixed Input NN architecture
如您所见,两个分支(每个分支四个神经元)的组合输出是混合数据网络各层的输入。我们添加了另一个由四个神经元组成的密集层,最后在最后一个神经元上进行线性激活,这就是预测的流行度。这产生了误差最小的最佳模型。结果如下所述。
*均绝对百分比差异:55.22%
均方根误差:0.08021
该模型为我们提供了超过 60%的数据的实际流行度的 0.25 以内的流行度预测。最佳拟合线也显著改善。我们对最终的 RMSE 值 0.08021 非常满意。*均而言,我们的受欢迎度指标下降了 0.08,这是一个非常好的估计值。

Figure 17: Line of best fit of our mixed input model
下面是我们的一些预测。

Figure 18: Predictions of our mixed input model
总结与未来工作
对于这个项目,MLP 和两层神经网络提供了最好的结果。由此产生的 RMSE 明显好于 XGBoost 给出的基准分数,即使它知道一篇帖子上的赞数。通过结合上述所有方法,我们能够实现一个非常好的预测模型。尽管如此,仍有一些途径我们可以进一步探索,但由于时间限制,我们未能这样做。例如,将文本从各种其他语言翻译成英语会产生噪音。通过将我们对帖子的搜索限制在英语帖子,这种噪音可能会减少。我们可以采取的另一个减少数据可变性的措施是排除某些类型的账户,比如最受欢迎的账户。由于数据和特征的这种自然可变性,任何模型都很难准确地学习和预测帖子的受欢迎程度。最后,通过考虑帖子上的标签和提及,我们可以为 NLP 任务生成进一步的功能组合,以查看它们是否增加了帖子收到的赞数的可变性。
作者:迪伦·布雷、哈桑·楚格泰、努曼·吉拉尼、西蒙·谢、查理·杨和桂·萨莫拉诺
用 Python 中的随机森林预测肉类库存价格

在本帖中,我们将使用随机森林来预测 Beyond Meat 股票的价格。Beyond Meat 是一家植物性肉类替代品生产商,由伊森·布朗于 2009 年在洛杉矶创立。
我们可以做的第一件事是导入必要的库。我们将使用 yahoo finance API、seaborn、matplotlib、pandas、numpy 和 sklearn:
import yfinance as yf
import seaborn as sns
import numpy as np
import pandas as pd 
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
如果您没有安装用于 yahoo finance API 的 python 包装器,您可以在命令行中键入以下内容:
pip install yfinance
我们可以从 Yahoo finance 获取过去五个月的“BYND”股票数据,并打印前五行。我们将拉取 2019 年 5 月 5 日至 2019 年 11 月 2 日的数据:
data = yf.Ticker('BYND')
df = data.history(period="max",  start="2019-05-01", end="2019-11-02")
print(df.head())

我们可以使用 seaborn 来绘制开盘价。我们还使用 matpltlib 来修改 seaborn 图。为了绘制时间序列,我们需要将日期字符串转换为日期时间对象:
sns.set()
df[‘timestamp’] = df.index
df[‘timestamp’] = pd.to_datetime(df[‘timestamp’])
sns.lineplot(df[‘timestamp’], df['Open'])
plt.ylabel("Open Price")

接下来,我们可以使用每日开盘价和收盘价计算每日回报率,并绘制结果图:
df[‘returns’] = (df[‘Close’]-df[‘Open’])/df[‘Open’]
sns.lineplot(df[‘timestamp’], df['returns'])
plt.ylabel("Returns")

接下来,我们定义一个变量来指定我们想要预测多远。让我们预测 3 天以后。我们还创建了一个新的预测列,它是向上移动了 3 天的目标变量。这里我们的目标变量是收盘价:
forecast_out = 3
df[‘prediction’] = df[[‘Close’]].shift(-forecast_out)
X = np.array(df['Close']).reshape(-1,1)
X = X[:-forecast_out]
y = np.array(df['prediction'])
y = y[:-forecast_out]
接下来,我们拆分用于训练和测试的数据,定义一个随机森林对象并训练我们的模型:
reg = RandomForestRegressor(n_estimators = 300, max_depth =300, random_state = 42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state = 7)
reg.fit(X_train, y_train)
print("Performance (R^2): ", reg.score(X_test, y_test))

我们的模型 R = 0.84,还不算太差。感谢阅读,机器学习快乐!这篇文章的代码可以在 GitHub 上找到。
预测健康的社会决定因素
数据科学@HF

健康的社会决定因素——一个人的直接健康状况之外的因素,如就业、居住地和教育水*——至少决定了20%的健康结果。在第一保健,面临与这些决定因素相关的挑战的会员去医院的次数增加了 30%,住院时间延长了 2 天,医疗费用增加了 33%。问题是我们缺乏系统测量它们的数据。如果这些数据随时可用,我们将能够实现将人们与社会和环境服务联系起来的新方法,以帮助治疗、预防和治愈疾病,提高生活质量,并降低总体医疗成本。
作为一家拥有 140 万纽约人的保险公司(八分之一!),我们的数据科学和人口健康战略围绕着分析临床数据和预测健康行为和结果。会不会是我们遗漏了一些对理解我们的成员至关重要的东西?是的,肯定的。在一个十分之三的家庭生活在联邦贫困线以下的城市(FPL ),只有 1%的会员医疗索赔包含财务压力的指标,这似乎从表面上看是错误的。这就是为什么在你分析性地做任何事情之前,有先验是有好处的。
好消息是机器学习可以有所帮助。人们已经做了大量无人监管的工作来对社区进行分类,并创建风险指数。但是我们有标签数据!真正积极的标签来自那 1%的所谓的 Z 代码的声明,并且我们合理地确定我们真正的零(基于我们的先验,可能十分之一到三分之一会被误标)。统计学家会退缩,但深度学习对标签噪音是鲁棒的。单侧标签噪声略有不同,因为估计真实的类条件分布需要更严格的理论假设(我们将有一个关于这方面的博客!).利用我们对某个成员的所有了解(人口统计、邻里关系、疾病负担、利用率、药物),我们可以合理地预测哪些成员可能正在与标签集中的这些相同的社会因素进行斗争。我们建立了 10 个模型(每个模型对应一组诊断代码),并用它对我们的全体会员进行评分。有了这些新知识,我们的人口健康团队、照护管理师和提供者合作伙伴可以更容易地接触到那些可能正在与一个或多个社会因素作斗争的成员,并为他们提供有用的资源,如用于住房的 PATH 和用于食品不安全的 SNAP 。
这些风险评分本身就很有价值,也为进一步分析提供了丰富的新特征集。医疗保险行业还没有想出如何将它们纳入风险模型中,但这并不能阻止他们使用它们来影响临床结果。在我们的计划全因再入院模型中,财务和住房压力风险得分是第二重要的变量,仅次于“您过去是否被再入院?”事实上,所有 10 个评分的第一个主成分本身就像一个不错的再入院模型:AUC 为 0.68,Brier 评分为 0.19。我们的目标是将它们用作任何分析中的标准描述性特征,就像您对待年龄或种族一样。
这是我们已知社会决定地位成员的密度图

这里有根据我们的车型分类的所有会员,增加了 10 倍!

验证和影响
作为医疗服务提供者赞助的健康计划,我们很幸运拥有最终的验证数据集:在模型培训期间,数据科学家根本无法获得这些数据。我们有来自赞助医院的调查数据,试图捕捉挣扎于社会负担中的成员。他们在不知道我们正在建模的情况下进行调查,而我们在不知道他们将进行调查的情况下建立模型。结果:c 统计值为 0.71,Brier 评分为 0.16,这意味着我们是方向正确的(你几乎可以听到数据科学家的合唱,“所有的模型都是错误的,有些是有用的”)。
我们与成员进行的每一次临床互动都需要了解社会决定因素。如果我们注意到会员在艰难地支付食物费用(或者即使我们有很好的猜测),我们可以将他们与他们可能不知道的重要服务联系起来。
随着我们在更好地理解会员需求这一愿景上取得的进展,我们将提高供应商对这些情况的认识,并与更多的赞助商合作;这两者都给了我们更好的标签,从而产生更好的模型。我们一定要这么做。但是,我们也可以利用这里提出的想法立即影响我们的成员。这就是我去上班的原因。
用马尔可夫链预测天气
基于历史天气数据构建马尔可夫链

在我们的机器学习工具箱中,有从简单到复杂的各种工具。马尔可夫链处于光谱的简单一端。
我们将通过使用马尔可夫链来学习预测明天的天气。
根据维基百科,
马尔可夫链是描述一系列可能事件的随机模型,其中每个事件的概率仅取决于前一个事件达到的状态。
翻译:马尔可夫链有有限个可能的状态。每个时间段,它从一个状态跳到另一个状态(或同一个状态)。跳到特定状态的概率只取决于与我们当前状态相关的概率。
当我们在示例的上下文中查看它时,它会更有意义。
天气
在我们简化的宇宙中,天气只能有两种可能的状态,“晴天”或“雨天”。
(在马尔可夫链的背景下)问题是,明天是晴天还是雨天,取决于今天是晴天还是雨天。
我们将从过去的数据中推导出这些概率,并构建一个转移矩阵。
我已经生成了 7 天的历史数据来“训练”我们的马尔可夫链。日子是:[雨,太阳,雨,太阳,雨,雨,太阳]

R S R S R R S
现在计算紧接着雨天的晴天的百分比。

3/4 所以 75%。
现在计算紧接着晴天的雨天的百分比。

那是 2/2 所以 100%。
我们将利用这些信息构建我们的转换矩阵,从我们已经获得的信息中推断缺失百分比(雨后= 25%和太阳后= 0%)。
跃迁矩阵

我们也可以用图表显示上述信息。
马尔可夫链

R = rainy, S = sunny
这张图表说明了一个事实,即概率完全取决于当前状态,而不是昨天或前天的天气。
让我们做一些预测
例一:
前 3 天为【雨天、晴天、雨天】。明天下雨的概率有多大?

R, S, R
基于我们之前训练的模型。明天有 75%的机会出太阳,25%的机会下雨。
例二:
前 2 天是【雨天,雨天】。

R R
同样,明天有 75%的机会出太阳,25%的机会下雨。
例三:
前 3 天都是【晴、雨、晴】。

S R S
明天有 100%的可能下雨。太阳落山后的日子总是下雨…我知道这很悲伤…
记住,我们只考虑当天的天气,然后在转移矩阵中查找天气状态的转移概率。
太简单了?很有可能。
但有时最好的起点是一个简单的模型,它比随机猜测表现得更好。
预测 2019 年橄榄球世界杯的冠军
根据机器学习。

我喜欢橄榄球,也喜欢跳羚队。当我们看到我们最喜欢的球队在 6 周的时间里展示他们的技能,争夺威廉·韦伯-埃利斯奖杯时,这是一种特殊的感觉。心会破碎,心会愈合,心会飞翔,只是为了再次破碎。眼泪(主要是我的)会流下来,啤酒会被喝光,球迷和球员会以真正的橄榄球方式分享祝贺和和解的拥抱。
但我也喜欢编码。务实地说。过去,我曾试图用我所知道的统计学和机器学习来模拟各种每周橄榄球比赛的结果。所以我决定拂去目录上的灰尘,更新数据和模型,看看哪支队伍会在今年的比赛中获胜。
数据
首先,我需要数据。ESPN 有可爱的历史数据库,但我似乎找不到下载按钮。我需要刮它。他们每页只显示 50 个结果。

检查页面,更重要的是检查next page按钮,我注意到有一个 href “转到结果的第 2 页”和一个 url。所以我可以使用这个和BeautifulSoup来解析页面上的html匹配数据,获得一个新的 url 并加载下一个页面。冲洗并重复。

此外,我想得到官方团队世界橄榄球排名,因为它应该是一个有用的功能。前往 World Ruby 的网站我们有可按年份配置的排名。我们再次在页面上添加了一个html解析器,但是我需要每年的数据(我很懒)。
使用基本相同的技巧,我可以通过检查小部件 url [rankings/mru?date=2019-08-26&client=pulse](https://cmsapi.pulselive.com/rugby/rankings/mru?date=%s-11-05&client=pulse)并简单地在字符串中递减年份来获得橄榄球排名的历史记录(*对于每场比赛,您可以获得比赛每天的排名,但目前我没有)。合并这些数据我得到以下基本结构:

Initial data used for analysis. home / away_pos & home / away_pts are the world ranking positions and points respectively
将一个团队称为home或away团队在 WC 环境中并不适用,因为除了日本,所有团队都在外地,但是数据是这样组织的。所以我采用了命名约定(它击败了left_team和right_team))。
当我在谷歌上搜索试图看看是否有其他人做过类似的事情时,我在 PYMC 文档中偶然发现了一个神奇的笔记本,作者是 Peadar Coyle,它使用层次贝叶斯模型来量化每个团队的进攻和防守实力。通过一点点复制意大利面和摆弄,我们可以扩展所有 WC 团队的 PYMC 模型以及估计每个赛季的参数。下面可以看到 2018**赛季的优势和劣势。

Team attacking (left) and defensive (right) statistics from Bayesian analysis
这些似乎都有道理。根据 PYMC 的文章:“我们期望我们的强队在进攻中有强烈的正面效应,在防守中有强烈的负面效应。”
结果也符合 2018 年的统计数据。威尔士被评为 2018 年最佳防守球队,紧随其后的是爱尔兰、新西兰和英格兰。在进攻方面,从我在 ESPNs stats 网站上看到的情况来看,这里最强的进攻球队和 2018 年得分最高的球队之间有着密切的一致(**请注意,上面情节中包括的比赛只适用于 2018 年,但是在最终的 PYMC 模型中,我们将 2019 年分为延长的 2018 赛季。据观察,来自缩短的 2019 年世界杯前赛季的小样本具有有偏差的参数)。
PYMC 是一个漂亮的分析工具。我们可以通过对每场比赛进行几(百)次模拟来进一步分析,并计算每场历史比赛的获胜概率以及对积分差异的估计(参见这篇精彩的博客了解更多)。
我们现在有了每场比赛的主要功能集——主队和客场队的贝叶斯进攻和防守实力、主队和客场队的世界橄榄球排名、主场获胜的贝叶斯概率以及 PYMC 预测的分差。
模型
最终数据包括自 2004 年以来所有国际橄榄球比赛的 2613 场比赛——我们对我们的球队、场地(为什么不)进行标记编码,并继续在数据集上运行分类器。为了让事情变得更简单,我把这个问题框定为一个二元问题,把主场胜利归类为 1(即home_score — away_score > 0),否则归类为 0。

将数据放入我最喜欢的分类器 XGBoost 分类器——进行随机训练测试分割,并用 Hyperopt 进行超优化,得到以下结果:
Bayes Only F1: 0.82
XGB Train F1: 0.90
XGB Test F1: 0.87
结果和预测
最后,我们需要厕所设备。我们可以在这里下载完整的 csv 列表。我再次对结果进行假设以简化并忽略绘图。如果是主场胜利,分配home_team 4分,否则away_team得分。
小组赛的结果多少是可以预测的。新西兰预计将击败南非和 B 组头名,而威尔士预计将在 d 组排名第一。不出所料,英格兰和爱尔兰将在各自的小组中排名第一。这里没有预测到大的混乱。

Top 2 from each pool
下面最后阶段的结果用graphviz和Networkx绘制,颜色按获胜概率编码。爱尔兰 vs 南非 QF 看起来不那么决定性,预计南非获胜的概率为 51%。同样,在新西兰对威尔士的决赛中,我们没有观察到任何一个队有很大的可能性(55%对 45%支持威尔士)。

Wales is going to win the World Cup
模型诊断
我们可以探索模型,找出哪些是最重要的特征,以及为什么它会做出某些预测。下面的全球功能重要性图表明,贝叶斯数据(获胜概率和预测分差)是最重要的功能,其次是相关团队的世界排名。

Global Feature Importance
类似地,我们可以局部地理解每个单独游戏的预测。在大莱姆和 SHAP 的辩论中,我选择了 SHAP。没有真正的原因,我只是喜欢匀称的价值观的“去除效应”背后的想法。下面我们可以观察到哪些特征对每个四分之一决赛都很重要。

我们看到,主队的排名在所有 QF 预测以及贝叶斯概率数据中起着重要作用。强大的防守得分在决定谁将获胜时也有很大的影响。
没有一种模式是完美的。这是作为周末的一点乐趣来完成的。我希望你喜欢这个分析。
最后,加油博克!
感谢马克·拉莫托斯基、理查德·菲茨杰拉德和丹妮尔·费舍尔对我的纵容。
预测泰坦尼克号幸存者(卡格尔竞赛)
本案例研究的目的是记录我在第一次 Kaggle 竞赛中创建预测的过程,该竞赛名为 Titanic:机器从灾难中学习。对于外行人来说,Kaggle 是一个受欢迎的数据科学网站,拥有数千个公共数据集,提供课程,通常作为具有分析思维的社区中心。他们还举办各种目标的机器学习竞赛。这个特殊比赛的目标是建立一个分类模型,可以成功地确定泰坦尼克号乘客的生死。

Could our data science efforts have helped? We’ll find out!
我们开始吧!
1.0 导入数据
这个过程的第一步总是加载数据和必要的包。在我使用的编程语言 R 中,包是允许用户执行特定任务的算法集合。有创造美丽的情节,建立股票投资组合和几乎任何你能想象的东西的软件包。在这里,我加载了许多包,允许我利用一些强大的机器学习(ML)模型。
lapply(c(“caret”,
 “h2o”,
 “pROC”,
 “randomForest”,
 “readr”,
 “tidyverse”,
 “xgboost”),
 library,
 character.only = TRUE)
 h2o.init()
 h2o.no_progress()
 set.seed(123)
 train <- read_csv(“~/Downloads/train.csv”)
 test <- read_csv(“~/Downloads/test.csv”)
竞争数据集来自两个文件:训练和测试。正如您可能猜到的,前者用于训练 ML 模型,而测试用于做出最终提交的预测。
2.0 探索数据
将我的数据放入 R 后,是时候探索数据的形状了。
train %>% glimpse()## Observations: 891
 ## Variables: 12
 ## $ PassengerId <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1…
 ## $ Survived <dbl> 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1…
 ## $ Pclass <dbl> 3, 1, 3, 1, 3, 3, 1, 3, 3, 2, 3, 1, 3, 3, 3, 2, 3, 2…
 ## $ Name <chr> “Braund, Mr. Owen Harris”, “Cumings, Mrs. John Bradl…
 ## $ Sex <chr> “male”, “female”, “female”, “female”, “male”, “male”…
 ## $ Age <dbl> 22, 38, 26, 35, 35, NA, 54, 2, 27, 14, 4, 58, 20, 39…
 ## $ SibSp <dbl> 1, 1, 0, 1, 0, 0, 0, 3, 0, 1, 1, 0, 0, 1, 0, 0, 4, 0…
 ## $ Parch <dbl> 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 5, 0, 0, 1, 0…
 ## $ Ticket <chr> “A/5 21171”, “PC 17599”, “STON/O2\. 3101282”, “113803…
 ## $ Fare <dbl> 7.2500, 71.2833, 7.9250, 53.1000, 8.0500, 8.4583, 51…
 ## $ Cabin <chr> NA, “C85”, NA, “C123”, NA, NA, “E46”, NA, NA, NA, “G…
 ## $ Embarked <chr> “S”, “C”, “S”, “S”, “S”, “Q”, “S”, “S”, “S”, “C”, “S…test %>% glimpse()## Observations: 418
 ## Variables: 11
 ## $ PassengerId <dbl> 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 90…
 ## $ Pclass <dbl> 3, 3, 2, 3, 3, 3, 3, 2, 3, 3, 3, 1, 1, 2, 1, 2, 2, 3…
 ## $ Name <chr> “Kelly, Mr. James”, “Wilkes, Mrs. James (Ellen Needs…
 ## $ Sex <chr> “male”, “female”, “male”, “male”, “female”, “male”, …
 ## $ Age <dbl> 34.5, 47.0, 62.0, 27.0, 22.0, 14.0, 30.0, 26.0, 18.0…
 ## $ SibSp <dbl> 0, 1, 0, 0, 1, 0, 0, 1, 0, 2, 0, 0, 1, 1, 1, 1, 0, 0…
 ## $ Parch <dbl> 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
 ## $ Ticket <chr> “330911”, “363272”, “240276”, “315154”, “3101298”, “…
 ## $ Fare <dbl> 7.8292, 7.0000, 9.6875, 8.6625, 12.2875, 9.2250, 7.6…
 ## $ Cabin <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, “B45…
 ## $ Embarked <chr> “Q”, “S”, “Q”, “S”, “S”, “S”, “Q”, “S”, “C”, “S”, “S…
上面的代码说的是,训练数据有 891 行,包含 12 个不同的变量。这些变量包括乘客的姓名、性别和年龄、票价和上车地点等。这里最重要的变量是名为“Survived”的变量,这是一个由 1 和 0 组成的列表,分别表示乘客是死是活。测试数据包含 418 行,缺少“幸存”变量,因为这是竞争对手要求我们预测的。
虽然现在的数据中包含了大量信息,但并不是所有的信息都可以以当前的形式使用。为了提取尽可能多的有用信息,我必须转换其中的一些变量。
3.0 转换数据
我要查看的第一个变量是“名称”据我所知,击沉泰坦尼克号的冰山与任何乘客都没有私人恩怨,所以简单地使用乘客的全名不会提供任何有用的信息。然而,可能是乘客的头衔。像“先生”、“夫人”或“伯爵夫人”这样的头衔可以帮助我们确定乘客的社会地位(例如,他们是*民还是贵族?)对他们的生存有任何影响。
为了获得这些标题,我必须从“Name”中提取它们,下面的代码就是这样做的。
titles <- c(unique(str_extract(str_extract(train$Name, “\\,\\s[A-Za-z]+”), “[A-Za-z]+”)))
 titles <- replace(titles, titles == “the”, “Countess”)
 titles## [1] “Mr” “Mrs” “Miss” “Master” “Don” “Rev” 
 ## [7] “Dr” “Mme” “Ms” “Major” “Lady” “Sir” 
 ## [13] “Mlle” “Col” “Capt” “Countess” “Jonkheer”
如果你想知道,“Jonkheer”是荷兰贵族使用的尊称。泰坦尼克号上有一个叫约翰·乔治·罗克林的人,剧透一下,他死了。_(ツ)_/
除了使用这个标题列表来创建一个新变量之外,我还将从“Cabin”中提取 Deck 并创建一个名为“Family_Size”的变量,它只是“SibSp”和“Parch”的组合,前者是船上兄弟姐妹和配偶的计数,后者是船上父母和子女的计数。我还将清理一些其他变量,使它们更容易为 ML 模型所理解。
train <- train %>% mutate(Survived = factor(Survived), Sex = factor(recode(Sex, 
 male = 1, female = 0)), Pclass = factor(Pclass), Embarked = factor(Embarked), 
 Deck = factor(replace_na(substr(train$Cabin, 1, 1), “Unknown”)), Title = factor(str_extract(train$Name, 
 paste(titles, collapse = “|”))), Family_Size = SibSp + Parch) %>% select(-c(Cabin, 
 Name, Ticket))
 test <- test %>% mutate(Sex = factor(recode(Sex, male = 1, female = 0)), Pclass = factor(Pclass), 
 Embarked = factor(Embarked), Deck = factor(replace_na(substr(test$Cabin, 
 1, 1), “Unknown”)), Title = factor(str_extract(test$Name, paste(titles, 
 collapse = “|”))), Family_Size = SibSp + Parch, Fare = ifelse(is.na(Fare), 
 mean(Fare, na.rm = TRUE), Fare)) %>% select(-c(Cabin, Name, Ticket))
3.1 预测乘客年龄
我之前检查数据时没有指出的一点是,有多少乘客的年龄没有被记录下来。在我们拥有数据的 1309 名乘客中,有 266 名没有年龄。丢失的信息以后会有问题,所以我觉得有必要用猜测来代替那些空值。
简而言之,下面的代码将训练和测试数据结合起来,提取出有年龄的记录,并拟合一个随机森林(RF)模型,该模型确定乘客年龄和其他变量之间的关系。最后,它会用对他们年龄的最佳猜测来填充所有缺失的年龄。
旁注:深入描述什么是 RF 模型将完全偏离本案例研究。如果你有兴趣了解更多关于射频模型及其工作原理的信息,请访问这个网站。
*# Combining the training and test data and selecting only the rows with ages*
 age <- train %>% select(-Survived) %>% rbind(test) %>% filter(!is.na(Age)) %>% 
 filter(!is.na(Embarked))
 *# Building a prediction model*
 age_rf_model <- randomForest(Age ~ . — PassengerId, age, ntree = 5000, mtry = 9, 
 na.action = na.exclude)
 *# Determining the accuracy of the model*
 age %>% select(Age) %>% add_column(Pred = predict(age_rf_model, age)) %>% na.omit() %>% 
 mutate(Error = Age — Pred, Error_Pct = Error/Age) %>% summarize(RMSE = sqrt(mean(Error²)), 
 MAPE = mean(abs(Error_Pct)))## # A tibble: 1 x 2
 ## RMSE MAPE
 ## <dbl> <dbl>
 ## 1 7.30 0.302*# Using the model to predict passenger age*
 train <- train %>% mutate(Age = ifelse(is.na(Age), round(predict(age_rf_model, 
 train)), Age))
 test <- rbind(train[1, c(1, 3:12)], test)
 test <- test[-1, ]
 test <- test %>% mutate(Age = ifelse(is.na(Age), round(predict(age_rf_model, 
 test)), Age))
为了检查 RF 模型的预测有多准确,我计算了预测的均方根误差(RMSE)和*均绝对百分比误差(MAPE ),以衡量这些预测的质量。关于这两个指标的简要描述,请参阅我之前的文章。
长话短说:两种误差指标都很低。MAPE 告诉我,*均预测只有 0.3%的误差,所以虽然不完美,但我觉得对于我预测生存的最终目标来说,这是可以接受的。
4.0 训练模型
既然数据是干净的,是我开始用数据训练 ML 模型的时候了。因为我想确保我的模型在看不见的数据上表现良好,所以我将把我的训练数据分成一个较小的训练和测试数据集。这样,我可以在将模型带到 Kaggle 提供的实际测试数据之前评估模型的准确性(记住,我不能评估准确性,因为数据缺少“存活”变量)。
train_1 <- stratified(train, c(“Survived”, “Deck”, “Title”), size = 0.7, replace = FALSE)
 train_2 <- setdiff(train, train_1)
我将使用四种不同的模型,每种模型都有自己的预测方式:线性模型,随机森林模型, XGBoost (极端梯度推进)模型和 H2O 的 AutoML 。同样,您可以随意点击超链接来了解这些模型是什么以及它们在做什么。
为了让下面发生的事情更容易理解,想象一下,我们想要赢得一场综合武术比赛,而不是预测泰坦尼克号的幸存者。在比赛开始前,我们只有足够的时间掌握一种武术,所以我们需要弄清楚我们应该学习哪一种才能最有机会获胜。我们知道竞争对手是谁(即我们的测试数据),但我们不确定哪种武术最适合我们。下面是我们正在进行的模拟,我们学习四种不同的武术(比如拳击、柔术、太极拳和跆拳道),看看我们如何应对与锦标赛中类似的竞争对手(即我们的训练数据)。
*# Linear Model — —* 
 glm_model <- glm(Survived ~ . — PassengerId, family = “binomial”, train_1)
 *# Random Forest — —* 
 rf_model <- randomForest(Survived ~ . — PassengerId, train_1, ntree = 10000, mtry = 3, na.action = na.exclude)
 *# XGBoost — —* 
 dummy_1 <- dummyVars(Survived ~ ., train_1[,2:12])
 train_1_dummy <- predict(dummy_1, train_1)
 dummy_2 <- dummyVars(Survived ~ ., train_2[,2:12])
 train_2_dummy <- predict(dummy_2, train_2)
 dtrain <- xgb.DMatrix(data = train_1_dummy, label = as.vector(train_1$Survived))
 dtest <- xgb.DMatrix(data = train_2_dummy, label = as.vector(train_2$Survived))
 watchlist <- list(train = dtrain, test = dtest)
 xgb_model <- xgb.train(
 data = dtrain,
 watchlist = watchlist,
 booster = “gbtree”,
 max.depth = 3,
 nthread = 2,
 nrounds = 5000,
 objective = “binary:logistic”,
 early_stopping_rounds = 500,
 print_every_n = 500
 )
 *# H2O — —* 
 train_1_h2o <- train_1 %>%
 select(-PassengerId) %>%
 mutate(Pclass = factor(Pclass, ordered = FALSE)) %>%
 as.h2o
 train_2_h2o <- train_2 %>%
 select(-PassengerId) %>%
 mutate(Pclass = factor(Pclass, ordered = FALSE)) %>%
 as.h2o
 y <- “Survived”
 x <- setdiff(colnames(train_1_h2o), y)
 split <- h2o.splitFrame(train_1_h2o, ratios = c(.70, .15))
 t1 <- split[[1]]
 t2 <- split[[2]]
 t3 <- split[[3]]
 h2o_model <- h2o.automl(
 x = x,
 y = y,
 train = t1,
 validation_frame = t2,
 leaderboard_frame = t3,
 nfolds = 5,
 stopping_metric = “AUC”,
 max_runtime_secs = 120
 )
 h2o_leader <- h2o_model@leader
5.0 模型比较
继续上面的比喻,没有一种武术能胜过所有的对手,所以我们要试着找到表现最好的一种。对于武术来说,衡量的标准可能是获胜的次数。对于《泰坦尼克号》的预测,我将精确地衡量它(主要是因为这是 Kaggle 用来给这场比赛打分的)。
为了确定这种准确性,我将生成一个所谓的置信矩阵。简单地说,这是一个 2x2 的盒子,沿着 x 轴显示实际值(在输出中称为“参考值”),沿着 y 轴显示预测值。这使您可以看到四个变量:
真阳性:预测= 1,实际= 1
真负数:预测= 0,实际= 0
误报:预测= 1,实际= 0
假阴性:预测= 0,实际= 1
准确性是对所有预测中有多少真阳性和真阴性的一种衡量。
compare_set <- train_2 %>% add_column(GLM_Pred = predict(glm_model, train_2, 
 type = “response”)) %>% add_column(RF_Pred = predict(rf_model, train_2)) %>% 
 add_column(XGB_Pred = predict(xgb_model, train_2_dummy)) %>% add_column(H2O_Pred = h2o.predict(h2o_leader, 
 newdata = train_2_h2o) %>% as_tibble() %>% pull(predict)) %>% mutate_at(vars(GLM_Pred, 
 XGB_Pred), list(~factor(as.numeric(. > 0.5))))
 for (i in 13:16) {
 conmat <- confusionMatrix(compare_set$Survived, compare_set[[i]], positive = “1”)
 print(colnames(compare_set[, i]))
 print(conmat$table)
 print(conmat$overall[1])
 }## [1] “GLM_Pred”
 ##            Reference
 ## Prediction 0   1
 ##          0 141 21
 ##          1 23  75
 ## Accuracy 
 ## 0.8307692 
 ## [1] “RF_Pred”
 ##            Reference
 ## Prediction 0   1
 ##          0 149 13
 ##          1 26  72
 ## Accuracy 
 ## 0.85 
 ## [1] “XGB_Pred”
 ##            Reference
 ## Prediction 0   1
 ##          0 147 15
 ##          1 20  79
 ## Accuracy 
 ## 0.8659004 
 ## [1] “H2O_Pred”
 ##            Reference
 ## Prediction 0   1
 ##          0 151 11
 ##          1 38  61
 ## Accuracy 
 ## 0.8122605
正如你所看到的,就纯粹的准确性而言,XGBoost 模型的表现最好,它正确预测了训练数据中所有幸存者的 86.6%。然而,准确性并不总是最好的衡量标准。如果您查看 XGBoost 的置信度矩阵,您会看到有 15 个假阴性。RF 模型虽然在准确性方面表现不佳,但只有 13 个假阴性。为什么这可能很重要取决于具体情况。
假设你是一名医生,负责确定病人是否患有某种疾病。假设对没有患病的人进行治疗是无害的,但如果不进行治疗,患病的人肯定会死亡。鉴于上述数字,RF 模型比 XGBoost 模型多拯救了两条生命。这里的要点是,永远不要简单地看准确性,并在此基础上做出最终判断。
所以我不会在这里!
相反,我将使用 RF 和 XGBoost 模型进行预测。由于第三次提交参赛作品不花我一分钱,我也将使用线性模型进行预测,因为它的准确性不会远远落后于其他两个模型。
6.0 做出最终预测
既然我已经有了训练有素的模型(或者说战士,如果你喜欢这个比喻的话),是时候让它们发挥作用了。我将把它们用在测试数据上,这些数据是模型从未见过的。
*# XGBoost*
 dummy_test <- dummyVars(PassengerId ~ ., test)
 test_dummy <- predict(dummy_test, test)
 submission_xgboost <- test %>% add_column(Survived = predict(xgb_model, test_dummy)) %>% 
 mutate(Survived = as.numeric(Survived > 0.5)) %>% select(PassengerId, Survived)
 *# Random Forest*
 submission_rf <- test %>% add_column(Survived = predict(rf_model, test)) %>% 
 select(PassengerId, Survived)
 *# Linear Model*
 submission_glm <- test %>% add_column(Survived = predict(glm_model, test)) %>% 
 mutate(Survived = as.numeric(Survived > 0.5)) %>% select(PassengerId, Survived)
让我们看看每个模型是如何预测测试数据中前 10 名乘客的存活率的。
submission_xgboost %>% left_join(submission_rf, by = “PassengerId”) %>% left_join(submission_glm, 
 by = “PassengerId”) %>% rename(XGBoost = Survived.x, RF = Survived.y, Linear = Survived) %>% 
 head(10)## # A tibble: 10 x 4
 ##   PassengerId XGBoost RF    Linear
 ##   <dbl>       <dbl>   <fct> <dbl>
 ## 1 892         0       0     0
 ## 2 893         0       0     0
 ## 3 894         0       0     0
 ## 4 895         0       0     0
 ## 5 896         0       0     1
 ## 6 897         0       0     0
 ## 7 898         0       0     1
 ## 8 899         0       0     0
 ## 9 900         1       1     1
 ## 10 901        0       0     0
如你所见,三个模型都预测乘客 900 幸存。线性模型还预测乘客 896 和 898 幸存。
7.0 提交预测
现在我有了我的预测,是时候把它们提交给 Kaggle,看看它们做得如何。首先,我必须将这些预测导出到一个 CSV 文件中,这样我就可以上传它们。
write_csv(submission_xgboost, “~/Downloads/Submission XGBoost.csv”)
 write_csv(submission_rf, “~/Downloads/Submission RF.csv”)
 write_csv(submission_glm, “~/Downloads/Submission GLM.csv”)
上传 CSV 后,Kaggle 会生成我每次提交的最终分数。所以,让我们看看我做得怎么样。

哇!看那黑马胜利!完全出乎意料!尽管对训练数据执行了三个模型中的第三个,但线性模型实际上对测试数据执行了所有模型中最好的。我真的没想到会这样。这只是表明你可以做世界上所有的训练,有时胜利只是靠运气。
客观地说,78.9%的分数并不令人印象深刻,因为还有其他提交的作品获得了满分。但鉴于这是我的第一次比赛,我在 11098 名参赛者中名列第 3149 名(比其他参赛者的 71.6%要好),我觉得这是一次令人满意的努力。
感谢您的阅读。我希望在下一个案例研究中见到您。
预测明天的黄金价格
我们有市场优势吗?

介绍
世界各地的央行都持有黄金储备,以保证储户、外债债权人和货币持有者的资金安全。各国央行也将黄金储备作为控制通胀和增强本国金融地位的一种手段。此外,金融公司、全球机构、基金经理和个人投资者也使用黄金来对冲通胀风险,并使其投资组合多样化。作为一种贵金属,黄金是流行的首饰和装饰品。
鉴于黄金在当代世界的受欢迎程度,预测其价格是一个广泛探索的话题,也是多个全球机构和大小规模投资者感兴趣的话题。这也是一个复杂的问题,因为黄金的价格波动并不完全取决于供求关系,还取决于许多地缘政治和金融因素。
方法学
用于此分析的方法有三个步骤:数据收集/组装步骤、模型构建步骤和评估步骤。

数据收集和汇编
本分析考虑的独立变量包括经济和市场因素,如 S & P 500、道琼斯工业*均指数、富时 100 指数、国债利率、银行利率、美元指数;以及其他商品指标如银、铂、钯和原油价格。此外,黄金期货也被认为反映了市场对未来黄金价格的预期。作为这项工作的一部分,许多研究都考虑了类似的变量,但黄金期货除外。
为了控制本项目的范围,本分析未考虑黄金供应国和消费国的国际经济和市场指标,以及表明黄金买卖季节性的变量,尤其是与一些亚洲消费市场相关的变量。该项目收集的数据是 2000 年至 2018 年这些变量的每日收盘价。其他每日市场指标如开盘价、最高价、最低价和交易量没有在本次分析中使用,但可能对未来的工作有价值。
因变量,黄金价格,是从 kitco.com 网站上收集的,并基于伦敦黄金定价基准。顾名思义,这一黄金基准价格由一组参与的国际银行在伦敦每个工作日制定两次,用于为全球市场的大多数黄金衍生品和产品定价。每天设定的两个比率中的最高者用于该分析。本项目使用的黄金价格如下所示:

该数据库由多个市场数据源组装而成,并使用日期作为合并属性。一旦数据被“缝合”在一起,美国假期就从分析中删除了。此外,在探索性数据分析步骤中标记的任何缺失或不合理的数据都使用前一天的价格进行估算(向前填充)。
建模
作为模型构建练习的一部分,使用了线性回归和时间序列方法,如下所示。

模型构建过程经历了以下步骤,其中每个步骤根据需要经历多次迭代:
- 使用 2000 年到 2015 年的每日价格来训练线性回归模型。作为该步骤的一部分,测试的因变量包括:第二天的价格、下周的价格、下个月的价格和第二天价格的百分比变化。然后使用 2016 年至 2018 年的每日价格对这些模型进行了测试。这一步的结果是使用次日价格作为因变量,并且只使用一年而不是三年进行模型测试。在此步骤中,我们注意到,随着测试数据与训练数据之间的距离越来越远,模型的性能越来越差。
 - 使用 2000 年到 2015 年的每日价格来训练线性回归模型,其中成本经过对数转换并缩放到零以上的中心。使用 2016 年的每日价格进行测试。
 - 使用 2000 年到 2015 年的每日价格来训练单变量时间序列模型,该模型使用经过和没有经过对数变换的黄金价格。使用 2016 年的每日价格进行测试。
 
对于时间序列模型,只使用了自回归(AR)模型。对于研究的两种时间序列函数形式,在有和没有对数转换黄金价格的情况下,根据阿凯克信息标准(AIC),最佳顺序被确定为前 3 天。
模型评估
评估时间序列(如黄金价格)的模型性能的关键步骤是将结果与简单的解决方案进行比较。在像黄金价格这样的非季节性变量的情况下(与棉花价格或交通流量这样的季节性变量相反),天真的预测是明天的黄金价格与今天的相同。Naive solution 作为投资策略或决策工具的效用有限,但它为模型评估提供了一个基准解决方案。对于上一节中提到的模型构建步骤 1 到 3,在模型选择和与原始解决方案的比较中使用的度量是 R *方值。
一旦选择了一个模型,该函数形式就被用于使用如下所示的扩展窗口概念来执行按时间顺序的训练/测试。从 2006 年到 2018 年,使用从 2000 年开始的前几年的数据训练的模型,对每一年的每日价格进行了时序训练/测试。对于这个时序测试,*均绝对误差(MAE)用于与原始解决方案进行比较。

结果
简单线性回归模型构建步骤的 2016 年测试结果如下所示。该模型使用 2000 年至 2015 年的每日黄金价格进行训练,并产生了与原始预测相比最佳的 R *方值(0.9719 比 0.9715)。该模型很好地跟踪了 2016 年的实际黄金价格,如下所示:

预测的 2016 年金价与实际金价的散点图如下所示。

2006 年至 2012 年使用线性回归模型进行的按时间顺序的培训/测试评估如下所示。对于这一时间段内的每一年,预测都比天真的预测更接*实际。*均预测偏差使用*均绝对误差(MAE)来衡量。

2006 年至 2018 年按时间顺序排列的培训/测试结果如下所示。请注意,该模型未能捕捉到 2013 年黄金市场的变化趋势。

2013 年发生了什么?
从贵金属到股票的投资热潮导致 2013 年黄金价格下跌* 30%,结束了长达 12 年的牛市。这一下降主要与投资者猜测美联储削减债券购买量,消除了购买黄金以对冲美元和通货膨胀的需求有关。
使用 2000 年至 2012 年训练数据估计的模型无法完全捕捉股票、国债、美元、联邦货币政策和商品市场之间不断变化的市场条件。
结论
使用线性回归和时间序列对黄金价格建模的上述历史分析得出以下结论:
- 对于时间序列变量,无论有没有可能战胜它,都要和一个简单的解决方案进行比较。
 - 检查你的模型能在多大程度上保持和扩展趋势。不是所有的模型都能完全概括一个像股票和商品市场这样高度复杂的系统。设定一个更小的时间框架,并经常更新你的模型。
 - 拥有多种型号。即使时间序列不会比 2012 年之前的天真预测表现得更好,它也会比线性回归更好地捕捉到 2013 年的金价下跌,线性回归在对抗天真预测方面表现得相当好。
 
参考
原载于https://mlbhanuyerra . github . io。
零射击学习:用“视觉到语义”的迁移预测未知类。
融合各种感官输入如何帮助您在图像分类任务中做出更好的预测并掌握更多信息。
机器学习喜欢大数据,尤其是当它被贴上标签的时候。Google 和腾讯发布了由数百万和数千万训练样本组成的图像任务数据集。OpenAI 表明,只需将数据集和网络参数提高 10 倍,网络就能在新的水*上运行。
人脑不是这样工作的。我们不仅能够从几个例子中学习,还能够进行跨领域学习。如果有人向你解释什么是老虎,老虎长什么样,你会认出它,即使你以前从未见过它。我们甚至可以通过语言描述来辨别气味。
我如何预测以前未见过和未知的类?
生物大脑中存在跨领域的可解释性。这个抽象层次比每个感官通道都要深。
基于这种逻辑,我想出了一个制作神经网络的主意,这个网络将在一个跨感官的基础上运行。经过一些研究,我发现(显然)这不是一个新方法,它被用于所谓的 ZSL(零射击学习)。这允许在预测中有(几乎)无限数量的类。
建筑。
这个想法很简单——将图像分类网络中的图像嵌入映射到单词嵌入,在视觉和语义表示之间架起一座桥梁。
该桥理论上允许在训练期间解决有限类别数量的问题,因为现代单词嵌入(fastText 作为第一种)不限于词汇,而是能够在英语语言的完整字母数字空间上操作。

技术细节
为了测试这个想法,我遵循了以下协议:
- 使用 ResNet101 处理来自开放图像 V2 验证数据集的 42620 幅图像,在开放图像数据集中进行预训练,并为每幅图像提取嵌入向量(在 pool5 之后)。
 - 每个图像对应的类名小写,用 fastText.wiki.en 模型得到嵌入向量[1x300d]。
 - 使用 4 层全连接网络将图像嵌入映射到单词嵌入。以余弦距离作为损失函数对网络进行 2000 个历元的训练,并基于验证子集选择最佳检查点。
 
结果
为了让你对结果有一个大致的了解,让我给你几个精选的结果。每个图像用 ResNet101 和图像到语义的转换进行分类。为了使事情更加公*,我还提供了与类名最相似的向量的结果。

我试图得到的主要结果是,使用这种方法可以提取出关于图像的更丰富、更多样的“标签云”。因此,显示类名到相似词的映射和图像到语义的转换之间的本质区别是很重要的。


进一步的想法
这个简单的实验引发了许多进一步的想法和观点。一个逆字到图像转移怎么样?使用键入的文本通过 GAN 生成图像?这些很难训练,但是很容易理解。
但是我们可以在这里更进一步。思考这个架构如何与简洁的本质相关联。人类的认知功能大量处理跨领域的转移,通过比较“抽象嵌入”不断地双重检查现实的性质,以找到基础真理。我认为小说特斯拉的 FSD 以同样的方式工作——所有的神经网络合并成一个单一的地面真实向量,描述汽车周围的环境。
神经网络架构
class ImgToWordModel(nn.Module): def __init__(self): super(ImgToWordModel, self).__init__() def fc_block(in_filters, out_filters): block = [nn.Linear(in_filters, out_filters), nn.LeakyReLU(0.2, inplace=True), nn.Dropout(0.1)] return block self.model = nn.Sequential( *fc_block(2048, 2048*3), *fc_block(2048*3, 2048*2), *fc_block(2048*2, 1024), ) self.last_layer = nn.Sequential(nn.Linear(1024, 300)) def forward(self, img): out = self.model(img) word = self.last_layer(out) return word
其他一切都很明显。ResNet101 的推理代码取自开放图像,训练细节如下(2000 个纪元)
loss_fn = torch.nn.CosineEmbeddingLoss().to(device) optimizer = torch.optim.Adam(model.parameters(),1e-3) flags = Variable(torch.ones(256)).to(device)
我肯定会写另一个关于这个想法的哲学方面的出版物,保持联系!
原载于 2019 年 4 月 29 日【https://fridayexperiment.com】。
预测未知的未知
参考论文:减少网络恐惧症:https://arxiv.org/pdf/1811.04110.pd

对于许多领域和场景的分类模型,重要的是预测何时给予模型的输入不属于它被训练的类别。
对于计算机视觉/物体检测器模型,作者提供以下理由:
Object detectors have evolved over time from using feature-based detectors to sliding windows [34], region proposals [32], and, finally, to anchor boxes [31]. The majority of these approaches can be seen as having two parts, the proposal network and the classification network. During training, the classification network includes a background class to identify a proposal as not having an object of interest. However, even for the state-of-the-art systems it has been reported that the object proposals to the classifier “still contain a large proportion of background regions” and “the existence of many background samples makes the feature representation capture less intra-category variance and more inter-category variance (...) causing many false positives between ambiguous object categories” [41]. In a system that both detects and recognizes objects, the ability to handle unknown samples is crucial. Our goal is to improve the ability to classify correct classes while reducing the impact of unknown inputs.
这也是许多领域中需要解决的一个重要问题,包括医疗保健、机器人(不考虑视觉或 NLP)。
术语:

过去处理这一问题的方法依赖于两种基本方法:
- 给定一个输入,根据该输入与培训中看到的输入的接*程度提供不确定性得分。==> P (U | x)
 - 给定输入 x,预测该输入属于训练该模型所有类别 Ci (i=1 到 n)的概率。然后,我们以最小概率为阈值,以最大概率拒绝集合外或未知的输入。
 
以下是一些相关方法的总结:
- 设定 Softmax 分数的阈值:这种方法假设来自未对网络进行训练的类别的样本将具有分布在所有已知类别中的概率分数,因此使得任何已知类别的最大 softmax 分数较低。因此,如果系统设定最高分数的阈值,它可以避免将这样的样本分类为已知类别之一。这是迄今为止最常见和最简单的技术,不需要任何模型再训练或额外的分布数据来应用它。然而,它很少工作得很好。主要是因为 softmax 已知会使概率偏向某个类,即使胜出类与其相邻类的 logit 值之间的差异很小。对此的一个解决方法是:
 

2.不确定性估计:2017 年,Lakshminarayanan 等人[20]介绍了一种使用 MNIST 数字训练的 MLP 系综及其对立示例来预测不确定性估计的方法。他们的方法不是逼* P(u | x),而是专注于在 x ∈ Du 时减少 max(P(c | x)),他们使用网络系综解决了这个问题
3.开放集方法 OpenMax:在训练过程中不使用背景样本。OpenMax 旨在直接估计 P(U | x)。使用来自训练样本的深度特征,它建立不属于已知类的输入的每类概率模型,并在每个类概率的 OpenMax 估计中组合这些模型,包括 P(U | x)。虽然这种方法提供了正式解决深度网络的开集问题的第一步,但它是在网络已经被训练之后的离线解决方案。它没有改进特征表示来更好地检测未知类。
4.背景类:用背景类训练的系统使用来自 Db 的样本,希望这些样本足以代表 Du,以便在训练后系统正确地标记未知。它类似于 1 末尾所示的 soft max-alpha 修改方法。阈值 Softmax 以上,除了它使用背景类的例子在训练。
在此背景下,本文的主要贡献如下:
Our Contributions: In this paper, we make four major contributions: a) we derive a novel loss function, the Entropic Open-Set loss, which increases the entropy of the softmax scores for background training samples and improves the handling of background and unknown inputs, b) we extend that loss into the Objectosphere loss, which further increases softmax entropy and performance by minimizing the Euclidean length of deep representations of unknown samples, c) we propose a new evaluation metric for comparing the performance of different approaches under the presence of unknown samples, and d) we show that the new loss functions advance the state of the art for open-set image classification. Our code is publicly available
[http://github.com/Vastlab/Reducing-Network-Agnostophobia](http://github.com/Vastlab/Reducing-Network-Agnostophobia)
熵开集损失:
如果有 C 个已知类别,这里的想法是当给定属于背景(已知未知)的输入时,训练网络为每个已知类别生成 1/C 的概率。如果背景有足够的变化,希望这能转化为对未知的类似预测。请注意,这只是对典型交叉熵损失的一个微小修改。
设 Sc 为上述 softmax 分数,我们的熵开集损失 JE 定义为:

基于上述熵开集损失(EOS ),我们有以下直观推导:

引理 1 和引理 2 相当直观。
为了解释定理 1:直觉是如果我们想要 softmax 概率对于背景类是相等的,一种方法是馈送到网络最后一层的特征向量 F(x)为零。这是因为 logits = Wl * F(x)。对于背景类示例,如果 F(x)是 zeors,则 logits 将为零,因此 softmax 概率将相等。
目标大气损失:
这种损失的目的是迫使背景样本的 F(x)为低值,并将已知样本推入我们称之为对象圈的地方,在那里它们具有大的特征量。

总结:object sphere loss 易于实现,在未知的未知预测中帮助很大。
车辆碰撞和机器学习
用机器学习预测车祸死亡率。Python 中的演练。

Heatmap Wellington Vehicle Crashes
道路事故是我们世界各地社会的一个主要问题。世界卫生组织(世卫组织)估计,2010 年有 125 万人死于道路交通伤害。2016 年,仅美国就记录了 37,461 起与机动车碰撞相关的死亡,*均每天约 102 人。在欧洲,统计数据还表明,2017 年每分钟就有 50 人死于道路交通事故。机器学习能帮助我们理解车祸的原因和影响车祸严重程度的因素吗?
在本文中,我们将通过 API 获取数据,执行探索性数据分析,并将现实世界的问题公式化为机器学习模型,从而完成一个完整的机器学习管道。完整的代码和 Jupyter 笔记本可以在这个 Github Gist 中找到。整个过程是在 Google Colab 中使用免费的 GPU/TPU 环境进行的,所以你可以直接从 Github 打开笔记本,并在 Google Colab 中进行实验。
获取数据
碰撞分析系统(CAS)数据有不同的格式和 API。很容易通过 API 接口获取它们,而不是下载到您的本地机器。这是有益的,因为我们将在每次运行 Jupyter 笔记本时访问最新更新的数据。我发现车辆事故这一特殊问题与位置(地理)密切相关,因此我们将获取 Geojson 文件,而不是通常的 CSV 文件,以便我们可以执行地理数据分析,而无需根据纬度和经度创建几何图形,并处理坐标参考系统和投影。
我们将使用 Geopandas 库来读取数据。如果你熟悉熊猫图书馆,那么你应该有家的感觉,因为地质公园是建立在顶级熊猫之上的。Geopandas 是一个高级库,它使使用 Python 处理地理数据变得更加容易,因为它允许 pandas 功能和数据类型允许对地理几何进行空间操作。它与 Python 生态系统很好地集成在一起,并且非常依赖 pandas、Matplotlib 和 shapely 库进行几何运算。
# Get the data from url and request it as json file
url = '[https://opendata.arcgis.com/datasets/a163c5addf2c4b7f9079f08751bd2e1a_0.geojson'](https://opendata.arcgis.com/datasets/a163c5addf2c4b7f9079f08751bd2e1a_0.geojson')
geojson = requests.get(url).json()# Read the data as GeodataFrame in Geopandas
crs = {'init': 'epsg:3851'} # Coordinate reference system (CRS) for Newzealand
gdf = gpd.GeoDataFrame.from_features(geojson['features'], crs=crs)
探索性数据分析
在新西兰,自 2000 年至 2018 年,车祸死亡总人数为 6922 人。而车祸中重伤和轻伤的总数分别达到 45044 人、205895 人。尽管该数据集记录了所有向新西兰警方报告的车祸,但我们必须考虑到并非所有车祸都向新西兰警方报告,尤其是非致命车祸。大多数撞车事故是非伤害性的,而致命性的撞车事故最少。就死亡人数而言,大多数车祸的死亡率为零。


Left — Crash severity categories. Right — Fatality count in crash accidents
这些年来,总体统计数据显示,碰撞严重程度和死亡人数有所下降,但正如您从线图中看到的那样,从 2016 年开始,死亡人数似乎有所上升。另一方面,2017 年出现了重伤和轻伤的高峰。

The crash casualty from 2000 to 2018.
道路和其他相关属性也表明了碰撞的严重程度和死亡水*。那么让我们来探讨一下它们之间的关系。就死亡人数和道路上的车道数而言,双车道似乎比其他任何数字都要高。直路似乎与死亡事故不太相关,而大多数死亡事故与某种道路弯曲有关(容易、中等和严重)。


Right: Road curvature and crash fatality. Left: Number of lanes and crash fatality
让我们看看交通法规及其与车祸严重程度和死亡率的关系。限速是探索这种关系的一个很好的措施。时速 90 公里是最致命的限速,其次是 100 公里。

Speed limit and crash fatality count
探索天气还表明,雾和强风在死亡人数方面的百分比最高。雨、雪和霜的影响也很大。


Impact of weather in crash fatalities
地理数据探索
地理数据可视化清楚地显示了冲突发生的位置。正如你可能已经预料到的,大多数车祸发生在道路上,而且大多发生在城市里。

All vehicle crash points
让我们来看看奥克兰聚集在一起的车祸。

Some Clustered crash Points in Auckland, New Zealand.
机器学习
我们可以用不同的方式处理这个问题的建模部分。我们可以将其视为一个回归问题,并根据碰撞数据集的属性预测死亡人数。我们也可以把它作为一个分类问题来处理,并根据碰撞数据集来预测碰撞的严重程度。在这个例子中,我将把它作为一个回归问题来处理。如果您想尝试一下,可以随意构建一个分类模型。基本上是同样的方法。在这种情况下,我不会进行任何特征工程,我认为我们拥有的属性足以建立一个基线,我们可以随时重新访问它,并在以后进行特征工程,以提高我们的模型准确性。
我们首先需要将分类特征转换成数值。我们可以像这样使用 Sklearn 库:
# Label encoder
from sklearn.preprocessing import LabelEncoder
lblE = LabelEncoder()
for i in df:
    if df[i].dtype == 'object':
        lblE.fit(df[i])
        df[i] = lblE.transform(df[i])
然后,我们将数据分为因变量和自变量以及训练和验证集,以便稍后评估我们的模型结果。
# Let us split our data into training and validation sets
X_train, X_test, y_train, y_test = train_test_split(df.drop('fatalCount', axis=1), df.fatalCount, test_size=0.33, random_state=42)
现在,我们准备将机器学习模型应用于我们的数据。我通常从随机森林开始,这是一种基于树的算法,在许多数据集上表现良好。
m = RandomForestRegressor(n_estimators=50)
m.fit(X_train, y_train)
print_score(m)Output:
RMSE Train:0.017368616661096157, 
RMSE Valid:0.042981327685985046, 
Accuracy Train: 0.977901052706869, 
Accuracy Valid: 0.8636075084646185
正如您所看到的,简单随机森林模型在验证集上为我们提供了 86%的准确性,经过一些初始微调和使用特征重要性选择,该模型可以提高到 87%。我们可以更进一步,在我们的模型中做一些改进,创建新的特性或者使用一些其他算法来提高模型性能,但是现在,这对于本文的目的来说已经足够了。以下是我们的随机森林模型的一些最重要的特征。

Feature Importance
结论
我希望你喜欢阅读这篇文章。如果你想尝试和试验代码,它可以作为 GitHub Gist 获得,你可以直接在 Google Colab 中打开笔记本。
你可以在推特@shakasom 上找到我。
预测与解释
以及为什么数据科学需要更多的“半贝叶斯人”

A directed acyclic graph depicting the causal pathways to foetal alcohol spectrum disorders
认知科学中的文化战争
我最*无意中发现了这场关于自然语言处理的非常有趣的辩论,这场辩论发生在几年前,辩论双方是该领域的老守卫者,被认为是现代语言学之父的诺姆·乔姆斯基和新守卫者,谷歌研究总监的彼得·诺维格。当评论这个领域的走向时,乔姆斯基说了下面的话:
“假设有人说他想取消物理系,并以正确的方式去做。“正确的”方法是将视频之外发生的事情的无数录像带,输入最大、最快的计算机,数十亿字节的数据,进行复杂的统计分析——你知道,贝叶斯这个和那个——你会得到某种关于窗外接下来会发生什么的预测。事实上,你得到的预测比物理系给出的要好得多。好吧,如果成功被定义为得到大量混乱的未分析数据的合理*似值,那么这样做比物理学家做的方法好得多,你知道,没有关于无摩擦*面的思想实验等等。但你不会得到科学一直致力于的那种理解——你得到的只是正在发生的事情的*似值。”
乔姆斯基在其他地方反复强调了这种观点:当前对自然语言处理成功的定义——即预测准确性——并不科学。将“一些巨大的文本语料库”扔进“复杂的机器”仅仅是“*似未分析的数据”,或者“蝴蝶收集”,这不会导致对语言的“真正理解”。他认为,科学的主要目标是“发现一个系统实际上如何工作的解释原则”,而实现这一目标的“正确方法”是“让理论指导数据”:通过精心设计的实验,抽象出“不相关的干扰”,研究系统的基本性质——这是自伽利略以来现代科学一直采用的方法。用他自己简洁的话来说:“只是试图处理未经分析的混乱数据不太可能让你有所作为,就像它不会让伽利略有所作为一样。”
Norvig 推测乔姆斯基对“贝叶斯这个和那个”的蔑视实际上来自于 Leo Breiman 描述的统计建模中两种文化之间的分裂:1)T2 数据建模文化,它假设自然是一个变量随机关联的黑盒子,建模者的工作是识别最适合这些潜在关联的模型;2)算法建模文化假设黑盒中的关联太复杂,无法用简单的模型来描述,建模者的工作是使用能够最好地估计输入变量输出的算法,而不期望能够理解黑盒内变量的真正潜在关联。诺维格怀疑乔姆斯基并不讨厌概率模型(数据建模文化)本身,而是讨厌带有“千万亿个参数”的算法模型,这些模型不容易解释,因此对解决“为什么”的问题没有用处。Norvig 和 Breiman 属于阵营#2,他们认为像语言这样的系统太复杂,太随机,太偶然,不能用一小组参数来表示;抽象掉复杂性类似于“制造一个精确调谐到永恒领域的神秘设备”,这是不存在的,因此“忽略了语言是什么以及它是如何工作的要点。”在另一篇论文中,Norvig 在这一点上加倍努力,他认为“我们应该停止行动,好像我们的目标是创作极其优雅的理论,而是拥抱复杂性,并利用我们最好的盟友:数据的不合理的有效性。”他指出,在语音识别、机器翻译以及机器学习对网络数据的几乎所有应用中,像“n 元模型或基于数百万特定特征的线性分类器”这样的简单模型比试图发现一般规则的复杂模型表现得更好。
这场辩论最让我着迷的不是乔姆斯基和诺维格的分歧,而是他们的共识:他们都同意,在不了解变量的情况下,用统计学习方法分析大量数据,往往会比试图模拟变量之间相互关系的理论方法产生更好的预测。我不是唯一一个被这个问题难倒的人:我与之交谈过的许多具有数学和科学背景的人也发现这相当违反直觉:最擅长建模底层结构关系的方法难道不应该也具有最强的预测能力吗?或者,如果我们不知道事物是如何运作的,我们怎么能准确地预测任何事情呢?
预测与因果推理
即使在像经济学和其他社会科学这样的学术领域,预测能力和解释能力的概念也经常被混为一谈——表现出高解释能力的模型通常被认为是高度预测的。但是构建最佳预测模型的方法与构建最佳解释模型的方法完全不同,建模决策通常会导致两个目标之间的权衡。为了说明方法上的差异,下面是“统计学习介绍”中对预测和推理建模的简短总结(ISL)
预测建模
预测模型的基本原理相对简单:使用一组容易获得的输入 X 来估计 Y。如果 X 的误差项*均为零,则可以使用以下公式来预测 Y:

其中,是 x 提供的关于 y 的系统信息,在给定 x 的情况下,这将导致ŷ(y 的预测)。只要能准确预测 y,则的精确函数形式通常无关紧要,并且被视为“黑盒”
这类模型的精度可以分解为两部分:可约误差和不可约误差:

为了提高模型的预测精度,主要目标是通过使用最合适的统计学习技术来估计,从而最小化可约误差。
推理建模
当我们的目标是了解 X 和 Y 之间的关系,即 Y 如何作为 X 的函数而变化时,就不能将ф视为“黑箱”,因为在不知道ф的函数形式的情况下,我们无法确定 X 对 Y 的影响。
几乎总是这样,参数方法被用来估计建模推理时。参数指的是这种方法如何通过假设参数形式来简化估计,并通过假设的参数来估计。这种方法有两个一般步骤:
1.对的函数形式做一个假设。最常见的假设是,在 X 中是线性的:

2.使用数据来拟合模型,即找到β₀、β₁,…,βp 的参数值,使得:

拟合模型最常用的方法是普通最小二乘法(OLS)。
灵活性/可解释性权衡
你可能已经在想:我们如何知道是否有线性形式?因为不知道真实的形式,我们实际上不知道,如果我们选择的模型离真实的太远,我们的估计就会有偏差。那么我们为什么要首先做出如此强有力的假设呢?这是因为在模型的灵活性和可解释性之间有一种内在的*衡。灵活性是指模型可以产生的形状范围,以适应许多不同的可能函数形式,因此模型越灵活,它可以产生越好的拟合,从而提高其预测准确性。但是一个更灵活的模型通常更复杂,需要更多的参数来拟合,并且对的估计经常变得太复杂,以至于任何单个预测因子的关联都是不可解释的。另一方面,线性模型中的参数相对简单且可解释,尽管它在准确预测方面做得不是很好。这里是 ISL 中的一个很好的图表,它说明了不同统计学习模型中的这种权衡:

如你所见,支持向量机和 Boosting 方法等预测精度更好的更灵活的机器学习模型在可解释性上也很低。并且通过对函数形式作出强假设以使模型更易解释,推理建模在此过程中也放弃了预测准确性。
因果识别/反事实推理
但是等等!即使你使用一个高度可解释的非常适合的模型,你仍然不能使用这些统计数据作为因果关系的独立证据。这是因为老生常谈的“相关性不是因果关系”,这里有一个简洁的例子:假设你有 100 根旗杆的长度、它们阴影的长度和太阳位置的数据。您知道阴影的长度是由极点的长度和太阳的位置引起的,但是即使您将极点的长度设置为因变量,将阴影的长度设置为自变量,您的模型仍然会得到非常好的拟合,具有统计上显著的系数,等等。这就是为什么因果推断不能仅由统计模型做出,而需要背景知识——推断的因果关系必须由一些先前对关系的理论理解来证明。因此,因果推论的数据分析和统计建模通常在很大程度上受理论模型的指导。
…即使你有坚实的理论依据来证明 X 导致 Y,确定因果关系通常仍然非常棘手。这是因为估计因果效应涉及到识别在 X 没有发生的反事实世界中会发生什么,根据定义这是不可观察的。这里有另一个简洁的例子:假设你想确定维生素 C 对健康的影响。你有关于某人是否服用维生素的数据(如果服用,X = 1;否则为 0),以及一些二元健康结果(如果健康,Y = 1;否则为 0),看起来像这样:

Y₁代表服用维生素 c 的人的健康结果,Y₀代表不服用的人的健康结果。为了确定维生素 C 对健康的影响,我们将估计*均治疗效果:
𝛉 = E(Y₁)- E(Y₀)
但是为了做到这一点,我们需要知道服用维生素 c 的人如果没有服用任何维生素 c 会有什么样的健康结果,反之亦然(或者 E(Y₀|X = 1,E(Y₁|X = 0),这在表中用星号表示,代表不可观察的反事实结果。如果没有这些输入,*均治疗效果(𝛉)无法得到一致的估计。
更糟糕的是,现在想象已经健康的人倾向于服用维生素 C,而已经不健康的人倾向于不服用。在这种情况下,即使维生素 C 实际上对健康没有任何影响,估计也会显示出强烈的治疗效果。在这里,既往健康被称为影响维生素 c 摄入和健康(x 和 y)的混杂因素,这导致对𝛉.的有偏估计
对𝛉进行一致估计的最安全方法是通过实验对治疗进行随机化,使 x 独立于 y。当随机分配治疗时,*均而言,未治疗组的结果可作为治疗组反事实结果的无偏替代,并确保没有混杂因素。A/B 测试就是在这种洞察力的指导下进行的。但是随机实验并不总是可行的(或者说是合乎伦理的,比如说,如果我们想研究吸烟或吃太多巧克力饼干的健康影响),在这些情况下,因果关系必须通过通常非随机治疗的观察数据来估计。有许多统计技术通过构建反事实结果或模拟观察数据中的随机治疗分配来识别非实验环境中的因果关系,但正如您可以想象的那样,这些类型的分析结果通常不是非常稳健或可重复的。更重要的是,这些方法障碍不是为了提高模型的预测准确性,而是通过逻辑和统计推理的结合来提供因果关系的证据。
衡量预测模型的成功也比因果模型容易得多——虽然预测模型有标准的性能指标,但评估因果模型的相对成功更具挑战性,这可能会使它们在情感上更不令人满意。但是即使因果推论很难做出,这并不意味着我们应该停止尝试。这里的要点是,预测模型和因果模型服务于非常不同的目的,需要非常不同的数据和统计建模过程,通常我们需要两者都做。这个关于电影行业的例子说明了这一点:电影工作室使用预测模型来预测票房收入,以便预测影院上映的财务结果,评估其电影投资组合的财务风险/回报等。,但预测模型对于理解电影市场的结构和动态并为投资决策提供信息不是很有用;这是因为在电影制作过程的早期阶段(通常在发行日期之前数年),当做出投资决策时,可能结果的方差非常高,因此基于早期阶段输入的预测模型的准确性大大降低。预测模型在接*影院上映日期时是最准确的,此时大多数制作决策已经做出,即当预测不再特别可行时。另一方面,因果推理模型允许工作室了解不同的生产特征如何影响生产过程早期阶段的潜在收入,因此对通知他们的生产策略至关重要。
当前对预测的过分强调——乔姆斯基有道理吗?
从定量研究文献的现状来看,不难理解为什么乔姆斯基感到不安——预测模型现在正主导着学术界和工业界。这份对学术预印本的文本分析发现,在这十年中,发展最快的定量研究领域越来越关注预测。例如,在人工智能领域,提及“预测”相关术语的论文增长了>的 2 倍,而提及“推理”相关术语的论文自 2013 年以来下降了一半。今天的数据科学课程在很大程度上忽略了因果推理方法,数据科学行业大多希望从业者专注于预测模型。即使是像 Kaggle 和网飞奖这样备受瞩目的数据科学竞赛,也总是基于提高预测性能指标。
另一方面,仍有许多领域没有对经验预测给予足够的重视,并且可以受益于机器学习和预测建模的进步。但是,将目前的事态框定为“乔姆斯基团队”和“诺维格团队”之间的文化战争似乎是一个错误的选择——我们没有理由只能选择一个,而且两种文化之间有很多相互交流的机会。有许多的工作正在进行,以使机器学习模型更具可解释性,我个人尤其对斯坦福大学的苏珊·艾希所做的工作感到兴奋,他们将机器学习技术应用于因果推理方法论(我将在接下来的几周内撰写相关文章——敬请关注!).

除了宣传朱迪亚·珀尔的作品,我想不出更好的方式来结束这篇博客,让它更完整。珀尔在 20 世纪 80 年代领导了人工智能的研究工作,允许机器使用贝叶斯网络进行概率推理,但此后成为了人工智能对概率关联的唯一关注如何阻碍进步的最大批评者。与乔姆斯基的观点相呼应, Pearl 认为“深度学习的所有令人印象深刻的成就只不过是拟合数据的曲线,”而今天的人工智能却被困在做完全相同的事情(预测和诊断/分类),这些事情机器在 30 年前就已经知道如何做了——只是稍微好一点而已——然而预测和诊断“仅仅是人类智能的尖端。”他认为,制造像人类一样思考的真正智能的机器的关键是教会机器思考因果关系,这样机器就可以提出反事实的问题,规划实验,并找到科学问题的新答案。他在过去三十年的工作重点是为机器建立一种形式语言,以使因果推理成为可能,类似于他在贝叶斯网络上的工作,使机器能够进行概率关联。在他的一篇论文中,他声称:
“人类的大部分知识是围绕因果关系而不是概率关系组织的,概率演算的语法不足以捕捉这些关系……正是因为这个原因,我认为自己只是半个贝叶斯。”
看起来数据科学会因为有更多的半贝叶斯人而受益。
用深度学习预测费西合唱团接下来会放什么歌

Phish, Hampton 2018
费西合唱团——一个标志性的现场摇滚乐队,和机器学习的世界……他们可能有什么共同点?
像绝大多数音乐艺术家的现场表演一样,对费西合唱团来说,大多数活动都是没有计划的。从乐队踏上舞台的前几天到前几个小时,没有预先确定的节目单、歌曲选择或演出持续时间。每场演出,乐队和观众都开始了一个全新的旅程,由集体能量和精湛的即兴表演推动。
我和我的朋友们多年来一直在观看费西合唱团的演出,像社区中的许多人一样,我们经常在每场演出前玩一个游戏,看谁能猜出费西合唱团的 876 首歌曲中的哪一首将在某个晚上播放。我们的游戏版本包括每个人猜演出开场,演出期间播放三首歌,以及一首安可歌曲。考虑到你(在技术上)有大约 0.11%的成功机会,如果你预测中有一个是正确的,那通常是一个非常美好的夜晚。
在工业界做了几年数据科学家后,我开始揭示隐藏在费西合唱团歌曲选择中的统计模式,并建立了一个模型来预测接下来会有什么歌曲。
方法。
我决定将这个问题设计成一个连续的多类分类任务,类似于神经语言模型——即:
"给定一系列歌曲,我能准确预测下一首将播放的歌曲吗?"
在本文接下来的部分中,我将详细介绍我的数据收集/准备过程、建模练习、结果和改进计划——让我们来看看本质。
数据。
对我来说幸运的是,在 Phish.net 有一个很棒的团队,他们积极地维护和更新一个全面的数据库和费西合唱团的公共 API,包括:表演,节目列表,场地,歌曲等等。在编写了一个 Python API 包装器(与迈克·阿兰戈合作)之后,我能够检索自 1983 年以来所有 1752 场费西合唱团秀的历史数据。

Most recent 5 shows from Phish.net API with setlist data parsed and pipe delimited
创建训练数据集
有了语言建模方法,我通过首先丢弃不完整的集列表,然后将每个集列表按时间顺序连接到一个长列表中,并对数据进行编码(876 首独特歌曲中每首歌曲的歌曲到整数,加上所有集列表标识符)来生成训练数据。维护集合列表标识符(集合 1、集合 2、Encore 等。)提供了上下文,并且将允许模型学习到某些歌曲更有可能出现在第二集的开始部分与中间部分与再唱部分。
接下来,我创建了训练样本对,即与序列中的下一首歌曲(Y)配对的歌曲列表(X)。我将单个的连接列表分割成长度为 L、的 N 个样本,其中 L 成为建模的超参数。模型需要多长的序列才能准确预测下一首歌?我测试了长度为 25、50、100、150 和 250 的序列,稍后会有更多的测试。然后,我在大约 37,000 个样本上创建了一个 80/20 的训练/验证分割,以评估我的模型。

Example of one sample training pair
建模。
虽然有许多机器学习模型可以应用于这种情况,但我选择实现一种深度学习方法,因为它在我的语言建模隐喻任务中具有最先进的性能。具体来说,我选择测试了一个具有嵌入层和 LSTM(长短期记忆)细胞的序列 RNN(递归神经网络)的几种不同配置。RNN 氏症的循环性质使得跨时间步骤的信息共享成为可能,这使得所学的知识能够以“记忆”状态在网络中持续存在。出于这个原因,这个架构非常适合学习我们的集合列表建模问题的顺序性质。我的模型的其他组件是:
- 歌曲嵌入层 — 类似于 NLP 世界中的单词嵌入…我选择为 876 个类别中的每一个类别嵌入一个 N 维向量,希望该模型将学习关于每首歌曲的潜在因素,以提供用于后续预测层的更丰富的特征集。这里的嵌入大小成为另一个可探索的超参数。稍后将对此进行更多分析。
 - LSTM 细胞——香草 RNN 细胞非常擅长学习和联想短期依赖性。如果我们的输入序列只有一个集合列表(~ 10–20 首歌曲),这是没问题的,但是因为我们需要监视和跟踪许多节目的长期依赖性,所以我们的输入序列有 50–250 首歌曲长。LSTM 单元引入了一个被称为“单元状态”的学习参数,该参数为网络提供了随时间选择性地“记住”或“忘记”重要或不重要的长期依赖性的选项。
 - 退出 —在【相对】小数据集上应用神经网络的一个常见问题是过度拟合的诅咒。我在这里提出的深度学习架构有> 300,000 个学习参数,这意味着模型很容易从它看到的训练数据中“学习太多”,而不能很好地推广到新数据。为了防止这种情况发生,我实现了退出正则化,在训练期间随机“关闭”一些神经元的激活。这种有意阻碍模型学习的方法在防止过度拟合方面非常有效。
 - 学习率探测器 —选择最佳学习率对于及时有效地训练神经网络至关重要。学习率太高,你的模型会发散;太低,你的模型将永远训练,损失很少改善。我加入了这个令人敬畏的 LR Finder Keras callback ,它绘制了几个小批量运行的学习率与损失的关系,以帮助您可视化最佳学习率。我还添加了一个*滑特性,采用指数移动*均来帮助清理视觉效果,以便于解释。最佳学习率对应于损失下降最大的——如下图绿色所示。
 

Example learning rate finder with smoothed plot (right)
- Adam 优化器 —Adam 通过结合每参数学习率(来自 AdaGrad)和动量(来自 RMSProp)的概念,改进了基本随机梯度下降(SGD)。简而言之,这种增强的优化器使您的模型能够更快地学习,并且已经成为该领域的一种“首选”技术。
 
有了这些模型和优化器组件,下面是用于实验的两种体系结构变体:
模型架构 1

Sequential model with Embedding Layer, Dropout Layer, LSTM Layer, Dropout Layer, and a Dense Layer
模型架构 2

Same model as above, but two stacked LSTM Layers for additional learned parameters
实验。
迭代 1 — “广撒网”
锁定模型组件后,我通过网格搜索以下超参数的各种设置,撒下一张大网:
- 架构:一层与两层 LSTM
 - 序列长度:模型需要多长的序列来正确学习下一首歌曲?初始设置为 25、50、100、150 和 250 首歌曲。但是请记住,这里的权衡是序列越长,可用的训练示例数量越少…
 - LSTM 单位数:我在 50 和 100 之间切换。
 - LSTM 之前辍学: 0%-70%(增量)
 - LSTM 之后的退学率: 0%-70%(递增)
 

Validation Loss vs. Epoch from four trained models (The ~100 other trained models have been hidden for interpretability)
调查结果
- 辍学是至关重要的,但不要太多。看起来大约 50%的辍学允许适当的学习而不会过度适应。
 - 正确的学习率确实能加快收敛。
 - 用一个更大的模型来解决问题并不一定有帮助。更多的参数(即层、LSTM 单位)并不一定等同于更大的学习潜力,并使模型更容易过度拟合。
 - 大约 50 的输入序列长度对于这个问题的建模是理想的。任何更短的时间,模型都无法学习某些依赖关系,任何更长的时间,模型都会失去焦点,并强调学习不太重要的长期依赖关系。
 - 许多不同的超参数设置和模型尺寸似乎集中在相同的损失水*附*,对应于大约 18%到 20% 的 。
 
迭代 2 — “嵌入深潜”
有了这些知识,我开始理解嵌入表示对我的模型的影响,看看是否有改进的空间。首先,我将嵌入向量的大小从固定长度 50 切换到 100、150、200 和 250。很明显,较大的嵌入大小对整体分类准确度有轻微的改善(约 21%),因为它允许模型为每首歌曲学习更多细微的特征。

解读
这些习得的嵌入实际上代表了什么?
为了更好地理解模型所学到的东西,我提取了嵌入,执行了主成分分析(PCA)以将它们折叠成三维,并以 3D 形式绘制它们。

3D visualization of principle components from song embeddings — contextually similar songs to “Ghost” are highlighted in yellow
正如所料,该模型已经学会了将出现在相似背景下的歌曲联系起来。上图展示了 20 首与《人鬼情未了》最相似的歌曲——费西合唱团的粉丝们可以在这里找到明显的联系。请注意它们在 PCA 向量空间中出现得有多*…
看到这些学习向量确实有改进的空间,我通过单独创建自己的歌曲嵌入扩展了这个想法。通过训练一个名为 CBOW(连续词袋)的 Word2Vec 算法,我创建了包含双向上下文和神经网络只进上下文的向量。使用这些大大改进的歌曲向量之间的余弦相似性揭示了一些真正有趣的模式。**

Six Phish songs with most similar songs (sorted by descending cosine similarity)
上图显示了一首给定的歌曲,以及 Word2Vec 模型学习到的 9 首最相似的歌曲。在这个意义上,相似性意味着歌曲出现在相同的上下文中或者在集合列表中的位置。对于知道这些歌曲的潘,你会立即认同:
- 与大卫·鲍依有关的乐观、高能的“谷仓燃烧者”
 - 像这样短小、快节奏的蓝调小曲闪耀着的光芒,在更突出的歌曲之间起到连接的作用
 - 节奏较慢、旋律不连贯的音乐
 - 老套而当之无愧的流行歌曲
 
在迁移学习的尝试中,我然后利用这些上下文丰富的嵌入作为我的神经网络嵌入层的初始化参数(而不是随机的)。在嵌入层冻结和不冻结的情况下训练网络;后者被证明更有效,允许我将 的准确度略微提高到 21.8% 。

把它包起来。
21.8%的准确率有多好?
首先,这比随机机遇好得多。非常令人惊讶的是,一个统计模型可以理解和解释我多年来内在化的一些微妙关系——特别是考虑到它对这些歌曲实际上听起来是什么样子一无所知。然而,现实情况是,模型(像我们人类一样)非常擅长学习出现在一些特定模式中的歌曲,而在其他模式中则相当糟糕。这些特殊的模式发生在歌曲出现的时候:
- 费西合唱团有几首歌曲几乎总是一首接一首地并排出现。我们的模型在很大程度上正确地处理了后续的歌曲。(例如。《麦克的歌》>《我是氢》>《weeka paug Groove》或《马》>《清晨无声》或《一扫而光》>《险峻》)
 - 作为集合开启器/闭合器
 - 作为安可
 - 当猜测是休息/再来一次的时候
 

Songs that the model performs best on (sorted by F1 Score)
改进的余地
这种建模方法的一个巨大问题是,它只关注顺序数据……这意味着它没有围绕费西合唱团的分类和抽象知识的概念。例如,该模型不识别什么是[较新的] 3.0 歌曲,因此,不理解这些歌曲与[较旧/现在较罕见的] 1.0 歌曲相比更可能现在播放。一个巨大的改进将是纳入分类数据(时代,地点,年份,专辑等)。)与集合列表序列一起输入到神经网络中。**
另一种改进方法(或至少改进相关性)是排除前 10-15 年的数据。如下所示,费西合唱团在 90 年代早期表演了他们的大部分节目(1994 年有 128 场演出!)当他们播放的独特歌曲相对较少时(今天的 850 多首中的约 375 首),这意味着大多数我们的训练数据严重偏向于学习与这 375 首歌曲相关的模式(在费西合唱团 1.0 期间)。一个很好的例子就是《冷若冰霜》>《脆皮罗茜》>《冷若冰霜》;该剧在 1992-1995 年间上演了 46 次,此后只上演了 4 次。

让事情变得更复杂的是,费西合唱团当时定期播放某些歌曲,现在很少播放了。更不用说,自费西合唱团 1.0 以来推出的新歌[并继续出现]总体上播放频率更低,因此可供学习的模式也更少。因此,这是一个很难建模的问题。
集合列表生成
使用新训练的神经网络[巧妙地命名为 TrAI],我们可以递归地进行预测,根据最*播放的 50 首歌曲的输入,生成费西合唱团的下一个曲目列表。不再赘述,以下是 TrAI 对 2019 年 11 月 29 日在罗德岛普罗维登斯举行的秋季巡回赛揭幕战的预测:

TrAI’s predicted setlist for next show in Providence, RI on November 29th 2019
这个项目使用的工具有:Python、Keras、Tensorflow、Gensim、Jupyter、Anaconda、Tableau 和 Tensorboard。所有支持代码都可以在我的 Github repo 这里找到。
感谢阅读——拿骚见!
使用大数据分析预测漫威人物是善是恶。

Marvel Universe
摘要
本文利用统计方法、数据挖掘技术和 Python 来创建超级英雄角色对齐的预测模型。
首先,我们选择要利用的数据集,然后对其进行准备、处理和分析。然后,将清洗后的数据导入数据挖掘工具;Weka,创建一个可行的预测模型,可以根据字符的描述来预测排列。然后对这个结果进行测试和讨论,以描述不同的结果。
本文假设您对 Python 和 Pandas 有一定的了解,因此不会对这些主题进行过多的讨论。如果你有任何问题,请发邮件给我,地址:【vfrantzvaag@gmail.com】。
关键词:数据挖掘、python、统计学、分析学、超级英雄
数据采集
本项目中使用的数据集是在 kaggle.com 从用户 FiveThirtyEight 处获得的,由 Kaggle 维护,增强了其可信度。(https://www . ka ggle . com/fivethirtyeight/fivethirtyeight-comic-characters-dataset)。数据集包含两个 CSV 文件和一个描述数据文件中内容的自述文件,并于 2019 年 1 月 31 日下载。尽管数据集包含 DC 和漫威的数据,但我决定只使用漫威的数据,因为它们是最受欢迎的(Statista、Finder、Boxofficemojo ),而漫威数据集包含的行数是它的 2.3 倍。此外,这些宇宙是由不同的团队创建的,这意味着我们从一个宇宙中推断出的东西可能与另一个宇宙不相关。
数据集描述
漫威数据集包含了漫威维基百科中所有记录的字符的信息,更具体地说,大约有 16400 个不同的字符。下载数据集并使用 Pandas package for Python,我可以请求列表顶部的五个元素并检查 CSV 文件的格式,还可以请求行数和列数。

Checking out the dataset using the framework Pandas for Python. (The set_option method is just for printing all the columns in the terminal)

What is outputted in the terminal after the previously written Python code.
表中的列有:page_id、name、urlslug、id、align、eye、hair、sex、GSM、alive、appearances、first appearance 和 year,它们在数据集附带的自述文件中有所描述。
数据准备
准备数据集以供使用是确保质量的关键步骤,包括减少数据中的异常和冗余。此过程的第一步是删除对最终案例没有帮助的列;基于特征预测字符对齐。这可以用正常的逻辑来完成;删除不表达特征的列。与最终案例不相关的列是:
- 
page_id: 维基百科页面的唯一标识符
 - 
Urlslug :角色的维基站点的 URL
 
GSM: 如果角色是性别或者性少数。会提供信息,但是只有 90 行的值可以用以下 python 代码进行验证:

Checking how many valid entries there are in the GSM column.
- 出场次数:漫画中的出场次数
 
——第一次出场:漫画中的第一次出场
- 年:漫画中的人物第一次出现
 
考虑到我发现这些列对我的目的来说无关紧要,我用 Python 将它们从数据集中删除。

Removing the insignificant values from the dataset.
由于这将是我的模型的训练集,因此“Align”列中必须有一个值,以便它能够使用数据进行训练,因此我删除了“Align”列中包含 NULL 的所有列,因为这不会提供任何信息。“Align”列当前有三个可能的值;好的,中立的,坏的。在这个项目中,我主要感兴趣的是弄清楚一个角色是否邪恶,并考虑到一些心理学家将“好”定义为“有移情和同情的能力”(史蒂夫·泰勒,2013),我将把“中性”和“好”列组合在一起。为了能够执行计算,为了简单起见,我还将列转换为数字;1 表示他们是邪恶的,0 表示他们是善良/中立的。

Python code for joining the neutral and good characters, as well as converting all columns to numeric values. Also calculating the amount of rows lost when dropping the null values.
现在,我可以从原始文件中减去新创建的文件中的行数,并看到通过删除“Align”列中的空值,总共丢失了 2812 行。

The outputted code for displaying how many rows we lost with the previous Python code.
现在对齐列已经准备好了,不重要的列已经被删除,我可以导入清理过的。CSV 文件导入统计工具;JMP 要做“模型检查”。我将目标变量设置为 Align,并选择其余的列作为模型效果,除了“name ”,因为它更像是一个标识列。这给了我一个整体模型测试的概述和一个效果总结。结果反映了显著性值为 0.95 的无效假设的总结,这意味着低于 0.05 的 p 值提供了足够的理由来抛弃无效假设,从而推断出另一个假设;这些属性有助于对齐。无效假设和替代假设如下所示:
H0 : β1 = β2 =… βg = 0
哈:βi ≠ 0

Here we are looking for P-values that stick out (being over 0.05). If we for example would’ve kept the attribute for the URL to the wiki site of the character, this probably would’ve given us a p-value higher than 0.05, signifying that we probably could remove that attribute.
查看汇总统计数据,可以注意到没有一个个体或整体模型的 p 值峰值超过 0.05;强调另一种假设,即有属性给出关于排列的信息,并且所有的单个属性都有贡献。
最后,我必须为我的数据挖掘工具准备文件;WEKA——一个。arff 文件是最合适的格式。由于 Weka 在解析 CSV 文件时遇到了问题,我无法使用内置转换器,只能选择外部转换器;伊利亚·库佐夫金【1】做的一个。然而,我在导入新创建的时仍然遇到了问题。arff 文件,因为在一些列中有特殊字符——我在 Sublime Text 中使用 find-all 搜索功能手动删除了这些字符。
数据分析
形象化
为了进一步了解不同的列如何影响字符的对齐,我将清理后的数据集导入到一个数据可视化工具:Tableau 中。我的主要兴趣点是比较字符特征如何影响对齐列。

Tableau dashboard comparing the characteristics to alignment. (Remember that Align = 1 is evil and Align = 0 is good/neutral.
从对齐方面来看特征之间的差异,可以看到有许多共同的元素,但在某些方面有所不同。如果我要根据这些信息构建一个“刻板印象”的角色,一个邪恶的角色将没有头发,红眼睛,是一个男性角色,有一个秘密的身份,并且已经去世——而一个好的角色将有金发,蓝眼睛,是一个女性角色,有一个公共身份并且活着。这些角色在你看来是恶是善?对我来说是的。
数据挖掘技术
现在,数据已经准备好、清理和分析完毕,我可以将它导入数据挖掘工具“Weka”来创建预测模型。我们现在进入分类领域,目的是识别一个物体属于哪一类。分类是监督学习的一种形式,我们创建一个模型,将目标变量的值设置为特征的函数(Provost & Fawcett),监督意味着我们为算法提供一个带标签的数据集进行训练。
目的是通过使用分类来预测作为特征结果的比对列,但是有大量不同的分类算法,这意味着我必须找到最适合的一个。使用 Weka 中的“分类器”栏,我可以检查不同的预设选项:

Looking into what classification algorithms Weka offers us by default.
选择正确的算法至关重要,这样才能获得最佳结果,并确保尽可能高的模型精度。通过利用由 SciKit 创建的“算法备忘单”,一个显示算法的不同前提的流程图(标有绿色),我从下面他们的网站绘制了图中的路径:

Choosing our path from the SciKit-learn algorithm cheat-sheet (marked in red).
考虑到 SVC(支持向量机)在 Weka 中试用过,但没有在训练集上运行,合理的选择是使用“朴素贝叶斯”算法。
朴素贝叶斯模型的一个明显优势是它可以很好地处理缺失值,这对于包含一些空列行的漫威数据集非常有用。(Witten 等人)朴素贝叶斯的前提之一,或者更确切地说,为什么它是“朴素的”,是因为它在变量独立的假设下运行。使用模型时必须考虑到这一点;这些列之间没有相关性,或者它们互不影响。尽管这有点无效,但考虑到这是例如头发和眼睛颜色之间已证实的相关性(Lin 等人),这只是用于模型计算,我们可以使用当前的假设来建立有效的模型。
导入被净化的。arff 文件到 Weka 中,我首先在我的训练数据集上运行朴素贝叶斯模型,不改变任何参数,并且在所有模型测试中将交叉验证设置为标准值 10,其中数据被分成 10 份;一些用于测试,一些用于训练。(Witten 等人)我主要感兴趣的 KPI 是整体模型精度(正确分类的实例),目前是 65.7%。

Summary of running a standard Naïve Bayes algorithm on my training set.
以 65.7%作为我的基准利率,我寻求提高模型的准确性。经过反复试验,我发现使用核密度估计(KDE)可以将准确率提高* 2%至 67.03 %。KDE 没有假设模型的任何特定分布,这适合于这种情况,例如,具有这种数据的标准分布可能难以实现。在我看来,追求明显更高的比例是有问题的,因为不可能根据每个角色的特征对他们进行正确的分类——一个人即使没有头发和红眼睛也可以很好。
现在我已经找到了一个成功率可以接受的合适模型,我想在我自己的一些训练数据上测试这个模型的表现如何。从原始数据集中提取 10 个字符;其中五个是“好的/中性的”,五个是“坏的”,并用“?”替换对齐列。

Taking some famous characters and labeling the alignment column ‘?’, in order to test out how well our model does in practice.
使用这个作为训练集,我在我创建的模型上重新评估它,并得到以下输出:

Summary of running our model on the ten aforementioned characters. In the predicted column (red), 1:0 tells us that the character is good and 2:1 tells us that the character is bad. The blue column tells us how certain the model is about its prediction.
在“预测”列下,所有前五个实例都被正确分类(比对为零是好的/中性的),而在后五个实例中,五个实例中有三个(60%)被正确分类,在这个小训练集中总共有 80%的实例被正确分类。还可以注意到,在“错误预测”栏下,该模型在分类“好的/中性的”字符方面比“坏的”字符更确定。其原因可能是许多“坏角色”有多重身份/人格,在做邪恶的行为时会改变形态或外表——正如下面可以看到的,两个错误分类的例子;毁灭博士和瑞雯·达克霍姆有一种“变化的眼光”:

The shifting look of the incorrectly classified instances.
讨论
根据一个人的特征来预测他的婚姻有很多伦理问题。陆荣兴等人认为,保护隐私并以道德和匿名的方式处理数据对于捍卫我们的自由是必要的。在这篇论文中,我没有预测真实的人的排列,因此没有暴露于这些法律和伦理问题。然而,如果这个模型要应用到其他地方,也就是说,如果有人要用它来预测他们刚刚遇到的人是好是坏,就必须考虑这些问题。
你可以有很多种可能性来描述一个角色,数据集中有描述超级英雄更详细的信息(力量,起源等等)。).然而,一个人必须将自己限制在一个特定的阈值,一个模型才是可行的。即使更多的信息可以导致更准确的模型,这个模型背后的主要思想是基于短暂的一瞥或谣言来预测角色的排列。过多的信息或复杂性也会导致模型从数据中捕获过多的噪声,从而导致所谓的“过度拟合”(Witten 等人)。
参考
文章
1.《票房魔咒》创下全球票房纪录,更新于 2019 年 2 月 8 日
可在https://www . box office mojo . com/all time/world/world wide openings . htm找到
2.截至 2017 年 8 月,美国公众对漫威电影和 DC 漫画电影的偏好,Statista,15.08.2017
可在:https://www . statista . com/statistics/754142/marvel-DC-movie-preference/找到
3.超级英雄统计;DC 对漫威,发现者,2017 年 11 月 16 日
可在:https://www.finder.com/superhero-statistics找到
4.预测恐怖行为的准确率超过 90%,宾厄姆顿大学,2017 年 3 月 2 日
可在:https://www . science daily . com/releases/2017/03/170302115740 . htm找到
5.预测恐怖行为的准确率超过 90%,宾厄姆顿大学,2017 年 3 月 2 日
可登陆:https://www . science daily . com/releases/2017/03/170302115740 . htm
6.中国已经开始用令人毛骨悚然的“社会信用”系统对公民进行排名,亚历山德拉·马,2018 年 4 月 8 日
7.“善”和“恶”的真正含义,史蒂夫·泰勒,2013 年 8 月 26 日
可在以下网址找到:https://www . psychologytoday . com/us/blog/out-the-darkness/2013 08/the-real-meaning-good-and-evil
文学
8.关于超级英雄的起源:从生活大爆炸到动作漫画,克里斯·加瓦勒,2015
9.对恐怖主义有效预测市场的道德分析,Dan Weijers & Jennifer Richardson,2014 年
10.业务数据科学,Provost & Fawcett,2013 年
11.头发和眼睛颜色的遗传重叠;威廉森 G;阿卜德拉维 A;巴特尔斯 M;Ehli EA 戴维斯·葛;布姆斯马·迪和霍滕加·JJ,2016 年 12 月 19 日
12.数据挖掘;实用机器学习工具和技术,Ian WittenEibe Frank & Mark Hall,2011 年
13.走向大数据时代的高效和隐私保护计算——卢荣兴;朱晖;西盟刘;刘和,2016。
R 简介—合并和过滤数据—第 1 部分
通过对 2019 年澳网男子巡回赛数据的筛选和合并进行数据理解。

Photo by Christopher Burns on Unsplash
你知道当澳大利亚网球公开赛造访墨尔本的时候是夏天,每个人都为罗杰和塞丽娜的到来而兴奋。
问题
我有兴趣预测谁可能赢得 2019 年澳大利亚网球公开赛男子巡回赛。我希望他退役前是罗杰·费德勒。
资料组
我从网站http://www.tennis-data.co.uk/data.php选择了从 2000 年到 2019 年 1 月的男子网球锦标赛历史成绩,这些成绩以 CSV 文件的形式提供。
数据字典
网球数据附带的注释解释了由网球博彩提供的数据的属性:
Key to results data:
ATP = Tournament number (men)
WTA = Tournament number (women)
Location = Venue of tournament
Tournament = Name of tournament (including sponsor if relevant)
Data = Date of match (note: prior to 2003 the date shown for all matches played in a single tournament is the start date)
Series = Name of ATP tennis series (Grand Slam, Masters, International or International Gold)
Tier = Tier (tournament ranking) of WTA tennis series.
Court = Type of court (outdoors or indoors)
Surface = Type of surface (clay, hard, carpet or grass)
Round = Round of match
Best of = Maximum number of sets playable in match
Winner = Match winner
Loser = Match loser
WRank = ATP Entry ranking of the match winner as of the start of the tournament
LRank = ATP Entry ranking of the match loser as of the start of the tournament
WPts = ATP Entry points of the match winner as of the start of the tournament
LPts = ATP Entry points of the match loser as of the start of the tournament
W1 = Number of games won in 1st set by match winner
L1 = Number of games won in 1st set by match loser
W2 = Number of games won in 2nd set by match winner
L2 = Number of games won in 2nd set by match loser
W3 = Number of games won in 3rd set by match winner
L3 = Number of games won in 3rd set by match loser
W4 = Number of games won in 4th set by match winner
L4 = Number of games won in 4th set by match loser
W5 = Number of games won in 5th set by match winner
L5 = Number of games won in 5th set by match loser
Wsets = Number of sets won by match winner
Lsets = Number of sets won by match loser
Comment = Comment on the match (Completed, won through retirement of loser, or via Walkover)
在 Mac Book Pro 中将 csv 文件合并成一个数据文件
我在 Youtube 上看到了一个来自的 Trent Jessee 的教程,它帮助我在 Macbook Pro 上将 2000 年至 2019 年的多个 csv 文件合并成一个文件。
打开终端会话,进入
cd 桌面
输入 cd 和保存 csv 文件的文件夹名称
cd CSV
用此命令合并文件
cat *。csv >合并. csv
将您的数据加载或导入 R
*# Set the working directory*
setwd("~/Desktop/ATP")
*# Read the dataframe into Rstudio as a csv file.* 
tennis_data <- read.csv("merged.csv",stringsAsFactors = FALSE, header = TRUE)
*# Review the first 5 observations*
head(tennis_data)##   ATP Location                         Tournament   Date        Series
## 1   1 Adelaide Australian Hardcourt Championships 1/3/00 International
## 2   1 Adelaide Australian Hardcourt Championships 1/3/00 International
## 3   1 Adelaide Australian Hardcourt Championships 1/3/00 International
## 4   1 Adelaide Australian Hardcourt Championships 1/3/00 International
## 5   1 Adelaide Australian Hardcourt Championships 1/3/00 International
## 6   1 Adelaide Australian Hardcourt Championships 1/3/00 International
##     Court Surface     Round Best.of       Winner          Loser WRank
## 1 Outdoor    Hard 1st Round       3   Dosedel S.    Ljubicic I.    63
## 2 Outdoor    Hard 1st Round       3   Enqvist T.     Clement A.     5
## 3 Outdoor    Hard 1st Round       3    Escude N.  Baccanello P.    40
## 4 Outdoor    Hard 1st Round       3   Federer R. Knippschild J.    65
## 5 Outdoor    Hard 1st Round       3  Fromberg R.  Woodbridge T.    81
## 6 Outdoor    Hard 1st Round       3 Gambill J.M.     Arthurs W.    58
##   LRank W1 L1 W2 L2 W3 L3 W4 L4 W5 L5 Wsets Lsets   Comment X X.1 X.2 X.3
## 1    77  6  4  6  2 NA NA NA NA NA NA     2     0 Completed              
## 2    56  6  3  6  3 NA NA NA NA NA NA     2     0 Completed              
## 3   655  6  7  7  5  6  3 NA NA NA NA     2     1 Completed              
## 4    87  6  1  6  4 NA NA NA NA NA NA     2     0 Completed              
## 5   198  7  6  5  7  6  4 NA NA NA NA     2     1 Completed              
## 6   105  3  6  7  6  6  4 NA NA NA NA     2     1 Completed
根据 2000 年至 2019 年的数据预测谁将赢得 2019 年澳大利亚网球公开赛
加载包
图书馆(dplyr)
设置工作目录
setwd(" ~/桌面/ATP ")
将数据帧作为 csv 文件读入 Rstudio。
tennis _ data
回顾前 5 条观察结果。最佳实践是使用 tail()来查看最后 5 次观察。
主管(网球 _ 数据)
查看合并数据的结构
在 R 中,我们可以探索数据的结构,检查数据的属性,在预处理之前观察原始数据。
str(网球 _ 数据)
在合并的数据文件中有 52383 行和 83 列。
## 'data.frame':    52383 obs. of  83 variables:
##  $ ATP       : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Location  : chr  "Adelaide" "Adelaide" "Adelaide" "Adelaide" ...
##  $ Tournament: chr  "Australian Hardcourt Championships" "Australian Hardcourt Championships" "Australian Hardcourt Championships" "Australian Hardcourt Championships" ...
##  $ Date      : chr  "1/3/00" "1/3/00" "1/3/00" "1/3/00" ...
##  $ Series    : chr  "International" "International" "International" "International" ...
##  $ Court     : chr  "Outdoor" "Outdoor" "Outdoor" "Outdoor" ...
##  $ Surface   : chr  "Hard" "Hard" "Hard" "Hard" ...
##  $ Round     : chr  "1st Round" "1st Round" "1st Round" "1st Round" ...
##  $ Best.of   : int  3 3 3 3 3 3 3 3 3 3 ...
##  $ Winner    : chr  "Dosedel S." "Enqvist T." "Escude N." "Federer R." ...
##  $ Loser     : chr  "Ljubicic I." "Clement A." "Baccanello P." "Knippschild J." ...
##  $ WRank     : chr  "63" "5" "40" "65" ...
##  $ LRank     : chr  "77" "56" "655" "87" ...
##  $ W1        : chr  "6" "6" "6" "6" ...
##  $ L1        : chr  "4" "3" "7" "1" ...
##  $ W2        : int  6 6 7 6 5 7 6 7 2 6 ...
##  $ L2        : int  2 3 5 4 7 6 1 6 6 7 ...
##  $ W3        : int  NA NA 6 NA 6 6 NA NA 6 6 ...
##  $ L3        : int  NA NA 3 NA 4 4 NA NA 1 4 ...
##  $ W4        : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ L4        : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ W5        : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ L5        : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ Wsets     : int  2 2 2 2 2 2 2 2 2 2 ...
##  $ Lsets     : int  0 0 1 0 1 1 0 0 1 1 ...
##  $ Comment   : chr  "Completed" "Completed" "Completed" "Completed" ...
数据框的尺寸
数据帧的尺寸包括-52383 行和 83 列。
dim(网球 _ 数据)
检查是否有丢失的值
有相当多的缺失值。评估后可能需要对缺失值进行插补。
is.na(网球 _ 数据)
过滤并子集化 R 中的数据
我需要过滤我的数据,以便更易于管理,我对分析 2000 年至 2019 年的澳大利亚网球公开赛很感兴趣。
我们只想查看结果数据的前 26 列
姓名(网球 _ 数据)[1:26]
我们想要过滤澳大利亚网球公开赛的数据,以便我们可以使用数据的子集:
aust _ Open
查看仅与澳大利亚网球公开赛相关的数据子集的结构:
str(aust_open)
## 'data.frame':    2413 obs. of  26 variables:
##  $ ATP       : int  6 6 6 6 6 6 6 6 6 6 ...
##  $ Location  : chr  "Melbourne" "Melbourne" "Melbourne" "Melbourne" ...
##  $ Tournament: chr  "Australian Open" "Australian Open" "Australian Open" "Australian Open" ...
##  $ Date      : chr  "1/17/00" "1/17/00" "1/17/00" "1/17/00" ...
##  $ Series    : chr  "Grand Slam" "Grand Slam" "Grand Slam" "Grand Slam" ...
##  $ Court     : chr  "Outdoor" "Outdoor" "Outdoor" "Outdoor" ...
##  $ Surface   : chr  "Hard" "Hard" "Hard" "Hard" ...
##  $ Round     : chr  "1st Round" "1st Round" "1st Round" "1st Round" ...
##  $ Best.of   : int  5 5 5 5 5 5 5 5 5 5 ...
##  $ Winner    : chr  "Agassi A." "Alami K." "Arazi H." "Behrend T." ...
##  $ Loser     : chr  "Puerta M." "Manta L." "Alonso J." "Meligeni F." ...
##  $ WRank     : chr  "1" "35" "41" "106" ...
##  $ LRank     : chr  "112" "107" "111" "28" ...
##  $ W1        : chr  "6" "6" "6" "6" ...
##  $ L1        : chr  "2" "4" "3" "2" ...
##  $ W2        : int  6 7 7 4 6 6 6 6 6 5 ...
##  $ L2        : int  2 6 6 6 4 1 1 4 4 7 ...
##  $ W3        : int  6 7 6 6 6 6 6 NA 6 6 ...
##  $ L3        : int  3 5 2 7 4 4 4 NA 4 3 ...
##  $ W4        : int  NA NA NA 6 0 NA 7 NA NA 7 ...
##  $ L4        : int  NA NA NA 3 6 NA 6 NA NA 5 ...
##  $ W5        : int  NA NA NA 6 6 NA NA NA NA NA ...
##  $ L5        : int  NA NA NA 0 4 NA NA NA NA NA ...
##  $ Wsets     : int  3 3 3 3 3 3 3 2 3 3 ...
##  $ Lsets     : int  0 0 0 2 2 0 1 0 0 1 ...
##  $ Comment   : chr  "Completed" "Completed" "Completed" "Completed" ...
编写并导出您的数据框架
现在,我对仅包含澳大利亚公开赛的数据感到满意,我将编写文件并将其导出为 csv 文件,这样我就可以用它来预处理我的数据以及在 R 和 Tableau 中可视化数据。
*# Save the dataframe to a csv file to write the csv file into R working folder:*write.csv(aust_open,file = "aust_open.csv", row.names = FALSE)
我的下一篇文章将包括:
- 预处理 R 中的数据
 - R 中的数据可视化,查看数据的样子
 - R 中数据的探索性数据分析
 - 缺失数据的处理
 
感谢阅读,敬请关注,编码快乐!
在泰坦尼克号数据集上预测谁将幸存
有志和初学者数据科学家的权威指南
您的首次数据科学之旅、探索性数据分析(EDA)和 Kaggle 提交的全面指南

Source: KWMP
上船啦!与泰坦尼克号一起开始您的数据之旅
欢迎来到数据科学 SS。我叫 Vincent,希望您会喜欢我们的数据科学首次旅程。今天,我们将和逝去的战友泰坦尼克号一起在大西洋中航行。我们要去仔细探索数据冰山,航行机器学习大海,准备有见地的下船。希望你和我以及数据科学 SS 一路顺风。
欢迎光临!!本文的目的是通过著名的 Kaggle Challenge 新手挑战赛——“泰坦尼克号:灾难中的机器学习”,来激起你对数据科学的兴趣
在这篇文章中,你将开始你的第一次探索性数据分析(EDA)和机器学习,以预测泰坦尼克号乘客的存活率。对于大多数入职数据科学家来说,这是一个创世纪的挑战,它将帮助你走向成功。希望这篇文章对你有所启发。上船啦!!
技术先决条件
我们将使用 Jupyter Notebook 和几个数据科学 Python 库。如果你还没有安装 Anaconda 在你的 Windows 或者 Mac 上。或者,您可以关注我的笔记本并享受这个指南!
台阶
对于大多数初学者来说。不要担心,我将指导您完成这篇文章,进行端到端的数据分析。以下是今天要探索的几个里程碑:

What we are going to learn
咻,离我们到达第一个目的地还有很长的一段路。我们开船吧,好吗?
导入

Importing Library. Source: unsplash
导入库
Python 库是一个函数和方法的集合,允许你在不写代码的情况下执行许多动作(Quora)。这将有助于您轻松运行几个数据科学功能。如果没有这个库,可以在命令提示符下运行pip install <library name>来安装。
这是我们正在使用的库列表:
- Numpy :多维数组和矩阵表示库
 - 熊猫:数据帧的 Python 数据分析库,CSV 文件 I/O
 - Matplotlib :数据可视化库
 - Seaborn :构建在 Matplotlib 之上的数据可视化库。这给了你一个更清晰的可视化和更容易调用的界面。
 
**import** **numpy** **as** **np** 
**import** **pandas** **as** **pd** 
**import** **seaborn** **as** **sns**
**import** **matplotlib.pyplot** **as** **plt**
导入数据
我们可以用熊猫从泰坦尼克号数据页读取 train.csv。这段代码将创建一个 DataFrame 对象,它是一个二维数组,用于优化数据浏览过程。可以把它想象成 Python 中包含行和列的 Excelsheet。
maindf = pd.read_csv(‘dataset/Titanic/train.csv’)
探索数据
头部()或尾部()
我们将从查看数据中的前几行开始。这是为了先睹为快,确保正确提取数据。
maindf.head()

Data Frame Head
描述()
describe 将帮助你得到所有统计数字列的描述。如果将include 参数写成 object,它将描述非数字列。这是一种非常有用的方法,可以快速了解统计数据。

Describe() to explore Titanic Data
从这段描述中,我们可以找到以下思路:
- 变量的均值和分布。
 - 大多数乘客以相对较低的价格买了票。但是,有一些是高价购买的,这表明可能是贵宾。
 - 由于四分位数表示 0,最大值表示 6,因此帕奇分布高度偏斜。这意味着大多数人不带父母或孩子上船,少数父母带多达 6 个孩子和父母上船。
 
信息()
这些信息帮助您确定数据类型和空值的存在。这里我们发现年龄、舱位、上船栏目有缺失值。

这很好,我们已经确定了一些探索的途径。但首先,让我们清理数据。
干净的

Source: Unsplash
处理年龄中缺失的值
有几种方法可以替换年龄列中缺失的值:
- 不推荐:用年龄*均值代替。这不是一个好方法,因为你可以看到大多数乘客年龄在 20-30 岁之间,其中最大的 80 岁,最小的 0.42 岁(婴儿)。
 - 推荐:替换为年龄中位数。这将是一个更好的方法,因为这将安全地将我们缺失的值分配到 20-30 岁,这是四分位数范围内的舒适值。
 - 最推荐:根据每个称呼的中位数替换年龄。这将是最好的方法,因为称呼将暗示估算数据中的共同年龄(例如:Sir、Mdm 等)。
 
结论:让我们采取第三种方法。如果你不知道lambda 是什么,你可以把它想成一个内联函数。这使得代码更容易阅读。
maindf['Salutation'] = maindf.Name.apply(lambda name: group = maindf.groupby(['Salutation', 'Pclass'])
group.Age.apply(lambda x: x.fillna(x.median()))
maindf.Age.fillna(maindf.Age.median, inplace = True)
删除不相关的列
为了简化分析,让我们删除一些可能与生存无关的列,比如乘客 id 和姓名。
但是,删除这些列时应该非常小心,因为这会限制您的假设。例如,名字为“约翰”的乘客生还的概率可能会高得惊人。仔细观察,这是因为“约翰”这个名字通常是为那些社会经济地位高的英国人保留的。因此,如果我们没有 SES 列,我们可能需要在分析中包含名称。
cleandf = maindf.loc[:,['Survived','Pclass','Sex','Age','SibSp','Parch','Embarked']]
设计功能
在这一部分,我们将对一些特征(列)进行处理,以进行合理且更有意义的数据分析。
社会经济状况
我们将根据 Pclass 中的数值对 SES 特征进行分类。我们只编码 1——上,2——中,3——下。
cleandf['socioeconomicstatus']=cleandf.Pclass.map({1:'upper',2:'middle',3:'lower'})
启航港口
我们将把字母值(' C ',' Q '和' S ')映射到它们各自的端口。然后,我们可以根据乘客的出发港口和生存状况来划分乘客的数量。我们将使用饼图来比较基于启运港和生存状态的百分比。
cleandf['embarkedport']=cleandf.Embarked.map({'C':'Cherbourg','Q':'Queenstown','S':'Southampton'})

Ratios of survivals based on Port of Embarkation
年龄
我们将生成年龄直方图,并得出以下宁滨。宁滨是一种将连续数据的偏斜分布量化为离散类别的好方法。每个条柱代表分组数值的范围和强度程度。
agesplit = [0,10,18,25,40,90]
agestatus = ['Adolescent','Teenager','Young Adult','Adult','Elder']
cleandf['agegroup']=pd.cut(cleandf.Age,agesplit,labels=agestatus)

binned Age based on Age Split and Age Status Group
家庭关系
然而,救生艇仍然漂浮着,因此“伯肯黑德演习”的传说诞生了——这是一项在海上灾难中优先考虑妇女和儿童的协议。—历史
伯肯黑德演习引发了一些思考,你的孩子或妻子的存在是否会提高你的存活率。因此,我们希望将船上的兄弟姐妹/配偶(SibSp)和父母/子女(Parch)的数量设计成每个人是否都有家庭成员— hasfamily。
cleandf['familymembers']=cleandf.SibSp+cleandf.Parch
hasfamily = (cleandf.familymembers>0)*1
cleandf['hasfamily'] = hasfamily
结果呢

The result of feature engineering
恭喜你。你已经完成了你的特征工程。现在我们可以用这些新的特征来分析
分析
有如此多的分析,我们可以使用新的清理数据集。现在,让我们回答几个问题。请随意访问我的 Python 笔记本获取更多分析。
- 存活率会因性别而异吗?
 - 生存率会因 SES 而不同吗?
 - 存活率会因性别和社会经济地位而不同吗?
 
给数据科学家一个小提示,你的角色是不断提问并以统计学的方式回答问题。这不会是一个一次性的瀑布过程,而是一个持续的迭代过程。正如我要说的…
这只是冰山一角!
存活率会因性别而异吗?
maindf.groupby(['Survived','Sex']).count().Name
maindf.groupby(['Survived','Sex']).count().Name.plot(kind='bar')

总共有 342 人幸存,549 人死亡。幸存者中(233 名女性,109 名男性),而非幸存者中(81 名女性,468 名男性)。似乎雌性比雄性更有可能存活。
生存率会因 SES 而不同吗?
我们可以使用交叉选项卡清楚地生成两个分类特征(SES,survival)的计数
survived = pd.crosstab(index=cleandf.Survived, columns = cleandf.socioeconomicstatus,margins=True)
survived.columns = ['lower','middle','upper','rowtotal']
survived.index = ['died','survived','coltotal']


The Counts and Percentage of Survived and Died Passengers
快速浏览一下,似乎社会经济地位对幸存者非常重要——上层阶级比下层阶级生存得更久。然而,让我们用卡方方法进一步检验这个假设。

Chi square run on the cross tab
让我们试着理解这意味着什么。Chi2 统计量是卡方统计量,自由度是列*行。这意味着你有 6 个自由度,包括 3 个 SES 事件(下、中、上)和 2 个生存事件(死亡、幸存)。自由度越大,差异的统计意义就越大。
p 值将决定 SES 对生存的重要性。如果我们的 p 值低于α(0.01),我们将拒绝我们的零假设。因为我们的 p 值是 6.25,远远高于我们的 alpha 值,所以我们可以说这个结果没有统计学意义。
也许我们可以把性包括进来,观察是否有显著的差异?
存活率会因社会经济地位和性别而不同吗?
这个交叉表允许我们为总共 6 个可能的事件生成一个特征(SES,Sex)。与男性低社会经济地位者相比,女性高社会经济地位者的存活率似乎有很大差异。
survivedcrosstabsex = pd.crosstab(index=cleandf.Survived, columns = [cleandf[‘socioeconomicstatus’],cleandf[‘Sex’]],margins=True)


让我们做和以前一样的事情,在 Chi2 测试中插入这个值的交叉表

Chi square run on the cross tab (SES and Sex)
p 值更低,这表明它比我们仅使用 SES 进行分析具有更大的统计学意义。但是,p 值仍然高于我们的 alpha (0.01)。因此我们仍然认为 SES 和性别对推断生存状态没有统计学意义。但是我们可以看到它接*统计意义,这是一个好现象!
现在,我们可以用我们的机器学习模型来探索这些功能:)。
模型
训练决策树模型
让我们用决策树来模拟我们的发现。决策树是一种机器学习模型,它根据信息增益提供基于规则的分类。这提供了一种选择关键特征和规则来最好地辨别我们的数据因变量的好的和圆滑的方法。
我们将使用我们的训练数据,然后修剪树木,以避免过度拟合。最后,我们将使用 GraphViz 库将我们的树可视化如下。由于代码很长,请随意浏览我的 Python 笔记本。

Decision Tree for Titanic Kaggle Challenge
从这个图中,我们可以发现决策树的美妙之处如下:
- 了解幸存者分布及概况:数组表示【死亡人数,存活人数】。在每个节点中,我们可以看到阵列和规则分类的不同拆分,以便分支到更低级别的节点。我们可以发现,如果性别=女性(≤0.5),数组表示更多的幸存者[69,184]。我们也可以跟踪叶级节点。
 - 了解关键特征可以区分幸存者:在顶级特征中,我们将性别和社会经济地位视为主要特征。然而,正如我们之前所发现的,这些特征本身不足以具有统计学意义。因此,也许第三级的起运港和年龄组可能给我们更好的意义。
 
恭喜你,你刚刚创建了你的第一个机器学习模型!
决策树的评估
**from** **sklearn.metrics** **import** accuracy_score, log_loss
train_predictions = clftree.predict(X_test)
acc = accuracy_score(y_test, train_predictions)
从这里我们将检索到我们的准确率是 77.65%。这意味着在 100 名乘客中,该模型可以正确回答 77 名乘客的生存状态。
为了进一步评估这个模型,我们可以将混淆矩阵和 ROC 曲线添加到我们的评估中,我将在随后的文章中详细介绍。
使服从
您将使用以下方法和命令生成预测的 csv。我们将其命名为“titanic _ submission _ tree . CSV”并保存在您的本地目录中。
def titanic_kaggle_submission(filename, predictions):
 submission = pd.DataFrame({‘PassengerId’:testdf[‘PassengerId’],’Survived’:predictions})
 submission.to_csv(filename,index=False)titanic_kaggle_submission("titanic_submission_tree.csv",predictions_tree)
一旦你提交了titanic _ submission _ tree . CSV .你会收到如下结果。在这里,我得到了所有相关条目中的排名 6535。

我们如何改进我们的分析?
- 超参数调谐和模型选择。使用梯度下降增加提交分析。还有其他提交的大量利用集合模型,如随机森林和 XG Boost 。
 - 特征工程:找出可能产生的其他特征。例如,也许有孩子的父母被拯救的可能性更小。或者,拥有早期字母的人可能会首先被保存,因为他们的房间分配是根据机票类型和字母顺序排序的?基于问题创建我们的特征将进一步提高我们分析的准确性。
 - 实验,实验,实验:享受乐趣,不断调整你的发现。在这个挑战中,没有什么想法是荒谬的!
 
恭喜你。您已经提交了您的第一份数据分析和 Kaggle 提交。现在,开始您自己的数据科学之旅吧!!
结论
在本文中,我们学习了一种在著名的泰坦尼克号数据上设计探索性数据分析(EDA)的方法。我们学习了如何导入、探索、清理、设计、分析、建模和提交。
除此之外,我们还学到了有用的技术:
- 探索 →描述、绘图、直方图
 - 清除 →插入缺失的数值,删除不相关的列
 - 工程师→宁滨,贴标签
 - 分析 →存活图、交叉表、Chi2 检验
 - 模型 →决策树可视化、预测和评估
 
最后…

Source : Unsplash
我真的希望这是一本很棒的读物,是你发展和创新的灵感来源。
请在下面评论出来建议和反馈。就像你一样,我也在学习如何成为一名更好的数据科学家和工程师。请帮助我改进,以便我可以在后续的文章发布中更好地帮助您。
谢谢大家,编码快乐:)
关于作者
Vincent Tatan 是一名数据和技术爱好者,拥有在 Visa Inc .和 Lazada 实施微服务架构、商业智能和分析管道项目的相关工作经验。
Vincent 是土生土长的印度尼西亚人,在解决问题方面成绩斐然,擅长全栈开发、数据分析和战略规划。
他一直积极咨询 SMU BI & Analytics Club,指导来自不同背景的有抱负的数据科学家和工程师,并为企业开发他们的产品开放他的专业知识。
请通过LinkedIn、Medium或 Youtube 频道 联系文森特
用神经网络预测温布尔登。
神经网络预测诺瓦克·德约科维奇将在决赛中击败罗杰·费德勒成为最终的冠军。

随着第二周的 温布尔登 即将来临,有许多激动人心的比赛值得期待。温布尔登网球公开赛第二周的周一可以说是全年最激动人心的一天。周一,16 名最优秀的男女网球运动员将在温布尔登网球公开赛四分之一决赛中争夺一席之地。将会有很多体育评论员和分析家预测谁会进入 8 强,4 强,并最终成为冠军。
然而,我还没有遇到任何使用机器学习/人工智能做出的预测。因此,我认为这将是一个很好的机会,让我实施我一直在学习的一些机器学习技能,以预测温布尔登第二周的比赛。更具体地说,我将实现一个简单的2-隐层神经网络来预测比赛的结果。
我如何得出我的预测:
- 第一步:创建可以帮助预测比赛获胜者的特征。
 - 步骤 2:使用 Keras 建立、验证和微调模型神经网络,并检查过拟合/损失函数/测试精度。
 - 第三步:做预测
 
步骤 1:创建特征:
神经网络或任何预测模型最重要的部分之一是创建能够解释结果变量的特征。像选手排名、整体胜率、草地胜率这样的特征将在很大程度上帮助解释一场网球比赛的结果。此外,根据过去 52 周的胜率和单挑记录捕捉到的玩家状态可以进一步帮助预测结果。总的来说,我创建了 21 个特征作为神经网络的输入层,下面是我认为最重要的 5 个特征。
- 排名。
 - 匹配胜率。
 - 在草地上头对头。
 - 过去 60 周在草地上的比赛胜率。
 - 五局三胜的百分比。
 
注意:对于每个特征,我计算两个玩家之间的差异。例如排名=(玩家 0 的排名)——(玩家 1 的排名)。
第二步:建立并微调神经网络。
在我描述神经网络的实现之前,下面是带有特征的数据的一个片段。

Training Sample Snippet
我的数据由 2010 年到 2018 年的所有温网比赛组成。为了使事情更简单,可读性更强,我总是把排名较高的玩家作为 0 号玩家,排名较低的玩家作为 1 号玩家。因此,结果 0 表示玩家 0 赢了(不是一次翻盘),结果 1 表示玩家 1 赢了(一次翻盘)。
接下来,我将我的数据分为训练和测试(dev)数据,以便根据训练数据优化神经网络,并在样本测试数据上验证它。下面的代码构建了神经网络。
下面是神经网络的一些细节。
`- Number of Layers: 3. (2 Hidden Layers)
- Number of Neuros in each layer: 64->32->1
 - Activation relu->relu->sigmoid
 - Stop if validation loss does not improve for 500 epochs
 - Save the best model which gives the minimum validation set loss`
 
这里需要注意的一件重要事情是,经过下图所示的几轮时期后,神经网络开始过度拟合训练样本。即,它在训练样本上获得了准确性,同时对于测试样本失去了准确性。因此,为了做出好的预测,避免使用过度拟合的神经网络是很重要的。因此,我使用给出最小验证集损失的模型。

Loss and accuracy level after each Epoch
在测试和训练集上,最好的模型具有下面的准确度水*,作为预测网球比赛的基准,这似乎是相当合理的。

第三步:预测结果。
一旦我有了一个训练好的神经网络并保存了最佳模型。我可以使用最佳模型来预测即将到来的比赛。以下是从第 16 轮开始以表格和括号格式对预定和潜在比赛的预测片段。

Final prediction table and bracket.
总决赛感想:
神经网络预测诺瓦克·德约科维奇将在决赛中击败罗杰·费德勒成为最终的冠军。根据模式,最接*的比赛将是费德勒和纳达尔在半决赛中的对决。考虑到这一点,根据模型,如果德约科维奇在决赛中对阵费德勒,他有 70%的胜算,而如果他在决赛中对阵纳达尔,他有 59%的胜算。
我会在所有比赛结束后更新这篇文章,看看这个模型的表现如何。然而,这篇文章的重点是而不是建立一个给出最准确预测的神经网络,而是这篇文章的重点是探索神经网络和其他机器学习技术可以帮助使用数据回答简单问题的方法。这篇文章的问题是“今年谁会赢得温布尔登网球赛?”
本文使用的代码和数据可以在下面的 github 资源库中找到。包含模型和结果的最终笔记本可通过 链接 查看。如果你有任何建议,请随时联系我。(github.com/jugalm)
预测温布尔登比赛:。通过在…上创建一个帐户,为 jugalm/predicting-Wimbledon-matches 的发展做出贡献
github.com](https://github.com/jugalm/predicting-wimbledon-matches)
参考文献:
- 数据:http://www.tennis-data.co.uk/alldata.php
 - 康曼、安德烈、格兰特·斯佩尔曼和丹尼尔·赖特。"用于职业网球比赛预测和投注的机器学习."
 
使用文本评论预测葡萄酒质量

As someone who doesn’t drink a lot of wine, I usually rely on the 100 point Wine Scale and the purple “Staff Recommended” sticker to pick something off the shelf
我将使用这个 Kaggle 数据集,其中包含葡萄酒评论、葡萄酒评级(以分数衡量)以及从葡萄酒爱好者那里收集的其他相关信息。
数据集包含两个在不同日期抓取的文件。我将使用文件wine mag-data _ first 150k . CSV作为训练集,使用 winemag-data-130k-v2.csv (从稍后的日期抓取)作为测试集。
这里是代码的库。
目的:训练一个基于文本评论预测葡萄酒质量的机器学习模型
葡萄酒爱好者使用从 1 到 100 的评分标准来给他们的葡萄酒打分(1 代表最差,100 代表最好)。不幸的是,该网站只发布积极的评论,这就是为什么数据集中的分数范围只有 80 到 100。
这意味着我们的数据集不能代表我们试图解决的问题。使用这些数据建立的任何模型只适用于广受好评的葡萄酒。
收集一些领域知识
在我们开始分析之前,我们应该尝试收集一些领域知识。在浏览了网站和阅读了其他一些与葡萄酒相关的资源后,我发现了一个基于积分系统的漂亮的分类系统。

对于最终用户(即葡萄酒购买者),积分的重要性只取决于它们传达的信息。如果我们把这个问题作为一个分类问题,我们可以保留葡萄酒质量的必要信息,同时减少问题的维度。
决策:我将把这个问题框定为一个情绪分析问题,在这个问题中,评论将被用来确定葡萄酒是经典、卓越、优秀、非常好、好还是可以接受
探索性数据分析
下一步是更好地了解我们的数据。这可以给我们更好地解决问题提供重要的见解。除了评论和评级,还有其他相关信息,如葡萄酒价格、品种(葡萄类型)和葡萄酒产地。

Preview of our data
如果我们想建立一个更全面的模型,我们也可以将这些特征作为预测因素来确定葡萄酒的质量。要将文本描述与其他预测特征相结合,我们可以创建一个集成模型(文本分类器是其中之一)或一个分层模型,其中文本分类器的结果将用作一个预测变量。
出于这里的目的,我们将只探讨评论和葡萄酒评分之间的关系。
从高层次检查数据完整性
“点和描述”列中没有缺失条目。正如我们之前已经注意到的,葡萄酒点向右移动。从我个人的经验来看,价格也是向右偏移的。

Output from data.describe()

Output from data.info()
检查文本数据
评论看起来很“干净”。似乎没有任何语法或拼写错误,所有的评论都是用非常简洁的语言写的。
样本审查:
This tremendous 100% varietal wine hails from Oakville and was aged over three years in oak. Juicy red-cherry fruit and a compelling hint of caramel greet the palate, framed by elegant, fine tannins and a subtle minty tone in the background. Balanced and rewarding from start to finish, it has years ahead of it to develop further nuance. Enjoy 2022–2030.
有些评论需要葡萄酒知识才能完全理解。在上面的例子中,单宁是一个文本元素,使葡萄酒尝起来很干。
我们还可以看看最常见的词汇出现的频率。

the most commonly occurring word is “wine” which occurs just over 0.025% of the time
准备分类
以前,我们将我们的类标识如下:
我们可以通过分数将评论映射到我们的一个类。
不幸的是,我们的数据不是很*衡。
第 4 类没有评论(94-97 分—极好),大多数评论集中在第 1、2 和 3 类。不*衡的类是有问题的,但是可以通过对较大的类进行采样或设置类权重来解决。然而,一门课的完全缺席更令人担忧。
决定:我将把 4 班和 5 班合并成新的 4 班。任何在 94-100 分范围内的评论都属于这个类别。
应该清理文本数据吗?
我们也可以选择清理/规范我们的葡萄酒评论。影响这个决定的最大因素是我们想要使用的学习算法的类型。如果我们选择将每个评论作为自己的向量嵌入,并将输入传递给一对一的分类器,那么我们应该花更多的时间来规范化文本。另一方面,将文本作为许多向量的表示进行顺序处理使得规范化变得不那么重要。
顺序处理文本(通常每个单词由其自己的向量表示,并学习单词关系)也有助于解决(同一单词拥有多个含义)和识别 同义词 。由于这些评论使用非常具体的行话分享非常相似的上下文,我不太关心词义歧义或同义词。但考虑到评论的总体积极情绪,我担心一对一的分类器可能无法找出相邻类别之间的细微差异。
决定:我将使用一个递归神经网络,通过将每次复习作为一个向量序列来预测课程。我还将保持文本描述的原始形式。
很难说这种选择是否比使用诸如 TF-IDF 这样的嵌入技术并将其传递给一对一的分类器更好。也许将来我也会尝试这样做,并比较结果。
嵌入文本
将每个单词作为其自己的向量嵌入的自然选择是使用基于神经的嵌入技术,如 word2vec、GloVe 或 fastText。我们也可以选择训练我们自己的嵌入模型或者使用预先训练的向量。由于我们正在处理的文本没有什么特别之处,使用预先训练的单词向量可能会帮助我们更好地理解语言。
决定:我们将使用预先训练的单词嵌入。
但是我们应该使用哪一类嵌入呢?我将立即消除 fastText,因为它通过对字符 n-gram 级别的向量求和来构建单词向量。因为我们正在处理的文本类型不太可能包含词汇以外的单词(没有拼写错误、不常见的俚语或缩写),所以它不会受益于这种粒度。
即便如此,通常也很难确定哪种技术效果最好。由于我发现一些葡萄酒的描述在本质上是相似的,我将选择 GloVe,希望从共现结构中学习将有助于更好地理解语义比较。
决策:我们将使用预先训练的手套向量
几个预先训练好的手套词向量可以在这里下载。我将使用带有 840B 令牌的普通爬网,因为它包含最大的词汇表,并且区分大小写。glove.840B.300d 中的每个单词向量有 300 个坐标。
在加载预训练的嵌入之前,我们应该定义一些固定的参数。
Num_classes: 自我说明——这是我们正在处理的类的数量
**嵌入 _ 尺寸:这是单词向量的尺寸
**时期:通过所有训练示例的向前和向后次数
batch_size: 每一遍的训练样本数
max_len: 文本描述中考虑的最大长度(以字为单位)。任何超过 100 字的描述都将被截断。任何少于 100 字的描述都将被填充以满足该长度。
class_weights: 我们之前观察到我们的类不是很*衡。具有较高权重的类(类 0 和类 4)将对学习算法产生较大影响。类别 0 的每个实例被视为 7 个实例。
关于选择 max_len 的注意:捕获太少的单词会导致信息丢失,但是捕获太多会导致数据稀疏的问题。理想情况下,我们希望选择一个值,该值能够捕获大多数文本描述的整体,而不会引入太多的零序列。
加载所需的库:
我们还必须对目标类进行一次性编码。
训练-验证分割
即使我们已经有了一个指定的测试集,出于参数调整的目的,将训练集分为训练集和验证集仍然是一个好主意。
标记输入并准备嵌入矩阵
我将使用 Keras 的 text_to_sequences 方法来保存文本的单词序列。每个单词将被映射到其来自预训练单词向量的向量。任何小于 100 (max_len)字的描述都将被填充,任何超过 100 (max_len)字的描述都将被截断,以便输入具有相同的长度。
在文本中找到的没有出现在预训练单词向量的词汇表中的单词被初始化为零向量。
注意:如果有很多单词在词汇表之外,那么设计一种更智能的方法来初始化这些单词可能是值得的
训练分类器
由于文字描述通常很短,我将使用 GRU 单位,而不是 LSTM 单位。有了更短的描述,我们对记忆单元的需求就更少了,并且可以从 GRU 更高效的学习算法中受益。
我还将利用早期停止,它(在这种情况下)使用验证准确性来确定我们是否应该继续训练网络。当验证准确性在几个时期内持续下降时,提前停止将会启动并结束训练过程。它还会将最佳权重保存为“检查点”(在本例中为 model.h5),并在准确度提高时重写权重。通过早期停止,我们可以让网络训练许多个纪元,而不必太担心过度适应。
耐心参数是用于确定是否/何时提前结束训练的阈值。耐心= 3 表示如果 3 个时期后验证损失没有改善,将开始提前停止。
递归神经网络的结构非常简单。该网络有一个具有 50 个单元的双向 GRU 层,其后是一个汇集、密集和丢弃层。双向意味着网络将学习文本序列的原始顺序以及单词出现的相反顺序。
分类器也在精确度上进行优化。准确性不会像人类那样区分不正确的预测。对一个人来说,预测 0 级为 4 级比预测 0 级为 1 级更糟糕。对网络来说,没什么区别。对于未来的实现,设计一个反映这种关系的度量可能是值得的。
是时候评估我们的模型了——让我们拿出测试集吧!
测试集的准确率:64%
让我们来看看混淆矩阵。在这个矩阵中,值以百分比的形式来衡量,以反映我们数据的不*衡性质。

不错的开始!
我们应该记住,由于所有的葡萄酒评论都非常正面,这个分类器将只适用于广受好评的葡萄酒。将来尝试使用不同的数据集会很有意思。
干杯!

Let’s end with a wine picture
感谢您的阅读!
如果你喜欢这篇文章,可以看看我关于数据科学、数学和编程的其他文章。通过 Medium 关注我的最新动态。😃
作为一个业余爱好项目,我还在 www.dscrashcourse.com建立了一套全面的免费数据科学课程和练习题。
如果你想支持我的写作,下次你报名参加 Coursera 课程时,可以考虑使用我的会员链接。完全公开—我从每一次注册中获得佣金,但不会对您产生额外费用。
再次感谢您的阅读!📕
用梯度提升机预测葡萄酒质量
培训和部署 GBM 模型的必要条件

Photo by Vincenzo Landino on Unsplash
介绍
本文给出了一个训练梯度增强机器(GBM)模型的教程,该模型仅使用葡萄酒的价格和书面描述来预测葡萄酒的质量。在许多真实的数据科学项目中,通过部署其他人可以用来获得实时预测的实时模型,将项目带入下一阶段是很重要的。在本文中,我使用 AWS SageMaker 创建一个活动端点来演示模型训练和部署过程。

我想从 Winc 购买一瓶“夏日之水”玫瑰酒,这是一家在线葡萄酒订阅服务公司。因为我不能在购买前试用,所以我想在决定购买前先了解一下它的质量。在这篇文章的最后,我们将看到使用经过训练的 GBM 模型对这款葡萄酒的质量预测。
让我们跳进数据和建模!
数据
该模型使用梯度推进树回归和来自 Kaggle 的真实数据来预测一瓶葡萄酒的质量点(y)。葡萄酒的“分数”分为 0-100 分,由《葡萄酒鉴赏家》分类如下:
- 95–100 经典:一款好酒
 - 90–94 杰出:一款具有卓越品质和风格的葡萄酒
 - 85–89 非常好:具有特殊品质的葡萄酒
 - 80–84 好:坚实、制作精良的葡萄酒
 - 75–79 *庸:可能有小瑕疵的可饮用的葡萄酒
 - 50–74 不推荐
 
特征工程
在这个模型中使用的特征(X)是一瓶酒的价格和从对来自描述的非结构化文本数据执行潜在语义分析(LSA)中获得的潜在特征。
使用以下步骤设计潜在文本特征:
- 使用清理文档字符串的典型方法来清理和处理文本数据,例如删除标点符号和将文本转换为小写字母。
 - 使用 LSA 对葡萄酒描述进行特征工程(使用 TF-IDF 和 SVD 进行矢量化,然后将文本的主体压缩成 25 个潜在特征)。
 

Figure 1: Example of wine description, price, and points data.
模型
使用 python 中的 xgboost 拟合梯度推进回归树模型,并使用*均绝对误差(MAE)进行评估
那么什么是梯度增压机呢?
一般来说,梯度增强机器是弱学习者集合到一个模型中以创建强学习者。梯度推进机器可用于回归或分类任务。它们通常应用于基于树的模型,但是理论上也可以应用于任何类型的弱学习者。

Figure 2: This visualization of one of the weak learner trees in the XGBoost model illustrates how the tree splits on the price and latent description of the wine. We can see that the price is very influential for predicting the wine quality points! This weak learner also found something meaningful in one of the latent description topics from the LSA.
训练数据用于适应每个弱学习者。Boosting 和 Bagging 都可以用来将这些弱学习者集成到一个模型中。Bagging 并行构建所有弱学习者。Boosting 采用了一种更系统的方法,并通过将权重应用于前一个弱学习者错误预测的观察值,顺序构建弱学习者,每个弱学习者都试图更好地解释上一个弱学习者错过的模式。
在随机梯度增强中,训练数据的样本用于拟合每个弱学习者。
Adaboosting
AdaBoosting 是最简单有效的二值分类 Boosting 算法。它顺序地用一次分裂来拟合决策树。这些小而弱的学习树被称为“决策树桩”。训练观察中的每个观察接收基于分类误差的权重,并且使用训练数据上的更新的权重来训练下一个决策树桩。还基于分类器的总误分类率为每个树桩分配一个权重。然后,该模型使用每个树桩上的权重来整合预测。具有大量错误分类的树桩接收较低的权重,导致它们的预测在集合预测中贡献较少。
梯度推进
梯度提升顺序地使弱学习者适应损失函数的梯度(导数),试图解释先前弱学习者错过的模式。当每一个学习者都适合时,使用加法模型来集成弱学习者。新的弱学习器的输出被加到先前弱学习器的输出上,以调整预测。这导致了一个递归方程,每个弱学习者都试图解释一个前一个学习者没有发现的模式。
第一个弱学习器被初始化为常数,例如*均值。

然后,函数 h(x)被拟合到残差。残差是损失函数的梯度。

其中 h(x)是适合损失函数梯度的弱学习器。Gamma 代表学习速率或步长。

最终的模型对每个特征都有许多项,每一项都将预测推向不同的方向。

因为弱学习器适合于预测损失函数的梯度,所以可以选择所使用的任何可微分损失函数,从而允许该方法应用于分类和回归问题。
用 Python 训练模型
首先,从导入所需的 python 库开始。
现在,加载葡萄酒数据并查看它的样本。

通过删除标点符号、数字并将所有字符转换为小写来预处理文本描述。
现在描述已经清理完毕,TF-IDF 用于向量化单词,SVD 用于将矩阵压缩成 5 个潜在向量。这种从文本数据中压缩特征的方法被称为潜在语义分析。为了简单起见,选择了 5 个潜在特征,但是在实践中,可以使用肘图来选择潜在特征的正确数量。

执行测试/训练分割,为 xgboost 格式化数据,并训练模型!
对测试数据进行预测,并使用*均绝对误差评估模型。*均而言,预测的质量点相差 1.84 个点。还不错!

使用 xgboost 中的要素重要性图查看对模型影响最大的要素。看起来价格是预测葡萄酒质量时最重要的特征。

Figure 3: Feature importance.
使用 AWS SageMaker 进行部署和推理
在这个笔记本中,我使用 SageMaker 的 estimator 来训练模型,并将其作为一个实时端点。估计器启动一个训练实例,并使用[train_wine_gbt.py](https://github.com/statisticianinstilettos/wine_quality_predictions/blob/master/train_wine_gbt.py)脚本中的代码来训练模型,将模型保存到 s3,并定义端点的输入和输出。可以使用 SageMaker 的许多内置模型进行训练和部署,但我想为实时预测指定我自己的特征转换和输出,这可以使用像train_wine_gbt.py这样的 python 脚本来完成。
现在这个模型已经被训练和部署了,我可以用它来预测任何一瓶酒的质量!使用来自 Winc 网站的“夏日之水”的文本描述和价格,模型预测这款酒为 87,属于“非常好”的类别!

如果您想重用这些代码,请点击这里查看项目的 GitHub repo,在那里我有 jupyter 笔记本用于培训和部署。
干杯!
张量流在时间序列数据预测和分析中的应用

Photo by Jason Briscoe on Unsplash
嘿大家好!在这篇文章中,我试图总结 Deeplearning.ai 关于序列、时间序列和预测的课程。
在这篇文章中,我们关注“时间序列数据”,它是序列模型的一部分。本质上,这代表了一种随时间变化的数据类型,例如特定地方的天气、一群人的行为趋势、数据的变化率、身体在 2D 或 3D 空间中的运动或者市场中特定股票的收盘价。
时间序列数据的分析可以对任何包含“时间”因素的事物进行。
那么机器学习可以帮助我们在时间序列数据上实现什么呢?
1)预测 —最显著的应用是根据收集的历史数据预测未来。
2)数据插补 —预测过去的数据,从而预测过去的数据,即使我们没有收集这些数据。它还可以用来预测数据中缺失的值。
3)检测异常 —可用于检测潜在的拒绝服务攻击。
4)检测模式 —可用于预测声波系列数据中的单词。
在处理时间序列数据时,总会出现某些关键词。
趋势

时间序列有一个特定的数据移动方向。上图是一系列具有向上趋势的数据。
季节性

以可预测的间隔重复的模式。以上是一个软件开发者网站的数据。该数据向上值为 5 个单位,向下值为 2 个单位。因此,我们可以对每个单独的峰进行推断,峰开始和结束时的下降对应于周末,中间的数据对应于工作日
组合

上面的 pic 是具有上升趋势和季节性的数据类型的组合。
白噪声

这只是一组随机值,不能用于预测。因此,这被称为白噪声。
自相关

没有季节性或趋势,峰值似乎是随机出现的,但峰值不是随机的。在尖峰之间,有一种非常确定的衰变类型。

下一个时间步长是前一个时间步长值的 99%加上一个偶然的尖峰。上面是一个自相关序列,也就是说,它与自身的延迟拷贝(也称为滞后)相关。

上面突出显示的框中的值似乎具有很强的自相关性, 像这样的时间序列被描述为具有记忆,其中步骤依赖于先前的步骤。这些尖峰通常被称为创新 。换句话说,这些创新不能用过去的价值来预测。
因此我们现在知道时间序列数据是由趋势、季节性、自相关和噪声组合而成。

机器学习模型被训练来发现模式,并基于这些模式来预测未来。因此,这在很大程度上与时间序列相关,除了不可预测的噪声,但这仍然给了模型一种直觉,即过去存在的模式可能在未来存在。

*稳(时间)序列是指其均值、方差、自相关等统计特性在一段时间内均为常数的序列 。因此,非*稳序列的统计特性会随时间而改变。
当然,现实生活中的时间序列,也可能有不可预见的事件,可能会影响数据。以上面的图表为例。如果上图是一只股票,那么可能导致这种变化的“大事件”可能是由于某种金融危机或丑闻。

预测数据的一种方法是使用“简单预测”,即取上一个值并假设下一个值将是相同的值。

将数据分成三部分用于训练、验证和测试,称为“固定部分”。在这样做的时候,必须确保每个时期包含一个整数个季节。
例如:如果时间序列具有年度季节性,那么每个周期必须包含 1 年、2 年或 3 年的季节性。如果我们取一个跨度为一年半的周期,那么某些月份会比其他月份表现得更多。
与非时间序列数据集相比,这有一点不同,在非时间序列数据集中,我们选择随机值来做同样的事情,这不会影响最终结果。但是,在这里,我们会注意到跨度和周期的选择会影响最终结果,因为数据是时间敏感的。
另一件需要考虑的事情是,在训练时,我们可以使用如上所述的策略将数据分成三个部分,但是一旦训练完成并且我们准备好模型,我们应该对整个数据进行再训练,因为用于测试的数据部分与当前时间点的最新数据相关,并且是确定未来值的最强信号。

绩效评估指标


最基本的预测方法是“移动*均线”。其思想是,上图中的 黄色 线是在一个称为“*均窗口”的特定固定时间帧中获取的蓝色值的*均值。
上面的曲线给出了时间序列的*滑曲线,但是它 没有预测趋势或季节性 。它甚至可以给出比天真预测差的性能,给出大的 MSE。

消除这种情况的一种方法是通过一种叫做“差异的方法来消除趋势或季节性。在这种方法中,我们研究时间' t '和时间' t-365 '的值。根据时间序列的时间段,进行差分的时间段可以改变。
这样做我们得到了上面的结果。以上数值没有趋势性,也没有季节性。

然后,我们可以使用移动*均线来预测时间序列。因此,黄线给出了上述数据的移动*均值,但这只是时间序列中差异的预测。为了得到真实的数据,我们将'差分的数据与' t-365 的数据相加。
在下图中,由于季节性周期是 365 ,我们将从时间 t 的值中减去 t-365 的值。


上述操作的结果如上图所示。与之前的移动*均线预测相比,我们得到了一个较低的“ MSE ”。这是比幼稚的方法稍微好一点的版本。
我们会注意到预测有很多噪音。这是因为在取差值时,来自' t-365 '数据的噪声被加入到我们的预测中。为了避免这种情况,我们可以对 t -365 数据进行移动*均,然后将其添加到我们的差分数据中。

如果我们这样做,我们最终会得到上面用黄线表示的预测。以上曲线*滑,具有较好的' MSE '。
让我们先接触一下实际的编码部分。我们将遵循下面提到的几个步骤来模拟时间序列数据集,并尝试在其上构建模型。
我们创建一个值范围从 0 到 9 的数据集,并显式地将其转换为 numpy 数组。

数据集被分成大小为 5 的窗口,即每个数据窗口包含 5 个数据实例。1 的移位导致下一个数据窗口将第一个数据实例移位 1 个单位。

drop_remainder 导致不包含一组 5 个数据点的剩余窗口被丢弃。

每个数据窗口被*面映射成 5 个一批。

进行映射以包含前 4 个实例作为训练数据,剩余的数据在每个窗口的末尾作为标签。然后,数据集以与数据范围大小相同的缓冲区大小进行混洗。
数据被混洗是为了避免 序列偏差 。
顺序偏差是当事物的顺序能够影响对事物的选择时。例如,如果我问你最喜欢的电视节目,并按顺序列出“权力的游戏”、“杀死夏娃”、“旅行者”和“神秘博士”,你可能更有可能选择你熟悉的“权力的游戏”,这是你看到的第一个节目。哪怕和其他电视剧持*。因此,当训练数据集中的数据时,我们不希望序列以类似的方式影响训练,所以最好将它们打乱。

数据集被分成每批 2 个,每个 X 作为包含训练数据的列表,每个 Y 作为标签映射到数据。

数据被拆分,以便训练数据包含要合并到训练数据中的季节性和趋势。

使用下面的函数将数据分解到不同的窗口中。

数据集的窗口实例通过名称 数据集 创建,模型创建。

迭代每个窗口,我们试图预测验证数据。

我们结合了一个学习率调度器,试图测量模型的最佳学习率。

我们绘制了一系列已经实现的不同学习率,并确定了最适合我们模型的学习率。

从上面的图表中,我们观察到与学习率相关的最低成本大约是 1e-5。然而,这里要注意的一件有趣的事情是,图表在这一点和随后的几个点上似乎很不稳定。使用这个学习率可能会对我们的预测模型产生负面影响。因此,最适合的学习速率似乎是 1e-6,既*滑又低。

我们现在绘制关于时期的损失函数。

该模型似乎已经停止学习,因此,该图似乎在前几个时期已经饱和,但事实并非如此。当我们绘制前 10 个时期的损失函数时,我们注意到损失持续减少。这意味着,即使学习速度非常慢,模型仍会继续学习。

最后,我们为数据绘制图表。 蓝色 为原始, 黄色 为预测,

我们的均方误差如下所示。

轮回层

我们开始使用机器学习技术来预测数据的未来值。在上图中,我们有一个大小为(4,1)的输入批量向量。想象一下,如果 存储单元 有 3 个神经元,那么 存储单元 的输出将具有(4,3)的形状。因此,如果整个系列有 30 个存储单元,网络输出的总大小将是(4,3,30)。

上图是序列到序列网络的一个例子,其中一个序列作为输入给出,一个序列作为输出接收,即输出为(4,3,30)的形状。当我们需要将一个 RNN 层堆叠在另一个之上时,这种类型的架构非常有用。
上图是一个序列到向量网络,其中一个序列作为输入给出,但我们接收一个向量作为输出,即输出是(4,3,1)的形状。

为了演示序列到向量模型的工作原理,我们使用上图。对于第一层,命令“return _ sequences = True”使下一层的每个时间步返回一个序列输出。这然后被馈送到下一层。默认情况下,下一层有" return_sequences = False ",这导致只给出一个向量作为输出。
请注意 input_shape = [None,1] 参数。Tensorflow 假设第一维是批量大小,它被设置为“无”意味着它可以有任何大小作为输入批量大小,下一维是时间步数,它可以被设置为“无”意味着 RNN 模型可以处理任何长度的序列,最终值为“1”,因为数据是单变量的。

如果我们在上面的模型中加入“return _ sequences = True”的参数,那么模型的第二层现在给出的是一个序列作为输出,而不是一个向量。密集层现在得到一个序列作为输入。Tensorflow 通过使用相同的密集层独立处理每个时间步长的输出。
LSTMs

当我们观察 RNN 时,它看起来就像上面的图表。这里,各个节点被输入批量大小的数据 X[i] ,并给出输出 y[i] ,同时将单元状态从该节点传递到下一个节点,该状态是计算后续输出的重要因素。
这种方法的问题是,随着单元状态从一个节点传递到另一个节点,它的值会减少,其效果会逐渐消失。
为了解决这个问题,应用了一种叫做 LSTMs 的新方法。
LSTMs 通过引入一种单元状态来消除这个问题,该单元状态在单元之间和时间步长之间传递,因此可以更好地保持状态。

单元状态可以是如上图所示的单向或如下图所示的双向。

这意味着,与 RNNs 的情况相比,早期窗口中的数据对整体预测具有更大的影响。
在我们的代码中实现 LSTMs。


在我们的模型中增加了另一层双向 LSTM。

上面的代码给出了以下输出:-

通过在下面添加一层新的双向代码,我们得到以下结果。

我们没有观察到太大的差异,事实上, MAE 似乎已经倒下,也就是说,我们的模型性能已经下降。

因此,必须在模型中试验不同类型的层,并选择最佳层。
对模型进行卷积
为什么我们要在时间序列分析问题中使用卷积?
一个原因是因为他们的训练成本更低。
第二,它们最适合解决许多实际问题。例如,在我们应用 RNNs 的某些情况下,我们假设先前出现的“每一个”数据将被要求猜测下一个数据。rnn 在这个概念上工作,因为它考虑了所有的历史数据来预测下一项数据。事实上,我们并不真的需要所有的数据。
为了理解这一点,让我们考虑一个子弹射弹的例子。为了预测抛射体的下一个值,我们实际上并不需要所有的历史抛射体数据。假设投射数据是一组‘n’实例,我们将只需要最新的‘k’实例来预测下一个投射数据,其中 k < n.
因此,人们可以限制时间依赖性,而是使用 CNN 架构来模拟时间序列。所以现在每个假设变成了依赖于前一个' k ' 实例的时间实例,前一个实例是卷积上的感受域。每个 CNN 过滤器学习一组规则,并将这些规则应用到最适合该规则的特定数据部分。因此,这成为一个非线性系统。

我们注意到“输入形状,它将数据转换为一维数据,而不是卷积通常用来处理图像的二维数据(图像是二维数据)。

上面的图是我们应用了 conv 图层后得到的。与早期的情节相比,这是一个巨大的进步。然而,情节仍然可以通过以下方式进行改进
- 对它进行更长时间的训练。
 

从图中可以看出,模型仍在学习,也许学习速度很慢,因此,如果我们继续训练模型一段更长的时间,模型的整体效率可以提高。
2。另一种方法是使模型双向化。


然而,我们注意到模型现在开始过度拟合数据,并且“ MAE ”实际上已经增加。

当我们绘制数据时,我们可以清楚地看到数据中有很多噪声,因为我们是以小批量的方式向模型提供数据,所以我们最终得到了这个结果。因此,这使我们能够得出结论,上述步骤是朝着正确方向迈出的一步,通过对批量大小等超参数进行一些调整,我们可以改善我们的结果。我们可以试验批量大小,并尝试得到适当的结果。
调整我们模型的过程

我们以“太阳黑子活动数据集”为例。我们使用基本的“密集”层网络来训练我们的模型,该网络具有两层,每层具有 10 个神经元。我们因此得到上述结果。

事实上,当我们放大时,我们可以看到我们的预测与原始数据相比表现如何。

我们可以看到,火车窗口大小为 20,这基本上意味着我们有 20 个时间片的数据。每个时间片对应一个月。

通过查看数据,我们意识到我们有 11 到 22 年的季节性。
因此,我们现在使用的时间片为 132,也等于 11 年(132 个月= 11 年)。

但是我们注意到 MAE 实际上增加了。因此,增加窗口大小不起作用。

当我们分析我们的数据时,我们发现即使数据具有 11 年的季节性,噪声也使其表现为典型的时间序列数据。

因此,我们将“窗口大小更改为 30,并更加关注为训练和测试提供的数据量。为训练提供更多数据可以提高模型的效率。

现在' MAE' 已经降到了 15.14。我们可以通过改变输入节点的数量来进一步做出改变。现在我们的输入数据已经增加到 30,我们可以有 30 个输入节点。然而,这导致我们的网络性能比以前更差,另一方面,调整'学习率'提高了模型的效率。
让我们意识到这样一个事实,尽管改变了:-
1.批量
2.神经元数量
3.窗口大小
4.训练数据大小
5.学习率
导致我们的模型发生了许多变化,有些促进了预测效率,有些则降低了预测效率,每一个变化都同样重要,需要进行试验以获得更好的结果。
这就把我们带到了记录课程的结尾。人们应该意识到机器学习可以用于对顺序和时间序列数据进行预测的多种方式。然而,我们在这里看到的只是表面现象,还有很多需要深入研究的。通过本文的学习,我们已经准备好迎接新的复杂的挑战。举一个…‘多元时间序列数据’。
我希望这能激励你真正开始学习这门课程,并尝试自己去实施。
感谢您阅读这篇博客。我希望听到你对此的想法。
线性回归中的预测区间

这篇文章讲述了如何计算线性回归的预测区间。通常在建模时,我们从回归模型中得到一个单一的值。但是如果这个价值被用来计划或做重要的决定呢?
那么,当我们想知道我们的不确定性或误差幅度时,一个单一的值可能会夸大我们的信心。当然,你可以像 RMSE 一样查看所有预测的总体误差分数,但是对于单个预测呢?预测间隔为您提供了一个预测范围,该范围考虑了对您至关重要的任何建模误差阈值。类似于置信区间,您可以选择一个阈值,如 95%,其中您希望实际值在 95%的时间内处于某个范围内。这在计划时非常好,因为您可以在评估过程中使用上限和下限。
我已经创建了一个小方法(使用来自这里的一些输入)来预测对你或你的项目很重要的某个置信阈值的范围。我将用波士顿住房数据集来说明一个预测区间,预测不同地区住房的中值。如果你喜欢阅读 GitHub 上的代码,这里有完整的笔记本。
否则,以下是数据集的描述:
from sklearn import datasets
print(datasets.load_boston()['DESCR'])Boston house prices dataset
---------------------------
**Data Set Characteristics:**  
    :Number of Instances: 506 
    :Number of Attributes: 13 numeric/categorical predictive. Median Value (attribute 14) is usually the target.
    :Attribute Information (in order):
        - CRIM     per capita crime rate by town
        - ZN       proportion of residential land zoned for lots over 25,000 sq.ft.
        - INDUS    proportion of non-retail business acres per town
        - CHAS     Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
        - NOX      nitric oxides concentration (parts per 10 million)
        - RM       average number of rooms per dwelling
        - AGE      proportion of owner-occupied units built prior to 1940
        - DIS      weighted distances to five Boston employment centres
        - RAD      index of accessibility to radial highways
        - TAX      full-value property-tax rate per $10,000
        - PTRATIO  pupil-teacher ratio by town
        - B        1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town
        - LSTAT    % lower status of the population
        - MEDV     Median value of owner-occupied homes in $1000's
我们将对数据进行预处理,使用 sklearn 的线性回归包对其建模。
#preprocess data
df = pd.DataFrame(datasets.load_boston()['data'])
df.columns = datasets.load_boston()['feature_names']
df['target'] = datasets.load_boston()['target']
#split data
X_train, X_test, y_train, y_test = train_test_split(
    df.drop('target',axis=1), df.target, test_size=0.2, random_state=42)#do modeling
model = LinearRegression()
fit_model = model.fit(X_train, y_train)
predictions = fit_model.predict(X_test)
如果想了解单个预测层面的模型误差呢?这里我构建了一个简单的方法来获得这个区间。
def get_prediction_interval(prediction, y_test, test_predictions, pi=.95):
    '''
    Get a prediction interval for a linear regression.
    INPUTS: 
        - Single prediction, 
        - y_test
        - All test set predictions,
        - Prediction interval threshold (default = .95) 
    OUTPUT: 
        - Prediction interval for single prediction
    '''
    #get standard deviation of y_test
    sum_errs = np.sum((y_test - test_predictions)**2)
    stdev = np.sqrt(1 / (len(y_test) - 2) * sum_errs)#get interval from standard deviation
    one_minus_pi = 1 - pi
    ppf_lookup = 1 - (one_minus_pi / 2)
    z_score = stats.norm.ppf(ppf_lookup)
    interval = z_score * stdev#generate prediction interval lower and upper bound
    lower, upper = prediction - interval, prediction + interval return lower, prediction, upperget_prediction_interval(predictions[0], y_test, predictions)
OUTPUT: (19.24072024369257, 28.996723619824934, 38.752726995957296)
结论
那么你应该从这篇文章中学到什么呢?您可以使用一些工具来计算称为预测区间的不确定性,对于线性回归,您可以在项目中使用上面的代码。这有助于我计算非常关键的业务流程的不确定性,并且是您工具箱中的一项有用技术。
随着您在数据科学职业生涯中的不断进步,您将需要更多量化风险和不确定性的方法,因为这将有助于为关键决策提供信息。希望你喜欢这个简短的教程!
多元时间序列和 VAR 模型的预测任务
基于统计 VAR 模型的天气预报

ime 系列数据可能会令人困惑,但探索起来非常有趣。这类数据引起我注意的原因是,它几乎存在于每一个行业(销售、交付、天气状况等)。).例如:使用谷歌大查询如何探索天气对纽约市的影响链接。
任务中的主要步骤:
- 问题定义
 - 收集信息
 - 探索性分析
 - 选择和拟合模型
 - 使用和评估预测模型
 
公式化问题。
我们希望使用数据集中的当前信息来预测序列的未来值。此信息包含系列的当前值和过去值。有很多项目使用单变量数据集,为了使它更复杂一些,更接*现实生活中的问题,我选择了一个多变量数据集。多元时间序列分析考虑处理相关数据的同步多个时间序列。(数据集包含多个时间相关变量。)
我想做一个天气预报。使用统计模型预测未来某一特定时间和地点的大气状态的任务。
收集信息和下载数据
我将使用来自以下来源的数据:
- 国家海洋和大气管理局。气候数据在线(CDO)提供网络服务,通过 API 提供对可用数据的访问。链接
 - GoogleCloud BigQuery 公共数据。链接
 - 卡格尔。你可以从这个页面下载并在你 env 中运行,或者使用 kaggle 提供的 kaggle 帐户并在你的笔记本中使用它。
 
从 NOAA 获取数据
为了访问 CDO 网络服务,必须首先从令牌请求页面获取令牌。文档是直截了当的,不应该花太多时间去理解。
示例:要查找缅因州波特兰的天气信息,您需要知道:State_id 和波特兰的坐标。首先,我将获得所有州的列表。
def get_states_list(self):
    url = conf.noaa['host']+'locations?locationcategoryid=ST&limit=50'
    headers = dict(token=conf.noaa['token'])
    r = requests.get(url, headers=headers)
    data = json.loads(r.content)
    states_list = json_normalize(data['results'])
    return states_list
然后,使用参数“name”:“Maine”查找有关特定州的信息:
def state_info(self, state):
    dataset = NoaaApi()
    states_info = dataset.get_states_list()
    df_states = pd.DataFrame(states_info)
    id = df_states[(df_states.name == state)].id
    return id
结果:其中缅因州的 id 为:“FIPS:23”
dataset.state_info('Maine')State id: FIPS:23
下一步是在波特兰附*建立站点,波特兰的坐标可以很容易地在谷歌地图上找到(北纬 43.6591,西经 70.2568)。
用下面的 GET 请求可以找到缅因州的电台列表。
def get_stations_list(self):
    url = conf.noaa['host']+'stations?locationid=FIPS:23&limit=687'
    headers = dict(token=conf.noaa['token'])
    r = requests.get(url, headers=headers)
    data = json.loads(r.content)
    stations_list = json_normalize(data['results'])
    return stations_list
我不需要州内所有的站,我想找波特兰附*的站。为此,我将指定坐标。
def station_info(self):
    dataset = NoaaApi()
    stations_list = dataset.get_stations_list()
    df_stations = pd.DataFrame(stations_list)
    portland_st = df_stations[(df_stations.latitude > 43.5)
                           & (df_stations.latitude < 43.7)
                           & (df_stations.longitude > -70.3)
                           & (df_stations.longitude < -70.1)]
    return portland_st

结论:我们得到了波特兰附*的站的列表,这些站点可用于获取该地区的天气数据。
从 Kaggle 获取数据
有很多数据集提供了学习和提高技能的机会,也提供了参加比赛挣钱和展示技能的机会。我找到了每日全球历史气候网络(BigQuery Dataset)的完整描述可以在概览页面找到:链接。这是练习 BigQuery 技能的绝佳机会。
import numpy as np 
import pandas as pd 
import os
import bq_helper
from bq_helper import BigQueryHelpernoaa = bq_helper.BigQueryHelper(active_project="bigquery-public-data", dataset_name="ghcn_d")
创建一个查询并估计大小:
#43.6591° N, 70.2568° W  Portland/Coordinates Maine 45.2538° N, 69.4455° WqueryStations = """SELECT
  id,
  name,
  state,
  latitude,
  longitude
FROM
  `bigquery-public-data.ghcn_d.ghcnd_stations`
WHERE
  latitude > 43.5
  AND latitude < 44
  AND longitude > -70.4
  AND longitude < -69.4; 
  """
noaa.estimate_query_size(queryStations)
Kaggle BigQuery.helper 为查询提供估计,以避免超出限制。
0.0065232375636696815
现在运行查询:
stations_portland = noaa.query_to_pandas_safe(queryStations)
stations_portland.head(20)

如我们所见,我们得到了几乎相同的电台列表。
从谷歌云获取数据
谷歌提供 30GB 的公共天气数据。有可能有一个免费的帐户和实践,以提高您的技能在大查询。还可以选择您需要的数据,并下载数据集进行进一步研究。对私人和公司都非常有用。我不会尝试查找电台列表,但会从找到的电台请求每日温度。
SELECT
  TIMESTAMP(CONCAT(year,"-",mo,"-",da)) AS date,
  AVG(IF (temp=9999.9, 0, temp)) AS temperature,
  MIN(IF (temp=9999.9, 0, min)) AS temperature_min,
  MAX(IF (temp=9999.9, 0, max)) AS temperature_max,
  AVG(IF (visib=999.9, 0, visib)) AS visibility,
  AVG(IF (gust=999.9, 0, gust)) AS wind_gust,
  AVG(IF (wdsp="999.9", 0, CAST(wdsp AS Float64))) AS wind_speed,
  AVG(IF (prcp=99.99, 0, prcp)) AS precipitation,
  AVG(IF (sndp=999.9, 0, sndp)) AS snow_depth
FROM
  `bigquery-public-data.noaa_gsod.gsod20*`
WHERE
  CAST(YEAR AS INT64) > 2008
  AND (stn="726060") 
GROUP BY
  date
ORDER BY
  date
该查询运行时将处理 5.19 GB。
该查询将返回缅因州波特兰市一个气象站过去 10 年的每日天气。
探索性分析
首先,我想把重要的信息可视化,让我们清楚地知道我们有什么样的数据。
地理数据
我将使用来自缅因州波特兰市的数据,通过 GeoPandas 库绘制气象站的位置。第一步是找到并下载一个形状文件(。shp 文件)。我已经展示了如何使用 NOAA API( portland_st )获得波特兰附*的站点
highway_map = gpd.read_file('./maine_highway/maine_highway.shp')
crs = {'init': 'epsg:4326'}
point = [Point(xy) for xy in zip(portland_st['longitude'], portland_st['latitude'])]
geo_stations = gpd.GeoDataFrame(portland_st, crs=crs, geometry=point)
fig, ax = plt.subplots(figsize=(5, 5))
highway_map.plot(ax=ax, alpha=0.4, color='grey')
geo_stations.plot(ax=ax, color='red', marker='o')
plt.legend(prop={'size': 5})
plt.show()
我找到了显示波特兰主要道路的形状文件(“maine_highway.shp”),并将其与车站位置结合起来。红点是气象站的位置。现在很明显特征模型需要哪个站。这是一种可视化地理空间数据的简单方法。

Portland, City in Maine
时间序列图形
时间序列分析的目标是发现数据中的模式,并使用数据进行预测。
探索时间序列之间的关系也很有用。让我们看看 2017 年的所有支线剧情:

当然,我们想看看将要预测的系列。我是用 iplot 库做的。
df[['temperature', 'temperature_min']].iplot(
    mode='lines+markers',
    opacity=0.8,
    size=8,
    symbol=1,
    xTitle='Time',
    yTitle='Temperature',
    title='Temperature over last 10 years')

出于好奇,我可以举例说明显示过去 10 年新年*均/最低/最高温度的线图:
sns.set(rc={'figure.figsize': (14.7, 8.27)})
g = sns.lineplot(data=newyear.temperature_max, palette="tab10", linewidth=2.5, label="max")
g = sns.lineplot(data=newyear.temperature_min, palette="tab10", linewidth=2.5, label="min")
g = sns.lineplot(data=newyear.temperature, palette="tab10", linewidth=2.5, label="avg")g.tick_params(labelsize=10)
plt.xticks(rotation=45)
plt.show()

27.12 至 03.01 期间的温度,为期 10 年。如果有人需要过去几年中某个特定时期的历史统计数据,比如说新年的那一周。

如果主要目的只是准备数据和选择模型。正确的解决方法是在查看特定系列时绘制四个图表。
除了查看数据的时间图,ACF 图对于识别非*稳时间序列也很有用。对于*稳的时间序列,ACF 会相对较快地下降到零,而非*稳数据的 ACF 下降较慢。
def tsplot(y, title, lags=None, figsize=(10, 6)):
    fig = plt.figure(figsize=figsize)
    layout = (2, 2)
    ts_ax = plt.subplot2grid(layout, (0, 0))
    hist_ax = plt.subplot2grid(layout, (0, 1))
    acf_ax = plt.subplot2grid(layout, (1, 0))
    pacf_ax = plt.subplot2grid(layout, (1, 1))
    y.plot(ax=ts_ax)
    ts_ax.set_title(title, fontsize=12, fontweight='bold')
    y.plot(ax=hist_ax, kind='hist', bins=25)
    hist_ax.set_title('Histogram')
    sm.tsa.graphics.plot_acf(y, lags=lags, ax=acf_ax)
    sm.tsa.graphics.plot_pacf(y, lags=lags, ax=pacf_ax)
    sns.despine()
    plt.tight_layout()
    plt.show()
    return ts_ax, acf_ax, pacf_ax


在一系列的每日温度中,*均温度不是恒定的,因为它每天都在变化,但对于不同年份的同一个月,我们可以期望一个恒定的*均值。
季节周期 s 定义了构成一个季节周期的观测次数。例如,每月系列的 s = 12,季度系列的 s = 4,每日系列的 s = 365。
然而,这可能并不完全正确:例如,如果我们有每日数据,并且季节周期是一个月的长度,则 s 将大约为 30,但它会逐月变化。最棘手的是,季节性可能不止一种。例如,对于每日数据,我们可以得到 s = 30 的月度季节性和 s = 365 的年度季节性。
由于另一个原因,每日数据具有挑战性——它们通常涉及多重 季节模式,因此我们需要使用一种方法来处理如此复杂的季节性。
时间序列数据也可能有其他模式,如趋势或周期。所有这些都表明数据不是静止的。
要使用统计模型,如 VAR 模型,我们应该在数据能够适合模型之前关注这些模式。对于风险值模型,你需要执行稳定条件。将足够的结构放入模型中,以识别模型中的一些参数。
对序列的对数应用季节差异应该使上述序列*稳。为气候数据定义参数是相当具有挑战性的,有很多关于这个主题的出版物。我不会深入挖掘,只选择简单的参数 lag=365 和 diff=1。更多关于参数的信息你可以在 T rend 气候时间序列分析出版物中找到。
变形
*稳时间序列的性质不依赖于序列被观察的时间。带有季节性的时间序列不是*稳的,因为季节性会影响时间序列在不同时间的值。
transformed = df.copy()
transformed['temperature'] = np.log(df.iloc[:, 0]).diff(1)
transformed['wind_speed'] = np.log(df.iloc[:, 1]).diff(1)
变换的目的是使数列*稳。

Temperature after transformation
下一步是分割数据。
将样本分成训练/测试和验证集。需要根据依赖关系结构对其进行仔细的划分。最适合这种情况的方法是滚动窗口。但是在这个特殊的例子中,我将在最后留下一些观察结果来验证我的模型。我想预测 7 天。稍后,为了检查模型的性能,我将使用这 7 个真值。
开发 VAR 模型
这种模型要求序列是*稳的,如果序列不是*稳的,那么单个序列必须被转换为*稳的。
两个变量的 VAR(p)可以矩阵形式(其中 p=1)写成

source: wikipedia
model = sm.tsa.VARMAX(y_train, order=(5, 0), trend='c')
model_result = model.fit(maxiter=1000, disp=False)
model_result.summary()


选择订单的方法是使用信息标准 AIC、BIC、HQIC。估计一系列模型,选择最好的一个。模型阶次选择的最常见方法包括最小化在模型阶次范围内评估的一个或多个信息标准。
for i in range(5):
    i += 1
    model = sm.tsa.VARMAX(y_train, order=(i,0))
    model_result = model.fit(maxiter=1000, disp=False)
    print('Order = ', i)
    print('AIC: ', model_result.aic)
    print('BIC: ', model_result.bic)
    print('HQIC: ', model_result.hqic)
关于如何选择正确顺序的更多细节,你可以在《T4 多时间序列分析新入门》一书中找到,作者是 Lütkepohl,Helmut(第 4 章)。在这个特殊的例子中,我将使用 p = 5,此时 AIC 标准达到最小值。
型号诊断
下一步是模型诊断,并检查基本假设是否正确。Statsmodels 中的 VARMAX 类允许对 VAR、VMA 和 VARMA 模型进行估计(通过 order 参数)。VARMAX 过程是一个完善且强大的多变量时间序列分析工具。
model = sm.tsa.VARMAX(y_train, order=(5, 0))
model_result = model.fit(maxiter=1000, disp=False)
model_result.plot_diagnostics()
plt.show()

常见的总体诊断是绘制残差图,并查看残差是否符合模型假设。
可以应用测试:
- 确认正常的测试
 - 缺乏序列相关性
 - 不存在异方差
 
这两个系列不显示趋势或规律的季节模式。因此,我们假设它们是*稳 VAR(p)过程的实现。
预测和估算
概括一下:我们用下面的等式来转换温度和风速,其中 yt 是原始序列:

这意味着它应该被转换回定义和估计预测的真实结果。为此,我们计算方程并应用于预测值:

z = model_result.forecast(steps=7)
转换值并打印结果:
pd.concat([df['temperature'][-7:], forecast], axis=1)

计算均方误差:
rmse = sqrt(mean_squared_error(df['temperature'][-7:], forecast))RMSE: 4.200
结论:时间序列数据很难正确处理。你需要适当地探索你的数据来理解它,意识到任何季节性或其他模式。不可能总是使用相同的方法。总的来说,最好从简单的模型开始,并在此基础上构建您的分析。
参考
- AM207:哈佛大学 pav los Protopapas
 - 预测:原则与实践
 - Jeffrey Yau,PyData 大会 2017
 - 多时间序列分析的新介绍
 - 谷歌 BigQuery 探索天气效应
 
政府决策中的预测分析

私营部门与公共部门
许多美国人都意识到机器学习和预测分析正在重塑我们的个人生活、工作和世界经济的速度。虽然最*的事件引起了对企业如何使用和共享我们的数据的更大审查,但很少有人认为私营部门不应继续推进它们的使用。市场力量(即客户、公众意见)和政府法规会影响公司如何采用和实施它们。
然而,政府处于市场之外,对立法和司法监督的缓慢进程作出反应。随着政府机构扩大对这些技术的采用和实施,我们如何确保政府机构采用机器学习和预测分析?
政府决定
在许多情况下,我们当前的法律法规要求政府做出直接影响公民的决定,尽管程度不同。这些决定中的一些与福利的资格有关,另一些是个人是否会受到惩罚,或者个人的公民自由是否会受到限制。在代议制民主国家,这些决策通常由一小部分公务员、当选者甚至是个人做出。这些决定的影响可能大不相同;从小的不便,如在机场托运行李,到更大的影响,如通过将公民关进监狱来剥夺他们的公民自由的决定。刑事司法有多个例子,包括根据对犯罪可能发生的地点的预测,决定何时何地派遣警察巡逻。以及在决定是否允许候审个人保释时的情况。
假设这些政府决策者在这些情况下尽了最大努力,这些决策者仍然不得不处理这样一个事实,即他们无法获得关于他们需要做出决策的情况和个人的完美信息。例如,最*的工作显示了个人偏见的深度,无论是决策中已知的偏见还是未知的偏见。此外,在缺乏工具帮助的情况下,个人不太擅长根据过去事件的统计数据对未来事件做出预测性决策。最*的研究还表明,个人做出预测的成功率通常并不比随机机会好。
结合这些限制和风险,以及我们的系统作出这些重要裁决的要求,产生了建立更好的方法来通知这些决定的需要。为做出更好的决策、更好的政策实施以及更高的效率所做的努力导致了几种不同的运动。这些努力的一个分支是基于证据的决策或基于绩效信息的决策,这已被政治家、公务员和公众衷心拥护。支持者认为需要更好的数据才能做出更好的决策。其他人现在认为,政府决策者也需要工具来使用更好的数据做出更好的决策,而大数据和预测分析可以实现这些目标。
我同意这样的观点,即预测分析是一个政府可以利用基于证据的决策能力并提高决策准确性和效率的领域,正如这些运动所规定的那样,从而获得公众信任和立法者的支持。
公共部门预测分析的优势和风险
即使预测分析算法在 99%的时候是准确的,应用于 3 亿公民,你仍然会有 300 万个误报或漏报。
政府预测分析的潜在好处有很多;包括更有效的决策制定、更高效的决策过程以及更少偏见的决策制定。还必须充分考虑风险和挑战。实施任何预测分析计划都存在风险,但在政府领域,风险会增加,因为预测的结果可能对公民产生更大的影响。假阳性和假阴性的风险增加了。此外,正如大多数从业者所知,这些风险几乎是肯定的。例如,没有一个模型是完美的,每个模型都有可能出现非随机和随机误差。即使预测分析算法在 99%的时候是准确的,应用于 3 亿公民,你仍然会有 300 万个误报或漏报。在推荐关于网飞的电影时,这可能是一个可以接受的错误率,但在推荐是否启动监控项目或逮捕公民时,我们可能会认为这是不可接受的。
偏差 —预测算法可能会因年龄、种族、性别或性偏好等固有的歧视性偏差而被错误地编程,这些偏差并不代表结果的真正因果因素。
隐私 —有人担心当政府或私营实体使用大数据技术时,会对的公民数据隐私产生影响,大数据技术可以在个人不知情或未经其同意的情况下,更快、更准确地识别个人及其敏感属性。
透明度 —另一个令人担忧的领域是预测分析的透明度,即个人将如何理解对他们做出的决定,对输入或算法提出异议,或理解他们过去和未来的行为将如何影响这些决定。立法机关制定的政策要么由公共资助的机构、公私伙伴关系执行,要么由政府工作人员承包和指导的私营公司执行。在公共部门的许多领域,存在着基于价值观和基于规则的等级制度,旨在以最小的成本取得成果。然而,由于公众缺乏监督一切的能力,存在着一种有利于机构而牺牲公民利益的信息不*衡。因此,公众和政府如何使用预测分析之间可能存在信息差距。政府机密的性质以及执法和国家安全信息的敏感性会加剧这种情况。
模型风险 —其他需要注意的地方是预测分析模型本身的风险。当它们是编程数据,不能准确说明构成实际情况的输入、输出和结果的广度时,就会发生这种情况。例如,在预测性警务模型中,风险将是仅使用由警察资源提供的数据,因为这将仅包括犯罪、逮捕或警察的其他行动。这可能导致一个基于过去有偏见的决定的回音室的决定,例如更高的警力和对某些少数群体的逮捕。至少,如果模型局限于那些向警方报告或由警方发现的犯罪,它将受到过去“犯罪”的不完整图片的影响。众所周知,并不是所有的犯罪都会被报道。相反,预测分析模型需要包括犯罪的第三方数据源(因为许多数据被少报了多达 50 %)和超出警方组织统计的结果。
孤立的数据科学家 —其中一些预测分析算法问题可能源于坏数据,但当数据科学家不一定了解他们正在处理的数据以及这些数据是如何收集的时,也会发现这些问题。这在政府中很常见,因为很少有机构拥有大数据、机器学习和预测分析的内部技能,并且通常依赖外部承包商或现成的产品解决方案。此外,预测分析所需的专业数据人员(通常从机构运营部门之外获得)和数据运营链(收集、编译、清理、转换)有可能增加模型的偏差或不准确性。
正当程序 —最后一个领域是对预测分析和大数据将如何影响正当程序的关注,以便组织或个人寻求纠正或不准确的决定,或者对宪法第五和第十四修正案中规定的行政部门决定进行司法审查。正当程序对我们的制衡制度很重要,因为它为受影响的公民提供补救,也为司法和立法监督以及行政部门的审查奠定基础。对许多公民来说,算法“黑箱”的性质可能排除传统形式的正当程序。
政府的本质是权力;权力,因为它必须放在人的手中,永远容易被滥用。
—詹姆斯·麦迪逊
政府实施预测分析的这些风险和潜在陷阱并非不可逾越。因为政府做出的决定有可能对公民产生重大影响,所以需要关注和监督。此外,如果公众没有理由相信政府的预测性分析决策,那么政府就不会获得信任和效率作为采纳的可能结果。
可能的解决方案
虽然以上所有的风险和担忧在当今世界都存在,但我相信所有的风险和担忧都有可能得到解决。政府试图在政府政策中说明这些风险的一种方式是通过透明度,例如根据《信息自由法》以及《行政程序法》和《文书工作减少法》中规定的规则。这些法律要求公开发布条例和规则草案,允许公众在修改定稿前提出意见和修改。此外,它们规定政府机构必须报告服务和福利申请所要求的数据和信息,以及这些数据和信息将如何被使用。此外,这些信息收集和计划在被批准实施之前,要接受司法审查,通常还要接受公众审查和评论。
独立机构监督 —我的提议是建立一个独立的第三方机构,负责几个领域,这些领域将直接减轻这些风险,并确保联邦政府准确、有效和高效地使用预测分析。该政策侧重于确保公众对预测分析计划的信任的机制,以及对算法的歧视性偏见、不准确性的独立审查和审计,并确保既定标准确实按照规定得到利用。
预测分析算法本身不可能进行同样的公开通知、公开审查和评论,因为系统的一些详细输入和输出过于敏感,不像乍看上去那么有用。学者们指出,大多数公民不具备必要的专业知识水*来理解和建设性地评论该算法。此外,那些具有理解它的专业知识水*的公民将能够针对输出的可能的不当行为和不当行为来玩弄预测分析模型,以便欺骗系统。
因此,该独立机构将接收所有预测分析计划和算法,以进行内部审计、审查和验证。未经批准,任何机构都不能实施他们的预测分析计划。除了审计以确保预测分析计划将产生预期的结果,审计还将寻找歧视性偏见和潜在的隐私损害。此外,该机构将保留预测分析计划的官方注册,以便在以后需要时允许司法和国会监督。这将减轻公众信任的担忧,以确保机构实际使用提议的预测分析系统和算法,这可以防止对机构不当行为的指控,因为这将允许将提议的系统与机构实际实施的系统进行比较。
限制 —本提案存在一些潜在的限制和挑战。首先,许多新的机构或办公室需要立法批准和资金。可以想象,这可以通过行政部门的授权开始,但资金必须从现有拨款中筹集。任何新的公共行政事业都需要资源。这可以通过向希望实施预测分析的机构收取独立机构的费用来实现,如经济法案所要求的。
此外,负责监督这些计划的机构同样需要资源,以确保机构的审查和批准请求得到快速裁定,从而使政府能够实现预测分析技术的有效性和效率增益。政府还必须投资于法律资源,致力于这一新兴技术,并确保有法律资源准备应对新的挑战和关注,它将提出。
然而,我认为,通过在决策中采用预测分析实现的准确性和效率收益不仅可以抵消这些资源支出,还有助于提高公众对政府裁决的信任度。
其他好处 —这家独立机构也将致力于以其他方式实施预测分析的联邦政府政策。首先,它可以成为政府的卓越中心,根据该领域的最新研究为联邦机构发布最佳实践和标准,并了解政府机构的需求。对预测分析项目进行审计的人员也可以向机构咨询现有的政府决策和项目,这些决策和项目可以从预测分析中受益。这将包括对信息技术需求、基础设施以及程序和流程开发的建议。
结论
最终,这些新技术将会存在,它们似乎为我们的政府利用数据做出更准确、客观和高效的决策提供了无数机会。正如我们在其他公众采用私营部门方法和技术的例子中所看到的那样,以不造成伤害或破坏公众信任的方式采用和实施这些新技术的能力将是公众反应的基础。公众的负面反应可能会导致立法者实施更严厉、更深入的监管和安全措施,这可能会抑制利用这些新技术的灵活性和敏捷性。因此,积极主动地采取这些步骤来采用减轻预测分析系统的潜在负面结果的政策,将大大有助于防止政治反弹。
当我们讨论政府机构在我们的民主中成功实施这些技术时,我欢迎其他想法,包括对这些想法的不同意见。
预测分析:
通过数据分析预测消费者行为
企业在推出新的服务或产品之前花费数百万美元进行市场调查,这并不奇怪。尽管如此,重要的是要认识到,最终产品不会自我销售,实际上需要正确的营销工具才能让潜在消费者看到自己。用传统的方法做这件事相当于承担了适量的风险——但不幸的是,企业无法承受试错法。这一直是一项具有挑战性的任务,但今天,随着消费者不断接触到新技术、产品和不断变化的“必需品”,赌注甚至更高了在数以百万计的购买选择中,这个时代的消费者的行为一直在闪烁!多亏了移动商务,购买一项简单的服务或产品不再是一项简单的任务;消费者在最终决定购买之前有很多东西要权衡。
然而,这还不是全部。即使一个产品碰巧是最好的,它仍然经常被遗弃在购物车中,因为买家很可能在其他地方找到了更好的交易或更有价值的替代产品。虽然企业失去潜在客户令人沮丧,但并非所有希望都破灭了。这正是数据分析发挥作用的地方。

Using data analytics to predict consumer behavior
如今,精通数字和商业的营销人员更喜欢将资金和信任投入到数据分析中,以更好地了解他们的客户和他们的行为。在一个数字化过度曝光的时代,将一个潜在买家塑造成一个忠诚的客户,需要对用户的偏好、动机、行为和购买习惯进行更深入的研究。因此,聪明的营销策略围绕着在智能工具的帮助下追踪潜在客户的数字足迹,使用数据作为他们的燃料。
今天,我们将快速了解分析世界,为什么我们需要主动而不是被动,以及预测分析如何帮助我们预测这个时代的消费者行为。
你说的“分析”是什么意思?
分析是对数据或统计数据进行系统的计算分析,以获得有意义的模式,以及应用这些模式做出有效决策的过程。
有三种类型的分析:
- 描述的
 - 预言性的
 - 规定的
 
但是,本次讨论的重点将是预测分析。因此,顾名思义,预测分析是使用数据或统计数据来获得可用于预测未来的有意义模式的过程。而描述性分析描述了过去,说明性分析有助于规划最佳行动方案。
公司仍在努力解释和实施这种新形式的分析,因为分析数据的技能仅限于少数数据科学家,他们通常不知道公司在预测消费者行为时的概念背景。然而,人们不应该对此感到害怕。福布斯进行的一项调查声称:
“监督预测性营销工作至少两年的绝大多数高管(86%)表示,他们的预测性营销提高了投资回报率(ROI)。”
因此,即使使用这种新的分析形式听起来有点可怕,人们也可以相信福布斯,并考虑投入其中。
分析消费者行为的理由
想象一下,如果你在顾客走进你的商店的那一刻就知道他想要什么,而你的库存中没有那件特定的商品。好吧,你可能最终会惹恼并永远失去一个潜在客户。如果你已经知道你的消费者想要什么,什么时候想要,不是更容易吗?要做到这一点,分析消费者行为至关重要
- 洞察:通过细分客户数据库来确定消费者细分。
 - 吸引和吸引潜在客户:通过分析过去的购买和个人资料,以相关优惠锁定细分客户。
 - 提高客户保留率:它允许企业评估客户价值,并使用主动保留方法来保留客户。
 

Predict your way to success
将预测分析应用于营销
虽然预测分析可以支持一系列其他商业活动,但营销是预测分析的最佳应用之一。因此,以下是预测分析在营销中的几种应用方式:
1。分段
细分围绕着将一个市场划分为具有相似特征(如人口统计、地理、行为或态度)的不同子群的过程。这样,企业主可以针对每个群体,更充分地满足他们的需求。
在这里,数据有助于开发您的目标细分市场,并为每个细分市场确定最有效的定位。在预测分析的帮助下,你甚至可以确定最“赚钱”的细分市场,并根据这些细分市场中的历史消费者行为相应地锁定他们。
营销经理使用这些数据将资源分配到真正需要的地方,也就是说,分配到利润最高的部分。
2。预测
预测分析的主要用途是开发预测销售和收入的需求模型,这对于制定预算至关重要。
3。需求定价
也称为收益管理需求定价,是根据消费者群体需求弹性的差异对产品和服务进行定价的过程。例如,像优步这样的服务在高峰时间收费更高,但每个人的费用并不相同。与临时乘客相比,上班族愿意为舒适的乘坐支付更多的费用,因此这些乘坐可以收取更多的费用,并且可以降低另一组乘客的价格,以满足 ROI(投资回报)目标,而不会在消费者中变得不受欢迎。
使用预测分析,人们可以设计实验,帮助企业找出影响价格对需求影响的因素,这有助于开发最有利的定价策略,最大限度地提高公司的财务增长。
4。提高客户满意度
如果你是向你的顾客销售,那你就做错了!现在是 2019 年,你的业务应该更多地服务于客户,而不是从他们的口袋里掏钱。
客户满意度对保留率和忠诚度有重大影响。一个满意的顾客等于一笔好生意。统计数据显示,失去一个客户的成本可能是留住一个客户的五倍。预测分析在留住客户方面发挥着至关重要的作用;像联合分析这样的工具使公司能够精确定位哪些产品/服务的改进能更大程度地提高客户满意度。
结论
预测分析是一种难以适应的强大技术,如果与正确的营销策略完美结合,可以有效预测消费者行为,帮助公司实现投资回报最大化。
预测性维护:使用 CNN 检测传感器故障
使用 python 代码和图形表示的有趣方法

Photo by Bruce Warrington on Unsplash
在机器学习中,随着时间的推移,预测性维护的主题变得越来越流行。这些挑战并不容易,而且非常多样化:对该领域有很好的了解或者与了解底层系统如何工作的人接触是很有用的。由于这些原因,当数据科学家投身于这个新的战场时,必须遵循线性和理性的方法,记住最简单的解决方案总是更好的。
在本文中,我们将研究一个分类问题。我们将在 Keras 应用一个由 CNN 制作的简单但非常强大的模型,并尝试对我们的结果给出一个直观的解释。
数据集
我决定从常青 UCI 仓库(液压系统的状态监控)获取一个数据集。
该数据集是用液压试验台通过实验获得的。该试验台由通过油箱连接的一次工作回路和二次冷却过滤回路组成。当四个液压部件(冷却器、阀门、泵和蓄能器)的状态定量变化时,系统周期性地重复恒定负载循环(持续时间 60 秒)并测量过程值,如压力、体积流量和温度。
我们可以设想有一个液压管道系统,该系统周期性地接收由于例如管道中特定类型液体的转移而产生的脉冲。这种现象持续 60 秒,由不同的传感器(传感器物理量单位采样率、PS1 压力棒、PS2 压力棒、PS3 压力棒、PS4 压力棒、PS5 压力棒、PS6 压力棒、EPS1 电机功率、FS1 体积流量、FS2 体积流量、TS1 温度、TS2 温度、TS3 温度、TS4 温度、VS1 振动、CE 冷却效率、CP 冷却功率、SE 效率因子)以不同的 Hz 频率测量。
我们的目的是预测组成管道的四个液压元件的状态。这些目标条件值以整数值的形式进行注释(易于编码),如果某个特定组件在每个周期都接*失效,则称之为 us 。
读取数据
每个传感器测量的值可在特定的 txt 文件中获得,其中每一行以时间序列的形式表示一个周期。
我决定考虑来自温度传感器(TS1、TS2、TS3、TS4)的数据,这些传感器以 1 Hz 的频率测量(每个周期 60 次观察)。
label = pd.read_csv(path+'profile.txt', sep='\t', header=None)
label.columns = ['Cooler','Valve','Pump','Accumulator','Flag']data = ['TS1.txt','TS2.txt','TS3.txt','TS4.txt']
df = pd.DataFrame()for txt in data:
    read_df = pd.read_csv(path+txt, sep='\t', header=None)
    df = df.append(read_df)
对于第一个周期,我们从温度传感器获得这些时间序列:

Temperature Series for cycle 1 from TS1 TS2 TS3 TS4
模型
为了捕捉有趣的特征和不明显的相关性,我们决定采用 1D CNN。这种模型非常适合于传感器时间序列的分析,并且要求在短的固定长度段中对数据进行整形。
在开发这个工作流程时,我从这篇文章中获得了灵感,这篇文章采用了一种非常有用的方法。我选择了在 Keras 网站上描述的 CNN,并刷新了参数。建立该模型是为了对冷却器组件的状态进行分类,只给定数组格式的温度时间序列作为输入(每个周期的 t_periods x n_sensor)。
num_sensors = 4
TIME_PERIODS = 60
BATCH_SIZE = 16
EPOCHS = 10model_m = Sequential()
model_m.add(Conv1D(100, 6, activation='relu', input_shape=(TIME_PERIODS, num_sensors)))
model_m.add(Conv1D(100, 6, activation='relu'))
model_m.add(MaxPooling1D(3))
model_m.add(Conv1D(160, 6, activation='relu'))
model_m.add(Conv1D(160, 6, activation='relu'))
model_m.add(GlobalAveragePooling1D(name='G_A_P_1D'))
model_m.add(Dropout(0.5))
model_m.add(Dense(3, activation='softmax'))
print(model_m.summary())model_m.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])history = model_m.fit(X_train, y_train, batch_size=BATCH_SIZE, epochs=EPOCHS, validation_split=0.2, verbose=2)
在这种情况下,仅用 10 个纪元,我们就能取得令人难以置信的结果!
Train on 1411 samples, validate on 353 samples
Epoch 1/10
1411/1411 [==============================] - 2s 2ms/step - loss: 0.2581 - acc: 0.9391 - val_loss: 0.0867 - val_acc: 0.9830
Epoch 2/10
1411/1411 [==============================] - 2s 1ms/step - loss: 0.1111 - acc: 0.9731 - val_loss: 0.0686 - val_acc: 0.9830
Epoch 3/10
1411/1411 [==============================] - 2s 1ms/step - loss: 0.0925 - acc: 0.9759 - val_loss: 0.0674 - val_acc: 0.9802
Epoch 4/10
1411/1411 [==============================] - 2s 1ms/step - loss: 0.1093 - acc: 0.9731 - val_loss: 0.0769 - val_acc: 0.9830
Epoch 5/10
1411/1411 [==============================] - 2s 1ms/step - loss: 0.1022 - acc: 0.9731 - val_loss: 0.0666 - val_acc: 0.9802
Epoch 6/10
1411/1411 [==============================] - 2s 1ms/step - loss: 0.0947 - acc: 0.9773 - val_loss: 0.0792 - val_acc: 0.9830
Epoch 7/10
1411/1411 [==============================] - 2s 1ms/step - loss: 0.0984 - acc: 0.9794 - val_loss: 0.0935 - val_acc: 0.9830
Epoch 8/10
1411/1411 [==============================] - 2s 1ms/step - loss: 0.0976 - acc: 0.9738 - val_loss: 0.0756 - val_acc: 0.9802
Epoch 9/10
1411/1411 [==============================] - 2s 1ms/step - loss: 0.0957 - acc: 0.9780 - val_loss: 0.0752 - val_acc: 0.9830
Epoch 10/10
1411/1411 [==============================] - 2s 1ms/step - loss: 0.1114 - acc: 0.9738 - val_loss: 0.0673 - val_acc: 0.9802
对试验数据进行预测,模型的准确率达到 0.9909%。

每个班的 KPI 都很牛逼!这一结果对于 3 级(部件冷却器“接*完全失效”)尤为重要,因为通过这种方式,我们能够检测并防止系统中可能出现的故障。
将结果可视化
如果我们想对系统状态有一个总体的了解,并看到我们的模型的不可思议的优点,看一个图形表示可能是有用的。为了达到这个目标,我们重新利用我们在上面建立的 CNN 来制作解码器,并从每个周期的时间序列中提取巧妙的特征。使用 Keras,这在一行代码中就可以实现:
emb_model = Model(inputs=model_m.input, outputs=model_m.get_layer('G_A_P_1D').output)
新模型是一个解码器,它以与我们用于分类任务的 NN 相同的格式接收输入数据(每个周期的 t_periods x n_sensor ),并以嵌入的形式返回“预测”,该嵌入来自具有相对维度的 GlobalAveragePooling1D 层(每个周期的一行 160 个嵌入变量)。
使用我们的编码器对测试数据进行预测计算,采用一种降维技术(如 PCA 或 T-SNE ),并绘制结果,我们可以看到这种魔力:
serie_features = emb_model.predict(X_test)
tsne = TSNE(n_components=2, random_state=42, n_iter=300, perplexity=5)
T = tsne.fit_transform(serie_features)plt.figure(figsize=(16,9))
colors = {0:'red', 1:'blue', 2:'yellow'}
plt.scatter(T.T[0], T.T[1], c=[colors[i] for i in np.argmax(y_test, axis=1)]) 
plt.show()

TSNE on cycle embeddings for test data
哇哦!!!这个图讲的是事实!每个点代表测试集中的一个循环,相对颜色是较冷条件的目标类别。可以看出冷却器组件的目标值之间的区别是如何定义的。这种方法是我们模型性能的关键指标。
摘要
在这篇文章中,我们试图解决一个预测性维护的问题,用 CNN 对时间序列进行分类。开发了一个具有令人印象深刻的性能的强大模型。我们还试图给出结果的可视化表示。重要的是要强调 CNN 的力量,不仅是在预测方面,而且是作为一种工具来检测数据之间的无形关系。
如果你对题目感兴趣,我建议:
保持联系: Linkedin
LSTM 暹罗网络的预测性维护
从传感器时间序列中检测故障

如今,预测性维护是一个活跃的领域,其中人工智能解决方案被引入以提高各种制造系统的生产率。典型的请求包括开发一个解决方案,当观察到的组件的特定部分接*失败时,该解决方案产生警告。可以猜到,这些是典型的“不*衡情况”,我们有来自各种传感器的大量数据,但缺少阳性标记样本,阳性样本表示存在故障。
在以前的一篇文章中,我介绍了一个解决方案,该方案对液压管道系统中特定组件的退化状态进行分类;结果很酷!现在,我尝试开发一种管道来检测存储系统是否接*故障。我们希望利用神经网络对来自传感器的连续时间序列进行分类。特别是,我使用适合时间序列的暹罗网络和 LSTM 架构,避免了缺乏故障样本的问题。
数据集
和往常一样,我更喜欢用真实的数据工作。我在 Kaggle 上发现了一个奇妙的数据集:能源优化的高存储系统数据,由智能工厂发布。数据集存储 4 条短传送带(BLO、BHL、BHR、布鲁)和 2 条轨道(HR、HL)的信号。

How the storage system works (source)
高位存储系统是为了在两个地点之间运输一个包裹而建造的。中间的两条传送带在不水*移动包裹的情况下只能垂直移动。中间的两条传送带可以水*移动包裹,也可以垂直移动。提供了整个系统的两次运行:优化和未优化。我使用了HRSS _ 异常 _ 优化. csv ,它包含了失败的优化运行。
我们有 19634 个时间观察结果,分成 111 个周期和 4517 个记录的故障。每次循环开始时,时间戳被设置为 0。这些周期不一定是一个接一个地记录下来的。他们之间可能有更大的时差。

Failure occurrences (orange) in cycles (blue)
对于每个周期,我们在 4 条传送带和 2 条轨道上放置了 18 个传感器,用于监控它们的活动。

standard deviations of sensor features in all the cycles
在开始考虑模型之前,我们必须花相当多的时间来考虑清理和预处理。在这种情况下,数据总是非常嘈杂,充分的初步处理对于获得良好的结果至关重要。我们没有缺失值,但是我们的传感器系列具有巨大的幅度差异,如 std 条形图所示。为了减少这种差异,我采用了三步预处理工作流:
- 将我们的数据分成不同的周期;
 - 将每个传感器值作为相对循环开始时间的增量来处理;
 - 使用标准缩放方法缩放增量。
 
所有这些程序都必须小心进行!我们不想污染我们的数据和损害我们的结果。由于这些原因,一开始就建立一个最佳的验证策略是很重要的。在我们的例子中,我们必须处理时间序列,所以最常见的验证方法是通过保留时间相关性来验证我们的结果。我想在最新的部分数据(最新的 10%)上测试我的模型;鉴于''最新部分【T3]'我打算每个周期的最后 10%。因此,有了这个概念,操作特定的预处理就更容易了。
模型
正如开头所介绍的,我们试图通过一个连体网络提前一步对系统中可能出现的故障进行建模。理解暹罗系统如何工作是非常简单和直观的。它接收一个双输入,并在此基础上计算嵌入距离。模型的范围是验证两个样本在空间上是相似还是相距较远。所有的过程可以作为一个二元分类任务来处理,其中阳性样本属于同一类(因此它们是相似的)。
暹罗原理经常应用于图像识别,我们尝试转换应用领域来处理预测维护领域中的一个时间序列分类问题。这一程序的好处是避免缺乏重要类别的未标记样本,即在预测性维护中,它等同于缺乏故障证据。
前提听起来不错!因此,要完成这项惊人的任务,最完美的工具就是强大的 LSTM。我们将建立我们的暹罗网络,采用由 LSTM 层组成的顺序编码器。
def SiamesNet(): left_input = Input((sequence_length, len(features)))
    right_input = Input((sequence_length, len(features))) lstmnet = Sequential([
        BatchNormalization(),
        LSTM(128, activation='relu', return_sequences=True,
             input_shape=(sequence_length, len(features))),
        LSTM(32, activation='relu')
    ]) encoded_l = lstmnet(left_input)
    encoded_r = lstmnet(right_input) L1_layer = Lambda(lambda tensor: K.abs(tensor[0] - tensor[1]))
    L1_distance = L1_layer([encoded_l, encoded_r]) drop = Dropout(0.2)(L1_distance)
    prediction = Dense(1,activation='sigmoid')(drop) model = Model(inputs=[left_input,right_input],
                  outputs=prediction) return model
选择 LSTM 结构意味着以顺序样本的形式管理数据。我们将初始时间序列分成一系列 8 个时间步骤,注意避免与循环开始重叠(在代码中,这个过程与预处理工作流一起计算)。

example of standardized sequence sample
我们从序列的训练群体中随机选择生成训练对。通过这种方式,我们能够大幅增加可供我们使用的样本数量。有了生成的线对,我们就准备好去适应暹罗网络了。在这个阶段的最后,我们必须进行验证。检查这种系统的性能并不总是立竿见影的。网络适合接收双输入,所以我们必须一次给它传递两个序列。其中一个肯定是我们的测试序列,另一个来自火车。首先,我们将测试与从故障类别中随机选择的训练序列相结合。其次,我们将它与非故障样本配对。因此,我们同时计算两个预测,以验证测试样本所属的最接*的类。最大相似性分数定义了我们的测试序列属于哪个类。
对于(特定类别的)成对测试序列/训练序列重复 N 次随机选择和预测的过程,可以获得结果的稳定性。假设通过进行上述 N 次比较,我们得到了单个类的 N 个相似性分数。我们可以通过取最大值或*均值(我选择最大值)等其他统计数据来总结它们。所以在这个程序之后,我们可以用一个经典的方法来检查性能。

我们能够以一种有价值的方式提前一步识别一些故障序列。我们可以预测大约 15%的限制误报数量的中断(高精度),这可以被认为是存储系统的良好起点。
摘要
在这篇文章中,我提出了一个提前检测故障的解决方案。我想在这个特殊而臭名昭著的任务中运用 LSTM 层的暹罗网络的力量。这种结构,结合适当和巧妙的预处理工作流程,允许我们“忽略”缺少阳性标记样本,并训练一个模型,该模型在特定时刻对我们系统的状态进行分类。
如果你对题目感兴趣,我建议:
保持联系: Linkedin
预测营销:以下是大数据如何重新定义我们的营销策略
数据已经并将永远是每个产品营销活动的关键,今天营销空间的性质使数据成为无可争议的王者。
我有超过 10 年的媒体、产品和营销经验。在决定下一步做什么之前,我总是使用数据。但直到几年前,它还只是基于市场上的分析工具。然后,随着数据科学的繁荣,我们遇到了预测营销,使我们不仅可以利用过去的数据,还可以预测未来。

Photo Credit: Unsplash, by @ pietrozj
预测营销的权威指南
我也在传统媒体工作过,但数字化已经接管了大量的营销,现在决定了我们如何看待品牌,并最终决定我们使用的新工具或购买的决定,这已经不是新闻了。预计全球将有 1.9 万亿人在网上购物。而在美国,79%的人已经进行了网上购物,而 2002 年只有 22%。然而,令人兴奋的是数字营销过程中的复杂程度,以控制更好的线索并增加销售机会。
随着技术的几次飞跃,市场营销变得越来越复杂。随着新兴公司完全基于网络,数字营销——在互联网和电子设备上为产品和服务做广告——已成为企业超越传统营销的关键。
正如数字营销已经成为我们业务的核心一样,市场数据已经成为营销过程中成功的重要决定因素。不用说,数据已经并将永远是我们每一次营销活动的关键,今天的数字营销空间的性质使数据成为无可争议的王者。
我们使用从多个市场来源获得的数据来做出明智的营销决策,例如如何最好地定位广告和理想的营销预算。为了改进营销决策,我们引入了更复杂的方法来更好地利用数据、分析数据,并在营销中利用数据来实现更好的结果。我们可以用预测营销这个术语来描述这些进步中的一个。
什么是预测营销?
预测营销,顾名思义,是一种决定不同营销策略成功概率的营销技术。除了流行词,这是 MarTech 的一个子集,其前提是营销和销售是由数据驱动的。
因此,在预测营销中,我们使用数据科学(或数据分析)来预测哪些营销行动更有可能成功,哪些更有可能失败。我们可以将所涉及的数据分析部分称为预测分析。
预测分析与预测营销
虽然这两个术语可以互换使用,但预测营销将商业营销的预测分析向前推进了一步,具有更广泛的含义。预测分析使用预测模型来提供对未来的洞察,而预测营销使用预测技术来测试企业的营销策略,在连续(有时是迭代)的过程中提供洞察并做出更好的营销决策。
在一个简单的场景中,预测营销专家(通常是数据科学家、数据分析师或分析公司)从多个来源收集关于企业的数据,并与公司的营销和客户数据一起进行分析。有了这些信息,数据科学家应用适合业务的预测模型,并以一定的准确度预测其营销工作的成功。
预测营销的工作原理
预测营销的一个经典案例是电子商务网站,它根据用户过去的行为向用户推荐产品和服务。从产品搜索页面到结账台,这些网站确保每一个回头客都受到这些产品推荐的狂轰滥炸。这些推荐是该网站“协同过滤”的产品,基于对客户行为的研究,如客户购物车中的商品或客户或其他客户过去互动或购买的商品。该算法的实际内容通常更加复杂,可能会将数据与时间、位置、人口分布以及包括打开率、点击率和选择退出率在内的大量其他指标相关联。
但不再是只有大公司才能负担得起昂贵的内部数据科学家,他们可以从预测营销技术中受益。我们的内部预测营销专家还从多个来源收集数据,并为我们的业务建立预测营销模型。他们已经获得了该公司的营销和客户数据,以及关于营销工作的信息。然后,数据分析师可以预测公司营销工作的成功。

Photo Credit: Unsplash, by @ arifrw
预测营销的好处
预测营销的相关性与数字营销中的数据科学非常相似。
首先,预测技术让营销人员更好地了解客户行为。与常规营销数据分析略有不同的是,预测营销工具直接提供决策,而数据科学家不必单独解释数据和提出建议。换句话说,预测营销模型准确地说明了什么样的营销策略可能有效,什么样的营销策略无效,从而使决策更容易做出。预测营销模型可以告诉客户是否会购买,何时以及如何购买,以及其他特定业务的预测,所有这些都基于从客户那里获得的数据。
通过分析客户以前的行为,数据供应商还可以帮助公司在营销预算管理、市场活动规划、线索挖掘和转化策略等方面做出决定。因为它基于对来自客户的大量不同数据的分析(而不是直觉和猜测),预测营销的决策更有针对性,并产生更好的结果。
此外,预测分析使我们的公司更接*自动化营销系统或专家所说的规范营销。在这个层面上,营销系统自动分析数据并实时做出决策。模型生成、销售线索评分和更新客户洞察等活动将即时发生。在这种熟练程度下,我们能够显著提高客户参与度,因为我们可以轻松细分客户,并部署量身定制的营销活动。这样的结果是显而易见的;必须优化我们的营销预算,提高销售线索得分,增加销售收入。
预测分析是数据驱动营销的支柱,根据 Jas Saran, Forbes 的说法,它可以改善公司在至少六个领域的营销工作,包括营销组合建模、向上销售和交叉销售、网络优化、客户获取、特征分析和保留。
以下是预测营销让我们的创业环境受益的一些具体方式:
我们如何通过预测营销为客户特征分析、客户获取和客户保持提供支持
复杂的预测营销模型有助于企业根据客户过去的行为和对未来行为的洞察,创建特定和独特的客户身份。因为用于形成预测营销模型的数据通常非常详细,围绕这些数据构建的营销工作往往具有更高的转化率。
当营销工作精确且只针对正确的客户时,客户获取工作变得更加有效和高效。再次,由于预测营销模型,营销人员可以定制营销活动和客户获取策略,以适当细分的潜在客户群的不同部分,具有高转换概率。
同样,对客户未来行为的洞察有助于企业规划其客户维系战略。当公司知道可能离开的客户群、他们可能离开的时间以及使他们离开的条件时,公司可以为每个客户群设计定制的保留计划,并根据一般假设消除一揽子努力。当企业了解这一点时,它就可以向现有客户进行追加销售和交叉销售,从而获得更高的成功概率。
以下是我们如何利用预测营销改进电子邮件营销和网站参与度
根据预测智能基准报告,使用预测智能的电子邮件营销活动产生最高的影响收入。在预测营销之前,营销人员不得不依靠广泛的概括(有时称为人物角色)来创建电子邮件,其中很多都不会被打开。但预测营销改变了游戏规则,它赋予营销人员特定的信息来创建个性化的电子邮件,从而提高了打开率和参与度。
这里有一个有趣的统计数据:“备货电子邮件”和废弃产品电子邮件活动——可以通过预测营销模型实现——的点击率最高,分别为 19%和 14%。
类似地,使用预测营销模型的网站可以通过研究网站访问者的行为来提高参与度和销售额,尤其是围绕广告横幅、产品页面和动作按钮等网络资产。他们可以利用从访问者和客户那里收集到的信息来优化网络体验。
总之,预测营销旨在预测促使客户购买产品的条件,并帮助企业优化定价和影响客户行为的其他因素。以亚马逊为例,据报道,当引入基于其预测分析模型的推荐时,该公司实现了约 30%的销售额增长。

Photo Credit: Unsplash, by @ srd844
预测营销如何削减 B2B 营销成本
企业对企业(B2B)营销是预测分析非常重要的领域,尤其是在降低营销成本和提高效率方面。一个 B2B 的成本可能从 35 美元到 100 美元或更多,视情况而定。这种高成本使得低转化率真的成本很高。在每条线索 50 美元的情况下,1%的转换率将使 B2B 营销人员仅在线索生成方面就花费 5000 美元。
因此,这并不令人惊讶,许多企业正致力于预测营销解决方案,以更好地瞄准他们的营销努力,以获得更好的投资回报。
这里有一个有趣的数据:在 Eversrting 的预测营销调查中,98%的营销人员至少拥有 CRM、营销自动化和一些营销工具,要么完全致力于或已经实施预测营销。
B2B 预测营销:使用案例和最佳实践
对于 B2B 营销人员来说,预测营销或多或少正在成为一种不可或缺的方法。正如我们所见,这种方法为营销人员节省了一些营销成本,这对于 B2B 业务来说是相当可观的。除此之外,根据预测营销的使用案例,预测营销为营销人员提供了一些优势。这里有几个。
B2B 客户拓展
首先,B2B 营销人员可以通过整合预测营销获得高质量的新线索。为此,营销人员通过公司信息和特殊信号应用预测营销模型,以较高的准确度识别潜在客户。
公司规模、产品和收入等信息在预测营销模型中与业务扩张、管理层变动等信号和成千上万的其他公司数据一起分析时,可以确定有资格成为潜在客户的公司行为。使用预测分析模型,营销人员可以生成具有这种行为的类似企业的长列表,作为 B2B 机会的数据库。

Photo Credit: Unsplash, oowgnuj
B2B 销售线索评分(销售线索优先排序)
获得潜在客户名单后,B2B 营销人员需要决定哪个潜在客户值得首先出手;这是更有可能成为客户的潜在客户。为了做到这一点,营销人员再次使用预测营销模型来对线索进行优先排序。
线索评分至关重要,因为它告知营销人员如何进行营销工作;应该追求哪些前景,何时追求,如何追求。通过使用预测模型,B2B 营销人员提高了手动建立线索评分公式的效率。所使用的预测模型可以基于购买的可能性或终身收入、盈利能力、促销响应、销售接受度或各种因素的组合。这取决于业务目标和优先级。
B2B 销售线索细分
接下来,B2B 营销人员可以再次借助预测营销技术将潜在客户划分为不同的细分市场。一个理想的模型将创建客户的人物角色,并根据他们的特征和行为将潜在的客户分组。
这些细分基于个人兴趣、公司特征,有趣的是,还有过去的行为。由于过去的客户行为是预测未来行动的可靠而准确的基础,基于预测营销模型的潜在客户群往往会提供更个性化的营销方法,从而产生更高的转化率。
线索细分对整个 B2B 营销过程至关重要,因为它有助于确定每个细分市场的确切方法,而不是一般的营销驱动。除了很大程度上是静态的人物角色,预测营销模型允许营销人员生成动态的细分市场,如“参与度”,这些细分市场经常变化,并且每次都定制营销方法。
主动销售整合
由于预测营销模型创建了动态的客户细分,它使销售团队能够及时获得有关其前景的信息(比如预测)。结合质量线索优先排序,预测模型有助于使销售工作更加主动、及时和高效。例如,一个模型可以预测某个客户群最有可能购买的时间段,并提示销售团队在该时间段内加强对该客户群的努力。
来自预测分析的其他信息,如基于过去决策的决策层次结构,可以帮助销售团队更好地协调他们的工作,并个性化他们的销售宣传。同样,销售团队可以更好地了解何时进行追加销售和交叉销售。
管理 B2B 客户的整个生命周期
除了产生和优先考虑高质量的线索,预测营销技术还帮助营销人员在客户生命周期中产生更大的影响。这些模型支持营销人员通过在销售过程的每个阶段提供关于客户的及时信息来吸引客户。
一些常见的 B2B 预测营销模式
实际的预测营销模型通常分为三类即:侧重于对潜在客户进行分组的细分模型,跟踪获得或搅动客户的可能性的倾向模型,以及预测哪些客户可能需要更多营销努力的智能推荐——通常是追加销售或交叉销售。
细分模型根据产品(基于产品的聚类)和行为(行为聚类)对潜在客户或客户进行分组,而倾向模型则根据客户钱包、竞争、其他客户的模式等因素,通过指出危险信号和机会,寻求保持和扩大客户群的方法。智能模型——规范营销的先驱——确定更好地吸引现有客户的领域。
预测营销的数据供应商和 SaaS 提供商
虽然与数据科学相关的服务似乎很昂贵,但它们更容易被常规企业接受,不像早期那样只有大公司才能负担得起聘请数据科学家团队的费用。由于越来越多的数据供应商和软件即服务(SaaS)系统提供基于云的预测分析。
以下是预测营销领域的一些领先数据供应商:
Everstring 拥有强大的预测营销引擎和全功能数据管理*台。自 2012 年上线以来,它已经为包括康卡斯特在内的许多知名客户提供了服务
Infer 专门从事契合度评分,预测哪个未来潜在客户准备购买,然后创建一个潜在客户数据库。销售和营销软件公司 HubSpot 使用 Infer 的 fit 建模。
6sense,服务于戴尔和联想,是预测市场领域的后来者之一。它强调预测客户意图和决策的能力,也称为意图评分。
LeadSpace 是一家社交媒体数据供应商,整合了预测性营销见解,以提高净新线索的质量。微软和 Adobe 使用 LeadSpace。

Photo Credit: Unsplash, franki
预测营销是 B2B 营销的未来
从活动中获得高质量的结果后,任何人都可以很容易地认为营销的未来是自动化,而自动化的核心是预测营销。
根据 Everstring & Forrester 报告,B2B 营销人员越来越多地采用预测营销。以下是一些重要的发现:
预测营销人员(41%)报告的收入增长是行业*均水*的 2.9 倍,相比之下,14%的回顾营销人员报告了积极的业务成果。
一半的预测营销人员声称在他们的产品和服务类别中处于领导地位,相比之下,只有 24%的回顾营销人员这样认为
49%的预测营销人员表示,他们的组织一直超过公司基准,相比之下,只有 28%的回顾营销人员能够有效地为他们的业务提供类似的价值。
在这三个方面,预测营销——以及一般的数据分析驱动的营销——正在为 B2B 营销人员设定节奏。据 Salesforce 称,91%的顶级营销人员已经在实施预测营销。它也吸引了商业金融家的注意。仅在几年内,风险资本家和行业参与者就在预测营销和类似的数据驱动营销上投入了超过 50 亿美元。
预测智能基准报告还显示,预测智能建议影响了总订单的 26.34%。经过 36 个月的分析,受影响的订单总数从 11.47%增加到 34.71%。
预测营销的挑战
我非常担心预测营销会取代人类的贡献。预测营销技术的一个主要挑战在于,随着系统走向全自动营销分析,如何去除“人”的贡献。一些专家同意,人类仍然有一些优势,通过自动预测系统增加人类贡献的限制可能会对销售产生负面影响。
作为一项新兴技术,采用方面的担忧将一直存在,尤其是在数据分析非常昂贵的情况下。然而,随着企业可以轻松插入的可扩展 SaaS 解决方案的增长,它正在帮助 B2B 营销人员从预测性营销洞察中受益,而不会破产。最后,对数据质量、数据量、数据相关性和隐私问题等数据科学的关注也会影响预测分析。

Photo Credit: Unsplash, sortino
结论
在采用预测营销后,我们在 Smartereum 和 WhatsAround 的业务都在增加流量、销售线索和收入方面获益。我们能够通过自动对销售线索进行分级来支持我们的销售团队,并将我们的重点放在最佳业绩上。
预测建模和多类分类:应对 Taarifa 挑战
对于多类预测任务,我们如何使用最*邻分类模型、决策树和支持向量机?
简介
分类预测问题是数据科学中最常遇到的问题之一。在本文中,我们将使用三个主要的分类家族来解决一个多类分类问题:最*邻、决策树和支持向量机(SVMs)。
数据集和原始代码可以通过这个 GitHub 链接访问。
挑战
本文解决了与本文中介绍的相同的挑战。虽然这篇文章是关于预测建模和多类分类的独立文章,但是如果您想知道我是如何清理数据集以用于建模的,您也可以查看那篇文章!(另外,如果您直接从那篇文章而来,请随意跳过这一部分!)
我在这篇文章中使用的挑战来自 Drivendata.org。你可以把它想象成一场挑战社会影响的游戏。你仍然可以获得同样的奖金和格式良好的数据集,额外的好处是你将对世界产生积极的影响!
我们在这篇文章中使用的特殊挑战叫做“ 向上泵:数据挖掘地下水位 ”面临的挑战是创建一个模型,该模型将预测特定水泵(“water point”)的状况,因为它有许多属性。
数据由 Taarifa 提供,这是一个开源 API,收集这些数据并呈现给世界。如果你对他们的工作和他们的数据点代表什么感到好奇,一定要去看看他们的网站(和 GitHub !)
数据
我们的原始数据集(由挑战赛提供)有 42 个特征的 74,000 个数据点。在上一篇关于数据预处理和探索性数据分析的文章中,我们将其转换为包含 114 个特征的 74,000 个数据点的数据集。特征数量的增加主要来自于的一键编码,我们将分类特征扩展为每个类别的多个特征。实际上,我们在一次性编码之前已经删除了超过一半的特性,从 42 个特性减少到仅仅 20 个。剩下的 20 个特性的一键编码引导我们找到了这里的 114 个特性。

You can see that all of our “new” features are the results of one-hot encoding. The feature title is “original_feature_name” and “class” combined together, with 0 or 1 for whether a data point belongs to that class.
数据准备
目前,我们的测试数据集没有与之相关联的标签。为了查看模型的准确性,我们还需要测试数据集的标签。尽管很痛苦,我们现在还是要放弃测试数据集。我们可以在训练完所有模型并决定最终提交时使用哪个模型后重复使用。
train = df[df.train==True].drop(columns=['train'])
X = train.drop(columns=['status_group'])
y = train.status_group
数据分割
我们将从我们的训练数据中创建一个人工测试数据集,因为训练数据都有标签。让我们从训练数据集中随机抽取三分之一的样本,并将其指定为模型的测试集。我们可以使用 scikit-learn 的 train_test_split 包(或者“sklearn”)。
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.33, random_state=1)

Our training dataset now has about 40,000 data points while our testing dataset has about 20,000. That’s a good 2:1 split!
数据输出不*衡
让我们在这里快速复查一下我们的标签余额。

The percentages of outputs per our training and testing datasets.
看起来我们的随机分裂做得很好!我们的输出*衡与我们的训练和测试数据集非常一致。输出类有点不*衡,我们稍后会谈到。
建模
虽然我们可以使用许多类型的分类器,但它们通常分为这三类:最*邻居、决策树和支持向量机。我们将从每个模型系列中挑选一个示例模型。
请注意,我们的任务是一个多类分类问题。虽然有很多方法可以进行多类逻辑回归,但我们在这里不做。
我们的特征之间也有很多关系。这或者是因为它们对应于相似的方面(例如纬度和经度),或者是一次性编码的结果。这就是为什么我们在这里也不做朴素贝叶斯模型的原因。
Taarifa 采用的指标是“分类率” —模型正确分类的百分比。我们来看看每个模型的分类率和运行时间。
# packages required for metrics
import time, math
from sklearn.metrics import accuracy_scorecols_results=['family','model','classification_rate','runtime']
results = pd.DataFrame(columns=cols_results)results
k-最*邻
对于我们的最*邻分类器,我们将采用 K-最*邻(KNN)模型。KNN 是一个"懒惰分类器"-它不构建任何内部模型,而只是"存储训练数据集中的所有实例。
所以,一个 KNN 没有“训练时间”——反而在预测上花了很多时间。当我们有一个大的数据集,并且 KNN 必须评估新数据点和现有数据点之间的距离时,这尤其糟糕。
让我们看看 k = 1 到 9 时,KNN 在精度和时间上的表现。(记住 k=1 的 KNN 只是最*邻分类器)
from sklearn.neighbors import KNeighborsClassifierkVals = range(1,10)
knn_names = ['KNN-'+str(k) for k in kVals]for k in kVals:
    knn = KNeighborsClassifier(n_neighbors=k)
    knn.fit(X_train, y_train)
    time_start = time.time()
    y_pred = knn.predict(X_test)
    time_run = time.time()-time_start
    results = results.append(pd.DataFrame([['KNN',knn_names[k-1],accuracy_score(y_test,y_pred),time_run]],columns=cols_results),ignore_index=True)results[results.family=='KNN']

The results of our KNN models! Runtime is in seconds.
好了,我们知道答案了。让我们想象一下他们做得有多好,花了多少时间
fig, ax = plt.subplots()
ax.plot(kVals,results[results.family=='KNN'].classification_rate,color='blue',marker='o')
ax.set_xlabel('k-value for KNN models')
ax.set_ylabel('classification rate (blue)')
ax2=ax.twinx()
ax2.plot(kVals,results[results.family=='KNN'].runtime,color='red',marker='o')
ax2.set_ylabel('runtime (seconds; red)')
plt.show()

The accuracy (classification rate; in blue) and runtime (seconds, in red) for KNN models of different k-values.
准确度在开始时确实有点波动,但随着我们考虑更多的邻居,逐渐稳定在 67%左右。运行时间通常随 k 值线性增加。
随机森林
对于我们基于决策树的模型,我们将创建一个随机森林。随机森林是一种在训练数据集的子集上创建多个决策树并取得一致结果的方法。由于这种随机子集化方法,随机森林对过度拟合具有弹性,但比单一决策树需要更长的训练时间。
让我们看看由 1 棵树(这只是一个决策树)、10 棵树、100 棵树和 1000 棵树组成的随机森林的情况。
from sklearn.ensemble import RandomForestClassifier
rVals = range(1,4)
rf_names = ['RF-'+str(int(math.pow(10,r))) for r in rVals]for r in rVals:
    clf = RandomForestClassifier(n_estimators=int(math.pow(10,r)),random_state=0)
    time_start = time.time()
    clf.fit(X_train,y_train)
    time_run = time.time()-time_start
    y_pred=clf.predict(X_test)
    results = results.append(pd.DataFrame([['RF',rf_names[r-1],accuracy_score(y_test,y_pred),time_run]],columns=cols_results),ignore_index=True)
results[results.family=='RF']

The results of random forest classifiers.
让我们看看他们是如何想象的。

The accuracy and runtime for random forest classifiers.
正如所预料的那样,运行时间几乎与随机森林中决策树的数量成线性增长。然而,精确度并没有增加多少,大约在 80%左右。
SVM
支持向量机利用所谓的"内核技巧为您的数据创建超*面分隔符(即非线性问题的线性分隔符)。虽然支持向量机在理论上“可能”过拟合,但是核的可推广性通常使它能够抵抗小的过拟合。
支持向量机确实倾向于花费大量的时间,并且它的成功高度依赖于它的内核。在这个数据集(100 个特征的 40k 个数据点)上运行一个纯 SVM 将花费很长时间,因此我们将使用 sklearn 提供的 BaggingClassifier 库创建一个“袋装分类器”。BaggingClassifier 将采用一个基础模型(对于我们来说,是 SVM),并在数据集的多个随机子集上训练多个基础模型。对于我们来说,让我们每次在 1%的数据(大约 400 个数据点)上为每个内核训练 10 个 SVM 模型。
让我们来看看我们的模型对于三种不同的内核的效果如何:线性、RBF、和 sigmoid 。 Sklearn SVC 库也给了我们 poly 内核,但是即使在缩减的数据集上也要花很长时间来训练,所以我们在这里不做了。

The accuracy and run time for SVM models on three different kernel types
让我们也想象一下这些 SVM 模型的准确性和运行时间。

Accuracy for SVM models

Run time for SVM models. Compared to the linear kernel, RBF’s and sigmoid’s <1 second runtime is not visible.
线性核确实表现出最高的准确性,但是它有一个可怕的训练时间。考虑到我们采用了最多取 10%数据的 bagging 方法(=10 个支持向量机,每个支持向量机占数据集的 1%),准确性实际上非常令人印象深刻。
结果
让我们比较一下我们所有模型的准确性和运行时间!


The accuracy and runtime of the many classifiers we have tried out in this article.
似乎随机森林给出了最好的结果——接* 80%的准确率!一个只有 100 棵树的随机森林只需要很少的训练时间就可以达到最好的结果之一。线性支持向量机和 KNN 模型给出了下一个最好的结果。但是除了将模型相互比较之外,我们如何“客观地”知道我们的模型做得有多好?
基本情况:随机分类器
对于任何分类任务,基础案例是一个随机分类方案。一种方法是创建随机分类器,对输入进行随机分类并比较结果。标签的随机分配将遵循培训时分配给它的标签的【基础】比例。
from sklearn.dummy import DummyClassifierclf = DummyClassifier(strategy='stratified',random_state=0)
clf.fit(X_train,y_train)
y_pred = clf.predict(X_test)
print('Accuracy of a random classifier is: %.2f%%'%(accuracy_score(y_test,y_pred)*100))

对于 45%的基本精度,我们所有的模型在精度方面都做得很好。
类别不*衡——采样不足
最后,我们回到我们在开始提到的阶级不*衡问题。标签的不*衡导致分类器偏向多数标签。对我们来说,它是朝向“功能性”标签的。
我们已经看到,在一半时间内预测“功能”标签的分类器(“功能”标签占数据集的 54.3%)已经达到 45%的准确度。这已经远远好于均匀随机猜测的 33% (1/3)。
如果类彼此明显分离,类不*衡可能不会影响分类器,但在大多数情况下,它们不会。为了看看阶级不*衡是否影响了我们的模型,我们可以欠采样数据。
*衡欠采样意味着我们从数据中随机抽取样本,其中类别是“*衡的”这可以通过使用 imblearn 库的 RandomUnderSampler 类来完成。可以把 imblearn 想象成一个不*衡数据集的 sklearn 库。
from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler(random_state=0)
X_rus_train,y_rus_train = rus.fit_resample(X_train,y_train)
X_rus_test,y_rus_test = rus.fit_resample(X_test,y_test)
虽然我们的原始 X_train 有将* 40,000 个数据点,但我们的欠采样数据集只有大约 8,700 个数据点。让我们通过我们最成功的模型——随机森林——运行它,看看欠采样是否会影响我们的模型准确性。
让我们在这个欠采样数据集上重新训练我们最成功的模型——我们的随机森林。
rf_rus_names = ['RF_rus-'+str(int(math.pow(10,r))) for r in rVals]for r in rVals:
    clf = RandomForestClassifier(n_estimators=int(math.pow(10,r)),random_state=0)
    time_start = time.time()
    clf.fit(X_rus_train,y_rus_train)
    time_run = time.time()-time_start
    y_rus_pred=clf.predict(X_rus_test)
    results = results.append(pd.DataFrame([['RF',rf_rus_names[r-1],accuracy_score(y_rus_test,y_rus_pred),time_run]],columns=cols_results),ignore_index=True)
results[results.family=='RF']

The model results of randomly undersampled data, compared with the results from the original random forest models.
因此,我们的模型精度从接* 80%下降到 70%以下。这部分是因为该模型有一个精简数据集来处理。但另一个因素是,由于多数类偏差,我们最初的随机森林模型得到了错误地“夸大”的准确性,这在类不*衡后现在已经消失了。与此同时,*衡类确实会导致一个客观上更准确的模型,尽管不是更有效的模型。最终的决定是由您做出的——您会关心“夸大”的准确性,还是这些“假阳性”会阻止您使用原始模型?
由于我们的“假阳性”可能会导致我们宣布非功能性或需要维修的供水点未得到解决,我们可能希望以其他方式出错,但这取决于您的选择。
预测建模:选择最佳模型
在相同的数据上测试不同类型的模型

无论您是在办公室环境中预测数据,还是只是在 Kaggle 比赛中竞争,测试不同的模型以找到最适合您正在处理的数据都是非常重要的。
最*,我有机会在一个私人的 Kaggle 比赛中与一些非常聪明的同事竞争,预测坦桑尼亚有问题的水泵。在做了一些数据清理后,我运行了以下模型,我将向您展示结果。
- 逻辑回归
 - 随机森林
 - 里脊回归
 - k-最*邻
 - XGBoost
 
加载数据
首先,我们需要看看我们正在处理的数据。在这个特定的数据集中,要素与标注位于不同的文件中。
import pandas as pd
pd.set_option('display.max_columns', None)X_df = pd.read_csv('./train_features.csv')
X_df.head()

y_df = pd.read_csv('./train_labels.csv')
y_df.head()

我们可以看到 status_group 或 target 标签是一个字符串,有些模型不需要修改就可以工作,但有些模型不需要。稍后我们会做些什么。让我们来看看我们的目标标签的分布。
y_df['status_group'].value_counts(normalize=True)

这种分离表明我们在标签中正好有 3 个类,因此我们有一个多类分类。大多数类是“functional ”,所以如果我们只是将 functional 分配给所有的实例,我们的模型在这个训练集上将是. 54。这被称为多数类基线,是我们运行的模型要达到的目标。
数据清理和特征工程
这个数据集中有许多功能,所以我不会详细介绍我所做的每一件事,但我会一步一步地从高层次进行介绍。
首先,我们希望通过查看所有的特性和数据类型来检查事物。
X_df.info()

为了能够在模型中使用它们,我们需要使用 30 个对象特征。int 和 float 对象可以直接使用。
另一个需要关注的是高基数特性。如果我们对这些特性的每一个都有超过 100 个类别,那么使用它们就没什么用了。这会给我们的数据集增加维度,我们不想这么做。
在我们删除这些高基数列之前,我看到 date_recorded 是一个对象,它肯定会随着我们的高基数特性而被删除,所以我在此基础上创建了一些特性。
#So date doesn't get dropped in next stepX_df['date_recorded'] = pd.to_datetime(X_df['date_recorded'])X_df['YearMonth'] = X_df['date_recorded'].map(lambda x: 100*x.year + x.month)X_df['Year'] = X_df['date_recorded'].map(lambda x: x.year)X_df['Month'] = X_df['date_recorded'].map(lambda x: x.month)
既然我们已经对日期进行了分类,我们可以检查高基数并删除那些特性。
max_cardinality = 100high_cardinality = [col for col in X_df.select_dtypes(exclude=np.number)
                   if X_df[col].nunique() > max_cardinality]X_df = X_df.drop(columns=high_cardinality)X_df.info()

所以,我们放弃了 8 个高基数的特性。现在我们可以使用 OneHotEncoder 或 Pandas get_dummies()将这些对象更改为 int。
现在我们所有的特征都是数字的,让我们进入模型吧!
逻辑回归
逻辑回归对于多类分类非常有用,因为如果目标标签是字符串,Scikit-learn 会自动对其进行编码。
首先,我们需要将数据分为训练和测试。
from sklearn.preprocessing import scale
from sklearn.model_selection import train_test_splitX = X.drop(columns='id') #id is our index and won't help our model
X = scale(X) X_train, X_test, y_train, y_test = train_test_split(
        X, y, train_size=0.75, test_size=0.25, random_state=42, shuffle=True)
当你使用一个学习模型时,重要的是缩放特征到一个以零为中心的范围。缩放将确保特征的方差在相同的范围内。
现在,我们将在训练和测试中运行该模型,并查看我们的准确度得分。
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_scorelogreg = LogisticRegression()
logreg.fit(X_train,y_train)
y_pred = logreg.predict(X_train)
print('Train accuracy score:',accuracy_score(y_train,y_pred))
print('Test accuracy score:', accuracy_score(y_test,logreg.predict(X_test)))

在训练和测试中,我们以 0.73 的成绩打破了大多数班级 0.54 的基线。让我们看看另一种模式是否能做得更好。
随机森林
随机森林也可以将字符串作为我们的目标标签,因此我们可以使用相同的训练测试分割来运行模型。
from sklearn.ensemble import RandomForestClassifier as RFCrfc_b = RFC()rfc_b.fit(X_train,y_train)
y_pred = rfc_b.predict(X_train)
print('Train accuracy score:',accuracy_score(y_train,y_pred))
print('Test accuracy score:', accuracy_score(y_test,rfc_b.predict(X_test)))

随机森林在训练和测试中击败了逻辑回归,训练中为 0.97,测试中为 0.79。
里脊回归
对于岭回归,我们需要在运行模型之前对目标标签进行编码。
X = X_df.drop(columns=['id'])
X = scale(X)y = y_df.drop(columns='id')
y = y.replace({'functional':0, 'non functional':2,'functional needs repair':1 })X_train, X_test, y_train, y_test = train_test_split(
        X, y, train_size=0.75, test_size=0.25, random_state=42, shuffle=True)
现在我们运行这个模型。Ridge 在其 predict()方法中输出一个概率,所以我们必须用 numpy 更新它,以便得到实际的预测。
from sklearn.linear_model import Ridge
import numpy as npridge = Ridge()ridge.fit(X_train,y_train)
y_prob = ridge.predict(X_train)
y_pred = np.asarray([np.argmax(line) for line in y_prob])
yp_test = ridge.predict(X_test)
test_preds = np.asarray([np.argmax(line) for line in yp_test])
print(accuracy_score(y_train,y_pred))
print(accuracy_score(y_test,test_preds))

所以,岭回归对于这些数据来说不是一个好的模型。
k-最*邻
对于 K-最*邻,我们将使用与岭相同的训练测试分割。
from sklearn.neighbors import KNeighborsClassifierknn = KNeighborsClassifier()knn.fit(X_train,y_train)
y_pred = knn.predict(X_train)
print('Train accuracy score:',accuracy_score(y_train,y_pred))
print('Test accuracy score:',accuracy_score(y_test,knn.predict(X_test)))

这些分数看起来比 Ridge 好很多,但仍然不是我们最好的分数。
XGBoost
XGBoost 是一种算法,在应用机器学习和针对结构化或表格数据的 Kaggle 竞赛中非常流行。
这是一个梯度增强决策树的实现,旨在提高速度和性能。
如果你想了解更多,请查看这里的文档。当运行这个模型时,我对这些参数进行了一些调整,这些参数是我运行的数据中最好的。
xg_train = xgb.DMatrix(X_train, label=y_train)
xg_test = xgb.DMatrix(X_test, label=y_test)xg_train.save_binary('train.buffer')
xg_test.save_binary('train.buffer')# setup parameters for xgboost
param = {}
# use softmax multi-class classification
param['objective'] = 'multi:softmax'
param['silent'] = 1 # cleans up the output
param['num_class'] = 3 # number of classes in target label watchlist = [(xg_train, 'train'), (xg_test, 'test')]
num_round = 30
bst = xgb.train(param, xg_train, num_round, watchlist)

XGBoost 分类器的输出输出一个错误,该错误被定义为
merror:多类分类错误率。它被计算为#(wrong cases)/#(all cases)
# get prediction
y_pred1 = bst.predict(xg_train)
y_pred2 = bst.predict(xg_test)
print('Train accuracy score:',accuracy_score(y_train,y_pred1))
print('Test accuracy score:',accuracy_score(y_test,bst.predict(xg_test)))

我们在训练中得到 0.79 分,在测试中得到 0.78 分,这也不是我们最好的成绩,但和随机森林差不多。
结论
出于我的目的,我选择使用 XGBoost 并修改了参数。我在上面使用的训练测试分割数据中的分数在训练中是. 97,在测试中是. 81。在给出的测试数据上,我的 Kaggle 分数以. 795 结束。
一旦您找到了最适合您所拥有的数据的模型,您就可以使用模型接受的参数,看看您是否可以获得更好的分数。
我希望这有助于您的预测建模工作!
用 Python 在云中预制人工智能

Photo by Eberhard Großgasteiger on Unsplash
使用 Azure 和 Colab 笔记本创建一个具有视觉、听觉和语音的简单机器人
这里有一队云带着他们自己的思想漂浮在互联网上,试图控制风。他们一直在非常积极地向世界推出各种服务,并从每一个可能的来源吸收数据。在这个巨大的服务泡沫中,越来越多的公司和应用程序依赖预制的人工智能资源来提取见解,预测结果,并从未探索的信息中获得价值。如果您想知道如何试用它们,我想给你一个非正式的概述,告诉你通过向这些服务发送不同类型的数据可以得到什么。简而言之,我们将把图像、文本和音频文件发送到高高的云端,并探索我们得到的回报。
虽然这种使用人工智能的方式不能让你直接、完全控制正在发生的事情(就像你使用机器学习框架一样),但这是一种快速的方法,让你可以尝试几种模型,并在你的应用程序中使用它们。这也是了解已经存在的东西的好方法。

Photo by Franck V. on Unsplash
一般来说,在我们可以使用任何种类的云服务之前,我们必须首先:
- 向特定的云提供商订购。
 - 创建一个资源:注册我们将要使用的特定服务
 - 检索凭证:到授权我们的应用程序访问服务。
 
虽然有许多云提供商可能能够满足您的需求,但我们将关注微软的Azure Cloud。如果你不知道从哪里开始,有大量的选项和教程可能会让你感到困惑,所以在这篇文章的第一部分,我们将从头开始,了解我们需要什么来使用以下服务:
所有资源来自 Azure 的认知服务*台,这是一个很好的服务集合,包含视觉、语音、语言、网络搜索和决策领域的用例。用他们的话说:
Azure Cognitive Services 的目标是帮助开发人员创建可以看、听、说、理解甚至开始推理的应用程序。
我们将使用 Colab 笔记本将它们付诸实施:我们将在 Azure 中设置我们需要的一切,实现调用这些服务的代码并探索结果。为了让它更有趣,我们还将利用摄像头、麦克风和扬声器来说话,看到和听到来自云的响应!
设置
你只需要订阅 Azure 就可以让笔记本焕发生机。之后,你应该可以毫无困难地运行本文中的例子了。
创建订阅
按照此链接创建 Azure 订阅。(如果你目前就读于一所大学,使用此链接)。如果这是你的第一个账户,你应该有一些试用资金,但要确保你在使用任何东西之前总是检查价格。对于本教程,我们将只使用免费服务,但这仍然是一件好事!
在您创建帐户后,您将可以访问 门户 。在这里,您可以管理有关您的订阅的一切,并配置大量的内容。

门户是一个非常有趣的地方,整个公司都使用这个大的工具包进行管理。为了不在森林里迷路,我在笔记本中实现了设置这篇文章所需的所有代码。但是我将在这里花点时间解释一下基本原理,并给你一个自己如何做的想法。
但是如果你已经知道如何创建组和资源,请完全跳过下面的“在 Azure 中设置”部分,直接进入笔记本。
在 Azure 中设置
这些都是在笔记本中自动完成的,但是如果你想知道如何自己做,请通读一遍。
创建资源组
在创建特定资源(如计算机视觉或文本翻译)之前,您需要创建一个 group 来保存多个资源。换句话说,我们创建的每个资源必须属于一个组。这允许您将所有这些作为一个实体来管理,并更容易地跟踪事情。
一般来说,在云中完成工作有两种主要方式:你可以使用云提供商的图形用户界面(GUI )(例如 Azure 的门户网站),或者在命令行界面(CLI)中键入代码行。为了说明这一点,让我们看看如何以两种方式创建资源组:
- 要使用门户创建资源组:
 

Making a resource group
在左侧菜单中,转到“资源组”,单击“添加”并在“资源组”和“区域”字段中填写名称和位置。
注意:在整个教程中,我们将使用MyGroup作为我们的资源组名称,西欧作为我们的地区。位置参数指定您希望数据中心/服务位于哪个区域。如果你不在西欧,除了一点延迟,对你来说应该不会有太大变化。虽然更改到另一个地区可能很简单,但是在使用资源时,参数**会一遍又一遍地出现(通常以不同的名称出现),所以如果您自己设置,请使用MyGroup和WestEurope到来保持简单,并允许您稍后运行代码示例而无需更改。
- 为了实现完全相同的目的,并且在不使用门户中的 GUI 的情况下创建
myGroup,我们也可以使用命令行界面。点击门户网站顶部菜单中的>_: 

在弹出的窗口中输入:
az group create -l westeurope -n MyGroup
和前面一样,这将在位置westeurope中创建一个名为MyGroup的资源组。
点击门户中的>_图标,您看到的是他们为您提供的虚拟机的命令行。它真的很强大,并附带了非常方便的工具:它自己的 go、python 和其他语言的环境,docker、git 等。准备出发。但最重要的是,它附带了一个来自 Azure 的命令行工具[az](https://docs.microsoft.com/en-us/cli/azure/get-started-with-azure-cli?view=azure-cli-latest),它提供了一些选项,可以完成你在门户网站上看到的所有功能,甚至更多。这是我们在** 笔记本 里面用来设置一切的工具。**
az工具太多了,无法在这里一一介绍,但是您可以键入az并开始探索!

创建资源
现在让我们创建单独的资源,并将它们分配给我们创建的组MyGroup。和以前一样,我们可以使用 GUI 或 CLI。出于直觉;这是使用 GUI 的整个过程:
- 在门户中创建资源的步骤:
 

Creating a resource
- 在左侧菜单中,单击“创建资源”,搜索您想要的资源(如计算机视觉),并填写项目详细信息。
 - 在“位置”中,指定您希望数据中心/服务位于哪个地区。(我们将使用“西欧”)。
 - 每个资源的“定价层”定义了其成本。对于每个资源和层级,将有不同的价格和条件。对于本教程,我们总是选择自由层F0以避免任何费用。
 - 最后,我们将我们的资源分配给一个现有的资源组(
MyGroup)。 
在资源被创建之后,我们需要检索它的密钥以便能够使用它。密钥是授权我们的应用程序使用服务的凭证。这是您在门户中检索密钥的方式:**

Finding the authentication key for some resource in the portal
- 在左侧菜单中,转到“所有资源”并单击您的目标资源顶部。在“资源管理”下,转到“密钥”并记下凭据。
 
简单解释一下,但这就是您在门户中手动创建资源和检索密钥的方式。我希望这能给你一个如何做的直觉。但是对于我们需要的所有资源来说,遵循这个过程需要一段时间。所以为了减轻的痛苦,防止读者感到厌烦。我制作了一个代码片段,使用 CLI 中的az工具一次性设置好一切。该代码片段将为以下资源创建和检索密钥,(指定 free tier F0):
进入门户中的命令行(或在您的机器中安装[az](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)):

然后复制、粘贴并运行以下代码片段:
To be pasted in the command line.
- 我们用我们想要的参数的具体名称创建一个数组
resources。 - 我们迭代
resources并应用命令az cognitive services account create来单独创建每个服务。(在这里,我们指定位置WestEurope、空闲层F0和我们创建的资源组MyGroup)。 - 我们再次在
resources上循环,并应用命令[az cognitiveservices account keys](https://docs.microsoft.com/de-de/cli/azure/cognitiveservices/account/keys?view=azure-cli-latest)来检索每个资源的键,并将它们附加到名为keys.py的文件中。 - 当它运行完毕后。
keys.py应包含带有资源及其凭证的标准字典: 
*# sample keys.py with fake credentialssubscriptions = {
  'TextAnalytics': 'ec96608413easdfe4ad681',
  'LUIS': '5d77e2d0eeef4bef8basd9985',
  'Face': '78987cff4316462sdfa8af',
  'SpeechServices': 'f1692bb6desae84d84af40',
  'ComputerVision': 'a28c6ee267884sdff889be3'
  }*
我们需要给我们的笔记本赋予生命。您可以通过键入以下命令来验证和查看我们做了什么:
*az resource list* 
好吧!如果您已经做到了,我将奖励您一组代码片段,您可以调用这些代码片段并向这些资源发送内容。
获取认知服务
既然我们已经完成了枯燥的工作,我们就准备利用这些资源,看看它们能做些什么。创建资源让我们可以使用它们各自的 REST-API。我们可以用刚刚做的东西做很多事情。
简而言之,为了访问这些服务,我们将向特定的 URL 发送带有特定参数和我们内容的请求,在服务器上触发一个动作,然后得到一个响应。为了知道如何组织我们将要使用的每个服务的请求,我们需要参考 API 文档(在这里你可以真正体会到 API 的用处)。**
每个 API 都有一组现成可用的函数。例如,通过计算机视觉 API,我们可以执行 OCR(光学字符识别)并从图像中提取文本,用文字描述图像,检测物体、地标等等。

A glimpse into the Computer Vision API.
在文档中查找我们可以访问的所有 API 可能会让人感到不知所措:**
所以让我们来看一个例子,给你一个直觉,让你知道如何开始一件事。假设您正在查找计算机视觉 API 的“分析图像”方法。
- 转到 API docs ,选择您想要的方法(“分析图像”)并向下滚动:O!
 - 您会看到一个 URL,其中包含发送请求的地址和参数。
 - 请求的报头和正文由什么组成。
 - 来自服务器的示例响应。
 - 错误响应和解释。
 - 以及包括 Python 在内的多种语言的代码样本。您只需要替换资源的键和要发送的数据。一旦你看到它被执行,这将变得清晰。**
 
发送请求
来自不同认知服务的 API 彼此非常相似!如果你仔细阅读代码样本,你会注意到它们都共享同一个主干,,但只是指向不同的 URL。这就是我们请求的基本框架:**
简而言之,我们定义headers、body和params(请求参数),将它们发送到某个 URL 并接收响应。
- 在
headers中,我们指定我们想要发送的数据的类型和访问 API 的资源键。**** - 在
body中,我们包含(或指向)要发送给的数据。主体本身可以有多种形式,取决于 API。**** - 在
params中,我们指定(通常是可选的)参数来更具体地告诉 API 我们想要什么。 - 然后,我们将这些变量作为标准请求发送给特定的端点,例如:
westeurope.api.cognitive.microsoft.com/computervision/v2.0/describe 
在笔记本中,我们利用这些公共元素来实现两个实用函数:get_headers_body和send_request,以帮助我们更快地构造请求并避免重复太多代码。
现在让我们把手弄脏吧! 跳进 Colab 笔记本 。我在这里添加了额外的代码take_picture、show_picture、record_audio、play_audio等等。这些将是我们笔记本中的效应器和致动器,并允许我们与云进行交互。
我们不会涵盖每个 API 的所有可能,而只是简单地看几个方法以及如何调用它们。
对于每个 API,我们将定义几个函数,并查看如何使用它们的实际示例。来自 API 的响应通常包含大量信息!我们将解析这些响应并只返回其中的一小部分(我们不会查看完整的响应)。**
计算机视觉 API
处理图像并返回各种信息。

Photo by Arseny Togulev on Unsplash
让我们定义一组返回图像视觉信息的函数。这些函数将根据我们想要分析的图像组成我们的请求,并将它们发送到计算机视觉 API 的特定 URL(端点)。
在这里,我们将利用函数get_headers_body 和send_request来加快速度(查看这些函数的定义和笔记本上的更多信息)。
[describe](https://westus.dev.cognitive.microsoft.com/docs/services/5adf991815e1060e6355ad44/operations/56f91f2e778daf14a499e1fe):返回图像的视觉描述。
让我们来看看它的实际应用:
*describe([source](https://images.unsplash.com/photo-1508175800969-525c72a047dd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60), number_of_descriptions=3)*

Source: URL of the image given as an argument.
*A yellow toy car 
A close up of a toy car 
A yellow and black toy car*
还不错!
classify:给图像分配一个类别,并对其进行标记。
*classify([source](https://images.unsplash.com/photo-1541673504494-8bcc1a340180?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60))*

*Categories in Image: outdoor_stonerock Tags found in the image:['outdoor', 'nature', 'mountain', 'man', 'water', 'waterfall', 'riding', 'going', 'hill', 'snow', 'covered', 'skiing', 'forest', 'large', 'lake', 'traveling', 'river', 'slope', 'standing', 'white', 'wave']*
[read](https://westus.dev.cognitive.microsoft.com/docs/services/5adf991815e1060e6355ad44/operations/56f91f2e778daf14a499e1fc):执行光学字符识别并提取图像中的文本。绘制文本所在的区域并显示结果。
除了检索响应和打印提取的文本,在read 内部,我们使用额外的 OCR 信息来绘制和标记图像中检测到的文本区域的边界框。让我们来看看它的实际应用:**
*text = read([source](https://www.maa.org/sites/default/files/images/upload_library/46/Swetz_2012_Math_Treasures/ColumbiaU/1502210097.png))
for line in text:
    print(line)*

*ANALYSIS 
Per Quantitatum 
SERIES, FLUXIONES5 
DIFFERENTIAS. 
c UM 
Enumeratione Linearum 
TERTII ORDINIS. 
LONDI,VIS 
Ex Offcina M.DCC.XL*
[see](https://westus.dev.cognitive.microsoft.com/docs/services/5adf991815e1060e6355ad44/operations/5e0cdeda77a84fcd9a6d3d0a):返回图像中识别的对象,并在图像中显示它们的边界框。
*see([source](https://images.unsplash.com/photo-1511317559916-56d5ddb62563?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60))*

*In the image of size 800 by 1181 pixels, 2 objects were detected 
person detected at region {'x': 354, 'y': 535, 'w': 106, 'h': 280} 
Toy detected at region {'x': 214, 'y': 887, 'w': 186, 'h': 207}*
Face API
检测、识别和分析图像中的人脸。
为了简洁起见,我们将只看一个 API 方法:
[detect_face](https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395236):显示图像中识别的人脸的包围盒和一些相关信息(年龄、性别和情感)。
在see和read中,我们使用一个内部函数draw_show_boxes在检测到的人脸周围绘制边界框。这是结果:
*detect_face([source](https://static.artfido.com/2013/09/Danielle.jpg))*

酷吧?
这些都是我们将尝试的关于图像的功能。但是,让我们通过使用功能take_picture用我们的设备拍摄一张照片来进一步试验它们(参见笔记本)。
捕捉并发送图片
我们来拍张照,看看云是怎么看的。在我们所有的函数中,我们可以指定参数localfile=True来允许我们以二进制图像的形式发送本地文件。
*# turns on the camera and shows button to take a picture
img = take_picture('photo.jpg')*
现在让我们通过应用describe和classify函数来看看云对它的“想法”:
*print(describe(img, localfile=True, number_of_descriptions=3))>> A man sitting in a dark room 
>> A man in a dark room 
>> A man standing in a dark roomprint(classify(img, localfile=True))>> Categories in Image:   dark_fire 
>> Tags found in the image    ['person', 'indoor', 'man', 'dark', 'sitting', 'looking', 'lit', 'laptop', 'front', 'room', 'light', 'standing', 'dog', 'watching', 'computer', 'wearing', 'mirror', 'black', 'living', 'night', 'screen', 'table', 'door', 'holding', 'television', 'red', 'cat', 'phone', 'white']*
文本分析
用于为情感分析、关键短语提取和语言检测等任务分析非结构化文本

Photo by Patrick Tomasso on Unsplash
detect_language:返回为每个给定字符串检测到的语言。
*detect_language('Was soll das?', 'No tengo ni idea', "Don't look at me!", 'ごめんなさい', 'Sacré bleu!')>> ['German', 'Spanish', 'English', 'Japanese', 'French']*
key_phrases:返回每个给定字符串的关键字列表(重要的、相关的文本点)。如果没有找到,则返回一个空列表。
*keys = key_phrases('I just spoke with the supreme leader of the galactic federation', 'I was dismissed', 'But I managed to steal the key', 'It was in his coat')for key in keys:
    print(key)>> ['supreme leader', 'galactic federation'] 
>> [] 
>> ['key'] 
>> ['coat']*
check_sentiment:对给定的字符串赋予积极、消极或中性的情感。
*print(check_sentiment('Not bad', "Not good", 'Good to know', 'Not bad to know', "I didn't eat the hot dog", 'Kill all the aliens'))>> ['positive', 'negative', 'positive', 'positive', 'negative', 'negative']*
find_entities:返回一个已识别的实体列表,分配给一个类别。如果可能的话,还有一个指向该实体的维基百科链接。
*find_entities('Lisa attended the lecture of Richard Feynmann at Cornell')>> [['Entity: Lisa, Type: Person', 
     'Entity: Richard Feynman, Type: Person,
       Link:[https://en.wikipedia.org/wiki/Richard_Feynman](https://en.wikipedia.org/wiki/Richard_Feynman)',   
     'Entity: Cornell University, Type: Organization, 
       Link [https://en.wikipedia.org/wiki/Cornell_University](https://en.wikipedia.org/wiki/Cornell_University)']]*
OCR +文本分析
让我们看看如何将一些东西组合在一起。在图像上应用read可以有效地为您生成文本数据。因此,它是应用我们的文本分析的完美匹配。让我们创建一个report函数,它提取单个文本区域,分析它们,并用我们的结果创建一个报告:
*report([source](https://i.pinimg.com/originals/5d/0c/90/5d0c90add4024dae1020e4e7fb545f7e.jpg))*

Source of image analyzed
*# Report ## Region 1 
> "o. 4230..." 
- Language: English 
- Sentiment: positive 
- Entities:  
    - 4230, Type: Quantity,  
- Keys: ## Region 2 
> "WASHINGTON, SATURDAY, APRIL 14, 1866..." 
- Language: English 
- Sentiment: positive 
- Entities:  
    - WASHINGTON, Type: Location,   
    - SATURDAY, APRIL 14, 1866, Type: DateTime,   
    - April 14, Type: Other, Wiki [Link]([https://en.wikipedia.org/wiki/April_14](https://en.wikipedia.org/wiki/April_14)) 
- Keys:  
    - WASHINGTON ## Region 3 
> "PRICE TEN CENTS..." 
- Language: English 
- Sentiment: positive
- Entities:  
    - Tencent, Type: Organization, Wiki [Link]([https://en.wikipedia.org/wiki/Tencent](https://en.wikipedia.org/wiki/Tencent))  
    - TEN CENTS, Type: Quantity,  
- Keys:  
    - PRICE  
    - CENTS...*
语音服务
将音频转换为文本和文本到语音

Photo by David Laws on Unsplash
我们将使用语音服务将声音转换成文本,反之亦然。与record_audio和play_audio(在笔记本中定义)一起,我们有一种方法来听到和与我们的笔记本交谈。但是在使用语音服务之前,我们需要获得一个 10 分钟内有效的令牌(一个秘密字符串)。我们将使用如下所示的函数get_token来实现这一点:
我们将使用它来定义我们函数内部的请求的headers,并授权它们使用我们的语音服务资源。
speech_to_text:接收音频文件的文件路径,并将识别出的给定语言的语音转换成文本。支持大量的语言。
text_to_speech:反其道而行之,将给定的文本转换成语音(一个音频文件),带有*乎人类的声音。这将为我们的笔记本提供声音。**
因为speech_to_text接收音频文件并返回单词,而text_to_speech接收单词并返回音频文件,所以我们可以这样做:
*# transform words to speech
audio = text_to_speech("Hi, I'm your virtual assistant")# transcribe speech back to words
words = speech_to_text(audio)print(words)
>> Hi I am your virtual assistant*
好酷!但这似乎完全没有意义。让我们做一些更有趣的事情。我们将使用record_audio记录我们的声音,使用speech_to_text将其转换为文字,对文字做一些事情,并大声说出结果。
让我们用check_sentiment来检验一下你所说的感觉:
*# speak into the mic
my_voice = record_audio('audio.wav')# transform it into words 
text = speech_to_text(my_voice)# analyze its feeling
sentiment = check_sentiment(text)[0]# convert analysis into speech
diagnosis = text_to_speech(sentiment)# hear the results
play_audio(diagnosis)*
让我们在函数中实现这个想法,使它更有用:
试试吧!
*motivational_bot()*
把你的声音转换成语音意味着你可以把你的声音作为你功能的输入。像这样的东西,你可以尝试很多。例如,你可以把它们翻译成一堆不同的语言(参见文本翻译 API ),在网上查找一些东西(参见 Bing 搜索)或者(超越 Azure)问一些复杂的问题来回答像 Wolfram Alpha 等引擎。**
路易斯—语言理解
基于机器学习的服务,将自然语言理解构建到应用程序、机器人和物联网设备中。

Photo by Gustavo Centurion on Unsplash
让我们让我们的笔记本更加智能,让它能够理解使用 LUIS API 的语言中的某些意图。简而言之,我们将训练一个识别语言中某些意图的语言模型。
例如,假设我们有意图到take_picture。在训练我们的模型后,如果我们的笔记本“听到”类似以下的句子:**
- 拍照
 - 用相机拍个截图
 - 拍张照
 
它会知道我们的意图是take_picture。我们称这些短语为话语。并且是我们需要提供来教语言模型如何识别我们的意图——我们想要执行的任务或动作。****
通过使用不同的和非冗余的语句,以及添加额外的语言组件,如实体、角色和模式,您可以创建灵活和健壮的模型来满足您的需求。良好实现的语言模型(由适当的软件支持)使得回答引擎能够回答诸如“旧金山的天气如何?”,“从华沙到普拉格有多少公里?”,“太阳有多远?”等等。
在这篇文章中,我们将保持事情的简单性,并为少数意图分配 5 种表达方式。正如您可能会想到的,这些意图将与我们已经实现的一些功能相匹配。
激活路易斯
与我们见过的所有服务相比,LUIS 是一个复杂的工具,它有自己的“门户”,在那里您可以管理 LUIS 应用程序,并创建、培训、测试和迭代改进您的模型。但是在我们使用它之前,我们需要激活一个 LUIS 账户。一旦你做到了这一点:
- 进入 LUIS dashboard,检索您帐户的创作密钥,如下所示,并将其粘贴到笔记本中。**
 

*AuthoringKey = '36bd10b73b144a5ba9cb4126ksdfs82ad2'*
这对我来说是一个困惑的话题。但是您的 LUIS 帐户的创作密钥与我们制作的 LUIS 资源的密钥不同。但是你可以将 Azure 资源分配给 LUIS 应用程序(例如,在不同地区开放接入点),但是更多详细信息请参考此处。**
创建 LUIS 应用程序
LUIS 门户网站使创建、删除和改进您的 LUIS 模型变得非常容易。但是在这篇文章中,我们将使用 LUIS 编程 API 来使用authoring_key在笔记本中设置东西。
让我们从创建应用开始:
*app_id, luis_config = create_luis_app('Notebot' )*
在这个实现中,我们跟踪应用 ID(由服务器返回)和我们在app_id和luis_config中指定的参数,作为以后使用的全局变量。
添加意图和话语
现在让我们定义一个函数来添加意图和一个函数来添加它们各自的话语。**
- 
[create_intent](https://westus.dev.cognitive.microsoft.com/docs/services/5890b47c39e2bb17b84a55ff/operations/5890b47c39e2bb052c5b9c0c):向 LUIS 应用程序添加一个意向。哪个应用程序由变量app_id和luis_config指定。 - 
[add_utterances](https://westus.dev.cognitive.microsoft.com/docs/services/5890b47c39e2bb17b84a55ff/operations/5890b47c39e2bb052c5b9c09):向 LUIS 应用程序中的现有意图添加一批示例/话语。 
有了这些函数,让我们在字典中定义我们的语言模型,如下所示,并将其应用于字典。这个阶段有很大的实验空间。
这本字典的关键字将是我们应用程序的意图。让我们遍历它们并创建它们:
*intents = intentions.keys()
for intent in intents:
    create_intent(intent)*
每个意图有 4 个例子/话语,现在让我们把它们添加到各自的意图中。
*for intent, utterances in intentions.items():
    add_utterances(intent=intent, utterances=utterances)*

Photo by Lenin Estrada on Unsplash
训练模型
现在让我们用我们用[train_luis_app](https://westus.dev.cognitive.microsoft.com/docs/services/5890b47c39e2bb17b84a55ff/operations/5890b47c39e2bb052c5b9c45)指定的信息来训练模型。
*train_luis_app(app_id, luis_config)*
发布应用程序
我们现在准备用[publish_app](https://westus.dev.cognitive.microsoft.com/docs/services/5890b47c39e2bb17b84a55ff/operations/5890b47c39e2bb052c5b9c3b)发布应用程序。
*publish_app(app_id)*
做一个预测
让我们通过预测我们的意图来看看我们的模型是否有用。注意 LUIS 有一个单独的 API 来进行预测,即 LUIS endpoint AP。
[understand](https://westus.dev.cognitive.microsoft.com/docs/services/5819c76f40a6350ce09de1ac/operations/5819c77140a63516d81aee78):使用给定文本预测意图
*understand('Can you give me some descriptions about what you are seeing?')# predicted intent is:
>> `describe`understand('Any homo sapiens in the picture?')>> `detect_faces`*
酷!现在我们的笔记本可以从简单的语言中大致理解我们的意图。但是必须自己输入文本似乎没什么帮助。笔记本应该能听到我们说的话,理解我们的意图。让我们写一个使用predict和record_audio以及speech_to_text的函数hear来解决这个问题。
我们现在可以呼叫hear对着麦克风说话,将我们的讲话转换成文字,并使用我们的 LUIS 应用程序预测我们的意图。
*intent = hear()# see the prediction
print(intent)*
使用应用程序
让我们编写一个函数,基于预测或识别的意图触发一组动作,然后映射以执行一些代码。
简而言之:当预测到某种意图时,执行所发生的事情的功能。这里有大房间做实验。**
最后,让我们召唤 Notebot 来实现我们的愿望:
根据你说的话,“note bot”可以拍照并:**
- 大声说出描述
 - 显示任何检测到的对象
 - 显示任何检测到的面孔。
 - 应用 OCR 并大声读出结果。
 
*# summon your creation
Notebot()*
Notebot将根据您所说的运行一系列动作。
让我们总结一下当你调用它时会发生什么。开始时,您会听到一条问候语。之后,Notebot将应用hear并开始记录你说的任何话,你的讲话(感知器)将被转录成单词并发送到 LUIS 应用程序以预测你的意图。基于这一预测,将执行一组不同的动作。如果从您的讲话中没有识别出明确的意图,则意图“无”将被预测,并且Notebot将再次调用自身。**
从上面看,Notebot最终充当了一个简单的基于反射的代理,它只是找到一个条件匹配当前情况的规则并执行它。(在这种情况下,如果你说这个或别的,那么Notebot会做什么)。**
在这一点上,你可能想用额外的概念升级你的代理人,例如增加感知的记忆。但是我将把这个任务留给勤奋的读者。
清理
这篇文章比我预想的要长得多。在我们结束之前,让我们清理一下东西。要清理我们在云中创建的一切:在命令行>_中运行以下命令,删除整个资源组(以及所有资源)和keys.py文件(包含您的凭证):
*az group delete --name MyGroup 
rm keys.py*
好吧,我希望这篇教程至少给了你一些在你的项目中实现的想法。
那都是我送的!谢谢你看完整个:)
准备机器学习面试——简介
机器学习面试的高层次概述。

在过去的几年里,机器学习已经成为主要技术进步的前沿和中心。这也导致了对具有 ML 专业知识的工程师的需求上升。正如整个深度学习领域正在发展一样,面试领域也在发展。几年前,了解如何设计卷积网络就足够了。然而,现在有各种各样的期望,从算法和数据结构到概率和统计等等。挑战不在于课程、教科书或博客不能满足每个主题,而在于有太多的课程、教科书或博客了。
我在这里的尝试是给出对机器学习/深度学习面试的不同方面的见解。希望这能给你一个好的开始来组织你的面试准备。
任何面试准备的关键是确定需要阅读/修改的关键部分,不要被大量可用的信息淹没。因此,在这篇文章之后,我会在每个访谈小节中提供详细的主题/链接。
ML/DL 面试结构。
在我们深入研究面试准备之前,重要的是要认识到,根据公司和受访者的背景,ML 工程师的角色可以有很多种。在下图中,我试图捕捉 ML/DL 访谈的不同方面。

Different layers of a machine learning / deep learning interview.
如上图所示,面试大致有四个部分。下面让我更详细地讨论一下这些部分。
机器学习

Photo by Paul Schafer on Unsplash
这是任何深度学习/机器学习岗位的核心。主要涵盖了标准的机器学习技术和一堆数学东西——主要是概率和统计,线性代数。如果你自己学会了深度学习(这是对你的褒奖),那么你需要在面试中复习这方面的知识。另外,它将有助于使你在深度学习位置上的生活更容易。
存在很多数学和机器学习技术(你看到凯文·墨菲或克里斯托弗·毕晓普的书的页数了吗)。我的建议是坚持阅读以下两本书来快速复习,并保留毕晓普或墨菲的书作为参考:
拉里·乏色曼的《统计学大全》:这是一本关于统计学的非常棒的书。乏色曼教授是统计学的教学大师,他总是抓住要点,言简意赅。每次通读这本书,我都觉得它是为工程师而不是数学家写的。【链接

Photo from: https://images.gr-assets.com/books/1347776274l/411722.jpg
Tom Mitchell 的《机器学习》:涵盖了我认为一个人需要为面试做准备的大多数人工智能主题。它简明扼要,有很好的关于决策树和贝叶斯学习的章节。【链接

Photo from https://booksbeka.com/image/cache/catalog/ANI/tom-500x500.jpg
深度学习

Photo by Ian Stauffer on Unsplash
面试堆栈的深度学习部分主要集中在发现你是否已经弄脏了你的手。这些问题往往围绕深度学习工程师每天面临的工程挑战。面试官试图判断你是否真的实现并训练了一个模型。例如,经常会遇到这样的问题:
退学需要称体重吗?
你用的退学典型值是多少?
如果将输入缩放到 softmax 层,会发生什么情况?
能解释一下反向传播算法吗?
深度学习的大部分面试知识可以从博客、YouTube 讲座和 MOOC 课程中收集。然而,挑战在于信息过载。我的计划是创建一个带有链接的主题列表,可以帮助你复习一些关键的挑战。我会在这个主题的后续文章中这样做。
如果您一直在积极地实现模型,那么我相信您可以跳过这一步,或者在最后优先考虑这一步。
软件

Photo by Chris Ried on Unsplash
几乎所有的深度学习岗位都会要求你精通数据结构和算法。根据你的资历,可能还有系统设计的问题。像其他事情一样,这些需要正确的准备工具和应该覆盖的正确范围。
如果申请的是研究岗位,软件编码可能会放宽。然而,你不应该指望这个折扣。通常,您需要通过一个电话屏幕,这将要求您对给定的问题进行编码。我不认为我能做得比已经在编码面试上写的和辩论的更好。我能提供的最好的是一个书籍和链接的列表,可以帮助你准备后续的文章。在那之前,一定要去 www.leetcode.com或 www.hackerrank.com看看。一般来说,公司倾向于灵活选择 ML 面试的语言。如果这是你选择的武器,你可以坚持使用 Python。也就是说,如果你在嵌入式领域寻找一个 ML 角色,你会想到 C/C++。
领域专业知识

Photo by Luca Bravo on Unsplash
面试过程中的领域专长部分旨在测试你对某个领域的热情和知识。如果你申请金融行业的机器学习职位,将会有与时间序列分析和/或金融方面相关的问题。另一个例子,如果你申请一个计算机视觉的角色,期待卷积网络和图像处理的问题。同样,如果你在面试一家机器人公司或一家自动驾驶汽车公司的规划轨道,你可能会遇到关于运动和路径规划的问题。此外,如果你以深度学习硬件加速器工程师的身份出现,询问你与量化、压缩和硬件架构相关的问题是公*的。
现在,如果你申请的是接*入门级的工作,或者招聘经理认为他可以让你的技能适应这份工作,那么衡量你在某个特定领域的经验水*可能就没有问题了。除了技术问题,可能还有衡量你选择这个重点领域的兴趣、激情和动机的问题。有时面试官也会问你最喜欢的建筑或最*的论文。所以一定要复习一些最*的论文。
结论
出现在 ML/DL 面试中可能会令人生畏,因为这个领域是如此的不稳定。更复杂的是,该领域覆盖了非常广泛的领域——概率和统计、机器学习、软件开发,当然还有深度学习。知道你追求什么样的角色是很重要的。不要羞于问你的招聘人员,在面试准备中你是否应该关注一些具体的事情。记住——如果你不问,答案总是否定的。
准备数据科学面试

随着我们进入熨斗学校训练营的最后几周,我们都变得有点担心面试过程。在我之前的博客文章 “为 2020 年做准备——完美的愿景” 中,我与你分享了我们在课程早期应该采取的步骤。我陈述的 3 个主题是:
- 更新你的 LinkedIn 个人资料
 - 找导师
 - 建立您的投资组合
 
我想继续这些话题,并分享我在研究数据科学采访时发现的一些技巧。如果你在这个行业中找到了一位导师,在进入他们公司的面试之前,接触他/她看看面试过程会是怎样的是一个很好的开始。
符合你职业道路的工作描述
弄清楚你在找什么样的工作描述,你最感兴趣的是什么。你的大部分技术性面试问题都与特定的工作描述有关,所以为特定的角色做好适当的准备是最理想的。
数据科学家的角色很难定义,但 Airbnb 在将工作描述分成 3 个不同的路径方面做得很好。
- 分析:定义和监控指标,创建数据叙述并构建工具
 - 算法:构建并解释支持数据产品的算法
 - 推理:用统计数据建立因果关系
 
大数据工程师和数据工程师一样;负责将机器学习模型投入生产的人。他们与数据科学家一起工作,确保模型可扩展,并能按需提供洞察力和预测。通常情况下,数据工程的职位需要 SQL 和强大的数据库技能,所以在申请之前,请确保你复习一些 SQL。数据工程师的另一个常见技能是 python 熊猫库。
选择职业道路可能很难,因此为自己制定一个 3-5 年的计划可能会让你对自己想去的公司和职位有一个良好的心态。选择哪种类型的数据科学对您有吸引力非常重要。根据你选择的道路或路线,你学习的内容和被问到的问题会有所不同。
不要忘记你以前的经历,并把它们与职位描述联系起来。告诉面试官你以前的技能对你将来有什么帮助。我的想法是离开金融行业,不做任何与这个话题相关的事情。但我错了。从事金融咨询工作让我有能力理解复杂的概念,并能够与客户沟通。
行为访谈
在你选择了你要申请的工作并递交了你的简历和作品集后,你可能会被考虑参加第一轮面试。这被称为行为面试。面试官通常是公司的人力资源代表,他们将决定是否将你的简历传递给数据科学团队或招聘经理。
在这次面试前准备好你的电梯间推介。确保你陈述了你加入训练营的原因和一些过去的经历,这将使你成为这个职位的一个很好的候选人。
我通常会在面试前拿出职位描述要求清单,看看这些如何融入我以前的经历,并与人力资源代表分享。
可能会被问到的一些行为问题:
- 告诉我关于你自己的情况——电梯推销
 - 告诉我你失败的一次经历,以及你从中学到了什么。
 - 长处和短处——确保每一个短处都有克服它的长处
 - 告诉我你在团队项目中克服的一个挑战。
 
在面试的这个阶段之前,记住公司的文化和价值观。我注意到大公司关注团队合作和与他人沟通的问题。对于初创科技公司,我听说过于华丽的辞藻会伤害你。它可以双向进行,所以在 Glassdoor 上做一些研究,实际上是对行为面试的评论。此外,人力资源代表很可能没有技术背景。所以沟通是关键。
统计问题
没有先进的统计学知识,很难成为一名成功的数据科学家。准备好回答一些基本的统计学问题,作为数据科学面试的一部分。
- 收到一个关于概率的面试问题是很常见的。
 - 什么是中心极限定理为什么重要?
 - 什么是采样?你知道多少种抽样方法?
 - I 型和 II 型误差有什么区别?
 - 什么是线性回归?
 
编程部分— Python/SQL
面试官有两种方式测试你的编程技能。第一,他们会要求你在没有代码的情况下从理论上解决编程问题;第二,他们会给你一个白板练习。
一些公司可能会让你接受一个有时间限制的编码挑战。幸运的是,在过去的 15 周里,我们每天都在做这些,所以我们知道会发生什么。编码挑战可以在像 Hackerrank 和 Codewars 这样的网站上进行,所以确保你熟悉这两个网站。
“当你面临编码挑战时,重要的是要记住,公司并不总是在寻找‘正确’的解决方案。他们可能还在寻找代码可读性、良好的设计,甚至是特定的最佳解决方案。”
其他提示
- 关注数据科学和机器学习的最新趋势。听播客是我了解今天发生的事情的最好方式。
 - 参加会议和社交活动,结识更多的人并获得听众。
 - 继续写博客,这是分享你的工作或任何涉及数据科学主题的研究的好方法。从出版物中获得一些吸引力以获得更多的读者。
 - 不要让职位描述的位置让你失去兴趣。如果你对一家公司感兴趣,这家公司有多个办公室,但只是在一个不理想的地点招聘……联系一下这家公司的某人,看看他们是否在多个地点招聘。
 
按公司列出的面试主题示例
Seattle Data Guy 分享了他的一些面试研究指南问题,随后是一些基于公司的焦点问题。
Airbnb — 产品繁重、指标诊断、指标创建、A/B 测试、大量行为问题和带回家的材料。
网飞— 产品感问题、A/B 测试、实验设计、度量设计
微软 —编程繁重,二叉树遍历,SQL,机器学习
Expedia —产品、编程、SQL、产品感知、关于 SVM 的机器学习问题、回归和决策树
结论
显然,面试轮次和问题将取决于你申请的公司和职位。这篇博客分享了一些开始准备面试的技巧和建议。
总的来说,研究公司的文化和价值观,看看你是否适合这家公司。数据科学面试压力很大,做好准备将有助于你赢得面试。对于技术面试来说,需要注意的是,你的问题是否正确并不重要,更重要的是你试图解决问题的过程。我们都在这个训练营,因为我们是编程新手。我们不能指望每个问题都答对,但要为每个面试问题计划好传递信息和思考过程,不要急于回答。
为意外做准备
如何将您的模型应用到从未见过的输入中

我们使用机器学习解决的一些问题涉及代表现实世界对象的分类特征,如单词、项目和类别。那么,当我们在推理时得到从未见过的新对象值时,会发生什么呢?我们如何提前做好准备,以便仍然能够理解输入的内容?
看不见的值,也称为 OOV(不在词汇表中)值,必须正确处理。不同的算法有不同的方法来处理 OOV 值。对分类特征的不同假设也应区别对待。
在这篇文章中,我将重点关注深度学习应用于动态数据的情况,其中新的值一直在出现。我将以 Taboola 的推荐系统为例。模型在推理时获得的一些输入包含看不见的值——这在推荐系统中很常见。例子包括:
- 项目 id:每个可推荐的项目都有一个唯一的标识符。每天都有数以千计的新项目进入系统。
 - 广告商 id:赞助内容是由广告商创建的。与新项目的数量相比,新的每日广告客户的数量要少得多。尽管如此,正确处理它们是很重要的,尤其是因为我们想要支持新的广告客户。
 
那么,OOV 价值观的挑战是什么?
学习处理 OOV 价值观
OOV 值与模型在训练时看不到的值相关联。因此,如果我们在推理时得到一个 OOV 值,模型不知道如何处理它。
一个简单的解决方案是在训练之前用一个特殊的 OOV 令牌替换所有罕见的值。因为从模型的角度来看,所有 OOV 值都是相同的,所以我们将在推理时用 OOV 令牌替换它们。该解决方案有两个积极的结果:
- 模特在训练时会接触到 OOV 令牌。在深度学习中,我们通常嵌入分类特征。训练后,模型将学习所有 OOV 值的有意义的嵌入。
 - 将减轻过度适应稀有值的风险。这些值出现在少数示例中。如果我们学习这些值的嵌入,模型可能会学习使用它们来解释这些特定示例中的特殊性或随机噪声。学习这些嵌入可能导致的另一个灾难是没有足够的梯度更新传播给它们。因此,相对于通过训练学习的信号,随机初始化将支配结果嵌入。
 
问题解决了…还是?
处理 OOV 价值观很难!
该模型使用项目 id 功能来记忆每个项目的不同信息,类似于纯粹的协同过滤方法。注入了 OOV 令牌的稀有物品无法从中受益,因此模型对它们的性能更差。
有趣的是,即使我们在训练时完全不使用物品 id,模型在稀有物品上的表现仍然更差!这是因为他们来自不同于一般人群的分布。它们具有特定的特征——可能它们在网上的表现很差,这导致 Taboola 的推荐系统较少推荐它们,反过来——它们在数据集中变得罕见。那么为什么这种分布差异很重要呢?
如果我们用这个特殊分布来学习 OOV 嵌入,它不会推广到一般人群。请这样想——每个项目在某个时候都是一个新项目。在那时,它被注入了 OOV 令牌。所以 OOV 嵌入应该对所有可能的项目都执行得很好。
随机性是数据科学家最好的朋友
为了使用一般群体来学习 OOV 嵌入,我们可以在开始训练过程之前将 OOV 令牌注入到来自数据集中的随机样本集中。但是有多少例子就够了呢?
我们采样越多,OOV 嵌入就越好。但同时,该模型将暴露于更少数量的非 OOV 值,因此性能将下降。
我们如何使用大量的例子来训练 OOV 嵌入,同时使用相同的例子来训练非 OOV 嵌入?我们没有在开始训练之前随机注入 OOV 令牌,而是选择了以下方法:在每个时期,模型使用所有可用的值进行训练(不注入 OOV 令牌)。在纪元结束时,我们随机抽取一组样本,注入 OOV 令牌,并再次训练模型。这样,我们享受两个世界!
和前面的方法一样,我们也将 OOV 令牌注入稀有值,以避免过度拟合。
为了评估新的方法,我们将 OOV 令牌注入到所有的示例中,并评估了我们的离线度量(MSE)。与在模型开始训练之前随机注入 OOV 令牌相比,它提高了 15%。
最后的想法
在我们想到新方法之前,我们的模型已经在生产中使用了很长时间。很容易忽略这种潜在的性能提升,因为该模型整体性能良好。它只是强调了一个事实,你总是要寻找意想不到的!
使用 Pix2Pix 为图像翻译准备 TIFF 图像
使用 tiff 图像的 pix2pix 入门指南
*年来,生成对抗网络(GANs)因其在图像生成、图像翻译、风格转换、图像着色等方面取得的令人印象深刻的成就而受到广泛关注。特别地,由 Isola 等人开发的 pix2pix 作为条件生成对抗网络(CGAN)已经变得非常流行,其允许用户基于输入图像生成图像。一些例子包括从语义标记的图像翻译成街道场景,从白天的照片翻译成夜晚的照片,从草图翻译成照片等等。

Image taken from https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix
所有这些都非常令人印象深刻,但目前,pix2pix 主要是迎合巴布亚新几内亚和 JPG 的图像。这是不幸的,因为一些任务,例如医学成像,使用无损的 TIFF 图像,而标准 JPEG 文件是无损的,因此捕捉更准确的细节。TIFF 图像具有浮点值,而 PNG 和 JPG 图像具有整数值,因此在实现 pix2pix 时保持这种精度非常重要。
此外,CGANs 需要将图像缩放到[-1,1]的范围,以便进行更稳定的训练。但是,标准化并不是简单地使用现成的函数就能实现的,因为 TIFF 图像与像素值为 0-255 的标准 PNG 和 JPG 图像不同,它们的值可能会有所不同。在我的例子中,我的 TIFF 图像的值范围是从 0 到 1200!
记住这几点,我将详细说明如何成功地将 pix2pix 应用于 TIFF 图像。
了解您的数据
首先,找到你的图像有多少通道。RGB 图像有 3 个通道,而灰度图像只有 1 个通道。对于 TIFF 图像,它们可以出现在不同数量的通道中,因此在使用 pix2pix 之前理解您的图像数据非常重要,因为您在对架构进行编码时做出的后续决定将取决于此。使用以下代码片段来查找您的图像拥有的通道数:
Find the number of channels in your image
准备数据集
现在您对数据集有了更好的理解,您必须准备数据集。Pix2pix 是独一无二的,因为它需要两个域中完全相同的成对图像。因此,在官方的 PyTorch 实现中,图像必须并排组合在一起,以产生宽度* 2 x 高度的合成图像。记住需要保持 TIFF 文件值的精度,我使用 PIL 库打开图像,然后使用 numpy 将两个图像连接在一起。
首先,按以下格式准备数据集:folderA 应包含包含域 A 中所有图像的子文件夹 train、validation(如果有)和 test(如果有),而 folderB 应包含包含域 b 中所有图像的子文件夹 train、validation(如果有)和 test(如果有),注意确保 folderA 和 folderB 中的图像具有相同的尺寸和名称。然后,使用下面的代码来生成连接的图像。目标路径(dest_path)是您希望保存串联图像的目录。结果名称将与 folderA 和 folderB 中的原始名称相同。
Concatenate 2 images from domain A and domain B to form a single image
规范化您的数据
Pix2pix 对生成器模型的输出层使用 tanh 激活函数,生成像素值在[-1,1]范围内的图像。因此,重要的是鉴别器也接收与发生器模型产生的范围相同的真实图像。但是,开箱即用的解决方案不起作用,因为它们假设像素值在 0-255 的范围内,就像普通的 PNG 和 JPG 图像一样。这不适用于 TIFF 图像,因为每个图像的像素值范围都不相同,所以在分割之前先找到图像的最小值和最大值非常重要。下面的代码片段允许您根据原始像素值缩放图像:
Scale any image to the pixel values of [-1, 1]
包扎
原来如此!你已经准备好了你的 tiff 数据集,并准备好实现 pix2pix 代码,无论是官方的 Torch 实现、 PyTorch 、 Tensorflow 等等。如果你面临任何问题,请在评论中告诉我,我会尽力帮助你。
这篇文章也发表在我的博客里。
预处理:用函数计算经纬度点之间的距离

作为关注一些独特的预处理技术的系列文章的一部分,本系列的第一篇文章将关注处理纬度/经度信息。这种类型的数据对于绘制可视化地图和其他地理定位目的非常重要。

纬度是指定地球表面南北点的地理位置。经度提供了东西点。写出来的时候,先写纬度,后写逗号,再写经度。赤道代表纬度的零点,本初子午线代表经度的零点。
有时,当您有几个点的地理位置时,计算距离可能有助于要素工程数据。我将使用 2018 年奥斯汀犯罪数据集,该数据集可在https://data . Austin Texas . gov/Public-Safety/Crime-Reports-2018/vmn 9-3bvu找到。关于地理位置数据,该数据集包含纬度、经度的独立特征和名为 location 的组合纬度/经度特征。

这些地理位置确定了犯罪发生的地点。大多数代表地址,有些是小巷,停车场等。所以使用地理定位很重要,可以参考。
奥斯汀有四个警察局。总指挥部和三个分站(北、东、西)。奥斯汀警察局还提供了一个以这些车站的位置为特征的数据集。在该数据集中,站的名称,以及单独的经度和纬度点(分别标记为 X 和 Y)。

该计划旨在描绘出每个犯罪现场到每个警察局的距离。幸运的是,地理位置数据是分离的,因为它节省了分离数据的几个步骤。如果您遇到这种情况,且您有一个类似于上面位置特性的组合地理位置(例如:(30.1876534,-97.475630)),您可以很容易地分离这些数据,首先使用 python strip()方法删除括号,然后使用 split()方法分离值,因为如果列中有任何字符,它们将被视为对象。
df[‘Location] = df.Location.strip(‘()’) #will remove the parentheses (can use regex if necessary to remove additional text,etc)df[[‘Longitude’,’Latitude’]] = df.str.strip(‘,’, expand = True)
本文将不讨论计算这种转换的公式的细节,但是在运行函数时,下面的函数将以纬度和经度为起点,将距离(以英里为单位)转换为 DataFrame 列。
‘’’Distance equation for long,lat data used via stackoverflow from user Michael0x2a. Updated to a function that converts to mileage’’’# constant values, if need to change end lat, long points, change the lat2, lon2 informationlat2 = np.array(clean.Latitude) #identifies iterable latitude column
lon2 = np.array(clean.Longitude) #identifies iterable longitude columnlatr = np.array(list(map(lambda x: np.radians(x), lat2)))
lonr = np.array(list(map(lambda x: np.radians(x), lon2)))def distance(lat1,lon1):
    lat1 = np.radians(lat1)
    lon1 = np.radians(lon1)
    dlon = np.array(list(map(lambda x: (x — lon1), lonr)))
    dlat = np.array(list(map(lambda x: (x — lat1), latr)))
    a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2
    c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 — a))
    # 6373.0 represents earth radius in kilometers
    kilo = 6373.0 * c
    miles = kilo * 0.62137119
    return miles
要运行该函数,请确保将新功能设置为变量:
clean[‘Main Distance’] = distance(30.267574,-97.735070)
如果你需要以公里为单位的距离,只需删除英里转换线,并确保返回千。
预处理:标准化方法的差异

如果您一直在关注预处理系列,我们已经介绍了通过插补处理缺失的连续和分类数据。除此之外,我们还包括编码分类值。
接下来是拟合模型之前的下一个最重要的预处理方法:标准化。让我们来看看这在数据中代表了什么,以及为什么它如此重要。
数据集的‘标准化 是 scikit-learn 中实现的许多机器学习估值器 的一个 共同要求;如果单个特征或多或少看起来不像标准的正态分布数据:具有 零均值和单位方差 的高斯数据,则它们可能表现不佳。
在实践中,我们经常忽略分布的形状,只是通过移除每个特征的*均值来转换数据以使其居中,然后通过将非恒定特征除以其标准偏差来缩放数据。
例如,学习算法的目标函数中使用的许多元素(如支持向量机的 RBF 核或线性模型的 l1 和 l2 正则化子)假设所有特征都以零为中心,并且具有相同顺序的方差。如果某个特征的方差比其他特征的方差大几个数量级,那么它可能会主导目标函数,使估计器无法像预期的那样正确地从其他特征中学习。【https://scikit-learn.org/stable/modules/preprocessing.html】()
本质上,这意味着将数据集中到相同的*均值,并将数据缩放到相同的范围。再次学会拯救。在这里,我们将涵盖一个特定的例子,与'泰坦尼克号'数据集,我们以前已经编码和估算。这篇文章的链接在下面。
在将我们的数据放入模型之前,需要对分类数据执行的两个步骤是编码和处理…
towardsdatascience.com](/preprocessing-encode-and-knn-impute-all-categorical-features-fast-b05f50b4dfaa)
为了展示使用标准标量和 PowerTransformer 之间的比较,我们将使用不同的 scikit-learn 包对每个标准化数据集运行一个线性回归模型。我们将把票价作为我们的目标。
所以首先,我们需要设置我们的目标和特性变量。
target = encode_data.fare
features = encode_data.drop(‘fare’, axis=1)
接下来,我们将导入我们要比较的包…所有这些包都在同一个 scikit-learn 预处理类中。
from sklearn.preprocessing import StandardScaler, RobustScaler, QuantileTransformer, PowerTransformer
接下来,我们将实例化每个转换包。
ss = StandardScaler()
rs = RobustScaler()
qt = QuantileTransformer(output_distribution='normal',n_quantiles=891)
yj = PowerTransformer(method = 'yeo-johnson')
bc = PowerTransformer(method = 'box-cox')
如果你注意到,有两种 PowerTransformer 方法,“yeo-johnson”和“box-cox”。Yeo-Johnson 可用于阳性和阴性数据,而 box-cox 只能用于阳性数据。如果存在任何否定数据,将会引发错误。现在,我们将用几行代码通过每种标准化技术运行我们的数据。
ss_data = ss.fit_transform(features)
rs_data = rs.fit_transform(features)
qt_data = qt.fit_transform(features)
yj_data = yj.fit_transform(features)
#bc_data = pd.DataFrame(bc.fit_transform(encode_data), columns = encode_data.columns)
box-cox 技术被注释掉,因为在集合中识别出了负面数据。现在,我们可以通过 scikit-learn 的现成线性回归模型对每个结果进行评分。
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
以下是不同软件包的结果:

Original Data without standardization
我们未经标准化的原始数据得出的 r *方值约为. 427。

Data with StandardScaler

Data with RobustScaler
如果你注意到,standardscaler 和 robustscaler 产生的 r *方分数与我们的原始数据相同。这是因为大部分数据是分类的,使用这些标量实际上对数据的分布没有影响。鲁棒定标器被设计成对异常值更加友好。这个数据集没有异常值,所以结果是一样的。

Data with QuantileTransformer
quantiletransformer 实际上比原始数据得分更低(~0 . 384)。虽然 quantiletransformer 在规范化双模态和统一数据方面表现很好,但对于这个特定的数据集却不是这样。

Data with PowerTransformer (Yeo-Johnson)
采用 Yeo-Johnson 方法的 powertransformer 软件包将分数提高到了~.449。这比原始数据提高了 2%,仅仅是因为使用了不同的标准化包!
这个故事的寓意是,确保在清理后的数据上测试不同的规范化技术。它真的不会占用太多时间,并且当处理时间证明它是正确的时候,每一点准确性都很重要。这个过程是从上一篇文章添加到 Github 的。可从以下网址获得:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Jason-M-Richards/Imputation-Techniques)
一如既往的感谢。下周再聊!
预处理:编码和 KNN 快速估算所有分类特征

在将我们的数据放入模型之前,需要对分类数据执行的两个步骤是编码和处理缺失的空值。编码是将文本或布尔值转换为数字值进行处理的过程。至于丢失的数据,有三种方法可以用来处理数据集中的空值。第一种是将它们留在数据是分类的情况下,可以被视为“缺失”或“非”类别。第二种是通过行或列删除数据。删除数据是一个危险的过程,您不希望从数据集中删除太多的数据。如果缺少值的特性与另一个特性不相关或高度相关,则可以删除该列。另一方面,行是基于具体情况的。第三种,我们将在这里讨论,是估算,或者用占位符值替换。
从 Python 3.6 开始,FancyImpute 就已推出,它是将替代插补方法应用于数据集的绝佳方式。fancyimpute 可以执行多种方法(文档在此:https://pypi.org/project/fancyimpute/,但是我们将专门针对分类特征讨论 KNN 估算器。
在我们开始之前,先简要概述一下我们将在这种特殊的预处理技术中使用的数据…非常有用的泰坦尼克号数据集,因为它可以通过 seaborn 数据集轻松获得。 我们将构建一个处理数据集中所有分类变量的流程。 这个过程将被一步一步地概述,所以除了少数例外,应该与数据集中标识的任何列列表一起工作。
首先,我们将加载我们的库。因为我们要遍历列,所以我们要对数据进行普通编码,而不是一次性编码。如果你注意到,KNN 软件包确实需要一个 tensorflow 后端,并使用 tensorflow KNN 流程。KNN 方法是一种多指数方法,这意味着数据需要全部处理,然后进行估算。

接下来,我们将加载并查看我们的数据。这一区有几个项目需要解决。首先,我们将最大列数设置为 none,这样我们就可以查看数据集中的每一列。其次,这个数据是直接从 seaborn 加载的,所以使用了 sns.load_dataset()。

接下来,看看我们在丢失值和数据类型方面正在处理什么是很好的。很快。info()将完成这个任务。

如您所见,有两个特性被列为类别 dtype。这会导致插补出现问题,因此我们需要将这些数据复制到新的要素中作为对象,并丢弃原始数据。如果你没有任何数据被识别为类别,你应该没事。

根据我们掌握的信息,我们的情况如下:
- 带有需要编码的文本的分类数据:性别、上船、阶级、谁、成人 _ 男性、上船 _ 城镇、活着、独自、甲板 1 和阶级 1。
 - 具有空值的分类数据:年龄、登船、登船 _ 城镇、甲板 1
 
我们将确定将要编码的列,但不会涉及太多细节(因为有注释),提取非空数据、对其进行编码并将其返回到数据集的过程如下。
*#instantiate both packages to use*
encoder = OrdinalEncoder()
imputer = KNN()
*# create a list of categorical columns to iterate over*
cat_cols = ['embarked','class1','deck1','who','embark_town','sex','adult_male','alive','alone']
**def** encode(data):
    *'''function to encode non-null data and replace it in the original data'''*
    *#retains only non-null values*
    nonulls = np.array(data.dropna())
    *#reshapes the data for encoding*
    impute_reshape = nonulls.reshape(-1,1)
    *#encode date*
    impute_ordinal = encoder.fit_transform(impute_reshape)
    *#Assign back encoded values to non-null values*
    data.loc[data.notnull()] = np.squeeze(impute_ordinal)
    **return** data
*#create a for loop to iterate through each column in the data*
**for** columns **in** cat_cols:
    encode(impute_data[columns])
你可能已经注意到了,我们没有对“年龄”进行编码?我们不想给年龄重新赋值。处理相关当前数据为空的分类数据的最佳方法是将这些数据与该方法分开处理。让我们来看看我们的编码数据:

如您所见,我们的数据仍然是有序的,所有的文本值都已被编码。既然我们有了估算器可以计算的值,我们就可以估算空值了。我们可以输入数据,将数据转换回数据帧,并在一行代码中添加回列名。如果您喜欢使用剩余的数据作为数组,只需省去 pd。DataFrame()调用。
*# impute data and convert* 
encode_data = pd.DataFrame(np.round(imputer.fit_transform(impute_data)),columns = impute_data.columns)
有了 tensorflow 后端,这个过程很快,每迭代 100 行就会打印出结果。我们需要对值进行舍入,因为 KNN 将产生 floats。这意味着我们的 fare 列也将被四舍五入,所以请确保将您不希望四舍五入的任何功能排除在数据之外。

该过程确实估算所有数据(包括连续数据),因此要预先处理任何连续的空值。幸运的是,我们所有的估算数据都是分类的。嗯,也许下次再发吧。查看 GitHub 上的笔记本:https://GitHub . com/Jason-M-Richards/Encode-and-Impute-categorial-Variables。
每周都会发布一个新的预处理技术(直到我再也想不出来了),所以请关注并留意!
预处理:缺失连续值的回归插补

作为编码和输入分类值的后续,本文将介绍使用回归技术来输入连续变量的缺失值。
在决定如何处理数据中的缺失值时,有三种选择:移除带有缺失数据的观测值、将缺失值保留在原位或估算(使用占位符)值。如果决定使用占位符值,实际选择是*均值、中间值或众数。如果缺失值很少和/或数据的变化不显著,这就足够了。
如果有一个特性非常重要,需要保留,但却缺少大量的变量值,该怎么办?Sci-kit Learn 和他们的迭代输入包。
我们将使用一个随机生成的数据集,其中包含有目的地放置的空值。首先,让我们来谈谈我们将要加载的包,并深入了解一下 IterativeImputer。
import pandas as pd
import numpy as np
# explicitly require this experimental feature
from sklearn.experimental import enable_iterative_imputer
# now you can import normally from sklearn.impute
from sklearn.impute import IterativeImputer
from sklearn.ensemble import ExtraTreesRegressor
from sklearn.linear_model import BayesianRidge
import random
如您所见,迭代输入在 sci-kit learn 库中仍处于实验阶段。在某些情况下,使用这种插补技术会牺牲模型的准确性,因此一定要比较没有使用插补技术的数据集的验证结果。如果你也注意到了,我们已经加载了几个回归模型。IterativeImputer 包允许灵活地选择预加载的 sci-kit 学习模型来迭代数据以估算缺失值。这里重点介绍了三种型号,文档中提供了型号列表和更详细的说明:
[## sk learn . input . iterativeinputr-sci kit-learn 0 . 21 . 3 文档
sk learn . impute . iterative imputr(estimator = None,missing_values=nan,sample_posterior=False,max_iter=10…
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.impute.IterativeImputer.html#sklearn.impute.IterativeImputer)
还要注意,我们使用的方法都是回归模型。这是基于数据的偏好。检查数据并寻找最适合估算值的模型的线索是一种很好的做法。
现在,我们可以生成一个随机数据集,添加 10%的缺失数据,然后将它们混在一起。
data = np.random.random([1000,20])
null_data = np.empty([1000,2])
null_data[:] = np.nan
full_data = np.concatenate((data,null_data), axis=1)
full_data = np.random.permutation(full_data.flat)
full_data = full_data.reshape([1000,22])
这就是 IterativeImputer 的美妙之处,两行代码处理了所有的空值。BayesianRidge 是用于估算的默认方法,但是我们将调用它来展示一个例子,说明将所选模型实例化到代码中是多么简单。
imputer = IterativeImputer(BayesianRidge())
impute_data = pd.DataFrame(imputer.fit_transform(full_data))
我对你的挑战是创建一个目标值集,并比较可用的回归和分类模型的结果以及带有缺失值的原始数据。该笔记本包含在上周预处理文章的分类插补笔记本中(https://github . com/Jason-M-Richards/Encode-and-Impute-categorial-Variables)。感谢所有的支持,我真心希望你的感恩节过得愉快!下周见。
NLP 第 2 部分|使用 Python 预处理文本数据
让我们为分析准备/清理数据,不要忘记这是一个迭代过程。
卡米尔·米西亚克

Photo by Dmitry Ratushny on Unsplash
我以前的 文章 探讨了使用名为 BeautifulSoup 的 python 库从网站上抓取文本信息的概念。我们很快就能从 Indeed.com 获取员工公司评级,并将数据导出到本地 CSV 文件中。抓取数据仅仅是从我们新获得的文本数据中收集有用见解的第一步。本文的目的是采取下一个步骤,应用一些标准的预处理步骤,以便为分析准备数据。
您选择执行哪种预处理方法将取决于您的数据、预期结果和/或您选择的数据分析方式。也就是说,下面列出的预处理方法是一些最常用的方法。
- 将库与我们的数据一起导入
 - 扩张收缩
 - 语言检测
 - 标记化
 - 将所有字符转换为小写
 - 删除标点符号
 - 删除停用词
 - 词性标注
 - 词汇化
 
导入必要的库
import pandas as pd
import numpy as np
import nltk
import string
import fasttext
import contractions
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords, wordnet
from nltk.stem import WordNetLemmatizerplt.xticks(rotation=70)
pd.options.mode.chained_assignment = None
pd.set_option('display.max_colwidth', 100)
%matplotlib inline
导入我们的数据
我们将导入在之前的 教程 中获得的粗略员工评估评级,并快速检查数据。
with open('indeed_scrape.csv') as f:
    df = pd.read_csv(f)
f.close()

我们将重点关注“评级”和“评级 _ 描述”列,因为它们包含最有价值的定性信息。尽管我们不会对“rating”列应用任何预处理步骤。
首先,让我们删除“Unnamed: 0”列,因为它只是复制了索引。
df.drop('Unnamed: 0', axis=1, inplace=True)
接下来,让我们检查是否有任何缺失的值。“评级”和“评级 _ 描述”似乎都不包含任何缺失值。
for col in df.columns:
    print(col, df[col].isnull().sum())

rws = df.loc[:, ['rating', 'rating_description']]

文本预处理
扩张收缩
缩写是我们采取的文学上的小捷径,我们更喜欢“应该”而不是“应该”,或者“不”很快变成了“不”。我们将向我们的数据框架添加一个名为“no_contract”的新列,并对“rating_description”字段应用一个 lambda 函数,这将扩展任何收缩。请注意,扩展的收缩将被有效地标记在一起。换句话说,“我有”=“我有”而不是“我”,“有”。
rws['no_contract'] = rws['rating_description'].apply(lambda x: [contractions.fix(word) for word in x.split()])
rws.head()

我们最终希望将扩展的缩写分别标记为“I”、“have”,因此,让我们将“no_contract”列下的列表转换回字符串。
rws['rating_description_str'] = [' '.join(map(str, l)) for l in rws['no_contract']]
rws.head()

英语语言检测
下一步是确定每篇评论使用的语言,然后删除任何非英语的评论。我们首先必须为我们的快速文本库下载预先训练好的语言模型(每个人都需要感谢 facebook 的这个)。TextBlob 是一个用于检测字符串语言的常用库,但是当您解析大量文本时,它会很快抛出一个错误。一旦我们下载了模型,我们将使用 for 循环来遍历我们的评论。结果是预测语言和预测概率的元组。在我们的例子中,我们只需要第一个(即。语言预测)部分。最后,我们只选择最后两个字符。
pretrained_model = "lid.176.bin" 
model = fasttext.load_model(pretrained_model)langs = []
for sent in rws['rating_description_str']:
    lang = model.predict(sent)[0]
    langs.append(str(lang)[11:13])rws['langs'] = langs

现在我们要做的就是删除所有非英语评论。

标记化
现在,我们已经删除了所有非英语评论,让我们应用我们的分词器,将每个单词拆分成一个单词。我们将对“rating_description_str”列应用 NLTK.word_tokenize()函数,并创建一个名为“tokenized”的新列。
rws['tokenized'] = rws['rating_description_str'].apply(word_tokenize)
rws.head()

将所有字符转换为小写
将所有单词转换成小写也是非常常见的预处理步骤。在这种情况下,我们将再次向 dataframe 追加一个名为“lower”的新列,这将把所有标记化的单词转换为小写。然而,因为我们必须迭代多个单词,所以我们将在 lambda 函数中使用一个简单的 for 循环来对每个单词应用“lower”函数。
rws['lower'] = rws['tokenized'].apply(lambda x: [word.lower() for word in x])
rws.head()

删除标点符号
标点符号经常从我们的语料库中删除,因为一旦我们开始分析我们的数据,它们就没有什么价值了。继续前面的模式,我们将创建一个删除了标点符号的新列。我们将再次在 lambda 函数中使用 for 循环来迭代令牌,但这次使用 IF 条件来仅输出 alpha 字符。可能看起来有点困难,但“下方”列中的符号化“句点”已被删除。
punc = string.punctuation
rws['no_punc'] = rws['lower'].apply(lambda x: [word for word in x if word not in punc])
rws.head()

删除停用词
停用词通常是无用的词,对句子没有多大意义。英语中常见的停用词包括“你、他、她、在、一个、有、是”等。。首先,我们需要导入 NLTK 停用词库,并将停用词设置为“english”。我们将添加一个新列“no_stopwords ”,该列将从“no_punc”列中删除停用词,因为它已被标记化,已被转换为小写,并且标点符号已被删除。lambda 函数中的 for 循环将再次遍历“no_punc”中的标记,并且只返回“stop_words”变量中不存在的标记。
stop_words = set(stopwords.words('english'))
rws['stopwords_removed'] = rws['no_punc'].apply(lambda x: [word for word in x if word not in stop_words])
rws.head()

词干化与词汇化
词干化的想法是将不同形式的单词用法减少到它的词根。例如,“驱动”、“被驱动”、“驾驶”、“被驱动”、“驱动者”是“驱动”一词的派生词,研究人员经常想从他们的语料库中去除这种可变性。与词干化相比,词干化当然是不太复杂的方法,但它通常不会产生特定于词典的词根。换句话说,对单词“pies”进行词干化通常会产生“pi”的词根,而词汇化会找到“pie”的词根。
让我们对我们的数据应用词汇化,而不是简单地使用词干化,但是与词干化相比,这需要一些额外的步骤。
首先,我们要应用词性标签,换句话说,确定词性(即。名词、动词、副词等。)每个单词。
rws['pos_tags'] = rws['stopwords_removed'].apply(nltk.tag.pos_tag)
rws.head()

我们将使用 NLTK 的 word lemmatizer,它需要将词性标签转换成 wordnet 的格式。我们将编写一个进行适当转换的函数,然后在 list comprehension 中使用该函数来应用转换。最后,我们应用 NLTK 的单词 lemmatizer。
def get_wordnet_pos(tag):
    if tag.startswith('J'):
        return wordnet.ADJ
    elif tag.startswith('V'):
        return wordnet.VERB
    elif tag.startswith('N'):
        return wordnet.NOUN
    elif tag.startswith('R'):
        return wordnet.ADV
    else:
        return wordnet.NOUNrws['wordnet_pos'] = rws['pos_tags'].apply(lambda x: [(word, get_wordnet_pos(pos_tag)) for (word, pos_tag) in x])
rws.head()

现在,我们可以在可靠的列表理解中应用 NLTK 的单词 lemmatizer。注意,lemmatizer 函数需要两个参数单词及其标签(以 wordnet 的形式)。
wnl = WordNetLemmatizer()
rws['lemmatized'] = rws['wordnet_pos'].apply(lambda x: [wnl.lemmatize(word, tag) for word, tag in x])
rws.head()

最后,我们将把这项工作保存到一个 csv 文件中,用于进一步的探索性数据分析,您可以在我的下一篇 博客 中读到所有相关内容。
rws.to_csv('indeed_scrape_clean.csv')
文本预处理可能很快成为编辑和进一步技术的兔子洞,但我们必须在某处划清界限。随着分析过程的深入,我经常会回到数据预处理阶段,因为我发现了一些需要解决的数据问题。也就是说,要学会在某处划清界限。
*稳时间序列中的记忆保持

Songkran festivities along the Ping river in Chiang Mai, Thailand. Extracting seasonality, the water level of a river is a stationary time series
许多预测模型要求时间序列具有一定的一致性,称为*稳性。通常的转换,即整数阶差分(在金融中,例如对回报率而不是绝对价格建模),消除了数据中的记忆,因此影响了建模的预测能力。这篇文章概述了分数微积分如何允许保留更多的信息,并更好地*衡*稳性和有意义的记忆。
一般来说,我们将一个给定的时间序列理解为一个随机过程产生的样本,我们试图为预测模型推断其分布和统计数据。
建立随机过程的预测模型是为了在样本的特异性和普遍性之间找到*衡:模型在一般模式的背景下解释给定的序列。
比一般的预测回归更具体的是,时间序列由于其时间结构而具有内在的顺序——任何给定的实例都反映了过去遍历的值的历史,即其过去跟踪记录的特定记忆。
*稳性
为了识别生成过程的一般模式并绘制给定的星座图,在实际建模之前,作为预处理步骤的一部分,这种系列特定的记忆通常被消除。
在监督学习的机器学习术语中,这用于发现通用结构,并将给定实例与带标签的训练集中的更多样本进行匹配。
在数学术语中,过程的统计属性以及序列的集合(如*均值、方差和协方差)应相对于时间顺序保持不变,这意味着序列不应显示出随时间变化的趋势。这个概念被称为*稳性(参见例如【1】以获得全面的解释)。
有多种方法可以检查序列的*稳性:
- 目视检查一段时间内的线图是否有明显的趋势,参见[6]中的一些示例。
 - 比较序列的各种(随机)分割的基本汇总统计数据(均值、方差、协方差)。
 - 检查自相关图:随着滞后时间的增加,曲线下降得越快,序列中非*稳性的顺序就越少。
 - 最常见的*稳性统计测试是单位根的扩展 Dickey Fuller (ADF)测试。
 
直观地说,单位根(形式上是位于单位圆上的过程的特征方程的解(见【2】)的含义是,初始条件或外部冲击不会随时间消散,而是通过系列传播并通知所有后续值。
对于一个给定的置信水*,ADF 测试零假设“某个顺序的单位根的存在”(意味着时间序列的非*稳性)相对于*稳性(或者,严格地说,趋势*稳性)的替代。使自己相信单位根的存在确实意味着级数的非*稳性是很直接的:

所以方差是依赖于时间的。
由于许多经典模型方法的一个必要假设是时间序列的*稳性:当您的数据中有明确的趋势或季节性时,您将删除它并对剩余部分进行建模。对于预测,然后将(确定性)趋势和模型输出结合起来。
使序列*稳的常用变换是某一阶的差分:一阶差分就是从每个值中减去前一个值(提取变化率)。二阶差分对结果序列重复这一过程,对高阶序列也是如此。例如,在金融时间序列中,您会考虑(对数)回报而不是绝对价格,以使模型对特定价格水*不可知(事实上,对于大多数金融序列,一阶差分足以确保*稳性——我仍然不知道为什么)。
在基于自相关的 Arima(p,d,q) 类型的模型中,差分实际上是算法的一部分:参数 p,d 和 q 是非负的 整数 ,其中 p 表示自回归模型的阶(即时滞的数量),而 d 表示差分的阶,而 q 表示阶
这个过程通过外科手术消除了数列中的单位根。
然而,另一方面,它清除了内存,而内存是模型预测能力的基础:差异限制了过去的信息如何通过序列传播。
例如,对于金融序列,人们面临着一个没有记忆的稳定回报序列(一阶差分)和一个有记忆但不稳定的绝对价格序列(零阶差分)之间的两难选择。
但也许根本不需要这种极性?如果我们能在这两个极端之间进行插值会怎么样?
“……这将导致一个悖论,总有一天会从中得出有益的结论。”莱布尼茨,1695 年
分数微积分
其实我们可以:17 世纪牛顿和莱布尼茨发明微积分后不久,数学家们就探索了分数导数的使用,其中微分或积分的阶从自然数扩展到实数。然而,分数微积分在 20 世纪的工作应该找到它的第一个自然应用,并在 20 世纪 80 年代通过 Hosking 和 Granger 的 Arfima 模型进入金融领域(全面的历史记录见[4])。
在历史上,这种推广的第一个试探法似乎是由欧拉在 1730 年左右通过伽马函数将二项式系数推广到实数阶而给出的。这后来通过用于重复微分的柯西公式以及在黎曼和刘维尔的积分理论中变得更加严格(例如参见[3])。
这里我们只是给出我们应用于时间序列差分的形式启发:
设 B 表示滞后算子,即B Xt=X{ t-1 }对于 t > 1 和某个时间序列 X ={X_ 1 ,…}。然后,一阶元素差分可以用恒等运算符 I 表示为

该算子的多项式理解为重复应用,如B X{ t }=X{ t-2 }。我们可以用二项式系数来展开这个数列:

Formal power series expansion of the differencing operator (see Arfima models [5]).
虽然对于 d ∈ ℜ,情况可以变得更加严格,但是在这里,由于我们将在下面的应用中仅使用这种展开的截断版本,我们实际上不必担心这种形式推导的收敛性。
从这个推导中,我们可以读出滞后权重的迭代公式

其中ω_ k 是滞后算子 B ^k 的系数。
比如退货,ω_ 0 = 1,ω_ 1 = -1,ω_ k =0 对于 k > 1(一阶差分)。
让我们看看不同阶差分的系数(代码如下)。

我们注意到分数差分的两个重要细节:
- 对于任何整数 d ∈ 𝒩且 d < k: 的滞后权重等于零,这意味着我们恢复了整数订单的通常推导。
 - 对于实数阶 d 和大滞后,滞后权重逐渐变小。这种现象被称为'长记忆'(或微积分语境中的'非定域性'),通常需要边界条件。这里,我们简单地选择切断超过某个窗口大小的(小)权重。
 
金融时间序列建模的应用
时间序列起主导作用的一个领域是金融。为了更直观地了解分数差分的特性,让我们将其应用于一些典型的金融时间序列。
我们通过将差分算子的上述形式级数展开应用于指定实数阶 d ∈ℜ和固定窗口大小的时间序列来获得变换后的序列——使用下面的代码,简单地将熊猫时间序列输入到函数ts _ difference中,带有参数 order 和 lag_cutoff 。

Bitcoin prices 2016–18 (in red, right axis) along with some fractional derivatives (shades of blue).
你可能已经注意到,比特币的价格在 2017 年和 2018 年经历了明显的炒作(上图中的红色曲线)。事实上,看一下一阶差异,我们会发现价格在某些日子里上涨了 2500 多美元(例如 12 月 17 日)。该图展示了一些分数阶差分的*滑函数插值。令人惊讶的是,即使对于如此强劲的趋势,大约 0.4 阶的微弱差异实际上也足以使序列*稳:给定样本的 ADF 统计量-5 已经低于 DF t 分布的临界值-2.86,因此在 95%的置信度下,可以假定序列*稳。事实上,随着财富的来来去去,很快就出现了均值回归。
对于许多其他金融时间序列来说,低阶差分足以满足*稳性的发现是相似的。
为了说明*稳性和记忆性之间的权衡,我们可以遵循[7]中的适当可视化,并绘制 ADF 测试统计数据以及与原始序列的(线性)相关性,用于以各种差分顺序转换的序列。(请注意,较低的 ADF 检验统计表明替代检验的可能性较高,即值越负,我们越有可能拒绝零假设并假设*稳性)。
对于各种典型的金融序列,如(滚动)商品期货、汇率和指数,这种比较清楚地表明,(低)分数阶差分满足金融建模的*稳性条件,同时保持特定的记忆结构,从而保持原始序列的统计动态。




ADF test statistics (left axis, curve in red) and linear correlation (right axis, curve in cornflower blue) with the original series for various fractional orders of differencing, applied to various Financial time series. The constant line in slate grey marks the 95% significance level of the ADF test.
结论
非常令人惊讶的是,在引入 Arfima 模型大约一代人之后,分数差分的概念似乎还没有在金融领域获得广泛的关注。在某种程度上,许多人可能归因于“市场效率”的东西可能只不过是通过不适当的数据预处理而自愿取消信息的人工制品。
我希望这篇文章能提出一个令人信服的观点,将这种有效的技术包含到您的建模工具包中。
作者:作为一名热情的数据科学家,我在过去四年里一直担任全球初创公司的技术主管,并实施现实生活中的人工智能解决方案。请发邮件到 simon'at'deepprojects.de 联系我。
参考文献:
[1]维基百科,*稳过程。
[2]维基百科,单位根。
[3]维基百科,分数微积分。
[4] Grave,Gramacy,Watkins and Franzke,《长记忆简史:赫斯特、曼德尔布罗和通往阿尔菲玛之路》,1951–1980。
[5]维基百科,阿尔菲玛。
[6]分析 Vidhya,非*稳时间序列。
[7]德普拉多,金融机器学习进展,威利 2018。
数据:
- 以美元计价的比特币,每日收盘价,来源:公共
 - 煤炭 API 2 月期货滚动链,每日结算价格,来源:专有
 - 道琼斯指数,每日结算价格,来源:雅虎
 - SP500 指数,每日结算价格,来源:雅虎
 
代码:
https://gist . github . com/skuttruf/FB 82807 ab 0400 FBA 51 c 344313 EB 43466
总统魅力:你应该投票给谁?

Photo by Glen Carrie on Unsplash
无论是总统候选人还是电视节目主持人,有魅力的人都能传达他们的信息,更好地与他人沟通,并获得他们的信任。但是对于一个总统来说,魅力能透露出他们有可能成为多好的总统吗?
当你决定投票给一位候选人时,你是投票给体现你的政党价值观的领导人还是偏向于健谈者?
魅力型领导者迎合观众的情绪,但不仅仅如此,根据康奈尔纪事报的研究,如果人们还没有决定,投票给候选人不再是政策或经验,而是魅力。
魅力被定义为在深层情感层面影响他人、与他人有效沟通、建立强大人际关系的力量。对我们人类来说,魅力很容易被发现,但这是一种机器很难识别的特征。为了让机器理解魅力,它应该被量化。为了继续测量魅力,我将转向自然语言处理(NLP),这是人工智能与语言打交道的一部分。
总统演讲提供了一个理想的文本收集来检测模式,量化一些特征并回答我们的问题:魅力与总统在办公室的表现有任何联系吗?我们将看看数据对此有何说明。
所有数据科学发生的地方
数据收集和清理:
没有数据就无法分析,所以我开始通过寻找我能找到的所有总统演讲的文字记录来回答我的问题。幸运的是,米勒中心组织拥有美国历史上每一次总统演讲的记录,这些脚本的内容是使用 Selenium 和 BeautifulSoup 库从他们的网站上刮下来的。
现在这部分对我来说是最具挑战性的,在没有 HTML 和 CSS 经验的情况下使用 BeautifulSoup(最终我得到了一个 web-scraper 和一些 HTML 知识)。这些文字记录随后被保存到一本字典中,上面有总统的名字和相应的讲话。代码可以在这里找到,除了可视化在 Tableau 上可以在这里找到。
量化魅力:
魅力是很难衡量的,但我还是打算回答如何量化它。在现代,那些利用故事和隐喻来调动情感、构建愿景并描绘愿景的领导人被认为是有魅力的。所以魅力型演讲简单地说,包含三个重要特质:
- 使用个人观点、情感、故事和隐喻。
 - 表达情感,展示自信,传递积极的信息。
 - 简单的语言让不同的人产生共鸣。
 
通过使用 NLTK 库、 TextBlob 和 Textstat ,这三个组件通过以下方式进行测量:
- 可读性:Flesch 阅读难易程度基于两个因素来衡量文本难度:*均而言,一个句子中的单词更多,单词更长,或者有更多的音节。其中较高的分数表示材料更容易阅读和理解;数字越小,段落越难阅读。
 - 文本的主观性:主观句一般指个人观点、情感、故事或判断,而客观句指事实信息。主观性是一个位于[0,1]范围内的浮点数。
 - 文本的极性:这衡量文本的整体信息,它被衡量为一个位于[-1,1]范围内的浮点数,其中 1 表示肯定的陈述,而-1 表示否定的陈述。
 
我将魅力定义为每位总统在所有收集到的演讲中的轻松度、极性和主观性得分的*均值。
特朗普在六年级水*演讲:

Flesch Reading Ease Measure
从 Flesch 阅读容易度的图表来看,特朗普的阅读容易度最高,大约是六年级的水*,易于阅读(消费者的英语会话),这意味着容易被 12 岁的普通学生理解。
我们还可以看到,40 年前的大多数总统*均水*在 7 年级左右,阅读英语相当容易,除了吉米·卡特,他的英语水*在 8 到 9 年级。
对大量听众讲话意味着用我们都能理解的方式讲话,知道哪种语言能引起特定人群的共鸣能让你走得更远。我更进一步,想象了英语多年来的变化。

Simplicity of Language Across the Years
从上面的情节中,我们可以注意到多年来语言简化的趋势,从大学水*-难以阅读-到容易被高中生理解或在今天的政治中,被六年级学生理解。
演讲最积极的总统:

Presidents with Most Positive Speeches
我们可以看到,詹姆斯·a·加菲尔德、哈里·S·杜鲁门和唐纳德·川普在极性测量中得分最高。从其余的结果来看,演讲的积极性与语言的简单性不同,它更多地取决于总统的性格而不是总统任期的长短。在本分析的其余部分,我们将关注那些在办公室完成时间导致唐纳德·特朗普从最终结果中排除的总统。
谁最有魅力?

Charisma Measure
请记住,魅力的衡量标准取决于阅读的难易程度,也就是说,阅读的难易程度越高,你就越有魅力。很自然,杜鲁门和比尔·克林顿领先,其次是理查德·尼克松、林登·约翰逊、巴拉克·奥巴马和乔治·h·w·布什。
政治学家兼博客作者乔纳森·伯恩斯坦在《福布斯》的文章中指出,虽然像克林顿和奥巴马这样的总统仍然被认为是有魅力的,但是像尼克松、约翰逊和老布什这样的总统已经失去了他们的魅力。
办公室表现:总统历史学家调查
为了完成所需的数据,美国总统排名数据来自总统历史学家调查,该调查根据十个不同的因素对总统进行排名,如危机领导力、道德权威、与国会的关系和经济管理。
魅力和排名的相关性:

Correlation Between Charisma and Ranking
绩效排名和魅力是两个独立变量,我们可以在图中看到两者的散点图。它们之间的相关性等于 0.168,表明这两个变量之间的关系非常轻微。然而,假设任何一种关系都需要更全面的方法来衡量魅力,但目前我们可以得出结论,两者之间没有相关性。
“言行一致”的总统:
现在在下图中,在添加了每半个世纪的相关线后,我们可以看到一些有趣的结果;从 20 世纪 50 年代开始,总统们的得分非常接*,而之前的总统们的得分更加分散。在 20 世纪 50 年代,随着电视在美国的广泛普及,使其成为影响公众舆论的主要媒体,总统们开始更加关注他们如何向公众发表演讲。

Correlation Between Charisma and Ranking
看看 1850 年、1900 年和 1950 年的数据,我们可以看到魅力和排名之间的正相关,所以那个时期的总统更有可能言行一致。进入 21 世纪,我们可以看到魅力和排名之间没有相关性,几乎是一条直线。因此,在我们这个时代,总统更有可能言出必行,但这并不一定意味着他们的表现会反映出他们是多么优秀的演说家。
魅力型领导者知道什么是最好的,在某些方面表现突出,在某种意义上是当天的救星,但真正的魅力是让你能够影响别人,让你的信息被传达,不管这个信息有多有效或理智。这并不一定能让你更善于做出决定,引导一个国家朝着正确的方向前进。
这给了我们一个结论性的答案,无论一位总统或总统候选人在选举、辩论或演讲时多么有魅力,都不能说明他们当选后会有多好。所以,当你下次投票时,请记住,魅力并不能让总统成为更有效的领导者。
这个项目是作为数据艺术与科学奖学金的一部分完成的。
使用的来源:
研究人员发现,投票给候选人与政策或经验无关,而是关乎个人魅力
2020 年初初选的新闻报道
2020 年民主党总统初选早期媒体报道观察
诚然,我们仍处于 2019 年,下一届美国总统选举是在 2020 年,距离撰写本文大约 17 个月。然而,选举进程已经开始,有 20 多名个人已经宣布参选,正在争取民主党的提名。事实上,该党已经举行了第一次辩论,竞选正在进行中。
这是探究候选人投票和媒体报道之间关系的好时机。获得洞察力和建立选举状况的全面概览的一个方法是分析参与竞选活动的民调和新闻指标数据,以寻找相似性、差异和模式。通过结合这两个数据维度,我们能够更好地评估单个候选人的相对表现和定位。
以前的工作和数据
这项分析更新了之前的工作,该工作检查了 2016 年共和党总统初选的类似数据(后)。此外,更多信息和 2016 年和 2020 年分析的底层代码可以在我的 GitHub 网站找到。
民意调查数据来自 FiveThirtyEight ,这是一家分析服务公司,拥有一个广受欢迎的网站,提供政治、体育、科学和健康、经济和文化的定量和统计分析。新闻数据来自全球事件、语言和语调数据或 GDELT 项目。GDELT 是一个监控、存储和提供“来自几乎每个国家每个角落的世界广播、印刷和网络新闻”的项目。
辩论结果
首先要看的是上周辩论后候选人的民调表现。下图包含辩论后第一次民意调查(2019 年 6 月 28 日发布)的排名快照,以及每位候选人相对于之前民意调查*均值的变化。从这一点上,我们注意到乔·拜登领先,他的民调结果在辩论后没有太大变化,尽管人们普遍认为他在舞台上表现不佳。许多人认为卡玛拉·哈里斯和伊丽莎白·沃伦表现出色,两个国家的民调都大幅上升。其他几名候选人,特别是贝托·奥罗克,从相对较低的水*下降。

新闻报道
绘制民意测验排名与媒体报道量的对比图是很有帮助的。下面的图表包含*均投票表现与*均投票周期之间出现的文章的*均数量,10 个候选人具有最高的*均投票。正如所料,两者之间存在积极的关系,领先的候选人获得了最多的报道。
在这张图表中,拜登似乎是一个明显的领先者,在民意调查中大幅领先,比任何其他候选人都有更多的媒体报道。伯尼·桑德斯的新闻报道与他在民调中的第二名一致,但鉴于他 2016 年的总统竞选和长期的公共存在,人们可能会认为新闻报道的数字更接*拜登。沃伦和哈里斯的民调数字相似,但沃伦吸引了更多的媒体报道。有趣的是,奥洛克和哈里斯的文章数量相似,但在民意调查中似乎朝着相反的方向发展,看看他们各自的新闻报道指标是否有所不同将是一件有趣的事情。

音调
GDELT 项目追踪的一个属性是文章语气的度量。关于声调的更多信息可以在 GDELT 文档中找到,但是,总而言之,它测量的是正负词频之间的差异。虽然它的范围可以从-100 到+100,但这里检查的文档的分数集中在零附*,对于这些数据,相对较小的差异是显著的(例如,涵盖 Warren 的文章的*均色调*均值在统计上不同于 0 和-0.5)。
绘制民意测验表现与这一指标的关系图很有帮助,这些指标是引用每个候选人的文章的*均值。即使*均色调较小,也会出现明显的模式。从下图中可以看出,候选人可以分为两组,分别用矩形和椭圆形表示。与奥罗克、皮特·布蒂吉格、科里·布克和艾米·克洛布查尔相比,沃伦、哈里斯、桑德斯、柯尔斯顿·吉利布兰德和拜登在报道中都看到了更多负面论调。

极性
GDELT 项目还测量文档极性,并绘制候选人之间的投票结果与该值的关系图,这也产生了有趣的结果。较高的值与文档中极化语言的较高流行度相关联。
在这种情况下,我们看到一组四个领先的候选人,拜登,桑德斯,沃伦和哈里斯,都比其余的前 10 名领域获得更高的极性覆盖。在这个群体中,桑德斯的报道具有最高的极性*均值。鉴于人们认为他的政策立场偏左,这可能是意料之中的。同样有趣的是,拜登的报道没有哈里斯、沃伦和桑德斯那么两极化。

概括起来
虽然现在显然还处于 2020 年民主党总统初选的早期,但潜在选民已经被要求开始形成观点,并在一个大型候选人中选择领导人。收集和分析这些候选人的数据是获得这些观点的本质的一种方法。
从这项工作中,我们看到领先的候选人享有最多的新闻文件。然而,与观察到的中层参与者相比,这种报道具有更消极的基调和更高的极性。此外,在领先的种族中,这些指标明显不同,其中一些具有特别负面和两极化的报道。
Python 中柱状数据的漂亮展示技巧
改进 Python 及其库显示数据的方式,并使其可读
对于以前使用 lists、Pandas 或 NumPy 广泛争论过数据的每个人来说,您可能都遇到过以正确的方式打印数据的问题。特别是如果有很多列,显示数据就变得很麻烦。本文向您展示了如何以可读的方式用 python 打印大型列数据。
为了解释清楚,我使用的是 NYC 房产销售数据,总共有 21 列。
如果您有一个包含许多列的 Pandas 数据帧,并试图用常规的 print 语句将其打印出来,就会发生这种情况:
**import** pandas **as** pdnycdata=pd.read_csv(**'nyc-rolling-sales.csv'**,index_col=0)print(nycdata.head())

Data is omitted from printing
发生这种情况是因为 Pandas 将检测它可以在终端窗口空间中容纳的列数,这将不会准确显示我们需要的内容。为了节省屏幕上的终端空间,打印时会忽略大部分数据。
要解决这个问题,这里有一些方法。
好的绝招
您可以增加 Pandas 允许您显示的最大列数,方法是在代码中添加以下代码行:
pd.options.display.max_columns = **None**
这将取消屏幕上显示的最大列数限制。以下是打印时的样子(现在只打印前 11 列..)

Print result after removing max column limit
但是,嘿,这并不完全是我们所需要的。数据被分成多行,标题由反斜杠分隔。这是可读和有用的,但仍不完美。
要克服这一点,只需在代码中使用这一行,就可以在一行中获得所有数据:
pd.options.display.width=None
这是它现在的样子(只打印了 7 列):

Print result after removing max width limit
注意——大多数代码编辑器不会以一种好的方式显示大块的列数据。您的输出将以一种完全不可读的方式变得混乱,并且您需要最大化您的输出窗口以便很好地查看所有的数据。PyCharm 在这种情况下做得非常好——它向您显示了一个水*滚动条,您可以在这里滚动浏览您打印的数据。标准终端或编辑器(如 VSCode)不会出现这种情况。
如果您使用终端或 VSCode,请将窗口最大化并减小字体大小,以便您可以在有限的空间中容纳最多的列,并且可以很好地查看您的数据。
这是完整数据在终端输出中的显示方式(VSCode 以同样的方式打印):

All columns in Terminal
这是 PyCharm 展示相同数据的方式:

PyCharm’s scrollbar print
如果您正在使用 PyCharm,并且希望显示与上述类似的数据,或者如果您认为最大化和缩小字体大小是可以接受的,这里有一个更好的方法来显示您的数据。
更好的绝招:
您可以使用名为“制表”的库来轻松显示列中的数据。这就像将一个简单的函数封装到数据帧上使用的打印函数中一样简单。
**from** tabulate **import** tabulate
.
.
.
print(tabulate(df,headers=**'firstrow'**))
这就是制表显示数据的方式:

Tabulate’s print
为了去掉 print 语句中多余的代码行,可以这样编写一个简单的 lambda 函数:
**from** tabulate **import** tabulate
pdtabulate=**lambda** df:tabulate(df,headers=**'keys'**)
.
.
.
print(pdtabulate(df))
更神奇的是,你可以从多种格式中选择打印格式。你所需要做的就是将' tablefmt '参数添加到制表函数中,并为其分配你选择的打印格式。我最喜欢的是“ psql ,它使用 PostgreSQL 的格式来显示表格数据。
**from** tabulate **import** tabulate
pdtabulate=**lambda** df:tabulate(df,headers=**'keys'**,tablefmt=**'psql'**)
.
.
.
print(pdtabulate(df))
这是它看起来的样子:

Feels like SQL!
如果您有必要将数据转换成 HTML 表格,制表很容易为您做到这一点。
**from** tabulate **import** tabulate
pdtabulate=**lambda** df:tabulate(df,headers=**'keys'**,tablefmt=**'html'**)
.
.
.
print(pdtabulate(df))

Data printed to HTML Tables
即使对于大型列表和巨大的 NumPy 数组,制表也非常有效。
**from** tabulate **import** tabulate
pdtabulate=**lambda** df:tabulate(df,headers=**'keys'**,tablefmt=**'psql'**)#Creating a list using garbage values
list = [['a', 'b', 'c','d'], ['aaaaaaaaaa', 'b', 'c'], ['a', 'bbbbbbbbbb', 'c'], ['aaaaaaaaaa', 'b', 'c'], ['a', 'bbbbbbbbbb', 'c'], ['aaaaaaaaaa', 'b', 'c'], ['a', 'bbbbbbbbbb', 'c'], ['aaaaaaaaaa', 'b', 'c'], ['a', 'bbbbbbbbbb', 'c']]print(pdtabulate(list))
这是它看起来的样子:

Normal vs tabulated prints of 2D lists
下面是一个使用制表可视化的示例 NumPy 数组:

Normal vs tabulated prints of a simple NumPy array
更多关于这个令人惊叹的图书馆的信息和更多关于不同印刷格式的知识,请访问本页。
虽然这些技巧会很有帮助,但下面的技巧尽可能以最好的方式展示了我们的数据。
最好的绝招:
忘掉 PyCharm、终端和制表软件吧——用 Jupyter 笔记本来显示你的数据。
Jupyter 笔记本显示您的数据类似于第一种开箱即用的情况——它们在显示中省略了几列。

Data displayed in a Jupyter Notebook — few columns are omitted
为了解决这个问题,使用打印示例中使用的同一行来显示数据的所有列:
pd.options.display.max_columns = **None**
Jupyter 向您展示了一个完美格式化的 HTML 表格:

Data after removing max column limit
一天的结束..
如果你习惯经常使用 Jupyter 笔记本,只需将最大列数设置为无,就可以一次显示所有数据。但是如果你是一个喜欢在编辑器中编写代码,而不是使用 Jupyter 笔记本来理解数据的人,那么使用制表库是最好的选择。
防止机器学习模型中的数据泄漏
在建立机器学习模型时,关于防止数据泄漏,您需要知道的一切。

Photo by Luis Quintero from Pexels
数据泄露问题
机器学习算法制作预测和分类数据的模型。常见的最佳实践是首先将可用数据集分成两个训练和测试数据子集。之后,使用训练集对模型进行训练,并通过将其性能与测试集的性能进行比较来衡量其成功。
但是如果模型在被训练的时候暴露在测试数据中会怎么样呢?
这就是数据泄露的问题——当用于训练模型的数据恰好包含试图预测的信息时。如果一个模型暴露于测试数据,那么它当然会在预测/分类它被训练来预测/分类的测试数据方面表现得更好。
如果未被检测到,数据泄露可能会导致问题,包括:
- 实验室中夸大的模型性能,以及
 - 与真实数据一起部署时性能较差。
 
使用机器学习算法来建立模型的目的是模拟现实世界中看不见的数据,并找出如何一致地预测或分类数据。但是,如果发生数据泄漏,一个模型不太可能在现实世界中用新数据很好地概括。因此,在开发模型时,必须采取措施防止数据泄漏。
帮助防止数据泄露的 6 种方法
- 了解数据集
 - 清除数据集的重复项
 - 选择关于目标变量相关性和时间排序的特征
 - 将数据集分为训练组、验证组和测试组
 - 在分割之后、交叉验证之前进行规范化
 - 以健康的怀疑态度评估模型性能
 
1.了解数据集
不言而喻,为了能够执行有效的分析和开发合理的模型,关于您正在处理的数据集的知识是必要的。
然而,在数据泄漏方面,很少提到的是,在将数据分成训练-验证-测试组之前,您应该避免研究数据集的分布或基本统计数据(稍后将详细介绍如何分割数据集)。如果您在分割之前检查您的数据,您将获得关于可能在您的测试组中结束的数据行的见解,这实际上是数据泄漏。
2.清除数据集的重复项
数据清理是大多数(如果不是全部)数据科学项目的必要步骤。一个常见的数据清理任务是处理具有重复信息的行。在数据泄漏的情况下,重要的是删除重复的行,这样就不会在训练组和测试组中都出现重复的行。
3.选择关于目标变量相关性和时间排序的特征
防止数据泄漏的下一个重要步骤是选择与目标变量不相关且在预测时可用的特征或独立变量。
考虑目标变量相关性
如果一个变量与目标变量高度相关,无疑会增加你的模型对目标的预测能力。例如,如果您的目标变量是家庭收入,并且您将家庭支出作为一个特征包含在您的模型中,那么很有理由认为您的模型会更好地预测家庭收入,因为家庭支出是家庭收入的一个非常直接的指标。因此,为了防止数据泄漏,最好从模型中省略这些特征。
考虑时间排序
用未来数据预测过去是数据泄露的一种形式。时间序列数据、预测发生时不可用的特征或关于未来数据的分类特征都是与数据的时间顺序(顺序计时)相关的数据泄漏威胁。
当处理时间序列数据时,挑战在于确保不将关于未来的信息泄露给过去。例如,将 2019 年的数据包括在一个模型中,该模型被训练来对 2018 年进行预测。克服时间序列数据泄漏的一个选择是对每个时间段进行训练-验证-测试分割。
另一种选择是移除在预测时不可用的所有数据/ 特征。例如,关于客户是否会拖欠贷款的信息可能要到客户实际拖欠并且贷款已经被批准之后才可用。因此,如果有关延迟付款状态的信息包含在决定是否批准向该客户提供贷款的模型中,将会出现数据泄漏,从而使模型在现实环境中变得不切实际。
此外,有必要研究一下标记未来信息的分类特征。例如,基于高购买频率,客户可能被标记为“大买家”,但是如果模型试图预测哪些客户将是频繁的回头客,此信息将导致数据泄漏。
关于在使用时间序列数据检验时防止数据泄漏的更多信息 Rafael Pierre 的" 数据泄漏,第一部分:认为你有一个很棒的机器学习模型?再想想 ”并且为了更深入的解释时态排序,checkout Devin Soni 的“ 机器学习中的数据泄漏 ”
4.将数据集分为训练组、验证组和测试组
将数据分成两组,训练组和测试组,是标准的做法。但是,我建议更进一步,将数据分成三组——训练组、验证组和测试组。有了三个组,您就有了一个验证组来帮助超调模型参数,以及一个在模型调优后使用的最终测试组。
分割后,不要在验证和测试集上执行探索性数据分析——只对训练集执行!通过检查验证或测试集的洞察力生成的任何附加特征或模型更新都是数据泄漏的实例。
分区是将数据集分成训练、验证和测试组时要考虑的一个重要步骤,因为有多个行来自同一个源。分区包括对该源的行进行分组,并且只将它们包含在一个分割集中,否则来自该源的数据将会在多个集中泄漏。
5.在分割之后、交叉验证之前进行规范化
很多机器学习算法都需要归一化。但是,在拆分数据后进行规范化非常重要。如果在分割前进行归一化,用于归一化数据的*均值和标准差将基于整个数据集,而不是训练子集,因此会将有关测试或验证集的信息泄漏到训练集中。
将数据拆分为训练集、验证集和测试集后,最佳方法是首先规范化训练集,然后将训练集规范化的*均值和标准差应用于验证集和测试集规范化。
但是,如果您计划使用网格搜索交叉验证来超调参数,如果在交叉验证之前进行,缩放训练集将导致数据泄漏,因为交叉验证进一步将训练集划分为附加的训练集和测试集。建议将 Pipeline 与 GridSearchCV 配合使用,以便通过标准缩放器等数据预处理程序更恰当地缩放数据。我在下面附上了一个代码截图,它使用管道在使用 GridSearchCV 时适当地缩放数据。

6.以健康的怀疑态度评估模型性能
最后,但同样重要的是,在评估模型性能时,保持健康的怀疑态度是很重要的。
多个来源警告数据科学家,当一个模型具有高性能分数时,要感到疲倦,因为优秀的分数可能表明数据泄漏。以下是评估模型性能时需要考虑的六点。这些问题的答案可能会暗示数据泄露是否正在发生。
考虑使用的机器学习算法
在评估你的模型的时候,先想想正在使用的机器学习算法。算法是在复杂问题上表现良好的弱算法吗?该算法过去是否用于类似的数据/问题?与您当前模型的性能相比,该算法在过去案例中的性能如何?
与基线比较
回头看看你的基线模型,寻找“好得令人难以置信”的表现
合理化功能重要性
如果你的算法返回特征重要性,试着想出一个合理的解释来解释为什么每个重要的特征是重要的。如果不存在逻辑上的原因,就有数据泄露的可能。也试着一次从你的模型中去掉一个特性,如果性能急剧下降,那么被去掉的特性有可能包含泄漏。
使用多个指标
建议在评估模型性能时使用多种方法。如果您只使用一个指标(例如准确性),该指标可能会隐藏其他指标可能会发现的数据泄漏。
检查训练集和测试集分布
在拟合模型和测量性能之后,探索训练、验证和测试组的分布以发现差异和可以解释结果的任何模式将是有益的。
使用新的验证集进行测试
最后,如果您有资源,检索更多的数据来测试模型在尽可能接*现实的新验证集上的性能总是有利的。
使用机器学习预防心脏病死亡
心脏病正在夺去全世界数百万人的生命。而机器学习或许可以帮助解决这个问题。
世界上最主要的死亡原因是什么?
癌症?
号码
伤害/事故?
不。继续努力。
呼吸道疾病,糖尿病,老年痴呆症?
不,不,不。
导致死亡的主要原因是心脏病。
自 2000 年以来,它一直是导致死亡的主要原因。

Source: WHO
每年有 50 多万美国人死于心脏病,如冠状动脉疾病、心血管疾病和心绞痛。(精确到 61.3 万)。医疗保健服务和心脏病药物每年花费美国* 2000 亿美元。
因此,50 万人失去了生命,2000 亿美元花掉了
每,
单个,
年,
用于心脏病。(仅在美国)
嗯,现在很糟糕,但是未来会是什么样子呢?
2030 年,美国心脏协会预计治疗心脏病的费用将上升到 8180 亿美元。美国将有 1.16 亿人患有某种形式的心血管疾病。
人们患心脏病有两个主要原因
问题的一半是遗传。人们生来就有基因突变,这增加了他们患心脏病的可能性。不幸的是,我们现在无法控制这一点,但通过像 CRISPR 这样的基因编辑技术,我们也许可以在未来防止这一点。
问题的另一半是糟糕的生活方式。人们每天都会做出导致心脏病的糟糕决定。
我们可以将这些因素分为四类。
- 缺乏运动——35%心脏病的原因。
 - 肥胖——2700 万美国人患有由肥胖引起的心脏病
 - 吸烟——20%的心脏病死亡与吸烟直接相关
 - 不良饮食美国有 50 万人因为高脂肪饮食而患心脏病。高胆固醇占心脏病患者的 15%。糖尿病占心脏病患者的 11%。
 
所有这些因素都有一个共同点。他们都在我们的控制之下。我们可以决定是否要锻炼、吸烟和保持健康的饮食。这是一个选择。因此,如果这些人做出更明智的决定,这些因素导致的死亡是可以避免的。
为了做出明智的决定,人们需要信息。
让我们预防心脏病造成的死亡。
首先,快速回顾一下。我们知道很多人死于心脏病,如果人们选择更好的生活方式,一半的死亡是可以避免的。那么我们如何做到这一点呢?
使用一种叫做机器学习的人工智能子集,我们可以在某人死于心脏病之前预测他患心脏病的可能性。如果人们知道他们患致命疾病的可能性,这将鼓励他们做出更明智的生活方式选择。从而减少死于心脏病的人数。
这将如何工作?
我们可以使用机器学习算法来获取信息,并对一个人是否可能患有心脏病进行分类。
使用 UCI 机器学习知识库中的 Cleveland 数据集,我自己进行了试验。
该模型接受了每个人的 13 个不同的数据点。

13 different attributes in Cleveland Heart Disease Dataset
我实现了一个支持向量机(SVM)
下面是外行人对支持向量机的解释。
SVM 是一种执行分类任务的监督学习算法。简单地说,它使用带标签的数据来区分输入的类别。
这是一个关于其工作原理的类比。
你是一所中学的老师。一天,你在中学操场上巡逻,确保每个人都安然无恙。突然,六年级学生和八年级学生之间爆发了一场打斗。作为一名教师,你需要做三件事。
- 把八年级和六年级的学生分开
 - 不要和任何一方有任何身体接触。
 - 保护你的生命:)
 
该字段如下所示:

Middle school field
在你的第一次尝试中,你成功地分开了六年级和八年级的学生,但是你和他们发生了身体接触,并且冒着生命危险接触了荷尔蒙分泌旺盛的八年级学生。

所以你再试一次:

Excellent SVM
第二次尝试非常成功。你不仅救了自己的命,还提醒你,你的学校教育终于是值得的。Jk,但是你在 1 号位做得很好。把八年级和六年级的学生和 2。最大化每个中学生与自己的距离。
这是一个非常好的支持向量机算法的例子。
在这个例子中,我们的两个班级是八年级和六年级。我们正试图将这两个阶层区分开来。
老师代表一个超*面。我不打算在本文中解释什么是超*面,但它可以被认为是进行分类的直线。
SVM 的目标是找到一个最优的分离超*面。
在上面的例子中,我们正是这样做的,因为我们对两个类进行了分类,并最大化了从蓝线到每个输入的距离。这也证明了为什么我们当老师的第一次尝试不那么顺利。我们没有找到最优分离超*面。
我们老师(蓝线)可以认为是一个超*面。最佳分离超*面的作用是对班级进行分类,在这种情况下是八年级和六年级,并最大化每个输入和完成的线之间的距离。
概括地说,SVM 是一种机器学习算法,它使用超*面来划分类别。最优分离超*面是它旨在用于类别之间的分类。可以用 1 来区分。准确地分离所有的类和 2。最大化每个输入和超*面之间的距离。
使用 scikit-learn,一个机器学习包,我实现了一个 SVM 来对心脏病高概率人群和低概率人群进行分类。
使用克里夫兰心脏病数据集,我实现了一个 SVM 来分类某人患心脏病的可能性…
github.com](https://github.com/BriannaGopaul/heartdisease/blob/master/Heart Disease Notebook.ipynb)
不幸的是,我得到了大约 62%的准确率,这不足以在现实世界中使用。经过更多的研究,我了解到三件事。首先,支持向量机并不擅长多类分类任务。其次,我需要更好地预处理更多的数据。这是我现在正在学习的东西,我重申。第三,在网上找到开源的健康数据真的很难。
尽管机器学习是一个非常新颖的领域,但如果数据科学家和机器学习专家能够获得开源的健康数据,我们将有望解决我们目前在医疗保健领域面临的许多问题。我们现在还没有达到预防心脏病死亡的阶段,但这是做类似事情的起点。
我接下来要做的:
为了继续开发人工智能知识库,我将在吴恩达的机器学习课程上取得更多进展,并致力于更多的项目来应用我的知识。
如果你想了解更多关于我参与的其他项目,请查看我的作品集 这里 和我联系linked ln。
防止信贷模型中的歧视性结果
机器学习正在被部署来进行大规模决策,这可以强烈影响个人的生活。如果不考虑和分析这种情况,我们最终可能会构建出无法*等对待社会、甚至违反反歧视法的模型。
有几种算法干预来识别不公*待遇基于什么被认为是公*。在本文中,我们将通过一个案例研究来探讨这些方法,并解释它们的优点和局限性。
👩🏻💻你可以在这个 Github 库中找到完整的 python 项目。
❗️Warning::这篇文章包含了很多关于混淆矩阵和相关指标的信息。
1)歧视的来源
尺寸
在机器学习中,我们的世界被测量并存储在数据集中。这种实践的最大挑战是它本质上是主观的。人类需要想出最佳的标签来对我们的世界进行分类,这可能会导致选择偏差。不仅目标变量可能对所有群体都不正确,而且收集的描述它的信息也不正确。
在技术方面,数据集也可能有不正确、不完整的 和/或 过时的 信息(阅读 美国各地的警察正在根据伪造的数据 ) 。同样重要的是要记住,随着世界的变化,描述世界的标签也在变化。这会导致对我们周围环境的过时描述。
最后,我们还有宣扬历史偏见,陈规定型观念和污名被保留为常态。
学问
模型从数据中学习,以检测模式并对其进行归纳,这可能包括数据差异、失真和偏差。即使我们没有明确提供敏感信息以避免偏见,也有几个代理可以*似它(阅读 性格测试不合格美国工人 )。
与此同时,随着更多相关信息的提供,模型工作得更好。少数群体默认处于劣势,因为他们通常没有多少数据可供模型学习(阅读 亚马逊废弃的秘密人工智能招聘工具,该工具显示出对女性的偏见 ) 。
动作
一个动作是来自一个模型的一个决策,比如批准一笔贷款或者显示一个广告。当一个模型被校准时,很可能会对不同的组产生不同的误差率。在这个群体中缺乏分析会导致不公*的待遇(我们将在后面的案例研究中修改这一点,另外,请阅读 ProPublica 的 机器偏见)。
反馈
一些模型从用户交互中获得“反馈”来改进模型。在这里,我们会遇到以自我实现预测形式出现的歧视问题。当数据有偏差时,不公*的预测往往会被证实。在这种情况下,人类将受到影响,以使他们的反应验证不公*的预测(阅读 美国各地的警察正在训练基于伪造数据预测犯罪的人工智能 ) 。
2)算法干预
在本节中,我们将回顾五种不同的实践,这些实践被认为是在有监督的机器学习中测量不公*性的。
无知中的公*
当我们通过简单地排除受保护的类来运行模型时,就是这种情况。这个概念在确保公*性方面非常低效,因为有大量的代理可以预测这些属性。
人口均等
人口均等要求每个群体都有资格以相同的频率获得贷款。这也意味着决策应该独立于受保护的属性 a。这可以描述为下面的等式。

对于信贷模型,这可以解释为合格贷款的比例在集团的所有类别中都是相同的(正利率相等)。
均等机会
机会均等意味着在“有利的”结果中,正确分类的成员的比例,即 Y=1,在所有组中应该是相同的。例如,当一个条目被认为是“没有拖欠贷款”时,我们可以考虑“有利的”结果。对于中的所有受保护类,以下条件必须成立。这可以用下面的等式来表示:

这一概念通常会带来更好的效用,但与人口均等一样,它会用不太准确的假阳性来惩罚某个阶层。
在实践中,这需要两组的真实阳性率 A=1 和 A=0 相同。
均等几率
与机会均等一样,均等几率也要求“优势”结果中正确分类的成员比例在组内所有级别中相同。然而,它也要求“优势”结果中错误分类成员的比例在相应组的所有类别中相同。这可以用下面的公式表示:

这意味着不仅每组的真阳性率应该相同,假阳性率也应该相同。
3)案例研究
在这个案例研究中,我使用了 Bondora 的一本公共贷款书,这是一个位于爱沙尼亚的 P2P 借贷*台。我观察了两个不同的保护组:性别和年龄。
Bondora 向信用较差的客户提供贷款,违约率比传统银行高得多。这意味着收集的利息要高得多。该数据集的贷款金额*均约为 2100€,支付期限为 38 个月,利率为 26.30%。
对于传统银行来说,假阳性(对违约贷款进行错误分类)的成本比真阳性(对非违约贷款进行正确分类)的回报高很多倍。鉴于与银行相比,Bondora 收取的利率更高,出于说明的目的,我将假设报酬与成本之比在 1 比 2 时要小得多。这将用于找到最佳阈值,以最大化利润,同时满足每个算法干预的所有要求。
然后,我开发了一个分类模型,使用梯度增强决策树技术预测贷款是否可能被偿还。根据模型预测的结果,我分析了以下场景:
- 利润最大化对每一组采用不同的分类阈值,仅追求利润最大化。
 - 无意识公*在实现利润最大化的同时,对所有群体使用相同的分类阈值。
 - 人口统计学奇偶校验对每组应用不同的分类阈值,同时保持每组的阳性率相同。
 - 机会均等对各组使用不同的分类阈值,但各组真实阳性率保持不变。
 - 等概率对各组适用不同的分类阈值,但保持各组真阳性率和假阳性率相同。
 
简要数据探索
我选择了 Bondora *台上发放给爱沙尼亚居民的所有贷款。从访问之日起,总共有 21,450 个条目。发放给女性的贷款占所有贷款的 39%,而发放给男性的贷款比例为 61%。40 岁以下的人获得贷款的比例为 63%,而 40 岁以上的人获得贷款的比例为 37%。

整体违约率约为 42%。如果我们按性别调查违约率,我们会发现两组的违约率几乎相同,都在 44%左右。如果我们研究一下年龄,40 岁以下的人违约率略高,约为 45%,而 40 岁以上的人违约率为 42%。

ROC 和 AUC
我们现在来看看每组班级的 ROC 曲线。我们将在曲线中注意到的差异(例如男性对女性)是由于真阳性率和假阳性率的差异。较低的曲线,因此具有较低的 AUC 值,表明这些类别的预测不太准确。

如果我们观察上图中性别的 ROC 曲线,我们可以注意到女性的曲线在大多数情况下低于男性的曲线。因此,我们可以看到女性的 AUC 值为 0.760,略低于男性的 0.767。
如果我们看同样的图表,但这次是年龄组,我们可以注意到 40 岁以上的人的线通常在 40 岁以下的人的线之上。值得注意的是,在邦多拉的贷款记录中,40 岁以下人口的比例远远高于 40 岁以上人口的比例。这意味着描述 40 岁以下人群的其他特征可能是必要的。
对于每个组中确定的差异,我们可以开始考虑所使用的特征集合可能更能代表男性和/或 40 岁以上的人。该数据集可能偏向于男性,通常是年龄较大的男性,因为从历史上看,这些数据更易于研究和使用。
算法干预(性别)


当查看每个性别的真阳性率和假阳性率的细分时,我们可以注意到利润水*变化很小,除了利润最大化干预。在这种情况下,我们可以看到该模型对男性(73%)的阳性分类优于女性(70%)。然而,它也向将拖欠男性(33.6%)贷款的人提供了比女性(32%)略高的贷款比例。
当看利润时,这在均等赔率算法干预下明显下降。这是因为使用了更严格的阈值。女性和男性组的阈值分别为 0.56 和 0.55,而所有干预措施使用的*均阈值女性为 0.49,男性为 0.48。
算法干预(年龄组)


如果我们现在看看年龄组,我们可以看到,当我们为所有群体选择一个共同的阈值时,群体不知情,我们倾向于更好地将贷款分类给那些能够偿还 40 岁以上的人,而不是 40 岁以下的人。假阳性率保持不变。
在人口统计均等的情况下,40 岁以下的人(13%)比 40 岁以上的人(11%)收到无法偿还的贷款的风险略高。对来说,利润最大化正好相反。
另一方面,均等机会以及均等几率在组中每个类别的真阳性率和假阴性率之间的权衡方面提供了更好的*衡。
然而,由于非常严格的阈值导致较小的假阳性率,利润在均衡赔率中显著下降。女性使用的阈值为 0.83,男性为 0.81,而所有干预措施使用的*均阈值为女性 0.69,男性 0.68。
4)结论
在这篇文章中,我们修正了在监督机器学习中歧视是如何发生的。然后,我们研究了不同的算法干预,以确定受保护群体中的某些阶层是否受到了不公*的待遇。我们修正了每种干预的陷阱,并用一个具体的例子进行了评估,这个例子使用了 P2P 贷款*台 Bondora 的公共贷款书。
当使用梯度推进决策树分析基于性别和年龄的模型的结果时,我们可以立即注意到,当对每个类别(例如,女性/男性)使用不同的无限制阈值时,利润最大化。然而,各组间真阳性率的比例不同。
均等机会和均等优势在保护组中每一类的真阳性率和假阴性率之间的权衡方面提供了更好的*衡。然而,在均等赔率中,我们可以看到利润受到了重大影响。
这种简单的后处理分析具有不涉及修改复杂模型的好处。它可以用来衡量不公*性,帮助利益相关者在特定阶层受到不公*待遇时采取行动。它还鼓励确保以公*的方式收集信息,并确保用于描述目标变量的特征能够代表群体中的每个类别。
最后,这种分析并没有质疑模型的因果推理。使用的标准是简单的观察性的,只取决于预测因子、保护属性、特征和结果的联合分布。
我能看看代码吗?
我已经在 Github 上公开了我的代码。我希望听到您的反馈和改进建议🙌🏼。
参考
数据
邦多拉的贷款簿。上市时间:https://www.bondora.com/en/public-reports【2018 年 8 月 18 日上市】
主要文献
巴罗卡斯,s .,哈特,M. &纳拉亚南,a .,2018。公*和机器学习。可用时间:【http://fairmlbook.org/】【2018 . 8 . 29 访问】。
Dwork,c .等人,2012 年。通过意识实现公*。在第三届理论计算机科学创新会议论文集中。12 年的 ITCS。美国纽约州纽约市:美国计算机学会,第 214-226 页。
Hardt,m .等人,2016 年。监督学习中的机会均等。在神经信息处理系统的进展。第 3315-3323 页。
防止不*衡数据导致恶劣分类:卫星图像说明
使用卫星图像识别城市区域
不*衡的数据如何在分类中造成破坏,以及用于解决这一问题的技术的发展。

Photo by Matthew Henry on Unsplash
不*衡数据:意味着什么?
当属于数据集的一个类的实例的出现是海量而属于其他类的实例是百万分之一的时候,我们称之为不*衡数据集。
"一个好的榜样远胜于一句好的箴言."― 德怀特·l·穆迪
话虽如此,不*衡数据的典型例子是将电子邮件分类为垃圾邮件或垃圾邮件、欺诈检测等。你也可以在 Kaggle 上找到与之相关的数据集。
究竟是什么让我选择了卫星图像?
嗯,答案就藏在问题本身!让我引用一段话来解释一下:
“当你看到卫星的数量、它们在做什么以及它们代表什么时,这真的是一个试图将世界掌控在你手中的愿景。”
— 特雷弗·帕格伦
这听起来一定有些哲学意味。下面是一些实用的例子:
“卫星记录了我们看不到的光谱不同部分的数据。正是这些信息让卫星在观察植被健康等方面变得如此强大,找到可能表明石油储藏或某种可以开采的矿物储藏的不同地质类型。”
“科学家利用卫星追踪天气、绘制冰盖融化图、检测疾病、展示生态系统变化……这样的例子不胜枚举。我认为几乎每个科学领域都受益于或可能受益于卫星图像分析。”
莎拉·帕尔卡
为了更深入地挖掘这一点,维基百科在此提供帮助。
注:如果你是遥感新手,那么加拿大测绘与地球观测中心(或加拿大遥感中心)的遥感教程是你的绝佳资源。
好吧!现在让我们动手对卫星图像进行分类。
意图:
这里的意图很简单,但却很有效。我们感兴趣的是从卫星图像中找出城市区域(标记为建筑,搁置图像的其余部分(标记为非建筑)。通过卫星图像监测城市地区有利于城市规划、可持续发展以及在灾害发生时快速更新城市地区地图。此外,它在研究城市扩张对生态系统和环境的影响方面也很突出。
数据:
我使用2A 哨兵,1C 级数据从美国地质调查局(USGS)网站下载位于印度北方邦西部的城市莫拉达巴德作为我的研究区域。首先,预处理卫星图像是必须的。然而,1C 级产品是大气顶部反射率数据,在进行正射校正的同时,还进行了辐射测量和几何校正。
花絮:预处理卫星图像,为机器学习估值器预处理数据(均值去除和方差缩放等。)就像粉笔和奶酪一样,也就是说,他们不一样。
四个波段【2(蓝色)、3(绿色)、4(红色)、8(*红外)】以 10m 空间分辨率合成并裁剪到研究区域。使用研究区域的 4 波段-10m 合成和组合掩膜进行分类。

‘Copernicus Sentinel data [2018]’ . 4-Band False Color Composite (FCC) of the Study Area. Think of it as the input variable X

Built-up Mask of the Study Area. Think of it as the target variable y.
一个在不*衡数据上训练的模型差一张牌就有一副牌了!
考虑二进制分类问题,如果负类的实例数量比正类的实例数量多得多,那么模型将总是试图预测负类,以便达到高精度。但这确实会产生误导。
该场景可能如下所示:


让我们通过数据集深入了解一下这个场景。
我使用 GDAL python 包获取复合图的栅格波段作为数组,并将数据转换为 CSV 文件格式。然而,这不是强制性的,只是为了方便起见。


从条形图中可以明显看出,我们的数据集是高度不*衡的,81.86%的非构建类(负类)和仅 18.14%的构建类(正类)。
如果我们试图在这种数据上训练我们的模型,它将成为所谓的准确性悖论的牺牲品。更详细地说明这一点,我们的模型将试图揭示隐藏在准确性伪装下的类分布。
寻找灵丹妙药:
有几个博客是关于对抗不*衡班级的技术的。但是,我发现这个像一个光滑的迪斯科球一样闪闪发光。
我发现下面的技巧比其他的更有吸引力。
- 使用流行的决策树算法,随机森林就是其中之一。
 - 通过使用 SMOTE(合成少数过采样技术)生成合成样本,对少数类进行过采样。
 
这篇博客的重点将是上面列出的两种技术中的第一种。
这个问题被分解为 3 个简单的步骤:
- 使用 scikit-learn 的 train_test_split 辅助函数对数据分割应用随机森林分类器,并决定用于我们数据的性能指标。
 - 通过分层 K 倍 交叉验证更进一步。
 - 使用网格搜索交叉验证调整模型的超参数。(将在本博客的后续部分全面讨论)。
 
第一步
随机森林分类器:
对决策树和打包 (Bootstrap Aggregating)有一个概述是继续之前的先决条件。
通俗地说,随机森林是通常用于【恰当】对抗决策树的高方差(过拟合)的决策树集合。与 Bagging 不同,随机森林限制了在每次分裂时要评估的特征,即,在每次分裂时使用特征的随机子集,导致决策树高度不相关。由于这个原因,随机森林广泛用于分类和回归任务。
让我们跟上潮流,考虑随机森林分类器的默认参数,检查我们的模型如何执行。
等等,我们为什么要分割数据?
当一个模型在整个输入数据上被训练时,被告知预测同样的输入数据,它表现得像一个天才。但它实际上已经成为一个谎言。当被告知要预测看不见的数据时,它将很难产生预期的结果。这种情况称为“过拟合”。为了防止这种情况,我们将数据分为训练集和测试集,其中模型不包含测试集,而是在训练集上进行训练。然后在测试集上评估模型的性能。
将数据分为 80%的训练集和 20%的测试集:
train_test_split Documentation
训练随机森林分类器(默认参数)并在测试集上预测结果:
在我们在训练集上训练我们的模型之前,我们需要执行特征缩放以将我们的数据带入特定范围内,以便模型不会因其系数或权重的微小变化而偏向特定特征。值得注意的是,我们仅在训练集上安装了定标器,并使用它来转换训练集和测试集,以防止数据泄漏,即在训练模型时,测试集的信息不应泄漏。
Random Forest Classifier Documentation
查看森林的*均节点数和最大深度:
对森林中某棵树的外观感到好奇?

测试集上的预测:

为了预测测试集中实例的类,我们使用 predict() 函数。
给定测试集中的一个实例,它可能落入的每个类的概率是多少,由predict _ proba()函数描述。
注:我们感兴趣的是预测正类,即累积类,因此我们将只关注先证者[:,1]部分。在博客接下来的部分,我们将用它来绘制精确召回曲线。
我们的模型达到预期了吗?
有几种方法可以评估我们的模型。在哪种情况下使用哪种评估指标确实让我们挠头!
混淆矩阵:
顾名思义,它描述了模型在预测类时所经历的混乱。
但是理解混乱矩阵本身往往是混乱的!让我们用最简单的方式来理解它。
在二进制分类问题中,混淆矩阵看起来像:

Confusion Matrix Documentation
真阳性(TP): 其实——造,模特说——造,我说,“牛逼!”
假阳性(FP): 其实——非杜撰,模型说——杜撰,我说“你觉得正面的,其实是负面的!”
假阴性(FN): 实际上——是捏造的,模型说——不是捏造的,我说:“唉!这是有史以来最糟糕的预测。”
真否定(TN): 实际上——非虚构,模型说——非虚构,我说:“最后,你开始知道否定也是现实的事实!”
记住这个的诀窍是:
我们已经知道了 的实际值 ,因此我们将它们归类为和 假 。
我们评估由我们的模型预测的 的 结果,我们通常将“结果”分类为和 负 。**
性能指标:
精度:
“不要专注于错误的预测;只专注于正确的,你就会蓬勃发展。”
这就是准确性的含义。因此,对于不*衡的数据集,这是评估模型的最差方式。

占据重要位置的指标,尤其是在我们的案例中:
精度:
“精确”是指非常精确的。顾名思义,precision 描述了一个模型的【精确】。在所有的预测阳性中,有多少是我们真正感兴趣的,这就是精度。

回忆:
召回描述了模型的“完整性”。它从实际阳性值中计算出真实阳性值。

F1-得分:
f1-得分是精确度和召回率的调和*均值和。在评估一个模型时,要注意精度和召回的贡献是*衡的。

你可能会有问题。为什么只有“调和”的意思而没有“算术”或“几何”的意思?这里有的原因。
Classification Report Documentation

科恩的卡帕统计:
根据维基百科,科恩的卡帕测量了两个评分者之间的协议,他们各自将 N 个项目分类为 C 个互斥的类别。这里是对此的详细解释。它可以是介于-1 和 1 之间的值,其中-1 表示不一致,1 表示完全一致。Kappa 统计优选地用于不*衡等级分布的情况,因为它没有考虑多数等级的支配效应。
在我们的案例中,kappa 统计值约为 0.74,这意味着测试集和模型预测之间存在基本一致。这表明该模型表现非常好。
引擎盖下是怎么回事?
再次参考此链接。
在我们的例子中,混淆矩阵看起来像:

根据上面的混淆矩阵:
总实例数: 379080
实际:
组合实例总数: 68373,非组合实例总数: 310707
预测:
组合实例总数: 61625,非组合实例总数: 317455
观测精度:

在我们的例子中,观测精度= (51241 + 10384) / 379080 = 0.927
预期精度:

在我们的例子中,
预期精度(组合)=(68373 * 61625) / 379080 = 11115.03
同样的,
预期精度(非组合)=(310707 * 317455)/379080 = 260197.03
总预期精度:

在我们的例子中,总的预期精度=(11115.03+260197.03)/379080 = 0.7157
卡帕统计:

在我们的例子中,Kappa 统计量=(0.927–0.7157)/(1–0.7157)= 0.744
因此,在评估模型时,Kappa 统计明智地取消了非组合类的优势。
精确召回曲线:
精度-召回曲线是在 y 轴上具有精度并且在 x 轴上具有不同阈值的召回的图。曲线下面积(AUC)用于总结曲线。AUC 越大,我们的模型表现越好。这在我们的情况下非常有用,通常比 ROC 曲线更可取。在我关注的这个博客中,一切都解释得非常清楚。

AUC 是 0.865。这表明我们的模型在预测正类时表现良好。
对精度和召回的深入了解:

Image Source: Wikipedia
精度:

用 TP 除分子和分母,我们得到:

我们知道精度的值在范围[0,1]内。
当比率(FP / TP)趋于无穷大时,精度将为 0,为此,FP 应该趋于无穷大(实际上,应该具有非常大的值)或者 TP 应该为 0。我们显然不想这样。
当比率(FP / TP)为 0 时,精度将为 1,因此 FP 应为 0。因此,这是最好的情况,因为当假阳性的数量减少时会产生高精度值。
回忆:

用 TP 除分子和分母,我们得到:

我们知道召回值在范围[0,1]内。
当比率(FN / TP)趋于无穷大时,召回将为 0,为此 FN 应该趋于无穷大(实际上应该具有非常大的值)或者 TP 应该为 0。我们显然不想这样。
当比率(FN / TP)为 0 时,召回将为 1,此时 FN 应为 0。我们知道,FN 是最坏的预测。因此,这是最好的情况,因为当假阴性的数量减少时会产生高召回值。
总而言之,
当涉及到不*衡数据分类时,Kappa 统计和精确召回曲线价值连城。
第二步
交叉验证:
train_test_split 辅助函数不报告模型的概化能力,因为结果仅取决于一个特定的随机分割。
此外,当我们调整参数设置(超参数)直到得到好的结果时,会出现一个问题。这可能给模型一个关于测试数据的提示,并且模型可能再次过拟合。为了防止这种情况,我们需要一个“验证集”,在其上对训练好的模型进行验证,然后最终在测试数据上进行测试,以防止它被泄露。但是这将大大减少训练样本的数量。这就是交叉验证帮助我们的地方。它避免了对验证集的需要。参见 scikit-learn 文档了解这一事实。
有几种交叉验证技术,可以应用于自己的数据。
我使用了分层 K-fold 交叉验证技术,以便在每个训练和验证 fold 中*似保留相对类频率。这对于阶级不*衡的情况很重要。
分层 K 倍交叉验证是如何工作的?
在分层的 K 折叠交叉验证中,数据集被分成 K 个大小大致相等的组(折叠),每个折叠的保持原始数据集中的类别比例。在这 K 个折叠中,K-1 个折叠用于训练模型,剩余的折叠用于验证模型。

Image source: scikit-learn
分层五重交叉验证:
Stratified K-Fold Documentation
注意:StratifiedKFold()中的参数“shuffle”被设置为“True ”,因为我们的数据不是任意的,因此,在我们分割数据之前,有必要对数据进行洗牌。当 shuffle=True 时,我们必须将“random_state”参数设置为一个随机数,这样可以防止代码执行多次时结果发生变化。
卡帕统计:
低标准偏差表明模型没有过度拟合。此外,Kappa 统计值(此处为 0.746)比之前的情况(0.744)有所改善,尽管幅度很小。
精确召回曲线:

在每一个折叠中,几乎相似的 kappa 统计值和几乎相似的 AUC 值证明我们的模型具有良好的泛化能力。
步骤 3(概述)
调节超参数:
超参数是其值在学习过程开始之前设置的参数,并且不由模型直接学习。
调整超参数有助于我们努力为特定模型找到理想的参数套件,从而获得最佳分数。
GridSearchCV 和 RandomizedSearchCV 最常用于调整超参数。
在接下来的部分中,我们将尝试使用 GridSearchCV 来揭示有助于进一步提高所讨论的评估指标值的最佳超参数。
在我的 GitHub 库中找到完整的代码。
希望热心的读者喜欢它,并有他们的发言权!敬请关注即将到来的部分!
参考文献:
[1] 遥感教程——加拿大自然资源部加拿大测绘和地球观测中心(或加拿大遥感中心)。
[2]'哥白尼哨兵数据[2018]' ( 从 USGS 网站下载)
[3] Thanh Noi,p;使用 Sentinel-2 影像进行土地覆盖分类的随机森林、k-最*邻和支持向量机分类器的比较。传感器* 2018 , 18 ,18。*
[4]博客:机器学习掌握,你有没有问过为什么 F1-Score 是精度和召回率的调和均值(HM)?
利用数据科学防止“气候末日”

The “Climapocalypse” consuming the world in its hellacious fires. Image rights are with Shutterstock.
在最*的媒体报道中,气候变化的威胁据说已经变得如此之大,以至于据说它能够毁灭全人类,成为“气候末日”——数据并不支持这种说法。作为一名实践气候学家,我亲自处理和分析了大时间跨度(超过 100 年)和空间范围(全球范围)的数据集,尽管数据中有变化的信号,但一个物种甚至一个国家终结事件的可能性远非现实。气候变化肯定会给人类、我们的基础设施和我们的社会经济现状带来新的负担,但当我们与不熟悉科学的人交流其影响时,我们需要现实一些。当然,传达这一信息的唯一有意义的方式是使用我们现有的数据,即使这样也必须非常谨慎。
为了理解我这篇文章的来源,去谷歌搜索“气候启示录”,然后看看这个查询返回了多少结果。在撰写本文时,返回了超过 900 万个结果,突出显示的文章可能会因当前与天气或气候相关的“热门话题”趋势而异。如果你浏览谷歌趋势,你会发现每当有极端天气事件发生时,“气候变化”一词就会出现在搜索中。从非政治的角度来看,人们可以说这是自然的。一群龙卷风穿过一个地区,造成了数百万美元的损失——人们想知道它是如何发生的,在哪里发生的,什么时候会再次发生。与“气候启示录”相关的文章数量也在这段时间飙升,媒体机构发布了关于全球变暖的沉闷报告,其中数百万人将遭受此类事件频率增加的影响。

Google trends results for “climate change” over a 5 year time period. Image from Google.
以这种方式呈现信息不仅有歪曲事实的公然的政治动机,而且还忽略了数据及其信息以及围绕这些事件频率的大量科学研究。对于龙卷风、干旱、洪水引发降水事件和热带气旋,研究表明,在全球变暖的情况下,这些事件将变得不那么频繁,但会更加强烈。虽然许多人听到这一点,并回忆起电影后天中过度夸张的风暴,但这种事件不太可能发生,即使发生,人类也能幸免于难。这不仅仅是一个过于乐观的科学家一厢情愿的想法,这可以在数据中观察到。1900 年,美国历史上最严重的飓风在德克萨斯州的加尔维斯顿登陆。死亡人数很多,财产损失也很大,但是人类并没有因为这次事件而从地球上完全消失。相对于今天,建筑法规要宽松得多,也不安全,据报道,加尔维斯顿飓风的强度接*哈维飓风。两次都是 4 级飓风。不同的是,加尔维斯顿飓风造成 6000 至 12000 人死亡,而哈维飓风造成 68 人死亡。生命损失无疑是悲剧性的,但这两次事件之间的急剧下降证明,我们对极端天气影响的理解已经改善了基础设施、灾害管理和应急响应。然而,有数百篇文章声称哈维是气候变化导致的天气导致人类灭亡的开始,这与事实相差甚远。


Aftermath of the Galveston Hurricane on the left and Hurricane Harvey on the right. Images from Google.
从数据科学的角度来看,特征工程、人工智能和计算方法的进步为我们提供了分析气候数据的新方法。异常值分析、宁滨、k-均值、相关矩阵甚至线性判别分析等特征工程技术使分析师和研究人员能够了解数据集中的哪些变量对感兴趣的现象贡献最大。这些信息可以用来改进预测未来的推理模型。对于人工智能算法来说,使用数据集的最佳特征至关重要。提供基于简单 sigmoid 函数的分类器温度数据(来自安装在铺砌的城市环境或阴影区域的气象站),可能会导致算法输出不准确和不精确。对于诸如卷积和递归神经网络的其他方法,这个问题将仍然存在,因为这些方法只能基于提供给它的数据来提供结果。水库计算是一项正在兴起的技术,可能会在气候学界得到更广泛的应用。它结合了最好的大数据技术和机器学习,根据提供给它的信息来创建预测产品。所有这些方法都取决于提供给它的数据,而且我们的大多数数据确实支持全球变暖,但不支持气候末日,即使地球继续以目前的速度变暖。
如今从事气候学或任何自然科学都很有趣。我们从该领域的前辈那里得到的大多数指导或建议都支持使用数据和以前的文献来开发关于该领域的新见解。然而,如果你在一个使用大量来自仪器仪表的数据的领域,你也可能发展自己成为一名数据科学家——或者你应该这样。气候学的某些方面将比以往任何时候都需要更多的数据科学技能,而那些不了解这些技术的人可能会制作出糟糕的模型,从而不恰当地告知公众。理解数据以及如何操作数据是创建有用信息、推动该领域发展以及帮助社区建设更可持续、更环保的基础设施的必要组成部分。在不久的将来,也有必要揭穿夸张的事件,如“气候末日”。
参考
[1]哈罗德·布鲁克斯,“严重的雷暴和气候变化。”大气研究123(2013):129–138。
[2]川伯斯,凯文·e 等,“全球变暖和干旱的变化。”自然气候变化 4.1 (2014): 17。
[3]凯文·e·川伯斯,“随着气候变化的降水变化”气候研究 47.1–2(2011):123–138。
[4] Knutson,Thomas R .等,“热带气旋和气候变化”自然地球科学 3.3 (2010): 157。
[5] Mizuta,Ryo 等人,“60 公里全球和 20 公里区域大气模型超过 5000 年的总体未来气候模拟”美国气象学会公报98.7(2017):1383–1398。
在线流媒体服务的价格优化
服务是如何选择价格的?

最*推出了几种流媒体服务,每一种都有不同的价位和不同的选择。一些网站提供无限制的无广告访问,而其他网站则提供低成本的广告支持版本。一些人可以获得消费者更看重的高质量优质内容,而另一些人拥有高数量但质量较低的内容。
每项服务都设定了一个他们认为能最大化其目标的价格。对于网飞来说,目标可能是收入、利润和/或增长。对于苹果或亚马逊来说,内容是将客户锁定在他们的产品生态系统中的门户。对迪士尼来说,它产生了对商品、公园或其内容套件(ESPN、Hulu、Disney+等)的兴趣。).
定价策略在很大程度上取决于消费者愿意支付的价格、竞争的存在以及组织的目标。本文将关注消费者将支付的第一部分。
你会付多少钱?流媒体案例研究
假设我们为一家公司工作,该公司希望向市场推出一种新的流媒体产品。最*的一项研究确定了消费者为一系列流媒体服务付费的意愿。4 个捆绑包及其价格范围是:
- 无限电视节目&电影:10-16 美元
 - 无限电视节目&带广告的电影:8-12 美元
 - 仅限无限量电视节目:8-12 美元
 - 仅限无限量电影:8-13 美元
 
我们应该提供哪些捆绑包(如果有)?是否应该给消费者多种选择?我们应该卖广告还是不卖广告?使收益最大化的一组价格是多少?然后呢?
定价优化:途径和方法
使用这些数据,我为 1,000 名消费者创建了一个说明性数据集,这些消费者在上述价格范围之间随机均匀分布。

Example fictionalized data with non-optimal pricing
我们首先通过从捆绑包的价格中减去消费者的支付意愿,找到每个选项的消费者剩余。
把这想象成你脑海中有一个产品的最高价格(“我只会为电影票支付 15 美元”),看着价格,并基于此决定你是否会去看电影。如果价格是 13 美元,你就去。你的“消费者剩余”是 2 美元,公司获得 13 美元的收入。如果价格是 18 美元,你不去,公司从你这里获得的收益是 0 美元。
如果所有四个捆绑包的剩余都是负的,消费者就不会购买。否则,他们将购买其支付意愿与捆绑包价格之间差额最大的捆绑包。
(这假设消费者的选择是理性的,他们可以评估不同的选择——这是许多经济模型中的一个基本假设。丹尼尔·卡内曼和阿莫斯·特沃斯基可能会有不同的看法。)
为每个客户选择产品捆绑包后,公司的收入就是每个捆绑包的相关价格。所有消费者的总收入代表了我们希望最大化的收入机会。

The top consumer purchases bundle 1; the bottom consumer makes no purchase
因此,我们创建了一个定价优化问题,目标是最大化总收入。可以建立并运行优化函数,该函数搜索不同的价格点,计算目标函数(例如,收入),并选择使该函数最大化的跨服务的价格组合。
在示例数据集上解决这个问题,得出以下最优定价和购买(或不购买)每个捆绑包的消费者百分比:

Optimal Pricing and Percent of Purchases
总而言之,这 1000 名客户的总收入为 10,735 美元,其中超过一半的客户选择了无限制的电视节目和电影。在这四个选项中,只有 4%的潜在客户不会购买这些价格的产品。最常见的购买是无限制的电视节目和电影,消费者希望以* 20%的折扣购买同样的捆绑广告。
这些价格代表了在给定客户支付意愿的情况下,使客户收入最大化的数学上的最优数字。
那么现在怎么办?
我们有数字,但我们没有答案。这些价格在数学上是最优的,但不适合商业。你上一次看到 x.14 美元或 x.06 美元的订阅是什么时候?这些价格有利可图吗?我们的目标是收入、利润、增长,还是别的?
这些是将分析转化为行动的业务问题。
下一步是确定这些内容在这些价格下是否可以盈利(无论是立即还是一段时间后)。否则,就缺乏产品与市场的契合度——消费者对产品的重视程度不足以将其推向市场。然后,产品必须缩小规模或增加额外的功能,以达到供需*衡。
如果它通过了盈利能力测试,接下来要考虑的是消费者在内容之外看重什么。一些消费者会为标准高清内容支付更多费用吗(如果会,支付多少费用)?获得多个同步流(即网飞家庭计划)是否有价值?
如果有其他有价值的功能,在无限制的电视和电影下面应该有多个子计划吗?这种“好-更好-最好”的模式在任何订阅计划中都很常见。
结论
这些价格应被视为一个基准,基于特定的业务目标,可以围绕该基准进行偏离。在市场上被视为优质产品的愿望可能会导致一些人牺牲收入,通过更高的价格来支持品牌资产。超越利润获取客户的欲望可能会导致更低的价格。
确定支付意愿(并相信人们会按照他们说的去做)是另一篇文章,本身也是一项具有挑战性的工作。然而,有了这些数据,大多数分析程序(Excel、R、Python)可以提供关于定价策略的第一层洞察力,用于推动更明智的决策和数据驱动的结果。
假设支付意愿与上述真实范围没有显著差异,市场上每种值得关注的流媒体服务的定价都说明了他们的战略:
- 苹果和迪士尼正在为客户获取定价
 - 亚马逊(有免费的 Prime 视频)完全专注于留住 Prime 会员
 - HBO / Showtime 价格是一个优质产品
 - 网飞价格既可接受,但必须*衡盈利能力
 - Hulu 正试图通过其灵活的无广告和有广告支持的版本来吸引各种各样的客户
 
撇开内容获取和管理费用不谈,服务的纯价格反映了他们在高层次上的业务目标。随着时间的推移,我将有兴趣监控低价格是否仍然存在(表明保留或增加硬件销售的相邻业务目标已经实现),或者是否存在服务盈利变得至关重要的转折点,如果是,我们将在哪里看到价格。
骄傲数据特辑:2019 年成为 LGBTQ 伦敦人
伦敦刚刚庆祝了骄傲,但数据能告诉我们关于异性恋者和 LGBTQ 伦敦人的不同观点的什么?

英国被评为“同性恋友好”国家,在 ILGA-Europe 的排名中,英国在 49 个欧洲国家中排名第九,在 T2 斯巴达克斯同性恋旅游的世界指数中排名第 16。在英国,伦敦拥有最大的 LGBTQ 社区,并经常被视为比布莱顿和曼彻斯特更先进的城市。
但是 LGBTQ 社区成员的生活经历可以讲述一个不同的故事。仇恨犯罪的报道越来越多,最*的一份石墙报告发现,伦敦 25%的 LGBT 群体经历过骚扰或攻击。
我使用了 Pride 发布前几天发布的一项调查的结果来创建这个简单的图表。直观的展现了 LGBTQ 和异性恋伦敦人的不同体验和看法。为了更详细地查看结果,我将图表一分为二。
首先,坏消息是…
如果你是伦敦的 LGBTQ,你更有可能孤独、负债并面临歧视
图表显示,LGBTQ 人群感到经常孤独或总是孤独的可能性几乎是异性恋人群的两倍(15%比 8%)。这一比例在残疾人和长期失业者中更高。

三分之一的 LGBTQ 受访者有沉重的债务负担——甚至高于失业者,但略低于穆斯林和残疾人。几乎一半的 LGBTQ 人群,略少于混血人群,不认为伦敦是一个公*的城市(47%)。
最可悲的是,也是伦敦市需要走多远的一个迹象是,在过去 12 个月中,60%的人受到过歧视,远高于异性恋者(36%)的经历,也远高于特定种族的残疾人。
伦敦的 LGBTQ 远不止是负面的
伦敦的 LGBTQ 人群更有可能融入他们的社区
对于了解 LGBTQ 问题的人来说,负面的结果并不令人惊讶,但对我来说,结果也有些令人惊讶。

他们是第二个最有可能志愿参加竞选等公民活动或参加文化活动的群体(在这三种情况下,仅次于犹太人,分别为 44%、40%和 87%)。
上图中没有的一个发现是,LGBTQ 群体更有可能一天查看几次社交媒体。最后,在调查中,处于工作年龄的 LGBTQ 伦敦人与异性恋者一样有可能找到稳定的工作,尽管他们有被歧视的经历。
许多曾经抗议镇压的年度骄傲游行现在已经成为庆祝活动,但正如调查结果以及大量其他研究发现所示,伦敦 LGBTQ 人群仍然更有可能挣扎。
我如何创建我的数据,即?
我使用 datawrapper.de 创建了我的范围曲线图,创建了两个不同的图表以使信息更清晰,并通过一些额外的设计将它们固定在一起。
我下载了伦敦人的调查结果,这是伦敦市长委托的一个强大的研究项目,包括许多不同人口统计和群体的数据。
该调查的样本量超过 6000 人,其中约 3800 人声明了自己的性取向,其中 9%的人被认定为 LGBT+。没有足够高的样本来单独关注有跨性别经历的人——一群在社会中受到高度歧视的人。
喜欢你看到的吗?在 Twitter 上关注我的骄傲#dataviz:
奥利弗·卡林顿
主键和分组依据——简单的 SQL 调查
探索 SQL 主键和“Group By”语句之间交互的复杂性
今天一个熟人问了我一个有趣的 SQL 问题,但不是典型的查询意义上的;他的问题更多地围绕着对 SQL 底层框架的理解。以下是背景:
1.问题是
该练习来自此 PostgreSQL 练习页面,其模式如下:

网站询问的 SQL 问题并不重要,但他们公布的解决方案是这样的:
**SELECT**  facs.name **AS** name,
 facs.initialoutlay/((sum(
 **CASE
**  **WHEN** memid = 0 
  **THEN** slots * facs.guestcost
 **ELSE** slots * membercost
 **END**)/3) - facs.monthlymaintenance) **AS** months  
**FROM** cd.bookings bks  
**INNER JOIN** cd.facilities facs   
 **ON** bks.facid = facs.facid  
**GROUP BY** facs.facid 
**ORDER BY** name;
我的朋友尝试将线路**GROUP BY** facs.facid切换到**GROUP BY** facs.name,这中断了查询,并显示消息:
column "facs.initialoutlay" must appear in the GROUP BY clause or be used in an aggregate function
我朋友问的问题是:
为什么上面的查询不适用于交换的行,即使两列对于每一行都是唯一的?
如果你知道答案,恭喜你,你应该回答我贴在最后的问题!如果你想跳到答案,请滚动到本文的“答案”部分。不然我们就进入解决这个问题的思维过程吧!
2.方法
首先,让我们检查一下显而易见的问题——这些列真的是惟一的吗?我们的查询(name, facid, initialoutlay, monthlymaintenance)中使用的列有多种组合吗?为了检查这一点,我们在facilities 表中查看这些列的不同组合。
**SELECT DISTINCT** facs.name as name, facs.facid, facs.initialoutlay, facs.monthlymaintenance
    **FROM** cd.bookings bks
    **INNER JOIN** cd.facilities facs
        **ON** bks.facid = facs.facid
**ORDER BY** facid;Output:╔═════════════════╦═══════╦═══════════════╦════════════════════╗
║      name       ║ facid ║ initialoutlay ║ monthlymaintenance ║
╠═════════════════╬═══════╬═══════════════╬════════════════════╣
║ Tennis Court 1  ║     0 ║         10000 ║                200 ║
║ Tennis Court 2  ║     1 ║          8000 ║                200 ║
║ Badminton Court ║     2 ║          4000 ║                 50 ║
║ Table Tennis    ║     3 ║           320 ║                 10 ║
║ Massage Room 1  ║     4 ║          4000 ║               3000 ║
║ Massage Room 2  ║     5 ║          4000 ║               3000 ║
║ Squash Court    ║     6 ║          5000 ║                 80 ║
║ Snooker Table   ║     7 ║           450 ║                 15 ║
║ Pool Table      ║     8 ║           400 ║                 15 ║
╚═════════════════╩═══════╩═══════════════╩════════════════════╝
Name和facid对于每一行都是唯一的,并且 1 对 1,每一对只有一个initialoutlay和monthlymaintenance值。直观地说,按这两列中的任何一列分组在功能上应该等同于按另一列分组。那么为什么按name分组对这个查询不起作用呢?
3.主键
如果你熟悉 SQL,你可能会有直觉,这是一个主键问题。对于那些不知道的人来说,主键是唯一标识表中每一行的值,并且对于一行来说它永远不能为“NULL”。但是我们如何找到一个表的指定主键呢?
快速的谷歌搜索会给我们以下来自 PostgreSQL wiki 的代码。在网站的查询部分运行该命令会得到以下结果:
**SELECT** a.attname, format_type(a.atttypid, a.atttypmod) **AS** data_type
**FROM**   pg_index i
**JOIN**   pg_attribute a **ON** a.attrelid = i.indrelid
                     **AND** a.attnum = ANY(i.indkey)
**WHERE**  i.indrelid = 'cd.facilities'::regclass
**AND**    i.indisprimary;Output:╔═════════╦═══════════╗
║ attname ║ data_type ║
╠═════════╬═══════════╣
║ facid   ║ integer   ║
╚═════════╩═══════════╝
所以facid是facilities表的主键!现在我们已经确认了可能的原因,但是什么原因使得通过主键分组可以像我们对facs.initialoutlay和facs.monthlymaintenance所做的那样,加入没有聚合函数的列呢?
**SELECT**  facs.name **AS** name,
 facs.initialoutlay/((sum(        /* <=========== */
 **CASE
**  **WHEN** memid = 0 
  **THEN** slots * facs.guestcost
 **ELSE** slots * membercost
 **END**)/3) - facs.monthlymaintenance) **AS** months /* <=========== */
**FROM** cd.bookings bks  
**INNER JOIN** cd.facilities facs   
 **ON** bks.facid = facs.facid  
**GROUP BY** facs.facid 
**ORDER BY** name;/* Shouldn't these two columns be inside of an aggregation? */
为了回答这个问题,我们看一下 PostgreSQL 帮助文档,专门针对GROUP BY:
当
GROUP BY存在或任何集合函数存在时,SELECT列表表达式引用未分组的列是无效的,除非在集合函数内或当未分组的列在功能上依赖于分组的列时,因为否则对于未分组的列将有不止一个可能的值返回。如果分组列(或其子集)是包含未分组列的表的主键,则存在函数依赖。
正如栈溢出用户 Tony L. 所说:
按主键分组会在每个组中产生一条记录,这在逻辑上等同于根本不分组/按所有列分组,因此我们可以选择所有其他列。
本质上,这意味着按表的主键分组不会导致该表的行发生变化,因此如果我们按表的主键分组,我们可以调用该表的所有列,而不使用聚合函数。
让我们重申一下:假设我们正在查看一个表,按其主键分组与按所有内容分组是一样的,这与根本不分组是一样的 —这些方法中的每一种都将导致每行一个组。一旦你明白了这一点,你就明白了这个问题的症结所在。
因此,类似这样的查询可以工作:
**1\. Group by everything:****SELECT** *
**FROM** cd.facilities f
**GROUP BY** facid, name, membercost, guestcost, initialoutlay, monthlymaintenance
**LIMIT** 5OUTPUT:

其功能上等同于
**2\. Don't group by anything****SELECT** * 
**FROM** cd.facilities f
**LIMIT 5**and **3\. Group by primary key but don't aggregate****SELECT** * 
**FROM** cd.facilities f
**GROUP BY** facid
**LIMIT 5**
这些都输出相同的值!现在我们有了解决方案。
3.答案
第一个查询有效的原因很简单,那就是facid是主键,而name 不是。尽管它们对于每一行都是唯一的,但是表facilities 是用facid作为主键创建的,因此当在上面提到的 group by 中使用时,它得到了特殊的处理。
他们发布的一些替代解决方案如下:
**1\. Group by name then aggregate everything else****SELECT** facs.name as name,
 **AVG(**facs.initialoutlay)/((sum(case
   when memid = 0 then slots * facs.guestcost
   else slots * membercost
  end)/3) - **AVG**(facs.monthlymaintenance) as months
 **FROM** cd.bookings bks
 **INNER JOIN** cd.facilities facs
  **ON** bks.facid = facs.facid
 **GROUP BY** facs.name
**ORDER BY** name;Why this works:
Because *facs.name* is unique to each row in the *facilities* table just as *facid* was, we group by *facs.name* then add *AVG* calls around previously unaggregated *facilities* columns.**2\. Group by all facility columns used in the select statement****SELECT**  facs.name as name,
 facs.initialoutlay/((sum(case
   when memid = 0 then slots * facs.guestcost
   else slots * membercost
  end)/3) - facs.monthlymaintenance) as months
 from cd.bookings bks
 **INNER JOIN** cd.facilities facs
  **ON** bks.facid = facs.facid
 **GROUP BY** facs.name, facs.initialoutlay, facs.guestcost,     
   facs.monthlymaintenance 
**ORDER BY** name;Why this works:
This includes all the values used in the SELECT statement in the GROUP BY, which is the normal GROUP BY logic and syntax.
4.附加问题
主要问题到此结束,但是如果您有兴趣探索更多的怪癖,我在解决张贴的问题时遇到了以下问题。如果你们中的任何人知道为什么,请随时联系我或留下评论!
/* This works (manually lists all columns in the group by)*/**SELECT** *
**FROM** cd.facilities f
**GROUP BY** facid, name, membercost, guestcost, initialoutlay, monthlymaintenance
**LIMIT** 5/* This does not (selecting all columns using f.*) */**SELECT** *
**FROM** cd.facilities f
**GROUP BY** f.*
**LIMIT** 5
感谢阅读,希望这篇文章对你有所帮助!随时查看我的其他教程,并在未来发布新的教程!
使用数据集时的主键、唯一键、外键和分组
分析任何数据集的一项关键技能是知道如何有效地对数据子集进行分组。在 SQL 数据库的情况下,您经常需要不同的索引来唯一地标识各自表中的各种元素。在最*的一个涉及欧洲足球数据库的项目中,我有机会进一步研究主键、唯一键和外键之间的区别。我可以练习根据外键拆分一些分组,以便进一步分析。接下来是通过我的 pairwork 项目的视角对所有类型的数据库键和一些分组技术的教程。
首先,我将谈谈上面提到的三种关键类型的区别。当您需要对数据进行分组以进行某种分析时,记住一些关于数据库键性质的事情是很重要的。在清理数据以使其具有延展性的过程中,首先要做的事情之一是检查缺失的值,并以适当的方式处理这些值。如果您曾经使用过数据集中的主键,重要的是要认识到缺失值(通常以 Null 或 NaN 形式出现,表示不是数字)不是您必须担心的键本身。对于外键来说也是如此,因为外键只是主键,它们在一个表中被引用,而不是它们所在的表。每个表只能有一个主键,但是可以有多个外键和唯一键。唯一键允许有一个缺失值,但不能超过这个值。对于缺失值和其他类型的值来说都是如此:之所以称之为“唯一”正是因为每个值都必须是不同的。所有这些都是为了说明,当您的数据分组需要一个键时,对缺失值的清理可以忽略不计。您最多需要处理一条缺失的数据,而且这只是在您使用的键类型是惟一键的情况下。
在这个项目中,我进行分析的一个方向涉及使用外键对主队和客场队的比赛进行分组,尽管我最终只需要主队的比赛,因为我对查看主场胜利与所有其他比赛结果类型(包括客场胜利、主场失败、主场*局和客场*局)感兴趣。客场比赛的*行分组包含在下面的片段中,只是为了进一步加强这个概念,尽管它没有出现在我的分析中。
games_home = df.groupby(df.home_team_api_id) 
games_away = df.groupby(df.away_team_api_id) 
数据集的作者 Hugo Mathien 从 Kaggle 页面(链接到上面)的引用中揭示了这里使用的命名约定:
“当你查看数据库时,你会注意到球员和比赛的外键与原始数据源相同。我已经把那些外键叫做‘API _ id’。”
API 是 Application Program Interface 的首字母缩写,在这种情况下,指的是他首先引用来创建数据集的那一部分的资源。另一个例子是类似于 Dark Sky 的东西,一个允许你访问历史天气数据和预报的天气 API。在另一个基于团队的项目中,我将它与另一个不同的足球数据集结合使用,以预测比赛的结果,但让我们回到手头的例子。
一旦主队比赛被那个外键切分,我就用下面的代码得到各个队:
team_ids = list(games_home.groups.keys()) 
从那时起,我确保所提供的关于目标的数据是完整的,并且没有缺失的信息需要处理。然后,它开始计算和存储主场胜率。所有其他游戏结果都可以通过从 1:
#This returns 0 values that are missing for either columndf[['home_team_goal', 'away_team_goal']].isna().sum() #So I go on to calculate a new column for victories at homedf['HomeWin']=df.home_team_goal>df.away_team_goal#Loop through to obtain home wins by teamfor team in team_ids:         x=games_home.get_group(team)home_percentage=x.HomeWin.sum()/len(x.HomeWin) 
最终,我得出的结论并不令人震惊:在主场比赛在你获胜的机会上提供了统计上的显著优势。真正的价值在于练习使用大型 SQL 数据集、按外键分组以及使用 Python 函数内部的逻辑来获得洞察力。
当不处理键时(在更糟糕的情况下只有一个 NaN ),通常会有许多缺失值需要以最适合手头任务的方式来处理,无论是简单地删除它们,还是用*均值或可能的中值来替换它们。这取决于您正在执行的具体分析类型。如果有几个异常值,最好对空值进行中值替换。这就进入了关于插补水*的更深层次的讨论。有时,思考数据丢失的原因比匆忙替换数据更重要。尽管超出了本文的范围,但还有一种更微妙的方法可以使用,那就是多重插补。

Screenshot from a dbdiagram.io schema crawler of some of the tables in the Data Set and how they connect
我想谈的最后一点数据集知识是,如何通过分类数据进行分组,以便通过统计指标研究每个类别。让我们来看看我的项目中的一些注释代码:
#First, set up columns to see who won (same as above), and who lost or drewdf[‘AwayWin’]=df.away_team_goal>df.home_team_goal
df[‘Draw’]=df.home_team_goal==df.away_team_goal#Then, create a new categorydf['GameOutcomes']=df[['HomeWin', 'AwayWin', 'Draw']]#Group dataset by result of gamesgame_groups=df.groupby(df['GameOutcomes'])#Discover insights about the rest of the dataset, for example by looking at the mean:game_groups.mean()
这实际上是让你看到三个类别的*均值,主场胜利、主场失败(换句话说就是客场胜利)或*局,分组以显示它们如何影响比赛表中的其他变量。你可以看看你喜欢的球队在赛季中的*均胜率的变化,或者调查他们的控球率在胜场和*局中有什么不同(控球率是我上面截图中 home_player 列下面列出的一个指标)。应该注意的是,在我对主场优势的分析中,我将这段代码又向前推进了一步,将主场胜率及其补码添加到了每个球队的字典中,并转换了该字典,以使其成为自己的数据框架。这些可以在第一段链接的 GitHub 资源库中看到。
我的 LinkedIn
咨询资源:
https://stats . stack exchange . com/questions/143700/*均替代和中位替代哪个更好
https://coding sight . com/the-difference-before-primary-key-and-unique-key/
https://www.youtube.com/watch?v=u9nftlpCdXQ
还要特别感谢我的项目伙伴,乔。
素数和哥德巴赫猜想可视化。
从向日葵叶子上的图案到太阳光线的反射角度,数学无处不在。它仅仅是自然的语言。
不管你同意与否,质数是迄今为止最著名的数学系统中最独特的数字集合。这组数字帮助数学家引入了奇迹般的理论和悖论,显示了自然出现的数字之间的模式。
如果你是谢尔顿·库珀的粉丝,那么你肯定知道最酷的质数 73。正如我们在《生活大爆炸》第 73 集《外星寄生虫假说》中从他那里学到的,谢尔登解释道。“73 是第 21 个质数。它的镜像 37 是第 12 个,它的镜像 21 是 7 和 3 相乘的结果……在二进制中,73 是一个回文,1001001,反过来是 1001001。酷!不是吗?
德国数学家 g . f . b . Riemann(1826–1866)观察到素数的分布与 Riemann Zeta 函数的行为密切相关。作为千年问题之一,它在各个领域都有应用,可以揭开许多隐藏的秘密。
数学家们观察到质数能够衍生出数字系统中的模式,由此哥德巴赫的猜想确实能够吸引任何人去研究数学。
偶数的哥德巴赫猜想:****哥德巴赫猜想断言每一个大于 4 的偶数都是两个素数之和。猜想已经测试到 40000000000000。虽然每一个偶数都有一种或多种可能的写法,可以写成两个素数之和。
2+2=4
3+3=6
3+5=8
3+7=10
5+5=10
....
13+37=50
19+31=50
43+7=50
47+3=50
......
虽然看起来很简单,但它的证明一直困扰着一些非常聪明的人,至今已有 250 年了,仍然是个问题。迄今为止,还没有人发现一个不能用两个质数形成的更大的偶数。
这种模式可以用类似箭头的结构来表示。

The ends represent the prime numbers meeting at their respective sums.
有趣的是,随着偶数的增加,它通过质数组合形成的方式也在增加。偶数和用两个素数构成的方式数之间的关系被称为哥德巴赫彗星。

Visualization of Goldbach’s comet using matplotlib-python
从散点图中,我们可以注意到素数组合的数量随着数量的增加而增加,但没有证据表明这种模式是对还是错。许多努力证明这一点的大脑会从一开始就一无所知。你只是不知道从哪里开始。但是希望总是存在的,因为既然我们能够证明奇数的哥德巴赫猜想,我们也能够证明这个猜想。
YESS!!Harald Helfgott 在 2013 年证明了哥德巴赫弱猜想或奇数猜想。
奇数哥德巴赫猜想:断言每一个大于 7 的奇数都可以表示为三个素数之和。
1+3+5=9
1+3+7=11
1+5+7=13
5+5+7=17
5+7+7=19
....
费马的房间是最受欢迎的西班牙惊悚电影之一,讲述了四个数学家的故事,核心情节是证明哥德巴赫猜想。在我看来,如果你是一个数学狂人或益智爱好者,这是一部必看的电影。
听起来很有趣?然后拿起笔和纸,开始尝试..因为价值百万美元的解决方案值得一试。
专注的数据收集和发布的重要性初级读本
概述
- 当涉及到数据收集、隐私和同意时,标准是不同的。
 - 然而,大多数人对相关政策的制定没有发言权。
 - 作为数据科学家,我们需要认识到我们如何处理数据,在哪里发布数据,它有多安全,以及它会如何伤害人们。
 
简介:数字足迹不可避免
也许说“数据”,尤其是各种各样的数据,不仅是专家之间,而且是他们的非专家朋友,互联网上的随机人群,实际上是任何仍然连接到网络的人之间,都是一个大讨论的话题,这是一种保守的说法。
在这一点上,感觉成为收集你的数据的网络的一部分不是一个选择。也许很长时间以来这都不是一个选择,但现在缺乏选择是难以否认的——你能想象在你必须接工作电话、与人联系时关掉手机,或者在你可以找到信息、建立关系网和与他人联系的地方永远离开脸书/Instagram/LinkedIn/Google 吗?
一方面,这看起来很可怕。例如,网站可以跟踪你向下滚动一篇文章有多远,你点击了多少次链接。人们可以调用 API 来获取你的推文,你的个人资料,你什么时候点击了什么。难怪现在科幻书籍、反乌托邦小说之类的好像无时无刻不在我们身边。
另一方面,可用的数据量确实惊人,令人兴奋。可能性似乎是无穷无尽的,尤其是对社会研究感兴趣的人。现在有了前所未有的测量社会行为的新工具和方法。像脸书、推特和谷歌这样的网站是如此令人兴奋,因为我们可以想象如何绘制网络和新的互动方式。然而,对于研究人员来说,这给现有的研究监督系统增加了一个新的非常重要的层面来维护研究对象的隐私。
数据收集:机构审查委员会
在任何研究机构,如果你正在进行人体研究,你必须首先起草一份关于你的研究、方法、理由等的提案。根据机构的 IRB。那么你的研究必须被批准。根据联邦法规 的 电子代码,要获得 IRB 批准,必须满足一整套标准。以下是一些标准:
(1)受试者的风险降至最低:
(I)使用与合理的研究设计一致的程序,并且不会不必要地使受试者面临风险,以及
(ii)在适当的时候,使用已经在受试者身上进行的用于诊断或治疗目的的程序。
很明显,有解释的余地,并且由 IRB 来决定一项研究是否符合“最小化”风险的第一个条件。IRB 还考虑了以下事实,即并非所有人都有相同的能力来决定是否参与研究,也并非所有人都有必要做出知情决定或给予知情同意:
(3)受试者的选择是公*的。在进行这种评估时,IRB 应考虑研究的目的和开展研究的环境。IRB 应特别认识到研究中的特殊问题,这些问题涉及易受胁迫或不当影响的一类受试者,如儿童、囚犯、决策能力受损的个人或经济或教育上处于不利地位的人。
知情同意总是需要的。任何研究机构都是如此,哪怕你是在进行本科研究性学习。以下两条规定是数据科学家最需要了解的:
(6)在适当的情况下,研究计划对监测收集的数据做出充分的规定,以确保受试者的安全。
(7)在适当的情况下,有足够的规定来保护受试者的隐私和维护数据的机密性。
IRB 过程是缓慢的,有时某些社会行为可能会启动,并且在进行研究之前必须获得批准的事实会减慢你的速度,并可能使你失去宝贵的时间和数据。但至少,这是一个监管系统,它被规范,被记录,并且它的主要焦点是在研究主题上。
然而,科技行业没有像研究机构那样的机构审查委员会。
许多科技公司能够进行大量的社会研究,而没有研究机构法律要求的那种监督或自由裁量权。这个问题已经被很好地记录下来,并且已经争论了好几年。(下面我链接了几篇可能会引起你兴趣的文章。)在研究、同意、隐私和安全方面,标准的差异不仅限于行业和学术界的分歧。对于如何安全地处理数据,国际上也没有达成共识。不同标准的问题最终会伤害到不知情的人,他们的数据在不知情的情况下被搜集、挖掘和分析。
例如:2014 年脸书幸福研究
2019 年,众所周知,脸书拥有我们的数据,可能比我们自己更了解我们。它当然知道我们在网上和谁互动,我们喜欢什么,不喜欢什么,我们用了多长时间,我们买了什么,我们不买什么,我们看了什么,等等。然而,在 2014 年,就在 5 年前,对于普通用户来说,脸书利用这些数据的程度变得更加清晰。一项研究发表了,研究“参与者”的数量多得离谱,数量之大,研究人员只能梦想:600,000+“参与者”。但是当然,这项研究没有经过 IRB 的审查,知情同意书也没有明确给出,结果也颇具争议。
在对使用脸书的人进行的一项实验中,我们通过减少新闻内容中的情感内容来测试情感传染是否发生在个人之间的面对面互动之外。当积极表达减少时,人们产生的积极帖子更少,消极帖子更多;当消极表情减少时,出现了相反的模式。
以上节选来自文章摘要,标题为“通过社交网络进行大规模情绪传染的实验证据”(Kramer,Guillory,and Hancock 2014)。虽然作者承认他们的研究结果是有争议的,但很难相信这项研究能够遵守上面列出的 IRB 法规。尤其是在这个心理健康、抑郁、焦虑和自杀问题被不断讨论的时代,当研究结果出来时,人们并不那么高兴也就不足为奇了。
数据存储与出版:展示你的作品?
在当今时代,为了保持相关性并成为技术对话的一部分,展示你的作品是至关重要的。人们想看你的探索性数据分析(EDA)。人们想要访问你的 csv 文件,你的代码。给我看看你的 GitHub。给我看看你的笔记本。给我看看你的原始数据。给我看看你的最终数据。这对于以透明和可复制的方式进行研究和数据科学来说是非常重要的,因为这是对知识的追求。但是你研究过的人呢?他们的个人身份信息(PII) 呢?
PII 指的是可以用来识别某人的信息。明显的例子是社会安全号、出生日期+全名等。但是还有一些不太明显的信息:IP 地址、年龄、性别和邮政编码。有许多不太明显的数据点的组合,当它们放在一起时,倾向于组成一组识别信息。
对于任何处理关于人的数据的人,特别是那些刚刚开始了解如何从你的数据中进行推断的人,我们必须考虑如何存储我们的数据,如何实际加密数据,以及我们应该和不应该以什么形式将我们的数据发布到网上。您拥有的信息是否完全匿名?那是什么意思?你收集数据的人有可能因为你的项目而受到伤害吗?
结论:我们仍在努力
得知还没有找到完美的解决办法,也许令人不满意。在过去的几年里,人们一直在呼吁制定更多的法律来规范数据隐私,一些立法者正在试图做出回应。就在 2018 年,欧盟通过了《通用数据保护条例》,试图将一些控制权归还给生成数据的个人。相对而言,考虑到这些技术是多么的新,以及它们发展的速度有多快,尤其是现在,当务之急是该领域的人们在选择保护他们的模型之前保持警惕并坚定地选择保护他们。
进一步阅读
这篇文章是与生物特征加密和智能数据代理发明者 George Tomko 博士合作完成的。
towardsdatascience.com](/why-we-need-to-rethink-central-authority-in-the-age-of-ai-4c6c35efb308) [## 如何成功穿越数据隐私监管的“灰色地带”
令牌化、数据湖、监管、加密和匿名化都是 2020 年的热门话题
towardsdatascience.com](/how-to-successfully-navigate-the-grey-areas-of-data-privacy-regulation-8bcc294fadf5) [## 《加密法案》保护加密免受美国各州的窥探
不仅仅是司法部和联邦调查局想要破坏你的私人通信权…
www.eff.org](https://www.eff.org/deeplinks/2018/06/encrypt-act-protects-encryption-us-state-prying) [## 数据安全法|私营部门
随着*年来公民个人身份信息的安全风险增加,一些州立法机构…
www.ncsl.org](http://www.ncsl.org/research/telecommunications-and-information-technology/data-security-laws.aspx) [## 加密法律和政策世界地图|全球合作伙伴数字
提供者协助当局的义务没有已知的立法或政策。个人有义务帮助…
www.gp-digital.org](https://www.gp-digital.org/world-map-of-encryption/) [## 如果科技公司要在你身上做实验,他们需要更好的道德监督
脸书想知道这对你是否有害。一些社会科学研究表明,使用社交工具的人…
slate.com](https://slate.com/technology/2015/05/facebook-emotion-contagion-study-tech-companies-need-irb-review.html)
统计和机器学习视角下的主成分分析(上)

https://www.jpl.nasa.gov/images/technology/20150522/Iceberg20150522.jpg
复杂数据分析中的一个常见问题来自于大量的变量,这需要大量的内存和计算能力。这就是主成分分析(PCA)的用武之地。通过 特征提取 降低特征空间的维数是一种技术。例如,如果我们有 10 个变量,在特征提取中,我们通过组合旧的 10 个变量来创建新的自变量。通过创建新的变量,看起来好像引入了更多的维度,但我们只从新创建的变量中按重要性顺序选择了几个变量。那么这些被选择的变量的数量就比我们开始时的少,这就是我们如何降低维数的。
看待 PCA 有多种方式。在本文中,我将从统计学的角度讨论 PCA,本文的第二部分是机器学习的角度(最小误差公式和最大化特征值),链接如下:https://towardsdatascience . com/principal-component-analysis-the-machine-learning-perspective-part-2-a 2630 fa 3b 89e。为了阅读第一部分和第二部分,熟悉以下一些内容会让本文更容易理解:线性代数(矩阵、特征向量/特征值、对角化、正交性)和统计学/机器学习(标准化、方差、协方差、独立性、线性回归)。
PCA 统计观点
为了理解 PCA,我们可以从这本线性代数教科书中的一个例子开始,其中作者从他的 14 名学生的荣誉微积分班上收集了一组测试数据。下面的四个变量是 ACT(全国测试的分数,范围为 1 到 36)、FinalExam(范围为 0 到 200 的期末考试分数)、QuizAvg(八个测验分数的*均值,每个分数的范围为 0 到 100)和 TestAvg(三个测试分数的*均值,每个分数的范围为 0 到 100)。

我们有所有这些考试分数,但有些分数是多余的,很难想象。但是,不能随便掉一些考试分数。这就是降维发挥作用的地方,在不损失太多信息的情况下,减少变量的数量。
这里的另一个问题是,很难解释这些考试分数,因为它们是基于不同的范围和尺度。变量,如上面的测试分数,在不同的尺度上或在一个共同的尺度上测量,有很大不同的范围,通常是标准化的,以引用相同的标准。
标准化
Z 评分是一种用于标准化/规范化数据的常用方法:从每个值中减去数据的*均值,然后除以标准偏差。
的意思是 被定义为

数据集 x 的方差为

计算数据方差的*均值和*方根后,即标准差:

现在,通过减去*均值并除以标准差(即方差的*方根),最终可以对数据进行 z 评分/归一化。

协方差/相关性
为了了解所有这些变量之间的关系,使用了协方差。协方差告诉你两个变量之间的线性关系:两个变量是如何密切相关的。
向量 x 和 y 的 样本协方差 定义为

然而,使用协方差的一个问题是它受测量单位的影响。例如,如果向量 x 以千克为单位,y 以英尺为单位,那么协方差现在是千克-英尺。为了使单位消失,使用了 样本相关性 (向量),它被定义为协方差除以标准偏差:

定义样本相关性(矩阵)的另一种方法是使用 z 得分数据,该数据已经除以标准差。

这是数据集的相关矩阵:

我们可以看到第三次考试成绩(小考*均分)和第一次考试成绩(ACT)的相关性最高,为 0.82780343。第二高的相关值显示在第一和第四:ACT 和 Test *均值之间。因此,我们证实了我们之前亲眼所见,这些测试分数是相互关联的,其中一些是多余的。
现在我们将开始我们的主成分分析。为了提出新的维度,我们将经历两个过程:
- 数据集的转换:定义新的变量替换现有的变量
 - 数据集的选择:衡量新变量代表原变量的程度。
 
以下是每一步的细节。
变换步骤
我们将从上面计算的相关矩阵开始。重要的是要看到,这个矩阵必须是对称的,因为它是由 Z 和 Z 的转置相乘得到的。也就是说,这里将使用对称矩阵的一个定理。一个 n×n 矩阵 A 是对称的当且仅当存在一个由 A 的特征向量组成的正交基,在这种情况下,存在一个正交矩阵 P 和一个对角矩阵 D 使得 A = PDP_transpose 。

我们可以得到列为 A 的特征向量或特征值的相关矩阵和对角矩阵 D 的正交矩阵 P。

从这里开始,我们将通过执行与 P: ZP 的矩阵乘法来转换我们的原始 Z 得分数据

这组新数据的形状与原始数据集的形状没有任何不同。现在,我们已经成功地将原始数据转换为新数据,在下一步中,我们将降低原始数据集的维度。
选择步骤
现在,我们将从 ZP 中选择向量,以实际降低维度,但是我们如何知道哪些要保留,哪些要丢弃呢?将基于特征值做出决定。我们将以一种可读的格式重写 ZP,其中 ZP 的每个列向量表示为 y_i

y1 为第一主成分,定义为新的向量,其系数为最大特征值为 2.978867 的相关矩阵的特征向量。那么第二主成分就是 y2,因为它的系数对应的是第二大特征值 0.762946。
在这种情况下,最后两个特征值无关紧要,因为与前两个相比,它们不够大。因此,我们将选择特征向量为系数的 ZP 向量对应前两个最大的特征值,即 y1 和 y2 。这两个向量是我们的新向量,我们将把它们作为降维的结果。
现在问题来了,为什么我们要做 ZP 来选择一组新的向量?为什么 ZP 如此重要?这是因为 ZP 的协方差是对角矩阵。
这是为什么的证据(这是前半段最重要的部分):

为什么我们要把 Z 乘以 P?
这解释了我们将归一化数据 Z 乘以 p 的原因。ZP 的协方差是对角矩阵的事实表明,除了与自身相关的变量之外,变量之间没有线性关系。换句话说,我们创建的新变量之间没有关系,新变量彼此独立。因此,我们已经成功地提出了一组新的数据集(转换后的数据集),它们之间没有任何相关性,我们可以根据方差选择变量,方差由特征值表示。
现在让我们更多地讨论特征值/方差。这里重要的是原始数据集的总方差与转换后数据集的总方差相同。也就是说,对角矩阵 D 的元素之和的元素之和就是 Z 得分的方差之和。当 ZP 的协方差矩阵为 D 时,ZP 的每个向量代表变换数据的方差,并且通过选择对应于最高特征值的向量,方差被最大化。因此,通过选择对应于最高特征值的向量,我们选择了新的变量,其具有被原始数据集的总方差分割的变换数据集的方差的高分数。
从统计角度看主成分分析的结论
当用较少的新变量替换原始变量时,试图捕捉尽可能多的方差是统计学中的常见做法",以说明原始数据集中方差的高百分比。“这在直觉上是有意义的,因为当我们考虑降低数据集的维度时,我们希望丢弃相似的特征,但只保留最大不相似的特征。在这种情况下,我们可以看到,一些测试分数彼此高度相关,因此一些测试分数是冗余的。但是我们想从数学上理解为什么保持尽可能多的方差是有益的。这个问题的答案在机器学习视角的 PCA 中更容易看到,这将是本文的第 2 部分。
参考文献: 1。https://www . stat . CMU . edu/~ cshalizi/uADA/12/lections/ch18 . pdf2。https://towards data science . com/a-一站式主成分分析-5582fb7e0a9c ,3 .https://www . Amazon . com/Elementary-Algebra-Classics-Advanced-Mathematics/DP/013468947 x4 .http://www.cs.columbia.edu/~verma/teaching.html
主成分分析降维
通过学习算法背后的数学知识并使用 Python 一步一步地执行它,了解如何执行 PCA!
在现代技术时代,越来越多的数据被产生和收集。然而,在机器学习中,太多的数据可能是一件坏事。在某一点上,更多的特征或维度会降低模型的准确性,因为有更多的数据需要归纳——这被称为维度诅咒。
降维是降低模型复杂性和避免过度拟合的方法。降维主要有两类:特征选择和特征提取。通过特征选择,我们选择原始特征的子集,而在特征提取中,我们从特征集中提取信息来构建新的特征子空间。
在本教程中,我们将探讨特征提取。在实践中,特征提取不仅用于提高存储空间或学习算法的计算效率,还可以通过减少维数灾难来提高预测性能,尤其是在我们使用非正则化模型的情况下。
具体来说,我们将讨论用于将数据集压缩到低维特征子空间的主成分分析 ( PCA )算法,目标是保持大部分相关信息。我们将探索:
- PCA 背后的概念和数学
 - 如何使用 Python 一步一步从头开始执行 PCA
 - 如何使用 Python 库执行 PCA
scikit-learn 
我们开始吧!
本教程改编自 Next Tech 的 Python 机器学习 系列的 Part 2 ,带你从 0 到 100 用 Python 进行机器学习和深度学习算法。它包括一个浏览器内沙盒环境,预装了所有必要的软件和库,以及使用公共数据集的项目。这里 可以免费上手 !
主成分分析导论
主成分分析 ( PCA )是一种无监督的线性变换技术,广泛应用于不同领域,最突出的是用于特征提取和降维。PCA 的其他流行应用包括股票市场交易中的探索性数据分析和信号去噪,以及生物信息学领域中的基因组数据和基因表达水*的分析。
PCA 帮助我们基于特征之间的相关性来识别数据中的模式。简而言之,PCA 旨在找到高维数据中最大方差的方向,并将其投影到一个新的子空间,该子空间的维数等于或小于原始子空间的维数。
给定新特征轴彼此正交的约束,新子空间的正交轴(主分量)可以被解释为最大方差的方向,如下图所示:

在上图中, x1 和 x2 为原始特征轴, PC1 和 PC2 为主要部件。
如果我们使用 PCA 进行降维,我们将构建一个dxk–维度变换矩阵 W ,它允许我们将样本向量 x 映射到一个新的k–维度特征子空间上,该子空间的维度少于原始的d–维度特征空间:

作为将原始 d 维数据转换到这个新的 k 维子空间(通常为 k ≪ d )的结果,第一个主分量将具有最大可能的方差,并且所有后续主分量将具有最大方差,假设这些分量与其他主分量不相关(正交)——即使输入特征相关,得到的主分量也将相互正交(不相关)。
请注意,PCA 方向对数据缩放高度敏感,如果在不同的缩放比例上测量特征,我们需要在 PCA 之前标准化特征,并且我们希望对所有特征赋予同等的重要性。
在更详细地查看用于降维的 PCA 算法之前,让我们用几个简单的步骤来总结该方法:
- 标准化 d 维数据集。
 - 构建协方差矩阵。
 - 将协方差矩阵分解为其特征向量和特征值。
 - 按降序对特征值进行排序,对对应的特征向量进行排序。
 - 选择 k 个最大特征值对应的 k 个特征向量,其中 k 为新特征子空间的维数( k ≤ d )。
 - 从“顶” k 特征向量构造一个投影矩阵 W 。
 - 利用投影矩阵 W 对 d 维输入数据集 X 进行变换,得到新的 k 维特征子空间。
 
让我们使用 Python 作为学习练习,一步一步地执行 PCA。然后,我们将看到如何使用scikit-learn更方便地执行 PCA。
逐步提取主成分
在我们的例子中,我们将使用来自 UCI 机器学习知识库的 Wine 数据集。该数据集由 178 个葡萄酒样本组成,其中 13 个特征描述了它们不同的化学性质。你可以在这里找到更多。
在本节中,我们将处理 PCA 的前四个步骤;稍后我们将复习最后三个。您可以通过使用 Next Tech 沙箱来遵循本教程中的代码,沙箱已经预安装了所有必要的库,或者如果您愿意,您可以在自己的本地环境中运行代码片段。
一旦您的沙盒加载完毕,我们将从直接从存储库加载 Wine 数据集开始:

接下来,我们将把葡萄酒的数据处理成单独的训练和测试集——使用 70:30 的分割——并将其标准化为单位方差:
完成强制预处理后,我们进入第二步:构造协方差矩阵。对称的 d x d 维协方差矩阵存储不同特征之间的成对协方差,其中 d 是数据集中的维数。例如,在群体水*上的两个特征 x_j 和 x_k 之间的协方差可以通过以下等式来计算:

这里, μ_j 和 μ_k 分别是特征 j 和 k 的样本均值。
请注意,如果我们标准化数据集,样本均值为零。两个要素之间的正协方差表示要素一起增加或减少,而负协方差表示要素以相反的方向变化。例如,三个特征的协方差矩阵可以写成如下形式(注意,σ代表希腊大写字母σ,不要与总和符号混淆):

协方差矩阵的特征向量代表主要分量(最大方差的方向),而相应的特征值将定义它们的大小。在 Wine 数据集的情况下,我们将从 13×13 维协方差矩阵中获得 13 个特征向量和特征值。
现在,对于我们的第三步,让我们获得协方差矩阵的特征对。一个特征向量 v 满足以下条件:

这里, λ 是标量:特征值。由于手动计算特征向量和特征值是一项有些繁琐和复杂的任务,我们将使用来自NumPy的linalg.eig函数来获得和协方差矩阵的特征对:
使用numpy.cov函数,我们计算了标准化训练数据集的协方差矩阵。使用linalg.eig函数,我们执行了特征分解,产生了一个向量(eigen_vals),该向量由 13 个特征值和相应的特征向量组成,以列的形式存储在 13×13 维矩阵中(eigen_vecs)。
总差异和解释差异
由于我们希望通过将数据集压缩到一个新的特征子空间来降低数据集的维数,因此我们只选择包含大部分信息(方差)的特征向量(主成分)的子集。特征值定义了特征向量的大小,所以我们要把特征值按大小递减排序;我们感兴趣的是基于它们相应特征值的值的前 k 个特征向量。
但是在我们收集那些最有信息的特征向量之前,让我们先画出特征值的方差解释比率。特征值 λ_j 的方差解释比就是特征值 λ_j 和特征值总和的分数:

使用NumPy cumsum函数,我们可以计算解释方差的累积和,然后通过matplotlib的step函数绘制:

得到的图表明,仅第一主成分就占了方差的大约 40%。此外,我们可以看到,前两个主成分合起来解释了数据集中* 60%的方差。
特征转换
在我们成功地将协方差矩阵分解成特征对之后,现在让我们继续进行 PCA 的最后三个步骤,将 Wine 数据集变换到新的主成分轴上。
我们将按照特征值的降序对特征对进行排序,从选定的特征向量中构造一个投影矩阵,并使用投影矩阵将数据转换到低维子空间上。
我们首先按照特征值的降序对特征对进行排序:
接下来,我们收集对应于两个最大特征值的两个特征向量,以捕获该数据集中约 60%的方差。请注意,出于说明的目的,我们只选择了两个特征向量,因为我们将在本小节稍后通过二维散点图绘制数据。在实践中,主成分的数量必须通过计算效率和分类器性能之间的权衡来确定:
*[Out:]
Matrix W:
 [[-0.13724218  0.50303478]
 [ 0.24724326  0.16487119]
 [-0.02545159  0.24456476]
 [ 0.20694508 -0.11352904]
 [-0.15436582  0.28974518]
 [-0.39376952  0.05080104]
 [-0.41735106 -0.02287338]
 [ 0.30572896  0.09048885]
 [-0.30668347  0.00835233]
 [ 0.07554066  0.54977581]
 [-0.32613263 -0.20716433]
 [-0.36861022 -0.24902536]
 [-0.29669651  0.38022942]]*
通过执行前面的代码,我们已经从顶部的两个特征向量创建了一个 13 x 2 维的投影矩阵 W 。
使用投影矩阵,我们现在可以将样本(表示为 1×13 维行向量)变换到 PCA 子空间(主分量 1 和 2)上,获得【x’,现在是由两个新特征组成的二维样本向量:**

类似地,我们可以通过计算矩阵点积将整个 124 x 13 维训练数据集转换到两个主分量上:

最后,让我们在一个二维散点图中可视化转换后的 Wine 训练集,现在存储为一个 124 x 2 维矩阵:

正如我们在结果图中看到的,数据更多地分布在第一主成分的x-轴上,而不是第二主成分(y-轴)上,这与我们之前创建的方差比图一致。然而,我们可以直观地看到,线性分类器可能能够很好地分离这些类别。
尽管在前面的散点图中,我们对类别标签信息进行了编码,但我们必须记住,PCA 是一种不使用任何类别标签信息的无监督技术。
scikit 中的 PCA 学习
尽管前一小节中的详细方法帮助我们了解了 PCA 的内部工作方式,但我们现在将讨论如何使用在scikit-learn中实现的PCA类。PCA类是scikit-learn的另一个 transformer 类,在使用相同的模型参数转换训练数据和测试数据集之前,我们首先使用训练数据拟合模型。
让我们使用葡萄酒训练数据集上的PCA类,通过逻辑回归对转换后的样本进行分类:
现在,使用一个定制的plot_decision_regions函数,我们将可视化决策区域:

通过执行前面的代码,我们现在应该看到训练数据的决策区域减少到两个主分量轴。
为了完整起见,让我们在转换后的测试数据集上绘制逻辑回归的决策区域,看看它是否能很好地分离类:

在我们通过执行前面的代码为测试集绘制了决策区域之后,我们可以看到,逻辑回归在这个小的二维特征子空间上表现得相当好,并且仅错误分类了测试数据集中非常少的样本。
如果我们对不同主成分的解释的方差比率感兴趣,我们可以简单地初始化PCA类,将n_components参数设置为None,这样所有主成分都被保留,然后可以通过explained_variance_ratio_属性访问解释的方差比率:
请注意,我们在初始化PCA类时设置了n_components=None,这样它将按照排序的顺序返回所有主成分,而不是执行维度缩减。
我希望你喜欢这篇关于主成分分析降维的教程!我们讨论了 PCA 算法背后的数学,如何用 Python 一步一步地执行 PCA,以及如何使用scikit-learn实现 PCA。其他降维技术有线性判别分析** (LDA)和核 PCA (用于非线性可分数据)。**
Next Tech 的 Python 机器学习(第二部分) 课程涵盖了这些其他技术和更多提高模型性能的主题,如数据预处理、模型评估、超参数调整和集成学习技术。
这里 可以免费上手 !
主成分分析:通过图像可视化的深入理解
用 Python 从头开始实现 PCA

Photo by Ben White on Unsplash
主成分分析导论
主成分分析(PCA)是在机器学习应用中使用的一种流行的降维技术。PCA 通过对大量变量进行某种变换,将它们的信息压缩成较少的变量。转换的应用方式是将线性相关变量转换为不相关变量。相关性告诉我们,信息存在冗余,如果这种冗余可以减少,那么信息就可以被压缩。例如,如果变量集中有两个高度相关的变量,那么,我们保留这两个变量不会获得任何额外的信息,因为一个变量可以*似表示为另一个变量的线性组合。在这种情况下,PCA 通过原始轴的*移和旋转以及将数据投影到新轴上,将第二变量的方差转移到第一变量上。使用特征值和特征向量来确定投影方向。因此,前几个变换特征(称为主成分)富含信息,而最后几个特征主要包含噪声,其中的信息可以忽略不计。这种可转移性允许我们保留最初的几个主成分,从而以最小的信息损失显著减少变量的数量。
本文更侧重于在图像数据上实际的一步一步的 PCA 实现,而不是理论上的解释,因为这方面已经有大量的资料。选择了图像数据而不是表格数据,以便读者可以通过图像可视化更好地理解 PCA 的工作。从技术上讲,图像是像素矩阵,其亮度代表该像素内表面特征的反射率。对于 8 位整数图像,反射系数值的范围是从 0 到 255。因此,反射率为零的像素显示为黑色,值为 255 的像素显示为纯白色,值介于两者之间的像素显示为灰色调。本教程使用了在印度沿海地区拍摄的 Landsat TM 卫星图像。图像被调整到较小的比例,以减少 CPU 的计算负荷。这组图像由 7 个波段的图像组成,涵盖电磁波谱的蓝、绿、红、*红外(NIR)和中红外(MIR)范围。对于有兴趣自己尝试这些步骤的读者,请参考这个包含输入数据集和这里使用的 Ipython 代码的 Github 存储库。让我们开始吧,不要再废话了。
1.加载模块和图像数据
第一步是导入所需的库并加载数据。为了便于访问和处理,波段图像以 850 x 1100 x 7(高 x 宽 x 波段数)的 3d numpy 阵列形式堆叠。下面显示的彩色图像是红色、绿色和蓝色(RGB)波段图像的合成,再现了我们看到的相同视图。瞥一眼现场。

图像场景包含各种表面要素,例如水、建筑区、森林和农田。
2.数据探索
让我们看看不同特征的单个波段图像的反射率,并尝试了解波段图像中的特征。

如果我们观察图像,所有波段都捕捉到了一个或多个表面特征,并且每个特征在多个波段中也捕捉得很好。例如,在波段 2(绿色)和波段 4(*红外)图像中,农田很容易与其他地表特征区分开来,但在其他图像中则不然。因此,波段之间存在信息冗余,这意味着波段之间的反射率有些相关。这给了我们在它们身上测试 PCA 的好机会。
3.数据标准化
在应用 PCA 之前,我们必须通过标准化将我们的数据转换成一种通用格式。这样做的目的是确保变量在内部彼此一致,而不管它们是什么类型。例如,如果数据集有两个变量,温度以摄氏度为单位,降雨量以厘米为单位。由于变量范围和单位不同,不建议使用不同的变量,否则,数量级不同的变量可能会导致模型偏向某些变量。标准化是通过减去*均值使变量居中,然后通过除以标准偏差使它们达到一个共同的范围。由于我们正在处理的变量(波段图像)是相似的,并且具有相同的范围,标准化是不必要的,但仍然是一个很好的应用实践。
我们的变量是图像二维数组,需要转换成一维向量,以方便矩阵计算。让我们创建一个大小为 935000 X 7(图像像素数 X 波段数)的可变矩阵,并将这些一维向量存储在其中。
4.PCA 变换
让我们进一步了解 PCA 内部发生的轴变换。下面的散点图显示了绿色和红色波段数据之间的相关性。然后使用特征向量确定主分量轴(X2,Y2 ),使得沿 X2 方向的方差最大,而与其正交的方向给出具有最小方差的 Y2。原始轴(X1,Y1)现在沿着主分量轴(X2,Y2)旋转,并且投影在这些新轴上的数据是主分量。重要的是要注意,原始数据中存在的相关性在变换到(X2,Y2)空间后被消除,而方差部分地从一个变量转移到另一个变量。

5.特征值和向量计算
下一步是计算协方差矩阵的特征向量和相应的特征值
特征值:
【5.508 0.796 0.249 0.167 0.088 0.064 0.128】
在这一步中,数据压缩和降维开始起作用。如果你看特征值,你会注意到值是非常不同的。这些值给出了特征向量或方向的重要性顺序,即沿着具有最大特征值的特征向量的轴是最重要的 PC 轴,等等。下一步是按照特征值从高到低排列特征向量,按照重要性的顺序重新排列主成分。我们需要在有序特征向量的方向上转换数据,这又会产生主分量。
6.主成分验证
依赖性检查
我们能够成功地生产主要部件。现在,让我们验证一下电脑,看看它们是否能够减少冗余,并检查数据压缩的程度。我们将创建散点图来可视化原始波段中的成对关系,并将其与 PCs 的成对关系进行比较,以测试依赖性的存在。

Pair plot of Bands (left) and PCs (right)
让我们看一下配对图,注意原始数据中存在的变量之间的相关性在主成分中消失了。因此,主成分分析能够显著降低相关性。沿着对角线的分布图告诉我们,PCA 也成功地传递了与可压缩性相关的方差。
压缩性检查

上面绘制的以百分比表示的特征值柱状图为我们提供了每个 PC 中保留的信息。请注意,最后的 PCs 特征值很小且不太重要,这就是降维发挥作用的地方。如果我们选择保留保留 93%信息的前三个相关部分,那么最终数据可以从 7 维减少到 3 维,而不会丢失太多信息。
7.将电脑转换回图像
是时候将 1-d PCs 整形回原始图像形状,并在 0 到 255 之间归一化 PCs,这与原始图像范围相同,以使图像可视化成为可能。
让我们直观地确定压缩量。

Intensities of Principal Components images
请注意,前几个 PC 具有丰富的信息并且是清晰的,当我们接*尾声时,这些 PC 开始丢失信息,而最后几个 PC 大多包含噪声。我们将保留前三台电脑,并丢弃其余的电脑。这将有助于通过去除噪声来提高数据质量,并且通过在时间和存储器使用方面高效的机器学习算法来进行处理。
8.PC 和 RCB 图像比较

Comparison of RGB image (left) and principal components composite image (right)
最后,我们使用前三个主成分再现了同一个场景。左边的图像看起来比原始图像 RGB 更丰富多彩,这使得场景中的特征看起来更清晰,彼此之间更容易区分。例如,由于可区分的颜色,农田可以更容易地与城市区分开来。一些特征在电脑图像中显得更突出,而在左侧图像中很难识别。因此,可以得出结论,PCA 在压缩性和信息保留方面对我们的图像数据做了很好的工作。
感谢您的阅读。任何想法将不胜感激。如果你喜欢,请鼓掌。
主成分分析—数学和直觉(后 1)

主成分分析(PCA)是现代数据分析中广泛使用的工具,不容忽视。不幸的是,许多人仍然对它知之甚少,因为它建立在坚实的数学基础上。PCA 的“是什么”相当简单;然而,好奇的人会渴望知道“如何”,这就是事情开始变得复杂的地方。这个 3 部分系列的目标是建立一个线性代数概念的框架,从而对 PCA 形成一个坚实的直觉。这个话题非常广泛,无法在一篇文章中得到证实。因此,我将其细分如下:
- PCA 介绍 :真实世界的例子,直观解释 PCA
 
2.PCA 数学背后的数学:中级线性代数(与 PCA 相关)
- 点点滴滴联系起来理解 PCA: 用扎实的数学概念重温岗位 1 所掌握的直觉
 
那么,什么是 PCA?
考虑一个例子,您被分配了一项任务,设计一个模型来预测城市居民的社会经济状况。市议会收集的数据集包括 70 多个特征,如年度个人收入、年度家庭收入、受抚养人数量、资产数量、房屋位置、房间、卧室、浴室、汽车数量、儿童数量、学校类型(公立/私立)、学费、替代收入来源、就业部门、教育水*、配偶就业、配偶教育、病史等等。整个数据集可以被视为一个 m(行)x n(列)矩阵;其中行代表居民,而每列代表一个特征或一个维度。通常,计算的数量随着每个维度以二次比例增加,这使得计算要求很高。
快速浏览一下特性列表,你会发现大多数特性都是相互关联的,它们只是潜在信号的指示器,并没有被直接观察到。例如,孩子数和学费是一个潜在信号的指标每个孩子的教育费用。房间、卧室、浴室的数量是房屋大小的指标。两个或更多特征之间的这种直接关联使得它们是冗余的,并且可以减少特征空间或数据集的维度。PCA 是一种算法方法,用于降低数据集的维数,使其在计算上可以处理。
需要注意的是,PCA 不执行特征消除。直观地说,它提取原始数据集中所有特征的有效位,并创建较少数量的新特征或主成分。从技术上来说,维数减少会造成信息损失,但这种损失会被边缘化,并通过优化计算能力得到很大补偿。
现在,您已经了解了什么是 PCA,您知道当应用 PCA 时,它会对您的数据集产生多大的影响。因此,有必要对它的功能有一个坚实的理解,我希望你有足够的兴趣和动力来进一步投入你的努力并继续 Post 2 。
主成分分析—数学和直觉(后 2)

这是关于主成分分析——数学和直觉的三部分系列的第二部分。如果你想通过真实世界的例子阅读 PCA 的直观解释,请前往帖子 1 。PCA 的数学涉及到中级的线性代数概念,我们将在这里讨论。
线性代数
线性代数是数学的一个分支,研究数字之间的线性关系。考虑下面的等式,
2x + 3y = 13
5x + 2y = 16
虽然你可能会尝试手动解决它们,这可能不会超过 30 秒;想象一个场景,你有 10 个变量和 10 个方程。这就是向量和矩阵符号出现的地方。上面的等式可以表示为,

向量和矩阵是简洁表示线性方程的方便符号。如果向量是一个列表,矩阵就是一个列表的列表。一个 m x n 矩阵是一个由 m行和 n列组成的矩形数组。向量也是矩阵,但只有一行或一列。有一些方法可以求解上面的表达式,并确定 x 和 y 的值,我们在这里就不深究了。在上面的例子中要理解的概念是,等式左边的向量被矩阵变换,以给出等式右边的向量。****
特殊矩阵
我们已经看到,矩阵是对向量或其他矩阵执行运算的 2D 数列。线性代数中定义了各种具有特殊性质的矩阵,这有助于简化这些运算。当你在机器学习应用中一次又一次地遇到这些特殊矩阵时,你就会意识到它们的重要性。让我们介绍几个与 PCA 相关的应用程序(以及其他几个机器学习应用程序)。
方阵
当行数等于列数时,矩阵是正方形的。简单?

Square matrices
对角矩阵
矩阵的主对角线是从左上到右下的。如果一个矩阵的所有非对角元素都为 0,则该矩阵是对角矩阵。非零条目只出现在主对角线上。主对角线可以有也可以没有零。

Diagonal matrix
单位矩阵
单位矩阵是一种特殊的方阵。当单位矩阵与向量相乘时,它对向量没有任何作用。这相当于将一个标量数乘以 1(例如,5 x 1 = 5)。类似地,将向量乘以单位矩阵没有任何作用。听起来很蹩脚,但它让一些操作变得简单多了。单位矩阵通常表示为 I。

Identity matrix
逆矩阵
标量数 5 的倒数是 1/5 或 5^-1.逆矩阵是应用于矩阵的相同概念。将矩阵 a 与其逆矩阵 A^-1 相乘得到单位矩阵(对于矩阵来说类似于 1),这是线性代数运算中广泛使用的概念。

Inverse Matrix operation
转置操作
对矩阵应用转置操作就是将矩阵的所有行都变成列,反之亦然。矩阵 a 的转置由 A^T.表示

Matrix Transpose
正交和标准正交矩阵
正交矩阵是一种方阵,其列和行是正交单位向量,即垂直且大小为 1。定理 1: 若 A 是正交矩阵,其逆矩阵等于转置矩阵即 A^T = A^-1
对称矩阵
对称矩阵是特殊的方阵。矩阵 a 是对称的,如果它等于它的转置 A^T.。对称轴总是对称矩阵的主对角线。定理 2: 若 a 是任意矩阵,则(A^T)A 和 A(A^T)是对称的。

Symmetric matrix
你可能不需要记住不同的矩阵类型或定理。最好将此保存为备忘单,因为您会经常遇到它们。
基础变更
考虑二维空间 R 中的向量 r 。空间 R 可以由任意一组正交的单位长度向量 e1 和 e2 来定义。

Vector r in R² space
现在来看相对于坐标 e1 和 e2 的矢量 r ,可以表示如下:

Vector r defined with basis e
我们最初将矢量 e1 和 e2 表示为一组“任意的”矢量。按照惯例,e1 和 e2 形成标准坐标集,因为它们具有单位长度并且彼此正交。当向量 r 相对于一组向量 e 或基 e 来描述时,可以表示为 r e(用基 e 读向量 r)。然而,相同的向量 r 仍然可以相对于另一组坐标来描述,例如 b1 和 b2。在这个新的坐标系中,向量 r b(以 b 为基读取向量 r)的编号会不同;在下图中用[x,y]表示。图中的矢量 b1 和 b2 是相对于标准坐标或基 e 来描述的。注意,矢量 b1 和 b2 不必彼此正交(在该特定示例中,它们是正交的)。

Vector r with basis e and basis b
我们如何确定 r b 中的数字?
因为我们知道了新坐标集合 b 相对于基 e 的向量,我们就有了将任意向量从基 b 变换到基 e 的变换矩阵,让我们称这个变换矩阵为 b。

因此,要确定基 B 中向量 r 的个数,我们现在要做的就是将矩阵 B 的逆乘以基 e 中的向量 r

我没有进入计算的细节,因为它是微不足道的。
这里我们需要注意的是,向量并不依赖于最初用来描述它的坐标轴。我们可以用一组新的坐标轴或基向量来重新描述它。这是线性代数中的一个重要概念。它允许我们移动向量或数据项的基础,从而移动向量中的数字。
让我们更进一步。你想在向量 r b 上应用一个用基 e 描述的变换矩阵 R(向量 R 用基 b)。由于我们不知道基 b 中的变换矩阵 R,我们将首先将其应用于向量 r e,然后将其变换回基 b
第一步:将矢量 r b 的基改为 r e

步骤 2:应用变换矩阵 R

步骤 3:转换回基础 b

综上所述,如果你想把一组坐标中描述的变换矩阵(e 基中的矩阵 R)应用到另一组坐标中描述的向量(b 基中的向量 r )上,这是线性代数中你会遇到相当多的情况;可以用 B(逆)和 B 把 R 包起来。
这可能有点难以理解,但它是线性代数中非常重要的概念,值得投入精力。
特征向量和特征值
“eigen”这个词来源于德语,意思是“特有的”。它帮助我们识别某样东西的特性。到目前为止,我们一直在研究一个向量在应用变换矩阵时是如何变化的。现在让我们试着想象一个变换矩阵是如何影响整个向量空间的。考虑由正方形突出显示的 R 的示例向量子空间。为了便于理解,我在这个空间中突出了三个向量(红色、绿色和蓝色)。

让我们应用变换矩阵 T,将这个正方形子空间放大到矩形。

注意一些向量在其跨度内保持不变,而另一些则不然。红色的水*向量指向相同的方向,大小不变。垂直的绿色向量指向相同的方向,但是其大小增加了 2 倍。对角线上的蓝色向量指向其他方向,其大小也有所增加。事实上,除了水*和垂直向量之外。我们子空间中的所有向量都通过应用这种垂直缩放的变换而改变了。
因此,水*和垂直向量是特殊的,并且是该特定变换矩阵 T 的“特征”,并且被称为变换矩阵 T 的“特征向量”。此外,水*向量的幅度保持不变,这意味着它具有 1 的相应“特征值”。垂直向量的特征值是 2,因为它在变换后大小加倍。注意,虽然在这个特定的例子中不适用,但是在变换时方向翻转的向量;但是保持在相同跨度中的向量也称为特征向量。您只需将负号(-)应用到相关的特征值上。
我们通过几何表示看到的特征向量和特征值的概念可以用代数表示如下,

其中,向量 v 是与变换矩阵 t 相关联的特征向量。它改变标量λ,该标量λ是与向量 v 相关联的特征值。
所以,我们已经知道,特征向量是在变换后不会改变太多的向量。它们可能被缩放或压缩,指向相同的方向或被颠倒;但是它们总是保持在相同的跨度内。特征向量是特定变换矩阵的特征,它们之所以重要,是因为它们是有趣的基向量或坐标,我们很快就会看到。
改变到特征基
考虑这样一个场景,你必须将一个 3×3 的变换矩阵 T 应用到一个向量 x 上,然后反复应用 n 次,其中 n = 1 百万。

在一些实际应用中,您可能需要执行更大规模的矩阵乘法,这使得这些任务的计算量非常大。然而,这个问题有一个明显的例外,那就是当 T 是一个对角矩阵时。对角矩阵是只在从左上到右下的对角线上有非零元素的矩阵。将一个对角矩阵乘以 n 次等于将对角元素提升 n 倍!

Raising a Diagonal matrix to a power of n
如果矩阵 T 不是对角的呢?这就是我们到目前为止所学的变化基和特征向量的概念可以应用到现实世界场景中的地方。让我们在这里重温一下我们的问题。我们想对一个向量应用一个变换矩阵 T n 次,这需要将 T 乘以自身 n 次或者将 T 提升到 n 次幂,我们这个问题的一个简单而优雅的解决方案是将基改为特征基;使用特征转换矩阵。如果矩阵 C 的列是矩阵 T 的线性无关特征向量,我们可以应用矩阵 C(逆)化为特征基。这将我们带到一个世界,其中矩阵 T 由对角矩阵表示,让我们称之为 D。矩阵 D 中的对角线由与相应的特征向量相关联的特征值组成。现在,应用该变换 n 次只是纯粹的缩放,或者有效地将主对角线上的特征值提升到 n 次幂,从而使计算过程更加高效。我们现在要做的就是把基础变回原来的坐标,瞧!我们有矩阵 T 的 n 次方。

Diagonalization of a matrix

这里的关键信息是,如果一个矩阵可以通过基到特征基的变换而对角化,那么它就是可对角化的矩阵。
谱定理
到目前为止,我们所学的一切都带我们到了谱定理。
设 a 是实数的 m×n 矩阵,A^T 是它的转置矩阵。
定理 3 :若 a 对称(意为 A^T = A),则 a 正交可对角化,且只有实特征值。换句话说,存在实数λ1,λ2。。。λn(特征值)和正交的非零实向量 v 1, v 2,… v n(特征向量)使得对于每个 i = 1,2,…,n:

这就是谱定理,线性代数中最重要最有力的定理之一。你可能已经注意到了,它受到一个事实的限制,即它只适用于对称矩阵。
但是,如果你回忆一下定理 2(在对称矩阵一节下陈述): 如果 a 是任意矩阵,那么(A^T)A 和 A(A^T)是对称的。 这暗示着谱定理可以应用于矩阵(A^T)A 和 A(A^T).谱定理是主成分分析的核心;这可能是它最重要的应用之一。
就是这样!你已经在线性代数方面打下了坚实的基础,并且知道足够的数学知识来理解 PCA 的数学。恐怕这是一个令人精疲力尽的帖子,但是你在这里学到的概念不仅会帮助你解开 PCA 但是数据科学中的其他一些应用。
做得好,请继续关注本系列的 post3 ,在这里我们将应用到目前为止学到的所有概念,并了解 PCA 是如何工作的。
参考
主成分分析—数学和直觉(后 3)

正如所承诺的,这是第三篇也是最后一篇关于主成分分析——数学和直觉的文章。在 Post 1 中,我们用一个真实世界的例子简要介绍了 PCA,并掌握了直觉。在帖子 2 中,我们学习了线性代数中与 PCA 相关的一些最重要的概念,或许还有各种其他数据科学应用。完成所有艰苦的工作后,现在是时候使用我们坚实的数学框架,将这些点连接起来,以真正理解 PCA 是如何以及为什么工作的。
PCA 是一种降维技术。它简化了复杂的数据集,使其在计算上可行。不涉及特征消除;相反,PCA 的工作原理是从原始数据集中的所有要素中提取有效信息,并创建较少数量的新要素。简而言之,如果你有一个 n 维(n 个特征)的数据集,应用主成分分析将它减少到一个 k 维特征空间,其中 k < n.
Let us use an example here. You have a dataset on hotel rooms listing the room areas and respective prices.

The 2-dimensional feature space can be plot as shown below.

The goal is to reduce the 2 dimensions that are represented as x-axis and y-axis respectively, into one.
Note that I have chosen a 2D dataset because it is easy to visualise. In a real world scenario, you may have 1000s or more features and therefore the need for dimensionality reduction. Also, please do not confuse the above plot with linear regression, because although it looks similar it is an entirely different concept. There is no prediction going on here.
Coming back to PCA, we would like to simplify our original dataset which is described on a 2D basis. Recall the concept of 基变化,这是我们在帖子 2 中遇到的。我们需要问的问题是,
有没有一个基是旧基的线性组合,能最好地描述数据?
在数学上,假设 X 和 Y 是通过变换 p 相关的 mxn 个矩阵。矩阵 X 是具有 n 个特征的原始数据集,Y 是具有 n 个新特征或主成分的新数据集。

- p 是将 X 转换成 y 的矩阵。
 - X 列为旧基础或原始特征。
 - 变换矩阵 P 的行是用于表示 x 的列的一组新基向量
 - 矩阵 Y 是 X 的重新表示,它的列是新特征或主成分。
 
现在我们有了目标的数学表示,我们想知道转换矩阵 P 的理想选择是什么?这取决于我们希望矩阵 Y 的特征表现出什么性质。这个问题将在后面的 方差 和 冗余 章节中回答。让我们单独处理它们。
投影误差和方差
我们的示例数据集的 2D 特征空间再次显示如下,

我们希望在一维空间中重新表达这些数据,或者将两个特征压缩成一个。因此,我们需要做的就是画一条穿过数据云的线,并将每个数据点投影到这条线上。在我们能画出的所有可能的线中,我用黑色和橙色代表了两条线。

你认为哪条线最能代表数据?我希望您选择黑线,因为它更接*大多数数据点(见下图)。红色记号与黑色/橙色线相交的点是相应蓝色数据点的投影。请注意将每个数据点分别连接到黑线和橙线的投影距离或红色标记的大小。黑线使数据点的累积投影距离最小化。换句话说,当我们将数据从 2D 转移到 1D 时,黑色矢量可以最小化投影误差或信息损失。

应该注意的是,数据的方差或“分布”沿着黑线是最大的。如果这种解释不是很明显,下面的动画可能会有所帮助。它显示了如何同时达到“最大方差”和“最小投影误差”,即沿着数据云两侧的洋红色刻度。

Courtesy : Making sense of principal component analysis, eigenvectors & eigenvalues
因此,矩阵 Y 的期望属性是新特征或其第一主分量应该沿着最小化投影误差的线,同时最大化投影数据的方差。
冗余
PCA 利用数据集中固有的冗余来降低维数。考虑以下 2D 特征空间的图,其覆盖了数据冗余的可能范围。

图 A 绘制了 员工工资 与 房间面积(*方英尺) 的关系图,两者互不相关。图 A 中的两个维度没有表现出任何冗余,不能通过 PCA 进行降维。在极端情况下,图 C 是以*方米为单位的 房间面积 对以*方英尺为单位的 房间面积 的曲线图。这两个特征之间完全相关,因此在这种情况下,消除其中一个是安全的,因为它们本质上提供了相同的信息。
PCA 的作用得到认可的理想场景是图 B,该图与我们之前的示例相同, 房间价格($) 与 房间面积(*方英尺)。 图 B 显示了两个特征之间的一些相关性,表明数据可以用一个新的特征来重新表达,这个新的特征是旧特征的线性组合。因此,如前所示,当我们通过将每个数据点投影到黑线上来将我们的基础从 2D 改变到 1D 时,我们也消除了特征冗余。如图 B 所示,沿着穿过数据云的黑线,数据点变得不相关。下图显示了同样的情况,

方差是一个变量的数据分布,而协方差是两个变量如何一起变化的度量。如果我们将房间面积(*方英尺)和房间价格(美元)分别表示为变量 x 和 y,

并且协方差矩阵可以计算如下:

注意,我没有深入方差和协方差的数学计算的细节,因为它是微不足道的。要说明的是,协方差矩阵总是对称的,主对角线上的所有元素都是每个变量的方差。所有其他条目都是每对变量的协方差。
回到我们的房间面积(*方英尺)对房间价格(美元)的例子,一旦我们改变基础,从 2D 到 1D 减少维度;这些特征变得彼此不相关,或者换句话说,协方差为 0。因此,协方差矩阵是对角矩阵。

总的来说,我们希望矩阵 Y 的特征/主成分展现的特性是:
- 主成分应该沿着使投影数据的方差最大化的方向。
 - 矩阵 Y 的特征应该彼此不相关,即其协方差矩阵应该是对角矩阵。
 
让我们重温一下我们先前推导出的 PCA 目标的数学表示,

x 是具有 n 个要素的原始数据集。p 是应用于矩阵 x 的变换矩阵。矩阵 Y 是具有 n 个新特征/主成分的新数据集。我们已经建立了矩阵 Y 中特征的性质,目标是减少冗余或者更准确地说矩阵 Y 的协方差矩阵(姑且称之为 S y )是对角的。因此,在我们的方程 PX = Y 中,矩阵 P 的选择应该使得 S y 对角化。
我们知道一个对称矩阵通过它的标准正交特征向量矩阵对角化。回忆一下我们在帖子 2 中学到的线性代数的谱定理,
如果 A 是对称的,那么 A 是正交可对角化的,并且只有实特征值。
这确实是我们拼图的最后一块。理论上,PCA 假设所有的基向量,即矩阵 P 的行是 X 的协方差矩阵的标准正交特征向量。将 P 变换到 X 产生矩阵 Y,使得 S y 对角化。其次,它假设方差最大的方向是最重要的或“最主要的”。在这种情况下,矩阵 P 的行根据其相应的方差或特征值进行排序。通过消除矩阵 P 中具有低特征值的行,方差低的方向被忽略。这使得有效地减少维数而不显著损失信息成为可能。
参考
- 关于主成分分析的教程 s,对于有兴趣进一步阅读该主题的人来说,这是一个极好的教程。
 - 如果没有这个无可否认的关于栈交换的令人敬畏的答案理解主成分分析,特征向量&特征值,那么参考文献列表可能是不完整的
 - 主成分分析。
 
主成分分析(PCA) 101,使用 R
一次提高一个维度的可预测性和分类能力!使用 2D 图“可视化”30 个维度!

Basic 2D PCA-plot showing clustering of “Benign” and “Malignant” tumors across 30 features.
如果你喜欢这篇文章并想看更多,请务必关注我的简介 !
设置
对于本文,我们将使用来自 UCI 机器学习报告 的乳腺癌威斯康星州数据集作为我们的数据。如果您想继续学习,请继续为自己加载:
**wdbc** <- read.csv("wdbc.csv", header = F)**features** <- c("radius", "texture", "perimeter", "area", "smoothness", "compactness", "concavity", "concave_points", "symmetry", "fractal_dimension")names(**wdbc**) <- c("**id**", "**diagnosis**", paste0(**features**,"**_mean**"), paste0(**features**,"**_se**"), paste0(**features**,"**_worst**"))
上面的代码将简单地加载数据并命名所有 32 个变量。 ID 、诊断和十(30)个不同的特征。来自 UCI:
表示 , 标准误差 , 最差 或者最大(三个最大值的*均值)这些特征被计算出来,从而得到 30 个特征 。例如,字段 3 是*均半径,字段 13 是半径 SE,字段 23 是最差半径。”
为什么是 PCA?
对,现在我们已经加载了数据,发现自己有 30 个变量(因此排除了我们的响应“诊断”和不相关的 ID 变量)。
现在你们中的一些人可能会说“30 个变量太多了”,一些人可能会说“呸..才 30?我和成千上万的人合作过!!"但是请放心,这同样适用于任何一种场景..!

使用 PCA 有几个很好的理由。本文开头的图是如何使用 PCA 绘制多维数据的一个很好的例子,我们实际上通过使用那些两个主成分捕获了整个数据集中的63.3%(dim 1 44.3%+dim 2 19%)的方差,当考虑到原始数据由 30 个特征组成,而这些特征不可能以任何有意义的方式绘制时,这是非常好的。
一个非常重要的考虑是承认我们从未在我们的 PCA 图中指定反应变量或任何其他东西来指示肿瘤是“良性还是“恶性”。事实证明,当我们试图使用 PCA 的线性组合来描述数据中的差异时,我们发现“良性”和“恶性”肿瘤之间有一些非常明显的聚类和分离!这为基于我们的特征开发分类模型提供了一个很好的案例!
PCA 的另一个主要“特性”(没有双关语的意思)是,它实际上可以直接提高模型的性能,请阅读这篇伟大的文章以了解更多信息:
介绍
towardsdatascience.com](/dimensionality-reduction-does-pca-really-improve-classification-outcome-6e9ba21f0a32)*
什么是 PCA,它是如何工作的?
让我们立即解决一些问题,PCA 的主要目的是而不是作为一种功能移除的方式!主成分分析可以减少维度,但是它不会减少数据中的特征/变量的数量。这意味着您可能会发现,仅使用 3 个主成分就可以解释 1000 个特征数据集中 99%的差异,但您仍然需要这 1000 个特征来构建这 3 个主成分,这也意味着在预测未来数据的情况下,您仍然需要新观测数据中的 1000 个特征来构建相应的主成分。
好了,够了,它是怎么工作的?
由于这纯粹是介绍性的,我将跳过数学,给你一个 PCA 工作的快速纲要:
- 标准化数据(中心和刻度)。
 - 从协方差矩阵或相关矩阵计算特征向量和特征值 (也可以使用奇异向量分解)。
 - 对特征值进行降序排序,选择 K 个最大特征向量(其中 K 为新特征子空间 k ≤ d 的期望维数)。
 - 从选择的 K 个特征向量中构造投影矩阵 W 。
 - 通过 W变换原始数据集 X,得到一个 K 维特征子空间 y
 
如果你没有上过代数课,这听起来可能有点复杂,但它的要点是将我们的数据从它的初始状态 X 转换到一个具有维度的子空间 Y ,其中 K 通常是——小于 X 的原始维度。幸运的是,使用 R 很容易做到这一点!**
肿瘤数据的主成分分析
现在我们对 PCA 的工作原理有了一点了解,这就足够了。让我们实际尝试一下:
**wdbc.pr <- prcomp(wdbc[c(3:32)], center = TRUE, scale = TRUE)
summary(wdbc.pr)**
这是不言自明的,' prcomp '函数对我们提供的数据运行 PCA,在我们的例子中,这是'*wdbc[c(3:32)]【T47]'数据,不包括 ID 和诊断变量,然后我们告诉 R 对我们的数据进行居中和缩放(因此标准化数据)。最后我们呼吁总结一下:*

The values of the first 10 principal components
回想一下,PCA 的一个特性是,我们的分量根据它们的标准差(特征值)从最大到最小排序。所以让我们来理解这些:
- 标准差: 在我们的例子中,这只是特征值,因为数据已经被居中和缩放(标准化)
 - 差异比例 :该组件在数据中所占的差异量,即。 PC1 仅在数据中就占 >总方差的 44%!
 - 累计比例:简单来说就是解释方差的累计量,即。如果我们使用前 10 个成分,我们将能够解释数据中总方差的 > 95%。**
 
好的,那么我们需要多少组件?我们显然希望能够解释尽可能多的差异,但要做到这一点,我们需要所有 30 个组件,同时我们希望减少维度的数量,所以我们肯定希望少于 30 个!
由于我们对数据进行了标准化,现在我们有了每台电脑的相应特征值,我们实际上可以用它们来为我们画一个边界。因为一个特征值< 1* 将意味着该分量实际上解释了少于单个解释变量,所以我们想要丢弃这些。如果我们的数据非常适合 PCA ,我们应该能够丢弃这些成分,同时保留至少70–80%的累积方差。让我们绘制并观察:***
***screeplot(wdbc.pr, type = "l", npcs = 15, main = "Screeplot of the first 10 PCs")
abline(h = 1, col="red", lty=5)
legend("topright", legend=c("Eigenvalue = 1"),
       col=c("red"), lty=5, cex=0.6)cumpro <- cumsum(wdbc.pr$sdev^2 / sum(wdbc.pr$sdev^2))
plot(cumpro[0:15], xlab = "PC #", ylab = "Amount of explained variance", main = "Cumulative variance plot")
abline(v = 6, col="blue", lty=5)
abline(h = 0.88759, col="blue", lty=5)
legend("topleft", legend=c("Cut-off @ PC6"),
       col=c("blue"), lty=5, cex=0.6)***

Screeplot of the Eigenvalues of the first 15 PCs (left) & Cumulative variance plot (right)
我们注意到的前 6 个分量有一个特征值> 1* 并且解释了几乎 90%的方差,这太棒了!我们可以有效地将维度从 30 个减少到 6 个,同时只“损失”大约 10%的方差!***
我们还注意到,仅用前两个成分,我们实际上就可以解释超过 60%的方差。让我们试着画出这些:
***plot(wdbc.pr$x[,1],wdbc.pr$x[,2], xlab="PC1 (44.3%)", ylab = "PC2 (19%)", main = "PC1 / PC2 - plot")***

好吧,这真的不太能说明问题,但是考虑一下,这代表了 30 维数据集中 60%以上的方差。但是我们从中看到了什么?在的上/中右有一些群集正在进行。让我们也考虑一下这个分析的实际目标是什么。我们想解释一下恶性和良性肿瘤的区别。让我们将响应变量* ( 诊断)添加到图表中,看看我们是否能更好地理解它:*******
**library("factoextra")
fviz_pca_ind(wdbc.pr, geom.ind = "point", pointshape = 21, 
             pointsize = 2, 
             fill.ind = wdbc$diagnosis, 
             col.ind = "black", 
             palette = "jco", 
             addEllipses = TRUE,
             label = "var",
             col.var = "black",
             repel = TRUE,
             legend.title = "Diagnosis") +
  ggtitle("2D PCA-plot from 30 feature dataset") +
  theme(plot.title = element_text(hjust = 0.5))**

这基本上是完全相同的图,带有一些花哨的椭圆和颜色,对应于受试者的诊断,现在我们看到了PCA的美妙之处。仅通过前两个组成部分,我们可以清楚地看到良性肿瘤和恶性肿瘤之间的一些区别。这清楚地表明数据非常适合某种分类模型(如判别分析)。****
下一步是什么?
我们的下一个直接目标是使用前 6 个主要成分构建某种模型来预测肿瘤是良性还是恶性,然后将其与使用原始 30 个变量的模型进行比较。
我们将在下一篇文章中讨论这个问题:
决策边界、分离、分类等等。让我们潜入 LDA!
towardsdatascience.com](/linear-discriminant-analysis-lda-101-using-r-6a97217a55a6)**
结束语
如果你想看和了解更多,一定要关注我的 媒体 🔍碎碎念 🐦****
阅读彼得·尼斯特拉普在媒介上的作品。数据科学、统计和人工智能...推特:@PeterNistrup,LinkedIn…
medium.com](https://medium.com/@peter.nistrup)****
其他资源:
想象一下一次家庭聚餐,每个人都开始问你关于 PCA 的事情。首先你向你的…
stats.stackexchange.com](https://stats.stackexchange.com/questions/2691/making-sense-of-principal-component-analysis-eigenvectors-eigenvalues) [## 用 Python 理解 PCA(主成分分析)
陷入变量的海洋来分析你的数据?在决定选择哪些功能时感到迷茫,以便…
towardsdatascience.com](/dive-into-pca-principal-component-analysis-with-python-43ded13ead21) [## 主成分分析的一站式商店
在我用于研究生统计理论课的教科书的开始,作者(乔治·卡塞拉和罗杰…
towardsdatascience.com](/a-one-stop-shop-for-principal-component-analysis-5582fb7e0a9c) [## 假人的降维第 1 部分:直觉
基于主成分分析和奇异值分解的维数约简。以简单、直观的方式解释。从大局到…
towardsdatascience.com](/https-medium-com-abdullatif-h-dimensionality-reduction-for-dummies-part-1-a8c9ec7b7e79) [## 在 R | Kaggle 中使用 PCA + LDA 预测乳腺癌
编辑描述
www.kaggle.com](https://www.kaggle.com/shravank/predicting-breast-cancer-using-pca-lda-in-r) [## 如何将新向量投影到 PCA 空间?
感谢您为交叉验证提供答案!请务必回答问题。提供详细信息并分享…
stats.stackexchange.com](https://stats.stackexchange.com/questions/2592/how-to-project-a-new-vector-onto-pca-space) [## PCA -主成分分析要点
用于数据分析和可视化的统计工具
www.sthda.com](http://www.sthda.com/english/articles/31-principal-component-methods-in-r-practical-guide/112-pca-principal-component-analysis-essentials/)****
主成分分析:机器学习的视角(下)

https://3c1703fe8d.site.internapcdn.net/newman/gfx/news/hires/2017/sixwaysandco.jpg
在我之前的文章中,我从统计学的角度回顾了主成分分析。在本文中,我将回顾同一主题的机器学习方面。请注意,我将涉及的范围是基本的,不包括 PCA 的变体,如概率 PCA 和核 PCA。就像我之前的文章一样,内容相当专业,所以熟悉以下一些内容会让这篇文章更容易理解:线性代数(矩阵、特征向量/特征值、对角化、正交性)和统计学/机器学习(标准化、方差、协方差、独立性、线性回归)。
我们将从寻找二维数据空间的一维投影开始。以下是我们的数据集。

我们有无限多可能的一维投影:

在我们所有的可能性中,我们将关注正交投影。

在所有可能的投影中,正交投影是我们感兴趣的原因,因为它具有最接*的矢量特性。根据最*向量性质,在 W 空间的所有向量中,最接* u 的向量就是 u 在 W 上的正交投影,换句话说,我们希望得到最接*原始数据集的投影,以保持降维后尽可能多的信息。这是最*向量性质的证明:

现在我们知道了投影的方向,让我们用数学公式来表示投影。为了做到这一点,我们将从正交投影的定义开始。

上面的等式是我们的数据需要经过正交化的线性变换。最后一个表达式显示了我们最终想要的:一个新的、更低的维度上的正交投影数据。因此,我们希望找到一个线性算子,它用最小正交投影将我们的数据映射到一个子空间上。
重要的是要看到,正交投影是原始 d 维空间的 k 维子空间,用原始 d 维坐标表示。比如 k = 1,q 的 q 转置为(d x k * k x d = d x d)。看起来降维还没做,但那是因为我们参考了原始坐标的投影。如下图所示,一维投影数据是指二维坐标。

考虑到这一点,我们可以将问题表述为寻找最佳线性变换 Pi(将我们的数据变换为投影到较低维度的线性算子),以最小化重建误差:

不要混淆 PCA 和线性回归。PCA 是最小化正交投影的距离,而线性回归是最小化在 y 轴上的距离。

在 k 维子空间中,有 k 个正交基向量。基向量不必是正交的,但是子空间中的每个基向量可以使用 Gram-Schmidt 过程用正交基来代替,并且我们可以容易地将基向量的长度改变为 1。因此,我们对这个优化问题的约束将是基向量的长度必须是 1。我们可以重申我们的问题:

将最小化转换为最大化(K = 1 的情况)
我们将从最容易处理的情况开始,即当投影维数 k = 1 时。处理 k = 1 情况的好处是,我们可以消除 Pi 或基向量 q 的内部求和,因为这里只有一个向量。
我们可以通过做一些线性代数,将这个问题转化为最大化问题,而不是致力于最小化问题。我们将从最初开始的正交投影表达式开始,而不是从上一段中的表达式开始。



第一次求和不依赖于基向量 q ,所以不影响我们的最小化问题。去掉常数后,现在我们试图最小化负面表达,就变成了最大化问题。

做更多的代数,

现在问题变成了,

http://www.cs.columbia.edu/~verma/teaching.html
最大化问题是什么意思?
我们开始的最小化问题是最小化从数据集到投影的正交距离。对于最大化问题,我们看到是最大化方差。现在我将展示为什么问题的最大化版本是投影数据集方差的最大化。为了证明它,让我们从方差的方程开始。

请注意,上面的等式是一个标量乘以一个矢量本身的点积。


为什么我们把最小化问题转化为最大化问题?
那什么是 X q 的转置呢?和原来的 X 有什么不同?

换句话说,列向量表示 k 维的新子空间内的距离。
从最小化和最大化的角度来看,看到同样的问题是很有趣的,因为它们都实现了降低维度的目标,但实现的方式不同。最小化将是最小化残差,残差是数据点和投影之间的正交距离。另一方面, 最大化问题是最大化正交投影数据集的方差 。我们可以直观地看一下最小化和最大化:

http://alexhwilliams.info/itsneuronalblog/2016/03/27/pca/
一般 K 情况
现在我们将把 k = 1 的表达式转换成一般的 k 种情况的表达式。的原始最小化表达式

http://www.cs.columbia.edu/~verma/teaching.html
相当于

http://www.cs.columbia.edu/~verma/teaching.html
当我们有不止一个 q 并且 q 不再是一个向量而是一个矩阵时。
原因是因为外积之和(即变换运算符)相当于矩阵乘法,因为它从一个向量增长为一个矩阵,如下所示:

http://mlwiki.org/index.php/Matrix-Matrix_Multiplication
为了将最大化问题转化为一般的 k 情况,我们需要决定我们想要从矩阵中最大化什么。让我们从轨迹的定义开始。一个 n -by- n 方阵 A 的迹定义为AA的主对角线(从左上到右下的对角线)上的元素之和。由于我们的矩阵 Q(Q 的转置)是对称的,所以上面提到的对称矩阵的相同定理将被应用于它可以被分解为 t 的 P D 转置,并且我们还将使用 trace 的一个性质 trace(AB) = trace (BA)。
如果 A 是可对角化的矩阵,那么 A 的迹等于 A 的特征值之和,证明如下:

因此,为了最大化方差,我们可以最大化矩阵的迹,它是 d 的对角线元素之和。

http://www.cs.columbia.edu/~verma/teaching.html
我们也可以像这样将迹的概念引入最小化问题:

因此,最大化矩阵的轨迹,

等同于最大化协方差矩阵以及与 X 的 X 转置相关联的特征值。注意,X 的 X 转置的维数是 d×d,但是其正被最大化的矩阵具有 k×k 的维数。追踪操作的输出是特征值之和的 k×k 矩阵, 但是 argmax 运算的输出是(d×k)Q 矩阵,其中每一列是 X 的 X 转置的特征向量。
投影数据

到目前为止,我们只研究了新维度的基本向量。然而,我们真正想要的是原始数据在新维度上的投影。PCA 的最后一步是我们需要将 Q 的 Q 变换与原始数据矩阵相乘,以获得投影矩阵。我们从(d×k)Q 矩阵和 Q 的 Q 转置得到 d×d 维的结果。乘以(d×n)X 矩阵,投影矩阵为 d×n。
结论
我们从 d×d 协方差矩阵开始,通过最小化重构误差得到前 k 个特征向量,这相当于最大化矩阵的迹。所以我们成功降维了。回到统计学的角度,我们为什么要最大化方差的问题已经得到了回答,因为我们要最小化重建误差,这与最大化方差有相同的结果。
主成分分析的主要成分

Photo by Katie Smith on Unsplash
主成分分析( PCA )用于机器学习应用中,以降低数据的维度。在其他应用中,它对图像压缩特别有用。在本帖中,我们将浏览 Lindsay Smith 的 关于主成分分析的教程 以及 python 中的实现。
我们的目标是通过布置数学公式来开发 PCA 的直觉,并超越 fit 和 fit_transform 方法。在继续之前,熟悉扩散度量和线性代数是有帮助的。如果解释看起来微不足道,可以直接跳到实现。
传播的量度

差异
方差是对分布的度量,它表示一组数字与它们的*均值相差多远。对于一维数组 X,方差 s2 为:

- Xi =数组 X 的第 I 个条目的值
 - X 条= X 的*均值
 - n =条目的数量
 
二维之间的协方差
如果我们想测量两个随机变量的联合可变性呢?协方差测量各条目相对于*均值的变化程度。它由下式给出:

- Xi =数组 X 的第 I 个条目的值
 - Yi =数组 Y 的第 I 个条目的值
 - X bar =数组 X 的*均值
 - Y 条=数组 Y 的*均值
 - n =条目数,X 和 Y 相同
 
查看协方差的输出时,查看符号很重要。如果是正的,那么就有正相关,意味着 X 和 Y 一起增加;如果是负的,那么两者都增加。如果我们关心值,那么最好使用皮尔逊相关系数。
n 维之间的协方差
如果我们有一个 n 维数据,我们如何测量协方差?回想一下,协方差仅在 2 维之间,因此结果是一个协方差矩阵。知道我们可以计算的协方差值的数量是有用的:

- n =维数
 
例如,如果我们有一个维度为 x、y 和 z 的数据集,那么我们的协方差矩阵 C 将为:

线性代数

Photo by Alex Block on Unsplash
特征向量
当我们将两个兼容的矩阵相乘时,我们实际上是在做一个线性变换。考虑一个方阵 A 和一个向量 v 以及以下属性:

- A =方阵
 - v =矢量
 - λ =标量值
 
上面告诉我们的是 v 实际上是一个特征向量。从几何学上讲,该表达式意味着对向量 v 应用线性变换会返回其缩放版本。
如果 A 是一个可对角化的矩阵,那么它有 n 个特征向量。特征向量的一个重要性质是它们都是正交的。稍后,我们将会看到如何用这些向量来表达数据,而不是原始维度。
本征值
在上一节中,我们在没有意识到的情况下计算了特征值:它不是别人,正是λ。在计算特征向量的时候,我们也会计算特征值。如本教程所示,可以手动计算这些值。然而,一旦 A 的维数超过 3×3,那么获得特征值和特征向量会非常繁琐和耗时。
PCA 实施

Photo by Lauren Mancke on Unsplash
我们现在知道了在我们选择的例子中实现 PCA 的必要成分。在本节中,我们将详细介绍每个步骤,并了解前面章节中的知识是如何应用的。
第一步:获取数据
在本练习中,我们将创建一个 3D 玩具数据。这是任意的数据,所以我们可以提前猜测我们的结果会是什么样子。为了使接下来的部分更简单,我们将把数据转换成玩具数据帧。
请注意,我们的数据没有任何缺失值,因为这是 PCA 正常运行的关键。对于缺失的数据,我们可以用均值、方差、众数、零值或我们选择的任何值来代替空的观测值。每种技术都会将方差归入数据集,由我们根据具体情况做出适当的判断。
查看 3D 散点图中的数据:

第二步:减去*均值
为了使 PCA 工作,我们需要具有*均值为零的数据集。我们可以用下面的代码轻松减去每个维度的*均值:
步骤 3:计算协方差矩阵
再次挑选熊猫让我们的生活变得更容易,我们使用了 cov 方法。
回想一下,非对角项是一个维度与另一个维度的协方差。例如,在下面的示例输出中,我们不太关心值,而是关心符号。这里 X 和 Y 是负相关的,而 Y 和 Z 是正相关的。

第四步:计算协方差矩阵的特征向量和特征值
我们用 numpy 的线性代数包 numpy.linalg.eig 计算特征向量 v 和特征值 w 。特征向量被归一化,使得列 v[:,i] 是对应于特征值 w[i] 的特征向量。计算出的特征值不一定是有序的,这将与下一步相关。
步骤 5:选择组件和新的特征向量
现在我们有了特征向量和特征值,我们可以开始降维了。事实证明,具有最高特征值的特征向量是数据集的主分量。事实上,具有最大特征值的特征向量代表了数据维度之间最重要的关系。
我们现在的任务是将特征值从最高到最低排序,按照重要性的顺序给出分量。我们从作为向量矩阵的特征向量中提取想要保留的特征向量:

让我们看看如何在代码中做到这一点。这里我们决定忽略最小的特征值,因此我们的索引从 1 开始。
步骤 6:派生新数据集
在最后一部分中,我们取向量的转置,并将其乘以原始数据集的左边,转置。
在上面的代码中,转置的特征向量是行特征向量,其中特征向量现在位于行中,因此最重要的特征向量位于顶部。行数据调整是转置的*均调整数据,其中每行保存一个单独的维度。我们的新数据如下所示:

你可能会注意到上面轴的标签不是 X 和 y。通过我们的变换,我们已经改变了我们的数据,用我们的 2 个特征向量来表示。
如果我们决定保留所有的特征向量,我们的数据将保持不变,只是旋转,使特征向量是轴。
步骤 1:取回旧数据
假设我们减少了图像压缩的数据,现在我们想检索它。为此,让我们回顾一下我们是如何获得最终数据的。

我们可以把这个表达式反过来得到:

因为行特征向量的倒数等于我们的特征向量的转置。这是真的,因为矩阵的元素都是数据集的单位向量。我们的等式变成:

最后,我们加上从开始减去的*均值:

在 python 代码中,这看起来像:
结论
恭喜你!我们在练习的最后,从头开始执行 PCA 以减少数据的维数,然后返回我们的步骤以取回数据。
尽管我们没有深入探究为什么会起作用的细节,但我们可以自信地解读来自 sklearn 的 PCA 等软件包的输出。
对于完整的 python 代码,可以随意探索本 笔记本 。
有原则的机器学习:高效协作的实践和工具
机器学习项目通常比它们应该的要难。我们正在处理数据和软件,这应该是一个简单的问题,运行代码,迭代一些算法调整,过一会儿我们就有了一个训练有素的人工智能模型。但是快进三个月后,训练数据可能已经被更改或删除,并且对训练脚本的理解可能是对哪个做什么的模糊记忆。您是否在已训练的模型和创建模型的过程之间建立了一个分离?您如何与同事分享工作以进行协作或复制您的成果?
对于一般的软件项目来说,需要的是更好地管理代码版本和项目资产。人们可能需要重新审视项目在过去任何阶段的状态。我们在软件工程中一直这样做(审查旧的提交)。一个机器学习项目不也应该需要偶尔这样做吗?不仅如此。拉式请求的等价物,或者其他领域中常规使用的其他种类的团队管理实践呢?
我自己,刚刚开始学习机器学习工具的旅程。在学习材料中,我会看一些教程视频,有时老师会谈到一些问题,让我想起我软件工程生涯早期的一段时间。例如,在 1993-1994 年,我是一个开发电子邮件用户代理团队的首席工程师。我们没有任何种类的源代码管理(SCM)系统。每天,我都会咨询所有其他团队成员,看看他们当天做出了哪些改变。我拥有的唯一工具是在他们的源代码树和主源代码树之间运行 diff(使用diff -c | less),然后手动应用更改。后来,团队成员从主源代码树中手动更新了他们的源代码树。这是一个烂摊子,直到我们发现了一个早期的 SCM 系统(CVS)。这一工具使得项目进行得更加顺利。
当我学习机器学习和数据科学项目中使用的工具时,这些故事感觉与此类似。即使在今天,ML 研究人员有时也将实验(数据、代码等)存储在*行的目录结构中,以方便区分,就像我在 1993 年所做的那样。
让我们从一些可能有助于改善机器学习项目的软件管理工具状态的原则的简要概述开始。
在任何机器学习项目中,科学家都会进行许多实验,为目标场景开发最佳训练模型。实验包含:
- 代码和配置:实验中使用的软件,以及配置参数
 - 数据集:使用的任何输入数据——其大小很容易达到数千兆字节,例如用于识别音频、图像或视频文件内容的项目
 - 输出:训练好的 ML 模型和来自实验的任何其他输出
 
一个机器学习项目只是运行软件。但是通常在与同事共享文件或复制结果时会有困难。获得可以与同事共享的可重复的结果,并且您可以及时返回以评估项目的早期阶段,这需要更全面的管理工具。
解决方案需要包含这样的想法(摘自 Patrick Ball 题为原则性数据处理的演讲):
- 透明:检查一个 ML 项目的每一个方面。
 - 使用什么代码、配置和数据文件
 - 项目中使用了哪些处理步骤,以及这些步骤的顺序
 - 可审核性:检查管道中间结果
 - 再现性:在项目开发的任何阶段精确地重新执行项目的能力,以及同事精确地重新执行项目的能力
 - 记录处理步骤,以便任何人都可以自动重新运行
 - 随着项目的进展记录项目的状态。“状态”是指代码、配置和数据集
 - 能够在项目历史中的任何时间重新创建可用的精确数据集对于可审计性的有用性至关重要
 - 可伸缩性:支持多个合作者从事一个项目的能力,以及同时从事多个项目的能力
 

ML 项目与常规软件工程的不同之处是什么?
你是否已经得出结论,如果 ML 项目与软件工程相同,那么我们为什么不在机器学习项目中使用常规的软件工程工具呢?没那么快!
在常规的软件工程项目中,有许多工具可能对 ML 研究人员有用。代码和实验配置可以在 Git 这样的常规源代码管理系统中轻松管理,pull requests 这样的技术可以用来管理这些文件的更新。CI/CD (Jenkins 等)系统甚至可以用于自动化项目运行。
但是 ML 项目的不同之处在于,常规的软件开发工具无法满足所有的需求。这里有几件事:
- 度量驱动的开发与特性驱动的开发:在常规的软件工程中,“是否发布”的决定是基于团队是否达到了特性里程碑。相比之下,ML 研究人员看的是一种完全不同的测量方法——生成的机器学习模型的预测值。研究人员将反复生成几十个(或更多)模型,测量每个模型的准确性。由于目标是找到最准确的模型,所以该项目由每个实验中获得的度量来指导。
 - ML 模型需要大量的资源来训练:常规软件项目组织文件来一起编译一个软件产品,而 ML 项目则训练一个描述人工智能算法的“模型”。在大多数情况下,编译一个软件产品只需要几分钟,这非常便宜,许多团队都遵循持续集成策略。训练一个 ML 模型需要很长时间,除非必要,否则最好避免这样做。
 - 巨大的数据集和训练过的模型:前面一点的概括是,机器学习开发阶段几乎总是需要用于训练 ML 模型的巨大数据集,加上训练过的模型可能是巨大的。普通的源代码管理工具(Git 等)不能很好地处理大文件,像 Git-LFS 这样的插件也不适合 ML 项目。(见我之前的文章)
 - 管道 : ML 项目是下载数据、准备数据、将数据分成训练/验证集、训练模型、验证模型等一系列步骤。许多人使用“管道”这个词,用每个步骤的离散命令来构建一个 ML 项目比把所有东西都塞进一个程序有用。
 - 专用硬件:软件组织可以在任何类型的服务器设备上托管其软件基础设施。如果他们想要云部署,他们可以从他们最喜欢的云计算提供商那里租用日常的 VPS。ML 研究人员有巨大的计算需求。高功率 GPU 不仅可以加快视频编辑速度,还可以让 ML 算法飞起来,大幅减少训练 ML 模型所需的时间。
 
如果中间结果是在三个月前生成的,而事情发生了变化,以至于您不记得当时软件是如何运行的,那该怎么办?如果数据集已被覆盖或更改,该怎么办?一个支持 ML 项目的透明性、可审计性和可再现性的系统必须考虑所有这些因素。
现在我们有了一个原则列表,让我们在这个背景下看看一些开源工具。
有大量的工具可能适合数据科学和机器学习从业者。在接下来的部分中,我们将具体讨论两个工具( MLFlow 和 DVC ),同时还将讨论一般原则。

ML 项目的原则性数据和模型存储
这场讨论的一面可以归结为:
- 跟踪每一轮训练机器学习模型使用了哪些数据文件。
 - 跟踪生成的训练模型和评估指标
 - 通过任何形式的文件共享系统与同事共享数据文件的简单方法。
 
需要一个数据跟踪系统来进行透明的审计,或再现结果。将项目团队扩展到多个同事所需的数据共享系统。
这可能已经很明显了,但是使用 Git 或其他 SCM(源代码管理系统)来存储机器学习项目中使用的数据文件是不切实际的。如果存储代码和配置文件的 SCM 也可以存储数据文件,这将是非常简单的。Git-LFS 也不是一个好的解决方案。我之前的文章为什么 Git 和 Git-LFS 不足以解决机器学习的可复制性危机,详细讨论了这个推理。
有些库提供 API 来简化远程存储上的文件处理,并管理向远程存储上传文件或从远程存储上传文件。虽然这对于远程数据集的共享访问很有用,但对这里描述的问题没有帮助。首先,它是嵌入式配置的一种形式,因为文件名是嵌入到软件中的。任何将配置设置嵌入到源代码中的程序都很难在其他情况下重用。其次,它没有关联每个版本的脚本使用了哪个数据文件。
考虑 MLFlow 的示例代码:
mlflow.pytorch.load_model("runs:/<mlflow_run_id>/run-relative/path/to/model")
这支持几种可选的文件访问“方案”,包括像 S3 这样的云存储系统。此处的示例从“run”区域加载了一个文件,在本例中是一个经过训练的模型。每次执行“一段数据科学代码”时,都会生成一个 MLFlow“运行”。您配置了一个存储“运行”数据的位置,很明显,每次运行都会生成一个“运行 ID ”,用于索引数据存储区域。
这看起来很有用,因为它会自动将数据与提交到存储代码和配置文件的 SCM 存储库相关联。此外,由于 MLFlow API 可用于多种语言,因此您不会局限于 Python。
DVC 有一种不同的方法。您的脚本只是使用普通的文件系统 API 输入和输出文件,而不是将文件 API 集成到 ML 脚本中。例如:
理想情况下,该路径名将从命令行传入。关键是代码没有什么特别的要求,因为 DVC 在用于训练或验证模型的代码的上下文之外提供它的值。
DVC 使这变得透明,因为数据文件版本控制与 Git 成对出现。使用以下命令将文件或目录置于 DVC 控制之下:
$ dvc add path/to/model.pkl
数据存储在一个自然的地方,在您的工作目录中。浏览各种运行的结果就像浏览 Git 历史一样简单。查看特定的结果就像运行git checkout一样简单,DVC 将被调用以确保正确的数据文件被链接到工作区。
创建一个“DVC 文件”来跟踪每个文件或目录,并由 DVC 插入到工作空间中。它们有两个目的,一个是跟踪数据和模型文件,另一个是记录工作流命令,我们将在下一节中讨论。
这些 DVC 文件记录被跟踪的文件或目录的 MD5 校验和。它们被提交到 Git 工作区,因此 DVC 文件为每次 Git 提交记录工作区中每个文件的校验和。在幕后,DVC 使用所谓的“DVC 缓存目录”来存储每个文件的多个实例。实例通过校验和进行索引,并使用引用链接或符号链接链接到工作区。当 DVC 响应git checkout操作时,它能够根据 DVC 文件中记录的校验和快速重新排列工作区中的链接文件。
DVC 支持用于与其他人共享数据和模型的远程缓存目录。
$ dvc remote add remote1 ssh://user@host.name/path/to/dir 
$ dvc push 
$ dvc pull
DVC 遥控器是一个存储池,通过它可以共享数据。它支持许多存储服务,包括 S3 和其他服务、HTTP 和 FTP。创建一个非常简单。dvc push和dvc pull命令特意与git push和git pull命令相似。当 dvc push 将数据发送到远程 dvc 缓存时,我们使用dvc pull从 DVC 缓存中检索数据。

ML 项目的原则性工作流程描述
讨论的另一方面是关于如何最好地描述 ML 项目中使用的工作流或管道。我们是不是把所有的东西都塞进一个程序里?还是我们使用多种工具?
最大的灵活性来自于将工作流实现为可重用命令的管道或有向非循环图,这些命令将配置选项作为命令行参数。这有意地类似于 Unix 的小型定义良好的工具的哲学,具有狭窄的范围,可以很好地协同工作,其中行为是由命令行选项或环境变量定制的,并且可以根据需要混合和匹配。这种哲学背后有一个漫长的集体历史。
相比之下,许多 ML 框架采用不同的方法,编写一个程序来驱动特定项目使用的工作流。单个程序可以从将数据分成训练集和验证集开始,然后通过训练模型和运行模型的验证来继续。这限制了我们在其他项目中重用代码的机会。
将 ML 项目构建为管道有一些好处。
- 管理复杂性:将各个步骤作为独立的命令来执行,可以提高透明度,让你集中注意力
 - 优化执行:如果文件没有改变,可以跳过不需要重新运行的步骤。
 - 可重用性:在多个项目之间使用相同工具的可能性。
 - 可扩展性:不同的工具可以由不同的团队成员独立开发。
 
在 MLFlow 中,框架让你编写一个“驱动程序”。该程序包含所需的任何逻辑,例如处理和生成机器学习模型。在幕后,MLFlow API 向 MLFlow 服务器发送请求,然后由它生成指定的命令。
多步骤工作流的 MLFlow 示例使这一点变得很清楚。即:
...
load_raw_data_run = _get_or_run("load_raw_data", {}, git_commit) 
ratings_csv_uri = os.path.join(load_raw_data_run.info.artifact_uri, "ratings-csv-dir") 
etl_data_run = _get_or_run("etl_data", {"ratings_csv": ratings_csv_uri, "max_row_limit": max_row_limit}, git_commit) 
... 
als_run = _get_or_run("als", {"ratings_data": ratings_parquet_uri, "max_iter": str(als_max_iter)}, git_commit) 
... 
_get_or_run("train_keras", keras_params, git_commit, use_cache=False) 
...
_get_or_run函数是对mlflow.run的简单包装。每个参数的第一个参数是在MLproject文件中定义的一个entrypoint。入口点包含环境设置、要运行的命令以及传递给该命令的选项。例如:
etl_data: 
    parameters: 
      ratings_csv: path 
      max_row_limit: {type: int, default: 100000} 
    command: "python etl_data.py --ratings-csv {ratings_csv} --max-row-limit {max_row_limit}"
乍一看,这似乎很好。但这里有几个问题值得思考:
- 如果你的工作流程必须比直线更复杂呢?您将 false 传递给 mlflow.run 的 synchronous 参数,然后等待 SubmittedRun 对象以指示任务已完成。换句话说,可以在 MLFlow API 之上构建一个流程管理系统。
 - 为什么需要服务器?为什么不直接在命令行运行这些命令呢?要求配置服务器会使 MLFlow 项目的设置更加复杂。
 - 如何避免运行不需要执行的任务?在许多 ML 项目中,训练一个模型需要几天时间。该资源成本只应在需要时使用,如更改数据、更改参数或更改算法。
 
DVC 有一种使用常规命令行工具的方法,但不需要安装服务器,也不需要编写驱动程序。DVC 支持使用前面提到的 DVC 文件集将工作流定义为有向无环图(DAG)。
我们前面提到过 DVC 文件与添加到工作区的文件相关联。DVC 文件还描述了要执行的命令,例如:
$ dvc run -d matrix-train.p -d train_model.py \
     -o model.p \
     python train_model.py matrix-train.p 20180226 model.p 
$ dvc run -d parsingxml.R -d Posts.xml \
     -o Posts.csv \ 
      Rscript parsingxml.R Posts.xml Posts.csv
dvc run 命令定义了一个描述要执行的命令的 dvc 文件。-d选项记录了对文件的依赖性,其中 DVC 将跟踪其校验和以检测对文件的更改。-o选项是命令的输出。一个命令的输出当然可以用作另一个命令的输入。通过查看依赖项和输出,DVC 可以计算命令的执行顺序。
与工作空间中的任何其他数据文件一样,所有输出(包括训练模型)都会在 DVC 缓存中自动跟踪。
因为它计算校验和,DVC 可以检测改变的文件。当用户请求 DVC 重新执行流水线时,它只执行有变化的阶段。如果输入文件没有变化,DVC 可以跳过你的三天模型训练任务。
一切都在常规命令行中执行,不需要设置服务器。如果您希望在云计算环境中或在连接了 GPU 的服务器上执行,只需将代码和数据部署到该服务器,并在该服务器的命令行上执行 DVC 命令。
结论
在探索改进机器学习实践的一些原则方面,我们已经走了很长的路。正如许多人认识到的那样,ML 领域需要更好的管理工具,以便 ML 团队能够更有效和可靠地工作。
复制结果的能力意味着其他人可以评估你所做的事情,或者就进一步的发展进行合作。再现性有许多先决条件,包括检查系统每个部分的能力,以及精确地重新运行软件和输入数据的能力。
机器学习项目中使用的一些工具有漂亮的用户界面,比如 Jupyter Notebook。这些工具在机器学习工作中有它们的位置。然而,GUI 工具并不完全符合本文讨论的原则。命令行工具非常适合处理在后台运行的任务,并且可以很容易地满足我们概述的所有原则,而典型的 GUI 会干扰这些原则中的大部分。
正如我们在本文中看到的,一些工具和实践可以从常规软件工程中借鉴。然而,机器学习项目的需求决定了更适合这一目的的工具。一些有价值的工具包括 MLFlow 、 DVC 、 ModelDb 甚至 Git-LFS (尽管我们之前已经说过了)。
原载于 2019 年 6 月 20 日https://dev . to。
先验函数:高斯过程
在这篇文章中,我们讨论高斯过程的工作。高斯过程属于核方法,且与模型无关。高斯过程对于低数据方案“学习”复杂函数特别有用。我们将回顾一个非常实际的真实世界应用(与深度学习或神经网络无关)。讨论是在主题专家尼尔·劳伦斯教授和 T2 教授理查德·特纳教授的演讲之后进行的。
背景阅读:
多元高斯分布:高斯分布可以使用均值(u)、方差(σ2)和概率分布函数(PDF)来指定,如下所示


如果我们有一个以上的独立高斯分布,我们可以把它们结合起来。组合的 PDF 也是高斯的,即多变量高斯。例如两个高斯的示例在下面针对两个高斯(即,二元)示出



一般来说多元高斯的 PDF 可以具体通过均值、方差(或标准差)和协方差矩阵(σ)

多元(MV)高斯的性质
- 高斯和就是高斯
 - 高斯的边际就是高斯
 - 调节高斯型也会导致高斯型
 
如果你想阅读证明或者只是想要方程式,请在这里看到它们或者在这里看到它们,摘要在这里看到它们。回顾这些非常重要,因为大多数与高斯过程相关的数学都是这些基本结果的应用。
贝叶斯规则:后验概率是先验概率乘以似然性,即
*后验,P(H|E) =(先验 P(H) 似然 P(E|H))|证据 P(E)
其中 H 是一些假设,E 是证据。
高斯过程:我们从线性回归方法开始讨论。对于一些输入( x ,我们可以写成

这个等式的一种形式是斜率截距形式(忽略噪声项,我们通常将其添加到权重 w 中)

现在让我们改变 w 1(斜率)和 w 2(截距),看看结果是什么(演示/gif 可能需要一些时间来加载)

我们有一系列的线!我们试图在参数模型中实现什么,例如这里的线性回归,是为了估计 w(或线性回归的β),它最好地描述了我们的数据,参见数学 这里的 。
在贝叶斯线性回归中,我们放置权重 w1 和 w2 的先验,然后获得后验,一旦我们观察到(x,y)即训练集
利用贝耶法则,这是


w1 和 w2 可以组合成一个矩阵,并从二元高斯分布中提取。一般来说,对于多元高斯分布,可以画出“n”个权重(β)“w”
后验:最能描述我们的训练集(x,y)的权重“w”
似然:对于给定的权重和训练输入 x,最像 p(y|x,w)的函数
边际可能性是归一化常数,是所有先验和所有可能性的积分


在获得后验“w”之后,我们可以将它们用于新数据,即不在我们的训练集(x,y)中的数据,这些数据是从高斯的边缘化属性获得的。


对于新的观察值,我们有 x并希望获得(f)或 y*,这使用贝叶斯规则

线性到非线性:到目前为止我们假设我们的函数是线性的,w 想要获得“w”。对于非线性和一般情况,我们可以用(x)代替 x,把 x 变换到一个我们可以线性处理的特征空间。然后利用(x )应用贝叶斯推理得到 f或 y*,松散地说变换就是把线性模型变成高斯过程。数学虽然相对简单,但很难评估到底发生了什么。它通常以指定作用于输入 x 的核函数或协方差函数结束。上述方程与核函数的关系很难理解,需要一些努力。为了使事情变得简单,我们求助于直觉。这里讨论的例子来自 Richard Tuner 的教程**
正如 Tuner 博士解释的那样,让我们从两个相关的高斯分布 y1 和 y2 开始,在图表上绘制它们的高度(随机抽取的)以获得一个新的表示。如果我们从“顶部”看这两个 2D 高斯,它可以产生一个等高线图。这里我们假设这两个高斯函数高度相关,如协方差矩阵所示,均值为零。

现在我们从这两个高斯样本中抽取一些样本,绘制如下

现在,我们固定一个高斯,然后从第二个相关的高斯中抽取样本,这限制了第二个样本来自红色显示的较小的高斯。

我们可以对 20 维高斯进行重复,现在协方差矩阵是由一个“函数”表示的,其中相关在对角线上是强的,而在其他方向上是弱的

这里固定两点,我们控制“蠕动”

一般来说,这对于无限维高斯是可以做到的。其中“y”中的每一个都是通过对任意输入(x)加上 so 噪声起作用的核函数 K 来指定的。I 是单位矩阵。这里我们只选择协方差矩阵 K 的必要部分

核函数或协方差函数 K 是允许我们将我们用线性模型开发的贝叶斯框架应用于任何函数的“诀窍”。通过将输入 x 变换到函数空间 的 ϕ:基或激活函数,将贝叶斯线性回归的权重空间视图关联到“函数空间”视图

(x)由于我们对协方差矩阵(σ)施加的技术条件而与核函数相关。σ是正的 半定的 因此,我们可以应用 【奇异值分解】、 并由此我们可以写出**

这个内核技巧允许直接处理函数空间中的输入。因此,核函数更重要,因为它直接作用于输入,我们不需要指定权重“w”或(x)
最常见内核函数如下所示

For a demo see source of changing parameters of K see the source here
在函数空间视图中,我们写道

通常*均 m(x)是零:你可以认为这是批量标准化数据的工作。
定义:高斯过程由(无限)随机变量的集合定义,通过协方差函数 k 指定
****先验:当我们从 GP 中抽取先验样本时,我们可以获得任意的函数样本,如下所示。
后验:利用我们的训练数据集(x,y),我们可以获得后验(y 或 f(x),因为 y = f(x)+噪声)。在这里,我们仅限于仅通过我们的训练数据点的函数,参见两个动画中“y”示例的修复

预测分布**也可以通过使用特定于 k 的无限协方差矩阵的相关子矩阵来获得。这里的输入是 X以获得似然性(y 和 f)。

由于一切都是高斯的,我们可以应用边际化属性,使用贝叶斯规则获得最终的高斯,这通过方差给出了*均预测函数和不确定性。

****直觉:*粗略地说,记住后验分布和预测分布的直觉,对于我们控制蠕动的图形来说更简单,其中红点是我们的训练示例(x,y),我们已经“固定”了它们,并从其他可能变化的高斯分布中进行选择。在预测时,我们甚至“更少”扭动,因为我们已经固定了更多的数据点(x+x ,y ),因此进一步减少了不确定性。
有许多技术细节已经被跳过,所以阅读拉斯姆森&威廉姆斯来理解它们是很重要的,因此我们遵循相同的惯例。这篇文章只是为了提供这个丰富的主题的概述,并方便我们广泛使用他们的作品来阅读文献。
****实现:在实践中,我们必须选择正确的核(协方差函数)及其参数,并应用 cholskey 分解,但这是计算开销很大的。关于实施问题的说明可在这里获得。为了克服这种限制变分法也可以用于像张量流概率这样的框架中。
应用 : GP 允许对复杂函数的不确定性进行估计,因此被广泛使用。下面列出的是我个人最喜欢的医学成像。
GP 是扩散 MRI 数据后处理的核心。 fsl 工具漩涡基于 GP。获得人脑的准确连接(白质轨迹)是至关重要的一步。显示主要白色轨迹的示例(低分辨率)如下所示

无模型方法也用于减少 MRI 扫描采集,以减少研究中的扫描时间。这里通过高斯过程对 MRI 扩散信号建模,然后采用该模型重建 k-q 空间中的缺失采集,如这里的所示。这为许多复杂的采集打开了大门,这些采集不能常规地在临床上进行,因为它们太长并且只限于研究工作。由于需要大量领域知识的专业性质,我们不讨论技术细节,但一定要阅读论文以了解工作的味道和复杂性。
参考资料:
- **理查德调谐器的网站【http://cbl.eng.cam.ac.uk/Public/Turner/Presentations **
 - 尼尔·劳伦斯的博客:http://inverseprobability.com/
 - 机器学习的高斯过程,c . e . Rasmussen&c . k . I . Williams 此处提供:
 - https://www . jgoertler . com/visual-exploration-Gaussian-processes/# Gaussian processes
 
对机器学习的隐私攻击
机器学习的安全性
或者如何从您的 ML 端点提取您的训练数据和模型

机器学习是惊人的,我想我们都同意,很快 ML 将成为你我日常使用的每一个科技产品的标准组件。
然而,挑战在于,伴随着 ML 承诺的所有闪亮的新功能,也出现了大量的漏洞,可供攻击者利用。
攻击者可以利用其中的一些漏洞来扰乱你的模型的思维,并让它输出错误的预测——就像在逃避和中毒攻击的情况下。然而,另一些方法允许攻击者从您的模型中提取敏感信息,比如底层数据或模型本身。
我们称这种攻击为对机器学习的隐私攻击——这正是我们今天帖子要讨论的内容。
数据
不用说,如果你试图在 YouTube 视频中识别猫,那么数据隐私对你来说可能不是一个大问题。但一旦你开始在银行和医疗保健等行业应用机器学习,控制底层训练数据的访问和传播就成了一个真正的问题。
但首先,让我们后退一步,想想机器学习到底是什么。比如这些机器到底在“学习”什么?希望在看到一定数量的训练数据后,机器能够发现数据中的某些模式。但是,至关重要的是,它不仅能够在同一个数据集内发现它们,而且还可以将其“学习”推广到其他之前未见过的数据集。
概括点很重要。如果我们希望机器只学习训练数据集而不进行归纳,我们可以让它简单地记住每个例子和每个标签,然后使用类似查找表的东西来提取知识。我们通过机器学习跳过所有额外障碍的原因是因为我们希望它学习世界的总体状态,而不仅仅是手头的数据集。

这就是隐私的来源。取决于我们如何构建和训练我们的模型,有时仍然有可能从机器的记忆(参数)中逆向工程机器在训练期间看到的东西。这为隐私攻击打开了几个通道。
第一个,也是最简单的一个是成员推理攻击。这时,攻击者手头有一个数据点,并想知道它是否属于原始数据集。想象一下,例如,如果有人想知道你的名字是否在一些敏感的医疗名单上?
这正是这项研究的作者所做的。他们设计了一种技术,使用建立在原始目标模型上的“影子”模型来决定患者是否在医院出院数据集中。他们在谷歌和亚马逊的商业“ML 即服务”分类器上证明了攻击的成功。
这里还有一些:
- 这里攻击者利用 GANs 对生成模型进行攻击。他们 100%成功地推断出哪些样本用于训练白盒攻击的目标模型,80%成功地推断出黑盒攻击的目标模型。
 

Real samples vs samples from the original generator vs samples the attackers were able to reconstruct using GANs.
- 在这里,本着 GDPR 等数据保护法规的精神,作者设计了一种方法来检查特定用户的文本数据是否被用于训练一系列语言模型(单词预测、对话生成)。
 - 在这里,作者研究了一个联合 ML 系统中敌对内部参与者的威胁。他们得出结论,威胁是真实的,事实上,他们发现不同用户之间的数据集差异越大,就越容易发起攻击。
 - 这里作者对聚合位置数据进行攻击,以确定特定用户是否是聚合的一部分。
 - 最后,以稍微不同的方式,在这里作者能够成功地推断出关于基础训练数据的有价值的统计信息。
 
为了更好地理解成员推理攻击,作者在这里做了一个非常深入的调查,关于是什么驱动了它们。他们有一些有趣的发现:
- 你训练你的模型的数据很重要。例如,类越多,模型就越脆弱,因为每个类在潜在空间中占据的区域越小,未知空间就越少。
 - 你选择的算法也很重要。一般来说,其决策边界不太可能受到特定实例的剧烈影响的算法更有弹性(选择贝叶斯而不是决策树!).
 - 白盒知识很重要,但不是全部。例如,尽管多达 10%的数据被噪声所取代,攻击者仍能发动成功的攻击。
 - 阴影模型不必像目标模型那样进行训练。事实上,对于作者测试的 7 个数据集中的 5 个,当攻击数据生成模型与目标模型的类型不同时,报告的准确性最高。
 - 成员推理攻击就像敌对例子一样可以转移
 
所以推断一个人是“在”还是“在外”是很有趣的。但是您可能想知道,如果只对分类器进行黑盒访问,是否有可能实际重建一些底层数据?
答案是肯定的(算是)。这种攻击(称为“数据提取”或“模型反演”)试图提取模型被训练的每个类的*均表示。他们无法提取单个实例,但结果往往相当可怕。
几个例子:
- 在这里作者从一个训练来预测医疗剂量的 ML 模型中提取了患者的基因组信息(尽管不清楚这是由于模型记忆还是他们使用的辅助信息)。
 - 这里作者从一个被训练来进行人脸识别的 ML 模型中提取了特定的人脸图像(还记得我在上面说过的关于*均表示吗?嗯这里 1 类= 1 张人脸图片)。
 

- 在这里作者从一个经过私人数据训练的文本生成器中提取了特定的信用卡号码和社会安全号码(他们研究了边缘案例或他们所谓的“无意识记忆”)。
 
模型
任何机器学习系统的第二个有价值的部分是模型本身——有一堆理由可能有人想要窃取它(执行“模型提取】)。
第一个也是最明显的——因为模型是有价值的。想象一下,您的数据科学团队夜以继日地工作了 6 个月,构建了一个让您从所有竞争对手中脱颖而出的杰作。如果有人通过向您的 API 发送几个查询就成功下载了全部内容,您会有什么感觉?
第二种——也许不太明显,但可以说更危险——因为他们想对你发起白盒规避攻击。通过访问模型渐变精心制作的规避攻击更加强大,因此如果对手可以先下载你的模型,他们将有更大的机会成功攻破你的系统。
不幸的是,在模型提取方面还没有做太多的工作,但在【2016 年的这篇论文中,作者通过观察输入输出对成功提取了模型参数。警告:他们依赖于访问置信度得分,这在现实的黑盒设置中可能可用,也可能不可用。

辩护
就像闪避和中毒攻击一样,你可以做一些事情来使你的模型更加安全。
让我们从最明显的开始: API 强化。我上面链接的大多数论文都依赖于对目标模型的 API 的无限制访问(带有置信度得分),这使得它成为最容易开始的地方。您可以:
- 根本不公开 API
 - 只暴露硬标签,不暴露可信度分数
 - 如果您必须公开置信度得分,您可以降低维度。例如,代替显示 64%,你可以把分数分成 3 或 4 个部分,只显示“高”
 
接下来是数据清理。另一个显而易见的要点是——如果你在大量用户信息上训练一个模型,并且不想意外泄露信用卡号码——就把它们过滤掉。你可以尝试在正文中查找所有的 16 位数字,或者一起过滤掉所有的数字。

稍微复杂一点的是模型硬化。还记得我们上面讨论的这篇论文的发现吗?我们可以利用其中的一些来使我们的机器学习更加强大:
- 模型选择——例如,贝叶斯模型比决策树更健壮
 - 拟合控制-一般来说,过度拟合可以更容易地从模型中提取数据,因此使用正则化是一个好主意
 - 知识控制——将模型及其开发限制在一小部分人的范围内,将有助于防止泄露对攻击者有用的知识
 
接下来是检测。为了从模型中提取任何数据,攻击者将不得不多次查询它,如果不是数十次,也可能是数千次。他们的查询模式与你的实际用户相比可能是异常的,因此是很好的异常检测材料。
最后还有差分隐私。如果你是这个游戏的新手,差分隐私是一个理论框架,旨在提供健壮性的正式保证。更具体地说,它旨在证明仅相差 1 个样本的两个模型将产生相似的预测(使得无法推断该样本)。
用外行人的话来说,差分隐私就是把噪音(或者“随机性”)注入你的机器学习系统。有很多方法可以做到:
- 扰乱用户对公共训练池的输入(例如,当用户向服务器发送数据时,x%被替换为随机数)
 - 扰乱底层数据
 - 扰动模型的参数(例如将噪声注入参数更新过程)
 - 扰动损失函数(类似于例如 L2 正则化)
 - 在预测过程中干扰输出(例如,你的 API 向 x%的用户发送随机噪声)
 
差别隐私的挑战在于它不是免费的。你想要的保护越多,你分配的“隐私预算”越多,你的模型的性能就越差。例如这里为了防止成员推理攻击,作者不得不遭受从 94.4%到 24.7%的训练准确度损失。模型基本上变得没用了。这里有一个替代差分隐私的有趣方法,适用于这种 DP 本身过于昂贵的情况。
结束语
尤其是最*,隐私是一个大话题。随着我们越来越多的生活被托付给算法,重要的是我们要确保它们既安全(抵御像逃避或中毒这样的攻击)又保护隐私。希望这篇文章能让你对问题有所了解——以及潜在的解决方案。
确保每个人的安全。
隐私第一——为什么今天的 AI 坏了,怎么修!

Photo by Dayne Topkin on Unsplash
人工智能正准备开始一场与电气革命期间世界经历的变革一样大的变革。人工智能作为一种技术将无处不在,无所不在。这又是一次自动化,但这一次是由数据推动的。在最*的一项研究中,IDC 预测人工智能市场到 2025 年将达到惊人的 2000 亿美元,由谷歌、亚马逊和微软等科技巨头主导,提供基于云的人工智能解决方案和 API。百度前首席数据科学家吴恩达多次使用人工智能和电力的美丽比喻,他强调数据稀缺是减缓人工智能的主要障碍,因为传统的人工智能方法需要大量的数据来训练模型。这个问题比我们预期的要严重得多,消费者大声疾呼对共享数据感到不舒服。为了解决这些问题并促进数据法律的自由流动,框架和咨询委员会如雨后春笋般涌现。最受欢迎的是欧洲议会(又名 GDPR)的 119 页法规,这是一个复杂法规的杰作,不仅引起了世界各地工程团队的恐慌,而且消费者还对新获得的被遗忘权感到好奇(加上浏览网页时一些令人难以忍受的确认对话。被遗忘的权利被庆祝为通过删除个人在互联网上的信息来保护个人隐私的一个重大胜利。然而,这些数据可能被用来训练一个模型——如何教会机器去遗忘?
如何解决隐私困境?谈到数据隐私,没有简单的答案,事实可能是不同方法的混合,需要在正确的环境中应用。在谷歌 2019 年 I/O 大会上,一项有前途的技术在一份简短的边注中悄然宣布,桑德尔·皮帅推出了 TensorFlow federated,这是一种分布式的隐私保护技术,用于在小型数据集上训练人工智能。简化:联邦学习改变了训练模型的方式,而不是将数据集中在服务器上,模型被发送到数据,在数据中提取知识和底层数学模型
权重被发送回云端,在那里来自多个贡献者的模型被聚合成一个全局模型,并与社区共享。由于数据不会离开您的设备,这将隐私标准提升到了一个新的水*。谷歌已经在智能数字键盘 Gboard 上应用了这一技术,以提高下一个单词的预测能力,例如通过学习你下一步想键入什么。除了保证数据隐私和更高的数据安全性,这还使模型能够从小数据中学习。
这有什么关系? 分布式学习是一种强大的工具,它让科技公司在将分布式数据转化为知识方面拥有竞争优势,并最终拥有卓越的人工智能模型,而无需向消费者索要数据,例如谷歌风险投资资助的 OWKIN ,它是医疗保健领域联合学习的先驱,以克服数据共享问题,从大规模分布式数据中建立集体智能,同时保护数据隐私和安全。
有哪些挑战?联合学习正在改变人工智能的学习方式,但也存在挑战:模型训练,以及对未知数据集的评估,起初会令人困惑。今天,联合学习被限制在一组狭窄的应用中,在这些应用中,可以直接导出必要的标签,而不需要用户做额外的工作。更困难的是,特性不是静态的,比如在企业环境中。此外,还有人的因素,集中汇总数据以构建客户特定模型以获得竞争优势的既定思维模式是另一个减缓联合学习采用速度的挑战。
乍一看,联合学习解决了数据隐私和安全的难题,这没有错,但真正的价值是它可以大幅减少训练模型时所需的数据量,这使得消费者可以通过利用智能即服务获得智能,而无需大数据,这可能会对游戏规则产生改变,尤其是对中小企业。最终允许我们训练模型,这在以前由于缺乏数据而无法训练。
私有人工智能——使用 PySyft 和 PyTorch 的联合学习
GRU 模型在垃圾短信检测中的应用

OpenMined
简介
在过去的几年里,我们都见证了人工智能和机器学习领域的一个重要而快速的发展。这种快速发展得益于计算能力的提高(通过上一代 GPU 和 TPU 实现)以及多年来积累的每秒钟都在创建的大量数据。
从对话助手到肺癌检测,我们可以清楚地看到 AI 发展对我们社会的几种应用和各种好处。然而,在过去的几年里,这种进步是有代价的:在某种程度上失去了隐私。剑桥分析公司丑闻敲响了保密和数据隐私的警钟。此外,无论大小,科技公司对数据的使用越来越多,导致多个司法管辖区的当局致力于制定有关数据保护和隐私的法规和法律。欧洲的 GDPR 是这种行为最著名的例子。
这些担忧和法规与人工智能和机器学习的发展并不直接兼容,因为模型和算法总是依赖于数据的可用性和将其集中在大型服务器中的可能性。为了解决这个问题,一个新的研究领域引起了 ML 研究者和实践者的兴趣:私有和安全的 AI。
什么是私有安全 AI?
这个新领域由一系列技术组成,这些技术允许 ML 工程师在不直接访问用于训练的数据的情况下训练模型,并避免他们通过使用密码术获得关于数据的任何信息。
这看起来像是黑魔法,不是吗?
不要担心…在一系列文章中,我将展示它是如何工作的,以及我们如何通过开源库 PySyft 将它应用于我们自己的 Python 深度学习模型。
该框架依赖于三种主要技术:
- 联合学习
 - 差异隐私
 - 安全多方计算
 
在本文中,我将介绍联合学习及其在垃圾短信检测中的应用。
联合学习
也许是私人人工智能中最容易理解的概念,联合学习是一种训练人工智能模型的技术,而不必将数据移动到中央服务器。谷歌在 2016 年发表的一篇论文中首次使用了这个术语。

Schema of a Federated Learning task
主要思想是,我们不是将数据带到模型中,而是将模型发送到数据所在的位置。
由于数据位于几个设备中(在这里我称之为 workers ),模型被发送给每个 worker,然后再发送回中央服务器。
现实世界中联合学习的一个简单例子发生在苹果设备上。应用程序 QuickType(苹果的文本预测工具)实际上使用的模型通过 WiFi 不时发送到 iOS 设备,用用户的数据在本地进行训练,然后发送回苹果的中央服务器,并更新其权重。
PySyft
PySyft 是一个为联邦学习和隐私保护而构建的开源库。它允许其用户执行私人和安全的深度学习。它是作为一些 DL 库的扩展而构建的,如 PyTorch、Keras 和 Tensorflow。
一个加密的、保护隐私的深度学习库
github.com](https://github.com/OpenMined/PySyft)
如果你更感兴趣,你也可以看看 OpenMined 发表的关于这个框架的论文。
在本文中,我将展示一个使用 PyTorch 的 PySyft 扩展的教程。
入门-设置库
为了安装 PySyft,建议您首先设置一个 conda 环境:
conda create -n pysyft python=3
conda activate pysyft # or source activate pysyft
conda install jupyter notebook
然后安装软件包:
pip install syft
请确保您的环境中也安装了 PyTorch 1.0.1 或更高版本。
如果你有一个关于 zstd 的安装错误,尝试卸载 zstd 并重新安装。
pip uninstall zstd
pip install --upgrade zstd
如果您在设置时仍然遇到错误,您也可以使用 Colab 笔记本并运行以下代码行:
!pip install syft
使用 PySyft 和 PyTorch 检测垃圾短信
包含以下代码的 jupyter 笔记本可以在我的 GitHub 页面上找到。
包含教程和应用程序的库,带有 PySyft-andrelmfarias/Private-AI 的 Private-AI 算法
github.com](https://github.com/andrelmfarias/Private-AI)
在本教程中,我将模拟两个工人,Bob 和 Anne 的设备,在那里存储 SMS 消息。使用 PySyft,我们可以通过使用 VirtualWorker 对象的抽象来模拟这些远程机器。
首先,我们钩住 PyTorch:
import torch
import syft as sy
hook = sy.TorchHook(torch)
然后,我们创建虚拟工人:
bob = sy.VirtualWorker(hook, id="bob")
anne = sy.VirtualWorker(hook, id="anne")
我们现在可以用方法向工人发送张量。送(工)。例如:
x = torch.Tensor([2,2,2]).send(bob)
print(x)
您可能会得到类似这样的输出:
(Wrapper)>[pointer tensor | me:79601866508-> bob:62597613886]
您还可以检查指针所指张量的位置:
print(x.location)
我们可以看到张量位于一个叫做“鲍勃”的虚拟工作者处,这个工作者有一个张量。
现在,您可以使用这些指针进行远程操作:
y = torch.Tensor([1,2,3]).send(bob)
sum = x + y
print(sum)
(Wrapper)>[pointer tensor | me:40216858934-> bob:448194605]
你可以看到在操作之后我们得到了一个指针作为返回。要取回张量,你需要使用方法。get()
sum = sum.get()
print(sum)
张量([3。, 4., 5.])
最令人惊奇的是,我们可以在这些指针上实现 PyTorch API 提供的所有操作,例如计算损失、将梯度归零、执行反向传播等。
现在你已经理解了虚拟工人和指针的基础,我们可以使用联合学习来训练我们的模型。
准备数据并将其发送给远程工作人员
为了模拟远程数据,我们将使用 UCI 机器学习库上的垃圾短信收集数据集。它由大约 5500 条短信组成,其中大约 13%是垃圾短信。我们将大约一半的消息发送到 Bob 的设备,另一半发送到 Anne 的设备。
对于这个项目,我执行了一些文本和数据预处理,我不会在这里展示,但如果你感兴趣,你可以看看我在我的 GitHub 页面上使用的 脚本 。还请注意,在现实生活中,这种预处理将在每个用户的设备中完成。
让我们加载处理过的数据:
# Loading data
inputs = np.load('./data/inputs.npy')
inputs = torch.tensor(inputs)
labels = np.load('./data/labels.npy')
labels = torch.tensor(labels)# splitting training and test data
pct_test = 0.2
train_labels = labels[:-int(len(labels)*pct_test)]
train_inputs = inputs[:-int(len(labels)*pct_test)]
test_labels = labels[-int(len(labels)*pct_test):]
test_inputs = inputs[-int(len(labels)*pct_test):]
然后,我们将数据集一分为二,发送给带有 sy 类的工人。基础数据集:
在 PyTorch 中训练时,我们使用数据加载器来迭代批处理。使用 PySyft,我们可以使用 FederatedDataLoaders 进行类似的迭代,其中批处理以联合的方式来自几个设备。
训练 GRU 模型
对于这个任务,我决定使用一个基于一层 GRU 网络的分类器。不幸的是,PySyft 的当前版本还不支持 PyTorch 的 RNNs 模块。然而,我能够手工制作一个简单的线性图层的 GRU 网络,这是 PySyft 支持的。
因为我们这里的重点是 PySyft 框架的使用,所以我将跳过模型的构建。如果你对我是如何构建的感兴趣,你可以在我的 GitHub 页面查看一下这个 脚本 。
让我们启动模型!
from handcrafted_GRU import GRU# Training params
EPOCHS = 15
CLIP = 5 # gradient clipping - to avoid gradient explosion 
lr = 0.1
BATCH_SIZE = 32# Model params
EMBEDDING_DIM = 50
HIDDEN_DIM = 10
DROPOUT = 0.2# Initiating the model
model = GRU(vocab_size=VOCAB_SIZE, hidden_dim=HIDDEN_DIM, embedding_dim=EMBEDDING_DIM, dropout=DROPOUT)
现在训练它!
请注意第 8、12、13 和 27 行。这些步骤将 PyTorch 的集中培训与 PySyft 的联合培训区分开来。
在训练循环结束时取回模型后,我们可以使用它在本地或远程测试集上用类似的方法评估它的性能。在这种情况下,我能够获得超过 97.5%的 AUC 得分,表明以联合方式训练模型不会损害性能。然而,我们可以注意到整体时间计算的增加。
结论
我们可以看到,使用 PySyft 库及其 PyTorch 扩展,我们可以使用张量指针执行操作,就像我们可以使用 PyTorch API 一样(但仍有一些限制需要解决)。
由于这一点,我们能够在不访问远程和私有数据的情况下训练垃圾邮件检测器模型:对于每一批,我们将模型发送给当前的远程工作器,并在将其发送给下一批的工作器之前将其返回到本地机器。
然而,这种方法有一个限制:通过取回模型,我们仍然可以访问一些私人信息。假设 Bob 的机器上只有一条短信。当我们取回模型时,我们只需检查模型的哪些嵌入发生了变化,就可以知道哪些是 SMS 的标记(单词)。
为了解决这个问题,有两种解决方案:差分隐私和安全多方计算(SMPC)。差分隐私将用于确保该模型不会提供对某些隐私信息的访问。SMPC 是一种加密计算,作为回报,它允许您私下发送模型,这样拥有数据的远程工作人员就看不到您使用的重量。
我将在下一篇文章中展示我们如何用 PySyft 执行这些技术。
欢迎随时给我反馈和提问!
如果你有兴趣学习更多关于安全和私人人工智能以及如何使用 PySyft 的知识,你也可以在 Udacity 上查看这个免费课程 。这是一门很棒的初学者课程,由 Andrew Trask 教授,他是 OpenMined Initiative 的创始人。
来源:
- OpenMined 关于 PySyft 在 arXiv 上的文章:【https://arxiv.org/pdf/1811.04017.pdf
 - 谷歌关于联邦学习的文章:https://arxiv.org/pdf/1602.05629.pdf
 - PySyft 初学者教程:https://github . com/open mined/PySyft/tree/dev/examples/tutorials
 - 联邦学习概述:https://medium . com/@ ODSC/an-open-framework-for-secure-and-private-ai-96c 1891 a4b
 - 一个安全私有 AI 的开放框架:https://medium . com/@ ODSC/an-Open-Framework-for-Secure-and-Private-AI-96c 1891 a 4b
 - PyTorch + PySyft 的 10 行联合学习:https://blog . open mined . org/upgrade-to-federated-Learning-in-10-lines/
 
概率机器学习系列文章 1:使用神经网络作为贝叶斯模型的一部分

source: https://www.pexels.com/photo/ask-blackboard-chalk-board-chalkboard-356079/
这一系列将是关于概率机器学习的不同实验和例子。概率机器学习的优势在于,我们将能够提供概率预测,并且我们可以分离来自模型不同部分的贡献。在第一篇文章中,我们将使用神经网络作为贝叶斯模型的一部分进行实验。这使得我们可以通过贝叶斯框架提供的不确定性估计来使用深度学习的特征学习方面。对于那些不熟悉贝叶斯框架的人,建议阅读第一章《黑客概率编程和贝叶斯方法》。简而言之,在贝叶斯框架中,概率被视为基于先验知识的信任程度。最终结果是,我们将看到数据是固定的,参数是随机变量。因此,我们模型的参数将由分布来表示。相比之下,在 frequentist 框架中,参数是固定的,但数据是随机的。代表不同样本的预期结果的置信区间。我们将使用数值方法评估后验 P(θ|y)。后验概率与可能性 P(y|θ)乘以前验概率 P(θ)成正比。

The posterior, left-hand side, is proportional to the likelihood times the prior.
对于我们的实验,主要假设是训练一个神经网络,作为特征提取器,用于贝叶斯线性回归。根据数据类型选择神经网络结构。我们的例子将是关于时间序列预测,所以我们将使用一个 LSTM (长期短期记忆)神经网络,因为它将能够提取时间相关性。神经网络与贝叶斯模型的这种完全分离的主要优点是,给出良好特征的预训练神经网络可以用于进行概率预测。缺点之一是我们失去了贝叶斯深度学习对于神经网络的正则化方面,而这需要以其他方式实现。
我们的目标是对仅使用短期时间相关性生成的时间序列进行概率预测,即 ARMA(4,2) 。时间序列分为两部分。第一个是自回归 AR(4),这意味着下一个值线性依赖于最后四个值。第二部分是移动*均部分 MA(2 ),这意味着下一个值也将取决于最后两个噪声值。这两部分结合起来就构成了 ARMA(4,2)过程。LSTM 将识别时间序列中的结构,而贝叶斯模型将提供概率估计。第一步,我们将训练一个具有线性最后一层的 LSTM,它将模拟贝叶斯线性回归。之后,我们将把 LSTM 作为特征提取器包含在我们的贝叶斯模型中。我们将在第三部分描述完整的模型。接下来的三个部分将是关于
- 训练 LSTM,
 - 描述贝叶斯模型和
 - 进行概率预测
 
但是我们先来看看生成的数据。

由于过程是 ARMA (4,2),我们只有短期相关性,没有季节性(也没有周期)和趋势。如果我们有了这两个组件,就需要进一步的预处理,但是我们希望在这个例子中保持乐观。在继续之前,我想提一下 LSTM 是在 PyTorch 中实现的,贝叶斯模型是在 PyMC3 中实现的。
步骤 1:训练 LSTM
用具有均方误差损失的七个时间步长的序列来训练 LSTM。我们使用早期停止来防止过度拟合。我们可以在接下来的图中看到,我们对训练集的预测接*真实值,并且可以使用正态分布很好地拟合误差。


我们现在有了一个准确的时间序列预测器,它只能给出逐点的预测。在下一节中,我们将把它包括在贝叶斯模型中,以获得概率预测。
第二步:贝叶斯模型
首先,我们将查看模型的图形表示。白色圆圈是随机节点,阴影圆圈是观测值,方形节点是确定性变换的结果。实线箭头指向随机节点的参数,虚线是确定性变换。我们从 y 开始,这是我们想要预测的值。

Figure 3: Graphical representation of our Bayesian model
我们假设 y 遵循一个正态(μ,σ)。μ相当于我们的 LSTM 预测值,定义如下

其中 z ᵢ 是 LSTM 的最后一个隐藏状态,θ ᵢ 是线性层的权重,θₒ是偏差,n 是 LSTM 的最后一个隐藏状态的数量。LSTM 模型的最后一层与贝叶斯模型的主要区别在于,权重和偏差将由正态分布表示,而不是点估计(即单个值)。σ是权重的不确定性无法捕捉到的预测值的随机误差。在这一点上,z 可以被认为是由观测数据的 LSTM 完成的确定性变换。由于权重的不确定性不取决于具体的数据值本身,我们只描述模型的不确定性。将 LSTM 纳入贝叶斯模型的步骤如下:
- 我们用线性的最后一层来训练 LSTM
 - 我们删除了最后一层,并使用 LSTM 作为特征提取器
 - 我们用贝叶斯线性回归代替了原始的线性层
 
现在我们已经知道了我们想要评估的模型的所有参数,让我们看看使用 ADVI ( 自动微分变分推断)和使用 MCMC ( 马尔可夫链蒙特卡罗)的一些微调获得的它们的分布。这些推理数值方法通过使用 ADVI 后验概率作为 MCMC 先验进行组合,这在 PyMC3 中很容易实现。ADVI 方法的优点是可扩展,但只能给出一个*似的后验概率。MCMC 方法较慢,但收敛于精确的后验概率。在下一篇文章中,我们将更详细地探讨这些问题。

在这一步中,我们将训练好的 LSTM 作为贝叶斯模型的一部分。我们已经获得了参数的分布,这些分布是上一步中的点估计。我们现在准备进行概率预测。
步骤 3:进行概率预测
使用后验预测检查进行预测(即,给定特征的模型参数被采样以获得概率预测)。我们可以在下图中看到 95%置信区间的结果。我们可以注意到,大多数预测都接*真实值,并且大多数预测都落在置信区间内。

Time series predictions (blue) with 95% confidence interval (shaded blue) and the true values (orange)
让我们简单回顾一下。为了获得准确的预测,我们在 LSTM 进行了时间序列的训练。我们可以就此打住,但是我们想要一个概率预测。正因为如此,我们使用 LSTM 作为贝叶斯模型的特征提取器。由于贝叶斯模型参数由分布表示,我们可以描述模型的不确定性。然后,贝叶斯模型用于使用后验预测检查进行概率预测。这个帖子里汇集了很多想法。如前所述,这是概率建模系列文章的一部分,所以我们将在以后的文章中单独处理其中的一些部分。
感谢阅读!
参考资料和建议阅读:
【1】a .盖尔曼、j .卡林、h .斯特恩、d .邓森、a .韦赫塔里和 d .鲁宾、* 贝叶斯数据分析 (2013)、查普曼和霍尔/CRC*
【2】c .戴维森-皮隆、* 面向黑客的贝叶斯方法:概率编程与贝叶斯推理 (2015)、艾迪森-卫斯理专业*
【3】a . Kucukelbir、D. Tran、R. Ranganath、A. Gelman 和 D. M. Blei、 自动微分变分推理【2016】、ArXiv
概率机器学习系列文章之二:模型比较

将原始数据转换为机器学习模型必须遵循许多步骤。这些步骤对于非专家来说可能很难,而且数据量还在持续增长。解决人工智能技能危机的一个建议是进行自动机器学习(AutoML)。一些著名的项目是谷歌云汽车和微软汽车。自动机器学习的问题包括不同的部分:神经结构搜索、模型选择、特征工程、模型选择、超参数调整和模型压缩。在本帖中,我们将对模型选择感兴趣。
模型选择可以被看作是一项微不足道的任务,但是我们将会看到,要获得模型质量的全貌,需要许多度量标准。在选择模型时,通常想到的衡量标准是准确性,但是在继续之前,还需要考虑其他因素。为了探究这个问题,我们将比较同一个数据集的两个相似的模型类。
在之前的帖子中,我们能够对一个时间序列进行概率预测。这就提出了一个问题,即预测的概率是否与经验频率相对应,这被称为模型校准。直观上,对于分类问题,我们希望 80%置信度的预测具有 80%的准确性。有人可能会问,为什么最后准确度还不够。如果在决策过程中使用这些结果,如果预测是错误的,过度自信的结果可能导致更高的成本,而在预测不自信的情况下,可能导致机会的损失。例如,假设我们有一个模型,可以根据土壤样本预测特定地区是否存在贵重矿物。由于贵重矿物的勘探钻井可能耗时且成本高昂,因此在校准模型时,通过关注高可信度预测,可以大大降低成本。
正如贾斯汀·汀布莱克在电影《时间里的 T0》中向我们展示的那样,时间可以是一种货币,所以我们要比较的下一个方面是训练一个模型所需的时间。尽管我们将使用小数据集(即经典的 Iris 数据集),但有许多理由跟踪训练模型所需的时间。例如,一些基于重采样的模型测试技术(例如:交叉验证和自举)需要用不同的数据样本进行多次训练。因此,模型将不会只被训练一次而是多次。当算法将被投入生产时,我们应该期待路上的一些颠簸(如果不是颠簸,希望是新数据!)并且知道重新训练和重新部署模型需要多少时间是很重要的。对训练一个模型所需时间的准确估计也将表明是否需要对更大的基础设施进行投资。
用于比较模型的最后一个方面(见后文)将是使用广泛适用的信息标准(WAIC)的模型的预测能力/复杂性。该标准可用于比较具有完全不同参数的相同任务的模型【1】。它是标准 AIC 的贝叶斯版本(另一个信息标准或 Alkeike 信息标准)。信息标准可以被视为交叉验证的一种*似,这可能很耗时【3】。
有哪些数据?
使用的数据集现在是机器学习的经典:虹膜分类问题。分类是基于萼片和花瓣的测量。这些数据是由英国统计学家和生物学家罗伯特·费希尔在 1936 年提出的。在下图中,长度和宽度的分布基于物种显示。线性分类器应该能够对除海滨锦鸡儿和杂色锦鸡儿以外的边缘物种进行准确的分类。

Pairplots of the features which will be used for the classification. A linear classifier should be able to make accurate classification except on the fringe of the virginica and versicolor species.
我们要对比的车型有哪些?
将为分类问题训练线性分类器。首先,使用特征的线性组合为每个类计算μ。

Equation for the calculation of μ for each of the k class using the N features.
然后,每个类的μ用于我们的 softmax 函数,该函数提供 0 到 1 之间的值(pₖ)。这个值(pₖ)将是索引为 k 的类的概率

Softmax function for the probability p of belowing to the k class based on the previous calculation of μ.
在第一个模型中,β都是常数,等于 1。这将被称为无温度模型(借用物理学术语,因为该函数类似于统计物理学中的配分函数)。第二个模型将对每个类有不同的β,这将增加模型的复杂性(更多的参数),但希望也将给出更好的结果。在文献【4】【5】中可以找到机器学习中用于校准的温度的用法。计算概率时,改变温度会影响每个μ的相对比例。举个例子,我们假设μ₁ = 1,μ₂ = 2,μ₃ = 3。将所有的初始温度固定为一,我们得到的概率是 p₁ = 0.09,p₂ = 0.24,p₃ = 0.67。现在让我们保持相同的温度β₂ = β₃ = 1,但是将第一个温度增加到 2(β₁= 2)。结果概率变成了 p₁ = 0.21,p₂ = 0.21,p₃ = 0.58。最后,如果我们将第一个温度降低到 0.5,第一个概率将向下移动到 p₁ = 0.06,其他两个将调整到 p₂ = 0.25 和 p₃ = 0.69。

Summary of the resulting probabilities for differents temperatures by keeping the μ values fixed.
我们在下面的图形模型中表示了参数和观测值之间的依赖关系。阴影圈是观察结果。z 是特征(萼片长度、萼片宽度、花瓣长度和花瓣宽度),类是用分类变量建模的花的种类。正方形代表其他变量的确定性变换,例如μ和 p,它们的方程已经在上面给出。圆圈是我们试图找到其分布的随机参数(θ和β)。方框表示参数重复出现的次数,由右下角的常数给出。

Graphical representation of the model with temperatures.
哪种模型的精确度最高?
尽管这不是一个模型唯一重要的特征,一个不精确的模型可能不是很有用。对于 50 个不同的训练/测试分割(0.7/0.3),计算两个模型的准确度。这样做是因为我们想要比较模型类,而不是学习模型的特定实例。对于同一个模型规格,很多训练因素会影响最终学习到哪个具体的模型。其中一个因素是所提供的训练数据。由于数据集很小,训练/测试分割可能会导致获得的模型发生很大变化。正如我们在下图中看到的,在测试集上,温度模型的*均精确度为 92.97 %(标准差:4.50 %),而没有温度时,*均精确度为 90.93 %(标准差:4.68 %)。

Distribution of accuracies of fifty different random train/test split for the model with and without temperatures. The model with temperatures has an average accuracy on the test set of 92.97 % (standard deviation: 4.50 %) compared to 90.93 % (standard deviation: 4.68 %) when there is no temperatures. The vertical lines are the corresponding means.
我的参数的分布是什么?
在接下来的两张图中,我们注意到,有温度模型中的一些θ分布比无温度模型中的更分散。我们通常希望这些值尽可能达到峰值。越分散的分布意味着参数值越不确定。我们遇到的通常的罪魁祸首是不良的先验,没有足够的采样步骤,模型设定错误,等等。因为我们想在这种情况下比较模型类,我们将在每个模型训练之间保持这些参数固定,所以只有模型会改变。

Distribution of the parameters for the model without temperatures. There is no distribution for the temperatures since the value is always a constant set to one.

Distribution of the parameters for the model with temperatures. There is a distribution for each blank circle in the graphical representation seen above.
我的概率可信吗?
概率模型只能将其概率建立在观察到的数据和模型规范给出的允许表示的基础上。在我们的例子中,我们只能根据特征的线性组合来区分类别。如果做不到这一点,不仅精度会很差,而且我们的校准也不会很好。在使用这些指标之前,基于后验样本的其他迹象将表明指定的模型对手头的数据并不好。为了测量校准,我们将使用静态校准误差(SCE)【2】定义为

常设专家委员会【2】可以理解如下。在 B 个时间 K 个箱中分离预测,其中 B 是用于计算的置信区间数(例如:在 0 和 0.1 之间、0.1 和 0.2 之间等),K 是类别数。对于这些仓中的每一个,取观测精度 acc(b,k)和预期精度 conf(b,k)之间的绝对偏差。取置信区间箱相对于那些箱中预测数量的加权和。最后取上一笔的班级*均值。示出了具有 89 %的相同准确度的两个训练模型的校准曲线,以更好地理解校准度量。

An exemple of calibration curve for two model with the same accuracy of 89 %. The model with the temperatures (blue) is better calibrated than the one without temperatures (orange). The green line is the perfect calibration line which means that we want the calibration curve to be as close as possible to this line. The dots are the values obtained for each of the eight intervals used.
绿线是完美的校准线,这意味着我们希望校准曲线接*它。如果我们看高置信度预测(0.70 及以上),没有温度的模型有低估其置信度和高估其在较低值(0.3 及以下)的置信度的趋势。有温度的模型通常比没有温度的模型校准得更好(*均 SCE 为 0.042,标准偏差为 0.007)(*均 SCE 为 0.060,标准偏差为 0.006)。

Distribution of SCE (a deviance calibration metric) of fifty different random train/test split for the model with and without temperatures. The model with temperatures (blue) is generally better calibrated (mean SCE of 0.042 with standard deviation of 0.007) than the model without temperature (orange) (mean SCE of 0.060 with standard deviation of 0.006). The vertical lines are the corresponding means.
我要等多久?
正如预期的那样,更复杂的带温度的模型需要更多的时间来进行相同次数的迭代和采样。*均花费 467 秒(37 秒的标准偏差)来训练具有温度的模型,而没有温度的模型花费 399 秒(4 秒的标准偏差)。

Computation times of fifty different random train/test split for the model with and without temperatures. It took on average 467 seconds (standard deviation of 37 seconds) to train the model with temperatures (blue) compared to 399 seconds (standard deviation of 4 seconds) for the model without temperatures (orange). The vertical lines are the corresponding means.
增加了什么复杂性?
在这个实验中,我们比较了更简单的模型(没有温度)和更复杂的模型(有温度)。一个有趣的度量标准是广泛适用的信息标准,它由下式给出

其中,LPPD 是对数逐点预测密度,P 是参数的有效数量。WAIC 用于估计样本外预测精度,不使用未观测数据【3】。WAIC 越低越好,因为如果模型与数据拟合得很好(高 LPPD),WAIC 将变得更低,并且无限数量的有效参数(无限 P)将给出无穷大。具有无限数量有效参数的模型只能记忆数据,因此不能很好地推广到新数据。因此,减去它是为了纠正这样一个事实,即它可能恰好符合数据。因子 2 来源于历史原因(自然来源于基于 Kullback-Leibler 散度和卡方分布的阿凯克信息准则的原始推导)。LPPD(对数逐点预测密度)是用来自后验分布的 S 个样本估计的,定义如下

使用每个数据点【3】的对数似然密度(也称为对数预测密度)相对于参数的方差之和来估计有效参数的数量。

正如我们在下图中看到的,没有温度的模型的 WAIC 通常更好(即更低)。原因之一可能是模型的一些参数随温度的高变化,这将导致更高的有效参数数,并可能给出更低的预测密度。人们可能希望两个模型之间的有效参数数量相同,因为我们可以通过将θ乘以相应的β,将带温度的模型转换为不带温度的模型,但经验证据表明并非如此。

Widely Applicable Information Criterion (WAIC) of fifty different random train/test split for the model with and without temperatures. The model without temperatures (orange) has a better WAIC, 247 with standard deviation of 12 , compared to the model with temperatures (orange), 539 with standard deviation of 60. The vertical lines are the corresponding means.
结论
下表总结了为特定任务比较两个模型类所获得的结果。具有温度的模型具有更好的精度和校准,但是需要更多的计算时间并且具有更差的 WAIC(可能由参数的变化引起)。

Summary of the mean results obtained for the metrics evaluated. The value in parenthesis is the standard deviation. The green dot indicate the better value of the two model classes while the red dots the worst value.
与精度和校准增益相比,计算时间并不令人望而却步,因此这里选择的是温度模型。在将它投入生产之前,人们可能会通过微调它来减少参数的不确定性。人们必须记住,不确定性也可能通过避免过度自信而给出更高的校准。我们看到,为了获得一个任务的模型类的质量的全貌,需要许多度量。在 AutoML 的情况下,系统会自动使用这些指标来选择最佳模型。正如我们所看到的,我们可以根据用户的需求和与模型使用相关的成本来解释它们。对数据科学家来说幸运的是,这也意味着仍然需要人类的参与。
感谢阅读
参考文献和推荐读物
[1] A.Gelman,J. Carlin,H. Stern,D. Dunson,A. Vehtari 和 D. Rubin,贝叶斯数据分析 (2013),Chapman and Hall/CRC
[2] J. Nixon,M. Dusenberry,L. Zhang,G. Jerfel,D. Tran,深度学习中的测量校准 (2019),ArXiv
[3] A. Gelman、J. Hwang 和 A. Vehtari,(2014),斯普林格统计和计算
[4] A. Vehtari,A. Gelman,J. Gabry,使用留一交叉验证和 WAIC 的实用贝叶斯模型评估(2017),Springer 统计和计算
[5] A. Sadat Mozafari,H. Siqueira Gomes,W. Leã,C. Gagné,无监督温度缩放:深度网络的无监督后处理校准方法 (2019),ICML 2019 深度学习中的不确定性和鲁棒性研讨会
概率矩阵分解
动机
“给你一个设计矩阵 X ,你会如何预测 Y ?”这个问题是基于监督学习和回归的任务的核心。这个问题假设完全了解设计矩阵 X 。在 X 中,我们在行中存储记录,在列中存储描述这些记录的特性。但是当这个矩阵被破坏时会发生什么呢?当一些观测值缺失时会发生什么?
考虑这样的设置,我们有一个 n 行 p 列的数据矩阵 X ,其中 X 始终有缺失值。

Data matrix X with missing values. The goal of matrix completion (and probability matrix factorization) is to impute or predict these missing values.
没有什么奇特的机器学习模型能拯救我们。事实上,奇特的监督学习技术依赖于对 X 的执行,就像它们做的一样好。在某种意义上,这是格言垃圾的最坏情况;垃圾出去——我们连垃圾都没有放进去!
这个问题在大多数数据分析中非常典型,最*又被重新讨论,因为许多现代数据科学问题都可以在这个框架内提出。我们将在下面的应用部分讨论其中的一些问题。
在这篇文章中,我们来看一个基于模型的方法来克服这个丢失数据的问题。我们将讨论一些令人惊讶的应用,在这些应用中,这种方法在矩阵补全之外也很有用。我们将从完全贝叶斯的角度来看这个问题,并分析在这个模型下,一个典型的 SGD 框架是如何与后验最大化紧密相连的。
应用程序
特别感兴趣的三个应用范围从数据分析的基础到推荐系统中最先进的方法。
- 数据插补- 当数据缺失时,监督学习技术很难提供高质量的解决方案。例如,在随机森林中丢失数据可能是灾难性的。输入缺失数据是任何数据分析的第一步。
 - 图像完成- 考虑这样一幅图像,其中图像的一部分已经被破坏、扭曲或看不到。如果我们希望完成图像,我们希望以使用其他观察到的像素的信息的方式来完成。智能地结合这些信息将导致更精确的图像恢复。
 - 基于模型的推荐系统- 许多协同过滤应用依赖矩阵完成算法向新用户提供推荐。如果矩阵的行是用户,列是产品,那么矩阵中的条目可以是该用户对该产品的评级。由于每个用户不会对每个产品进行评级,因此我们的目标是找到没有被用户评级但可能被高度评级的产品。通过预测这些缺失值(用户尚未评级的产品),我们可以根据用户过去的评级和其他人的评级向用户推荐新产品。
 
这些只是适合矩阵完成框架的问题的示例。在后面的帖子中,我将考虑图像完成任务,并使用下面介绍的模型构建一个推荐系统。
基于模型的方法
形式化该任务的一种方式是矩阵完成问题,其中我们试图用已知值的知识(白色图块)替换缺失的数据(蓝色图块)。我认为这是在矩阵中“堵塞漏洞”。
一种流行的基于模型的方法是假设数据矩阵 X 具有低秩,因此可以分解成两个低秩矩阵 U,V 的乘积。希望 d = rank( X )远小于 min(n,p)以降低计算复杂度。

Factorization of data matrix X into the “observation” matrix U and the “feature” matrix V.
你可以把矢量 uᵢ 想象成描述第 i - th 观察行为的矢量,把 v ⱼ想象成描述第 j - th 特征行为的矢量。必然地,我们假设词条 Xᵢⱼ = ⟨uᵢ,v ⱼ ⟩.我们的问题归结为获得 U 和v的估计值
这个问题的常见解决方案是最小化最小*方损失的优化方法。使用交替最小二乘算法可以有效地(并行地)解决这个问题。文献中也详细描述了正则化扩展和解决方案。
另一种提供更健壮的统计框架的方法是基于模型矩阵 X 的贝叶斯观点。这个名为概率矩阵分解的方法是由 Salakhutdinov 和 Mnih 在 2006 年提出的。在这个模型下,我们假设 X 的条目正态分布在内积 ⟨uᵢ,v ⱼ ⟩ 的周围,具有共同的方差。假设 Iᵢⱼ 在观察到条目时为 1,在数据值缺失时为 0,我们可以将 X 的条目的可能性写成如下。

Likelihood of the entries of X. The entries are independent normals centered around the inner product ⟨uᵢ, vⱼ⟩.
这种可能性的核心假设是:( a)X的条目是独立的;( b)每个条目是正态分布的;( c)这些条目共享一个共同的方差σ。这些假设可能适合也可能不适合某些应用,需要在实践中更仔细地考虑。
为了包含完整的贝叶斯范式,我们将先验分布放在以下形式的矩阵 U 和 V 中。

在这些先验中,我们假设(a)U和 V 的行是不相关的,(b)是正态分布的,以及(c)具有共同的方差。有了额外的先验信息,我们可以构建更多信息的先验分布,以捕捉设计矩阵 X 中观察值或特征之间的已知相关性。
后验推断
引入了矩阵 X 的先验分布和似然性后,我们可以推导出归一化常数的完整后验概率。

Full posterior distribution of matrices U and V.
在他们的工作[3]中,建议通过找到最大化该后验分布的矩阵 U 和 V 来导出最大后验估计值(MAP)。在未来,我们着眼于通过为这些模型 parameters⁴.构建 MCMC 采样器来开发完整的后验分布
最大化这个后验概率相当于最大化对数后验概率。对数后验概率具有下面给出的形式。

The log posterior up to a normalizing constant. Notice that the last two terms have built in regularization on the matrices U and V.
这样,我们的目标是最小化损失函数 L( U,V ) ,它可以写成如下形式

其中 I 是具有上面定义的 Iᵢⱼ 的 n × p 矩阵,圆积表示元素式矩阵积,使用的范数是 Frobenius 范数。
从这个损失中,我们看到我们*衡了 U 和 V 的乘积与这些矩阵相对于 Frobenius 范数的“大小”的拟合优度。我们通过调整先验方差σ、σᵤ和σᵥ来*衡拟合优度和正则化之间的权衡。这些参数可以通过交叉验证以数据依赖的方式进行选择,或者通过对这些 hyerparameters 进行先验的贝叶斯方法进行选择。
从这里我们看到,最大化对数后验概率是等价于在【2】中考虑的正则化优化方法。因此,我们看到,通过正确选择先验,概率矩阵分解方法概括了矩阵分解中的标准优化技术。
通过为 U 和 V 的行选择更复杂的先验分布,我们可以设计出类似弹性网和套索的优化问题,其中更稀疏的解是优选的。
通过优化映射解决方案
已经根据优化问题描述了 U 和 V 的 MAP 估计,我们现在考虑解决该问题的优化方法。不幸的是,这个优化问题不是凸的,所以我们不能保证随后的任何方法都有全局解。最* work⁵致力于刻画全局解的性质,这将有望增强我们对任何局部解的性质的理解。
为了获得 U 和 V 的估计,我们考虑(随机)梯度下降更新方案。虽然我们也可以考虑交替最小二乘更新,这可以通过使用迭代岭解来解决,但 SGD 方法将能够更容易地扩展到更大的数据集。
将损失函数 L( U,V ) 相对于 uᵢ 或 vⱼ 进行微分将提供感兴趣的梯度。梯度可以写成

Gradient of the loss function for each row of U and V. Stochastic gradients can be applied by using a subset of the full n observations or p features. Moreover, rows of each matrix can be updated in parallel.
其与来自正则化回归设置的岭回归估计有明确的联系。请注意,每个梯度包括 n 或 p 个元素的总和。这些总和在实践中可能很难计算,并且可能有必要通过对 n 个观测值或 p 个特征的子集(小批量)求和来使用随机梯度。
使用这些梯度,我们迭代地更新我们的估计,直到收敛。完整的算法如下所示。

A full SGD algorithm for PMF.
可以对该算法进行一些改进以提高运行时间。特别是,使用随机梯度可以大大加快计算时间。此外,每个嵌套的 for 循环都可以并行完成,并跨单元分布。 Kevin Liao 在 PySpark 上有一个关于这个的不错的帖子,我会在这里链接。
结论
至此,我们已经基本涵盖了概率矩阵分解的基础知识!这里讨论的大多数观点都在[3]中介绍过,我真的鼓励你读一读他们的论文。希望这篇文章能在这个问题和贝叶斯统计、正则化回归和正则化矩阵分解之间找到一些联系。
既然我们已经解决了所有的数学问题,是时候实现上面介绍的 SGD 算法了。在我的下一篇文章中,我将会关注图像补全的问题以及一个推荐系统。
[1]:m·尤德尔和 a·汤森。为什么大数据矩阵的排名很低? (2019),暹罗。
这种假设在许多统计和机器学习环境中非常普遍。请查看由 Udell 和 Townsend 在 2019 年完成的这项工作,其中有一个关于为什么这一假设是合理的有趣讨论。
[2]: T. Hastie 等人通过快速交替最小二乘法进行矩阵补全和低秩 SVD。(2015),机器学习研究杂志。
[3]: R. Salakhutdino 和 A. Mnihv。概率矩阵分解。 (2008),NIPS 会议录。
[4]: R. Salakhutdino 和 A. Mnihv。使用马尔可夫链蒙特卡罗的贝叶斯概率矩阵分解。(2008),2008 年机器学习国际会议。
[5]: S. Zheng 等正则化奇异值分解及其在推荐系统中的应用。(2018),ArXiv。
概率编程杂志 1:模拟事件变化
免责声明:我的来源和灵感来自《黑客的贝叶斯方法》(Cameron Davidson-Pilon),这篇文章出于非盈利原因。我只是记录我对这个新主题的学习,并在媒体上分享我的学习,以强化我自己的概念。大部分代码都是从这本书里派生出来的,我只做了很少的改动,但是我花了很大的力气来解释每个代码块是如何工作的。
问题:我们的目标是了解我们的数据是否随时间发生了变化。
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inlinecount_data = np.loadtxt("Data/txtdata.csv")
n_count_data = len(count_data)
f, ax = plt.subplots(figsize=(20, 3))
sns.barplot(np.arange(n_count_data), count_data, color = 'black');
plt.xlabel("Time (days)")
plt.ylabel("Text messages received")
plt.title("Did the user’s texting habits change over time?")
plt.xlim(0, n_count_data);

我们正在处理的数据与文本相关。我们观察和收集数据的时间段是总共 74 天,加载的数据是包含每天文本观察的向量形式。我们生成一个互补向量,记录向量中每个点的日期。这可以在上面使用 numpy arrange 函数的代码中看到。我们的目标是确定趋势是否有变化。由人类来完成这项任务将是非常具有挑战性的,因为目测数据根本无助于确定变化。所以我们将使用一些概率模型来解决这个问题。
我们如何对这些数据建模?我们的选择之一是使用泊松模型。为什么?因为这种模型可以很好地处理计数数据。

为了表示我们的模型,假设λ将在我们的数据集τ中的时间点(t)之后改变。

下一个要解决的难题是我们如何估计λ?模型假设λ可以采用任何正数的形式。指数分布提供了一个连续的密度函数,但指数分布有自己的参数,称为α。所以…

当一个随机变量 Z 具有参数为λ的指数分布时,我们说 Z 是指数的,写 Z∞Exp(λ)给定一个特定的λ,一个指数随机变量的期望值等于λ的倒数。即 E[Z|λ] = 1/λ (黑客的贝叶斯方法,卡梅伦·戴维森)
根据上述概念,将α设置为计数数据*均值的倒数。

最后τ

在数据集中持续 70 天,其中τ在每一天都是同等可能的。
在我解释下一步之前,我想分享一个关键概念。因此,泊松模型中的主要模型采用参数λ。Lambda 是每个间隔的*均事件数,它是由另一种称为指数分布的方法估计的。编程意义上的指数分布将由该特定分布的特征产生。因此,如果一个程序员调用一个分布函数,他们可以期待一个对象或向量的值。现在有了这些值,接下来发生的是泊松函数使用它,另一个生成函数。因此,泊松函数将在由指数生成器生成的λ值数组上生成值。
当我们看τ和 T 时,令人困惑的部分来了,它们的目的是什么?我们猜测模型的分布在 t 点发生变化。这与下面代码中描述的函数有关。我会在代码后解释 tau 的作用。
import pymc as pm#Alpha as described in above
alpha = 1.0/count_data.mean()# Exp distribution for lambda using alpha
lambda_1 = pm.Exponential("lambda_1", alpha)
lambda_2 = pm.Exponential("lambda_2", alpha)#Uniform distribution for tau 
tau = pm.DiscreteUniform("tau", lower=0, upper=n_count_data)#Declare a deterministic result
[@pm](http://twitter.com/pm).deterministic
def lambda_(tau=tau, lambda_1=lambda_1, lambda_2=lambda_2):
    #create a null vector of size == size(data)
    out = np.zeros(n_count_data)
    # t < tau will recieve lambda1
    out[:tau] = lambda_1
    #t > tau will recieve lambda2
    out[tau:] = lambda_2
    return out#feeding custom function to observed poisson generator
observation = pm.Poisson("obs", lambda_, value=count_data,observed=True)#declaring pymc model
model = pm.Model([observation, lambda_1, lambda_2, tau])#blackbox MCMC model for sampling
mcmc = pm.MCMC(model)
mcmc.sample(40000, 10000)#Drawing samples from mcmc model
lambda_1_samples = mcmc.trace('lambda_1')[:]
lambda_2_samples = mcmc.trace('lambda_2')[:]
tau_samples = mcmc.trace('tau')[:]
所以,发生的事情是,一个生成器被创建,它输出 1 到 70 之间的值,其中每一天都有均等的机会被抽取。想象这是一袋 70 颗红色弹珠,画一颗弹珠是 1/70。所以一定数量的随机抽取被记录下来并发送给 lambda_ function。在基于τ值的 lambda 函数中,向量 lambda 被分成将接收 lambda_1 值的左半部分和将接收 lambda_2 值的右半部分。这个过程用 lambda _i(i = 1 或 2)的不同组合来测试。然后将其转换为泊松生成器。我很难解释后面的部分,因为它涉及到使用 MCMC 方法从我们创建的条件中采样和重新采样。用最简单的话来说,我能说的是,我们有一个复杂的对象迭代来检索显示可能值的分布。
# histogram of the samples
f, ax = plt.subplots(figsize=(10, 10))#plt sublot 1 declarartion (lambda 1)
ax = plt.subplot(311)
sns.distplot(lambda_1_samples, bins=30,label="posterior of $\lambda_1$", color="#A60628")
plt.legend(loc="upper left")#declare main title
plt.title(r"""Posterior distributions of the parameters""")plt.xlim([15, 30])
plt.xlabel("$\lambda_1$ value")
plt.ylabel("Density")
#lambda1 plot ends#plt sublot 2 declarartion (lambda 2) setting similar to plot 1
ax = plt.subplot(312)
ax.set_autoscaley_on(False)
sns.distplot(lambda_2_samples, bins=30,label="posterior of $\lambda_2$", color="#7A68A6")
plt.legend(loc="upper left")
plt.xlim([15, 30])
plt.xlabel("$\lambda_2$ value")
plt.ylabel("Density")#plt sublot 2 declarartion (lambda 2)
plt.subplot(313)
w = 1.0 / tau_samples.shape[0] * np.ones_like(tau_samples)
plt.hist(tau_samples, bins=n_count_data, alpha=1,
         label=r"posterior of $\tau$", color="#467821",
         weights=w, rwidth=2.)
plt.legend(loc="upper left")
plt.ylim([0, .75])
plt.xlim([35, len(count_data)-20])
plt.xlabel(r"$\tau$ (in days)")
plt.ylabel("Probability");

做完这些,我们就能画出λI 和τ的可能值。我对这里的理论的理解仍然不是很强,但是我认为我们能够基于我们使用泊松分布产生的观察结果来产生这些分布。还有一点需要注意的是,泊松样本被观察和固定,而其他样本则没有。对观察结果的解释总结如下。
- λ1、λ2 可以分别保持大约 18 和 23 的值。
 - 基于λ分布,我们可以评论两组中存在差异,回想一下,我们将λ1 分配给组 t < τ,并且我们相应地改变了λ2。两组都采用相似的指数分布,每组的后验分布各不相同。
 - τ的正序分布是离散的。基于我们输出前的假设。
 - 第 45 天有 50%的几率表现出行为变化。
 
概率思维,一个被大多数人抛在脑后的批判性思维。

让我们用一个简单的问题来测试你是否放弃了概率思维的基本权利。当你做下一个决定时,看看你可能会错过什么。
这是我的“我们生活的算法”系列之一。见链接中另一个有趣的问题。
在深入研究细节之前,我们先来看一个思维实验。

看看上面的问题,你会怎么做选择?你会按哪个按钮?红色或绿色。
我知道你心中有一个答案,你可以找到理由来证明你的选择,但请暂时保持这个想法,直到本文结束。
请记住这些想法:
- 你应该如何解读这个问题的语境?
 - 除了按红色或绿色按钮,这个问题中还有其他选项吗?
 - 你是在做一个冲动的、启发式的决定,还是在计算每个选项的概率?
 - 如何计算两个选项的概率?
 
为什么呢?为什么我称赞概率思维是人类最关键的特质和技能之一?
答案对我来说是不言自明的。“可劫性是世界的运行规则,不仅在社会层面,也在宇宙学原理层面。”因此,能够破译这一隐藏信息的人将有机会预测未来,然后做出更好的行动决定。
The stunning nature of probability distribution
不幸的是,只有在顶峰的人才能真正理解这个信息,并通过它的信号来执行它。
出于本文的目的,我将这些人分为三个层次:
- 一级:懂得如何计算概率的人
 - 二级:能够直观地进行概率性思考的人
 - 第三级:了解概率结果并能采取行动的人
 
你在某一关获得的技能并不保证你能进入下一关。
你可以是计算概率的大师,也可以意识到概率思维,但你可能不是一个总能根据先验概率做出公*决策的人,更不用说立即采取行动了。约翰·梅纳德·凯因斯花了几十年才成为第三级。

A British economist, whose ideas fundamentally changed the theory and practice of macroeconomics and the economic policies of governments.
但是,没有学过概率理论和概率思维的人,有几个天生就是永远作用于概率结果的人。比如德州扑克的高手或者市场奇才。

我们来做一个简单的计算。
有多少人知道概率计算?
不到 10%
在这些人中,有多少人能把计算运用到日常思维中?
另外 1%。
在概率思维的人当中,有多少人能够采取行动?
不到 1%(推理,想想有多少人能执行他们的计划或策略)
于是,在世界主义者中,几千万人中只有几千个概率大师。
你可能会说,在像纽约或上海这样的大城市,千万富翁的人数超过数千。但请记住,基于“随机的普遍概率”,他们的成功更多的是运气因素,而不是战略行动。(被随机性愚弄)
风险决策中的三个关键概念
1。期望值 :一个离散随机变量的期望值是其所有可能值的概率加权*均值。换句话说,随机变量的每一个可能值都要乘以它出现的概率,然后将结果相加得到期望值。(来自维基百科)

根据这个理论,100%的机会赢得 100 万或者 50%的机会赢得 10 亿是一回事。贝叶斯定理是聪明的决策者最常用的公式之一。看看这个星球上最聪明的人的话。

塔勒布在一次投资研讨会上提到,“我相信市场有 70%的机会小幅上涨。”但在现实世界中,他做空标准普尔 500 指数,押注市场会下跌。他真正的愿景是:尽管市场有很大的增长机会,但做空是更好的选择。因为如果市场丰满了,它会大幅度下跌。
下面列出了对行为的分析:
- 市场有 70%的机会上涨,有 30%的机会下跌。
 - 但上升趋势只会是 1%,下降趋势会是 10%。
 - 因此,预期结果是:70% *1% + 30% *(-10%) = -2.3%
 - 总体而言,做空将有更好的机会获得更多利润
 
正如查理·芒格(沃伦·巴菲特的长期合作伙伴,世界上另一个聪明的头脑)所说,他和巴菲特每天所做的就是解这道简单的数学方程式。与其说是数学能力,不如说是思维模式。知道容易,执行难。那些设法训练他们的大脑像肌肉记忆一样直观地运行模型的人(芒格和巴菲特)在他们的生活中可以比我们其他人取得更大的成就。

By 2019 (in the age of technology domination and revolution), Berkshire Hathaway is the only financial service company left in the top 5 companies measured by market cap.
2。预期效用假说:该假说认为,在不确定性下,所有可能的效用水*的加权*均值将最好地代表任意给定时间点的效用。期望效用理论被用作一种工具,用来分析个人必须在不知道决策可能产生何种结果的情况下做出决策。(来自 Investopedia)

它也用来解释“圣彼得堡悖论”——另一个与概率和决策理论有关的有趣悖论。
你可以用预期效用假说来解释野心(期望值)和恐惧(风险下的决策)。
- 边际效用递减定律:同样数量的额外收入对一个已经很富有的人来说,不如对一个穷人有用。
 - 效用最大化原则:游戏者的目标不是最大化他的预期收益(金钱),而是最大化他的收益的对数(预期效用)。
 
背一下两键悖论。如果选择红色按钮,可以立即领取 100 万,同时放弃 5 亿(10 亿* 50%)选项。一方面,100 万英镑对于那些相信这笔钱可以改变他们生活的人来说是令人满意的。另一方面,大多数人都想逃避与绿色按钮相关的归零风险。仅仅是因为他们对失去一切的恐惧大于对得到 4.99 亿(10 亿* 50%-100 万)的期望。
3。前景理论: 这个理论是丹尼尔·卡内曼(2002 年诺贝尔经济学奖得主,著名著作< 思考快与慢 >)发展出来的。它挑战了预期效用理论,是行为经济学的基本原理。简而言之,它描述了个人如何以不对称的方式评估他们的得失前景。例如,对一些人来说,损失 1000 美元的痛苦只能通过赚 2000 美元的快乐来补偿。

卡尼曼总结:
- 面对导致收益的风险选择,个人是风险厌恶者,更喜欢导致较低预期效用但具有较高确定性的解决方案
 - 面对导致损失的风险选择,个人会寻求风险,更喜欢导致较低预期效用的解决方案,只要它有可能避免损失
 - 理性决策者不会受到锚/参考点的影响(损失或收益),相反,正常个体会坚持参考点。(例如,一个理性的决策者不会等到盈亏*衡时才卖出一只看跌的股票)
 
它与行为经济学研究相一致,行为经济学研究调查心理、认知、情感、文化和社会因素对个人经济决策的影响,特别是对那些非理性决策的影响。
成功的科技创业公司老板是如何做出风险决策并发展业务的?
马克·扎克伯格出生于一个中产阶级家庭。然而,他有远见地拒绝了 2006 年雅虎 10 亿美元的收购要约,当时该公司正经历一段困难时期。

这是一个艰难的决定,几年后,马克告诉记者,在他做出决定的一年内,所有的高管都离开了公司。
马克·扎克伯格面临的问题很简单,“10 亿美元的即时收益还是几年内将公司增长到 1000 亿美元的微小机会?”这与我们之前讨论的“纽扣问题”非常相似,尽管马克在现实世界中将会经历更加残酷的惩罚。
对他来说,秘诀不是在 10 亿或 1000 亿之间做出选择,而是决定坚持你的梦想,或者用它来换取即时的满足。
具有讽刺意味的是,这件事发生几年后,一个年轻人拒绝了脸书对他的创业公司 30 亿英镑的收购。他叫埃文·斯皮格尔,Snapchat 的联合创始人。

历史会重演。年轻的硅谷企业家总是按绿色按钮。
“红色或绿色按钮”问题的可能答案
- 根据期望值理论,人们应该选择绿色按钮,因为它的期望值是 5 亿(10 亿* 50%)
 - 但对于风险承受能力较低的人来说,损失 100 万的想法是无法忍受的,红色按钮将是正确的选择。
 - 一个豁达的回答,如果你有“选择权”,你可以把这个“权利”以 5 亿甚至更低的价格卖给对风险(归零)有很高容忍度的人。
 - 进一步优化上面的答案,把“选择权”卖 100 万作为首期,求买家分红赢 10 亿。
 - 再进一步,利用这种“选择权”,重新包装成公开发行的彩票。一张票 2 美元,总共 20 亿张票。获胜者可以带 10 亿回家。这种模式风险低,利润高。(但也是最难执行的)
 
终极答案
在我们生活中遇到的每个问题(或多项选择)中都有隐藏的选项。有些人可以破译信息,并找到一个新的路径来打破悖论。

我们可以选择绿色按钮或红色按钮。但是有没有一个终极的方法来将我们现在的机会货币化呢?
最后一个选择,把“选择权”卖给 VC 或者 PE。利用资本偏好冒险、追逐高额利润的行为。通过估值调整机制分享 100 万到 5 亿之间的利息。
这是通往财富世界的秘密路径之一。对于渴望的年轻心灵来说,他们不需要屈服于 100 万的欲望,失去 5 亿的机会。他们所需要的只是一个边界视野,让看到更大的图景。
最终,你如何解读“情境 ( 搜索空间)”和“选项(概率),”以获得更好的决策和计划周密的执行模式,将决定你在“财富食物链”中的位置
关于我,我是👧🏻现居澳大利亚墨尔本。我学的是计算机科学和应用统计学。我对通用技术充满热情。在咨询公司做 AI 工程师👩🏻🔬,帮助一个组织集成人工智能解决方案并利用其创新力量。在LinkedIn上查看更多关于我的内容。
数据分析中隐私的概率工具

Photo by Stephen Dawson on Unsplash
我们将继续我们的旅程来学习差分私有算法,这一次探索更多的概率工具。
在上一篇文章中,我们学习了如何使用大数理论和概率来设计差分私有算法。
我鼓励您在继续学习之前查看一下,以便更好地理解本教程的范围。
我们将继续探索学习隐私保护数据分析的技术,更深入地挖掘…
towardsdatascience.com](/a-coin-some-smokers-and-privacy-in-data-analysis-1339b83ede74)
如果您阅读了本系列的上一篇文章,您已经知道任何随机化算法 M 都可以是( ε,δ)差分私有算法,,如果它满足这样的性质。
这种方法的核心特性之一是在进行任何分析之前,甚至在将数据放入数据库之前,向数据本身注入噪声。像这样给数据引入随机性在隐私保护数据分析中相当常见,事实上它有一个专门的名字叫做局部差分隐私。

Photo by Franki Chamaki on Unsplash
然而,仅仅为了防止数据被对手窃取而破坏我们的数据的想法听起来非常妥协。一定有别的办法。
此时我们应该想到的两个问题是:
- 本地差分隐私是防止隐私数据泄露的唯一方法吗,有什么方法可以在不损坏我们数据的情况下提供隐私?
 - 除了随机化回答,还有其他算法可以解决这个保护隐私的数据分析问题吗?
 
我们将在本文中尝试解决这两个问题。
全球差异隐私—简介:
我们已经知道,在局部差分隐私的情况下,我们向输入数据点添加噪声。因此,每个人都可以向自己的数据中添加噪声,从而完全消除了信任数据所有者或管理者的需要。我们可以说,在这种环境下,个人隐私得到了最大程度的保护。
另一方面,全局差分隐私给数据库的查询输出增加了噪声。因此,在这种情况下,我们有一个包含所有敏感信息的数据库,但是对该数据库的任何查询都不一定会生成真实的结果,因为这些结果是错误的。
但是,如果局部差异隐私更能保护个人隐私信息,为什么还要使用全局差异隐私呢?
如果你还记得上一篇文章,你应该知道,准确性和隐私之间总是有一个权衡。因此,如果你的目标是更多的隐私,它会来找你,但代价是失去一些准确性。考虑到这一点,本地和全局差异隐私的唯一区别在于:
如果数据所有者值得信任,那么对于相同级别的隐私保护,全局差异隐私会产生更准确的结果。
一个重要的问题是要有一个值得信赖的所有者或管理者,如果找到了,我们就可以在相同的隐私级别上有更好的准确性,因为在全球差异隐私的设置中,我们不再破坏我们的数据,而是将所需的噪声添加到我们对该数据库的查询的输出中。

Difference b/w Local and Global Privacy Settings
上面给出的图表毫不费力地解释了这一点。然而,我们现有的保护隐私的方法没有为应用全局差分隐私提供空间,因此我们需要设计一种不同的算法来做到这一点。
保护隐私的拉普拉斯机制:
在上一篇文章中,我们了解了一种实现差分隐私的技术,我们设计的算法给了数据生成器一种 似是而非的可否认性 的感觉,从而允许它们向数据中添加噪声。
在这里,我们将了解一个更常用的工具,它为我们提供差分隐私,拉普拉斯机制,,它为实(向量)值查询提供差分隐私。这些查询将数据库映射到一些实数,而不是整数值。
ℓ1-敏感度可以再次用于确定我们可以多准确地回答数据库的查询,因此,直观地,我们必须引入响应中的不确定性以隐藏单个个体的参与。因此,拉普拉斯机制帮助我们在全局差分隐私的设置下保护隐私。

函数(查询)的敏感度也告诉我们,为了保护隐私,我们必须对其输出进行多大程度的扰动,它为我们提供了查询输出中最大可能变化的度量。拉普拉斯机制将简单地计算 func ,并用从拉普拉斯分布中提取的噪声扰动每个坐标。噪声的标度将被校准到 func 的灵敏度(除以 ε ,这被称为β。
β= Lap(δf/ε)

From the Algorithmic Foundation of Diff. Privacy

Formalizing Laplace mechanism
因此,在拉普拉斯机制的情况下,不是在查询之前将噪声添加到数据,而是将该噪声添加到对数据库的查询的输出。拉普拉斯机制只是简单地把对称连续分布的噪声加到真答案上,如上图所示。

Photo by Markus Spiske on Unsplash
这里需要理解的重要一点是,在拉普拉斯机制的情况下,这种对称连续分布以零为中心。
辛西娅·德沃克(Cynthia Dwork)的《差分隐私算法基础》( algorithm Foundation of Differential Privacy)中提供了为什么拉普拉斯机制是( ε,0)差分隐私算法的有力证明。
总结:
在本文中,我们了解了局部和全局差分隐私之间的差异,并介绍了一种使用后者的设置来实现差分隐私的算法。
本系列接下来的几篇文章将更侧重于使用差分隐私进行深度学习。
敬请关注。暂时快乐学习。
PS。这是我关于媒体的第三篇文章,所以欢迎任何反馈和建议。
资源:
- https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf
 - 【http://www.cis.upenn.edu/~ahae/papers/epsilon-csf2014.pdf
 - http://dimacs . Rutgers . edu/~ Graham/pubs/slides/priv db-tutorial . pdf
 - https://arxiv.org/pdf/1808.10410.pdf
 - https://towards data science . com/understanding-differential-privacy-85ce 191 e 198 a
 - https://towards data science . com/a-coin-some-smokers-and-privacy-in-data-analysis-1339 b 83 ede 74
 - https://towards data science . com/Mr-x-网飞和数据分析隐私-f59227d50f45
 
概率不是可预测性
天气预报、癌症诊断、掷硬币

假设你正在看晚间新闻(或者更有可能是你的手机告诉你),明天有 30%的可能性会下雨。明天,你带伞了吗?
这似乎是一个良性的问题,但我们解释概率的方式对我们如何决策、做生意和生活有着真正的影响。它
在下文中,我们将分解像这样的概率和统计数据的核心含义,以及我们如何围绕这种不确定性做出决策。
当统计变成概率
让我们用同样的例子——明天有 30%的可能性下雨。一般来说,像这样的陈述使用的是推理统计学:它们观察一个事件在过去发生的频率,并使用推理将其应用于未来。

Via windy.com.
假设在过去的 100 次特定天气模式中,有 30 次第二天下雨。如果今天气象学家看到这种模式,他或她可能会说:
“我见过 30%的这种模式,第二天就下雨了。所以明天有 30%的可能性会下雨。”
——某处某气象学家
然而,这并不是概率(注意:统计数据是历史频率,概率是未来的可能性)的意思。它实际上的意思大致是:
基于我在过去 100 次中见过 30 次这种模式,第二天就下雨了,我 推断在接下来的 100 次我看到这种模式时,第二天会下雨 30 次。
假设我今天看到了模式,有 30%的几率这是我看到模式的一天,第二天下雨。
——任何地方都没有气象学家
我们马上看到这是一个更复杂的声明。重要的是,我们看到了历史观察(即统计)是如何转化为前瞻性概率的。不幸的是,我们不知道明天是否会下雨——知道概率并不能帮助我们预测明天是否带伞。毕竟,明天不会发生 100 次,只会发生一次。
概率和离散事件
天气是每天都会发生的事情,所以从长远来看,用概率来描述天气可能是合适的。让我们来看看一些不相关的事情:一个接受癌症诊断的病人。

当患者被诊断患有癌症时,他们通常会问(或被医生告知)的一个问题是“我的机会有多大?”这经常被用来帮助病人评估诊断的严重性。直觉上,我们理解“80%的类似患者在 10 年后存活”是比“8%的机会活到 10 年”更好的预后。然而,我们应该进一步展开这个问题,以真正理解这些意味着什么。
为了帮助我们,我使用了纪念斯隆-凯特琳癌症中心发表的一个模型(以及他们发表的其他几个模型),显示了结肠直肠癌手术后 5 年的存活率。在模型中,我输入了一个假设的 N1 期 T3 期癌症,已经扩散到 16 个淋巴结中的 2 个,具有中度分化,且为 27 岁男性。该模型正确地指出,我在这里还要补充一点,“预测工具不能用来替代任何健康状况或问题的医疗建议、诊断或治疗。”
那么,结果如何呢?

“这个数字以百分比的形式显示了您在接受结肠癌完全切除术(手术切除所有癌组织)后至少存活 5 年的概率。这一概率意味着,对于每 100 名像你这样的患者,我们预计有 85 人在手术后存活 5 年,15 人将在 5 年内死亡。”
我们先来看第二句:“每 100 个像你这样的病人,我们预计有 85 个会在手术后存活 5 年。”这与我们的降雨示例非常匹配,假设的气象学家指出,对于特定的天气模式,每 100 天就会有 30 天降雨。MSK 的模型使用过去的患者数据,并对 100 名患者的未来生存可能性做出推断,我们的患者只是其中之一。然后(甚至在此之前),MSK 跳出来说,由于 100 个病人中有 85 个会在 5 年后存活,我们的病人有 85%的机会存活 5 年。
但是这种跳跃有一个问题——它没有声音。我们的病人患的不是 100 种癌症中的 85 种,而是一种癌症。也许对医生来说,知道如果医生有 100 个病人,他可以期望 85 个存活 5 年是有用的,但是这并不意味着对每个病人都有用。这不能提供任何类型的可预测性——它不能告诉病人他们是在 85%还是在 15%的关键信息,医生当然不能说。
这是保罗·卡兰尼蒂在他的回忆录中写的当呼吸变成空气:
与其说“中位生存期是 11 个月”或“你有 95%的机会在两年内死亡”,我会说,“大多数病人能活几个月到几年。”对我来说,这是一个更真实的描述。问题是你不能告诉一个病人她处在曲线的哪个位置:她会在六个月还是六十年后死去?我开始相信,比你能做到的更精确是不负责任的。
其实,连数学家都在争论这个。具体来说,“频繁主义者”坚持认为概率只适用于事件,就像掷硬币一样,可以被广泛重复(理论上无限重复)。因为抛硬币和天气有规律地反复发生,你可以指定一个概率,因为随着时间的推移,你会做出足够的预测来与指定的概率进行比较。然而,对于癌症预测,以及其他离散事件,如超级碗(以及超级碗的硬币投掷)和总统选举,不会有数百个事件被重复——只有一个。

再者,概率不是可预测性。知道了一枚公*的硬币正面朝上的概率是 50%,你在不可能准确预测下一次掷硬币。也许你可以*均预测 100 次翻转中有多少次是正面,但你无法确定地预测下一次翻转。

Huffington Post’s 2016 presidential election probabilities, for posterity.
这种思考方法可能会增加混乱,因为它看起来不太精确,而且确实如此!但它让我们面对未来的不确定性。我们常常过于自信,因为概率让不可能的事情看起来不可能,而事实上它们极有可能发生。邓肯·沃茨在中写道,这是企业向应急战略发展的一个原因,一切都很明显**
因此,如果连[数学家]都难以理解“明天下雨的概率是 60%”这句话的含义,那么我们其他人也能理解就不足为奇了。
延伸阅读:
不*衡数据集的概率校准
对欠采样方法的一点建议

Photo by Bharathi Kannan on Unsplash
当我们试图为现实世界的问题建立机器学习模型时,我们经常会面临不*衡的数据集。重采样方法,尤其是欠采样是克服类别不*衡最广泛使用的方法之一(我在另一篇中的文章中也展示了那些重采样方法是如何在我的硕士论文中起作用的)。然而,由于训练和测试集中不同的类别分布,实现这种方法倾向于增加假阳性。这会使分类器产生偏差并增加假阳性。[1] Pozzolo 等人,(2015) 认为可以利用贝叶斯最小风险理论来修正由于欠采样而产生的偏差。这有助于我们找到正确的分类阈值。
内容
- 概率校准是如何工作的?
 - 实验
 - 结论
 
1.概率校准是如何工作的?

Photo by John Schnobrich on Unsplash
如上所述,欠采样会导致后验概率出现偏差。这是由于随机欠采样的特性,其通过随机移除它们来缩小多数类,直到两个类具有相同数量的观察值。这使得训练集的类分布不同于测试集中的类分布。那么,在这个问题上,使用贝叶斯最小风险理论的概率校准究竟是如何工作的呢?—这种方法的基本思想是通过考虑欠采样率 β 考虑来试图减少/消除随机欠采样率引起的偏差。让我们来看看一些定义:
设 ps 为随机欠采样后预测为正类的概率;

,而 p 是预测给定特征的概率(不*衡)。我们可以把 ps 写成 p 的函数;

,其中 β 为欠采样情况下选择负类的概率,可表示如下。

,可以这样写

上式可解出 p 并表示如下。

因此,在应用欠采样率 β、之后,我们可以计算出 p ,这是无偏概率。
这个阈值可以是:

,这是数据集中正类的概率。

简要介绍了利用贝叶斯最小风险理论进行概率校准的方法。现在我们将继续看看这是如何在一个代码示例中工作的。
2.例子

Photo by Nathan Dumlao on Unsplash
在本节中,我们将看到概率校准技术如何在 Kaggle 上著名的信用卡欺诈数据集上对二进制分类问题进行建模。该数据集由 28 个 PCA 特征(全部匿名)和数量特征组成。目标特征是二元的,要么是诈骗,要么不是。正类占整个数据集的 0.17%,严重不*衡。让我们看看这个例子的代码。
首先,导入包。
## config
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import io, os, sys, types, gc, re
from sklearn import preprocessing
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import average_precision_score,
confusion_matrix, precision_score, recall_score, precision_recall_curve, f1_score, log_loss
from sklearn.decomposition import PCA
pca = PCA(n_components=1,random_state=42)
from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler(random_state=42)
from imblearn.ensemble import BalancedBaggingClassifier
from src.functionalscripts.BMR import *def make_prediction(model,X,threshold):
    y_pred = model.predict_proba(X)
    y_predicted = np.where(y_pred[:,1]>=threshold,1,0)
    return y_pred, y_predicteddef evaluation(true, pred):    
    print('F1-score: ' + str(round(f1_score(true,pred),4)), '\n'
'Precision: ' + str(round(precision_score(true,pred),4)), '\n'
'Recall: ' + str(round(recall_score(true,pred),4)), '\n'
'Log loss: ' + str(round(log_loss(true,pred),4)), '\n'
'Cohen-Kappa: ' + str(round(cohen_kappa_score(true,pred),4)), '\n'
'Confusion matrix:' + '\n' + str(confusion_matrix(true,pred)))
现在读取数据集。
# read the data
df = pd.read_csv('src/resources/data/creditcard.csv')
这是数据集的前几行。

First few rows of the dataset
Class 列是我们的目标变量,Amount 列是交易金额。现在看正班的比例。
# The percentage of positive class in this dataset
len(df[df['Class']==1])/len(df)
正面类就是我上面说的,0.17%。现在我们将继续参观模型建筑。我们将使用逻辑回归来看看。让我们将 Amount 列标准化,并分成训练和测试数据集。
# Normalise the Amount feature
df['amt'] = preprocessing.normalize(np.array(df['Amount']).reshape(-1,1),
norm='l2')
现在,数据准备好了,让我们分成训练(整个数据的 80%)和测试(整个数据的 20%)数据集,并实现随机欠采样。
# Split the dataset into train and test, and drop unnecessary features
tr, te = train_test_split(df.drop(['Amount','Time'],1), test_size=.2,random_state=42)# Rundom Under Sampling (RUS)
tr_x_rus, tr_y_rus = rus.fit_resample(tr.drop(['Class'],1),tr.Class)
我们可以在随机欠采样后检查训练、测试和训练集中类的分布。
# See the class distribution with features
feats_distribution_rus = pd.DataFrame(pca.fit_transform(tr_x_rus),columns=['after']).reset_index(drop=True)
feats_distribution_rus['Class'] = tr_y_russns.regplot(x='after',y='Class',data=feats_distribution_rus,logistic=True, n_boot=500, y_jitter=.03)
plt.title('Class distribution of training set after undersampling')
plt.show()




Class distributions of before and after undersampling and test set comparison
左上角是训练集的分布,左下角和右边是随机欠采样后的分布,都是测试集(用于比较)。y 轴表示类别,1 表示交易是欺诈,否则不是欺诈。我们可以在训练集和测试集中看到类似的分布,因为它们是通过随机采样创建的。另一方面,在随机欠采样后的训练集中,显示出与其他分布完全不同的分布。让我们看看这种差异是如何影响分类器的。
现在建立模型。为了比较,让我们看看 RUS 装袋(随机欠采样+装袋)的性能。
# Logistic regression
logit = LogisticRegression(random_state=42,solver='lbfgs',
max_iter=1000)# Rundom Under Sampling (RUS)
tr_x_rus, tr_y_rus = rus.fit_resample(tr.drop(['Class'],1),tr.Class)
logit_rus = logit.fit(tr_x_rus,tr_y_rus)# RUS bagging
bc = BalancedBaggingClassifier(base_estimator=logit,random_state=42)
logit_bc = bc.fit(tr.drop(['Class'],1),tr.Class)
现在,我们使用贝叶斯最小风险来实现概率校准方法。这里我们创建 beta(少数选择比率)、tau(阈值)和校准函数。
# BMR (Bayes Minimum Risk) implementation
# Pozzolo et al., 2015, Calibrating Probability with Undersamplingclass BMR:
    def beta(binary_target):
        return binary_target.sum()/len(binary_target) def tau(binary_target, beta):
        return binary_target.sum()/len(binary_target) def calibration(prob, beta):
        return prob/(prob+(1-prob)/beta)
将这些校准技术应用于 RUS 和 RUS·鲍格的预测概率。
# Calibration
beta = BMR.beta(tr.Class)
tau = BMR.tau(tr.Class,beta)# with RUS
y_pred_calib_rus = BMR.calibration(prob=logit_rus.predict_proba(te.drop(['Class'],1))[:,1],beta=beta)y_predicted_calib_rus = np.where(y_pred_calib_rus>=tau,1,0)# wtih RUS bagging
y_pred_calib_bc = BMR.calibration(prob=logit_bc.predict_proba(te.drop(['Class'],1))[:,1],beta=beta)y_predicted_calib_bc = np.where(y_pred_calib_bc>=tau,1,0)
现在我们有了所有的预测,让我们评估它们,看看它们的表现如何。我将 RUS 和 RUS 装袋模型的阈值设为 0.5。
# Evaluation
## Random Under Sampling (RUS)
y_pred_rus, y_predicted_rus = make_prediction(model=logit_rus, X=te.drop(['Class'],1), threshold=.5)
evaluation(te.Class, y_predicted_rus)## RUS + Bagging
y_pred_bc, y_predicted_bc = make_prediction(model=logit_bc, X=te.drop(['Class'],1), threshold=.5)
evaluation(te.Class, y_predicted_bc)## Calibration with Rundom undersampling
evaluation(te.Class, y_predicted_calib_rus)## Calibration with RUS bagging
evaluation(te.Class, y_predicted_calib_bc)
这是结果。正如我们所料,有这么多的误报,这一点我们可以从精度得分中看出。

哦,等等,概率校准根本没有改变什么?一定有什么不对劲。让我们看看校准后的 RUS 装袋预测概率的预测分布。蓝色垂直线是通过校准的 RUS 装袋预测概率的*均值,红色垂直线是通过 RUS 装袋模型预测概率的*均值。显然,它们的*均值相差很远,因为校准后的概率*均值为 0.0021,而校准前为 0.5。考虑到正类在整个数据集中占 0.17%,校准后的概率似乎非常接*实际分布。

因此,如果我们修改阈值,效果应该会更好,这里我们可以看到修改阈值后的结果。在 RUS 模型上校准之前和校准之后的阈值被设置为 0.99,并且用 RUS 装袋的校准被设置为 0.8。

Summary of results after thresholds are modified
正如我们所看到的,在校准后,这些分数得到了提高,尤其是在随机欠采样模型上校准前后的差异非常显著。
因此,通过使用概率校准来校正有偏差的概率,我们可以看到性能的提高。
3。结论和想法
在这篇博文中,我们浏览了 Pozzolo 等人(2015)。这回答了我们的经验,即应用随机欠采样后会有更多的假阳性。观察重采样方法如何使分布产生偏差是非常有趣的。这将导致时间序列问题中的类似问题,因为我们预测的目标变量可能与我们训练模型时大不相同。
看看这种方法是否适用于不同类型的分类器(如基于树的分类器或神经网络分类器)以及不同类型的重采样方法,会很有意思。
这篇文章的代码可以在我的 GitHub 页面上找到。
包裹
- 引入重采样会导致后验分布出现偏差
 - 利用贝叶斯最小风险理论引入概率校准方法(Pozzoli,et al. 2015)
 - 展示了这种方法的例子
 - 证实了该方法纠正了偏差,改善了模型结果
 
参考
[1] Pozzolo 等,不*衡分类欠采样的概率校准 (2015),2015 IEEE 计算智能研讨会系列
每个数据科学家都应该知道的 5 种概率分布

Probably a nice dashboard. Source: Pixabay.
概率分布就像 3D 眼镜。它们允许一个熟练的数据科学家识别完全随机变量中的模式。
在某种程度上,大多数其他数据科学或机器学习技能都是基于对数据概率分布的某些假设。
这使得概率知识成为你作为统计学家构建工具包的基础的一部分。如果你想出如何成为一名数据科学家的第一步。
事不宜迟,让我们切入正题。
什么是概率分布?
在概率统计中,随机变量是取随机值的东西,比如“我看到的下一个人的身高”或者“我下一碗拉面里厨师的头发数量”。
给定一个随机变量 X ,我们希望有一种方法来描述它取哪些值。除此之外,我们还想描述一下变量取某个值** x 的可能性有多大。**
例如,如果 X 是“我的女朋友有多少只猫”,那么这个数字很有可能是 1。有人可能会说,有非零的概率,值甚至可能是 5 或 10。
然而,一个人不可能(因此也不可能)有消极的猫。
因此,我们希望有一种明确的数学方式来表达变量 X 可能取的每一个可能值 x ,以及事件 (X= x) 发生的可能性有多大。
为了做到这一点,我们定义了一个函数 P ,使得 P(X = x) 是变量 X 具有值 x 的概率。
我们也可以要求 P(X < x), or P(X > x ),要求间隔而不是离散值。这将很快变得更加重要。
P 是变量的密度函数,表征该变量的分布。
随着时间的推移,科学家们已经认识到自然界和现实生活中的许多事情往往表现相似,变量共享一个分布,或具有相同的密度函数(或类似的函数改变其中的一些常数)。
有趣的是,为了让 P 成为一个真实的密度函数,有些东西必须适用。
- P(X = X)<= 1为任意值 x 。没有比确定更确定的了。
 - P(X =x) > = 0 为任意值 x 。一件事可能是不可能的,但可能性不会比那更小。
 - 而最后一个:所有可能值X的 P(X=x) 的总和为 1 。
 
最后一个意思是“X 取宇宙中任何值的概率,因为我们知道它会取某个值”。
离散与连续随机变量分布
最后,随机变量可以被认为属于两组:离散的和连续的随机变量。
离散随机变量
离散变量有一组离散的可能值,每个值都有非零概率。
例如,当掷硬币时,如果我们说
X = "1 如果硬币是正面,0 如果是反面"
那么 P(X = 1) = P(X = 0) = 0.5 。
然而,请注意,离散集合不必是有限的。
一个几何分布,用于模拟在 k 重试之后发生概率为p的某个事件的几率。
它的密度公式如下。

其中 k 可以取任意一个概率为正的非负值。
注意所有可能值的概率总和仍然是加起来是 1 。
连续随机变量
如果你说
X = "从我头上随机拔下的一根头发的长度,单位为毫米(不四舍五入)"
X 可以取哪些可能的值?我们可能都同意负值在这里没有任何意义。
然而,如果你说它正好是 1 毫米,而不是 1.1853759…或类似的东西,我会怀疑你的测量技能,或你的测量误差报告。
一个连续的随机变量可以在给定的(连续的)区间内取任何值。
因此,如果我们给所有可能的值分配一个非零概率,那么它们的总和不会等于 1** 。**
为了解决这个,如果 X 是连续的,我们为所有的 k 设置 P(X=x) = 0 ,取值取值 X 改为分配一个非零的机会。
为了表示 X 位于值 a 和 b 之间的概率,我们说
P(a<X<b)。
为了得到连续变量 X 的 P(a < X < b) ,而不是仅仅替换密度函数中的值,您将对从 a 到 b 的 X 的密度函数进行积分。
哇,你已经通过了整个理论部分!这是你的奖励。

Source: pixabay.
现在你知道什么是概率分布了,让我们来学习一些最常见的概率分布吧!
伯努利概率分布
具有伯努利分布的随机变量是最简单的变量之一。
它代表一个二元事件:“这发生了”vs“这没发生”,取一个值 p 作为它的唯一参数,它代表事件发生的概率****。
具有参数为 p 的伯努利分布的随机变量 B 将具有以下密度函数:
P(B = 1) = p,P(B =0)= (1-p)
这里 B=1 表示事件发生了, B=0 表示没发生。
注意这两个概率加起来都是 1,因此 B 不可能有其他值。
均匀概率分布
有两种均匀随机变量:离散的和连续的。
一个离散均匀分布将取一组(有限)值 S ,并给它们中的每一个分配一个概率 1/n ,其中 n 是 S 中元素的数量。
这样,举例来说,如果我的变量 Y 在{1,2,3}中是一致的,那么有 33%的几率出现这些值。
在骰子中可以找到离散均匀随机变量的一个非常典型的例子,其中典型的骰子具有一组值{1,2,3,4,5,6}。
一个连续均匀分布取而代之,只取为参数,并在它们之间的区间内给每个值分配相同的密度。
这意味着 Y 在区间(从 c 到 d )中取值的概率与其大小相对于整个区间( b-a 的大小成比例。
因此,如果 Y 均匀分布在 a 和 b 之间,则

这样,如果 Y 是 1 到 2 之间的均匀随机变量,
Python 的random包的random方法采样 0 到 1 之间的均匀分布的连续变量。
有趣的是,可以证明给定一个均匀随机值生成器和一些演算,可以对任何其他分布进行采样。
正态概率分布

Normal Distributions. source: Wikipedia
正态分布变量在自然界如此普遍,它们实际上是。这就是这个名字的由来。
如果你把你所有的同事聚集在一起,测量他们的身高,或者称他们的体重,并把结果绘制成柱状图,很可能会接*正态分布。
当我向您展示探索性数据分析示例时,我实际上看到了这种效果。
还可以看出,如果您从任意随机变量中抽取一个样本,然后对这些测量值进行*均,并多次重复该过程,该*均值也将具有一个正态分布。这个事实非常重要,它被称为统计学的基本定理。
正态分布变量:
- 是否对称,以*均值为中心(通常称为 μ )。
 - 可以取真实空间上的所有值,但只有 5%的时间偏离标准值两个 sigmas。
 - 到处都是和。
 
大多数情况下,如果你测量任何经验数据,并且它是对称的,假设它是正态的会有点用。
例如,滚动 K 骰子,将结果相加,将会得到非常正常的分布。
对数正态概率分布

Lognormal distribution. source: Wikipedia
对数正态概率分布是正态概率分布的较小的,不太常见的姐妹。
如果变量 Y = log(X) 遵循正态分布,则称变量 X 为对数正态分布。
当绘制成直方图时,对数正态概率分布是不对称的,如果它们的标准偏差更大,这种情况会变得更加严重。
我认为对数正态分布值得一提,因为大多数基于货币的变量都是这样的。
如果你观察任何与金钱相关的变量的概率分布,比如
- 某银行最*一次转账的金额。
 - 华尔街最*的交易量。
 - 一组公司给定季度的季度收益。
 
它们通常不具有正态概率分布,而是表现得更接*于对数正态随机变量。
(对于其他数据科学家:如果你能想到你在工作中遇到的任何其他经验对数正态变量,请加入评论!尤其是财务之外的任何事情)。
指数概率分布

Source: Wikipedia
指数概率分布也随处可见。
它们与一个叫做泊松过程的概率概念紧密相关。
直接从维基百科上偷来的,泊松过程是“一个事件以恒定的*均速率连续独立发生的过程”。
这意味着,如果:
- 你有很多事情要做。
 - 它们以一定的速率发生(该速率不会随着时间而改变)。
 - 仅仅因为一件事发生了,另一件事发生的可能性不会改变。
 
然后你有一个泊松过程。
一些例子可能是对服务器的请求,超市中发生的交易,或者在某个湖中钓鱼的鸟。
想象一个频率为λ的泊松过程(比如,事件每秒发生一次)。
指数随机变量模拟一个事件发生后,下一个事件发生所需的时间。
有趣的是,在泊松过程中,一个事件可能发生在 0 到无限时间 ( 概率递减)之间的任何时间间隔。
这意味着不管你等了多长时间,该事件都有非零的几率不会发生。这也意味着它可能在很短的时间间隔内发生多次。
在课堂上,我们曾经开玩笑说公交车到站是泊松过程。我认为当你向某些人发送 WhatsApp 消息时的响应时间也符合标准。
然而,λ参数调节事件的频率。
它将使事件发生的预期时间****以某个值为中心。
这意味着如果我们知道每 15 分钟就有一辆出租车经过我们的街区,尽管理论上我们可以永远等下去,但我们很可能不会等超过 30 分钟。
指数概率分布:在实践中
以下是指数分布随机变量的密度函数:

假设您有一个来自变量的样本,并想看看它是否可以用指数分布变量来建模。
最佳 λ参数可以很容易地估计为采样值*均值的倒数。
指数变量非常适合建模任何概率分布,这些概率分布非常罕见,但是有巨大的(和均值突变的)异常值。
这是因为它们可以取任何非负的值,但是集中在较小的值上,随着值的增加频率降低。
在一个异常值特别多的样本中,你可能想要估计λ作为中值而不是*均值,因为中值对于异常值更加稳健。你的里程可能会有所不同,所以要有所保留。
结论
总而言之,作为数据科学家,我认为学习基础知识对我们来说很重要。
概率和统计可能不像深度学习或无监督机器学习那样华而不实,但它们是数据科学的基石。尤其是机器学习。
以我的经验来看,在不知道特征遵循哪种分布的情况下,给机器学习模型提供特征是一个糟糕的选择。
记住无处不在的指数和正态概率分布以及它们较小的对应物,对数正态分布也是很好的。
在训练机器学习模型时,了解它们的属性、用途和外观是改变游戏规则的。在进行任何类型的数据分析时,记住它们通常也是好的。
你觉得这篇文章有用吗?这些都是你已经知道的东西吗?你学到新东西了吗?请在评论中告诉我!
在 Twitter 上联系我 ,Mediumofdev . to如果有任何你认为不够清楚的事情,任何你不同意的事情,或者任何明显错误的事情。别担心,我不咬人。
原载于 2019 年 6 月 17 日http://www . data stuff . tech。
数据科学中的概率分布
介绍数据科学中一些最常用的概率分布,并附有实际例子。

Photo by Robert Stump on Unsplash
介绍
拥有扎实的统计背景对数据科学家的日常生活大有裨益。每当我们开始探索一个新的数据集时,我们需要首先做一个探索性数据分析(EDA) ,以便对某些特性的主要特征有一个大致的了解。如果我们能够了解数据分布中是否存在任何模式,我们就可以定制我们的机器学习模型,以最适合我们的案例研究。这样,我们将能够在更短的时间内获得更好的结果(减少优化步骤)。事实上,一些机器学习模型被设计成在一些分布假设下工作得最好。因此,了解我们正在使用哪些发行版,可以帮助我们确定哪些模型最适合使用。
不同类型的数据
每次我们处理数据集时,我们的数据集代表来自人群的样本。使用这个样本,我们可以试着理解它的主要模式,这样我们就可以用它来预测整个人口(即使我们从来没有机会检查整个人口)。
假设我们想预测给定一套特征的房子的价格。我们可能能够在网上找到旧金山所有房价的数据集(我们的样本),在进行一些统计分析后,我们可能能够对美国任何其他城市(我们的人口)的房价做出相当准确的预测。
数据集由两种主要类型的数据组成:数值型(例如整数、浮点数)和分类型(例如姓名、笔记本电脑品牌)。
数值数据还可以分为另外两类:离散和连续。离散数据只能取某些值(如学校的学生人数),而连续数据可以取任何实数值或分数值(如身高和体重的概念)。
从离散随机变量中,可以计算出概率质量函数,而从连续随机变量中可以推导出概率密度函数。
概率质量函数给出了变量可能等于某个值的概率,相反,概率密度函数值本身不是概率,因为它们首先需要在给定范围内积分。
自然界中存在许多不同的概率分布(图 1),在本文中,我将向您介绍数据科学中最常用的概率分布。

Figure 1: Probability Distributions Flowchart [1]
在整篇文章中,我将提供关于如何创建每个不同发行版的代码片段。如果您对其他资源感兴趣,可以在 this my GitHub repository 中找到。
首先,让我们导入所有必需的库:
二项分布
伯努利分布是最容易理解的分布之一,并且可以用作推导更复杂分布的起点。
这种分布只有两种可能的结果和一次试验。
一个简单的例子可以是投掷一枚有偏/无偏的硬币。在这个例子中,结果可能是正面的概率可以被认为等于反面的 p 和 (1 - p) (包含所有可能结果的互斥事件的概率需要总和为 1)。
在图 2 中,我提供了一个有偏差硬币的伯努利分布的例子。

Figure 2: Bernoulli distribution biased coin
均匀分布
均匀分布可以很容易地从伯努利分布推导出来。在这种情况下,可能允许无限数量的结果,并且所有事件发生的概率相同。
作为一个例子,想象一个公*的骰子滚动。在这种情况下,有多个可能的事件,每个事件发生的概率相同。

Figure 3: Fair Dice Roll Distribution
二项分布
二项式分布可以被认为是遵循伯努利分布的事件结果的总和。因此,二项分布用于二元结果事件,并且在所有连续试验中成功和失败的概率是相同的。该分布将两个参数作为输入:事件发生的次数和分配给两个类别之一的概率。
一个简单的二项式分布的例子可以是一个有偏/无偏硬币的投掷,重复一定的次数。
改变偏差量将会改变分布的样子(图 4)。

Figure 4: Binomial Distribution varying event occurrence probability
二项式分布的主要特征是:
- 给定多个试验,每个试验都是相互独立的(一个试验的结果不会影响另一个)。
 - 每次尝试只能导致两种可能的结果(例如,赢或输),其概率为 p 和 (1 - p) 。
 
如果给定了成功的概率( p )和试验的次数( n ),我们就可以使用下面的公式计算这 n 次试验的成功概率( x )(图 5)。

Figure 5: Binomial Distribution Formula [2]
正态(高斯)分布
正态分布是数据科学中最常用的分布之一。我们日常生活中发生的许多常见现象都遵循正态分布,例如:经济中的收入分布、学生*均报告、人口中的*均身高等。除此之外,小随机变量的总和也通常遵循正态分布(中心极限定理)。
在概率论中,中心极限定理 ( CLT )确立了,在某些情况下,当独立的随机变量相加时,它们的正常标准化和趋向于正态分布,即使原始变量本身不是正态分布
— 维基百科

Figure 6: Gaussian Distribution
可以帮助我们识别正态分布的一些特征是:
- 这条曲线在中心对称。因此,*均值、众数和中位数都等于同一个值,使所有值围绕*均值对称分布。
 - 分布曲线下的面积等于 1(所有概率的总和必须为 1)。
 
正态分布可以用下面的公式推导出来(图 7)。

Figure 7: Normal Distribution Formula [3]
使用正态分布时,分布均值和标准差起着非常重要的作用。如果我们知道它们的值,我们就可以很容易地通过检查概率分布来找出预测精确值的概率(图 8)。事实上,由于分布特性,68%的数据位于*均值的一个标准偏差内,95%位于*均值的两个标准偏差内,99.7%位于*均值的三个标准偏差内。

Figure 8: Normal Distribution 68–95–99.7 Rule [4]
许多机器学习模型被设计为使用遵循正态分布的数据工作得最好。一些例子是:
- 高斯朴素贝叶斯分类器
 - 线性判别分析
 - 二次判别分析
 - 基于最小二乘法的回归模型
 
此外,在某些情况下,还可以通过应用对数和*方根等变换将非正常数据转换为正常形式。
泊松分布
泊松分布通常用于寻找事件可能发生的概率或不知道它通常发生的频率。此外,泊松分布也可用于预测一个事件在给定时间段内可能发生的次数。
例如,保险公司经常使用泊松分布来进行风险分析(例如,预测预定时间跨度内的车祸数量)以决定汽车保险定价。
使用泊松分布时,我们可以确信不同事件发生之间的*均时间,但是事件可能发生的精确时刻在时间上是随机的。
泊松分布可使用以下公式建模(图 9),其中 λ 代表一段时间内可能发生的事件的预期数量。

Figure 9: Poisson Distribution Formula [5]
描述泊松过程的主要特征是:
- 这些事件相互独立(如果一个事件发生,这不会改变另一个事件发生的概率)。
 - 一个事件可以发生任意次数(在定义的时间段内)。
 - 两件事不能同时发生。
 - 事件发生之间的*均速率是恒定的。
 
图 10 显示了改变一个周期(λ)内可能发生的事件的预期数量如何改变泊松分布。

Figure 10: Poisson Distribution varying λ
指数分布
最后,指数分布用于模拟不同事件发生之间的时间。
例如,假设我们在一家餐馆工作,我们想预测不同顾客来到餐馆的时间间隔。对于这种类型的问题,使用指数分布可能是一个完美的起点。
指数分布的另一个常见应用是生存分析(如设备/机器的预期寿命)。
指数分布由参数λ控制。λ值越大,指数曲线衰减越快(图 11)。

Figure 11: Exponential Distribution
使用以下公式模拟指数分布(图 12)。

Figure 12: Exponential Distribution Formula [6]
如果你对研究概率分布如何被用来揭开随机过程的神秘面纱感兴趣,你可以在这里找到更多关于它的信息。
联系人
如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:
文献学
[1]数据科学统计学导论。
迪奥戈·梅内塞斯·博尔赫斯,数据科学家的成就。访问:https://medium . com/diogo-menez es-Borges/introduction-to-statistics-for-data-science-7bf 596237 ac6
[2]二项式随机变量,用友生物统计学开放学习教材。访问地址:https://bolt . mph . ufl . edu/6050-6052/unit-3b/binomial-random-variables/
[3]正态分布或钟形曲线的公式。ThoughtCo,考特尼泰勒。访问:https://www . thoughtco . com/normal-distribution-bell-curve-formula-3126278
[4]解释正态分布的 68–95–99.7 规则。
迈克尔·加拉尼克,中等。访问:https://towardsdatascience . com/understanding-the-68-95-99-7-rule-for-a-normal-distribution-b7b 7 CBF 760 c 2
【5】正态分布,二项式分布&泊松分布,让我分析师。访问网址:http://makemanealyst . com/WP-content/uploads/2017/05/Poisson-Distribution-formula . png
[6]指数函数公式,&学习。访问地点:https://www.andlearning.org/exponential-formula/
概率论
机器学习基础(第一部分)
这是我认为机器学习基础的一系列主题中的第一部分。概率论是一个数学框架,用于量化我们对世界的不确定性。它允许我们(和我们的软件)在不可能确定的情况下进行有效的推理。概率论是许多机器学习算法的基础。这篇文章的目标是在将概率论应用于机器学习应用程序之前,涵盖所需的词汇和数学。所涉及的主题将在以后的帖子中讨论!

一些关于概率的哲学
概率到底是什么?大多数人都知道事件发生的概率是介于 0 和 1 之间的某个值,它表示事件发生的可能性有多大。看起来很简单,但是这些值实际上来自哪里呢?
客观主义者的观点是,随机性是宇宙的基础。他们会说,公*硬币正面朝上的概率是 0.5,因为这是公*硬币的本性。或者,主观主义者的观点认为,概率代表了我们对事件将会发生的相信程度。如果我们知道硬币的初始位置以及力是如何施加的,那么我们就可以确定它是正面朝上还是反面朝上。在这种视角下,概率是衡量我们无知的一个尺度(就像不知道力是如何作用在硬币上的)。
我个人是主观主义者。如果我们有适当的测量方法,我们应该能够确定地预测任何事情。一个不正确的领域是量子力学。为了理解一些量子现象,我们必须将它们视为真正随机的。有可能有一天我们会对宇宙如何运作有更好的理解,因此也能正确预测这些现象。似乎阿尔伯特·爱因斯坦也认同我的主观主义:
"上帝不和宇宙玩骰子。"
无论我们对随机性的本质有什么样的信念,我们都需要一些有原则的方法来实际估算概率。
频率主义者的立场是,估计来自实验,而且只是实验。如果我们想估计一个六面骰子掷出 4 的可能性,我们应该掷几次骰子,观察 4 出现的频率。
当我们有大量数据时,这种方法工作得很好,但是在例子较少的情况下,我们不能对我们的估计有信心。如果五卷之后我们还没有看到 a 4,是不是意味着 a 4 是不可能的?另一个问题是,我们不能将任何关于骰子的先验知识注入到我们的估计中。如果我们知道骰子是公*的,那么在前五次掷骰中没有看到 4 是完全可以理解的。
另一个流行的评估哲学是贝叶斯理论。概率的贝叶斯处理允许我们将我们先前的信念与我们的观察相结合。想象一下,一枚我们认为公*的硬币被抛了三次,结果是三个头。一个频率主义者的计算会建议硬币是装载的(虽然可信度低),但是我们的贝叶斯先验硬币是公*的允许我们保持一定程度的信念,即一个尾巴仍然是可能的。我们如何结合我们先前的信念的实际机制依赖于所谓的贝叶斯法则,这将在后面介绍。
概率数学
一开始,我提出概率论是一个数学框架。正如任何数学框架一样,需要一些词汇和重要的公理来充分利用该理论作为机器学习的工具。
概率就是各种结果的可能性。所有可能结果的集合被称为样本空间。抛硬币的样本空间是{正面,反面}。水温的样本空间是冰点和沸点之间的所有值。样本空间中一次只能有一个结果,并且样本空间必须包含所有可能的值。样本空间通常用ω(大写ω)表示,特定结果用ω(小写ω)表示。我们将事件发生的概率ω表示为 P(ω)。
概率的两个基本公理是:

Axioms of Probability
说白了,任何事件的概率都得在 0(不可能)到 1(一定)之间,所有事件的概率之和应该是 1。这是因为样本空间必须包含所有可能的结果。所以我们确定(概率 1)可能的结果之一会发生。
一个随机变量 x,是一个从样本空间随机取值的变量。我们经常用斜体表示 x 可以取的一个特定值。例如,如果 x 代表掷硬币的结果,我们可以讨论一个特定的结果为 x =正面。随机变量既可以像硬币一样是离散的,也可以是连续的(可以有无数个可能的值)。
为了描述随机变量 x 的每个可能值的可能性,我们指定一个概率分布。我们写 x ~ P(x)来表示 x 是一个随机变量,它取自一个概率分布 P(x)。根据随机变量是离散的还是连续的,概率分布有不同的描述。
离散分布:
离散随机变量用一个概率质量函数 (PMF)来描述。PMF 将变量样本空间中的每个值映射到一个概率。一个这样的 PMF 是在 n 个可能结果上的均匀分布:P(x= x ) = 1/ n 。这读作“x 取值 x 的概率是 1 除以可能值的数量”。它被称为均匀分布,因为每种结果都有相同的可能性(可能性均匀分布在所有可能的值上)。因为骰子的每个面都有相同的可能性,所以公*掷骰由均匀分布来模拟。加载的骰子通过分类分布来建模,其中每个结果被分配一个不同的概率。

另一种常见的离散分布是伯努利分布。伯努利分布规定了随机变量的概率,它可以取两个值中的一个(1/0,正面/反面,真/假,下雨/不下雨,等等)。).伯努利分布的 PMF 是 P(x)= {Pifx= 1,1- p if x =0}。因此,我们可以用单个参数 p 指定整个分布,即正面结果的概率。对于一枚公*的硬币,我们有 p = 0.5,因此正面或反面的可能性是相等的。或者,如果我们说明天下雨的概率是 p = 0.2,那么我们可以推断不下雨的概率是 0.8。
连续分布:
连续随机变量由概率密度函数 (PDF)描述,这可能有点难以理解。我们通常将随机变量 x 的 PDF 表示为 f ( x )。pdf 将无限样本空间映射到相对似然值。为了理解这一点,让我们看一个最著名的连续分布的例子,高斯(正态)分布。
高斯分布(俗称钟形曲线)可以用来模拟几种自然现象。例如,每个性别的身高*似为高斯分布。高斯分布由两个值参数化:均值μ(μ)和方差σ(σ*方)。*均值指定分布的中心,方差指定分布的宽度。你可能也听说过标准差σ,它就是方差的*方根。为了表示 x 是从具有均值μ和方差σ的高斯分布中抽取的随机变量,我们写:

X is drawn from a Normal distribution with mean μ and variance σ².
乍一看,高斯分布的 PDF 的函数形式可能令人生畏。我保证,在应用程序中使用高斯分布后,这种恐惧就会消失!PDF 的功能形式是:

The PDF of x given μ and σ²
等式的左手边写着“给定μ和σ的 x 的 PDF”。竖线代表单词“given ”,表示我们已经知道括号中它后面的所有值。假设μ = 0,σ = 4,我们来绘制这个等式:

那么我说的相对可能性是什么意思呢?与离散分布不同,x = x 处的 PDF 值并不是 x 的实际概率。当人们刚开始涉足概率论时,这是一个常见的误解。因为 x 可以取无限多的值,所以 x 取任何特定值的概率实际上是 0!我猜你不相信我,但是让我们在重温我们的公理时一起考虑一下。
回想一下,每个可能值的总概率总和需要为 1。我们如何对无限多的值求和?答案来自积分形式的微积分。我们可以用积分来重写 PDF 形式的公理:

The integral of the PDF over the sample space is 1.
如果你不熟悉微积分,积分是一个计算曲线下面积的运算符 f ( x )。这是对无穷多个值求和的概括。所以 PDF 下面的区域代表高斯分布的总概率!如果你熟悉微积分(并且有能力),你可以自己计算高斯函数的积分来确定面积是 1。
因为面积是我们感兴趣的,所以使用连续随机变量的累积分布函数 (CDF)通常更有用。我们把 CDF, F ( x )写成:

CDF is a function of the integral of the PDF.
这到底是什么意思?嗯,对于给定的值 x ,我们对 PDF 从负无穷大到那个值进行积分。所以 F ( x )给出了从负无穷大到 x 区间的 PDF 下的面积。
我们只要确定面积对应概率,那么 F ( x )给我们 P(x≤ x )。现在,我们可以通过注意到 P(a≤x≤b)=F(b)-F(a)来使用 CDF 确定任何给定范围[ a , b ]的概率。这就回答了“x 在 a 和 b 之间的概率是多少?”。
求 P(x= x )等价于求 P(x≤x≤x)= F(x)-F(x)= 0。现在你知道了,从分布中抽取一个特定数字的概率是 0!(更有力的论据可以通过实际采用极限来提出)。这是之前相同高斯的 CDF:

我们看到 x 取小于-2.5 的值的概率接*于 0。我们还看到,从 x 采样的值大多小于 2.5。
联合概率分布:
多个随机变量的分布称为联合概率分布。我们可以把随机变量的集合写成一个向量 x 。在 x 上的联合分布指定了 x 中包含的所有随机变量的任何特定设置的概率。为了更清楚地说明这一点,让我们考虑两个随机变量 x 和 y,我们把联合概率写成 P(x= x ,y= y )或者简称为 P( x , y )。我大声说出“x= x 和 y= y 的概率”。如果两个随机变量都是离散的,我们可以用一个简单的概率表来表示联合分布。例如,让我们考虑我穿哪件外衣与天气条件的联合分布(在只有这些选项的宇宙中):

Joint Distribution of clothes and weather (in an odd universe)
这个玩具例子强调了一些重要的事情。首先,我不擅长做玩具例子。其次,请注意,该表满足我们的公理所提出的要求。我们可以立即回答 P 形式的问题(衣服=T 恤衫,天气=晴天),但是联合分布给了我们更多!
边际概率分布:
首先,我们来看看求和规则:

Sum Rule
术语 P( x )被称为边际概率分布,因为我们已经将随机变量 y“边缘化”了。让我们使用求和规则来计算我穿帽衫的概率。P(帽衫)= P(帽衫,晴天)+ P(帽衫,多云)+ P(帽衫,雨天)= 3/9。我们可以使用相同的过程来找到任何衣服项目或任何天气条件的边际概率。
如果 P( x , y )是连续随机变量的联合分布,那么为了将 y 边缘化,我们将求和转化为 y 上的积分,就像之前一样。
条件概率分布:
我们也经常对一个事件发生的概率感兴趣,因为另一个事件已经被观察到了。给定 y,我们将 x 的条件概率分布 T37 表示为:

Probability of x conditioned on observing y
换句话说,如果我观察到 y= y ,那么 x= x 的概率就是 P( x,y )/P( y )。为什么观察 y 会改变 x 的概率?想象一下你看到我穿着夹克走进去。知道我穿了夹克,就给了你关于天气的信息,不用直接观察天气。
注意,条件概率只存在于 P( y ) > 0 的情况下。如果 y 不可能发生,那么我们一开始就不可能观察到 y 。
将最后一个方程的两边乘以 P( y )我们得到概率的链式法则,P( x,y)= p(x|y)⋅p(y)。链式法则可以推广到任意数量随机变量的联合分布:P( x,y,z ) = P( x | y,z ) ⋅ P( y,z ) = P( x | y,z)⋅p(y|z)⋅p(【t34
贝叶斯法则:
请注意,我们可以用两种等价的方式来编写两个变量的链式法则:
- P( x,y)= p(x|y)⋅p(y)
 - P( x,y)= p(y |x)⋅p(x)
 
如果我们设置两个右侧相等,并除以 P( y ),我们得到贝叶斯法则:

Bayes Rule
贝叶斯法则对于许多统计学和机器学习来说至关重要。如前所述,这是贝叶斯统计背后的驱动力。随着我们从数据中收集更多的观察结果,这个简单的规则允许我们更新我们对数量的信念。我肯定会在以后的文章中更多地讨论贝叶斯法则(和贝叶斯统计)。
独立性和条件独立性:
在前面的例子中,我们看到 P( x|y ) ≠ P( x )是因为观察 y 给了我们关于 x 的信息。总是这样吗?我们假设 P( x,y )是一个联合分布,x 代表一家店的冰淇淋量,y 代表月亮每天被物体撞击的次数。知道其中一个值会给我们任何关于另一个值的信息吗?当然不是!所以在这种情况下 P( x|y ) = P( x )!通过把这个代入链式法则,我们发现在这个场景中我们得到 P( x,y)= p(x | y)⋅p(y)= p(x)⋅p(y)。这直接把我们引向我们对独立的定义。如果 P( x,y)= p(x)⋅p(y),则称两个变量 x 和 y 是独立的。
一个类似的概念是条件独立性。给定另一个变量 z,如果 P( x,y | z)= p(x | z)⋅p(y | z),则两个变量 x 和 y 称为条件独立。让我们做一个例子来看看这是怎么回事。
假设 x 是一个随机变量,表示我是否带伞上班,y 是一个随机变量,表示我的草地是否潮湿。很明显,这些事件不是独立的。如果我带了一把伞,这可能意味着下雨了,如果下雨,我的草是湿的。现在让我们假设我们观察变量 z,它代表外面实际上正在下雨。现在不管我有没有带伞上班,你都知道我家的草是湿的。所以下雨的条件已经使我的伞独立于我的草是湿的!
当我们需要表示非常大的联合分布时,独立性和条件独立性变得非常重要。独立性让我们将分布分解成更简单的术语,实现有效的内存使用和更快的计算。我们将在未来关于贝叶斯网络的文章中具体看到这一点!
随机变量的函数
创建以随机变量为输入的函数通常很有用。让我们考虑去一趟赌场。玩我最喜欢的游戏“猜一个 1 到 10 之间的数字”要花 2 美元。如果你猜对了,你将赢得 10 美元。如果你猜错了,你什么也赢不了。设 x 是一个随机变量,表示你是否猜对了。然后我们可以写一个函数h(x)= { $ 8 ifx= 1,和-$2 if x = 0}。换句话说,如果你猜对了,你会得到 10 美元减去你支付的 2 美元,否则你会失去你的 2 美元。你可能有兴趣提前知道预期的结果是什么。
期望:
随机变量 x ~ P(x)上的函数 h (x)的期望值,或期望值,是 P(x)加权后的 h ( x )的*均值。对于离散的 x,我们写为:

Expected Value of h(x) with respect to P(x)
如果 x 是连续的,我们会用一个积分代替求和(我敢打赌你现在已经看到一个模式了)。因此,期望充当了对 h ( x )的加权*均,其中权重是每个 x 的概率。
如果我们假设有 1/10 的机会猜中正确的数字,在赌场玩猜谜游戏的期望值是多少?
𝔼[ h (x)] = P(赢)⋅ h (赢)+ P(输)⋅ h (输)=(1/10)⋅$ 8+(9/10)⋅(-$ 2)= $ 0.80+(-1.80)=-1 美元。所以*均来说,我们每次玩游戏都会输掉 1 美元!
期望的另一个很好的特性是它们是线性的。我们假设 g 是 x 的另一个函数,α和β是常数。然后我们有:

Expectations are linear
方差和协方差:
当我们讨论连续随机变量时,我们看到了高斯分布的方差。一般来说,方差是随机值与其*均值相差多少的度量。类似地,对于随机变量的函数,方差是函数输出与其期望值的可变性的度量。

Variance of h(x) with respect to P(x)
另一个重要的概念是协方差。协方差是两个随机变量(或随机变量上的函数)之间线性相关程度的度量。函数 h (x)和 g (y)之间的协方差写为:

Covariance between h(x) and g(y).
当协方差的绝对值较高时,两个函数往往同时偏离均值很远。当协方差的符号为正时,两个函数一起映射到更高的值。如果符号为负,则一个函数映射到较高的值,而另一个函数映射到较低的值,反之亦然。本文开头的可视化展示了变量间具有正协方差的联合高斯分布的样本。你可以看到,随着第一个变量的增加,第二个变量也在增加。
时刻:
注意,我们可以通过用 x 本身替换函数 h (x)来计算随机变量的期望和方差。一个分布的期望是它的*均值,或一阶矩。分布的方差是它的二阶矩。概率分布的高阶矩捕捉其他特征,如偏斜度和峰度。
重要分布
我们已经讨论了概率论的大部分重要方面。这些想法为开发大多数统计学和机器学习的基础提供了基础。为了掌握概率论并开始弥补统计学的差距,人们需要对更有用的概率分布有所了解。
概率分布的函数形式可能令人生畏。我的建议是不要太关注那个方面,而是关注每个发行版擅长建模什么类型的情况。型号/用途描述的一些示例包括:
- 伯努利:模拟掷硬币和其他二元事件的结果
 - 二项式:模拟一系列伯努利试验(一系列抛硬币等)。)
 - 几何:模拟在你成功之前需要翻转多少次
 - 多项式:将二项式推广到两个以上的结果(如掷骰子)
 - 泊松:模拟在特定时间间隔内发生的事件数量
 
对于连续分布,知道形状也是有用的。例如,我们看到高斯分布的形状像一个钟,其大部分密度接**均值。贝塔分布在区间[0,1]上可以呈现各种各样的形状。这使得贝塔分布成为我们对特定概率的信念建模的一个很好的选择。
记住这些格式良好的发行版更像是模板,这一点也很重要。您的数据的真实分布可能并不那么好,甚至可能会随着时间的推移而改变。
太好了,但是这一切和机器学习有什么关系呢?
这篇文章的目标是建立我们的概率语言,这样我们就可以用概率的观点来构建机器学习。我将在未来的帖子中介绍具体的机器学习算法和应用,但我想描述一下我们刚刚实现的功能。
监督学习:
在监督机器学习中,我们的目标是从标记的数据中学习。被标记的数据意味着对于一些输入 X,我们知道期望的输出 y。一些可能的任务包括:
- 识别图像中的内容。
 - 给定公司的一些特征,预测股票的价格。
 - 检测文件是否是恶意的。
 - 给病人诊断病情。
 
在这些情况下,概率如何帮助我们?我们可以用各种方法学习从 X 到 Y 的映射。首先,你可以学习 P(Y|X),也就是说,假设你观察到一个新的样本 X,Y 的可能值的概率分布。找到这种分布的机器学习算法被称为判别。想象一下,我告诉你,我看到了一只长着毛皮、长尾巴、两英寸高的动物。你能区分可能的动物并猜出它是什么吗?

Photo by Ricky Kharawala on Unsplash
或者,我们可以尝试学习 P(X|Y),即给定标签下输入的概率分布。实现这一点的算法被称为生成。假设我想要一只老鼠,你能描述一下老鼠的身高、体毛和尾巴长度吗?枚举特性的可能值有点像生成所有可能的鼠标。
你可能想知道了解生殖模型如何帮助我们完成动物分类的任务?还记得贝叶斯法则吗?从我们的训练数据中,我们可以学习 P(Y),任何特定动物的概率,以及 P(X),任何特定特征配置的概率。使用这些术语,我们可以用贝叶斯法则回答 P(Y|X)形式的查询。
有可能知道从 X 到 Y 的映射,它不是以概率分布的形式。我们可以用一个确定性函数 f 来拟合我们的训练数据,这样 f ( X ) ≈ Y。好吧,想象一个算法正在诊断你的疾病,它告诉你你还能活一个月。函数 f 无法向你表达它在评估中有多自信。也许你有算法在训练数据中从未见过的特征,导致它或多或少地猜测出一个结果。概率模型量化了不确定性,常规函数没有。
无监督学习:
无监督学习是一套从无标签数据中学习的广泛技术,其中我们只有一些样本 X,但没有输出 y。常见的无监督任务包括:
- 将相似的数据点分组在一起(聚类)。
 - 取高维数据,投射到有意义的低维空间(降维、因子分析、嵌入)。
 - 用分布表示数据(密度估计)。
 
表征未标记数据的分布对于许多任务是有用的。一个例子是异常检测。如果我们学习 P(X),其中 X 代表正常的银行交易,那么我们可以用 P(X)来衡量未来交易的可能性。如果我们观察到低概率的交易,我们可以将其标记为可疑和可能的欺诈。
聚类是无监督学习的典型问题之一。给定一些来自不同组的数据点,我们如何确定每个点属于哪个组?一种方法是假设每个组是从不同的概率分布中产生的。解决这个问题就变成了寻找这些分布最可能的配置。
降维是无监督学习的另一个主要领域。高维数据占用内存,降低计算速度,并且难以可视化和解释。我们希望有办法在不丢失太多信息的情况下将数据降低到一个较低的维度。人们可以把这个问题看作是在低维空间中寻找一个与原始数据的分布具有相似特征的分布。
强化学习:
强化学习领域就是训练人工智能体在特定任务中表现出色。代理通过在他们的环境中采取行动并根据他们的行为观察奖励信号来学习。代理人的目标是最大化其预期的长期回报。概率在强化学习中用于学习过程的几个方面。你可能在目标中发现了“期望”这个词。代理人的学习过程通常围绕着量化采取一个特定行动相对于另一个行动的效用的不确定性。
结论
这是对概率论语言的温和概述,并简要讨论了我们将如何将这些概念应用于更高级的机器学习和统计学。请务必查看关于最大似然估计的第二部分:
机器学习基础(二)
towardsdatascience.com](/maximum-likelihood-estimation-984af2dcfcac)
如果你想从另一个角度来研究概率论,我强烈推荐看看《看见理论》中这个令人惊叹的视觉介绍:
概率和统计的直观介绍。
seeing-theory.brown.edu](https://seeing-theory.brown.edu/)
下次见!
概率学习 I:贝叶斯定理
通过一个简单的日常例子来了解概率的基本定理之一。

这篇文章假设你有一些概率和统计的基础知识。如果你不知道,不要害怕,我已经在收集了我能找到的向你介绍这些主题的最佳资源,这样你就可以阅读这篇文章,理解它,并且充分享受它。
在这本书中,我们将讨论概率论中最著名和最常用的定理之一:贝叶斯定理。没听说过?那么你将会享受到一顿大餐!已经知道是什么了?然后继续读下去,用一个简单的日常例子巩固你的知识,这样你也可以用简单的语言向他人解释。
在接下来的帖子中,我们将了解一些更实用的贝叶斯定理的简化,以及其他机器学习的概率方法,如 隐马尔可夫模型 。
最后,在我们开始之前,这里有一些额外的资源可以让你的机器学习生涯突飞猛进:
*Awesome Machine Learning Resources:**- For* ***learning resources*** *go to* [***How to Learn Machine Learning***](https://howtolearnmachinelearning.com/books/machine-learning-books/)*! 
- For* ***professional******resources*** *(jobs, events, skill tests) go to* [***AIgents.co — A career community for Data Scientists & Machine Learning Engineers***](https://aigents.co/)***.***
我们走吧!
概率介绍:
在本节中,我列出了三个非常好的和简明的来源(主要是前两个,第三个更广泛一点)来学习概率的基础知识,这是你理解这篇文章所需要的。不要害怕,这些概念非常简单,只要快速阅读,你就一定能理解它们。
如果你已经掌握了基本概率,可以跳过这一节。
- 有趣的小概率介绍在机器学习 中,主要用一个神秘但简单的例子来介绍概率的每个主要术语。
 - 哈佛的统计学 110 课程。这是一个更大的资源,以防你不仅想学习基础知识,还想更深入地了解统计的奇妙世界:
 
好了,现在你已经准备好继续这篇文章的其余部分了,坐下来,放松,享受吧。
贝叶斯定理:
贝叶斯是谁?
托马斯·贝叶斯 (1701 — 1761)是的英国神学家和数学家,隶属于皇家学会(世界上最古老的国家科学学会,也是促进英国科学研究的主要国家组织),其他知名人士都曾在此注册,如牛顿、达尔文或法拉第。他发展了一个最重要的概率定理,这个定理创造了他的名字:贝叶斯定理,或条件概率定理。

Portrait of the Reverend Thomas Bayes, father of Bayes’ Theorem
定理:条件概率
为了解释这个定理,我们将使用一个非常简单的例子。假设你被诊断出患有一种非常罕见的疾病,这种疾病只影响 0.1%的人。也就是说,每 1000 人中有 1 人。
您进行的疾病检查测试对 99%的患病者进行了正确分类,而对健康人的错误分类只有 1%的几率。
我完了!这种病致命吗医生?
大多数人都会这么说。然而,在这次测试之后,我们真的患病的可能性有多大?
99%肯定!我最好把我的东西整理好。
基于这种想法,贝叶斯的想法应该会占上风,因为它实际上与现实相差甚远。让我们用贝叶斯定理来获得一些观点。
贝叶斯定理,或者我之前称之为条件概率定理,用于计算假设(H)为真的概率(即。患有疾病)鉴于某一事件(E)已经发生(在测试中被诊断为该疾病阳性)。使用以下公式描述该计算:

Bayes’ formula for conditional probability
等号 P(H |E ) 左边的项是假设我们在这种疾病的测试中被诊断为阳性(E)** ,那么我们实际上想要计算的是患这种疾病的概率(H)。概率项中的竖线(|) 表示条件概率(即给定 B 的概率将是 P(A|B) )。**
右边 P(E|H) 的分子左边一项是假设为真的情况下,事件发生的概率。在我们的例子中,这将是在测试中被诊断为阳性的概率,假设我们患有疾病。
它旁边的术语;【P(H)是假设在任何事件发生之前的先验概率。在这种情况下,这将是在进行任何测试之前患病的可能性。
最后,分母上的项; P(E) 是事件发生的概率,即被诊断为该疾病阳性的概率。这个术语可以进一步分解为两个更小术语的总和:患病且检测呈阳性加上未患病且检测也呈阳性。

Deconstruction of the probability of testing positive on the test
在这个公式中 P(~H) 表示没有患病的先验概率,其中 ~ 表示否定或不否定。下图描述了条件概率整体计算中涉及的每个术语:

Description of each of the terms involved on the formulation of by Bayes’ Theorem
记住,对我们来说,假设或假设 H 患有疾病,而事件或证据 E 在这种疾病的测试中被诊断为阳性。
如果我们使用我们看到的第一个公式(计算患有疾病并被诊断为阳性的条件概率的完整公式)分解分母,并插入数字,我们得到以下计算结果:

Calculation of the conditional probability
0.99 来自 99%的被诊断为阳性的概率,0.001 来自 1000 分之一的患病概率,0.999 来自没有患病的概率,最后的 0.01 来自即使我们没有患病也能被诊断为阳性的概率。这种计算的最终结果是:

Result of the calculation
9%!我们患这种疾病的可能性只有 9%!怎么会这样?”你大概在问自己。魔法?不,我的朋友们,这不是魔术,这是只是概率:应用于数学的常识。就像丹尼尔·卡内曼在《思考,快与慢》一书中描述的那样,人类的大脑非常不擅长估计和计算概率,就像前面的例子所显示的那样,所以我们应该总是抑制我们的直觉,后退一步,使用我们所能使用的所有概率工具。
现在想象一下,在第一次测试被诊断为阳性后,我们决定在不同的诊所以相同的条件进行另一次测试以复查结果,不幸的是,我们再次得到阳性诊断,这表明第二次测试也表明我们患有该疾病。
现在得这种病的实际概率是多少?好的,我们可以使用和之前完全一样的公式,但是用上一次得到的后验概率(一次检测阳性后 9%的概率)代替最初的先验概率 (0.1%患病几率),以及它们的补充项。
如果我们处理这些数字,我们会得到:

Calculation of the conditional probability after the second positive

Results after the second positive
现在,我们有更高的几率真的患上这种疾病。尽管看起来很糟糕,但在两次阳性测试后,仍然不能完全确定我们患有这种疾病。确定性似乎逃离了概率的世界。
定理背后的直觉
这个著名定理背后的直觉是,我们永远无法完全确定这个世界,因为它是一个不断变化的存在,变化是现实的本质。然而,我们可以做的事情,这是这个定理背后的基本原则,是随着我们获得越来越多的数据或证据,更新和改善我们对现实的知识。
这可以用一个非常简单的例子来说明。想象以下情景:你在边上方形的花园里,坐在椅子上,看着花园外面。在对面,躺着一个仆人,他把一个蓝色的球扔进了正方形。在那之后,他继续在方块内投掷其他黄色球,并告诉你它们相对于最初的蓝色球落在哪里。

Video of this mental experiment with our good old Bayes sitting on the edge of his garden with his back towards a servant that is throwing the balls.
随着越来越多的黄球落地,你得到了它们相对于第一个蓝球落地的位置的信息,你逐渐增加了关于蓝球可能在哪里的知识,忽略了花园的某些部分:随着我们获得更多的证据(更多的黄球),我们更新了我们的知识(蓝球的位置)。
在上面的例子中,只扔了 3 个黄色的球,我们已经可以开始建立一个确定的想法,蓝色的球位于花园左上角的某个地方。
当贝氏第一次公式化这个定理时,他起初没有发表,认为这没什么了不起,而公式化这个定理的论文是在他死后才被发现的。
今天,贝叶斯定理不仅是现代概率的基础之一,而且是许多智能系统中高度使用的工具,如垃圾邮件过滤器和许多其他文本和非文本相关的问题解决程序。
在接下来的文章中,我们将看到这些应用是什么,以及贝叶斯定理及其变体如何应用于许多现实世界的用例。来看看 跟我上媒 ,敬请期待!

想了解更多关于概率和统计的资料,请点击下面的最佳在线课程来了解这个精彩的话题!
就这些,我希望你喜欢这个帖子。请随时在 LinkedIn 上与我联系,或者在 @jaimezorno 的 Twitter 上关注我。还有,你可以看看我其他关于数据科学和机器学习的帖子这里 。好好读!
概率学习 II:贝叶斯定理如何应用于机器学习
了解贝叶斯定理是如何在机器学习中进行分类和回归的!

在上一篇文章中,我们看到了什么是贝叶斯定理,并通过一个简单直观的例子展示了它是如何工作的。你可以在这里 找到这个帖子。如果你不知道贝叶斯定理是什么,并且你还没有阅读它的乐趣,我推荐你去读,因为它会让你更容易理解这篇文章。
在本帖中,我们将看到这个定理在机器学习中的用途。
在我们开始之前,这里有一些额外的资源可以让你的机器学习事业突飞猛进:
*Awesome Machine Learning Resources:**- For* ***learning resources*** *go to* [***How to Learn Machine Learning***](https://howtolearnmachinelearning.com/books/machine-learning-books/)*! 
- For* ***professional******resources*** *(jobs, events, skill tests) go to* [***AIgents.co — A career community for Data Scientists & Machine Learning Engineers***](https://aigents.co/)***.***
准备好了吗?那我们走吧!
机器学习中的贝叶斯定理
正如上一篇文章中提到的,贝叶斯定理告诉我们,当我们获得更多关于某件事的证据时,如何逐渐更新我们对某件事的知识。
通常,在监督机器学习中,当我们想要训练一个模型时,主要构件是一组包含特征(定义这种数据点的属性)这种数据点的标签(我们稍后想要在新数据点上预测的数字或分类标签),以及将这种特征与其相应标签相链接的假设函数或模型。我们还有一个损失函数,它是模型预测和真实标签之间的差异,我们希望减少该差异以实现最佳可能结果。

Main elements of a supervised Learning Problem
这些受监督的机器学习问题可以分为两个主要类别:回归,其中我们希望计算与一些数据(例如房子的价格)相关联的一个数字或数字 值,以及分类,其中我们希望将数据点分配给某个类别(例如,如果一幅图像显示一只狗或猫)。
贝叶斯定理既可以用于回归,也可以用于分类。
让我们看看如何!
回归中的贝叶斯定理
假设我们有一组非常简单的数据,它代表一个城镇的某个地区一年中每天的温度(数据点的特征,以及该地区一家当地商店每天卖出的数量(数据点的标签)。
通过制作一个非常简单的模型,我们可以查看这两者是否相关,如果相关,然后使用这个模型进行预测,以便根据温度储备水瓶,永远不会缺货,或者避免库存过多。
我们可以尝试一个非常简单的线性回归模型来看看这些变量是如何相关的。在下面描述这个线性模型的公式中,y 是目标标签(在我们的例子中是水瓶的数量),每个θs 是模型的参数(y 轴的斜率和切割),x 是我们的特征(在我们的例子中是温度)。

Equation describing a linear model
这种训练的目标是减少提到的损失函数,以便模型对已知数据点的预测接*这些数据点的标签的实际值。
用可用数据训练模型后,我们将得到两个 θs 的值。该训练可以通过使用类似梯度下降的迭代过程或类似最大似然的另一种概率方法来执行。无论如何,我们只需要为每个参数设定一个值。
以这种方式,当我们得到没有标签的新数据(新的温度预测)时,因为我们知道 θs 的值,我们可以使用这个简单的等式来获得想要的 Ys (每天需要的水瓶数量)。

Figure of an uni-variate linear regression. Using the initial blue data points, we calculate the line that best fits these points, and then when we get a new temperature we can easily calculate the Nº sold bottles for that day.
当我们使用贝叶斯定理进行回归时,不是认为模型的参数(θs)具有单一的唯一值,而是将它们表示为具有特定分布的参数:参数的先验分布。下图显示了一般贝叶斯公式,以及如何将其应用于机器学习模型。

Bayes formula

Bayes formula applied to a machine learning model
这背后的想法是,我们在没有任何实际数据之前,已经有了模型参数的一些先验知识: P(模型) 就是这个先验概率。然后,当我们得到一些新的数据时,我们更新模型的参数的分布,使之成为后验概率 P(模型|数据) 。
这意味着我们的参数集(我们模型的θs)不是常数,而是有自己的分布。基于先前的知识(例如,来自专家,或来自其他作品)我们对我们的模型的参数分布做出第一个假设。然后,当我们用更多的数据,训练我们的模型时,这个分布得到更新,变得更加精确(实际上方差变得更小)。

Figure of the a priori and posteriori parameter distributions. θMap is the maximum posteior estimation, which we would then use in our models.
该图显示了模型参数的初始分布 p(θ)** ,以及当我们添加更多数据时,该分布如何更新,使其更精确地增长到 p(θ|x) ,其中 x 表示该新数据。这里的θ相当于上图公式中的型号,这里的xT37 相当于这样公式中的数据。**
贝叶斯公式一如既往地告诉我们如何从先验概率到后验概率。随着我们获得越来越多的数据,我们在迭代过程中这样做,让后验概率成为下一次迭代的先验概率。一旦我们用足够的数据训练了模型,为了选择最终参数组,我们将搜索最大后验(MAP)估计,以使用模型参数的一组具体值。****
这种分析从最初的先验分布中获得其优势:如果我们没有任何先验信息,并且不能对其做出任何假设,那么像最大似然法这样的其他概率方法更适合。
然而,如果我们有一些关于参数分布的先验信息,贝叶斯方法被证明是非常有效的,特别是在有不可靠的训练数据的情况下。在这种情况下,由于我们不是使用该数据从零开始构建模型和计算其参数,而是使用某种先前的知识来推断这些参数的初始分布,该先前的分布使得参数更加稳健,并且更少受到不准确数据的影响。****
我不想在这部分讲太多技术,但是所有这些推理背后的数学是美丽的;如果你想了解它,不要犹豫,给我发电子邮件到 jaimezorno@gmail.com 或者通过 LinkdIn 联系我。
分类中的贝叶斯定理
我们已经看到,通过估计线性模型的参数,贝叶斯定理可以用于回归分析。同样的推理可以应用于其他类型的回归算法。
现在我们将看看如何使用贝叶斯定理进行分类。这就是所谓的贝叶斯最优分类器。现在的推理和之前的很像。
假设我们有一个分类问题,用 i 不同的类。我们在这里追求的是每个类wI的类概率。与之前的回归案例一样,我们也区分先验概率和后验概率,但现在我们有了先验类概率 p(wi) 和后验类概率,在使用数据或观测值 p(wi|x) 之后。****

Bayes formula used for Bayes’ optimal classifier
这里的【x】是所有数据点【x | wi】所共有的密度函数,是属于 wi** 类的数据点的密度函数, P(wi) 是 wi 类的先验分布 P(x|wi) 是从训练数据中计算出来的,假设某个分布,并计算每个类别的均值向量和属于该类别的数据点的特征的协方差。先验类分布 P(wi) 是基于领域知识、专家建议或以前的工作来估计的,就像回归示例中一样。******
让我们看一个如何工作的例子:图像我们测量了 34 个人的身高: 25 个男性(蓝色)和 9 个女性(红色),我们得到了一个 172 cm 的新的身高观察值,我们想将它分类为男性或女性。下图显示了使用最大似然分类器和贝叶斯最优分类器获得的预测。

On the left, the training data for both classes with their estimated normal distributions. On the right, Bayes optimal classifier, with prior class probabilities p(wA) of male being 25/34 and p(wB) of female being 9/34.
在这种情况下,我们使用训练数据中的个样本作为的先验知识用于我们的类别分布,但是例如,如果我们对特定国家的身高和性别进行相同的区分,并且我们知道那里的女性特别高,也知道男性的*均身高,我们可以使用这个信息来构建我们的先验类别分布。
从例子中我们可以看出,使用这些先验知识会导致与不使用它们不同的结果。假设先前的知识是高质量的(否则我们不会使用它),这些预测应该比没有结合这些信息的类似试验更加准确。
在这之后,一如既往,当我们得到更多的数据时,这些分布会得到更新以反映从这些数据中获得的知识。
和前一个案例一样,我不想太过技术化,或者过多地延伸文章,所以我就不深究数学上的细节了,但是如果你对它们感兴趣,可以随时联系我。
结论
我们已经看到贝叶斯定理是如何用于机器学习的;无论是在回归还是分类中,都要将以前的知识融入到我们的模型中并加以改进。
在接下来的文章中,我们将看到贝叶斯定理的简化如何成为自然语言处理中最常用的技术之一,以及它们如何应用于许多真实世界的用例,如垃圾邮件过滤器或情感分析工具。来看看 跟我上媒 ,敬请期待!

Another example of Bayesian classification
就这些,我希望你喜欢这个帖子。欢迎在 LinkedIn上与我联系,或者在 Twitter 上关注我,邮箱: @jaimezorno 。还有,你可以看看我其他关于数据科学和机器学习的帖子这里 。好好读!
额外资源
如果您想更深入地研究贝叶斯和机器学习,请查看以下其他资源:
有关机器学习和数据科学的更多资源,请查看以下资源库: 如何学习机器学习 !有关职业资源(工作、事件、技能测试),请访问AIgents.co——数据科学家的职业社区&机器学习工程师 ,如有任何问题,请联系我。祝你有美好的一天,继续学习。
概率学习 III:最大似然
我们成为概率大师的又一步…

在之前的两篇关于贝叶斯定理的帖子之后,我收到了很多请求,要求对定理的回归和分类用途背后的数学进行更深入的解释。下一个系列的帖子是对这些要求的回答。
然而,我认为,如果我们首先涵盖概率机器学习的另一个基本方法最大似然法背后的理论和数学,贝叶斯背后的数学将会更好理解。本帖将致力于解释。
前面的文章可以找到 这里 和这里 。我建议在处理下一个问题之前先读一读,然后跟随我们一起创造的美丽故事线。
在我们开始之前,这里有一些额外的资源可以让你的机器学习生涯突飞猛进
*Awesome Machine Learning Resources:**- For* ***learning resources*** *go to* [***How to Learn Machine Learning***](https://howtolearnmachinelearning.com/books/machine-learning-books/)*! - For* ***professional******resources*** *(jobs, events, skill tests) go to* [***AIgents.co***](https://aigents.co/)[***— A career community for Data Scientists & Machine Learning Engineers***](https://aigents.co/)***.***
最大似然原则
最大似然法的目标是使一些数据符合最佳的统计分布。这使得数据更容易处理,更通用,允许我们查看新数据是否遵循与先前数据相同的分布,最后,它允许我们对未标记的数据点进行分类。
就像在上一篇中,想象一个男性和女性个体使用身高的二元分类问题。一旦我们计算了男女身高的概率分布,并且我们得到了一个新数据点(作为没有标签的身高)我们就可以将其分配到最有可能的类别,看看哪个分布报告了两者的最高概率。

Graphical representation of this binary classification problem
在之前的图像中,该新数据点( xnew, 对应于 172 cm 的高度)被分类为女性,对于该特定高度值,女性高度分布产生比男性高的概率。
你可能会说这很酷,但是我们如何计算这些概率分布呢?不要担心,我们现在就开始。首先我们将解释其背后的一般过程,然后我们将通过一个更具体的例子。
计算分布:估计参数密度函数
像往常一样在机器学习中,我们首先需要开始计算一个分布是要学习的东西:我们宝贵的数据。我们将把我们的大小 n 的数据向量表示为 X 。在这个向量中,每一行都是具有 d 个特征的数据点,因此我们的数据向量 X 实际上是向量的向量:大小为 n x d 的矩阵;n 个数据点,每个具有 d 个特征。
一旦我们收集了想要计算分布的数据,我们需要开始猜测。猜谜?是的,你没看错,我们需要猜测我们的数据符合哪种密度函数或分布:高斯、指数、泊松……
不要担心,这听起来可能不太科学,但大多数情况下,每种数据都有一个最可能符合的分布:温度或高度等特征的高斯分布,时间等特征的指数分布,电话通话时间或细菌种群寿命等特征的泊松分布。
完成后,我们计算最符合我们数据的特定分布参数。对于正态分布,这将是*均值和方差。由于高斯或正态分布可能是最容易解释和理解的分布,我们将继续这篇文章,假设我们已经选择了一个高斯密度函数来表示我们的数据。

Data and parameters for our gaussian distribution
在这种情况下,我们需要计算的参数个数是 d means(每个特征一个)和 d(d+1)/2 方差,因为协方差矩阵是对称的 dxd 矩阵。

Total parameters we need to calculate for a normal distribution depending on the number of features
让我们称分布的整体参数组为 θ 。在我们的例子中,这包括每个特征的*均值和方差。我们现在要做的是获得使数据向量的联合密度函数最大化的参数集θ;所谓 似然函数 L(θ)。 这个似然函数也可以表示为 P(X|θ) ,可以读作给定参数集θ时 X 的条件概率。

Likelihood function
在这个符号中,X 是数据矩阵,X(1)到 X(n)是每个数据点,θ是分布的给定参数集。同样,由于最大似然法的目标是选择参数值,使观察到的数据尽可能接*,我们得出一个依赖于θ的优化问题。
为了获得该最佳参数集,我们对似然函数中的θ进行求导,并搜索最大值:该最大值代表尽可能观察到可用数据的参数值。

Taking derivatives with respect to θ
现在,如果 X 的数据点彼此独立,则似然函数可以表示为给定参数集的每个数据点的个体概率的乘积:

Likelihood function if the data points are independent of each other
在保持其他参数不变的情况下,对该方程的每个参数(*均值、方差等)进行求导,得到数据点数值、数据点数和每个参数之间的关系。
让我们看一个使用正态分布和一个简单的男性身高数据集的例子。
使用正态分布深入了解最大似然法的数学原理
让我们来看一个例子,如何使用最大似然法来拟合一组数据点的正态分布,其中只有一个特征:以厘米为单位的身高。正如我们之前提到的,我们需要计算一些参数:*均值和方差。
为此,我们必须知道正态分布的密度函数:

Density function for the normal distribution. Source Wikipedia
一旦我们知道了这一点,我们就可以计算每个数据点的似然函数。对于第一个数据点,它将是:

Likelihood equation for the first data point
对于整个数据集,考虑到我们的数据点是独立的,因此我们可以将似然函数计算为各个点的似然性的乘积,它将是:

Likelihood equation for the whole dataset
我们可以用这个函数和以对数方式表达它,这有助于后验计算和产生完全相同的结果。

Same equation expressed in a logarithmic way
最后,我们将似然函数相对于*均值的导数设置为零,得到一个表达式,其中我们获得第一个参数的值:

Derivative of the likelihood function for the mean, and Maximum Likelihood value for this parameter
惊喜!正态分布均值的最大似然估计就是我们直观预期的:每个数据点的值之和除以数据点的数量。
现在我们已经计算了*均值的估计值,是时候为其他相关参数做同样的事情了:方差。为此,就像以前一样,我们在似然函数中求导,目标是找到使观察数据的似然性最大化的方差值。

Maximum likelihood estimate for the variance
这与上一个案例一样,给我们带来了同样的结果,我们熟悉每天的统计数据。****
就是这样!我们已经看到了计算正态分布的最大似然估计背后的一般数学和程序。最后,让我们看一个快速的数字示例!****
男性身高的最大似然估计:一个数值例子
让我们举一个我们之前提到过的非常简单的例子:我们有一个某个地区男性身高的数据集,我们想使用最大似然法找到它的最优分布。****
如果我们没记错的话,第一步(在收集和理解数据之后)是选择我们想要估计的密度函数的形状。在我们的例子中,对于身高,我们将使用高斯分布,这也是我们在 ML 数学背后的一般推理中看到的。让我们重新看看定义这种分布的公式:

Density function for the normal distribution. Source Wikipedia
此外,让我们只恢复数据集的一个点的似然函数。

Likelihood equation for the first data point
想象我们的数据向量 X** ,在我们的例子中如下:**

Data vector of male heights
我们有 10 个数据点(n = 10) 和每个数据点(d=1)** 一个特征。如果在上面所示的公式中,我们为每个数据点代入它们的实际值,我们会得到如下结果:**

Likelihood of the first two data points
如果在这些公式中,我们选择一个特定的*均值和方差值,我们将获得观察到具有这些特定*均值和方差值的每个高度值(在我们的例子中是 176 和 172cm)的可能性。例如,如果我们选择 180 厘米的*均值,方差为 4 厘米,我们将得到上面所示两点的如下可能性:****

Calculations of likelihood of observing points of 176 cm and 172 cm of height on a normal distribution with a mean of 180 cm and a variance of 4 cm
简要说明后,如果我们继续该过程以获得最适合数据集的最大似然估计值,我们将不得不首先计算*均值。对于我们的例子来说,非常简单:我们只需将数据点的值相加,然后将这个和除以数据点的数量。

Maximum likelihood estimate for the mean of our height data set
如果我们对方差做同样的处理,计算每个数据点的值减去*均值的*方和,并除以我们得到的总点数:

Variance and Standard deviation estimates for our height data set
就是它!现在我们已经计算了*均值和方差,我们已经拥有了建模分布所需的所有参数。现在,当我们得到一个新数据点时,例如,一个高度为 177 cm 的数据点,我们可以看到该点属于我们数据集的可能性:

Likelihood of the new data point belonging to our data set

Representation of the obtained normal distribution and the likelihood of the new data point
现在,如果我们有另一组数据,例如女性身高,我们做同样的程序,我们会有两个身高分布:一个是男性,一个是女性。
这样,我们可以使用两种分布来解决男性和女性身高的二元分类问题:当我们获得一个新的未标记身高数据点时,我们计算该新数据点属于两种分布的概率,并将其分配给该分布产生最高概率的类别(男性或女性)。****
结论
我们已经看到了什么是最大似然,它背后的数学原理,以及如何应用它来解决现实世界的问题。这给了我们解决下一个问题的基础,你们都一直在问:贝叶斯定理背后的数学,它非常类似于最大似然法。
来看看吧 关注我的 ,敬请关注!
就这些,我希望你喜欢这个帖子。请随时在 LinkedIn 上与我联系,或者在 Twitter 上关注我,地址是:jaimezorno。还有,你可以看看我其他关于数据科学和机器学习的帖子这里 。好好读!
额外资源
如果你想更深入地了解最大似然法和机器学习,请查看以下资源:
一如既往,有任何问题请联系我。祝你有美好的一天,继续学习。
概率学习 IV:贝叶斯背后的数学
支持分类和回归的贝叶斯定理的数学充分解释

在之前的两篇关于贝叶斯定理的帖子之后,我收到了很多请求,要求对定理的回归和分类用途背后的数学进行更深入的解释。
正因为如此,在上一篇文章中,我们介绍了最大似然原理背后的数学原理,以构建一个坚实的基础,让我们能够轻松理解并享受贝叶斯背后的数学原理。
你可以在这里找到所有这些帖子:
这篇文章将致力于解释贝叶斯定理背后的数学,当它的应用有意义时,以及它与最大似然法的差异。
闪回贝叶斯
正如在上一篇文章中我们解释了最大似然一样,我们将在这篇文章的第一部分记住贝叶斯定理背后的公式,特别是与我们在机器学习中相关的公式:

Formula 1: Bayes formula particularised for a Machine Learning model and its relevant data
如果我们将此公式放入与我们在上一篇文章中使用的关于最大似然的相同的数学术语,我们会得到以下公式,其中 θ是模型的参数,X 是我们的数据矩阵:

Formula 2: Bayes formula expressed in terms of the model parameters “θ” and the data matrix “X”
正如我们在致力于贝叶斯定理和机器学习的帖子中提到的,贝叶斯定理的优势是能够将一些关于模型的先前知识整合到我们的工具集中,使其在某些情况下更加健壮。
贝叶斯背后的数学解释
既然我们已经很快记住了贝叶斯定理是关于什么的,让我们充分开发它背后的数学知识。如果我们采用前面的公式,并且以对数方式表示它,我们得到下面的等式:

Formula 3: Bayes’ formula expressed in logarithms
还记得最大似然公式吗?等号右边的第一项你看着眼熟吗?

Formula 4: Likelihood function
如果有,说明你做足了功课,看了前面的帖子,理解了。等号右边的第一项正好是似然函数。这是什么意思?这意味着最大似然和贝叶斯定理以某种方式相关。
让我们看看当我们对模型参数求导时会发生什么,类似于我们在最大似然法中所做的,以计算最适合我们数据的分布(我们在上一篇文章中对最大似然法所做的也可以用于计算特定机器学习模型的参数,最大化我们数据的概率,而不是某个分布)。

Formula 5: Taking derivatives with respect to the model parameters
我们可以看到这个方程有两个依赖于θ 、的项,其中之一我们在之前已经看到过:似然函数关于θ的导数。然而,另一个术语对我们来说是陌生的。这个术语代表了我们可能拥有的关于模型的先验知识,稍后我们将看到它如何对我们大有用处。
让我们用一个例子来说明。
回归的最大似然和贝叶斯定理的比较
让我们用一个我们以前探索过的例子来看看这个术语是如何使用的:线性回归。让我们恢复等式:

Formula 6: Equation of linear regression of degree 1
让我们将这个线性回归方程表示为依赖于一些数据和一些未知参数向量θ 的更一般的函数。

Formula 7: Regression function
此外,让我们假设当我们使用这个回归函数进行预测时,存在某个相关误差ɛ**。然后,每当我们做一个预测 y(i) (忘记上面用于 LR 的 y,那个现在已经被 f 代替了),我们就有了一个表示回归函数得到的值的项,和某个相关的误差**。
所有这些的组合看起来像是:

Formula 8: Final form of the regression equation
获得模型 θ 的一个众所周知的方法是使用最小二乘法(LSM) 并寻找减少某种误差的参数集。具体来说,我们希望减少一个误差,该误差被公式化为每个数据点 y 的实际标签和模型 f 的预测输出之间的*方的*均差。

Formula 9: The error that we want to reduce in the Least squares method
我们将看到,试图减少这一误差相当于使用最大似然估计法最大化观察我们的数据与某些模型参数的概率。
首先,然而我们必须做出一个非常重要的假设,尽管自然假设:回归误差【ɛ(i】, 对于每一个数据点来说,都是独立于【x(I)(数据点)的值,并且正态分布着一个*均值 0 和一个标准差 σ。对于大多数错误类型,这种假设通常是正确的。
然后,特定参数集θ 的 ML 估计由以下等式给出,其中我们应用了条件概率的公式,假设 X 独立于模型参数的,并且 y(i) 的值彼此独立(为了能够使用乘法)

Formula 10: Likelihood function
这个公式可以读作:X 和 Y 给定 θ 的概率等于 X 的概率乘以 Y 给定 X 和θ 的概率。
对于那些不熟悉联合或组合和条件概率的人,你可以在这里找到一个简单易懂的解释。如果你仍然不能从最左边的术语找到最终结果,请随时联系我;我的信息在文末。
现在,如果我们像过去一样取对数,我们得到:

Formula 11: Same equation as above expressed in logs
如果 X(数据点的特征)是静态的并且彼此独立(就像我们之前在条件概率中假设的那样),那么 y(i)的分布与误差的分布(来自公式 8)相同,除了*均值现在已经被移动到 f(x(i)|θ而不是 0。这意味着 y(i)也有正态分布,我们可以将条件概率 p(y(i)|X,θ) 表示为:

Formula 12: Conditional probability of y(i) given the data and the parameters
如果我们使常数等于 1 以简化,并在公式 11 内替换公式 12,我们得到:

Formula 13: Logarithm of the Likelihood function
如果我们试图最大化它(对θ求导),项 ln p (X) 将不复存在,我们只有负*方和的导数:这意味着最大化似然函数相当于最小化*方和!****
Bayes 能做些什么来让这一切变得更好呢?
让我们恢复用对数表示的贝叶斯定理公式:

Formula 3: Bayes’ formula expressed in logarithms
等号右边的第一项,正如我们之前看到的,是可能性项,这正是我们在公式 13 中的内容。如果我们将公式 13 的值代入公式 3,考虑到我们也有数据标签 Y,我们得到:

Formula 14: Bayes formula expressed in terms on likelihood and logarithms
现在,如果我们试图最大化这个函数,以找到最有可能使我们的数据被观察到的模型参数,我们就有了一个额外项: ln p(θ)。还记得这个术语代表什么吗?就是这样,模型参数的先验知识。****
这里我们可以开始看到一些有趣的东西** : σ与数据的噪声方差相关。由于项 ln p(θ) 在求和之外,如果我们有一个非常大的噪声方差,求和项变小,以前的知识占优势。但如果数据准确,误差小,这个先验知识术语就没那么有用了 。**
还看不出用途?让我们用一个例子来总结这一切。
ML 与 Bayes:线性回归示例
假设我们有一个一阶线性回归模型,就像我们在这篇文章和之前的文章中一直使用的模型。
在下面的等式中,我已经将模型参数的 θs 替换为a【b(它们代表相同的东西,但符号更简单)并添加了误差项。

Formula 15: Our linear regression model
让我们使用 Bayes 估计,假设我们有一些关于 a 和b:ab的均值为 0,标准差为 0.1,均值为 1,标准差为 0.5。这意味着 a 和 b 的密度函数分别为:**

Formula 16: Density functions for a and b
如果我们移除常数,并将该信息代入公式 14,我们得到:

Formula 17: Final form of Bayes Formula
现在,如果我们用对 a 求导,假设所有其他参数为常数,我们得到以下值:

同样,对于 b,给我们一个带有两个变量的线性方程,从中我们将获得模型参数的值,该值报告观察我们的数据(或减少误差)的最高概率。
贝叶斯贡献在哪里?非常简单,没有它,我们将失去术语 100σ。这是什么意思?你看,σ与模型的误差方差有关,正如我们之前提到的。如果这个误差方差很小,说明数据是可靠的、准确的,所以计算出的参数可以取很大的值,这就可以了。****
然而,通过引入 100σ项,如果该噪声显著,它将迫使参数值更小,这通常使得回归模型的表现优于具有非常大的参数值的回归模型。
我们还可以在这里看到分母中的值 n,它表示我们有多少数据。与σ值无关,如果我们增加 n,这一项就失去了重要性。这突出了这种方法的另一个特点:我们拥有的数据越多,贝叶斯的初始先验知识的影响就越小。
就是这样:拥有以前的数据知识,有助于我们限制模型参数的值,因为加入贝叶斯总是会导致更小的值,这往往会使模型表现得更好。
结论
我们已经看到了贝叶斯定理、最大似然法及其比较背后的完整数学。我希望一切都尽可能清楚,并且回答了你的许多问题。
我有一些好消息:繁重的数学岗位结束了;在下一篇文章中,我们将讨论朴素贝叶斯,一种贝叶斯定理的简化,以及它在自然语言处理中的应用。
来看看吧 关注我的 ,敬请关注!
就这些,我希望你喜欢这个帖子。请随时在 LinkedIn 上与我联系,或者在 Twitter 上关注我,地址是:jaimezorno。还有,你可以看看我其他关于数据科学和机器学习的帖子这里 。好好读!
一如既往,有任何问题联系我。祝你有美好的一天,继续学习。
概率学习 V:朴素贝叶斯
概率机器学习的朴素模型。还是没那么幼稚…

亲爱的读者们,你们好。这是概率学习系列的第五篇文章。之前的帖子有:
我强烈鼓励你阅读它们,因为它们很有趣,充满了关于概率机器学习的有用信息。
在上一篇文章中,我们讨论了机器学习的贝叶斯定理背后的数学。这篇文章将描述这个定理的各种简化,这些使它更实用,更适用于现实世界的问题:这些简化被称为朴素贝叶斯。此外,为了澄清一切,我们将看到一个非常有说明性的例子,它展示了朴素贝叶斯如何应用于分类。
为什么我们不总是使用贝叶斯?
正如在以前的文章中提到的,贝叶斯定理告诉我们,当我们获得更多关于某事的证据时,如何逐步更新我们关于某事的知识。
我们看到,在机器学习中,这通过更新新数据证据中的某些参数分布来反映。我们还看到了如何使用贝叶斯定理进行分类,方法是计算一个新数据点属于某个类别的概率,并将这个新点分配给报告最高概率的类别。我们提到过,这种方法的优势在于能够将先前的知识整合到我们的模型中。
让我们恢复一下最基本的贝叶斯公式:

General version of Bayes Formula
该公式可以定制为计算一个数据点 x ,属于某个类 ci 的概率,如下所示:

Bayes formula particularised for class i and the data point x
像这样的方法可以用于分类:我们计算一个数据点属于每个可能类别的概率,然后将这个新点分配给产生最高概率的类别。这可用于二值和多值分类。
当我们的模型中的数据点具有不止一个特征时,贝叶斯定理应用的问题就出现了:计算似然项 P(x|ci) 并不简单。该术语说明了给定某个类别的数据点(由其特征表示)的概率。如果这些特征在它们之间是相关的,那么这个条件概率计算的计算量会非常大。此外,如果有许多特征,并且我们必须计算所有特征的联合概率,计算也可能相当广泛。
这就是为什么我们不总是使用贝叶斯,而是有时不得不求助于更简单的替代方法。
那么什么是朴素贝叶斯呢?
朴素贝叶斯是贝叶斯定理的简化,它被用作二元多类问题的分类算法。之所以称之为幼稚,是因为它做出了一个非常重要但却不太真实的假设:数据点的所有特征都是相互独立的。通过这样做,它极大地简化了贝叶斯分类所需的计算,同时保持了相当不错的结果。这类算法通常被用作分类问题的基线。
让我们看一个例子来阐明这是什么意思、以及与贝叶斯的区别:假设你喜欢每天早上去你家旁边的公园散一会儿步。这样做了一段时间后,你开始遇到一个非常聪明的老人,他有时会和你走同样的路。当你遇到他时,他会用最简单的术语向你解释数据科学的概念,优雅而清晰地分解复杂的事物。
然而,有些日子,当你出去散步,兴奋地想听到更多老人的消息时,他却不在了。那些日子你希望你从未离开过你的家,并感到有点难过。

One of your lovely walks in the park
为了解决这个问题,你在一周内每天都去散步,并记下每天的天气情况,以及老人是否外出散步。下表显示了您收集的信息。“散步”一栏指的是老人是否去公园散步。

Table with the information collected during one week
利用这些信息,以及这位数据科学专家曾经提到过的一些东西,朴素贝叶斯分类算法,你会根据当天的天气情况计算出老人每天出去散步的概率,然后决定你是否认为这个概率足够高,让你出去尝试遇见这位睿智的天才。
例如,如果我们在字段值为“否”时将每个分类变量建模为 0,在字段值为“是”时建模为 1,那么我们表格的第一行将是:
111001 | 0
其中竖线后的 0 表示目标标签。
如果我们使用正态贝叶斯算法来计算每种可能的天气情况下每个类别(步行或不步行)的后验概率,我们将必须计算每个类别的 0 和 1 的每种可能组合的概率。在这种情况下,我们必须为每个类计算 2 的 6 次方个可能组合的概率,因为我们有 6 个变量。一般推理如下:

这有各种各样的问题:首先,我们需要大量的数据来计算每个场景的概率。然后,如果我们有这些可用的数据,计算将比其他类型的方法花费更长的时间,并且这个时间将随着变量或特征的数量而大大增加。最后,如果我们认为这些变量中的一些是相关的(例如,阳光与温度),我们将不得不在计算概率时考虑这种关系,这将导致更长的计算时间。
朴素贝叶斯是如何修复这一切的?通过假设每个特征变量独立于其他变量:这意味着我们只需计算给定每个类别的每个单独特征的概率,将所需的计算从 2^n 减少到 2n。同时,这意味着我们不关心变量之间可能的关系,比如太阳和温度。
让我们一步一步地描述它这样你们就能更清楚地看到我在说什么:
- 首先,我们使用上表计算每个类别的先验概率。
 

Prior probabilities for each class
2.然后,对于每个特征,我们计算给定每个类别的不同分类值的概率(在我们的示例中,我们只有“是”和“否”作为每个特征的可能值,但这可能因数据而异)。以下示例显示了特征“Sun”的这种情况。我们必须对每个特性都这样做。

Probabilities of sun values given each class
3.现在,当我们获得一个新的数据点作为一组气象条件时,我们可以通过将给定类别的每个特征的个体概率与每个类别的先验概率相乘来计算每个类别的概率。然后,我们将这个新数据点分配给产生最高概率的类。
让我们看一个例子。假设我们观察以下天气状况。

New data point
首先,给定这些条件,我们将计算老人行走的概率。

Probabilities needed to calculate the chance of the old man walking
如果我们做所有这些的乘积,我们得到 0.0217 。现在让我们做同样的事情,但是对于另一个目标类:不走。

Probabilities needed to calculate the chance of the old man not walking
同样,如果我们做乘积,我们得到 0.00027 。现在,如果我们比较两种可能性(男人走路和男人不走路),我们得到一个男人走路的更高的可能性,所以我们穿上运动鞋,拿一件外套以防万一(有云),然后去公园。
注意在这个例子中我们没有任何概率等于零。这与我们观察到的具体数据点以及我们拥有的数据量有关。如果任何一个计算出的概率为零,那么整个乘积将为零,这是不太现实的。为了避免这些,使用了被称为*滑的技术,但是我们不会在这篇文章中讨论它们。
就是它!现在,当我们醒来,想要看到我们会发现老人在散步的机会时,我们所要做的就是像前面的例子一样,看看天气情况,做一个快速的计算!
结论
我们已经看到了如何使用贝叶斯定理的一些简化来解决分类问题。在下一篇文章中,我们将讨论朴素贝叶斯在自然语言处理中的应用。
就这些,我希望你喜欢这个帖子。要获得更多关于数据科学和机器学习的资源,请查看下面的博客:如何学习机器学习。谢谢,祝你阅读愉快!
其他资源
如果您渴望了解更多信息,您可以使用以下资源:
一如既往,有任何问题请联系我。祝你有美好的一天,继续学习。
概率学习 VI:隐马尔可夫模型
马尔可夫链和马尔可夫模型变得简单

朋友们,你们好!这是我们概率学习系列的第六篇文章,列出来是为了防止你错过之前的文章:
我强烈建议你阅读它们,因为它们很有趣,充满了关于概率机器学习的有用信息。然而,如果你不想读它们,那绝对没问题,这篇文章不需要通过一点概率知识就能理解。
此外,不要担心,我不会在本文中包括任何复杂的数学:它的目的是奠定隐马尔可夫模型的理论背景,展示如何使用它们,并谈论它的一些应用。
我们已经见过 Bayes 牧师了,今天我们要去见另一个在博弈论和概率世界里非常有影响力的人。这不是别人,正是安德烈·马尔科夫,他把马尔可夫链放到隐马尔可夫模型中
隐马尔可夫模型是概率机器学习世界的一个分支,对于解决涉及处理序列的问题非常有用,如自然语言处理问题或时间序列。一会儿,我们会看到这是为什么,但首先,让我们了解一下马尔可夫。
最后,在我们开始之前,这里有一些额外的资源可以让你的机器学习事业突飞猛进:
*Awesome Machine Learning Resources:**- For* ***learning resources*** *go to* [***How to Learn Machine Learning***](https://howtolearnmachinelearning.com/books/machine-learning-books/)*! 
- For* ***professional******resources*** *(jobs, events, skill tests) go to* [***AIgents.co — A career community for Data Scientists & Machine Learning Engineers***](https://aigents.co/)***.***
这个安德烈·马尔科夫是谁?

Image of Andrei Markov
安德烈·马尔科夫(1856-1922)是一名俄罗斯数学家,在圣彼得堡大学教授概率论,同时也是一名非常活跃的政治人物。他研究了连续分数、中心极限定理和其他数学成果,然而,他最被人们铭记的是他在概率论方面的工作,特别是对随机过程的研究;我们一会儿将要讨论的马尔可夫链。
马尔可夫链:概率序列
让我们从马尔可夫提议的最基本元素开始:马尔可夫链。在概率论中,马尔可夫链或马尔可夫模型是一种特殊类型的离散随机过程,其中一个事件发生的概率仅取决于紧接在之前的事件。
潜在的假设是,给定现在,未来独立于过去。换句话说,如果我们知道系统或变量的当前状态或值,我们不需要任何过去的信息来尝试预测未来的状态或值。

Example of a two state Markov Chain
马尔可夫链通常由一组状态和每个状态之间的转移概率定义。在上面的例子中,显示了两个状态的马尔可夫链:我们有状态 A 和 B 以及四个转移概率:再次从 A 到 A,从 A 到 B,从 B 到 A,再次从 B 到 B。这些转移概率通常以矩阵的形式表示,称为转移矩阵,也称为马尔可夫矩阵。

One possible transition matrix for this chain
元素 ij 是从状态 j 过渡到状态 i 的概率。在某些情况下,会使用转置符号,因此元素 ij 代表从状态 I 到状态 j 的概率。因此,我添加了‘to’和‘from’只是为了澄清。总的来说,该系统看起来像这样:

Diagram of a Markov Chain with the transition probabilities
我们如何计算这些概率?这个答案你可能已经听过一百万次了:来自数据。
想象一下我们的马尔可夫链中的状态是晴天和雨天。为了计算从一个状态到另一个状态的转移概率,我们只需要收集一些代表我们想要解决的问题的数据,计算从一个状态到另一个状态的转移次数,并对测量结果进行归一化。下图显示了在我们的示例中如何实现这一点。

Calculations of transition probabilities from data
目前,马尔可夫链看起来就像任何其他的状态机,其中我们有状态和状态之间的转换。然而,在这篇文章的后面,我们将会看到它们是多么的特别。
好了,现在我们知道了什么是马尔可夫链,以及如何计算相关的转移概率,接下来我们继续学习隐马尔可夫模型。
隐马尔可夫模型:发现未知
隐马尔可夫模型是一种概率模型,它试图基于一些其他的 观察到的变量来找到具有某个值的某个 隐藏变量的值或概率。这些变量通常被称为隐藏状态和观察状态。
一个系统的状态可能只是部分可观测的,或者根本不可观测,我们可能不得不根据另一个完全可观测的系统或变量来推断其特征。
使用前面的示例,想象我们添加了以下信息。每天,我们都有可能接到住在不同大陆的最好的朋友约翰的电话,这种可能性取决于当天的天气情况。利用后一种信息(如果我们接到电话或没有接到电话- 观察变量 ) 我们想推断前一种信息(约翰生活的大陆的天气-隐藏变量)

Hidden and observed variables for our problem
这里显示的概率定义了约翰在某一天给我们打电话的可能性,这取决于该天的天气,这些概率被称为 发射概率 。他们定义了在给定隐藏变量的某个值的情况下,看到某个被观察变量的概率。
知道了这些概率,加上我们之前计算的转移概率,以及隐变量的先验概率(有多可能是晴天或雨天),我们就可以试着找出某段时间的天气,知道约翰在哪一天给我们打了电话。
让我们用简单的统计数据来看看如何解决这个问题:假设约翰连续两天没有给我们打电话。最有可能的天气情况是什么?为此,我们首先需要计算先验概率(即,在任何实际观测之前晴天或雨天的概率),这是我们从与转移概率相同的观测中获得的。

Calculations of prior probabilities
现在,我们准备解决我们的问题:连续两天,我们没有得到一个迹象表明约翰还活着。那么最有可能的天气情况是什么?正如我们在下图中看到的,我们有 4 种可能的情况要考虑:晴天接着晴天,晴天接着下雨,下雨接着晴天,最后下雨接着下雨。

Diagram of the process of calculating the probability for one weather scenario
在上图中,我们选择了第二个选项(晴天,然后下雨),并使用先验概率(第一天在没有任何观测的情况下是晴天的概率),从晴天到雨天的转换概率,以及在两种情况下没有接到电话的发射概率,我们通过简单地乘以所有上述概率计算出了整个事件发生的概率。
我们将不得不为每一个可能的天气场景(我们的例子中还剩 3 个)这样做,最后我们将选择一个产生最高概率的场景。(这叫做最大似然估计,在我之前的一篇文章中有完整的描述)。
连续两天,我们必须计算四种可能的情况。三天之内,我们会有八个场景。一共四天十六天。如果我们想计算一整周的天气,我们将有 128 种不同的情况。随着可能情况的数量呈指数级增长,很容易看到这种情况会如何失控,从而促使我们使用更实用、更智能的技术。
这不仅是因为我们有更多的情景,而且在每一个情景中,我们都有更多的计算,因为在链条中有更多的转变和更多的排放概率。
这就是马尔可夫链派上用场的地方。
让我们刷新一下马尔可夫链的基本假设:“给定现在,未来独立于过去”。
知道了这一点,隐马尔可夫模型的操作原理是,它逐渐地存储从长度 1 到 n-1 的场景链的概率,n 是我们想要推断隐藏状态的链的长度,而不是计算许多不同场景的概率。
这是什么意思?假设我们想在知道约翰给我们打电话的日子的情况下计算一整周的天气情况。为了计算最后一天的天气状况,我们将计算出那天是晴天的概率,给出通向晴天的最佳路径,对下雨的星期天做同样的事情,并只选择最高的一个。
这大大简化了前面的问题。

Intuition behind a Hidden Markov Model
递归地,为了计算周六晴天和雨天的概率,我们会做同样的事情,考虑减少一天的最佳路径。这意味着,在任何给定的一天,为了计算第二天可能的天气情况的概率,我们将只考虑在那一天达到的最好的概率——没有先前的信息。

At each given day we only use the BEST probabilities up to that day
在实践中,这是通过从第一时间步开始,计算观察隐藏状态的概率并选择最佳状态来完成的。然后,用那个最好的,我们在第二天做同样的事情,以此类推。让我们看看在我们的例子中是如何做到这一点的。
利用先验概率和排放概率,我们计算出第一天 T2 是晴天还是雨天的可能性。

Calculations of the probabilities of Monday being sunny and rainy
让我们看看第二天我们将如何继续:使用先前计算的晴天和雨天的最佳概率,我们将为第二天计算同样的概率,但是不使用我们上次使用的先验,我们将使用晴天和雨天的最佳计算概率。
为了做到这一点,我们首先来看看实际的观察结果是什么:假设星期一是晴天。那发生的概率是 0.375。现在,让我们来看看星期二是晴天:我们必须将星期一是晴天的概率乘以从晴天到晴天的转换概率,乘以晴天没有被约翰打电话的排放概率。这给了我们一个概率值 0,1575。

Calculations of probabilities of sunny and rainy for Tuesday
现在,假设星期一下雨。星期二是晴天的可能性有多大?为此,我们将周一下雨的最高概率(0.075)乘以从下雨到晴天的转换概率(0.4)乘以晴天且没有接到电话的排放概率,就像上次一样。这导致概率为 0.018,并且因为我们计算的前一个(周一晴和周二晴)更高(它是 0.1575),我们将保留前一个。
我们现在必须为一个多雨的星期二做同样的事情,保持两个计算概率中的最高值。如果我们继续这个链条,现在计算周三的概率:

Calculations of probabilities for Wednesday
如果我们对整个星期都这样做,我们会得到七天中最可能的天气情况,如下图所示:

Weather conditions for the whole week
通过这个过程,我们可以推断出任何时间段最可能的天气情况,只需知道 John 是否给我们打过电话,以及来自历史数据的一些先验信息。
就是它!现在你已经知道了隐马尔可夫模型背后的基本原理,让我们看看它的一些实际应用。
隐马尔可夫模型:应用
如前所述,hmm在处理序列时非常出色。正因为如此,它们在自然语言处理中被广泛使用,在这里短语可以被认为是单词序列。
hmm 用于许多 NLP 应用程序,但是让我们举几个具体的例子来巩固您头脑中的想法。
论文使用统计方法的实时在线无约束手写识别 讲述了使用 HMMs 将手写文档翻译成数字文本的。
我手机上有一个名为“钢笔打印”的应用程序,就是做这个的。它将手写文本作为输入,将其分解成不同的行,然后将整个内容转换成数字格式。下图显示了这样一个例子。

Pipeline of the Pen to Print app
有很多这样的应用程序,大多数时候它们使用一些概率方法,比如我们看到的隐马尔可夫模型。
另一篇论文, 为基于 HMM 的语音合成考虑全局方差的语音参数序列建模 做了类似的事情,但是用语音代替文本。
我认为,我们所有的虚拟助手,如 Siri、Alexa、Cortana 等,都是在以下过程中工作的:你用某种行动号召短语唤醒他们,他们开始积极倾听(或者他们是这么说的)。在这之后,你说的任何话,比如对某种音乐的请求,都会被麦克风拾取并从语音翻译成文本。然后这些文本被处理,我们得到想要的输出。
hmm 的其他用途包括从计算生物学到在线营销或为在线商店发现购买因果关系。
结论
我们已经看到了什么是隐马尔可夫模型,以及它们被用来解决实际问题的各种应用。未来会有更多概率学习的帖子,请关注我的,敬请关注!
就这些,我希望你喜欢这个帖子。请随时在 LinkedIn 上与我联系,或者在 Twitter 上关注我,地址是:jaimezorno。还有,你可以看看我其他关于数据科学和机器学习的帖子这里 。好好读!
额外资源
如果你想了解更多一点,从这篇文章中澄清你的学习,或者深入 HMMs 的数学,我在这里留下了一些我认为可能会很有用的信息。
有关机器学习和数据科学的更多资源,请查看以下资源库: 如何学习机器学习 !有关职业资源(工作、事件、技能测试),请访问AIgents.co——数据科学家职业社区&机器学习工程师 。
请尽情享受,如有任何疑问,请随时联系我!
人工智能冬天来临的概率
这篇文章讨论了人工智能领域是否正在走向另一个人工智能冬天的问题。
动机
行业和政府都在人工智能领域投入了大量资金,在过去 5 年里,许多人工智能相关的初创公司成立了。如果另一个人工智能冬天即将到来,许多人可能会失业,许多创业公司可能不得不关闭,就像以前发生的那样。此外,根据麦肯锡公司的数据,到 2025 年,即将到来的冬季和持续的成功之间的经济差异估计至少有数百亿美元。
本文的目的不是讨论人工智能的进步是否值得期待。相反,本文讨论和结果的目的是告诉读者人工智能研究有多大可能取得进展。
分析:是什么导致了人工智能冬天?
关于这两个 AI winters 的详细概述,请查看我关于这个主题的第一篇第一篇和第二篇第三篇中型文章。
在这一节中,AI 冬天的主要原因是从以上对以前冬天的讨论中提取出来的。
首先,可以观察到的一个重复模式是,最初点燃兴奋情绪,但后来证明是膨胀的承诺是人工智能冬天的主要原因。例如,在对结果进行诚实的评估后,政府资金在两次 AI 冬季都被削减了。这一进展被高估了,因为人工智能最初导致了各个领域的重大改进,非常快。这表明大部分工作已经完成,只有一些小问题需要解决。然而,后来的事实证明,这些问题一开始就不是那么小。莱特希尔报告,第一次人工智能冬季的主要贡献者说:“到目前为止,该领域的任何发现都没有产生当时承诺的重大影响。”同样,1984 年 AAAI 小组表示:“这种不安是由于担心对人工智能的期望可能过高[……]”
第二,经费的削减对两个人工智能领域的研究都产生了重大影响。在第一个人工智能冬天,Lighthill 报告导致英国除了两所大学之外的所有大学都被削减了资金,并进一步导致欧洲和美国的削减。在第二个人工智能冬天,DARPA 的资金减少了。此外,20 世纪 80 年代末许多人工智能相关创业公司的商业失败标志着第二次人工智能冬天。
第三,技术限制,如 20 世纪 60 年代经历的感知机,抑制了进步。感知器最初被认为很快就会“意识到自己的存在”,但当时它无法解决异或问题。同样,专家系统在 1980 年代也面临着局限性。他们不能解决像视觉或语言这样的基本问题,并且缺乏常识。
因此,在评估另一个人工智能冬季的可能性时,应仔细检查以下方面:
- 与实际结果相比的期望和承诺;
 - 来自政府和行业的资金;
 - 技术限制。
 
许多技术表现出与上述类似的模式。为了进一步缩小关注范围,有必要弄清楚 AI 是如何偏离其他技术的。尽管在某些方面相似,人工智能似乎很容易受到夸大的估计和技术限制的影响。人工智能不同于其他技术的一些原因是:
1.智力是高度多维的:
在某种程度上,人工智能研究人员认为,通过解决象棋,智力之谜将得到解决。这被证明是错误的,因为智力不仅仅包括有意识的、战略性的思考。象棋只是智能宇宙中的一个微小粒子。研究人员把它放在如此重要的位置是因为它对人类来说很难,这导致了第二个原因。
2.莫拉维克悖论
国际象棋需要更高层次的思维,在我们的进化史上是一种非常新的技能,这可能是为什么它对人类来说相对困难并因此与智力相关联的原因。另一方面,视觉是古老的,主要是潜意识的,这导致人们认为它很容易,但没有理由认为它没有更高层次的思考难,甚至更难。这是莫拉维克悖论,人们可以说人工智能研究人员已经成为这种说法的牺牲品,因为他们低估了我们下意识的过程,如感觉运动技能或常识。
3.与达到人类水*的智力相关的炒作和恐惧
正如 I. Jordan 指出的,对能够实现智能的机器的大肆宣传和恐惧很容易导致夸大其词,并引起媒体的关注,这在其他领域不太常见。
考虑到这些原因,可以用适当的框架来分析即将到来的人工智能冬天的可能性。
人工智能冬天来临的概率
随后,评估了即将到来的人工智能冬天的可能性。研究了人工智能及其公众接受的现状。此外,对于预先提取的关键区域,比较当前和历史的冬前时间。概括来说,这些领域是:
- 与实际结果相比的期望和承诺;
 - 来自政府和行业的资金;
 - 技术限制。
 
期望和承诺
许多公众人物表达的观点让人想起 20 世纪 50 年代早期人工智能研究人员的观点。通过这样做,前一组为未来的进步创造了兴奋,或炒作。例如,库兹韦尔不仅以预测奇点而闻名,人工超级智能将在 2045 年无处不在,而且人工智能将在 2029 年超过人类智能。以类似的方式,斯科特预测“到 2035 年,人类的思维没有理由也不可能跟上人工智能机器。”此外,Ng 将人工智能视为新的电力。
这种说法为人工智能设定了很高的期望,并引发了炒作。因此,炒作的现象和它如何与人工智能的当前状态相关被调查。
炒作和炒作周期
Gartner 的炒作周期是一个常用的工具。它有实际应用,让我们很容易做出预测,但它的有效性没有科学依据。首先,它不是为科学方法开发的工具。这是为商业决策制作的程式化图表。也就是说,已经有人尝试从经验上验证不同技术的炒作周期。可以得出结论,炒作周期是存在的,但其具体模式变化很大。

Figure 1: Gartner’s Hype Cycle
周期的关键阶段是高峰期和低谷期,在高峰期,人们的兴趣和兴奋程度最高,而在低谷期,最初的期望无法实现。在这里,人们对这个领域的兴趣是最低的。然后,油田慢慢恢复,并达到产量的稳定期。
正如门泽斯所证明的,炒作周期在 20 世纪 80 年代 AAAI 会议的与会人数中得到了很好的体现。首先,会议开始时,门票销售迅速增加,达到高峰,然后这些数字迅速下降。目前,NIPS 等会议的与会者人数达到甚至超过了 20 世纪 80 年代 AAAI 的峰值,而且他们的规模正在迅速扩大。
在人工智能初创公司的风险投资基金、职位空缺和收入电话提及中,也可以观察到对该领域兴趣的类似模式。炒作研究人员指出,覆盖的数量很重要,但它必须得到定性情绪的支持。媒体文章中的情感分析显示,从 2016 年到 2018 年,人工智能相关的文章变得积极 1.5 倍。尤其是 2016 年 1 月到 2016 年 7 月期间,情绪发生了转移。这一进步可能与 2016 年 1 月 Alpha Go 的公开发布以及 3 月战胜世界冠军 Lee Sedol 有关。

随着炒作周期的趋势,这可能导致另一个票房收入、资金和工作机会迅速暴跌的幻灭低谷。然而,AI 是一个描述许多技术的非常宽泛的术语。这使问题变得更加复杂,因为在人工智能这个大术语下的每项技术都有自己的炒作周期,而炒作周期之间以及与人工智能之间的相互作用,总的来说,仍然不清楚。
更进一步,对这些说法进行了更深入的研究,评估人工智能兴趣的快速上升是否只是夸大承诺的结果,或者这些说法是否有坚实的基础。
与专家意见的比较
现在,公众人物做出的声明和承诺被与领先的人工智能研究人员的调查相比较。2017 年,对 352 名机器学习研究人员进行了一项调查,这些研究人员在领先的会议上发表了论文。这项调查预测,高级机器智能在 45 年内出现的几率为 50%,在未来 9 年内出现的几率为 10%。然而,劳动力的完全自动化被预测要晚得多,有 50%的可能性在未来 122 年内发生。
这项研究呈现的结果与库兹韦尔等未来学家的预测相去甚远。此外,一项关于人工智能预测的元研究发现了一些证据,表明无论何时做出预测,高级机器智能的大多数预测都是在未来 20 年左右。本质上,这指向了人工智能未来预测的不可靠性。此外,对高级机器智能的每一个预测都必须持保留态度。
总之,在当前的人工智能格局中存在一个炒作周期模式,导致人们的兴趣很快可能会下降。此外,乐观的预测是由公众人物做出的,但经验证据质疑它们的有效性。
然而,像 Ng 这样将人工智能视为新的电力的言论,更多地是指该行业的现状。因此,接下来就要考察企业和政府的资助。
投资和融资
资金在人工智能研究中一直扮演着重要的角色。正如亨德勒指出的,由于现有的研究项目仍在继续,政府资金的削减只能在几年后才能感觉到。因此,随着时间的推移,新研究项目的缺乏变得明显起来。这意味着目前需要减少资金,才能在未来几年被察觉。
2018 年 4 月,欧盟成员同意就人工智能研究进行合作。发布了一份关于人工智能的通讯,在 2018 年至 2020 年期间为人工智能研究投入了 17 亿美元的资金。随后,2018 年 6 月,欧盟委员会提出创建数字欧洲资助计划,重点关注五个关键领域,总资助额为 92 亿欧元,其中 25 亿专门用于人工智能研究。
2018 年 3 月,美国政府提出了确保美国“仍然是人工智能的全球领导者”的目标。后来,在 2018 年 9 月,DARPA 宣布了一项 20 亿美元的活动,为下一波人工智能技术提供资金。作为直接反对,中国宣布了到 2030 年在人工智能方面领先世界的目标。因此,中国已经启动了几项人工智能计划。这些相互矛盾的说法促使许多人采用“人工智能竞赛”这个术语来指代美国和中国之间在人工智能领域的领导权之战。这类似于 20 世纪美国和苏联之间的太空竞赛,两国争夺太空旅行的主导权。当时,这场比赛引发了大量的资金和研究。同样,“人工智能竞赛”的心态可能会使未来几年的资金减少不太可能。这是对即将到来的人工智能冬天的一个有力支持,因为以前的冬天伴随着政府资金的减少。
另一个关键点是不断增长的人工智能产业。过去的人工智能研究人员一直非常依赖政府资助,但根据麦肯锡公司的数据,2016 年非科技公司在人工智能上花费了 260 亿至 390 亿美元,科技公司在人工智能上花费了 200 亿至 300 亿美元。
另一方面,2025 年的市场预测差异巨大,从 6.44 亿美元到 1260 亿美元不等。这种差异展示了即将到来的人工智能冬天和另一个繁荣时期之间的经济差异。
综上所述,政府资助非常扎实,“AI 竞赛”的心态使得这种情况很可能会持续下去。此外,该行业目前正在蓬勃发展。然而,市场预测却大相径庭。
为了确定哪个预测更有说服力,人工智能在过去几年取得的进展与对当前方法的批评有关。
评估进展
为了在适当的框架下查看对当前人工智能技术的批评,评估了从 2012 年到今天(2019 年 4 月)取得的进展。
正如我们之前看到的那样,人工智能和机器学习在许多方面都变得越来越受欢迎。一些关键事件在景观的形成中脱颖而出。2012 年,一个卷积神经网络以较大优势赢得了 ImageNet 竞赛。这与物体检测的进展相结合,彻底改变了计算机视觉的领域,从手工制作的特征工程到学习表示,从而使自动驾驶汽车在可预见的未来变得可行。在自然语言理解领域也取得了同样令人印象深刻的成果。深度学习已经启用了所有流行的语音助手,从 Alexa 和 Siri 到 Cortana。
深度神经网络的强化学习在游戏中取得了令人印象深刻的结果。2014 年,DeepMind 使用深度 q 学习器解决了 50 个不同的 Atari 游戏,而没有改变模型的架构或超参数。这种任务的灵活性是前所未有的,这导致他们很快被谷歌收购,并随后凭借 AlphaGo 和 AlphaStar 等成就领先于强化学习领域。
最后,在过去几年中,生成对抗网络(GAN)在生成例如人脸的图像方面已经取得了令人印象深刻的结果。
本质上,深度学习已经在许多行业取得了突破性的成果。
对深度学习的批评
在这一章中,讨论了对深度学习的批评。正如所证明的那样,深度学习处于人工智能领域进步的最前沿,这就是为什么对深度学习潜力的怀疑态度也是对人工智能前景的批评。这与 20 世纪 80 年代的情况类似,当时专家系统主宰了这个领域,它们的崩溃导致了一个冬天。如果深度学习方法面临与它们的历史对手类似的技术障碍,可以预期类似的结果。
对深度学习的批评主要集中在几个方面:深度学习的局限性、脆弱性和缺乏无监督学习。
深度学习的局限性
“如今,从事深度学习的人比以往任何时候都多——比 2014 年多了大约两个数量级。在我看来,这是 5 年来最慢的进展速度。是时候来点新鲜的了。”
Francois Chollet,Twitter 上 Keras 的创建者
由于这句话摘自 Twitter,其有效性值得怀疑,但它似乎与他提出的类似论点一致,并且很好地抓住了普遍的感觉。在他的书《用 Python 进行深度学习》(Deep Learning with Python)中,Chollet 有一章专门讨论了深度学习的局限性,他在书中写道:“它(深度学习)不会解决更基本的问题,即深度学习模型在它们所能表示的方面非常有限,并且人们可能希望学习的大多数程序都无法表达为数据流形的连续几何变形。”作为一个思想实验,他提出了一个巨大的数据集,其中包含标有程序描述的源代码。他认为,深度学习系统永远无法以这种方式学习编程,即使有无限的数据,因为像这样的任务需要推理,并且没有从描述到源代码的可学习映射。他进一步阐述说,增加更多的层和数据使这些限制看起来正在消失,但只是表面上的。
他认为,从业者很容易陷入一个陷阱,认为模型理解他们承担的任务。但是,当模型呈现的数据与训练数据中遇到的数据不同时,它们可能会以意想不到的方式失败。他认为这些模型没有对现实的体验,因此它们不能理解它们的输入。这类似于德雷福斯在 20 世纪 80 年代提出的论点,他认为人工智能需要体现。不幸的是,对体现在人工智能中的作用还没有一个清晰的理解。以类似的方式,这指向了深度学习方法尚未解决的基本问题,即推理和常识。
简而言之,Chollet 警告深度学习实践者不要夸大深度学习的能力,因为基本问题仍然存在。
深度学习是脆弱的
用于描述深度学习模型的通用术语是脆弱的。有几个例子可以说明为什么这样的描述是准确的,包括对抗性攻击、缺乏概括能力和缺乏数据。对这些缺陷和最终的预防机制进行了详细的讨论。
1.对抗性攻击:已经证明深度学习算法容易受到通过对抗性例子的攻击。对手使用以人类不可识别的方式修改的数据来彻底影响深度学习模型的行为。有多种方法可以创造对立的例子。在一种技术中,通过另一种学习算法将噪声添加到图像中,以便影响分类,而不可见。

Figure 3: A demonstration of fast adversarial example generation applied to GoogLeNet on ImageNet.
通过这种技术,可以以这样的方式改变图像,即可以实现指定的分类,即使它与原始分类非常不同(如人类可以容易地区分的“熊猫”和“长臂猿”)。当对抗攻击的方法已知时,可以通过用对抗的例子增加训练集来防御它。澄清一下,防御特定的对抗性攻击是可能的,但是一般来说,防御对抗性攻击是困难的。尽管如此,最*开发的一些成功的方法在这个问题上显示出了希望。通过限制模型的输出空间,已经使用了防御一般对抗的正式方法。像区间边界传播这样的技术在不同的流行图像集中具有最先进的准确性。
Alcorn 等人指出,当熟悉的物体以奇怪的姿势出现时,也会发生极端的错误分类。诸如此类的例子表明,深度学习模型对物体的理解可能相当幼稚。

Figure 4: The Google Inception-v3 classifier fails to recognize familiar objects in strange poses.
此外,对抗性攻击表明了一个更深刻的潜在问题——缺乏可解释性。由于深度学习模型的黑盒性质,预测网络正在做什么是很难的。这些对抗性攻击表明,模型可能已经找到了在训练数据中对对象进行分类的最佳方法,但它可能仍然无法捕捉到真实世界的浩瀚。
也就是说,在提高模型的可解释性方面已经做了很多工作,主要是在视觉空间中通过语义词典、显著性图和激活地图集等方法。这些作品代表了对深度学习模型隐藏层的深入了解。
2.缺乏归纳能力:此外,深度学习模型在归纳所提供的训练数据之外存在问题。Kansky 等人证明了在 Atari 游戏 Breakout 上训练的模型在环境发生微小变化时会失败。例如,稍微改变桨的高度会导致药剂的性能非常差。类似的批评可以应用于任何强化学习系统。
Cobbe 比较了强化学习代理和监督学习的评估,并得出结论,在代理接受培训的环境中评估代理就像用测试集评估监督学习者的表现一样。不同的是,第一种情况被很好地接受和实践,第二种情况在任何意义上都是不被容忍的。
为了解决这个问题,Cobbe 作为 OpenAI 的一部分,设计了一个通用化的基准,以促进该领域的工作。此外,强化学习领域的迁移学习最*在 OpenAI 的 Dota 代理中看到了令人印象深刻的结果。他们宣布,通过使用迁移学习技术,尽管规则和模型大小发生了重大变化,他们仍然能够继续对代理进行训练。使用类似的方法,可以改善代理中缺乏通用性的问题。
3.缺乏数据:正如《数据的不合理有效性》所展示的,数据在深度学习中是必不可少的。此外,可用数据的增加是深度学习革命的主要贡献者之一。同时,并不是每个领域都能接触到海量数据。
也就是说,有两种方法可以解决这个问题:创建更多的数据或者创建需要更少数据的算法。Lake 等人的研究表明,人类能够从几个例子中学习视觉概念。

Figure 5: Test yourself on one shot learning. From the example boxed in red, can you find the others in the array? On the left is a Segway and on the right is the first character of the Bengali alphabet.
单次或少次学习中的最*方法已经取得了实质性的改进,在这些方法中,仅用一个或几个数据点(例如,给定类别的一个图像)来呈现算法。与此同时,迁移学习方法也有了很大的改进。通过使用在大型数据集上预先训练的模型作为基础,可以显著减少在新数据集上的训练时间。
总而言之,深度学习模型被恰当地描述为脆弱的。也就是说,研究人员正在研究解决这个问题的有希望的方法。
监督学习的优势
深度学习实现的大多数成就都是通过监督或强化学习实现的。然而,正如 LeCun 指出的那样,人类大多是通过观察环境以无监督的方式进行学习。此外,据粗略估计,大约 95%的数据是非结构化的。此外,标注是一个耗时且昂贵的过程,但标签仅包含关于每个数据点的非常少的信息。这就是为什么 LeCun 认为该领域必须更多地转向无监督学习。
一种特殊类型的无监督学习,有时称为自我监督学习,在过去几年中获得了关注。自监督学习过程利用训练数据的某些属性来创建监督信号。例如,在一个视频剪辑中,所有帧都是连续的,研究人员利用这一特性,让模型预测剪辑的下一帧,这很容易评估,因为事实是数据固有的。类似的方法可以用于文本或音频信号。此外,可以使用数据的不同特征,例如旋转图像和预测正确的角度。直觉告诉我们,为了将旋转后的图像恢复到其原始形式,模型需要了解世界的属性,这在不同的任务中也是有用的,如物体识别。这被证明是正确的,因为该模型可以通过迁移学习在分类任务中取得很好的结果。当观察网络的第一层时,过滤器非常类似于监督模型,甚至更多样。

Figure 6: First layer filters learned by a AlexNet model trained on (a) the supervised object recognition task and (b) the self-supervised task of recognizing rotated images.
如果研究人员不予理会,这种批评可能会对深度学习和人工智能产生不利影响,但似乎并非如此。OpenAI 已经展示了一些有希望的结果,这些结果是通过今年早些时候使用 GPT-2 transformer 语言模型的无监督学习实现的。这个模型可以通过使用一个非常大的模型和来自 Reddit 的大量数据来生成非常像人类的文本。他们使用一种自我监督的学习方法,利用文本的顺序性,让模型预测下一个单词。使用相同的架构,MuseNet,一个作曲的模型,最*已经被创建。
无监督学习有可能解决深度学习中的重大障碍。目前的研究证据表明,对这种学习技术的进展持乐观态度。
结论
人工智能研究人员、公司、技术和对人工智能的认知在许多不同层面上存在复杂的相互作用。因此,很难做出任何预测。然而,我们可以观察到一些与历史上的冬前时期不同的关键现象。
在过去,对政府资金的依赖非常强烈,而这个行业很弱。今天的情况远非如此;许多大公司,如谷歌、脸书和阿里巴巴,仅在人工智能技术上的投资就超过了人工智能行业在 20 世纪 80 年代繁荣时期的价值。更重要的是,这些公司不仅在人工智能上投入巨资,还将它大量融入到产品中。这为该领域提供了坚实的基础,即使公众情绪开始转变。类似地,“人工智能竞赛”心态提供了稳定性,这降低了政府资助下降的风险。
同样重要的是对深度学习及其局限性的批评。尽管其中大部分是有效的,但证据表明研究人员已经在研究解决方案,或者已经意识到这项技术的先天局限性。
此外,无监督学习,特别是自我监督学习,通过允许使用大量的未标记数据和节省大量的繁琐劳动,提供了有希望的机会。
也就是说,这个领域的期望太高了。关于机器达到人类智能的预测是不可靠的。此外,随着该领域在许多规模上快速增长,炒作周期模式可以在当前的会议与会者人数中表现出来。随着炒作周期模式的变化,无法做出任何特定的陈述或预测。
最后,历史视角展示了该领域的波浪式本质。每天都在创造新技术;它们中的大量灭绝了;有些正在复苏。从这个角度来看,为当前方法的消亡做好准备,以及寻找一些值得复兴的被遗忘的技术,似乎已经足够了。
总结一下:对进一步人工智能研究的资助目前看起来很稳定。然而,有一些技术限制,加上非常高的期望,可能会导致另一个人工智能的冬天。
“人们担心计算机会变得太聪明并接管世界,但真正的问题是它们太笨了,它们已经接管了世界。”
佩德罗·多明戈斯
感谢阅读!
留下一个👏如果你喜欢!
对来源感兴趣?查看我的 论文 关于本文出处的话题。
用概率论寻找 2019 年的最佳约会策略
了解一些统计理论如何让找到如意郎君变得稍微容易一点?

Image from Pixabay.com
这是探索爱情和约会的第一部分。点击查看第 2 部分。
让我从大多数人都会同意的事情开始:约会很难!!!
(如果你不同意,那太棒了!!!你可能不会像我一样花那么多时间阅读和撰写中型帖子
如今,我们每周花无数时间在 Tinder 或微妙的亚洲约会上点击个人资料,给我们觉得有吸引力的人发信息。
当你最终“明白”时,你知道如何为你的 Tinder 的个人资料拍摄完美的自拍照,你可以毫不费力地邀请你韩语班的那个可爱女孩吃饭,你会认为找到完美先生/夫人并不难。没有。!!我们很多人就是找不到合适的匹配。
约会对凡人来说太复杂、太可怕、太困难了!!!

Do social media and online dating apps make it easier to find The One? Image by amrothman from Pixabay
我们的期望太高了吗?我们是不是太自私了?还是我们注定不会遇见那个人?放心吧!这不是你的错。你只是没有做数学计算。
在你开始满足于更严肃的事情之前,你应该和多少人约会?
这是一个棘手的问题,所以我们必须求助于数学和统计学家。而他们有一个答案: 37% 。
那是什么意思?
这意味着在你可能约会的所有人中,假设你预见自己在未来 10 年内会和 100 人约会(对我来说更像是 10 人,但那是另一个讨论),你应该先约前 37%或 37 人,然后满足于第一个人之后的第一个人比你在之前见过的人更好(或者如果这样的人没有出现,就等到最后一个)
他们是怎么找到这个号码的?让我们挖掘一些数学知识。
天真(或绝望)的方法:
比方说,我们预见到 N 个潜在的人将依次进入我们的生活,他们根据一些“匹配/最佳伴侣统计”进行排序。当然,你希望最终与排名第一的人在一起——姑且称此人为 X 。

If you can rank these N people. How can you find X?
在我们探索最佳约会策略之前,让我们从一个简单的方法开始。如果你不顾一切地想在 Tinder 上找到伴侣或约会对象,以至于决定和第一个出现的人结婚,那该怎么办?这个人是 X 的几率有多大?
嗯!是 1/N 。
随着我们考虑的时间范围越大,n 越大,这个概率将趋向于 T2 为零。好吧,你可能不会在 20 年内和 10,000 个人约会,但即使是 1/100 的几率也足以让我觉得这不是一个好的约会政策。
那么我们该怎么办呢?
我们做人们约会时会做的事。也就是说,我们不是承诺第一个选项,而是想认识几个潜在的伴侣,探索我们约会领域的质量,并开始安顿下来。所以这个约会游戏有探索和安定两个部分。
但是我们应该探索和等待多久呢?
把这个策略公式化:你从 N 个人中约会 M ,拒绝所有人,然后立刻和下一个比你目前所见的所有人都好的人定下来。我们的任务是找到 M 的最优值。前面说过,M 的最优规则值是 M = 0.37N 。但是我们如何得到这个数字呢?
一个小模拟:
我决定在 R 中运行一个小模拟,看看是否存在 m 的最优值。
设置很简单,代码如下:
我们可以为基本的可视化绘制模拟结果:

因此,似乎在 N = 100 的情况下,图表确实显示了 M 的值,该值将最大化我们使用我们的策略找到最佳伙伴的概率。值是概率 39.4% 的 M = 35,相当接*我前面说的魔值,也就是 M = 37 。
这个模拟实验还表明,我们考虑的 N 的值越大,就越接*幻数。下图显示了随着我们考虑的候选人数量的增加,M/N 的最佳比率。

这里有一些有趣的观察:随着我们考虑的候选人 N 数量的增加,不仅最佳概率降低并趋向收敛,最佳比率 M/N 也是如此。稍后,我们将严格证明这两个最优实体收敛到大约 0.37 的相同值。
你可能会想:“等一下,我不会以很小的 N 值达到找到最佳人选的最高概率吗?”那是部分正确的。基于模拟,在 N = 3 时,我们只要每次选择第三个人,就可以达到高达 66%的成功概率。那么这是不是意味着我们应该总是以和最多三个人约会为目标,然后选择第三个人呢?
你可以。问题是,这种策略只会最大化在这 3 个人中找到最佳者的机会,在某些情况下,这就足够了。但是,我们大多数人可能想考虑比进入我们生活的前三个可行选项更广泛的选项。这本质上与我们年轻时被鼓励去多次约会的原因是一样的:找出我们吸引和被吸引的人的类型,对约会和与伴侣一起生活有一些很好的理解,并在这个过程中更多地了解自己。
你可能会发现更多乐观的事实,随着我们与 N 约会生活范围的扩大,找到完美先生/夫人的最佳概率不会衰减为零。只要我们坚持我们的策略,我们可以证明存在一个阈值,最优概率不会低于这个阈值。我们的下一个任务是证明我们策略的最优性,并找到最小阈值。
能否严谨地证明 37%最优法则?
实际的数学:
设 O_best 为最佳候选人的到达顺序(完美先生/夫人,The One, X,排名为 1 的候选人,以此类推。)我们不知道这个人什么时候会出现在我们的生活中,但我们可以肯定地知道,在下一个预定的 N 个我们将会见到的人中, X 将会出现。
让 S(n,k) 成为在 N 个候选人中成功选择 X 的事件,采用我们的 M = k 策略,即探索并断然拒绝第一个 k-1 候选人,然后与第一个排名比你目前所见的所有人都好的人和解。我们可以看到:

为什么会这样呢?显而易见,如果 X 是进入我们生活的第一批 k-1 人之一,那么无论我们后来选择谁,我们都不可能选择 X (因为我们把 X 包括在我们断然拒绝的人之内)。否则,在第二种情况下,我们注意到,只有当第 k-1 个人中有一个是第 i-1 个人中最好的,我们的策略才能成功。
下面的视觉线条将有助于澄清上述两种情况:

然后,我们可以用全概率定律求成功的边际概率 P(S(n,k))

总之,我们得出成功概率的一般公式如下:

我们可以插入 n = 100 并将这条线覆盖在我们的模拟结果之上进行比较:

Our theoretical results align perfectly well with the simulated experiment. The theoretical result yields a maximum probability of 37.1% at M = 37
我不想用更多的数学来烦你,但是基本上,当 n 变得非常大时,我们可以把对 P(S(n,k)) 的表达式写成黎曼和,并简化如下:

最后一步是找到使这个表达式最大化的 x 的值。下面是一些高中微积分:

我们刚刚严格证明了 37%最佳约会策略。
最后一句话:
那么最后的笑点是什么?你应该用这种策略来寻找你的终身伴侣吗?这是不是意味着你应该在 Tinder 上向左滑动前 37 个有吸引力的个人资料,或者把 37 个滑入你 DMs 的人放在“seen”上?
好吧,由你决定。
该模型提供了最佳解决方案假设你为自己设定了严格的约会规则:你必须设定特定数量的候选人 N,你必须想出一个排名系统,保证没有*局(给人排名的想法并不适合很多人),一旦你拒绝了某人,你就再也不会认为他们是可行的约会选择。
显然,现实生活中的约会要混乱得多。
可悲的是,不是每个人都在那里等着你去接受或拒绝——当你遇到他们时,他们可能真的会拒绝你!在现实生活中,人们有时会回到以前拒绝过的人身边,这是我们的模型所不允许的。很难在日期的基础上比较人们,更不用说拿出一个统计数据来有效地预测一个人会成为多么好的潜在配偶,并据此对他们进行排名。我们还没有解决其中最大的问题:估计可行的约会选择的总数是不可能的。如果我想象自己在 20 年后把大部分时间花在编码和写关于约会的中型文章上,我的社交生活会有多活跃?我会和 10 个人、50 个人或 100 个人约会吗?
是的,孤注一掷的方法可能会给你更高的赔率,团!!!
另一个有趣的副产品是,如果你认为最佳选择永远不会出现,在这种情况下,你试图最大化机会至少以第二好、第三好等结束。这些考虑属于一个被称为“博士后问题”的一般问题,它与我们的约会问题有类似的设置,并假设最好的学生将去哈佛(耶鲁,咄!!!) [1]
你可以在我的 Github 链接找到我文章的所有代码。
[1]罗伯特·范德贝伊(1980 年)。“人口子集的最佳选择”。运筹学的数学。5(4):481–486
[2]希尔,t . p .知道何时停止。美国科学家,第 97 卷,126–133 页(2009 年)
概率论继续:用 Kolmogorov 的联合概率定义注入全概率定律
通过扩展贝叶斯统计揭开概率论的一个方面

在我之前的博客中,我简化了贝叶斯定理。在这篇博客中,我将翻译全概率定律,它指出:
对于一组可数的 x 个事件B₁、B₂、…、Bₓ,且事件 a 仅在事件 b 发生时发生,则事件 a 的概率为 P(A) = ∑P(A∩Bₓ
同样,就像贝叶斯定理一样,乍一看,这似乎非常令人费解和难以理解。但是当把它分解成更小的步骤时,它并不太复杂(实际上相当直观)。当 A 发生的每一个可能条件都发生时,A 发生的概率等于 A 唯一发生的概率之和。或者想象一下:

注意,在上面的图像中,a 只出现在 B₂、B₃、B₄和 B₅,所以 P(A∩B₁)和 P(A∩B₆)都是 0,所以在这个例子中我们有:
p(a)=∑p(a∩bₓ)= 0+p(a∩b₂)+p(a∩b₃)+p(a∩b₄)+p(a∩b₅)+0
当这样想的时候,这个等式可能看起来令人困惑,因为它听起来太简单或者太明显了;听起来应该是微不足道的一点。该定律最有用的扩展可能是当我们应用联合概率的 Kolmogorov 定义时,该定义指出
P(A∩B) = P(A|B)*P(B)
当我们把这个应用到全概率定律时,我们看到
P(A) = ∑P(A∩Bₓ) = ∑ P(A|Bₓ)*P(Bₓ)
理解我们为什么需要这个公式(以及如何使用它)的最好方法是看一个例子(这个例子是我直接从由大会主办的 DSI 项目的实验室作业中获得的):
假设你和你的朋友在玩游戏。你的朋友在你面前放了四枚硬币。如果你抛头,你会从你的朋友那里赢得一美元。如果你抛尾巴,你欠你朋友一美元。然而,你面前的硬币并不公*。
- 一枚硬币有 80%的几率会翻转正面。(称这枚硬币为 a)
 - 一枚硬币有 60%的几率翻转头像。(称这个硬币为 B.)
 - 一枚硬币有 40%的几率翻转头像。(称这个硬币为 C.)
 - 一枚硬币有 10%的几率翻头。(称这个硬币为 D.)
 
假设你随机选择一枚硬币。也就是说,你不知道你选择的是硬币 A、B、C 还是 d。你会翻转头部。给定这些数据,你选择硬币 A、硬币 B、硬币 C 和硬币 D 的概率是多少?

首先,让我们试着把我们刚刚被告知的内容转换成一种可以被读入概率公式的格式:我们被告知,给定硬币 A,有 80%的机会翻转头部,这可以被解释为
P(H|A) = 0.8
我们被告知,给定硬币 B,有 60%的机会翻转头部,这是可以解释的
当 P(H|B) = 0.6 时,
我们被告知,给定硬币 C,有 40%的机会翻转头部,这可以被解释为
P(H|C) = 0.4,
我们被告知,给定硬币 D,有 80%的机会翻转头部,这可以被解释为
P(H|D) = 0.1
因为有 4 个硬币,并且没有理由认为捡起一个硬币的概率与捡起另一个硬币的概率没有任何差异,所以我们可以推断,捡起每个硬币的概率是相等的,也就是四分之一(1/4)的概率。因此:
P(A) = P(B) = P(C) = P(D) = 0.25
为了求解抛头的概率,你可以将所有这些代入全概率定律的公式:
P(H)= P(H | A)* P(A)+P(H | B)* P(B)+P(H | C)* P(C)+P(H | D)* P(D)
= (.8 * .25) + (. 6* .25) + (.4 * .25) + (.1 * .25)
= 0.475
从这里,我们可以使用贝叶斯定理来解决问题的其余部分:
P(A | H)=(P(H | A)* P(A))/P(H)=(. 8 * . 25)/. 475 = 0.42105263
P(B | H)=(P(H | B)* P(B)/P(H)=(. 6 * . 25)/. 475 = 0.31578947
P(C | H)=(P(H | C)* P(C))/P(H)=(. 4 * . 25)/。
因此,如果你抛 A 头,你有 42.1%的机会选择硬币 A,31.6%的机会选择硬币 B,21.1%的机会选择硬币 C,5.3%的机会选择硬币 d。
通过这个例子,你可以看到(一旦应用了 Kolmogorov 对联合概率的定义)全概率定律远不是微不足道的,当一步步解释时并不那么难以理解。看到这三个不同的规则(全概率定律、科尔莫戈罗夫定义和贝叶斯定理)一起使用来寻找更多的关系和相关性也是很好的(至少我认为是这样),你可以开始看到数学领域中创造性思维的潜力。
机器/深度学习的概率论

Probability and Statistics!
简介
为什么我们需要概率论的基础才能理解机器/深度学习算法?
对上述问题的回答是这篇文章背后的主要动机。机器/深度学习经常处理 随机 或随机量,这些量可以被认为是非确定性的(无法预先预测或表现出随机行为的东西)。对这些量的研究与在一系列计算机科学领域中出现的确定性量截然不同。有了这些重要的信息,在不确定的环境中进行推理是很有必要的,概率论就是帮助我们这样做的工具。
因为我不想一开始就用数学术语来混淆你的思想,所以我在文章的最后增加了一节关于所有这些东西的应用。T 这应该是你理解这个东西的主要动机 。那我们开始吧
那么,是什么使得任何系统都容易出现这些不确定性呢?
让我们建立一些数学文献,作为我们进一步讨论的基础。首先,一个确定性系统可以被认为是在未来状态的发展中绝对没有随机性的东西。以牛顿第二运动定律为例。人们可以决定一个加速系统的未来状态。结果不是随机的。
另一方面,非确定性系统是非确定性的(或者在未来状态中包含相当多的随机性)。例如,抛硬币是一个不确定的过程,因为结果中包含随机性(不是正面就是反面,没有办法确定会出现哪种结果)。
回到问题。系统中引入随机行为的方式多种多样。
一个系统可能是固有随机的,就像量子力学模型一样。在这种情况下,我们无法对系统的状态做出确定性的论证。或者可能有一个系统是确定性的,因为我们对这个系统的变量有完全的了解。如果我们失去了一些关于这些变量的知识,我们就失去了决定系统未来发展状态的能力。因此,确定性系统变成了非确定性系统。
先决条件
阅读这篇文章需要对概率的概念有一个基本的理解,对频率主义和贝叶斯概率有一些了解,对条件概率有一些基本的了解,对(不)相关事件有一些了解。如果你想更新这些概念,我推荐你看看这篇由基里尔·杜波维科夫撰写的关于 TDS 的文章
那我们开始吧…
随机变量
如上所述,非确定性系统可能有不止一种可能的结果。例如,抛硬币可能有两种不同的、同样可能的结果——正面或反面。
一个随机变量(或随机变量)可以被认为是一个变量,它的可能值是被模拟的非确定性系统的结果。例如,我们可以定义一个随机变量 X 来表示抛硬币的结果。因此,当结果是正面时,X 取值 1,当结果是反面时,X = 0。所以说随机变量 X 取{0,1}中的一个值。
从形式上来说,如果 S 是具有概率测度的事件结果的样本空间,X 是定义在 S 的元素上的实值函数,那么 X 是随机变量(或者是对实验结果的系统可能状态的描述)。
随机变量可以是离散的(如果它覆盖了有限的或可数无限的个状态)或连续的(如果它覆盖了不可数无限的个状态)。
注 :可数无穷和不可数无穷的概念值得一整篇文章来解释,这里就省略了。然而,你可以在网上查看关于 set 统治的想法。我在这里附上一个非常简短的讨论。
考虑两个集合——X 和 N(自然数的集合)以及映射和双射的通常定义。如果存在从 N 到 X 的子集的映射(而不是到整个 X 的映射),则称集合 X 为严格支配N。换句话说,在 X 中至少存在一个元素在 N 中没有预像。你可以为严格支配集合 X 的集合 N 构造类似的条件。此外,当两者之间存在双射时,称集合 X 与集合 N 的等价。****
当 N 严格支配 X 时,X 是有限的。当 X 等价于 N 时,X 是可数无穷的。当 X 严格支配 N 时,X 是不可数无穷的。
概率分布函数
简而言之,PDF 告诉你一个随机变量取一个特定值的可能性有多大。例如,在我们抛硬币的例子中,X =正面的概率分布是 0.5(或者当事件发生时,硬币出来是正面的概率是 0.5)。正式声明,
P (X = x) = f(x)用 x ~ f(x)表示
或者 PDF 可以被认为是从一个状态的值到它出现的概率的映射。
概率质量函数(PMF)
这是一个离散随机变量的概率分布函数。考虑投掷两个骰子的实验,设 X 是一个随机变量,描述单个骰子的数量之和。然后,

Source: http://www.henry.k12.ga.us/ugh/apstat/chapternotes/7supplement.html
你可以在这里看到 X 的值状态是如何映射到上面定义的表中它们各自的概率的。你可以在这里找到更多关于如何计算这个的信息。
概率密度函数
这是连续变量的概率分布函数。与关联 X 取某一值的概率的概率质量函数相反,密度函数将 X 落在具有测量值 dx 的无穷小区域的概率与 X 相关联(其中测量值=长度(对于单变量分布)、面积(对于双变量分布)、体积(对于三变量分布)等等)。相关的概率可以由 f(x)给出。dx
显然,我们可以应用积分计算 X 落在任意两个极限(比如 a 和 b,使得 a ≤ b)之间的测量中的概率,方法是重复累加由 f(x)给出的无穷小区域的概率。dx

即 X 取值于 a 和 b 之间的概率是 a 和 b 之间无穷小概率的积分。
你可能还想了解二元分布函数(联合概率分布函数(离散和连续))和边际分布函数。
期待值
随机变量的期望值可以认为是根据概率分布 f(x)绘制的变量的*均值。计算过程如下:

Fig 1: Calculating expectation value of a discrete random variable

Fig 2: Calculating expectation value of a continuous random variable
同样,随机变量的方差可以看作是当 X 从概率分布 f(x)中抽取时,随机变量的函数值变化多少的度量。方差是(X —均值)的*方的期望值。

Fig 3: Variance as the expectation value of the square of the difference of the value of X and mean ( calculated by E(X))

Fig 4: Expanding the equation in Fig 3 using the equation in Fig 1
关于期望值的非常详细的理论和实践可以在这里找到。
协方差
协方差是变量之间有多少相互关联的一种感觉。以这个协方差矩阵为例:

在这个矩阵的第一行,150 是 A 的方差,-90 是 A 和 B 的协方差,100 是 A 和 C 的协方差等等。

Fig 5: Calculation of covariance using expectation function
图 5 显示了上表中描述的协方差的计算,其中 f(x,Y)是随机变量 X 和 Y 的联合概率分布。可以求解上述方程,得到 cov(X,Y) = E(XY) — E(X)。e(Y)
从表中可以得出某些推论。负协方差意味着当一个变量的值增加时,另一个变量倾向于取较低的值。反之亦然,对于正协方差(两个变量倾向于同时取高值或低值)。独立变量的协方差为 0(因为它们不相互依赖,所以一个变量的值不会影响另一个变量的值)。然而,0 协方差不一定意味着变量的独立性。
预定义的概率分布
有几个预定义的概率质量和概率密度函数。我在这里解释其中的一些。
二项分布
这是二进制、单个、离散随机变量或离散随机变量 X(只能取 2 个值)的分布函数。举例来说,我有一枚硬币,当扔的时候,正面朝上的概率是𝑝.所以它落在反面的概率是 1−𝑝(抛硬币没有其他可能的结果)。
形式上,伯努利分布由表示成功概率的单个参数来参数化(或者其值等于 p ,如果你考虑上一段中的例子的话):

Bernoulli distribution parameter
现在考虑以下情况:

Fig 6: Probabilities of the outcomes {0, 1} in terms of the Bernoulli parameter
这里,X 取值为 1 的概率(或者在我们的例子中头部被抛出)由参数 phi (取 0 和 1 之间的某个值)给出。同样,另一个事件发生的几率(抛尾)是(1 — phi )。我们可以将这两种概率组合成一个由下式给出的概括陈述:

Fig 7: You can try to place values of x = 1 and x = 0 to see how this generalised statement returns the individual probabilities
利用上面讨论的期望值和方差的概念,可以得到该分布的均值和方差,如下所示:

Fig 8: Mean and variance of Bernoulli distribution in terms of Bernoulli parameter
二项分布
二项式分布可以认为是 n 个独立和同分布的伯努利随机变量之和,其中每个伯努利随机变量取两个值{0,1}中的一个。
n 个独立同分布伯努利变量之和的非正式含义是,我们将同一个实验重复 n 次,每个实验的结果独立于其他实验的结果。我们还定义了一个参数 p (与伯努利分布中的参数φ相同),该参数表示在 n 个实验实例中的该实验实例中随机变量取值 1 的概率。二项式分布是这样的:

Fig 9: Binomial Distribution. n and p are parameters controlling the distribution for k
例如,投掷 5 次公*且*衡的硬币。现在定义一个随机变量 X,它表示获得的头数。因此,x 可以取{0,1,2,3,4,5}中的任何值。这里 n = 5(实验重复的次数)。从形式上来说,如果我们将伯努利变量 X[i]定义为第 i 次抛硬币的结果,我们需要将 X[1],X[2],…,X[5]相加,以获得我们想要的 X 值。还要注意 X[1],X[2],…,X[5]是成对独立的,或者一次抛硬币不依赖于另一次抛硬币。
浓缩上一段的信息,我们可以直接计算 Pr(k = 2;n = 5,p = 0.5),将这些变量置于图 9 所示的分布中。假设我们投掷 5 次*衡的(*均值 p = 0.5)硬币,这将输出找到 2 个头的概率。
高斯分布(正态分布)
这是连续随机变量最基本的分布函数。这由分布的均值和方差(用标准符号表示)参数化,如下所示:

Fig 10: The Gaussian distribution function
该函数如下图所示:

Fig 11: The Gaussian Distribution Function
在我们对随机变量的分布一无所知的情况下,高斯分布是明智的选择。因此,假设值将遵循正态分布,*均值上下的测量次数相等,*均值为分布的峰值。例如,我们的任务是模拟一个连续的随机变量,而我们对它的分布一无所知。在这种情况下,明智的做法是对变量的分布做出最少的假设,并选择高斯分布函数(在所有具有有限方差的分布中,高斯分布函数在 X 的分布上引入了最大不确定性)。
把上面的一段话浓缩成一个陈述,你的连续随机变量 X 很有可能遵循一个带有一些噪声的高斯分布(由中心极限定理提出)。那么,为什么不事先做出这样的假设呢?
如果我们希望对多元分布进行建模,我们可以将高斯分布表示为:

Fig 12: Gaussian distribution in case of multivariate scenarios
这里,均值现在是一个向量,而不是方差,我们使用一个协方差矩阵,用大写 sigma 表示(已经在上面的部分讨论过)。
在下面讨论的高斯混合模型中,查找有关多变量设置中的高斯分布的更多信息。
指数和拉普拉斯分布
在深度学习中,我们需要调整神经网络的参数,以防止过度拟合。从贝叶斯的角度来看,拟合正则化模型可以被解释为计算最大后验概率估计值。这里不再赘述更多细节(你显然可以在这里读到更多关于那个的内容),我们需要在 x = 0 或 X = X 分布的均值处有一个非常尖锐的点,以帮助正则化。因此,我们使用以下内容:

Fig 13: Exponential distribution introducing a spike at x = 0
在哪里,

Fig 14: The indicator function in Fig 13
指示函数用于将 0 概率分配给 x 的所有负值。您可以查看图表:

Fig 15: The exponential distribution function graph
指数分布描述了 泊松点 过程中事件之间的时间,即事件以恒定的*均速率连续独立发生的过程。
类似地,如果我们希望在 X 分布的*均值处模拟尖峰,我们可以使用拉普拉斯分布函数,

Fig 16: The Laplacian Distribution

Fig 17: The Laplacian Distribution graph. Here b in the figure is the same as gamma in the equation in fig 16
这个拉普拉斯分布可以被视为两个背靠背拼接在一起的指数分布,从而我们在分布的*均值处获得一个尖峰(注意我们如何在上图中获得绿色曲线的偏移,这可以通过拉普拉斯分布中的参数*均值来管理)。
狄拉克δ分布
Dirac Delta 函数用于聚集单个点周围的所有分布,并中和连续随机变量 x 的所有其他值上的分布。

Fig 18: The Dirac Delta function
上述等式倾向于收集*均值周围的所有质量。更具体的例子是下面的函数:

Figure 19: Dirac Delta function to concentrate mass about the origin
这里, a 是一个参数,其值用于定义峰值与原点的接*程度(或原点周围的质量浓度)。随着 a 接* 0,峰值变得无限窄和无限高。
您可以用*均值参数化图 19 中的等式。然后,该函数将类似于图 18 中的等式,并将在所需点处产生一个峰值(0°以外)。






Fig 20: Growth of the Dirac Delta functions as value of the parameter changes
狄拉克δ函数在下一个分布中发现了它们的重要性:
经验分布
经验分布是连续随机变量的多元分布。
经验分布用于将(1/m)质量(而不是狄拉克δ分布中的全部质量)集中在样本空间中的 m 个点上,利用狄拉克δ分布在这些点上的能力。请考虑以下情况:

Fig 21: Empirical Distribution
很明显,这个分布以 x(1),x(2),…,x(m)上的(1/m)质量为中心。在下一节中可以找到更多的解释…
分配混合物
如果你已经走了这么远,恭喜你!我们现在开始理解上述分布的集合。您可以组合这些发行版来创建更复杂的发行版。我们举一个你已经见过的分布混合的例子——经验分布。
经验分布如图 21 所示。它是我们所瞄准的 m 个点上描述的狄拉克δ函数的混合。考虑以下等式:

Fig 22: Distribution Mixture equation
让我解释一下。这里, c 代表定义的不同分量分布。在我们的例子中,我们有 m 个点,每个点上有一个狄拉克δ函数。因此,您可以将经验分布视为一个混合的 m 狄拉克δ分布,其中每个分布都由 x(i)点参数化,它需要将质量集中在 x(I)点上。
图 22 中的等式。意味着最终分布 P(x) 是单个分布分量 c、上的多努利分布,通过找到从我们拥有的 m 狄拉克德尔塔分布中选择第 i 狄拉克德尔塔分布的先验概率 ( 或观察 x 之前的概率),然后从第 i 狄拉克德尔塔分布中采样 x 来计算。
简单地说,你有 m 个狄拉克δ分布,你选择其中一个,然后在其上集中(1/m)质量。然后你选择另一个狄拉克δ分布,并在其上集中(1/m)质量。继续这样做,直到所有狄拉克德尔塔函数用尽。最后,将它们相加得到你的经验分布。
我们来讨论一个最终分布混合,高斯混合模型。你可以再一次把这个混合物想象成有 m 个独立的成分,其中每个成分是一个高斯分布,有独立的参数:均值向量和协方差矩阵。现在请看下图:

Fig 23: A Gaussian Mixture model
这是一个高斯混合分布。你可以清楚地观察到三个不同的集群。每一个都是高斯分布。请注意这些参数化的不同(我将从协方差矩阵的角度进行解释,如果您需要复习这个参数,请参考图 12)。
- 左下分布有一个各向同性协方差矩阵。因此,它在所有方向上都有相同的方差
 - 中间分布有一个对角协方差矩阵。这意味着只有对角线元素是非零的,或者两个变量的协方差都是 0,意味着它们是独立的。
 - 右上分布有一个满秩协方差矩阵。
 
我希望这有助于理解如何将具有不同参数的相同分布组合成一个混合模型。
最后!!!
所有这些的应用
指数分布有助于调整神经网络的参数,以防止过度拟合。这是一项非常需要完成的任务,因为过度拟合会导致性能不佳,需要不惜一切代价予以消除。
前几天,我试图在 Kaggle 上解决桑坦德银行客户交易预测,在探索数据时,我试图查看所有 200 个变量(匿名)的分布,以查看是否有可以立即看到的明显关系。变量的分布可以给出关于您试图处理的数据的性质的重要信息。我附上了我获得的一部分图表:

Can you find anything ???
或许,你可以。我的一个初步想法是,顶行中的前三个图表示相同变量在不同组中的不同分布(用 1 和 0 表示)。另一方面,顶行的第四个图表看起来是完美的重叠。因此,第四个变量可能不会影响由 1 和 0 表示的组的分布,而第一、第二和第三个变量可能会影响。
以上推断是初步的。但它可能会给进一步的探索指明方向。
还有很多其他的例子,比如不同算法背后的数学原理,如果你有一些相关的背景知识,现在可以更好地理解。
最后,也是更重要的,你将能够开始以更好的方式理解机器/深度学习文献,因为大多数事情都有这些概念的基础。
另外,你可能想看看这些帖子:
学习系列!!!
medium.com](https://medium.com/ml-research-lab/how-to-self-learn-statistics-of-data-science-c05db1f7cfc3) [## 大多数 ML 模型都假设了一个底层的数据分布,以便它们能够很好地运行。在哪里可以学到…
回答(第 1 题,共 8 题):问题是: >>大多数 ML 模型都假设了一个底层数据分布,以便它们能够很好地运行…
我希望你在这篇文章中学到了一些新东西。请在下面的评论中告诉我你对这篇文章的看法。
祝你今天开心!玩的开心!
概率与统计
基本问题 4 毫升
概率与统计的区别以及统计方法的分析。
我们经常看到“概率”和“统计”这两个词放在一起,但是它们指的是同一个东西吗?这是 Essential probNstats 4 ML 项目的后续文章,在这篇文章中,我将解释这两个术语之间的区别,为什么它们被链接在一起,以及现有的统计方法。
概率与统计
概率论是与概率有关的数学分支。概率是一个事件发生可能性的数字描述。很多时候说概率,我们指的是概率论而不仅仅是数字。从句子的上下文来看,这是可以理解的。
统计学是数学的一个分支,涉及数据的收集、组织、显示、分析、解释和呈现。
这两者的关系是,在统计学中,我们应用概率(概率论)从数据中得出结论。
为了使定义更清楚,这里举两个例子:
概率示例:
你有一枚公*的硬币(正面或反面的概率相等)。你会扔 100 次。60 头以上的概率有多大?由于标准的计算策略,我们只能得到一个答案。
统计示例:
你有一枚来历不明的硬币。为了调查它是否公*,你把它扔 100 次,然后数人头的数量。假设你数了 60 个头。作为统计学家,你的工作就是从这些数据中得出结论(推论)。在这种情况下,不同的统计学家可能得出不同的结论,因为他们可能使用不同的结论形式或可能使用不同的方法来预测概率(例如着陆头)。
概率的基本术语
在我们继续之前,让我们定义一些必要的概率基本术语:
实验(或试验)是可以无限重复的任何程序,并且具有一组明确定义的可能结果。
样本空间是实验中所有可能结果的集合。
一个事件是一组实验结果。
事件可以是:
- 独立,表示不受其他事件影响。例如,如果你掷一枚公*的硬币,无论如何,它落在正面的机会是 1/2。
 - 也就是说,他们受到其他事件的影响。例如,随着我们从一副牌中取出牌,我们选择国王的概率变得越来越高。
 - 互斥也就是说它们不能同时发生。你不能同时向左转和向右转。
 
但是不同的统计学家如何根据概率得出不同的结果呢?
有两种统计解释用于解决一个问题:和 贝叶斯 。
频率主义者认为概率是实验中各种结果出现频率的量度。例如,如果我们有一个公*的硬币(50%的概率正面落地),我们预计一半的实验将正面落地。
贝叶斯主义者认为概率是一个抽象的概念,用来衡量一个给定命题的知识状态或信任程度。这意味着概率有一个可能为真的值的范围,而不是单一的一个。这种方法将被我们作为数据科学家或 ML 工程师采用,用于语音或人脸识别等系统。
集合的基本定义
在我们继续之前,我们需要对集合有一些基本的了解:
集合是元素的集合。
一个空集被表示为 ∅ ,它不包含任何元素。
集合(S)的子集 (A)是存在于该集合中的一组元素。它被描绘成 A⊂S.
s 中 a 的补码是 s 中不是 a 中的元素的集合,用 Aᶜ或 s A 表示
A 和 B 的并集是 A 或 B(或两者)中所有元素的集合。它表示为 A ∪ B。
A 和 B 的交集是 A 和 B 中所有元素的集合,表示为 A ∩ B。
如果两个或多个子集没有公共元素并且它们的交集等于 ∅ ,则它们是不相交的。
两个或更多子集(如 A 和 B)的差是 A 中不在 B 中的元素的集合。我们将其记为 A-B。
最后,有两个重要的法则结合了交集、并集和补集。它们被称为德摩根定律,如下所示:
- (一∪b)ᶜ=aᶜ∪bᶜ
 - (一∩ B)ᶜ= Aᶜ ∪ Bᶜ
 
概率计算示例
在我们跳入问题之前,我们需要学习一些重要的概率概念:
- 积法则:如果有 a 做某事的方式和 b 做另一件事的方式,那么就有a*b 两种动作的执行方式。例如,如果在一项奥林匹克运动中有 7 名参赛者,则有 765 = 210 种方法来授予奖牌(7 人授予金牌,6 人授予银牌,5 人授予铜牌)。*
 - 排列是***集合中元素放置的顺序。例如,集合{a,b,c}有六种排列:abc,acb,bac,bca,cab,cba。该集合的排列数也可以通过乘积法则找到:321 = 6 个排列。通常,集合的排列数是其长度的阶乘(在我们的例子中是 3!).*****
 - ****一个集合的组合是从该集合中选择项目,使得不同顺序的元素没有重复。所以上一个集合中所有可能的 2 个元素组合是:{a,b},{b,c},{c,a}
 
我们也可以计算一个集合中 k 个元素的排列和组合。在任一情况下,计算这两者的通用公式为:
**********
ₙPₖ =一组大小为 n 的元素中 k 个不同元素的排列(列表)数
ₙCₖ =大小为 n 的集合中 k 个元素的组合(子集)数量
最后,在那个阶段,我们准备着手解决问题!
假设我们有一枚公*的硬币,在 10 次投掷中正好有 3 个正面着地的概率是多少?
首先,我们必须计算在 10 次翻转中得到 3 个头的方法。这可以通过“组合”公式来实现:

10 次翻转中的每一次都有 2 种可能的结果,所以根据乘积法则,我们有 222…=2 个 10 次翻转的⁰=1024 序列。现在我们可以用组合数除以序列总数来计算 10 次翻转中落地 3 头的概率:120/1024 ≈ 0.117 。
结论
我们了解了概率和统计的区别。我们还了解到,统计学家可能会根据结论的形式或概率计算方法得出不同的结果。最后,我们学习了如何计算一个具有同等可能性结果的问题的概率。
参考
杰里米·奥洛夫和乔纳森·布鲁姆。 18.05 概率统计导论。2014 年春天。麻省理工学院:麻省理工学院开放课件,https://ocw.mit.edu。许可:知识共享协议 BY-NC-SA 。
皮尔斯罗德。(2017 年 10 月 6 日)。“概率:事件的类型”。数学很有趣。2019 年 12 月 14 日检索自http://www . maths isfun . com/data/probability-events-types . html
维基百科贡献者。(2019 年 11 月 2 日)。实验(概率论)。在维基百科,免费百科。检索到 2019 年 12 月 14 日 20:24,来自 https://en.wikipedia.org/w/index.php?title=Experiment_(概率论)& oldid=924254710
维基百科贡献者。(2019 年 12 月 13 日)。概率论。在维基百科,免费百科。检索到 2019 年 12 月 15 日 10:59,来自https://en.wikipedia.org/w/index.php?title =概率论& oldid=930545712
史蒂文·斯基娜。(2001 年 4 月 6 日)。概率与统计。2019 年 12 月 15 日检索自https://www3 . cs . stony brook . edu/~ skiena/jaialai/excepts/node 12 . html
维基百科贡献者。(2019 年 12 月 4 日)。统计学。在维基百科,免费百科。检索于 2019 年 12 月 15 日 11:04,来自https://en.wikipedia.org/w/index.php?title=Statistics&oldid = 929190255
维基百科贡献者。(2019 年 10 月 5 日)。乘积法则。在维基百科,免费百科。检索 2019 年 12 月 15 日 18:20,来自https://en.wikipedia.org/w/index.php?title=Rule_of_product&oldid = 919664907
工具面前的问题:全栈数据科学通才的另一种视角
现实世界中的数据科学
我们是否已经不再关注数据科学到底是什么?

我最*读了一篇来自 Stitch Fix 首席算法官 Eric Colson 的文章,他谈到我们应该如何避免建立像制造工厂一样的数据科学团队,由高度专业化的个人组成,操作制造流程的不同部分。相反,数据科学团队应该采用全栈方法来构建,在这种方法中,数据科学家被视为多面手。多面手指的是执行从概念到建模到实施到测量的各种功能的能力。我不会在这里对这篇文章进行详细的总结,但是你应该在继续之前阅读 Eric 的文章。
这篇文章的目的是为埃里克的哲学提供一个补充的观点。在他的文章中,他采用了非常自上而下的方法来描述为什么数据科学团队应该由多面手组成。我相信,从数据科学从业者的角度以及数据科学的真正含义来看,通过自下而上的方法也可以得出相同的结论。
让我们从定义数据科学开始讨论。数据科学到底是什么,或者说数据科学家是做什么的?向我们友好的邻居 Interweb 先生寻求帮助,这里是我找到的一些定义。
先生,请告诉我,您所指的数据科学是什么?
“数据科学是一个多学科领域,它使用科学的方法、流程、算法和系统,从各种形式的结构化和非结构化数据中提取知识和见解,类似于数据挖掘。” — 维基百科
“数据科学是“统一统计学、数据分析、机器学习及其相关方法的概念”,以便用数据“理解和分析实际现象”。它采用了从数学、统计学、信息科学和计算机科学等许多领域汲取的技术和理论——维基百科
数据科学是一个跨学科领域,使用科学方法、流程、算法和系统从数据中提取价值。数据科学家结合一系列技能(包括统计学、计算机科学和商业知识)来分析从网络、智能手机、客户、传感器和其他来源收集的数据。——神谕
“数据科学是一个结合领域专业知识、编程技能以及数学和统计知识的研究领域,旨在从数据中提取有意义的见解。数据科学从业者将机器学习算法应用于数字、文本、图像、视频、音频等,以产生人工智能(AI)系统,该系统执行通常需要人类智能的任务。反过来,这些系统会生成分析人员和业务用户转化为切实商业价值的见解。” — 数据机器人
这些是一些精心制作的定义(比我能够表达的更好),但这些定义(以及互联网上的许多其他定义)的一个可观察到的一致模式是,数据科学往往是通过执行一组特定任务或使用一组特定工具来定义的。如果你做 X,Y,Z 并使用 A,B,C,那么这被认为是数据科学。因果链应该是这样的:

数据科学——21 世纪最不性感的领域

实践数据科学将引导您使用数学和统计学,应用机器学习算法,学习编程,增加领域专业知识。为什么?首先,我认为通过包装和营销数据科学成为这个性感领域的过程,我们错误地定义了数据科学。我不认为上面提到的定义是不正确的,但我认为这样的定义更可信:
“数据科学,就其最基本的术语而言,可以定义为从数据中获得洞察力和信息,实际上是任何有价值的东西。像任何新领域一样,试图给其定义设定具体界限往往很有诱惑力,但却适得其反。 — 深思熟虑
要让定义更不性感,我相信数据科学应该简单一点:“只是用数据解决问题”。数据科学家应该是“数据女孩或数据男孩”。不再性感了。
虽然我们在两个因果链中仍然有所有相同的元素,但因果关系逆转的微妙差异实际上导致了数据科学在现实中的实践方式的巨大差异。这和把一杯水看成半满还是半空是一个概念。尽管这两种观点都是正确的,但是认为事物半满的人和认为事物半空的人在行为方式上有很大的不同。
在第一个因果链中,我们看到许多数据科学从业者只对数据科学的特定任务感兴趣。你遇到过明确表示他们只对构建模型感兴趣,而不关心分析或与利益相关者合作的人吗?你很有可能。在通过第二个因果链的世界中,特定的数据科学任务被执行,因为它有助于解决手头的问题。
这与成为多面手有什么关系?
那么,经过这么多弯路,这些东西和成为多面手有什么关系呢?我相信,如果我们以正确的方式看待数据科学,真正优化数据科学的唯一方法是成为一名多面手(再次,欢迎在下面的评论中听到您的想法和意见)。为什么?如果我们总是以问题为主要焦点,我们会意识到,如果我们想以尽可能最好的方式解决问题,我们不能只做数据科学的一部分,而不做另一部分。回应 Eric 在他的文章中的观点,多面手角色提供了驱动工作满意度的所有东西:自主性、掌控力和目标。特别是在掌握方面,如果我们总是从问题开始,我们可以确定我们当前的工具包是否能够充分回答问题,或者我们需要更深入地分支并应用新的数据科学技巧或技术来帮助解决问题。
原载于 2019 年 3 月 29 日artofmarketingscience . github . io。
机器学习模型中的问题?先检查你的数据
在将清洗数据输入机器学习算法之前对其进行简要分析

Photo by Eleonora Patricola on Unsplash
许多人经常说数据预处理是机器学习算法中最重要的部分。人们常说,如果不清理数据并对其进行预处理,机器学习算法将会爆发。但是你有没有想过什么是不干净的数据,你如何区分干净的数据和不干净的数据,以及干净的数据有哪些不同的方面,然后我们可以在其上建立我们的模型?

Photo by Joshua Sortino on Unsplash
好吧,这里是对机器学习中存在的主要挑战的一个小介绍。正如奥雷连·杰龙(Aurelien Geron)在他的书动手机器学习中所说,数据中可能存在两种类型的问题,正如他所说的,“糟糕的算法”和“糟糕的数据”。
数据不足
用来建立机器学习模型的数据仓库应该包含大量的数据,这通常是明智的。虽然这通常是正确的,但是一个简单的机器学习模型可以建立在少到只有几百条记录的基础上。然而,更复杂的系统确实需要大型数据集和模型,例如图像识别甚至可能需要数百万条记录。
数据不足的真正问题在于,数据越少,方差越大。方差,可以很容易地定义为给定数据点或告诉我们数据如何分布的值的模型预测的可变性。模型中的高可变性意味着模型将完美地适合训练数据,但是一旦新数据被输入其中,模型将停止工作。

Photo by Suhyeon Choi on Unsplash
非代表性训练数据
为了很好地概括模型,训练数据准确地表示总体是至关重要的。换句话说,每次从总体中得出一个新样本时,样本必须准确地描绘总体的情况是至关重要的。训练数据集必须能够代表您想要归纳的案例。然而,这比听起来要难。如果样本太小,将会有采样噪声,这是由于偶然产生的不具有代表性的数据,但是如果采样方法有缺陷,即使是大样本也可能不具有代表性。这被称为采样偏差。
这里需要注意的是,如果必须减少采样偏差,方差就会上升,而如果方差要减少,偏差就会上升。这种现象也被称为 偏差-方差权衡 ,是找到一个最佳*衡点的过程,该*衡点使数据集中的方差和偏差都保持较低。
在处理偏见时,还有两个同样重要的概念,它们是:
- 样本可能倾向于选择部分人群,因此可能无法准确代表真实人群。这也就是俗称的数据中存在偏斜,数据可以是右偏的,也可以是左偏的。
 - 第二,也可能有这样的情况(特别是在调查中),有足够多的人可能没有回答问题,并且没有在数据中得到体现。这也称为数据中存在 无响应偏差 。
 

Presence of outliers in data
质量差的数据
很明显,如果输入的数据已经是脏的,那么模型将不能很好地运行。脏数据是倾向于存在错误、异常值和噪声的数据。如果数据中有缺失的观察值,数据也可能是脏的。
- 为了处理异常值,如果我们可以丢弃这些观察值,这将减少数据集的大小,或者我们可以 winsorize 它们,这可能会更好。Winsorized 观察值是那些最初是异常值的观察值,但是附加的条件已经传递给它们,以便将它们限制在特定的边界内。
 - 数据集中的空白可以是缺失值,也可以是不存在的值。不存在的值通常在调查中更普遍,在调查中,一些特定的问题没有得到回答,我们没有它们的任何数据,而缺失的值更普遍地存在于数据中存在的值,但没有记录下来,因此可以不使用特殊的 标准化 方法进行处理。
 

Photo by Sofia Kuniakina on Unsplash
无关紧要的特征
我在俄克拉荷马州立大学的项目主任 Goutam Chakraborty 博士总是说,机器学习在很大程度上取决于 GIGO(垃圾进,垃圾出)。这意味着,如果你把含有大量特征、大量噪声的坏数据放入模型,它最终会把垃圾还给你。ML 算法的一个重要方面是 特征工程 方面。这包括:
- ****特征选择:在现有特征中选择最有用的特征进行训练。这可以通过使用套索回归等方法来实现。
 - ****特征提取:结合现有特征,创建一个新的、更有用的特征,在模型中具有更高的重要性。
 - 通过收集新数据创建新特征
 

Various types of fits that can be present in the model
过度拟合数据
正如上面的图像试图解释的那样,过度拟合数据是指模型已经尝试完全拟合训练数据。这通常是通过强制安装来实现的,而且通常好得令人难以置信。它也被称为傻瓜的黄金。这是因为每当这样的模型看到新数据时,该模型将给出令人难以置信的差性能。这种问题的可能解决方案是:
- 正则化**:通过减少训练数据中的属性数量或约束模型,选择一个参数较少的模型,从而简化模型的过程。学习期间应用的正则化量可由超参数控制。
 - 收集更多训练数据
 - 减少训练数据中的噪声
 
数据拟合不足
欠拟合与过拟合相反:当模型过于简单而无法了解数据的底层结构时,就会发生欠拟合。这通常会导致无法解释的高度差异,因为模型无法解释这种差异。这个问题的解决方案可以是:
- 选择具有更多参数的更好(更强大)的模型
 - 向学习算法提供更好的特征(特征工程)
 - 减少对模型的约束(减少应用的正则化或减少超参数)
 
因此,上述问题可能存在于数据中,这可能使数据存在问题,并且为了机器学习模型有效地工作,这些问题应该被消除。要了解如何解决这些问题,应该使用并遵循此处的教程:
如何在几分钟内为机器学习模型成功准备数据
towardsdatascience.com](/the-complete-beginners-guide-to-data-cleaning-and-preprocessing-2070b7d4c6d)**
用 R 进行过程能力分析
r 代表工业工程师
探索“六西格玛”R 包

Image by Lenny Kuhne available at Unsplash
过程能力分析
过程能力分析是六适马项目中 DMAIC(定义、测量、分析、改进、控制)周期的测量阶段的重要组成部分。这种分析衡量过程性能如何符合客户的要求,并转化为要制造或生产的产品的有趣特性的规格限制。这种分析的结果可以帮助工业工程师识别过程中的变化,并制定进一步的行动计划,以提高产量、降低变化和减少缺陷数量。
规格
规格是客户的心声。每一个过程都应该能够满足顾客的要求,这些要求必须量化才能达到。规格极限是客户要求的数字表达。由于过程中的自然变化,规格通常是一个有上限和下限的范围。(规格上限)是工艺性能不可接受的值,而 LSL (规格下限)是工艺性能不可接受的值。
规格必须切合实际。为了评估它们的有效性,使用了来自六个适马场的伦巴方法,其中 R 代表合理, U 代表可理解, M 代表可测量, B 代表可信, A 代表可实现。
过程性能
流程绩效是流程的声音。当一个过程接*目标,且变化尽可能小时,该过程可以被认为是正确的。在六适马方法中,最常见的过程绩效测量是:
- 产量( Y ):流程生产出的好产品或物品的数量。流程完成后,可以对其进行评估,计算符合规格的项目:
 

- 一次成品率( FTY ):考虑了工序中间的返工。因此,不管流程结束时有多少正确的项目,都会将正确的项目计为“第一次”正确的项目:
 

- 滚动产量( RTY ):当一个过程由几个相互联系的过程组成时使用。它是通过乘以每个链接进程的 FTY 计算出来的:
 

- 每机会缺陷( DPU ):每单位不符合项数量。缺陷是产量的补充:
 

- 每百万次机会中的缺陷( DPMO ):每百万次机会中的不符合项数量。它主要用作流程的长期性能测量:
 

来自 SixSigma R 软件包的 ss.ca.yield 函数计算所有之前的过程性能测量。对于下面的例子,让我们考虑一个过程由三个过程链接。我们来看看 R 代码!
流程与规格
流程(Z)的西格玛得分是一个简单的数字,它表达了流程如何符合客户的规格。达到 6 的 sigma 水*的工艺可以被认为是“几乎完美”(即几乎没有缺陷)的设计工艺。6 的 sigma 值意味着将获得少于 3.4 的 DPMO(每百万个机会中的缺陷)。 sigma 是符合规格极限和过程*均值之间的标准偏差数。它是使用以下公式计算的:
**
DPMO through sigma scores
能力指数
能力指数直接比较客户规格和过程的性能。它们基于以下事实:过程的自然极限或有效极限介于*均值和+/- 3 标准偏差之间(即包含 99.7%的数据)。流程的能力(C p )通过以下公式计算:

然而,该公式不允许验证过程是否在*均值的中心(这是期望的)。为了解决这个问题,调整后的能力指数(C pk )通过以下公式计算:

像 sigma 分数一样,能力指数有助于确定过程满足客户规范的程度。一般来说,1.33 的 C pk 是可以接受的,但是它的值越大越好。
six sigmaRR包包含几个函数,用于获取对工业工程师和过程工程师有用的过程能力度量。我们来看看 R 代码!**

Six Sigma Capability Analysis Study
从上面的六适马能力分析研究来看,上面的图表代表了样本数据的直方图,包括目标和规范。绘制了经验和理论密度函数的密度线。底部的图表表示分位数-分位数图(Q-Q 图),用于验证数据点是否呈正态分布。以同样的方式,两个常见的统计测试包括验证正态性假设:夏皮罗-维尔克测试和 Lilliefors (K-S)测试。在图的右边,包括了分析的事实:规格极限是在函数中输入的那些;计算过程性能和指数,并计算能力指数的置信区间(CI)。
总结想法
过程能力分析为工业和过程工程师提供了一个很好的工具,用于识别过程中的变化,以提高其产量和效率。six sigma R 包只需要几行代码就可以获得关于过程能力的重要信息。非常鼓励工业、过程和质量工程师利用这一工具,以高质量和高效率的标准满足客户的要求。
— —
如果你觉得这篇文章有用,欢迎在 GitHub 上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 个人资料 来浏览我以前的文章。感谢阅读。
——罗伯特
用 R 绘制流程图
r 代表工业工程师
使用 R 包创建流程图

Image by Matteson Ellis available at FCPAmericas
说得好的问题是解决了一半的问题。
——查尔斯·富兰克林·凯特林
流程图是在 DMAIC(定义、测量、分析、改进、控制)周期的定义阶段检索流程信息的一个很好的工具。作为项目章程,流程图是其构建的来源,流程图包括描述流程所需的步骤,并确定其输入、输出、参数和特征;它描述了流程的当前状况,是确定根本原因的基础。流程图令人大开眼界,它们有助于识别流程的利益相关方(例如所有者、客户、供应商)、瓶颈、浪费和改善事件和精益改进的机会领域。
然而,构建流程图并不是一件容易的事情;收集关于进程的信息不是小事。顶级流程图的分解(即,将流程分解为简单的步骤)和信息检索流程可能包括许多必须克服的障碍。激励员工获取关于流程的更精确的信息是流程工程师必须克服的最重要的挑战之一,这可以通过选择最佳策略使他们参与项目并使他们相信其成功实施可以给整个组织带来的潜在好处来实现。
一旦过程被分解成更小的步骤,过程工程师必须独立地关注每一个步骤。必须充分识别和测量参数(对过程输出的产品特性有影响的所有因素或变量)和特性(定义质量的特性),以便对它们进行绘图和分析,从而设计实验、测试假设,并获得未来改进的重要结果。
来自 R 的 SixSigma 和 grid 包包含几个用于开发逐步流程图的函数。对于下面的例子,我们将考虑 Cano,Moguerza 和 Redchuk (2012)的教科书 Six 适马与 R 中的披萨餐厅案例,其中一家餐厅的经理对研究制作和提供披萨的过程感兴趣。我们来看看 R 代码!
- 
步骤 1: 加载网格和 SixSigma R 包
 - 
步骤 2: 声明过程输入和输出
 - 
第三步:申报项目的步骤
 - 
第四步:声明每一步的输出
 - 
第五步:对每一步的参数进行声明和分类
 
— — — — — — — — — — — — — — — — — — — — — — — — —
参数组:
- 噪声:不可控制的因素
 - C =可控因素:可能在过程中发生变化
 - P =程序:通过标准程序的可控因素
 - Cr =关键:对流程影响较大的因素
 
— — — — — — — — — — — — — — — — — — — — — — — — —
- 
第六步:声明每一步的特点
 - 
步骤 7: 用 SixSigma 包绘制流程图
 - 
最终结果:
 

Six Sigma Process Map Final Outcome
总结想法
six sigma R 包包含了很棒的特性,只需要几行代码就可以开发出顶级的流程图。用 R 开发它们的主要优势是它们的可再现性(即每次生成它们时,它们都有相同的方面),这代表了在项目中使用可再现研究技术时的一个有用特性。通过将代码存储在您自己的库中,您将只需修改输入,流程图将再次自动呈现,这将节省您的时间,因为您不必打开新的绘图图、修改它、检查方面并从其他所谓的用户友好程序中导出图像。虽然这个用于开发流程图的 SixSigma 特性并不打算取代其他程序,但它提供了一种以更快和可重复的方式开发它们的新方法。
— —
如果你觉得这篇文章有用,欢迎在GitHub上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 简介 来探索我以前的文章。感谢阅读。
——罗伯特
使用 Apache Spark 处理维基百科,创建热点数据集
从维基百科:名人数据集创建一个你选择的数据集

Wikipedia, The Free Encyclopedia
我们大多数人肯定都遇到过这样的情况,每当我们想了解某个国家的历史、纪念碑、电视剧和电影、名人的生活和职业生涯、过去的事件或当前的事件时,我们的首选是维基百科。聪明的人用它来获取各种各样的知识,听起来甚至更聪明。但是,你有没有想过它有多大?它有多少文件/文章?
维基百科目前有大约 598 万篇文章,并且每天都在增加。有各种各样来自各个领域的文章。我们可以使用这些数据来创建许多有趣的应用程序。如果您可以访问这些数据,您的下一个有趣的应用是什么?你如何得到整个数据集?即使你得到了它,处理它需要多少计算量?
所有这些问题都将得到解答。
在本文中,我想创建一个名人数据集。过去或现在所有在维基百科上有页面的受欢迎的人,像维拉特·科利、萨钦·坦杜尔卡尔、板球界的瑞奇·庞廷、布拉德·皮特、莱昂纳多·迪卡普里奥、电影界的阿米特巴·巴强、物理学家阿尔伯特·爱因斯坦、伊萨克·牛顿等等。我将使用 Apache Spark (PySpark)来处理这个庞大的数据集。
1.获取维基百科转储
为了开始这项任务,首先,我们需要 Wikipedia 转储。维基百科转储可以从这里以 XML 格式下载。它不断刷新,包含最新的维基百科数据。
解析维基百科 XML 的脚本
接下来,可以使用免费提供的 Python 包非常容易地解析这个下载的 XML。关于如何使用该软件包的更多细节可以在这里找到。
一旦解析完成,这就是解析后的目录结构的外观。

Parsed Directory Structure
每个目录由多个纯文本文件组成。文件内容的快照

Snapshot of File Content
每个文件包含多个维基百科文章。每篇文章都以
2.通过 Apache Spark (PySpark)处理维基百科解析数据
阿帕奇火花
Apache Spark 是一种快如闪电的集群计算技术,专为快速计算而设计。它基于 Hadoop MapReduce 并扩展了 MapReduce 模型,以有效地将其用于更多类型的计算,包括交互式查询和流处理。Spark 的主要特点是它的内存集群计算提高了应用程序的处理速度。
一些 Apache Spark 术语和转换函数(可选)
此部分是可选的。这一节是为 Spark 初学者或那些想在继续之前快速掌握一些 Spark 变换函数的人准备的。要了解关于这些功能的更多信息,请浏览此链接。
- RDD : RDD(弹性分布式数据集)是 Apache Spark 的基本数据结构,它是在集群的不同节点上计算的不可变对象集合。RDD 是分布在集群中许多机器上的数据元素的分布式集合。
 - 数据帧:数据帧是组织成指定列的数据的分布式集合。它在概念上相当于关系数据库中的一个表。
 - map():map 函数遍历 RDD 的每一条线,分割成新 RDD。使用 map()变换,我们接受任何函数,并将该函数应用于 RDD 的每个元素。
 
Usage of map() transformation function
- flatMap() :借助 flatMap()函数,对于每个输入元素,我们在一个输出 RDD 中有很多元素。flatMap()最简单的用法是将每个输入字符串拆分成单词。
 
Usage of flatMap() transformation function
- filter() : Spark RDD 过滤器()函数返回一个新的 RDD,只包含满足谓词的元素。
 
Usage of filter() transformation function
- whole text files():whole text files 返回一个 PairRDD,其键是文件路径,值是文件内容。
 
开始执行任务
首先,我们将获取 HDFS 中传输的所有数据,并使用 wholeTextFiles 读取数据。
data = sc.wholeTextFiles(“hdfs:///Data_w/*/*”)
输出将具有键-值配对的 RDD,其中键是文件路径,内容是值。我们可以去掉文件路径,只处理内容。每个文件内容包含由
pages = data.flatMap(lambda x :(x[1].split('</doc>')))
一旦我们有了所有的文章,我们需要找到文章是关于什么的。每篇文章的第一行是标题,其余部分是内容。我们可以使用这些信息将每篇文章转换成一个键-值对,其中键是标题,值是内容。

Snapshot of each article
Function to extract the title
Function to extract the content
pages = data.flatMap(lambda x :(x[1].split(‘</doc>’))).map(lambda x : (get_title(x),get_content(x)))
接下来,就是只过滤掉人物(名人)对应的文章。之前,写一些逻辑,让我们看看一些名人网页看起来如何。

Wiki Page of Sir Isaac Newton

Wiki Page of Virat Kohli

Wiki Page of Brad Pitt

Wiki Page of Michael Jackson
让我们也看看一些非名人的网页。

Wiki Page of the United States

Wiki Page of Taj Mahal, India
名人页面和非名人页面有什么不同?所有名人页面的共同点是什么?
大多数名人的页面在第一句话就包含了出生日期。在维基百科数据中,这个出生日期是以下两种格式之一:
- 年月日:如 1993 年 8 月 12 日
 - 年月日:如 1993 年 8 月 12 日
 
我们可以利用这个事实来快速过滤掉所有的名人页面。我将使用 Regex 来查找这种格式。
Code to check if the Wiki page is a Celebrity Page or not
最后,我们可以将输出保存为表格。完整的代码如下所示:
Entire Code for the project
3.验证创建的名人数据集
维基百科总共有大约 598 万篇文章。我们的名人数据集有 138 万篇文章。所有名人的名单和获得的数据可以在这里找到。
该数据集包含了关于迈克尔·杰克逊、阿米特巴·巴强、布拉德·皮特、萨钦·坦杜尔卡尔、多尼女士以及所有我们能想到并核实的其他名人的文章。
4.结论
维基百科是互联网上所有可能信息的最佳去处之一。我们可以用它来创建许多有趣的应用程序,你的下一个大而有趣的 NLP 项目。随着 Apache Spark 的使用,处理这些海量数据变得很容易。用不到 20-25 行代码,我们就可以从中创建大多数有趣的数据集。
写一篇清晰易懂的好文章需要很多努力。我会继续努力做好我的工作。在 中 关注我,查看我以前的帖子。我欢迎反馈和建设性的批评。所有名人和数据集的列表以及代码可以在这里找到。
我的 Youtube 频道获取更多内容:
嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…
www.youtube.com](https://www.youtube.com/channel/UCg0PxC9ThQrbD9nM_FU1vWA)
5.参考
- https://www . tutorialspoint . com/Apache _ spark/Apache _ spark _ introduction . htm
 - https://spark.apache.org/
 - 【https://en.wikipedia.org/wiki/Apache_Spark
 - https://en.wikipedia.org/wiki/MapReduce
 - https://data-flair . training/blogs/spark-rdd-operations-transformations-actions/
 - https://data-flair.training/blogs/spark-rdd-tutorial/
https://data-flair . training/博客/Apache-spark-rdd-vs-data frame-vs-dataset/ - https://www . analyticsvidhya . com/blog/2019/10/py spark-for-初学者-第一步-大数据-分析/
 - https://blog.softhints.com/python-regex-match-date/
 
在 AWS 中使用 PySpark 处理渐变维度类型 2
随着新技术的出现,使得数据处理变得像闪电一样快,云生态系统允许灵活性、成本节约、安全性和便利性,似乎有一些数据建模哲学不太经常使用。其中一种方法是星型模式数据架构。
简而言之(我假设阅读本文的人熟悉概念),星型模式以多维方式存储数据,以便通过提供更快更简单的查询性能来提供更好的用户体验。在维度模型中,数据驻留在事实表或维度表中。事实表保存动作的度量和相关维度的键,维度包含所述动作的属性。维度可以是静态的(例如时间维度),也可以保存历史(也称为渐变维度类型 2,也称为 SCD2)。值得注意的是,星型模式是分析系统,这意味着它们不通常直接从用户应用程序中消费数据。相反,数据存储在高度规范化的事务系统中,星型模式利用一些提取过程从该系统中获取数据。
下面是一个销售计划的基本星型模式的示例,它有一个事实表和三个维度(dim_customer_scd 是一个 SCD2)。

星型模式通常在 RDBMS 层处理,这里允许更新和删除(这里不讨论),但是当事实和 SCD2 表包含数百万或数十亿行时,处理时间可能是个问题。在这个时代,我们经常会想到 Spark 或 Hadoop 这样的分布式集群框架。人们可以整天开玩笑和假设哪个是首选框架,但这不是本次讨论的主题,我将解释如何在 AWS 环境中使用 Spark 作为框架和 PySpark 作为脚本语言来处理 SCD2,并使用大量 SparkSQL。
最基本的,SCD2 的目的是保存变更的历史。如果客户更改了他们的姓氏或地址,SCD2 将允许用户将订单链接回客户及其在订单时所处状态的属性。如果我不保留那段历史,就很难做到。本质上,我可以找到客户在任何时间点的真实状态。

dim_customer_scd (SCD2)
数据集非常窄,由 12 列组成。我可以把这些列分成 3 个小组。
- 按键 : customer_dim_key
 - 非维度属性:名,姓,中间名,地址,城市,州,邮政编码,客户号
 - 行元数据:生效开始日期,生效结束日期,当前日期
 
key通常是自动创建的,没有商业价值。它们只是用作其他表的外键,并为行提供唯一性。有时可以使用自然键,但是在星型模式中非常少见。
非维度属性描述了数据集主题的不同方面,在所用的例子中是一个客户。这些属性可能具有业务意义,并在报告和分析中被进一步用于下游。我将把这些简单地称为“属性”。
行元数据列特定于 SCD2s,描述记录的状态。eff_start_date 存储记录生效的日期。eff_end_date 存储记录到期的日期(注意:未到期的记录通常有一个遥远的日期,如‘9999–12–31’);is_current 表示记录是否是最新的。is_current 对于生效日期来说是多余的,但是有些人喜欢这个标志,以避免在他们的查询或脚本中使用日期逻辑。
我在这个数据集中有四行。如果我查看 customer_number ,我可以看到所有的行都由三个不同的客户组成:John、Susan 和 William。John 和 William(分别在第 1 行和第 4 行)在表中只有一个条目,这意味着他们的数据在插入后没有更改过。
另一方面,Susan 有两条记录(第 2 行和第 3 行)。第 2 行是历史记录,用 is_current = false 表示,而第 3 行是 Susan 自 is_current = true 以来的最新信息。第 2 行“姓氏”列中的值为“Jones ”,第 3 行包含“Harris ”,而所有其他属性字段保持不变。
当 Susan 的姓是 Jones 时,表中只有三行,当她的姓改变时,会添加第四行。在表格中实现这一点的实际逻辑是什么?在高层次上:
- 发现源系统中的姓氏发生了变化。
 - 记录已过期;eff_end_date 更新为昨天的日期,is_current 设置为 false。
 - 将插入一条新记录,其中包含新的姓氏、今天的生效开始日期和将来的生效结束日期,并且 is_current 设置为 true。
 
注意:对于 eff_start_date 和/或 eff_end_date 字段,使用逻辑业务日期通常更好,但是为了讨论的目的,让它保持简单
在 RDBMS 中,很容易实现这一点。然而,由于 Spark 中更新功能的各种限制,我不得不采用不同的方式。
是时候讨论细节了。
步骤 1:创建 Spark 会话
我可以开始我们的 Spark 会议,并为我们在 S3 的目标路径创建一个变量:
from pyspark.sql import SparkSessionspark = SparkSession.builder.appName("scd2_demo").getOrCreate()v_s3_path = "s3://mybucket/dim_customer_scd"
步骤 2:创建 SCD2 数据集(用于演示目的)
您可以使用下面的脚本来生成当前的 SCD2,将其写入 Parquet,创建一个临时表,并查看结果(我将始终使用这个模式来帮助描述):
# ############## generate current_scd2 dataset ############## #hd_current_scd2 = """
 SELECT   BIGINT(1) AS customer_dim_key,
          STRING('John') AS first_name,
          STRING('Smith') AS last_name,
          STRING('G') AS middle_initial,
          STRING('123 Main Street') AS address,
          STRING('Springville') AS city,
          STRING('VT') AS state,
          STRING('01234-5678') AS zip_code,
          BIGINT(289374) AS customer_number,
          DATE('2014-01-01') AS eff_start_date,
          DATE('9999-12-31') AS eff_end_date,
          BOOLEAN(1) AS is_current
 UNION
 SELECT   BIGINT(2) AS customer_dim_key,
          STRING('Susan') AS first_name,
          STRING('Jones') AS last_name,
          STRING('L') AS middle_initial,
          STRING('987 Central Avenue') AS address,
          STRING('Central City') AS city,
          STRING('MO') AS state,
          STRING('49257-2657') AS zip_code,
          BIGINT(862447) AS customer_number,
          DATE('2015-03-23') AS eff_start_date,
          DATE('2018-11-17') AS eff_end_date,
          BOOLEAN(0) AS is_current
 UNION
 SELECT   BIGINT(3) AS customer_dim_key,
          STRING('Susan') AS first_name,
          STRING('Harris') AS last_name,
          STRING('L') AS middle_initial,
          STRING('987 Central Avenue') AS address,
          STRING('Central City') AS city,
          STRING('MO') AS state,
          STRING('49257-2657') AS zip_code,
          BIGINT(862447) AS customer_number,
          DATE('2018-11-18') AS eff_start_date,
          DATE('9999-12-31') AS eff_end_date,
          BOOLEAN(1) AS is_current
 UNION
 SELECT   BIGINT(4) AS customer_dim_key,
          STRING('William') AS first_name,
          STRING('Chase') AS last_name,
          STRING('X') AS middle_initial,
          STRING('57895 Sharp Way') AS address,
          STRING('Oldtown') AS city,
          STRING('CA') AS state,
          STRING('98554-1285') AS zip_code,
          BIGINT(31568) AS customer_number,
          DATE('2018-12-07') AS eff_start_date,
          DATE('9999-12-31') AS eff_end_date,
          BOOLEAN(1) AS is_current
"""df_current_scd2 = spark.sql(hd_current_scd2)df_current_scd2.coalesce(1).write.mode("overwrite").parquet(v_s3_path + "/current_scd2/")df_current_scd2.createOrReplaceTempView("current_scd2")# ############## review dataset ############## #df_current_scd2 = spark.read.parquet(v_s3_path + "/current_scd2/*").orderBy("customer_dim_key")df_current_scd2.show(10, False)
步骤 3:从源系统创建客户数据集(用于演示目的)
您可以使用下面的脚本来生成您的源数据,我将用它来修改我们的 SCD2:
# ############## generate customer_data dataset ############## #hd_customer_data = """
 SELECT   BIGINT(289374) AS customer_number,
          STRING('John') AS first_name,
          STRING('Smith') AS last_name,
          STRING('G') AS middle_initial,
          STRING('456 Derry Court') AS address,
          STRING('Springville') AS city,
          STRING('VT') AS state,
          STRING('01234-5678') AS zip_code
 UNION
 SELECT   BIGINT(932574) AS customer_number,
          STRING('Lisa') AS first_name,
          STRING('Cohen') AS last_name,
          STRING('S') AS middle_initial,
          STRING('69846 Mason Road') AS address,
          STRING('Atlanta') AS city,
          STRING('GA') AS state,
          STRING('26584-3591') AS zip_code
 UNION
 SELECT   BIGINT(862447) AS customer_number,
          STRING('Susan') AS first_name,
          STRING('Harris') AS last_name,
          STRING('L') AS middle_initial,
          STRING('987 Central Avenue') AS address,
          STRING('Central City') AS city,
          STRING('MO') AS state,
          STRING('49257-2657') AS zip_code
 UNION
 SELECT   BIGINT(31568) AS customer_number,
          STRING('William') AS first_name,
          STRING('Chase') AS last_name,
          STRING('X') AS middle_initial,
          STRING('57895 Sharp Way') AS address,
          STRING('Oldtown') AS city,
          STRING('CA') AS state,
          STRING('98554-1285') AS zip_code
"""df_customer_data= spark.sql(hd_customer_data)df_customer_data.coalesce(1).write.mode("overwrite").parquet(v_s3_path + "/customer_data/")df_customer_data.createOrReplaceTempView("customer_data")# ############## review dataset ############## #df_customer_data= spark.read.parquet(v_s3_path + "/customer_data/*").orderBy("customer_number")df_customer_data.show(10, False)

Current State of the SCD2

Customer_Data from Source System
第四步:手动查找变更(只是为了主题)
请记住,来自源系统的数据馈入到我们的 SCD2 中,因此我需要比较这两个数据集,以确定是否有任何差异。经过我们的手动调查,我看到:
- 约翰·史密斯改变了他们的地址
 - 丽莎·科恩是一位新顾客
 - 威廉·蔡斯和苏珊·哈里斯的属性保持不变
 
现在,我需要编写一些逻辑来完成以下所有任务:
- 为 John Smith 创建新条目
 - 使约翰·史密斯的当前条目过期
 - 保持威廉·蔡斯和苏珊·哈里斯的记录不变
 - 为我们的新客户 Lisa Cohen 添加一个条目
 
步骤 5:为现有客户创建新的当前记录
为了从逻辑上捕捉这种地址变化,我需要比较当前的 SCD2 和源数据(,就像我在上面手动做的那样)以及标志变化。我还需要注意我们的行元数据字段,以确保我使用适当的日期终止和开始记录。
幸运的是,我可以在一个 SQL 块中完成这项工作,并将结果写到 S3 的一个文件中:
- 将 customer_data 数据集连接到 customer_number 上的当前 SCD2 数据集和当前记录
 - 检查 WHERE 子句中的差异
 - 从源数据集中选择所有属性
 - 从当前 SCD2 数据集中选择 customer _ dim _ key(用于步骤 6 )
 - 将生效日期设置为今天
 - 将生效日期设置为将来
 - 将 is_current 设置为 1
 
# ############## create new current recs dataaset ############## #hd_new_curr_recs = """
 SELECT   t.customer_dim_key,
          s.customer_number,
          s.first_name,
          s.last_name,
          s.middle_initial,
          s.address,
          s.city,
          s.state,
          s.zip_code,
          DATE(FROM_UTC_TIMESTAMP(CURRENT_TIMESTAMP, 'PDT'))
              AS eff_start_date,
          DATE('9999-12-31') AS eff_end_date,
          BOOLEAN(1) AS is_current
 FROM     customer_data s
          INNER JOIN current_scd2 t
              ON t.customer_number = s.customer_number
              AND t.is_current = True
 WHERE    NVL(s.first_name, '') <> NVL(t.first_name, '')
          OR NVL(s.last_name, '') <> NVL(t.last_name, '')
          OR NVL(s.middle_initial, '') <> NVL(t.middle_initial, '')
          OR NVL(s.address, '') <> NVL(t.address, '')
          OR NVL(s.city, '') <> NVL(t.city, '')
          OR NVL(s.state, '') <> NVL(t.state, '')
          OR NVL(s.zip_code, '') <> NVL(t.zip_code, '')
"""df_new_curr_recs = spark.sql(hd_new_curr_recs)df_new_curr_recs.coalesce(1).write.mode("overwrite").parquet(v_s3_path + "/new_curr_recs/")df_new_curr_recs.createOrReplaceTempView("new_curr_recs")# ############## review dataset ############## #df_new_curr_recs = spark.read.parquet(v_s3_path + "/new_curr_recs/*").orderBy("customer_number")df_new_curr_recs.show(10, False)
上面的逻辑遍历所有记录,找到我手动观察到的一个变化。正如您在下面看到的,为 John Smith 用他的新地址创建了一个新记录,行元数据显示这个记录今天生效,将来过期。

New Record for John Smith
步骤 6:查找要过期的以前的当前记录
现在我有了一个已经存在的客户的新的当前记录,我需要终止以前的当前记录。我在之前的数据集中包含了之前的当前记录的 customer_dim_key,所以我将其分离出来供将来使用。
# ########### isolate keys of records to be modified ########### #df_modfied_keys = df_new_curr_recs.select("customer_dim_key")df_modfied_keys.coalesce(1).write.mode("overwrite").parquet(v_s3_path + "/modfied_keys/")df_modfied_keys.createOrReplaceTempView("modfied_keys")

Records to be Modified
步骤 7:终止以前的当前记录
现在我可以让之前的记录过期,同时再次注意我们的行元数据字段并正确地修改它们。回想一下,我不能更新记录,所以我必须创建它的一个新实例。
在这段代码中,我将:
- 将当前 SCD2 数据集连接到 customer_dim_key 上的 modified_keys 数据集
 - 通过仔细检查 is_current = 1,确保当前记录即将到期
 - 从当前 SCD2 数据集中选择所有属性和 eff_start_date
 - 将生效日期设置为昨天
 - 将 is_current 设置为 0
 
# ############## create new hist recs dataaset ############## #hd_new_hist_recs = """
 SELECT   t.customer_dim_key,
          t.customer_number,
          t.first_name,
          t.last_name,
          t.middle_initial,
          t.address,
          t.city,
          t.state,
          t.zip_code,
          t.eff_start_date,
          DATE_SUB(
              DATE(FROM_UTC_TIMESTAMP(CURRENT_TIMESTAMP, 'PDT')), 1
          ) AS eff_end_date,
          BOOLEAN(0) AS is_current
 FROM     current_scd2 t
          INNER JOIN modfied_keys k
              ON k.customer_dim_key = t.customer_dim_key
 WHERE    t.is_current = True
"""df_new_hist_recs = spark.sql(hd_new_hist_recs)df_new_hist_recs.coalesce(1).write.mode("overwrite").parquet(v_s3_path + "/new_hist_recs/")df_new_hist_recs.createOrReplaceTempView("new_hist_recs")# ############## review dataset ############## #df_new_hist_recs = spark.read.parquet(v_s3_path + "/new_hist_recs/*").orderBy("customer_number")df_new_hist_recs.show(10, False)
上述逻辑使记录正确过期,并写入其自己的数据集:

Expired Record for John Smith
步骤 8:隔离未受影响的记录
威廉·蔡斯和苏珊·哈里斯的记录没有变化,它们需要保留在目标数据集中,所以下一步是将它们放入自己的数据集中。
该逻辑将:
- 将 modified_keys 数据集左连接到 customer_dim_key 上的当前 SC2 数据集
 - 查看不在 modified_keys 数据集中的记录
 - 保持所有属性和行元数据不变
 
# ############## create unaffected recs dataset ############## #hd_unaffected_recs = """
 SELECT   s.customer_dim_key,
          s.customer_number,
          s.first_name,
          s.last_name,
          s.middle_initial,
          s.address,
          s.city,
          s.state,
          s.zip_code,
          s.eff_start_date,
          s.eff_end_date,
          s.is_current
 FROM     current_scd2 s
          LEFT OUTER JOIN modfied_keys k
              ON k.customer_dim_key = s.customer_dim_key
 WHERE    k.customer_dim_key IS NULL
"""df_unaffected_recs = spark.sql(hd_unaffected_recs)df_unaffected_recs.coalesce(1).write.mode("overwrite").parquet(v_s3_path + "/unaffected_recs/")df_unaffected_recs.createOrReplaceTempView("unaffected_recs")# ############## review dataset ############## #df_unaffected_recs = spark.read.parquet(v_s3_path + "/unaffected_recs/*").orderBy("customer_number")df_unaffected_recs.show(10, False)
未受影响的记录实际上是孤立的:

Unaffected Recs
步骤 9:为新客户创建记录
Lisa Cohen 是一位新客户,因此还不存在于我们的 SCD2 中。
以下逻辑:
- Left 将当前 SCD2 数据集连接到 customer_number 上的 customer_data 数据集
 - 查看不在当前 SCD2 数据集中的记录
 - 使用源中的所有属性
 - 将生效日期设置为今天
 - 将生效结束日期设置为将来
 - 将 is_current 设置为 1
 
# ############## create new recs dataset ############## #hd_new_cust = """
 SELECT   s.customer_number,
          s.first_name,
          s.last_name,
          s.middle_initial,
          s.address,
          s.city,
          s.state,
          s.zip_code,
          DATE(FROM_UTC_TIMESTAMP(CURRENT_TIMESTAMP, 'PDT')) 
              AS eff_start_date,
          DATE('9999-12-31') AS eff_end_date,
          BOOLEAN(1) AS is_current
 FROM     customer_data s
          LEFT OUTER JOIN current_scd2 t
              ON t.customer_number = s.customer_number
 WHERE    t.customer_number IS NULL
"""df_new_cust = spark.sql(hd_new_cust)df_new_cust.coalesce(1).write.mode("overwrite").parquet(v_s3_path + "/new_cust/")df_new_cust.createOrReplaceTempView("new_cust")# ############## review dataset ############## #df_new_cust = spark.read.parquet(v_s3_path + "/new_cust/*").orderBy("customer_number")df_new_cust.show(10, False)
这是结果。新客户的预期格式是:

New Customer Record
步骤 10:合并新 SCD2 的数据集
我已经创建了创建新的 SCD2 迭代所需的四个数据集:
- 现有客户的新当前记录的数据集(" new_curr_recs ")
 - 现有客户的过期前当前记录的数据集(" new_hist_recs ")
 - 未被修改的记录数据集("未受影响 _ 记录")
 - 以前未见过的新客户的数据集(" new_cust ")
 
剩下的就是将它们融合在一起,形成最终产品。在最后这段代码中,我将:
- 找出最大客户尺寸关键值
 - 联合两个没有 customer_dim_key 的数据集:new_cust 和 new_curr_recs
 - 要创建新的 customer_dim_key,请使用 ROW_NUMBER()函数并添加最大 customer_dim_key 值(以保持连续性和唯一性)
 - 将先前联合的数据集联合到 unaffected _ recs 和 new_hist_recs
 
# ############## create new scd2 dataset ############## #v_max_key = spark.sql(
    "SELECT STRING(MAX(customer_dim_key)) FROM current_scd2"
).collect()[0][0]hd_new_scd2 = """
 WITH a_cte
 AS   (
        SELECT     x.first_name, x.last_name,
                   x.middle_initial, x.address,
                   x.city, x.state, x.zip_code,
                   x.customer_number, x.eff_start_date,
                   x.eff_end_date, x.is_current
        FROM       new_cust x
        UNION ALL
        SELECT     y.first_name, y.last_name,
                   y.middle_initial, y.address,
                   y.city, y.state, y.zip_code,
                   y.customer_number, y.eff_start_date,
                   y.eff_end_date, y.is_current
        FROM       new_curr_recs y
      )
  ,   b_cte
  AS  (
        SELECT  ROW_NUMBER() OVER(ORDER BY a.eff_start_date)
                    + BIGINT('{v_max_key}') AS customer_dim_key,
                a.first_name, a.last_name,
                a.middle_initial, a.address,
                a.city, a.state, a.zip_code,
                a.customer_number, a.eff_start_date,
                a.eff_end_date, a.is_current
        FROM    a_cte a
      )
  SELECT  customer_dim_key, first_name, last_name,
          middle_initial, address,
          city, state, zip_code,
          customer_number, eff_start_date,
          eff_end_date, is_current
  FROM    b_cte
  UNION ALL
  SELECT  customer_dim_key, first_name,  last_name,
          middle_initial, address,
          city, state, zip_code,
          customer_number, eff_start_date,
          eff_end_date, is_current
  FROM    unaffected_recs
  UNION ALL
  SELECT  customer_dim_key, first_name,  last_name,
          middle_initial, address,
          city, state, zip_code,
          customer_number, eff_start_date,
          eff_end_date, is_current
  FROM    new_hist_recs
"""df_new_scd2 = spark.sql(hd_new_scd2.replace("{v_max_key}", v_max_key))# ############## review dataset ############## #df_new_scd2.coalesce(1).write.mode("overwrite").parquet(v_s3_path + "/new_scd2/")df_new_scd2 = spark.read.parquet(v_s3_path + "/new_scd2/*").orderBy("customer_dim_key")df_new_scd2.show(10, False)

New SCD2
在新版本的 SCD2 中,一切都如预期的那样:
- 威廉·蔡斯和苏珊·哈里斯的记录没有改变
 - 约翰·史密斯有一个旧地址在 2019 年 4 月 14 日到期的记录
 - 约翰·史密斯有一个新记录,新地址于 2019 年 4 月 15 日生效
 - 丽莎·科恩的新纪录于 2019 年 4 月 15 日生效
 - 数据集上一次迭代中存在的记录保留了它们的 customer_dim_keys,因此星型模式中的事实表不需要重新映射
 
新的 SCD2 存放在 S3,可以随心所欲地使用。
一些注意事项:
- 表演很精彩。在我的生产环境中,源表有 382 列和大约 700 万条记录,SCD2 有 81 列和大约 1 . 1 亿条记录。处理这些数据*均需要大约 10 分钟。在标准 RDBMS 中,大约 180 分钟即可完成。处理时间缩短了 94%。
 - 我在这次讨论中使用的 S3 路径并不真正适用于现实生活中的商业场景,但在这个教学场景中非常适用。
 
我很难在网上找到任何关于使用 Spark 处理 SCD2s 和 star 图式的信息。坦白地说,这很令人沮丧,我很高兴自己弄明白了这一点。此外,我惊喜地发现,不需要火箭科学学位就能做到这一点。我希望您可能遇到的任何挫折都是短暂的,并且这个讨论可以帮助您进行大数据、星型模式脚本工作。
正在处理 MongoDB 操作日志
数据处理
从操作日志重建 MongoDB 文档
在之前的帖子中,我介绍了什么是 MongoDB 操作日志及其语义。在这篇文章中,我将研究如何处理它以获得文档的新状态。
概述
首先,让我们提醒一下数据操作:插入、更新和删除。对于插入和删除,整个文档中只有o字段存在,或者只有_id被删除。对于更新,o字段包含作为$set和$unset命令的更新,o2记录正在更新的文档的_id。
我们可以忽略c (DB 命令)和n (NOOP)操作,因为它们不会修改数据。
问题
让我们考虑一个包含超过 1TB 数据的大型 MongoDB 集合,它每天都需要传输到一个仓库或湖泊或另一个存储系统。一种方法是每天使用mongoexport实用程序执行一次完全导出。然而,我们很快发现,这可能需要很长时间,这使得日常出口不可行。我们还必须考虑对集群本身的性能影响。
另一种方法是导出一次,获取 1 天的更新(操作日志),并将这些更新应用于现有对象。这需要 MongoDB 集群上更少的资源来读取操作日志,但也允许以任何所需的频率应用更改。
解决办法
请记住,操作日志是 MongoDB 集群变化的绝对有序列表。这意味着需要对每个文档顺序应用操作日志。这导致通过文档收集所有操作,排序和更新文档。从逻辑上讲,这听起来很简单。
我选择用 Apache Spark 和 Python 来解决这个问题,因为数据量需要分布式处理,而且我熟悉 Python。
读取操作日志
首先是阅读所有现有的导出文档和操作日志。
objs = sc.textFile(self.input()['objects'].path) \
         .map(json.loads)ops = sc.textFile(self.input()['oplog'].path) \
        .map(json.loads) \
        .map(lambda x: x['message']) \ #my tailing app writes the oplog as string in this `message` field.
        .map(json.loads)
清理和过滤操作日志
在此步骤中,我们将对象转换为元组,第一个元素作为对象 ID,第二个元素是操作日志条目本身。这将帮助我们基于密钥加入。
操作日志条目被类似地转换,但是因为每个对象 ID 可以有多个条目,所以我们使用一个groupBy。如果您记得操作日志也有在碎片之间迁移数据的系统操作,我们需要排除这些操作。这发生在现有的fromMigrate字段上的一个简单过滤器上。
objs = objs.map(lambda x: (str(x['_id']), x))ops = ops.filter(lambda x: "fromMigrate" not in x) \
         .map(prepare_op) \
         .groupBy(lambda x: str(x['id']))
此时,我们的对象和操作日志条目都已准备好进行处理和合并。
操作日志合并

为了应用操作,我们使用一个定制的映射函数应用于一个完全外部连接的结果。我们需要完全外部连接的原因是为了在操作日志中包含不存在的新对象,以及没有任何操作日志条目的未修改文档。完全连接为我们提供了完整的数据集,而不仅仅是修改过的文档。
final = objs.fullOuterJoin(ops) \
            .map(merge_object) \
            .filter(lambda x: x[1][0] is not None) \
            .map(lambda x: x[1][0]) \
            .map(remove_extra)
合并 _ 对象
这个映射函数负责应用操作。对于插入,它创建一个新记录。对于更新,它遍历$set和$unset来操作被改变的字段。对于删除,它会从 RDD 中移除文档。
滤镜&贴图
然后,过滤器和地图改变形状,返回一个 RDD,其中仅包含处于最终状态的合并文档。remove_extra功能通过删除merge_object期间添加的元数据字段来清理文档。
final RDD 现在包含在应用操作日志条目结束时所有文档处于一致状态的结果数据集。在我们的例子中,这是第二天的数据集。这种在 Spark 集群上运行的处理可以加快处理速度,并且不需要每次都完全导出数据。
流式传输
现在流媒体是一件大事,所以这里有一些关于它的话。这个管道可以变成流式管道。如果你照现在这样做,就有可能在小批量上运行它;但是,处理时间可能会比批处理间隔长。一种替代方式是以规则的间隔处理操作日志条目,以将这些条目折叠/合并成最终操作,该最终操作可以以更长的间隔应用于对象。我没有玩过这个,但是根据收藏的大小,它可能会工作得很好。对于流,返回修改过的文档并忽略任何删除或未修改的文档可能是有意义的。这将使连接更快,处理的集合更小。
如果你以相似或不同的方式处理 MongoDB 操作日志,我很乐意听听你对这个过程的想法。我希望在另一篇文章中讨论变更流,但是如果你用它来代替,请让我知道。
r 代表产品分析
用 R 从用户行为中获得洞察力
如何从用户行为中获得洞察力
该分析基于 Alistair Croll 和 Benjamin Yoskovitz 所著的《精益分析:使用数据分析更快地建立更好的创业公司》一书的概念。根据这本书,它旨在对产品生命周期的三个关键阶段——获取、活动和保留进行简单的数据探索。
关于数据
该示例基于一个真正的软件即服务、基于订阅的产品。有两个数据集可用:
- registrations.csv :拥有基本人口统计数据的唯一用户
 - activity.csv :哪些用户在哪个月活跃过
 
关于数据集的更多信息可以在项目的 GitHub 库上获得。
获得物ˌ获得
习得是一个阶段,在这个阶段,你应该通过各种方式,包括有机的和无机的,来引起别人的注意。评估获取的相关指标包括流量、提及次数、每次点击成本、搜索结果、获取成本、打开率等。
作为分析的第一步,让我们看看每个月的注册数量:

Figure 1: number of registrations per month
我们可以看到,第二年的注册数量总体较低(21831 对 18295)。第一年,大多数登记发生在秋季/初冬期间(9 月至 11 月)。我们不知道该产品何时投放市场,第一年上半年的低谷期可能类似于早期适应者,第二年下半年的高峰可能是一次成功的营销活动。在圣诞节假期经历了一些低谷之后,在第二年的五月出现了第二个高峰,然后注册人数突然下降了 36.87%。这可能是产品更新失败、市场覆盖范围缩小或其他情况。
为了更深入地挖掘数据,我们可以看到注册的逐年增长:

Table 1: Year on Year growth of registrations
下一个图显示了每个月的增长率,以及第 22 个月(第二年的 10 月)的简单预测:

Figure 2: Year-on-year growth & Naive Forecast
同比数据似乎在下降,但第二年的注册数量一直保持在较高水*,直到 9 月份。10 月份的天真预测是 0.976。
我们可以根据地理区域调查注册号是否有任何差异:

Figure 3: Region differences in year-on-year growth
比较地区,似乎有区别。除了第一年年初,美洲的表现不如 T2、EMEA 和世界其他地区。所有城市的注册人数都呈下降趋势,但排区域的增长速度似乎最快。这可能会推动未来注册量的增长,而 EMEA、尤其是美洲可能对该产品有不同的兴趣,或者他们受营销活动的影响较小。
活动
激活是将由此产生的路过访客转化为以某种方式注册的用户。这可以通过跟踪特定的活动里程碑来完成,如注册、签约、完成入职流程、至少使用一次服务、订阅等。
下图显示了每月活跃用户的数量:

Figure 4: number of active users per month
用户数增加到第一年夏天,然后下降,9 月份才回到 5 月份的水*。它在 11 月达到高峰,在圣诞节和冬季下降。第二年的活跃用户数量在 3 月至 5 月间达到最高,夏季再次下降,显示出季节性特征。
正如我们所看到的,美国地区正在努力应对新注册。让我们看看 America 在每月活跃用户中所占的百分比:

Figure 5: number of active users per month
我们可以看到,来自美国的用户数量*均在 17-22%之间。该公司必须考虑投资于其他方式来推动市场,或者专注于他们的其他客户,这些客户似乎有更好的注册率和活动率。
看看用户的活动模式是值得的。用户可分为新(当月注册)保留(前一个月也活跃)或复活(前一个月不活跃且不是新)。
为了说明这一点,看一下随机选择的用户的活动历史:

Table 2: User activity history
这个在 7 月注册的用户在 8 月继续使用该服务,然后在 9 月没有进行任何活动。他 11 月回来,12 月也很活跃。第二年就没有用过了。
现在让我们来看看每个月保留的活跃用户的数量:

Figure 6: number of Retained users per month
保留
留存阶段的主要任务是 说服用户反复回来,展现粘性行为。它可以通过参与度、自上次访问以来的时间、每日和每月的活跃使用、搅动等指标来跟踪。
在我们的例子中,我们可以计算第二个月的保留率(第一个月的注册用户在第二个月是活跃的)。
第二个月的保留率为 46.33%。可以认为相当不错,通常在 20%到 60%之间。
让我们看看第二年(第 13 个月和第 14 个月之间)的相同指标。
二年级一月注册的用户,二月活跃的占 36.84%。这仍是一个可以接受的数值,但自去年以来下降 10%的原因是什么呢?这可能是因为对该产品感兴趣的大多数用户已经注册了,所以新注册的潜在感兴趣的用户变得更少了。通过这种方式,第二年加入的用户并没有参与到产品中,并在接下来的一个月中以更高的比例决定退出。
我们还可以根据用户的操作系统来计算第二个月的保留率:

Table 3: Second-month retention rate by Operating System
对于未知的操作系统,留存率(38%)远低于 Mac 用户(61.5%)。一项措施是调查数据收集过程,并确定这些用户实际使用的操作系统。在 Mac 和 Linux 用户之间也有 20%的显著差异。这可能意味着该产品并没有像在 Mac 上那样针对 Linux 进行优化。
结论
通过对不同产品分析实践的基本介绍,我们可以看到,只需很少的努力和一些编程知识就可以得出关于用户行为的有趣假设。A/B 测试等方法可以用来测试这些假设,例如:优化产品的 Linux 版本将如何影响保留率,特定的广告活动应该针对哪些地区,等等。
这个项目是作为匈牙利中欧大学“掌握产品分析”课程的要求而完成的。R 代码和数据集可以在 GitHub 上我的 ceu_product-analytics 存储库中找到。
基于 ARIMA 的时间序列产品类别预测

假设我们手头有现有数据,可以告诉我们某一特定产品类别的市场现状。现在,我们能够看到趋势和运动,以及每个时期的重大事件,这些事件对事件的积极或消极转变产生了影响。
下面的图表显示了美国销售的新车总数。从 2002 年到 2019 年。从这张简单的图表中,我们可以看到,由于 2008 年 3 月开始的金融危机,这一趋势从 2008 年开始逐渐下降,并在 2009 年达到最低点。

of new cars sold in the U.S. from 2002–2019
如果我们想进一步分析汽车类别,预测消费者是否会像过去一样继续购买新车,该怎么办?这就是我们可以用 ARIMA 来回答这类问题的地方。
自回归综合移动*均线或 ARIMA,最简单的说法是使用自己的历史数据告知未来结果的方法,条件是数据是稳定的,即不受趋势、周期性、季节性或不规则性的影响。为什么?因为 ARIMA 研究的时间序列的性质并不依赖于观察时间。预测是困难的,因为时间序列本质上是不确定的。在我们上面的例子中,2008 年的金融危机影响了新车销售总量,这可以被视为一种不规则的变化,不会在一段时间内以特定的模式重复出现——这不是静态的。如果时间序列是*稳的,我们可以通过预测其统计特性,如均值、方差、自相关,使我们的问题变得简单一点。
ARIMA 由建模中的三个部分组成:
AR( p )模型(自回归) =作为预测因子的自身滞后值或
I(d)(积分) =*稳性所需的非季节性差异数,也称为 差异度
MA( q )模型(移动*均) =过去预测误差的类回归模型,顺序称为 顺序的移动*均
如果时间序列是*稳的,那么预测某个时间 𝑡 的𝑦值的 ARIMA 方程为 AR + I + MA 表示为:
预测为 𝑦 时 𝘵 = 常数 +加权求和的最后一个𝑝𝑦值+加权求和的最后一个 q 预测误差。
相同的等式用希腊字母正式表示为:
ŷ_𝑡= 𝑢+𝜑_₁𝑦_𝑡-₁+…+𝜑_𝑝𝑦_𝑡-𝑝-𝜃₁𝑒𝑡-̿-…-_**
其中𝑢为常数, 𝜑_𝑘 为滞后 𝑘时的 AR 系数, 𝜃_ 𝑘 为滞后 𝑘 时的 MA 系数,而 𝑒_ 𝑡- 是在时间段- 时产生的预测误差
在应用程序中,首先,我们必须确定数据是否稳定,这可以通过使用 增强的 Dickey-Fuller 测试 来实现。在测试中,我们想看看我们是否能拒绝陈述时间序列不是*稳的零假设(𝐻₀)。第二,可以用滚动均值和滚动标准差进行数学变换,直观地检验时间序列是否*稳。我们可以创建一个函数供将来使用。请注意,我们使用 12 年(或 1 年)作为数据评估的窗口期。
我们通过调用新创建的函数test _ stationary()来查看原始时间序列

A Dickey-Fuller Test on the original time-series
不出所料,p 值高于 5%,表明我们不能拒绝零假设,ADF 检验统计高于所有临界值,因此,结果不显著。请注意,所有临界值都会导致负数,这意味着更强烈地拒绝零假设。
另一种方法是绘制自相关图来可视化时间序列的*稳性——如果时间是非*稳的,我们将看到非常缓慢的衰减。

ACF of original non-stationary time series shows slow decay
数据转换实现静止
由于大多数统计预测方法都是基于这样一个假设,即时间序列在经过数学变换后可以*似*稳,因此我们将尝试几种类型的变换,然后用 ADF 测试来检验时间序列是否已经*稳。
我们可以使用 numpy 包中的对数标度变换,将时间序列变换成对数标度。

A Dickey-Fuller Test on the logarithmic scale of ts.
从对数标度变换中,我们可以观察到滚动*均值和滚动标准差的更*滑趋势,这表明时间序列正在接**稳性。然而,p 值仍然大于 5%,测试统计仍然大于所有临界值,因此我们将继续进一步区分转换后的数据。

A Dickey-Fuller Test on the differenced logarithmic scale of ts.
现在我们可以看到 ADF 检验统计量小于 10%和 5%的临界值,表明时间序列是*稳的,分别有 90%和 95%的置信度。为了获得更好的 ADF 检验统计,我们可以尝试其他类型的数学变换。但为了简单起见,我们将继续以对数标度为例。
选择型号规格
这里,当选择 p 和 q 时,最常见的方法是通过自相关函数(ACF) 和偏自相关函数(PACF) 将其可视化。ACF 测量时间序列和其自身滞后版本之间的相似性。请注意,系数也捕捉二手影响。这意味着 t 捕捉滞后系列的直接和间接方式; t-1 , t-2 影响原。如果我们只想知道时间序列和它的滞后版本之间的直接关系,那么我们使用 PACF 来确定这种影响。
我们现在将使用 ACF 和 PACF 图来查看模型规格。

从 ACF 测试中,我们注意到在 h = 12,24,36 处有多个重复出现的峰值,这是由于每年的循环效应。但是我们不会考虑季节性因素。对于 PACF 检验,我们将尝试用 AR(1),MA(0)和 ARIMA(1,1,0)来拟合模型,以解释滞后数,从而解释时间序列中的自相关模式。
请注意,理论上,实际情况是两个(p,q)中的一个应该是非零的,并且对于业务应用程序,两者之和通常小于 3。还建议避免使用既有 AR 系数又有 MA 系数的混合模型,除非您正在处理来自物理或工程应用程序的数据。最后但同样重要的是,经验法则是你应该总是得到一个更简单的模型。有关于规格选择的指南,其中 AR 和 MA 参数考虑单位根。

AR(1) Model

MA(0)
最后,我们使用 ARIMA(1,1,0)将 AR + I + MA 与 d = 1 组合起来。

ARIMA(1,1,0)

Summary of ARIMA(1,1,0)
我们还可以参考赤池信息准则 (AIC)来衡量我们比较不同模型时的拟合优度——AIC 数越小,模型拟合越好。最后,我们使用 plot_predict() 方法,根据实际时间序列来绘制我们的预测。

ARIMA forecast vs actual
概括起来
- 在本例中,我们只尝试了对数标度的时间序列转换。在实际应用中,可以使用指数衰减或时移等其他算术运算来*稳化时间序列,这可能会产生更好的 ADF 测试统计。
 - 其次,我们肯定应该尝试使用不同的参数来降低每个模型的 RSS 分数——这可以通过拟合不同的 p 和 q 值来实现。
 - 最后,我们所做的测试没有考虑季节性,在我们的时间序列中,我们看到每年有 12 个月的周期性影响,这可以通过季节性 ARIMA 来解决。
 
参考资料:
- http://people . cs . Pitt . edu/~ Milos/courses/cs 3750/lections/class 16 . pdf
 - https://otexts.com/fpp2/arima.html
 - http://people . duke . edu/% 7 ernau/Notes _ on _ non seasonal _ ARIMA _ models-Robert _ nau . pdf
 - https://people.duke.edu/~rnau/411arim3.htm#unitroot
 
使用机器学习的产品分类-第一部分
根据文本信息将产品分为最相关的类别。
机器学习中从“M”到“L”
如果你考虑一下英语字母表,字母 M 和 L 是连续的,从一个字母移动到另一个字母似乎是小菜一碟。然而,机器学习(ML)可能并非如此。我们对后者的了解可能是不断扩张的沙漠中逐渐消退的海市蜃楼。在这里,我将探索分类问题,以弥补“M”和“L”之间的差距。

我的问题,我的方式
有一点经常被重申,那就是彻底理解你的问题陈述的重要性。眼前的问题是将产品分类到最合适的类别或桶中。 Indiamart ,一个在线市场,总是需要相似的产品( 此处阅读 关于 Indiamart 上的产品)在它的*台上被列在一个标题下,这应该代表它们的特征,任何新产品都应该被分配到最合适的标题下。(,其将被进一步称为‘类别’)。
例如,棕色皮革安全手套应列在皮革安全手套(微观类别)和安全手套(宏观类别)下。这些宏观和微观类别列在一个产品组下。我们永远不会希望用户访问我们的皮手套页面,发现羊毛手套。我们只是想确保产品映射的正确性。
宏观和微观分类
这个问题需要在两个层面上进行分类——确定宏观和微观类别。对我们来说,每个微观范畴都与某个宏观范畴相关。为了理解我们如何定义宏观和微观类别,让我们以手机为例。在这里,三星、苹果、Lava 和索尼手机形成了一个宏观类别手机的微观类别。所以如果,我拿到一个像三星 Note 这样的 4 GB RAM,64 GB 内存的产品,必须分配给三星手机(微单类)和手机(微单类)。

A Product At Indiamart. The Product Title, Specifications, and Description have been used to train the model. Also, note the product’s mapping in macro and micro categories.
产品组就像是相关宏类别的保护伞。我们当前的架构正确地认识到这一更广泛的产品范围,因此我们在这里的主要关注点将是产品组内宏观和微观类别的识别。
当瀑布激发你解决问题的方法时
我是一个狂热的自然爱好者,水让我有了许多发现,但正如人们所说的那样,“你不能仅仅站着凝视就穿越海洋”。谢谢,维克拉姆·瓦什尼帮助我渡过难关。在我们的瀑布方法中,有两个独立的模型——一个用于宏观类别,另一个用于微观类别;两者都是按顺序调用的。我们试图通过两步预测结果来降低树:首先,预测一个宏类别,然后预测一个微类别(仅在预测的宏类别内)。
这就是说,对于一个产品,一旦你知道它是一个空调(宏观类别),那么我们将微观类别(分体式空调、窗式空调、盒式空调等)的预测限制在宏观类别内。所以,我不会在其他电器下寻找结果。
解码分类器
我们使用 FastText 来训练我们的模型。F astText 是来自脸书的开源库,用于高效学习单词表示和句子分类。
如果你是 FastText 的新手,在运行它时遇到问题,请参考这个 视频教程 。
我们使用的是一个基于监督文本的分类器,它是使用以前标记的产品训练的。培训文件包含产品,每个产品在单独的文件中都有宏观和微观类别的适当标签。
宏类别的培训文件:
label *地机*地机推土机卡特彼勒 140k2
label 挖掘机 jcb js140 挖掘机
培训文件为微类别:
_ _ label _ _ JCB _ 挖掘机 jcb js140 挖掘机
label 卡特彼勒 _ *地机*地机推土机卡特彼勒 140k2
训练命令
imart@DESKTOP-CFGCP74 ~                                                                                                                                                 
$ fastText/fasttext.exe supervised -input ~/Training_File.txt -output ~/model.bin -lr 0.8 -minn 3 -wordNgrams 1 -thread 4 -loss hs;
针对每个宏观和微观类别标签,对数千种产品进行机器训练,以便建立关系。下次我们向它提供产品的文本信息时,它应该能够解释产品的宏观和微观类别。
测试宏类别的模型
imart@DESKTOP-CFGCP74 ~                                                                                                                                                 
$ fastText/fasttext.exe predict- prob ~/model.bin - 1 ;
**used mahindra earthmaster**
__label__**Backhoe_Loader** 0.9862
测试微观类别的模型
$ fastText/fasttext.exe predict-prob /cygdrive/c/Users/imart/Desktop/Bin\ Files/Backh.bin - 2                                                                           
**used mahindra earthmaster**                                                                                                                                               
__label__**Mahindra_Backhoe_Loader** 0.910756 __label__**Used_Backhoe_Loaders** 0.0892926
精度和召回
$ fastText/fasttext.exe -test ~/model.bin ~/Testing_File.txt ;@p : 0.952
@r : 0.952
注意:对于产品“二手 Mahindra Earthmaster ”,我们得到的宏观类别预测为“反铲装载机”,微观类别预测为“Mahindra 反铲装载机”和“二手反铲装载机”,这是正确的。 目前,当结果与对相同产品进行分类的主题专家进行比较时,该模型运行的准确率为 93.70%。
数据清理
这是非常必要的,这里我们将整个数据转换成小写,删除 xml,html 标签,如
等。、特殊符号和一些与用例相关的停用词。
超参数调谐
只有当弦被微调时,你才能得到完美的音乐,同样,机器的输出取决于用于训练模型的超参数。我们对 320 多个模型进行了训练和测试,以达到学习率、纪元、单词 n 元语法的最佳组合。这将在另一篇文章中详细介绍。
越多越开心
建议的一件事是获取尽可能多的训练数据。更大数量的标签将提高结果的准确性。为了避免预测偏差,我们还求助于标签加载。
这不是结束
正如丘吉尔所说——“这不是终点。这甚至不是结束的开始。但这也许是开始的结束。”到目前为止,我只探索了产品的一个方面——它包含的文本。图像、价格和位置呢?视觉可能会给这个分类问题增加另一个维度。
我们正从基于单词的向量转向句子嵌入,从文本挖掘转向图像分类——谷歌的 BERT,GUSE 脸书的《InferSent》和《ResNeXt》可能会成为一线希望。
我将在后续文章中介绍如何应用基于图像的分类器来解决同样的问题。此外,我将分享我们如何尝试将宏观和微观类别的独立模型整合成一个单一模型。
维克拉姆·瓦什尼 , 阿尤什·古普塔 , 阿苏托什·辛格——感谢你对这个项目的持续贡献,感谢你鼓励我写这篇文章。
感谢整个品类团队一直以来的支持。
电子商务中的图像分类第一部分

This eye-catching image becomes all the more enchanting when you get to know that our brain processes visuals 60,000 times faster than text and retains 80 percent of what we see versus just 20 percent of what we read.
当图像成为故事讲述者
图像通常承担着讲述故事和表达强大思想的角色,就像他们说的那样“一张图片胜过千言万语”。图像讲述思想的能力吸引了人类,由于人类大脑的一半直接或间接用于视觉,视觉成为我们理解周围世界的主要感觉。
在本文中,我将解释我们如何使用图像来解决最流行的商业问题之一,即产品分类。
圣杯
像 Indiamart 这样的大型在线市场有数以千计的宏类别,用于列出各种产品。产品必须被映射到*台上最合适的微观类别下。【关于 宏观范畴 和 微观范畴 的定义请参考这篇值得称道的 帖子 的一节:“我的问题,我的方式”]
这篇文章的目标是建立直觉和理解,如何训练神经网络来使用产品的图像识别产品的微观类别。
例如,在宏观类别‘皮革安全手套’,中可以有各种微观类别,如工业皮革手套、皮革焊接手套、铬革手套等。我们打算对我们的产品进行分类,使工业 皮革 安全手套图片始终归入工业 皮革 安全手套微型类别。同样,一个工作靴的图像总是预测一个微观类别安全工作靴,其中其宏观类别是“安全靴”。

For an Industrial Leather Glove product, ‘Leather Safety Gloves’ is a macrocategory for which the microcategory is ‘Industrial Leather Gloves’

For a Work Boot product, ‘Safety Boots’ is the macro category and the micro categoryhereis ‘Safety Work Boot’
现在让我们看看图像分类背后使用的概念。如果您想直接跳到实现,请随意跳过' 引擎盖下有什么?--部分技术基础知识。

Predicting the number written inside the image would have become comically trivial to dauntingly difficult for a machine using only its pixel information, without the concept of Machine Learning and Neural Network!
引擎盖下是什么?-技术基础
我们将使用卷积神经网络(CNN) 使用监督学习对产品图像进行分类,并在 PyTorch( 这是一个由脸书开发的人工智能框架)上运行。为此,我们采用了脸书的 ResNet 模型,该模型根据来自 ImageNet 数据库的 100 多万张图像进行了预训练。
什么是预训练模型?
预先训练的模型先前已经在数据集上训练过,并且包含代表它被训练的数据集的特征的权重。学习到的特征通常可以转移到不同的数据中。

什么是深度学习?
深度学习是机器学习的一个子集,它通常有不止一个隐藏层。深度学习最重要的一点是,它可以在有大量(通常是有标签的)数据的地方取得非常好的结果。
在数学中,卷积是对两个函数进行数学运算以产生第三个函数,该函数表示一个函数的形状如何被另一个函数修改。
卷积神经网络 (CNN )是受构成动物大脑的生物神经网络启发的计算系统。这类系统 学习 (逐步提高自己的能力)通过考虑实例来做任务,一般不需要针对任务的编程。例如,他们可能会学习识别包含猫的图像,分析已被手动标记为“猫”或“没有猫”的示例图像,并使用分析结果来识别其他图像中的猫。标记通常采用一组未标记的数据,并用有意义的信息性标记来增加每一段未标记的数据。
残差学习试图解决更深层次的神经网络训练的复杂性及其随深度的饱和精度的问题。
什么是剩余学习?
在一般的 CNN 中,几个层被堆叠起来,并被训练来完成手头的任务。网络在其层的末端学习几个低/中/高级特征。在残差学习中,我们不是试图学习一些特征,而是试图学习一些残差。
残差可以简单理解为学习到的特征减去该层的输入的减法。

Residual Learning: A building block
ResNet 通过将第 n 层的输入直接连接到某个第(n+x)层来实现这一点。使用 ReLU (ReLU 代表整流线性单元,是一种激活功能)。

A ‘Rectified’ Linear Unit substitutes everything dissimilar (negative value) with zero. So by the end, we are left with only a similar looking image.
如果您不确定在您的网络中使用什么激活功能,ReLU 通常是一个不错的首选。为什么?请阅读这篇了解更多 ReLU。
ResNet34 是一个 34 层深度剩余网络。其他型号如 ResNet50、ResNet101 和 ResNet152 也有售。
系统需求
从脸书的 Github 链接下载或克隆 ResNet 模型。
在 Ubuntu 14.04+ 上安装 Torch ResNet 依赖项:
- 在装有 CUDA GPU 的机器上安装焊炬(计算能力为3.5 或以上的 NVIDIA GPU)
 - 安装 cuDNN v4 或 v5 和焊枪 cuDNN 固定器
 
参见安装说明获取分步指南。
我们开始吧!
先决条件:假设对 Python & Linux 命令有一个基本的了解,以便继续学习。
我们如何为自定义数据集采用 RESNET?
数据收集-
了解数据的第一步可以让你达到前所未有的高度,达到预期的预测结果的准确性。我们确定了自定义标签所需的属性,以便与训练好的模型一起使用,并将微类别 ID 、产品 ID、和产品图片的 URL 提取为 tsv(制表符分隔值)格式。
我们把图片从网址下载到一个文件夹结构里,组织成-
标签名称被保存为单独的文件夹名称,每个名称都有其相关的图像。这整个结构被封装到另一个文件夹中,该文件夹应该被命名为' train '。同样,另一个名为“ val ”的文件夹(即包含产品图像的标签名称文件夹)应保存在与“列车”相同的位置。【该文件夹组织标准由脸书给出,是其模型工作所必需的】
在我们的场景中,该结构应该类似于:
train/<Micro_category_ID1>/<Product_ID1.jpg>
train/<Micro_category_ID2>/<Product_ID1.jpg>
val/<Micro_category_ID1>/<Product_ID1.jpg>
val/<Micro_category_ID2>/<Product_ID1.jpg>
为了实现这一点,我们使用了下面的 Linux 命令,该命令应该在终端中的路径“train”处触发:
while read -r mcat_id product_id url; do if [ ! -d "${mcat_id}" ]; then mkdir -p ${mcat_id}; fi; cd $mcat_id; wget -O $product_id $url; cd ..; done < tsvfilename
该命令从 tsv 文件中读取微类别 id、产品 id 和图像 URL,并在相应的微类别文件夹路径中迭代地从 URL 中下载图像,将其重命名为产品 ID(以便于以后识别)。
瞧!我们已经准备好了训练数据。等等……什么?不,它仍然不在那里!
下面是获得想要的结果的最重要的步骤之一。
数据清理-
我们希望准备一个同质的输入数据集,以避免模型在训练时偏向某些微类别 id 的图像,从而总是预测这些微类别。
我们设计了一个 shell 脚本,将所有图像转换成。jpeg(无论是名称还是格式,不包括。png,。gif 等。),删除下载的错误文件,删除重复文件,并将所有图像的尺寸缩小到 224 X 224 px(如果宽度或高度大于 224 px)。
我们选择图像尺寸大小为 224 X 224 px,因为观察到此设置的顶部 1 和顶部 5 误差较小。欲了解更多详情,请查看和。
在 top1 score 中,您检查预测的顶级类别(具有最高概率的类别)是否与目标标签相同。
在 top5 得分的情况下,您检查目标标签是否是您的前 5 个预测之一(具有最高概率的 5 个预测)。
标签加载-
顾名思义,这是一个处理标签上的数据负载的过程,使得每个标签的图像计数达到一个可比较的水*。
为了向模型提供涵盖每天从用户处收到的各种产品图像的数据,我们对现有数据集执行了图像增强。

Here, the input image has been augmented in various forms (by introducing noise and inclination) to increase scarcely available training data set.
下面的 python 脚本用于镜像每张图像,顺时针、逆时针旋转它们,还为每张图像创建了粒状图像。
我们还必须确保一些微类别 id 最终不会比其他微类别 id 具有更大的权重,从而使模型产生偏差,预测不正确的结果。这可能是这样的情况,一些微类别比另一个有更多的列出的产品(有图片)。
例如,在宏观类别“充气家具”中,微观类别“充气沙发”比微观类别“充气沙发”具有更多带有图像的产品。

我们使用了一个 Python 脚本,它将文件夹 train 的微观类别 ID 文件夹中的图像相乘。目前,我们已将倍增系数定为 98 个百分点(即所有单个文件夹的图像计数中的一个图像计数,其中涵盖了总计数的 98%的图像)。
终于可以去训练了!
训练模型-
使用从 Github 下载的文件夹下的 main.lua 文件,即 fb.resnet.torch,用我们自己的数据集训练模型的各层。
th ~/fb.resnet.torch/main.lua -nClasses 122 -nEpochs 100 -data ~/imageclassification/train/ -save ~/Desktop/imageclassification_c122e100b30t4g1 -batchSize 30 -nThreads 4 -nGPU 1
- -nClasses 是我们的标签数量(即微类别 id)
 - -数据是列车文件夹的路径
 - -save 是保存所有模型(即. t7 文件)的文件夹路径(在指定的新文件夹(即~ ~/Desktop/image classification _ c 122 e 100 b 10t 4g 1)中的每个时期结束时会生成一个模型,其中每个模型都在其之前的模型数据之上进行训练。)
 - -batchSize 是每个历元中用于训练的图像数量
 - 
- nEpochs 是我们希望我们的模型运行的迭代次数(我们还在每个时期的末尾获得 top1 和 top5 误差,用于最佳模型的分析)
 
 - -nThreads 是 GPU 使用的线程数
 - 
- nGPU 是我们将用于培训的 GPU 数量
 
 
另一个参数是-深度(此处未使用),因此,默认情况下,我们有一个 ResNet-34 模型。如果它是 50,我们将有一个 ResNet-50 模型。
根据您的便利和资源可用性,在培训时可以使用各种其他参数。可以通过以下方式探索它们:
th main.lua --help
好的!让我们发出命令!
搞定!
根据您的训练数据集大小和系统速度,您应该有耐心并为您的学生提供充足的 时间来学好:)

Training…Training……Training!!!
main.lua 自动在-save 文件夹中并行生成两个额外的模型,即 model_best.t7 和 latest.t7 。
model_best.t7 是在具有最少 top1 和 top5 错误的纪元上创建的模型的副本。
latest.t7 是完全训练的模型,即由最后一个时期创建的模型。
这两种模式并不总是相同的。在我们的例子中,观察到最好的模型是在纪元 99 生成的,但是最新的模型是来自纪元 100 的模型。所以,我们使用了 model_best.t7 进行测试。
测试模型-
classify.lua (在 fb.resnet.torch/pretrained/文件夹中)用于从 model_best.t7 获取所有测试图像的前 5 个预测。
这里需要注意的重要一点是, classify.lua 从 imagenet.lua (在同一个文件夹中,即“pretrained”)中导出预测标签。

所以,我们替换 imagenet.lua 中的旧标签(鸟类、动物等的名称。来自 ImageNet 数据库)与我们自己的标签值,即微类别 id。

The left image shows the original labels in the imagenet.lua file. The micro category ID’s which are used as our labels are being substituted in the same file as shown in the right picture.
现在,让我们测试我们的最佳模型!
我们从“train”中挑选了一些标签,并将其复制到“val”中,以测试我们训练的模型在相同数据上的准确性。
下面的测试命令输出“val”中每个图像的前 5 个预测结果及其预测概率:
for f in ~/imageclassification/val/* ;do ( [ -d $f ] && cd "$f" && echo Entering into $f && th ~/fb.resnet.torch/pretrained/classify_new.lua ~/Desktop/imageclassification_c122e100b30t4g1/model_best.t7 $f/*  >> ~/Desktop/imageclassification_c122e100b30t4g1.txt); done
余波
通过将创建的文本文件转换成 excel 文件进行分析。

The testing file created by running classify.lua
excel 文件将上述预测分成列(使用 R 脚本)用于原始微类别 ID 和产品 ID (来自图像的本地路径)以及预测微类别 1、预测微类别 1 的概率。
通过对预测的和原始的微类别进行匹配检查,我们观察到在 99.28% 的情况下预测为真。这些是训练模型的案例。
后来,我们为添加的 70 个新产品重复了测试活动(因此,被训练的模型没有更早地学习它们)。
在这种情况下,高于覆盖 80%数据的 50%模型置信度(概率)阈值,我们观察到精度为 95.38%。
该模型的精度观察为 1.00 ,灵敏度/召回率观察为 0.95 。该结果的混淆矩阵如下所示:

The matrix shows results for 65/70 cases excluding 5 cases where the user uploaded product image was not clear or was irrelevant for this macro category.
接下来会发生什么…
- 我们也正在分析宏类别级别的预测准确性。
 - 我们打算利用特征提取在不同的微观类别中找到相似的图像。为此,fb.resnet.torch/pretained 文件夹中提供了一个有用的脚本,即 exract-features.lua 。
 - 我们希望利用图像分类来识别*台上被禁止的内容。
 
本系列的后续文章将会重点介绍上述目标的实现。
我希望这篇文章能帮助您扩展关于使用 Resnet 进行定制业务案例的知识,如果您有任何问题或意见,我很乐意听取您的意见。你可以打jain.prachi@indiamart.com找到我
感谢 维克拉姆阿尤什【古普塔】阿苏托什穆凯什 的大力支持。**
使用亚马逊评论数据集的产品推荐器
现实世界中的 DS

有什么问题?为什么我们需要推荐系统?
在线商店的目录中有数百万种产品。由于这种“信息过载”,找到合适的产品变得很困难。用户会感到困惑,这使得用户在选择产品时认知超载。
什么是推荐系统?
推荐系统通过推荐可能的产品列表来帮助客户,他们可以很容易地从中选择合适的产品。它们通过提供可比较的成本、功能、交付时间等,使客户了解可供购买的新产品和/或类似产品。
推荐系统已经成为电子商务网站和其他业务(如社交网络、电影/音乐呈现网站)不可或缺的一部分。它们对这些企业的收入有着巨大的影响,也通过减少搜索和筛选过载数据的认知负荷而使用户受益。推荐系统通过理解用户对系统的使用并推荐他们认为有用的项目来个性化用户体验。
你可能遇到过亚马逊推荐系统的例子,如下所示:

Recommendation based on recently viewed items
推荐系统可以用两种不同的方法构建:基于内容的过滤和协同过滤。
基于内容的过滤
在基于内容的过滤中,不同产品之间的相似性是基于产品的属性来计算的。例如,在基于内容的书籍推荐系统中,书籍之间的相似性是基于流派、书籍的作者、书籍的出版商、书籍的标题等来计算的。
协同过滤
协同过滤通常用于推荐系统。这些技术旨在填充用户-项目关联矩阵的缺失条目。我们将使用协同过滤(CF)方法。
CF 基于这样一个想法,即最好的推荐来自有相似品味的人。换句话说,它使用志同道合者的历史项目评级来预测某人将如何评价某个项目。协同过滤有两个子类别,通常称为基于记忆和基于模型的方法。
基于内存的
有两种方法:第一种方法识别用户群,并利用一个特定用户的交互来预测其他相似用户的交互。第二种方法标识已经被用户 A 评级的项目的聚类,并利用它们来预测用户 A 与不同但相似的项目 b 的交互。这些方法通常遇到大型稀疏矩阵的主要问题,因为用户-项目交互的数量对于生成高质量的聚类来说可能太低。
基于模型的
这些方法基于机器学习和数据挖掘技术。目标是训练模型能够做出预测。例如,我们可以使用现有的用户-项目交互来训练一个模型,以预测用户可能最喜欢的前 5 个项目。这些方法的一个优点是,与基于记忆的方法等其他方法相比,它们能够向大量用户推荐大量项目。它们有很大的覆盖范围,甚至在处理大型稀疏矩阵时也是如此。[10]
矩阵分解
一种非常流行的协同过滤方法是矩阵分解。它有一组用户和一组项目,以及一个非常稀疏的矩阵,表示已知的用户对项目的评级。我们希望预测矩阵中缺失的值。为了做到这一点,我们将每个用户和每个项目表示为潜在特征的向量,使得这些向量的点积紧密匹配已知的用户对项目的评级。期望未知的用户对项目的评级也可以通过相应特征向量的点积来*似。我们希望最小化的目标函数的最简单形式是:

这里,r 是已知的用户对项目的评级,x 和 y 是我们试图找到的用户和项目特征向量。由于有许多自由参数,我们需要正则化部分来防止过拟合和数值问题,gamma 是正则化因子。经过一定次数的迭代后,特征向量的变化变得非常小,并且达到收敛。
交替最小二乘法
交替最小二乘法(ALS)是矩阵分解的方法之一。当有两个因变量(在我们的例子中,向量 x 和 y)时,它用于非线性回归模型。该算法固定其中一个参数(用户向量 x),同时通过最小化二次型来最优地求解另一个参数(项目向量 y)。该算法在固定用户向量和更新项目向量以及固定项目向量和更新用户向量之间交替,直到满足收敛标准。
业界有几种有效且可扩展的矩阵分解实现。其中一个突出的例子是由 Apache Spark 提供的,这是一个分布式数据处理引擎,可以通过 Elastic Mapreduce 集群在亚马逊网络服务上轻松运行。
Apache Spark 实现了一个分布式版本的交替最小二乘法(ALS)和权重正则化。
数据采集和选择
该数据集可在加州大学圣地亚哥分校网站上获得。感谢麦考利教授和他的团队提供了这个数据集。[1][2]该数据集包含亚马逊的产品评论和元数据,包括 1996 年 5 月至 2014 年 7 月期间的 1.428 亿条评论。[1]由于数据的巨大规模,处理所有这些数据是一个相当大的挑战。因此,推荐器是使用 5 个产品类别的数据集构建的,即庭院、草坪和花园、乐器、办公产品、汽车、即时视频。
数据清理
为了使数据具有一致的格式,采取的步骤有:
- 删除不必要的列
 - 删除重复记录
 - 检查无效数据
 - 检查适用列的范围(如等级在 1 到 5 之间)
 - 处理缺失值和异常值
 
探索性数据分析
了解要素及其数据类型并查看数据分布是一种很好的做法。绘制数据可以洞察数据遵循的模式。“庭院、草坪和花园”产品类别数据集用于绘制图表 1 至 6。
1)产品总体评分分布
许多用户给产品打 5 分,然后是 4 分和 3 分,而很少用户给 1 分或 2 分。

2)历年评分的*均值和中值
从下图中,我们可以推断出,从 2000 年到 2014 年,产品的*均评级有所下降。从 2000 年到 2014 年,除了 2010 年和 2011 年,产品评级的中位数保持在 5

3)跨年度评分数量趋势
用户对亚马逊上的产品给出的评级数量呈上升趋势,这表明越来越多的用户开始使用亚马逊电子商务网站进行在线购物,越来越多的用户开始对 2000 年至 2014 年购买的产品给出反馈。从 2012 年到 2014 年,用户给出的评级数量显著增加。

4)每个用户的评级分布
每个用户的收视率分布呈长尾正态分布。花园和庭院数据集中的用户总数是 1685。单个用户给出的最大评分数为 63,单个用户给出的最小评分数为 1。根据目前的数据(截至 2014 年),用户在亚马逊上*均给出 7.55 分。

5)按月评级分布
从下面的方框图中,我们可以说 6 月的收视率最高,其次是 5 月和 7 月。这表明在这三个月里,购买量很大。与此相反,二月显示了用户给出的最低数量的评级,因此可以推断最低销售额可能发生在二月。这是有道理的,因为在夏季,园艺产品的购买量较高。

6)具有特定评级的亚马逊产品的年度统计
下图显示,与评级为“4”和“5”的产品相比,评级为“1”、“2”或“3”的产品数量逐年显著减少。

7)按产品类别划分的亚马逊评分明细
我使用了来自亚马逊评论数据集的 5 个不同数据集来绘制下图,即“汽车”、“花园和庭院”、“乐器”、“办公室”和“即时视频”。总的来说,“办公类”产品和“即时视频”在这 5 个类别中似乎更受欢迎。在所有五个类别中,好的评级数量(4.5)多于坏的评级数量(1.2)。

履行
火花设置
我在一台搭载 32 GB 内存英特尔 i5 处理器的 Windows 10 机器上安装了 Spark。
火花 MLLib
Apache Spark MLlib 提供的 ALS 实现用于该推荐器。MLlib 是 Apache Spark 的可扩展机器学习库。Spark 擅长迭代计算,使 MLlib 能够快速运行。
Apache Spark 实现了一个分布式版本的交替最小二乘法(ALS)和权重正则化。Apache 的 spark.mllib 目前支持基于模型的协同过滤,其中用户和产品由一小组潜在因素描述,这些因素可用于预测缺失的条目。spark.mllib 使用交替最小二乘(ALS) 算法来学习这些潜在因素。[6] [12]
模型选择和超参数
为推荐引擎设置的主要超参数是秩(潜在因素的数量)、λ(正则化参数)和迭代。对于[0.6,0.2,0.2]拆分,等级设置为值[8,10,20],对于数据集中无拆分,等级设置为[ 2,5,10,20]。使用的λ范围从[0.001 到 50]。对于数据集中的无分割,迭代次数在 5 到 20 之间变化,对于数据集中的[0.6,0.2,0.2]分割,迭代次数设置为 20。
我使用了 spark.mllib 中的 ALS 实现,在那里可以设置和测试这些超参数。
模型评估
对于推荐引擎评估,使用不同的指标,如 RMSE、MAE、精确度和召回率。我用 RMSE 进行了模型评估。RMSE 越小,推荐引擎越好。

结果
1)数据集分为训练、测试和验证,训练占 60%,测试占 20%,验证占 20%。除了使用分割,我们还在 8-20 的范围内改变等级超参数。一些重要的观察结果如下:
- 我们一直看到这里评估的所有类别的 RMSE 值都很低。
 - 令人惊讶的是,办公用品类别的 RMSE 为 0,表明预测是完美的(我们检查了数据中的错误或系统问题,如所有空值或相同值,但没有发现任何问题)。
 
我们看到度量对秩超参数非常小或没有敏感性。在更大的范围内搜索这个参数将是一个有趣的下一步。

2)在第二种方法中,我们再次对训练、验证和测试集使用 60–20–20 分割。除了使用分割,我们还在 0.001-50 的范围内改变正则化超参数。一些重要的观察结果如下:
a)对于除“办公产品”类别之外的所有产品类别,将正则化参数设置为 0.001 会给出最佳 RMSE。对于“办公产品”类别,0.5 及以上的正则化参数给出最佳 RMSE。
b)除了在办公产品类别的情况下,我们看到度量对正则化超参数非常小或没有敏感性。

结论
在本文中,我们讨论了使用 Apache PySpark MLLib 构建的亚马逊评论数据集的五个不同产品类别的产品推荐器,并讨论了作为数据科学项目构建推荐器的主要步骤。
后续步骤
我们希望在云中实现这个推荐器。下一步将是为亚马逊评论数据集中剩余的产品类别定制推荐器。这个推荐器利用用户给出的等级。进一步利用用户给出的评论文本会很有意思。
确认
我真诚地感谢我的数据科学导师 Ramakrishna Soma 博士对我完成这个项目的指导和鼓励。
参考
- 
R. He,J. McAuley,沉浮:用一类协同过滤对流行趋势的视觉演变建模, WWW ,2016 pdf
 - 
J. McAuley,C. Targett,J. Shi,A. van den Hengel,基于图像的风格和替代品推荐,2015 年, pdf
 
3)好的、坏的和丑陋的:数据科学工作的 Apache Spark
https://thenewstack . io/the-good-bad-and-ugly-Apache-spark-for-data-science-work/
4)使用 NumPy 和 Pandas 清理 Pythonic 数据
https://realpython.com/python-data-cleaning-numpy-pandas/
5)使用 Python 和 Pandas 清理数据:检测缺失值
6)阿帕奇火花https://spark.apache.org/
7)阿帕奇 PySpark
https://spark . Apache . org/docs/0 . 9 . 1/python-programming-guide . html
8)博瓦迪利亚、奥尔特加、埃尔南多阿。Gutiérrez,基于知识的系统中的推荐系统调查,第 46 卷,2013 年 7 月,第 109–132 页
9)什么是协同过滤?
https://dzone . com/articles/building-sales-recommendation-engine-with-Apache-s
10)夏如华, 推荐者系统 ,一本综合的书
- Greg Linden,Brent Smith,Jeremy York,Amazon.com 建议:项目对项目协作过滤,IEEE 互联网计算,第 7 版第 1 号,第 76-80 页,2003 年 1 月
 
12)阿帕奇火花 ALS
https://spark . Apache . org/docs/2 . 2 . 0/ml-collaborative-filtering . html
13)使用 Pyspark 对 Movielens 数据集进行简单矩阵分解的示例
用 PySpark 在自动气象站电子病历上处理生产数据
使用 AWS CLI 在集群上提交 PySpark 应用程序,分步指南
带有 PySpark 和 AWS EMR 的数据管道是一个多部分系列。这是第二部分。如果你需要 AWS EMR 的入门知识,请查看第 1 部分。
- 在 AWS EMR 上开始使用 PySpark
 - 用 PySpark 在 AWS EMR 上处理生产数据(本文)
 

动机
Apache Spark 在大规模数据处理和分析领域风靡一时,这是有充分理由的。借助 Spark,组织能够从不断增长的数据堆中提取大量价值。正因为如此,能够构建 Spark 应用的数据科学家和工程师受到企业的高度重视。本文将向您展示如何从命令行在 Amazon EMR 集群上运行 Spark 应用程序。
大多数 PySpark 教程都使用 Jupyter 笔记本来演示 Spark 的数据处理和机器学习功能。原因很简单。在集群上工作时,笔记本通过在 UI 中提供快速反馈和显示错误消息,使得测试语法和调试 Spark 应用程序变得更加容易。否则,您将不得不挖掘日志文件来找出哪里出错了——这对于学习来说并不理想。
一旦您确信您的代码可以工作,您可能想要将您的 Spark 应用程序集成到您的系统中。在这里,笔记本就没那么有用了。要按计划运行 PySpark,我们需要将代码从笔记本转移到 Python 脚本中,并将该脚本提交给集群。在本教程中,我将向您展示如何操作。
我们开始吧
一开始,从命令行向集群提交 Spark 应用程序可能会令人生畏。我的目标是揭开这个过程的神秘面纱。本指南将向您展示如何使用 AWS 命令行界面来:
- 创建一个能够处理比本地计算机容量大得多的数据集的集群。
 - 向集群提交 Spark 应用程序,集群读取数据、处理数据并将结果存储在可访问的位置。
 - 该步骤完成后自动终止集群,因此您只需在使用集群时付费。
 
Spark 开发工作流程
当开发 Spark 应用程序来处理数据或运行机器学习模型时,我的首选是从使用 Jupyter 笔记本开始,原因如上所述。这里有一个关于创建一个亚马逊 EMR 集群并用 Jupyter 笔记本连接到它的指南。
一旦我知道我的代码起作用了,我可能想把这个过程作为一个预定的工作来进行。我会把代码放在一个脚本中,这样我就可以用 Cron 或 Apache Airflow 把它放在一个时间表中。
生产火花应用
重要更新:本指南使用 AWS CLI 版本 1 —以下命令需要进行一些调整才能与版本 2 配合使用。
创建您的 AWS 帐户如果您还没有。安装和配置AWS 命令行界面。要配置 AWS CLI,您需要添加您的凭据。您可以按照这些说明创建凭证。您还需要指定您的默认区域。对于本教程,我们使用us-west-2。您可以使用任何您想要的区域。只是要确保所有的资源都使用相同的区域。
定义 Spark 应用程序
对于这个例子,我们将从 S3 加载亚马逊书评数据,执行基本处理,并计算一些聚合。然后,我们将把聚合数据帧写回 S3。
这个例子很简单,但这是 Spark 的一个常见工作流。
- 从源(本例中为 S3)读取数据。
 - 使用 Spark ML 处理数据或执行模型工作流。
 - 将结果写在我们的系统可以访问的地方(在这个例子中是另一个 S3 桶)。
 
如果您还没有,现在就创建一个 S3 存储桶。 确保你创建桶的区域与你在本教程剩余部分使用的区域相同。我将使用地区“美国西部(俄勒冈州)”。 复制下面的文件。确保编辑main()中的output_path来使用你的 S3 桶。然后把pyspark_job.py上传到你的桶里。
# pyspark_job.pyfrom pyspark.sql import SparkSession
from pyspark.sql import functions as Fdef create_spark_session():
    """Create spark session.Returns:
        spark (SparkSession) - spark session connected to AWS EMR
            cluster
    """
    spark = SparkSession \
        .builder \
        .config("spark.jars.packages",
                "org.apache.hadoop:hadoop-aws:2.7.0") \
        .getOrCreate()
    return sparkdef process_book_data(spark, input_path, output_path):
    """Process the book review data and write to S3.Arguments:
        spark (SparkSession) - spark session connected to AWS EMR
            cluster
        input_path (str) - AWS S3 bucket path for source data
        output_path (str) - AWS S3 bucket for writing processed data
    """
    df = spark.read.parquet(input_path)
    # Apply some basic filters and aggregate by product_title.
    book_agg = df.filter(df.verified_purchase == 'Y') \
        .groupBy('product_title') \
        .agg({'star_rating': 'avg', 'review_id': 'count'}) \
        .filter(F.col('count(review_id)') >= 500) \
        .sort(F.desc('avg(star_rating)')) \
        .select(F.col('product_title').alias('book_title'),
                F.col('count(review_id)').alias('review_count'),
                F.col('avg(star_rating)').alias('review_avg_stars'))
    # Save the data to your S3 bucket as a .parquet file.
    book_agg.write.mode('overwrite')\
        .save(output_path)def main():
    spark = create_spark_session()
    input_path = ('s3://amazon-reviews-pds/parquet/' +
                  'product_category=Books/*.parquet')
    output_path = 's3://spark-tutorial-bwl/book-aggregates'
    process_book_data(spark, input_path, output_path)if __name__ == '__main__':
    main()
使用 AWS 命令行界面
是时候创建集群并提交应用程序了。一旦我们的应用程序完成,我们将告诉集群终止。自动终止允许我们仅在需要时才支付资源费用。
根据我们的使用案例,我们可能不想在完成时终止集群。例如,如果您有一个依赖 Spark 来完成数据处理任务的 web 应用程序,那么您可能希望有一个一直运行的专用集群。
运行下面的命令。确保用你自己的文件替换 粗体斜体 部分。关于--ec2-attributes和--bootstrap-actions以及所有其他参数的细节包括在下面。
aws emr create-cluster --name "Spark cluster with step" \
    --release-label emr-5.24.1 \
    --applications Name=Spark \
    --log-uri ***s3://your-bucket/logs/*** \
    --ec2-attributes KeyName=***your-key-pair*** \
    --instance-type m5.xlarge \
    --instance-count 3 \
    --bootstrap-actions Path=***s3://your-bucket/emr_bootstrap.sh*** \
    --steps Type=Spark,Name="Spark job",ActionOnFailure=CONTINUE,Args=[--deploy-mode,cluster,--master,yarn,***s3://your-bucket/pyspark_job.py***] \
    --use-default-roles \
    --auto-terminate
**aws emr create-cluster**重要论据:****
--steps告诉您的集群在集群启动后要做什么。确保将--steps参数中的s3://your-bucket/pyspark_job.py替换为 Spark 应用程序的 S3 路径。您还可以将应用程序代码放在 S3 上,并传递一个 S3 路径。--bootstrap-actions允许您指定要安装在所有集群节点上的软件包。只有当您的应用程序使用非内置 Python 包而不是pyspark时,这一步才是必需的。要使用这样的包,使用下面的例子作为模板创建您的emr_bootstrap.sh文件,并将其添加到您的 S3 桶中。在aws emr create-cluster命令中包含--bootstrap-actions Path=s3://your-bucket/emr_bootstrap.sh。
#!/bin/bash
sudo pip install -U \
    matplotlib \
    pandas \
    spark-nlp
--ec2-attributes允许您指定许多不同的 EC2 属性。使用以下语法设置您的密钥对--ec2-attributes KeyPair=your-key-pair。 注意:这只是你的密钥对的名字,不是文件路径。 你可以在这里了解更多关于创建密钥对文件的信息。--log-uri需要一个 S3 桶来存储你的日志文件。
其他 **aws emr create-cluster** 论据解释:
--name给你正在创建的集群一个标识符。--release-label指定使用哪个版本的 EMR。我推荐使用最新版本。--applications告诉 EMR 您将在集群上使用哪种类型的应用程序。要创建火花簇,使用Name=Spark。--instance-type指定要为集群使用哪种类型的 EC2 实例。--instance-count指定集群中需要多少个实例。--use-default-roles告诉集群使用 EMR 的默认 IAM 角色。如果这是你第一次使用 EMR,你需要运行aws emr create-default-roles才能使用这个命令。如果您已经在配置了 AWS CLI 的区域中的 EMR 上创建了一个集群,那么您应该已经准备好了。--auto-terminate告诉集群在--steps中指定的步骤完成后立即终止。如果您想让您的集群保持运行,请排除此命令—请注意,只要您保持集群运行,您就是在为它付费。
检查 Spark 应用程序的进度
在您执行了aws emr create-cluster命令之后,您应该会得到一个响应:
{
    "ClusterId": "j-xxxxxxxxxx"
}
登录到 AWS 控制台并导航到 EMR 仪表板。您的集群状态应该是“正在启动”。您的集群启动、引导和运行您的应用程序大约需要 10 分钟(如果您使用了我的示例代码)。一旦该步骤完成,您应该会在 S3 存储桶中看到输出数据。
就是这样!
最后的想法
您现在知道了如何创建 Amazon EMR 集群并向其提交 Spark 应用程序。该工作流是使用 Spark 构建生产数据处理应用程序的重要组成部分。我希望您现在对使用所有这些工具更有信心了。
一旦你的工作顺利进行,考虑在亚马逊上建立一个气流环境来安排和监控你的管道。
取得联系
感谢您的阅读!请让我知道你是否喜欢这篇文章,或者你是否有任何批评。如果你觉得这个指南有用,一定要关注我,这样你就不会错过我以后的文章。
如果你在一个数据项目上需要帮助或者想打个招呼,在LinkedIn上联系我。干杯!
使用 Flask 和 Google App Engine 生产您的机器学习模型

这个小教程将帮助你理解一个经过训练的机器学习模型是如何用于生产的。
如今,你可以找到很多学习数据科学和机器学习的教程、MOOCs 和视频。但它们都没有解释当你在 jupyter notebook 或其他 IDE 中的本地系统上训练和优化一个机器学习模型后,你的机器学习模型会发生什么。
在生产环境中,没有人坐在系统前面提供输入并检查您创建的模型的输出。
因此,在本教程中,我们将在 flask 中创建一个简单的 RESTful web 服务,以 API 响应的形式提供我们的机器学习模型输出,然后在谷歌云*台的应用引擎中部署该应用。
设置和要求:
- Python 3.6
 - 文字编辑器
 - 谷歌云*台账户
 - Jupyter 笔记本
 
另外,请安装下面指定的库:
在 Flask 中创建 RESTful API 所需的库
训练一个样本机器学习模型:
我将在波士顿住房数据集上训练一个样本线性回归模型,这两个数据集都可以在 Scikit-learn 库中找到,最后我将使用 Joblib 将训练好的模型保存在一个文件中。
下面是示例 python 代码:
## Importing required Librariesimport pandas as pd
import numpy as np
## for sample dataset
from sklearn.datasets import load_boston
## for splitting data into train and test
from sklearn.model_selection import train_test_split
## LinearRegression model
from sklearn.linear_model import LinearRegression
## For saving trained model as a file
from sklearn.externals import joblib## Getting sample dataset
boston_dataset = load_boston()
boston = pd.DataFrame(boston_dataset.data, columns=boston_dataset.feature_names)
boston['MEDV'] = boston_dataset.target## Preparing variable
X = pd.DataFrame(np.c_[boston['LSTAT'], boston['RM']], columns = ['LSTAT','RM'])
Y = boston['MEDV']## splitting train and test data
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.2, random_state=5)
#print(X_train.shape)
#print(X_test.shape)
#print(Y_train.shape)
#print(Y_test.shape)## Training Model
lin_model = LinearRegression()
lin_model.fit(X_train, Y_train)## Saving trained model
joblib.dump(lin_model, 'test_model')
创建一个简单的烧瓶应用程序:
现在,我们将创建一个简单的 RESTful 应用程序,将我们的模型输出作为 API 响应。我们的应用程序将完成以下任务:

Task flow of our API
下面是 flask 应用程序的代码。你也可以从 GitHub 获得,使用这个链接。
from flask import Flask,request
from flask_restful import Resource,Api
from sklearn.externals import joblib
import pandas as pdapp=Flask(__name__)
api=Api(app)class Test_index(Resource):
    def post(self):
        loaded_model = joblib.load('./model/test_model')
        test_data=request.get_json()
        input_df=pd.DataFrame([test_data])
        input_df.rename(columns={"input_lstat":'LSTAT',"input_rm":'RM'},inplace=True)
        print(input_df)
        y_train_predict = loaded_model.predict(input_df)
        test_output=pd.DataFrame(y_train_predict,columns={'output'})
        output=test_output.to_dict(orient="list")
        return outputapi.add_resource(Test_index,"/test")
if __name__=='__main__':
    app.run(debug=True)
测试我们的应用程序(本地或开发环境):
在编写完我们的应用程序后,我们将在本地或开发环境中进行测试,然后在 Google 云*台中进行生产。
我使用 Gunicorn,一个运行我们应用程序的 WSGI 应用服务器。
只需在终端中打开项目目录并运行以下命令:
$ gunicorn test_flask:app
我们将获得运行我们的应用程序的本地端口的详细信息:

App running in gunicorn server
让我们用 postman 应用程序测试 API 响应。我们将向应用程序端点发出一个 POST 请求,传递一个包含输入参数的 JSON 请求体,如果没有错误,我们将得到一个包含模型预测的 JSON 对象响应。

Testing app response in Postman
在 Google 云*台中将应用部署到生产:
我们测试的应用程序部署在本地系统中。为了使我们的系统可以全球访问,我们需要将它部署在一些服务器上,这些服务器有一个全球 URL 来评估我们的应用程序。
为此,我们将使用谷歌云*台的应用程序引擎。
注意:在接下来的步骤之前,请检查您是否拥有 Google Cloud Platform 帐户,以及您的系统中是否安装了 google cloud SDK。你可以在这里 找到设置 google SDK 的细节。
Google App Engine 需要一个名为“app.yaml”的部署描述符文件,用于在 google cloud 中部署我们的应用程序。
下面是部署描述符 app.yaml 文件的内容:
app.yaml 文件的内容
现在创建一个目录结构,如下所示:

Directory Structure for deploying app in production
最后,在终端中打开同一个目录文件夹,使用 below 命令在 Google cloud 中部署 app。
$ gcloud app deploy --version 1
Google Cloud SDK 将检查适当的权限,然后读取部署描述符文件“app.yaml”并要求确认。键入“Y”。

App deployment in Google app engine
得到确认后,Google cloud SDK 将复制应用程序引擎实例中所有需要的文件,如果没有错误,我们将获得应用程序的全局端点。

Successful deployment in google app engine
在我们的例子中,全局端点 URL 是:https://hadooptest223316.appspot.com
测试我们的应用程序(生产环境):
让我们再次用 postman 应用程序测试我们的 API 响应。我们将向我们的全局端点 URL 发出 POST 请求:

Testing the production app in GCP app engine
我们再次将所需模型的预测作为 API 响应。
结论:
在本文中,我们看到了机器学习模型是如何在生产中使用的。虽然这是一个非常基本的用例。但这将让你对机器学习模型如何在不同应用程序内的云服务器中投入生产有所了解。
我希望你喜欢我的文章,如果你想了解更多关于这个话题的信息,你可以在insta gram或LinkedIn上关注并留言给我。
用 Django API 生产机器学习模型
关于在 Django API 背后部署机器学习模型的教程。

之前,我写过一篇关于用烧瓶制作 ML 模型的教程。
Flask 的重量更轻,但是如果我们需要更多的功能,django 会附带它。
我构建了一个 API,通过 sklearn 模型进行预测。下面是我一步一步的代码。
本教程包含 3 个部分:
1。训练 ML 模型
2。构建 django 应用程序
3。测试 API
第 1 部分:训练 ML 模型
第一部分可以在笔记本上完成。
这不是关于机器学习的教程。所以我们将根据虚构的数据训练一个模型。也就是说,它将像你可以训练的任何其他 sklearn 模型一样工作。
我们的模型将根据动物发出的噪音来检测动物是否是狗。
创造虚构的数据!在每个内部列表中,第一个索引是动物的声音,第二个索引是指示动物是否是狗的布尔标签。
data = [
    ['woof', 1],
    ['bark', 1],
    ['ruff', 1],
    ['bowwow', 1],
    ['roar', 0],
    ['bah', 0],
    ['meow', 0],
    ['ribbit', 0],
    ['moo', 0],
    ['yip', 0],
    ['pika', 0]
]
将上述内容转换为功能和标签列表。
X = []
y = []for i in data:
    X.append( i[0] )
    y.append( i[1] )
安装矢量器并转换要素。
from sklearn.feature_extraction.text import CountVectorizervectorizer = CountVectorizer()
X_vectorized = vectorizer.fit_transform(X)
训练线性回归。
from sklearn.linear_model import LinearRegression
import numpy as npregressor = LinearRegression()
regressor.fit(X_vectorized, y)
现在用几个例子来测试一下。
test_feature = vectorizer.transform(['woof'])
prediction = regressor.predict(test_feature)
print(prediction)test_feature = vectorizer.transform(['ribbit'])
prediction = regressor.predict(test_feature)
print(prediction)test_feature = vectorizer.transform(['meoww'])
prediction = regressor.predict(test_feature)
print(prediction)#=> [1.]
#=> [0.]
#=> [0.36363636]
完美。
将我们的模型打包成字节流,这样我们就可以将它们存储在应用程序中。
import picklepickl = {
    'vectorizer': vectorizer,
    'regressor': regressor
}
pickle.dump( pickl, open( 'models' + ".p", "wb" ) )
第 2 部分:构建 django 应用程序
打开命令行,进入存储 django 项目的目录。为这个应用程序创建一个目录并cd到其中。
mkdir DjangoMLAPI && cd DjangoMLAPI
创建虚拟环境并安装所需的软件包。
python3 -m venv env
source env/bin/activate
pip install django djangorestframework sklearn numpy
现在创建一个 django 项目,这个目录包含了我们正在处理的所有代码。如果我们需要的话,这还包括数据库配置和应用程序设置。
虽然“项目”实际上代表了我们正在构建的应用程序,但是 django 使用术语“app”来指代项目中的包。我们的主包将被称为api。
django-admin startproject api

这生成了一堆支持我们的项目所需的样板代码。它看起来像左边的文件树。
外层的/api只是一个包含我们所有项目代码的文件夹。
内部的/api是我们项目的主要 python 包。
接下来,我们将在项目中生成一个“应用程序”。这将为我们 API 背后的机器学习提供动力。
我们把这个叫做预测器。
cd api
python manage.py startapp predictor

完整的目录现在看起来像左边的文件树。
我们在这里添加了一个名为/predictor的文件夹,里面有很多文件。
我们的用例甚至不需要这些文件中的几个。在本教程的最后,我们将继续删除它们。
apps.py是我们定义配置类的地方。这是只运行一次(而不是每次请求都运行)的代码,所以我们最终会将代码放在那里来加载我们的模型。
将包含在每个请求上运行的代码。所以我们把矢量化和回归逻辑放在那里。
现在让我们将这个应用程序添加到INSTALLED_APPS中。打开/api/api/settings.py,给INSTALLED_APPS添加'predictor'。它应该如下图所示。
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'predictor'
]
现在在/predictor中创建一个名为/models的文件夹。把你训练好的腌渍模型移到这个目录。
请注意,在真实的生产环境中,我会将它从应用程序中分离出来(可能使用 S3),这样我们就不需要在每次更新模型时都重新部署应用程序。但在这里,我们只是将模型包含在应用程序中。
将这一行也添加到设置中。我们将使用它来加载我们的模型。
MODELS = os.path.join(BASE_DIR, 'predictor/models')
现在编写在应用程序启动时加载我们的模型的代码。在/api/predictor/apps.py里面使用这个代码。
from django.apps import AppConfig
from django.conf import settings
import os
import pickleclass PredictorConfig(AppConfig): # create path to models
    path = os.path.join(settings.MODELS, 'models.p')
    # load models into separate variables
    # these will be accessible via this class
    with open(path, 'rb') as pickled:
       data = pickle.load(pickled) regressor = data['regressor']
    vectorizer = data['vectorizer']
现在创建一个支持我们回归逻辑的视图。打开/api/predictor/views.py并用此代码更新。
from django.shortcuts import renderfrom .apps import PredictorConfigfrom django.http import JsonResponse
from rest_framework.views import APIViewclass call_model(APIView):
    def get(self,request):
        if request.method == 'GET': # get sound from request
            sound = request.GET.get('sound')
            # vectorize sound
            vector = PredictorConfig.vectorizer.transform([sound]) # predict based on vector
            prediction = PredictorConfig.regressor.predict(vector)[0] # build response
            response = {'dog': prediction} # return response
            return JsonResponse(response)
设置路由,将 URL 映射到/api/api/urls.py中的视图。
from django.urls import path
from predictor import viewsurlpatterns = [
    path('classify/', views.call_model.as_view())
]
您可以删除以下文件,因为我们不需要它们。
api/predictor/tests.py
api/predictor/models.py
api/predictor/admin.py
第 3 部分:测试 API
现在启动服务器。
python manage.py runserver
并发出几个 curl 请求来测试它。你也可以直接在浏览器中输入网址。
curl -X GET [http://127.0.0.1:8000/classify/?sound=meow](http://127.0.0.1:8000/classify/?sound=meow)
#=> {"dog": 0.0}curl -X GET [http://127.0.0.1:8000/classify/?sound=woof](http://127.0.0.1:8000/classify/?sound=woof)
#=> {"dog": 1.0}
放松点皮兹。起作用了!接*1的数字表示是狗,接*0的数字表示不是狗。
我们找到了。一个 django API,加载并运行一个经过训练的机器学习模型!

                    
                


                
            
        
浙公网安备 33010602011771号