TowardsDataScience 博客中文翻译 2019(五十八)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

喀拉斯 LSTM 异常探测

原文:https://towardsdatascience.com/anomaly-detection-with-lstm-in-keras-8d8d7e50ab1b?source=collection_archive---------2-----------------------

使用置信区间预测异常

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

Photo by Scott Umstattd on Unsplash

我在任何地方的各种竞赛中都读到过“异常”的定义。在这个混沌中,唯一的真理就是这个定义的可变性,即异常解释完全与兴趣域相关。

对这种行为的检测在每个行业中都是有用的,检测这些观察的难度取决于应用领域。如果您正在处理一个涉及人类活动的异常检测问题(如销售或需求预测),您可以利用人类行为的基本假设,规划一个更有效的解决方案。

这正是我们在这篇文章中所做的。我们试图预测纽约市在一个关键时期的出租车需求。我们制定了关于人类行为的简单而重要的假设,这将允许我们发现预测异常的简单解决方案。所有的脏活都是由喀拉斯开发的忠诚 LSTM 完成的,它可以同时预测和检测异常情况!

数据集

我从 Numenta 社区获取了用于我们分析的数据集。特别是,我选择了纽约出租车数据集。该数据集显示了纽约市从 2014 年 7 月 1 日到 2015 年 1 月 31 日的出租车需求,每半小时观察一次。

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

Example of Weekly NORMAL observations

在此期间,就偏离正常行为而言,存在 5 种异常。它们分别发生在纽约马拉松、感恩节、圣诞节、新年和暴风雪期间。

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

Example of Weekly ABNORMAL observations: NYC marathon — Christmas

我们的目的是提前探测到这些异常的观测结果!

从数据来看,我们注意到的第一个考虑因素是存在一个明显的每日模式(白天的需求高于夜间)。出租车需求似乎也受到每周趋势的驱动:在一周中的某些日子,出租车需求高于其他日子。我们简单地证明这个计算自相关。

timeLags = np.arange(1,10*48*7)
autoCorr = [df.value.autocorr(lag=dt) for dt in timeLags]plt.figure(figsize=(19,8))
plt.plot(1.0/(48*7)*timeLags, autoCorr)
plt.xlabel('time lag [weeks]')
plt.ylabel('correlation coeff', fontsize=12)

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

AutoCorrelation 10 weeks depth

我们现在能做的是记下这些重要的行为,以便我们进一步分析。我每小时计算并存储一周中每一天的平均值。当我们将数据标准化以构建我们的模型时,这将是有用的,以便减少各种时间依赖性(我计算将成为我们未来训练集的前 5000 个观察值的平均值)。

模型

我们需要一种策略来提前检测异常值。为此,我们决定关注出租车需求预测。我们希望开发一种模型,能够在考虑不确定性的情况下预测需求。一种方法是发展分位数回归。我们关注极值的预测:下限(第 10 个分位数),上限(第 90 个分位数)和经典的第 50 个分位数。计算第 90 个和第 10 个分位数,我们涵盖了现实中最有可能出现的值。这个范围的宽度可以很深;我们知道,当我们的模型对未来有把握时,它是小的,当我们的模型不能看到感兴趣领域的重要变化时,它可能是大的。我们利用了这种行为,并让我们的模型说明了出租车需求预测领域中的异常值检测。当我们的模型对未来有把握时,我们期望得到一个很小的区间(90-10 分位数范围),因为一切都在控制之中;另一方面,当间隔变大时,我们期望得到一个异常。这是可能的,因为我们的模型没有被训练来处理这种可能导致异常的场景。

我们在 Keras 建立了一个简单的 LSTM 神经网络,让这一切成为现实。我们的模型将接收过去的观察结果作为输入。我们用每日窗口大小(48 次观察:每半小时一次观察)来调整数据大小,以便为 LSTM 提供数据。当我们生成数据时,正如我上面提到的,我们操作对数转换和标准化减去平均每日小时值,以便将观察值视为其每日平均小时值的对数变化。我们以同样的方式构建目标变量,每半小时转换一次(我们希望预测接下来三十分钟的需求值)。

inputs = Input(shape=(X_train.shape[1], X_train.shape[2]))
lstm = Bidirectional(LSTM(64, return_sequences=True, dropout=0.5))(inputs, training = True)
lstm = Bidirectional(LSTM(16, return_sequences=False, dropout=0.5))(lstm, training = True)
dense = Dense(50)(lstm)
out10 = Dense(1)(dense)
out50 = Dense(1)(dense)
out90 = Dense(1)(dense)model = Model(inputs, [out10,out50,out90])

在 Keras 中操作分位数回归非常简单(我从这篇文章中获得了灵感)。我们很容易定义自定义分位数损失函数,该函数基于分位数以及误差是正的(实际>预测的)还是负的(实际<预测的)来惩罚误差。我们的网络有 3 个输出和 3 个损失,分别对应于我们试图预测的每个分位数。

def q_loss(q,y,f):
    e = (y-f)
    return K.mean(K.maximum(q*e, (q-1)*e), axis=-1)losses = [lambda y,f: q_loss(0.1,y,f), lambda y,f: q_loss(0.5,y,f), lambda y,f: q_loss(0.9,y,f)]model.compile(loss=losses, optimizer='adam', loss_weights = [0.3,0.3,0.3])

交叉问题

在处理 Keras 中的神经网络时,一个繁琐的问题是由于内部权值初始化导致的结果的不确定性。用它的提法,我们的问题似乎特别遭受这种问题;即计算分位数预测我们不能允许分位数重叠,这没有意义!为了避免这个陷阱,我在预测阶段使用自举:我重新激活我的网络的丢失(模型中的trainible:true),迭代预测 100 次,存储它们并最终计算期望的分位数(我在这篇文章中也使用了这个聪明的技术)。

pred_10, pred_50, pred_90 = [], [], []
NN = K.function([model.layers[0].input, K.learning_phase()], 
                [model.layers[-3].output,
                 model.layers[-2].output,
                 model.layers[-1].output])for i in tqdm.tqdm(range(0,100)):
    predd = NN([X_test, 0.5])
    pred_10.append(predd[0])
    pred_50.append(predd[1])
    pred_90.append(predd[2])

这个过程在下面用图表解释,重点放在预测的子集上。给定分位数引导,我们计算它们的汇总测量(红线),避免交叉。

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

q90 prediction bootstraps (cyan); q50 prediction bootstraps (blue); q10 prediction bootstraps (green)

结果

正如我前面提到的,我使用前 5000 个观察值进行训练,剩下的(大约 5000 个)用于测试。

我们的模型用第 50 个分位数达到了很好的预测出租车需求的性能。大约 0.055 的均方对数误差是一个辉煌的结果!这意味着 LSTM 网络能够理解驱动出租车需求的潜在规则。因此,我们的异常检测方法听起来很棒…我们计算了第 90 个分位数预测和第 10 个分位数预测之间的差异,看看发生了什么。

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

Real (red line); Quantile interval length (blue dots)

分位数区间范围(蓝点)在不确定时期较高。在其他情况下,正如我们所预期的那样,该模型往往能够很好地概括。更深入地说,我们开始调查这些高度不确定的时期。我们注意到这些与我们最初的假设相吻合。下面标绘的橙色圆圈分别是:纽约马拉松、感恩节、圣诞节、元旦和暴风雪。

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

Anomaly Detection

我们可以得出结论,我们达到了我们最初的目标:实现了强大的预测能力,并利用我们的模型的优势来识别不确定性。我们还利用这一点来说一些关于异常检测。

摘要

在这篇文章中,我复制了一个异常检测和预测的好方法。我们利用 LSTM 网络来了解纽约市的出租车需求行为。我们利用学到的知识进行预测,同时估计不确定性。我们隐含地将异常定义为不可预测的观察结果——即具有很大的不确定性。这个简单的假设允许我们的 LSTM 为我们做所有的工作。

查看我的 GITHUB 回购

保持联系: Linkedin

置换欠采样和时间相关的异常检测

原文:https://towardsdatascience.com/anomaly-detection-with-permutation-undersampling-and-time-dependency-5919e7c695d0?source=collection_archive---------31-----------------------

预测失衡情况下的政策转变

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

Photo by Francisco Ghisletti on Unsplash

在异常检测中,最乏味的问题之一是处理不平衡。我们作为数据科学家的角色是,在第一阶段,检测导致异常行为的模式。第二,开发特别的 ML 模型,该模型覆盖类不平衡并试图返回最佳结果。

我们在这篇文章中所做的就是利用不平衡。通过构建一个聪明的管道和一些技巧,我们将能够提高我们的 ML 模型的性能。

详细地说,我们分析了一个转换率预测的问题,但我们的方法并不只是专门针对这项任务。不平衡分类的类似问题可以是欺诈检测、流失预测、剩余寿命估计、毒性检测等等。

数据集

我为我们对 Kaggle 的分析找到了一个很好的基准,直接来自过去的比赛( Homesite 报价转换),目的是让一切变得更加真实和有趣。

该数据集代表了对购买保单感兴趣的大量客户的活动。每个条目对应于一个潜在客户,QuoteConversion_Flag 指示该客户是否购买了保单。

所提供的特征(总共 296 个)是匿名的,并且提供了潜在客户和保单的丰富表示。它们包括特定的覆盖范围信息、销售信息、个人信息、财产信息和地理信息。我们的任务是预测 QuoteConversion_Flag。

我们必须管理 211,859 次未转化中的 48,894 次成功转化(占总数的 23.07%)。如你所见,这是一个巨大的不平衡问题!

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

Label distribution on full dataset

验证策略

在我看来,当我们面临像这样的分类问题时,我们必须做的第一件事是对时间依赖的存在进行推理。这里,时间模式的存在由“原始报价日期”列给出。记住时间特征是重要的,以便开发一个健壮的验证方案,它以最好的方式反映现实;也就是说,我们希望开发一个能够预测未来可能转换的模型。因此,开发强大而稳定的解决方案的最佳方式是根据“报价日期”在培训/测试中分割我们的数据。鉴于此,我将原始数据按时间排序,并将前 70%(从 2013 年 1 月 1 日到 2014 年 8 月 25 日)作为训练,将后 10%(从 2015 年 3 月 9 日到 2015 年 5 月 18 日)作为测试。我没有故意使用 20%的数据(从 2014 年 8 月 25 日到 2015 年 3 月 9 日),因为我想制造一个漏洞,我很好奇我们的模型对未来的预测有多好。

凭借强大的验证渠道,我们已经处于有利位置。我们现在要做的是比较两种不同的架构。一个是经典的,由一个简单的交叉验证的逻辑回归组成,另一个是更复杂的,由多个交叉验证的逻辑回归组成,其中我们操作负下采样。我们简单地从多数类中随机抽取一部分条目,以使其等于少数类(转换)。

模型

现在我们已经介绍了所有我们需要的,让我们使它工作。我不太关注特征工程和模型选择;我更喜欢说明一个在各个方面都可以定制的通用方法。

首先,我实现了基线模型的结构。它由一个交叉验证模式组成,在每一个折叠中,我用主成分分析将原始特征的维度减少到前 50 个组件,并拟合一个逻辑回归。我尝试了 StratifiedCrossValidation 标准,以了解它处理不平衡的能力以及对我们的数据进行良好概括的可能性。使用 5 个折叠进行训练时,我在折叠外拆分中获得了 0.837 的平均 AUC,在测试中获得了 0.773 的最终 AUC,这导致训练数据明显过度拟合!

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

同样的,少数类的召回值极低,不能令人满意。

我们的第二个架构也是基于交叉验证模式,其中我像降维前一样操作,并拟合逻辑回归。与前一种情况不同,它在以下方面有所不同:

  • 我选择一个简单的 Kfold 交叉验证过程,没有洗牌;
  • 在交叉验证循环之前,我减少了对少数类采样不足的初始训练数据集(所选条目的选择是随机的);
  • 当整个交叉验证过程结束时,我存储结果并全部重复……我没有发疯,我全部重复(给定次数),改变构成欠采样类样本的条目,即,我改变采样的种子;
  • 最后,我平均所有的结果,获得置换种子,并计算性能(也堆叠西装)。
for s, seed in enumerate(seeds):

    train_pos = X_train.loc[y_train == 1, features].copy()
    train_pos['QuoteConversion_Flag'] = [1]*neg_istances
    train_pos['Quote_Date'] = Time_train[y_train == 1]
    train_neg = X_train.loc[y_train == 0, features].copy()
    train_neg['QuoteConversion_Flag'] = [0]*pos_istances
    train_neg['Quote_Date'] = Time_train[y_train == 0]
    train_neg = train_neg.sample(neg_istances, random_state=seed)

    train = pd.concat([train_pos, 
                       train_neg]).sort_values('Quote_Date')
    y = train.QuoteConversion_Flag.values
    train = train.drop(['Quote_Date',
                        'QuoteConversion_Flag'], 
                       axis=1).reset_index(drop=True)

    for fold,(in_index,oof_index) in enumerate(skf.split(train, y)):

        print(fold+1, 'FOLD --- SEED', seed)

        scaler = StandardScaler()
        pca = PCA(n_components=50, random_state=seed)

        y_in, y_oof = y[in_index], y[oof_index]
        X_in = train.iloc[in_index, :]
        X_in = scaler.fit_transform(X_in)
        X_in = pca.fit_transform(X_in)
        X_oof = train.iloc[oof_index, :]
        X_oof = scaler.transform(X_oof)
        X_oof = pca.transform(X_oof)

        model = LogisticRegression(C=0.1, solver="lbfgs", 
                                   max_iter=1000)
        model.fit(X_in, y_in)

        yoof[oof_index,s] = model.predict_proba(X_oof)[:,1]
        pred[:,s] += model.predict_proba(
                        pca.transform(
                            scaler.transform(X_test[features])
                        ))[:,1]

        print('AUC', roc_auc_score(y_oof, yoof[oof_index,s]))
        AUC[s] += roc_auc_score(y_oof, yoof[oof_index,s])  

        del model; del pca; del scaler

pred = pred/n_splits
AUC = AUC/n_splits

非折叠分割的 AUC 为 0.852(高于之前),但测试的相对 AUC 为 0.818。此外,混淆矩阵也有所改善。

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

这意味着我们能够在提高性能的同时减少过度拟合。这些结果之所以可能,有两个主要原因:

  • 我们利用了置换缩减采样,因为每次我改变种子时,我们都会在数据中引入一点多样性;
  • **我们选择了更现实的交叉验证模式,因为我们的数据遵循一种时间模式,使得现在(训练)不同于未来(测试)。**没有洗牌的 K-fold 能够在训练中重现这种依赖性,降低过度拟合。

摘要

在这篇文章中,我创建了一个有效的管道来处理训练和测试之间的数据不平衡和差异的情况。正如你所看到的,这是现实生活中的一个常见场景,但也经常在许多 Kaggle 比赛中出现。我们可以做的第一件事是定义一个好的验证模式,并尝试从采样技术中提取价值。这将允许我们获得更好的性能并减少计算时间。

查看我的 GITHUB 回购

保持联系: Linkedin

使用 SQL 进行异常检测

原文:https://towardsdatascience.com/anomaly-detection-with-sql-7700c7516d1d?source=collection_archive---------6-----------------------

有很多方法可以检测数据中的异常,就像生活中的大多数事情一样,没有一个明确的“正确的方法”来做到这一点。您采用的方法将由您的数据决定,但也取决于项目的要求。

这是否需要像信用欺诈检测一样尽可能准确,您是否只需要监控一些潜在问题的指标,这是否需要快速启动并运行,或者您是否有 6 个月的时间将其投入生产,您有什么样的可用资源等。

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

Anomalies Detected!!

异常检测有两种基本方法。你可以走基于规则的路线,也可以走机器学习的路线。机器学习模型,如隔离森林、局部离群因子、自动编码器等。都可以用来成功检测异常。如果你走这条路,你应该看看 sklearn 的以及《 手无监督学习 这本书,它们都是很好的起点。

然而,基于规则的方法工作得很好,更容易实现,更容易投入生产,启动和运行更快。根据您的需求,它们可能是最佳解决方案。

听着我明白了,每个人都想立即去机器/深度学习解决问题,因为让我们面对它,它很有趣,也很有挑战性。然而,走机器学习路线并不总是最好的选择,尤其是在商业环境中。

一种基于规则的方法效果很好并且易于在 SQL 中实现,那就是使用四分位数范围。IQR 被定义为数据集的 75%和 25%之间的差值。

如果一个数据点高于第 75 百分位 1.5 倍 IQR 或更多,或者低于第 25 百分位 1.5 倍 IQR 或更少,它们可以被认为是异常值。

  • *正异常值=第 75 百分位+ 1.5 (第 75 百分位-第 25 百分位)
  • *负异常值=第 25 百分位- 1.5 (第 75 百分位-第 25 百分位)

为什么是 1.5 倍而不是 2 倍或 3 倍?1.5x 相当于平均值以上的 3 个标准差(见下图)。你当然可以把它改成 1.75 倍或者 2.25 倍等等。这取决于您希望异常值检测有多“敏感”,这是使用 IQR 的另一个优点。

由于 IQR 使用中值而不是平均值,因此它被视为尺度的稳健度量,与使用平均值的度量(如标准差)相比,受少数异常值影响的可能性更小。这将更容易识别实际的异常值。

如果你曾经看过箱线图,那就是 IQR 离群点检测方法的可视化。“盒子”是 IQR,“胡须”位于第 25 和第 75 百分位,任何高于这些值的数据点(称为“飞行者”)都是异常值,如下图所示:

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

Source: Wikipedia

在我们开始这个例子之前,还有一些关于异常检测的注意事项。异常检测可以是单变量或多变量的。单变量更简单,更容易解释,因为您可以很容易地知道哪个指标触发了异常。如果您有多个指标,那么您可以设置单独的查询来检测每个指标的异常,这使得最终产品更容易理解。如果你走多元路线,机器学习可能更适合。异常检测也可以是有监督的或无监督的,但大多数时候是无监督的,就像我们在这里做的一样。

例子

我将使用 BigQuery 中的一个公共数据集,因此您可以自己重新创建它。“爱荷华州酒类销售”数据集(big query-public-data . Iowa _ liquid _ Sales . Sales)包含了爱荷华州自 2012 年以来的每日酒类销售情况。

酒类销售有很多不同的方式,包括城市、县、经纬度、类别、售出的瓶数、售出的数量等。在本例中,我将只查看一天的总销售额,但是您可以在表中的任何分项中发现异常。

带评论的完整问题可以在我的 GitHub 页面上找到,这里是一个要点。让我们来分解一下这个查询是做什么的。

我做的第一件事是创建一个 CTE(通用表表达式),用第 25 个百分位数、第 75 个百分位数和 IQR 制作一个表,用于查询的主要部分。

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

为了得到四分位数,我使用 BigQuery 的近似分位数函数。我们说我们需要 4 个分位数来创建一个数组,所以我们只需要用 offset 函数从数组中选择我们想要的分位数。

返回的数组如下所示[最小值,25,50,75,最大值]。如您所见,它还返回最小值和最大值。索引从零开始,所以应该是[0,1,2,3,4]。因此,对于第 25 个百分位数,我们使用偏移函数选择位置 1 的元素,依此类推。

接下来,我们进入查询的主要部分:

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

从内部查询开始,我们将再次获取每天的总酒类销售额,然后与我们在上面创建的 IQR CTE 进行交叉连接(不过要注意大型数据集上的交叉连接)。然后,我们将创建一个 case 语句,说明当天的酒类销售额是正/负异常值还是非异常值(内标)。为了便于显示,我们还获取了当天的总销售额和日期,并按日总销售额降序排列。这给了我们:

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

我们现在有一个名为“type”的列,它将告诉我们当天的酒类销售额是内值、正值异常值还是负值异常值。

让我们看看数据的分布情况,以确认查询是否有效。这是一个柱状图,左边显示的是几乎没有销售的日子,右边显示的是销售非常高的日子。这两个问题都应该进一步调查。

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

这是一个显示异常值的箱线图。您可以看到,箱线图反映了查询,正异常值被确定为大约 2.1MM,就像我们在上面的输出中看到的那样。

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

现在,您可以安排这个查询每天运行(或者根据需要频繁运行)并输出到一个表中。然后你有一个表,自动更新,识别离群值,你可以连接到你的可视化工具的选择。

您还可以更进一步,在云函数/lambda 中运行它,并在检测到异常时通过 api 自动发送松弛警报/电子邮件,并提供一些关于异常的基本信息。我用这种方法自动对工作中的异常情况发出松弛警报,效果非常好。以后我会写一篇关于这个的帖子。

任何会使用 SQL 的人(分析师、数据科学家、工程师等)都很容易在短时间内建立并运行这样的东西。)而且也很有效。现在你可以回到你的机器/深度学习😃

基于时间序列预测的异常检测

原文:https://towardsdatascience.com/anomaly-detection-with-time-series-forecasting-c34c6d04b24a?source=collection_archive---------0-----------------------

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

嗨,这是一篇关于异常检测的后续文章(链接到上一篇文章:https://medium . com/my ntra-engineering/anomaly-detection-with-isolation-forest-visualization-23 CD 75 c 281 e 2其中我们使用无监督学习进行了异常检测)。

这里我们将看到用时间序列预测检测异常。时间序列是与时间相关的任何数据(每天、每小时、每月等)。例如:商店每天的收入是一个天级别的时间序列数据。许多用例,如需求估计、销售预测是一个典型的时间序列预测问题,可以通过像萨里玛、LSTM、霍尔特温特斯等算法来解决。时间序列预测通过用当前数据估计未来需求,帮助我们为未来需求做准备。一旦我们有了预测,我们就可以使用这些数据,通过与实际数据进行比较来发现异常情况。我们来实现一下,看看它的利弊。

安装和导入可视化库

#Installing specific version of plotly to avoid Invalid property for color error in recent version which needs change in layout
!pip install plotly==2.7.0
import pandas as pd
import numpy as np
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import plotly.plotly as py
import matplotlib.pyplot as plt
from matplotlib import pyplot
import plotly.graph_objs as go
init_notebook_mode(connected=True)
time_series_df=pd.read_csv('../input/time-series-data/time_series_data.csv')
time_series_df.head()

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

这里的数据顺序很重要,应该是**按时间顺序* *因为我们要预测下一个点。

将 load_date 列转换为 datetime 格式,并根据日期对数据进行排序。

time_series_df.load_date = pd.to_datetime(time_series_df.load_date, format='%Y%m%d')
time_series_df = time_series_df.sort_values(by="load_date")
time_series_df = time_series_df.reset_index(drop=True)
time_series_df.head()

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

提取数值并应用对数变换以稳定数据中的方差或在将数据输入模型之前使其稳定

actual_vals = time_series_df.actuals.values
actual_log = np.log10(actual_vals)

用测试数据中的 70 分来划分数据进行训练和测试。

首先让我们尝试应用 SARIMA 算法进行预测。SARIMA 代表季节性自回归综合移动平均线。它有一个季节性参数,由于我们销售数据的每周季节性,我们将其初始化为 7。其他参数是 p、d、q,它们是基于 ACF 和 PACF 图确定的,或者理想情况下,我们应该使用预测误差最小的参数。

更多细节可以在这里找到:https://people.duke.edu/~rnau/arimrule.htm

我不会在这里讨论获得正确参数集的问题,我们稍后将使用 Auto Arima 来解决这个问题,它允许我们在误差最小的范围内获得最佳参数集。

这里我指定差分因子(d)为 1。它帮助我们去除数据中的趋势和周期。

import math
import statsmodels.api as sm
import statsmodels.tsa.api as smt
from sklearn.metrics import mean_squared_error
from matplotlib import pyplot
import matplotlib.pyplot as plt
import plotly.plotly as py
import plotly.tools as tlstrain, test = actual_vals[0:-70], actual_vals[-70:]train_log, test_log = np.log10(train), np.log10(test)my_order = (1, 1, 1)
my_seasonal_order = (0, 1, 1, 7)

每次我们预测下一个数据点的**,我们循环遍历训练数据以预测下一个数据,并在预测后添加下一个数据点用于进一步预测。**

这就像一个移动窗口日水平数据(例如:前 90 点用于预测任何给定时间的下一点)。

通过的 10 次方变换将预测数据转换回比例,并绘制结果。

history = [x for x in train_log]
predictions = list()
predict_log=list()
for t in range(len(test_log)):
    model = sm.tsa.SARIMAX(history, order=my_order, seasonal_order=my_seasonal_order,enforce_stationarity=False,enforce_invertibility=False)
    model_fit = model.fit(disp=0)
    output = model_fit.forecast()
    predict_log.append(output[0])
    yhat = 10**output[0]
    predictions.append(yhat)
    obs = test_log[t]
    history.append(obs)
   # print('predicted=%f, expected=%f' % (output[0], obs))
#error = math.sqrt(mean_squared_error(test_log, predict_log))
#print('Test rmse: %.3f' % error)
# plot
figsize=(12, 7)
plt.figure(figsize=figsize)
pyplot.plot(test,label='Actuals')
pyplot.plot(predictions, color='red',label='Predicted')
pyplot.legend(loc='upper right')
pyplot.show()

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

Actuals vs Predict forecast plot

这是一个很好的时间序列预测。趋势、季节性是时间序列数据中的两个重要因素,如果您的算法能够捕捉到您数据的趋势(上升/下降),并且如果您的数据是季节性的(每周、每天、每年的模式),那么您的算法就适合您的情况。

在这里,我们可以观察到,我们的 SARIMA 算法从峰值中捕捉到了趋势(不是通过复制它,而是通过捕捉峰值),并在正常情况下很好地预测了实际值。

我们在这里指定的参数似乎很适合这个指标,但是要进行绘图、验证和调整参数将是一项非常艰巨的任务。一个解决方案是 Auto Arima ,它在我们指定的范围内返回算法的最佳参数集。

为 auto arima 安装金字塔-arima。

!pip install pyramid-arima
from pyramid.arima import auto_arima
stepwise_model = auto_arima(train_log, start_p=1, start_q=1,
                           max_p=3, max_q=3, m=7,
                           start_P=0, seasonal=True,
                           d=1, D=1, trace=True,
                           error_action='ignore',  
                           suppress_warnings=True, 
                           stepwise=True)

让我们使用 auto_arima 查找 p 和 q 参数,并将 d 指定为 1 表示一阶差分,将季节性指定为 7 表示每周季节性。

现在,auto arima 模型可以通过我们在上面执行的相同过程用于逐步预测:

import math
import statsmodels.api as sm
import statsmodels.tsa.api as smt
from sklearn.metrics import mean_squared_error
train, test = actual_vals[0:-70], actual_vals[-70:]train_log, test_log = np.log10(train), np.log10(test)# split data into train and test-setshistory = [x for x in train_log]
predictions = list()
predict_log=list()
for t in range(len(test_log)):
    #model = sm.tsa.SARIMAX(history, order=my_order, seasonal_order=my_seasonal_order,enforce_stationarity=False,enforce_invertibility=False)
    stepwise_model.fit(history)
    output = stepwise_model.predict(n_periods=1)
    predict_log.append(output[0])
    yhat = 10**output[0]
    predictions.append(yhat)
    obs = test_log[t]
    history.append(obs)
    #print('predicted=%f, expected=%f' % (output[0], obs))
#error = math.sqrt(mean_squared_error(test_log, predict_log))
#print('Test rmse: %.3f' % error)
# plot
figsize=(12, 7)
plt.figure(figsize=figsize)
pyplot.plot(test,label='Actuals')
pyplot.plot(predictions, color='red',label='Predicted')
pyplot.legend(loc='upper right')
pyplot.show()

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

在这种情况下,auto arima 和我们的初始 SARIMA 在预测方面做得很好,也没有过多地追逐实际值。

接下来,让我们用可用的实际数据和预测结果创建一个数据框架

predicted_df=pd.DataFrame()
predicted_df['load_date']=time_series_df['load_date'][-70:]
predicted_df['actuals']=test
predicted_df['predicted']=predictions
predicted_df.reset_index(inplace=True)
del predicted_df['index']
predicted_df.head()

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

我们有预测和实际的结果,使用这些信息来检测异常,我使用了数据分布的属性。请注意,这仅在数据分布为正态/高斯时才有效。

我检测异常的步骤:
1。计算误差项(实际-预测)。
2。计算滚动平均值和滚动标准差(窗口为一周)。
3。将误差为 1.5、1.75 和 2 个标准偏差的数据分类为低、中、高异常。(基于此属性,5%的数据点将被识别为异常)

我使用 lambda 函数对基于误差和标准偏差的异常进行分类,而不是使用单独的循环和函数。

import numpy as np
def detect_classify_anomalies(df,window):
    df.replace([np.inf, -np.inf], np.NaN, inplace=True)
    df.fillna(0,inplace=True)
    df['error']=df['actuals']-df['predicted']
    df['percentage_change'] = ((df['actuals'] - df['predicted']) / df['actuals']) * 100
    df['meanval'] = df['error'].rolling(window=window).mean()
    df['deviation'] = df['error'].rolling(window=window).std()
    df['-3s'] = df['meanval'] - (2 * df['deviation'])
    df['3s'] = df['meanval'] + (2 * df['deviation'])
    df['-2s'] = df['meanval'] - (1.75 * df['deviation'])
    df['2s'] = df['meanval'] + (1.75 * df['deviation'])
    df['-1s'] = df['meanval'] - (1.5 * df['deviation'])
    df['1s'] = df['meanval'] + (1.5 * df['deviation'])
    cut_list = df[['error', '-3s', '-2s', '-1s', 'meanval', '1s', '2s', '3s']]
    cut_values = cut_list.values
    cut_sort = np.sort(cut_values)
    df['impact'] = [(lambda x: np.where(cut_sort == df['error'][x])[1][0])(x) for x in
                               range(len(df['error']))]
    severity = {0: 3, 1: 2, 2: 1, 3: 0, 4: 0, 5: 1, 6: 2, 7: 3}
    region = {0: "NEGATIVE", 1: "NEGATIVE", 2: "NEGATIVE", 3: "NEGATIVE", 4: "POSITIVE", 5: "POSITIVE", 6: "POSITIVE",
              7: "POSITIVE"}
    df['color'] =  df['impact'].map(severity)
    df['region'] = df['impact'].map(region)
    df['anomaly_points'] = np.where(df['color'] == 3, df['error'], np.nan)
    df = df.sort_values(by='load_date', ascending=False)
    df.load_date = pd.to_datetime(df['load_date'].astype(str), format="%Y-%m-%d")return df

下面是一个可视化结果的函数。清晰全面的可视化同样重要,有助于业务用户对异常情况提供反馈,并使结果具有可操作性。

第一个图中的误差项指定了上限和下限。

突出显示异常的实际值图将易于用户解释/验证。因此,第二个图突出显示了实际值和预测值以及异常情况。

蓝线-实际值

橙色线条-预测的

红色-错误

绿色——移动平均线

虚线——正常行为的上限和下限

def plot_anomaly(df,metric_name):
    #error = pd.DataFrame(Order_results.error.values)
    #df = df.sort_values(by='load_date', ascending=False)
    #df.load_date = pd.to_datetime(df['load_date'].astype(str), format="%Y%m%d")
    dates = df.load_date
    #meanval = error.rolling(window=window).mean()
    #deviation = error.rolling(window=window).std()
    #res = error#upper_bond=meanval + (2 * deviation)
    #lower_bond=meanval - (2 * deviation)#anomalies = pd.DataFrame(index=res.index, columns=res.columns)
    #anomalies[res < lower_bond] = res[res < lower_bond]
    #anomalies[res > upper_bond] = res[res > upper_bond]
    bool_array = (abs(df['anomaly_points']) > 0)#And a subplot of the Actual Values.
    actuals = df["actuals"][-len(bool_array):]
    anomaly_points = bool_array * actuals
    anomaly_points[anomaly_points == 0] = np.nan#Order_results['meanval']=meanval
    #Order_results['deviation']=deviationcolor_map= {0: "'rgba(228, 222, 249, 0.65)'", 1: "yellow", 2: "orange", 3: "red"}
    table = go.Table(
    domain=dict(x=[0, 1],
                y=[0, 0.3]),
    columnwidth=[1, 2 ],
    #columnorder=[0, 1, 2,],
    header = dict(height = 20,
                  values = [['<b>Date</b>'],['<b>Actual Values </b>'],
                            ['<b>Predicted</b>'], ['<b>% Difference</b>'],['<b>Severity (0-3)</b>']],
                 font = dict(color=['rgb(45, 45, 45)'] * 5, size=14),
                  fill = dict(color='#d562be')),
    cells = dict(values = [df.round(3)[k].tolist() for k in ['load_date', 'actuals', 'predicted',
                                                               'percentage_change','color']],
                 line = dict(color='#506784'),
                 align = ['center'] * 5,
                 font = dict(color=['rgb(40, 40, 40)'] * 5, size=12),
                 #format = [None] + [",.4f"] + [',.4f'],#suffix=[None] * 4,
                 suffix=[None] + [''] + [''] + ['%'] + [''],
                 height = 27,
                 #fill = dict(color=['rgb(235, 193, 238)', 'rgba(228, 222, 249, 0.65)']))
                 fill=dict(color=  # ['rgb(245,245,245)',#unique color for the first column
                      [df['color'].map(color_map)],
                      )
    ))#df['ano'] = np.where(df['color']==3, df['error'], np.nan)anomalies = go.Scatter(name="Anomaly",
                       x=dates,
                       xaxis='x1',
                       yaxis='y1',
                       y=df['anomaly_points'],
                       mode='markers',
                       marker = dict(color ='red',
                      size = 11,line = dict(
                                         color = "red",
                                         width = 2)))upper_bound = go.Scatter(hoverinfo="skip",
                         x=dates,
                         showlegend =False,
                         xaxis='x1',
                         yaxis='y1',
                         y=df['3s'],
                         marker=dict(color="#444"),
                         line=dict(
                             color=('rgb(23, 96, 167)'),
                             width=2,
                             dash='dash'),
                         fillcolor='rgba(68, 68, 68, 0.3)',
                         fill='tonexty')lower_bound = go.Scatter(name='Confidence Interval',
                          x=dates,
                         xaxis='x1',
                         yaxis='y1',
                          y=df['-3s'],
                          marker=dict(color="#444"),
                          line=dict(
                              color=('rgb(23, 96, 167)'),
                              width=2,
                              dash='dash'),
                          fillcolor='rgba(68, 68, 68, 0.3)',
                          fill='tonexty')Actuals = go.Scatter(name= 'Actuals',
                     x= dates,
                     y= df['actuals'],
                    xaxis='x2', yaxis='y2',
                     mode='line',
                     marker=dict(size=12,
                                 line=dict(width=1),
                                 color="blue"))Predicted = go.Scatter(name= 'Predicted',
                     x= dates,
                     y= df['predicted'],
                    xaxis='x2', yaxis='y2',
                     mode='line',
                     marker=dict(size=12,
                                 line=dict(width=1),
                                 color="orange"))# create plot for error...
    Error = go.Scatter(name="Error",
                   x=dates, y=df['error'],
                   xaxis='x1',
                   yaxis='y1',
                   mode='line',
                   marker=dict(size=12,
                               line=dict(width=1),
                               color="red"),
                   text="Error")anomalies_map = go.Scatter(name = "anomaly actual",
                                   showlegend=False,
                                   x=dates,
                                   y=anomaly_points,
                                   mode='markers',
                                   xaxis='x2',
                                   yaxis='y2',
                                    marker = dict(color ="red",
                                  size = 11,
                                 line = dict(
                                     color = "red",
                                     width = 2)))Mvingavrg = go.Scatter(name="Moving Average",
                           x=dates,
                           y=df['meanval'],
                           mode='line',
                           xaxis='x1',
                           yaxis='y1',
                           marker=dict(size=12,
                                       line=dict(width=1),
                                       color="green"),
                           text="Moving average")axis=dict(
    showline=True,
    zeroline=False,
    showgrid=True,
    mirror=True,
    ticklen=4,
    gridcolor='#ffffff',
    tickfont=dict(size=10))layout = dict(
    width=1000,
    height=865,
    autosize=False,
    title= metric_name,
    margin = dict(t=75),
    showlegend=True,
    xaxis1=dict(axis, **dict(domain=[0, 1], anchor='y1', showticklabels=True)),
    xaxis2=dict(axis, **dict(domain=[0, 1], anchor='y2', showticklabels=True)),
    yaxis1=dict(axis, **dict(domain=[2 * 0.21 + 0.20 + 0.09, 1], anchor='x1', hoverformat='.2f')),
    yaxis2=dict(axis, **dict(domain=[0.21 + 0.12, 2 * 0.31 + 0.02], anchor='x2', hoverformat='.2f')))fig = go.Figure(data = [table,anomalies,anomalies_map,
                        upper_bound,lower_bound,Actuals,Predicted,
                        Mvingavrg,Error], layout = layout)iplot(fig)
pyplot.show()classify_df=detect_classify_anomalies(predicted_df,7)
classify_df.reset_index(inplace=True)
del classify_df['index']
plot_anomaly(classify_df,"metric_name")

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

通过使用滚动平均值和标准偏差,我们能够避免在大减价日这样的场景中出现连续的错误异常。

突出显示第一个峰值或谷值,之后调整阈值。

此外,提供实际数据的表格根据异常水平预测了变化和条件格式。

接下来,我们还尝试使用 LSTM 预测,这是一个递归神经网络。

https://machine learning mastery . com/time-series-prediction-lstm-recurrent-neural-networks-python-keras/是一个非常好的使用 lstm 进行时间序列预测的教程,我们将在这里使用部分代码作为我们的用例。

以下是用于差分、与它们的倒数一起缩放以及训练和预测LSTM的辅助函数。

from pandas import DataFrame
from pandas import Series
from pandas import concat
from pandas import read_csv
from pandas import datetime
from sklearn.metrics import mean_squared_error
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from math import sqrt

# frame a sequence as a supervised learning problem
def timeseries_to_supervised(data, lag=1):
    df = DataFrame(data)
    columns = [df.shift(i) for i in range(1, lag+1)]
    columns.append(df)
    df = concat(columns, axis=1)
    df.fillna(0, inplace=True)
    return df# create a differenced series
def difference(dataset, interval=1):
    diff = list()
    for i in range(interval, len(dataset)):
        value = dataset[i] - dataset[i - interval]
        diff.append(value)
    return Series(diff)# invert differenced value
def inverse_difference(history, yhat, interval=1):
    return yhat + history[-interval]# scale train and test data to [-1, 1]
def scale(train, test):
    # fit scaler
    scaler = MinMaxScaler(feature_range=(-1, 1))
    scaler = scaler.fit(train)
    # transform train
    train = train.reshape(train.shape[0], train.shape[1])
    train_scaled = scaler.transform(train)
    # transform test
    test = test.reshape(test.shape[0], test.shape[1])
    test_scaled = scaler.transform(test)
    return scaler, train_scaled, test_scaled# inverse scaling for a forecasted value
def invert_scale(scaler, X, value):
    new_row = [x for x in X] + [value]
    array = np.array(new_row)
    array = array.reshape(1, len(array))
    inverted = scaler.inverse_transform(array)
    return inverted[0, -1]# fit an LSTM network to training data
def fit_lstm(train, batch_size, nb_epoch, neurons):
    X, y = train[:, 0:-1], train[:, -1]
    X = X.reshape(X.shape[0], 1, X.shape[1])
    model = Sequential()
    model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True))
    model.add(Dense(1))
    model.compile(loss='mean_squared_error', optimizer='adam')
    for i in range(nb_epoch):
        model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
        model.reset_states()
    return model# make a one-step forecast
def forecast_lstm(model, batch_size, X):
    X = X.reshape(1, 1, len(X))
    yhat = model.predict(X, batch_size=batch_size)
    return yhat[0,0]#### LSTM
supervised = timeseries_to_supervised(actual_log, 1)
supervised_values = supervised.values# split data into train and test-sets
train_lstm, test_lstm = supervised_values[0:-70], supervised_values[-70:]# transform the scale of the data
scaler, train_scaled_lstm, test_scaled_lstm = scale(train_lstm, test_lstm)# fit the model                 batch,Epoch,Neurons
lstm_model = fit_lstm(train_scaled_lstm, 1, 850 , 3)
# forecast the entire training dataset to build up state for forecasting
train_reshaped = train_scaled_lstm[:, 0].reshape(len(train_scaled_lstm), 1, 1)
#lstm_model.predict(train_reshaped, batch_size=1)

使用 LSTM 预测数据并绘制结果

from matplotlib import pyplot
import matplotlib.pyplot as plt
import plotly.plotly as py
import plotly.tools as tls# walk-forward validation on the test data
predictions = list()
for i in range(len(test_scaled_lstm)):
#make one-step forecast
    X, y = test_scaled_lstm[i, 0:-1], test_scaled_lstm[i, -1]
    yhat = forecast_lstm(lstm_model, 1, X)
    # invert scaling
    yhat = invert_scale(scaler, X, yhat)
    # invert differencing
    #yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)
    # store forecast
    predictions.append(10**yhat)
    expected = actual_log[len(train_lstm) + i ]
# line plot of observed vs predicted
figsize=(12, 7)
plt.figure(figsize=figsize)
pyplot.plot(actual_vals[-70:],label='Actuals')
pyplot.plot(predictions, color = "red",label='Predicted')
pyplot.legend(loc='upper right')
pyplot.show()

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

LSTM 也很适合这个指标。LSTM 神经网络的重要参数是激活函数、神经元数量、批量大小和时期,需要对其进行调整以获得更好的结果。

现在,让我们在不同的指标数据中尝试一下。数据是同一时期的。

tf_df=pd.read_csv('../input/forecast-metric2/time_series_metric2.csv')
tf_df.head()

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

按照与上述相同的步骤,我们使用 auto arima 获得最佳参数并逐步预测。

绘制实际结果和预测结果。

actual_vals = tf_df.actuals.values
train, test = actual_vals[0:-70], actual_vals[-70:]
train_log, test_log = np.log10(train), np.log10(test)
from pyramid.arima import auto_arima
stepwise_model = auto_arima(train_log, start_p=1, start_q=1,
                           max_p=3, max_q=3, m=7,
                           start_P=0, seasonal=True,
                           d=1, D=1, trace=True,
                           error_action='ignore',  
                           suppress_warnings=True, 
                           stepwise=True)
history = [x for x in train_log]
predictions = list()
predict_log=list()
for t in range(len(test_log)):
    #model = sm.tsa.SARIMAX(history, order=my_order, seasonal_order=my_seasonal_order,enforce_stationarity=False,enforce_invertibility=False)
    stepwise_model.fit(history,enforce_stationarity=False,enforce_invertibility=False)
    output = stepwise_model.predict(n_periods=1)
    predict_log.append(output[0])
    yhat = 10**output[0]
    predictions.append(yhat)
    obs = test_log[t]
    history.append(obs)
    #print('predicted=%f, expected=%f' % (output[0], obs))
#error = math.sqrt(mean_squared_error(test_log, predict_log))
#print('Test rmse: %.3f' % error)
# plot
figsize=(12, 7)
plt.figure(figsize=figsize)
pyplot.plot(test,label='Actuals')
pyplot.plot(predictions, color='red',label='Predicted')
pyplot.legend(loc='upper right')
pyplot.show()

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

这里,算法试图追踪实际值。虽然这可能是一个误差较低的好预测,但是实际中的异常行为不能用这个来识别。

这是一个使用预测技术进行异常检测的问题。我们试图捕捉数据中的趋势/季节性,同时不对误差进行过多优化,以获得实际值的精确副本(这使得我们难以发现异常)。

每个指标都需要用微调的参数进行验证,以便在使用预测来检测异常时检测到异常。此外,对于具有不同数据分布的指标,需要遵循不同的方法来识别异常。

另一个缺点是,隔离林我们检测到一个用例的异常,该用例一次包含多个指标,我们向下钻取其中单个指标的异常。而使用预测机制,我们需要一个单独的关联逻辑,因为预测是针对指标的

而像隔离森林这样的算法从数据中分离出异常行为,这些异常行为可用于归纳多个指标。

又一起自动驾驶车祸,又一堂人工智能开发课

原文:https://towardsdatascience.com/another-self-driving-car-accident-another-ai-development-lesson-b2ce3dbb4444?source=collection_archive---------13-----------------------

作为一名数据科学家,优步能从自动驾驶汽车事故中学到什么

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

Photo from https://blogs.nvidia.com

他的事故实际上发生在大约一年半前,发生在一辆优步的自动驾驶汽车上,并夺走了一名女性的生命。这对 AI 社区是一个严重的提醒,正在做的工作承载着很多重量,有时是其他人的生命。

对所发生事情的回顾

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

T 他的可怕事故发生在 2018 年 3 月 19 日深夜。一辆优步自动驾驶汽车在自动模式下行驶,方向盘后面有一名安全驾驶员,在亚利桑那州坦佩撞死了一名女子。详细的调查结果可以在这里找到。从仪表板摄像头和内部驾驶座摄像头的录像来看,事故发生在一条光线不足的道路上,限速 40 英里/小时。在汽车撞上这名女子之前,这名安全司机正在看她的手机(可能在看 Hulu)。根据优步在撞车后获得的遥测数据,算法将这些女性分类为’未知物体,然后是’车辆,然后是’自行车’,在此过程中,优柔寡断导致了非常晚的行动(在撞车前 1.3 秒命令汽车停下),最终导致了悲剧的发生。激光雷达或雷达传感器都没有触发,也没有付费的安全司机看到行人。以上任何一种方法,如果有效,都有可能挽救这位妇女的生命。这起事故已经过去了一段时间,优步已经恢复在道路上测试他们的自动驾驶汽车。然而,从数据科学的角度多思考一些问题可能是有价值的,这些问题是什么,优步的自动驾驶系统中有哪些缺陷导致了这场悲剧。

自动驾驶系统可能存在的缺陷

在深入探讨自动驾驶系统的潜在缺陷之前,值得注意的是,自动驾驶汽车实际上是人工智能的最先进应用,最接近于 AGI(人工智能)。首先,驾驶是一项非常复杂且潜在相当危险的行为。自动驾驶汽车必须应对的环境可能非常复杂,需要各种情况意识:其他汽车、行人、自行车、交通信号、标志、天气、路况等。诚然,这些年人工智能已经取得了很大的进步,但对于这项任务来说,它足够好吗?不管答案是什么,所有可能的问题都应该彻底解决和测试,不遗余力。这导致了该系统的第一个也是最重要的方面,即开发自动驾驶汽车的团队。

应用人工智能开发团队有时工程师人手不足

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

Photo from https://365datascience.com

做数据科学工作不一定需要硕士或者博士,但是统计数据显示行业内的数据科学家绝大多数至少有硕士学历。他们中的很大一部分人甚至拥有博士学位。这是非常合理的,因为人工智能和数据科学不是微不足道的领域。它需要多年的数学、计算机科学和各种技术的训练。这已经是业界的共识。这种共识如此强烈,有时人们会忘记其他同样重要的角色,以使自动驾驶汽车等现实生活中的人工智能项目取得成功。最重要的是,工程。如果需要证明某个算法对于某个单一目的任务的性能(比如放射学图像识别),你不需要太多的工程能力。一个可靠的数据科学家可能会做得足够好。如果在 web 上开发和部署一个机器学习应用程序来分析评论情绪是一项任务,那么你可能需要雇用更多可靠的开发人员和 DevOps 工程师来确保该应用程序结构良好、精心编码并且易于维护。那么,如果你想建立一个自动驾驶汽车系统,需要在现实世界中维持许多小时而不发生任何事故,那该怎么办呢?你可能想雇佣汽车设计师、监管专家、汽车安全专家、物理学家和一些顶尖的数据科学家来创建一个多元化的团队,以便正确处理这项任务。对于这起优步自动驾驶汽车事件,自动驾驶汽车未能迅速做出反应的一个原因是,激光雷达和雷达系统都没有捕捉到过马路的女子。优步从使用 7 个激光雷达传感器改为只在汽车顶部使用一个,这在汽车周围产生了一些“盲点”。这是什么原因呢?出于安全原因,是否有其他工程债务需要承保?传感器的放置是否存在任何设计缺陷?环境中是否存在任何干扰问题?传感器和中央计算机之间的通信通道是否顺畅?这并不是说这些是确切的情况,只是这些是需要被询问和解决的问题,解决这些问题的最佳人才类型是工程师,而不是数据科学家。

小数据

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

现在,小数据是一个需要解决的数据科学问题。这意味着要建立一个有效的模型,每种情况下都需要大量的数据来训练模型。但有时不平衡数据问题很难解决,而且成本很高。以自动驾驶汽车为例。说到安全,最重要的是什么时候出了问题。收集的不同事故类型的数据越多,就越有利于训练一个足够稳健的模型,使其能够在所有条件下自行处理。但与装有黑匣子的飞机不同,车祸数据更难收集。首先,很难“产生”或“制造”事故。其次,并不是所有的汽车都配备了传感器来收集事故发生时的数据(一些更“智能”的汽车,如特斯拉,可能可以,但大多数汽车还没有)。作为数据科学家,一个共识是高性能模型的瓶颈通常不是算法,而是数据。如果没有足够的车祸相关数据,数据科学家将很难开发出一个能够很好地处理这些事故类型的模型。要做出一个能在街上驾驶汽车,转弯,适当加速/减速的自动驾驶汽车系统,并不是最难的任务。最困难的任务是在没有足够数据的情况下,创建一个能很好地处理所有事故的模型。

处理边缘情况

这实际上是小数据问题的一个更极端的例子,但值得一提。安全的一个经验法则是考虑所有可能出错的边缘情况,并做好准备。这对人类来说不是问题,因为人类比任何算法都具有常识和更广泛的情境意识,所以人类更有准备来处理边缘情况,但算法通常不够复杂,因此需要更多的工作。

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

Photo from https://www.chron.com

让我们想象一些边缘情况。

**道路上的洪水:**人类会后退,或者选择一些更平坦的草地来穿越洪水,但如果汽车只接受在道路上驾驶的训练,它无法正确处理这一点。

**非常滑的路:**人类会改变他们的驾驶模式,非常轻柔地转弯以避免打滑。或者停下来放防雪链,AI 就很难达到同等水平的灵活度。

**涂鸦之路:**人类很容易知道发生了什么,不会出错,但 AI 如果没有受过涂鸦之路的训练,可能会把涂鸦误认为是真实的道路指引。

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

这个清单还在继续。如果你能从过去的驾驶经历中想到你遇到的其他边缘案例,请在下面留下回应。底线是,在现实世界中驾驶需要更复杂的系统来处理所有奇怪的情况,人类非常擅长这一点(因此这是有保证的)。而人工智能需要在每种情况下进行训练。没有捷径。提出这些边缘案例并围绕其设计自动驾驶系统的能力将获得鲁棒性和安全性分数,并可能在竞争中获得优势。

哪里需要改进

那么自动驾驶车祸应该阻止技术的发展吗?当然不是!这项技术在拯救许多生命方面有巨大的潜力。人工智能可能有偏见或不够复杂,但它有一个人类没有的优点。他们永远不会变得情绪化、鲁莽或困倦。如果做得好,在大多数情况下,它应该在安全性方面优于人类,但显然它还没有做到这一点。那么流程的哪些部分可以改进呢?(我本人并不是自动驾驶汽车专家,只是想在本文中探索各种可能性,所以对以下内容持保留态度。如果你有更好的想法,欢迎在下面留下回应!)

测试过程

同样,在深入研究技术之前,需要首先解决与人相关的问题。这起事故中特别令人惊讶的一点是,这辆车竟然有一名安全驾驶员。如果安全司机尽职尽责,不看手机,眼睛盯着路面,整件事本来是可以避免的。这并不难做到,但她未能做到这一点间接代价是一条生命。这与技术无关,但与如何改善自驾测试过程有关。让一名付费的安全司机开车,为测试增加一层安全,这是一个好的开始,但人类会犯错误。既然汽车已经有一个内部摄像头监控司机,为什么不开发一种算法来监控她/他的行为,并在她/他的眼睛离开道路时给出警告/分数?

五金器具

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

Photo from https://labs.sogeti.com

激光雷达/雷达在这起事故中未能触发。原因是什么?多加一个传感器会不会效果更好?添加更多类型的传感器?优化传感器的位置?传感器需要在任何天气条件下都能工作。炎热、高温、下雪、极度晒伤、刮风等。如果没有,要有后备计划。做好极端的准备。

软件

中央驾驶系统有一个优先控制系统,意味着传感器或图像识别系统上触发的一些特殊事件将导致汽车立即停止以避免严重事故,超越所有其他驾驶控制系统。(例如,硬代码确保前方净距离)优先系统需要仔细设计和调整,以实现最大的安全性。

算法

对于所有机器学习模型来说非常重要的一点是验证集。一个好的验证集定义了模型的泛化能力,从而在很大程度上决定了项目在现实生活中的成败。这也适用于自动驾驶汽车。这里什么是好的验证集?嗯,驾驶汽车不像我们的分类器问题那么简单,因此没有非常明确的定义。这正是问题所在。所有自动驾驶汽车公司和监管机构是否应该合作,开发一个良好的“测试例程”,捕捉所有极端情况、边缘情况、测试场景、自动测试软件等。,以有效地充当自动驾驶汽车的“验证集”?我认为,所有参与者在这方面达成一致并做出努力是至关重要的,但这一点还没有得到充分探讨。

最后的想法

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

Photo by Ciprian Morar on Unsplash

无论自动驾驶汽车取得了多大的进展,有时感觉就像只是触及表面,水下潜伏的冰山的大小仍然未知。此外,自动驾驶汽车事故通常会受到媒体的高度关注。据《连线》报道,去年仅在美国就有近 4 万人死于交通事故,但很少有人(如果有的话)像优步事件那样成为头条新闻。不公平?不真的。这其实是一件好事。严格和密切的审查是一件好事,可以推动自动驾驶汽车的安全极限。因为人命关天。

更新:调查的最终结果将于 2019 年 11 月 20 日公布。你可以参考这篇由 The Verge 撰写的文章。

觉得这篇文章有用?在 Medium 上关注我(李立伟)或者你可以在 Twitter @lymenlee 或者我的博客网站wayofnumbers.com上找到我。你也可以看看我下面最受欢迎的文章!

[## “这是 CS50”:开始数据科学教育的愉快方式

为什么 CS50 特别适合巩固你的软件工程基础

towardsdatascience.com](/this-is-cs50-a-pleasant-way-to-kick-off-your-data-science-education-d6075a6e761a) [## 一枚硬币的两面:杰瑞米·霍华德的 fast.ai vs 吴恩达的 deeplearning.ai

如何不通过同时参加 fast.ai 和 deeplearning.ai 课程来“过度适应”你的人工智能学习

towardsdatascience.com](/two-sides-of-the-same-coin-fast-ai-vs-deeplearning-ai-b67e9ec32133) [## 你需要了解网飞的“朱庇特黑仔”:冰穴📖

是时候让 Jupyter 笔记本有个有价值的竞争对手了

towardsdatascience.com](/what-you-need-to-know-about-netflixs-jupyter-killer-polynote-dbe7106145f5)

机器学习中特征选择的方差分析

原文:https://towardsdatascience.com/anova-for-feature-selection-in-machine-learning-d9305e228476?source=collection_archive---------2-----------------------

方差分析在特征选择中的应用

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

Photo by Fahrul Azmi

机器学习中最大的挑战是选择最佳特征来训练模型。我们只需要高度依赖于响应变量的特征。但是如果响应变量是连续的,而预测变量是分类的呢???

ANOVA(AnanalysisofVariance)帮助我们完成选择最佳特征的工作

在这篇文章中,我将带您了解

a.差异的影响

b.f 分布

c.方差分析

c.举例说明单因素方差分析

差异的影响

方差是一个变量中数字之间分布的度量。它衡量一个数字与平均值和变量中每个数字的距离。

特征的方差决定了它对响应变量的影响程度。如果方差较低,则意味着该特性对响应没有影响,反之亦然。

f 分布

通常用于方差分析的概率分布。它假设假设为

H0:两个方差相等

H1:两个方差不相等

自由度

自由度是指逻辑上独立的值的最大数量,这些值可以自由变化。简而言之,它可以定义为观测值的总数减去施加在观测值上的独立约束的数量。

Df = N -1 其中 N 是样本大小

f 值

它是两个卡方分布的比率除以它的自由度。

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

F value

让我们求解上面的方程,看看它对分析方差有什么用处。

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

F ratio

在现实世界中,我们总是处理样本,因此比较标准差几乎等于比较方差。

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

image from https://newonlinecourses.science.psu.edu

在上图中,我们可以观察到 F 分布的形状总是依赖于自由度。

方差分析

方差分析方差分析是一种统计方法,用于检验两个或两个以上显著不同的组的均值。它假设假设为

H0:所有群体的手段都是平等的。

H1:至少有一组是不同的。

均值比较如何转化为方差比较?

考虑下图中的两种分布及其行为。

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

Behavior of distributions

从上图中,我们可以说,如果分布重叠或接近,大平均值将类似于个体平均值,而如果分布较远,大平均值和个体平均值相差较大。

指各组之间的差异,因为各组中的值不同。所以在方差分析中,我们将比较组间差异和组内差异。

ANOVA 使用 F-tet 检查各组之间是否有任何显著差异。如果所有方差相等的组之间没有显著差异,ANOVA 的 F 比率结果将接近 1。

举例说明单因素方差分析

  1. 单向 ANOVA 检验分类预测值与连续反应之间的关系。
  2. 在这里,我们将检查连续反应的分类特征组之间是否有相等的方差。
  3. 如果组之间的方差相等,则意味着该特征对响应没有影响,并且可以不考虑用于模型训练。

让我们考虑一个包含学生表现数据的学校数据集。我们必须根据年龄、监护人、学习时间、失败、活动等特征来预测学生的最终成绩。

通过使用单因素方差分析,我们可以确定监护人对最终成绩是否有任何影响。下面是数据

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

Student final grades by the guardian

我们可以看到监护人(母亲、父亲、其他)为列,学生最终成绩为行。

执行单向方差分析的步骤

  1. 定义假设
  2. 计算平方和
  3. 确定自由度
  4. f 值
  5. 接受或拒绝零假设

定义假设

H0:“守护者”中的所有等级或团体都有相同的方差

H1:至少有一个群体是不同的。

计算平方和

平方和是用于确定数据点离差的统计技术。它是偏差的度量,可以写成

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

Sum of Squares

如 ANOVA 中所述,我们必须进行 f 检验,通过比较组间方差和组内方差来检查组间是否存在任何方差。这可以通过使用平方和来完成,定义如下。

总平方和

每个观察点 x 与大平均值 xbar 之间的距离是 x-xbar。如果您计算每个数据点之间的距离,请计算每个距离的平方,并将您得到的所有平方距离相加

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

Total Sum of Squares

之间的平方和

各组平均值 g 与 grand means xbar 之间的距离为 g-xbar。类似于我们得到的平方和

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

Between the Sum of Squares

平方和内

组 x 内的每个观察值与组均值 g 之间的距离为 x-g。类似于我们得到的平方和

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

Within the Sum of Squares

总平方和=间平方和+内平方和

确定自由度

我们已经讨论了自由度的定义,现在我们将计算组间和组内的自由度。

  1. 因为我们有 3 个组(母亲、父亲、其他),所以组之间的自由度可以给定为(3–1)= 2。
  2. 每组有 18 个样本,组内的自由度将是所有组的自由度之和,即(18–1)+(18–1)+(18–1)= 51。

f 值

因为我们比较的是组间方差和组内方差。F 值由下式给出

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

F value

计算平方和和 F 值这里是总结。

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

ANOVA table

接受或拒绝零假设

在 95%的置信度下,alpha = 0.05,df1 =2,df2 =51 从 F 表给定 F 值为 3.179,计算出的 F 值为 18.49。

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

F test

在上图中,我们看到计算出的 F 值落在超出我们置信水平的剔除区域内。所以我们拒绝零假设。

总之,由于零假设被拒绝,这意味着组之间存在差异,这表明监护人对学生的最终分数有影响。因此,我们将在模型训练中包含此功能。

使用单因素方差分析,我们可以只检查单个预测因子与反应,并确定关系,但如果你有两个预测因子呢?我们将使用双向方差分析,如果有两个以上的特征,我们将进行多因素方差分析。

使用双向或多因素方差分析,我们可以检查以下响应的关系

  1. 《卫报》会影响学生的最终成绩吗?
  2. 学生活动会影响学生的最终成绩吗?
  3. 《卫报》和学生活动一起会影响期末成绩吗?

得出以上结论做一个测试总是有趣的,对吗??我正在写一篇关于双向多因素方差分析的文章,会写得更有趣。

在这里,我们处理了连续响应和分类预测如果回答是分类的,预测器也是分类的,请查看我的文章 卡方检验机器学习中的特征选择

[## 机器学习中特征选择的卡方检验

我们总是想知道卡方检验在机器学习中的什么地方有用,以及这个检验有什么不同。功能…

towardsdatascience.com](/chi-square-test-for-feature-selection-in-machine-learning-206b1f0b8223)

希望你喜欢!!敬请期待!!!请对任何疑问或建议发表评论!!!!

ANOVA 估计平方和的三种类型:不要选错!

原文:https://towardsdatascience.com/anovas-three-types-of-estimating-sums-of-squares-don-t-make-the-wrong-choice-91107c77a27a?source=collection_archive---------0-----------------------

在本文中,我将解释计算方差分析平方和的三种不同方法,方差分析是一种使用统计显著性比较不同组平均值的常用统计方法。

这篇文章直接进入双向方差分析。如果你需要回到更基本的单因素方差分析,请查阅我以前的文章。

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

Ronald Fisher, the guy who invented ANOVA.

1.双向方差分析基础概述

双向方差分析的目的是将因变量的总变异(以平方和衡量)分成不同的变异源。这使我们能够发现我们的自变量是否对因变量有显著影响。

双向方差分析是有 2 个独立变量的方差分析。

存在三种不同的分裂变异方法:第一类、第二类和第三类平方和。在不平衡数据的情况下,它们不会给出相同的结果。

I 型、II 型和 III 型方差分析结果不同!

根据工作日和天气解释销售(笔记本在这里)

我将在一个实际的例子中应用这三种平方和来看它们的区别:

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

An example with data for two way ANOVA

2.第一类平方和

第一类平方和,也称为序列平方和,以序列顺序分配变量。

如果模型有两个自变量 A 和 B 以及交互作用效应,按顺序指定,I 类平方和将:

  • 首先给变量 A 分配一个最大变化量
  • 在剩余的变化中,将最大变化分配给变量 B
  • 在剩余的变化中,将最大变化分配给交互效果
  • 把剩下的分配给剩余平方和。

第一类平方和是连续的,因此模型中变量的顺序有所不同。这在实践中很少是我们想要的!

平方和在数学上定义为:

  • 自变量 A 的 SS(A)
  • 自变量 B 的 SS(B | A)
  • 相互作用效应的 SS(AB | B,A)

I 型方差分析结论为:

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

ANOVA table for the Type I Sums of Squares

在 I 型平方和中,weekday 被错误地选为最重要的变量,只是因为它在模型中首先被指定。

3.第二类平方和

第二类平方和在两个方面采取了不同的方法。

  • 首先,分配给自变量 A 的变化是对 B 的解释,而分配给 B 的变化是对 A 的解释。
  • 第二,第二类平方和没有交互作用的影响。

如果自变量之间没有交互作用,则应使用第二类平方和。

平方和在数学上定义为:

  • 自变量 A 的 SS(A | B)
  • 自变量 B 的 SS(B | A)
  • 无交互效应

第二类方差分析结果为:

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

ANOVA table for the Type II Sums of Squares

在第二类平方和中,天气是唯一重要的变量。这比 I 型平方和好得多。

4.第三类平方和

第三类平方和也称为部分平方和,这是计算平方和的另一种方法:

  • 与类型 II 一样,类型 III 的平方和不是连续的,因此说明的顺序并不重要。
  • 与第二类不同,第三类平方和确实规定了一种相互作用效应。

平方和在数学上定义为:

  • 独立变量 A 的 SS(A | B,AB)
  • 独立变量 B 的 SS(B | A,AB)

III 型方差分析结果为:

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

ANOVA table for Type III Sums of Squares

在第三类平方和中,天气和工作日都很重要。给定我们的示例数据,这似乎是一个可以接受的结果。

5.不同的软件—不同的结果

关于使用哪种平方和存在激烈的争论。

r 给出 I 型,Python 给出 II 型,SAS 给出 III 型。

I 型和 II 型在 R 软件社区更受欢迎。在 R 的 anova()aov() 函数中,平方和的实现类型是类型 I,即顺序计算。对于其他类型的平方和,使用 car 包中的 Anova() 函数,该函数带有一个类型参数。

在 **SAS 软件社区中,**类型 III 平方和被更多地使用,因为这通常是 SAS 的默认实现。

Python statsmodels 库中,默认实现是 Type II,但是 type 参数使得使用 Type I 或 Type II 变得非常容易。

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

Default Types of Sums of Squares for different programming languages

6.结论:不同的平方和——不同的问题

仔细观察,每种平方和都给出了划分共享变量的不同方法。在我们的例子中,我们根本不知道哪个答案是正确的,所以我们可以采取多种策略:

只有在理论上有充分理由时才使用 I 型,没有相互作用时使用 II 型,有相互作用时使用 III 型。

在类型 I 中,我们选择最“重要”的自变量,它将得到最大可能的变化量。

在类型 II 中,我们忽略了共享变量:没有假设交互作用。如果这是真的,第二类平方和在统计上更有力量。然而,如果在现实中有一个相互作用的影响,该模型将是错误的,将有一个问题的分析结论。

如果存在交互作用效应,并且我们正在寻找自变量之间的“相等”分割,则应使用类型 III。

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

Decision Tree for Different Types of Sums of Squares in ANOVA

所以这个综述的结论是:只有在有严肃的理论理由时才使用 I 型,没有相互作用时使用 II 型,有相互作用时使用 III 型。

回顾 ANOVA 理论真的很有趣,我希望这些内容能帮助你踏上数据科学之旅。 感谢阅读!

用蒙特卡洛回答蒙蒂·霍尔难题

原文:https://towardsdatascience.com/answering-monty-hall-problem-with-monte-carlo-6c6069e39bfe?source=collection_archive---------17-----------------------

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

Photo by Adam Rhodes on Unsplash. Adams’s Website

蒙特卡洛是一种概念简单但功能强大的技术,被广泛使用。它利用随机性来回答问题。

在这篇文章中,我将解释如何使用蒙特卡罗方法解决蒙蒂霍尔问题。这是用 python 实现的,Python 是一种编程语言,它的名字本身就是向英国喜剧团体——蒙蒂 Python 致敬。

蒙蒂·霍尔问题

我第一次接触到蒙蒂霍尔问题是在电影《21 世纪》。这个片段展示了这个问题。

Vsauce 的迈克尔大卫·史蒂文斯和 Vox 对此也有解释。

让我们跳入问题— 想象一下,你面前有三扇门。

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

游戏节目主持人让你选择其中一扇门。如果你选择了正确的门,你会赢得一辆车,否则你会得到一只山羊。

假设您选择了门№1

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

知道每扇门后是什么的游戏节目主持人打开 3 号门,露出一只山羊。

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

游戏节目主持人给你两个选择

  1. 贴着 1 号门
  2. 切换到 2 号门

你会选择哪一个?

蒙特卡罗实验

蒙特卡洛实验的定义根据维基百科 蒙特卡洛方法 ,或 蒙特卡洛实验 ,是一大类 计算 算法 即依靠重复 随机抽样 底层概念是用 随机性 来解决原则上可能是 确定性 的问题。

这意味着你可以模拟一个实验,基于某个或某些条件模拟任意次,然后分析模拟的结果以得出一个解决方案。

在电影《复仇者联盟 3:无限战争》中,奇异博士对未来进行了近 1400 万次模拟,以确定未来有多少结局,复仇者联盟会赢吗?本质上,他是在应用蒙特卡罗实验的原理。

用蒙特卡洛模拟蒙提霍尔

想象一下前面描述的游戏陷入了一个循环,就像电影土拨鼠日中的比利·穆雷一样。

每次游戏开始时,我们记录坚持第一个选择的门和切换到新的门的成功和失败。

假设这个游戏已经进行了 100 次。我们会检查在这 100 场比赛中,有多少场比赛的车是通过不开关车门和开关车门赢得的。

通过查看这些比率,我们将知道哪个选项增加了成功的机会。

编纂蒙蒂霍尔和蒙特卡洛

让我们定义一个模拟蒙蒂霍尔问题的函数

def monty_hall():
    ...

在该函数中,创建三个车门,并将汽车随机分配给其中一个车门。列表中的值“1”代表汽车

doors = [0, 1, 0]
shuffle(doors)

玩家选择打开一扇门。值 0、1 和 2 代表列表变量“门”的索引

door_selected = choice([0, 1, 2])

游戏节目主持人现在打开后面没有汽车的门

non_car_doors = list()
for i,d in enumerate(doors):
 if d == 0 and i != door_selected: non_car_doors.append(i)door_opened = choice(non_car_doors)

现在,评估以下两个选择

  1. 坚持最初的选择赢得一辆车
non_switch_success =  True if doors[door_selected] == 1 else False

2.通过切换到剩下的门赢得一辆车

remaining_door = set([0,1,2]).difference([door_selected, door_opened])
remaining_door = remaining_door.pop()
switch_success =  True if doors[remaining_door] == 1 else False

最后,返回每个选项的成功结果

return non_switch_success, switch_success

定义蒙特卡洛函数,该函数采用单个参数“n”来表示要运行的模拟数量。运行 Monte Hall 模拟“n”次,并返回每个选项的成功分布。

def monte_carlo(n):
    non_switch_success_count = 0
    switch_success_count = 0for i in range(n):
        ns, ss = monty_hall()
        non_switch_success_count += ns
        switch_success_count += ssprint(f"Number of plays: {n}")
    print(f"Number of success on switch: {switch_success_count}     
     {(switch_success_count/n)*100}%")
    print(f"Number of success on non-switch:                       {non_switch_success_count}  
     {(non_switch_success_count/n)*100}%")

完整的代码可以在下面找到,如何运行它在标题评论。

运行模拟

让我们模拟 100 个游戏

╰─$ ./main.py 100
Number of plays: 100
Number of success on switch: 71  71.0%
Number of success on non-switch: 29  28.999999999999996%

我们可以看到切换的成功率更高。

让我们再运行一次

╰─$ ./main.py 100
Number of plays: 100
Number of success on switch: 62  62.0%
Number of success on non-switch: 38  38.0%

我们仍然可以看到切换的成功率更高,但是成功率差别很大。

让我们对 100 万个游戏进行同样的模拟,然后做 3 次,看看成功率是否有很大的不同。

╰─$ ./main.py 1000000
Number of plays: 1000000
Number of success on switch: 666566  66.6566%
Number of success on non-switch: 333434  33.3434%╰─$ ./main.py 1000000
Number of plays: 1000000
Number of success on switch: 666588  66.6588%
Number of success on non-switch: 333412  33.3412%╰─$ ./main.py 1000000
Number of plays: 1000000
Number of success on switch: 666628  66.6628%
Number of success on non-switch: 333372  33.3372%

我们可以看到,成功的百分比变化不大,它告诉我们,如果我们进行转换,那么获胜的机会是三分之二。

进行切换!

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

结论

这篇文章的动机是介绍蒙特卡罗方法,并将其应用于一个对新手来说容易理解和有趣的问题。蒙特卡罗方法可能在概念上看起来很简单,但它是一种强大的方法,广泛用于金融行业、强化学习、物理科学、计算生物学等领域。

3 个最常见的数据科学问题的答案

原文:https://towardsdatascience.com/answers-to-the-3-most-common-data-science-questions-b2148568c85d?source=collection_archive---------22-----------------------

问我们任何事情

从“我该不该读研?”到“R vs. Python”

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

Photo by Bryan Minear on Unsplash

今年早些时候,我非常兴奋地作为一名编辑加入了《走向数据科学》。帮助社区成长是一件非常有趣的事情,在本文中,我将回答 3 个常见的数据科学问题,为“向我们提问”系列做出贡献。我希望你喜欢!

该不该读研?

这可能是我收到最多的问题,也可能是最难回答的。很难对这个问题给出一个通用的答案,因为答案确实需要针对您的具体情况。也就是说,我认为有些事情可以帮助你更容易做出决定。但是请记住这是我的一个观点,获得多个数据点通常是有帮助的(这个建议适用于我所有的回答)。

你不必在本科毕业后马上就去。大多数人似乎认为在他们的高年级有一颗滴答作响的定时炸弹,如果他们不立即去读研,那么机会肯定会与他们擦肩而过。以我的经验来看,肯定不是这样。如果你对读研没有把握,请考虑等待是否更有意义,获得几年经验,再做决定。

大多数数据科学家不是研究科学家。如果你正在考虑将博士学位作为获得高薪数据科学工作的捷径,那么我会重新考虑。一个博士项目需要至少4-5 年,而需要 6 年以上也不罕见。那是一段很长的时间。你所做的大部分深入研究不会直接应用到行业工作中。这并不意味着它没有价值,但绝对有一个不平凡的转变,除非你最终在一个工业实验室做研究。这就是为什么像 Insight Data Science 这样的公司存在,以帮助弥合这一差距。虽然你会比没有博士学位的人进入更高的层次,但以我的经验来看,这并不能解释大约 5 年的高工资损失。目前的货币甜点似乎是硕士学位。你花了 2 年时间获得硕士学位,然后又花了 2-3 年的时间积累经验,通常你现在是在一个新的博士学位开始的地方,但你在过去的 2-3 年里一直在赚钱。一些人认为博士学位有更高的上限,这可能是真的,但一般来说,真正做得好的数据科学家往往会这样做,因为他们可以弥合科学和公司价值之间的差距。我认为这种技能在不同的学术背景中分布相当均匀。注意:如果你的目标是成为一名研究科学家,博士学位显然更有意义。

你去哪所学校或加入哪所实验室可能比你学到的东西更重要。这是因为当前的招聘系统非常糟糕,而且可以在网上公开找到如此多的数据科学资源。我认为,你需要知道的通过数据科学面试的一切都可以在网上免费找到。甚至还有数不清的关于“最佳”资源的文章。那你问为什么要读研?因为虽然你可能知道你需要知道的一切,但你需要首先证明你的能力。公司筛选简历的一个重要方式是看你上的学校和你是否有高等学位。你刚从斯坦福毕业吗?你将比那些毕业于不知名大学的人更容易获得面试机会。此外,众所周知的项目也是建立关系网的绝佳机会。如果你就读于斯坦福这样的学校,你几乎肯定会认识许多顶尖科技公司以及成长中的“独角兽”公司的人。那个网络会让你进门。如果你正在考虑博士学位,同样的道理也适用于博士实验室。你要仔细考虑你加入哪个实验室,因为在某种程度上,你将你的价值与你的实验室和导师的声誉和价值联系在一起。

**做你的研究。读研是你时间的一大投资。你的时间非常宝贵。花点时间在 LinkedIn 上联系那些参加过你正在考虑的项目的人。联系你认为你可能想与之共事的教授。打电话给学校办公室,问他们问题。**你的目标应该是发现你对研究生院将如何帮助你的愿景是否与现实相符。例如,也许你正在考虑一个硕士项目,因为你认为它会帮助你过渡到像谷歌这样的公司工作。然后,你应该做你的研究,找出人们结束后的计划。如果几乎每个人都以咨询结束,那么这个项目可能不适合你。

预测未来很难。希望以上几点有助于你的决定,但最终,对于什么是“正确”的选择,总会有一个未知的因素。你能做的最好的事情就是尝试并确定你未来的目标,然后评估读研和其他途径相比如何帮助你实现目标。然后采取行动,不要害怕在学习的过程中重新评估和调整。

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

https://towardsdatascience.com/a-tutorial-on-fairness-in-machine-learning-3ff8ba1040cb

数据科学中最迫切的问题是什么?

我认为有太多太多了,无法计数,但这里有三个是我目前想得很多的。

公平与偏见。我们已经构建了一些令人惊叹的算法,但直到最近才开始考虑它们可能存在的偏见或不公平。这一领域的挑战之一是,机器学习的优势在于它从历史数据中学习并将这些模式应用于未来案例的能力。如果你的历史数据有偏差,你会怎么做?比如在娱乐圈,就有历史的性别偏见。在 2017 年的前 250 部电影中,88%没有女性导演,83%没有女性编剧,96%没有女性摄影师。因此,如果你要建立一个模型,利用历史数据来预测“好”董事,你的模型几乎肯定会有偏差。我认为你如何减轻这些偏见将有助于建立对社会产生更强更好影响的人工智能。

**安全。**我对自动驾驶汽车超级兴奋。我喜欢大规模深度学习的技术和应用。他们的现状也让我深感担忧。我们对这些车辆的安全性或性能几乎没有任何保证。对优步致命车祸的调查清楚地表明了这一点。

“虽然[自动驾驶系统]在撞击前近 6 秒感应到了行人,但该系统从未将她归类为行人——或正确预测她的目标是乱穿马路的行人或骑自行车的人——因为她正在穿越……在一个没有人行横道的位置,”报告称。“这个系统的设计没有考虑到乱穿马路的行人.”

基本上,优步忘了考虑过马路的行人。我可以想象如此多类似的边缘案例,我不禁想知道我们如何量化甚至正式验证基于人工智能的系统的安全性。

**小数据和计算。**大数据和深度学习算法超级性感。事实证明,它们对 T2 环境非常不利,也不适用于许多重要问题。我对正在进行的使我们的算法更具计算和数据效率的研究感到兴奋。例如,谷歌的 MorphNet 有一个很好的推卸算法,允许你从一个大网络中提取一个更有效的网络。我认为这将使尖端算法更适用于没有大量计算预算的实体,以及适用于小数据问题,如预测罕见疾病。

我该学 Python 还是 R 还是别的?

实际上我对这个问题有很强烈的看法。不过,在我给出答案之前,我认为归根结底最重要的是学习数据科学。如果你有很强的知识基础,你用来实现它的编程语言并不重要。此外,编程语言来来去去,所以转换的能力肯定是有价值的。

也就是说,在今天的环境下,对于我主要研究的问题(在工业中应用人工智能),我认为你不从 Python 开始就是疯了。Python 是一种通用编程语言,具有强大的机器学习支持。r 是一种专门为统计计算和图形构建的语言,我认为这在今天的环境中限制了它。

Python 更容易发布到产品中,为您学习可能开发的不同编程语言做了更好的准备,具有更好的深度学习支持,并且更容易扩展。此外,开源机器学习社区对 Python 的支持是巨大的。几乎每个正在发布的流行包都是用 Python 编写的。我知道 R 也有一个很好的社区和支持,但它的优势更多地在于小众的统计需求(根据你工作的领域可能不那么小众)和探索性的数据分析。但是我认为对于大多数探索性的数据需求,Python 已经很好地满足了。

所以——对我来说,Python 是一个不用动脑筋的东西,但是我是一个样本大小为 1 的人。为什么不两个都试试?自己决定。

你也可以在这里找到这篇文章

人脸识别解决方案的反欺骗技术

原文:https://towardsdatascience.com/anti-spoofing-techniques-for-face-recognition-solutions-4257c5b1dfc9?source=collection_archive---------7-----------------------

防止演示攻击的机器学习

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

Source

在我们日益数字化的世界中,网络犯罪呈上升趋势,这并不奇怪。许多公司现在正在探索由机器学习工程师提供的生物面部识别作为可行的安全解决方案。这项创新技术展现了巨大的前景,可能会彻底改变我们获取敏感信息的方式。

人脸识别技术将是决定人工智能未来前景的因素之一。

尽管面部识别很有前途,但它也有缺陷。用户照片可以很容易地通过社交网络找到,并用于欺骗面部识别软件。让我们说使用纸质照片,截图,或三维面部重建。

这就是为什么对公司来说,部署 face 反电子欺骗系统以保护敏感数据、减少盗窃和欺诈非常重要。这些系统通过提高检测欺诈的能力来增强现有的面部识别解决方案。

虽然这在理论上看起来很棒,但很明显弱点确实存在。是什么阻止了一个人用假脸获取敏感数据?

这就是反电子欺骗解决方案发挥作用的地方。我们依靠活体检测来验证个体的身份。这些检查可以验证个人是否实际存在或使用照片来欺骗系统。

最流行的人脸反欺骗技术

大多数面部欺骗攻击被称为表示攻击。这些攻击使用 2D 和 3D(静态或动态)来欺骗面部识别软件。

静态 2D 演示攻击依赖于照片、平面纸或面具,而动态版本使用屏幕视频回放或一系列照片。

静态 3D 呈现攻击可能使用 3D 打印、雕塑或面具,而动态版本使用复杂的机器人来再现表情,并完成化妆。

当然,这些例子并不是最终的真相。随着技术的发展,表示攻击也在发展。

如今,由于技术限制,2D 比 3D 更受欢迎。

在开发该问题的解决方案时,我们认为重点关注以下技术非常重要:

  • 防止静态和动态 2D 欺骗
  • 使用图像,而不是视频
  • 不需要用户的交互

一个可靠的解决方案需要达到最大的准确性,需要很少的时间,并优先考虑用户体验。

最重要的是,它需要与现有的面部识别软件集成。

眨眼检测

眨眼检测是一种非常准确的活体检测测试。自然眨眼是判断一张脸是否真实的简单方法。人类平均每分钟眨眼 15-30 次。在一次眨眼过程中,眼睛会保持大约 250 毫秒的闭着状态。现代相机记录视频的帧间隔要小得多(每秒 30 帧,50 毫秒)。

我们可以使用视频找到闭着眼睛的帧,并对它们进行计数,以获得预期的数量。眨眼检测的实现可以使用面部标志分析并计算眼睛的表面积。我们也可以将深度学习应用于这项任务。

深度学习特征:卷积神经网络

深度学习和卷积神经网络(CNN)是可以帮助反电子欺骗的附加解决方案。

在探索技术时,我们开始将反电子欺骗视为一个二元分类问题。我们可以训练 CNN 识别哪些是真实的照片,哪些是伪造的。会成功的。

但是有一个问题。

卷积网络没有“看到”和“理解”的一致(稳定)的功能集这整个模型依赖于希望系统能探测到我们肉眼看不到的东西。

这里有一个例子。

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

A trained CNN identifies both photos as spoofing

以上两张图都是恶搞。是的——我们训练有素的 CNN 能够识别出这两个都是欺骗。甚至在左边也有许多肉眼看不到的失真。但它只能在特定条件下处理特定数据集,包括相机质量、环境、光线等。

如果其中任何一个发生了变化,神经网络都不会提供准确的结果。因此,这种方法只在有限的用例中可行。

挑战-回应技术

挑战和响应是另一种可行的反欺骗技术。这种技术使用一种称为挑战的特殊动作。

该系统工作以验证挑战发生在视频序列期间。挑战应答系统依靠一系列挑战来验证个人的身份。

这些挑战可能包括:

  • 笑容
  • 悲伤或快乐的面部表情
  • 头部运动

然而,虽然有效,但这种方法需要额外的输入,并且会显著影响用户体验。

3D 相机

3D 摄像头是最可靠的反欺骗手段。精确的像素深度信息可以提供抵抗呈现攻击的高准确度,因为我们可以区分人脸和平面形状。

3D 攻击可能会造成困难,但摄像头仍然是可用的最可靠的人脸反欺骗技术之一。尽管有相机,但并不是所有用户的电脑上都有。

这就是为什么我们觉得处理常规 RGB 图像很重要。

活动闪光灯

主动闪存是一项有趣的技术,我们认为它很有前途。我们决定为我们的特定项目测试它。与其他一些解决方案不同,它没有“黑盒问题”

这种解决方案使我们能够利用人脸上的反光来检测电子欺骗。这个想法涉及到使用一个不断变化的光环境,这种光环境是由来自设备屏幕的额外光线提供的。白光在脸上产生适当的反射。

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

Active Flash anti-spoofing technique

我们可以用这种技术让真脸和假脸不同。

但是它是如何工作的呢?

我们在闪光发生前后取帧,并用这些数据训练我们的网络。主动闪光帮助我们分离面部特征并进行分类。

有可能建立一个独立于面角的模型(具有合理的限制)。但是,如果我们计算像素差异,人脸对齐就变得必要了。但是很明显这个方法是有效的。基于需要解决的特定用例,该技术可以变得更加复杂。

定义成功的衡量标准

我们提到的每一种反欺骗方法都有各自的可行性。但是像任何事情一样,它们有优点也有缺点。其中一些可以通过增加额外的复杂性来改进,另一些则适合单独使用,而某些解决方案在组合使用时会表现得更好。

但是你如何定义成功呢?我们认为度量标准对于衡量人脸反欺骗系统的准确性是必要的。

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

False Acceptance Rate (FAR) and False Rejection Rate (FRR) are common metrics

错误接受率(FAR)错误拒绝率(FRR) 是在生物特征验证中使用的常见度量,也适用于反电子欺骗。特定的任务定义了我们在解释错误时需要考虑的指标。

有几件事需要考虑。

如果最少遗漏的冒名顶替者是成功的衡量标准,我们应该消除 FAR。但是如果我们优先考虑用户体验,那么更重要的是关注 FRR。根据我们的经验,流畅的用户体验至关重要。

人脸反欺骗的下一步是什么?

依靠深度学习的反欺骗技术不仅仅是炒作。面部识别软件的成功将依赖于这些技术。但是,这种成功也需要反欺骗方法的组合和合理的成功度量标准。

无论如何,人工智能的未来令人兴奋,很明显,这项技术将改变我们进行身份验证的方式。

有兴趣知道如何运行具有 DS/ML 特性的软件开发项目吗?阅读我最近的文章数据科学咨询:从想法到部署

蚂蚁和神经网络的问题

原文:https://towardsdatascience.com/ants-and-the-problems-with-neural-networks-778caa73f77b?source=collection_archive---------7-----------------------

认知科学可能如何改变神经科学

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

Photo by Mikhail Vasilyev on Unsplash

一个nt 是相当愚蠢的。它们能活一周,除了四处走动、寻找食物和为它们的蚁丘搬运小树枝之外,不做太多事情(现在我想起来,我们人类也不做太多其他事情)。

但是,除了过着平淡无奇的蚂蚁生活之外,他们也是愚蠢的。从技术角度来说,它们是愚蠢的:一只蚂蚁只有大约 250,000 (2,510⁵)个神经元。作为比较:一个普通的智人平均有 800 亿个神经元(810 ⁰),所以如果我们假设智力至少在某些方面与大脑的大小成比例(忽略一些动物的大脑比我们大的事实),那么我们大约是蚂蚁的 320,000 倍。

尽管蚂蚁的大脑很小,但它们也有自己的时刻。他们不断地做一些非常复杂的事情,以至于可以直接通过大学水平的数学考试。其中一个东西叫做 航位推算

航位推算

当像 双色斑翅蚁 这样的蚂蚁外出觅食时,它们会离开家,朝着预期食物来源的方向移动。由于他们不知道食物来源的确切位置,他们走在摇摆不定的路线和圆圈中(更多细节和图解见 Maroudas 和 Harkness 的论文)。如果你在野外观察过蚂蚁,你可能会认为这一切看起来完全是随机的。

但是一旦蚂蚁找到了食物来源并得到了它的那份食物,它就会直接回到它的家。而我说的直线,我指的是字面上沿着 的直线,不借助任何地标 来指引它们。

航位推算 是一种通过回忆自己从哪里来,从而知道自己在哪里的艺术。没有人真正知道为什么它被称为航位推算。你需要非常活跃才能做到。这不是一个简单的任务。

对于蚂蚁来说,要想知道它们在哪里,它们需要考虑它们在某个方向上行进的时间和速度。他们需要对长时间内路径上的所有微小位移进行汇总,并且他们需要能够随着时间的推移可靠且可访问地存储这些信息。

在数学中,你称这个过程为 路径积分 ,因为你在一段时间内对微小的位移进行积分,得到一个总和,然后你可以用它来计算有用的东西。

然后蚂蚁需要利用这些信息来计算出回家的最佳路线。为了做到这一点,蚂蚁必须 隐含地理解直角三角形的样子。 知道了它总共走过的路径的总位移(比方说,向北 10 米,向东 5 米),如果它想回到最优路径,它需要在直角三角形 的斜边上行进。

要沿着斜边行进,它需要找到合适的角度,这个角度就是北和东位移比例的反正切

我们并不知道蚂蚁是如何做到这一点的。

但是如果我们试图建造一个完成这项工作的设备,我们会假设我们需要以一种可靠的方式建造它,关于蚂蚁位置的信息以一种可靠的方式存储,并且在需要的时候也可以通过 计算访问 因为它需要它来计算蚂蚁在返回的路上将要采取的路线的角度,并且它需要能够独立于它去了哪里和它花了多少时间寻找食物来完成这项工作。

这一点在 A. King 和 C.R. Gallistel 的《改变思维的 记忆和计算大脑:为什么认知科学会改变神经科学 》中反复提到(我偷偷为我的标题修改了副标题)。

这篇文章是这本书的一些重要方面的 TL:DR 版本。这本书用了大得多的篇幅来阐述类似的观点。如果为了简洁起见,我不得不牺牲一些细节,我很抱歉,但我相信这些见解是高度相关的,并希望以一种不太耗时的格式来浓缩它们。

现在,记住 航位推算 是蚂蚁日常做的事情,也是过蚂蚁生活所需的许多其他任务之一。记住他们只有 25 万个神经元。

蚂蚁的大脑不是我们建造的,而是经过数百万年的进化而形成的。神经科学家面临的问题是,蚂蚁的大脑是如何连接的,以便以最佳方式进行这类计算。大自然已经一次又一次地证明了它在花费资源方面的吝啬,所以它很可能会认为它使用了一种为这项任务而优化的架构,尤其是考虑到蚂蚁大脑的大小。

作为一个物理过程,大脑必须遵守物理规则和计算的基本规则(由图灵等人制定),就像任何其他计算设备必须遵守的一样。尽管大脑确实“与普通计算机的工作方式非常不同”,进行“大量的并行处理”,并拥有“大量的神经元连接”,但大脑的这些特性不应该成为重新描述大脑本身某种神奇能力的借口。

所以我们可以继续提问:基于神经网络的神经元架构能在多大程度上完成这类任务?

神经网络的问题

“先说实话:机器不会学习”
—安德烈·布尔科夫在长达百页的机器学习书中

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

Photo by Franck V. on Unsplash

机器学习(ML)为我们提供了极其强大的分类学习算法。这是一种从数据中推断模式和结构的艺术,而无需给出如何推断这些模式的明确指示。

ML 方法让我们做了很多疯狂而有用的事情。如果目前围绕神经网络的大肆宣传是可信的,那么看起来它们可以学会做任何事情。我们需要注意,神经网络不会在未来几年失去控制,迎来由人工超级智能主导的人类反乌托邦未来。

但是根据安德烈·布尔科夫的说法,机器实际上“学习”的意义与我们或动物学习的意义相同,这有点牵强。对于通常的监督学习过程,我们只是进行大量的参数调整:我们试图找到由以下等式给出的决策边界(所谓的*、*、**、、**中的超平面,它们只是二维空间中的一条线)

wx -b=0,

为训练数据提供良好的分类结果。

当机器“学习”时,权重 w 被调整,以便在特征空间中找到决策边界,该边界为任何任意特征向量 x 给出最佳分类结果。

为了更加复杂,我们可以使用核方法来使特征空间中的度量在样本环境中非线性缩放,或者我们可以使用支持向量机来映射到具有其他维度的特征空间,我们可以调整神经元的激活函数等。

但这并没有改变机器学习算法的一个基本事实: 在神经网络中并没有进行实际的计算。

从这个意义上说,神经网络只不过是复杂的 查找表 (在计算机科学中,它被称为计算设备的有限状态架构,类似于图灵机,但没有读/写存储器):它们预先指定特定输入的特定输出。他们如何进行这种映射对用户是隐藏的(特别是当使用字面上称为 隐藏层 的东西时),并且关于网络如何分类的信息通常被编码在结构中并通过整个网络传播。

因此,它们的功能是 不具有代表性: 输入的任何表示都不会通过网络传送,并且可以通过网络中的每一步进行追踪。输入和输出就是一切。没有中间步骤, 网络不需要知道输入是什么意思就可以处理。

神经网络和联想学习

“所有的模型都是错的,但有些是有用的。”
—乔治·博克斯

虽然神经网络在某种程度上受到了大脑运作方式的启发,但神经科学家不一定认为神经网络足以代表大脑的工作方式。许多生物学的复杂性都被丢弃了,神经元通常以一种极其简化的方式来表示(树突的作用或突触处的钙流,以及许多其他东西,在模型中都被忽略或大大简化了)。

然而,神经网络目前的成功与心理学中可能最突出的学习理论不谋而合:即 联想学习 。信息是通过加强或削弱大脑不同神经元之间的连接来处理和整合的,遵循的规则是著名的流行语:“ 【什么东西把电线连在一起】 ”。

突触连接 是大脑在学习过程中调整的参数,因此它们的功能类似于人工神经网络中的权重。

就我自己而言,这让我相信神经网络真的可以在原则上解决他们面临的几乎所有任务,因此,大脑具有与人工神经网络非常相似的架构和学习机制。

但这种观点存在一些内在问题。

一个问题是,人工神经网络中最流行的学习方法(如【梯度下降】 )作为生物系统实际使用的方法是不现实的,因为它们需要用权重值进行计算,这又意味着网络外部的无所不知,可以访问权重值并相应地改变它们。**

但是突触权重是生物系统无法通过计算获得的。它们在人工神经网络中,但只是因为这些变量的值也存储在计算机的其他地方,而计算机本身不是神经网络。这反过来意味着神经元的功能结构对大脑本身来说是不透明的,它不能用来以一种允许大脑在需要时使用它的形式存储信息。

关于大脑是否使用符号表示它正在处理的事物,在神经科学界有一个持续的争议,就像基于图灵机概念的计算设备一样(我在这里详细介绍了图灵机的基础知识,并解释了记忆和符号的功能)。

也就是说,这意味着一个读/写头可以访问它正在计算的符号,以及一种对计算进行编码的符号语言。正如我前面所描述的,神经网络是 而不是代表 ,它们不处理输入的符号表示。

这一点把我们带回到蚂蚁身上,以及它们是如何在觅食后返回它们的山丘的。

又是蚂蚁

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

Photo by Thomas Kinto on Unsplash

正如我们所看到的,对于一只成功导航回蚁丘的蚂蚁来说,它看起来很像是有一些方法来将其当前位置存储在变量 中,并使用该当前位置变量来计算返回的最佳路线。

King’s 和 Gallistel 指出,对于由神经网络解决的航位推算任务,网络的计算和物理需求将**

这是因为网络不擅长记忆,即动态存储信息。在为学习程序优化后,它在运行时基本保持不变。这就是布尔科夫所说的网络不会学习的意思,因为它们只在学习任务时发挥灵活性,而不是在执行任务时。

作为记忆的循环反馈回路

鉴于这个问题,已经进行了一些尝试来在网络中建立能够动态存储信息的体系结构。它们基于所谓的 循环反馈回路,可以作为网络的记忆。

在这里,记忆这个术语再次在图灵的广义上使用: 作为一种可靠地携带计算所需信息的手段

循环反馈回路是神经网络中自我维持活动的突起。这种持续的活动可以起到符号的作用,因为活动 的信号需要时间来传播 ,因此将它编码的符号 在时间 上向前传送。由于权重在神经网络中是不可计算的,所以符号必须被动态编码,因此存储器将动态操作。

这种方法在早期的模拟计算机中使用,但当新的发展提供了更好的存储信息的方法时,这种方法很快就被放弃了。

在神经网络中实现该技术的一种方法是使用 连接到权重为 1 的自身的循环神经元,因此它们通过一次又一次地激活自身来存储信息。

例如,在航位推算模型中,神经网络中活动高峰的位置可以对蚂蚁的位置进行编码。网络中相应位置的神经元会继续自我激活,直到蚂蚁继续前进。

问题

当一个人试图在实践中实现这个想法时,事情变得复杂了(详见 Samsonovitch 和 McNaughton 的论文)。

这里不涉及太多的细节,作为记忆的循环反馈回路有几个固有的问题,特别是当它涉及到长期记忆时:

  1. 大脑在花费资源方面极其吝啬。任何一个头脑正常的计算机工程师都不会想到建造一个通过自持电流来存储信息的硬盘。摩擦和连续加热会导致 能量消耗 ,这是不必要的,也是不合理的。想象一下,为了不丢失其中的所有信息,你必须插上硬盘/u 盘并不断冷却它。
  2. 自然是凌乱的 。动力系统容易受到扰动,由于大多数动力系统的非线性,小扰动往往会随着时间的推移而放大(并非所有东西都是谐振子,因为本科物理学家往往会在花两年时间研究它后发现很多令人懊恼的事情)。如果您通过值为 1.01 的砝码发送值为 1 的信号,而不是通过值为 0.99 的砝码发送值为 1 的信号,那么在运行 50 次后,信号强度将为 1.64,而不是 0.61。当人们想到真实神经元的物理现实,及其所有的子结构、对神经递质的依赖性、钙流等时,对这种小扰动的定位一点也不牵强。假设它会将特定信号长时间保持在恒定的循环中,这可能是一种不切实际的简化。更有可能的假设是,自然界选择储存信息的实际机制以不同的方式工作,以一种更好地装备来校正扰动和错误。

加里斯特尔国王 写着:

从一开始,计算机科学家就意识到强大的计算机的关键特征是速度、效率和可靠性。

当在大脑中设计基于反馈回路的记忆机制时,这些问题都没有得到令人满意的解决。自然计算设备的效率使得大脑似乎不可能真的那样运作。记住蚂蚁只有大约 25 万个神经元。上面链接的由 Samsonovitch 和 McNaughton 建立的简化模型已经需要大约 50 000 个神经元来完成航位推算的工作,如果考虑到蚂蚁还必须做的所有其他复杂事情,这个数字就太高了。大自然不喜欢耗费资源,蚂蚁肯定没多少资源可以备用。

寻找记忆机制

这个故事的寓意是,对于许多认知任务来说,执行该任务的计算硬件需要某种类似于可访问的符号记忆机制的东西。当观察蚂蚁外出觅食后导航的效率时,这一点变得很明显。

总结一下我们遇到的两个问题:

*****突触强度*神经网络可能不会真正完成这项工作,因为它们执行计算的方式都是低效的(本质上是通过构建复杂的有限状态自动机,但它们的计算能力有限),而且存储在它们中的信息是分散的,对大脑本身来说是不透明的。因此,当谈到理解大脑如何计算时,通过调整突触强度实现的联想学习很可能不是全部答案。

网络中的循环反馈回路 同样似乎不适合作为良好的符号记忆,因为它们能量成本低且容易产生噪声,因此作为长期存储信息的手段并不可靠。

Gallistel 和 King 提出,它们太浪费了,不能成为大自然在构建大脑时实际采用的路线,大脑中需要有另一种我们尚未发现的记忆机制。

这绝不是说神经元不处理信息,或者信息在某种程度上与它们的活动、位置和连通性无关。这方面的一个例子是海马内位置细胞的作用,由 奥基夫陀思妥耶夫斯基 于 1971 年发现(他们因此获得了 2014 年诺贝尔医学奖)。它们的放电与动物(如老鼠)的空间位置有关,它们被认为是地点的认知地图(见这部动画中的插图)。

虽然它们可以为动物如何导航的问题提供更好的答案,但是它们作为路径整合者的功能还没有确定。而且它们也没有解决潜在的读/写符号记忆的问题,这在任何情况下也是许多其他任务 所必需的 ,我无法在这里介绍(比如间隔计时、学习一天中的时间、或者松鸦获取它们藏起来的食物)。

为什么认知科学会改变神经科学

这就把我们带回了这篇文章的副标题。

认知科学研究具有认知能力的设备,更具体地说,大脑,必须如何运行。计算约束表明,大脑作为计算设备的设置必须遵守某些基本原则,这些原则可以告知我们思考大脑神经科学基础的方式。

GallistelKing 提出相关的记忆机制可以驻留在大脑的不同层,例如分子或亚分子层。从物理学的角度来看,神经元绝对是巨大的,人类大约有 20 个微米 ,相比之下,平均原子大小为 30 pm 。正如费曼所说, 底部通常有很大的空间 ,在这六个数量级中(类似于你的体型与纽约和洛杉矶的距离之差),有很大的潜在空间来建立新的机制。

正如我们在 SSD 驱动器、蓝光甚至 DNA 的例子中所看到的,存储信息并不自动预设大量空间和大量资源,并且可以通过更节俭的方式来完成。

然而,国王 并没有提出任何具体的想法:

总之,我们不知道记忆的物理机制是什么。此外,我们拒绝猜测,除了举例说明,它可能是什么。我们拒绝,因为我们相信,面对我们目前的无知水平,我们不可能推测出正确的答案。

我认为这非常令人兴奋,因为这表明我们刚刚开始了解大脑的工作。如果我们甚至不知道它是如何存储和处理信息的,我们就无法理解它是如何计算的。神经网络很酷,也是一项伟大的发明,但看起来它们不会为我们提供所有的答案。

还有其他人力资源专业人士吗?这就是非专业开发者社区的样子。

原文:https://towardsdatascience.com/any-other-hr-out-there-this-is-how-the-non-professional-developer-community-looks-like-4c7101bd8dcf?source=collection_archive---------37-----------------------

一种基于数据的方法,使用 2019 Stack Overflow 的开发者调查数据。

介绍

我刚刚开始我的数据科学之旅,我可以告诉你:我不是天生的,作为一个成年人更难学习。

我的动机是相信通过“做”,我将能够理解这个新的数字企业世界,并有望与我的同行们——主要是人力资源专业人士——一起帮助翻译这个世界。

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

最近,我听到了很多关于未来最有价值的能力将是最基本的人类能力的说法。人工智能和自动化将出现在我们的工作场所,完成我们认为只有人类智能才能完成的任务。

这听起来像是一个为未来工作优先考虑人文科学和情商的论点。然而,我认为在我们到达那里之前,我们仍然有许多其他的积木要塑造。如果我们不认为功能知识和技术技能会被简单地推进机器,让机器神奇地自动运转,那将是明智的。

我的观点是:所有职业(办公室职员、工厂经营者、销售人员、教师、首席执行官……)都需要某种程度的数字素养,以了解我们如何才能以一种我们作为一个社会不会经历我们所担心的令人生畏的破坏性变化的方式来构建这个新的现实。

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

当我们用数据来检验想法和讲述故事时,我们的能力会更有效。对于一些专业人士来说,未来的数字素养可能会以学习一些编程技能的形式出现,以处理和理解复杂而混乱的数据集。

在这篇文章中,我想利用 2019 年 Stack Overflow 年度开发者调查来探索这一人群的一个片段。对于不熟悉的人来说, Stack Overflow 是开发者学习和分享编程知识的最大在线社区。

非专业开发人员的简介工作满意度薪酬是什么?让我们来看看…

第一部分:今天,非专业开发人员的开发人员是什么样的?

我用的是最近一次调查(2019 年),有 88,883 名受访者。只有 12.32%的人口:

  • 不是专业开发人员,但有时会将编写代码作为工作的一部分(8.53%)或
  • 编码主要作为爱好(3.78%)。

我将把选择这些答案中任何一个的所有回答者称为“非专业开发人员”。

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

Table 1: Type of respondent (excluding null answers) from 2019 survey.

与 2017 年的调查数据(11.78%)相比,我们可以观察到这一人口参与率略有增加。

这些回答者都不是专业开发人员,但是他们有多少编码经验呢?

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

Figure 1: Age of first code and current age (left) and years the respondents have been coding (right) of non-professional developers population (2019 survey results).

30 岁是受访者的年龄中位数。第一次编码经历的平均年龄是 15 岁。但回答者编码 8 年(中位数),所以有差距。

他们的就业状况如何?

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

Figure 2: Employment status of non-professional developers (2019 survey results).

大部分受访者(64.22%)是全职就业,其次是“独立承包人、自由职业者或个体户”,占 11.45%。

他们的最高学历和研究领域是什么?

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

Table 2: Educational level of non-professional developers, excluding null responses (2019 survey results).

64.18%的人口至少拥有学士学位。

最常见的学习领域是计算机科学/工程(35.40%),其次是另一个工程学科(15.99%)。

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

Table 3: Field of study of non-professional developers, excluding null responses (2019 survey results).

这部分人口主要是男性(86%)。妇女占总人口的 8%,其他类别占 6%。

第二部分:该人群和所有受访者的工作满意度相比如何?

以下是我们将要研究的问题:

  • 总的来说,到目前为止,你对自己的职业有多满意?
  • 你对目前的工作有多满意?
  • 你对你的经理知道他们在做什么有多少信心?
  • 以下哪一项最能描述您目前的求职状态?

为了给这些定性的答案打分,我对“工作满意度”做了如下分类,并添加了结果:

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

Table 4: Job satisfaction score based on answers available at the 2019 survey.

总体人口和非专业开发人员的平均得分相同(3.00),但是非专业开发人员的平均得分较低(2.50 比 2.85)。

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

Figure 3: Job satisfaction, all respondents (left) and non-professional developers (right).

第三部分:这个群体的薪酬与专业开发商相比如何?

为了进行薪酬分析,我选择了薪酬信息回复频率最高的前十个国家:

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

Table 5: Countries with the highest frequency of compensation information at the 2019 survey.

在准备可视化的工资信息时,我们需要考虑一些细节,更多细节请查看我的代码这里

让我们比较一下专业开发人员和非专业开发人员的报酬。为了更好的可视化,补偿被标准化为国家最低工资的倍数,并进行对数转换。

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

Figure 4: Compensation distribution comparing professional developers and non-professional developers.

该数据库包含大量异常值,由最大值上方和最小值下方的点表示(可能是虚拟条目)。对比各国,我们可以发现薪资分配存在一些差异:

  • 在印度和巴西等国家,分布(由彩色方框表示)更大,表明受访者之间的工资差异更大;
  • 另一方面,我们有法国、德国、荷兰、加拿大和澳大利亚,分布较窄——这表明总体上工资差距较小;
  • 与其他国家相比,印度的最低工资高出许多倍。

看起来比较两组(专业开发人员和非专业开发人员)的分布是相似的。我们来看看中位数的绝对信息。

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

Figure 5: Median compensation (multiple of minimum wage), professional developer and non-professional developer.

  • 巴西、荷兰和法国的非专业开发人员和专业开发人员人口的中位数相似;
  • 与专业开发人员相比,印度和澳大利亚的非专业开发人员受访者的中位数更高。

总结和结论

这个小型的非专业开发人员社区似乎是由大多数在正规教育中接触过编码的人组成的。此外,他们将编码作为工作的一部分。

至于工作和职业满意度,将这一人群与所有受访者相比,我们没有发现任何明显的差异。

非专业开发者和专业开发者的薪酬分配也是如此。我们可以观察到国家之间的一些不同的行为,但是,总的来说,专业和非专业开发人员之间没有明显的差异。

这些只是观察发现。我很想知道这些年来这个种群会如何演变。

你会加入数字化转型吗?

要了解更多关于这个分析的信息,请查看链接到我的 Github。

AnzoGraph:一个基于 W3C 标准的图形数据库

原文:https://towardsdatascience.com/anzograph-a-w3c-standards-based-graph-database-9836fa64087e?source=collection_archive---------19-----------------------

剑桥语义学的巴里·赞访谈

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

Image by Kyle McDonald on Flickr CC BY 2.0

介绍

在这次采访中,我正赶上剑桥语义学的副总裁巴里·赞。巴里是 AnzoGraph 的创造者,这是一个本地的大规模并行处理(MPP)分布式图形数据库。Barry 在数据库领域经历了一段漫长的旅程。他在 2000 年至 2005 年期间担任 Netezza Corporation 的技术副总裁,负责指导软件架构和实施的所有方面,从最初的原型到批量出货,再到领先的电信、零售和互联网客户。Netezza 最终被出售给了 IBM,但在此之前,Barry 已经将注意力转向了其他地方,成立了另一家公司 ParAccel,该公司最终成为了 AWS Redshift 的核心技术。市场上开始出现对基于图形的在线分析处理(图形 OLAP)数据库的需求,基于这一市场需求,Barry 于 2013 年创立了 SPARQL City。

Barry 友好地同意本周与我交谈,此前最近宣布AnzoGraph 数据库现已可供下载,用于独立评估和在客户应用程序中使用,无论是在内部还是在云上。虽然还没有宣布,Barry 还透露 AnzoGraph 已经得到了增强,可以使用 RDF*/SPARQL*来提供完整的属性图功能。所以和他交谈并了解更多关于图形分析和 W3C 标准是如何结合在一起的是令人兴奋的。

首先,巴里,你能告诉我们一些关于剑桥语义学的事情吗?

剑桥语义学大约从 2007 年开始出现。我们多年来构建的解决方案之一是名为 Anzo 的语义层产品。Anzo 用于许多大型企业,如制药、金融服务、零售、石油和天然气、医疗保健公司和政府部门。这些企业都有一个共同的趋势,即拥有多样化的数据源,并且真正需要发现和分析数据。Anzo 提供的语义层将原始数据与业务含义和上下文结合起来并呈现出来。恰好图形数据库是这个解决方案的关键基础设施元素。

Cambridge Semantics 很早就看到了图形分析的价值,并且是 SPARQL City 的首批客户之一。他们在 2016 年收购了我们。2018 年末,我们将图形引擎置于 Anzo 之下,并将其分拆为自己的产品,名为 AnzoGraph。

请解释一下 AnzoGraph 的主要使用案例好吗?

在 OLTP 数据库方面,图形数据库市场得到了很好的覆盖。我们决定构建一个 OLAP 风格的图形数据库,而不是像 Neo4J 和最近的 AWS Neptune 那样的 OLTP 图形数据库。市场上确实需要执行数据仓库风格的分析,并获得处理结构化和非结构化数据的额外好处。借助 AnzoGraph,我们可以提供报告、BI 分析和聚合、图形算法(如页面排名和最短路径)、推理以及更多市场上缺失的数据仓库式分析。

客户使用 AnzoGraph 发现大规模多样化数据的新见解,包括历史和最近的数据。它非常适合在非常大的数据集上运行算法和分析,以找到相关的实体、关系和见解。我们将用户使用基于 W3C 标准的 RDF 数据库获得的价值与他们使用属性图获得的价值结合起来。

我们对将 AnzoGraph 用于多种用途很感兴趣。想一想,在所有需要执行分析的时候,连接数据的信息与数据本身同样重要。例如,知识图在许多试图将不同数据源连接在一起的公司中很流行,我们在 Anzo 中的经验对此有所帮助。各公司都在努力理解买家的意图,并建立推荐引擎。图表可以帮助解决“喜欢产品 A 的人可能也会喜欢产品 B”的问题。在金融服务领域,银行正在使用图表来“跟踪资金”。图表提供了跟踪衍生品和其他资产转移的能力,因此可以帮助银行管理风险。甚至 IT 组织也在关注复杂的网络,并试图更好地了解 IP 流量如何在设备之间流动。

有几个新出现的用例让我感到非常兴奋。首先,当与自然语言处理引擎或解析器配对时,AnzoGraph 非常擅长处理链接的结构化/非结构化数据和基于图形的基础设施,用于人工智能和机器学习中基于图形的算法。其次,关注图表分析如何对基因组研究产生影响是很有趣的。科学家们没有采用带来遗传学中许多分析驱动创新的蛮力技术,而是通过图形分析开发新的分析技术,允许用户找到新的见解,而无需像在关系数据库中那样为这些见解显式编程。

AnzoGraph 有什么不同于其他数据库仓库解决方案的地方?

这可能是您没有预料到的,并且与传统 RDBMS 数据仓库世界中共享模式的不灵活性有关,在传统 RDBMS 数据仓库世界中,我们的任务是创建表和固定模式。为了得到答案,我们可能需要创建复杂的连接来查询表。然而,在图形数据库世界中,由于一切都用三元组表示,我们用一个动词和一个描述来描述一个人、一个地方或一件事,所以很容易添加更多的三元组来进一步描述它,而不需要改变模式。标准的本体帮助我们描述关系,这在我们想要共享数据时尤其有用。数据库模式通常不那么灵活,因为它们通常从一开始就是固定的和定制的。

图形数据库中的本体非常灵活,可以更好地与你的伙伴共享数据。

当然,对分析的支持也是一个巨大的差异。虽然 AnzoGraph 提供了传统数据仓库的所有分析功能,但它还提供了图形算法、推理和其他功能。这使得处理我上面提到的用例变得非常容易。图形数据库更适合某些类型的机器学习算法,并提供基于机器的推理,这在机器学习中非常有价值。

与传统的数据仓库不同,AnzoGraph 非常适合部署灵活性和可伸缩性。由于可伸缩性因素,市场对用 Docker 和 Kubernetes 这样的容器构建的应用程序做出了响应。当您可以随意旋转多个容器并将其旋转回来时,这是一个非常经济的可扩展解决方案。在基准测试中,我们实现了比其他数据库快 100 倍的性能,前途无量。当然,AnzoGraph 可以部署在裸机、虚拟机或任何云中,但容器最受关注。

2018 年,机器学习的一系列技术领域都有了巨大的发展,而深度学习正在等待时机。图形数据库有什么可以提供给那些想要加入人工智能淘金热的海量数据的人吗?

我们正在看到机器学习和人工智能的更广泛采用,图形数据库将发挥作用。我们都知道机器学习最大的挑战是数据准备。然而,通过直接导入原始数据,然后在图形数据库本身而不是复杂的 ETL 管道中进行管理,这种准备和管理得到了简化。数据模型的简单性使得管理比关系数据库中的管理更加简单和快速。当复杂的模式消失时,用户将能够更容易地挖掘非结构化数据,并且他们可以利用容器的可伸缩性。

图形数据库使用户能够自由地“旋转”他们的分析,提出新的、特别的问题,而不受关系技术的限制。图形数据库可以为机器学习和人工智能提供很多东西。

图形数据库已经存在了一段时间,但现在才开始成熟。你对这个领域未来两年的预测是什么,AnzoGraph 将如何领导下一代图形数据库?

我期待在未来几年里,人们对执行大数据分析的一般类别有更深入的了解,而不是运营查询。AnzoGraph 非常关注跨图形空间聚合的大数据分析。我们可以超越狭窄的查询“告诉我关于史蒂夫的事情”来涵盖更广泛的分析,例如“告诉我关于人类的事情”。

我认为来年将会看到下一代标准查询语言的定义。

W3C 标准是目前唯一的正式标准,但是 Cypher 显然是标签属性图的事实标准。有一个组织已经成立来创建下一代正式标准,看看它是如何形成的会很有趣。在剑桥语义学,我们非常支持这一过程,拥有一种强大的图形语言是一件好事。因此,我对图形空间未来几年的预测是,专有模型即将过时。

市场将决定确切的标准,我们将调整我们的解决方案以符合标准,因为我们坚定地致力于标准。我不认为这种演变是一种威胁,而是一个巨大的机会,因为它符合我们的心态,只会增加图形技术的吸收。

最后

我要感谢 Barry 和剑桥语义的团队给我机会去了解更多关于 AnzoGraph 的知识。我与该公司没有任何关系,我应该指出,我没有从他们那里得到这次面试的报酬。

如果你想了解关于 AnzoGraph 的更多细节,从 2018 年 10 月开始,Slideshare 上有一个很棒的技术演示,或者查看一下网站。请在下面的评论中留下任何问题!

Apache Airflow:自动收集日常电子邮件附件

原文:https://towardsdatascience.com/apache-airflow-automating-the-collection-of-daily-email-attachments-213bc7128d3a?source=collection_archive---------14-----------------------

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

Photo by Mathyas Kurmann on Unsplash

这篇文章演示了如何使用 Apache airflow 和 IMAP 邮件协议从任何通用电子邮件服务器自动收集日常电子邮件附件。

俗话说,数据科学家 80%的时间都花在收集、清理和组织数据上。在很大程度上,这是真的,特别是在一次性洞察生成项目的情况下,然而一旦我们将模型投入生产,我认为表盘会移动得更远。我们不仅需要确保数据的完整性,还需要确保数据是最新的,并与内部系统无缝集成。

当集成一个新的数据源时,有许多方法可以探索,仅举几个例子:

  • 有报告 API 吗?
  • 有数据库吗?
  • 客户端或平台能支持 SFTP、S3、谷歌驱动等吗?

当所有希望都破灭时,我们可以求助于自动电子邮件报告。计划的电子邮件报告是一种在报告平台和最终用户之间共享数据的广泛支持的方法,并且在设置成本方面也相对便宜。因此,与其每天登录我们的电子邮件,下载报告并将文件复制到更永久的存储解决方案,我们可以使用 Airflow 插件和 DAG 来为我们完成这些工作。

这篇文章假设你有一个现有的气流环境和气流概念的基本知识。

IMAP 插件

Airflow 的一个很大的特性是插件,插件是扩展 Airflow 现有特性集的一个简单方法。要将新插件与现有气流环境集成,只需将插件文件移动到$AIRFLOW_HOME/plugins文件夹中。

IMAP 插件将包含一个钩子和操作符,钩子处理外部连接并构成操作符的构件。操作员将执行我们的任务。插件文件夹结构如下:


├── README.md
├── init。py
├──钩子
│ ├── init。py
│ └── imap_hook.py
└──运算符
├── init。py
└──IMAP _ attachment _ operator . py

要创建一个插件,你需要派生 AirflowPlugin 类并引用你想插入到 Airflow 中的对象,我们在 init 中做了这些。py 文件:

注意钩子和操作符是如何相对于文件夹结构导入的。

IMAP 挂钩

在创建一个钩子之前,气流连接需要到位,或者至少经过深思熟虑。这告诉气流如何连接到外部环境。IMAP 挂钩需要 IMAP 服务器 url、电子邮件地址和密码。可以在 Airflow UI 的管理选项卡中创建连接。以下是 iCloud 的 IMAP 连接示例。

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

IMAP 挂钩继承自 BaseHook 模块,它是所有挂钩的基类,并使用 get_connection 方法来访问连接模型。

请注意 init 方法中的“get_connection”是如何使用连接 id 来返回一个气流连接对象的,根据 UI 中创建的 IMAP 连接,它的属性是 host、login 和 password。

imaplib 库用于处理 Authenticate 方法中的邮件连接。IMAP4_SSL 类实现 is IMAP 协议,并通过 SSL 连接到服务器。login(user,password)方法授予 IMAP 对象对指定电子邮件帐户的访问权限。

既然钩子已经连接上了,它需要能够搜索特定的电子邮件。find_mail 方法就是这样做的:

mailbox 参数指示要搜索的邮箱,search_criteria 是一个搜索术语的字典,它定义了我们要查找的电子邮件。所有可接受的搜索词都可以在这里找到。

该方法返回相对于所搜索邮箱的电子邮件 id。如果没有找到电子邮件,则返回的 mail_id 为 None,如果找到了多个电子邮件,则只返回最新的 mail_id。

最后,get_mail_attachment 方法将电子邮件附件保存到本地目录。

mail_id 参数应该是 find_mail 方法的输出,邮箱已经设置好了。附加参数是可选的,local_path 指示保存附件的位置,file_name 允许您选择是否重命名附件。

fetch 方法使用 mail_id 返回电子邮件部分,这些部分被解码并使用 message_from_string 命令转换为消息对象。遍历用于“遍历”消息树并产生每个部分;最后一部分总是包含使用 get payload 函数检索的附件。

IMAP 附件操作员

如前所述,气流挂钩是操作员的构建模块。下面的操作员使用 IMAP hook 命令和 Airflow 的执行上下文来下载任务执行日期前一天(总是昨天)收到的电子邮件的附件,并将其保存到本地目录。

所有气流操作符必须继承 BaseOperator 类,该类创建成为 DAG 中节点的对象。下面所有的参数都已经在 IMAP 钩子中提到了。唯一的新参数是 execute 方法中的上下文变量;这是一个描述任务执行环境的字典,即 execution_date & run_id。气流执行上下文的全部内容可以在这里找到。

Airflow 操作符的一个重要特性是能够定义模板字段;这些是 Jinjaified 字段,在执行时可以接受 Airflow 宏。文件名是一个 template_field,这意味着它可以在运行时使用宏动态设置。在 8 月 1 日运行 DAG 将产生以下结果:file_name = {{ ds }}_attachment = 2019-08-01_attachment

execute 命令使用上下文变量将搜索标准的 date received 元素预设为执行日期的前一天。这是通过使用“yesterday_ds”宏设置或更新“ON”值来实现的。这背后的想法是,如果每天都有电子邮件报告发送,我们只需要最新的附件。

我使用“yesterday_ds”宏,因为有时报告和数据会在一天的不同时间合并,所以我们只是给它额外的交付时间。我不要求我的数据比几天前更新,但如果速度是最重要的,气流传感器会更合适。

get_attachment 方法验证 IMAP 挂钩,并调用每个方法将附件下载到 disc。

S3 达格的电子邮件附件

既然插件现在已经完成了,下一步就是在气流 DAG 中将它投入使用。下面是一个简单的 DAG,每天运行,下载电子邮件附件并保存到 S3。

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

已经定义了 IMAP 附件操作符,下面的代码描述了将附件上传到 S3 和删除本地存储的附件所需的两个函数。

这些将使用 Python 操作符的扩展版本在 DAG 中执行。扩展的 Python 运算符继承了 Python 运算符,并将 op_kwargs 字段定义为模板字段,这意味着 upload_file_to_s3 和 remove_file 函数中的关键字参数现在都可以被 Jinjaified(接受 airflow 宏)。

下一步是定义 DAG。下面的 DAG 在八月份每天运行,在出现故障时重试 3 次,每次尝试之间有 5 分钟的延迟。

最后一步是将所有任务放在一起并定义依赖关系。file_name 变量是使用 yesterday_ds_macro 定义的(我们正在提取昨天的电子邮件附件)。由于 file_name 在所有操作符中都是一个模板化的字段,因此它将用于跨任务跟踪附件。

描述这个 DAG 的最佳方式是想象一下 8 月 1 日的一场挤兑。动态变量定义如下:

  • DAG 以一个伪操作符开始;虚拟操作符不做任何事情,但是对于分组任务非常有用。
  • DAG 启动后,下一步是下载电子邮件附件。这是使用 IMAP 附件操作符来完成的,该操作符使用新的文件名保存附件:email _ Attachment _ received _ on _ 2018 07 31。
  • 将附件上传至 s3 任务将文件 staging _ folder/email _ attachment _ received _ on _ 2018 07 31 上传至 S3 存储桶:email_attachment_bucket。
  • “删除本地附件”任务从暂存文件夹中删除文件:email _ attachment _ received _ on _ 2018 07 31。
  • 最后,DAG 以另一个伪操作符结束。

我希望你喜欢这篇文章;如果你有任何问题或建议,甚至是对未来帖子的想法,请在评论区告诉我,我会尽最大努力回复你。

Apache Drill 与 Apache Spark —哪个 SQL 查询引擎更适合您?

原文:https://towardsdatascience.com/apache-drill-vs-apache-spark-which-sql-query-engine-is-better-for-you-2a43f381bcd7?source=collection_archive---------15-----------------------

原文发布于此:https://blog . contact sunny . com/tech/Apache-drill-vs-Apache-spark-which-SQL-query-engine-is-better-for-you

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

如果您在大数据、数据科学或 BI 领域,您可能听说过 Apache Spark。你们中的一些人可能也听说过 Apache Drill,你们中的一小部分人可能实际上使用过它。我最近发现了 Apache Drill。但从那以后,我开始喜欢它所提供的东西。但是当我浏览 Apache Drill 的功能时,我想知道的第一件事是,它与 Apache Spark 有什么不同?我能互换使用这两个吗?我做了一些研究,找到了答案。在这里,我将回答这些问题,为我自己,也许也为你们。

理解这两者之间的根本区别、它们是如何实现的以及它们能够做什么是非常重要的。

使用 Apache Drill,我们编写 SQL 查询来从各种来源获取数据,例如 SQL 数据库、MongoDB、AWS S3、Apache Kafka、JSON 文件等等。但是使用 Apache Spark,我们编写“类似 SQL”的查询来从各种数据源获取数据。这里的区别在于,Drill 是一个 ANSI SQL:2003 查询引擎,具有比传统 SQL 查询引擎更强大的功能。另一方面,Apache Spark 只支持 SQL 查询的一个子集,而且是有限的。Spark 是一个通用的计算引擎,它支持类似 SQL 的查询来获取运行这些计算所需的数据。Spark 还为您希望运行查询的各种存储服务提供了驱动程序。

SparkSQL 支持的数据源列表也相当长,但没有 Drill 那么长。长期使用 BI 工具的人会发现自己对 SQL 查询驾轻就熟。将这些知识带到 Apache Drill 中,将使他们能够从对他们来说可能是新的数据源中查询数据,如 NoSQL 数据库、拼花文件、S3 文件等。这样的人可以使用 Apache Drill 运行复杂的聚合查询;而且大多数时候,他们得到了他们需要的结果。SparkSQL 就不一样了。

SparkSQL 非常适合在 Spark 内部处理数据,并且希望通过一些简单的连接和 where 条件从外部数据源获取数据。一旦将数据放入 Spark 数据集,就可以应用转换并执行操作。

这两个工具处理底层数据的方式非常不同。Apache Drill 能够接受在多个数据源上运行的复杂查询,并且能够将这些查询下推到相关数据源的本地驱动程序。它在内部将数据映射为 JSON 格式,并且它使用 JSON 的能力使得 Drill 在某种程度上比 Spark 更加灵活。

Drill 还使用 FLATTEN 和 KVGEN 等命令扩展了 ANSI SQL 查询,这使得处理简单甚至复杂的 JSON 数据变得更加容易。由于 Drill 在内部使用 JSON,它使 Drill 能够动态地发现模式。

总之,如果您想做大量的数学、数据转换和机器学习工作,最好坚持使用 Apache Spark。如果不是这样,而您只想运行一些聚合查询来分析数据,那么您可以使用 Apache Drill。

有意思的是,Drill 支持 JDBC 驱动,Spark 可以在 SparkSQL 内使用 JDBC 驱动来取数据。因此,如果您希望对导入 Spark 的数据进行精细控制,并希望对这些数据进行复杂的转换,您可以使用 Spark 中的 Drill 将数据导入 Spark。这种组合对于大多数应用来说应该足够了。

Apache Druid(第 1 部分):可伸缩的 Timeseries OLAP 数据库系统

原文:https://towardsdatascience.com/apache-druid-part-1-a-scalable-timeseries-olap-database-system-af8c18fc766d?source=collection_archive---------7-----------------------

在线分析处理(OLAP)系统通常用于许多商业智能、分析和数据科学应用中。根据维基百科,“OLAP 是一种在计算中快速回答多维分析查询的方法”。

与传统的关系数据库系统相比,主要区别在于 OLAP 系统中的数据是以预聚集和多维形式存储的。以这种形式存储数据的主要好处是,它针对特定的复杂聚合进行了优化。例如,通过使用不同的粒度级别(每小时、每天、每周等)存储预聚合。),我们可以高效地回答类似“两年前的月销售额是多少?”,或者“在过去的 90 天里,用户每天使用我们服务的特定功能的平均时间是多少?”。此外,我们可能需要随时深入到更详细的视图,并在数据的任何其他维度上重新计算聚合。例如,现在我们想重新计算上述问题,并对世界上每个国家的结果进行分组,以便生成更详细的可视化/报告/仪表板,并帮助制定决策。

从关系数据库中收集这样的答案并非不可能,但是模式设计和维护的复杂性,以及能够“有效地”回答这种复杂的特别聚合的需求,可能会导致数据工程的噩梦(多个表、索引、可能的多个数据库和定制 ETL 任务)。

简而言之,OLAP 系统的主要特征概述如下:

  • 保留数据的时间序列—例如,能够了解指标值的演变。
  • 分析师通常执行的查询是特定的,因此系统应该能够回答任何业务问题,而不需要模式工程。应该快速收集和查询任何维度的数据。
  • 与关系数据库相比,数据可能以大量冗余存储。这是期望的,或者是为了提高收集结果的速度(例如,避免连接),或者是因为需要具有时间序列中的数据演变。
  • 为了回答业务问题,可能需要扫描大量数据。

OLAP 系统背后的主要概念如下:

  1. OLAP 立方体:你可以把立方体看作是电子表格的多维概括。例如,考虑我们想要按国家、按某些时间段(例如,每周、每月、每季度和每年)以及按任何其他可能的维度(例如,按地区、城市、服务特征等)进行销售。).
  2. 对于任何查询来说,预先计算一个多维数据集中所有可能的聚合将是最快的答案响应时间的理想情况,但是这需要大量的处理时间和存储。根据业务需求、系统配置和聚合类型,我们通常设置哪些聚合将在数据接收期间完全预先计算,因此,任何其他聚合都是在查询计算期间按需计算的。

有许多商业和开源的 OLAP 系统,一个简单的比较可以在维基百科中找到。正如本文标题所揭示的,我们将重点关注 Apache Druid ,这是一个分布式数据存储,旨在对大型数据集进行高性能切片分析(OLAP 式)。

阿帕奇德鲁伊

Apache Druid 由广告分析公司 Metamarkets 创建,目前已经被许多公司使用,包括 Airbnb、网飞、尼尔森、易贝、Paypal 和雅虎。它结合了来自 OLAP 数据库时间序列数据库搜索系统的想法,为广泛的用例创建了一个统一的系统。最初,Apache Druid 在 2012 年成为 GPL 许可下的开源软件,此后在 2015 年改为 Apache 2 许可,并在 2018 年加入 Apache 软件基金会作为孵化项目。

Druid 提供了什么来处理类似 OLAP 的查询:

  • 为了存储效率和对数据维度的快速过滤,Druid 以面向列的压缩格式存储数据(参见面向列的系统面向列的数据库系统)。因此,它可以处理数据冗余,同时使用有效的格式对多维聚合和分组执行查询。
  • 为了回答查询,它只加载所需的精确列。
  • 每一列都针对其特定的数据类型进行了优化存储。
  • 为了提供跨多列的快速过滤和搜索,Druid 使用了最先进的压缩位图索引(详情见简明咆哮)。
  • 任何数据源的模式(例如,Druid 中的一个表)都非常灵活,可以很容易地发展。
  • 数据基于时间进行分区,因此时间序列查询比传统数据库快得多。
  • Druid 提供了开箱即用的算法,用于近似计数区分、近似排序以及近似直方图和分位数的计算。
  • 它具有高度的可伸缩性,已经在生产环境中使用,每秒钟处理数百万个事件,存储数年的数据。
  • 查询的亚秒级平均响应时间。
  • 容错架构。
  • 集成最先进的大数据技术,包括 Apache KafkaApache FlinkApache SparkApache Hive
  • 提供了一种基于本地 JSON 的语言,以及基于 HTTP 或 JDBC 的 SQL(实验性的)。
  • 由高级商业智能和分析数据探索和可视化工具支持,如元数据库Apache 超集

数据是如何存储的

Druid 中的表被命名为数据源,它们按照时间间隔进行划分。每个时间间隔被命名为组块,由片段组成。段是一种不可变的数据结构,它被周期性地持久化。例如,您可以设置每天或每小时创建一次分段,等等。如图 1 所示,一个段由以下三种列类型组成:

  • 时间戳:数据的时间戳(是否汇总)。
  • 维度:输入数据的字段,可用于过滤和分组。
  • 指标:预聚合(例如,第一、最后、总和、最大值等。).

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

图 1 ~分段核心数据结构

每个可以由一个或多个段文件组成。根据数据摄取的配置,当其记录的数量达到某个最大阈值(例如,五百万个记录)时,或者当存在多个并发摄取任务并且因此每个任务创建单独的段文件时,或者当任务中的段文件的文件大小超过某个阈值(例如,超过 512MB)时,可以创建段。有关细分市场的更多详细信息,您可以阅读官方文档。

此外,您可以指定段内数据的粒度。例如,假设您在用例中需要一个小时级别的粒度。您可以设置 druid 按小时自动聚合您的实时数据。为了说明 rollup 在 Druid 中是如何工作的,例如,考虑以下 JSON 中的输入数据片段:

{"timestamp":"2018-01-01T01:01:31Z","user_name":"Boxer","city":"San Fransisco","characters_added":1000} {"timestamp":"2018-01-01T01:02:16Z","user_name":"Boxer","city":"San Fransisco","characters_added":400} {"timestamp":"2018-01-01T01:03:21Z","user_name":"Boxer","city":"San Fransisco","characters_removed":25} {"timestamp":"2018-01-01T01:03:46Z","user_name":"Boxer","city":"San Fransisco","characters_added":400} {"timestamp":"2018-01-01T02:05:41Z","user_name":"Helz","city":"Calgary","characters_added":1800} {"timestamp":"2018-01-01T02:07:36Z","user_name":"Helz","city":"Calgary","characters_removed":17} {"timestamp":"2018-01-01T02:10:06Z","user_name":"Helz","city":"Calgary","characters_added":153}

每一行都是一个 json,代表一个输入事件。字段时间戳是使用 ISO-8601 标准表示的事件的时间戳,而 characters_addedcharacters_removed 是度量。为了简化起见,给定的数据片段在示例 JSON 中只包括两个维度,即用户名城市。通过将 rollup 设置为小时级别的粒度,上面的示例将被聚合到每小时的记录中,如图 1 所示。例如,在对应于区间2018–01–01t 01:00:00Z2018–01–01t 02:00:00Z的段中添加的 characters 的值就是其在该区间内的所有值的总和(即 1000 + 400 + 400 = 1800 )。有关汇总的更多细节,请参见官方教程。

架构的简要概述

Druid 有一个分布式和可伸缩的架构。Druid 的设计是由具有高可用性系统的需求驱动的,具有灵活的配置,同时是云友好的和易于操作的。下面的图 2 显示了该架构的示意图。

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

图 2 ~德鲁伊教建筑

首先,Druid 平台依赖于以下三个外部依赖:

  1. 深度存储:它可以是任何分布式文件系统或对象存储,如亚马逊 S3、Azure Blob 存储、阿帕奇 HDFS(或任何 HDFS 兼容系统),或网络挂载文件系统。深度存储的目的是持久存储 Druid 获取的所有数据,作为备份解决方案,同时在需要时可供所有 Druid 组件和集群使用。
  2. 元数据存储:由传统的关系数据库系统支持,如 PostgreSQL 或 MySQL。所有元数据对任何 Druid 组件都可用。Druid 中有各种类型的元数据,有些与深层存储中的持久段有关,例如段文件的路径、它们的时间戳、它们的版本等等。其他可能与外部系统相关,如来自 Apache Kafka 主题的摄取的分区偏移,其余与各种内部进程的元数据相关(例如,其中现在正在创建片段)。
  3. 动物园管理员:用于内部服务发现,协调,领袖选举。

Druid 的架构由以下处理类型的组件组成:

  • 中间管理器进程处理集群的数据接收。例如,他们负责从 Apache Kafka 接收实时流数据,或者从其他来源加载批量数据(例如,来自 HDFS 的文件)。
  • 历史进程处理“历史”数据的存储和查询。运行历史进程的节点从深层存储中提取数据段到本地磁盘,并响应关于这些数据段的查询。
  • 代理进程接收来自外部客户端的查询。它们识别哪些历史中间管理器节点正在服务这些段,并向这些进程中的每一个发送重写的子查询。此后,他们收集和合并结果,并回复呼叫者。在内部,历史进程响应对应于已经保存到深度存储的数据段的子查询,而中间管理器响应对应于最近摄取的数据(即,还没有发布到深度存储的内存中的数据)的子查询。
  • 为了平衡历史中层管理者流程上的数据,德鲁伊分别拥有协调者流程和霸主流程。协调器进程,具体来说,负责将段分配给运行历史进程的特定节点。类似地,霸王流程负责向中层经理分配摄取任务,并负责协调部门发布。
  • 最后路由器处理,在经纪人领主协调人面前提供统一的 API 网关。它们的使用是可选的,因为你也可以直接联系经纪人上司协调员

如前所述,Druid 由用于摄取、查询和协调的独立组件组成。每个 Druid 流程组件都可以独立地配置和伸缩,为您提供了最大的灵活性,以及对容错的健壮性(因为一个组件的中断不会立即影响其他组件)。此外,将深度存储和元数据存储与 Druid 系统的其余部分分离开来,可以从深度存储和元数据存储中保存的数据重新启动组件或整个集群。

数据摄取流程

数据接收流程分为两个部分。在第一部分中,中层管理人员正在运行索引任务,这些任务创建段并将其发布到深层存储。第二部分,通过历史进程从深层存储中获取发布的片段,以便在查询回答中使用。

索引:线段创建和发布

中层管理人员负责外部数据源的接收,例如在 HDFS 批量接收文件或从 Kafka 流式接收。图 3 中的图表突出显示了在数据摄取过程中参与的组件,而其余的组件是灰色的。在摄取期间,数据被索引、预聚合、分割成段(记录数量以及汇总间隔),然后发布到深层存储

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

图 3~索引:段创建和发布

来自数据源的数据摄取可对应于一个或多个摄取任务。对于日志和资源隔离,中间管理器进程创建摄取任务并将其转发给Peons——也就是每次处理单个摄取任务的独立 JVM 实例。

在索引任务开始时,会创建一个新的段。片段的输入数据可以来源于实时流(例如,卡夫卡主题)或一批文件(例如,HDFS 的 CSV 文件)。有两种摄入模式:

  • 附加模式:当输入数据源是一个流(例如,Kafka 主题)或者批量索引任务被设置为附加模式(即,读取文件并附加一个现有的 Druid 数据源)时,任务将新的段添加到相同时间间隔的现有段集合中。
  • 覆盖模式:旧段被停用,并被具有相同时间间隔的新版本号的新段替换。

Druid 的一个重要特性是,当前从实时任务中创建的片段是可立即查询的——例如,从 Kafka 消费的记录是可立即查询的,尽管它们尚未发布到深层存储

当任务已经索引了每个段的最大数量的记录(例如,五百万条记录)或者达到了期望的汇总时间间隔(例如,每小时聚集)时,任务完成。此时,通过将其数据保存到深层存储并将元数据保存到元数据存储来发布该段。

移交:为查询应答提取已发布的段

图 4 中的图表突出显示了在切换期间参与的组件,其余的组件是灰色的。

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

图 4 ~移交:为查询应答提取已发布的片段

协调器进程定期轮询元数据存储,以便从数据摄取任务中找到任何新发布的片段。一旦一个新创建的段被一个协调器进程发现,它选择哪个历史进程应该从深层存储器中获取该段。当该段成功加载后,历史流程准备好为其提供查询服务。

查询回答

客户端直接向代理发送查询(或者通过路由器间接发送)。可以使用基于本地 JSON 的语言或实验性 SQL 语言来表达查询。查询的类型可以是时间序列TopNGroupBy 中的任何一种。所有类型的前述查询至少包含目标间隔时间,以及感兴趣的维度和/或度量。目标时间间隔是 Druid 用来决定需要处理哪些片段来回答查询的信息。图 5 中的图表突出显示了在查询应答期间参与的组件,其余的组件是灰色的。

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

图 5 ~查询回答

一旦客户请求查询,代理的初始任务之一就是识别哪些流程服务于所需的细分市场。例如,假设 a 我们有兴趣找到“从现在开始过去 48 小时内每小时平均时间最高的前 10 名用户”。该查询既需要已经被索引并发布到深层存储的数据,也需要当前从中层管理器进程获取数据的片段。此时,代理将相应的子查询发送到历史中间管理器节点,每个节点将计算请求的聚合和过滤,然后发回结果。最后,代理收集并合并所需的数据,然后将最终结果返回给客户机。

结论

OLAP 系统是非常强大的数据库,用于处理商业智能、分析和数据科学应用程序常用的复杂聚合的即席查询。其设计背后的特征和概念将它们与传统的关系数据库区分开来,并使它们成为这类应用程序的理想选择。本文简要介绍了类似 OLAP 的 timeseries 数据库 Apache Druid ,概述了它的架构以及它的组件为数据接收、索引和查询应答而交互的方式。正如已经说明的,该架构是云友好的、易于操作的、高度可扩展的和灵活配置的。已经了解了数据是如何组织的,查询是如何计算的,在下一篇文章中,我们将通过使用开源库 Scruid 的示例查询来关注 Druid 的实际使用。

原载于 2019 年 3 月 29 日anskarl . github . io

Apache Hive 挂钩和 Metastore 监听器:元数据的故事

原文:https://towardsdatascience.com/apache-hive-hooks-and-metastore-listeners-a-tale-of-your-metadata-903b751ee99f?source=collection_archive---------7-----------------------

元数据介绍,什么是 hive 挂钩和 metastore 侦听器,何时使用它们,以及使用它们的一些探索

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

Photo by Dennis Kummer on Unsplash

开始前的假设

本文的目标读者应该对 Hive 和 Hadoop 生态系统特性有基本的了解。本文着重于比较和展示编写一个 Hive 钩子和一个 Metastore 侦听器需要什么,使您能够自动化元数据管理。

本帖涵盖的主题将是:

  • 元数据管理的需求
  • 元数据
  • 元数据管理
  • 为什么是阿帕奇蜂房?
  • 配置单元挂钩和 Metastore 监听器
  • 蜂巢挂钩概要
  • Metastore 侦听器摘要
  • 开始使用 Hive 环境
  • 探索钩子
  • 探索听者

元数据管理的需求

据 Gartner " 称,到 2020 年,大多数数据和分析用例 将需要连接到分布式数据源 ,这将导致企业在元数据管理方面的投资翻倍。

读完这句话后,您可能想知道:元数据到底代表什么?为什么它需要管理?

我可以告诉你,这是几个月前我想到的第一个问题…

[计]元数据

我们可以将元数据分类为:

  • 技术元数据:关于资产的详细信息,比如它的名称、类型、创建者的名字、对象的大小,或者最后一次更新的时间。
  • 业务元数据:提供关于资产的附加业务上下文,例如,它是否包含 PII(个人身份信息)、它应该被删除的日期以及许多其他信息。
  • 运营元数据 : 通常是关于资产使用情况的信息,如查询日志、数据采样和数据分析。

您还可以考虑关于资产的物理和逻辑信息,让我通过查看 Hive 和 Hadoop 生态系统来澄清这一点…

您的数据可以物理地存储在 hdfs 位置,并且在 Hive 上有许多不同的逻辑表指向它。

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

Photo by Amy Chen on Unsplash

这是一个很大的过程,但它会变得更加清晰…

元数据管理

元数据管理解决方案有助于回答与您的数据资产相关的问题,例如:

  • 我的数据资产安全吗?
  • 我是否符合所有这些新的数据保护法规?如 CCPAGDPRHIPAA
  • 谁具有可见性,谁可以对这些资产进行更改?

管理的本质通常始于维基、电子表格和各种文档,但当我们开始进入大数据世界时,它们很容易失去同步,我们变得无法回答这些问题。

你还记得关于脸书用户数据隐私的 50 亿美元罚款吗?你不想被放在一个无法回答这些问题的地方。

我们需要开始自动化我们的元数据管理!

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

A Data Dashboard. Photo by Carlos Muza on Unsplash

为什么是阿帕奇蜂房?

正如 Gartner 所言:“*大多数数据和分析用例都需要连接到分布式数据源”。*虽然Hive 只是其中之一,但它是一个开源项目,仍然被许多组织使用。

通过深入研究配置单元挂钩和 Metastore 侦听器,我们将了解如何在这种环境中连接到数据源,并收集有关其元数据更改的信息。值得一提的是,对于更复杂的元数据场景,像 Apache Atlas 这样的健壮数据治理和元数据框架可以在这个过程中为您提供帮助。

因此,我们将在本文中展示的是非常简单的实现,可以帮助您入门。

配置单元挂钩和 Metastore 侦听器

为了节省您的时间,让我简单地说一下,从概念上讲,它们基本上是相同的。重点是如何将每一个注册到 Hive 中,以及为他们提供什么信息。

本质上,我们创建了一个扩展接口或抽象类的类,带有我们的自定义逻辑,它将被钩子或监听器事件调用。

根据事件的不同,我们将获得不同的工作对象,让我们看一些例子:

  • 蜂巢挂钩:

Hive Hooks: Properties and Classes

  • Metastore 侦听器:

Metastore Listeners: Properties and Classes

对于它们中的每一个,你都有一对属性

属性是触发事件的地方,而类是您必须扩展的,所以配置单元运行器知道如何调用它。

为了演示如何以及何时使用它们,我们将探索**hive.exec.post.hook****hive.metastore.event.listener**属性。

蜂巢挂钩概述

让我们来看看使用 Hive 钩子的优缺点:

优点

  • 在查询处理的各个步骤中,可以更加灵活地运行/注入一些代码。
  • 可用于更新您的资产元数据,如表的访问时间,例如UpdateInputAccessTimeHook

缺点

  • 关于您的资产的元数据可能很难理解,您可能必须解析它,因为您正在处理钩子对象。
  • 您可以更改挂钩对象并影响配置单元查询处理。

对于 hive hook 方法,我们将使用**hive.exec.post.hook** 属性,这个属性在查询执行之后和结果返回给用户之前运行,一旦我们看到它运行,它将变得更加清晰。

Metastore 侦听器摘要

让我们来看看使用 Metastore 侦听器的一些优点和缺点:

优点

  • 关于您的资产的元数据已经被解析,更容易处理。
  • 不能影响查询处理,它是只读的。

缺点

  • 灵活性较差,您只能访问属于您的事件的对象。

对于 metastore 监听器方法,我们将使用**hive.metastore.event.listener**属性**。**

在该属性中,我们能够从**MetaStoreEventListener**抽象类的事件列表中进行选择。

Methods from the MetaStoreEventListener with their Parameters

为了使用它,我们覆盖我们想要的方法,当事件发生时,我们将接收参数对。为了展示这一点,我们将覆盖两个方法:**onCreateTable****onAlterTable**

是时候动手了,让我们探索这两种策略。

开始使用 Hive 环境

我们将使用通常推荐的生产配置单元环境,在该环境中,我们为配置单元服务器、metastore 和底层 RDBMS(代表配置单元存储元数据)提供了单独的进程。

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

Hive Environment showcasing Hook and Listener usage

需要指出的是,钩子和监听器连接到不同的进程,正如你在上面的图片中看到的。

如果你想建立一个如图所示的环境,有一个很好的 repo: docker-hive ,可以帮助你开始。

探索钩子

让我们来看看我们的定制钩子代码:

在 hook 上下文中,我们可以访问执行的查询、执行的操作以及查询执行的输入和输出。在这种情况下,我们只是过滤资产中的修改操作,并记录输入和输出值,这样我们就可以看到它们的结果。

出于测试目的,让我们在一个连接到我们的 Hive 服务器的直线终端中注册这个钩子。

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

现在让我们运行一些命令来查看它们的结果:

  • show tables

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

在我们的钩子中这是一个不受监控的操作,所以在这种情况下没有关于对象的日志,但是您能发现操作元数据吗?

我们正在记录执行的查询:)

  • CREATE TABLE post (code INT, text STRING);

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

让我们看看 JSON 日志对象:

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

Full JSON file here

你能在这个 JSON 对象中找到所有的技术元数据吗?!看看所有这些字段和布尔标志,并开始思考我们可以监控的一切!

如果您注意到 JSON 中没有关于列名(codetext)的信息,那么在CREATETABLE事件中,如果我们需要这些信息,我们将需要额外的工作。

  • ALTER TABLE post ADD COLUMNS (release_date string COMMENT ‘Release date for this post’);

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

让我们看看 JSON 日志对象:

Some fields were suppressed to keep it short

与 Create Table 语句相比,我们有两个output对象,一个代表数据库,另一个代表表。
现在,对于 Alter Table 语句,我们有一个input对象和一个output对象,两者都表示表。

这里有一个问题,output对象不包含新列release_date,它表示应用更改之前的目标对象。

让我们使用侦听器运行相同的操作进行比较。

你可以在这个 git repo 上找到完整的实现。关于注册钩子需要改变什么文件的更多细节,请查看README.md文件。

探索听者

让我们看一下我们的定制监听器代码:

这里我们订阅了两个事件:**onCreateTable****onAlterTable**。如您所见,我们访问的对象与它们的事件相关联,对于**onCreateTable** 我们获得事件表元数据,对于**onAlterTable** 我们获得新旧表元数据。

当使用监听器时,我们不能像使用自定义钩子那样注册它,因为它运行在 Metastore 进程上。如果你想看到你需要修改的配置文件,请查看本主题底部的README.md

现在让我们运行一些命令来查看它们的结果:

在运行命令之前,我清除了配置单元环境,以便我们能够使用相同的表名。

  • CREATE TABLE post (code INT, text STRING);

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

让我们看看 JSON 日志对象:

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

Full JSON file here

  • ALTER TABLE post ADD COLUMNS (release_date string COMMENT ‘Release date for this post’);

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

Some fields were suppressed to keep it short

这里我们可以看到新的表元数据包含了添加的列release_date,因此使用已经解析的对象有其优势。

你可以在这个 git repo 上找到完整的实现。有关注册监听器需要更改哪些文件的更多详细信息,请查看README.md 文件。

结束语

在本文中,我们介绍了如何在 Hive 环境中连接来自资产的元数据,使您能够自动化元数据管理。我们演示了一个简单的实现,只是记录了操作性的元数据,但是正如我们在本文开头看到的,我们可能会处理许多分布式数据源。下一步是扩展代码,将元数据事件发布到消息系统,如 Kafka、Pub/Sub 或 SQS,并更新您的元数据管理工具。这样做将使我们能够将业务元数据添加到我们的资产中,所以敬请关注!

希望你觉得有用!如果你喜欢这篇文章并想看更多,一定要关注我的简介。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值