TowardsDataScience-博客中文翻译-2019-六十六-
TowardsDataScience 博客中文翻译 2019(六十六)
TPOT 时间预报

Photo credit: Pixabay
自动化机器学习管道,找到性能最佳的机器学习模型
我的同事向我推荐了几个很棒的机器学习库,其中一些对我来说是新的。因此,我决定一个一个地尝试。今天是轮到 TPOT 的日子。
该数据集是关于预测戴姆勒梅赛德斯-奔驰汽车测试系统速度的工程师,目的是减少汽车花费在测试上的时间,拥有超过 300 个功能。坦白地说,我对汽车行业没有什么专业知识。无论如何,我会尽我所能做出最好的预测,使用 TPOT ,这是一个 Python 自动化机器学习工具,使用遗传编程优化机器学习管道。
数据
这个数据集包含一组匿名的变量,每个变量代表一辆奔驰汽车的定制功能。
目标特性被标记为“y ”,代表汽车通过每个变量测试所用的时间(秒)。数据集可以在这里找到。
train = pd.read_csv('mer_train.csv')
print('Train shape: ', train.shape)

我们知道我们有什么问题:太多的特性(列)和不够的行。

Figure 1
另外,除了“y”和“ID”,我们不知道那些特征是什么。
目标特征
目标特征“y”是汽车通过每个变量测试所用的时间(秒)。我们来看看它的分布。
plt.figure(figsize = (10, 6))
n, bins, patches = plt.hist(train['y'], 50, facecolor='blue', alpha=0.75)
plt.xlabel('y value in seconds')
plt.ylabel('count')
plt.title('Histogram of y value')
plt.show();

Figure 2
train['y'].describe()

Figure 3
plt.figure(figsize = (10, 6))
plt.scatter(range(train.shape[0]), np.sort(train['y'].values))
plt.xlabel('index')
plt.ylabel('y')
plt.title("Time Distribution")
plt.show();

Figure 4
有一个异常值,最大时间为 265 秒。
功能探索
cols = [c for c in train.columns if 'X' in c]
print('Number of features except ID and target feature: {}'.format(len(cols)))
print('Feature types :')
train[cols].dtypes.value_counts()

Figure 5
在所有特征中,我们有 8 个分类特征和 368 个整数特征。特性的基数呢?以下想法和剧本来自米克尔·鲍勃·伊里扎尔。
counts = [[], [], []]
for c in cols:
typ = train[c].dtypes
uniq = len(train[c].unique())
if uniq == 1:
counts[0].append(c)
elif uniq == 2 and typ == np.int64:
counts[1].append(c)
else:
counts[2].append(c)
print('Constant features: {} Binary features: {} Categorical features: {}\n'.format(*[len(c) for c in counts]))
print('Constant features: ', counts[0])
print()
print('Categorical features: ', counts[2])

Figure 6
有 12 个特征只包含一个值(0),这些特征对于监督算法是没有用的,我们稍后将删除它们。
我们数据集的其余部分由 356 个二元特征和 8 个分类特征组成。让我们首先探索分类特征。
分类特征
for cat in ['X0', 'X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X8']:
print("Number of levels in category '{0}': \b {1:2}".format(cat, train[cat].nunique()))

Figure 7
特征 X0
sort_X0 = train.groupby('X0').size()\
.sort_values(ascending=False)\
.index
plt.figure(figsize=(12,6))
sns.countplot(x='X0', data=train, order = sort_X0)
plt.xlabel('X0')
plt.ylabel('Occurances')
plt.title('Feature X0')
sns.despine();

Figure 8
X0 对目标特征 y
sort_y = train.groupby('X0')['y']\
.median()\
.sort_values(ascending=False)\
.index
plt.figure(figsize = (14, 6))
sns.boxplot(y='y', x='X0', data=train, order=sort_y)
ax = plt.gca()
ax.set_xticklabels(ax.get_xticklabels())
plt.title('X0 vs. y value')
plt.show();

Figure 9
特征 X1
sort_X1 = train.groupby('X1').size()\
.sort_values(ascending=False)\
.index
plt.figure(figsize=(12,6))
sns.countplot(x='X1', data=train, order = sort_X1)
plt.xlabel('X1')
plt.ylabel('Occurances')
plt.title('Feature X1')
sns.despine();

Figure 10
X1 对目标特征 y
sort_y = train.groupby('X1')['y']\
.median()\
.sort_values(ascending=False)\
.index
plt.figure(figsize = (10, 6))
sns.boxplot(y='y', x='X1', data=train, order=sort_y)
ax = plt.gca()
ax.set_xticklabels(ax.get_xticklabels())
plt.title('X1 vs. y value')
plt.show();

Figure 11
特写 X2
sort_X2 = train.groupby('X2').size()\
.sort_values(ascending=False)\
.index
plt.figure(figsize=(12,6))
sns.countplot(x='X2', data=train, order = sort_X2)
plt.xlabel('X2')
plt.ylabel('Occurances')
plt.title('Feature X2')
sns.despine();

Figure 12
X2 对目标特征 y
sort_y = train.groupby('X2')['y']\
.median()\
.sort_values(ascending=False)\
.index
plt.figure(figsize = (12, 6))
sns.boxplot(y='y', x='X2', data=train, order=sort_y)
ax = plt.gca()
ax.set_xticklabels(ax.get_xticklabels())
plt.title('X2 vs. y value')
plt.show();

Figure 13
特写 X3
sort_X3 = train.groupby('X3').size()\
.sort_values(ascending=False)\
.index
plt.figure(figsize=(12,6))
sns.countplot(x='X3', data=train, order = sort_X3)
plt.xlabel('X3')
plt.ylabel('Occurances')
plt.title('Feature X3')
sns.despine();

Figure 14
X3 对目标特征 y
sort_y = train.groupby('X3')['y']\
.median()\
.sort_values(ascending=False)\
.index
plt.figure(figsize = (10, 6))
sns.boxplot(y='y', x='X3', data=train, order = sort_y)
ax = plt.gca()
ax.set_xticklabels(ax.get_xticklabels())
plt.title('X3 vs. y value')
plt.show();

Figure 15
功能 X4
sort_X4 = train.groupby('X4').size()\
.sort_values(ascending=False)\
.index
plt.figure(figsize=(12,6))
sns.countplot(x='X4', data=train, order = sort_X4)
plt.xlabel('X4')
plt.ylabel('Occurances')
plt.title('Feature X4')
sns.despine();

Figure 16
X4 对目标特征 y
sort_y = train.groupby('X4')['y']\
.median()\
.sort_values(ascending=False)\
.index
plt.figure(figsize = (10, 6))
sns.boxplot(y='y', x='X4', data=train, order = sort_y)
ax = plt.gca()
ax.set_xticklabels(ax.get_xticklabels())
plt.title('X4 vs. y value')
plt.show();

Figure 17
功能 X5
sort_X5 = train.groupby('X5').size()\
.sort_values(ascending=False)\
.index
plt.figure(figsize=(12,6))
sns.countplot(x='X5', data=train, order = sort_X5)
plt.xlabel('X5')
plt.ylabel('Occurances')
plt.title('Feature X5')
sns.despine();

Figure 18
X5 对目标特征 y
sort_y = train.groupby('X5')['y']\
.median()\
.sort_values(ascending=False)\
.index
plt.figure(figsize = (12, 6))
sns.boxplot(y='y', x='X5', data=train, order=sort_y)
ax = plt.gca()
ax.set_xticklabels(ax.get_xticklabels())
plt.title('X5 vs. y value')
plt.show();

Figure 19
功能 X6
sort_X6 = train.groupby('X6').size()\
.sort_values(ascending=False)\
.index
plt.figure(figsize=(12,6))
sns.countplot(x='X6', data=train, order = sort_X6)
plt.xlabel('X6')
plt.ylabel('Occurances')
plt.title('Feature X6')
sns.despine();

Figure 20
X6 与目标特征 y 的对比
sort_y = train.groupby('X6')['y']\
.median()\
.sort_values(ascending=False)\
.index
plt.figure(figsize = (12, 6))
sns.boxplot(y='y', x='X6', data=train, order=sort_y)
ax = plt.gca()
ax.set_xticklabels(ax.get_xticklabels())
plt.title('X6 vs. y value')
plt.show();

Figure 21
功能 X8
sort_X8 = train.groupby('X8').size()\
.sort_values(ascending=False)\
.index
plt.figure(figsize=(12,6))
sns.countplot(x='X8', data=train, order = sort_X8)
plt.xlabel('X8')
plt.ylabel('Occurances')
plt.title('Feature X8')
sns.despine();

Figure 22
X8 对目标特征 y
sort_y = train.groupby('X8')['y']\
.median()\
.sort_values(ascending=False)\
.index
plt.figure(figsize = (12, 6))
sns.boxplot(y='y', x='X8', data=train, order=sort_y)
ax = plt.gca()
ax.set_xticklabels(ax.get_xticklabels())
plt.title('X8 vs. y value')
plt.show();

Figure 23
遗憾的是,我们并没有从上面的 EDA 中学到太多东西,这就是生活。然而,我们确实注意到一些分类特征对“y”有影响,而“X0”似乎影响最大。
在探索之后,我们现在将使用 Scikit-learn 的 MultiLabelBinarizer 将这些分类特征的级别编码为数字,并将它们视为新特征。
encode_cat.py
然后,我们丢弃已经编码的恒定特征和分类特征,以及我们的目标特征“y”。
train_new = train.drop(['y','X11', 'X93', 'X107', 'X233', 'X235', 'X268', 'X289', 'X290', 'X293', 'X297', 'X330', 'X347', 'X0', 'X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X8'], axis=1)
然后,我们添加编码的特征以形成用于 TPOT 的最终数据集。
train_new = np.hstack((train_new.values, X0_trans, X1_trans, X2_trans, X3_trans, X4_trans, X5_trans, X6_trans, X8_trans))
最终数据集以 numpy 数组的形式出现,形状为 (4209,552)。
TPOT
是时候构建和安装 TPOT 回归器了。完成后,TPOT 将显示“最佳”模型(在我们的例子中,基于测试数据 MSE)超参数,并将管道输出为可执行的 Python 脚本文件,供以后使用或我们的调查。
TPOT_Mercedes_regressor.py

Figure 24
运行上述代码将发现一个管道作为输出,在测试集上实现 56 均方误差(MSE ):
print("TPOT cross-validation MSE")
print(tpot.score(X_test, y_test))

你可能已经注意到 MSE 是一个负数,根据这个线程,TPOTRegressor 的neg_mean_squared_error代表均方误差的负值。让我们再试一次。
from sklearn.metrics import mean_squared_error
print('MSE:')
print(mean_squared_error(y_test, tpot.predict(X_test)))

print('RMSE:')
print(np.sqrt(mean_squared_error(y_test, tpot.predict(X_test))))

所以,我们预测的时间和实际时间之间的差异大约是 7.5 秒。那是一个相当好的结果!而产生这一结果的模型是一个在数据集上符合与 KNeighborsRegressor 算法堆叠的 RandomForestRegressor 的模型。
最后,我们将导出此管道:
tpot.export('tpot_Mercedes_testing_time_pipeline.py')
tpot_Mercedes_testing_time_pipeline.py
我喜欢学习和使用 TPOT,希望你也一样。 Jupyter 笔记本可以在 Github 上找到。周末愉快!
参考: TPOT 教程
R 中的时间智能计算
什么是时间智能?
什么是时间智能?
时间智能只是在日期或时间周期内进行计算。例如,您可能会收到一个常见的请求,即获取一年中按月汇总的总销售额,或者计算产品的 YTD 总销售额和去年同期的销售额,以比较和计算增长。根据我自己的实践经验,我将分享一些在 R 中使用 tidyverse 和 lubridate 包进行这些计算的方法
阅读和准备我们的数据集
在本练习中,我在 Excel 中创建了一个虚拟数据集。该数据集包含从 2017 年 1 月 2 日到 2019 年 9 月 30 日的销售额
library(tidyverse) #Data manipulation
library(lubridate) #For working with date and time sale_data <- read_xlsx("C:\\Users\\ACER\\Desktop\\regression_test.xlsx") %>%
mutate(Date = ymd(Date))
- 使用 read_xlsx 函数读入我们的数据集
- 在 mutate 函数中,我们传递了 ymd 函数来将我们的 Date 列转换为 Date 类型

- 这是我们数据集的样子
一些基本计算
让我们从一些基本的时间智能计算开始。您可能会收到的一个常见请求是显示每月的总销售额
sale_data %>%
group_by(Year=year(Date),Month=month(Date,label = T)) %>%
summarise(total_sales=sum(Offered_Calls,na.rm = T))
- 在 group_by 之后,我创建了年和月列,之后使用summary函数得到 total_sales 。还有另一种方法也是一样
sale_data %>%
group_by(Monthly=floor_date(Date,unit = "1 month")) %>%
summarise(total_sales=sum(Offered_Calls,na.rm = T))
- 基本上,我使用 lubdridate 的 floor_date 函数将日期列四舍五入到最近的月份,然后计算总销售额

Code output
如果有人要求 2019 年 1 月至 6 月的总销售额,并与去年同期进行比较以查看变化,会怎么样?
sale_data %>%
**summarise**(sales_2019 = **sum**(Offered_Calls[Date **%within% interval**("2019-01-01","2019-06-30")],na.rm = T),
sales_2018 = **sum**(Offered_Calls[Date **%within%** **interval**("2018-01-01","2018-06-30")],na.rm = T))
所以基本上我使用了 lubridate 包中的%
更高级的计算
但是,如果您正在处理一个实时数据集呢?您不希望每次运行定期报告时都要更新代码,以考虑最新的日期参数。对此我也有一个很好的解决方案
sale_data %>%
**summarise**(sales_current_mtd = **sum**(Offered_Calls[Date **%within% interval**(**cut**(**Sys.Date()**,"month"),**Sys.Date()**)],na.rm = T),
same_period_last_year = sum(Offered_Calls[Date **%within% interval**(**cut**(**Sys.Date()-years(1),"month"**),**Sys.Date()-years(1)**)],na.rm = T))
这和之前的公式是一样的。唯一的变化是,我将 interval 函数中的日期参数替换为在您运行报告或刷新数据时自动计算所需日期间隔的函数。让我们来分解一下:
- 切割(系统。Date()," month") 将销售日期与最接近的月份相加,这样您将总是得到每个月的第一天
- Sys。Date() 基本上只是获取当前日期。因此,在 interval 函数中输入这两个参数,您将获得从每个月的月初到月末的时间间隔,从而得出 MTD 的总数
- 要获得去年同期的总数,只需添加一个额外的参数。将两个时间间隔的年(-1) 函数相加,将得到相同的时间间隔,但是是去年的时间间隔,从而得到去年 MTD 的总数
我将展示另一个例子,在这个例子中,您必须按年度粒度(如 YTD)进行计算,这将展示这种计算的灵活性
sale_data %>%
**summarise**(sales_ytd = **sum**(Offered_Calls[Date **%within% interval(cut(Sys.Date()**,"year"),**Sys.Date()**)],na.rm = T),
same_period_last_year = **sum**(Offered_Calls[Date **%within% interval(cut(Sys.Date()-years(1)**,"year"),**Sys.Date()-years(1))**],na.rm = T))
- 这里唯一的不同是我在 cut 函数中把参数从“月”改成了“年”。这将日期推至年初。这使我们能够计算当前和去年的 YTD
结论
这些是我在工作中用来在 r 中进行“时间智能”计算的一些解决方案。我展示了用于一次性特别请求的手动过程和用于定期报告的自动解决方案。虽然我的例子只包括每年、每月的计算,但是通过遵循我所展示的相同原则,您可以在任何级别上进行计算,如每周、每天和每季度。我发现这个解决方案对于计算必须在我们的周/月/季度报告中定期更新/报告的 KPI 非常有用。它允许我只刷新报告,而不必每次都手动计算它们。
时间序列分析 1

时间序列数据的分析是任何数据科学家工作不可或缺的一部分,在量化交易领域更是如此。金融数据是时间序列数据中最令人费解的,而且经常看起来不稳定。然而,在这几篇文章中,我将建立一个分析这种时间序列的框架,首先使用成熟的理论,然后深入研究更奇特的现代方法,如机器学习。所以让我们开始吧!
ARIMA 模型
我们要讨论的第一个模型是 ARIMA 模型。它代表自回归综合移动平均模型。是的,有很多需要理解。然而,它本质上只是结合了两个更简单的模型,自回归模型和移动平均模型,这两个模型我们将在下面详细说明。在此之前,我们需要建立平稳性的概念,因为它对于能够准确地建模和预测时间序列至关重要。
平稳性
平稳性的概念来源于随机过程,有时这些随机过程的结果就是白噪声。以下是平稳性的广义定义:
平稳时间序列是其统计特性(如均值和标准差)不依赖于时间的时间序列。
对于那些有统计学和随机学经验的人来说,下面是一个更正式的定义
设{Xt}是一个随机过程,并且

是{Xt}的无条件联合分布的累积分布函数。那么,{Xt}是严格平稳的,当且仅当,

然而,在大多数应用程序中,我们不会使用随机方法手动检查平稳性。我们使用的测试,如迪基-富勒和扩大迪基-富勒测试。
还有一个较弱的平稳性概念,在大多数情况下足以满足。这种弱平稳性被定义为时间序列的期望值和协方差不随时间变化。
自回归模型
自回归模型在概念上很简单:它使用滞后值作为当前/下一时间步的简单线性回归模型的回归量。形式上,它是:

其中:

AR 模型可能类似于普通的最小二乘(OLS)回归,其中先前的时间步长是回归量,当前的 x 值是预测变量。我认为我们应该花一点时间来理解 OLS 回归和 AR 模型之间的区别。考虑下面的 OLS 问题:
您有数据 X 和 Y,并希望找到以下形式的回归公式的 OLS 估计:

OLS 的目标是找到一个最小化误差平方和的β估计值。换句话说,找到的最小值

展开它,对方程求导,我们可以找到驻点,结果是

这是对 OLS 估计的解决办法。然而,将这种方法应用于 AR 模型的关键问题是,数据 X 和 Y 不是在好的矩阵中,并且每次我们处理数据时很难将它们整合到这样的矩阵中。因此,我们使用另一种方法来寻找 AR 模型中滞后变量的系数。在我们研究寻找系数的方法之前,我们先来看看 ARIMA 模型的其他部分。
移动平均模型
移动平均模型考虑了以前的误差项,并使用它来模拟时间序列的当前值。形式上,

MA 模型看起来与 ar 模型非常相似。然而,有几个关键的区别需要注意:
- MA 模型中的误差项直接影响时间序列的当前值,而在 AR 模型中,来自先前时间步长的误差项只是隐含地存在。
- MA 模型中的误差项只影响未来 q 步的时间序列,而 AR 模型中的误差项影响未来无限时间的时间序列。
这种关键的差异给了我们一个自然的扩展模型。这正是 ARMA 模型。ARMA 模型和 ARIMA 模型的区别在于积分。就时间序列而言,整合是指使时间序列成为平稳时间序列所需的差异程度。因此,如果我们有一个时间序列 y,我们把它差 d 倍,并把它叫做 x,我们只需要把上面的两个模型一起应用,就可以得到下面的 ARIMA 模型:

既然我们理解了 ARIMA 模型,我们可以继续探索如何估计系数。
估计系数
有几种方法可以计算模型的系数,我们来看看其中的两种。第一种方法是使用一组称为 Yule-Walker 方程的方程。尤尔-沃克方程源于统计学中的矩方法。我们将首先考虑 AR 模型,因此考虑 AR(p)模型的自协方差:


我们可以将它写成矩阵形式,得到:


现在我们可以用样本自协方差替换总体自协方差来获得系数:


使用相关矩阵也可以得到同样的结果,但我将把它留给读者做练习。
注意:Yule-Walker 方程是线性方程,但是 MA 模型实际上是非线性的,因为前面的误差项不能容易地观察到以形成可以求解的矩阵。
接下来,更常用的估计系数的方法是最大似然估计(MLE)。MLE 是统计分布中估计参数的一种常用方法。MLE 背后的核心原则是最大化可能性的概念(它可以简单地是概率的乘积,但通常是总概率的对数)。关于 MLE 的介绍,请查看我关于 MLE 的另一篇文章。结果表明,如果 ARMA 是高斯型的,则存在 MLE 的解析表示:

最大化这个,我们将获得参数的估计。
选择模型
现在我们已经知道了模型的工作原理和拟合方式,在使用模型时需要做出一个重要的决定:选择参数 p 和 q 的值。p 和 q 的值不仅会极大地影响模型所需的计算能力,还会影响构建模型时使用的信息量。决定这些值的常用方法是考虑一些信息标准,并选择具有最佳信息的参数。换句话说,计算 Akaike 信息标准或贝叶斯信息标准,然后选择最小化信息标准的参数值。
在 Python 中实现
现在我们可以尝试用 python 实现 ARMA 模型。库 statsmodels 已经实现了 ARMA 模型,因此我们将只使用它。下面的代码将产生预测英国 GDP 的 ARMA 模型。
import statsmodels.api as sm
import matplotlib.pyplot as plt
import pandas as pd
import numpy as npdta = pd.read_csv("mgdp.csv", index_col=None)
dta = dta.iloc[:, 1]
res = sm.tsa.ARIMA(dta, (20, 1, 6)).fit()
fig, ax = plt.subplots()
ax = dta.iloc[:].plot(ax=ax)
res.plot_predict(50, 100, dynamic=True, ax=ax,
plot_insample=False)
plt.show()
以下是估计值:

显然,一个简单的 ARIMA 模型不会是最佳的,尤其是当正确的参数没有确定。这只是说明 ARIMA 模型预测能力的一个例子。我鼓励读者尝试使用 statsmodel ARIMA 函数来产生更好的结果。
结论
时间序列分析是一个庞大的课题,有许多分析方法。本文是许多探索时间序列模型的文章中的第一篇。概括地说,我们首先定义了平稳性的概念,然后探讨了 AR 和 MA 模型以及它们是如何形成的。随后,我们深入研究了模型的实际参数是如何确定的,研究了 Yule-Walker 方程和 MLE 估计。最后,我们以预测英国 GDP 增长为例说明了 ARIMA 模型的工作原理
时间序列分析与气候变化

CREDIT: Graphic by the author using Canva and their library
时间序列分析和预测的介绍性实践指南;使用 Python、熊猫和脸书先知库调查气候数据
内容——这篇文章的内容

Contents of this Blog Post (CREDIT: Author on Canva)
为什么是时间序列?
所有的生活场景都被放置在时间的前景中,把她带走,没有一幅我们能理解的画面留下。理解时间本身并不是胆小的人的追求(见这里的和这里的),我们人类很难将时间理解为一个线性概念。
时间序列分析非常有用,主要有两个原因:
- 它让我们能够理解和比较事物,而不会失去重要的、共享的“时间”背景
- 它让我们能够做出预测
时间序列的“组成”
时间序列是对同一现象的一组重复测量,按时间顺序进行;因此,这是一种有趣的数据类型变化——它封装了这种时间背景,以及……呃……任何其他东西。
时间(通常)是时间序列中的独立变量,而因变量是“其他东西”。将一个时间序列想象成由不同的成分组成是很有用的——这被称为 分解建模,并且所得到的模型在本质上可以是加法的或者乘法的。
四个主要组成部分是:
- 趋势
- 季节性
- 周期性
- 不规则

The four main components of a time series (CREDIT: Author on Canva)
趋势
持续时间相对较长的趋势是该时间序列的总体上升或下降。在上图中,我们可以看到这个系列是如何呈现上升趋势的(用两条绿色直线表示)。
季节性
季节性是指以特定的规律间隔出现的变化;它是数据和序列的组成部分,在一段固定的时间内经历有规律的和可预测的变化。季节性如上图所示——请注意以 x 分钟的固定间隔看到的六个相同的“上下”波动。波峰和波谷也可以说明季节性成分。
周期性
周期性是指由环境引起的变化,它以不规则的间隔重复。季节性行为非常有规律,这意味着在数据的波峰和波谷之间有精确的时间间隔;另一方面,周期性行为会随着时间漂移,因为周期之间的时间并不精确。例如,股票市场倾向于在高值和低值之间循环,但是在这些波动之间没有固定的时间量。循环性如上图所示;在这种情况下,周期性似乎是由于每次事件发生前发生的特定事件。
不规则
不规则性是时间序列中不可预测的部分,即“随机性”。这个组成部分不能用任何其他组成部分来解释,它包括由于不可预测的因素而发生的变化,这些因素不会以固定的模式重复出现。上图中;放大镜说明了这种粗糙、随机和不规则的成分。
数据集
提取数据
本教程假设您熟悉 Jupyter 笔记本,并且至少有一些关于熊猫的经验。在这一节中,我们将通过获取一些气候数据,并将其放入我们的大熊猫 Jupyter 笔记本中来开始实践。
我们将使用两个数据集:
*注意:medium 附加到上面的 URL 会导致 NASA 数据出现“访问被拒绝”的错误,要解决这个问题,请将 URL 明确粘贴到浏览器中(https://data.giss.nasa.gov/gistemp/tabledata_v3/GLB.)Ts+dSST.csv )。
*注:为了得到一个更现实的实验,实际上可以做的是随着全球人口的增长,将人均排放量标准化——很想听到这里的任何评论。
首先下载 CSV 格式的数据集(使用上面的链接)并在使用熊猫:
Using Pandas to read in climate data in CSV format
请注意,在这些情况下,当读取数据集时,我们必须跳过几行才能得到我们想要的内容,这是由于数据集的结构。
请注意,上面给出的 CO₂排放数据集的链接下载了一个包含 3 个文件的压缩文件夹,我们使用的是文件“API_EN”。' ATM . co2e . PC _ DS2 _ en _ CSV _ v2 _ 10515380 . CSV '。我已经将两个原始 CSV 移动到它们自己的名为“data”的文件夹中。
让我们来看看我们新获得的数据集:

GISTEMP temperature anomaly data from NASA

CO₂ emissions data, in metric tons per capita, from the World Bank
背景
温度数据代表每个月和每个季节(DJF = 12 月-2 月,MAM =月-5 月等)的温度异常(与平均值/期望值的差异)。我们不会使用绝对温度数据,因为在气候变化研究中,异常比绝对温度更重要。正异常表示观察到的温度比基线温度高,而负异常表示温度比基线温度低。
CO₂给了我们人均 CO₂排放量(公吨)。数据集按国家和其他类别划分,如“世界”或“中上收入”,在本教程中,我们只对“世界”感兴趣,因为我们是在全球范围内观察事物。
有关这两个数据集的更多信息,请参见它们各自的下载页面这里和这里。现在我们有了数据,让我们稍微争论一下以便更容易处理。
争论
“数据争论是将数据从一种“原始”数据形式转换和映射为另一种格式的过程,以便使其对下游流程(如分析)更有价值”
争论不休的温度数据
我们将首先讨论美国宇航局的温度异常数据。在此过程中,我们将关注几个方面:
- 使用日期时间索引
- 基本操作和处理缺失值
- 重新采样到不同的频率
使用日期时间索引:
使用日期时间索引可以让我们在时间序列操作中更有效率;它将允许我们使用时间戳或时间范围进行选择和切片。
对于温度数据,我们将创建一个具有每月频率的日期时间索引的空数据帧,然后我们将使用原始数据来填充这个新的数据帧。空的数据框架将从 1880 年到 2019 年 3 月。
Creating a new Pandas DataFrame to hold the temperature anomaly data using a DateTime index

Resulting empty DataFrame, with DateTime index
好吧。我们有了数据框架,现在需要填充它。这个想法是,每一行将代表该月的异常值——因此我们可以使用“月”的离散索引(或者甚至是“年”的月异常值的平均值)。我选择这样做是因为这是一个关于时间序列分析的教程,我认为这是一个更有用的练习。
基本操作和处理缺失值
为了填充我们的数据框架,我们将基本上遍历我们感兴趣的原始数据的一部分(即年和月列),并将相应的异常值分配给我们的新数据框架。
让我们首先只选择我们想要的数据,为此我们使用 Pandas 的选择功能。我们只需要年列和月列,将省略季节列。
*raw_t = raw_t.iloc[:,:13]
raw_t.head()*

Slice of raw temperature data
我们现在将使用 Pandas 的应用函数来“遍历”原始数据的行(axis=1 表示行,0 表示列)。我们还将使用几个额外的库,即:
Python 的日期时间“库”将会很有用,因为它可以帮助我们解析各种格式的日期和时间(见这里)。日历库用于获取每个月的最后一天。
Using NASA data to populate our DataFrame using DateTime index

Now populated DataFrame
你可能已经注意到,异常值似乎有点乱,它们是字符串和浮点的混合——在(2019)中混合了一些不可用的' *** '值。让我们把它们清理干净。
Cleaning up anomaly values, and dealing with NaNs using Panda’s ‘Foward Fill’

Final temperature DataFrame, after wrangling
太好了!我们已经成功地将 NASA 的温度异常数据转换成了一种很好的、可用的形式。我们将在后面更详细地介绍数据的绘制,但与此同时,您可以使用 Matplotlib 在笔记本中绘制一个简单的图:
Code to plot our temperature anomaly data using Matplotlib

Resulting plot of temperature anomaly data using Matplotlib (CREDIT: Author on Jupyter Notebook)
重采样到不同的频率:
现在这一切都很好,但上面的图看起来有点乱——似乎在这么长的时间内,数据太细了,无法很好地可视化。Pandas 提供了一个非常方便的功能,称为'重采样',它可以将我们的频率从几个月改变为几年(这在以后与 CO₂的数据进行比较时也会有所帮助)。
让我们将温度数据向下采样为年,字符串“A”代表“日历年末”。对于所有的频率字符串,见这里。
*t.resample('A').mean().head()*

Resulting DataFrame after resampling to yearly frequency (end-of-year)
最终的情节更加清晰:
Code to plot resampled temperature anomaly data

Resulting plot of resampled temperature anomaly data (CREDIT: Author on Jupyter Notebook)
好了,我想我们已经把我们的温度数据争论到一个我们能够有效利用它的状态——让我们继续讨论 CO₂的排放数据。
CO₂排放数据的争论
这一部分将解决我们二氧化碳排放数据的争论。我们将使用上面使用的一些相同的技术,并研究一些新的技术:
- 切片和搜索
- 有用的功能
熟悉的技法
在我们的数据框架中,我们将只使用代表全球 CO₂排放量的行。像以前一样,我们将创建一个使用日期时间索引的新数据帧,然后使用原始数据填充它。
Creating a DataFrame — and populating it — with world emissions data

Resulting emissions DataFrame
切片搜索
日期时间索引便于数据切片,让我们选择 2011 年以后的所有数据:
*e[e.index.year>2011]*

Slice of emissions data after the year 2011 (notice the missing data) (CREDIT: Author on Jupyter Notebook)
嗯。在我们数据的末尾似乎有一些 NaN 让我们使用 Panda 的 fillna 方法来处理这个问题。
*e.fillna(method='ffill', inplace=True)
e[e.index.year>2011]*

Slice of emissions data after the year 2011 (no missing data)
好多了!我们还可以利用日期时间索引来搜索特定范围内的值:
*e['1984-01-04':'1990-01-06']*

Resulting slice of emissions data within the specified range
对于更细粒度的基于时间的数据,这种功能开始变得非常有用——在我们的例子中,我们有年,因此范围索引可能已经足够了。
有用的功能
Pandas 提供了一系列其他函数,在处理时间序列数据时非常有用——我们无法在本教程中一一介绍,但下面列出了一些:
- 数据框。滚动 →提供滚动窗口计算
- pandas . to _ datetime→datetime . datetime 的 strptime 函数的替代,它更有用,因为它可以推断格式
- TimSeries。shiftTim series。 tshift →允许时间序列的值在时间上前后移动或滞后
欲了解更多信息和功能,请参见时间序列中的大熊猫页面。
肉眼观察
现在我们已经很好地讨论了数据集,让我们看看如何绘制它们。我们将使用两个绘图库,即:
- Matplotlib
- Plotly
使用 Matplotlib 绘图
Matplotlib 是一个非常流行的 Python 2D 绘图库,可以使用 pip 轻松下载。
让我们使用 Matplotlib 再次绘制我们的温度数据,这一次我们将做得更好——添加轴标签和标题等。:
Code to plot temperature anomalies using Matplotlib

Resulting temperature plot using Matplotlib (CREDIT: Author on Jupyter Notebook)
我们的 CO₂排放数据:
Code to plot emissions using Matplotlib

Resulting emissions plot using Matplotlib (CREDIT: Author on Jupyter Notebook)
用 Plotly 绘图
Plotly 是一个很棒的库,用于生成既交互式又适合网络的图。 Plotly Python 包是一个构建在 plotly.js 上的开源库——后者又构建在 d3.js 上。在本教程中,我们将使用名为袖扣的包装——这使得它很容易与熊猫数据框一起使用。
Importing Plotly and Cufflinks correctly for offline mode
现在我们已经正确导入了库,让我们再次绘制两个数据集,这次使用 Plotly 和袖扣:
Plotting temperature data using Plotly
Plotting emissions data using Plotly
结果图看起来更好,而且是交互式的:

Resulting temperature plot using Plotly (CREDIT: Author on Jupyter Notebook)

Resulting emissions plot using Plotly (CREDIT: Author on Jupyter Notebook)
时间序列相关性
虽然看起来相对明显的是两个系列都呈上升趋势,但我们实际上想做的是确定温度变化是否是 CO₂排放的结果。
格兰杰因果关系
现在,证明因果关系实际上非常困难——仅仅因为两件事是相关的,并不意味着一件事导致另一件事(任何统计学家都会认真地告诉你!).相反,我们要做的是确定 CO₂排放数据在预测温度数据方面有多大帮助;为此,我们将使用格兰杰因果关系测试。
不要被这个名字所迷惑,格兰杰因果关系并不测试真正的因果关系。实际上,称之为格兰杰可预测性或者类似的名称更合适。
总之,这个测试的目的是确定一个时间序列是否有助于预测另一个时间序列。
动态时间扭曲
我们人类已经开发了许多聪明的技术来帮助我们测量时间序列之间的相似性——动态时间弯曲(DTW)就是这样一种技术。DTW 特别擅长的是测量“速度不同”的系列之间的相似性。
例如,引用维基百科:
“即使一个人走得比另一个人快,或者在观察过程中有加速和减速,用 DTW 也能检测出行走的相似性。”
由于这篇博客文章非常长,我决定把格兰杰因果关系和动态时间扭曲的东西分开,放到一篇单独的文章中。
建模和预测
好的,我们可以提取、争论和可视化我们的数据——我们可以做格兰杰因果检验,以确定一个时间序列是否可以用来预测另一个;但是预测呢?
预测很有趣,因为它让我们尝试预测未来。
在这一节中,我们将使用一个库,即脸书的先知库来看预测。
我们还将简要地看一下 ARIMA 模型——尽管为了避免这篇博文变得冗长,我们不会过多地讨论 ARIMA(至少在这篇博文中不会)。
使用脸书的先知进行预测
我们的蓝色霸主——脸书——发布了一个极其强大且用户友好的库,名为“先知”。Prophet 使那些很少或没有经验的人能够预测时间序列,同时提供易于调整的直观参数。该库的工作方式类似于sklearn中的模型——实例化Prophet的一个实例,然后调用fit和predict方法。这对机器学习爱好者来说可能是一股新鲜空气,对我来说确实如此。
创建、拟合并绘制温度模型
我们将首先导入 Prophet,然后创建一个单独的数据帧,我们将以正确的格式将数据复制到该数据帧中——Prophet 采用一个具有两列的数据帧,一列用于日期,一列用于值。日期列必须称为“ds”,而值列必须称为“y”。您可以通过修改原始数据帧来实现这一点,但是我选择了创建一个新的数据帧:
Python code to train a temperature anomaly model using Prophet

Resulting forecast for temperature anomalies (CREDIT: Author on Jupyter Notebook)
这就是我们对未来 100 年全球气温异常的预测!注意那个浅蓝色的区域,它随着我们进一步向未来移动而变宽?这就是预测的不确定性;它随着我们在时间上的进一步前进而增长。
请记住,这种预测只考虑过去的异常数据,不考虑其他因素。在现实中,这可能被证明是有问题的,因为保留的热量实际上可能随着大气中 CO₂的增加而呈指数增加。下图是 NASA 目前对未来不同水平排放的全球地表温度预测(嘿,我们做得还不算太差!).

NASA’s forecast (CREDIT: Nasa forecast)
分解
正如本文开头所述,将时间序列看作由几个部分组成是有用的;幸运的是,Prophet 可以帮助我们将模型分解成这些组件,这样我们就可以直观地看到它们。
我们已经实例化了上面的模型,将模型分割成组件—运行下面的代码:
*# Plot the forecast components
m.plot_components(forecast);*
默认情况下,您将看到时间序列的趋势和年度季节性。如果你包括假期,你也会在这里看到。(使用更精细的数据,也会显示每周的季节性)。

(CREDIT: FB Prophet, and author on Jupyter Notebook)
看部件能看出什么?请在下面留下您的评论。
使用 ARIMA 进行预测
自回归综合移动平均(或 ARIMA)是一种预测技术,能够预测一个序列的未来值。
ARIMA 是更广泛的时间序列模型的一部分,所有这些模型都非常有用,因为它们 提供了一种方法,通过它我们可以对非平稳数据使用线性回归类型的模型。
平稳性基本上意味着您的数据不随时间演变(参见下一节的解释)。线性模型要求平稳性;他们擅长处理和预测平稳数据。
因此,基本的直觉是,我们希望获得一个平稳的时间序列,我们可以对其进行线性回归,而 ARIMA 只是用一些术语“强迫”你的时间序列平稳的线性回归。
由于这篇博文越来越长,我已经决定把自回归综合移动平均建模留到另一天,另一篇博文。现在,请看这篇文章对各种预测方法(包括 ARIMA)的精彩介绍。
一般提示、术语和常见陷阱
条款
自相关
自相关是进行时间序列分析时需要理解的一个重要概念;该术语指的是给定时间序列与其自身在连续时间间隔内的滞后版本之间的相似程度(并且是其数学表示)。将自相关视为时间序列与其自身的相关性,因此有时也称为滞后相关性(或序列相关性)。如果你有兴趣做 ARIMA 模型(见下文),理解自相关是加倍重要的。
乱真关联
在统计学中,虚假相关实际上并不罕见;虚假相关是一种数学关系,其中两个或多个事件或变量相关,但没有因果关系。这可能是由于巧合或第三个看不见的因素(有时称为“共同反应变量”、“混杂因素”或“潜伏变量”)的存在。
平稳性
平稳时间序列是指几个统计属性(即均值、方差和协方差)不随时间变化的序列。这意味着,尽管这些值会随时间而变化,但序列本身随时间变化的方式不会随时间而变化。

Stationary vs. Non-Stationary Time Series (CREDIT: Author on Canva)
关于这方面的更多信息,请看这里的和这里的。我们不会深入探讨平稳性——但是我们会在这篇文章中讨论如何测试平稳性,以及如何让我们的两个序列平稳(为了格兰杰因果关系测试的目的)。
技巧
相关不是因果
在统计领域,相关性并不等于因果关系,这已经成为一个基本原则。这意味着,仅仅因为两件事看起来相互关联,并不意味着一件事会导致另一件事。这是一个值得尽早学习的课程。

Correlation does not have to equal causation (Credit: original)
提防趋势
趋势出现在许多时间序列中,在开始探索两个不同时间序列之间的关系之前,您应该首先尝试测量和控制这种趋势。这样做,你将减少遇到虚假相关性的机会。但是,即使去除时间序列的趋势也不能保护你免受所有虚假相关性的影响——季节性、周期性和自相关性等模式也可以。
注意你如何应对趋势
天真地去趋势化是可能的。如果您正在寻找滞后效应,尝试使用(例如)一阶差分方法实现平稳性可能会破坏您的数据。

Thanks for reading! (CREDIT: Author)
我希望这篇文章对那些刚开始时间序列分析的人有所启发——我真的很喜欢写它,并且学到了很多。
所有的源代码都可以在 Github 上找到。请在下面张贴反馈或问题。
参考
- https://climate.nasa.gov/evidence/
- https://www . svds . com/TBT-避免-常见错误-时间序列-分析/
- https://medium . com/@ shachiakyaagba _ 41915/dynamic-time-warping-with-time-series-1 f 5c 05 FB 8950
- https://www . machinelingplus . com/time-series/time-series-analysis-python/
- https://towards data science . com/basic-time-series-manipulation-with-pandas-4432 afee 64 ea
- https://machine learning mastery . com/time-series-forecasting-methods-in-python-cheat-sheet/
- https://towards data science . com/end-to-end-time-series-analysis-and-modeling-8 c 34 f 09 a 3014
- https://machine learning mastery . com/time-series-data-stationary-python/
- https://www . quora . com/ARIMA 的直观解释是什么
Web 服务度量的时间序列分析和预测
讨论用于分析和预测 Web 服务度量及其应用的各种机器学习技术。
概观
在本文中,我们将 讨论用于分析和预测 web 服务指标的各种机器学习技术及其应用 。 Auto-scaling 就是一个很好的应用,预测技术可以用来估计 web 服务的请求率。类似地,预测技术可以应用于服务指标,以预测警报和异常。
在本文中,我将首先讨论时间序列数据及其在预测技术中的作用。稍后,我将举例说明一个用于预测 web 服务请求率的预测模型。本文提供了对时间序列预测技术的基本理解,这些技术可以应用于服务度量或任何时间序列数据。

开始使用…
什么是时间序列?
时间序列是以恒定的时间间隔收集的数据点的集合。时间序列数据的示例可以从应用程序指标(如 RPM 中的请求率)到系统指标(如以固定时间间隔获取的空闲 CPU 百分比)不等。
为了用机器学习技术解决预测问题,需要将数据转换成时间序列格式。时间序列数据具有自然的时间顺序。时间序列分析可以应用于实值、连续数据、离散数字数据或离散符号数据。
为了说明,我使用了 Python 。 Numpy,Pandas,Matpoltlib 模块用于转换&分析,S tatsmodel 用于预测模型。

Statistics of Request Rate data

Few data points of time series

Time series graph representing request rates (in RPM) for a web service taken at every minute of interval.
预处理数据
查看上面以 RPM 为单位的请求率图表,您是否发现数据存在任何挑战?
在上图中,您可以观察到有太多的数据点和峰值需要处理。
如何处理这个问题?
重采样:所有的数据点都是以一分钟为间隔采集的。每小时、每天或每周重新采样数据有助于减少要处理的数据点数量。在本例中,我们将使用日平均重采样*值。
变换:可以应用对数、平方根或立方根等变换来处理图形中的尖峰。在本例中,我们将对时间序列执行对数转换*。

Observe that large number of data points have reduced and the graph looks smoother as a result of daily resampling.

Observe the values on the y-axis as a result of log transformation
时间序列基本
单变量与多变量时间序列 单变量时间序列数据只包含一个变量。单变量分析是最简单的数据分析形式,其中被分析的数据只包含一个变量。因为它是一个单一的变量,它不处理原因或关系。这种单变量时间序列的一个例子可以是请求速率度量。
当时间序列由两个变量组成时,称为二元时间序列。对这类数据的分析涉及原因和关系,分析的目的是找出两个变量之间的关系。例如,web 服务的 CPU 使用率百分比取决于请求率。为了更好地理解数据,这些变量通常绘制在图表的 X 轴和 Y 轴上,其中一个变量是独立的,而另一个是相关的。
多元时间序列由三个或更多的变量组成。多变量时间序列的例子可以是依赖于多个变量的股票价格。
时间序列的组成部分 为了想出一个适合预测时间序列的模型,了解时间序列数据的组成部分是很重要的。时间序列数据主要由以下部分组成:
- 趋势 趋势显示数据在一段较长时间内增加或减少的总体趋势。趋势是一个平滑的、一般的、长期的、平均的趋势。在给定的时间内,增加或减少并不总是必须在同一方向。对 web 服务的请求率可能会在一段较长的时间内显示出某种类型的移动趋势。
- 季节性 这些是由于季节性因素而在数据中出现的短期变动。短期通常被认为是时间序列发生变化的时期。电子商务网络服务在某些月份可能会收到更多的流量。
- 周期 这些是时间序列中发生的长期振荡。
- 错误 这些是时间序列中的随机或不规则运动。这些是在时间序列中发生的突然变化,不太可能重复。
加法与乘法模型
简单分解模型可以是: 加法模型:Y[t] = T[t] + S[t] + e[t]
乘法模型:Y[t] = T[t] * S[t] * e[t]其中,Y[t]为‘T’时刻的预测值,T[t],S[t]和 e[t]分别为‘T’时刻的趋势分量、季节分量和误差。

Additive Decomposition Model for time series

Multiplicative Decomposition Model for time series
平稳序列
如果时间序列在一段时间内具有恒定的统计特性,即。以下内容:
- 常数平均值
- 恒定方差
- 不依赖于时间的自协方差。
大多数时间序列模型要求时间序列是平稳的。
如何检查时间序列的平稳性?
以下是检查时间序列平稳性的一些方法:
- 滚动统计 我们可以 绘制移动平均值或移动方差 来检查随时间的变化。例如,7 天内每分钟请求的滚动平均值图表。这是一种视觉技术。
- Dickey-Fuller 检验 这是用于检查平稳性的 统计检验 之一。它是 单元根测试 的一种类型。测试结果由测试统计数据和不同置信水平的一些临界值组成。如果“检验统计量”小于“临界值”,我们可以拒绝零假设,说序列是平稳的。这里的零假设是时间序列是非平稳的。

Rolling Stats Plot and AD Fuller Test results for original time series
如何让一个时间序列平稳?
有多种方法可以使时间序列平稳。其中有 求差、去趋势、变换 等。

Rolling Stats Plot and AD Fuller Test results for log transformed and differenced time series.
模型拟合和评估
我大致讲两种预测模型, 数学模型和人工神经网络 。

Predictive Models
数学模型
下面提到一些经典的时间序列预测模型。我将为我们的场景举例说明 SARIMA 模型。
AR、MA、ARMA、ARIMA 等模型都是萨里玛模型的特例。VAR、VARMA、VARMAX 类似于前面提到的模型,它们在向量数据而不是单变量时间序列的情况下很有用。
在某些情况下,Holt-Winter 模型可用于预测带有季节性成分的时间序列。
萨里玛型号
当时间序列中存在趋势和季节性时,非常流行的方法是使用 S 季节自回归综合移动平均(SARIMA) 模型,它是 ARMA 模型的推广。
萨里玛模型由萨里玛(P,D,q) (P,D,Q) [S] 表示,其中
- p,q 指 ARMA 模型的自回归和移动平均项
- d 是差异度(数据减去过去值的次数)
- P、D 和 Q 指的是 ARIMA 模型季节部分的自回归、差分和移动平均项。
- S 指每个季节的周期数
模型参数估计
对于萨里玛 (p,D,q) (P,D,Q)【S】模型,我们需要估计 7 个参数**。*
*从季节分解中我们看到,时间序列数据具有季节性。因此, S = 365 ,表示季节变化有 365 天的滞后。
对于 p,Q,P & Q 参数,我们可以绘制 ACF(自相关函数)& PACF(部分自相关函数)并且对于参数 d & D 我们可以尝试在时间序列中具有差异的相同绘图。***

ACF Plot suggests a possibility of P = 0 and D = 0

ACF Plot suggests a possibility of p ~ 43 and d = 0

PACF Plot suggests a possibility of Q = 0 and D = 0

PACF Plot suggests a possibility of q ~ 7 and d = 0
*估计参数的另一种方法是通过尝试多组值来找到一个模型,对于该模型, AIC ( Akaike 信息准则)值相对较小。
*模型的估计参数是: SARIMA (2,1,4) (0,1,0)【365】
训练和测试数据集拆分
就像其他机器学习模型一样,为了评估模型的准确性,我们将数据集分为训练和测试数据集。这个比例可以从 60%到 90%不等。在我们的例子中,由于数据点的数量较少,我保持 95% 的比率。保持该比率为 95%的另一个原因是,为了使 SARIMA 模型准确预测,训练数据集应该具有足够的 2 个季节的数据点。
Model will be trained with 2 years data and tested with 39 days data.
模型拟合
被拟合的数据是 日均重采样和对数变换的时间序列 。模型调用估计参数 (2,1,4) (0,1,0)【365】。注意到该型号的 AIC 值为-296.90 。
预测
现在模型已经训练好了,我们可以进行预测了。为此,我们可以提供要预测的步数作为参数。

Graph showing Training, Test and Predicted values for Average Daily and Log Transformed RPM values for the service.
注意:观察文章开头的原图 和上面提到的预测图中 y 轴上的数值。web 服务的 RPM 值大约为 300,而预测值大约为 5,这是因为预测值被转换了。我们需要应用逆变换来获得原始刻度上的值。根据我们应用的转换,您能猜出哪个逆转换是合适的吗?****
基于应用的对数变换,我们需要对逆应用指数变换。这在评估预测之前是必需的,因为我们需要知道原始标度上预测值的准确性。**
验证预测
既然我们已经将预测值逆变换回原始比例,我们就可以评估预测模型的准确性了。
*为此我们需要找出原始 & 预测测试值之间的误差来计算:
*均方误差(MSE)
*均方根误差(RMSE)
*变异系数
四分位数离散系数等
由于我们的数据集只有 39 个数据点,我们将能够评估 39 天的预测。让我们评估一下 39 天和 20 天的模型,以比较结果。
39 天预测

Actual and Predicted RPM for 39 days
注意:变异系数为 11.645,这意味着该模型能够以 88%的准确度预测未来 39 天*的服务的日平均转速。*
20 天预测

Actual and Predicted RPM for 20 days
注意:变异系数为 5.55,这意味着该模型能够以 94%的准确率预测未来 20 天的服务日平均转速*。*
神经网络
基于预测的问题的神经网络模型与数学模型的工作方式不同。一个递归神经网络 ( RNN )是一类人工神经网络,表现出时间动态行为。
LSTM【长短期记忆】是最合适的 RNN 。为了发展 LSTM 模型,时间序列预测问题必须重新构造为监督学习问题。
结论
- 为了预测 web 服务的某些度量,如,需要非常高效的模型来预测 实时时间序列数据 。**
- 每个指标都有一个合适的 粒度的时间步长 与之相关联。为了预测响应时间,时间步长的合适粒度应该是秒或分钟。而对于自动缩放,预测每天的 RPM 就足够了。
- 在预测涉及 多变量时间序列 的复杂指标时,如 CPU 使用率%或磁盘交换 ,应选择适当的模型,因为它可能不是单变量时间序列,并且多个变量肯定会影响其值。
- 为预测一个指标而开发的预测模型可能不适合另一个指标。
- 模型 的精度可以通过用更大的数据集训练它和微调模型的参数来提高。
进一步阅读
- 要了解更多关于本文中提到的其他时间序列预测模型,你可以阅读温特-霍尔特和 LSTM 。
- 要理解多变量时间序列的时间序列分析,请阅读格兰杰因果关系测试。
- 对于 ACF 和 PACF 图,请参考自相关和部分自相关。
Python 中从头开始的时间序列分析:第 1 部分
不可否认,时间序列分析在数据科学领域是一件大事,所以我想出了一个主意,创建一个涵盖几乎所有内容的完整系列文章——从基本的日期和时间操作到 LSTMs 和深度学习。

Photo by Lukas Blazek on Unsplash
我并不是说已经没有太多可用的资源,但我更喜欢由一个作者编写学习资源,因为速度和基调在一开始就设定好了,而且更容易理解——前提是你喜欢作者解释事情的方式。
话虽如此,我认为从小处着手从基础做起是个好主意——那就是使用 Python 的日期处理。更准确地说,在本文中,您将学习如何在纯 Python 中处理日期,同时也在 Numpy 和 Pandas 中处理日期。如果你以前做过数据分析,我肯定你对这些库很熟悉。但是如果你没有,那也没关系,这不是火箭科学。
所以,事不宜迟,让我们进入好东西。
用纯 Python 处理日期
要开始,你需要做一个奇怪的导入:

是的,我也不知道为什么要这样设计,但事实就是如此。您现在可以使用 日期时间 模块来创建 日期时间 对象。让我们来看看实际情况。今天是 2019 年 11 月 15 日,所以让我们以某种方式来表示:

注意,如果知道确切的排序,就不需要指定参数名(年、月、日),但是我认为显式总是比隐式好,所以我就这么做。
你还可以更进一步,比如指定小时和分钟:

太酷了。
但是如果我想知道当前的时间呢? 这也是完全容易实现的:

请注意这个 日期时间 对象有以下内容:
- 年份= 2019 年
- 月份= 11
- 天= 15
- 小时= 18
- 分钟= 0
- 秒= 48
- 微秒= 692023
因此,您可以在任何给定时间轻松提取其中任何一个:

这一切都很棒。但是在数据分析的过程中,我也倾向于用 Numpy 和 Pandas 来处理日期。事不宜迟,让我们探索他们的能力。
嗨,我是 Numpy
不先导入 Numpy 库,就不能开始使用它:

好了,现在解决了这个问题,让我展示如何使用 Numpy 来创建一个 datetime 对象的数组:

您看到您需要指定数据类型, Numpy 会自动推断出正确的‘级别’,在本例中是日级别。这是可以改变的,尽管,假设你只对年份感兴趣。您不必排除日和月信息,因为有更简单的方法:

派对不止于此。有时,您可能希望在两个日期之间的特定时间间隔提取日期。酷的是你可以使用 arange() 函数,只是记住你需要指定数据类型:

您还可以做更多的事情,但是目前这已经足够了,至少对于 Numpy 库来说是这样。
以熊猫结束强势
熊猫是一个很棒的图书馆——但是我想你现在已经知道了。话虽如此,我也确信你知道如何导入,但只是为了导入:

现在让我们探索如何从某个开始日期创建一个日期数组。我将在每日频率中创建整个11 月的日期:

好吧,这里没什么特别的,但是让我们看看你能在这里做什么。我将把上面的相同逻辑存储到一个变量中:

酷的是你可以在新创建的变量上使用所有可用的函数。让我们探索其中的几个:

我认为就此打住是个好主意——这足够写一篇文章了。
在你走之前
我知道这对于你们中的一些人来说是基本的东西,但是偶尔回顾一下也没什么坏处。此外,一些更有趣的帖子即将发布,比如日期转换和重采样(可能是下一篇文章的想法),所以如果你对此感兴趣,请继续关注。
感谢阅读,保重。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
* [## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)*
Python 中从头开始的时间序列分析:第 2 部分
这是 Python 中时间序列分析的第二部分,将涵盖比前一部分更有趣的主题。如果您错过了上一篇文章,并且不熟悉 Python 中的日期和时间,您可以在这里找到它。

Photo by Sonja Langford on Unsplash
这一次,我想把重点放在一些更有趣的事情上,你可以用 Python 来处理日期,这些事情包括:
- 重采样
- 改变
因此,如果你还不熟悉你要享受的话题,如果你已经熟悉了,简单回顾一下也无妨。
事不宜迟,我们开始吧。
数据采集
在这篇文章中,我选择使用雅虎财经的一些股票数据。但是在我解释如何获得它之前,让我们先做导入。您将需要 Pandas 库,并且需要设置% matplotlib inlineparam 来查看笔记本中的图表。我不会单独导入 matplotlib ,因为我们将使用熊猫来制作图表。

现在开始收集数据。我选择使用 Google Inc. 股票价格数据集,您可以通过打开此 URL 并点击 下载数据 按钮下载 CSV 格式的数据集。下载完成后,你可以通过 Pandas 导入它,并且只保留相关的列以供进一步分析。
看看我是如何指定 索引 列以及如何将 parse_dates 参数设置为 True 的:

瞧。通过使用 index_col 和 parse_dates 参数,数据集自动处于所需的格式,并准备好进行进一步分析。
让我们快速检查一下索引,看看它是否确实是 日期时间 格式:

一切看起来都很好。我们继续吧。
基本重采样
简而言之,重采样意味着聚合数据的一种方式。这里我用【M’作为重采样规则,代表月,我用 mean 作为聚合函数。这将执行以下操作:
- 获取给定月份的所有价格
- 通过将所有价格的总和除以该月的日期数来计算平均值
让我们来看看它的实际应用:

不过,您并不局限于每月重新采样,以下是可用的最流行的重新采样方法列表:

Source: https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html
我知道这是一个很长的列表,但是它能让你做任何你想做的事情,所以把它放在你身边。
派对并没有就此结束,因为我现在将使用 Pandas 内置的可视化方法来获得月平均股票价格的条形图:

看到了吗? 非常容易做到,而且你不必使用专用的绘图库。
这是对重采样的基本介绍,我将把进一步的探索留给你(一旦你掌握了它的要点,这就不难了)。
时间位移
时间转移基本上意味着从一个时间周期转移到另一个时间周期。让我们回顾一下数据集的样子:

在熊猫 DataFrame 对象上,可以使用 。shift()从一个时间移到另一个时间的方法。让我们来看看实际情况,我将使用这种方法向前移动一段时间:

您可以看到第一个值丢失了,这很明显,因为在第一次观察之前没有关于股票价格的信息。
您也可以通过在整数参数前面加上减号来后退:

如果您想知道这种技术什么时候有用,那么,您可以声明几个列,每个列在过去多移动一天。通过这样做,你可以建立一个模型来预测第二天价格是上涨还是下跌。
在你走之前
这又是对一些基本时间序列方法的简短介绍。我更喜欢这种方式,而不是写一篇你会在一分钟内点击离开的长文章。
过几天,我会写一篇文章介绍 StatsModels 库,稍后会有更多介绍。
感谢阅读。保重。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
SFO 流量增长的时间序列分析

Photo by Ross Parmly on Unsplash
深入分析
未来 4 年 SFO 的增长速度会有多快?
这是我完成的一个机器学习项目的文字记录。在这篇文章中,我将介绍我的项目过程,并展示我们对 SFO 未来的期望。
这个分析的所有代码都可以在my Github上找到。
随着对科技工作者的需求和科技对商业的影响持续增长,旧金山湾区现在是一个热门的居住市场。
我不想分析更传统的衡量湾区需求的方法,如房价,我想看看进出旧金山的交通流量,看看我们如何预计未来 4 年的交通流量增长。
数据清理
首先,我需要清理我的数据。我确保没有空值,使用 matplotlib 可视化我的数据,并修复了数据的其他小问题。
例如,来自 SFGov 的数据使用整数表示年份和月份值(201801 表示“2018 年 1 月”)。这似乎不是一个问题,直到你看到下面一张特定航空公司的航班起飞时间图:

What is that long line?
上图显示了“2018 12”(2018 年 12 月)和“2019 01”(2019 年 1 月)之间的巨大差距。它将这一差距视为时间上的巨大差距,而不是理解为 2019 年 1 月紧接着 2018 年 12 月。
一旦我将 integer 列转换为 datetime,彻底清理我的数据,并将较小的数据点聚合为我想要分析的格式,时间序列数据的完整版本如下:

Much better — time for actual analysis!
通用方法
总的来说,由于我试图预测 SFO 在未来 4 年将会有什么样的流量,我将在我的数据中进行训练/测试分割,测试集为最近 4 年。这样,当我在测试集上测量我的模型的平均绝对误差时,它将代表我的实际未来预测中预期的那种误差。
列车组:05 年到 14 年
测试集:“15 到 19”
1.萨里玛
我使用 SARIMA 作为我的时间序列分析的基线模型。萨里玛只是带有季节性成分的 ARIMA(从上图的视觉效果来看,我的数据显然是这样的)。一个很好的使用 ARIMA 的技术资源可以从杜克大学的网站上获得。
SARIMA 的工作原理是将多个更简单的模型结合在一起:
- S :季节性的(数据有一些整体的季节性模式,为下面的所有组件复制一个额外的术语层)
- AR :自回归(使用以前期间的值来预测未来期间)
- I : Integrated(通过使用至少一阶差分使数据平稳化——我不会在这里深入讨论)
- MA :移动平均线(一种滞后指标,使用过去值的窗口来“平滑”数据。这抵消并缓和了 AR 分量的趋势)
我没有手动摆弄上面的组件,而是编写了自己的网格搜索方法,通过参数找到最低的 AIC 分数。
AIC 平衡拟合优度,同时惩罚模型复杂性以避免过度拟合。返回最低 AIC 的模型给出了模型的拟合和概化的最佳组合。
自相关和部分自相关图(相关图)
找到最低的 AIC 后,有必要抽查我的数据的自相关和偏自相关图,以确保我的模型没有任何可以改进的地方。
自相关图显示了在多个时间滞后时与过去值的相关程度(介于-1 和 1 之间)。部分自相关图显示了与过去残差的相关程度。在高水平上,如果我的任何自相关或部分自相关超过蓝色置信带,这意味着存在统计上显著的相关性,我们仍然可以用不同的 SARIMA 模型来解释。

我们可以看到,在滞后为 0 时,存在完美的+1.0 相关性。这是有意义的,因为滞后为 0 的任何时间点的值只是它本身,并且与它本身完美地相关。我们还看到,在大多数情况下,除了在 2 年和 3 年的标记上有一些轻微的负部分自相关(但奇怪的是,不是 1 年标记),没有任何统计上显著的自相关。这是足够好的考虑这是我们的萨里玛模型的最终版本。
具有最低 AIC 的模型是 SARIMA(1,1,2)(1,1,2,12)。这意味着我的模型最多追溯到 2 年前,以获得预测未来的相关数据。因此,当我对我的 SARIMA 模型评分时,我应该只根据至少有 2 年数据支持的预测来判断它。这就是为什么我的训练预测从 07 年末开始,尽管我的训练数据从 05 年开始。
产生的 SARIMA 低于(蓝色为实际值,橙色为预测值):

你可以看到,我的模型在预测 4 年的测试数据时,开始越来越大幅度地偏离。
平均绝对误差:5.5%
在获得 5.5%的 MAE 后,我对所有数据重新训练了我的 SARIMA,以便预测 2019 年至 2023 年的流量。

My SARIMA estimates growth conservatively
为什么我的模型预测如此保守?你可以在过去两年的真实数据(2017-2019)中看到,增长逐渐减弱。因为 SARIMA 只有 AR 季节成分 1 和 MA 成分 2,所以我的模型最远可以追溯到 2 年前。它将过去两年的趋势延续到未来。
预计增长(超过 4 年):
+3.7%
+26 万人次/年
最后,我使用 Q-Q 图和残差图来确保我的模型在制作模型时不违反任何线性的假设(这些图不包括在本文中,但它们在我的 Github 上的笔记本中)。
2.脸书先知

接下来,我想用脸书先知来进行同样的分析。脸书预言家是脸书团队在 2017 年初发布的一款开源时间序列工具。它在后端做更多的计算工作,以生成比 SARIMA 等更传统的方法更高质量的时间序列分析。例如,Prophet 将寻找多个级别的季节性(每小时、每天、每周)。它还设计用于处理异常值、非线性季节性和节假日,这使它比 SARIMA 更灵活。
FB Prophet 还有一个优点就是好用。一旦你的数据是正确的格式,你可以插入数据,看看你得到什么样的预测。

平均绝对误差:5.4%
我们看到 Prophet 在预测中的表现与我的 SARIMA 模型大致相同——仍然始终低估了随时间的增长。这让我相信 SFO 流量的增长可能会以一种在我的模型的训练数据中意想不到的方式加速。

FB Prophet: Predicted much larger growth than SARIMA
然而,您可以看到,当 Prophet 在所有数据上重新训练时,它的未来预测比 SARIMA 更好地推断了整体趋势。
预计增长(超过 4 年):
+18%
+130 万人次/年
3.神经网络

最后,我想尝试建立一个比萨里玛和 FB Prophet 更好的神经网络。
神经网络是有用的,因为它们可以通过数百次迭代来捕捉隐藏的模式,而这些模式是设计像 SARIMA 这样的参数化方法的人所遗漏的。
然而,我遇到了一个问题。因为神经网络很容易过度拟合,所以我需要手动分离一个验证集,这对于 SARIMA(因为我使用 AIC 分数来确定最佳模型的超参数)或 FB Prophet(因为它运行过一次,并且没有我正在调优的超参数)都是不必要的。
列车组:“05 年至 12 年”
验证集:“13 至 14 年”
测试集:“15 至 19 年”
现在,我们的训练数据离我实际预测的范围越来越远——2019 年至 2023 年。
我也是用小数据操作的。我的新训练集只有大约 80 个数据点来训练(每个月一个点),这比大多数神经网络的有效使用量要小得多。对我的时间序列分析来说,建立精确神经网络的可能性越来越渺茫。
我打算尝试三种不同的神经网络,以便看看哪一种能最有效地处理我的问题。
3 种神经网络
- LSTM(长短期记忆):结合了记忆门来“忘记”可能是旧的数据——对时间序列分析特别有用。对于时间序列分析来说,这是一个老掉牙的好东西,从 90 年代末就有了。
- CNN-LSTM: 在 LSTM 的基础上增加一个卷积神经网络。尽管 CNN 经常用于图像识别,但在时间序列中,它们可以提取模式(季节性的细粒度类型),然后可以滚动到 LSTM 中。
- GRU(门控循环单元):更新的架构,通过将门的数量从 3 个减少到 2 个,简化了 LSTM。适用于小数据。
在训练我的模型时,我确保在每个时期对我的模型在验证集上的表现进行评分,以防止过度适应训练集。
我测试了每种架构,GRU 远远胜过其他的。
对于我的问题,最好的 GRU 模型有 2 个 GRU 层,然后是 3 个大小递减的致密层(没有任何脱落层)。这种架构让我怀疑过度拟合。然而,下面的测试预测图(以及我最终的 2019-2023 预测)足够平滑,让我相信我的模型没有过度拟合。
在拟合我的 GRU 之后,在做预测的时候,我给它 12 个月的数据,让它预测下个月。然后,我会将该预测纳入未来 12 个月的数据滑动窗口,并在此基础上做出预测。这意味着经过 12 个月的预测,我的 GRU 完全是根据合成数据进行预测的。

虽然 GRU 的性能看起来类似于萨里玛和 FB 先知,但实际上它的误差比这两者都低得多。
平均绝对误差:4.6%
这意味着我的神经网络比萨里玛和脸书先知的预测误差少 20%,同时用更少的数据训练,自我预测,防止过度拟合。
当我的 GRU 根据所有可用数据进行重新训练,并根据之前 12 个月的数据进行 1 个月的滚动预测时,它预测到 2023 年的增长如下:

预计增长(超过 4 年):
+22%
+160 万人次/年
这些投影的平滑性让我相信,新训练的神经网络不会在整个数据集上过度拟合,尽管在我的神经网络架构中缺乏脱落层。
结论
总之,由于我的 GRU 神经网络具有最低的平均绝对误差(超过脸书先知和萨里玛约 20%),我们可以对它的未来预测最有信心。
我的 GRU 预测,SFO 每年将增加 160 万次出发,到 2023 年,每年的出发总量将增加 22%。
未来的工作
将来,我会检查每个航空公司从旧金山出发的和到达的之间的差异的季节性模式。然后我就可以知道是否有办法预测某个特定月份哪个航空公司可能有最多的空位。
例如,也许在假日期间,联合航空公司在旧金山的离境乘客通常比抵达乘客多,这表明他们的飞机在离开旧金山的路上将会非常满。但也许捷蓝航空在假日月份有更有利的到达/离开比率,这意味着如果你想最大限度地增加乘坐空飞机的机会,你应该在假日乘坐捷蓝航空旅行。
上述模式可能会随着时间的推移保持不变,也可能会在其他月份发生逆转。然后,我就可以逐月推荐未来乘坐哪家航空公司的飞机,以最大限度地增加空飞机的机会(以便最大限度地增加腿部空间和免费随身行李空间)。
感谢阅读!如果你想了解我的工作,可以随时查看my Github。
使用金融数据的时间序列分析教程

VIX predictions from my ARMA (8,2) time window refitting model
对于我在 Metis 的第二个项目,我创建了一个使用时间序列分析预测 CBOE 波动率指数(VIX)价格的模型。VIX 是热门股票期权价格的综合,它表明了整个市场的波动程度。我还加入了联邦基准利率作为外生数据来源,看看这是否能改善预测。这是一个深入学习如何处理时间序列数据的绝佳机会。看我的项目介绍这里。
这篇文章是学习如何创建你自己的股票时间序列分析的教程。首先,在这里克隆我的代码回购。
本教程将完成以下步骤:
- 探索您的数据
- 检查平稳性
- 使用 ARIMA、萨里马克斯和脸书预言家(3 个流行的时间序列模型)进行模型优化
到本文结束时,您应该有能力将这一过程应用于您认为可能有帮助的任何其他时间序列数据。
探索您的数据
对于这个项目,我们将使用 VIX 指数和联邦优惠利率历史。
weekly_pct, vix_close = clean_data() #custom function to clean data
vix_close.vix_close.plot(figsize=(8,4)); #raw vix close scores

Historical VIX close chart
你可以看到我们有从 1990 年到近 2020 年的数据,在金融危机前后有一个非常大的峰值。如果我们使用 Seaborn 的小提琴图,我们也可以看看每月数据的形状,看看是否有季节性。

您还会想跟随笔记本并尝试。描述()和。info()方法来确保您知道输入的基本最小值和最大值以及一些其他汇总统计数据。这将有助于您稍后尝试进行更改,以便在出现问题时能够及时发现。
检查稳定性
在时间序列分析中要检查的最重要的事情之一是确保你的数据是稳定的。这是一个很重要的术语,你可以在这里详细查找,但要注意的是,你要确保你的数据从头到尾都没有一个整体趋势。每日、每周、每月或每年的趋势都很好,我们的模型可以利用这些来做出更好的预测,但如果数据整体趋势向上,我们就需要修正这一点。对于我们的数据,我们将首先把它转换成百分比变化,然后检查它的平稳性。
#In the clean_data function we convert the data:
vix_close.vix_close = vix_close.vix_close.pct_change()#Then we call the dftest function on our pandas Series:
dftest(weekly_pct.vix_close)

在上表中,我们可以看到 dftest 函数的 p 值低于 0.05。这个函数使用 Dickey-Fuller 测试来确定你的数据是否稳定。小于 0.05 的 p 值允许我们拒绝数据不是静态的零假设,并继续建模。
除此之外,我做了一些数据清理,你可以在笔记本和代码中读到更多。我做的最大的事情包括将原始数据转换成百分比变化格式,并将其转换成两个来源的周数据,以避免周末闭市时的问题。
模型优化
所以现在我们已经准备好为我们的数据建模了!我使用了 StatsModels 的 ARIMA 和 SARIMAX 模型以及流行的脸书先知模型。
我首先看的是自相关和偏自相关图。在时间序列中,我们使用之前的数据点(我们称之为滞后)来预测接下来会发生什么。因此,如果我们只看到 1 个滞后,我们将预测今天与明天有一些加权相关性(例如,回归模型可能会说它会大 0.5(beta 值)+一个误差项)。这些图帮助我们确定什么可能是最重要的滞后。以下是我们 VIX 数据的图表:

首先要注意的是,除了它本身之外,任何一点都没有很强的相关性。滞后从与自身完全相关(1.0)跳到下一个滞后大约为-0.2。
第二件要注意的事情是,两个图是相似的。当左边的自相关图中存在来自多个滞后的持久影响时,部分自相关可以显示差异。这不是我们的数据,它似乎不是高度自相关的。
最后,为了便于理解,请看一下两张图中的蓝色阴影区域。每一个点要么伸出去,要么留在里面。这是一个置信区间,所以当点在阴影区域内或附近时,表示它们可能不值得纳入模型。
为了进一步帮助您理解,让我们简单看一下另一个数据集。看看这些 20 年每月温度数据的图表,可以更清楚地看到自相关数据:

Monthly temperature ACF & PACF plots
在自相关图上,您可以看到 12 和 24 附近的峰值。这些都是每年相同的月份,这与我们拥有的 20 年数据中另一年的温度高度相关。
此处的部分自相关图表明,一旦过滤掉每个中间滞后的影响,当值开始接近阴影区时,真正有更大影响的滞后约为 1–12 左右。
如果你想更深入地了解这一点,请阅读这篇杜克时间序列指南,它提供了更深入的解释。就本教程的目的而言,主要的要点是每年的天气都与前一年相关。VIX 的情况似乎并非如此!
自回归模型
因此,对于我们的建模过程,我们将从最简单的模型开始,AR(1)模型,它只是使用回归模型中的最后一个数据点来预测下一个数据点。我们将把我们的数据分成一个训练集、验证集和测试集(只在最后使用测试集一次)。对于时间序列,我们不能使用 KFolds 或其他更好的交叉验证方法,我们必须确保分割的顺序。
train_vix, train_prime, validation, validation_prime, test = split_data(weekly_pct)
然后,我们将经历正常的 ML 流程:
- 导入 ARIMA 模式
- 用我们的训练数据和参数拟合我们的模型
- 对我们的模型进行评分,看看它与验证数据相比表现如何
这应该和你正在使用的许多其他库一样。你可以看到下面的代码:
from statsmodels.tsa.arima_model import ARIMA #import model
model = ARIMA(train, order=(1,0,0)).fit() #fit training data
preds = model.forecast(52*2)[0] #predict
RMSE(validation,preds) #score
请注意,我预测 104 周,因为我将验证集设置为 2 年,而不是取 20%的数据,以避免过于接近我们在 2008 年看到的疯狂峰值。我还选择了验证集的长度,这是基于我接下来将使用的一种计算量更大的技术。
第一个模型做得不太好,预测 RMSE 为 0.04217,我们看到数据的标准偏差为 0.028008。所以我们最好猜测一下目前为止的平均值。
AR 时间窗口重新调整
我尝试的下一项技术计算量更大。我没有预测接下来的 104 个点,而是决定拟合模型,预测出 1 个点,然后重新拟合,重复这个过程 104 次。你走得越远,你的预测能力就越弱,所以我想这会有所帮助。
这是我制作的一个图形,用来帮助解释这项技术:

Loop and fit one more data point before each prediction to improve model
下面是该函数的代码:
def window_refitting_model(df,p,q):
preds = []
df = list(df)
for i in validation:
model = ARIMA(df, order=(p,0,q)).fit()
pred = model.forecast()[0][0]
preds.append(pred)
df.append(i) plt.plot(validation)
plt.plot(preds)
rmse = RMSE(validation,np.array(preds))
print(rmse)
return rmse,validation,predswindow_refitting_model(train,1,0)
这产生了稍微好一点的分数,RMSE 分数提高了大约 1%。
ARIMA
那么下一步是什么?到目前为止,我只是在 ARIMA 模型中使用了第一个参数(p ),这使它成为一个自回归模型。接下来,我试图为 ARIMA StatsModel 软件包优化我的 p 和 q 分数。p 参数告诉模型要查看多少滞后(以防我的自相关图不正确),q 参数查看大量数据点的移动平均值,这可以通过消除噪声变化来改进模型。
经过一些计算后,我发现 ARMA(8,2)模型(p=8,q = 2)比我的 AR(1)模型稍好,提高了 0.047%。这些改进可能不值得在生产中使用,但考虑到我们使用的艰难的财务数据,我继续使用它们,至少是为了找到最好的模型。
当我在 ARMA(8,2)上使用窗口调整技术时,我现在得到了 0.04117 的 RMSE 和 2.37%的改进。
在我们继续之前,有一点需要注意,我没有尝试 ARIMA 模型的中间参数(差异参数),因为我已经将我的数据转换成了百分比变化。这对其他数据集也尝试优化该参数可能很有用。有关更多信息,请参见文档。
萨里马克斯
SARIMAX 模型的想法是做与 ARIMA 相同的事情,但也增加了使用第二组(p,d,q)参数向模型添加季节维度的能力。如果有大量的滞后预测您的数据,但在不同的时间间隔也有一些自相关(例如,滞后 1-5 和滞后 30-50 真的很重要),这将有所帮助。最后,X 字母代表外源数据,它可以是你认为可以改进模型的任何特征。鉴于我们的数据中缺乏任何季节性指标,我尝试了第二组(p,d,q)参数中的一些参数,但没有看到任何改善。
然后,我继续添加外部数据(我的联邦基准利率数据)并对模型进行评分。
import statsmodels.api as sm
validation_prime_df = pd.DataFrame(validation_prime)
sar = sm.tsa.statespace.SARIMAX(train_vix, exog=train_prime,
order=(1,0,0), seasonal_order=(0,0,0,12), trend='c').fit()
pred = sar.forecast(52*2,exog=validation_prime_df)
RMSE(validation,pred)
你认为优惠利率会有帮助吗?它没有,它与我的基线 AR(1)模型得分相同,RMSE 为 0.04217。
脸书先知
脸书有一个非常受欢迎的时间序列库,我从工业界的朋友那里听说过这个库。虽然 ARIMA 和 SARIMAX 需要大量的超参数调整,但 Prophet 模型在引擎盖下完成了所有这些工作。你必须调整你的数据以适应它们的格式,但这并不需要太多的工作,你可以在回购中的脸书先知 Jupyter 笔记本上看到我所有的代码。他们的库的一个优点是它提供了可视化。虽然我的模型最终表现不如脸书先知(-0.95%),但它确实为这些图表提供了一些可解释性。

Here is a nice graphic of FB’s predictions for my validation dataset
脸书预言家的年度趋势图,显示了我的验证数据集的趋势。

摘要
为了完成我的项目,我创建了一个主要模型和结果的汇总表,以及我的最佳模型的预测与实际验证数据集的图表。

然后,我在我的测试集上对我的最佳模型进行评分(最后只使用一次这个集),并将它作为我的模型中预测误差的指标。我的结论是:我肯定不会用这个模型来交易 VIX!
最后,我确实学到了一些关于金融数据的值得讨论的东西:
- 时间序列分析对于像 VIX 这样高度分析的市场指数是具有挑战性的。
- 我选择联邦最优惠利率是基于它们如何预测市场波动的理论,但对于这种类型的分析来说,它不是一个足够快速的经济指标,而且与固定利率相比变化不频繁,所以对我的模型没有影响。
希望你已经能够在笔记本上学习了,并且学到了很多关于时间序列分析的知识。如果你有任何问题,请不要犹豫,通过 GitHub 或 T2 推特联系我。
利用 LSTM 进行时间序列分析、可视化和预测

Photo credit: Unsplash
统计正态性检验,迪基-富勒平稳性检验,长短期记忆
标题说明了一切。
事不宜迟,我们滚吧!
数据
该数据是一个家庭在近 4 年的时间内以一分钟的采样率测量的电力消耗,可从此处下载。
不同的电量和一些分计量值是可用的。然而,我们只对全局有功功率变量感兴趣。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
pd.set_option('display.float_format', lambda x: '%.4f' % x)
import seaborn as sns
sns.set_context("paper", font_scale=1.3)
sns.set_style('white')
import warnings
warnings.filterwarnings('ignore')
from time import time
import matplotlib.ticker as tkr
from scipy import stats
from statsmodels.tsa.stattools import adfuller
from sklearn import preprocessing
from statsmodels.tsa.stattools import pacf
%matplotlib inlineimport math
import keras
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Dropout
from keras.layers import *
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error
from keras.callbacks import EarlyStoppingdf=pd.read_csv('household_power_consumption.txt', delimiter=';')
print('Number of rows and columns:', df.shape)
df.head(5)

Table 1
需要完成以下数据预处理和特征工程步骤:
- 将日期和时间合并到一列中,并更改为日期时间类型。
- 将 Global_active_power 转换为数字,并删除缺少的值(1.2%)。
- 创建年、季度、月和日功能。
- 创建工作日特征,“0”是周末,“1”是工作日。
df['date_time'] = pd.to_datetime(df['Date'] + ' ' + df['Time'])
df['Global_active_power'] = pd.to_numeric(df['Global_active_power'], errors='coerce')
df = df.dropna(subset=['Global_active_power'])
df['date_time']=pd.to_datetime(df['date_time'])
df['year'] = df['date_time'].apply(lambda x: x.year)
df['quarter'] = df['date_time'].apply(lambda x: x.quarter)
df['month'] = df['date_time'].apply(lambda x: x.month)
df['day'] = df['date_time'].apply(lambda x: x.day)
df=df.loc[:,['date_time','Global_active_power', 'year','quarter','month','day']]
df.sort_values('date_time', inplace=True, ascending=True)
df = df.reset_index(drop=True)
df["weekday"]=df.apply(lambda row: row["date_time"].weekday(),axis=1)
df["weekday"] = (df["weekday"] < 5).astype(int)print('Number of rows and columns after removing missing values:', df.shape)
print('The time series starts from: ', df.date_time.min())
print('The time series ends on: ', df.date_time.max())

去除缺失值后,数据包含 2006 年 12 月至 2010 年 11 月(47 个月)期间收集的 2,049,280 个测量值。
初始数据包含几个变量。这里我们将关注一个单一的值:一所房子的全局有功功率历史,即家庭全局每分钟平均有功功率,单位为千瓦。
统计正态性检验
有几个统计测试,我们可以用来量化我们的数据是否看起来像是来自高斯分布。我们将使用达戈斯蒂诺的 K 检验。
在测试的 SciPy 实现中,我们将 p 值解释如下。
stat, p = stats.normaltest(df.Global_active_power)
print('Statistics=%.3f, p=%.3f' % (stat, p))
alpha = 0.05
if p > alpha:
print('Data looks Gaussian (fail to reject H0)')
else:
print('Data does not look Gaussian (reject H0)')

:描述一个分布的尾部的沉重程度
*sns.distplot(df.Global_active_power);
print( 'Kurtosis of normal distribution: {}'.format(stats.kurtosis(df.Global_active_power)))
print( 'Skewness of normal distribution: {}'.format(stats.skew(df.Global_active_power)))*

Figure 1
正态分布的峰度接近于 0。如果峰度大于零,那么分布有较重的尾部。如果峰度小于零,则分布为轻尾。我们的峰度大于零。
偏斜度 :测量分布的不对称性
如果偏斜度在-0.5 到 0.5 之间,则数据相当对称。如果偏斜度介于-1 和-0.5 之间或介于 0.5 和 1 之间,则数据是中度偏斜的。如果偏斜度小于-1 或大于 1,则数据高度偏斜。我们的偏斜度大于 1。
第一时间序列图
显然,这个情节不是一个好主意。不要这样。
*df1=df.loc[:,['date_time','Global_active_power']]
df1.set_index('date_time',inplace=True)
df1.plot(figsize=(12,5))
plt.ylabel('Global active power')
plt.legend().set_visible(False)
plt.tight_layout()
plt.title('Global Active Power Time Series')
sns.despine(top=True)
plt.show();*

Figure 2
全球年度与季度有功功率的箱线图
当我们并排比较每年的箱线图时,我们注意到 2006 年的全球有功功率中值比其他年份高得多。这有点误导。如果你记得的话,我们只有 2006 年 12 月的数据。而 12 月显然是家庭电力消耗的高峰月。
*plt.figure(figsize=(14,5))
plt.subplot(1,2,1)
plt.subplots_adjust(wspace=0.2)
sns.boxplot(x="year", y="Global_active_power", data=df)
plt.xlabel('year')
plt.title('Box plot of Yearly Global Active Power')
sns.despine(left=True)
plt.tight_layout()plt.subplot(1,2,2)
sns.boxplot(x="quarter", y="Global_active_power", data=df)
plt.xlabel('quarter')
plt.title('Box plot of Quarterly Global Active Power')
sns.despine(left=True)
plt.tight_layout();*

Figure 3
这与季度全球有功功率中值一致,第 1 和第 4 季度(冬季)较高,第 3 季度(夏季)最低。
全球有功功率分配
正态概率图也显示数据远非正态分布。
*plt.figure(figsize=(14,6))
plt.subplot(1,2,1)
df['Global_active_power'].hist(bins=50)
plt.title('Global Active Power Distribution')plt.subplot(1,2,2)
stats.probplot(df['Global_active_power'], plot=plt);
df1.describe().T*

Figure 4
日、周、月、季度和年的平均全球有功功率重新采样
总的来说,我们的时间序列没有上升或下降的趋势。最高的平均功耗似乎是在 2007 年之前,实际上是因为我们只有 2007 年 12 月的数据,而那个月是高功耗月。换句话说,如果逐年比较,一直是平稳的。
timeseries_plot.py





Figure 5
按年、季度、月和日分组的全球平均有功功率图
以上情节证实了我们之前的发现。到了 2008 年,情况稳定了下来。按季度来看,平均功耗最低的是第三季度。按月份来看,平均用电量最低的是 7 月和 8 月。白天,平均功耗最低的时候是在 8 号左右(不知道为什么)。
grouped_plot.py

Figure 6
按年份划分的全球有功功率
这一次,我们去掉 2006。
从 2007 年到 2010 年,每年的情况都差不多。
*pd.pivot_table(df.loc[df['year'] != 2006], values = "Global_active_power",
columns = "year", index = "month").plot(subplots = True, figsize=(12, 12), layout=(3, 5), sharey=True);*

Figure 7
工作日与周末的全球有功功耗
2010 年之前,工作日的全球有功功率中值似乎低于周末。2010 年,他们是一模一样的。
*dic={0:'Weekend',1:'Weekday'}
df['Day'] = df.weekday.map(dic)a=plt.figure(figsize=(9,4))
plt1=sns.boxplot('year','Global_active_power',hue='Day',width=0.6,fliersize=3,
data=df)
a.legend(loc='upper center', bbox_to_anchor=(0.5, 1.00), shadow=True, ncol=2)
sns.despine(left=True, bottom=True)
plt.xlabel('')
plt.tight_layout()
plt.legend().set_visible(False);*

Figure 8
按工作日与周末划分的全球有功功率因数图
工作日和周末全年都遵循类似的模式。
*plt1=sns.factorplot('year','Global_active_power',hue='Day',
data=df, size=4, aspect=1.5, legend=False)
plt.title('Factor Plot of Global active power by Weekend/Weekday')
plt.tight_layout()
sns.despine(left=True, bottom=True)
plt.legend(loc='upper right');*

Figure 9
原则上,当我们使用时,我们不需要检查 的平稳性 也不需要对其进行校正。但是,如果数据是静态的,这将有助于提高性能,并使神经网络更容易学习。**
平稳性
在统计学中, 迪基-富勒检验 检验自回归模型中存在单位根的零假设。备选假设根据使用的测试版本而不同,但通常是平稳性或趋势平稳性。
平稳序列在一段时间内具有恒定的均值和方差。时间序列的滚动平均值和滚动标准差不随时间变化。
迪基-富勒试验
【H0】:暗示时间序列有单位根,意味着它是非平稳的。它有一些依赖于时间的结构。
交替假设【H1】:暗示时间序列没有单位根,意味着它是平稳的。它没有依赖于时间的结构。
p 值> 0.05:接受零假设(H0),数据有单位根,非平稳。
p 值< = 0.05:拒绝零假设(H0),数据没有单位根,是平稳的。
从上述结果,我们将拒绝零假设 H0,数据没有单位根,是平稳的。
stationarity.py

Figure 10
LSTM
这里的任务是预测一个时间序列的值,给定一个家庭 200 万分钟的电力消耗历史。我们将使用多层 LSTM 递归神经网络来预测值序列的最后一个值。
如果您想要减少计算时间,并且还想快速获得测试模型的结果,您可能想要在一个小时内对数据进行重新采样。我会把它记录下来。
在构建 LSTM 模型之前,需要进行以下数据预处理和特征工程。
创建数据集,确保所有数据都是浮动的。
- 将特征标准化。
- 分为训练集和测试集。
- 将值数组转换为数据集矩阵。
- 重塑成 X=t,Y=t+1。
- 将输入整形为 3D(样本数,时间步长数,要素数)。
- 模型架构
lstm_data_preprocessing.py
定义 LSTM,第一个隐层 100 个神经元,输出层 1 个神经元,用于预测全局有功功率。输入形状将是具有 30 个特征的 1 个时间步长。
- 退学 20%。
- 使用 MSE 损失函数和有效的随机梯度下降的 Adam 版本。
- 该模型将适合 20 个训练时期,批量大小为 70。
- 做预测
lstm_timeseries.py
绘图模型损失
**train_predict = model.predict(X_train)
test_predict = model.predict(X_test)
# invert predictions
train_predict = scaler.inverse_transform(train_predict)
Y_train = scaler.inverse_transform([Y_train])
test_predict = scaler.inverse_transform(test_predict)
Y_test = scaler.inverse_transform([Y_test])print('Train Mean Absolute Error:', mean_absolute_error(Y_train[0], train_predict[:,0]))
print('Train Root Mean Squared Error:',np.sqrt(mean_squared_error(Y_train[0], train_predict[:,0])))
print('Test Mean Absolute Error:', mean_absolute_error(Y_test[0], test_predict[:,0]))
print('Test Root Mean Squared Error:',np.sqrt(mean_squared_error(Y_test[0], test_predict[:,0])))**

比较实际与预测
**plt.figure(figsize=(8,4))
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Test Loss')
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epochs')
plt.legend(loc='upper right')
plt.show();**

Figure 11
对我来说,每一个时间步都是一分钟。如果您提前一个多小时重新采样数据,那么每个时间步长就是一个小时。
我将比较过去 200 分钟的实际和预测。
LSTMs 太神奇了!
**aa=[x for x in range(200)]
plt.figure(figsize=(8,4))
plt.plot(aa, Y_test[0][:200], marker='.', label="actual")
plt.plot(aa, test_predict[:,0][:200], 'r', label="prediction")
# plt.tick_params(left=False, labelleft=True) #remove ticks
plt.tight_layout()
sns.despine(top=True)
plt.subplots_adjust(left=0.07)
plt.ylabel('Global_active_power', size=15)
plt.xlabel('Time step', size=15)
plt.legend(fontsize=15)
plt.show();**

Figure 12
Jupyter 笔记本可以在 Github 上找到。享受这周剩下的时光吧!
参考:
Keras 中 LSTMs 的多元时间序列预测
** [## 像长短期记忆(LSTM)循环神经网络这样的神经网络能够几乎无缝地模拟…
machinelearningmastery.com
machinelearningmastery.com](https://machinelearningmastery.com/multivariate-time-series-forecasting-lstms-keras/)**
深度学习时间序列分析:简化
参加在时间序列分析中使用深度学习的“为什么”和“什么时候”的速成班。
什么是时间序列分析?
时间序列是使用时间戳排序的数据点序列。时间序列分析是..你猜对了..时间序列数据分析:P

从你喜欢的水果的每日价格到电路提供的电压输出读数,时间序列的范围是巨大的,时间序列分析的领域也是如此。分析时间序列数据通常集中在预测,但也可以包括分类、聚类、异常检测等。例如,通过研究过去价格变化的模式,你可以试着预测你关注已久的手表的价格,以判断什么是购买它的最佳时机!!
为什么要深度学习?
时间序列数据可能非常不稳定和复杂。深度学习方法对数据中的潜在模式不做任何假设,并且对噪声(这在时间序列数据中很常见)也更加鲁棒,使它们成为时间序列分析的首选。
数据处理
在我们继续预测之前,首先以数学模型可以理解的形式处理我们的数据是很重要的。通过使用滑动窗口来切割数据点,可以将时间序列数据转化为监督学习问题。每个滑动窗口的期望输出是窗口结束后的时间步长。

循环网络
递归网络是深度学习网络,有一个转折……它们可以记住过去,因此是序列处理的首选。RNN 细胞是循环网络的骨干。RNN 单元有 2 个输入连接,输入和先前的状态。类似地,它们也有 2 个输出连接,即输出和当前状态。这种状态帮助他们组合来自过去和当前输入的信息。

一个简单的 RNN 单元过于简单,不能统一用于不同领域的时间序列分析。因此,多年来已经提出了大量的变体来使递归网络适应各种领域,但是核心思想仍然是相同的!!
RNNs 上的 LSTMs
LSTM 单元是一种特殊的 RNN 单元,其中有门,本质上是 0 和 1 之间的值,对应于状态输入。这些门背后的直觉是忘记或保留过去的信息,这让他们记住的不仅仅是眼前的过去。没有人能比 Colah 的博客更好地解释 LSTMs,所以如果你还没有去过,就去看看吧。
*[## 了解 LSTM 网络
2015 年 8 月 27 日发布人类不是每秒钟都从零开始思考。当你读这篇文章时,你…
colah.github.io](https://colah.github.io/posts/2015-08-Understanding-LSTMs/)* 
Complex internal architecture of an LSTM cell. GRU is another variation of gated RNN cells.
美国有线电视新闻网
我们讨论过,由于状态信息通过每个时间步传播,rnn 只能记住最近的过去。另一方面,像 LSTMs 和 GRUs 这样的门控网络可以处理相对较长的序列,**但即使这些网络也有其局限性!!为了更好地理解这个问题,我们也可以看看消失和爆炸渐变。**

那么如何处理非常长的序列呢??显而易见的解决方案是缩短它们!!!但是如何?一种方法是丢弃信号中存在的细粒度时间信息。这可以通过将小组数据点累积在一起并从中创建特征来实现,然后将这些特征传递给 LSTM,就像一个单独的数据点,。

多尺度分层 LSTMs
看着 CNN-LSTM 的架构,我想到了一件事…为什么要用 CNN 来组合那些小团体??为什么不使用不同的 LSTM 呢!!!多尺度分级 LSTMs 基于相同的理念。

输入在多个尺度上被处理,每个尺度都致力于做一些独特的事情。对更细粒度的输入起作用的较低等级关注于传递细粒度的(但仅仅是最近的)时间信息。另一方面,上层关注于提供完整的图片(但是没有细粒度的细节)。多种尺度结合在一起可以更好地理解时间序列。
下一步是什么?
时间序列分析是一个非常古老的领域,包含各种跨学科的问题陈述,每一个都有自己的挑战。然而,尽管每个领域都根据自己的需求调整模型,但在时间序列分析中仍然有一些需要改进的一般研究方向。例如,从非常基本的 RNN 单元到多尺度分级 LSTM 的每个发展都在某种程度上关注于处理更长的序列,但是即使是最新的 LSTM 修改也有其自身的序列长度限制,并且我们仍然没有能够真正处理超长序列的架构。
这个博客是努力创建机器学习领域的简化介绍的一部分。点击此处的完整系列
在你一头扎进去之前就知道了
towardsdatascience.com](/machine-learning-simplified-1fe22fec0fac)
或者只是阅读本系列的下一篇博客
让我们来看看计算机视觉中最著名的问题陈述之一
towardsdatascience.com](/object-detection-simplified-e07aa3830954)
参考
[1]程,闵,等.“MS-LSTM:一种用于 BGP 异常检测的多尺度 LSTM 模型”2016 IEEE 第 24 届国际网络协议大会(ICNP)。IEEE,2016。
[2]阿拉亚、伊格纳西奥·阿、卡洛斯·瓦莱和埃克托尔·阿连德。"基于 LSTM 的多尺度风速预报模式."伊比利亚美洲模式识别大会。施普林格,查姆,2018。
[3] Hochreiter,Sepp,和 Jürgen Schmidhuber。“长短期记忆。”神经计算 9.8(1997):1735–1780。
[4]沃索基、索罗什、普拉尚·维贾亚拉哈万、德布·罗伊。" Tweet2vec:使用字符级 cnn-lstm 编码器-解码器学习 Tweet 嵌入."第 39 届国际 ACM SIGIR 信息检索研究与发展会议录。ACM,2016。
[5]帕斯卡努,拉兹万,托马斯·米科洛夫,约舒阿·本吉奥。"关于训练递归神经网络的难度."机器学习国际会议。2013.*
使用 Python 实现时间序列和与股票市场数据的相关性
我最近在金融数据服务公司 IEX 云上开了一个账户。由于我一直在学习这种新数据源(对我来说是新的)的特性,并在我的 Jupyter 笔记本上进行试验,我认为下面的内容可能对其他人也有帮助。因此,我正在创建我的第一篇媒体文章,并将它集中在金融时间序列数据上。
关于定义相关性以及相关性和因果关系之间的区别,有相当多的文章和资料来源;因此,下面你会发现,将主要显示一些方法来测试相关性和结果意味着什么。如果你想使用 IEX 云,如果你想用 Python 做相关性测试,如果你对时间序列数据感兴趣,你会发现这篇文章很有帮助!
如果你正在遵循这个并且自己编码,去 https://iexcloud.io/给自己弄一个 API 密匙!接下来你会需要它的!此外,不要忘记安装一个 IEX Python 库:【https://addisonlynch.github.io/iexfinance/】(林奇,2019)。使用以下方式安装此库:
$ pip3 安装 iexfinance
**import** **config**
**import** **os***#os.environ['IEX_API_VERSION'] = "iexcloud-sandbox"*
os.environ['IEX_TOKEN'] = config.iex_api_key *# Replace "config.iex_api_key" with your API Key from IEX Cloud!*
我们将加载一些我们接下来需要的库。此外,我们将使用 2017 年 1 月 1 日至 2019 年 11 月 22 日之间的数据。
**from** **datetime** **import** datetime
**from** **iexfinance.stocks** **import** get_historical_data
**import** **matplotlib.pyplot** **as** **plt**
%matplotlib inlinestart = datetime(2017, 1, 1)
end = datetime(2019, 11, 22)
为了简单起见,我们将任意选择‘close’。从这个 API 数据响应中,您还可以选择开盘价、最高价、最低价和成交量。我们将尝试使用“close”
现在,让我们进行一个 API 调用并下载更多数据,“SPDR 标准普尔 500 信托 ETF”,它跟踪标准普尔 500。我们稍后会在一些相关性测试中用到它。
SPY = get_historical_data("SPY", start, end, output_format='pandas')plt.figure(figsize=(10, 4))
plt.plot(SPY.index, SPY['close'])
plt.title('Daily Times Series for the SPY');

现在,让我们继续通过下载 FAANG 股票(脸书、亚马逊、苹果、网飞和谷歌)(Kenton,2019)的数据来探索 API,并添加我的一个兴趣,Tesla。还有,把这些都记录下来。仔细注意图表,并与上面的间谍图进行比较。其中一些看起来很像间谍图,一些则不像。
FAANGT = get_historical_data(["FB","AMZN","AAPL","NFLX","GOOG","TSLA"], start, end, output_format='pandas')
print(FAANGT.head())FB AMZN \
open high low close volume open high low
date
2017-01-03 116.03 117.84 115.51 116.86 20663912 757.92 758.76 747.70
2017-01-04 117.55 119.66 117.29 118.69 19630932 758.39 759.68 754.20
2017-01-05 118.86 120.95 118.32 120.67 19492150 761.55 782.40 760.26
2017-01-06 120.98 123.88 120.03 123.41 28545263 782.36 799.44 778.48
2017-01-09 123.55 125.43 123.04 124.90 22880360 798.00 801.77 791.77 ... GOOG \
close volume ... open high low close volume
date ...
2017-01-03 753.67 3521066 ... 778.81 789.63 775.80 786.14 1657268
2017-01-04 757.18 2510526 ... 788.36 791.34 783.16 786.90 1072958
2017-01-05 780.45 5830068 ... 786.08 794.48 785.02 794.02 1335167
2017-01-06 795.99 5986234 ... 795.26 807.90 792.20 806.15 1640170
2017-01-09 796.92 3446109 ... 806.40 809.97 802.83 806.65 1274645 TSLA
open high low close volume
date
2017-01-03 214.86 220.33 210.96 216.99 5923254
2017-01-04 214.75 228.00 214.31 226.99 11213471
2017-01-05 226.42 227.48 221.95 226.75 5911695
2017-01-06 226.93 230.31 225.45 229.01 5527893
2017-01-09 228.97 231.92 228.00 231.28 3979484 [5 rows x 30 columns]plt.figure(figsize=(15, 4))
#FB
plt.subplot(1, 2, 1)
plt.plot(FAANGT.index, FAANGT['FB']['close'])
plt.title('Daily Times Series for the FB')#AMZN
plt.subplot(1, 2, 2)
plt.plot(FAANGT.index, FAANGT['AMZN']['close'])
plt.title('Daily Times Series for the AMZN'); plt.figure(figsize=(15, 4))
#AAPL
plt.subplot(1, 2, 1)
plt.plot(FAANGT.index, FAANGT['AAPL']['close'])
plt.title('Daily Times Series for the AAPL');#GOOG
plt.subplot(1, 2, 2)
plt.plot(FAANGT.index, FAANGT['GOOG']['close'])
plt.title('Daily Times Series for the GOOG');plt.figure(figsize=(15, 4))
#TSLA
plt.subplot(1, 2, 1)
plt.plot(FAANGT.index, FAANGT['TSLA']['close'])
plt.title('Daily Times Series for the TSLA');



现在我们有了 FAANG 股票(和 TSLA)和标准普尔 500 的数据,我们把它们画出来,这样我们就知道它们看起来像什么了;我们来做个实验吧!我们将尝试皮尔逊相关性测试,测试所有这些股票和标准普尔 500 的相关性。你怎么想呢?基于对图表的观察和直觉,它们会有关联吗?
当皮尔逊相关系数在-1 和+1 之间时,将显示相关性。如果接近+1,我们会看到正相关。如果皮尔逊相关性更接近-1,则为负相关(Cheong,2019)。
**import** **pandas** **as** **pd
import scipy.stats as stats***# Slice this up to make it easier to work with.*
indx = pd.IndexSlice
df1 = FAANGT.loc[:, (indx[:],'close')]
c, p = stats.pearsonr(df1['FB'].dropna()['close'], SPY.dropna()['close'])
print(f"FB vs SPY Pearson Correlation: **{c}\n**")
c, p = stats.pearsonr(df1['AMZN'].dropna()['close'], SPY.dropna()['close'])
print(f"AMZN vs SPY Pearson Correlation: **{c}\n**")
c, p = stats.pearsonr(df1['AAPL'].dropna()['close'], SPY.dropna()['close'])
print(f"AAPL vs SPY Pearson Correlation: **{c}\n**")
c, p = stats.pearsonr(df1['GOOG'].dropna()['close'], SPY.dropna()['close'])
print(f"GOOG vs SPY Pearson Correlation: **{c}\n**")
c, p = stats.pearsonr(df1['TSLA'].dropna()['close'], SPY.dropna()['close'])
print(f"TSLA vs SPY Pearson Correlation: **{c}**")FB vs SPY Pearson Correlation: 0.7325442525842248
AMZN vs SPY Pearson Correlation: 0.910899729798812
AAPL vs SPY Pearson Correlation: 0.9176098570966427
GOOG vs SPY Pearson Correlation: 0.9485878709468345
TSLA vs SPY Pearson Correlation: -0.26968006350226387
截至 2019 年 11 月 22 日,在所有这些选项中,谷歌(Google)的皮尔逊相关系数最高。此外,特斯拉(TSLA)与标准普尔 500 负相关。你可以在上面的图表中找到许多,并将这些图表与标准普尔 500 图表进行比较;但是现在你有了一个定量的关联方法!
现在,为了更深入地探索 API,让我们看看社交情感特性是什么样子的。我们来看看昨天(2019 年 11 月 22 日),对于特斯拉来说。
**from** **iexfinance.altdata** **import** get_social_sentiment, get_ceo_compensation
period='minute'
specDay="20191122"
TSLA_Sent = get_social_sentiment("TSLA", period, specDay, output_format='pandas')
print(TSLA_Sent.head())minute negative positive sentiment totalScores
0 0000 0.12 0.88 0.084958 26
1 0001 0.12 0.88 0.160624 17
2 0002 0.11 0.89 0.061056 18
3 0003 0.29 0.71 -0.180071 17
4 0004 0.07 0.93 0.066293 15
昨天,特斯拉最积极和最消极的社会情绪的最高分是多少?
TSLA_Sent_Pos = TSLA_Sent['sentiment'].max()
TSLA_Sent_Neg = TSLA_Sent['sentiment'].min()print("Highest Social Sentiment on 11/22/2019:", TSLA_Sent_Pos)
print("Lowest Social Sentiment on 11/22/2019:", TSLA_Sent_Neg)Highest Social Sentiment on 11/22/2019: 0.9785
Lowest Social Sentiment on 11/22/2019: -0.9487
这个 API 还有 CEO 信息!让我们来看看我们之前研究的 FAANG 和 TSLA 股票的 CEO 信息。我们将使用 df1,它是在执行相关性测试时为了简化而创建的。
**import** **pprint**
**for** n, q **in** df1:
pprint.pprint(get_ceo_compensation(n)){'bonus': 0,
'companyName': 'Facebook Inc. Class A',
'location': 'Menlo Park, CA',
'name': 'Mark Zuckerberg',
'nonEquityIncentives': 0,
'optionAwards': 0,
'otherComp': 22554542,
'pensionAndDeferred': 0,
'salary': 1,
'stockAwards': 0,
'symbol': 'FB',
'total': 22554543,
'year': '2018'}
{'bonus': 0,
'companyName': 'Amazon.com Inc.',
'location': 'Seattle, WA',
'name': 'Jeffrey Bezos',
'nonEquityIncentives': 0,
'optionAwards': 0,
'otherComp': 1600000,
'pensionAndDeferred': 0,
'salary': 81840,
'stockAwards': 0,
'symbol': 'AMZN',
'total': 1681840,
'year': '2018'}
{'bonus': 0,
'companyName': 'Apple Inc.',
'location': 'Cupertino, CA',
'name': 'Timothy Cook',
'nonEquityIncentives': 12000000,
'optionAwards': 0,
'otherComp': 682219,
'pensionAndDeferred': 0,
'salary': 3000000,
'stockAwards': 0,
'symbol': 'AAPL',
'total': 15682219,
'year': '2018'}
{'bonus': 0,
'companyName': 'Netflix Inc.',
'location': 'Los Gatos, CA',
'name': 'Reed Hastings',
'nonEquityIncentives': 0,
'optionAwards': 35380417,
'otherComp': 0,
'pensionAndDeferred': 0,
'salary': 700000,
'stockAwards': 0,
'symbol': 'NFLX',
'total': 36080417,
'year': '2018'}
{'bonus': 0,
'companyName': 'Alphabet Inc. Class A',
'location': 'Mountain View, CA',
'name': 'Larry Page',
'nonEquityIncentives': 0,
'optionAwards': 0,
'otherComp': 0,
'pensionAndDeferred': 0,
'salary': 1,
'stockAwards': 0,
'symbol': 'GOOG',
'total': 1,
'year': '2018'}
{'bonus': 0,
'companyName': 'Tesla Inc',
'location': 'Palo Alto, CA',
'name': 'Elon Musk',
'nonEquityIncentives': 0,
'optionAwards': 2283988504,
'otherComp': 0,
'pensionAndDeferred': 0,
'salary': 56380,
'stockAwards': 0,
'symbol': 'TSLA',
'total': 2284044884,
'year': '2018'}
还有很多东西需要探索和分析。在下一篇文章中,我计划探索 IEX 云的一些“实时”数据,例如书籍。此外,我可能会继续时间序列分析,并转移到一些基本的预测。我希望您发现这个探索有用!
参考
- 西肯顿(2019 年 11 月 18 日)。FAANG 股票是什么?检索于 2019 年 11 月 28 日,发自 https://www.investopedia.com/terms/f/faang-stocks.asp。
- 林奇,A. (2019 年 10 月 24 日)。addisonlynch/iexfinance。检索于 2019 年 11 月 28 日,发自 https://github.com/addisonlynch/iexfinance。
- Cheong,J. H. (2019 年 5 月 13 日)。量化时间序列数据同步性的四种方法。检索于 2019 年 11 月 28 日,来自https://towardsdatascience . com/four-way-to-quantify-synchrony-between-time-series-data-b 99136 C4 a9 c 9。
时间序列聚类和降维
利用 Kolmogorov Smirnov 统计和机器学习对传感器数据进行聚类

Photo by Igor Ferreira on Unsplash
数据科学家必须小心处理时间序列。这种数据包含关于时间依赖性的内在信息。我们的工作是在可能和有用的地方提取这些黄金资源,以帮助我们的模型发挥最佳性能。
对于时间序列,当我们面对降维或聚类的问题时,我看到了困惑。我们习惯于在更经典的领域中考虑这些任务,而当我们处理时间序列时,它们仍然是一个标签。
在这篇文章中,我试图澄清这些话题,开发一个有趣的解决方案,在这个方案中,我与来自不同个人的多维系列一起工作。我们的目的是利用深度学习,以无监督的方式对它们进行聚类,警惕相关性,并指出每个数据科学家都必须知道的有用技术!
数据集
我从 UCI 机器学习知识库中获得数据;我选择了人体运动基元检测加速度计数据公共数据集。这些数据是标记的加速度计数据记录的公共集合,用于创建和验证人类运动原语的加速度模型。
跟踪不同类型的活动,即喝酒、吃饭、爬山等。对于测量的特定个人的特定活动,我们有 3 个不同的传感器系列可供使用:X 轴(指向手部)、Y 轴(指向左侧)、Z 轴(垂直于手部平面)。
我在这种情况下思考自己,因为它允许在一个单独的案例中执行我们最初的问题聚类(多个个体)和维度缩减(每个个体的多个序列)。
下面我画了两个数据的例子,分别来自男性和女性。总共,我们有 20 个测量长度相同的个体。

降维
首先,我们的攻击计划提供了解决多维度问题。我们希望将存储在传感器数据中的所有信息总结成一个有意义的系列。这一最新步骤将使我们能够轻松地将我们的个人分组。
有很多种技术可以降低数据的维数,但我们的注意力集中在深度学习算法上。一个神经网络结构将允许我们容易地处理我们的初始数据:我记得你,我们有 20 个个体,对于每个个体,我们有 3 个长度为 170 的位置运动序列(用 pythonic 语言来说,我们有一个维数为 20x170x3 的数组)。传统的基于 PCA 的方法不允许我们处理这种问题,所以我们在 Keras 中建立了我们手工制作的自动编码器来处理我们臭名昭著的原始数据结构。
inp = Input(shape=(data.shape[1], data.shape[2]))
encoder = TimeDistributed(Dense(200, activation='tanh'))(inp)
encoder = TimeDistributed(Dense(50, activation='tanh'))(encoder)
latent = TimeDistributed(Dense(10, activation='tanh'))(encoder)
decoder = TimeDistributed(Dense(50, activation='tanh'))(latent)
decoder = TimeDistributed(Dense(200, activation='tanh'))(decoder)out = TimeDistributed(Dense(3))(decoder)autoencoder = Model(inputs=inp, outputs=out)
autoencoder.compile(optimizer='adam', loss='mse')
上面我已经展示了我使用的架构:时间分布层允许处理 3D 数据,其中索引 1 的维度将被认为是时间维度。对于我们的实验,我们使用前 10 个人来训练我们的自动编码器,并利用其余的人来计算相对预测的误差重构。在输入自动编码器之前,不要忘记标准化你的数据!在我们的例子中,我已经通过单个观察(通过行)对每个人的数据进行了标准化。
我们最终的重建误差看起来类似于下面的这个,当我们有信心并且能够检测到这个被选择的人的活动时,我们有接近零的点;而当我们的模型没有足够的学习,并且没有足够的信心来重建行走活动时,我们有很高的价值。

相关聚类
此时,我们已经有了可管理的对象(20 个人的维度为 175x1 ),并且我们已经准备好进行集群。从技术上来说,我们对测试个体的重构误差进行层次聚类。为了捕捉这些系列之间的重要关系,我们尝试了两种不同的工具来组合我们的集群。
在第一阶段,我们的选择包括采用皮尔逊相关指数。不幸的是,这个度量在统计学和机器学习领域非常 过度估计和滥用 ,但是我们想给它一个机会…
获得相关矩阵后,我们直接对其进行操作,执行层次聚类。我们应用高阈值(传感器系列之间的最高成对距离的 99%)来形成我们的扁平聚类。这将导致高水平组的创建,数量很少,但是给我们测试数据的第一印象深刻的概述。
d = sch.distance.pdist(corr)
L = sch.linkage(d, method='ward')
ind = sch.fcluster(L, d.max(), 'distance')
dendrogram = sch.dendrogram(L, no_plot=True)df = [df[i] for i in dendrogram['leaves']]
labels = [person_id[10:][i] for i in dendrogram['leaves']]
corr = np.corrcoef(df)dendrogram = sch.dendrogram(L, labels=[person_id[10:][i] for i in dendrogram['leaves']])

Hierarchical Clustering on Correlation Matrix
查看相关矩阵的颜色强度(我们刚刚对其进行了聚类操作),我们看不到明显的分组模式。在右边,树状图的切割线(黑线)在一些初始的“不确定性”之后,并没有创造出理性的群体。男女混在一起没有逻辑!
皮尔逊相关指数再次证实了它的不可靠性,我们必须走另一条路…
KOLMOGOROV SMIRNOV 聚类
最近,我读到了 Kolmogorov Smirnov 的统计数据,这对我产生了双重影响:它让我想起了大学,也让我注意到了它的适应性。这个统计量,加上相对 p 值,用于测量两个样本之间的分布差异。我认为我们的聚类任务是这个杀手级工具的一个很好的应用领域。
使用 python 计算这个统计数据非常简单,为了在我们的例子中使用它,我们只需创建 Kolmogorov Smirnov 矩阵(相当于相关矩阵)并重复上面所做的相同步骤。

Hierarchical Clustering on Kolmogorov Smirnov Matrix
现在,查看我们矩阵的颜色强度(我们刚刚对其进行了聚类操作),我们可以观察到女性和男性之间存在一种模式。从右边的树状图中可以清楚地看到,我们的分级程序已经创建了两个合理的群体,其中男性和女性都是分开的。集群建立之初的“不确定性”也消失了。
这是我们想要的结果,它证实了 Kolmogorov Smirnov 统计数据在每个数据科学家的武器库中的重要性。
摘要
在这篇文章中,我们同时解决了时间序列数据的降维和聚类问题。我们利用自动编码器来总结(以重建误差的形式)加速度计的相关特性。在我们的一维系列中,我们对个体进行了聚类划分。最令人满意的结果来自 Kolmogorov Smirnov 统计和层次聚类的组合,再次证实了必须谨慎处理 Pearson 相关性。
保持联系: Linkedin
时间序列预测(1):初步分析
所有这些信息都可以在我的 kaggle 个人资料中找到。
让我们从定义什么是时间序列开始这个系列。我选择了最简单的方法,并询问了维基百科,答案如下:
时间序列是按时间顺序索引(或列出或绘制)的一系列数据点。最常见的是,时间序列是在连续的等间隔时间点取得的序列。因此,它是一个离散时间数据序列。—维基百科
因此,时间序列基本上与任何其他数据集相似,但具有两个重要特征:
- 数据的顺序很重要,我们不仅关心数据的值,还关心这些值何时出现。
- 我们有观察每个实例的时间信息:我们或者有一个包含日期时间信息的列,或者我们知道数据在时间上是等间距的(例如,每秒一个值)。
在这里,我将介绍时间序列的概念,并对数据进行初步分析和调整;由于 Kaggle 数据通常非常清楚,这项工作比现实生活中容易得多,但其想法是表示过程,而不是编写复杂的代码。我要遵循的流程是这样的:
- 加载数据并设置子集(我不会在这里使用整个数据集)
- 可视化数据
- 清理数据:是否有丢失的值?所有的数据都是期望的格式吗?
- 查看统计数据:有异常值吗?
- 寻找平稳性和自相关性
- 趋势和季节性分解
数据
我正在使用来自 Kaggle 知识库的历史每小时天气数据。该数据集包含不同城市大约 5 年的天气信息,包括温度、湿度、压力、风和天气描述等信息。我将把重点放在温度数据上,因为我觉得它更直观。
为了举例,我将使用两个城市的温度数据,选择的将是旧金山(因为我喜欢它)和变化最大的城市。
加载数据
我将在整个笔记本中使用 Pandas 来处理数据和 matplotlib 进行可视化。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
让我们从加载数据 a 开始,快速浏览一下它的形状和第一个值。因为我已经知道这是一个时间序列,所以我将把 datetime 列设置为索引。
temp = pd.read_csv('../input/temperature.csv', parse_dates=['datetime'])
temp = temp.set_index('datetime')
print('Dataset shape: {}'.format(temp.shape))
temp.head()

该数据集由 36 列组成,对应 36 个不同的城市,45253 行,给出了从 2012 年末到 2017 年末每小时的温度值。
如我所说,我要使用的城市之一是年气温变化最大的城市。让我们找出是哪一个。
all_std = temp.std(axis=0)
max_std = all_std.max()
city_max_std = temp.columns[all_std==max_std][0]print('City with highest temperature variation: {} ({} degrees)'.format(city_max_std,round(max_std,2)))

现在让我们对数据进行子集划分,使其仅包含旧金山和明尼阿波利斯的值,并查看一些统计数据。
data = temp[['San Francisco','Minneapolis']]
data.describe()

我看到的第一件事是两列中都有丢失的数据,我将很快处理这个问题。此外,这个温度值显然不在日常温度的正常范围内。因为我住在欧洲,所以我要将数据从开尔文转换为摄氏度(抱歉,如果你用的是 Farenheit,但是国际系统)。
data = data-273.15
data.describe()

可视化数据
让我们来看看这两个城市历年的气温情况。
_=data.plot(
figsize=(15,5),
subplots=False,
title='Temperature',
alpha=0.7
)
_=plt.xlabel('Date')
_=plt.ylabel('Temperature')

还不错,明尼阿波利斯的天气似乎很冷,也许冬天我不会去那里。
此外,数据有明显的季节性,周期为一年。也有更多的变化,我稍后会检查这种变化是否与一些日常季节性有关,或者它更随机。
从这个图中我可以看出,旧金山的数据更少。蓝线距离 2018 年并没有那么近。
清理数据
正如我们所看到的,这里明显缺少值,图中引起我注意的一些东西可能是原因之一。正如我提到的,旧金山的数据结束得更早,为了同时处理这两个系列,我将丢失明尼阿波利斯系列的最终值。
为此,我将保留旧金山的所有非缺失值,并查看它们到达的最大日期。然后,我们将删除日期大于该日期的所有数据。
SF_non_missing = data['San Francisco'].dropna()
max_date = SF_non_missing.index.max()
data = data[data.index <= max_date]
让我们看看我们是否还有丢失的值。
print(data.isna().sum())

好了,我们还是要处理数据缺失的问题,不过有件事我想先处理一下。我在这里的目的是研究数据的年度行为,我对每日变化不感兴趣,所以我将通过取当天所有温度的平均值、最小值和最大值,将数据重新采样为每日频率。
data_mean = data.resample('D').mean()
data_min = data.resample('D').min()
data_max = data.resample('D').max()
print('Resample shape: {}'.format(data_mean.shape))
data_mean.describe()

如果每天都有更多没有丢失数据的行,这也可以解决我们丢失数据的问题。让我们检查一下。
print('Missing data now?')
print(data_mean.isna().sum())

现在没有丢失数据!这意味着我们每天至少有一个值。
如果不是这样,我会使用前一天的值。对于时间序列,我更喜欢这种解决方案,而不仅仅是删除行(最好在所有行之间有相同的时间间隔)或只使用平均值(因为这会扰乱曲线的形状)。
让我们检查一下重采样后数据的外观。
_=data_mean.plot(
figsize=(15,5),
subplots=False,
title='Temperature',
alpha=0.7
)
_=plt.fill_between(
x=data_mean.index,
y1=data_min['San Francisco'].values,
y2=data_max['San Francisco'].values,
alpha=0.3
)
_=plt.fill_between(
x=data_mean.index,
y1=data_min['Minneapolis'].values,
y2=data_max['Minneapolis'].values,
color='orange',
alpha=0.3
)
_=plt.xlabel('Date')
_=plt.ylabel('Temperature')

曲线周围的阴影显示当天的最小值-最大值,而主线显示平均值。
现在两条曲线都在同一点结束,我们有更少的每日变化。
极端值
有时奇怪的事情会发生,我们最终得到的值会搞乱整个模型。例如,一个传感器可能发生故障,在夏天测量到零下 10 度的温度,这肯定是不正常的。在夏天的其他时候,你可以看到 10,这很低,但可能不是一个错误,有时它会变冷,你不能删除这种类型的值,因为它可能有一些原因。我们必须小心对待异常值,除非我们知道它是一个错误或者是一次性的,不应该影响我们的模型,否则我们不应该删除它。
识别哪些点是异常值以及如何处理它们并不总是很容易,但是一个好的起点是检查数据以查看是否有值非常高或非常低的点。直观地看到这一点的一个好方法是使用直方图。
_=plt.hist(data_mean['San Francisco'], alpha=0.5, label='San Francisco')
_=plt.hist(data_mean['Minneapolis'], alpha=0.5, label='Minneapolis')
_=plt.legend()

让我们分别来看看每个城市:
- 旧金山的值似乎遵循具有小标准偏差的高斯分布,我们在该数据中看不到任何异常值。
- 明尼阿波利斯的曲线不太完美,向右偏高(负偏)。虽然我们不能说这些点中的任何一个是异常值,因为有相当多的异常值,同样,在温度的可视化表示中,我们可以看到每年都达到非常低的值。
我没有看到任何异常值,也不认为我应该删除任何点。
寻找平稳性和自相关性
我们先前绘制的高斯型直方图是时间序列可以是平稳的第一个线索。
另一个线索是计算不同时间范围内的时间序列的一些统计数据,并寻找变化。
cut = data_mean.index[int(0.5*len(data_mean))]
print('Mean before {}:'.format(cut))
print(data_mean.loc[:cut].mean())
print('')
print('Mean after {}:'.format(cut))
print(data_mean.loc[cut:].mean())
print('')
print('---------------------------')
print('')
print('Std before {}:'.format(cut))
print(data_mean.loc[:cut].std())
print('')
print('Std after {}:'.format(cut))
print(data_mean.loc[cut:].std())

我们可以看到,旧金山的值非常接近,但明尼阿波利斯的值更远,它们仍然足够接近,时间序列是平稳的,因为我们需要考虑标准偏差。
这种方法并不证明或否认我们的时间序列是平稳的,它只是表明它可以是平稳的。
我们还可以使用统计测试来确定是否应该拒绝非平稳性假设增强的 Dickey-Fuller 测试。
from statsmodels.tsa.stattools import adfullerresult = adfuller(data_mean['San Francisco'])
print('San Francisco')
print('--------------------------')
print('ADF Statistic: %f' % result[0])
print('p-value: %f' % result[1])
print('Critical Values:')
for key, value in result[4].items():
print('\t%s: %.3f' % (key, value))print('\n\n')
result = adfuller(data_mean['Minneapolis'])
print('Minneapolis')
print('--------------------------')
print('ADF Statistic: %f' % result[0])
print('p-value: %f' % result[1])
print('Critical Values:')
for key, value in result[4].items():
print('\t%s: %.3f' % (key, value))

那么,这些值意味着什么呢?
- ADF 统计量是扩大的 Dicken-Fuller 评分,该值越负,我们可以拒绝零假设(时间序列是平稳的概率)的确定性越高。
- p 值是零假设的置信度。这个值的通常阈值是 0.05,这意味着如果 p 值< = 0.05 ,我们可以拒绝零假设。
- 其余值分别是 99%、95%和 90%置信区间的临界值。
因此,在这种情况下,所有这些意味着我们可以拒绝旧金山的零假设,因为 p 低于 0.05,并且 ADF 得分低于 99%置信区间的限制。然而,我们无法拒绝明尼阿波利斯的这一假设,我们可以说它是具有 90%置信区间的平稳性,但是由于阈值是 95% ( p = 0.05 ),我们不能拒绝它。这意味着我们应该在应用任何模型之前区别数据。
可以在下面找到一些参考资料来理解这些测试:
自相关
最后要检查的是数据是否自相关。我想使用一些自回归方法来预测未来的帖子,我只能在数据自相关的情况下这样做(意味着特定时间点的值取决于以前的值)。
statmodels 库提供了一个很好的工具来检查这一点。阴影区域之外的一切都很有可能是自相关的(超过 95%的置信区间)。
import statsmodels.api as sm
print('San Francisco')
_=sm.graphics.tsa.plot_acf(data_mean['San Francisco'])
plt.show()
print('Minneapolis')
_=sm.graphics.tsa.plot_acf(data_mean['Minneapolis'])
plt.show()


让我们把重点放在最重要的滞后(更接近要点的),例如,一年范围的数据。
import statsmodels.api as sm
print('San Francisco')
_=sm.graphics.tsa.plot_acf(data_mean['San Francisco'], lags=365)
plt.show()
print('Minneapolis')
_=sm.graphics.tsa.plot_acf(data_mean['Minneapolis'], lags=365)
plt.show()


我们还可以检查部分自相关,它计算去除任何其他先前点(更接近新值的点)的影响的相关性。在这里,更远的点失去了重要性,我将重点放在一个月的范围。
print('San Francisco')
_=sm.graphics.tsa.plot_pacf(data_mean['San Francisco'], lags=30)
plt.show()
print('Minneapolis')
_=sm.graphics.tsa.plot_pacf(data_mean['Minneapolis'], lags=30)
plt.show()


以下是一些关于自相关的参考资料:
趋势-季节性分解
我们可以把时间序列看作趋势、季节性和残差(噪声或其他随机行为)的组合。由这些部分组成的时间序列可以是加法的,也可以是乘法的:
- 加法:数据=趋势+季节性+残差
- 乘法:数据=趋势季节性残差
Statsmodels 包提供了一个函数来一次提取这 3 个组件:季节性分解
这里的分解很简单,因为我们知道周期是 365 天。
from statsmodels.tsa.seasonal import seasonal_decompose as sd
sd_SF = sd(data_mean['San Francisco'], freq=365)
sd_M = sd(data_mean['Minneapolis'], freq=365)_=plt.figure(figsize=(15,10))
ax1=plt.subplot(311)
_=ax1.plot(sd_SF.trend, label='San Francisco', alpha=0.7)
_=ax1.plot(sd_M.trend, label='Minneapolis', alpha=0.7)
_=plt.legend()
ax2=plt.subplot(312)
_=ax2.plot(sd_SF.seasonal, label='San Francisco', alpha=0.7)
_=ax2.plot(sd_M.seasonal, label='Minneapolis', alpha=0.7)
_=plt.legend()
ax3=plt.subplot(313)
_=ax3.plot(sd_SF.resid, label='San Francisco', alpha=0.7)
_=ax3.plot(sd_M.resid, label='Minneapolis', alpha=0.7)
_=plt.legend()



看到这一点,我们可以理解为什么我们发现明尼阿波利斯的数据是不稳定的,温度有明显的上升。
我们还可以通过移动平均来发现趋势,我在这里不会这样做,因为这是季节性分解函数在幕后做的事情。
暂时就这样了。以后的帖子我先说一些预测算法。
希望这能帮助到一些和我一样的初学者,感谢阅读!😃
警察。:我非常希望得到一些反馈
Pd2。:我要感谢 Jason Brownlee 的博客 machinelearningmastery,因为我在这里学到了我所知道的关于时间序列数据的大部分知识,他有许多关于这个主题的帖子,他的解释和例子非常清楚,如果你刚刚开始,或者想扩展你关于这个或任何其他机器学习主题的知识,我完全推荐它
时间序列预测—入门指南
多元时间序列预测导论
介绍
当我开始写这篇文章时,我想解释如何用一个“简单”的时间序列(也就是单变量时间序列)进行预测。然而,我所参与的项目中最具挑战性的部分是预测需要结合多个变量。出于这个原因,我决定让这个指南更接近现实,并使用多元时间序列。
让我们先搞清楚一些概念…
一个 多变量 TS 是一个具有多个时间相关变量的时间序列。每个变量依赖于它过去的值,但也依赖于其他变量。预测值时会考虑这种依赖性。这些变量可以是内生的,也可以是外生的。在这里,我将重点关注外生变量。
外生变量是其值在模型之外确定并强加于模型的变量。换句话说,影响模型而不受其影响的变量。点击阅读更多关于外生变量的信息。
许多模型可以用来解决这样的任务,但我们将与 SARIMAX 合作。SARIMAX 代表带有外生回归量的季节性自回归综合移动平均线。
一切都好!现在,我们将介绍建立销售预测者可以遵循的步骤。
正如我在之前解释的那样,处理时间序列会带来一些挑战,比如让它保持平稳。如果你想知道更多关于我为什么在 dataframe 上执行一些转换的细节,去看看我以前的帖子。本文的重点是预测方法。
在这个机会中,我们有两个文件:一个包含过去销售的数据,另一个包含当地公共假日的信息。可以想象,任务将是通过组合这两个数据集来预测销售额。加载文件后,数据帧看起来像这样:

feriados_df — Holidays dataframe

ventas_df — past sales dataframe
我们的两个数据集的粒度都是在天的级别,也就是说,‘Date’和‘fecha’列都是具有每日频率的索引。如果我们想设置数据集的频率,我们可以运行下面一行:
ventas_df = ventas_df.resample(‘D’).mean() # 'D' for daily frequency
我们将需要连接这两个数据集,以便用我们拥有的所有数据来拟合我们的模型。' ventas_df '有我们要预测的变量。‘feria dos _ df’包含我们的外生变量。
为了让我们的生活更轻松,最好在加入 feriados_df 之前先站起来 ventas_df。我用来使序列更加平稳的方法包括应用对数变换和差分。固定化系列存储在“ts_log_diff”数据帧中。
test_stationarity(ts_log_diff)

现在我们可以加入 feriados_df 和 ts_log_diff,这是我们改造后的 ventas_df。
data_df = ts_log_diff.join(feriados_df, how='left')
data_df.head()

data_df — joined dataframe
有时在对熊猫进行一些操作后,我们得到的数据帧会丢失频率。为了解决这个问题,我们可以做到:
data_df = data_df.asfreq('D')
是时候来点特色工程了!
人们可以从现有的特性中想出多种创造新特性的方法。为了简单起见,让我们计算下面的列。
-假日 _ 工作日:公共假日是否在工作日
-假日 _ 周末:公共假日是在星期六还是星期天
-是星期几:日期是否在工作日
-是星期几:如果是周末
-在 25 日和 5 日之间:工资通常在这几天发放
**data_df['isweekday']** = [1 if d >= 0 and d <= 4 else 0 for d in data_df.index.dayofweek]
**data_df['isweekend']** = [0 if d >= 0 and d <= 4 else 1 for d in data_df.index.dayofweek]
**data_df['inbetween25and5']** = [1 if d >= 25 or d <= 5 else 0 for d in data_df.index.day]
**data_df['holiday_weekend']** = [1 if (we == 1 and h not in [np.nan]) else 0 for we,h in data_df[['isweekend','Holiday']].values]
**data_df['holiday_weekday']** = [1 if (wd == 1 and h not in [np.nan]) else 0 for wd,h in data_df[['isweekday','Holiday']].values]
让我们对列“Holiday”也应用一次热编码。
data_df = pd.get_dummies(data_df, columns=['Holiday'], prefix=['holiday'], dummy_na=True)

feature-engineered data_df
请我们已经可以预测了!?
亚斯。有点……首先,我们必须将数据分成训练和测试数据。你知道,为了良好的实践和避免过度拟合的东西;)
我们不能仅仅使用 k-folding 方法来将我们的数据集分成训练和测试。这是因为对于 TS,我们必须考虑时间因素。我们可以应用一些技术,其中包括:
- 训练测试分割尊重观察的时间顺序。
- 多重训练测试分割尊重观察的时间顺序。
- 前推验证,每次收到新数据时更新一个模型。
在这种情况下,将使用 1 号。从系列开始到 2019 年 2 月的数据点将用作训练数据。其余的数据点将用于测试。
生成和可视化预测
result_daily = my_train_sarimax(data_df[:'2019-02-28'], i_order=(2,1,2), i_freq='D', i_seasonorder=(2, 1, 1, 12))
在上面的行中,训练数据点' data _ df[:' 2019–02–28 ']被传递给函数。值得注意的是,dataframe 中的第一列必须包含要预测的值。其余列是我们的外生变量(即假期和工程特征)。数据帧的频率在“i_freq”参数中给出。参数“i_order”和“i_seasonorder”指定训练模型所需的参数,请查看 SARIMAX 的文档以了解有关这些参数的更多信息。
my_train_sarimax()函数定义如下。

现在是时候验证我们的预测了。为此,我们将使用一个函数来检索预测值,然后将它们与测试数据点中的真实值进行比较。
ypred, ytruth = compare_pred_vs_real(result_daily, data_df, ‘2019–03–01’, exog_validation=data_df[‘2019–03–01’:].iloc[:,1:])
值得一提的是,必须向模型提供要预测的时间范围的外生变量。请记住,这些是模型外部的变量,它需要这些变量来进行预测。
如果我们查看“compare_pred_vs_real()”定义,我们可以看到预测是使用“get_prediction()”函数进行的。可以通过使用“预测平均值”方法来提取这些值。

Performance of our model
我们可以说我们的模型在 MSE 和 RMSE 方面有相当不错的表现。让我们看看我们的预测与实际售出的商品数量相差有多远。
ypred - ytruth

predictions minus true values
但是,等等…为什么我们会看到十进制数值?出售的商品数量必须是整数!
预测的(反)转换
请记住,我们进行了对数转换,然后对数据集应用了差分。为了看到我们的模型估计的实际销售数字,我们必须恢复这些转换。
由于差异操作,TS 中的原始第一个日期丢失。我们需要从“data_df”中填充缺失的值。接下来,我们需要将预测之前的所有日期追加到‘y _ pred’中。这些日期也来自‘data _ df’。完成所有这些后,我们可以用 cumsum()恢复差异,然后应用 exp()恢复对数转换。
#create a series with the dates that were dropped with differencing
restore_first_values = pd.Series([6.008813], index=[pd.to_datetime(‘2014–01–01’)])#get the values that the prediction does not have
missing_part = data_df[‘cantidad’][:’2019–02–28']
rebuilt = restore_first_values.append(missing_part).append(ypred)#revert differencing:
rebuilt = rebuilt.cumsum()#revert log transformation:
rebuilt = np.exp(rebuilt).round() # apply round() to have integers
我们终于可以看到我们的预测值,并与实际值进行比较。耶!
# Check how far were the predictions from the actual values
rebuilt['2019-03-01':] - ventas_df['cantidad']['2019-03-01':]

Looks like we got it right most of the time 😃
最终意见
请记住,可以使用许多方法来实现 TS 中的平稳性。此外,SARIMAX 不是唯一一个对时间序列进行预测的模型,进一步的参数调整有助于提高模型的准确性。
请随意在我的 github repo 上查看该指南的全部代码。
感谢阅读!
英国道路交通事故的时间序列预测
在这篇文章中,我们旨在预测英国未来的交通事故数量。使用的数据来自交通部(GB) [1]。该数据提供了 2014 年至 2017 年英国人身伤害道路事故情况的详细道路安全信息。我们将使用 ARIMA 和 Prophet 实现时间序列预测,以找出未来道路交通事故的数量。

Photo by Stephen Dawson on Unsplash
什么是时间序列?
时间序列是变量在不同时间取值的一组观察值。例如销售趋势、股票市场价格、天气预报等。时间序列是用来根据以前的观察值预测未来值的。
时间序列的成分
- 趋势:趋势可以显示一个时间序列在很长一段时间内的增长或下降。这种趋势将持续很长一段时间。例如,价格和进出口数据反映出明显的增长趋势。
- 季节性:这些是由于季节性因素而在数据中出现的短期变动。短期通常被认为是随着天气或节日的变化,时间序列发生变化的时期
- 不规则性:这些是在时间序列中发生的不太可能重复的突然变化。它们是时间序列的组成部分,无法用趋势、季节或周期运动来解释。这些变化有时被称为残差或随机分量。
- 周期性的:这些是发生在时间序列中的长期振荡。这些振荡大多在经济数据中观察到,并且这种振荡的周期通常从五年延长到十二年或更长。这些波动与众所周知的商业周期有关。[2]
什么是 ARIMA 模式?
ARIMA 代表自回归综合移动平均线。有季节性和非季节性 ARIMA 模型可用于预测。ARIMA 模型的特征在于 3 项:p,d,q,其中 p 是 AR 项的阶,q 是 MA 项的阶,d 是使时间序列稳定所需的差的数量。如果一个时间序列有季节模式,那么你需要添加季节项,它就变成了萨里玛,是“季节性 ARIMA”的缩写。等我们结束 ARIMA 后会有更多的报道。[3]
让我们用所需的库准备好我们的环境,然后导入数据!
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
import matplotlib
plt.style.use('ggplot')
import warnings
import itertools
matplotlib.rcParams['axes.labelsize'] = 14
matplotlib.rcParams['xtick.labelsize'] = 12
matplotlib.rcParams['ytick.labelsize'] = 12
matplotlib.rcParams['text.color'] = 'k'
检查数据
df = pd.read_csv('~/accident_UK.csv')
df.head()

df.info()

将日期列转换为日期类型
df['Date'] = pd.to_datetime(df['Date'])
df.head()

按日期对数据进行排序
df = df.sort_values(by=['Date'])
df.head()

设置索引的日期
accident = df.set_index('Date')
accident.index

我们来提取一下每个月的平均事故次数。
y = accident['Total_Accident'].resample('MS').mean()
y.head()

让我们看一下每个月平均事故的数量。
y.plot(figsize=(15, 6))
plt.show()

让我们使用时间序列分解来可视化数据,这允许我们将时间序列分解为三个不同的部分:趋势、季节性和噪声。
from pylab import rcParams
import statsmodels.api as sm
rcParams['figure.figsize'] = 16, 10
decomposition = sm.tsa.seasonal_decompose(y, model='additive')
fig = decomposition.plot()
plt.show()

季节性 ARIMA 的参数组合示例
p = d = q = range(0, 2)
pdq = list(itertools.product(p, d, q))
seasonal_pdq = [(x[0], x[1], x[2], 12) for x in list(itertools.product(p, d, q))]
print('Examples of parameter combinations for Seasonal ARIMA...')
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[1]))
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[2]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[3]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[4]))

这一步是为我们的 ARIMA 时间序列模型选择参数。我们在这里的目标是使用“网格搜索”来找到为我们的模型产生最佳性能的最佳参数集。
for param in pdq:
for param_seasonal in seasonal_pdq:
try:
mod = sm.tsa.statespace.SARIMAX(y,
order=param,
seasonal_order=param_seasonal,
enforce_stationarity=False,
enforce_invertibility=False)
results = mod.fit()
print('ARIMA{}x{}12 - AIC:{}'.format(param, param_seasonal, results.aic))
except:
continue

上述输出表明,SARIMAX (1,1,1)x(1,1,0,12)产生的 AIC 值最低,为 186.26。因此,我们应该认为这是一个最佳选择。
拟合 ARIMA 模型
mod = sm.tsa.statespace.SARIMAX(y,
order=(1, 1, 1),
seasonal_order=(1, 1, 0, 12),
enforce_stationarity=False,
enforce_invertibility=False)
results = mod.fit()
print(results.summary().tables[1])

我们需要始终运行模型诊断来调查任何不寻常的行为。
results.plot_diagnostics(figsize=(16, 8))
plt.show()

预测评估
为了了解我们预测的准确性,我们将预测的事故数量与时间序列的实际事故数量进行比较,我们将预测从 2017 年 1 月 1 日开始到数据结束。
pred = results.get_prediction(start=pd.to_datetime('2017-01-01'), dynamic=False)
pred_ci = pred.conf_int()
ax = y['2014':].plot(label='observed')
pred.predicted_mean.plot(ax=ax, label='One-step ahead Forecast', alpha=.7, figsize=(14, 7))
ax.fill_between(pred_ci.index,
pred_ci.iloc[:, 0],
pred_ci.iloc[:, 1], color='k', alpha=.2)
ax.set_xlabel('Date')
ax.set_ylabel('Furniture Sales')
plt.legend()
plt.show()

让我们找出 MSE 来看看我们模型的准确性。均方误差(MSE)主要用作确定算法性能的度量。此外,MSE 是一个变量的观察值和预测值之差的平方的平均值。
y_forecasted = pred.predicted_mean
y_truth = y['2017-01-01':]
mse = ((y_forecasted - y_truth) ** 2).mean()
print('The Mean Squared Error of our forecasts is {}'.format(round(mse, 2)))

可视化预测
正如我们在下面的图表中所看到的,英国的交通事故数量在未来几年将会下降。
pred_uc = results.get_forecast(steps=100)
pred_ci = pred_uc.conf_int()
ax = y.plot(label='observed', figsize=(14, 7))
pred_uc.predicted_mean.plot(ax=ax, label='Forecast')
ax.fill_between(pred_ci.index,
pred_ci.iloc[:, 0],
pred_ci.iloc[:, 1], color='k', alpha=.25)
ax.set_xlabel('Date')
ax.set_ylabel('Furniture Sales')
plt.legend()
plt.show()

什么是先知模型?
Prophet 是一个来自脸书的开源时间序列预测算法,它的设计是为了在没有时间序列预测或统计方面的专家知识的情况下易于使用。时间序列预测通过寻找最佳平滑线来建立模型,该最佳平滑线可以表示为以下分量的总和:
- 总体增长趋势
- 早期季节性
- 每周季节性
- 节日影响
先知方法的好处:
- 数据之间不均匀的时间间隔不是问题
- 天娜不是问题
- 默认情况下,会处理多个期间(周和年)的季节性
- 默认设置下工作良好,参数易于解释
让我们按日期对值进行排序
df = df.sort_values(by=['Date'])
df.head()

Prophet 要求时间序列中的变量名为:
- y-目标
- ds —日期时间
因此,下一步是根据上述规范转换数据帧
df = df.rename(columns={'Date': 'ds',
'Total_Accident': 'y'})
df.head()

让我们想象一下每天的交通事故数量
ax = df.set_index('ds').plot(figsize=(15, 8))
ax.set_ylabel('Total Accident')
ax.set_xlabel('Date')
plt.show()

拟合先知模型
将不确定性区间设置为 95%(Prophet 默认为 80%)
from fbprophet import Prophet
my_model = Prophet(interval_width=0.95)
my_model.fit(df)

要使用我们的模型创建预测,我们需要创建一些未来日期。Prophet 为我们提供了一个辅助函数,叫做 make_future_dataframe。我们传入未来周期的数量和频率。以上是我们对未来 36 个月或 3 年的预测。
future_dates = my_model.make_future_dataframe(periods=36, freq='MS')
future_dates.tail()

正如我们在下表中看到的,yhat 是我们的预测值。
forecast = my_model.predict(future_dates)
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()

让我们创建一个实际值和预测值的图表
plt.figure(figsize=(10,8))
my_model.plot(forecast,
uncertainty=True)

plot_components 为我们提供了趋势和季节性的图表
my_model.plot_components(forecast)

模型评估
from fbprophet.diagnostics import cross_validation
df_cv = cross_validation(my_model, initial='730 days', period='180 days', horizon = '365 days')
df_cv.head()

from fbprophet.diagnostics import performance_metrics
df_p = performance_metrics(df_cv)
df_p.head()

非常感谢你阅读我的文章!!!
参考资料:
[1].https://data . gov . uk/dataset/CB 7 AE 6 f 0-4be 6-4935-9277-47 E5 ce 24 a 11 f/road-safety-data
[2].克利夫兰,R. B .,克利夫兰,W. S .,麦克雷,J. E .,&特彭宁,国际法院(1990)。STL:基于黄土的季节趋势分解过程。官方统计杂志, 6 (1),3–33。
[3].Hyndman,R. J .,& Khandakar,Y. (2008 年)。自动时间序列预测:R. 统计软件学报, 27 (1),1–22 的预测包。
时间序列预测:从天真到 ARIMA 及以后
简单和复杂的商业决策预测技术

Photo by Aron Visuals on Unsplash
- 在未来五年内再建一座发电厂需要预测未来的需求;
- 下周在呼叫中心安排员工需要预测下周的呼叫量;
- 储存零售存货需要预测存货需求。
事实上,短期和中期预测是各行各业商业决策的重要组成部分。历史数据是这一预测过程的重要输入。
时间序列数据集是在任何业务中最广泛生成和使用的数据。它们既用于理解过去,也用于预测未来。在本文中,我将通过相关的案例研究和示例来讨论如何将各种预测方法应用于时间序列数据集。这篇文章的目的不是评价哪个模型是好是坏,而是展示我们在实践中可以做预测的许多不同的方法。本文分为两大部分:
(1)首先,我将概述时间序列数据以及如何分解不同的时间序列成分;
(2)然后我将提供不同预测技术的例子以及相关的实现方法
理解和分解时间序列数据
那么什么是时间序列数据呢?时间序列是在离散时间点记录的一系列观察值。它们可以以每小时(如气温)、每天(如 DJI 平均)、每月(如销售额)或每年(如国内生产总值)的时间间隔记录。时间序列广泛应用于所有学科,包括统计学、数学、天文学和工程学。时间序列绘图是在数据科学和分析的探索性数据分析(EDA)阶段实施的最基本的绘图练习之一。

Time series data: Daily Dow Jones Industrial (DJI) averages over 6 months
我们来看看下图。

即使用肉眼也很少有明显的特性:
- 这是一个时间序列图
- 有上升的趋势
- 观察值具有季节性(在固定的时间间隔内起伏)
事实上,如果我们分解这些数据,我们会看到这些组件,如下所示。

时间序列数据的预测技术
预测未来可以简单到外推历史观察的趋势,应用复杂的算法。在这里,我介绍了商业应用程序中最常用的不同技术。我使用两个统计和可视化包在 R 环境中演示这些技术:
# install packages
library("forecast")
library("ggplot2")
在导入数据(零售销售数据集)并将其转换为时间序列对象后,它看起来是这样的。
# import dataset
retaildata = readxl::read_excel("../retail.xlsx", skip=1)# convert dataset into a time series object
retailts = ts(retaildata, start = c(1982,4), frequency = 12 )# plot the time series object with autoplot() function that comes with forecast() package
autoplot(retailts)

首先我将解释一些简单的技术来预测这个时间序列对象。虽然这些简单的技术在实践中不经常使用,但知道它们是如何产生的是很好的,然后我们将进入更复杂的技术。
简单的预测技术
简单的预测技术被用作基准。它们提供了对历史数据的一般理解,并建立直觉,在此基础上增加额外的层复杂性。几种这样的技术在文献中很常见,如:均值模型、简单预测、随机游走、漂移法等。例如,均值模型采用以前观察值的均值,并将其用于预测。那就是:
预测值=训练数据的平均值
另一方面,随机游走将预测下一个值,ŷ(t,它等于前一个值加上一个常数变化。
ŷ(t)= y(t-1)+α
初始预测的值是基于最后一次观察的值设置的。和其他简单的方法一样,它提供了一个大概的数字作为初步估计,直到进一步的研究完成。下面是季节性朴素预测模型的实现。
# subsetting train and test data using window()function
retailtstrain = window(retailts, end = c(2010,3))
retailtstest = window(retailts, start = c(2010,4))# model building
retailtstrain_snaive = snaive(retailtstrain, h=50)# ploting
autoplot(retailts)+
autolayer(retailtstrain_snaive, series = "S Naive", PI = FALSE)

# Accuracy test
accuracy(retailtstrain_snaive, retailtstest)

指数平滑法
根据数据类型的不同,指数平滑几乎没有变化。简单的指数平滑法用于没有明确趋势的非季节性数据,而霍尔特-温特法用于有趋势和季节性的数据。它应用于平稳时间序列,其中平滑由参数 alpha (0~1)控制,其中较低的值意味着对最近观察值的较低权重。下面是使用相同数据集的霍尔特-温特指数平滑的实现。
# Holt Winter Exponential Smoothing
# Two variations: additive for roughly constant seasonal variation, otherwise multiplicative methoddata = window(retailts, start=2000)
data_add = hw(data, seasonal="additive")
data_mult = hw(data, seasonal="multiplicative")autoplot(data, series = "original data")+
autolayer(data_add, series = "additive", PI=FALSE)+
autolayer(data_mult, series = "multiplicative", PI=FALSE)

# model summary and performance
data_add[["model"]]

ARIMA 家族
自回归综合移动平均(ARIMA)可以说是最流行和最广泛使用的统计预测技术。顾名思义,这个技术家族有 3 个组成部分:a)一个“自回归”部分,它模拟序列和它的滞后观测值之间的关系;b)将预测建模为滞后预测误差的函数的“移动平均”模型;和 c)使系列静止的“集成”组件。
该模型采用以下参数值:
定义滞后数量的 p;
d 指定使用的差异数;和
q 定义了移动平均窗口的大小
使用时序对象进行预测的 ARIMA 模型的实现如下:
# implementing auto.arima() to forecast
retailts_arima = auto.arima(retailts, seasonal=TRUE, stepwise = FALSE, approximation = FALSE)
retailts_arima %>% forecast(h=10) %>% autoplot()

更先进的技术
最后,还有一些盒子外的技术,如基于代理的和系统动态建模。系统动力学是 20 世纪 50 年代由麻省理工学院斯隆管理学院开发的,是一种模拟复杂系统行为的方法,其中一个组件的变化会导致其他组件的变化。这种方法广泛应用于医疗保健、疾病研究、公共交通、商业管理和收入预测等行业。系统动力学最著名的应用可能是罗马俱乐部的增长极限模型。
一个系统动态模型代表了一个复杂的系统,通过反馈循环来预测系统的行为。假设一个银行账户有 100 美元的“股票”。每月存入 20 美元(由“流程”1 表示),每月提取 15 美元(由“流程”2 表示):

System dynamic modeling workflow
在这个例子中,股票的未来价值(即账户存款)被建模为未来流量(即存款和取款)的函数。本文提供了在建筑行业实施系统动态预测模型的案例研究。
额外资源
- 罗布·海德曼的网站https://robjhyndman.com/是 R 中所有预测问题的一站式解决方案。也可以查看开放存取书籍https://otexts.com/fpp2/中的理论讨论以及 R 实施示例。
- 《R 对于时间序列的一个小本子》什么都有简化形式。http://www . Calvin . edu/~ stob/courses/m344/S15/a-little-book-of-r-for-time-series . pdf
- 如果你喜欢 Python,请点击下面的链接。还有一本关于时序的 python 实现的书的参考。https://machinelementmastery . com/time-series-forecasting-methods-in-python-cheat-sheet/
基于深度堆叠单向和双向 LSTMs 的时间序列预测

这篇文章假设读者对 LSTMs 的工作原理有一个基本的了解。不过,你可以在这里得到 LSTMs 的简要介绍。另外,如果你是时间序列预测的绝对初学者,我推荐你去看看这个博客。
这篇文章的主要目的是展示深度堆叠单向和双向 LSTMs 如何作为基于 Seq-2-Seq 的编码器-解码器模型应用于时间序列数据。我们将首先介绍这个架构,然后看看实现它的代码。
让我们深入研究这个模型
等等。!在进入架构的细节之前,让我们理解序列到序列模型的特殊性。因此,顾名思义,序列对序列模型将一系列特征作为输入,并输出一个目标序列作为输入目标序列的延续(它可以预测未来的“n”个时间步)。
它基本上有两个部分,编码器输出输入序列的上下文向量(编码),然后传递给解码器解码和预测目标。

Lol,这可能有点让人不知所措,但是随着我们进一步深入和可视化架构,你会慢慢理解这些术语的。
模型架构
让我们从基本的编码器-解码器架构开始,然后我们可以逐步添加新的功能和层来构建更复杂的架构。
1。使用单向 LSTMs 作为编码器

这里,LSTM 编码器将时间序列作为输入(每个 LSTM 单元一个时间步长),并创建输入序列的编码。该编码是由所有编码器 LSTM 单元的隐藏和单元状态组成的向量。编码然后作为初始状态与其他解码器输入一起被传递到 LSTM 解码器,以产生我们的预测(解码器输出)。在模型训练过程中,我们将目标输出序列设置为模型训练的解码器输出。
2。使用双向 LSTMs 作为编码器

双向 LSTMs 具有两个递归分量,前向递归分量和后向递归分量。前向组件计算隐藏和单元状态,类似于标准单向 LSTM,而后向组件通过以逆时间顺序(即从时间步长 Tx 到 1 开始)取输入序列来计算它们。使用后向组件的直觉是,我们正在创建一种方式,网络可以看到未来的数据,并相应地学习其权重。这可能有助于网络捕获标准(前向)LSTM 无法捕获的一些相关性。BLSTM 也是大多数 NLP 任务的首选算法,因为它能够很好地捕捉输入序列中的相关性。
在 BLSTMs 中,前向组件的隐藏和单元状态与后向组件的不同。因此,为了获得编码,前向组件的隐藏和单元状态必须分别与后向组件的隐藏和单元状态连接。
3。使用堆叠单向 LSTMs 作为编码器

当这些层堆叠在一起时,编码器和解码器的第一层 LSTM 单元的输出(单元状态)被传递到第二层 LSTM 单元作为输入。似乎具有几个隐藏层的深度 LSTM 架构可以有效地学习复杂的模式,并且可以逐步建立输入序列数据的更高级别表示。
双向 LSTMs 也可以以类似的方式堆叠。第一层的前向和后向分量的输出分别传递给第二层的前向和后向分量。
实施细节:D
数据准备—
我们将在标准的“墨尔本每日最低气温”(单变量时间序列)数据集上应用上述模型(从这里下载)。但是,在进入培训场景之前,让我们首先准备数据。
- 将数据标准化。
注意: reshape 仅用于将单变量 1D 数组转换为 2D,如果数据已经是 2D,则不需要调用。
2.初始化参数。
3.生成输入输出序列对。
上述函数返回一批大小为“total_start_points”的输入序列和输出(目标)序列,它们将分别被馈送到编码器和解码器。注意返回的序列是形状的 3D 张量(batch_size,input_seq_len,n_in_features ),因为 keras 要求输入为这种格式。
模型—
我们定义了一个单一的函数来构建架构,这取决于传递的隐藏维度列表,以及在调用该函数时设置为“真”或“假”的参数“双向”。
注意当编码器是双向的时,我们在解码器 LSTM 中有‘hidden _ dim * 2’来容纳级联的编码器状态。
模特.飞度:D
默认情况下,Keras 在训练时会打乱数据,因此我们可以(不一定)在“model.fit”函数中设置“shuffle=False ”,因为我们已经在随机生成序列。
注意我们输入零作为解码器输入,也可以使用 教师强制 (其中一个解码器单元的输出作为输入输入到下一个解码器单元)(此处未涉及)。
结果

Unidirectional Layer-1 and Layer-2

Bidirectional Layer-1 and Layer-2
哇!所有的模型只被训练了 100 个时期(具有相同的参数),与单向 lstm 相比,双向 lstm 在学习数据中的复杂模式方面表现突出。因此,所描述的模型可以应用于许多其他时间序列预测方案,甚至可以应用于多变量输入情况,在这种情况下,您可以将具有多个特征的数据作为 3D 张量进行传递。
你可以在我的 GitHub 库中找到这个例子的 Jupyter 笔记本实现。
我希望你喜欢这篇文章,并让你很好地理解了如何使用深度堆叠 LSTMs 进行时间序列预测。非常感谢您的反馈或改进建议。
使用 TensorFlow 2 和 Keras 在 Python 中使用 LSTMs 进行时间序列预测
利用 LSTMs 进行时间序列预测的数据准备和预测介绍

TL;DR 了解时间序列,并使用递归神经网络进行预测。准备序列数据并使用 LSTMs 进行简单预测。
想学习如何使用多元时间序列数据?阅读下一部分:
[## 使用 TensorFlow 2 和 Keras 在 Python 中使用 LSTMs 进行需求预测
了解如何通过深度学习从多元时间序列数据中预测需求
towardsdatascience.com](/demand-prediction-with-lstms-using-tensorflow-2-and-keras-in-python-1d1076fc89a0)
通常,您可能不得不处理包含时间成分的数据。不管你怎么眯眼,都很难做出你喜欢的数据独立性假设。似乎数据中的新值可能依赖于历史值。你怎么能使用这种数据来建立模型呢?
本指南将帮助您更好地理解时间序列数据,以及如何使用深度学习(递归神经网络)建立模型。您将学习如何预处理时间序列,构建一个简单的 LSTM 模型,训练它,并使用它来进行预测。以下是步骤:
- 理解什么是时间序列
- 了解递归神经网络
- 在 Keras 中用 LSTMs 预测时间序列数据
- 评估模型
时间序列
时间序列是数据点的集合,根据它们被收集的时间进行索引。大多数情况下,数据是以固定的时间间隔记录的。时间序列数据的特殊之处是什么?
预测未来时间序列值是实践中一个相当常见的问题。预测下一周的天气、明天的比特币价格、圣诞节期间你的销售数量以及未来的心脏衰竭都是常见的例子。
时间序列数据引入了对先前时间步长的“硬依赖”,因此观测值独立性的假设不成立。时间序列可以具有哪些属性?
平稳性、季节性和自相关性是您可能感兴趣的时间序列的一些属性。
当均值和方差随时间保持不变时,称时间序列为平稳。如果平均值随时间变化,那么时间序列具有趋势。通常,您可以通过应用对数变换来消除它并使序列平稳。
季节性是指特定时间范围内的变化现象。人们在圣诞节期间购买更多的圣诞树(谁会想到)。消除季节性的一种常见方法是使用差异。
自相关 指当前值与前一时间(滞后)的拷贝值之间的相关性。
为什么我们想要季节性、趋势性和平稳的时间序列?这是用经典方法如 ARIMA 模型进行时间序列预测所需的数据预处理步骤。幸运的是,我们将使用递归神经网络进行建模。
递归神经网络
递归神经网络(RNNs)可以预测序列中的下一个值或对其进行分类。一个序列被存储为一个矩阵,其中每一行都是一个描述它的特征向量。自然,矩阵中行的顺序很重要。
rnn 非常适合解决自然语言处理(NLP)任务,其中文本中的单词形成序列,它们的位置很重要。也就是说,前沿 NLP 使用变压器来完成大多数(如果不是全部)任务。
你可能已经猜到了,时间序列只是序列的一种类型。我们必须将时间序列切割成更小的序列,这样我们的 RNN 模型就可以用它们进行训练。但是我们如何训练 rnn 呢?
首先,让我们对递归的含义有一个直观的理解。rnn 包含循环。每个单元都有一个状态,并接收两个输入-来自前一层的状态和来自前一时间步的该层的统计数据。
反向传播算法在应用于 RNNs 时会因为循环连接而失效。展开网络可以解决这个问题,在网络中,具有循环连接的神经元的副本被创建。这将 RNN 转换成常规的前馈神经网络,并且可以应用经典的反向传播。该修改被称为通过时间的反向传播。
经典 rnn 的问题
展开的神经网络会变得非常深(他就是这么说的),这给梯度计算带来了问题。权重可以变得非常小(消失梯度问题)或者非常大(爆炸梯度问题)。
经典的 rnn 也有记忆问题(长期依赖性)。由于最近状态的压倒性影响,我们用于训练的序列的乞求倾向于被“遗忘”。
在实践中,这些问题可以通过使用门控 rnn 来解决。它们可以存储信息以备后用,就像有一个内存一样。阅读、写作和从记忆中删除都是从数据中学习的。两种最常用的门控 rnn 是长短期记忆网络和门控复发性单位神经网络。
用 LSTMs 进行时间序列预测
我们将从一个简单的例子开始,使用简单的 LSTM 网络预测正弦函数的值。
设置
让我们从库导入和设置种子开始:
数据
我们将从正弦函数中生成 1,000 值,并将其作为训练数据。但是,我们会添加一点精加工:

从正态分布中提取的随机值被添加到每个数据点。那会让我们模型的工作变得有点困难。
数据预处理
对于我们的模型,我们需要将数据“切碎”成更小的序列。但首先,我们将把它分为训练和测试数据:
800 200
为时间序列预测(尤其是 LSTMs)准备数据可能很困难。直观地说,我们需要利用历史( n 时间步长)来预测当前时间步长的值。这里有一个通用函数可以完成这项工作:
该函数的妙处在于它可以处理单变量(单特征)和多变量(多特征)时间序列数据。让我们用 10 个时间步骤的历史来制作我们的序列:
(790, 10, 1) (790,)
我们有形状为(samples, time_steps, features)的序列。我们怎么用它们来做预测呢?
建模
在喀拉斯培养 LSTM 模式很容易。我们将使用序列模型中的 LSTM 层进行预测:
LSTM 图层期望时间步长数和要素数能够正常工作。模型的其余部分看起来像一个常规的回归模型。我们如何训练一个 LSTM 模特?
培养
训练时间序列模型时要记住的最重要的事情是不要打乱数据(数据的顺序很重要)。其余的都很标准:

我们的数据集非常简单,包含了我们采样的随机性。经过大约 15 个时期后,模型已经基本完成了学习。
估价
让我们从我们的模型中选取一些预测:
我们可以根据时间序列的真实值绘制预测图:

我们的预测在这个尺度上看起来非常好。让我们放大:

该模型似乎在捕捉数据的一般模式方面做得很好。它未能捕捉到随机波动,这是一件好事(它概括得很好)。
结论
恭喜你!你做了你的第一个递归神经网络模型!您还了解了如何预处理时间序列数据,这是一件让很多人感到困惑的事情。
我们只是触及了时间序列数据和如何使用递归神经网络的表面。一些有趣的应用是时间序列预测、(序列)分类和异常检测。有趣的部分才刚刚开始!
想学习如何使用多元时间序列数据?阅读下一部分:
[## 使用 TensorFlow 2 和 Keras 在 Python 中使用 LSTMs 进行需求预测
了解如何通过深度学习从多元时间序列数据中预测需求
towardsdatascience.com](/demand-prediction-with-lstms-using-tensorflow-2-and-keras-in-python-1d1076fc89a0)
参考
Scikit-Learn、TensorFlow 和 Keras 深度学习实践指南了解如何解决现实世界的机器学习…
leanpub.com](https://leanpub.com/Hackers-Guide-to-Machine-Learning-with-Python)
原载于https://www.curiousily.com。
使用 LSTM 预测序列数据:简介
使用长短期记忆(LSTM)网络预测股票等序列数据的未来。

Photo by Chris Liverani on Unsplash
预测是使用当前和以前的数据预测未来的过程。主要的挑战是理解数据序列中的模式,然后使用这种模式来分析未来。如果我们手工编码这些模式,那么对于下一个数据来说,这将是乏味的和变化的。深度学习已被证明在理解结构化和非结构化数据中的模式方面更好。
为了理解一长串数据中的模式,我们需要网络来分析时间上的模式。递归网络通常用于学习这种数据。他们能够理解长期和短期的依赖性或时间差异。
好了,不介绍了…
这篇文章将向你展示如何在 Keras 中使用 LSTM 网络和一些很酷的可视化工具来实现一个预测模型。我们将使用来自雅虎财经的谷歌股价,但你可以随意使用任何你喜欢的股票数据。
履行
我已经使用 colab 来实现这个代码,以使可视化更容易,你可以使用你喜欢的方法。我们将从导入必要的库开始:
下载完您的。csv 文件,使用 pandas 加载数据。
dataframe 的信息显示如下:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3797 entries, 0 to 3796
Data columns (total 7 columns):
Date 3797 non-null object
Open 3797 non-null float64
High 3797 non-null float64
Low 3797 non-null float64
Close 3797 non-null float64
Adj Close 3797 non-null float64
Volume 3797 non-null int64
dtypes: float64(5), int64(1), object(1)
memory usage: 207.7+ KB
对于本教程,我们只需要 Date 和 Close 列,其他的都可以删除。
在我们进行训练和预测之前,让我们看看数据是什么样子的。对于所有的可视化,我使用的是 Plotly python 库。为什么是 Plotly?…因为它是最好的图形库,可以生成一些好看的图形。
使用 plotly,我们可以定义一个轨迹和布局,它可以做任何其他事情。
图表从 2018 年开始振荡,序列并不平滑…继续前进。
数据预处理
对于我们的分析,让我们在前 80%的数据上训练模型,并在剩余的 20%上测试它。
在我们进行培训之前,我们需要对我们的数据进行一些重大修改。记住,我们的数据仍然是一个序列..一列数字。神经网络被训练为监督模型。因此,我们需要将序列数据转换成监督数据😱。
我来解释一下,训练任何机器学习模型的神经网络都需要数据是{ <特征 >,< 目标 > }格式。同样,我们需要将给定的数据转换成这种格式。这里,我们引入一个回望的概念。
回顾只不过是使用前几天的数据来预测第二天的值。比如我们说回望是 2;所以为了预测明天的股价,我们需要今天和昨天的股价。
回到格式,在给定的一天x(t),特征是 x(t-1),x(t-2),…。,x(t-n) 其中 n 为回看。
所以如果我们的数据是这样的,
[2, 3, 4, 5, 4, 6, 7, 6, 8, 9]
所需的数据格式(n=3)如下:
[2, 3, 4] -> [5]
[3, 4, 5] -> [4]
[4, 5, 4] -> [6]
[5, 4, 6] -> [7]
[4, 6, 7] -> [6]
[6, 7, 6] -> [8]
[7, 6, 8] -> [9]
咳😓。
幸运的是,Keras 中有一个模块可以做到这一点: TimeseriesGenerator 。请查阅文档以获取更多信息。
我已经将 look_back 设置为 15,但是您可以随意使用这个值。
神经网络
现在我们的数据已经准备好了,我们可以继续创建和训练我们的网络。
使用 Adam 优化器和均方损失函数训练 25 个时期的 LSTM 单元的简单架构。注意,我们没有使用 model.fit(),而是使用 model.fit_generator(),因为我们已经创建了一个数据生成器。
想了解更多关于 LSTM 网络的信息,请看这篇令人敬畏的博文。
预言;预测;预告
现在我们已经完成了培训,让我们看看网络是否运行良好。我们可以在测试数据上测试模型,看看预测值和实际值是否重叠。
我们可以画出预测值和实际值之间的损失,而不是计算它们。
从图表中,我们可以看到预测值和实际值(地面实况)有些重叠。但如果放大看,拟合并不完美。我们应该预料到这一点,因为这是不可避免的,因为我们正在进行预测。
预测
我们的测试表明这个模型还不错。所以我们可以继续预测未来。
伏笔:因为我们试图预测未来,所以预测中会有很大的不确定性。
预测未来很容易…要预测明天的价值,将过去 n (回望)天的价值输入模型,我们就可以得到明天的价值作为输出。要获得后天的值,需要输入过去 n-1 天的值,以及明天的值和后天的模型输出。
更长时间的预测是不可行的。所以,让我们预测一个月的股票价格。
现在描绘未来的价值,
预测未来很容易…是吗?
在预测未来时,很有可能模型输出在很大程度上是不确定的。模型的输出作为输入反馈给它。这导致模型的噪音和不确定性被重复和放大。
但是,我们还是创建了一个模型,它给出了图表的趋势,以及未来可能的取值范围。
结论
通过这个模型,我们创建了一个能够在一定程度上进行预测的基本模型。尽管这个模型并不完美,但我们有一个能很好地逼近过去数据的模型。但是对于新数据,我们需要更多的参数调整。
如果在模型训练期间存在任何问题,请尝试调整这些参数:
- 回望 _ 回顾
- 批量
- LSTM 台
- 次数
您还可以通过堆叠 LSTM 图层来增强架构。
谢谢大家!!😁
使用 TensorFlow.js 进行时间序列预测
从在线 API 获取股票价格,并使用递归神经网络和长短期记忆(LSTM)以及 TensorFlow.js 框架进行预测

如今,机器学习变得越来越受欢迎,世界上越来越多的人将它视为一个神奇的水晶球:预测未来何时会发生什么。该实验使用人工神经网络来揭示股票市场趋势,并展示了时间序列预测根据过去的历史数据预测未来股票价格的能力。
免责声明:由于股票市场波动是动态的和不可预测的,由于多种因素,这个实验是 100%的教育,绝不是一个交易预测工具。
探索演示。
项目演练
本项目演练分为 4 个部分:
- 从在线 API 获取股票数据
- 计算给定时间窗口的简单移动平均值
- 训练 LSTM 神经网络
- 预测并将预测值与实际值进行比较
获取股票数据
在我们可以训练神经网络并做出任何预测之前,我们首先需要数据。我们正在寻找的数据类型是时间序列:按时间顺序排列的数字序列。获取这些数据的好地方是 alphavantage.co 的。这个 API 允许我们检索过去 20 年中特定公司股票价格的时序数据。
该 API 生成以下字段:
- 公开价格
- 那天的最高价
- 当天的最低价
- 收盘价(本项目中使用)
- 卷
为了给我们的神经网络准备训练数据集,我们将使用收盘股票价格。这也意味着我们将致力于预测未来的收盘价。下图显示了微软公司 20 年来的每周收盘价。

20 years of Microsoft Corporation weekly closing prices data from alphavantage.co
简单移动平均线
对于这个实验,我们使用监督学习,这意味着将数据输入到神经网络,它通过将输入数据映射到输出标签来学习。准备训练数据集的一种方法是从时序数据中提取移动平均值。
简单移动平均线(SMA) 是一种通过查看某个时间段内所有值的平均值来确定该时间段趋势方向的方法。时间窗口中的价格数量是通过实验选择的。
例如,假设过去 5 天的收盘价是 13,15,14,16,17,那么 SMA 就是(13+15+14+16+17)/5 = 15。因此,我们的训练数据集的输入是单个时间窗口内的一组价格,其标签是这些价格的计算移动平均值。
让我们计算微软公司每周收盘价数据的 SMA,窗口大小为 50。
这是我们得到的,蓝色的是每周股票收盘价,橙色的是 SMA。因为 SMA 是 50 周的均线,比周线价格平滑,周线价格可以波动。

Simple Moving Average of Microsoft Corporation closing prices data
培训用数据
我们可以用每周股票价格和计算出的 SMA 来准备训练数据。假设窗口大小为 50,这意味着我们将使用每连续 50 周的收盘价作为我们的训练特征(X),并将这 50 周的 SMA 作为我们的训练标签(Y)。看起来是这样的…
接下来,我们将数据分成两组,训练集和验证集。如果 70%的数据用于训练,那么 30%用于验证。API 返回给我们大约 1000 周的数据,因此 700 周用于训练,300 周用于验证。
训练神经网络
既然训练数据已经准备好,是时候为时间序列预测创建一个模型了,为此我们将使用 TensorFlow.js 框架。TensorFlow.js 是一个用 JavaScript 开发和训练机器学习模型的库,我们可以在 web 浏览器中部署这些机器学习能力。
选择顺序模型,它简单地连接每一层,并在训练过程中将数据从输入传递到输出。为了让模型学习时序数据,创建了递归神经网络 (RNN)层,并在 RNN 中增加了多个 LSTM 细胞。
该模型将使用亚当 ( 研究论文)进行训练,这是一种流行的机器学习优化算法。均方根误差将决定预测值和实际值之间的差异,因此模型能够在训练过程中通过最小化误差进行学习。
下面是上面描述的模型的代码片段,Github 上的完整代码。
- 训练数据集大小(%):用于训练的数据量,剩余数据将用于验证
- 时期:数据集用于训练模型的次数(了解更多信息
- 学习率:每一步训练中的重量变化量(了解更多)
- 隐藏 LSTM 层:增加模型的复杂性,以便在更高维度的空间中学习(了解更多)

Web frontend, showing parameters available for tweaking
单击“开始培训模型”按钮…

User interface showing training model progress
该模型似乎在大约 15 个历元处收敛。
确认
既然模型已经定型,就该用它来预测未来值了,对于我们的情况,它是移动平均值。我们将使用 TFJS 中的 model.predict 函数。
数据被分成两组,训练组和验证组。训练集已用于训练模型,因此将使用验证集来验证模型。由于模型尚未看到验证数据集,如果模型能够预测接近真实值的值,那就太好了。
因此,让我们使用剩余的数据进行预测,这可以让我们看到我们的预测值与实际值有多接近。

The green line denotes the prediction of the validation data, from web demo
看起来模型预测的价格(绿线)与实际价格(蓝线)非常接近。这意味着该模型能够预测该模型看不到的最后 30%的数据。
可以应用其他算法,并使用均方根误差来比较 2 个或更多模型的性能。
预言;预测;预告
最后,模型已经过验证,预测值与其真实值非常接近,我们将使用它来预测未来。我们将应用相同的 model.predict 函数,并使用最后 50 个数据点作为输入,因为我们的窗口大小是 50。由于我们的训练数据每天都在增加,我们将使用过去 50 天作为输入,来预测第 51 天。

Predict the 51st day
为什么我的模特不表演了?
该模型过去从未出现过类似的数据。2020 年 3 月,市场下跌,并在一两个月内恢复,这在历史上从未发生过。该模型很可能无法预测这些时期股票价格的剧烈变化。
我们可以添加更多的功能。一般来说,更多的功能往往会使模型性能更好。我们可以包括交易指标,如移动平均线收敛背离(MACD),相对强弱指数(RSI),或布林线。
增加更多功能。Alpha Vantage API 提供的另一个惊人的 API 是基础数据。这意味着您还可以包括感兴趣的公司的年度和季度损益表和现金流。谁知道呢,这些功能可能会有用。
模型无法学习和预测的原因可能还有很多。这是机器学习的挑战;建立好的表演模型是一门艺术也是一门科学。
结论
除了使用简单的移动平均线,还有许多方法可以进行时间序列预测。未来可能的工作是利用来自各种来源的更多数据来实现这一点。
有了 TensorFlow.js,在网络浏览器上进行机器学习就成为可能,而且这实际上非常酷。
探索 Github 上的演示,这个实验是 100%教育性的,绝不是交易预测工具。
40%的吸尘器,40%的看门人,20%的算命师。
towardsdatascience.com](/data-scientist-the-dirtiest-job-of-the-21st-century-7f0c8215e845) 


Python 中使用动态时间弯曲的时间序列层次聚类
让我们考虑下面的任务:我们有一堆均匀分布的不同长度的时间序列。目标是通过定义数据中呈现的一般模式来对时间序列进行聚类。
在这里,我想介绍一种解决这个问题的方法。我们将使用层次聚类和 DTW 算法作为时间序列的比较度量。该解决方案在人力资源数据(员工历史得分)上运行良好。对于其他类型的时间序列,DTW 函数可能比其他指标更差,如 CID(复杂性不变距离),MAE 或相关性。
我将跳过对层次聚类和 DTW 算法的理论解释,而专注于我为什么选择这样的组合:
- 层次聚类简单、灵活、可调(链接标准),并允许我们不聚类所有轨迹
- DTW 方法让我们可以比较不同长度的时间序列,根据我的经验,它非常适用于不频繁的时间序列
好了,我们开始吧!我们的进口:
import random
from copy import deepcopy
from scipy import interpolate
import numpy as np
from dtaidistance import dtwimport matplotlib.pyplot as pltfrom _plotly_future_ import v4_subplots
import plotly.graph_objects as go
from plotly.subplots import make_subplots
时间序列生成的一些参数和我们的阈值:
- 轨迹数量我们必须聚类的轨迹数量
- 最小轨迹长度和最大轨迹长度任何轨迹的长度下限和上限
- 门槛我们 DTW 的门槛
NUM_OF_TRAJECTORIES = 200
MIN_LEN_OF_TRAJECTORY = 16
MAX_LEN_OF_TRAJECTORY = 40THRESHOLD = 0.50
为简单起见,我们所有的轨迹将位于-1 和 1 之间。此外,我添加了一些平滑。
for item in range(NUM_OF_TRAJECTORIES):
length = random.choice(list(range(MIN_LEN_OF_TRAJECTORY, MAX_LEN_OF_TRAJECTORY + 1)))
tempTrajectory = np.random.randint(low=-100, high=100, size=int(length / 4)).astype(float) / 100
oldScale = np.arange(0, int(length / 4))
interpolationFunction = interpolate.interp1d(oldScale, tempTrajectory)
newScale = np.linspace(0, int(length / 4) - 1, length)
tempTrajectory = interpolationFunction(newScale)
trajectoriesSet[(str(item),)] = [tempTrajectory]
注意,所有轨迹都存储为列表类型的字典值(为了方便,我们将开始把它们组合成组)。出于同样的原因,轨迹的名称存储为元组。
我们的算法如下:
- 我们找到一对最接近的实体(轨迹-轨迹或轨迹-簇或簇-轨迹或簇-簇)
- 如果它们的距离低于阈值,则将它们分组到单个簇中
- 重复步骤 1
- 如果我们在步骤 2 失败或者我们得到一个大的集群,我们就停止我们的算法(所以我们所有的轨迹都进入其中——这意味着我们的阈值非常大)
算法的第一部分:
trajectories = deepcopy(trajectoriesSet)
distanceMatrixDictionary = {}iteration = 1
while True:
distanceMatrix = np.empty((len(trajectories), len(trajectories),))
distanceMatrix[:] = np.nan
for index1, (filter1, trajectory1) in enumerate(trajectories.items()):
tempArray = []
for index2, (filter2, trajectory2) in enumerate(trajectories.items()):
if index1 > index2:
continue
elif index1 == index2:
continue
else:
unionFilter = filter1 + filter2
sorted(unionFilter)
if unionFilter in distanceMatrixDictionary.keys():
distanceMatrix[index1][index2] = distanceMatrixDictionary.get(unionFilter)
continue
metric = []
for subItem1 in trajectory1:
for subItem2 in trajectory2:
metric.append(dtw.distance(subItem1, subItem2, psi=1))
metric = max(metric)
distanceMatrix[index1][index2] = metric
distanceMatrixDictionary[unionFilter] = metric
字典距离矩阵字典帮助我们保持已经计算好的距离。
Numpy 数组 distanceMatrix 在每一步开始时用 np.nan 填充。只需要保持索引对和计算的距离之间的表示。向 distanceMatrixDictionary 添加相同功能后,可能会被删除。
这部分代码允许我们比较所有可能的选项——轨迹-轨迹或轨迹-簇或簇-轨迹或簇-簇:
metric = []
for subItem1 in trajectory1:
for subItem2 in trajectory2:
metric.append(dtw.distance(subItem1, subItem2))metric = max(metric)
上面最后一行— metric = max(metric) —是称为“完全关联”的关联标准。它对我来说更好,但你可以尝试其他标准,甚至定制它。
好了,距离已经计算好了,让我们继续分组。
我们找到最低的距离和一对提供这个距离的指数。
这里为了简单起见,我们将只使用一对(第一对)。甚至,如果我们对于相同的距离有两个、三个或更多对,其余的将在下一次迭代中逐步处理。
minValue = np.min(list(distanceMatrixDictionary.values()))if minValue > THRESHOLD:
breakminIndices = np.where(distanceMatrix == minValue)
minIndices = list(zip(minIndices[0], minIndices[1]))minIndex = minIndices[0]
获得一对索引后,我们只需定义实体名称和值,组合它们,将组合放入字典中,并从字典中删除这些单个实体:
filter1 = list(trajectories.keys())[minIndex[0]]
filter2 = list(trajectories.keys())[minIndex[1]]trajectory1 = trajectories.get(filter1)
trajectory2 = trajectories.get(filter2)unionFilter = filter1 + filter2
sorted(unionFilter)trajectoryGroup = trajectory1 + trajectory2trajectories = {key: value for key, value in trajectories.items()
if all(value not in unionFilter for value in key)}distanceMatrixDictionary = {key: value for key, value in distanceMatrixDictionary.items()
if all(value not in unionFilter for value in key)}trajectories[unionFilter] = trajectoryGroup
之后,我们重复上一步,直到我们没有任何集群。
我已经描述了一般的方法,但是这个算法可以被简化、增强和修改以避免任何重新计算。
结果,我们得到这样的分组:

在这个集群中,我们看到 3 个不同长度的时间序列。它们都有相同的一般模式:前三分之一是局部最小值,后半部分是全局峰值,最后是全局最小值。
更多结果(此处,对于每个聚类,左边的子图表示原始轨迹长度,右边的子图——重新缩放到 MAX_LEN_OF_TRAJECTORY 用于比较):

Cluster #1–2 items

Cluster #2–2 items

Cluster #3–3 items

Cluster #4–3 items

Cluster #5–3 items
根据阈值的值,我们可以使我们的集群更大(更一般化)或更小(更详细)。
如果当前方法在另一个数据集上表现不佳,我们可以改进什么?
- 我们可以尝试用另一种距离度量来代替 DWT
- 我们可以尝试对时间序列进行额外的处理:缩放/重新缩放、平滑或去除异常值
- 我们可以尝试使用不同的阈值
- 我们可以尝试改变联系标准
找到最佳超参数后,可以重构代码并加快计算速度。
这里有可以使用的代码:
https://github . com/avchauzov/_ articles/blob/master/1.1 . trajectoriesclustering . ipynb
Python 中的时间序列—指数平滑和 ARIMA 过程
TL;DR:在这篇文章中,你将学习执行时间序列分析的基本步骤,以及趋势、平稳性、移动平均线等概念。您还将探索指数平滑方法,并学习如何在非平稳数据上拟合 ARIMA 模型。
时间序列随处可见
场景 1:你负责一家披萨配送中心,你想知道你的销售是否遵循特定的模式,因为你觉得每周六晚上你的订单数量都会增加……
场景 2:你的公司正在销售一种产品,而你负责预测,或者说预测,在未来某个特定时刻,这种产品所需的供应……
情况 3:您正在监控一个数据中心,并且想要检测任何异常情况,比如可能导致服务器停机的异常 CPU 使用情况。您跟踪 CPU 使用率的曲线,并想知道何时出现异常…
在每一种情况下,你都在处理时间序列。分析序列是一项迷人的工作,因为尽管有所有的数学模型(包括神经网络),我们人类仍然无法预测未来,并且必须处理不确定性。让我们仔细看看什么是时间序列,可以用哪些方法来分析它们。在本文中,我们将广泛依赖于用 Python 编写的【stats models】库。
时间序列是按时间排序(或索引)的数据序列。它是离散的,每个点之间的间隔是常数。
系列的性质和类型
趋势 :数据的长期增减。这可以被看作是粗略穿过数据的斜率(不必是线性的)。
季节性 :当一个时间序列受到季节性因素(一天中的某个小时、一周、一月、一年等)的影响时,称之为季节性的。).季节性可以通过固定频率的良好循环模式来观察。
周期性 :当数据呈现非固定频率的上升和下降时,出现一个周期。这些波动通常是由经济条件造成的,而且往往与“商业周期”有关。这些波动的持续时间通常至少为两年。
残差 :每个时间序列可以分解成两部分:
-一个预测,由一个或几个预测值*
-残差。它们是每个时间步的观测值和预测值之间的差值。记住这一点*
t 时刻序列值= t 时刻预测值+t 时刻残差
**
Left: Series with a trend. Right: Series exhibiting seasonal behavior
**
Left: Cyclical series. Right: Random walk
时间序列的分解
每个时间序列都可以看作是几个部分的混合:
- 趋势(曲线长期向上或向下移动)
- 季节性成分
- 残差
下面是我们的时间序列分解成上述部分后的样子:

我们的时间序列显示出明显的上升趋势。它不是季节性的,你可以看到季节性的部分看起来很难看。残差的方差似乎随着时间的推移而增加,表明序列在结束时表现出更多的随机行为。
黄金法则:平稳
在我们进一步分析之前,我们的系列必须使 静止。
平稳性 是展现恒定统计性质(均值、方差、自相关等)的性质。).如果时间序列的平均值随着时间的推移而增加,那么它就不是稳定的。
用于静态化数据的转换:
- 去趋势 :我们去除序列中的潜在趋势*。这可以通过多种方式实现,具体取决于数据的性质:
- 指数化数据:以货币计量的数据与价格指数挂钩或与通货膨胀相关。因此,将序列除以该指数(即缩减)是去除数据趋势的解决方案。
- 非指数型数据:是否需要估计趋势是常数、线性还是指数型。前两种情况很容易,对于最后一种情况,有必要估计增长率(通货膨胀或通货紧缩),并应用与指数化数据相同的方法。*
- 差分 :可以通过减去周期值来去除季节性或周期性模式。如果数据是 12 个月的季节性数据,用 12 个滞后的差值序列减去该序列将得到一个“更平”的序列
- 日志 :在趋势中的复合率不是由于某个价格指数(即序列不是以货币计量的)的情况下,日志可以帮助线性化一个具有指数趋势的序列(回想一下 log(exp(x)) = x)。与通缩不同,它并没有消除任何最终趋势。
检查平稳性
绘制滚动统计数据
绘制滚动平均值和方差是直观检查我们系列的第一个好方法。如果滚动统计显示出明显的趋势(向上或向下)并显示出变化的方差(增加或减少幅度),那么您可能会得出结论,该序列很可能不是平稳的。

扩充迪基-富勒试验
该检验用于评估时间序列是否是平稳的。不必深入假设检验的太多细节,你应该知道这个检验将给出一个叫做“检验统计”的结果,根据这个结果,你可以用不同的置信水平(或百分比)来判断时间序列是否平稳。

KPSS
KPSS(科维亚特科夫斯基-菲利普斯-施密特-申)检验测试的是序列是趋势平稳的零假设。换句话说,如果检验统计量的 p 值低于 X%置信度阈值,这意味着我们可以拒绝这个假设,并且序列不是具有 X%置信度的趋势平稳序列。高于阈值的 p 值将使我们接受这一假设,并得出序列是趋势平稳的结论。
自相关图(ACF 和 PACF)
自相关 (ACF)图表示具有自身滞后的序列的自相关。
偏自相关 (PACF)图表示一个序列和其自身滞后之间的相关量,该相关量不能用所有更低阶 - 滞后的相关来解释。理想情况下,我们不希望序列与其自身的滞后之间存在相关性。从图形上来说,我们希望所有的尖峰都落在蓝色区域。

正如我们所见,蓝色区域上方有几个尖峰,这意味着在滞后 1、2、3 和 4 处存在相关性。
选择模型
指数平滑法适用于非平稳数据(即具有趋势的数据和季节性数据)。
ARIMA 模型应该只用于静态数据。因此,应该去除数据的趋势(通过缩减或记录),然后查看有差异的序列。
平滑方法
平滑方法作为加权平均值工作。预测是过去观察的加权平均值。权重可以是统一的(这是一个移动平均值),或者遵循指数衰减-这意味着给予最近的观察更多的权重,给予旧的观察更少的权重。更高级的方法包括预测中的其他部分,如季节性成分和趋势成分。
我们将使用数学方程的分量形式。 y 表示我们的时间序列, p 表示我们的预测, l 表示水平, s 表示季节性成分, b 表示趋势成分
简单指数平滑
>什么时候使用?
数据点少,数据无规律,无季节性或趋势性。
>数学背后 只要记住 SES 只有一个组件叫做 level (下面用“alpha”表示平滑参数)。是前一级和当前观测值的加权平均值:

霍尔特线性平滑
>什么时候使用? 数据中的趋势,无季节性。
数学背后 预测由一个水平分量和一个趋势分量组成。:
**
霍尔特阻尼趋势
霍尔特的线性趋势法的问题是,趋势在未来是恒定的,无限增加或减少。对于长期预测来说,这可能是个问题。因此,阻尼趋势法是一种添加阻尼参数的方法,以便趋势在未来收敛到恒定值(它使趋势变平)。参数𝑏由𝜙𝑏代替
>什么时候使用?
数据有趋势。使用乘法版本,除非之前已经记录了数据。在这种情况下,使用附加版本

Notice how the green curve flattens at the end of the forecast
霍尔特-温特季节平滑法
这将在下一篇文章的中讨论。但你要知道,这种方法就像霍尔特的线性平滑,除了我们增加了一个季节的成分!
ARIMA
ARIMA 模型(包括 ARMA、AR 和 MA 模型)是预测平稳时间序列的一类通用模型。ARIMA 模型由三部分组成:
- 序列((AR)部分)的滞后 值 的加权和**
- 序列(()MA)的滞后 预测误差 的加权和
- 一个 差 的时间序列((I)部分)
一个 ARIMA 模型通常被标注为【p,d,q】其中 p 表示 AR 部分、 d 差分的顺序(I部分),而 q 表示 MA 项的顺序。
1)选择差分阶数
拟合 ARIMA 模型的第一步是确定差分阶数以平稳化序列。为此,我们来看看 ACF 和 PACF 图,并记住这两条规则:
”—规则 1:如果序列对大量滞后具有正自相关,那么它可能需要更高阶的差分。
—规则 2:如果 lag-1 自相关为零或负值,或者自相关都很小且无模式,则序列不需要高阶差分。如果滞后-1 自相关为-0.5 或更负,则该系列可能有过度差异。 (罗伯特·诺,统计预测)
我们从记录数据开始,因为原始数据呈现指数趋势:

记录的序列似乎更平坦,但它是平稳的吗?让我们计算一个 KPSS 测试来检验这一点:

检验统计量高于临界值,我们拒绝零假设,我们的序列是而不是趋势平稳的。然而,为了使这篇文章简短,我们将继续好像它是。
(—为了得到一个趋势稳定的序列,我们可以考虑线性回归我们的对数序列,并用回归系数除我们的序列...— )
现在让我们来看看记录的一阶差分数据的 ACF 图:

“ACF —记录的数据”图表显示了非平稳数据,其特征是峰值缓慢线性衰减(参见上述规则 1)。添加一阶差会在滞后值 1 处产生单个负尖峰。根据规则 2,我们不需要进一步区分这个系列。让我们通过比较(0,0,0)和(0,1,0) ARIMA 模型来检查我们的结果:
****
ARIMA(0,1,0)的阿凯克信息标准(AIC)较低,这意味着该模型的表现优于 ARIMA(0,0,0)。让我们看看残差并检查它们的方差:

Which residuals do you think look better ?
2)选择移动授权订单
现在我们知道我们必须在模型中包含一阶差分,我们需要选择移动平均阶。这是通过查看差分序列来完成的(因为我们刚刚看到一阶差分序列是平稳的)。同样,我们看看我们的 ACF 和 PACF 图,记住这条规则:
“如果差分序列 ACF 的滞后-1 自相关为负,和/或存在锐截止,则选择顺序为 1 的 MA ”。
问:为什么选择 1 阶而不是更高阶的移动授权?因为我们会一步一步来。如果我们在更高的滞后下观察自相关,并且通过查看我们的(1,1,0)模型的自相关残差,我们仍然观察到这些尖峰,我们可以增加我们的 MA 阶数,尽管通常不建议超过 2!



注意 AIC 是如何再次下降的,残差方差是如何减小的。这表明我们的(1,1,0) ARIMA 比(0,1,0)模型表现得更好!
3)选择应收账款订单
现在你可能会想:我们有必要添加一个 AR 术语吗?答案是否定的。事实上,在以下情况下,您应该添加一个 AR 术语:
如果差分序列 PACF 的滞后-1 自相关为负,和/或有一个锐截止,那么选择一个为 1 的 AR 阶。
在我们的例子中,我们在 ACF 和 PACF 中都观察到负的滞后-1 自相关。请注意,差分序列的 PACF 在滞后 1 和滞后 2 处显示了两个负峰值,这意味着理论上我们可以将 AR 阶数提高到 2。

这是我们通过拟合(1,1,1) ARIMA 得到的结果:
****
添加 AR 项降低了 AIC,方差从 0.155 降到了 0.145,我们做得很好!我们应该增加一个 AR 项并选择一个(2,1,1) ARIMA 吗?让我们来看看 ARIMA(1,1,1)残差的 ACF & PACF:

图中没有显著的自相关滞后值,我们的模型似乎不需要任何额外的 AR 项。你可能会指出第 12 阶段的峰值:这可能是季节性的迹象。我们将在的下一部分中与萨里玛和萨里马克斯一起探讨这个问题。
绘制预测
幸运的是,statsmodels 有一个很好的 API,允许我们从 ARIMA 过程中绘制预测。我强烈建议您将数据放在带有 DateTimeIndex 的 DataFrame 中,因为 plot_predict() 方法确实喜欢日期…
在这种情况下,我们将选择 12 个预测步骤,并将 dynamic 关键字设置为 True:这将强制算法使用其自己的预测值作为未来预测的滞后值:

让我们看看更大的预测窗口(34 个预测步骤):

那都是乡亲们!在下一部分的中,我将讨论季节性 Holt-Winter 和季节性 ARIMA。希望你喜欢:)
****附加讲座:
如果你对时间序列预测和分析感兴趣,我强烈推荐下面两个:
- 预测、原理与实践(Hyndman&Athanasopoulos)
- 【罗伯特·诺】****
你也可以查:
如果你想知道 2019 年哪支球队真的是最好的 NBA 球队,请查看 这篇文章 !
Python 中的时间序列—第 2 部分:处理季节性数据
在 第一部分 中,你学习了趋势和季节性、平滑模型和 ARIMA 过程。在这一部分中,您将学习如何处理季节性模型,以及如何实现季节性 Holt-Winters 和季节性 ARIMA (SARIMA)。
获取数据
我们将使用“每月牛奶产量”数据:

季节分解
在上一篇中,我简单讲过季节分解。季节性分解的思想是,任何序列都可以分解为三个部分的总和(或乘积):趋势、季节性成分和残差。

在我们的例子中,我们将使用 statsmodels 提供的季节性分解函数:

趋势分量是一条增长曲线,似乎达到了一个平稳状态,并最终在终点下降。这是一个有用的信息,当我们将消除趋势,以稳定的数据。
将数据固定化
应对趋势
基于我们的分解,我们看到趋势是跟随一个向上的运动,然后在最后达到稳定状态(或者下降)。为了消除这种趋势,我们将尝试一种新颖的方法,即回归 STL 分解给出的趋势。然后,如果回归令人满意,我们将尝试通过从原始序列中减去获得的回归来“缩小”序列。

我们回归的 r 平方系数相当好(0.988),但是查看残差,我们注意到它们的方差从左到右增加。这是异方差的标志。您可以自己查找确切的定义,只要记住这并不好,我们的模型中缺少了一些东西。我们将放弃回归趋势的想法,因为它现在需要太多的努力。
应对趋势,第 2 页
我们的系列仍然需要站化,我们将回到基本方法,看看我们是否可以消除这种趋势。我们将分几个步骤操作:
- 对原始数据进行 ADF 测试以检查平稳性
- 12 个月差异的 ADF 测试
- 对记录数据的 12 个月差异进行 ADF 检验
- 对减去 12 个月移动平均值的数据进行 ADF 测试
如果您需要代码,请参考第一部分,了解如何进行 ADF 测试

让我们用 KPSS 检验来确认数据减去 12 个月的均线是平稳的:

测试统计低于阈值,因此我们的序列是平稳的(回想一下,对于 KPSS 测试,零假设是序列是平稳的)。
霍尔特-温特季节平滑模型的拟合
记得从第一部分得知,霍尔特-温特的模型有几个部分:一个 水平 ,一个 趋势 ,在季节性平滑的情况下,一个 季节性 成分。这背后的数学有点难,所以我不会把它放在这里,只要记住上面的三个组成部分。以下是我们拟合模型后得到的结果:

没有阻尼的模型似乎表现更好,因为 AIC 更低。
季节性 ARIMA
老 ARIMA 又回来了,但这一次我们将为它添加季节性元素!SARIMA 模型由两部分组成:非季节性部分和季节性部分。如果你还记得上一部分,非季节性部分由 AR(p)项、MA(q)项、I(d)项组成,我们写 ARIMA (p,d,q)。季节性的部分也是一样的!
我们的舍利玛是指 ARIMA (p,D,q)x(P,D,Q)。
问题:我们如何确定所有这些 P,D,Q,P,D,Q?
每当你听到“ARIMA”,就想到“ACF/PACF”。
有了 ACF 和 PACF 图,我们将能够猜测我们的参数的合理值。让我们绘制我们的静态化数据的 ACF 和 PACF 图:

鉴于在 ACF 中观察到的尖峰信号的缓慢衰减,数据显然不是稳定的。这是一个信号,表明我们应该对 x: 取一个额外的差值

我们的系列现在是静止的。总而言之,我们有:
- 取平稳序列的 12 个滞后差。这相当于“一个季节滞后”的差异。
- 取 12 滞后差分序列的 1 滞后差分。这对应于 1 的非季节性差序。
这给了我们一个萨里玛(?, 1, ?)x(?, 1, ?).
AR 和 MA 术语呢?
嗯,我们知道在 ACF 和 PACF 中仍然有显著的峰值,所以我们可以决定添加 AR 术语和 MA 术语。我们应该从哪一个开始?这一次,我们将使用网格搜索 AR 和 MA 术语的可能组合(最大顺序限制为 2)…
当运行不同的配置时,使用 SARIMA(0,1,2)x(0,1,2)可以获得最低的 AIC。

使用plot _ diagnotis()命令,我们可以显示残差并检查它们的正态性(记住,残差应该是正态分布的(零均值和一元方差)并且不相关)。

请注意正态 Q-Q 图和直方图如何显示我们的残差遵循正态分布(我们可以使用额外的测试来测试正态性,如 Ljung-Box)。相关图还显示残差是不相关的!
附加讲座:
如果你对时间序列预测和分析感兴趣,我强烈推荐下面两个:
- 预测、原理与实践 (海德曼& Athanasopoulos)
- (罗伯特·诺)
你还可以查看 这篇文章 关于神经图灵机和 这篇文章 关于基于注意力的神经网络!
Python 中的时间序列第 3 部分:用 LSTMs 预测出租车出行
在本文中,我们将使用 LSTMs 预测纽约的 FHV 数量(如优步出租汽车)。我们将学习如何使用蒙特卡洛法将置信区间添加到我们的预测中。

Photo by Lexi Anderson on Unsplash
介绍
LSTM(Long Short Memory)是一种 a 型递归神经网络(RNN)架构,由 Sepp Hochreiter 和 Jürgen Schmidhuber 于 1997 年提出。rnn 是专门设计用于通过递归机制处理顺序数据的深度神经网络。它们以一种自回归的方式表现,因为它们通过内部状态来跟踪过去(因此是“记忆”部分)。它们被广泛用于语音识别、机器翻译、语音合成等。但是当用于时间序列时,LSTMs 值多少呢?假设可用数据的规模足够大,它们可以被证明对非线性关系的建模非常有用..
优步用例:贝叶斯预测
在找用 LSTMs 实现时间序列预测的论文时,找到了优步 2017 年写的一篇论文,优步对时间序列的深度自信预测。这篇论文背后的基本问题是:我们有多大信心(即我们如何量化不确定性)用 LSTMs 进行预测?
优步开发的方法是编码器-解码器(用作自动编码器)和完全连接的前馈网络的混合,用于根据以前的数据预测城市的出行次数,或实时检测异常。

The Uber LSTM forecasting architecture (Zhu & Laptev, 2017)
优步的论文是最先使用贝叶斯方法进行时间序列预测的论文之一。如果你想了解更多关于贝叶斯神经网络和贝叶斯推理的知识,可以看看下面的链接:
- 让你的神经网络说不知道
- 辍学为贝叶斯近似
- 深度贝叶斯神经网络
- 黑客的贝叶斯方法,卡梅隆·戴维森-皮隆
贝叶斯神经网络
简而言之,贝叶斯神经网络估计每个权重的概率分布,而经典神经网络试图找到每个权重的最佳值。听到“贝叶斯”,就想到“概率分布”。
——但是预测不确定性和贝叶斯网络有什么联系呢?
想象两个气象专家,鲍勃和爱丽丝。你们都知道他们很擅长预测天气温度,但有时他们也会弄错。你问他们明天早上 8 点的温度是多少,这样你就可以知道你是否需要穿上外套。
鲍勃说:“将会是 15.6 摄氏度”。爱丽丝说:“我有 95%的把握气温会在 16 到 18 摄氏度之间”。虽然他们似乎不同意,但你会相信谁呢?
就我个人而言,我相信爱丽丝有两个原因:
- 她给了我一个信心区间。当有人能够告诉我一些事情以及他/她对这些信息有多自信时,我会感到更加放心。
- 我并不在乎确切的温度,因为 1 摄氏度的温差不会影响我穿上外套的决定。
然而,如果 Alice 告诉我“我 95%确定温度将在 0°C 到 18°C 之间,我会说虽然她给了我一个信心水平,但这个区间太大了,无法提供信息……
BNN 框架下的不确定性
我们通常将不确定性分为 3 类: 模型不确定性 , 固有噪声 , 模型误设定 。前两个是最著名的,通常被称为和 任意 不确定性。
模型(或认知)不确定性是关于我们的模型参数的不确定性。数据越多,就越能解释(即“减少”)这种不确定性。噪声(或任意性)不确定性是指观测值中的噪声。如果所有样本的噪声不确定度都是常数,我们称之为 同方差 不确定度。否则,如果一些样本比其他样本更不确定,我们将使用术语 异方差随机变量 。噪声不确定性不能随着更多的数据而减少。
在优步的论文中,使用了第三种不确定性:模型设定错误。这种不确定性旨在“在预测与训练数据集有很大不同的模式的未知样本时捕捉不确定性”。
— 现在为什么要区分所有这些不确定性 ?
嗯,正是因为有些可以用更多的数据(模型/认知)来对抗,而有些不能。因此,一些研究人员认为,考虑到即使有更多的数据也无法减少随机不确定性,关注随机不确定性更有意义( Kendall & Gal,2017 )
在本文中,为了简单起见,我们将只关注模型的不确定性。优步使用不同的算法来评估另外两种不确定性,但是研究它们超出了本文的范围。
获取和准备数据
论文中的作者使用美国 8 个城市 4 年的数据来训练他们的模型。3 年用于培训,1 年用于测试。不幸的是,优步还没有发布这个数据,但是为了重现他们论文的结果,我们将使用纽约开放数据门户上的可用数据。我们选取了三年的数据,时间跨度从 2015 年初到 2018 年年中。每天对数据进行重新采样。这是完整数据的样子

平稳性
如果你习惯于分析时间序列,我们可以注意到一些你应该熟悉的东西:
- 我们观察到明显的上升趋势
- 均值和方差随时间增加
- 我们还观察到可能由外部事件(节假日和天气)引起的峰值。)
前两个要点表明我们的系列显然不是一成不变的。后者表明我们可能需要将外部数据合并到我们的系列中。平稳性可以用扩展的迪基-富勒测试或 KPSS 测试来检验。那么我们应该像对 ARIMA 模型那样进行这些测试吗?
—答案是:不一定。
当我们平稳化一个序列时,我们想要的是在整个时间内均值和方差不变。这保证了如果你取一个 N 点样本进行预测,并用另一个 N 点不同的样本重复这一过程,那么你的 N 点样本和你试图预测的 N+1 点之间的关系是相同的(即它们来自相同的分布)。如果均值和方差不相等,那么您是从不同的分布中抽取样本来进行预测,您的模型肯定无法进行概括。
与 ARIMA 不同,rnn 能够模拟数据中的非线性关系。
rnn,尤其是 LSTM 和 GRU,能够捕捉长期依赖关系(前提是你有足够多的数据!).因此,去趋势化和去季节性之类的问题不那么重要,但你应该经常问自己:
我用于测试的数据是否遵循与我用于训练的数据相同的行为(即来自相同的分布)?
假期和天气
添加假日指示非常简单。我们使用 Python 中的 holidays 库来获取 2015 年到 2018 年的假期日期。
在我们的系列中添加了一个假日布尔之后,我们仍然观察到无法解释的峰值…
在互联网上快速浏览显示,其中几天实际上是纽约州遭受暴风雪等极端天气事件袭击的日子。
我们在下面的图表中用红色标出了节假日,绿色标出了极端天气事件:

因此,在我们的数据框架中,我们有一个“计数”列,一个“是 _ 假日”列,一个“是 _ 恶劣天气”列。但是,假设我们要进行预测,我们需要“预测”这些日期,就像我们对未来预测一样,因此我们将创建两个额外的列,指示第二天是假日或第二天预计会出现极端天气:
*weather = [datetime.datetime.strptime(date, "%Y-%m-%d") for date in ['2018-01-04', '2018-03-21','2017-03-14','2017-02-09','2016-01-23']]holidays = [date for y in range(2015, 2019) for date, _ in sorted(holidays.US(years=y).items())]df['is_holiday'] = np.where(df.index.isin(holidays), 1, 0)
df['bad_weather'] = np.where(df.index.isin(weather), 1, 0)
df['next_is_holiday'] = df.is_holiday.shift(-1)
df['next_bad_weather'] = df.bad_weather.shift(-1)*
选择窗口大小和回测
做时间序列预测时,你可能会听说 回测 。回溯测试是在训练过程中使用的一个程序,它包括以递增的方式将数据分割成块。在每一次迭代中,一个块被用作你的训练集。然后你试着在你的块之前预测一个或多个值。可以使用两种方法,展开和滑动窗口:

source: https://www.datapred.com/blog/the-basics-of-backtesting
在我们的案例研究中,作者使用由步长等于 1 的 28 天滑动窗口组成的样本,用于预测下一个值(提前 1 步预测)。
记录和缩放
在论文中,作者首先采用数据的对数来“减轻指数效应”。然后,他们在每个窗口中减去窗口的第一个值,以消除趋势,并根据窗口第一个值的波动来训练网络(等式(1)* )。也可以想到其他方法,例如减去第一值并除以第一值(等式(2) )😗

构建数据集
我们的数据集将是一个生成器,产生一批滑动窗口(每一批都是在未来移动 1 个值的前一批)。为了遵循论文的说明,我们还将在每一批中从所有其他值中减去第一个值。然后,每批样本被分为 28 天样本和 1 天目标样本。
定义模型
我们将使用 PyTorch 来定义我们的模型。一个简单的原因是,我们将在推理过程中使用 dropout,并且它很容易在 PyTorch 中实现。我们将从使用一个简单的 LSTM 网络开始,如论文中所定义的:1 个具有 128 个单元的 LSTM 层,1 个具有 32 个单元的 LSTM 层,以及一个具有 1 个输出的全连接层。在每一层之后添加漏失。
——中途辍学者 中途辍学可以被看作是做贝叶斯推理的一种方式(尽管围绕这一点还有争论)。从技术上讲,退出是神经网络中使用的过程,包括随机退出单元(以及它们的连接)。
随机打开和关闭神经元的事实大致相当于执行伯努利分布的采样,因此“模拟”了贝叶斯神经网络的机制(其中权重是分布,而不是单个值)。应用 dropout 有点像我们从网络中“取样”。如果我们在推理过程中多次重复这个过程,我们将得到不同的预测,用这些预测我们可以估计一个分布,最终,不确定性!总而言之:

现在,让我们通过在每个 LSTM 层之间添加下降层来定义模型(注意 train 如何设置为 True,以便在训练和测试期间使用下降)
培养
我们用 Adam 优化器和学习率设置为 0.001,batch_size 为 1,训练 5 个时期。
结果:

Fitted values on the train set
测试— 1 天预测范围
本文的主要兴趣之一是不确定性的估计。
具体而言,在每个隐藏层之后应用随机漏失,并且模型输出可以近似地视为从后验预测分布生成的随机样本。因此,可以通过几次重复的模型预测的样本方差来估计模型的不确定性。
因此,本文背后的想法是用随机漏失运行几次模型,这将产生不同的输出值。然后,我们可以计算输出的经验均值和方差,以获得每个时间步长的置信区间!
对于每一步,我们预测 100 个值。所有的值都是不同的,假设我们保持辍学集。这使我们能够模拟从我们的网络中采样(事实上,辍学与贝叶斯神经网络密切相关,因为通过随机断开权重,它模拟了一种概率分布)。我们将这 100 个值的平均值作为我们的预测平均值,并将这 100 个值的标准偏差用于我们的置信区间。假设我们的预测来自正态分布 N ( μ ,σ)——均值 μ 等于我们的经验均值,标准差 σ 等于我们的经验标准差——那么我们可以估计置信区间。在我们的例子中,它由下式给出:
**
Predicted values and uncertainty intervals
预测和测试曲线似乎非常接近!然而,我们需要找到一个度量标准来查看我们的模型表现如何。
如果我们查看 95%预测区间的经验覆盖率(即预测的 95%置信区间中包含的真实测试值的数量),我们会获得 28.51%的值,与论文中测试集上获得的值相差甚远……当我们取 99% CI 时,该值会上升到 44%覆盖率。这不是一个很好的结果,但请记住,我们的置信区间很小,因为我们只预测模型的不确定性…
测试— 7 天预测范围
单日预测的结果对于预测模型来说并不太好,而且我们对模型的要求并不高,因为我们要求的是一个非常短的预测范围。如果我们训练我们的模型来预测更大范围的预测会怎么样?
结论
lstm 因其捕捉长时间相关性的能力而显示出建模时间序列的有趣前景,但应仅用于大型数据集。永远不要期望你的 RNN 在 100 个样本的数据集上给出好的结果!神经网络中的参数数量和可用数据大小之间的平衡对于避免过度拟合非常重要。优步论文的作者之一尼古拉·拉普捷夫总结说:
经典模型最适合:
○短的或不相关的时间序列
○已知的世界状态神经网络最适合:
○大量时间序列
○长时间序列
○隐藏交互
○解释不重要
时间序列机器学习分析和需求预测与 H2O 和 TSstudio
我如何使用机器学习来实现每周收入的时间序列预测

Photo by Ben Elwood on Unsplash
传统的时间序列分析和预测方法,如、 霍尔特-温特斯指数平滑 、ARMA/ARIMA/萨里玛 和 ARCH/GARCH ,已经建立了几十年,并在商业和金融(例如预测股票价格和分析金融市场的趋势)
最近,开源框架的普及和更广泛的可用性,如 Keras 、 TensorFlow 和 scikit-learn 帮助机器学习方法,如 【随机森林】 、 极端梯度提升、 时间延迟神经网络 这些技术允许通过一组时间延迟将历史信息作为输入引入模型。
与更传统的方法相比,使用机器学习模型的优势在于,它们可以有higher predictive power,尤其是当预测器与响应有明确的因果联系时。此外,它们可以处理大量输入的复杂计算。
不过,它们往往有wider array of tuning parameters,一般都是more complex比【经典】型号多,而且可以expensive来上手,无论是计算能力还是时间。更重要的是,他们的black box本性使得他们的输出更难解释,并催生了不断增长的 机器学习可解释性 (我不打算触及这一点,因为这超出了项目的范围)
项目结构
在这个项目中,我将详细解释用机器学习模型对时间序列数据建模所需的各个步骤。
其中包括:
- 探索性时间序列分析
- 特征工程
- 模型训练和验证
- 模型性能对比及预测
特别是,我使用TSstudio来执行“传统的”时间序列探索性分析来描述时间序列及其组成部分,并展示如何使用我收集的洞察力来为机器学习管道创建特征以最终生成每周收入预测。
对于建模和预测,我选择了高性能、开源的机器学习库。我正在安装各种机器学习模型,例如广义线性模型、梯度推进机器和随机森林,并且还使用 AutoML 进行自动机器学习,这是H2O库最令人兴奋的特性之一。**
数据
**library(tidyverse)
library(lubridate)
library(readr)
library(TSstudio)
library(scales)
library(plotly)
library(h2o)
library(vip)
library(gridExtra)**
我在这里使用的数据集附带了一个红皮书出版物,可以在附加资料部分免费下载。这些数据涵盖了样本户外公司的销售额orders,这是一家虚构的 B2B 户外设备零售企业,并提供了他们销售的products以及他们的客户(在他们的案例中是retailers)的详细信息。由于它的人工性质,这个系列呈现了一些古怪和怪癖,我将在整个项目中指出这些。
在这里,我只是加载已编译的数据集,但如果你想继续,我也写了一篇名为加载、合并和连接数据集的文章,其中我展示了我如何组装各种数据馈送,并整理出变量命名、新功能创建和一些常规内务任务等内容。
**# Import orders
orders_tmp <-
read_rds("orders_tbl.rds")**
你可以在我的 Github 库上找到完整的代码。
初步探索
时间序列数据有一组独特的特征,如时间戳、频率和周期/时期,它们在描述性和预测性分析中都有应用。r 提供了几个类来表示时间序列对象(xts和zoo仅举几个主要的例子),但是为了涵盖这个项目的描述性分析,我选择了使用ts类,它由TSstudio库支持。****
TSstudio附带了一些非常有用的功能,用于时间序列对象的交互式可视化。我真的很喜欢这个库使用作为它的可视化引擎!**
首先,我选择我的分析所需的数据(在本例中是order_date和revenue,并将其聚合为一个周频率。我用一个_tmp后缀来标记这个数据集,表示它是一个临时版本,在它可以使用之前还需要一些步骤。**
**revenue_tmp <- orders_tmp %>%
# filter out final month of the series, which is incomplete filter(order_date <= "2007-06-25") %>%
select(order_date, revenue) %>%
mutate(order_date =
floor_date(order_date,
unit = 'week',
# setting up week commencing Monday
week_start = getOption("lubridate.week.start", 1))
) %>%
group_by(order_date) %>%
summarise(revenue = sum(revenue)) %>%
ungroup()revenue_tmp %>% str() ## Classes 'tbl_df', 'tbl' and 'data.frame': 89 obs. of 2 variables:
## $ order_date: Date, format: "2004-01-12" "2004-01-19" ...
## $ revenue : num 58814754 13926869 55440318 17802526 52553592 ...**
这个系列跨越了3&1/2 年的销售额orders,所以我应该期望至少有 182 个数据点,但是只有 89 个观察值!
让我们仔细看看发生了什么:
**revenue_tmp %>% head(10) ## # A tibble: 10 x 2
## order_date revenue
## <date> <dbl>
## 1 2004-01-12 58814754\.
## 2 2004-01-19 13926869\.
## 3 2004-02-09 55440318\.
## 4 2004-02-16 17802526\.
## 5 2004-03-08 52553592\.
## 6 2004-03-15 23166647\.
## 7 2004-04-12 39550528\.
## 8 2004-04-19 25727831\.
## 9 2004-05-10 41272154\.
## 10 2004-05-17 33423065.**
这里需要注意一些事情:这个系列呈现出一种不同寻常的每周模式,平均每月记录两次销售。此外,2004 年的第一周没有任何销售记录。
为了使用ts对象进行时间序列分析,我需要确保我每年有整整 52 周的时间,这也应该包括没有销售额的几周。
所以在将我的数据转换成一个ts对象之前,我需要:
- 在系列开始处增加 1 次观察以确保第一年包括 52 次每周观察
- 一切都是按时间顺序排列的。这一点尤其重要,因为输出可能无法正确映射到序列的实际索引,从而导致不准确的结果。
- 填补不完整日期时间变量的空白。
padr库中的pad函数为每个缺失的时间点插入一条记录(默认填充值为 NA) - 用零替换缺失值,因为空周没有销售记录。来自
padr库的fill_by_value函数对此有所帮助。
**revenue_tbl <-
revenue_tmp %>%
rbind(list('2004-01-05', NA, NA)) %>%
arrange(order_date) %>%
padr::pad() %>%
padr::fill_by_value(value = 0)revenue_tbl %>% summary() ## order_date revenue
## Min. :2004-01-05 Min. : 0
## 1st Qu.:2004-11-15 1st Qu.: 0
## Median :2005-09-26 Median : 0
## Mean :2005-09-26 Mean :24974220
## 3rd Qu.:2006-08-07 3rd Qu.:52521082
## Max. :2007-06-18 Max. :93727081**
现在我可以看看周收入,我的反应变量
**revenue_tbl %>%
ggplot(aes(x = order_date, y = revenue)) +
geom_line(colour = 'darkblue') +
theme_light() +
scale_y_continuous(labels = scales::dollar_format(scale = 1e-6,
suffix = "m")) +
labs(title = 'Weekly Revenue - 2004 to June 2007',
x = "",
y = 'Revenue ($m)')**

如前所述,该系列是人为生成的,并不一定反映现实生活中会发生什么。如果这是一个实际的分析咨询项目,我肯定会质疑我的客户每周的销售频率。
但假设这是真实的交易,这里的挑战是构建一个经过深思熟虑选择的有意义的特征,并在几个机器学习模型上测试它们,以找到一个能够产生良好预测的模型。
挑战除外!
探索性分析
在这一部分,我将探索时间序列,检查其组成部分和季节性结构,并进行相关性分析,以确定该序列的主要特征。
在将我的系列转换成一个ts对象之前,我需要定义系列的start(或end)参数。我希望从一年的第一周开始计算周数,这样可以确保所有事情都符合ts框架。
**start_point_wk <- c(1,1) start_point_wk
## [1] 1 1**
我通过选择响应变量(revenue)作为数据参数并指定 52 周的频率来创建ts对象。
**ts_weekly <-
revenue_tbl %>%
select(revenue) %>%
ts(start = start_point_wk, frequency = 52)ts_info(ts_weekly) ## The ts_weekly series is a ts object with 1 variable and 181 observations
## Frequency: 52
## Start time: 1 1
## End time: 4 25**
用ts_info()函数检查系列属性显示,该系列是一个包含 1 个变量和 181 个观察值的每周ts对象。
时间序列组件
现在让我们借助TSstudio的图形功能来绘制我们的时间序列。
ts_decompose将序列分解为其元素:趋势、季节性和随机成分。
**ts_decompose(ts_weekly, type = 'additive')**

- 趋势:该系列似乎没有周期性成分,但显示出明显的上升趋势。趋势可能不是线性的,我将通过在特性中包含一个平方趋势元素来捕捉这一点。****
- 季节性:这个情节显示了一个明显的季节性模式,我将在接下来探究。**
- 随机:随机成分看起来是随机分布的。**
季节性成分
现在让我们放大这个系列的季节性部分
**ts_seasonal(ts_weekly, type = 'normal')**

尽管有 12 个不同的“峰值”(一年中的每个月一个),但该图并不表明存在典型的季节性。然而,除了极少数例外,销售记录在每年的同一周,我将尝试用一个特征变量来捕捉这种规律性。
相关分析
自相关函数(ACF) 描述了序列与其滞后之间的相关程度。
由于手头的系列的奇怪性质,AC 图不是很容易阅读和解释:它表明存在滞后结构,但由于系列中的噪声,很难拾取有意义的模式。
**ts_acf(ts_weekly, lag.max = 52)**

然而,我可以利用滞后可视化和玩滞后数字,以确定序列和它的滞后之间的潜在相关性。
在这种情况下,将周数与季度频率对齐显示了与季度滞后的明显的线性关系。为简单起见,我将只在模型中包括滞后 13 ,以控制上一季度销售水平的影响。
**ts_lags(ts_weekly, lags = c(13, 26, 39, 52))**

使用相同的技巧揭示了与第一年滞后的强线性关系。同样,我将在模型中只包括一个滞后 52 。
ts_lags(ts_weekly, lags = c(52, 104, 156))

探索性分析总结
- 该系列的购买频率为两周一次,两周一次,没有典型的季节性。然而,除了极少数的例外情况,每年的销售额都大致记录在同一个星期。****
- 该系列似乎没有周期性成分,但显示出明显的上升趋势以及潜在的非线性趋势。
- 由于数据嘈杂,ACF 很难解释,但滞后图暗示了年度和季度滞后结构。
系统模型化
****建模和预测策略是:
- 使用 Q1 2007 训练并交叉验证 Q1 2007 之前的所有车型,并比较其样本内预测性能。
- 假设我没有 Q2 2007 的数据,使用所有合适的模型生成该期间的预测,并将它们的预测性能与 Q2 2007 实际值进行比较
下面是该策略的可视化表示。我从经验中发现,用一个好的形象化来支持解释是一个让你的观点变得生动的好方法,尤其是在进行时间序列分析的时候。
所有模型精度将与性能指标和实际与预测图进行比较。
我将使用的绩效指标是:
- R 是一个拟合优度指标,它以百分比的形式解释了由于特征变量的变化而导致的响应变量的变化量。**
- RMSE (或均方根误差)是残差的标准差,衡量预测误差的平均大小。基本上,它告诉你残差是如何分布的。**
revenue_tbl %>%
filter(order_date >= "2005-01-03") %>%
ggplot(aes(order_date, revenue)) +
geom_line(colour = 'black', size = 0.7) +
geom_point(colour = 'black', size = 0.7) +
geom_smooth(se = FALSE,
colour = 'red',
size = 1,
linetype = "dashed") +
theme_light() +
scale_y_continuous(limits = c(0, 11.5e7),
labels = scales::dollar_format(scale = 1e-6,
suffix = "m")) +
labs(title = 'Weekly Revenue - 2005 to June 2007',
subtitle = 'Train, Test and Forecast Data Portions',
x = "", y = 'Revenue ($m)') + # Train Portion
annotate(x = ymd('2005-12-01'), y = (10.5e7), fill = 'black',
'text', label = 'Train\nPortion', size = 2.8) + # Test Portion
annotate(x = ymd('2007-02-05'), y = (10.5e7),
'text', label = 'Test\nPortion', size = 2.8) +
geom_rect(xmin = as.numeric(ymd('2006-12-18')),
xmax = as.numeric(ymd('2007-03-25')),
ymin = -Inf, ymax = Inf, alpha = 0.005,
fill = 'darkturquoise') + # Forecast Portion
annotate(x = ymd('2007-05-13'), y = (10.5e7),
'text', label = 'Forecast\nPortion', size = 2.8) +
geom_rect(xmin = as.numeric(ymd('2007-03-26')),
xmax = as.numeric(ymd('2007-07-01')),
ymin = -Inf, ymax = Inf, alpha = 0.01,
fill = 'cornflowerblue')

****非常重要的一点:如你所见,我没有在图中显示 2004 年的数据。这是因为,每当您在模型中包含滞后变量时,用于计算滞后的第一个周期【drop off】数据集,将无法用于建模。在有年度滞后的情况下,所有观察值都提前一年,并且由于没有 2003 年的销售记录,这导致前 52 周被从分析中删除。
特征创建
现在,我可以开始将时间序列探索的结果整合到我的特征变量中。为此,我创造了:
趋势**特征:(一个趋势和趋势平方)。这是通过一个简单的数字指数来控制上升趋势和潜在的非线性趋势。**
Lag 特性:(a _lag 13 和 _lag 52 )捕捉观察到的收入与其季度和年度季节性滞后的相关性。
季节性**特性,用于处理两周工作、两周休息的采购频率
model_data_tbl <-
revenue_tbl %>%
mutate(trend = 1:nrow(revenue_tbl),
trend_sqr = trend^2,
rev_lag_13 = lag(revenue, n = 13),
rev_lag_52 = lag(revenue, n = 52),
season = case_when(revenue == 0 ~ 0,
TRUE ~ 1)
) %>%
filter(!is.na(rev_lag_52))
下一步是创建训练、测试和预测数据帧。
事实上,测试数据集合是不是严格要求的,因为H2O允许多重交叉验证自动执行。
然而,正如上一段所暗示的,为了评估和比较装配模型的样品内性能,我正在从列车数据中“切割”一个测试集。
train_tbl <-
model_data_tbl %>%
filter(order_date <= "2007-03-19") test_tbl <-
model_data_tbl %>%
filter(order_date >= "2006-10-02" &
order_date <= "2007-03-19")train_tbl %>% head()
## # A tibble: 6 x 7
## order_date revenue trend trend_sqr rev_lag_13 rev_lag_52 season
## <date> <dbl> <int> <dbl> <dbl> <dbl> <dbl>
## 1 2005-01-03 0 53 2809 0 0 0
## 2 2005-01-10 54013487\. 54 2916 45011429\. 58814754\. 1
## 3 2005-01-17 40984715\. 55 3025 30075259\. 13926869\. 1
## 4 2005-01-24 0 56 3136 0 0 0
## 5 2005-01-31 0 57 3249 0 0 0
## 6 2005-02-07 51927116\. 58 3364 51049952\. 55440318\. 1
创建预测数据集时的主要考虑围绕着对预测变量的可能值和水平进行计算假设****
- 说到
trend特性,我只是从 _model_data tbl 数据集中选择它们。它们是基于数字索引的,这样就很好了 - 假设有订单的周数几乎都是年复一年一致的(还记得探索性分析吗?)我将
season和rev_lag_52设置为一年前(52 周前)的值 rev_lag_13的值被设置为等于其上一季度的值(即 Q1 2007)
forecast_tbl <-
model_data_tbl %>%
filter(order_date > "2007-03-19") %>%
select(order_date:trend_sqr) %>%
cbind(season = model_data_tbl %>%
filter(between(order_date,
as.Date("2006-03-27"),
as.Date("2006-06-19"))) %>%
select(season),
rev_lag_52 = model_data_tbl %>%
filter(between(order_date,
as.Date("2006-03-27"),
as.Date("2006-06-19"))) %>%
select(rev_lag_52),
rev_lag_13 = model_data_tbl %>%
filter(between(order_date,
as.Date("2006-12-25"),
as.Date("2007-03-19"))) %>%
select(rev_lag_13)
) forecast_tbl %>% head()
## order_date revenue trend trend_sqr season rev_lag_52 rev_lag_13
## 1 2007-03-26 449709 169 28561 0 0.0 0
## 2 2007-04-02 0 170 28900 0 0.0 0
## 3 2007-04-09 89020602 171 29241 1 45948859.7 63603122
## 4 2007-04-16 70869888 172 29584 1 41664162.8 63305793
## 5 2007-04-23 0 173 29929 0 480138.8 0
## 6 2007-04-30 0 174 30276 0 0.0 0
和 H2O 一起做模特
终于准备好开始做模特了!
H2O是一个面向机器学习应用的高性能开源库,致力于分布式处理,这使得它适合于较小的内存项目,并且可以通过外部处理能力快速扩展以实现更大的目标。
它基于 Java,具有与 R 和 Python 的专用接口,并整合了许多监督和非监督的机器学习模型。在这个项目中,我特别关注 4 种算法:
- 广义线性模型(GLM)
- 梯度推进机(GBM)
- 我还使用了 AutoML 工具,并使用 leader 模型来比较性能
首先:启动一个H2O实例!
当 R 通过h2o.init命令启动 H2O 时,我可以指定内存分配池集群的大小。为了加快速度,我把它设置为“16G”。
h2o.init(max_mem_size = "16G")
## H2O is not running yet, starting it now...
##
## Note: In case of errors look at the following log files:
## C:\Users\LENOVO\AppData\Local\Temp\RtmpSWW88g/h2o_LENOVO_started_from_r.out
## C:\Users\LENOVO\AppData\Local\Temp\RtmpSWW88g/h2o_LENOVO_started_from_r.err
##
##
## Starting H2O JVM and connecting: . Connection successful!
##
## R is connected to the H2O cluster:
## H2O cluster uptime: 4 seconds 712 milliseconds
## H2O cluster timezone: Europe/Berlin
## H2O data parsing timezone: UTC
## H2O cluster version: 3.26.0.10
## H2O cluster version age: 2 months and 4 days
## H2O cluster name: H2O_started_from_R_LENOVO_xwx278
## H2O cluster total nodes: 1
## H2O cluster total memory: 14.22 GB
## H2O cluster total cores: 4
## H2O cluster allowed cores: 4
## H2O cluster healthy: TRUE
## H2O Connection ip: localhost
## H2O Connection port: 54321
## H2O Connection proxy: NA
## H2O Internal Security: FALSE
## H2O API Extensions: Amazon S3, Algos, AutoML, Core V3, TargetEncoder, Core V4
## R Version: R version 3.6.1 (2019-07-05)
我也喜欢关闭进度条,因为在某些情况下,输出消息可能会非常冗长。
h2o.no_progress()
下一步是安排响应和预测变量集。为了进行回归,您需要确保响应变量不是一个因子(否则H2O将进行分类)。
# response variable
y <- "revenue"
# predictors set: remove response variable and order_date from the set
x <- setdiff(names(train_tbl %>% as.h2o()), c(y, "order_date"))
随机森林
我将从安装一个random forest开始。
注意,我包括了nfolds参数。无论何时指定,该参数使交叉验证能够在不需要validation_frame的情况下执行——例如,如果设置为 5,它将执行 5 重交叉验证。
我还使用了一些控制参数来处理模型的运行时间:
- 我将
stopping_metric设置为RMSE作为提前停止的误差度量(当度量停止改善时,模型将停止构建新的树) - 通过
stopping_rounds,我指定了考虑提前停止前的训练轮数 - 我使用
stopping_tolerance来设置训练过程继续所需的最小改进
# random forest model
rft_model <-
h2o.randomForest(
x = x,
y = y,
training_frame = train_tbl %>% as.h2o(),
nfolds = 10,
ntrees = 500,
stopping_metric = "RMSE",
stopping_rounds = 10,
stopping_tolerance = 0.005,
seed = 1975
)
我现在用h2o.varimp_plot可视化变量重要性,它返回一个每个变量的排名贡献图,标准化为 0 到 1 之间的范围。
rft_model %>% h2o.varimp_plot()

model_summary功能允许访问关于模型参数的信息。
rft_model@model$model_summary
## Model Summary:
## number_of_trees number_of_internal_trees model_size_in_bytes min_depth
## 1 27 27 12560 7
## max_depth mean_depth min_leaves max_leaves mean_leaves
## 1 14 10.29630 12 45 32.37037
这里我们可以看到,随机森林只使用了允许估计的最多 500 棵树中的 26 棵树(我用ntrees参数设置了这一点)。我们还可以估算出树的深度范围从 7 到 14(不是特别深的森林),每棵树的叶子数量范围从 12 到 45。
最后但同样重要的是,我可以用h2o.performance查看模型的性能
h2o.performance(rft_model, newdata = test_tbl %>% as.h2o())
## H2ORegressionMetrics: drf
##
## MSE: 3.434687e+13
## RMSE: 5860620
## MAE: 3635468
## RMSLE: 9.903415
## Mean Residual Deviance : 3.434687e+13
## R^2 : 0.9737282
该模型实现了 97.4% 的高R^2,这意味着特征变量的变化解释了响应变量的几乎所有可变性。
另一方面,RMSE显得相当大!RMSE 的高值可能是由于少量高误差预测的存在(如异常值的情况),考虑到响应变量的波动性,这并不奇怪。
谈到基于误差的指标,如 RMSE、平均误差、均方误差等。没有好坏的绝对值,因为它们是用响应变量的单位表示的。通常,你想要实现一个更小的RMSE,因为这意味着更高的预测能力,但是对于这个项目,我将简单地使用这个指标来比较不同模型的相对性能。
扩展到许多型号
让我们以编程的方式概括性能评估,一次性计算、评估和比较多个模型。
首先,我安装了几个型号,并确保我为所有型号启用了cross-validation。注意,对于 GBM ,我指定了与用于随机森林相同的参数,但是有大量的参数可以用来控制模型估计的几个方面(我不会涉及这些,因为这超出了本项目的范围)
# gradient boosting machine model
gbm_model <-
h2o.gbm(
x = x,
y = y,
training_frame = as.h2o(train_tbl),
nfolds = 10,
ntrees = 500,
stopping_metric = "RMSE",
stopping_rounds = 10,
stopping_tolerance = 0.005,
seed = 1975
)
# generalised linear model (a.k.a. elastic net model)
glm_model <-
h2o.glm(
x = x,
y = y,
training_frame = as.h2o(train_tbl),
nfolds = 10,
family = "gaussian",
seed = 1975
)
我还运行了非常方便的automl功能,可以安装多个模型并优化网格搜索。就像我对其他模型所做的那样,我可以指定一系列参数来指导这个函数,比如几个stopping度量和max_runtime_secs来节省计算时间。
automl_model <-
h2o.automl(
x = x,
y = y,
training_frame = as.h2o(train_tbl),
nfolds = 5,
stopping_metric = "RMSE",
stopping_rounds = 10,
stopping_tolerance = 0.005,
max_runtime_secs = 60,
seed = 1975
)
检查引导板将显示适合的模型
automl_model@leaderboard
## model_id
## 1 GBM_2_AutoML_20200112_111324
## 2 GBM_4_AutoML_20200112_111324
## 3 StackedEnsemble_BestOfFamily_AutoML_20200112_111324
## 4 GBM_1_AutoML_20200112_111324
## 5 DeepLearning_grid_1_AutoML_20200112_111324_model_1
## 6 DeepLearning_grid_1_AutoML_20200112_111324_model_5
##
## mean_residual_deviance rmse mse mae rmsle
## 1 1.047135e+14 10232963 1.047135e+14 5895463 NaN
## 2 1.070608e+14 10347021 1.070608e+14 5965855 NaN
## 3 1.080933e+14 10396794 1.080933e+14 5827000 NaN
## 4 1.102083e+14 10498016 1.102083e+14 5113982 NaN
## 5 1.104058e+14 10507419 1.104058e+14 6201525 NaN
## 6 1.146914e+14 10709407 1.146914e+14 6580217 NaN
##
## [22 rows x 6 columns]
如你所见,顶部的模型是一个梯度推进机模型。还有几个深度学习模型和一个堆叠合奏,H2O迎战超级学习者。
性能评价
首先,我将所有模型保存在一个文件夹中,这样我就可以访问它们,并通过一系列函数以编程方式处理性能指标
# set path to get around model path being different from project path
path = "/02_models/final/"
# Save GLM model
h2o.saveModel(glm_model, path)
# Save RF model
h2o.saveModel(rft_model, path)
# Save GBM model
h2o.saveModel(gbm_model, path)
# Extracs and save the leader autoML model
aml_model <- automl_model@leader
h2o.saveModel(aml_model, path)
可变重要性图
让我们从可变重要性图开始。之前我在random forest模型中使用了绘图功能,但是现在我想一次将它们全部绘制出来,这样我就可以比较和对比结果了。
有许多库(如 IML 、 PDP 、 VIP 、 DALEX 等更受欢迎的库)有助于机器学习模型可解释性、特征解释和一般性能评估。在这个项目中,我使用的是vip包。
这些库的主要优势之一是它们与其他 R 包如gridExtra的兼容性。
p_glm <- vip(glm_model) + ggtitle("GLM")
p_rft <- vip(rft_model) + ggtitle("RF")
p_gbm <- vip(gbm_model) + ggtitle("GBM")
p_aml <- vip(aml_model) + ggtitle("AML")
grid.arrange(p_glm, p_rft, p_gbm, p_aml, nrow = 2)

Seasonality和以前的收入水平(lags)在几乎所有车型中都排在前 3 位(唯一的例外是 GBM )。相反,没有一个模型发现trend及其对应的squared是反应变量变化的有力解释者。
性能指标
perf_gbm_model <-
h2o.performance(gbm_model, newdata = as.h2o(test_tbl))
perf_gbm_model
## H2ORegressionMetrics: gbm
##
## MSE: 1.629507e+13
## RMSE: 4036716
## MAE: 2150460
## RMSLE: 9.469847
## Mean Residual Deviance : 1.629507e+13
## R^2 : 0.9875359
然而,为了评估和比较模型的性能,我将重点关注RMSE和R^2^。
使用h20.metric函数可以一次提取所有性能指标,由于某种原因,这似乎不适用于H2ORegressionMetrics对象。
perf_gbm_model %>%
h2o.metric()
## Error in paste0("No ", metric, " for ",
## class(object)) : argument "metric" is missing, with
## no default
此外,在这种情况下,错误消息不是特别有用,因为“metric”参数是可选的,默认情况下应该返回所有指标。这个问题似乎与执行回归有关,因为它实际上可以很好地处理H2OClassificationMetrics对象。
幸运的是,提供了一些有用的助手函数来单独提取单个指标,它们工作正常!
perf_gbm_model %>% h2o.r2()
## [1] 0.9875359
perf_gbm_model %>% h2o.rmse()
## [1] 4036716
因此,我将使用这些单独的助手来编写一个小函数,该函数对测试数据上的所有模型运行预测,并返回一个包含所有性能指标的简便 tibble。****
performance_metrics_fct <- function(path, data_tbl) {
model_h2o <- h2o.loadModel(path)
perf_h2o <- h2o.performance(model_h2o, newdata = as.h2o(data_tbl))
R2 <- perf_h2o %>% h2o.r2()
RMSE <- perf_h2o %>% h2o.rmse()
tibble(R2, RMSE)
}
现在我可以将这个公式传递给purrr包中的map函数,以迭代计算并编译所有模型中的RMSE和R^2^。为了正确地识别每个模型,我还确保从路径中提取模型的名称。
perf_metrics_test_tbl <- fs::dir_info(path = "/02_models/final_models/") %>%
select(path) %>%
mutate(metrics = map(path, performance_metrics_fct, data_tbl = test_tbl),
path = str_split(path, pattern = "/", simplify = T)[,2]
%>% substr(1,3)) %>%
rename(model = path) %>%
unnest(cols = c(metrics))perf_metrics_test_tbl %>%
arrange(desc(R2))
model R2 RMSE
AML 0.9933358 2951704
GBM 0.9881890 3929538
DRF 0.9751434 5700579
GLM -0.0391253 36858064
所有基于树的模型都达到非常高的R^2,其中有 autoML 模型(这是一个 GBM,记得吗?)达到惊人的 99.3% 并达到最低RMSE。另一方面, GLM 得到一个负 R^2 。
负 R 并非闻所未闻:R 将模型的拟合与水平直线的拟合进行比较,并计算模型解释的方差与直线(零假设)解释的方差的比例。如果拟合实际上比仅仅拟合一条水平线差,那么 R 平方可以是负的。
实际与预测图
最后但同样重要的是,为了提供模型性能的额外和更直观的显示,我将绘制所有模型的实际与预测。
我正在使用一个类似于我用来计算性能指标的函数,因为基本原理是相同的。
predict_fct <- function(path, data_tbl) {
model_h2o <- h2o.loadModel(path)
pred_h2o <- h2o.predict(model_h2o, newdata = as.h2o(data_tbl))
pred_h2o %>%
as_tibble() %>%
cbind(data_tbl %>% select(order_date))
}
正如我之前所做的,我将公式传递给一个map函数来迭代计算,并使用所有模型的test数据子集来编译prediction。
validation_tmp <- fs::dir_info(path = "/02_models/final_models/") %>%
select(path) %>%
mutate(pred = map(path, predict_fct, data_tbl = test_tbl),
path = str_split(path, pattern = "/", simplify = T)[,2] %>%
substr(1,3)) %>%
rename(model = path)
然而,得到的validation_tmp是一个嵌套的 tibble,每个单元格中的预测都存储为列表。
validation_tmp
## # A tibble: 4 x 2
## model pred
## <chr> <list>
## 1 AML <df[,2] [25 × 2]>
## 2 DRF <df[,2] [25 × 2]>
## 3 GBM <df[,2] [25 × 2]>
## 4 GLM <df[,2] [25 × 2]>
这需要几个额外的操作来获得一个可用于绘图的形状:取消列表嵌套,围绕order_date旋转预测,并将收入添加为actual。
validation_tbl <-
validation_tmp %>%
unnest(cols = c(pred)) %>%
pivot_wider(names_from = model,
values_from = predict) %>%
cbind(test_tbl %>%
select(actual = revenue)) %>%
rename(date = order_date)
现在,我要把这个绘图函数直接写在里 plotly
validation_tbl %>%
plot_ly() %>%
add_lines(x = ~ date, y = ~ actual, name = 'Actual') %>%
add_lines(x = ~ date, y = ~ DRF, name = 'Random Forest',
line = list(dash = 'dot')) %>%
add_lines(x = ~ date, y = ~ GBM, name = 'Gradient Boosting Machine',
line = list(dash = 'dash')) %>%
add_lines(x = ~ date, y = ~ AML, name = 'Auto ML',
line = list(dash = 'dot')) %>%
add_lines(x = ~ date, y = ~ GLM, name = 'Generalised Linear Model',
line = list(dash = 'dash')) %>%
layout(title = 'Total Weekly Sales - Actual versus Predicted (various models)',
yaxis = list(title = 'Millions of Dollars'),
xaxis = list(title = ''),
legend = list(orientation = 'h')
)

除了 GLM 模型,它产生了一条看似平坦的预测线(还记得负面的 R ?),所有模型都很好地捕捉到了系列中的波峰和波谷。预测仅开始错过最后 2 个尖峰周围的响应变化的全部范围。
预测
无需编写任何新函数,因为performance_metrics_fct和predict_fct也可用于预测。
首先,我看一下性能指标
perf_metrics_cast_tbl <- fs::dir_info(path = "/02_models/final_models/") %>%
select(path) %>%
mutate(metrics = map(path, performance_metrics_fct,
data_tbl = forecast_tbl),
path = str_split(path, pattern = "/", simplify = T)[,2]
%>% substr(1,3)) %>%
rename(model = path) %>%
unnest(cols = c(metrics)) perf_metrics_cast_tbl %>%
arrange(desc(R2))
model R2 RMSE
GBM 0.8678649 14544327
AML 0.8363565 16185792
DRF 0.8042526 17702414
GLM -0.0617160 41227664
有趣的是,在顶部位置有一点互换,与 autoML 模型相比,“手动”GBM 在预测中表现更好。与验证指标相比,所有模型的性能指标都恶化了。
然后,我计算预测…
cast_tbl <- fs::dir_info(path = "/02_models/final_models/") %>%
select(path) %>%
mutate(pred = map(path, predict_fct, data_tbl = forecast_tbl),
path = str_split(path, pattern = "/", simplify = T)[,2] %>%
substr(1,3)) %>%
rename(model = path) %>%
unnest(cols = c(pred)) %>%
pivot_wider(names_from = model, values_from = predict) %>%
cbind(forecast_tbl %>% select(actual = revenue)) %>%
rename(date = order_date)
…并想象它
cast_tbl %>%
plot_ly() %>%
add_lines(x = ~ date, y = ~ actual, name = 'Actual') %>%
add_lines(x = ~ date, y = ~ DRF, name = 'Random Forest',
line = list(dash = 'dot')) %>%
add_lines(x = ~ date, y = ~ GBM, name = 'Gradient Boosting Machine',
line = list(dash = 'dash')) %>%
add_lines(x = ~ date, y = ~ AML, name = 'Auto ML',
line = list(dash = 'dot')) %>%
add_lines(x = ~ date, y = ~ GLM, name = 'Generalised Linear Model',
line = list(dash = 'dash')) %>%
layout(title = 'Total Weekly Sales - Actual versus Forecast (various models)',
yaxis = list(title = 'Millions of Dollars'),
xaxis = list(title = ''),
legend = list(orientation = 'h')
)

除了不出所料产生持平预测的 GLM 之外,所有车型都继续很好地捕捉 2 周开工、2 周停工的购买模式。此外,所有模型预测都未能捕捉到所有 3 个峰值的反应变量运动的全部范围,这表明在 2007 年可能有另一种动态在起作用,而当前的预测者无法控制这种动态。
forecast_tbl %>%
select(-trend, -trend_sqr) %>%
tail(10)
order_date revenue season rev_lag_52 rev_lag_13
4 2007-04-16 70869888 1 41664162.8 63305793
5 2007-04-23 0 0 480138.8 0
6 2007-04-30 0 0 0.0 0
7 2007-05-07 78585882 1 41617508.0 64787291
8 2007-05-14 78797822 1 48403283.4 59552955
9 2007-05-21 0 1 0.0 0
10 2007-05-28 0 0 0.0 0
11 2007-06-04 0 0 45696327.2 0
12 2007-06-11 75486199 1 53596289.9 70430702
13 2007-06-18 86509530 1 774190.1 60094495
最后一件事:完成后不要忘记关闭H2O实例!
h2o.shutdown(prompt = FALSE)
结束语
在这个项目中,我经历了建立时间序列机器学习管道和生成每周收入预测所需的各个步骤。
特别是,我用TSstudio和进行了一个更“传统”的探索性时间序列分析,并利用我收集的洞察力创建了许多预测器。然后我用开源库H2O训练并验证了一系列机器学习模型,并且使用性能指标和实际与预测图比较了模型的准确性。
结论
这只是制作每周收入预测的第一次尝试,显然还有很大的改进空间。尽管如此,一旦你有了这样的建模和预测管道,创建和测试几个模型和不同的预测集就会变得更加容易和快速。
数据序列是人工生成的这一事实并不理想,因为它不一定包含您在现实生活数据集中会遇到的动态。尽管如此,这促使我发挥创造力,让整个练习变得更加愉快。
预测总收入可能不是最好的策略,例如,通过product line或country分解响应变量可能会带来更好、更准确的预测。这超出了本项目的范围,但也可能是未来项目的主题!
我从这个练习中学到的一件事是H2O是绝对聪明的!它的设置快速、直观,并具有广泛的定制选项。 AutoML 非常棒,支持 R 、 Python 和 Java 并且任何人都可以免费使用它的事实给了像 Google AutoML 和 AWS SageMaker AutoML 这样的平台一个机会!
代码库
完整的 R 代码可以在 我的 GitHub 简介 中找到
参考
- 对于 H2O 网站T5 H2O 网站
- 对于 H2O 文档 H2O 文档
- 有关在 R 中使用 R 进行时间序列分析和预测的详细讨论
- 关于 TSstudio 的介绍 [关于 TSstudio 包的介绍](https://diegousai.io/2019/12/time-series-machine-learning-analysis-and-demand-forecasting/Introduction for the TSstudio Package)
- T21 简介机器学习可解释性
原载于 2019 年 12 月 11 日https://diegousei . io。**
时间序列机器学习回归框架
构建时间序列预测管道来预测每周销售交易

Most commonly, a time series is a sequence taken at successive equally spaced points in time. Thus it is a sequence of discrete-time data. Photo by Justin Campbell on Unsplash
介绍
Fig.1) Let’s borrow the concept of time from Entropy & thermodynamics: Entropy is the only quantity in the physical sciences that seems to imply a particular direction of progress, sometimes called an arrow of time. As time progresses, the second law of thermodynamics states that the entropy of an isolated system never decreases in large systems over significant periods of time. Can we consider our Universe as an isolated large system? Then what?
时间!宇宙中最具挑战性的概念之一。我研究物理学多年,看到大多数杰出的科学家都在努力处理时间的概念。在机器学习中,即使我们远离那些复杂的物理理论,在这些理论中,对时间概念的共同理解会改变,时间的存在和 ML 问题中的观察序列会使问题变得更加复杂。
时间序列的机器学习;

Fig.2) In time series forecasting, we use historical data to forecast the future. George Santayana: Those Who Do Not Learn History Are Doomed To Repeat It. The right figure is taken from https://www.kdnuggets.com/2018/02/cartoon-valentine-machine-learning.html
时间序列是按时间顺序进行的一系列观察。时间序列预测包括采用模型,然后根据历史数据进行拟合,然后用它们来预测未来的观测值。因此,例如,测量的分钟(秒)、天(秒)、月(秒)、前(秒)被用作预测

Fig.3) Transform Time Series to Supervised Machine Learning.
接下来的分钟、天、月。被认为是在时间(序列)上向后移动数据的步骤,称为滞后时间或滞后。因此,通过添加测量的滞后作为监督 ML 的输入,可以将时间序列问题转化为监督 ML。见图 3 右侧。一般来说,探索滞后的数量作为一个超参数。

Fig.4) Transform the time series to supervised machine learning by adding lags. Lags are basically the shift of the data one step or more backward in the time.
时间序列的交叉验证
时间序列的交叉验证不同于不涉及时间或序列的机器学习问题。在没有时间的情况下,我们选择一个随机的数据子集作为验证集来估计测量的准确性。在时间序列中,我们经常预测未来的某个值。因此,验证数据总是必须在训练数据的之后出现。有两种模式滑动窗口和前向链接验证方法,可用于时间序列 CV。

Fig. 5) Basically, there are two kinds of cross-validation for the time series sliding window and forward chaining. In this post, we will consider forward chaining cross-validation method
图 5 顶部显示了滑动窗口方法。对于这种方法,我们在 n 个数据点上训练,并在接下来的 n 个数据点上验证预测,为下一步及时滑动 2n 训练/验证窗口。图 5 底部显示了正向链接方法。对于这种方法,我们在最后 n 个数据点上训练,并在接下来的 m 个数据点上验证预测,在时间上滑动 n+m 训练/验证窗口。这样,我们就可以估计我们模型的参数了。为了测试模型的有效性,我们可能会在时间序列的末尾使用一个数据块,该数据块是为用学习到的参数测试模型而保留的。

Fig.6) Forward chaining cross-validation.
图六。显示了正向链接 CV 的工作方式。在这里,有一个滞后。因此,我们从第一秒到第三秒/分钟/小时/天等来训练模型。然后验证第四个,以此类推。既然现在我们已经熟悉了 TS 问题,让我们选择一个时间序列问题并建立一个预测模型。
预测每周销售交易
假设一家商店的经理要求我们建立一个 ML 模型来预测下周的销售额。该模型必须每周日运行,预测结果必须在每周一上午报告。然后,经理可以决定一周的订单数量。经理给我们提供了 52 周 811 产品的销售数据。销售数据可以在 UCI 仓库 或 kaggle 中找到。
我们来看数据。

许多数据科学家可能会为每种产品创建一个模型来预测销售数量。虽然这可以很好地工作,但我们可能会有问题,因为每个模型只有 52 个数据点,这真的很低!尽管这种方法是可行的,但它可能不是最佳解决方案。此外,如果两种或更多产品的销售数量之间存在交互,我们可能会因为为每种产品构建一个模型而错过它们的交互。因此,在这篇文章中,我们将探讨如何建立一个多时间序列预测模型。
数据准备
原始数据有一个产品代码列和 52 周销售额列。首先,我们将通过融合周数据来创建一个新的数据框架。因此,新的数据框架有三列,产品代码、周和销售额。此外,“W”和“P”分别从星期和产品中删除。那么,让我们看看新数据帧的头部和尾部

为了熟悉数据集,销售分布绘制在图 7 中。可以看出,有大量产品的销售额很低,数据也向左倾斜。这个问题对建模的影响将在后面讨论。

Fig. 7) Sales distribution. There are many product sales items with very low sales.
基础特征工程
因为这篇文章的目标不是 TS 的特性工程,我们将尽量保持这部分简单。让我们创建两个通常用于时间序列的特征。时间上后退一步,1-lag(shift =1)和一周前(W 1)的购买数量与其前一周的购买数量之差,意味着,两周前(W2)。此后,由于 lag 和 diff 导致数据集中的值为空,参见图 4,我们将其删除。因此,当我们查看数据帧的头部时,它从 week = 2 开始。

“ToSupervised”和“ToSupervisedDiff”类,代码 1 和代码 2,如编码部分所示,用于通过简单的管道获得新的数据帧:
steps = [('1_step',
ToSupervised('Sales','Product_Code',1)),
('1_step_diff',
ToSupervisedDiff('1_Week_Ago_Sales',
'Product_Code',1,dropna=True))]super_1 = Pipeline(steps).fit_transform(df)
现在,数据有了适当的形状,可以在受监督的 ML 中使用。
正向链接交叉验证:
另一个问题是,当我们处理时间序列时,我们必须处理时间序列的 CV。我们选择前向链接进行模型验证。为了避免在很少的几周内有一个非常好的模型,我们将使用从 40 到 52 的每一周,每次重复一个过程,并计算分数。因此,这个模式下的 k 倍代码可以在 C. 3 中找到。
kf = Kfold_time(target='Sales',date_col = 'Week',
date_init=40, date_final=52)
因为这篇文章只是一个演示,所以我不打算分离一个测试数据集。在实际项目中,总是保留一些时间段作为测试数据集,以根据看不见的数据评估模型。
公制的
由于问题是回归,有几个众所周知的指标来评估模型,如均方误差(MSE),平均绝对误差(MAE),均方根误差(RMSE),均方根对数误差(RMSLE),R 平方,等等。这些度量标准中的每一个都有自己的用例,它们以不同的方式惩罚错误,但它们之间也有一些相似之处。在本文中,我们选择 RMSLE 来评估这个模型。
基线:
通常,当我们构建一个模型时,我们可能会提出一个非常简单的假设,认为使用 ML 可以改进它。在这里,让我们假设每种产品的数量在本周售出,下周也是如此。这意味着,如果产品-1 在第 1 周销售了 10 次,那么它在第 2 周的销售数字也将是相同的。这通常是一个不错的假设。所以,让我们把这个假设当作我们的基线模型。
基线模型用 C. 5 编码,让我们看看基线模型是如何工作的
base_model = BaseEstimator('1_Week_Ago_Sales')
errors = []
for indx,fold in enumerate(kf.split(super_1)):
X_train, X_test, y_train, y_test = fold
error = base_model.score(X_test,y_test,rmsle)
errors.append(error)
print("Fold: {}, Error: {:.3f}".format(indx,error))
print('Total Error {:.3f}'.format(np.mean(errors)))
折:0,误差:0.520
折:1,误差:0.517
折:2,误差:0.510
折:3,误差:0.508
折:4,误差:0.534
折:5,误差:0.523
折:6,误差:0.500
折:7,误差:0.491
折:8,误差:0.506 【T8
这里,折叠 0 到 11 表示周= 40 到周= 52。基线模型在这 12 周内的 RMSLE 平均值为 0.51。这可以被认为是一个很大的错误,这可能是由于图 7 所示的大量商品的销售量很少造成的
机器学习模型:
现在,我们将应用 ML 来改进基线预测。让我们定义一个时间序列回归器类 C. 5,它与我们的时间序列交叉验证一起工作。该类获取 cv 和模型,并返回模型预测及其得分。有很多种最大似然算法可以用作估计器。这里,我们选择一个随机的森林。简单地说,RF 可以被认为是装袋和在决策树顶部随机选择特征列的组合。因此,它减少了决策树模型预测的方差。因此,它通常比单个树具有更好的性能,但比旨在减少决策树模型的偏差误差的集成方法具有更弱的性能。
model = RandomForestRegressor(n_estimators=1000,
n_jobs=-1,
random_state=0)steps_1 = [('1_step',
ToSupervised('Sales','Product_Code',1)),
('1_step_diff',
ToSupervisedDiff('1_Week_Ago_Sales',
'Product_Code',1,dropna=True)),
('predic_1',
TimeSeriesRegressor(model=model,cv=kf))]super_1_p = Pipeline(steps_1).fit(df)
Model_1_Error = super_1_p.score(df)
我们得到了
倍:0,误差:0.4624
倍:1,误差:0.4596
倍:2,误差:0.4617
倍:3,误差:0.4666
倍:4,误差:0.4712
倍:5,误差:0.4310
倍:6,误差:0.4718
倍:7,误差:0.4494
倍:8,误差:
似乎模型起作用了,误差减小了。让我们添加更多的滞后,并再次评估模型。因为我们构建了管道,所以添加更多的 lag 会非常简单。
steps_3 = [('1_step',
ToSupervised('Sales','Product_Code',3)),
('1_step_diff',
ToSupervisedDiff('1_Week_Ago_Sales','Product_Code',1)),
('2_step_diff',
ToSupervisedDiff('2_Week_Ago_Sales','Product_Code',1)),
('3_step_diff',
ToSupervisedDiff('3_Week_Ago_Sales',
'Product_Code',1,dropna=True)),
('predic_3',
TimeSeriesRegressor(model=model,cv=kf,scoring=rmsle))]
super_3_p = Pipeline(steps_3).fit(df)
倍:0,误差:0.4312
倍:1,误差:0.4385
倍:2,误差:0.4274
倍:3,误差:0.4194
倍:4,误差:0.4479
倍:5,误差:0.4070
倍:6,误差:0.4395
倍:7,误差:0.4333【T15
似乎预测的误差再次减小,并且模型学习得更多。我们可以继续添加滞后,看看模型的性能如何变化;然而,我们将推迟这个过程,直到我们使用 LGBM 作为一个估计。
统计转换:
销售的分布,图 7 显示数据向低销售数字或左边倾斜。通常,对数变换在应用于偏斜分布时很有用,因为它们倾向于扩展较低幅度范围内的值,并倾向于压缩或减少较高幅度范围内的值。当我们进行统计变换时,模型的可解释性会发生变化,因为系数不再告诉我们原始特征,而是变换后的特征。因此,当我们对销售数字应用 np.log1p 来转换其分布以使其更接近正态分布时,我们也对预测结果应用 np.expm1,参见 C. 6,TimeSeriesRegressorLog。现在,我们用提到的变换重复计算
steps_3_log = [('1_step',
ToSupervised('Sales','Product_Code',3)),
('1_step_diff',
ToSupervisedDiff('1_Week_Ago_Sales',
'Product_Code',1)),
('2_step_diff',
ToSupervisedDiff('2_Week_Ago_Sales',
'Product_Code',1)),
('3_step_diff',
ToSupervisedDiff('3_Week_Ago_Sales',
'Product_Code',1,dropna=True)),
('predic_3',
TimeSeriesRegressorLog(model=model,
cv=kf,scoring=rmsle))]
super_3_p_log = Pipeline(steps_3_log).fit(df)
所以我们有
倍:0,误差:0.4168
倍:1,误差:0.4221
倍:2,误差:0.4125
倍:3,误差:0.4035
倍:4,误差:0.4332
倍:5,误差:0.3977
倍:6,误差:0.4263
倍:7,误差:0.4122【T33
这表明模型的性能提高了,误差又减小了。
套装 ML:
现在,是时候使用更强的 ML 估计量来改进预测了。我们选择 LightGBM 作为新的估计器。所以让我们重复计算
model_lgb = LGBMRegressor(n_estimators=1000, learning_rate=0.01)steps_3_log_lgbm = [('1_step',
ToSupervised('Sales','Product_Code',3)),
('1_step_diff',
ToSupervisedDiff('1_Week_Ago_Sales',
'Product_Code',1)),
('2_step_diff',
ToSupervisedDiff('2_Week_Ago_Sales',
'Product_Code',1)),
('3_step_diff',
ToSupervisedDiff('3_Week_Ago_Sales',
'Product_Code',1,
dropna=True)),
('predic_3',
TimeSeriesRegressorLog(model=model_lgb,
cv=kf,scoring=rmsle))] super_3_p_log_lgbm = Pipeline(steps_3_log_lgbm).fit(df)
然后,
倍:0,误差:0.4081
倍:1,误差:0.3980
倍:2,误差:0.3953
倍:3,误差:0.3949
倍:4,误差:0.4202
倍:5,误差:0.3768
倍:6,误差:0.4039
倍:7,误差:0.3868 【T43
我们再次成功地改进了预测。
调整步骤数:
在这一部分,我们将调整步数(滞后/差异)。在使用 LGBM 作为回归变量后,我有意推迟了本节的步骤,因为它比 RF 更快。图 8 清楚地显示,通过向模型添加更多的步骤,误差减小;然而,正如我们预期的那样,在超过步长= 14 左右的阈值后,增加更多的步长不会显著降低误差。您可能有兴趣定义一个错误阈值来停止这个过程。剩余的计算选择步长= 20。请检查代码 C 7。a 和 B 用于调谐。
model_lgbm = LGBMRegressor(n_estimators=1000, learning_rate=0.01)list_scores2 = stepsTune(df,TimeSeriesRegressorLog(model=model_lgbm,
scoring=rmsle,cv=kf,verbosity=False),20)

Fig 8) Tuning the number of lags/diff is shown. The x-axis shows the RMSLE error as a function of the steps (number of lags/diffs). The model improves by adding more steps; however, steps more than 14 do not improve the model significantly.
调整超参数:
在这一部分,我们将实现网格搜索方法,我们可以通过管道应用它,参见代码 8 A 和 B. C.8.A 代码是从 Sklearn 库借来的。这一部分的目的不是构建一个完全调优的模型。我们试图展示工作流程。稍加调整后,误差变为
RMSLE= 0.3868
对于这两个超参数{'learning_rate': 0.005,' n_estimators': 1500}。
params = {'n_estimators':[100,500,1000,1500,2000],
'learning_rate':[0.005,.01,.1]}steps_20 = getDataFramePipeline(20)
super_20 = Pipeline(steps_20).fit_transform(df)model_lgbm2 = LGBMRegressor(random_state=0)tune_lgbm =TimeSeriesGridSearch(model = model_lgbm2, cv = kf,
param_grid=params,verbosity=False,scoring=rmsle)
当最佳调整超参数处于调整参数的边缘时,意味着我们必须重新考虑超参数的范围并重新计算模型,尽管在本文中我们不会这样做。
预测与实际销售
图九。显示第 52 周的预测值与销售额。可以看出,该模型对于高达 15 的销售数字工作良好;然而,它对 30 左右的销量预测很差。正如我们在图 7 中所讨论的,我们可能会为不同的销售范围建立不同的模型来克服这个问题,并拥有一个更强大的预测模型,尽管进一步的建模超出了本文的范围,并且本文已经很长了。

Fig. 9) Prediction of sales vs. real sales number. It is seen that the model works properly for the low number of sales (less than 15); however, it does not work well for a large number of sales. Therefore, this might be a good motivation to build two models for low and high sales items.
最后,图 10 显示了我们预测销售的所有尝试。我们从一个非常简单的假设作为基线开始,并试图通过使用不同的 lags/diff、统计转换和应用不同的机器学习算法来改进预测。基线误差为 0.516,调整后的模型误差为 0.3868,这意味着误差减少了 25%。

Fig. 10) Our different models score are shown. We could reduce the error of the baseline by 25%.
仍然有许多方法来改进所提出的模型,例如,适当地将产品作为分类变量来处理,更广泛的特征工程,调整超参数,使用各种机器学习算法以及混合和堆叠。
结论:
我们建立了一个时间序列预测管道来预测每周的销售交易。我们从一个简单的逻辑假设作为基线模型开始;然后,我们可以通过构建一个包括基本特征工程、统计转换和应用随机森林和 LGBM 并最终对其进行调优的管道,将基线误差降低 25%。此外,我们还讨论了不同的时间序列交叉验证方法。此外,我们展示了如何使用 Sklearn 基类来构建管道。
编码:
这篇帖子的完整代码可以在我的 GitHub 上找到。
代码 1。
class ToSupervised(base.BaseEstimator,base.TransformerMixin):
def __init__(self,col,groupCol,numLags,dropna=False):
self.col = col
self.groupCol = groupCol
self.numLags = numLags
self.dropna = dropna
def fit(self,X,y=None):
self.X = X
return self
def transform(self,X): tmp = self.X.copy()
for i in range(1,self.numLags+1):
tmp[str(i)+'_Week_Ago'+"_"+self.col] =
tmp.groupby([self.groupCol])[self.col].shift(i)
if self.dropna:
tmp = tmp.dropna()
tmp = tmp.reset_index(drop=True)
return tmp
代码 2。
class ToSupervisedDiff(base.BaseEstimator,base.TransformerMixin):
def __init__(self,col,groupCol,numLags,dropna=False):
self.col = col
self.groupCol = groupCol
self.numLags = numLags
self.dropna = dropna
def fit(self,X,y=None):
self.X = X
return self
def transform(self,X):
tmp = self.X.copy()
for i in range(1,self.numLags+1):
tmp[str(i)+'_Week_Ago_Diff_'+"_"+self.col] =
tmp.groupby([self.groupCol])[self.col].diff(i)
if self.dropna:
tmp = tmp.dropna()
tmp = tmp.reset_index(drop=True)
return tmp
代码 3。
from itertools import chain
class Kfold_time(object):
def __init__(self,**options):
self.target = options.pop('target', None)
self.date_col = options.pop('date_col', None)
self.date_init = options.pop('date_init', None)
self.date_final = options.pop('date_final', None) if options:
raise TypeError("Invalid parameters passed: %s" %
str(options))
if ((self.target==None )|(self.date_col==None )|
(self.date_init==None )|(self.date_final==None )):
raise TypeError("Incomplete inputs")
def _train_test_split_time(self,X):
n_arrays = len(X)
if n_arrays == 0:
raise ValueError("At least one array required as input") for i in range(self.date_init,self.date_final): train = X[X[self.date_col] < i]
val = X[X[self.date_col] == i] X_train, X_test = train.drop([self.target], axis=1),
val.drop([self.target], axis=1) y_train, y_test = train[self.target].values,
val[self.target].values yield X_train, X_test, y_train, y_test def split(self,X):
cv_t = self._train_test_split_time(X)
return chain(cv_t)
代码 4。
class BaseEstimator(base.BaseEstimator, base.RegressorMixin):
def __init__(self, predCol):
"""
As a base model we assume the number of sales
last week and this week are the same
Input:
predCol: l-week ago sales
"""
self.predCol = predCol def fit(self, X, y):
return self def predict(self, X):
prediction = X[self.predCol].values
return prediction def score(self, X, y,scoring):
prediction = self.predict(X)
error =scoring(y, prediction) return error
代码 5。
class TimeSeriesRegressor(base.BaseEstimator, base.RegressorMixin):
def __init__(self,model,cv,scoring,verbosity=True):
self.model = model
self.cv = cv
self.verbosity = verbosity
self.scoring = scoring
def fit(self,X,y=None):
return self
def predict(self,X=None):
pred = {}
for indx,fold in enumerate(self.cv.split(X)): X_train, X_test, y_train, y_test = fold
self.model.fit(X_train, y_train)
pred[str(indx)+'_fold'] = self.model.predict(X_test)
prediction = pd.DataFrame(pred)
return prediction def score(self,X,y=None): errors = []
for indx,fold in enumerate(self.cv.split(X)): X_train, X_test, y_train, y_test = fold
self.model.fit(X_train, y_train)
prediction = self.model.predict(X_test)
error = self.scoring(y_test, prediction)
errors.append(error) if self.verbosity:
print("Fold: {}, Error: {:.4f}".format(indx,error)) if self.verbosity:
print('Total Error {:.4f}'.format(np.mean(errors))) return errors
代码 6。
class TimeSeriesRegressorLog(base.BaseEstimator,
base.RegressorMixin):
def __init__(self,model,cv,scoring,verbosity=True):
self.model = model
self.cv = cv
self.verbosity = verbosity
self.scoring = scoring
def fit(self,X,y=None):
return self
def predict(self,X=None):
pred = {}
for indx,fold in enumerate(self.cv.split(X)): X_train, X_test, y_train, y_test = fold
self.model.fit(X_train, y_train)
pred[str(indx)+'_fold'] = self.model.predict(X_test)
prediction = pd.DataFrame(pred)
return prediction def score(self,X,y=None):#**options): errors = []
for indx,fold in enumerate(self.cv.split(X)): X_train, X_test, y_train, y_test = fold
self.model.fit(X_train, np.log1p(y_train))
prediction = np.expm1(self.model.predict(X_test))
error = self.scoring(y_test, prediction)
errors.append(error) if self.verbosity:
print("Fold: {}, Error: {:.4f}".format(indx,error)) if self.verbosity:
print('Total Error {:.4f}'.format(np.mean(errors))) return errors
代码 7。
答:
def getDataFramePipeline(i):
steps = [(str(i)+'_step',
ToSupervised('Sales','Product_Code',i))]
for j in range(1,i+1):
if i==j: pp = (str(j)+'_step_diff',
ToSupervisedDiff(str(i)+'_Week_Ago_Sales',
'Product_Code',1,dropna=True)) steps.append(pp)
else: pp = (str(j)+'_step_diff',
ToSupervisedDiff(str(i)+'_Week_Ago_Sales',
'Product_Code',1)) steps.append(pp)
return steps
乙:
from tqdm import tqdm
def stepsTune(X,model,num_steps,init=1):
scores = []
for i in tqdm(range(init,num_steps+1)):
steps = []
steps.extend(getDataFramePipeline(i))
steps.append(('predic_1',model))
super_ = Pipeline(steps).fit(X)
score_ = np.mean(super_.score(X))
scores.append((i,score_))
return scores
代码 8。
答:
from collections.abc import Mapping, Sequence, Iterable
from itertools import product
from functools import partial, reduce
import operatorclass TimeGridBasic(base.BaseEstimator, base.RegressorMixin):
def __init__(self,param_grid):
if not isinstance(param_grid, (Mapping, Iterable)):
raise TypeError('Parameter grid is not a dict or '
'a list ({!r})'.format(param_grid)) if isinstance(param_grid, Mapping):
# wrap dictionary in a singleton list to support
either dict
# or list of dicts
param_grid = [param_grid] if isinstance(param_grid, Mapping):
# wrap dictionary in a singleton list to support
either dict
# or list of dicts
param_grid = [param_grid] # check if all entries are dictionaries of lists
for grid in param_grid:
if not isinstance(grid, dict):
raise TypeError('Parameter grid is not a '
'dict ({!r})'.format(grid))
for key in grid:
if not isinstance(grid[key], Iterable):
raise TypeError('Parameter grid value is not
iterable '
'(key={!r}, value={!r})'
.format(key, grid[key])) self.param_grid = param_grid
def __iter__(self):
"""Iterate over the points in the grid.
Returns
-------
params : iterator over dict of string to any
Yields dictionaries mapping each estimator parameter to
one of its
allowed values.
"""
for p in self.param_grid:
# Always sort the keys of a dictionary, for
reproducibility
items = sorted(p.items())
if not items:
yield {}
else:
keys, values = zip(*items)
for v in product(*values):
params = dict(zip(keys, v))
yield params
乙:
class TimeSeriesGridSearch(TimeGridBasic,base.BaseEstimator,
base.RegressorMixin):
def __init__(self,**options):
self.model = options.pop('model', None)
self.cv = options.pop('cv', None)
self.verbosity = options.pop('verbosity', False)
self.scoring = options.pop('scoring', None)
param_grid = options.pop('param_grid', None)
self.param_grid = TimeGridBasic(param_grid)
if options:
raise TypeError("Invalid parameters passed: %s" %
str(options)) if ((self.model==None )| (self.cv==None)):
raise TypeError("Incomplete inputs")
def fit(self,X,y=None):
self.X = X
return self def _get_score(self,param): errors = []
for indx,fold in enumerate(self.cv.split(self.X)): X_train, X_test, y_train, y_test = fold
self.model.set_params(**param).fit(X_train, y_train)
prediction = self.model.predict(X_test)
error = self.scoring(y_test, prediction)
errors.append(error) if self.verbosity:
print("Fold: {}, Error: {:.4f}".format(indx,error)) if self.verbosity:
print('Total Error {:.4f}'.format(np.mean(errors)))
return errors def score(self): errors=[]
get_param = []
for param in self.param_grid:
if self.verbosity:
print(param)
errors.append(np.mean(self._get_score(param)))
get_param.append(param) self.sorted_errors,self.sorted_params =
(list(t) for t in zip(*sorted(zip(errors,get_param))))
return self.sorted_errors,self.sorted_params
def best_estimator(self,verbosity=False): if verbosity:
print('error: {:.4f} \n'.format(self.sorted_errors[0]))
print('Best params:')
print(self.sorted_params[0]) return self.sorted_params[0]
价格异常检测的时间序列

Photo credit: Pixabay
异常检测会检测数据中与其余数据不匹配的数据点。
也称为异常检测,异常检测是一个数据挖掘过程,用于确定在数据集中发现的异常类型,并确定其发生的详细信息。在当今世界,自动异常检测至关重要,因为海量数据使得无法手动标记异常值。自动异常检测有着广泛的应用,如欺诈检测、系统健康监控、故障检测以及传感器网络中的事件检测系统等。
但我想对酒店房价进行异常检测。原因有些自私。
你有过这样的经历吗,比如说,你经常去某个目的地出差,并且总是住在同一家酒店。虽然大多数情况下,房价几乎是相似的,但偶尔对于同一家酒店,同一种房间类型,房价高得令人无法接受,你必须换到另一家酒店,因为你的差旅补助不包括该房价。我已经经历过几次了,这让我想到,如果我们可以创建一个模型来自动检测这种价格异常会怎么样?
当然,有些情况下,一些异常现象一生只会发生一次,我们已经提前知道了它们,并且很可能在未来几年内不会在同一时间发生,例如 2019 年 2 月 2 日至 2 月 4 日亚特兰大荒谬的酒店价格。

Figure 1
在这篇文章中,我将探索不同的异常检测技术,我们的目标是用无监督学习来搜索酒店房价时间序列中的异常。我们开始吧!
数据
很难得到数据,我能得到一些,但数据并不完美。
我们将要使用的数据是个性化 Expedia 酒店搜索数据集的子集,可以在这里找到。
我们将对 training.csv 集合的子集进行切片,如下所示:
- 选择一家拥有最多数据点
property_id = 104517的酒店。 - 选择
visitor_location_country_id = 219,因为我们从另一个分析中知道国家 id 219 是美国。我们这样做的原因是为了统一price_usd栏目。因为不同的国家有不同的关于显示税费和费用的惯例,并且该值可以是每晚或整个住宿。我们知道展示给我们游客的价格总是每晚不含税。 - 选择
search_room_count = 1。 - 选择我们需要的特征:
date_time、price_usd、srch_booking_window、srch_saturday_night_bool。
expedia = pd.read_csv('expedia_train.csv')
df = expedia.loc[expedia['prop_id'] == 104517]
df = df.loc[df['srch_room_count'] == 1]
df = df.loc[df['visitor_location_country_id'] == 219]
df = df[['date_time', 'price_usd', 'srch_booking_window', 'srch_saturday_night_bool']]
经过切片和切块后,这是我们将要处理的数据:
df.info()

Figure 2
df['price_usd'].describe()

在这一点上,我们已经发现了一个极端的异常情况,即最高价格为 5584 美元。
如果一个单独的数据实例相对于其余的数据可以被认为是异常的,我们称之为(例如,大额交易的采购)。我们可以回去查看日志,看看是关于什么的。经过一点点调查,我猜想这要么是一个错误,要么是用户偶然搜索了一个总统套房,并没有打算预订或查看。为了找到更多不极端的异常,我决定去掉这个。
*expedia.loc[(expedia['price_usd'] == 5584) & (expedia['visitor_location_country_id'] == 219)]*

Figure 3
*df = df.loc[df['price_usd'] < 5584]*
在这一点上,我相信您已经发现我们遗漏了一些东西,也就是说,我们不知道用户搜索的房间类型,标准房的价格可能与海景特大床房的价格相差很大。记住这一点,为了演示的目的,我们必须继续。
时间序列可视化
*df.plot(x='date_time', y='price_usd', figsize=(12,6))
plt.xlabel('Date time')
plt.ylabel('Price in USD')
plt.title('Time Series of room price by date time of search');*

Figure 4
*a = df.loc[df['srch_saturday_night_bool'] == 0, 'price_usd']
b = df.loc[df['srch_saturday_night_bool'] == 1, 'price_usd']
plt.figure(figsize=(10, 6))
plt.hist(a, bins = 50, alpha=0.5, label='Search Non-Sat Night')
plt.hist(b, bins = 50, alpha=0.5, label='Search Sat Night')
plt.legend(loc='upper right')
plt.xlabel('Price')
plt.ylabel('Count')
plt.show();*

Figure 5
总的来说,非周六晚上搜索,价格更稳定,更低。周六晚上搜索时价格会上涨。似乎这家酒店在周末很受欢迎。
基于聚类的异常检测
k 均值算法
k-means 是一种广泛使用的聚类算法。它创建了“k”个相似的数据点聚类。不属于这些组的数据实例可能会被标记为异常。在开始 k-means 聚类之前,我们使用 elbow 方法来确定最佳的聚类数。
elbow_curve.py

Figure 6
从上面的肘形曲线中,我们看到该图在 10 个聚类之后变平,这意味着增加更多的聚类并不能解释我们的相关变量中更多的变化;在这个案例中price_usd。
我们设置n_clusters=10,并在生成 k-means 输出时使用数据来绘制 3D 聚类。
k-means_3D.py

Figure 7
现在我们需要找出要保留的组件(特性)的数量。
PCA.py

Figure 8
我们看到第一个因素解释了将近 50%的差异。第二个成分解释了 30%以上。然而,我们必须注意到,几乎没有一个组件是真正可以忽略的。前两个组件包含 80%以上的信息。所以,我们将设置n_components=2。
基于聚类的异常检测中强调的假设是,如果我们对数据进行聚类,正常数据将属于聚类,而异常将不属于任何聚类或属于小聚类。我们使用以下步骤来查找和可视化异常。
- 计算每个点与其最近质心之间的距离。最大的距离被认为是异常。
- 我们使用
outliers_fraction向算法提供关于数据集中异常值比例的信息。不同数据集的情况可能有所不同。然而,作为一个起始数字,我估计了outliers_fraction=0.01,因为它是在标准化正态分布中,Z 得分距离平均值超过绝对值 3 的观察值的百分比。 - 使用
outliers_fraction计算number_of_outliers。 - 将
threshold设为这些异常值的最小距离。 anomaly1的异常结果包含上述方法簇(0:正常,1:异常)。- 使用集群视图可视化异常。
- 用时序视图可视化异常。
viz_cluster_view.py

Figure 9
viz_time_series_view.py

Figure 10
似乎 k-均值聚类检测到的异常要么是一些非常高的比率,要么是一些非常低的比率。
隔离森林进行正常检测**
隔离林纯粹基于异常是少量且不同的数据点这一事实来检测异常。异常隔离是在不采用任何距离或密度测量的情况下实现的。这种方法从根本上不同于基于聚类或基于距离的算法。
- 当应用一个 IsolationForest 模型时,我们设置
contamination = outliers_fraction,也就是告诉模型数据集中异常值的比例是 0.01。 fit和predict(data)对数据进行离群点检测,正常返回 1,异常返回-1。- 最后,我们用时间序列视图可视化异常。
IsolationForest.py

Figure 11
基于支持向量机的异常检测
一个 SVM 通常与监督学习相关联,但 OneClassSVM 可用于将异常识别为一个非监督问题,该问题学习异常检测的决策函数:将新数据分类为与训练集相似或不同。
OneClassSVM
根据论文:支持向量机方法进行新颖性检测。支持向量机是最大边际方法,即它们不模拟概率分布。用于异常检测的 SVM 的思想是找到一个函数,该函数对于具有高密度点的区域是正的,而对于低密度点的区域是负的。
- 在拟合 OneClassSVM 模型时,我们设置
nu=outliers_fraction,它是训练误差分数的上界,也是支持向量分数的下界,必须在 0 到 1 之间。基本上这意味着在我们的数据中我们期望的异常值的比例。 - 指定算法中使用的内核类型:
rbf。这将使 SVM 能够使用非线性函数将超空间投影到更高维度。 gamma是 RBF 内核类型的参数,控制单个训练样本的影响——这会影响模型的“平滑度”。通过实验,我没有发现任何显著的差异。predict(data)对数据进行分类,由于我们的模型是单类模型,所以返回+1 或-1,-1 为异常,1 为正常。
OneClassSVM.py

Figure 12
使用高斯分布的异常检测
高斯分布也叫正态分布。我们将使用高斯分布来开发异常检测算法,也就是说,我们将假设我们的数据是正态分布的。这是一个假设,不能适用于所有的数据集,但当它适用时,它证明了一个发现异常值的有效方法。
Scikit-Learn 的[**covariance.EllipticEnvelope**](https://scikit-learn.org/stable/modules/generated/sklearn.covariance.EllipticEnvelope.html)是一个函数,它试图通过假设我们的整个数据是一个潜在的多元高斯分布的表达式来计算出我们数据的总体分布的关键参数。过程大概是这样的:
- 基于前面定义的类别创建两个不同的数据集,search_Sat_night,Search_Non_Sat_night。
- 在每个类别应用
EllipticEnvelope(高斯分布)。 - 我们设置
contamination参数,它是数据集中异常值的比例。 - 我们使用
decision_function来计算给定观测值的决策函数。它等于移动后的马氏距离。作为异常值的阈值是 0,这确保了与其他异常值检测算法的兼容性。 predict(X_train)根据拟合的模型预测 X_train 的标签(1 个正常,-1 个异常)。
EllipticEnvelope.py

Figure 13
有趣的是,通过这种方式发现的异常只观察到了异常高的价格,而没有观察到异常低的价格。
到目前为止,我们已经用四种不同的方法进行了价格异常检测。因为我们的异常检测是无监督学习。在建立模型之后,我们不知道它做得有多好,因为我们没有任何东西可以测试它。因此,在将这些方法应用于关键路径之前,需要对其结果进行实地测试。
Jupyter 笔记本可以在 Github 上找到。享受这周剩下的时光吧!
参考资料:
特定主题的经验:新手专业经验:无行业经验本概述旨在…
www.datascience.com](https://www.datascience.com/blog/python-anomaly-detection) [## sk learn . ensemble . isolation forest-sci kit-learn 0 . 20 . 2 文档
decision_function 的行为可以是“旧的”或“新的”。传递行为= '新'使…
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html) [## sk learn . SVM . oneclasssvm-sci kit-learn 0 . 20 . 2 文档
指定要在算法中使用的内核类型。它必须是“线性”、“多边形”、“rbf”、“sigmoid”中的一个…
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.svm.OneClassSVM.html) [## sklearn .协方差. elliptic envelope-sci kit-learn 0 . 20 . 2 文档
如果为真,则计算稳健位置和协方差估计的支持,并且重新计算协方差估计…
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.covariance.EllipticEnvelope.html) [## 无监督异常检测| Kaggle
编辑描述
www.kaggle.com](https://www.kaggle.com/victorambonati/unsupervised-anomaly-detection)*
Python 中使用 Prophet 进行时间序列预测
在本帖中我们将探讨 facebook 的时间序列模型先知。我们将了解什么是先知和它的优势。我们探索 Prophet 使用一个数据集来了解变化点,如何包括假期,最后使用多个回归变量进行时间序列预测。

什么是先知?
Prophet 是 facebooks 的开源时间序列预测。Prophet 将时间序列分解为趋势性、季节性和假日性。它有直观的超级参数,很容易调整。
先知时间序列=趋势+季节性+假日+误差
- 趋势对时间序列值的非周期性变化进行建模。
- 季节性是周期性变化,如每日、每周或每年的季节性。
- 在一天或一段时间内不定期发生的假日效应。
- 误差项是模型无法解释的。
使用 Prophet 的优势
- 适应多个时期的季节性
- 先知对缺失的价值观有弹性
- 处理 Prophet 中异常值的最佳方法是删除它们
- 模型的拟合是快速的
- 易于调整的直观超级参数
安装 Prophet
使用命令提示符或使用 pip 的 Anaconda 提示符安装 Prophet
**pip install fbprophet**
我们也可以安装 plotly 为 prophet 绘制数据
**pip install plotly**
为 Prophet 创建输入数据
Prophet 的输入是一个至少有两列的数据帧:ds 和 y。
ds 是日期戳列,应该符合 pandas datatime 格式,时间戳为 YYYY-MM-DD 或 YYYY-MM-DD HH:MM:SS。
y 是我们要预测或预报的数值列。
Prophet 遵循 sklearn 模型 API 创建 Prophet 的实例,拟合 Prophet 对象上的数据,然后预测未来值。
我们现在直接进入代码,看看变化点,如何包括假期,然后添加多个回归变量。
导入所需的库
from fbprophet import Prophet
from fbprophet.plot import plot_plotly
import numpy as np
import pandas as pdimport matplotlib.pyplot as plt
import plotly.offline as py
py.init_notebook_mode()
%matplotlib inline
从 csv 文件中读取数据
dataset= pd.read_csv(“C:\\avocado-prices\\avocado.csv”)
理解数据
让我们首先来看看列和数据
dataset.head(2)

让我们打印关于数据集的信息,包括列、列的数据类型以及列是否为空
dataset.info()

我们看到两个分类变量,类型和地区。让我们检查一下
dataset.describe(include=’O’)

使用 LabelEncoder 将分类变量转换为数值
我们将具有两个不同值的分类变量 type 转换为数值。为了将分类变量转换成数值,我们使用了 LabelEncoder。在这个例子中,我们没有转换分类变量 region。
**from sklearn.preprocessing import LabelEncoder**le = LabelEncoder()
dataset.iloc[:,10] = le.fit_transform(dataset.iloc[:,10])
dataset.head(2)

type is now converted to numeric
创建输入要素(X)和目标变量(y)
X= dataset[['Date',‘Total Volume’, ‘4046’, ‘4225’, ‘4770’,
‘Small Bags’, ‘Large Bags’, ‘XLarge Bags’, ‘type’]]
y= dataset.iloc[:,1]
为 Prophet 创建数据集
如前所述,Prophet 的输入是一个至少包含两列的数据帧:ds 和 y
train_dataset= pd.DataFrame()
train_dataset['ds'] = pd.to_datetime(X["Date"])
train_dataset['y']=y
train_dataset.head(2)

使用默认值创建和拟合 Prophet 模型
我们将首先探索默认的 Prophet 模型。使用所有默认值创建 Prophet 实例,以适应数据集。
**prophet_basic = Prophet()
prophet_basic.fit(train_dataset)**
预测未来的价值
为了使用 Prophet 预测值,我们需要创建一个带有 ds(datetime stamp)的 dataframe,其中包含我们要进行预测的日期。
我们用make _ future _ data frame()给我们指定的天数延伸到未来。默认情况下,它包括历史记录中的日期
**future= prophet_basic.make_future_dataframe(periods=300)
future.tail(2)**

原始数据集中的总行数是 18249,我们看到我们为预测创建的未来数据框包含历史日期和另外 300 个日期。
**forecast=prophet_basic.predict(future)**
绘制预测数据
fig1 =prophet_basic.plot(forecast)

绘制预测组件
我们可以绘制趋势和季节性,预测的组成部分。
fig1 = prophet_basic.plot_components(forecast)

Components of the forecast
给先知增加改变点
变点是时间序列在轨迹中发生突变的日期时间点。
默认情况下,Prophet 向数据集的最初 80%添加 25 个变点。
让我们画出发生潜在变化点的垂直线
**from fbprophet.plot import add_changepoints_to_plot**fig = prophet_basic.plot(forecast)
**a = add_changepoints_to_plot(fig.gca(), prophet_basic, forecast)**

Vertical lines are where changepoints occurred
我们可以查看变化点发生的日期
**prophet_basic.changepoints**

我们可以通过设置 变点 _ 范围 来改变推断的变点范围
**pro_change= Prophet(changepoint_range=0.9)**forecast = pro_change.fit(train_dataset).predict(future)
fig= pro_change.plot(forecast);
a = add_changepoints_to_plot(fig.gca(), pro_change, forecast)

在初始化 prophet 时,可以使用n _ change points参数设置变点数
**pro_change= Prophet(n_changepoints=20, yearly_seasonality=True)**forecast = pro_change.fit(train_dataset).predict(future)
fig= pro_change.plot(forecast);
a = add_changepoints_to_plot(fig.gca(), pro_change, forecast)

调整趋势
Prophet 允许您调整趋势,以防过度拟合或拟合不足。change point _ prior _ scale帮助调整趋势的强弱。
change point _ prior _ scale 的默认值为 0.05。减小该值会降低趋势的灵活性。增加change point _ prior _ scale的值,使趋势更加灵活。
将change point _ prior _ scale增加到 0.08,使趋势更加灵活
**pro_change= Prophet(n_changepoints=20, yearly_seasonality=True, changepoint_prior_scale=0.08)**
forecast = pro_change.fit(train_dataset).predict(future)
fig= pro_change.plot(forecast);
a = add_changepoints_to_plot(fig.gca(), pro_change, forecast)

将change point _ prior _ scale减小至 0.001,以降低趋势的灵活性
**pro_change= Prophet(n_changepoints=20, yearly_seasonality=True, changepoint_prior_scale=0.001**)
forecast = pro_change.fit(train_dataset).predict(future)
fig= pro_change.plot(forecast);
a = add_changepoints_to_plot(fig.gca(), pro_change, forecast)

添加假日
节假日和事件会导致时间序列发生变化。在我们的例子中,7 月 31 日的全国鳄梨日和 9 月 16 日的鳄梨日会影响鳄梨的价格。
我们可以通过创建一个包含两列 ds 和 holiday 的 dataframe 来为 Prophet 创建一个定制的假日列表。假日的每一个事件占一行
**avocado_season = pd.DataFrame({
'holiday': 'avocado season',
'ds': pd.to_datetime(['2014-07-31', '2014-09-16',
'2015-07-31', '2015-09-16',
'2016-07-31', '2016-09-16',
'2017-07-31', '2017-09-16',
'2018-07-31', '2018-09-16',
'2019-07-31', '2019-09-16']),
'lower_window': -1,
'upper_window': 0,
})**
下部窗口和上部窗口将假期延长至日期前后的天。如果我们想包含国家鳄梨日和鳄梨酱日之前的一天,我们设置lower _ window:-1 upper _ window:0
如果我们想使用假期后的一天,那么设置lower _ window:0 upper _ window:1
pro_holiday= Prophet(**holidays=avocado_season**)
pro_holiday.fit(train_dataset)
future_data = pro_holiday.make_future_dataframe(periods=12, freq = 'm')
#forecast the data for future dataforecast_data = pro_holiday.predict(future_data)
pro_holiday.plot(forecast_data);

添加多个回归变量
可以向 Prophet 模型中添加额外的回归变量。这是通过使用 add_regressor 来完成的。拟合和预测数据框架中都需要有额外的回归变量 列值。
使用附加回归量创建拟合和预测数据集
train_dataset[‘type’] = X[‘type’]
train_dataset[‘Total Volume’] = X[‘Total Volume’]
train_dataset[‘4046’] = X[‘4046’]
train_dataset[‘4225’] = X[‘4225’]
train_dataset[‘4770’] = X[‘4770’]
train_dataset[‘Small Bags’] = X[‘Small Bags’]train_X= train_dataset[:18000]
test_X= train_dataset[18000:]
我们对数据集进行了分割,以展示额外回归变量的使用,因为我们需要拟合和预测数据框中所有额外回归变量的值
#Additional Regressor
**pro_regressor= Prophet()
pro_regressor.add_regressor('type')
pro_regressor.add_regressor('Total Volume')
pro_regressor.add_regressor('4046')
pro_regressor.add_regressor('4225')
pro_regressor.add_regressor('4770')
pro_regressor.add_regressor('Small Bags')**#Fitting the data
**pro_regressor.fit(train_X)
future_data = pro_regressor.make_future_dataframe(periods=249)**#forecast the data for Test data
**forecast_data = pro_regressor.predict(test_X)**
pro_regressor.plot(forecast_data);

Prediction using additional regressor
预测数据是最后的蓝色阴影区域。
Jupyter 笔记本可用此处
参考资料:
https://facebook.github.io/prophet/docs/quick_start.html
https://peerj.com/preprints/3190.pdf
人工智能专家:是时候让守护者保护我们自己了
计算机越来越多地使用我们的数据来对我们做出决定,但我们能信任它们吗?
每天,在你不知情的情况下,计算机算法会利用你的数据来预测你的习惯、偏好和行为。
他们认为你喜欢 YouTube 上的猫视频意味着你会收到胡须广告的垃圾邮件,或者你的披头士下载意味着你想听保罗·麦卡特尼的第 100 首单曲。
如果你喜欢被推荐的音乐,或者不觉得广告反映了你令人毛骨悚然的网络浏览,那么你可能不会介意。
但是通过算法做出决策要更进一步。
算法正在决定谁能通过护照检查,谁能收到债务催收通知、房屋贷款和保险,甚至谁会成为警察的目标以及他们的刑期有多长。
最近,透露了算法告诉经期跟踪应用程序通知脸书你可能怀孕了。
算法基本上是计算机如何处理它接收到的数据的一组指令。
随着越来越多的系统变得自动化和个性化,这些输入越来越成为我们的个人数据:手机位置、社交媒体或应用程序使用习惯、网页浏览历史,甚至健康信息。
问题在于,你永远不知道一种算法是如何处理你的数据并做出决定的:你的抵押贷款申请被拒绝是基于你的未付账单历史还是你头发的颜色。
事实上,你对决策过程没有任何意见,你可以保证你的利益将永远支持那些开发应用程序的人。

Your trail of mobile and other data is being monetised daily
一群领先的计算机科学家最近一直在讨论在这个新兴系统中更好地保护我们自己的必要性。
他们说如果不采取行动,我们将失去对个人数据的控制,也失去对我们决策的透明度。
RMIT 大学副教授 Flora Salim、UNSW 大学教授 Salil Kanhere 和迪肯大学教授 Seng Loke 提出的解决方案之一是编写我们自己的算法监护人。
什么是“算法守护者”?
算法守护者将会是个人助理机器人,甚至是伴随我们到任何地方的全息图,并提醒我们在线幕后发生的事情。
这些守护者本身就是算法,但它们只为我们工作,被编程为根据我们的个人偏好管理我们与社交平台和应用程序的数字交互。
它们可以根据我们的意愿改变我们的数字身份,对不同的服务应用不同的设置,甚至在我们选择的时候让我们变得可识别或匿名。
我们的监护人可以确保我们的备份和密码是安全的,并允许我们决定在我们的在线存在中记住什么和忘记什么。
实际上,算法监护人将:
- 如果我们的位置、在线活动或对话被监控或跟踪,提醒我们,并给我们选择消失
- 当我们注册在线服务时,请帮助我们理解冗长繁琐的条款和条件的相关要点
- 当我们不明白我们的电脑、电话记录和手机后台运行的数十个应用程序之间的数据发生了什么变化时,请给我们一个简单的解释
- 如果有应用程序将我们手机中的数据发送给第三方,请通知我们,并让我们选择实时阻止它
- 请告诉我们,我们的数据是否被第三方货币化,以及用途是什么。
算法守护者被设想为当前个人助理(如 Siri、Alexa 或 Watson)的下一代。
他们不需要像人类一样聪明,只要与他们居住的环境相关就行——识别其他算法并解释他们在做什么。
如果没有这种责任感,我们生活中的关键时刻将越来越多地被未知的、看不见的和任意的算法所影响。
算法监护人将承担沟通和解释这些决定的重要角色。
可解释的机器学习是人工智能研究中越来越感兴趣和活跃的一个领域,它试图提供对算法如何做出最终决定的洞察。
既然算法已经渗透到日常生活中,可解释性不再是一种选择,而是一个迫切需要进一步关注的领域。
算法守护者何时到来?
就在我们说话的时候,实现算法守护者的技术正在出现,滞后的是我们需要它们的普遍意识。
你可以在存储和管理密码的数字保险库中,以及在让我们对如何使用我们的数据进行一些控制的软件设置中,看到算法守护者技术的原始版本。但是在普适计算时代,需要更全面的东西。
该团队表示,我们需要在未来几年内开发特定的算法监护人模型,为未来十年的开放算法系统奠定基础。
需求肯定是存在的,是吗?
在过去的十年里,隐私的概念发生了根本性的变化。
有没有可能在下一个十年里,我们甚至不会在乎每个系统都知道我们的一切,并利用这些信息为所欲为,因为大多数情况下,它都工作得很好?
本文改编自《对话》中出现的 一片 ,作者为萨利姆、坎 here 和洛克。
迈克尔·奎恩
是时候停止在虚假点击上浪费金钱了!
用机器学习处理点击欺诈

Image source: https://www.bankinfosecurity.com/click-fraud-kingpin-receives-7-year-sentence-a-9072
什么是点击欺诈?
隐藏在 300×250 像素横幅后面的是一个复杂的数字广告生态系统。与传统广告业相比,互联网时代的新商业模式涉及广告专员(也称为广告网络),充当广告商和内容出版商之间的经纪人。
广告商计划预算,向专员提供广告,并就每个客户行为(例如,点击广告、填写表格、在拍卖中出价等)商定佣金。内容发行商与专员签订合同,在他们的网站上显示广告,并根据它给广告商带来的流量获得佣金。然而,这种模式可能会刺激不诚实的出版商在他们的网站上产生非法点击——这是一个被称为点击欺诈的主要问题。
数据介绍
这篇文章描述了我的个人机器学习项目,即针对移动应用广告的点击欺诈预测。所有的源代码都可以在我的 Github 上找到:https://github.com/jystacy/Click_Fraud。这个项目来源于 Kaggle 的 TalkingData AdTracking 欺诈检测挑战赛,旨在预测用户点击移动应用广告后是否会下载某个应用。这个人工数据集的整个时间范围包括 27 分钟。
数据集的每一行都包含一条点击记录,具有以下特征:
ip:点击的 ip 地址。app:营销用 app id。device:用户手机的设备类型 id(如 iphone 6 plus、iphone 7、华为 mate 7 等。)os:用户手机的 os 版本 idchannel:移动广告发布商的渠道 idclick_time:点击时间戳(UTC)is_attributed:要预测的目标,表示已经下载了 app


Summary of five original categorical features
检查标记特征的分布总是很重要的。这是一个非常不平衡的数据集,99.65%的点击都没有导致应用程序下载。为了避免即使随机猜测也能达到 99%以上的准确率,我将在数据分割后处理不平衡的挑战。

数据准备
高基数属性
数据是干净的,没有应用任何技术,因为具有七个特征的所有数据记录都是完整的。但是,值得注意的是,具有超过 100 个不同值的分类特性(应用程序、设备、操作系统和渠道)可能具有很强的预测性,同时会对包含在预测模型中造成问题。
包含这种高基数属性的一种优雅而简单的方法是将名义变量转换为一个连续变量,其值与目标标签相关。我选择了监督比率来转换这些分类特征:用一个类别中正面实例的百分比(is_attributed = 1)替换名义上的表示值。
特征工程
给定原始变量可以提供的有限信息,特征生成将对模型性能产生强烈影响。以点击计数为导向的收入分享系统为虚假点击提供了肥沃的土壤,所以我试图创建一系列特征来捕捉点击行为的异常行为模式。某段时间内来自某个 ip、某个设备、某个操作系统、某个应用程序或某个渠道的点击次数都可能是很好的预测指标。我利用(然后删除)前 60 秒内的点击记录来为所有样本生成额外的预测值。
我创建了 25 (=5*5)功能,通过计算特定 ip、操作系统或设备或通过特定应用程序或渠道产生的点击记录之前 1、3、10、30 和 60 秒内的点击计数。对于这五个原始分类特征(ip、os、app、频道和设备)的每个组合,40(= 5 (5–1) 2)更多创建的交互时间窗口计数特征集中在每个点击记录之前的 10 秒和 3 秒的时间间隔。例如, ip_channel_10s 表示在过去 10 秒内对特定频道做出点击的唯一 ip 的计数,而 channel_ip_10s 表示特定 ip 在过去 10 秒内点击的频道的计数。
通过使用 python 中的多处理库并行计算对超过 1 亿个值的特征工程实现过程进行了超过 10000%的优化。我的 Github 上也有代码。
误差分配
我执行了 80/20 的训练-测试分割,使用前 80%的点击进行训练,后 20%作为测试数据,因为没有点击和欺诈的时间序列模式(如 EDA 部分的前两个图表所示)。然后,我对大多数进行随机下采样,以组成一个平衡的训练数据集。在平衡数据之后,我再次输出类分布来可视化差异。


数据缩放
在这个项目中,数字特征的范围变化很大。如果数据集中的某个要素与其他要素相比规模较大,则此大规模要素将成为主导要素,需要针对测量欧氏距离的算法(如 KNN 和 SVC)进行归一化。我使用 scikit-learn 库中的 StandardScaler 进行数据缩放。
探索性数据分析
我是从点击记录和欺诈点击的时间序列分布开始 EDA 的。然而,在这种情况下,数据收集的持续时间太短,无法显示时间序列模式。因此,我没有从点击时间特性中提取小时或分钟属性。相反,我根据时间序列分割数据集,而不考虑偏差。


在生成了数百万个基于点击计数的数值变量之后,需要检查属性之间的相关性。从相关性热图来看,这些累计计数属性之间存在高度的正相关性,比如一个 app 或一个频道在过去 1 秒和 3 秒内获得的点击计数。因此,在线性模型的模型训练期间,主成分分析(PCA)将有助于更好的模型性能。

作为可视化探索的最后一步,我们来检查一下数据的可分性。为了可视化高维数据集,我选择了 t 分布随机邻居嵌入 ( t-SNE ),这是另一种比 PCA 更适合可视化的降维技术,旨在" 最小化两种分布之间的差异:一种分布测量输入对象的成对相似性,另一种分布测量嵌入中相应低维点的成对相似性。
具有两个结果维度的平衡训练数据的散点图可以在模型选择方面提供提示。例如,图表显示,在这种情况下,SVM 极有可能表现不佳。

模特培训
性能赋值
如何评估模型的性能应该与项目的目标相匹配。这种情况下的目标是从不平衡的数据集中检测虚假点击,并预测用户在点击移动应用广告后是否会下载应用。因此,我使用了 ROC-AUC (受试者操作特征-曲线下面积)性能指标。ROC 是概率曲线,AUC(0 和 1 之间的值)代表可分性的程度或度量。它告诉我们模型在多大程度上能够区分不同的类。如果一个算法的 ROC-AUC 得分高于 0.5,则它比随机猜测获得了更高的性能。
型号选择
本项目中考虑的模型包括最流行的分类算法:
- 逻辑回归
- 线性判别分析
- k 最近邻(KNN)
- 分类树
- 支持向量分类器
- XGBoost 分类器
- 随机森林分类器
模型选择的输入数据是所有的数字计数特征。我使用 10 重交叉验证来评估模型在训练数据集上的性能。我为不同类型的分类模型定制了输入数据。我将 PCA 生成的 13 个特征(保留了 95%的方差)输入线性模型——逻辑回归和 LDA。对于基于距离的算法(KNN 和 SVC),所有输入数据都是标准化的。

由于在点击欺诈的情况下强调的是预测欺诈点击的能力,而不是可解释性,XGBoost 在 ROC-AUC 得分方面无疑优于其他模型。此外,SVM 的 ROC-AUC 评分验证了 t-SNE 可视化产生的猜测。
XGBoost 的模型训练
XGBoost 本质上不受特征量和多重共线性的影响。我的 XGBoost 性能改进策略包括向模型中添加转换后的高基数分类变量以增加分类特征提供的信息量,使用验证数据集仔细调整超参数以在过度拟合和欠拟合之间进行权衡,以及根据特征重要性分析优化输入特征的数量。
- 没有分类特征的优化模型:

- 具有高基数分类特性的优化模型:

- 具有转换的高基数分类特征的优化模型:

结论
我最终选择了经过良好调优的 XGBoost 模型,它有 20 个最重要的属性,包括数字点击计数变量和转换后的高基数分类特性。测试数据集上的 ROC-AUC 得分达到 0.969132,同时避免了过拟合。
在记录点击的频道方面的特征在特征重要性方面排名最高的发现表明不诚实的移动广告发布者倾向于集中而不是分散某些频道上的欺诈点击,以便为高点击计数要求更高的奖励。
下一步
类别特征的实体嵌入
说到分类特征,有几种处理特征包含的技术。由于高基数特征一键编码的计算效率低和潜在的稀疏性问题,一种源于神经网络的新技术——实体嵌入受到越来越多的关注。
实体嵌入与我在项目中使用的转换方法(监督比率)有相似的原则,即产生的嵌入向量是类别的表示,其中相似的类别(相对于任务)彼此更接近,而实体嵌入在嵌入向量的维度上更灵活。后一个特征提高了揭示范畴变量内在连续性的能力,同时可以保留不同基数之间的更多差异。所以我计划将实体嵌入应用于分类特征的转换,作为下一步的改进。
请随时查看我的 Github 上的所有代码以供参考:https://github.com/jystacy/Click_Fraud。
热烈欢迎所有的反馈和讨论。😊
Time2Vec 用于时间序列特征编码
为您的机器学习模型学习一个有价值的时间表示

Photo by Luca Micheli on Unsplash
在每个涉及时间序列的机器学习问题中,时间是黄金信息。作为数据科学家,我们必须尽最大努力提取时间模式,让我们的数据自己说话。在预处理过程中,常见的程序有标准化(平稳性检查、自相关消除…)、创建和编码分类时间特征(日、周、月、季…)、人工特征工程(傅立叶变换…)。我们的努力并不总是有回报的,因为在模型化过程中,我们选择的模型可能无法正确地将时间本身视为一个特征。
在这篇文章中,我试图再现论文' Time2Vec:学习时间的向量表示法 ' 【T5,中提出的方法,其最终目标是开发一种通用的模型不可知的时间表示法,这种表示法可以潜在地用在任何架构中(我在 Keras 中开发了一个神经网络,采用了这种解决方案)。作者不想为时间序列分析提出一个新的模型,相反,他们的目标是以向量嵌入的形式提供时间的表示,以便以更好的方式自动化特征工程过程和建模时间。
数据集
为了给出证据和整个解决方案的具体效用,我们需要一个足够的数据集。在我的例子中,我需要时间序列格式的数据,没有任何额外特征形式的冗余信息。这种情况在自回归问题中很典型,在这种情况下,我们只有一个时间序列,并将其作为预测未来的一个特征。在现实生活中这是一个常见的任务,所以不难找到一个数据集。我在 Kaggle 上发现了一个不错的。它储存了威尼斯大量的历史水位。预测这些值是一项严肃的任务;每天游客都可以获得该城市不同地区海平面的详细而准确的报告。
我爱威尼斯,我的目标不是和他们竞争。我们也没有足够的信息来提供真正明显的表现(额外的回归因素,如温度、月相、天气条件等,提供了足够的推动)。在这里,我们不得不利用仅有的历史数据来预测下一个小时的水位。

Example of hourly water level (cm) in a week
时间 2 秒实现
从数学角度来说,实现 Time2Vec 非常容易:

from: https://arxiv.org/pdf/1907.05321.pdf
其中 k 是时间 2 维,τ是原始时间序列, F 是周期性激活函数,ω和φ是一组可学习的参数。在我的实验中,我将 F 设置为一个 sin 函数,以使选定的算法能够捕捉数据中的周期性行为。同时,线性项代表时间的进程,可用于捕捉依赖于时间的输入中的非周期性模式。
这种简单性使得这种时间向量表示很容易被不同的架构所使用。在我的例子中,我试图在修改简单 Keras 密集层的神经网络结构中转移这个概念。
class T2V(Layer):
def __init__(self, output_dim=None, **kwargs):
self.output_dim = output_dim
super(T2V, self).__init__(**kwargs)
def build(self, input_shape): self.W = self.add_weight(name='W',
shape=(input_shape[-1], self.output_dim),
initializer='uniform',
trainable=True) self.P = self.add_weight(name='P',
shape=(input_shape[1], self.output_dim),
initializer='uniform',
trainable=True) self.w = self.add_weight(name='w',
shape=(input_shape[1], 1),
initializer='uniform',
trainable=True) self.p = self.add_weight(name='p',
shape=(input_shape[1], 1),
initializer='uniform',
trainable=True) super(T2V, self).build(input_shape)
def call(self, x):
original = self.w * x + self.p
sin_trans = K.sin(K.dot(x, self.W) + self.P)
return K.concatenate([sin_trans, original], -1)
该自定义层的输出维度是用户指定的隐藏维度 (1 ≤ i ≤ k) ,即从网络学习的正弦曲线,加上输入的线性表示 (i = 0)。有了这个工具,我们只需将它与其他层堆叠在一起,并在我们的案例研究中尝试它的威力。
模型
Time2Vec 是一个很好的时间表示吗?为了回答这个问题,我比较了在我们的预测任务中实现的性能,建立了两个不同的序列神经网络模型。第一个将我们定制的 Time2Vec 层作为输入,叠加在一个简单的 LSTM 层上。第二层仅由先前结构中使用的简单 LSTM 层组成。
def T2V_NN(param, dim):
inp = Input(shape=(dim,1))
x = T2V(param['t2v_dim'], dim)(inp)
x = LSTM(param['unit'], activation=param['act'])(x)
x = Dense(1)(x)
m = Model(inp, x)
m.compile(loss='mse', optimizer=Adam(lr=param['lr']))
return mdef NN(param, dim):
inp = Input(shape=(dim,1))
x = LSTM(param['unit'], activation=param['act'])(inp)
x = Dense(1)(x)
m = Model(inp, x)
m.compile(loss='mse', optimizer=Adam(lr=param['lr']))
return m
我们执行拟合程序操作超参数优化。这是使用keras-hype tune完成的。该框架以非常直观的方式提供了神经网络结构的超参数优化。我们对一些参数组合进行标准网格搜索。所有涉及的两个训练程序都要这样做。
结果
我使用前 70%的数据作为训练集,剩下的 30%作为测试集。在拟合过程中,该系列还分为验证,以便进行超参数调整。最佳和优化的 T2V + LSTM 在测试中实现了大约 1.67 MAE,而简单和优化的 LSTM 实现了大约 2.02。

这两个网络似乎都能很好地识别数据中的模式。使用 T2V 编码可以稍微提高性能。
摘要
在这篇文章中,我介绍了一种自动学习时间特征的方法。特别是,我复制了 Time2Vec ,一个时间的向量表示,使其适应神经网络架构。最后,我能够在一个真实的任务中展示这种表现的有效性。我想指出的是,正如论文作者所建议的,T2V 不是时间序列分析的新模型,而是一种简单的向量表示,可以很容易地导入到许多现有和未来的架构中,并提高它们的性能。
如果你对题目感兴趣,我建议:
保持联系: Linkedin
参考文献
Time2Vec:学习时间的向量表示法。赛义德·迈赫兰·卡泽米、里沙卜·戈埃尔、塞佩赫尔·埃格巴利、贾纳汉·拉曼南、贾斯普里特·萨霍塔、桑杰·塔库尔、斯特拉·吴、卡塔尔·史密斯、帕斯卡尔·普帕特、马库斯·布鲁贝克
时代在变,成员在变动
预测成员退出健康计划的最佳实践

Photo by rawpixel.com
每年健康计划和提供者花费大量的时间、资源和金钱来留住他们的成员。实际上,有专门关注会员参与度和忠诚度的会议,允许组织从行业领导者那里学习技巧和诀窍。
留住会员的一个策略是问“谁可能退出我的计划”这个问题。预测会员退保(“流失”)在任何计划选择由个人决定的会员群体中都是一个极其常见的用例,我将在下面解释原因。
让我来布置舞台。
每年有 11%的 Medicare Advantage 计划参与者自愿转投另一项计划(凯撒家庭基金会)。为了取整数,我们就把它定为 10%吧。为了说明 10%的退保率对计划收入的实际意义,假设您有 50,000 名成员,平均每个成员每月支付 700 美元(每个成员每年 8400 美元)的保费。如果你的组织分享了全国平均 10%的会员流失率,这意味着 5000 名会员将选择退出你的计划——损失你 4200 万美元的补偿。是的,你没看错——4200 万美元!
年复一年保持 100%的会员是不现实的,但是如果你能把退保率从 10%降低到 9%会怎么样?1%的人口对你的计划收入有多大影响?
当你减少 1%的会员流失率,你就能保留每年 420 万美元的收入!

Photo by Ben White
1%有如此大的影响,可以理解的是,健康计划和提供者正在寻找解决方案,以确定哪些成员最有可能退出他们的计划。被认定为“高风险”的成员可以加入激励/干预计划,以期改变预测的结果。
如果您希望在内部构建这一模型,或者希望使用预测分析解决方案,我们已经找到了一些最佳实践,希望您在尝试预测会员流失时谨记在心。
1.快速创建基线模型
在他在 Coursera 的机器学习课程中,吴恩达解释说,当建立一个新的机器学习模型时,你应该尽可能快地得到第一个结果,最好是在 24 小时内。我们同意!
这一切都是为了展示潜在的投资回报率。获取您可用的数据源,并获得将作为基线预测模型的第一个结果。我们经常看到团队一开始就试图构建最复杂的模型。但是如果你的数据中没有足够的信号来预测你想要的结果呢?从一个轻量级模型开始,看看最初的预测是什么样的。仅使用现成的数据流快速获得基线模型,有助于证明是否有足够的 ROI,并确定为提高模型准确性而付出的额外努力的价值。
具体到会员流失,从一年的索赔和录取数据开始。仅这些数据源就应该产生一个简单而有洞察力的基线模型。它可能没有你理想中想要的那么准确,但是它将能够识别风险极高的成员,并证明是否应该花更多的时间来更深入地开发模型。
当与您的主管、人口健康副总裁、首席财务官或首席执行官交谈时,交流投资回报看起来有所不同。为了帮助向您的组织传达您的预测模型的明确价值,ClosedLoop 在平台中内置了 ROI 图。有许多不同的观点可以根据你的受众来定制信息。

Image from ClosedLoop.ai Platform
在闭环,我们用一些主要参数计算 ROI。人口规模、结果成本(您的组织将花费多少干预成本)、干预成本(您的组织运行特定干预的成本)和干预功效(干预的有效性)。
2.使用所有可用的患者数据
机器学习从多个数据源中提取有用的模式,以建立更准确和全面的风险评分。一旦建立了基线模型,就开始测试额外的患者可链接数据(ADT feeds、EMR、社会因素、实验室等)的预测价值。).这里的一行外卖— 使用所有可用的患者数据 。
如果你计划在内部建立这个模型,这个过程就变得非常昂贵和劳动密集。首先,想想你的数据来自多少不同的内部部门和外部组织,然后想想每个来源中的数据是如何以自己特定的方式格式化的。以索赔中的患者 ID 列为例。它将位于数据集中数百列中的一列。现在,看看您的 ADT 提要或 EHR,不仅这个患者 ID 不在同一列,而且它可能有完全不同的列标题。如果这还不够混乱的话,还有一个病人 ID 栏,但它与您声明中的 ID 不同。手动搜索多个数据源中的数百列既耗时又令人困惑,而且没有数据科学家愿意这样做!
ClosedLoop 在平台中内置了许多不同的功能,可以自动接收不同的数据源,包括定制的专有数据集。在这种自动化方法中,测试和试验哪些数据源会产生增量预测值只需最少的工作。因为工作量很小,所以尽可能多地测试数据源!
在预测会员流失时,我们发现了几个可以提高模型准确性的外部数据源。例如社会决定因素数据,如美国农业部食物图谱和人口普查数据(也是公开的!)可以提供大量的价值,让你了解你的人口的营养和经济状况。现在,从这些数据源本身开始不会产生很好的结果(这是非常棘手的),但是将它们放在一个基线模型之上是非常有效的,该模型包含带有患者人口统计数据的声明。为你的预测模型提供支持的数据源越多,你的风险评分和预测就越全面,越有解释力。
3.采取行动
太好了,你已经确定了有风险的成员。但是,预测谁最有可能退出你的计划只是拼图的第一部分。你打算如何处理这些预测?
对处于危险中的成员进行干预,是您的组织采取行动并试图改变预测结果的机会。但是你的干预应该是什么呢?它可能会打电话给高风险会员,询问他们是否喜欢他们的医生,如果不喜欢,就提议安排下一次与新医生的预约。也许这是一个真正的来自护理经理的电话提醒,而不是来自自动线路。对于退出网络的会员,干预措施可以是建议转介给网络内提供者。
我们建议以多种方式利用分析。同样,如果你计划在内部建立这个模型,这一块是相当棘手的。通过为相似的患者群体提供个性化的护理方法,提供多种干预措施是非常有益的,但是您如何决定哪个患者从哪种干预措施中受益最大呢?
当针对特定的患者群组采取不同的干预措施时,了解某个成员被确定为高风险的原因会有所帮助。ClosedLoop 正是提供了对预测的人类可读的解释,称为起作用的因素。这些因素使您可以看到某人被确定为高风险的确切原因,从而更容易将特定的成员群组与不同的干预措施相关联。
预测会员流失是所有健康计划的首要任务,会员选择是个人的决定,在看到 1%的会员可能产生的影响后,很容易明白为什么会这样。如果您希望构建这种预测模型或与解决方案提供商合作,我们希望您记住这些最佳实践。
快速建立模型:尽可能快地建立一个新模型,然后进行迭代以提高模型的准确性。
使用所有可用的患者数据:添加标准和专有数据集,为每个成员创建更准确和全面的风险评分。
采取行动:没有行动的预测是对时间、金钱和资源的巨大浪费。让会员参与不同的干预措施,以期主动改变预测的结果。

作者:Allyson CIA burri| closed loop . ai |医疗保健营销
原载于 2019 年 6 月 13 日https://closed loop . ai。
时间序列数据管理—分布在多个组中的滞后变量

Photo by Jon Tyson on Unsplash
方法链接、分组和索引操作
对时间序列数据建模可能具有挑战性,因此一些数据爱好者(包括我自己)推迟学习这个主题直到他们绝对必须这样做是有道理的。在将机器学习模型应用于时间序列数据之前,您必须将其转换为模型的“可吸收”格式,这通常涉及计算滞后变量,这可以测量自相关,即变量的过去值如何影响其未来值,从而释放预测值。以下是我最近用来生成熊猫滞后变量的三种不同方法:
1。在一组中滞后一个或多个变量—使用 移位 方法
2。跨多个组延迟一个变量—使用 分解 方法
3。跨多个组延迟多个变量—使用 groupby
首先,让我们生成一些虚拟时间序列数据,因为它将“在野外”出现,并将它放入三个数据帧中用于说明目的(所有代码在一个地方)。
其次,做一些转换,让 pandas 将您的 dates 列识别为一个 datetime 变量。这对我们以后会有帮助。旁注,显然是熊猫的策划者,韦斯·麦金尼,特别发明了熊猫来解决处理时间索引数据的问题。因此,在生成虚拟数据并转换日期列之后,您现在应该有 3 个数据帧,如下所示。

现在是有趣的部分!第一种方法非常简单,如下所示。
1。在一个组/类别中滞后一个或多个变量——使用“移位”方法
这里,我们简单地使用可用于 dataframe 的 shift 方法,并指定在将日期列设置为索引后要延迟的步数(在我们的例子中,是 1“天”)。记住,你也可以使用负数作为位移,这意味着未来的值正在影响过去(时间机器,有人知道吗?😊).
df_onegrp.set_index(["date"]).shift(1)

注意第一行现在有空值,表明我们确实滞后了数据。如果您落后两步,前两行将为空等。对于这个例子,索引已经是惟一的了,但是您可能希望对其他数据进行检查,以避免意外的后果。
2。将一个变量延迟到多个组——使用“拆分”方法
这种方法稍微复杂一些,因为有几个组,但易于管理,因为只有一个变量需要滞后。总的来说,我们应该意识到,我们希望首先对数据进行索引,然后在应用 lag 函数之前,通过 T2 分解来分离组。不这样做实际上会对您的数据做错误的事情。例如,它可以将前一个组的最后一个值移动到下一个组的第一个值上,从而跨组混合数据。想象一下,如果这些群体是国家,变量是以年为单位的人口。如果你犯了这样的错误,这就像假设宾夕法尼亚州晚年的人口会影响罗德岛早年的人口,因为这两个州按字母顺序相邻。这说不通。这可能是一个巨大的陷阱,会导致完全错误的分析。
因此,将索引设置为您的日期和组。然后使用拆垛拉出组,然后移动列,就像前面的方法一样。更多关于堆叠、拆解技巧的信息,请看我的另一篇 文章这里 。
现在将组放回行中。注意如何保存空值,然后对它们做任何你想做的事情(替换,删除等等)。)
为了便于说明,我选择保留空值/缺失值并重新排列数据
df.reset_index().sort_values("group")

好的,如果你密切关注,你会注意到这种方法也适用于许多组中的许多变量,但是我想把这个场景留给另一种技术,在下一节中使用 groupby 来代替。所以,你可以停止阅读,使用上面的方法。但是你很好奇,所以我们继续…

Photo by Joakim Honkasalo on Unsplash
3。 同时延迟分布在多个组中的多个变量——使用“分组依据”方法
这个方法依赖于 pandas groupby 函数结合我们在前面的方法中学到的所有招数。所以我不会花时间解释我们已经讨论过的概念。关键步骤是使用“组”列对数据进行分组;制作一个函数,使对进行排序,按日期对进行索引,对每组中的数据进行移位,然后通过对象对组中的进行迭代,将函数应用于每组。最后,我们使用便利的列表理解,然后将这个列表连接回其原始格式。
这种方法中使用的一些很酷的概念是:
- 赋值 : 我最近发现了数据帧可用的赋值方法。它清理了您的代码,允许您生成一个新列并为其分配新值,而不必使用中间的 dataframe 。它会自动返回数据的副本。
- 方法链接 : 该函数还在返回语句中使用括号,以便允许方法链接,这是编写干净、易读代码的另一种方式。
将数据分组:
grouped_df = df_combo.groupby(["group"])
使用赋值和方法-链接创建功能:
使用列表理解对每个组应用函数,然后垂直连接:
dflist = [lag_by_group(g, grouped_df.get_group(g)) for g in grouped_df.groups.keys()]pd.concat(dflist, axis=0).reset_index())

这就对了。滞后时间序列的三种不同方法。可能还有更多,例如,您可以通过 x 步骤移动数据,然后删除每个组的第一个 x 步骤,但是我认为上述解决方案更加健壮和灵活,允许您对空值做任何您想做的事情。下面让我知道你的想法。
编码快乐!
修补张量和其他伟大的冒险

Source: www.pexels.com
在(不严格地)保持理智的同时,思考如何实现你的第一篇深度学习论文。
在 2018 年底一个普遍不起眼的周三,我听从了互联网明智的建议,踏上了通往人工智能中心的痛苦旅程;我开始在自然语言处理(NLP)中实现深度学习研究论文。
经过许多天驯服怪物、追捕真正科学家的材料、凝视黑暗之心,我出现了疲惫,但胜利。接下来是对解决这样一个项目的动机和期望的描述。
如果你也敢冒险进入深海,那就加入我吧。
…正如 Ilya 喜欢说的那样,你需要做好遭受痛苦的准备:预计将花费数小时调试拒绝学习的模型,许多遍重新构造你的代码,并为改变各种超参数建立你自己的约定。但是每次你遭受痛苦的时候,要知道你已经积累了一点技能,这对未来是无价的。
——格雷格·布罗克曼, Quora 05/16
动机
为什么要实现一篇研究论文?为什么是 NLP?
先说后者。
假设你想为人类的持续利益创造有益的人工智能(我的意思是,谁不想呢?),你就必须创造一个具有高级推理能力的系统,并且能够更好地向人类解释其意识的内容。自然语言理解(NLU)是处理这些基本问题的人工智能的一个子领域,它本身嵌套在更大的自然语言处理学科中。
更简单地说, 教机器理解语言对于安全解开智能本身的奥秘至关重要。
此外,如果你关注了 2018 年发布的flurry论文 ,你就会知道,尽管计算机视觉凭借其在深度学习方面的突破和应用长期以来一直吸引着公众的注意力,NLP 的时代已经到来。这一点,以及我在硅谷一家对话式人工智能初创公司担任机器学习工程师的角色,极大地激发了我对这一领域的兴趣。
所以,这里有两个令人信服的理由来尝试和实现一篇研究论文:
- 增进你的理解。不弄脏自己的手,你根本无法获得理论在实践中如何运作的良好直觉,而完成一篇论文会弄脏自己的手。 如果你一直在利用 书籍、在线 课程、和 录制的 讲座自学深度学习的课题,这是一个必不可少的下一步,它会无情地暴露你知识中的任何缺口。
- 成为一个坏蛋。复制一篇论文的表现并不简单,这将考验你工程能力的极限以及你的毅力。无论你已经做了一段时间,还是你刚刚开始做这个领域,最终完成这样一个项目可以作为你的“成年”仪式。 它将标志着你从一个被动的观察者转变为人工智能研究社区的积极参与者。你还会积累谦逊和自信,这样你就可以在未来面对更具挑战性的项目。
如果这些听起来有一点点有趣,那么你来对地方了。卷起袖子,涂上防晒霜,我们上路吧。

Let’s hit the road! Source: www.pexels.com
但是首先,像任何这种性质的冒险一样,我们要确保我们意识到前面的任何危险…
预期
你复制一篇研究论文的经历将受到你实现个人目标的成功程度的影响。因此,当你开始你的旅程时,要记住的最重要的事情是为自己设定合理的期望,当然,要保持水分充足。
期望#1:研究与工程
即使在阅读了其他人的经验之后,我仍然惊讶地发现,完成一篇论文会让你学到更多的工程知识,而不是研究知识。
许多在线课程将创建美丽的环境,在其中你可以玩深度学习概念。这些可以运行从预加载库的云实例到浏览器中完全集成的运动场的所有范围(想想fast . aivsuda city)。这对于降低新人的准入门槛是必要的,让他们在职业生涯的早期享受人工智能的全部荣耀。

There are many details safely hidden in online AI courses. Source: www.pexels.com
不幸的是,就像那些过度保护但用心良苦的父母的孩子一样,这种溺爱让小约翰尼对现实世界毫无准备。该由我们年轻人用实际知识来填补空白了。
我的意思是:
我不仅严重低估了这个项目需要的总时间,还错误地估计了工作的分配。我最初假设我会在周末完成这个实现,花大约五天的时间测试不同的假设,其中有 20/80 的时间。
实际上,我大约 40%的时间花在操作开销上,40%的时间花在实现、调试和测试模型架构上,最后 20%的时间花在实验上。
我花了两周半的时间,在工作前和工作后编码,在周末,这个项目总共花了我大约 60 个小时。我花了额外的 20 个小时处理模型部署,稍后会花更多的时间。
对于你的第一篇论文,假设你选择了一篇在你已经相当熟悉的学科中有点挑战性的论文,那么这种分布和时间承诺并不是不合理的。
总的来说:
- 为运作准备、预算比你认为需要的更多的时间,尤其是你的第一篇论文。利用这个机会提高你的软件工程技能和解决问题的能力。
- 在实施阶段,不断地在适当的检查点通过网络运行虚拟数据。让自己相信输出是有意义的,如果不合理就修复它。绝对不要等到所有东西都构建好了才开始调试。
- 为了记录你的实验,以及追溯过去,做详细的笔记。一个快乐的副作用是能够深情地回顾你所取得的一切。
简而言之,好好计划,闻一闻玫瑰花香,多拍几张照片。
期望#2:再现性
复制危机是一种经常折磨社会和医学科学的疾病,因为进行人体实验研究是有风险的。当学者们无法复制同行的成果时,科学发现的引擎本身就会停止运转。
如果巨人没精打采,你不可能很好地站在他们的肩膀上。
发生这种情况有很多原因,包括软弱无力的研究标准,“发表或灭亡”的激励,以及在极限情况下,彻头彻尾的欺诈活动。即使好的科学是怀着最美好的愿望进行的,它也不总是一帆风顺的。在人工智能研究中,这通常以算法论文的形式出现,这些论文带有未记录的代码(如果发表的话),其性能会随着敏感的训练条件而波动。
这对你来说意味着什么,勇敢的旅行者,如果你的结果看起来不完全像你选择的论文,你一定不要气馁。我很快发现 作者经常会省略细节,因为它们不重要(它们很重要)或者因为它们非常明显(它们不重要)。

Authors can leave out seemingly unimportant, but crucial, details. Source: www.pexels.com
为了克服这一点,你不能仅仅将你的研究论文局限于原文。你必须汇集外部资源(GitHub、StackOverflow、你的邻居),并对影响每篇论文但并不总是显而易见的关键概念培养良好的直觉。这将帮助你智能地填补空白,以最终进行复制,并有望甚至超越深度学习算法的性能。
以下是作者没有回答的最常见的问题,但你仍然必须努力解决:
权重是如何初始化的?
在任何给定的层中,你都不希望你的权重相同、太大或太小。如果所有的权重彼此相同,你的更新(学习率乘以每个权重的导数)将具有相同的方向和幅度。
不太好。
不同的“神经元”需要有不同的变化,以便你的网络学习输入和输出之间的复杂关系——这被称为打破对称,也是单层神经网络有可能逼近任何连续函数的原因。本质上,这就是为什么深度学习这么有用。
您的权重值太大或太小将导致爆炸/消失梯度,最终使训练过程不稳定、缓慢或完全无效。如果你在高速公路上开车,坡度大的话,你会以每小时 120 英里的速度飞驰,坡度小的话,你会以每小时 5 英里的速度缓慢前行。
你要么错过退路,要么无聊而死...在这两种情况下,你都会被开罚单。
因此,为了得到完美的权重,我们必须确保它们是从一个合适的概率分布中抽取的。因为这种特别的洞察力是如此重要,许多真正聪明的人已经就这个主题写了完整的论文。因此, 当前的最佳实践是分别对 ReLUs(校正线性单位)或 tanh/sigmoid 激活函数使用 He 或 Xavier 初始化。
不幸的是,这些初始化方案本质上是随机的,因为权重是从分布中随机选择的。这意味着,即使神经网络可以用固定的初始权重和输入来确定,论文的复制也变得不确定。你的体重,以及随后你的结果,会略有不同,现在,我们将不得不接受这一点。

Initializations can be robust, but ultimately stochastic. Source: www.pexels.com
然而,使用上面的直觉,如果你的结果与论文的结果完全不同,你至少知道不要责怪权重。如果作者没有提到任何初始化过程,你也不会束手无策。
使用了哪些超参数?
有相当多的超参数在将深度学习算法带入生活中发挥着不可或缺的作用,其中大多数你会毫不费力地发现。
在大多数研究论文中,对隐藏层的大小和数量、正则化系数和其他建筑地标的描述与令人信服的理论基础讨论无缝地交织在一起。
这些 设计 超参数为您提供了成功实施的蓝图,但不会带您走得更远。为了配合论文的表现,你必须寻找不同种类的 训练 超参数。
这是你开始出汗的地方。
学习率在哪里?批量大小,时代?超越传统的超参数,使用了什么优化器?数据集中的训练和测试拆分是什么?
对于那些满足于仅仅跟上人工智能世界的最新进展的人来说,这些细节是无关紧要的。“我就看看报纸,然后继续前进!”他们会说,“更好的是,有没有我可以看一下的摘要?”
但对于那些头发花白、想要追逐疯狂、让现实屈从于我们意志的少数人来说,这些特征至关重要。你的目标不仅仅是简单地理解这些论文,而是将它们重新组合在一起,甚至是在它们成功的基础上再接再厉。
一种方法是在互联网上搜寻这些训练超参数。您可以在 GitHub 上找到相关的实现,并提取相关的值。不幸的是,涉水通过互联网代码可以非常令人沮丧和误导。
更好的策略是从基本原则开始,确定最佳实践,并磨练您对这些反复出现的主题的直觉:
批量:32 左右从开始。使用较少的训练样本来更新权重会产生一个“嘈杂的”梯度信号。与直觉相反,这种噪音对你的网络产生了一种规则效应,允许它很好地推广到看不见的测试数据。

Source: www.twitter.com
历元数:这个很简单。从足够多的历元开始(完全遍历您的数据),当验证错误开始变得更糟时停止训练。假设你一直在定期保存你的体重,选择那些给你最低验证损失的——这就是所谓的提前停止。
训练/验证/测试集:一个好的经验法则是将你的数据集分成 80/10/10。然而,你拥有的数据点越少,你投入训练的数据点就越多,所以这个比例是可变的。对数据如何在这些不同的集合中分布持怀疑态度并不是一个坏主意,但是如果你的论文使用了一个众所周知的基准,那么细节很可能已经提前为你处理好了。
优化器:与 AdamW ,Adam的更好变体。基本原理是选择一个优化器,该优化器使用梯度信号的一部分,根据它们的“需要”更新各个参数。想想社会主义。AdamW 将这种自适应更新与动量相结合,动量是先前梯度的移动平均。这可以智能地改变参数,同时防止当前批次的损耗大幅波动。
学习率:这是一个系数,优化器将其与梯度相乘以抑制误差信号(在 AdamW 的情况下是自适应的)。首先,使用任何学习率(lr)探测器获得最大和最小值。然后使用周期策略来调整你的学习速度和动力。这里的直觉是,在慢慢收敛到最佳参数之前,网络将在开始时快速探索解决方案。
再现性对科学进步非常重要,所以当人工智能研究人员让其他人更难跟随他们的脚步时,这是一种耻辱。掌握以上这些概念会给你前进的信心,即使你论文的作者没有明确说明训练程序。
更重要的是,你会注意到观点的转变,不再只是阅读一篇论文并思考,“这很有道理”,而是“我同意这个观点”或“我会用不同的方式来做这件事”。完成一篇研究论文将从一项纯粹的教育活动演变成同行评议。

Welcome to the scientific enterprise! Source: www.pexels.com
期望#3:个人舒适
虽然这无疑将是一次有趣的经历,但是您可以做一些事情来确保您的第一次实现之旅进展顺利。
- 选择培训时间在 5 小时以下的纸张。这可能有助于减少您在第一次实施上花费的资金(取决于您运行的 GPU 实例)。更重要的是,后续训练之间更快的反馈循环可以让你快速实验,并且不会在出现问题时摧毁你的自尊。
- 从小处着手,逐步积累,直至全面实施。绝对不要试图构建论文的完整架构,却发现自己犯了一些小错误,导致你的网络无法访问。解决这个问题的方法是一点一点地构建,通过网络运行一批数据,并说服自己事情是有意义的。在继续前进之前,解决你为自己构建的更简单的问题。
- 等到原来的结果接近可复制的时候再做实验。我一让事情运转起来,就开始运行迷你实验来戳戳我的网络,最终观察它的行为。这不一定是一件坏事,因为它可能会帮助您发展直觉,但是这些直觉与您的实现应该如何工作没有关系。所以先复制,后实验。
- 确保选择一个你知道一些或愿意探索的、启发智力的话题。我选择复制 NLP 上的一篇论文的结果,我觉得这很有趣,也与我的工作相关。这让我即使在材料具有挑战性的时候也能保持专注,我甚至能够将我学到的知识应用到工作中的算法中。
结束语
你是应该先一头扎进去,边走边学,还是应该在 试图完成一篇研究论文之前 尽你所能地学习?答案真的取决于你为什么要这么做,你希望从这次经历中得到什么。
不管你的策略是什么,重要的是要认识到,你的问题的答案并不总是在论文本身,当作者不明确时,概念性的理解可以帮助填补空白。或许,在你上船之前,一条让你具备基本知识的中间道路,会给你毫发无损地浮出水面的最佳机会。
到目前为止,我已经避免引用我的实际实现,因为这个讨论主要是关于动机和期望。然而,如果你感兴趣,我实现了 IBM 的双边多视角匹配模型,这是我第一次尝试复制深度学习算法。你可以在 GitHub 上找到我的实验、代码和测试。所有的东西都有详细的文档记录,而且我让事情变得非常容易理解。挖的开心!
关于复制深度学习论文的性能,当然还有更多可以说的(工具、调试策略、测量实验等)。),也许我会在以后的文章中深入探讨其中的一些。但是现在,希望你发现这篇文章对计划你的冒险有指导意义,并且理解在你的旅途中等待你的一些惊喜(愉快的或其他的)。
所以,勇敢的旅行者,保持安全但好奇,轻装上阵,记得把一切都带进去!一路顺风!

Bon Voyage! Source: www.pexels.com
将预训练嵌入空间投影到 KDE 混合空间的小数据集假设检验
一种主要用于通过面向领域的信息转换来帮助快速原型化、引导主题建模、假设检验、概念验证的方法。

文本分类任务通常需要高样本数和精细的语义可变性来进行可靠的建模。在许多情况下,手头的数据在样本计数、类别的过度偏斜和低可变性(即词汇多样性和语义)方面都是不够的。在这篇文章中,我将介绍一种新颖的方法来克服这些常见的障碍。这种方法的目的主要是帮助快速原型制作、引导主题建模、假设检验、概念验证(POC),甚至是创建最小可行产品(MVP)。
该方法由以下步骤组成:
- 加载我们的小数据集或主题词汇表(用于主题建模用例)
- 选择最合适的预训练嵌入
- 创建集群
- 最后,使用核密度估计(KDE)创建新的嵌入
第一步:加载我们的数据
我们从一个非常小的数据集开始。我们用的是施莱歇尔的寓言,其中的每一句话都是一个文档样本。
第二步:选择最佳嵌入空间
单词在本质上看起来是绝对的,但通过 Word2Vec & GloVe 等嵌入方法,它们现在可以被视为有限语义、密集表示的空间中的点。这种伪欧几里得空间表示可以极大地帮助简化语义任务。由于许多领域的数据短缺,通常的做法是从预先训练好的易于使用的嵌入模型开始。
作为一般规则,我们的域应该被完全表示。因此,所选择的嵌入应该包含尽可能多的单词,这些单词将是我们的数据的(主题建模)词汇。为了防止词汇之外(OOV)的单词,所选择的模型应该包含非常大量的记号。我通常选择最低的适应维度空间,因为更高的维度空间可以在来自嵌入空间的单词和我们的领域之间有更大的距离。换句话说,这可能导致聚类边界从我们的域向由预先训练的嵌入所表示的原始域倾斜。最后,我试图选择一个尽可能接近我的用例的嵌入空间,如图 1 所示。

Figure.1 — A t-SNE projection of our dataset overlaid on top of the chosen embedding space, sampled for visibility.
我用 Gensim 来训练一个 Word2Vec 模型。我通常在任何数据集上训练一个模型。然而,如下所示,最好是在一个大的外部数据集上训练,最好是与您自己的数据集混合。在这个实现中,空间维度是手动设置的,这给了我们关于聚类边界的优势。
一旦选择了嵌入空间,我们就根据我们的词汇表解析这个空间。以下假设有助于我们完成这项任务:
- 该空间是伪语义的,即,它是自动选择的,并且不受嵌入空间的真实上下文语义( Ker{} )的指导。它确保源数据在语义上尽可能均匀地分布单词距离,这有助于很好地定义聚类边界。
- 源数据应具有足够低的属性域偏差,以允许多个属性域基于所确定的距离。如前所述,这种假设似乎是一厢情愿的想法。
- 单词之间的差异由单个半径定义,即,在空间中没有方向依赖性。
下面的代码从预先训练的嵌入空间列表中选择最佳的编码空间,该列表由斯坦福大学提供,可从这里获得。请注意,以下过程使用标准的文本预处理方法,如文本清理、标点符号和停用词删除,然后是词干处理&词汇化。如下面的代码所示,可以使用 Gensim 包在您选择的任何数据集上创建其他嵌入文件,例如:
第三步:聚类
根据前面的假设,在步骤 2 中,我们如何选择正确的聚类算法、聚类的数量以及每个质心在空间中的位置?这些问题的答案在很大程度上依赖于领域。然而,如果您不确定如何添加您的领域的指导性约束或增强,我建议一种通用的、剥离的方法。一般来说,聚类的数量应该通过观察数据集来设置,因为任何转换的语义可分性应该与域本身中的未来任务相关。最小聚类数应该由您在未来任务中预见的最低类数来确定。例如,如果在不久的将来,您看到您的数据或域中的文本分类任务不超过 10 个类,那么最小分类计数应该设置为 10。然而,如果这个数字高于嵌入空间的维数,那么下限应该更大,并且在这一点上是未定义的。在任何情况下,它都不应该超过数据集的词汇或主题数,记住在这个用例中它是非常低的。
像聚类边界不确定性、每个聚类的 P 值分析、自适应阈值和有条件的聚类合并和分割等问题超出了本文的范围。
我们假设嵌入空间中的相邻单词在语义上足够接近,可以加入到某个语义簇中。为了定义聚类,我们需要确定一个距离度量。对于这个任务,让我们看看占据嵌入空间的令牌,并找出最接近的两个。设这两者之间的余弦距离为 Ro,则定义簇字邻接的最小距离为 R = Ro / 2 - ε,此时簇计数最大。换句话说,进行简单的实例到实例距离聚类来对单词进行分组。在主题建模的情况下,Ro 将是来自不同主题的最近单词之间的最小距离。
下面的代码使用选择的手套嵌入空间,使用 K=2 的最近邻对其进行聚类,并使用余弦相似度来确定最小距离。
前一种方法确保聚类将包含来自数据集的至少一个单词,同时记住在嵌入空间中总是存在未分配的单词。
将未分配的点(词)聚集成生成的簇的直接方法是标签传播/标签传播,如图 2 & 3 所示。
然而,由于较高的运行时间复杂性(代码#5),您可能希望使用更快且不太精确的方法,如线性 SVM(代码#6)。由于运行时复杂性问题,下面的代码比较了这两种方法。这一步是一个“蛮力”聚集,在未来的探索中,当我们的数据集预计会更丰富时,可能会产生不太理想的结果。

Figure.2 — A t-SNE projection after label-spreading of our dataset and a selection of samples from our chosen embedding space. please note that this is purely for illustrative purposes, as the real 2D display of the labeling would be similar to Figure 3.

Figure 3: A t-SNE projection after label-spreading, using a sample of tokens from our embedding space, colors represent the different labels. Please note that this is in a higher space compared to Figure 2 without dimensionality reduction.
让我们来关注一下为什么核心聚集之后是样本聚集是有意义的。嗯,我们希望将嵌入限制在我们的数据锚/主题(单词)上。这需要语义上的接近。一旦实现了这一点,假设最外围的单词在未来的样本中不太可能出现。让我再强调一次——当我们从获得非常少的数据开始,并且想要制作一个概念验证或基本产品(MVP)时,就会出现这种用例。
步骤 4:使用 KDE 创建新的嵌入空间
现在,所有的单词都被分配到一个聚类中,我们需要一个更有信息的表示,这将有助于未来的未知样本。由于嵌入空间是由语义接近度定义的,我们可以通过空间中该位置处每个聚类的概率密度函数(PDF)的密度来编码每个样本。
换句话说,在一个簇中位于密集区域而在另一个簇中密度较低的单词,将使用通过使用新的密度嵌入所投射的信息来展示这种行为。请记住,嵌入维数实际上是聚类计数,并且嵌入的顺序是相对于初始化该嵌入时提出的聚类来保持的。使用我们的小数据集,得到的投影可以在图 4 中看到。最后,下面的代码使用 KDE 创建一个新的嵌入。

Figure.4 — A t-SNE projection of the final density encoding map, which is a mixture model. label colors may have changed but they correspond to the label clusters as seen in Figure 2.
感谢 Ori Cohen 和Adam Bali的宝贵批判、校对、编辑和评论。
Natanel Davidovits
奇异问题解决者。数学建模、优化、计算机视觉、NLP/NLU &数据科学方面的专家,拥有十年的行业研究经验。
经济高效的机器学习项目提示
剧透:你不需要一个 24/7 运行的虚拟机一天处理 16 个请求。

Street art by Mike Mozart
你刚刚发布了一个机器学习项目。它可以是你刚起步的新产品,可以是客户演示的概念验证,也可以是丰富你的投资组合的个人项目。你不是在寻找一个生产级网站;你想完成工作。为了便宜。这样一些用户就可以测试你的产品。
如何经济高效地提供您的项目?
这篇文章是对这篇前一篇文章的后续和更新,在那篇文章中,我介绍了 raplyrics.eu ,这是一个使用 ML 生成说唱音乐歌词的文本生成网络应用。
到目前为止,这个项目已经提供了一年的笑点。我在此分享更新的架构,它使我们将云提供商的账单从每月 50 美元减少到每月不到 1 美元。
我使用这个项目作为例子,但是这里讨论的建议适用于每个具有灵活延迟需求的类似项目。
期待什么?
首先,我描述了服务的架构以及我们想要交付的内容。然后,我定义实现我们目标的可能方法。最后,我重点介绍了我们如何使用无服务器功能大幅降低计算成本。
服务剖析

First the user fetches the static assets, then locally executes the JS that calls the prediction server to generate lyrics.
- 首先,用户获取静态文件。
- 然后,用户在本地调用预测服务器。
- 最后,服务器返回预测。
在最初的解决方案和下面介绍的新解决方案之间,关注点的逻辑分离保持不变。我们只更新底层技术。
初始解决方案设计

What paying 600$ a year for a porftolio project feels like — Photo by Jp Valery on Unsplash
当我们开发 raplyrics 时,我们希望它非常简单。它最初是一个在我们的机器上构建和测试的项目。然后,我们把它推到了云端。
目前,有几种服务于机器学习模型的方法。以前,我们想弄脏自己的手,所以我们实施了我们的服务策略。
建议:不要开发你自己的机器学习模型服务框架——成熟的解决方案,如 tensorflow serving 已经存在。TF Serving 有详尽的文档,会比自己动手更有效率。
话虽如此,让我们回到我们的项目。我们把前面和后面分开;
- 客户端层是一个 Apache Http 服务器
- 服务器层是运行歌词生成模型的 Python flask 应用程序。
我们购买了一个领域模型,将我们的代码部署到一个 EC2 上,并且准备好为用户服务。
问题是
在免费试用期到期之前,一切都是乐趣和游戏。在最初的 12 个月之后,在 2019 年 9 月为 32 个用户服务时,这个单个项目的每月账单飙升至 ~每月 45/50 美元。
事实是,我们有一个 2GB Ram 的虚拟机,全天候运行,为几十个用户提供服务。
更新的解决方案设计
在免费试用之后,很明显我们处理这个项目的方式中有些地方出了问题。
我们服务的典型用户知道这个网站是一个个人项目;它设定了期望的水平。
典型的用户生成一打歌词,然后离开。
我们知道我们想要实现什么,服务一个两层架构,前端处理调用服务生成歌词的用户输入。前后松耦合。(仅指前端的后端端点)。
有哪些可能性,可能的如何?
列出选项
- A —将同一个项目部署到另一个提供免费积分的云提供商。重复一遍。
那是可能的。例如,如果你来自 AWS,GCP 的 300 美元信用可以让你运行一段时间。也许你只需要在有限的时间内为客户提供这个投资组合项目或概念证明。
我们想把我们的项目保留一段时间;选项 A 不太适合。
- B —为客户端层使用静态网站,通过对无服务器计算的 API 调用来服务请求。
什么是无服务器计算?
无服务器计算是一种按需提供后端服务的方法。服务器仍在使用,但从无服务器供应商那里获得后端服务的公司是根据使用情况收费的,而不是固定的带宽量或服务器数量。—来自 CloudFare
我们选择了选项 B,使用静态网站并在无服务器计算服务上公开我们的 API。选项 B 的缺点是增加了冷启动时的延迟。冷启动是无服务器计算服务的第一次运行;它通常需要比 W 臂启动更长的时间。
静态网站和运行中无服务器计算机
既然我们已经定义了我们想要如何去做,我们可以专注于技术的选择。
托管静态页面
存在多种静态托管解决方案。我们选择了 Netlify。很容易在最少的时间内完成这项工作。在 Netlify 上,使用自定义域名的基本主机和 SSL 证书是免费的。
用无服务器计算服务 API
每个云提供商都提供无服务器计算服务;我们选择了谷歌云及其云功能。
Google cloud 有一个教程是关于如何通过云功能来服务机器学习模型的。以本教程为基础,我们可以通过一点点重构来服务我们的模型。
每个云提供商倾向于以略微不同的方式处理他们如何提供云功能。谷歌云还提供基于 Dockerfile 的无服务器计算服务 Cloud Run。使用 Dockerfiles 可以更容易地将项目从一个云提供商转移到另一个云提供商。
冷启动延迟
对于冷启动,我们必须从桶中装载模型重量(150Mb)。然后,python 应用程序加载权重。在这些情况下,响应时间最长可达 40 秒。对于热启动,响应时间通常低于 2 秒。对于投资组合项目,我们可以接受这种成本/延迟权衡。
我们在前端添加了一些用户界面元素,使第一次预测更加清晰,这可能需要一些时间。
外卖食品
你不需要一个完整的生产规模来为你的小项目服务。以最具成本效益的解决方案为目标。
- 投资组合项目的延迟需求与生产服务的延迟需求不同。
- 静态网站和使用基于无服务器计算的 API 是服务于你的项目的一个划算的解决方案。
需要一些技巧来处理状态,有效地从网络加载资源,但是这样做的经济性值得一试。
感谢 Cyril 对这篇文章的深思熟虑的反馈。
资源
Raplyrics 源代码可在 GithHub 上获得。
托管静态网站
- 在亚马逊 S3 上托管一个静态网站, aws doc
- 您和您的项目的网站, GitHub 页面
- 托管一个静态网站, gcloud doc
- 在几秒钟内部署您的站点, netlify
无服务器计算服务
- AWS——运行代码时不考虑 AWS 上的服务器,
- Google Cloud——事件驱动的无服务器计算平台, gcloud functions
- Azure——事件驱动的无服务器计算, Azure functions
- 阿里巴巴——全托管无服务器运行环境,函数计算
有效数据可视化的技巧

Photo by Carlos Muza on Unsplash
数据可视化具有很强的设计元素。考虑到领域、应用程序和受众的差异,很难围绕可视化数据的最佳方式建立一个结构。然而,肯定有错误的方法!我遇到过许多这样的例子,它们是这篇文章背后的驱动力。
在这篇文章中,我想分享一些有用的技巧来帮助你避免视觉上的失误。
1.选择正确的视觉效果
这个可能看起来太明显了!但是我看到一些人试图毫无理由地展示他们艺术的一面..
永远记住形式跟随功能——一个视觉的目的应该是其设计的出发点**
问问你自己——你是在尝试比较价值、展示趋势、探索变量之间的分布或关系吗?然后根据你要传达的信息选择合适的视觉效果。考虑以下图表。基础数据集包含产品投诉/缺陷。我们试图用缺陷率 ppm(百万分率)来显示需要注意的产品。条形图是显示这些数据的简单而有效的方法。树状图和气泡图的一个缺点是要求读者比较面积而不是高度,这在视觉上很费力。

Choosing the right visual based on it’s function
2.琐碎的很多,但重要的很少(数据点)
不要只是在数据集上拍一张照片。分析您的数据,并将其转化为受众可以理解的信息“金块”。

旁边的图显示了过程变量的时间序列图。线 A-A '显示了周期和振幅都改变的时间点,这是问题的开始,最终导致其值在几个周期后突然下降。哪个图表能更好地揭示这种洞察力?
顶部的图表只是将数据转化为视觉效果,而底部的图表“调节”数据以提供洞察力。
假设我们想按项目 ID 显示年度总支出。有 41 个独特的类别。左边的图表看起来很拥挤,所有的类别都挤在里面。更好的显示方式是显示前 5 个类别,并将其余类别合并到“其他”类别中。

Suppressing the “noise” in the data
此外,请注意,过滤掉“其他”类别可能会夸大饼图的面积,或者改变总计算的百分比。这可能会产生误导!在显示百分比时,一定要确保它们加起来是 100%,或者解释为什么以及排除了什么。
3.数字不会说谎,但俗人会说谎!
视觉效果应该反映现实,而不是扭曲现实。图表的格式非常重要,因为它为观众建立了一个参考框架。
在下面的例子中,在 6 个月的时间里,一个过程的产量从 56%增加到 67%。左侧的图表试图夸大改进,将 y 轴格式化为从 50%开始。后一种视觉描绘了一幅精确的画面,其中 y 轴从 0 开始,并且还包括一条球门线。

Figures don’t lie..liars figure!
4.明智地使用颜色
应该使用颜色来添加更多信息或突出视觉效果中的关键数据点。在所有其他情况下,这是多余的和分散注意力的。
这篇由丽莎·夏洛特·罗斯特撰写的文章给出了一些选择视觉效果配色方案时需要考虑的要点。我还推荐试试由苏西·卢和以利亚·米克斯开发的工具。

5.与功能相比,美观有多重要?
如今可用的可视化工具让我们只需点击几下鼠标就能创造出最令人惊叹的丰富视觉效果。然而,过度渲染美学元素可能会分散人们对视觉效果关键信息的注意力。精益理念中的七种浪费之一是“过度加工”。

还有其他可以防止可视化失误的技巧吗?欢迎在下面评论!
信息图能讲述数据故事吗?

Author
创建第一个信息图的想法和技巧
让每个人都专注于你的数据分析是一项挑战。您面临着各种各样的挑战:糟糕的数据素养、不感兴趣,甚至注意力持续时间的缩短。
您是否考虑过在数据通信中添加信息图表?
这种技术以一种视觉上令人兴奋的方式讲述了一个数据故事,让用户按照自己的节奏消化数据。让我们回顾一些信息图示例来寻找灵感,然后是一些入门提示。
什么是信息图?
信息图(或信息图)用图像、数据可视化和文本讲述一个故事。这种技术有很多优点,但我喜欢它,因为它很容易抓住注意力持续下降的观众。信息图表可以让你将大量的数据浓缩成易于理解的片段。你可以把它看作是仪表盘和数据故事的结合。这些作品讲述了一个关于所选主题的快速而清晰的故事。
在广告中使用信息图表,或在社交媒体上分享,以吸引人们对你的分析的注意。一个设计良好的信息图的视觉本质能够抓住浏览者的注意力。我认为这种方法比其他数据表示方法更随意。这是一种有趣的方式来打开一个话题进行更多的探索。
但是,您也可以在内部使用这种技术!也许你有一个重点领域,你想突出。客户服务部门可能会显示客户在过去 30 天内致电的前 5 个原因,并突出显示有关这些电话的一些关键事实。
精明的数据分析师可以与工程或产品管理团队分享该信息图,以帮助他们了解他们如何影响客户。
了解信息图表类型
Travis Murphy 在他的书《SAS 支持的信息图表:商业报告的数据可视化技术 中描述了两种信息图表:艺术和商业。
艺术信息图 特色图片和极简文字。你经常会在厨房的墙上或青少年卧室的天花板上发现这些信息图表。想想展示各种可食用花卉或福特野马多年来如何变化的海报。艺术信息图是高度视觉化的。
你用你的眼睛去学习和比较什么是相似的,什么是不同的。
下面这张由 Cathryn Lavery 设计的信息图展示了蝙蝠侠标志这些年来是如何变化的。令人好奇的是,这个标志是如何变化的,却又保持不变。

快速消息的信息图表

SAS 用这张信息图解释了 SAS Viya 的主要特点。他们在社交媒体上使用了这张信息图,并在 SAS 全球论坛上发布。虽然它有一个商业主题,但它的内容并不侧重于分享统计数据,而是允许观众探索 SAS Viya 产品的功能和用途。
信息图中的信息很简单,该产品有四个主要特点。该产品非常适合多种分析角色。他们传达的信息是这款产品非常灵活,适用于多种角色。
它使用公司主题的颜色来传达信息,并引导你的视线向下。
商业信息图比艺术信息图更加结构化。这些更像 web 报告,因为它们包含统计数据和数据可视化。这些信息图表用数据讲述了一个故事。
信息图讲述数据故事

下图显示了一个业务信息图。你可以看到图片和图形比文字更流行。
生命统计数据被用来用一条短消息来启发观众。
考虑一下 SAS 的这张信息图,它可以帮助您了解数据技能差距。它讲述了一个关于问题的故事,以及他们需要什么来解决问题。
他们会带您浏览每个元素,并提供支持信息和有趣的数据可视化以供探索。
信息图表带领观众踏上探索之旅

罗伯特·艾利森的下面这张信息图从定量的角度帮助你理解《星际迷航》。
这里的艺术品是色块。请注意,该信息图引用了原始电视连续剧的颜色和字体。
这些字体与片头序列中使用的字体相同。颜色和原来 60 年代的船员穿的一样。颜色传达了如此强烈的信息!
所有有用的信息图表都需要一个外卖,例如作为一名红衫军成员是危险的,柯克船长不仅仅是一个人类女士的男人。这些数据引起了激烈的争论——成为一名黄衫军是危险的。]但是饼状图在这里看起来很好吃!
在下面的信息图中, Falko Schulz 用 SAS 视觉分析软件讲述了珠穆朗玛峰的故事。他使用各种图片、数据对象和文本字段来引导您浏览数据。你的眼睛滑过数据,发现了一些小细节。
这张信息图是让人们回答下一个问题的绝佳方式:“如果这项活动如此危险,人们为什么要这么做?”你注意到底部的折线图了吗?这是一个非常棒的信息图表!

想象一下,如果我试图用幻灯片给你同样的信息!虽然这个话题很有趣(尽管有点病态),但是想想看,如果你看完了 25 张幻灯片,看完了我对喜马拉雅探险队数据库的分析,或者翻阅了 PDF 文件,你会怎么想?
通过使用信息图,您的受众可以探索信息的详细程度。也许知道下山比登顶更危险就足够了。
也许当你得知雪崩比坠落更致命时会感到惊讶。
当你查看上山路线时,你可以清楚地看到登山者的路径覆盖了一个雪崩的完美地点。然而,Falko 让你发现了那种洞察力。
信息图表娱乐并吸引观众
在创建我的信息图时,我想突出一个让我好奇的主题——鲨鱼。虽然我同意这是一个性感的话题,但这张信息图可以让你说服自己,鲨鱼事件是否如此普遍或致命。
我在 SAS 可视化分析 8.3 中创建了这个信息图。我们想用一个数据故事来庆祝鲨鱼周。这张地图看起来很漂亮。

创建有效信息图的技巧
与其他数据交流方式相比,信息图表更能挑战你的编辑、设计和布局技能。对于那些可能更擅长机器学习的人来说,这是一种全新的设计体验。
为了取得成功,请牢记这些最佳实践:
- 确定主要信息和支持该信息的数据事实。由于篇幅有限,每个页面元素都很重要。此外,用户还可以从图形在页面上的显示方式中得出结论。
- 视觉元素越大,用户认为信息越重要。
- 在纸上创建页面元素的布局。你可以用纸和笔记下你的想法,并预先组织好你的事实。
- 考虑每个元素给故事增加了什么,以及它如何引导用户浏览故事。
- 你的图形或网页设计技能在这个练习中很有用。如果你没有接受过培训,可以考虑阅读设计原则。互联网上有许多免费的课程,如 Udemy 、 Skillshare 以及其他类似的网站。
- 如果你在 SAS Visual Analytics 中创建信息图,使用 Travis Murphy 的这些有用的提示。如果你用的是基地 SAS,那么用 Robert Allison 的流程。
如果你第一次尝试制作信息图感觉有点僵硬,你一定不要气馁;你的技能会随着练习而提高。
当您希望快速传达信息并吸引观众时,请将信息图表添加到您的数据通信组合中。信息图表允许你的用户以一种有趣而悠闲的方式探索数据。这种技术让用户问下一个问题,同时仍然有一些重要的收获。
最初在 https://www.zencos.com 出版。
IPython Alias 预加载您喜爱的模块并激活自动加载
用一种非常简单的方法获得您自己的强大的 IPython
TL;速度三角形定位法(dead reckoning)
您只需复制下面的别名,并将其粘贴到您的.bashrc、.zshrc或某个配置文件中:
alias ipy="ipython --no-confirm-exit --no-banner --quick --InteractiveShellApp.extensions=\"['autoreload']\" --InteractiveShellApp.exec_lines=\"['%autoreload 2', 'import os,sys']\""

Photo by Geetanjal Khanna on Unsplash
我经常使用 IPython 来开发我的库或做一些研究,因为 IPython 有如下非常好的特性:
- 运行常见的 shell 命令:ls、cp、rm 等。
- 此外,运行任何 shell 命令!(一些命令)。
- IPython 提供了许多神奇的命令 : run、debug、timeit 等
- 伟大的自动完成
- 在 Python 中预装你喜欢的模块
- 自动重装扩展
我想你已经知道 IPython 提供了一个很好的 Python 解释器,但是也知道你需要准备profile来定制 IPython,比如预加载或者激活一个扩展。我觉得这有点麻烦。所以我在这篇文章中解释了预加载你喜欢的模块或者激活autoreload而不需要配置文件的方法。
在 Python 中预装你喜欢的模块
当 IPython 启动时,您可以像下面这样执行 Python 代码。在这种情况下,我预加载 os 和 sys 模块。
ipython --InteractiveShellApp.exec_lines="['import os,sys']"
如果你想预装 PyTorch 或 Tensorflow,这里是你想要的:
ipython --InteractiveShellApp.exec_lines="['import torch', 'import tensorflow as tf']"
激活自动重新装入扩展
autoreload在执行代码之前自动重新加载模块。您可以按如下方式激活autoreload:
ipython --InteractiveShellApp.extensions="['autoreload']" --InteractiveShellApp.exec_lines="['%autoreload 2']"
通过使用--InteractiveShellApp.extensoins,可以加载 IPython 扩展。要启用autoreload,需要执行%autoreload 2。
其他提示

您可以删除横幅:
ipython --no-banner

此外,您还可以删除确认:
ipython --no-confirm-exit
获取您自己的强大 IPython
我建议您将所有内容组合起来,并使其成为别名:
alias ipy="ipython --no-confirm-exit --no-banner --quick --InteractiveShellApp.extensions=\"['autoreload']\" --InteractiveShellApp.exec_lines=\"['%autoreload 2', 'import os,sys']\""
注意--quick是一个无需配置文件的快速启动选项。现在,您可以轻松地以自己喜欢的方式更改这个别名。您可能想要加载额外的模块,如PyTorch、TensorFlow、Keras、scikit-learn等等。
我的帖子到此为止。在这篇文章中,我解释了用一种非常简单的方法定制你的 IPython 并使它强大的方法。这篇文章是写给那些不喜欢建立自己的配置文件,并且想要一个更简单的方法来做这件事的人的。希望我的帖子能帮到你。如果你想更多地定制 IPython 或使用 Jupyter,请查看这篇精彩的帖子:如何将你最喜欢的库自动导入 IPython 或 Jupyter 笔记本。感谢您的阅读。
关于与企业一起定义数据科学项目范围的 3 个提示
如何以数据科学家的身份与企业交流
永远不要因为在错误的时间把错误的东西送给错误的人而陷入麻烦

作为一名数据科学家,你希望得到一份能让你做酷事情的工作——大数据、大机器(或者像成年人一样的云)和深度神经网络。当你意识到你的模型、你的项目经理的时间表和你的利益相关者的期望之间的不匹配时,现实很快就来了。他们(通常)需要的不是一个 128 层的 ResNet,而是一个简单的 select & group by 查询,提供可操作的洞察力。
你的新工作已经进行了两个月,你的闪亮模型刚刚被束之高阁,嘟囔着:“什么是可操作的见解。谁的洞察力?用什么行动?”

本文概述了在(不)定义数据科学项目范围中的常见陷阱,以及如何分散或防止这些情况发生的技巧和框架。
陷阱 1:范围太广或未定义
使用数据主导、数据驱动和数据优先的方法的人数激增,分析领域的每个人都遇到过这一(或)著名的业务需求:
“告诉我数据怎么说。”
不要误会我;我非常支持根据历史模式和精心设计的预测做出决策。然而,作为数据从业者,我们也知道有各种各样的数据类型:通常管理不善的内部数据,每个人都认为是分析圣杯的外部数据和什么都不说的内向数据。
操纵数据的表示来传达您想要发送的信息甚至容易得令人不安。例如,通过稍微挤压图表,你的收入增长突然看起来像5 倍,而不是 0.5 倍。更糟糕的是,通过不提出正确的问题和开发强有力的假设测试,数据甚至可以用来增强你现有的信念。

范围宽泛且不明确的危险就在于此。这对于你先前的信念来说是非常主观的,大多数时候,企业和科学家在理解和解释不同的事情。
陷阱 2:范围过窄或定义过窄
与过于宽泛的范围相反,你可能还会遇到一些非常热情的利益相关者,他们在哈佛商业评论上阅读了一些关于客户流失建模或客户细分的文章,并要求你构建一些非常具体的东西。

当这种情况发生时,我们的第一反应往往是进入求解模式,开始幻想两周前你读过的那篇论文中的卷积 LSTM。然后我们开始卷起袖子,掰着手指头想…
嘿,我知道怎么做。
在经历了血、汗和泪之后,你终于有东西可以展示了。在演示会上,利益相关者看着你,你回头看着他,期望得到奖金或至少拍拍他的背,但他困惑地问道:
好吧,那很酷,但是仪表板在哪里?
等等什么?原来他从来没有想要一个客户流失模型。

他想要的只是一个仪表板,上面有合同将在未来三个月内到期的客户。其目的不是预测谁会续签合同,而是让一线呼叫中心跟踪他们与这些客户的接触情况。
你站起来,收拾好你构造精美、优化高效的模型,然后走出来。
现在深呼吸(不要打你的电脑)
让我们在这里暂停一下,回想一下这是什么时候发生在你身上的。看看下面两个与范围过宽或过窄相关的选项。如果你能回到过去选一个,你会怎么做?

这里(或者永远)没有正确或错误的答案,这些都是优秀的敏捷方法,可以在需求不明确的时候使用。
但是,我希望你做的不是专注于如何缩小或重新定义范围,而是提出更多的问题。无论是太宽泛还是太狭窄的场景都假设问题是正确的,并且是我们不舒服的解决方案,但是如果问题甚至不是真实的呢?如果没有问足够多的问题,你可能会无意中掩盖症状,掩盖根本原因。
因此,如果你从这篇文章中拿走一样东西,我希望你再次记住这一点:企业不知道他们想要什么。
你的工作是帮助企业找到他们想要的东西。
技巧 1:找出企业真正想要的是什么
事实是,我们的大多数业务利益相关者不了解数据科学项目的可能性。在构建他们的问题时,通常有很多假设但没有明确地说出来,所以从表面上接受他们的请求会导致无数次的范围变化。
作为你所在领域的专家,你的工作是引导企业通过术语的丛林,将他们的征服世界的神奇按钮业务问题转化为可以解决的问题,数学上,以及他们的数据。
想象一下,在对想要的可操作的见解进行一些探究之后,你发现他们所关注的是【缓慢增长】。咻,至少它限制了对与成长相关的神奇事物的探索。然后,您可以提供一些与增长相关的出色见解,如收购成本和流失率。

不幸的是,读懂另一个人的想法并不容易,但幸运的是,你可以使用一些试探性的问题:
1.是什么让你夜不能寐?
2。你想证明或反驳什么?
3。你的直觉告诉你什么?
4。如果你有预算做好一件事,那会是什么?
技巧 2:不要只是被抛给一个问题,帮助定义它
作为一个技术人员,你对解决问题的热情定义了你。与此同时,这个特征最终会阻碍你解决真正的问题。幸运的是,帮助定义问题不仅可以防止范围的改变,而且非常有趣。
有时,问题不是立即可以解决的,需要多个步骤才能实现——但同样,企业可能不知道这一点。与其被指责为你的流失模型无助于减少流失,你可以掌握自己的事情,为自己(或你的利益相关者,因为你应该更了解)构建一个路线图。

这是你释放所有创造力的时候,你又回到了五岁:
1.你为什么想知道是谁取消了他们的合同?
2。如果你知道这些,你会怎么做?
3。但是为什么,为什么为什么?
有大量的方法可以帮助你发现真正的问题(例如 5 个为什么、根本原因分析和石川(鱼骨)图),所以我将跳过这篇文章来节省我们的时间。我鼓励你们研究并熟悉它们。
最后,我想分享我用来揭示我的利益相关者有什么问题的研讨会框架。
研讨会框架:定义用例并确定优先级
今年早些时候,我参与了一个“帮助我们创建 XYZ 滚动预报”的项目。这似乎是一个直接的时间序列预测问题,但当试图最终确定需求时,我意识到每个人都认为这种“预测模型”将提供巨大的差距。它包括每日预报(每月的时间序列?!)到用户必须执行的具体行动要求,以缩小差距。
我召集了一大群来自不同业务部门的人,开了一个研讨会,了解他们真正想要的是什么。最后,每个人都同意他们需要一个时间序列预测模型,但是他们现在想要的是一个场景规划工具。
这个 3 小时的研讨会让我发现:

让每个人都发泄出来
这是你问每个人他们生活中有什么问题的部分。这些可以是大的或小的,长期的或短期的,他们观察到的或他们经历的,他们想要的或他们需要的。

The actual screenshot from the actual workshop #provingithappened
将他们所有的愤怒和挫折分成不同的主题,并向听众总结。
第二步:让每个人都思考
最重要的部分不是他们想要什么,而是 为什么 他们想要。第一步的全部目的是唤醒他们对世界上所有问题的记忆。练习的这一部分迫使他们理解为什么他们会感到沮丧。他们想实现却无法实现的是什么?

第三步:让每个人都为此而战
然而可悲的是,有些梦想注定永远是梦想,企业自己认识到这一点是至关重要的。通常,不同的利益相关者在奖励水平上会有分歧:信贷团队想要所有最有可能违约的用户,呼叫中心想要最有可能升级的用户,而财务团队想要终身价值最高的用户。你可以解释为什么有些项目很难实现,但是对于回报,商业利益相关者必须自己解决。

最后:有一个路线图。
有一个路线图,如果不是为业务,那么为自己。
当然,需求总是会变化的,但是具有前瞻性的观点有助于让每个人都保持在正确的轨道上。最终的目标往往是一条漫长而艰辛的路,所以眼睛盯着球,放开那 0.2%的准确度。

有时候在现实生活中,够好就够好了
如果你喜欢这篇文章,我将在接下来的几周发表以下内容:
- 如何用业务管理数据科学项目范围
- 如何向企业传达数据科学项目进展
我会确保这些帖子出来后我会超链接它们:)
从学术界到工业界的建议
我学到的从学术界转移到数据科学工作行业的经验

Unsplash
我职业生涯早期是一名学者,在工业界工作了十年。我在公司环境中做的许多事情经常让我想起学术生活。我阅读大量的工业发展文章(有时是研究论文),指导人们的职业发展(有时是研究生),在真实数据(有时是玩具数据集)上试验不同的技术,为商业客户写建议书(不再有研究拨款),写演示文稿(不是为了在课堂上教学生)。
我希望我的一些经验可以帮助你避免陷阱,平稳过渡。
做好准备。这是艰难的
总的来说,我相信从生命的早期开始就没有容易的转变。我仍然记得当保育员向我解释如何让婴儿从婴儿室过渡到学步室时。从学术界转到工业界并不容易,可能比换领域要难得多。在学术界呆的时间越长,跳槽就越难。这也是一种生活方式的改变,会引起不适。这可能比你预期的要长得多,而且你可能会面临一些文化冲击。所以,你应该做好准备,告诉自己这将是艰难的。
搬家前先试一试
当你还在校园工作的时候,不管你是做研究,还是做教学,或者两者兼而有之,你都应该尝试着去涉足行业工作。你应该寻找机会,利用来自行业合作伙伴的真实数据进行研究项目,以解决真实的行业问题。问题和数据可能很小或定义很窄,但它仍然会为您提供学习业务逻辑和了解行业的机会。有时你会有机会在公司工作或参观公司,并与业内人士直接接触。如果你的重点是教学,试着成为基于行业的学习、教学和课程开发的一部分。在这两个场景中,你将接触到在工业领域工作的人,并接触到真实的工业商业案例。以我的经验来看,这些都是非常有价值的经历,它们会帮助你决定是否真的想搬家。
按照行业风格准备你的简历,去掉你的出版物
经过几轮求职后,你会收集到一份你感兴趣的职位空缺清单。在您点击“上传”提交您的简历之前,请检查您的简历是否超过两页,或者是否包含您所有出版物的一页。当我要求扔掉你完成的出版物和资助时,我完全理解你的感受。我还记得有一段时间我觉得这是我简历上除了学位以外唯一具体的东西。把它们拿走!把它们变成你学术成就的总结,你已经发表了许多有声望的期刊论文。不过,我有一份我的学术简历作为纪念。你应该做的是将你在研究、项目和教学中所做的转化为行业雇主所渴望的技能清单。例如,突出你的团队工作,时间管理,演示,分析,沟通技巧。只有当你的专业技能相关时,才包括在内。
上 LinkedIn,参加聚会,和招聘人员交流
申请一个网上的职位空缺不足以实现你从学术界转向工业界的目标。即使你积极申请很多工作,回复率也可能非常低。如果你是那种刻板的内向者,不太想亲自或在社交聚会上与人交谈,那么一定要利用 LinkedIn 这样的专业社交平台,发布你的知识,分享你的技能,你会得到未来雇主的注意。如果你乐于参加社交活动,你可以参加很多聚会,在那里你可以亲自与人建立联系。不要忘了和招聘人员谈谈。他们可以帮助你进入一个你从未考虑过的目标市场。
找一个导师或者以前做过这个的人
找一个做过过渡的导师不容易,但是你要尽量找一个以前做过过渡的人,寻求建议。即使这个人不是和你在同一个领域工作,他们的经验仍然是非常相关和有用的。当你从一次失败的面试中得到的一些评论让你感到沮丧或困惑时,你可以向那个人寻求反馈,以确认你所做的事情是否正确。你的错误可能是每个人在尝试跳跃时都会犯的。如果你能找到一个和你同领域的人,特别是你已经认识并信任的人,他们可能会帮助你制定适合你情况的策略。
选择一家有 R&D 的公司来轻松过渡
在你的行业中有许多不同类型的公司,从咨询公司到公司,再到初创公司。以我的经验来看,与直接跳到咨询或商业公司相比,加入一家公司的 R&D 能让你更平稳地过渡。尽管许多 R&D 机构做的开发比研究多得多,但 R&D 的各个部门仍在学术风格的商业环境中运作,这种环境远没有企业那么正式。你可以避免大的文化冲击,并经常找到像你一样从学术界转到工业界的人。
选择一个老板,也许不是一个完美的职位描述
假设你面前有两个类似的机会:一个提供的职位描述对你的梦想来说并不完美,但足够接近你想做的事情,但你觉得未来的老板会欣赏你的技能,看到你的潜力;另一个职位有一个完美的描述,但你不会真正感受到未来老板的共鸣。我建议你挑能理解并看到你身上价值的老板。从学术界到工业界的转变更多的是在工作方式、思维和风格上,而不是你将要做的实际任务上。你可能会发现,工业界的工作不像你在学术界做的项目和任务那样被狭隘和严格地定义,而且会有很大的发展和变化的灵活性。最重要的是,好老板会给你探索的空间。
用足够的时间试一试,并从中学习
恭喜你!你锁定了一个机会,你准备从学术界进入工业界。当我听到你们中的一些人发现这太难适应或者这对你们来说不够有智力挑战时,我不会感到惊讶。不管你的感受是什么,请不要太快下结论。你的第一份行业工作会给你一个分析利弊的基线,接下来的转变会容易得多。
数据科学是一个有利于快速向产业跃升的领域吗?
这个主题可以单独成为一篇文章。数据科学家职位的数量正在快速增长,博士学位在候选人要求上得到了高度认可,这当然让许多离开学术界的人认为他们比其他候选人更具竞争力。然而,这也可能会产生误导,因为博士学位并不是选择标准中最重要的东西,也有更多的候选人申请。如果你对商业、编码、数据、解决问题和不断学习新事物感兴趣,你可以成为一名伟大的数据科学家。有很多材料、课程、竞赛和开源项目,如果你愿意投资,还有很多机会。只是不要以为,因为你有博士学位,你就自动比任何人都优秀。
所有的建议纯粹是基于我自己的经验,可能不适用于你的情况,但希望你会发现一些有用的东西。祝你顺利过渡。
这篇文章在 LinkedIn 上也有。
确保数据科学和产品管理之间成功关系的提示
来自 NeuroFlow 团队的建议,neuro flow 是一家医疗保健技术和分析公司,致力于在整个护理过程中实现行为健康访问和参与

Speaking on a panel at Comet.ml meetup with Bill Lynch, Michelle Morgenbesser and Jean-Francois B. Guertin
上个月,我们的首席数据科学家 Bill Lynch 和我应邀参加了由 Comet.ml 在纽约举办的专题讨论会,讨论数据科学和产品团队如何合作。作为一家医疗保健软件和分析公司的产品负责人,我已经迫不及待地报名了。此次活动以热烈的讨论和有趣的问题为标志,涵盖了技术公司中关于这两个关键业务部门如何成功合作的新兴话题。比尔和我总结了我们在 NeuroFlow 工作期间与观众分享的一些经验教训:
项目选择本来就是协作的
数据科学触及业务的每个部分,推动产品组织中一些最高价值的计划。因此,我们发现位于产品和数据科学之间的项目通常需要其他利益相关者的支持。与这些其他功能的对话可能发生在不同的时间(例如,优先级和范围批准来自领导层,架构可能来自工程),但是它们是帮助项目向前发展并朝着正确的方向前进的关键,最终为业务交付价值。
尽早并经常传达价值
不管是好是坏,移动目标通常与数据科学计划相关联;这就是为什么考虑到这些努力的较长时间线,展示进展是重要的——什么可行和什么不可行可能与构建事物本身一样重要。我们发现,每两周向公司的相关利益相关者分享数据科学里程碑、阻碍因素和项目更新有助于实现这一目标,并让人们提出我们可能没有想到的问题。
取得正确的平衡
我们注意到一种模式,工程师解决已定义的问题,而数据科学家解决未定义的问题。因此,为实质性的人工智能项目做一些适当的客户发现是很重要的。走出去问客户,你正在考虑的机器学习模型或算法是否会真正有用,为他们解决一个关键问题。考虑到我们在时间和资源上的限制,我们不能花费数周的时间来开发一些东西,然后从客户那里听到,“嗯,这很有趣,但是我真正需要的是这个或那个。”最终用户不仅需要获得模型的结果,还需要能够直观地知道它在做什么以及为什么做。这并不容易,但你需要在进入有趣和好玩的兔子洞之间取得平衡——这有时会带来创新和突破——同时带来即时价值。
测量是关键
以定量的方式监控数据科学工作至关重要。我们将 NeuroFlow 的数据科学项目指标分为三个不同的类别:
- 业务指标(即收入目标)
- 产品指标(即应用下载和使用)
- 模型指标(即精确度、F1 分数)
我们的使命是弥合身体和精神健康之间的差距,适当的数据科学将成为实现这一目标的催化剂。我们希望这些提示能帮助其他公司在数据科学和产品之间的微妙但重要的动态中导航。我们错过或忘记什么了吗?请通过评论或联系 julia@neuroflowsolution.com 让我们知道。
关于神经流:
NeuroFlow 是一家医疗保健技术和分析公司,致力于在整个护理过程中实现行为健康访问和参与。NeuroFlow 结合了经过验证的技术、数据科学和行为经济学,允许数百家诊所、卫生系统和提供商使用循证实践客观地评估、跟踪和吸引患者,以支持他们的精神健康。欲了解更多信息,请访问www.neuroflowsolution.com。
多元线性回归的技巧和窍门
收集分析数据、诊断模型和可视化结果的方法
这个分析是我决定在学校回归分析模块中承担的一个项目。我已经学习并收集了几种方法,你可以在 R 中使用,使你的分析更深入。像往常一样,我总是自学最有发现的东西。
数据
回应变量:承认的机会
预测因素:GRE 成绩,托福成绩,大学评级,SOP,LOR,CGPA,研究
图书馆
library(dplyr);
library(ggplot2);
library(GGally);
library(vioplot);
library(corpcor);
library(ppcor);
library(mctest);
library(ggfortify);
library(lmtest);
library(MASS);
library(car);
library(DAAG);
library(jtools);
library(relaimpo);
描述性统计
summary(df)

分布图
par(mfrow=c(4, 2))
colnames = names(df)
for(name in colnames) {
vioplot(df[name], horizontal=TRUE, col='gold', lineCol='gold', lty=0, colMed='floralwhite', yaxt='n',rectCol='dodgerblue4')
title(main=name)
}

There is no extreme skew for the variables. this makes the confidence intervals for estimating parameters for our predictors and estimating the mean response more meaningful.
检查 1)DV 和每个 iv 之间的线性 2)iv 之间的多重共线性
ggpairs(df, progress=FALSE)

From the last row, we can observe that most of the IVs seem to have a linear relationship with our response variable except for the binary variable Research. Therefore the assumption for linearity between DV and each of IVs hold.
所有变量的成对相关性都相当高。这似乎违反了多元线性回归没有多重共线性的假设。
偏相关系数
考虑到其他预测因素的混杂效应。
pcorr = as.data.frame(cor2pcor(cov(df)))
names(pcorr) = names(df)
rownames(pcorr) = names(df)
pcorr = format(pcorr, digits=1)
print.data.frame(pcorr)

The partial correlation coefficients suggest otherwise, that there is less multicollinearity with only GRE.Score & TOEFL.Score having a value > 0.4. Partial correlation between CGPA and our response variable Chance.of.Admit is fairly high but it does not violate the “No Multicollinearity between its IVs assumption” of MLR.
使用个别多重共线性诊断测量
imcdiag(df[,1:7],df$Chance.of.Admit)

All the predictors have a VIF (=1/(1-R²)) value of <5 which indicates that the multicollinearity is not so problematic.
安装 MLR
fit = lm(Chance.of.Admit ~ ., data=df)
summary(fit)

Fit: Chance.of.Admit = -1.28 + 0.00186(GRE.Score) + 0.00278(TOEFL.Score) + 0.00594(University.Rating) + 0.00159(SOP) + 0.0169(LOR) + 0.118(CGPA) + 0.0243(Research) (3s.f.)
这表明平均而言,GRE 每增加一个单位。分数/托福。分数/大学。Rating/SOP/LOR/CGPA/Research 在保持所有其他变量不变的情况下,将录取机会增加 0.00186/0.00278/0.00594/0.00159/0.0169/0.118/0.0243。
F 统计量的 p 值是<2.2e-16, indicating that we can reject the null hypothesis that the intercept-only model is the same fit as the MLR model even at alpha=0.001. Therefore, the MLR model is highly statistically significant at the 0.01 significance level.
The Adjusted R-squared: 0.8194 is high which suggests that the model is a good fit.
The coefficients for GRE.Score, TOEFL.Score, LOR, CGPA, Research are statistically significant at alpha=0.01 where the respective pvalues < 0.01 as we reject the null that their coeffs is 0 at the 0.01 significance level.
The coefficients for University.Rating (0.118) and SOP (0.728263) are > 0.01,我们无法在 0.01 的显著性水平上拒绝它们的系数为 0 的空值。
模型诊断
autoplot(fit)

(1)残差 vs 拟合
蓝线(每个拟合值的残差平均值)几乎是平的。这表明残差没有明显的非线性趋势。残差看起来是随机分布的,但当接近较高的拟合值时,它会收敛。这似乎是方差的减少,它违反了 MLR 的同方差假设。
bptest(fit)

Using the Breusch-Pagan test, we can reject the null hypothesis at the 0.05 significance level that variance of the residuals is constant and infer that heteroscedasticity is present. Therefore, this makes our coefficient estimates less precise and increases the likelihood that the estimates are further from the true population value.
(2)正常 Q-Q (分位数-分位数图)
残差似乎偏离较低尾部的对角线很多。残差的分布向左倾斜。这表明 MLR 模型对残差正态性的假设被违反。
使用 Box-Cox 幂变换变换响应变量,使其正常并处理异方差
bc = boxcox(Chance.of.Admit ~ ., data=df);

The procedure identifies an appropriate exponent (Lambda = l) to use to transform data into a “normal shape. The Lambda value indicates the power to which all data should be raised and it is suggested to use lambda=2.
lambda = bc$x[which.max(bc$y)]
powerTransform <- function(y, lambda1, lambda2 = NULL, method = "boxcox") {
boxcoxTrans <- function(x, lam1, lam2 = NULL) {
# if we set lambda2 to zero, it becomes the one parameter transformation
lam2 <- ifelse(is.null(lam2), 0, lam2)
if (lam1 == 0L) {
log(y + lam2)
} else {
(((y + lam2)^lam1) - 1) / lam1
}
}
switch(method
, boxcox = boxcoxTrans(y, lambda1, lambda2)
, tukey = y^lambda1
)
}
# re-run with transformation
bcfit <- lm(powerTransform(Chance.of.Admit, lambda) ~ ., data=df)summary(bcfit)
调整后的 R 平方从 0.8194 增加到 0.8471,而预测因子仍然显著。然而,这个模型的可解释性较差,我们希望我们的模型尽可能简洁。我们将在以后探索更多的模型。
(3)残差与杠杆
cooksd <- cooks.distance(fit)
sample_size <- nrow(df)
plot(cooksd, pch="*", cex=2, main="Influential Obs by Cooks distance")
abline(h = 4/sample_size, col="red")
text(x=1:length(cooksd)+1, y=cooksd, labels=ifelse(cooksd>4/sample_size, names(cooksd),""), col="red")

This helps us to find influential outliers. They are points above the dashed line which are not approximated well by the model (has high residual) and significantly influences model fit (has high leverage). By considering Cook’s D > 4/sample size criterion, we identify influential outliers to remove.
移除异常值后重新拟合 MLR
influential = as.numeric(names(cooksd)[(cooksd > (4/sample_size))])
df2 = df[-influential, ]
fit2 = lm(Chance.of.Admit ~ ., data=df2)
summary(fit2)

By removing the highly influential outliers, we refitted the model on the filtered data and the Adjusted R-squared increased to 0.8194 to 0.8916 without introducing complexity to the model.
使用响应变量的函数来拟合模型
fit3 = lm(exp(Chance.of.Admit) ~ ., data=df2)
summary(fit3)
通过回归我们对预测因子的反应指数,我们得到了调整后的 R 平方从 0.8916 增加到 0.9023,而预测因子仍然保持显著性。
通过添加交互项来说明交互
fit4 = lm(exp(Chance.of.Admit) ~ GRE.Score*University.Rating+TOEFL.Score+Research+SOP+LOR+CGPA, data=df2)
summary(fit4)

Interaction arises as the relationship between Chance.of.Admit and the IVs: GRE.Score and University.Rating is affected by the interaction between the GRE.Score & University.Rating. This makes it hard to predict the consequence of changing the value of GRE.Score & University.Rating without controlling for this interaction.
该模型显示了 GRE 之间的显著交互作用。分数&大学。评级为 p 值=0.000799 < 0.001 and is significant at the 0.001 significance level.
Comparing nested models with ANOVA
anova(fit3, fit4)

The first order model is nested within the interaction model. By using ANOVA to compare the simpler first order model vs the more complex model with interaction term, the p-value=0.0007995 is <0.001. The null hypothesis that the reduced simpler model is adequate is rejected at the 0.001 significance level. Therefore, the complex model did significantly improve the fit over the simpler model.
Drop insignificant predictor SOP
fit5 = lm(exp(Chance.of.Admit) ~ GRE.Score*University.Rating+TOEFL.Score+Research+LOR+CGPA, data=df2)
summary(fit5)
Previously, SOP was insignificant at the 0.05 significance level and even after removing it, the model’s Adjusted R-squared is still 0.904.
Variable selection using stepwise model selection by AIC
step <- stepAIC(fit5, direction="both")

A model with fewer parameters is to be preferred to one with more. AIC considers both the fit of the model and the number of parameters used. Having more parameters result in penalty. AIC helps to balance over- and under-fitting. The stepwise model comparison iteratively adds/removes variables one at a time and compares the AIC. The lowest AIC is selected for the final model.
step$anova

In our case, there no further addition or removal of variables required by AIC.
Relative feature importance
calc.relimp(fit5,type="lmg", rela=TRUE)

Relative importance is measured by an algorithm by Lindemann, Merenda and Gold (lmg; 1980) which decomposes total R-squared and observe the increase in R-squared by adding the predictors sequentially. The order of adding predictors matters and therefore, the algorithm takes the average of the R-squared across all orderings.
Relative importance is measured by an algorithm by Lindemann, Merenda and Gold (lmg; 1980) which decomposes total R-squared and observe the increase in R-squared by adding the predictors sequentially. The order of adding predictors matters and therefore, the algorithm takes the average of the R-squared across all orderings.
The features are ranked in this order with highest relative importance first: GRE.Score, CGPA, University.Rating, TOEFL.Score, LOR, Research and GRE.Score*University.Rating.
K-Fold cross-validation results on final model
cv_new = CVlm(data=df2, fit5, m=3, printit=FALSE)attr(cv_new, "ms")[1] 0.007749426

Each of the k-fold model’s prediction accuracy isn’t varying too much for any one particular sample, and the lines of best fit from the k-folds don’t vary too much with respect the the slope and level. The average mean square error of the predictions for 3 portions is 0.00775. The value is low and represents a good accuracy result.
95% CIs for every IV’s estimates
export_summs(fit5, error_format = "[{conf.low}, {conf.high}]", digits=5)

plot_summs(fit5)

Individual CI plots
effect_plot(fit4, pred = CGPA, interval = TRUE, plot.points = TRUE)

I hope this has helped improve your analysis one way or another. Please do not take any of it as a perfect example or as entirely correct and accurate as I am still learning as well. This has certainly liven up my otherwise dull module 😃.
请在 LinkedIn 或通过 jasonyip184@gmail.com 与我进一步讨论!
清理你的 R 代码!更好的特征工程的秘密

by jarmoluk at pixabay.com
使用变异特征设计新的分类
dplyr中最有用的函数是mutate;它允许您创建新的变量——通常是通过在数据集中的其他变量之上分层放置一些逻辑。
快速示例
假设您正在分析用户数据,并希望根据使用量对用户进行分类。
您决定需要四个等级——非活动用户、受限用户、健康用户和高级用户。
您的代码可能如下所示。您将在这里看到的是,为了创建新的user_type变量,我们使用mutate函数,声明新的变量名,然后利用ifelse来确定在什么波段下应用不同的值。正如你在下面看到的,如果应用程序中的动作少于 5,这是最低的阈值,那么我们称之为非活动...如果该标准不为真,那么我们将进入下一个ifelse语句来建立下一组标准。
df %>%
mutate(user_type = ifelse(
app_actions <= 5, 'inactive user', ifelse(
app_actions <= 10, 'limited user', ifelse(
app_actions <= 15, 'healthy user', 'active user' ) ) ) )
虽然ifelse是一个主要工具并且非常有用,但是当你开始嵌套太多ifelse时,就会出现一些问题。
- 难以解释和编辑的混乱代码
- 你写了很多多余的代码
我应该补充一下,我上面写的并不太疯狂,但是你可能很快就需要两位数的ifelse语句,这就产生了我们正在讨论的问题。
case_when化险为夷
在许多方面,R 比 sql 提供了更多的灵活性,但是也就是说,许多人不必要错过的一个 SQL 命令是case_when。幸运的是,case_when实际上是 r 中的一个东西。
查看用case_when呈现的完全相同的代码片段。
df %>%
mutate(user_type = case_when(
app_actions <= 5 ~ 'inactive user',
app_actions <= 10 ~ 'limited user',
app_actions <= 15 ~ 'healthy user',
TRUE ~ 'active user' ) )
同样,这是一个非常简单的示例,但是当您必须进行二十种条件/值组合时,这可以节省大量时间,并且清晰易读。这里的主要区别在于,左侧实际上是为条件保留的,~符号用作比较值&之间的分隔符,显然右侧是要给出匹配标准的值。最后一点,TRUE作为最终的总括,类似于else语句。
结论
简而言之,虽然ifelse有它们的位置并且非常有用,但是当你面对无数的ifelse陈述时,case_when让一个简单的&变得容易解释。
我希望这在你所有的特性工程工作中对你有用!如果你觉得这有用而且有趣,来看看我们在 datasciencelessons.com 的其他数据科学帖子吧!祝数据科学快乐!
原载于 2019 年 11 月 22 日【http://datasciencelessons.com】。
是时候了:使用决策树来解释模型行为
如何用一个简单的决策树来帮助你理解什么让你的深度模型表现好,什么不好?

在 Taboola,我们每天都在努力改进我们基于深度学习的内容推荐模型。我们使用它每天向数亿用户建议个性化的新闻文章和广告,因此自然地,我们必须坚持最先进的深度学习建模方法。但我们的工作并没有就此结束,分析我们的结果也是必须的,然后我们有时会回到数据科学的根本,应用一些非常基本的技术。
让我们来解决这样一个问题。我们正在研究一个行为相当奇怪的深度模型:对于看起来像是随机的一组广告客户,它赢过了我们的默认模型,而对于另一组广告客户,它输了。这种行为每天都是稳定的,所以看起来可能有一些内在的广告商品质(我们称之为活动特征)要对此负责。您可以在下面看到 4 个活动的典型模型行为。

Daily results for selected campaigns, compared to a baseline of 100%. We can see the new model is very stable. But, how can we predict which campaign is going to succeeded?
因此,我们假设,这场运动的某些因素使得这个模型要么成功,要么失败。会不会是竞选使用的出版商类型?他们的观众规模?他们的每次点击成本?也许所有这些都在一起?圣诞老人还没来帮忙,所以我们应该调查一下!
如果我们认为可能有一个数字特征对此负责,我们可以用 python 编写一个简单的脚本来寻找不同活动特征和我们的标签之间的相关性。但是我们认为这不仅仅是一个竞选特征造成的,而且我们有许多分类特征——所以我们不能简单地联系起来。怎么办?让我们利用机器学习的力量!因此,我们将使用机器学习算法(特别是决策树)来帮助解释我们的深度学习模型结果:

在我们继续之前,您可能会有一些问题:
- 为什么要使用树,而不是像 SHAP 一样使用深度学习解释工具?我们在这里试图隔离活动特征,通用模型使用了许多现在不相关的其他特征(用户特征、上下文特征)。此外,我们可能有更多的元数据可以使用,而不是进入深度模型——比如,活动的语言,它已经运行了多长时间等。
- 为什么要用一棵树,而不是另一个深度模型来解决这个问题呢?我们寻求最大的可解释性,即使我们的模型不是 100%准确——只要它能指出让我们赢/输的主要疑点。
- 为什么使用简单的决策树,而不是随机森林或 xgboost?就像上一个问题一样。决策树足够强大,可以抓住主要的坏人,它只有几行代码,你可以绘制它!
- 我们如何选择树的深度?尽量保持简单,如果你认为你可能有 1-3 个主要特征要寻找,深度为 2 的树就足够了。你可以看看深度 3,看看你没有错过什么。再多可能就太多了。
因此,概括一下,我们生成一个包含我们所有活动特征的表格,并添加一个带有 0/1 的标签列,这取决于我们比默认模型做得更好还是更差(这是我们试图预测的)。使用此表来拟合树分类器。然后画出树,看看它找到了什么,或者只看按重要性排序的特征。只需大约 15 行代码就能得到结果,而且你阅读这篇文章的时间也更短。
这项技术最终变得非常有用:如果确实有使模型工作的特征,我们几乎可以立即发现它们。对于我们的情况,我们可以精确地指出我们需要多少流量来积累足够的数据以使我们的模型成功。更重要的是,在其他情况下,如果树只找到嘈杂的无法解释的列,这意味着我们的假设是错误的。
下面是我们粘贴实际代码之前的一些亮点。
- 树可以处理分类特征,但是你必须首先对它们进行编码。不用辛苦自己实现,用下面的熊猫内置函数。
- 小心与你的标签列相关的奇怪的列!记住可解释性是这里的关键——所以如果你突然发现某个随机的分类值在你的决策树上非常高,那很可能是噪音!去掉它,从头开始。
- 不需要在训练和测试之间分割数据,使用一个低的深度应该可以解决过度拟合的问题。
就是这样。有时,简单的解决方案甚至对令人困惑的问题也足够了。树是快速的,可解释的,它们的图形在演示中看起来非常好🙂
祝大家圣诞快乐,节日快乐!

正如承诺的那样,这里是 python 代码示例:
# Imports
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
import pandas as pd# Read the files
data = pd.read_csv(“your_file_here.csv”)
label = “your label column”# Split data from label
y = data[label]
X = data.drop(label, axis=1)# Data preprocessing:
# Fill in NaN
X = X.fillna(0)# Turn categorical features to 1 hot encoded columns
X = pd.get_dummies(X)# Fit tree
max_depth=2
classifier = DecisionTreeClassifier(random_state=0, max_depth=max_depth)
classifier.fit(X, y)# Print top 5 features by importance
print(“max depth:”, max_depth)
print(sorted(zip(X.columns, classifier.feature_importances_), key=lambda x: x[1])[-5:])# Plot tree
from sklearn.tree import export_graphviz
import graphviz
export_graphviz(classifier, out_file=”mytree.dot”,feature_names=X.columns)
with open(“mytree.dot”) as f:
dot_graph = f.read()
graphviz.Source(dot_graph)
本帖原载于 2019 年 12 月 18 日 https://engineering.taboola.com**的 。
泰坦尼克号:数据分析中的爱情
《泰坦尼克号》一直是我最喜欢的电影之一。自从这部电影在 1997 年被搬上大银幕以来,我已经看过至少 10 遍了。这部电影本质上是一个爱情故事,围绕着 1912 年在这艘臭名昭著的船上的两个主角。一个 17 岁的贵族在一艘豪华的、命运多舛的船上爱上了一个善良但贫穷的艺术家。
结局浪漫又悲伤。当我们为杰克和罗斯短暂的爱情悲伤时,1912 年泰坦尼克号上其余的 891 名乘客发生了什么?为了回答这个问题,我使用了 Kaggle 的乘客名单数据集,用机器学习算法预测生存或死亡困境。
这是一个比较两种机器学习算法应用结果的简单练习: K 近邻(KNN) 和 随机森林 。你可以在这里 找到数据集 的副本来试用。
为什么 KNN 和随机森林?两者都是 二进制分类算法 根据一个对象是否具有某些定性属性的决定,将给定集合的元素标记为两组(预测每组属于哪一组)。两者都是这一类中最流行的算法;其他的只是 KNN 和兰登森林的衍生物。你可以在这里阅读其他二进制分类算法。
当您的问题的答案落在一组有限的可能结果中时,二元分类在数据集上最有效。
一个例子是确定患者是否患有某种疾病的医学测试——分类属性是疾病的存在。在泰坦尼克号数据集中,我的目标是根据一组属性,如年龄、性别、机票等级等,预测乘客是否在悲惨的事故中幸存。这是一个经典的二元分类,因为只有两种可能的结果:生存或死亡。
让我们深入研究代码。请注意,有许多方法可以执行 Python 代码。为了简单和易用,我更喜欢 Python 的 Jupyter 笔记本。
数据准备
第一项任务是从文件中加载训练数据集。Python 提供了一种使用 Pandas 库加载和操作数据集的简单方法。让我们从导入实用程序库和训练数据集开始。
**import** **pandas** **as** **pd**df = pd.read_csv('titanic_dataset.csv')
df.head()

Top 5 rows of the data frame
使用数据集时,一些记录可能不完整。由于我们的示例包含几十年前的数据,因此会有一些信息丢失。
幸运的是,有一些方法可以填补一些缺失的数据。对于所进行的分析,年龄是表征因素之一。因此,数据集包含所有记录的年龄非常重要。下面的代码将从数据集中计算平均年龄,然后用计算出的平均值填充任何缺失的记录。它还会将始发港未知的乘客的港口设置为“S”。
*# Fill the missing age with mean*
mean_age = df['Age'].mean()
df['Age'] = df['Age'].fillna(mean_age)*# Fill the missing embarked port with S*
embarked_port = 'S'
df['Embarked'] = df['Embarked'].fillna(embarked_port)
客舱位置可能会潜在地影响乘客存活率。但是,值的数量不太理想,最好删除。可能其他信息如 PassengerID 和 Name 可能不相关。因此,其他列可以从我们的数据集中删除,因为它们没有增加任何实际价值。
*# Drop Cabin & PassengerID columns*
df = df.drop(['PassengerId', 'Cabin', 'Name'], axis = 1)
尽管人类更喜欢文字,但计算机喜欢和数字打交道。我们数据准备的下一个任务是将人类可读的标签转换成算法可以解释的数字。下面的代码将字符串转换为整数,为每个表示的值添加新列,并根据特定值是否在行中表示,将值 0 或 1 分配给每个列。这将把性别(Sex)和装载列从字符串更改为整数,并将它们作为男性/女性和 CQS(字母代表装载的始发港)添加回数据帧。
df_sex = pd.get_dummies(df['Sex'])
df_em = pd.get_dummies(df['Embarked'])
df2 = pd.concat([df, df_em, df_sex], axis = 1)df2.head()

Top 5 rows of data frame after data preparation
在上表中,我们可以看到第一排的乘客是一名男性,他从一个未知的始发港上船。因此,S 和男性列被设置为 1,C/Q/女性被设置为 0。
K-最近邻
我们将回顾的第一个算法是 K-最近邻算法。你可以在维基百科中找到更多关于该算法的信息。
在下面的代码中,我实例化了算法,并使用 StandardScaler 将数据转换为使用相同范围的值。接下来确定如何在不同的训练数据集之间拆分数据,随后使用 cross_val_score 函数调用算法,并在拆分的数据集中找到算法的准确性。
*# instantiating a K Nearest Neighbor model*
**from** **sklearn.neighbors** **import** KNeighborsClassifier
clf = KNeighborsClassifier(n_neighbors = 5)*# import classes and functions from the library to be used in cross validation*
**from** **sklearn.preprocessing** **import** StandardScaler
**from** **sklearn.pipeline** **import** Pipeline
**from** **sklearn.model_selection** **import** StratifiedKFold, cross_val_scoress = StandardScaler() *# packages scaler and model together*
pipeline = Pipeline([('transformer', ss), ('estimator', clf)])*# how we want to split up the data*
skf = StratifiedKFold(n_splits=5,random_state=42)*# using cross_val_score to train 80% of data and test remaining 20%. Generate 5 scores as it tests 5 different times*
scores = cross_val_score(pipeline, X, y, cv = skf)scores
输出:数组([0.79888268,0.78212291,0.82022472,0.84269663,0.83050847])
cross_val_score 函数将我们之前从文件中加载的初始数据集分成 5 个子集,并对每个子集运行 KNN 算法。然后计算算法的精度。换句话说,它检查算法是否成功地计算出了实际发生的结果。阵列显示,对于每个子集,该算法的准确率为 79–84%。
何时使用 KNN:
- 数据被标记
- 数据是无噪声的
- 数据集很小,因为算法被认为是“懒惰的学习者”
随机森林
我们要讨论的下一个算法是随机森林。同样,你可以在维基百科中找到更多关于该算法的信息。
在 Python 中使用该算法非常简单。我们再次使用具有相同输入和预期输出的 cross_val_score 函数。
*# instantiating a K Random Forest model with the default arguments*
**from** **sklearn.ensemble** **import** RandomForestClassifier
clf_rf = RandomForestClassifier()**from** **sklearn.model_selection** **import** cross_val_score, StratifiedKFold *# how we want to split up the data*
skf_rf = StratifiedKFold(n_splits = 5, shuffle = **True**, random_state = 42)*# using cross_val_score to train 80% of data and test remaining 20%. Generate 5 scores as it tests 5 different times*
score_rf = cross_val_score(clf_rf, X, y, cv = skf_rf)score_rf
输出:数组([0.81005587,0.77094972,0.80898876,0.85393258,0.82485876])
如前所述,对于 KNN,cross_val_score 函数对随机森林的作用类似。它分割初始数据集,对每个子集运行算法,然后计算算法的准确性。阵列显示,对于每个子集,该算法的准确率为 77–85%。
何时使用随机福里斯特:
- 大型数据集
- 不要过度拟合
- 数据集包含缺失数据,因为算法可以自动估计它们。可以使用的其他度量是切比雪夫、余弦等。
外卖:
在我的 KNN 模型中,一个值得注意的观察是 StandardScaler 的加入,这是包含不同规模变量的数据集中的一个必要步骤。在《泰坦尼克号》中,值为 5 到 50 的年龄列与 3 美元到 125 美元的票价列相比具有不同的比例。StandardScaler 执行标准化的任务。我发现这种利用极大地提高了我 KNN 模型的准确性,从基线的 62%提高到平均 81%。
具有最小训练阶段的 KNN 对于像泰坦尼克号这样的较小数据集是理想的,因为 KNN 在测试阶段保留所有的训练数据。在超过 100k 行的大型数据集中,随机森林可能更理想。与 KNN 相比,随机森林模型建立标签/分类所需的初始训练时间更长。然而,应用程序要快得多,因为事实模型是在新对象通过时创建的。
海难导致如此多生命损失的原因之一是没有足够的救生艇容纳乘客和船员。虽然幸存有一些运气成分,但是一些群体比其他群体更有可能幸存。女性性别和存活率之间有很强的相关性。尽管男性乘客比女性乘客多 84%,但女性幸存者比男性多。
当面对种类繁多的机器学习算法时,初学者提出的一个典型问题是“我应该使用哪种算法?”这个问题的答案取决于许多因素,包括:(1)数据的大小、质量和性质;(2)可用的计算时间;(3)任务的紧迫性;以及(4)你想用这些数据做什么。
这个有用的 scikit-learn 流程图为您提供了一个映射指南,帮助您根据数据大小、数据类型、预期结果和数据结构来确定最佳算法。

Credit: © 2007–2018, scikit-learn developers (BSD License)
参考文献:
二元分类。在维基百科中。检索于 2019 年 2 月 23 日,来自 https://en.wikipedia.org/wiki/Binary_classification
选择正确的评估者。在 Scitkit-Learn 中。检索于 2019 年 2 月 23 日,来自https://sci kit-learn . org/stable/tutorial/machine _ learning _ map/index . html
sci kit-learn:Python 中的机器学习,Pedregosa 等人,JMLR 12,第 2825–2830 页,2011 年。
抓住一个剑桥:监管法国的公开数据
由吉娜·阿克鲁特、萨曼莎·班西尔、马克西米利安·德·弗雷兹、亚斯米恩·莫罗、阿加特·R和尼古拉·乌尔施勒格
六名政治学院的学生寻求利用法国公开的犯罪数据来获得更大的利益。

经过两天的激烈竞争,我们这些掌握数字和新技术科学专业的学生参加了一个数据马拉松,旨在对来自法国公共服务的开放数据集的研究和计算进行实验。我们中的六个人决定研究公务员的费用问题。
寻找正确数据的挑战
我们的公共政策问题最初集中在法国公务员的成本上。为了成功回答我们的研究问题,我们试图在互联网上找到准确可靠的数据,然而,我们很快意识到许多数据集要么不可用、不完整,要么格式不正确。例如,我们在经合组织网站上找到的一个数据库提供了许多经合组织国家预算支出的详细数据,但没有法国的数据。似乎能提供我们正在寻找的信息的其他来源要么有过时的链接,要么由于缺乏正确的凭证而无法访问。
一份 Cour des Comptes 文件提供了图表,但是图表中使用的数据无法获取,因此无法核实。这揭示了透明度问题,并可能导致一些人质疑提供给已经过滤和“分析”的人的信息的真实性。通过向人们提供对简化信息的访问,理论上任何人都应该容易阅读和/或理解这条信息,但这阻止了那些想要实际挖掘迪普并出于学术原因或仅仅为了验证而使用“公开公共数据”的个人。

我们试图将话题转移到公务员养老金的成本上,希望我们能为这个更具体的话题找到高质量的数据。我们最终也面临着同样的问题。这些数据要么丢失了,要么已经被处理成让人们在无法接触到初始数据的情况下就能简单地阅读的形式。
甚至法国开放数据门户网站( data.gouv.fr )也提供了无法访问或无法使用的数据。例如,来自Caisse national de retraites des agents des collective s localés网站上的许多信息都是不可下载的。

改变话题
因此,我们被迫选择一个新的研究问题。有了对完整/干净数据集重要性的更好理解,我们试图解决另一个相关的公共政策问题:犯罪。我们选择犯罪作为一个问题,是因为它对公众福利的深远影响,也因为对这些数据的地理分析似乎是相关的。我们的目标是分析入室盗窃背后的相关数据和模式,以及更好地了解各部门之间的差异,以确定关键因素,如:警力密度、住房类型和社区财富水平。这一次,我们意识到这样一个事实,即我们的研究问题很可能必须根据我们所能找到的可用数据稍作调整。
为了创建一个完整的概览并探索整个国家的模式,我们分析了警方报告的数据,这些数据描述了自 1996 年以来每个月各省 107 起不同犯罪的警方档案数量。这些数据是最新的、完整的、可访问的,并且还提供了关于数据收集方式的描述,这对于找出可能影响数据集数量的偏差很有意思。
尽管警方报告提供的数据完整且质量良好,但我们知道其潜在的局限性。首先,并非所有罪行都被宣布,因此没有被纳入数据库。第二,日期是指它们被报告的时间,而不是它们发生的时间。最后,犯罪登记流程在过去几年发生了变化,即随着 2015 年 4 月 LRPPN 的实施,这意味着犯罪数量的部分变化实际上可能是由于登记流程的变化。我们试图绕过这些限制,把重点放在一类犯罪上,这类犯罪不应该被警方数据低估实际犯罪数量的问题过于关注。
考虑到大多数保险公司要求入室盗窃的受害者向警方提交报告才能获得赔偿,我们决定把重点放在入室盗窃上。网上公布的数字和统计数据以及法国内政部提供的数据证实,窃贼仍然以个人住宅为目标实施入室盗窃。回到法国大都市的规模,盗窃率相当于平均每天 667 起记录在案的盗窃案。换句话说,每两分钟就发生一起盗窃案。
我们决定专注于这一类别(更具体地说是针对主要住宅的盗窃)的原因之一是,事实上,如今追踪人们的活动越来越容易,例如,他们住在哪里,他们的习惯以及他们可能何时去度假。此外,为了不受犯罪登记流程演变的影响,我们选择将重点放在数据库中最近的两年,即 2017 年和 2018 年。
数据分析工作流程

Source: Joel Gombin via Github
从完整的警察犯罪数据集中,我们根据各个部门的盗窃总数对数据进行了过滤。我们将这些数据与 INSEE 提供的每个部门的人口数据进行了合并。因为入室盗窃与人口有关,我们进一步计算了入室盗窃与人口的比率,作为更准确的比较基础。然后,我们将这些数据集与这些部门的平均房产价值相结合,以每平方米的平均价格来衡量。由于我们在 data.gouv.fr 和 INSEE 的网站上都找不到关于房价的数据集,我们不得不手动创建它们,对法兰西岛地区使用来自 http://paris.notaires.fr 的估计,对其余省份使用来自https://www.efficity.com的估计。
最后,为了可视化数据,我们使用了 Science Po ' s Atelier de Cartographie 开发的 Khartis 地图 app 。在可视化数据后,我们使用多元线性回归来模拟财产价值和盗窃之间的关系,同时检查人口。
结果:
法国


法国 2018 年的入室盗窃/人口比例与房价的相关系数相对较高(0.5)。回归结果证实了房价与入室盗窃之间的正相关关系,在 99%的显著性水平上显著。即使在控制人口规模的情况下,房价变量仍然与入室盗窃数量呈正相关,并且仍然具有统计显著性(也处于 99%的水平)。我们还检查了多重共线性和异方差,没有发现多重共线性的证据,但有轻微的异方差。当校正异方差时,我们发现我们的结果仍然具有统计学意义。
法兰西岛大区(2017)


法兰西岛地区(2018)


我们对法兰西岛地区进行了回归分析,但没有足够的观察数据来证明相关性检验结果的显著性。因此,我们不能对法兰西岛地区的入室盗窃和房产价值之间的潜在联系做出任何结论。
我们的解决方案:电子警察
虽然法国国家相对来说是开放数据最好的供应商之一,但我们在网上找到的数据并没有给我们提供现成的数据。从为正确的研究问题获取适当的数据,到处理数据以供进一步使用,这一具有挑战性的过程对公共政策的制定和随后的实施具有重要意义。在我们的设计实验中,我们努力应用通过计算数据集收集的知识。
首先,为了形成一套多样化和创新的政策解决方案来解决我们的问题,我们试图通过集思广益来促进思想的自由流动。我们站在利益相关者的角度,更好地理解各方的观点,并以全面的方式处理问题。这一重要步骤提高了我们对数据处理复杂性的认识,从房主打电话到警察局报案开始创建数据,到警官为同事或上级写报告处理数据。然后,通过写下我们的想法,相互交流,并阐述彼此的想法,我们能够就我们的最佳选择达成一致:一个允许公民跟踪盗窃案件并在数据归档过程中成为更积极参与者的平台。
该数据库可在线访问,也可通过手机访问,具有简单的用户友好界面,允许利益攸关方通过多种途径访问,并与当局和保险公司建立沟通渠道。利用从不完整和/或难以使用的数据中吸取的经验教训,这一解决方案提高了收集数据的简单性和质量,以及透明度,有可能更有效地利用公共警察资源。
结论
总之,我们在访问数据集的复杂性方面的经验使我们更加意识到这些不可访问的数据对于公民和公共利益攸关方所代表的潜在损失。在我们的旅程中,我们仍然能够使用完整的数据库,这使我们能够根据部门研究盗窃的发生率,我们研究了与住房价格的关系。使用设计思维模型,我们为法国政府概述了可能的政策解决方案,以改善数据收集,作为一个简单且受监控的盗窃报告流程。最终,所收集数据的质量可以提高对入室盗窃模式的认识,帮助警方解决这些问题。
跳舞还是不跳舞?—机器学习方法。
我爱跳舞!好了,我说了。尽管我可能不想一直跳舞,但我发现自己经常滚动播放列表,寻找最适合跳舞的歌曲。事情是这样的,它与流派无关——至少对我来说是这样。但这一切都与音乐有关。

这一切是如何开始的
我有一个问题:我能根据歌曲的属性预测我是否能随着歌曲跳舞吗?所以,我开始寻找一些答案——但在我与你分享我的旅程之前,让我们讨论一些将在整个项目中出现的关键概念。
可舞性 根据歌曲的音频特征,如节奏、拍子、效价 等,描述歌曲适合舞蹈的程度。我选择 danceability 是因为它是一首歌的音频特征的直接产物,因此是这些特征的准确表达——因为我喜欢跳舞,我认为这将是创建播放列表和提供推荐的一个很好的选择。
许多歌曲已经有了与之相关的可跳性指数,我们将使用这些数据来预测之前没有被分类的歌曲的可跳性水平。
音频特征是用于表征音频信号 的 特征。在这种情况下,这些特征是调、调式、拍号、声音、能量、乐器感、活跃度、响度、语速、效价和速度。
于是旅程开始了…
进入机器学习
来自机器学习大师的 Jason Brownlee 所讨论的预测建模,指的是 从输入变量(X)到输出变量(y)逼近一个映射函数(f)的数学问题。这就是所谓的函数逼近问题 。换句话说,我们正在使用历史数据对新数据进行预测。
一般来说,我们可以将大多数函数逼近问题分为两大类:回归和分类。由于我想练习分类算法,所以我决定将其设置为分类问题。
分类到底是什么?
斯蒂芬·马斯兰德(Stephen Marsland)在他的书《机器学习,算法视角,中定义的分类问题包括 获取输入向量,并根据每个类别的样本训练来决定它们属于 N 个类别中的哪一个。
分类问题是离散的,这意味着每个输入向量属于一个类别,类别集覆盖整个输出空间。

有几种方法可以解决分类问题,每种方法的解决方法可能不同,但本质上都是试图找到将一个类与另一个类分开的决策边界。
数据
这个项目中使用的数据集是使用 Spotify 的 API 构建的。它由 266,000 个观察值(歌曲)和以下预测属性组成:
- 轨道名称
- 艺术家姓名
- 相册名称
- 歌曲所属的播放列表
- 发布日期
- 流行
- 持续时间(分钟)
- 声学
- 拍子
- 方式
- 钥匙
- 效价
- 工具性
- 语音
- 活性
- 活力
- 音量
- 时间签名
目标变量 danceability 是一个介于 0.0 和 1.0 之间的浮动值,为了对歌曲进行分类,该变量被离散化并分成三个类别,从而使这成为一个多类分类问题。
- 此处禁止跳舞(0.0–0.49)
- 稍微摆动一下(0.5-0.69)
- 像没有人观看一样跳舞(0.70-1.0)
探索性数据分析
永远不要低估 EDA 的重要性。您需要非常熟悉您的数据以理解它,为建模准备您的数据,为您的问题提供更好的背景,阐明您可能有的一些初始假设,并更好地解释您的模型的结果。另外,EDA 很有趣!在处理分类问题时,我至少会建议:
- 绘制观察值的分布图,以检查类别不平衡。
Code for count plot to check for class imbalance.
2.使用箱线图检测预测要素中的异常值和异常值。
Code to create boxplots.
3.相关矩阵,用于研究不同变量之间的关系,并检查数据的多重共线性。
Code to create a correlation matrix.
4.检查连续变量的分布。
Code to generate histograms.
5.使用堆积图检查每个离散要素类别中的观察分布。
Code to create stacked plots.
考虑因素,然后是模型
正如我前面提到的,有一些分类模型可以尝试。我在这个项目中使用了 8 种不同的模型,但是今天我们将讨论其中的三种:k-最近邻(KNN) 、决策树和随机森林;我将使用 Scikit-Learn 库来实现它们。
在您进行任何建模之前,您应该使用您新发现的数据知识,现在您已经完成了彻底的 EDA,来查看您的功能并做出关于功能工程和功能转换的决策。我不会谈论我做了什么,因为这一步没有一个公式。但这是非常重要的一步。如果你想了解更多这方面的知识,我强烈推荐:Sinan Ozdemir 的《简单的特性工程》。
在这一点上,你也应该开始考虑如何评估你的机器学习模型的结果。当然,我还有另外一本书也很喜欢:Alice Zheng 的《机器学习模型评估》。有不同的评估标准,在不同的环境中,为不同的问题服务于不同的目的。谈到这些,人们也有他们的偏好和观点。因此,你的选择最终将取决于所有这些因素的组合,以及你试图回答的问题。
对于这个特定的项目,我决定测量 F1 的微观平均分数,并使用混淆矩阵。F1 分数是精确度和召回率之间的加权平均值。在评估多类问题时,这是一个非常常见的指标。混淆矩阵显示了每个类别的正确和错误分类的详细分类,这很重要,因为每个类别的错误分类可能会产生不同的成本。
k-最近邻(KNN)
假设你要去看歌剧,但你以前从未去过。你出现在歌剧院,却不知道该做什么。所以你选一个和你最亲近的人,观察,模仿。然后你去找 5 到 10 个和你最亲近的人,观察并模仿。这是 KNN 背后的总体想法。

Image from KNN Classification using Scikit-Learn by Datacamp.
KNN 存储整个数据集,并通过搜索 k 个最近的实例,并汇总这些实例的输出变量来预测新的数据点。为了确定实例之间的相似性,它计算距离的度量。这种度量可以是欧几里德距离、汉明距离、曼哈顿距离、闵可夫斯基距离、谷本距离、雅克卡距离、马哈拉诺比斯距离或余弦距离,仅举几个例子。
距离度量也是一种个人选择,取决于您的具体问题和数据;T2 k T3 号也是如此。通常,您会想要一起试验不同的数据度量和 k 的值,以查看哪种组合会产生最准确的模型。您可以在这里 查看使用 KNN 时可以调整的超参数列表。
在我的例子中,我决定使用 Scikit-Learn 中的穷举网格搜索方法来搜索超参数空间,以获得最佳的交叉验证分数。
KNN Classification: Model, Grid Search, Confusion Matrix and Classification Report.

Classification Report for KNN
这是一个很好的 F1 微观平均分数,但有一个关于 KNN 的小细节我之前没有提到:它是 计算昂贵的 ,并且它遭受 维度诅咒 。
决策图表
决策树在机器学习中相当受欢迎,因为制作一棵树的计算成本很低,使用它的成本更低。

Image from Decision Tree Classification with Python by Datacamp
借助决策树,我们将分类问题分解为一组决策,从根(基)开始,向下处理到叶。决策树不被视为黑盒型算法,因为它们共享内部决策逻辑。算法在给定节点上做出决策所依据的分割规则是您可以调整以优化决策树的超参数之一。其他流行的还有分裂策略和树的最大深度。
与 KNN 一样,在使用决策树时,有许多超参数可供选择,所以我再次使用穷举网格搜索来找到交叉验证分数最好的那些。
Decision Tree: Model, Grid Search, Tree Visualization, Confusion Matrix, and Feature Importance.

Classification Report for Decision Tree.
决策树的表现不如 KNN。如你所见,F1 的微观平均分数相当低。
随机森林
如果一个决策树是好的,那么许多树(因此,森林)一定更好,只要它们之间有足够的多样性。这是一个随机森林背后的基本思想,一个 集成学习 方法,在每个决策节点使用打包和约束特征选择的概念将随机性引入数据集。

Image by Victor F. Rodriguez-Galiano.
装袋,或 自举聚合 。bootstrap 样本是用替换样本进行的样本,所以我们最终会不止一次地选取一些观察值,而另一些则完全不选取。为什么?因为这样我们会得到很多表现稍有不同的弱学习者,这正是集成学习背后的想法。如前所述,随机森林也不同于常规决策树,它将学习算法限制在随机的特征样本上,以搜索每一棵单独的树;这样,每个子树都略有不同。在每个分割点可以搜索的特征数量是您可以使用的超参数之一。
Random Forest: Model, Grid Search, Confusion Matrix and Classification Report.

Classification Report for Random Forest.
这里要注意的一件重要事情是,即使 KNN 的 F1 微平均分高于随机森林,它也需要两倍以上的时间和内存来运行。正如我之前提到的,KNN 的计算成本很高。
那么,我们跳舞好吗?
有人说流派已死,有人不以为然。事实是,用户消费音乐的方式在过去 10 年里发生了巨大的变化。
播放列表创建习惯对音频流媒体公司进行更好的音乐推荐非常有帮助。正是因为播放列表为用户提供了灵活性,我们才开始发现使用流派作为推荐的主要特征还有哪些其他选择。
其中一个选项是可跳舞性。正如我们从我们一起经历的三个模型中看到的,我们可以准确地预测一首歌曲属于哪一个可跳舞类别。这意味着我们现在可以使用这个模型来分类那些没有舞蹈指数的歌曲,仅仅使用它们的属性。
在大多数情况下,你会尝试许多不同的车型来寻找最好的——我说的最好,并不是指 F1 微观平均分数最高的车型。你会想要一个在你选择的任何度量上都有良好性能的模型,是的,但是你也会想要警惕计算的复杂性,以及你的项目的特定需求。
算还是不算?粗心的估算可能导致错误结论的实际例子
有了估算缺失数据的强大力量,就有了了解自己在做什么的巨大责任。

Photo by Jean-Philippe Delberghe on Unsplash
背景
近年来,我有幸与许多在该领域起步的数据专业人士进行了交流,并看到他们中的许多人都经历了类似的顿悟:
你在课程中学到的东西并没有为你在现实世界中可能遇到的各种场景做好充分的准备!
公平地说,有太多的角落案例,没有哪门课程能够全面涵盖。因此,作为一名数据专业人员,我们每个人都应该把自己发展到能够解决我们从未见过的问题的程度。这篇文章讲的就是这样一个例子,这个例子在课程中没怎么教过,但它可能意味着一个“普通”的数据专家和一个“超出预期”的数据专家之间的区别。
每当建模任务中出现缺失数据时,一种常用的技术是估算缺失数据,这是我们的建模代码工作所必需的。然而,在有大量缺失数据的情况下,如大批量生产测量,插补后的结果模型表面上看起来可能很弱。但是只要再深入一点,就可以发现这个模型相当强大,估算值扰乱了度量计算。这篇文章就是一个这样的例子,用一个典型的非常稀疏的数据集来展示这个场景,这个数据集就是统计过程控制测量数据。这篇文章的所有代码都在这里:链接
统计过程控制
在现代大规模制造(HVM)工厂中,统计过程控制(SPC)系统对于确保所有制造设备交付符合客户规格的产品至关重要。例如,在自动化汽车装配厂,客户规格可能是平均汽车发动机应提供 22.5 英里每加仑(mpg)的燃料,并且是“响应”变量。
然而,自然界中没有一个过程会 100%的时间都在目标上。相反,正常的变化会导致一些发动机的输出功率高于 22.5 英里/加仑,一些发动机的输出功率低于 22.5 英里/加仑。假设客户理解这一点,可以容忍+/-1.5 英里/加仑的偏差。任何超出这些公差限制的发动机都不能出售给客户,需要报废或作为备件出售,从而给公司造成收入损失。因此,我们的响应变量的目标为 22.5 英里/加仑,控制上限(UCL)为 24 英里/加仑,控制下限(LCL)为 21 英里/加仑。
正如预期的那样,公司的高级管理层希望生产的发动机 100%符合这些规格(规范)。然而,在自然界中,除了死亡和税收,没有什么是 100%确定的。相反,作为工程师和统计学家,我们退而求其次:我们可以使用 SPC 系统和 6-sigma 流程来确保 99.73%的发动机符合规格。
延迟响应的困境
典型的 HVM 生产线从纯原材料到销售给客户的完整成品可能需要一周到几个月的时间。由于“响应”变量是客户规格,因此它们只能在产品已经制造完成并准备交付给客户时,在制造产品线的末端进行测试
这里的问题是,如果生产线早期的一台设备出现故障并生产出有缺陷的零件,只有在几周或几个月后我们测试这些产品的“反应”时才能发现因此,大量产品可能在流氓设备中加工,并在被检测到之前对公司的收入造成重大影响。所以很明显,这个策略是超级冒险的。
为了防止劣质设备造成巨大的收入损失,HVM 工厂在生产线的各个阶段持续测量产品的临界尺寸(CD)。然后,SPC 系统使用这些 CD 来跟踪测量值是否在 6-sigma 流程之后的可接受公差范围内运行。
最后,这个帖子的问题陈述
现在考虑下面的问题陈述:所有的 CDs 都在其指定的 6-sigma 容差范围内执行,但是响应变量有很大一部分落在客户规格之外。我们需要收紧一些 CD 中的变化,以加强响应。因此,有两个问题需要回答:
- 考虑对产品测量的所有 CDs,哪一个对响应的变化影响最大,它们的贡献是什么?
- 这些相关 CD 的变化应该收紧到什么程度,以确保响应符合客户规格?
让我们尝试使用数据分析来回答这两个问题。第一个问题将在这篇文章中回答,而第二个问题是我下一篇文章的主题:在这里保持警惕!
免责声明:本研究中使用的所有数据完全是综合生成的,以证明标准回归技术。
方法
让我们更详细地考虑第一个问题,并看看我们可以得到的数据。如下面的代码片段所示,我们的数据由 200 个特性列、一个响应列和 30K 行组成。
Dataset rows = 30000, columns = 201

df.head() shows a large number of NaN values
在我们对这些数据进行任何分析之前,让我们首先将数据帧分成训练集和测试集,这样,从训练集泄漏到测试集的信息的可能性最小。我们将“train”拆分为前 80% (24K)的行,将“test”拆分为后 20% (6K)的行,以模拟使用过去的数据进行培训,使用未来的数据进行测试。所有后续研究应在“训练”组上进行,并最终仅使用“测试”组来确认我们的模型在未知数据上的性能
X_train, y_train, X_test, y_test shapes = (24000, 200), (24000,), (6000, 200), (6000,)
反应研究:

response variable distribution
让我们先来看看我们的响应变量的分布,看看是否有什么问题首先值得解决。该响应符合良好的正态分布,约 10%的响应在规格范围之外。因此,我们生产的产品几乎有 10%都卖不出去。真是浪费!我们现在可以理解为什么高级管理层不高兴,并内化为我们需要做些什么来改善这种情况。
特征工程:
接下来,让我们更仔细地看看特性。我们的第一个观察结果是,有大量的“NaN”值表示数据集中缺少数据。我们与我们的领域工程师交谈,以了解为什么会这样。原因很简单。在制造工厂中,任何额外的测量都会占用有限的时间,而不会给产品增加任何价值。因此,生产工程师希望尽可能减少测量的产品数量。对于这种产品,数据告诉我们,平均来说,大约 80%的产品没有在每个特性上得到测量。
Mean missing = 81.39%; Min missing = 65.23% ; Max missing = 81.98%
不过没关系,我们对机器学习了如指掌,可以用插补让那些缺失的值神奇地重新出现,对吧?也许吧。也许不是。坚持这个想法,直到我们在这篇文章的后面讨论结果。让我们从使用来自sklearn的SimpleImputer类输入每一列的“平均值”开始。
# Impute missing values
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='mean')
我们的下一个观察是,每个特征似乎在一个非常不同的尺度上。为了对哪些特征对响应影响最大进行排序,我们需要将它们标准化到相同的尺度。标准化确保了在我们的分析过程中它们都被平等对待。我们将使用sklearn中的StandardScaler类来实现这一点。

X_train.describe()
# Scaling
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
建模:
向我们提出的问题陈述是,我们不仅需要解释哪些特征对反应有影响,而且我们还需要提供每个特征有多大影响的估计。由于这种可解释性要求,我们决定抛弃黑盒模型,坚持使用易于被工程团队解释的线性模型。我们将使用sklearn中的LinearRegression, LassoCV, RidgeCV and ElasticNetCV回归估计器来构建和测试最流行的线性模型。
# Linear model
from sklearn.linear_model import LinearRegression, LassoCV, RidgeCV, ElasticNetCV
alphas = np.logspace(-6, -0.1, 100)
lr_model = LinearRegression()
lass_model = LassoCV(alphas=alphas, cv=3, max_iter=10000)
rid_model = RidgeCV(alphas=alphas, cv=3)
elas_model = ElasticNetCV(alphas=alphas, cv=3, max_iter=10000, l1_ratio=0.5)
管道:
最后,为了将特征工程和建模部分联系在一起,我们使用了来自sklearn的Pipeline类。
model_pipeline = Pipeline([
('imputer', imputer),
('scaling', scaler),
(model, estimator)
])
结果

Summary of results for different linear models
对于每个估计量,我们在 10 次交叉验证(CV)分割中平均均方根误差(RMSE)和 R 平方(R2 ),以评估它们的性能。由于Lasso, Ridge and ElasticNet嵌入了alpha超参数搜索,我们还打印出每个估计量的最佳alpha。所有模型的结果都不好。均方根误差仅比响应的标准差低 0.1 左右。
现在,很容易在这一点上停下来,告诉高级管理层数据太稀疏(80%缺失)并完全放弃这个案例。但是,一个真正的数据科学家是不会这么快放弃的!我们决定进一步挖掘这些结果,看看是否还能提取一些有用的东西。毕竟,有志者事竟成!
实际与预测图

我最喜欢的可视化任何回归模型性能的方法之一是绘制实际与预测图。在这种情况下,我们立即看到有两个相关性。一些数据点落在“显著相关”线上,而许多其他数据点落在“弱相关”线上。如果我们能够消除那些落在弱相关线上的数据点,我们的性能指标应该会有很大的提高。
但是是什么导致了这种情况呢?嗯,一个很大的线索是所有这些数据点的预测值。是~22.5,也是我们实际反应数据的“均值”。如果你还记得,在这篇文章的特征工程部分,我们用每一列的“平均值”来估算所有缺失的数据。由于该数据非常稀疏,那些具有跨所有特征估算的“平均”数据的数据点将预测也接近“平均”的响应!
重要特征

Coefficients of the Lasso model: coef[coef[‘standardized_coefficient’] != 0]
在这一点上,我们可以删除所有等于“平均值”的预测,这将大大改善我们的预测。然而,为了获得最好的预测能力,我们首先研究影响反应的主要特征。由于我们将所有特征标准化为相同的尺度,因此我们可以简单地将所有特征的标准化线性系数的绝对值按降序排列。或者在 Lasso 回归的情况下,打印所有非零标准化系数。在数据集中的 200 个要素中,有五个要素与 Lasso 模型的响应变量最相关。有了这些信息,我们现在可以只删除 Lasso 模型用来防止插补噪声的这五个特征中包含插补值的行。
在测试集上检查性能
最后,我们在测试集上通过计算 RMSE、R2 和绘制实际与预测图来测试模型。回想一下,我们已经删除了在与回答相关的五个特征中的任何一个特征中具有估算数据的行。如您所见,一旦在预测过程中移除估算值,该模型就具有非常强的预测能力!这表明,在进行预测时,我们必须限制自己只预测那些包含所有 5 个重要特性的数据的行。

Actual vs Predicted plot on Test dataset after removing rows that have imputed data in any of the 5 important features
有了这种认识,我们就可以影响负责选择测量采样方式的工程团队。例如,由于每个特征是在 20%的行上测量的,工程团队可以实施一种抽样策略,以确保这些测量值的一半(10%)是在所有 5 个特征上测量的,而另一半(10%)保持随机。了解您的客户并利用数据影响他们的决策是任何数据专业人员的重要技能!
结论
在本帖中,我们看到了一个估算可能导致错误结论的实际例子,我们试图回答这个问题:考虑对产品测量的所有 CDs,哪个对响应的变化影响最大,它们的贡献是什么。然而,更深入的挖掘可以揭示一个有用的模型和额外的见解,可以用来影响客户行为。在我的下一篇文章中,我们将看到如何使用这个模型来回答第二个问题:相关 CDs 的变化应该收紧多少,以确保响应符合客户规格。这篇文章的所有代码都可以在这里找到:链接
让人工智能发挥作用——让计算机像计算机一样思考
人工智能研究人员渴望复制人类思维。但我们已经看到,人工智能的真正关键是让机器以自己的方式超越他人。
由(www.percepto.co)Percepto的首席技术官 Sagi Blonder 提供
人工智能(AI)这个词在今天的科技(和日常生活)世界中是不可避免的。高端、最先进的人工智能应用确实正在改变企业分析数据的方式,或者工业产品的设计和生产方式。
也就是说,什么是人工智能,什么不是人工智能可能会令人困惑。对人工智能应该如何工作的根本误解可能会阻碍真正自主机器的进展。原因?我们需要学会区分人工智能和人工智能,前者依靠人类来准确定义机器应该如何学习,后者由人类向机器提出问题,然后让机器根据自己的经验和能力来解决这个问题。
例如,让谷歌助手开玩笑或帮助 Spotify 和网飞学习你喜欢和不喜欢什么的人工智能就是前者的一个例子。这是机器学习,人工智能的一个分支,但本质上是一种超级聪明的方法,让机器编程来执行任务。
人类驱动的人工智能的另一个例子是神经网络——其操作模仿人脑。这些技术正被用来创造惊人的专家机器,这些机器被训练来完成一项单一的任务,并且成功的水平不断提高。例如,最近的一项研究显示,一种基于神经网络的算法在脑部 CT 图像中对颅内出血进行分类的成功率相当于一名四年的放射科住院医师。这些解决方案非常可靠,FDA 已经批准使用图像分析算法来帮助诊断,甚至自动确定病人护理的优先顺序。
然而,这些机器仍然按照我们教它们的方式做我们教它们做的事情。
这就是问题的要点。因为把一个能产生艺术的机器和一个有创造力的机器,或者一个知道因果的机器和一个有常识的机器混为一谈是很危险的。只有当我们让机器像机器一样思考,而不是像制造它们的人一样思考,真正的机器自主才能实现。
这看起来怎么样?
举个最近的例子,想想谷歌子公司 DeepMind 开发的国际象棋算法 AlphaZero 。为了探索国际象棋本身的复杂性,AlphaZero 开发了罕见的棋步——以一种完全独特的风格下棋,并持续获胜。AlphaZero 的兄弟 AlphaGo 掌握了古老而复杂得可笑的围棋——采用了一种独创的策略和看不见的战术,让世界知名的大师们瞠目结舌(并一直被打败)。
在更实际的层面上,自动驾驶汽车的出现提出了有趣的人工智能挑战。考虑“驾驶员直觉”的问题。有经验的人类司机通常能够预测汽车何时要变道,即使在转向灯激活之前。我们人类能够利用我们的经验来直觉行为,这些行为可能在物理上并不明显。我们是如此无意识地这样做,以至于我们中的许多人无法用语言准确地表达我们是如何知道我们所知道的——我们只是知道而已。
这种直觉——可以说对安全驾驶和其他危险的现实世界任务至关重要——可以被分解并教给机器吗?可以用来历不明的信息注释一个图像吗?解决这个问题的一个常见方法是使用强化学习——通过改进自己的技术来训练机器达到某个目标,而不是通过从其他人那里学习样本。然而,通过强化的方式训练自动驾驶汽车也有其自身的挑战。一个是模拟质量的内在限制,因为我们无法真正让自动驾驶汽车在真实的道路上学习如何驾驶。给汽车的感官数据加上标签,描述道路上还没有发生的事情,又怎么样呢?我们如何标记无关的数据——例如,传感器看不到的汽车,隐藏在卡车后面或框架外的汽车。而没有这个出发点,机器又怎么能学会寻找汽车存在的暗示呢?
简单的答案是我们无法教会一台机器 直觉。我们可能永远也不会制造出像人类一样思考的机器,这也不是我们必须追求的目标。在实验室和现实世界中已经证明了自己的是,让机器以它能理解的方式理解给定的任务——让机器利用它们的优势来补偿不是人类。
例如,一项新的研究表明,一台经过训练的细胞分类机器学会了在不添加荧光标签的情况下做到这一点,荧光标签用于使细胞特征对人眼来说显而易见。通过在添加侵入材料之前拍摄细胞图像,并用后验知识进行标记,机器找到了一种检测人类无法检测到的东西的方法。澄清一下,没人教机器怎么做这个。它看着数据和自己的能力,无视建造它的人类的限制,独自解决问题。
底线
当我们放下我们狭隘的学习和理解概念,接受不同的有机体有不同的运作方式时,真正的自主机器就能实现。鉴于今天的技术限制(仍然有很多),当我们放弃生产像人一样思考的机器的目标,让机器成为机器时,我们将在机器自主方面取得更有效的结果。
识别野外家庭(RFIW):大数据挑战
野外家庭的视觉识别
前方的路(第一部或多部)

Training machinery to identify relatives using visual cues like imagery, videos, and such.
相关链接
- 2020 识别野外家庭 (RFIW) w 工作坊网页
- RFIW-2019 、 RFIW-2018 、 RFIW-2017 挑战赛网站
- 野生家庭项目页面
- 亲属关系验证:Python 熊猫教程(第二部分)
概述
我的博士研究涉及亲属识别和 FIW 数据集。在不久的将来,我们的目标是总结关键发现,同时在每年举行的顶级会议上提供数据挑战的经验教训和演示(即,这是未来的第一次)。概观
我的博士研究涉及亲属识别和 FIW 数据集。在不久的将来,我们的目标是总结关键发现,同时在每年举行的顶级会议上提供数据挑战的经验教训和演示(即,这是未来的第一次)。
要了解更多关于 FIW 的信息,请访问项目页面。要了解更多信息、注册并参与即将到来的 RFIW 2020,请访问研讨会页面。
通过图像自动识别血亲(即亲属关系)的能力在大量应用中具有前景。仅举几个例子:法医(例如,人类追踪、失踪儿童、犯罪现场调查)、边境控制和安全、流离失所的难民家庭、历史和家谱血统研究、社交媒体、预测建模,以及减少面部识别的搜索空间。
在微笑实验室,我们是这个问题的最初开拓者之一【7-10】。2011 年,我们为基于亲属的视觉任务铺平了道路,这是一个最初的公共数据集, UB KinFace 数据库。尽管如此,几年后,我们用第一个用于亲属识别的大规模图像数据库,即野生家庭 (FIW)数据库[4,6],推动了“深度学习”的热潮。FIW 为 1,000 个家庭提供图像,平均每个家庭有 5.6 个成员和 13.7 张家庭照片;每个家庭都有完整的标签,包括所有成员的姓名、性别和关系——FIW 从这些丰富的标签信息中服务于多任务目的[2]。
我们发起了第一次大规模的亲属识别数据挑战,识别野外家庭 (RFIW) [4]。我们在 2017 年(即 RFIW'17 )开始举办数据挑战研讨会,与 ACM 多媒体的会议同时举行。在第一次 RFIW 成功后,101 个团队在两个任务之间注册(即亲属关系验证和家庭分类),七篇论文在2017 RFIW 会议录中被接受并在研讨会上发表。为此,我们也很荣幸地邀请到了这样一位杰出的主题演讲人:DHS 的 Chris Myles 和 Salesforce 的研究员 Xiong。
自此,RFIW 转型为一个系列赛,在 2018 和 2019 举办的挑战赛为 IEEE FG 挑战赛【3】。在我们的开源报告中,公众可以获得作为基准记录并作为最先进技术发布的协议、实验和模型。要深入了解 FIW 数据,请参见我们的 PAMI [2]。
几个出版物被引用了 500 次,两个数据集,研讨会,挑战和最近的 Kaggle 竞赛,我们预计这一势头只会从这里开始——研究人员被吸引到 RFIW,这已经形成了一个年度挑战。此外,FIW 作为一个整体,吸引了专家,新的博士,甚至其他领域的专业人士。此外,FIW 的数据在实际应用中有很多方法,比如给父母一对面孔,预测孩子的外貌[1]。
毫无疑问,这个问题现在需要从研究转向现实的资源关注。
文献学
[1]·高,·夏,约瑟夫·P·鲁宾逊,·张,,,和云复.“你的孩子会是什么样子?DNA-Net:年龄和性别意识的亲属脸合成器 arXiv 预印本 arXiv:1911.07014 (2019)。[ 纸张
[2]约瑟夫·罗宾逊、邵明、刘洪福、吴越、蒂莫西·吉利斯和傅云。《野外家庭的视觉亲属识别》IEEE TPAMI 特别版:计算脸(2018)。[ 论文
[3],,丁,,约瑟夫·P·鲁宾逊,和傅云。通过潜在自适应子空间进行亲属分类,,在第十三届 IEEE 国际会议上,自动人脸&手势识别(FG 2018)。IEEE。论文
[4]约瑟夫·P·罗宾逊,,,,赵,,蒂莫西·吉利斯,傅云.识别野外家庭(RFIW):结合 ACM MM 2017 举办的数据挑战研讨会,载于ACM 多媒体会议:2017 年识别野外家庭研讨会会议录,第 5-12 页。ACM。【论文、论文集、内容
[5]王淑洋、约瑟夫·罗宾逊和傅云。“利用边缘化去噪度量学习对野外家庭进行亲属关系验证”,第 12 届 IEEE 自动人脸和手势识别国际会议(FG 2017)。第 216–221 页。IEEE。[ 纸张
[6] Joseph Robinson,,,,和 Yun Fu,野外家庭(FIW):大规模亲属图像数据库和基准,,载于 2016 年 ACM 多媒体会议论文集(第 242-246 页)。ACM。
[7]夏,,罗杰波,傅云,在一张照片中了解亲属关系,载于 IEEE 多媒体汇刊(T-MM),第 14 卷,第 4 期,第 1046–1056 页。IEEE,2012 年。
[8]夏,,傅云,利用视觉属性进行亲属关系验证,载于模式识别(ICPR),2012 年第 21 届国际学术会议上(第 549–552 页)。IEEE。
[9]夏,,傅云,通过迁移学习进行亲属关系验证,人工智能国际联合会议论文集。第 22 卷。№3.2011.
[10],,夏,云复,基于 UB KinFace 数据库的系谱人脸识别,计算机视觉与模式识别研讨会(CVPRW),2011 年 IEEE 计算机学会会议上。IEEE,2011 年。
公差叠加
以及如何使用蒙特卡罗模拟来代替
什么是公差叠加?

想象你有两个圆盘,你想把它们紧紧地放在一个开口里。如果你只需要将这三个部分装配在一起一次,你可以测量一下这些圆盘有多高,然后按照这个尺寸裁剪,调整到完美为止。如果你试图将这三个部分组合在一起很多次,那么事情就变得不确定了。你的一些冰球可能比你的开放和不适合。你的一些冰球堆可能比开口小得多,你的零件会比你想要的更松。

你可以把你的黄色冰球设计成 30 毫米高,但是冰球的尺寸更可能在 29 到 31 毫米之间。在这种情况下,黄色圆盘的高度公差为 1 毫米。
你可以测量每一个部分,将较大的黄色圆盘和较小的红色圆盘配对,强迫所有东西都工作。(这个过程被称为宁滨)。这确实有效,但是测量零件需要时间。俗话说,时间=金钱。顺便说一句,时间也等于时间。所以如果你想减肥,你需要愿意花很多时间和金钱去减肥。
这就是公差叠加的用武之地。当您有想要放入开口中的零件时,公差叠加是一种工具,允许您确定您的零件是否总是放入开口中,即使您正在制造成千上万个这样的组件。
公差叠加是一种创建循环的方法,该循环包括“堆栈”中的每个关键尺寸它使您能够查看这些值的尺寸和公差,以确定您的设计是否会相应地工作和更新。它通常看起来像这样:

那么,为什么不使用容错堆栈呢?
在类似上面例子的情况下,公差叠加很容易组合在一起,它给了你创建一个好的设计所需要的所有信息。如果出现以下情况,公差叠加就不再那么有用:
- 在你的层叠中你有更多的维度
- 您看到的是圆形零件的公差及其径向配合。
- 你已经知道你的零件的分布情况
每一种情况都需要蒙特卡洛模拟。

FUN FACT: Monte Carlo simulations are named after the location because it is a gambling hot spot.
如何使用蒙特卡洛模拟来代替公差叠加?
在蒙特卡洛模拟中,您可以为包含在公差叠加中的每个尺寸生成真实值。一旦生成了这些值,就可以通过相同的循环来加减值,从而生成临界尺寸的分布(在我们的示例中,是从 4 到 1 的差距)。最后,你要设定一个预期的 yield⁴,看看你的产量的临界尺寸是多少。这可能会告诉你,你可以让你的设计差距变小,或者你需要让它变大。这种分布可能会告诉你,宁滨有很强的优势。

First three histograms show simulations based on the expected tolerances of the parts. Last histogram shows the expected resultant gaps. Green lines show ± 3 sigma from the mean.
请注意,零件遵循公差叠加中预期的零件规格。然而,最终的间隙分布得足够紧密,使得间隙上的公差比来自公差叠加的 RSS 值更紧密。
为了让事情更有趣,我们来看一个放射状的例子。
想象一下,你正在将一个塑料钉安装到一个金属开口中,如左图所示。这种联系汇率制度对 it⁵.有决定性的影响你想让顶部塑料部分和顶部金属部分之间的间隙在四周尽可能的小,而不要撞到它。

看起来很简单,对吧?可惜不是。如果一切都是完美的圆形,这将工作得很好。但是,如果您考虑下面画出的场景,您会发现公差叠加缺少一些信息。这些图像是对现实场景的夸大。

蒙特卡洛模拟允许您模拟每个零件偏离中心的径向角度和每个零件离圆角最远的径向角度。通过模拟您的结果,您可以考虑偏心特征同时导致零件配合的次数,以及它们同时导致零件干涉的次数。这通常会导致比公差叠加更紧密、更真实的合成公差。这是因为公差叠加迫使你假设问题维度都处于相同的径向角度,而实际上,它们几乎肯定不是。

我已经将用于生成此模拟的代码粘贴在下面:
# importing libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt%matplotlib inline # Generating part measurement data
df['purple_r'] = np.random.normal(15.05, .1, 1000)
df['purple_off_center'] = np.random.normal(0, .02, 1000)
df['angle_purple_off_center'] = np.random.uniform(0, 6.283185, 1000)
df['grey_off_center'] = np.random.normal(0, .02, 1000)
df['grey_r'] = np.random.normal(15.5, .03, 1000)
df['angle_grey_off_center'] = np.random.uniform(0, 6.283185, 1000) # Generating assembly measurement data
# Using df['angle_purple off center'] as direction of gap
df['Circularity Contribution Purple'] = df['purple_r']
df['Concentricity Contribution Purple'] = df['purple_off_center']df['Circularity Contribution Grey'] = df['grey_r']
df['Concentricity Contribution Purple'] = df['grey_off_center'] * \
np.cos(df['angle_purple_off_center']-df['angle_grey_off_center'])df['gap'] = np.abs(df['Circularity Contribution Purple']) + \
df['Concentricity Contribution Purple'] - np.abs(df['Circularity Contribution Grey']) \
- df['Concentricity Contribution Purple']# Part measurement data graphfig, ax = plt.subplots(2, ncols=3, figsize = (14, 8))
ax = ax.ravel()
ax[0].hist(df['purple_r'], bins =20, color='purple')
ax[0].set_title('Distribution of \n- Purple Large Radius')
ax[0].set_xlabel('mm')
ax[1].hist(df['purple_off_center'], bins =20, color='purple')
ax[1].set_title('Distribution of Concentricity\nof Features on Purple Part')
ax[1].set_xlabel('mm')
ax[2].hist(df['angle_purple_off_center'], bins =20, color='violet')
ax[2].set_title('Distribution of Angle of\n Off Center for Purple Part')
ax[2].set_xlabel('radians')
ax[3].hist(df['grey_off_center'], bins =20, color='dimgray')
ax[3].set_title('Distribution of Concentricity\nof Features on Grey Part')
ax[3].set_xlabel('mm')
ax[4].hist(df['angle_grey_off_center'], bins =20, color='lightgray')
ax[4].set_title('Distribution of Angle of\n Off Center for Gray Part')
ax[4].set_xlabel('radians')
ax[5].hist(df['grey_r'], bins =20, color='dimgray')
ax[5].set_title('Distribution of \n - Grey Large Radius')
ax[5].set_xlabel('mm')
plt.tight_layout(); # Assembly measurement data graph
fig, ax = plt.subplots(1, ncols=4, figsize = (14, 4))
ax = ax.ravel()
ax[0].hist(df['Circularity Contribution Purple'], bins =20, color='purple')
ax[0].set_title('Circularity Contribution Distribution \n Purple Outer Radius')
ax[1].hist(df['Concentricity Contribution Purple'], bins =20, color='violet')
ax[1].set_title('Concentricty Contribution Distribution \n Purple Radii Relative to Each Other')
ax[2].hist(df['Circularity Contribution Grey'], bins =20, color='dimgray')
ax[2].set_title('Circularity Contribution Distribution \n Grey Outer Radius')
ax[3].hist(df['Concentricity Contribution Purple'], bins =20, color='lightgray')
ax[3].set_title('Concentricty Contribution Distribution \n Purple Radii Relative to Each Other')
plt.tight_layout();# Final Gap Graph
mu = df['gap'].mean()
sigma = df['gap'].std()plt.hist(df['gap'], bins =20, color='black')
plt.title('Resultant Gap Distributions', fontsize = 16)
plt.axvline((mu-(3*sigma)), color='green', alpha=0.5)
plt.axvline((mu+(3*sigma)), color='green', alpha=0.5)
plt.axvline((mu+(3*sigma)), color='green', alpha=0.5)
plt.xlabel("Gap (mm)")
plt.ylabel("Assembly Count")
plt.tight_layout();
[1]公差通过多种方式确定。设计工程师将在零件图中规定每个关键尺寸的公差。该公差通常是基于该制造方法的零件公差的最佳实践以及来自制造零件的供应商的反馈而创建的。如果公差叠加表明它需要比最佳实践更严格,在许多情况下也可以这样做,但会增加零件的成本。
[2]我说的总是,是指几乎总是。离群值总是会发生。零件将超出规格。你甚至可能愿意在知道你会扔掉零件的情况下进行设计。对于这个博客来说,“总是”实际上意味着“你想要多少就有多少。”
[3]如果这是在数据可用之前完成的,那么你可以根据给定的制造过程和质量,根据你对这些数据的期望来生成值。如果您已经在制造零件,您可以使用每个工具的平均值和标准偏差来生成数据。
[4]如果你以前听说过“六个适马”这个词,并想知道它是什么意思,那么你从杰克·多纳吉那里听到的都不是真的。它指的是设定您的收益率,使 3 个标准差(六西格玛)符合规格(即您的收益率为 99.99966%)

[5]挤压肋是包含在较软零件中的小肋,当它被推入较硬零件时会被挤压。除非硬零件的圆度或小零件中的挤压肋有重大问题,否则这往往会创建一个足够接近挤压特征中心的配合,您可以假定配合的公差为零。
太多颠倒的照片?花 20 分钟,用 AI 来翻它们。

当你花了两个小时扫描照片,却突然发现你已经把一些随机的照片上下颠倒了,这真是太棒了。与其痛苦地浏览每一个并翻动它们,你可能会觉得你宁愿跳到一辆卡车前面。嗯,当一个客户带着类似的问题来找我们时,我立即想知道机器学习是否能够有所帮助。你猜怎么着?确实如此。结束了。
如果你有兴趣知道我是如何在 20 分钟内做到的,那么请继续阅读。
有时候,机器学习可能更多地是一门艺术而不是科学,即使它在技术上是一门科学。也许科学就是艺术?一个稍后讨论的无聊话题,更有趣的是我在这里提出它的原因。
每当我被问到“我们可以用机器学习来解决这个问题吗?”我的回答永远是“不知道— 我们试试看”。
实验对于成功使用机器学习至关重要。如果你花了 6 个月的时间为一个特定的用例建立一个模型,你可能会发现为时已晚,它并不真的工作得很好。相反,我喜欢寻找快速测试的方法,看看使用机器学习来解决问题是否有一些可行性。
所以,回到正面朝下的照片。这个特殊的用例是关于有时上下颠倒的人的照片。大多数面部识别工具在面部上下颠倒时都会有困难,所以我们至少需要在将其提交给面部识别功能之前将其翻转为正面朝上。
所以我想,让我们试着训练一个图像分类器,看看我们能否检测出一张照片是不是上下颠倒的。请注意,这是在研究了检查 EXIF 元数据以查看其中是否有关于旋转的信息的可能性之后;没有。
我做的第一件事是搜寻训练数据。我去谷歌图片搜索‘脸’。我下载了尽可能多的图片(大约 346 张),并创建了一组正面朝上的图片。然后,我尝试用谷歌图片搜索“颠倒的脸”——这是一个错误,原因有很多很多。最相关的原因是因为我想做的是训练分类器来检测两个可能相同的东西之间的差异,所以我选择翻转所有正面朝上的照片,这样我就有了一个颠倒的副本。我知道如何大规模实现这一点的唯一方法是使用苹果的 Automator。
设置您的工作流程,使“获取指定的 Finder 项目”指向“面孔”文件夹,链接到“获取文件夹内容”,链接到“拷贝 Finder 项目”并创建新文件夹,然后将“旋转图像”设置为 180 度。
我运行了这个工作流程,最终得到了相同数量的颠倒的面。然后,我去了我们的一个开源项目 imgclass ,下载了命令行工具,安装了分类框,开始了培训工作。
“该死”当我看着 imgclass 输出的结果精度时,我喊道。只有 34%。不够好。我需要更多的训练数据。所以我想,哪里可以找到更多的面孔?没错,野外贴标签的脸!
野生环境中的标签人脸拥有 13234 张独特的人脸图片。我很快下载了它,运行 bash 命令将所有照片从它们的嵌套目录中移除,并将其展平到一个文件夹中,然后在这个文件夹上再次运行 automator 工作流以创建颠倒的类,并在新的数据集上启动 imgclass。

在我的 Mac 电脑上用这么多照片训练 Classificationbox 花了大约 1 小时 45 分钟,所以从技术上讲,整个过程花了 20 多分钟,但我自己只花了大约 20 分钟。
一旦完成,我对 imgclass 报告的新的准确数字感到自豪。99.97%
果酱!
现在,我有了一个有效的模型来检测面部照片何时颠倒,我可以在工作流程中使用它来校正无数的图像。如果你真的对使用这个感兴趣,我会为你节省 20 分钟+~ 2 小时的处理时间,并在这里给你一个模型的链接。
将该状态文件加载到 Classificationbox 中,就可以开始检测颠倒的人脸了。
不客气。
过于强大的自然语言处理模型(GPT-2)
什么是生成性预训练

Photo by Edward Ma on Unsplash
OpenAI 发布了生成式预训练模型 (GPT),该模型在 2018 年的许多 NLP 任务中取得了最先进的结果。GPT 利用 transformer 来执行无监督学习和有监督学习,以学习 NLP 下游任务的文本表示。
为了展示这种模式的成功,OpenAI 对其进行了增强,并于 2019 年 2 月发布了一款 GPT-2。GPT-2 被训练为基于 40GB 文本预测下一个单词。与其他模型和实践不同,OpenAI 没有发布完整版本的模型,而是发布了一个轻量级版本。他们在自己的博客中提到了这件事:
由于我们担心该技术的恶意应用,我们不会发布经过训练的模型。作为负责任披露的一项实验,我们发布了一个小得多的模型供研究人员进行实验,以及一篇技术论文。
由于这个原因,它制造了许多关于没有最新型号和源代码可供公众使用的噪音。应该研究开放模型和源代码吗?OpenAI 确实引发了很多讨论,但似乎大多数反馈都是负面的。忽略它是否应该开放,这个故事将讨论关于语言模型是无监督的多任务学习者(拉德福德等人,2019),并将涵盖以下内容:
- 数据
- 体系结构
- 实验
- 经验
数据
资料组

Reddit Logo
OpenAI 没有使用现有的数据集,而是选择建立一个新的强调文档质量的网络抓取工具。所有文字来自出站克林从 Reddit 职位和职位必须被评为至少 3 因果报应。换句话说,它是由人类确认的有趣的、有教育意义的或有意义的事情。
数据预处理
不需要预处理步骤。换句话说,小写、标记化和其他步骤被跳过,因为作者认为这些预处理步骤限制了模型的能力,并且它能够评估所有语言模型基准。
GPT 2 号的建筑
输入表示
文本表示法是一种很好的表示方法,一个词在神经网络中无疑是真实的。然而,拉德福德等人既不适用字级也不适用字级。他们选择中间的一个子词。子字可以通过字节对编码(BPE)算法获得。
【BPE】字节对编码
BPE 本来就是压缩的方式。将使用以下算法计算子字列表。
- 将单词拆分成字符序列。
- 加入最高频率模式
- 继续执行上一步,直到达到预定义的最大迭代子词数。
以“低:5”、“低:2”、“最新:6”和“最宽:3”为例,在每次迭代中提取最高频率的子字:
- 9 个频率的“es”
- 9 个频率的“est”
- 等等

Algorithm of BPE (Sennrich et al., 2015)
网络体系结构
同 GPT ,GPT-2 利用变压器模型。而 GPT 和 GPT-2 的区别在于:
- 将归一化层移动到每个子块的输入端
- 在最终自我关注模型后添加标准化层

Architecture of GPT (Radford et al., 2018)
为了适应不同场景,训练了具有不同参数的 4 个模型

Architecture Hyperparameters (Radford et al., 2019)
模特培训
GPT-2 使用无监督学习方法来训练语言模型。不同于其他模型,如 ELMo 和 BERT 需要两个阶段的培训,即预培训和微调阶段。GPT-2 没有微调阶段。
没有 GPT-2 的定制培训。OpenAI 不发布训练 GPT-2 的源代码(截至 2019 年 2 月 15 日)。因此,我们只能将训练好的模型用于研究或采用。同时,唯一发布的训练模型是最小的模型,有 117 个参数。要下载这个模型,你可以按照 GPT-2 Github 中的说明进行。
实验
拉德福德等人证明了最大的模型(即 1542M 参数)达到了 8 个最先进的结果,而最小的模型达到了 4 个最先进的结果。

Result of 4 models in different dataset (Radford et al., 2019)
经验
很容易尝试 GPT-2 小型模型。你只需要遵循来自 GPT-2 Github 的简单指令。下载源代码和模型并安装库后,可以使用unconditional sample generation或conditional sample generation生成文本。
无条件样本生成
第一种模式是Unconditional Sample Generation。它意味着无条件地生成文本。
python src/generate_unconditional_samples.py
过一会儿,会生成一些文本,这里是一个例子:
Most people think that when a warship runs aground it doesn't just kill people and then sink or burn all of society. That would make L.S. Kaminsky blush. Yet Kaminsky is doing one thing right: the CREAPH presidency. Whoever he is that fired the salt gun after getting thrown out of the Senate tossup race here in Richmond, he runs the "war," real, that is, guys like Alvin Dream, Dennis Hastert and Vijay Swarup. Given that Ed Gillespie, the GOP nominee barely a month into the campaign, on May 2 earned 45 points from the Tea Partiers, secessionists and nativities, right much everyone under 30 has been cheering the idea of "the war." Elliot Abrams, one of the Campus Reform editorial staff writers, also called the "war" mundane in the broadest terms. "Oh, well with them suiting it up voting be vigilant. And that produces 14 Rand Paul a grand total of 50 but Johnson 53\. Two just finished with a 45 for Johnson 46\. 'Well I hope it keeps getting led!' No, it's to save your mates from gun sin," wrote James Hernandez in New York to figure out what was going on. Ditto Bob Corker, who greeted the notion this far by saying it was "a dip in accuracy." As for the Rand Paul and Marco Rubio brilliant running mates like Thad Execury (FML) — who are now both running for president estranged from their father, John Doe III, and miscarried by accident — it's just another rebel outside cover.
您也可以通过更改默认配置来生成文本。温度是随机化的水平。较低的值很有可能从 WebText 的测试集中输出数据。
python src/generate_unconditional_samples.py --top_k 1 --temperature 0.1
输出可以是:
The first time I saw the new version of the game, I was so excited. I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game, I was so excited to see the new version of the game,
条件样本生成
在无条件文本生成之后,我们将尝试有条件文本生成。
python src/interactive_conditional_samples.py --top_k 40
让我们试试香港乐队(法玛)的一首歌词

Reply of “I go to school by bus”
让我们试试来自爱莉安娜·格兰德的 7 枚戒指:

Reply of “Yeah, breakfast at Tiffany’s and bottles of bubbles.”
拿走
- 使用子词(BPE)而不是使用字符和单词嵌入。也许单词嵌入的层次太高,而纯字符嵌入的层次太低。BPE 包括字符级、子词级和词级嵌入。
- 数据很重要,但标记数据的成本很高。拉德福德等人使用高质量的数据进行无监督学习,这样他们可以避免有限的标记数据问题。如前所述,至少选择 3 个因果报应数据。换句话说,这是一种人群过滤。
- 通过对预先训练好的模型进行多次尝试,得到了令人印象深刻的结果。这是 OpenAI 不公开发布所有内容的原因吗?不知道,但有一点是肯定的,这是一个非常好的营销,OpenAI 忽略了许多负面反馈。期待最大的模型和源代码。
关于我
我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。你可以通过媒体博客、 LinkedIn 或 Github 联系我。
延伸阅读
参考
- A.、吴、蔡尔德、栾、阿莫代和苏茨基弗。语言模型是无人监督的多任务学习者。2019
- A.拉德福德、K. Narasimhan、T. Salimans 和 I. Sutskever。通过生成性预训练提高语言理解。2018
- R.森里奇 b .哈多和 a .伯奇。具有子词单元的生僻字的神经机器翻译。2015
对任何机器学习项目至关重要的工具/技巧

from pixabay here
这是系列“如何利用 LSTM 预测股价”的最后一篇帖子。在上一篇文章中,我们已经看到了如何微调神经网络的超参数。在这篇文章中,我将提到一些对于任何 ML 项目来说都是常见和不可或缺的组件,但是它们经常被忽略(甚至我最初也是这样做的)。
记录
在早期阶段,这似乎是一种开销,但是我们不能夸大日志在调试任何应用程序中的作用。python 中的日志很简单,但是我们必须做一些初始化来使它更有效。以下是我所做的。
这段代码带有注释,非常容易理解。您也可以添加其他处理程序。一旦您设置了日志程序,实际的日志记录就很简单了:
logging.debug("Train--Test size {} {}".**format**(**len**(df_train), **len**(df_test)))
当您有一个 bug,但不知道它来自哪里时,日志可以证明是一个分析残骸的黑盒。
形象化
视觉化是另一个有时被忽视的领域。绘制训练误差与验证误差以及预测与真实数据的关系图对于理解正在发生的事情是绝对必要的,尤其是在涉及如此多参数的神经网络中。为了绘制误差图,我们需要存储所有时期的所有误差。它真的有助于识别过度拟合/欠拟合。使用 Keras 非常简单:

同样,您可以绘制预测值与实际值的对比图,以寻找任何异常。我给你举个例子。对于这个项目,在最初的试验中,我只关注最初的预测值,它们总是不太好。但当我开始绘制整个预测时,我意识到由于某种原因,该模型仅在测试数据的初始部分做得不太好。但是时间线的其他部分都很好。见下文。

To realise that model performance over the complete test set is not so bad, we need bigger picture
虽然我很确定这可以通过更多的调整得到进一步的改善。
释放 Keras
虽然我在这里使用 Keras 作为例子,但是在您熟悉的任何其他工具中也应该有类似的工具。
- CSVLogger :顾名思义,它可以用来在每个时期结束时记录各种变量。默认情况下,它存储纪元编号、列车丢失和验证丢失。但是也可以存储你自己的变量。本节末尾包含所有要点的示例代码。
- 提前停止:如果 Keras 检测到长时间没有改善,用于停止训练。有各种属性来定义系统何时应该停止,如“耐心”,它说明在宣布模型没有改善之前,Keras 应该允许运行多少个时期。类似地,“min_delta”是另一个有用的参数。可以想象,这些参数会因不同的问题而有所不同。例如,你必须监控你的验证损失随着时代的变化有多少(这也取决于你的学习速度)。这就是日志记录派上用场的地方。你可能会想,我的训练每一个时期需要 10 秒钟,如果我的训练不提前停止,再多跑 30 个时期,对我来说没问题;我可以抽出 5 分钟,或者我会手动停止。但是回想一下以前的文章,我们使用了各种自动化超参数调优工具和网格搜索。你不能控制每一次迭代。如果你要检查 50 个组合,并且每个组合节省了 5 分钟(这实际上比那个多得多,因为可能有许多组合只是坏)那么你就节省了 250 分钟!但是不要为“耐心”使用太小的值否则系统会过早停止,即使它可以在更多的时期后得到改善。
- ModelCheckpoint :如果‘save _ best _ only’为真,则该回调在每个时期后保存训练好的模型,或者只保存所有时期中最好的一个。同样,这在自动化大量参数组合搜索时非常方便。
以结构化的方式保存所有数据,以便以后分析
就像一般生活一样,在机器学习中,我们可以从回顾中学到很多东西。做得不太好的训练(有一些超参数组合)也能给出一些有价值的见解。例如,让我们假设您正在调整辍学率或学习率。如果您已经保存了以前训练的所有数据,那么您可以比较在 150 个纪元时的训练损失,从而决定模型是否学习得更快。或者你甚至会发现一些有趣的东西,可以应用到你的下一个项目中。
对于这个项目,我将每次更改/尝试的结果存储在一个文件夹结构中,如下所示:
我想以此结束这篇文章和我的博客系列。我希望我能对所有的 ML 粉丝有所帮助。
因为我是从预测 ML 公司的股票价格开始这个系列的,所以在结束之前我想说几句。虽然我们发现我们可以预测未来的价格有一定的准确性,但它仍然不适合捕捉特殊情况(基于其他市场因素的突然价格变化)。这里的目的不是完全解决问题(尽管如果我们找到一种方法将其他因素整合到我们的问题陈述中,我们可以做到),而是意识到,我们可以用机器学习,坐在家里,用我们平庸的笔记本电脑做什么。这就是机器学习的力量。
继续编码。
10 大人工智能新闻:11 月回顾
今年 11 月,人工智能世界发生了什么
- 澳大利亚开始在交通摄像头上使用计算机视觉来检测人们在开车时使用手机的情况。
- 英国批准了一项动议,对无法解释人工智能如何影响其决策的公司进行罚款。这预计将于 2020 年生效。
- 著名围棋冠军李世石(Lee Se-dol)退出,并称 AI 是“无法被打败的实体”。
- 反对人类的卡片现在正在使用人工智能来编写他们的卡片,这可能为如何用人工智能取代创造性工作的人开创了一个先例。
- 现在,胎盘正在用计算机视觉进行分析,以改善对母亲和新生儿的临床护理。开发者的目标是通过在智能手机上部署他们的软件来实现这一实践。
- 脸书发布了一种类似人类的“外围视觉”GAN,称为 DeepFovea,能够重建只有 10%像素的图像。
- IBM 与 Unitary Fund 合作,鼓励与量子计算相关的开源项目。
- 苹果发布了一篇论文,其中他们表明智能手机的使用可以用来预测认知障碍。
- Python 3.8 现已推出。
- Lyft 以开源方式发布了它的 ML 平台 Flyte。

数据科学家犯的 10 大编码错误

数据科学家是“比任何软件工程师更擅长统计,比任何统计学家更擅长软件工程的人”。许多数据科学家有统计学背景,但对软件工程几乎没有经验。我是一名高级数据科学家,在 python 编码的 Stackoverflow 上排名前 1%,与许多(初级)数据科学家一起工作。以下是我经常看到的 10 个常见错误。
1.不要共享代码中引用的数据
数据科学需要代码和数据。因此,为了让其他人能够复制你的结果,他们需要能够访问这些数据。看起来很简单,但是很多人忘记了与他们的代码共享数据。
import pandas as pd
df1 = pd.read_csv('file-i-dont-have.csv') # fails
do_stuff(df)
解决方案:使用 d6tpipe 与您的代码共享数据文件,或者上传到 S3/web/google drive 等,或者保存到一个数据库中,以便接收方可以检索文件(但不要将它们添加到 git 中,见下文)。
2.硬编码不可访问的路径
类似于错误 1,如果你硬编码了其他人不能访问的路径,他们就不能运行你的代码,并且不得不寻找很多地方来手动改变路径。Booo!
import pandas as pd
df = pd.read_csv('/path/i-dont/have/data.csv') # fails
do_stuff(df)# or
impor os
os.chdir('c:\\Users\\yourname\\desktop\\python') # fails
解决方案:使用相对路径、全局路径配置变量或 d6tpipe 来使你的数据易于访问。
3.将数据与代码混合
既然数据科学代码需要数据,为什么不把它转储到同一个目录中呢?当你这么做的时候,把图片、报告和其他垃圾也保存在那里。呀,真是一团糟!
├── data.csv
├── ingest.py
├── other-data.csv
├── output.png
├── report.html
└── run.py
解决方案:将你的目录分类,比如数据、报告、代码等等。参见 Cookiecutter Data Science 或 d6tflow 项目模板并使用#1 中提到的工具来存储和共享数据。
4.Git 用源代码提交数据
大多数人现在控制他们代码的版本(如果你不这样做,那是另一个错误!!参见 git 。为了共享数据,将数据文件添加到版本控制中可能很有诱惑力。这对于非常小的文件来说是可以的,但是 git 并不适合数据,尤其是大文件。
git add data.csv
解决方案:使用#1 中提到的工具来存储和共享数据。如果你真的想要版本控制数据,参见 d6tpipe 、 DVC 和 Git 大文件存储。
5.编写函数而不是 Dag
数据说够了,让我们来谈谈实际的代码!由于学习编码时首先要学习的是函数,因此数据科学代码通常被组织成一系列线性运行的函数。这导致了几个问题,参见你的机器学习代码可能不好的 4 个原因。
def process_data(data, parameter):
data = do_stuff(data)
data.to_pickle('data.pkl')data = pd.read_csv('data.csv')
process_data(data)
df_train = pd.read_pickle(df_train)
model = sklearn.svm.SVC()
model.fit(df_train.iloc[:,:-1], df_train['y'])
解决方案:与其线性链接函数,不如将数据科学代码编写为一组任务,这些任务之间存在依赖关系。使用d6t 气流或气流。
6.编写循环
像函数一样,for 循环是你学习编码的第一件事。容易理解,但是它们速度慢且过于冗长,通常表明您不知道矢量化的替代方法。
x = range(10)
avg = sum(x)/len(x); std = math.sqrt(sum((i-avg)**2 for i in x)/len(x));
zscore = [(i-avg)/std for x]
# should be: scipy.stats.zscore(x)# or
groupavg = []
for i in df['g'].unique():
dfg = df[df[g']==i]
groupavg.append(dfg['g'].mean())
# should be: df.groupby('g').mean()
解决方案: Numpy 、 scipy 和 pandas 对大多数你认为循环可能需要的东西都有向量化函数。
7.不要写单元测试
随着数据、参数或用户输入的变化,您的代码可能会中断,有时您并没有注意到。这会导致糟糕的结果,如果有人根据你的结果做决定,糟糕的数据会导致糟糕的决定!
解决方案:使用assert语句检查数据质量。 pandas 有相等测试, d6tstack 有数据接收检查, d6tjoin 有数据连接检查。数据检查示例代码:
assert df['id'].unique().shape[0] == len(ids) # have data for all ids?
assert df.isna().sum()<0.9 # catch missing values
assert df.groupby(['g','date']).size().max() ==1 # no duplicate values/date?
assert d6tjoin.utils.PreJoin([df1,df2],['id','date']).is_all_matched() # all ids matched?
8.不要记录代码
我明白了,你急着做分析。你把事情拼凑起来,把结果交给你的客户或老板。然后一周后他们回来说“你能改变 xyz 吗”或者“你能更新这个吗”。你看着你的代码,却不记得你为什么要这么做。现在想象其他人必须运行它。
def some_complicated_function(data):
data = data[data['column']!='wrong']
data = data.groupby('date').apply(lambda x: complicated_stuff(x))
data = data[data['value']<0.9]
return data
解决方案:花额外的时间,即使是在你完成分析之后,来记录你做了什么。你会感谢你自己,别人会更感谢你!你会看起来像个专业人士!
9.将数据保存为 csv 或 pickle
背数据,毕竟是数据科学。就像函数和 for 循环一样,CSV 和 pickle 文件是常用的,但它们实际上并不是很好。CSV 不包含模式,所以每个人都必须再次解析数字和日期。Pickles 解决了这个问题,但是只能在 python 中工作,并且没有被压缩。这两种格式都不适合存储大型数据集。
def process_data(data, parameter):
data = do_stuff(data)
data.to_pickle('data.pkl')data = pd.read_csv('data.csv')
process_data(data)
df_train = pd.read_pickle(df_train)
解决方案:使用带有数据模式的 parquet 或其他二进制数据格式,最好是压缩数据的格式。 d6tflow 自动将任务的数据输出保存为 parquet,这样你就不用处理了。
10.使用 jupyter 笔记本
让我们以一个有争议的问题来结束:jupyter 笔记本和 CSV 一样普遍。很多人都在用。这并不意味着他们是好人。Jupyter 笔记本助长了上面提到的许多坏的软件工程习惯,特别是:
- 您很想将所有文件都转储到一个目录中
- 您编写自顶向下运行的代码,而不是 Dag
- 你没有模块化你的代码
- 难以调试
- 代码和输出混合在一个文件中
- 他们没有很好的版本控制
感觉很容易上手,但是扩展性很差。
基于谷歌地图的十大客户友好国家
根据谷歌地图的数据,创建一个“顾客友好国家”指数
一切都始于布鲁塞尔!
比利时布鲁塞尔-2018 年 8 月 11 日。我第一次访问这个城市,作为我等待已久的欧洲之旅的一部分,这是一个阳光明媚的星期六早上,我醒来,吃了早餐,然后去一家受欢迎的咖啡馆喝了第一杯咖啡,你猜怎么着…这是一个可怕的经历!
工作人员很粗鲁,不灵活,他们有一些愚蠢的规则,什么可以做,什么不可以做,并增加了等待服务的长队。像任何沮丧的顾客一样,我直接去谷歌地图给他们一个差评,却发现其他人已经这样做了。
这次经历让我目瞪口呆,我产生了内心的斗争;我是应该用这次经历来评判整个城市还是干脆无视,再给布鲁塞尔一次机会:)
我决定选择后者,这时候我有了一个想法💡在我脑海中闪现…
能否通过汇总谷歌地图的点评数据来判断一个国家的友好程度!?
挑战
回答这样的问题是困难的、具有挑战性的和棘手的。然而,这个月我开始着手做这件事,我设法进行研究,用数据来回答这个问题,遵循以下步骤:
- 定义一个假设:“如果我们对一个国家的餐馆和咖啡馆进行抽样调查并汇总评论得分,排名靠前和靠后的国家之间会有显著差异”,从而找出友好国家和不友好国家
- 获取数据**:从谷歌地图 API 获取每个国家的评论的统计样本——我决定只关注 餐馆&咖啡馆首都城市****
- ****清理数据,例如删除评论人数少的咖啡馆
- ****分析数据并确保结果有意义,这包括 统计测试
- 可视化并总结结果
更多的技术和统计细节可以在文章末尾的 方法论&统计 部分找到
结果
对 153 个国家*(首都城市)的分析显示 排名靠前和垫底国家的综合评估得分均值之间存在明显的统计显著差距 。
*由于缺乏足够的数据,91 个国家被排除在外
我还发现数据中所有国家的平均谷歌地图评论分数为 4.31 分,最低 2 分,最高 5 分

Boxplot chart for all review scores in all countries
接下来,您将找到更多关于排名靠前和靠后的国家的信息
测验:现在停下来想一想……你认为你的国家会排在名单的哪个位置:顶端、底端还是中间?
十大国家
根据平均评审分数查找以下 10 个国家

Top 10 Countries (capitals) based on Aggregated Review Scores (horizontal lines shows the IQR, point size denotes the average number of reviews per restaurant or cafe — 365.7 for Bosnia, color is random)****
垫底 10 个国家
根据平均评估分数,排名最差的 10 个国家

Bottom 10 Countries (capitals) based on Aggregated Review Scores (horizontal lines shows the IQR, color is random)****
国家友好世界地图
在这里,您可以找到按每个国家的平均点评分数着色的世界地图

Countries colored by average review score (lighter is better )— white means no data
以下是按每家咖啡馆或餐厅的平均点评数量进行着色的国家

Countries colored by average number of reviewsper cafe or restaurant — lighter is higher
国家友好指数—完整列表
最后,所有国家和分数的完整列表…

Country Friendliness & Service Quality Index — 2019
“大陆”友好度地图
下面是世界地图,用颜色表示按“洲”汇总的平均点评分数

Continents colored by average review score (lighter is better ) — white means no data
统计显著性检验
除了数据分布中明显的视觉差异之外,对排名靠前和垫底国家的数据点进行了尾部 t 检验,结果证实了最初的假设,审查得分均值的差异具有统计学意义,其 p 值为:0.00000000000000002****
下面你可以看到这两个国家的评论分数分布图

Distribution (KDE) of review scores for top & bottom countries
用户评论分析
下图显示了按评审分数汇总的评审者使用的热门短语

Aggregated word clouds (Tri-grams) by review scores range
我们可以在这里看到一些模式
- 对于那些评价高于平均水平(4.31+)的人,你可以看到他们的热情和对“员工友好”的重视
- 对于得分平均或低于平均(低于 4.31)的地方,更多关注“地方”和“食物”,热情较低(较少“非常”和“很好”)
- 差评在 2-3 之间的地方主要与价格有关(这里的数据并不充分,因为只有 3 家商店在这个范围内)
- 你也注意到红色区域的德语文本了吗?..任何德国人或生活在德国的人都会知道为什么:)
名人墙
在这里,我展示了一个具有出色的 5 星级评分的咖啡馆的例子
我从没想过有人会得到数百人一致的 5 星评价,我很好奇你——读者——对此有何解释!
布加勒斯特的一家咖啡馆

耻辱之墙
现在是谷歌地图的一个坏例子的时候了
罗马的咖啡馆获得了 2 星的一致评级,主要的痛点似乎是极端和透明的价格

结论
在这篇文章的开始,我问了下面这个问题
“我们可以通过汇总谷歌地图的评论数据来判断一个国家的友好度吗!?"****
现在,在研究结果出来后,我可以自信地说是的,但有一点小小的变化** …正如我们一起看到的,(名声/耻辱墙)评论并不总是转化为友好,它可能是关于价格、清洁、速度等..因此,总体而言,评价是关于友好度和服务质量的,因此我将把这句话改为**
“能否通过汇总谷歌地图的点评数据来判断一个国家的友好度&服务质量!?"
这就是为什么这篇文章的标题是“基于谷歌地图的十大客户友好国家”
谷歌地图是座金矿
在我看来,谷歌地图是一个非常有价值的数据来源,可以带来各种各样的机会,例如,你可以在地图上构建应用程序,以提供基于评论文本的智能标记搜索——比如“给我找一家目前不拥挤的咖啡馆”**
*** * Google 的功能请求:)**
也就是说,请注意从谷歌地图获取数据是昂贵的,我为这项研究支付了大约 150 欧元
结果有意义吗?
定义“意义”…就个人而言,结果并没有证实我最初的偏见,我仍然不明白为什么国家以这种方式排名,为什么巴尔干半岛的 3 个国家占据了前 5 名(以前从未出现过)
可能有许多因素影响结果,例如主导评论的人群(可能是游客),该国的评级文化——比如他们倾向于给出好评或差评,该国的发达程度,该国服务业的质量,以及公民的文化和友好程度
请在评论中告诉我你对这些结果的看法
你个人如何使用这些数据?
- 你可以将你的店铺评论分数与国际平均分数 4.31 或者你所在国家的当地平均分数进行比较
- 现在你知道提供优质服务、美食和友好员工的首都城市列表了:)
- 你知道应该关注什么来获得高于平均水平的评价分数(1-员工友好度 2-食品质量 3-地点和价格)
进一步研究
我很想知道这些数据与其他指数如联合国人类发展指数(T1)、T2 zendex 客户服务指数(T3)有什么关联。如果您想对数据做进一步的分析,您可以在这里访问聚合结果 CSV 文件。
方法论和统计学
关于这项研究的一些详细的技术信息
- ****21807 个数据点已经使用Google Maps Places API获取
- 只获取了每个首都城市的餐馆和咖啡馆的数据****
- 选择的样本量范围为每个城市 60-120 家咖啡馆/餐厅,以达到 95%置信区间和 10%误差范围的统计显著性。总人口(根据城市规模,假设每个城市的餐馆数量为 1,000 至 30,000 家)
- 删除所有评论数量少于 10 的咖啡馆/餐厅,以避免偏见(16%的数据)****
- 删除任何不符合 60 家咖啡馆/餐厅目标样本量的国家/地区——特别是在上述清理步骤之后****
- 这样,从谷歌地图上获取的最初 242 个国家中,只剩下 15727 个数据点和153 个国家(由于数据大小和质量原因,91 个国家被排除在外)
密码
我很乐意在下面的 Github 存储库中分享数据提取和分析代码,但是由于服务协议的条款,我不能分享获取的谷歌地图数据
https://github.com/karimouda/country-friendliness-index
信用
我要感谢 Hamza Ibrahim 、 Hany Ouda 、 Mostafa Nageeb 花时间审阅本文并提出宝贵意见。
关于我
我目前是柏林数据和产品领域的自由顾问。数据不仅是我的工作,也是我的热情所在,我在 2012 年创建我的分析初创公司时开始爱上数据,后来我决定通过攻读数据科学硕士学位来更深入地了解它,我还曾经在 Kaggle.com 上参加比赛,当我有时间时,我会不时地做一些像这样有趣的研究:)你可以在这里找到更多关于我的信息:https://karim.ouda.net
您应该关注的 10 大数据科学领导者
如果你是一名数据科学家

我始终相信,为了有效地学习,我们必须向最优秀的人学习。
如果你一直在关注我的工作,我两年前作为一名物理系学生开始学习数据科学,对数据科学一无所知。
我设法在一年内从物理科学过渡到数据科学。
的确,我挣扎了很多。我犯了很多错误。
我失败了。振作起来。又往前走了。
当我回顾我的数据科学之旅以及我已经走了多远时,在我的整个学习之旅中,真正让我加快速度的是我学到了(而且还在学!)来自最优秀的数据科学领导者,他们是数据科学领域的专家。
这极大地帮助了我成为一名数据科学家的数据科学之旅,因为他们定期分享他们在数据科学方面的真实生活经验、正在使用的最新技术和工具、技术和非技术知识以及许多其他知识…
事实上,这些数据科学领导者只是 LinkedIn 上令人敬畏的数据科学社区的一部分,他们激励我通过在 LinkedIn 和 Medium 上分享我的经验和知识来回馈社区。
因此,你现在正在阅读这篇文章(以及其他关于媒介的文章)。
如果你在数据科学领域,我强烈建议你关注这些巨头——我将在下面的部分列出这些巨头——并成为我们数据科学社区的一员,向最优秀的人学习并分享你的经验和知识。
我们开始吧!
您应该关注的 10 大数据科学领导者

1。兰迪·劳
兰迪老认真牛逼。事实上,他是我刚起步时关注的第一个数据科学领导者,对数据科学一无所知。
如果你是一名有抱负的数据科学家,我强烈推荐你去看看他的网站,那里有所有有用的免费数据科学和机器学习资源与你分享。
最重要的是,他还是数据科学梦想工作的数据科学导师,这是一个帮助有抱负的数据科学家成长和获得工作的电子学习平台,由凯尔·麦基乌创立。
凭借他在数据科学领域的分享和丰富经验,我相信您会从他那里学到很多东西,我也是。
2。凯尔·麦基乌
如果你是 LinkedIn 的活跃用户,你可能已经听说过他的名字。
如前所述,Kyle 是 数据科学梦想工作 的创始人,该公司教授来自不同背景的有抱负的数据科学家如何在数据科学领域找到工作。
这门课程本身比任何东西都有价值,因为他和其他出色的导师向有志的数据科学家传授思维方式、技术和非技术技能、求职技巧以及如何最终在这个行业开始职业生涯。
这不仅仅是 Udemy 或 Coursera 上的另一门只教授编程或机器学习技术技能的在线课程。
Kyle 还定期在 LinkedIn 上与数据科学社区分享他在数据科学方面的经验和见解。
如果你想进入数据科学领域——即使你没有任何背景——那么跟随凯尔,看看他的课程。
3。基里尔·叶列缅科
基里尔·叶列缅科是数据科学家在线教育门户网站 SuperDataScience 的创始人兼首席执行官。
该公司的使命是“化繁为简”,愿景是成为数据科学爱好者最大的学习门户。
此外,该平台还提供数十种分析课程,从 R 编程、Python、Tableau 等基于工具的课程到机器学习 A-Z 和数据科学导论等综合课程。
我个人最喜欢的课程:深度学习 A-Z:动手操作的人工神经网络由基里尔·叶列缅科和哈德琳·德·庞特维斯教授。这是我第一次接触深度学习,相信我,他们的课程真的是独一无二的,非常强调本能的理解水平,有监督和无监督深度学习的动手编码教程。
最近,我有机会读了他的书— 自信的数据技能 ,这本书帮助你理解从项目开始到结束的完整数据科学工作流程,全部零代码!
4。法维奥·巴斯克斯
Favio Vázquez 在数据科学方面有着丰富的经验,他总是愿意毫无保留地在 LinkedIn 上分享他的想法和见解。
就我个人而言,我是他的 YouTube 频道之一的粉丝——数据科学办公时间,与其他令人惊叹的数据科学领导者分享他们在不同主题中的经验。
光是从他们的网络研讨会上,我就无法告诉你我学到了多少。
因为到最后,作为一个有抱负的数据科学家,你可以参加很多在线课程和证书,尽可能多地学习。但是,如果你不能理解数据科学家如何在真实的工作环境中工作,你将无法应用你从这些课程中学到的东西。
你将无法理解作为数据科学家的角色。
所以,向数据科学家学习一直是我首选的学习和探索方式。
5。埃里克·韦伯
Eric 是 LinkedIn 的高级数据科学家,现在在 CoreLogic 担任数据管理和数据科学的负责人。
我非常喜欢 Eric 的一点是他对当前数据科学领域的敏锐观察。
他总是愿意分享他的知识和经验,以揭开数据科学中一些常见但被遗忘的领域的神秘面纱,这些领域从未让我感到惊讶。
Eric 是我加入 LinkedIn 数据科学社区以来一直关注的数据科学领导者之一。有太多的东西要向他学习,我迫不及待地想在未来与你分享!
6。凯特·斯特拉奇尼
凯特以《颠覆者 T2:数据科学领导者》一书的作者而闻名。
她也是数据化周刊的主持人,这是一个致力于帮助其他人了解数据领域各种主题的项目,她还是 YouTube 数据频道的数据科学人类(HoDS)的主持人。
在本文中,她还采访了一些数据科学的领导者,所以如果你想了解数据领域的各种主题,我强烈建议你去看看她的 YouTube 频道。
Humans of Data Science (HoDS) with Favio Vázquez
您可能已经意识到,LinkedIn 上的数据科学社区是一个联系紧密的社区,我们在这里相互交流,分享和共同学习。
7。塔利·辛格
Tarry Singh 是 deepkapha.ai 的创始人兼首席执行官,该公司除了为人工智能研究和慈善事业做出贡献外,还为公司和企业带来人工智能解决方案。
Tarry 在使用深度学习和人工智能解决现实世界问题方面的热情启发了我,在我刚开始从事数据科学时,我就用数据来回报社会。
关注他的工作和分享。你会对他的想法和分享感到惊讶,尤其是在人工智能的最新前沿技术上。
8。伊马德·穆罕默德·汗
Imaad Mohamed Khan 目前是 Indegene 的数据科学家。
他的帖子总是如此鼓舞人心,并且对数据科学中的任何话题都一针见血。
此外,Imaad 还不定期在印度组织尾数数据科学会议,让大家有机会在一起学习的同时分享和表达自己的想法。
他绝对是我一直期待向其学习的数据科学家之一。
9。安德烈亚斯·克雷茨
每当我们谈论数据科学时,大多数人都倾向于认为这都是关于建立很酷的机器学习模型和做出令人敬畏的预测。
实际上,构建模型只是整个工作流的一部分,而数据工程(也称为数据科学的管道工)是支持数据科学项目的工作流的关键部分。
如果没有一个稳定和可靠的数据工程管道和平台,一开始就很难获得数据来执行任何分析。
谈到数据工程和构建大数据平台以支持数据科学项目,Andreas 是真正的专家。
他是一名数据工程师和数据科学平台架构师,构建每天处理和分析海量数据的数据科学平台。
如果你想了解更多关于数据工程的东西,比如 Hadoop、Spark 和 Kafka,可以去看看他的 YouTube 频道——数据科学的管道工。
What is Plumbers of Data Science? — by Andreas Kretz
10。安德烈·布尔科夫
Andriy——Gartner的数据科学总监兼机器学习团队负责人——可以被认为是 LinkedIn 上的数据科学领导者和名人之一,他的畅销书是百页机器学习书籍。
他的这本受欢迎的书已经被翻译成不同国家的不同语言(甚至被一些大学的图书馆和课程收录为教材!).
他还定期分享大量有用的数据科学技巧(几乎每天!)在 LinkedIn 上,我相信你不会想错过的。
最后的想法

感谢您的阅读。
这里的数据科学领导者名单绝非详尽无遗。这些只是我两年前开始从事数据科学工作时跟随和学习的一些顶级数据科学领导者。
直到现在,我每天都在学习他们的分享和经验。
受到他们贡献的启发,我正在通过分享我的知识和经验来回馈数据科学社区,希望能够帮助更多有抱负的数据科学家。
最终,作为数据科学社区的一员,我们在这里,并将永远在这里分享、帮助、学习和共同成长。
这就是一个社区的意义所在。
我希望你喜欢阅读这篇文章。
记住,不断学习,永不停止进步。
一如既往,如果您有任何问题或意见,请随时在下面留下您的反馈,或者您可以随时通过 LinkedIn 联系我。在那之前,下一篇文章再见!😄
关于作者
阿德蒙德·李 目前是东南亚排名第一的商业银行 API 平台 Staq — 的联合创始人/首席技术官。
想要获得免费的每周数据科学和创业见解吗?
你可以在 LinkedIn 、 Medium 、 Twitter 、脸书上和他联系。
让每个人都能接触到数据科学。Admond 正在通过先进的社交分析和机器学习,利用可操作的见解帮助公司和数字营销机构实现营销投资回报。
www.admondlee.com](https://www.admondlee.com/)
数据可视化中的 10 大地图类型

为什么大家都喜欢用不同的地图类型来可视化新闻媒体或者数据分析报告中的信息?
除了传递信息的效率高,还有一个重要原因,就是审美。再无聊的内容,只要配上酷炫的地图,都会让人眼前一亮。
地图可视化用于分析和显示地理上相关的数据,并以地图的形式呈现出来。这种数据表达更加清晰直观。我们可以直观的看到各个区域的数据分布或者比例。方便大家挖掘更深层次的信息,做出更好的决策。
地图可视化有多种类型,如行政地图、热图、统计图、轨迹图、气泡图等。地图可分为 2D 地图、3D 地图或静态地图、动态地图、交互式地图……它们通常与点、线、气泡等结合使用。在本文中,您将找到数据可视化中 10 大地图类型的示例!
(注:文中所有地图类型均用 FineReport 制作,个人下载完全免费。)
1.点地图
点地图非常简单,尤其是在显示地理信息分布广泛的数据时。比如有的公司业务范围很广。如果公司要查看某个区域内各个站点(具体位置)的数据,用一般的地图实现起来会比较复杂,精度不高。然后就可以利用点图进行精准快速的定位了。


使用场景:点事件分布。点地图还可以实现大事件的特殊识别。和上面的事故追踪图一样,可以用图片、文字或者动态效果识别相对严重的事件。
2.平面图
你可能不会经常使用线图,因为它们相对来说比较难画。但是,线图有时不仅包含空间,还包含时间。对于特殊场景的分析,其应用价值特别高。

使用场景:骑行或驾车的路线分布,公交或地铁线路分布,比如上图中纽约市的出租车路线。
3.区域地图
区域地图也称为填充地图。可以按国家、省、市、区甚至一些定制地图显示。你可以通过地图上颜色的深浅或者不同的颜色来知道数据的大小。

使用场景:某个特性在不同地区的分布。可以实现从省到市的分步钻探。它可以用不同的颜色或标签来表示不同的特征。例如,在上图中,我们可以从省到市向下钻取数据来查看销售情况。销量越大,颜色越深。
4.流程图作业图
流程图通常用于可视化始发地-目的地流程数据。起点和终点可以是点或曲面。始发地和目的地之间的交互数据通常用连接空间单元的几何重心的线来表示。线条的宽度或颜色表示起点和终点之间的流向值。每个空间位置可以是起点或终点。

使用场景:区域间贸易、交通流量、人口迁移、购物消费行为、通讯信息流、航空航线等。
5.热图
热图用于显示地理范围内每个点的权重。它通常以特别突出的方式显示。如下图所示,是一张雾霾图。该地区的颜色越深,该地区的空气质量越差。

使用场景 : PM 2.5 分布、注册日期和年龄分布、产品偏好分布等。
6.热点图
热点地图是热点地图和点地图的综合应用。与热图相比,其识别的准确率可以更高。而且和点图相比,它的点其实是一个圆,圆之间相互重叠,更有层次感。

使用场景:显示地理范围内各复杂点的权重。比如上面的公交车站使用图,人越多点越大,颜色越深。也可以确定最大和最小人数。
7.时空分布图
这种地图显示了具有时间和空间信息的轨迹分布。他们可以记录每个点的时间和空间分布。

使用场景 : GPS 地理追踪等。
8.数据空间分布图
我们用一个具体的例子来解释这张地图。下图是轨道交通客流空间分布图。不同的颜色标识不同的线路(更直观),线路的粗细表示不同站点的车流量(类似于热点)。线越粗,流量越大。它还可以指示轨迹线的方向。

使用场景:通过这种可视化效果,运营者可以清楚地知道某一时间段的客流分布情况,从而合理安排运营(如员工数量等。).
9.三维矩形地图
这种类型的地图是点地图的升级版本。点的形状各不相同,包括这种三维矩形。


使用场景:点地图的所有场景。它更侧重于特定对象的地理分布,如房地产建设项目。
10.自定义地图
自定义地图是您自己设计的地图可视化。可以满足任何使用场景,但是需要一定的数据分析和可视化设计基础。所以我就不多说了,只给大家看两张我做的自定义地图。


终于
读到这里,你可能会问你应该使用什么工具来制作地图可视化。我觉得没必要强调工具的选择。Excel,D3,甚至 PS 都可以做你想做的。你应该多想想你使用这些工具的主要目的。
如果只是想展示处理后的数据,可以选择 Excel。又或许你有各种各样的数据,但是你不懂数据建模、编程,或者数据清洗,甚至 SQL 优化,那么你就需要一个像 FineReport 和 Tableau 这样简单易用的数据可视化工具。我在本文中制作的地图看起来可能有点难画,但我实际上使用了 FineReport 的内置地图模板。通过简单的拖放操作,数据可以很容易地可视化。

总之,上面提到的工具都有地图可视化的功能,只是有区别。你要根据自己的需求选择适合自己的可视化工具。
您可能也会对…感兴趣
原载于 2019 年 8 月 1 日【http://www.finereport.com】。
2019 年美国十大最成功的公司

Photo by rawpixel.com from Pexels
最近我碰到了Inc .2019 年美国最成功的 5000 家公司,这些公司实际上是根据 2015 年至 2018 年的收入增长百分比进行排名的。这是数据集能告诉我们的关于哪些州、行业和城市现在是最热门的。
对于那些想看实际的 5000 强名单的人来说,这里有完整的文章和对每个公司的简要描述。
让我们从排名前 10 的公司开始,包括他们的增长和收入以及位置。

Top 10 Ranking by Growth Percent
在按行业对 5000 强名单中的公司数量进行细分后,我们意识到硬件、IT 服务、环境服务和媒体在数据集中几乎没有代表性,因此它们位于图表的底部;另一方面,有趣的是看到零售在中间,实际上属于零售行业的最有趣的公司之一是 Chewy ,这是一个宠物产品(药物、食物、零食、用品)的在线平台,它始于 2011 年,到 2018 年已经实现了 35 亿美元的收入,增长了 736%。

Countplot of Number of Companies by Industry
到目前为止,赚钱最多的行业是健康公司;他们在 3 年内(2015 年至 2018 年)的收入接近 1600 亿美元。Inc 的数据集实际上有 5012 个值,而不是 5000 个值,其中健康仅占 7%,而商业产品&服务、广告&营销和软件公司占近 27%的值。即使在医疗行业与其他价值更高的行业竞争时,它的收入仍排在第一位。

Revenue by Industry
当我们查看公司在各州的分布时,我们可以看到加利福尼亚州、德克萨斯州和佛罗里达州的公司数量最多,排名前三,而波多黎各、密西西比州、佛蒙特州、罗德岛州和怀俄明州则排名垫底。这种高公司分布增加了各州的收入/增长,这就是前 3 个州与后 5 个州之间存在巨大差异的原因。

Revenue by State

Countplot of the Top Ten Cities
有趣的是,即使加州在行业数量(709 家公司)和收入(1930 亿美元)方面处于领先地位,纽约也是领先的城市,紧随其后的是芝加哥、亚特兰大、奥斯汀、休斯顿和达拉斯。
就行业增长率而言,软件实际上排名第一;软件公司发展非常迅速,我们可以看到,在旧金山、西雅图、纽约等城市,软件和在线服务公司不仅要专注于他们的主要优先事项,而且要准备好随着增长重新评估产品和流程,这一点很重要。我们可以在这个数据集中看到它的反映。尽管软件在总收入中排名第四,但它在增长图表中排名第一。

Growth Percent by Industry

Top 10 Billion Dollar Companies with their Ranking
5000 家(实际上是 5012 家)公司名单中有 4989 家公司的收入达到数百万美元,但有 23 家公司的收入达到数十亿美元。没有一家十亿美元的公司排在前 100 名,甚至没有排在前 500 名,这显然意味着收入本身不是上榜的最重要因素,而是时间和收入。十亿美元公司的平均“成立年龄”是 27 年(1992 年),而增长更快、排名更好的公司的“成立年龄”是 14 年(2005 年)。
与那些已经在市场上存在了相当长时间的公司相比,年轻的公司如果在短时间内赚了很多钱,就会有如此大的增长,这是有道理的,这些公司的价值逐年增加,但不是以指数方式,而是以线性方式增加。

Companies by Founded Year
结论:
虽然有些公司比其他公司赚得更多,但我们得出的结论是[时间+收入]是这里的重要因素;如果一个年轻的公司在短时间内赚了很多钱,那么排名就会上升。
除此之外,数据集在不同的收入、公司规模和增长方面有许多起伏,我们能够确定我们在开始这篇文章时想到的关键问题。
分析的三个主要问题是:
- 2019 年最热门的行业是哪个(根据数据集)。
- 哪个城市/州显示了最大的行业增长。
- 哪种类型的公司增长最快。
- 对于第一个问题,在按州和行业分解收入后,我们可以得出结论,目前最热门的投资行业是健康行业,除了价值低于软件和广告及营销行业外,它仍然排在这两个行业的前面。
- 就州而言,加利福尼亚州是公司最多的州,其次是德克萨斯州和佛罗里达州。即使加利福尼亚是交通最繁忙的州,纽约也是公司最多的城市。
- 软件公司发展非常快,我不认为这些类型的公司会很快停止增长,因为随着时间的推移,不同类型的行业似乎需要更多的软件“需求”。
数据科学的 10 大 Python 库

一段时间以来,Python 一直吸引着数据科学家。我与数据科学领域的资源、文献、课程、培训和人员的互动越多,精通 Python 的知识就成为一种很好的资产。话虽如此,当我开始提高我的 Python 技能时,我有一个必须了解的 Python 库列表。过了一会儿…
一段时间以来,Python 一直吸引着数据科学家。😀
数据科学领域的人肯定知道可以在数据科学中使用的 Python 库,但是当在采访中被要求说出它们的名称或陈述它的功能时,我们经常笨手笨脚,或者可能不记得超过 5 个库(这发生在我身上:/)
今天,我整理了 10 个 Python 库的列表,它们有助于数据科学及其外围领域,何时使用它们,它的重要特性和优势是什么。
在本文中,我根据自己最近的经验和探索,简要概述了对数据科学家和工程师最有用的 10 个 Python 库。阅读完整的故事,了解 4 个奖金库!
1.熊猫
Pandas 是一个开源的 Python 包,为 Python 编程语言中的标注数据提供了高性能、易于使用的数据结构和数据分析工具。熊猫代表 Python 数据分析库。谁知道呢?
什么时候用?Pandas 是一个完美的数据争论或管理工具。它设计用于快速简单的数据操作、读取、聚合和可视化。
熊猫获取 CSV 或 TSV 文件或 SQL 数据库中的数据,并创建一个包含行和列的 Python 对象,称为数据框。数据框非常类似于统计软件中的表格,比如 Excel 或 SPSS。
你能用熊猫做什么?
- 索引、操作、重命名、排序、合并数据帧
- 更新、添加、删除数据框中的列
- 估算丢失的文件,处理丢失的数据或变量
- 用直方图或箱线图绘制数据
这使得 Pandas 成为学习数据科学 Python 的基础库。
2.NumPy
Python 中最基本的包之一, NumPy 是一个通用的数组处理包。它提供了高性能的多维数组对象和工具来处理数组。NumPy 是通用多维数据的有效容器。
NumPy 的主要对象是同构多维数组。它是由相同数据类型的元素或数字组成的表,由正整数元组索引。在 NumPy 中,尺寸称为轴和轴的数量称为等级。NumPy 的数组类叫做 ndarray 又名 array。
什么时候用?NumPy 用于处理存储相同数据类型值的数组。NumPy 有助于数组的数学运算及其矢量化。这显著增强了性能,并相应地加快了执行时间。
你能用 NumPy 做什么?
- 基本数组操作:加法、乘法、切片、展平、整形、索引数组
- 高级阵列操作:堆叠阵列、分割成部分、广播阵列
- 使用日期时间或线性代数
- NumPy Python 中的基本切片和高级索引
3.SciPy
SciPy 库是构成 SciPy 栈的核心包之一。现在,SciPy Stack 和 SciPy 库是有区别的。SciPy 建立在 NumPy 数组对象的基础上,是包括 Matplotlib、Pandas 和 SymPy 等工具的堆栈的一部分,
SciPy 库包含高效数学例程的模块,如线性代数、插值、优化、积分和统计。SciPy 库的主要功能是建立在 NumPy 及其数组之上的。SciPy 大量使用了 NumPy。
什么时候用?SciPy 使用数组作为它的基本数据结构。它有各种模块来执行常见的科学编程任务,如线性代数、积分、微积分、常微分方程和信号处理。
4.Matplotlib
这无疑是我的最爱,也是一个典型的 Python 库。您可以使用 Matplotlib 可视化的数据创建故事。SciPy 堆栈中的另一个库 Matplotlib 绘制 2D 图形。
什么时候用?Matplotlib 是 Python 的绘图库,它提供了面向对象的 API,用于将绘图嵌入到应用程序中。它非常类似于嵌入在 Python 编程语言中的 MATLAB。
你能用 Matplotlib 做什么?
直方图,条形图,散点图,面积图到饼图,Matplotlib 可以描绘各种各样的可视化。借助 Matplotlib,只需一点努力和可视化功能,您就可以创建任何可视化效果:
- 线形图
- 散点图
- 面积图
- 条形图和直方图
- 饼图
- 树干图
- 等高线图
- 颤动图
- 光谱图
Matplotlib 还通过 Matplotlib 简化了标签、网格、图例和其他一些格式化实体。基本上能画的都画了!
5.海生的
所以当你阅读 Seaborn 上的官方文档时,它被定义为基于 Matplotlib 的数据可视化库,该库为绘制有吸引力和信息丰富的统计图形提供了高级接口。简单来说,seaborn 是 Matplotlib 的扩展,具有高级特性。
那么,Matplotlib 和 Seaborn 有什么区别呢?Matplotlib 用于基本绘图;条形图、饼图、线图、散点图等等,而 seaborn 提供了各种可视化模式,具有更简单的语法。
你能用 Seaborn 做什么?
- 确定多个变量之间的关系(相关性)
- 观察聚合统计的分类变量
- 分析单变量或双变量分布,并在不同的数据子集之间进行比较
- 绘制因变量的线性回归模型
- 提供高级抽象、多绘图网格
Seaborn 对于像 corrplot 和 ggplot 这样的可视化库来说是一个很好的二手工具。
6.Scikit 学习
Scikit Learn 是作为 Google 代码之夏项目向世界推出的,它是一个强大的 Python 机器学习库。它具有最大似然算法,如支持向量机,随机森林,k-均值聚类,谱聚类,均值漂移,交叉验证等...Scikit Learn 甚至支持 NumPy、SciPy 和相关的科学操作,Scikit Learn 是 SciPy 堆栈的一部分。
什么时候用?Scikit-learn 通过 Python 中的一致接口提供了一系列监督和非监督学习算法。像朴素贝叶斯这样的监督学习模型对 KMeans、Scikit learn 等未标记数据进行分组将是您的首选。
你能用 Scikit Learn 做什么?
- 分类:垃圾邮件检测、图像识别
- 聚类:药物反应,股票价格
- 回归:客户细分,分组实验结果
- 降维:可视化,提高效率
- 模型选择:通过参数调整提高精度
- 预处理:将输入数据准备为文本,以便用机器学习算法进行处理。
Scikit Learn 侧重于建模数据;不操纵数据。我们有 NumPy 和熊猫用于总结和操作。
7.张量流
回到 2017 年,我收到了一个 TensorFlow USB,作为对我在谷歌 WTM 活动上成为一名出色演讲者的感谢,哈哈。USB 装载了 TensorFlow 的官方文档。由于当时对张量流一无所知,我在谷歌上搜索了一下。
TensorFlow 是一个 AI 库,帮助开发人员使用数据流图创建具有许多层的大规模神经网络。TensorFlow 还促进了深度学习模型的建立,推动了 ML/AI 的最新发展,并允许轻松部署 ML 驱动的应用程序。
所有图书馆中最发达的网站之一是 TensorFlow。像 Google,可口可乐,Airbnb,Twitter,Intel,DeepMind 这样的巨头,大家都用 TensorFlow!
什么时候用?TensorFlow 在分类、感知、理解、发现、预测和创建数据方面非常高效。
TensorFlow 怎么办?
- 语音/声音识别—物联网、汽车、安全、UX/用户界面、电信
- 情绪分析—主要用于 CRM 或 CX
- 基于文本的应用程序—威胁检测、谷歌翻译、Gmail 智能回复
- 人脸识别——脸书的深度人脸、照片标签、智能解锁
- 时间序列—来自亚马逊、谷歌和网飞的推荐
- 视频检测—游戏、安全、机场中的运动检测、实时威胁检测
8.克拉斯
Keras 是 TensorFlow 的高级 API,用于构建和训练深度神经网络代码。它是 Python 中的一个开源神经网络库。有了 Keras,统计建模、处理图像和文本变得更加容易,简化了深度学习的编码。
Keras 和 TensorFlow 到底有什么区别?
Keras 是一个神经网络 Python 库,而 TensorFlow 是一个用于各种机器学习任务的开源库。TensorFlow 提供高级和低级 API,而 Keras 只提供高级 API。keras是为 Python 打造的,这使得它比 TensorFlow 更加用户友好、模块化和可组合。
你能用 Keras 做什么?
- 确定准确度百分比
- 计算损失函数
- 创建自定义功能层
- 内置数据和图像处理
- 用重复的代码块编写函数:20、50、100 层深
9.统计模型
当我第一次学习 R 时,进行统计测试和统计数据探索似乎是 R 中最容易的,并避免使用 Python 进行统计分析,直到我探索 Statsmodels 或 Python。
什么时候用?Statsmodels 是最终的 Python 包,它为描述性统计和统计模型的估计和推断提供了简单的计算。
如何处理 Statsmodels?
- 线性回归
- 相互关系
- 普通最小二乘(OLS)为经济学家在你!
- 生存分析
- 广义线性模型和贝叶斯模型
- 单变量和双变量分析,假设检验(基本上,R 能做什么!)
10.Plotly
Plotly 是一个典型的 Python 图形绘制库。用户可以导入、复制、粘贴或流式传输要分析和可视化的数据。Plotly 提供了一个沙盒 Python(你可以运行一个有能力限制的 Python ),现在我很难理解沙盒是什么,但我知道 Plotly 让它变得简单!?
什么时候用?如果您想要创建和显示图形,更新图形,悬停在文本上查看详细信息,您可以使用 Plotly。Plotly 还有一个额外的功能,就是把数据发送到云服务器。真有意思!
你能用 Plotly 做什么?
Plotly 图形库提供了大量可供绘制的图形:
- 基本图表: 折线图、饼图、散点图、气泡图、圆点图、甘特图、旭日图、树状图、散点图、填充面积图
- 统计和 Seaborn 风格 :误差、方框、直方图、面和格子图、树形图、小提琴图、趋势线
- 科学图表: 等高线、三元图、对数图、箭图、地毯图、雷达图、热图、风玫瑰图和极坐标图
- 财务图表
- 地图
- 支线剧情
- 转换
- Jupyter Widgets 交互
告诉过你,Plotly 是精华剧情库。想想可视化和 plotly 可以做到这一点!
现在是时候了,当我们探索了十大数据科学 Python 库的采访笔记指南,我们寻找我们的四个额外的库!
1.空间
SpaCy 是一个开源库,用于 Python 和 Cython 的高级 NLP(一种 Python 编程语言,使用 Python 代码提供类似 C 的感觉和性能,加上受 C 启发的语法)
2.散景
Bokeh 是一个 Python 库,我想称之为交互式数据可视化。有了 Tableau、QlikView 或 PowerBI 这样的工具,我们为什么还需要散景呢?首先,散景允许用简单的命令快速构建复杂的统计图表。它支持 HTML,笔记本或服务器输出。其次,可以将散景可视化集成到 Flask 和 Django 应用程序中,或者集成到 matplotlib、seaborn、ggplot 等其他库中编写的可视化中。
3.根西姆
我认为 Gensim 与我们目前所看到的有很大不同。它可以高效、轻松地从文档中自动抽取语义主题。Gensim 算法是无人监管的,这意味着不需要人工输入——只需要纯文本文档,然后就可以执行提取。
4.NLTK
NLTK(自然语言工具包)主要与人类语言而不是计算机语言一起工作,以应用自然语言处理(NLP)。它包含文本处理库,您可以使用这些库对数据执行标记化、解析、分类、词干分析、标记和语义推理。这听起来可能重复了这个库的功能,但是 Python 中的每个库都是为了提高效率而编写的。
这个故事到此为止。接下来…
数据科学 10 大算法!!
感谢您的阅读!如果您喜欢这篇文章,请点击拍手按钮,让我知道是什么库让您的数据科学之旅变得有趣。数据帐篷快乐!
了解你的作者
Rashi 是一名研究生,也是一名数据分析师、用户体验分析师和顾问、技术演讲者和博客作者!她渴望建立一个组织,将商界女性与资源海洋联系起来,让她们对工作和世界充满热情,无所畏惧。随时给她留言这里!
数据科学家犯的十大统计错误
数据科学家是“比任何软件工程师更擅长统计,比任何统计学家更擅长软件工程的人”。在数据科学家犯的十大编码错误中,我们讨论了统计学家如何成为更好的编码员。在这里,我们讨论编码人员如何成为更好的统计人员。
每个例子的详细输出和代码可以在 github 和交互式笔记本中找到。代码使用数据工作流管理库 d6tflow ,数据与数据集管理库 d6tpipe 共享。
1.没有完全理解目标函数
数据科学家希望建立“最佳”模型。但是情人眼里出西施。如果您不知道目标和目标函数是什么,以及它是如何表现的,那么您就不太可能构建出“最佳”模型。fwiw 的目标可能甚至不是一个数学函数,而是改进一个商业度量。
解决方案:大多数 kaggle 赢家花大量时间理解目标函数,以及数据和模型如何与目标函数相关联。如果您正在优化一个业务指标,请将其映射到一个适当的数学目标函数。
示例 : F1 分值通常用于评估分类模型。我们曾经建立了一个分类模型,它的成功取决于它正确出现的百分比。F1 分数具有误导性,因为它显示模型在大约 60%的时间里是正确的,而实际上它只有 40%的时间是正确的。
f1 0.571 accuracy 0.4
2.没有一个假设,为什么有些东西应该工作
通常,数据科学家希望构建“模型”。他们听说 xgboost 和 random forests 效果最好,所以让我们使用它们。他们阅读深度学习,也许这将进一步改善结果。他们在没有查看数据,也没有形成哪种模型最有可能最好地捕捉数据特征的假设的情况下,就抛出模型来解决问题。这也使得解释你的工作变得非常困难,因为你只是随机地向数据扔模型。
解决方案:看数据!了解其特征,并形成一个假设,即哪个模型最有可能捕捉到这些特征。
例:不需要运行任何模型,仅仅通过绘制这个样本数据,你就已经可以有一个强烈的观点,x1 与 y 线性相关,x2 与 y 没有太大的关系。

3.在解释结果之前不看数据
不查看数据的另一个问题是,您的结果可能会受到异常值或其他工件的严重影响。对于最小化平方和的模型来说尤其如此。即使没有异常值,您也可能会遇到不平衡的数据集、截断或缺失的值,以及其他各种您在课堂上没有看到的真实数据的奇怪现象。
解决方案:太重要了,值得重复一遍:看数据!了解数据的性质如何影响模型结果。
例:有异常值,x1 斜率从 0.906 变为-0.375!

4.没有一个简单的基线模型
现代的 ML 库几乎把它变得太简单了……只要改一行代码,就可以运行一个新的模型。另一个。另一个。误差指标在减少,调整参数——太好了——误差指标在进一步减少……有了所有的模型,你可以忘记预测数据的愚蠢方式。如果没有这个天真的基准,你就没有一个好的绝对比较来衡量你的模型有多好,它们可能都很差。
解答:预测一个值的最笨方法是什么?使用最近的已知值、(滚动)平均值或某个常数(如 0)建立一个“模型”。将您的模型性能与零智能预测猴子进行比较!
例:对于这个时间序列数据集,model1 一定比 model2 好,MSE 分别为 0.21 和 0.45。但是等等!仅取最后一个已知值,MSE 就下降到 0.003!
ols CV mse 0.215
rf CV mse 0.428
last out-sample mse 0.003
5.不正确的样品外测试
这可能会让你的职业生涯脱轨!你建立的模型在 R&D 看起来很棒,但在生产中表现糟糕。你所说的将创造奇迹的模式正在导致非常糟糕的业务结果,可能会使公司损失$m+。这很重要,除了最后一个错误,所有剩下的错误都集中在这上面。
解决方案:确保你已经在真实的样本条件下运行了你的模型,并且明白什么时候它会表现良好,什么时候表现不好。
示例:样本内随机森林比线性回归好得多,mse 为 0.048,而 ols mse 为 0.183,但样本外随机森林比线性回归差得多,mse 为 0.259,mse 为 0.187。随机森林训练过度,在实际生产中表现不佳!
in-sample
rf mse 0.04 ols mse 0.183
out-sample
rf mse 0.261 ols mse 0.187
6.不正确的样本外测试:对整个数据集应用预处理
你可能知道强大的 ML 模型会过度训练。过度训练意味着它在样本内表现很好,但在样本外表现很差。所以你需要意识到训练数据会泄露到测试数据中。如果您不小心,任何时候您进行特征工程或交叉验证时,训练数据都可能混入测试数据中,并夸大模型性能。
解决方案:确保你有一个真正的测试集,没有来自训练集的任何泄漏。特别要注意生产使用中可能出现的任何依赖于时间的关系。
例子:这种情况经常发生。在将整个数据集分为训练和测试之前,对其进行预处理,这意味着您没有真正的测试集。在将数据分成训练集和测试集之后,需要单独应用预处理,以使其成为真正的测试集。在这种情况下,两种方法之间的 MSE(混合样本外 CV mse 0.187 对真实样本外 CV mse 0.181)并没有那么大的不同,因为训练和测试之间的分布特性并没有那么大的不同,但情况可能并不总是如此。
mixed out-sample CV mse 0.187 true out-sample CV mse 0.181
7.不正确的样本外测试:横截面数据和面板数据
你被教导交叉验证是你所需要的。sklearn 甚至为你提供了一些便利的功能,让你觉得你已经检查了所有的选项。但是大多数交叉验证方法都是随机抽样的,因此您可能会在测试集中使用训练数据,这会提高性能。
解决方案:生成测试数据,使其准确地反映您在实际生产使用中进行预测的数据。特别是对于时间序列和面板数据,您可能需要生成自定义的交叉验证数据或进行前滚测试。
例:这里有两个不同实体(如公司)的面板数据,它们在横截面上高度相关。如果您随机分割数据,您会使用测试期间实际上没有数据进行准确预测,夸大模型性能。您认为您通过使用交叉验证避免了错误#5,并发现随机森林在交叉验证中比线性回归表现得好得多。但是运行一个前滚样本外测试来防止将来的数据泄露到测试中,它的表现又差了很多!(随机森林 MSE 从 0.047 到 0.211,高于线性回归!)
normal CV
ols 0.203 rf 0.051
true out-sample error
ols 0.166 rf 0.229
8.决策时不考虑哪些数据可用
当您在生产环境中运行模型时,它会得到您运行模型时可用的数据。该数据可能与您在培训中假设的数据不同。例如,数据的发布可能会有延迟,因此当您运行模型时,其他输入已经发生变化,您正在使用错误的数据进行预测,或者您的真实 y 变量不正确。
解决方案:做一个推出样品前向测试。如果我在生产中使用了这个模型,我的训练数据会是什么样的,即你有什么数据来进行预测?这是您用来进行真正的样品外生产测试的训练数据。此外,想想如果你按照预测行事,在决策时会产生什么结果?
9.轻微过度训练
你花在数据集上的时间越多,你就越有可能过度训练它。您一直在修补功能和优化模型参数。你用了交叉验证,所以一切都很好。
解决方案:在你完成模型构建后,试着寻找数据集的另一个“版本”,它可以作为真实样本外数据集的替代。如果你是一名经理,故意隐瞒数据,使其不被用于培训。
示例:将数据集 1 上训练的模型应用到数据集 2 上,结果显示 MSEs 增加了一倍多。它们还能被接受吗…?这是一个判断电话,但你的第四个结果可能会帮助你决定。
first dataset
rf mse 0.261 ols mse 0.187
new dataset
rf mse 0.681 ols mse 0.495
10.“需要更多数据”的谬论
与直觉相反,通常开始分析数据的最佳方式是处理数据的代表性样本。这允许您熟悉数据并构建数据管道,而无需等待数据处理和模型训练。但是数据科学家似乎不喜欢这样——数据越多越好。
解决方案:从一个小的代表性样本开始,看看你是否能从中获得一些有用的东西。还给最终用户,他们能用吗?是否解决了真正的痛点?如果不是,问题可能不是因为你的数据太少,而是你的方法。
有关更多详细信息,请参见 github 和交互式笔记本中每个示例的输出和代码。
成为 Rockstar 数据科学家的 13 大技能
这将你与优秀的数据科学家区分开来

一周前,我在 LinkedIn 上问了这个问题:
是什么将优秀的数据科学家与 rockstar 数据科学家区分开来?

[Question on LinkedIn](http://What separates a good data scientist from a rockstar data scientist?)
令人惊讶的是,我得到了来自不同行业的许多顶级数据科学家的巨大回应,他们都分享了他们的想法和建议-我觉得非常有趣和实用。
为了更多地了解优秀数据科学家和 rockstar 数据科学家之间的主要区别,我一直在互联网上搜索…直到我在 KDnuggets 上找到了的这篇文章。
所以我收集了所有的信息,列出了成为一名 rockstar 数据科学家的技能。
实际上,一个数据科学家不可能具备下面列出的所有技能。但在我看来,这些技能是 rockstar 数据科学家不同于优秀数据科学家的地方。
在本文结束时,我希望您会发现这些技能对您作为数据科学家的职业生涯有所帮助。
我们开始吧!
🚀成为 Rockstar 数据科学家的 13 大技能
1.教育
数据科学家受过高等教育,88%的人至少拥有硕士学位,46%的人拥有博士学位,尽管有明显的例外,但通常需要非常扎实的教育背景才能培养成为数据科学家所需的知识深度。要成为一名数据科学家,你可以获得计算机科学、社会科学、物理科学和统计学的学士学位。最常见的研究领域是数学和统计学(32%),其次是计算机科学(19%)和工程学(16%)。这些课程中的任何一个学位都将为你提供处理和分析大数据所需的技能。
完成学位课程后,你还没有完成。事实是,大多数数据科学家都有硕士学位或博士学位,他们还接受在线培训,学习一项特殊技能,如如何使用 Hadoop 或大数据查询。因此,您可以报名参加数据科学、数学、天体物理学或任何其他相关领域的硕士学位课程。您在学位课程期间学到的技能将使您能够轻松过渡到数据科学。
除了课堂学习,你可以通过开发应用程序、创建博客或探索数据分析来实践你在课堂上学到的东西,从而让你学到更多。
在我看来,只要你能完成工作,硕士或博士是可选的。在大多数行业工作范围内,只要你能够解决业务问题,你就不需要做研究和部署尖端和新颖的机器学习模型。
👉🏻有用的免费资源电子书:成为专业数据科学家的 74 个秘密
2.r 编程
对这些分析工具中的至少一种有深入的了解,对于数据科学 R 通常是首选的。r 是专门为数据科学需求而设计的。你可以用 R 来解决你在数据科学中遇到的任何问题。事实上,43%的数据科学家正在使用 R 来解决统计问题。然而,R 有一个陡峭的学习曲线。
这很难学,尤其是如果你已经掌握了一门编程语言。尽管如此,互联网上有很好的资源可以让你开始学习 R,比如 Simplilearn 的 R 编程语言数据科学培训。对于有抱负的数据科学家来说,这是一个很好的资源。
3.Python 编码
Python 是我通常在数据科学角色中看到的最常见的编码语言,还有 Java、Perl 或 C/C++。对于数据科学家来说,Python 是一种很棒的编程语言。这就是为什么 O'Reilly 调查的 40%的受访者将 Python 作为他们的主要编程语言。
由于 Python 的多功能性,您可以将它用于数据科学过程中的几乎所有步骤。它可以接受各种格式的数据,您可以轻松地将 SQL 表导入到您的代码中。它允许你创建数据集,你可以在谷歌上找到你需要的任何类型的数据集。
通过阅读以下书籍,您可以了解更多关于 Python 的基础知识以及如何在数据科学中使用 Python:
4.Hadoop 平台
尽管这并不总是必需的,但在许多情况下,这是首选。有蜂巢或者猪的经验也是一个很强的卖点。熟悉诸如亚马逊 S3 这样的云工具也是有益的。CrowdFlower 对 3490 份 LinkedIn 数据科学工作进行的一项研究将 Apache Hadoop 列为数据科学家第二重要的技能,有 49%的评级。
作为一名数据科学家,您可能会遇到数据量超过系统内存或者需要将数据发送到不同服务器的情况,这就是 Hadoop 的用武之地。您可以使用 Hadoop 将数据快速传递到系统中的各个点。这还不是全部。你可以使用 Hadoop 进行数据探索、数据过滤、数据采样和汇总。
5.SQL 数据库/编码
即使 NoSQL 和 Hadoop 已经成为数据科学的一个重要组成部分,仍然希望候选人能够用 SQL 编写和执行复杂的查询。SQL(结构化查询语言)是一种编程语言,可以帮助您执行添加、删除和从数据库中提取数据等操作。它还可以帮助您执行分析功能和转换数据库结构。
作为一名数据科学家,你需要精通 SQL。这是因为 SQL 是专门为帮助您访问、交流和处理数据而设计的。当你用它来查询一个数据库时,它给你洞察力。它有简明的命令,可以帮助您节省时间,减少执行困难查询所需的编程量。学习 SQL 将帮助你更好地理解关系数据库,提升你作为数据科学家的形象。
6.阿帕奇火花
Apache Spark 正在成为全球最受欢迎的大数据技术。它和 Hadoop 一样是一个大数据计算框架。唯一的区别是 Spark 比 Hadoop 快。这是因为 Hadoop 读写磁盘,这使得它更慢,但 Spark 将其计算缓存在内存中。
Apache Spark 是专门为数据科学设计的,有助于更快地运行复杂的算法。当你处理大量数据时,它有助于分散数据处理,从而节省时间。它还帮助数据科学家处理复杂的非结构化数据集。您可以在一台机器或一群机器上使用它。
Apache spark 使数据科学家能够防止数据科学中的数据丢失。Apache Spark 的优势在于它的速度和平台,这使得它可以轻松地执行数据科学项目。借助 Apache spark,您可以执行从数据获取到分布式计算的分析。
7.机器学习和人工智能
大量的数据科学家并不精通机器学习领域和技术。这包括神经网络、强化学习、对抗学习等。如果你想从其他数据科学家中脱颖而出,你需要知道机器学习技术,如监督机器学习、决策树、逻辑回归等。这些技能将帮助您解决基于主要组织成果预测的不同数据科学问题。
数据科学需要应用机器学习不同领域的技能。Kaggle 在其一项调查中显示,一小部分数据专业人员能够胜任高级机器学习技能,如有监督的机器学习、无监督的机器学习、时间序列、自然语言处理、离群点检测、计算机视觉、推荐引擎、生存分析、强化学习和对抗学习。
数据科学涉及处理大量数据集。你可能想熟悉 机器学习 。
8.数据可视化
商业世界经常产生大量的数据。这些数据需要转换成易于理解的格式。比起原始数据,人们更自然地理解图表和图形形式的图片。一个习语人说“一幅画胜过千言万语”。
作为一名数据科学家,你必须能够借助 ggplot、d3.js 和 Matplotlib、Tableau 等数据可视化工具实现数据的可视化。这些工具将帮助您将项目的复杂结果转换成易于理解的格式。问题是,很多人不理解序列相关或 p 值。你需要直观地向他们展示这些术语在你的结果中代表了什么。
数据可视化为组织提供了直接处理数据的机会。他们可以迅速掌握洞察力,这将有助于他们抓住新的商业机会,并在竞争中保持领先。
特别是,我写了一篇文章来谈论数据可视化的重要性以及如何用数据创造更好的故事。
9.非结构化数据
数据科学家能够处理非结构化数据至关重要。非结构化数据是不适合数据库表的未定义内容。示例包括视频、博客帖子、客户评论、社交媒体帖子、视频源、音频等。它们是堆在一起的沉重的文本。对这些类型的数据进行排序是困难的,因为它们不是流线型的。
由于其复杂性,大多数人将非结构化数据称为“黑暗分析”。处理非结构化数据有助于您理清对决策有用的见解。作为一名数据科学家,您必须能够理解和操作来自不同平台的非结构化数据。
10.好奇心
“我没有特别的天赋。我只是强烈好奇。”
——阿尔伯特·爱因斯坦
毫无疑问,你最近到处都能看到这个短语,尤其是当它与数据科学家相关时。Frank Lo 描述了它的含义,并在几个月前发布的客座博客中谈到了其他必要的“软技能”。
好奇心可以被定义为获取更多知识的欲望。作为一名数据科学家,您需要能够提出有关数据的问题,因为数据科学家花费大约 80%的时间来发现和准备数据。这是因为数据科学领域是一个发展非常迅速的领域,您必须学习更多知识才能跟上步伐。
您需要通过在线阅读内容和阅读有关数据科学趋势的相关书籍来定期更新您的知识。不要被互联网上飞来飞去的大量数据淹没,你必须知道如何理解这些数据。好奇心是作为一名数据科学家取得成功所需的技能之一。例如,最初,您可能看不到您收集的数据中有多少洞察力。好奇心将使你能够筛选数据,找到答案和更多的见解。
11.商业头脑
要成为一名数据科学家,你需要对你所在的行业有一个扎实的了解,并且知道你的公司正在试图解决什么样的业务问题。就数据科学而言,除了确定企业应该利用其数据的新方法之外,能够辨别哪些问题对企业来说是重要的解决方案也是至关重要的。
要做到这一点,您必须了解您所解决的问题会如何影响业务。这就是为什么你需要了解企业是如何运作的这样你就可以把你的努力引向正确的方向。
12.通讯技能
寻找强大数据科学家的公司正在寻找能够清晰流利地将他们的技术发现翻译给非技术团队(如营销或销售部门)的人。数据科学家除了了解非技术同事的需求以便适当地争论数据之外,还必须通过用量化的见解武装他们来使企业能够做出决策。
除了使用公司理解的相同语言,你还需要通过使用数据故事来沟通。作为一名数据科学家,你必须知道如何围绕数据创建一个故事情节,让任何人都容易理解。例如,呈现一个数据表不如以讲故事的形式分享这些数据的见解有效。用讲故事的方式将有助于你恰当地向你的雇主传达你的发现。
交流时,注意你分析的数据中包含的结果和价值。大多数企业主不想知道你分析了什么,他们感兴趣的是它如何积极地影响他们的业务。学会专注于通过沟通传递价值和建立持久的关系。
13.协力
数据科学家不能独自工作。你必须与公司高管合作制定战略,与产品经理和设计师合作创造更好的产品,与营销人员合作开展更好的转化活动,与客户端和服务器软件开发人员合作创建数据管道并改善工作流程。你将不得不与组织中的每个人合作,包括你的客户。
本质上,您将与您的团队成员合作开发用例,以便了解解决问题所需的业务目标和数据。您需要知道处理用例的正确方法、解决问题所需的数据,以及如何将结果转换并呈现为每个相关人员都可以轻松理解的内容。
最后的想法

感谢您的阅读。
如果你被所需的技能弄得不知所措,这完全没关系(我也是!).
归根结底,这些技能并不是成为数据科学家的必备条件,但与其他典型的数据科学家相比,它们肯定会让你与众不同。
我知道你不是典型的。
一如既往,如果您有任何问题或意见,请随时在下面留下您的反馈,或者您可以随时通过 LinkedIn 联系我。在那之前,下一篇文章再见!😄
关于作者
阿德蒙德·李 目前是东南亚排名第一的商业银行 API 平台 Staq — 的联合创始人/首席技术官。
想要获得免费的每周数据科学和创业见解吗?
你可以在 LinkedIn 、 Medium 、 Twitter 、脸书上和他联系。
让每个人都能接触到数据科学。Admond 正在通过先进的社交分析和机器学习,利用可操作的见解帮助公司和数字营销机构实现营销投资回报。
www.admondlee.com](https://www.admondlee.com/)
数据可视化中的 16 种图表类型
看看下面的仪表盘,你知道有多少种图表吗?

From FineReport
在信息爆炸的时代,越来越多的数据堆积起来。然而,这些密集的数据是不集中的,可读性较差。所以我们需要数据可视化来帮助数据容易被理解和接受。相比之下,可视化更直观,更有意义,使用合适的图表来可视化数据是非常重要的。
在这篇文章中,我将介绍数据可视化中的 16 种图表类型,并分析它们的应用场景,以帮助您快速选择显示数据特征的图表类型。
注:文中所有图表均取自数据可视化工具 FineReport ,个人下载完全免费。
1.柱形图
柱形图使用垂直列来显示类别之间的数字比较,列数不能太多(如果列数太多,轴的标签可能会显得不完整)。

From FineReport
柱形图利用柱的高度来反映数据的差异,人眼对高度差异比较敏感。局限性是只适用于中小规模的数据集。

From FineReport
应用场景:分类数据对比
2.条形图
条形图类似于柱形图,但条形图的数量可能相对较多。与柱形图相比,其两个坐标轴的位置发生了变化。

From FineReport

From FineReport
应用场景:数据比较(类别名称可以长一点,因为 Y 轴上有更多的空间)
3.折线图
折线图用于显示连续时间间隔或时间跨度内的数据变化。它的特点是倾向于反映事物随时间或有序类别的变化。
需要注意的是,折线图的数据记录数应大于 2,可用于大数据量的趋势对比。并且在同一个图上最好不要超过 5 条折线。

From FineReport

From FineReport
应用场景:数据量随时间变化的趋势,序列趋势对比
4.对比图
面积图是在折线图的基础上形成的。它用颜色填充折线图中折线和轴之间的区域。颜色的填充可以更好的突出趋势信息。
面积图的填充颜色要有一定的透明度。透明度可以帮助用户观察不同系列之间的重叠关系。没有透明度的区域将导致不同的系列相互覆盖。

From FineReport

From FineReport
应用场景:序列比率,时间趋势比率
5.圆形分格统计图表
饼图广泛应用于各个领域,用来表示不同分类的比例,并通过弧线来比较各种分类。
饼图不适合多个系列的数据,因为随着系列的增加,每个切片都变小,最后大小区分不明显。

From FineReport
饼状图也可以做成多层饼状图,显示不同分类数据的比例,同时也反映出层次关系。

From FineReport
应用场景:数列比,数列大小比较(玫瑰图)
6.散点图
散点图在直角坐标系中以点的形式显示两个变量。点的位置由变量的值决定。通过观察数据点的分布,我们可以推断变量之间的相关性。
做散点图需要大量数据,否则相关性不明显。

From FineReport

From FineReport
应用场景:关联分析、数据分发
7.泡泡图
气泡图是一种多元图表,是散点图的变体。除了 X 轴和 Y 轴代表的变量值之外,每个气泡的面积代表第三个值。
我们要注意的是,气泡的大小是有限的,过多的气泡会使图表难以阅读。

From FineReport
应用场景:分类数据对比,关联分析
8.测量
数据可视化中的仪表是一种物化图。刻度代表公制,指针代表尺寸,指针角度代表数值。它可以直观地表示一个指标的进度或实际情况。
该量表适用于区间对比。

From FineReport
也可以做成环型或管型,标明比例。

From FineReport
应用场景:时钟、比率显示
9.雷达图
雷达图用于比较多个量化变量,比如看哪些变量有相似的值,或者是否有极值。它们还有助于观察数据集中哪些变量的值较高或较低。雷达图适用于展示工作表现。

From FineReport
雷达图还具有堆叠柱形图样式,可用于分类和系列之间的双向比较,同时也表示比例。

From FineReport
应用场景:维度分析、序列比较、序列权重分析
10.构架图解
框架图是以树形结构的形式呈现层次结构的可视化手段,它清晰地显示了层次关系。

From FineReport
应用场景:层级显示、流程显示
11.矩形树形图
矩形树形图适用于呈现具有层次关系的数据,可以直观地反映相同级别之间的比较。与传统的树形结构图相比,矩形树形图更有效地利用了空间,并具有显示比例的功能。
矩形树形图适用于显示具有权重关系的层次结构。如果不需要体现比例,框架图可能更清晰。

From FineReport
应用场景:加权树数据,树数据比例
12.漏斗图
漏斗图显示了每个阶段的比例,直观地反映了每个模块的大小。适合比较排名。

From FineReport
同时,漏斗图也可以用来对比。我们横向排列多个漏斗图,数据对比也很清晰。

From FineReport
应用场景:数据排名、比率、标准值比较
13.单词云图表
单词云是文本数据的可视化表示。它是由词汇组成的云状彩色图形。它用于显示大量文本数据,可以快速帮助用户感知最突出的文本。
单词云图要求数据量大,数据的区分度比较大,否则效果不明显。并且它不适合于精确分析。

From FineReport
应用场景:关键词搜索
14.线条图
甘特图直观地显示了任务的时间安排、实际进度以及与要求的比较。所以管理人员可以很容易地了解一项任务(项目)的进展。

From FineReport
应用场景:项目进度、状态随时间的变化、项目过程
15.地图
地图分为三种类型:区域地图、点地图和流程地图。
(1)区域地图
区域地图是一种使用颜色来表示地图分区上某个范围的值的分布的地图。

From FineReport
应用场景:数据对比和分发
(2)点地图
点地图是一种通过在地理背景上绘制相同大小的点来表示数据地理分布的方法。
点的分布便于把握数据的整体分布,但在需要观察单个具体数据时就不适合了。

From FineReport
应用场景:数据分发
但是如果你用气泡代替点,那么点地图不仅可以显示分布,还可以大致比较每个区域的数据大小。

From FineReport
(3)流程图
流图显示流出区域和流入区域之间的交互数据。通常用连接空间元素几何重心的线来表示。线条的宽度或颜色表示流量值。
流动地图有助于说明地理迁移的分布,动态流线的使用减少了视觉混乱。

From FineReport
应用场景:数据的流动、分布和比较
16.热图
热图用于指示地理区域中每个点的权重。除了地图作为背景层,你也可以使用其他图像。热图中的颜色通常是指密度。

From FineReport
应用场景:区域访问,热度分布,各种东西的分布
终于
以上是数据可视化中 16 种常用的图表类型。如果你想开始数据可视化,我建议你从学习制作这些基本图表开始,用一个像 FineReport 这样简单易用的工具练习。
可能有人会觉得基础图表太简单原始,倾向于使用更复杂的图表。但是,图表越简单,越容易帮助人们快速理解数据。这难道不是数据可视化最重要的目的吗?所以请不要小看这些基础图表。因为用户对它们最熟悉。只要它们适用,就应该优先考虑。
您可能也会对…感兴趣
初学者如何设计酷的数据可视化?
原载于 2019 年 7 月 22 日http://www.finereport.com。
20 大码头安全提示
瞄准安全!
这篇文章充满了帮助你安全使用 Docker 的技巧。如果你是 Docker 新手,我建议你先看看我以前的文章,关于 Docker 概念,Docker 生态系统,Docker 文件,瘦身图片,流行命令,以及 Docker 中的数据。

你需要对 Docker 的安全性有多担心?看情况。Docker 内置了明智的安全特性。如果您使用的是官方 Docker 映像,并且不与其他机器通信,您就没有太多需要担心的。
然而,如果你在生产中使用非官方图像、服务文件或运行应用程序,那么情况就不同了。在这些情况下,你需要对 Docker 安全有更多的了解。

Looks safe
您的主要安全目标是防止恶意用户获取有价值的信息或造成破坏。为此,我将在几个关键领域分享 Docker 安全最佳实践。在这篇文章结束时,你会看到超过 20 个 Docker 安全提示!😃
在第一部分中,我们将重点关注三个方面:
- A 门禁管理
- 我法师安全
- 秘密的管理
想出首字母缩写 AIM 来帮助你记住它们。
首先,让我们看一下限制容器的访问。
访问管理—限制权限
当您启动一个容器时,Docker 会创建一组名称空间。命名空间防止容器中的进程看到或影响主机中的进程,包括其他容器。名称空间是 Docker 将一个容器与另一个容器隔离开来的主要方式。
Docker 也提供私有容器网络。这可以防止容器获得对同一主机上其他容器的网络接口的特权访问。
因此,Docker 环境在某种程度上是隔离的,但对于您的用例来说,它可能还不够隔离。

Does not look safe
良好的安全性意味着遵循最低特权原则。你的容器应该有能力做它需要做的事情,但除此之外不能有更多的能力。棘手的是,一旦你开始限制哪些进程可以在一个容器中运行,这个容器可能就不能做它应该做的事情了。
有几种方法可以调整容器的权限。首先,避免以 root 身份运行(如果必须以 root 身份运行,则重新映射)。第二,用--cap-drop和--cap-add调整能力。
避免 root 和调整功能应该是大多数人限制特权所需要做的。更高级的用户可能需要调整默认的 AppArmor 和 seccomp 配置文件。我将在我即将出版的关于 Docker 的书中讨论这些问题,但是为了防止这篇文章膨胀,我将它们排除在外。🎈
避免以 root 用户身份运行
Docker 的默认设置是让映像中的用户以 root 身份运行。很多人没有意识到这有多危险。这意味着攻击者更容易获得敏感信息和您的内核。
作为一般的最佳实践,不要让容器以 root 用户身份运行。

Roots
“防止来自容器内部的特权提升攻击的最佳方式是将容器的应用程序配置为以无特权用户的身份运行。”——DockerDocs。
您可以在构建时指定一个不同于 root 的用户 id,如下所示:
docker run -u 1000 my_image
-- user或-u标志可以指定用户名或用户标识。userid 不存在也没问题。
在上面的例子中, 1000 是一个任意的、无特权的用户标识。在 Linux 中,通常保留 0 到 499 之间的 userids。选择一个大于 500 的 userid,以避免作为默认系统用户运行。
不要从命令行设置用户,最好在您的映像中从 root 更改用户。那么人们就不必记得在构建时更改它。只需在您的映像中将用户 Dockerfile 指令放在需要 root 自带功能的 Dockerfile 指令之后。
也就是说,先安装你需要的包,然后切换用户。例如:
FROM alpine:latest
RUN apk update && apk add --no-cache git
USER 1000
…
如果您必须以 root 用户的身份在容器中运行流程,请将 root 用户重新映射到 Docker 主机上权限较低的用户。参见对接文件。
您可以通过改变功能来授予用户所需的权限。
能力
能力是允许的过程的捆绑。
使用--cap-drop和--cap-add通过命令行调整功能。最好的策略是用--cap-drop all放弃一个容器的所有特权,用--cap-add重新添加需要的特权。

Stop or go
您可以在运行时调整容器的功能。例如,要放弃使用kill来停止容器的功能,您可以像这样删除默认功能:
docker run --cap-drop=Kill my_image
避免给进程赋予 SYS_ADMIN 和 SETUID 特权,因为它们被赋予了很大的权力。向用户添加这种能力类似于授予 root 权限(避免这种结果就是不使用 root 的全部意义)。
不允许容器使用 1 到 1023 之间的端口号更安全,因为大多数网络服务都在这个范围内运行。未经授权的用户可以监听诸如登录和运行未经授权的服务器应用程序之类的事情。这些编号较低的端口需要以 root 用户身份运行,或者被明确授予 CAP_NET_BIND_SERVICE 功能。
要了解容器是否有特权端口访问,可以使用 inspect 。使用docker container inspect my_container_name将向您显示关于您的容器的已分配资源和安全配置文件的许多细节。
这里是 Docker reference 了解更多特权。
和 Docker 中的大多数东西一样,最好在一个自动的、自我文档化的文件中配置容器。使用 Docker Compose,您可以在服务配置中指定如下功能:
cap_drop: ALL
或者您可以在 Kubernetes 文件中调整它们,如这里讨论的。
Linux 功能的完整列表在这里。
如果你想对容器特权进行更细粒度的控制,可以在我即将出版的书中查看我对 AppArmor 和 seccomp 的讨论。订阅我的电子邮件简讯以便在有消息时得到通知。

Closed road
访问管理—限制资源
限制容器对内存和 CPU 等系统资源的访问是一个好主意。如果没有资源限制,容器可以用尽所有可用的内存。如果发生这种情况,Linux 主机内核将抛出内存不足异常并终止内核进程。这会导致整个系统崩溃。你可以想象攻击者如何利用这些知识来关闭应用程序。
如果在同一台机器上运行多个容器,明智的做法是限制任何一个容器可以使用的内存和 CPU。如果你的容器内存不足,那么它就会关闭。关闭你的容器会导致你的应用崩溃,这可不好玩。然而,这种隔离保护了主机不会耗尽内存,也保护了主机上的所有容器不会崩溃。这是件好事。

Wind resource
Docker Desktop CE for Mac v2.1.0 有默认的资源限制。您可以在 Docker 图标->首选项下访问它们。然后点击资源选项卡。您可以使用滑块来调整资源限制。

Resource settings on Mac
或者,您可以从命令行限制资源,方法是指定--memory标志或简称为-m,后跟一个数字和一个度量单位。
4m 表示 4 兆字节,是最小容器内存分配。一兆字节(MiB)略大于一兆字节(1 兆字节= 1.048576 MB)。文档目前是不正确的,但是希望在你读到这篇文章的时候,维护者已经接受了我的修改。
要查看您的容器正在使用哪些资源,请在新的终端窗口中输入命令[docker stats](https://deploy-preview-9237--docsdocker.netlify.com/config/containers/runmetrics/)。您将看到正在运行的容器统计数据定期刷新。

Stats
在幕后,Docker 使用 Linux 控制组(cgroups)来实现资源限制。这项技术经过了实战考验。
点击了解更多关于 Docker 资源限制的信息。
图像安全
从 Docker Hub 抓取图像就像邀请某人到你家一样。你可能想要故意的。

Someone’s home
使用值得信赖的图片
图像安全的第一条规则是只使用你信任的图像。你怎么知道哪些图片是可信的?
很有可能流行的官方图片相对安全。这样的映像包括 alpine、ubuntu、python、golang、redis、busybox 和 node。每个网站都有超过 1000 万的下载量和大量的关注。🔒
Docker 赞助了一个专门的团队,负责审查和发布官方图片中的所有内容。该团队与上游软件维护人员、安全专家和更广泛的 Docker 社区合作,以确保这些图像的安全性。
减少你的攻击面
与使用官方基础映像相关,您可以使用最小基础映像。
内部代码越少,出现安全漏洞的几率就越低。较小、不太复杂的基础图像更透明。
比起你的朋友的图像依赖于她的朋友的图像依赖于另一个基础图像,在高山图像中看到发生了什么要容易得多。短的线更容易解开。

Tangled
类似的,只安装自己实际需要的包。这减少了您的攻击面,加快了您的图像下载和图像构建。
需要签名的图像
您可以通过使用 Docker 内容信任来确保对图像进行签名。🔏
Docker 内容信任阻止用户使用标记图像,除非它们包含签名。可信来源包括来自 Docker Hub 的官方 Docker 图像和来自用户可信来源的签名图像。

Signed
默认情况下,内容信任被禁用。要启用它,请将 DOCKER_CONTENT_TRUST 环境变量设置为 1。从命令行运行以下命令:
export DOCKER_CONTENT_TRUST=1
现在,当我试图从 Docker Hub 下载我自己的未签名图像时,它被阻止了。
Error: remote trust data does not exist for docker.io/discdiver/frames: notary.docker.io does not have trust data for docker.io/discdiver/frames
内容信任是将痞子拒之门外的一种方式。点击了解更多关于内容信任的信息。
Docker 通过图像内容的加密校验和来存储和访问图像。这可以防止攻击者造成图像冲突。这是一个很酷的内置安全功能。
管理秘密
您的访问受到限制,您的图像是安全的,现在是时候管理您的秘密了。"
管理敏感信息的规则 1:不要把它放进你的映像中。在代码库、日志和其他地方找到未加密的敏感信息并不困难。
规则 2:也不要为你的敏感信息使用环境变量。任何能把docker inspect或exec跑进集装箱的人都能找到你的秘密。任何以 root 用户身份运行的人也可以。希望我们已经配置好了,这样用户就不会以 root 身份运行,但是冗余是良好安全性的一部分。日志通常也会转储环境变量值。你不希望你的敏感信息泄露给任何人。
Docker 卷更好。它们是访问 Docker 文档中您的敏感信息的推荐方式。您可以将卷用作内存中的临时文件系统。卷消除了docker inspect和日志记录风险。然而,根用户仍然可以看到这个秘密,任何能够进入容器的人也可以看到。总的来说,卷是一个很好的解决方案。
比卷更好的是,使用 Docker 秘密。秘密是加密的。

Secrets
一些 Docker 文档声明你只能在 Docker Swarm 中使用秘密。尽管如此,你可以在 Docker 中使用秘密而不用 Swarm。
如果您只需要图像中的秘密,您可以使用 BuildKit。对于构建 Docker 映像,BuildKit 是比当前构建工具更好的后端。它大大减少了构建时间,并且有其他好的特性,包括构建时秘密支持。
BuildKit 相对较新——Docker Engine 18.09 是附带 BuildKit 支持的第一个版本。有三种方法可以指定 BuildKit 后端,这样现在就可以使用它的特性了。将来,它将是默认的后端。
- 用
export DOCKER_BUILDKIT=1将其设置为环境变量。 - 用
DOCKER_BUILDKIT=1启动你的build或run命令。 - 默认情况下启用 BuildKit。用
{ "features": { "buildkit": true } }将/etc/docker/daemon . JSON中的配置设置为 true 。然后重启 Docker。 - 然后,您可以在构建时使用带有
--secret标志的秘密,如下所示:
docker build --secret my_key=my_value ,src=path/to/my_secret_file .
其中您的文件将您的秘密指定为键值对。
这些秘密不会存储在最终图像中。它们也被排除在映像构建缓存之外。安全第一!
如果您需要在运行容器中使用您的秘密,而不仅仅是在构建图像时,请使用 Docker Compose 或 Kubernetes。
使用 Docker Compose,将 secrets 键-值对添加到服务中,并指定机密文件。帽子提示到栈交换答案为 Docker 编写秘密提示,下面的例子是改编自。
带有秘密的 docker-compose.yml 示例:
version: "3.7"
services:
my_service:
image: centos:7
entrypoint: "cat /run/secrets/my_secret"
secrets:
- my_secret
secrets:
my_secret:
file: ./my_secret_file.txt
然后用docker-compose up --build my_service照常开始作曲。
如果你用的是 Kubernetes,它支持秘密。头盔-秘密可以让 K8s 中的秘密管理更加容易。此外,K8s 具有基于角色的访问控制(RBAC),Docker Enterprise 也是如此。RBAC 使团队的访问机密管理更易管理,更安全。
使用机密的最佳实践是使用诸如 Vault 之类的机密管理服务。 Vault 是 HashiCorp 提供的一项服务,用于管理对秘密的访问。它也限制了秘密的时间。更多关于 Vault 的 Docker 图像的信息可以在这里找到。
AWS Secrets Manager 和其他云提供商的类似产品也可以帮助您在云上管理您的秘密。

Keys
记住,管理你的秘密的关键是保密。绝对不要把它们放进你的图像或者变成环境变量。
更新内容
与任何代码一样,保持映像中的语言和库是最新的,以便从最新的安全修复中受益。

Hopefully your security is more up to date than this lock
如果您在映像中引用基础映像的特定版本,也要确保它是最新的。
与此相关的是,您应该保持 Docker 版本的更新,以获得 bug 修复和增强,从而允许您实现新的安全特性。
最后,让您的主机服务器软件保持最新。如果您运行的是托管服务,这应该是为您完成的。
更好的安全性意味着保持更新。
考虑一下 Docker 企业
如果您有一个由一群人和一堆 Docker 容器组成的组织,那么您很可能会从 Docker Enterprise 中受益。管理员可以为所有用户设置策略限制。所提供的 RBAC、监控和日志记录功能可能会使您的团队更容易进行安全管理。
有了 Enterprise,你还可以在 Docker 信任的注册表中秘密托管你自己的映像。Docker 提供内置的安全扫描,以确保您的图像中没有已知的漏洞。
Kubernetes 免费提供了部分功能,但是 Docker Enterprise 为容器和图像提供了额外的安全功能。最棒的是, Docker Enterprise 3.0 于 2019 年 7 月发布。它包括 Docker Kubernetes 服务与“明智的安全默认值”。
其他提示
- 不要以
-- privileged的身份运行容器,除非你需要在 Docker 容器中运行 Docker 这样的特殊情况——并且你知道你在做什么。 - 在你的 docker 文件中,支持 COPY 而不是 ADD。添加自动提取压缩文件,并可以从网址复制文件。COPY 不具备这些能力。尽可能避免使用 ADD,这样就不会受到远程 URL 和 Zip 文件的攻击。
- 如果您在同一服务器上运行任何其他进程,请在 Docker 容器中运行它们。
- 如果您使用 web 服务器和 API 来创建容器,请仔细检查参数,以便不会创建您不想要的新容器。
- 如果您公开一个 REST API,用 HTTPS 或 SSH 保护 API 端点。
- 考虑与码头工人安全工作台进行一次检查,看看你的集装箱在多大程度上遵循了他们的安全准则。
- 仅将敏感数据存储在卷中,不要存储在容器中。
- 如果使用联网的单主机应用程序,不要使用默认的桥接网络。它存在技术缺陷,不建议用于生产。如果您发布一个端口,桥接网络上的所有容器都可以访问。
- 使用加密 HTTPS 证书进行服务。在这里可以看到 NGINX 的例子。
- 当您只需要读取卷时,以只读方式装载卷。在这里看到几种做这个的方法。
摘要
你已经看到了许多使你的码头集装箱更安全的方法。安全没有设置-它和忘记它。它需要保持警惕,以保持您的图像和容器的安全。

Keys
考虑安全性时,请记住目标
- A 访问管理
- 避免以 root 用户身份运行。如果必须使用根目录,请重新映射。
- 放弃所有功能,添加那些需要的功能。
- 如果您需要细粒度的权限调优,请深入研究 AppArmor。
- 限制资源。
2.我法师安全
- 使用官方的、流行的、最简单的基础图片。
- 不要安装你不需要的东西。
- 要求对图像签名。
- 随时更新 Docker、Docker 图像和其他与 Docker 相关的软件。
3.秘密的管理
- 使用秘密或卷。
- 考虑像 Vault 这样的秘密管理器。

Bullseye!
保持码头集装箱安全意味着以安全为目标。
不要忘记更新 Docker、你的语言和库、你的图像和你的主机软件。最后,如果你作为团队的一员运行 Docker,考虑使用 Docker Enterprise。
我希望这篇 Docker 安全文章对您有所帮助。如果你有,请在你最喜欢的论坛或社交媒体渠道上与他人分享,这样你的朋友也可以找到它!👏
你有其他 Docker 安全建议吗?如果有,请在评论中或在 Twitter @discdiver 上分享。👍
如果你有兴趣在我的难忘的 Docker 书发布时得到通知,那就注册我的邮件列表。
我写关于 Python、数据科学、人工智能和其他技术主题的文章。如果你对这些感兴趣的话,可以在 Medium 上看看它们。
安全快乐!😃
来自《走向数据科学》编辑的注释: 虽然我们允许独立作者根据我们的 规则和指南 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
最常用的 20 个 Git 命令

嘿,你是新来的吗?如果是的话,你已经迟到了,你应该昨天就知道了。但是不要担心,现在还不算太晚。
甚至我们大多数人都听说过 Git,但是仍然有许多人可能不知道如何使用它。在本指南结束时,您将知道 Git 中几个最常用的命令。
Git |简介
Git 是一个分布式版本控制系统(DVCS ),用于跟踪源代码中的变化,但是它也可以用于跟踪任何一组文件中的变化。
- 中央版本控制系统(CVCS)
- 分布式版本控制系统(DVCS)
- Git 命令
版本控制系统
版本控制系统是对文档、计算机程序、大型网站和其他信息集合的更改的管理。市场上有许多版本控制系统,但通常分为两类,即中央版本控制系统和分布式版本控制系统。
中央版本控制系统(CVCS):
中央版本控制系统(CVCS)是某处(可能在服务器上)的单个存储库或项目副本,开发人员将他们的更改提交到该存储库中。同时,对这个存储库所做的更改对其他开发人员也是可见的。

Image by http://guides.beanstalkapp.com
分布式版本控制系统(DVCS):
分布式版本控制系统(DVCS)也是一个版本控制系统,其中每个开发人员的硬盘上都有完整的代码库和完整的版本历史。在没有上传到服务器之前,任何人都看不到对此本地存储库所做的更改。

Image by http://guides.beanstalkapp.com
Git 术语
- 存储库:存储库是存储和管理数据的中心位置。
- 提交:提交是永久保存更改的操作。
- Staging Area: Staging 是 git 中提交流程之前的一个步骤。也就是说,git 中的提交分两步执行:准备和实际提交。
- 推送:****git 推送命令用于将本地存储库内容上传到远程存储库。
- Pull:****git Pull命令用于从远程存储库获取和下载内容,并立即更新本地存储库以匹配该内容。
- 远程服务器:远程服务器是一种不在局域网上的服务器,它为全球的用户提供数据服务。
- 分支:分支就像你的项目的目录,里面包含了所有的文件。Git 存储库总是创建默认的分支,称为主分支。
- 克隆:克隆是创造某物的复制品的过程。
我们将看到一个如何将本地存储库推送到远程服务器的实例。我会演示给你看,现在我们开始吧。
第一步
首先移动到您的项目所在的目录,因为我的项目位于 PycharmProjects/git_commands 中,所以现在打开您的终端并运行下面的命令到达那里。

如果你想看到你的项目目录中的文件,然后输入下面的命令。

As you can see there is only single file inside my git_commands folder.
第二步
一旦你进入你的项目目录,现在我们将在 Bitbucket 上创建我们的远程存储库,你可以使用 Github 来代替。现在打开你的浏览器,输入 bitbucket,如果你没有 Bitbucket 账户,那么你必须创建一个。点击此链接 bitbucket 创建账户或登录 bitbucket。
要创建新的存储库,请单击+按钮并选择存储库

现在给你的库命名,就像我给 GitTutorial 一样,你可以给任何你想要的名字。然后点击高级设置,选择你正在使用的语言,一切保持原样,最后点击创建库。您将看到新的存储库将在您的 Bitbucket 帐户上创建。创建存储库后,您的帐户将如下所示。

Repository created with name GitTutorial
第三步
git config: 使用 git config 命令设置系统的全局变量。 git config 命令是一个方便的功能,用于在全局或本地项目级别设置 Git 配置值。转到您的终端,键入下面的命令如下。

git Config
git init: 该命令用于初始化系统上的本地存储库

git init
git remote: 这个命令用于将您的本地存储库连接到远程服务器。
现在,我们将添加我们的远程存储库的连接,以便我们可以将我们的代码库推送到 Bitbucket。现在,从 Bitbucket 复制远程存储库的链接,并将其粘贴到终端。

git 状态:该命令列出了所有必须提交的文件。如下图所示, calculator.py 标记为红色,表示该文件尚未提交,需要提交。

git add:****git add命令将工作目录中的更改添加到登台区。它告诉 Git 您想要在下一次提交中包含对特定文件的更新。在我的例子中, calculator.py 文件被添加到暂存区。如果您有多个文件要添加,那么您可以使用 **git add *** 。

git add
git commit:gitcommit命令用于将您的更改保存到本地存储库。git commit-m[键入提交消息]

git commit
git log: 这个命令用来告诉我们提交记录。请参见下图,只有一次提交,这就是为什么它只显示“初始提交”消息以及提交内容的 SHA1 40 字符校验和。

git log
如果您重新运行 git commit 命令,它会告诉我们,自从上次提交以来,我们没有对文件进行任何更改,所以没有什么要提交的。

git branch: 如果您在终端中运行这个命令,那么它将显示所有的分支,默认情况下它只有主分支。下图中 master 前面的星号*表示您目前在 master 分支机构中。如果您想要创建新的分支,那么您可以运行 git branch [branch name]。在我的例子中,我创建了名为子主的分支。

git branch
git checkout: 该命令用于切换分支。即使创建新分支后,你仍然在主分支中。如果你想在分支之间切换,你可以运行 git checkout【分支名称】命令。正如您在下图中看到的,我们从主分支切换到子主分支,子主前面的星号( ***** )告诉我们当前在子主分支中。

Switched from master branch to sub-master branch
git push:****git push命令用于将本地存储库内容上传到远程存储库。推送是将提交从本地存储库转移到远程存储库的方式。在下图中,我们的本地存储库已经被复制到远程存储库。

git push — f origin master
正如你在给定的图片中看到的“calculator.py”文件成功上传到 Bitbucket 存储库,它只有一个功能。现在我们将修改这个文件,并向它添加更多的函数,然后我们将看到这个文件如何在我们的远程服务器上更新。让我们开始吧。

“Calculator.py” is on the remote server now
如果您现在运行 git status 命令,它会告诉您自上次提交以来,您对文件做了一些更改。如您所见,Calculator.py 文件是修改后的文件。

现在,我们将再次重复相同的过程,将此更改推送到我们的远程服务器。我们将把这个文件从项目目录添加到临时区域,然后提交更改,最后我们将推送它。

Code pushed to the server.

Bitbucket Repo
git show: 该命令显示指定提交的元数据和内容变化。

git clone: 该命令用于将存储库从远程服务器克隆到本地机器。
要使用这个命令,我建议您在系统上的任意位置创建新文件夹,然后运行 git clone 命令。如你所见,我在桌面上创建了一个名为 git_clone 的新文件夹。现在,从 Bitbucket 复制远程存储库 URL,并将其粘贴到终端。

现在打开 git_clone 文件夹,您将看到项目下载到文件夹中。

git pull: 这个命令获取并合并远程服务器上的更改到您的工作目录中。要使用这个命令,请转到 git_commands 目录,然后运行 git pull 命令。正如你所看到的,我们的项目已经是最新的,所以没有新的获取和合并。

git 复位:该命令用于撤销对 Git repo 状态的本地更改。
git diff: 该命令显示尚未暂存的文件差异。
git stash: git stash 用于临时存储修改后的文件。
git 复位:该命令用于撤销对 Git repo 状态的本地更改。
这个命令从你的工作目录中删除这个文件,并且分阶段删除。
git 标签:该命令用于给指定的提交赋予标签。
git merge: 该命令将指定分支的历史合并到当前分支中。
资源:
- Git 源代码
Git 源代码镜像——这是一个只发布的库,所有的拉请求都会被忽略。请跟随…
github.com](https://github.com/git/git)
- 源代码树
[## 用于 Mac 和 Windows 的免费 Git GUI
作为我们新的比特桶空间站管理员,你需要有条理。当你为你的空间站制作文件时…
www.sourcetreeapp.com](https://www.sourcetreeapp.com/)
总结
- CVCS 将其所有项目文件保存在一个地方。并且在进行项目时需要在线。
- DVCS 工作在分布式模式,每个开发人员从远程服务器克隆项目,并在他们的本地机器上工作,所以他们不需要在线。
- 推、拉和合并命令允许我们上传、下载和合并我们的项目。
我希望你喜欢读这篇文章,你也可以访问我的 网站 ,在那里我会定期发布文章。
订阅 我的邮件列表,直接在您的收件箱中提前获得我的文章,或者关注我自己在 Medium 上发表的文章The Code Monster以完善您的技术知识。
了解你的作者
希曼舒·维尔马毕业于印度勒克瑙的 APJ 阿卜杜勒·卡拉姆大学博士。他是 Android & IOS 开发人员、机器学习和数据科学学习者、金融顾问和博客作者。
如果你有一个严厉的老板,三条建议
我希望我能早点知道的经验教训
我数据科学实习的真实故事

当我试图开始我的数据科学之旅时,我尝试了许多方式来提交我的简历,只是为了一个开始数据科学实习的机会。然而,无论我如何努力,由于缺乏专业技能,我仍然无法进入那个领域。
我很难过。
在我快要放弃的时候,朋友分享了一个全职的数据科学实习,叫我去试一试。
我答应了!
一定,我会试试!
那真是我成功的大好机会。尽管我刚刚递交了简历,甚至还没有接到面试的电话,但我已经开始准备了。几天后,我收到了我渴望已久的电子邮件。采访是在几周后进行的。
面试那天,我准备了很多项目来给面试官留下深刻印象,但最后,面试官的主要关注点变成了寻找一个对学习有很好态度的人。
你说得对,我得到了实习机会,这段经历的确成为我一生中最难忘的实习经历。
给了我一台 mac 台式机,我甚至不知道如何使用 Mac,但我很感激,给了我足够的时间来学习。你想知道我第一个月的经历吗?我可以告诉你,在我的第一个月,我所做的只是开始熟悉自己使用 mac,mac 终端,并阅读文档,希望让自己有一个良好的开端。

是的,实际上我在第一个月并没有非常努力地工作,这就是为什么我觉得我在第二个月几乎无法生存。我开始接受大量的工作,为了完成给定的任务,我开始被逼得很紧。我仍然记得,在我第二个月的每一天,我都需要至少工作到凌晨 12 点,非常努力地修复抓取整个网站时给定任务的所有错误(那时我完全是一个网络爬行新手),希望我能够达到他或她的期望。
作为一个人,休息是必不可少的,很快,我开始感到筋疲力尽。我觉得我总是背着一块大石头,这让我觉得只想在家休息一下。我的大脑不断告诉我退出,“这只是一个实习,退出吧!”。
经过一年的工作经验,以下是我想与你们分享的前三条建议或想法!
如果一个老板愿意把你推到极限,他或她被认为是一个好老板。
不是每个老板都愿意花精力去培训或督促你。你的老板没有责任培训你,他或她可以让你做一些简单的工作,这样他或她就有更多的时间专注于他或她的工作。
此外,如果你的老板不仅愿意推动你,而且在你希望在职业生涯中拥有的领域也非常强大,那么一定要珍惜这个机会。
例如,也许你是一家公司的数据科学家,你希望提高自己的技术技能。然而,你的老板更擅长使用 powerpoint/Excel 提供数据见解,那么你也许可以考虑为你的职业生涯做出改变。

更严格的老板会迫使你更加独立
在我实习期间,我每天只有两次提问的机会。此外,我的老板要求我在问任何问题之前至少连续搜索 2 小时的答案。起初,我真的很沮丧,但渐渐地我能理解老板的意图,把我塑造成一个能独立工作的人。
有时候,我被分配了一项任务,要在一天结束前完成,但实际上,我的大部分时间都用在了连接服务器上。这是因为他们的服务器位于新加坡之外,他们有自己的 Bash 脚本来连接服务器。给的任务已经很有挑战性了,再加上你大部分时间都用来连接服务器,这的确会让你变得更有压力。
如你所知,解决问题的技能是这个行业非常需要的技能之一。拥有这项技能一定会让你成为一个很抢手的人。
不要害怕你严厉的老板,要更加积极主动
这是我的老板在我的实习结束后给我的建议之一——要更加积极主动。
你可能会想,什么?
我的老板已经这么严格了,而我没有多少时间来完成我的任务,你却告诉我要更加积极主动?
不要等着你的老板给你如何解决任务的指示,你应该更积极主动地测试你的一些方法或目的你的老板一些你认为可行的解决方案,然后寻求指导。
相反,这不仅会减少老板要做的工作,还会展示你解决问题的能力。

最后的想法
真的希望这篇文章将有利于你在任何方面。请记住:
不要挑工作。选一个老板。你的第一个老板是你事业成功的最大因素。—威廉·拉杜切尔
如果你的老板是一个严格的老板,不要害怕,相反,要更加积极主动,尽可能多地学习。我向你保证,你会发现你在短时间内提升自己的速度有多快!
关于作者
Low 魏宏是 Shopee 的数据科学家。他的经验更多地涉及抓取网站,创建数据管道,以及实施机器学习模型来解决业务问题。
他提供爬行服务,能够为你提供你所需要的准确和干净的数据。你可以访问 这个网站 查看他的作品集,也可以联系他获得的抓取服务。
在媒体上阅读低纬鸿的作品。数据科学家|网络搜集服务:http://datainfinite.mystrikingly.com/…
medium.com](https://medium.com/@lowweihong?source=post_page-----c934d55f9c9a----------------------)
你不知道的熊猫的三大功能(大概)
我以前写过关于熊猫的文章,原因很明显——它是一个用于数据分析甚至数据可视化的惊人的库。前一篇文章介绍了一些您应该经常使用的函数,因为它们:
- 会让你的代码保持干净
- 不会让你重新发明轮子

Photo by Tanner Boriack on Unsplash
如果你错过了它,这里有一个链接,这样你就可以在有时间的时候保存它:
停止重新发明轮子。说真的。
towardsdatascience.com](/3-pandas-functions-you-should-be-using-more-often-696b41e8d7ca)
然而,在今天的帖子中,我想把注意力转移到几个更有用的功能上,这些功能让我觉得自己在工作中完全是个白痴。你可能会问,这是为什么。嗯,我很懒,在我写代码之前我不喜欢谷歌,所以我甚至不知道这些功能的存在。
最后的结果至少可以说是令人沮丧的。我成功地实现了所需的逻辑,但代价是几个小时,一把新的白发,当然,还有许多不必要的代码。
为了避免同样的事情发生在你身上,请继续阅读。
idxmin()和 idxmax()
是的,我知道我在过去已经报道过这些,但是它们是这篇文章的本质。你先不理解这几个就不会理解第二个有用的功能,那就言归正传吧。
简而言之,这些函数将返回所需条目的 ID ( 索引位置)。假设我创作了以下熊猫系列:

并希望找到最小和最大项目的索引位置。当然,仅仅通过观察不难发现这一点,但是你绝不会(我是说绝不会)在你的项目上有这么少的数据点。
这意味着您需要利用 idxmin() 和 idxmax() 函数的能力,让我们看看如何实现:


请记住,这些函数将返回最小/最大值第一次出现的索引。
ne()
这个对我来说是一个大发现。不久前,我在工作中处理一些时间序列数据,遇到了第一个 n 观测值为 0 的问题。
为了简单起见,想想你可能已经买了东西,但一段时间内没有消费掉。该物品在您手中,但由于您没有使用它,在给定日期的消费为 0。因为我只对你真正开始使用这该死的东西时的用法感兴趣,【ne()就是那个拯救了你的功能。
让我们考虑下面的场景。你有一个 Pandas DataFrame 对象,它的一些观察值在开始时为 0:

现在 ne() 要做的是,如果当前值不是您指定的值(假设为 0 ),则返回 True ,否则返回 False :

这本身没多大用处。你还记得我说过你需要知道 idxmax()来理解这一点吗? 好吧,我没有说谎,你可以从上面的代码链 idxmax() :

所以在索引位置 6,我们有第一个非零观测值。这又一次没有给你提供多少价值。好的一面是,我们可以使用该信息对数据帧进行子集化,以仅显示从项目第一次使用时开始的值:

当你处理时间序列数据的时候,这就派上用场了。
nsmallest()和 nlargest()
我猜你可以从名字中推断出这两个函数是关于什么的。假设我创建了下面的 DataFrame 对象:

为了好玩,让我们假设这 5 个是在编写测试后观察到的分数。您有兴趣找出哪 3 名学生表现最差:

或者哪三个学生表现最好:

这两个函数是像sort _ values()这样的函数的绝佳替代品。
在你走之前
随着时间的推移,我相信我会遇到更多值得在文章中提及的节省时间的功能,所以你肯定会看到更多这样的帖子。同时,请在评论区分享你最喜欢的熊猫功能。
感谢阅读。保重。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
你不知道(可能)的 4 大 Numpy 函数
在今天的文章中,我想讨论几个我日常用于数据分析的基本 Numpy 函数。无论如何,这不是一个全面的列表,但它足以让你开始,我相信它们会很适合你。

Photo by Nadine Shaabana on Unsplash
我甚至不知道自己思考了多少次“我需要实现的东西并不那么简单,不可能存在预建的函数”。我常常是错的。Pure Numpy 是如此强大,我将冒险让你不知道它所提供的一切。
我以前写过一些很棒但不太为人所知的熊猫的功能,它们将为你节省大量时间,所以如果你每天都在使用熊猫,一定要看看这些功能:
为我节省了大量时间和挫折的功能
towardsdatascience.com](/top-3-pandas-functions-you-dont-know-about-probably-5ae9e1c964c8)
所以,事不宜迟,让我们开始吧。您需要的唯一导入是 Numpy:

哪里()
where() 函数将从数组中返回满足特定条件的元素。下面我们用一个例子来探讨一下。
我将声明某种等级的数组(实际上是任意的):

您现在可以使用 where() 来查找所有大于 3 的成绩:

注意它如何返回索引位置。
派对不止于此,朋友,你可以提供两个额外的参数:
- 第一个将替换满足给定条件的值
- 第二个当然会替换那些不满足条件的

因为我想保持文章的简洁,我认为这将会给你足够的时间继续自己的探索。
argmin(),argmax(),argsort()
好吧,这些花哨的名字是怎么回事?
这里没有什么特别的东西,但是如果你不想自己实现这个逻辑的话,这三个函数会非常适合你。
argmin() 函数将返回最小值的索引。在我们之前使用的同一个数组上,它将返回最小值的索引位置:

您猜对了, argmax() 会执行相反的操作—返回最大值的索引:

另一个漂亮的函数是 argsort() ,它将返回一个排序数组的索引。这在很多情况下都会派上用场:

交叉 1d()
intersect 1d()函数将做的是,它将返回两个数组的交集,即两个数组中的公共项。与前面的函数不同,它不会返回索引位置,而是返回实际值。
首先,让我们声明两个有一些共同元素的数组:

现在,您可以使用上面提到的函数来查找共有元素:

allclose()
最后,但绝不是最不重要的,是 allclose() 函数。如果两个数组中的项在容差范围内相等,它将返回 True。它将为您提供一种检查两个数组是否相似的好方法,在某些情况下,手动实现这两个数组是很痛苦的。
首先,我将声明两个列表,并确保各个项目的差异在任何地方都不大于 0.2:

如果我现在调用公差为 0.1 的 allclose() 函数,它应该返回 False:

但是如果我决定将阈值改为 0.2,它应该返回 True:

在你走之前
很多次,我都有(有时仍然)重新发明轮子的罪恶感。人们很容易认为你的问题是独一无二的,没有人想到要创造一个函数来解决它。虽然在某些情况下这可能是真的,但更多的时候,当你为过去几个小时一直手动实现的东西找到一个预制函数时,你会觉得自己像个十足的傻瓜。
确保你意识到你正在使用的图书馆的力量,它们如此受欢迎是有原因的。
感谢阅读。保重。
广泛用于数据可视化的五大 BI 工具
商业智能(BI)——这个话题在商业领域已经讨论了很长时间。几乎所有类型的企业都相信好的商务智能工具的潜力,并使用它们来改善他们的业务。随着商业智能现象的兴起,先进的商业智能工具和技术被大量引入。这使得市场上为客户提供了许多潜在高效的 BI 工具。
今天,我将分享商业智能领域顶级玩家的详细信息,这意味着用于数据可视化的顶级 BI 工具。让我们从数据可视化的介绍开始讨论。

什么是数据可视化?
**术语商业智能是指用于收集、整合、可视化和分析原始数据的工具和技术的统称。在当今时代,随着自由流动数据量的不断增加,高效的 BI 工具对于充分利用隐藏在原始和未处理数据中的知识至关重要。
数据可视化在整个商业智能动态中扮演着至关重要的角色。简单来说,数据可视化是给定数据集的图形化表示。基于文本的数据以图表、图形、表格、信息图、地图等形式可视化。在可视化的帮助下,可以发现数据中的新见解和隐藏模式。
数据可视化的目的是检测不同数据集之间的模式、趋势和相关性,否则无法从简单(非图形)形式的数据中进行研究。它帮助用户更好地了解市场现状,评估客户需求。此外,企业可以通过新的战略和技术来发展,以增强和促进他们的业务。这正是所有数据科学软件公司专注于使其 BI 工具在数据可视化功能方面表现最佳的原因,因为它有助于揭示巨大的原始数据库中隐藏的信息。
用于数据可视化的顶级 BI 工具
让我们从讨论 2019 年数据可视化的顶级 BI 工具开始。我们将讨论 BI 领域的主要参与者,如微软 Power BI* 、 Tableau 、 QlikView 和 Qlik Sense 。这些 BI 工具被 Gartner 的《2019 年分析和商业智能平台魔力象限》( Gartner 发布的调查系列)列在不同的类别中。*

- 画面
Tableau 是一个新时代的数据分析和商业智能平台,为用户提供灵活性和易用性。Tableau 的核心优势被认为是其交互式仪表盘、快速响应和实时数据分析功能。它提供引人注目的图形(可视化)来形象地表示您的数据集。从根本上说,Tableau 提供了数据提取、处理、表示和与他人共享最终报告/仪表板/工作表的所有必要功能。
Tableau 受欢迎的主要原因***是其易于拖放的功能,可以创建可视化效果。它比其他 BI 工具更快,而且非常直观,是一款完美的自助式 BI 工具。它还提供了与大量数据和大数据源的连接,如 Oracle、Teradata、SAP HANA、MongoDB、Excel、文本文件、JSON、Google Cloud、SQL、Hadoop、Amazon Redshift 等。*****
连接到这些数据源不需要购买连接器许可证。此外,Tableau 是为所有类型的用户设计的,不需要任何特定的技能或知识。企业中所有类型的用户都可以轻松执行所有数据分析和可视化功能。
推荐你去探索这个 Tableau 教程系列 获取 Tableau
画面特征
- 询问数据
- Tableau 准备指挥
- 适用于 iOS 和 Android 的 Tableau mobile
- 连接器和连接
- 数据共享
- 安装和部署
- 设计视图和可视化

下面给出了一个Tableau dashboard的一些数据可视化示例。****
**********
2。微软 Power BI
微软 Power BI 是一个强大的数据可视化工具,非常受欢迎。这是一个基于云的软件,有两个版本;动力匕桌面和动力匕移动。微软 Power BI 以其易于使用的数据准备和数据可视化功能而闻名。Power BI 附带了许多可视化功能,如 自定义可视化 ,使用自然语言创建可视化,拥有 Cortana 个人助理等。
Microsoft Power BI 提供与各种数据源的连接,如 Oracle、IBM、SQL Server、Salesforce、Google analytics、Azure DevOps、Excel、文本文件、JSON、Zendesk、Mailchimp 等。除此之外,借助使用 web 服务的直接连接,与大数据源的集成也很容易。
看看一些示例微软 Power BI 应用使用不同种类的可视化。****


微软 Power BI 的特性
- 访问内部和基于云的数据源
- 直观和图形丰富的可视化
- 对复杂情况的快速响应
- 移动兼容性
- 轻松洞察(仪表板、报告等。)组织内的共享
- 将数据报告和仪表板发布到 web
- 帮助和反馈按钮
- 模式指示器
- Power BI Desktop 提供信息丰富且直观的报告
你必须详细探究这些 异能匕的特性

3. QlikView
根据 Gartner 2019 年魔力象限报告,QlikView 是领先的 BI 工具 之一。QlikView 提供内存存储功能,可快速收集、整合和处理数据。报告使用可视化工具生成,数据之间的关系由 QlikView 软件自动导出。换句话说,QlikView 是一个数据发现工具,有助于创建用于数据分析的动态应用程序。
QlikView 主要是一种数据发现工具,因此它具有一些独特的数据可视化功能。数据发现是用户驱动的对数据集中的模式和趋势的搜索。它通过提供图形、表格、地图等视觉辅助帮助用户理解和看到这些模式。QlikView 的独特之处还在于其灵活性、内存功能和协作辅助功能。
看看一些使用不同可视化方式的 QlikView 应用示例。


QlikView 的功能
- 独特的数据发现和全局搜索
- 交互式可视化
- 合作
- 对数据的绝对控制
- 安全的工作环境
- 灵活性和集成
- 一致的报告
升级技能的最佳时机— 向专家学习 QlikView
4。Qlik 感应
Qlik Sense 也是一款流行的数据分析和可视化软件。它的核心是一个相关的 QIX 引擎。该引擎使用户能够链接和关联来自不同来源的数据来执行分析。Qlik Sense 作为一个数据分析平台,面向从非技术用户到技术用户的广大用户。
Qlik Sense 更侧重于数据可视化,因为它具有增强的图形。但是,在 QlikView 中,您可以通过脚本以多种技术方式操作数据。如果您使用 Qlik Sense 的动机是以尽可能好的图形来可视化和分析数据,那么您做出了正确的选择。
Qlik Sense 为用户提供了很大的灵活性,因为他们可以通过自助式可视化和分析执行完全独立的操作。此外,它们可以由 Qlik Sense 的认知引擎进行自动机器引导分析。Qlik Sense 使用关联模型,用户可以自由探索大量复杂的数据,并从中获得直观的见解。从 Qlik 的角度来看,集成来自多个来源的大型数据文件是可能的。客户端可以在中央集线器上共享数据应用程序和报告。除此之外,他们还可以共享安全的数据模型,导出数据故事等。来提升他们的业务。
看看一些使用不同类型可视化的 Qlik Sense 应用程序示例。


学习 Qlik Sense 成为商业智能大师
Qlik Sense 的特性
- 联想模型
- 智能可视化和分析
- 自助创建
- 集中式共享和协作
- 数据叙述和报告
- 应用移动性
- 数据准备和整合
- QIX 引擎
- 企业治理和可扩展性

5。SAP Lumira
SAP Lumira 也在十大商务智能工具中占有一席之地。根据 Gartner 的 2019 年分析和商业智能平台魔力象限, SAP Lumira 被归类为具有巨大潜力的前瞻性 BI 工具。SAP Lumira 是一款自助式数据可视化和分析工具,以其易用和直观的应用程序而闻名。SAP Lumira 提供丰富的交互式可视化,如表格、图形、图表、地图、信息图等。
根据使用目的,SAP Lumira 有两个版本;SAP Lumira 的发现版和设计师版。在 Discovery edition 中,您可以创建自助式数据可视化,并将其直接发布到 SAP BusinessObjects BI 工具。而在 Designer edition 中,您可以使用这些自助式可视化来创建详细的分析应用程序。****
SAP Lumira 是一个用户友好的工具,有一个主屏幕,所有数据源都可以在这里找到。输入控件,以便用户可以自由地处理应用程序。应用程序屏幕提供了使用导入的数据创建可视化和应用程序的单一平台。用户可以访问实时数据,如治理数据、宇宙数据、云数据、元数据、来自大数据源的数据等。
看看一些 SAP Lumira 应用程序的例子,它们使用了不同的可视化技术。



将 SAP Lumira 连接到 SAP HANA
由于 SAP HANA 是一种内存数据库技术 ,来自它的数据被带入 SAP Lumira,供用户进行数据可视化和分析。SAP Lumira 使用 JDBC 连接(即 OLAP 连接)直接连接到 SAP HANA。SAP HANA 和 SAP Lumira 之间的通信使用的语言是 SQL。
您可以将 SAP Lumira 连接到 SAP HANA,以使用存储在 HANA 数据库中的数据。要连接到 SAP HANA 数据库,请转到 SAP Lumira 的文件菜单,通过建立连接来添加新数据集。将 SAP Lumira 连接到 SAP HANA 的完整步骤在单独的教程“连接 SAP Lumira 和 SAP HANA ”中给出。请参考。****
一旦您与 SAP HANA 建立了连接并从中导入数据集,您就可以在 Lumira 中创建许多可视化效果。您可以从一系列可视化图形中进行选择,如饼图、条形图、树形图、环形图、热图等。
SAP Lumira 的特性
- 使用低级 JavaScript 编程轻松开发数据可视化应用程序。
- 基于模板的数据可视化仪表板指导设计。
- 通过网络和移动平台访问 Lumira 应用程序。
- 嵌入式可视化和可定制的扩展。
- 集成来自多个数据源的数据。
- 集成 SAP BusinessObjects BI 分析工具。
- 创建临时报告和仪表板
- 讲故事

虽然,Power BI,Tableau,Qlik Sense,QlikView 是截至 2019 年领先的数据分析和可视化 BI 工具。
BI 领域还有其他工具,如 ThoughtSpot 、 Sisense 、 Salesforce 、 Looker 、 Domo 、 SAP (SAP Lumira) 等。证明了它们作为数据可视化的完美 BI 工具的潜力。在不久的将来,市场上将会出现数十种新的商务智能工具。这将为客户提供具有高级 BI 功能的广泛选项。
希望你喜欢阅读这篇文章。
你需要知道的五大数据分析方法
在数据分析中,数据分析思维是基于框架的指南。在分析问题的时候,我们需要很多技巧和工具。就像在中学一样,你可以用公式法、完成平方、平方根的提取或因式分解法来解二次方程。数据分析中也有一些技术,我们可以在一些常见的分析场景中使用。并且它们可以在将来构建数据分析模型时有所帮助。

在本文中,我们将分享五种常用的数据分析方法:公式法、比较法、象限法、80/20 法则、漏斗分析法。我们经常组合使用它们。
注意:这些方法主要偏向于思维层面,是基于业务问题对数据的探索性分析。它们不同于专业统计学中的数据处理方法。
1.公式法
所谓公式法,就是用公式对某一指标的影响因素进行分解。
例:用公式法分析某产品销量低的原因。
- 产品销售额=销售量*单价
- 销量=渠道 A 销量+渠道 B 销量+渠道 C 销量+ …
- 渠道销量=用户数*订单率
- 用户数量=曝光率*点击率
第一步:寻找产品销售的影响因素。是销量太低还是价格设定不合理?
第二步:找到影响销量的因素。分析每个渠道的销量。和之前的销售对比一下,找出异常的。
第三步:分析影响渠道销售的因素。是用户数低还是订单率低?如果订单率低,就要看渠道的广告内容是否与产品的实际受众相匹配。
第四步:分析影响点击的因素。是曝光度不够还是点击率太低?如果点击率低,你需要优化活动。而曝光度与渠道有关。
为此,公式法是对问题的层次分析。它将影响因素逐级分解。
2.比较法
比较法是对两组或多组数据进行比较,是数据分析中最常用的方法。
我们知道孤立的数据是没有意义的,我们通过比较看到差异。人们通过比较一些直接描述事物的变量,如长度、数量、高度、宽度等,得到比率、增长率、效率等指标。
比较法可以发现数据变化的规律。下图是 A 公司和 B 公司的销售对比,虽然 A 公司的销售普遍有所增长并且高于 B 公司,但是 B 公司的增速高于 A 公司,即使 B 公司后期增速下滑,最终销售也是迎头赶上。

3.象限法
通过划分两个或多个维度,我们用坐标来表示数值,这就是象限法。象限法是基于战略驱动的思想。我们经常在产品分析、市场分析、客户管理和商品管理中使用它。
例如,下图是广告点击的四象限分布。

如果一个广告获得高转化率( CVR )和高点击率( CTR ),说明它的目标受众是相对精准的。
如果点击率高,CVR 低,这意味着大多数点击的人是被广告本身吸引的。低 CVR 表明广告的目标人群与产品的实际受众不匹配。
高 CVR 和低点击率表明广告的受众和产品的实际受众更加一致。问题是广告的内容需要优化,才能吸引更多人点击。
我们可以放弃低 CVR 和低点击率的广告。
用象限法分析具有相同特征的事件,可以找到问题的共同原因。在上面的广告案例中,观察第一象限的事件,可以总结出有效的推广渠道和策略。第三和第四象限可以排除一些无效的推广渠道。同时可以针对不同象限建立优化策略。
4.八二十分法则
80/20 法则也被称为 帕累托法则 。它是以其创始人,意大利经济学家维尔弗雷多·帕累托的名字命名的。他注意到,当时意大利 80%的财富掌握在 20%的人口手中。在数据分析中,我们可以理解为 20%的数据产生 80%的效果。我们需要挖掘这 20%的数据。
它通常与排名相关,前 20%被视为有效数据。80/20 法则分析关键部分,适用于任何行业。找到重点,发现它们的特点,然后思考如何让剩下的 80%转化到这 20%来提高效果。
通常,它将用于产品分类,以衡量和建立 ABC 模型。比如一个零售企业有 500 个 SKU(库存单位),那么哪些 SKU 是重要的?这就是商业运作中分清主次的问题。
通常的做法是使用产品的 SKU 作为一个维度,并使用相应的销售额作为一个基本指标来对这些销售指标进行排名,并计算每个 SKU 的累计销售额占总销售额的百分比。比如我们可以把他们分为 3 类:A 类(< 70%),B 类(70%-90%),C 类(90%-100%)。可以根据自己的实际情况调整百分比。
ABC 分析模型不仅可以用来划分产品和销售,还可以用来划分客户和利润。比如哪些客户为公司贡献了 80%的利润?如果这部分客户占 20%,那么在资源有限的情况下,你知道要重点维护这 20%的客户。

5.漏斗分析
漏斗分析是一个漏斗图,有点像倒金字塔。这是一种简化的思维方式。我们经常在分析变化和某些过程时使用它,比如新用户的开发、购物转化率等等。

上图是一个经典的营销漏斗,展示了从获取用户到最终转化为购买的全过程。漏斗模型将整个购买过程分成几个步骤。然后它用转化率来衡量每一步的表现,最后通过异常的数据指标找到有问题的那一步。这样就可以优化步骤,提高整体购买的转化率。
漏斗模型的核心概念可以分为分解和量化。比如分析电商的转化,我们要做的就是监测每个层级的用户转化,找到每个层级的可优化点。对于没有按照流程走的用户,我们专门构建他们的转化模型,缩短路径,提升用户体验。但是,单一的漏斗分析是没有用的。我们应该把它与其他方法结合起来,如与历史资料的比较。
数据分析工具
使用数据分析方法的好处是,它提供了一个思维框架,帮助你建立对事物和问题的观点。既然有了思维框架,我们还需要有效的工具来实现真正的数据分析,像 Tableau 和 Python 。这里推荐一款免费的数据分析工具 FineReport ,供大家练习。这是一个集成了数据显示(报告)和数据输入(填充)的 BI 报告&仪表板软件。成功入选《Gartner 全球市场指南》,成为中国唯一入选的厂商和产品,与微软、SAP、Oracle 等国际巨头一同上市。
FineReport 允许您通过简单的拖放操作创建复杂的报告。接下来,我将向您展示一些使用 FineReport 的数据分析场景。
销售分析

实时订单监控

营销分析

人口流动分析

如果你对 FineReport 感兴趣,可以去官网免费下载。还有针对 FineReport 初学者的帮助文档。
您可能也会对…感兴趣
原载于 2019 年 4 月 25 日【http://www.finereport.com】。
值得关注的 5 大数据治理框架工具

了解数据治理
数据被誉为 21 世纪的石油,组织最终意识到数据不再是个人之间交换的信息包。现在,个人是有机体,在他们不断创造的无底数据海洋中游泳!
事实上, 95%的 C 级高管已经在使用数据来形成他们的商业战略。有鉴于此,全球各地的公司已经意识到拥有一个正式的数据治理系统的重要性,这实质上是一种处理公司数据的系统方法。
它提供了一个策略、协议、程序和指标的结构来帮助公司规避风险和责任,并提供了一套工具来挖掘数据以实现其最大价值。此外,它还可以控制如何使用、存储和操作数据。它帮助组织中的每个人有效地、高效地、负责任地使用数据。
为什么需要数据治理工具?
随着数据及其应用对组织变得至关重要,保护数据资产完整性的数据治理工具也变得越来越重要。
虽然成功的数据治理计划的确是建立在业务运营人员的仔细规划和宝贵见解之上,但数据治理工具与任何其他因素一样重要,甚至更重要。以下是数据治理工具如何帮助您:
∇授权决策
∇提高了数据质量
∇简化了主数据管理
∇高级数据互操作性
∇高级数据血统
量身定制的数据治理政策至关重要
没有一种数据治理策略能适合所有组织。决策者、数据专家和业务运营部门的成员需要通力合作,定制符合特定组织数据要求的数据治理策略。
大约 49%的组织认为人为错误是数据不准确的主要原因,这使得所有部门的参与对这些政策的成功至关重要。决定数据治理决策的一些重要因素包括:
∇内部功能要求
∇数据收集方法。
∇数据的质量和规模
∇商业目标
∇数据存储框架
∇自动化程度
创建适合您组织的数据治理策略的第一步是根据所需的功能和分析能力为各种数据操作设计框架。
一旦确定了框架,决策者和各种利益相关者需要达成一致。只有当框架有益并为不同的跨职能合作伙伴带来价值时,才能实现这一点。
一旦数据治理策略的广泛目标最终确定,您需要开始寻找适合您的框架和数据操作的数据治理工具。让我们来看看一些关键的数据治理工具,以及它们如何对您的组织有所帮助:
Collibra 被誉为企业范围的数据治理工具,以自动化数据操作和让跨职能团队保持一致而闻名。虽然事实上没有解决方案能够真正满足所有组织的需求,但 Collibra 已经过定制,以满足具有不同数据治理策略的各种框架的需求。
Collibra 提供的语义搜索功能是一个令人惊叹的功能,这使它比市场上的传统数据治理工具更具优势。治理和数据管理任务可以实现自动化,从而提高工作流的效率和可靠性。有了 Collibra 提供的预建集成模板,团队可以以简化的方式轻松链接到数据湖和元数据。
2。 TALEND
Talend 将其数据治理工具定义为可信数据的统一云平台。从元数据管理到改进的数据血统,这种数据治理工具有很多优点。不仅如此,这个数据治理工具还简化了数据的云集成。为了向您的数据操作团队介绍和熟悉该工具,您甚至可以使用该工具的免费开源版本。
****3。IO-TAHOE
IO-TAHOE 是另一个很棒的数据治理工具,可以最大化数据治理活动的产出。使用该工具可以验证数据质量,并发现新的信息来源。数据可视化及其发现的高度自动化带来了数据操作的高度互操作性,从而简化了组织中的信息流。当您的框架使用这种数据治理工具时,还可以确保遵守 GDPR、多德-弗兰克和 CCAR 等关键法规。
4。 IBM
IBM 提供的数据治理解决方案对您的组织来说是一个真正的陷阱。这个工具最大的优点是它能够灵活地适应各种数据治理策略,这对于许多拥有来自多个跨职能团队的多个数据入口的组织来说是一个障碍。
IBM 的这个解决方案的另一个重要特性是数据编目。这些数据目录由机器学习算法驱动,可以更快地收获元数据和培养数据资产。其安全基础设施由 IBM 的尖端技术提供支持,您可以放心地保护您用户的数据和隐私。
Informatica 为合规性和数据治理提供了快速解决方案,可以在内部或云中实施。它提供了强大的数据沿袭和历史的可视化,主动监控数据质量的主数据仪表板和数据安全的动态屏蔽。它还提供了检测和保护敏感客户数据、管理 GDPR 数据风险以及确保联系信息最新、准确和完整的功能。
当遵守 GDPR 等法规是您的数据治理框架的最终目标时,Informatica 被誉为终极工具。除此之外,该工具还提供了强大的可视化和改进的数据沿袭,从而提高了数据操作的效率。
Informatica 对数据质量的主动监控有助于您的框架在处理最复杂的数据湖时表现良好。由于在创建这些解决方案时对数据安全性给予了特别关注,因此可以确保您的数据治理框架适合保护客户数据。
总之
从元数据收集到您期望的数据安全级别,从数据存储实践到您采用的数据可视化技术,这些因素中的每一个都决定了您应该选择哪种工具。
这是市场上最好的 5 种数据治理框架工具。为您的数据治理框架选择正确的工具与其说是关于工具,不如说是关于了解您自己的数据治理策略的目的和目标。
回答的前 5 个数据科学面试问题

当你开始下一次数据科学面试时,确保你知道这 5 个面试问题的答案。
- 监督学习和无监督学习有什么区别? 有监督学习和无监督学习是机器学习的两大类别。两者之间的主要区别是,在监督学习中有一个目标变量,或一个已知的输出来预测,而在无监督学习中没有。出于这个原因,用于监督学习的数据被称为有标签的,用于无监督学习的数据被称为无标签的。比方说,您正在处理一个选民数据集,包括邮政编码、收入、家庭规模、政党登记以及此人是否在上次选举中投票。你可以建立一个监督学习模型来预测如果这个人在上次选举中从所有(或一些)其他特征中投票。或者,您可以使用所有(或部分)功能构建无监督学习模型,以生成有关投票者的新信息,例如按投票者类型创建聚类。
- 什么是假设检验?
假设检验是一种统计推断;换句话说,它是一个获取样本信息的工具,用来对相应的总体做出判断。在假设检验中,你正在检验的假设被称为零假设,大多数时候它只是一个什么都没发生的想法。一个很好的类比是美国的刑事司法系统:“在被证明有罪之前是无辜的。”另一种选择是另一种假设,如果你愿意的话,是“有罪的”;这是一些已经发生的想法。根据假设检验的类型,零假设和替代假设看起来会非常不同,但举个例子,我们可以说零假设是指居住在加利福尼亚的人的平均身高与居住在纽约的人的平均身高相比没有差异。在这种情况下,另一个假设是存在差异。每种类型的假设检验看起来都有一点不同,但是结果总是一个p-值,或者如果零假设为真,你将得到你的数据(或者更极端的数据)的概率。通常,阈值 0.05 用于 p 值。如果比较加州和纽约平均身高的假设检验结果是 0.1 的p-值,这意味着如果假设人口身高没有差异,则有 10%的机会获得更极端的数据。这并不罕见,不足以得出加州和纽约人口的平均身高存在差异的结论。另一方面,如果假设检验的结果是 0.02 的p-值,则只有 2%的数据为极端值或更极端(假设人口身高没有差异),因此我们可以得出结论,加州和纽约人口的平均身高存在统计学上的显著差异。 - 为什么拥有培训和测试数据很重要?
在进行监督学习模型建立和评估的过程中,拥有训练数据和测试数据是很重要的。在监督学习中,第一个重要的想法是使用一些数据来教授模型模式。模型根据这个数据集,即训练数据来学习这些模式。但总体目标不是在已知信息的基础上建立最佳模型;它是建立一个模型,可以接受新的或看不见的数据,并根据以前学习的模式做出预测。这个新数据就是测试数据。简而言之,模型需要训练数据来学习和构建模式,测试数据对于查看模型根据新数据进行预测的效果是必要的。 - 描述偏差-方差权衡。
偏差-方差权衡是建立和评估监督学习模型时要考虑的现象。偏差是对模型预测目标的糟糕程度的一种度量。方差是衡量模型对新数据进行归纳的能力有多差的指标。偏差-方差权衡是当偏差低时,方差高,当偏差高时,方差低。当偏差较低且方差较高时,模型在预测所见数据方面做得如此之好,以至于它过度适应该数据,而不能很好地响应新信息。另一方面,当偏差较高且方差较低时,模型不能很好地预测目标,并且过于一般化(即拟合不足),以至于它对看不见的数据的表现大致相同。理想情况下,模型处于偏差-方差权衡的“最佳点”,不会过拟合或欠拟合。 - 什么是敏感度,如何计算?
敏感度是一个可以用来评估二元分类模型的度量。例如,假设您有一个模型,它根据一些特征预测某人是否患有癌症。如果我们认为阳性类别是患有癌症的人,而阴性类别是没有患癌症的人,那么我们正确预测某人患有癌症的模型是真正的阳性,而我们正确预测某人没有患癌症的模型是真正的阴性。如果模型预测某人患有癌症,但他们没有,这是假阳性或 I 型错误。如果模型预测某人没有患癌症,但他们患了,这是假阴性或 II 型错误。在这种情况下,假阴性更糟糕,因为这个人将无法接受治疗。为了最大限度地减少模型中的假阴性数量,我们希望优化灵敏度,或模型的真实阳性率(有时也称为“召回”)。灵敏度是真阳性与所有阳性的比率;换句话说,灵敏度是真阳性除以真阳性和假阴性之和。例如,如果我们有 90 个真阳性病例和 10 个假阴性病例,我们的灵敏度将为 0.9。
你还遇到过哪些数据科学面试问题?下面补充一下。面试愉快!
A/B 测试中的五大统计错误

A/B 测试(也称为在线控制实验)被广泛用于评估网站和移动应用程序的拟议更改的影响,并作为管理与此类更改相关的风险的工具。许多软件供应商在该领域与转换率优化人员、登录页面优化专家、增长专家、产品经理和数据分析师使用的定制测试平台竞争。
然而,尽管该领域相对成熟,但使用 A/B 测试统计数据仍存在一些普遍的错误。它们的影响从降低测试的效率从而增加成本,到使 A/B 测试的结果变得无用(或者更糟——完全误导)。我将讨论 5 个最常遇到的高影响问题,讨论为什么我认为它们很普遍,并提供一些解决它们的方法。
错误 1:没有测试你的 A/B 测试设置
如今,测试是发布一个成功的网站或应用程序的最小变化的先决条件,然而,通常 A/B 测试设置本身避免了这种审查。
不应该!
它是一个软件(准确地说,是几个相互关联的部分),和其他软件一样容易出现问题。如果它不可靠或不按预期工作,出于某种原因,它的输出将不可信。如果 A/B 测试平台不能按照规范工作,那么 A/B 测试的核心功能——作为防止破坏业务的用户体验的最后一道防线——将会部分或完全受损。
简而言之,问题在于不适当的随机化、测试组之间的用户分配或跟踪会使任何 A/B 测试结果不可靠。这是因为用于评估数据的统计模型需要满足一定的假设才能工作。常见的假设是观测值的独立性、同质性和某些分布假设(如正态性)。
危害是用错误指定的模型进行 A/B 测试的结果将是不准确的或误导的。基于这种测试做出的决策不仅会损害业务结果,而且还会在它们周围获得一种确定性的氛围(“我们已经测试过了,这没问题”),这样以后通过观察分析发现的任何问题都不太可能归因于测试的变化。
这种错误盛行的原因是几乎没有任何商业工具提供对违反统计假设的内置检测。除了谷歌、微软和亚马逊等公司使用的一些系统之外,我在实践中看到的许多定制系统都是如此。另一个原因可能是,统计工具的输出常常被认为是不容置疑的,这是因为对检验统计假设的必要性缺乏认识。
一些解决方案包括:
1。)测试发射前严格的质量保证流程。它可以帮助检测各种跟踪问题、可能影响结果的技术问题(例如,仅仅由于测试交付过程,变体的交付比控制慢 500 毫秒),以及简单的中断测试体验。
2。)后数据,可以执行拟合优度测试来检查实际分配比率是否符合指定的分配比率。例如,我们可以使用 50/50 目标分配计划 A/B 测试的以下结果:

结果——变异体优于对照组,p 值:0.02——可信吗?为了找到答案,我们可以进行卡方拟合优度测试。此类测试的低 p 值表明预期分配和实际分配不匹配。这就是有人所说的样本比例不匹配 ( 克鲁克等人 2009 (pdf) ,德米特列夫等人 2017 (pdf) )
这个特定测试的结果明确指出了一个问题(计算):

如此小的 p 值意味着它极不可能观察到我们实际得到的分配。这并没有告诉我们到底是什么问题。这种样本比率不匹配可能是由于不适当的随机化、分配程序的问题、跟踪问题或这些问题的组合造成的。需要进一步的调查来确定罪魁祸首,但至少我们知道存在问题,并且结果不可信。
3。)可执行常规 A/A 测试以确保标称和实际错误率(尤其是 I 型错误率)匹配。可以对 A/A 测试数据进行正态性和其他假设的统计测试,以确保这些假设适用于使用该特定测试设置进行的测试。前面提到的 Crook 等人题为“在网络上运行受控实验时要避免的七个陷阱”的论文中的第 8.2 点是关于 A/A 测试的很好的入门。
错误 2:测量错误的指标
我在我的书《在线 A/B 测试中的统计方法》中花了相当多的篇幅来解释统计和测量工具应该如何调整以适应一个人所面临的业务问题,而不是相反。
原因是,在许多情况下,我看到了相反的情况:衡量一个人拥有的数据,而不是一个人需要的数据。在这种情况下,无论采取什么措施都不足以回答提出的业务问题。然而,它经常被呈现出来,好像这正是我们所需要的。
问题是,所使用的指标常常无法回答正在接受测试的业务问题。转换率并不总是正确的指标。当转化的商业价值存在差异时,它当然不应该是您使用的唯一指标。
原因,我认为,部分是习惯,部分是易用性和方便性。大多数 A/B 测试工具支持各种比率的统计模型,因为这些模型操作简单。大多数仍然不支持或有限支持连续的度量标准,如每用户平均收入差异(ARPU)或平均订单价值(AOV),尽管这些对于回答与电子商务相关的典型业务问题是必不可少的。像 Google Analytics 这样的报告工具也缺乏对大多数连续指标的统计计算的适当支持。
另一个原因可能是需要更大的样本量,加上的额外开销,需要估计历史数据的标准偏差,以便计算所需的样本量/统计功效;对于基于二项式变量(如转换率差异)的指标,这一步要简单得多。
危害用一个简单的电子商务例子就很容易说明。如果测试变体的业务目标是增加商店的收入,这通常会转化为每个用户平均收入的增加。在其他条件相同的情况下,如果商店的人均收入增加,收入就会增加。
每个用户的平均收入由两部分组成,即转换率和平均订单价值(ARPU = CR x AOV)。仅测量转换率而忽略平均订单价值很容易导致实施一种变体,这种变体虽然提高了转换率,但实际上损害了业务,因为较低的 AOV 最终会降低 ARPU。由于度量标准选择不当,测试结果可能会与预期效果完全相反。
上例的解决方案是基于 ARPU 的测试。这是一个简单的解决方法,但是在实践中可能不那么容易,因为这可能需要将软件供应商转换为那些基于 ARPU*的支持报告和统计计算的供应商。
如上所述,当从 CR 切换到 ARPU 时,预期的测试持续时间将不可避免地增加,这是因为 ARPU 相对于 CR 的方差增加,CR 是其组成部分之一。然而,这通常是让你的商业问题得到正确回答的合理代价。
作为一名软件供应商,我理解为什么整个行业在提供对持续指标的适当支持方面行动缓慢——产品对最终用户来说变得更加复杂,存储持续数据更加昂贵,而且需求还不太大。然而,在 www.analytics-toolkit.com*的一些基本统计计算器中提供对这些指标的支持已被证明是有用的,我们正在努力将其扩展到我们的高级统计工具中。我鼓励其他人以我们为榜样。**
错误 3:使用双尾检验
如果你没有听说过双尾检验和单尾检验,或者双边假设和单边假设,你并不孤单。除非你已经深入研究了统计数据,否则你可能根本不会面对这个问题,因为大多数时候所使用的测试类型并不是立即可见的,可能只会在技术参考或手册中提到。在定制平台中,这可能更不明显。
篇幅不允许我在这里深入讨论单尾检验和双尾检验的问题,但是如果你想更深入地研究——我已经揭穿了围绕这个问题的一些常见的神话,并在这里简要地陈述了单尾检验的情况,在我的书和 OneSided 项目的一系列文章中有更详细的描述。
如果你不想陷入细节,理解这一切都是关于将手头的业务问题与被测试的统计假设对齐就足够了。通常,我们希望控制实施劣质解决方案的风险,或者有时控制实施不比我们现有的更好的东西的风险。
因此,我们在在线 A/B 测试中面临的大多数业务问题都是“我们希望得到某种保证,体验 B 比用 X 度量的 A 更好”。这些恰当地转化为一个单侧假设,从而成为一个单尾检验。我们很少,如果有的话,问这样的问题“我们想要一些保证 B 不等于 A,无论如何”,这确实需要一个双尾检验。更难得的是,与前一个答案相比,我们愿意付出代价来获得与前一个答案同样精确的结果。
因此,的问题是,双尾检验的统计模型与手头的业务问题不一致。
其流行的原因是许多统计工具专门或默认执行双尾计算。如果我们深入到问题的当前状态的原因,讨论将变得非常深入,但结果是,许多最终用户仍然幸福地没有意识到这个问题。
使用双尾检验的危害是由于报告的不确定性测量(p 值、置信水平等。)明显高估*实际不确定性——通常约 100%;如果工具报告的误差概率为 0.1%或 10%,实际上是 0.05%或 5%。这再次发生,由于提出的问题和测试的统计假设之间的不一致。*
此外,与具有相同参数而非不同假设的单尾测试相比,双尾测试需要大 20%到 60%的样本量(更多用户,因此 A/B 测试持续时间更长)。
这里的解决方案看你的具体情况。如果你的统计工具已经默认为单尾计算,那么就继续使用它们。如果它们同时支持双尾和单尾计算,则切换到单尾(单侧)选项。如果它们只支持双尾计算,还是有解决方案的——只要感兴趣的参数的误差分布是对称的,你需要做的就是不确定性估计的一半。
因此,如果它是一个 p 值,并且报告的双侧 p 值为 0.1,只需除以 2 即可得到 0.05 的单侧 p 值。如果是以置信水平报告的,比如说 90%,那么简单地将 100%-90%除以 2,并将其加到报告的水平上。所以 90%两面就变成了 90% + (100%-90%)/2 = 90% + 5% = 95%。如果误差分布是不对称的,那么我假设您已经在使用足够先进的工具来根据请求计算单尾值。
如果您不确定使用哪种计算方法,请阅读技术手册或参考资料,或者联系供应商的支持人员。如果是定制的解决方案,请查阅其手册或与其开发人员合作,以确定采用哪种类型的计算。
错误 4:高估了 A/B/n 测试的样本量
A/B/n 检验——对照一个以上的检验变量对控制进行检验的检验——是另一个经常出错的领域,无论是在计算统计估计值方面,还是在估计实现特定显著性和最小感兴趣效应的目标功效所需的样本量方面。在这里我将重点讨论后一个问题。
问题在于,通常每个测试组的样本量是为简单的 A/B 测试计算的,然后乘以测试变量的数量加 1,得到 A/B/n 测试的样本量。
考虑这种情况:A/B/n 测试有 4 个变量与对照(A/B/C/D/E)。一个简单的计算是从估计 A/B 测试每组需要 24,903 个用户开始。因此,对于 A/B/C/D/E 测试,用户总数就是 5 x 24,903 = 124,515。
然而,在现实中,使用这些参数进行 A/B/C/D/E 测试只需要 95,880 个用户(总数),或者说比天真计算少 23%。
发生这种情况的原因是大多数免费的样本大小计算器,也许还有一些付费的,只支持一个变量相对于一个控制变量的计算。更糟糕的是——有些人声称支持 A/B/n 测试的计算,但实际上只是执行上面显示的简单计算。因此,这很容易成为这个错误的牺牲品。
危害是相当明显的——由于样本量计算中的高估,测试计划的时间比需要的时间长得多。业务损失是由于错过了早期实现 winners 的机会,以及由于用劣质变体运行测试的时间超过了必要的时间而错过了销售。
解决方案是使用适当的样本量计算。使用 Dunnet's test 的样本量计算会产生最佳测试,因为它们考虑了 A 与 B、A 与 C、A 与 D 等比较的相关性。基于 Holm-Bonferroni 方法的计算是可以接受的,尽管它们会导致略微次优的测试。
Analytics-Toolkit.com 的样本量计算器提供为在线 A/B 测试量身定制的付费解决方案(可免费试用)。这个样本量计算器是完全免费的,也使用了邓尼特的,但是学习操作界面可能更具挑战性。如果你更喜欢使用 R,那么检查一下 DunnettTests 包。
错误 5:不正确地使用置信区间
在评估和交流在线 A/B 测试的结果时,我看到了许多使用置信区间的错误,但有三个特别突出。
第一个与上面讨论的问题有关——单尾和双尾测试。除了这里它转化为使用单边和双边区间的问题。
我认为,大多数时候,人们感兴趣的是查看值,低于这些值的参数值可以在某种置信水平 XX% 下被排除。这也是通常解释区间的方式——比如,在观察下面从 2%到 5%的双侧 95%置信区间时,可以说低于 2%的值可以排除 95%的置信度。

但是,这是不正确的!事实上,在这个特定的例子中,我们可以以 95%的置信度排除低于 3%的值。这是通过计算正确的单边区间实现的,范围从 3%到正无穷大。如果我们要无限多次构建这个区间,95%的时间其下限将低于我们试图估计的参数的真实值(例如转换率的差异)。
因此,如果您希望限制两侧的值,请使用双边区间,但是当您声称某个特定方向上的区间外的值可以以给定的置信度排除时,您需要构建一个单边区间,而不是双边区间。如果您的软件不支持单侧区间,出于某种原因,只需构造一个具有两倍不确定性的区间,例如 90%双侧置信区间的下限正好是 95%单侧置信区间的下限(对于具有对称误差分布的参数)。
关于置信区间的第二个错误我在 A/B 测试(包括主要供应商的测试)中看到了很多,就是每个测试组的区间估计的报告和使用,而实际上感兴趣的参数是组均值/比例之间的差异。
人们经常会看到类似左图的东西或一个“爱好者”

分布图达到相同的效果(分布图可以在同一 x 轴上,也可以重叠,这是一回事)。从这样的陈述中得出的逻辑是,由于变异体的区间和对照的区间之间存在一些重叠,我们不能得出变异体在期望的置信水平下优于对照的结论。
这种逻辑是完全不正确的,因为在上面的例子中,比例相对差异的置信区间通常不包括零,这意味着在指定的置信水平下,差异可以被接受为非零。这样使用区间肯定会导致高估 A/B 测试结果的不确定性。
我看到几乎普遍犯的第三个错误是将为绝对差异计算的置信区间界限天真地转换为相对差异的界限。例如,转换率从 0.0015 到正无穷大的绝对差异的 95% CI 计算如下:

以 10%的基线转换率,下限将被转换为 1.5%,并且声称可以以 95%的置信度排除小于 1.5%的差异。
通过计算比例相对差异的正确置信区间,可以证明这是不正确的(科哈维等人,2009 年,第 154-155 页(pdf) )。在这个例子中,它的跨度从-2.9%到正无穷大,这意味着在 95%的置信水平下不能排除-2.9%以上的差异。在这种特殊情况下,构建适当的区间也会逆转测试的结果:在 95%的置信水平下,变体不再被认为优于对照。
如果您有兴趣更详细地讨论绝对差异区间和相对差异区间之间的差异,以及可以预期的误差程度,所有这些都附有大量的模拟结果,请查看这篇关于百分比变化置信区间的文章。
我希望你会发现这个相当详细的概述和在线 A/B 测试中使用统计方法的 5 个最常见错误的解决方案是有用和实用的。这些是我作为顾问和工具供应商在日常实践中看到的代价高昂的错误。我真的认为我们应该看到更少的这种情况,特别是考虑到它们中的大多数是多么容易避免。
2020 年必备的五大数据科学技能
“R、Python、SQL 和机器学习”长期以来一直是一个数据科学家的标准工作描述。但随着该领域的发展,这已不足以在就业市场上保持竞争力。

Update your skills for the 2020 data job market!
数据科学是一个竞争激烈的领域,人们正在快速积累越来越多的技能和经验。这催生了机器学习工程师的蓬勃发展的工作描述,因此我对 2020 年的建议是,所有数据科学家都需要成为开发人员。
为了保持竞争力,请确保为新工具带来的新工作方式做好准备。
为了保持竞争力,请确保为新的工作方式和随之而来的工具做好准备。
1.敏捷
敏捷是一种组织工作的方法,已经被开发团队广泛使用。数据科学的角色越来越多地由最初的技能组合是纯软件开发的人担任,这导致了机器学习工程师的角色。

Post-its and Agile seem to go hand-in-hand
越来越多的数据科学家/机器学习工程师被作为开发人员来管理:在现有的代码库中不断改进机器学习元素。
对于这种类型的角色,数据科学家必须知道基于 Scrum 方法的敏捷工作方式。它为不同的人定义了几种角色,这种角色定义确保了持续改进和顺利实施。
2.开源代码库
Git 和 Github 是开发者在管理不同版本软件时很有帮助的软件。它们跟踪对代码库所做的所有更改,此外,当多个开发人员同时对同一个项目进行更改时,它们增加了协作的便利性。

GitHub is the way to go
随着数据科学家的角色变得越来越侧重于开发,能够处理这些开发工具变得非常关键。Git 正成为一项严肃的工作要求,习惯使用 Git 的最佳实践需要时间。当你独自一人或者当你的同事是新同事时,开始使用 Git 是很容易的,但是当你加入一个有 Git 专家的团队,而你还是一个新手时,你可能会比你想象的更加困难。

Git is the real skill to know for GitHub
3.工业化
在数据科学领域,我们思考项目的方式也在发生变化。数据科学家仍然是用机器学习回答商业问题的人,一如既往。但是数据科学项目越来越多地被开发用于生产系统,例如作为大型软件中的微服务。

AWS is the biggest Cloud Vendor
与此同时,高级类型的模型越来越需要 CPU 和 RAM 来执行,尤其是在使用神经网络和深度学习时。
就数据科学家的工作描述而言,越来越重要的是,不仅要考虑模型的准确性,还要考虑项目的执行时间或其他工业化方面。

Google also has a cloud service, just like Microsoft (Azure)
4.云和大数据
虽然机器学习的产业化正在成为数据科学家的一个更严重的制约因素,但它也成为了数据工程师和整个 it 的一个严重制约因素。

A famous comic (source: https://www.cyberciti.biz/humour/dad-what-are-clouds-made-of-in-it/ )
如果数据科学家可以致力于减少模型所需的时间,IT 人员可以通过转向更快的计算服务来做出贡献,这些服务通常通过以下一种或两种方式获得:
- 云:将计算资源转移到外部供应商,如 AWS、微软 Azure 或谷歌云,可以非常容易地建立一个非常快速的机器学习环境,可以远程访问。这要求数据科学家对云的功能有一个基本的了解,例如:在远程使用服务器而不是自己的计算机,或者在 Linux 而不是 Windows / Mac 上工作。

PySpark is writing Python for parallel (Big Data) systems
- 大数据:更快的 IT 的第二个方面是使用 Hadoop 和 Spark,这些工具允许同时在许多计算机(工作节点)上并行化任务。这要求作为数据科学家使用不同的方法来实现模型,因为您的代码必须允许并行执行。
5.自然语言处理、神经网络和深度学习
最近,数据科学家仍然认为 NLP 和图像识别仅仅是数据科学的专门化,并不是所有人都必须掌握。

You will need to understand Deep Learning: Machine Learning based on the idea of the human brain
但是图像分类和 NLP 的使用案例越来越频繁,甚至在“常规”业务中也是如此。目前,对这种模型没有起码的基本知识已经变得不可接受。
即使您在工作中没有直接应用这些模型,动手项目也很容易找到,并且可以让您理解图像和文本项目所需的步骤。
祝你在提高技能的同时好运,不要犹豫,继续关注更多!
成为更好的软件工程师的 5 大技巧
从好奇的新手到经验丰富的寻求答案的瑞典人,这个快速指南是为你准备的。
A video version of this article, if you’re more of a visual learner 😃
成为软件工程师的艺术是一个在连续迭代中不断完善的过程。这篇文章是为那些刚刚起步的人,那些好奇的人,或者那些决定提高技能的人准备的,大胆地投入到令人惊讶的软件世界中去吧!

Learning how to code is a continual process, you never stop. It’s an upward spiral. Emphasis on the spiral.
你不会仅仅学习 12 周、6 个月或 2-4 年,然后就“完成”了。你在不断成长。从我 7 岁开始,我就一直致力于在机器中模拟人脑。当然,我一个人做不到。我们需要建立一支由志同道合的混合技术专家组成的队伍,他们积极寻求理解人脑和机器如何计算信息。在这个更大的计划中的一小步是指导我的伙伴们,建设者们,修补者们和梦想家们成为更好的软件工程师。
这里是我的五大技巧,可以帮助你成为一名更好的软件工程师。
学习如何使用数据结构和算法

不仅要知道它们是什么,还要知道如何使用它们,为什么使用它们,以及一种方法相对于另一种方法的利弊。比如链表和数组有什么区别?二分搜索法的优点是什么,你什么时候使用它?你知道如何识别现实世界中的问题何时可以映射为动态规划问题吗,比如著名的 0-1 背包问题,或者最长公共子序列?
了解计算机网络基础知识

Photo by Denys Nevozhai on Unsplash
令我非常惊讶的是,很多人不知道他们的代码是如何与外部世界相连的。一些你应该问自己的问题…
- 你写的软件是如何与外界连接的?
- 你知道 WiFI 和局域网是怎么工作的吗?
- UDP 和 TCP 有什么区别?
- 当您将信息从一台设备传输到另一台设备时,开放系统互连中的 7 层如何处理数据?
- 劳动力如何在路由器和主机等组件之间分配?
- 或者说,不同并发协议之间的分工是怎样的,那些并发协议是什么?
了解 Linux 或 UNIX 的基础知识

到目前为止,UNIX 已经存在了 30 多年,了解如何在命令行中使用 Linux 或 UNIX 将有助于您变得更加高效。
- 你知道它是什么插座吗?
- 杀死一个进程?
- 什么是线程?
- 你能正则表达式吗?
学习数据库的基础知识

虽然我们不指望您是数据库专家,但是您应该知道如何编写简单的 SQL 查询来访问数据集中的数据。你将编写以某种方式操纵数据的软件,所以你至少应该明白如何导入数据。
有一个成长的心态

你应该知道,什么是“时尚”的字母汤总是在变化。你应该随时准备学习新的语言,当你学得更多的时候,你会意识到语言之间的共同点通常比不同点多。
例如,Clojure 和 Haskell 实现非常适合函数式编程。相比之下,面向对象编程(OOP)范例在 Python、Java 和 Ruby 中得到广泛应用。
然而,在 1990 年,FORTRAN、COBOL 和 C++是“流行”语言的主导者。
所以每当你认为“我永远学不会那个”的时候,停止它。立即停止这种想法。
你不“只是一个 webapp 的家伙”或“只是一个后端的家伙。”你会有你的专长,你最喜欢的领域。然而,就像我的老朋友达尔文曾经说过的有机体和适者生存,
永远不是最强大的生物赢得了进化的游戏。总是那些适应性最强,对变化最敏感的人。
所以,你也需要相信你可以学到任何东西,你可以不断成长。
好了,朋友们,这是我认为对一个软件工程师来说最重要的五个建议。当然,我也在沿着这个不断向上的螺旋前进。有时我会从头开始重建我的知识。其他时候,我可以立即行动,因为我以前见过类似的问题或模式。有时,我也会碰壁,不得不回到我最初的原则。
在你看来,你认为最重要的软件工程师技能是什么?请在下面的评论中留下你的想法。
2021 年 6 大数据分析工具
谈到数据分析工具,我们总是有疑问。这么多数据分析工具有什么区别?哪个更好?我应该学习哪一个?
虽然这是一个老生常谈的话题,但是真的很重要,我也一直在努力追寻这个终极问题的答案。如果你去网上搜索这方面的相关信息,很难看到公正的观点。因为评测某个数据分析工具的评测者可能是从不同的角度,带着一些个人的感受。
今天,让我们抛开这些个人感受。而我也在尽量客观的和大家谈谈我个人对市面上数据分析工具的看法,供大家参考。
我一共选择了三种类型的 6 个工具。接下来让我逐一介绍。
1.擅长
具有各种强大的功能,如表单创建、数据透视表、VBA 等。,Excel 的系统庞大到没有任何分析工具可以超越,保证了人们可以根据自己的需求来分析数据。

但是,有些人可能认为自己对计算机编程语言非常精通,不屑于使用 Excel 作为工具,因为 Excel 无法处理大数据。但是你想想,我们日常生活中使用的数据是否超出了大数据的极限?在我看来,Excel 是一个多面手。它最适合小数据,通过插件它可以处理数百万的数据。
综上所述,基于 Excel 强大的功能和用户规模,我的看法是它是一个不可或缺的工具。想学数据分析, Excel 绝对是首选。
2.商务智能工具
商业智能是为数据分析而生的,而且是在非常高的起点上诞生的。目标是缩短从业务数据到业务决策的时间,用数据影响决策。
Excel 的产品目标不是这样的。Excel 可以做很多事情。你可以用 Excel 画一个课程表,做一个调查问卷,或者当计算器用,甚至可以用来绘图。如果你掌握了 VBA,你也可以做一个小游戏。但这些并不是真正的数据分析功能。

IMGUR, MICHELLEASAURR
但是 BI 工具是专门做数据分析的。
以 Power BI、FineReport、Tableau 等常见 BI 工具为例。你会发现它们是按照数据分析流程设计的。首先是数据处理、数据清理,然后是数据建模,最后是数据可视化,它使用图表演示来识别问题并影响决策。
这些是数据分析的必经之路,在这个过程中也有一些员工的痛点。
例如,清理数据的重复性和低附加值工作可以通过 BI 工具来简化。
如果数据量很大,传统工具 Excel 无法完成数据透视表。
如果我们用 Excel 做图形显示,编辑图表,包括颜色和字体设置,都要花很多时间。
这些痛点正是 BI 工具可以为我们带来改变和价值的地方。
现在我们来对比一下市面上比较流行的三款 BI 工具:Power BI、FineReport、Tableau。
1) Tableau
Tableau 的核心本质其实就是 Excel 的数据透视表和数据透视图。可以说,Tableau 敏锐地察觉到了 Excel 的这一特性。它较早进入 BI 市场,并将这一核心价值发扬光大。

从发展历史和目前市场反馈来看,Tableau 更擅长可视化。我不认为这是因为它的图表有多酷,而是它的设计、颜色和用户界面给我们一种简单清新的感觉。
这确实像 Tableau 自己宣传的,投入大量学术精力研究人们喜欢什么样的图表,如何在操作和视觉上给用户极致的体验。正如 Tableau 所宣传的那样,他们的团队投入了大量的学术精力来研究人们喜欢什么样的图表,以及如何在操作和视觉上给用户带来极致的体验。
此外,Tableau 还增加了数据清洗功能和更多智能分析功能。这也是 Tableau 可以预见的产品开发优势。
2) 异能匕
Power BI 的优势在于商业模式和数据分析能力。
Power BI 之前是 Excel 的插件,发展并不理想。所以它走出了 Excel,发展成了 BI 工具。Power BI 作为后来者,每个月都有迭代更新,追赶速度非常快。

Power BI 目前有三种许可方式:Power BI 免费版、Power BI 专业版和 Power BI 高级版。就像 Tableau 一样,其免费版的功能也不全。但是个人用也差不多够了。而 Power BI 的数据分析是强大的。它的 PowerPivot 和 DAX 语言允许我以类似于在 Excel 中编写公式的方式实现复杂的高级分析。
3) FineReport
FineReport 的独特之处在于,它的自助式数据分析非常适合商业用户。通过简单的拖放操作,您可以使用 FineReport 设计各种风格的报表,轻松构建数据决策分析系统。

From FineReport
FineReport 可以直接连接各种数据库,自定义各种样式制作周报、月报、年报,方便快捷。其格式类似于 Excel 的界面。包括报表创建、报表权限分配、报表管理、数据录入等功能。
此外,FineReport 的可视化功能也非常突出,提供了多种仪表盘模板和多个自主开发的可视化插件库。
价格方面,个人版 FineReport 完全免费,所有功能开放。
3.R & Python
R 和 Python 是我要说的第三类工具。虽然像 Excel 和 BI 工具这样的软件已经尽最大努力设计来考虑数据分析的大多数应用场景,但它们本质上是定制的。如果软件没有设计一个功能,或者为一个功能开发一个按钮,你很可能无法用它们来完成你的工作。
编程语言对此有所不同。它非常强大和灵活。你可以写代码做任何你想做的事情。比如 R 和 Python 就是数据科学家不可或缺的工具。从专业角度来说,它们绝对比 Excel 和 BI 工具强大。
那么有哪些是 R 和 Python 可以实现,而 Excel 和 BI 工具很难实现的应用场景呢?
1)专业统计分析
R 语言方面,最擅长统计分析,比如正态分布,用算法对聚类进行分类,回归分析。这种分析就像用数据做实验。它可以帮助我们回答以下问题。

From Google
比如数据的分布是正态分布,三角分布还是其他类型的分布?离散的情况是怎样的?是否在我们想要达到的统计可控范围内?不同参数对结果的影响有多大?而且还有假设模拟分析。如果某个参数发生变化,会带来多大的影响?
2)个体预测分析
例如,我们想要预测消费者的行为。他会在我们店里呆多久?他会花多少钱?我们可以查到他的个人信用状况,根据他的网上消费记录,做出贷款额度。或者我们可以根据他在网页上的浏览历史推送不同的项目。这也涉及到目前流行的机器学习和人工智能的概念。

结论
以上对比说明了几款软件的区别。我想总结的是,真实的就是合理的。Excel、BI 工具或编程语言有重叠的功能,但也是互补的工具。每种方法的价值取决于正在开发的应用程序的种类和当前的情况。
在你选择一个数据分析工具之前,你必须先了解你自己的工作:你是否会使用我刚才提到的应用场景。或者考虑一下你的职业方向:是走向数据科学还是商业分析。
您可能也会对…感兴趣
KPI 仪表板的前 7 种图表类型
KPI 已经成为各种商业组织的重要考核体系和方法,并贯穿于各种商业活动中。如何使用合适的可视化图表呈现实际结果和关键指标,实现实时监控,也一直是商业分析,乃至各种商业智能系统关注的焦点。
在今天的文章中,我总结了 KPI 仪表盘常用的 7 种图表类型,希望对你有用。
(注:本文所有图表和仪表盘均采用数据可视化工具 FineReport 制作,个人下载完全免费。)
1。数字文本
显示 KPI 最简单的方法是直接以文本形式列出数字。好处是非常直观。而且特别适合显示销售总额、营业额、财务分析利润总额、毛利率等核心指标。

From FineReport
这种图表类型的用法简单明了。但不建议列出多个数据,因为比较困难,数据之间缺乏关联性。此外,不同的颜色可以用作数字文本风格的区分。
2.单词云图表
词云图是一种直观显示数据频率的形式。它能在视觉上突出出现频率高的“关键词”,形成“关键词云层”,从而过滤掉大量的文本信息,让浏览者一目了然地抓住重点。
比如你汇报工作的时候,可以用几个突出的词来表达一年工作中最突出的点,形成“2019 关键词云”。

From FineReport
3.仪表板
仪表板可用于指标值的进度分析,以显示计划和实际结果之间的比较。为了同时显示,您可以使用多个仪表板。

除了刻度盘之外,还有一个百分比仪表盘,类似于甜甜圈图。这种图表类型的优点是可以清楚的看到数据的范围和大小,但是无法观察趋势变化是最大的缺点。


From FineReport
4.散点图
散点图用于显示不同数据点之间的关系,并比较不同时间段的趋势。效果如下图。


5.多系列折线图
多系列折线图用于查看同一区域内指标的趋势,可以直观的看到趋势对比。具有 KPI 的折线图可以同时显示多个数据系列,并自动计算差异率。

6.组合图表
组合图是多个图表的组合,如折线图、柱形图、饼图等。
让我们看一个折线图和堆积柱形图组合的例子。
在下面的组合图中,订单数量和再订购数量被累加,并与库存数量进行比较。如果累计总订单数量大于库存数量,则表明需要补货。

7.动态图表
最后,我将重点介绍 KPI 仪表板中常用的动态图表。上面说的 KPI 图表都是基本图表。其实要做一个清晰酷炫的 KPI 仪表盘,必须使用更高级的动态图表,让你的关键指标更加突出,更加醒目。
现在,我们来看看 FineReport 的几张动态图。
目录齿轮

定时齿轮

动态指示卡

发光仪表盘

GIS 点地图

说到这里,您可能想看看这些图表在 KPI 仪表板中的实际应用。所以我在 FineReport Demo 里找了几个仪表盘模板给你参考。
项目管理仪表板

投资管理系统

银行仪表板

公路监控仪表板

对了,如果想了解更多的图表类型,可以看看这篇文章: 数据可视化中的 16 大图表类型 。
您可能也会对…感兴趣
GitHub 上的 7 大数据科学课程

Photo by Carlos Muza on Unsplash
GitHub 是广为人知的最著名的版本控制库之一。在里面,你可以找到几乎无数的多种编程语言的公共项目。它让您可以轻松地与团队成员和全球的开发人员协作。你们可以一起从这些项目中学习,也可以为这些项目做出贡献。
GitHub 的一个伟大之处在于,你也可以把它作为搜索引擎来寻找你可以从中受益的伟大项目和资源。
许多教师或技术讲师使用它来发布他们的课程,包括课程笔记、作业、幻灯片和其他可供学生使用的材料。
他们公开并免费发布,这样每个人都可以访问,包括那些没有正式参加这些课程,但有兴趣学习并从中受益的人。
以下是在 GitHub 上发布资料的 8 门最受欢迎的数据科学课程的列表。排名分别基于每个存储库的分叉数量。
1.斯坦福 TensorFlow 教程(4072 个分叉)

这个库与斯坦福的 CS 20 课程相关联:深度学习研究的 TensforFlow】课程。课程网站上有详细的教学大纲、幻灯片和课堂讲稿。讲师用的是 python 3.6 和 TensorFlow 1.4.1。
以下是对课程的描述:
TensorFlow 是谷歌研究人员开发的一个强大的机器学习开源软件库。它有许多预构建的功能来简化构建不同神经网络的任务。TensorFlow 允许在不同的计算机之间分配计算,以及在一台机器内分配多个 CPU 和 GPU。TensorFlow 提供了一个 Python API,以及一个文档较少的 C++ API。在本课程中,我们将使用 Python。
本课程将涵盖深度学习研究中 Tensorflow 库的基础知识和当代用途。我们旨在帮助学生理解 TensorFlow 的图形计算模型,探索它必须提供的功能,并学习如何构建和构造最适合深度学习项目的模型。通过本课程,学生将使用 TensorFlow 建立不同复杂性的模型,从简单的线性/逻辑回归到卷积神经网络和递归神经网络,以解决诸如单词嵌入、翻译、光学字符识别、强化学习等任务。学生还将学习构建模型和管理研究实验的最佳实践。
2.Coursera 上的深度学习专业化(3,352 个分叉)

这是一个由一名学生创建的知识库,他发布了 Coursera 深度学习专业的编程作业和解决方案。
它不是一个装满课程或学习资源的存储库。不过可以用来稍微好一点理解深度学习相关的一些概念。将您的解决方案与该存储库中提供的解决方案进行比较也很有用。
以下是你可以找到编程作业和提问的课程列表:
- 课程 1:神经网络和深度学习
- 课程 2:改进深度神经网络:超参数调整、正则化和优化
- 课程 3:构建机器学习项目
- 课程 4:卷积神经网络
- 课程 5:序列模型
3.实用 RL:野外强化学习课程(3368 叉)

以下课程有英语和俄语的在线版本,但在高等经济学院教授俄语。
已经进行了 9 周,存储库还包含额外的材料,可供现场参加课程或只想在线学习的学生使用。
这是一门侧重于实用机器学习的课程,涵盖如下主题:
- 简介。我们周围的问题。决策过程。随机最优化,交叉熵方法。参数空间搜索与动作空间搜索。
- 基于价值的方法。打折奖励 MDP。基于价值的方法。价值迭代。政策迭代。打折奖励失败。
- 无模型强化学习。q-学习。萨莎。策略外算法与策略内算法。n 步算法。TD(λ)。
- 深度学习回顾。深度学习 101。它附带了一个研讨会,介绍 pytorch/tensorflow,使用 convnets 进行简单的影像分类
- 近似(深)RL。无限/连续状态空间。价值函数近似。收敛条件。多重代理诡计;经验重放,目标网络,双/决斗/自举 DQN 等。
- 探索。语境强盗。汤普森抽样,UCB,贝叶斯 UCB。探索基于模型的 RL,MCTS。探索的“深度”启发法。
- 政策梯度方法。基于政策的动机、政策梯度、对数导数技巧、强化/交叉熵方法、方差缩减(基线)、优势行动者-批评家(包括 GAE)
- 序列模型的强化学习。顺序数据的问题。循环神经网络。时光倒流。消失&爆炸渐变。格鲁·LSTM,《渐变裁剪》
- 部分观察到 MDP。 POMDP 简介。POMDP 学习(有记忆的代理)。POMDP 规划(POMCP 等)
- 先进的基于政策的方法。信任区域策略优化。NPO/PPO。确定性政策梯度。DDPG
- 基于模型的强化学习& Co. 基于模型的强化学习,一般规划,模仿学习和逆向强化学习
- 逆 RL 和模仿学习。这门课没有教的所有东西
4.深度学习与 Tensorflow 的创造性应用(1341 个分叉)

这门课程有 Kadenze 学院利用 TensorFlow 课程创造性应用深度学习的作业和讲稿。
本课程包括以下几个部分:
- 会议 1:张量流简介
- 会议 3:无监督和有监督的学习
- 会议 4:视觉化和幻觉化的表现
- 会议 5:生成模型
该存储库还包含大量关于安装和开始使用所需工具的文档。
5.数据科学 Coursera (714 分叉)

这个存储库是由一位名叫 Michael Galarnyk 的数据科学硕士学生准备的。他创建了这个存储库来记录他在约翰霍普金斯大学 Coursera 数据科学课程中的经历,作为他在加州大学圣地亚哥分校项目的补充。
这个 GitHub 库包含每周的相应目录,以及每个课程的博客帖子。
以下课程与相应的回购和博客相关联:
6.Udacity 的机器学习工程师 Nanodegree 斯坦福用于视觉识别的卷积神经网络(69 叉)

已经有许多 GitHub 仓库与 Udacity 的机器学习工程师 Nanodegree 相关,这个带有一个有用的自述文件。
它有关于如何使用内容的信息,与课堂材料相关的超链接,以及对学生有用的附加链接,如 Andrej Karpathy 的博客,Andrew Trask 的博客等。
当学生完成作业后,他们会被邀请在知识库中分享他们的解决方案,以便其他人可以查看并从中受益。
7.Hadoop 和 MapReduce 介绍(47 个分支)

这个存储库与 Udacity 的 Hadoop 和 MapReduce 入门课程相关。
它包含源代码和问题集,以及演示设置方法的有用的自述文件、输入和输出数据文件的文档以及课程的问题集,并提供 Python 和 Java 的解决方案。
这只是根据叉子的数量列出的一些最受欢迎的课程。有许多其他的存储库可以作为有用的资源来学习和受益。
快乐学习!
感谢您抽出时间阅读。
请关注我的 推特
现在要学习的 7 种现代编程语言
权威指南
Rust、Go、Kotlin、TypeScript、Swift、Dart、Julia 如何促进您的职业发展并提高您的软件开发技能

Photo by h heyerlein on Unsplash
如果我们把现代人类文明想象成一辆汽车,那么软件开发行业就像汽车的发动机,编程语言就像发动机的燃料。应该学习哪种编程语言?
学习一门新的编程语言是对时间、精力和智力的巨大投资。但是学习一门新的编程语言可以提高你的软件开发技能,并给你的职业生涯带来提升,正如我在另一篇博客中所写的:
学习一门新的编程语言来提升你的职业和技能
medium.com](https://medium.com/@md.kamaruzzaman/5-reasons-to-learn-a-new-programming-language-in-2020-bfc9a4b9a763)
通常情况下,选择一种在职业生涯中给你助力的编程语言。还有,学一门人气上升的语言。这意味着你应该学习成熟的和非常流行的编程语言。在这里,我列出了 2020 年要学习的 10 种主流编程语言:
针对求职者和新开发人员的顶级编程语言的深入分析和排名
medium.com](https://medium.com/@md.kamaruzzaman/top-10-in-demand-programming-languages-to-learn-in-2020-4462eb7d8d3e)
我非常尊重主流编程语言。但是在这里,我会给你一个现代编程语言的列表,它可以提高你的生产力,促进你的职业发展,让你成为一个更好的开发者。此外,我将涉及广泛的领域:系统编程、应用程序开发、web 开发、科学计算。

术语“现代编程语言”有歧义。许多人认为像 Python、JavaScript 这样的语言是现代编程语言。同时,他们认为 Java 是一种古老的编程语言。现实中,它们都在同一时间前后出现: 1995 。
主流编程语言大多是在上个世纪开发的,主要是70 年代(如 C)、80 年代(如 C++)、90 年代(如 Java、Python、JavaScript) 。这些语言并不是为了利用现代软件开发生态系统而设计的:多核 CPU、GPU、快速网络、移动设备、容器和云。尽管他们中的许多人在他们的语言中有类似并发性的改进特性,并且进行了自我调整,但是他们也提供了向后兼容性,并且不能抛弃旧的、过时的特性。
Python 在 Python 2 和 Python 3 之间做得很好(或者很差,取决于上下文)。那些语言通常提供 10 种方法来做同样的事情,并且不关心开发人员的人机工程学。根据 StackOverflow 开发者调查,大多数主流老编程语言都在“最可怕的语言类别中名列前茅:

Source: Stackoverflow
我认为新旧编程语言的明确界限是在 2007 年 6 月 29 日,第一代 iPhone 发布的时候。在那之后,景观发生了变化。在这个列表中,我将考虑 2007 年后的编程语言。

首先,开发现代编程语言是为了充分利用现代计算机硬件(多核 CPU、GPU、TPU) 、移动设备、大数据集、快速联网、容器和云。此外,大多数现代编程语言提供了更高的开发人员工效学,如下所示:
- 简洁明了的代码(较少的样板代码)
- 对并发的内置支持
- 空指针安全
- 类型推理
- 更简单的功能集
- 降低认知负荷
- 融合了所有编程范例的最佳特性
第二,列表中的许多编程语言具有颠覆性,并将永远改变软件行业。其中一些已经是主流编程语言,而另一些正准备取得突破。至少把这些语言作为第二编程语言来学习是明智的。
在之前的一篇博文《关于 2020 年软件发展趋势的 20 个预测》中,我已经预测了 2020 年许多现代语言的突破:
云、容器、编程、数据库、深度学习、软件架构、Web、App、批处理、流、数据湖…
towardsdatascience.com](/20-predictions-about-software-development-trends-in-2020-afb8b110d9a0)
锈

Source: Thoughtram
系统编程语言领域被类似 C、C++的准金属语言所主导。尽管它们对程序和硬件有完全的控制权,但它们缺乏内存安全性。即使它们支持并发,使用 C/C++编写并发程序也是一个挑战,因为没有并发安全性。其他流行的编程语言是解释型语言,如 Java、Python、PHP。它们提供了安全性,但需要庞大的运行时或虚拟机。像 Java 这样的语言由于运行时间长,不适合系统编程。
有很多尝试将 C/C++的强大功能和 Haskell、Java 的安全性结合起来。看起来 Rust 是第一个成功的产品级编程语言。
Graydon Hoare 最初开发 Rust 是作为一个附带项目。他受到了研究编程语言气旋的启发。Rust 是开源的,Mozilla 与许多其他公司和社区一起领导着语言开发。Rust 于 2015 年首次发布,并很快吸引了社区的目光。在之前的一篇文章中,我深入研究了 Rust,并论证了在大数据领域使用 Rust 优于 C++、Java 的原因:
[## 回归金属:2019 年开发大数据框架的 3 大编程语言
C++,Rust,用 Java 做数据密集型框架
towardsdatascience.com](/back-to-the-metal-top-3-programming-language-to-develop-big-data-frameworks-in-2019-69a44a36a842)
主要特点:
- 通过所有权和借用的概念提供内存安全和并发安全。
- 内存安全和并发性安全的编译时保证,即如果一个程序代码被编译,那么它既是内存安全的,也是无数据竞争的。这是 Rust 最吸引人的特性。
- 它还提供了 ML,Haskell 的表现力。凭借不可变的数据结构和函数式编程特性,Rust 提供了函数式并发和数据并发。
- 生锈的速度快得惊人。根据 基准测试游戏 ,惯用 Rust 的性能优于惯用 C++。
- 由于没有运行时,Rust 提供了对现代硬件(TPU、GPU、多核 CPU)的完全控制。
- Rust 有 LLVM 支持。因此,Rust 提供了与 WebAssembly 的一流互操作性,并允许极快的 Web 代码。
人气:
自 2015 年首次亮相以来,Rust 深受开发者的欢迎,并在 StackOverflow 开发者调查中连续四年(2016、2017、2018、2019) 被评为最受喜爱的语言:

Source: Stackoverflow
根据 GitHub Octoverse 的说法,Rust 是仅次于 Dart 的第二大发展最快的语言:

Source: Octoverse
此外,编程语言流行网站 PyPl 将 Rust 排在第 18 位,并且呈上升趋势:

Source: PyPl
比较它所提供的功能,难怪像微软、亚马逊、谷歌这样的大型科技公司最终宣布投资 Rust 作为长期系统编程语言。
在过去的 5 年里,Rust 每年都在增加牵引力,正如 Google trends 所显示的:

Source: Google Trends
主要使用案例:
- 系统程序设计
- 无服务器计算
- 商业应用
主要竞争对手语言:
- C
- C++
- 去
- 迅速发生的
去

Source: Wikimedia
谷歌是最大的网络规模公司之一。本世纪初,Google 曾面临过两个缩放问题:开发缩放和应用缩放。开发规模意味着他们不能通过投入更多的开发人员来增加更多的特性。应用程序伸缩性意味着他们不容易开发一个可以伸缩到“Google”规模的机器集群的应用程序。大约在 2007 年,谷歌开始创造一种新的“实用的编程语言,可以解决这两个缩放问题。在 Rob Pike (UTF-8)和 Ken Thompson (UNIX 操作系统),他们有两个世界上最有才华的软件工程师来创造一种新的语言。
2012 年,谷歌发布了第一个官方版本的 Go 编程语言。Go 是一种系统编程语言,但不同于 Rust。它还有一个运行时和垃圾收集器(几兆字节)。但是与 Java 或 Python 不同,这个运行时打包了生成的代码。最终,Go 生成一个单独的本机二进制代码,可以在机器上运行,而不需要额外的依赖或运行时。
主要特性:
- Go 拥有一流的并发支持。它没有通过线程和锁提供“共享内存”的并发性,因为编程要困难得多。相反,它提供了一个基于 CSP 的消息传递并发性(基于东尼·霍尔的论文)。Go 使用“ Goroutine ”(轻量级绿色线程)和“通道”进行消息传递。
- 围棋最大的杀手锏就是简单。它是最简单的系统编程语言。一个新的软件开发人员可以像 Python 一样在几天内编写出高效的代码。一些最大的云原生项目( Kubernetes,Docker )是用 Go 编写的。
- Go 还具有嵌入式垃圾收集器,这意味着开发人员不需要像 C/C++那样担心内存管理。
- 谷歌在围棋上投入了大量资金。因此,Go 拥有大量的工具支持。对于新的围棋开发者来说,有一个庞大的工具生态系统。
- 通常,开发人员花 20%的时间编写新代码,80%的时间维护现有代码。由于其简单性,Go 在语言维护领域表现出色。如今,围棋在商业应用中被大量使用。
人气:
自从 Go first 出现以来,软件开发社区已经欣然接受了它。在 2009 (刚出道不久)和 2018 ,Go 已经由 TIOBE 指数 进入编程语言名人堂榜单。难怪 Go 的成功为 Rust 这样的新一代编程语言铺平了道路。
Go 已经是主流编程语言了。最近,Go 团队宣布了对“ Go 2 ”的工作,只是为了让语言更加扎实:
在几乎所有比较网站的流行编程语言中,Go 排名都很高,已经超过了很多现有的语言。以下是 2019 年 12 月的 TIOBE 指数评级,Go 排名第 15 位:

Source: TIOBE
根据 Stackoverflow 的调查,Go 是十大最受欢迎的编程语言之一:

Source: Stackoverflow
根据 GitHub Octoverse 的调查,Go 也是十大发展最快的语言之一:

Source: Octoverse
Google trends 还显示,在过去五年中,围棋的发展势头越来越猛:

Source: Google Trends
主要使用案例:
- 系统程序设计
- 无服务器计算
- 商业应用
- 云原生开发
主要竞争对手语言:
- C
- C++
- 锈
- 计算机编程语言
- Java 语言(一种计算机语言,尤用于创建网站)
科特林

Java 是无可争议的企业软件开发之王。最近,Java 成了众矢之的:它冗长,需要大量样板代码,容易出现意外的复杂性。但是关于 Java 虚拟机(JVM) 的争论很少。JVM 是软件工程的杰作,它提供了一个久经沙场的运行时,通过了时间的考验。在之前的一篇文章中,我已经详细讨论了 JVM 的优势:
大数据框架概述
towardsdatascience.com](/programming-language-that-rules-the-data-intensive-big-data-fast-data-frameworks-6cd7d5f754b0)
多年来,像 Scala 这样的 JVM 语言试图回答 Java 的缺点,想要成为更好的 Java,但是失败了。最后,在 Kotlin 中,对更好的 Java 的探索似乎结束了。Jet Brains(流行的 IDE IntelliJ 背后的公司)开发了 Kotlin,它运行在 JVM 上,解决了 Java 的缺点,并提供了许多现代功能。最棒的是,与 Scala 不同, Kotlin 比 Java 简单得多,并在 JVM 中提供了类似 Go 或 Python 的开发效率。
谷歌已经宣布 Kotlin 是开发 Android 的一流语言,并提高了 Kotlin 在社区中的接受度。同样热门的 Java 企业框架 Spring 从 2017 年开始在 Spring 生态系统中支持 Kotlin。我用过 Kotlin 的反作用力弹簧,体验非常棒。
主要特点:
- Kotlin 的 USP 是它的语言设计。我总是将 Kotlin 视为 JVM 上的 Go/Python,因为它的代码干净、简洁。因此,科特林的生产力很高。
- 像许多其他现代语言一样,Kotlin 提供了空指针安全、类型推断等特性。
- 由于 Kotlin 也运行在 JVM 中,所以可以使用现有的庞大的 Java 库生态系统。
- Kotlin 是开发 Android App 的一流语言,早已超越 Java 成为开发 Android App 的头号编程语言。
- Kotlin 由 JetBrains 和开源软件支持。因此,Kotlin 拥有出色的工具支持。
- 有两个有趣的项目: Kotlin Native (将 Kotlin 编译成本机代码)和 kotlin.js (Kotlin 转 JavaScript)。如果他们成功了,那么 Kotlin 可以在 JVM 之外使用。
- Kotlin 还提供了一种简单的方法来编写 DSL(领域特定语言)
人气:
自 2015 年首次发布以来,Kotlin 的人气正在飙升。根据堆栈溢出,Kotlin 是 2019 年第四大最受欢迎的编程语言:

Source: Stackoverflow
Kotlin 也是发展最快的编程语言之一,排名第四:

Source: Github Octoverse
流行编程语言排名网站 PyPl 将 Kotlin 列为第 12 大最流行编程语言,并呈现出高上升趋势:

Source: Pypl
自从谷歌宣布 Kotlin 是开发 Android 应用的一流语言以来,Kotlin 在趋势方面经历了巨大的积极推动,如下所示:

Source: Google Trends
主要使用案例:
- 企业应用
- Android 应用程序开发
主要竞争对手语言:
- Java 语言(一种计算机语言,尤用于创建网站)
- 斯卡拉
- 计算机编程语言
- 去
以打字打的文件

JavaScript 是一种优秀的语言,但 2015 年以前的 JavaScript 有许多缺点。甚至著名的软件工程师道格拉斯·克洛克福特也写了一本书“JavaScript:好的部分”并暗示 JavaScript 有不好的部分和丑陋的部分。没有模块化和“回调地狱”,开发人员不喜欢维护特别大的 JavaScript 项目。
谷歌甚至开发了一个将 Java 代码转换成 JavaScript 代码的平台( GWT )。许多公司或个人试图开发更好的 JavaScript,例如 CoffeeScript、Flow、ClojureScript 。但是微软的 TypeScript 可以说是中了大奖。由著名的安德斯·海尔斯伯格(Delphi、Turbo Pascal、C#)领导的一组微软工程师创建了 TypeScript,作为 JavaScript 的静态类型化、模块化超集。
TypeScript 在编译期间被转换为 JavaScript。它于 2014 年首次发布,迅速吸引了社区的关注。Google 当时也计划开发一个静态类型的 JavaScript 超集。谷歌对 TypeScript 印象深刻,他们没有开发新的语言,而是与微软合作改进 TypeScript。
Google 已经使用 TypeScript 作为其 SPA 框架的主要编程语言 Angular2+ 。此外,流行的 SPA 框架 React 提供了对 TypeScript 的支持。另一个流行的 JavaScript 框架 Vue.js 已经宣布他们将使用 TypeScript 开发新的 Vue.js 3:

Source: Vue.js Roadmap
此外,node.js 创建者 Ryan Dahl 已经决定使用 TypeScript 来开发一个安全的 Node.js 替代方案 Deno 。
主要特性:
- 就像列表中的 Go 或 Kotlin 一样,TypeScript 的主要特征是语言设计。凭借其简洁明了的代码,它是最优雅的编程语言之一。就开发者生产力而言,在 JVM 或 Go/Python 上与 Kotlin 不相上下。TypeScript 无疑是最高效的 JavaScript 超集。
- TypeScript 是 JavaScript 的强类型超集。它特别适合大型项目,被恰当地称为“可扩展的 JavaScript”。
- “三巨头”单页面应用程序框架( Angular,React,Vue.js )为 TypeScript 提供了出色的支持。在 Angular 中,TypeScript 是首选的编程语言。在 React 和 Vue.js 中,TypeScript 越来越受欢迎。
- 两个最大的科技巨头:微软和谷歌(T21)正在合作开发由活跃的开源社区支持的 TypeScript。因此,对 TypeScript 的工具支持是最好的之一。
- 由于 TypeScript 是 JavaScript 的超集,它可以在 JavaScript 运行的地方运行:无处不在。TypeScript 可以在浏览器、服务器、移动设备、物联网设备和云上运行。
人气:
开发人员喜欢 TypeScript 优雅的语言设计。在 Stackoverflow 开发者调查中,它在最受欢迎的语言类别中与 Python 并列第二:

Source: Stackoverflow
TypeScript 是发展最快的 Web 编程语言之一,根据 GitHub Octoverse 排名第五:

Source: Octoverse
根据 GitHub 的贡献,TypeScript 也进入了前 10 名(排名第 7):

Source: Octoverse
TypeScript 在过去的一年里吸引了越来越多的眼球,这从 Google Trends 中可以看出:

Source: Google Trends
主要使用案例:
- Web UI 开发
- 服务器端开发
主要竞争对手语言:
- Java Script 语言
- 镖
迅速发生的

史蒂夫·乔布斯(Steve Jobs)拒绝在 iOS 系统中支持 Java (和 JVM ),因为他引用了一句著名的话:Java 不再是主流编程语言。我们现在知道史蒂夫·乔布斯对 Java 的评估是错误的,但 iOS 仍然不支持 Java。相反,苹果选择了 Objective-C 作为 iOS 的一流编程语言。Objective-C 是一种很难掌握的语言。此外,它不支持现代编程语言所要求的高开发效率。
在苹果,克里斯·拉特纳和其他人开发了 Swift 作为一种多范式、通用的编译编程语言,提供了 Objective-C 的替代方案。Swift 的第一个稳定版本于 2014 年发布。Swift 还支持 LLVM 编译器工具链(同样由克里斯·拉特纳开发)。Swift 与 Objective-C 代码库具有出色的互操作性,并且已经成为 iOS 应用程序开发的主要编程语言。
主要特点:
- Swift 的杀手锏之一是它的语言设计。凭借更简单、简洁和清晰的语法,它为 Objective-C 提供了一个更高效的替代方案。
- Swift 还提供了现代程序语言的特性:空安全。此外,它还提供了避免“末日金字塔”的句法糖。
- 作为编译语言,Swift 和 C++一样快。
- Swift 支持 LLVM 编译器工具链。所以,我们可以在服务器端编程甚至浏览器编程(使用 WebAssembly)中使用 Swift。
- Swift 提供自动引用计数(ARC) 支持,从而限制内存管理不当。
人气:
开发人员喜欢 Swift 编程语言,就像许多其他现代语言一样。根据 StackOverflow 的调查,Swift 在最受欢迎的编程语言中排名第六:

在 TIOBE 的编程语言排名中,Swift 在 2019 年已经移动到了数字 10 的排名。考虑到这种语言是多么年轻(5 年),这是一个了不起的成就:

Source: TIOBE Index
Google 趋势还显示 Swift 的受欢迎程度急剧上升,随后在最近几个饱和期趋势略有下降:

Source: Google Trends
主要使用案例:
- iOS 应用程序开发
- 系统程序设计
- 客户端开发(通过 WebAssembly)
主要竞争对手语言:
- 目标-C
- 锈
- 去
镖

Dart 是 Google 做的这个列表中的第二种编程语言。谷歌是 Web 和 Android 领域的关键参与者,谷歌在 Web 和应用程序开发领域开发自己的编程语言也就不足为奇了。在丹麦著名软件工程师 Lars Bak(他领导了 Chrome 的 V8 JavaScript 引擎的开发)的带领下,谷歌已经在 2013 年发布了 Dart。
Dart 是一种通用编程语言,支持强类型和面向对象编程。Dart 还可以转换为 JavaScript,可以在 JavaScript 运行的地方运行,这意味着几乎可以在任何地方运行(例如 Web、移动设备、服务器)。
主要特点:
- 像其他 Google 语言 Go 一样,Dart 也非常注重开发人员的生产力。Dart 非常高效,并且因为其干净、简单、简洁的语法而受到开发人员的喜爱。
- Dart 还提供强类型和面向对象编程。Dart 也是这个列表中的第二种语言,它符合“可伸缩 JavaScript 标签。
- Dart 是少数支持 JIT 编译(运行时编译)和AOT 编译(创建时编译)的语言之一。因此,Dart 可以以 JavaScript 运行时(V8 引擎)为目标,并且 Dart 可以被编译为快速本机代码(AOT 编译)
- 跨平台原生应用开发平台 Flutter 选择 Dart 作为开发 iOS 和 Android 应用的编程语言。从那以后,Dart 变得更加流行。
- 和其他 Google 编程语言 Go 一样,Dart 也有优秀的工具支持和庞大的 Flutter 生态系统。 Flutter 越来越受欢迎只会增加 Dart 的采用。
人气:
根据 Github Octoverse 的数据,Dart 是 2019 年增长最快的编程语言,其受欢迎程度在去年翻了五倍:

根据 TIOBE 指数,Dart 排名第 23 位,仅用了 4 年时间就已经超过了许多现有的和现代的编程语言:

Source: TIOBE index
它也是最受欢迎的编程语言之一,在 StackOverflow 开发者调查中排名第 12 位:

Source: StackOverflow
与 Flutter 一样,Dart 在过去两年中也经历了巨大的牵引力,这一点从 Google Trends 中可以清楚地看出:

Source: Google Trends
主要使用案例:
- 应用程序开发
- UI 开发
主要竞争对手语言:
- Java Script 语言
- 以打字打的文件
朱莉娅

列表中的大多数编程语言都是由大公司开发的,除了 Julia。在技术计算中,通常使用像 Python、Matlab 这样的动态语言。这些语言提供了易于使用的语法,但不适合大规模的技术计算。他们使用 C/C++库来完成 CPU 密集型任务,这就产生了著名的双语问题,因为他们需要胶水代码来绑定两种语言。当代码在两种语言之间翻译时,总会有一些性能损失。
为了解决这个问题,麻省理工学院的一组研究人员计划从头开始创建一种新的语言,它利用现代硬件的优势,并结合了其他语言的最佳部分。他们在麻省理工学院创新实验室工作,有以下宣言:

Source: Julia Presentation
Julia 是一种动态的高级编程语言,为并发、并行和分布式计算提供一流的支持。Julia 的第一个稳定版本于 2018 年发布,并很快受到社区和行业的关注。Julia 可以用于科学计算、人工智能和许多其他领域,并且可以最终解决“双语”问题。
功能:
- 像 Rust 一样,Julia 的主要特点是语言的设计。它试图在不牺牲性能的情况下,结合现有编程语言在高性能和科学计算方面的一些最佳特性。到目前为止,它做得很好。
- Julia 是一种动态编程语言,具有可选类型。因此,Julia 很容易学习编程语言,而且生产率很高。
- 它在其核心使用了多分派编程范例。
- 它内置了对并发、并行和分布式计算的支持。
- 它还为 I/O 密集型任务提供了异步 I/O 。
- 它快得惊人,可以用在需要数百万线程的科学计算中。
人气:
Julia 主要在很多领域与 Python 竞争。由于 Python 是最流行的编程语言之一,Julia 将成为主流还需要几年时间。
朱莉娅相对较新(只有一岁),但在 TIOBE 指数中仍排在第 43 位:

Source: TIOBE
谷歌趋势也显示了多年来对朱莉娅的稳定兴趣。

但是考虑到功能集和支持 Julia 的公司数量,如 NSF、DARPA、NASA、Intel、,Julia 取得突破只是时间问题,而不是如果:
主要使用案例:
- 科学计算
- 高性能计算
- 数据科学
- 形象化
主要竞争对手语言:
- 计算机编程语言
- 矩阵实验室
如果你觉得这很有帮助,请分享到你最喜欢的论坛上( Twitter,LinkedIn,脸书)。
如果你对编程语言感兴趣,也可以看看我下面的文章:
云、边缘、容器、量子、区块链、AI、深度学习、批处理、流媒体、数据库、编程、软件……
towardsdatascience.com](/21-predictions-about-the-software-development-trends-in-2021-600bfa048be) [## 2020 年最受欢迎的 10 种编程语言
针对求职者和新开发人员的顶级编程语言的深入分析和排名
medium.com](https://medium.com/@md.kamaruzzaman/top-10-in-demand-programming-languages-to-learn-in-2020-4462eb7d8d3e) [## 2020 年前端开发的五大热门 JavaScript 框架
为前端开发人员、求职者和其他人提供的顶级 JavaScript 框架的深入分析和排名
我在数据科学硕士课程中学到的 7 件事
尽管我还在学习,这里还是列出了我学到的最重要的东西(到目前为止)。
其中一些你已经很熟悉了,但是我不建议跳过它们——另一种观点总是很有用的。

Photo by Charles DeLoye on Unsplash
1.总是咨询领域专家
我说的“总是”是指如果你有机会这样做的话。
这是最先学会的事情之一。我们被介绍给这个家伙,当谈到数据世界时,他就像一个摇滚明星,更准确地说是搅动建模。听到这句话的时候,可能是我关于数据科学的第一个神话被打破的时候。
你可以在这里阅读更多关于他和整个案件的信息:
最近我写了一篇关于递归特征消除的文章,这是我最常用的特征选择技术之一…
towardsdatascience.com](/attribute-relevance-analysis-in-python-iv-and-woe-b5651443fc04)
最初,我认为数据科学家是一种罕见的物种,只要提供正确的数据,他们几乎可以做任何事情。但是在大多数情况下,这个与事实相去甚远。是的,你可以用一切来分析一切,这样做你会发现一些有趣的东西,但这真的是对你时间的最佳利用吗?
问问你自己,
问题是什么?X 如何连接到 Y?为什么?
了解这些将会引导你找到解决问题的好方向。这正是领域专家派上用场的时候。
另一件真正重要的事情是特色工程。同一位教授强调指出,您可以使用领域专家进行特征工程过程。如果你花一分钟思考一下,这是有道理的。
2.你将花费大部分时间准备数据
是的,你没看错。
我参加数据科学硕士课程的最大原因之一是机器学习——我不太关心数据是关于什么的,以及数据是如何收集和准备的。由于这种态度,当学期开始时,我有点震惊和失望。
当然,如果你在一家既有数据工程师又有机器学习工程师的大公司工作,这可能不适用于你,因为你一天的大部分时间都在做机器学习。但如果不是这样,你只会花大约 15%的时间进行机器学习。
这其实很好。机器学习并不那么有趣。在你跳到评论区之前,听我说完。
https://giphy.com/gifs/breaking-bad-huh-say-what-l41YkFIiBxQdRlMnC
我认为机器学习并不那么有趣的原因是,对于大多数项目来说,它归结为尝试几种学习算法,然后优化最佳算法。
如果您在此之前没有做好工作,因此在数据准备过程中,您的模型很可能会很糟糕,您对此无能为力,除了调整超参数、调整阈值等。
这就是为什么数据准备和探索性分析才是王道,机器学习只是它之后自然而然的事情。
一旦我意识到我已经失去了对机器学习的大部分宣传。我发现我更喜欢数据收集和可视化,因为我在那里学到了最多的数据。
特别是,我真的很喜欢网络抓取,因为相关的数据集很难找到。如果这听起来像是你喜欢东西,请看看这篇文章:
使用 Python 和 BeautifulSoup 的强大功能来收集对您重要的数据。
towardsdatascience.com](/no-dataset-no-problem-scrape-one-yourself-57806dea3cac)
3.不要多此一举
图书馆的存在是有原因的。行动之前先谷歌一下。
我会给你看一个你可能没有犯过的“错误”的小例子,但它会帮助你理解这一点。
关于计算中位数的两种方法。中位数定义为:
数字排序列表的中间部分。
因此,要计算它,您必须实现以下逻辑:
- 对输入列表排序
- 检查列表的长度是偶数还是奇数
- 如果是偶数,中位数是两个中间数的平均值
- 如果是奇数,中值就是中间的数字
幸运的是,有像 Numpy 这样的库,它可以帮你完成所有繁重的工作。看看下面的代码就知道了,前 17 行指的是自己计算中位数,后两行用 Numpy 的力量达到了同样的效果:
Median calculation — https://gist.github.com/dradecic/7f295913c01172ffebe84052c8158703
正如我所说的,这只是一个你自己可能没有做过的微不足道的例子。但是想象一下,你写了多少行代码都是徒劳的,因为你没有意识到已经有一个这样的库了。
4.掌握 lambdas 和列表理解
虽然不是数据科学的特定内容,但我会说我一直使用 列表理解 进行特性工程,使用 lambda 函数进行数据清理和准备。
下面是特征工程的一个简单例子。给定一个字符串列表,如果给定的字符串包含一个问号(?)否则为 0。你可以看到,无论有没有列表理解,你都可以做到这一点( 提示 :它们可以节省大量时间):
List Comprehension Example — https://gist.github.com/dradecic/9f23eb0c8073ecc8957f8fd533388cef
现在对于 lambdas ,假设你有一个你不喜欢格式的电话号码列表。基本上你要把' / '换成' - '。这几乎是一个微不足道的过程,只要你的数据集是Pandasdata frame 格式:
Lambdas — https://gist.github.com/dradecic/68e81f6610b26fe8da68e25d217c5052
花点时间想想如何将这些应用到您的数据集。很酷,对吧?
5.了解你的统计数据
如果你没有生活在岩石下,你就知道统计学在数据科学中的重要性。这是你必须发展的基本技能。
让我引用 T2 的话:
统计用于处理现实世界中的复杂问题,以便数据科学家和分析师可以在数据中寻找有意义的趋势和变化。简而言之,通过对数据进行数学计算,统计可用于从数据中获得有意义的见解。[1]
从我迄今为止从我的硕士课程中学到的关于统计学的知识来看,你有必要了解它,以便能够提出正确的问题。
如果你的统计技能生疏了,我强烈建议你看看 YouTube 上的 StatQuest 频道,更准确地说是基于统计的播放列表:
Statistics Playlist
6.学习算法和数据结构
如果你不能提供解决方案,问正确的问题(见第 5 点)就没有意义,对吗?
我因为忽视算法和数据结构而感到内疚,因为我认为只有软件工程师才应该担心这些。至少可以说,我大错特错了。
我并不是说你必须在睡觉的时候知道如何编写二进制搜索算法,但只是一个基本的理解会帮助你更清楚地了解如何用代码思考——因此,如何编写代码来完成工作,而且尽可能快地完成工作。
对于一个没有计算机科学背景的人来说,我强烈推荐这门课程:
请注意:如果你是一个完全的 PYTHON 初学者,请查看我的另一门课程:完整的 PYTHON BOOTCAMP 来学习…
www.udemy.com](https://www.udemy.com/course/python-for-data-structures-algorithms-and-interviews/)
此外,确保查看面试问题——它们非常有用!
7.超出范围
永远做那个努力工作的人。有回报。
至少在我的情况下,我的小组是根据其中一门课的最初表现来评估的。这不是关于谁知道的最多,因为这在第一学期会是一件愚蠢的事情,而是关于谁会表现出职业道德和纪律。
因为那时我没有全职工作,所以我为了这个项目拼命工作。因为我做了,而别人没有,所以我被指派了一个全方位的数据科学项目,这个项目将持续两年,并将为我的硕士论文服务。
是的,我可以把它写进我的简历。
所以,牺牲几周的个人生活值得吗?你自己判断吧,但我会说是的。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
参考
[1]https://www . edu reka . co/blog/math-and-statistics-for-data-science/
2019 年数据可视化软件的 7 大趋势
数据提取和数据管理是公司在当今世界面临的两大挑战。业务流程中从数据到信息的转换有助于实现业务目标。它的组织和分类是业务流程中的主要障碍。数据可视化软件就是为了克服这些障碍而诞生的。

Data visualization from FineReport
数据来自不同的来源,并且是在不同的时间或时期收集的。一个信息代理通过提供他们的数据需求来帮助企业。从不同时间段收集的数据的累积问题是对组织的数据管理技能的考验。目前,该软件提供数据管理辅助业务。
1.什么是数据可视化软件?
用于处理大量数据的软件也提供数据可视化功能。数据可视化是分组数据的图形化表示,有助于用户制定有效及时的决策。顶级数据可视化实践由标准化的过程、数据可视化的清晰分组、数据分析和数据呈现组成。在未来,预期的顶级数据可视化实践将是将在分析过程中使用的数据的故事化。

数据可视化软件有助于增加组织内部和外部收集的数据的价值。它帮助企业收集相关数据、制定策略和改进业务流程。该软件还通过创建每日、每周、每月、每年销售额的图形表示,帮助销售部门监控销售信息。这也可以为决策者生成报告。
据 Cision 美通社报道,数据可视化市场的 CARG 预计将超过 9%。预测期为 2019 年至 2024 年。
公司必须了解其在数据管理和数据可视化方面的具体需求。这有助于企业确定满足其独特需求的最佳数据可视化工具。
拥有大量数据的企业需要强大的数据可视化软件。大数据可视化工具提供多种功能,为组织提供数百种优势和有效帮助。

公司必须拥有有竞争力的项目管理开发人员和系统,以实现有效的数据可视化。对于开发人员来说,最好的在线项目管理软件应该能够帮助开发人员满足竞争和更新的技术需求。它应该能够帮助解决开发人员的问题,如延迟、糟糕的结果和超预算。
因此,了解什么是云服务器以及它们对数据可视化的影响是很重要的。云服务器是基于计算机的服务器,采用云计算技术。它提供了高科技的硬件和软件集成的可能性,以有效地协助其用户的日常运作。
2.数据可视化软件的重要特性
互联网上提供了多个数据可视化工具示例。这些工具的价格、功能、特性和设计各不相同。
以下是数据可视化软件拥有的重要功能。
2.1 各种图形设计
数据可视化软件是一个有用的营销工具,配备了额外的和更新的图形模板和设计。这不仅将为数据提供有效的分类和安排,而且还将支持其用户的创造性。

数据可视化软件中可用的常见图形有饼图、条形图和折线图。对于软件来说,在图形上具有标记功能也是可取的。
2.2 准确的趋势跟踪
数据可视化软件应该具备准确跟踪趋势的能力。该功能有助于跟踪企业所属行业的最新趋势。
2.3 强安全性
通过收集、整理和分类从数据处理中获得的信息的完整性对于准确的分析和决策非常重要。
数据保护对于保护机密和来之不易的数据非常重要。如果软件中没有足够的安全措施,丢失数据的风险就会增加。丢失的数据会导致额外的现金流出。
2.4 简单界面
用户更喜欢用户友好的软件,以缩短学习曲线。应该很容易操作和学习。在选择数据可视化软件时,应考虑软件主要操作员的知识和技能。

还应该有易于理解的手册,提供正确使用设备的基本提示。该手册还将允许公司立即将软件集成到其系统中。
3.数据可视化软件的最新趋势
由于企业与计算机的相互依赖,数据的复杂性已经成为在业务流程中集成数据可视化软件的主要原因。数据可视化软件是无数创作者开发的。软件的设计取决于市场的最新趋势。
以下是数据可视化软件的最新趋势。
3.1 响应和交互分析
敏捷响应用户命令的软件正在成为当前市场上大多数数据可视化软件的重要特征。这包括在创建仪表板和图形插图时实现拖放式用户界面。

Drag-and-drop operation of FineReport
交互式仪表盘支持软件网络内的主动通信。交互式仪表板有助于企业与员工、业务伙伴和公司客户有效沟通。
3.2 深入分析原始数据,以便及时决策
数据可视化软件的这一趋势被各种规模的企业比作希望根据快速的原始数据分析做出及时决策。一个能够使用 SQL 来整理非结构化数据的软件展示了一个强大的智能平台。
通用数据建模语言的使用带来了令人印象深刻的可视化效果和流畅的数据整合活动。即时报告生成也是该软件的一个众所周知的功能。
3.3 将数据整合到一个平台,以便对数据进行强大的分析
数据可视化软件的这种趋势允许安全地共享来自一个组织的所有不同部门的全部数据。这也支持完整的注释和实时数据更新。
它还通过实施更吸引人的图形工具和设计来提供有效的数据分析。通过快速创建展示业务流程和工作描述的可视化工具,组织的团队成员将更有效地开展日常工作。
3.4 有用工具的可用性
许多公司购买的软件拥有各种工具,如 KPI 小部件、数据透视表和表格视图组件。这些是报告生成中的有用工具。
这种类型的软件通过实现准确、完整和及时的报告创建和决策制定来支持团队协作。这也允许在公司的网站、博客和应用程序中插入任何报告或仪表板。
3.5 可通过台式电脑和移动设备访问
它可以将桌面计算机上的数据链接、绘制图表并共享到移动设备上。仪表板可以与团队成员共享,并通过台式计算机、笔记本电脑和/或移动设备(如智能手机和平板电脑)进行分析。
3.6 社交协作
仪表板为正在使用软件的团队成员提供了更有效的协作工作的实时数据。它还拥有多功能小部件、迷你图和趋势指示器,以帮助团队理解数据可视化。
数据可视化软件的用户到用户消息传递功能支持软件用户之间的有效通信。这种社交分享功能是团队成员之间成功传递信息的一个有益因素。
3.7 设置默认值并自定义数据连接器和模板

用于对公司收集的数据进行分类和排列的图形可视化设计也为大多数软件购买者树立了一种趋势。一些软件的定制功能允许用户根据他们的需要操作数据连接器和图形模板。
4.数据可视化软件:变化是迅速的
单个数据可视化软件拥有多种功能组合。数据可视化软件的最新趋势集中在图形设计和模板可用性、交互功能、快速数据转换、数据分析辅助、有用工具的可用性、设备可访问性(如桌面和移动设备软件兼容性)、团队通信支持和定制功能。这些是全球数据可视化工具市场的最新趋势。随着技术进步日新月异,它每年都在发生变化。
在文章的最后,我列举了一些数据可视化的学习资料,希望对你有所帮助!
数据可视化采集:
初学者如何设计酷的数据可视化?
仪表盘教程:
数据可视化中的图表类型:
除 Kaggle 之外的顶级竞争数据科学平台

Photo by George Becker from Pexels
学习任何东西的最好方法是实践。
在你完成了数百门 MOOCs 课程、阅读了数千本书籍和笔记、听了一百万人慷慨激昂地讲述他们在数据科学领域的经历之后,你会做些什么?你开始应用这些概念。应用机器学习概念的唯一方法就是把手弄脏。要么在你感兴趣的领域找一些现实世界的问题,要么参加黑客马拉松和机器学习比赛。
竞争数据科学不仅仅是应用算法。算法本质上是一种工具,任何人都可以通过编写几行代码来使用它。参加这些比赛的主要收获是它们提供了一个很好的学习机会。当然,现实生活中的问题不一定与竞赛中提供的问题相同;尽管如此,这些平台使你能够将你的知识应用到流程中,并观察你与他人相比的表现。
参加数据科学竞赛的优势
参加这些比赛你会有很多收获,实际上也不会有什么损失。它有有形和无形的好处,如:
- 很好的学习机会。
- 接触最先进的方法和数据集。
- 与志同道合的人建立关系网。在团队中工作甚至更好,因为它有助于从不同的角度思考问题。
- 向世界展示你的才华和被录用的机会
- 参与并看看自己在排行榜上的表现也很有趣。
- 这个奖是奖金,但不应该是唯一的标准。

Kaggle 是数据科学大赛的知名平台。这是一个拥有 100 多万注册用户的在线社区,包括新手和专家。不过,除了 Kaggle,还有其他数据挖掘竞赛平台值得了解和探索。以下是其中一些的简要概述。
驱动数据
DrivenData 举办数据科学竞赛以建设更美好的世界,为解决世界上最具挑战性的问题的组织带来尖端的预测模型。Driven data 在国际发展、卫生、教育、研究和保护以及公共服务等领域举办数据科学竞赛。你可以参加比赛或者主持自己的比赛。
该网站有一个部分专门介绍[样本项目](http://Top Competitive Data Science Platforms other than Kaggle),以案例研究的形式提供一些关于他们成功项目的信息。驱动数据中列出的数据集与非营利组织有关,从野生动物保护到公共卫生。因此,如果你想把你的技能应用到现实世界的问题中,这就是你的平台。
CrowdANALYTIX
CrowdANALYTIX 是一个将商业挑战和问题转化为竞争的众包分析平台。CrowdANALYTIX 社区合作&竞争构建&优化 AI、ML、NLP 和深度学习算法。该平台还拥有一个社区博客,里面有很好的资源,包括采访和参考资料。
无辜的
InnoCentive 主要关注与生命科学有关的问题,但也有其他令人兴奋的比赛。在这里,Solvers 致力于解决一些世界上最紧迫的问题,从在家庭层面促进清洁水的获取到旨在吸引&杀死携带疟疾的蚊子的被动式太阳能设备。挑战是真正的问题,需要持续的专注、批判性思维、研究、创造力和知识综合。开发解决方案是令人难以置信的回报,也是无与伦比的精神锻炼。
TunedIT
TunedIT 始于华沙大学进行的科学博士项目。目标是帮助数据挖掘科学家进行可重复的实验,并快速评估数据驱动的算法。研究部分后来补充了用于举办数据竞赛的 TunedIT Challenges 平台——用于教育、科学和商业目的。
Codalab
Codalab 是一个开源的基于网络的平台,使研究人员、开发人员和数据科学家能够合作推进使用机器学习和高级计算的研究领域。CodaLab 通过其在线社区帮助解决了许多面向数据的研究中的常见问题,在那里人们可以分享工作表并参与竞争。您可以参加现有的比赛,也可以举办新的比赛。
津迪

Zindi 是非洲首个数据科学竞赛平台。Zindi 拥有一个完整的数据科学生态系统,由科学家、工程师、学者、公司、非政府组织、政府和机构组成,致力于解决非洲最紧迫的问题。
数据源。人工智能

DataSource.ai 是 SMB&创业公司的数据科学竞赛。他们试图解决数据科学竞赛领域的一个基本问题。众所周知,大多数数据科学竞赛平台都是针对大公司的。这主要是因为举办这类比赛的平台收取高额费用。这不利于数以百万计的中小企业和初创企业,它们可以从中受益匪浅。
Datasource.ai 的使命是使数据科学民主化。因此,他们让数据科学竞赛变得更加实惠。用他们自己的话说:
我们的目标是释放数据科学和人工智能活动的浪潮,使全球各种规模和预算的企业受益匪浅。
Bitgrit

https://bitgrit.net/competition
Bitgrit 是今年推出的数据科学竞赛领域的新人。该平台由日本初创公司 Bitgrit Inc 牵头。已经在全球积累了超过 25,000 名数据科学家。
自成立以来,Bitgrit 已经举办了几次人工智能比赛,包括一次预测外汇汇率的和另一次为一个配置匹配移动应用程序优化算法的。他们还有一个 工作委员会 专注于为各种全球客户提供数据科学工作机会。****
分析 Vidhya
分析 Vidhya 为分析和数据科学专业人士提供了一个基于社区的知识门户。除了为数据科学学习提供大量资源外,它还举办黑客马拉松,这是以竞赛形式发布的现实生活中的行业问题。你可以参加挑战,也可以赞助黑客马拉松。大多数在 Analytics Vidhya 上组织黑客马拉松的公司也向最高分者提供工作机会。
克劳代
2020 年 3 月 17 日更新:
克劳代,即已自关机(见【https://www.crowdai.org/blogs/7】)。从那以后,他们的创始人之一创建了另一个类似名字的网站,举办比赛:https://www.aicrowd.com/。感谢Harald Carlens提供此信息。
数据科学挑战赛平台 crowdAI 每年都会举办多个开放式数据科学挑战赛。这些挑战涵盖图像分类问题、文本识别、强化学习、对抗性攻击、图像分割、资源分配优化以及跨多个领域的许多其他领域。他们因 2017 年名为“学习运行”的挑战获得了亚马逊和英伟达超过 10 万美元的奖励。
数字
numeri是一个由数据科学家网络建立的AI-运行、众包对冲基金。它每周举办一次数据科学竞赛,为真正的对冲基金提供动力。Numerai 每周向参与者提供加密数据,然后参与者提交他们的预测。Numerai 然后从所有提交的材料中创建一个元模型,并进行投资。
数据科学家提交他们的预测,以换取在以太坊区块链上获得一些密码令牌的潜力。********
天池
天池 我是阿里云旗下的一个数据竞赛平台,在很多方面和 Kaggle 很像。在这个社区中,成千上万的数据科学家与全球的企业和政府合作和联系,以解决跨行业最具挑战性的业务问题。
数据科学挑战
这些数据科学挑战由国防科学技术实验室 (Dstl)和其他几个英国政府部门主办,包括 政府科学办公室 、 SIS 、和 MI5 。这些挑战旨在鼓励数据科学领域最聪明的头脑帮助解决现实世界的问题。该平台提供的两个挑战目前已经结束,但它们很快会出现新的问题,这些问题将挑战您找到现实世界问题的非正统答案。
除此之外,还有一些比赛只是每年举行一次。
KDD 杯
KDD 杯 是由数据挖掘者领先的专业组织 ACM 知识发现和数据挖掘特别兴趣小组举办的年度数据挖掘和知识发现比赛。
维兹杜姆人工智能竞赛(VDAIC)
ViZDoom 是一个基于 Doom 的 AI 研究平台,用于从原始视觉信息中进行强化学习。视觉末日 AI 竞赛参与者应该提交一个玩末日游戏的控制器(C++、Python 或 Java)。
机器学习竞赛

机器学习竞赛 是一个数据科学竞赛聚合网站。它列出了 Kaggle、DrivenData、AICrowd 和其他公司正在进行的机器学习竞赛/数据科学竞赛。都是开源的,社区维护的。
结论
虽然这个列表会随着时间的推移而改变,但我相信你仍然会找到最相关和最有趣的竞争。如果你想到其他我没有提到的数据科学竞赛平台,请放在下面的评论区。
强化学习的俯视图
将强化学习的不同部分和分支缝合在一起

Photo by Josh Power on Unsplash
更新:学习和练习强化学习的最好方式是去 http://rl-lab.com
当你是强化学习的新手时,你无疑会被一些奇怪的术语轰炸,比如基于模型的、无模型的、策略上的、策略外的等等…
很快你会发现跟踪这些似乎无处不在、术语之间没有明显联系的术语令人疲惫不堪。
这篇文章将尝试把所有这些术语放在一个角度,这样初学者就不会感到不知所措。
声明:本文假设你已经知道什么是强化学习和一些现有的算法。它没有介绍或解释任何特定的算法,但它会试图将不同的分支放在一起,这样你就可以得到一个全面的大画面,以及这些分支是如何适应的。
强化学习
正如已经建立的强化学习是一个框架,让代理人从经验中学习决策。它由一个与环境交互的代理组成,在环境中它采取行动并收集奖励。代理人的目标是收集最大的回报。

为此,我们需要建立以下定义。
状态
状态是描述某一时刻或某一时间步的情况的元素或特征的集合。状态的例子可以是机器人的位置、方向、周围的风景、风速、温度等等
环境安全
环境状态是描述某一时刻或某一时间步的环境的状态。环境的状态可能包含太多的细节,这些细节可能是不可能的,也没有兴趣包含在任何计算中。例如,机器人运动中的原子状态问题就不值得考虑。
代理状态
代理状态是代理感知到的状态。代理可能无法检测环境的完整状态,例如,带有固定摄像机的机器人无法看到 360°视图。在扑克游戏中,代理人只知道对手的公共牌。一般来说,代理状态不同于环境状态,但在最简单的情况下,它们是相同的,例如在一些棋盘游戏中。
在完全可观察的环境中,代理看到完整的环境状态,因此以这种方式观察是环境状态。
这个智能体被称为处于马尔可夫决策过程(MDP)。
部分可观察的环境,代理获得部分信息。这被称为部分可观察 MDP (POMDP),env 仍然可以是 MDP,但是代理不知道它。
历史
历史是一系列的观察、行动和回报。

马尔可夫决策过程
马尔可夫决策过程(Markov Decision Process)(MDP)是一种在各种情况下对决策进行建模的数学框架。
一个过程是马尔可夫的如果下一个状态只依赖于当前状态,任何过去的状态都是无关紧要的。
状态/动作值函数
状态和动作值函数,是给某个状态 s 或对状态执行的动作赋值的函数。这个想法是评估处于某个状态和/或执行某个动作相对于其他状态或动作的重要性。简而言之,它们告诉我们处于那种状态有多有价值,采取那种行动有多好。想象一盘国际象棋,白方有机会将死。处于这样的位置是一种非常有价值的状态,在这个位置上所有可能的行动中,进行将死是最好的行动。
在状态数量有限的问题中,很容易计算出状态和动作的确切值。然而,当状态的数量变得非常大时,为了节省时间和资源,近似的需要将更加迫切。对于这类问题,使用函数近似法。**
政策
策略 𝜋(s) 是将状态映射到动作的功能。这就像在某种情况下,你问自己“我现在应该做什么?”。政策告诉你该采取什么行动。策略可以是确定性的,即相同的状态导致相同的动作,也可以是随机性的,即相同的状态根据某种概率分布导致不同的动作。在文章“开发者强化学习策略”中可以找到对策略的简单介绍
模型
一个模型预测环境下一步会做什么。例如,转移概率预测下一个状态,奖励函数预测下一个奖励。一个模型不会自动给我们一个好的政策,我们仍然需要计划。
学习和规划
RL 中的两个基本问题:
- 学习:环境最初是未知的,代理通过与环境的交互来学习。
- 规划:给定一个模型,模型中的 agent 规划(无外部交互)。我们所说的计划是指推理、思考和探索。
预测和控制
预测是在给定政策的情况下对未来的评估,而控制是通过找到最佳政策来优化未来,使累积回报最大化。
探索与开发
探索就是寻找更多关于环境的信息。利用是指利用获得的信息来获得最大的回报。重要的是要知道有多少东西要探索有多少东西要开发。
基于模型/无模型
基于模型的强化学习是关于环境动态的知识,例如状态之间的转移概率,以及奖励。这在棋盘游戏中是众所周知的,但在现实生活中却很难做到。
模型可以被给定或被学习,然后它可以服从计划,或以不需要采取实际行动的方式被学习。规划阶段使用专门的算法,如 AlphaZero 中使用的蒙特卡罗树搜索。
不言而喻,模型必须足够精确才能代表真实的问题,否则基于不精确的模型来规划行动将会浪费时间和资源,导致在真实环境中表现不佳。
动态规划是基于模型的算法之一。
另一方面,无模型算法不依赖于模型来学习,它们通过直接经验来学习,这意味着它们在真实环境中采取行动。在这些算法中,我们可以找到蒙特卡罗和时间差异(TD) 。
开策略/关策略
在 TD 学习中,我们计算状态 s 下的动作值 Q(s,a),同时考虑下一个状态 Q(s’,a’)下的动作值。

下一个状态的 q 受开/关策略方法的影响。
在策略上包括基于某个策略计算 Q(s,a)值,意味着 Q(s,a)需要值 q(s’,a’)。为了得到 Q(s ',a ')的值,我们需要动作 a' ,这是使用带来动作的相同策略【𝜋】得到的。当移动到状态' s '时,我们仍然遵循先前已经确定的动作 a' 。在策略上使用的算法称为 SARSA。**
相反,关闭策略通过在使用所有可用动作的最大 Q(s’)来计算 Q(s,a)。这意味着我们不必根据策略选择特定动作a’我们只需选择具有最高值的 q(s’,a’),然后当移动到状态s’时,我们不必遵循带来最大 q 值的动作 。 使用这种技术的算法叫做 Q-Learning。**
分类代理
根据智能体算法用于学习和决策的组件类型,智能体可以以不同的方式进行分类:
- 没有策略(它是隐式的)
- 价值函数
- 政策
- 无价值函数
- 政策
- 价值函数
与上述类别正交,上述每种类型的代理可以是:
无模型
- 政策/价值功能
- 没有模型
基于模型:
- 可选策略/价值函数
- 模型
下图总结了强化学习中常用的代理类别

这张图片展示了一些 RL 算法及其类别:

https://spinningup.openai.com/en/latest/spinningup/rl_intro2.html#a-taxonomy-of-rl-algorithms
Udemy 上面向初学者的五大机器学习课程

现在每个人都想做机器学习。机器学习、数据科学、人工智能、深度学习、神经网络——这些已经成为当今科技领域最常用的词汇。我并不是说这特别糟糕,但是对于那些并不真正知道这一切意味着什么,但却想进入激烈竞争的人来说,这确实很可怕。
从软件开发人员的角度来看,这些只是不同类型的软件或应用程序,但是涉及到更多的数学知识。我知道我过于简化了数据科学,但是对于没有数学或统计学背景的人来说,一开始理解术语是非常困难的。我去过那里,老实说,我还在那里。我仍然不完全明白我在做什么。我想我在工作中学习。
但是今天,我想帮助一些新手进入数据科学的世界,看看你可以在 Udemy 上在线学习的一些很棒的课程。现在,我想坦率地承认,我个人最初也参加了一些这样的课程,它们帮助我理解了每件事的意义以及如何开始。对于开发人员来说,最困难或最可怕的部分可能是不知道如何开始这段旅程。我开始考虑重温你在学校学的数学,或者上一些统计课,诸如此类的事情。但我后来理解并意识到,我可以在家里通过上网学习所有这些。
你找到的大多数数据科学教程或课程都希望你有某种编程经验。如果你已经知道 Python 或 R 之类的编程语言,那就太棒了,但是如果没有,至少任何面向对象编程语言的知识就足够了。如果你是一个真正的编程初学者,我强烈建议在涉足数据科学或机器学习之前,先看一些 Python 编程课程。而且我说这些课程是针对初学者的,并不是指绝对的开发或编程初学者,而是数据科学初学者。
因此,我在这里列出的这些课程将帮助你开始进入数据科学的旅程,在此过程中,你可以找出你需要填补的所有空白。所以让我们开始吧。
数据科学 A-Z:包括现实生活中的数据科学练习

这可以被认为是一门关于数据科学的综合课程。在本课程中,您将学习从 SQL 查询到 Tableau 中的数据挖掘以及一些基本的机器学习算法。如果你想进入数据科学领域,这可能是一个很好的起点。这个课程是由 SuperDataScience 的 awesome 团队创建的。我是这些人的粉丝,因为我的第一个机器学习课程就是这些家伙创造的。他们很好地解释了一切,给了你一些可靠的例子,而且总的来说,让你明白了这一点。
因为这是“数据科学 A-Z”,所以您不仅可以了解机器学习算法,还可以了解数据科学中其他不太为人所知的部分,例如准备好数据以进行处理,使用 SQL,甚至 Tableau。你会对数据科学有一个全方位的了解。当然,本课程只会向您介绍所有这些工具和技术的基础知识,但这正是您现阶段所需要的。一旦掌握了基本知识,您就可以继续探索更多内容,或者决定专攻数据科学的某个特定领域。目前,这门课程有 21 小时的视频内容,售价 18.99 美元。如果你感兴趣,可以在 Udemy 网站上查看。
用 Python 实现机器学习、数据科学和深度学习

这门课,顾名思义,讲的都是机器学习和深度学习。你会被介绍给 Tensorflow 和 Keras。您还将学习一些分类算法和一个名为 MatPlotLib 的 Python 图表绘制库。如果图像分类和情感分析让你感兴趣,你可以考虑把这门课加入你的清单。
你需要确保你有一点点编程知识。如果你懂 Python 编程,那真的很好,因为这门课的大部分内容(也包括这个列表中的大部分其他课程)都是基于 Python 的。所以如果你不知道 Python,确保你先学会它。在 Udemy、 Coursera 上也有很多这方面的课程,你也可以在 YouTube 上找到很多的免费教程。不管怎样,如果你感兴趣,这门课有 14 个小时的视频,售价 18.99 美元。你可以在 Udemy 查看这里。
R Programming A-Z:R For Data Science With Real exercise!

这是 SuperDataScience 团队的又一个牛逼课程。你可以把这门课程看作是 R 编程语言的介绍,但它是为数据科学量身定制的。此外,这不仅仅是对 R 编程语言的介绍。它有适当的语言教程,如果你正计划未来几年的 R 职业生涯,或者只是想深入研究 R,你会非常感激。
在本课程中,你将接触到财务和统计问题,以及如何用 R 编程语言解决这些问题的课程。这将会很有趣,因为 R 不像其他编程语言。尤其是如果你在学完 Python 的其他课程后又学了这门课,你会看到一些非常酷的不同之处。我说酷的区别是因为有些事情用 r 做起来超级简单。
无论如何,如果你对此感兴趣,那么请点击 Udemy 上的查看完整的课程。该课程现在正以 18.99 美元出售,你可以点播 10.5 小时的视频内容。
使用 Python 进行深度学习的 TensorFlow 完全指南

嗯,名字说明了一切。这是使用 Python 入门 TensorFlow 的一体化课程。如果你不知道,TensorFlow 是谷歌维护的神经网络。您将学习如何为 TensorFlow 编写 Python 代码。但是在开始编码部分之前,将向您介绍什么是神经网络。一旦你理解了它们是什么以及它们是如何工作的,你就可以开始教程的编码部分了。这个结构,在我看来,相当不错。因为在使用它们之前理解它们是如何工作的是合乎逻辑的。
在本课程中,您将学习如何使用各种算法,如时间序列分析、分类、回归、卷积等等。所以是的,这很有趣。这门课程目前在我的待办事项清单上。我很快就会开始讨论这个问题。如果你有兴趣,你可以在 Udemy 上的这里报名参加的课程。这也以 18.99 美元出售,你可以获得 14 小时的点播视频教程。
数据科学和机器学习训练营

这是另一门介绍 R 编程语言的课程,但重点是数据科学和机器学习。在本课程中,您将学到许多关于 R 的知识,从在本地机器上安装编程语言的简单步骤开始,一直到读取 R 中不同类型的文件和创建数据框。还会有一些关于可视化、数据操作和机器学习算法的教程。如果您是第一次开发 R,或者正在考虑开始使用 R,这可能是很好的第一步。有兴趣的话来这里看一下。它提供了长达 18.5 小时的视频内容,目前售价为 18.99 美元。
这是我在 Udemy 上发现的几门关于数据科学和机器学习的非常有趣的课程。这些绝不是最好的课程或必须要学的课程。我只是觉得他们提供的东西很有趣。如果你想让我用 Coursera 或 YouTube(免费课程)来整理这样一个列表,请在评论中告诉我,我会马上着手处理。这也许会促使我在 YouTube 上完成另一门课程。
在推特上关注我,了解更多数据科学、机器学习,以及通用技术更新。此外,你可以关注我的个人博客,因为我在 Medium 之前发布了许多我的教程、操作方法帖子和机器学习的优点。
如果你喜欢我在 Medium 或我的个人博客上的帖子,并希望我继续做这项工作,请考虑在 Patreon 上支持我。
2019 年顶级 Javascript 机器学习库
machinelearn.js 社区精心挑选的最佳库列表

Out of many Machine Learning libraries, only a few have survived
从企业到个人项目,Javascript 无处不在,并通过 Typescript 和 ReasonML 等超集语言得到增强。尽管在 Github 中,Python 是第三种最受欢迎的机器学习编程语言,但大多数数据科学家和公司更喜欢 Python 作为他们的首选语言。Javascript 机器学习在 2018 年出现了飞跃式的增长,尽管许多著名的项目仍未得到维护,但包括 Brain.js 和 Tensorflow.js 在内的许多关键参与者在 2018 年全年一直在发展,直到 2019 年的现在。
以下是 2019 年最佳 Javascript/Typescript 机器学习库的列表,符合以下标准
- 维护并拥有一个活跃的社区
- 生产就绪
- 流行
免责声明:虽然标题说的是最好的“机器学习 Javascript 库”,但我已经包括了不是严格意义上的 ML 但有紧密关系的库。
1.Tensorflow.js

2019 年的 Tensorflow.js 由于其全面的线性代数核心和深度学习层,已经成为所有机器学习 Javascript 项目的面包和黄油。在支持的 API 数量上,它已经迅速赶上了它的 Python 姐妹,在这一点上,几乎机器学习中的任何问题都可以用它来解决。
除了在 Node.js 环境中提供深度学习和机器学习,Tensorflow.js 还可以直接在浏览器中使用,同时利用 WebGL 进行加速。同时支持浏览器和 Node.js 环境的 Tensorflow.js 模型已经被包括 brain.js 和 machinelearn.js 在内的很多开源库采用。
Sentdex’s tutorial on Tensorflow.js
2.Brain.js
Brain.js 的目标是将机器学习和深度学习的复杂性降低到孩子可以理解的程度,它无疑是最容易的深度学习库,包括 Python 生态系统中的深度学习库。
作为最活跃的 Javascript 深度学习库之一,他们最近推出了一个有趣的新互动教程:
https://scrimba.com/g/gneuralnetworks
此外,我向任何深度学习的新手推荐 Brain.js,因为你可以在网上找到一系列针对 Brain.js 和深度学习本身的绝对初学者的精彩教程。
查看 Youtube 上点击率最高的 Brain.js 教程之一:
Brain.js tutorial targetting the absolute beginners
3.标准库-js

绘图和样本数据集是任何机器学习工作流的基本组件。绘图提供了对数据集的更深入了解,并帮助机器学习工程师决定下一步行动,以解决手头的问题。此外,该库配备了大量不同类型的样本数据集,包括二元分类、回归和图像数据集套件。
该库可以成为任何机器学习项目的好伙伴,因为它提供了如上所述的一些基本的机器学习操作,并且有很好的文档。
4.machinelearn.js

Machinelearn.js 是一个新手,来完成 ScikitLearn 在 Javascript 机器学习的 Python 领域中的角色。它为监督和非监督问题提供了简单明了的关键任务模型和实用程序。专注于 Javascript 和 Typescript 开发人员的简单性和一体化通用机器学习,它提供了聚类、分解、集成、打包、线性模型、特征提取等等。
它将久经考验的库 Tensorflow.js 用于其核心数学,使用 C++原生接口、CUDA 和 WebGL 实现加速。与它的同行 mljs 不同,machinelearn.js 是用 Typescript 编写的,它为已经在使用该语言的用户提供了类型定义。
5.数学. js

这是一个满足 Javascript 中所有数学需求的库,具有广泛的线性代数 API,包括矩阵运算和核心数学。它是相当轻量级的,因为它不依赖于其他加速技术,如 WebAssembly 或 WebGL。
math.js 拥有大量来自社区的贡献者,是由包括 Jos de Jong 在内的核心开发人员管理的最有活力的开源社区之一。
在 Javascript 机器学习领域,Math.js 足以完成 Numpy 的角色,因为它提供了解决机器学习问题所需的所有基本实用程序。
6.face-api.js

js 包括在各种数据集上预先训练的著名人脸检测和识别模型的实现。它提供了一个现成的 API,可以直接插入任何 Node.js 和浏览器环境。
该库实现了 SSD MobileNet V1 ,微小人脸检测器和 MTCNN 用于检测架构,以及类似于 ResNet-34 的架构用于人脸识别。使用 Tensorflow.js 是轻量级的,这个库可以毫无问题地在移动和 web 浏览器上使用。
查看 Github 资源库和作者的博客文章。
7.R-js

R-js logo
如果您正在寻找一个像 R 中那样的核心数学实用工具,社区的一个成员已经将 R 的重要组件移植到了 Typescript 中。
BLAS 等线性代数规范被 Numpy 和 R 等机器学习应用程序的核心广泛采用,R-js 项目将整个 BLAS 重新编写为 Typescript,为未来的项目实现更强大的数学基础框架(如 Python 的 Numpy 和 SciPy)奠定了基础。
看看他们的 Github 组织。
8.自然的
如果你正在寻找像 Javascript 中的 NLTK 或 spaCy 这样的 NLP 工具,natural 是目前维护得最好、最活跃的 NLP 配套库。
它提供了机器学习 NLP 工作流所需的基本 API,包括预处理实用程序,包括标记化器和词干分析器,以及搜索实用程序,如 tf-idf 。
它有一个内置的情感分析,使用一个简单的算法和一些数据结构,包括尝试,短路径树和长路径树。
查看他们的 Github 库。
用于增强推荐系统的 Top-K 偏离策略校正

Make your newsfeed propaganda free again with recnn! Photo by freestocks.org on Unsplash
在我的强化推荐库中,OffKTopPolicy 现在可供您开箱即用,没有任何先决条件!
这是我的学校项目。它侧重于个性化新闻推荐的强化学习。主要的…
github.com](https://github.com/awarebayes/RecNN)
该代码还可在 Colab 中在线使用 TensorBoard 可视化功能:
看链接短信 colab.research.google.com](https://colab.research.google.com/drive/1bCAJG_lGQg9dBGp2InvVygworHcqETlC)
原始论文“用于增强推荐系统的 Top-K 偏离策略校正”,作者陈等人;
[## 用于增强推荐系统的 Top-K 偏离策略校正
工业推荐系统处理非常大的活动空间——数百万的推荐项目…
arxiv.org](https://arxiv.org/abs/1812.02353)
在我们开始之前说几句话:我是 rec nn——围绕 PyTorch 构建的增强推荐工具包的创建者。我用的数据集是 ML20M。奖励在[-5,5],状态是连续的,动作空间是离散的。
此外, 我不是谷歌的员工 ,不像论文作者,我不能有关于推荐的在线反馈。 我用影评人来分配报酬。在现实世界中,这将通过交互式用户反馈来完成,但在这里,我使用一个神经网络(critic)来模拟它。
理解强化
需要理解的一件重要事情是:本文描述了具有离散动作的连续状态空间;
对于每个用户,我们考虑一系列用户与系统的历史交互,记录推荐者采取的行动,即推荐的视频,以及用户反馈,如点击和观看时间。给定这样的序列,我们预测要采取的下一个动作,即要推荐的视频,使得例如由点击或观看时间指示的用户满意度度量提高。

试着理解这个题目,我发现我不知道算法是什么。几乎每个人都熟悉 Q-Learning:我们有一个值函数映射(状态)->值。q 学习实际上无处不在,无数的教程已经涵盖了它。请注意,这里的值是通过时间差异获得的累积奖励。强化类似于 Q 学习。基本上,您需要理解价值和策略迭代之间的区别:

- 策略迭代包括:策略评估 + 策略改进,两者反复迭代直到策略收敛。
- 值迭代包括:寻找最优值函数 +一个策略抽取。这两者没有重复,因为一旦价值函数是最优的,那么由此得出的策略也应该是最优的(即收敛的)。
- 寻找最优值函数也可以看作是策略改进(由于 max)和截断策略评估(在不考虑收敛性的情况下,仅一次扫描所有状态后重新分配 v_)的组合。
- 用于策略评估和寻找最优值函数的算法非常相似,除了最大值运算(如突出显示的)
- 类似地,策略改进的关键步骤和策略提取是相同的,除了前者涉及稳定性检查。
注意:这不是我的解释,我是从这里抄来的:
感谢贡献一个堆栈溢出的答案!请务必回答问题。提供细节,并且爱泼斯坦没有自杀
stackoverflow.com](https://stackoverflow.com/questions/37370015/what-is-the-difference-between-value-iteration-and-policy-iteration)
现在让我们把这个翻译成 python:
下图使用 PyTorch 的增强实现。链接到 Github 上的文件。

code is from official pytorch examples

code is from official pytorch examples

code is from official pytorch examples
使用 recnn 的实现
本周,我发布了增强实现,以便与我的库一起使用。让我们来看看使用 recnn 增强需要什么:

prepare_dataset 是一个责任链模式,将您的数据转换为可用状态。注意:这种用法是完全可选的,如果您不想弄乱对 recnn 内部工作方式的理解,可以事先按照您喜欢的方式转换您的数据。
embed_batch 将嵌入应用于单个批次。正如你所记得的,状态是连续嵌入的,而动作空间是离散的。幸运的是,有一个现成的版本可供您使用: batch_contstate_discaction。
因为我没有很强大的 PC (1080ti 农民),所以无法使用大的行动空间。因此,我将动作删减为 5000 部最常见的电影。
我不是谷歌的员工 ,与论文作者不同,我不能获得关于推荐的在线反馈。我用评论家来分配奖励。在现实世界中,这将通过交互式用户反馈来完成,但在这里,我使用一个神经网络(critic)来模拟它。
现在,让我们定义网络和算法本身。

经过 1000 步后,我们得到:

Note: the policy loss is pretty large!
回到论文:关闭政策修正
问题如下:我们有多种其他政策。让我们把 DDPG 和 TD3 训练有素的演员从我的图书馆。鉴于这些政策,我们希望以一种非政策的方式学习一种新的、不带偏见的政策。正如作者所说:
偏离策略候选生成:我们应用偏离策略校正来从记录的反馈中学习,这些反馈是从先前模型策略的集合中收集的。我们结合了行为策略的学习神经模型来纠正数据偏差。
不要将其与迁移学习混淆:
由于等式(2)中的梯度要求从更新的策略ωθ中采样轨迹,而我们收集的轨迹来自历史策略β的组合,因此简单的策略梯度估计器不再是无偏的。我们用重要性权重解决分布不匹配问题
因此,简单地说,不符合政策的纠正是重要性加权,因为先前的建议是有偏见的,并且基于现有的模型。
现在让我们考虑一下公式:
β —是历史的,也称为行为策略(以前的模型)
ωθ—是一个更新的策略(新模型)
仔细研究论文中列出的数学难题,作者得出了这个奇特的公式:

Proposed Reinforce with OffPolicyCorrection
也就是说,动作 A 概率,给定状态 S 在时间步长 T 上具有更新策略/历史策略的重要性。他们的结论是,不需要整个情节的乘积,一阶近似已经足够好了。更多关于近似值的。
P.S .一级近似:f(x+h)≈f(x)+f′(x)×h。
等式[3]表明,这种关系(Pi/Beta)仅用作重要性加权项。如果您查看原始的增强更新,这些函数的唯一不同之处是前面提到的重要性权重:

Original Reinforce
参数化策略πθ(网络架构)
下一节只是作者使用的模型的简单描述。这与政策外修正没有多大关系。
如果你一直关注我的作品,你就会知道我主要是在做连续动作空间的东西,比如 DDPG 或者 TD3。本文主要研究离散动作空间。离散行动空间的特点是它会迅速变大。为了解决这种增长的问题,作者使用了默认情况下 TensorFlow 附带的 Sampled Softmax,。遗憾的是,PyTorch 没有这样的选项。因此,我将利用噪声对比估计、代替作者使用的采样 Softmax ,这是一种类似的方法,具有 Pytorch 库:stones jtu/py torch-NCE。
无论如何,让我们来看看网络架构:
作者使用简单的递归状态表示法,这里没什么特别的:
我们在每个时间 t 的用户状态上对我们的信念建模,这使用一个 n 维向量捕获了两个不断发展的用户兴趣。沿着轨迹在每个时间 t 采取的动作使用 m 维向量 u 嵌入。我们使用递归神经网络对状态转移 P: S×A×S 进行建模。
对于新状态 S,它们执行 softmax

其中 v_a ∈ R n 是动作空间 A 中每个动作的另一个嵌入,T 是通常设置为 1 的温度。关键的一点是,他们使用的是的另一种嵌入,而不是一种用于状态表示的嵌入。一件很酷的事情是,我们将通过 torch.nn.Embedding 学习这些嵌入
不要看在β_θ`处从 RELU 向左的可怕箭头,上面有区块渐变。我们暂时忽略它。因此,就目前而言,总的来说,网络架构看起来像是:

评估行为策略β
现在回到那个可怕的箭头,在β_θ处从 RELU 向左倾斜:

理想情况下,对于我们收到的每一个关于所选操作的记录反馈,我们也希望记录行为策略选择该操作的概率。然而,在我们的情况下,直接记录行为策略是不可行的,因为(1)在我们的系统中有多个代理,其中许多是我们无法控制的,以及(2)一些代理具有确定性策略,并且将β设置为 0 或 1 不是利用这些记录的反馈的最有效方式。
他们说他们在谷歌有很多行为政策可以学习。但是在纠正部分,他们只有一个用于重要性加权的行为策略β。
相反,我们采用[39]中首次介绍的方法,并使用记录的动作估计行为策略β,在我们的情况下,行为策略β是系统中多个代理的策略的混合。给定一组记录的反馈 D = {(si,ai),i = 1,,N},斯特雷尔等人[39]通过在整个语料库中聚合动作频率来估计与用户状态无关的ˇβ(a)。相比之下,我们采用上下文相关的神经估计器。
[39]中提到的论文可以追溯到 2010 年,所以他们决定使用深度学习的幻想。据我所知,他们从这些其他历史模型中获取输出,并使用简单的深度学习模型来预测历史政策β。也是这样做的,它使用了公共状态表示模块,一个具有 ReLU 的 RNN 单元。但是梯度通道被阻塞,因此状态表示只从更新的策略π_θ中学习。对于 PyTorch 来说:block gradient = tensor.detach()
现在让我们看看目前为止我们得到了什么
另外,第一个(zeroest)笔记本有一个最少使用 recnn 的基本实现。这里详细解释了一切,这样你就不用去查源代码了。
不管怎样,下面是如何在 recnn 内部实现偏离策略的纠正:

difference between select action and select action with correction

difference between reinforce and reinforce with correction

Beta class. Notice: it learns to resemble historical policy by calculating cross-entropy with action
你可能已经注意到,我没有包括次级项目嵌入、噪声对比估计和作者描述的其他东西。但是这些对于算法背后的思想来说并不重要。你可以使用简单的 PyTorch softmax 而不用花哨的 log 均匀采样,代码会保持不变。
使用 recnn 进行政策外修正
代码保持不变:我们从定义网络和算法开始。

还记得 nn 中的_ select _ action _ with _ correction方法。离散策略类所需动作?它在这里被传递。我知道,这是糟糕的代码,我还没有想出更好的方法来这样做。测试版更新也通过了操作。别忘了在参数中选择加强修正,毕竟那才是主要目的!

如果你看看损失,他们没有太大的变化。或者他们有吗?如果你看一下之前的损失图,损失是以千计的数量级来衡量的。

Make sure to check ‘ignore outliers’

Correction in action: w/o outliers ignored. Start’s pretty rough, but then corrected

beta_log_prob

correction can get pretty large
Top K 偏离策略修正
这对于单个推荐来说是可以的。但请记住,我们面对的是一系列这样的问题。作者介绍如下:
- π_θ —我们的政策
- A —是从π_θ采样的一组动作
- π_θ—是一种新策略,它不是单一的操作,而是产生一组 K 建议。不过,跑题了:有个很酷的东西叫 gumbel_softmax。使用它会很酷,而不是重新采样。 Gumbel 最大技巧解释、无替换采样序列的 Gumbel-Top-k 技巧(合著者中的 Max Welling)

4.π_θ上的奖励设置和更多信息

5.α_θ(a | s)= 1(1πθ(a|s))^k 是项目 a 出现在最终非重复集合 a 中的概率,这里 k = | a′| > | a | = k . p . s . k 是有重复项的大小抽样集合。k 是同一个集合的大小,但是去掉了重复的部分。作为具有替换和去重复的采样的结果,最终集合 A 的大小 k 可以变化。
这些变量中的大多数都是为了帮助理解背后的数学原理而引入的。例如,从未使用过π_θ。然后公式简化成一个非常简单的表达式,但是我现在想让你明白一些事情。
Top K 与从集合中选择一个项目的概率有关。随着重复,你的分布将是二项式的。这是二项分布的第页的统计数据。的确,看看上面的α_θ。不像什么吗?
考虑到这一点,我们得出:


附注:没有解释他们是如何想出这个公式的,但正如我所说,它与二项式分布和#重复选择 TopK 项的方法有关。动手组合学。就是这样!最后,我们得出了一个非常简单的公式,可以轻松地添加到我们现有的模块和更新函数中:
lambda_k = K*(1 - pi_prob)**(K-1)
用代码实现

difference between top k and not top k

difference between top k and not top k
链接到笔记本。除了->增强 with_TopK_correction、和 select _ action _ with _ correction->_ select _ action _ with _ TopK _ correction 之外,什么都没变。****

losses be looking unusual

Lambda_K stays pretty small, unlike correction
图形中的其他内容看起来与非 TopK 版本完全相同,为什么会不同呢?数据集和网络没有改变。现在,让我们来看看保单损失的确切原因:
- 因为ωθ(a | s)→0,λK (s,a) → K。与标准非政策校正相比,top-K 非政策校正将政策更新增加了 K 倍
- 当ωθ(a | s)→1,λK (s,a) → 0。这个乘数将策略更新清零。
- 随着 K 的增加,当ωθ(a | s)达到合理范围时,该乘数会更快地将梯度降至零。
总之,当所需项目在 softmax 策略πθ ( |s)中具有小的激活值时,top-K 校正比标准校正更积极地提高其可能性。一旦策略ρθ(| s)开始在 softmax 中具有特定项目的所需激活值(以确保它将有可能出现在 top-K 中),校正然后使梯度为 0,从而不学习它,以便其他 K-1 个项目可以出现在推荐中。
结果比较
所有的结果都可以在顶部链接的 Google Colab 笔记本上看到并在线互动。
注:要查看修正后的损失,请单击左侧 Runs 部分的圆形单选按钮,而不是方形复选框。

Policy: orange — NoCorrection, blue — Correction, red — TopK Correction
修正本身只是让损失变小。TopK 使亏损类似于原始亏损 w/o 修正,但这次更集中于零,没有明确的趋势。

Value Loss: nothing unusual
我没做的事:
作者还提到了方差减少技术。就我而言,我有合理的损失,所以我认为我不需要它们。但是如果需要的话,实现这些应该不是问题。
- 重量上限:校正=最小值(校正,1e4)
- 专业提示:看看张量板上的修正分布,算出一个重量上限的大数字
- 重要性抽样的政策梯度:我发现了这个回购github.com/kimhc6028/policy-gradient-importance-sampling
- TRPO:有很多实现。选择你喜欢的。也许 PPO 会是更好的选择。
好了
暂时不要走开。有几种方法可以帮助 RecNN:
- 一定要在 GitHub 上拍和给一颗星:https://github.com/awarebayes/RecNN
- 用于您的项目/研究
- recnn 目前缺乏一些特性:顺序环境和不容易配置的用户嵌入。有实验性的顺序支持,但还不稳定。也许可以考虑捐款
recnn 的 StreamLit 演示即将到来!您可以通过给库标一颗星来加快速度:
这是我的学校项目。它侧重于个性化新闻推荐的强化学习。主要的…
github.com](https://github.com/awarebayes/RecNN)
recnn 还将进行许可变更。如果没有加密和联合学习,您将无法使用 recnn 进行生产推荐。用户嵌入也应该存储在他们的设备上。我相信言论自由和第一修正案,所以建议应该只在一个联邦(分布式)的方式。下一篇文章是关于联邦学习和 recnn 的 PySyft(github.com/OpenMined/PySyft)集成!**
顶级 Python 库:Numpy 和 Pandas
在本教程中,我将尝试对 Python 中最重要的两个库 Numpy 和 Pandas 做一个简单的描述。不再拖延,让我们先通过号号。
Numpy
[numpy](https://www.numpy.org)是 Python 中科学计算的核心库。它提供了一个高性能的多维数组对象和工具来处理这些数组。Numpy 是一个强大的 N 维数组对象,是 Python 的线性代数。Numpy 数组本质上有两种风格:向量和矩阵。向量是严格的一维数组,而矩阵是二维的,但矩阵只能有一行/一列。
要在您的系统中安装numpy库并进一步了解 python 基础知识,您可以点击以下链接:
第 1 章:基本 python 和安装
towardsdatascience.com](/machine-learning-and-data-analysis-inha-university-part-1-be288b619fb5)
现在要在程序中使用numpy,我们需要导入模块。为了方便起见,一般将numpy包定义为np的缩写。但是您可以使用任何想要的东西来导入它。
import numpy **as** np
np**.**array([1, 2, 3]) *# Create a rank 1 array* np.arange(15) # generate an 1-d array from 0 to 14
np.arange(15).reshape(3, 5) # generate array and change dimensions
现在要了解更多关于numpy包及其功能,你可以直接关注官方网站https://numpy.org/。这里我们将讨论numpy库的一些重要命令和功能。

在上图中,我们可以看到numpy首先被导入,然后定义了一个 1-d numpy数组a。然后,我们可以使用提到的命令检查数组的类型、维度、形状和长度。以下是创建阵列的一些重要命令:
***np.linespace(0,3,4)*** #create 4 equally spaced points 0-3 range inclusively
***np.linespace(0,3,4, endpoint=False)*** # remove endpoint and other equally spaced values.
***np.random.randint(1,100,6)*** #create array of 6 random values in 0-100 range.
***np.random.randint(1,100,6).reshape(3,2)*** #reshape the array according to row and column vectors.
***np.random.rand(4)*** #create an array of uniform distribution (0,1)
***np.eye(3)*** #create a 3*3 identity matrix
***np.zeros(3)*** #create array([0,0,0])
***np.zeros((5,5))* ** #create a 5*5 2-d array of zeros
**np.random.randn(2,2)** #return standard normal distribution vcenter around zreo.
***np.empty((2,3))* ** # uninitialized
***np.arange(0, 2, 0.3)*** # from 0 to a number less than 2 with 0.3 intervals
***np.ones((2,3,4), dtype=np.int16)*** # all element are 1
***np.array([[1,2],[3,4]], dtype=complex)*** # complex array
***np.array([(1.5,2,3),(4,5,6)])*** # two-dimensional array
***np.array([2,3,4])*** # one-dimensional array
n 数组对象的重要属性
ndarray.shape:数组的维度。这是一个整数元组,表示每个维度中数组的大小。对于具有 n 行和 m 列的矩阵,形状将为(n,m)。
ndarray.ndim:数组的轴数(维度)。
ndarray.dtype:如果想知道数组的数据类型,可以查询 dtype 的属性。描述数组中元素类型的对象。可以使用标准 Python 类型创建或指定 dtype 。
另外, numpy 提供了自己的类型。 numpy.int32 、 numpy.int16 和 numpy.float64 就是一些例子。

Attributes of ndarray object
ndarray.itemsize:数组中每个元素的字节大小。例如,float64 类型的元素数组的项大小为 8 (=64/8),而 complex32 类型的元素数组的项大小为 4 (=32/8)。相当于ndarray . dtype . itemsize .
ndarray.size:数组元素的总数。这等于形状元素的乘积。
打印数组:打印数组时,numpy以类似于嵌套列表的方式显示数组,但使用以下布局:最后一个轴从左到右打印,倒数第二个轴从上到下打印,其余的也从上到下打印,每个切片与下一个切片之间用空行隔开。

ndarray 的基本操作:
***A = np.array([[1,1],[0,1]])
B = np.array([[2,0],[3,4]])***
***A+B*** #addition of two array
***np.add(A,B)*** #addition of two array
***A * B*** # elementwise product
***A @ B* ** # matrix product
***A.dot(B)*** # another matrix product
***B.T* ** #Transpose of B array
***A.flatten()*** #form 1-d array
***B < 3* ** #Boolean of Matrix B. True for elements less than 3
***A.sum()*** # sum of all elements of A
***A.sum(axis=0)*** # sum of each column
**A.sum(axis=1)** # sum of each row
***A.cumsum(axis=1)*** # cumulative sum along each row
***A.min()*** # min value of all elements
***A.max()*** # max value of all elements
***np.exp(B)* ** # exponential
***np.sqrt(B)*** # squre root
***A.argmin()*** #position of min value of elements
***A.argmax()*** #position of max value of elements
***A[1,1]* ** #member of a array in (1,1) position
在 numpy : 中的索引、切片和迭代
***a = np.arange(4)**3*** # create array a
***a[2]*** # member of a array in 2nd position
***a[::-1]*** # reversed a
***a[0:4,1]* ** # each row in the second column of b
***a[1,...]*** # same as a[1,:,:] or a[1]
***a[a>5]*** # a with values greater than 5
***x = a[0:4]* ** # assign x with 4 values of a
***x[:]=99*** # change the values of x to 99 which will change the 4 values of a also.
如果一个数组的任何位置被分配给另一个数组,并且它被广播到一个新的值,那么原来的数组也改变了。这是因为 numpy 不想为同一个数组使用更多的内存。如下图所示, a 的值随着数组 a 的一部分 x 的值的改变而改变。

当我们在数组中使用比较运算符时,它会返回一个布尔数组。然后使用布尔数组,我们可以有条件地从原始数组中选择元素。
熊猫
pandas是一个构建在 numpy 之上的开源库,为 Python 编程语言提供高性能、易于使用的数据结构和数据分析工具。它允许快速分析和数据清理和准备。它在性能和生产力方面表现出色。它可以处理来自各种来源的数据。pandas适用于许多不同类型的数据:表格数据、时间序列数据、带有行和列标签的任意矩阵数据,以及任何其他形式的观察/统计数据集。要在你的系统中安装 pandas,你可以使用这个命令pip install pandas或conda install pandas。
***import numpy as np* ** #importing numpy
***import pandas as pd*** #importing pandas
***arr=np.array([1,3,5,7,9])*** #create arr array
***s2=pd.Series(arr)*** #create pandas series s2
***print(s2)*** #print s2
***print(type(s2))*** #print type of s2
输出:
0 1
1 3
2 5
3 7
4 9
dtype: int64
<class 'pandas.core.series.Series'>
为了在pandas中制作系列,我们需要使用pd.Series(data, index)格式,其中data是输入数据,index是数据的选择索引。为了充分理解它,我们可以遵循下面的例子。

熊猫系列在列表和 numpy 数组以及字典中的工作方式相同。 面板 ,三维数据结构,有三个轴,
轴 0 ( 项)轴 1 ( 长 _ 轴)轴 2 ( 短 _ 轴)。0 轴对应一个二维数据帧。对应数据框的行,轴 2 对应数据框的列。下面的例子使用 numpy 生成一个三维随机数,然后将其应用于
pandas.Panel()。输出显示创建了一个大小为 2 ( 项目 ) x 3 ( 长轴 ) x 4 ( 短轴)的面板对象。如果您从面板对象 p 中查找p[0],您可以看到 DataFrame,0 轴的第一个元素被显示。

熊猫数据帧 创建一个带有标签轴(行和列)的表格数据结构。数据帧的默认格式是pd.Dataframe(data, index, column)。您需要提到数据、索引和列值来生成数据帧。数据至少应该是二维的,索引将行名和列的值作为列名。

Example of pandas Series & DataFrame
下面我提到了熊猫图书馆中使用的一些基本命令及其用法:
***s4=pd.DataFrame(np.random.randn(20,7), columns=['A','B','C','D','E','F','G'])***
***s4[(5<s4.index) & (s4.index<10)]*** # s4 with values that satisfy both conditions
***s4.head()* ** # First five rows of s4
***s4.tail()*** # Last five rows of s4
***s4.describe()* ** # statistical information of data
***s4['B']* ** # data of the 'B' column
***s4[['B','E']]* ** # data of the 'B' and 'E' column
***s4[0:3]*** # data of the 1~3 rows
***s4.iloc[0:3]*** # data of the 1~3 rows
***s4.loc[[2,3],['A','B']]*** # value of row 2,3 column 'A' ,'B'
***s4[2 < s4]*** # s4 with values matching conditions
***s4.mean()* ** # means of each column
***s4.mean(1)*** # mean of each row
***s4.drop('A')*** # delete row 'A'
***s4.drop('D',axis=1)*** # delete 'D' column
***s4.drop('D',axis=1, inplace=True)*** # delete 'D' column permanently
***s4['H']=np.random.rand(20,1)*** # add a new column of same length.
字典可用于创建熊猫系列和数据框架。字典可以用作数据来创建表格数据,但是值应该比 多一个用于每个键和所有 值 应该具有 相同的长度 ,而在 pandas 系列中不同的值长度是可以的。

Pandas Series and Dataframe through Dictionary
要重置框架的索引并在列中添加前一个索引,我们需要遵循下面的命令。重置指数将是数值。
***df.reset_index(inplace=True)
df.set_index('Name')*** #index will be 'Name' column but not permanent.
***df.set_index('Name', inplace=True)***#permanent new index 'Name' column
大多数数据帧在不同的列中有几个 Nan 值。有时我们需要去掉南项或者用别的东西代替它们。我们可以通过以下方式删除或替换熊猫数据帧中的 Nan 值:
***df.dropna()*** # remove the rows that have Nan value ***df.dropna(inplace=True)*** # remove the Nan value rows parmenently***df.dropna(axis=1)*** # remove columns that has Nan value ***df.dropna(axis=1, inplace=True)*** *#* remove the Nan valued columns parmanently. ***df.fillna(value='Arman')*** # fill Nan values with 'Arman'.
***df.fillna(value='Arman', inplace=True)*** #fill values parmanently.
***df.fillna(value=df.mean(), inplace=True)*** #fill Nan value with each column mean value.
***df['A'].fillna(value=df['A'].mean())*** #fill Nan value of column 'A' with its mean.
在我的下一篇教程中,我将尝试总结一下 Matplotlib 和 seaborn,这两个最常用的可视化库。我会尽快为这个教程添加一个回购。感谢您的时间和任何类型的建议或批评是非常可观的。你可以关注我的简介,看看几个教程。
阅读媒体上的 Md Arman Hossen 的文章。韩国仁荷大学 ICE 硕士。数据科学| ML |大数据|…
medium.com](https://medium.com/@armanruet)
参考链接:
- Numpy:https://numpy.org/
- 斯坦福 cs 231:http://cs231n.github.io/python-numpy-tutorial/
- Numpy 基础 cheet sheet:https://S3 . amazonaws . com/assets . data camp . com/blog _ assets/Numpy _ Python _ Cheat _ sheet . pdf
- 熊猫:https://pandas.pydata.org/
- 熊猫 cheet sheet:https://pandas.pydata.org/Pandas_Cheat_Sheet.pdf
https://assets . data camp . com/blog _ assets/pandasphidonfordatascience . pdf
数据科学中使用的顶级 Python 库
让我们来了解一下数据科学中可以使用的最重要、最有用的 python 库有哪些。

Credits: DataQuest
众所周知,数据科学是研究数据的过程。是的,你所要做的就是研究数据,并从数据中获得新的见解。这里不需要关注从零开始应用或学习新的算法,你需要知道的只是学习如何处理数据和解决问题。你需要知道的一件关键事情是使用适当的库来解决数据科学问题。这篇文章是关于提供数据科学中使用的重要库的上下文。在深入讨论这个主题之前,我想先介绍一下解决数据科学问题的 5 个基本步骤。现在我已经坐下来从头开始设计这些步骤,所以没有正确或错误的答案,正确的答案取决于你如何处理数据。你可以在我的 GitHub 库上找到更多关于数据科学、python 的教程和代码,如下所示:
Python 下载:(https://www.python.org/downloads/)py charm 下载…
github.com](https://github.com/Tanu-N-Prabhu/Python)
数据科学涉及的五个重要步骤如下所示:
- 获取数据。
- 清理数据
- 探索数据
- 构建数据
- 呈现数据
现在,这些步骤是根据我的经验设计的,不要陷入这是万能答案的假设,但是当你坐下来思考问题时,那么这些步骤就会有很多意义。

1.获取数据
这是解决数据科学问题的最重要的步骤之一,因为你必须想到一个问题,然后最终想到解决它。获取数据的最佳方式之一是从互联网上抓取数据或从 Kaggle 下载数据集。现在就看你如何以及从哪里获取数据了。我发现 Kaggle 是获取数据的最佳途径之一。下面的链接会带你到 Kaggle 的官方网站,我需要你们花一些时间来使用 Kaggle。
[## 数据集| Kaggle
下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…
www.kaggle.com](https://www.kaggle.com/datasets)
或者,你可以从网站上搜集数据,要搜集数据,你需要特定的方法和工具。下面是我的文章,我展示了如何从网站上收集数据。
让我们使用 Python 从 web 中抓取数据。
towardsdatascience.com](/web-scraping-using-python-libraries-fe3037152ed1)
一些最重要的用于从互联网上获取或抓取数据的库如下所示:
- 美味的汤
- 要求
- 熊猫
Beautiful Soup: 它是一个 python 库,用于从 HTML 或 XML 文件中提取或获取数据。下面是美汤库的官方文档,推荐你去看看链接。
Beautiful Soup 是一个 Python 库,用于从 HTML 和 XML 文件中提取数据。它与您最喜欢的解析器一起工作…
www.crummy.com](https://www.crummy.com/software/BeautifulSoup/bs4/doc/)
要手动安装 Beautiful Soup,只需键入下面的命令,这里我已经告诉你如何手动安装所有的库,并确保首先安装 python,但我建议你们使用 Google Colab 来键入和练习代码,因为在 Google Colab 中,你不需要安装任何库,你只需告诉“import library _ name ”, Colab 就会自动为你导入库。
pip install beautifulsoup4
要使用 Beautiful Soup,需要如下图导入:
from bs4 import BeautifulSoupSoup = BeautifulSoup(page_name.text, ‘html.parser’)
请求:python 中的请求库用于以一种简单且更友好的方式发送 HTTP 请求。请求库中有很多方法,其中最常用的方法是 request.get(),它返回 URL 传递的状态,无论是成功还是失败。下面是 requests 库的文档,我建议您浏览文档以了解更多细节。
[## Python 的请求库(指南)-真正的 Python
在这篇关于 Python“请求”库的教程中,您将看到请求必须提供的一些最有用的特性…
realpython.com](https://realpython.com/python-requests/)
要手动安装请求,请键入以下命令:
pip install requests
要导入请求库,您需要使用:
import requestspaga_name = requests.get('url_name')
Pandas : Pandas 是一种高性能、易用便捷的数据结构,是 python 编程语言的分析工具。熊猫为我们提供了一个数据框架,以清晰简洁的方式存储数据。下面是熊猫图书馆的官方文档。
[## pandas:强大的 Python 数据分析工具包- pandas 0.25.1 文档
是一个开源的、BSD 许可的库,提供高性能、易于使用的数据结构和数据分析工具…
pandas.pydata.org](https://pandas.pydata.org/pandas-docs/stable/)
要手动安装 pandas,只需输入代码:
pip install pandas
要导入 pandas 库,您只需:
import pandas as pd
2.清理数据
清理数据包括移除重复行、移除异常值、查找缺失值或空值、将对象值转换为空值,以及使用图形绘制它们,这些是在清理数据期间必须执行的一些步骤。要了解更多关于清洁过程的信息,请阅读我的文章,如下所示:
[## 使用 Pandas 库用 Python 进行数据清洗。
根据这篇文章,数据清理和组织占了总重量的 57%。
towardsdatascience.com](/data-cleaning-with-python-using-pandas-library-c6f4a68ea8eb)
数据清理过程中涉及的一些主要库如下所示:
- 熊猫
- NumPy
Pandas: 是的,在数据科学中,我们到处都在使用 pandas library,同样,我不必给出关于 Pandas library 的详细信息,您可以参考上一节中的上下文。
NumPy: NumPy 是一个 python 库,也称为数字 python,可以执行科学计算。你们都必须知道 python 从来不提供数组数据结构,只有在 numpy 库的帮助下,才能创建数组并对数组执行操作。要阅读 numpy 库的官方文档,请访问下面的网站:
欢迎光临!这是 NumPy 1.18.0.dev0+68bd6e3 的文档,最后更新于 2019 年 9 月 27 日。部分…
numpy.org](https://numpy.org/devdocs/)
同样,要下载 numpy,只需在命令行上运行以下命令(确保首先安装了 python):
python -m pip install --user numpy scipy matplotlib ipython jupyter pandas sympy nose
要在 python 中导入 numpy,您只需:
import numpy as np
3.探索数据
探索性数据分析(EDA)是通过将信息指标的基本属性有规律地绘制出来来理解信息指标。换句话说,你是在以一种更深入、更简洁(清晰)的方式探索数据。通过 EDA 的程序,我们可以要求对我们的信息收集的有意义的问题公告或定义进行特征化。要了解更多关于 EDA 过程的信息,请阅读下面我的文章:
让我们了解如何在 python 中探索数据。
towardsdatascience.com](/exploratory-data-analysis-in-python-c9a77dfa39ce)
执行 EDA 时使用的一些主要库如下所示:
- 熊猫
- 海生的
- Matplotlib.pyplot
pandas: 正如我所说,Pandas 库非常重要,我们在整个数据科学中使用这个库,有关 Pandas 库的更多详细信息,请浏览上面的第一部分。
Seaborn: Seaborn 是一个 python 数据可视化库,它为绘制带有统计信息的图形提供了一个高级接口。要安装最新版本的 seaborn,请使用:
pip install seaborn
我建议您浏览 seaborn 的官方文档,如下所示:
编辑描述
seaborn.pydata.org](https://seaborn.pydata.org/examples/index.html#example-gallery)
在 seaborn 的帮助下,可以绘制各种图,如条形图、散点图、热图等。要进口 seaborn,您只需:
import seaborn as sns
Matplotlib . py plot:Matplotlib 是一个 2D 绘图 python 库,使用它我们可以跨各种环境用 python 绘制各种图。它是 seaborn 的替代品,seaborn 基于 matplotlib。要安装 matplotlib,您只需:
python -m pip install -U matplotlib
要阅读 matplotlib 的官方文档,请浏览下面的链接:
[## 用户指南- Matplotlib 3.1.1 文档
编辑描述
matplotlib.org](https://matplotlib.org/users/index.html)
要导入 matplotlib.pyplot 库,请使用以下代码:
import matplotlib.pyplot as plt
4.构建模型
这是数据科学中最重要的步骤之一,这一步明显比其余步骤更难,因为在这一步中,您将基于您的问题陈述和数据构建一个机器学习模型。现在,问题陈述非常重要,因为它引导你定义一个问题,并思考不同的解决方案。互联网上许多可用的数据集都是基于一个问题,所以在这里你解决问题的技能非常重要。此外,没有一种算法最适合您的解决方案,您必须考虑您的数据是属于回归、分类、聚类还是降维,所有算法都有不同的类别。要了解更多关于构建模型的信息,请阅读下面我的文章:
在本教程中,我们将学习如何使用 python 建立一个机器学习模型来预测…
medium.com](https://medium.com/analytics-vidhya/building-a-machine-learning-model-to-predict-the-price-of-the-car-bc51783ba2f3)
大多数时候,选择最佳算法是一项非常令人困惑的任务,因此我使用了sci kit learn algorithms cheat sheet来帮助您找到最适合的算法。下面是 Scikit learn 的备忘单。

Credits: scikit learn
用于构建模型的重要库是显而易见的:
- SciKit 学习
SciKit learn: 这是一个易于使用的 Python 库,用于构建机器学习模型。它构建在 NumPy、SciPy 和 matplotlib 之上。以下是 scikit 学习库的官方文档。
编辑描述
scikit-learn.org](https://scikit-learn.org/stable/)
为了导入 scikit learn,您只需:
import sklearn
要手动安装,请使用以下命令:
pip install -U scikit-learn
5.展示数据
这是他们大多数人最不想做的任务之一。这是因为没有人愿意公开谈论他们在数据上的发现。有一种呈现数据的方式。这是至关重要的,因为在一天结束的时候,你应该有能力向人们解释你的发现,让它变得非常小,因为人们对你的算法不感兴趣,他们只对结果感兴趣。因此,为了演示您的发现,您需要安装 Jupyter 笔记本,如下所示:
JupyterLab 可以使用 conda 或 pip 安装。有关更详细的说明,请参阅安装指南。如果你…
jupyter.org](https://jupyter.org/install.html)
另外,还要安装一个命令来帮助您的笔记本启用演示选项:
pip install RISE
关于如何让你的笔记本成为一个完全令人惊叹的演示文稿的更多指导可以在下面的文章中找到这里。确保你遵循教程的每一行。此外,您还可以观看 YouTube 视频,了解如何在 Jupyter 笔记本上进行演示:
Credits: LiveLessons
现在我们已经到了文章的结尾,您现在知道了如何、何时以及在哪里在数据科学中使用 python 库。对于这篇文章,我已经尽力从头开始解释所有的事情。如果你们有任何疑问,请在下面随意评论。关于数据科学编码的更多信息,请访问我的 GitHub 库。谢谢你们阅读我的文章,我希望你们喜欢,如果没有让我知道需要改进的地方,我会改正的。不管怎样,再见,祝你愉快。
机器学习数据集的主要来源
寻找机器学习数据集的终极指南

Photo by Mika Baumeister on Unsplash
很难找到一个特定的数据集来用于各种机器学习问题,甚至很难进行实验。下面的列表不仅包含用于实验的伟大数据集,还包含描述、使用示例以及在某些情况下解决与该数据集相关的机器学习问题的算法代码。
1- Kaggle 数据集
[## 数据集| Kaggle
www.kaggle.com](https://www.kaggle.com/datasets)
这是我最喜欢的数据集位置之一。每个数据集都是一个小社区,在这里你可以讨论数据,找到一些公共代码或者在内核中创建你自己的项目。它们包含大量各种形状和大小、不同格式的真实数据集。您还可以看到与每个数据集相关联的“内核”,许多不同的数据科学家已经提供了笔记本来分析数据集。有时,您可以在笔记本上找到解决特定数据集中预测问题的算法。
2-亚马逊数据集
[## 自动气象站开放数据登记处
除非在适用的数据集文档中特别说明,否则可通过 Open…
注册表. opendata.aws](https://registry.opendata.aws/)
该资源包含不同领域的许多数据集,例如:(公共交通、生态资源、卫星图像等。).它还有一个搜索框来帮助您找到您正在寻找的数据集,它还有数据集描述和所有数据集的使用示例,这些信息非常丰富且易于使用!
数据集存储在亚马逊网络服务(AWS)资源中,如亚马逊 S3——云中高度可扩展的对象存储服务。如果您使用 AWS 进行机器学习实验和开发,这将非常方便,因为数据集的传输将非常快,因为它位于 AWS 网络的本地。
3- UCI 机器学习知识库:
https://archive.ics.uci.edu/ml/index.php

Snapshot from UCI Repos
来自加州大学信息与计算机科学学院的另一个伟大的存储库100 个数据集。它根据机器学习问题的类型对数据集进行分类。您可以找到单变量和多变量时间序列数据集、分类、回归或推荐系统的数据集。UCI 的一些数据集已经被清理干净,随时可以使用。
4-谷歌的数据集搜索引擎:
[## 数据集搜索
了解有关在数据集搜索中包含数据集的详细信息。
toolbox.google.com](https://toolbox.google.com/datasetsearch) 
2018 年末,谷歌做了他们最擅长的事情,推出了另一项伟大的服务。这是一个可以按名称搜索数据集的工具箱。他们的目标是统一成千上万不同的数据集存储库,并使数据可被发现。干得好,谷歌。
5-微软数据集:
2018 年 7 月,微软与外部研究社区一起宣布推出“微软研究开放数据”
[## 微软研究院开放数据
编辑描述
msropendata.com](https://msropendata.com/)
它在云中包含一个数据存储库,致力于促进全球研究社区之间的合作。它提供了一堆在已发表的研究中使用的精选数据集。
6- Awesome 公共数据集集合:
[## awesome data/awesome-公共数据集
公共领域中以主题为中心的 HQ 开放数据集列表。公关☛☛☛-awesome data/awesome-公共-数据集
github.com](https://github.com/awesomedata/awesome-public-datasets)
这是按主题组织的数据集的一个很好的来源,如生物学、经济学、教育学等。这里列出的大多数数据集都是免费的,但是在使用任何数据集之前,您都应该检查许可要求。
7-政府数据集:
也很容易找到政府相关的数据集。许多国家向公众公开了各种数据集,作为一种透明的做法。以下是一些例子:
- 欧盟开放数据门户:欧洲政府数据集。
- 美国政府数据(并非出于政治目的,但由于川普政府关闭或主页上提到的“缺乏资金”,该网站暂时不可用)。
- 新西兰政府数据集。
- 印度政府数据集。
- https://www.opendatani.gov.uk/(北爱尔兰公共数据集)
8-计算机视觉数据集:
如果你从事图像处理、计算机视觉或深度学习,那么这应该是你实验的数据来源。
计算机视觉数据集的搜索引擎
www.visualdata.io](https://www.visualdata.io/)
视觉数据包含少量可用于构建计算机视觉(CV)模型的大型数据集。您可以通过特定的 CV 主题(如语义分割、图像字幕、图像生成)甚至是解决方案(如自动驾驶汽车数据集)来查找特定的数据集。
9- Lionbridge 人工智能数据集:
机器学习数据集
|用于机器学习的 Lionbridge AI 数据集 lionbridge.ai](https://lionbridge.ai/datasets/)
总之,从我的观察来看,似乎有一个全球方向,让越来越多的数据可供研究和机器学习社区使用和轻松访问。这些新数据集的社区将继续增长,并使数据易于访问,以便众包和计算机科学社区可以继续快速创新,并为生活带来更多创造性的解决方案。
数据工作者的热门 SQL 查询
您需要知道的棘手和最常见的 SQL 查询
SQL(结构化查询语言)是关系数据库管理系统(RDBMS)中管理数据的主要语言。简单地说,SQL 是您与数据库交互的语言。

image by Steve Halama
在本文中,我将带您了解在访谈中最常见的 SQL 查询。
1.第 n 高工资
从员工表中获取第三高的薪金。
3rd Highest Salary
Dense_Rank(): 返回结果集分区中每一行的排名,结果值之间没有间隔。
您可以使用子查询来获得相同的结果。
2.查找重复记录
使用唯一标识符在表中查找重复记录。这里我使用 Firstname 作为标识符,但是您可以根据表信息使用任何其他标识符。
Duplicate records
3.不使用循环打印从 1 到 100 的数字
Numbers from 1 to 100
4.生成累计
给定产品和订单细节,我们必须生成每个产品的运行总数。(例如:第 3 行的累计将是前 3 行的总和)
a.编写一个子查询,通过对产品名称进行分组来生成每种产品的总量。
b.从上面的查询中计算运行总数。
Running total
5.查询以生成唯一的组合
考虑一个场景,你有 5 支球队,我们必须计划球队之间的联赛,这样所有的球队对都应该是唯一的。我将使用临时表和内部连接来实现这个结果。
a.创建具有唯一团队的临时表
下面是上述查询的结果集!!

Teams
b.用上面的结果生成所有可能的组合。
下面是上述查询的结果。

All combinations
在这里,我们可以看到所有可能的组合以及重复的组合,如(印度,澳大利亚;澳大利亚、印度)
c.让我们只生成唯一的组合
我们可以看到,如果 fromid 和 toid 匹配,则代表相同的组合。有两种可能的组合,要么来自 Id 的将大于来自 id的要么来自 id的将大于来自 id 的。让我们只取其中一个组合。
Query to get unique combinations

Final result
希望你喜欢!!!如果您有任何疑问,请评论!!
分享如果你遇到了任何棘手/复杂的问题,我会试着解决它们,并在这里添加。
塑造金融业的技术
“信息技术是你如何开展业务以及你的业务模式如何发展的核心。”
—微软首席执行官塞特亚·纳德拉
T4:向数字革命问好。虽然金融功能的必要性应该经得起时间的考验,但它的形式却不能这么说。这个行业不会消失,但它肯定会见证一些重大变化。
不出所料,一个关键的变革催化剂是技术。许多行业已经感受到了数字化变革力量的影响,金融也不例外。有大量的数字公司、软件和系统正在改变这个领域的工作方式。虽然有些高管可能会抵制集成技术,但事实是这种方法不会让你走得太远。尽管犹豫不决,金融技术在工作场所的整合今天可以相当成功地完成。
虽然金融功能的必要性应该经得起时间的考验,但它的形式却不能这么说。
金融科技的崛起无时不在,而且只会变得越来越强大,这证明了工作世界中没有哪个行业或角色可以免受数字化渗透的影响。由于《金融政策与分析》周刊的目标是让你跟上时代的步伐,下面我们将介绍当今可用的顶级金融技术,并解释它们如何能够立即融入你的工作场所。
自然语言处理 自然语言处理(NLP)是人工智能的一种形式,目前在当今会计和审计发展中发挥着重要作用。简而言之,NLP 涉及编程计算机来分析大量的自然语言数据。NLP 结合了计算能力和语言学,使用深度学习从示例中学习,进而为最终用户自动获取信息。现在,NLP 可以更好更快地完成任务,而不是让员工花时间浏览成千上万的文档,人类只需验证结果。
Kai
一个这样的 NLP 平台是 Kai ,这是 Kasisto 的一个对话式人工智能平台,它可以与客户进行类似人类的对话。Kai 精通金融语言,能够以一种引人入胜、充满智慧的方式与潜在客户和现有客户交谈。Kai 享有很高的声誉,已经得到了包括摩根大通、富国银行和万事达卡在内的顶级金融机构的信任。
通过识别哪些任务涉及大量的文书工作和信息验证,您可以将 NLP 平台集成到您的业务中。通过将这些任务分配给机器而不是人类,你会发现你的员工正在从事需要人类能力而机器目前无法执行的任务,例如需要创造力或情商的任务。
预测分析
预测分析分析目前的数据,以便对未知的未来事件做出预测。他们通过观察历史数据中发现的模式来识别未来的趋势和行为。使用预测分析使组织能够积极主动,并根据数据而不是人类的本能或假设做出决策。在金融领域,预测分析大有可为。据甲骨文称,预测分析在许多领域都是有益的,例如预测收入、检测欺诈和分析损失驱动因素。
Endor
Endor就是这样一个预测分析平台,它允许企业生成人工智能驱动的预测,从而充分利用组织数据。该公司以三项核心能力为傲:前所未有的速度和准确性,不需要数据科学家专业知识的无缝使用,以及该平台分析加密数据的能力。
机器人流程自动化(RPA) RPA 涉及自动化结构化和基于规则的任务。RPA 不被视为一种智能形式,因为它不能做出复杂的决策或改变其典型的行动过程。但是,集成 RPA 可以提高生产效率并极大地节省时间,因为它为更高附加值的活动腾出了时间。RPA 技术可以让您的业务达到全新的效率水平,因为它们消除了整合过程等浪费时间的事情。
DataRails
自动化整合流程的平台之一就是 DataRails。这是一款面向 FP & A 团队的企业级软件,他们的技术允许你继续以你习惯的方式使用 Excel 工作,同时消除了合并你接收和使用的所有不同电子表格的烦人任务。此外,您的所有数据都存储在您可以访问的结构化数据库中,您可以使用 DataRails 的平台来创建报告和提取见解。
可视化平台 数据可视化是发掘数据价值的关键一步。借助数据可视化平台,企业可以更多地了解组织的日常状况,并揭示数字背后的故事。可视化不同的统计数据以及对信息进行切片和切块为企业提供了视角和洞察力。通过无缝结合来自多个来源的信息,可视化平台通过访问实时财务和运营数据为您提供了一幅全面的画面。在动态图形和视觉效果之间进行选择,利用趋势跟踪功能,并使用直观的界面。通过考虑来自不同业务职能部门的所有信息,做出更明智的决策。
Sisense
说到金融可视化工具, Sisense 是一个领先的平台。Sisense 允许您连接和分析以前可能断开的数据,因此您可以简单方便地连接这些点。在一个地方清理、转换、管理和保护您的数据。
数据分析期间 K 均值聚类的三大错误
介绍
在本帖中,我们将看看 KMC 算法表现不佳或可能产生不直观结果的一些情况。具体来说,我们将查看以下场景:
- 我们对(真实)星团数量的猜测是错误的。
- 特征空间是高度多维的。
- 这些簇以奇怪或不规则的形状出现。
所有这些情况都会导致 K-Means 出现问题,所以让我们来看看。
错误的集群数量
为了简单起见,让我们定义一个助手函数compare,它将为我们创建并解决聚类问题,然后比较结果。
from sklearn import datasets
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs, make_circles, make_moons
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import pandas as pd
import itertools
def compare(N_features, C_centers, K_clusters, dims=[0, 1],*args):
data, targets = make_blobs(
n_samples=n_samples if 'n_samples' in args else 400,
n_features=N_features,
centers=C_centers,
cluster_std=cluster_std if 'cluster_std' in args else 0.5,
shuffle=True,
random_state=random_state if 'random_state' in args else 0)
FEATS = ['x' + str(x) for x in range(N_features)]
X = pd.DataFrame(data, columns=FEATS)
X['cluster'] = \
KMeans(n_clusters=K_clusters, random_state=0).fit_predict(X)
fig, axs = plt.subplots(1, 2, figsize=(12, 4))
axs[0].scatter(data[:, dims[0]], data[:, dims[1]],
c='white', marker='o', edgecolor='black', s=20)
axs[0].set_xlabel('x{} [a.u.]'.format(dims[0]))
axs[0].set_ylabel('x{} [a.u.]'.format(dims[1]))
axs[0].set_title('Original dataset')
axs[1].set_xlabel('x{} [a.u.]'.format(dims[0]))
axs[1].set_ylabel('x{} [a.u.]'.format(dims[1]))
axs[1].set_title('Applying clustering')
colors = itertools.cycle(['r', 'g', 'b', 'm', 'c', 'y'])
for k in range(K_clusters):
x = X[X['cluster'] == k][FEATS].to_numpy()
axs[1].scatter(
x[:, dims[0]],
x[:, dims[1]],
color=next(colors),
edgecolor='k',
alpha=0.5
)
plt.show()
集群太少

Figure 1a. Example of a 2-dimensional dataset with 4 centres, requesting 3 clusters (compare(2, 4, 3)).
尽管数据中有不同的聚类,但我们低估了它们的数量。因此,一些不相交的数据组被迫放入一个更大的群集中。
太多集群

Figure 1b. Example of a 2-dimensional dataset with 2 centres, requesting 4 clusters (compare(2, 2, 4)).
与最后一种情况相反,试图将数据包装到太多的集群中会在真实的数据集群中产生人为的边界。
高维数据
在我们开始发现问题之前,数据集不需要有那么高的维数。尽管可视化和对高维数据的分析已经很有挑战性了(现在开始诅咒…),但是 KMC 经常被用来洞察数据,它并不能帮助你理解数据的模糊性。
为了解释这一点,让我们生成一个具有明显不同聚类的三维数据集。
fig = plt.figure(figsize=(14, 8))
ax = fig.add_subplot(111, projection='3d')
data, targets = make_blobs(
n_samples=400,
n_features=3,
centers=3,
cluster_std=0.5,
shuffle=True,
random_state=0)
ax.scatter(data[:, 0], data[:, 1],
zs=data[:, 2], zdir='z', s=25, c='black', depthshade=True)
ax.set_xlabel('x0 [a.u.]')
ax.set_ylabel('x1 [a.u.]')
ax.set_zlabel('x2 [a.u.]')
ax.set_title('Original distribution.')
plt.grid()
plt.show()

Figure 2. Example of a 3-dimensional dataset with 3 centers.
尽管有无限多种方法可以将这个 3D 数据集投影到 2D 上,但是有三个主要的正交子空间:
查看x2 : x0投影,数据集看起来好像只有两个集群。右下角的“超星系团”实际上是两个不同的群组,即使我们猜对了K**(K = 3),这看起来也是一个明显的错误,尽管这些星系团非常局限。

Figure 3a. Projection on x0 : x2 shows spurious result (compare(2, 2, 4, dims=[0, 2])).
可以肯定的是,我们必须从不同的角度来看剩下的预测,才能真正理解这个问题。

Figure 3b. Projection on x1 : x2 resolves the ambiguity (compare(2, 2, 4, dims=[1, 2])).

Figure 3c. Projection on x0 : x1 resolves the ambiguity (compare(2, 2, 4, dims=[0, 1])).
这更有道理!
另一方面,我们有不可思议的优势。首先,有了三维,我们能够绘制整个数据集。其次,数据集中存在的聚类非常独特,因此很容易识别。最后,有了三维数据集,我们只需要面对三个标准的 2D 投影。
在 N,N > 3 特征的情况下,我们将不能绘制整个数据集,并且 2D 投影的数量将与 N 成二次比例:
更不用说数据集可能会有形状奇怪或者非本地化的聚类,这是我们的下一个挑战。
不规则数据集
到目前为止,我们提到了“我们这边”的问题。我们查看了一个非常“表现良好”的数据集,并讨论了分析方面的问题。但是,如果数据集不适合我们的解决方案,或者我们的解决方案不适合问题,该怎么办?正是这种情况,数据分布以奇怪或不规则的形状出现。
仅仅看到这张图,我们可能会误以为数据中只有两个聚类。然而,当绘制剩余的投影时,我们很快发现这是不正确的。
fig, axs = plt.subplots(1, 3, figsize=(14, 4))
# unequal variance
X, y = make_blobs(n_samples=1400,
cluster_std=[1.0, 2.5, 0.2],
random_state=2)
y_pred = KMeans(n_clusters=3, random_state=2).fit_predict(X)
colors = [['r', 'g', 'b'][c] for c in y_pred]
axs[0].scatter(X[:, 0], X[:, 1],
color=colors, edgecolor='k', alpha=0.5)
axs[0].set_title("Unequal Variance")
# anisotropically distributed data
X, y = make_blobs(n_samples=1400, random_state=156)
transformation = [
[0.60834549, -0.63667341],
[-0.40887718, 0.85253229]
]
X = np.dot(X, transformation)
y_pred = KMeans(n_clusters=3, random_state=0).fit_predict(X)
colors = [['r', 'g', 'b'][c] for c in y_pred]
axs[1].scatter(X[:, 0], X[:, 1],
color=colors, edgecolor='k', alpha=0.5)
axs[1].set_title("Anisotropicly Distributed Blobs")
# irregular shaped data
X, y = make_moons(n_samples=1400, shuffle=True,
noise=0.1, random_state=120)
y_pred = KMeans(n_clusters=2, random_state=0).fit_predict(X)
colors = [['r', 'g', 'b'][c] for c in y_pred]
axs[2].scatter(X[:, 0], X[:, 1],
color=colors, edgecolor='k', alpha=0.5)
axs[2].set_title("Irregular Shaped Data")
plt.show()

Figure 4. Misleading clustering results are shown on irregular datasets.
左图显示了其分布(虽然是高斯分布)不具有相等标准偏差的数据。中间的图表显示了各向异性数据,即沿着特定轴拉长的数据。最后,右图显示了完全非高斯的数据,尽管这些数据被组织成清晰的簇。
在这两种情况下,不规则性使得 KMC 算法表现不佳。由于算法平等地对待每一个数据点,并且完全独立于其他点,算法未能发现一个聚类内任何可能的连续性或局部变化。它所做的只是采用相同的指标,并将其应用于每一点。因此,KMC 算法可能会在数据中产生奇怪的或违反直觉的聚类,即使我们正确地猜测了 K 并且特征 N 不是很多。
结论
在这篇文章中,我们讨论了 K-Means 聚类算法给我们错误答案的三个主要原因。
- 首先,由于需要先验地确定聚类数 K ,因此我们很有可能会错误地猜测它。
- 其次,从分析的角度来看,高维空间中的聚类变得很麻烦,在这种情况下,KMC 将为我们提供可能具有误导性的见解。
- 最后,对于任何形状不规则的数据,KMC 很可能会人为地进行不符合常识的聚类。
知道了这三个谬误,KMC 仍然是一个有用的工具,尤其是在检查数据或构造标签的时候。
还会有更多…
我计划把文章带到下一个层次,并提供简短的视频教程。
如果您想了解关于视频和未来文章的更新,订阅我的 简讯 。你也可以通过填写表格让我知道你的期望。回头见!
最初发表于【https://zerowithdot.com】。
在线聊天的话题抽取和分类
一个用推断主题分类未标记文本数据的框架

当我们想要分类未标记的数据,即我们没有想要分类的信息的数据时,无监督和有监督的机器学习方法的组合可以是一个很好的解决方案。这篇博客文章介绍了一种可能的解决方案
- 首先,通过使用无监督主题建模自动识别文本数据语料库中的主题,
- 然后,应用监督分类算法,通过使用前一步骤的结果作为目标标签,将主题标签分配给每个文本文档。
这个项目使用了一家金融科技公司的客户关系管理团队的数据,特别是他们在英国和意大利的客户的在线聊天记录。
方法学

Flow overview
1.收集在线聊天文本

Data preprocessing pipeline
第一步是检索文本数据,并将其转换成我们想要使用的模型的兼容形式。在这种情况下,通常的 NLP 数据准备技术已被应用,此外还有针对该数据集特定性质的其他特别转换:
- 删除每次聊天中重复的文字部分;
- 应用自动翻译以使整个语料库用一种语言编写,在本例中是英语。另一种选择是保持文本的原始语言,然后为每种语言应用独立的预处理管道和机器学习模型;
- 使用符号化、词汇化、停用词和数字去除对文本进行预处理;
- 将 n-grams 添加到数据集,以指导主题模型。这里的假设是,被视为单个实体或标记的单词的短序列通常包含识别句子主题的有用信息。在这种情况下,只有二元模型才是有意义的——事实上,它们极大地提高了主题模型的性能;
- 使用计数矢量化将数据转换为数字术语-文档矩阵,将聊天文档作为行,将单个标记作为列,将相应的频率作为值(给定聊天中所选标记的频率)。这种所谓的单词包(BoW)方法没有考虑单词顺序,单词顺序在主题识别中不应该起关键作用。
2。摘录主题
此时,数据集处于潜在狄利克雷分配(LDA)模型的正确形状,该模型是本研究中已经实现的概率主题模型。文档术语矩阵实际上是模型需要的输入类型,以便推断以下方面的概率分布:
- 文档中的一组潜在(即未知)主题;
- 语料库词汇表(数据集中使用的所有单词的集合)中的单词,通过查看包含该单词的文档中的主题以及语料库中该特定单词的其他主题分配。

Credits: Christine Doig
LDA 以高维向量的形式输出 K 个主题(其中 K 作为参数提供给模型),其中每个分量代表词汇表中特定单词的权重。通过查看具有最高权重的术语,可以手动为 K 主题命名,从而提高输出的可解释性。

Manually given topic names on the left; top 10 words for the corresponding topics on the right.
LDA 还为数据集中的每个文档提供了一个主题分布,作为一个稀疏向量(少数组件具有高权重,所有其他组件具有 0 权重),从而更容易解释高维主题向量并提取每个文本的相关主题。

LDA output visualised with the pyLDAvis library. The model has been trained on about 10k chats, containing both English and Italian chats (translated into English). K=15 is the number of topics which has performed best among the tested values, according to the perplexity score. In the chart above, each circle on the left-hand side represents a topic with the size proportional to its frequency in the corpus; the right-hand side shows the overall relevance of the given token across the corpus. In the interactive visualisation, the bars on the right update after hovering over a topic circle to show the relevance of the tokens in the selected topic (red bars) as opposed to the relevance of the same tokens in the whole corpus (grey bars).
3.为聊天分配主题标签
因此,LDA 模型为每个接受训练的文档提供主题权重。现在,向监督方法的过渡变得简单明了:选择权重最高的向量分量,并将相应的主题用作给定聊天文档的目标标签。为了增加标签分配的置信度,在随后的步骤中,仅保留主导主题权重高于 0.5 的文本(也测试了其他阈值,但是 0.5 是允许同时在数据集中保持合理比例的在线聊天以及分配的良好置信度的值)。
4.分类新聊天
在建立了与监督机器学习算法兼容的设置之后,多项式逻辑回归模型已经被训练和测试,以将新聊天分类到相应的主题标签。在所使用的 4 重交叉验证技术的所有迭代中,在精确度和召回率方面的分类结果已经超过 0.96(在 15 个主题类别中的平均值)。
显然有许多方面可以调整和改进(例如,处理主题类别的不平衡,提高自动翻译的准确性,尝试对每种语言使用不同的流程,而不是对所有翻译的文本使用单一的流程,等等。),但有明确的证据表明,这种方法可以从非结构化文本的语料库中识别出有意义和有趣的话题信息,并提供一种算法,将话题准确地分配给以前看不见的在线聊天文本。
那又怎样?
这一应用于类似于本文所述的业务环境的分析显示了一个简单框架的有效性,公司可以在内部实施该框架,以了解其客户的查询、投诉或问题的类型。这也可以是一个起点,了解客户对特定产品、服务或缺陷的情绪或感觉,而不明确要求他们提供反馈。这是一种快速有效的方式来收集关于顾问和客户之间互动的见解,特别是如果有关于对话的元数据(如日期、持续时间)和其他类型的信息(如客户注册日期、在线活动、以前的投诉等)作为补充的话。).
2019 人力资源技术大会 Twitter 主题建模
人力资源技术大会暨博览会是全球领先、最大的人力资源和 IT 专业人士会议,于 2019 年 10 月 1 日至 4 日在拉斯维加斯举行。大会涵盖了大量的人力资源技术话题。不幸的是,不是每个人都能去,包括我自己。有没有可能不用身临其境就能说出流行语和话题是什么?答案是肯定的!我们在推特上寻找一些快速的见解。
我们使用#HRTechConf 抓取推文,并建立潜在狄利克雷分配(LDA)模型来自动检测和解释推文中的主题。以下是这项工作的流程:
- 数据收集——Twitter 抓取
- 文本预处理
- 可视化词云中的关键词
- 训练 LDA 模型
- 可视化主题
我们使用 Python 3.6 和以下软件包:
- TwitterScraper ,一个抓取推文的 Python 脚本
- NLTK (自然语言工具包),一个用于文本处理的 NLP 包,例如停用词、标点符号、标记化、词条化等。
- Gensim ,“生成相似”,一个流行的用于主题建模的 NLP 包
- 潜在狄利克雷分配 (LDA),一种用于主题聚类/建模的生成式概率模型
- pyLDAvis ,一个交互式 LDA 可视化包,用于帮助解释在文本数据语料库上训练的主题模型中的主题
数据采集
使用 Twitter 自己的 API 来抓取它总是具有挑战性。最大的一个缺点是,它只允许搜索过去 7 天内发布的推文。这是任何人寻找更老的过去数据来制作模型的一个主要瓶颈。幸运的是,有了 TwitterScraper 就没有这样的限制了。
from twitterscraper import query_tweets
# https://twitter.com/search-advanced
list_of_tweets = query_tweets('HRTechConf',
begindate=datetime.date(2019, 9, 26),
enddate=datetime.date(2019, 10, 6),
lang='en')
# Convert list of tweets to DataFrame
tweets_df = pd.DataFrame([vars(x) for x in list_of_tweets])
我们收集了 2019 年 9 月 26 日至 2019 年 10 月 6 日期间包含关键字“HRTechConf”的推文。在 10 天内,有 7,274 条推文,大多数推文是在 10 月 1 日至 3 日(会议的前 3 天)收费的。

HRTechConf 2019 Number of Tweets
我们来看看一些推文。
@Workday @ #HRTechConf 的 Charles Mah 强调了变革管理在转变您的团队和技术堆栈中的重要作用。它经常被低估和资源不足,但作为一名助教领导者,它对你的成功至关重要。
@josh_bersin 谈论#talentacquisition 的大规模增长。@jobvite 认为空间拥挤,用点解决方案碎片化。查看我们的技术信息图。https://bit.ly/2nQdmVq# HRTechConf
文本预处理
在我们可以应用任何机器学习算法之前,Twitter 数据需要进行预处理,以便将推文转换为可分析的形式。以下是预处理步骤:
- 将所有单词转换成小写
- 删除非字母字符
- 删除短单词(长度小于 3)
- 标记化:将句子分解成单词
- 词性标注:将单词按其语法类别分类的过程,目的是理解它们在句子中的作用,如动词、名词、形容词等。词性标注为词汇化提供了语法环境。
- 词汇化:将一个单词转换成它的基本形式,例如汽车、汽车和汽车的到汽车
- 去掉常见的英语单词,如 a,the,of 等。,并去掉对我们的分析增加很少价值的常用词,如 hrtechconf、much、hr、get 等。
from nltk.stem import WordNetLemmatizer
from nltk.corpus import stopwords, wordnet
import nltkdef get_wordnet_pos(word):
"""
Map POS tag to first character lemmatize() accepts
"""
tag = nltk.pos_tag([word])[0][1][0].upper()
tag_dict = {"J": wordnet.ADJ,
"N": wordnet.NOUN,
"V": wordnet.VERB,
"R": wordnet.ADV}
return tag_dict.get(tag, wordnet.NOUN)text_clean = text.lower()
# Remove non-alphabet
text_clean = re.sub(r'[^a-zA-Z]|(\w+:\/\/\S+)',' ', text_clean).split()
# Remove short words (length < 3)
text_clean = [w for w in text_clean if len(w)>2]
# Lemmatize text with the appropriate POS tag
lemmatizer = WordNetLemmatizer()
text_clean = [lemmatizer.lemmatize(w, get_wordnet_pos(w)) for w in text_clean]
# Filter out stop words in English
stops = set(stopwords.words('english')).union(additional_stop_words)
text_clean = [w for w in text_clean if w not in stops]
在预处理之后,上述推文被转换成:
['charles ',' mah ',' workday ',' highlight ',' essential ',' role ',' change ',' management ',' transform ',' stack ','经常','低估','资源丰富','关键','成功','领导者']
['josh ',' bersin ',' massive ',' growth ',' talentacquisition ',' jobvite ',' space ',' crowd ',' fragment ',' point ',' solution ',' infograph ']
单词计数和单词云
很难解释一个单词的意思。例如, machine 可能是机械机器、机枪或机器学习。相反,我们使用二元模型,即连续单词对进行单词计数。以下是在所有提取的推文中出现频率最高的 20 个短语。

HR Tech Twitter Word Count — Bigrams
从这个列表中我们能看出什么?
- “乔希·伯辛”是发微博最多的——乔希·伯辛是主题发言人。
- ADP 有很多 Twitter 报道“ADP 平台”、“thrill adp”、“action adp”、“ADP occurs”—ADP 是大会的金牌赞助商,其人力资本管理(HCM)平台在大会上赢得了一些顶级关注。
- 【人工智能】出现在很多推文中。
- “女性峰会”被多次提及——本次会议也以人力资源技术领域的女性为主题。
这里有一句话云:

HR Tech Twitter Wordcloud
特征抽出
推文或任何文本都必须转换为数字向量——描述文本(或语料库)中单词出现的字典。我们使用的技术被称为单词袋,这是一种提取文本特征的简单方法。以下是步骤。
词汇袋(二元模型)
统计二元模型
二元模型是两个单词的序列,例如机器学习,人才获取。通常情况下,一袋二元模型比一袋单词(单个单词或一元模型)更强大,能产生更有意义的见解。
建字典
我们构建推文的字典(或词汇表),其中推文的所有独特二元模型都被赋予 id,并且它们的频率计数也被捕获。我们使用 Gensim 库来构建字典。
我们从字典中排除了出现在不到 10 条 tweets 中的所有标记,因此我们只处理最有代表性的单词。此外,在超过 50%的推文中出现的二元模型也被删除,例如不久的将来,明年。
from gensim import corpora
tweets_dict = corpora.Dictionary(token_tweets)
tweets_dict.filter_extremes(no_below=10, no_above=0.5)
基于词典重建语料库
现在,使用上面的字典,我们为每条 tweet 生成一个单词计数向量,它由该特定 tweet 的词汇表中所有单词的频率组成。它们中的大多数都是零,因为 tweet 没有字典中的所有单词。
bow_corpus = [tweets_dict.doc2bow(doc) for doc in token_tweets]
TF-IDF
单词包基于文档由最频繁出现的单词表示的原理,即具有高“词频”(TF)的单词。这种方法的一个问题是,高频词开始在文档中占主导地位,但可能不像低频词那样代表模型。
解决这个问题的一种方法是测量一个词在所有文档(或推文)中的独特程度(或罕见程度),这被称为“逆文档频率”或 IDF。通过引入 IDF,在所有文档中频繁出现的常用词的权重会降低。
在 TF-IDF 中,我们将TF x IDF计算为字典中每个单词的权重,代表该单词在 tweet 中的出现频率乘以该单词在所有 tweet 中的独特性。TF-IDF 权重突出了 tweet 中不同的词(相关信息)。
from gensim import models
tfidf = models.TfidfModel(bow_corpus)
tfidf_corpus = tfidf[bow_corpus]
基于 LDA 的主题建模
现在,我们准备训练我们的 LDA 模型,从推文中学习主题。
LDA 是一种无监督的机器学习算法,它是一种生成统计模型,以文档为输入,以发现主题为输出。每个文档被认为是许多主题的混合物,每个主题由单词的频率(或单词分布)决定。LDA 是一种流行的概率主题建模算法。下面是对潜在狄利克雷分配的介绍。
我们使用 Gensim 库来训练超过 7000 条推文的 LDA 模型。要调整的一些模型超参数:
- 话题数量:每个话题是一组关键词,每个关键词对话题有一定的权重(即重要性)。太少的主题会导致不连贯的主题,包含不同种类的词,很难区分。太多的主题没有提供任何主题的任何语义意义。鉴于这是一个大事件,推文覆盖了几天,所有推文的主题数量可能会很高。我们将主题数量设置为 30。我们也尝试了 10,20 和 50,没有一个比 30 更好的结果。
- Alpha(文档主题密度):Alpha 越低,一条推文就越有可能包含几个主题的混合。默认设置是
1.0/NUM_TOPICS,我们使用0.001,因为每条推文都很短,很可能只有一个主题。 - Eta(单词-主题密度):Eta 越低,主题就越有可能包含少量单词的混合。默认是
1.0/NUM_TOPICS我们用的默认。 - 遍数:所有 tweets 的训练遍数/迭代次数。我们把它设置为 50。我们尝试了更大的数字,它们并没有产生更好的结果。
from gensim import models
NUM_TOPICS = 30
NUM_PASSES = 50
ALPHA = 0.001
ETA = 'auto'
# Train LDA model
lda_model = models.ldamodel.LdaModel(corpus=tfidf_corpus,
num_topics=NUM_TOPICS,
id2word=tweets_dict,
passes=NUM_PASSES,
alpha=ALPHA,
eta=ETA,
random_state=49)
以下是一些示例主题。数字越高,它们对主题的权重(重要性)就越大。
Topic: 20
Words: 0.823*"josh bersin" + 0.055*"opening keynote" + 0.018*"woman opening" + 0.012*"opportunity connect" + 0.007*"amaze event" + 0.006*"rebeccahrexec katieachille" + 0.006*"jeanneachille rebeccahrexec" + 0.006*"steveboese jeanneachille" + 0.005*"event feel" + 0.005*"lucky opportunity"
这个主题似乎是关于“乔希·伯辛”的,涉及“开场主题”和“女性开场”。在查看了人力资源技术会议网站后,我们可以确认 Josh Bersin 是主题演讲人,而人力资源技术会议开幕式也在同一地点举行。下面是一条推文示例:
今天从@Josh_Bersin 在#HRTechConf 的开幕主题演讲中签到!我们的团队喜欢听 Josh 分享他对技术如何为 HR . pic.twitter.com/ku27LKzmcb 塑造和创造新机会的见解
Topic: 3
Words: 0.259*"kronos ceo" + 0.059*"rule follow" + 0.041*"kronos highly" + 0.041*"surprisingly simple" + 0.041*"simple rule" + 0.041*"reveals surprisingly" + 0.041*"replicate success" + 0.041*"workinspired kronos" + 0.041*"follow replicate" + 0.041*"culture reveals"
看来这个话题是关于克罗诺斯的 CEO 揭示了一些令人惊讶的简单规则(文化?为了成功?)下面是一条推文:
hrconfes RT KronosInc:在#WorkInspired 中,克罗诺斯首席执行官 Aron Ain 带你走进克罗诺斯备受推崇的文化,并揭示了你可以遵循的惊人简单的规则,以开始复制这种成功。#HRTechConf
Topic: 7 Words: 0.187*"marcus buckingham" + 0.177*"book signing" + 0.138*"free copy" + 0.124*"nine lie" + 0.079*"present lie" + 0.079*"buckingham present" + 0.001*"peopledoc inc" + 0.001*"drive engagement" + 0.001*"around world" + 0.001*"answer question"
好像这个话题是关于马库斯白金汉的签名售书和免费赠送(九个谎言?可能是书名)下面是一条推文:
hrtechconf 与 Marcus Buckingham 的图书签售# FreeThinkingCoalition # 9 lies about workhttps://www . insta gram . com/p/b 3 khdhwlrgrifxreqnoixdaznthcdr-_ tj8ae 00/?IGS id = 19 rvtzygznze 1…
主题可视化
为了让它更有趣,我们使用了一个交互式 LDA 可视化包 pyLDAvis ,来绘制所有生成的主题及其关键字。pyLDAvis 计算 2D 平面上的主题和项目主题之间的语义距离。
import pyLDAvis.gensim
lda_data = pyLDAvis.gensim.prepare(lda_model, corpus, dict, mds='mmds')
pyLDAvis.display(lda_data)
这里是到互动页面的链接。
左边的每个气泡代表一个主题。气泡的大小代表主题的流行程度。气泡之间的距离反映了主题之间的相似性。两个圈越近,话题越相似。
好的主题模型应该有一些占主导地位的较大的气泡,较小的分散在平面上。如果一个图有许多重叠的小圆圈,通常是有太多主题的迹象。
在右边,它显示了该主题的前 30 个最重要的二元模型。当悬停在一个气泡上时,它会更新右边的单词列表。此外,如果您从列表中选择一个单词,它将突出显示所选单词出现的圆圈。

HR Tech Conf 2019 Topics LDA
结束语
我们搜集了 #HRTechConf 的推文,生成了一个词云来显示流行语,并建立了一个 LDA 模型来学习推文的主题。
LDA 很难训练,结果需要人工解释。然而,它非常强大而且直观。我们的实验表明,所学主题的单词并不完全相似或连贯,但肯定与主题相关。
改进 LDA 结果的未来工作:
- 使用网格搜索优化超参数
- 正式确定最佳建模性能的最佳主题数量
所有代码都可以在 GitHub 上找到。
机器学习快乐!
基于自然语言处理的新加坡子编辑评论主题建模

Marina Bay Sands, Singapore
新加坡网民在谈论什么?
动机
你们中有些人可能不知道,我报名参加了 Metis 的数据科学训练营的第一批学员。作为一名外国人,我想更多地了解我所在的国家,还有什么比在 subreddit 论坛上进行主题建模更好的方式来了解外国呢?你可能会说,走出去,与当地人打成一片,你可能是对的——但这包括走出舒适的空调房(新加坡真的很热);不,我只是还没准备好离开我的安全空间。
于是,我开始了我的探索之旅(提示戏剧探索音乐),穿越新加坡的数字景观,这是新加坡的子编辑区——富含一些未经过滤的对话数据,涉及新加坡人日常谈论的问题。完全不知道会发生什么,我做好了内心深处的准备。好吧,有点夸张了。继续前进。
数据采集

此处关注的时间范围为 2015 年 1 月至 2019 年 6 月。我选择了一个特别大的时间段来考虑季节性和抽样偏差。例如,如果我只看 2015 年的数据,话题可能会偏向政治,因为新加坡上一次大选就是在那一年举行的。
在工具方面,Python Reddit API 包装器(PRAW)被考虑并抛弃,转而支持 Pushshift API。对 PRAW 施加的限制意味着只能获得有限数量的评论;Pushshift 的情况并非如此。
虽然 Pushshift 确实将 API 调用限制为每次调用 1000 个条目,但是对可以进行的调用数量没有实际限制。编写了一个脚本来迭代这个过程,直到在指定的时间范围内检索到所有的评论。由于硬件和时间限制,随机抽取了 100 万条评论。
数据清洗&预处理
不出所料,获得的数据极其肮脏。在进行 NLP 预处理之前,必须进行彻底的清理。是时候重新承担责任了。

How I look cleaning data in Python (Source)
总之,这些是步骤:
- 删除自动生成的 bot 注释(例如,“[已删除]”、“[已删除]”、“您的提交已被删除,因为它没有任何内容……”等)
- 删除符号和标点符号,包括表情符号,如:)和奇怪的流行(͡ ͜ʖ ͡),出现了几百次
- 删除汉字和新加坡式英语(新加坡式英语俚语)词汇,如‘lah’,‘lor’,‘shiok’,‘bojio’等(确实是非常丰富多彩的语言)
- 删除 URL 和图像链接
- 标记化和小写
- 过滤掉停用词和短词(少于 3 个字母)
- 生成二元模型和三元模型
- 通过词类(PoS)标记,仅识别和考虑名词和形容词
- 词汇化
- 生成唯一单词的字典
- 生成词袋语料库作为术语文档矩阵,在论坛线索内聚集评论,并将线索视为不同的文档
部分代码如下所示:
def preprocess(comment):
**# Tokenize**
def sent_to_words(sentences):
for sentence in sentences:
yield(gensim.utils.simple_preprocess(str(sentence),
deacc=True))
data_words = list(sent_to_words(comment))
**# Remove Stop words & Short Words**
from nltk.corpus import stopwords
stop_words = stopwords.words('english')
stop_words.extend(['congrats', 'lol', 'yup', 'thanks', 'nope',
'http', 'www', 'com', 'https','amp', 'sg',
'reddit', 'gt'])
def remove_stopwords(texts):
return [[word for word in simple_preprocess(str(doc)) if
word not in stop_words and len(word) > 2] for doc
in texts]
data_words_nostops = remove_stopwords(data_words)
**# Bigrams**
bigram_config = gensim.models.Phrases(data_words_nostops,
min_count=5,
threshold=100)
bigram_mod = gensim.models.phrases.Phraser(bigram_config)
def make_bigrams(texts):
return [bigram_mod[doc] for doc in texts]
bigrams_list = make_bigrams(data_words_nostops)
**# Lemmatization**
def lemmatization(texts):
nlp = spacy.load('en', disable=['parser', 'ner'])
allowed_postags = ['NOUN', 'ADJ']
texts_out = []
for sent in texts:
doc = nlp(" ".join(sent))
texts_out.append([token.lemma_ for token in doc if
token.pos_ in allowed_postags])
return texts_out
data_lemmatized = lemmatization(bigrams_list)
**# Create Dictionary**
id2word = corpora.Dictionary(data_lemmatized) **# Create Corpus**
corpus = [id2word.doc2bow(text) for text in data_lemmatized]
return corpus, id2word, data_lemmatized
建模&评估
在对数据进行清理和预处理后,对几个模型进行了实验。潜在狄利克雷分配(LDA)和 Mallet LDA 似乎总是优于潜在语义分析(LSA)和非负矩阵分解(NMF)。
这些模型及其结果的简要回顾如下:
LSA

LSA Decomposition — Source
LSA 是一种矩阵分解模型,它假设具有相似含义的单词将包含在相似的文本片段中。本质上,使用奇异值分解(SVD)将文档频率矩阵分解成上述 3 个矩阵,当相乘时,这些矩阵近似地重构原始的 M X M 矩阵。
左单数 M X N 矩阵以话题的方式表达文字。右单数 N X M 矩阵用主题表示文档。通过应用类似余弦相似度的方法,能够评估不同单词之间的相似度和不同文档之间的相似度。
要注意的是,通常,术语频率-逆文档频率(TF-IDF)矩阵将被用于归一化每个词在整个文档集合中的频率,以给予不太频繁的术语更多的权重。与使用原始词频计数相比,这通常会产生更好的结果。
NMF

NMF Decomposition — Source
NMF 也是一个矩阵分解模型,非常类似于 LSA,但有一个额外的限制,即所有 3 个矩阵必须只包含非负值。这样做的效果是,NMF 不能撤销潜在特征的应用(由于没有负值),因此对于如何导出这些特征更加“小心”。这也意味着 NMF 模型在分解过程中会丢失更多的信息。
LSA vs NMF 结果


LSA Topics (left) vs NMF Topics (right)
可比。有些话题可以从两者中推断出来,但一般来说,还不够好。
LDA

LDA — Source
与上面的两个模型不同,LDA 是一个概率模型。在 LDA 中,每个文档由主题的概率分布来描述,每个主题由词的概率分布来描述。在第一遍中,该算法为每个文档中的每个单词分配一个随机主题。每次通过后:
- (1)通过计算 P(主题 T |文档 D) =文档 D 中当前分配给主题 T 的单词的比例,检查主题在文档中出现的频率
- (2)通过计算 P(单词 W |主题 T) =在包含单词 W 的所有文档中,主题 T 的分配比例,检查该单词在主题中出现的频率
- (3)基于(1)和(2)更新每个单词的主题分配。
- (4)当从一个单词移动到另一个单词时,它通过保持所有其他赋值为真和当前赋值为可疑来实现这一点。
传球越多,责任越大。什么?随着作业达到大致稳定的状态,主题群开始变得越来越清晰可辨。
Gensim LDA 结果

Gensim LDA Topics
你可以从生成的主题中看出,它们比 LSA & NMF 模型要好很多。有些主题已经可以确定,而其他一些像主题 7 仍然是…奇怪的。护肤?我需要找人聊天。我没说它很完美。
马利特有限公司
Mallet LDA 是上面使用的 Gensim LDA 的变体。不同之处在于,Gensim 使用变分贝叶斯采样方法,与 Mallet 的 Gibbs 采样方法相比,变分贝叶斯采样方法速度更快,但精度较低。
Mallet LDA 结果
我用 Mallet 的 LDA 获得了最大的成功,产生了主题清晰可辨的单词簇(对我来说)。因此,我冒昧地将它们与我认为合适的标签一起封装在 word cloud glory 中。








Mallet LDA Topics Word Cloud
设定 K

Coherence Score k=8 Peak
到目前为止,您可能已经注意到,上面描述的所有模型都使用 k=8 作为主题数。这是因为连贯性得分在 k=8 时达到峰值,并随着话题的增多或减少而下降。和往常一样,也有必要关注生成的主题簇,看看它们是否有意义。不过,在我的案例中,我很满意一致性分数和人工检查似乎彼此一致。
部署
皮尔戴维斯
正如你将从下面的交互式可视化中看到的,潜在空间中的主题有很好的分离。您可以试验一下相关性指标,看看还有哪些词属于每个主题。
Mallet LDA visualized using pyLDAvis
收尾
对结果相当满意。领域知识在这方面很重要,可以用不同的 k 值进行实验,看看主题集群是否有意义。如果有更多的时间,我会喜欢用 lda2vec 进行实验,并结合一些时间序列分析,看看主题景观如何随时间变化。或许情感分析也是?有了数据,你可以做很多事情。但是现在,这是我的结论。
使用的工具:NLTK,SpaCy,Sk-learn,Gensim,Mallet,pyLDAvis
用 Gensim 进行主题建模
使用 Python 的 Gensim 库预处理文本和主题建模的入门指南

Photo by Jelleke Vanooteghem on Unsplash
主题建模是一种发现出现在文档集合中的主题的方法。它可以用于从聚类到降维的任务。
主题模型在许多场景中都很有用,包括文本分类和趋势检测。
然而,一个主要的挑战是提取高质量、有意义和清晰的主题。Gensim 是一个 Python 库,它将自己定义为“人类的主题建模”,这有助于使我们的任务变得简单一些。
在 Gensim 的介绍中,它被描述为“被设计成尽可能高效(对计算机而言)和无痛(对人类而言)地从文档中自动提取语义主题。”
对我来说,这使得使用它进行主题建模变得显而易见。
数据和目标
我们将继续使用我们的唐纳德·特朗普推特数据集。它相对较小,易于使用,并且涵盖了非常多样的主题。
鉴于推特的数据集,我们将尝试识别关键话题或主题。
文本预处理
Gensim 的网站称其“旨在处理原始的、非结构化的数字文本”,并为此配备了一个预处理模块。
preprocess_string方法使得准备文本变得非常容易。默认情况下,它会去掉标点符号、HTML 标签、多个空格、非字母字符和停用词,甚至会对文本进行词干处理!它返回一个完全处理过的字符串列表:
Preprocess_string example
不幸的是,对于我们的 twitter 数据集,默认设置可能不是最好的选择:链接被分成两个标记,其中第二个标记似乎没有意义。
幸运的是,我们仍然可以使用preprocess_string并声明一个定制的过滤器变量来选择我们想要使用的过滤器:

这样更好看!我们已经对文本进行了预处理,保持了链接的完整性。
词典和语料库创建
Gensim 要求将令牌转换为字典。在这种情况下,字典是单词和它们的整数 id 之间的映射。

主题和转换
Gensim 支持几种不同的转换,但这里我们将只关注 TF-IDF 和 LDA。
TF-IDF 或术语频率逆文档频率类似于词袋,但它降低了频繁出现的标记的权重。
根据 Gensim 的文档,LDA 或潜在狄利克雷分配是“从词袋计数到低维度主题空间的转换”。。。LDA 的主题可以解释为单词的概率分布。
我们首先将 TF-IDF 应用于我们的语料库,然后是 LDA,试图获得最佳质量的主题。

形象化
我们可以使用 PyLDAVis 轻松地可视化和解释我们的 LDA 模型中的主题。
当解释我们的视觉化时,请记住,较大的主题表明它们更频繁,彼此更接近的主题更相似。


我们可以看到我们有 10 个主题。一些主题有明显的重叠。这可能表明我们的主题可能不理想。
有几种方法可以用来改善我们的主题分离。一些潜在的选择是提高我们预处理的质量,改变主题的数量,以及添加 n 元语法。
结论
在这里,我们探索了用 Gensim 进行主题建模和预处理,这只是该库所提供的一小部分。
在以后的文章中,我们将继续探索主题建模,包括提高主题质量的方法。
拓扑数据分析-解开行话

Turning points into shapes into insight.
听到“拓扑数据分析”这句话,几乎每个人的反应都不一样。数学家们对“拓扑学”和“分析”这两个词的结合感到兴奋,但原因是错误的。统计学家看到了一个以新的方式应用工具的机会。至于其他人,“分析”是简历中最常见的名词之一,所以我认为这个领域的其他部分都包括在内了。
好了,够了。什么事?
在本文中,我将具体分解什么是拓扑数据分析以及如何考虑它。我的目标是回答以下问题:
- 什么是拓扑数据分析?
- 拓扑和拓扑数据分析有什么关系?
- 数据分析与拓扑数据分析有什么关系?
基础
拓扑数据分析的目的是应用拓扑的工具——一个处理定性几何特征如光滑度和连通性的数学领域——来分析数据集。
这些数据集通常很大而且是高维的,但是也可能有不完整的部分或者有噪声。希望在理解数据的几何结构时,可以获得一些看不见的洞察力。

Excellent example drawn from here.
看看上面的数据集。这些点集有什么拓扑结构?
它似乎代表了一个有一定宽度的环,如下图所示。

A donut shape surrounding the points.
这只是我们的直觉。我们如何实际验证这是潜在的几何结构?
点→形状
当前的设置是我们在空间中有一个大的点集合。问题是:我们如何把点变成形状?
要做到这一点,我们需要定义什么是所谓的k-单形。ak-单纯形是你取 k +1 个点,画出包围所有这些点的最小形状(称为凸包)得到的。一张照片总是做得最好:

A k-simplex for k = 0, 1, 2, 3. Picture from this excellent course on discrete differential geometry.
我们也可以把这些k-单形(复数;想顶点→顶点)形成单纯复形。

A simplicial complex.
接下来呢?
有单纯的情结听起来不错,但是这怎么适应呢?如果我们回到我们收集的点,让我们考虑如何连接它们。考虑这个过程:
- 固定一个实值距离 d 。
- 围绕每个点画一个半径为 d 的圆。
- 如果两个圆相交,在圆心处的两点之间画一条线(单形)。
- 如果三个圆相交,在圆心的三点之间画一个三角形(2-单纯形)。
- 若 k +1 圆相交,则在圆心的 k +1 点之间画一条k-单形 。
说了这么多,做了这么多,我们最终得到的是一个简单的复合体,它粗略地描述了物体的形状。

The result of the procedure above.
选择正确的距离
我们差点就成功了!我们有一个把点变成形状的机制,这是进一步分析之前最大的障碍。
最后一个组成部分是选择正确的距离 d,如果 d 太小怎么办?d 太大怎么办?对于不同的距离值,几何特征会发生变化。
这些方面在持续同源领域都是必不可少的,持续同源是拓扑数据分析受到启发的主要工具。支持持续同源性的数学是相当先进的,但是这个想法都在我们已经讨论过的文字和图片中!
资源
本文在很大程度上依赖于各种资源创建的思想和图表。我希望这篇文章能激发人们对拓扑数据分析的兴趣,所以我也将给出一些你接下来可能想去的地方的链接!
一如既往,我很高兴听到你的反馈和下面的问题。
全文关于拓扑数据分析&持久同调:
幻灯片 & 课程笔记解释了k-单形和单形复形,以及离散微分几何中的更多概念:
拓扑数据分析的技术介绍:
Torch vs Keras 用于 CNN 图像分类:关于石头剪刀布数据集的思考
上周,我写了一篇关于使用 CNN 分类法对石头、纸或剪刀手势的图像进行分类的文章,该分类法是使用名为“torchvision”的软件包在 pyTorch 框架上构建的。
参见:
在过去的一年里,我一直在探索 Pytorch 框架的使用,并注意到许多答案…
medium.com](https://medium.com/swlh/rock-paper-scissor-image-classifier-using-torch-vision-and-a-cnn-f54d3ed0a65e)
的文章,并且:
在 GitHub 上创建一个帐户,为 xijianlim/torch_and_keras 的开发做出贡献。
github.com](https://github.com/xijianlim/torch_and_keras/blob/master/CNN_RPS_torch.ipynb)
对应的代码。
我想在 Keras 中复制相同的分类器,以查看相对易用性和特性。简而言之:Keras 和它的包看起来比 Torch 好用得多。这里是在数据加载、网络架构和培训上使用深度学习框架所涉及的阶段的比较。
- 图像数据集加载:
这两个软件包都完成了繁重的工作,只需提取存储文件夹中的所有图像,然后将它们添加到数据加载器中,然后输入到您的网络中。前提是你如何存储你的图像在单独的子文件夹(“石头”,“纸”或“剪刀”)在一个数据文件夹,和加载器包读取相应的图像和标签的基础上的子文件夹名称。
让我们看看不同之处
喀拉斯:

还有火炬:

如果你马上想到 Keras 的 ImageDataGenerator 看起来更加用户友好,呈现更加整洁,那你就对了。它用目标张量形状以直观的方式处理图像大小调整。另一方面,Torch 使用“中心裁剪”和“调整大小”等术语来分别表示高度和宽度。
2。神经网络架构
Keras 作为一个包装器在 Tensorflow 后端做了很多繁重的工作。它越来越受欢迎的一个原因是由于它的顺序功能,你可以在“阶段”添加你的输入,隐藏和输出层。
我使用大致相同的架构重建了相同的 CNN 模型(唯一的例外是辍学率)。
Keras 脚本:

vs 火炬:

Torch 要求你建立一个实际的类,所有的层都有相应的输出到每个连接的层。这在迫使用户适应从整体上思考神经网络架构方面是很棒的,但如果手动争论和寻找答案,这确实需要一点时间。
一个明显的例子是在 Keras 和 Torch 之间后来的最终输出:
在 Keras 中,我们简单地使用一个 softmax 函数来获取模型为 3 个类生成的数值类:{'paper': 0,' rock': 1,'剪刀':2}。
另一方面,在 Torch 中,在将最终输出传递给具有张量大小和 3 个 out_channels 的线性函数之前,我们必须通过 out=out.view(out.size(0),-1)将最终输出处理为 soft max“like”函数。迷茫?我也是!你可能会认为火炬会自动重塑 conv2 函数中的张量,但可惜事实并非如此。
3。训练:
Keras 使用标准的“model . fit”函数,熟悉很多机器学习模型:

如此简单,干净,优雅,最少的大惊小怪。
在火炬中:

实际上,你必须声明为网络供电所需的回路、清除梯度、计算损耗、训练步骤并测试精度。如果您喜欢灵活地分配自己的训练步骤和验证批次,并且非常擅长循环,Torch 绝对适合您。
关于两种包装的想法
老实说,我在 20 多分钟内就建立、训练并运行了这个 Keras 模型。相比之下,Torch 需要使用在线材料和课程来解决问题,特别是处理与读出的最终层的形状有关的输出张量。Torch 也有非常不直观的词汇来重塑图像大小,这需要在阅读文档后进行实验。
然而,Torch 确实迫使用户思考所有深度学习模型的根源:张量。人们必须始终考虑张量的形状、输入层、输出层的样子以及模型将产生的表达式。
如果 torch 有一种方法来执行张量形状的迷你输出,或者有一种方法来预览连接层之间的输出,我认为用户会更愿意尝试一下 Torch。
描述 torch 的最佳方式就像是玩一个类似 Darksouls 或 Sekiro 的软游戏:

…或者读尼采和德勒兹。
当你试图获得事物的机制时,这可能会令人沮丧,但是看到你的模型最终开始前馈和训练步骤的满足感是超越宣泄的。
我将推荐的是,首先使用在线课程尝试 Torch,以获得所有的基础知识,然后使用 Keras 制作生产版本。
到目前为止,我已经看到了无数不同的训练步骤,作为一名编码人员,从中学习和产生想法是很棒的。正如 Keras 在包装器中为您做的繁重工作一样,为您自己的表达式调整代码的灵活性可能不存在。
如果您想查看 CNN Keras 版本的代码,请访问:
在 GitHub 上创建一个帐户,为 xijianlim/torch_and_keras 的开发做出贡献。
github.com](https://github.com/xijianlim/torch_and_keras/blob/master/CNN_RPS_torch.ipynb)
火炬视觉和迁移学习
试图直接操纵预先训练好的火炬视觉模型

Photo by Possessed Photography on Unsplash
这篇文章可能对刚开始深度学习的人或相对来说不熟悉 PyTorch 的人最感兴趣。这是我最近尝试修改 torchvision 包的 CNN 的经验总结,这些 CNN 已经根据来自 Imagenet 的数据进行了预训练。目的是使多体系结构分类器更容易编程。
众所周知,机器学习实践者可以通过保留预训练模型的最后一层以外的所有层来利用预训练模型,冻结剩余层中的参数,然后将自定义分类器附加到模型的末尾,稍后使用用户数据进行训练。
我在 2019 年 3 月下旬完成了 Udacity 所谓的纳米学位“用 Python 进行人工智能编程”。对于本课程的期末项目,学生必须使用至少两种不同类型的 CNN 架构来正确分类不同类型的植物和野花的照片。
可供学生使用的 CNN 架构由 PyTorch 的 torchvision 模块提供,并在 Imagenet 的图像上进行了预处理。面临的挑战是采用这些不同的预训练 CNN 架构,然后利用迁移学习的概念,将我们自己的利用 PyTorch 的分类层附加到模型的末尾。然后,该分类器将根据互联网上某个来源提供的植物和野花照片进行训练。
为了检查 torchvision 中包含的预训练模型的架构,我使用了 Python 解释器中的以下过程:
>>> from torchvision import models
>>> model = models.vgg13(pretrained=True)
>>> model
VGG(
(features): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU(inplace=True)
(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(3): ReLU(inplace=True)
(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
[…snip…]
(24): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
(classifier): Sequential(
(0): Linear(in_features=25088, out_features=4096, bias=True)
(1): ReLU(inplace=True)
(2): Dropout(p=0.5, inplace=False)
(3): Linear(in_features=4096, out_features=4096, bias=True)
(4): ReLU(inplace=True)
(5): Dropout(p=0.5, inplace=False)
(6): Linear(in_features=4096, out_features=1000, bias=True)
)
)
请注意,对于 torchvision vgg13 预训练实现,最后一个父模块,即被学生的分类器替换的模块,被命名为“分类器”。
由于任务的目标是使用至少两种不同的预训练 CNN 架构,我看了看 torchvision 模块提供的其他模型。我发现火炬视觉预训练 CNN 模型的分类部分至少有两个不同的名字。除了“分类器”,resnet101 预训练 CNN 使用“fc”(大概代表“完全连接”)作为其最终分类模块。
最终,我的自定义分类层需要使用类似下面的语句连接到预训练的 CNN:
model.classifier = my_custom_classifier
但是,如果用户从命令行指定一个 resnet101 架构,会发生什么呢?既然架构的名称与“分类器”不同,我该如何用上面的技术覆盖最后一个模块呢?
因为我想在项目中重用尽可能多的代码,所以我有几个选择。第一,我可以为分类模块选择具有相同名称的架构,第二,我可以看看是否可以找到一种方法来实现 任何通用架构 ,并找到一种方法来处理不同架构对分类模块具有不同名称的事实。第三种选择是根据用户选择的模型将自定义分类器附加到用户选择的架构上。比如“如果”用户选择了 resnet101,“那么”我们使用“fc”,否则,我们使用“分类器”。
最终,我选择了第二个选项。我的决定是试图将“分类器”模块名等同于“fc”模块名。换句话说,我选择了做类似这样的事情:
model.classifier = model.fc = my_custom_classifier
目标是为我的自定义分类器提供多个名称,这样无论我选择什么架构,我都可以使用名称“fc”来引用分类层。这个 看起来 起作用了,这是我最后一个项目(通过了)用的。
在 2019 年 8 月完成“深度学习”纳米学位项目(我的第二个人工智能相关纳米学位)后,我想回到我最初的“用 Python 进行人工智能编程”项目,花多一点时间熟悉 PyTorch,因为大多数深度学习项目都使用 Tensorflow。我还想添加一个命令行参数,以便用户可以指定分类器可以区分的类别数量,而不是在代码库中固定数量。
很快,我开始研究几个月前完成的项目代码,准备修改它以接受分类器可以从命令行区分的类别数量。
没过多久,我就发现我的“诡计”根本没有达到我的预期目的。代码运行得很好,但不像我最初设计的那样。
代码没有让我用多个名称引用我的自定义分类器,而是在我选择的预训练架构的末尾添加了两个自定义分类器。例如,我对 vgg13 架构的总结如下:
*VGG(
(features): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU(inplace=True)
(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(3): ReLU(inplace=True)
(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
[…snip…]
(24): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
(classifier): Network(
(hidden_layers): ModuleList(
(0): Linear(in_features=25088, out_features=256, bias=True)
)
(output): Linear(in_features=256, out_features=102, bias=True)
(dropout): Dropout(p=0.2, inplace=False)
)
(fc): Network(
(hidden_layers): ModuleList(
(0): Linear(in_features=25088, out_features=256, bias=True)
)
(output): Linear(in_features=256, out_features=102, bias=True)
(dropout): Dropout(p=0.2, inplace=False)
)
)*
正如您从名为' classifier '和' fc '的模块中看到的,我尝试为自定义分类器提供多个名称的最终结果失败了。它所做的只是将自定义分类模块的两个副本放在预训练的 vgg13 CNN 的末尾。更糟糕的是,我的辍学层出现在了错误的地方。我希望它在隐藏层之后显示出来。回到众所周知的绘图板。
我意识到我需要的是一种方法,可以用来操纵 torchvision 模块提供的预训练模型的架构。如果我能够操纵这个架构,我就可以对 torchvision 提供的任何预训练 CNN 的最后一个模块执行相当于“删除”(或者“重命名”)的操作。然后,我想,在预先训练的 CNN 中,分类模块的名称是什么并不重要,我可以随便叫它什么,而不必担心分类模块的名称。更好的是,我不必担心决策代码来处理不同架构的使用。
在这一点上,我决定看看 torchvision 模型到底有哪些可用的方法和属性。为了做到这一点,我再次回到解释器:
*>>> from torchvision import models
>>> x = models.vgg13(pretrained=True)
>>> x.<tab><tab>
x.add_module( x.cpu( x.features( x.named_buffers( x.register_buffer( x.state_dict(
x.apply( x.cuda( x.float( x.named_children( x.register_forward_hook( x.to(
x.avgpool( x.double( x.forward( x.named_modules( x.register_forward_pre_hook( x.train(
x.buffers( x.dump_patches x.half( x.named_parameters( x.register_parameter( x.training
x.children( x.eval( x.load_state_dict( x.parameters( x.requires_grad_( x.type(
x.classifier( x.extra_repr( x.modules( x.register_backward_hook( x.share_memory( x.zero_grad(*
通过查看上面的输出,我学到的第一件事是,每个顶级模块都有对应的方法。例如,每个“特性”、“avgpool”和“分类器”都有相应的方法。其中名称根据火炬视觉模型而不同,因此方法也不同。例如,resnet101 模型没有“classifer”方法。它有一个用于分类器的“fc”方法。
我花了一些时间来试验不同的方法,并利用 Python 的帮助工具来探索它们,并提出了我的第一个(尽管是天真的)想法,即使用从 nn 继承的“add_module”方法。模块:
*>>> help(model.add_module)
Help on method add_module in module torch.nn.modules.module:
add_module(name, module) method of torch.nn.modules.container.Sequential instance
Adds a child module to the current module.
The module can be accessed as an attribute using the given name.
Args:
name (string): name of the child module. The child module can be
accessed from this module using the given name
module (Module): child module to be added to the module.*
根据上面的信息,这似乎正是我所需要的,我对实现进行了如下测试:
*>>> from torchvision import models
>>> from torch import nn
>>> tv_model = models.vgg13(pretrained=True)
>>> model = nn.Sequential()
>>> tv_model_children = list(tv_model.children())[:-1]
>>> tv_model_children
[Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU(inplace=True)
(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(3): ReLU(inplace=True)
(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
[…snip…]
(24): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
), AdaptiveAvgPool2d(output_size=(7, 7))]
>>>*
请注意,tv_model_children 列表中没有列出“分类器”模块。由于我们最终将把我们自己的分类器附加到上面创建的名为“model”的模型上,这正是我们想要的。
现在,让我们将 tv_model_children 列表中的模块添加到我们的新模型中:
*>>> for i in range(len(tv_model_children)):
... model.add_module(str(i), tv_model_children[i])
...
>>> model
Sequential(
(0): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU(inplace=True)
(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(3): ReLU(inplace=True)
(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
[…snip…]
(24): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(1): AdaptiveAvgPool2d(output_size=(7, 7))
)*
此时,一切似乎都如我所愿。我已经有效地从 torchvision vgg13 预训练模型中“删除”了分类器模块。现在,我可以用我选择的任何名称将分类器附加到模型上。我的下一步是在我的程序中复制这种方法,看看它是如何工作的:
*python train.py --arch vgg13 --dropout 0.2 --epochs 7 --gpu --hidden_units 1024 512 256 --learning_rate 0.003 /opt/data/flowersConstructing vgg13 pretrained neural network:
Hidden units: [1024, 512, 256]
Establishing training, validation and testing loaders...
Training classification layer:
Epochs: 7
Learning Rate: 0.003
Dropout Prob: 0.2
GPU: TrueTraceback (most recent call last):
File "train.py", line 38, in <module>
checkpoint = trainmodel(args, model, loader_dict)
File "/home/rsbrownjr/work/test/aikit.py", line 369, in trainmodel
output = model.forward(images)
File "/home/rsbrownjr/anaconda3/envs/imgclassifier/lib/python3.6/site-packages/torch/nn/modules/container.py", line 92, in forward
input = module(input)
File "/home/rsbrownjr/anaconda3/envs/imgclassifier/lib/python3.6/site-packages/torch/nn/modules/module.py", line 547, in __call__
result = self.forward(*input, **kwargs)
File "/home/rsbrownjr/work/test/aikit.py", line 37, in forward
x = F.relu(linear(x))
File "/home/rsbrownjr/anaconda3/envs/imgclassifier/lib/python3.6/site-packages/torch/nn/modules/module.py", line 547, in __call__
result = self.forward(*input, **kwargs)
File "/home/rsbrownjr/anaconda3/envs/imgclassifier/lib/python3.6/site-packages/torch/nn/modules/linear.py", line 87, in forward
return F.linear(input, self.weight, self.bias)
File "/home/rsbrownjr/anaconda3/envs/imgclassifier/lib/python3.6/site-packages/torch/nn/functional.py", line 1371, in linear
output = input.matmul(weight.t())
RuntimeError: size mismatch, m1: [114688 x 7], m2: [25088 x 1024] at /pytorch/aten/src/THC/generic/THCTensorMathBlas.cu:273*
好吧,这可不太管用,不是吗?让我们看看生成的模型,并将其与预训练的 vgg13 架构进行比较,因为异常输出提到了乘法步骤中涉及的张量大小问题。也许在创建模型的过程中有些东西被破坏了?
*Sequential(
(0): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU(inplace=True)
(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(3): ReLU(inplace=True)
[…snip…]
(24): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(1): AdaptiveAvgPool2d(output_size=(7, 7))
(fc): Network(
(hidden_layers): ModuleList(
(0): Linear(in_features=25088, out_features=1024, bias=True)(1): Dropout(p=0.2, inplace=False)
(2): Linear(in_features=1024, out_features=512, bias=True)
(3): Linear(in_features=512, out_features=256, bias=True)
)
(output): Linear(in_features=256, out_features=34, bias=True)
)
)*
一切看起来井然有序。我的分类器只有一个名为“fc”的副本,dropout 层现在位于正确的位置,尽管我完成后会有更多的分类器。此时,我被难住了。我去了谷歌的搜索引擎。
搜索类似于“删除火炬视觉模型的最后一个模块”的字符串会提供大量线索。有人建议 Python 的“del”函数可以和我想要移除的图层的名称一起使用。这是行不通的,因为 PyTorch 的“Sequential”对象没有“del”方法。许多其他的线索包含了和我自己相似的问题,但是都没有答案。
还有其他线索包含一个共同主题的变化。这些线程依赖于使用“children()”方法,但是它们直接绕过了 add_module()方法。例如:
*model = models.resnet152(pretrained=True)
newmodel = torch.nn.Sequential(*(list(model.children())[:-1]))
print(newmodel)*
这看起来和我之前尝试的方法非常相似。但是,因为它没有直接使用 add_module 方法,所以我想在我的代码中尝试一下。再次执行程序后,我得到了完全相同的异常输出。这里也不走运。
此时,我开始考虑尺寸不匹配的潜在来源。由于我的新模型与预训练模型的架构几乎相同,我开始想知道这两个模型之间有什么不同。当我直接使用 torchvision vgg13 型号时,它工作正常。当我在试图删除分类模块时“复制”它时,它没有。
我又回头看了一遍回溯,发现提到了对“forward”的调用。这给了我一个想法。如果仅仅是将模块从一个架构复制到另一个架构,而不包括与模型相关联的 forward()方法的副本,那会怎么样呢?在偶然发现这个想法后,我回到我的代码,添加了下面一行:
*model.forward = tv_model.forward*
再次运行该程序产生了另一个异常,但这一次非常不同,它的内容帮助我认识到:
*Traceback (most recent call last):
File "train.py", line 38, in <module>
checkpoint = trainmodel(args, model, loader_dict)
File "/home/rsbrownjr/work/test/aikit.py", line 371, in trainmodel
output = model.forward(images)
File "/home/rsbrownjr/anaconda3/envs/imgclassifier/lib/python3.6/site-packages/torchvision/models/vgg.py", line 46, in forward
x = self.classifier(x)
File "/home/rsbrownjr/anaconda3/envs/imgclassifier/lib/python3.6/site-packages/torch/nn/modules/module.py", line 547, in __call__
result = self.forward(*input, **kwargs)
File "/home/rsbrownjr/anaconda3/envs/imgclassifier/lib/python3.6/site-packages/torch/nn/modules/container.py", line 92, in forward
input = module(input)
File "/home/rsbrownjr/anaconda3/envs/imgclassifier/lib/python3.6/site-packages/torch/nn/modules/module.py", line 547, in __call__
result = self.forward(*input, **kwargs)
File "/home/rsbrownjr/anaconda3/envs/imgclassifier/lib/python3.6/site-packages/torch/nn/modules/linear.py", line 87, in forward
return F.linear(input, self.weight, self.bias)
File "/home/rsbrownjr/anaconda3/envs/imgclassifier/lib/python3.6/site-packages/torch/nn/functional.py", line 1369, in linear
ret = torch.addmm(bias, input, weight.t())
RuntimeError: Expected object of backend CPU but got backend CUDA for argument #4 'mat1'*
请注意,这个异常不仅不同,而且它似乎是基于对一个名为“classifier”而不是“fc”的方法的调用!换句话说,将向前方法转移到我的新模型 中,解决了尺寸不匹配的问题 。但是 torchvision vgg13 模型内部的前向代码仍然在寻找一个叫做“分类器”而不是“fc”的方法。如果我想让这种方法工作,我就要编写我自己的 forward 方法,以便通过每个不同层的输入产生正确大小的输入,进入我的分类器 ,其中 是分类器的正确名称。不值得。
我也开始想知道与火炬视觉 vgg13 模型相关的参数。很可能我也要照顾这些。同样,不值得。
作为我尝试操作 torchvision 预训练模型的层的研究结果,我得出的结论是,没有任何方法可以让我将我的方法推广到我的训练代码中的不同网络。
我必须考虑代码内部层名的差异,或者干脆选择与最终分类模块同名的 torchvision 架构。我至少可以说,通过这次练习,我学到了很多东西,并享受了这段旅程。
我希望你发现这是一份有价值的资料。
数据中燃烧的多伦多,第一部分

火灾事件的分段泊松分析在实践中的应用
每年,多伦多消防局(TFS)被派往这个有 270 万居民的城市处理 9,000 到 10,000 起火灾。严重程度从草地或垃圾的小火到仓库或高层住宅的大火不等。本研究是关于 2011 年至 2016 年多伦多火灾数据分析的两部分系列的第一部分,我通过数据分割和汇总,分析了事故频率的特性,不考虑严重程度。
数据分析仅限于报告的实际火灾。这意味着 TFS 解决的额外需求,如医疗紧急情况、误报火警和从故障电梯中救援,被排除在目前的分析之外。此外,没有 TFS 参与处理的火灾也不在数据中。
多伦多市 85 个消防站的位置如下所示。

从数据中得出的第一个简单观察结果是,在所研究的六年中,一年中的火灾事件总数没有显示出有意义的趋势。就火灾事故而言,不断变化的法规、消防安全教育、经济等变化不够快。因此,所有分析都将这六年视为相同分布。
晚上和周末:点火时间
数据分析从数据探索开始,这意味着数据可视化。在下面的热图中,显示了作为一天中的小时和一周中的天的函数的火灾事件的数量。绿色越暗,相关时间段内的事件数量越多。

可视化显示,火灾事件在晚上发生的程度较高,在夜间和清晨发生的程度较低,并且周末与一周中的其他时间有细微但明显的不同。
事故数据进一步汇总,接下来显示了一天中给定时间、周末和周一至周五的火灾事故平均数。

从线形图中可以看到一些简单的观察结果:在周末午夜和凌晨 1 点之间,多伦多平均有 1.2 次火灾调度;平均事故数最低,略高于 0.3,发生在工作日的凌晨 4 点至 5 点。
从更大的角度来看折线图,下面是两个额外的一般性观察结果:
- 周末几乎全天都有更多的火灾发生(周末曲线垂直向上移动)。
- 与工作日相比,火灾事件的相对频率在周末偏移了大约一个小时(周末曲线水平向右偏移)。
从数据探索的第一阶段来看,在多伦多的城市环境中,很大一部分火灾是由随时间变化的某些人类活动引起的,而不是随机的雷击或均匀分布的电气故障。这类活动在晚上也更常见。周末晚些时候的转移表明,这些活动,或者至少其中相当大的一部分,也是以这种方式转移的。
住宅与垃圾,与季节的互动
季节之间的变化呢?下图显示了火灾事故的频率如何取决于一天中的小时数以及一年中的季节和月份。

常见的晚间活动模式出现了。然而,与寒冷和黑暗的季节相比,温暖和明亮季节的曲线向上移动,其峰值向右移动。换句话说,更温暖和更明亮意味着多伦多更多和更晚的火灾事件。
TFS 大体上根据着火的是什么来对火灾进行分类:高层住宅、草地或垃圾、高速公路上的车辆等。出现次数最多的类别是“草地/垃圾”和所有类型住宅火灾的组合。通过进一步分割这一分类变量的数据,然后绘制季节和一天中的小时变化,得到以下曲线。

住宅火灾(左图)随一天中的不同时间而变化,峰值在下午 6-7 点左右,但没有随季节而变化(可观察到的差异不足以从统计噪声中区分出来)。另一方面,涉及草地或垃圾的火灾事件(右图)高度依赖于季节。多伦多寒冷的冬天提高了户外火灾的门槛,这是可以理解的。但是,是火的燃料的物理性质,还是引起火灾的人们的户外活动被改变得最多呢?
事故频率超出平均值
在我继续钻研数据之前,我会看看平均值以外的情况。到目前为止,所有数据可视化都与不同时间段的平均值以及最近两个时间段的火灾类型有关。然而,每个细分市场都包含多个数据点,在数据分析中描述这些分组中的分布通常是有启发性的,甚至是必要的。
两个说明性部分的事故数量直方图如下所示:第一个是冬季星期一到星期五上午 9 点到 10 点;第二个是夏季周末下午 6 点到 7 点。


考虑两个直方图中的第一个。它将数据的事实可视化,例如
- 在冬季所有工作日的近一半时间里(约 49%),在第 9 小时(上午 9 点到 10 点),消防调度为零
- 每 10 天中有一天多一点(~12%)不是周末,在冬天的第 9 小时有两次火灾调度。
第一个直方图的平均事件频率为 0.7,反映了数据在分段中的分布向低值移动。
与平均值为 2.3 的第二个直方图形成对比。大部分数据向稍高的值移动,例如,具有 1、2 或 3 个事件的天数占该特定时间段中所有天数的三分之二。还有一个趋势是更高的值,例如 6 次和 7 次事故。
使用泊松分析直方图的意义
两个直方图都类似于泊松分布的概率密度。为什么这个应该是预期的形式,也有理论上的原因。
泊松分布有一个参数,通常表示为λ,称为强度参数。

我不会深入这个等式的细节,它的特点在别处有很好的描述。与火灾事件数据相关的定性解释最好理解为:在给定时间段内发生事件数量 k 的概率由以下等式给出,其中强度参数λ越大,事件的平均频率越高,这将相应的直方图向更高的值扩展,尽管总是存在一个值 k ,超过该值概率降低。
数据分析表明,火灾事件过程的强度参数是随时间变化的。换句话说,λ是时间的函数。
这相当于将火灾事故建模为非均匀泊松过程。λ与数据的拟合可以通过最大似然估计正式完成。然而,有一个方便且相当好的近似值可用:给定时间段的平均事件数等于λ。对于精确的泊松分布,平均值实际上等于λ。
换句话说,上述所有折线图都可以重新解释为作为时间段函数的泊松过程强度参数λ的曲线图。
泊松过程对数据的描述有多好?
事实证明相当不错。最差的拟合是下图所示的直方图。

麻烦的部分是几天非常高的值。直方图的其余部分很好地符合λ=3.1 的泊松分布。然而,这个数值应该使 10、12 和 13 起事故非常罕见。这表明,至少在这个时间段,还存在一个较小但重要的附加过程。离群值可能具有启发性,并指出下一步要挖掘的地方。
异质空间片段
大多数火灾事件的数据条目包括最近的街道交叉口的记录。将此与独立公开数据集中的纬度和经度地理坐标进行交叉引用,可以很好地解析多伦多事故发生地的图片。下图显示了数据集中的大多数火灾事件,其中蓝点表示住宅建筑中的火灾,琥珀色表示所有其他类型的火灾(未出现的事件将在注释中讨论)。

从这个高层次的角度来看,蓝色和琥珀色圆点之间的空间隔离讲述了一个简单的故事:多伦多的住宅区并不是均匀分散的,有些空间段没有住宅或高层建筑。不是惊天动地的实现。
原则上可以沿着不同的时间段重复先前的分析,这些时间段进一步划分为空间段。例如,是否多伦多的一些街区对时间有着明显的依赖性,反映了潜在的人口、经济或建筑特征?
然而,火灾事件的近 60,000 个数据点可以告诉我们,一旦它们被分割成精细的片段,如一天中的小时、一年中的季节、一周中的日子、和街区,数据就变得过于稀释了。没有一个指导性的假设,数据探索太容易迷失在对统计噪音的创造性解释中。交叉引用的额外数据以及量化模型的创建,可以帮助更全面地了解城市的细节,这些细节使得整个城市的火灾事件各不相同。解析时空模型并不遥远。
数据中引人注目的是:2013 年 12 月的冰风暴
当相对于月份和年份进行动态化时,事件数据的地图可视化使得一个主要偏差在视觉上非常清楚。下面的动画形象地展示了从 2013 年底到 2014 年初的几个月里多伦多草地/垃圾火灾事件的空间分布。

与春季和秋季相比,2013 年 12 月冬季的草地和垃圾火灾平稳减少。放大到邻近的北约克中心,加上日期作为标签,很明显在 12 月 21 日和 12 月 26 日之间,发生了一些不寻常的事情。

事实上,这是一场严重的暴风雪袭击多伦多的日子。电线在冰柱的重压下断裂,选择在室内生火取暖的人们也为火灾数量的增加尽了自己的一份力量。
2013 年 12 月的冰风暴很好地提醒了我们,拟合的非齐次泊松过程对于火灾事件频率的定量建模是有用的,也是最准确的,但λ的参数化可能会出现重大错误。当基础特征的变化超过临界阈值时,在这种情况下,(至少)电力基础设施抵御冰风暴的能力——多伦多冬季火灾事件的典型领域——不再具有代表性。跨越这种不连续性,以及典型领域内的内插和外插完全是在错误的现实领域中。困难的问题,有些人认为是不可能的问题,是在它们被跨越之前,知道这些临界阈值是什么。
细分市场、特征-解释和交叉引用
那么火灾发生的频率仅仅是一天中的时间、一周中的日子和季节的函数吗?这个紧凑的模型很好地再现了观测结果,所以这个简单的概念是有道理的。也许毕竟大多数火灾是由炉灶失误和舒适的晚间户外烧烤引起的,在这种情况下,解释主导关系的城市特征可能并不困难,可以通过与其他数据集的交叉引用来建立和验证预测模型。
然而,火灾事件的后果并不一致。罕见但巨大的火灾隐藏在微小的草地和垃圾事件的海洋中。许多小事件的变化和相关性的模型当然有用,但它通常会忽略重要的极端情况。这是第二部分的主题。
掌声是货币。如果你觉得这值得一读,请按下按钮。
笔记
- TFS 事件原始数据来自多伦多市公开数据网页。
- 来自多伦多市开放数据网页的街道交叉口地理数据。
- 并非所有的火灾事故都与十字路口有关;缺失数据(尤其是路径)和不一致的标点符号也妨碍了某些事件的地理坐标匹配。85%的火灾事件与地理坐标相匹配。
- 可视化用 Tableau 完成,大多数定量分析用 Python 库 Pandas 和 Numpy 完成,地理空间数据解析用 Python 库 PyShp 完成。
数据中燃烧的多伦多,第 2 部分

模拟极端事件及其巨大的随机性
这是关于 2011 年至 2016 年多伦多火灾数据分析的两部分系列的第二部分,我分析了多伦多消防局(TFS)处理的火灾的严重程度。在系列的第一部分中,分析了火灾事件集合的一般属性,特别是当发生时的,但很少或没有考虑事件的火灾性质。
意外火灾是极端事件比典型事件更重要的一个很好的例子。一个消防部门能够很好地处理 90%的火灾,却不能处理前 10%的严重火灾,这是不合适的。像地震、洪水、流行病、保险索赔和某些财务规划一样,极端事件,尽管罕见,在任何有能力的设计中都必须考虑。这些非常重要,但难以捉摸的事件伴随着一系列命名的概念出现:极端事件,肥尾,柏拉图世界,黑天鹅。为了使概念尽可能简单和直观,我称之为极端事件。
极端事件对纯数据驱动的分析方法提出了根本性的挑战。根据定义,这些是罕见的事件,因此在任何有限的数据收集中,它们的抽样都很差。在机器学习中,偏斜或不平衡类别的问题就是这种情况的一种表现。虽然有办法避开处理这类数据的陷阱,但如果没有系统力学理论来帮助填补空白,数据能够揭示的关于采样不良地区的信息是有根本限制的。
仍然有一些有用的方法来量化极端程度,并获取所研究系统的知识。这是一个积极研究的课题,下面的方法介绍了一些可以做的事情。
如何量化严重性
为了继续,我需要量化严重性。决定严重程度的是火灾覆盖的面积,还是火灾持续的时间,还是财产价值的损失,还是危在旦夕的人命数量?答案是:对所有人都是。
实际上,TFS 在部署其有限资源时必须做出这一决定。这是我将用来衡量严重程度的一个代理指标:在火灾事故过程中派出的单位数量。机构和负责处理火灾的人员认为火灾更加严重时,应派出更多的单位(消防车、危险品车、供气车、指挥车等)。领域专家将严重性的多目标定义简化为标量属性。
这几乎不是一个完美的代理指标,这是我在本文结尾时再次提到的问题。但我认为这足以量化火灾严重程度的显著特征。称之为起点。
观测频率对概率密度
在下面的散点图中,显示了与一定数量的部署单位相关的事故数量;注意纵轴上的对数刻度。

正如所预料的那样,大部分火灾都是轻微的,只有一小部分是非常严重的。
仔细观察后发现,在整个范围内,事故数量并不随着响应单位数量的增加而均匀减少。事实上,最常见的两个值是 1 和 6 个响应单位。这种变化可以用 TFS 的运作规则来解释:即使最小的住宅火灾也要用六个单元来处理。
这是相对于火灾之间的更精细细节的分辨率的严重性度量的限制。因为这项工作的目标是描述极端事件,但是,这些更好的细节不应该成为众所周知的阻碍森林被看到的树。
我通过宁滨将响应单元的数量划分为[1,6],[7,12],…换句话说,具有 1 到 6 个响应单元的火灾之间的差异被排除在考虑范围之外——它们现在被视为同等严重。散点图转换如下:

第一个箱是导致一到六个响应单元的火灾事件的总和;第二个箱用于导致 7 到 12 个响应单元的事件;诸如此类。
对数对数和帕累托分布
注意,在上面的图中,横轴也是对数的。因此,这是一个双对数图。除了两三个极端值,这些点排列得相当好。用最小二乘方线拟合这些点(现在不包括仓 33 和 76 处的点)得出:

在这个等式中, S 表示 bin 号,它是粗粒度的严重性等级,而 N_{annual} 表示严重性为 S 的事件的年度数量。等式被重新组织:

为了使这个等式定性,考虑如果严重性加倍会发生什么,即S’= 2S。自 2⁴=16 以来,其含义是严重性增加一倍意味着发生次数减少 16 倍。换句话说,严重程度加倍的火灾事故减少了 16 倍。此外,这种说法是标度不变的,也就是说,无论 S 的值是多少,将其加倍,事件发生的频率就会降低 16 倍。
这种形式的频率分布被称为 帕累托分布 。这是一类具有有趣性质的分布,并且被推崇为理解现代世界(从投资到爱情)的真正方法。我将远离一般的说法,就这项研究而言,简单地注意到,作为第一近似值,多伦多火灾严重程度的概率是形状参数等于 4 的帕累托分布。
给随机性的极端性加上一个数字
帕累托分布的一个特征是,在某个阈值γ以上,该分布具有无限的矩。例如,求上述分布的三阶矩的积分不是有限的;另一方面,一阶和二阶矩是。法裔美国数学家 Mandelbrot 用γ值描述了系统的随机状态。阈值越低,极端随机事件相对于典型随机事件越极端。Mandelbrot 将阈值在 1 和 2 之间的分布的随机性定义为无序随机性。
矩变得无限大的阈值可以用来表征极端事件相对于典型事件有多极端。该属性不需要帕累托分布。基于关于基础分布的更宽松的假设的阈值γ的估计是有帮助的。
一种方法基于基于采样数据的以下比率的特性×T21。

可以证明,在无穷大 n 的极限下,这个比值趋于零当且仅当 p-矩是有限的。因此,反过来,使这个比值而不是趋于零的 p 的值就是临界阈值。
我使用 2011 年至 2016 年 TFS 数据集的响应单位数量(这次没有粗粒度指标),并计算更多数据点级数的比率。

从有限样本中估计渐近极限是有风险的——毕竟我们永远不会到达终点。然而,该图强烈地表明一阶和二阶矩都是有限的。在范围 p=2.5 到 p=3.5 的某处,比率似乎稳定在大于零的值。
上述方法的一个有利特征是,它几乎不受低火灾事故严重性分布的确切性质的影响。在上一节的直线拟合中, S 的低值点很重要。由于本研究的目标是描述极端事件的特征,而不是火灾事件严重程度的整个范围,如上所述,低严重程度的平稳递减分布的偏差最好不会影响分析方法。
超出阈值以隔离极端情况
进一步描述极端事件分布特征的直观想法是研究超过。这是严重性超过某个高阈值的事件的分布。
围绕这种方法产生了大量的理论。在水文学中,这被称为超过阈值的 峰值接近,并且可以被可视化为河流流量超过阈值多远,忽略未超过阈值的次数的确切值。特别地,可以证明关于这个阈值的渐近关系。

上面的时间序列线图显示了火灾事件时间序列的一个片段,其中显示了 20 个响应单位的阈值。超过严重性阈值的值的统计特征可以与极端事件分布的特征相关联。
和以前一样,每当估计极限数量时,这次是阈值,用有限的样本,艺术和科学都在发挥作用。在不涉及细节的情况下,用这种方法发现尾部分布的形状在 2.5 到 4.5 的范围内,主要取决于是否考虑了最极端的严重情况。
用来表征和量化火灾事件分布的极端情况的少数方法指向从高 2 到低 4 范围内的指数(形状参数)。如果我们采用 3.5 作为折衷,则扩大到极端事件的定性含义是:严重程度加倍的火灾事件的发生频率约低 11 倍,高于某个中等严重程度阈值。
衡量什么,什么重要?
在上面的部分分析中,我忽略了严重性等级中两个最极端的事件。他们似乎不太合群。我是否犯了强迫现实符合我的美丽方程式的罪行?也许吧。很可能在很高水平上的极端值被低估了,并且对于尾部分布应该降低形状参数。
这两起事件分别是仓库着火,充足的燃料使大火持续了一天多,以及床垫厂着火,由于燃料充足,这也持续了很长时间。大量的响应单位部分反映了这些火灾持续时间的延长,因为多个单位必须来来去去。我采用的严重性代理指标可能会将需要很长时间才能终止的火灾评定为非常严重。
在现实世界数据的分析中,对感兴趣的问题或预测真正重要的属性可能是模糊的,因此很难实际量化。火灾严重程度不会是第一位的。辨别公式和工程的伟大指标,衡量什么是真正重要的可以使所有的差异。这种分析先于数据库、算法或图形处理器的任何创造性使用。
综上所述,考虑到可供学习的极端数据的自然短缺,这些技术已经成为多伦多火灾事件极端严重性的特征。为了创造一种预测方法,甚至可能具有空间和时间分辨率,还需要进一步的改进。其中之一是严重性度量,它有其局限性,因为它涉及到有意义的现实世界方面。但我们必须从某个地方开始,找出需要解决的问题,极端事件无疑是值得解决的。
掌声就是货币。如果你觉得这值得一读,请按下按钮。
笔记
- TFS 事件原始数据来自多伦多市开放数据网页。
- Embrechts 等人 写的这本书是对极端事件建模的有益介绍。
- 可视化是用 Tableau 完成的,大多数定量分析是用 Python 库 Pandas 和 Numpy 完成的。
触摸驱动的推荐引擎
推荐系统
从流行推荐发展到个性化推荐

A recommendation schedule that follows the touch points of the consumer journey. Image: Author
在数字时代,互联网将全球数十亿人与无数产品联系在一起,为消费者提供了前所未有的更多选择。2016 年,仅在亚马逊市场,就有 185,000 名卖家出售了超过 3.53 亿件产品。虽然精明的选择者可能会找到他们想要的东西,但许多消费者可能会被决策过程弄得不知所措。
贾芳·塞西·艾扬格和马克·莱珀在 2001 年发表的《果酱实验》研究了选择如何影响消费者行为。24 种果酱吸引的顾客(60%)比 6 种果酱(40%)多。但是只有 3%的顾客从大的一套中购买,而 30%的顾客从小的一套中购买。当选择更少时,购物者有信心选择最好的果酱。
推荐系统帮助消费者搜索和发现新产品和服务,有选择地减少呈现给他们的选项集。⁴展示了他们的商业价值,网飞将其每年 10 亿美元的成本节约归功于其人工智能推荐系统。⁵这些系统通过涉及不同个性化水平的几种方法来过滤选项。
个性化推荐系统受到“冷启动”问题的困扰,在这种情况下,它们需要一些关于客户偏好的初始数据来进行有针对性的推荐。⁶为了解决这个问题,人口数据挖掘方法可以预先填充关于新消费者的假设,而集成技术可以聚合多个推荐系统。
但也许我们可以利用简单的非个性化推荐系统来跟踪消费者旅程中的触摸 points⁷。⁸:我们可以通过向新客户推荐受欢迎的产品,然后逐步转向更个性化的推荐,来解决冷启动问题。因此,让我们尝试为电子商务平台实现一个触摸驱动的推荐引擎。
消费者之旅
- 意识
- 熟悉
- 考虑
- 购买
- 忠诚
Farfetch 平台和市场
Farfetch 是一个在线奢侈品零售平台和市场,将 190 多个国家的消费者与 3000 多个品牌联系起来。由于每个品牌销售各种各样的产品,Farfetch 可以被视为一个漫长的 tail⁹市场。该平台的价值是由众多吸引不同消费者的差异化产品驱动的,而不是大众市场的热门产品。
像许多电子商务平台一样,Farfetch 发布客户对单个产品的购后评论⁰,以向潜在客户提供社交证明。我们可以使用这些数据(审核的、购买的、商品网址、评分)来训练我们的推荐引擎。在最近的 100,000 条客户评论中,我们会找到 9,667 名客户对 13,518 种产品的 16,105 条库存评级。
由于我们已经有了每件商品的商品网址,我们可以收集到大量的商品详细信息⁰ ( 原价、折扣、售价、设计师、类别、性别、款式、颜色、制造等。)关于 13,518 款产品中的每一款。未来,我们甚至可以通过收集用于分类的图像和产品描述来执行自然语言处理分析,从而丰富我们的数据集。
推荐调度
推荐系统通常可以分为非个性化(基于数据集的描述性统计提供推荐)基于内容的(生成与客户积极评价的产品客观相似的推荐)和协作式(利用群体的智慧基于相似客户的偏好过滤选项)。
想象一下,第一次走进一家餐厅,让服务员推荐一道菜。我们可以简单地开始,“最受欢迎的菜是什么?“下一次,可能是,”“你能给我指出类似(或不同)的东西吗?“经过几次拜访,当我们的服务员对我们足够了解,可以根据我们的口味进行个性化服务时,我们可能会问,”“像我这样的顾客通常点什么?
在创建我们的触摸驱动推荐引擎时,我们可以遵循这个直观的例子,将多个系统集成到一个自适应引擎中,自然变得更加个性化。通过这样做,我们可以避免直接跳到协作建议中会遇到的冷启动问题。我们的推荐程序可能如下所示:
- 评分最高的单个产品
- “最佳之一”收视率最高的子类别
- “最受欢迎的九个”子类别
- 基于内容的皮尔逊相关产品相似度
- 基于奇异值分解的用户间协同过滤
为了在最小可行的产品中实现我们以客户为中心的推荐之旅,我们应该专注于有限的一组要实现的功能。我们需要记录向每位客户推荐的历史记录,检查我们推荐的产品是否有库存,确保推荐不会重复,并在每次客户接触后更新我们的数据库:
触摸驱动的推荐引擎
记录每个客户的接触点及其对适应性建议的响应的系统。
库存缺货的实时检查点
检查每个推荐产品是否有货,查询产品网页或数据库的状态。
非重复滚动建议
根据推荐历史检查推荐给客户的每个产品是否新颖。
与 NoSQL 数据库同步
在发布下一条建议之前,数据库反馈客户对每条建议的回应。
预热客户的建议
当新客户来到市场时,我们可以立即提供非个性化的推荐,不需要该客户的任何信息。基于评分最高的单个产品的推荐只需查询我们的数据库,即可找到拥有最多客户评价的产品。然后,我们可以根据受欢迎程度提供三个建议。

The three most-rated individual products. Image: Author
通过检查最受欢迎商品的产品评级总数,我们可以看到市场中长尾的完整范围。在我们数据库中的 16,105 个产品评级中,最受欢迎的产品只获得了 15 个评论,占所有评论的不到 0.1%。我们现在可以通过跟踪我们的用户评分历史来预热我们的客户数据。

Recommender engine history of the three most-rated individual products. Image: Author
由于很少一部分客户可能会购买任何给定的产品,我们可以通过子类别提供建议,以获得更广泛的吸引力。通过对 1184 个设计师和 29 个类别进行分组,我们可以找到“最佳一个”评分最高的子类别。下面给大家推荐三款最受欢迎的阿迪达斯鞋,这三款鞋共占 375 个评分或所有购后评论的 2.3%。

The “Best One” most-rated subcategory. Image: Author
当我们测试我们的推荐引擎时,我们跟踪每个推荐的模拟用户评分。虽然这些评级对于生成非个性化推荐来说并不是必需的,但是当我们过渡到基于内容的和协作推荐系统时,它们将会被利用。让我们注意一下,我们的模拟器给第二双阿迪达斯鞋打了五颗星。

Recommender engine history of the “Best One” most-rated subcategory. Image: Author
受 Instagram 的最佳九个帖子⁴的启发,我们可以通过对“最佳九个”最受欢迎的子类别中的每一个进行抽样,来探索客户对广泛流行产品的兴趣。最顶级的设计师是阿迪达斯、杜嘉班纳&加巴纳和古驰,而最顶级的类别是鞋子、服装和包包包。请注意每个设计师如何定位自己,领导不同的类别,以红色突出显示。

The “Best Nine” most-rated subcategories. Image: Author
我们推荐了、“最受欢迎的九个”子类别中的一个,但与我们所有的推荐者一样,客户一次只能看到一个产品并对其进行评级。我们的测试模拟器简单地多次调用“Best Nine”推荐器来演示它的行为。我们没有看到阿迪达斯鞋,因为我们以前展示过它们,我们的推荐器平衡了子类别视图。

Recommender engine history of the “Best Nine” most-rated subcategories. Image: Author
可比产品推荐
现在,我们已经有了客户对各种产品的兴趣历史,让我们展示一下与评分高的产品相似的产品。回想一下,我们的客户给阿迪达斯鞋打了五颗星。基于内容的商品相似度通过皮尔逊相关度可以通过比较原价、折扣、性别、国产、品类推荐相似商品。

Content-based product similarity via Pearson correlation. Image: Author
由于我们在一个拥有 13,518 种差异化产品的长尾市场中运营,基于内容的推荐器可以有效地找到与我们感兴趣的特征非常匹配的商品。请注意建议 15 和 16 与建议 4 的匹配程度,我们的客户将其评为五星。同样,推荐 17 为阿迪达斯包匹配推荐 13 。

Recommender engine history of content-based product similarity via Pearson correlation. Image: Author
我们的基于内容的推荐器通过将每个产品的特征与所有其他产品的特征相关联来运行。连续特征如原价和折扣可以保持不变,以强调消费者价格敏感度,而分类变量如性别、制造和类别可以通过虚拟编码转换成数值。
Calculating content-based product similarity via Pearson correlation. Source: Author¹⁵
来自群众智慧的建议
最后,我们可以使用⁶的惊喜库无限期地提供用户对用户的协作推荐,该库使用奇异值分解,这是一种由西蒙·芬克在 2006 年网飞奖期间推广的矩阵分解方法。⁷该方法创建一个所有客户产品组合的矩阵,并使用现有的评级来预测客户对未评级配对的反应。

Recommender engine history of user-to-user collaborative filtering via Singular Value Decomposition. Image: Author
我们的数据库中有 13,518 种产品和 9,667 个客户,因此在我们的客户-产品效用矩阵中有 130,678,506 种可能的组合!由于我们只有 16,105 条客户评论(用蓝色突出显示),我们的矩阵是 99.988%稀疏的(用空白表示)。这给使用协作过滤带来了一些挑战,但是在后面的讨论中会有更多关于这个主题的内容。

Matrix sparsity of the Customer-Product Utility Matrix in Singular Value Decomposition. Image: Author
为该分析编写的源代码可以在⁸的 GitHub 上获得,其中包括一个触摸驱动推荐引擎的实现和本文中给出的示例。我们已经看到了如何将多个推荐系统集成到一个全面的引擎中,以跟踪消费者旅程的接触点,同时解决冷启动问题。
参考
- “亚马逊有多少产品?,“零售接触点网络,https://retailtouchpoints . com/resources/how-many-products-does-Amazon-carry,2019。
- A.图根德,“太多的选择:一个可以瘫痪的问题”,《纽约时报》,2010 年 2 月 26 日。
- 南 S. Iyengar 和 M. Lepper,“当选择使人失去动力时:一个人会对一件好事期望过高吗?,“《人格与社会心理学杂志》,第 79 卷,第 6 期,第 995–1006 页,2001 年。
- C.安德伍德,“商业中推荐系统的用例——当前应用和方法”,Emerj 人工智能研究,2020 年 3 月 4 日更新。
- C.A. Gomez-Uribe 和 N. Hunt,“网飞推荐系统:算法、商业价值和创新”, ACM 管理信息系统汇刊,第 6 卷,第 4 期,2015 年。
- B.Lika,K. Kolomvatsos 和 S. Hadjiefthymiades,“面对推荐系统中的冷启动问题”,专家系统与应用,第 41 卷,第 4 期,第 2065–2073 页,2014 年。
- “在所有客户接触点,公司都面临着新的关联要求,”Salesforce,https://www.salesforce.com/research/customer-touch-points,2019 年。
- D.Court,D. Elzinga,S. Mulder 和 O. J. Vetvik,“消费者决策之旅”,麦肯锡季刊,2009 年 6 月 1 日。
- C.安德森,“长尾理论”,连线,2004 年 10 月 1 日。
- 法菲奇,https://www.farfetch.com,2019。
- 米(meter 的缩写))申克,“如何使用恰尔迪尼的 6 项说服原则来促进转化”, CLX ,2019 年 6 月 29 日。
- B.DeWees 和 J. A. Minson,“使用群体智慧的正确方法”,《哈佛商业评论》,2018 年 12 月 20 日。
- 《方法论》,精益创业,http://theleanstartup.com/principles,2019。
- J.兰斯,“2020 年 Instagram 前 9 名:如何获得你最好的帖子”,魅力,2020 年 12 月 2 日更新。
- A.C. Dick,《为推荐系统创建基于内容的产品相似度矩阵》,载于 GitHub,https://gist . GitHub . com/AC Dick/FB 76 dcde 98 CD 622 f 7756 e 9 af 9d 54d 464,2019。
- 名词(noun 的缩写)拥抱,惊喜:用于推荐系统的 Python scikit。,http://surpriselib.com,2019。
- 南芬克,“网飞更新:在家里试试这个”,《控制论的进化:期刊,2006 年 12 月 11 日。
- A.C. Dick,“触摸驱动的推荐引擎”,载于 GitHub,https://github.com/acdick/touch_driven_recommender_engines,2019。
用深度学习润色宝宝照片
像数字时代任何自豪的新父母一样,我给我的宝宝拍了许多照片。用手指轻敲几下,我就把照片上传到网上相册,在那里,照片会受到家人和朋友崇拜的观众的 oohs 和 aahs 。
尽管技术在通讯速度和文件存储容量方面取得了令人印象深刻的进步,但在更复杂的生物学领域却没有取得同样大的进步。婴儿的发育仍然和他们几代人一样缓慢。学习精细的运动技能、基本的语言能力和独立行走仍然需要多年的努力。婴儿面临着漫长而曲折的发展道路,这一事实在视觉上没有比给他们喂固体食物更明显的了。他们的饭菜不知怎么弄得到处都是。虽然这是喂养婴儿的现实,但这种混乱并不一定会玷污互联网上传播的婴儿照片。
NVIDIA 有一个简洁的交互演示,它使用深度学习模型来重建图像中缺失或被掩盖的部分,这被称为“图像修复”在他们的论文中,研究人员解释了他们如何通过使用部分卷积来改进现有模型,这些卷积以图像的原始像素值为条件,并且对替换到缺失区域的占位符值不可知。它们在自动更新步骤中逐渐缩小图像的蒙版部分。这使得输出图像摆脱了困扰其他方法的视觉伪像。
我在我宝宝的照片上运行了 NVIDIA 的演示。以下是原文:

我的意图是去除下巴下褐色的食物污渍。玩了几个不同的蒙版区域后,我选定了这些区域…

…提供最佳重建效果。

在输出图像中,污点被移除。一个精于 Photoshop 的艺术家可以做得更好,因为一些棕色仍然存在于修饰过的区域,而绵羊图案是模糊的。但是考虑到重建是免费的并且在几秒钟内完成,我对最终的结果很满意。
通过自动分析空中影像加速灾难响应
对 SpaceNet 挑战的评论:离底建筑物足迹提取
SpaceNet 的使命是加速地理空间机器学习,并得到 SpaceNet 成员组织的支持。了解更多请访问https://spacenet . ai。

A series of images taken by DigitalGlobe’s WorldView-2 satellite, from the SpaceNet Multi-View Overhead Imagery (MVOI) dataset described below, illustrating how look angle changes image appearance.
在本帖中,我们将描述与从航拍影像自动制图相关的挑战。关键要点:尽管算法非常擅长从直接从头顶拍摄的“理想”图像绘制地图,但紧急收集环境中存在的图像类型——如自然灾害后——对最先进的计算机视觉算法来说是一个目前尚未解决的问题。
当前的事态
随着计算机视觉方法的改进和高空图像变得更加容易获得,科学家们正在探索将这些领域结合起来用于许多应用的方法:其中有监测去造林和跟踪难民情况下的人口动态。自动图像分析有助于快速救灾:灾后新地图往往必不可少,因为协调救灾工作所需的基础设施(如道路)可能会被破坏。目前,这是由政府、私营部门的团队或志愿组织(如人道主义开放街道地图(HOT-OSM)团队)人工完成的,该团队应美国联邦紧急事务管理局(FEMA)的要求,创建了飓风 Maria 后波多黎各的底图(道路和建筑物)。但是手动标注既费时又费力:即使有 5300 名制图人员参与该项目,波多黎各的第一张底图直到飓风袭击一个多月后才交付,该项目又过了一个月才正式结束。这绝不是对热 OSM 团队或他们奇妙的标签社区的批评——他们有 950,000 座建筑和 30,000 公里的道路要贴标签!即使是初步的自动标注步骤,然后手动纠正,也可以缩短地图交付时间。
随着深度学习模型从在 TensorFlow 存在之前实施的 AlexNet 的不成熟发展到今天的高级模型架构,包括挤压和激励网络、双路径网络,以及在像 Keras 这样易于使用的软件包中实施的高级模型训练方法,基于计算机视觉的高空图像地图创建已经取得了很大进展。除了这些发展,自动制图挑战的性能也在稳步提高,正如 SpaceNet 竞赛系列所证明的那样:从 2016 年的第一次挑战到 2018 年底的最近一次挑战(在此讨论),直接从头顶拍摄的图像的建筑物提取分数提高了近三倍。
为什么自然灾害后不自动地图?
在灾害应对场景中,自动分析空中影像仍然存在一个主要障碍:视角。

Schematic representation of look angle.
卫星的位置——也就是卫星图像可以显示的区域——受到卫星轨道的限制。在紧急收集情况下,没有时间让卫星直接从头顶飞过,这意味着要以一个角度拍摄图像——有时是一个很大的角度。根据 DigitalGlobe 的 Discover 平台的数据,飓风玛丽亚过后两天,在波多黎各圣胡安上空拍摄的第一张无云的公开照片是在 52 度的天底角。作为比较,这个故事顶部的动画中最偏离角度的图像是在 54 度拍摄的。
所谓的“偏离最低点”影像的许多特征对自动化分析提出了挑战:
位移和变形
在离底影像中,高物体(树、建筑物等)的顶部。)被从它们的地面足迹中移走。这使得细分具有挑战性!

Buildings are perfectly outlined in the nadir looks, but the footprint is offset in distorted off-nadir looks. Competitors’ solutions needed to account for this. Imagery courtesy of DigitalGlobe.
阴影和各种照明
在高射影像中,根据阴影的不同,一个区域的视图在外观上可能会有很大的不同。参见下面的例子,当太阳光反射回卫星时,建筑物很明显,但当图像从建筑物的阴影侧收集时,建筑物就不那么明显了。

Two looks at the same buildings at nearly the same look angle, but from different sides of the city. It’s visually much harder to see buildings in the South-facing imagery due to shadows. Imagery courtesy of DigitalGlobe.
物体的遮挡
如果你在图像中看不到一个物体,你就很难识别它!在非最低点看起来,高物体阻挡了其他结构:

Occlusion can make it impossible to see some objects in off-nadir imagery. A building whose roof is visible (though cloaked in shadow) in nadir imagery (left, red arrow) is obscured by the skyscraper in off-nadir imagery (right).
解决
在更大角度拍摄的图像覆盖了更多的地面,但仍然包含相同数量的像素,降低了地面分辨率。在下文描述的 SpaceNet 多视图高架图像(MVOI)数据集中,“在天底”拍摄的图像分辨率为 0.51 米/像素,而远离天底的分辨率降至 1.67 米/像素。这在这个故事顶部的动画中显而易见——随着图像越来越偏离最低点,分辨率越来越差。为了找出这些因素对模型性能的影响程度,我们需要一个标记良好的数据集来控制除视角之外的所有变量。
SpaceNet 多视图高架图像(MVOI)数据集
为了探索视角在多大程度上影响模型性能,我们发布了 SpaceNet MVOI 数据集,这是开源的,可以在 AWS S3 免费获得——您所需要的只是一个 AWS 帐户!下载说明和其他元数据可从这里获得。
意象
该数据集来自 DigitalGlobe WorldView-2 卫星在美国佐治亚州亚特兰大上空单次通过时收集的一系列独特数据。这颗卫星拍摄了 27 张图像,范围从偏离天底 7 度到 54 度,包括朝北和朝南的两种外观:

Location where each collect was taken from to generate the SpaceNet 4 Off-Nadir dataset. This not-to-scale representation is simplified: in reality, the satellite did not pass directly over Atlanta, but nearby. See this paper and the dataset metadata for additional details.
这些收集的每一个都覆盖了亚特兰大及其周围同样 665 平方公里的土地。因为它们都是在 5 分钟之内获得的,所以对照明、土地使用和其他时间因素的改变被最小化。真的,不同系列之间唯一不同的是视角。

Sample images from the SpaceNet Multi-View Overhead Imagery (MVOI) dataset (described below). The look angle is shown on the left, along with a bin ID: Nadir, ≤25 degrees off-nadir; Off-nadir, >25 and <40 degrees; very off-nadir, ≥40 degrees off-nadir. Negative numbers correspond to South-facing looks, positive numbers to North-facing looks. Imagery courtesy of DigitalGlobe.
根据观察方向和角度的不同,完全相同的地理看起来非常不同。理解这对算法性能的影响不仅在遥感分析中有应用,而且在一般的计算机视觉领域中也有应用。
标签
SpaceNet 的合作伙伴 Radiant Solutions 开展了一项严格的标注活动,在数据集中的 126,747 座建筑物周围绘制多边形足迹。我们使用覆盖区而不是边界框,因为边界框通常不足以进行基础制图,例如,如果建筑物覆盖区与道路重叠,重要的是要知道这实际上是真实的,而不是标注的伪像。我们进行了仔细的质量控制,以确保所有的建筑物都被标记,因为高质量的标签对于训练计算机视觉模型(即)来说至关重要,如果数据集中只有一半的建筑物被标记为这样,那么算法如何才能学会找到它们呢?)建筑物覆盖区的大小从 20 平方米到 2,000 多平方米不等,并且密度在数据集中的不同地理区域有很大差异:

A histogram showing the number of buildings in each unique geography in the dataset. X axis: the number of buildings apparent in the image, which ranges from 0 (mostly forested areas) to 297 (a very dense suburb). Y axis is the number of images from unique geographies that have that number of buildings — multiply that number by 27 for the total number of images.
这种可变性本身就提出了一个挑战,因为该算法无法学习到每张图像中应该存在大致相同数量的对象。这对于对象检测(包围盒预测)算法来说尤其困难,因为这种算法通常需要估计每幅图像的对象数量作为超参数。
标注完成后,我们对图像进行了重新采样,以便它们每个像素都覆盖相同的地面面积,然后将图像和标签分成 900 x 900 像素的小块,以便更容易地创建模型输入。处理完成后,我们将其分成三部分:一个大的训练集和两个小的测试集,一个用于公共测试,一个用于最终的比赛验证。我们发布了训练集的图像和标签,只发布了公共测试集的图像,并保留了最终测试集的所有内容。
太空网 4:非最低点建筑足迹提取挑战
竞赛总结
一旦数据集完成,我们就通过 TopCoder 主办的公共 SpaceNet Off-Nadir 建筑足迹提取挑战赛来测试算法。在那里,参赛者训练算法来识别不同视角图像中的建筑足迹,争夺 5 万美元的奖金。
得分
分割任务的常见评估工具是逐像素评分,但我们要求竞争对手提供更多信息:建筑物的实际多边形足迹。这些在部署环境中更有用,在部署环境中,人们经常需要知道各个建筑物的位置。为了给他们的多边形预测打分,我们使用了一个交集/并集(IoU)度量:

We scored algorithms by an instance IoU metric. Algorithms generated building proposals for each image, and predictions where the intersection between a ground truth and prediction footprint was greater than 50% of the union of those footprints were scored successes. All other predictions were scored as failures (false positives).
我们为阳性预测设置了 0.5 的 IoU 阈值,并在评分后,计算了每个视角组(最低点/偏离最低点/非常偏离最低点)中的真阳性、假阳性和假阴性的数量。我们计算了每一个的 F1 分数,因为这个指标会惩罚假阳性和假阴性预测。然后,我们将这三个 F1 分数进行平均,得到最终的比赛分数。
近 250 名参赛者报名参赛,产生了 500 多份独特的参赛作品。成绩在下面!
获胜的算法
分数摘要
首先,让我们来看看前五名竞争者的得分:

Competitors’ scores in the SpaceNet 4: Off-Nadir Building Detection Challenge compared to the baseline model. Each score represents the SpaceNet Metric for the entire image set (Overall) or subsets of the imagery with specific look angles: Nadir, 7–25 degrees; Off-nadir, 26–40 degrees; Very off-nadir, >40 degrees.
从这些结果中可以得出一些值得强调的要点:
- 自从两年前的第一届 SpaceNet 建筑物识别比赛以来,建筑物足迹提取分数已经显著提高,当时获胜的算法实现了约 0.3 的 IoU-F1。地理空间计算机视觉算法走了很长的路,而且很快!
- 从非天底点(25-40 度视角)提取建筑物覆盖区的效果几乎与天底点影像一样好。这种类型的知识可以通知图像采集决策,因为我们现在知道,完美的外观不是这项任务所必需的。也就是说,
- 建筑物足迹提取仍然具有挑战性,非常偏离最低点(> 40 度视角)。这些图像的性能大约低 25%。我们将回到为什么这可能很快。
获奖算法总结
顶级竞争对手提供了他们算法的摘要版本,包括完整的解决方案代码和书面摘要,这些都是开源的这里。除了这些总结,我们还研究了每个竞争对手使用的算法,并发现了一些有趣的细节。

A summary of the models used by the top 5 competitors in the SpaceNet Off-Nadir Building Footprint Extraction Challenge. See the end of this post for numbered reference links.
让我们在这里分解几个关键细节:
各种深度学习模型(但没有经典的机器学习):
我们惊讶于使用了多少不同的深度学习模型架构,以及它们之间的分数有多么相似。一些竞争对手使用大量的集成——超过 20 个独立训练的模型——来生成哪些像素对应于建筑物的预测,然后对这些预测进行平均,以获得最终结果。另一个竞争者(编号 13)为每个单独的系列训练了一套不同的权重,然后使用相应 look 的模型权重为每个图像生成预测。
我们并不十分惊讶每个获胜的算法都使用了深度学习。这与计算机视觉的一般趋势是一致的:几乎所有的高性能分割算法都利用了深度学习。唯一使用的“经典”机器学习算法是梯度提升树,前两个竞争对手 cannab 和 selim_sef 用于从神经网络中过滤出“糟糕的”建筑足迹预测。
针对地理空间特定(及相关)问题的模型裁剪
这些算法教会了我们很多关于裁剪模型以适应空中影像的知识。建筑物像素仅占整个训练数据集的 9.5%。分割算法被训练来将单个像素分类为属于对象(这里是建筑物)或背景。在这种情况下,一种算法可以通过预测所有事物的“非建筑物”来实现高像素精度!这导致用“标准”损失函数(如二进制交叉熵)训练的算法崩溃到到处预测零(背景)。竞争对手通过两种方法克服了这一点:1 .使用相对较新的焦损失,这是一个交叉熵变量,它对低置信度的预测造成了极大的惩罚;2 .将该损失函数与基于 IoU 的损失相结合,例如 Jaccard 指数或骰子系数。这些损失函数通过强烈惩罚预测不足来防止“全零谷”。
使用高射影像的另一个挑战(以及小而密集的物体的实例分割等相关问题)是物体合并。上面描述的语义分割方法不做任何事情来分离单个对象(一项称为“实例分割”的任务,这是竞争对手在这次挑战中被要求做的)。通常通过将相邻的对象标记为单个实例来从语义掩码中提取实例;但是,语义分割可能会在附近的对象错误地相互连接的地方产生像素遮罩(参见下面的示例)。这可能会导致问题:

Building instance segmentation from attached (left) vs. separated (right) semantic segmentation output masks. Red arrows, poor prediction results in connection of very closely apposed buildings.
如果用例需要了解一幅图像中存在多少对象,或者它们的精确边界在哪里,这将是一个问题。一些竞争对手通过创建多渠道学习目标模板来应对这一挑战,如下所示:

A sample pixel mask taken from cannab’s solution description. Black is background, blue is the first channel (building footprints), pink is the second channel (building boundaries), and green is the third channel (points very close to two different or more buildings). Cannab’s algorithm learned to predict outputs in this shape, and in post-processing he subtracted the boundaries and contact points from the predicted footprints to separate instances more effectively.
该算法现在有效地预测三件事情,而不仅仅是预测每个像素的建筑物/无建筑物:1 .建筑/无建筑,2。建筑物的边缘/无边缘,3。建筑物之间的接触点/无接触点。减去边缘和接触点的后处理可以“清理”并置的对象,从而改进实例分割。
培训和测试时间不同
比赛规则要求参赛者的算法可以在 4 个 Titan Xp GPUs 上训练 7 天,并在不超过 1 天的时间内完成推理。上表列出了培训和测试时间。值得注意的是,在需要持续、及时更新的产品环境中,许多解决方案的部署速度可能太慢。有趣的是,来自大型集合的单个模型或许可以在不显著降低性能的情况下独立使用(并且速度大幅提高)——例如,cannab 在他的解决方案描述中指出,他的最佳单个模型的得分几乎与获奖的集合一样高。
离底影像分析算法的优缺点
我们问了几个关于 SpaceNet Off-Nadir 挑战赛获胜算法的问题:
- 获胜的算法识别了每栋建筑的哪一部分?即,脚印有多精确?
- 每种算法在不同视角下的表现如何?
- 不同算法的预测有多相似?
- 建筑物的大小会影响建筑物被识别的可能性吗?
这些问题在 CosmiQ Works 博客 DownlinQ 上有更详细的探讨。有趣的观点总结如下。
脚印有多精确?
当我们运行 SpaceNet Off-Nadir Challenge 时,我们为建筑物检测设置了 0.5 的 IoU 阈值,这意味着在地面真实足迹和预测之间存在的所有像素中,> 50%必须重叠才能算作成功。根据使用情况,该阈值可能高于或低于实际需要的值。低 IoU 阈值意味着你不关心一栋建筑有多少被正确标记,只关心它的某个部分被识别。这适用于计数对象,但如果您需要精确的轮廓(例如,在灾难后定位损坏),则不适用。当评估用于产品部署的计算机视觉算法时,考虑这个阈值是很重要的:对于用例,对象必须被精确地标记吗?
我们问,如果我们改变这个阈值,算法的建筑回忆(它们识别的地面真实建筑的比例)会发生什么变化。结果是惊人的:

Recall, or the fraction of actual buildings identified by algorithms, depends on the IoU threshold. Some algorithms identified part of many buildings, but not enough to be counted as a successful identification at our threshold of 0.5. The inset shows the range of IoU thresholds where XD_XD (orange)’s algorithm went from being one of the best in the top five to one of the worst out of the prize-winners.
如果阈值设定在 0.3 以下,竞争对手的表现几乎没有变化——在竞争对手找到的建筑中,大多数都达到了这个分数,如果不是更好的话。然而,性能在这一点上开始下降,一旦阈值达到~0.75,分数就下降了 50%。这种明显的下降凸显了计算机算法可以改进的另一个领域:小对象的实例级分割精度。
视角性能
接下来,让我们检查每个竞争对手的算法在每个不同视角下的表现。我们将考察三个性能指标:召回率(识别出的实际建筑的比例)、精确度(与实际建筑相对应的预测建筑的比例,而不是误报),以及 F1 得分,这是结合了这两个特征的竞争指标:

F1 score, recall, and precision for the top five competitors stratified by look angle. Though F1 scores and recall are relatively tightly packed except in the most off-nadir look angles, precision varied dramatically among competitors.
不出所料,竞争对手在这些图表中的表现非常相似,这与他们在排行榜上的排名一致。最值得注意的是这种分离产生的地方:竞争对手在“最低点”范围(0-25 度)内非常密集。事实上,顶部两个(cannab 和 selim_sef)之间仅有的显著分离的视角是那些 45 度的>。cannab 似乎已经赢得了他的算法在非常低的图像上的性能!
这些图的最后一点:在中间视角范围内有一些奇怪的尖峰图案。得分较低的角度对应于朝南拍摄的图像,其中阴影掩盖了许多特征,而朝北的图像具有建筑物反射的更明亮的阳光(下图复制自之前作为提醒):

Two looks at the same buildings at nearly the same look angle, but from different sides of the city. It’s visually much harder to see buildings in the South-facing imagery, and apparently the same is true for neural nets! Imagery courtesy of DigitalGlobe.
这种模式在我们的基线模型中更加明显。视角并不重要,方向也很重要!
获胜算法之间的相似性
我们检查了图像中的每一栋建筑,并询问有多少竞争者成功地识别了它。结果是惊人的:

Histograms showing how many competitors identified each building in the dataset, stratified by look angle subset. The vast majority of buildings were identified by all or none of the top five algorithms — very few were identified by only some of the top five.
超过 80%的建筑物被零个或全部五个竞争者在最低点和非最低点箱中识别出来!这意味着算法的不同之处仅在于它们识别大约 20%的建筑物的能力。考虑到神经网络架构的巨大差异(以及从不同算法训练和生成预测所需的计算时间),我们发现这一点值得注意。
性能与建筑规模
该数据集中建筑物覆盖区的大小变化很大。我们根据竞争对手识别大于 20 平方米范围内所有东西的能力给他们打分,但是竞争对手在整个范围内的表现都一样好吗?下图回答了这个问题。

Building recall (y axis) stratified by building footprint size of varying size (x axis). The blue, orange, and green lines represent the fraction of building footprints of a given size. The red line denotes the number of building footprints of that size in the dataset (right y axis).
即使是最好的算法在小型建筑上的表现也相对较差。cannab 仅识别出约 20%小于 40 平方米的建筑,即使在视角偏离最低点 25 度以下的图像中也是如此。该算法在范围超过 105 平方米的建筑物上实现了其峰值性能,但这仅对应于数据集中大约一半的对象。不过,值得注意的是,这种算法正确识别了天底影像中占地面积大于 105 平方米的建筑物的大约 90%。
结论
前五名竞争对手很好地解决了这一挑战,实现了出色的召回和相对较低的误报预测。尽管他们的神经网络架构各不相同,但他们的解决方案产生了惊人相似的预测,强调神经网络架构的进步对构建足迹提取和类似任务的回报越来越少——开发更好的损失函数、预处理和后处理技术以及针对特定挑战优化解决方案可能会提供更多价值。对象大小可能是高射影像分割的一个重要限制,视角和方向会显著改变性能。最后,通过查看 GitHub 上的获胜竞争者的代码以及他们对解决方案的描述,我们可以了解更多,我们鼓励您更多地探索他们的解决方案!
下一步是什么?
我们希望您喜欢从这个挑战中学习非最低点建筑物足迹提取,我们希望您将亲自探索数据集!不久将会有更多的 SpaceNet 挑战——请关注我们的更新,感谢您的阅读。
型号参考:
- https://arxiv.org/abs/1505.04597
- https://arxiv.org/abs/1709.01507
- https://arxiv.org/abs/1707.01629
- https://arxiv.org/abs/1409.0575
- https://arxiv.org/abs/1512.03385
- https://arxiv.org/abs/1608.06993
- https://arxiv.org/abs/1602.07261
- https://arxiv.org/abs/1612.03144
- https://arxiv.org/abs/1703.06870
- https://arxiv.org/abs/1405.0312
- https://www.crowdai.org/challenges/mapping-challenge
- https://arxiv.org/abs/1409.1556
- https://arxiv.org/abs/1801.05746
用本能创造人工智能
具有预训练知识的神经网络
2019 年 8 月下旬,谷歌的研究人员发布了一篇题为“重量不可知神经网络”的论文,让我们看到了我们在寻求创造尽可能接近自然大脑的人工智能(AI)过程中缺失的一块拼图:本能。本文涵盖了迄今为止寻找人工神经网络(ANN)架构的方法,指出了本能在大脑中的重要性,并为渴望细节的人描述了本能如何融入人工智能。
迄今为止的神经网络架构
简而言之,人工神经网络的结构是指其中神经元的数量、排列和连接。当构建一个人工神经网络来解决一个问题时,在所有约束条件下可能的最佳架构是所期望的。毕竟,拥有一个次优的解决方案是不划算的。寻找最佳人工神经网络架构的方法在不断发展。在他们旅程的开始,人工智能爱好者手动选择他们的架构,例如选择两个隐藏层,每个层有 4 个节点,如下图所示。明智的做法是,他们可以通过反复试验来尝试不同的架构,比较性能并选择最佳架构。

A basic, manually-chosen ANN architecture, sourced from Arden Dertat’s article
有了一些经验,他们可能会尝试使用遗传算法,最终得到一个比他们手动选择的架构更好的架构。如果更雄心勃勃,他们可能会去强化学习为基础的架构搜索,一个例子是 AutoML。
到目前为止,所有架构的一个共同点是,无论架构多么优化,所有的权重(神经元之间的连接)在开始时都是随机值。这是有道理的,因为对于复杂的问题,我们可能不知道从什么值开始,所以最好的办法是用随机权重创建一个空的大脑,让它通过训练从数据中学习,在这个过程中调整权重。学习是从零开始的。(关于深度学习如何从空大脑的想法中发展起来的有趣阅读,请阅读本文。)
对于复杂的问题,我们可能不知道从什么权重值开始,所以最好的办法是用随机权重创建一个空大脑,让它通过训练从数据中学习,在这个过程中调整权重。
但是让我们后退一步,把目光放在最终目标上,那就是复制大脑的工作方式。我们有办法创造一个完全随机的“婴儿大脑”,并允许它学习成为专家。没错,这就是大脑的功能。它会学习。然而,如果我们想让人工神经网络尽可能接近自然神经网络,还缺少一些东西:本能,天生就对自己的任务有一些了解。
先天与后天二分法
先天与后天二分法是由优生学和行为遗传学的创始人弗朗西斯·高尔顿受他的同父异母表兄查尔斯·达尔文著作的影响而流行起来的。
这里的自然是指一个有机体的预布线。本能,出生时的知识。狗追逐松鼠是因为它们的狩猎本能,甚至不知道一旦抓到它们该怎么办。一些鸟类在没有父母明确教导的情况下筑巢。你,作为一个人,倾向于沉溺于甜食,因为我们的祖先,狩猎采集者,发现在捕食者出现之前尽可能多的吃水果对他们最有利。这种与生俱来的倾向已经传了几千代给我们,即使我们现在是阿尔法物种,不用害怕任何捕食者。

The predator hunting instinct, sourced from: https://i.pinimg.com/originals/8a/32/fd/8a32fd409c364771fac7562ae687221d.jpg
另一方面,后天培养被视为外部因素对大脑的影响。它需要本能,并把它变成一种行为。这可以在国家地理纪录片中看到,当母猎豹削弱或固定她的猎物,以便幼崽可以练习攻击它。虎鲸也表现出类似的行为,它们在海豹周围翻滚。这是学习发生的地方。
自然是生物体的预布线(本能)。后天是外界因素(学习)的影响。
可见,学习在动物界发生得非常快,因为动物天生就有本能。因此,如果人工智能的目标是创建尽可能接近真实的神经网络,那么本能就必须被纳入其中,否则人工智能将是 100%的后天培养,而不是天生的。但是如何创建一个已经知道在训练前做什么的神经网络呢?进入重量不可知的神经网络。
重量不可知神经网络
WANN 是一种神经网络架构,其中 ANN 已经知道它应该显示的行为的一般趋势。用机器学习的术语来说,它有很强的归纳偏见。WANNs 具有共享的权重,即同一模型中的所有权重具有相同的值,因此不进行微调。
那么,如果传统的架构搜索方法找不到这样的架构,该如何找到呢?这是在一种被称为神经进化的技术的帮助下,通过扩充拓扑结构(NEAT) 以递归的方式完成的。听起来很恐怖?不用担心,这是容易理解的:神经进化意味着神经网络的人工进化(通过遗传算法),而增加拓扑结构意味着架构变得更加复杂。
寻找崇拜者的过程相对简单:
- 创建一组(群体)具有不同简单架构的神经网络。
- 使用不同的共享权重值来衡量各自的性能。这意味着,对于每个神经网络,使用一系列值对其进行评估,其中,对于每个值,所有权重都是相等的。简单地说,尝试所有权重的值都是 a. ,然后是值 b ,然后是 c ,以此类推。
- 根据性能和复杂性对不同的体系结构进行排序。
- 只选择性能最好的架构,使用 NEAT 改变它们以重新创建新的群体,然后从步骤 2 开始重复,直到获得满意的架构。
下图总结了这一过程。

The process of finding a WANN, sourced from the WANN white paper
万纳戒要统治他们所有人?
那么这是否意味着训练神经网络现在将变得过时?不完全是。因为一张图胜过千言万语,所以下面的 GIF 是 WANN 和微调模型在 Cartpole Swing-up 任务上的表现对比。

Performance of WANN with shared weights=1.0 (top), WANN with shared weights=-1.5 (middle, sub-optimal) and neural net with weights fine-tuned through training (bottom)
顶部的 WANN 并没有胜过微调的模型,但它已经完成了它的目的:它抓住了本能!这是一个神经网络,它甚至没有经过训练(它的所有权重都等于 1.0),但已经大致知道它要做什么。现在,可以采用并训练这种结构,期望训练将显示出比具有随机初始化权重的 ANN 更快的收敛。
结论
权重不可知的神经网络是一种寻找解决问题的神经网络结构的新方法。虽然它们不能从一开始就击败训练好的模型,但它们确实捕捉到了必要的偏差,作为未来训练更好模型的垫脚石。这样做,可以创造出具有本能的人工智能。
Hans A. Gunnoo 是一名数据科学家,他的职业生涯始于电子工程,后来专攻机器学习。他还在业余时间为开源人工智能项目和关于数据科学领域最新趋势的博客做出贡献。
走向数据驱动的组织
超过 97%的“2019 年大数据和人工智能高管调查”【1】受访者表示,他们的公司正在投资数据和人工智能计划,然而,只有 31%的人认为他们的公司是数据驱动的,更少的人认为他们的公司成功打造了数据文化(28.3%)。这清楚地表明,对数据计划的大量投资并没有假定一家公司是“数据驱动型”的。那是什么?
根据同一份报告,低水平的组织数据驱动转型的主要问题之一是公司接受数据驱动文化的速度缓慢。没错,这不仅仅是关于技能和天赋或者花哨的分析工具。这是关于文化的!
为了确保我们都在同一页上,让我们参考韦氏词典在组织环境中对“文化”的定义【2】:
"作为一个机构或组织特征的一套共同的态度、价值观、目标和实践."
简而言之,公司文化可以被描述为一种共同的思维模式,由组织中的每个成员在业务的各个方面共享和执行。它通常被称为企业 DNA——一种生物 DNA 的隐喻,编码在活生物体的遗传指令中。
但是,一家公司如何培养一种数据驱动的文化呢?我们来试着回答一下这个问题。
你看过体育剧《金钱球》(2011)吗?如果你还没有,它当然应该在你的“观察”列表的顶端。这部电影基于真实生活事件,讲述了奥克兰运动家队总经理比利·比恩(布拉德·皮特)和他的助手彼得·布兰德(乔纳·希尔)在有限的预算下,完全基于数据和分析,凭借高效的招聘决策,组建了美国棒球联盟历史上最成功的球队之一。然而,在到达那里之前,他们有许多挑战要克服。
格雷迪·富森:“美国职业棒球大联盟及其粉丝……如果你继续做你现在做的事情,他们会更乐意把你和谷歌男孩扔到公共汽车底下。你不会用一台电脑来组建一个团队。”
比利·比恩:“没有?”
格雷迪·富森:“不,棒球不仅仅是数字。这不是科学。如果是任何人都可以做我们所做的,但他们不能,因为他们不知道我们所知道的。他们没有我们的经验,也没有我们的直觉。”
比利·比恩:【不屑】“好吧。”
Grady Fuson: " Billy,你的孩子在耶鲁大学获得了经济学学位。你有一个有 29 年棒球经验的球探。你听错了。现在有些无形的东西只有棒球人才懂。你抛弃了童子军 150 年来所做的一切,甚至是你自己?”
比利·比恩:“适应或者死亡。”
尽管来自经验丰富的球探的所有敌意和反对,他们基于直觉做出决定,并为此感到自豪,但比恩和布兰德从未放弃对数据和分析的信任。最终,他们彻底改变了棒球比赛,并证明了数据驱动的决策方法远远胜过直觉。
这部电影是一个很好的例子,说明了数据、数据的良性使用和数据驱动的思维模式如何在高度竞争的环境中获得优势,同时又能在有限的条件下工作。这也适用于现代公司吗?
麦肯锡全球研究所 2013 年的研究报告称,数据驱动的组织在获取客户方面比竞争对手高出 23 倍,拥有更强的客户忠诚度,因此保留已获客户的可能性是竞争对手的 6.5 倍,最终盈利的可能性是竞争对手的 19 倍【3】。
弗雷斯特报告最近的一项研究表明:
“每家公司都想成为洞察驱动型企业。洞察驱动的企业平均每年增长超过 30%,有望在 2021 年赚到 1.8 万亿美元。这些以客户为中心的公司系统地利用整个组织的洞察力击败竞争对手,保持指数级的收入增长。”
听起来很有希望,不是吗!但是除了时髦的词语,数据驱动到底意味着什么呢?
" 数据驱动型组织将数据和分析置于其业务战略和所有层级的前端和中心。它使数据驱动的优化成为日常运营的一部分,从而在竞争中脱颖而出。”【5】
因此,数据驱动意味着基于全面的数据分析而不是直觉做出战略和运营决策,这正是比恩在他的团队中引入的,并受到他的老派球探的批评。虽然直觉由于个人经验可能是主观的和高度偏见的,但由数字支持的事实免除了这些缺点,而且可以提供超越人类直觉的洞察力。后面会有一个很好的例子来说明后一点。
彼得·布兰德:“嘿,比利。我想让你看看你让我做的这些球员评估。”
比利·比恩:“我让你做三个。”
彼得品牌:“耶。”
比利·比恩:“要评价三位选手?”
彼得·布兰德:“耶。”
比利·比恩:“你做了几个?”
彼得布兰德:“四十七。”
比利·比恩:“好的。”
彼得品牌:“其实,五十一。我不知道我刚才为什么撒谎。”
既然我们都认同数据驱动的含义,那么下一个合乎逻辑的问题就是:公司如何产生数据驱动?为了回答这个问题,我想使用卡尔·安德森在他的书“创建一个数据驱动的组织”【6】中对数据驱动的美好定义:
“数据驱动是关于建立工具、能力,以及最重要的,作用于数据的文化。”
数据驱动不仅意味着拥有一套适当的数据和分析技能,而且非常重要的是,培养和促进其作为一种组织文化的使用。虽然这在理论上听起来微不足道,但培养数据文化仍然是大多数公司需要解决的巨大挑战。为了支持这一说法,NewVantage 调查【7】指出,文化挑战是公司数据驱动转型的最大障碍之一:
“公司报告(77.1%)称,企业采用大数据和人工智能计划仍然是一项重大挑战。高管列举了多种因素(组织一致性、敏捷性、阻力),其中 95.0%源于文化挑战(人员和流程),只有 5.0%与技术有关。如果企业希望转型,它们必须开始解决文化障碍。”
根据对处于数据文化前沿的公司高管的采访,麦肯锡关于“为什么数据文化很重要”【8】的研究提出了努力采用数据驱动文化的组织应该采纳的 7 个主要方面:
1.数据文化就是决策文化——不要把数据分析当作一个很酷的“科学实验”或为了数据而收集数据的练习。收集、分析和部署数据的基本目标是做出更好的决策。
2.数据文化、最高管理层的要求和董事会 —首席执行官和董事会的承诺至关重要。但是,这种承诺不能仅仅通过偶尔的高级别声明来体现;必须与最高决策者和整个组织中领导数据计划的人进行持续、知情的对话。
3.数据的民主化 —把数据放在人们面前,他们会感到兴奋。但是建立很酷的实验或者自上而下地使用工具并不能解决这个问题。为了创造竞争优势,刺激对基层数据的需求。
4.数据文化和风险 —有效的数据文化将风险置于核心位置,这是您价值主张的“阴阳两极”。尽管公司必须确定它们的“红线”并尊重它们,但风险管理应该像智能加速器一样运作,以负责任的方式将分析引入关键流程和交互。
5.文化催化剂 —董事会和首席执行官吹响数据号角,一线人员响应号召。但要真正确保认同,必须有人带头冲锋陷阵。这需要能够沟通两个世界的人——数据科学和实地操作。通常,最有效的变革推动者并不是数字原住民。
6.在公司之外共享数据?别急 —关于即将转向生态系统的传言越来越多,人们认为,通过汇集市场上可用的各种最佳数据和分析资产,而不是在内部创建一切,将为客户提供更大的价值。然而,数据领导者正在建立一种文化,将数据视为“皇冠上的宝石”资产,在一个更加互联的世界中,数据分析被视为专有和竞争优势的来源。
7.人才与文化的联姻 —对数据人才的竞争是无情的。但是还有另一个因素在起作用:为您的数据文化整合合适的人才。这就要求你的机构在注入新员工和改造现有员工之间取得适当的平衡。从更广阔的角度看待采购,更敏锐地审视您的数据团队所需的技能。
比利·比恩:“我认为我们应该问的问题是:你是否相信这个东西?”
彼得品牌:“我愿意。”
彼得·布兰德(Peter Brand)对我们的棒球英雄的故事进行了反思,他拥有出色的分析技能,他让比利·比恩相信,使用数据是评估球员招聘决策的最佳方式,有时这些决策似乎与任何常识都相矛盾。例如,比恩给受伤的捕手斯科特·哈特伯格提供了一份合同,仅仅是因为他的高上垒率,根据布兰德的说法,这与得分高度相关。有哪个球探会喜欢这个吗?可能不会,因为哈特伯格的受伤会让他直接离开市场。尽管如此,这种完全基于数字的“疯狂”决策让该队登上了联赛榜首。如果没有两个角色共有的价值观、目标和决心,这可能吗?再说一次,很可能不是,但要让你知道,正是由于哈特伯格,奥克兰运动家队打破了之前的 19 连胜纪录,并创下了 20 连胜的历史新高。
总而言之,数据驱动型组织培养全公司的思维模式和价值观,专注于将数据和分析作为运营各方面决策的基础,以超越竞争对手并实现价值最大化。
数据文化和数据驱动的转型不是一朝一夕的事情。这当然需要一个长期的战略旅程,需要公司各级管理层的大力支持和参与。那么,为什么我们正在失去宝贵的时间呢?是时候开始准备计划了!
illy Beane: “如果我们成功了,我们就改变了游戏。我们永远改变了游戏。”
参考和链接:
【1】http://new vantage . com/WP-content/uploads/2018/12/Big-Data-Executive-Survey-2019-Findings-Updated-010219-1 . pdf
【2】https://www.merriam-webster.com/dictionary/culture
[4]https://go . thoughtspot . com/analyst-report-Forrester-insights-driven-business . html
【5】https://www . Delaware . pro/en-BE/Solutions/Data-driven-organization
【6】https://www . oreilly . com/library/view/creating-a-data-driven/9781491916902/ch01 . html
可再现的数据处理:Make + Docker

A real-life DAG 😃
避免依赖管理和容器化带来的再现性问题
动机
在数据科学和机器学习中进行实验时,最初进展的两个主要障碍是构建/使用“基础代码”的延迟和缺乏可重复性。感谢一些伟大的开源工具,你不必是一个软件大师来绕过这些障碍,并在一个更顺畅的过程中从你的数据中获得意义。
“嘿,我在运行你的代码时遇到了这个错误……你能帮我吗??"

…这是值得在 facepalm 上使用的东西。你在这里,试图与朋友或同事一起找到一个有趣的想法,而你现在正在调试一个文件未找到的错误。欢迎回到编程入门课程!
我敢肯定,代码的所有者也最喜欢花大量时间帮助别人以蜗牛的速度解决这些问题。你们两个刚刚对最近的实验结果的承诺所分享的纯粹的喜悦现在已经变成了无言的尴尬和沮丧,因为演示在显示出任何价值之前就失败了。

但是没关系。挺好的!你的朋友知道在哪里能找到丢失的文件。你被告知几分钟之内就能拿到,然后你就可以上路了!
“好吧,下载那个文件——我已经用电子邮件发给你了。然后运行train.py,你应该在 20 个历元内得到 98%的准确率。”
啊哈!就是这个!是时候加入受人尊敬的数据魔术师的行列了,铸造一个又一个键盘咒语,看着你的数据宝宝的大脑越来越先进,因为它在召唤一个新的终结者电影中的角色!让我们看看我们得到了什么!

…是的,我们都经历过。
会是什么呢?嗯,也许是显而易见的事。我了解 python,我知道你的代码应该做什么。我会打开你的train.py四处看看…不。

不要担心,这不会是一篇关于如何总是写一个软件杰作并嘲笑任何你认为不服从的东西的挥舞着小手指的文章。总的来说,这是一个棘手的问题,因为它带有主观性和竞争性标准。这些例子旨在强调,有无数的方式,我们不喜欢新的实验开始。
我们感兴趣的是以一种方便的方式重现和在结果上提高,而不是跌跌撞撞地重现过去的成就。记住这一点,让我们来看看一些流行的工具,它们可以用来简化任何新的 ML 软件项目的开始: Docker 和 Make 。
码头工人
python 生态系统在处理依赖性方面有一些很棒的特性,比如 pip 和 virtualenv 。这些工具允许用户根据需要安装的一些规范轻松地启动和运行,以继续运行一些代码。
例如,假设您刚刚遇到了 scikit-learn 库(当然是一见钟情)。您对其中一个演示示例特别感兴趣,但希望用保存在 pandas 数据框架中的数据重新制作它。此外,您正在进行的另一个项目需要一个旧版本的 pandas,但是您想使用仅在新版本中可用的特性。有了 pip 和 virtualenv,你就没有什么可害怕的了(……除了害怕本身)。
当你第一次学习这个流程时,你会感觉从依赖管理这种地狱般的存在中解脱出来。您胜利地宣布,您将永远不会再被丢失的软件包或臃肿的整体系统环境所征服。然而,不幸的是,这并不总是足够的…
当依赖不是在语言层面,而是在系统层面时,Python 环境工具就有所欠缺。
例如,假设您想用一个 MongoDB 数据库后端来设置您的机器学习项目。没问题!然后我们就自由了!没那么快...

嗯……事情没有像预期的那样发展。现在,除了设置我的库依赖项,我们还需要管理 python 之外的库?啊!进一步拖延!是时候谷歌一下 mongoDB 的包名了…
如果我连同事用的是什么操作系统都不知道怎么办?如果他在 CentOS 上,我不能给他一些sudo apt-get install片段。更重要的是,没有简单的方法来为未来的项目自动化这个步骤。让我做一次,我会做的。让我再做一次...zzzz。
因此,我们面临着为新的数据相关工作建立软件库和其他系统依赖的标准化和自动化的愿望,遗憾的是,我们常用的 python 工具已经不够用了。输入 Docker:一个在操作系统上运行服务的引擎,作为轻量级虚拟化包,称为容器。Docker 容器是 Docker 图像定义的实现,它由一个名为Dockerfile的文件指定。
可以把 order 文件想象成一个(详细的)设置步骤的处方,我们需要这样做,以便让系统处于我们想要的实验状态。例子包括建立数据库、安装库和初始化目录结构。如果您曾经编写过一个很好的 shell 脚本来完成类似的设置,那么您就离典型的 Docker 工作流不远了。相对于 shell 脚本,Docker 在这方面有很多优势,最显著的是容器化:使用 Docker 容器,我们可以从运行容器的主机系统中抽象出来。运行容器的虚拟系统是在它自己的进程中定义的。因此,我们可以让多个容器在同一台主机上运行完全不同的设置。这对于抵御系统依赖地狱来说如何?
此外,我们还进一步避免了文件丢失和系统状态差异等问题。我们确切地知道系统运行时的状态。我们知道这一点,因为我们通过 Dockerfile 文件中的明确说明做到了这一点。
为了实际构建映像,我们使用如下命令:
至此,我们已经建立了图像。有了这个图像,我们可以根据需要重复实例化它,例如执行多个实验。
瞧啊。
如果我们从这一点出发,向 N 个方向跑去做各种不同的实验,这些命令可能会变得很麻烦…
不要担心,如果你的眼睛在这一点上蒙混过关。关键是要不停地打字。不过没关系,我们使用 shell 脚本是有原因的。有了 shell 脚本,我们可以将制作一个非常具体的命令序列的微小细节封装到像bash doit.sh这样无需动脑的东西中。然而,还要考虑一个场景,其中 Dockerfile 定义依赖于其他文件(即 requirements.txt 文件或要使用的环境变量文件)。在这种情况下,我们还希望根据上游依赖关系,自动知道何时需要重新创建 Docker 映像。
那么是什么有四个字母,让你不用输入冗长费力的命令,并且自动化了依赖管理呢?
制造
GNU Make 是一个非常棒的工具,是软件运动赋予我们的,正是这个软件运动成就了今天的数字世界。我将为您保存一个更精彩的介绍,并跳转到它的核心抽象:一个基于 DAG 的方法来智能地管理流程中动作的依赖关系,以便高效地实现期望的结果。
好的,这也是编译 C 代码的一种便捷方式。但是要专注于第一个定义,要想得更大!多年来,重用基于 DAG 的一般依赖管理思想已经产生了一些伟大的工具,如德雷克(不是说唱歌手)路易吉(不是马里奥的兄弟),也许最著名的是气流 (AirBnB 的婴儿,但现在是 Apache 基金会的一部分)。
考虑下面这个人为的例子。我们想用训练好的模型对视听数据进行预测。当新的原始图像出现时,我们是否需要重新训练模型以创建预测?抛开在线学习等应用,我们不会。类似地,假设我们刚刚更新了我们的训练模型的一些参数。我们是否需要重新挑选原始图像,以便重新创建相同的数据样本?没有。

这就是品牌发挥作用的地方。通过指定一个带有“目标”的 Makefile ,该“目标”对应于 DAG 中的(一个或多个)期望输出,调用该目标将自动为您提供该结果,同时只重新调用必要的依赖过程。
Make 可以用于几乎所有涉及动作及其依赖关系的事情。它并不总是合适的工具(参见气流关于分布式应用程序的这个过程),但是它可以让你走得很远。我甚至用它生成了上面的图像!下面是 Makefile 的样子。
将两者结合
因此,我们努力克服可复制工作的困难,并引入了优秀的工具来管理环境封装(Docker)和依赖管理(Make)。这是两只很酷的猫,我们应该把它们介绍给彼此!

假设我们刚刚发现了 Magenta 项目,并且想要建立一个环境来一致地运行演示和实验,而不用进一步考虑某人的计算机上运行的是什么版本的this_or_that.py。毕竟,在某种程度上,我们并不关心你的机器上运行的是什么版本的this_or_that.py。我们关心的是,您能够以最小的努力体验发送者体验过的相同演示/结果。
所以,让我们建立一个基本的Dockerfile定义来完成这个任务。令人欣慰的是,Magenta 的人已经尽职尽责地自己创造了一个基础码头工人形象,使其成为 T21 琐碎的基础:
在将基础映像指定为 Magenta 的之后,我们在一个/opt卷上设置一个工作目录,安装一些系统级和 python 级的依赖项,并创建一个简单的bash入口点,直到我们有一个工作的应用程序。典型的requirements.txt文件可能如下所示:
太棒了。所以现在我们有了我们想要的环境的规格。我们现在可以制作一个Makefile来处理一些依赖关系:
此Makefile指定了run、image和$(DOCKERFILE)的目标。$(DOCKERFILE)目标将requirements.txt列为依赖项,因此当文件改变时,将触发 Docker 映像的重建。image目标是$(DOCKERFILE)目标的简单别名。最后,run目标允许一个简洁的调用来执行 Docker 容器中所需的程序,而不是每次都键入费力的命令。
一个码头工人统治所有人?

在这一点上,你可能会有动力去定义一个Dockerfile中的每一个可能的依赖项,以便不再为确保下一个项目的合适环境而烦恼。比如 Floydhub 有一个一体机 Docker 镜像用于深度学习项目。这个图像规范包括众多深度学习框架和支持 python 库。
不要那样做!
为了便于讨论,让我们把它发挥到极限。在你接下来的 100 个项目中,你的 Docker 形象会是什么样的?而接下来的 1000 个项目之后呢?随着时间的推移,它会变得臃肿,就好像你在每个项目中逐渐改变了你的主操作系统一样。这违背了 Docker 的集装箱哲学——你的集装箱应该是轻量级的,同时保持充足。
此外,由于所有这些膨胀,您失去了维持需要不同依赖版本的项目的多个方向的能力。如果您的一个项目需要运行最新版本的 Tensorflow,但您不想更新之前的 99 个项目(并处理更新带来的所有失败),该怎么办?
结论
到目前为止,我们已经为使实验和应用成为相对无痛的过程奠定了基础。我们通过 Docker 使用容器化来确保实验和应用程序是可复制的并且易于执行。然后我们通过 Make 使用了一些自动依赖管理来保持实验管道高效和简单运行。

值得注意的是,对于这两个问题,有许多可供选择的解决方案;然而,它们遵循相同的一般模式:容器化给你可复制性,自动依赖管理给你效率。由此,其他解决方案中的附加值通常归结为一些华而不实的东西,比如云集成、可伸缩性或总体易用性。每个人都有自己选择的工具。
原载于 2019 年 7 月 10 日https://anthonyagnone.com。
面向医疗保健的可解释人工智能:预测和可视化胸片中的年龄
我最近在 2019 年 SPIE 发表了一篇论文,该论文与一个使用胸部 x 光(CXR)和深度学习来估计一个人年龄的系统有关。这种系统可以在缺少患者年龄信息的情况下使用。法医是一个可以受益的领域的例子。
然而更有趣的是,通过使用深层网络激活图,我们可以可视化年龄对 cxr 的哪个解剖区域影响最大;提供关于网络“所见”的洞察,以估计年龄。
现在判断 CXRs 上的年龄估计和可视化如何具有临床意义还为时过早。然而,网络预测和真实患者年龄之间的年龄差异对于患者健康状况的预防性咨询是有用的。
本文提供了论文节选以及新的实验。
介绍
使用医学图像来估计一个人的年龄或一个器官的年龄并不是什么新鲜事,而且经常可以用于临床和法医目的。自 1937 年以来,一直有工作使用手 X 射线来估计一个人的骨龄,以评估儿科人群的内分泌生长障碍[1]。其他类似的例子包括 DEXA 扫描的骨密度 T 值(随年龄而降低)和计算机断层扫描(CT)中冠状动脉的钙值(随年龄而增加)。放射科医生也可能会报告患者的脑部 CT 有“慢性缺血性微血管改变和与患者年龄不成比例的萎缩”。换句话说,各种医学成像模式通常包含关于人的内部解剖结构或器官的视觉特征。这些特征对于人眼来说是明显的,并且通常与预期的生物年龄具有一些相关模式。
这种观察到的成像视觉特征和人的年龄之间的相关性使得这个问题有可能解决,并引起计算机视觉研究人员的兴趣。我们设想,随着计算机视觉研究转向分析多种成像模式(例如 X 射线、CT、MR 等)。)不断提高的图像质量,一个潜在的有用输出将是计算机在个人水平上对患者年龄的估计,并且可能是对所有不同器官的单独估计。
资料组
在写这篇论文的时候,最大的公开可用的 CXR 数据集是 NIH ChestX-ray8。它包含了来自大约 30,000 个不同个体的超过 110,000 幅正面 CXR 图像。它还带有元数据,包含每个图像的以下信息:1)图像索引,2)查找标签,3)随访号,4)患者 ID,5)患者年龄,6)患者性别,7)视图位置,8)原始图像宽度和高度,9)原始图像像素间距。

Figure 1. Age distribution for NIH ChestX-ray8 dataset (x axis: age in years, y: frequency of images)
图 1 显示了仅移除 19 个 90 岁以上的异常值后,整个数据集的患者年龄分布(即 1 岁至 90 岁)。
实验
我们首先根据患者 ID 将数据集分成 80%的训练、10%的验证和 10%的测试,以避免训练/验证/测试之间的重叠。
回归
我们使用 DenseNet 169(非预训练)网络来训练回归网络,其中原始 CXR 图像作为输入,归一化年龄值(0,1)作为输出。该输出节点的激活设置为【this 形。
- 第一轮实验:我们使用均方差作为这一轮的损失。

Training and validation loss for PA view using MSE loss. Minimum validation loss: 0.003
- 第二轮实验:我们还使用了决定系数 R 2 作为损失,因为在处理回归问题时,我们想要识别训练网络的拟合优度。

Training and validation loss for PA view using R2 loss. Minimum validation loss: 0.90
分类
作为另一种方法,我们将年龄值分为 9 个年龄组:(0,10),(10,20),(20,30),(30,40),(40,50),(50,60),(60,70),(70,80),(80,90)。我们使用 DenseNet 201(非预训练的)作为分类器,目标是这些年龄组,并且我们使用原始 CXR 图像作为输入进行训练。网络输出的激活设置为 softmax 。分类器的性能通过下面的 ROC 曲线展示。

DenseNet 201 ROC for 9 age groups: (0, 10], (10, 20], (20, 30], (30,40], (40,50], (50,60], (60,70], (70,80], (80,90]
我们还尝试了预训练的 DenseNet 201,但性能非常相似。
告诉我你看到了什么
总的来说,分类器网络的性能是令人满意的,这促使我们研究显著图,并更好地理解网络在分类期间“看到了什么”。为此,我们使用了标准深度网络可视化方法自带的 Keras-Viz 库。下图显示了来自上面我们训练的 DenseNet 分类器的不同年龄组的显著性图。



Average saliency map per age group on the testing set. Left: (0,10], Middle: (10,20], Right: (20,30]



Average saliency map per age group on the testing set. Left: (30,40], Middle: (40,50], Right: (50,60]


Average saliency map per age group on the testing set. Left: (60,70], Right: (70,80]
有趣的是,也许在临床上并不令人惊讶的是,随着患者年龄的增长,显著区域从多种多样的解剖区域转移到主动脉弓和纵隔壁周围更受限制的区域。就这些结果咨询了我们的临床医生后,我们认为这与随着患者年龄的增长主动脉弓和纵隔的增大和钙化有关。
结论
这项工作为我们下一步的研究方向奠定了基础。更具体地说,虽然激活图可以帮助可视化 cxr 中预测年龄的区域,但真正的临床价值是探索我们如何在疾病分类器中利用这些图,以便我们可以识别异常区域有多少是由于自然年龄增长,有多少是由于病理/疾病。我们相信这些额外的信息可以帮助建立更好的疾病分类器,例如对一幅图像“就年龄而言”是正常还是异常进行分类。该信息还可以帮助量化患者中存在的生理和病理过程的程度。后者的例子可以包括但不限于骨关节炎或肌肉骨骼系统的退化性椎间盘疾病、肺的衰老或肺气肿变化、以及主动脉和脉管系统的钙化性动脉粥样硬化。事实上,随着算法的改进,以前未知但更可靠的衰老或病理标识符将被识别出来。在临床环境中,医生可以在各种器官系统的预测年龄或总体预测年龄中找到建议患者改善健康习惯的机会。
朝向快速神经类型转移
Gatys 等人[1]提出的神经类型转移的开创性论文展示了深度卷积神经网络的显著特征。从参数卷积层学习到的顺序表示可以分为“内容”和“样式”。风格转移背后的基本思想是,在图像网络分类等任务上预先训练的 DCNNs 可以用作描述符网络。图像通过预先训练的 DCNN,如 VGG [2],中间特征激活可用于融合一个图像的“风格”与另一个图像的“内容”。从预训练网络的特征激活中导出损失函数是神经类型转移背后的基本思想。
尽管有惊人的结果,根据[1]实现神经类型转移需要一个缓慢的迭代优化过程。首先,使用生成器网络生成图像。这个输出的图像通过预先训练的 VGG。通过计算 Gram 矩阵,来自层 1、2、3、4 和 5 的 ReLU 激活是非局部化的,这形成了样式输出。层 4 中 ReLU 激活的内积形成内容输出。然后通过反向传播优化图像,使得样式和内容输出与目标样式和目标内容图像相匹配。

Results from Ulyanov et al. [3] ‘s Faster Style Transfer with Feed-Forward Networks
本文将介绍 Ulyanov 等人[3]的一篇论文,该论文通过训练前馈网络来加速这种神经风格转移的过程,使得只需要一次正向传递来风格化图像。以下是本文的链接:
[## 纹理网络:纹理和风格化图像的前馈合成
Gatys 等人最近证明了深度网络可以从一个单一的…
arxiv.org](https://arxiv.org/abs/1603.03417)
报纸上有趣的快速统计
- 该网络在 NVIDIA Tesla K40 GPU 上训练了 2 个小时
- 风格转换 20 毫秒
- 170 MB 以生成 256 x 256 的样本
- 作者发现用 16 张内容图片训练时效果最好
网络体系结构
我认为理解一篇新的深度学习论文的最有用的方法之一是查看所使用的架构,因此这就是本文将如何开始探索这项技术。

Multi-Scale Generator Architecture for Feed-Forward Style Transfer [3]
这个架构有很多部分。首先,它是一种多尺度架构,类似于 LAP-GAN 或渐进增长 GAN 中使用的架构。每个 z 代表不同空间分辨率的随机噪声输入。每个训练历元对包含 K 个张量的噪声向量 z 进行采样,在上图中,K = 5。每个噪声向量被卷积 3 次,然后通过放大和连接操作与下面的层结合。上图仅用于合成纹理。不幸的是,作者没有提供风格是如何合成的额外图片,但它是一个可以阅读和理解的快速增强。与上面的图像相反,当他们进行风格转换时,他们对内容图像 y 进行下采样,以匹配 z 中的每个噪声张量,并将它们连接在一起。例如,4x4xc 噪声张量 0 与下采样的 4×4×3 内容图像 8x8xc + 8x8x3 连接,..,等等。
另一个有趣的细节是在网络末端使用 1x1 卷积。这样做是为了保持空间分辨率,但是减少特征图的深度,使得输出从 HxWxC 张量收敛到 HxWx3 RGB 图像,(H =高度,W =宽度,C =通道)。

然而,也许比建筑更有趣的是这项任务中使用的损失函数的推导。这个损失函数由两部分组成,一个是风格损失,另一个是内容损失,这两部分都是从预先训练好的深度卷积神经网络(在这种情况下是 VGG-19)的中间激活中得到的。
通过 Gram 矩阵的计算,风格损失是非局部的:

Gram Matrix Equation
这取每个深度的特征图的内积。例如,如果卷积的输出是具有 64 个特征映射的 50×50×64,则特征映射 1 的点积与特征映射 2 相乘,依此类推,直到特征映射 64。从而形成损失函数,

相反,内容损失计算如下:

该等式计算每个要素地图上空间位置之间的差异。因此,损失函数为每个任务捕捉了非常不同种类的信息。这两个损失被组合用于风格转移,并用参数α加权。

这个损失函数与 Gatys 等人[1]提出的损失函数没有太大的不同,但是,想到它被用来训练一个前馈网络是很有趣的。
非常有趣的是,可以看到如何通过深度神经网络的单次正向传递来实现神经类型的转移。未来的工作强调,这种方法仅限于预先训练的风格,结果的质量并不总是像 Gatys 等人[1]那样高。看看神经风格转移算法如何进一步发展会很有趣,感谢阅读!

More Results from This Paper [3]
参考
[1]莱昂·a·加蒂斯,亚历山大·s·埃克,马蒂亚斯·贝赫。艺术风格的神经算法。2015.
[2]卡伦·西蒙扬,安德鲁·齐泽曼。用于大规模图像识别的非常深的卷积网络。2014.
[3] Dmitry Ulyanov、Vadim Lebedev、Andrea Vedaldi、Victor Lempitsky。纹理网络:纹理和风格化图像的前馈合成。2016.
走向智能
在这一系列中,我将提供真实世界的例子,在这些例子中,数学被用来做出更明智的决定

Illustration by Garry Killian
处理不确定性
我们生活在一个动态的世界里,各种事件相互影响。大多数现实世界的变量都是随机的,变量的结果也存在不确定性。如果这个变量会严重影响你的业务,你会想知道任何可能的负债。我工作的公司为欧洲的电力贸易提供市场。大部分交易都是在金融结算前一天达成的当日合约。由于我们每天都要清算大量的交易,我们需要从会员处获得抵押品,以防会员违约,无法履行其义务。电价是不稳定的,我们需要在前一天收集抵押品,以获得第二天我们期望从会员那里获得的任何价格和数量。
处理这种风险的当前流程是将 3 年的历史价格拟合到最佳拟合分布中,并计算价格的置信度。在这篇文章中,我将展示为什么这是一个过于简化的方法,这对业务有什么影响,以及新思维如何能够完全改变业务的健康和稳定。那么这种模式如何改进呢?如何才能做出更智能的方法来理解和预测电价?数据中存在增加信息价值的结构,拟合算法和机器学习工具可以用来做出更明智的决策。例如,我们知道价格是有时间顺序的。这是可用于改进模型的第一个信息值。这将允许预测模型考虑时间维度。这一特性极大地增强了算法感知价格的方式,以及算法捕获具有预测能力的数据模式的能力。对于算法来说,这完全是关于它所能看到的使其在预测方面表现良好或不太好的东西。也有外力可以增加信息价值。例如,线性回归可以用来寻找风级能够给出的关于价格的信息。本系列的一个主题是提供一些强大的数学工具,并展示如何使用这些工具以及内在理论的价值。在接下来的几节中,我将带您了解如何创建一种更智能的方法来解决企业面临的问题,以及采用更智能的方法所获得的收益。
数学发展了很久。有一些强有力的思想已经被构思和推理出来,并且数学给出的一些知识是具有挑衅性的。我想谈的第一个重要观点是独立事件的概念。独立事件之所以强大,是因为它们的总和近似于正态分布。对于有界分布,有可能找到平均值的法线的收敛。如果您有许多独立的观察结果,您甚至可以使用卡方检验来推断数据是否来自特定的分布,从而得出更有力的结果。
电价不是独立事件。我们可以围绕价格进行构建,这样我们只剩下独立的事件,我们可以将它们视为来自相同的分布。为了形成价格的这种转换,我们利用我们对价格性质的了解,建立了一个捕捉这些特征的模型。价格显示时间序列结构。指数平滑和自回归模型都可以模拟两个或多个时间步长之间的线性相关性。我们知道在价格之间有一个整合的模式,早期阶段的价格影响当前阶段的价格。指数模型用于捕捉价格的这种依赖性。在我们包含的模型中,我们还有一个价格的周相关性或周期。这两个依赖关系应该抓住了价格的大部分依赖性。为了给模型更大的解释力,从该模型得到的独立观测值与风级一起回归。在丹麦电力市场中,风力水平可以解释 15.47%的价格水平。下表显示了指数平滑模型在有风回归和没有风回归的情况下能够解释多少价格变化。在 2019 年初至 2019 年 9 月的样本内和样本外期间,该模型能够解释多达 65-70%的价格变化。

下图显示了残差的自相关图,得到的序列是不相关的随机变化。

残差是不相关的,观测值的平均值,即 OLS 估计量,将给出真实的平均值,模型将是无偏的。皮尔逊卡方检验拒绝这些独立事件来自正态分布。我们利用经验累积分布函数,围绕价格画出一个 95%的置信区间。下图显示了测试期内价格的点位预测。

该模型是对电价的描述,它使用多个概念来寻找描述价格的公式。它解释了差异,解释了产生这个价格的机制。使用 95%置信区间的新风险价格与原始方法的风险价格一起绘制。

由于当前风险价格不被视为时间序列,因此风险价格不考虑一年中温度变化导致的任何季节性变化。当前风险价格每月更新一次,在第一次发布风险价格和第二次发布风险价格之间发生的时间事件会丢失,不会引起任何注意。从上图可以看出,在很长一段时间内,该公司面临着巨大的风险,没有足够的抵押品来对冲。此外,我们在风险低得多的夏季收取过高的费用。这个例子显示了正确建模的重要性,以及数学对业务和公司健康发展的影响。这种新模式将转移公司目前面临的风险,同时提高盈利能力。在此期间,我们对会员要求的平均差额总共减少了 49.06 亿欧元。这就是数学的力量,也就是智慧决策的力量。
走向基于神经科学的人工智能
为什么在先了解生物智能之前,不会有人类级别的人工智能。
在过去的十年里,我们见证了人们对人工智能的重新兴趣,以及对其未来发展的新希望。这一新的乐观浪潮不仅来自公众辩论和商业炒作,而且来自研究界本身,在最近的一项调查中[超过 90%的人工智能科学家](https://www.technologyreview.com/s/602410/no-the-experts-dont-think-superintelligent-ai-is-a-threat-to-humanity/)说人类水平的人工智能将在 2075 年达到。
然而,我们如何到达那里似乎仍然相当不清楚。值得注意的是,大多数人工智能科学家并不认为“复制大脑”将是追求人类水平的人工智能或人工一般智能的好策略,因为我们还不如复制其生物约束。**
然而,在这篇简短的博文中,我将指出一些想法,说明为什么我认为在首先了解生物智能之前,不会有人类级别的人工智能。
人工智能研究:打地鼠游戏
尽管人工智能取得了显著的进步,但由于机器学习研究的最新进展,对其开发的全面和有凝聚力的方法似乎仍然是一个遥远的目标。如今,人工智能研究通常在小型研究实验室中进行,致力于解决问题的自下而上、渐进(和部分)的解决方案,这些解决方案很少会通向人类水平的人工智能系统。
更令人担忧的是,“人工智能”算法和技术往往专注于孤立的非常狭隘的智能方面(T21)。虽然,一方面,孤立地研究子组件对于更好地理解它们并将其从外部因素中分离出来可能是重要的,但另一方面,如果我们想要理解的是这些子组件的相互作用,从而导致复杂智能行为的出现,这种方法可能是不可能的。
第一种方法在今天的人工智能研究中非常常见,通常被转化为一种“打地鼠”游戏,在这种游戏中,如果在同时考虑问题的多个维度的更复杂的环境中使用,对一项狭窄任务的过度设计的解决方案被证明是无效的,甚至是自我挫败的。
“[……]针对单个指标或一组指标进行优化通常会导致权衡取舍和走捷径,而不是针对[……]进行衡量和优化。就人工智能而言,专注于实现特定任务的性能,而不对系统如何实现这种性能设置任何条件,这导致了尽管目标任务执行得很好,但系统在很大程度上不具备人工智能领域试图建立的那种人类智能。”— F.Chollet,《论智力的衡量》,2019 年
例如,您可以考虑我们希望我们的智能系统具备的不同关键计算原则(例如,连续学习、表示学习、序列学习、组合性、稀疏分布式表示和计算等……)。所有这些原则都集中在智能的特定方面,这些方面对于开发真正智能的机器也同样重要。然而,这些很少一起研究,它们的算法解决方案的相互作用/冲突经常是未知的。
当然,如果我们同时考虑多个维度,全面人工智能解决方案的搜索空间会迅速扩大。例如,让我们考虑一个简单的场景,其中我们已经确定了 10 个属性来满足人类级别的* AI。让我们也假设对于每一个都存在 10 个可能的解决方案(如果孤立地考虑的话),并且假设也存在一个唯一的综合解决方案,天真地为每个维度组合一个。总的搜索空间仍然是 10 个⁰= 10.000.000.000 个可能的算法解。*
虽然作为一个研究团体,我们无疑在过去 60 年里在这个领域取得了一些进展,但我们确定我们能在没有任何帮助的情况下找到这个解决方案吗?**

Figure 2: The number of possible AI solutions given a set of properties to fulfill (x, y, z) starts from 5 and ends up with 125 when we increase the number of properties from 1 to 3 with an exponential trend.
弗兰肯斯坦方法
许多人工智能研究人员的一个共同观点是,也许我们在研究“”主算法时,根本不需要在这个巨大的可能性空间中搜索。我们可能只是划分和维护独立的不同解决方案,这些解决方案擅长解决不同的问题,只是后来将它们拼凑到一个综合系统中,该系统应该能够平衡它们,并根据要求的环境利用这些子系统提供的功能。**
我将这种方法称为"弗兰肯斯坦方法",因为我不认为仅仅将东西拼凑在一起就可以构成一个可扩展的解决方案,从而导致复杂和涌现的智能行为(尽管它可能会在一些实际应用中显示出自己的用处)。相反,我认为人工智能研究最有趣的方法是理解关键的计算原理如何协同地、有效地和有效地一起发挥作用,以实现我们可以在生物智能系统中观察到的惊人的新兴特性。

****Figure 3: “ Young Frankenstein” movie parody, 1974. Igor chooses the wrong brain to transplant ending up with a demented Frankenstein.
Gary Marcus 是这一观点最突出的捍卫者之一,他提出了“ 混合人工智能系统 ”,将连接主义者与符号化和概率化方法结合在一起:
最强大的人工智能系统……使用像深度学习这样的技术只是一整套非常复杂的技术中的一个元素,从贝叶斯推理的统计技术到演绎推理。——加里·马库斯,2012 年
而 Yoshua Bengio 更符合我个人的看法:
我敢打赌,深度网络的输出被离散化,然后传递给 GOFAI 符号处理系统的简单混合是行不通的。为什么?很多原因:(1)你需要在系统 2 组件和系统 1 部分中学习,(2)你也需要在那里表示不确定性(3)强力搜索(符号处理系统的主要推理工具)不可扩展,相反,人类使用无意识(系统 1)处理来指导推理中涉及的搜索,所以系统 1 和系统 2 非常紧密地集成,(4)你的大脑始终是一个神经网络。— Yoshua Bengio,2019 年
基于神经科学的人工智能
这个问题的一个可能的解决方案是从大自然那里获得一点帮助,引导我们朝着人类水平的人工智能进行巨大的搜索。这个论点已经被很多人使用,最著名的是戴密斯·哈萨比斯和他对神经科学启发的人工智能 的探索。然而,与此同时,其他人工智能研究人员,包括图灵奖获得者 Yann LeCun 等,警告我们关注生物学,这可能也会适得其反。这一观点的主要论据经常以飞行器的历史作为例证。
我有幸在巴黎的 艺术与博物馆 亲自看到的雄伟的 Avion III 是一架由 Clément Ader 在 1892 年至 1897 年间建造的原始蒸汽动力飞机。它的设计灵感主要来自大自然(特别是蝙蝠),有着铰接的翅膀,然而这种交通工具无法飞行,法国政府在 1898 年停止了对它的研究。大约在 1903 年,莱特兄弟制造了第一架飞行器。

****Figure 4: Y. Lecun Slide, from a talk in 2016.
“ Wright Flyer ”的设计并不是从鸟类中获得灵感,而是基于对空气动力学原理的研究。因此,这个例子经常被引用作为一个令人信服的论据来证明不是从生物学中复制,而是从生物学中获得灵感:拍打翅膀、羽毛等等,对有效飞行并不重要。
然而,我认为这种说法在很大程度上被人工智能研究界误解了,因此任何与主流人工智能研究无关并且从生物学中获得更多灵感的东西都经常被标记为“注定失败”,如果它不能在几个标准基准上达到正确的准确率。
莱特兄弟花了大量时间观察飞行中的鸟类。事实上,虽然生物学可能确实会造成与智力没有具体关系的限制,但只有通过对生物系统的仔细研究,我们才能理解正确的抽象层次、智力的关键原则,将它们与可能出于不同进化原因而存在的实现细节分开。
这里说实话,大多数机器学习研究人员(包括我自己)没有知识、时间和精力去调查其他学科,并真正了解那里发生了什么。当他们说他们“T0”从大脑中获取灵感时,是在一个不可思议的高抽象层次上(比如想一想 记忆回放 )。此外,他们通常不愿意失去他们在现实世界中的优势,实际应用,也不会冒任何风险去研究生物学。
基于神经科学的智能框架
与此同时,我仍然不清楚,在不清楚什么是智能的情况下,我们如何想象创造出真正智能的机器。我们最终如何称人工智能为识别手写数字的简单算法?
我认为人工智能的研究重点不应该是狭隘应用的增量改进,而是更多地关注智能计算框架的发展,这种框架可以解释人类和机器智能行为的出现。
在这篇博文中,我使用了术语“基于神经科学的人工智能”,因为我认为我们应该开发这个智能框架,而不仅仅是从生物学中获得松散的灵感,也不受其实现细节的约束,而是开发一种智能理论,这种理论应该受到理论和计算神经科学发现的强烈指导。
实际上,这意味着循环执行以下步骤:
- 确定关键的计算原则,将它们从实现细节中分离出来。
- 理解它们的相互作用和新兴属性。
- 在硅片(在模拟和实际应用中)和神经科学数据中验证该框架。
如果目标是达到人类水平的人工智能,那么开发和专注于不包括所有预先确定的智能原则(打地鼠,过度设计风险)的过度设计的狭义人工智能是没有意义的。
人工智能与神经科学的融合
我相信在未来十年,由于大脑想象、脑机接口、神经科学发现等方面的重大进展。显而易见,实现人类水平的人工智能的最快途径是首先理解生物智能。
许多人工智能研究人员经常未能认识到的是,我们已经在缓慢地朝着那个方向前进(见下面的图 5 )。例如,神经网络正在慢慢整合有趣的功能和计算属性,这些功能和属性一直被认为在神经科学中很重要。以“持续学习”为例:这是神经网络中最近的趋势(从 2016 年开始,人们对它的兴趣越来越大),但它长期以来一直被认为是生物学习和突触可塑性基础上的一个关键计算属性。
问题是,我们在神经科学的基础轴上来回移动,只是为了那一刻的实际应用,但从长远来看,我们只是在放慢我们走向人类水平的人工智能的道路。

****Figure 5: The progress in AI can be already seen as more and more neuroscience grounded over time.
虽然我们可能会在特定的狭窄问题(例如下棋或下围棋)上找到比进化更聪明的解决方案,但如果没有大自然的帮助来指导我们的研究,一般智能系统的指数级复杂性可能太难把握了。
这一认识将引发人工智能和神经科学之间前所未有的自然互动。此外,在这种情况下,共享智能框架不仅可以让我们建造更智能的机器,还可以更好地了解我们自己,并可能扩展我们的认知能力,缩小人类和机器之间的界限。

****Vincenzo Lomonaco, the author of this story.
如果你想看更多关于人工智能和持续学习的帖子,请关注我的《媒体》( Medium )( Medium )( Medium )( Medium )( Medium )( Medium )( Medium )( Medium )( Medium )(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体)(媒体:(媒体)(媒体)(媒体:(媒体(今天加入我们的松弛期!😄 🍻)
如果你想取得联系,访问我的网站vincenzolomonaco.com!😃
走向精确安全
利用同态加密实现量身定制的安全性

Image by Yücel Ünlü from Pixabay
"但就她自己而言,她比你们其他成百上千朵玫瑰更重要……因为她是我的玫瑰"。
安东尼·德·圣埃克苏佩里的《小王子》
我们都想要最好的。作为一个行业,我们渴望为我们的客户提供最好的安全性。但是什么是最好的安全呢?显然,答案因客户而异。他希望保护自己免受*的威胁,而不仅仅是任何威胁,他希望保护* 他的 数据,而不仅仅是任何数据—他希望获得量身定制的安全性。
个性化的客户体验绝对不是一个新概念。一个与安全行业有许多共同之处的行业正在朝着这个方向经历一场大革命。(PM)精准医疗是一个描述针对个人的医疗保健实践定制化的术语。这种方法有多种好处,主要是提高患者护理质量,实现成本效益,并降低再入院率和死亡率。机器学习 ( ML )在这个新兴领域有很大的作用。它用于大量数据的分析、生活方式影响分析和基因组测序。ML 在网络安全领域也被大量使用——尽管有些人会说还不够多。**
看起来就像在医学中一样,下一个“低挂的果实”是以最大化个人客户安全体验的方式利用 ML。通过使用他的数据,他的生活方式(组织政策)和他的基因组(特定的软件,上下文)。
下一步,在我看来是意料之中的——精密安全 ( PS )。
让我们为我们的客户提供最适合他们的安全体验,并基于他们的个人数据。我们有动力,也有技术,只有数据这个小问题——这是隐私。根据定义,如果你想使用我的数据来个性化我的安全,你会暴露于我的所有个人 IP,而且你可能会希望它在世界各地传播,被你基于云的 ML 管道处理。这令人不安,对客户来说可能是一个很大的“不”字,尤其是在保守的行业。他们是对的。这是他们的数据,也是他们最重要的资产。这种担心是有道理的。
这个问题也有一个很好的解决方案——(全)同态加密。 FHE 是一种新的加密技术,它可以对加密数据进行数学计算,而不需要解密。这些计算的加密结果(一旦解密)将与它们是在普通数据上进行的一样——令人惊讶。在实践中,这意味着数据可以在客户端加密,发送到远程服务器,处理和操作,然后发送回客户进行解密。客户数据在整个链条中被加密,风险极小。

data is encrypted and decrypted on client side, all computation is done on encrypted data
生产级实现已经上市。这个领域有几个创业公司,像恩维尔、二元和福塔尼克斯。 PALISADE 和微软 Seal 作为同态加密的开源框架值得一提。使用这些工具,我们可以打破数据壁垒,为我们的客户提供真正的个人安全体验。市场将我们推向精密安全,现在是我们接受挑战的时候了。
请分享您的想法,并在 Medium 或 Twitter 上关注我的博客帖子更新!
[1]:另一个有趣的解决方案是联合学习( FL )。FL 是一种在边缘设备(移动设备、网关等)上训练算法的 ML 技术。)而不共享他们的数据样本。这个模型可以上传到云中,改进协作模型,或者只在本地使用。一个很好的用例是 Google Gboard 。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
走向安全的人工智能/机器学习
企业正在将 AI/ML 工作负载迁移到云,但遇到了重大的安全问题。以下是问题和解决方法。

Photo by William Bout on Unsplash
AI/ML 向云的迁移已经开始
今天,AI/ML 对高级计算和数据存储的需求推动企业将 AI/ML 工作负载从舒适的数据中心迁移到云中。但是最近引人注目的数据泄露事件的头条新闻表明,存在着有效、真实和严重的网络安全问题需要解决。
这对 AI/ML 来说是一个特别尖锐的问题。毕竟,AI/ML 从业者依赖于大量的数据来训练他们的模型,这些数据大多是敏感的和/或专有的。让事情变得更加复杂的是,数据科学家使用的数据必须在很大程度上保持未混淆(或“明文”),这可能会扩大数据泄露的机会,或许还会扩大其影响。
因此,企业带着一定程度的恐惧和谨慎看待 AI/ML 向云的迁移可能并不奇怪。事实上,国际咨询公司德勤最近在 T2 进行的一项调查显示,所有行业的高级技术和安全主管和专业人士都认为“网络安全漏洞会减缓甚至阻止人工智能的发展。”
今天,解决网络安全问题似乎已经成为许多企业将 AI/ML 工作负载迁移到云的先决条件。
本文将讨论企业将人工智能/人工智能工作负载迁移到云时面临的主要安全问题,然后确定几种方法来保护企业的云租用,以支持人工智能/人工智能活动。

Photo by Markus Spiske on Unsplash
AI/ML 云迁移引入了有效的安全问题
过去,企业安全主要基于保护企业数据中心周围的网络边界,前提是边界内的所有系统、数据和资源都是安全的、可信的。当时,这是有意义的,因为大多数有用的应用程序和资产都存在于网络边界内的数据中心。
今天,几乎每个企业都使用互联网与客户进行互动,与业务合作伙伴进行交易,并与企业保护伞下的远程组织进行通信。随着企业利用灵活、可扩展且廉价的云计算资源,云的使用也在飞速增长。
但是使用云处理人工智能/人工智能工作负载的本质引入并加剧了网络安全问题。有两个值得强调的独特特征:(a) AI/ML 要求访问大量敏感数据,以及(b) AI/ML 要求这些数据不被屏蔽(“明文”),以便于数据科学家进行模型探索、培训和验证活动。
因此,很明显,企业通信模式以及云消费模式已经发生了巨大的变化。同样清楚的是,由于 AI/ML,数据可见性和可访问性的需求也发生了变化。
不幸的是,过去的企业安全实践并没有跟上时代的步伐。至少,最近关于 Capital One 数据泄露的头条暗示了这一点。
但是为什么企业安全实践没有跟上呢?有几个原因:首先,云的本质产生了一个安全问题,因为默认情况下,许多资源在创建时就可以通过互联网访问。这一点的含义相当深远:建立网络安全边界不足以像保护数据中心一样保护云上的资产。
第二,现在的敌人更加聪明,并且获得了更好的工具,导致网络边界看起来变得更加漏洞百出。优步最近的云数据泄露无疑证明了这一点。
第三,随着 AI/ML 所需的大量敏感数据可供员工使用,企业需要引入控制措施以避免故意泄露。环球邮报报道影响 290 万客户的 Desjardins 集团数据泄露事件是由一名违规员工引起的,该员工涉嫌窃取和暴露敏感数据,包括个人信息,如姓名、出生日期、社会保险号(类似于美国社会保险号)以及电子邮件、电话和家庭地址。
最后,安全配置不可避免地会随着时间的推移而变化:它们由多个小组执行,并且可能带有某种程度上分散的治理机制。随着时间的推移,一个更改会与先前的更改发生冲突,或者无意中与另一个更改的执行目的相反,最终,这将导致先前安全的环境漂移,最终产生安全漏洞。也许 Capital One 最近在云上的经历是这种情况下最深刻的例子。

Photo by Ozzie Stern on Unsplash
解决 AI/ML 引入的网络安全问题
有几种现代技术(见图 1)可以解决上述安全威胁,并且是安全企业云租用的基础。

Figure 1
首先,基于身份的 安全方法规定,只有有效的身份凭证才能提供身份验证和授权,以允许访问企业云租户内的资源。
基于身份的安全性(图 1 中的“1”)方法确保敏感数据只能由具有验证证书的数据科学家访问。由此得出的推论是:恶意或未经授权的代理没有访问敏感数据所需的必要凭证。
基于身份的安全方法的实施应至少考虑以下几点:
- 本地和云目录(例如:微软的 Active Directory 或 LDAP)应该同步(图 1 中的“2”)。这使得无论身份在哪里创建或使用,都可以一致地管理身份和关联的凭据
- 本地实例是为身份提供单一权威来源的主实例,这将降低由于人为错误和配置复杂性而带来的安全风险。从最终用户的角度来看,这为访问云和内部资源提供了单点登录(SSO)体验,解决了管理多个 id 和密码的常见问题
- 在企业身份管理系统中维护的基于角色的访问控制( RBAC )机制(图 1 中的“3”)是一种授权系统,它将对资源的访问限制在授权用户。它是这样工作的(尽管这是一种简化):角色通常被创建来代表工作职能;权限被分配给角色以执行各种操作;然后,用户/员工通常被分配到组,这些组又被分配到角色。这创建了一个有帮助的间接层:用户没有被分配权限,而是通过成为角色的成员来获得权限。现在,用户权限的管理得到了简化,因为它只需要为用户/员工的帐户分配适当的角色。
第二,一种零信任安全方法(图 1 中的“4”)规定创建的资源没有访问权限,除非提供明确的身份验证和授权,否则在企业的云租用中无法访问任何资源。零信任体系结构使用身份凭据和设备声明/信息(例如,IP 地址)来对用户进行身份验证,并验证访问企业云租户中的数据和应用程序所需的授权。这样,基于身份的安全性提供了实现零信任策略所需的基本功能。****
第三, " 零泄漏 " 政策规定数据不能以任何方式在企业云租用之外传输。该策略将阻止有权访问敏感数据的员工或有权访问敏感数据的恶意代理让数据离开企业云租户或从企业云租户中泄漏。根据我的经验,可以使用“安全门户”(图 1 中的“5”)来实现零泄漏,该门户充当数据科学家用来访问云租户的视口。门户允许对云进行相对完整的访问,但禁用了允许数据移动的特定功能(通常是“剪切-粘贴”和下载的功能)。Citrix 有许多产品支持这一点,Microsoft(远程桌面)和 VMWare (Horizon View)也是如此。
最后,为连续的 " 配置漂移监控 " (图 1 中的“6”)建立策略是至关重要的。管理众多云组件非常复杂,管理它们的安全性更是难上加难。而且,不管你喜不喜欢,熵最终会以意想不到的方式改变你的云配置。监控企业的云租赁并标记您的团队或云供应商所做的任何意外配置更改,可确保任何网络安全漏洞在造成重大损害之前被发现并纠正。

Photo by Donald Giannatti on Unsplash
走向安全的人工智能/机器学习
回到我最初的主张:AI/ML 工作负载向云的企业迁移是必然的。但是必须承认,这带来了新的严重的安全问题,使得企业对这种迁移持谨慎态度。
但是企业并不是一成不变的。他们的回应是:
- 迁移到基于身份的安全方法,该方法使用身份和相关的认证和授权来确定访问权限
- 向“零信任”策略发展,该策略规定,除非提供明确的身份验证和授权,否则在企业的云租赁中不能访问任何内容
- 实施工具和控制以建立“零泄漏”策略,这样,除非明确批准,否则任何信息都不能泄漏企业云租赁
- 监控配置漂移从而降低意外安全漏洞的风险
AI/ML 似乎已经成为改变企业传统上谨慎的安全姿态的先决条件。有趣的是,虽然解决这些安全问题将加速 AI/ML 工作负载向云的迁移,但还有许多其他非 AI/ML 云项目受到相同安全限制的阻碍,现在将被解除这些限制。
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
走向社会数据科学

数量越多,责任越大
将社会科学和数据科学结合起来并不是一种新的方法,然而在经历了几次曝光之后(以及巨额罚款)大型科技公司开始意识到自己的处境。似乎研究机构,尤其是欧洲的研究机构,很乐意促进这种转变。本文是(1)数据科学的广义定义;(2)快速浏览社会数据科学;(3)从表面上看,相对而言,社会数据科学学科目前有多新。
1.广义定义的数据科学
让我们首先考虑什么是数据科学,然后继续解释为什么添加了社交的这个新术语是有用的。作为一个简短的免责声明,我并不是说数据科学对社会问题一无所知,不是社会性的或有重要的见解。相反,它是一个特殊的研究领域,可以与其他学科互补或混合。
数据科学 是运用科学的方法、流程、算法和系统,从结构化和非结构化数据中提取知识和见解的多学科领域。
It 可以更具体地定义为拥有三种互补角色的强大技能组合的人:
- 专家分析师
- 机器学习工程师
- 统计员
然而,研究工程和数据科学家都可以使用。艾伦·图灵研究所似乎跨越了这两种模式。
今年早些时候,一些作者在的《走向数据科学》中提出了一个关于数据科学中模糊性和解释的关键问题。托马斯·尼尔德认为它需要被分解成专门的学科。Cassie Kozyrkov 认为数据分析中存在心理陷阱,导致了解释问题。我很感兴趣地看到两篇文章使用了相同的罗夏测试图像——墨迹测试感知。

Two of my favourite authors writing about ambiguity in data science
凯西的观点尤其引人注目:“你确定你最近的数据顿悟不是伪装的 apop hany(T1)吗?” Apophenia 暗指人类普遍倾向于在随机信息中寻找模式。她认为大脑处理墨迹就像处理数据一样,一旦你获得了“洞察力”,你将很难不去发现它。
出于某种原因,罗夏测试经常被质疑为伪科学和不科学。事后看来,拍一张整洁的照片,带给不同的人,并用它来诊断问题似乎是一个相当严重的错误。多年来,这种方法被用于从法庭到精神健康机构的各种场合,有时会产生广泛的负面后果。我们喜欢整洁的图片,然而它们并不总是给人以正确的印象。
2.社会数据科学
让我来陈述一个显而易见的事实:数据科学与社会科学有着不同的关注点。有一个巨大的研究领域是大多数计算机科学家不会学习或关注的。培养计算机工程师或程序员的技能需要时间和大量的努力,这个领域有各种子领域,但是它有传统可能不同。
社会科学是一个学科门类,关注社会和社会中个人之间的关系。社会科学作为一个整体有许多分支。这些社会科学包括但不限于:人类学、考古学、传播学、经济学、历史学、音乐学、人文地理学、法学、语言学、政治学、心理学、公共卫生和社会学。
在 7 月 26 日发表的另一篇名为《人工智能和数据科学的十大角色》的文章中,她再次引用了凯莉的话,将社会科学家列为第八位:
“我们没有意识到社会科学家有多么有价值。他们通常比数据科学家更有能力将决策者的直觉和意图转化为具体的指标。”
谷歌首席决策情报工程师凯西·科济尔科夫
**然而,她的观点似乎是基于对编程一无所知或知之甚少的社会科学家,意在作为一种扩充工程团队的方式。然而,这让我们想到了社会科学和计算机科学的结合。
艾伦图灵研究所(ATI) 是英国国家数据科学和人工智能研究所,成立于 2015 年。它是以艾伦·图灵的名字命名的,艾伦·图灵是英国数学家和计算机先驱,通常被认为是计算机科学的创始人之一。计算机科学是研究与数据交互的过程,可以用程序的形式表示为数据。**
ATI 的一个研究领域是社会数据科学。他们试图通过两个主题来解决与大量数据相关的挑战:(1)在不同的社会和时间尺度上发展人类行为的基础理论;(2)确定方法上的挑战和解决方案,使社会数据科学能够在关键应用领域提供稳健可信的结果。
其目标是:
- 培养足够数量的社会科学家、数据科学家和社会数据科学家
- 通过学术、商业、非政府组织和政府利益相关者的定期会议,与数据基础设施和培训投资及政策制定者建立关系。
据我所知,目前有三所大学开设了理学硕士课程。一个是牛津大学,伦敦政治经济学院,哥本哈根大学。哥本哈根大学网站上对社会数据科学的描述如下:
社会数据科学是一门结合了社会科学和计算机科学的新学科,其中大数据的分析与社会科学理论和分析相关联。
与社会数据科学相关的研究领域很多。它们可以基于从例如社交媒体收集的数字数据、注册数据、客户数据或者基于人们留下的其他类型的数字痕迹,例如通过他们个人使用互联网、他们使用智能电话和其他数字服务。这些庞大的数据集也可以与通过人类学实地工作等收集的定性数据相结合。
–哥本哈根大学社会科学教员检索到 7 月 19 日
3.社会数据科学的学科有多新?
截至 2019 年 7 月 19 日,维基百科上没有关于该主题的页面。

在我写作的时候,只有一篇关于媒体的文章提到了社会数据科学,我可以通过搜索找到。这篇文章是去年写的,现在关于这个话题的文章可能比我想象的要多得多。

Picture taken the 19th of July 2019
将数据科学与社会科学的理论相结合的想法并不一定是一种新的方法。然而,计算机科学和社会科学以这种方式的结合也许可以说代表了一种有趣的新形式——值得探索。
这是第 500 天的第 47 天
什么是#500daysofAI?
我在挑战自己,写下并思考未来 500 天的人工智能话题。一起学习是最大的快乐,所以如果你觉得一篇文章引起了你的共鸣,请给我反馈。感谢您的阅读!
走向跨包容的人工智能
性别二进制算法的问题是
人工智能像设计它们的人一样“思考”——对性别有一种二元的、非规范性的概念。他们排斥变性人,强化性别陈规定型观念。更糟糕的是,世界各国政府花费数十亿美元将顺式性别歧视人工智能扩展到政府机构等新行业和图像识别等新应用,而很少考虑它们的性别影响。计算机科学界、技术界和政府机构应该对他们算法的性别影响承担更多责任。他们需要学会使用酷儿和跨性别理论来分析算法的性别影响,然后将这种学习应用于社会中人工智能算法的设计、部署和监控。
背景
人工智能算法通常是两种类型之一:机器学习算法或专家系统。机器学习是人工智能的一个子领域,算法从训练数据中学习以做出决策。该领域的三位先驱,Yann LeCun、Geoffrey Hinton 和 Yoshua Bengio 最近因他们的工作获得了图灵奖。这证明了机器学习算法在图像识别、无人驾驶汽车和语言翻译等众多应用中的强大功能。专家系统是更简单的算法,由领域专家创建的 if-then 规则组成。例如,由医生创建的算法可以执行以下规则"如果患者显示 X 和 Y 症状,则进行 Z 干预"。
我对以性别作为输入或输出的机器学习算法感兴趣。这里有两个例子:
自动性别识别(AGR) —输入是某人的图片、视频或社交媒体帖子。输出是他们预测的性别,问题是只限于男性或女性。
脸书的广告推荐算法 —输入是用户的个人资料,包括他们的性别身份。输出是一个脸书新闻提要广告。
性别歧视 AI——性别输出
自动性别识别是顺性别歧视和跨性别歧视。顺性别歧视是一种假设,即某人出生时分配的性别与其性别认同相匹配,并且性别认同不会随着时间的推移而改变。ARG 的顺性别歧视排斥跨性别者和性别酷儿,强化了“真正的”男人和女人的性别刻板印象。 自动性别识别不应该做 。跨性别者和性别酷儿的认同向我们表明,性别既不是由性别决定的,也不是二元的,更不是不可改变的。假设其他暴力抹去这些群体的经验。
对看起来不像“真正的”男人或女人的人的压迫——无论他们是否认为自己是跨性别者——是他们与人工智能定期互动的一部分。例如,在同工同酬日,柏林运输公司(BVG) 向“真正的”女性提供机票折扣。BVG 指出,“在柏林乘坐地铁、公共汽车或电车的女性将比男性少支付 21%的费用……这是为了突出德国日益扩大的性别薪酬差距。”BVG 试图让人们意识到德国严重的薪酬差距,却忽视了跨性别和性别不合群的人。BVG 的工作人员被授权对乘客的性别身份做出决定,这是他们本不该拥有的权力。如果一名跨性别女性因为 BVG 的工作人员不相信她的性别身份而被拒绝打折机票,会怎么样?现在想象一下,不是 BVG 的员工来做这些关于性别身份的决定,而是一台相机和一个人工智能算法。整个柏林的火车站都安装了摄像头来进行面部识别。一个人工智能算法现在有权决定任何在柏林乘坐公共交通工具的人的性别身份,这是一个非常可怕的想法。一个可能的跨性别替代方案是向自我认定为非独联体男性的人发放折扣票,这将使人们意识到独联体男性与其他性别之间的薪酬差距。当然,一些独联体国家的人会滥用这一制度,但跨性别的薪酬差距信息将会清晰响亮。
一般来说,人工智能算法不应该对性别身份做出决定。使用性别作为人工智能算法的输出是不科学的,因为性别身份是在个人的权威之下。这不是看身体或外在表情就能决定的。如果一个组织需要知道某人的性别身份,他们应该问,而不是推断。
性别歧视人工智能——性别输入
脸书广告算法有提供基于自我认同的性别的歧视性广告的历史。其中一个例子是脸书算法拒绝女性观看在线招聘广告。然而,脸书算法并不是唯一一个使用性别输入做出性别歧视决定的算法。有一种广告牌广告算法,它使用隐藏的摄像头来猜测路过的人的性别,然后向他们提供广告。被认为是男性的人会收到比萨饼的广告,而被认为是女性的人会收到沙拉的广告。将性别化的输入纳入人工智能算法,更有可能做出顺性别歧视和性别歧视的决定。
由于上面的例子,还不清楚是否有一种负责任地使用性别输入的方法。也许我们可以找到一种方法,负责任地使用性别身份来提高一些算法的能力,而不会对女性、跨性别者和性别酷儿造成伤害,但也许不会。当然,唯一有效的性别输入是打破 M 或 F 性别二元结构的自我识别的性别。我们需要回答的问题是“性别输入是提高了算法性能还是仅仅延续了性别刻板印象?”
用人工智能缩放性别歧视
我们正在通过扩大人工智能在社会中的作用来克服顺性别歧视,同时忽略它的偏见。由于在公共和私营行业的广泛使用,AI 算法在社会上越来越普遍。美国、中国和其他国家的政府每年花费数十亿美元资助人工智能的研究和开发。杰出的人工智能研究者吴恩达称之为下一个电力时代,科技行业正等待人工智能将世界变得更好。然而,人们很少意识到人工智能系统如何对跨性别者、同性恋者和异性恋者产生异规范效应。
现在很多行业都在使用人工智能。临床决策支持系统被医生用于医疗保健中的一系列任务,自动决策系统被市政府用于预测刑事再犯和进行预测性警务。这一趋势只会继续,因为机器学习研究人员正在扩展算法的能力,像亚马逊网络服务(AWS)和谷歌云平台(GCP)这样的云计算平台正在让非专家更容易使用人工智能系统。部署人工智能算法所必需的人力资本正在增长。
唐纳德·特朗普(Donald Trump)最近签署了一项行政命令,建立了“美国人工智能倡议——这将要求联邦机构向人工智能(AI)研究、培训和推广投入更多资源”。对行政命令最大的批评?它没有足够的资金来跟上中国、韩国和加拿大的人工智能项目,这些项目涉及数亿美元的多年战略。
我们必须承认人工智能不断扩大的作用。人工智能算法不再是政治中立的。他们做出的决定会对社会产生巨大而复杂的影响,可能会产生性别偏见,特别是对跨性别和性别不一致的人。研究、设计和使用人工智能算法的人必须理解这一点,这样他们才能负责任地推动人工智能在社会中的应用。
怎么修
人工智能系统的透明使用。人工智能算法的设计者声称的“商业秘密”和普遍缺乏公开披露阻止了公众、记者和学者探索人工智能算法的性别影响。最迫切需要这种透明度的是公共机构使用的自动决策系统。NYU AI Now 部门的一个团队设计了一个算法影响评估,为公共机构负责任地使用人工智能算法提供了一个框架。
重视跨知识。我们需要解决创建、使用和部署人工智能算法的社区中预先存在的性和性别观念。例如,设计 AGR 算法的人机交互研究人员分享了他们算法的性别歧视观点。从广义上讲,有影响力的人工智能社区包括机器学习研究人员、数据科学家和技术高管,所有这些人都主要由顺式性别男性组成,他们通常对性别有二元概念。为了使人工智能系统的专家审计有效,审查算法的人必须了解机器学习/人工智能的技术方法和跨性别观点。两个领域都有专长的人很少。这里有一个关于跨性别观点的简短阅读列表,可能有助于分析人工智能算法的性别影响:
1.让我们从出生证明上删除性别身份
4.边飞行边运输
致谢
我要感谢 Davy Knittle 在撰写这篇博文中发挥的核心作用。他在跨性别研究方面的专业知识以及对人工智能和性别话题的兴奋使这篇博文成为现实。
走向幸福,数据科学(第 1 部分)

Credit: EUFIC
我用我的苹果健康数据来衡量我目前的状态,并设定未来的健身目标。
在过去的几周里,我一直好奇如何在自己的生活中使用数据。在我的日常工作中,我使用数据来帮助在企业环境中做出更好的决策,所以我想,为什么不使用我当前可用的数据来设定更健康生活的指标和目标呢?
在这些系列中,我将经历 A .介绍,b .探索数据 c .分析&绘图,d .测试,e .结论。
A.介绍
苹果健康
这是什么?这是苹果提供的描述:
健康应用程序可以轻松了解您的健康状况,并开始实现您的目标。它整合了来自 iPhone、Apple Watch 和您已经使用的第三方应用程序的健康数据,因此您可以在一个方便的地方查看您的所有进展。它还推荐了其他有用的应用程序来完善你的收集——让你的健康变得前所未有的简单。
健康应用程序可以更容易地跟踪你的健康和健康数据,集中在四个方面:活动,睡眠…
www.apple.com](https://www.apple.com/ios/health/)
动机
我目前有一部 iPhone X,附带苹果健康应用。它还有健康记录 API,您可以连接到它并从中提取更多有趣的数据,但是出于各种目的,我们将在本文中使用一个更简单的方法。
据我所知,苹果健康也包含在以前的 iPhone 型号中,所以如果你有一个旧版本的手机,你不会被排除在外。此外,如果你有一个苹果手表,你就有了额外的指标,如:心率监测、心电图、跌倒检测、生命体征、血压等。
苹果健康应用程序有交互式可视化功能,可以查看你的数据,所以我这么做主要是为了自娱自乐。我必须说,它缺乏工具来拥有一个聚合视图,所以我想我可以使用一些 python 库来可视化我当前的表单。
下载数据
在转换数据之前,您需要从 Apple Health 文件中导出数据文件。虽然有几种方法可以做到这一点,但我用电子邮件给自己发送了数据导出。为此,只需在手机中导航:苹果健康>健康数据>个人资料图标>导出健康数据
为了转换数据,我使用了 markwk 的“苹果健康提取器和数据分析”工具。更多信息见链接:
https://github . com/markwk/QS _ ledger/tree/master/apple _ health
markwk 代码的第一个脚本允许您将 XML 文件转换为 CSV,我将它加载到 Jupyter Notebook 中:
# %run -i ‘apple-health-data-parser’ ‘export.xml’
%run -i ‘/Users/stephenhyungilkim/qs_ledger-master/apple_health/apple-health-data-parser.py’ ‘/Users/stephenhyungilkim/apple_health_export/export.xml’

该脚本将代码分成几个部分,包括:
身高、体重、步数、步行距离、跑步、燃烧的积极能量、飞行攀爬、锻炼数据。
B.探索数据
任何数据分析项目的第一步,我们必须寻求理解数据的不同维度以及文件包含的内容!先说其中一个特点,步骤:
steps = pd.read_csv("/Users/stephenhyungilkim/apple_health_export/StepCount.csv", parse_dates=["startDate"], index_col="startDate")
steps.describe()

figure 1
这给了我们一些关于数据的一般统计。例如,我们可以看到有 6833 个“步”的实例,平均值是 374 步…但是推荐的平均值不是每天 10,000 步吗?😮
steps.tail()

figure 2
在图 2 中,我们可以看到我在导出之前的最新数据。我们可以得出的一些信息是,数据源来自我的 iPhone 设备’,我们也有值。不过,我开始为自己辩护,因为数据似乎表明我非常懒惰。一天只走 34 步可能吗?
然后,我意识到 34 步并不是一天的总数,因为“开始日期”在同一天内有多次。我回到我的手机上查看我那天的总步数,令我欣慰的是,它超过了 34 步。
len(steps)
这再次证实我们有 6833 项记录。
steps.columns

figure 3
在图 3 中,我们可以看出有 8 个特性,但是对于我们的时间序列用例,我们可以保留'值和'开始日期,并删除所有其他的特性(我将在更深入的研究后马上这么做)。
steps.value.sum()

figure 4
图 4 显示了我们在给定范围内采取的所有步骤的总和。10,000 步大约相当于 5 英里,所以你们可以算一下。这可能看起来很多,但是请记住,对于健康来说,每天的数字比总和更重要。每天都要踩这些台阶,对吧?
steps.value

figure 5
图 5 开始看起来有点像时间序列,其中我们有一个数据和值。这是有希望的,似乎是可以策划的。我确实意识到,如果我想要一个每日视图,我将需要每天进行聚合,而不是使用 startDate 特性。正如我们之前提到的,我们仍然需要去掉其他特性。
steps_new = steps.drop(['sourceName','sourceVersion','device','type','unit','creationDate','endDate'], axis=1)
上面的代码从数据帧中删除了不必要的特性。
type(steps_new)

figure 5
为了让我们处理时间序列,我们需要相应地修改数据。上面的代码向我们展示了我们正在处理什么类型的数据。请注意,当我使用' read_csv '时,我确保' startDate '是日期时间(不是字符串或任何其他值),并且' startDate '是索引列。
其他维度
因为还有 6 个维度,所以我迭代相同的代码来理解数据。考虑到我的身高保持不变,像“身高”这样的一些特征看起来并不令人兴奋。为了保持连续性,我将继续探索这个步骤的维度。
C.分析和绘图
虽然有几个有趣的列,但我们应该主要关注“值”和“开始日期”。这些将是我们的线图的轴,所以请查看我的“健康”的时间序列表示。
steps_new.plot()
plt.title('How Many Steps Has Stephen Taken?')
plt.ylabel('Steps')
plt.xlabel('Date')

figure 6
这是一个有趣的第一个图…我们可以看到从 10 月到 11 月中旬的巨大活动。我立刻有了一些初步的想法。那段时间比较暖和,当我导出数据时,我确实注意到它正在从三四个来源检索数据。我的 iPhone,我的高尔夫 GPS 应用程序,我的 nike run 应用程序,我的 Fitbit,直到它坏掉。我最初的想法是,在那几个月里,我更多地使用了所有这些设备,因此我看到了峰值。
我的第一部分结论是:
第 1 部分到此结束。在第 2 部分中,我将更深入地研究这个情节,讨论时间序列的考虑因素,并在我们的数据中使用一个叫做 ARIMA/博克斯詹金斯方法的模型。我还会谈到时间序列因素,如趋势、季节性、均值和方差。
对我的朋友 WH 大声喊出来,是他启发了我去做这件事!虽然我确实想公开他的名字以保护他的隐私,但他之前的数据探索,包括使用 python 绘制他在纽约最常去的地方的地图,以及使用苹果公司的“屏幕时间”应用程序监控他的数字福祉,都激励我将数据很好地用于我自己的个人生活。
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
走向幸福,数据科学(第二部分)

Credit: EUFIC
请参考(第 1 部分)来看看我们在前面的故事中涵盖了什么。
我用我的苹果健康数据来衡量我目前的状态,并设定未来的健身目标。
towardsdatascience.com](/towards-well-being-with-data-science-part-1-7f8035f73aa)
现在…我们说到哪了?
上次,我们停止了用 matplotlib 可视化数据。我们还讲述了一些介绍性的材料,探索了表层的数据,并借助可视化开始了更深入的分析。我们注意到有 6 个不同的特征可以分析,但是我们决定把重点放在“步骤上,因为它更容易衡量,也更有趣。
在《迈向幸福》的第 2 部分,我们将从数据科学出发,继续我们的旅程,解决 C 分析和绘图(续)、d 测试和 e 结论。
C.分析和绘图(续)
答看完上一张图表后,我意识到我必须重新采样数据。为什么,你会问吗?还记得我提到过“start date”不是一个每日集合,而是每当设备检测到我的运动时创建的吗?这意味着每天测量的步数是不一致的。
以下代码将其重新采样为每日格式:
steps_new = steps_new.resample('D').sum()steps_new.head()
现在,如果我们再看,我们可以看到这是一个日常视图。这确保了我们每天都有一致性,以做出公平、公正的比较和更准确的绘图。

figure 1
我还想检查是否有重复的数据。接近 40,000 步对我来说似乎有点可疑…
steps.sourceName.unique()
测绘
让我们再画一次。
steps_new.plot()
plt.title(‘How Many Steps Has Stephen Taken?’)
plt.ylabel(‘Steps’)
plt.xlabel(‘Date’)
plt.figure(figsize=(12,8))
我擅自改变了风格。我是 fivethirtyeight 的忠实粉丝,他们在 matplotlib 中有一种风格可以选择。注意我之前的图和这张图在风格上的不同:
plt.style.use(‘fivethirtyeight’)

figure 2
图 2 是我所有数据的图表。只做 2018 年的怎么样?
steps_new[‘2018’][‘value’].plot()

figure 3
将数据分成 2018 年和 2019 年有助于我理解数据中的峰值。我能够“放大”数据集的特定部分。例如,在 2018 年的 10 月和 11 月,天气很好,所以我花了更多的时间在外面做运动,比如慢跑和散步。
我怀疑假期在年底占据了我的大部分时间,这意味着我锻炼得更少了,也不太“灵活”。至于 8 月之前的数据,我在 8 月购买了 iPhone,因此没有该月之前的数据。
2019 年至今怎么样?
steps_new[‘2019’][‘value’].plot()

figure 4
更多分析
对于 2019 年,我在 2 月底和 3 月初之间旅行,所以作为一名游客,我走了很多路,并反映在图表中!查看之前日期的天气信息并将其映射到我的步骤会很有趣(这需要一点工作,因为我必须获取每个位置和日期的天气数据…所以可能在不久的将来当我感觉更有效率时:P)。
通常,有三种类型的时间序列结构:单变量、外部回归和多变量。在我们的例子中,它是单变量的,因为我们有一个带时间戳的数字向量,我们的预测模型将基于历史数据,以查看我采取了多少步骤。我们正在处理时间戳/索引和有序的单变量数据,因此我们可以应用时间序列模型进行预测,因为它有特定的顺序。
时间序列分析
既然我们已经确定我们的数据集适合于时间序列分析,我们需要确定一些特征。这四个特征有助于我们在建模之前确定使用哪个模型以及执行哪些步骤。
季节性:如果我在夏季看到同样的高峰,而在冬季看到较低的活动,我敢说存在季节性,但鉴于我只有> 1 年的数据,我想假定事实并非如此。从逻辑上讲,我会在春天和夏天多走路是有道理的…
趋势:我看不出有什么趋势。线图中没有真正的向上或向下移动。这意味着我们有一个恒定的平均值,这是缺乏趋势的结果,而不是水平的变化。
可变性:是与均值的偏差,数据集中没有一致性。如果我们拆分数据集,您可以说 2019 年低约为 5,000,高约为 20,000,2018 年低约为 0,高约为 25,000。
平均值:平均值似乎在 10,000 步左右,我们将在应用平滑器时对此进行更多探索。
D.测试
一旦我们深入研究了特征,我们需要看看时间序列统计:自相关(ACF 和 PACF 图)和平稳性(增强的 Dickey-Fuller 测试)。为了分析这些统计数据,我们将进行一些测试。
平稳性
现在,我们将执行扩展的 Dickey-Fuller 测试来测试平稳性。记住,平稳性回答了这个问题:数据在整个时间序列中具有相同的统计特性吗?方差,均值,自相关?ADF(单位根测试之一,还有其他几个)非常强大,因为它消除了自相关并测试平稳性。
让我们进行测试:
# Test for Stationarity
def stationarity_test(timeseries):
""""Augmented Dickey-Fuller Test
Test for Stationarity"""
from statsmodels.tsa.stattools import adfuller
print("Results of Dickey-Fuller Test:")
df_test = adfuller(timeseries, autolag = "AIC")
df_output = pd.Series(df_test[0:4],
index = ["Test Statistic", "p-value", "#Lags Used",
"Number of Observations Used"])
print(df_output)
分析结果。如果 p < 0.05,则静止。测试统计、p 值、使用的滞后=过去多长时间
stationarity_test(steps_new)

figure 5
p 值确实小于 0.05,因此我们的数据集是稳定的。
自相关
自相关回答了这样一个问题:早期的观察会影响后期的观察吗?为了验证这一点,我们使用了 ACF 和 PACF 图。
ACF 和 PACF
ACF 显示滞后之间的自相关。PACF 对所有早期的滞后进行了调整,因此,我们看到了两个图表之间的差异。蓝色区域是置信水平界限。CI 外的标记暗示自相关。95%的信心。
# Classic ACF and PACF Plots for Autocorrelation
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf# Autocorrelation and partical autocorrelation in the Steps dataset
# Two plots on one sheet
%matplotlib inline
fig = plt.figure(figsize=(12,8))
ax1 = fig.add_subplot(211)
fig = plot_acf(steps_new, lags=20, ax=ax1)
ax2 = fig.add_subplot(212)
fig = plot_pacf(steps_new, lags=20, ax=ax2)

figure 6
没有多少数据集在突出显示的蓝色区域之外。这很好。
预言;预测;预告
我应用平滑器来消除数据中的一些巨大尖峰,这是预测之前的。请注意,数据集现在变得更加“平坦”:

figure 7
我们将使用自回归综合移动平均模型进行预测。我邀请您在此了解更多信息:
https://machine learning mastery . com/ARIMA-for-time-series-forecasting-with-python/
python 包“statsmodel”使我们很容易使用它,但你仍然必须知道如何正确选择参数。对于我们的数据集,我们将研究两种不同的 ARIMA 模型,并对它们进行比较。ARIMA 模型为您提供了模型诊断和预测功能。
以下是我的模型的诊断:
# ARIMA Model Setup
from statsmodels.tsa.arima_model import ARIMA
# Model Diagnostics
results_AR.summary()

figure 8
AIC 和 BIC 都是模式选择和比较的标准。点击此处阅读更多内容:
[## AIC 对 BIC
我经常用 AIC 和 BIC 这样的合适标准来选择模特。我知道他们试图平衡良好的契合度与…
www.methodology.psu.edu](https://www.methodology.psu.edu/resources/aic-vs-bic/)
因为我们的数据是每月一次,所以我们来预测未来 5 个月的情况:
# ARIMA forecasts
# Setting up
model_AR4 = ARIMA(steps_new, order=(4, 0, 0))
results_AR4 = model_AR4.fit()# model 1
Fcast400 = results_AR4.predict(start = ‘08/19/2018’,
end = ‘08/19/2019’)# setup 2
# Arima(2,0,2) model and its fitted values
model303 = ARIMA(steps_new, order=(3, 0, 3))
results_M303 = model303.fit()# model 2
Fcast303 = results_M303.predict(start = ‘08/19/2018’,
end = ‘08/19/2019’)
形象化
# Comparing the forecasts via data visualization
plt.figure(figsize = (12, 8))
plt.plot(steps_new, linewidth = 2, label = “original”)
plt.plot(Fcast400, color=’red’, linewidth = 2,
label = “ARIMA 4 0 0”)
plt.plot(Fcast202, color=’blue’, linewidth = 2,
label = “ARIMA 3 0 3”)
plt.legend()

figure 9
这两个模型的预测似乎都表明,在接下来的 5 个月里,我将徘徊在 10,000 步以上。现实是,数据会更加不稳定,但我很高兴看到我在现实生活中有多接近/远。
E.结论
你可能会说,好吧,那又怎么样?通读这些很酷(或者不是!哈哈),但这怎么是迈向幸福的一步呢?
幸福是每个人个人的、持续的追求,我只分析了幸福的几个组成部分中的一个特征。在这个练习中,我的希望是在我的锻炼计划中增加目标,让自己负起责任。然而,我希望我能把我自己放在一些不同的衡量标准中,以看到进步、持续的健康和繁荣。
我认识到它的局限性,但我并不打算概括说幸福仅仅是由锻炼组成的,更不用说采取措施了。心理健康、财务健康、社会福祉、精神繁荣、营养等等都是等式的一部分。除了运动之外,还应该考虑冥想、睡眠、正念等活动。
我对这个过程做了很多改进。例如,我可以将我过去的数据与天气进行映射,并在那里看到相关性。这可能有点棘手,因为我还必须考虑每个日期戳的位置。
量化情绪、压力等无形因素,以及饮食(热量摄入、宏指令)、水摄入和睡眠时间等有形因素,也可以影响和补充预测。我提到的一些数据源现在很容易获得,但仍然是分散的,还没有找到一个设备来捕获所有这些数据。构建一个全面的、可定制的仪表板也会很有趣。
使用大数据和利用云计算来获得更多宏观分析也是非常有趣的。除了个性化体验,看到总体趋势将是有益的。
这让我不得不说…谢谢你阅读,我邀请你自己尝试这段代码!需要考虑的一些警告是:
位置和生活方式:这两个因素的数据会有所不同。有些人走路多,而有些人开车多。一个简单的例子是纽约对洛杉矶。通勤模式不同,这只是一个方面。
设备:我用的是 iPhone,但 Fitbit、Apple Watch、Garmin 和其他设备追踪的指标更全面。
追寻艾的足迹
现代人工智能的旅程,从小说到科学

Photo by Tim Swaan on Unsplash
人工智能在我们的想象中已经存在了很长时间。机器人是潘多拉等古希腊神话的核心。犹太文化中有这些神秘的魔像。令人惊叹的卡拉库里娃娃在日本传统中占有重要地位。
在 17 世纪,一些哲学家认为应该把思想放入物质中。他们提出了各种理论。勒内·笛卡尔相信精神和身体的二元论。他的观点否定了智能机械化的可能性。
莱布尼茨有不同的观点。他认为人类所有的思想都可以用几个基本符号进行数学表达。为此,他提出了逻辑字母表的特征普遍性。
从不记得的时代起,人工智能和机器人就出现在小说中。说到几个,一个实验室制造的生物是玛丽·雪莱的弗兰肯斯坦的核心。 R.U.R. (Rossum 的万能机器人)于 1921 年首映,将“机器人”一词引入文学。
这为 AI 奠定了哲学基础。现在,让我们谈谈使人工智能发生的具体科学工作。这样具体的历史来自“新”时代。这个领域是在 1956 年才建立的。著名的图灵测试是在 1950 年提出的。说到这里,让我们开始吧。
该设置
与人工智能相关的科学工作在 20 世纪 50 年代和 60 年代突然兴起。这是由一些先前的作品建立起来的。伯特兰·罗素和阿尔弗雷德·诺斯·怀特海于 1913 年出版了《数学原理》。大约同一时间,乔治·布尔提出了他的 思想法则 。这些奠定了数理逻辑的基础。
真正的交易始于一个 15 岁的离家出走的男孩冲进鲁道夫·卡尔纳普的办公室。卡尔纳普已经是一位有影响力的哲学家了。那时,他在芝加哥大学教书。他曾出版过 语言的逻辑句法。这个男孩未经允许就进来指出了这篇作品中的错误。鲁道夫肃然起敬。这个男孩很特别。他甚至没等介绍自己。经过几个月的寻找,鲁道夫终于找到了那个在大学里游荡的无家可归的男孩。
小沃尔特·哈里·皮茨是他的名字。三年前,他起草了一封给伯特兰·罗素的信(是的,当时他 12 岁)。他指出了上述原则中的问题。拉塞尔印象深刻,邀请皮茨去读研究生。但那时,他正在英国剑桥大学教书。沃尔特住在美国的底特律。
所以当罗素加入芝加哥大学时,我们的孩子做了决定,来加入他。他没有在那里注册为学生。即便如此,沃尔特还是获得了认可。很快,他参加了大学的讲座。
沃尔特的生活非常有趣。我会再写一篇文章来讨论这个问题,这样我们就不会离题太远了。
回到船上,1942 年,沃尔特·皮茨遇到了沃伦·麦卡洛克。麦卡洛克邀请皮茨去他家做客。他们相信莱布尼茨的理论允许所有人类思想的机械化。因此,他们试图为人类神经系统的神经科学构建一个模型。他们在 1943 年发表了关于这个问题的开创性论文。他们将它命名为 “神经活动中内在思想的逻辑演算。这篇论文是对人工智能领域的无价贡献。他们提出了一个简单的模型,称为麦卡洛克-皮茨神经元。它仍然在每个机器学习课程中讲授。他们提出的想法是今天几乎所有先进人工智能的基础。**

Warren McCulloch (L) and Water Pitts (R). Image credits: https://www.timetoast.com/timelines/iinteligencia-artificial
诺贝特·韦纳的控制论和克劳德·香农的信息论出现在 1948 年。控制论是对“动物和机器中的控制和交流”的研究信息论是对信息的“量化、存储和交流”的研究。都影响了人工智能领域。
控制论提供了对生物和机械智能的直接研究。这个概念在未来被证明是无价的。信息论提供了基本的数学。
此后不久,艾伦·图灵于 1950 年提出了 T2 图灵测试。他描述了一种确定机器是否“智能”的方法简而言之,图灵测试是这样的:一个人同时与另一个人和一台机器对话。这个人必须识别出这两者中的哪一个是机器。如果人做不到这一点,机器就会通过“模仿游戏”。尽管图灵测试在现代系统中的应用范围太窄,但它在当时是一个重要的时刻。艾伦·图灵的名字使得这篇论文,以及这个领域更受欢迎。

The Turing Test. Image credits: wikipedia commons
1956 年,达特茅斯举办了一次会议。它的主要座右铭是探索智能化的概念。这些参与者后来成为人工智能领域最著名的人物。其中最重要的是马文·明斯基,他在 1951 年建造了第一台神经网络机器 SNARC。在接下来的几十年里,他将成为人工智能世界中最著名的名字。
克劳德·香农也出席了会议。未来的诺奖得主司马贺和艾伦·纽厄尔亮相他们的逻辑理论家它将继续解决罗素的《数学原理》中前 52 个定理中的 38 个。
约翰·麦卡锡也是人工智能的先驱之一,他提出了“人工智能”这个名字与会者表示同意。这就是人工智能的诞生。
河流,当它流动时(1956-1974)

Photo by Jon Flobrant on Unsplash

Semantic Net. Image credits: wikipedia commons
由于这次会议,人们对人工智能的兴趣增加了。有许多创新。纽维尔和西蒙在 1959 年创造了一个“通用问题解决程序”。理论上,它可以解决任何形式化的问题。James Slagle 创造了 SAINT(符号自动积分器)来解决大一的微积分问题。这些节目令人印象深刻。
自图灵测试以来,自然语言是人工智能的一个重要领域。丹尼尔·鲍勃罗的项目学生能够解决高中的文字问题。语义网的概念很快就出现了。它是不同概念以及它们之间关系的映射(如图)。几个成功的项目就是建立在这个基础上的。约瑟夫·韦森鲍姆在 1966 年创造了伊莱扎。它能够与人类进行真实的对话。
人工智能领域发生了这么多事情,研究人员有点太兴奋了,提出了这样的说法:
——Newell 和 Simon,1958:“10 年内,数字计算机将成为国际象棋世界冠军”。并且,“在 10 年内,数字计算机将会发现并证明一个重要的新数学定理。”
——h . a .西蒙,1965: “在 20 年内,机器将能够做任何人能做的工作。”
——明斯基,1967: “在一代人之内……创造‘人工智能’的问题将得到实质性的解决。”
——明斯基,1970: “三到八年内,我们将拥有一台具有普通人一般智力的机器。”

credits: gfycat.com
因此,该领域获得了大量资金。高级研究计划局(ARPA,后更名为 DARPA)向麻省理工学院的团队拨款 220 万美元。当时的 DARPA 主席决定他们应该“资助人,而不是项目!”发展了一种自由的研究文化。这使得研究人员可以从事他们认为正确的任何项目。
瀑布,当它落下时(1974-1980)

Photo by Štefan Štefančík on Unsplash
1969 年,马文·明斯基和西蒙·派珀特出版了他们的书,书名为。它强调了感知器的优势和劣势(神经网络的单体)。****
然而,他们的批评对联结主义领域来说是致命的。他们强调了感知器无法操作基本的异或电路。
因此,象征性人工智能的替代方法出现了爆炸性增长。但是,这种方法没有提供任何显著的结果。在 20 世纪 70 年代,人工智能研究人员显然对人工智能过于乐观。他们承诺的目标还没有实现,还有很长的路要走。
研究人员意识到他们有基本的限制。有计算上的限制。人工智能被应用于简单的问题。但是现实生活中的场景对系统来说太复杂了。这些算法要探索的可能性是天文数字。这就导致了组合爆炸的问题。然后,还有一个经典的问题“如何给计算机常识。”这就是常识推理的问题。
这让出资人很失望。人工智能的资金因此消失,研究停滞不前。由于法律修订,DARPA 不再允许黑客文化的研究。捐款人对人工智能领域变得冷淡。从 1974 年到 1980 年这段时间被称为“艾冬”。
复兴(1980 年至 1987 年)
日本政府在 1981 年对人工智能研究采取了强硬立场。它为其“第五代计算机项目拨款 8.5 亿美元。它以人工智能为中心。设想中的计算机可以交谈,翻译语言,解释图片,并表达类似人类的推理。

The WABOT-2. Credits: https://robots.ieee.org/robots/wabot/
日本的研究很有前途。1980 年,早稻田大学开发出机器人 WABOT-2 。它可以和人类交流。它还可以阅读乐谱和演奏电子琴。日本的成功促使其他政府和机构重新审视人工智能领域。
与此同时,联结主义领域重新出现。1982 年,Hopfield 给出了一种可以学习和处理信息的新型神经网络。杰弗里·辛顿和大卫·鲁梅尔哈特推广了反向模式自动差速器。这种技术是非凡的,至今仍是机器学习的关键。
与此同时,人工智能以“专家系统”的形式获得了商业上的成功。这些系统对特定主题有深入的了解。CMU 的人们在 1980 年建立了一个名为 XCON 的专家系统。它在数字设备公司使用。到 1986 年,它每年为公司节省 4000 万美元。

The PC revolution. Image credits: Seattle Business Journal, October 1981
不幸的是,第二个艾冬季(1987-1993)
在 20 世纪 80 年代末,另一场革命掩盖了人工智能领域的成功和发展。苹果和 IBM 同时生产越来越强大的电脑。个人电脑革命开始了。台式电脑比基于人工智能的 Lisp 机器更便宜,功能更强大。价值 5 亿美元的整个产业在一夜之间被摧毁。事实证明,人工智能在 XCON 机器等专家系统上的成功过于昂贵,难以维持。
专家系统出现了几个问题。他们无法学习。他们是“脆弱的”(也就是说,当给他们不寻常的输入时,他们可能会犯奇怪的错误)。他们成为几年前发现的问题的牺牲品。例如,这包括资格问题。专家系统的实用范围变得有限。
DARPA 的新领导层决定,人工智能不是“下一波”。他们将资金投向那些似乎更有可能产生立竿见影效果的项目。
1991 年,日本第五代计算机项目的目标没有实现。研究人员再次低估了他们的困难。
到 1993 年底,已有 300 多家人工智能公司关闭、破产或被收购。这有效地结束了 AI 的第一次商业浪潮。

Photo by Mervyn Chan on Unsplash
流动
个人电脑革命的迷雾开始消退。现在有了更多的计算能力。此外,随着个人电脑开始变得普遍,大型数据集变得可用。这些都有助于人工智能的发展。
我们正在解决之前强调的一些问题,打破限制我们的东西。随着计算能力的增强,我们正在挑战可能的极限。有了大型数据集,我们能够提取越来越多的知识。实用的人工智能算法开始变得有意义。
一种被称为“智能代理”的新范式在 20 世纪 90 年代被接受。智能代理是一个感知其环境并采取行动以最大化其成功机会的系统。人们希望有一天我们能够让这些智能代理相互交流。这将给我们带来更多功能和智能的系统。

Credits: Peter Morgan/Reuters
人工智能社区对在人工智能中使用数学有不同的看法。“scruffies”认为智力太复杂,不适合数学。他们认为我们人类很少在决策中使用逻辑。另一方面,“neats”认为用逻辑寻找最佳解决方案是未来的方向。
更新、更热门的人工智能版本使用了复杂的数学工具。这些数学算法获得了广泛的成功。Russell 和 Norvig (2003)因此称之为“neats 的胜利”
很快在 1997 年,IBM 的超级计算机“深蓝”打败了加里·卡斯帕罗夫。他是当时的世界冠军。纽维尔和西蒙所说的 1968 年将会发生的事情最终在 1997 年发生了。
今天下棋的计算机比任何人类棋手都强得多。人类达到的最高 Elo 评级是 2882。计算机引擎(即使是那些可以在你的电脑上运行的引擎)达到 3000 Elo 额定值是正常的。历史最高值超过了 3350 点。
2005 年,斯坦福大学开发了一种自动驾驶机器人。它赢得了 DARPA 大挑战。它沿着一条未经训练的沙漠小道行驶了 131 英里。

Image credits: https://www.wired.com/wp-content/uploads/blogs/geekdad/wp-content/uploads/2011/02/jeopardy-watson.jpg
2011 年 2 月,IBM 决定在“危险边缘”智力竞赛节目中测试其 IBM Watson。它以显著优势击败了两位最伟大的危险冠军。
随着互联网的发展和社交媒体的出现,数据量激增。科技公司需要对这些数据进行智能操作。因此,人工智能的应用成为一种必然。现在,谷歌使用机器学习对结果进行排序。YouTube 推荐使用 ML 算法的视频。亚马逊推荐你带 ML 的产品。脸书的新闻提要是 ML 生成的。事实上,Tinder 使用 ML 算法为你找到匹配。
随着这场人工智能的迷你革命,这项技术已经站稳了脚跟。它实际上是不可替代的。人工智能领域只需要展望超级机器的未来。尽管人工智能进步的影响仍有争议,但一场全面的人工智能革命是不可避免的。
用 tensornets 在 tensorflow python 中实现 YOLOv3

Spectacular architecture and a splendid view! source:https://pixabay.com/en/architecture-buildings-cars-city-1837176/
从对象检测到生成对抗网络 (GAN),深度学习显示了它的威力。物体检测从很好的老式人工设计的特征检测器发展到现在的基于深度学习的卷积神经网络(CNN)物体检测器,如 R-CNN、 YOLO 。使用 CNN 的检测通过预测对象的边界框坐标来近似图像中对象的位置,而分割通过预测图像中对象的边界来更进一步。在本文中,我们将逐步运行一个车辆检测网络,使用在 MS-COCO 数据集上训练的 YOLOv3,该网络可以检测大约 90 种不同类别的对象。有了这个网络,我们将能够检测和跟踪汽车,公共汽车,卡车,自行车,人和更多!要找到更多有趣的人工智能文章,请点击这里。
1。了解张量网
下载 YOLOv3 的暗网权重并让它在 tensorflow 上运行是一项相当繁琐的任务。但是我们两分钟后也要做同样的事情!你怎么问?
嗯,李泰勋先生将各种流行网络的权重转换成 tensorflow 的格式,并发布了一个名为“Tensornets”的 PyPi 库。Tensornets 使迁移学习和运行推理成为可能,只需“10 行”直观代码。
查看他的 Github 页面:https://github.com/taehoonlee/tensornets

Some of the models available in tensornets
2。装载 YOLO

You Only Look Once source:https://pixabay.com/photos/yolo-sparklers-new-year-1758212/
YOLOv3 是 YOLOv2 的改进版本,具有更高的精确度和地图得分,这也是我们选择 v3 而不是 v2 的主要原因。
让我们开始吧。
首先,我们需要安装“tensornets”库,使用方便的“PIP”命令可以很容易地做到这一点。“pip install tensornets”就可以了,但是你也可以从 GitHub 上下载来安装。在开始使用代码之前,请确保安装了 Tensorflow。
启动您最喜欢的 IDE 并导入 tensorflow 和 tensornets。除此之外,我们还需要 OpenCV 和 numpy 来帮助导入图像和视频。我们使用“时间”来监控网络处理一帧所需的时间。
import tensorflow as tf
import tensornets as nets
import cv2
import numpy as np
import time
一旦我们导入了必要的库,我们继续为网络和模型本身创建输入占位符。
inputs = tf.placeholder(tf.float32, [None, 416, 416, 3])
model = nets.YOLOv3COCO(inputs, nets.Darknet19)
这两行完成了加载权重和图形的繁重任务,“就两行”。
3。运行推断
现在是时候创建一个 tensorflow 会话并对视频进行推理了。下面几行定义了我们要跟踪的对象的类别和它们的 MS-COCO 索引。
classes={'0':'person','1':'bicycle','2':'car','3':'bike','5':'bus','7':'truck'}
list_of_classes=[0,1,2,3,5,7]#to display other detected #objects,change the classes and list of classes to their respective #COCO indices available in their website. Here 0th index is for #people and 1 for bicycle and so on. If you want to detect all the #classes, add the indices to this listwith tf.Session() as sess:
sess.run(model.pretrained())
cap = cv2.VideoCapture("D://pyworks//yolo//videoplayback.mp4")
#change the path to your directory or to '0' for webcam
while(cap.isOpened()):
ret, frame = cap.read()
img=cv2.resize(frame,(416,416))
imge=np.array(img).reshape(-1,416,416,3)
start_time=time.time()
preds = sess.run(model.preds, {inputs: model.preprocess(imge)})
4。结果
继续前进。一旦视频帧被传送到网络,它就会返回边界框并将其封装在“preds”对象中。现在,我们可以从“preds”对象中获取检测到的类及其坐标。
print("--- %s seconds ---" % (time.time() - start_time)) #to time it
boxes = model.get_boxes(preds, imge.shape[1:3])
cv2.namedWindow('image',cv2.WINDOW_NORMAL)cv2.resizeWindow('image', 700,700)
boxes1=np.array(boxes)
for j in list_of_classes: #iterate over classes
count =0
if str(j) in classes:
lab=classes[str(j)]
if len(boxes1) !=0:
#iterate over detected vehicles
for i in range(len(boxes1[j])):
box=boxes1[j][i]
#setting confidence threshold as 40%
if boxes1[j][i][4]>=.40:
count += 1
cv2.rectangle(img,(box[0],box[1]),(box[2],box[3]),(0,255,0),3)
cv2.putText(img, lab, (box[0],box[1]), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), lineType=cv2.LINE_AA)
print(lab,": ",count)
#Display the output
cv2.imshow("image",img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
这将在一个新窗口中显示带有名称标签的被跟踪车辆!

Et voila!
就是这么做的!
YOLOv3 在英伟达 GTX 1060 6GB 上运行时的速度约为 12 fps,在英伟达 Titan 上可以达到 30 fps。随着功能强大的边缘计算设备的兴起, YOLO 可能会取代 Mobilenet 和其他不如 YOLO 精确的紧凑型物体探测网络。卷积网络可以做的不仅仅是物体检测。语义分割、图像生成、实例分割和更多。
跳转到这里深入研究 YOLO 文件,并了解其优雅的架构和工作。
解读 YOLO 文件的实质细节
机器学习无疑正在改变数字世界的面貌。而且几乎每个行业都会很快受到 AI 的冲击。
为了更深入地探索人工智能,请进入 HackerStreak
在 GitHub 上找到完整的代码https://GitHub . com/baakcshu/Vehicle-and-people-tracking-with-yolov 3-
有什么问题吗?向我开枪。
使用 MLflow 跟踪 ML 实验

演示 MLflow 如何改善您的 ML 建模体验
简介
如果你熟悉构建机器学习模型,无论是在工作中还是作为一种爱好;您可能遇到过这样的情况,您构建了大量不同的模型,具有不同的代码库,并且当您优化代码和调整模型以提升准确性时,需要跟踪大量的图表或笔记本和指标。
你并不孤单。【1】
我认为,这些年来,随着我在数据科学领域的实践,我遇到了很多人们倾向于处理这个问题的方法。我的 go to 方法通常是一个 excel 表。它易于使用,易于可视化,易于传达给外部各方。

Tracking experiments on a spreadsheet
我也见过有人试图以编程方式将指标存储在数据库表中。但是这些可能会变得非常混乱(不是说 excel 表格本身不混乱,但是如果我需要运行一些命令来添加一个新的指标——我会说从长远来看这是不可持续的
一旦有多人在研究同一个机器学习问题,事情就会变得更加棘手。一些基本规则需要在项目执行前设定,否则跟踪将变得很麻烦。成熟的人工智能团队很可能已经解决了这个问题,但我想象早期阶段的初创公司在处理这种协调工作时会有一些问题(如果他们能够负担得起让多个数据科学家从事同一件事情)。
这是一个如此大的问题,以至于催生了一些致力于解决这个特殊问题的公司。我知道的一些例子是:
- 海王星 ML:https://neptune.ml/
2.权重和偏差:https://www.wandb.com/
3.彗星 ML:https://www.comet.ml/
为了简洁起见,我将不涉及它们实际上有什么特性,它们是如何工作的,也不涉及它们的定价模型。一些更侧重于基于深度学习的实验,而另一些则覆盖更广的范围。我在这里想强调的一点是,这个问题已经大到人们实际上为了某种解决方案而付钱给其他人。
值得一提的是 TensorBoard,但它似乎是明确针对 Tensorflow 和深度学习的(我本人不是一个重度 TensorBoard 用户,请在评论部分与我分享你所知道的内容,以便让大家受益)。
MLflow
另一个选择是 MLflow。由 Databricks 开始,它基本上是一个用于整个机器学习生命周期的开源平台 (一字不差地摘自他们的网站)。

What they mean by covering the entire ML lifecycle [2]
这就把我们带到了本文的焦点——跟踪指标。
我的 MLflow 环境
在我目前的工作场所,我们最常用的工具之一是数据块。最近几个月,他们增加了 MLflow 功能。作为一个渴望学习如何更好地跟踪事物的人,这是一个尝试的绝佳机会。我的 MLflow 跟踪演练的上下文将基于此(也就是 Databricks 用户)。
对于非 Databricks 用户,MLflow 可以单独设置并连接到您的环境。应该存在相同的功能。查看他们的文档了解更多细节。
实验
为了展示我目前如何在工作中使用 MLflow,以及为什么我觉得它很有用,我将在 Kaggle 内核[3]上使用它,作者使用加密货币数据集进行了一些数据分析和预测实验。一些小的改动把从[3]中取出的原始代码变成了数据块(主要是为了能够可视化图形),但本质上是一样的。
注:最近刚开始用 MLflow,很有可能会漏掉一些东西。
我在这篇文章中使用的笔记本可以参考这里的。笔记本有两个版本可用—“前的“T11”表示最初移植到 Databricks 的 Kaggle 内核,而“后的“T13”包含用于跟踪的附加代码。
要用 MLflow 开始一个实验,首先需要使用mlflow.set_experiment命令,然后是实验文件的存储路径。
接下来,你可以开始思考在你的分析/实验中,你想要跟踪什么。MLflow 将这些分为 3 个主要类别:
- 参数(通过
mlflow.log_param())。参数是您在调整模型时更改或调整的变量。 - 度量标准(使用
mlflow.log_metric())。度量是调整参数后想要测量的值。被跟踪的典型指标可以是 F1 分数、RMSE、MAE 等项目。 - 工件(使用
mlflow.log_artifact())。工件是您希望存储的任何其他项目。我跟踪的典型工件是 png 图,即特性重要性变量列表。有时我也存储模型(腌 scikit 学习模型)。(更新:我突然想到,你也可以保存你正在使用的原始/转换/训练/测试/验证数据集。多酷啊。)
MLflow 跟踪是围绕运行的概念组织的,这些运行是某段数据科学代码【4】的执行。(接下来,我们将使用斜体
**run** )来表示这个 run 概念)
在每一次运行中可以跟踪的其他事情是代码版本、开始和结束时间以及源文件。参考文件了解更多细节。
跟踪参数和指标
在笔记本的第 37 单元中,作者试图反复探索不同的参数组合,以获得最适合我们数据的 ARIMA 模型。让我们使用这部分代码,并跟踪正在使用的参数和正在生成的指标。
为了开始我们的运行,我们使用mlflow.start_run().,然后将qs和ps参数以及model.aic度量记录到 MLFlow。运行以上代码将在 MLFLow UI 中使用以下结果。

Each row of result is generated for each run.
如果我们要点击进入其中一个运行,我们将进入以下窗口。

Detailed page for each MLflow run
从上面可以看出,我们只跟踪了每次运行的有限数量的参数和指标。既没有被记录的艺术品也没有标签。如果有的话,我们可以选择添加我们自己的注释。记录的其他内容包括日期、用户(在我的例子中是我的数据块 ID)、运行 ID、持续时间和源。
运行被提交给 Git
我发现后者非常有用,因为它实际上将正在运行的笔记本提交到 Git 中。我目前不确定这如何转化为 MLflow 的自设置版本,但在我的情况下,单击 source 链接会将我带回到 Databricks 中的笔记本提交版本(如下)。

Opening the Revision History reveals that this notebook was committed by MLFlow (ie. “Taken by MLflow”)
现在让我们试试别的。
存储图和其他文件
按照前面的例子,我们构建了多个模型,以确定我们应该用于 ARIMA 模型的最佳参数。在我们的下一个例子中,我们将存储一些与模型相关的工件;即模型概要和一些情节。
让我们为我们的 SARIMAX 模型这样做。
从上面的代码中可以看出,登录工件需要比平常多一点的工作。该文件不能直接将图保存到 MLflow 中,而是必须先存储在某个地方,然后才能发送到 MLflow 的 S3 存储桶中。
在我的例子中,文件首先保存到本地 Databricks 集群,然后复制到 MLflow 的 S3 存储桶(在本例中也在 Databricks 内)。或者,也可以为每个实验定义一个外部 S3 存储桶,并将所有相关文件存储在那里。)
作为参考,下面是存储的工件在 UI 中的显示方式。

Artifact 1

Artifact 2

Artifact 3
对我来说,这相当简化和标准化了通常只存储在笔记本上的情节和摘要的集合。虽然让它们存在于 notebook 中是可以的,但是 notebook 可以按单元运行,而不是从上到下完整运行,这意味着某些图实际上可以作为很晚才发生的操作的结果而生成(或者在开发过程中可以完全删除)。由于存储在 MLflow 中的图与 Git 中提交的代码相关联,我们现在有了一种更好的方法来确保实验及其结果以可重复的方式被记录。
保存模型
MLflow 还允许您保存正在训练的模型。这可以通过将其作为工件登录到 MLflow(通过[log_model](https://www.mlflow.org/docs/latest/python_api/mlflow.sklearn.html#mlflow.sklearn.log_model)())或者直接登录到本地文件系统(通过[save_model](https://www.mlflow.org/docs/latest/python_api/mlflow.sklearn.html#mlflow.sklearn.save_model))来完成。
回溯测试
我最喜欢的 MLflow 特性之一是它的指标可视化。为了更好地突出这一点,我将使用内核的最后一部分[3],并对其进行修改,以便在部署运行一段时间(即滑动窗口验证)。
在上面的例子中,我们建立了一个 3 个月的时间窗口,并在 10 个滑动窗口的时间段内评估模型的 RMSE 得分,其中每个向前移动是 1 个月。每次评估时,我们还会将比较图记录到 MLflow 中,以备将来参考和验证。

Plot are captured across multiple sliding window
深入研究 RMSE 指标,我们可以看到它在 10 个时间步长内的表现。我们可以看到,该模型通常在一段时间内是稳定的,直到在第 5 次迭代时达到峰值。如果我们回头参考上图中比特币价格的波动性,这是相当令人期待的。

Performance of the SARIMA model over time
摘要
在这篇文章的过程中,我谈到了每个机器学习实践者都面临的问题——如何整齐地组织和跟踪多个建模实验结果。
MLflow 是实现这一目标的众多工具之一。在本文中,我通过运行几个例子强调了它的几个特性,这些例子说明了如何在日常建模工作中使用它来帮助数据科学从业者。
从短期来看,良好管理的结果有助于团队沟通和协作——这对远程团队来说尤其重要。
从长远来看,对建模活动及其可交付成果进行适当的治理有助于保留学到的知识和发现,减少错误,并确保过去的研究和结果可以被其他团队或其替代者复制。
这篇文章中使用的代码可以在我的 github 这里找到。

Throw away those ugly spreadsheets you’re currently using. Pretty sure it’s not making you happy. (source)
参考
- https://medium . com/@ u39kun/managing-your-machine-learning-experiments-and-make-repeatable-in-tensor flow-py torch-BC 8043099 DBD
- https://www . slide share . net/databricks/ml flow-infra structure-for-a-complete-machine-learning-life-cycle
- https://www . ka ggle . com/taniaj/cryptocurrency-price-forecasting
4.https://mlflow.org/docs/latest/tracking.html
追踪社交网络的演变
一种跟踪社区出生、死亡、合并和分裂的算法

在社交网络中,社区无处不在:人们上同一所学校,在同一家公司工作,喜欢同一部电影,去同一家餐馆,等等。为了方便起见,我们认为拥有相似特征、偏好或历史的人属于同一个社区。
当社区拥有唯一的 ID 时,很容易跟踪他们的历史。例如,我们确切地知道一个学生什么时候被大学录取,什么时候毕业。这是因为学校名称充当社区的事实上的 ID,并且该 ID 不会改变。
当社区没有 id 时,挑战就出现了。ID 可能会丢失,因为这些现象是自然的。当两只蚂蚁随机选择一个地方开始一个蚁群时,它们不会声明一个唯一的名称,例如切萨皮克湾蚁群,以使数据科学家的工作更容易。有时,邪恶的实体会故意隐藏他们的目的(一群黑客计划摧毁你的服务器)。未能跟踪这些社区可能代价高昂。
当社区没有 ID 时,一个简单的方法是创建一个 ID。我们将第一个社区称为。如果出现另一个社区,我们称之为 B 。我们会一直分配新的 id 直到世界末日!
如果这能解决问题,我就不会写这篇博客了。虽然简单,但它留下了许多未解之谜。当两个社区合并时会发生什么?我们是否应该将合并后的社区视为拥有新 ID 的新社区?一个社区分裂成两个/三个/四个会怎么样?我们需要一种更优雅的方式来处理所有边缘情况。此外,我们应该能够追溯一个社区的历史,看看何时发生合并或分裂,谁是参与者。
所以有一天我在回家的路上想到了这个算法。用英语解释很简单。它优雅到足以解决所有的边缘情况。用大约 80 行 SQL 就可以轻松实现。所以我提出一个简单的名字:核心追踪算法。
直觉
一个图由顶点和边组成。顶点代表一个实体,在许多情况下,代表一个用户帐户。边表示两个顶点之间的某种连接。例如,如果两个帐户有相同的电话号码,我们可以在它们之间画一条边。
社区检测算法帮助你有效地发现社区。常见的算法有连通分量、鲁汶模块化、标签传播。这些算法都有很好的文档记录,并有开源的实现。所以这里就不细说了。核心跟踪方法足够通用,可以与任何社区检测算法一起工作。
社区检测算法为每个社区分配一个随机的字符串 ID。当两个人拥有相同的团体 ID 时,你知道他们属于同一个团体,但是 ID 不是持久的。如果您明天再次运行社区检测算法,这两个人将接收到不同的社区 ID,即使他们仍然属于同一个社区。
为了使临时 ID 持久化,我们需要从每个社区中挑选一个 代表顶点 来携带持久 ID。当然,我们希望代表是社区的稳定成员。我们不希望它突然变得与众不同。于是在每个社区中,我把边数(度数)最高的顶点标记为核心,因此得名核心追踪算法。
举例来说,在这个博客中,每个社区都用不同的颜色标记。每个社区的核心由一个带边框的圆圈标记。非核心顶点没有边界。不属于任何社区的顶点被标记为灰色。

Community cores have degree 4 (brown), 4 (blue), 5 (pink), 4 (green) respectively
核心跟踪算法
对于每个时间步长,运行以下六个步骤:
- 使用您选择的任何算法检测社区。
- 从之前的时间步继承核心顶点的社区 ID。这些顶点被称为幸存核心。
- 合并现在属于同一团体的任何幸存核心。合并后的社区继承数字上最小的社区 ID。
- 将幸存核心的团体 ID 传播到属于幸存核心团体的所有顶点。
- 解散不再符合有效社区资格的社区。
- 发现现在有资格成为有效社区的新社区。分配社区 ID,从曾经使用过的最大的ID 开始递增。**
- 为所有有效社区重新分配核心顶点。如有必要,中断联系。
- 缓存有史以来最大的社区 ID。
让我们通过一个扩展的例子来剖析这个算法。
时间步长 1:第一次运行
当我们第一次运行算法时,我们不需要做任何特别的事情。步骤 2 不会继承任何核心顶点,因此跳过步骤 2-5(图中未显示)。只有步骤 1、6 和 7 是重要。在下图中,步数标记在每一帧的右下角。**

时间步长 2:新顶点寄存器
出现一个新顶点,并且没有边将其连接到任何现有顶点。它被独自留下。另一个新的顶点出现,并加入粉红色的社区。
- 第 0 帧是从先前时间步长的末尾复制的(颜色变灰)。
- 框架 1 是在注册了两个新帐户之后更新的图表。
- 第 2 帧继承核心顶点。
- 第 4 帧传播核心顶点的社区 ID。
- 算法的第 3,5,6,7 步并不重要。

时间步骤 3:顶点离开社区
一个顶点决定离开粉红社区,现在只有两个成员。核心顶点度从三降到二。
- 帧 0 是从先前时间步长的末尾复制的。
- 帧 1 是当前图形。顶点离开粉红社区后。
- 第 2 帧继承核心顶点。
- 第 4 帧传播核心顶点的社区 ID。
- 算法的第 3,5,6,7 步并不重要。

时间步 4:核心顶点移动
这两个独立的顶点都加入了粉红色社区。
- 帧 0 是从先前时间步长的末尾复制的。
- 帧 1 是更新的图形。
- 第 2 帧继承核心顶点。
- 第 4 帧传播核心顶点的社区 ID。
- 第 7 帧为每个社区重新指定核心顶点。粉色社区核心已经更新,现在有 3 级了。
- 算法的第 3,5,6 步并不重要。

时间步骤 5:顶点迁移
一个顶点直接从粉色社区跳到蓝色社区。
- 帧 0 是从先前时间步长的末尾复制的。
- 帧 1 是更新的图形。
- 第 2 帧继承核心顶点。
- 第 4 帧传播核心顶点的社区 ID。
- 第 7 帧为每个社区重新指定核心顶点。请注意,两个顶点的度数为 2。 核心可能不可调职。 我们只需要一种一致的方式来打破束缚,例如按账号 ID 的字母顺序,或者按注册日期的升序。
- 算法的第 3,5,6 步并不重要。

时间步骤 6:社区合并
两个社区合并,合并后的社区 继承旧社区的 ID 。因为我们在数字上增加了社区 ID。合并的团体总是继承组成团体中最小的团体 ID。我们假设蓝色社区比较老。
- 帧 0 是从先前时间步长的末尾复制的。
- 帧 1 是更新的图形。
- 第 2 帧继承核心顶点。
- 帧 3 发现两个幸存的核心属于同一个社区。检测到合并。所以我们忽略了新社区的核心,保留了最老的(这很容易推广到 N 路合并)。
- 第 4 帧传播核心顶点的社区 ID(现在全部为蓝色)。
- 算法的第 5,6,7 步并不重要。

时间步骤 7:社区分裂
蓝色社区分裂成三个较小的社区和一个独立的顶点。
- 帧 0 是从先前时间步长的末尾复制的。
- 帧 1 是四路分割后的更新图。
- 第 2 帧继承核心顶点。
- 第 4 帧传播核心顶点的社区 ID。
- 帧 6 检测到两个新的社区,它们被分配了新的社区 ID 和颜色(以前从未使用过)。
- 第 7 帧为所有社区重新指定核心顶点。如有必要,中断联系。
- 算法的第 3 步和第 5 步无关紧要。

时间步骤 8:社区解散
两个社区解散了。一般来说,独立的顶点不是有意义的社区。但是这一步让我们有更大的自由来定义什么是社区。例如,我们可以设置最小规模为 5 的社区作为有效社区。
- 帧 0 是从先前时间步长的末尾复制的。
- 帧 1 是两个社区解散后的更新图。
- 第 2 帧继承核心顶点。
- 第 4 帧传播核心顶点的社区 ID。
- 帧 5 分解无效社区。
- 算法的第 3,6,7 步并不重要。

算法亮点
社区 id 不仅是持久的,而且是有意义的。较小的身份证号码意味着较老的社区。该特性反映了关系数据库中的自动递增索引。这一点由 step 8 来保证,step 8 花费恒定的内存来跟踪曾经使用过的最大 ID。
在扩展示例中,我使用了 连通分量 算法来检测社区,因为它在视觉上是直截了当的。在实践中,您可以将任何社区检测算法切换到步骤 1。
在扩展的例子中,我使用了中心性 来分配社区核心。有不同的度量中心性的方法:接近度、中间度、调和度、特征向量。您可以将任何社区检测算法切换到步骤 7。**
在极端的情况下,核心可能直接离开社区。在这种情况下,旧社区被解散,剩余的顶点成为一个全新的社区。这显然是不可取的。所以我们需要选择一个中心性度量来最小化一个核心顶点直接离开的概率。
分析洞察力
在运行该算法足够的迭代次数后,无论您使用社区还是个人顶点作为分析单位,它都会产生巨大的洞察力。例如,要研究社区 10 的规模如何随时间演变,一个简单的 SQL 查询就足够了:
要查找用户“shawlu”何时从一个社区切换到另一个社区,以及他在每个社区停留了多少天,可以写:
脚注
最初的实现是 Coupang Global LLC 的专有代码和知识产权。我不能透露。
尽管如此,该算法的每一步都可以被任何一个具有该语言基础知识的人翻译成一个 SQL 查询。
更明智地交易和投资——强化学习方式
深入探究 TensorTrade——使用深度强化学习进行交易和投资的 Python 框架

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
赢得高赌注扑克锦标赛,击败世界级星际争霸玩家,以及自动驾驶特斯拉的未来跑车。他们都有什么共同点?长期以来,这些极其复杂的任务中的每一项都被认为是机器不可能完成的,直到深度强化学习的最新进展表明它们今天是可能的。
强化学习开始接管世界。

Source: https://deepmind.com/blog/article/alphastar-mastering-real-time-strategy-game-starcraft-ii
两个多月前,我决定参加这场革命,于是我开始了一段旅程,利用最先进的深度强化学习算法创建一个有利可图的比特币交易策略。虽然我在这方面取得了相当大的进展,但我意识到这类项目的工具可能会令人望而生畏,因此很容易迷失在细节中。
在优化我之前的分布式高性能计算(HPC)系统项目之间;迷失在无尽的数据和功能优化管道中;围绕高效的模型建立、调整、培训和评估,我忙得团团转;我意识到一定有更好的做事方法。在对现有项目进行了无数小时的研究,花了无数个晚上观看 PyData 会议演讲,并与数百名 RL trading Discord 社区成员进行了多次来回交谈后,我意识到没有任何现有的解决方案是那么好。
互联网上散布着许多零碎的强化学习交易系统,但没有一个是完整的。出于这个原因,我决定创建一个开源的 Python 框架,使用深度强化学习,高效地将任何交易策略从想法变成产品。
输入 TensorTrade。想法是创建一个高度模块化的框架,以一种可组合、可维护的方式构建高效的强化学习交易策略。依我看,这听起来像是一大堆术语,所以让我们进入正题吧。
目录
概观

TensorTrade 是一个开源的 Python 框架,使用深度强化学习来训练、评估和部署稳健的交易策略。该框架的重点是高度可组合和可扩展,以允许系统从单个 CPU 上的简单交易策略扩展到在分布的 HPC 机器上运行的复杂投资策略。
在引擎盖下,该框架使用现有机器学习库中的许多 API 来维护高质量的数据管道和学习模型。TensorTrade 的主要目标之一是通过利用由numpy、pandas、gym、keras和tensorflow提供的现有工具和管道,实现算法交易策略的快速试验。
框架的每一部分都被分割成可重用的组件,允许您利用社区构建的通用组件,同时保留您的专有特性。目的是使用深度强化学习来简化测试和部署稳健交易代理的过程,让你我专注于创造盈利策略。
RL 底漆
如果你的强化学习技能有点生疏,让我们快速回顾一下基本概念。
每个强化学习问题都始于一个环境和一个或多个可以与环境交互的代理。
This technique is based off Markov Decision Processes (MDP) dating back to the 1950s.**
代理将首先观察环境,然后建立当前状态的模型以及该环境中动作的期望值。基于该模型,代理将采取它认为具有最高期望值的行动。
基于所选动作在环境中的效果,代理将被奖励与该动作的实际价值相对应的金额。然后,强化学习代理可以通过试错过程(即,通过强化学习)来改进其底层模型,并随着时间的推移学习采取更有益的行动。
如果在这个问题上你还需要一点新鲜的东西,在这篇文章的参考资料中有一篇文章的链接,标题是深度强化学习简介,它更深入地介绍了细节。我们继续吧。
入门指南
下面的教程将提供足够的例子,让你开始使用 TensorTrade 创建简单的交易策略,尽管你会很快发现这个框架能够处理更复杂的配置。
你可以跟随 Google Colab 或者 Github 上的教程。
装置
TensorTrade 需要 Python 3.6 或更高版本,所以在 pip 安装框架之前,请确保您使用的是有效版本。
pip install git+https://github.com/notadamking/tensortrade.git
为了完成整个教程,您需要安装一些额外的依赖项,比如tensorflow、tensorforce、stable-baselines、ccxt、ta和stochastic。
pip install git+[https://github.com/notadamking/tensortrade.git#egg=tensortrade[tf,tensorforce,baselines,ccxt,ta,fbm](https://github.com/notadamking/tensortrade.git#egg=tensortrade[tf,tensorforce,baselines,ccxt,fbm)] -U
这就是所有必要的安装!让我们进入代码。
TensorTrade 组件
TensorTrade 是围绕模块化组件构建的,这些组件共同构成了交易策略。交易策略以gym环境的形式将强化学习代理与可组合的交易逻辑结合起来。交易环境是由一组模块组成的,这些模块可以混合和匹配,以创建高度多样化的交易和投资策略。稍后我将进一步详细解释这一点,但现在知道一些基本知识就足够了。

就像电气组件一样,TensorTrade 组件的目的是能够根据需要混合和匹配它们。
本节中的代码片段应该作为创建新策略和组件的指南。随着更多组件的定义,可能会遗漏一些实现细节,这些细节将在后面的章节中变得更加清晰。
贸易环境
交易环境是遵循 OpenAI 的gym.Env规范的强化学习环境。这允许我们在交易代理中利用许多现有的强化学习模型,如果我们愿意的话。

交易环境是完全可配置的gym环境,具有高度可组合的Exchange、FeaturePipeline、ActionScheme和RewardScheme组件。
Exchange提供对环境的观察并执行代理的交易。- 在将交换输出传递给代理之前,
FeaturePipeline可选地将交换输出转换成一组更有意义的特性。 ActionScheme将代理的行为转换成可执行的交易。RewardScheme根据代理的表现计算每个时间步的奖励。
如果说现在看起来有点复杂,其实真的不是。这就是全部内容,现在只需要将这些组件组成一个完整的环境。
当TradingEnvironment的reset方法被调用时,所有的子组件也将被重置。每个交换、特性管道、变形金刚、行动方案和奖励方案的内部状态将被设置回默认值,为下一集做好准备。
让我们从一个示例环境开始。如前所述,初始化一个TradingEnvironment需要一个交换,一个行动方案,一个奖励方案,特征流水线是可选的。
**from** tensortrade.environments **import** TradingEnvironmentenvironment = TradingEnvironment(exchange=exchange,
action_scheme=action_scheme,
reward_scheme=reward_scheme,
feature_pipeline=feature_pipeline)
虽然推荐的用例是将交易环境插入到交易策略中,但是很明显,您可以单独使用交易环境,就像使用
gym环境一样。
交换
交易所确定交易环境中可交易工具的范围,在每个时间步将观察结果返回给环境,并在该环境中执行交易。有两种类型的交流:现场交流和模拟交流。
实时交易所是由实时定价数据和实时交易执行引擎支持的Exchange的实现。例如,CCXTExchange是一个实时交易所,它能够返回定价数据,并在数百个实时加密货币交易所执行交易,如币安和比特币基地。
**import** ccxt**from** tensortrade.exchanges.live **import** CCXTExchangecoinbase = ccxt.coinbasepro()exchange = CCXTExchange(exchange=coinbase, base_instrument='USD')
也有股票和 ETF 交易的交易所,如
RobinhoodExchange和InteractiveBrokersExchange,但这些仍在进行中。
另一方面,模拟交易所是由模拟定价数据和交易执行支持的Exchange的实现。
例如,FBMExchange是一个模拟的交易所,它使用分数布朗运动(FBM)生成定价和交易量数据。因为它的价格是模拟的,所以它执行的交易也必须模拟。该交易所使用简单的滑点模型来模拟交易的价格和交易量滑点,尽管像 TensorTrade 中的几乎所有东西一样,这个滑点模型可以很容易地被更复杂的东西取代。
**from** tensortrade.exchanges.simulated **import** FBMExchangeexchange = FBMExchange(base_instrument='BTC', timeframe='1h')
虽然FBMExchange使用随机模型生成虚假的价格和交易量数据,但它只是SimulatedExchange的一个实现。在幕后,SimulatedExchange只需要一个价格历史的data_frame来生成它的模拟。这个data_frame既可以由编码实现(如FBMExchange)提供,也可以在运行时提供,如下例所示。
**import** pandas **as** pd**from** tensortrade.exchanges.simulated **import** SimulatedExchangedf = pd.read_csv('./data/btc_ohclv_1h.csv')exchange = SimulatedExchange(data_frame=df, base_instrument='USD')
特征管线
特征管道意味着将来自环境的观察转换成有意义的特征,以便代理从中学习。如果一个管道已经被添加到一个特定的交换中,那么在输出到环境之前,观察结果将通过FeaturePipeline。例如,特性管道可以标准化所有价格值,使时间序列稳定,添加移动平均列,并删除不必要的列,所有这些都在观察结果返回给代理之前完成。

可以用任意数量的逗号分隔的转换器初始化特征管线。每个FeatureTransformer都需要用要转换的列集进行初始化,否则如果没有传递任何内容,所有输入列都将被转换。
每个特征转换器都有一个transform方法,该方法将从更大的数据集中转换单个观察值(a pandas.DataFrame),在内存中保留任何必要的状态以转换下一帧。因此,经常需要定期对reset和FeatureTransformer进行调整。每次重置父FeaturePipeline或Exchange时,这将自动完成。
让我们创建一个示例管道,并将其添加到现有的交换中。
**from** tensortrade.features **import** FeaturePipeline
**from** tensortrade.features.scalers **import** MinMaxNormalizer
**from** tensortrade.features.stationarity **import** FractionalDifference
**from** tensortrade.features.indicators **import** SimpleMovingAverageprice_columns = ["open", "high", "low", "close"]normalize_price = MinMaxNormalizer(price_columns)
moving_averages = SimpleMovingAverage(price_columns)
difference_all = FractionalDifference(difference_order=0.6)feature_pipeline = FeaturePipeline(steps=[normalize_price,
moving_averages,
difference_all])exchange.feature_pipeline = feature_pipeline
此功能管道在添加一些移动平均列并通过连续值的微小差异使整个时间序列平稳之前,将价格值标准化为 0 到 1 之间。
行动计划
行动方案定义了环境的行动空间,并将代理的行动转换成可执行的交易。例如,如果我们使用 3 个动作的离散动作空间(0 = hold,1 = buy 100%,2 = sell 100%),我们的学习代理不需要知道返回一个动作 1 等同于购买一个乐器。相反,我们的代理需要知道在特定情况下返回动作 1 的回报,并且可以将动作转换为交易的实现细节留给ActionScheme。
每个动作方案都有一个get_trade方法,它会将代理的指定动作转化为可执行的Trade。通常需要在方案中存储额外的状态,例如跟踪当前交易的头寸。每次调用动作方案的reset方法时都应该重置该状态,这是在重置父TradingEnvironment时自动完成的。
**from** tensortrade.actions **import** DiscreteActionsaction_scheme = DiscreteActions(n_actions=20,
instrument_symbol='BTC')
该离散动作方案使用 20 个离散动作,相当于 5 种交易类型(市场买入/卖出、限价买入/卖出和持有)中每种交易类型的 4 个离散金额。例如[0,5,10,15]=
hold,1=market buy 25%,2=market sell 25%,3=limit buy 25%,4=limit sell 25%,6=market buy 50%,7=market sell 50%等…
奖励计划
奖励方案接收在每个时间步进行的交易,并返回一个float,对应于特定行动的收益。例如,如果这一步采取的行动是导致正利润的出售,我们的RewardScheme可以返回一个正数,以鼓励更多这样的交易。另一方面,如果行动是导致损失的销售,该方案可以返回负奖励,以教导代理人在未来不要做出类似的行动。
该示例算法的一个版本在SimpleProfit组件中实现,然而显然可以使用更复杂的策略来代替。
每个奖励方案都有一个get_reward方法,它接受在每个时间步执行的交易,并返回一个与该动作的值相对应的浮点数。与动作方案一样,出于各种原因,经常需要在奖励方案中存储附加状态。每次调用奖励方案的reset方法时都应该重置该状态,这是在重置父TradingEnvironment时自动完成的。
**from** tensortrade.rewards **import** SimpleProfitreward_scheme = SimpleProfit()
简单利润方案返回的回报为-1 表示不持有交易,1 表示持有交易,2 表示购买工具,如果出售工具,则对应于交易所得(正/负)利润的值。
学习代理
到目前为止,我们还没有看到深度强化学习框架的“深度”部分。这就是学习代理的用武之地。学习代理是数学(阅读:魔术)发生的地方。

在每个时间步,代理将来自环境的观察作为输入,通过其底层模型(大部分时间是神经网络)运行它,并输出要采取的行动。例如,观察值可能是交易所以前的开盘价、最高价、最低价和收盘价。学习模型将这些值作为输入,并输出对应于要采取的动作的值,例如购买、出售或持有。
重要的是要记住,学习模型对这些值所代表的价格或交易没有直觉。相反,该模型只是学习对于特定的输入值或输入值序列输出哪些值,以获得最高的回报。
稳定基线
在本例中,我们将使用稳定基线库为我们的交易策略提供学习代理,然而,TensorTrade 框架与许多强化学习库兼容,如 Tensorforce 、 Ray 的 RLLib 、 OpenAI 的基线、英特尔的蔻驰,或 TensorFlow 系列中的任何库,如 TF 代理。
自定义 TensorTrade 学习代理可能会在未来添加到该框架中,尽管该框架的目标始终是与尽可能多的现有强化学习库进行互操作,因为该领域有如此多的并发增长。
但是现在,稳定的基线对于我们的需求来说足够简单和强大。
**from** stable_baselines.common.policies **import** MlpLnLstmPolicy
**from** stable_baselines **import** PPO2model = PPO2
policy = MlpLnLstmPolicy
params = { "learning_rate": 1e-5 }agent = model(policy, environment, model_kwargs=params)
注意:使用 TensorTrade 并不需要稳定的基线,尽管在本教程中它是必需的。这个例子使用了一个支持 GPU 的近似策略优化模型和一个层标准化的 LSTM 感知器网络。如果您想了解更多关于稳定基线的信息,您可以查看文档。
我还将快速介绍一下 Tensorforce 库,以展示在强化学习框架之间切换是多么简单。
**from** tensorforce.agents **import** Agentagent_spec = {
"type": "ppo_agent",
"step_optimizer": {
"type": "adam",
"learning_rate": 1e-4
},
"discount": 0.99,
"likelihood_ratio_clipping": 0.2,
}network_spec = [
dict(type='dense', size=64, activation="tanh"),
dict(type='dense', size=32, activation="tanh")
]agent = Agent.from_spec(*spec*=agent_spec,
*kwargs*=*dict*(*network*=network_spec,
*states*=environment.states,
*actions*=environment.actions))
如果你想了解更多关于 Tensorforce 代理的信息,你可以查看文档。
交易策略
一个TradingStrategy由一个学习代理和一个或多个交易环境组成,用于调整、训练和评估。如果只提供一个环境,它将用于调优、培训和评估。否则,可以在每个步骤提供单独的环境。
**from** tensortrade.strategies **import** TensorforceTradingStrategy,
StableBaselinesTradingStrategya_strategy = TensorforceTradingStrategy(environment=environment,
agent_spec=agent_spec,
network_spec=network_spec)b_strategy = StableBaselinesTradingStrategy(environment=environment,
model=PPO2,
policy=MlpLnLSTMPolicy)
如果您还不理解策略初始化,请不要担心,稍后会有更详细的解释。
把所有的放在一起
现在我们知道了组成TradingStrategy的每个组件,让我们构建并评估一个组件。

简单回顾一下,TradingStrategy由TradingEnvironment和学习代理组成。一个TradingEnvironment是一个gym环境,它接受一个Exchange、一个ActionScheme、一个RewardScheme和一个可选的FeaturePipeline,并返回观察结果和奖励,学习代理可以在这些观察结果和奖励上进行培训和评估。
创造环境
第一步是使用上面概述的组件创建一个TradingEnvironment。
**from** tensortrade.exchanges.simulated **import** FBMExchange
**from** tensortrade.features.scalers **import** MinMaxNormalizer
**from** tensortrade.features.stationarity **import** FractionalDifference
**from** tensortrade.features **import** FeaturePipeline
**from** tensortrade.rewards **import** SimpleProfit
**from** tensortrade.actions **import** DiscreteActions
**from** tensortrade.environments **import** TradingEnvironmentnormalize_price = MinMaxNormalizer(["open", "high", "low", "close"])
difference = FractionalDifference(difference_order=0.6)
feature_pipeline = FeaturePipeline(steps=[normalize_price,
difference])exchange = FBMExchange(timeframe='1h',
base_instrument='BTC',
feature_pipeline=feature_pipeline)reward_scheme = SimpleProfit()action_scheme = DiscreteActions(n_actions=20,
instrument_symbol='ETH/BTC')environment = TradingEnvironment(exchange=exchange,
action_scheme=action_scheme,
reward_scheme=reward_scheme,
feature_pipeline=feature_pipeline)
很简单,现在environment是一个gym环境,可以被任何兼容的交易策略或学习代理使用。
定义代理
既然环境已经设置好了,是时候创建我们的学习代理了。同样,我们将为此使用稳定的基线,但也可以在这里随意添加任何其他强化学习代理。
由于我们使用的是StableBaselinesTradingStrategy,所以我们需要做的就是为要训练的底层神经网络提供模型类型和策略类型。对于这个例子,我们将使用一个简单的近似策略优化(PPO)模型和一个层标准化的 LSTM 策略网络。
有关模型和策略规范的更多示例,请参见稳定基线文档。
**from** stable_baselines.common.policies **import** MlpLnLstmPolicy
**from** stable_baselines **import** PPO2model = PPO2
policy = MlpLnLstmPolicy
params = { "learning_rate": 1e-5 }
训练策略
创建我们的交易策略就像插入我们的代理和环境一样简单。
**from** tensortrade.strategies **import** StableBaselinesTradingStrategystrategy = StableBaselinesTradingStrategy(environment=environment,
model=model,
policy=policy,
model_kwargs=params)
然后,为了训练策略(即,在当前环境下训练代理),我们需要做的就是调用strategy.run()并告知您想要运行的步骤或剧集的总数。
performance = strategy.run(steps=100000,
episode_callback=stop_early_callback)
瞧啊。三个小时和数以千计的打印报表后,你会看到你的代理如何做的结果!
如果这个反馈循环对你来说有点慢,可以给run传递一个回调函数,每集结束时都会调用。回调函数将传入一个包含代理在那一集的表现的数据帧,并期待一个bool作为返回。如果True,代理将继续培训,否则,代理将停止并返回其整体绩效。

A simple performance output at the end of the episode, including the final 5 balances and net worths of the agent.
保存和恢复
所有的交易策略都能够将它们的代理保存到一个文件中,以便以后恢复。环境没有被保存,因为它没有我们关心保存的状态。为了将我们的TensorflowTradingStrategy保存到一个文件中,我们只需要将文件的path提供给我们的策略。
strategy.save_agent(path="../agents/ppo_btc_1h")
为了从文件中恢复代理,在调用restore_agent之前,我们首先需要实例化我们的策略。
**from** tensortrade.strategies **import** StableBaselinesTradingStrategystrategy = StableBaselinesTradingStrategy(environment=environment,
model=model,
policy=policy,
model_kwargs=params)strategy.restore_agent(path="../agents/ppo_btc/1h")
我们的策略现在恢复到了之前的状态,并准备再次使用。
调整您的策略
有时,交易策略需要在一个环境中调整一组超参数或特征,以达到最佳性能。在这种情况下,每个TradingStrategy提供一个可选的可实现的tune方法。
调整模型类似于训练模型,但是除了调整和保存最佳执行模型的权重和偏差之外,该策略还调整和保持产生该模型的超参数。
**from** tensortrade.environments **import** TradingEnvironment
**from** tensortrade.exchanges.simulated **import** FBMExchangeexchange = FBMExchange(timeframe='1h',
base_instrument='BTC',
feature_pipeline=feature_pipeline)environment = TradingEnvironment(exchange=exchange,
action_scheme=action_scheme,
reward_scheme=reward_scheme)strategy.environment = environmenttuned_performance = strategy.tune(episodes=10)
在这种情况下,代理将被训练 10 集,每集有一组不同的超参数。最佳设置将保存在策略中,并在此后调用
strategy.run()时使用。
战略评估
现在我们已经调优并训练了我们的代理,是时候看看它的表现如何了。为了评估我们的策略在看不见的数据上的性能,我们需要在这样的数据支持的新环境上运行它。
**from** pandas **import** pd**from** tensortrade.environments **import** TradingEnvironment
**from** tensortrade.exchanges.simulated **import** SimulatedExchangedf = pd.read_csv('./btc_ohlcv_1h.csv')exchange = SimulatedExchange(data_frame=df,
base_instrument='BTC',
feature_pipeline=feature_pipeline)environment = TradingEnvironment(exchange=exchange,
action_scheme=action_scheme,
reward_scheme=reward_scheme)strategy.environment = environmenttest_performance = strategy.run(episodes=1, testing=True)
完成后,strategy.run返回代理绩效的 Pandas 数据框架,包括代理在每个时间步的净值和余额。

Example evaluation performance — this agent has not been trained on this feature set, so performance is arbitrary.
现场交易
一旦你建立了一个有利可图的交易策略,训练了一个代理来正确交易它,并确保它对新数据集的“泛化能力”,剩下要做的就是盈利。使用像CCXTExchange这样的实时交流,你可以插入你的策略并让它运行!

虽然你可能喜欢开始一个策略,并让它无限制地运行,但你可以使用一个trade_callback,它将在每次策略交易时被调用。这个回调函数类似于剧集回调,将传入一个包含代理整体表现的数据帧,并期望得到一个bool作为回报。如果True,代理将继续交易,否则,代理将停止交易并返回其在整个交易期间的表现。
**import** ccxt**from** tensortrade.environments **import** TradingEnvironment
**from** tensortrade.strategies **import** StableBaselinesTradingStrategy
**from** tensortrade.exchanges.live **import** CCXTExchangecoinbase = ccxt.coinbasepro(...)exchange = CCXTExchange(exchange=coinbase,
timeframe='1h',
base_instrument='USD',
feature_pipeline=feature_pipeline)environment = TradingEnvironment(exchange=exchange,
action_scheme=action_scheme,
reward_scheme=reward_scheme)strategy.environment = environmentstrategy.restore_agent(path="../agents/ppo_btc/1h")*live_performance = strategy.run(steps=0, trade_callback=episode_cb)*
通过
steps=0指示策略运行,直到停止。
这就是全部了!正如你所看到的,使用简单的组件和深度强化学习来构建复杂的交易策略是非常简单的。你还在等什么?投入其中,亲自动手,看看使用 TensorTrade 能做些什么。
未来
目前,该框架正处于早期阶段。到目前为止,重点是获得一个工作原型,具有创建高利润战略所需的所有必要构件。下一步是构建未来的路线图,并决定哪些即将到来的构件对社区是重要的。
很快,我们将看到框架中增加了高度信息化的可视化环境,以及更多交易所、交易更多工具的更深入的策略。

An example environment visualization, created in a previous article.
天空是极限。基础(即框架)已经奠定,现在要由社区来决定下一步做什么。我希望你能成为其中的一员。
最后的想法
TensorTrade 是一个强大的框架,能够构建高度模块化、高性能的交易系统。尝试新的交易和投资策略是相当简单和容易的,同时允许你在另一个策略中利用一个策略的成分。但不要相信我的话,创建一个自己的策略,并开始教你的机器人接管世界!
虽然这个教程应该足以让你开始,但如果你想创造一个有利可图的交易策略,还有很多东西要学。我鼓励你去 Github 看看代码库,或者看看我们在 tensortrade.org的文档。还有一个相当活跃的 Discord 社区,共有近 1000 名成员,所以如果你有问题、反馈或功能请求,请随时在那里提出!

This is my GitHub commit history for the TensorTrade framework — you could say I’ve been busy.
我已经让这个项目达到了高度可用的状态。不过,我的时间有限,我相信你们中有很多人可以为开源代码库做出有价值的贡献。因此,如果你是一个对构建最先进的交易系统感兴趣的开发人员或数据科学家,我希望看到你打开一个拉请求,即使它只是一个简单的测试案例!
贡献的
其他人问他们如何在不写代码的情况下为项目做贡献。目前有三种方法可以做到这一点。
- 为 TensorTrade 框架编写代码或文档。 Github 上的许多问题都是通过 Gitcoin 智能合约资助的,所以你可以通过贡献获得报酬。迄今为止,社区捐赠的近 10 ETH(~2000 美元)已经用于支付开源开发者对框架的贡献。
- 用比特币或以太坊资助这个项目。这些捐赠用于资助我们的 Gitcoin 智能合同,它允许任何贡献优质代码和文档的人获得报酬。
- 在 Github 上赞助我。Github 目前正在 1:1 匹配所有捐款,最高可达 5000 美元,因此这是赞助我的工作和 TensorTrade 发展的最佳时机。所有的赞助都直接用于资助框架的开源开发。
感谢阅读!一如既往,本教程的所有代码都可以在我的 GitHub 上找到。如果您有任何问题或反馈,请在下面留下评论,我很乐意收到您的来信!我也可以通过@notadamking 上的Twitter联系到。**
你也可以通过下面的链接在 Github 赞助商 或者Patreon上赞助我。**
嗨,我是亚当。我是一名开发人员、作家和企业家,尤其对深度…
github.com](https://github.com/users/notadamking/sponsorship) [## 亚当·金正在创造改变世界的内容
嗨,我是亚当。我是一名开发人员、作家和企业家,尤其对深度…
patreon.com](https://patreon.com/notadamking)
参考
- 【1。】深度强化学习介绍惠,乔纳森。" RL-深度强化学习入门."中2019 年 1 月 7 日https://Medium . com/@ Jonathan _ hui/rl-introduction-to-deep-reinforcement-learning-35 c 25 e04c 199。
- 【2。]政策梯度算法
翁,李莲。“政策梯度算法。”Lil ' log2018 年 4 月 8 日https://lilian Weng . github . io/Lil-log/2018/04/08/policy-gradient-algorithms . html #加强。 - 【3。]干净的代码:敏捷软件技术手册
马丁,罗伯特 C. 干净的代码:敏捷软件技术手册。普伦蒂斯霍尔,2010 年。 - 【4。]金融机器学习进展 普拉多马科斯 Ló pez de。金融机器学习的进展。威利,2018 。**
















浙公网安备 33010602011771号