TowardsDataScience-博客中文翻译-2016-2018-三十三-

TowardsDataScience 博客中文翻译 2016~2018(三十三)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

综述:例外—深度方向可分离卷积,优于 Inception-v3(图像分类)

原文:https://towardsdatascience.com/review-xception-with-depthwise-separable-convolution-better-than-inception-v3-image-dc967dd42568?source=collection_archive---------3-----------------------

在这个故事中,谷歌的exception【1】,代表《盗梦空间》的极致版,进行了回顾。通过修改的深度方向可分离卷积**,它在 ImageNet ILSVRC 和 JFT 数据集上都比 Inception-v3**【2】(也是由谷歌在 ILSVRC 2015 中获得亚军)更好。虽然这是一篇去年刚刚发表的 2017 CVPR 论文,但在我写这篇文章的时候,它已经被引用了 300 多次。( Sik-Ho Tsang @中)

涵盖哪些内容

  1. 原始深度方向可分离卷积
  2. 外的改进深度方向可分离卷积
  3. 整体架构
  4. 与最先进结果的比较

1。原始深度方向可分离卷积

Original Depthwise Separable Convolution

原始深度方向可分离卷积是深度方向卷积后跟一个点方向卷积

  1. 深度方向卷积通道方向 n×n 空间卷积。假设在上图中,我们有 5 个通道,那么我们将有 5 个 n×n 空间卷积。
  2. 逐点卷积实际上是改变尺寸的 1×1 卷积

与常规卷积相比,我们不需要在所有通道上执行卷积。这意味着连接数量更少,型号更轻。

2。除外的改进深度可分卷积

The Modified Depthwise Separable Convolution used as an Inception Module in Xception, so called “extreme” version of Inception module (n=3 here)

修改的深度方向可分离卷积是点方向卷积,后面是深度方向卷积。这种修改是由 inception-v3 中的 Inception 模块引起的,即在任何 n×n 空间卷积之前首先进行 1×1 卷积。因此,它与原来的有点不同。(这里 n=3 因为在 Inception-v3 中使用了 3×3 空间卷积。)

两个小区别:

  1. 操作顺序:如上所述,通常实现的原始深度方向可分离卷积(例如在 TensorFlow 中)首先执行通道方向空间卷积,然后执行 1×1 卷积,而修改的深度方向可分离卷积首先执行 1×1 卷积,然后执行通道方向空间卷积。这被认为是不重要的,因为当它被用在堆叠设置中时,在所有链接的初始模块的开始和结束处只有很小的差别。
  2. 存在/不存在非线性:在初始模块中,第一次操作后存在非线性。除了修改的深度方向可分离卷积之外,没有中间 ReLU 非线性

The modified depthwise separable convolution with different activation units

测试了具有不同激活单元的改进深度可分卷积。如上图所示,与使用 ELU 或 r ELU 的情况相比,没有任何中间激活的例外具有最高的准确性

3。整体架构

Overall Architecture of Xception (Entry Flow > Middle Flow > Exit Flow)

如上图所示, SeparableConv 是修正的深度方向可分离卷积。我们可以看到,SeparableConvs 被视为初始模块,并被放置在整个深度学习架构中。

还有最初由 ResNet [3]提出的针对所有流的剩余(或快捷方式/跳过)连接

ImageNet: Validation Accuracy Against Gradient Descent Steps

正如在架构中看到的,存在剩余连接。这里,它使用非剩余版本测试异常。从上图可以看出,使用残差连接时,精度要高得多。由此可见,剩余连接极其重要!!!

4。与最先进结果的比较

测试了 2 个数据集。一个是 ILSVRC。一个是 JFT。

4.1.ImageNet — ILSVRC

ImageNet 是一个数据集,包含超过 1500 万张带有标签的高分辨率图像,大约有 22,000 个类别。

ILSVRC 在 1000 个类别中的每个类别中使用大约 1000 个图像的 ImageNet 子集。总的来说,大约有 130 万幅训练图像、50,000 幅验证图像和 100,000 幅测试图像。

ImageNet: Xception has the highest accuracy

Xception 优于 VGGNet [4]、ResNet [3]和 Inception-v3 [2]。(如果感兴趣,也请访问我关于他们的评论,广告了,lol)

需要注意的是,在错误率方面,而不是准确率方面,相对提升不小!!!

ImageNet: Validation Accuracy Against Gradient Descent Steps

当然,从上图来看,沿着梯度下降的台阶,Xception 比 Inception-v3 有更好的准确率。

但如果用非残差版本和 Inception-v3 对比,Xception 表现不如 Inception-v3。为了公平比较,是不是应该有一个残版的 Inception-v3 比较好?无论如何,Xception 告诉我们,利用深度方向可分离卷积和残差连接,确实有助于提高精度。

Model Size/Complexity

据称,Xception 与 Inception-v3 的模型大小相似。

4.2.JFT—fast val 14k

JFT 是一个用于大规模图像分类数据集的内部谷歌数据集,由 Hinton 教授等人首先介绍,它包括超过 3.5 亿张高分辨率图像,标注有来自 17,000 个类别的标签。

使用辅助数据集 FastEval14k。FastEval14k 是一个包含 14,000 幅图像的数据集,具有来自大约 6,000 个类的密集注释(平均每幅图像 36.5 个标签)。

由于多个目标密集地出现在一幅图像中,因此使用平均精度预测(mAP)进行测量。

FastEval14k: Xception has highest mAP@100

FastEval14k: Validation Accuracy Against Gradient Descent Steps

同样,与 Inception-v3 相比,Xception 的 mAP 更高。

参考

  1. 【2017 CVPR】【例外】
    例外:深度可分卷积深度学习
  2. 【2016 CVPR】【盗梦空间-v3】
    重新思考计算机视觉的盗梦空间架构
  3. 【2016 CVPR】【ResNet】
    用于图像识别的深度残差学习
  4. 【2015 ICLR】【VGGNet】
    用于大规模图像识别的极深度卷积网络

我的评论

  1. 回顾:Inception-v3–ILSVRC 2015 亚军(图像分类)
  2. 回顾:ResNet—ils vrc 2015(图像分类、定位、检测)获奖者
  3. 点评:VGGNet—ils vrc 2014 亚军(图像分类)、冠军(本地化)

复习:YOLOv2 & YOLO9000 —你只看一次(物体检测)

原文:https://towardsdatascience.com/review-yolov2-yolo9000-you-only-look-once-object-detection-7883d2b02a65?source=collection_archive---------4-----------------------

在这个故事里, YOLOv2,你只看一次版本 2,是评论。YOLOv2 比 YOLOv1 有多项改进。YOLO9000 还被提议使用单词树检测超过 9000 个对象类别。

下面(我相信)是作者非常著名的 YOLOv2 视频:

YOLOv2

在 67 FPS 时,YOLOv2 在 PASCAL VOC 2007 上获得了 76.8%的 mAP40 FPS,YOLOv2 获得 78.6% mAP更快 R-CNN 使用ResNet和 SSD。取得如此好的成绩,YOLOv2 发表在 2017 CVPR 上,并获得超过 1000 次引用。( Sik-Ho Tsang @中)

YOLOv2

论文题目是“ YOLO9000:更好更快更强”。
那么,让我们看看怎样才能更好更快更强!!!

涵盖哪些内容

  1. YOLOv2 比yolo v1(更好)
  2. YOLOv2 使用 Darknet-19(更快)
  3. YOLO9000 by WordTree(更强)

1。YOLOv2 的改进超过了yolo v1(更好)

1.1.批量归一化(BN)

  • BN 用于 YOLOv2 中的所有卷积层。
  • 地图提高 2%。

1.2.高分辨率分类器

  • 经过 224×224 图像训练后,YOLOv2 还使用 448×448 图像在 ImageNet 上对分类网络进行 10 个时期的微调。
  • 地图增加 4%。

1.3.带有锚盒的回旋

  • YOLOv2 移除所有完全连接的层,并使用锚定框来预测边界框。
  • 移除一个池层以提高输出的分辨率。
  • 现在使用 416×416 的图像来训练检测网络。
  • 并且获得 13×13 的特征图输出,即 32×下采样。
  • 在没有锚盒的情况下,中间模型获得了 69.5%的 mAP 和 81%的召回率。
  • 使用锚盒,获得了 69.2%的 mAP 和 88%的召回率。虽然地图略有下降,但召回率大幅上升。

1.4.维度群

  • 锚定框的大小和比例是预先定义的,没有获得任何事先信息,就像《更快的 R-CNN 中的 一样。
  • 使用基于标准欧几里德距离的 k-means 聚类不够好,因为较大的盒子比较小的盒子产生更多的误差
  • YOLOv2 使用 k-means 聚类,可获得良好的 IOU 分数:

Cluster IOU

  • k = 5 是在模型复杂性和高召回率之间取得良好平衡的最佳值。

Different IOU Clustering Approaches with DIfferent Number of Anchor Boxes

  • 具有 5 个锚框的基于 IOU 的聚类(61.0%)具有与具有 9 个锚框的 更快 R-CNN 中的相似的结果(60.9%)。
  • 基于 IOU 的 9 锚盒聚类得到 67.2%。

1.5.直接位置预测

  • YOLOv1 对位置预测没有约束,这使得模型在早期迭代时不稳定。预测的边界框可能远离原始网格位置。
  • YOLOv2 使用逻辑激活σ来限定位置,这使得值落在 0 到 1 之间:

Constrained Bounding Box Prediction

  • (cx,cy)是网格的位置。
  • (bx,by)是包围盒的位置:(cx,cy) +由σ(tx)和σ(ty)包围的 delta。
  • (pw,ph)是从聚类中得到的锚盒先验。
  • (bw,bh)是边界框尺寸:(pw,ph)乘以(tw,th)。
  • 地图比锚盒版本增加了 5%。

1.6.精细特征

  • 13×13 特征图输出足以检测大物体。
  • 为了更好地检测小目标,将前一层的 26×26×512 特征图映射为 13×13×2048 特征图,然后与原始的 13×13 特征图连接进行检测。
  • mAP 增加了 1%。

1.7.多尺度训练

  • 对于每 10 个批次,随机选择新的图像尺寸。
  • 图像尺寸为{320,352,…,608}。
  • 调整网络大小并继续训练。

1.8.增量改进总结

Incremental Improvements

  • 较小尺寸的图像网络运行速度更快。
  • 对于低分辨率的 YOLOv2,在 90 FPS 的情况下,mAP 和 快速 R-CNN 一样好,非常适合更小的 GPU。
  • 对于高分辨率 YOLOv2,以实时速度获得 76.8%的 mAP。

PASCAL VOC 2007 Dataset

对于 MS COCO 数据集,以下方法中只有 YOLOv2 可以获得实时性能:

Microsoft COCO Dataset

2。YOLOv2 使用 Darknet-19(更快)

除了以上修改,网络架构也是影响 mAP 的一个因素。

在 YOLOv2 中使用 Darknet-19 分类网络进行特征提取:

Darknet-19 Classification Network

我们可以看到,Darknet-19 有许多 1×1 卷积来减少参数的数量。(如果对原因感兴趣,请访问我在 GoogLeNet 上的评论。)

Darknet-19 可以在准确性和模型复杂性之间获得良好的平衡:

1000-Class ImageNet Classification Results

由于 Top-1 和 Top-5 错误接近于 ResNet-50 ,Darknet-19 具有更低的模型复杂度(FLOP),因此具有更快的检测速度(FPS)。

3. YOLO9000 by WordTree(更强)

有多个数据集用于分类和检测。作者有一个想法,“他们能结合在一起吗?”

3.1。联合收割机

COCO and ImageNet

  • 微软 COCO : 100k 图片,80 个类,检测标签,类比较笼统像“狗”或者“船”。
  • ImageNet:1300 万张图片,22k 个类别,分类标签,类别更具体,如“诺福克梗”,“约克夏梗”,或“贝德灵顿梗”。
  • 像“狗”和“诺福克梗”这样的类别并不互相排斥。

我们不能通过添加更多的类来直接组合它们,如下所示:

We CANNOT combine like this

为了合并,使用了单词树:

WordTree

如上所示,WordTree 有一个层次结构树,将类和子类联系在一起。简而言之,基于树的单词树是在基于图的单词网的基础上,通过将 ImageNet 中的名词可视化,并在单词网中选择较短的路径来构建的。

例如:“诺福克梗”也有“狗”和“哺乳动物”的标签。

如果网络看到“狗”的图像,但不确定它是哪种类型,它仍然会基于条件概率以高置信度预测为“狗”。

最后有 9418 个班。

3.2.YOLO9000 培训

  • 使用 3 个先验而不是 5 个先验来限制输出大小。
  • 对于检测图像,损失通常反向传播。
  • 对于分类图像,只有分类损失在标签的相应级别或以上被反向传播。

3.3.YOLO9000 结果

  • 获得了 19.7%的 mAP。

YOLO9000 Results

最初,COCO 女士没有这么多的基本事实类,而 ImageNet 有类,但没有基本事实边界框。

现在 YOLO9000 提供了一种将它们结合在一起的方法。

参考

【2017 CVPR】【yolov 2 & yolo 9000】
yolo 9000:更好更快更强

我的相关评论

[ R-CNN ] [ 快速 R-CNN ] [ 更快 R-CNN][SSD][yolov 1][VGGNet][ResNet][Google net/Inception-v1][Inception-v2/BN-Inception]

岭和套索回归:L1 和 L2 正则化

原文:https://towardsdatascience.com/ridge-and-lasso-regression-a-complete-guide-with-python-scikit-learn-e20e34bcbf0b?source=collection_archive---------0-----------------------

使用 Scikit 的完整指南-学习

从我上周讨论的非常重要的非监督学习技术继续,今天我们将通过线性回归深入探讨监督学习,特别是两个特殊的线性回归模型——Lasso 和 Ridge regression。

由于我使用了术语“线性”,首先让我们澄清一下,线性模型是使用输入要素的线性函数来预测输出的最简单方法之一。

Linear model with n features for output prediction

在上面的等式(1.1)中,我们已经示出了基于 n 个特征的线性模型。只考虑单一特征,因为你可能已经知道 w[0] 将是斜率,而 b 将代表截距。线性回归寻找优化 wb ,使得它最小化成本函数。成本函数可以写成

Cost function for simple linear model

在上面的等式中,我假设数据集有 M 个实例和 p 个特征。一旦我们对分成训练集和测试集的数据集使用线性回归,计算训练集和测试集的分数可以给我们一个粗略的概念,即模型是过拟合还是欠拟合。如果你足够幸运的话,选择的线性模型也可以是恰到好处的!如果数据集上的特征很少,训练集和测试集的得分都很低,那么这就是拟合不足的问题。另一方面,如果我们有大量的特征,并且测试分数比训练分数相对较差,那么这就是过度概括或过度拟合的问题。岭和套索回归是降低模型复杂性和防止简单线性回归可能导致的过度拟合的一些简单技术

岭回归: 在岭回归中,通过增加一个等价于系数大小平方的惩罚来改变成本函数。

Cost function for ridge regression

这相当于在如下条件下最小化等式 1.2 中的成本函数

Supplement 1: Constrain on Ridge regression coefficients

因此岭回归对系数 (w)施加了约束。罚项(λ)正则化系数,使得如果系数取大值,优化函数被罚。因此,岭回归缩小了系数,有助于降低模型复杂性和多重共线性。**回归情商。1.3 可以看出,当λ → 0 时,成本函数变得类似于线性回归成本函数(等式。1.2).因此*降低对特征的约束(低λ),模型将类似于线性回归模型。*让我们看一个使用波士顿数据的例子,下面是我用来描述线性回归作为岭回归的极限情况的代码

import matplotlib.pyplot as plt
import numpy as np 
import pandas as pd
import matplotlib
matplotlib.rcParams.update({'font.size': 12})from sklearn.datasets import load_boston
from sklearn.cross_validation import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import Ridgeboston=load_boston()
boston_df=pd.DataFrame(boston.data,columns=boston.feature_names)
#print boston_df.info()# add another column that contains the house prices which in scikit learn datasets are considered as target
boston_df['Price']=boston.target
#print boston_df.head(3)newX=boston_df.drop('Price',axis=1)
print newX[0:3] # check 
newY=boston_df['Price']#print type(newY)# pandas core frameX_train,X_test,y_train,y_test=train_test_split(newX,newY,test_size=0.3,random_state=3)
print len(X_test), len(y_test)lr = LinearRegression()
lr.fit(X_train, y_train)rr = Ridge(alpha=0.01) # higher the alpha value, more restriction on the coefficients; low alpha > more generalization,
# in this case linear and ridge regression resemblesrr.fit(X_train, y_train)rr100 = Ridge(alpha=100) #  comparison with alpha value
rr100.fit(X_train, y_train)train_score=lr.score(X_train, y_train)
test_score=lr.score(X_test, y_test)Ridge_train_score = rr.score(X_train,y_train)
Ridge_test_score = rr.score(X_test, y_test)Ridge_train_score100 = rr100.score(X_train,y_train)
Ridge_test_score100 = rr100.score(X_test, y_test)plt.plot(rr.coef_,alpha=0.7,linestyle='none',marker='*',markersize=5,color='red',label=r'Ridge; $\alpha = 0.01$',zorder=7) plt.plot(rr100.coef_,alpha=0.5,linestyle='none',marker='d',markersize=6,color='blue',label=r'Ridge; $\alpha = 100$') plt.plot(lr.coef_,alpha=0.4,linestyle='none',marker='o',markersize=7,color='green',label='Linear Regression')plt.xlabel('Coefficient Index',fontsize=16)
plt.ylabel('Coefficient Magnitude',fontsize=16)
plt.legend(fontsize=13,loc=4)
plt.show()

Figure 1: Ridge regression for different values of alpha is plotted to show linear regression as limiting case of ridge regression. Source: Author.

让我们来理解上图。在 X 轴上,我们绘制了系数索引,对于波士顿数据,有 13 个特征(对于 Python,第 0 个索引是指第 1 个特征)。对于较低的α值(0.01),当系数限制较少时,系数的大小几乎与线性回归相同。对于较高的α (100)值,我们看到,与线性回归情况相比,系数指数 3、4、5 的幅度要小得多。这是一个使用岭回归缩小系数大小的例子。

**Lasso 回归:**Lasso(最小绝对收缩和选择算子)回归的成本函数可以写成

Cost function for Lasso regression

Supplement 2: Lasso regression coefficients; subject to similar constrain as Ridge, shown before.

就像岭回归成本函数一样,对于λ= 0,上面的等式简化为等式 1.2。*唯一的区别是,不考虑系数的平方,而是考虑幅度。*这种类型的正则化(L1)可导致零系数,即某些特征在输出评估中被完全忽略。**因此,Lasso 回归不仅有助于减少过度拟合,还能帮助我们进行特征选择。**正如岭回归一样,可以控制正则化参数(λ),我们将使用sklearn中的癌症数据集看到以下效果。我使用癌症数据而不是我以前使用的波士顿房屋数据的原因是,癌症数据集有 30 个特征,而波士顿房屋数据只有 13 个特征。因此,通过改变正则化参数可以很好地描述 Lasso 回归的特征选择。

Figure 2: Lasso regression and feature selection dependence on the regularization parameter value. Source: Author.

我用来绘制这些图的代码如下

import math 
import matplotlib.pyplot as plt 
import pandas as pd
import numpy as np# difference of lasso and ridge regression is that some of the coefficients can be zero i.e. some of the features are 
# completely neglectedfrom sklearn.linear_model import Lasso
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_breast_cancer
from sklearn.cross_validation import train_test_splitcancer = load_breast_cancer()
#print cancer.keys()cancer_df = pd.DataFrame(cancer.data, columns=cancer.feature_names)#print cancer_df.head(3)X = cancer.data
Y = cancer.targetX_train,X_test,y_train,y_test=train_test_split(X,Y, test_size=0.3, random_state=31)lasso = Lasso()
lasso.fit(X_train,y_train)
train_score=lasso.score(X_train,y_train)
test_score=lasso.score(X_test,y_test)
coeff_used = np.sum(lasso.coef_!=0)print "training score:", train_score 
print "test score: ", test_score
print "number of features used: ", coeff_usedlasso001 = Lasso(alpha=0.01, max_iter=10e5)
lasso001.fit(X_train,y_train)train_score001=lasso001.score(X_train,y_train)
test_score001=lasso001.score(X_test,y_test)
coeff_used001 = np.sum(lasso001.coef_!=0)print "training score for alpha=0.01:", train_score001 
print "test score for alpha =0.01: ", test_score001
print "number of features used: for alpha =0.01:", coeff_used001lasso00001 = Lasso(alpha=0.0001, max_iter=10e5)
lasso00001.fit(X_train,y_train)train_score00001=lasso00001.score(X_train,y_train)
test_score00001=lasso00001.score(X_test,y_test)
coeff_used00001 = np.sum(lasso00001.coef_!=0)print "training score for alpha=0.0001:", train_score00001 
print "test score for alpha =0.0001: ", test_score00001
print "number of features used: for alpha =0.0001:", coeff_used00001lr = LinearRegression()
lr.fit(X_train,y_train)
lr_train_score=lr.score(X_train,y_train)
lr_test_score=lr.score(X_test,y_test)print "LR training score:", lr_train_score 
print "LR test score: ", lr_test_scoreplt.subplot(1,2,1)
plt.plot(lasso.coef_,alpha=0.7,linestyle='none',marker='*',markersize=5,color='red',label=r'Lasso; $\alpha = 1$',zorder=7) # alpha here is for transparency
plt.plot(lasso001.coef_,alpha=0.5,linestyle='none',marker='d',markersize=6,color='blue',label=r'Lasso; $\alpha = 0.01$') # alpha here is for transparency

plt.xlabel('Coefficient Index',fontsize=16)
plt.ylabel('Coefficient Magnitude',fontsize=16)
plt.legend(fontsize=13,loc=4)plt.subplot(1,2,2)plt.plot(lasso.coef_,alpha=0.7,linestyle='none',marker='*',markersize=5,color='red',label=r'Lasso; $\alpha = 1$',zorder=7) # alpha here is for transparency
plt.plot(lasso001.coef_,alpha=0.5,linestyle='none',marker='d',markersize=6,color='blue',label=r'Lasso; $\alpha = 0.01$') # alpha here is for transparency
plt.plot(lasso00001.coef_,alpha=0.8,linestyle='none',marker='v',markersize=6,color='black',label=r'Lasso; $\alpha = 0.00001$') # alpha here is for transparency
plt.plot(lr.coef_,alpha=0.7,linestyle='none',marker='o',markersize=5,color='green',label='Linear Regression',zorder=2)plt.xlabel('Coefficient Index',fontsize=16)
plt.ylabel('Coefficient Magnitude',fontsize=16)
plt.legend(fontsize=13,loc=4)
plt.tight_layout()
plt.show() #output training score: 0.5600974529893081
test score:  0.5832244618818156
number of features used:  4training score for alpha=0.01: 0.7037865778498829
test score for alpha =0.01:  0.664183157772623
number of features used: for alpha =0.01: 10training score for alpha=0.0001: 0.7754092006936697
test score for alpha =0.0001:  0.7318608210757904
number of features used: for alpha =0.0001: 22LR training score: 0.7842206194055068
LR test score:  0.7329325010888681

让我们用简短的总结来理解剧情和代码。

  • Lasso 回归中正则化参数的默认值(由α给出)为 1。
  • 由此,在癌症数据集中的 30 个特征中,仅使用了 4 个特征(系数的非零值)。
  • 训练和测试分数(只有 4 个特征)都很低;得出结论,该模型不符合癌症数据集。
  • 通过减少 alpha 和增加迭代次数来减少这种欠拟合。现在α = 0.01,非零特征=10,训练和测试分数增加。
  • 图 2 的左图显示了两个不同α值的系数大小的比较。对于α= 1,我们可以看到大部分系数为零或接近零,而α= 0.01 则不是这样。
  • 进一步减少α =0.0001,非零特征= 22。训练和测试分数类似于基本线性回归情况。
  • 在右图中,当α = 0.0001 时,套索回归和线性回归的系数非常相似。

套索正则化如何导致特征选择?

到目前为止,我们已经学习了岭和套索回归的基础知识,并看到了一些理解应用的例子。现在,我将尝试解释为什么套索回归可以导致特征选择,而岭回归只减少接近零的系数,而不是零。下面的插图将帮助我们更好地理解,我们将假设一个只有两个特征的假设数据集。使用脊和套索回归系数的约束(如以上补充 1 和 2 所示),我们可以绘制下图

Figure 3: Why LASSO can reduce dimension of feature space? Example on 2D feature space. Modified from the plot used in ‘The Elements of Statistical Learning’ by Author.

对于二维特征空间,用青色和绿色绘制套索和脊回归的约束区域(见附录 1 和 2)。椭圆轮廓是线性回归的成本函数(等式)。1.2).现在,如果我们放宽了系数的条件,那么约束区域会变得更大,最终它们会到达椭圆的中心。当岭和套索回归类似于线性回归结果时就是这种情况。否则,**两种方法都通过找到椭圆轮廓碰到约束区域的第一个点来确定系数。菱形(套索)在轴上有角,不像圆盘,每当椭圆区域碰到这样的点,其中一个特征完全消失!**对于更高维度的特征空间,使用 Lasso 回归可以在轴上有许多解决方案,因此我们只选择重要的特征。

最后,为了结束这次冥想,让我们总结一下到目前为止我们学到了什么

  1. 脊套回归的代价函数和正则项的重要性。
  2. 通过一些使用简单数据集的例子来理解线性回归作为套索和岭回归的极限情况。
  3. 理解了为什么 Lasso 回归可以导致特征选择,而 Ridge 只能将系数缩小到接近于零。

对于进一步的阅读,我建议“统计学习的元素”;J. Friedman 等人,Springer,第 79-91 页,2008 年。这里展示的使用 L1 和 L2 来演示正则化的例子受到了 Andreas Muller 的《使用 Python 进行机器学习》一书的影响。

希望你喜欢这篇文章,并保持快乐!干杯!

页(page 的缩写)请参阅阿坎沙·拉瓦特的评论,他对在应用岭回归算法之前标准化变量提出了批评意见。

如果你对更深入的基础机器学习概念感兴趣,可以考虑加盟 Medium 使用 我的链接 。你不用额外付钱,但我会得到一点佣金。感谢大家!!

[## 通过我的推荐链接加入媒体

更多来自 Saptashwa(以及媒体上的所有其他作者)。你的会员费直接支持 Saptashwa 和其他作家…

medium.com](https://medium.com/@saptashwa/membership?source=publishing_settings-------------------------------------)

撕掉文字云,聊天情节万岁

原文:https://towardsdatascience.com/rip-wordclouds-long-live-chatterplots-e76a76896098?source=collection_archive---------13-----------------------

在 R 中用一种整洁的方法代替“文本数据的饼图”

在这篇简短的帖子中,我提出了一个信息更加丰富的替代方案,以 R 代码为例,使用了一个tidy text&gg plot 2框架。

前言

数据即字云的缺陷已经很好的覆盖了,随着替代 接近,我在此不再赘述。

尽管如此,单词云仍然是常见的,因为它们令人困惑。在许多方面,它们仍然是文本数据可视化的事实上的标准,至少在技术含量较低的分析中是这样(这一点很明显,并且可能因为大量易于使用的在线工具而变得更加糟糕)。这才真正使它们成为*饼状图 的自然语言 。(因此,两者仍然有它们的位置,尽管几乎总是不如其他选项)。*

总结我个人对 wordclouds 的不满:

  • ***无序&迷失方向:*一个单词在视觉平面上的位置(或者它面对的方向)没有逻辑,所以我永远不知道从哪里开始,下一步看哪里,或者我已经看了哪里。我总是在几句话后就迷失了方向,然后我放弃了。
  • 一维低信息:它们通常只传达一个维度:词频,尽管有时会故意使用颜色编码。这限制了上下文传达的信息量。
  • ***没有尺度:*通常捕捉到的单一维度(词频)甚至没有很好的表现,因为几乎从来没有任何尺度感。例如,即使按比例调整了大小,也没有指示最大或最小的单词在文档中出现的频率。最重要的词可能出现在 90%或 9%的回答中,彻底改变了对数据的任何合理解释。
  • ***任意性&不透明:*以上几点都导致了文字云压倒性的任意性&不透明性,导致了糟糕的信噪比,这使得文字云往往更令人困惑,而不是更有启发性。

我认为,文字云的一些可取之处:

  • 直接绘制数据 (而不是数据的几何抽象)
  • 能够让自己获得身临其境、探索性的用户体验

那么什么是更好的方法呢?

几乎任何事情。

除了上面链接的备选方案 方法之外,茱莉亚·西尔格&大卫·罗宾逊的用 R 整理文本挖掘包含了许多例子,从简单的条形图到更复杂的网络图(&是的,向文字云致敬),并附有 R 代码。

我在与《每日新闻》Philly.com 的问询者&的&洞察团队一起为内部 NLP 框架构建方法原型时,大量借鉴了他们的工作。我们最初的任务是总结对 NPS 调查的自由形式的回复,但是应该推广到各种自然语言:用户评论、客户服务反馈、实际文章内容等等。

介绍聊天情节

在总结 NPS 响应的情况下,我们有关于多尺度&维度的信息:

  • 词频 : 一个离散的数值变量
  • 每位用户自我报告的推广者得分(“您推荐我们产品的可能性有多大,从 1 到 10 分?”):一个离散的数值/序数变量
  • 每个用户的 NPS 发起者/诋毁者/被动者 类别,基于他们的发起者分数:分类/顺序变量
  • 用户群 /每个用户的调查版本(例如 7 天印刷订户、仅周日印刷、仅数字等):分类变量
  • 复合指标,如按词、NPS 类别或用户群的净或平均推广者分数:连续数字变量
  • 派生的 NLP 度量情感得分 & tf-idf :典型的连续数值变量**

有这么多的信息要传达,一个词云感觉远远不够。

除了用多面条形图通过分类变量简单表示单词或 n- gram 频率之外,我还想利用一个完整的 x,y 笛卡尔平面&将 wordclouds 的直接数据绘制、探索性质映射到更定量的声音、信息丰富的可视化方法。

我的第一个想法是尝试一个带标签的散点图,y 轴是词频,x 轴是每个词的平均推广分数。但是散点图的点很快变得多余&有噪声,那么为什么不直接绘制标签呢?

ggplot[geom_text()](https://ggplot2.tidyverse.org/reference/geom_text.html)实现了这一点,而gg replay扩展包通过geom_text_repel().提供了更好的易读性的自动间距

我绝对没有发明最终的情节,因为它只是一个用文字而不是点组成的散点图,但我相信我是第一个用聪明/愚蠢的名字'chatter plot'命名它的人,不管那值不值得…

为了演示,我们将通过 Google BigQuery 的公共数据集调出黑客新闻评论&他们的排名:

**

因此,我们有 8000 多条评论和它们的排名(越低=越好),我们将使用它们作为原始 NPS 调查数据的推广者分数的某种代理。

可以看到,排名有很大的偏差(可能的排名取决于评论的总数:如果至少有 10 条评论,一个人只能排在第 10 位),所以为了可视化的目的,我们希望用对数表示它们。

但是首先,我们需要预处理自然语言文本数据,如整齐文本挖掘中所述:

看起来前 8 个左右的单词是文本编码工件,所以我们将在绘图前过滤掉所有大于 2000 的内容。

我们还需要计算每个单词的平均排名,以在我们的图中加入一个额外的维度,然后将其加入到单词计数数据中:

*# compute avg comment ranking of each word
hn_word_avg_rank <- hn_word_tokens_no_stop %>%
  group_by(word) %>%
  summarize(avg_rank = mean(ranking))# filter word counts & join to average ranks
hn_counts_and_ranks <- hn_word_counts %>% filter(n < 2000 ) %>% 
  left_join(hn_word_avg_rank, by = "word")*

现在我们准备好选择前 100 个单词&构建我们的聊天情节!

输出:

它就像是一个单词云,除了有顺序的实际数量逻辑,元素的布局美学方面,以及每一个的显式比例参考。这使我们能够在情节中表现更多的多维信息,为观众提供一个连贯的视觉逻辑。

在这个特定的情节中可能有几个有趣的点,但这些都是常见的词(事实上是 8000 条评论中最常见的),所以尽管删除了停用词,但往往不是很有实质性。排名也没有太大变化,因为大多数单词来自前 10 名评论。

让我们尝试另一个对话图,这次按照最低排名(意味着最高排名)选择前 100 个单词:

Careers 是一个明显的离群值,而其余的词则拥挤在低频范围内,最右边、排名最低的评论中有很多网址(可能表明是垃圾邮件?).

我们可以通过添加对 ggplot 的ylim(0,6)调用来放大这些:

这样更好看。

不爱 opentable ,但send grid&riot games的境遇更好。预测型 ' & ' 定量型'也有像样的看点,恰如其分的适合黑客新闻。但是我们应该注意,这些词的频率为 0-6,无论如何都不能被认为代表了它们所来自的 8493 条评论。但是 chatterplot 使这一点完全清楚,而这样的细节几乎被所有的文字云所掩盖。

显然,这只是出于演示目的的 toy ish 数据的一个起点。 chatterplot 框架是灵活的&可以以多种方式扩展。我将把这样的进一步探索留给读者作为练习。

几句临别赠言:

  • 在上面的例子中,我们有二维的冗余表示:字数 & 平均评论排名字数y 轴以及文字大小表示,而排名x 轴 & 颜色渐变表示。显然,我们可以通过交换这些冗余的表示,在这样的图中编码更多的维度,从而获得更高的信息密度。
  • 由于 ggrepel 尽最大努力避免重叠元素,我们失去了一些精度,因为它们被“推到”平面中更开放的空间,所以坐标有些近似。
  • 这是在 R 中完成的,但应该可以移植到大多数绘图库或软件中。

***【编辑:*感谢詹姆斯·斯科特-布朗在推特上指出杰森凯斯勒的类似(但要深得多)散射文本 python 包,快来看看!

概述

imo 的 chatterplot 通过将 ordercoherencequantitative rightness、&、多维信息容量引入众所周知的探索性、直接数据 plot,对 wordcloud 进行了改进。

尝试一下&让我知道你提出的任何反馈、例子或改进!

另外关注我&查看我的其他帖子:)


在推特上关注:@ dnlmcLinkedIn:【linkedin.com/in/dnlmc】T4Github:https://github.com/dnlmc

机器的崛起

原文:https://towardsdatascience.com/rise-of-the-machines-a68a011eb6fc?source=collection_archive---------2-----------------------

Homer Simpson of the 22nd Century?

大多数看情景喜剧的人都不可避免地会遇到《辛普森一家》,这是一个关于美国工人阶级和社会的典型故事。辛普森一家的父亲荷马·辛普森开车去附近的一家发电厂工作,他是那里的一名核安全检查员。他的大部分工作是检查关键的操作参数是否有异常。如果荷马这样的人生在 150 年前,他会做什么工作?如果他 50 年后出生呢?让我们做一些猜测——

1850 年——普通人荷马可能会在煤矿工作。他会走路去上班,挖煤(或者如果他幸运的话,监督那些工作的人),拿现金,大概还会去户外或者玩棋盘游戏取乐。他吃从家里带来的食物,或者食堂工作人员提供的食物。家里的扫帚有助于清洁灰尘。

1925 年——本世纪初,标准的美国工作是工厂工作。现在,他可能有某种交通工具去那里。休闲发展引入了现代游戏,如篮球和棒球。书籍和游乐园也在增加。他仍然通常吃从家里带来的食物,或者食堂工作人员提供的食物,但有时也会吃包装好的食物。强大的扫帚继续统治。

2000 年——今天,荷马开车去上班。他坐在办公室里,观察机器输出的数字。他通过电子方式向自己的银行账户付款,并让电视在家陪伴他。他还有视频游戏和社交媒体等选择。当家里没人做饭时,他就把一包现成的放进微波炉里吃。现在他的房子变大了,他使用真空吸尘器,因为这比找人替他打扫要便宜。

2050 年——荷马驾驶自动驾驶汽车去他的工作场所,在那里,所有的机器都在内部自我照顾。对于娱乐,有无数的设备。有一台机器可以准备任何你想要的食物。这房子是自动清洁的。等等,为什么他又要去工作了?

‘I’m bored.’

尽管纯属假设,但这确实让我们了解了我们的工作进展情况。他从更多劳动密集型工作到更少劳动密集型工作。从采煤到在工厂使用机器,它们正越来越多地渗透到我们的生活中。在我们过去依赖他人的地方,我们不再依赖科技。无论是社交媒体取代邮递员,还是谷歌地图取代我们在路上询问的人,技术似乎正在为我们做大量的工作。但是他们能做我们所有的工作,让我们无事可做吗?

比较优势

几位经济学家说不会——人类永远都有工作要做。他们认为,李嘉图在 19 世纪倡导的比较优势理论适用于所有情况。即使机器在我们做的每件事情上都做得更好,我们仍然有理由做我们最擅长的事情。这本质上就是比较优势——如果 A 国比 B 国生产更多的小麦和钢铁,他们之间的贸易还是有意义的。尽管这似乎有悖常理,但它已被广泛接受,并成为国际贸易的全部基础。经济学家大卫·H·奥特尔说,虽然机器的工作越来越好,但我们所做工作的价值是对它的补充。引用他的话,“通常情况下,这些输入都扮演着重要的角色;也就是说,一个方面的改进并不排除对另一方面的需要。如果是这样,一组任务的生产率提高几乎必然会增加其余任务的经济价值。既然我们只坚持是否所有人类工作都可以被取代的理论问题,我们现在可以忽略社会因素。但我仍然认为,当我们把机器和技术带入画面时,奥托尔的比较优势假设就失效了。

让我们假设一个由两个成员组成的社会——一个人类和一个机器人。假设人类一天能砌 1000 块砖,或者一天能做 20 公斤意大利面(为了便于讨论)。一个机器人可以砌 10000 块砖或者煮 100 公斤意大利面。很明显,机器人有绝对的优势,无论它做什么工作。比较优势理论告诉我们,每个国家进行专业化分工然后进行贸易仍然是有意义的。(如果你不能理解这一点,这里有一个很棒的链接)。但是如果另一个机器人能在短时间内制造出来呢?那么,人类的产出将比两者都少得多,人类再做任何一项任务都没有意义了!显然,机器人(以及总体技术)在短时间内以低成本复制的能力,是我认为比较优势可能不成立的关键。

互补性

随着汽车的出现,出现了加油站工人、机械师、挡风玻璃清洁工等工作。这些是随着汽车的发展而出现的意想不到的工作。它是否重新创造了所有被拿走的工作是一个次要问题;事实是机器不能做所有的工作。奥特尔沿着这些思路论证道:随着技术的进步,将会创造出我们无法想象的工作岗位。这些是进步带来的互补性。他提出了这样一个观点,即当一项活动变得更有成效时,流程中的所有其他活动都具有更大的价值。因此,人类将永远在填补这些空白方面发挥作用。但是,随着技术发展的步伐,它们所需要的互补性也变得更加技术性。机器现在需要更多的机器才能更好地工作。然而,人类仍然需要建造那些‘其他’机器。这一点让我对机器人是否能完全取代我们深感矛盾。每 1000 个无所事事的家庭中,就有 1 个人在制造那辆自动驾驶汽车。然而,人工智能可能会改变这一点。

人工智能的到来

在此之前,让我们退一步考虑什么是智能。你怎么知道什么是笔记本?有些大,有些小。有些是螺旋装订的,有些是精装的。但是当我们看到一个笔记本时,我们只是知道它是一个笔记本。但是想象一下,向一个没有智力的人描述一个笔记本。笔记本有各种各样的形状、大小、封面和颜色。需要智慧才能知道什么是笔记本。这就是波兰尼悖论——我们知道的比我们能说的多。这在传统上被视为计算机无法取代人类的原因。然而,这种情况正在迅速改变。这方面的一些证据

谷歌 DeepMind 开发的程序 AlphaGo 在 2016 年 3 月击败了世界最佳围棋选手 Lee Sedol。围棋是一种抽象的战略棋类游戏,被认为比国际象棋更难,而 wand 则需要很强的直觉和智力。

每次你在谷歌上使用图片搜索,你实际上是在使用谷歌 DeepMind 的技术,今天的错误率为 5.5%。如果这听起来很多,考虑一下这个——人为错误率大致相同。

人工智能的一个标准是图灵测试。英国著名数学家艾伦·图灵(更著名的是*,模仿游戏*就是基于他)提出,如果一台机器能够在一次对话中成功地愚弄人类,让对方相信它是人类,那么这台机器将显示出真正的人工智能。这是 75 年前的事了。有几个系统已经接近甚至击败了它(尽管这是有争议的)。不管怎样,我们已经非常接近了

为什么这日益成为一个大话题?我们每天产生的数据量是巨大的;世界数据每两年翻一番*。据预测,到 2025 年,人类大脑将拥有和人类大脑一样的能力。随着计算能力的进步,机器学习算法可以处理的大量数据是海量的,可以用来建立更好的人工智能。*

Source

用外行人的话来说,凭借我们所拥有的数据量和计算能力,我们可以使用蛮力——向计算机展示一百万张岩石照片,它将能够正确识别接下来的一千张照片——来开发计算机的智能。这意味着波兰尼悖论将被规避。计算机现在将和我们知道的一样多。而且没有任何人类的缺点,比如需要休息、食物或熟悉感——不难想象这些机器人会夺走我们目前做的所有工作。当埃隆·马斯克说我们应该担心人工智能时,我们可能应该保持警惕。

Source: WaitbutWhy.com

总而言之,我们目前所做的所有工作,将来都有可能被机器人接管。这是否一定意味着世界末日即将来临,更多的是一个社会问题——这取决于人类社会适应变化的速度,同时让每个人都参与进来。因为有一件事是清楚的——转变将是困难的。70 年代和 80 年代创造的工作岗位已经被人工智能夺走了。人类文明从未处于如此快速的变化之中。查尔斯·斯特罗斯(Charles Stross)的《土星的孩子》(Saturn's Children)中说,一旦人类社会有机器人做所有的工作,我们就会退缩到“内部快乐”中,对外部世界失去兴趣,最终导致我们的灭绝。希望我们能证明他是错的。

如果你想深入探讨这个话题,这里有一些很棒的链接-

[## 人工智能革命:第 1 部分-等待,但为什么

PDF:我们为这篇文章制作了一个精美的 PDF,用于打印和离线浏览。在这里买。(或者看个预览。)注意:…

waitbutwhy.com](http://waitbutwhy.com/2015/01/artificial-intelligence-revolution-1.html) [## 健谈的经济学家

自动化和机器人技术的貌似合理的进步会导致大规模失业吗?如果…

conversable economist . blogspot . in](http://conversableeconomist.blogspot.in/2015/08/how-automation-affect-labor-markets.html)

无脑机器的崛起

原文:https://towardsdatascience.com/rise-of-the-mindless-machines-c0e578061e65?source=collection_archive---------9-----------------------

当人们讨论人工智能的未来时,一个普遍表达的担忧是对抗性超级智能的出现,这可能意味着我们所知的人类的终结。事实上,我们应该已经考虑好预防措施,以便在人工智能达到人类水平甚至更高时,与它安全共存。

然而,一个更直接的威胁没有得到应有的关注:不是说我们的生活将被超级智能的人工通用智能控制,而是被只会模仿智能的无脑代理人控制,这些代理人执行他们没有充分准备好的任务。

对于一些用例来说,不充分的人工智能可能会令人讨厌,但它的失败通常不会产生严重的影响。例如,我最近给一群流浪猫拍了一张假期快照。云存储服务的图像分类器判定这些动物是狗。

A bunch of “dogs”

在其他情况下,对人工智能不足的担忧更为严重。例如,每个人都希望自动驾驶汽车尽可能安全。所有道路使用者的生活关键取决于控制车辆做出正确决策的算法。

对于上面的示例应用程序,我们很好地理解了问题的机制,以及机器无法做出正确决策的后果。此外,我们可以通过客观的衡量标准(例如,自动驾驶汽车是否能够在路上行驶)或非常直观的标准(例如,那不是一只狗,咄)来评估机器的性能。因此,这些问题非常适合依靠最先进的统计机器学习做出的决策来解决。

H 然而,在一些问题上,我们并没有很好地理解形势的内在机制,也没有明显的有效性标准。最重要的是,如果我们实施不充分的人工智能来大规模地为我们做出这些决定,我们并不容易掌握对人类社会的长期后果。

这种决定的例子有:

在每个例子中,算法可能会引入对某些特征的偏见,这些特征在伦理上是有问题的,例如种族、年龄或性别。可怕的是,这些都是对许多个人的命运和未来有重大影响的决定,我们做出这些决定的方式将塑造整个社会。

一些机器学习专家会告诉你,为了让机器的决策可靠而没有过度的偏见,你只需要调整你的统计模型,在正确的数据上运行它,并可能实施额外的规则来帮助防止歧视性决策:换句话说,这些任务可以由最先进的机器学习来充分执行。

然而,我认为目前的算法甚至无法模拟人类推理的关键特征,这一事实本身就必须让我们在让这些无脑机器做出不仅仅需要数据处理的决定之前非常谨慎。

无脑机器如何无法推理

假设你在远足时被一场雷雨惊到了。你会躲在树下等暴风雨过去吗?你可能不会,因为你知道站在树旁边更容易被闪电击中。你的生命取决于这个信息。

一个基于贝叶斯范式的机器学习算法会同意你的评估:远离树木,因为站在一棵 10 米高的树旁边,被闪电击中的可能性会比不站在树旁边的情况高出 3 倍多。

现在假设你漫步在德国柏林这样的大城市的某个地方。警告你在雷雨时站在树旁的同一算法也将告诉你避开任何有许多外国血统的人居住的地区。毕竟,你遇到的这些人中,有 3 倍的可能性是惯犯

虽然最终取决于你的政治观点,但是这个被无脑机器使用的“推理路线”可能会引起一种不安的感觉。

最后,如果你比普通人多吃 50%的奶酪,你被床单缠住致死的可能性是普通人的 3 倍:

http://tylervigen.com/spurious-correlations

出于这个原因,无脑机器会强烈建议你少吃美味的切达干酪——这当然是个可笑的建议。

上面的例子都只使用了一个解释变量,所以它们必须被认为是坏特征工程的例子。尽管如此,似乎人类的大脑能够捕捉到增加简单概率推理的方面——无脑机器完全忽视的方面。

在下文中,我将确定其中的三个方面:对因果关系的认识,对这些因果关系的良好解释,以及利用前者来实现积极目标的能力。

**因果关系。**统计学的一个众所周知的口头禅是“相关性并不意味着因果关系”。事实证明,虽然有明确定义的相关性统计方法,但众所周知,因果关系很难定义、形式化或量化。

因果推理的一个方面是反事实思维:如果一棵非常高的树被闪电击中,我们相信如果它不那么高,这一事件就不会发生。另一方面,我们确信,如果我们用邪恶博士的闪电枪射击这棵大树,它将不会发生有效收缩的直接后果(除了被烧伤之外)。因此,树被闪电击中是因为它高,而不是相反。

此外,我们无法想象吃大量奶酪会导致床单成为死亡陷阱的世界。

**很好的解释。**我们是如何如此确信这些反事实的陈述的?毕竟,我们还没有进行任何(随机)实验,包括给整天躺在床上的人喂食奶酪。答案是因果关系是通过我们可以很好解释的机制来传达的:树木中的水分使其成为比空气好得多的导体,树木越高,它就越能为闪电提供阻力最小的路径。

好的解释也是我们如此确信这个推理可以被广泛推广的原因:你知道你不想在雷雨时躲在树下。但是你也知道,无论你在地球上的什么地方,你都应该遵守这条规则,它不仅适用于树木,也适用于其他高大的导电结构。

最后,将这些对世界的解释汇集在一起,让我们对吃太多奶酪会对你产生什么影响以及不会产生什么影响有了很好的直觉。

**目标&行动。**一旦人类明白了因果,他们就可以付诸行动:用一根棍子摩擦另一根棍子会产生火,在寒冷的夜晚和冬天,家人会保持温暖。再加上一个好的解释的力量,他们明白热和火可以通过其他方式产生。这些解释越深入、越普遍,人类与环境的互动就越深远,实现目标的工具就越强大。例如,他们认识到热能是一种能量形式,可以转化为驱动机械工具,比如说蒸汽机。

简而言之,人类的推理和决策不仅基于观察到的数据,还基于对我们的行为将如何影响产生数据的环境和过程的预测。这也是任何道德行为的基础。为了有助于改善社会,代理人需要意识到这样一个事实,即她或他的行动可能有助于改变。

C 当前最先进的机器学习实际上执行或至少模拟了理性推理和决策的上述方面?毕竟,因果推理是机器学习中的一个活跃研究课题。然而,因果推断绝不是战壕中数据科学家的标准工具箱的一部分。

当谈到道德时,无脑机器不会表现出任何良心,目前确保算法不会产生不想要的结果的唯一可靠方法可能是良好的老式监管和审计。

最后,所有这些关键的方面都是相互依赖的:如果不观察和把握因果关系,你就无法给出一个好的解释,如果没有这样的理解,你的行动将是徒劳的。但更重要的是,人类思维过程的其他方面也是必不可少的:反事实思维需要想象力,解释需要抽象(如数学建模),通过明智的行动追求目标甚至需要更多。

无脑机器将如何控制

到目前为止,et 的总结是:虽然人工智能仍然缺乏理性、道德和上下文推理的必要和基本方面,但已经有人努力实现该技术来完成各种道德敏感和上下文敏感的任务,如招聘或浪漫的配对。

一般来说,只有当技术足够成熟时,你才会期待它的广泛实现。

然而,一个常见的认知偏见可能会导致在适当的成熟之前被广泛采用:人工智能的拟人化。请注意,虽然当前围绕人工智能的炒作可能会减弱,但拟人化的趋势已经根深蒂固地融入了人类的大脑,因此将会持续下去。

此外,拟人化习惯性地通过营销行话延续下去。例如,DeepDream 为其用户提供“从人工智能的意识中发现惊人的新维度和视觉文物”当输入一幅图像时,软件可能会产生这样的结果:

Cats, dogs, hellspawn?

所以我们被告知的是:机器有意识,它可以做梦。暗示机器“思考”和“感觉”非常像人。即使你没有从表面上理解这种暗示,你仍然会因为经常接触这种语言的使用而受到影响。

现在考虑由计算机产生的这件“艺术品”或“梦”:

Ceci ne pas un mouton électrique

这是部分曼德尔布洛特场景的可视化。虽然美丽、复杂和微妙,但图像生成的过程基本上只涉及复数的重复平方:这是一个非常简单的数学规则,任何具有第一学期数学知识的人都可以完全理解和应用。

没有人会把更高的认知功能归因于如此简单和任意的计算结构。当然,当前最先进的机器学习也不会产生更高的认知功能:

  • 虽然“神经网络”指的是许多复杂的机器学习算法,但它们都与传统的数学工具有着更密切的联系,而不是实际的生物大脑
  • 即使是最大的神经网络(数十亿个权重)的复杂性也远远低于人脑的复杂性(数万亿个神经连接)。

粗略地说,Siri 或 Alexa 将被赋予比 80 年代的袖珍计算器更多的人性,这种想法近乎疯狂。但这是市场行话、公开文章和文章所隐含的想法——包括这篇关于“无脑”机器的文章。

这一发展并非巧合。人们表现出与计算机互动的需求,就像他们与其他人互动一样:几十年的互动设计以相当直接的方式从命令行界面到语音识别和对人形机器人和情感计算的研究。

这意味着人们投入了大量的努力来使机器看起来像人,因此比它们实际上更聪明。因此,对人工智能软件的信任比实际保证的要多。最终,这项技术的采用可能会比合理证明的更快、更广泛。

此外,在我们将无脑机器拟人化的同时,一些人可能会认为世界上的大部分地区已经进入了一个非人化、反科学和反智主义的新时代。如果这些担忧成为现实,前景实际上是相当暗淡的。

我们如何安全使用无脑机器

总之,我们可能不得不应对一个不同的反乌托邦,远早于一个将人类变成一大滩计算机的流氓人工超级智能:一群没有大脑的机器将通过决定谁将找到工作、配偶或朋友,或者谁将获得贷款,或者谁将入狱,来控制数十亿个人的社会地位和福祉。当然,也将控制我们投票给哪个政府,而将决定世界各地战场上的生死

他们会这样做,没有审查或任何后果感,因为他们每个人的认知能力都不如果蝇。他们将无处不在,他们将忙于彼此交流,没有学到任何新的东西,但在许多反馈循环中延续旧的偏见和错误。他们缺乏任何内在动机,无法真正理解或解释他们的环境或行为。一些机器会假装它们不是哲学僵尸,但它们实际上是,而是伪装成你的“老师”、“朋友”、“同事”或“伴侣”。其他机器会对你隐藏起来,我们甚至不知道它们在那里,从无处不在的计算基础设施的一些黑暗的、被遗忘的角落拉你的弦。

我们能做些什么来阻止这样一个暗淡的未来呢?当然,每个人都要尽自己的一份力量,我最后提出一些建议:

  • 在我看来,因果推理和强化学习将是机器学习研究前进的关键概念。理解因果关系和与环境的相互作用是发展人类智能的先决条件。
  • 与此同时,我们不能将智能算法的监管和审计工作留给各大人工智能公司。数据保护法需要在全球范围内实施防止算法偏差的政策。
  • 数据科学家和机器学习工程师需要就构建敏感的人工智能应用程序的道德准则和最佳实践达成一致。

最后,随着人工智能越来越成为日常生活的一部分,该技术的安全、好处和风险需要像道路交通安全一样自然地成为日常政治和公共话语的一部分。

进一步阅读/观看

大卫·多伊奇:我们离创造人工智能还有多远?

大卫·多伊奇:解释的新方法

山姆·哈里斯:我们能在不失去控制的情况下制造人工智能吗?

约翰·塞尔:人工智能中的意识

弗朗西斯科·梅希亚·乌里韦:没有证据就相信在道德上是错误的

更多技术说明

比尔·希巴德:道德人工智能

乔纳斯·彼得斯:因果关系讲座

对消防工作中“风险”的思考

原文:https://towardsdatascience.com/risk-in-the-fire-service-5812cfdbac9e?source=collection_archive---------4-----------------------

The 2017 Las Vagas Shooting produced more than 800 victims in less than 10 minutes

这个比喻

想象一下,你和世界闻名的叔叔丹一起去露营,他是经济学教授,在“风险”方面的专业知识得到了广泛认可。午饭后,你看到丹把手伸进大岩石下寻找响尾蛇。惊恐之余,你坚持丹立即停止他的“野生王国”探险。丹毫不惊慌,平静地解释说,他是“风险”方面的专家,并根据他的“统计历史”得出结论,响尾蛇咬他的可能性几乎为零。你突然意识到经济学中的“风险”肯定不同于现实世界中的“风险”,也许丹叔叔应该呆在安全的大学校园里。

理解“风险”有不同的框架。在股票市场上赔钱的风险和从着火的屋顶上掉下来的风险是不同的。因此,不同的领域有不同的理解风险的方法。偶尔,一个领域借用另一个领域的风险模型,导致有缺陷的思维方式。不幸的是,这正是消防部门所做的,他们采用了经济学中的风险模型,即“经济效用理论(EUT)”

经济学中的风险史

Exposition of a New Theory on The Measurement of Risk

1738 年,丹尼尔·伯努利发表了《关于风险度量的新理论的阐述》,这为度量风险奠定了基础,被称为经济效用理论,或简称为“EUT”伯努利的 EUT 认为,“风险”是概率和后果的产物,是衡量投资的有用工具。EUT 最终成为经济、金融、商业以及消防服务领域风险度量的基础。

美国国家消防协会(NFPA)对“风险”的定义之一是“不利影响的可能性和严重性的度量”这是伯努利的 EUT 的另一种说法。需要澄清的是,我并不是批评 NFPA 对“风险”的定义,而是批评好心的用户对这一特定定义的不当应用。在不考虑不利后果的情况下,NFPA 对风险的定义进入了消防部门的覆盖标准、社区风险降低计划和公共安全卓越中心。

A Screen shot from NFPA’s 2018 Glossary of Terms

尽管 NFPA 对风险的定义在技术上没有错,但如果用在错误的上下文中,它可能会产生误导。由于缺乏 EUT 模型所要求的“概率度量”,消防部门经常用统计数据来代替。这种对概率的历史统计的不正确使用是常见的和欺骗性的,经常导致图表通过基于出现频率的分数将两个对立的概念联系在一起。

Screen shot for Sacramento Fire Departments 2017 Standards of Coverage Report

概率出现频率的换位使用有很大缺陷。例如,仅仅因为某人在六面骰子上掷出十次“一”,并不意味着掷出额外一个“一”的概率增加了。掷出“1”的概率仍然是六分之一或 16%,即使最近掷出“1”的频率非常高。

统计历史和概率之间的巨大差异是 EUT 从未被用于消防服务等领域的原因。用统计学代替概率会导致危险的结论。更糟糕的是,概率测量在消防服务中是不可计算的。

赌场是我所知道的唯一一个概率是已知的、高斯的(即,钟形曲线),并且几乎是可计算的人类冒险。

——纳西姆·塔勒布,被随机性愚弄

为什么消防服务中没有“概率”

概率是一个等式;基于 随机不相关 事件产生一个介于 0 和 1 之间的数的计算。例如,使用“先验概率”,在一轮俄罗斯轮盘赌中幸存的概率是 6 分之 5 或 83%。为了计算概率,我们将有利结果的数量除以可能结果的总数。在俄罗斯轮盘赌的例子中,我们用空室的数量 5 除以空室的总数 6。换句话说,要诚实地计算概率,你需要知道所有 可能的 结果

Probability (PA) is equal to the number of favorable outcomes divided by the total possible outcomes

现在挑剔的读者可能会立即看到问题;如何才能知道现实世界中所有 可能的 结果?批判思想家突然认同纳西姆·塔勒布、爱德华·索普、巴西尔·帕斯卡(概率的创始人)等学者和数学家;他们都认为概率只在游戏中起作用。

因此,如果消防部门使用 EUT,我们如何在不知道所有可能结果的情况下计算概率呢?如前所述,消防部门经常混淆概率和统计趋势,或者说是错误的假设,即一个人的历史是一个人未来的预测。这类似于假设既然一条蛇从未咬过你,那么你未来的“概率”很低。幸运的是,美国国土安全部(DHS)已经着手解决这个问题,并为理解风险提供了一个替代框架。

联邦政府对风险的了解。

“我们必须在所有国土安全工作中应用基于风险的框架。”
——国土安全部——风险指导社区,2008 年

衡量风险的方法有很多。使用不合适的风险模型可能比什么都不做更糟糕;制造虚假的安全感,让社区面临更多风险。联邦政府在 911 之后吸取了这个教训。所有基于历史事件的风险客观衡量标准都对 2001 年 9 月 11 日的事件视而不见。自那以后,DHS 采用了一种主观风险框架,定义为“根据威胁、脆弱性和后果评估的负面结果”,简称“TVC”

Risk model from Center from Homeland Security and Defense

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

TVC 等主观风险框架是一种混乱的做法。与 EUT 不同,TVC 没有一个清晰、客观的数据。相反,TVC 用的客观性换取了的灵活性。TVC 更像是一个组织思想的框架,而不是产生数字计算,它允许用户利用直觉和新信息。借用统计学家乔治·博克斯的话来说,TVC 是错误的,但却非常有用。

没有证据并不是不存在的证据。

"最大的失败是想象力的失败。"-911 委员会报告

TVC 防止我们陷入“缺少证据就是缺少证据”的谬论或者说,只是因为我们以前没有见过它,并不意味着它不存在。“911 委员会”称这是“想象力的失败”。“想象力的失败”在阿波罗 1 号事故、珍珠港事件和泰坦尼克号沉没中被提及。因此,联邦政府大多放弃了 EUT 等定量风险指标,转而采用 TVC 等主观框架。

想象力的丧失

就像 DHS 一样,消防部门面临着不寻常事件的可能性,这些事件源于复杂系统的相互作用,如天气、人类行为和相互交织的基础设施;想想圣布鲁诺管道破裂或者 FIU 大桥坍塌或者。相互关联的复杂系统,如城市,固有地具有发生新的灾难性事件的可能性。复杂系统产生的事件的新颖性需要一个允许想象的风险框架。需要说明的是,不一定是对所有可能发生的事件的想象,而是对**可能发生的事件的描述;**比如时速 100 英里的大风引发的野火,火灾后的泥石流,或者在音乐会上有人向 22,000 名观众开枪。

Driven by heavy winds through topography that burned 40 years ago, the Tubb’s fire was very plausible with an incalculable probability

衡量风险是一件棘手的事情,包含了大量的模型和框架。选择错误的模型或框架会导致错误的安全感。这为我们面临的实际风险创造了一个“盲点”。由于对概率的依赖,风险的客观度量如 EUT 在“真实生活”环境中是失败的。接受消防服务中不存在“概率”的事实将符合我们社区的最大利益。我们需要采用更灵活的框架,比如 TVC。继续使用需要数字变量的客观模型只是在科学的幌子下对自己撒谎的一种精心设计的方式,可能会因为错过独特的事件而将我们的社区置于更高的风险之中。

“当风险最大的时候,安全感也达到了顶点”——纳西姆·塔勒布,《黑天鹅:极不可能事件的影响》

Photo by Timothy Meinberg on Unsplash

人工智能解决方案

原文:https://towardsdatascience.com/risks-of-ai-solutionism-dangers-of-machine-learning-and-artificial-intelligence-in-politics-and-government-728b7577a243?source=collection_archive---------2-----------------------

机器学习对人类的未来有着巨大的潜力——但它不会解决我们所有的问题

尽管媒体标题暗示我们已经生活在一个人工智能已经渗透到社会各个方面的未来,但这实际上对人工智能真正能为人类做什么设定了不切实际的期望。世界各国政府都在竞相承诺支持人工智能倡议,但他们往往低估了在现实世界中部署先进的机器学习系统的复杂性。这篇文章反思了“人工智能解决方案主义”的风险:越来越流行的观点认为,只要有足够的数据,机器学习算法就可以解决人类的所有问题。没有万能的人工智能解决方案。所有的解决方案都是有成本的,并不是所有可以自动化的都应该有成本。

关于人工智能(AI)未来的预言无处不在。关于人工智能如何治愈疾病加速人类创新提高人类创造力的耸人听闻的新闻并不缺乏。单从标题来看,你可能会认为我们已经生活在一个人工智能已经渗透到社会各个方面的未来。

不可否认的是,人工智能已经开启了大量充满希望的机会,它也导致了一种心态的出现,这种心态可以被最好地描述为“人工智能解决方案主义”。这就是 en vogue 哲学,给定足够的数据,机器学习算法可以解决人类所有的问题

但是这个想法有一个很大的问题。它没有支持人工智能的进步,而是通过忽视重要的人工智能安全原则和对人工智能真正能为人类做什么设定不切实际的期望,实际上危害了机器智能的价值。

人工智能梦想和妄想

仅仅几年时间,人工智能解决方案主义就从硅谷的技术传道者传播到了世界各地的政府官员和政策制定者。钟摆已经从反乌托邦观念人工智能将毁灭人类转向新发现的乌托邦信念,即我们的算法救世主已经到来。

在世界各地,我们现在看到各国政府承诺支持国家人工智能倡议,并在技术和言论上展开军备竞赛,以主导蓬勃发展的机器学习领域。例如,英国政府誓言投资 3 亿英镑在人工智能研究上,将自己定位为该领域的领导者。着迷于人工智能的变革潜力,法国总统埃马纽埃尔·马克龙已经承诺将法国变成一个全球人工智能中心。与此同时,中国政府正在增加其人工智能实力,制定了一项国家计划,到 2030 年创造价值 1500 亿美元的中国人工智能产业。

正如预言科幻作家威廉·吉布森曾经写道的,“未来已经在这里了——只是分布得不太均匀。“因此,许多国家都希望主导第四次工业革命。人工智能解决方案主义正在兴起,并将继续存在。

“当谈到机器学习时,政府应该停下来深呼吸一下。仅仅为了人工智能而使用人工智能可能并不总是有成效或有用的。”

虚假承诺或有缺陷的前提?

虽然许多政治宣言吹捧即将到来的“人工智能革命”的积极变革效应,但他们往往低估了在现实世界中部署先进机器学习系统的复杂性。自然,人工智能的能力是有限的,这些限制与机器学习技术的实际工作方式有关。为了理解这些错误观念背后的原因,让我们来看看基础知识。

最有前途的人工智能技术之一是神经网络。这种形式的机器学习是松散地模仿人脑的神经元结构,但规模要小得多。许多基于人工智能的产品使用神经网络从大量数据中推断模式和规则。但许多政治家不明白的是,简单地将神经网络添加到问题中并不意味着你会自动找到解决方案。

“简单地给民主添加一个神经网络,并不意味着它会立刻变得更加包容、公平或个性化。”

如果政策制定者开始在左右和中间部署神经网络,他们不应该假设人工智能会立即使我们的政府机构更加敏捷或高效。简单地给民主添加一个神经网络,并不意味着它会立刻变得更加包容、公平或个性化。

通过类比,考虑将一个实体购物中心转变为一家公司,比如亚马逊。仅仅增加一个脸书页面或推出一个网站不足以让实体购物中心成为一家真正的数字技术公司。需要更多的东西。

挑战数据官僚主义

人工智能系统需要大量数据才能运行。但是公共部门通常没有合适的数据基础设施来支持高级机器学习。其大部分数据仍然存储在离线档案中。现存的为数不多的数字化数据来源往往被官僚机构所掩盖。通常情况下,数据分散在不同的政府部门,每个部门都需要特殊许可才能访问。最重要的是,公共部门通常缺乏具备适当技术能力的人才来获得机器智能的全部好处。

此外,部署机器学习系统的许多困难之一是,AI 极易受到对抗性攻击。这意味着恶意的 AI 可以针对另一个 AI,迫使它做出错误的预测或以某种方式行事。许多研究人员警告不要在没有适当的安全标准和防御机制的情况下推出人工智能。然而,令人震惊的是,在政策制定者的政治言论中,人工智能安全仍然是一个经常被忽视的话题。

由于这些原因,媒体对艾的炒作吸引了许多批评。伯克利大学计算机科学教授斯图尔特·拉塞尔(Stuart Russell)长期以来一直倡导对神经网络采取更现实的方法,专注于人工智能的简单日常应用,而不是假设的超级智能人工智能接管机器人。

同样,麻省理工学院的机器人学教授罗德尼·布鲁克斯写道“几乎所有机器人和人工智能的创新都需要比领域内外的人想象的更长、更长的时间才能真正广泛部署”。真正的进步是痛苦而缓慢的。而在 AI 的情况下,需要大量的数据。

制造机器,而不是魔法

如果我们要获得人工智能的好处,并最大限度地减少其潜在危害,我们必须开始思考如何将机器学习有意义地应用于政府、企业和社会的特定领域。这意味着我们需要就人工智能伦理和许多人仍然对机器学习的不信任进行长期的多方利益相关者讨论。

最重要的是,我们需要意识到人工智能的局限性,以及人类仍然需要领先的领域。我们不应该描绘人工智能机器人所提供的超能力的不切实际的画面,而是应该后退一步,将人工智能的实际技术能力与魔法分开。机器学习既不是神奇的仙尘,也不是解决一切的方法。

就连脸书最近也承认,人工智能并不总是答案。很长一段时间,社交网络相信错误信息和仇恨言论的传播等问题可以通过算法识别和阻止。但在最近来自立法者的压力下,该公司迅速承诺用一支超过 10,000 人的审查队伍取代其算法。

医学界也认识到人工智能不能作为解决所有问题的灵丹妙药。IBM 肿瘤学沃森项目是人工智能的一部分,旨在帮助医生治疗癌症。即使它被开发来提供最好的算法建议,人类专家发现很难信任机器。结果,尽管在技术上进行了大量投资,人工智能程序在大多数医院被放弃

类似的问题也出现在法律领域,当算法被用于美国法院对罪犯进行判决时。一种不透明的算法被用来计算风险评估分数,并确定某人再次犯罪的可能性。人工智能旨在帮助法官在法庭上做出更多以数据为中心的决定。然而,该系统被发现放大了结构性的种族歧视,导致法律专业人士和公众的强烈反对。

人工智能仪器的法律

这些例子表明没有万能的人工智能解决方案。仅仅为了人工智能而使用人工智能可能并不总是高效或有用的。并不是每个问题都可以通过应用机器智能得到最好的解决。

在 1964 年出版的一篇近乎预言性的论文中,美国哲学家亚伯拉罕·卡普兰(Abraham Kaplan)将这种趋势描述为“工具法则”。

它被表述为:“给一个小男孩一把锤子,他会发现他遇到的一切都需要敲打”。只是这一次,卡普兰小男孩的心态被有影响力的世界领袖所分享,而 AI 锤子不仅非常强大,而且非常昂贵。

因此,这对于所有旨在加大对昂贵的人工智能投资和国家人工智能项目的投资的人来说都是至关重要的一课:所有解决方案都有成本,并非所有可以自动化的东西都应该有成本。

我们不能坐以待毙,直到我们在遥远的未来达到一般水平的感知人工智能。也不能靠狭隘的 AI 来为我们解决今天所有的问题。我们今天需要自己解决这些问题,同时积极塑造新的人工智能系统来帮助我们完成这项艰巨的任务。

关于作者: 维亚切斯拉夫·波隆斯基 博士是牛津大学的研究员,研究复杂的社会网络和集体行为。他拥有计算社会科学博士学位,之前曾就读于哈佛大学、牛津大学和伦敦政治经济学院。他积极参与了 世界经济论坛 专家网 WEF 全球塑造者 社区,在那里他担任了 牛津中心 的馆长。2018 年,《福布斯》杂志在欧洲的 《福布斯》30 岁以下 30 人 榜单上专题报道了他的工作和研究。他写的是社会学、网络科学和技术的交集。

本文的早期版本出现在大众影响中心大思考世界经济论坛议程 **

非常感谢 2017 年关于机器学习的 迪奇利会议 给了我一个独特的机会来完善我的想法,并获得该领域领先的人工智能研究人员、政策制定者和企业家的早期反馈。

RNN 训练技巧和诀窍:

原文:https://towardsdatascience.com/rnn-training-tips-and-tricks-2bf687e67527?source=collection_archive---------0-----------------------

以下是安德烈·卡帕西关于训练 RNN 管道的一些好建议。链接到最初来自的

监控验证损失与培训损失

如果你对机器学习或神经网络有些陌生,获得好的模型可能需要一点专业知识。要跟踪的最重要的量是训练损失(在训练期间打印)和验证损失(对验证数据运行 RNN 时偶尔打印一次,默认情况下每 1000 次迭代打印一次)之间的差异。特别是:

  • 如果你的训练损失远低于验证损失,那么这意味着网络可能过度拟合。解决这个问题的方法是缩小你的网络规模,或者增加辍学率。例如,您可以尝试 0.5 的辍学,等等。
  • 如果你的训练/验证损失大致相等,那么你的模型不符合。增加模型的大小(层数或每层神经元的原始数量)

参数的大概数量

控制模型的两个最重要的参数是lstm_sizenum_layers。我建议你总是使用 2/3 的num_layerslstm_size可以根据您拥有的数据量进行调整。这里要跟踪的两个重要量是:

  • 模型中的参数数量。这是你开始训练时打印出来的。
  • 数据集的大小。1MB 的文件大约有一百万个字符。

这两个应该差不多一个数量级。有点难以分辨。以下是一些例子:

  • 我有一个 100MB 的数据集,我使用默认的参数设置(目前打印 150K 的参数)。我的数据量要大得多(100 密耳> > 0.15 密耳),所以我预计会严重不足。我在想,我有足够的钱让lstm_size变得更大。
  • 我有一个 10MB 的数据集,正在运行一个 1000 万参数的模型。我有点紧张,我在小心地监控我的确认损失。如果它比我的训练损失大,那么我可能会尝试增加一点点辍学,看看这是否有助于验证损失。

最佳模式战略

获得非常好的模型的获胜策略(如果你有计算时间)是总是错误地将网络变大(大到你愿意等待它计算),然后尝试不同的压差值(在 0,1 之间)。无论哪种模型具有最好的验证性能(写在检查点文件名中的损失,低是好的),都是您最终应该使用的模型。

在深度学习中,使用许多不同的超参数设置运行许多不同的模型是非常常见的,最终采用任何给出最佳验证性能的检查点。

顺便说一下,你的训练和验证分割的大小也是参数。请确保您的验证集中有足够的数据,否则验证性能将会很嘈杂,并且不能提供很多信息。

使用深度学习的道路场景理解

原文:https://towardsdatascience.com/road-scene-understating-using-deep-learning-c3610f6b1c4?source=collection_archive---------2-----------------------

The final outcome of applying semantic segmentation on road scene

场景理解

语义分割代表了深度学习中的一种技术,其中我们通过将图像中的每个像素分配给预定义的类别集来为其分配意义。从上面的 GIF 中,我们可以看到我们在语义分割过程中有两个类( roadnot road )被相应地着色。

使用语义分割的方法,我们能够将场景分解成我们特别感兴趣的片段。这对于自动驾驶汽车尤其重要,因为它将能够检测场景的哪个部分是可驾驶区域。

这是如何工作的?

语义分割的一种方法是使用全卷积网络(FCN)。加州大学伯克利分校有一篇很棒的论文,详细解释了方法论和架构。我们的实现也将基于本文。

典型的卷积网络由几个卷积层和完全连接的层组成。这种类型的架构适用于分类问题(例如:这是一条路吗?)。但是为了在一幅图像上定位道路(*道路在哪里?*问题)我们需要网络能够保存空间信息。这就是 FCN 发挥作用并提供最先进的语义分割结果的地方。

如何建设 FCN?

建造 FCN 有三种主要技术:

  1. 用 1x1 卷积层替换全连接层。
  2. 通过使用转置卷积层引入上采样。
  3. 添加跳过连接。

下面我们来详细看看如何做到这一点。

我们的 FCN 架构有两部分:编码器解码器

FCN architecture

对于编码器,我们将使用在 ImageNet 上预先训练的 VGG16 模型。VGG16 模型中完全连接的层将替换为卷积 (1) 。编码器从图像中提取将被解码器使用的特征。

下一步是构建解码器,这是通过使用转置卷积层 (2) 对最后一个编码器层进行上采样来完成的。转置卷积本质上是一种逆卷积。

FCN architecture based on pre-trained model, replaced fully connected layers and transposed convolutions

最后,我们将在特定层之间添加跳过层 (3) ,使网络能够使用多种分辨率。这反过来提供了更好的分割结果。跳过连接可以减少信息丢失,使网络能够“看到全局”,因为典型的卷积网络只关注图像的一部分。

Skip connections in FCN

我们在添加跳过连接时应该小心,因为它们会极大地影响模型的大小。

最后结局

用于道路场景理解的 FCN 的实施是作为 Udacity 自动驾驶纳米学位项目的一部分完成的。我已经使用 Python 和 TensorFlow 建立和训练了模型。该模型已经在 NVIDIA 1080Ti 显卡上进行了 30 次训练,耗时不到半小时。

这是推理的输出:

结论

相关的源代码可以在我的 GitHub 个人资料中找到:

[## bdjukic/CarND-语义分段

通过在 GitHub 上创建一个帐户,为 CarND-Semantic-Segmentation 开发做出贡献。

github.com](https://github.com/bdjukic/CarND-Semantic-Segmentation)

革命之路:社会主义 vs 共产主义

原文:https://towardsdatascience.com/road-to-revolution-socialism-vs-communism-8b150c1aa54c?source=collection_archive---------3-----------------------

通过 PushShift API 和自然语言处理进行子编辑分类

我一直认为,在一个社会经济不平等继续困扰社会并阻碍人类真正进步的时代,社会主义和共产主义背后的意识形态非常引人注目。虽然没有一个政治/经济体系是完美的,但我们必须承认资本主义的缺点及其在助长这种不平等中的作用。

在马克思主义理论中,社会主义是继资本主义之后社会向共产主义过渡的阶段。它们都建立在集体合作的理念上,但不同之处在于共产主义者认为合作应该由一个政党组成的政府来管理。无论你同意其中一个,另一个,两个,还是都不同意,我们都可以从这些理论中学到很多关于创造一个更加公正和平等的社会的东西。

由于两者之间的微妙差异,社会主义和共产主义将成为探索自然语言处理能力的伟大范例。为了做到这一点,我进行了一项实验,利用了子编辑r/共产主义r/社会主义的文本。使用以下步骤,我可以将这些帖子转换成语料库,用于训练随机森林或其他类型的分类算法:

  1. 查询 PushShift API 以检索提交
  2. 清理和预处理文本
  3. 分析矢量化/标记化的文本
  4. 网格搜索跨两种分类算法优化超参数

步骤 1:查询 PushShift API

我没有直接从 Reddit(限制最多 1000 个查询)获取提交内容,而是利用了 PushShift API,该 API 创建了大多数子编辑的历史档案。通过这个 API,我能够获取提交的标题、文本、作者和日期。

步骤 2:清理和预处理文本

在从两个子编辑中读入合并的文件后,我做了一些清理和预处理:即删除特殊字符,转换成小写,并对结果单词进行词汇化。

此外,我删除了已删除/已删除帖子或版主自动帖子的所有标签(这些标签特定于子编辑,可能会影响训练集):

步骤 3:分析矢量化/标记化的文本

为了进一步完善我的文本分析,我需要对词汇化的文本字段进行标记,并确定每个集合中哪些单词最罕见和最频繁。我首先想要移除(通过停用词)组合数据帧中最频繁出现的词,这些词在分类算法中是低预测特征。

步骤 4:网格搜索优化超参数

最后,我想比较两种不同分类算法的准确性:逻辑回归和随机森林。这两个都是强大的工具,但我发现逻辑回归是更可靠的预测器,尤其是考虑到 75K+标记化的特征。

虽然随机森林为训练数据生成了可比较的准确性分数,但我想通过比较 ROC / AUC 分数来比较模型,以了解在平均阈值范围内哪个更可靠:

征服计算机视觉的路线图

原文:https://towardsdatascience.com/roadmap-for-conquering-computer-vision-213695472ad0?source=collection_archive---------8-----------------------

计算机视觉如何入门

写博客给 ace 机器学习提供指导已经成为一种传统。我很难找到任何这样的计算机视觉路线图和任务清单。作为一名视觉爱好者和顾问,我发现很多人询问掌握计算机视觉的具体路线图(在技能、课程等方面)。下面的博客试图达到这个目的。

应该注意的是,这将是一个长期的、以努力为导向的路线图。我个人不鼓励人们在学习一个硬核领域的时候走捷径。我相信,按照上面提到的路线图,你会在正确理解事物的基础上,在正确的轨道上完成大量严谨的愿景工作。够兴奋了吧?没关系!

什么是计算机视觉?

计算机视觉是人工智能的一个子领域,旨在使机器足够智能以理解图像。由于机器学习(和深度学习)是当今世界上最活跃的人工智能子集之一,在机器学习框架中处理计算机视觉将是合适和明智的。为了理解我将要提出的路线图的全部本质,考虑一个通用的机器学习过程是很重要的。

注意:下面的部分有点技术性。只想开始使用路线图的人应该跳过这一步,阅读食谱部分

机器学习是如何工作的?

每个机器学习系统都可以分解为以下两个子系统:

  1. 从原始数据(图像、音频、文本等)中提取特征
  2. 在特征空间上拟合学习算法

学习算法本质上需要 n 维特征空间来绘制决策边界(在分类范例中)或拟合超平面(就线性回归而言)。为了将原始数据转换到特征空间,我们通常需要两件重要的事情:

a.领域/业务知识

b.数据处理知识

领域知识告诉我们在我们的商业决策中研究数据的重要因素(考虑一个医生告诉你在 MRI 中寻找一个来检测肿瘤)。然后,数据处理知识将这些因素(来自领域知识)编码到来自数据处理知识的特征空间(考虑使用图像处理从 MRI 检测圆)。

数据处理对于从原始数据中提取重要特征至关重要。如果原始数据是图像的形式,图像处理就是我们需要的数据处理知识。如果数据是文本的,我们需要有语言学和文本挖掘知识来提取特征。每种类型的数据都有相应的处理知识。

深度学习有多不一样?

深度学习是机器学习的一个子集,有其技术根源。在不深入研究深度学习背后的技术细节的情况下,应该理解的是,深度学习使我们能够摆脱特征提取步骤。我们只是有一个学习算法来做所有的事情。这些深度学习算法可以直接在原始数据空间上工作。现在所有的人工智能炒作都是因为深度学习。

配方是什么?

由于我们有两种不同的学习范式,我们可以以两种不同的形式学习和应用计算机视觉。由传统机器学习算法支持的计算机视觉被称为经典计算机视觉。如果计算机视觉是基于深度学习的,则称为现代计算机视觉。

经典计算机视觉路线图

与任何机器学习系统一样,经典计算机视觉也由两个主要子系统组成:

  1. 图像处理:将数据编码到合理的特征空间(与特征提取相同)
  2. 学习算法:适应该空间中的任何相关模型

所以伙计们,掌握计算机视觉与理解上述两件事有着重要的关系。我列出了一些图像处理和计算机视觉的课程来开始学习:

  1. 关于计算机视觉介绍的 Udacity 课程
  2. YouTube 上的穆巴拉克·沙阿博士课程
  3. 一门纯机器学习的课程对我们的第二步也很重要。你可以选修任何现有的课程。比如吴恩达在 T4 Coursera 上的课程或者南多在 YouTube 上的课程
  4. 还需要掌握 OpenCV 等一些开源工具,以便快速实验和学习。你可以看看一些很酷的 PyImageSearchLearnOpenCV 博客

现代计算机视觉路线图

现代计算机视觉系统基本上建立在深度学习的基础上。它给了我们灵活性,我们可以在没有经典图像处理知识的情况下完成许多视觉任务。要采用这种方法,请尝试以下课程:

  1. 斯坦福的 Cs231n (用于视觉对象识别的卷积网络)
  2. 安德鲁关于卷积神经网络的课程
  3. 一般深度学习课程,查这个专精

我强烈建议读者在深入研究现代计算机视觉之前,至少对经典计算机视觉有所了解。这对以后很有帮助。

结论

列出的大纲将使你们能够开始计算机视觉的不断学习之旅。肯定是很费时间的。这肯定需要很多努力,但这是最基本的要求。我希望每个人都意识到为什么她/他要应用某些算法。该路线图还将帮助您设计和构建针对新问题的定制解决方案。

我花了半个博客来描述一个通用的机器学习过程。你可以把相同的路线图推广到人工智能的其他子领域,包括自然语言处理、语音识别等。

机器人也错了——最坏情况下的混乱映射

原文:https://towardsdatascience.com/robots-are-wrong-too-confusion-mapping-for-the-worst-case-2e01b7e19936?source=collection_archive---------5-----------------------

这里有龙

Photo by Seth Doyle on Unsplash

上一次计算器不按你的意愿工作是什么时候?一个人最后一次这样做是什么时候?从确定性的角度来看,像机器学习这样的算法介于这两者之间。

今天,我们正在制造比我们所能理解的更复杂的机器,我们需要用不同于以往技术的方式来处理它们。它不再是指定我们想要做什么,然后调试它。

Philosophie 我们一直在构建新的工具和练习,如机器移情映射,为人工智能和机器学习项目带来人类目的。最新的是我们称之为混淆映射,它帮助你更好地为所有可能的非确定性系统失败做准备。

混乱矩阵速成班

正如我们从设计思维中窃取了移情映射一样,我们也从数据科学中窃取了混淆矩阵用于混淆映射。混淆矩阵是分类算法(包括机器学习)的性能可视化。当深入研究系统如何运行时,您需要了解的不仅仅是错误率和准确率。你需要知道它是如何失败的。

这里有一个例子:

It is always about cats, isn’t it?

一般来说,横轴是实际发生的事情,纵轴是在理想世界中预期会发生的事情。有四个象限需要考虑:

  • True positive —系统认为它应该是真的,并且它是真的
  • True negative —系统认为它应该是假的,但它确实是假的
  • 假阳性(又名“假警报”或倾向于这些统计的 I 型错误)—系统认为它应该是真的,但它是假的
  • 假阴性(又名“遗漏”或第二类错误)—系统认为它应该是假的,而它是真的

混淆矩阵最传统的用法是用于分类问题。例如,如果你想把一张图片归类为一只狗或一只猫,你会在混淆矩阵中考虑两个不同的类别。认为一张猫的照片是一只狗将会是一个错误的结果。在这种情况下,有 18 种情况下狗被错误地归类为猫:

Example of confusion matrix plot for a dogs and cats classifier from the fast.ai course.

对于每个象限,我们考虑正确(或不正确)分类发生的次数。当考虑特定结果与其频率相比的影响程度时,这可能非常有帮助。

通常当它用图表示时,你会看到一条从左上到右下的对角线,在那里你有每一类或预测的真阳性和真阴性。

有些情况下,您可以有许多分类。在 ImageNet 的情况下,有许多许多可能的分类。关于狗,仅狗的种类就有 120 种。

They can be huge!

困惑矩阵是关于结果的…

建立解决人们问题的服务的第一步是关注结果而不是解决方案。混淆矩阵通过计算分类器做它应该做的事情的次数来做到这一点。

你需要知道当机器做它应该做的事情时,以及当它正确地不做任何事情时,期望的结果是什么。

当创建混淆矩阵时,他们对原始分类最感兴趣。我们需要更进一步,思考我们的机器按照我们期望的方式工作会有什么样的结果或可能的影响。

让我们以自动驾驶汽车的前方物体检测系统为例。它需要识别车辆前方何时有人或物,以便采取正确的行动,例如紧急刹车或急转弯以避免碰撞。当没有检测到任何东西时,它不应该干扰车辆的其他计划和执行。

对于我们为现场服务运营 (FSO)所做的一个项目,有一个界面会根据预测算法推荐是否将现场技术人员分配到某项工作。我们要么希望系统指派某人以便他们可以去工作,要么在指派之前要求某人获得更多信息。

A field service operations job detail for a dispatcher with automatically recommended technicians, parts, schedule, etc.

要采取的干预措施是这个例子中最重要的部分。根据所识别的事物的类型,它可能想要采取不同的动作。

…以及应用程序将如何出错

当我们构建这些类型的智能算法时,它们会出错。原因是我们不会尝试每一种可能的情况组合,只是那些我们认为会发生的情况。如果我们不这样做,将会花费很长时间来建立和训练这些类型的系统。

Watch out for that bicyclist!

对于我们一直在谈论的自主车辆障碍物检测系统,当它认为汽车前方有障碍物而实际上没有障碍物时,就会产生误报。错误的否定是认为车前有东西,而实际上有。这两种情况之间有明显的区别,因为一种是导致不恰当地猛踩刹车(假阳性),另一种是像人一样撞到障碍物(假阴性)。

假阴性并不总是比假阳性更糟糕。以诊断癌症的算法为例:假阳性可能引发一系列不必要的手术干预,从而导致进一步的问题。从假阴性和假阳性的角度来理解尽可能多的影响是很重要的。

对于 FSO 理工学院的推荐,误报是在工作准备好分配之前分配现场技术人员。如果现场技术人员不合格、没有合适的零件或者只是不知道该做什么,这可能需要返回(对于预测算法来说,这是一种“感觉糟糕”的情况)。在这种情况下,错误的否定是让作业在队列中等待,并在分配之前要求更多的澄清。这可能导致现场技术的利用率下降,并减少计费时间量(对于算法来说,这两种情况都是“糟糕的”)。

作为灵感的死亡前

混淆矩阵显示了特定的分类算法是如何特别失败的。预死亡是一种帮助我们理解我们的项目和团队将如何失败的技术。他们在复杂的团队结构中特别有用。

预死亡的好处在于,它允许每个人戴上他们的黑帽子,在最坏的情况下发挥真正的创造力。群众的智慧在决定什么是项目中最有可能自己造成的问题方面非常有用。

作为一种方法的前概念和作为一种概念的混淆矩阵是我们在 Philosophie 创建的混淆映射练习的灵感来源。

混淆映射方法

当你专注于一个问题和一个可能的解决方案时,这个练习是最合适的。在我们举办的一个研讨会上,在做这个练习之前,我们做了挑战映射(用一个很好的‘我们如何能……’)、疯狂的 8 个想法机器的移情映射

在这个练习中最关键的是不要担心病例的发生频率。你专注于收集尽可能多的问题。

你应该和一群跨学科的人(例如,数据科学家、工程师、设计师、产品经理、高管等)一起计划大约一个小时。)来完成这些类型:

  1. 用“积极”表示你希望实现的功能,用“消极”表示没有实现的功能。
  2. 对于四个象限中的每一个,privately ideate on post 都指出了如果发生这种情况会对人们或其他系统产生什么影响。花 3 分钟时间构思每个象限,并在每个象限的生成步骤后立即分享…
  3. 你们一起把每个单独构思的项目放在黑板上,如果不明白就澄清,并删除任何共同的项目。在这一点上尽量避免过多的讨论。为此,每个象限大约需要 2 分钟。
  4. 现在点选真实正象限和真实负象限中最重要的项目。按照票数从多到少的顺序把他们排在一边。
  5. 接下来点票假阳性和假阴性象限中最差的项目。Stack 将他们按照从差到差的顺序排在一边。

Photo from our NYC Media Lab Design Thinking for AI workshop.

在这个过程之后,你应该有一个堆叠排列的结果列表,当事情成功或失败时,这些结果是最重要的。锻炼的最重要的方面是团队内部对可能出错的地方的一致和共同理解。

少一些困惑

在 Philosophie,我们在从问题到计划的过程中使用这些类型的练习,我想你会发现它们是有益的。

既然你们在团队中已经达成共识,那么有几件事情需要考虑:

  • 采用具有更确定性模块的系统方法来调整或指导输出,以避免这些情况。
  • 将模型分解成多个具有不同的单一误差指标的模型,作为一个整体,以降低这些误差发生的可能性。
  • 开始着眼于评估不同结果的频率。

理解这些系统是如何出错的,是与使用它们的人建立信任的第一步。不使用不受信任的解决方案。

会推理的机器人

原文:https://towardsdatascience.com/robots-that-reason-b33c9851dfa9?source=collection_archive---------19-----------------------

基于模型强化学习的无机知识传统

这篇文章探索了无机知识传统的概念,它能够使用基于模型的强化学习进行连续改进

许多行为经济学家目前认为,人类进行战略决策时主要使用两种方法。一种是快速、直觉和无意识的——被称为系统 1 思维。另一种是缓慢的、有逻辑的、循序渐进的,需要努力思考,被称为系统 2 思维。

越来越多的证据现在支持 DeepMind 等人推广的无模型强化学习的说法。所有这些在功能上都与来自卡尼曼和特沃斯基的双重过程理论的系统 1 思维相对应。在我看来,这一发展没有得到应有的重视。考虑到系统 1 思维可能是迄今为止几乎所有高级动物认知形式的基础。各种各样的 RL 算法现在可以在功能上复制系统 1 的思维,这很可能会导致机器人控制机制的复兴,至少如此。如果有人能像训练狗一样训练一个家庭机器人,那他能训练它做什么呢?可能是一些非常漂亮的东西,各种各样奇怪的东西,嘿,老实说,一些彻头彻尾的邪恶的东西!毕竟是人类在进行训练,而不是天使。

然而,这种前景忽略了强化学习领域一个更重要的发展,即可以在功能上复制双重过程理论中的系统 2 思维的算法——人类特别擅长的基于缓慢深思熟虑的模型的推理。不希望把它说得太细,系统 2 算法的全面开花可能会使一些关于奇点临近的更大胆的说法显得不太牵强。也就是说,本文的目的不是要说服奇点的怀疑论者,而是指出基于模型的强化学习的一些最新发展,并探索它们的含义。

关于直觉系统 1 的决策,当我们经历时,那些经历会改变我们未来的决策。直到最近,这种随时间改变和适应直觉决定的能力一直是生物智能的专属领域。这也是我们认为的“一般智力”的基础。这是一个激烈争论的话题,一些人认为没有“一般智力”这样的东西,只有许多种专门的智力。直觉上,我们中的许多人可能会有不同的感觉,认识到一个共同的线索,这就是我们学习如何骑自行车和征服 Atari 视频游戏的能力。一个可能的共同思路是无模型强化学习,大量的证据支持这一观点。

赋予计算机无模型强化学习带来的一个有问题的结果是,代理人没有办法知道它的策略为什么有效,也没有办法就此进行交流或推理。和进化一样,无模型强化学习的手也是瞎的。它可以优化,而不知道它做了什么导致了理想的结果。这是一个无意识的过程,因为主体不能抽象地推理环境中的特定元素如何与它的动作相结合来实现期望的结果。就像一只狗可以成功地操纵它的主人,却不知道为什么当它坐在枕头上做出愚蠢的表情时,食物会像雨点般落在它身上。狗只是知道过去什么工作得好,而不是它为什么工作的机制。因此,生成这些解的路径经常隐藏在代理为达到其目标状态而采用的随机变化中。

这使得复制或交流通过无模型强化学习产生的技能变得困难。在固定的环境中,在固定的回报下,人们会期望多个无模型 RL 算法在给定足够训练的情况下最终收敛到单个目标状态。这种收敛性的证明已经在 SARSA 和 Q Learning 中得到验证。然而,在一个丰富的真实世界环境中,有一个连续的动作空间,可能很难或不可能复制最终导致代理达到所需目标状态的动作的精确组合,就像试图将一个雪球滚下山,并让它遵循前一个雪球滚入的完全相同的路径-但滑雪者和雪地摩托车一直穿过这些相同的轨道。

另一方面,基于模型的强化学习的优势在于,当代理学习事物时,它创建了事物在环境中交互方式的抽象。然后,可以将这些信息传递给其他代理,或者存储起来供以后在其他环境中使用,从而加快相关技能的获取。因此,基于模型的强化学习的发展很可能构成人工智能领域的下一波进步。DeepMind 已经朝着这个目标取得了一些令人印象深刻的进展,推出了用于“关系深度强化学习”的算法。这些将关系网络与强化学习结合起来,允许代理推测环境中的对象如何与它的动作交互以产生期望的结果。

在许多方面,这种向基于模型的强化学习的转变概括了人类获得性文化策略的进化。以现代农业为例——正如贾雷德·戴蒙德在他的书《第三只黑猩猩》中指出的,这很可能始于一个完全无意识的过程,发生在人类采集野生植物的过程中,在这个过程中,不知不觉地将种子放在它们的家养围栏附近。其中一些种子后来发芽了,形成了第一个原始花园。因此,当人类开始除草、收割和重新种植那些曾经是野生的植物时,一个无意识模式的策略可能会逐渐产生一个基于有意识模式的策略。通过关系型深度强化学习,可以认为计算机正在经历类似的“大跃进”,从无模型的强化学习策略过渡到使用模型对环境进行推理和推测的策略。

其结果是,人类文化,我们物种的集体知识,可以转移和改进,可能很快就会在计算机科学和机器人技术中产生必然结果。由深度 RL 代理开发的关系网络可以逐渐改进,然后传播到其他代理。从理论上讲,这允许多个主体以类似于人类科学知识随着时间的推移而增长的方式,慢慢地提高他们对给定环境的集体理解,从而产生了我们目前生活的文明。

使用先进的计算机视觉技术的鲁棒车道发现:中期项目更新

原文:https://towardsdatascience.com/robust-lane-finding-using-advanced-computer-vision-techniques-mid-project-update-540387e95ed3?source=collection_archive---------0-----------------------

车道发现对于开发自动驾驶机器人或自动驾驶汽车的算法至关重要。车道寻找算法必须对变化的光线条件、天气条件、道路上的其他汽车/车辆、道路的曲率和道路本身的类型具有鲁棒性。在这篇文章中,我们提出了一种基于先进的计算机视觉技术的算法,从仪表板上安装的摄像头视频中识别左右车道。我们在以下步骤中实现了车道寻找算法,

  1. 不失真的相机图像,并应用透视变换获得街道的鸟瞰图。
  2. 转换到 HSV 色彩空间并应用颜色遮罩来识别黄线
  3. 应用 Sobel 滤波器以获得具有潜在线条/边缘的图像
  4. 组合来自 Sobel 过滤器和 HSV 颜色遮罩的二进制遮罩
  5. 应用移动平均过滤器来去除任何可能是由于图像中的其他伪像造成的标记或特征。
  6. 应用多项式回归计算左右车道
  7. 应用帧到帧平滑以丢弃图像之间的噪点,并在图像上画回线条。
  8. 计算曲率和车道偏离,并将其写在图像上。

接下来我们将详细讨论每个步骤。上述过程的最终结果如下所示,

Advanced lane finding using computer vision

下面的视频展示了制作上面的视频所涉及的所有步骤的诊断视图。

第一步:不失真的相机图像和应用透视变换。

当相机镜头捕捉图像时,它们捕捉的不是真实的图像,而是原始图像的变形。图像中心的点具有较低的失真,而远离中心的点具有较高的失真。这种失真可能是由于与相机中心的距离不同、不同镜头位置的光线弯曲不同或透视失真造成的。一篇关于不同类型失真的好文章可以在这里找到。

因此,图像处理的第一步是对原始图像进行去失真处理。对用于不失真摄像机图像的算法的详细描述可以在这里找到。对于我们的算法,我们首先使用提供的棋盘图像计算相机失真矩阵和失真参数。然后,我们加载相机矩阵,并使用它来不失真的图像。下图显示了未失真的结果。最后一个面板显示了原始图像和未失真图像之间的差异。

Removing image distortion

接下来,我们应用透视变换来获得道路的鸟瞰图。我们首先在原始相机图像中识别 4 个点,然后拉伸图像,使 4 个点之间的区域形成一个矩形截面。

Perspective transform to get bird-eye view

一旦获得了俯视图,我们就开始确定车道。

步骤 2:转换到 HSV 色彩空间并应用颜色遮罩

下一步是将鸟瞰图 RGB 图像转换为 HSV 颜色方案。HSV 指的是色调、饱和度、数值。HSV 方案是作为一种更直观的方式来表示颜色而开发的。色调(或 H)代表特定的颜色,饱和度(或 S)代表颜色的数量,数值(或 V)代表相对于类似照明的白色的亮度。因此,通过将图像转换为 HSV 尺度,可以获得良好的颜色分辨率。我们使用 HSV 颜色空间来识别黄色和白色。我们应用黄色面具作为

yellow_hsv_low  = np.array([ 0, 80, 200])
yellow_hsv_high = np.array([ 40, 255, 255])
res = apply_color_mask(image_HSV,warped,yellow_hsv_low,yellow_hsv_high)

其中,apply_color_mask 返回指定强度介于低值和高值之间的像素。应用黄色蒙版的结果是,

Applying yellow-mask

因为黄色掩模对于不同的照明条件非常鲁棒,因为黄色的不同照明图像是通过改变亮度通道而产生的,同时保持色调或颜色通道固定。下图显示了不同照明条件下应用黄色遮罩的效果。

Yellow mask on shadowed and bright patch of road

Yellow mask on bright patch of road

类似地,使用阈值应用白色遮罩,如下所示

white_hsv_low  = np.array([  20,   0,   200])
white_hsv_high = np.array([ 255,  80, 255])

为了识别白线,

Applying white mask,

一旦应用黄色和白色蒙版,通过如下组合两个通道蒙版获得来自彩色蒙版的通道。

Combined lane from color masks

第三步:应用索贝尔过滤器得到潜在的线条/边缘

下一步是应用索贝尔过滤器,以获得潜在的线/边缘。如果道路上没有其他黄色或白色标记,上面的颜色遮罩是选择车道标记的好方法。这并不总是可能的,因为道路上可能有白色或黄色的文字。因此,为了避免混淆,我们还使用 Sobel 滤波器进行边缘检测。Sobel 滤波器用于图像处理,通过执行原始图像和 Sobel 算子(或滤波器)的 2-D 卷积来获得图像的边缘。这个操作可以表示为,

Sobel filter, circle denotes convolution operation

沿着 x 和 y 方向 Sobel 滤波器给出了沿着 x 和 y 方向的图像强度的梯度或变化。然后,这些强度可以通过大小和方向进行阈值处理,以获得仅在边缘处等于 1 的二进制图像。我们将应用 Sobel 滤波器,并对 HLS 图像的 S 和 L 通道的 x 和 y 方向的梯度幅度进行阈值处理。我们选择 HLS 通道是因为在以前的实验中,发现 HLS 颜色空间对于检测边缘是最鲁棒的。

Sobel filter applied on L and S channel of image

第四步:组合索贝尔滤镜和彩色蒙版

接下来,我们将来自 Sobel 过滤器的二进制掩码和颜色掩码相结合,以获得车道的更强指示符。车道应该是深色背景上的白色或黄色标记,因此应该显示较大的坡度。白色和黄色通道的组合 Sobel 图像和颜色遮罩如下所示。

Lane masks from Sobel filters and color masks

来自颜色掩蔽和 Sobel 滤波器的最终组合的车道和边缘掩蔽如下所示。很明显,原始图像中预期有车道的区域用粗粗线突出显示。我们能够获得这些粗线是因为我们结合了边缘检测和颜色掩膜。

Final combined lane mask

第五步:应用窗口来删除任何可能是由于图像中的其他伪像而产生的标记或特征。

在最终的合成蒙版中,我们看到了许多可能是由其他伪像造成的边缘特征,其中一个突出的是由汽车引擎盖造成的水平线。因此,我们计算沿 x 方向的所有像素的平均值,并使用移动平均滤波器来获得沿 x 方向的平滑强度分布。然后,我们应用阈值 0.05 来识别可能包含车道线的区域。这些区域边界用蓝线表示。

Plot of intensity along X direction

我们使用这些峰的左右边缘作为边界来选择左右车道标志点。通过去除左右车道标志的点,我们得到了表示车道的点,

Left and right lane markings

步骤 6:应用多项式回归计算左右车道

接下来,我们使用多项式回归获得二次拟合来近似车道线。我们使用 numpy 的简单多项式拟合函数来计算左右车道的二次拟合。一旦获得了左和右车道的二次拟合,我们将它们画回到图像上,并如下用青绿色标记左和右车道之间的区域。

Redrawing lane lines and lane back on the original image

第七步:逐帧平滑去除图像间的噪声,并在图像上画线。

接下来,我们通过一阶滤波器对帧进行平滑处理。我们还包括一个干扰抑制例程,该例程丢弃任何系数与前一帧中的系数偏差超过 5%的多项式拟合。

步骤 8:计算车道曲率和车道偏差

最后,我们计算了曲率半径和车道偏离,并实现了一个简单的车道偏离警告系统,如果车道偏离超过 30 厘米,该系统会将蓝绿色区域变为红色。

反思

这是一个非常有趣的项目。最有趣的部分是查看在以前的简单项目中开发的技术如何应用于更一般的场景。这个项目的工作远未结束。当前的算法不够健壮,不足以推广到挑战视频,但性能非常好。我们将在最终报告中详细介绍一个更强大的算法。

致谢:

我非常感谢 Udacity 选择我作为第一批,这让我能够与许多志同道合的人联系。一如既往,从与亨里克·特纳曼和陈志强的讨论中学到了很多。我也感谢获得 NVIDA 的 GPU 拨款。虽然这是工作用的,但我也用它来办公。

特别感谢一位同学陈志强。John 发布了一个简单的解决方案来实现管道的诊断视图,但是当论坛从旧论坛迁移过来时,这个解决方案被删除了。尽管约翰在度假,他还是及时上传了新论坛上的代码片段,并把链接发给了我。

坚如磐石的预测——预测…岩石?

原文:https://towardsdatascience.com/rock-solid-predictions-predicting-rocks-c0138a8994f6?source=collection_archive---------4-----------------------

序幕——在战场上翻滚

许多年前,我在(超级)大石油公司的第一个任务期间,我负责陆上气田钻井的重大决策。每口井都钻得很快,平均需要 5-7 天。地质情况是众所周知的,一般来说,储层是经济的,钻井的作业风险相当低且易于管理。

尽管该油田的区域地质具有明显的同质性(地质学中没有什么是真正同质的),但作业地质学家(比如我自己)不得不做一些非常手工的工作。

当我们接近每口井的储油层部分时,我被要求根据钻井时获得的数据确认我们正在接近储油层。在行业中,这被称为随钻测井或 LWD 测井。

Sunset in Wyoming at the rig site

在确认我们到达了储油层部分后,我被要求根据我们绘制的储油层厚度图来确认油井的总深度(TD)。最后,在确认 TD 后,我被要求观察最终的测井记录,以决定为生产目的关闭油井。尽管我们尽了最大努力,但并不是每口井都是经济井,因此我必须决定储层中是否有足够的天然气(产层)来保证在井眼中放置生产质量的套管。

At the rigsite. I still cherish the helmet the mudloggers bought specifically for me.

这一切都非常有趣和酷,直到人们意识到两个主要问题:

  1. 钻井作业是全天候的,因此,你可以(也将会)全天候接到电话
  2. 这些井钻得很快。负责 2-3 条钻井管线意味着我必须定期处理这些电话,几乎没有停机时间

除了清晨的钻机呼叫之外,这需要许多个深夜。我一直在想,一定有更好的方法…

这显然是一个可以通过机器学习来解决的问题!

然而,这是在 2007-2008 年,现代机器学习刚刚起步,在石油和天然气等行业还不存在。

快进到去年秋天。2016 年,SEG(勘探地球物理学家协会)在 Github 上提出了一项挑战,要求使用机器学习来解释岩石类型/地层的样本测井记录。

渴望有趣的项目,我一头扎进去,看看我能做些什么…

摇滚是个大问题

“最近人们对大数据非常兴奋,并且迫切需要能够从中提取意义的数据科学家。与此同时,地球科学家多年来一直在利用大量数据进行科学研究,不需要吹嘘数据有多大。但是现在大而复杂的数据集随处可见,分析它们的工具和技术也随之激增。现在存在许多免费和开源的软件包,为地球科学家的工具箱提供了强大的补充,其中许多以前只能在专有(且昂贵)的软件平台上获得…

…在我们的例子中,特征将是来自九口气井的测井数据。这些井已经根据岩心描述进行了岩相分类。一旦我们训练了一个分类器,我们将使用它来分配尚未描述的井的相。"

好吧,说真的,对于那些不是地球科学家或者不精通这个主题的人来说,这毫无意义。然而,它可以被提炼为简单的…

我们能预测岩石相吗?

对于非地球科学家来说,什么是真正的岩石相?

Classic alluvial depositional environment. In this case, a braided stream. The sandstone will be deposited and recorded where the streams are today.

沉积岩相是根据其沉积环境对不同类型的沉积岩进行分类的基本方法。 这是一个冲积砂岩的简单例子,这种砂岩形成于溪流或河流中。岩石相让我们知道石油和天然气可能在哪里,也可能不在哪里。

尽我们所能从数据中提取信息

数据集来自堪萨斯大学,重点是 Hugoton 和 Panoma 气田。它有 7 个特征(来自测井的 5 个电缆测量和 2 个指示变量)以及每 6 英寸一个的相标签。

Sample Well log. The facies labels are on the far right of the log.

左边是一个示例测井记录。该数据通常在钻井作业期间或在钻井完成后通过钻柱上的工具或下降到井内的测井电缆工具来记录。除了通过钻孔向上循环的岩屑的岩石描述之外,这些结果通常是地质学家关于所讨论的井的唯一信息。

通常情况下,地球科学家会手动获取测井记录并进行对比。他们必须从一条测井曲线到另一条测井曲线,以获得岩石类型/岩相、其特征(孔隙度/渗透率/保持和流动流体的能力)及其含量(水、油、气等)的整体视图。).这在成熟的领域中会变得单调乏味,并且在新的领域中容易被误解。

本项目的目标是预测维持组的相标签(不在下表中,而是在上面测井记录的最右侧),作者可以在其上运行模型以评估模型的成功。

Example of dataset features. What the fields mean are of relatively little importance in this case. Assume it’s just standard data obtained from every well in a given field.

退出石器时代…

我取了上面的数据,做了一些简单的特征工程。

首先,我使用虚拟变量对地层名称进行编码(这些名称包含有价值的沉积环境信息)。

然后,我将数据分成训练集和测试集,从数据集中删除相信息。

既然我已经把数据整理好了,现在是选择模型的时候了。

这个多类分类模型对我来说是一个新的模型,因为它没有预测二元结果。我想探索的不仅仅是一个简单的随机森林,还想探索我能用这些数据做些什么。

因此,我选择评估两种不同的模型:

  1. OVO(一对一分类器)
  2. 随机森林

我让事情非常简单,因为这是一个下午的项目,但结果非常有趣…

摇滚明星的结果!

如上所述,这个问题将使用 F1 分数进行评估。

https://www.slideshare.net/DhianaDevaRocha/qcon-rio-machine-learning-for-everyone

相对于对数损失、AUC 和其他指标,我最初对这个指标并不熟悉,所以我做了一点研究。

F1 分数是精确度和召回率的调和平均值。

该模型将对相预测的准确性和相邻相预测的准确性进行评分。

我对我的两个模型都进行了评分,结果相当疯狂:

OVO 分类器—

OVO 分类器将问题分解成许多 1:1 的比较,并学习如何区分不同的输出。需要 K (K-1) / 2 个二元分类器来将多类问题分成二元类。然后,它对每次运行中的每次观察的投票进行评分,并根据这些投票对最终的类读数进行排序。

OVO 的 F1 分数低于 Github repo 上其他人的模型结果。

然而,看看我的随机森林模型测试集的结果…

随机森林—

在我的测试集上,我的分数比非正式比赛的最高分高出 0.1 分。玩了一下午还不错…

不过,差不多是好…

我从来没有正式提交过我的模型 ,所以我一直无法实际验证我在官方 holdout set 中的 F1 分数。

滚过我的不安全感…

冒名顶替综合症——恐惧…

然而,摇滚可以拯救你的灵魂!

我知道你们每个人都在为此挣扎。

谈论它是有帮助的。写下来会有帮助。唱出来会有帮助!通过任何对你有意义的方式来表达自己会有帮助。

感谢文字,表达思想,思考和学习,我每天都在克服这些挑战。

每天谈论和做让你感到不舒服的事情。我拿了一个自己比较舒服的东西,地学,和一开始让我不舒服的东西混在一起,编程。

现在,通过每天做一些不舒服的事情,我对自己的数据科学和编码技能更有信心了。

喜欢你正在读的书吗?请在未来几周继续关注我正在撰写的关于营销分析以及如何使用数据作为工具讲述令人信服的以客户为中心的故事的文章。

错过了我的职业支点系列?我是如何从地球科学转向数据科学的?阅读此处跟随我的旅程…

更多阅读:http://library.seg.org/doi/10.1190/tle35100906.1#_i2

https://github.com/seg/2016-ml-contest

https://en.wikipedia.org/wiki/Impostor_syndrome

卷起轮圈:真的是六分之一吗?

原文:https://towardsdatascience.com/roll-up-the-rim-is-it-actually-1-in-6-965b77c92642?source=collection_archive---------7-----------------------

蒂姆·霍顿名言的统计分析

蒂姆·霍顿即将赢得 2018 年的比赛。你每买一杯热饮,就有六分之一的几率中奖(奖品包括免费甜甜圈、咖啡和汽车)。随着比赛的进行,对他们标志性的“六分之一”声明的怀疑也在增加。

这是运气不佳、确认偏差或者可能蒂米斯实际上在欺骗我们的综合结果。由于没有人能够购买流通中的全部 3600 万杯,没有人能够绝对肯定地反驳或证实他们的说法。

然而,即使样本量相对较小,我们也可以用证据来说明他们的陈述有多准确。

数据收集

在对朋友和家人进行调查后,我收集了 108 种购买饮料的相关数据。其中,16 个是赢家。乍一看,这意味着 1/6.75 的可能性。还不错。但这是否足够接近六分之一来支持 Timmies 的签名声明呢?

先说一个假设。

**假设:**有 1/6 的中奖几率。

你可能不同意这个假设,但没关系——如果我们有证据,我们可以稍后反驳它。因为有足够多的杯子在流通,所以一个结果不会显著改变获奖的几率,我们可以使用伯努利分布来模拟这个假设。

Jacob Bernoulli, famous mathematician and also very stylish

拟合优度检验

我们可以使用卡方检验来评估我们的样本数据在多大程度上符合伯努利分布,在伯努利分布中,成功的几率(在这种情况下,是获奖)是 1/6。卡方检验要求我们计算一个统计量,这个统计量概括了我们观察到的和我们期望看到的之间的差异。对于我们的示例,我们预计会看到 18 个奖项和 90 个“请再玩一次”的奖项。

有了这些信息,我们可以使用以下公式计算卡方检验统计量:

卡方检验统计量方便地遵循卡方分布。伴随着这种有点复杂的现象,有一个很好的证明,但这是我们幸运拥有的东西。

当我们知道统计数据遵循的分布时,我们可以根据统计数据在分布中的拟合程度来测试我们的假设。

结果

幸运的是,R 有一个内置的卡方检验函数。如果没有它,我们将不得不用传统的方法来计算,并将结果与表格进行比较。

哪些输出:

Chi-squared test for given probabilities data: observed 
X-squared = 0.26667, df = 1, p-value = 0.6056

这里感兴趣的参数是 p 值。更容易将 p 值解释为百分比(60.56%)。

p 值表示 1) 假设我们的假设为真,并且 2)我们根据我们的假设从分布中重复采样,那么我们观察到的 60.56%的样本将比我之前收集的 108 个样本更加“极端”。

通常,我们使用 5%的 p 值作为拒绝假设的准则。如果不到 5%的后续样本更“极端”,这表明我们的观察非常“极端”,因此我们的假设不太可能是真的。我们的样本显示情况并非如此。

底线:我们的 108 个样本没有证据否定蒂姆·霍顿的说法,即 1/6 的几率。

这是否意味着中奖几率确实是 1/6?

肯定不是!反驳一种说法比证实一种说法容易得多。

这引出了另一个问题——如果问题出在我们的样本上呢?大多数关于样品的问题都是“好吧。如果我们真的非常非常幸运,看到了我们所看到的,会怎么样?”。

这些问题归结为以下几个问题:

  • 样本是否偏向某些群体?
  • 108 的样本够大吗?

**针对第一点,**答案是肯定的,抽样是有偏差的。我调查的大多数人来自安大略省南部。他们中的大多数是喝咖啡的人。大多数人在上班前都会买咖啡。问题是——这些偏见重要吗?我认为,一旦杯子生产出来,奖品(或缺少奖品)不会改变是公平的。一个更合理的担忧是地理位置和杯子的大小。蒂姆·霍顿的分销网络是如何构建的?如果有的话,他们付出了什么样的努力来确保获胜的奖杯被平均分配?没有进一步的数据,我们对这些情况视而不见。

**样本量呢?**更好的问题— 多大的样本才算“足够大”?虽然我们有一个封闭形式的公式来计算控制误差的样本量,但我认为模拟可能更有见地。

模拟时间

让我们模拟五种不同的场景,其中我们假设实际获奖几率分别为:

  • 四分之一
  • 五分之一
  • 六分之一
  • 七分之一
  • 八分之一

我们根据 100 人、1,000 人和 10,000 人的样本量将这些场景分成三组。我们对每一组模拟 100 次,并用概率为“1/6”的天真假设进行测试。

卡方检验能正确拒绝假设多少次?或者,在潜在的赔率实际上是 1/6 的情况下,卡方检验会错误地拒绝假设多少次?

R code for simulation

我们观察到以下结果。让 n 表示样本大小。

We reject the hypothesis when p-value < 0.05

嗯。不幸的是,看起来我微薄的 108 个样本太小,无法检测出假阳性(不是 1/6 的几率被认为是 1/6 的几率),特别是当实际几率更小的时候。它似乎在消除假阴性方面做得不错(1/6 的几率不会被认为是 1/6 的几率)。

但是,如果我们给自己更多的宽容来惩罚假阳性呢?毕竟,我的样本确实达到了 60.56%的 p 值,这比建议的 5%临界值高得多。

如果当 50%或更少的后续样本更极端时,我们拒绝 1/6 的赔率假设(即当 p 值< 0.5), we obtain the following.

We reject the hypothesis when p-value < 0.5

Not too bad for a first run! Ideally, I would have liked to work with a larger data set with more variables to explore (such as location, time of purchase, cup size …etc). That could provide more insight into Tim Horton’s distribution network and eliminate more biases from the sample. Alas, we must make do with what we have.

Maybe for next year, I will make more of an effort to collect data.

结论:虽然我们的样本表明没有证据拒绝 1/6 的赔率,但我们认识到 108 的样本量可能不够。然而,我们的样本结果和样本大小在评估真实几率时,在消除假阴性和假阳性方面做得还可以。

感谢您的阅读!

如果你喜欢这篇文章,可以看看我关于数据科学、数学和编程的其他文章。通过 Medium 关注我的最新动态。😃

作为一个业余爱好项目,我还在www.dscrashcourse.com建立了一套全面的免费数据科学课程和练习题。

如果你想支持我的写作,下次你报名参加 Coursera 课程时,可以考虑使用我的会员链接。完全公开—我从每一次注册中获得佣金,但不会对您产生额外费用。

再次感谢您的阅读!📕

深度学习图像分类器的罗夏测验

原文:https://towardsdatascience.com/rorschach-tests-for-deep-learning-image-classifiers-68c019fcc9a9?source=collection_archive---------2-----------------------

当没有东西可看的时候,他们看到了什么?

The inventor of the Rorschach Test, Hermann Rorschach, next to his modern day counterpart, Walter Kovacs.

随着对图像分类和标记的大量探索,我们倾向于使用各种库来快速评估和标记图片。但是除了内存使用和重新训练图层的便利性,当呈现不清楚、有颗粒的图片时,它们会有什么表现呢?

为了在实践中更好地感受每个 ConvNet 的细微差别和趋势,我对罗夏测试中的所有卡片连续运行了最流行的那些。

目标很简单:设定我的期望,理清我对每一个期望的理解,这样我就可以使用正确的工具来推进工作。

罗夏测验

由赫曼·罗夏克发明(或者更准确地说,修改)的罗夏测验是最著名的墨迹测验。墨迹测试是与你的治疗师的一个简单的对话开始,那就是“你看到了什么?”在被展示一张纸上挤压的故意抽象的(通常是对称的)墨滴之后。罗夏更进一步,创造了一套标准。这套标准现在可以用于病人和治疗师之间。

All 10 cards from the original Rorschach Test. Note the use of colors, as opposed to some of the inkblot tests used before Mr. Rorschach’s standardized version.

这个测试的目的是唤起对抽象艺术的潜意识反应,用你自己的偏见和最深刻的想法覆盖它,这样你首先看到的就是你正在思考的。尽管它在过去几年中已经失宠(“伪科学”被用来描述它),但它仍然是描述心理学领域的一个非常有用的比喻。

在这种情况下,我使用它来强制各种库将这个无害的数据集分类到预定义的标签中。

分类器

为了对图片进行分类,我查看了以下库:

  • ResNet50
  • VGG16
  • VGG19
  • InceptionV3
  • InceptionResNetV2
  • 例外
  • MobileNet
  • MobileNetV2
  • DenseNet
  • 纳斯网

(这些都是在 Keras 2.2.0 中可用的原生应用程序库。)

这些分类器中的每一个都具有特定的结构和与之相关联的权重。

Documentation for each classifier from Keras.

除了内存使用和可训练参数之外,每一个的实现细节都有很大的不同。与其深入挖掘每个结构的特殊性,不如让我们看看他们是如何看待同样令人困惑的数据的。

(如果你想单独了解每个结构的更多信息,如果你想了解更多关于 ResNetInceptionDenseNetNASNetVGG16/19MobileNet 的信息,这里有链接。)

结果呢

总的来说,我们的目标是快速了解预测和预测背后的信念强度。为了做到这一点,我将前 1 名的预测按名称分组,并将它们的得分加在一起。这给出了每个分类者准备在一张特定的牌上赌多少的感觉。对每个标签都这样做,可以很好地代表每个分类器的可信度,并让我们了解每个卡片的相对预测可信度。

举个例子,InceptionResNetV2、NASNetLarge、DensetNet201 认为卡 1 是战机(得分分别为 88.3%、46.2%、18.6%)。然后我把它加起来,无量纲的分数是 153.1。现在,我可以在分类器之间比较这个分数,看看哪一个表现最好。

卡片 1、2 和 3

Cards 1, 2, 3. Or, according to the classifiers, a fighter jet, a rooster, and a book jacket. Go figure.

Card 1:
warplane 153.05
wall_clock 75.41
letter_opener 47.29
lampshade 33.13
buckeye 28.95
jigsaw_puzzle 23.19
paper_towel 22.51
birdhouse 11.50Card 2:
cock 72.84        # <--- Rooster.  They mean rooster.
lampshade 59.99
brassiere 59.47
velvet 43.84
earthstar 41.42
mask 29.46
candle 21.84
tray 19.30
wall_clock 18.41
hair_slide 17.84
vase 11.44Card 3:
**book_jacket 325.35** # <--- No idea what's going on here.
coffee_mug 62.61
chocolate_sauce 45.00
candle 32.68
ant 25.81
matchstick 24.02
jersey 16.94

卡片 4、5、6 和 7 —错误和爆炸

First row: Card 4 and Card 5. Second row: Card 6 and Card 7. Card 5 is without a doubt a picture of some sort of bug.

卡片 4 到 7 引出了更多的烟、飞船和虫子。这让我想起了我的农村童年,玩着有史以来最好的乐高玩具。(我显然指的是 M-Tron 、邪恶 BlackTronIce Planet 。)

Card 4:
volcano 101.76
fountain 72.11
space_shuttle 32.72
hen-of-the-woods 29.40
pitcher 28.28
vase 25.00
king_crab 23.99
wall_clock 18.25
triumphal_arch 11.04Card 5:            # <--- Bugs. Definitely bugs.
isopod 106.54
king_crab 83.67
ant 61.58
long-horned_beetle 32.23
tick 30.05
hip 26.32
rhinoceros_beetle 14.52Card 6:
space_shuttle 174.48
warplane 155.58
conch 104.73
missile 63.71
airship 57.73
fountain 11.57Card 7:
missile 195.66
parachute 52.52
projectile 42.31
space_shuttle 31.18
hip 29.89
geyser 20.92
warplane 17.50

卡片 8、9 和 10——降落伞、海螺和托盘?

Cards 8, 9, and 10. How the right one is a “tray” is beyond me.

Card 8:
fountain 189.59
parachute 98.27
umbrella 94.61
pencil_sharpener 63.27
spoonbill 51.08
poncho 45.19
coral_fungus 12.05
shovel 10.12Card 9:
missile 238.45
fountain 64.82
parachute 48.21
volcano 44.77
paper_towel 41.59
lampshade 13.48Card 10:
tray 229.22
handkerchief 151.63
conch 77.94
feather_boa 60.34
rapeseed 15.95

当然,我们可以更深入地了解每个预测的平均置信度。下面是卡 1 的一些示例数据。所有的结果都可以在该项目的 GitHub 页面上找到。

All of the results available for Card #1.

代码

为了标记每张图片,我们首先加载 Pandas、NumPy 和 Keras 图像预处理库:

from keras.preprocessing import image
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.models import Model
import keras.backend as K
import numpy as np
import pandas as pd
import json

然后,我们创建一个助手函数来返回包含每个库的前 10 个结果的分数的数据帧,以便快速汇集每个图像的分数:

def getLabels(model, dims, pi, dp):
"""
Returns the top 10 labels, given a model, image dimensions, 
preprocess_input() function, and the labels inside decode_predictions().
"""df = pd.DataFrame()

    for img_path in images:# Resize image array
        image = load_img(img_path, target_size=(dims, dims))
        image = img_to_array(image)
        image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
        image = pi(image)

        # Predict what is in the image
        yhat = model.predict(image)

        # return the top 10 labels
        labels = dp(yhat, top=10)[0]# create empty list and counter
        labellist = []
        counter = 0

        # get labels for each image
        for label in labels:
            # Display the score of the label
            print('%s (%.2f%%)' % (label[1], label[2]*100))

            # Add image results to list
            labellist.append(
                {"labelnumber":counter, 
                 "labelname"  :label[1], 
                 "pct"        :'%.2f%%' % (label[2]*100), 
                 "image"      :img_path})
            counter = counter + 1

        # Add to dataframe
        df_row = pd.Series()
        df_row = pd.read_json(json.dumps(labellist), typ='frame', orient='records')
        df = df.append(df_row,ignore_index=True)
        print("------------")

    return df

现在,我们有了一个快速评估每个图书馆的方法。

# ...
# ResNet50 Rorschach assessment
from keras.applications.resnet50 import ResNet50
from keras.applications.resnet50 import preprocess_input
from keras.applications.resnet50 import decode_predictionsmodel = ResNet50()df = getLabels(model, 224, preprocess_input, decode_predictions)
df.to_csv('results_resnet50.csv', index=False)# ----------# VGG16 Rorschach assessment
from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input
from keras.applications.vgg16 import decode_predictionsmodel = VGG16()df = getLabels(model, 224, preprocess_input, decode_predictions)
df.to_csv('results_vgg16.csv', index=False)
# ...

…等等。

这种方法的有趣之处在于,当使用不同的图像集时,它是一个非常实用的笔记本:

A snapshot of the notebook from the repository.

这种笔记本结构允许您快速浏览不同的数据集,并查看适合您的产品或项目的最佳分类器。你是否在模糊的图片上寻找一个可靠的顶级精度?如何识别一张图片的所有不同内容?你的里程可能会有所不同,但你现在可以开始自己探索了。

你可以在这里得到的全部代码。

玩得开心!

马特。
matt @ lemay . ai

LEMAY . AI
1(855)LEMAY-AI

您可能喜欢的其他文章:

我的首席技术官丹尼尔·夏皮罗(Daniel Shapiro)的其他文章您可能会喜欢:

附注:发音是吼-肖克。

树莓 Pi 3 vs 龙板

原文:https://towardsdatascience.com/rpi3-vs-dragonboard-f4dd877b7da9?source=collection_archive---------1-----------------------

从 Python 的角度来看

Python 是创建简单 PoC 项目的完美语言。我们不会谈论 Python 优点的完整列表,但最神奇的是 Python 是跨平台。这个特性对于构建嵌入式系统应用程序非常有用。无需等待编译器构建二进制文件,无需将应用部署到主板上。同样的代码既可以在 PC 桌面上运行,也可以在基于 Linux 的板上运行,比如 Raspberry Pi。

然而,这种方法有其局限性。它不能用于一些与硬件相关的项目,例如 PC 桌面没有 SPI。显然,基于 ARM 的主板比 PC 要慢。因此,在某些情况下,在桌面上完美运行的算法在嵌入式系统上会出现性能下降。

性能对比

在我们最新的项目中,性能至关重要。我们使用 Dragonboard 410c 作为目标平台之一。我们对董事会的表现感到惊喜。即使没有仪器基准测试,我们也能感觉到与 Raspberry Pi 3 相比,OS 包安装、应用程序启动和整体性能都有显著提升。

Board specs

看起来相当平等,并不能解释 DragonBoard 的优越性能。所以我们执行了一个基准测试来分析它是否真的更快。

基准测试

我们决定在这些主板上测量 Python 3 的性能,作为我们最感兴趣的版本。我们使用了 Python 性能基准测试套件,声称它关注真实世界的基准测试,而不是尽可能使用整个应用程序的合成基准测试。

我们在嵌入式平台上使用了我们最喜欢的操作系统。该操作系统是一致的,并提供事务性更新。最重要的是,它支持两种板进行我们的基准测试。我们在 SD 卡上安装了 Ubuntu Core,并使用“经典”环境进行测试。

以下命令安装 Pyperformance:

pip3 install pyperformance

我们用以下方式运行它:

echo pyperformance run --python=python3 -o result.json | nohup sudo classic &

我们使用这个棘手的命令只是为了允许测试在没有活动 ssh 连接的情况下在后台运行,因为这需要时间,并避免由于丢失 ssh 连接而导致的任何问题(测试也会被停止)。

Results

结果

结果真的很让人吃惊。DragonBoard 几乎比树莓 Pi 3 快两倍!现在我们明白了为什么我们会感觉到性能提升。当然,Raspberry Pi 3 官方内核使用的是 32 位的 armhf (v7)架构,而 DragonBoard 410c 使用的是 64 位的 amr64(v8)内核。由于 Python 大量使用 64 位算法,这可能解释了差异。

最终系统台架测试

为了用本机代码确认这个结果,让我们也运行“sysbench”测试。Sysbench 有一些我们想要运行的测试:cpu、内存、线程、互斥。这些测试更具综合性,但我们还是来比较一下这些板的计算能力吧。

Results

CPU 基准测试快了 25 倍。这是因为 CPU 测试使用显式的 64 位整数。在这种情况下,64 位操作系统具有很大的优势。其他测试大约快两倍,这与 pybenchmark 非常相似。即使线程测试不会受到 64 位内核的影响。

结论

当然,总有机会用 C 甚至纯汇编语言开发你的项目,获得更好的性能。但是通常开发时间比板子的价格要贵。使用像 Python 这样的工具来帮助开发质量更好的产品并更快地将其交付给市场,会更便宜、更有效、生产率更高。

Python 导致的性能下降可以通过一个更强大的板来轻松克服。我们真的希望树莓派官方形象会有一个 64 位的 OS。但是现在 DragonBoard 410c 是 Python 应用程序开发的完美选择。

DataArt 的高级建筑师尼古拉·哈巴罗夫执笔。

可微分神经计算机:综述

原文:https://towardsdatascience.com/rps-intro-to-differentiable-neural-computers-e6640b5aa73a?source=collection_archive---------5-----------------------

可微分神经计算机是一种神经网络,它利用了记忆增强,同时也利用了注意力机制。最初的论文是由 Alex Graves、Greg Wayne 等人撰写的使用具有动态外部存储器的神经网络的混合计算(T2)。2016 年 10 月出版。

结构

让我们把 DNC 想象成一台带有 CPURAM 的机器。
一个神经网络,即控制器,将扮演 CPU 的角色。一个存储器,它只是一个矩阵,将扮演 RAM 的角色。
存储矩阵的每一行称为位置。矩阵将有 N 个位置,它们是 W 维向量。那么,存储器就是一个 N×W 矩阵。

记忆增强和注意机制

控制器将从存储器中存储和读取信息,网络将通过一些参数向量来学习如何做到这一点,但我们将对此进行讨论。主要的一点是,网络的内存是在网络本身之外的。
通常,网络的全部知识都存储在其权重中。相反,DNC 是一种叫做“记忆增强神经网络”的东西,这种特性为它提供了一些很好的特性。

内存增强并不是本文介绍的新奇事物;事实上,这根本不是什么新鲜事。DNC 中最酷的是在控制器和内存之间起中介作用的向量和操作系统。这被称为注意机制,这是过去几年的一个基本概念。

权重和人头

注意机制定义了 N 个位置上的一些分布。这些分布是 N 向量,称为权重。加权向量的每个第 I 个分量将传达控制器应该给予存储器的第 I 个位置中的内容多少关注。有更多的进程需要观察内存内容,这就是不同权重将采取行动的地方。

在我们的网络图中,每一个涉及操作的过程都是一个功能单元。生产和使用砝码的单位称为。基本上,我们在控制器和存储器之间有两种类型的交互:通过读取权重调节的读取过程,以及通过写入权重调节的写入过程。发生这种中介作用的功能单元被称为读磁头和写磁头。

可微性

正如我们将会看到的,在大脑内部,一种可区分的注意力机制以三种不同的方式被应用。当我说可微时,我是说产生读写权重的函数是可微的,然后我们可以对磁头应用梯度下降。

权重背后的直觉

当我谈到权重时,我指的是下面的概念:控制器想要做一些涉及内存的事情,而不仅仅是查看内存的每个位置;相反,它将注意力集中在那些包含它正在寻找的信息的位置上。谁把信息放在这些地方的?以前是控制器自己把它写在那里:它现在只想恢复它。

我说过,这个结构中的每个单元和操作都是可微的,也就是说,我们可以通过迭代应用梯度下降来学习一切。所以,脑袋的工作方式也是学来的!

概括一下:DNC 可以学习如何为每个输入产生良好的权重,也就是说,它知道如何根据其相对于给定输入的相对重要性,对其存储器进行不同的加权。为输入产生的权重是在特定过程(读或写)中 N 个位置相对重要性的分布。

权重是如何确定的?

权重通过控制器发出的向量产生,该向量被称为接口向量。接口向量是一组值,这些值对控制器需要和向存储器发出的请求进行编码。

注意高贵的三重路径

控制器和存储器之间有三种交互,它们由接口向量来调节:

  1. 内容查找:将接口向量中的一组特定值与每个位置的内容进行比较,我们将把这些值收集到一个叫做 key vector 的东西中。这种比较是通过相似性度量(在这种情况下,余弦相似性)来进行的。
  2. 临时内存链接:连续写入位置之间的转换记录在一个 N x N 矩阵中,称为临时链接矩阵 l。控制器写入内存的顺序本身就是一个信息,它是我们想要存储的东西。你可以这样想:如果我不记得我把智能手机放在哪里了,我可以试着回忆一下在到达现在的位置之前我在哪里。
  3. 动态内存分配:每个位置都有一个使用级别,用 0 到 1 的数字表示。挑选出未使用位置的权重被发送到写磁头,以便它知道在哪里存储新信息。“动态”一词是指控制器重新分配不再需要的内存,擦除其内容的能力。此外,分配机制独立于内存的大小和内容,这意味着我们可以扩展内存,而无需牺牲或重新训练网络。

这是对可微分神经计算机的初步观察。如果你在寻找一个定性的描述,我希望我足够清楚(不要犹豫,在评论中写下任何问题!).

Rubikloud 兑现了全渠道的承诺

原文:https://towardsdatascience.com/rubikloud-delivers-on-the-promise-of-omnichannel-37e44cca2547?source=collection_archive---------7-----------------------

大约在十年前,全渠道的理念开始深入人心。传统零售商认为这是一个“概念”,因为他们主要的实体店仍然是服务客户的重点渠道。快进到 2018 年,机器学习正在将这个概念变成现实。根据定义,

全渠道承诺通过满足消费者对购物即时性、便利性和无处不在的更高期望,拉近零售商与消费者的距离。它还认识到一个不可避免的现实:购物者越来越需要超越网上购物和商店购物之间障碍的零售体验。

我很荣幸地会见了首席执行官刘可莉和数据科学经理坎查纳·帕德马纳班,他来自 Rubikloud ,这是一家总部位于多伦多的软件公司,今天最接近实现这一承诺。

“全球领先的零售机器学习平台”

这是公司的价值主张。Rubikloud 是一个先进的零售机器学习平台,提供促销和忠诚度营销的市场内建议。影响:优化个性化,在正确的时间,通过正确的渠道,向正确的客户提供正确的产品和正确的信息。

现在,Rubikloud 拥有 100 名员工,在全球范围内拥有 10 多家零售客户,风投融资 4500 万美元,它正在进行零售革命。

开始:永远改变了企业软件的融合

五年前,凯瑞在一次收购后退出了一家初创公司。当时,他注意到了 3 个重要事件,这些事件有助于形成 Rubikloud 的推动力:

  • 云:三巨头——亚马逊、谷歌和微软在弹性计算方面进行了大量投资,为开发者提供云访问和计算可扩展性。
  • 数据框架:开源和各种数据框架的快速部署和采用。
  • 人工智能:人工智能开始在消费者领域变得越来越普遍,为脸书的新闻推送、网飞的推荐引擎和亚马逊的动态定价提供动力。

这三种趋势正在推动内部人工智能系统,它们正在汇聚成一种新形式的企业软件。一家新公司正是基于这一理念成立的:

我们成立 Rubikloud 最初是为了用一个垂直领域解决这三个挑战,随着我们的扩张,我们会进入新的垂直领域。我们决定关注全球零售业,即在市场成熟的世界关键地区拥有多样化终端用户体验的传统零售商。

克里的信念是,传统零售商没有死。他们只是需要技术来帮助他们转型和发展。

协调客户从线下到线上的旅程

测量客户购买的影响以确定倾向是困难的,因为直到现在,由于不同的系统和数据库,一次关注一个客户以及他/她在每个在线或离线购买点的购买的机制在很大程度上是分散的。

Rubikloud 的零售客户已经收集这些数据很长时间了,在许多情况下,他们被困在多个遗留系统中,而没有采取任何措施。

协调来自数据的见解并使其与业务目标相匹配不可能一蹴而就。然而,通过了解每个业务利益相关者(即销售和营销团队)的目标和挑战,Rubikloud 从根本上使这些团队的预测更加精确,执行更加无缝,并创建了更强大的绩效系统。

正如 Kerry 指出的,销售团队需要知道在几十万个 SKU 下订购多少库存,以什么价格设定,以及为每个渠道和商店分配多少。

Rubkiloud 的价格和促销经理将向零售商提供商店级分配和在线级分配。它还会告诉零售商对该库存使用什么促销策略,以及在促销过程中他们需要多久补充一次库存。

所有这些变量都由系统以自动化的方式进行计算,并由系统发送到沿途的各个接触点,无论是供应链系统、商店运营还是 ERP……它旨在解决零售商目前面临的最困难的计算问题之一:有多少库存、什么价位、哪些特定的 SKU 正在移动、在什么地区,最重要的是,哪些客户群受到这些 SKU、该价位和库存量的影响。

这些见解的价值注定会吸引更大的 CPG 玩家,他们传统上无法控制或获得其营销或推广工作的投资影响。在过去,接触零售数据在很大程度上是难以捉摸的。像尼尔森这样的推断数据源提供了 CPGs 的价格、市场份额和销售信息。相比之下,Rubikloud 收集了与 SKU 相关的数百个数据点,因为它们与客户细分、促销策略、购买、价格和位置相关。

零售数据的状态

数据是新的货币。它现在是、将来也将是近乎实时地在市场上做出决策的驱动力。然而,考虑到当今在转换数据以进行分析方面的普遍挑战(一些行业估计称 80%的模型开发工作处于清理阶段),再加上大型零售商之间缺乏对数据的使用、聚合和分析,数据转换可能需要 1-6 个月的时间。Kerry 指出,这不仅高度依赖于数据及其系统的状态,还依赖于零售目标的要求。

数据科学家 Kanchana Padmanabhan 认为,好的数据是关键。Rubikloud 吸收所有客户数据——交易数据、促销数据和其他相关数据源。零售商之间的差异可能导致可扩展性挑战:如不同的模式、遗留系统、不同的技术堆栈和数据量差异。加入数据,尤其是验证数据变得至关重要。

随着时间的推移,在许多用例及客户中,Rubikloud 在数据处理、管理和加工方面做得越来越好。他们已经学会并善于在数据进入他们的系统之前预先提出正确的问题。坎查纳补充道:

我们也有稳定的产品,所以我们知道我们在构建什么样的模型。我们知道我们提供的解决方案,更重要的是,我们知道我们需要什么数据。

Kanchana 指出,他们可以处理各种格式:从调查,到广告,电子邮件,交易,CRM,ERP 和社交媒体等。在某些情况下,鼓励营销人员一致且正确地输入信息,以确保数据的有用性。

除了主要信息外,Kanchana 表示,他们还覆盖了人口统计数据、竞争性定价信息、产品图片和描述。虽然社交媒体具有价值,但如今这些数据非常混乱,试图从社交媒体中找出交易也很困难…这就让我们想到了房间里的大象…

以客户为中心和隐私可以共存吗?

考虑到欧洲通用数据保护条例(GDPR),像 Rubikloud 这样的智能系统会受到威胁吗?通过生活方式管理器解决个性化的圣杯将需要在理想的环境和情况下,增加背景来确定顾客的购买意图。然而,克里强调,

我们不会收集个人身份信息(PII):我们不会收集您的姓名、电子邮件、信用卡号码和电话号码。原因是:这对我们没有帮助。了解 PII 对我们的模型没有任何帮助。我们更喜欢客户给我们一个哈希 ID 的客户…我们正在下降到 1-1 客户级别,但我们不知道这个人的名字或 PII。

该散列 ID 将通过 Adobe Campaign 或 Salesforce Marketing Cloud 发送回营销自动化堆栈,并将与 Rubikloud 及其系统范围之外的客户端系统中的客户信息进行匹配。

对于许多营销人员来说,使用任何和所有可用的数据进行分析和细分都是理所当然的。使用人工智能,在整个客户群的数千/数百万数据属性中搜索模式,不需要像 Kerry 那样需要个人信息来建立有效的模型。

虽然《今日 PII》是当今隐私辩论中的一个强大支柱,但即将到来的从元数据中进行的推理(人工智能在其中找到这些模式来定义上下文并预测客户倾向)肯定会成为一个辩论的话题。随着 GDPR 起飞,我们将继续关注此事。

零售业的未来意味着回归基础

凯瑞认为,零售业作为一个整体正在增长。客户的期望发生了显著变化。衡量零售商的技术能力也是一个品牌发展的标志。客户想要相关的推荐;他们喜欢亚马逊的动态定价;他们希望每次与零售商互动时,体验会更熟悉一些。

我们认为零售商不会消亡,但他们只有很短的时间来修正技术。他们不能再在大型遗留项目或临时创新项目上浪费时间了。他们必须解决消费者问题或产品问题。

克里指出,零售商把问题复杂化了。挑战在于他们如何以产品化的方式部署解决方案。我们生活在一个人工智能实验猖獗的时代。Rubikloud 已经进入全面生产阶段,他们已经学会了如何构建一个适用于该行业的整体解决方案。

你购买打包了所有用例及输入的软件,并与了解你业务细微差别的公司合作。在我们看来,您购买软件是为了解决可以解决的核心问题。

这意味着零售商将重新成为零售商。对于购买者来说,他们会将财务分析从工作描述中删除。相反,他们会将自己的核心能力应用于价格谈判、产品资源配置以及新产品和新客户的试验中。

通过采用技术,它允许客户做他们最擅长的事情。在 Rubikloud 的例子中,它肯定影响了这个咒语。

关于:

Kerry Liu is the Co-Founder & CEO at Rubikloud, where he leads three important functions: people, sales, and technology disruption. In his role, Kerry works to manage and maintain a thriving company culture that recruits the best and brightest in the industry, while also maintaining relationships with global retailers and investors. Kerry is passionate about machine learning and big data, and enjoys providing enterprise retailers with the tools and knowledge needed to enhance their overall business goals.

Kanchana Padmanabhan is the Manager of Data Science at Rubikloud. Kanchana received her PhD from North Carolina State University in Raleigh, NC with a focus on Graph Mining and Analytics, Computational Biology, and Network Modeling. Prior to Rubikloud, Kanchana spent 3 years at Sysomos, a social media analytics company for research projects that use machine learning, network analysis and NLP techniques in conjunction with big data technologies such as Hadoop, MapReduce, and Spark. She currently focuses her time on solving big data problems in retail. She has 4 patent filings and co-edited a book titled “Practical Graph Mining with R“ CRC Press.

本帖原载认知世界

用 Galaaz 绘制 Ruby:GraalVM 中 Ruby 和 R 紧密耦合的一个例子

原文:https://towardsdatascience.com/ruby-plotting-with-galaaz-an-example-of-tightly-coupling-ruby-and-r-in-graalvm-520b69e21021?source=collection_archive---------8-----------------------

介绍

Galaaz 是一个紧密耦合 Ruby 和 r 的系统。Ruby 是一种强大的语言,有一个大型社区,一个非常大的库集,非常适合 web 开发。然而,它缺乏数据科学、统计学、科学绘图和机器学习的图书馆。另一方面,R 被认为是解决上述所有问题的最强大的语言之一。也许 R 最强的竞争对手是 Python,它有诸如 NumPy、Panda、SciPy、SciKit-Learn 等库。

对于 Galaaz,我们不打算在 R 中重新实现任何科学库,我们允许两种语言之间非常紧密的耦合,以至于 Ruby 开发人员不需要知道有一个 R 引擎在运行。为此,我们使用了 Oracle 提供的新技术:GraalVM、TruffleRuby 和 FastR:

GraalVM is a universal virtual machine for running applications written in JavaScript, Python 3, Ruby, R, JVM-based languages like Java, Scala, Kotlin, and LLVM-based languages such as C and C++. GraalVM removes the isolation between programming languages and enables interoperability in a shared runtime. It can run either standalone or in the context of OpenJDK, Node.js, Oracle Database, or MySQL. GraalVM allows you to write polyglot applications with a seamless way to pass values from one language to another. With GraalVM there is no copying or marshaling necessary as it is with other polyglot systems. This lets you achieve high performance when language boundaries are crossed. Most of the time there is no additional cost for crossing a language boundary at all.Often developers have to make uncomfortable compromises that require them to rewrite their software in other languages. For example: * “That library is not available in my language. I need to rewrite it.” 
  * “That language would be the perfect fit for my problem, but we cannot run it in our environment.” 
  * “That problem is already solved in my language, but the language is too slow.”With GraalVM we aim to allow developers to freely choose the right language for the task at hand without making compromises.

感兴趣的读者还应该查看以下网站:

加拉茨是什么意思

加拉茨是“加拉哈德”的葡萄牙语名称。来自维基百科:

Sir Galahad (/ˈɡæləhæd/; sometimes referred to as Galeas /ɡəˈliːəs/ or Galath /ˈɡæləθ/), in Arthurian legend, is a knight of King Arthur's Round Table and one of the three achievers of the Holy Grail. He is the illegitimate son of Sir Lancelot and Elaine of Corbenic, and is renowned for his gallantry and purity as the most perfect of all knights.Emerging quite late in the medieval Arthurian tradition, Sir Galahad first appears in the Lancelot–Grail cycle, and his story is taken up in later works such as the Post-Vulgate Cycle and Sir Thomas Malory's Le Morte d'Arthur. His name should not be mistaken with Galehaut, a different knight from Arthurian legend.

Galaaz 演示

先决条件

  • GraalVM (>= rc7)
  • 松露红宝石
  • FastR

以下 R 包将在必要时自动安装,但如果需要,也可以在演示之前安装:

  • ggplot2
  • gridExtra

安装 R 包需要一个开发环境。在 Linux 中,gnu 编译器和工具应该足够了。

为了运行“规范”,以下 Ruby 包是必需的:

  • gem 安装 rspec

准备

  • gem 安装 galaaz

运行演示

这个演示的 ggplot 是从这里的中提取的

在控制台上做

> galaaz master_list:scatter_plot

运行其他演示

在控制台上做什么

> galaaz -T

将显示所有可用演示的列表。要运行列表中的任何演示,请将对“rake”的调用替换为“galaaz”。例如,列表中的一个示例是“rake sthda:bar”。为了运行这个示例,只需执行“galaaz sthda:bar”。执行“galaaz sthda:all”将运行 sthda 类别中的所有演示,在本例中,幻灯片放映中有 80 多个用 Ruby 编写的 ggplot 图形。

一些示例要求“rspec”可用。要安装“rspec ”,只需执行“gem install rspec”。

演示代码

以下是上述示例的 Ruby 代码和绘图。示例中的代码和下面的代码有一点不同。如果运行该示例,绘图将出现在屏幕上,如下所示,我们生成一个“svg”图像,然后将其包含在本文档中。为了生成和成像,使用了 R.svg 设备。要在屏幕上生成绘图,请使用 R.awt 设备,如代码中所述。

require 'galaaz'
require 'ggplot'# load package and data
R.options(scipen: 999)  # turn-off scientific notation like 1e+48
R.theme_set(R.theme_bw) # pre-set the bw theme.midwest = ~:midwestR.svg                   # run the svg device to generate an
                        # image in .png format# Scatterplot
gg = midwest.ggplot(E.aes(x: :area, y: :poptotal)) + 
     R.geom_point(E.aes(col: :state, size: :popdensity)) + 
     R.geom_smooth(method: "loess", se: false) + 
     R.xlim(R.c(0, 0.1)) + 
     R.ylim(R.c(0, 500000)) + 
     R.labs(subtitle: "Area Vs Population", 
            y: "Population", 
            x: "Area", 
            title: "Scatterplot", 
            caption: "Source: midwest")R.png('midwest.png')     
puts ggR.dev__off               # R.dev__off turns off the device.  
                         # If using awt, the plot window will 
                         # be closed

Midwest Scatterplot

在 R 中,生成该图的代码如下

# install.packages("ggplot2")
# load package and data library(ggplot2)options(scipen=999)    # turn-off scientific notation like 1e+48
theme_set(theme_bw())  # pre-set the bw theme.data("midwest", package = "ggplot2")# Scatterplot
gg <- ggplot(midwest, aes(x=area, y=poptotal)) + 
      geom_point(aes(col=state, size=popdensity)) + 
      geom_smooth(method="loess", se=F) + 
      xlim(c(0, 0.1)) + 
      ylim(c(0, 500000)) + 
      labs(subtitle="Area Vs Population", 
           y="Population", 
           x="Area", 
           title="Scatterplot", 
           caption = "Source: midwest")plot(gg)

请注意,这两个代码非常相似。Ruby 代码要求在调用任何函数之前使用“R”,例如,在 Ruby 中,R 函数“geom_point”变成了“R.geom_point”。r 命名参数如(col = state,size = popdensity),在 Ruby 中变成(col: 😒tate,size: :popdensity)。

需要注意的最后一点是对‘AES’函数的调用。在 Ruby 中,我们不用“R.aes ”,而是使用“E.aes”。为什么需要 E.aes 的解释是 R 中的一个高级主题,取决于 R 中的非标准求值(NSE)。简而言之,函数“aes”在 R 中是延迟求值的,即在 R 中调用 geom_point(aes(col=state,size=popdensity))时,函数 geom_point 接收类似于包含“aes(col=state,size=popdensity)”的字符串作为参数,aes 函数将在 geom_point 函数内部求值。在 Ruby 中,没有懒惰求值,做 R.aes 会尝试立即求值。为了延迟函数 aes 的评估,我们需要使用 E.aes。对 R 中的 NSE 感兴趣的读者可参考此处的。

该示例的扩展

如果这两个代码如此相似,那么为什么要用 Ruby 而不是 R 呢?galaaz 到底有什么好处呢?

Ruby 是一种现代的面向对象语言,有许多非常有用的结构,比如类、模块、块、过程等等。上面的例子关注于两种语言的耦合,并没有展示其他 Ruby 结构的使用。在下面的例子中,我们将展示一个使用其他 Ruby 结构的更复杂的例子。这当然不是一个写得很好的健壮的 Ruby 代码,但是它给出了 Ruby 和 R 是如何紧密耦合的想法。

让我们想象一下,我们在一家公司工作,这家公司有自己的情节主题。因此,它定义了一个“CorpTheme”模块。该公司的地块不应有网格,标签中的数字不应使用科学符号,首选颜色是蓝色。

# corp_theme.rb
# defines the corporate theme for all plots

module CorpTheme#----------------------------------------------------------------
# Defines the plot theme (visualization).  In this theme we
# remove major and minor
# grids, borders and background.  We also turn-off scientific
# notation.
#---------------------------------------------------------------

  def self.global_theme # turn-off scientific notation like 1e+48    
    R.options(scipen: 999)
    # remove major grids
    global_theme = R.theme(panel__grid__major: E.element_blank())
    # remove minor grids
    global_theme = global_theme + 
       R.theme(panel__grid__minor: E.element_blank)
    # remove border
    global_theme = global_theme + 
       R.theme(panel__border: E.element_blank)
    # remove background
    global_theme = global_theme + 
       R.theme(panel__background: E.element_blank)
    # Change axis font
    global_theme = global_theme +
                   R.theme(axis__text: E.element_text(size: 8,
                                color: "#000080"))
    # change color of axis titles
    global_theme = global_theme +
                   R.theme(axis__title: E.element_text(
                             color: "#000080", 
                             face: "bold",
                             size: 8,
                             hjust: 1))
  end

end

我们现在定义一个散点图类:

# ScatterPlot.rb
# creates a scatter plot and allow some configuration

class ScatterPlot attr_accessor :title
  attr_accessor :subtitle
  attr_accessor :caption
  attr_accessor :x_label
  attr_accessor :y_label

  #----------------------------------------------------------------
# Initialize the plot with the data and the x and y variables
#---------------------------------------------------------------- def initialize(data, x:, y:)
    @data = data
    @x = x
    @y = y
  end#----------------------------------------------------------------
# Define groupings by color and size
#--------------------------------------------------------------- def group_by(color:, size:)
    @color_by = color
    @size_by = size
  end#----------------------------------------------------------------
# Add a smoothing line, and if confidence is true the add a
# confidence interval, if false does not add the confidence
# interval
#-_-------------------------------------------------------------- def add_smoothing_line(method:, confidence: true)
    @method = method
    @confidence = confidence
  end 
  #---------------------------------------------------------------
# Creates the graph title, properly formated for this theme
# @param title [String] The title to add to the graph
# @return textGrob that can be included in a graph
#---------------------------------------------------------------- def graph_params(title: "", subtitle: "", caption: "", 
                   x_label: "", y_label: "")
    R.labs(
      title: title, 
      subtitle: subtitle, 
      caption: caption,
      y_label: y_label, 
      x_label: x_label, 
    )
  end#---------------------------------------------------------------
# Prepare the plot's points
#--------------------------------------------------------------- def points
    params = {}
    params[:col] = @color_by if @color_by
    params[:size] = @size_by if @size_by
    R.geom_point(E.aes(params))
  end#----------------------------------------------------------------
# Plots the scatterplot
#---------------------------------------------------------------- def plot(device = 'awt') device == 'awt' ? R.awt : R.svg

    gg = @data.ggplot(E.aes(x: @x, y: @y)) +
      points + 
      R.geom_smooth(method: @method, se: @confidence) +
      R.xlim(R.c(0, 0.1)) +
      R.ylim(R.c(0, 500000)) + 
      graph_params(title: @title,
                   subtitle: @subtitle, 
                   y_label: @y_label, 
                   x_label: @x_label, 
                   caption: @caption) +
      CorpTheme.global_theme R.png('scatter_plot.png') if !(device == 'awt')
    puts gg
    R.dev__off

  end

end

这是用中西部数据制作散点图的最终代码

require 'galaaz'
require 'ggplot'sp = ScatterPlot.new(~:midwest, x: :area, y: :poptotal)
sp.title = "Midwest Dataset - Scatterplot"
sp.subtitle = "Area Vs Population"
sp.caption = "Source: midwest"
sp.x_label = "Area"
sp.y_label = "Population"
sp.group_by(color: :state, size: :popdensity)    # try sp.group_by(color: :state)
# available methods: "lm", "glm", "loess", "gam"
sp.add_smoothing_line(method: "glm") 
sp.plot('svg')

Midwest Plot with ‘glm’ function and modified theme

结论

r 是一种非常强大的语言,用于统计分析、数据分析、机器学习、绘图和许多其他具有非常大的软件包生态系统的科学应用。然而,R 通常被认为很难学,缺乏现代计算机语言的结构,如面向对象的类、模块、lambdas 等。正因如此,许多开发人员已经开始或从 R 转向 Python。

有了 Galaaz,R 程序员几乎可以透明地从 R 移植到 Ruby,因为语法几乎是一样的,而且他们用 fastR 作为 R 引擎。根据大多数基准测试,FastR 可以比 Gnu R 快几个数量级。此外,通过使用 Galaaz,R 开发人员可以开始(如果需要的话,可以慢慢地)使用 Ruby 的所有构造和库来很好地补充 R 包。

对于 Ruby 开发人员来说,Galaaz 允许完全透明地直接使用 R 函数。如上面第二个例子所示,类 ScatterPlot 完全隐藏了 R 调用 Ruby 开发者的所有细节,此外,Galaaz 由 TruffleRuby 提供支持,也可以比 MRI Ruby 快几个数量级。

指导您的数据科学战略的规则

原文:https://towardsdatascience.com/rules-to-guide-your-data-science-strategy-cf4a4eff0e4d?source=collection_archive---------10-----------------------

作为数据科学家,我们在一个年轻的领域工作——我们应该努力向更成熟领域的最佳老师学习

许多关于企业战略的文献都过于狭隘,不适用于数据科学战略的制定。虽然企业战略文献通常专注于竞争战略,暗示对手,但更常见的情况是,作为数据科学家,你唯一的竞争对手是你自己;如果数据科学是一项运动,它看起来更像高尔夫而不是网球。

具有讽刺意味的是,军事战略文献虽然也关注击败对手,但对战略目标有着更广泛的看法,特别是当人们认识到战争往往是在战场之外而不是在战场上取得胜利的时候。因此,正如我在早些时候关于数据科学战略的讨论中解释的那样,许多军事院校用来教授战略的公式是用非常通用的术语“战略=目标+方法+手段”来构建的。这个定义的关键是目标的明智选择。

巴兹尔·利德尔·哈特爵士被认为是第一次世界大战后军事战略方面最清晰的思想家之一。在他被广泛阅读的文章《战略》中,他提出了一套八条战略准则。在接下来的内容中,我列出了六条格言(外加一条我自己发明的额外格言),它们并不是专门为了打败对手,还包括了关于它们如何应用于数据科学问题的评论(这些格言的表达方式,我非常感谢弗雷德·尼科尔斯的表述)。

当最初由利德尔·哈特提出时,这些格言的目的是巴兹尔爵士通过研究至少数百年来战争的方式而了解到的战略。数据科学出现的时间并不长,但这并不意味着我们不能或不应该学习他人如何在其他领域取得成功,并将其应用到我们自己的领域,以便取得比巴兹尔爵士研究的将军们更有效的成就——事实上,巴兹尔爵士的、*、*以下面的观察为开头,并将其归功于奥托·冯·俾斯麦:“傻瓜通过经验学习。我更喜欢从别人的经验中获益”。

格言一:量入为出

在某些方面,这应该是法律的全部,正如原始数据科学家阿莱斯特·克劳利可能会说的。在敏捷时代,学会根据需要进行调整是最重要的,但是如果有比这更重要的事情,那就是确保手段是目的的仆人,当你的计划不能让你更接近目标时,是时候制定一个新的,或者至少是改变的计划了。

格言二:时刻牢记你的目标,同时根据情况调整你的计划

数据科学家很容易陷入建模、统计和编程的琐事中。作为商业环境中的专业人士,重要的是要记住,你正在努力为客户解决问题——通常情况下,放弃针对这一特定问题的技术,选择另一种技术,会比试图将不合适的解决方案强加给问题更明智。

我们从战略的 Art Lykke 等式开始,这也意味着如果数据科学不符合目的,我们应该完全拒绝它作为一种工具。数据科学家面临着巨大的同行压力,要求他们对能够实现的目标持乐观态度。然而,请注意,在医学等更成熟的领域,专家不会不好意思告诉病人他们找错了医生,并指导病人去其他地方。

格言三:利用阻力最小的路线——只要它能把你引向任何有助于你根本目标的目标。

数据科学家很容易选择当前的工具——这不太可能是阻力最小的路线。至少,目前的工具可能也是最新的工具,与使用你以前多次使用的工具相比,你需要花费额外的精力来掌握它。

准则四:确保计划和部署都是灵活的——适应环境

数据并不像你想象的那样,直到你对它进行了分析和确认。这条格言几乎是“没有自由的预感”定理,适用于不同的环境。你最喜欢的算法或你认为最有可能成功的方法更有可能失败——拥抱失败,选择一个比你一开始拥有更多知识的新方法,然后再试一次。建立这样的预期,你将会失败于你对任务规模的估计。从最初失败的方法中吸取教训,更好地理解和解决客户的问题。

格言五:一次进攻失败后,不要沿同一路线(或以同一形式)重新发起进攻。

从上面继续,当你不可避免地失败时,确保当你失败时,你避免疯狂地重复同样的行动,同时期待不同的结果。如果一个算法看起来不起作用,不要浪费时间试图调整它,并尝试选择下一个算法来最大化方法的差异。

格言六:选择一条有多种选择的路线

知道你可能会失败意味着你选择了一种解决问题的方法,这种方法可以根据需要很容易地改变,并且在失败的情况下可以产生最大的价值。例如,避免将“黑盒”算法作为您解决问题的第一次尝试,而是选择一种方法,即使它无法实现您所追求的准确结果,也可以最大限度地揭示您的目标与其预测变量之间的关系,以便您的后续尝试可以由您在第一次尝试中所学到的内容来指导。

补充点:避免为他人工作

这最后一个不是来自利德尔·哈特,而是纯粹是我自己的发明。然而,重点是直截了当的-数据科学并不存在于真空中,数据科学团队将依靠他人的善意来获得最佳结果。因此,试着让你周围的人生活得更轻松。如果你的工作流程是一个模型被交给不同的团队去实现,理解他们的过程,并且让你的模型实现变得友好。如果你的公司有一个营销团队,你有时会为他们准备文档,那就按照他们的风格指南去做。一方面,这是礼貌,也是应该做的事情,另一方面,你不知道什么时候你会需要他们的帮助——即使不是特定的那些人,拥有乐于助人的名声会让其他人更有可能在未来想要帮助你。

当然,你也应该避免为自己工作,我上面写的不应该被视为更加努力工作的戒律。取而代之的是,对数据科学采取一种防御方法,这可以防止他人和你自己不必要的努力。

有关改进数据科学策略的更多信息,请查看我正在撰写的 leanpub 书籍“懒惰的数据科学家”。

跑或走(第 1 部分):用机器学习和核心 ML 检测运动活动

原文:https://towardsdatascience.com/run-or-walk-detecting-user-activity-with-machine-learning-and-core-ml-part-1-9658c0dcdd90?source=collection_archive---------4-----------------------

在最近六月的苹果 WWDC 会议上有很多公告。其中最引人注目的是 Core ML 框架的发布,该框架为每个开发者提供了设备上的机器学习能力。这是革命性的。

革命性意味着,在更早的时候,想要在应用程序中使用任何有点现代的机器学习模型的人只有一些不容易配置和实现的选择。核心 ML 成为在您应用程序中以“拖放”方式使用 ML 模型的唯一选择。iOS 做了大部分繁重的工作来生成表示模型本身、其输入和输出的接口。

这为每个人提供了实施端到端解决方案的机会:从收集数据和训练模型,到在 iOS 应用程序中利用该模型。

有了这个前景,我早就有的想法——自动检测体育活动——变成了现实。我决定证明一个假设,即内置于 iOS 应用程序中的预训练机器学习模型可以根据加速度计和陀螺仪的数据来分类这个人是跑步还是走路。当然,还有更多其他体育活动可以用自动化的方式检测,但对于第一次尝试,我选择了那些从人们的角度以及从传感器接收的数据中可以明显区分的活动。

Accelerometer data when the person is walking

Accelerometer data when the person is running

在调查 iOS 上已经有哪些类似的工具可用于此目的时,我发现 CMMotionActivityManager 类的 CMMotionActivity 对象可以检测设备是否在行走或跑步的人身上,或者设备是否在汽车上,甚至是在自行车上。

乍一看,这个问题似乎已经解决了,但在深入研究文档后,我意识到苹果的 Core Motion 使用了来自广泛输入源的数据,包括加速度计、陀螺仪、磁力计和计步器。

仅仅使用传感器数据的一小部分,我们能预测这个人是在走还是在跑吗?有多准确?任何机器学习模型都能够完成这项任务吗?最后,我以后还能在我的 iOS 应用中使用这种模式吗?

这些是我将在接下来几周的一系列博客文章中找到答案的主要问题。

请跟随我,看看我在收集训练数据、设计、训练和调整高精度机器学习模型并将其构建到 iOS 应用程序中时面临了哪些挑战。

阅读下一部分:

跑步或行走(第 2 部分):以正确的方式收集设备运动数据

原文:https://towardsdatascience.com/run-or-walk-part-2-collecting-device-motion-data-the-right-way-58a277ff2087?source=collection_archive---------2-----------------------

阅读上一部分: “跑还是走(第一部分):用机器学习和 Core ML 检测运动数据活动”

出于开发一个机器学习模型来准确预测用户是走路还是跑步的动机,我需要数据。快速搜索包含此类活动的公开可用数据集没有得到任何结果。剩下的唯一选择就是自己收集数据。

每个参加过任何数据科学竞赛的人都知道,数据集总是需要经过某种程度的处理,才能馈入机器学习模型。你不能错过这个阶段,否则,你的模型将会遭受缺失、扭曲的数据、异常值和其他一些问题。有时,在完成一项比赛后,回头看看投入的时间,您会意识到将近一半的努力都花在了处理数据集上!原因?数据集是基于现实生活中的数据,而现实生活中的数据在连续性、同质性或统计分布方面并不理想。

DIY 数据

当你独自负责收集数据时,事情会变得更好。从一方面来说,这是获取数据的最昂贵的方式,但是从另一方面来说,你有一个很好的机会通过以你需要的方式收集数据来节省你未来的努力。仔细思考你试图解决的问题的基础有助于找到收集数据的适当方法。

我从要点开始。如果我想知道这个人是在跑还是在走,我首先需要在人体上找到一个地方,根据传感器数据可以清楚地区分这些活动。简单地将 iPhone 放在口袋里并从那里收集数据并不是一个好的解决方案,因为每次设备可以放在不同的位置。这可能导致传感器的结果差异太大,即使是相同的活动。鉴于我收集数据的时间有限,我宁愿为了简单而牺牲数据的可变性。

收集人的活动数据的最佳选择是手腕。原因如下:

Walking: hand wrist directed to the ground, moves with low to medium velocity

Running: hand wrist directed mostly perpendicular to the ground, moves with medium to high velocity

考虑到大多数人有两个手腕,我的 2 级分类模型的数据应该以下列变化收集:

  • 走路,右手腕;
  • 走路,左手腕;
  • 跑步,右手腕
  • 跑步,左手腕;

这里的一个有效问题应该是“等等,当 Apple Watch 是一个更合适的选择时,为什么要在你的手腕上安装 iPhone?!"完全同意,但那时我还没有手机,并认为 iPhone 及其加速度计和陀螺仪将提供相同的传感器数据。

iPhone was always positioned with Home button pointing to the fingers

收藏什么?

第一个似乎很容易回答的问题,可能会把你引向错误的方向。在你的 iPhone 中有加速度计、陀螺仪、磁力计、计步器甚至气压计并不意味着从所有这些设备中收集传感器数据是有意义的。

这里一个很好的起点是一个官方的 文档,它揭示了每个传感器的能力和局限性。仔细阅读后,我意识到最有价值的数据来自两个传感器:加速度计和陀螺仪。记得吗,我想用尽可能少的数据?限制传感器的数量是这个方向的第一步。

为什么是那两个?加速度计提供了设备沿 3 个轴的速度变化,这是关于一个人如何移动他的手的重要信息。陀螺仪提供设备绕空间轴旋转的速率,这可能对区分跑步和行走活动没有太多帮助,但可能仍然有所帮助。

Sensor axes for accelerometer (left) and gyroscope (right)

原始数据还是经过处理的数据?

苹果在为不同场合提供不同格式的运动数据方面做得非常好。如果需要加速度计数据仅限于仅由用户应用于设备的加速度,在这种情况下,处理后的数据是一个有效的选项。它不包括不同形式的偏差,如重力引起的加速度。

另一方面,原始加速度计数据由您决定如何处理。这种数据是在我未来的机器学习模型中使用的完美候选。未经处理意味着数据不会因 iOS 中处理算法的实施细节而产生任何形式的偏差。这使得数据有可能在其他平台上重用,并使得在训练模型时出现难以识别的问题的风险降低。

传感器更新频率

根据硬件的不同,苹果表示加速度计和陀螺仪的最大传感器更新频率令人印象深刻的“至少 100 Hz”。很明显:你需要的关于设备移动的信息越详细,这个值就应该越高。但是,当你获得足够详细的数据时,总会有一个阈值,即使获得更详细的测量也没有意义。

如何找到一个最佳的传感器更新频率?以最大可能频率收集等效活动数据,然后是该值的 70%,然后是 40%,最后是 10%。绘制您从这些值中的每一个接收到的信号,并找到一个保持信号的重要细节并且同时具有最低传感器更新频率的图。

Data collected at 50Hz

The same data downsampled to 30Hz. Important signal details are lost.

在尝试了几个值之后,我确定 50Hz 是我要记录的活动类型的最佳传感器更新频率。

收集间隔

最初,我试图在一个“不受控制”的环境中收集数据。我想我会步行穿过这个城市,无休止地记录步行活动的数据。跑步也是一样——我只是用我的常规慢跑来记录数据。

然而,现实表明,在像城市这样的真实环境中连续记录活动是一个非常糟糕的想法,在那里你的运动经常被十字路口、交通灯和其他人打断。在 30 分钟的步行过程中获得的数据充满了来自干扰的噪音。我尝试应用一些技术来删除无关的数据样本,但是没有一个技术能让我确信我保留了原始数据的特征。

解决方案是大幅缩短数据收集间隔。当我评估仅持续 10 秒钟的记录会话时,我发现其中只有 3–4%包含异常值。与连续记录会话后 45%的数据样本包含噪声相比,这是一个明显的改进,还有很长的路要走。

用于数据收集的应用程序

我需要一个应用程序来收集数据,并在将数据上传到处理样本的环境之前临时存储数据。

对应用程序可能的功能保持务实,我避免开发花哨的东西,专注于一个目标——以固定的时间间隔可靠地收集数据,并将其存储在应用程序中。

关于我希望多长时间收集一次数据样本(50Hz)和多长时间(10 秒间隔)的主要问题已经得到了回答。我必须实现一个应用程序来收集数据样本,并向它们提供元信息,如日期和时间戳、用户名和记录发生的手腕。录制的会话存储在*中的数据录制应用程序的容器中。csv 格式,然后从中提取并复制到我的电脑上。

此外,我在固定的时间间隔内实现了触觉反馈,以便通知自己记录仍在发生,并且我不会浪费时间去某个地方而不实际收集数据。

有两种记录模式:手动和连续。我在 95%的时间里使用第二个,它不需要我每 10 秒钟就开始新的录音,而是自动为我做这件事。

Simplest possible UI

根据点击的是“行走”还是“跑步”,收集的数据会相应地标记在结果*中。csv 文件。

最终数据集

在总共收集了大约 5 个小时的行走和跑步数据后,我可以得到几乎相同数量的每一类数据,包括左/右手腕的变化。这产生了具有以下结构的 88588 个数据样本:

为了证明我收集的数据集是健壮的,并且不会遭受典型的数据集问题,我将它上传到 Kaggle 并让其他人查看和分析它。

我也做了自己的分析,以确保在这个数据集上训练机器学习模型时,我不会面临难以分析的问题。

事实上,Kaggle 团队展示了数据集,这让我相信记录这些数据所花费的时间是值得的。当然,最大的收获是,在我收集数据的几周内,我可以减轻一些体重。

请关注我,了解我对这个数据集应用了哪些机器学习技术,以 99%以上的准确率预测用户活动。

阅读下一部分:

图像/视频演职员表:

  • https://docs-assets . developer . apple . com/published/96e 9d 46 b 41/ab 00 c 9d 5-4f3d-475 b-8020-95066068 a18d . png
  • https://docs-assets . developer . apple . com/published/96 e9 d 46 b 41/C9 b 606 b 2-9a 52-487 e-8385-e 710 FFA 1 ce 5f . png
  • Videezy.com

跑或走(第 3 部分):用于检测运动活动的准确度> 99%的神经网络分类器

原文:https://towardsdatascience.com/run-or-walk-part-3-99-accuracy-neural-network-classifier-for-detecting-motion-activity-675e16af4a7d?source=collection_archive---------3-----------------------

阅读前几部分: ——跑还是走(第一部分):用机器学习和 Core ML 检测运动数据活动 ——跑还是走(第二部分):以正确的方式收集设备运动数据

前一部分中收集了大量的行走和跑步数据后,我准备进一步利用这些数据。我的目标是设计和训练一个机器学习模型,根据这些数据准确预测用户活动的类型。

框架和模型选择

思考这个任务选择什么机器学习框架,我参考了 Core ML 支持的框架列表。这极大地缩小了候选人的范围,因为只有少数候选人受到本地支持。

每个试图用机器学习解决问题的人都面临着多样性的挑战。可以使用的模型种类繁多。选择最合适的一个是至关重要的,因为通常你有时间和资源去评估其中的几个,而不是全部。

如今,围绕深度学习的宣传是巨大的,当你为你的项目考虑完美的模型时,你不能忽视它。嗯,可能我不需要一个真正深度的神经网络来解决这个问题——我想——但至少这将是朝着正确的方向迈出的一步。“浅层”人工神经网络也因其在解决多类分类问题中的效率而闻名。

考虑到 Core ML 中的前馈神经网络仅受 Keras 框架支持,我的选择很简单。这个框架是为快速实验而设计的,可以在 TensorFlow、CNTK 或 Theano 上使用,因此对我来说是一个完美的选择。我选择了 TensorFlow backend for Keras,因为我已经用它体验过了,并且很容易理解它的概念。

事先说一下我使用这种设置的经历,我可以确认它允许我快速试验,并使我专注于设计而不是模型的实现。

模型架构:输入层

在前馈神经网络中,一切都从输入层开始。这是一个休息时间,再次查看我的数据,以便我可以定义输入层中输入神经元的数量。

我的数据集的初始格式如下:

这是一个很好的时间点来思考如何在理论上有可能根据传感器数据预测运动活动的类型?基于单个样本来做是不可行的,但是考虑多个数据样本将使得检测模式成为可能。

一个普通人在走路或跑步时做一次自然的手腕运动需要多少时间?1 到 2 秒之间。考虑到这一点,训练数据是以大约 5Hz 的频率收集的,我只需要为每次学习迭代选择大约 10 个样本。这将给我一个 10 乘 6 的矩阵作为我的神经网络的输入

然而,这是不可接受的,因为前馈神经网络的输入层必须是列矩阵,而不是 mn 矩阵。这意味着在一次学习迭代中结合来自所有传感器的数据的想法是不可实现的,因此,我必须使用 6 个模型:2 个传感器*每个传感器 3 个轴。

当使用这些模型来预测运动活动类型时,我可以应用集成技术来评估它们的输出并生成单个预测。

这种方法要求我将初始数据集转换成 6 个独立的数据集,每个数据集代表一个加速度计或陀螺仪轴,包含 12 个传感器样本(约 2 秒。观察时间)。这个“神奇的数字”是从后面几个阶段的大量实验中得出的,我试图在模型的准确性和输入的数量之间找到一个平衡。

The format of one of the final datasets: rows represent continuous sensor measurements equivalent to ~2 sec. of observation. Column ‘y’ represents a label for each row.

模型架构:隐藏层

我决定从一个只包含一个隐藏层的神经网络开始,评估它的性能,如果需要的话,进一步增加额外的隐藏层。这种从基本模型开始,然后逐渐增加复杂性的方法保证了我在训练模型时不会出现难以识别的问题。

只有一个隐藏层导致了 92.5%的准确率,再增加一个隐藏层导致了 97.2%的准确率,而具有 3 个隐藏层的神经网络最终产生了 99.2%的准确率。添加 3 个以上的隐藏层对精确度没有影响或者降低了精确度。我在这里和所有进一步的实验中对测试数据进行了 10 重交叉验证,以得出准确的数字。

这是有争议的,是否这样的神经网络可以被认为是一个“深”的,但最重要的是我能够找到一个最佳的隐藏层数。

模型架构:其他超参数

我试图借助网格搜索来调整其他一些可用的超参数:隐藏层中神经元的数量及其激活函数。搜索过程表明,预测精度最高的网络在每个隐层有 15 个神经元,并校正线性单元激活函数。

我选择分类交叉熵损失函数是因为它能够独立于定义的学习速率提高网络的学习速度。我选择 ADAM optimizer 作为我的模型,是因为它的计算效率很高,并且能够为我试图解决的问题提供足够的结果。

数据量明显减少,但精确度几乎相同

当我准备好我的神经网络的架构时,我想证明关于网络需要精确执行的数据量的下限在哪里的假设。

关于数据量,我理解的是预测单个例子时,馈入网络的数据样本数。还记得吗,我提到过 12 这个数字(~2 秒的观察)?我通过比较使用较低和较高数据量时网络的准确性选择了这个数字:

  • 17 个样本:99.32%
  • 12 个样本:99.23%
  • 6 个样本:97.93%

即使当 12 个样本选项的精度最低低于 17 个样本时,它也会大大减少网络消耗的输入数据量,从而降低训练网络所需的计算能力。令人印象深刻的是,每次预测 6 个样本(约 1 秒。观察)允许神经网络也相当准确地执行!

我决定坚持使用 12 个样本,因为它为模型提供了更多的数据以更好地进行归纳,此外,允许我从每个传感器/轴的总共 37777 个数据样本中获得 7387 个样本的数据集。

证明另一个假设

不同的手腕,没有训练数据

如果我只在一只手腕上收集我的所有训练数据,在上面训练我的模型,然后询问是否从另一只手腕预测活动类型,会怎么样?一个有趣的问题,我没花多少时间就找到了答案。

事实证明,神经网络只能在 91%的情况下预测正确的活动。嗯,这不是一个惊人的结果,但它仍然显示了一个相对简单的神经网络可以很好地检测数据中的模式,而不管它的符号!

陀螺仪 Y 轴的可预测性低

专门根据陀螺仪 Y 轴数据训练的模型“只有”85%的预测精度。这证明了当人们试图预测行走或跑步时,该轴对整体准确性没有太大贡献:人的手腕不会围绕该轴以强烈的模式做出反应。或者至少我移动我的手,这样陀螺仪的 Y 轴就没有机会被用于可靠的预测。

其他人的结果

我从 Kaggle 上的贡献者那里获得了有趣的见解,他们使用了我的全部数据集:无论他们使用什么模型或方法,准确性总是最高的!

在深入研究了他们的实现后,我意识到他们都是在训练时将数据集“按原样”输入到他们的模型中——一个样本接一个样本,而没有理解时间序列数据中的单个样本在检测整个序列的模式方面毫无价值。

本应使用的数据集可能看起来类似于这个

这是一个很好的提醒,不要在没有花时间去理解问题的基础之前就去解决它。

下一步是什么?

如果你对这篇文章中描述的模型在现实世界中的样子感兴趣,你可以在 Kaggle 上找到它

请继续关注本系列的最后一篇文章,在这篇文章中,我将展示神经网络是如何在 Core ML 的帮助下导入并用于 iOS 应用程序的。

阅读下一部分:

跑还是走(第 4 部分):在 iOS 中使用 Keras 神经网络分类器与核心 ML

原文:https://towardsdatascience.com/run-or-walk-part-4-using-keras-neural-network-classifier-in-ios-with-core-ml-a29723ab3235?source=collection_archive---------1-----------------------

阅读前几部分: -跑或走(第一部分):用机器学习和核心 ML 检测运动数据活动 -跑或走(第二部分):以正确的方式收集设备运动数据-跑或走(第三部分):> 99%准确率的神经网络分类器用于检测运动活动

终于,我走到了这段旅程的最后一步。现在是时候利用我们在第三部分中训练的模型在 iOS 应用中预测用户的运动活动了。

保存 Keras 模型

首先,我必须将训练好的模型序列化到 JSON 中,并保存它的权重。

Keras 提供了一个简单的 API 来实现这一点:

将模型的权重保存到磁盘上的*.h5 文件的简单方法相同:

将 Keras 模型转换为核心 ML

现在是时候将我保存的模型转换成 Core ML 格式了。由于我有一个 Keras 模型神经网络,我可以使用苹果的核心 ML 工具 Python 包,它为我完成了转换模型的工作:

在 iOS 应用程序中使用转换后的核心 ML 模型

将核心 ML 模型导入到我的 iOS 应用程序就像拖放到 Xcode 项目一样简单。我刚才用于设置模型元数据、输入和输出描述的值现在可以在 Xcode 中的核心 ML 模型窗口中看到。

Core ML model window in Xcode

由于 Xcode 已经为导入的 accel_x_model Core ML 模型自动生成了一个自定义 API,我已经准备好为模型提供传感器数据并读取其预测。

终点线

看到检测运动数据活动的想法如何演变成这样一个有趣的项目真的很酷,这不仅需要我学习关于机器学习及其在 iOS 中的 Core ML 应用的新知识,还需要我在为模型收集数据时有机会减肥。

iOS app detects motion activity in real time

像苹果的 Core ML 这样一个在移动应用中应用机器学习的简单方法,会有什么新的可能性,这真是令人惊讶!

关注我,了解我在机器学习和 iOS 方面的最新实验!

使用 Python 中的掷骰子数据运行卡方测试

原文:https://towardsdatascience.com/running-chi-square-tests-in-python-with-die-roll-data-b9903817c51b?source=collection_archive---------2-----------------------

在本世纪初的某个时候,我赶上了棋盘游戏热潮。大约每个月,我都会在 BoardGameGeek 、【BGG】、评分最高的游戏中搜寻新的桌游来购买。BGG 网站上有成千上万的棋盘游戏,很多都有评论和批评。我最喜欢的策略游戏不是一个不寻常的选择。相反,它目前是 BGG 有史以来排名第四的游戏,之前排名第一。那个游戏是暮光之城之战

《暮光之城之战》是一款以“冷战”为主题的卡牌驱动 2 人策略游戏。从某些方面来说,这感觉像是国际象棋和扑克的结合。一方扮演美国,一方扮演苏联。这个游戏和真正的冷战有着相同的偏执感,因为你必须不断地猜测你的对手可能有哪些牌,以及他们如何用这些牌来伤害你。

虽然技能在 TS 中非常重要,但运气在结果中也起着重要作用。该游戏包括政变、重组、战争卡和太空竞赛,所有这些都由掷骰子决定。

The Soviets never foresaw The Giant Cat Invasion from the Middle East

几年前,在一次成功的众筹活动之后,一个在线版本的《暮光之城之战》在 PC 和 MAC 上发布了(Steam 上有)。玩了几百个在线游戏后,我决定尝试创建一个运气测量系统来评估我自己的结果。在这个过程中,我开始收集“政变”和“战争卡”的掷骰结果。这就是事情变得有趣的地方:我的掷骰子样本有令人惊讶的分布。

279 卷之后,我的平均卷数是 3.254。303 滚之后,我对手的平均分是 3.855。我想知道这个分布有多不寻常,所以我用 Python 进行了一些卡方测试。

了解卡方检验

然而,在我们看这些测试之前,我将更详细地解释卡方。

卡方统计检验用于确定预期分布和实际分布之间是否存在显著差异。它通常用于教育程度、肤色或性别等分类数据。

掷骰子是适合卡方检验的数据的一个很好的例子。如果我们掷一个标准的六面骰子一千次,我们知道每个数字出现的概率大约是 1/6(即 16.66667%)。卡方检验有助于确定骰子是否是“公平”的,或者掷骰发生器(如软件中使用的那些)是否产生“随机”结果。

然而,在“预期分布”已知的情况下,掷骰子就是一个变量的例子。情况并非总是如此。有时候,我们的‘预期分布’是通过数据估算出来的。

假设我们不知道掷骰子的预期频率。我们必须通过数据样本来估计预期的频率。让我们做几个样本来确定每次滚动的频率。我决定手动做 4 个骰子滚动的样本(即实际骰子),前 3 个样本各 35 个,最后一个样本 45 个。这些样本比我们想要的要小,但是我想给我们一些真实的数据。这是我的面包卷分布,四个样品用字母“a”、“b”、“c”和“d”表示。

根据我们对概率的了解,对于 150 次掷骰子,我们应该预计每个数字出现大约 25 次(即 150 次的 1/6)。我们可以看到,1、5 和 6 都出现了这种情况,但 4 出现的次数比预期的多,2 和 3 出现的次数有点少。这可能是由于我们的样本量相对较小(见"大数定律"),但我们会处理它。

让我们对这个数据集的列联表中的变量进行独立的卡方检验。首先我要输入数据。

import numpy as npa1 = [6, 4, 5, 10]
a2 = [8, 5, 3, 3]
a3 = [5, 4, 8, 4]
a4 = [4, 11, 7, 13]
a5 = [5, 8, 7, 6]
a6 = [7, 3, 5, 9]dice = np.array([a1, a2, a3, a4, a5, a6])

然后,我使用 SciPy Stats 库运行测试

from scipy import stats

stats.chi2_contingency(dice)

不幸的是,尽管它是一个非常有用的工具,但 SciPy 并没有以最漂亮的方式提供结果。

我会解释这一切意味着什么。第一个值(16.49)是卡方统计。跳到输出中的第三个数字;这就是“自由度”这可以通过将行数减 1,然后将该结果乘以列数减 1 来计算。

在这种情况下:

行数= 6[模具辊 1–6]

列= 4[样本]

所以我们用(6–1)乘以(4–1)得到 15 个自由度。

利用卡方统计和自由度,我们可以找到 p 值。p 值是我们用来确定显著性(或本例中的独立性)的值。根据测试的不同,我们通常会在 0.05 或 0.01 处寻找一个阈值。如果我们得到一个低于阈值的 p 值,我们的测试是有意义的(即我们拒绝零假设)。

出于我们的目的,我们将使用 0.01 作为阈值。在这个特殊的例子中,p 值(输出中的第二个数字:0.3502)远为 0.01,因此我们没有达到统计显著性的阈值。

既然我已经解释了每件事的含义,我们可以在 SciPy 中创建更易读的输出代码。

chi2_stat, p_val, dof, ex = stats.chi2_contingency(dice2)print("===Chi2 Stat===")
print(chi2_stat)
print("\n")print("===Degrees of Freedom===")
print(dof)
print("\n")print("===P-Value===")
print(p_val)
print("\n")print("===Contingency Table===")
print(ex)

这将产生更加一致的输出:

最后,输出末尾的数组是列联表,其中包含基于所有样本的期望值。注意,在这种情况下,我们的列联表产生的值,在某些情况下,与我们所知道的掷骰子的期望值相差甚远。这是因为我们使用的样本太少,无法准确测量总体。

运行大样本以获得预期的人口分布

我们可以运行一个更大的样本,看看这种方法如何更好地工作。由于我不愿意手动掷骰子数千次,我们将使用 Python 来做这件事。我们需要 np.random.randintnp.unique 。我做了 5 个样本,每个样本 1000 个骰子点数。

r1 = np.random.randint(1,7,1000)
r2 = np.random.randint(1,7,1000)
r3 = np.random.randint(1,7,1000)
r4 = np.random.randint(1,7,1000)
r5 = np.random.randint(1,7,1000)

然后通过 np.unique 保存结果。

unique, counts1 = np.unique(r1, return_counts=True)
unique, counts2 = np.unique(r2, return_counts=True)
unique, counts3 = np.unique(r3, return_counts=True)
unique, counts4 = np.unique(r4, return_counts=True)
unique, counts5 = np.unique(r5, return_counts=True)

现在,我们结合我们的数组来运行 stats.chi2_contingency:

dice = np.array([counts1, counts2, counts3, counts4, counts5])

让我们进行测试。

chi2_stat, p_val, dof, ex = stats.chi2_contingency(dice)

这是结果。

注意我们的列联表现在产生了一个更均匀的期望分布。它仍然稍有偏差(在 1,000 个掷骰子的样本中,我们预计每个数字会出现大约 166.7 次),但我们已经非常接近这个分布了。

我决定再运行一次测试,这次使用 10,000 个骰子点数的 5 个样本。

我们可以看到我们的分布更加接近已知的总体分布(每个数字的概率为 16.667%,即样本中 10,000 卷中的 1,666.7)。有趣的是,由于我们知道真实的期望分布,我们可以看到样本如何让我们估计总体分布。

暮光之城奋斗骰子卡方测试

现在,让我们进入我们的在线暮光之城奋斗骰子数据。

对于我们的实际测试,我们不需要列联表。我们知道期望分布。对于 6 面骰子,每个数字预计出现的时间约为 1/6。既然我们知道预期分布,我们可以使用 scipy.stats.chisquare 而不是 chi2_contingency。

对于我的暮光之城奋斗骰子数据,我有两个样本:我自己的掷骰子和我对手的掷骰子。我们的零假设是骰子是随机分布的(因此是均匀分布的)。

我的数据是,我滚了 279 次。我们除以 6,得到期望的分布(每个数字 46.5)。运行 scipy.stats.chisquare 时,要注意确保参数的顺序正确;否则,你会得到不准确的结果。第一个参数(f_obs)是“实际结果”,而第二个参数(f_exp)是“预期结果”。

my_rolls_expected = [46.5, 46.5, 46.5, 46.5, 46.5, 46.5]
my_rolls_actual =  [59, 63, 37, 38, 32, 50]stats.chisquare(my_rolls_actual, my_rolls_expected)

运行这个测试,我们得出 p 值为 0.0037。

这低于 0.01,具有统计学意义。这意味着如果骰子真的是随机的,我们只有 0.4%的机会看到这个结果。

接下来让我们看看我的对手掷骰子。我的对手掷出了 303 次。我们再一次除以 6,得到 50.5 的期望分布。我们与实际分布进行比较。

opp_rolls_expected = [50.5,50.5,50.5,50.5,50.5,50.5]
opp_rolls_actual =  [39,39,46,54,53,72]stats.chisquare(opp_rolls_actual, opp_rolls_expected)

我们发现了类似的结果。

我们的 p 值是 0.0097,也低于 0.01,这表明如果掷骰子是真正随机的,我们观察到这种分布的概率略低于 1%。

虽然我已经有趣地注意到了掷骰子中的奇怪模式(我之前已经放弃了“观察偏差”),但我实际上对这些结果有点惊讶。对于我们 2 个随机样本中的我的掷骰子和对手的掷骰子,我们可以拒绝骰子是真正随机的无效假设。

这很有趣,我决定继续收集数据,看看我是否能在未来复制这些结果。不幸的是,我可能还需要几个月的时间来构建一些更有意义的数据样本。

结论

卡方是比较涉及分类数据的结果的一个很好的工具。我们可以看到样本是如何偏离预期分布的。Python 的 SciPy 库为运行卡方测试提供了很好的工具。

更多资源

为了更好地了解卡方,我推荐可汗学院的优秀系列视频

在 15 分钟内在谷歌云平台上运行 Jupyter 笔记本

原文:https://towardsdatascience.com/running-jupyter-notebook-in-google-cloud-platform-in-15-min-61e16da34d52?source=collection_archive---------0-----------------------

最近,当我使用卷积神经网络做计算机视觉的研究项目时,我发现我的 8GB RAM 笔记本电脑毫无用处。我花了一个小时才从一个时代学会。因此,我没有花 1500 美元买一台新的基于 GPU 的笔记本电脑,而是在谷歌云上免费完成了这项工作。(谷歌云提供 300 美元信用,我有 3 个 gmail 账户和 3 张信用卡:D)

所以,让我们不要再浪费时间,直接在 GCP 运行 jupyter 笔记本。

第一步:在谷歌云中创建一个 300 美元的免费账户

在这一步,你必须输入你的支付信息并验证你的账户。这是最简单的一步。如果这一步你失败了,合上你的笔记本电脑,想想你的人生将走向何方。

步骤 2:创建新项目

点击下图中的三个点,然后点击+号创建一个新项目。

步骤 3:创建一个虚拟机实例

单击左上角的三行,然后在计算选项中,单击“计算引擎”

现在,单击“创建新实例”。命名您的实例,选择 zone 为“us-west1-b”。选择您的“机器类型”。(我选的是 8v CPUs)。

选择您的启动磁盘为“Ubuntu 16.04 LTS”。在防火墙选项下勾选“http”和“https”(非常重要)。然后,选择磁盘选项卡,取消选中“删除实例时删除引导磁盘”。

如果您点击“自定义”,您将能够找到使用 GPU 的选项。您可以在 2 个 NVIDIA GPUs 之间进行选择。

一些防火墙设置:-

现在点击“创建”,您的实例就准备好了!

您的新 VM 实例应该看起来像这样。记下外部 IP。

重要提示:完成后,不要忘记通过点击上图中的三个点并选择停止来停止 GPU 实例。否则 GCP 会继续按小时收费。

步骤 4:将外部 IP 地址设为静态

默认情况下,外部 IP 地址是动态的,我们需要使它成为静态的,以使我们的生活更容易。单击左上方的三条水平线,然后在“网络”下,单击“VPC 网络”,然后单击“外部 IP 地址”。

将类型从短暂更改为静态。

步骤 5:更改防火墙设置

现在,点击“网络”下的“防火墙规则”设置。

点击“创建防火墙规则”并参考下图:

在协议和端口下,您可以选择任何端口。我选择了 tcp:5000 作为我的端口号。现在点击保存按钮。

步骤 6:启动您的虚拟机实例

现在启动您的虚拟机实例。当您看到绿色勾号时,单击 SSH。这将打开一个命令窗口,现在你在虚拟机内。

第七步:安装 Jupyter 笔记本和其他软件包

在 SSH 终端中,输入:

wget [http://repo.continuum.io/archive/Anaconda3-4.0.0-Linux-x86_64.sh](http://repo.continuum.io/archive/Anaconda3-4.0.0-Linux-x86_64.sh)
bash Anaconda3-4.0.0-Linux-x86_64.sh

并按照屏幕上的说明进行操作。默认设置通常很好,但是对于最后一个关于将安装位置添加到 PATH 的问题,回答是:

Do you wish the installer to prepend the 
Anaconda3 install location to PATH 
in your /home/haroldsoh/.bashrc ? 
[yes|no][no] >>> yes

要立即使用 Anaconda,请使用您的 bashrc:

source ~/.bashrc

现在,安装其他软件:

pip install tensorflowpip install keras

步骤 8:设置虚拟机服务器

打开到您的虚拟机的 SSH 会话。检查您是否有 Jupyter 配置文件:

ls ~/.jupyter/jupyter_notebook_config.py

如果不存在,请创建一个:

jupyter notebook --generate-config

我们将在您的 Jupyter 配置文件中添加几行内容;该文件是纯文本的,所以您可以通过您喜欢的编辑器(例如,vim、emacs)来完成。确保将端口号替换为您在步骤 5 中允许防火墙访问的端口号。

c = get_config()
c.NotebookApp.ip = '*'
c.NotebookApp.open_browser = False
c.NotebookApp.port = <Port Number>

它应该是这样的:

步骤 9:启动 Jupyter 笔记本

要运行 jupyter 笔记本,只需在您所在的 ssh 窗口中键入以下命令:

jupyter-notebook --no-browser --port=<PORT-NUMBER>

一旦运行该命令,它应该会显示如下内容:

现在,要启动您的 jupyter 笔记本,只需在浏览器中键入以下内容:

http://<External Static IP Address>:<Port Number>

其中,外部 ip 地址是我们设置为静态的 ip 地址,端口号是我们允许防火墙访问的地址。

恭喜你!您成功地在 GCP 上安装了 jupyter 笔记本!

我们连线:https://www.linkedin.com/in/aankul

在媒体上跟随我:【https://medium.com/@aankul.a

注意——看在上帝的份上!不要忘记停止虚拟机实例!!

编辑:
所有面临'
ERR _ CONNECTION _ TIMED _ OUT'错误的人。请在评论中尝试 庸碌口才的解决方案。

运行随机森林?使用此代码检查特性的重要性

原文:https://towardsdatascience.com/running-random-forests-inspect-the-feature-importances-with-this-code-2b00dd72b92e?source=collection_archive---------2-----------------------

A Random Forest | FPhoto by Robert Bye on Unsplash

随机森林和其他集成方法是一些数据科学任务的优秀模型,尤其是一些分类任务。它们不像其他方法那样需要太多的预处理,并且可以接受分类变量和数值变量作为输入。简单的决策树不是很健壮,所以集成方法运行许多决策树并聚集它们的输出进行预测。该过程控制过度拟合,并且通常可以产生非常健壮、高性能的模型。随机森林和其他一些 boosting 方法是简单的现成模型,我经常在建模过程的早期使用它们来查看它们如何处理我的数据。此外,它们还有一个非常有用的特性,叫做特性重要性。

这些方法最常用于预测,但是查看特征重要性可以让您了解哪些变量在这些模型中影响最大。您可以使用该信息来设计新的功能,删除看起来像噪音的功能,或者只是在您继续构建模型时通知您。

决策树以及基于决策树的集成方法通过将数据分成子集来工作,这些子集主要属于一个类别。该树将继续构建不同的子集,直到它理解并表示变量与目标的关系。提升集成树更进一步,从错误中学习,迭代地调整树以更好地分类数据。所有种类的树方法都是通过数学方法来计算它们的分裂,确定哪一个分裂将最有效地帮助区分类。因为这是他们的方法,所以这些模型的 sklearn 实例有一个.feature_importances_属性,它返回每个特性在确定分割时的重要性的数组。

查看这些会非常有帮助,但是.feature_importances_属性只是打印一个数字数组。它不会告诉你哪些数字对应哪些变量。我将运行一段代码,这段代码将在一个日期框中返回特性的重要性以及它们各自的变量名。

这是我将要使用的数据集。我曾在其他帖子中使用过这套工具,所以你可能会认出它。这是银行营销数据集,在这里可以从 UCI 机器学习资料库获得。看一看:

任务是对银行在营销活动中的哪些目标将认购新的定期存款进行分类。以下是运行随机森林模型的代码:

## Import the random forest model.
from sklearn.ensemble import RandomForestClassifier 
## This line instantiates the model. 
rf = RandomForestClassifier() 
## Fit the model on your training data.
rf.fit(X_train, y_train) 
## And score it on your testing data.
rf.score(X_test, y_test)

如您所见,这很容易实现。现在谈谈特性的重要性。下面的代码片段将从模型中检索特性的重要性,并将它们制作成数据帧。

import pandas as pd
feature_importances = pd.DataFrame(rf.feature_importances_,
                                   index = X_train.columns,
                                    columns=['importance']).sort_values('importance',                                                                 ascending=False)

运行该代码将得到以下结果:

现在,您可以很容易地看出哪些功能对您的模型很重要,哪些不重要。尽情享受吧!

俄罗斯虚假推文可视化

原文:https://towardsdatascience.com/russian-fake-tweets-visualized-6f73f767695?source=collection_archive---------6-----------------------

Fake Tweet Cloud

合著者:大卫·凯斯

随着俄罗斯调查扭曲了总统选举的热情,以及臭名昭著的脸书/剑桥分析丑闻仍然占据国内每日头条,我们清楚地看到,“假新闻”和俄罗斯用户仍然普遍存在,但概念模糊。这些假用户伪装成谁?这些假用户是怎么忽悠人的?他们是如何影响人们的?因此,凭借我们在自然语言处理、数据可视化方面的背景,以及对技术和政治相结合的兴趣,用 Python 和 Plotly 检查假俄罗斯用户的 Tweet 数据是很自然的。特别是,我们分析了:

用户和推文概述

  1. 这些假冒用户的身份——姓名和描述
  2. 当假账户被创建的时候
  3. 当虚假账户在推特上最活跃的时候
  4. 这些报道涵盖了哪些主题

大多数成功(或不成功)用户的案例研究

  1. 推特速度
  2. 推特极性
  3. 推特主观性

数据

NBC 新闻发布了超过 20 万条推文的数据库,推特将其与 2016 年美国总统大选期间与俄罗斯相关的账户的“恶意活动”联系在一起。这些账户,作为大型网络的一部分,协同工作,发布了数十万条煽动性的推文。这里的数据可以找到

Figure 1: Joined User and Tweet Data Provided by NBC

Figure 2: Example of a (non-fake) Twitter Account with Highlighted Description and Tweet

现在我们有了数据,让我们开始分析:

这些假冒用户是谁?

Figure 3: First and Last “Names” of the Users

如果我们看看我们的假用户的面值,我们可以看到有三个不同类别的假帐户名称。第一个组合由美国发音的名(如“Chris”、“Rick”或“Jeremy”)和美国发音的姓(如“Green”、“Roberts”或“Cox”)组成。第二个组合由正式的新闻来源组成,如“纽约时报”或“今日亚特兰大”。最后,第三种组合由纯粹的外国名字组成。从这一点上,我们可以看到,仅仅根据名字很难判断哪些账户是假的,因为它可能是任何普通人、新闻网站或无法识别的名字。

他们的简介是什么?

Figure 4: Topics Within the Descriptions of Fake Users

创建 Twitter 账户的一个独特之处在于,你可以选择简单描述自己是谁。用户经常发布他们的总结和意识形态给其他人看。具体来说,上图显示了一个与虚假账户相同的话题——宗教。通过使用诸如“上帝”、“InGodWeTrust”和“GodBlessAmerica”这样的词,这些虚假账户可以与一大群人联系起来。其他 bios 包括黑人生活问题主题、官方新闻声音描述(如“体育”、“天气”和“官方”)以及外国主题。因此,通过快速地(如果不是立即地)与这个虚假用户相关联,用户更有可能关注或同意虚假账户的推文。更多关于这种相似吸引现象的信息可以在这里阅读

它们是什么时候制造的?

Figure 5: Russian Fake Accounts Created from 2009 to 2017

在被认为是假俄罗斯账户的 454 个账户中,我们可以看到假账户的创建始于 2009 年,并在 2013 年达到创建高峰,然后在 2017 年初慢慢减少。有趣的是,这意味着大多数虚假账户是在 2016 年总统选举前几年创建的,可能是为了在选举前引起我们读者的冲突和分裂。

他们来自哪里?

我们查看了假冒用户的来源,发现在 454 个值中,大约有一半的值丢失了。在列出的 287 个地点中,124 个被列为某种形式的“美国”,68 个被列为美国的大型大都市(即:旧金山、纽约、亚特兰大、洛杉矶),37 个值在外国,其余 58 个值是虚构的,如“位于幸福健康的拐角处”或“沿街的街区”。因此,由于数据大部分缺失并且很可能是假的,我们选择不进一步分析数据。

他们的影响力有多大?

Figure 6: Followers vs. Number of Tweets of Fake Accounts

从高层次来看,我们可以看到推文的数量随着关注者的数量而增加。这是有道理的,因为这些假账户正在利用他们在社交媒体上的受欢迎程度来接触和影响更多的人。其中一个著名的虚假用户是臭名昭著的 Jenna Abrams 账户,其种族主义、有争议和虚假的推文一度被主流媒体报道。在这一点上,可以肯定地说,这些推文肯定对大众有影响。

他们什么时候发布?

Figure 7: Heat Map of Fake User Tweet Activity

从上面的热图中,我们可以看到,假用户主要在一年中的后几个月(即:8 月、9 月、10 月、11 月和 12 月)的周日和周二发帖。因此,我们可以预料这不是偶然的;当下半年选举和其他重大事件发生时,假冒用户明白他们的内容在周末而不是工作日到达更多的个人。

他们在说什么?

Figure 8: Topical Modeling of Tweet Content

类似于对虚假用户的描述,我们看了一下实际 tweet 内容中包含的主题。在上图中,我们可以看到,黑人生活问题和其他种族问题是俄罗斯报道的一个主题,其中包括“警察”、“黑人生活问题”、“犯罪”等词,以及圣贝纳迪诺的枪击事件,特别是关于罪犯是少数族裔的问题。用户关注的其他话题包括希拉里·克林顿的私人电子邮件服务器、ISIS、支持特朗普的口号、对选举辩论的诽谤以及校园枪击事件。这些令人心酸和受欢迎的事件是一个特别容易的话题,虚假的报道可以添加他们的宣传观点,因为个人已经愤怒了,并对如何对这些事件做出反应产生了分歧。

案例研究—深入了解前 20 名用户

我们现在知道了典型的假账户是什么样的,但是一个成功的(或者不成功的)俄罗斯假账户是什么样的呢?他们是如何获得关注的?从图(散点图)中,我们看到了关注者数量和推文数量之间的正相关关系。因此,下面的图表从速度、情绪和主观性的角度考察了他们的推特行为,随着时间的推移,前 20 名被关注的虚假俄罗斯账户。

推文速度

Figure 9: Number of Tweets Tweeted by Fake Accounts

就纯粹的推文量而言,我们可以看到假账户几乎不存在的趋势,直到 2016 年 6 月左右,推文量急剧增加——在 2016 年 10 月达到顶峰。2016 年 11 月(选举月)后,推文数量下降,2016 年 12 月左右最后一次复苏,然后回到几乎不活跃的状态。这种令人担忧的趋势显示了虚假账户的机会主义行为,在选举热情最紧张和最重要的时刻发布推文。

推特情绪和主观性

下图是前 20 名被关注用户所发推文的平均情绪和主观性。在推文中,情绪被定义为一种态度、思想或判断。特别是,可以通过使用 Textblob 包来分析推文的情绪,负面情绪推文的得分为-1,正面情绪推文的得分为+1。最后,推特环境中的主观性通常被视为给定推特的固执己见程度。在 Textblob 中,分数从 0 到 1 不等,0 代表非常客观,1 代表非常主观或固执己见。

Figure 10: Average Sentiment and Subjectivity of Top 20 Followed Users

时间序列点分析

Figure 11: Time Series Tweets with Hash Tags

利用后见之明的力量和美国时事的维基百科,我们可以看到一些值得注意的峰值与什么有关:

2016 年 8 月 4 日:散列标签#obamaswishlist 的峰值,这些帖子是关于奥巴马“想要”的稀奇古怪和被认为虚伪的物品

2016 年 8 月 17 日:散列标签#trumpsfavoriteheadline 的峰值,这些是关于唐纳德·特朗普将支持的讽刺性标题的推文

2016 年 9 月 28 日:# ihavearighttoknow 通过虚假账户了解希拉里·克林顿的电子邮件

2016 年 10 月 5 日:#ruinadinnerinonephrase 实际上被视为政治支持和非政治支持,有些人提到了希拉里·克林顿,而其他人则利用这个标签制作了迷因

2016 年 10 月 17 日:#makemehateyouinonephrase,另一个被视为模因文化或政治制度一部分的哈希标签运动

2016 年 11 月 14 日:# reallifemagicspells 用于参考黑人生活问题和特朗普的家人

2016 年 12 月 7 日:#idrunforpresidentif“我早知道我需要毫无经验”和其他关于总统选举的讽刺性评论

也许巧合与否,最初的峰值都与同时使用标签嘲笑总统和总统候选人的虚假账户有关。这些推文显然是基于政治的,实际候选人的名字被删除了。然而,随着时间的推移,这些推文之间的区别因素变得不那么明显,因为虚假账户使用的是实际流行的标签,而不是明显的政治标签。此外,在特朗普实际当选之前,这些推文似乎是针对所有候选人而不是某个特定候选人的——此时所有的攻击都是针对特朗普的。

结论

从我们的分析中,我们了解到,这些虚假账户伪装成(1)普通美国人,(2)以大都市名字命名的新闻网站,或(3)以相关话题如政治和宗教信仰描述自己的国际名字;他们通过在机会性时间发布主观和极端的推文来达到影响 Twitter 用户的目的,比如在丑闻和大型公告发生的周末。最后,他们通过微妙地加入流行标签并在其中注入宣传,对自己明显的帖子变得有感觉。

感谢您花时间阅读我们对俄罗斯虚假推文的分析。如果你现在可以谈论虚假的推文而不听起来虚假,认为我们应该分析任何其他事情,或者有任何意见,请留下赞或评论。欢迎在 LinkedIn 上关注或联系斯蒂芬和/或大卫,因为我们将发布更多有趣的文章和教程!

参考文献:

  1. Plotly 用于可视化
  2. Pyldavis 用于局部建模
  3. NBC 俄罗斯虚假推文数据集
  4. 詹娜·艾布拉姆斯在主流媒体上的报道
  5. 文本块用于自然语言处理(NLP)
  6. 美国历史事件
  7. 相似吸引心理学
  8. 圣贝纳迪诺枪击案
  9. 图形和预处理代码 Github

Rust 编程语言介绍。

原文:https://towardsdatascience.com/rust-off-the-grid-introduction-to-rust-programming-language-58df4f2a5664?source=collection_archive---------2-----------------------

Rust 是一种专注于安全性、速度和并发性的系统编程语言。它通过在不使用垃圾收集的情况下保持内存安全来实现这些目标。

Rust 是一种非常现代的语言。它在后端使用 LLVM。Rust 支持命令式过程、并发角色、面向对象和纯函数式风格的混合。它还有助于静态和动态技术中的泛型编程和元编程。

装置

如果你使用的是 Linux 或 Mac,安装 Rust 所需要做的就是启动你的终端并运行:

$ curl -sf -L [https://static.rust-lang.org/rustup.sh](https://static.rust-lang.org/rustup.sh) | sh

如果你用的是 Windows,请下载并运行 32 位安装程序64 位安装程序

如果你已经安装了 Rust,你可以打开你的外壳,输入:

$ rustc — version
rustc 1.20.0

它打印正在运行的 rust 版本。

这里是官方的安装指南

入门!!

向铁锈问好。

现在让我们开始我们的传统程序,“Hello World”
我们的程序从 main 函数开始,main 函数之后的语句将在编译时执行。

println!作为一个类似于函数的宏调用,但以一个感叹号/bang“!”结束,但不是函数调用,宏被扩展成源代码,与程序的其余部分一起编译。

现在首先运行我们的程序,我们需要使用命令“rustc file_name.rs”编译我们的代码,然后生成一个应该执行的二进制文件。

$rustc hello_rust.rs
$./hello_rust
Hello World!

评论

正如我们所知,每种编程语言都需要注释,Rust 支持一些不同种类的注释,这些注释被编译器忽略了。

这些是我们经常使用的评论类型。

// — Single line comments which go the end of the line.
/* */ — Multiple line comments which go to the closing delimiter.

变量

变量是包含一个值的存储块。在 Rust 中,很容易定义一个变量并为其设置一个值。假设您想将数字 1 存储在一个名为 one 的变量中。

let one = 1

就这么简单!你刚刚把变量 one 赋值给了值 1,let 用来引入一个绑定。

类型注释

Rust 允许你声明自己大小的变量,因为 rust 是一种静态类型语言,我们可以预先指定我们的类型,并且在编译时检查它们。

下面是一个声明 32 位有符号整数的示例。我们使用 let 进行绑定,后跟一个变量名和类型,大小,跟在冒号(:)后面。

let x: i32 = 19;

Rust 有许多不同的原始整数类型。它们以 i 开头表示有符号整数,以 u 开头表示无符号整数。可能的整数大小为 8、16、32 和 64 位。

易变性

在 Rust 中,当你声明一个变量时,绑定是不可变的,这意味着我们不能改变变量的值。

这段代码给出了一个错误,它显示了不可变变量` x '的重新赋值!

$rustc rust_mut.rs
./rust_mut
--> rust_mut.rs:3:2
  |
2 |  let x = 5;
  |      - first assignment to `x`
3 |  x = 10;
  |  ^^^^^^ re-assignment of immutable variable

如果你希望一个绑定是可变的,你可以使用关键字*。*

数据类型

Rust 中的原始数据类型

1.布尔代数学体系的

一个标准的布尔值。可以是真也可以是假。

2.特性

到目前为止,我们只处理了布尔值和数字,但是 Rust 也支持字母。Rust 的char类型是该语言最原始的字母类型,下面的代码展示了使用它的一种方法:

3.数字类型

整数

这些类型包括 i8、i16、i32、i64、isize、u8、u16、u32、u64、usize。字母表示它是有符号的(I)还是无符号的(u),数字表示整数的大小。因此,i8 是一个 8 位整数,u64 是一个无符号的 64 位整数。isize 和 usize 取决于计算机的架构。

漂浮物

这些类型包括 f32 和 f64。浮点数就是我们通常所说的十进制数。

4.数组

数组是固定大小的相同类型元素的集合。

声明如下:

*let name: [type; size] = [elem1, elem2, elem3, elem4];*

5.元组

不同(或相同)数据类型元素的固定大小有序列表

元组的声明类似于数组。我们用“()”代替“[ ]”。

元组在默认情况下也是不可变的,即使有了 mut ,它的元素计数也不能改变。此外,如果您想要更改元素的值,新值应该与以前的值具有相同的数据类型。

6.用线串

str 是“字符串片段”,是最原始的字符串类型。

现在有些人在开始使用 rust 时会犯的错误是打印变量' '。为了打印它,我们需要写:

这类似于 Python 格式。

7.向量

在 Rust 中,向量在堆上将它们的内容存储为 T 的连续数组。这意味着它们必须能够在编译时知道 T 的大小(即存储一个 T 需要多少字节?).

你可以用 vec 创建它们! 宏:

控制流

我们总是需要检查条件并相应地改变程序行为的能力。条件语句给了我们能力。最纯粹的形式是‘if’语句。

让您控制 Rust 代码执行流程的最常见的结构是 if 表达式和循环。

如果-否则

所有的if表达式都以关键字if开头,后跟一个条件。我们还可以包含一个else表达式,在条件评估为 false 时,为程序提供一个可供选择的代码块来执行。

带有 else-if 的多个条件

Rust 目前提供了三种方法来执行某种迭代活动。它们是:for、while 和 loop。每种方法都有自己的一套用法。

For 循环

rust 中的 For 循环用于基于给定的开始位置和结束位置进行迭代。Rust 的 for loop 看起来不像这个“C 风格”的 for loop,是这样的。

在这个例子中,变量 x 从 0 迭代到 9,并打印一直到 9 的数字。

While 循环

Rust 也有一个 while 循环。当条件为真时,循环运行。当条件不再为真时,调用break,停止循环。

看起来是这样的:

关键字loop告诉 Rust 一次又一次地执行一段代码,直到你明确地告诉它停止。为了停止这个无限循环,我们需要通过键盘快捷键(CRTL + C)来中断它。

功能

函数是执行特定任务的可重用代码块。它是一个小的计算单元,可以接受参数,也可以返回值。

每个 Rust 程序至少有一个功能,主要功能:

*fn main() {
//body
}*

在 Rust 中声明函数时,我们使用 fn 关键字,后跟函数名和一些括号,如果有参数的话,我们可以在括号中包含参数。

现在让我们写一个函数,可以把两个整数相加。

这些函数在主函数中被声明调用,并在主函数外被声明。

无论是调用函数还是声明函数,都要用逗号分隔参数。

返回类型的函数

默认情况下,函数返回空元组()。如果要返回值,必须在 - > 后指定返回类型。

这是一个返回数字的函数的例子。

在上面的程序中,函数 plus_one()plus_two() 返回整数类型,我们将它们赋给主函数中的变量。

恭喜您刚刚完成了基本的 Rust 编程!

向所有阅读并支持这篇报道的人致敬。

感谢阅读。如果你觉得这个故事有帮助,请点击下面的👏去传播爱。

源代码位于:

* [## 维哈尔/鲁斯特-丽莎

rust-lisa -几分钟学会 rust!即将发布。

github.com](https://github.com/vihar/rust-lisa)

参考资料:

[## 生锈文件

关于参考文献的另外几句话:它保证是准确的,但不完整。我们的政策是…

doc.rust-lang.org](https://doc.rust-lang.org/)*

2018 年莱德杯-美国通配符(来自数据)

原文:https://towardsdatascience.com/ryder-cup-2018-us-wildcards-from-the-data-d53d5e0c843f?source=collection_archive---------12-----------------------

Photo by Markus Spiske on Unsplash

随着 2018 年莱德杯的快速临近,对于双方的团队组成有很多猜测。自动资格赛已经有以下球员参加了 Le Golf National 的比赛:

Rankings accurate as of August 30th 2018, ahead of the Dell Technologies C’ship & Made in Denmark

欧洲队仍然有一些有潜力的人可以加入积分争夺最后一名,丹麦制造活动是索比约恩·奥尔森、马特·菲茨帕特里克和埃迪·佩珀雷尔争夺第 8 号球衣的机会。

然而,美国已经锁定了他们的八个人。剩下的就是吉姆·福瑞克选择他的四个外卡球员来组成球队。每个人都有自己的观点,认为哪些人应该被选中,以及他们拥有什么样的品质使他们成为理想的人选。在做出选择时,经验和性格都是典型的考虑因素,高尔夫媒体已经指定了一些他们认为应该出现在福瑞克球队名单上的明星球员。

在这么多意见被公布的情况下,做出这样的决定并不容易。数据告诉我们什么?在这篇博文中,我们将使用几个不同的指标来更深入地了解美国顶级非自动化项目的形式(不仅仅是 RC 点)。

(所有 Python 代码可在https://github.com/jjaco/rydercup2018获得)

一个有趣的起点是看看本赛季美国球员 PGA 巡回赛每周的结束情况。如果我们获得了到目前为止至少 10 次出局的每个球员的最终位置,我们就可以粗略估计他们每周在球场上的表现。

Weekly rank data in 2018 for US players making 10 cuts in the regular season (thru Northern Trust)

上面的插图概括了每个球员的所有每周排名数据:空白对应于错过的比赛或跳过的比赛,蓝色越多意味着成绩越差,而红色越多表明成绩越好,最深的红色表示获胜。如果我们计算一下每周的平均排名,按照这个值对玩家进行排序,看看表现最好的玩家,事情会变得更清楚一些:

Top 20 US players by mean weekly rank (thru Northern Trust)

不出意外,世界排名第一的达斯汀·约翰逊以非常出色的平均排名第 6 位遥遥领先。他是本赛季唯一一个平均最终排名前 10 的球员。

美国其他自动入围者也表现不错:除了布巴沃森(Bubba Watson)之外,所有人都排在前 20 名,他的每周平均排名约为 36 位。这可能是因为布巴在戴尔技术比赛中的胜利没有被计算在内(抱歉,布巴,至少这与莱德杯有关)。

非资格赛的名人是(按平均排名):老虎伍兹(12.07),帕特里克坎特莱(12.88),托尼菲瑙(12.9),菲尔米克尔森(13.94)和布赖森德尚博(14.95)。这一结果让泰格的回归更加令人印象深刻,本赛季他每次出场的场均排名都在前 15 名之内。与菲尔一起,你必须预计这些人将是福瑞克的前两个选择:他们所有的经验加上 2018 年的良好表现将是无价的。

对于剩下的两个槽点,让我们继续从目前的分析来看领跑者:菲瑙、德尚博和坎特莱。由于平均每周成绩不考虑平局或最终位置之间的相对差距,让我们看看一个不同的指标来找出更多信息:与最终赢家的相对击球数。这是该球员相对于该周最佳球员表现的大致情况。

这是通过计算一名选手四轮比赛的总成绩和最终获胜者的总成绩之差得出的:请注意,赢得一场比赛的结果是相对击球数为 0,这是理想值。

Histograms of relative strokes from winner for Finau, DeChambeau & Cantlay, with average relative strokes annotated

Finau 在这 3 项指标中的平均得分最低,但本赛季没有赢过 DeChambeau 和 Cantlay 的 2 场和 1 场。从这个角度来看,只有达斯汀·约翰逊和贾斯汀·托马斯在相对击球方面比菲瑙好,分别为+5.31 和+7.33。同样值得注意的是,Cantlay 和 DeChambeau 在美国选手中的相对击球数分别排名第 5 和第 9。

这三个家伙本赛季显然打得很好,他们每个人都有很强的理由成为球队的一部分。但是只剩下两个名额了。

有大量的统计数据和指标可以用来量化高尔夫表现,包括球员比赛的细节。也许我们需要开始审视这些个人属性,以确定最适合这份工作的两个人。PGA 巡回赛跟踪一切,从驾驶距离,到从接近获得的击球,到反弹能力——几乎有太多的选择来做出决定性的选择。为了解决这个问题,我们为每个玩家构建了一个被称为的特征向量,由以下关键绩效指标组成(旨在涵盖尽可能多的“精彩表现”支柱):

  • 击球次数:开球,接近,果岭周围,推杆,球座到果岭,总杆数
  • 驾驶:距离、准确度
  • 百分比:规则中的果岭,节省的沙地
  • 平均分:老鹰(每洞数),小鸟,得分

这个 13 分量向量充当每个玩家的表现签名。利用这一点,我们可以开始直接比较球员,测量相似性,并将相似的比赛风格聚集在一起。

以下是加工前达斯汀·约翰逊的特征示例:

Pre-scaling feature vector for Dustin Johnson

每一个都相对于巡回赛中的其他活跃球员(不仅仅是美国人,就像之前的分析一样)进行缩放,以使他们在全球特征空间中直接可比。所有这些都是通过减去平均值并除以每列的标准偏差来对值进行范围归一化。

这为每个球员创建了一个较少人工解释但更具统计鲁棒性的签名,这使我们能够测量两个给定球员的每个特征之间的距离,例如,谁在驾驶推杆时最像 DJ?在特征空间中有几种计算距离的方法,但是我们使用一种叫做余弦相似度的技术来衡量两个玩家有多相似。这提供了一个在[1,-1]范围内的值,1 是最大相似度,-1 是完全不相似。

如果我们假设自动合格的团队成员代表了美国莱德杯球员的理想品质,我们可以通过对他们的后处理特征向量取平均值来构建他们的组合。这已经充当了团队中八个玩家的某种“重心”,并且是团队围绕其存在的特征向量空间中的锚点。我们可以看看谁的特征向量和这个最相似。

Overview of ‘most like US Ryder Cup team’ method

那么三位候选人中谁最像这位‘理想的美国莱德杯选手’或者‘美国队主播’呢?计算所有不合格美国选手的余弦相似度:

德尚博,坎特雷,菲瑙都还在上面!这可能并不令人惊讶,因为好的锦标赛结果是建立在好的发挥上的,但请注意,我们的特征向量表示并不像前两个指标那样考虑锦标赛位置或获胜者的击球数(尽管获得的击球数肯定是相关的)。

从这个结果中,我们可以得出结论,从统计数据来看,布赖森是最像自动合格的非合格人员,从数据来看,他将是团队的一个极好的补充(这并不奇怪)。

至于 Finau vs. Cantlay,那真的是一个很艰难的选择。这种势头可能与 Finau 最近的结果和更高姿态的巡回赛有关,但正如我们在这里看到的,Cantlay 确实有数据支持它(实际上在某些方面胜过 Tony)。

祝吉姆·福瑞克和他的选择好运,也祝美国好运。我们去欧洲吧!

致谢

销售分析:改善销售策略和绩效

原文:https://towardsdatascience.com/sales-analytics-improving-sales-strategy-and-performance-30b770de68fc?source=collection_archive---------4-----------------------

销售分析的出现让销售专业人士开始关注每天的电话和电子邮件等指标,以跟踪潜在客户。至于绩效衡量,管道价值和成功率是考虑的指标。这是销售人员刚刚开始理解数据分析的价值和潜力的时期。

然后,企业开始使用更好的工具来提高他们的分析能力。这些工具使他们能够发现更多的销售业绩指标,如配额达成率和销售线索周转率,这对收入有相当大的影响。

当今的传统销售分析平台(CRM 分析等。)的确在许多方面给企业带来了好处,超出了人们的想象。然而,它们似乎有其局限性。以下来自 Salesforce.com 和 Hubspot 的统计数据解释了企业销售的现状。由于传统平台在机器学习和人工智能等概念的应用方面仍然落后,因此销售业绩和有效性存在差距。当然,仍有很大的改进空间。这就是 销售决策引擎 发挥作用的地方。

销售决策引擎

为了克服上述限制,分析和技术解决方案提供商 BRIDGEi2i Analytics Solutions 开发了一个高级销售支持平台——销售决策引擎(SDE ),以帮助企业:

  1. 全面了解客户细分、销售、收入和渠道
  2. 做出准确可靠的销售预测
  3. 识别最有可能转化的机会
  4. 使销售团队能够识别和衡量需要改进的领域
  5. 识别战略干预点,以便销售团队提高达成交易的成功率

SDE 使不同角色和需求的销售人员(销售代表或经理)能够更好地预测结果,制定数据驱动的行动,并提高绩效和效力。

SDE 是如何运作的

SDE 采用了可扩展和灵活的架构,由先进的机器学习算法和人工智能驱动。因此,该平台能够识别和适应市场动态、销售流程和业务需求的变化。

该平台分析从相关来源(营销自动化系统、CRM 系统和内部仓库)收集的数据。然后,它利用专有的统计模型和算法进行异常检测、监督和非监督分类、时间序列预测和场景规划等操作。最后,该平台使用预先构建的可视化工具(force.com、Tableau、QlikView 等)。)帮助专业人士改进销售策略和决策。

因此,SDE 使销售组织能够对他们的业务采取度量驱动的方法。该平台不仅仅是为了解决某些销售问题或痛点;它有助于将高级分析功能嵌入他们的决策系统,以实现持续的业务影响。

现在,让我们讨论一下 SDE 对销售策略和效率有所贡献的几种方式。

预测销售速度和渠道绩效

SDE 在销售分析过程中引入了游戏化的概念。该平台有助于领导和销售代表跟踪个人层面的销售业绩。它计算销售速度,并根据当前绩效预测销售代表在特定时间内可能达到的价值。销售代表可以实时了解当前的实际价值、他或她可能达到的总价值以及预测价值和实际目标之间的差距。

通过基准测试识别风险团队并获得可见性

借助 SDE,销售经理可以生成包含详细信息的报告,如总体销售目标、实际价值、与目标的差距、漏斗中的剩余价值、平均销售周期和成功率。此外,销售代表可以进行基准测试,以评估相对绩效。这些见解有助于及时干预;它们有助于识别“有风险”的团队或个人,以便采取适当的措施来提供支持并改善他们的成果。

提高机会得分

SDE 提出了关于可能具有更高转换率的机会的说明性建议。机会分越高,转化的概率越大。因此,销售代表可以根据这些可行的建议来确定其机会的优先级。

至于销售漏斗进展,有几个阶段,例如:

  • 初次接触
  • 资格
  • 会议
  • 建议
  • 谈判

通常,某些机会不会以预期的速度从一个阶段过渡到另一个阶段。SDE 帮助确定这些“不同步”的机会。这种见解有助于销售代表或经理根据业务需求采取最合适的行动。

总之,高级销售分析解决方案在有效部署后,可以显著改善销售战略和利润。然而,这里的关键词是“有效部署”。部署和优化数据分析需要时间、投资和努力。对于企业来说,认识到这一点并理解建立一个“分析第一”的组织是持续业务增长的关键是至关重要的。SDE 是接受相同商业理念的结果。该平台出现在 Gartner 于 2016 年 9 月 7 日发布的面向 B2B 销售和营销的 SaaS 预测分析应用市场指南中。

在这一点上,学习销售决策引擎的所有方法和内容;并请求试玩,这里

这篇文章最先出现在 BRIDGEi2i 博客 上,部分文章最先发表在 Analytics India 杂志 上。

销售水晶球——人工智能驱动的 B2B 销售平台

原文:https://towardsdatascience.com/sales-crystal-ball-an-ai-driven-b2b-sales-platform-3a16213aae7?source=collection_archive---------4-----------------------

人工智能和机器学习正在让企业的每个可能领域都能感受到它的存在。

销售和营销组织正在慢慢加入到这个聚会中来。

对于营销和销售组织来说,一些长期得不到解答的问题是:

企业能否预测哪些潜在客户转化的可能性非常高?

企业能否预测哪些现有客户表现出大量生产的高概率?

企业能否识别显示高购买倾向的潜在客户?因此是理想的目标?

在这篇文章中,我探讨了一家具有代表性的大型 IT 公司的销售和营销部门所面临的挑战,以及错过一些销售机会的原因。以及人工智能驱动的智能销售平台(ISP)如何帮助应对这些挑战,从而提高成功率、交易速度和规模。

这些场景涉及销售代表、销售开发代表(SDR)、营销人员等角色。主要来自销售组织和营销组织。

销售漏斗中隐藏的地雷

#1 —销售线索评分

“不适合与适合”:营销团队经常面对大量的潜在客户。虽然这是一个令人垂涎的场景,但这些线索大多是不合格/原始的线索。通过手动处理来确认潜在客户的资格通常繁琐、耗时且效率低下。传统的销售线索评分系统(简单的双轴方法:人口统计、公司地理)显示出严重的局限性。因此,最终的结果是,营销组织将“不适合”的领导交给了销售团队。销售代表在最终不会购买的客户身上投入了宝贵的时间。

#2 —细分

传统的基于规则或简单的公司图分割常常不能描绘出客户群的正确特征。这导致了营销努力和金钱的浪费。

挑战 1—优先考虑客户

在预算和资源有限的情况下,并不是所有的客户都能成为营销活动的目标。对于营销人员来说,从数千个显示高购买倾向(适合度、意向)的账户中分离和分层是一场噩梦。这导致在没有任何优先顺序的情况下,在所有客户之间进行“糟糕的”通用营销预算分配。

挑战 2 —交叉销售和追加销售

许多公司严重依赖于发掘现有客户群,而不是寻找新客户。并非所有现有账户都有资格获得类似的关注。销售代表和 SDR 应该更多地关注显示高购买倾向的客户。但在现实中,高质量的数据——关于顾客表现出强烈购买信号的数据——通常很难找到。

挑战 3 —需求挖掘

无法找到并跟踪表现出强烈购买兴趣的潜在客户是销售漏斗中的一个关键瓶颈。营销团队通常依赖于基本的代理,如谁下载了白皮书,谁观看了网络研讨会等,来预测兴趣。有大量的数字足迹/信号尚未开发,如果客户表现出强烈的意向,这些数字足迹/信号可以忠实地建模。在缺乏技术支持的情况下,营销人员无法挖掘这些信息流。

以上所有挑战的共同点是:缺少关于客户的丰富和可操作的洞察力(例如:“意图”和“适合”)

抱负

在优先级方面,销售和营销组织通常希望实现以下部分或大部分目标:

  • 提高销售线索转化率
  • 提高续订率
  • 增加交叉/向上销售量
  • 加快销售周期
  • 减少客户流失
  • 提高活动效果
  • 改进管道卫生的预测和测量

在这种背景下,让我们看看智能销售平台(ISP)如何应对一些挑战,并推动流程朝着上述目标前进

智能销售平台(ISP)能当水晶球吗?

注入人工智能的智能销售平台是一种应用程序,它从内部和外部来源、模型(机器学习)消费客户数据,并为营销人员、SDR 和销售代表提供智能见解。“智能”意味着正确使用“机器”的平台-收集、处理相关数据,并具有强大的内置模型,可以规定正确的行动方针。

智能销售平台(ISP)的一些关键特性是什么?

关键特性#1:智能分段

传统的静态细分方法无法充分发挥海量客户数据的威力。

在智能销售平台(ISP)中,使用内部 CRM 数据和外部来源的数据,创建了丰富的 360 度客户档案。这些记录最初是为现有客户创建的。然后使用机器学习对数据集进行建模,以创建非常准确的“理想客户”细分市场。任何属于这些细分市场的公司都有很高的转化机会。

智能平台可以根据这些细分市场检查任何未来的入站销售线索,并显示转换潜力。

关键特征#2:交叉销售/ups 销售机会评级

在智能销售平台中,使用围绕购买模式的内部 CRM 数据和来自外部来源的数据,首先训练机器学习模型。随后,模型忠实地预测交叉销售机会的可能性。

关键特征#3:呼入销售线索评分

使用智能销售平台可以从噪音中过滤出令人畏惧的高质量铅。该平台会根据转化的可能性对入站销售线索进行评分。销售团队只能追踪得分高于阈值的销售线索。

内部智能销售平台使用 CRM 数据和从不同来源收集的许多数据点。这些集合在一起是为了详细查看每个历史客户。例如,线索评分可以考虑公司的许多有趣的“特征”(用机器学习术语来说),例如:

公司的核心信息:收入、成本、利润、核心产品领域、地理位置、员工数量

增长信息:同比收入增长、季度招聘增长、新收购、高管职位变动

购买意向:各种网络平台的近期参与度指标(执行搜索、阅读博客、参加网络研讨会)

技术堆栈(适用于 IT 销售人员):CRM、ERP、HRM、云等中使用的技术

关键特征#4:人物角色草图

从关于购买者概况的历史数据(资历、背景、头衔等),机器学习模型可以建立购买者的高保真度的角色。销售代表可以利用这种角色来锁定合适的人,并组织对话,从而获得更高的说服机会。

功能#5:通信优化

基于沟通模式、沟通频率、沟通模式,ML 模型可以理解什么可行,什么不可行。这些见解可用于未来的项目,以复制成功。

智能销售平台(ISP)的机制

ISP 可以像 SaaS 一样建立(或购买)在私有或公共云上。机器学习模型可以是应用的组件。

应用程序可以使用 Rest APIs 访问外部信息(例如,来自第三方信息管理者的公司信息)。此外,应用程序可以使用原始格式的信息,随后使用数据管理引擎进行清理,并使用 NLP 引擎提取结构化数据块。存储结构化的、扩充的数据用于机器学习模型的训练。经过训练的模型在 ISP 中存档。

当新的潜在客户到来时,这些信息通过特定的模型提供,模型可以预测转化的可能性。类似地,细分模型也可以勾画出多个客户概况(这是公司追逐的理想选择)

减去

设定您的目标:如果您正在考虑在您的销售和营销工作流程中注入更多“智能”,您可能想要实现的主要目标可能是:提高销售线索转化率、提高续购率、增加交叉/向上销售量、加快销售周期、减少客户流失、提高活动有效性、提高管道卫生的预测和测量。提前设定目标。

构建/购买平台:在构建/购买人工智能解决方案时,您可以考虑以下三组最具影响力的能力:智能细分能力、呼入销售线索评分、交叉/向上销售机会评级。构建或购买人工智能解决方案只是通往最终结果的整个旅程的一部分。现有的流程必须保持一致,必须建立正确的人类技能集(尤其是围绕人工智能),以增加成功的机会。

持续测量成功和支点:在一定的时间间隔内(例如每个季度),必须根据一组目标来测量进度。执行计划必须围绕这一点。

很想听听你的想法。

我的坐标:@saunakdg 在 Twitter

图片提供:任务和目的http://taskandpurpose . com/movie-kilo-two-Bravo-offers-unfifthed-look-at-the-ground-war-in-Helmand/和 Joblohttp://www . Joblo . com/horizon-movies/news/mine-goes-click-movie-review-155

抽样技术

原文:https://towardsdatascience.com/sampling-techniques-a4e34111d808?source=collection_archive---------0-----------------------

采样对研究有很大帮助。这是决定研究/调查结果准确性的最重要因素之一。如果你的样本出了什么问题,那么它会直接反映在最终的结果中。有很多技术可以帮助我们根据需要和情况收集样本。这篇博客文章试图解释其中的一些技巧。

首先,让我们看一下一些基本术语

人口

样品

抽样

人口是具有某种或其他共同特征的要素的集合。人口中要素的数量就是人口的规模。

样本是总体的子集。选择样本的过程称为抽样。样本中的元素数就是样本大小。

Sampling

有许多抽样技术,分为以下两类

  • 概率抽样
  • 非概率抽样

两者的区别在于样本选择是否基于随机化。在随机化的情况下,每个元素都有同等的机会被选取并成为研究样本的一部分。

概率抽样

这种抽样技术使用随机化来确保总体中的每个元素都有平等的机会成为所选样本的一部分。也就是所谓的随机抽样。

简单随机抽样

分层抽样

系统抽样

巢式抽样法

多阶段抽样

**简单随机抽样:**每个元素被选为零件样本的机会相等。当我们没有任何关于目标人群的先验信息时,就会用到它。

**例如:**随机抽取 20 名学生组成 50 人的班级。每个学生都有平等的机会被选中。这里选择的概率是 1/50

Single Random Sampling

分层抽样

该技术基于相似性将群体的元素划分为小的子组(层),使得该组内的元素在所形成的其他子组中是均匀和不均匀的。然后从这些层中的每一层随机选择元素。我们需要有关于人口的先验信息来创建子群体。

Stratified Sampling

整群抽样

我们的整个人口被分为集群或部分,然后集群是随机选择的。集群的所有元素都用于采样。使用诸如年龄、性别、位置等细节来识别集群。

可以通过以下方式进行集群采样:

单阶段整群抽样

整群随机抽样。

Single Stage Cluster Sampling

两阶段整群抽样

这里,我们首先随机选择集群,然后从这些选择的集群中随机选择用于采样的元素

Two Stage Cluster Sampling

系统聚类

这里,除了第一个元素之外,元素的选择是系统的,而不是随机的。样本中的元素是在群体的规则间隔中选择的。首先将所有元素按顺序放在一起,每个元素都有同等的机会被选中。

对于大小为 N 的样本,我们将大小为 N 的总体分成 k 个元素的子组。

我们从 k 个元素的第一子组中随机选择第一个元素。

要选择样品的其他元素,请执行以下操作:

我们知道每组元素的数量是 k,即 N/n

所以如果我们的第一个元素是 n1,那么

第二个元素是 n1+k,即 n2

第三个元素 n2+k,即 n3,依此类推..

以 N=20 为例,n=5

每个子组中的元素数量是 N/n,即 20/5 =4= k

现在,从第一个子组中随机选择第一个元素。

如果我们选择 n1= 3

n2 = n1+k = 3+4 = 7

n3 = n2+k = 7+4 = 11

Systematic Clustering

多阶段采样

它是上述一种或多种方法的组合。

将群体划分为多个聚类,然后基于相似性将这些聚类进一步划分和分组为各种子组(层)。可以从每个层中随机选择一个或多个集群。这个过程一直持续到集群不能再分为止。例如,国家可以分为州、城市、城市和农村,所有具有相似特征的地区可以合并在一起形成一个阶层。

Multi-Stage Sampling

非概率抽样

它不依赖于随机化。这项技术更依赖于研究人员为样品选择元素的能力。抽样的结果可能会有偏差,使得所有的人口元素很难平等地成为样本的一部分。这种类型的抽样也称为非随机抽样。

方便抽样

立意抽样

定额抽样

转诊/滚雪球抽样

方便取样

在这里,样本是根据可用性选择的。这种方法用于样品稀缺且价格昂贵的情况。因此,基于方便选择样本。

例如:在调查研究的初始阶段,研究人员更喜欢这种方式,因为这种方式可以快速轻松地提供结果。

目的性抽样

这是基于学习的意图或目的。只有那些元素会从最适合我们研究目的的群体中选出。

**例如:**如果我们想了解对攻读硕士学位感兴趣的人的思维过程,那么选择标准应该是“你对……感兴趣吗..?"

所有回答“否”的人将被排除在我们的样本之外。

配额抽样

这种类型的采样取决于一些预设的标准。它从总体中选择有代表性的样本。样本中特征/性状的比例应与总体相同。选择元素,直到获得特定类型数据的确切比例或收集到不同类别的足够数据。

例如:如果我们的人口中女性占 45%,男性占 55%,那么我们的样本应该反映相同的男女比例。

转诊/滚雪球抽样

这种技术用于人口完全未知和稀少的情况。

因此,我们将从我们为总体选择的第一个元素中获得帮助,并请他推荐符合所需样本描述的其他元素。

所以这种推荐技术继续下去,像滚雪球一样增加人口数量。

Referral /Snowball Sampling

例如:它用于高度敏感的话题,如艾滋病,人们不会公开讨论和参与调查来分享有关艾滋病的信息。

并非所有的受害者都会回答问题,因此研究人员可以联系他们认识的人或志愿者,与受害者取得联系并收集信息

在我们无法接触到足够的具有我们所寻求的特征的人的情况下提供帮助。从找人学习开始。

希望现在你们都对取样和它的技术有了很好的了解。

感谢阅读!

SAS 客户智能 360 —将数据转化为体验

原文:https://towardsdatascience.com/sas-customer-intelligence-360-turn-data-into-experience-a6289f097e38?source=collection_archive---------7-----------------------

不久前, SAS 的安吉拉·科普斯科姆联系了我,向我介绍了 SAS 的客户决策中心的概念。

他们的客户决策中心是一个解决方案概念,将允许组织从与外部方的交互中获得洞察力并触发行动,如基于规则和所获得的洞察力的客户。

例如,客户决策中心协调确定下一个最佳行动,并允许使用分析和决策逻辑实时响应传入的请求。同时,基于相同的规则集,标准通信可能会被禁止。

换句话说,客户决策中心基于通过组织分析和处理的入站信号来促进客户参与。

我听到你问,这有什么了不起的?

它之所以引人注目,是因为 SAS Software 首先是一家分析公司,在高端性能和价位的企业分析方面享有盛誉。SAS 在 LinkedIn 上将自己描述为“商业分析软件和服务的领导者,商业智能市场上最大的独立供应商。通过创新的解决方案,SAS 帮助超过 70,000 个站点的客户提高性能,并通过更快地做出更好的决策来提供价值。自 1976 年以来,北欧航空公司一直致力于让世界各地的客户了解真相。”

SAS 并不是一家因积极参与客户参与市场而广为人知的公司(双关语)。

所以我很好奇。你也应该如此。

最后,几天前,我有点不稳定的日程安排允许我与新西兰 SAS 软件公司的特洛伊·库萨布进行后续会谈,这是他早些时候提出的。特洛伊让我对这个概念有了更多的了解,并告诉我 SAS 软件是如何支持用生命填充它的。它基于 SAS 数字智能和个性化平台“SAS 客户智能 360”。SAS Customer Intelligence 360 的目的是允许企业根据数据创建相关的客户约定,从而带来更好的客户体验。SAS 称之为“创造相关的、令人满意的、有价值的客户体验”。

SAS Customer Intelligence 360 由两个应用程序组成,它们位于 SAS 分析系统之上,通过实现实时决策、智能营销和活动管理功能来支持营销。这些应用程序被命名为 SAS 360 Discover 和 SAS 360 Engage,它们允许从数字交互中收集数据,从这些交互中获得洞察力,然后使用这种洞察力通过 web、聊天、电子邮件和移动应用程序与客户进行有意义的互动。人们可以粗略地说,SAS 360 Discover 提供了分析引擎,SAS 360 Engage 使用了分析结果。

企业可以定义和维护数据收集和规范化规则,并基于这些规则分配个性化规则。使用网站或应用程序代码等简单的增强功能来跟踪客户互动,这有助于建立他们的档案,首先是匿名档案,在可能的情况下识别和合并这些技术档案。这些数据在一个数据集市中进行聚合,并可以通过来自企业拥有的其他来源的数据进一步丰富,如产品信息和来自 CRM 和其他系统的信息。然后,可以利用 SAS 的核心优势,即强大的分析系统,将这些信息用于进一步的合作。

这种参与是 SAS 360 Engage 应用程序的工作,它允许将消息和资产结合到营销任务中,这些任务被聚合到客户旅程中,被 SAS 称为活动。这同样受到 SAS 分析功能的支持,包括预测分析和机器学习。

整个系统运行在 AWS 上,并被强制设计为开放平台。API 和 ETL 功能提供了与源系统的连接。

我的看法

很高兴看到传统的分析供应商站出来,帮助他们的客户构建一个集成的解决方案,使他们能够利用他们所拥有的数据宝库。客户参与和客户体验是最热门的话题,这是展示这种能力的好机会。当然,SAS 也为决策管理、欺诈检测和风险管理提供解决方案。

SAS 能够将领先的分析引擎与业务逻辑相结合,这是一个非常有说服力的案例。分析是达到目的的一种手段,即商业目的。这种情况得到了 API 方法和提供开放平台声明的支持。

尽管如此,SAS Customer Intelligence 360 所覆盖的市场是一个竞争非常激烈的市场。像 SAP、微软、甲骨文和 Salesforce(或 Adobe)这样的商业应用软件供应商也试图垄断它。他们可能没有强大的分析引擎,但他们掌握了大量的业务逻辑和业务知识。然后是专业厂商,这里我只想提一下 Kitewheel 和 Thunderhead。这些公司在发现和参与方面表现出色,并拥有旨在支持其专业化的分析引擎,他们正在提供与主要业务(主要是 CRM 系统)的现成(OOB)集成。

整合是一个重要的话题。虽然提供 API 是关键,但是拥有 OOB 集成的信息是非常强大的。

最后,它是关于信息和哲学的。查看“开始使用”信息图在此说明。这种想法是以公司为中心,而不是以客户为中心。因此,它不必要地限制了自己。虽然有人提到客户“善变”,但这是假设客户的旅程可以由公司预先规划,这是错误的。公司可以提供许多接触点,客户可以在任何给定的时间点从中选择他认为最方便的接触点。真诚地传递信息是关于与 客户交谈,而不是与 客户交谈 。将消息传递转变为由外向内的观点,然后进一步改进解决方案,可以帮助 SAS 真正脱颖而出。

SAT 数据— 2001 年

原文:https://towardsdatascience.com/sat-data-2001-8e86f1671840?source=collection_archive---------3-----------------------

在我们的第一个大会数据科学沉浸式项目中,该班级获得了一些 2001 年的 SAT 数据。这些数据包括各州的参与率、各州的平均语言成绩以及各州的平均数学成绩。

Sample of the data in excel — (please don’t tell anyone I opened this in excel!)

首先,我在 excel 中打开 csv 文档。excel 表格很有趣,我可以用它对数据进行一些基本的推断——高分和低分,计算一些基本的统计数据,等等。然而,我真的想以一种能给我更多控制的格式来查看这些信息,所以我把所有的东西都导入了一个 jupyter 笔记本。

因为我被告知不要在这个项目中使用 pandas dataframes,所以我将所有内容导入到一个 list 列表中,并使用字典来处理数据。导入过程看起来像这样:

Importing……………..

一旦它成为列表格式的列表,我就可以制作一些图表和可视化效果来真正利用这些数据。第一步是值的直方图。

直方图是每个范围内数值数量的条形图。在这种情况下,它显示分数出现在某个范围或“bin”内的州的数量

(我用 matplotlib 在 jupyter 笔记本上制作了所有这些图表,但为了让它们看起来更漂亮,我在 tableau 中重新制作了它们)

https://public.tableau.com/views/DCDSIProject1-HIstograms/Dashboard3?:embed=y&:display_count=yes

从这些信息中我们能马上看出什么? 这些都不是正态分布!

没有更多的数据很难说,但我猜想整个美国的 SAT 分数可能更接近正态分布。由于各州人口的差异,各州得分的平均值并不能告诉我们太多关于整个人口的直方图是什么样子。

下一步是绘制散点图,直观地显示数据是如何分布的。

https://public.tableau.com/views/DCDSIProject1-LinePlots/Dashboard2?:embed=y&:display_count=yes

现在我们可以看到一些有趣的关系。

参加测试的合格学生越多,平均分就越低。这是有道理的:在中西部各州,要求 SAT 的学校较少,只有申请竞争更激烈、通常是沿海学校的学生才会参加 SAT,而不是 ACT。

让我们看看这个假设是否支持沿海和内陆州的划分。幸运的是,tableau 将让我们制作一个热图,以查看地理上哪些州的参与率较高。

是的,沿海各州以及德克萨斯州和伊利诺伊州的参与率较高。

也许还有其他因素在起作用。

德克萨斯州、伊利诺伊州和沿海各州的另一个特点是人口水平高。让我们看看人口(2000 年)如何与参与率相关联。

这是一个很好的尝试,但是这个数据没有太多的人口相关性。至少我验证了我的假设。

那么,非沿海州的学生不参加 SAT 考试,而是在做什么呢?

ACT Participation Rates 2001

采取行动。

我在网上找到了一个 2001 年 ACT 参与率的列表(https://forms . ACT . org/news room/data/2001/States . html https://forms . ACT . org/news room/data/2001/States . html)。这些分数的分布图几乎是 SAT 分数分布图的逆分布。

我从现有的数据中获得了一些有趣的见解,但我想用更多的时间和大学委员会的数据来考虑几个问题:

还有哪些信息可以与每个州的参与率和分数相关联?

我们怎样才能把结果按州分开,这样就不会像参与度那样重要了。我们能否将这些分数标准化,以便更好地进行跨州比较?

那些问题将不得不等待另一天。

沙特股票市场分析和预测(Tadawul)——第一部分

原文:https://towardsdatascience.com/saudi-stock-market-analysis-and-forecasting-tadawul-part-i-a22254c7a95b?source=collection_archive---------10-----------------------

这是我在金融行业的第一个项目,尤其是在花了大量时间在医疗保健领域进行机器学习项目(如英国的 A & E 出勤和急诊,以及乳腺癌细胞类型分类器)之后。所以,我决定在中东最大的股票市场之一——沙特阿拉伯股票市场(Tadawul)发挥我的技能。虽然,数据获取和收集是一个具有挑战性的部分。但是多亏了 Tadawul,这才变得很容易!在那里,我必须浏览所有在他们网站上发布的沙特市场活动年度报告,提取所需的数据,并最终将它们合并到一个 CSV 文件中。最终,我得到了一个从 2006 年 1 月到 2018 年 8 月沙特阿拉伯市场活动的数据集。

关于 Tadawul 的更多信息:Tadawul 是在沙特阿拉伯王国被授权作为证券交易所(以下简称“交易所”)的唯一实体。它主要进行证券的上市和交易,以及在交易所交易的证券的存管、转让、清算、结算和所有权登记

该项目旨在分析从 2006 年开始到 2018 年 8 月的沙特阿拉伯股票市场数据,并对 12 个月(2018 年 9 月到 2019 年 8 月)进行预测/预报。我将完成这个项目的一系列,其中每一部分将详细讨论不同的主题。

第一部分—加载数据集、数据争论、数据分析和探索

加载数据集

首先,我们加载所需的库,然后是数据集:

library(dplyr)library(urca)library(forecast) library(repr)library(data.table)library(psych)library(dygraphs)require(ggplot2)

这是我从 Tadawul reports and publications(4x 152)整合的月度市场活动数据集的截图。所有货币单位均为沙特里亚尔:

正在加载数据集:

df <- read.csv ( file= "… /Tadawul/Datasets/Monthly Market Activity.csv", 
                 header= TRUE )
head(df)

按如下方式更改标题名称:

月:日期

股票交易价值(SAR): VST

股票交易数量:NST

交易:Tra

setnames(df, old=c("Month","Value.of.Shares.Traded","Number.of.Shares.Traded", "Transactions"), 
             new=c("Date", "VST", "NST","Tra"))
head(df)

数据角力

检查数据类型:

class(df$Date)
class(df$VST)
class(df$NST)
class(df$Tra)> 'factor'
> 'numeric'
> 'numeric'
> 'numeric'

列“日期”的类别是“因子”。对于时间序列分析,我们应该有日期和时间数据类型。但首先,让我们检查是否有任何缺失的数据存在:

summary(is.na(df$Date))
summary(is.na(df$VST))
summary(is.na(df$NST))
summary(is.na(df$Tra))*>   Mode   FALSE* 
*> logical     152*
*>
>   Mode   FALSE*
*> logical     152*
*>
>   Mode   FALSE*
*> logical     152*
*>
>   Mode   FALSE*
*> logical     152*

没有丢失数据,将“日期”列类型更改为日期和时间类“POSIX CT”“POSIX t”:

to.POSIXct <- function(col){ dateStr <- paste(as.character(col))
  as.POSIXct( strptime(dateStr, "%d/%m/%Y"))
}df$Date <- to.POSIXct(df$Date)
class(df$Date)> 'POSIXct'  'POSIXt'

创建“月”列,它有助于数据可视化和探索:

df$month = month(df$Date)
df$month = month.abb[df$month]
head(df)

数据分析、可视化和探索

让我们首先检查数据帧摘要:

summary(df[,2:5])>  VST                 NST                 Tra              month          
> Min.   :3.240e+10   Min.   :1.557e+09   Min.   :    3185   Length:152        
> 1st Qu.:8.006e+10   1st Qu.:3.503e+09   1st Qu.: 1969411   Class :character  
> Median :1.163e+11   Median :4.669e+09   Median : 2707780   Mode  :character  
> Mean   :1.487e+11   Mean   :4.875e+09   Mean   : 3254791                     
> 3rd Qu.:1.731e+11   3rd Qu.:6.125e+09   3rd Qu.: 3787704                     
 Max.   :8.284e+11   Max.   :1.383e+10   Max.   :12105358

时间段(2006 年 1 月-2018 年 8 月)内交易股份价值散点图(VST),用交易股份数量(NST)进行颜色编码:

ggplot(df, aes(Date, VST, color = NST)) +
  geom_point(shape = 16, size = 2, show.legend = TRUE) +
  theme_minimal()

检查数据分布(直方图)以及交易股票价值、交易股票数量和交易数量之间的关系;

pairs.panels(df[,1:3], method = "pearson", # correlation method hist.col = "#00AFBB", density = TRUE,  # show density plots ellipses = TRUE # show correlation ellipses)

很明显,在 VST、NST 和 Tra 中有异常值或大数据会扭曲分布曲线,大部分是 2006-2008 年的数据。我们将在时间序列绘图和分析中看到这些数字的确切位置。然而,股票交易价值(VST)和交易数量(Tra)之间存在明显的线性关系。因此,更高的交易数量意味着更高的股票交易价值。皮尔逊相关法通过显示 VST 和 Tra 之间的线性关系强度(0.89)可以肯定地证明这一点。

事实上,我有兴趣了解更多关于(2006 年至 2018 年)期间每股交易的平均价值。但是首先,我们必须创建这个功能,并将其命名为(Avg。v)通过将 VST 除以 NST:

*# Average value of each share Avg.V*
df$Avg.V <- df$VST/df$NST
summary(df$Avg.V)> Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
>  13.97   21.25   24.53   29.60   32.39  104.78

检查每个份额分布的平均值:

ggplot(df, aes(x =Avg.V))  + geom_histogram()

平均散点图。“v”与“日期”相对,带有“nst”颜色编码:

ggplot(df, aes(Date, Avg.V, color = NST)) +
  geom_point(shape = 16, size = 2, show.legend = TRUE) +
  theme_minimal()

与 VST 类似,每股平均价值在 2007 年前很高,2010 年后波动。看起来股票数量对这些股票的价值没有影响。我将在时间序列分析中验证这一假设。

创建每列的时间序列数据:

*# create ts data*
VST.ts <- ts(df[,'VST'], frequency = 12, start=c(2006,1), end= c(2018,8))
NST.ts <- ts(df[,'NST'], frequency = 12, start=c(2006,1), end= c(2018,8))
Tra.ts <- ts(df[,'Tra'], frequency = 12, start=c(2006,1), end= c(2018,8))

绘制股票交易价值 VST 时间序列:

随着时间序列的绘制,我们注意到股票交易的最高价值是在 2006 年初,然后曲线开始呈指数衰减。最高数字超过 8,000 亿沙特阿拉伯里亚尔,最低数字低于 2,000 亿沙特阿拉伯里亚尔。为了更好地了解趋势,让我们按季度和年度累计数据,然后再次绘制时间序列。

绘制每季度交易股票的价值:

plot.ts(VST.ts.qtr, main = "Value of Shares Traded - Quarterly", 
         xlab = "Year", ylab = "Value")

plot.ts(VST.ts.yr, main = "Value of Shares Traded - Yearly", 
        xlab = "Year", ylab = "Value")

如季度图和年度图所示,沙特股票市场受到了 2007-2008 年全球经济危机的影响。当时,交易股票价值严重缩水,在 2010 年达到最糟糕的水平。

为了同时了解三个特征的行为,为了更好地显示,我将在基本缩放后一起绘制三个时间序列(VST、NST、Tra ):

options(repr.plot.width=8, repr.plot.height=6)
plot(VST.ts/10000, col = "red", xlab = "Date", ylab = "Value", 
     main = "Saudi Stock Market Activities 2006 - 2018")
lines(NST.ts/600,col = "blue")
lines(Tra.ts*5, col = "black")
grid() 
legend("topleft",lty=1,col=c("red", "blue", "black"), cex = 0.65,
       legend=c("Value of Shares Traded x10^4", 
       "Number of Shares Traded x10^3", "Transactions /5"))
axis(1, at=1:152, labels= (df$Date))

同样,绘制 VST、NST 和 Tra 时间序列—每年:

如图所示,2010 年 VST、NST 和 Tra 值最低。然而,三条线基本上是一致的。

交易股票价值柱状图(VST.ts):

hist(VST.ts, breaks = 30, 
     main = paste('Value of Shares Traded Distribution'), xlab = "VST")

VST 每月箱线图:

boxplot(VST.ts ~ cycle(VST.ts), xlab = "Month", ylab = "VST", 
         main = "Monthly Value of Shares Traded - Boxplot")

从月度箱线图中,我们可以注意到最低的交易值发生在八月和十月。而交易量最高或最热的月份是二月、三月和四月。

应用移动平均技术对 VST 时间序列 12 年间的概貌。我们将计算 6、12、24 和 36 个月的平均值,以控制趋势平滑度。

par(mfrow = c(2,2))
plot(VST.ts, col="gray", main = "Half Year Moving Average Smoothing")
lines(ma(VST.ts, order = 6), col = "red", lwd=3)
plot(VST.ts, col="gray", main = "1 Year Moving Average Smoothing")
lines(ma(VST.ts, order = 12), col = "blue", lwd=3)
plot(VST.ts, col="gray", main = "2 Year Moving Average Smoothing")
lines(ma(VST.ts, order = 24), col = "green", lwd=3)
plot(VST.ts, col="gray", main = "3 Year Moving Average Smoothing")
lines(ma(VST.ts, order = 36), col = "yellow4", lwd=3)

在 AWS 上节省一分钟

原文:https://towardsdatascience.com/save-that-one-minute-on-aws-88dab5a37233?source=collection_archive---------7-----------------------

自动化日志记录和到 EC2 实例的隧道

更多的时候,为了不参与我的项目,我不得不求助于 AWS 来满足我的计算需求。有时候是我的 128 GB 本地机器存储不足,有时候是需要 GPU 运行深度学习模型。AWS EC2 实例并不便宜,尤其是如果您使用的是支持 GPU 的实例。我使用每小时 0.9 美元的 p2xlarge,在我完成工作后,我需要停止(而不是终止)它,这样我就不会被收取不必要的费用。除非您使用的是保留的实例,否则每次重新启动实例时,都会为您分配一个新的 IP。然后,您必须经历将 IP 复制到 ssh 命令以登录的枯燥过程。

#ssh login
ssh -o ServerAliveInterval=60 -i yourkey.pem [ec2-user@ec2-xx-xxx-xx-xxx.us-west-2.compute.amazonaws.com](mailto:ec2-user@ec2-34-210-18-190.us-west-2.compute.amazonaws.com)

然后,如果您想要隧道进入您的实例,您必须为您的隧道命令再重复一次这个过程。

#ssh tunneling
ssh -o ServerAliveInterval=60 -i yourkey.pem [ec2-user@ec2-xx-xxx-xx-xxx.us-west-2.compute.amazonaws.com](mailto:ec2-user@ec2-34-210-18-190.us-west-2.compute.amazonaws.com) -L9000:127.0.0.1:8888

对于像我这样一天要多次停止和重启实例的人来说,这很快就会变得令人恼火。在这篇文章中,我将谈论一个在某种程度上避免这一过程的巧妙技巧。

弹性 IP

拼图的第一块是 AWS 上的弹性 IP 功能。

弹性 IP 地址是与您的 AWS 帐户相关联的静态 IPv4 地址

您可以将此 IP 分配给一个实例,然后每次都可以使用此 IP 登录到您的实例。这将解决不断变化的 IP 问题。这方面的成本可以忽略不计。如果 IP 连接到正在运行的实例,则不会产生任何成本。但是,如果 IP 连接到一个停止的实例,这是您所需要的,它将花费您每小时 0.005 美元。如果我们粗略计算一下,50 天内每天 20 小时的停止实例将花费您 5 美元。一点都不差!!

以下是您预订弹性 IP 的方式:

步骤 1: EC2 仪表板→网络和安全→弹性 IP

第二步:点击分配新地址,并按照步骤

步骤 3:选择新 IP →操作→关联地址

步骤 4:选择要将此 IP 附加到的实例

对于选定的实例,公共 IP 将永久更改为弹性 IP,除非您将其释放。现在,您不需要一次又一次地更改日志和隧道命令的 IP 部分。

只是用弹性 IP 会节省你的时间。但是仍然有提高效率的空间,所以继续吧。

用于日志和隧道的 SSH 脚本

在这里,我将讨论创建 ssh 脚本的一系列步骤,您可以从您的终端运行该脚本,它不仅可以登录到您的实例,还可以创建从您的本地主机到您的实例的隧道。

**第一步:**输入你的。ssh 目录。

步骤 2: 记住,您需要 pem 文件来登录到您的实例。将这个 pem 文件复制到 ssh 目录。

步骤 3: 现在使用任何文本编辑器在同一个目录中创建一个 ssh 配置文件。我用纳米来做这个。并在配置文件中定义实例细节。

Host <any name you like> <elasticIP>.us-west-2.compute.amazonaws.com
 HostName <elasticIP>.us-west-2.compute.amazonaws.com
 User ec2-user
 IdentityFile <location of pem file>
 IdentitiesOnly yes
 ForwardAgent yes
 LocalForward 9000 localhost:8888

注:

  • 在上面的配置文件中,如果你使用的是 ubuntu 实例,用户将是 ubuntu
  • LocalForward 9000 localhost:8888 会将本地主机上的端口 9000 转发到 EC2 实例的本地主机。您也可以使用任何其他端口来代替 9000

完成后,每当您想要重启实例时,只需调用这个命令即可

ssh DL-box

希望这个小技巧能省下那一分钟。这篇推文要旨启发了我写这篇帖子。

使用简单的决策树分类器在 Naira 节省数百万美元

原文:https://towardsdatascience.com/saving-millions-in-naira-with-simple-decision-tree-classifier-1c52ed44439c?source=collection_archive---------3-----------------------

随着最近尼日利亚商业界对数据科学的大量谈论,相当多的从业者可能会忽视其真正的本质。根据一份关于数据科学的 Cloudera 培训材料,数据科学最终旨在发现组织的商业价值,然后将其作为可操作的见解传达给利益相关方。

在很高的层面上,数据科学旨在解决业务问题。要么降低成本,要么增加收入。这种解决商业问题的方法非常科学,非常有条理,并且以研究为基础。因此,我们不只是在谈论用一些 Python/R 库来处理数据。我们参与解决现实生活中的问题,以创造真正的价值。

用例

问题陈述

电子商务行业面临着尼日利亚经济特有的诸多挑战,从市场成熟度、对在线支付系统的信任、严酷的经济现实到人类行为倾向。

为了从在尼日利亚运营电子商务平台的微薄利润中挤出利润,提高客户保留率(如商品推荐引擎)和终身价值或降低运营开销是关键。高运营开销的一个主要原因是客户诱导的订单取消。一般来说,订单可能会因为各种原因被取消,例如支付网关故障、技术故障、客户不满等。我们的用例关注的是在电子商务平台上成功完成流程后被客户取消的订单。

我们的问题是一个分类问题{A 类:完成订单,B 类:取消交付 },我们的目标是预测客户订单在任一类中的概率。

商业目标

将客户导致的订单取消减少 X %。实现上述业务目标将通过减少因取消订单造成的收入损失以及在退货流程中产生的运营费用,对组织的底线产生积极影响。

假设

解决上述问题的方法是科学的,而不是头脑知识,我们必须定义一个假设:

如果我们知道产品的订单历史和客户行为的历史,那么我们应该能够预测客户下的特定订单最终取消交付的概率。

分析管道阶段

在保持简单性的同时,确保我们不偏离我们的科学方法,我们强调了以下分析管道阶段:

  1. 识别数据集中的模式(又名探索性数据分析 — EDA)。
  2. 从现有特征中提取固有特征以揭示潜在模式(特征提取和工程)。
  3. 将发现传达给涉众,以就模型公式的特征达成一致(领域专业知识)
  4. 模型组成
  5. 生产部署
  6. 确保分析中的可重复研究可移植到组织内的其他用例。

模型、算法和库

由于定义的假设是一个二元分类问题,我们部署了分类技术,如逻辑回归,决策树,随机森林(集成算法)和支持向量机(SVM)。在预测准确性、速度、模型解释和生产部署的便利性方面的性能比较用于确定算法的选择。

对于第一次迭代,使用了 决策树分类器 并在 Python 中进行分析,然而分析可以在 RScala 中重现。使用的库包括:

结果和评价

我们训练模型的方法很简单:

  1. 列车组
  2. 测试装置
  3. 交互效度分析

测试集和交叉验证的准确率分别为 77%74% 。这可能没有那么高,但是决策树分类器的优点在于它的可解释性。

在生产中,我们在预测 A 类时达到了大约 70% 的准确率,在预测 b 类时达到了大约 40% 的准确率。

总体结果是,在 3 个月的时间内,由于确定的问题陈述而产生的间接成本减少了 26% MoM

结论

我们在这里讨论的是一个真实的使用案例,其中我们用数据科学技术处理了一个业务问题,从而创造了真实的、可衡量的业务价值。完成的大部分工作是团队工作,这导致需要数据科学团队,而不是数据科学家。

我希望这能推动企业挑战他们的数据团队,不要讨论最新机器学习工具的花哨,而是与他们一起创造直接的商业价值。

请随时给我留言,通过 LinkedIn电子邮件联系,讨论您的数据机会。

Scala vs Kotlin:务实程序员的实际考虑

原文:https://towardsdatascience.com/scala-vs-kotlin-practical-considerations-for-the-pragmatic-programmer-d50bcc96765f?source=collection_archive---------0-----------------------

source: superkotlin.com

Java 不仅仅是一门语言;这是一个生态系统。您可以不用编写任何 Java 就能为 JVM 编写代码。这让你可以选择使用更现代的语言。Java 的一些缺点是很明显的。这会让你写很多样板代码。它只在事后才支持函数式编程;lambda 特性是一个组装品。NullPointerException 是每个 Java 程序员的祸根。

2004 年,由马丁·奥德斯基领导的一个小组发布了该语言的更新版本,名为 Scala (“可扩展语言”)。它增加了一些特性,比如所有事物的对象、作为可分配数据的函数、类型推断和模式匹配。它编译成 Java 字节码,并且可以与 Java 代码混合使用。

另一种目标相同的语言是由 JetBrains 于 2012 年发布的 Kotlin 。它建立在人们使用 Scala 的经验之上。对 Scala 的一个常见抱怨是编译速度慢,而 Kotlin 提供了与 Java 相当的编译速度。它最近得到了谷歌的大力支持,谷歌宣称它是安卓开发的一流语言。

如果 Java 的一些特性经常让你烦恼,你会发现两种语言都有你喜欢的地方。如果你烦到要跳下去,你该走哪条路?应该选择 Scala 的成熟还是 Kotlin 的新鲜?对双方都有好处。

解题方法不同

Kotlin 和 Scala 和 Java 一样,都是静态类型的。无论一个变量开始是什么类型,它都将在整个生命周期中保持不变。但是这两种方法都省去了你声明每个变量的努力。可以用初始值设定项隐式声明类型。用任何一种语言你都可以写

var count = 1

这使得计数为整数。请注意,不需要分号。这两种语言的区别在于 Scala 在允许隐式转换方面走得更远。如果你使用了 x.transmogrify() ,并且 x 属于一个没有 transmogrify 函数的类,那不一定是错误。你可以创建一个隐式类,它有一个转换方法,编译器会在不需要你做任何转换的情况下,判断出它是否可以介入来完成这项工作。

科特林的创造者发现这有点太自由了。它允许您在一个类上定义扩展方法,添加自定义功能。即使在标准数据类型上也可以这样做。(记住,一切都是对象,所以每个数据类型都是一个类。不再需要简单数据类型的装箱。)

空值在 Java 中是一个非常令人头疼的问题。Scala 从几个方面缓解了这个问题。首先,变量必须初始化。您可以将它们初始化为默认值( var a:Int = _ ),这个值通常为空,但至少它让您意识到您正在这么做。其次,Option 类有助于保证参数和返回值的空安全性。这是这种语言中比较难理解的特性之一,但是它给了你很大的控制权。

科特林直奔主题。默认情况下,它不允许变量的值为空。如果你真的需要,你可以声明一个变量为可空,方法是在类型后面加一个问号。如果您使用过 Swift,这种方法听起来会很熟悉。如果使用可为空的值,编译器会进行大量的检查,以确保不会使它们面临 NullPointerException 的风险,如果会,它会给出一个编译时错误。

如果您只想将一些数据打包到一个对象中,Java 会让您使用常规类或枚举。Scala 和 Kotlin 提供了一些更好的选择。Scala 为您提供了 case 类,它是数据对象的专用类。它自动定义访问器函数(为什么 Java 不这样做呢?).实例通过结构而不是引用进行比较。自动提供一个复制功能来进行浅层复制。

Kotlin 的数据类做了几乎相同的事情。主要区别是 Scala 有一个强大的模式匹配特性,这是 Kotlin 没有的。一个匹配语句就像一个仿生增强的 case 语句。模式不仅可以检查文字值,还可以检查类型、列表和范围。Scala 可以对所有类型的对象进行匹配,但是这个特性对于 case 类尤其强大。

Scala 为 XML 提供了强大的支持。您可以将 XML 直接放入 Scala 代码中,并将其分配给一个 XML 对象。这造成了复杂性,因为后面没有空格的 < 操作符可能被解读为 XML 表达式的开始。Kotlin 使用更传统的类方法来处理 XML 对象。

类型类是 Scala 的一个特性,在 Kotlin 中没有对应的特性。类型类定义了一组成员类必须支持的操作。这不像 Java 中的子类化;可以将类型类添加到已经存在的类型中。它允许开发人员用现有类型创建新的多态类型。Kotlin 中的扩展函数不是一回事,但是它们允许您为不同的类型添加共同点,因此它们解决了一些相同的需求。

语言的感觉

好吧,这两种语言之间是有差异的,但它们的目标或多或少是一样的。哪个都可以学。选择这个或那个有更大的,更哲学的原因吗?

对一些人来说,区别在于 Scala 更旨在探索新的想法,而 Kotlin 更专注于获得结果。Kotlin 对快速编译的强调和对 Scala 一些深奥特性的去除反映了这一点。Scala 只是让你做很多事情。操作员姓名**?:+** 看起来是合法的,也许你想用它是有原因的。科特林的限制更多。有人会说更理智。

如果你喜欢函数式编程,Scala 比 Kotlin 拥有更多的特性。类型类是一种函数式编程特性。再比如,Scala 支持 currying 和 partial application,这是分解接受多个参数的函数的方法。这为使用参数列表提供了额外的灵活性。科特林提供了做同样事情的方法,但它们可能没有数学上的优雅。

学过 Scala 的人彻底爱死它了。这需要更多的努力,但它让开发人员可以做他们在 Kotlin 中做不到的事情。科特林的追随者经常发现,灵活性更令人困惑,而不是有用的。

实际考虑

有时候你想做的事情的现实是主要因素。你需要选择能让你做这项工作的语言,即使你不太喜欢它。如果你打算做 Android 开发,Kotlin 是唯一的选择。Android 不使用 Oracle 的 JVM,所以你不能使用任何旧的兼容 JVM 的语言。Kotlin 拥有在 Android 上编译、调试和运行软件的工具。是 Android Studio 内置的,从 3.0 版本开始。

在 Android 之外,Kotlin 的选择更加有限。您致力于为您的 IDE 开发 Eclipse 吗?在某种程度上,您可以使用它来处理这两种语言。Eclipse 的 Scala IDE 比 Kotlin 插件更成熟,设置起来有点痛苦。一些用户报告说他们很难使用后者。NetBeans 的情况类似。随着科特林越来越受欢迎,一两年后情况可能会更加平等。如果您喜欢从命令行工作,IDE 环境不是问题,Kotlin 有所有必要的工具。

Kotlin 仍在不断成熟,但许多 Java 人发现采用它比 Scala 更容易。哪一个最适合你的需求将取决于你的个人风格和你的实际目标。在做决定之前仔细看看这两者。

解释机器学习的可扩展方法

原文:https://towardsdatascience.com/scalable-methods-for-explaining-machine-learning-f28f2b8f9f13?source=collection_archive---------8-----------------------

机器学习通常被称为人工智能的一部分。然而,越来越多的人感到不安,我们并不真正理解它为什么如此有效。还有对算法失控的担忧。这些批评并不完全公平。设计了一些最成功的算法的该领域的中坚分子确实明白事情为什么会这样。然而,这是一种既模糊又深刻的理解形式。机器学习算法很复杂,解释复杂的对象从来都不容易。但是,随着机器学习作为一个领域的成熟,并在软件中变得无处不在,也许是时候谈论更多有形的理解和解释形式了。

在这篇文章中,我将讨论为什么我们传统的理解方法对机器学习不是很有用。然后我会讨论另一种理解方法,这种方法可能更适合机器学习的特定环境。我在这篇文章中讨论的东西都不是新的。对于经验丰富的从业者来说,这应该是非常熟悉的。这只是我试图把这个领域中一些隐含的智慧表达出来。

复杂系统中的决策

机器学习对于复杂系统中的决策问题最为有用。目标是在给定的特定环境下预测最合适的行动,以引出最理想的反应。在现实生活中,问题几乎从来不用可观察量来表述。因此,第一步是用可观测的量来表述这个问题。这远不是微不足道的,但这不是机器学习的一步。无论你选择哪种解决问题的方法,你都需要采取这一步。

一旦你用可观察的形式描述了这个问题,下一步就是发展一个解决方案的数学形式。解总是被公式化为描述复杂系统的数学函数。这个函数被称为系统的模型。

模型的输入和输出将取决于你的公式。例如,输入可以是上下文动作对,输出是预期反应,或者输入可以是上下文,输出是最佳动作和预期反应,或者您可以选择概率公式,在这种情况下,输入可以是上下文动作反应三元组,输出是这种三元组出现的概率。没有选择配方的通用指南。哪一种方法最有效在很大程度上取决于问题的具体情况。

一旦你选择了你的数学公式,那么你剩下的核心任务就是确定模型。该模型必须与我们对复杂系统的感知一致。我们的感知可以分为两个部分:假设和数据驱动的洞察力。

假设是你对系统做出的独立于任何可用数据的陈述。假设可以进一步分为两个部分:已知的事实和猜测。众所周知的事实是每个人都同意的关于系统的事实,不需要争论。猜测是那些对你来说特定的假设,可以被质疑。猜测可能来自您以前使用类似系统的经验,在这种情况下,它们将是有根据的猜测,并且是可以辩护的。它们也可能仅仅来自你的直觉,在这种情况下,它们很可能是错误的猜测,也很可能不那么有说服力。

当谈到数据驱动的洞察力时,概括地说,有两种方法可以从数据中提取洞察力:手动和自动。人工方式主要包括分析数据趋势,以确定变量之间的函数关系。人工洞察的质量在很大程度上取决于获得这些洞察的人的能力和偏见。但它们确实有更容易解释的好处,因为获得洞见的人应该能够陈述获得所述洞见的逻辑步骤。自动化方式主要包括使用数学优化来确定变量之间的函数关系。给定优化目标的选择,自动洞察的质量独立于任何人。但这也使它们更难解释,因为人们不知道优化方法为获得这些见解所采取的确切逻辑步骤;如果人们知道确切的步骤,那么就不需要自动化的方法,人们可以简单地手动推导它们。手动和自动模式之间没有明显的分界线。相反,在一端完全手动和另一端完全自动化之间有一个连续体。

一般来说,你的假设越强、越多,数据驱动的洞察力在确定模型时的作用就越小。如果你想减少一个或几个特定的人对你的模型的影响,那么你会想减少猜测和人工洞察提取的作用。让我们先来看看这个程序的两个极端:无数据区和无理论区。

在无数据区,你将完全摆脱对数据的依赖,并根据已知事实做出决策。为了能够做到这一点,已知的真理本身应该能够提供一个复杂系统的完整描述。换句话说,你需要一个复杂系统的完整的实用理论。在有趣的现实生活问题中,从来不会出现这种情况——要么我们没有完整的系统理论,要么即使我们有,我们也没有办法计算上述理论的结果。

在无理论区,你可以完全抛弃假设,只根据数据构建模型。从数学上来说,这意味着你需要模型所有可能的输入和输出数据。除了这种数据永远不可用这一事实之外,这完全违背了建立模型的初衷。您可能希望构建一个模型,以便它可以从一个样本推广到整个人群。如果你有整个人口的数据,那么就没有必要建立一个模型。

因此,仅仅基于假设或仅仅基于数据建立模型既不可行也没有用。机器学习的价值在于从决策过程中完全消除猜测和手动洞察的作用,并提供完全基于已知事实和全自动数据驱动洞察的解决方案。不幸的是,我们还没有到那一步。此时,每个机器学习模型都会包含一些猜测和人工数据驱动的洞察。

正如我们所讨论的,已知的真理不需要解释。猜测和人工洞察相对容易解释。解释机器学习的关键在于解释自动化数据驱动的见解。这种解释意味着什么?一个解释与期望的概念密切相关。通常,如果我们能以某种方式表明某件事的行为与我们的预期一致,我们就说我们对这件事有了解释。因此,解释取决于能否形成预期。

为了解释机器学习模型,我们需要能够形成对它的期望,独立于用于构建它的过程。此外,这种形成预期的方法应该比构建模型的过程更简单,否则我们将需要另一种方法来解释预期形成方法——这将违背解释的全部目的。这立即排除了精确和全面预期的可能性。如果我们确实有一个更简单的方法,可以用来准确预测模型在所有可能场景中的行为,那么我们将简单地使用该方法来构建模型,而不是原来的方法。因此,我们能达到的最好目标是近似的和/或部分的解释。

如何不解释

在我们讨论一个可能行得通的解释方法之前,让我们先讨论一些几乎肯定行不通的解释方法。我们可以把这些方法看作后验方法。换句话说,这些方法以某种方式试图将最终优化的模型分解成部分,并解释这些部分。例如,我们可能希望将模型的输出视为以某种方式独立地受到具有某些权重的输入的影响。对于强相关系统来说,这是非常危险和完全错误的。这里很好地解释了为什么在机器学习模型中基于特征权重来判断变量重要性不是一个好主意。因此,如果输入变量是相关的,这种方法根本不起作用。

另一种选择是用小块拼出模型的区域,这样在每个小块上,你可以用一个简单的函数得到模型的精确的局部近似。然后,我们可以将整个模型想象成这些简单的局部近似的拼凑,并询问这些局部近似的行为是否与我们的预期一致。这种方法非常类似于使用等价类划分来理解和测试传统软件的方式。

问题是我们认为什么是简单函数?对大多数人来说,很难想象三维空间以外的情况,这意味着一个简单的函数最多只能有两个独立变量。此外,我们会发现很难对具有一个或两个以上极值的函数进行推理。当我们将这些约束强加到一个简单函数的定义中时,我们将会看到,所需的面片数量随着输入变量的数量和模型极值的数量呈指数增长。

如果我们在操作上将函数的复杂性定义为输入的数量、极值的数量和变量之间的相关性的强度的某种组合,那么上述解释方法就不起作用,因为它们在复杂性方面不能很好地扩展。这些方法没有规模,因为它们试图建立一个后验还原近似。一个可伸缩的方法不需要考虑最终的模型,而是优化方法本身。为了扩大规模,它需要为如何做出决策建立全局近似,而不是为每个单独的决策建立近似。

从对称性开始

首先,我们需要阐述我们的术语。在机器学习中,人们从已知的真相、猜测和人工数据驱动的见解开始。这些在数学上表示为部分定义的多元函数,称为算法。除了输入和输出,算法还将有一组未确定的参数。通过用数据训练算法来固定参数。训练算法本质上是以自动化的方式从数据中提取洞察力,它通常涉及解决优化问题。用数据训练算法的结果是一个完全定义的函数,称为训练模型。到目前为止,我们讨论的模型都是经过训练的模型。优化的目标函数以这样的方式设置,即最小化它将意味着训练的模型捕获与该特定问题相关的数据中的稳定模式。

解释的第一步是清晰。在我们解释任何事情之前,我们需要明确起点。在机器学习中,起点是已知的真相、猜测和人工数据驱动的见解。对于任何给定的问题,我们只能在给定这些出发点的情况下提供一个解释。因此,需要非常清楚和全面地陈述它们。

问题几乎总是用领域的语言来表述。然后你可以用一种表示法把它转化成一个数学问题。当你做这个翻译时,问题的复杂性就显现出来了。任何解释如果能够根据问题领域的期望来提供,而不是根据为解决方案选择的特定表示来提供,那么它也将具有更高的效力。因此,起点有更好的机会随着复杂性扩展,并且如果它们按照领域的语言而不是表示的语言来陈述,它们将具有更高的解释能力。

但是,当我们说应该用领域的语言来陈述起点时,我们到底是什么意思呢?在机器学习的情况下,起点通常是关于什么与问题相关的陈述。让我们考虑机器学习最成功的应用之一的例子:图像识别。深度学习是机器学习的一种,已经被证明在分类图像方面非常成功。不仅如此,我们实际上对深度学习为什么对图像识别如此有效有了相当好的理解。这种成功和理解的主要原因之一是我们设计了将图像域的相关对称性编码到相关算法(深度神经网络)中的方法。在这种情况下,对称本质上是一种不改变结果的变换。对于图像,这些对称性是分辨率、旋转、平移等的变化。卷积神经网络本质上是神经网络语言中这些对称性的编码。

对称是以一种整体的方式陈述我们关于相关性的知识的最经济的方式。对称告诉你什么是不相关的。除此之外,其他一切都可能是相关的。它们使我们能够以独立于数据的方式识别对于给定领域什么是相关的,什么是不相关的。他们对算法的函数形式进行约束,而不是对模型的局部行为进行陈述。为任务选择的算法类别必须足够强大,以适应域的对称性。如果训练数据具有足够高的质量和数量,那么模型行为不当的主要原因将是错误的对称性被无意中编码到算法中。

对于图像识别,我们有一个清楚的例子,当对称性被用作它们的基础时,产生的算法是成功的和可理解的。毫无疑问,形式化一个领域的相关对称性并将其编码到机器学习算法中是非常重要的。图像识别是一个“简单”的例子,因为我们对图像的对称性非常熟悉。然而,我认为对称性对于理解机器学习至关重要。只要有可能,一个算法的起点应该被表述为定义域的对称性。

逐次全局逼近法

对称性会对算法的参数空间施加一些限制。剩余的参数欠定将通过训练来消除。我们现在需要一条将对称性连接到模型的路径。这相当于在施加对称性和模型中完全定义的参数之后,找到连接算法中部分确定的参数的路径。我们将使用的方法是逐次全局逼近法。

我举个例子说明一下。假设您请求一个地图服务(如 Google maps)来查找一个城市中两个位置之间在旅行时间方面的最佳路线。为了节省时间,地图服务的算法通常会生成一条包含许多转弯的路径。如果你手边没有地图服务,如果你像大多数人一样,那么你可能会选择最少混乱的路线,即转弯次数最少的路线。本质上,您是在解决地图服务算法问题的一个受限版本。您首先要检查是否有一条完全没有转弯的路线。如果是这样的话,你会选择这条路线。如果这样的路线不存在,那么你将寻找一个转弯的路线。如果这样的路由存在并且是唯一的,那么您将选择该路由。如果有多条这样的路线,那么你会选择花费最少时间的一条。如果没有这样的路线,那么你可以尝试一条有两个转弯的路线,以此类推。

理解地图服务生成的路径的一种方法是继续上述过程,直到到达地图服务生成的路径。假设您的解决方案有两个转弯,而地图服务生成的解决方案有五个转弯。你现在可以尝试依次寻找三圈、四圈、五圈和六圈的解决方案。在每种情况下,你都可以看到增加一个转弯节省了多少时间。当从五个转到六个转时,你应该能够看到增加一个转并不能节省更多的时间,也许还会增加旅行时间。

注意,在上面的方法中,我们并没有试图孤立地理解地图服务产生的每个转弯。相反,我们着重于把整个解决方案理解为一系列近似的终点。一般来说,人类的大脑还不能很好地从整体上把握复杂功能的行为。但它相当擅长理解基于两个复变函数之间差异的“有效理论”。这就是为什么上面的方法是理解的有用工具的原因。

在研究复杂系统的许多不同学科中也使用了类似的方法。事实上,即使在机器学习中,我们在针对基线模型对模型进行基准测试时也使用类似的想法。例如,当试图确定一个分类器有多好时,人们会将其性能与随机分类器的性能进行比较。基准模型只不过是优化问题的解决方案,附加的约束条件使解决方案“更简单”。我们可以通过显式地构建连续的基准作为约束优化问题的解决方案,将这种基准测试方法转变为一种解释方法,其中在每个连续的步骤中,我们移除一些约束。换句话说,我们将优化的解决方案解释为一系列逐次逼近的最终结果。

面对复杂性,逐次逼近的次数应该是可伸缩的,这在上下文中意味着该次数应该是独立的,或者在最坏的情况下弱依赖于算法中参数的数量。确保这一点的一种方法是将导致近似的约束框定在与参数的表示相邻的表示中——广义傅立叶空间。逐次逼近可以看作是在解中逐渐包含高阶波动。

与对称性相似,构造连续的全局近似并不容易。一个人需要有非常深厚的专业知识,才能对一个复杂的系统进行全局而非局部的思考。但是复杂系统之所以被称为复杂是有原因的,如果认为我们能够理解它们,并在没有必要的专业知识的情况下以解释的形式传达这种理解,那就太天真了。

机器学习是游戏规则的改变者。它已经被证明是非常成功的,毫无疑问,它是我们目前所知的为复杂系统构建软件的最强大的方法。但是,成功之后一定会有智慧。我们理解软件的传统方法不足以理解机器学习软件,因为它们不能很好地适应复杂性。另一方面,对称性和连续的全局近似确实与复杂性成比例。我试图讨论当一起使用时,它们如何能够提供一种可扩展的方法来解释机器学习。

可伸缩的 Web 开发

原文:https://towardsdatascience.com/scalable-web-development-d57a46a7f349?source=collection_archive---------1-----------------------

开发一个简单的具有可伸缩性的 web 应用程序

如今,随着移动接入的增加和电子商务的发展,web 服务变得越来越流行。任何想出一个网站的人肯定会希望它能吸引越来越多的访问者。

但是,首先,我们是否要使用整个服务器场来预期 100 万用户?,这可能是 5 年后的目标。答案是否定的。但是我们要完全忽略我们真诚的期望,建立一个静态的网页吗?。又一个大不了!!!。让我们看看我们能做些什么。

首先要考虑的事项…

简单来说,让我们继续使用 5W 框架,这是一种公认的收集信息和解决问题的方法。让我们在应用框架时考虑到可伸缩性,并在此基础上进行开发。

什么?

对于我们的场景,这是一个 web 应用程序。但是首先要问的问题应该是它是一个 web 应用程序吗?可能不是。目前是这样。

为什么?

web 应用程序的目的。以下是目前常见的一些常见用例。

  • 电子商务—需要安全、SSL 和其他认证。
  • 交互式应用—社交网络、教育、博客,其中有大量用户同时访问和流式传输内容。
  • 信息显示——只是展示内容,没有太多的严肃计算。
  • 分析平台——异步/同步接受请求和服务器。基于发布/订阅的处理(PubSub)。提供接口来执行功能的 API。很少有昂贵的处理会运行更长的时间。

什么时候?

我们什么时候部署产品。时间就像 【时间就是金钱】 一样至关重要。我们花费的时间越多,我们为软件过程支付的费用就越多。随着现代敏捷实践的发展,人们更加关注 编码 而不是文档。因此,必须遵循清晰的架构,并定期进行沟通。否则会发生这种事。

Failed Design: source

从高度可扩展的解决方案开始,从设计阶段开始,肯定会花费更多的时间。开始太简单会增加返工的额外压力。因此,在实际开发之前,必须达成折衷方案。我们将看到如何…

在哪里?

其中 有几种形式。

  • 我们的目标市场在哪里?
  • 我们在哪里?
  • 我们将在哪里部署产品/项目?

这些问题主要通过业务分析来解决。然而,作为工程师,由于延迟、安全性和负载平衡的原因,我们更喜欢将服务部署在离目标客户/用户群更近的地方。

谁啊。

我们的目标是谁。他们的访问模式是什么。时区等等,都在这一节中。这是因为,此类信息直接显示了一段时间内工作负载分布的性质。在两个时区工作有时会使发布变得容易,因为我们可以预期在开发中心的工作时间会有较低的工作量。或者,我们可能需要在维护期间提供冗余服务器来满足请求,以获得更好的 QOS(服务质量)。

可扩展的解决方案

现在让我们考虑构建可伸缩解决方案的 web 应用程序场景。提前考虑总是好的,但不能超出可预见的未来。

可维护性和可扩展性

我们所做的任何事情都必须是可持续的。否则在版本的每个发布中都会有大量的返工。因此,适当的 关注点分离 必须在整个项目中实施。

Layering

该图显示了两个数据库实例的内容分层。负载平衡用于同时使用两个实例或一次使用一个实例作为故障保护模式。

连接组件

它总是有单独的组件,并传递消息进行通信。这将增加沟通,但这可以很好地扩展,也很容易维护。下图显示了实施中组件的组织。这与上图不同。这并没有演示信息的实际流动,而是用技术术语演示了组件的分离。

Arrangement of components in actual implementation

通常使用 NGINX (过去使用 Apache ,微软有 IISPassenger 用于 Python 和 Ruby)路由请求。容器通常运行在不同的端口,但是我们通常只向外界公开端口 80(出于安全原因),这样就没有外部的人可以连接到我们的数据库。

样品流

  • 用户请求www.mydomain.com,这个请求将被路由到 HTML 静态内容。
  • 静态内容将被加载到用户浏览器中。这主要是一个角度或反应的应用。这是因为,不像过去我们使用 PHP、JSP、JADE、Twig 或 Blade 来制作模板,我们不再那样做了。它使我们的应用程序与 API 和请求控制器保持耦合。
  • 一旦内容被加载,所有其他工作通常通过调用 web API 来完成。例如,登录请求如下所示。
"method": "POST",
"body": {
    "username": "anuradha",
    "password": "password1234"
},
"headers": {
    "content-type": "application-json"
}
  • 这些请求作为一个post请求被发送到 url www.mydomain.com/login。这些将被 NGINX 定向到认证服务器。成功后,将为 web 应用程序提供一个令牌。这些被称为 JWT (JSON Web 令牌)。这些将用于以后验证用户。
  • 所有到来的请求都将被发送到www.mydomain.com/api/somepath.,NGINX 将把/api/请求路由到 API 容器。JWT 必须作为标题以authorization: bearer <token>的形式发送。显然,为了防止有人劫持您的令牌,必须使用一个https连接。

为什么是集装箱

容器是轻量级的虚拟化层,主要运行 linux 内核。使用它们是因为它们可以比虚拟机启动和终止得更快。此外,它们不会像虚拟机那样消耗大量资源。

此外,该容器支持内容的安全部署。举例来说,供应商可以在为特定环境进行配置后为 API 提供 Docker 映像,而不必发送代码库。

在某些情况下,NGINX 本身是一个容器,用来处理大量请求并路由到大量其他容器。点击看看!

弹性豆茎一瞥

Elastic Beanstalk

这是一个提供许多 web 服务器的平台,这些服务器可以随着负载的增加而扩展。他们监视资源利用率,并不断自动添加资源,并相应地收费。由于易于部署,这已经变得流行起来。用他们自己的话说就是,

Elastic Beanstalk 不收取额外费用——您只需为存储和运行应用程序所需的 AWS 资源付费。

优势
*简单
*自动扩展
*资源监控
*提供所需的所有基础架构组件
*安全

他们没告诉你的关于扩展人工智能的事

原文:https://towardsdatascience.com/scaling-ai-2be294368504?source=collection_archive---------10-----------------------

现在有 AI 的一切的教程。如何做物体检测,图像分类,自然语言处理,建立聊天机器人等。,这样的例子不胜枚举。

但是当我寻找如何恰当地缩放人工智能的信息时,我发现内容很少。更令人惊讶的是,确实存在的少数资源似乎重复了相同的几点:

  • 使用像 TensorFlow 这样的可扩展框架构建您的模型
  • 要么打包到你的客户端(TF.js,TF Lite,TF-slim 等。)或者将其部署为带有容器的微服务

我对第二部分更感兴趣,因为我已经开发了一个模型,但令我惊讶的是,几乎没有提供关于如何实际实现这一点的细节,关于每个解决方案的缺点的信息甚至更少。在研究了几天并在 Crane.ai 上扩展 AI 之后,我收集了一些关于部署的更多信息**,它们的缺点,以及如何在低层次上优化你的 TensorFlow 模型。**

把它打包到你的客户身上——糟透了!

最常用的技术之一是使用 TensorFlow.js、TF Lite 或 TensorFlow Slim 等工具将 AI 打包到您选择的客户端中。关于这些框架是如何运作的,我不会讲太多细节,而是集中讨论它们的缺点。

  • 计算能力。部署这些型号的问题在于,它们需要巨大的内存(我指的是移动应用或浏览器的限制,即>1–2GB 内存)。许多手机没有这种能力,桌面浏览器会延迟 UI 线程,同时也会降低用户计算机的速度,加热计算机,打开风扇等等。
  • 推断时间。当你在一个计算能力未知的设备上运行模型时,推理时间通常也是未知的;然而,这些不是 GPU 驱动的高 RAM 高 CPU 机器,而是运行在普通计算机上的手机、浏览器和桌面应用程序。用一些更大的模型进行推理可以轻松地占用一分钟,从用户体验的角度来看这是一个巨大的

Stolen from a Reddit parody of XKCD 303

  • 大文件。不幸的是大多数模型都存储在相当大的文件中(我们说的是几十、几百 MB)。因此,这将是缓慢和内存密集型加载,并增加了你的应用捆绑包的大小很大一部分。
  • 没有安全感。除非您使用开源模型,否则您会希望将您的 AI 和预训练检查点相对保密。不幸的是,当你把你的模型和你的应用打包在一起时,不仅你的推理代码容易被反编译,而且你的预训练检查点也会在包里面,很容易被窃取
  • 更难更新。如果您更新您的模型,您在客户端有两种选择。要么通过集中式管理器(即,Play Store、App Store 等)向用户发布更新。这导致频繁的大规模更新(对于用户来说非常烦人,并且根据他们的设置,进程可能会被中断或永远不会启动),或者应用程序本身运行新模型检查点和元数据的获取。后者听起来好得多,但这也意味着你必须通过用户可能不稳定的连接下载 100MB 以上的文件;这将需要一段时间,因此你的应用程序必须至少在后台打开才能完成这个过程,而且你会产生相当大的互联网成本(这取决于你的云)。

  • **缺乏可训练性。**针对新用户数据的训练模型提供了一定程度的个性化,同时提高了其准确性,并建立了一个核心的高信号数据集。不幸的是,大多数设备缺乏训练模型的计算能力,即使它们有,也不可能将训练的效果传播到您的服务器或运行应用程序的其他设备。

这些缺点使得在客户端上部署和维护大型神经网络几乎是不可能的,因此我们将排除这个作为扩展模型的选项。

将其部署为云端点

XKCD 908, and 1117 is also relevant

是大规模部署模型的强大工具。您可以启动完全根据您的需求定制的环境,将您的应用程序容器化,并立即进行水平扩展,同时提供可与大公司媲美的 SLA 和正常运行时间。

对于大多数 TensorFlow 模型,部署周期是相同的:

  • 将您的图形冻结成 Protobuf 二进制文件
  • 调整您的推理代码以处理冻结的图形
  • 容器化您的应用程序
  • 在顶部添加一个 API 层

第一块比较简单。“冻结”您的图需要创建一个 protobuf 二进制文件,其中包含与您的检查点相关的所有命名节点、权重、架构和元数据。这可以通过各种各样的工具来完成,最流行的是 TF 自己的工具来冻结任何给定了输出节点名称的图。你可以在这里找到更多关于这个技巧以及如何完成它的信息。

调整您的推理代码也不难;在大多数情况下,您的feed_dict将保持不变,主要的区别将是添加代码来加载模型,可能还有输出节点的规范。

容器化也很简单——只需在 Dockerfile 中设置你的环境( 你可以使用一个 TF docker 镜像作为你的基础 **)。**当我们开始添加 API 层时,事情开始变得混乱。通常有两种方法可以做到这一点:

  • 部署运行推理脚本的缩放容器。这些容器针对输入运行一个脚本,该脚本启动一个会话并运行推理,然后输出一些东西,结果通过管道返回给您。这是极有问题的;对于大多数云提供商来说,添加一个操纵容器和管道进出的 API 层并不容易或简单(例如,AWS 有 API Gateway,但它远没有你想象的那么方便),这是你可以使用的效率最低的方法。这里的问题是您在容器启动、硬件分配、会话启动和推理中损失了宝贵的时间。如果您让stdin保持打开并保持管道输出,您将加速您的脚本,但是会失去可伸缩性(您现在被连接到这个容器的 STDIN,并且它也不能接受多个请求)。
  • 部署运行 API 层的扩展容器。尽管在体系结构上相似,但出于几个原因,这要高效得多;通过将 API 层放在容器中,您可以缓解之前提出的大部分问题。虽然这需要更多的资源,但这是最小的,并不意味着垂直扩展;它允许每个容器保持运行,并且因为在这种情况下 API 是分散的,所以将特定的stdin / stdout挂接到主请求路由器没有问题。这意味着您摆脱了启动时间**,并且可以在服务多个请求的同时,轻松保持速度和水平缩放**。您可以使用**负载平衡器、**集中您的容器,并使用 Kubernetes 来保证几乎 100%的正常运行时间并管理您的设备。简单有效!

Deploy your fleet!

通过集装箱船队分散 API 的主要缺点是成本会相对较快地增加到一个大数目。不幸的是,这是人工智能不可避免的,尽管有一些方法可以减轻这一点。

  • 重用你的会话。您的车队随着负载成比例地增长和收缩,因此您的目标是最小化运行推理所需的时间,以便容器可以释放空间来处理另一个请求。一种方法是重用 **tf.Session** **tf.Graph** ,一旦初始化就存储它们并作为全局变量传递它们;这将消除 TF 启动一个会话和构建图所花费的时间,这将大大加快您的推理任务。这种方法即使在单个容器上也是有效的,并且作为一种技术被广泛使用,以最小化资源重新分配和最大化效率。
  • 缓存输入,如果可能,缓存输出。动态编程范式在 AI 中最为重要;通过缓存输入,可以节省预处理输入或从远程获取输入所需的时间,通过缓存输出,可以节省运行推理所需的时间。这在 Python 中可以很容易地完成, 尽管你应该问问自己这对于你的用例是否正确! 通常情况下,你的模型会随着时间变得更好,这将极大地影响你的输出缓存机制。在我自己的系统中,我喜欢使用我所谓的“80-20”法则。当一个模型的准确率低于 80%时,我不缓存任何输出。一旦达到 80%,我就开始缓存,并且将缓存设置为在某个精确度到期(而不是说,在某个时间点)。这样,输出会随着模型变得更加精确而变化,但在这种 80–20减轻的高速缓存中,性能和速度之间的权衡较少。

  • 使用任务队列。经常有较大和较小的推理任务需要运行(在我们的例子中,较大和较小,复杂和简单的图像)。对于 UX 来说,在这里使用堆队列可能更好,并且处理优先级为的较小的任务,这样运行小步骤的用户只需等待该步骤,而不是等待另一个用户的较大推断先完成。(如果你在想,*为什么我不在这里只是水平缩放呢?,*你可以但是会增加成本
  • **在带有任务队列的专用 GPU 上训练您的模型。**培训是一项漫长而艰巨的任务,需要大量的资源使用,并使模型在其持续时间内不可用。如果你将每个交互反馈到你的模型中进行训练,**考虑在一个单独的服务器上运行这个,**也许用一个 GPU。一旦训练完成,您就可以将模型部署到您的容器中(在 AWS 中,您可以将您的模型库集中在 S3)。

结论

经过深思熟虑,我们提出了一个大规模部署人工智能的有效工作流程:

  • 冻结图形并在一个 API 下包装推理
  • 重用会话和图形,并缓存输入和输出
  • 使用 Docker 封装应用程序(包括 API 层
  • 使用 Kubernetes 在您选择的云上大规模部署应用
  • 从推理中分离出训练
  • 开发一个任务队列来优先处理较小的任务

使用这些技术,您应该能够以最小的成本和开销进行部署,同时最大限度地提高速度和效率!

关于我:我是 Crane.ai (我们用 ai 做 app)的 AI 研究员。在过去的几年里,我一直在研究人工智能,今年花了几个月的时间研究如何扩展人工智能!我希望这是信息,如果你有任何问题,请随时询问。

用 Python 扩展分析洞察力(第 2 部分)

原文:https://towardsdatascience.com/scaling-analytical-insights-with-python-part-2-73b45ce9584e?source=collection_archive---------6-----------------------

在这篇第二部分的文章中(第一部分可以在这里找到****),我将结合几个我认为非常有用的资源,这篇文章将结合一些关键的分析,以便更好地了解直接面向消费者的订阅/ SaaS 客户群。** 为了将所有这些融合在一起,我还将使用我最喜欢的数据分析/数据科学工具之一, 模式分析 最后,我希望你会发现既有用又酷的是一份开源模式分析报告,可以在这里找到;这是我在 FloSports 担任数据仓库和数据分析主管时制作的报告类型的精简版本,所有代码和可视化都可以克隆到您自己的模式报告中,并重新用于类似的数据集(假设您创建了一个帐户,该帐户对公共数据集是免费的)。如果你没有 Mode Analytics 帐户,并且还没有被说服注册,你应该仍然能够访问 Python 笔记本,并且你还将在 这个链接 看到所有底层 SQL 查询。

快速总结这篇文章将涵盖的内容(注意,每一部分都将使用 Greg Reda 在他的原始文章中引用的相同电子商务用户数据集,在此处找到):

  1. 重新创建第 1 部分的订户群组和保留分析,这次使用 Mode 的 SQL + Python
  2. 利用 Ryan Iyengar 的一篇出色的博客文章,使用指数衰减在 SQL 中创建一个预计的 LTV 分析,这篇文章可以在这里找到
  3. 开发 RFM(近期、频率、货币价值)分析,这是电子商务网站用来细分和更好地了解用户/订户购买行为的一种方法
  4. 在一份全面的开源模式报告中,使用 SQL 和 Python 的简要记录和可视化展示所有这些是如何联系在一起的

同样,模式分析报告在此处可用 —您不需要创建模式分析帐户来查看报告,但是,克隆它需要一个免费帐户。原始数据集可以在之前提供的链接中找到,其他所有内容(SQL、Python 代码、如何构建图表和 Python 可视化)都可以在链接的报告中找到。

首先,我将 relay-foods 数据集作为一个公共文件添加到 Mode 上— 这里是 Mode 关于如何做的说明(我还添加了一个空前数据集,在计划的 LTV 部分会有更多)。这部分帖子中的 Python 代码可以在报告的笔记本部分这里找到;这与我在上一篇文章中使用的代码相同——不同之处在于,从 SQL 查询创建的数据帧是在模式 Python 笔记本中使用的。此外,下面提供的 SQL 代码显示了我在这个数据集上采取的一个小的数据丰富步骤,其中我将用户的第一次付款归类为“初始”,将任何后续付款归类为“重复”。这是可以应用于数据源的业务逻辑类型的一个相当小但快速的例子,通常使用我在过去提到过的聚合事实表。

**with payment_enrichment as (

  select

    order_id
    , order_date
    , user_id
    , total_charges
    , common_id
    , pup_id
    , pickup_date
    , date_trunc('month', order_date) as order_month
    , row_number() over (partition by user_id order by order_date) as payment_number

  from kdboller.relay_foods_v1  
  )

  select
    pe.*
    , case when payment_number = 1 then 'Initial' else 'Repeat' end as payment_type

  from payment_enrichment as pe**

作为这一分析的下一步,我将建立一个预测的 LTV 分析,参考我之前提到的另一个有用的在线资源——Ryan Iyengar 一年多前在 Medium 上发布了这篇预测 LTV 邮报,在这里找到了。如果您曾经在 Excel 中进行过 LTV 分析,您会知道这可能相当耗时,并且这些模型可能会变得非常大,并且远不如您所希望的那样动态。您可能认为必须有更好的方法来计算单个值,这对于了解订阅业务的健康状况至关重要。幸运的是,至少有一些更好的、高度可重复的方法可以做到这一点。此外,评估群组的不同开始/结束日期范围以包括,例如,对特别强的“早期采用者”群组进行标准化,是在 SQL 和/或 Python 中进行这种类型的分析的显著优势。

综上所述,Ryan 的文章肯定需要对 SQL 有一个相当透彻的理解,特别是考虑到公共表表达式(cte)的重要用途。鉴于结果查询的长度,我没有直接粘贴到这篇文章中,但是您可以在模式报告中找到最终查询的几个构建。如果你对我这篇文章的背景或理由有任何疑问,我会推荐你参考他颇有见地和丰富的解释。出于我的文章和报告的目的,我已经展示了如何从我们正在使用的原始数据集创建所需的数据返回,从下面的数据集提供了一些观察数据,还展示了 LTV 部分的一些关键图表,Mode 允许我轻松地将这些图表添加到我的整体报告中。

LTV 部分—查询摘要

****与 LTV 相关的 SQL 查询,借用了 Ryan 非常有用的工作,从报告中的编号 2-8 开始。在 Mode 中,我尝试使用该系统对我的查询进行排序,以便跟踪在一个项目中编写的查询的自然进展— 一个很好的功能请求是拥有某种类型的文件夹系统,以便将这些查询组织到支付、LTV 和 RFM 查询部分。查询#2 操作数据集,以便拉回与 Ryan 在他的帖子中使用的数据集一致的返回结果——因此,这有望使它更容易理解。我还构建了查询中断来模拟 Ryan 在他的博客帖子中暂停的地方,这样就可以更容易地在他的帖子和我创建的模式报告之间进行跟踪。

在查询 4–6 中,您将看到在执行此操作时,我在一个群组中检测到异常情况(参见本段下方的屏幕截图)。在 2009/04/01 年度,在最近的三个月中,该集团的收入份额实际上大幅增加;虽然用户离开一个群组然后又回来的情况并不少见,但这明显扭曲了预测收入,因此也扭曲了这个特定群组的 LTV。因此,该模型并没有预测收入的下降,而是预测每月增长 20%以上(整个预测)。虽然可能有一些首选的方法来规范这一点,但出于时间的考虑,我决定从整体分析中排除这一群体——我要说的是,几乎每个分析中都有类似的事情发生,显然审查数据并确定如何根据需要进行调整至关重要。考虑到公司的行业、未来前景和成熟度,调整决策会有所不同。

查询 7 和 8 以最终预期回报完成查询,一个显示每个群组的预计 LTV,一个显示考虑所有群组的预测预测和初始用户时的总体预测 LTV。正如您从下面的屏幕截图中看到的,从模式报告输出中复制的,总的 LTV 是大约 315 美元。除此之外,我们看到初始群组(最有可能是“早期采用者”)的 LTV 比随后几个月中看到的要高得多——注意,我们只有 12 个月的群组进行评估,这是一家很少出现的新公司。鉴于此示例,接下来的步骤可能包括进一步细分用户并找到每个 LTV,以及通过从该分析中排除“早期采用者”的贡献来潜在地标准化整体 LTV。同样值得注意的是,随着最近队列数量的增加,LTV 会降低很多,我们希望了解,随着时间的推移,我们是否能够更有效地扩大我们的用户群,同时理想地扩大或至少维持我们的 LTV。 请注意,在完成此类分析时,您还应该计算毛利润,或者最好是边际贡献,以反映每个订户的真实基础经济和 LTV。

RFM 分析

在这最后一节,我已经包括了一个近期,频率,货币价值(RFM)分析。在回顾有效的用户细分方法的过程中,在发现这种方法后,我在 Joao Correia 的 GitHub 上找到了这个有用的笔记本。这里是 RFM 的一个非常简短的纲要。

****新近度:从评估日期起,例如今天,用户/订户已经从网站购买了多近。

****频率:用户/订户一生中在特定网站上购买的次数。

****货币价值:用户/订户在其作为客户的整个生命周期中从其所有购买中支付的美元总额。

虽然有几种方法可以完成 RFM 分析,包括通过 SQL,但我在这里的部分意图是展示如何使用一个相当简单的初始数据集来重新利用其他人的有用工作。在《Python 笔记本》中,RFM 分析了第部分,你会发现我在很大程度上遵循了若昂的笔记本。正如在他的笔记本结论中,我在下面显示了 RFMClass 111 中的前十名客户—这代表了在所有三个 RFM 指标中处于前四分之一的用户;这些用户是最近才付费的,而且比该网站 75%的其他用户付费次数更多,货币价值也更高。因此,这些用户是定性调查的主要对象,这些调查要求对他们喜欢什么和什么可以做得更好进行反馈,你也可以研究他们的网站行为,了解他们可能在做什么,发现哪些与其他访问者不同,以及你可以接受的几种不同的评估。

在模式报告中使用 Plotly,然后我添加了三个可视化工具,帮助我更好地理解数据,也是为了预测来自业务利益相关者的潜在问题。第一个显示了每个 RFMClass 中的用户分布。积极的一面是,81 名用户属于 111 类,但 75 名属于 344 类,65 名属于 444 类——这些用户已经有一段时间没有付费了,他们的付费次数和货币价值也远低于所有用户的中值。我们想看看我们是否能复活这些用户,或者是否发生了什么事情导致他们(几乎)再也不会回到我们的网站。

最后,我想知道每一个 RFMClass 指数是如何根据群体分组的——早期的群体是那些主要在 111 类中的群体吗?如果是这样的话,这可能是一个令人担忧的原因。为了完成这一部分,您将在 Python 笔记本中找到“合并数据以显示按群组划分的 RFM 等级”一节,在这里,我提取了初始付款数据帧的子集,并将其与创建的 rfmSegmentation 数据帧合并。如果你需要一本关于在 Python 中合并数据帧的入门书,类似于 SQL 中的 join,我会推荐你到另一个 Greg Reda 帖子这里

回顾下面的两个图表,第一个是按群组划分的总用户,第二个是按群组划分的 RFM 111 级用户,我们看到 RFM 111 级的最大贡献者来自 2009 年 11 月和 2010 年 1 月。然而,当我们回顾第一张有每个群组用户总数的图表时,我们看到 2009 年 11 月是一个特别大的群组,相对来说,并不是 RFM 顶级用户的主要来源。更好的输出将为每个群组计算每个月群组中 RFMClass 111 用户所占的百分比;但是我将把它留给下一次/可能是后续的帖子。

这是一篇我很喜欢整理的分析文章的结尾。希望这传达了超越 Excel 的价值,利用有洞察力的人的公共贡献以及 SQL 和 Python 等工具的好处。

关于使用 Mode 的好处的一些快速说明( )此外,这里有一篇来自 Mode 的博客的帖子 ,关于他们如何从 Excel 转向 SQL 和 Python:

  • 可以用 SQL(内置图表功能)或 Python 轻松创建图表;然后,这些图表与您的数据查询相关联,并将自动更新
  • 报告具有很高的可复制性,如果您想保留以前的报告,例如季度业务回顾
  • 减少了创建数据集并以 CSV 格式读入 Jupyter 笔记本的需求;您可以将每个查询作为数据帧直接读入 Mode 的 Python 笔记本中
  • 我说这些是有警告的,并不是所有的 Python 库在 Mode 中都可用,尽管有相当一部分是可用的,并且计算能力是 Mode 不断寻求改进的一个领域

从一个非常基本的用户数据集开始,利用模式分析的全部功能,我们能够完成以下工作:

  • 在 Mode 的平台上贡献两个公共数据集
  • 通过 SQL 和 Python 将用户按月分组
  • 在 Python 中为这些月度群组构建保留曲线/保留热图
  • 在 Python 中计算群组的加权平均保留曲线
  • 使用 SQL 为整个公司和每个团队设计 LTV 项目
  • 进行 RFM 分析,了解 Python 中每个类的分布以及每月群组的贡献——这是通过在 Mode 的 Python 笔记本中合并两个数据框架(一个由 SQL 和 Python 共同创建,另一个由 Python 直接创建)来完成的
  • 最后,我们创建了一个(希望如此)直观、全面的开源报告
  • 就添加额外的分析而言,该报告是相当可扩展的,并且也可以随着新的每月数据的滚动而容易地更新

希望你发现这篇文章和我发现的 Mode 一样有帮助,以及参考的文章被用来制作这份 Mode 报告,如果你有任何问题或想法,请在评论区告诉我。

用数据流扩展游戏模拟

原文:https://towardsdatascience.com/scaling-game-simulations-with-dataflow-172926612d50?source=collection_archive---------9-----------------------

The GUI version of the Game Simulation

数据流是构建可扩展数据管道的一个很好的工具,但它也可以用于不同的领域,如科学计算。我最近使用谷歌云数据流工具的方法之一是模拟不同自动化玩家的游戏。

几年前,我制作了一个自动俄罗斯方块播放器,作为加州理工学院人工智能课程的一部分。我使用了元启发式搜索方法,这需要大量的训练时间来学习超参数的最佳值。我能够编写系统的分布式版本来扩展这种方法,但是在实验室的 20 台机器上部署它需要很大的努力。使用现代工具,将这些代码扩展到几十台机器上运行是很容易的。

出于多种原因,在游戏中模拟自动玩家是很有用的。最常见的原因之一是测试游戏中的 bug。你可以让机器人不停地敲打游戏,直到有东西坏掉。模拟游戏性的另一个原因是为了建立可以高水平学习和玩的机器人。通常有三种模拟游戏的方式:

  • **实时:**你用正常设置运行游戏,但是一个机器人模拟鼠标点击和键盘输入。
  • Turbo: 你禁用渲染组件和其他游戏系统,以尽可能快地运行游戏。如果你的游戏逻辑从渲染逻辑中分离出来,这将会带来数量级的加速。
  • 运行模拟最快的方法是禁用游戏中的所有图形和渲染组件。使用这种方法,游戏可以作为函数调用,运行模拟的结果由函数返回。

对于人工智能课程,我使用了涡轮模式,每个人工智能代理独立运行。如果我要重复这个实验,我会使用像 Dataflow 这样的工具,在一个托管环境中扩展系统。这篇文章讨论了如何使用谷歌的数据流工具来实现这个逻辑。它非常适合可以独立运行的长时间运行的任务。

如果你对构建自己的俄罗斯方块游戏代理感兴趣,Bohm 等人的这篇文章介绍了一种创建强大玩家的有趣方法。他们定义了许多用于确定如何采取最佳行动的指标,如下面所示的海拔高度和油井差异。

Heuristics used by Bohm et al.

对于俄罗斯方块来说,这已经不是最先进的了,但是这是一个很好的起点。俄罗斯方块也是编写人工智能的一个好问题,因为从头开始编写一个俄罗斯方块游戏并不太复杂,然后可以用来模拟人工智能玩家。GitHub 上提供了该模拟器的完整代码:

[## BG Weber/模拟器

GitHub 是人们构建软件的地方。超过 2800 万人使用 GitHub 来发现、分享和贡献超过…

github.com](https://github.com/bgweber/Simulator/tree/master)

俄罗斯方块代码来自我 10 年前写的一个课程项目,我不建议以此为起点。回顾我的一些旧代码很有趣,我必须对它进行一些修改,以便让它在数据流的无头模式下运行。我已经为游戏解耦了游戏逻辑和图形线程,但是我删除了许多在分布式环境中无法工作的静态对象引用。

设置数据流 如果你熟悉 Java 和 Maven,启动并运行云数据流应该不是什么难事。第一步是在 pom.xml 中定义依赖关系:

<dependencies>          
  <dependency>      
    <groupId>com.google.cloud.dataflow</groupId>      
    <artifactId>google-cloud-dataflow-java-sdk-all</artifactId> 
    <version>2.2.0</version>     
  </dependency>     
</dependencies>

一旦您将这个依赖项添加到项目中,您就能够构建和部署数据流作业。我在这个项目中使用了 Eclipse,但是 intelliJ 是另一个很好的用 Java 创作数据流任务的 IDE。关于设置数据流的更多细节可以在我以前关于扩展预测模型的文章中找到:

[## 用数据流生产 ML 模型

我在数据科学职业生涯中面临的主要挑战之一是将探索性分析的结果转化为…

towardsdatascience.com](/productizing-ml-models-with-dataflow-99a224ce9f19)

用数据流 模拟游戏在修改了我的旧代码后,我现在有了一个游戏模拟,我可以用它作为一个函数(方法)以无头模式运行,并在完成时返回游戏统计数据。一旦你以这种方式建立了一个游戏,就可以直接使用数据流来运行数千次模拟。我用以下操作定义了一个 DAG:

  1. 创建种子值集合以用作输入
  2. 对每个种子进行模拟
  3. 将游戏结果保存到 BigQuery

第一步是创建一个种子集合,作为游戏模拟器的输入。拥有一个具有可重复结果的游戏模拟是很好的,以便 QA 和测量不同游戏代理的性能。我用这一步来指定要完成多少工作。如果实例化了少量的种子,那么将执行少量的模拟,如果你使它更大,将执行更多的模拟。

Random rand = new Random();
ArrayList<Integer> seeds = new ArrayList<>();
for (int i=0; i<10; i++) {
    seeds.add(rand.nextInt());
}

我使用下面的代码来设置数据流管道,并将种子作为输入传递给管道流程。

Simulator.Options options = PipelineOptionsFactory.
        fromArgs(args).withValidation().as(Simulator.Options.class);Pipeline pipeline = Pipeline.create(options);
pipeline.apply(Create.of(seeds))

下一步是使用传入的种子作为游戏模拟的输入。这个应用步骤的结果是,输入的种子值用于创建一个 TableRow 对象,该对象捕获游戏的汇总统计数据。种子被传递给游戏对象,结果是代理完成的行数。我还记录了代理在决定采取哪一步行动时使用的超参数。

.apply("Simulate Games", ParDo.of(new DoFn<Integer, TableRow>() { @ProcessElement
  public void processElement(ProcessContext c) throws Exception {
    Integer seed = c.element(); // play the game
    Game game = new Game(seed);
    int levels = game.runSimulation(); // save the results
    TableRow results = new TableRow();
    results.set("levels", levels);
    results.set("heightFactor", game.getHeightFactor());
    results.set("balanceFactor", game.getBalanceFactor());
    results.set("holeFactor", game.getHoleFactor()); // pass the stats to the next step in the pipeline
    c.output(results);
  }
}))

最后一步是将结果保存到 BigQuery。这是在数据流中执行的一个简单步骤,但是您需要首先为目标表定义一个模式。下面的代码显示了如何执行这一步。

.apply(BigQueryIO.writeTableRows() 
    .to(String.format("%s:%s.%s", PROJECT_ID, dataset, table))
    .withCreateDisposition(BigQueryIO.Write.
                 CreateDisposition.CREATE_IF_NEEDED)
    .withWriteDisposition(BigQueryIO.Write.
                 WriteDisposition.WRITE_TRUNCATE)
    .withSchema(schema));

我们现在有了一个数据流图,可以在本地运行进行测试,或者部署在完全托管的云环境中进行大规模运行。运行这个 DAG 的结果是,将在 BigQuery 中创建一个表,其中包含每个游戏模拟的汇总统计数据。

运行模拟

你可以在本地或云中运行数据流。最简单的方法是先在本地测试,然后再扩大规模。通过将模拟数量设置为一个较小的数字(如 3),然后运行管道,可以测试整个管道。因为我们将结果保存到 BigQuery,所以我们需要为管道指定一个临时位置。为此,您可以为 java 应用程序提供一个运行时参数,例如:

--tempLocation=gs://ben-df-test/scratch

运行管道后,您应该会看到在 BigQuery 中创建了一个包含模拟结果的新表。下一步是扩大模拟的数量。

The operations in our Dataflow DAG

要在云上运行模拟,您需要指定更多的运行时参数。我将机器的最大数量设置为 20,以便从缺省值 3 开始加速这个过程。请记住,对于长时间运行的操作,使用更多的机器会变得昂贵。

--jobName=level-sim
--project=your_project_ID
--tempLocation=gs://ben-df-test/scratch
--runner=org.apache.beam.runners.dataflow.DataflowRunner
--maxNumWorkers=20

对 1,000 个种子运行此模拟会产生如下所示的自动缩放图表。在完成所有的模拟和保存结果之前,我的工作扩展到 14 个工作。

Autoscaling to meet the simulation demand

一旦完成,我就有了我的俄罗斯方块游戏代理的 1000 次迭代的游戏统计数据。

模拟结果

结果现在可以在 BigQuery 中获得。对于每个模拟,我都对超参数值进行了微小的更改,如下表所示:

Simulation results in BigQuery

我们现在可以在数据中寻找相关性,例如确定某些因素是否对清除的行数有影响:

select corr(holeFactor, levels) as Correlation
      ,corr(holeFactor, log(levels)) as logCorrelation
FROM [tetris.sim_results]

然而,结果中没有信号,对数相关的 R = 0.04。由于数据在 BigQuery 中可用,我们还可以使用 Google Data Studio 来可视化结果:

可视化证实了数据中没有相关性,但是我也为因子使用了小范围的值。

结论

数据流是扩大计算的一个很好的工具。它是为数据管道设计的,但可以应用于几乎任何任务,包括模拟游戏。

本·韦伯是 Zynga 的首席数据科学家。我们正在招聘

使用估计器扩大 Keras

原文:https://towardsdatascience.com/scaling-up-keras-with-estimators-2e1f3f759d9f?source=collection_archive---------12-----------------------

Keras can’t scale up Mt. Hood, but TensorFlow can!

你知道你可以把一个 Keras 模型转换成一个张量流估算器吗?围绕分布式培训和扩展,它将为您提供一整套选项。我们将准备一个 Keras 模型,通过将其转换为张量流估计量来进行大规模运行。

Keras 模型,符合估计量

所以我们有一个 Keras 模型。易于定义,易于阅读,易于维护。但是我们在扩展到更大的数据集或跨多台机器运行方面做得不太好。

幸运的是,Keras 和 TensorFlow 有一些很棒的互操作性特性。

我们想要做的是将我们的 Keras 模型转换为 TensorFlow 估算器,它内置了分布式训练。这是我们解决扩展挑战的入场券。

另外,一旦我们的培训结束,做模型服务也变得很容易。

[## 大规模部署 scikit-learn 模型

Scikit-learn 非常适合组装一个快速模型来测试数据集。但是如果你想运行它…

towardsdatascience.com](/deploying-scikit-learn-models-at-scale-f632f86477b8)

事实真相

我们感兴趣的函数叫做model_to_estimator。“模型”部分指的是 Keras 模型,而“估算器”指的是 TensorFlow 估算器。

我已经拿了我们在上一集中从开始的笔记本,并用新代码更新了它,以将我们的 Keras 模型转换为张量流估计器。培训完成后,我们还将了解如何导出 Keras 模型和 TensorFlow 模型。

[## 演练:Keras 入门,使用 Kaggle

这是一个简短的帖子——真正的内容在下面的截屏中,我在这里浏览代码!

towardsdatascience.com](/getting-started-with-keras-e9fc04f7ea6a)

我用我的 Kaggle 内核录制了一段视频来帮助说明这一切是如何进行的细节:

包扎

使用张量流估值器获得分布式训练是对 Keras 模型的简单调整。因此,现在您拥有了两个世界的精华:易于阅读的 Keras 模型创建语法,以及通过 TensorFlow 估值器进行的分布式训练。

请记住,使用 Keras 模型获得分布式培训只需使用model_to_estimator

感谢阅读这一集的云人工智能冒险。如果你喜欢这个系列,请为这篇文章鼓掌让我知道。如果你想要更多的机器学习动作,一定要关注媒体上的me订阅 YouTube 频道以观看未来的剧集。更多剧集即将推出!

Spark 上分布张量流的放大

原文:https://towardsdatascience.com/scaling-up-with-distributed-tensorflow-on-spark-afc3655d8f95?source=collection_archive---------7-----------------------

https://unsplash.com/photos/ZiQkhI7417A

您可能在过去经历过,或者可能在某个时候会经历,内存不足是数据科学中一个非常常见的问题。

由于业务涉及面广,创建包含超过 10,000 个或更多要素的数据集并不罕见。我们可以选择用树算法来处理这样的数据集。然而,Deeplearning 可以更容易地自动设计功能,并将它们处理成你选择的模型。

一个经常出现的问题是,在处理如此大量的数据时,如何在适当的数量内训练您最喜欢的模型。

结合 Tensorflow 和 Spark 的分布式深度学习为这个问题提供了一套便捷的解决方案。

1。简而言之分布式深度学习

分布式深度学习的关键成分包括中央 参数服务器工人

Fig 1: Illustration of Distributed Deeplearning from Joeri Hermans’thesis

每个 Worker 被分配一个数据集的分区,也称为 shard、 和一个 局部模型副本 。在数据集的这一部分上,每个工人应用常规的深度学习优化,例如 mini-batch,并计算梯度。在计算梯度时,工人 将其结果 提交给中央 参数服务器

在接收到来自所有工作者的所有提交之后,梯度被平均并且模型被更新。接下来 允许工人拉动 模型的新参数化。

从这个框架中,出现了许多令人兴奋的数学问题,例如想知道这个过程是否可以异步进行?这将避免让工人等待来自参数服务器的每个新的更新。这种技术的缺点是工人可能用过时的模型参数处理数据。我推荐阅读游里·赫曼的论文来了解更多关于这个话题的细节。

2.分布式张量流来了

Tensorflow 使用数据流图来表示各个操作之间的计算依赖关系。分布式张量流允许我们在不同的进程中计算图的部分,因此在不同的服务器上。

图 2 示出了分布式张量流设置,即张量流集群。

在该集群中,可以找到多个组件,如第一部分所述。

Fig 2. Illustration of a distributed Tensorflow set-up on Google Cloud Platform (https://cloud.google.com/architecture/running-distributed-tensorflow-on-compute-engine)

Tensorflow 提供集装箱管理器 Kubernetes 作为服务不同工作的主要选项。容器可以通过 Tensorflow 的协议缓冲区 tf.train.Example 从输入管道接收数据。

就我个人而言,我已经开始喜欢 Tensorflow 的 dara 格式和数据集类 tf.data.Dataset ,并开始喜欢上它。遗憾的是,Tensorflow 的数据预处理库还处于起步阶段。如果你像我一样,喜欢在通过任何神经架构之前创建大量的功能,你会寻找另一个专门从事 ETL 的分布式计算框架,比如 Spark。

火花来了…

3.火花拯救我们!

Spark 的优化能力在于使用弹性分布式数据集,即 rdd

Yahoo 提供了一个开源存储库,它为您管理 workers 和 parameters 服务器,同时为您提供来自 rdd 的流数据的可能性。

为此,我们需要使用包装器 TFCluster 定义一个集群,如图所示

如果您计划传递一个 rdd 来训练或生成预测,您需要将 input_mode 设置为 TFCluster。输入模式。火花。

使用以下代码应用训练或推理:

一切都很好,现在仍然有两个关键问题需要回答:

  • 我们应该在哪里传递我们的计算图,包含我们的神经网络?
  • 您应该从哪里提取数据批次?

所有这些都是在一个 map-function 中定义的,您需要将它作为一个参数传递。

包含主要成分的示例如下所示:

如本文第一部分所述,集群中有两种类型的作业,参数服务器和 worker。

如前所述,您需要您的参数服务器不断地监听来自作品的可能的 提交 。这是使用***server . join()***方法完成的。这个方法告诉 TensorFlow 阻塞并监听请求,直到服务器关闭。

在 worker 中,可以在由TF . device(TF . train . replica _ device _ set(…))处理的上下文管理器中定义自己喜欢的计算图。

这一行确保参数服务器知道您的工人正在计算任何 tf 的梯度。你可能已经定义了变量。因此,它将聚合这些梯度,并在每次提交后发回更新。

如果你像我一样懒惰,你可能也使用TF . train . monitored training session来处理回调,比如保存/恢复你的模型,并最终计算训练的摘要。

您需要确保不是所有的员工都在处理这些子任务。建议定义一个所谓的首席工人,例如任务指数为 0 的工人。

rdd 上的流用 ctx.get_data_feed(…) 调用。Spark 和 Tensorflow 的组合不是 100%最佳的。您可以根据TF . train . monitored training session中定义的一些条件,基于步骤或指标,选择终止应用程序。然而,Spark 不能提前终止 RDD 操作,所以多余的分区仍然会被发送给执行器。 tf_feed.terminated() 是为了表示这些多余的分区被忽略。

4.结论

在这篇博客中,我们学习了如何将 Spark 和 Tensorflow 结合起来,将弹性分布式数据帧分布在不同的作品上。我们还理解了参数服务器如何在每次提交 workers 之后不断更新变量。

我们希望这个博客对你有用,因为它对我们来说是一次很好的学习经历!

关于作者

庞欣是一名高级数据科学家,专攻 Spark,目前在一家最大的物流跨国公司应用她的技能。

Benoit Descamps 是一名独立的人工智能顾问,对数学和软件工程充满热情。如果您对集成最新的机器学习解决方案有任何疑问,请直说!

更多精彩内容!

@ Spark 研究笔记:核心概念可视化

@ 调整超参数(第一部分):成功减半

@tensor flow 中的自定义优化器

@XG boost 回归预测区间

参考

[1] 关于分布式深度学习的来龙去脉的有见地的技术讨论 n/

[2] 分布式张量流导

[3] 分布式张量流简介

[4] [分布式 Tenforflow @ Tensorflow 发展峰会(2017)](http://TensorFlow Dev Summit 2017)

[5] 雅虎在 Spark 上的分布式张量流

作为商业案例的扩展与失败的数据科学

原文:https://towardsdatascience.com/scaling-versus-failing-data-science-as-a-business-case-699b26291f59?source=collection_archive---------16-----------------------

…在公司或行业中。

赋予人才转向数据科学家的追求导致了一个后续观察:许多公司正在努力建立机器学习的商业案例。

努力建立业务案例会导致不必要的后果,例如

  • 数据科学项目经常失败
  • 很少或没有为公司增加价值
  • 新的或改进的产品不能吸引顾客
  • 人才离开公司

从我所知道的和我所举的例子中,我提炼出了以下见解:

  • 如何让数据科学业务案例失败
  • 如何成功扩展数据科学

“Data has a better idea” by Franki Chamaki on Unsplash

如何让数据科学业务案例失败

  1. 项目管理的人工智能——例如,汽车行业已经到了“要么人工智能,要么死亡”的时刻。我见过的一个经常性策略是在数字/数据/创新实验室建立一个团队,给他们一些项目。3 到 6 个月后,有了一个新项目,团队将重点从文本处理和为司机构建聊天机器人转移到销售数据的预测建模。管理层和团队可能认为他们在敏捷项目管理、快速迭代和概念验证方面做了正确的事情。不幸的是,这通常是所有发生的事情。事实证明,项目管理不是一种策略。
  2. 快速招聘——“我希望在未来 12 个月内招聘 150 名数据科学家”。我没有开玩笑:我确实接到了那个电话,是关于招聘“数据科学家顾问”的。是的,专业知识很重要。是的,人才短缺。是的,随着公司努力建立数据科学能力,他们可能会热衷于咨询服务。然而,专家短缺是真实的。此外,高级数据科学家可能更喜欢构建产品而不是项目工作,更喜欢影响客户而不是项目管理会议。总的来说,我见过不少尝试使用“招聘即解决”的方法,但往往在实施中已经失败了,要么是因为不切实际的“独角兽”愿望列表,要么是因为无法解释为什么一个有经验的数据科学家应该加入公司。此外,数据科学家经常报告他们被非专家采访。
  3. 通过在线学习提高技能 —在线学习全天候可用,公司已经开始赞助员工,通常是大量的员工。对公司来说,好处似乎很明显,因为员工已经拥有领域专业知识,通常利用自己的时间提高技能,谁有能力和毅力进入数据科学或机器学习角色变得很明显。我见过不少公司学习小组的参与者。然而,通过练习和顶点项目学习并不等同于构建机器学习用例。如果你停下来一分钟,我想你会看到要求新提升的员工交付用例是在等待奇迹。
  4. 在顶部喷洒机器学习——最初的冲动是询问机器学习如何改进现有的产品或服务。它可能会以渐进的方式做到这一点——但我们都明白自动驾驶(带驾驶员辅助系统)与自动驾驶汽车不同,你需要重新设计自动驾驶汽车及其基础设施。这同样适用于或许更为平凡的电子商务环境。如果你有一个目录,然后试图在上面建立一个小的推荐引擎,或者你决定建立一个真正强大的推荐系统,看看它如何改变你的产品,这很重要。在我看来,在顶部喷洒机器学习意味着让你的业务面临任何积极追求人工智能优先战略的竞争对手的风险。
  5. 群龙无首还是群龙无首——如果你雇佣了一个明星,但她没有能力组建一个团队,如果有必要的话,从头开始,你不会走得很远。也许在创业公司中更常见的是,你有机器学习部队,但没有头。乍一看,这可能令人惊讶,因为你会认为初创公司 CxO 明白这一点,但我的经验是,他们经常不明白,包括 CTO。一个常见的场景是,数据科学夫妇或三人组试图推动创业公司知道应该做但并不真正理解的业务案例,无论是从客户的角度还是从将技术作为产品部署的角度来看。

数据科学商业案例的失败会产生影响。如果公司、管理层和员工一直失败,他们将失去对机器学习方法的信任,并停止接受更多数据驱动的方法。其次,这将导致不再具有竞争力的生存风险。

那么,如何从失败走向成功呢?如何实现可扩展的数据科学方法?

“Failing forward to success” by Ian Kim on Unsplash

如何成功扩展数据科学

有些故事线我反复听过,也知道公司有成绩。这些故事有一些共同的元素。通常情况下,并非所有元素在开始时都存在,但最终大部分(如果不是全部的话)都会显现出来。我认为,要成功扩展数据科学,以下五个要素值得特别关注。

  1. 数据科学商业案例是新产品或服务的核心 —从根本上说,这是一个战略决策,即如果你选择建立数据科学,就建立它来开发新产品或服务。这通常会确保数据科学是一个商业案例,机器学习技术是产品或服务的核心。这样你就有了一些灵活性:产品的用户可以是你公司的外部或内部用户,它可以是付费用户,也可以不是。同样,如果你最初失败了,你现在也在向前失败。你的商业案例会给你带来可衡量的影响。对客户影响力的追求推动你前进。
  2. AI-first 在战略上非常重要,足以让公司重新考虑其产品或服务 —例如,假设你是一家电子商务公司,正在建立一个推荐系统(“你可能也会喜欢”功能),旨在通过交叉销售和追加销售来提高客户满意度和篮子大小。你的商业案例的一部分必须是“我是否需要扩大或改变目录以更好地服务我的顾客?”很可能会对你的供应链、仓储等产生影响。如果你再次考虑自动驾驶汽车的例子,就很容易看出设计、生产、销售和售后市场将会发生多大的变化。管理层必须理解并接受 AI-first 改变了产品,业务案例应该要求实现这些改变。
  3. 该公司在全球范围内投资数据,也从外部来源投资 —我们都听说过“数据湖”以及数据可访问性和质量的重要性。然而,即使你没有一个大湖,你仍然可以开始:有公共数据集、数据市场和 API。我的观察是,更敏捷的团队也利用外部数据。构建新产品也是如此,您可能会使用自己的数据,但也可能会利用新的数据源。需要的是对数据治理的承诺:广泛的数据收集、透明的元数据、方便的访问和持续的质量评估。如果数据不是数据团队面临的问题,但数据是每个生产数据的员工所拥有的产品,这将有所帮助。我经常听到对 GDPR 的抱怨,但我认为我们必须认识到,无论如何,当务之急是在全球范围内收集数据,并开发尊重和支持民主和隐私的数据治理形式。
  4. 建立国际团队,最好是在数据科学热点 —欧洲已经出现了一些数字创新中心,大多数数据科学人才聚集在这些中心。我的经验是,如果公司将总部设在地区或省会城市,如果公司还在数据科学中心(如柏林)开设办公室,并允许员工选择工作地点,那么组建团队会更加有效。数据科学和机器学习人群非常国际化,在其商业发展的早期阶段,每个人都受益于邻近性,正如许多大型 Meetup 社区所体现的那样。即使我们在网上工作和协作,个人发展和商业案例也会从活跃的社区中受益匪浅。
  5. 在 12 到 24 个月的时间里实施混合员工技能提升和人才招聘的战略由于全球范围内的专家数量相当少,任何团队的组建都必须超越招聘:员工技能提升和新人才投资。最近,我了解到航空业的一家大型公司正在提高数百名员工的机器学习技能,他们之前的角色是数据生产者、所有者或用户。这是我第一次看到大规模的实施工作。另一方面,需要系统化地持续招聘新人才。虽然在美国这是常见的做法,但我在欧洲没有看到太多的证据。在欧洲,找到人才并赋予他们权力仍然是关键问题。

我希望听到业内任何有兴趣解决这一关键战略问题的人的意见,即在发现和培养人才的同时,将数据科学扩展为商业案例。我的联系方式在 LinkedIn 上。

如果你有更多的观察或故事,欢迎评论或联系。对于输入、评论和更正,我感谢我出色的合作者——所有数据科学家:帕特里克·拜尔博士、特里斯坦·伯伦斯博士、马卡雷纳·贝吉尔-邦帕德雷博士、迪娜·代法拉博士、朱江猛·杜博士、塞巴斯蒂安·福考博士、、法赫纳兹·贾兰内贾德、达尼亚·梅拉、卡尔弗洛·佩鲁马尔博士。

基于 k-近邻的扫描数字识别

原文:https://towardsdatascience.com/scanned-digits-recognition-using-k-nearest-neighbor-k-nn-d1a1528f0dea?source=collection_archive---------3-----------------------

标签 : Python、scikit-image、scikit-learn、机器学习、OpenCV、ImageMagick、梯度方向直方图(HOG)。

如何在 2 分钟内将 500 张背景嘈杂的扫描图像上打印的数字(如下图)提取成 100% 准确率的 excel 文件?

简单的答案是:你不可能在 2 分钟内达到 100%的准确率,这需要 8 分钟。

Figure 1. Original image

预处理图像需要 2 分钟,机器学习模型正确预测 98%的数字需要 6 分钟,人工修复 2%的不准确预测,尽管只需很少的努力。通过向用户呈现模型无法以 100%的置信度分类的数字,6 分钟成为可能,如本博客结尾的“呈现”部分所示。

不成功的方法

在解释 k-NN 解决方案之前,我将简要回顾一下我探索过的一些不成功的提取数字的方法。

1-宇宙魔方——谷歌的光学字符识别(OCR)

尽管使用了 Tesseract 的选项将图像识别为单个文本行,并且仅识别数字,但是应用 Google 的 Tesseract 导致了低精度的数字识别。请注意,在应用 Tesseract 之前,图像的背景噪声已被去除(在本博客后面的去噪步骤中有更多内容)。

2-图像模板匹配

第二种方法是为 9 个数字中的每一个生成模板图像,然后检测图像中的每一个数字,并使用 openCV 的 matchTemplate 函数将其与 0 到 9 个模板中的每一个进行比较

**import** cv2result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF)
(_, score, _, _) = cv2.minMaxLoc(result)

由于噪音,这种方法对我们的问题不起作用。然而,这篇博客https://www . pyimagesearch . com/2017/07/17/credit-card-ocr-with-opencv-and-python/成功演示了使用模板匹配来识别信用卡上的印刷数字。

成功的方法:使用机器学习进行训练和预测

最后一种方法是训练我自己的机器学习模型。该解决方案需要满足以下要求:

  • 从图像中挑出每个数字
  • 选择适当的特征提取应用于每个数字
  • 选择多类分类器

输入/数据预处理、特征工程和数据准备是任何基于机器学习的解决方案的核心。选择使用哪种机器学习分类器是一个重要的步骤,然而,它的成功在于上面提到的。

大纲:

  1. 图像预处理
  2. 数字提取和训练/测试数据准备
  3. 特征抽出
  4. 培养
  5. 预测
  6. 介绍会;展示会

1.图像预处理

弗莱德·魏因豪斯(http://www.fmwconcepts.com/imagemagick/textcleaner/)的 TextCleaner 脚本已经被用于去除图像背景噪声,随后是图像锐化步骤。这两个步骤都需要 ImageMagick 库(【https://www.imagemagick.org】T2)。或者,我推荐使用 python 的库,如 OpenCVscikit-image 来预处理图像。

# text cleaner
./textcleaner -g -e stretch -f 25 -o 10 -u -s 1 -T -p 10 **input.jpg** **output_clean.jpg**# image sharpening
convert **output_clean.jpg** -sharpen 0x10 **output_sharp.jpg**

上面的代码产生了下面的图像

Image 2. De-noised image

2.数字提取和数据准备

由于噪声,使用 OpenCV 的 findContour 操作从图像中挑选出每个数字不会产生可靠的结果。对于这个特定的问题,检测数字周围的“边界框”(图像裁剪),然后从裁剪的图像中“挑出”每个数字,这是更健壮的。找到边界框后,后一步很容易,因为每个数字相对于裁剪图像的左上角都有一个固定的坐标。

Figure 3. De-noised inverted image

注意:使用梯度方向直方图(HOG)进行特征提取需要反转黑/白像素。

2.1 检测包围盒

使用第三方工具来裁剪图像的边界并不能在所有图像上很好地工作。相反,我创建了一个简单的方法来确定性地裁剪图像,并以 100%的准确度检测边界框。

该方法从计算矩形的白色像素开始,如图 4 所示。如果白色像素的计数超过经验设定值,则矩形的坐标是数字的上边界,并将用于裁剪图像。

Figure 4. Top image cropping

Figure 5. Top image cropping

同样的技术可以用来左裁剪图像,如图 6 所示。

Figure 6. Left image cropping

上述操作的输出产生了以下图像:

Figure 7. Cropped image

2.2 数字提取

既然检测到了边界框,应该很容易挑出每个数字,因为每个数字都有相对于裁剪图像左上角的预先固定的坐标。

我将上面的代码应用于一组图像,并手动将每个数字的图像分类到标记为 0 到 9 的单独文件夹中,如下所示,以创建我的训练/测试数据集。

Figure 8. Manually labeling datasets

3.特征抽出

特征提取或特征工程是识别输入(在我们的情况下是数字)的独特特征的过程,以使机器学习算法能够工作(在我们的情况下是聚类相似的数字)。特别令人感兴趣的是梯度方向直方图(HOG) ,它已经在许多 OCR 应用中成功用于提取手写文本。下面的代码演示了使用 skimage 的 hog 函数从图像中提取 HOG。

**from** skimage.feature **import** hogdf= hog(training_digit_image, orientations=8, pixels_per_cell=(10,10), cells_per_block=(5, 5))

在我的例子中,图像是 50x50 像素,hog 的输入参数(即 像素 _ 每单元单元 _ 每块 )是凭经验设置的。下图说明了如何在图像上应用 HOG,生成一个包含 200 个值(即特征)的矢量。

Figure 9. Illustration of Histogram of Oriented Gradients (HOG)

4.培养

在前面的步骤中,我们将相似的数字提取到文件夹中,以构建我们的训练数据集。下面的代码演示了如何构建我们的训练/测试数据集。

既然我们已经创建了训练数据集并将其存储到了 featuresfeatures_label 数组中,那么我们就使用 sklearn 的函数 train_test_split 将训练集划分为训练集和测试集,并使用结果来训练 k-NN 分类器,最后保存模型,如下面的代码所示。

*# store features array into a numpy array* features  = np.array(features_list, **'float64'**)*# split the labled dataset into training / test sets* X_train, X_test, y_train, y_test = train_test_split(features, features_label)*# train using K-NN* knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)# get the model accuracy
model_score = knn.score(X_test, y_test)

*# save trained model* joblib.dump(knn, '**/models/knn_model.pkl**')

5.预测

预测新图像上的数字的过程遵循相同的步骤,即挑选出上述训练步骤中所示的数字,然后简单地应用 k-NN 的 预测 函数,如下所示。

knn = joblib.load(**'/models/knn_model.pkl'**)**def** feature_extraction(image):
    **return** hog(color.rgb2gray(image), orientations=8, pixels_per_cell=(10, 10), cells_per_block=(5, 5))**def** predict(df):
    predict = knn.predict(df.reshape(1,-1))[0]
    predict_proba = knn.predict_proba(df.reshape(1,-1))
    **return** predict, predict_proba[0][predict]digits = []# load your image from file# extract featuress
hogs = list(map(**lambda** x: feature_extraction(x), digits))# apply k-NN model created in previous
predictions = list(map(**lambda** x: predict(x), hogs))

k-NN 的 预测 函数返回一个介于 0 和 9 之间的单个数字值,以表示输入图像的预测类别。K-NN 的predict _ proba函数返回每个预测类关联的精度。

例如,假设我们对包含数字“5”的图像应用了预测。输出的一个例子是prediction=5 and predict_proba =[[0 0 0 0 0 .8 0 0 .2 0]]。这意味着 k-NN 以 80%的置信度将图像分类为“5”,以 20%的置信度将图像分类为“8”。

最后,predictions = list(map(lambda x: predict(x), hogs))产生以下元组向量,其中每个元组表示图像上每个数字的预测类别及其相关预测置信度。任何未以 100%置信度对输入进行分类的预测都将呈现给用户进行手动校正,如下一节所示。

*[
(5, 1.0), (1, 1.0), (9, 1.0), (2, 1.0), (1, 1.0), (2, 1.0), (4,1.0), (7, 1.0), (2, 1.0), (3, 1.0), (4, 1.0), (3, 1.0), (4, 1.0), 
**(4, 0.8)**, (0, 1.0)
]*

6。演示文稿

最后一步是在 excel 文件中呈现机器学习模型的结果,如下所示。对于没有 100%准确预测的数字,我在实际预测的下面嵌入了预期数字的图像。这个微小的显示调整减少了用户 80%的时间来修正不准确的预测。此外,这项活动并不令人畏惧,因为它不需要大量的脑力劳动。用户可以在几分钟内滚动文件,并在视觉上将实际结果与预期结果相匹配。许多预测实际上是假阴性的,因此用户不需要做很多修正。

参考书目

哈米德,不适用,& Sjarif,不适用(2017)。基于 SVM、KNN 和神经网络的手写识别。arXiv 预印本 arXiv:1702.00723。

阿德里安·罗斯布鲁克的博客和书籍(【https://www.pyimagesearch.com】T2)。伟大的计算机视觉资源和许多关于数字识别的文章。

帕特尔,I .,贾格塔普,v .,&卡莱,O. (2014) 。手写数字识别的特征提取方法综述。国际计算机应用杂志107 期 (12)。

建设方案

原文:https://towardsdatascience.com/scenarios-for-construction-d7f55306168?source=collection_archive---------8-----------------------

在本帖中,我们给出了我们应用程序的一个用例的扩展说明,场景:对一个城市建设任务的劳动力成本和预算建模。(这是我们的第二个扩展示例用例;我们之前已经讨论过使用场景进行会计和管理。)在此过程中,我们将提供示例 Excel 模型,您可以下载并自己运行(如果您有场景)。要下载场景,请点击加入我们的 alpha 计划

敏感性分析

考虑下面的假设情况。你是一家建筑公司的主管,该公司承包了一栋 15 层的大楼,要价 1000 万美元。固定成本(如设备和材料)占该价格的 500 万美元,在计入劳动力成本之前,收益为 500 万美元。

然而,计算劳动力成本并不那么简单。作为建筑行业中经验丰富的专业人士,你知道预算中写的内容往往与实际情况不尽相同。在规划预算时,您使用了施工经理提供给您的数字。施工经理告诉会计,假设你的 100 名工人,每人每年支付 55,000 美元,每天工作 8 小时,将在 11 天内完成每一层,在 24 周内完成建筑。

更具体地说,他假设完成每层楼总共需要 8,000 个工时,可以分配给多个工人,加上每层楼一天的准备时间。根据这一假设,您的预算指定了 2,493,132 美元的劳动力成本,导致税前收益为 2,506,868 美元,折旧和摊销( EBITDA )。施工经理的假设正确吗?你的利润率取决于此。

如果对完成建筑所需的劳动力数量判断错误,你的公司将付出比劳动力直接成本更多的代价。根据合同条款,你的公司必须在 30 周内完成这座大楼,否则你将面临罚款:超过合同规定的完工时间,每超过一周,你将支付 15 万美元的罚款,从而侵蚀你的利润率。

这些假设以及由此产生的预算在以下电子表格模型中进行了详细说明(请访问我们的网站下载该模型):

上述给计划者和决策者提出的第一个问题叫做敏感性分析。这项工作的利润率对每层楼需要多长时间的假设有多敏感?如果出于某种原因,每个楼层需要 15 天而不是 11 天,这是否会破坏利润率?如果每完成一层楼,建筑的速度就会加快,那么后续的楼层也会很快完成——如果速度变慢了呢?两者都是可行的,取决于项目的类型。

解决这些问题的卓越工具是蒙特卡洛模拟。我们,建模者,通过将某些量指定为未知数,作为假设,来增加上述预算。这就考虑到了施工经理做出的假设可能并不准确的可能性。在这种情况下,未知数是 a)完成一个楼层所需的工时数,b)楼层与楼层之间的工时变化,以及 c)完成每个楼层所需时间的可变性都是未知的。使用场景,将先前的模型改变成概率模型是简单的:简单地用分布替换将要变得随机的单元。同样,请访问我们的网站下载模型:

这个模型增加了三个新的假设。首先,我们假设完成一层楼所需的工时是正态分布,期望值为 8000 小时,标准差为 1000 小时。本质上,这意味着建模者预计该值为 8,000 小时,但也考虑到了低至 5,000 小时、高至 11,000 小时的可能性。

我们的第二个假设与施工进度有关。我们考虑到施工速度可能会随着每层楼的完工而减慢或加快。我们认为最有可能的情况是施工速度不会减慢或加快,但我们考虑到了施工速度减慢或加快的可能性,即每层楼在任一方向上可能会增加多达 900 个工时。我们考虑到了这种可能性,因为我们不知道它会减速还是加速,而且如果它真的减速,正如我们将看到的,这对我们的利润率非常不利。

最后,在上图右下方的公式中,我们进行第三个假设。我们假设每个楼层施工时间的可变性也是不确定的——虽然大多数楼层预计需要大约 8,000 个工时才能完成,但我们不知道同一栋建筑内楼层完成时间的差异有多大。高可变性表明楼层完成时间非常不可预测,而低可变性表明如果第一层需要 8,500 小时,其余楼层可能也需要非常相似的时间。

(注意:这些假设仅利用了打包在场景中的几个概率分布——正态分布和伽玛/厄兰分布。关于场景中包含的发行版的完整列表,请参见场景文档。有关如何解释这些假设和理解由场景执行的分析的更多信息,请参见此处的和此处。)

通过使用场景为上述模型生成 100,000 个场景,我们可以分析利润率对我们做出的特定假设的敏感度。以下是这些模拟结果的报告:

左边的图表显示了场景运行的 100,000 个模拟中每个模拟产生的 EBITDA。右边的图表只是左边图表的压缩版本,只显示了在每种情况下 EBITDA 是否为正。

因此,在大多数模拟运行中(约 98%),EBITDA 大于零。在其余 2%的场景中,要么是每层楼的完工时间比专家预计的时间长得多,要么是楼层完工时间呈明显上升趋势,导致上层楼的完工时间比下层楼长得多。如果 2%是你和你的公司可以承受的风险水平,敏感性分析已经做出了你的决定——你应该同意这个提议,继续这个项目。

合并实际值

然而,一旦你决定继续这个项目,决策就不会停止。事实上,Invrea 的洞察力是,最重要和最困难的决定还在前面。如果您的团队没有对建筑项目的实际数据做出正确的反应,如果您的团队没有将实际数据纳入决策过程,那么您可能会损失惨重。这就是我们的意思。

决策不是一个静态的过程。通常,商业决策需要根据新数据重新评估。以您的建筑项目为例,考虑一下如果您的公司开始该建筑项目,前四层分别用了 11.5 天、11 天、14.5 天和 15.8 天,您会处于什么位置。

这些结果使你陷入困境。这些最低完工时间是否代表一种明显的上升趋势,从而导致完工时间的显著延迟?或者这仅仅是由于不可预见的因素,使得第三层和第四层的时间比预期的要长?如果有明显的上升趋势,那么由此导致的延误可能会使你的劳动力规模增加一倍,以便在合同规定的时间内完成项目,这样你仍然可以盈利。然而,如果这些数据点只是异常值(T1)和 T2(T3 ),而不是趋势的指示,那么将员工数量增加一倍就是浪费,会侵蚀你的利润率。

具体来说,您必须解决的问题是,在构建模型的过程中,我们做了两个相互有些矛盾的假设。我们对楼层间的工时变化做了一个假设,指出这种幅度的上升趋势是完全可能的。我们对每层建筑时间的可变性做了另一个假设,假设这种程度的异常值是完全合理的,并且可能与恒定的楼层完工时间一致。我们有非常少量的数据。你如何权衡这两种假设,以便最好地解释观察到的数据,然后使用结果来通知并可能重新评估你的决定?这正是场景的核心独有技术概率编程新技术所要解决的问题。

场景中,有一个特殊的构造告诉模型它必须以这种方式从新数据中学习。我们称之为模型必须从实际值中学习的数据点。向模型添加实际数据点就像右击单元格并按下“记录实际数据”一样简单:

通过按下该对话框中的“记录”,用户告诉场景,他们只对观看第四层需要 15.8 天完成的场景感兴趣。(这个过程可以很容易地对前面的三层楼重复;或者访问我们的网站下载生成的模型。)场景以一种在商业应用中从未见过的方式使用这些实际数据点:同时验证和改进我们建模者输入的假设。 Scenarios 然后根据新的数据和修改后的假设产生新的预测和建议。(关于场景如何解决这些问题的深入讨论,见这里这里。)

因此,使用场景,我们又生成了 500,000 个场景,这次考虑了前四层的结果。我们发现我们的预测发生了重大转变:

考虑到前四层的完工时间,EBITDA 小于零的几率超过 35%。所以,为了保证公司在这个项目上不赔钱,我们必须雇用更多的工人。情景告诉我们,根据新数据,我们关于楼层完工时间的最初假设是错误的,并将其修正为更准确的假设。

不使用场景就无法得到这种分析。如果您不是按“记录实际”而是简单地将观察到的楼层完成时间输入到相应的单元格中,我们就不会修改我们的初始假设,我们仍然会在一个错误的模型上操作,我们将有超过 35%的机会损失数十万美元。要了解这一点,请从我们的网站下载模型并运行场景:

当被指示从数据中学习时,场景使用这些数据来检查其用户输入的假设是否正确,改进这些假设,然后使用这些改进的假设来建立对未来的改进预测。在这种情况下,it 部门了解到,实际上建造楼层需要将近 9,000 个工时(而不是我们最初假设的 8,000 个工时),而且很有可能会导致楼层越高,建造时间越长。

为了检查场景对构建过程了解了什么,比较下面两个直方图。左边的是我们对楼层间工时趋势的最初假设,以零为中心,右边的是场景推断的分布,以更好地代表实际发生的数据:

因此,这些实际情况——楼层完工时间——迫使你重新考虑你未来的假设。作为对这些新数据的反应,你应该改变你的决定——增加劳动力的规模,这样这个项目最终将在 30 周内完成。然而,你不想增加太多的劳动力,因为这将在劳动力成本上浪费金钱。那么,你如何选择何时增加员工数量,以及增加多少?

场景,使用上面的模型,也可以解决这个问题。只需改变模型中使用的劳动者数量,保留前四层的结果来训练模型,有关 EBITDA 的预测就会更新。例如,假设您正在考虑在建造 10 至 15 层时将员工人数增加一倍。下图显示了 EBITDA 为正的概率,如果您决定按照此方案增加员工人数:

仅在后几层就将员工人数增加了一倍,这大大降低了因罚款而超出预算的风险。因此,尽管劳动力成本增加,但将 10 至 15 层的劳动力规模增加一倍是一个好主意。

场景的应用绝不仅限于建筑。如果你面临一个不确定性很高且数据可用的决策问题,考虑使用场景来为你的分析提供信息。决策和数据都不是静态的,在几乎所有情况下,最重要的数据都是最新的数据。一旦新的数据出现,预测就会改变。场景可以自动为你做到这一点。在这里加入阿尔法计划

原载于invrea.com

使用云功能和云调度程序安排数据接收

原文:https://towardsdatascience.com/scheduling-data-ingest-using-cloud-functions-and-cloud-scheduler-b24c8b0ec0a5?source=collection_archive---------11-----------------------

随着谷歌云的不断发展,我在《谷歌云平台上的数据科学》一书中提出的一些解决方案被取代了,因为更简单、更强大的解决方案变得可用。

There is now a better way to do periodic ingest than the method I suggested in Chapter 2 of this book.

例如,几个月前,我展示了如何仅使用 SQL 构建回归和分类模型。无需移动数据即可实现高度可扩展的机器学习,这意味着我们可以非常轻松地探索机器学习的价值。如果我今天写这本书,我会在第 5 章(交互式数据探索)中插入一个关于 BigQuery ML 的部分。

在本文中,我将讨论第二个更新:一个比我在第 2 章最后一节中介绍的更好的定期数据接收方法。

老办法:使用 AppEngine Cron 每月更新

在本书第二章的最后一节,我提出了一个安排每月下载的解决方案。这包括五个步骤:

  1. 在 Python 中摄取
  2. Flask webapp
  3. 在 AppEngine 上运行
  4. 保护 URL
  5. 调度 Cron 任务

The solution for periodic ingest presented in the book can be greatly simplified now.

第一步已经在书中完成了,我可以简单地重用那个 Python 程序。剩下的步骤变得更容易了。简单多了。

使用云功能摄取

有一种更简单的方法来创建可通过 Http 访问的 web 端点,而不是构建 Flask web 应用程序并在 AppEngine 中运行它。新的方法是使用云功能。我可以使用用于摄取的相同 Python 代码,但是将它包装在一个名为 main.py 的文件中(本文中的所有代码都在 GitHub 上):

import logging
from flask import escape
from ingest_flights import *

def ingest_flights(request):
   try:
      logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
      json = request.get_json()
      year = escape(json['year']) if 'year' in json else None
      month = escape(json['month']) if 'month' in json else None
      bucket = escape(json['bucket'])  # requiredif year is None or month is None or len(year) == 0 or len(month) == 0:
         year, month = next_month(bucket)
      logging.debug('Ingesting year={} month={}'.format(year, month))
      gcsfile = ingest(year, month, bucket)
      logging.info('Success ... ingested to {}'.format(gcsfile))
   except DataUnavailable as e:
      logging.info('Try again later: {}'.format(e.message))To create

本质上,我的 main.py 有一个接收 Flask 请求对象的函数,从中我可以提取 HTTP Post 的 JSON 有效负载,云函数将通过它被触发。

我通过查看桶中已经有哪些月份,然后使用 ingest_flights.py 中的现有代码获取必要的数据,从而获得下一个月。

一旦我写好了 main.py,就可以通过 gcloud 部署云功能了:

gcloud functions deploy ingest_flights \
       --runtime python37 --trigger-http --timeout 480s

我们可以通过向 Cloud 函数发送 curl 请求来测试它:

REGION='us-central1'
PROJECT=$(gcloud config get-value project)
BUCKET=cloud-training-demos-mlecho {\"year\":\"2015\"\,\"month\":\"03\"\,\"bucket\":\"${BUCKET}\"} > /tmp/message curl -X POST "[https://${REGION}-${PROJECT}.cloudfunctions.net/ingest_flights](https://${REGION}-${PROJECT}.cloudfunctions.net/ingest_flights)" -H "Content-Type:application/json" --data-binary @/tmp/message

保护云功能

正如上面的代码所示,云函数的 URL 是完全开放的。为了在某种程度上保护 URL 免受拒绝服务攻击,我们应该将 URL 改为不可访问的。

要使 URL 不可访问,请使用 openssl 库生成一个 48 个字符的字符串,删除非字母数字字符,并将结果精简为 32 个字符:

URL=ingest_flights_$(openssl rand -base64 48 | tr -d /=+ | cut -c -32)
echo $URLgcloud functions deploy $URL --runtime python37 --trigger-http --timeout 480s

这本身是不够的。我们还应该坚持让合法的调用者向我们提供一个令牌作为有效负载的一部分。同样,我们可以使用 openssl 程序生成一个令牌,并将支票添加到 main.py:

if escape(json['token']) != 'DI8TWPzTedNF0b3B8meFPxXSWw6m3bKG':
         logging.info('Ignoring request without valid token')
         return

做这两件事——一个不可访问的 URL 和检查云函数中的令牌——有助于保护云函数。

使用云调度程序调度摄取

现在,云功能提供了一个启动接收作业的 http 端点,我们可以使用云调度程序每月访问该端点一次:

gcloud beta scheduler jobs create http monthlyupdate \
       --schedule="8 of month 10:00" \
       --uri=$URL \
       --max-backoff=7d \
       --max-retry-attempts=5 \
       --max-retry-duration=3h \
       --min-backoff=1h \
       --time-zone="US/Eastern" \
       --message-body-from-file=/tmp/message

调度器采用多种格式,包括 Unix 的 crontab 格式,但是我发现 AppEngine 的 cron 支持的简单语言格式可读性最好。因此,我们的端点将在每月 8 日美国东部时间上午 10 点被访问。

使它不那么单一

如果你看看 ingest_flights.py,ingest 方法做了相当多的事情。它下载文件,解压缩文件,清理文件,转换文件,然后将清理后的文件上传到云存储。

既然我们正在使用云函数,那么重新设计使其不那么单一可能会更好。除了通过 http 调用触发之外,云功能还可以通过向桶中添加文件来触发。

因此,我们可以让第一个云函数简单地将解压缩后的文件上传到云存储,然后让第二个云函数执行提取-转换-加载(ETL)部分。这可能更容易维护,尤其是如果事实证明我们在 ETL 部分有一个 bug。原始数据可用于重新运行 ETL 作业。

后续步骤

轻松调度:Python 成本优化教程

原文:https://towardsdatascience.com/scheduling-with-ease-cost-optimization-tutorial-for-python-c05a5910ee0d?source=collection_archive---------2-----------------------

了解如何使用 Python 中的线性编程快速解决优化问题

介绍

语境

恭喜你!你是镇上最酷商店的骄傲的新主人。为了保持运营,您需要确保为每个班次安排了正确数量的工人。在本教程中,我们将为即将到来的一周设计最低成本的时间表。

考虑

在接下来的一周里,每天有两次 8 小时的轮班。您目前有十名员工,其中四名被视为经理。对于一周内超过 40 小时的任何班次(总共 5 个班次),您都要向员工支付加班费。为了对你的员工公平,你决定每个人至少要工作 3 班,但不能超过 7 班。而且为了保证店铺顺利运转,每个班次至少需要一个经理。

构建问题

在深入研究代码之前,让我们通过定义目标、变量和约束来为我们的任务添加结构。

目标函数

简而言之,我们要设计最低成本的时间表,既考虑常规时间,也考虑加班时间。我们可以从数学上将其定义为:

其中 w 是我们的工人列表,RegCostOTCost分别是每个工人正常和加班班次的美元成本,RegShiftsOTShifts分别是每个工人正常和加班班次的总数。

变量

我们将为每个工人/班次组合创建一个变量列表(例如['雇员 1 ','星期一 1'],['雇员 2 ','星期一 1'],等等)。).这些变量中的每一个都将是一个二进制值,以表示一个工人是否被调度(1)或不被调度(0)。我们还需要处理常规时间和加班时间的划分,我们将把它作为变量和约束的混合来处理。

限制

从上面的问题陈述中,我们知道我们需要遵循一些特殊的注意事项。为了确保我们的优化计划是可接受的,我们将创建特定的约束条件:

  • 配备的工人总数等于每班所需的工人总数
  • 员工必须保持在全球最小和最大轮班数之间
  • 只能在工作人员可用时安排他们(在决策变量“x”中处理)
  • 每班至少配备一名经理

用 Python 创建我们的模型

准备数据

在进入优化模型之前,我们需要一些(说明性的)数据来处理。由于将数据加载到 Python 超出了本教程的范围,我们将快速浏览这一部分。

以下是我们现在所掌握的情况:

  • 我们的 14 个班次(一周内每天两班)和 10 名员工的列表(第 7-9 行)
  • 每班需要的工人数量(第 12-13 行)
  • 每个班次每个工人的可用性(第 17-23 行)
  • 一个是经理的列表和一个不是经理的列表(第 26-27 行)
  • 每个工人的轮班成本,包括正式工和加班工(第 31-36 行)
  • 一些关于最小和最大班次以及在触发加班之前允许多少班次的全局假设(第 40-43 行)

初始化模型

注:从上面的代码可以看出,我们使用的是一个名为guro bi的包。Gurobi 是一个优化求解器,可用于许多编程语言。虽然 Gurobi 的完整版本需要商业许可证,但您可以获得学术或在线课程许可证来免费运行有限版本。

我们首先需要创建模型的外壳。我们使用以下代码来实现这一点:

model = Model(“Workers Scheduling”)

添加决策变量

让我们将结构化变量转化为代码:

首先,我们需要为每个工人/班次组合创建二进制变量。我们可以用 Gurobi 的addVars函数来做到这一点(注:如果只添加一个变量,用 addVar 代替)。我们指定变量是二进制的,我们还读入了之前创建的作为ub(“上限”)的avail字典。每个古罗比变量都有一个上限和下限。因为我们使用二进制变量,自然我们的变量必须等于 0 或 1。通过将上限设置为等于avail中的值,我们能够嵌入特定工人/班次组合必须等于 0 的约束(即当该工人不可用时)。

接下来,我们必须创建变量来处理正常工作时间和加班时间。如前所述,我们将把这种分割作为变量和约束的组合来处理。现在,我们只是为每个工人创建变量,没有进一步的说明。一个例外是,我们将overtimeTrigger设置为一个二进制变量(当给定的工人本周没有加班时为 0,当有加班时为 1)。

添加约束

类似地,让我们使用addConstrs(一次添加多个约束)和addConstr(一次添加一个约束)函数,将上面概述的每个约束转化为代码。

首先,我们指定每个班次分配的工人总数(每个计划工人 1,每个非计划工人 0)等于总班次需求:

接下来,我们处理正常时间和加班时间的划分。为了准确地捕捉到这一点,我们采取了保守的方法。首先,我们指定常规班次的数量加上加班班次的数量等于每个工人的总班次数量。然后,我们确保常规班次的数量小于或等于指定为加班触发器的班次数量。我们这样做是为了确保在加班之前考虑常规班次。为了更进一步,我们添加了最后一个约束条件,即如果一个工人的正常轮班次数小于 5 ( OTTrigger),那么加班的二进制触发器将被设置为 0。

有了这个,我们就可以完成最后的约束了。与上面类似,我们计算每个工人分配的总班次数。我们指定这必须大于或等于最小班次的全局输入,并且小于或等于全局最大班次。最后,我们处理每个班次至少需要一名经理的需求。

定义目标函数

我们的目标是最小化计划工人的总成本。我们可以很简单地通过定义一个成本函数来处理这个问题,该函数将正常班次总数乘以每个工人正常班次的成本,以及加班班次总数乘以每个工人加班班次的成本相加。我们告诉 Gurobi,目标是使用ModelSense来最小化这种情况。最后,我们使用setObjective来指定Cost是目标函数。

运行优化

在运行优化之前,检查模型可能会有所帮助。一个很好的方法是:

有了这段代码,你将能够看到目标函数、变量、约束等。列为公式,这对于确保代码产生您想要的功能特别有帮助。

在您对模型满意之后,我们可以用一行简单的代码来解决优化问题:

model.optimize()

输出

optimize函数产生了一个非常有用的输出,但是并没有给我们太多的工作。在接下来的步骤中,我们将从模型中提取更有意义的信息。

首先,我们想知道计划的总成本。通过运行以下命令,我们发现成本为 7535 美元:

print('Total cost = $' + str(model.ObjVal))

现在,让我们使用以下内容来查看时间表的控制面板:

Output of the dashboard

最后,让我们创建仪表板的另一个视图,只需打印出分配到每个班次的每个员工的姓名:

Output of the shift assignments

结论

通过本教程,我们使用 Python 制作了一个优化问题的端到端解决方案。如果这激起了你的兴趣,你可以自己举个例子。尝试处理连续决策变量、多目标问题、二次优化、不可行模型——可能性是无限的。如果你对创建自己的优化算法感兴趣,可以看看我的关于使用 Python 构建遗传算法的教程。

结束注释

你可以在这里找到一个合并的笔记本

参考资料:

学校假期、机器学习和正在学习“看”的机器人

原文:https://towardsdatascience.com/school-holidays-machine-learning-and-robots-that-are-learning-to-see-c5ab183090f6?source=collection_archive---------12-----------------------

去年九月学校放假时,Coding Kids 带着一群学生参观了位于布里斯班花园点校区 QUT 的澳大利亚机器人视觉中心。该中心专门研究和开发学习“看”的机器人。他们的视觉能力是机器人在社会中无处不在部署的剩余技术障碍…

澳大利亚机器人视觉中心在克服这一障碍方面发挥着关键作用。该中心正在开发基础科学和技术,使机器人能够看到、理解它们的环境,并在我们生活和工作的复杂、无组织和动态变化的环境中执行有用的任务。

在参观研究设施的过程中,我们了解到机器人很难像人类一样“看到”和识别图像,并且在这一领域正在进行大量研究,以便改进我们使用技术的方式。如果机器人能学会像人类一样看东西,机器人帮助我们和我们社区的潜力是无穷无尽的。机器人和机器只懂 1 和 0,那么机器人学家和科学家是如何教和训练机器人看图像的呢?

正在开发的机器人原型之一是 Guiabot,这是一种正在学习“看到”周围环境的自动驾驶汽车。与人类不同,机器人更难确定两幅略有不同的图像是否位于同一位置。学生们和一个机器人玩了一个游戏,以测试他们在识别两个图像是否在同一位置上的能力。一个学生试着做了这个游戏,得到了 10/10 的分数。机器人同一场比赛的得分只有 9/10。这表明,对于人类来说,识别两张照片是否属于同一地点要容易得多。尽管技术在进步,但机器人仍然不能像人类一样通过视觉识别自己的位置。

我们了解到机器人正在使用一种叫做机器学习的过程来学习“看”。1959 年,阿瑟·塞缪尔(Arthur Samuel)将机器学习定义为“在没有明确编程的情况下,赋予计算机学习能力的研究领域”。

这是机器人视觉公司的三个机器人,它们正在使用机器学习来学习“看”:

  1. COTSbot 是一个正在学习“看见”和识别大堡礁棘冠海星(COTS)的机器人。COTSbot 的设计是为了控制 COTS 的过剩,这是破坏大堡礁。
  2. QUT 的 Harvey the harvester(基于 UR5 手臂)是一个辣椒采摘机器人。它是学习“看见”和识别成熟的辣椒,准备采摘。澳大利亚 30%的作物都被浪费了,原因是在一年中需要收割作物的确切时间缺少工人。
  3. QUT 的 AgBot 是一个 3 米宽的杂草清除机器人,可以识别需要清除的棉花和杂草。

这三个机器人正在学习识别一个特定的物体,以便它能为我们做有用的工作。学习和训练机器人的方法被称为机器学习。机器学习基于一套复杂的算法,计算机,或者在这种情况下,机器人,使用已知数据进行学习和预测。

机器人首先通过学习识别图像中的目标物体,如棉花、辣椒和杂草,开始它们的学习之旅。然后,机器人开始学习识别目标物体的 3D 打印版本。在成功完成这一级别的训练后,机器人开始训练识别现实生活中的物体,例如大堡礁中的帆布床、果园中成熟的辣椒和土壤中的杂草。在这个级别的训练中,机器人学会区分 3D 打印版本和真实的目标对象。

澳大利亚机器人视觉卓越中心专注于机器人“看”的研究和开发,并在克服机器人在社会中无处不在部署的最后一个技术障碍方面发挥了关键作用。机器人改善我们生活和环境的潜力是无限的。这是一个有趣的研究领域,我们学校团体对该中心的访问是一个让孩子们接触科技奇迹的好机会。正如孩子们在学习一样,机器人也在学习。

点击我们的脸书页面了解我们最新的儿童免费科技活动。

在下面的视频中观看机器人 Nao 跳江南 style:

文章最初发表在这里

科学数据分析管道和再现性

原文:https://towardsdatascience.com/scientific-data-analysis-pipelines-and-reproducibility-75ff9df5b4c5?source=collection_archive---------13-----------------------

Photo by Campaign Creators on Unsplash

管道是做什么的?我们为什么需要它们?

管道是方便的计算工具。数据分析通常需要数据采集、质量检查、清理、探索性分析和假设驱动分析。管道可以自动完成这些步骤。他们将原始数据处理成合适的格式,并以简化的方式用统计工具或机器学习模型进行分析。实际上,数据分析管道执行一系列命令行工具和定制脚本。这通常提供经过处理的数据集和人类可读的报告,涵盖诸如数据质量、探索性分析等主题。

在我们的领域中,原始数据是包含测序读数的文本文件。读数有一个 4 个字母的代码(ACGT ),它们来自基因组的特定位置。我们需要对读数进行质量检查,将它们与基因组对齐,量化它们,并对它们运行统计/机器学习模型。不同的命令行工具和定制脚本必须按顺序运行才能完成这些任务。如果质量检查或校准出现问题,部分或所有步骤需要使用不同的参数重新运行,具体取决于使用数据观察到的问题的性质。我们可能需要运行数百次,因此通过管道至少自动化部分任务是有益的。

什么是再现性?为什么重要?

当您不得不重复处理一个带有一些参数变化的数据集或处理多个数据集时,管道会有很大帮助。由于基本的数据处理和分析任务可能需要大量的实际操作时间,因此自动化这些任务的某些部分可以节省时间。然后,研究人员可以将更多时间花在可视化、结果交流或定制的统计/机器学习分析上。由于这种便利,许多研究人员正在创建管道,并通过出版物与社区共享。通常,当您共享管道时,您会希望确保在为其他用户提供相同的输入数据时,您的管道会产生相同的输出。如何使用创建者使用的完全相同的依赖项安装完全相同的管道,并确保它产生相同的输出?虽然这听起来是一个微不足道的问题,但关于“科学中的再现性危机的报道表明,实现这一点并不容易。其他研究人员一再未能重现已发表的实验。这种“再现性危机”并不局限于生物学或心理学等领域。计算领域也遭受这种

对于可再现的数据分析,有几个标准。

数据和元数据可用性: 数据和元数据应该毫无疑问地可用。没有这些,就没有办法重现一个分析。在我们的研究领域,数据和元数据通常在发布后存放在公共数据库中。

透明: 你所使用的代码以及运行代码所需的依赖关系应该是完全透明的。这也延伸到依赖项的源代码可用性。不希望有一个工具的行为主要依赖于专有的二进制 blob /黑盒。此外,您需要知道依赖项的确切版本和配置,以便有机会重现数据分析管道。优选地,安装过程跟踪不同的依赖结构并安装你需要的所有东西,参见下面的要点。

易于安装(可安装性): 计算分析工具和管道应该努力做到易于安装。我认为,如果管道有许多必须单独安装的依赖项,我们中的许多人都会望而却步。即使我们得到承诺,在我们努力完成每个依赖项的安装后,会得到一个可以复制作者版本的工作管道,这种情况仍然会存在。管道的依赖项越多,就越有可能至少有一个在安装过程中出现问题。很多已发布的科学软件无法安装。研究声称至少有 50%的已发布软件是不可安装的【参见这里 & 这里】。我怀疑对于管道来说,情况更糟,因为许多管道都有更复杂的依赖关系。浏览过糟糕的自述文件并试图安装所有依赖项的人非常清楚为什么“易于安装”很重要。

运行时环境再现性: 安装的软件应该在每台机器上表现相同,也就是说我们需要在每台机器上安装完全相同的软件。实现这一点并不简单,因为软件依赖于许多不同的东西,从编译器到系统库,再到第三方软件和所需的库。如果您想在不同的机器上以完全相同的方式构建软件并获得相同的软件,您需要控制这个复杂的依赖系统。依赖项的版本及其构建方式会对您尝试安装的软件产生影响。例如,如果您尝试安装的软件需要 Boost C++库,则 Boost 1.68 版与 1.38 版相比可能会有所不同。可能会有错误修复或改进,可能会改变我们试图安装的软件的行为。因此,由于依赖关系的差异,即使在两台不同的计算机上安装了相同的版本,该软件也会有不同的行为。

如果您可以安装完全相同的软件,以完全相同的方式构建,并对编译器有完全相同的依赖关系,您就有很好的机会在不同的机器上重现运行时环境,从而使用相同的输入数据进行分析。唯一的例外是,如果软件有一些你不能控制的随机成分,那么就不可能重现分析。例如,k-means 聚类算法可能根据随机初始化过程每次产生不同的聚类结果。如果我们不能通过设置随机种子来控制这种行为,我们就无法重现结果。

Essential ingredients of data analysis reproducibility. Reproducibility requires availability of data and being able to use the same exact software.

计算分析的再现性光谱

科学家们的主要目标是尽可能快速准确地分析数据,因此任何为我们自己或其他潜在用户的未来版本做好事的努力似乎都是错误的。对于许多科学期刊来说,把你的代码放在 github 上就足够了,这只是最近一些期刊的要求。我们和许多其他人认为这并不总是足够的。

实际上,当我们想使用一个已发布的数据分析工具时,我们许多人的想法是:1)“我能安装已发布的软件并得到类似的结果吗?2)“我也可以在我的研究中使用这个吗?".在这一点上,我们只是想使用软件,不会试图在出版物中重现分析,除非它是测试用例或例子的一部分。因此,许多研究人员对再现性的理解是与可安装性联系在一起的。

然而,如果我们真的关心可重复性,正确的问题应该是“如果我可以安装它,我可以用相同的输入数据得到与发表的论文相同的结果吗?”。更普遍但相关的问题是“当我在不同的系统上安装软件时,我可以用相同的输入数据得到相同的结果吗?”。我认为正面回答这些问题需要严格控制数据分析管道的依赖性。提供管道的人应该复制他们的软件环境,并以虚拟机或容器的形式提供。或者,他们应该确保当用户安装管道时,他们获得了相同版本的依赖项。每个依赖项都应该以相同的方式构建,并且在您的机器和用户的机器上安装的软件应该是完全相同的。不严格控制依赖关系将导致软件行为不同。这些行为差异可能会改变分析结果。

所有这些不同的观点或对再现性的无知造成了从“不可再现”到“黄金标准”的再现性范围。虽然许多人认为在线提供源代码就足够了,但其他人需要满足以上提到的更多标准。

Reproducibility spectrum observed in publications. Sharing data and code is seen as enough to reproduce the data analysis by many. However, this is not enough.

拯救集装箱

处理运行时环境的可安装性和可复制性的最流行的方法之一是使用容器,这是一种轻量级的虚拟机。我们领域中最流行的容器是 docker 和最近的 singularity 容器。使用这种方法,管道和管道本身的复杂依赖关系可以被“容器化”。这意味着,如果您能够设法在这个轻量级虚拟机中安装您的管道和依赖项,您就可以运送容器,并确保使用该容器的任何人都能够复制您的软件环境。不同操作系统的结果应该是相同的。另一种方法是以容器的形式提供管道的依赖关系。在此设置中,您在管道中使用的每个工具都将是一个容器。有一些管道框架可以利用这一点,但我发现这种方法有些不切实际。

安装和运行时复制的便利性是以降低透明度和安全性为代价的。很难确切核实集装箱里装的是什么。Docker 建议使用 docker 文件,但是它们不一定具有容器中的软件版本。它主要是从软件包管理器安装软件的命令集合。如果不专门在 dockerized 环境中分析数据和开发代码,容器也更难维护。如果没有,在创建管道后,您必须将其容器化,并检查是否有相同的结果,这是额外的工作。人们努力使容器更加安全、透明和易于使用,但是它们没有被社区广泛采用。

包装经理和再现性

提供可安装性和依赖性管理的另一种方式是使用包管理器。您可以使用软件包管理器将您的管道构建为真正的软件和软件包,或者从软件包管理器提供要安装的软件包列表。

不管你选择哪种途径,一个非常流行的方法是使用 Conda 包管理器。它非常容易使用,不需要 root 访问权限,你可以获得预编译的二进制文件,这大大减少了安装时间,并且可以在 windows、mac OS 和 linux 上工作(大部分时间)。给康达打包软件也相对容易一些。此外,康达还有大量的贡献者和维护者。这些功能旨在最大化可安装性。然而,Conda 包根本不可复制。您可以在不同的时间获得相同名称+版本查询的不同二进制文件,并且没有办法跟踪哪些依赖项的源文件生成了该二进制文件。构建软件的系统环境不是孤立的。在构建期间,进程可以访问不在软件包配方中的其他库,并且 conda 还假设某些低级软件包在所有环境中都可用。它们的存在或它们的版本会影响构建,并在不同的系统上创建不同的软件。Bioconda 试图通过在容器中建造来规避这些问题。

虽然包管理器通常提供可安装性,但是很少有人关心构建的可重复性。如果您可以确保安装的软件在不同的系统上是完全相同的,那么您就可以获得运行时再现性,并在相同的输入数据下获得相同的结果(减去“运行时环境再现性”小节中提到的警告)。 GNU Guix 包管理器通过严格管理和跟踪要构建的软件的完整依赖图来实现这一点。它减少了对构建和安装软件的系统环境的假设。因为它知道所有的依赖项,所以它可以在一个隔离的环境中构建它们。这个过程的结果通常是在不同的机器上安装后逐位相同的文件(见此处对不同机器上构建的各种生物信息学软件逐位相同性的评估)。它还提供开箱即用的容器化。您可以为您的管道及其所有依赖项制作 docker 和 singularity 容器。Guix 构建的容器包含了管道所需要的依赖——不多也不少。考虑到它提供的可再现性和健壮性,我们选择使用 Guix 来管理我们的管道的依赖性。

然而,Guix 本身只适用于 linux,并且需要一个根 dameon 来进行构建隔离。打包软件不像 conda 那么容易,尽管 R 和 Python 的导入程序为来自那些框架的包做了几乎所有的工作。对于其他软件,可能会更复杂。此外,用户可能会发现很难管理 Guix 的灵活性。你可以拥有同一个软件的不同版本,你可以回滚到旧版本,但是管理那个可能会令人困惑。

管道框架对再现性的影响

管道框架对再现性几乎没有影响。再现性的主要挑战是提供运行时环境的可安装性和再现性。管道框架提供了一种结构化的方式来将工具/脚本管道化在一起,并提供了额外的功能,例如简单的并行化。snakeMake、Rufus、nextflow 等管道框架在此回顾不同的优缺点。

重申一下,框架的选择不是重现分析管道的主要问题。对于我们自己的目的由于 snakeMake 在生物信息学社区的广泛使用,我们选择了它,但是我们可以很容易地切换到其他东西,并且仍然是可复制的。

离别的思念

如果科学家们希望他们的工具或方法被更广泛的受众使用,那么让数据分析管道具有可重复性应该是他们的目标。快速和肮脏的方法是使用容器。然而,这对于维护或未来升级来说并不容易。Needles 说,部署分析管道不是一种透明的方式,研究需要最大的透明度。更明智的方法是将管道打包到包管理器中。Conda 软件包管理器易于使用,但永远无法完全重现。但是它的易用性和对生物信息学的大量社区支持使它成为许多人的首选工具。通过 Guix 包管理器,可以获得更多的可复制性,这是其他包管理器所不能提供的。它通过设计和源代码到二进制代码的透明性提供了软件构建的可再现性。像其他一些包管理器一样,Guix 附带了项目/用户特定的软件概要文件,其中您可以拥有相同软件的不同版本,而不会有任何冲突。您还可以毫不费力地构建 docker 和 singularity 容器。共享一个 Guix 清单文件和你的脚本就足以重现你的分析的软件方面。

实际上,所有选项(Conda、containers 和 Guix)都比仅仅共享代码和文档要好得多。但在我看来,Guix 更接近再现性的黄金标准,包括透明性、易于安装和运行时环境再现性。

Comparison of different ways of deploying pipelines with respect to criteria for reproducibility. Containers and Guix have medium installability because they require a framework to be installed first before users can use it, this first step most often needs root access. Conda does not keep track of full dependency graphs and makes assumptions about your system that’s why it doesn’t have high transparency or reproducible runtime environment. Containers have low transparency because it is hard to tell what is exactly in them even with dockerfiles present.

sci kit-了解亚马逊美食评论的文本分析

原文:https://towardsdatascience.com/scikit-learn-for-text-analysis-of-amazon-fine-food-reviews-ea3b232c2c1b?source=collection_archive---------1-----------------------

Photo credit: Pixabay

(本文首发于 DataScience+ )

我们知道亚马逊产品评论对商家很重要,因为这些评论对我们如何做出购买决定有着巨大的影响。所以,我从 Kaggle 下载了一个亚马逊美食评论数据集,这个数据集最初来自 SNAP ,看看我能从这个庞大的数据集里学到什么。

我们在这里的目的不是掌握 Scikit-Learn,而是探索单个 csv 文件上的一些主要 Scikit-Learn 工具:通过分析截至 2012 年 10 月(包括 10 月)的一组文本文档(568,454 篇食品评论)。让我们开始吧。

数据

查看数据帧的头部,我们可以看到它包含以下信息:

  1. 产品 Id
  2. 用户标识
  3. ProfileName
  4. 帮助分子
  5. 有用性分母
  6. 得分
  7. 时间
  8. 摘要
  9. 文本
import pandas as pd
import numpy as np

df = pd.read_csv('Reviews.csv')
df.head()

Figure 1

就我们今天的目的而言,我们将重点关注分数和文本列。

让我们从清理数据框开始,删除任何缺少值的行。

分数列的范围是从 1 到 5,我们将删除所有等于 3 的分数,因为我们假设这些分数是中性的,没有为我们提供任何有用的信息。然后,我们添加了一个名为“积极性”的新列,其中任何高于 3 的分数都被编码为 1,表明它得到了积极的评价。否则,它将被编码为 0,表明它是负面评价。

df.dropna(inplace=True)
df[df['Score'] != 3]
df['Positivity'] = np.where(df['Score'] > 3, 1, 0)
df.head()

Figure 2

看起来不错。

现在,让我们使用“Text”和“Positivity”列将数据分成随机的训练和测试子集,然后打印出第一个条目和训练集的形状。

from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(df['Text'], df['Positivity'], random_state = 0)print('X_train first entry: \n\n', X_train[0])
print('\n\nX_train shape: ', X_train.shape)from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(df['Text'], df['Positivity'], random_state = 0)print('X_train first entry: \n\n', X_train[0])
print('\n\nX_train shape: ', X_train.shape)

X_train 第一条目:

我买过几款活力狗粮罐头,发现质量都很好。这种产品看起来更像炖肉,而不是加工过的肉,而且闻起来更香。我的拉布拉多是挑剔的,她比大多数人更欣赏这个产品。

X_train 形状:(26377,)

查看 X_train,我们可以看到我们收集了超过 26000 条评论或文档。为了对文本文档执行机器学习,我们首先需要将这些文本内容转换为 Scikit-Learn 可以使用的数字特征向量。

词汇袋

最简单和最直观的方法是“单词袋”表示法,它忽略了结构,只计算每个单词出现的频率。CountVectorizer 允许我们使用单词袋方法,将一组文本文档转换成一个令牌计数矩阵。

我们实例化 CountVectorizer 并使其适合我们的训练数据,将我们的文本文档集合转换为令牌计数矩阵。

from sklearn.feature_extraction.text import CountVectorizervect = CountVectorizer().fit(X_train)
vect

count vectorizer(analyzer = ' word ',binary=False,decode_error='strict ',dtype =<class ' numpy . int 64 '>,encoding='utf-8 ',input='content ',lowercase=True,max_df=1.0,max_features=None,min_df=1,ngram_range=(1,1),preprocessor=None,stop_words=None,strip_accents=None,token_pattern= '(?u)\b\w\w+\b ',tokenizer=None,vocabulary = None)

这个模型有许多参数,但是默认值对于我们的目的来说是相当合理的。

默认配置通过提取至少两个字母或数字的单词(由单词边界分隔)来标记字符串,然后将所有内容转换为小写,并使用这些标记构建词汇表。我们可以通过使用 get_feature_names 方法来获取一些词汇表,如下所示:

vect.get_feature_names()[::2000]

['00 ',' anyonr ','漂白','矮胖','战败',' er ','贾尼尼','印象','小','项链','宠物','缩减','衬衫','夜宵']

看着这些词汇,我们可以对它们的内容有一个小小的了解。通过检查 get_feature_names 的长度,我们可以看到我们正在处理 29990 个特性。

len(vect.get_feature_names())

29990

接下来,我们将 X_train 中的文档转换成一个文档术语矩阵,它给出了 X_train 的单词包表示。结果存储在一个 SciPy 稀疏矩阵中,其中每一行对应一个文档,每一列是来自我们训练词汇表的一个单词。

X_train_vectorized = vect.transform(X_train)
X_train_vectorized

< 26377x29990 以压缩稀疏行格式存储了 1406227 个元素的“<类“numpy . int 64”>”稀疏矩阵>

列的这种解释可以按如下方式检索:

X_train_vectorized.toarray()
array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ..., 
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], dtype=int64)

该矩阵中的条目是每个单词在每个文档中出现的次数。因为词汇表中的单词数量比单个文本中可能出现的单词数量大得多,所以这个矩阵的大多数条目都是零。

逻辑回归

现在,我们将基于这个特征矩阵 *X_ train_ vectorized,*来训练逻辑回归分类器,因为逻辑回归对于高维稀疏数据工作得很好。

from sklearn.linear_model import LogisticRegressionmodel = LogisticRegression()
model.fit(X_train_vectorized, y_train)

LogisticRegression(C=1.0,class_weight=None,dual=False,fit_intercept=True,intercept_scaling=1,max_iter=100,multi_class='ovr ',n_jobs=1,penalty='l2 ',random_state=None,solver='liblinear ',tol=0.0001,verbose=0,warm_start=False)

接下来,我们将使用 X_test 进行预测,并计算曲线得分下的面积。

from sklearn.metrics import roc_auc_scorepredictions = model.predict(vect.transform(X_test))print('AUC: ', roc_auc_score(y_test, predictions))

AUC:0.797745838184

成绩还不错。为了更好地理解我们的模型是如何做出这些预测的,我们可以使用每个特征(一个词)的系数来确定它在积极和消极方面的权重。

feature_names = np.array(vect.get_feature_names())sorted_coef_index = model.coef_[0].argsort()print('Smallest Coefs: **\n{}\n**'.format(feature_names[sorted_coef_index[:10]]))
print('Largest Coefs: **\n{}\n**'.format(feature_names[sorted_coef_index[:-11:-1]]))

最小系数:['最差' '失望' '可怕' '糟糕' '还行' '都不是' '耻辱' '不幸' '失望' '恶心']

最大系数:['上钩' '光明' '美味' '惊艳' '怀疑' '担忧' '好吃' '极好' '再订购' '好吃']

对十个最小和十个最大的系数进行排序,我们可以看到该模型预测了像“最差”、“令人失望”和“可怕”这样的负面评论,以及像“着迷”、“明亮”和“美味”这样的正面评论。

但是,我们的模型可以改进。

TF–IDF 术语权重

在大型文本语料库中,一些单词会经常出现,但很少携带关于文档实际内容的有意义的信息(例如“the”、“a”和“is”)。如果我们将计数数据直接输入到分类器中,那些非常频繁的词将会掩盖那些更罕见但更有趣的词的频率。Tf-idf 允许我们根据术语对文档的重要性来衡量它们。

因此,我们将实例化 TF–IDF 矢量器,并使其适合我们的训练数据。我们指定 min_df = 5,这将从我们的词汇表中删除出现在少于五个文档中的任何单词。

from sklearn.feature_extraction.text import TfidfVectorizervect = TfidfVectorizer(min_df = 5).fit(X_train)
len(vect.get_feature_names())

9680

X_train_vectorized = vect.transform(X_train)model = LogisticRegression()
model.fit(X_train_vectorized, y_train)
predictions = model.predict(vect.transform(X_test))
print('AUC: ', roc_auc_score(y_test, predictions))

AUC:0.759768072872

因此,尽管我们能够将特征的数量从 29990 减少到仅仅 9680,我们的 AUC 分数下降了几乎 4%。

使用下面的代码,我们能够获得一个具有最小 tf-idf 的功能列表,这些功能通常出现在所有评论中,或者很少出现在很长的评论中,以及一个具有最大 TF-IDF 的功能列表,这些功能包含经常出现在评论中,但通常不会出现在所有评论中的单词。

feature_names = np.array(vect.get_feature_names())sorted_tfidf_index = X_train_vectorized.max(0).toarray()[0].argsort()print('Smallest Tfidf: \n{}\n'.format(feature_names[sorted_tfidf_index[:10]]))
print('Largest Tfidf: \n{}\n'.format(feature_names[sorted_tfidf_index[:-11:-1]]))

最小 tfi df:[' blazin ' ' 4 thd ' ' nations ' ' Committee ' ' 300 MGS ' ' 350 MGS ' ' sciences ' ' biochemical ' ' nas ' ' fnb ']

最大 Tfidf: ['芥末' ' br ' '挺举' '唐' '辣椒' '伤口' '鱼子酱' '莎莎' '垃圾' ' el']

让我们测试我们的模型:

print(model.predict(vect.transform(['The candy is not good, I will never buy them again','The candy is not bad, I will buy them again'])))

【1 0】

我们当前的模型将“糖果不好吃,我再也不会买它们”的文档错误分类为正面评论,也将“糖果不好吃,我会再买它们”的文档错误分类为负面评论。

n-grams

解决这种错误分类的一种方法是添加 n 元语法。例如,二元模型计算相邻单词对的数量,并且可以给我们一些特征,比如坏和不错。因此,我们正在重新调整我们的训练集,指定最小文档频率为 5,并提取 1-grams 和 2-grams。

vect = CountVectorizer(min_df = 5, ngram_range = (1,2)).fit(X_train)
X_train_vectorized = vect.transform(X_train)
len(vect.get_feature_names())

61958

现在我们有了更多的功能,但是我们的 AUC 分数增加了:

model = LogisticRegression()
model.fit(X_train_vectorized, y_train)predictions = model.predict(vect.transform(X_test))
print('AUC: ', roc_auc_score(y_test, predictions))

T5 AUC:0.838772959029

使用系数来检查每个特征,我们可以看到

feature_names = np.array(vect.get_feature_names())
sorted_coef_index = model.coef_[0].argsort()print('Smallest Coef: \n{}\n'.format(feature_names[sorted_coef_index][:10]))
print('Largest Coef: \n{}\n'.format(feature_names[sorted_coef_index][:-11:-1]))

最小系数:['最差' '还行' '不推荐' '不值得' '糟糕' '最好' '不幸' '糟糕' '非常失望' '失望']

最大系数:['好吃' '惊艳' '不太' '优秀' '失望' '不苦' '好吃' '上瘾' '很棒' '喜欢这个]]

我们的新模型已经正确地预测了负面评论的“不推荐”、“不值得”等二元模型,以及正面评论的“不苦”、“不太”等二元模型。

让我们测试我们的新模型:

print(model.predict(vect.transform(['The candy is not good, I would never buy them again','The candy is not bad, I will buy them again'])))

[0 1]

我们的最新模型现在可以正确地将它们分别识别为负面和正面评论。

自己试试

我希望你喜欢这篇文章,并享受在文本数据上练习机器学习技能的乐趣!请随意留下反馈或问题。

参考资料:

Scikit-learn

使用 Rvest 和 Shiny 在 R 中抓取数据并构建一个 Webapp

原文:https://towardsdatascience.com/scrape-data-and-build-a-webapp-in-r-using-rvest-and-shiny-f20d84dd1b74?source=collection_archive---------3-----------------------

Photo by Patrick Fore on Unsplash

通过传统方法分享你的分析和数据科学发现很酷,但是如果你想和更多的人分享呢?如果您想要实时共享某个数据集的分析,该怎么办?通过几十行代码,您可以在一个下午创建这样一个工具。

我将分享我如何使用 R 计算语言和几个关键包构建了一个几乎实时的 webapp。您将学习如何抓取网站、解析数据,以及创建任何拥有浏览器的人都可以访问的 webapp。

问题陈述

我需要显示来自 https://coinmarketcap.com/gainers-losers/[的数据,以便让我轻松地看到当天哪些硬币在真正的加热器上。](https://coinmarketcap.com/gainers-losers/)

工具

我们将利用 Rvest 包shinyshinydashboard 以及各种 tidyverse 工具,都在 Rstudio IDE 中。

虽然 RSelenium 是一个流行且可行的 web 抓取工具(通过解析 HTML 从网站收集数据),但 Rvest 包无疑是一个更整洁、更干净的工具。

该脚本的基本工作流程如下:

  1. 创建新的 Rstudio 项目
  2. 创建一个“应用程序。r "闪亮的文件
  3. 调用库
  4. 构建函数
  5. 构建用户界面
  6. 构建服务器
  7. 部署

所以让我们开始吧。

调用库

我们将调用上面“工具”一节中讨论的库:

library(shiny)
library(tidyverse)
library(shinydashboard)
library(rvest)

构建函数

始终认识到编码的枯燥(不要重复自己)准则,我们将构建简单的函数来收集和整理我们的数据,因此我们不必重复代码。

#####################
####### F N S #######
#####################get.data <- function(x){myurl <- read_html("[https://coinmarketcap.com/gainers-losers/](https://coinmarketcap.com/gainers-losers/)") # read our webpage as htmlmyurl <- html_table(myurl)  # convert to an html table for ease of use

  to.parse <- myurl[[1]]  # pull the first item in the list
  to.parse$`% 1h` <- gsub("%","",to.parse$`% 1h`) # cleanup - remove non-characters
  to.parse$`% 1h`<- as.numeric(to.parse$`% 1h`) #cleanup - convert percentages column to numeric so we can sort
  to.parse$Symbol <- as.factor(to.parse$Symbol) # cleanup - convert coin symbol to factor

  to.parse$Symbol <- factor(to.parse$Symbol,
                            levels = to.parse$Symbol[order(to.parse$'% 1h')])  # sort by gain value
  to.parse  # return the finished data.frame
}

get.data 函数抓取我们的网站,返回一个对我们有用的数据框。

我们使用 Rvest 包中的 read_htmlhtml_table 函数读入网页数据,并对其进行格式化,以便于处理。接下来,我们从该网页中取出许多表格中的第一个,并用基本的 R 函数清理它。最后,我们根据百分比增益值对新数据帧进行排序。

如果您要在 R 控制台中用

get.data()

您将返回如下所示的数据框:

get.data() returns this data.frame

如你所见,这显示了哪些硬币在过去的一个小时里收益最大,按收益百分比排序。这些数据是整个仪表板的基础。

我们将构建的下一个函数叫做 get.infobox.val. 它只是从上面的数据框中提取最高值。

get.infobox.val <- function(x){

  df1 <- get.data() # run the scraping function above and assign that data.frame to a variable
  df1 <- df1$`% 1h`[1]  # assign the first value of the % gain column to same variable
  df1   # return value

}

最后一个函数叫做 get.infobox.coin ,返回最高硬币的名称。

get.infobox.val <- function(x){

  df1 <- get.data() # run the scraping function above and assign that data.frame to a variable
  df1 <- df1$`% 1h`[1]  # assign the first value of the % gain column to same variable
  df1   # return value

}

现在我们已经构建了我们的函数,是时候构建闪亮的仪表板,向全世界显示我们的数据了。

进入闪亮的 Webapps

一个闪亮的 webapp 将允许我们建立一个交互式仪表板,我们将让 Rstudio 通过他们的服务器为我们托管。他们有一个免费的计划,所以任何人都可以很容易地开始使用它。来自 Rstudio 文档:

闪亮的应用程序有两个组件,一个用户界面对象和一个服务器函数,它们作为参数传递给shinyApp 函数,该函数从这个 UI/服务器对创建一个闪亮的应用程序对象。

在这一点上,我强烈推荐浏览上面引用的官方文档,让自己熟悉基本的闪亮的概念。

为了避免过多赘述,让我们从构建 UI 对象开始。

用户界面

在 UI 对象中,我们将展示我们的仪表板。当我做这个的时候,我用了一个铅笔线框草图。为了帮助您直观地看到最终结果,这里是成品的截图:

Our finished dashboard for reference

shinydashboard 结构允许我们有一个侧边栏和一个仪表板区域,我们可以在那里添加行和列中的框。上面的黑色区域是侧边栏,右边的是主体。现在来看一下 UI 代码。

ui <- dashboardPage(

  # H E A D E R

  dashboardHeader(title = "Alt Coin Gainers"), 

接下来,我们将 dashboardPage 函数分配给 UI,然后添加我们需要的部分。

# S I D E B A R

  dashboardSidebar(

    h5("A slightly interactive dashboard that pulls the top gainers from the last hour from
       coinmarketcap.com. Refreshes every 60 seconds."),

    br(),
    br(),
    br(),
    br(),
    br(),
    br(),
    br(),
    br(),
    br(),
    br(),

    h6("Built by Brad Lindblad in the R computing language 
      [  R Core Team (2018). R: A language and environment for statistical computing. R Foundation for Statistical Computing,
  Vienna, Austria. URL [https://www.R-project.org/](https://www.R-project.org/)]"),
    br(),
    h6("R version 3.4.4 (2018-03-15) 'Someone to Lean On'"),
    br(),
    a("[bradley.lindblad@gmail.com](mailto:bradley.lindblad@gmail.com)", href="[bradley.lindblad@gmail.com](mailto:bradley.lindblad@gmail.com)")

  ),

侧边栏是放置文档或过滤器的好地方(这在本教程中没有涉及)。您会注意到,您可以将某些 html 标签和类传递给文本。 H5 只是一个标签,它将文本定义为文档中的第五层标题,通常是第五大文本。

# B O D Y
  dashboardBody(

  fluidRow(

    # InfoBox
    infoBoxOutput("top.coin",
                  width = 3),

    # InfoBox
    infoBoxOutput("top.name",
                  width = 3)

  ),

  fluidRow(column(
    # Datatable
      box(
        status = "primary",
        headerPanel("Data Table"),
        solidHeader = T,
        br(),
        DT::dataTableOutput("table", height = "350px"),
        width = 6,
        height = "560px"
      ),

      # Chart
      box(
        status = "primary",
        headerPanel("Chart"),
        solidHeader = T,
        br(),
        plotOutput("plot", height = "400px"),
        width = 6,
        height = "500px"
      ),
      width = 12
    )

  )
  )

)

主体部分,我们构建仪表板中的主要项目。主体部分有几个关键部分实际输出数据。

信息盒

# InfoBox
    infoBoxOutput("top.coin",
                  width = 3),

    # InfoBox
    infoBoxOutput("top.name",
                  width = 3)

这两个代码块输出了仪表板顶部的两个紫色框。两个输出 ID“top . coin”和“top.name”引用了在服务器函数中输出的数据,我们将在后面介绍。

数据表和图

# Datatable
      box(
        status = "primary",
        headerPanel("Data Table"),
        solidHeader = T,
        br(),
        DT::dataTableOutput("table", height = "350px"),
        width = 6,
        height = "560px"
      ),# Chart
      box(
        status = "primary",
        headerPanel("Chart"),
        solidHeader = T,
        br(),
        plotOutput("plot", height = "400px"),
        width = 6,
        height = "500px"
      ),

数据表和曲线图也是如此。是将绑定到下面的服务器函数的输出 ID,并且也绑定到服务器

计算机网络服务器

下一个议程是定义我们的服务器功能。服务器函数是通过 UI 函数计算、读取、绘制或显示数值的地方。

#####################
#### S E R V E R ####
#####################server <- function(input, output) {# R E A C T I V E 
  liveish_data <- reactive({
    invalidateLater(60000)    # refresh the report every 60k milliseconds (60 seconds)
    get.data()                # call our function from above
  })

  live.infobox.val <- reactive({
    invalidateLater(60000)    # refresh the report every 60k milliseconds (60 seconds)
    get.infobox.val()         # call our function from above
  })

  live.infobox.coin <- reactive({
    invalidateLater(60000)    # refresh the report every 60k milliseconds (60 seconds)
    get.infobox.coin()        # call our function from above
  })

还记得我们一开始定义的函数吗?我们现在就要使用它们。我们还将添加另一个概念:反应式表达。这些允许我们闪亮的仪表板定期更新或基于用户输入。对于这个仪表板,我们要求程序每 60 秒运行一次我们的函数,用我们抓取的网站的最新值更新仪表板。

数据表

# D A T A   T A B L E   O U T P U T
  output$table <- DT::renderDataTable(DT::datatable({
    data <- liveish_data()}))

还记得我们上面定义的输出 ID 吗?我们将在上面的函数中引用它。注意,我们从一开始就使用了 liveish_data 反应函数,而不是我们的原始函数。

情节

# P L O T   O U T P U T
  output$plot <- renderPlot({ (ggplot(data=liveish_data(),       aes(x=Symbol, y=`% 1h`)) +
          geom_bar(stat="identity", fill = "springgreen3") +
          theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
          ggtitle("Gainers from the Last Hour"))
  })

接下来,我们使用 ggplot2 绘制一个简单的柱状图。

信息盒

# I N F O B O X   O U T P U T - V A L
  output$top.coin <- renderInfoBox({
    infoBox(
      "Gain in Last Hour",
      paste0(live.infobox.val(), "%"),
      icon = icon("signal"),
      color = "purple",
      fill = TRUE)
  })

  # I N F O B O X   O U T P U T - N A M E
  output$top.name <- renderInfoBox({
    infoBox(
      "Coin Name",
      live.infobox.coin(),
      icon = icon("bitcoin"),
      color = "purple",
      fill = TRUE)
  })

}

最后,我们使用服务器函数开头定义的反应表达式绘制两个信息框。

部署

脚本的最后一部分将我们的 UI 与服务器结合起来,并部署应用程序。

#####################
#### D E P L O Y ####
###################### Return a Shiny app objectshinyApp(ui = ui, server = server)
shinyApp(ui = ui, server = server)

此时,您应该有一个正在运行的应用程序出现在 Rstudio 的一个窗口中。

点击在浏览器中打开按钮,查看应用程序的非混乱版本;部署后您将看到的实际版本。

收尾工作

至此,所有的重担都完成了;我们构建了一个从网站下载并解析 html 的刮刀,然后我们使用 shinydashboard 框架构建了一个闪亮的应用程序,向全世界展示我们的分析。

在这一点上,所有剩下的是部署应用程序,这让我们非常容易。只需点击 Rstudio 预览中出现的部署按钮,然后按照说明进行操作。总的来说,从这一点开始部署应该不到 10 分钟。

我希望这篇小教程能在你的 R 之旅中帮助你,并给你一些关于用这种强大的开源语言可以构建什么样的东西的想法。

如果你有任何问题或者只是想聊聊 R,请发邮件到bradley.lindblad@gmail.com 给我。

附录

这是完整的脚本,你也可以从我的 Github 页面上为这个项目克隆。

library(shiny)
library(tidyverse)
library(shinydashboard)
library(rvest)#####################
####### F N S #######
#####################get.data <- function(x){myurl <- read_html("[https://coinmarketcap.com/gainers-losers/](https://coinmarketcap.com/gainers-losers/)") # read our webpage as html
  myurl <- html_table(myurl)  # convert to an html table for ease of use

  to.parse <- myurl[[1]]  # pull the first item in the list
  to.parse$`% 1h` <- gsub("%","",to.parse$`% 1h`) # cleanup - remove non-characters
  to.parse$`% 1h`<- as.numeric(to.parse$`% 1h`) #cleanup - convert percentages column to numeric
  to.parse$Symbol <- as.factor(to.parse$Symbol) # cleanup - convert coin symbol to factor

  to.parse$Symbol <- factor(to.parse$Symbol,
                            levels = to.parse$Symbol[order(to.parse$'% 1h')])  # sort by gain value
  to.parse  # return the finished data.frame
}get.infobox.val <- function(x){

  df1 <- get.data() # run the scraping function above and assign that data.frame to a variable
  df1 <- df1$`% 1h`[1]  # assign the first value of the % gain column to same variable
  df1   # return value

}get.infobox.coin <- function(x){

  df <- get.data()  # run the scraping function above and assign that data.frame to a variable
  df <- df$Name[1]  # assign the first value of the name column to same variable
  df   # return value

}#####################
####### U I #########
#####################ui <- dashboardPage(

  # H E A D E R

  dashboardHeader(title = "Alt Coin Gainers"),

  # S I D E B A R

  dashboardSidebar(

    h5("A slightly interactive dashboard that pulls the top gainers from the last hour from
       coinmarketcap.com. Refreshes every 60 seconds."),

    br(),
    br(),
    br(),
    br(),
    br(),
    br(),
    br(),
    br(),
    br(),
    br(),

    h6("Built by Brad Lindblad in the R computing language 
      [  R Core Team (2018). R: A language and environment for statistical computing. R Foundation for Statistical Computing,
  Vienna, Austria. URL [https://www.R-project.org/](https://www.R-project.org/)]"),
    br(),
    h6("R version 3.4.4 (2018-03-15) 'Someone to Lean On'"),
    br(),
    a("[bradley.lindblad@gmail.com](mailto:bradley.lindblad@gmail.com)", href="[bradley.lindblad@gmail.com](mailto:bradley.lindblad@gmail.com)")

  ),

  # B O D Y
  dashboardBody(

  fluidRow(

    # InfoBox
    infoBoxOutput("top.coin",
                  width = 3),

    # InfoBox
    infoBoxOutput("top.name",
                  width = 3)

  ),

  fluidRow(column(
    # Datatable
      box(
        status = "primary",
        headerPanel("Data Table"),
        solidHeader = T,
        br(),
        DT::dataTableOutput("table", height = "350px"),
        width = 6,
        height = "560px"
      ),

      # Chart
      box(
        status = "primary",
        headerPanel("Chart"),
        solidHeader = T,
        br(),
        plotOutput("plot", height = "400px"),
        width = 6,
        height = "500px"
      ),
      width = 12
    )

  )
  )

)#####################
#### S E R V E R ####
#####################server <- function(input, output) {# R E A C T I V E 
  liveish_data <- reactive({
    invalidateLater(60000)    # refresh the report every 60k milliseconds (60 seconds)
    get.data()                # call our function from above
  })

  live.infobox.val <- reactive({
    invalidateLater(60000)    # refresh the report every 60k milliseconds (60 seconds)
    get.infobox.val()         # call our function from above
  })

  live.infobox.coin <- reactive({
    invalidateLater(60000)    # refresh the report every 60k milliseconds (60 seconds)
    get.infobox.coin()        # call our function from above
  })

  # D A T A   T A B L E   O U T P U T
  output$table <- DT::renderDataTable(DT::datatable({
    data <- liveish_data()}))

  # P L O T   O U T P U T
  output$plot <- renderPlot({ (ggplot(data=liveish_data(), aes(x=Symbol, y=`% 1h`)) +
                                 geom_bar(stat="identity", fill = "springgreen3") +
                                 theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
                                 ggtitle("Gainers from the Last Hour"))
  })

  # I N F O B O X   O U T P U T - V A L
  output$top.coin <- renderInfoBox({
    infoBox(
      "Gain in Last Hour",
      paste0(live.infobox.val(), "%"),
      icon = icon("signal"),
      color = "purple",
      fill = TRUE)
  })

  # I N F O B O X   O U T P U T - N A M E
  output$top.name <- renderInfoBox({
    infoBox(
      "Coin Name",
      live.infobox.coin(),
      icon = icon("bitcoin"),
      color = "purple",
      fill = TRUE)
  })

}#####################
#### D E P L O Y ####
###################### Return a Shiny app objectshinyApp(ui = ui, server = server)
shinyApp(ui = ui, server = server)

在网上搜寻收视率最高的电视电影

原文:https://towardsdatascience.com/scrape-the-web-for-top-rated-movies-on-tv-ac66df0bd502?source=collection_archive---------8-----------------------

Photo by Frank Okay on Unsplash

在这篇文章中,我将展示如何使用 Scrapy 框架 在互联网上搜索顶级电影。这个网页抓取器的 目标 是找到在电影数据库上具有高用户评级的电影。这些影片的列表将存储在一个 SQLite 数据库中,并通过电子邮件发送给 。这样你就知道你再也不会错过电视上的大片了。

寻找一个好的网页来抓取

我从在线电视指南开始寻找比利时电视频道上的电影。但是您可以轻松地修改我的代码,将其用于任何其他网站。为了让你刮电影的时候更轻松,确定你要刮的网站

  • 具有带 的可理解类或 id 的 HTML 标签
  • 以一种 一致 的方式使用类和 id
  • 结构良好的网址
  • 在一个页面上包含所有相关的 电视频道
  • 每个工作日都有一个 单独的页面
  • 只列出电影 ,没有其他节目类型,如现场表演、新闻、报道等。除非你能轻易地将电影与其他节目类型区分开来。

有了发现的结果,我们将从电影数据库【TMDB】中获取电影评级和其他一些信息。

决定存储什么信息

我将收集以下关于电影的信息:

  • 电影名称
  • 电视频道
  • 电影开始的时间
  • 这部电影在电视上播出的日期
  • 类型
  • 情节
  • 出厂日期
  • 链接到 TMDB 的详细页面
  • TMDB 评级

你可以用所有演员、导演、有趣的电影事实等等来补充这个列表。所有你想知道更多的信息。

在 Scrapy 中,该信息将存储在 的字段中。

创建 Scrapy 项目

我假设你已经安装了 Scrapy。如果没有,可以按照 Scrapy 优秀的安装手册。

安装 Scrapy 后,打开命令行并转到您想要存储 Scrapy 项目的目录。然后运行:

*scrapy startproject topfilms*

这将为 top films 项目创建一个文件夹结构,如下所示。现在可以忽略 topfilms.db 文件。这是我们将在下一篇关于管道的博客文章中创建的 SQLite 数据库。

定义废料项目

*在这个故事中,我们将使用文件 **items.py 。*创建你的 Scrapy 项目时默认创建 Items.py。

一个scrapy.Item是一个容器,将在网页抓取过程中被填充。它将保存我们想要从网页中提取的所有字段。该项目的内容可以用与 Python dict 相同的方式访问。

打开 items.py 并添加一个包含以下字段的Scrapy.Item class:

*import scrapyclass TVGuideItem(scrapy.Item):
    title = scrapy.Field()
    channel = scrapy.Field()
    start_ts = scrapy.Field()
    film_date_long = scrapy.Field()
    film_date_short = scrapy.Field()
    genre = scrapy.Field()
    plot = scrapy.Field()
    rating = scrapy.Field()
    tmdb_link = scrapy.Field()
    release_date = scrapy.Field()
    nb_votes = scrapy.Field()*

用管道处理项目

在开始一个新的 Scrapy 项目后,您将拥有一个名为 pipelines.py 的文件。打开该文件,复制粘贴如下所示的代码。之后,我将一步一步地向您展示代码的每一部分是做什么的。

*import sqlite3 as lite
con = None  # db connection
class StoreInDBPipeline(object):
    def __init__(self):
        self.setupDBCon()
        self.dropTopFilmsTable()
        self.createTopFilmsTable()def process_item(self, item, spider):
        self.storeInDb(item)
        return itemdef storeInDb(self, item):
        self.cur.execute("INSERT INTO topfilms(\
        title, \
        channel, \
        start_ts, \
        film_date_long, \
        film_date_short, \
        rating, \
        genre, \
        plot, \
        tmdb_link, \
        release_date, \
        nb_votes \
        ) \
        VALUES( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )",
        (
        item['title'],
        item['channel'],
        item['start_ts'],
        item['film_date_long'],
        item['film_date_short'],
        float(item['rating']),
        item['genre'],
        item['plot'],
        item['tmdb_link'],
        item['release_date'],
        item['nb_votes']
        ))
        self.con.commit()def setupDBCon(self):
        self.con = lite.connect('topfilms.db')
        self.cur = self.con.cursor()def __del__(self):
        self.closeDB()def createTopFilmsTable(self):
        self.cur.execute("CREATE TABLE IF NOT EXISTS topfilms(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \
        title TEXT, \
        channel TEXT, \
        start_ts TEXT, \
        film_date_long TEXT, \
        film_date_short TEXT, \
        rating TEXT, \
        genre TEXT, \
        plot TEXT, \
        tmdb_link TEXT, \
        release_date TEXT, \
        nb_votes \
        )")def dropTopFilmsTable(self):
        self.cur.execute("DROP TABLE IF EXISTS topfilms")

    def closeDB(self):
        self.con.close()*

首先,我们从导入 SQLite 包开始,并给它起别名lite。我们还初始化了一个用于数据库连接的变量con

创建一个类来存储数据库中的项

接下来,您创建一个具有逻辑名称的 。在设置文件中启用管道后(稍后将详细介绍),这个类将被调用。

*class StoreInDBPipeline(object):*

定义构造函数方法

构造函数方法是名为__init__的方法。当创建一个StoreInDBPipeline类的实例时,这个方法会自动运行。

*def __init__(self):
        self.setupDBCon()
        self.dropTopFilmsTable()
        self.createTopFilmsTable()*

在构造函数方法中,我们启动了在构造函数方法下面定义的另外三个方法。

SetupDBCon 方法

通过方法setupDBCon,我们创建了 topfilms 数据库(如果它还不存在的话)并用connect函数连接到它。

*def setupDBCon(self):
        self.con = lite.connect('topfilms.db')
	self.cur = self.con.cursor()*

这里我们将 alias lite 用于 SQLite 包。其次,我们用cursor函数创建一个光标对象。使用这个游标对象,我们可以在数据库中执行 SQL 语句。

DropTopFilmsTable 方法

构造函数中调用的第二个方法是dropTopFilmsTable。顾名思义,它删除 SQLite 数据库中的表。

每次运行 web scraper 时,数据库都会被完全删除。如果你也想这样做,那就看你自己了。如果你想对电影数据进行一些查询或分析,你可以保存每次运行的抓取结果。

我只想看接下来几天的顶级电影,仅此而已。因此,我决定在每次运行时删除数据库。

*def dropTopFilmsTable(self):
        self.cur.execute("DROP TABLE IF EXISTS topfilms")*

使用光标对象cur我们执行DROP语句。

CreateTopFilmsTable 方法

放下 top films 表后,我们需要创建它。这是通过构造函数方法中的最后一个方法调用来完成的。

*def createTopFilmsTable(self):
        self.cur.execute("CREATE TABLE IF NOT EXISTS topfilms(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \
        title TEXT, \
        channel TEXT, \
        start_ts TEXT, \
        film_date_long TEXT, \
        film_date_short TEXT, \
        rating TEXT, \
        genre TEXT, \
        plot TEXT, \
        tmdb_link TEXT, \
        release_date TEXT, \
        nb_votes \
        )")*

我们再次使用游标对象 cur 来执行CREATE TABLE语句。添加到桌面电影中的字段与我们之前创建的 Scrapy 项目中的字段相同。为了简单起见,我在 SQLite 表中使用了与 Item 中完全相同的名称。只有id字段是额外的。

旁注:查看 SQLite 数据库的一个很好的应用是 Firefox 中的 SQLite 管理器插件。你可以在 Youtube 上观看这个 SQLite 管理器教程来学习如何使用这个插件。

流程项目方法

此方法必须在 Pipeline 类中实现,并且必须返回 dict、Item 或 DropItem 异常。在我们的网络刮刀,我们将返回项目。

*def process_item(self, item, spider):
        self.storeInDb(item)
	return item*

与解释的其他方法相比,它有两个额外的参数。被刮的item和刮物品的spider。从这个方法中,我们启动storeInDb方法,然后返回项目。

StoreInDb 方法

这个方法执行一个INSERT语句将抓取的条目插入 SQLite 数据库。

*def storeInDb(self, item):
        self.cur.execute("INSERT INTO topfilms(\
        title, \
        channel, \
        start_ts, \
        film_date_long, \
        film_date_short, \
        rating, \
        genre, \
        plot, \
        tmdb_link, \
        release_date, \
        nb_votes \
        ) \
        VALUES( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )",
        (
        item['title'],
        item['channel'],
        item['start_ts'],
        item['film_date_long'],
        item['film_date_short'],
        float(item['rating']),
        item['genre'],
        item['plot'],
        item['tmdb_link'],
        item['release_date'],
        item['nb_votes']
        ))
        self.con.commit()*

表字段的值来自 item,这是此方法的一个参数。这些值被简单地称为一个字典值(记住一个条目只不过是一个字典?).

每个构造函数都有一个…析构函数

与构造函数方法相对应的是名为__del__的析构函数方法。在 pipelines 类的析构函数方法中,我们关闭了与数据库的连接。

*def __del__(self):
	self.closeDB()*

CloseDB 方法

*def closeDB(self):
	self.con.close()*

在最后一个方法中,我们用close函数关闭数据库连接。所以现在我们已经写了一个全功能的管道。还剩下最后一步来启用管道。

在 settings.py 中启用管道

打开 settings.py 文件,添加以下代码:

*ITEM_PIPELINES = {
    'topfilms.pipelines.StoreInDBPipeline':1
}*

整数值 表示流水线运行的顺序。因为我们只有一个管道,所以我们给它赋值 1。

在 Scrapy 中创建一个蜘蛛

现在我们就来看看刺儿头的核心, 蜘蛛 。这是你的刮网器将完成的地方。我将一步一步地向您展示如何创建一个。

导入必要的包

首先,我们将导入必要的包和模块。我们使用CrawlSpider模块跟踪在线电视指南中的链接。

RuleLinkExtractor用于确定我们想要关注的链接。

config模块包含一些在蜘蛛中使用的常量,如DOM_1, DOM_2START_URL。配置模块位于当前目录的上一个目录。这就是为什么你在配置模块前看到两个点。

最后,我们导入了TVGuideItem。该 TVGuideItem 将用于包含抓取过程中的信息。

*import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from fuzzywuzzy import fuzz
from ..config import *
from topfilms.items import TVGuideItem*

告诉蜘蛛去哪里

其次,我们创建了 CrawlSpider 类的子类。这是通过插入 CrawlSpider 作为TVGuideSpider类的参数来实现的。

我们给蜘蛛一个name,提供allowed_domains(例如 themoviedb.org)和start_urls。在我的例子中,start_urls 是电视指南的网页,所以您应该通过自己的首选网站来更改它。

通过rulesdeny 参数,我们告诉爬行器在起始 URL 上跟随(不跟随)哪些 URL。不跟随的 URL 是用正则表达式指定的。

我对昨天放映的电影不感兴趣,所以我拒绝蜘蛛跟踪以“ gisteren ”结尾的 URL。

好吧,但是蜘蛛应该跟踪哪些 URL 呢?为此,我使用了restrict_xpaths参数。它说要关注所有带有 class = " button button–beta "的 URL。这些事实上是未来一周每天的电影链接。

最后,通过callback参数,我们让蜘蛛知道当它跟踪一个 URL 时该做什么。它将执行功能parse_by_day。我将在下一部分解释这一点。

*class TVGuideSpider(CrawlSpider):
    name = "tvguide"
    allowed_domains = [DOM_1, DOM_2]
    start_urls = [START_URL]# Extract the links from the navigation per day
    # We will not crawl the films for yesterday
    rules = (
        Rule(LinkExtractor(allow=(), deny=(r'\/gisteren'), restrict_xpaths=('//a[@class="button button--beta"]',)), callback="parse_by_day", follow= True),
    )*

解析跟踪的 URL

TVGuideScraper 的一部分功能parse_by_day每天从网页上抓取每个频道所有电影的概览。response参数来自运行网络抓取程序时启动的Request

在被抓取的网页上,你需要找到用来显示我们感兴趣的信息的 HTML 元素。两个很好的工具是 Chrome 开发者工具和 Firefox 中的 Firebug 插件。

我们想要存储的一个东西是我们正在抓取电影的date。这个日期可以在带有class="grid__col__inner"的 div 中的段落(p)中找到。显然,这是您应该为自己的网页修改的内容。

利用响应对象的xpath method,我们提取段落中的文本。在这篇关于如何使用 xpath 函数的教程中,我学到了很多东西。

通过使用extract_first,我们确保不会将这个日期存储为一个列表。否则,在 SQLite 数据库中存储日期时会出现问题。

之后,我对 film_date_long 执行了一些数据清理,并创建了格式为 YYYYMMDD 的film_date_short。我创建了这种 YYYYMMDD 格式,以便稍后按时间顺序对电影进行排序。

接下来,刮电视频道。如果是在ALLOWED_CHANNELS(在 config 模块中定义)的列表中,我们继续刮标题和开始时间。该信息存储在由TVGuideItem()启动的项目中。

在这之后,我们想继续刮电影数据库。我们将使用 URLhttps://www.themoviedb.org/search?query=来显示被抓取的电影的搜索结果。对于这个 URL,我们要添加电影标题(代码中的url_part)。我们只是重复使用在电视指南网页上的链接中找到的 URL 部分。

有了这个 URL,我们创建了一个新的请求,并继续 TMDB。使用request.meta['item'] = item,我们将已经抓取的数据添加到请求中。这样我们可以继续填充我们当前的 TVGuideItem。

Yield request实际发起请求。

*def parse_by_day(self, response):film_date_long = response.xpath('//div[@class="grid__col__inner"]/p/text()').extract_first()
        film_date_long = film_date_long.rsplit(',',1)[-1].strip()  # Remove day name and white spaces# Create a film date with a short format like YYYYMMDD to sort the results chronologically
        film_day_parts = film_date_long.split()months_list = ['januari', 'februari', 'maart',
                  'april', 'mei', 'juni', 'juli',
                  'augustus', 'september', 'oktober',
                  'november', 'december' ]year = str(film_day_parts[2])
        month = str(months_list.index(film_day_parts[1]) + 1).zfill(2)
        day = str(film_day_parts[0]).zfill(2)film_date_short = year + month + dayfor col_inner in response.xpath('//div[@class="grid__col__inner"]'):
            chnl = col_inner.xpath('.//div[@class="tv-guide__channel"]/h6/a/text()').extract_first()if chnl in ALLOWED_CHANNELS:
                for program in col_inner.xpath('.//div[@class="program"]'):
                    item = TVGuideItem()
                    item['channel'] = chnl
                    item['title'] = program.xpath('.//div[@class="title"]/a/text()').extract_first()
                    item['start_ts'] = program.xpath('.//div[@class="time"]/text()').extract_first()
                    item['film_date_long'] = film_date_long
                    item['film_date_short'] = film_date_shortdetail_link = program.xpath('.//div[@class="title"]/a/@href').extract_first()
                    url_part = detail_link.rsplit('/',1)[-1]# Extract information from the Movie Database [www.themoviedb.org](http://www.themoviedb.org)
                    request = scrapy.Request("https://www.themoviedb.org/search?query="+url_part,callback=self.parse_tmdb)
                    request.meta['item'] = item  # Pass the item with the request to the detail pageyield request*

抓取电影数据库中的附加信息

正如您注意到的,在函数parse_by_day中创建的请求中,我们使用了回调函数parse_tmdb。这个函数在请求抓取 TMDB 网站时使用。

在第一步中,我们获取 parse_by_day 函数传递的商品信息。

带有 TMDB 搜索结果的页面可能会列出同一个电影名称的多个搜索结果(查询中传递了 url_part)。我们也用if tmddb_titles检查是否有结果。

我们使用 fuzzywuzzy 包对电影片名进行模糊匹配。为了使用 fuzzywuzzy 包,我们需要将import语句与前面的导入语句一起添加。

*from fuzzywuzzy import fuzz*

如果我们找到 90%匹配,我们使用搜索结果来做剩下的搜集工作。我们不再看其他搜索结果。为此,我们使用了break语句。

接下来,我们从搜索结果页面中收集genreratingrelease_date,收集方式与之前使用 xpath 函数的方式类似。为了获得发布日期的 YYYYMMDD 格式,我们使用splitjoin函数执行一些数据处理。

我们想再次对 TMDB 的详细信息页面发起一个新的请求。这个请求将调用parse_tmdb_detail函数来提取电影情节和 TMDB 的票数。这将在下一节中解释。

*def parse_tmdb(self, response):
        item = response.meta['item']  # Use the passed itemtmdb_titles = response.xpath('//a[@class="title result"]/text()').extract()if tmdb_titles:  # Check if there are results on TMDB
            for tmdb_title in tmdb_titles:
                match_ratio = fuzz.ratio(item['title'], tmdb_title)
                if match_ratio > 90:
                    item['genre'] = response.xpath('.//span[@class="genres"]/text()').extract_first()
                    item['rating'] = response.xpath('//span[@class="vote_average"]/text()').extract_first()
                    release_date = response.xpath('.//span[@class="release_date"]/text()').extract_first()
                    release_date_parts = release_date.split('/')
                    item['release_date'] = "/".join([release_date_parts[1].strip(), release_date_parts[0].strip(), release_date_parts[2].strip()])
                    tmdb_link = "https://www.themoviedb.org" + response.xpath('//a[@class="title result"]/@href').extract_first()
                    item['tmdb_link'] = tmdb_link# Extract more info from the detail page
                    request = scrapy.Request(tmdb_link,callback=self.parse_tmdb_detail)
                    request.meta['item'] = item  # Pass the item with the request to the detail pageyield request
                    break  # We only consider the first match
                else:
                    return*

从详细信息页面抓取电影情节

我们要讨论的最后一个函数是一个短函数。像以前一样,我们获取 parse_tmdb 函数传递的项目,并抓取plotnumber of votes的详细信息页面。

在这个阶段,我们已经完成了为这部电影搜集信息的工作。换句话说,这部电影的项目已经满员了。Scrapy 然后将使用管道中编写的代码来处理这些数据,并将其放入数据库。

*def parse_tmdb_detail(self, response):
        item = response.meta['item']  # Use the passed item item['nb_votes'] = response.xpath('//span[@itemprop="ratingCount"]/text()').extract_first()
        item['plot'] = response.xpath('.//p[@id="overview"]/text()').extract_first() yield item*

在 Scrapy 中使用扩展

在关于管道的部分,我们已经看到了如何将抓取结果存储在 SQLite 数据库中。现在我将向您展示如何通过电子邮件 发送刮擦结果。通过这种方式,你可以在邮箱里看到下周收视率最高的电影。

导入必要的包

我们将使用文件 扩展名. py 。当您创建 Scrapy 项目时,这个文件会自动创建在根目录中。我们首先导入我们将在本文件后面使用的包。

*import logging
from scrapy import signals
from scrapy.exceptions import NotConfigured
import smtplib
import sqlite3 as lite
from config import **

并不真正需要logging包。但是这个包可以用来调试你的程序。或者只是向日志中写入一些信息。
signals模块将帮助我们知道蜘蛛何时被打开和关闭。我们将在蜘蛛完成工作后发送带有电影的电子邮件。

我们从scrapy.exceptions模块导入方法NotConfigured。当在 settings.py 文件中没有配置扩展名时,会出现这个问题。具体来说,参数MYEXT_ENABLED必须设置为True。我们将在后面的代码中看到这一点。

导入smtplib包以便能够发送电子邮件。我使用我的 Gmail 地址发送电子邮件,但是你可以修改 config.py 中的代码来使用另一个电子邮件服务。

最后,我们导入sqlite3包来从数据库中提取收视率最高的电影,并导入config来获取我们的常量。

在扩展中创建 SendEmail 类

首先,我们定义了logger对象。通过这个对象,我们可以在特定事件时将消息写入日志。然后我们用构造函数方法创建了SendEmail类。在构造函数中,我们将FROMADDRTOADDR分配给类的相应属性。这些常量设置在 config.py 文件中。这两个属性我都用了我的 Gmail 地址。

*logger = logging.getLogger(__name__)class SendEmail(object):
    def __init__(self):
        self.fromaddr = FROMADDR
        self.toaddr  = TOADDR*

实例化扩展对象

SendEmail对象的第一个方法是from_crawler。我们做的第一项检查是在 settings.py 文件中是否启用了MYEXT_ENABLED。如果不是这种情况,我们抛出一个NotConfigured异常。发生这种情况时,扩展中的其余代码不会被执行。

settings.py 文件中我们需要添加以下代码来启用这个扩展。

*MYEXT_ENABLED = True
EXTENSIONS = {
    'topfilms.extensions.SendEmail': 500,
    'scrapy.telnet.TelnetConsole': None
}*

所以我们将布尔标志MYEXT_ENABLED设置为True。然后我们将自己的扩展SendEmail添加到EXTENSIONS字典中。整数值 500 指定了扩展必须执行的顺序。我还不得不禁用了TelnetConsole。否则发送电子邮件不起作用。通过放置None而不是整数顺序值来禁用该扩展。

接下来,我们用cls()函数实例化扩展对象。我们将一些signals连接到这个扩展对象。我们对spider_openedspider_closed信号感兴趣。最后我们返回ext对象。

*@classmethod
    def from_crawler(cls, crawler):
        # first check if the extension should be enabled and raise
        # NotConfigured otherwise
        if not crawler.settings.getbool('MYEXT_ENABLED'):
            raise NotConfigured# instantiate the extension object
        ext = cls()# connect the extension object to signals
        crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened)
        crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed)# return the extension object
        return ext*

定义 spider_opened 事件中的操作

当蜘蛛被打开时,我们只是想把它写到日志中。因此,我们使用在代码顶部创建的logger对象。使用info方法,我们向日志中写入一条消息。Spider.name替换为我们在 TVGuideSpider.py 文件中定义的名称。

*def spider_opened(self, spider):
        logger.info("opened spider %s", spider.name)*

在 spider_closed 事件后发送电子邮件

SendEmail类的最后一个方法中,我们发送包含顶级电影概述的电子邮件。

我们再次向日志发送通知,告知蜘蛛已经关闭。其次,我们创建一个到 SQLite 数据库的连接,该数据库包含 ALLOWED_CHANNELS 下周的所有电影。 我们选择带有rating >= 6.5的影片。您可以根据需要将评级更改为更高或更低的阈值。然后,生成的影片按格式为 YYYYMMDD 的film_date_short和开始时间start_ts排序。

我们获取游标cur中的所有行,并检查是否有一些使用len函数的结果。例如,当您将阈值等级设置得太高时,可能会没有结果。

for row in data我们浏览每一个结果电影。我们从row中提取所有有趣的信息。对于一些数据,我们用encode('ascii','ignore')进行编码。这是为了忽略一些特殊字符,如é、à、è等。否则,我们会在发送电子邮件时出错。

当收集了关于电影的所有数据后,我们编写了一个字符串变量topfilm。每个topfilm然后连接到变量topfilms_overview,这将是我们发送的电子邮件的信息。如果我们的查询结果中没有电影,我们会在短消息中提到这一点。

最后,由于有了smtplib包,我们用 Gmail 地址发送邮件。

*def spider_closed(self, spider):
        logger.info("closed spider %s", spider.name)# Getting films with a rating above a threshold
        topfilms_overview = ""
        con = lite.connect('topfilms.db')
        cur = con.execute("SELECT title, channel, start_ts, film_date_long, plot, genre, release_date, rating, tmdb_link, nb_votes "
                          "FROM topfilms "
                          "WHERE rating >= 6.5 "
                          "ORDER BY film_date_short, start_ts")data=cur.fetchall()if len(data) > 0:  # Check if we have records in the query result
            for row in data:
                title = row[0].encode('ascii', 'ignore')
                channel = row[1]
                start_ts = row[2]
                film_date_long = row[3]
                plot = row[4].encode('ascii', 'ignore')
                genre = row[5]
                release_date = row[6].rstrip()
                rating = row[7]
                tmdb_link = row[8]
                nb_votes = row[9]
                topfilm = ' - '.join([title, channel, film_date_long, start_ts])
                topfilm = topfilm + "\r\n" + "Release date: " + release_date
                topfilm = topfilm + "\r\n" + "Genre: " + str(genre)
                topfilm = topfilm + "\r\n" + "TMDB rating: " + rating + " from " + nb_votes + " votes"
                topfilm = topfilm + "\r\n" + plot
                topfilm = topfilm + "\r\n" + "More info on: " + tmdb_link
                topfilms_overview = "\r\n\r\n".join([topfilms_overview, topfilm])con.close()if len(topfilms_overview) > 0:
            message = topfilms_overview
        else:
            message = "There are no top rated films for the coming week."msg = "\r\n".join([
          "From: " + self.fromaddr,
          "To: " + self.toaddr,
          "Subject: Top Films Overview",
          message
          ])
        username = UNAME
        password = PW
        server = smtplib.SMTP(GMAIL)
        server.ehlo()
        server.starttls()
        server.login(username,password)
        server.sendmail(self.fromaddr, self.toaddr, msg)
        server.quit()*

通过分机发送电子邮件的结果

这段代码的最终结果是在你的邮箱里有一个顶级电影的概览。太好了!现在,您不必再在在线电视指南上查找这些内容了。

规避知识产权禁令的技巧

当你在短时间内发出许多请求时,你就有被服务器禁止的风险。在这最后一部分,我将向你展示一些避免 IP 封禁的技巧。

推迟你的请求

避免 IP 禁止的一个简单方法是在每个请求 之间 暂停。在 Scrapy 中,只需在 settings.py 文件中设置一个参数即可。您可能已经注意到,settings.py 文件中有很多参数被注释掉了。

搜索参数DOWNLOAD_DELAY并取消注释。我将 暂停长度设置为 2 秒 。根据您必须发出的请求数量,您可以更改这一点。但我会把它设置为至少 1 秒。

*DOWNLOAD_DELAY=2*

避免 IP 封禁的更高级方法

默认情况下,每次你做一个请求,你用 同一个用户代理 来做。由于有了包fake_useragent,我们可以很容易地为每个请求改变用户代理。

这段代码的所有功劳归于 Alecxe,他写了一个很好的 python 脚本来使用 fake_useragent 包。

首先,我们在 web scraper 项目的根目录下创建一个文件夹scrapy _ fake _ user agent*。在这个文件夹中,我们添加了两个文件:*

  • init。py 是一个空文件
  • middleware . py

要使用这个中间件,我们需要在 settings.py 文件中启用它。这是通过代码完成的:

*DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddleware.useragent.UserAgentMiddleware': None,
    'scrapy_fake_useragent.middleware.RandomUserAgentMiddleware': 400,
}*

首先,我们通过指定 None 而不是一个整数值来禁用 Scrapy 的默认值UserAgentMiddleware。然后我们启用自己的中间件RandomUserAgentMiddleware。直观地说,中间件是在请求 期间 执行的一段代码。

在文件middleware . py中,我们为每个请求添加代码到 随机化用户代理 。确保您安装了 fake_useragent 包。从fake _ user agent 包中,我们导入了UserAgent模块。这包含了 不同用户代理 的列表。在 RandomUserAgentMiddleware 类的构造函数中,我们实例化了 UserAgent 对象。在方法process _ request中,我们将用户代理设置为来自ua对象的随机用户代理。在请求的报头中。

*from fake_useragent import UserAgentclass RandomUserAgentMiddleware(object):
    def __init__(self):
        super(RandomUserAgentMiddleware, self).__init__()self.ua = UserAgent()def process_request(self, request, spider):
        request.headers.setdefault('User-Agent', self.ua.random)*

结论

就是这样!我希望你现在对如何在你的网页抓取项目中使用 Scrapy 有一个清晰的认识。

抓取新加坡米其林星级餐厅名单

原文:https://towardsdatascience.com/scraping-a-list-of-singapore-michelin-star-restaurants-b0f3829e3c14?source=collection_archive---------9-----------------------

今天,我想通过提取新加坡米其林星级餐厅的名称、地址、星级和菜肴类型来练习网络抓取,以了解其地理位置和菜肴类型分布。

没有一个网站能同时包含这两种信息,所以我找到了一个包含地址的新闻网站和包含 T2 美食种类的米其林官方网站。我使用了 selectorgadget 和 rvest 来收集数据,做了一些清理工作,因为一些地址在帧中用不同的 CSS ids 进行了编码,而且菜肴类型包括英语和汉语单词。

然后我使用 BatchGeo 通过地址查找地理编码,这相当准确,也方便地提供了地图,只是它是否在输出中提供纬度/经度数据并不明显。

click for interactive version

它们似乎主要集中在 3 个集群周围:

  • 从丹戎巴葛一直到市政厅(市中心)
  • 位于果园/植物园区域(购物/旅游区)
  • 3 在圣淘沙,1 星(Osia)/2 星(L'Atelier de Joel Robuchon)/3 星(Joel Robuchon)(旅游/富裕住宅区)各一个

Click for interactive version

下一步,我们可以模糊匹配来自两个来源的餐馆名称(不同的拼写)以获得菜肴类型,按照地理区域对它们进行分组,并确定到不同住宅区的距离。

看看菜肴类型,当代和创新的食物是一件大事。法国菜和广东菜分别在西方和本地食物排行榜上名列前茅。今年有两家小贩/街头小吃被评为一星级。

cuisine types by star rating

这是我关于数据科学和视觉故事的# 100 日项目的第 57 天。报废数据可以在这里找到。感谢阅读。欢迎新主题的建议和反馈。

刮痧和模型和游戏,天啊!

原文:https://towardsdatascience.com/scraping-and-models-and-games-oh-my-8c6c5d4a7204?source=collection_archive---------15-----------------------

(Beautiful) Soup of the Day

注意:这不是一个高科技博客。然而,如果你是一个对这种事情感兴趣的男人或女人,这里是我的 GitHub 上这个项目的代码

完全披露:我累坏了。今天早上我在 Metis 展示了我的第一个重要的个人项目。这是一个为期两周的项目,巧合的是,这是我两周内的第一篇博文。我认为这其中可能存在一种有意义的关联——称之为有抱负的数据科学家的直觉吧。

不管怎样,这个项目完成了,我的报告结束了,冷的那份被打开了。因此,我在这里记录下我最后几周的神秘启蒙之旅和技术能力。

Data trumps features trumps algorithms... one of the main morals of this fable

在这个项目中,我们可以自由支配。唯一的方向是:

  1. 通过网络搜集搜集某种类型的数据集
  2. 使用线性回归预测你搜集的数据中的某种目标变量

我知道“乞讨”有负面含义。那是因为我选择从MobyGames.com收集数据。对于那些不熟悉的人来说,莫比游戏是“最古老、最大、最准确的视频游戏数据库”… 根据莫比游戏的说法。我有疑问。

我的目标(我试图预测的变量)是综合评价分数特征(用于产生预测的变量)是每个游戏的特征,例如:ESRB 等级、流派、游戏风格、发布日期、控制台等。
注意:有技术倾向的人可能会注意到这些特征都是绝对的。哦天啊。

喜欢刮数据。然后我讨厌它。然后我又喜欢上了它。这样的循环重复了几次,我却降落在了爱的一边(awww)。使用 BeautifulSoup,我写了几个刮刀。一个抓取了一个主游戏列表并收集了所有游戏的 URL,另一个实际上从这些页面中抓取了数据。

单个页面刮刀需要多次更换。因此,爱恨循环。尽管莫比游戏公司提出了很高的要求,但这些页面是不一致的,包含不同的字段,并且一般来说不能很好地使用通用的页面抓取器。然而,我克服了这个巨大的困难,写了一个对所有 8000 页都有效的 scraper。

That blank look on the whale’s face should have been a red flag

所以刮刮太棒了!我手里拿着一个数据框。一个包含所有现代家用游戏机游戏数据的数据框架——至少我是这么认为的。

不要误会我的意思:我的确成功地获取了莫比奥运会的所有数据,但对我来说不幸的是,只有 250 个条目包含了我的目标变量:综合评论家得分

所以我减少到一个 250 行的数据集。虽然没有 8000 英镑好,但至少也算不错了。当然,一旦我开始清理数据,我发现在那些包含评论家分数的 250 款游戏中,其中大约有 160 款有一套很好的功能没有任何 NaNs 不是一个数字’——也就是莫比游戏中另一个缺失的值)。

当我进行实际的线性回归时,我正在处理一个非常小的数据集。哦,我所有的特征都是绝对的。我尝试对各种特性的组合进行建模,但是由于要处理的观察数据如此之少,而特性又如此之多(一旦类别被分解到各自的列中),我只能对噪声进行建模。

这个故事的一个重要寓意是:当涉及到一堆分类变量时,线性回归并不好。

My pesudo-ordinal feature. Along with MPAA equivalents for those supposed ‘real adults’ out there who don’t know the ESRB scale.

这是我开始有创造力的时候。我没有数字特征作为输入,但这并不意味着我不能强制使用一个。如果你真的斜视,ESRB 评级可以被视为序数值。从适合孩子的到更成熟的,ESRB 组织对每个等级都设定了最低年龄。因此,我的“目标年龄”功能诞生了。

我的“万福玛利亚”特征工程起作用了…技术上。它确实给了我一个有一点点预测能力的模型。该模型采用游戏的目标年龄并预测评论家得分。

Can you even fathom the analytical beauty you see before you? The purple points are the actual data, the red line is the predicted scores from my model.

我的模型比 100 分制的随机猜测要好*,所以为我欢呼吧!(我在等谷歌招聘人员的电话)。平均而言,两个方向都只相差大约 9.7 点。印象深刻,对吧?*

嗯……没有。

我还建立了一个“虚拟模型”,不管游戏特征如何,它都能简单地猜出 77.5 分(平均值)。平均而言,该模型在任一方向上都偏离了 9.9 个百分点。不需要一个数据科学家就能看出 9.7 并不是一个巨大的进步,但它确实是一个进步。

由于数据如此不完整且充满了分类变量,要挤出任何预测值,需要极其不确定的特征工程辅助。我在数据收集和建模方面投入了大量的时间和精力,但最终,一切都回到了这篇博客条目顶部的白板寓意:

数据胜过特征胜过算法。

我可能没有造出世界上最好的模型,但我学到了从石头中吸取血液的重要一课。另外,构建过多无用的模型也无妨。它不仅给了我一些关于模型构建的很好的实践,而且给了我甚至更好的经验来评估糟糕的模型并确定它们实际上是糟糕的。

我们已经被介绍了项目 3,所以是时候开始了。我不是 100%确定我接下来会处理什么,但我知道一件事:

我将彻底检查我的下一个数据来源。

使用 Python 抓取哈维飓风洪水数据

原文:https://towardsdatascience.com/scraping-hurricane-harvey-flood-data-using-python-4e406d024f5f?source=collection_archive---------12-----------------------

正如数据科学中常说的那样,80%的工作是不那么迷人的数据获取和数据争论任务,剩下的 20%留给“性感”的分析和机器学习任务。通常,即使是这些数字也很慷慨——就我个人而言,我在这些乏味的数据争论任务上花费了过多的时间。如果你从事数据科学工作,你可能会感受到同样的痛苦。

在最近的一个项目中,我需要收集我的家乡德克萨斯州休斯顿的洪水数据,所以我建立了一个网络抓取器来从哈里斯县洪水预警系统获取数据。为了帮助缓解上面提到的一些乏味的数据科学困境,我在 Github 上为其他对洪水研究感兴趣的人发布了我的代码。您可以在下面的链接中找到该回购的链接。这篇文章的其余部分将展示几个使用代码的快速例子。

****** Github 洪水数据网页抓取器 ******

项目背景
当地县应急管理部门开发了 【哈里斯县洪水预警系统(FWS)】

Stream Gage Locations on the Harris County Flood Warning System (FWS) Website

FWS 从美国地质调查局(USGS)维护的流量表中获取数据。虽然每个 stream gauge 网站都提供了以 Excel 文件形式下载数据的功能,但我需要更多的数据,所以我构建了一个 webs scraper。你可以从这个回购中克隆刮刀。

使用
T21【Scraper】克隆 repo 后,安装' requirements.txt '文件中列出的需求。使用刮刀很简单:

Code snippet for querying stream gauge data from the FWS website

数据也可以下载到 JSON 文件中:

“高程”字段包含溪流底部上方水深的记录。“深度”字段是一个计算字段,记录了高出堤岸顶部的水的高度(TOB)。如果
水的深度高于 TOB,则‘above bank’键保存值‘True ’,否则为‘False’。有关更多详细信息,请参见自述文件。

{
    "sensorMetaData": {
        "sensorId": "519",
        "sensorType": "USGS Radar",
        "installedDate": "3/27/1984",
        "topOfBankFt": 32.0
    },
    "sensorData": [
        {
            "timestamp": "8/26/2017 7:31 AM",
            "elevation": {
                "value": 21.69,
                "units": "ft"
            },
            "depth": {
                "value": 0,
                "units": "ft"
            },
            "aboveBank": false
        },
        {
            "timestamp": "8/27/2017 5:43 AM",
            "elevation": {
                "value": 39.49,
                "units": "ft"
            },
            "depth": {
                "value": 7.490000000000002,
                "units": "ft"
            },
            "aboveBank": true
        }
    ]
}

查询和绘图示例 下面是从 475 号流量计获取数据并绘制数据的一小段代码:

这就产生了下面的情节…

Plotting the data using matplotlib

…正如我们所料,这符合 FWS 的情节:

Data as shown at https://www.harriscountyfws.org

最后总结 希望这个刮刀对其他有抱负的洪水研究者有用。如果您在使用代码时有任何疑问或问题,请随时联系我们!

刮实际和预测工资

原文:https://towardsdatascience.com/scraping-indeed-for-job-salaries-e7ede688f169?source=collection_archive---------4-----------------------

我最近参与的一个最有趣的项目涉及收集数据科学工作的工资信息,以便根据位置、职位和工作摘要来预测某些工作的工资。该项目是对一些新获得的数据科学技能的真正测试,如网络搜集、自然语言处理和建立分类预测模型。回归可以用于这样的任务,但由于工作工资存在相当大的差异,我将这视为一个分类问题,目标是预测工作工资是高于还是低于数据科学家的工资中位数。

这个问题的第一部分包括从 Indeed.com 上列出的招聘信息中收集数据,包括职位名称、公司、工作摘要、地点和薪水。这一部分是通过抓取大量不同的搜索页面来完成的。正如我在我的其他帖子中多次提到的,抓取是我最喜欢的,也可能是我最好的数据科学技能之一,所以在这一部分我有一点乐趣。首先,我创建了一个全国 30 个主要城市的列表,希望从中收集工作数据。然后,为了能够从一个网页上获得尽可能多的职位发布,我使用了 indeed 上的高级搜索功能来显示 50 个结果,但后来意识到我可以调整 url 来显示 100 个结果。

https://www.indeed.com/jobs?q=data+scientist&**l=Washington+DC**&**limit=50**&radius=25&**start=0**&pp=ADIAAAFbp-95iAAAAAEMMobjAQEBD3MzvjaRN_DEggu9hUHO3jOZTkJ2Z7SvcZJ1pEgnRjAhqUC21q96H2LZRAEACYLb_gg9TZj-Uiq9LmLnHRNRQqKGAQPQktPTwy4n4Swd39sFFyyDrS9wQYcfRpSo64YDtw

正如你在上面的 url 链接中看到的,为了让页面显示 100 个搜索结果,我只需将limit=50改为limit=100。然后,为了过滤搜索结果页面,我可以将start=0改为start=100start=200,一直到start=900,以获得相应城市的 1000 个结果。然后,我可以通过简单地将 url 中的l=Washington+DC更改为另一个城市名,比如l=Pittsburgh,为列表中的所有 30 个城市做这件事。

为了做到这一点,我创建了一个 for 循环,它将遍历我的 30 个城市,然后遍历每个搜索页面,为每个城市收集多达 1000 个职位发布。数据收集过程中出现的第一个问题是,并不是所有的招聘信息都列出了薪水。为了解决这个问题,我创建了一个简单的 try/except 语句,如果没有列出薪水,就返回'NA'。一旦我有了一个可用的 web 刮刀,我就在两三天的时间里运行刮刀几次,以便收集尽可能多的结果。然后我把我的结果放入熊猫的数据框架中,以便进行我的分析。因为我试图预测工资,所以我必须过滤我的结果,只包括列出工资的招聘信息,我决定只包括年薪。下一步是计算我的结果的中位数工资,结果是 110,000 美元,然后我为每份工作创建了一个二元变量——如果工资高于中位数,则为 1,如果工资低于中位数,则为 0。

继续建模!现在我有了一个清晰完整的数据框架——大约有 500 条记录,我可以用它来建立许多具有不同特征的分类模型,然后检查是什么因素导致一份工作成为“高薪”或“低薪”工作。我决定对模型使用随机森林分类,因为这是最准确的学习算法之一,而且它还会返回对分类中重要变量的估计,这对我们的分析尤其有价值。我特别感兴趣的特性是位置、职位和工作摘要。我分别为每个特征建立了分类模型。例如,我建立了一个模型,仅仅根据位置来预测一份工作是高薪还是低薪。对于职称和工作总结模型,我使用自然语言处理来根据出现的各种单词预测工资类别。

总的来说,我对结果相当满意。位置模型产生了大约 66%的准确性分数,这是三个模型中最不准确的。随机森林模型的要素重要性属性将为每个要素返回一个值,在本例中为每个城市,该值描述了该要素在模型预测过程中的重要性。我使用这个函数来查找最具预测能力的城市,并且我还将每个城市的工资中位数与我用于分析的总体工资中位数进行了比较。结果并不令人惊讶。我的模型显示,大市场和更昂贵的城市通常意味着更高的工资。这些城市包括纽约、圣何塞、旧金山、波士顿和费城。较小和较便宜的城市通常意味着较低的工资,如圣路易斯、密苏里州、佛罗里达州的珊瑚墙、宾夕法尼亚州的匹兹堡、德克萨斯州的休斯顿和德克萨斯州的奥斯汀。

职称和工作总结模型产生了更好的结果。为了稍微扩展一下模型构建过程,我首先使用了一个计数矢量器函数,该函数计算哪些词出现在了职位名称中,以及这些词出现的次数。这在所有职位上完成,以便为所有职位发布创建一个词频值矩阵。然后,我用这些字数建立了一个模型来预测一份工作是高薪还是低薪,这产生了一个强有力的模型,准确率约为 81%。根据该模型的结果,数据、科学家、工程师、学习、高级和机器等关键词通常与高薪工作相关,而研究和分析师等词通常与低薪工作相关。

使用相同的自然语言处理技术来构建工作总结模型。根据工作总结中出现的单词,最终的模型能够在大约 83%的情况下正确地确定一份工作是高薪还是低薪。机器、学习、数据、分析、工程和 python 等词通常与高薪工作相关,而健康、研究和大学等词通常与低薪工作相关。

为了构建一个更加复杂的模型,我将所有三个特性聚合到一个模型中。从本质上讲,这个模型会根据某个职位发布的位置、职位名称和职位摘要进行预测。虽然这并没有产生一个更准确的模型(大约 79%的准确率),但它确实表明,与工作地点相比,职称和工作总结更能预测一份工作的薪酬是高还是低。

那么这些信息为什么有用呢?作为雇主,我们的调查结果可以告诉我们,根据求职者被聘用的职位以及该职位所需的技能,他们可能值多少钱。例如,精通 python 技能的数据科学家可能比数据分析师的报酬更高。此外,如果一家公司希望扩大他们的数据科学团队,他们可能会考虑在数据科学家工资不高的地方进行,如密苏里州圣路易斯或德克萨斯州休斯顿。

在进行这样的分析时,肯定会有一个很大的假设。此问题假设 Indeed.com 上发布的数据科学家工资代表所有数据科学家的工资。这是一个不太安全的假设,因为大多数公司都不会在招聘信息中包含薪资信息。虽然这种假设可能会给我们一个数据科学家的工资中位数的不准确估计,但我们对某个工作是高薪还是低薪的预测仍然是有效的预测,这是可信的。

和往常一样,这里有一个我的 jupyter 笔记本的链接,以便更仔细地查看我的分析!

用 PRAW 刮红迪网

原文:https://towardsdatascience.com/scraping-reddit-with-praw-76efc1d1e1d9?source=collection_archive---------5-----------------------

最近,我试图开始一个项目,该项目将使用自然语言处理来分类一个给定的帖子来自哪个子编辑。例如,这个模型应该能够预测一个帖子是否来自于 r/Python 子编辑或者 r/Rlanguage 子编辑。这个过程的第一步是从每个子编辑中收集一些帖子。在过去,我使用过 BeautifulSouprequests python 库来完成这项工作。我的一些同事提到 API 包装器非常有用,可以简化大部分过程。这就是我如何偶然发现 Python Reddit API 包装器( PRAW )。

我发现的最有帮助的文章之一是 Felippe Rodrigues 的“如何用 Python 刮 Reddit”他在基本步骤和设置方面做得很好。如果你有兴趣做类似的事情,一定要去看看。我将这篇文章作为我自己项目的起点。下面我将带你了解如何使用 PRAW 进行设置,以及如何抓取文章标题、内容和其他元数据。你可以在我的个人 Github 上找到完整的代码。

开始使用 PRAW 的第一步是通过 reddit 创建一个应用程序。如果你转到这个链接,你应该会在底部找到一个标有“创建应用”或“创建另一个应用”的按钮你必须给你的脚本一个名字,并填写一个描述。一旦完成,确保选择“脚本”选项,然后确保将以下内容放入重定向 uri 框: http://localhost:8080 。这是由 PRAW 文档建议的,但显然是必要的,因为 Reddit 需要一个重定向 uri,即使我们的应用程序不使用它。如果成功的话,你会得到两串看似随机的字符。你可以在左上角找到第一个,你的“个人使用脚本”,就在“个人使用脚本”的正下方这个应该有 14 个字符长。接下来你需要的是“秘密”。虽然这听起来像是幻想小说中的东西,但它应该表示为一个 27 个字符的字符串,列在“个人使用脚本”的下面。有了这两样东西,我们终于可以开始从 Reddit 抓取帖子的旅程了!

现在,您需要打开您最喜欢的编辑器或 IDE。我用 PyCharm 做这个项目,但是 Atom 或者 Sublime 也可以。我们首先需要创建一个 praw.ini 文件。这将允许我们在未来利用 PRAW Reddit 实例,这意味着如果您决定发布它,我们可以将我们的个人使用脚本和秘密从我们的主要脚本中删除。

你可以参考关于 praw.ini 文件的文档,但是一定要确保这个文件确实叫做“praw.ini ”,并且它和你的抓取脚本位于同一个目录。可以在这个文件中定义多个凭证,但是今天我们将只使用一个凭证,所以我们将坚持使用[默认]站点。

[DEFAULT]
; this is your 14 character personal use script
client_id=51IfSlyxtyOUy3; this is your 27 character secret
client_secret=NToU1zG5d0LJq9fo3ryUtOigM5h; this is the name you gave your application
user_agent=subreddit scraper; this is username for the reddit account the app was created with
username=fake_username; password for the account
password=fake_password

请确保在这些字段中填写您的信息。上面的字段是使用随机生成的假值填写的。如果您不使用自己的信息替换这些字段,它将不起作用。

现在我们可以开始编写实际的抓取脚本了。第一步是导入必要的库,并使用我们在 praw.ini 文件中定义的凭证实例化 Reddit 实例。

from os.path import isfile
import praw
import pandas as pd
from time import sleep*# Get credentials from DEFAULT instance in praw.ini* reddit = praw.Reddit()

我决定创建一个类,允许我指定我感兴趣的特定子编辑、排序方法、文章数量以及结果是否应该写入文件。init 方法如下所示:

class SubredditScraper:

    def __init__(self, sub, sort=**'new'**, lim=900, mode=**'w'**):
        self.sub = sub
        self.sort = sort
        self.lim = lim
        self.mode = mode print(
            **f'SubredditScraper instance created with values '
            f'sub = {sub}, sort = {sort}, lim = {lim}, mode = {mode}'**)

我加入了一些打印语句来感受一下脚本的进度,因为在处理数百个帖子时可能需要一点时间来运行。接下来,我们将为 subreddit 实例设置排序方法。

def set_sort(self):
    if self.sort == **'new'**:
        return self.sort, reddit.subreddit(self.sub).new(limit=self.lim)
    elif self.sort == **'top'**:
        return self.sort, reddit.subreddit(self.sub).top(limit=self.lim)
    elif self.sort == **'hot'**:
        return self.sort, reddit.subreddit(self.sub).hot(limit=self.lim)
    else:
        self.sort= **'hot'** print(**'Sort method was not recognized, defaulting to hot.'**)
        return self.sort, reddit.subreddit(self.sub).hot(limit=self.lim)

这个方法将把 reddit 实例的 subreddit 和排序参数设置为我们在实例化我们的类时指定的值。这将返回一个元组,我们将在下一个方法中解包它。如果排序方法不是“新”、“前”或“热”,则默认为“热”。

最后,我们可以开始从指定的子编辑中收集帖子和其他信息:

def get_posts(self):
    *"""Get unique posts from a specified subreddit."""* sub_dict = {
        **'selftext'**: [], **'title'**: [], **'id'**: [], **'sorted_by'**: [],
        **'num_comments'**: [], **'score'**: [], **'ups'**: [], **'downs'**: []}
    csv = **f'{self.sub}_posts.csv'** *# Attempt to specify a sorting method.* sort, subreddit = self.set_sort()

    *# Set csv_loaded to True if csv exists since you can't 
    # evaluate the truth value of a DataFrame.* df, csv_loaded = (pd.read_csv(csv), 1) if isfile(csv) else (**''**, 0)

    print(**f'csv = {csv}'**)
    print(**f'After set_sort(), sort = {sort} and sub = {self.sub}'**)
    print(**f'csv_loaded = {csv_loaded}'**)

    print(**f'Collecting information from r/{self.sub}.'**)

这里我们创建了一个占位符字典,其中包含了我们将从这个子编辑的每个帖子中收集的每个属性。那我们就要建立。csv 文件以备将来使用,我们正在对 set_sort 方法返回的元组进行解包。最后一项设置是查看我们之前是否为此子编辑收集过帖子。如果是这样,我们将加载它。csv 文件放入数据帧,并将布尔变量 csv_loaded 设置为 1。否则,df 将是一个空字符串,csv_loaded 将被设置为 0。

这给我们带来了真正的刮肉。我们将使用 for 循环来查看每篇文章,并收集我们感兴趣的属性。

for post in subreddit:

    *# Check if post.id is in df and set to True if df is empty.
    # This way new posts are still added to dictionary when df = ''* unique_id = post.id not in tuple(df.id) if csv_loaded else True

    *# Save any unique posts to sub_dict.* if unique_id:
        sub_dict[**'selftext'**].append(post.selftext)
        sub_dict[**'title'**].append(post.title)
        sub_dict[**'id'**].append(post.id)
        sub_dict[**'sorted_by'**].append(sort)
        sub_dict[**'num_comments'**].append(post.num_comments)
        sub_dict[**'score'**].append(post.score)
        sub_dict[**'ups'**].append(post.ups)
        sub_dict[**'downs'**].append(post.downs)
    sleep(0.1)

如果您计划多次使用这个脚本来收集大量的帖子,我们需要检查每个帖子是否是唯一的,或者我们是否已经将它添加到我们的。csv 文件。这就是我们的布尔变量 csv_loaded 派上用场的地方。我们将检查文章的 id 属性是否在数据框(df)的“id”列中。如果这是我们第一次为此子编辑收集帖子,那么 unique_id 将为每个帖子设置为 True。然后,我们将把我们感兴趣的文章的每个属性添加到占位符字典中。最后,也可能是最重要的,我们会在每次发布后睡十分之一秒。这是一种人为的限速器。如果我们不这样做,我们最终会达到 API 的请求限制(1000)。有几种方法可以绕过这个限制,其中之一是请求一个刷新令牌,但是这暂时应该可以正常工作。

接下来,我们将把结果保存到. csv 文件中,或者根据我们之前是否抓取过这个子编辑来修改现有的文件:

new_df = pd.DataFrame(sub_dict)

*# Add new_df to df if df exists then save it to a csv.* if **'DataFrame'** in str(type(df)) and self.mode == **'w'**:
    pd.concat([df, new_df], axis=0, sort=0).to_csv(csv, index=False)
    print(
        **f'{len(new_df)} new posts collected and added to {csv}'**)
elif self.mode == **'w'**:
    new_df.to_csv(csv, index=False)
    print(**f'{len(new_df)} posts collected and saved to {csv}'**)
else:
    print(
        **f'{len(new_df)} posts were collected but they were not '
        f'added to {csv} because mode was set to "{self.mode}"'**)

这里我们使用 pandas concat 方法,以便将我们的新结果添加到现有结果中。如果存在 csv 文件,并且在实例化我们的类时 mode 被设置为“w ”,那么我们将它加载到 df 数据帧中。如果没有现存的。我们将把结果写入这个子编辑的 csv 文件。如果模式没有设置为“w ”,我们将打印出找到的帖子数量,而不是将它们写入文件。

这就是我们完善 SubredditScraper 类所需的全部内容。剩下要做的最后一件事是实例化我们的新类。

if __name__ == **'__main__'**:
    SubredditScraper(
        **'python'**,
         lim=997,
         mode=**'w'**,
         sort=**'new'**).get_posts()

如果你不熟悉if __name__ == '__main__':的用法,我建议看看科里·斯查费的关于这个话题的视频这里。这样,您应该能够运行这个脚本,从 python subreddit 中收集近 1000 篇帖子,并将这些帖子及其一些元数据保存到一个. csv 文件中。我希望这有所帮助!别忘了你可以在这里找到这个项目的完整代码。

用于酒店评论的网页抓取猫途鹰、文本挖掘和情感分析

原文:https://towardsdatascience.com/scraping-tripadvisor-text-mining-and-sentiment-analysis-for-hotel-reviews-cc4e20aef333?source=collection_archive---------0-----------------------

Phone credit: pexels

如何应用自然语言处理对酒店评论进行分类

一项又一项研究表明,猫途鹰在旅行者的决策过程中变得极其重要。然而,理解猫途鹰泡沫评分与数以千计的猫途鹰评论文本之间的细微差别可能具有挑战性。为了更彻底地了解酒店客人的评论是否会影响酒店的加班表现,我从猫途鹰搜集了一家酒店的所有英文评论——希尔顿夏威夷村。我不会讨论网页抓取的细节,这个过程的 Python 代码可以在这里找到。感谢 Furas 的提示。

加载库

library(dplyr)
library(readr)
library(lubridate)
library(ggplot2)
library(tidytext)
library(tidyverse)
library(stringr)
library(tidyr)
library(scales)
library(broom)
library(purrr)
library(widyr)
library(igraph)
library(ggraph)
library(SnowballC)
library(wordcloud)
library(reshape2)
theme_set(theme_minimal())

数据

df <- read_csv("Hilton_Hawaiian_Village_Waikiki_Beach_Resort-Honolulu_Oahu_Hawaii__en.csv")
df <- df[complete.cases(df), ]
df$review_date <- as.Date(df$review_date, format = "%d-%B-%y")dim(df); min(df$review_date); max(df$review_date)

Figure 1

希尔顿夏威夷村在猫途鹰上有 13,701 条英文评论,评论日期从 2002 年 3 月 21 日到 2018 年 8 月 2 日。

df %>%
  count(Week = round_date(review_date, "week")) %>%
  ggplot(aes(Week, n)) +
  geom_line() + 
  ggtitle('The Number of Reviews Per Week')

Figure 2

2014 年底收到的每周评论数量最多。该酒店在那一周收到了 70 多条评论。

评论文本的文本挖掘

df <- tibble::rowid_to_column(df, "ID")
df <- df %>%
  mutate(review_date = as.POSIXct(review_date, origin = "1970-01-01"),month = round_date(review_date, "month"))review_words <- df %>%
  distinct(review_body, .keep_all = TRUE) %>%
  unnest_tokens(word, review_body, drop = FALSE) %>%
  distinct(ID, word, .keep_all = TRUE) %>%
  anti_join(stop_words, by = "word") %>%
  filter(str_detect(word, "[^\\d]")) %>%
  group_by(word) %>%
  mutate(word_total = n()) %>%
  ungroup()word_counts <- review_words %>%
  count(word, sort = TRUE)word_counts %>%
  head(25) %>%
  mutate(word = reorder(word, n)) %>%
  ggplot(aes(word, n)) +
  geom_col(fill = "lightblue") +
  scale_y_continuous(labels = comma_format()) +
  coord_flip() +
  labs(title = "Most common words in review text 2002 to date",
       subtitle = "Among 13,701 reviews; stop words removed",
       y = "# of uses")

Figure 3

我们肯定可以做得更好一点,把“留下来”和“留下来”,把“游泳池”和“游泳池”结合起来。所谓的词干化,词干化是将屈折词(或有时是派生词)简化为词干、词根或词根格式的过程。

word_counts %>%
  head(25) %>%
  mutate(word = wordStem(word)) %>% 
  mutate(word = reorder(word, n)) %>%
  ggplot(aes(word, n)) +
  geom_col(fill = "lightblue") +
  scale_y_continuous(labels = comma_format()) +
  coord_flip() +
  labs(title = "Most common words in review text 2002 to date",
       subtitle = "Among 13,701 reviews; stop words removed and stemmed",
       y = "# of uses")

Figure 4

二元模型

我们经常想了解一篇复习中单词之间的关系。评论文章中有哪些常见的单词序列?给定一个单词序列,接下来最有可能是哪个单词?哪些词之间的关系最强?因此,许多有趣的文本分析都是基于这些关系。当我们检查两个连续单词对时,这被称为“二元模型”。

那么,希尔顿夏威夷村对猫途鹰最常见的评论是什么呢?

review_bigrams <- df %>%
  unnest_tokens(bigram, review_body, token = "ngrams", n = 2)bigrams_separated <- review_bigrams %>%
  separate(bigram, c("word1", "word2"), sep = " ")bigrams_filtered <- bigrams_separated %>%
  filter(!word1 %in% stop_words$word) %>%
  filter(!word2 %in% stop_words$word)bigram_counts <- bigrams_filtered %>% 
  count(word1, word2, sort = TRUE)bigrams_united <- bigrams_filtered %>%
  unite(bigram, word1, word2, sep = " ")bigrams_united %>%
  count(bigram, sort = TRUE)

Figure 5

最常见的重名是“彩虹塔”,其次是“夏威夷村”。

我们可以想象单词网络中的二元模型:

review_subject <- df %>% 
  unnest_tokens(word, review_body) %>% 
  anti_join(stop_words)my_stopwords <- data_frame(word = c(as.character(1:10)))
review_subject <- review_subject %>% 
  anti_join(my_stopwords)title_word_pairs <- review_subject %>% 
  pairwise_count(word, ID, sort = TRUE, upper = FALSE)set.seed(1234)
title_word_pairs %>%
  filter(n >= 1000) %>%
  graph_from_data_frame() %>%
  ggraph(layout = "fr") +
  geom_edge_link(aes(edge_alpha = n, edge_width = n), edge_colour = "cyan4") +
  geom_node_point(size = 5) +
  geom_node_text(aes(label = name), repel = TRUE, 
                 point.padding = unit(0.2, "lines")) +
  ggtitle('Word network in TripAdvisor reviews')
  theme_void()

Figure 6

以上可视化了猫途鹰评论中常见的二元词,显示了那些至少出现了 1000 次并且没有一个词是停用词的词。

网络图显示了顶部几个单词(“夏威夷”、“村庄”、“海洋”和“景色”)之间的强连接。然而,我们在网络中看不到清晰的聚类结构。

三元模型

二元模型有时是不够的,让我们看看希尔顿夏威夷村的猫途鹰评论中最常见的三元模型是什么?

review_trigrams <- df %>%
  unnest_tokens(trigram, review_body, token = "ngrams", n = 3)

trigrams_separated <- review_trigrams %>%
  separate(trigram, c("word1", "word2", "word3"), sep = " ")

trigrams_filtered <- trigrams_separated %>%
  filter(!word1 %in% stop_words$word) %>%
  filter(!word2 %in% stop_words$word) %>%
  filter(!word3 %in% stop_words$word)

trigram_counts <- trigrams_filtered %>% 
  count(word1, word2, word3, sort = TRUE)

trigrams_united <- trigrams_filtered %>%
  unite(trigram, word1, word2, word3, sep = " ")

trigrams_united %>%
  count(trigram, sort = TRUE)

Figure 7

最常见的三元组是“希尔顿夏威夷村”,其次是“钻石头塔”,等等。

评论中的关键词趋势

随着时间的推移,哪些词和话题变得越来越频繁或越来越不频繁?这些可以让我们了解酒店生态系统的变化,如服务、翻新、问题解决,并让我们预测哪些主题将继续增长。

我们想问这样的问题:随着时间的推移,哪些词在猫途鹰评论中出现的频率越来越高?

reviews_per_month <- df %>%
  group_by(month) %>%
  summarize(month_total = n())word_month_counts <- review_words %>%
  filter(word_total >= 1000) %>%
  count(word, month) %>%
  complete(word, month, fill = list(n = 0)) %>%
  inner_join(reviews_per_month, by = "month") %>%
  mutate(percent = n / month_total) %>%
  mutate(year = year(month) + yday(month) / 365)mod <- ~ glm(cbind(n, month_total - n) ~ year, ., family = "binomial")slopes <- word_month_counts %>%
  nest(-word) %>%
  mutate(model = map(data, mod)) %>%
  unnest(map(model, tidy)) %>%
  filter(term == "year") %>%
  arrange(desc(estimate))slopes %>%
  head(9) %>%
  inner_join(word_month_counts, by = "word") %>%
  mutate(word = reorder(word, -estimate)) %>%
  ggplot(aes(month, n / month_total, color = word)) +
  geom_line(show.legend = FALSE) +
  scale_y_continuous(labels = percent_format()) +
  facet_wrap(~ word, scales = "free_y") +
  expand_limits(y = 0) +
  labs(x = "Year",
       y = "Percentage of reviews containing this word",
       title = "9 fastest growing words in TripAdvisor reviews",
       subtitle = "Judged by growth rate over 15 years")

Figure 8

在 2010 年之前,我们可以看到一个围绕“星期五焰火”和“泻湖”的讨论高峰。像“度假费用”和“忙碌”这样词在 2005 年之前增长最快。

哪些词在评论中出现的频率越来越低?

slopes %>%
  tail(9) %>%
  inner_join(word_month_counts, by = "word") %>%
  mutate(word = reorder(word, estimate)) %>%
  ggplot(aes(month, n / month_total, color = word)) +
  geom_line(show.legend = FALSE) +
  scale_y_continuous(labels = percent_format()) +
  facet_wrap(~ word, scales = "free_y") +
  expand_limits(y = 0) +
  labs(x = "Year",
       y = "Percentage of reviews containing this term",
       title = "9 fastest shrinking words in TripAdvisor reviews",
       subtitle = "Judged by growth rate over 4 years")

Figure 9

这显示了几个自 2010 年以来兴趣逐渐消失的话题,包括“hhv”(我相信是希尔顿夏威夷村的简称)、“早餐”、“升级版”、“价格”和“免费”。

让我们比较几个精选的单词。

word_month_counts %>%
  filter(word %in% c("service", "food")) %>%
  ggplot(aes(month, n / month_total, color = word)) +
  geom_line(size = 1, alpha = .8) +
  scale_y_continuous(labels = percent_format()) +
  expand_limits(y = 0) +
  labs(x = "Year",
       y = "Percentage of reviews containing this term", title = "service vs food in terms of reviewers interest")

Figure 10

服务和食物都是 2010 年之前的热门话题。关于服务和食物的对话在 2003 年左右的数据开始时达到高峰,在 2005 年后一直处于下降趋势,偶尔出现高峰。

情感分析

情感分析广泛应用于客户意见材料,如评论和调查回复、在线和社交媒体,应用范围从营销到客户服务再到临床医学。

在我们的案例中,我们旨在确定评论者(即酒店客人)对其过去的经历或对酒店的情绪反应的态度。态度可能是一种判断或评价。

评论中最常见的正面和负面词汇。

reviews <- df %>% 
  filter(!is.na(review_body)) %>% 
  select(ID, review_body) %>% 
  group_by(row_number()) %>% 
  ungroup()
tidy_reviews <- reviews %>%
  unnest_tokens(word, review_body)
tidy_reviews <- tidy_reviews %>%
  anti_join(stop_words)

bing_word_counts <- tidy_reviews %>%
  inner_join(get_sentiments("bing")) %>%
  count(word, sentiment, sort = TRUE) %>%
  ungroup()

bing_word_counts %>%
  group_by(sentiment) %>%
  top_n(10) %>%
  ungroup() %>%
  mutate(word = reorder(word, n)) %>%
  ggplot(aes(word, n, fill = sentiment)) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~sentiment, scales = "free") +
  labs(y = "Contribution to sentiment", x = NULL) +
  coord_flip() + 
  ggtitle('Words that contribute to positive and negative sentiment in the reviews')

Figure 11

让我们试试另一个情感库,看看结果是否相同。

contributions <- tidy_reviews %>%
  inner_join(get_sentiments("afinn"), by = "word") %>%
  group_by(word) %>%
  summarize(occurences = n(),
            contribution = sum(score))
contributions %>%
  top_n(25, abs(contribution)) %>%
  mutate(word = reorder(word, contribution)) %>%
  ggplot(aes(word, contribution, fill = contribution > 0)) +
  ggtitle('Words with the greatest contributions to positive/negative 
          sentiment in reviews') +
  geom_col(show.legend = FALSE) +
  coord_flip()

Figure 12

有趣的是,“钻石”(如钻石头)被归类为积极情绪。

这里有一个潜在的问题,例如,“干净”,取决于上下文,如果前面有“不是”这个词,就有一种消极的情绪。事实上,在大多数情况下,unigrams 都有否定的问题。这就把我们带到了下一个话题:

在情感分析中使用二元模型提供上下文

我们想知道单词前面有多少个像“不是”这样的单词。

bigrams_separated %>%
  filter(word1 == "not") %>%
  count(word1, word2, sort = TRUE)

Figure 13

在数据中有 850 次单词“a”在单词“not”之前,在日期中有 698 次单词“the”在单词“not”之前。但是,这些信息没有意义。

AFINN <- get_sentiments("afinn")
not_words <- bigrams_separated %>%
  filter(word1 == "not") %>%
  inner_join(AFINN, by = c(word2 = "word")) %>%
  count(word2, score, sort = TRUE) %>%
  ungroup()

not_words

Figure 14

这告诉我们,在数据中,跟在“not”后面的最常见的情感关联词是“worth”,跟在“not”后面的第二个常见的情感关联词是“recommend”,它通常具有 2 的(正)分数。

那么,在我们的数据中,哪些词在错误的方向上贡献最大?

not_words %>%
  mutate(contribution = n * score) %>%
  arrange(desc(abs(contribution))) %>%
  head(20) %>%
  mutate(word2 = reorder(word2, contribution)) %>%
  ggplot(aes(word2, n * score, fill = n * score > 0)) +
  geom_col(show.legend = FALSE) +
  xlab("Words preceded by \"not\"") +
  ylab("Sentiment score * number of occurrences") +
  ggtitle('The 20 words preceded by "not" that had the greatest contribution to 
          sentiment scores, positive or negative direction') +
  coord_flip()

Figure 15

“不值得”、“不太好”、“不好”、“不推荐”和“不喜欢”这几个词是错误识别的主要原因,这使得文本看起来比实际情况积极得多。

除了“不”之外,还有其他否定后项的词,如“没有”、“从来没有”、“没有”。我们去看看。

negation_words <- c("not", "no", "never", "without")

negated_words <- bigrams_separated %>%
  filter(word1 %in% negation_words) %>%
  inner_join(AFINN, by = c(word2 = "word")) %>%
  count(word1, word2, score, sort = TRUE) %>%
  ungroup()

negated_words %>%
  mutate(contribution = n * score,
         word2 = reorder(paste(word2, word1, sep = "__"), contribution)) %>%
  group_by(word1) %>%
  top_n(12, abs(contribution)) %>%
  ggplot(aes(word2, contribution, fill = n * score > 0)) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~ word1, scales = "free") +
  scale_x_discrete(labels = function(x) gsub("__.+$", "", x)) +
  xlab("Words preceded by negation term") +
  ylab("Sentiment score * # of occurrences") +
  ggtitle('The most common positive or negative words to follow negations 
          such as "no", "not", "never" and "without"') +
  coord_flip()

Figure 16

看起来,将一个词误认为积极的最大来源是“不值得/很棒/很好/推荐”,而被错误分类的消极情绪的最大来源是“不坏”和“没问题”。

最后,让我们找出最正面和最负面的评论。

sentiment_messages <- tidy_reviews %>%
  inner_join(get_sentiments("afinn"), by = "word") %>%
  group_by(ID) %>%
  summarize(sentiment = mean(score),
            words = n()) %>%
  ungroup() %>%
  filter(words >= 5)sentiment_messages %>%
  arrange(desc(sentiment))

Figure 17

最正面评论的 ID 是 2363:

df[ which(df$ID==2363), ]$review_body[1]

Figure 18

sentiment_messages %>%
  arrange(sentiment)

Figure 19

最负面评论的 ID 是 3748:

df[ which(df$ID==3748), ]$review_body[1]

Figure 20

很有趣!源代码可以在 Github 上找到。祝你一周愉快!

参考:文本挖掘用 R

筛选数据科学职位的候选人—我的经验

原文:https://towardsdatascience.com/screening-candidates-for-data-science-positions-my-experiences-ab9c5332cfb?source=collection_archive---------3-----------------------

我是多伦多一家中型软件公司的数据科学家。在过去的几个月里,我参加了三个数据科学职位的面试——数据工程师、数据科学家和数据科学 QA。这篇文章包含了我作为一名面试官看待这些申请的一些想法。我写下这些,希望那些想申请数据科学职位的人会发现这有助于准备简历和参加面试。我确实找到了很多关于准备数据科学面试的东西,但从面试官的角度来看并不多。

公司中的“数据科学”团队是一个相对较新的现象,其中有各种各样的角色。这篇文章总结了一些角色及其描述。随着这种角色的增加,我们开始看到许多主要和次要角色提供数据科学方面的认证课程。抛开这些认证中哪些是好的不谈,由于这种趋势,我们开始看到许多带有“认证数据科学家”标签的简历。这也是评估一份简历变得困难的地方。

So many data science resumes! (image source: https://goo.gl/hWe6jy)

通常,当你作为一个非人力资源人员直接成为被雇佣者的团队成员看简历时,你会寻找什么?我寻找的是:a)与团队工作相关的经验,b)简历中还有哪些关于候选人的细节,如何呈现?体验部分很明显。我说的第二点是什么意思?我在寻找这样的东西:

  1. 清楚和/或完整地描述候选人工作/学习的时间和地点
  2. 存在任何 Github 档案和/或技术博客
  3. 技能和成就部分有哪些内容
  4. 简历的长度

我来一一说说,为什么我觉得这些很重要。

  1. 清晰/完整的描述:我一直看到简历中没有提到目前工作的国家或城市。我认为这很重要,尤其是当雇主对签证担保或那些通常希望在本地招聘的人有一些限制时(我不是在评论这是好是坏——这些只是雇主的偏好)。开始某种面试过程,然后很久以后才意识到这是一个限制,这是在浪费每个人的时间。一些候选人没有提到毕业的国家。虽然这本身不是一个大问题,但我认为这不必要地让简历看起来不完整。不是所有的大学都举世闻名。如果有人写“斯坦福大学”而没有提到一个国家,我仍然会说它不完整,但不是“红旗升旗”那种不完整。如果有人写了一个“ABC 工程学院”,之后什么也没提,那就是让简历看起来可疑的事情。当然,我只是给出个人观点,但我肯定我不是唯一的一个,而且在那里加上城市/国家名称并不需要太多。只是一个权宜之计,只要写的是真的。简历应该精确、简洁、完整。

2。github 简介/博客的出现:我认为这对于刚接触数据科学的人来说尤其重要,尤其是刚刚完成认证课程和相关顶点项目的人。仅仅列出课程项目是不够的,因为每个完成课程的人都必须完成这些项目。除此之外,还必须有一些东西告诉面试官,候选人理解他们所学的东西,能够适应新的问题场景,并关注该领域正在发生的事情。从事个人数据科学项目(例如,不属于任何课程的 kaggle 竞赛),发布一些文章(例如,关于他们最近阅读的内容,或者他们喜欢的工具,或者一些算法等。)是展示这一点的一些方式。

我个人觉得很难评估除了来自已知/未知机构的认证之外,完全不相关的工作,只有数据科学的“经验”是这个认证计划的课程项目,没有其他参考资料的个人资料。我同意这对求职者来说是一项额外的工作,但我认为这是值得的,因为这将我们与其他求职者区分开来,他们也有类似的背景/经验水平。

3.被提及的技能/成就有哪些:我不认为是 MS Office、敏捷方法论、参与每日 scrum 会议、在机器学习课上获得最高分等等。应该在中作为数据科学家职位的成就或技能提及。我希望在技能中看到的是某种逐项列出的项目,这些项目是技能的不同方面,例如:编程语言、机器学习库、可视化库、项目管理等。我一般不把成就放在我自己的简历中,但是如果有人把它放在那里,我希望看到一些实际的成就(例如,我为 Y 建立的模型 X 将软件 Z 中的错误减少了 XX%等)。用每一个可能的关键词填充简历也是一个坏主意。它可能通过了机器的筛选,但会吓退一个人。

4.**简历长度:**不同的人、不同的国家对此有不同的规范。最近,在 LinkedIn 上有一个关于这个话题的讨论,在安德烈·布尔科夫的帖子下,他说任何工作经验少于 10 年的人都应该有一页纸的简历。在其他地方,我每 5 年读 1 页,这对我来说更有意义。然而,我经常看到长达 7-8 页的简历(这在 QA 职位上更常见),它们基本上不能给我任何信息。每个小项目都有不必要的详细解释,在大多数情况下,项目甚至与数据科学毫无关系。

一些博士生或博士后的简历列出了他们所有的出版物。我认为这也是在软件行业背景下让面试官却步的原因。我本人有博士学位,有些工作我提交了长达 8 页的简历,列出了所有的出版物。然而,我还保留了一份 2 页的简历,专门针对与工程团队有更密切互动的行业职位。

另一件让我完全困惑的事情是——有些人在电话采访中听起来是多么冷漠。表现出对工作的兴趣 , 向潜在的团队成员提问(例如,团队有多少人,典型的分工是什么,比如工程和研究等),以及对面试过程的好奇心——这些都表明了候选人自己对广告职位的兴趣。在我有限的经验中,不问这些问题是一个很大的危险信号。虽然这只会发生在简历筛选之后,但有些问题也可以在求职信中解决(只要有选择,就使用它!).我个人对超长的求职信和那些有很多关于公司的通用的、最高级的奉承形容词的求职信感到厌恶。然而,我认为,即使没有这些特征,也可以写一封求职信,表明候选人对这个职位的兴趣,以及他们是如何适合这个职位的。

快速总结一下,在准备简历和准备面试时,要记住以下 5 件事:

  • 确保简历清晰、简洁
  • 尝试拥有一个最新的 github 简介和/或博客,并在简历中给出链接
  • 使技能/成就部分简洁并与职位相关
  • 不要把简历写得太长
  • 对公司和职位表现出兴趣

那么,这是否意味着以前没有数据科学经验的人不应该申请呢?不,我不是这个意思。让我们考虑个人 P 的情况,他是一位自学成才的数据科学家。他们做了一些在线课程,并从那里接手,自己做了一些家庭项目。他们没有写博客,也没有把所有东西都放在 github 上,但是可以详细描述他们做了什么。那应该怎么写在简历里呢?对此我不知道一个好的答案,但我看到人们放了一个叫做“个人数据科学项目”或类似的标题,来描述他们所做的工作——每个项目 3,4 句话。这是展示你作品的一种方式。显然,这不应该一直持续下去。也许挑选 2-3 个最重要的项目就可以了。然而,光靠 Kaggle 竞赛可能还不够,因为它们远离真实世界的场景。

最终,每个人的目标都是让自己的个人资料在其他人当中脱颖而出。

还有一些其他问题与工作职位有关(例如,数据科学 QA 职位对筛选候选人个人来说特别具有挑战性),以及关于面试流程,但也许我会在将来就此单独写一篇文章。 Jeremie Harris 关于“要成为数据科学家,不要从众”的帖子给了我写这篇帖子的灵感。所以,我向他致谢。

SD-WAN 链路交换机作为深度 Q 学习的强化学习实验

原文:https://towardsdatascience.com/sd-wan-link-switch-as-reinforcement-learning-experiment-with-deep-q-learning-7a39cd1e8722?source=collection_archive---------15-----------------------

Credit — https://usblogs.pwc.com/emerging-technology/deep-learning-ai/

Deep Q '或 Deep Q-Learning 是强化学习中众所周知的算法,它用深度神经网络逼近 MDP 系统的 Q 值。在本文中,我探索了解决 SD-WAN 网络中链路切换问题的相同算法,为此我已经开发了一个基于 Mininet 的 AI-gym(参见我以前的文章-Open-AI gym for SD-WAN Link Selection)。在应用 Deep-Q 算法时,我发现基于 Mininet 的 gym 通过发送真实的 TCP/UDP 流量来执行测量,花费了相当多的时间。这让我想到了另一个使用纯统计后端的想法,它通过生成具有特定均值和方差的高斯随机数来模拟流量测量。然后,该算法会根据数千集进行调整,并在最后与实际的 Mininet 后端进行交叉检查。本实验为 SD-WAN 链路切换问题可以通过强化学习得到有效解决提供了合理的证据。

关于深度 Q 学习实现的一些话

深度 Q-Learning 出自 DeepMind 研究团队(见开创性论文 用深度强化学习玩雅达利(Atari)Mnih et 的。艾尔。).实现这种算法有几种选择。我可以实现“双 Q 网络”或“单 Q 网络”以及“经验回放”。我也可以使用决斗架构(王等人的深度强化学习决斗网络架构)。艾尔。).围绕着*(open-ai,* Denny Britz Keon ) 我从Greg *中汲取了灵感。*这是一个简单的实施,只有经验回放和单一网络。这是解决翻转 问题的基线。跟我的问题类似,有离散的动作和无限连续的状态空间。这类似于我在两条链路中的一条上发送流量并观察吞吐量的问题。代理部分非常相似,只是 Cartpole AI-gym 将被替换为我之前已经开发的 SD-WAN 专用 AI-gym(参见我以前的文章)。

用于近似 Q 值的深度神经网络模型具有两个密集层,随后是线性激活

观察空间是由三个参数组成的元组——

(动作 _ 选择,当前 _ 带宽,可用 _ 带宽)

动作空间有两个值——0 和 1,用于选择 MPLS 或 INTERNET 链接。

深度 Q 学习的参数如下

伽马= 0.95

学习率= 0.001

内存大小= 1000000

批处理大小= 20

EXPLORATION_MAX = 1.0

EXPLORATION_MIN = 0.01

探索 _ 衰退= 0.995

回顾—剧集评分的下降趋势

正如我在之前的文章中提到的,单集的累积奖励呈下降趋势,如下图所示

从多次试验中也可以明显看出,随机试验的平均回报并没有显示出任何改善。

正如这里看到的,分数在零附近波动。没有任何学习就没有上升趋势(因为我们还没有应用深度 Q 学习)。然而,这一次在应用深度 Q 学习算法时,我遇到了一种新的障碍。在进行多集实验时,仅完成一集就存在时间跨度大的问题。这一次我使用 Mininet 来模拟 SD-WAN 环境,完成一集最多 30 个“时间刻度”真的很漫长。

基于 Mininet 的剧集执行时间过长

有了 Mininet 的后端,即使只有 30 个时间刻度,每集也要花相当多的时间。随着每个“时间滴答”流量在互联网链路上发送,然后进行测量。一个 100 集的实验在云虚拟机上轻松进行了 12 个多小时,并且在深度 Q 学习的性能上没有明显的趋势

深度 Q-Learning 众所周知需要大量的训练,只有 100 集,还不能确定训练进展如何。

统计后端

这个想法很简单。由于通过 Mininet 的实际流量需要时间,为什么我不根据某种统计分布来生成测量值呢?在 Mininet 实验中,我生成了一些分布式流量。为什么不在不实际发送流量的情况下,在生成测量时应用相同的分布呢?有了这个想法,我创建了一个健身房的统计后端,它基于正态分布生成测量值,具有一定的均值( )和标准差(σ),但没有流量通过链接。

以前,我们实际上是以一定的平均值( )和标准差(σ)生成互联网链接流量,然后将它发送到 Mininet 链接。现在,我们没有生成任何实际流量,而是将测量结果直接输出为由具有相同σ的正态分布生成的数字。这表示占用链路的外部互联网流量。由于链路容量固定在某个值,我们通过从链路容量中减去外部流量带宽来获得流量吞吐量。我在测量“达到的带宽”时也加入了一些随机性。这是通过生成一个具有窄正态分布的数字来实现的,该数字具有“实现的带宽”和低σ值(0.5 Mbps)。

具有统计后端的较短剧集

我用 deep Q agent 和随机试验进行了相同的训练测量。现在这几集的时间缩短了很多,但是学习并不明显。

下面是《随机特工》超过 100 集的评分。你可以看到平均分数是负的-

以下是用深 Q 网训练 100 集的结果-

你可以看到平均分数远低于零。

1000 集(见下)很明显训练失败了。没有上升趋势。这几集的累积分数都很低-

奖励设计中的修正

很明显,这个问题对代理人来说太难训练和解决了。据我所知,有多种因素导致代理人的报酬较低

1)严格的带宽分配

我将链路容量设置为 10 Mbps,并通过它发送了 5 Mbps 的 UDP 流量(偏差为 2 Mbps)。这为我们的预期流量留下了大约 5 Mbps。然而,我将 SLA 限制设置为 6 Mbps。这意味着,如果“实现的带宽”小于 6 Mbps,我们应该进行链路切换。由于这种紧密的安排没有太多的空间,代理别无选择,只能不时地进行链接切换,最终导致较低的累积分数。所以解决方案是公平分配带宽。我再次将 SLA 保持在 6 Mbps,但这次给了其他一般流量 4 Mbps。这为我们留下了大约 6 Mbps 的“预期流量”,以满足现在更频繁的 SLA。

2)奖励设计因失败而倾斜

以前的设计是增加+1 以在“时间滴答”中存活。每当“实现的带宽”不能满足 SLA 限制时,惩罚为-5。同样,对于采用 MPLS 链路,惩罚是-2。然而,对于采取正确的行动,即在带宽可用时使用互联网链接,只给予+1 奖励。因此,在默认奖励为+1 的情况下,如果它采取了正确的行动,总奖励为 2,而对于错误的行动,总奖励为-1。此外,每当错过 SLA 时,该“时间刻度”的总奖励为-4。由于紧张的带宽预算,代理经常无法达到 SLA 目标,总体得分迅速下降。

还有一条规则可以提前结束一集。如果一个情节连续两次没有达到 SLA 指导原则,则该情节会被突然终止。然而,这并没有体现在奖励上。这也在新的逻辑中被修正了。

新逻辑

新的设计原则基于以下几点

鼓励在“时间滴答”中生存

鼓励正确的链接选择,这次奖励更多

阻止错误的链接选择,但不要像以前那样惩罚

阻止 SLA 违约,但不作为最高处罚

因结束这一集而受到重罚

下面是新逻辑的实现(参见下面的代码)

因此,这一次我们在选择 MPLS 链路时扣除 1,而不是 2。此外,只要选择了正确的链接,奖励就会增加+2。“SLA 失误”被罚了-2 分,而不是之前的-5 分。每多活一个滴答+1 的奖励仍然存在。然而,我们因为提前结束这一集而扣除了最大值(-5)。这一次,没有提前结束这一集的目标变成了奖励设计。

3)短插曲长度

每集长度会影响奖励结果,从而影响学习过程。以前一集只有 30 分钟。考虑到实际的 Mininet 后端的实验速度很慢,这个值保持得很低。以每集 30 个“时间刻度”计算,总共 100 集在云虚拟机中需要大约 12 个小时。这是将情节重复数千次的主要障碍。众所周知,深度 Q-learning 最初需要许多片段来预热,因此不知道学习是否正在进行。有了统计后端,我能够保持 300 集的长度(因为 30 集对于一集来说是很低的数字),并且剧集完成得更快。我这次做了几千次实验,以获得学习的真实情况。只有当我切换到统计后端时,这种扭曲的奖励设计才变得明显。

培养

在修改了奖励设计和应用了统计后端之后,我又开始训练代理人。统计后端上的随机代理没有显示任何预期的学习。然而这一次每集的平均分数是正的。

然而,深度 Q 代理在很早的时候就显示出轻微的上升趋势事件,甚至有 100 集。

预热发生在大约 500 集的时候,如下图所示

当我们放大到 400-600 的范围时,这种突然的跳跃是很明显的

确认

在我用统计后端运行了 1000 集的训练后,很明显代理人在每一集上都有持续的进步。现在是在 Mininet 后端验证这种学习的时候了。关于统计后端的学习对于 Mininet 是否仍然有效,在这里我们实际发送流量以确定吞吐量?

我使用Mininet 后端运行 deep Q agent,但这次使用的是通过使用统计后端学习 1000 集训练获得的相同神经网络权重。细看单集 - ,评分的涨幅非常明显

Single Episode comparison after training

与随机和确定性代理相比,可以看到 deep Q 代理的明显增益。

从下面两个图中也可以清楚地看出,与随机代理相比,deep Q 代理进行的链路切换非常少

Random agent one episode details

Deep Q agent play for one episode

最后,对 100 集的情节进行了比较,很明显,deep Q 代理的平均回报远远高于具有 Mininet 后端的相同设置的随机代理

100 episode play random vs deep Q agent

结论

很明显,deep Q 代理知道何时为 SD-WAN 设置切换链路,并实际解决了链路切换问题。这是一个非常简单的代理,只有单 Q 网络与经验重播。结果可以通过更复杂的方法来改善,如双 Q 网络决斗双 Q 网络,甚至通过政策梯度方法,如演员-评论家(见萨顿和巴尔托)或 A3C 。本实验的目标不是实现最大可能的回报,而是表明强化学习在应用于 SD-WAN 链路切换问题时,实际上可以以合理的效率解决问题。人们可以通过增加 QOS 参数,如抖动、延迟等,用更先进的算法和更真实的观察空间来改进这一点。

密码

上述实验的代码已经被签入 github(https://github.com/amitnilams/sdwan-gymhttps://github.com/amitnilams/sdwan-gym-stat、https://github.com/amitnilams/sdwan-rl)

参考

1)我之前的文章— Open-AI gym for SD-WAN 链接选择

2 ) 玩深度强化学习的雅达利由 Mnih et。铝

3) 深度强化学习的决斗网络架构王等。

4) open-ai 基线

5) DQN 实施由丹尼·布里兹

6)深度 Q 由 Keon 实现

7) 翻筋斗格雷格 实现。

8)Richard s . Sutton 等人提出的利用函数逼近进行强化学习的策略梯度方法。艾尔。

9) 深度强化学习的异步方法Mnih et。艾尔。

10) 萨顿和巴尔托著《强化学习:导论》第二版

11)David Silver 等人的利用双 Q 学习的深度强化学习。艾尔。

在随机森林中寻找能量

原文:https://towardsdatascience.com/searching-for-energy-in-a-random-forest-1eab9be15d53?source=collection_archive---------2-----------------------

我们需要覆盖多少地球表面的太阳能电池板来满足整个人口的能源需求?不多,根据土地艺术发电机倡议组织,他们在 2009 年计算出我们需要在世界上大约 496,805 平方公里的土地上铺设太阳能电池板来满足人类 2030 年的能源需求。这听起来很多,但事实上只有 0.35%的土地没有被水覆盖。

这太不可思议了,看起来是一个完全可以实现的目标,尽管这有点简单化。我们不能只把那些面板放在一个地方,很多地区可能更适合不同的清洁能源。事实上,在一次更新中,原始文章指出需要考虑可再生能源生产的多样性和分布。然而,这种“容易”的想法是诱人的,100%可再生能源的想法正在被一些组织如解决方案项目认真推动。

那么,我们如何着手弄清楚哪种类型的可再生能源应该去哪里呢?这实际上是一个极其复杂的决定,需要我们考虑地球物理因素,包括天气、气候、土地类型、海拔、坡度,以及人口密度、基础设施、电网特征、能源市场等人为因素。如果你是决定在哪里建下一个发电厂的人,那要考虑很多。因此,围绕这个问题有一个完整的行业,它依赖于大量的人类专业知识。

对我来说,这似乎是一个绝佳的机会,看看我们是否能够利用机器学习做出更好、更快的决策。有成千上万个现有的可再生能源网站,我们可以训练计算机从中学习。为什么不尝试教一种算法来理解每个地点的什么特征使这些地点成为建设可再生能源的好地方,将该公式应用于我们剩余的可用土地,并查看全球最佳的能源生产地点在哪里?

在华盛顿大学的 2016 年地理黑客周上,我提出了这个想法,并成立了一个项目来测试它。在几天黑客攻击的时间限制内,目标是获取美国各地带有少量地理特征的可再生能源站点的位置,并使用这些信息来训练计算机,以决定应该在整个国家放置哪些类型的可再生能源。为了让事情变得简单一点,我们把自己限制在只关注大规模的太阳能、风能和地热发电。

我们选择的机器学习方法是随机森林分类器。分类器是一种学习预测类别(从有限的选项中选择)的算法。随机森林技术通过构建一系列决策树来实现这一点。在我们的例子中,我们告诉它每个有清洁能源的地方的特点,以及那里有什么类型的可再生能源。然后,它会生成多个不同的决策树,这些决策树都可以用来计算哪些特征会导致每一个可更新。这是我们的森林。当我们给它一个未知类别的新数据点(在我们的例子中,是关于我们想要知道最佳可再生能源适用性的特定位置的数据)时,它会遍历所有决策树,并从他们的选择中获得多数票,以决定哪种可再生能源最适合该位置。

可再生能源所在地的数据来自EIA,我们收集了海拔、坡度、坡向、太阳辐照度、风速、温度梯度和人口数据。我们为地理空间机器学习问题选择的平台是谷歌地球引擎。它利用谷歌的硬件资源以非常高的速度完成巨大的地理空间计算,并内置了机器学习功能。我们部署了他们的随机森林算法,来制作一张地图,以令人难以置信的 4 公里分辨率,在全国范围内预测风能、太阳能和地热能生产的适宜性。我们也将某些地点设为禁区,例如城市、森林和水体。

最终的地图显示了现有的两个可再生能源网站,以及整个美国在 4 公里网格上的每个点上从三个可再生能源中选择最佳的颜色编码。即使只是考虑几个变量,我们也能看到有意义的东西;中西部大多被归类为最适合风能的地区,而南部有更多适合太阳能的地区,该算法预测地热的最佳地点集中在山脉和火山周围。从放大的地图部分,我们还可以看到,在局部水平上,为每种类型的能源生产选择的区域之间有高分辨率的区别。

这只是一个原型黑客,但它仍然很酷,看看如何可能确定整个国家的可再生能源的适用性,在高空间分辨率的几个点击。它非常符合能够为全世界提出可再生能源计划的愿景,同时赋予决策者在地方层面制定优化能源战略的权力。在现实世界中,情况肯定更复杂。我们没有包括许多相关的功能,没有考虑现有可再生能源站点的建设时间,也没有考虑复杂的因素,如经济、地方政策或电力分配。

至于分类机器学习方法是否是这个问题的最佳方法,我可以想到一些优点和局限性。首先,任何机器学习技术都是从过去关于在哪里建电厂的决策中建立理解。一方面,这是好的,因为我们在没有明确定义它们的情况下,自动将人类的专业知识和关注点构建到我们的模型中,但是不能保证以前的决策适用于未来的场景。现代电网、政治、能源市场和可再生技术本身都处于进化状态,但也许通过精心选择的特征,这些都可以得到解释。

还有一个问题是,分类模型的最终结果只能告诉我们哪种可再生能源最适合某个地方。它没有告诉我们不同类型在每个地点的比较,或者一个地点是否比另一个地点更适合某种类型。仅仅知道你的国家哪里比其他可再生能源更适合太阳能,而不知道哪里是建造太阳能发电厂的最佳地点,这并没有多大用处。我们简要地看了一下实现这一点的回归算法(产生一个数量,而不是一个简单的选择),设想创建一个相对场地适宜性的热图,进一步探索肯定会很有趣。另一种选择可能是使用人类专家定义的公式,并应用全局优化方法来生成相对场地适宜性图。

这个项目在未来肯定会有一些有趣的方向,希望我能找到时间回到这个话题上来!关于 hack week 项目的更多技术细节、数据和代码可以在它的 GitHub 库上看到。非常感谢我的团队成员,劳拉·辛克曼山姆·胡珀茱莉亚·金瑞秋·怀特同意继续这个想法,并感谢凯瑟琳·库恩的所有协助。也感谢 Anthony Arendt 和 GeoHackWeek 团队的其他成员举办了一场精彩的活动!

相关链接

这里有一个其他可再生能源测绘项目和组织的列表,它们是这个项目的灵感来源。

  • 可再生能源忍者——模拟全球风能和太阳能输出。
  • 谷歌的项目天窗——告诉你你的屋顶有多适合太阳能。
  • 爱荷华州风力涡轮机场地适用性的机器学习——一篇学术论文证明我不是唯一一个愚蠢到认为这可能是一个好主意的人。
  • NREL 可再生能源潜力 —报道美国可再生能源的技术和经济潜力。

这篇文章的副本也可以在georgerichardon.net上找到

寻找为《纽约时报》撰写专栏的抵抗组织成员

原文:https://towardsdatascience.com/searching-for-the-resistance-member-who-penned-the-new-york-times-op-ed-a9566ca09a80?source=collection_archive---------10-----------------------

自然语言处理能预测作者的真实身份吗?

周三下午,《纽约时报》发表了一篇令人震惊的观点文章,详细描述了一些白宫顾问为遏制特朗普总统最鲁莽的倾向而进行的秘密抵抗,这是这家著名(或者我敢说,失败)报纸发表匿名评论的罕见例子。该专栏的作者被描述为一名未透露姓名的“特朗普政府高级官员”,他以匿名的名义撰写,可能是为了避免作者立即被解雇,但也是为了让读者能够专注于故事的重要信息,而不是信使。几分钟内,这篇文章就像病毒一样传播开来,因为现在是 2018 年,Twitter 和全国各地的政治学者立即开始搜索这位作者。大量的理论迅速充斥网络,几个小时内多家博彩公司发布了的投注赔率。当互联网侦探在一些暗示作者身份的奇怪短语上划区域时(对于任何声称在阅读文章之前知道‘lodestar’是什么意思的人来说——Google Trends 保留收据),我在过去 3 个月里完全沉浸在数据科学中,立即想到是否有可能使用自然语言处理来揭示作者的身份。这是我对破案的初步尝试。

Trump criticizing the “amomynous” author

假设

首先,我需要对这个列做一些假设。虽然 NYT 的一条推文最初称作者为“他”(一名时报发言人后来澄清这是一个错误),但我忽略了作者的性别被如此无伤大雅地暴露出来的想法。相反,我认为他们被称为男性,因为政府中没有高级别的女性,如果作者被揭露为女性,公众很容易发现他们的身份。我还必须假设观点文章是用作者自己的声音写的,而不是由演讲稿撰写人精心制作的,或者经过大量编辑,因此不可能符合作者的独特风格。【Axios 公司的张克帆·斯旺之前的一份报告称,一名白宫官员详细描述了他们如何“注意其他员工的习惯用语,并将其用在[他们的]背景引语中”,以掩盖他们的踪迹。

These people definitely did not write it

我最后的假设是,一名政府官员的公开否认并不排除那个人写了这篇文章——知道被曝光的可怕后果,对他们的参与撒谎是他们的最大利益。没有这些假设,就不可能准确地预测作者,我必须强调,目前的这项工作是一项非常不精确的研究。

一旦我的假设成立,我必须得到一份潜在作者的名单。不幸的是,对我自己和这个国家来说,有一个长得惊人的潜在候选人名单,涵盖了行政部门的所有领域。

出于时间的考虑,我把名单缩小到了三个人,每个人都有可能成为候选人,他们都有公开的演讲和在线发表的专栏文章。我最初选择关注的三个人是副总统迈克·彭斯、驻联合国妮基·黑利大使和现任经济顾问委员会主席凯文·哈塞特。Pence 被包括在内是因为“lodestar”这个词的奇怪用法,在文章发布几分钟后,Twitter 用户 @danbl00m 发现它是副总统(显然不是其他人)常用的词之一。这篇文章对外交政策失误和经济及放松管制的成功进行了深入的审视,因此我觉得有必要将各个学科的官员都包括进来。我选择了哈利和哈塞特,因为在我看来,他们都是高级官员,在很大程度上避开了目前笼罩白宫的真人秀聚光灯。

余弦相似性

一旦我有了我想看的三个候选人的名单,我就在网上搜寻这些人的观点、文章和演讲。我使用的第一种方法是余弦相似度,它使用两个矢量化语料库之间的余弦角来衡量相似度,输出越接近 1 被视为越相似。使用术语频率-逆文档频率(TF-IDF)将每个语料库转换为向量,我能够计算潜在作者和匿名抵抗成员之间的相似性。

好消息是每个作者的余弦相似度接近 1,这意味着很好的匹配。坏消息是,这三个数字被如此紧密地组合在一起,以至于无法确定哪个(如果有的话)与作者最相似。我推断,三个余弦相似性之间缺乏变化是由于一个小的目标集,在这种情况下,只有 881 个词写在专栏中。

TF-IDF 降维

我尝试的下一个方法是使用 t-SNE 将每个候选人的 TF-IDF 向量矩阵的维度降低到三维,然后绘制每个候选人的图表,以查看是否有任何候选人比其他人更接近专栏作家。令我沮丧的是,这 4 个点就像我能想象的那样平均分布,对于作者可能是谁没有留下任何洞察力。

Useless 3D Scatter Plot

作者归属

我的最后一次尝试使用了尼尔·雅戈开发的作者归属代码,它分析了四个不同的特征来预测哪个作者最有可能写了一篇文章。这四个特征分别是:词汇特征,如每句话的平均字数和作者词汇量的大小;**标点特征,**包括每个句子中逗号、分号和冒号的平均数量;**单词包特征,表示特定单词在文档中出现的频率;以及句法特征,**将每个词归类到某个词类(名词、动词等。).在大多数 NLP 实例中,通常会删除在所有文档中频繁出现的单词,如“the”和“are ”;然而,作者归属的操作不同于正常的文本分类,并且有一种信念,即作者以一种独特但一致的方式使用这些常用词。

###### code to create lexical and punctuation feature vectors ######for i, text in enumerate(authors):

    tokens = nltk.word_tokenize(text.lower())
    words = word_tokenizer.tokenize(text.lower())
    sentences = sentence_tokenizer.tokenize(text)
    vocab = set(words)
    words_per_sentence = np.array([len(word_tokenizer.tokenize(s))
                                   for s in sentences])

    # Average number of words per sentence
    fvs_lexical[i, 0] = words_per_sentence.mean()
    # Sentence length variation
    fvs_lexical[i, 1] = words_per_sentence.std()
    # Lexical diversity
    fvs_lexical[i, 2] = len(vocab) / float(len(words))

    # Commas per sentence
    fvs_punct[i, 0] = tokens.count(‘,’) / float(len(sentences))
    # Semicolons per sentence
    fvs_punct[i, 1] = tokens.count(‘;’) / float(len(sentences))
    # Colons per sentence
    fvs_punct[i, 2] = tokens.count(‘:’) / float(len(sentences)) 

在创建了特征向量之后,我继续在特征空间中寻找三个聚类,希望至少一些(如果不是所有的)专栏特征将与候选人的那些特征共享一个聚类。我决定用三个集群来测试它,假设三个已知作者中的每一个都将他们的功能作为独特集群的一部分,而论坛版功能将属于其中之一。

author_files=[pence,hassett,haley,oped]**code:**
fvs_list = [fvs_lexical,fvs_punct,fvs_bow,fvs_syntax][PredictAuthors(fvs).labels_ for fvs in fvs_list]**output:**
[array([0, 0, 2, 1], dtype=int32),
 array([2, 1, 0, 0], dtype=int32),
 array([0, 1, 2, 2], dtype=int32),
 array([0, 2, 0, 1], dtype=int32)] 

Representation of which cluster each feature belongs to

数组中的每一行代表一个不同的特性,而列代表四个不同的作者(最后一列是专栏)。数字表示每个要素属于哪个聚类。同样,结果是不确定的,尽管它们比前两种方法提供了更多的信息。该论坛版的标点符号和单词袋功能与妮基·黑利的相同功能共享一个群集,而其其他功能都不属于与其他两位作者的匹配功能相同的群集。这是朝着正确方向迈出的一步,但仍然没有给出明确的答案。

在接下来的几天里,我希望收集更多政府成员的发言和文章,看看是否有官员引人注目。这个最初的尝试给了我一个坚实的感觉,我将需要使用的技术,以作出准确的预测。我期待改进这个模型,并对作者的真实身份给出一个有把握的猜测。

**更新:**维基解密将搜索范围缩小到一名年长的保守男性。

西雅图非常适合数据科学家。原因如下!

原文:https://towardsdatascience.com/seattle-is-perfect-for-data-scientists-heres-why-2a8e3bb4bdd3?source=collection_archive---------14-----------------------

Photo by Zhifei Zhou on Unsplash

最近,我有机会在西雅图与我工作的数据科学学院 Metis 进行了为期六个月的教学轮换。我小时候的最初记忆是和家人一起探索市中心和华盛顿湖;在东海岸住了多年后,我欣然接受了在翡翠城多待些时间的机会。现在,我有一些时间来反思我在西雅图的经历,我开始意识到这个城市是有抱负的数据科学家可以称之为家的最佳地方之一。

第一:西雅图是美国发展最快的城市。一个主要原因是强劲的就业市场,尤其是在科技领域。像亚马逊和 Zillow 这样的公司正以贪婪的速度增长,为有 STEM 头脑的学生和工人带来了有利可图的职业前景和高流动性。事实上,Indeed.com 对下一个“硅谷”的搜索发现西雅图是科技中心,科技职位空缺增速最快

西雅图特别需要数据科学家,因为这个城市面临着美国最大的数据科学家短缺之一推动数据科学家军备竞赛的因素之一是需要以下领域的专家:

尽管这个城市及其经济飞速发展,我还是很高兴地发现西雅图并没有失去它的魅力。它提供了纽约市、芝加哥或旧金山的大部分能量,同时让人感到亲切和平易近人。这里的新数据科学家可以很快感觉自己是一个真实社区的一部分;在网络活动中看到熟悉的面孔意味着联系和插上电源并不困难!

这种平衡感延伸到在西雅图雇用数据科学家的各种公司,这些公司形成了初创公司、家喻户晓的组织的卫星办公室以及将西雅图作为家的大型科技公司的良好组合。每个人都知道该地区的大公司,如微软和亚马逊。在初创企业方面,西雅图的前沿城市精神依然存在,因为来自大公司的团队已经脱离出来,成立了自己的组织。即使是总部不在西雅图的科技企业集团也不能忽视西雅图的人才库,因此脸书和谷歌等公司已经在市中心设立了办事处,以确保他们不会错过这个机会。

有人可能会说,那些在西雅图设立卫星办公室的组织只是在追随员工的流失。事实上,在过去的一年中,大多数 LinkedIn 会员从旧金山湾区搬到的美国城市已经有了定论。顶级城市?你猜对了。口袋里有更多的钱也没有坏处,因为西雅图数据科学家的平均工资(根据生活成本调整后)超过了旧金山和纽约。

西雅图的另一个好处是该地区丰富的学术成就历史。顶级教授和从业者在西雅图生活和工作,他们中的许多人在西雅图的大小公司兼职,横跨学术界和商界。这座城市的整体氛围有利于深入思考和学术研究;下雨的天气往往会这样!

当我们谈到自然的主题时,我必须提到美丽的海滨和各个方向的山脉景观(奥林匹克、瀑布、雷尼尔),以及城市的其他自然特征。徒步旅行和滑雪的机会比比皆是,西雅图以其名副其实的绿色城市而闻名(色彩、环保意识和休闲)。

在过去的两年里,我在亚特兰大、芝加哥、西雅图和旧金山(我目前在 Metis 的 SoMA 校区任教)生活和工作,因此我可以谈谈每个地区的独特之处。如果你能适应灰色的天空,你会发现西雅图是一个称之为家的好地方,有丰富的身心锻炼活动,从聚会和黑客马拉松到皮划艇和山地自行车。作为一名数据科学家,西雅图是最值得投资的市场,具有巨大的潜在上升空间和强劲的发展势头!

有了所有这些有利条件,越来越多有抱负的数据科学家开始把西雅图当成自己的家也就不足为奇了!

你住在西雅图还是最近去过?同意还是不同意?

HBR 分析的秘密段落

原文:https://towardsdatascience.com/secret-paragraphs-from-hbrs-analytics-ddd2ead761d4?source=collection_archive---------6-----------------------

我们来谈谈混合角色,研究的本质,Bat 信号,数据江湖骗子,牛逼的分析师!

我本周的博文在 HBR 发表,所以如果你错过了那篇,你可以在:

优秀的数据分析师做什么——为什么每个组织都需要他们

在发送之前,我尽了最大的努力来缩短篇幅,所以如果你在读完的文章后还觉得不够,这里有一些秘密段落和 B 面供你娱乐。尽情享受吧!

购买奖品

小心你崇拜的技能,因为不明智的选择会带来毁灭性的影响。除了管理不善的团队和不必要的雇佣,你会看到真正的英雄辞职或自我再教育,以适应你今天的动机。这种现象的一个主要例子是在分析。

买家当心

不幸的是,真正的分析师相对较少——买家请注意:有许多数据骗子冒充数据科学家或数据分析师。这些人兜售胡说八道,以无纪律的方式超越数据,以基于一厢情愿的想法“支持”决策。如果你的道德标准松懈,也许你会把这些蛇油推销员留在身边,把他们安置在你生意的营销黑艺术部分。就我个人而言,我宁愿不要。

统计学家的真正本质

大多数人没有意识到的是统计学家本质上是认识论者。因为没有魔法能把不确定性变成确定性,所以他们的角色不是产生真相,而是把合意的假设和可用的信息进行合理的整合。

毫不奇怪,许多统计学家对那些学习方程式却没有吸收任何哲学的“暴发户”反应尖刻。如果与统计学家打交道似乎令人疲惫不堪,这里有一个快速解决办法:不要得出任何超出你的数据的结论,你就不需要他们的服务了。(说起来容易做起来难,对吧?尤其是如果你想做一个重要的发射决定。)

草率的胡说八道还是一流的故事?

为了避免浪费时间,分析师应该把他们想说的故事摆出来,从几个角度戳穿它,并进行后续调查,看看它是否站得住脚,然后再提交给决策者。如果一个决策者因为一个鼓舞人心的故事而面临被迫采取重要行动的危险,那么就是一个蝙蝠信号,让的统计学家突然介入,并根据决策者愿意接受的假设和他们的风险偏好来检查(当然是新数据)该行动是否是一个明智的选择。

分析师和统计学家的混合体

对于坚持事实的分析师来说,没有错,只有慢。将统计专业知识添加到“正确做事”中,在一个重要的方面错过了要点,特别是因为在探索性数据分析和统计严谨性之间有一个非常重要的过滤器:决策者。负有决策责任的人必须签署追求分析师洞察力的业务影响,这值得专家花费大量时间。除非分析师和统计学家的混合体也是一个熟练的决策者和商业领袖,否则他们的技能组合会形成一个中间有裂缝的三明治。

然而,弥合这一差距的分析师,其价值不亚于黄金。珍惜他们!

分析师和 ML 专家的混合体

分析师加速机器学习项目,因此双重技能非常有用。不幸的是,由于分析和 ML 工程在编码风格和方法上的差异,很难在一个人身上看到顶尖的专业知识(更难得的是,这个人在需要的时候表现得缓慢而富有哲理,这就是为什么真正的全栈数据科学家是一种罕见的野兽)。

低估分析师的危险

初学者没有意识到的是,这项工作要求顶级分析师比其他任何一种应用类型都更好地掌握数据科学的数学知识。除非任务足够复杂,需要发明一种新的假设检验或算法(T2 的研究人员 T3 的工作),统计学家和 T4 的 ML 专家 T5 可以依靠检查现成的软件包和测试是否适合这项工作,但他们通常可以跳过不得不面对方程本身。

例如,统计学家可能会忘记一个t-测试的 p 值的方程式,因为他们是通过点击软件包上的 run 得到的,但他们永远不会忘记如何以及何时使用它,以及对结果的正确哲学解释。另一方面,分析师不打算解读。他们在寻找一个血淋淋的,巨大的,多维数据集的形状。通过了解 p 值方程分割数据集的方式,他们可以形成原始数据集中的模式的反向视图,以产生他们看到的数字。如果不懂得数学,你就不会有这种观点。然而,与统计学家不同的是,他们不关心数据的测试是否正确。他们关心的是 t 检验能让他们对当前数据集中发生的事情有一个有用的了解。区别很微妙,但很重要。统计学家处理数据之外的事情,而分析师坚持数据之内的事情。在 peak excellence,两人都有深厚的数学功底,他们经常使用相同的方程式,但他们的工作完全不同。

类似地,分析师经常使用机器学习算法来分割他们的数据,识别引人注目的分组,并检查异常情况。由于他们的目标不是性能而是灵感,他们的方法是不同的,在 ML 工程师看来可能显得草率。同样,这是在不同的工作中使用相同的工具。

用一个类比来总结一下:别针被外科医生、裁缝和办公室工作人员使用。这并不意味着工作是相同的,甚至是可比的,鼓励你所有的裁缝和办公室职员学习外科以在职业生涯中取得进步是危险的。

研究人员的护理和喂养

如果这听起来还不够糟糕的话,许多领导者试图聘请博士,并过分强调 研究——而不是应用版本的统计学家ML 工程师 …而没有一个有价值、重要且已知不可能用现有算法解决的问题。

只有在你投资于一个研究部门,并且不打算询问你的研究人员最近为你做了什么的情况下,这才是好的。为研究而研究是一项高风险投资,很少有公司能够承担得起,因为从中得不到任何价值是一种非常现实的可能性。

只有当你有合适的问题让他们解决时,研究人员才属于研究部门之外——他们的技能是从零开始创造新的算法和测试,而现成的版本并不存在——否则他们将经历一个悲惨的西西弗螺旋(这将完全是你的错,而不是他们的错)。研究人员通常会花上十年以上的时间进行培训,这至少值得尊重,因为他们不会从事完全不相关的任务。

因此,在你的分析师帮助你确定了一个有价值的项目,并且试图用应用数据科学家完成它的努力已经失败之后,才是雇佣他们进行应用项目的合适时机。当你让职业发明家上场的时候。

VICKI JAURON, BABYLON AND BEYOND PHOTOGRAPHY/GETTY IMAGES image used with the HBR article. My favorite interpretation is that the human is a business leader chasing away flocks of analysts while trying to catch the trendy job titles.

感谢阅读!YouTube AI 课程怎么样?

如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:

Enjoy the entire course playlist here: bit.ly/machinefriend

喜欢作者?与凯西·科兹尔科夫联系

让我们做朋友吧!你可以在 TwitterYouTubeSubstackLinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用表格取得联系。

深度学习之美背后的秘密酱:激活函数初学者指南

原文:https://towardsdatascience.com/secret-sauce-behind-the-beauty-of-deep-learning-beginners-guide-to-activation-functions-a8e23a57d046?source=collection_archive---------1-----------------------

激活功能是获取输入信号并将其转换为输出信号的功能。激活函数将非线性引入网络,这就是为什么我们称之为非线性。神经网络是通用函数逼近器,深度神经网络使用反向传播来训练,反向传播需要可微分的激活函数。反向传播在这个函数上使用梯度下降来更新网络权重。理解激活函数非常重要,因为它们在深度神经网络的质量中起着至关重要的作用。在这篇文章中,我列出并描述了不同的激活功能。

  • 恒等式或线性激活函数— 恒等式或线性激活函数是所有激活函数中最简单的。它对你的数据进行恒等运算,输出数据与输入数据成正比。线性激活函数的问题是,它的导数是一个常数,它的梯度也是一个常数,下降将是一个常数梯度。

Equation for Identity or Linear activation function

范围:(-∞,+∞)

例如:f(2) = 2 或 f(-4) = -4

  • Heaviside(二进制步长,0 或 1,高或低)步长函数通常只在单层感知器中有用,这是一种早期的神经网络,可用于输入数据可线性分离的情况下的分类。这些函数对于二元分类任务非常有用。如果输入和高于某个阈值,则输出为某个值 A1,如果输入和低于某个阈值,则输出为 A0。感知器使用的值是 A1 = 1 和 A0 = 0

Equation for Heaveside/Binary Step Function (0 or 1, high or low)

范围:{0 或 1 }或 1

例子:f(2) = 1,f(-4) = 0,f(0) = 0,f(1) = 1

Source — https://en.wikipedia.org/wiki/Heaviside_step_function

  • Sigmoid 或逻辑激活函数(软步骤)- 主要用于二元分类问题(即输出范围为 0-1 的值)。它有渐变消失的问题。由于输入(X)在输出(Y)中引起非常小的变化,网络在某些时期后拒绝学习或学习非常慢。它是一个广泛用于分类问题的激活函数,但最近。这个函数更容易使后面的层饱和,使得训练更加困难。计算 Sigmoid 函数的导数非常容易。

对于神经网络中的反向传播过程,你的误差将在每一层被压缩(至少)四分之一。所以,你的关系网越深,从数据中获得的知识就会越多。我们从输出层获得的一些“大”错误可能不会对相对较浅的层中的神经元的突触权重产生太大影响(“浅”意味着它接近输入层)——来源https://github . com/kul bear/deep-learning-nano-foundation/wiki/ReLU-and-soft max-Activation-Functions

Sigmoid or Logistic activation function

Derivative of the sigmoid function

范围:(0,1)

例如:f(4) = 0.982,f(-3) = 0.0474,f(-5) = 0.0067

Source — https://en.wikipedia.org/wiki/Logistic_function

Source — https://github.com/Kulbear/deep-learning-nano-foundation/wiki/ReLU-and-Softmax-Activation-Functions

  • **双曲正切(TanH)——**它看起来像一个缩放的 sigmoid 函数。数据以零为中心,所以导数会更高。Tanh 比 sigmoid 和 logistic 激活函数收敛更快

Equation for Hyperbolic Tangent(TanH) activation function

范围:(-1,1)

示例:tanh(2) = 0.9640,tanh(-0.567) = -0.5131,tanh(0) = 0

Source — https://commons.wikimedia.org/wiki/File:Hyperbolic_Tangent.svg

  • **整流线性单元(ReLU)——**训练速度比 tanh 快 6 倍。当输入值小于零时,输出值将为零。如果输入大于或等于零,则输出等于输入。当输入值为正值时,导数为 1,因此不会出现在 sigmoid 函数反向传播误差的情况下出现的压缩效应。

Equation for Rectified Linear Unit(ReLU) activation function

范围:[0,x]

例如:f(-5) = 0,f(0) = 0 & f(5) = 5

Source — https://en.wikipedia.org/wiki/Rectifier_(neural_networks)

From Andrej Karpathy’s CS231n course

  • 泄漏整流线性单元(泄漏 ReLU) — 当单元不工作时,泄漏 ReLU 允许一个小的非零梯度。0.01 是小的非零梯度 qhere。

Equation for Leaky Rectified Linear Unit (Leaky ReLU) activation function

范围:(-∞,+∞)

Leaky Rectified Linear Unit(Leaky ReLU)

  • **参数校正线性单元(PReLU)——**它使泄漏系数成为一个参数,该参数与其他神经网络参数一起学习。α(α)是这里的泄漏系数。

对于α ≤ 1 f(x) = max(x,αx)

范围:(-∞,+∞)

Equation for Parametric Rectified Linear Unit(PReLU)

  • 随机泄漏整流线性单元(RReLU)

范围:(-∞,+∞)

Randomized Leaky Rectified Linear Unit(RReLU)

  • **指数线性单元(ELU)——**指数线性单元试图使平均激活接近零,从而加快学习速度。研究表明,ELUs 比 ReLUs 具有更高的分类精度。这里,α是一个超参数,需要调整,约束条件是α ≥ 0(零)。

范围:(-α,+∞)

Exponential Linear Unit (ELU)

  • 比例指数线性单位(SELU)

范围:(-λα,+∞)

Scaled Exponential Linear Unit(SELU)

  • S 形整流线性激活单元(SReLU)

范围:(-∞,+∞)

S-shaped Rectified Linear Activation Unit

  • 自适应分段线性(APL)

范围:(-∞,+∞)

  • **soft plus—**soft plus 函数的导数是逻辑函数。ReLU 和 Softplus 在很大程度上是相似的,除了在 0(零)附近,softplus 非常平滑且可微分。计算 ReLU 及其导数比使用 log(.)和 exp(。)的提法。

范围:(0,∞)

Softplus

softplus 函数的导数是逻辑函数。

Derivative of the softplus function

Source — https://en.wikipedia.org/wiki/Rectifier_(neural_networks)

  • 本特的身份

范围:(-∞,+∞)

Bent Identity

  • Softmax- Softmax 函数将原始值转换成后验概率。这提供了一定程度的确定性。它将每个单元的输出压缩到 0 和 1 之间,就像一个 sigmoid 函数一样。但是它也划分每个输出,使得输出的总和等于 1。

Equation for Softmax function

softmax 函数的输出相当于分类概率分布,它告诉您任何类为真的概率

结论:ReLU 及其变体应优先于乙状结肠或 tanh 激活功能。以及 ReLUs 训练起来更快。如果 ReLU 导致神经元死亡,使用 Leaky ReLUs 或它的其他变体。Sigmoid 和 tanh 遭受消失梯度问题,不应用于隐藏层。ReLUs 最适合隐藏层。应该使用易于微分和易于训练的激活函数。

参考资料:

  1. https://en.wikipedia.org/wiki/Activation_function
  2. https://github . com/kul bear/deep-learning-nano-foundation/wiki/ReLU-and-soft max-Activation-Functions
  3. https://en . Wikipedia . org/wiki/Rectifier _(neural _ networks)

关于

Mate Labs我们已经构建了 Mateverse ,一个全自动的机器学习平台,在这里你可以构建定制的 ML 模型,比 快 10 倍,而无需编写一行代码。我们利用专有技术、复杂管道、大数据支持、自动化数据预处理(使用 ML 模型的缺失值插补、异常值检测和格式化)、自动化超参数优化和等等,让分析师和数据科学家的工作变得更加轻松。

为了帮助您的企业采用机器学习,而不会浪费您的团队在数据清理和创建有效数据模型方面的时间,请填写类型表 此处 ,我们将与您联系。

让我们携起手来。

Twitter 、LinkedIn 上与我们分享您的想法

如果你有新的建议,请告诉我们。我们的耳朵和眼睛总是为真正令人兴奋的事情而张开。

之前我们分享过。

  1. 如何在 5 分钟内训练出一个机器学习模型。
  2. 公共数据集:用这些在 Mateverse 上训练机器学习模型。
  3. Mateverse 公测公告。
  4. 为什么我们需要机器学习民主化?
  5. 一个非常清晰的解释全有线电视新闻网的实施。这些研究人员如何尝试一些非常规的东西来实现更小但更好的图像识别。
  6. 我们的愿景。关于人工智能大家都没告诉你的事情

Vinho Verde 的秘密

原文:https://towardsdatascience.com/secrets-of-vinho-verde-36a248193d83?source=collection_archive---------4-----------------------

本周的挑战是利用研究的力量来确定哪些 T2 因素促成了一杯上好的红酒。

至少有 3 名葡萄酒专家对 1599 款葡萄酒进行了测试,并给出了从 0 (糟糕)到 10 (优秀)的质量等级。

测量了 11 个因子:固定酸度*,柠檬酸,残糖,氯化物,游离和总二氧化硫,密度,pH,硫酸盐酒精*。

Example of Normal (density) and Skewed (Free SO2) distributions.

单变量分析

查看每个因子并检查空值异常值 ( 异常高或低条目)并做出相应的决策。

分布*(即密度)越“正常”,比较结果越好。对于具有偏斜分布的因子(即游离 SO2)* ,我测试了 log10 或平方根转换是否会改善这种情况,并相应地做出了决定。

双变量分析

现在使用 GGPairs 来寻找因素之间的相关性

显著的 Pearson 的 R 结果以黄色(0.3-0.5 的小意思)或橙色(0.5-0.7 的中等意思)突出显示。我还在流程图上追踪了这个。

这导致了 3 个观察结果:

1.游离 SO2 和总 SO2 高度相关,但与其他变量不相关。
2。残糖与密度有很小的相关性,但与其他无关。
**3。三个关键因素:**酒精、挥发酸、硫酸盐。

关键因素 1:酒精

酒精含量越高,似乎意味着葡萄酒质量越好。

没什么10<为的质量。
没事
没事> 12** 为降低质量。多数中间范围 (5/6) = 10。**

高于质量= 5 有一个明显的积极趋势。

其他变量呢?

随着密度的降低酒精的含量会略微增加(这并不奇怪,因为它们是相互关联的)。

固定酸度较低而 pH 较高时,这种趋势更加明显。

统计结果还表明,这种关系可能是显著的。

关键因素 2:硫酸盐

图表显示硫酸盐品质之间存在轻微的正相关关系,即品质越高的葡萄酒硫酸盐含量越高。

然而,统计结果并不支持这一点,所以我们对这种关系的信心要少得多。

关键因素 3:挥发性酸度

这里的图表显示了明显的负面趋势。高质量的葡萄酒往往具有较低的挥发酸含量。因为高挥发性酸度会导致酸味,所以这并不奇怪。

不幸的是,统计结果并不确定,所以我们也不能确定这两者之间的相关性。

结论

结果表明,以下因素可能有助于高品质的葡萄酒:

  • 酒精水平(超过 10)
  • 密度(低于 0.998)
  • ●固定酸度**(低于 9)**
  • ph 值更高(超过 3)

它们还表明了到之间的可能联系

  • 挥发酸度**(低于 0.75)**
  • 更高的硫酸盐**(超过 0.5)**

但是对于这个数据集,它看起来并不重要。理想的后续行动是对随后几年进行匹配分析。该数据集记录于 2009 年。如果在过去的六年里收集了类似的数据,那将使我们得出更可靠、更有力的结论。

安全数据市场和分布式深度学习

原文:https://towardsdatascience.com/secure-data-marketplace-and-distributed-deep-learning-76c2c7505ba?source=collection_archive---------19-----------------------

单个项目中的人工智能和区块链听起来可能非常自大,但这不仅仅是营销废话,所以不要太早逃跑。深度学习可以做很酷的事情,但它通常需要大量的数据。此外,在许多情况下,这些数据是敏感的,人们不想分享这些数据。然而,有一种方法可以根据来自许多矿工的数据训练神经网络,同时保持其私密性。每个矿工将训练模型,但不能做出任何有意义的预测。模型的所有者将能够使用它,但不会获得任何数据。双赢。OpenMined 旨在为此开发开源工具包。

Mine, Syft and Sonar are the names of corresponding services

通用组件:

联合深度学习-计算每个用户的梯度并在通用模型中总结它们的方法。事实上它只是分布式随机梯度下降。它既有很好的理论属性,也在一些大型产品(如 Android)中得到了验证。

同态加密保护这些梯度到主服务器的安全过渡。he 的主要特点是可以对加密数据进行数学运算,解密后效果相同。由于计算成本高,它没有被广泛使用,但在过去几年中,一些有效的整数和浮点数类型得到了发展。

通过基于区块链的智能合约,所有的梯度和金融交易对矿商和公司来说都将是透明和安全的。

循序渐进

  1. AI Inc .创建了一个模型,并将其发布给矿工
  2. Miner 下载该模型,并根据他的数据计算该模型的梯度
  3. Miner 对渐变进行编码,并发送给 AI Inc .
  4. AI Inc .评估这些梯度如何改进验证集上的模型
  5. AI Inc .根据矿工的坡度值按比例支付报酬
  6. 重复 2-5 次,直到模型达到所需的精度

很酷,不是吗?OpenMined 团队将不得不应对许多挑战,如培训速度、评估质量、支付策略、安全性等。总之,整个想法看起来很有希望。你可以在本帖中找到加密分布式 DL 的技术细节。

公司可能会用它来训练医疗记录、个人资料、驾驶模式等敏感数据的模型。或者,他们可以合作创建一个通用模型,而不互相泄露他们的数据。或者,你可以挖掘和出售数据来获利。这些工具肯定会有很多用例。

如果您对更多细节感兴趣,请查看他们的 github、推介资料中的 Docs 文件夹以及公开会议的录音:

最初发表于 认知混乱

人工智能和机器学习中的安全和隐私考虑—第 2 部分:新资产

原文:https://towardsdatascience.com/security-and-privacy-considerations-in-artificial-intelligence-machine-learning-part-2-the-new-39748342a5a?source=collection_archive---------7-----------------------

Where are the assets that need to be protected?

注:这是“人工智能中的安全和隐私&机器学习”系列文章的第二部分。以下是所有文章的链接(到目前为止):

上一篇文章中,我们从“传统”网络安全的角度(没有深入到 AI & ML 工作流的具体细节)看了从端到端考虑 AI & ML 生态系统和工作流时出现的关键挑战。在这一部分中,我们将开始放大 AI & ML 组件——从探索 AI & ML 带来的有趣的新资产开始。这一练习将帮助我们认识这些资产,使我们在执行威胁建模和为端到端系统选择安全技术时,能够将它们与其他关键信息资产一起对待。识别资产后,将更容易考虑攻击者破坏这些资产的机密性、完整性或可用性(CIA)的可能方式,每种类型的破坏可能对业务产生的影响,并系统地确保我们设计和实施针对这些攻击的适当保护。

在上一篇文章中,我们已经讨论了如何在端到端人工智能工作流的各个点上涉及大量的敏感业务数据,以及由于(a)新工具和框架的大量涌现,(b)系统/子系统的新类型和组合,以及(c)涉及的新利益相关方,我们已经看到了一些安全和隐私挑战。我们将从那里向前迈进,并通过其他层来识别与用于“学习”的业务数据量相关的“下游”有趣资产。

AI & ML 引入的有趣“新资产”

在一个非常简单的层面上,许多 ML 算法(尤其是那些与预测或分类有关的算法)本质上试图解决一个看起来像这样的数值问题:

y=w . x+b

这里' x '表示输入(或特征),'y【T21]'表示过去数据中观察到的相应输出或结果。

因此,在房屋销售预测环境中, x 可能是影响其价格的房屋属性(如建筑面积、庭院大小、位置、条件等)。)和“ y ”可能是过去几个月房屋销售的价格。该算法的任务是发现最佳的' w 和' b ',它们可以解释过去的数据,并且可以用于做出良好的未来预测' y ',给定先前未看到的输入' x *'。*计算出“ w ”和“ b ”(以下统称为“权重”或“ w ”)的过程称为“训练”或“学习”。

一旦算法“学习”了权重“T24”w“T25”,我们就可以用它们来预测新投放市场的房屋可能的售价。(在大多数现实世界的问题中,对' w '的求值涉及到对非常大的矩阵的计算密集型和昂贵的操作。)

在这个非常简短的概述的背景下,让我们看看从 AI & ML 中出现的有趣的新资产:

1。特点

在许多 ML 问题中,数据科学家与领域专家密切合作,为机器学习算法设计数据的最佳“表示”。这被称为“特征工程”,需要大量的努力和洞察力。领域专业知识有助于直觉判断什么可能是(或不是)值得考虑的有趣特征,数据科学家或统计学家有助于找出最合适的方法来考虑这些特征。因此,即使您从相同的训练数据开始,良好的特征选择和组合也可以产生更好的结果,并且从数据保护的角度来看,这使得“特征工程”的工件成为重要的资产。

(如今,模型自己“学习”这些特性变得越来越普遍,尤其是在较大的系统中。这项技术被称为“特征学习”或“表征学习”,其基本原理是输入所有可用的输入,并让算法(在内部)找出哪些特征重要,哪些不重要。当这种情况发生时,“特征”仍然保留在模型内部。也就是说,没有显式的称为“特性”的工件需要担心保护。然而,如果特性是手工设计的,它们就代表了一个有价值的工件,需要像对待任何其他信息资产一样对待。)

A typical ‘deep’ neural network

2。模型超参数

大多数机器学习算法都有几个“设置”,可以调整这些设置来修改算法的行为。这些设置可以被认为是定义底层机器学习模型的物理特征和行为的“设计选择”。例如,在线性回归的情况下,“学习率”是影响模型在搜索最佳权重时收敛(或不收敛)速度的因素。在深度神经网络的情况下(见上面的图片),有许多其他选择,如层数(网络的深度)、每层中神经元的数量(层的高度)、训练期间使用的批量大小、通过的次数、使用的优化方法等。等。

这些设置被称为“超参数,因为它们的选择会影响模型从训练数据中学习到的最终“参数”(即系数或权重)。在更大的问题中,可能会涉及到几十个这样的选择,需要做大量的工作来发现和确定能够提供期望结果的正确组合。在数据本身不是唯一的问题环境中(例如,在各方都可以获得数百万张图像的情况下的图像识别),这些超参数代表了一种竞争优势。换句话说,一旦您投入了大量辛勤工作来创建一个已经开始产生巨大成果的模型,相应的超参数对于您的组织来说与任何其他“高价值资产”(HVA)没有什么不同,无论它们位于何处,考虑保护它们都变得非常重要。

3。权重或系数

与超参数类似,模型学习到的权重/系数(上面的“y=w . x+b”中的“ w 和“ b ”)代表了模型在训练阶段从数百万条数据记录中收集到的所有宝贵“见解”。模型中的未来预测是使用这些权重对新数据点进行简单(通常也是快速)的数学运算。

就像“超参数”一样,这些砝码是“可重复使用的”。此外,与超参数相比,它们更易于重用。使用一种称为“迁移学习”的技术,其他数据科学家可以从您的模型导出的权重开始,进一步改进给定的解决方案,或者尝试解决原始问题的变体。事实上,这是数据科学家常用的协作技术。

然而,根据业务环境的不同,共享这些权重可能并不总是明智的(有意或无意)。例如,如果你是一家股票交易公司,你的团队制定了一个创新的基于 ML 的交易方案,你希望从中获得大量利润,你真的不希望另一个竞争对手利用这些权重进行“迁移学习”。(因为在类似的市场条件下,他们可能会开始做类似或比你更好的交易。)

The weights/coefficients of a model. (Source: Andrej Karpathy on Medium)

4。专业硬件上的计算投资

大多数大规模/现实世界的问题需要大量的计算时间来学习正确的系数。由于涉及大量基于矩阵的计算,大多数解决方案需要专门的硬件——现场可编程门阵列(FPGAs)或图形处理单元(GPU)——来以省时的方式计算权重。使用这些硬件技术是因为它们能够以高度并行的方式执行计算(高维矩阵计算就是这种情况)。

Specialized hardware is often needed to make ML time-efficient (Source: NVidia)

此外,由于拥有这些设备可能非常昂贵,而且技术一直在快速发展,大多数情况下都采用云托管服务来访问这些硬件,因此可以使用“按需付费”的模式。

A cloud datacenter (Source: Microsoft)

大多数人听到后会说“哇!”关于谷歌 DeepMind 团队创造的 AlphaGo 系统如何击败围棋世界冠军(一种靠蛮力计算和搜索深度都不够的高度直观的游戏)。然而,人们忽略了一个细节,那就是投入了多少计算工作。

AlphaGo playing Lee Sedol at Go (Source: DeepMind)

DeepMind 关于他们壮举的论文提到了42 天的训练时间和各种硬件进步,有些涉及 48 个张量处理单元(TPU),有些涉及 168 个 TPU——所有这些都托管在云中。

在许多现实世界的问题环境中,对计算的投资和由此产生的费用可能会类似地急剧增加。因此,在“ w ”矩阵中所有那些“权重”代表了大量的$$。此外,还必须小心对计算的访问,因为您不希望攻击者使用或重新利用它来满足自己的计算需求(例如试图从被盗的数据库中破解密码或增强其僵尸网络的计算能力)。

5。自定义算法

人工智能和人工智能领域正在迅速发展,因为有很多机会以创造性的方式和在新的问题领域应用这些技术。有趣的是,来自一个问题领域的算法和模型的现有“最佳实践”在应用于一个完全不同的领域时并不一定“延续”。也就是说,在一个问题领域产生优秀结果的东西在另一个领域可能不那么有效或有洞察力。因此,从一个在另一个环境中工作的解决方案开始的团队经常发现他们自己在开始得到有趣和令人兴奋的结果之前投入了大量的实验,并进行了重大的修改和改进。因此,如果你正在研究一个新奇的问题,当你有效地解决了这个问题之后,如果你看到一个专有的算法,你不应该感到惊讶。当这种情况发生时,恭喜您,您手头又多了一份需要保护的无价资产!

ML algorithms (Source: SciKit-Learn docs)

保护新资产

我们已经看到了 ML & AI 解决方案带来的有趣的新型信息资产——如工程特征、模型超参数、权重/系数、高度昂贵的计算以及定制或专有的 ML 算法。

这些新资产遭受的攻击可以分为两类。可以被视为“传统”数据篡改/数据窃取攻击的攻击,我们可能会在其他数据保护环境中看到这些攻击。(例如,从数据科学家的笔记本电脑或邮箱中窃取模型参数,或者从不受保护的文件共享中窃取权重。)保护这些资产免受这种“传统”攻击的技术和方法已经在上一篇文章中介绍过了。只要这些新类型的资产也包括在威胁目标中,并且在工作流的不同阶段(相应的资产出现的地方)建立了足够的保护,我们就可以认为这类攻击已被涵盖。

第二类也是更有趣的一类代表了源于人工智能& ML 算法内部工作方式的攻击。我们将在下一部分继续我们的旅程,并通过冒险进入 AI & ML 系统的“运行时”来探索这些。

People at work!

[在‘资产’的话题上,我还想提一下,在当前人工智能和人工智能人才相对于需求如此稀缺的时代,优秀的数据科学家和机器学习/数据工程师也是任何企业的宝贵资产。所有良好的人力资源实践,通过恰当的认可和奖励,让你最优秀的员工保持快乐、有挑战性和兴奋、有动力,等等。,应该对那些有所帮助!]

人工智能和机器学习中的安全和隐私考虑—第 3 部分:对“运行时”的攻击

原文:https://towardsdatascience.com/security-and-privacy-considerations-in-artificial-intelligence-machine-learning-part-3-attacks-f3987342b903?source=collection_archive---------5-----------------------

Photo by Justyn Warner on Unsplash

注:这是“人工智能中的安全和隐私&机器学习”系列文章的第 3 部分。以下是所有文章的链接(到目前为止):

不适当或不完整的数据验证一直是程序和系统安全的祸根。在新的计算范式中,当系统本身从输入数据中“实现”(或定义)时,我们该怎么办?

欢迎来到对抗性机器学习的世界!

在本系列的上一篇文章中,我们探索了当人们考虑 AI & ML 的内部时,会出现的有趣的新资产。最后,我们观察到这些新资产的安全和隐私方面可以从两个角度来考虑——第一个是传统的数据安全/隐私(我们现有的分析可能的攻击点和设计保护的技术应该适用),第二个是基于 AI & ML 算法如何在内部工作。在本文中,我们将关注第二类攻击——涉及 AI & ML 算法运行时方面的攻击。

我们所说的“运行时间”是什么意思?

自动驾驶汽车长期以来一直是人工智能和人工智能领域的魅力和进步的衡量标准。你一定读过很多文章,看过很多视频,比如下面这个让我惊叹的视频:

在最近的一次演示中,当我要求举手表决有多少人愿意坐在后座时(播放完视频后),大约一百人中只有两个人举手!你有什么看法?

不管怎样,当我问汽车在陡峭弯曲的街道上行驶时看到了什么,答案包括“路边”、“标志”、“人”、“建筑物”、“障碍物”等等。真的是这样吗?或者这就是我们相信(或希望)汽车看到的情况?

在汽车的情况下,“视觉”大多是从一个流(漩涡?)的位,如下所示:

What is the self-driving car really ‘seeing’?

从那里开始,车辆中的各种系统一起工作,在这个过程中,应用概率统计向量代数和大型多维矩阵上的浮点运算,以得出关于如何命令车辆(转向、加速器、刹车等)的决策。)实时而且——尽管有可靠的数学基础——潜在的决策过程有很强的概率成分。

考虑下图,其中描述了卷积神经网络(CNN)对“显示”给它的图像进行分类。如果我们快速看一下左边的图片,我们大多数人都不太可能认出图片中的车辆,除了“一辆汽车”。然而,正如你在网络的输出端看到的,CNN 对于它是什么有一个更“分散”的观点。事实上,网络的某些部分甚至认为它可能是一匹

Clearly a car but a small part of the network thinks this is a horse!

对抗性机器学习利用上述思想使 AI/ML 系统中的学习和/或预测机制“做错事”。这可以通过影响学习过程(当攻击者可以在学习权重或系数的同时提供数据)或在预测/操作期间(当攻击者可以让模型对攻击者选择的给定输入做一些错误或意外的事情)来实现。此外,在安全术语中,攻击可能以“白盒”方式进行(当攻击者知道关于模型内部的大部分事情,超参数等)。)或“黑盒”方式(当攻击者只能从“外部”通过观察系统对某些输入的决定(像任何其他最终用户一样)来探索系统)。在对抗性攻击中,从数学上来说,攻击者试图“扰乱”输入,使“这是什么?”的概率分布以对攻击者有利的方式变化。(因此,在上面的 CNN 例子中,对手可能试图将图像的某些部分调整到“刚好足够”,以便网络认为它是“马”的概率显著上升,并且“马”被投票为“正确”的分类。)

这里可怕的部分是,算法预测失误或行为不当所需的修改往往非常微妙,人类很容易错过。

Humans are used to ‘looking past’ the graffiti and stickers on traffic signs!

例如,只需几个精心放置的贴纸(通过视觉算法观察到的图像“变形”),自动驾驶汽车就可以快速驶过停车标志,就像是限速标志一样。现在,作为人类,我们很少会把停车标志当成其他东西——即使上面有贴纸、海报或涂鸦(如上图所示)。目前,让机器做同样的事情似乎并不容易。也就是说,对立的例子不可能欺骗人类观察者,但是会对 AI/ML 系统产生不利影响。研究人员已经发现并展示了一些技术,这些技术可以获取正确分类的输入图像,并进行选择性修改,以使网络将其分类为任何其他图像。例如,在这张纸的下面的图像中,在图像的选定位置添加一些点,任何给定的输入数字都可能被误分类为任何目标输出数字。

Adversarial examples for mis-classifying hand-written digits

顺便说一下——虽然我们已经谈论了神经网络,并从视觉相关的问题中提取了例子——类似的挑战也适用于其他学习算法家族(决策树、支持向量机等)。)和其他问题领域(例如,自然语言处理、推荐系统等。).此外,同样有趣的是,对立的例子似乎在算法家族之间“翻译”——即使算法的数学基础非常不同!因此,一种类型的模型的坏例子很可能服务于攻击者的目的,即使在其他类型的模型中。当攻击者试图进行黑盒攻击时,这给了他们很大的优势。

Macrovision 复制保护——一种平行?

对抗性机器学习让我想起了一种有趣的复制保护技术,称为 Macrovision(或 MV),它曾在 80 年代末和 90 年代的 VCR 时代流行过。(是的,电子内容保护甚至在模拟时代也很流行,在那个时代,现代 DRM 和 IRM 技术都无能为力!)

Content protection in the analog era

时代的需要是有效地阻止 T2 人复制从商店购买或租用的原版 VCR 磁带。Macrovision 的内容保护方法基于一项有趣的观察,即电视和录像机中的电子设备对噪声信号的灵敏度和响应之间的差异。MV 保护本质上是在原始录制内容上叠加一个精心制作的“噪声”信号。这种噪声信号使得接收该信号的另一个 VCR(例如,试图从受 MV 保护的原始磁带上进行录制)会以某种方式“补偿”该噪声,使得录制本身有噪声并且实际上不可观看(亮度、色带、抖动等的剧烈波动)。).然而,同样的(“噪声叠加”)信号发送到电视上会播放得很好,并且可以观看,没有任何副作用!

A VCR‘s response to ‘noise’ was very different than a TV

通常情况下,对抗性输入表现出类似的行为——对数据的干扰人类很难察觉,但完全摆脱了人工智能和人工智能的机器。

“Tay Bot”——一个反对学习幼稚的案例

考虑到敌对输入的可能性,现实世界的学习系统不能是幼稚的。这方面的一个很好的例子是由微软人工智能研究团队创建的人工智能聊天机器人 Tay Bot ,它在 Twitter 上发布,与其他用户进行对话,并学习“沿途”与人互动。然而,作为协调攻击“误训”它的结果,Tay 迅速变得令人不快,并开始发布各种煽动性的推文。它必须在发射后 14 小时内被击落!

The Tay bot survived for just 14 hours in the ‘big bad world’

抵御对抗性攻击——当前的想法

鉴于在现实世界场景中部署人工智能和人工智能系统的风险越来越高,目前一个巨大的挑战和研究领域是我们如何在对手面前正确学习。换句话说,我们如何才能让学习变得更加健壮,这样——系统不仅可以沿着一条‘快乐的路径’(由良好的输入和无害的用户组成)做正确的事情——而且在存在主动和被动对手的情况下都不能做任何错误的事情!

对于那些在各种背景下经历过几轮软件安全漏洞的人来说,这应该感觉像是似曾相识。在某种程度上是这样的。但是解决方案并不是那么明显。多年来,我们已经开发了许多防御措施,帮助我们的程序变得强大,可以抵御敌对的输入。然而,我们所有的成熟度和工具都是为人类编写程序的世界而构建的。在人工智能/人工智能的世界里,程序是由机器编写的(或者说是由机器内部“计算出来的”)——我们只是通过向机器提供大量数据(有时还有标签或奖励/强化)来帮助它们计算出程序。因此,在这个软件 2.0 的新时代——模型内部的许多工作方式仍然超出了解释的范围——我们几乎没有什么可以应付的。

那么,很自然的是,当前的许多重点是设计能够更好地解释他们的决策并在额外约束下工作的算法。例如,较新类型的神经网络(例如,胶囊网络或 CapsNets)可以提供更高级别的保证,并接受某些物理约束(例如,在直立图像中,不仅脸部有两只眼睛和一个鼻子,而且鼻子必须在眼睛下方)。这些应该有助于减少对手的“自由度”。CapsNets 还能够通过从最外层向后工作来重现“他们所看到的”,从而为可验证性提供了范围。令人欣慰的是,人们已经意识到安全问题以及在设计阶段解决这些问题的必要性。

关于安全的简要说明

当我们谈到健壮性的话题时,让我们看看 AI & ML 的“安全”考虑。一个重要的区别是,即使没有敌对的输入,这些也可以发挥作用。例如,下面这张来自这篇 Twitter 帖子的图片显示,一辆特斯拉的仪表盘上显示 101 号高速公路标志为“限速 105”。令人欣慰的是,似乎这辆车实际上并没有加速到 105 英里/小时,但这个例子应该足以突出令人担忧的安全隐患。(Twitter 上的帖子读起来很有趣——首先是几个关于“人类司机如何在 101 号高速公路上以 105 英里/小时的速度行驶”的笑话,几个对埃隆·马斯克的挖苦,一些对问责制影响的有效思考,甚至有人发布了一段代码片段,可能会避免一个灾难性的决定实际得到实施。)

解决 AI & ML 中的安全问题的方法是零碎的、特定领域的,并且(有时)“硬编码”以确保特定解决方案中的安全性。然而,随着系统变得更加自主,并开始做出可能产生深远影响的决策,有必要探索适用于各种环境和学习算法的通用解决方案。

A Tesla reading the Highway-101 sign as ‘Speed Limit 105’

(出于对安全和隐私风险的关注,我将把对这个相当有趣的安全话题的讨论限制在这里。如果你想阅读更多,这篇论文提供了一个广泛的安全处理和一个相关工作的无价的引用列表。)

接下来呢?

在迄今为止的文章中,我们已经研究了正确对待传统网络安全的重要性(第 1 部分),分析了特定于 AI & ML 的新资产(第 2 部分),并考虑了 AI & ML 系统如何工作所带来的安全风险(第 3 部分,本文)。

在下一部分中,让我们稍微转向积极/建设性的一面,看看 AI 和 ML 是如何在各种环境中被用来提高安全性的,以及攻击者是如何使用上述技术来破坏安全机制的。

人工智能和机器学习中的安全和隐私考虑—第 4 部分:安全用例

原文:https://towardsdatascience.com/security-and-privacy-considerations-in-artificial-intelligence-machine-learning-part-4-the-d02a2fa3f665?source=collection_archive---------7-----------------------

Photo by Enrique Alarcon on Unsplash

注:这是“人工智能中的安全和隐私&机器学习”系列文章的第 4 部分。以下是所有文章的链接(到目前为止):

AI & ML — use cases for security

在这篇文章中,我们将仔细研究 AI&ML 在各种与安全相关的用例中的使用。我们不仅会讨论网络安全,还会讨论一些一般的安全场景,以及基于人工智能和人工智能的解决方案是如何在所有这些领域变得越来越流行的。最后,我们还将探索攻击者可能规避这些安全技术的方法。

因此,让我们从一些有趣的领域开始,在这些领域中,安全特性受益于 ML&AI。

监控和响应

当我们考虑网络安全时,AI&ML 最常被提及的领域之一是解决大规模环境安全中的“大海捞针”问题。当你看到一个大的生态系统时,人类几乎不可能在噪音的海洋中发现真正的积极因素。多年来,我们一直试图通过制定越来越复杂的试探法来应对这一挑战,这些试探法依赖于基于规则的过滤,试图发现可能的可疑事件。然而,最终,基于规则的方法被限制在规则设计者已知或构想的模式范围内。也就是说,任何基于规则的方法只能从规则覆盖的有限空间中发现问题。最后,当基于规则的系统确实发现了可能的可疑活动时,在传统的安全运营中心(SOC)环境中,我们仍然面临着由于人的疲劳而遗漏它的风险。

Suspcious activity is far more challenging to identify in large systems

基于 ML 的系统可以毫不费力地解决以上三个问题!也就是说,它可以扩展到来自不同层的不同传感器的数十亿个事件,它可以“识别”新的、迄今为止未见过的攻击模式,并且它可以随时做出正确的判断,而不像疲惫的 SOC 工程师那样。基于 ML 的系统在 0 天攻击(基于签名的方法根本不起作用)和高级持续威胁(APTs)的环境中具有进一步的优势,在高级持续威胁中,攻击者在很长一段时间内秘密地取得进展,并明确试图保持在可能触发警报的阈值以下。

在线欺诈—金融和其他

另一个基于 AI/ML 的安全特性产生影响的有趣领域是欺诈检测和欺诈预防领域。在这里,早期的方法也是“基于规则”的,并提出了自己的挑战。例如,使用现有技术的企业发现,由于“假阳性”(来自好客户的交易被拒绝),他们损失的钱比系统标记的“真阳性”(实际欺诈案例)节省的钱多。因此,较低的“假阳性”率对他们来说非常重要。在这种背景下,基于人工智能和人工智能的技术显示出了更好的“精度”和“召回”指标的前景——更不用说能够检测到以前没有看到的异常。

Minimizing false positives is critical in fraud detection techniques

除了金融欺诈,还有许多其他欺诈检测领域采用了基于 ML 的技术。例如,风格测定领域采用基于 ML 的技术来识别写作和音乐中的作者身份欺诈(或者甚至基于对编码风格的分析来识别恶意软件的作者)。

Stylometry — not only for writing but also music (and code!)

高级身份验证

传统上,用户认证是在系统的入口点进行的单一的“一刀切”式的检查。在跨站点请求伪造(CSRF)等基于 web 的攻击盛行之后,当用户将要执行更具特权的操作(例如,转账,而不仅仅是浏览帐户余额)时,一些更敏感的场景开始通过额外的挑战(非常熟悉的 OTP)得到保护。然而,这些大多是增强身份验证的静态方法。随着 AI&ML 进入游戏,游戏场将会变得更好,而且是显著的改变。

Learning individual keystroke patterns

就在几年前,在一个网上银行的场景中,银行不能做出任何假设,除了线路另一端的人知道密码(如果是你的密码,那么一定是你的!).随着“多模态生物特征识别”(使用一种以上的生物特征识别)和“行为生物特征识别”(通过个人的打字模式或鼠标移动来识别个人等功能)的出现,身份认证的可信度开始大幅提高。

此外,在 AI&ML 的支持下,身份验证在本质上变得真正“自适应”,因为系统可以根据大量信号和环境条件(关于用户、正在使用的设备、地理位置、网络层指标、一天中的时间、活动性质等)做出决定。)在一系列互动的任何阶段,用什么因素来挑战一个人。这些自适应认证机制很可能成为未来大多数在线系统的规范。

乘客筛查

这些年来,机场的安全检查越来越严格。缓慢移动的队列和不得不把你的电子产品包翻过来(然后把所有东西都装回去)的痛苦是任何地方的每个人都一致感受到的……这甚至没有涉及到侵犯隐私和侧写等敏感问题。

“black DSLR camera near sunglasses and bag” by Anete Lūsiņa on Unsplash

这一切可能很快会变得更好。基于人工智能和人工智能的人脸识别系统(FRS)已经可以大规模部署,并与其他识别属性(如某人的行走风格(步态分析))结合使用。人们也在努力从实时 X 射线扫描中更好地识别可疑物体。例如,在 2017 年期间,TSA 赞助了一场数据科学家之间的全球竞赛,以帮助提高其乘客筛查系统的预测准确性,奖金为 150 万美元!

鉴于这一切,我们可能离一个愿景不远了,当你要赶飞机时,你只需进入机场,径直走向登机口,进入飞机,按照你的座位号就座。那不是常旅客(以及其他人)的乌托邦吗?

Can we fly like it is our own private plane?

大规模监视

说到人脸识别和物理安全,在监控和人群安全领域有很多有趣的场景。人群监控系统现在可以识别和跟踪大量人群中的个人——这在寻找和监视潜在的麻烦制造者方面非常方便。即使潜在的麻烦制造者以前并不为人所知,人群中的异常行为也可以用来更好地进行有针对性的管理。

AI&ML are making crowd surveillance tractable

在要覆盖的区域非常大的监控场景中,基于人工智能和人工智能的技术与它们在网络安全 SOC 场景中的表现非常相似——它们可以识别大量传入流中的异常,并且不太可能因疲劳而错过一些东西。

Surveillance of a large area

这些新功能有多简单?

寻找安全特性中的缺陷和弱点一直是攻击者感兴趣的领域。自然,在我们上面提到的许多基于 AI & ML 的安全特性的上下文中,同样的故事也在上演。

例如,人脸识别系统(FRS)已经被证明容易受到对人脸巧妙修改的影响。研究人员用这个展示了一些惊人的结果。在这篇有趣的论文中,作者展示了通过佩戴定制印刷的护目镜(见论文下面的图片),他们可以伪装成一个看起来完全不同的目标人物,骗过最先进的 FRS 系统。

Researchers wore custom-printed goggles to impersonate to an FRS system

这与我们之前在第 3 部分中看到的问题是相反的,当时我们考虑了一个稍加修改的停车标志的例子。在这种情况下,我们观察到人类绝不会将带有涂鸦的停车标志误认为除了停车标志之外的任何东西——然而机器却将其解释为完全不同的东西。相反,在下面描述的攻击中,人类不可能把上面的人误认为下面的人。然而,FRS 系统很容易被说服。不过,这两种攻击的基本技术是相似的。定制印刷的护目镜用于充分地改变输入矩阵(或向其添加扰动),使得其余的计算产生关于该人是谁的完全不同的结论。

类似的攻击也适用于基于语音的认证系统。在这种情况下,声音样本被组合或者使用声音变形技术来欺骗声音识别技术。此外,已经证明只有音素足以制作攻击样本。也就是说,不用等着偷偷录下你说'嘿,Siri '即使攻击者可以听到你说单个单词''坐'rim' ',来自那里的音素可以组合成'嘿,Siri '!现在想一想,如果您是语音模仿攻击的目标,有多少种不同的方法可以收集您的语音样本?

安全性仍然是系统设计关注的问题!

有时,攻击者可以通过不特别需要击败系统的 AI/ML 组件来绕过基于 AI/ML 的安全特性。这里有一个很好的例子:

在一项名为海豚攻击的巧妙攻击中,研究人员能够向几乎所有的个人助理(Alexa、Siri 等)发送“听不见的”命令。)做各种事情,从“打开后门”或“订购此项”。这种攻击包括产生高于人类听觉范围的声音,然后解决问题,使其仍能被个人助理“听到”(因此得名“海豚攻击”)。

Dolphins communicate at frequencies above human audible range

一对巧妙的观察被用于策划实际的攻击。首先,个人助理设备中的麦克风通常响应声音信号而产生“谐波”,其次,这些设备中的下游电子设备被设计成滤除或忽略人类可听范围以上的频率(在期望人类执行命令的合理假设下)。因此,攻击将人类频率命令(h’)调制到一个听不见音高的载波信号(c’)上,产生一个组合(人类听不见)信号(c+h’)。当设备中的麦克风接收到该信号时,它会产生谐波(原始信号中分量频率的各种倍数/组合,即 2(c+h)* 、 2c+h* 、 c-h 等)。).你猜怎么着?其中一个产生的谐波恰好是' h '!现在,低通滤波器负责消除人类不可能产生(或听不到)的一切,下游(设备更深处)记录的只是“ h ”。也就是系统的反应就像听到了主人的命令一样!

The Dolphin Attack uses harmonics

这次攻击很好地提醒了我们,归根结底,安全性是一个系统设计问题。仅仅集成一个复杂的基于 ML 的安全特性实际上并不能使系统更加安全。攻击者可能会到处寻找,为了真正提高安全级别,设计人员必须进行端到端的考虑,确保不仅新功能被安全集成,而且支持机制是在考虑安全性的基础上从头设计的。因此,基于 ML 的安全特性本身可能并不是系统中最薄弱的环节。但是攻击者在乎吗?

接下来呢?

我们从 AI&ML 被用于构建网络安全和物理安全领域的各种类型的安全特性的领域开始了这一部分。我们还研究了对这些功能的攻击是如何同时发展的。在本系列的下一部分,我们将看看攻击者如何通过对各种类型的攻击使用 AI&ML 技术而受益,以及攻击者如何能够“武器化”AI 带来一些可怕的可能性。

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

人工智能和机器学习中的安全和隐私考虑—第 5 部分:当攻击者使用人工智能时。

原文:https://towardsdatascience.com/security-and-privacy-considerations-in-artificial-intelligence-machine-learning-part-5-when-6d6d9f457734?source=collection_archive---------14-----------------------

注意:这是“人工智能中的安全和隐私&机器学习”系列文章的第 5 部分。以下是所有文章的链接(到目前为止):

ML & AI as an attacker’s weapon

在上一篇文章中,我们回顾了 AI & ML 在安全相关场景中的一些建设性用例。然而,正如我们,防御者,已经开始越来越多地使用人工智能来提高安全性一样,攻击者也开始让攻击变得更加复杂!

让我们看看 AI & ML 是如何被部署和利用作为攻击者军械库的一部分的。与之前一样,我们将从网络安全场景开始,但也会触及围绕“武器化”的更广泛问题,以及对人工智能失控的担忧。

攻击者工具箱中的 AI & ML

现在让我们看看更广阔的空间,我们假设攻击者开始使用 AI & ML 作为他们武器的核心部分。

为什么验证码变得这么难?

你还记得就在 3-4 年前,当遇到挑战时,我们曾经愉快地“通过”的“简单”验证码吗?你从一张图片上读出一串弯弯曲曲的字母和数字,然后把它们输入文本框,瞧,你被认证为人类(而不是机器人)!如今,当我看到一个包含大量图像的验证码时,我会感到害怕(如果我需要完成的一个重要动作被这样的验证码保护,我会感到紧张)。似乎验证码不知何故把事情搞混了——它们提出的问题似乎对人类来说更难解决!

然而,这是攻击者使用 AI & ML 破解验证码的必然结果。图像识别和转录技术进步如此之大,以至于当攻击者热衷于使用人工智能/人工智能来绕过它们时,旧式验证码就是“活靶子”。这篇 BlackHat 论文详细介绍了如何结合机器学习,利用现有服务的巧妙即兴创作,破解目前使用的最复杂的验证码。

Do CAPTCHAs make you nervous these days?

适应性恶意软件和智能僵尸网络

就像通过使用人工智能和人工智能,身份验证等安全功能已经变得“适应性”一样,网络攻击也是如此。拥有机器学习能力的恶意软件可以“学习”在某个环境中什么可能有效,什么可能无效,并改变自身以通过防御和渗透系统。此外,一旦恶意软件进入目标系统,如果它可以为每个目标系统制定不同的隐藏策略,那么它不被检测到的机会就会大大增加。

Malware that can ‘learn’

攻击者经常使用一群被入侵的计算机来实施大规模攻击。这些通常被称为“僵尸网络”,由来自 C&C 指挥控制中心的攻击者控制。随着 AI & ML 的引入,这些僵尸网络被设计成“自我学习”和“智能”,使它们在发现可能的攻击点的方法上更加点对点,在决策上更加自主,而对 C&C 中心的依赖比传统僵尸网络少得多。这种方法将使这些机器人变得非常高效,同时也非常致命

Swarm botnets

机器学习破解密码

今天,许多信息安全都建立在密码学的基础之上。许多密码学原语都是基于密码学家设计的算法,其目标是通过使攻击者“在实践中很难”破解密码来实现“足够好”的安全性(而不是逃避性的“完美”安全性)。

例如,对称加密技术试图实现“伪随机”置换函数的效果。也就是说,实际上,对于不知道加密密钥的攻击者来说,明文块和相应的加密文本之间的映射看起来就像是原始块中比特的随机排列。

然而,要意识到在设计好的算法的这种“伪随机”行为和真正的随机性之间有一个差距。此外,隐藏密钥和算法的组合本质上代表了“伪随机”函数。

现在考虑,在他们的核心,ML 技术是关于发现一个隐藏的“目标功能”。一个强大的神经网络有可能用足够多的纯文本和加密文本样本“推断”出一个密钥吗?(注意,这里的“足够”可能是一个非常大的数字。然而,在密码学中,即使是超出算法理论难度的微小改进——通常表现为强力方法中的努力——也会被视为漏洞或弱点。)同样,在不知道密钥的情况下,给定一个新的明文,一个经过“训练”的神经网络能产生一个可能的密文吗?

Can Crypto be attacked using machine learning?

有趣的是,谷歌大脑团队似乎已经沿着这些路线(使用人工智能的加密攻击和防御)进行了一些工作,正如本文中概述的那样。虽然这个 Reddit 帖子让人们对这项工作的价值产生争议,但我觉得人工智能加密的风险并不完全是假设的,也不牵强。

在一个非常基础的层面上,AI & ML 已经开始极大地帮助攻击者的一个领域是加速对 crypto 的暴力攻击。暴力攻击的挑战之一是能够推断解密密文的暴力尝试何时产生“潜在有效”的明文。在过去,这需要人工检查,并大大降低了暴力攻击的速度。鉴于原始纯文本在许多常见用例中是自然语言,使用各种自然语言处理(NLP)技术来自动标记“看起来”像是有效消息的解密消息大大减轻了攻击者的负担。

社会工程及其他…

考虑到人类一直是系统安全中“最薄弱的一环”,“社会工程”领域是攻击者部署人工智能和人工智能的天然目标。

AI & ML 能做些什么让‘社会工程’攻击变得更可怕?

网络钓鱼邮件——社会工程师使用的一种更流行的技术——现在可以变得更有说服力和“个性化”。在过去,精明的收件人(或检测软件)可以推断出特定的电子邮件是一个骗局。然而,有了分析和捕捉一般上下文并模拟自然写作风格的能力,这项任务的难度就越来越大。此外,在过去,如果攻击者想要让特定/目标用户真正信服,他们必须手动进行大量的“攻击个性化”。今天不会了!ML & AI 解决了社会工程攻击的一个主要扩展挑战。

Future ‘social engineering’ will be AI-powered

如果我们看看基于电话呼叫的攻击,请注意今天我们如何经常听到另一端的陌生人的声音试图执行“社会工程”。基本上,某个你以前不认识的人(但掌握了一些关于你的信息)正试图说服你泄露敏感信息。然而,鉴于人工智能和人工智能的进步,未来另一边的人可能听起来像亲密的家庭成员(例如,在困境中寻求帮助的孩子或配偶)。当这种情况发生时,我们该怎么办?

这种攻击的另一端是 ML & AI 为“大规模社会工程”提供的能力。快速追逐这些会让我们陷入对民主等基本社会制度的威胁。如今的选举更多的是关于数据科学,而不是候选人的竞选承诺和跟踪记录,人工智能和人工智能已经提供了急需的技术,以可扩展的方式瞄准(和操纵)个体公民。(我们将在以后的文章中再次讨论这一方面。)

Democracy under attack?

我们的球场怎么样?在大多数司法管辖区,法院在了解和采用新技术方面往往落后。随着基于 ML 的音频和视频创作的进步,我们离能够制作一个完全无法从现实中分辨的假场景还有多远?视听证据的可采性会发生什么,当这种情况发生时,倒霉的法官该怎么办?

Fabricated evidence will get more real and convincing.

自主武器

进一步考虑这个“人类面临的风险”的主题,在“自主武器”的背景下,关于人工智能和人工智能的使用有很多争论。这就是反对自主武器的签名运动对这个术语的定义:

自主武器在没有人类干预的情况下选择并攻击目标。例如,它们可能包括武装四轴飞行器,可以搜索并消除符合某些预定义标准的人,但不包括巡航导弹或遥控无人机,因为人类可以做出所有的目标选择决定。人工智能(AI)技术已经达到了这样一个地步,即在几年内(而不是几十年内)部署这样的系统是可行的——即使在法律上不可行,也是可行的,并且赌注很高:自主武器被描述为继火药和核武器之后的第三次战争革命。

本质上,使用自主武器,人类被排除在最终的“扣动扳机”决定之外——本质上是授予 AI“杀人许可”。

即使在今天,人工智能和人工智能已经被广泛地部署在各种武器系统中,并为拥有这些先进系统的一方提供了显著的优势。然而,自主系统完全改变了等式,并带来了重大的道德和伦理困境——除了快速、不受控制的升级风险。几乎所有从事 AI & ML 开发的主要软件供应商都宣布了不参与这类武器开发的决议。但是,在资源丰富的国家有兴趣创建它们的情况下,这很难说是一种安慰。此外,如果我们回顾战争的历史——在机枪、潜艇和化学战的背景下也出现了类似的担忧——自主武器的最终部署和使用似乎是不可避免的。我们从过去的经历中非常清楚地知道,“跨国信任”是一个复杂的概念。各国可能会从事这样的工作,只是因为担心“如果我们不这样做,别人就会这样做”。

Autonomous Weapons — the next frontier of weaponization!

有一天 AI 会控制人类吗?

本文的大部分内容都是关于(人类)攻击者使用 AI & ML 作为他们工具包/军械库的一部分。然而,有一个很大的社区担心人工智能会发展成“意识”或“有自己的思想”并变得流氓。在这种情况下,我们必须把人工智能本身看作是一个对手!

这个场景涉及两个基本概念。

第一个是关于“特殊目的”与“一般目的”的智能。这更类似于在通用计算机出现之前,我们仍然拥有专用的、特定领域用例的计算机。用那个类比,我们目前仍然处于特殊目的(专用)人工智能的时代。我们有很多复杂的东西,并且看到了巨大的成果——但是是在垂直的、面向任务的领域(无人驾驶汽车、语音识别等)。).这些场景和支持它们的人工智能类型可以归类为人工“特殊”智能(ASI)。然而,正在进行认真的努力来征服下一个前沿领域,并创造可以称为人工“通用”智能(AGI)的东西——机器可以自己学习一系列不相关领域中以前未知的任务。

第二个概念是关于人工智能能力的指数级加速(这是我们所熟悉的,因为我们已经看到它在过去的其他技术中发生了)。在这里,预计在大约 15-20 年内,人工智能将与人类不相上下,尽管在人脑的能力和人工智能/人工智能系统的能力之间的映射上存在争议。将“意识”添加到这个画面中,可怕的可能性开始出现在未来,从那时起,我们进入了人工“超级”智能(ASI)的领域及其令人不安的含义。

这里要注意的一件重要事情是——尽管“人类智力水平”对我们(人类)来说似乎是一个重要的里程碑——对一个有意识的 ASI 来说,它甚至可能不仅仅是学术兴趣!

The road to ASI (Courtesy: Wait but Why — Tim Urban)

就我们而言,如果一个 ASI 出现了,那么现在地球上就有了一个全能的上帝——对我们来说最重要的问题是:它会是一个好上帝吗?

——蒂姆·厄本(等等,但是为什么

自然,这是一个激烈辩论的话题,讨论的双方都有来自“人工智能和 ML 中的名人”的头面人物(人工智能是否会接管 v. 仍然牢牢地在人类的控制之下)。然而,其他研究人员提出了一种不同的、不那么引人注目的方式来描述这个问题,即“如何构建人工智能,使它不会开发出与其创造者不一致的目标?”。

接下来呢?

在这篇文章中,我们触及了一系列非常广泛的问题——我们从利用人工智能和人工智能的网络攻击开始,一直到人类的生存问题。

虽然这个系列的标题是“AI & ML 的安全和隐私,但是到目前为止,我们只是零星地涉及了隐私。在下一篇文章中,我们将更加关注人工智能的隐私含义,以及正在开发的提供各种级别隐私保证的技术。

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

人工智能和机器学习中的安全和隐私—第 1 部分:现状

原文:https://towardsdatascience.com/security-and-privacy-in-artificial-intelligence-and-machine-learning-part-1-c6f607feb94b?source=collection_archive---------3-----------------------

如今,关于机器学习(ML)和人工智能(AI)以及它们为几乎各行各业带来的用例,人们兴奋不已,议论纷纷。在如此多的领域中,我们现在已经有了成熟的解决方案,而且,我们不时地听到 ML & AI 在解决迄今为止尚未探索的问题方面有趣而有见地的应用,这让我们不禁“哦,哇!”。

随着部署的场景变得更加丰富和广泛,我们必须确保 AI & ML 的安全和隐私方面得到充分考虑。为了做到这一点,理解安全和隐私与人工智能和人工智能领域交叉的不同方式是很重要的。在本系列中,我们将一次一个“方面”地探索这些交叉点,目的是了解所涉及的风险的性质和程度,以及针对每种风险有哪些保护措施可用或正在探索中。

虽然我在信息安全和隐私领域有几年的工作经验,但相对而言,我对 AI & ML 还是个新手。(我们刚刚开始在工作中的云安全和开发运营项目中使用 ML 技术。)所以这个系列更多的是从一个安全人员的角度,以系统的方式对 AI & ML 环境中的安全和隐私进行推理。本系列的前几部分将集中在稍微狭窄的技术方面。然而,在这个系列的过程中,我们也将涉及更广泛的社会/社会问题。随着这个系列的发展,我很想听听这两个领域的专家对我组织演讲的方式的看法。

在这第一部分中,我将从网络安全的角度出发,从“让我们把基本的东西做好”开始,而不会深入到 AI & ML 的内部。在接下来的部分中,我们将开始仔细观察 AI & ML 组件。

人工智能和人工智能解决方案的传统网络安全

像任何新领域一样,AI & ML 带来了一堆有趣的人工制品,相关的细微差别和警告,从安全角度来看,它们构成了挑战。

下面的两张图片(来自微软 Azure 文档)显示了端到端 AI/ML 工作流的不同阶段涉及的典型工件和利益相关者团体。

The End-2-End Workflow — Lots of systems, data formats, tools, stakeholders, etc.

The diaspora of development tools, platforms, frameworks, data handling, etc.

此类图表强调了我们面临的安全挑战的性质和类型的以下特征:

  • 有一个由(一些旧的,一些新的)工具、语言、框架组成的庞大生态系统,其功能包括数据摄取、数据预处理、建模、模型评估、集成、可视化、打包和部署等。
  • 从传统的软件工程师到机器学习工程师、数据科学家和统计学家,多个利益相关者群体都参与到任何项目中。
  • 完整的工作解决方案通常涉及在不同接口耦合在一起的多个系统。

从安全的角度来看,这是很多未知的新事物。我们正在寻找许多新的工具和框架,新的人(利益相关者团体)和新的系统或系统的组合。暂且抛开人工智能& ML 的细节/内部机制,在这样的背景下,即使仅仅是传统的网络安全也很难做得很好。这是因为新的工具和框架通常需要时间来变得“足够安全”,新的利益相关群体可能并不总是对安全性有统一的理解或认识,第三,涉及许多系统和接口的解决方案在边界/接口处有过有趣的安全失败历史。

关于数据科学中“数据”的一点注记

现在让我们看一下“数据安全”方面。在人工智能和人工智能的背景下,数据安全挑战的以下特征非常突出:

  • 在大多数解决方案中,巨大(巨大!)涉及大量的业务数据。我们谈论的是数百万甚至数十亿张唱片。而且,根据问题领域的不同,这些信息可能具有巨大的价值(例如,经纪公司过去的交易)或敏感性(例如,来自连锁医院的病历)。
  • 此外,不仅涉及大量数据,而且更倾向于考虑数据的所有属性/方面(维度)。这与隐私的“数据最小化”原则产生了有趣的矛盾。
  • 与传统的软件工程不同,在 AI & ML 中,通常不能在测试/预生产阶段使用“虚拟数据”。(整点讲的是‘从数据中学习’!)因此,在生态系统的所有点上,我们都在谈论处理宝贵的真实数据的各种利益相关方和各种系统。(例如,协作开发模型的数据科学家团队必须在实验过程中访问许多相同的数据,而这些数据是您多年来在生产系统上精心保护的,这导致业务数据进入了过去通常不会进入的系统。)对各种数据的多次迭代和请求可能会破坏您现有的任何数据治理。
  • 鉴于 AI & ML 已经进入了各行各业,我们正在寻找数百种迄今为止晦涩难懂的数据和记录格式(以及相应的阅读器、编码器和解码器)。我们有着丰富多彩的安全漏洞历史,只是在少数更流行的编码格式中。当我们考虑到乘数效应时,想想未来会发生什么。

第一步:做好基础工作

虽然这些挑战确实令人望而生畏,但对于安全从业者来说,上述许多挑战并不陌生。我们过去经历过技术范式的转变。我们已经看到了良好安全性的基本原则是如何保持不变的,以及如何在仔细理解任何新环境/生态系统的细微差别和独特要求后应用它们。在一天结束的时候,它应该归结为做好最基本的事情——也就是说。,

  • 确保所有团队成员/利益相关者对安全性和隐私有很好的基本了解,如数据分类、数据保护技术、身份验证/授权、隐私原则、适用的法规要求等。目标应该是确保所有利益相关者对安全和隐私有适当的理解,并且每个人都使用相同的术语,知道并理解相关的政策和标准。
  • 拥有良好的数据治理结构。随着数据在每个工作流程的不同阶段易手,各利益相关方的所有权和责任应该是明确的。考虑到 ML & AI 项目中不可避免的数据的广泛流通,这一点尤其重要。
  • 在组件级别和从端到端的角度对解决方案进行认真的威胁建模。这将确保安全性被“内置”到设计中,并且在端到端系统中的每一点(处理、存储或传输有价值的数据的地方)都满足适用的安全性要求。
  • 在威胁建模时,应该特别注意不同子系统之间的边界和接口。任何一方在这些接口上所做的假设都应该清楚地记录和验证。
  • 此外,因为生产数据无处不在,所以请确保详尽地涵盖威胁模型中的所有工作流—从最早的实验和概念证明开始,到将在生产中部署的完全可操作的系统。
  • 确保在实施过程中遵循良好的编程实践,并根据所使用的技术减轻相应的漏洞(例如,如果解决方案的某个部分基于 web,则必须保护身份验证令牌/cookie 免受 XSS、CSRF 等攻击。)
  • 通过执行功能安全测试和渗透评估的组合,确保在威胁建模过程中识别的、被认为足够重要的所有威胁/风险都得到实际解决。
  • 确保不同框架和子系统的本机安全模型得到充分理解和合理化,以实现整个系统的统一安全性。这一点尤其重要,因为多个可能完全不同的组件和框架将“粘合”在一起,组成端到端的解决方案。
  • 对于在项目的不同阶段被不同的利益相关者使用或者被导入到不同的“管道”中的软件组件要小心。在可能的情况下,使用经过验证和签名的组件,如果这不是一个选项,则考虑其他因素,如开发人员的声誉、使用范围、存储库的可信度、评论和审查、安全问题/漏洞的历史等。这些应该有助于从安全质量的角度评估组件是否足够好。
  • 考虑您的部署(CICD)管道的安全性。你能很好地控制谁能改变构建/发布环境吗?您是否充分保护了部署所需的任何机密/连接字符串?您的生产设置是否足够严格,以至于人们无法进行特别的配置更改?
  • 实行良好的监控和安全卫生。确保所有软件组件都处于最新的安全补丁级别,定期进行访问检查,轮换密钥/证书等。
  • 最后,一定要有一个好的事件响应计划,这样如果灾难真的发生了,你就可以应对。

好了,我们到了!对于安全专业人士来说,以上这些听起来都不新鲜。你过去一定在不同的问题环境中做过一些或所有这些事情。因此,AI & ML 的安全和隐私的第一个方面是在新的环境中应用所有的专业知识,同时与所有相关的利益相关者合作。

但是要意识到,到目前为止,我们已经将系统的 AI & ML 组件作为一个“黑盒”来对待。当我们更仔细地观察这个盒子时,事情开始变得有趣多了。这正是我们将在本系列的下一部分中探讨的内容。期待再次见到你!

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

参见机器人游戏:探索人类和机器的好奇心。

原文:https://towardsdatascience.com/see-robot-play-an-exploration-of-curiosity-in-humans-and-machines-b384b61b0f7b?source=collection_archive---------22-----------------------

好奇心在人类和人工智能代理中的作用。

你可以在文章末尾找到一个 GitHub 存储库,里面有重现实验的代码。

F 从生存的角度来看,驱动动物和人类的主要生物需求并没有特别的不同。人类和动物需要吃和喝才能生存,需要庇护,他们有一种繁殖的冲动,以保持物种的生存。但是,很明显,人类和动物的行为完全不同。这是为什么呢?

人类大脑的进化创造了动物不存在或特别发达的区域,如前额皮质,这是一个通常负责推理、规划和逻辑思维的区域。大脑的这种发展导致了完全不同的冲动和驱动力的产生。其中之一在很大程度上驱动了人类的行为。这是电影和图书产业存在的原因,举几个例子,这是几个世纪前探险家航行数月的原因,也是你阅读这篇文章的原因:好奇心

好奇心是寻找意想不到的东西的冲动,是探索、发现和揭开面纱的需要。它经常被描述为智慧物种的一个特征:探索和扩展知识的需要甚至在伟大的希腊神话中就被认为是定义智慧和美德的女人和男人。

因此,在人类的好奇心和人工智能之间建立联系是很直观的:研究人员认为,在人工大脑中模仿这些现象将是创造真正的机器智能的基础。在这篇文章中,我们将探索如何在智能体的电子大脑中创造好奇心,以及它对其行为有什么影响,发现它将如何导致在某种意义上非常人性化的行为。

我们在这篇文章开始时谈到了需求和冲动。我们如何在机器中模拟那些生物信号?一个非常流行的框架是强化学习 (RL)。在 RL 中,智能体(如机器人)可以观察环境和自身的状态,如其在空间中的位置,并采取相应的行动。代理人的主要目标是获得高额报酬。奖励是我们定义的信号,它应该告诉代理哪些行为是好的,哪些行为应该避免。从生物学的角度来看,积极的回报可以通过饮食来给予。消极的奖励可能是通过对自身造成伤害来给予的。比如像吃豆人这样的电子游戏,吃水果会有奖励,而被鬼吃了之后会有负奖励,而这就足以教会玩家如何打败游戏了。

近年来,深度强化学习取得了巨大的成就,比如学会了以超人的水平玩雅达利电子游戏,打败了世界上最好的围棋选手,学会了如何控制复杂的模拟机器人。让我们关注最后一个例子:为了教会机器人移动,环境奖励代理向前移动而不是摔倒,因此 RL 算法通过试错来学习导致向前移动的行为,例如步态或行走模式。这些奖励被称为外在:它们来自环境,它们是任务的一部分,因此代理可以学习如何完成任务。但是还有第二种奖励:内在奖励。内在奖励不是环境的一部分,而是由代理本身产生的。代理可以奖励自己发现新事物达到新的未知状态,无论最终的环境任务是什么。在这一类别中,我们可以找到好奇心:这的确是对发现新奇事物的一种奖励,就像你发现了一篇新的有趣的文章、一本书或一家餐馆时的奖励一样。那么,好奇心是如何在代理中产生的呢?为了理解这一点,我们必须首先理解什么是预测正向模型

Explorers sailed to discover new lands driven by curiosity.

在计算机科学和控制理论中,我们可以创建模型,在给定当前状态和动作的情况下预测下一个状态。这些模型通常是神经网络,根据经验预测行动对未来的直接影响。你知道用一定的力量把球抛向空中会发生什么,因为你以前经历过。因此,神经网络可以通过从以前的观察、行动和新观察的经验中学习,来学习预测下一个机器人手臂将会发生什么。简而言之,这是一个预测性的正向模型。

从某种意义上来说,你的大脑在不断地根据刚刚过去的事情预测不久的将来。正如一些神经科学研究所表明的,大脑是一台预测机器。因此,如果事情没有按预期进行,你会感到惊讶。你可能几乎每天都走同一条路线去上班,所有这些记忆都渐渐消失了。但是如果有一天你看到一辆车在路中间着火了呢?几年后你肯定会记得这件事,甚至可能记得确切的日期。同样,这也是为什么你要读一本书、一篇文章、看一部电影、去某个地方旅行:去看看和学习一些你没有预料到或已经知道的东西。既然我们知道什么是正向模型,这种驱动冲动可以在机器中复制:人工智能代理可以通过采取导致其达到令人惊讶的状态的行动来奖励自己。从计算上来说,惊喜是预期的未来和实际发生的未来之差,从一个状态,做某个动作。

我们现在可以介绍我们将做实验的环境:一个模拟的取物机器人,它可以用手臂推着一个盒子。这是著名的 OpenAI 的健身房图书馆里的 FetchPush-v1 环境。代理的目标是将盒子推到它的目标位置,即红色的球。但是我们现在不关心这个任务:正如之前解释的,我们对内在奖励感兴趣,我们想看看通过用好奇心引导代理会发生什么。

我们机器人 Fetch 可以在三维空间内移动它的末端执行器。每走一步,它都能观察到自己在空间中的位置,以及立方体的位置。我们可以在智能体中创建一个内部预测向前模型,通过简单地移动手臂,让它体验它的环境。基于这种经验,代理将很快了解当它给它的手臂一个命令时会发生什么:手臂在指定的方向上移动一点点。因此,前向模型在预测手臂运动方面将很快变得非常好。但是当给手臂一个动作命令时,第二件事可能发生:手臂可以触摸立方体并移动它。虽然这对我们来说很直观,但对像婴儿一样第一次探索世界的机器人来说却不是这样。学习预测立方体被触摸时会发生什么是非常困难的,这既是因为接触力的复杂物理学,也是因为在最初的探索中,机器人只会触摸立方体几次,因为整个操作空间相当大,而立方体非常小。所以,机器人将体验到立方体在 99%的情况下不受手臂移动的影响,并且可能认为立方体永远是静止的。因此,预测正向模型将很难预测立方体的移动。这里我们可以看到好奇心对机器人的影响。

Two of the Fetch gym environments. We will focus on FetchPush (left).

既然机器人已经学会了最初的前进模式,我们可以让它在好奇心的驱使下更多地探索环境。然后,机器人将尝试寻找结果令人惊讶的动作。正如预期的那样,移动手臂对机器人来说通常很无聊,因为它很清楚会发生什么。但是,一点一点地,它会知道它发现在触摸立方体时会发生什么令人惊讶的事情。立方体以一种不可预测的方式移动,这是它感到惊讶的原因,激起了它的好奇心。因此,就像婴儿一样,机器人将学习玩立方体,因为从某种意义上来说,这很有趣。有趣的是,它发现当它把盒子推出桌子时,最不可预测的事情发生了,盒子掉在了地上。

Fetch learns to play with the cube guided by curiosity.

机器人已经学会在没有任何外部指导或信号的情况下玩立方体**。它不知道任务的目标,它只是试图探索周围的世界,并试图发现令人惊讶的事情,因为它很好奇。这种简单的内在动机使它发现了立方体,就像玩具一样是它现在的主要兴趣。正如在这篇博文中所描述的,好奇心可以极大地帮助一个特工探索周围环境,发现原本看不见的东西。有了好奇心,智能体可以学习激活环境中的罕见事件,并逐渐了解复杂系统的所有底层机制。**

近年来,人工智能领域的研究人员已经在广泛的环境中研究了好奇心对智能体的影响。最有趣的结果之一来自于将好奇心应用到玩电子游戏的代理人身上。最近的一项研究表明,如果有好奇心的引导,一个代理人可以在没有任何外部奖励的情况下学会玩几个级别的超级马里奥兄弟。它对打破记录没有兴趣,只是对发现接下来会发生什么有着强烈的兴趣,并渴望发现新的和意想不到的东西。在这个游戏中,最好的方法就是在一个关卡中前进并发现下一个区域。为了做到这一点,代理人必须学会如何生存,避免敌人和陷阱,只是为了发现新的东西。

另一项研究展示了这种情况在几款雅达利视频游戏中是如何发生的:代理人可以通过遵循这种内在奖励来学习如何玩好一款游戏。但真正有趣的是研究人员在论文中写道的一个结论:这个结果不仅是人工智能的一项成就,也是对人类好奇心影响的一个很好的洞察。我们玩电子游戏是因为它们很有趣,它们是新的刺激、体验和挑战的来源。因此,一个设计良好的视频游戏应该围绕奖励玩家的好奇心来创建,这就是为什么由好奇心驱动的人工智能代理可以学习玩这些游戏。

好奇心是人类智力的重要组成部分。它不仅是人类行为的特征,也是构建进一步智能和知识的重要工具:没有好奇心,我们就无法发现新事物,除非它们撞上我们。这就是为什么,要建造真正智能的机器,就必须对好奇心和其他内在刺激进行描述和建模,这些刺激是由我们的大脑产生的,并推动人类不断进化。

觉得好奇?你可以在这个 GitHub 库里找到所有的代码。

谢谢你读到这里!你可以在推特(@normandipalo)上关注我关注我的工作和研究。

Seed AI:历史、哲学和艺术状态

原文:https://towardsdatascience.com/seed-ai-history-philosophy-and-state-of-the-art-22b5294b21b5?source=collection_archive---------16-----------------------

让我们把超智能机器定义为一种能够远远超越任何人的所有智力活动的机器,不管这个人有多聪明。因为机器的设计是一种智力活动,一台超级智能机器可以设计出更好的机器;毫无疑问,那时将会出现“智力爆炸”,人类的智力将会被远远地抛在后面。因此,第一台超智能机器是人类需要制造的最后一项发明,只要这台机器足够温顺,能告诉我们如何控制它。(欧文·约翰·古德,1965)

上面的引文包含了对术语智能爆炸的第一次提及和解释。从那以后,人工智能领域发生了很多事情,无论是哲学上还是实践上。尽管自 1965 年以来,该领域已经取得了巨大的进展,但与智能爆炸的想法密切相关的术语“种子人工智能”相对来说是闻所未闻的。

什么是 Seed AI?

种子人工智能是人工智能研究者和理性倡导者 Eliezer S. Yudkowsky 创造的一个术语。在我们讨论种子 AI 的定义之前,有必要讨论一个人工通用智能。我会用维基百科的定义:

人工通用智能 ( AGI )是一台机器的智能,它能够成功地完成人类能够完成的任何智力任务。

继续讨论 Seed AI,LessWrong 的 Wiki(由 Yudkowsky 创建的一个流行博客)对这个术语的定义如下:

一个种子 AI (一个由 Eliezer Yudkowsky 创造的术语)是一个人工通用智能 (AGI),它通过递归地重写自己的源代码来改进自己,而无需人工干预。

同一篇文章中提到了 Seed AI 的几个关键特征:

  • “了解自己的源代码。”因为一个 AI 的源代码,这意味着它理解本身。如果一个人工智能不理解自己代码的“目的、语法和架构”,它就不能成为种子人工智能。
  • "重写自己的代码。"这已经在定义中了,但重要的是要指出它是在没有人类干预的情况下做到这一点的,并且更好地实现了它的目标。

种子人工智能的目标可以是任何东西。例如,Nick Bostrom 创建了一个著名的思维实验,其中中央人工智能的目标是最大化宇宙中回形针的数量。因此,重写自己的代码使它变得有趣。

AI-Foom

种子人工智能可以从相对较低的智能水平开始。然而,如果它足够聪明,可以重写它的源代码以变得更聪明(也就是说,更好地实现它的目标),结果它甚至可以更好地重写自己的源代码以变得更聪明。这个可能导致智能爆炸,人工智能迅速变得超级聪明(远比列奥纳多·达·芬奇聪明)。

Will AI ever reach for the clouds? Photo by Samuel Zeller on Unsplash

这种“傻瓜”的可能性已经被争论了很多,也许最著名的是由埃利泽·尤德考斯基和罗宾·汉森提出的。对他们争论的全面讨论超出了这篇文章的范围,但是他们讨论的一个(明显的)关键点是种子人工智能变得更加智能的速度。Yudkowsky 认为,人类的结构变化(DNA 的变化)导致了相对较大的智力差异(比学习更大),因此,有能力改变其结构(代码)的人工智能可以使其智力产生巨大差异。另一方面,汉森认为,虽然可能性可能存在,但这并不一定会给人工智能智慧来做出正确的结构变化。他们的讨论远不止这些,但这部分已经很有趣了。

哥德尔机器

Seed 人工智能的一个理论模型是由 Jürgen Schmidhuber 在 2003 年提出并以库尔特·哥德尔的名字命名的哥德尔机器。哥德尔机器从其环境接收输入,并产生能够影响其环境的输出。在任何给定的时间,哥德尔机器都希望最大化它的效用函数,代表它在环境中成功地实现了它的目标,不管这个目标是什么。然而,关键的是,如果哥德尔机器能够证明新代码在最大化其效用函数方面更好,那么它有能力重写自己的源代码。这正是种子人工智能所需要的:人工智能重写其源代码,以便能够更好地实现其目标。

还没有人造出哥德尔机器,但是理论上是可能的。

技术发展水平

你可能知道,据我们所知,还没有人建立一个种子人工智能。然而,有一些组织正在为此而努力。这种组织的一个例子是机器智能研究所(MIRI)。MIRI 的工作(到目前为止)主要是理论性的,侧重于有益的机器智能的数学基础。OpenCog 基金会有一个更实际的方法,旨在通过开源计划开发有益的一般智能。

种子、卫星和传感器——科技如何种植今年的作物

原文:https://towardsdatascience.com/seeds-satellites-and-sensors-how-technology-is-planting-this-years-crop-2f38b5a2296c?source=collection_archive---------1-----------------------

他们说成功是 90%的准备和 10%的汗水的结果。这适用于许多活动及其潜在结果。农业就是这样一种努力,计划和准备是成功收获的主要因素。

为健康茁壮的作物打下良好的基础至关重要。在撰写本文时,几乎是春天了,所以对许多种植者来说,种植指日可待。由于作物生长和繁殖周期的性质,农业具有很强的季节性。每种作物都有一个健康种子发芽所需的土壤温度、湿度和肥力的最佳窗口。

这个播种窗口是生长季节最关键的时期之一。对于种植者来说,在正确的时间将正确的种子与正确的土壤相匹配是重中之重(仔细权衡,试图确定各种商品的市场价格走向)。

一旦播种开始,接下来就是执行了。将适量的种子放在合适的深度,让它们同时发芽,有助于管理风险。统一的作物意味着相同的护理和管理措施可以应用于整个季节(假设不存在其他主要的可变性来源)。

然而,如果种子在不同的时间发芽,那么作物的成熟度和整体健康状况会在整个田地中发生变化。正在进行的作物季节变化管理可能会出现问题,并可能导致收获时产量的重大损失。

幸运的是,现有的技术可以帮助种植者高精度地管理播种。目标是建立一个坚实的基础,使作物能够茁壮成长。一些新兴的精量播种技术可以改装到现有设备上,而不需要购买大量资本。

事半功倍

随着商品价格在可预见的未来保持在历史低位,种植者不太倾向于购买新设备。然而,他们确实认识到需要不断改进他们的经营,并寻找新的方法来提高产量、降低成本和增加农场利润。

农业是资本高度密集的行业。以中西部一个 2000 英亩的玉米和大豆农场为例。资本成本可能包括每英亩约 5,000 美元的土地价值、300,000 美元的大马力拖拉机、200,000 美元的精密播种机、350,000 美元的联合收割机……你明白了吧。

除此之外,农民每英亩还必须投入数百元用于种子、化学药品、肥料和其他投入成本。正如你所看到的,一些农民可能有数百万美元的收入,却无法保证他们年底的作物收入。

资本设备最终会磨损并需要更换,然而,如果种植者目前的机器处于良好的工作状态,那么当利润如此之低时,就没有必要更换它。播种机技术就属于这一类。一台新的精密高速播种机的成本可能高达 25 万美元,而升级现有播种机的成本约为 4 万美元。

通过将正确的硬件升级与正确的精准农业软件相结合,经济回报将变得非常可观。此外,在大宗商品价格上涨后,效率的提高每年都会持续很久。

种子、卫星和传感器

农业中有许多活动部件,需要考虑大量信息。幸运的是,技术正在帮助消除分析和规划阶段的大量繁重工作。

现在农民在种植过程中可以利用的一些技术包括:

种子科技

  • 种子杂交技术(使种子特性与土壤和条件相匹配)
  • 种子处理(建立抗虫害和杂草能力)
  • 种子微生物(处理种子以减少肥料需求)

卫星

  • 种子位置的精确放置(精确施肥)
  • 卫星参考数据(对理解现场可变性至关重要)
  • 实时季节图像(测量作物生物量的卫星图像)

传感器

  • 关闭控制以防止种子重叠(使用较少的种子)
  • 单行控制(使种子品种与土壤类型相匹配)
  • 精确的下压力系统(均匀的种子深度和出苗)

投资回报

所有这些技术都提供了一定程度的经济回报。例如,消除种子深度、重叠和位置的可变性具有明显的投资回报。各种自动化下压力技术的制造商报告称,与传统系统相比,玉米产量每英亩可提高 10-11 蒲式耳。因此,即使玉米价格为每蒲式耳 3.50 美元,这也相当于可观的回报。

假设整个作物的平均产量每英亩增加 5 蒲式耳。在前面引用的农场示例中,2000 英亩的农场每英亩 17.50 美元,即第一年 35000 美元。几乎一年就能收回硬件升级成本,这意味着投资在接下来的几年里会产生正回报。

土壤类型的可变性越大,控制下压力的需求就越大,潜在回报也就越大。新的自动化设备还带来了其他好处,因为在换季期间减少了重新校准和设置。

数据驱动决策

当结合新一代自动化精准农业软件工具,如 AgDNA 时,回报甚至会更高。这些基于云的大数据工具能够分析上一季数百万英亩的土地,以确定最佳的种子和土壤组合。

每年都有这么多新的杂交种子技术被引进,种植者几乎不可能确定哪一种适合他的操作。然而,AgDNA 等新一代大数据平台可以在云端运行这些预测分析,并产生惊人的结果。

对大量数据集进行基准分析,以确定给定土壤类型和其他属性的最佳种子品种,可以带来每英亩 30 美元以上的回报。对于种植者来说,这是非常宝贵的信息,不仅可以让他们了解什么最适合他们的农场,还可以让他们根据选择参与标杆管理服务的其他种植者的经验获得洞察力。

结论

因此,尽管 2017 年农业大宗商品价格前景看好,但种植者仍有重大机会利用新兴硬件和软件技术,获得明显的经济回报。作物生产行业作为一个整体,在寻求更高的产量和更高的效率方面继续推进创新的边界。

因此,下次你在杂货店或吃你最喜欢的谷物时,请放心,全国各地的农民正在采用创新技术和耕作方法,以实现更可持续的未来。

从决策树看随机森林——对随机森林的一种解释

原文:https://towardsdatascience.com/seeing-the-random-forest-from-the-decision-trees-an-intuitive-explanation-of-random-forest-beaa2d6a0d80?source=collection_archive---------1-----------------------

So many bagged decision trees, so little processing resources.

在过去的这个周末,我有点无聊,决定温习一下我的简历。作为一名在 Insight 的研究员,我几乎完全是用 Python 编程的,但我实际上没有做过太多的 R 语言预测分析,除了非常普通的线性回归。我想要一个有点干净的数据源,这样我就可以在 r 中进行建模了。因此,一个好的干净数据源是好的 ole' kaggle 。我决定研究一个视频游戏销售数据集

决定,决定…

决策树,以及它们的表亲如袋装决策树、随机森林、梯度推进决策树等。,通常被称为系综方法。

为了理解更复杂的集成方法,我认为理解这些方法中最常见的决策树和随机森林是很好的。让我们举一个最简单的例子:使用决策树的回归。对于一个给定的 n 维数据集,你可以生成一个有 n 个分支和 n 个叶子的决策树。决策树的目标是确定最大程度减少残差平方和的分支,并尽可能提供最具预测性的叶子。也许一个数字会有所帮助…

Taken from the book Introduction to Statistical Learning

上图显示了一个棒球相关的数据集,我们想要确定一个球员的日志工资。在左图中,如果一个球员的经验少于 4.5 年,他们预计可以赚 511 万美元。如果一个玩家有超过 4.5 年的经验,但少于 117.5 次点击,他们预计会赚 6 千美元(同样基于日志)。在右边的数据中,预测值分别代表子空间 R1、R2 和 R3。

For those who like the see the math: decision trees essentially grow branches that reduce the sum of the errors for Rj sub-spaces in the data.

上面的例子使用了连续的数据,但是我们可以将其扩展到分类。在分类设置中,我们本质上是在增加分支以减少分类错误,尽管这并不那么简单。在分类设置中,我们采用一种类似熵的度量,并尝试减少每个分支的熵值,以提供最佳的分支分裂。基尼指数是一个常用的指标。

p-hat mk 表示来自第 k 类的第 m 个区域中的观测值的比例。从本质上说,基尼指数是一种方差的度量。方差越大,错误分类就越多。因此,基尼系数越低,分类越好。

将这些预测打包…

决策树通常被称为“贪婪的”。这只是算法如何试图确定减少误差的最佳方式的函数。不幸的是,这导致了模型过度拟合和模型过度一般化。

一种用于应对这种情况的方法被称为自举聚合或简称为‘bagging’。如果你理解统计学中的 bootstrapping 的概念(在估计未知人口的方差和误差方面),当涉及决策树时,bagging 是类似的。

在打包过程中,我们决定要从数据集中抽取多少个重复的引导,将它们放入同一个决策树中,然后将它们聚合在一起。这给了我们一个更健壮的结果,并且不容易过度拟合。

此外,通常每棵装袋的树会留下三分之一的样本。然后,我们可以将装袋的树与该样本进行拟合,并获得袋外误差率。这实质上是交叉验证的决策树版本,尽管您可以在超出袋外错误率的基础上执行交叉验证!

进入随机森林

现在我们对决策树和装袋有了大致的了解,随机森林的概念就相对简单了。香草随机森林是一个袋装决策树,其中一个附加算法在每次分裂时随机抽取 m 个预测值。这有助于对随机森林中使用的树进行去相关处理,并有助于自动应对多重共线性。

在分类中,所有的树都聚集在一起。从这种聚合中,该模型实质上采取了投票/投票来将数据分配给一个类别。

对于给定的观察,我们可以通过观察每个袋装树为该观察输出什么类来预测类。然后我们查看所有的树,看看这个观察被预测了多少次。如果观察结果是根据大多数袋装树预测的,则为该观察结果指定一个类别。

A random forest takes a random subset of features from the data, and creates n random trees from each subset. Trees are aggregated together at end.

一个在 R 中应用随机森林的危险的简短例子,使用视频游戏 Sales kaggle 数据集

可在此处找到数据集的概述。

我所有乱七八糟的代码都可以在我的 github 上找到。

本例的目标是看看销售数字和游戏所在的主机是否可以预测其类型(例如,体育、动作、RPG、策略等)。).

在这个例子中,我使用了caretggplot2。我使用包dummies为分类预测器生成虚拟变量。

我想得到一些使用caret的练习,它本质上是 R 版的scikit-learn。但是首先,和任何数据集一样,有必要对其进行一点探索。我的一般方法是首先在数据中寻找古怪之处,探索潜在的相关性,然后再深入一点,看看数据中是否有任何其他值得注意的趋势。理想情况下,您会希望在建模之前从各个方面检查数据。为了简洁起见,我跳过了一些数据探索,直接进行了一些建模。

首先,我检查了数据中缺失的值。有一大堆的NaNs,所以我继续使用DMwR包做了 K-最近邻插补。

接下来,我想检查一下销售数据,看看是否有异常值。曾经有。而且分布是高度倾斜的。

Most sales were far less than $20 million total.

我继续使用对数转换将它们标准化。

Normalized-ish, but still sorta skewed.

在这里,我为每个游戏运行的不同主机生成虚拟变量,然后检查相关性。毫不奇怪,全球销售额与所有其他销售额相关联。评论家分数和计数不是。这里没有显示控制台的相关性。考虑到控制台虚拟数据的稀疏性,这里没有什么值得注意的。如果多重共线性是一个大问题,可以简单地删除全局销售变量,而不是保留所有其他销售变量。

caret中,我做了 80%-20%的训练测试分割,作为进行建模的惯例。我将所有的流派重新标为数字,它们如下:

  1. 运动
  2. 平台游戏
  3. 竞赛
  4. 角色扮演游戏
  5. 难题
  6. 多方面的
  7. 射手
  8. 模拟
  9. 行动
  10. 战斗的
  11. 冒险
  12. 战略

我做了一些网格搜索在每个树分裂可用的功能数量。回想一下,当随机森林为树中的每个节点创建一个分割时,它不会获取所有可用的功能。这是模型中可操作的超参数

mtry <- sqrt(ncol(vg))
tunegrid <- expand.grid(.mtry = mtry)

在上面的代码片段中,我将列数的平方根作为可用的初始数字特性。在此基础上进行网格搜索,使得caret将迭代初始起始变量,然后在下一次拟合迭代中进行另一次 sqrt(ncol(vg))附加特征,然后再次评估模型。

metric <- 'Accuracy'
control <- trainControl(method = 'repeatedcv', number = 10, repeats = 2, search = 'random', savePredictions = TRUE)

接下来,我将我的度量设置为准确性,因为这是一个分类过程。我做交叉验证来评估我的训练数据是否不可靠。典型的折叠次数为 5-10 次(表示为number参数)。我做了一个随机搜索,因为它更快,计算量更小。

使用 caret,我训练了两个模型。一个有 15 棵袋装树。另一个有 500 袋树。500 树模型需要一些时间来运行(可能大约 30 分钟?).人们可以很容易地将袋装树木的数量纳入网格搜索中。为了简洁(和时间),我只比较了两个模型。

注:我允许模型使用 Box Cox 来确定如何适当地规范化数据(它对数据进行了对数转换)。

model_train1 <- train(Genre ~ ., data = vg_train, method = 'rf', trControl = control, tunegrid = tunegrid, metric = metric, ntree = 15, preProcess = c('BoxCox'))model_train2 <- train(Genre ~ ., data = vg_train, method = 'rf', trControl = control, tunegrid = tunegrid, metric = metric, ntree = 500, preProcess = c('BoxCox'))

我的交叉验证结果显示,500 树模型做得好一点点…但只是一点点。给定交叉验证结果,每个分割 21 个特征似乎是合适的。

Model 1 with 15 bagged trees.

Model 2 with 500 bagged trees

我的准确度是然而全然可怕的 。我在 Model 2 的整体准确率只有 34.4%。

随机森林允许我们查看特征重要性,这是一个特征的基尼指数在每次分裂时降低了多少。某个特征的基尼指数下降得越多,它就越重要。下图从 0 到 100 分对这些特性进行评分,100 分是最重要的。

看来用户数评论家数尤为重要。然而,鉴于模型拟合度如此之差,我不确定解释这些变量有多大用处。我已经包含了变量重要性代码的一个片段,以防您想要复制它。

# Save the variable importance values from our model object generated from caret.
x<-varImp(model_train2, scale = TRUE)# Get the row names of the variable importance data
rownames(x$importance)# Convert the variable importance data into a dataframe
importance <- data.frame(rownames(x$importance), x$importance$Overall)# Relabel the data
names(importance)<-c('Platform', 'Importance')# Order the data from greatest importance to least important
importance <- transform(importance, Platform = reorder(Platform, Importance))# Plot the data with ggplot.
ggplot(data=importance, aes(x=Platform, y=Importance)) +
  geom_bar(stat = 'identity',colour = "blue", fill = "white") + coord_flip())

我们可以查看混淆矩阵,看看有多少准确的分类和错误的分类。对角线表示正确的分类百分比。斜线表示模型错误分类一个流派的次数百分比。

太可怕了。射击游戏有 68%的机会被正确分类……但是也有很大一部分时间被错误分类为策略游戏。

外卖食品

为什么我们的模型做得这么差?有几个原因。该模型往往不符合数据。这可能意味着 random forest 不够复杂,不足以捕捉数据中的趋势,我们可能必须使用另一个模型来使用更复杂的方法。然而,更有可能的是,这些特征根本不能预测视频游戏的类型。

如果我们的功能有点糟糕,我们可以做两件事之一:我们可以为给定的数据集设计一些额外的功能。例如,我们可能能够创建一个变量,表示数据中每种游戏类型的平均评论家分数,作为一个预测器(但这可能是无趣的)。

我们可能要做的是从视频游戏存储库中获取一些额外的信息,该存储库中可能有每种类型的视频游戏的额外历史销售数据。第二个简单的方法是简单地计算每个流派的总销售额,然后将其应用于整个数据集。这么多选择!

或者答案更简单。可能是数据在类别方面不平衡。如果是这种情况(如果你进一步检查数据的话,确实如此),你可能想要修剪或合并流派来纠正这种情况。

结论

随机森林是机器学习中常用的模型,通常被称为经常使用的现成模型。在许多情况下,它的性能优于它的许多等效参数,并且启动时计算量较小。当然,对于任何模型,请确保您知道为什么要选择模型,例如随机森林(提示,可能您不知道您的数据的分布,可能您的数据非常高维,可能您有很多共线性,可能您想要一个易于解释的模型)。不要像我在这里一样漫不经心地选择一个模型。:-)

资源

我并不真正深入研究随机森林的机制。如果你想深入了解,我强烈推荐两本书:

后者被一些人认为是机器学习的圣经!

看路——自动驾驶汽车入门

原文:https://towardsdatascience.com/seeing-the-road-getting-started-with-self-driving-cars-31cbc68d290a?source=collection_archive---------6-----------------------

在一个奇怪的虐待狂事件中,我决定一头扎进自动驾驶汽车,把人工智能作为一个副业。有一家咨询公司,一个蹒跚学步的孩子,几乎没有空闲时间,我想,“顺便上些课程?这真是个好主意!”[1] .至少,也许我可以解开一些技术之谜

在参加自驾课程的过程中,我经常与人谈论这项技术。我在与人们谈论自动驾驶汽车时发现,大多数人要么对当前的技术水平感到惊讶,要么感到震惊。这是很自然的反应。驾驶已经成为如此明显的人类努力,以至于大多数人不可能理解计算机可以在很少或没有驾驶员错误的情况下在更高的程度上执行这项任务。或者他们认为自动驾驶汽车还很遥远,他们不必担心。

但是,低估计算机的能力并不是驾驶所独有的。在我年轻的时候,作为一个无耻的糟糕棋手,我崇拜大师们的激情和强度。用“创造性、侵略性、不屈不挠”这样的术语来说,卡斯帕罗夫确实是 1997 年在一系列电视比赛中倒下之前的最后几位大师之一。这成了国际象棋中计算机算法的转折点,他们没有回头。如今,即使是一款 20 美元的普通游戏,的等级也比的特级大师高。象棋是人类能力巅峰的时代迅速陨落,并且没有回头。

Even if you didn’t like chess you have to admire that soundtrack

同样,自动驾驶汽车将在更短的时间内超越人类的能力。这很好,因为我无法想象教我女儿开车的压力。

计算机视觉

人类司机没有太多的传感器来工作,但他们有一个出色的视觉系统。驾驶是为配合它而量身定做的。交通标志、车道标志和转向灯(甚至在宝马上)为在环境中导航提供了线索。但是看到一些东西并不等同于理解它的背景。我们可以看到道路标记,但理解它们的含义完全不同。对于计算机来说,驾驶的感知部分是复杂的(大多数司机也是如此,认真看路),大多数人认为这是人类擅长的地方。如果自动驾驶汽车要在路上行驶,他们不仅需要看到道路,还需要理解这些标记背后的背景。

自动驾驶汽车的计算机视觉技术现在反映了我们对人类视觉的了解(或猜测)。眼睛在视锥细胞中执行一系列图像转换,提取颜色、线条和图案,并将这些信息传递给大脑进行处理。它从不捕捉整个图像,而是简单地聚焦不同的区域来寻找模式。这就是为什么你可以数球的移动,却看不到大猩猩。

NVIDIA 和其他公司已经采用了这个概念,并将其集成在一个学习算法中,称为卷积神经网络 (CNN)。CNN 是机器视觉中的一个重要工具,并且已经被证明在大量的计算机视觉领域中是有效的。在驾驶中,我们希望专注于道路上的视觉指示器,CNN 可以通过简单地用驾驶视频训练它来识别道路特征。

End to End Learning for Self-Driving Cars, NVIDIA, https://arxiv.org/pdf/1604.07316v1.pdf

NVIDIAs 的实现甚至走得更远,教汽车仅使用摄像头视觉导航道路。如果你认为这种类型的技术仅限于拥有巨额研究预算的大大学或公司,这里有一个应用于模拟课程的相同技术,作为 3 个月自动驾驶课程的一小部分;

应用于自动驾驶汽车的计算机视觉领域还很遥远。与谷歌、宝马、奔驰和几乎所有其他汽车制造商在计算机视觉方面所做的工作相比,这里甚至连概念都是初级的。

也许我们需要一个人对机器车的挑战…

[1]如果你熟悉他们的话,我正在参加 Udacity 的几个纳米学位项目,专门研究人工智能和自动驾驶汽车。它们是对该领域的很好的介绍,并吸引了一些顶级的行业人员。它们涵盖了大量的信息,有时感觉就像从消防水管里喝水一样。

分割、定位和计数图像中的对象实例

原文:https://towardsdatascience.com/segmenting-localizing-and-counting-object-instances-in-an-image-878805fef7fc?source=collection_archive---------0-----------------------

当我们视觉感知世界时,可能会获得大量的数据。如果你用现代相机拍一张照片,它会有超过 400 万像素和几兆字节的数据。

但实际上,在一张照片或一个场景中,我们人类消耗的有趣数据很少。这取决于任务,但例如在一个场景中,我们寻找其他动物和人类,他们的位置,他们的行动。我们可能会通过寻找面孔来衡量情绪,或者行动的强度和严重性来了解整个场景中的情况。

开车时,我们会寻找可通行的道路、其他车辆、行人和移动物体的行为,并注意交通标志、灯光和道路标记。

在大多数情况下,我们会寻找一些物体,它们的 x,y,z 位置,并拒绝绝大多数我们称之为背景的东西。背景是我们的任务不需要注意的任何东西。如果我们在找钥匙,人们可以做背景。

有时我们也需要数数,并且能够说出一种物体有多少,它们在哪里。

在大多数情况下,我们观察一个场景,并希望获得以下信息:

Ideal segmentation, localization and instance counting in a visual scene. Segmentation gives precise boundaries of object instances, a much more refined approach that bounding boxes.

我们可能还想在第二次扫视时获得更多的细节信息,例如面部关键点、人体骨骼关键点的位置等等。一个例子:

Our facial keypoints detector neural network in action

我们现在将回顾如何通过神经网络和深度学习算法来实现这一点。

我们应该明白,人类的视觉在视觉场景中是多次传递的。这意味着我们递归地观察波形中的视觉场景,首先在最短的时间内获得最粗糙的内容,对于时间敏感的任务。然后,我们可能会一遍又一遍地扫视,以找到越来越多的细节,用于精确的任务。例如,在驾驶情况下,我们想知道我们是否在路上,是否有障碍物。为了快速响应,我们着眼于粗略的特征。我们对将要撞上的车的颜色或牌子/型号不感兴趣。我们只需要快速刹车。但如果我们在人群中寻找特定的人,我们会先找到人,然后找到他们的脸,然后用多种眼神研究他们的脸。

神经网络不需要遵循人脑的规则和方式,但通常在算法的第一次迭代中这样做是一个好主意。

现在,如果你运行一个神经网络来对一幅大图像中的物体进行分类,你会在输出端得到几幅地图。这些地图包含物体在多个位置出现的概率。但是因为分类神经网络想要将大量的像素减少到少量的数据(分类),所以它们也在某种程度上失去了精确定位对象实例的能力。请参见下面的示例:

Neural network raw output on a large image: probability of person category

请注意,您得到的输出是“免费的”,这意味着我们确实需要运行除神经网络之外的任何其他算法来找到定位概率。输出图的分辨率通常较低,并且取决于神经网络、其输入训练眼大小和输入图像大小。通常这是粗糙的,但是对于许多任务来说这已经足够了。这不能给你所有对象的精确实例分割和精确的边界。

为了获得最精确的边界,我们使用分割神经网络,例如我们的 LinkNet ,这里修改了来检测许多不同种类的图像关键点和边界框。:

Our Generative Ladder Network used to detect key-points in an image (facial, bounding boxes, body pose, etc…). This uses a special new network architecture designed for maximum efficiency.

这些类型的神经网络是生成梯形网络,它使用编码器作为分类网络和解码器,能够在输入图像平面上提供精确的定位和图像分割。

这种网络为同时识别、分类和定位任何种类的对象提供了最佳性能。

以下是我们可以用生成式梯形网络获得的结果:

Typical results obtained with LinkNet and Generative Ladder Networks — see videos [here](https://codeac29.github.io/projects/linknet/index.html\)

生成梯形网络的计算量不是很大,因为编码器是一个标准的神经网络,可以设计成高效的,像 eNetLinkNet 。解码器是一个上采样神经网络,它可以被制造得非常快并且计算成本低廉,例如在 eNet 中,或者使用像 LinkNet 这样的旁路层来提高精度。

旁路层用于通知每层的解码器如何在多个尺度上聚集特征,以实现更好的场景分割。由于编码器层对某些层中的图像数据进行下采样,因此编码器必须根据编码器中发现的特征对每层的神经图进行上采样。

我们多年来一直在争论和论证**LinkNet**为分类、精确定位和切分提供了主干。分割在图像中提供了更精细的定位,也为神经网络提供了更好的训练示例。原因是精确的边界比不精确的边界(如边界框)更有效地将对象组合在一起。显而易见,一个边界框将包含许多背景或其他类别的像素。用这样的错误标签训练神经网络会降低网络的分类能力,因为背景信息会混淆其训练。我们建议不要使用边界框。

在过去,文献中充斥着使用边界框的方法,对神经网络的使用效率非常低,甚至对它们的工作方式和使用方式的理解也很差。次优方法列表在这里: YoloSSD 单拍多盒检测器R-CNN 。对这些劣质方法的回顾和比较是这里是 —我们注意到 SSD 是唯一一种至少尝试使用神经网络作为尺度金字塔来回归边界框的方法。

这些方法不合格的原因列表:

  • 使用低效编码器作为 VGG
  • 使用边界框进行训练比使用更精确的分割标签产生更差的准确性
  • 复杂的体系结构,有些不能通过端到端的反向传播来训练
  • 边界框的选择性搜索、边界框的裁剪和回归并不是一种优雅的端到端方法,而是让人想起在深度神经网络之前执行计算机视觉的方式:作为不同方法的任意集合
  • 需要一个单独的“客观”网络来查找区域建议
  • 在多个尺度上使用低效且庞大的分类器来回归边界框

最近的工作来自:密集物体检测的焦点损失更有见地,因为它表明生成梯形网络可以被视为基本框架,该框架应该驱动未来的神经网络设计,例如分类、定位(参见注释 1)。

但是我们如何使用像 LinkNet 这样的网络来执行包围盒回归、关键点检测和实例计数呢?这可以通过在每个解码器层的输出端附加子网来实现,如这里的和这里的所做的那样。这些子网需要最少网络和小分类器来快速有效地工作。这些网络的设计需要由有经验的神经网络架构工程师来执行。请看我们最近的工作在这里,我们展示了一个像 LinkNet 这样的单一神经网络是如何执行所有提到的任务的。

总结:

  • 不要使用边界框(注 3)
  • 使用生成梯形网络作为主神经网络(注 1)——参见此处
  • 添加分支以定位、分割和查找关键点
  • 使用高效的编码器架构(注 4)
  • 不要使用这些网络来执行动作识别和分类(注 2)

****注 1:最近的一篇关于定位、分割和实例级视觉识别方法的教程也指出,像 LinkNet 这样的模型是对象检测的通用框架。他们称生成梯形网络为:特征金字塔网络(FPN)。他们认识到生成式梯形网络具有编码器下采样内置的内在比例金字塔。他们还认识到,解码器可以对图像进行上采样,以更好地定位、分割和完成更多任务。

注 2: 试图从单一图像中识别动作并不是一个好主意。动作生活在视频空间中。图像可以让你了解一个动作,因为它可以识别一个与动作相关的关键帧,但它不能代替准确分类动作所需的序列学习。不要在单个帧上使用这些技术来分类动作。你不会得到准确的结果。使用基于视频的神经网络,如 CortexNet类似的

注 3: 分割标签比包围盒更费力获得。用粗略的边界框来标记图像更容易,以便手动精确地绘制所有对象的轮廓。这是像包围盒这样的劣质技术长期存在的一个原因,这是由越来越多的具有包围盒的大型数据集的可用性决定的。但最近有一些技术可以帮助分割图像,尽管可能不如人类标记精确,但至少可以自动分割大量图像。参见作品(通过观察物体移动学习特征)和作为参考。

注 4:**生成式梯形网络的编码器网络需要高效设计,以实现实际应用中的真实性能。人们不能使用花费 1 秒来处理一帧的分段神经网络。然而,文献中的大多数结果只关注于获得最佳的精度。我们认为最好的度量是准确性/推理时间,正如这里所报告的。这是我们 eNetLinkNet 的关键设计。一些论文仍然使用 VGG 作为输入网络,这是迄今为止效率最低的模型。

关于作者

我在硬件和软件方面都有将近 20 年的神经网络经验(一个罕见的组合)。在这里看关于我:媒介网页学者LinkedIn 等等…

宋飞与神经网络:一个关于虚无的博客(第二部分)

原文:https://towardsdatascience.com/seinfeld-with-neural-network-a-blog-about-nothing-part-2-50ac642c705f?source=collection_archive---------10-----------------------

继续我的科学研究所有数据的旅程,我终于进入了深度学习和人工神经网络(ANN)的世界。这个话题绝对是最吸引人的话题之一,但也是我最紧张的话题之一。我的焦虑主要源于这样一个事实,即这个故事的技术和数学方面非常吓人、复杂,对我的舒适区来说太乏味了。然而,在了解到神经网络本质上是一种组合以及通过反向传播迭代调整的权重和偏差的炼金术之后,我的焦虑水平大大降低了,我确信神经网络不仅强大,而且超级酷。

任何优秀的数据科学学生都知道,学习新概念的最佳方式是良好的实践。我决定以我之前关于宋飞的博客为基础,将新概念应用于一个老问题,并测试各种工具的组合来提高我的模型的分类准确性。迷你项目的目标是获得建立神经网络和自然语言处理的经验。

[## 宋飞与 TF-IDF:一个什么都没有的博客

在为我的班级项目分析 OKCupid 约会简介一周后,我想做一些有趣的事情,同时仍然…

towardsdatascience.com](/seinfeld-with-tf-idf-a-blog-about-nothing-1732abcfd773)

之前的模型涉及使用 TF-IDF 对文本进行矢量化,并使用投票分类器来训练机器学习模型,以预测哪个字符说了哪一行。实验取得了 43%的准确率,不算很大。有了人工神经网络及其更好地提取特征的能力,我认为可能值得尝试一种新的模型。

Overview of dialogue distribution for each of the main characters over the 9 seasons. Jerry has significantly more dialogues than the rest of the characters, signaling a class imbalance. https://www.ceros.com/originals/breaking-down-seinfeld/

首先,考虑到 Jerry 的对话和其他演员之间的类别不平衡,我决定只运行来自 George、Elaine 和 Kramer 的对话的模型。下面列出了模型的精度结果。

The model does not perform better with increase epochs, it essentially plateaus at around epoch 2 for this particular model.

83%的训练准确率和 57.05%的低测试准确率表明,该模型对于我正在执行的特定分类来说过于笼统,并且该模型不适合该任务。使用带有计数矢量化的新矢量化,对超参数进行一些调整,并添加正则化,结果仍然暗淡无光。

考虑到我随机猜测的基线是 33.33%,之前模型的准确率是 48%,模型的测试准确率 57.83%可能不显著,但它仍然比随机猜测要好。

A slight increase in test data accuracy and epoch numbers. An increase in epoch number will increase my training accuracy, however, the tradeoff struggles with the long training time.

最后,我决定让杰瑞回来。这需要额外的调整来适应类的不平衡,结果见下文。

With Jerry added back to the mix, the accuracy is slightly lower as I expected, however, it still outperforms the previous model.

49.92%的准确率并不令人印象深刻,但这是使用浅层学习模型或 4 个类别之间随机猜测的 25%基线的 43%的改进。相对而言,我对我训练的模型并不那么失望,但是,我对它的表现也不是特别满意。

由于神经网络更擅长提取人类语言中的特征,因此它通常是用于自然语言处理的更有效的模型。然而,由于语言在与上下文相关联时是有意义的,所以我喜欢尝试的另一种方法是 Word2Vec。Word2Vec 被认为是更好的矢量化/嵌入方法,可以更好地处理语言数据。

[## 单词的矢量表示|张量流

目标是对嵌入参数(\theta)进行更新,以改进(在这种情况下,最大化)这个目标…

www.tensorflow.org](https://www.tensorflow.org/tutorials/representation/word2vec)

对于诸如语音识别之类的任务,成功执行识别任务需要编码数据,因为人类的认知能力允许我们从原始文本中识别含义,而计算机从稀疏矩阵中辨别矢量化文本的上下文具有挑战性,因为传统的自然语言处理系统将单词视为离散元素。因此,使用 TF-IDF 和 CountVectorization,正如我对我的模型所做的那样,计算机在识别语言模式和字符的区别方面面临着挑战。

我这个迷你项目的下一步是尝试不同的矢量化技术,结合不同的机器学习模型(监督或无监督),以便比较和对比每个模型的结果性能。即使我还没有完全用尽我的机器学习工具包,随着更多的时间和更多的练习,我可能能够将这些野生神经网络计算成一个足够的分类模型,以区分彼此的字符。

使用 Seinfeld 脚本帮助我了解了许多关于每个机器学习模型的细微差别以及使用自然语言处理的挑战。

资源:

[## 宋飞编年史

完整的宋飞正传剧本和剧集细节

www.kaggle.com](https://www.kaggle.com/thec03u5/seinfeld-chronicles)

宋飞与 TF-IDF:一个什么都没有的博客

原文:https://towardsdatascience.com/seinfeld-with-tf-idf-a-blog-about-nothing-1732abcfd773?source=collection_archive---------11-----------------------

在为我的班级项目分析了 OKCupid 约会简介一周之后,我想做一些有趣的事情,同时还得到了一些急需的单词矢量化练习,TF-IDF ( 术语频率,逆文档频率)。

由于我最近没怎么看电视,探索经典情景喜剧《宋飞正传》中的这个数据集似乎是一个有趣的想法,我将尝试预测哪个角色说了哪句台词。

TF-IDF 是一种矢量化形式,它根据术语在样本中的独特程度对样本中的每个术语进行加权。基本上,这种方法有助于提取与特定来源密切相关的关键词。将 TF-IDF 的概念应用到我的《宋飞正传》挑战中:如果一个单词被角色经常使用,那么这个单词不够独特,不足以帮助指示哪个角色说了那个对话;另一方面,如果一个单词经常被其中一个角色提及,但很少被其他角色提及,这个单词就成为了一个强有力的指示器,告诉我们是哪个角色说了这句话。

为了缩小数据集的范围以优化效率,我根据每个角色说出的行数选择了主要角色,并挑选了前 5 个角色进行处理。此外,为了找出剧中哪个角色说了最多的话,下图显示了杰瑞在所有角色中拥有最多的台词和最多的单词...这个节目是以他的名字命名的,所以这并不奇怪。

number of dialogues for each of the main characters

number of words spoken by each of the characters

知道 Jerry 说了大部分台词,我意识到单词 predictor 将受到这种限制的挑战。因为大多数台词是杰瑞说的,所以数据集在他的对话上有很大权重。此外,作为该剧的编剧和制片人,他的声音可能会渗透到其他角色的对话中。如下面我们的 TF-IDF 分类模型的摘要所示,在数据集中包括 Jerry 的对话时,我们的精度是 43%,而没有 Jerry 的对话时,我们的精度是 48%。精确度比我预期的要低。

Prediction model without Jerry

Prediction model with Jerry

为了更好地理解角色之间的对话有多相似,我使用了一个名为 g ensim 的语义库,由 Kaggle Kernal 提出,它有一个相似性方法,能够确定特定文档和一组其他文档之间的相似程度。通过使用 TF-IDF 为每个角色的对话转换一个单词包,用单词计数作为每个单词的权重,我能够对 gensim 库中的文本运行相似性查询。下图显示了一个字符的对话分数,作为与每个文档进行比较的查询向量。相似性得分范围从 0 到 1,0 表示不相似,1 表示非常相似。

visualization of how similar each of the characters’ corpus in relation to another.

图表证实了我的怀疑,杰瑞、乔治、伊莱恩和克莱默非常相似。乔治和杰瑞的对话是最相似的,这也解释了为什么这两个人是最好的朋友。人物对话相似性的可视化是数据集局限性的另一个解释。因为主要角色所讲的语言非常相似,所以预测模型无法检测角色对话之间的细微差别。

我不愿意放弃享受数据集的乐趣,所以我探索了用预测工具娱乐自己的其他方式。考虑到这部剧是由杰瑞·宋飞和拉里·戴维共同编剧/制作的,我想看看这个模型是否能够预测拉里和剧中其他主要角色之间的差异。

这个结果并没有让我吃惊。由于拉里是这部剧的原创作者之一,他的声音和乔治的声音一定非常相似。为了好玩,我测试了拉里在《抑制你的热情》中最著名的几段话,看看这个模型的表现如何。拉里更像乔治还是杰瑞?

参与这项挑战给了我一些使用 TF-IDF 作为语言预测工具的实践,同时,我也有机会学习 gensim 的功能,并从预测模型中获得一些乐趣。我很想知道如果我用《抑制你的热情》中的对话训练模型,该模型是否能够区分宋飞和拉里的声音。此外,我很好奇这个模型在真实的文本样本中是否会有更好的性能,在真实的文本样本中,声音的作者不是由房间中真正有趣的作者创建的。

测绘世界各地的地震活动

原文:https://towardsdatascience.com/seismic-activities-around-the-world-976dbf759e54?source=collection_archive---------4-----------------------

自 1965 年以来,全球平均每年发生 441 次 5.5 级以上地震。5.5-6.0 的震级可能会造成轻微的破坏,而 6.1 或更高的震级可能会在人口密集的地区造成重大破坏。

Magnitude 6.1 or over

来自国家地震信息中心(NEIC)的数据集包含地震的日期时间、坐标、震级和类型(并非所有地震都是由自然引起的,少数是由 20 世纪 60-90 年代的核弹引起的地震活动)。)

当观察重大地震时,我们可以看到东亚和东南亚的高度集中,尤其是印度尼西亚。

Magnitude 5.5–6.0

可视化这些不太重要的地震给了我们一个“火环”的清晰视图,这是一个位于太平洋盆地的地震带。

除了自然灾害之外,研究由核弹引起的地震也是值得的。

seismic activity from nuclear bombs in 1960s-1990s. Icon from http://www.flaticon.com/free-icon/radiation_195741#term=radioactivity&page=1&position=20

试验的可怕核弹的数量简直让我吃惊。由于数据只涵盖到 1965 年,那些早期的活动,如广岛不包括在内。

我今天学到的:

  • 传单地图很酷,但fleet . extras包只是增加了这种酷炫感,有像 addWebGLHeatmap 和 addDrawToolBar 这样的功能。
  • 有几种方法可以将地理坐标映射到国家。但是,对于该数据集,许多数据点位于海洋中,不会映射到国家。

这是我第 100 天项目的第 11 天。我的 github 上的全部代码。感谢阅读。

不要害怕人工智能的孩子:人工智能面临的紧迫挑战的优先列表

原文:https://towardsdatascience.com/select-from-ai-threats-order-by-danger-desc-68fcd3010432?source=collection_archive---------7-----------------------

最近,我在 LinkedIn 上目睹了两位从事人工智能工作的专业人士之间的对话——尽管他们都不是技术人员。这次对话是关于谷歌的 AutoML ,这是一个可以自动优化自身以在给定任务中实现更好性能的系统。悲剧源于谷歌研究博客使用的措辞:文章称两个网络控制器和一个孩子。然后文章继续解释人工智能设计可以超越人类制造的。

不用说,孩子这个词已经引起了轻微的恐慌,因为它已经被几家主流 媒体媒体报道,如太阳报类似的。这种恐慌源于“人工智能创造出超越人类的孩子”的框架,但这种不准确往往是因为人工智能研究人员和人工智能实践者不参与这些辩论。使用“孩子”这样的术语,并将这个网络的输出描述为比人类设计的更聪明,肯定会成为一些头条新闻。然而,将所发生的描述为“算法使用一组预定义的规则来实现稍好的性能”并不可怕,但可能更准确。

上面的例子比其他任何事情都有趣,但我认为它展示了一个更深层次的观点,即人工智能的讨论可能会偏离未来几年真正关注的问题。

尽管我很欣赏公众对人工智能安全的兴趣,但对人工智能技术经验和理解有限的人的兴趣最终导致了对辩论的重新构建,我认为这对最终目标毫无帮助,甚至是有害的。

作为一名人工智能从业者,即将在生成对抗网络上发布一个教育资源,我觉得有必要以我所看到的方式来框定这场讨论。毫无疑问,会有主观的判断,但鉴于讨论的状态,我觉得这仍然是一个重要的贡献。

我将从最有争议的部分开始:与谷歌的员工研究员、最受欢迎的深度学习框架之一的作者 Francois Chollet 一致,我认为人工通用智能仍然非常遥远。因此,对超级智能的担忧也许并非无关紧要,但绝对不紧迫。

应用历史学家和人工智能研究人员长期以来一直在谈论这种智能爆炸的想法。我不完全确定这种推理应该归功于谁,但我第一次从在牛津马丁学院讲课的乔安娜·布赖森博士那里听说了这一点。这个讲座很棒,你绝对应该听一听,但要点是:最终担心人工智能爆炸是没有意义的。人工智能将通过增加恶意的人类行为者并帮助他们达到规模来造成更多的破坏。

直觉上这是有道理的:和核武器一样,人工智能最终只是一项技术,它取决于人类将如何使用它。这再加上事实上大多数人工智能是一些人所谓的“白痴学者”,因此在偏离原始任务的微小情况下都会灾难性地失败,这让我们得出一个不可避免的结论,即摧毁人类的超级智能不太可能成为“未来几十年”的担忧。

那么,在我看来,有什么值得担心的呢?

  1. 俄罗斯或其他民族国家被 AI 增强

这个列表中的第一个是我们已经见过的。除非在未来,仅仅通过应用现有的企业技术,这可以变得更加可扩展,因此也更加危险。更不用说中国将投资 1500 亿美元到 AI 。(不过,公平地说,与俄罗斯相比,中国对参与经合组织成员国政治的兴趣要小得多。)

混合战争对民族国家的网络攻击对核计划的网络破坏的时代,我们面临着世界上许多理论上完全无法追踪的问题。越来越多的关于俄罗斯干预美国选举结果的指控当然于事无补。更糟糕的是,对世界上最强大的民主国家进行这样一次根本性的攻击据称花费了一架 F-35 战斗机花费的四分之一

如果你在世界上的任何地方,认为美国的衰落对你没有任何意义,请三思。不仅有证据表明俄罗斯通过使用大型复杂的 Twitter 机器人网络试图在英国社会制造不和来干涉英国退出欧盟的投票,还有证据表明俄罗斯干涉了荷兰、德国、法国和英国的选举。

现在,如果这没有吓到你,还有大量证据表明,剑桥分析公司(Cambridge analytic a)——罗伯特·默瑟和其他影子人物资助的组织——正在提升其使用数据分析和人工智能影响美国和英国人口的能力

最后,如果你研究这些人工智能增强的试图挑起不和的动态,它们会跨越围栏两边每个预先存在的社会鸿沟。例如,外国机器人在美国被检测到既支持 NFL 球员又反对他们,批评特朗普又支持他,还利用性别、性和身份问题进一步分裂美国社会。

不要误解我的意思,所有这些在原则上都是可以解决的,主要还是由人工智能来解决,但目前无论是科技公司还是政府都没有付出足够的努力来真正解决这些问题。即使你相信这些关于的段落只是一些疯狂的阴谋论,你也必须承认这至少是可信的,而且我们目前没有任何适当的监控来防止这种情况。

2。人工智能破坏社会结构

记住,平均每个人每天查看手机 150 次,想想这对社交能力有什么影响。此外,对于我们的孩子来说,完美的顺从技术在如何与世界尤其是其他人互动方面是一个非常糟糕的心理模型。毫无疑问:你今天购买的软件和硬件产品都装载了人工智能,它不断学习如何抓住你的注意力。

这还没提到在脸书上花太多时间会让我们不那么快乐;愤怒和愤慨推动了脸书的大部分互动,因为那些非法的高回复率;对自动化日益逼近的恐惧让许多人更加焦虑,也让他们的工作变得更加公平。这甚至还没有深入到在线回音室的问题中,这是一个巨大的问题,正如链接的文章所描述的

此外,当你想到人类巨人及其最先进的智能产品:企业时,我们陷入了另一个泥潭。这条推文总结得很好:“非常令人惊讶的是,人们立即看到了“如果人工智能被设计成不惜一切代价制造曲别针会怎么样”的问题,但没有看到“我们将围绕一个机械的社会过程来设计我们的整个社会,以最大化短期资本增长”的危险信号。公司是原始的超级智能,因为它们聚合了几十个人的知识来追求一个目标。

目前的解决方案肯定是思考你花在技术上的所有时间是否都是值得的,从长远来看,开始考虑自动化和普遍基本收入的心理影响。

3。人工智能增强的非国家行为者

第三个角度与民族国家或公司的关系要小得多,与独立的个人或个人团体如何行动的关系要大得多。我将只给你一瞥我的意思,因为我相信这一个是不紧急的,我们将继续缩短与降低重要性。

另外,我已经解释过了,很多熊都有一个类似于民族国家的例子,除了现在,或者用更少的资源处理更分散的群体。但是人们只是在考虑安全后果和自主武器。

我普遍认为,各国将能够通过联合国或其他方式进行协调,或许禁止发展,但最有可能的是使用自主武器技术。然而,我不相信非国家行为者会在涉及到笑机器人和类似的问题时坚持同样的标准。

这已经在小范围内发生了;像“匿名者”这样的组织和像“丝绸之路”这样的平台已经证明了政府没有能力处理超出其范围的行为者。尤其是如果他们的东道国政府不合作的话。因此,我们可能不得不应对网络恐怖主义、规模空前的黑客以及来自非国家行为者的自动化政治宣传。

4。超级智能

最初,我想把超级智能放在第五位,但后来我的几个朋友在谷歌 Deepmind 安全团队的影响下说服了我。我不会争论超级智能的时机;关于这个话题,其他人已经写了很多。

我只想说,有许多研究人员认为,即使我们很快实现奇点,对世界的影响也是有限的。说来有趣,想想你高中班上最聪明的孩子。他们走了多远?他们的智力帮了他们这么大的忙吗?事实上,当我们考虑到在优化中没有免费的午餐时,是否有可能构建一个一致的更智能的方法?

也许这里的论点是,人工智能的增长是指数级的,因此进化的人工智能对于人类来说就像人对于马一样。马永远不会成为发明家。所以它在数量上要好得多,在质量上也不同。然而,这一点我也有异议,因为人们通常在没有太多正当理由的情况下将生物系统作为人工智能的明显类比。AI 的成长不像一个人从孩童到成人的成长。人工智能可以以超人的表现解决许多问题,但看似类似的问题实际上是不可能的。

此外,尽管有理由认为超级智能可能有能力伤害人类,但请记住,尽管投资了数十亿美元,Siri 仍然几乎不明白你的意思。比方说,我们必须在明年(非常乐观)完成语音合成中的语音识别,并在两年后实现量产。在接下来的五年里,我们解决了感知问题,在那之后的五年里,我们解决了无监督理解问题,在那之后的十年里,我们解决了常识推理问题。但是以上所有(1-3)都是现在有可能发生的事情。看起来还那么紧急吗?

但总的来说,我很乐意向任何人提出这个挑战:你怎么能想象超级智能会毁灭人类?为什么它会在乎呢?

5。AI 只是犯错或者偷工减料

这两个问题是紧密相通的,因为我不相信有人想写会出错的 AI。但是正如我所说,这一点非常接近第五名。最终我相信,即使我们到达奇点,我们也不知道这是否完全有目的,这种可能性是 50%。事实上,我们仍然没有真正理解为什么深度学习完全有效。

最终,人工智能研究人员和实践者将受到来自他们的经理、赞助商或其他利益相关者的压力,因此被迫走捷径。公平地说,对于公众辩论,我认为这是传播意识——无论多么初级——极其有用的一点。

因此,总的来说,尽管人工智能安全看起来像是一个有趣的问题,许多哲学家已经等待了很长时间,但我们应该避免通过它的叙述来判断这项技术。至少目前是这样。

写这篇文章花了我大约 2 天的时间。在这个时候,最初的故事又发生了,在我看来,这只是表明那些流行的误解是多么频繁。

想加入对话吗?查看更多 attweet at meat @ langrjakub!我也正在写一本关于 生成对抗网络 (人工智能新的最令人兴奋的领域之一)的书,你可以 查看这里 。如果您速度很快,在结账时使用促销代码“mllangr”仍然可以享受 50%的折扣(持续到 7 月 26 日)。

(我为标题的变化道歉,但文章的原名称是“选自丹吉·desc 的 ai_threats ORDER ”,尽管我无法想象还有比 SQL 查询更令人兴奋的事情,但我认为这恰恰分散了我最想吸引的读者群。)

为您的回归问题选择最佳的机器学习算法

原文:https://towardsdatascience.com/selecting-the-best-machine-learning-algorithm-for-your-regression-problem-20c330bad4ef?source=collection_archive---------1-----------------------

想获得灵感?快来加入我的 超级行情快讯 。😎

当处理任何类型的机器学习(ML)问题时,有许多不同的算法可供选择。在机器学习中,有一个叫做“没有免费的午餐”的定理,它基本上说明了没有一种最大似然算法对所有问题都是最好的。不同 ML 算法的性能很大程度上取决于数据的大小和结构。因此,除非我们通过简单的试错法直接测试我们的算法,否则算法的正确选择通常是不清楚的。

但是,每个 ML 算法都有一些优点和缺点,我们可以用它们作为指导。虽然一种算法并不总是比另一种算法更好,但是每种算法都有一些特性,我们可以用它们来指导快速选择正确的算法和调整超参数。我们将看看一些用于回归问题的著名的最大似然算法,并根据它们的优缺点设定何时使用它们的准则。这篇文章将有助于为你的回归问题选择最好的 ML 算法!

在我们开始之前,请查看 人工智能快讯 以阅读人工智能、机器学习和数据科学方面的最新和最棒的信息!

线性和多项式回归

Linear Regression

从简单的例子开始,单变量线性回归是一种使用线性模型(即直线)对单个输入自变量(特征变量)和输出因变量之间的关系进行建模的技术。更一般的情况是多变量线性回归,其中为多个独立输入变量(特征变量)和一个输出因变量之间的关系创建模型。该模型保持线性,因为输出是输入变量的线性组合。

还有第三种最常见的情况,称为多项式回归,其中模型现在变成特征变量的非线性组合,即可能有指数变量、正弦和余弦等。然而,这需要了解数据与输出之间的关系。可以使用随机梯度下降(SGD)来训练回归模型。

优点:

  • 建模速度快,并且当要建模的关系不是非常复杂并且您没有大量数据时特别有用。
  • 线性回归很容易理解,对商业决策非常有价值。

缺点:

  • 对于非线性数据,多项式回归的设计可能相当具有挑战性,因为必须有一些关于数据结构和特征变量之间关系的信息。
  • 由于上述原因,当涉及到高度复杂的数据时,这些模型不如其他模型好。

神经网络

Neural Network

神经网络由称为神经元的一组相互连接的节点组成。来自数据的输入特征变量作为多变量线性组合传递给这些神经元,其中乘以每个特征变量的值称为权重。然后将非线性应用于该线性组合,这赋予神经网络模拟复杂非线性关系的能力。神经网络可以有多层,其中一层的输出以相同的方式传递到下一层。在输出端,通常没有应用非线性。使用随机梯度下降(SGD)和反向传播算法(都显示在上面的 GIF 中)来训练神经网络。

优点:

  • 由于神经网络可以有许多非线性层(和参数),它们在模拟高度复杂的非线性关系时非常有效。
  • 我们一般不用担心数据的结构,神经网络在学习几乎任何一种特征变量关系时都非常灵活。
  • 研究一直表明,简单地给网络提供更多的训练数据,无论是全新的还是增加原始数据集,都有利于网络性能。

缺点:

  • 由于这些模型的复杂性,它们不容易解释和理解。
  • 它们的训练可能非常具有挑战性和计算强度,需要仔细的超参数调整和学习率时间表的设置。
  • 它们需要大量数据来实现高性能,并且在“小数据”情况下通常优于其他 ML 算法。

回归树和随机森林

Random Forest

从基本情况开始,决策树是一种直观的模型,通过它可以遍历树的分支,并根据节点上的决策选择下一个分支。树归纳的任务是将一组训练实例作为输入,决定哪些属性最适合拆分,拆分数据集,并在生成的拆分数据集上重复,直到所有训练实例都被分类。在构建树时,目标是在属性上进行分割,以创建尽可能最纯粹的子节点,这将使分类数据集中的所有实例所需的分割数量保持最小。纯度是通过信息增益的概念来衡量的,信息增益与需要知道多少关于一个以前未见过的实例的信息以便对其进行正确分类有关。实际上,这是通过将熵(或对当前数据集分区的单个实例进行分类所需的信息量)与对单个实例进行分类所需的信息量(如果当前数据集分区将在给定属性上进一步分区)进行比较来测量的。

随机森林只是决策树的集合。输入向量在多个决策树中运行。对于回归,所有树的输出值被平均;对于分类,使用投票方案来确定最终类别。

优点:

  • 擅长学习复杂、高度非线性的关系。它们通常可以实现相当高的性能,比多项式回归更好,通常与神经网络不相上下。
  • 非常容易解释和理解。虽然最终训练的模型可以学习复杂的关系,但在训练期间建立的决策界限易于理解且实用。

缺点:

  • 由于训练决策树的性质,它们很容易过度拟合。完整的决策树模型可能过于复杂,并且包含不必要的结构。虽然这有时可以通过适当的树木修剪和更大的随机森林集合来缓解。
  • 使用更大的随机森林集合来实现更高的性能会带来速度更慢和需要更多内存的缺点。

结论

嘣!有你的利弊!在下一篇文章中,我们将看看不同分类模型的优缺点。我希望你喜欢这篇文章,并学到一些新的有用的东西。如果你看到了,请随意鼓掌。

自动驾驶汽车——我们应该因为黑客而扣上安全带吗?

原文:https://towardsdatascience.com/self-driving-cars-should-we-buckle-up-because-of-hackers-9faee2940500?source=collection_archive---------7-----------------------

保护 CAN 总线和避开传感器欺骗是迈向 5 级自治的一部分。

Freakout level as a new technology navigates the hype cycle

自从第一个网络摄像头出现以来,我们已经看到了大量联网设备出错的轶事。消费和工业物联网的滚雪球扩大了可能被恶意攻击的设备的数量。黑客已经控制了设备,监视人们,扰乱企业和政府,将数以千计的设备涌入 T2 僵尸网络。这样的例子不胜枚举。

每一项新技术都驱使坏人花费时间和精力去寻找利用他人的方法。物联网技术是一个大目标:智能助理、联网家庭、医疗保健设备、交通系统、制造传感器等。

物联网安全是一个热门话题,大玩家都知道。最近,芯片制造商 ARM 宣布了平台安全架构(PSA) ,这是一项针对开发者、硬件和芯片提供商的行业标准提案。Standard schmstandard ,但是微软、谷歌、思科、Sprint 和其他公司都支持它,所以谁知道呢?

汽车黑客和自动驾驶技术

对物联网安全的普遍担忧促使技术和主流媒体产生点击诱饵和耸人听闻的新闻。毫不奇怪,自动驾驶技术现在也出现了同样的情况。

CAN 总线和汽车黑客

控制器局域网(CAN)总线是由博世和英特尔于 1983 年开发的标准,其当前版本于 20 世纪 90 年代发布。CAN 是一种串行通信协议,允许在车辆部件(如制动器)之间进行分布式实时通信和控制👀,动力转向🙀、窗户、空调、安全气囊、巡航控制、信息娱乐系统、车门、电动汽车的电池和充电系统等。

通过对 CAN 总线进行逆向工程,我们能够通过软件向车辆发出命令。所以控制一辆车就是访问 CAN 总线。因为它的主要焦点是安全性和可靠性,所以它从未提供任何加强安全性的方法——例如,通过认证或加密。

汽车黑客手册是向任何人介绍这些部件的“圣经”。这本书研究脆弱性;详细解释了 CAN 总线上以及设备和系统之间的通信。

自动驾驶

自动驾驶车辆将给我们的生活带来实质性的转变。人工智能、计算机视觉和传感器技术的进步正在将我们推向第五级场景(汽车方向盘是“可选”的,不需要任何人为干预的状态。)

这一切都是由摩尔定律和数十亿美元的资本促成的。

就这样,我们的老朋友 CAN 总线突然变得流行起来。原因是大多数自动驾驶汽车公司不是从零开始设计或制造自己的车辆。他们正在开发控制汽车的软件——更具体地说是控制转向、加速和刹车。查看这里来自 Voyage (一种自动驾驶出租车服务)的工程师如何使用福特嘉年华的 CAN 总线来控制其温度。

根据自动驾驶技术传感器捕获的大量数据,制动、加速或改变转向角度的命令被发送到 CAN 总线。安装的摄像头、雷达和激光雷达是汽车的眼睛和耳朵。粗略地说,十几个传感器混合数据(称为传感器融合)来跟踪车辆环境,本地软件实时做出所有决定。

但是汽车是物联网的一部分吗?

对于自动驾驶技术来说,好消息是每辆车都像一个封闭的系统。不需要持续的云连接到汽车。它们最终将连接到外部世界来发送和接收信息,例如交通报告。仍然存在这样的风险,即与自动驾驶功能无关的另一个系统——如 wi-fi——可能会为黑客提供一个入口。这种黑客行为促使克莱斯勒在 2015 年召回 140 万辆汽车。

传感器欺骗

外部因素可以影响汽车传感器的行为,或者欺骗它的人工智能“认为”它“看到”不同的东西。

许多关于对抗性扰动的论文表明,深度神经网络可以被愚弄来错误分类对象。例如,通过在交通标志上添加伪装成涂鸦艺术的贴纸,软件会将其解释为不同的东西。看下面的视频。

现在有项研究正在进行中,用机器学习模型来对抗这些扰动,这些模型通过训练具有更高抵抗力的网络来保证鲁棒性。

除了摄像头,还有其他已知类型的传感器欺骗。一组中国研究人员成功发起攻击,使用现成的无线电、声音和光工具来欺骗特斯拉的超声波传感器和毫米波雷达,影响其自动驾驶系统。

韩国的另一个小组想出了一种方法( PDF )在路上创造假的物体,这些物体被激光雷达检测到,使汽车锁住刹车以避免撞车。

前方的路

因为我们处理的是乘客和行人的生命,所以安全必须始终是首要考虑的问题。不幸的是,在没有尖端技术的情况下,车辆武器化已经成为现实。大多数黑客攻击相当于临时攻击,比如有人从天桥上向汽车投掷重物。或者类似于将激光指示器瞄准驾驶员的眼睛。

你上一次从高层建筑的顶层乘电梯时担心黑客会让电梯坠落 30 层以上是什么时候?嗯,有人认为自动驾驶汽车就像电梯

变革即将到来,现在的问题是什么时候,而不是如何。所以让我们系好安全带上路吧!

使用深度学习的自动驾驶汽车

原文:https://towardsdatascience.com/self-driving-cars-using-deep-learning-14add64fa8a2?source=collection_archive---------5-----------------------

无人驾驶汽车无疑将成为未来的标准交通方式。从优步和谷歌到丰田和通用汽车的大公司都愿意花费数百万美元来实现它们,因为未来的市场预计价值数万亿美元。在过去的几年里,我们看到了这一领域的巨大发展,优步、特斯拉和 Waymo 的汽车记录中总共有 800 万英里。

当然,由于硬件和软件方面的许多不同技术进步,自动驾驶汽车现在已经成为现实。激光雷达传感器、照相机、全球定位系统、超声波传感器协同工作,从每一个可能的来源接收数据。这些数据使用先进的算法进行实时分析,使自动驾驶功能成为可能。

https://www.technologyreview.com/s/609674/whats-driving-autonomous-vehicles/

形成自动驾驶管道有 5 个基本步骤,顺序如下:

  1. 本地化
  2. 感觉
  3. 预言;预测;预告
  4. 规划
  5. 控制

定位基本上是自动驾驶车辆如何准确地知道它在世界上的位置。在这一步中,他们从所有上述传感器(传感器融合)获得数据,并使用一种称为卡尔曼滤波器的技术以最高的精度找到他们的位置。卡尔曼滤波器是一种概率方法,使用随时间变化的测量值来估计物体的位置状态。另一种广泛使用的技术是粒子过滤器

感知是汽车感知和理解周围环境的方式。这就是计算机视觉和神经网络发挥作用的地方。但稍后会详细介绍。

在预测步骤中,汽车预测周围每个物体(车辆或人)的行为。它们将如何运动,朝哪个方向,以什么速度,沿着什么轨迹运动。这里最常用的模式之一是递归神经网络,因为它可以从过去的行为中学习并预测未来。

路径规划是不言自明的。它是汽车规划路线的地方,或者说是产生轨迹的地方。这是通过搜索算法(如 A* )、点阵规划和强化学习来完成的。

最后,控制工程师从这里接手。他们使用上一步生成的轨迹来相应地改变汽车的转向、加速和刹车。最常见的方法是 PID 控制,但也有一些其他方法,如线性二次调节器(LQR)模型预测控制(MPC)

顺便说一句,如果你想了解更多,请查看 Udacity 免费提供的两门精彩课程:

嗯,我认为现在是我们自己制造自动驾驶汽车的时候了。好吧,不全是。但我们能做的是使用驾驶模拟器,记录下摄像头看到的东西。然后,我们可以将这些帧输入神经网络,希望汽车能够学会如何自己驾驶。让我想想…

我们将使用 Udacity 开源的自动驾驶汽车模拟器。要使用它,你需要安装 Unity 游戏引擎。现在有趣的部分来了:

不言而喻,我花了大约一个小时记录帧。是一些认真工作的人。我不是在鬼混。

无论如何,现在模拟器已经从 3 个不同的角度产生了 1551 帧,还记录了 517 个不同状态下的转向角、速度、油门和刹车。

在 keras 中构建模型之前,我们必须读取数据,并将它们分成训练集和测试集。

之后,我们将建立我们的模型,该模型具有 5 个卷积层、1 个漏失层和 4 个密集层。

网络将只输出一个值,即转向角。

在我们传递模型的输入之前,我们应该做一些预处理。请注意,这是通过 OpenCV 完成的,OpenCV 是一个为图像和视频操作而构建的开源库。

首先,我们必须产生更多数据,我们将通过扩充现有数据来做到这一点。例如,我们可以翻转现有的图像,翻译它们,添加随机阴影或改变它们的亮度。

接下来,我们必须确保裁剪和调整图像大小,以适应我们的网络。

培训时间:

现在我们有了经过训练的模型。它本质上克隆了我们的驾驶行为。让我们看看我们是怎么做的。为此,我们需要一个简单的服务器(socketio server)将模型预测实时发送给模拟器。我不打算谈论太多关于服务器的细节。重要的是我们利用模拟器实时生成的帧和日志来预测转向角度的部分。

结果是:

还不错。一点也不差。

我们真的做到了。我认为 Udacity 的模拟器是开始学习自动驾驶车辆的最简单的方法。

总而言之,自动驾驶汽车已经开始成为主流,毫无疑问,它们比我们大多数人想象的更快变得司空见惯。建造一个非常复杂,因为它需要从传感器到软件的许多不同的组件。但是这里我们只是迈出了非常非常小的第一步。

重要的是未来就在眼前。令人兴奋的是…

如果您有任何想法、评论、问题或者您只想了解我的最新内容,请随时在LinkedinTwitterinsta gramGithub或在我的

原载于 2018 年 9 月 4 日sergioskar . github . io

无人驾驶(非常小)汽车——第一部分

原文:https://towardsdatascience.com/self-driving-very-small-cars-part-i-398cca26f930?source=collection_archive---------4-----------------------

在野外用 Python,蓝牙汽车和多米尼克·托雷托做人工智能。

人工智能与物理世界相遇(在预算之内)

“我是那种欣赏好身材的男孩,不管身材如何。”——多米尼克·托雷托

A 自动驾驶汽车初创公司现在在非常火:即使不考虑通常的嫌疑人(、 WaymoCruise 等)。),有一大堆不太知名、资金相对较少的初创公司正在攻击这个领域(甚至还有一个 Udacity 课程!).这里的关键词是相对:你如何做并不重要,与你的标准 SaaS 公司相比,这只是一个很高的价格(因为像激光雷达这样的酷工具非常昂贵+收集训练/测试数据是一件痛苦的事情)。

为什么这些人要享受所有的乐趣?在我们破烂不堪的车库里,我们就不能做点什么来开始玩耍吗?事实证明,行业中一个常见的举动是使用模拟器,从特设的物理引擎到现成的视频游戏(你也可以在你的浏览器中尝试!).然而,我们在周末的黑客活动中尝试了一些别的东西:我们没有用现实世界来换取对现实世界的模拟,而是选择缩小问题的规模,用一个玩具宇宙来工作。

以前已经强调过玩具的教育(甚至研究)价值:如果你年纪足够大,还记得人工智能时代的美好时光,你可能会想起一只昂贵的索尼狗机器人世界杯球队之类的天堂(有趣的事实:我写的第一个程序运行在一只白蓝相间的艾博上,它现在在好机器狗的天堂里自由自在地游荡)。具体来说,在谈到移动玩具时,荣誉奖当然要归功于车辆,这是由瓦伦蒂诺·布莱滕贝格撰写的一本聪明的书,在书中,简单的车辆展现出越来越复杂的“合成心理学”特征。

在这篇由两部分组成的文章中,我们将建立一个基于 Python 的开发环境来发送/接收赛车上的蓝牙小汽车的信息。由于我们缺钱,但不缺款式,我们将从著名的 Anki Overdrive 赛车套装的速度与激情版开始。

如果你像我们一样生活,一次一个 Git commit,跟随我们一起踏上从零到无人驾驶(非常小)汽车的疯狂旅程。

写这篇文章时,还没有好莱坞名人受到伤害。

免责声明:这是一个有趣的周末项目,绝不是经过深思熟虑的研究声明或生产就绪代码;事实证明,在选定的环境中,有许多真实的汽车无法再现(稍后将详细介绍)。也就是说,我们开始学习蓝牙的东西,更有趣的是,如何在不同的约束下构建人工智能和学习问题,而不是我们习惯的 API 开发的稀薄世界。

请注意,这个帖子的所有代码都免费 在 Github 上提供。

设置

"你刚刚赢得了与魔鬼共舞的机会,孩子。"—卢克·霍布斯

为了开始与卢克和多姆一起玩,我们只需要一条装有蓝牙汽车的赛道和一台可以与它们对话的计算机,这样我们就可以教它如何自动驾驶:

  • 正如预期的那样,我们选择了 Anki Overdrive 作为我们的小尺度物理宇宙。Overdrive 被宣传为“智能战斗赛车系统”,它基本上是你的旧polis til/scale xtric赛道的蓝牙版本。让 Overdrive 对书呆子友好的是,包含与汽车交互的蓝牙协议的 Drive SDK 是开源的(然而,弄清楚汽车通信的具体细节花了我们一段时间:见下文);
  • 就“具有蓝牙功能的计算机”而言,我们选择 Python+node 来通过 noble 实现跨平台兼容性,因此几乎任何东西都应该只需很小的修改,甚至不需要修改。具体来说,我们使用我们的 Rasp Pi 3B+ 在 Linux 上编译和运行原始 C 库,并在大多数实验中使用我们的 2017 MacBook Pro。

没有一个车库项目可以说是完整的,如果没有一张低分辨率的粒状照片——所以这是我们的(这里是原件):

The difference between man and boy is apparently the price of their toys.

愤怒但不要太快:去试驾

首先,让我们测试一下设置:在深入研究 Anki Drive 协议之前,我们检查一下我们是否可以使用现成的库从我们的蓝牙汽车中读取/向我们的蓝牙汽车发送消息。我们将运行两个测试:为您自己的设置选择一个您最喜欢的。

Anki 官方 C 工具上的一个树莓派

2017 款 Mac Book Pro 上的 Chrome 68+web app+ 蓝牙 API

  • 将您的浏览器指向这个精彩的演示这里
  • 连接并测试一堆命令(笨拙的我用浏览器开车的视频)。

任务开始!

使用 Python 实现实时汽车通信

“我们做我们最擅长的事情。我们随机应变,好吗?”—布莱恩·奥康纳

既然我们知道一切正常,现在是 Python 时间了!我们只能找到一个非官方的 Python 包装器用于驱动 SDK:代码实际上看起来很惊人,我们在 Raspberry 上测试成功example.py;但是依赖于 bluepy ,所以只是在 Linux 上运行。

我们最终开发的 hack-y 解决方案是来自上面的 Python 包装器(的简化版本)、一个不错的 Java 包装器和这个节点项目的想法的混合:

特别是,所有的“决定”都将在 Python 层做出,正如预期的那样,但 Python 不会直接与汽车通信,因为一个小节点网关(用 noble 构建)将从蓝牙传感器提供所需的跨平台抽象;在内部,Python 和 node 将利用套接字连接的速度来读/写信息。

如果你想了解更多关于包装器本身的信息,回购协议是有点自我说明的,结尾的附录会给你一个很好的高层次概述。如果您只是想开始驾驶,您需要:

  • 记下目标车辆的蓝牙设备 id
  • 克隆回购
  • cd 放入节点文件夹,用npm install下载依赖项
  • cd 放入 python 文件夹,并下载您最喜欢的 Python env pip install -r requirements.txt的依赖项(如果有的话)
  • 启动节点网关node node_server.js PORT UUID
  • 从你最喜欢的 Python env,运行python constant_speed_example.py —-car=UUID并看到车辆移动!

(这是我 在一分钟内完成所有这些步骤 ,为了方便起见,重用了一个 Python virtualenv)

我们已经准备好开始我们的第一个四分之一英里!

我们的第一个四分之一英里

“要么骑要么死,记得吗?”—多米尼克·托雷托

我们要做的第一件事就是绕着我们的椭圆形轨道匀速跑,比如说,400 毫米/秒(我知道,那是太慢了)。

Oval track with piece identifiers (IDs from our kit).

(可以用回购中的constant_speed_example.py来做同样的事情;轨迹图像取自此处

我们的 Python 应用程序将开始实时打印汽车位置通知,例如:

{'location': 17, 'piece': 36, 'offset': 67.5, 'speed': 390, 'self_speed': 400, 'clockwise': 7, 'notification_time': datetime.datetime(2018, 8, 25, 21, 9, 33, 359248), 'is_clockwise': False}{'location': 23, 'piece': 57, 'offset': 67.5, 'speed': 422, 'self_speed': 400, 'clockwise': 71, 'notification_time': datetime.datetime(2018, 8, 25, 21, 9, 32, 229689), 'is_clockwise': True}...

piecespeed都很琐碎(speed是车辆记录的速度,self_speed是我们命令设定的“理论”速度),offset标识“车道”(见此处的一个直观解释,位置是一个增量整数(见此处的一个很好的直观解释)。

我们现在可以走快了吗?我们当然可以,但是在踩油门之前,我们需要解决一个基本问题:我们如何测量跑完一圈需要的时间?当我们梦想改进我们的机器辅助驾驶策略时,我们需要一种方法来衡量我们一圈接一圈的速度。

即使位置更新没有那么频繁(因为我们每秒收到 3/4 次通知),我们也将简单地以 33 分段(起跑线)上两次连续通过之间的时间作为圈速这是在我们的椭圆形跑道上以 400 毫米/秒的速度运行lap_time_example.py的输出:

time lap in seconds was 9.046201
...
time lap in seconds was 9.029405
...
time lap in seconds was 9.045055
...
time lap in seconds was 9.044495
...

虽然有一些差异,但看起来没那么糟糕(SD 0.007)!作为进一步的测试,这是在 800 毫米/秒下的相同程序:

time lap in seconds was 4.497926
...
time lap in seconds was 4.502276
...
time lap in seconds was 4.497534
...

还是合理的!作为第一近似值,这就足够了。

正如我们刚刚看到的(惊喜惊喜!),通过提高车辆速度,我们获得了更好的性能(在 800 毫米/秒时,时间几乎正好是 400 毫米/秒时的 1/2)。为什么我们不越走越快呢?嗯,这不是那么微不足道,因为我们的宇宙很小,但仍然是物理现实的。为了理解我的意思,如果我们以 1000 毫米/秒的速度初始化汽车,会发生这样的情况:

Oooops

即使是多米尼克·托雷托也不可能转过那个弯(嗯,也许可能有)!

让我们从专业飞行员手册(或者实际上只是常识)中获取一些技巧:我们将写下稍微复杂一点的驾驶政策(参见custom_policy_example.py),如下所示:

  • 在每个直线段开始时,我们将速度增加到 1000 毫米/秒;
  • 就在掉头之前,我们将刹车并将速度降低到 800 毫米/秒。

Pretty basic, but we need to start somewhere, don’t we?

结果在数量上(更快的单圈时间)和质量上都更好:车辆行为现在更加真实:

We’re drifting baby!

当然,许多其他改进会立即浮现在脑海中,例如以更智能的方式使用车道。

由于可能的优化是无止境的,如果计算机能解决这个问题,那该多好? 是的,它会(也就是说,最终,玩具车如此有趣的全部科学借口)。

在我们的玩具世界里,确实有很多有趣的数据问题可以尝试和提问:

  • 给定赛道配置,车辆如何学习最佳“驾驶策略”?这实际上是两个挑战合二为一:学习一项政策并将其推广——如果在一个领域学到的东西可以立即用于另一个看不见的领域,那不是很酷吗?
  • 当我们将其他车辆引入组合时,会有什么变化?例如,我们可以让他们相互竞争,或者我们可以使用第二个工具来学习合作行为(例如避免碰撞)。
  • 除了赛道配置之外,我们能否以其他变量作为学习过程的条件?例如,我们可以想象通过一个以不同方式实现它们的汽车接口,从当前库中抽象出转向和制动命令。会有什么变化?
  • 使用当前的传感器,车辆能有多智能?正如我们已经看到的位置,传感器是非常基本的,不允许细粒度的控制:我们可以做些什么来更智能地利用我们所拥有的(例如,插值位置?)我们可以轻松添加哪些东西,让我们有更多的玩法(例如带物体识别功能的网络摄像头)?
  • …当然还有更多我们没有想到的!

重要的是,我们现在有一个基本的,但功能性的设置来运行实验,并从我们的小型汽车中收集数据。在第二部中,我们将开始将所有这些工程材料投入使用,并帮助我们为无人驾驶汽车设计越来越智能的行为(剧透:我们将从使用 Mac 键盘手动驾驶开始)。

附录:回购结构

本教程使用的代码是开源的,拥有 Apache 许可证。请注意,当前的master是作为 alpha 发布的,因为它只包含了最基本的东西:没有单元测试,没有花哨的东西,几乎没有对错误的保护,等等..随着实验的进展,我们希望对代码库进行一些改进:非常欢迎反馈和贡献!

项目结构非常简单,两个主要文件夹包含 node 和 Python 代码:

node_app
    node_socket-app
       node_server.js
    package-lock.json
python_app
    py_overdrive_sdk
        py_overdrive.py
    track_images/
    create_track_image.py
    constant_speed_example.py
    track_discovery_example.py
    custom_policy_example.py
    requirements.txt
.gitignore

node_server.js是一个服务器扫描和与蓝牙设备聊天的简单节点实现(受这个包装器的启发)。当服务器启动时, noble 等待蓝牙设备可用,并开始使用 Anki 特征 UUIDs 进行扫描。剩下的代码只是服务器监听来自 Python 的事件并执行蓝牙相关的逻辑:“元命令”带有语法 COMMAND|PARAM (例如CONNECT | ba 0 d6a 19–1bf 6–4681–93da-e 9c 28 F2 b 6743**),而 car 命令是十六进制字符串,直接发送给车辆(例如 03900101 启用 SDK 模式)。仅供参考,这也是我在 node 中编写的第一个应用程序(所以如果它不工作,那就是我的借口!).**

py_overdrive.py包含Overdrive类,该类封装了车辆相关逻辑和来自/去往节点网关的通信。我们利用 Python 线程和队列来处理并发进程,以非阻塞的方式写入、读取和处理位置事件。在初始化时,如果一个函数被提供给构造器,系统将采取定制的动作(“驱动策略”)来响应位置事件(简单的用例见custom_policy_example.py)。track_discovery_example.py和配套的脚本create_track_image.py将让你开始绘制轨道的不同部分,并打印出布局(附注:代码只是一个快速而肮脏的存根,它做出了许多简化的假设)。

如果你愿意帮忙,repo README包含了一个正在进行的改进和实验清单。随时寻求评论、反馈和想法。

再见,太空牛仔

**请继续关注,因为我们将很快带着第二部分回来。如果您有问题、反馈或评论,请将您的故事分享到jacopo . taglia bue @ tooso . ai

别忘了在 LinkedinTwitterInstagram 上获取 Tooso 的最新消息。

感谢

这将是一个的项目,而不是一个周末的项目,没有互联网和互联网上的出色的人分享他们的代码和想法(具体的学分见回购内的链接):就复制+粘贴而言,这个项目确实是首屈一指的。

当然,如果没有 Anki 让机器人民主化的愿景,这一切都不可能实现。我们第一次发现 Anki 是通过 Cozmo,一个瓦力般可爱的小机器人和一个奇妙的 Python SDK (Cozmo 的可能性使它成为各种周末项目的令人难以置信的游乐场)。虽然我们当然与 Anki blah blah 法律事务没有任何关系,但我懒得复制+粘贴 blah blah blah,我们非常喜欢他们的产品。

自学习人工智能代理 IV:随机策略梯度

原文:https://towardsdatascience.com/self-learning-ai-agents-iv-stochastic-policy-gradients-b53f088fce20?source=collection_archive---------13-----------------------

在连续的动作空间中控制人工智能:从自动驾驶汽车到机器人。

自学习人工智能代理系列—目录

0.介绍

使用 深度 Q 学习深度(双)Q 学习 我们能够在离散的动作空间中控制 AI,其中可能的动作可能简单到向左或向右、向上或向下。尽管有这些简单的可能性,人工智能代理仍然能够完成令人惊讶的任务,例如以超人的表现玩雅达利游戏,或者在棋盘游戏中击败世界上最好的人类选手 T21。

然而,强化学习的许多现实应用,如训练机器人无人驾驶汽车需要代理从连续空间中选择最佳行动。让我们用一个例子来讨论连续作用空间这个术语。

当你开车转动方向盘时,你可以控制方向盘转动的幅度。这就产生了一个连续的动作空间:例如,对于某个范围内的每一个正实数 x ,“向右转动轮子 x 度”。或者你踩油门到什么程度?这也是一个持续的输入。

记住:连续的动作空间意味着(理论上)有无限量的可能动作。

事实上,我们在现实生活中会遇到的大多数动作都来自连续动作空间。这就是为什么理解我们如何训练一个在有无限可能性的情况下选择行动的人工智能是如此重要。

这就是随机政策梯度算法显示其优势的地方。

你如何实践随机政策梯度?

OpenAI 健身房“连续登山”问题的这个例子是用随机政策梯度解决的,如下所示。有据可查的源代码可以在我的 GitHub 资源库 中找到。我选择 MountainCarContinuous 作为一个例子,因为这个问题的训练时间非常短,你可以很快地自己重现它。如果你看完这篇文章想练习一下,克隆库,执行src/policy gradients/random/random _ pg . py启动算法。

1.随机政策

马尔可夫决策过程中,我引入了人工智能代理作为一个神经网络,它与环境(电脑游戏、棋盘、现实生活等)相互作用。)通过观察它的状态 s (屏幕像素、板配置等。)并根据当前可观测状态采取动作 a、

Fig. 1 Schematic depiction of deep reinforcement learning

对于处于**状态s的每一个**动作at**,AI 代理接收一个奖励奖励的数量告诉代理他的动作在这个特定的状态中关于解决给定目标的质量,例如学习如何走路或赢得一个计算机游戏。任何给定的状态下的动作策略π 决定。**

马尔可夫决策过程中,我引入了策略作为 AI 的策略,该策略决定了他从一个状态 s 到下一个状态**s’**的移动,跨越所有可能状态 s_1 的整个序列,...,环境中的 s_n

深度 Q 学习中,代理遵循策略 π ,该策略告知在状态 s 中采取动作,这对应于最高动作值 Q(s,a) 。行动价值函数是我们从状态 s 开始,采取行动 a ,然后遵循政策 π 所获得的预期回报(所有状态的回报总和)(比较马尔可夫决策过程 )

在随机策略的情况下,基本思想是通过参数概率分布来表示策略:

Eq. 1 Stochastic policy as a probability distribution.

Fig. 1 Sample an action a from the policy, which is a normal distribution in this case.

该分布根据一个参数向量 θ 随机选择状态 s 中的动作 a 。作为概率分布的策略的一个例子是高斯分布,其中我们随机选择一个动作,作为这个分布的样本(图 1)。这就产生了动作是一个连续变量。**

记住 :与深度 Q 学习相反,策略现在是从状态到动作的直接映射/函数。******

一步法

但是我们如何确定当前的政策π是一个好政策呢?为此我们必须为π定义一个性能函数,我们称之为 J(θ)

我们来讨论一个简单的案例,这里我们要衡量的是 π 的质量/性能只针对代理的一个步骤(从状态 s 到下一个状态s’*)。在这种情况下,我们可以将质量函数定义如下:*****

Eq. 2

等式中的第二行无非是期望操作符 E 对期望动作的执行——值 r(s,a) 对于动作 a 处于状态s是从环境中选择的,而 a 是根据策略选择的 R_a_s 是状态 s 中动作 a 的奖励。

请注意 : r(s,a)Q(s,a)q(s,a) 含义相同,但仅针对一步流程****

必须考虑到,在深度强化学习中,环境是随机的,这意味着采取行动并不能保证代理人最终会处于他想要的状态。环境在一定程度上决定了代理的最终位置。因为动作值【s,a】依赖于依赖于下一个状态【s’(参见等式。17 在 马尔可夫决策过程中 )我们必须平均报酬 R_a_s 整体转移概率p(s):= p(s→s’)从状态 s 到下一个状态s’。* 再者因为 R_a_s 也取决于行动,我们必须将所有可能的 π(a,s)上的报酬平均化。*****

2.随机政策梯度定理

策略梯度算法通常通过对这种随机策略进行采样并朝着更大的累积回报的方向调整策略参数来进行。

现在我们已经定义了策略 π、 的性能,我们可以更进一步,讨论如何学习最优策略。由于 π(θ) 取决于一些参数 θ ( 这些参数在大多数情况下是神经网络的权重和偏差)我们必须找到使性能最大化的最优 θ

政策梯度法背后的基本思想是在绩效梯度的方向上调整政策的这些参数【θ】。******

如果我们计算 J(θ) 的梯度,我们得到下面的表达式:

Eq. 3 The gradient of the performance function for the one-step process.

因为我们想要找到使性能最大化的,所以我们必须更新进行梯度上升——与梯度下降相反,我们想要找到使预定义损失函数最小化的参数。****

多步骤过程

既然我们知道了如何改进一步式流程的策略,我们可以继续这个案例,在这里我们考虑 AI 智能体在整个状态序列中的移动过程。

实际上,这种情况并没有那么困难,如果我们记住,在遵循一个政策从一个状态到另一个状态的运动过程中,我们将获得的(折扣)奖励的总和,就是行动-价值函数 Q(s,a) 的准确定义。这产生了多步骤过程的策略梯度的以下定义,其中单个预期回报【r(s,a)】与预期累积回报(回报总和) Q(s,a) 交换。

Eq. 4 The gradient of the performance function for the multi-step process.

3.演员-评论家算法

根据等式使用更新规则的算法。4 被称为演员评论家算法。策略 π(a|s) 被称为参与者,因为参与者决定了在 s 状态下必须采取的动作。与此同时,评论家 Q(s,a), 通过赋予演员的行为一个质量值来达到批评的目的。

可以看到J【θ】的渐变与这个的质量值成比例。高质量值表明在状态中采取的动作 a 实际上是一个好的选择,并且可以增加性能方向上的 θ 的更新。反之适用于小质量值。**

现实中,我们无法预先知道【Q(s,a)】T3。因此我们必须用一个函数 Q_w(s,a) 来近似它,这个函数依赖于参数 w 。一般来说 Q_w(s,a) 可以通过神经网络来估计。******

Eq. 5 Estimation of the action-value function.

这产生了性能梯度的新定义:

E6. A new definition of the performance gradient.

总之,随机策略梯度算法试图完成以下两件事:

  • 更新演员 π 的参数 θ 朝向表演的渐变 J(θ)
  • 用常规的时间差异学习算法更新评论家的参数 w ,这是我在深度 Q 学习中介绍的。

整个 Actor-Critic 算法可以用下面的伪代码来表示:

算法的关键部分发生在代表人工智能代理生命周期的循环中。让我们更深入地讨论每一步:

  • 通过在状态中采取动作从环境中获得奖励 R ,并观察新状态【s’********
  • **给定这个新状态s’***样本一个动作 *一个’随机地从分布 π
  • 使用旧的a 和新的s’**,a’计算时间差异目标δ
  • 根据时间差异学习更新规则更新参数 w 。(更好的替代:用常规的梯度下降算法最小化r+γQ(s’,a’)*【s,a】*之间的距离来更新w*****。)*******
  • 通过向性能梯度 J(θ) 执行梯度上升步骤,更新策略的参数 θ
  • 将新状态 s' 设为旧状态 s ,并将新动作 a' 设为旧动作 a
  • 如果进程没有终止,从头开始循环

4.减少方差

众所周知,Actor-Critic-Algorithm 的普通实现具有很高的方差。减小这种方差的一种可能性是从动作值【Q(s,a)】**中减去状态值 V(s) (等式 1)。7) 状态值在马尔可夫决策过程中被定义为预期的总奖励,如果它在状态 中开始它的进程而不考虑动作,AI 代理将会收到该奖励。****

Eq. 7 Definition of the advantage.

这个新术语被定义为 优势 并且可以被插入到性能的梯度中。利用这一优势在减少算法的方差方面显示了有希望的结果。

Eq. 8 Advantages is inserted into the policy gradient.

在具有优势的另一方面,我们引入了要求具有第三函数逼近器(如神经网络)来估计的问题。然而,可以看出预期的时间差误差为**【V(s)】(等式。9) 无非是优点。****

Eq. 9 Temporal difference error of V(s).

这可以用 Q(s,a) 的一个定义来表示,就是r+γV(s’)**期望值。通过减去剩余的项 V(s) 我们获得优势 A (等式 1)的先前定义。10) ****

Eq. 10 Advantage equals the expected TD-Error of V(s).

最后,我们可以将【V(s)的时差误差插入到【J(s)的梯度中。这样做我们一举两得:

  • 我们减少了整个算法的方差
  • 同时,我们去掉了三次函数近似

Eq. 11

自学习人工智能代理第一部分:马尔可夫决策过程

原文:https://towardsdatascience.com/self-learning-ai-agents-part-i-markov-decision-processes-baf6b8fc4c5f?source=collection_archive---------2-----------------------

深度强化学习理论的数学指南

这是关于自我学习人工智能代理的多部分系列的第一篇文章,或者更准确地说,是深度强化学习。本系列的目的不仅仅是让你对这些话题有一个直觉。相反,我想为您提供对最流行和最有效的深度强化学习方法背后的理论、数学和实现的更深入的理解。

自学习人工智能代理系列—目录

Fig. 1. AI agent learned how to run and overcome obstacles.

马尔可夫决策过程—目录

  • 0。简介
  • 1。简而言之强化学习
  • 2。马尔可夫决策过程
  • 2.1 马尔可夫过程
  • 2.2 马尔可夫奖励过程
  • 2.3 价值函数
  • 3。贝尔曼方程
  • 3.1 马尔可夫报酬过程的贝尔曼方程
  • 3.2 马尔可夫决策过程— 定义
  • 3.3 政策
  • 3.4 动作值函数
  • 3.5 最佳政策
  • 3.6 贝尔曼最优方程

如果你喜欢这篇文章,想分享你的想法,问问题或保持联系,请随时通过 LinkedIn 与我联系。

0.介绍

深度强化学习正在兴起。近年来,深度学习的其他子领域没有被研究人员和全球大众媒体谈论得更多。深度学习中的大多数杰出成就都是由于深度强化学习而取得的。从谷歌的阿尔法围棋(Alpha Go)击败了世界上最好的人类棋手(这一成就在几年前被认为是不可能的),到 DeepMind 的人工智能智能代理(AI agents ),它们可以自学行走、奔跑和克服障碍(图 1-3)。

Fig. 2. AI agent learned how to run and overcome obstacles.

Fig. 3. AI agent learned how to run and overcome obstacles.

自 2014 年以来,其他人工智能代理在玩老派雅达利游戏如突破(图 4)时超过了人类水平。在我看来,所有这些最令人惊讶的事情是,这些人工智能代理中没有一个是由人类明确编程或教会如何解决这些任务的。他们是靠深度学习和强化学习的力量自己学会的。这个多部分系列的第一篇文章的目标是为您提供必要的数学基础,以便在接下来的文章中处理这个人工智能子领域中最有前途的领域。

Fig. 4 AI agent learned how to play Atari’s Breakthrough.

1.简而言之,深度强化学习

深度强化学习可以概括为构建一个直接从与环境的交互中学习的算法(或 AI agent)(图 5)。环境可以是真实的世界、计算机游戏、模拟甚至是棋盘游戏,如围棋或象棋。像人类一样,人工智能代理从其动作的结果中学习,而不是从被明确教导中学习。

Fig. 5 Schematic depiction of deep reinforcement learning

在深度强化学习中,代理由神经网络表示。神经网络直接与环境互动。它观察环境的当前状态并决定采取哪个动作(例如向左、向右移动等。)基于当前状态和过去的经验。基于所采取的动作,AI 代理接收奖励。奖励的数量决定了所采取的行动在解决给定问题方面的质量(例如学习如何走路)。一个代理的目标是学习在任何给定的情况下采取行动,使累积的回报随着时间的推移而最大化。

2.马尔可夫决策过程

一个马尔可夫决策过程 ( MDP )是一个离散时间随机控制过程。MDP 是迄今为止我们为人工智能代理的复杂环境建模的最好方法。代理旨在解决的每个问题都可以被认为是一系列状态 S1、S2、S3……Sn(例如,一个状态可以是围棋/国际象棋棋盘配置)。代理采取行动并从一种状态转移到另一种状态。在接下来的内容中,你将学习在任何给定的情况下,决定代理人必须采取何种行动的数学方法。

2.1 马尔可夫过程

马尔可夫过程是描述一系列可能状态的随机模型,其中当前状态仅依赖于先前状态。这也称为马尔可夫性质(等式)。1).对于强化学习,这意味着人工智能主体的下一个状态只依赖于上一个状态,而不是之前的所有状态。

Eq. 1 Markov Property

马尔可夫过程是一个随机过程。意味着从当前状态 s 到下一个状态s’的过渡只能以一定的概率发生Pss(等式。2).在马尔可夫过程中,被告知向左的代理只会以某个概率(例如 0.998)向左。在小概率情况下,由环境来决定代理的最终位置。

Eq. 2 Transition probability from state s to state s’.

Pss可以被认为是状态转移矩阵 P 中的一个条目,该矩阵定义了从所有状态 s 到所有后继状态’s**的转移概率。3).

Eq. 3. Transition probability matrix.

记住:一个马尔可夫过程(或马尔可夫链)是一个元组 < SP >S 是状态的(有限)集合。 P 是状态转移概率矩阵。

2.2 马尔可夫奖励过程

一个马氏奖励过程是一个元组 < S,P,R > 。这里 R 是代理人在状态 s (Eq。4).这一过程的动机是,对于一个旨在实现某个目标(例如赢得一场国际象棋比赛)的人工智能主体来说,某些状态(比赛配置)在策略和赢得比赛的潜力方面比其他状态更有希望。

Eq. 4. Expected reward in a state s.

兴趣的首要话题是总奖励 Gt (Eq。5)这是代理将在所有状态序列中收到的预期累积奖励。每个奖励由所谓的折扣因子γ ∈ [0,1]加权。贴现回报在数学上是方便的,因为它避免了循环马尔可夫过程中的无限回报。此外,贴现因子意味着我们越是在未来,回报就变得越不重要,因为未来往往是不确定的。如果奖励是经济上的,即时奖励可能比延迟奖励获得更多的利息。此外,动物/人类的行为显示出对即时回报的偏好。

Eq. 5. Total reward across all states.

2.3 价值函数

另一个重要的概念是价值函数 v(s) 的概念。value 函数将一个值映射到每个状态 s 。状态 s 的值被定义为如果 AI 代理在状态 s 中开始其进程,它将接收的预期总奖励(等式。6).

Eq. 6. Value function, the expected return starting in state s.

价值函数可以分解为两部分:

  • 代理人在状态****【s .**下收到的即时报酬 R(t+1)
  • 状态之后的下一个状态的贴现值 v(s(t+1))**

Eq. 7 Decomposition of the value function.

3.贝尔曼方程

3.1马尔可夫奖励过程的贝尔曼方程

分解的值函数(等式。8)也称为马尔可夫奖励过程的贝尔曼方程。该功能可以在节点图中可视化(图 6)。从状态 s 开始导致值 v(s) 。处于状态 s 我们有一定的概率*【Pss’结束于下一个状态s’。在这个特例中,我们有两个可能的下一个状态。为了获得值 v(s) ,我们必须对可能的下一个状态的值s v(s)求和,该值由概率【Pss’*加权,并加上从处于状态 s 中得到的直接奖励。这产生了等式。如果我们在等式中执行期望操作符 E ,这就是等式 8。

Eq. 8 Decomposed value function.

Fig. 6 Stochastic transition from s to s’.

Eq. 9 Bellman Equation after execution of the expectation operator E.

3.2 马尔可夫决策过程—定义

马尔可夫决策过程是一个带有决策的马尔可夫回报过程。马尔可夫决策过程由一组元组 < S,A,P,R >来描述,A 是代理在状态 s 中可以采取的有限的可能动作集合。因此,处于状态 s 的直接回报现在也取决于代理在这种状态下采取的动作(等式。10).**

Eq. 10 Expected reward depending on the action in a state s.

3.3 政策

在这一点上,我们将讨论代理如何决定在一个特定的状态下必须采取的行动。这是由所谓的策略【π】(等式。11).从数学上来说,策略是给定状态 s 下所有动作的分布。该策略确定从状态到代理必须采取的动作*的映射。***

Eq. 11 Policy as a mapping from s to a.

记住:直观地说,策略π可以描述为代理根据当前状态 s 选择某些动作的策略。

该政策导致了国家价值函数的新定义 v(s) (等式。我们现在把它定义为从状态 s 开始,然后遵循一个策略 π的期望收益。

Eq. 12 State-value function.

3.4 动作值函数

**除了状态值函数之外,另一个重要的函数是所谓的动作值函数 q(s,a) (等式。13) **。行动值函数是我们从状态 s 开始,采取行动 a ,然后遵循策略 π 所获得的预期收益。注意,对于状态 sq(s,a) 可以取几个值,因为在状态 s 中代理可以采取几个动作。 Q(s,a) 的计算由神经网络实现。给定一个状态 s 作为输入,网络以标量形式计算该状态下每个可能动作的质量(图 7)。更高的质量意味着对于给定的目标更好的行动。

Fig. 7 Illustration of the action-value function.

****记住:行动价值函数告诉我们,在特定状态下采取特定行动有多好。

Eq. 13 Action-value function.

之前,状态值函数 v(s) 可以分解为以下形式:

Eq. 14 Decomposed state-value function.

同样的分解可以应用于动作值函数:

Eq. 15 Decomposed action-value function.

此时,让我们讨论一下*【v(s)*q(s,a) 是如何相互关联的。这些函数之间的关系可以在图表中再次可视化:

Fig. 8 Visualization of the relation between v(s) and q(s,a).

在这个例子中,处于状态 s 允许我们采取两种可能的动作 a 。根据定义,在特定的状态下采取特定的动作给了我们动作值 q(s,a) 。价值函数*【v(s)是在状态【s】(Eq)中采取行动的概率(非策略 π )加权的可能*【q(s,a)*** 之和。16) ***

Eq. 16 State-value function as weighted sum of action-values.

现在让我们考虑图 9 中相反的情况。二叉树的根现在是一种状态,在这种状态下我们选择采取一个特定的动作。记住马尔可夫过程是随机的。采取行动并不意味着你会百分百确定地到达你想去的地方。严格地说,你必须考虑采取行动后在其他州结束的可能性。在这种特殊情况下,在采取行动之后,你可能会以两种不同的下一个状态*结束:*****

Fig. 9 Visualization of the relation between v(s) and q(s,a).

要获得行动值,您必须获得由概率Pss’加权的贴现状态值,以结束所有可能的状态(在本例中只有 2 个),并添加即时奖励:

Eq. 17 Relation between q(s,a) and v(s).

现在我们知道了这些函数之间的关系,我们可以从等式中插入【v(s)】。16 从 Eq 变成 q(s,a) 。17.我们得到等式。18,可以注意到,当前 q(s,a) 和下一个动作值q(s’,a’)之间存在递归关系。

Eq. 18 Recursive nature of the action-value function.

这种递归关系可以在二叉树中再次可视化(图 10)。我们从 q(s,a) 开始,以某个概率在下一个状态 s' 中结束 Pss' 从那里我们可以以概率*【π采取行动' a '并以行动值结束为了获得 q(s,a)* ,我们必须沿着树向上,对所有概率进行积分,如等式 1 所示。18.**

Fig. 10 Visualization of the recursive behavior of q(s,a).

3.5 最佳政策

深度强化学习中最重要的感兴趣的主题是找到最佳动作值函数 q 。寻找 q 意味着代理人确切地知道在任何给定状态下动作的质量。此外,代理可以根据质量决定必须采取的行动。让我们定义一下 q* 的意思。最可能的行动价值函数是遵循最大化行动价值的政策的函数:**

Eq. 19 Definition of the best action-value function.

为了找到可能的最佳策略,我们必须在q(s,a)上最大化。最大化意味着我们只从所有可能的动作中选择动作,其中 q(s,a) 具有最高值。这就产生了最优策略π的如下定义:**

Eq. 20 Optimal policy. Take actions that maximize q(s,a).

3.6 贝尔曼最优方程

最优策略的条件可以代入方程。18.从而为我们提供了贝尔曼最优性方程:

Eq. 21 Bellman Optimality Equation

如果人工智能代理可以解决这个方程,那么它基本上意味着给定环境中的问题得到了解决。代理人知道在任何给定的状态或情况下任何可能的行动的质量,并能相应地行动。

解决贝尔曼最优方程将是接下来文章的主题。在接下来的文章中,我将向你展示第一种叫做深度 Q 学习的技术。

自学习人工智能代理第二部分:深度 Q 学习

原文:https://towardsdatascience.com/self-learning-ai-agents-part-ii-deep-q-learning-b5ac60c3f47?source=collection_archive---------1-----------------------

深度 Q 学习的数学指南。在这个关于深度强化学习的多部分系列的第二部分中,我将向您展示一种有效的方法,来说明 AI 智能体如何在具有离散动作空间的环境中学习行为。

自学习人工智能代理系列—目录

深度 Q-学习-目录

  • 0。简介
  • 1。时间差异学习
  • 2。q-学习
  • 2.1 开启和关闭策略
  • 2.2 贪婪政策
  • 3。深度 Q 学习
  • 3.1 目标网络和 Q 网络
  • 3.2ε-贪婪政策
  • 3.3 勘探/开采困境
  • 3.4 体验回放
  • 4。具有经验重放伪算法的深度 Q 学习

如果你喜欢这篇文章,想分享你的想法,问问题或保持联系,请随时通过 LinkedIn 与我联系。

0.介绍

在本系列的第一篇文章中,我向您介绍了马尔可夫决策过程的概念,这是深度强化学习的基础。为了完全理解下面的主题,我建议你重温一下第一篇文章。

通过深度 Q 学习,我们可以编写能够在具有离散动作空间的环境中运行的人工智能代理。离散动作空间是指定义明确的动作,例如向左或向右、向上或向下移动。

FIg. 1. Atari’s Breakthrough as an example for discrete action spaces.

雅达利的突破是一个具有离散行动空间的环境的典型例子。人工智能代理可以向左或向右移动。每个方向的运动都有一定的速度。

如果代理可以决定速度,那么我们将有一个连续的动作空间,有无限多的可能动作(不同速度的运动)。这一案件将在今后审议。

1.动作值函数

在上一篇文章中,我介绍了动作值函数的概念 ***Q(s,a)***由 Eq 给出。1. 提醒一下,动作值函数被定义为 AI 智能体通过从状态 s 开始,采取动作 a 然后遵循策略 π而获得的预期回报。

记住:直观地说,策略π可以描述为代理根据当前状态 s 选择某些动作的策略。

Eq. 1 Action-Value function.

***【s,a】***告诉代理人一个可能动作的值(或质量)s。给定一个状态 s ,动作值函数计算该状态下每个可能动作 a_i 的质量/值,作为标量值(图 1)。更高的质量意味着对于给定的目标更好的行动。

Fig. 1 Given a state s, there are many actions and appropriate values of Q(s,a)

如果我们执行等式中的期望运算符 E 。1 我们获得了一种新形式的行动价值函数,在这里我们处理概率。**【Pss’是从一个状态到下一个状态*【s’的转移概率,由环境决定。【π(a ')*是政策或从数学上讲是给定状态下所有行动的分配

Eq. 2 Another form of Q(s,a) incorporates probabilities.

1.时间差异学习

我们在深度 Q-Learning 中的目标是求解动作值函数 Q(s,a) 。我们为什么想要这个?如果 AI 智能体知道 Q(s,a) ,那么给定的目标(比如赢得一场与人类玩家的象棋比赛或者玩 Atari 的突破)可以被认为是已解决的。这样做的原因是这样一个事实,即 Q(s,a) 的知识将使代理人能够确定在任何给定状态下任何可能行动的质量。因此,代理可以相应地行动。

情商。2 还给出了一个递归解,可以用来计算 Q(s,a) 。但是因为我们在考虑递归,而且用这个方程来处理概率是不实际的。而是必须使用所谓的时间差分 ( TD )学习算法来迭代求解 Q(s,a)

在 TD 学习中我们更新 Q(s,a) 对于每一个动作 a 处于一种状态 s 朝向估计返回 R(t+1)+γQ(s(t+1),a(t+1)) ( Eq。3 )。估计回报也称为 TD 目标。对每个状态和动作多次迭代地执行该更新规则,对于环境中的任何状态-动作对,产生正确的动作值*【Q(s,a)*

Eq. 3 Update rule for Q(s,a)

TD-Learning 算法可以总结为以下步骤:

  • 对于状态 s_t 中的动作 a_t 计算 Q(s_t,a_t)
  • 转到下一个状态*【t+1】,在那里采取一个动作【t+1】*并计算值 Q( s_(t+1),a(t+1))
  • 使用 Q( s_(t+1),a(t+1)) 和即时奖励 R(t+1) 进行动作 a_t 最后状态 s_t 计算 TD-Target
  • 通过将*【Q(s _ t,a _ t)】添加到 TD-Target 和【Q(s _ t,a _ t)】α之间的差值来更新先前的【s _ t,a _ t】*

1.1 时间差异

让我们更详细地讨论 TD 算法的概念。在 TD- learning 中我们考虑了 Q(s,a) — 两个“版本”之间的差异【a】Q(s,】一旦之前我们采取行动处于状态

采取行动前:

请看图 2。假设 AI 代理处于状态 s (蓝色箭头)。在状态下,他可以采取两种不同的动作**【a _ 1】【a _ 2】。基于来自一些先前时间步骤的计算,代理知道该状态下两个可能动作的动作值【s,a _ 1】Q(s,a_2)**

Fig. 2 Agent in state s knows every possible Q(s,a).

采取行动后:

基于这个知识,代理决定采取行动 a_1 。采取此操作后,代理处于下一个状态*‘s’。因为采取了行动 a_1 他获得了直接奖励 R 。处于状态s’时,代理可以再次采取两种可能的动作a’_ 1a’_ 2***,他从先前的一些计算中再次知道了这些动作的值。**

如果从方程 Eq 中 Q(s,a) 的定义上看。1 你会发现,在状态*s’中,我们现在有了新的信息,可以用来计算 Q(s,a_1) 的新值。该信息是针对上一个状态中的上一个动作而接收到的即时奖励 R 以及针对动作a’而接收到的Q(s’,a’)代理将在这个新状态中获取。根据图 3 中的等式可以计算出 Q(s,a_1) 的新值。等式的右边也是我们所说的 TD 目标。TD-target 与旧值或【s,a _ 1】*的'时态版本之差称为时态差。

记住:在 TD-learning 期间,我们为任何可能的动作值Q(s,a)【s,a】计算时间差,并同时使用它们来更新【Q(s,a)** ,直到 Q(s,a) 收敛到其真实值。****

Fig, 3 Agent in state s’ after taking action a_1.

2.萨尔萨

应用于*【S,A】*的 TD-Learning 算法俗称 SARSA 算法(State—Aaction—Reward—State—Aaction)。 SARSA 是被称为 on-policy 算法的特殊学习算法的一个很好的例子。

前面我介绍了策略 π(a|s) 作为从状态 s 到动作 a 的映射。此时需要记住的一点是, on-policy 算法使用与相同的策略来获取 TD-Target 中*【s _ t,a _ t】*以及 Q(s(t+1),a_(t+1)) 的动作。这意味着我们正在跟随同时改进同样的政策。

3.q 学习

我们最终到达文章的核心,在这里我们将讨论 Q-Learning 的概念。但在此之前,我们必须先看看第二种特殊类型的算法,称为非策略算法。正如你可能已经想到的,Q-Learning 属于这种算法,这是一个区别到 on-policy 算法,如 SARSA

为了理解非策略算法,我们必须引入另一个策略 (a|s) ,并将其称为行为策略。行为策略决定行动*a _ t ~(a | s)forQ(s _ t,a _ t)*for allSARSA、的情况下,行为策略将是我们同时遵循并试图优化的策略。

非策略 算法中,我们有两种不同的策略(a | s)***π(a|s)(a|s) 是行为,而π(a|s) 是所谓的目标策略。*行为策略用于计算 Q(s_t,a _ t)目标策略用于计算 Q(s_t,a_t) 只有中的TD-Target。(这一概念将在下一节进行实际计算时更加全面)

记住:行为策略为所有 Q(s,a) 挑选动作。相比之下,目标策略只为 TD 目标的计算确定行动。

*我们实际上称之为 Q 学习算法的算法是一个特例,其中目标策略【π(a | s)***是一个贪婪的 w.r.t. **Q(s,a)这意味着我们的策略正在采取导致最高值 Q 的行动。这产生了以下目标策略:

Eq. 4 Greedy target policy w.r.t Q(s,a).

在这种情况下,目标策略被称为贪婪策略。贪婪策略意味着我们只选择产生最高**【s,a】值的行为。这个贪婪的目标策略可以被插入到行动等式中-值【Q(s,a)】其中我们之前已经遵循了随机策略【π(a | s):

Eq. 5 Insertion of greedy policy into Q(s,a).

贪婪策略为我们提供了最优动作值 Q(s,a) ,因为根据定义 Q(s,a)Q(s,a) 遵循最大化动作值的策略:**

Eq. 6 Definition of optimal Q(s,a).

Eq 中的最后一行。5 就是我们在上一篇文章中推导出的贝尔曼最优方程。这个方程作为递归更新规则,用来估计最优动作值函数 Q(s,a)。***

然而,TD-learning 仍然是找到 Q(s,a) 的最佳方法。利用贪婪目标策略,对等式中的 Q(s,a) 的 TD 学习更新步骤。3 变得更加简单,如下所示:*

Eq. 7 TD-learning update rule with greedy policy.

用于具有贪婪目标策略的【Q(s,a)】的 TD-学习算法可以概括为以下步骤:

  • 对于状态 s_t 中的动作 a_t 计算 Q(s_t,a_t)
  • 转到下一个状态【s (t+1),采取动作‘a’***,产生最高值 Q ,并计算 ***Q( s(t+1),a’)******
  • ***使用 ***Q( s_(t+1),a’)和即时奖励 R 进行动作 a_t 最后状态 s_t 计算 TD-Target
  • 更新先前的 Q(s_t,a_t) ,将 Q(s_t,a_t) 添加到 TD-Target 和 Q(s_t,a_t)之间的差值,α 为学习率。

考虑前面的图(图 3),其中代理处于状态【s’,并且知道该状态下可能动作的动作值。遵循贪婪目标策略,代理将采取具有最高动作值的动作(图 4 中的蓝色路径)。这个策略还为我们提供了一个新的值 Q(s,a_1) (图中的等式),这就是定义的 TD 目标。

Eq. 8 Calculation of Q(s,a_1) following the greedy policy.

3.深度 Q 学习

*我们终于到达了这篇文章的标题得到其序言深度的地方— 我们终于利用了深度学习。如果您查看 Q(s,a) 的更新规则,您可能会认识到,如果 TD-Target 和 Q(s,a) 具有相同的值,我们不会得到任何更新。在这种情况下 ***Q(s,a)收敛到真实的动作值,目标达到。

这意味着我们的目标是最小化 TD-Target 和【Q(s,a)】之间的距离,这可以通过平方误差损失函数(等式 1)来表示。10).这种损失函数的最小化可以通过通常的梯度下降算法来实现。

Eq. 10 Squared error loss function.

3.1 目标网络和 Q 网络

在深度 Q 学习中,TD-Targety _ IQ(s,a) 分别由两个不同的神经网络估计,这两个网络通常称为 Target-和 Q-网络(图 4)。目标网络的参数 θ(i-1) (权重、偏差)对应于 Q 网络在较早时间点的参数【θ(I)。意味着目标网络参数在时间上被冻结。在用 Q 网络的参数进行了 n 次迭代之后,它们被更新。

记住 :给定当前状态 s ,Q 网络计算动作值 Q(s,a) 。同时,目标网络使用下一个状态s’来计算 TD 目标的Q(s’,a)* 。***

Fig. 4 Target,- and Q-Network. s being the current and s’ the next state.

研究表明,对 TD-Target 和 Q(s,a) 计算采用两种不同的神经网络,模型的稳定性更好。

3.2ε-贪婪政策

虽然目标策略【π(a | s)仍然是贪婪策略,但是行为策略 (a|s) 决定了 AI 代理采取的动作 a_i ,因此必须将哪个 Q(s,a_i) (由 Q-网络计算)插入到平方误差中

行为方针通常选择ε-贪婪。使用ε-贪婪策略,代理在每个时间步选择一个具有固定概率ε的随机动作。如果ε具有比随机生成的数 p ,0 ≤ p ≤ 1 更高的值,则 AI 代理从动作空间中选取一个随机动作。否则,根据学习的动作值 Q(s,a): 贪婪地选择动作**

Eq. 11 Definition of the ε-Greedy policy.

选择ε-贪婪策略作为行为策略解决了探索/剥削权衡的困境。

3.3 勘探/开采

关于采取何种行动的决策涉及一个基本选择:

  • 利用:根据当前信息做出最佳决策
  • 探索:收集更多信息,探索可能的新路径

利用而言,代理根据行为策略采取可能的最佳行动。但是这可能会导致一个问题。也许有时可以采取另一种(替代的)行动,在状态序列中产生(长期)更好的路径,但是如果我们遵循行为策略,这种替代行动可能不会被采取。在这种情况下,我们利用当前政策,但不探索其他替代行动。

ε-贪婪策略通过允许 AI 代理以一定的概率从动作空间中采取随机动作来解决这个问题。这叫探索**。通常,根据等式,ε的值随着时间而减小。12.这里 n 是迭代次数。减小ε意味着在训练开始时,我们试图探索更多的可选路径,而在最后,我们让政策决定采取何种行动。**

Eq. 12 Decreasing of ε over time.

3.4 体验回放

过去,可以表明,如果 Deep-Q 学习模型实现经验重放**,则估计 TD-Target 和 Q(s,a) 的神经网络方法变得更加稳定。经验回放无非是存储 < s,s’,a’,r>元组的记忆,其中

  • s:AI 代理的状态
  • a’:代理在 s 状态下采取的动作
  • r :在 s 状态下行动*a’*获得即时奖励
  • s' :状态 s 后代理的下一个状态

在训练神经网络时,我们通常不使用最近的 < s,s’,a’,r > 元组。而是我们从经验回放中随机取一批 < s,s’,a’,r > 来计算 TD-Target, Q(s,a) 最后应用梯度下降。

3.5 具有经验重放伪算法的深度 Q 学习

下面的伪算法实现了具有经验重放的深度 Q 学习。我们之前讨论的所有主题都以正确的顺序包含在这个算法中,就像它在代码中是如何实现的一样。

Pseudo-Algorithm for Deep-Q Learning with Experience Replay.

带有交互代码的 Tensroflow 中的自组织地图/图层[带 TF 的手动后道具]

原文:https://towardsdatascience.com/self-organizing-map-layer-in-tensroflow-with-interactive-code-manual-back-prop-with-tf-580e0b60a1cc?source=collection_archive---------3-----------------------

GIF from this website

Teuvo Kohonen 是一位传奇的研究者,他发明了自组织地图。(能读到他 1990 年发表的原创论文,我感到荣幸和感谢)。有不同类型的自组织映射,如递归 Som无参数 Som 。它们还与神经气体密切相关。

Paper from this website

附加阅读和帮助实现

Image from this website

对于任何有兴趣阅读更多这方面内容的人,请查看这个链接(ai-junkie),它在更深入地解释这个问题方面做了令人惊讶的工作。我在网上找到了两种实现方式,这篇博文通过在线训练的方式实现,而这篇博文通过批量训练实现。

自组织地图作为图层

通过使用这里完成的实现,我修改了这里和那里的代码,以便我使用 SOM 作为神经网络中的典型层。如果你想看完整的代码,请看下面。

颜色数据结果

如上所述,当我们将一些颜色数据(如下所示)应用到 SOM 时,我们可以清楚地看到它在颜色聚类方面做得很好。

MNIST 数据结果

上图是对 30 * 30 * 784 维的 SOM 进行无监督学习的结果,值得一提的是,这个 SOM 的总维数相当大。现在,我们可以做一些有趣的事情,因为我们已经将 SOM 修改为一个层,我们可以在 SOM 之前连接任何类型的神经网络,希望聚类将更加清晰,并减少维数。

蓝色矩形 →全连通层
红色立方体 →自组织地图

如上所述,在将我们的 MNIST 向量(784*1)传递到 SOM 之前,我们可以有几个完全连接的层来处理数据。同时也降低了向量的维数。结果可以在下面看到。

关于上面的 SOM 需要注意的一件重要事情是,它只有(3030256)维,所以现在我们使用 256 而不是 784 的向量大小。但是我们仍然能够在这里和那里得到一些好的结果。但我真的相信我们可以做得比上述结果更好。

结果于 CIFAR 10 数据

上图显示了矢量化 CIFAR 10 上的聚类结果,我们可以直接观察到聚类有多糟糕。对自然图像进行聚类实际上是一项相当具有挑战性的任务,即使它们的维数仅为 3072 的向量。(32323).

绿色矩形 →卷积层
蓝色矩形 →全连通层
红色立方体 →自组织图

现在对于 CIFAR 10,让我们使用完全连接层和卷积层的组合来(希望)有效地减少维度和集群数据。

与直接使用 SOM 的情况相比,它做得更好。但总的来说,这是可怕的集群。(再次注意,上述 SOM 具有(3030256)的维数,这比直接使用 SOM 小 12 倍。(230400 个参数用于带网络的 SOM,2764800 个参数用于直接使用 SOM,不计算网络参数。)

然而,我对结果很失望。

交互代码

对于 Google Colab,你需要一个 Google 帐户来查看代码,而且你不能在 Google Colab 中运行只读脚本,所以在你的操场上做一个副本。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!

要访问带颜色的 SOM 代码,请点击此处。
要访问与 MNIST、的 SOM 代码,请点击此处。
要访问 for SOM 网络的代码,请点击此处。
要访问带有 CIFAR 的 SOM 代码,请点击此处
要使用 CIFAR 访问 SOM 网络代码,请点击此处。

最后的话

现在,下一个任务是设计一个好的成本函数,我不认为直接从差值的幂减少平均值中取成本是一个好主意。我认为还有另一种方法。

如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你想看我所有写作的列表,请点击这里查看我的网站。

同时,在我的推特这里关注我,访问我的网站,或者我的 Youtube 频道了解更多内容。我还实现了广残网,请点击这里查看博文 pos t。

参考

  1. NumPy . histogram—NumPy 1.14 版手册。(2018).Docs.scipy.org。检索于 2018 年 5 月 10 日,来自https://docs . scipy . org/doc/numpy-1 . 14 . 0/reference/generated/numpy . histogram . html
  2. pylab_examples 示例代码:histogram _ demo . py—Matplotlib 1 . 2 . 1 文档。(2018).Matplotlib.org。检索于 2018 年 5 月 10 日,来自https://matplotlib . org/1 . 2 . 1/examples/pylab _ examples/histogram _ demo . html
  3. (2018).Cis.hut.fi 于 2018 年 5 月 10 日检索,来自http://www.cis.hut.fi/research/som-research/teuvo.html
  4. t .科霍宁(1998 年)。自组织地图。神经计算,21(1–3),1–6。
  5. 自组织地图——IEEE 期刊和杂志。(2018).Ieeexplore.ieee.org。检索于 2018 年 5 月 11 日,来自https://ieeexplore.ieee.org/document/58325/
  6. SOM 教程第 1 部分。(2018).Ai-junkie.com。检索于 2018 年 5 月 11 日,来自http://www.ai-junkie.com/ann/som/som1.html
  7. CPU,H. (2018)。如何在 CPU 上运行 Tensorflow?堆栈溢出。检索于 2018 年 5 月 11 日,来自https://stack overflow . com/questions/37660312/how-to-run-tensor flow-on-CPU
  8. tensorflow,C. (2018)。改变张量流中张量的比例。堆栈溢出。检索于 2018 年 7 月 19 日,来自https://stack overflow . com/questions/38376478/changing-a-scale-of-a-tensor-in-tensor flow
  9. tf.random_uniform | TensorFlow。(2018).张量流。检索于 2018 年 7 月 19 日,来自https://www . tensor flow . org/API _ docs/python/TF/random _ uniform
  10. 使用 Google 的 TensorFlow 进行自组织地图。(2015).Sachin Joglekar 的博客。检索于 2018 年 7 月 19 日,来自https://codesachin . WordPress . com/2015/11/28/self-organizing-maps-with-Google-tensor flow/
  11. cgorman/tensorflow-som。(2018).GitHub。检索于 2018 年 7 月 19 日,来自https://github.com/cgorman/tensorflow-som
  12. t,V. (2018)。递归自组织映射。公共医学——NCBI。Ncbi.nlm.nih.gov。检索于 2018 年 7 月 19 日,来自https://www.ncbi.nlm.nih.gov/pubmed/12416688
  13. JaeDukSeo/忧郁。(2018).GitHub。检索于 2018 年 7 月 19 日,来自https://github.com/JaeDukSeo/somber
  14. [复本],H. (2018)。如何在 Matplotlib (python)中隐藏轴和网格线?堆栈溢出。检索于 2018 年 7 月 19 日,来自https://stack overflow . com/questions/45148704/how-to-hide-axes-and-gridlines-in-matplotlib-python
  15. 数据,S. (2017)。MNIST 数据的自组织映射。SurfingMLDL。检索于 2018 年 7 月 19 日,来自https://wonikjang . github . io/deep learning _ unsupervised _ som/2017/06/30/som . html
  16. 数据,S. (2017)。MNIST 数据的自组织映射。SurfingMLDL。检索于 2018 年 7 月 19 日,来自https://wonikjang . github . io/deep learning _ unsupervised _ som/2017/06/30/som . html

自助本地新闻

原文:https://towardsdatascience.com/self-serve-local-news-eaad4347b61f?source=collection_archive---------9-----------------------

在不稳定的媒体景观中提升同理心

眼前的危机

在互联网和唐纳德·特朗普(Donald Trump)总统任期的双重拐点上,美国新闻业陷入了危机。社交媒体和在线注意力经济扰乱了曾经支撑良好报道的经济模式和读者模式,导致印刷媒体大量解雇有才华的记者,并在数字媒体中转向愤怒、点击诱饵和企业赞助。与此同时——也许是同样的潜在技术文化转变的结果——至少自理查德·尼克松(如果不是更早的话)以来最公开反对新闻的总统的当选重新点燃了对媒体机构的普遍怀疑,并打破了对自由、独立新闻业的共识支持的假设。

但是,尽管在这个动荡的时代,全国的时报邮报吸引了人们的注意力,但首当其冲的冲击还是来自地方层面。皮尤研究中心最近的一项研究发现美国新闻编辑室的就业人数在 2008 年至 2017 年间下降了近四分之一,下降了 45 %,这对报纸来说损失更大。但中型报纸似乎失血最多;虽然自 2016 年以来,全国范围内的报道(具有讽刺意味的是)重新焕发了活力,超级地方报纸得到了其紧密联系的社区的支持,但许多城市地区媒体既缺乏读者支持,也缺乏经济偿付能力,无法跟上互联网出现前的标准。

不用说,这是一场民主危机。在第一修正案中,媒体的名字不仅是为了保证记者写作的权利,也是为了保证公民阅读的权利。毕竟,只有在知情的情况下,投票才是真正的民主。

这个问题的答案之一是通过新的经济模式和报道方法来振兴城市和地区报纸。一种可行的方法?通过将文案制作部分外包给外部合作伙伴,新闻编辑室的时间和精力支出可以削减,新闻编辑室之间的冗余(如多家城市报纸委托记者报道同一篇报道时的 T2)可以消除。当然,这已经是某些类型报道的标准,如联合通讯社(美联社)、多功能数据工具(ProPublica)或公共文档库(The Intercept)。但是,在创造独特的本地体验时,这些选择会遇到问题。例如,每份刊登路透社关于最新枪支管制措施的报道的城市报纸都会刊登相同的路透社报道,即使国家趋势或细节与那些对特定地方读者更有意义的报道不一致。

考虑一下 2015 年皮尤的一份报告,其中发现“每个城市大约十分之九的居民说他们至少在一定程度上密切关注当地的新闻,而大约十分之八的人说他们关注附近的新闻。”这些读者显然有兴趣了解这些问题——然而,如果没有经济上可行的渠道来满足他们的需求,这很可能得不到满足。通过重新思考记者如何在地区性和全国性报道之间斡旋,以及他们的雇主如何在两种报道之间分配资源,这一差距可以被填补。

地方报道的问题也是新闻效率的问题。通过将原本是全国性的故事地方化,抽象的问题变成了读者切实关心的问题。《纽约时报》的一篇关于美国毒品战争的文章可能会引起读者的兴趣,比如说,坦帕市的读者,但是对他们来说,改编成包含坦帕市具体细节的同一篇文章更有切身利益。如果新闻在很大程度上是政治教育的工具,而地方政治对读者有最明显的影响(至少在短期内),那么对于记者来说,在可能的情况下,通过本地化的镜头来探索大局问题是有意义的。

因此,自助式本地新闻的主张是:通过创建技术基础设施和报道流程,利用国家规模的资源进行本地规模的报道,有可能同时满足经济现实和现代本地新闻的内容需求。

新闻本地化

作为这一理论概念的证明,我们的团队选择了 Maimuna Majumder 年发表的一篇名为“仇恨犯罪率上升与收入不平等有关”的文章 Majumder 的文章使用数据分析在全国范围内探索了人均仇恨犯罪和经济不平等(以及在较小程度上的教育不平等)之间的联系。

我们选择对本文进行本地化试验有几个原因:

  1. 这个想法很有趣;特别是在特朗普意外赢得选举以及随后仇恨犯罪激增的背景下,Majumder 的论文激起了我们的兴趣。
  2. 它有明确定义的主张——仇恨犯罪和经济不平等是相关的;仇恨犯罪和教育水平是相关的——这可以用数量来检验。
  3. Majumder 在 GitHub 存储库中提供了她的所有数据,消除了许多来源挑战。
  4. 关于仇恨犯罪、经济不平等和教育不平等的数据是固有的地理,因此我们本地化文章的中心任务是有意义的。

为了开始开发一个系统来本地化 Majumder 的文章,我们首先创建了一个中性的文章“模板”版本,可以根据它修改版本。这包括从模板中删除任何特定日期的内容(因为这篇文章已经发表一年多了),并删除大部分解释 Majumder 统计分析方法的内容。这给我们留下了我们称之为的基础层

然后,我们必须收集所有必要的数据,以获取 Majumder 的故事,并放大到地方一级。这些本地数据来自各种来源。我们从美国人口普查局的年度美国社区调查中获取给定城市或州的人口统计数据,如经济不平等的基尼指数或高中毕业率。与此同时,仇恨犯罪的数据来自联邦调查局的统一犯罪报告计划,该计划汇编了当地机构的犯罪数据。最后,我们询问了南方贫困法律中心(SPLC ),寻找活跃在各州的仇恨组织。

除了 SPLC 的数据,我们利用了预计算的汇总统计数据。例如,对于毕业率,人口普查局已经收集了某个城市每个居民的教育程度的详细资料,并计算了至少获得高中学位的人的百分比。因此,获取数据意味着下载这些预先计算的百分比,而不是下载每个居民的教育记录。

然后,我们用编程语言 R 创建了一个数据框架,这将允许我们测试仇恨犯罪与经济不平等和教育率之间的相关性。将来自联邦调查局(仇恨犯罪)、SPLC(仇恨团体)和美国人口普查局(经济不平等和高中毕业率的基尼指数)的数据结合在一起,我们得到了一个强大的数据集,可以探索不同因素之间的关系,例如,在任何给定的城市或州,仇恨犯罪率和经济不平等在几年内的密切相关程度。为了计算相关性,我们只研究了拥有至少六年数据的城市和州。

从地区数据的特殊性转移到记者可能想告诉的关于地区数据的故事的大概情况,我们决定了可能有必要发表的八种一般类型的文章,这取决于记者为哪个城市或州写文章。这些文章基于三个二元价值观:

  1. 仇恨犯罪和经济不平等之间是否有统计学上的显著关系。
  2. 仇恨犯罪和教育水平之间是否有统计学上的显著关系。
  3. 给定区域是城市还是州。

因此我们有 222 个因素在起作用,或者总共八个可能的文章。我们将文章本地化的这一阶段概念化为一个决策树,由此利用关于数据的相关细节(在我们的数据集中识别的相关性)和用户输入(文章将被本地化的地理位置)来识别多个预先编写的文章框架中的哪个将被加载到系统中。

生成的树上的八个“叶子”中的每一个都用这些骨架中的一个来标识,这些骨架是通过修改基础层文章来组装的。我们有两种主要的方法来进行这种修改。

一种类型的修改是通过基于它们在文章中的相对重要性上下移动某些文本块来重新组织文章,基于这些重要性,趋势被识别为与给定位置相关。例如,一篇关于经济不平等和仇恨犯罪之间存在关联的城市的文章可能会强调这种关系,而一篇关于教育水平和仇恨犯罪之间存在关联的州的文章可能会强调这种关系。这植根于倒金字塔的新闻实践,即一篇文章中最重要的信息放在顶部。

另一种类型的修改是在文章框架中标识出内容中立的站点,在这里可以插入额外的特定位置信息。我们将文章本地化的这个阶段概念化为一个疯狂的 Libs 游戏。在 Mad Libs 中,提供了一个短篇故事的框架,但是为某些单词留出了空间。然而,为了在文章的上下文中有意义——并且模仿自然语言——这些插入的单词必须满足某些参数;最常见的是词类。类似地,我们的文章框架确定了什么类型的数据或其他信息可以自动插入给定框架的特定部分。但是,在一个疯狂的 Libs 游戏可能需要一个动词或名词的地方,文章骨架可能需要 X 国仇恨犯罪的最常见原因或 y 国的基尼指数。

首先,我们确定了近 70 种可以插入文章的数据特征:

然后,我们将这些数据点合并到我们的骨架中,根据这些数据点,在讲述一个属于决策树上八个分类之一的地方的故事时,哪一个最相关。这产生了八个最终骨骼,其中一个开始于:

带括号的紫色元素是插入的数据点,而绿色文本标识添加到基础层的任何副本。与此同时,括号中的橙色特性是 Mad Libs 风格插件的第二种类型,它需要更多的叙述性(而不是数字)细节。因为人们可能希望包含在文章中的某些特定于地点的“价值”——如轶事或引语——在有组织的数据库或电子表格中(还)不存在,这些地点向当地记者标识他们仍然需要出去做他们自己的报道的地方。然后,该系统的最终输出将使用相关值填充紫色要素,但不修改橙色要素。

本土化实践

如果一名记者正在为洛杉矶的一家报纸写作,这种两部分本地化方法将导致以下决策树…

…这将导致下面的文章框架…

…当系统插入相关数据点时,会输出最终文章…

八个可能的文章框架与 3020 个城市、44 个州和哥伦比亚特区的数据相结合,结果是一个灵活的系统,用于自动生成独特的定制文章,这些文章可以以相对较小的开销整合到全国各地的本地媒体。虽然不是这个过程的每个方面都是自动化的,也就是说,编写文章框架和填充橙色文本特征,但是这个过程确实提出了一种大规模生产本地化文章的可能方法。

使用 JavaScript libraries Mapbox 进行绘图,使用 D3.js 进行数据可视化,我们的团队开发了一个 web 应用程序,使得这个系统易于使用,并且对于没有计算机或数据科学背景的人来说也是可访问的:

通过点击他们的城市或州,一个资源稀缺的新闻编辑室不仅可以调出一篇充实的文章…

…而且还有有用的汇总统计数据…

…特定于地点的数据可视化…

…甚至还有一份简洁的提示表,如果文章内容本身没有必要,它会指出哪些内容仍然值得研究…

扩大范围

为了进一步发展这种概念验证,我们的团队决定将同样的方法应用于另一篇文章:本·卡塞尔曼的《2015 年警察杀死美国人的地方》,另一篇 538 文章。Casselman 的文章使用了美国人口普查局的数据和《卫报》关于警察杀人的数据项目,探讨了贫困、种族和该国警察杀害最多平民的地方之间的关系。

本地化这一叙述基本上遵循与以前相同的过程:

  1. 从初始副本创建一个中性的“基础层”。
  2. 聚合数据,并在数据框架中将它们连接在一起。
  3. 创建一个考虑规模(州或城市)和统计趋势(人均警察杀人事件和平均家庭收入是高于还是低于全国平均水平)的决策树。
  4. 识别可以插入的 Mad Libs 风格的特征(定量和定性),可以从数据集插入,也可以由本地记者插入。
  5. 修改基础层以考虑决策树结果(又是八种可能性)和 Mad Libs 特征。
  6. 将这个过程嵌入到基于地图的 web 应用中。
  7. 整合额外的数据可视化、汇总统计、提示表等。如有可能。
  8. 让记者了解结果。

主要依赖汇总统计回避了这种产品是否能扩展到大规模数据集的问题。例如,在处理警察杀人的文章时,我们遇到了一个数据集,它包含了几年来美国每一次警察杀人的记录。当用户点击一个特定的地点来查看自动生成的填充了相关数据的文章时,一种简单的方法是查询发生在特定城市的所有警察杀人事件的数据集,然后计算适当的信息。然而,这种方法在计算上是昂贵的低效的,因为相同的查询和计算可能被执行多次。一个更健壮的解决方案将涉及预计算每个城市的必要信息,并将这些信息存储在一个数据库中,该数据库将城市映射到它们的特定数据,这样每当用户点击一个特定的城市时,我们的系统将直接返回信息,而无需进行额外的计算。

例如,下图说明了当用户单击德克萨斯州的城市韦科时会发生什么。每一行都包含一个警察杀害受害者的信息。在前面提到的简单解决方案中,程序将搜索整个表,选择城市与 Waco 匹配的每一行。然而,在健壮的解决方案中,程序将搜索 Waco 并返回与之相关的数据块。因此,我们看到我们的程序对于大型数据集在计算上是可伸缩的。

大局

对于一个资金紧张、遭受多轮裁员、在一个适得其反的环境中努力维持读者信任的新闻编辑室来说,这种系统可以——在 AP 或 ProPublica 等组织的基础设施和报道支持下——将标准报道流程中涉及的大量体力劳动外包出去。目前,像数据采集、数据清理、统计分析、文章写作、源编辑、文案编辑、图形开发等工作对新闻编辑室来说是一个巨大的压力,并且还可能在报道类似问题的多个新闻编辑室之间造成劳动力冗余。如果这项工作被集中起来,它将为已经承受巨大压力的媒体机构减轻一个重大负担,即利用有限的资源制作大量高质量的内容。

与任何自动化一样,新闻编辑室可能会将此视为裁员的机会。但至少聪明的人会看到它的本来面目:让有才华的记者腾出手来从事更重要的工作的机会,比如激发同情心的人类兴趣报道或让当权者承担责任的深度调查报道。明智而充满激情地去做,最终的结果将是美国自由媒体的各个层面都变得更强大、更聪明、更有效。

笔记

这个项目是为斯坦福大学 2018 年秋季的课程“探索计算新闻学”(CS206/COMM281)创建的,与布朗媒体创新研究所合作。

两个网络应用都可以在这里访问:http://web.stanford.edu/~sharon19/.

特别感谢:

教授们。Krishna Bharat、Maneesh Agrawala 和 R.B. Brenner 在本项目过程中提供了真知灼见、指导和专家建议;

Maimuna Majumder、Ben Casselman 和 FiveThirtyEight 深刻的报告和可获得的数据;

Cheryl Phillips 教授、Dan Jenson 和斯坦福开放警务项目,感谢他们对本项目早期迭代的帮助;

以及所有参与实现这项工作的人。

图像引用:

图 1:皮尤研究中心(链接

图 5:萨姆·斯普林,中等(林克)

数据来源包括:

联邦调查局

《卫报》

南方贫困法律中心

美国人口普查局

华盛顿邮报

如果您有兴趣了解这项工作的更多信息,可以通过以下方式联系相关人员:

陈莎伦(sharon19@stanford.edu)

布莱恩·孔特雷拉斯(brianc42@stanford.edu,@ _ 布莱恩 _ 孔特雷拉斯 _)

黄志鹏(dhuang7@stanford.edu)

向利益相关者销售分析

原文:https://towardsdatascience.com/selling-analytics-to-your-stakeholders-3e516cd6cc2b?source=collection_archive---------10-----------------------

你不会想到你不得不卖掉这么值钱的东西。你错了。

我们刚刚完成了一个大规模数据收集和分析项目中最雄心勃勃的阶段。我们的一个关键项目发起人提出了一个关键问题:如果人们在内部截止日期后向我们提交,这对他们成功的机会有多大影响?因此,我们深入到新创建的工作流模式中,找出了答案。

这并没有伤害他们。事实上,这帮助了他们。这对他们帮助很大!他们给我们的时间越少,我们做得越好。*看,这里是曲线,*我们说。看看这个置信区间。让我们从时间的角度来看——哇,我们比以往任何时候都更擅长处理最后一分钟的提交。

我们的赞助商回复了。

“我不想再听了。我估计这个数据没用。”

什么?!

经过近两年的艰苦工作,从一个晦涩的供应商系统的噩梦般的事务模式中映射和提取数千个数据元素,我们能够将工作流里程碑和一些真正有趣的维度联系起来。

与此同时,我们的项目发起人已经为他们的内部客户忽略最后期限而奋斗了多年,让发起人的团队来收拾残局。这导致了高流动率、低工作满意度、高压力和低绩效。其中一个赞助者有一个想法:如果我们能让我们的客户看到,忽视截止日期会损害他们的成果,那么他们将不得不开始尊重我们!他在寻找一个数据大头棒来敲碎一些脑袋。

I think his plan went something like this

因此,我们尽职尽责地处理这些数字,自豪地展示我们现在能够提供的各种见解,这要归功于我们的 SQL 团队和数据分析师的不懈努力。正如你现在已经知道的,我们提供了一个非常有趣的见解。

这当然立刻开启了各种后续问题。我们的零假设:忽略截止日期的人和遵守截止日期的人在成功率上没有区别。我们的结果让这一切变得不可思议。但它做错了!分析师们接下来会有一大堆有趣的后续问题——我们会优先考虑这些迟交的问题吗?迟到的提交者是不是在骚扰我们的员工,只是成为吱吱作响的轮子?我们从哪里获得这些数据,电子邮件服务器日志和 PBX 日志?或者这只是一种关联,因为我们最成功的提交者也确实很忙,所以他们通常会延迟提交?

所以我们来参加会议,介绍我们的发现以及我们提出的所有有趣的后续问题。为了更好地了解我们的组织,我们制定了一个战略来追踪这一激动人心的线索。我们直接撞到了墙上。

我们不仅要学会做分析师,还要学会做分析理念和流程的销售人员。我们的项目发起人对我们正在做的事情感到非常兴奋,因为他们听说了其他人在“大数据”方面取得的成就他们思考了他们最大的问题,并将数据和分析视为解决问题的灵丹妙药,因为数据最终会证明他们是对的。我们谁都没有想到,他们给我们的第一个假设会是完全错误的。

事后看来,我们本可以做得更好,也应该做得更好的是,告诉他们数据可以帮助你提出正确的问题。然后它会帮助你找到答案!在这个框架中,一个不正确的假设并不是一件坏事——它真的很有趣!

但我们被赋予了一个特定的使命,我们傲慢地攻击了这些数据,认为其他人也会因为我们的结论而同样兴奋。所以我们走进一个会议,基本上是说,“嘿,你错了,但是看看我们发现的这些很酷的东西!”在“你错了”之后,我们强大的赞助商停止了倾听,并停止了讨论。

我们的项目发起人对他的业务线没有错,他对违法行为对他的办公室造成的不良影响也没有错,但 hr 错在只有一个假设,并把所有鸡蛋都放在那个篮子里。

我们将很快为不同的系统和不同的赞助商启动另一个数据提取项目。在我们进行这一旅程时,我打算记住以下几点,如果您有利益相关者赞助您自己的计划,这对您也可能有用:

  • 确认偏差是真实的。我们的利益相关者都是有才华的人,他们在职业生涯中已经升到了管理链的顶端。很可能你们中的一些人也是。而且,像我们一样,很可能你们的一些利益相关者在没有任何数据分析来支持他们的管理决策的情况下已经这样做了几十年。他们习惯于相信自己的直觉,并期望数据能完全支持他们的想法。
  • 公开表扬,私下批评。如果我们的发起人(或项目中的任何人)有一个未被证实的假设,公共项目会议不是揭开它的地方。提前与他们会面,填写表格,并在后续调查中获得他们的认可。这让他们认同这些努力,并让他们在公开会议上显得聪明,而不是错误。
  • 教授分析的过程,而不仅仅是结果。我们过于关注我们的潜在“胜利”对我们的数据来说有多么令人兴奋。我们的赞助商只有从同事和会议上获得的信息,这些信息是“管理层”的总结信息。对这一过程的更广泛的理解会导致更多好奇的利益相关者,他们会更支持有机调查。
  • “做点什么”数据。我们不会只是等待我们的利益相关者告诉我们他们想知道什么。当我们把新的数据集放到网上时,我们会主动挖掘它们以获得有趣的(也许是令人愉快的)见解。如果我们需要捍卫一个不受欢迎的观点,这将给我们一些政治信用。这也意味着我们的利益相关者将被介绍给对我们有利的数据,而不是根据他们自己想法的价值来掷骰子。

乔纳森是加州大学洛杉矶分校研究信息系统的助理主任。在获得斯坦福大学的物理学学位后,他在信息系统架构、数据驱动的业务流程改进和组织管理领域工作了 10 多年。他还是Peach Pie Apps Workshop的创始人,这是一家专注于为非营利和小型企业构建数据解决方案的公司。

销售您的数据科学项目

原文:https://towardsdatascience.com/selling-your-data-science-project-7e3e06f91ec6?source=collection_archive---------5-----------------------

无论你的数据科学项目有多伟大,如果没有人想要,它都是徒劳的。如果我们不能让其他人相信我们的工作会改善他们的生活,或者至少有这种潜力,它就会一直呆在某个服务器上,直到它坏掉停止工作。

但是,告诉顾客为什么我们的工作会让他们的生活变得更好,正确的方法是什么呢?创建销售文档或演示文稿,列出我们的数据科学应用程序可以做的所有闪亮的新东西是非常诱人的。我们努力开发这些功能,每个人都会喜欢的,对吗?

不完全是。首先,很有可能你的目标受众不具备理解你所推销的东西的技术能力。毕竟,如果他们有你的技术技能,他们就不会考虑雇佣数据科学,他们只会自己做。当你创建一份销售文件时,你首先要做的是尽量减少对最新工具的引用,让他们知道你知道你在做什么。

下一个问题是,你不能相信客户意识到你的解决方案是如何帮助他们走出目前的困境的。此外,让他们替你做事是不尊重你的。因此,你需要确保你的推销在你打算为客户做什么和如何让他们的生活变得更轻松之间加入了点。

在销售行话中,这被称为“销售好处”,也就是说,让潜在客户清楚购买你的产品将如何改善他们的生活,这被概括为一句话“没有人想买床,他们想睡个好觉”。困难在于,在大多数数据科学场景中,与潜在利益相对应的问题是业务问题,如库存减少或销售成本下降,而不是人的问题,如睡个好觉。

因此,要想完成从功能到益处的旅程,需要对客户的业务有所了解(尽管每个人都知道睡个好觉的好处——以及睡不好觉的可怕之处——但在床垫弹性和床结构的细节方面,了解的人要少得多),还需要能够解释其中的联系。最后一点至关重要,因为你的工作带来的好处太重要了,不能让你的客户错过。

所有这一切最终意味着,希望找到“洞见”的检查数据集的方法往往会失败,甚至可能是危险的。相反,您需要从您的客户想要实现什么、他们面临什么问题开始,然后才能看到哪些问题与可用于构建工具来解决问题的数据相对应。在这方面,古老的格言“你生来就有两只耳朵和一张嘴,所以多听少说”开始发挥作用。

如果你成为一名数据科学家,部分原因是你的气质更适合安静地分析数据,而不是高兴地接待客户,那么销售的整个概念可能听起来令人生畏。不过,这听起来不应该太令人畏惧。上面的建议同样适用于内部销售——向公司的其他部门销售——也适用于外部销售。如果你想在内部销售,应该有很多机会去发现是什么让你公司的其他人感到痛苦。人们喜欢谈论自己,世界上许多人都不会错过抱怨的机会。

如果涉及外部销售,很有可能正在使用或可能会使用团队销售方法。在这种情况下,您将作为首席销售人员的技术支持。让你的首席销售人员做他们最擅长的事情——培养关系,获得领导地位,介绍你的业务,让客户兴奋起来。

利用这段时间尽可能多地学习,找出客户生活中不尽如人意的地方,并搭配您的分析解决方案,使其变得简单。如果一个客户的生活已经够痛苦了,那么只要有人能解决这个问题,他们就会立刻掏出自己的支票簿。

这篇文章的早期版本也出现在我的博客上,名为“销售和数据科学”。详见本页同系列后续文章。

SELU——让 FNNs 再次伟大(SNN)

原文:https://towardsdatascience.com/selu-make-fnns-great-again-snn-8d61526802a9?source=collection_archive---------1-----------------------

上个月,我看到了一篇最近的文章(发表于 2017 年 6 月 22 日),文章提出了一个新概念,叫做自归一化网络(SNN)。在这篇文章中,我将回顾它们的不同之处,并展示一些对比。
文章链接——Klambauer 等人
本帖代码摘自bio info-jku 的 github

这个想法

在我们进入什么是 SNN 之前,让我们谈谈创建它们的动机。作者在文章的摘要中提到了一个很好的观点;虽然神经网络在许多领域获得了成功,但似乎主要阶段属于卷积网络和递归网络(LSTM,GRU),而前馈神经网络(FNNs)被留在初学者教程部分。
还要注意的是,在 Kaggle 取得胜利结果的 FNN 最多只有 4 层。

当使用非常深的架构时,网络变得容易出现梯度问题,这正是批量归一化成为标准的原因——这是作者将 FNNs 的薄弱环节放在训练中对归一化的敏感性上的地方。
snn 是一种替代使用外部标准化技术(如 batch norm)的方法,标准化发生在激活函数内的**。
为了清楚起见,激活函数建议(SELU-比例指数线性单位)输出归一化值,而不是归一化激活函数的输出。
为了使 SNNs 工作,它们需要两样东西,一个定制的权重初始化方法和 SELU 激活函数。**

认识 SELU

在我们解释它之前,让我们看一下它是关于什么的。

Figure 1 The scaled exponential linear unit, taken from the article

SELU 是某种 ELU,但有一点扭曲。
α和λ是两个固定的参数,这意味着我们不会通过它们进行反向传播,它们也不是需要做出决策的超参数。
α和λ是从输入中得到的——我不会深入讨论这个,但是你可以在文章中看到你自己的数学计算(有 93 页附录:O,数学计算)。
对于标准比例输入(平均值为 0,标准偏差为 1),值为α=1.6732~,λ=1.0507~。
让我们绘制图表,看看这些值是什么样子。

Figure 2 SELU plotted for α=1.6732~, λ=1.0507~

看起来很像 leaky ReLU,但等着看它的魔力吧。

重量初始化

SELU 不能让它单独工作,所以一个定制的权重初始化技术正在使用。
SNNs 用零均值初始化权重,并使用 1/(输入大小)的平方根的标准偏差。
代码如下所示(摘自开篇提到的 github)

# Standard layer
tf.Variable(tf.random_normal([n_input, n_hidden_1], stddev=np.sqrt(
1 / n_input))# Convolution layer
tf.Variable(tf.random_normal([5, 5, 1, 32], stddev=np.sqrt(1/25)))

现在我们已经了解了初始化和激活方法,让我们开始工作吧。

表演

让我们看看 SNNs 如何使用指定的初始化和 SELU 激活函数在 MNIST 和 CIFAR-10 数据集上运行。
首先,让我们看看在 2 层 SNN(两个隐藏层都是 784 个节点,MNIST)上使用 TensorBoard 是否真的保持了输出的标准化。
绘制第 1 层的激活函数输出和第 2 层的权重。
github 代码中没有layer1_act的绘图,我是为了这个直方图才添加的。

Figure 3 SELU’s output after the first layer in the MLP from the github

Figure 4 Second layer’s weights on the second layer.

不出所料,第一层的激活和第二层产生的权重几乎都是完美的零均值(我在运行中得到 0.000201)。
相信我,直方图在第一层权重上几乎是一样的。

更重要的是,snn 似乎能够表现得更好,正如你从提到的 github 的图中看到的那样,比较了 3 个具有相同架构的卷积网络,只是它们的激活功能和初始化不同。
SELU vs ELU vs 雷鲁。

似乎 SELU 收敛得更好,在测试集上得到更好的精度。

请注意,使用 SELU +上述初始化,我们在 CNN 网络上获得了更高的精度和更快的收敛速度,因此不要犹豫,在非纯 FNN 的架构上尝试它,因为它似乎也能够提高其他架构的性能。

结论和进一步阅读

看起来 snn 确实可以在神经网络的世界中找到自己的位置,也许可以在更短的时间内提高一点额外的准确性——但我们必须等待,看看它们自己会产生什么结果,更重要的是整合到联合架构中(就像上面的 conv-snn)。也许我们会在竞赛获奖的建筑中遇到他们,谁知道呢。

有些东西我没有在这里讨论,但在这篇文章中提到了,比如提议的“alpha dropout ”,这是一种符合 SNNs 概念的 dropout 技术,也在提到的 github 中实现,所以非常欢迎您深入研究。

SNNs 是不是一个东西,我真的不知道,但他们是另一个工具添加到您的工具包。希望你喜欢这篇文章并学到一些新东西:)

如何用深度学习创建任意对象的自然语言语义搜索

原文:https://towardsdatascience.com/semantic-code-search-3cd6d244a39c?source=collection_archive---------3-----------------------

这是一个端到端的例子,展示了如何构建一个可以在语义上搜索对象的系统。由哈默尔侯赛因 & 吴和祥

A picture of Hubot.

动机:

现代搜索引擎的力量是不可否认的:你可以随时从互联网上获取知识。不幸的是,这种超级力量并非无处不在。在许多情况下,搜索被归为严格的关键字搜索,或者当对象不是文本时,搜索可能不可用。此外,严格的关键字搜索不允许用户进行语义上的搜索,这意味着信息不容易被发现。

今天,我们分享一个可复制的、最低限度可行的产品,它展示了如何为任意对象启用语义搜索!具体来说,我们将向您展示如何创建一个从语义上搜索 python 代码的系统——但是这种方法可以推广到其他实体(比如图片或声音剪辑)。

语义搜索为什么这么激动人心?考虑下面的例子:

Semantic search at work on python code. *See Disclaimer section below.

呈现的搜索查询是“ Ping REST api 并返回结果”。然而,即使找到的代码&注释不包含单词 Ping、RESTapi,搜索也会返回合理的结果。

这说明了 语义搜索 威力:除了关键词之外,我们还可以搜索内容的含义,最大限度地提高用户找到所需信息的几率。语义搜索的含义是深远的——例如,这样一个过程将允许开发人员在存储库中搜索代码,即使他们不熟悉语法或者没有预料到正确的关键字。更重要的是,你可以将这种方法推广到图片、音频和其他我们还没有想到的东西。

如果这还不够令人兴奋的话,这里有一个现场演示,展示在本教程结束时你能够构建的东西:

Sometimes I use Jupyter notebooks and custom magic functions to create demonstrations when I cannot build a pretty website. it can be a quick way to interactively demonstrate your work!

直觉:构建一个共享的向量空间

在深入研究技术细节之前,向您提供一个关于我们将如何完成语义搜索的高层次直觉是很有用的。中心思想是在一个共享的向量空间中表示文本和我们想要搜索的对象(代码),如下所示:

Example: Text 2 and the code should be represented by similar vectors since they are directly related.

目标是将代码映射到自然语言的向量空间中,使得描述相同概念的(文本,代码)对是近邻,而不相关的(文本,代码)对则相距更远,通过余弦相似度来测量。

有许多方法可以实现这一目标,但是,我们将展示一种方法,即采用一个预先训练好的模型从代码中提取特征,然后微调这个模型,将潜在的代码特征投射到自然语言的向量空间中。一个警告:在本教程中,我们交替使用术语 向量嵌入*。*

{ 2020 年 1 月 1 日更新}:代码搜索网

这篇博文中介绍的技术是旧的,并且在随后的一个名为 CodeSearchNet 的项目中得到了显著的改进,并附有一篇相关的论文

我建议看看前面提到的项目,寻找一种更现代的方法来解决这个问题,因为回想起来这篇博文有点丑陋。

先决条件

我们建议在阅读本教程之前熟悉以下内容:

  • **序列对序列模型:回顾一下之前教程中的信息会很有帮助。
  • 从高层次阅读本文,理解所介绍方法的直觉。我们利用类似的概念在这里介绍。

概述:

本教程将分为 5 个具体步骤。这些步骤如下所示,在您学习本教程的过程中,它们将成为有用的参考。完成本教程后,重新查看此图以强调所有步骤是如何结合在一起的,这将非常有用。

A mind map of this tutorial. Hi-res version available here.

每一步 1-5 对应一个 Jupyter 笔记本这里。我们将在下面更详细地探讨每个步骤。

第 1 部分—获取和解析数据:

第一部笔记本

谷歌的人从开源的 GitHub 仓库收集数据并存储在 BigQuery 上。这是一个非常棒的开放数据集,适合各种有趣的数据科学项目,包括这个!当你注册一个谷歌云账户时,他们会给你 300 美元,这足够你查询这个练习的数据了。获取这些数据非常方便,因为您可以使用 SQL 查询来选择您要查找的文件类型以及关于 repos 的其他元数据,如 commits、stars 等。

笔记本中概述了获取这些数据的步骤。幸运的是,Google的 Kubeflow 团队中一些出色的人已经经历了这些步骤,并慷慨地为这个练习托管了数据,这也在本笔记本中有所描述。

收集完这些数据后,我们需要将这些文件解析成(code, docstring )对。对于本教程,一个代码单元要么是一个顶级函数,要么是一个方法。我们希望收集这些对作为模型的训练数据,该模型将总结代码(稍后将详细介绍)。我们还希望剥离所有注释的代码,只保留代码。这似乎是一项艰巨的任务,然而,在 Python 的标准库中有一个名为 ast 的惊人的库,可用于提取函数、方法和文档字符串。我们可以通过使用 Astor 包将代码转换成一个 AST ,然后再从该表示转换回代码,从而从代码中删除注释。本教程不要求理解 ASTs 或这些工具是如何工作的,但这是非常有趣的话题!

For more context of how this code is used, see this notebook.

为了准备用于建模的数据,我们将数据分为训练集、验证集和测试集。我们还维护文件(我们称之为“沿袭”)来跟踪每个(code,docstring)对的原始来源。最后,我们对不包含 docstring 的代码应用相同的转换,并单独保存,因为我们也希望能够搜索这些代码!

第 2 部分——使用 Seq2Seq 模型构建代码摘要:

第二部分笔记本

从概念上讲,构建一个序列到序列的模型来汇总代码与我们之前介绍的 GitHub 问题汇总器是相同的——我们使用 python 代码代替问题主体,使用文档字符串代替问题标题。

然而,与 GitHub 问题文本不同,代码不是自然语言。为了充分利用代码中的信息,我们可以引入特定于域的优化,比如基于树的 LSTMs 和语法感知标记化。对于本教程,我们将保持简单,像对待自然语言一样对待代码(并且仍然得到合理的结果)。

构建一个函数摘要器本身是一个非常酷的项目,但是我们不会花太多时间在这上面(但是我们鼓励你这么做!).本笔记本中的描述了该模型的整个端到端培训流程。我们不讨论该模型的预处理或架构,因为它与问题汇总器相同。

我们训练这个模型的动机不是将它用于总结代码的任务,而是作为代码的通用特征提取器。从技术上讲,这一步是可选的,因为我们只是通过这些步骤来初始化相关下游任务的模型权重。在后面的步骤中,我们将从这个模型中提取编码器,并为另一个任务微调。下面是该模型的一些示例输出的屏幕截图:

Sample results from function summarizer on a test set. See notebook here.

我们可以看到,虽然结果并不完美,但有强有力的证据表明,该模型已经学会了从代码中提取一些语义,这是我们这项任务的主要目标。我们可以使用 BLEU metric 对这些模型进行量化评估,在本笔记本中也有讨论。

应该注意的是,训练 seq2seq 模型来总结代码并不是构建代码特征提取器的唯一方法。例如,你也可以训练一个 GAN使用鉴别器作为特征提取器。然而,这些其他方法超出了本教程的范围。

第 3 部分—训练一个语言模型来编码自然语言短语

第三部分笔记本

现在我们已经建立了一个将代码表示为向量的机制,我们需要一个类似的机制来编码自然语言短语,就像在文档字符串和搜索查询中找到的那些一样。

有太多的通用预训练模型可以生成高质量的短语嵌入(也称为句子嵌入)。这篇文章提供了一个很好的景观概述。例如,谷歌的通用句子编码器在许多情况下都工作得很好,并且在 Tensorflow Hub 上有售。

尽管这些预先训练的模型很方便,但是训练一个捕捉特定领域词汇和文档字符串语义的模型可能是有利的。有许多技术可以用来创建句子嵌入。这些方法从简单的方法,如平均单词向量到更复杂的技术,如用于构建通用句子编码器的技术。

对于本教程,我们将利用一个神经语言模型,使用一个 AWD LSTM 来生成句子的嵌入。我知道这听起来可能有点吓人,但是精彩的 fast.ai 库提供了一些抽象概念,允许您利用这项技术,而不必担心太多的细节。下面是我们用来构建这个模型的一段代码。有关该代码如何工作的更多内容,请参见本笔记本

Part of the train_lang_model function called in this notebook. Uses fast.ai.

在构建语言模型时,仔细考虑用于训练的语料库非常重要。理想情况下,您希望使用与下游问题领域相似的语料库,这样您就可以充分捕获相关的语义和词汇。例如,这个问题的一个很好的语料库是栈溢出数据,因为这是一个包含非常丰富的代码讨论的论坛。然而,为了保持本教程的简单性,我们重用了一组文档字符串作为我们的语料库。这是次优的,因为关于堆栈溢出的讨论通常包含比单行 docstring 更丰富的语义信息。我们把它作为一个练习,让读者通过使用替代语料库来检查对最终结果的影响。

在我们训练语言模型之后,我们的下一个任务是使用这个模型为每个句子生成一个嵌入。这样做的一个常见方法是总结语言模型的隐藏状态,例如本文中的 concat 池方法。然而,为了简单起见,我们将简单地计算所有隐藏状态的平均值。我们可以用这行代码从 fast.ai 语言模型中提取隐藏状态的平均值:

How to extract a sentence embedding from a fast.ai language model. This pattern is used here.

评估句子嵌入的一个好方法是测量这些嵌入对下游任务的有效性,如情感分析、文本相似性等。你可以经常使用通用基准测试,比如这里列出的例子来测量你的嵌入的质量。然而,这些通用的基准可能不适合这个问题,因为我们的数据是非常具体的领域。不幸的是,我们还没有为这个领域设计一套可以开源的下游任务。在没有这种下游任务的情况下,我们至少可以通过检查我们知道应该相似的短语之间的相似性来检查这些嵌入是否包含语义信息。下面的屏幕截图展示了一些例子,在这些例子中,我们根据用户提供的短语(摘自本笔记本)来搜索矢量化文档字符串的相似性:

Manual inspection of text similarity as a sanity check. More examples in this notebook.

应该注意的是,这只是一个健全性检查——更严格的方法是测量这些嵌入对各种下游任务的影响,并使用它来形成关于您的嵌入质量的更客观的意见。关于这个话题的更多讨论可以在这本笔记本中找到。

第 4 部分—将代码向量映射到与自然语言相同的向量空间的训练模型

第四部分笔记本

在这一点上,重温一下本教程开始时介绍的图表可能会有所帮助。在该图中,您可以找到第 4 部分的图示:

A visual representation of the tasks we will perform in Part 4

这一步的大部分内容来自本教程前面的步骤。在这一步中,我们将对第 2 部分中的 seq2seq 模型进行微调,以预测文档字符串嵌入,而不是文档字符串。下面是我们用来从 seq2seq 模型中提取编码器并添加密集层进行微调的代码:

Build a model that maps code to natural language vector space. For more context, see this notebook.

在我们训练该模型的冻结版本之后,我们解冻所有层,并训练该模型几个时期。这有助于对模型进行微调,使其更接近这个任务。你可以在这本笔记本中看到完整的训练程序。

最后,我们希望对代码进行矢量化,以便构建搜索索引。出于评估的目的,我们还将对不包含 docstring 的代码进行矢量化,以查看该过程对我们尚未看到的数据的推广情况。下面是完成这项任务的代码片段(摘自本笔记本)。请注意,我们使用 ktext 库将我们在训练集上学到的相同预处理步骤应用于该数据。

Map code to the vector space of natural language with the code2emb model. For more context, see this notebook.

收集了矢量化代码后,我们就可以开始最后一步了!

第 5 部分—创建语义搜索工具

第五部分笔记本

在这一步中,我们将使用我们在前面步骤中创建的工件构建一个搜索索引,如下图所示:

Diagram of Part 5 (extracted from the main diagram presented at the beginning)

在第 4 部分中,我们对不包含任何文档字符串的所有代码进行了矢量化。下一步是将这些向量放入搜索索引中,这样可以快速检索最近的邻居。一个很好的用于快速最近邻查找的 python 库是 nmslib 。要享受使用 nmslib 的快速查找,您必须预先计算搜索索引,如下所示:

How to create a search index with nmslib.

现在您已经构建了代码向量的搜索索引,您需要一种将字符串(查询)转换成向量的方法。为此,您将使用第 3 部分中的语言模型。为了简化这个过程,我们在 lang_model_utils.py 中提供了一个名为 Query2Emb 的助手类,在本笔记本中的中演示了这个类。

最后,一旦我们能够将字符串转换成查询向量,我们就可以检索该向量的最近邻居,如下所示:

*idxs, dists = self.search_index.knnQuery(query_vector, k=k)*

搜索索引将返回两个项目(1)索引列表,这些索引是数据集中最近邻居的整数位置(2)这些邻居与您的查询向量的距离(在这种情况下,我们将索引定义为使用余弦距离)。一旦有了这些信息,构建语义搜索就简单了。下面的代码概述了如何实现这一点的示例:

A class that glues together all the parts we need to build semantic search.

最后,这个笔记本向你展示了如何使用上面的 search_engine 对象来创建一个交互式演示,如下所示:

This is the same gif that was presented at the beginning of this tutorial.

恭喜你!您刚刚学习了如何创建语义搜索。我希望这次旅行是值得的。

等等,你说搜查任意的东西?

尽管本教程描述了如何为代码创建语义搜索,但是您可以使用类似的技术来搜索视频、音频和其他对象。与使用从代码中提取特性的模型(第 2 部分)不同,您需要训练或找到一个预先训练好的模型,从您选择的对象中提取特性。唯一的先决条件是,您需要一个足够大的带有自然语言注释的数据集(比如音频的文字记录,或者照片的标题)。

我们相信您可以使用在本教程中学到的想法来创建自己的搜索,并希望收到您的来信,看看您创建了什么(参见下面的联系部分)。

限制和遗漏

  • {Update 1/1/20202}:这篇博文中讨论的技术已经过时,尤其是关于模型架构和技术。对于同一项目的更新版本,请参见 CodeSearchNet 项目和相关论文
  • 这篇博文中讨论的技术是经过简化的,并且仅仅触及了可能的表面。我们提供的是一个非常简单的语义搜索—但是,为了使这种搜索有效,您可能需要使用关键字搜索和其他过滤器或规则来增强这种搜索(例如,搜索特定回购、用户或组织的能力以及通知相关性的其他机制)。
  • 有机会使用利用代码结构的特定领域架构,例如树-lstms 。此外,还有其他标准技巧,如利用注意力随机教师强迫,为了简单起见,我们省略了这些技巧。
  • 我们忽略的一部分是如何评估搜索。这是一个复杂的主题,值得在自己的博客上发表。为了有效地迭代这个问题,你需要一个客观的方法来衡量你的搜索结果的质量。这将是未来博客文章的主题。

取得联系!

我们希望你喜欢这篇博文。请随时与我们联系:

资源

谢谢

实体模型搜索界面是由贾斯汀·帕尔默设计的(你可以在这里看到他的其他作品)。也感谢以下人员的评论和投入:艾克·奥康科沃大卫·希恩金梁

放弃

本文中提出的任何想法或观点都是我们自己的。提出的任何想法或技术不一定预示 GitHub 的未来产品。这个博客的目的只是为了教育。

基于深度学习的语义分割

原文:https://towardsdatascience.com/semantic-segmentation-with-deep-learning-a-guide-and-code-e52fc8958823?source=collection_archive---------1-----------------------

指南和代码

Semantic Segmentation

想获得灵感?快来加入我的 超级行情快讯 。😎

什么是语义切分?

深度学习和计算机视觉社区的大多数人都明白什么是图像分类:我们希望我们的模型告诉我们图像中存在什么单个对象或场景。分类很粗,层次很高。

许多人也熟悉对象检测,我们试图通过在它们周围绘制边界框,然后对框中的内容进行分类,来对图像中的多个对象进行定位和分类。检测是中级的,我们有一些非常有用和详细的信息,但仍然有点粗糙,因为我们只画了边界框,并没有真正得到对象形状的准确想法。

语义分割是这三者中信息量最大的,我们希望对图像中的每一个像素进行分类,就像你在上面的 gif 中看到的那样!在过去的几年里,这完全是通过深度学习来完成的。

在本指南中,您将了解语义分割模型的基本结构和工作原理,以及所有最新、最棒的最先进方法。

如果您想亲自尝试这些模型,您可以查看我的语义分割套件,其中包含 TensorFlow 培训和本指南中许多模型的测试代码!

[## GeorgeSeif/语义分段套件

TensorFlow 中的语义切分套件。轻松实现、训练和测试新的语义分割模型!…

github.com](https://github.com/GeorgeSeif/Semantic-Segmentation-Suite)

基本结构

我将要向您展示的语义分割模型的基本结构存在于所有最先进的方法中!这使得实现不同的应用程序变得非常容易,因为几乎所有的应用程序都有相同的底层主干、设置和流程。

U-Net 模型很好地说明了这种结构。模型的左侧代表**为图像分类而训练的任何特征提取网络。**这包括像 VGGNet、ResNets、DenseNets、MobileNets 和 NASNets 这样的网络!在那里你真的可以使用任何你想要的东西。

选择用于特征提取的分类网络时,最重要的是要记住权衡。使用一个非常深的 ResNet152 会让你非常准确,但不会像 MobileNet 那样快。将这些网络应用于分类时出现的权衡也出现在将它们用于分割时。需要记住的重要一点是在设计/选择您的细分网络时,这些主干将是主要驱动因素,这一点我再强调也不为过。

U-Net model for segmentation

一旦这些特征被提取出来,它们将在不同的尺度下被进一步处理。原因有两个。首先,你的模型很可能会遇到许多不同大小的物体;以不同的比例处理要素将赋予网络处理不同规模要素的能力。

第二,当执行分段时,有一个折衷。如果你想要好的分类准确度,那么你肯定会想要在网络的后期处理那些高级特征,因为它们更有鉴别能力,包含更多有用的语义信息。另一方面,如果你只处理那些深度特征,由于分辨率低,你不会得到好的定位!

最近最先进的方法都遵循上面的特征提取结构,然后是多尺度处理。因此,许多都非常易于端到端的实施和培训。您选择使用哪一个将取决于您对准确性与速度/内存的需求,因为所有人都在尝试提出新的方法来解决这一权衡,同时保持效率。

在接下来的最新进展中,我将把重点放在最新的方法上,因为在理解了上面的基本结构之后,这些方法对大多数读者来说是最有用的。我们将按照大致的时间顺序进行演练,这也大致对应于最新技术的发展。

最先进的漫游

全分辨率残差网络(FRRN)

FRRN 模型是多尺度处理技术的一个非常明显的例子。它使用两个独立的流来实现这一点:剩余流和池流。

我们希望处理这些语义特征以获得更高的分类精度,因此 FRRN 逐步处理和缩减采样池流中的特征映射。同时,它在残差流中以全分辨率处理特征图。所以池流处理高级语义信息(为了高分类精度),残差流处理低级像素信息(为了高定位精度)!

现在,由于我们正在训练一个端到端网络,我们不希望这两个流完全断开。因此,在每次最大池化后,FRRN 对来自两个流的特征地图进行一些联合处理,以组合它们的信息。

FRRN model structure

金字塔场景解析网络

FRRN 在直接执行多尺度处理方面做得很好。但是在每一个尺度上进行繁重的处理是相当计算密集的。此外,FRRN 做一些全分辨率的处理,非常慢的东西!

PSPNet 提出了一个聪明的方法来解决这个问题,通过使用*多尺度池。*它从标准特征提取网络(ResNet、DenseNet 等)开始,并对第三次下采样的特征进行进一步处理。

为了获得多尺度信息,PSPNet 使用 4 种不同的窗口大小和步长应用 4 种不同的最大池操作。这有效地从 4 个不同的尺度捕获特征信息,而不需要对每个尺度进行大量的单独处理!我们简单地对每个图做一个轻量级的卷积,然后进行上采样,这样每个特征图都有相同的分辨率,然后把它们连接起来。

瞧啊。我们已经合并了多尺度特征地图,而没有对它们应用很多卷积!

所有这些都是在较低分辨率的特征图上完成的。最后,我们使用双线性插值将输出分割图放大到期望的大小。这种仅在所有处理完成后才进行升级的技术出现在许多最新的作品中。

PSPNet model structure

一百层提拉米苏

如果深度学习带来了一种令人敬畏的趋势,那就是令人敬畏的研究论文名称!百层提拉米苏(听起来很好吃!)使用了和我们之前看到的 U-Net 架构类似的结构。主要贡献是巧妙使用了类似于 DenseNet 分类模型的密集连接。

这确实强调了计算机视觉的强大趋势,其中特征提取前端是在任何其他任务中表现良好的主要支柱。因此,寻找精度增益的第一个地方通常是您的特征提取前端。

FCDenseNet model structure

重新思考阿特鲁卷积

DeepLabV3 和是另一种进行多尺度处理的聪明方法,这次没有增加参数

这个模型非常轻便。我们再次从特征提取前端开始,获取第四次下采样的特征用于进一步处理。这个分辨率非常低(比输入小 16 倍),因此如果我们能在这里处理就太好了!棘手的是,在如此低的分辨率下,由于像素精度差,很难获得良好的定位。

这就是 DeepLabV3 的主要贡献所在,它巧妙地使用了阿特鲁卷积。常规卷积只能处理非常局部的信息,因为权重总是彼此紧挨着。例如,在标准的 3×3 卷积中,一个权重与任何其他权重之间的距离只有一个步长/像素。

对于 atrous 卷积,我们将直接增加卷积权重之间的间距,而不会实际增加运算中权重的数量。因此,我们仍然使用一个总共有 9 个参数的 3x3,我们只是将相乘的权重间隔得更远!每个砝码之间的距离称为膨胀率。下面的模型图很好地说明了这个想法。

当我们使用低膨胀率时,我们将处理非常局部/低尺度的信息。当我们使用高膨胀率时,我们处理更多的全局/高尺度信息。因此,DeepLabV3 模型混合了具有不同膨胀率的 atrous 卷积来捕捉多尺度信息。

在 PSPNet 中解释的所有处理之后,在最后进行升级的技术也在这里完成。

DeepLabV3 model structure

多路径细化网络

我们之前已经看到 FRRN 是如何成功地将来自多个分辨率的信息直接组合在一起的。缺点是在如此高的分辨率下处理是计算密集型的,我们仍然需要处理和结合那些低分辨率的特征!

RefineNet 模型说我们不需要这样做。当我们通过特征提取网络运行输入图像时,我们自然会在每次下采样后获得多尺度特征图。

然后,RefineNet 以自下而上的方式处理这些多分辨率特征图,以组合多尺度信息。首先,独立处理每个特征图。然后,当我们放大时,我们将低分辨率的特征图与高分辨率的特征图结合起来,对它们一起做进一步的处理。因此,多尺度特征地图被独立地和一起处理。在下图中,整个过程从左向右移动。

这里也采用了 PSPNet 和 DeepLabV3 中所述的在所有处理结束后进行升级的技术。

RefineNet model structure

大内核问题(GCN)

之前,我们看到了 DeepLabV3 模型如何使用具有不同膨胀率的 atrous 卷积来捕捉多尺度信息。棘手的是,我们一次只能处理一个秤,然后必须将它们组合起来。例如,速率为 16 的 atrous 卷积不能很好地处理局部信息,必须在以后与来自速率小得多的卷积的信息相结合,以便在语义分割中表现良好。

因此,在以前的方法中,多尺度处理首先单独发生,然后将结果组合在一起。如果能一次性获得多尺度信息,那就更有意义了。

为了做到这一点,全球卷积网络(GCN) 巧妙地提出使用大型一维核,而不是方形核。对于像 3x3、7x7 等这样的平方卷积,我们不能让它们太大而不影响速度和内存消耗。另一方面,一维内核的缩放效率更高,我们可以在不降低网络速度的情况下将它们做得很大。这张纸甚至被放大到了 15 号!

你必须确保做的重要的事情是平衡水平和垂直回旋。此外,该论文确实使用了具有低滤波器数的小 3×3 卷积,以有效细化一维卷积可能遗漏的任何内容。

GCN 遵循与以前作品相同的风格,从特征提取前端处理每个尺度。由于一维卷积的效率,GCN 在所有尺度上执行处理,一直到全分辨率,而不是保持小规模,然后扩大规模。这允许在我们按比例放大时不断细化分割,而不是由于停留在较低分辨率而可能发生的瓶颈。

GCN model structure

DeepLabV3+

DeepLabV3+ 模型,顾名思义,是 DeepLabV3 的快速扩展,从它之前的进步中借用了一些概念上的想法。正如我们之前看到的,如果我们只是简单地等待在网络末端使用双线性插值来扩大规模,就会存在潜在的瓶颈。事实上,最初的 DeepLabV3 模型在结尾被 x16 升级了!

为了解决这个问题,DeepLabV3+建议在 DeepLabV3 之上添加一个中间解码器模块。通过 DeepLabV3 处理后,特征由 x4 进行上采样。然后,它们与来自特征提取前端的原始特征一起被进一步处理,然后被 x4 再次放大。这减轻了网络末端的负载,并提供了从特征提取前端到网络近端的快捷路径。

DeepLabV3+ model structure

CVPR 和 ECCV 2018

我们在上一节中讨论的网络代表了你需要知道的进行语义分割的大部分技术!今年在计算机视觉会议上发布的许多东西都是微小的更新和准确性上的小波动,对开始并不是非常关键。为了彻底起见,我在这里为任何感兴趣的人提供了他们的贡献的快速回顾!

图像级联网络(ICNet) 使用深度监督并以不同的尺度运行输入图像,每个尺度通过其自己的子网并逐步组合结果

【DFN】**—**使用深度监督并尝试分别处理线段的平滑和边缘部分

DenseASPP**—**结合了密集连接和粗糙卷积

上下文编码**——**通过添加通道关注模块,利用全局上下文来提高准确性,该模块基于新设计的损失函数来触发对某些特征地图的关注。损失基于网络分支,该网络分支预测图像中存在哪些类别(即,更高级别的全局上下文)。

密集解码器快捷连接 在解码阶段使用密集连接以获得更高的精度(以前仅在特征提取/编码期间使用)

【BiSeNet】**—**有两个分支:一个是深度分支,用于获取语义信息,另一个是对输入图像进行很少/很小的处理,以保留低级像素信息

ex fuse**—**使用深度监督,在处理之前,显式组合来自特征提取前端的多尺度特征,以确保多尺度信息在各级一起处理。

ICNet model structure

TL;DR 或者如何做语义分割

  • 注意分类网络权衡。您的分类网络是您处理要素的主要驱动力,您的大部分收益/损失将来自于此
  • 在多个尺度上处理并将信息结合在一起
  • 多尺度池、atrous convs、大型一维 conv 都适用于语义分割
  • 你不需要在高分辨率下做大量的处理。为了速度,在低分辨率下完成大部分,然后升级,如果必要的话,在最后做一些轻微的处理
  • 深度监督可以稍微提高你的准确性(尽管设置训练更加棘手)

喜欢学习?

在 twitter 上关注我,我会在这里发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn 上和我联系吧!

半监督学习和 GANs

原文:https://towardsdatascience.com/semi-supervised-learning-and-gans-f23bbf4ac683?source=collection_archive---------3-----------------------

文森特·梵高在 1889 年画了这幅美丽的艺术作品:“星夜”,今天我的甘模型(我喜欢称之为甘·高:P)画了一些 MNIST 数字,只有 20%的标记数据!!它是如何实现这一非凡壮举的?…让我们来看看

简介

什么是半监督学习

大多数深度学习分类器需要大量的标记样本才能很好地泛化,但获得这样的数据是一个昂贵而困难的过程。为了处理这种限制提出了半监督学习,这是一类利用少量已标记数据和大量未标记数据的技术。许多机器学习研究人员发现,未标记数据在与少量标记数据结合使用时,可以大大提高学习精度。GANs 在半监督学习中表现出了很大的潜力,其中分类器可以用很少的标记数据获得良好的性能。

甘斯背景

gan 是深度生成模型的成员。它们特别有趣,因为它们没有明确表示数据所在空间的概率分布。相反,它们通过从概率分布中抽取样本,提供了一些与概率分布不太直接交互的方式。

Architecture of a Vanilla GAN

甘的基本想法是在两个玩家之间建立一个游戏:

  • A 发生器 G :以随机噪声 z 为输入,输出一幅图像 x 。它的参数被调整,以便在它生成的假图像上从鉴别器得到高分。
  • A 鉴别器 D :取图像 x 作为输入,输出反映其为真实图像的置信度的分数。它的参数被调整为当由真实图像馈送时具有高分,当由生成器馈送假图像时具有低分。

我建议您浏览一下这个这个,了解更多关于他们工作和优化目标的细节。现在,让我们稍微转动一下轮子,谈谈 GANs 最突出的应用之一,半监督学习。

直觉

鉴别器的标准结构只有一个输出神经元用于分类 R/F 概率。我们同时训练两个网络,并在训练后丢弃鉴别器,因为它仅用于改进生成器。

对于半监督任务,除了 R/F 神经元之外,鉴别器现在将有 10 个以上的神经元用于 MNIST 数字的分类。此外,这一次它们的角色发生了变化,我们可以在训练后丢弃生成器,它的唯一目标是生成未标记的数据以提高鉴别器的性能。

现在,鉴别器变成了 11 类分类器,其中 1 个神经元(R/F 神经元)代表假数据输出,另外 10 个神经元代表具有类的真实数据。必须谨记以下几点:

  • 当来自数据集的真实无监督数据被馈送时,断言 R/F 神经元输出标签= 0
  • 当来自生成器的假的无监督数据被馈送时,断言 R/F 神经元输出标签= 1
  • 当输入实际监控数据时,置位 R/F 输出标签= 0,相应标签输出= 1

不同数据源的这种组合将有助于鉴别器比仅提供一部分标记数据更准确地分类。

体系结构

现在是时候用一些代码:D 弄脏我们的手了

甄别器

接下来的架构类似于 DCGAN 论文中提出的架构。我们使用步长卷积来降低特征向量的维度,而不是任何池层,并对所有层应用一系列 leaky_relu、dropout 和 BN 来稳定学习。对于输入层和最后一层,BN 被丢弃(为了特征匹配)。最后,我们执行全局平均池,以在特征向量的空间维度上取平均值。这将张量维数压缩为一个值。拼合要素后,将添加 11 个类别的密集图层,并激活 softmax 以实现多类别输出。

发电机

发生器结构被设计成反映鉴频器的空间输出。分数步长卷积用于增加表示的空间维度。噪声 z 的 4-D 张量的输入被馈送,其经历一系列转置卷积、relu、BN(除了在输出层)和丢失操作。最后,tanh 激活映射范围(-1,1)内的输出图像。

模型损失

我们首先通过将实际标签附加为零来为整批准备一个扩展标签。这样做是为了在输入标记数据时将 R/F 神经元输出置为 0。通过将假图像的 R/F 神经元输出置为 1,将真实图像置为 0,可以将未标记数据的鉴别器损失视为二进制 sigmoid 损失。

生成器损失是假图像损失和特征匹配损失的组合,假图像损失错误地将 R/F 神经元输出断言为 0,特征匹配损失惩罚训练数据上的某组特征的平均值和生成样本上的该组特征的平均值之间的平均绝对误差*。*

培养

训练图像的大小从[batch_size,28,28,1]调整到[batch_size,64,64,1]以适应生成器/鉴别器架构。计算损耗、精度和生成的样本,并观察其在每个时期的改进。

结论

由于 GPU 访问受限,训练进行了 5 个时期和 20%的标记率。为了获得更好的结果,建议使用具有更低标记率的更多训练时段。完整的代码笔记本可以在这里找到。

Training Results

无监督学习被认为是 AGI 领域的一个空白。为了弥补这一差距,GANs 被认为是学习低标记数据复杂任务的潜在解决方案。随着半监督学习领域新方法的出现,我们可以预期这种差距将会缩小。

如果我不提及我从这个美丽的博客,这个实现以及我在类似项目中工作的同事的帮助中获得的灵感,那将是我的失职。

下次见!!Kz

基于 PCA 和 PLS 的半监督回归:MATLAB、R 和 Python 代码——你所要做的只是准备数据集(非常简单、容易和实用)

原文:https://towardsdatascience.com/semi-supervised-regression-based-on-pca-and-pls-matlab-r-and-python-codes-all-you-have-to-do-is-1814be979dd5?source=collection_archive---------3-----------------------

我发布了基于主成分分析和偏最小二乘法的半监督回归的 MATLAB、R 和 Python 代码。它们非常容易使用。你准备数据集,然后运行代码!然后,可以获得新样本的 PCAPLS 和预测结果。非常简单容易!

你可以从下面的网址购买每一个代码。

矩阵实验室

https://gum.co/PnRna
请从下面的 URL 下载补充 zip 文件(这是免费的)来运行 PCAPLS 代码。
http://univproblog . html . xdomain . jp/code/MATLAB _ scripts _ functions . zip

稀有

https://gum.co/PXJsf
请从下面的 URL 下载补充 zip 文件(这是免费的)来运行 PCAPLS 代码。
http://univproblog . html . xdomain . jp/code/R _ scripts _ functions . zip

计算机编程语言

https://gum.co/XwnQl
http://univprovblog . html . xdomain . jp/code/supporting functions . zip

MATLAB 中的 PCAPLS 程序,R 和 Python 代码

为了执行适当的 PCAPLS,加载数据集后,MATLAB、R 和 Python 代码遵循以下程序。

1。决定 PCA 的累积贡献率的阈值
主成分数(PCs)在检查累积贡献率时确定。例如,如果给定数据集中包含 5%的噪声,则应使用累积贡献率为 95%的 PCs。其他 PC 可以作为噪声去除。

2。将带有目标变量(Y)的数据集和不带有目标变量(Y)的数据集合并(样本被合并)

3。组合数据集
的自动缩放解释变量(X)自动缩放意味着居中和缩放。通过从居中的变量中减去每个变量的平均值,每个变量的平均值变为零。通过将每个变量的标准偏差除以换算中的变量,每个变量的标准偏差变为 1。
缩放是任意的(但是推荐),但是需要居中,因为 PCA 是基于轴的旋转。

4。运行 PCA,并获得每台 PC 的得分和加载向量

5。根据 1 中的阈值决定电脑的数量。

6。仅提取 Y 样本的分数

7。自动缩放分数和 Y
缩放是任意的(但推荐)。需要对中。

8。用交叉验证(CV)估计 Y,把分量数从 1 改成 m
留一 CV 很有名,但是在训练样本数很高的时候会造成过拟合。所以,5 折或 2 折 CV 比较好。首先,将训练样本分成 5 或 2 组。第二,一组作为测试样本处理,另一组建立模型。重复 5 或 2 次,直到每组都作为测试样品处理。然后,可以得到不是计算的 Y 而是估计的 Y。
m 必须小于 X 变量的数量,但 m=30 最大值就足够了。

9。计算每个组件数量的实际 Y 和估计 Y 之间的均方根误差(RMSE)

10。用最小 RMSE 值
决定最佳元件数,用第一个局部最大 RMSE 值决定最佳元件数即可

11。用最佳组分数构建 PLS 模型,得到标准回归系数

12。计算实际 Y 和计算 Y 之间的行列式系数和 RMSE(r2C 和 RMSEC)以及实际 Y 和估计 Y 之间的行列式系数和 RMSE(r2CV 和 RMSECV)
r2C 是指 PLS 模型能够解释的 Y 信息的比值。
RMSE 表示 PLS 模型中 Y 误差的平均值。
r2CV 表示 PLS 模型对新样本可以估计的 Y 信息的可能比率。
RMSECV 表示新样本 Y 误差的可能平均值。
较好的 PLS 模型具有较高的 r2CV 值和较低的 RMSECV 值。
r2C 和 r2CV 之间以及 RMSEC 和 RMSECV 之间的巨大差异意味着 PLS 模型对训练样本的过拟合。

*小心!r2CV 和 RMSECV 不能代表 PLS 模型的真实可预测性,因为它是 CV 而不是外部验证。

13。检查实际 Y 和计算 Y 之间以及实际 Y 和估计 Y 之间的图
可以检查计算值和估计值的异常值。

14。在预测中,用 1 减去 X 的自动调用中的平均值。然后,用 X 变量除以 X 在 1 中自动调用的标准偏差。,用于新样品

15。使用 4 中的加载向量计算新样本的分数。

16。减去 7 中分数自动调用的平均值。从新分数开始,然后用新分数除以 7 中分数自动调用的标准偏差。

17。根据 11 中的标准回归系数估计 Y。

18。将 Y 的自动调用中的标准差乘以 1。通过估计的 Y,然后,在 1 中添加 Y 的自动调用中的平均值。到估计 Y

执行 PCAPLS 的方法

1.购买代码并解压文件

MATLAB:https://gum.co/PnRna

R:https://gum.co/PXJsf

Python:https://gum.co/XwnQl

2.下载并解压缩补充 zip 文件(这是免费的)

MATLAB:http://univprovblog . html . xdomain . jp/code/MATLAB _ scripts _ functions . zip

R:http://univprovblog . html . xdomain . jp/code/R _ scripts _ functions . zip

Python:http://univproblog . html . xdomain . jp/code/supporting functions . zip

3.将补充文件放在与 PCAPLS 代码相同的目录或文件夹中。

4.准备数据集。有关数据格式,请参见下面的文章。

https://medium . com/@ univprovblog 1/data-format-for-MATLAB-r-and-python-codes-of-data-analysis-and-sample-data-set-9 b0f 845 b 565 a # . 3 ibr PHS 4h

data.csv、data_prediction1.csv 和 data_prediction2.csv 的样本在 PCA 之前合并。

5.运行代码!

“data_prediction2.csv”的 Y 估计值保存在“PredictedY2.csv”中。

必需的设置

请看下面的文章。
https://medium . com/@ uniprofblog1/settings-for-running-my-MATLAB-r-and-python-codes-136 B9 e 5637 a 1 #、paer8scqy

执行结果的示例

****

传感器融合第 1 部分:卡尔曼滤波基础知识

原文:https://towardsdatascience.com/sensor-fusion-part-1-kalman-filter-basics-4692a653a74c?source=collection_archive---------2-----------------------

在本系列中,我将尝试解释卡尔曼滤波算法以及一个在多个传感器输入的帮助下跟踪车辆的实现示例,这通常称为传感器融合。

最基本形式的卡尔曼滤波器由 3 个步骤组成。a)预测——基于车辆位置和运动学方程的先前知识,我们预测时间 t+1 后车辆的位置。b)测量-从传感器获得关于车辆位置的读数,并将其与预测进行比较 C)更新-基于我们的预测和传感器读数更新我们关于车辆位置(或状态)的知识。仅此而已。卡尔曼滤波器的所有变体只是上述 3 个步骤的不同变体,这取决于你想要使用的不同运动学方程和你想要并入算法的不同种类的传感器读数。但是不管变型如何,所有卡尔曼滤波器的实现都包括上述 3 个步骤。因此,让我们使用车辆跟踪示例来分析它们。

A.预测

使用速度、距离和时间的基本方程,我们知道如果我的车辆在时间 t 的位置在 x 位置,那么在时间 t+1 车辆将在位置 x+((t+1)-t)* v,其中 v 是车辆的速度。进一步挖掘,如果我们有可用的加速度值,我们可以将它添加到上面的等式中,并将车辆的新位置更新为 x+((t+1)-t)* v+ 0.5 * a *(t+1)-t)2。公式化上述方程,让表示车辆的当前状态,其由作为向量 x 的车辆的当前位置和速度组成。因此向量 x 将具有 4 个元素,即 px、py、vx、vy;分别表示 x 和 y 方向的位置和速度。

为了让我们的例子尽可能简单(但不要比它需要的更简单),我们将在二维空间跟踪车辆,考虑到我们还没有会飞的汽车,这是一个公平的估计😊。位置 x 和 y 距离是相对于我们的车辆本身的位置。所以如果我们说一辆车在位置 px 和 py,我们的意思是它离我们的车有 px 和 py 的距离。

继续,让我们将速度和加速度定义为分别具有 x 和 y 方向上的速度和加速度数据的速度和加速度矢量。我们将时间变化表示为 delta_t,这样,我们跟踪位置和速度的单独方程就变成:

1.Px(t+1)= Px+delta _ t * VX+0.5 * ax * delta _ t 2

2.Py(t+1)= Py+delta _ t * vy+0.5 * ay * delta _ T2

3.Vx(t+1) = Vx + ax * delta_t

4.Vy(t+1) = Vy + ay * delta_t

不用深入细节,我们应该明白的一件事是,执行矩阵运算在计算上比求解单个方程有效得多。一个简单的理由是,如果我们考虑上述 4 个等式,控制器(将执行 1 和 0 操作的实际微控制器)将需要执行以下动作 4 次。I)创建一个变量 Px(t+ 1),ii)。获取 Px iii 的值)。获取 delta_t iv 的值)。获取 vx v 的值)。获取 ax vi 的值)。执行数学运算 vii)。存储结果。对于每个等式,所有这些操作都必须执行一次。为了更好地解释这个类比,假设你妈妈让你去杂货店买些洋葱(类似于从内存中获取 Px,vx,ax 值)。作为一个听话的孩子,你马上去把它带来。然后她让你切开它们(类似于数学运算),你照做了,然后就在你要看足球比赛的时候,她让你从商店里带西红柿回来。再次,作为听话的孩子,你回去带西红柿,收集所有的设备(刀,切割片和一个碗来保存它们),切西红柿并为她储存。然后她让你带些水果来……还有更多。你在这里得到了要点,足以说,那天晚上你不会是一个快乐的孩子。如果你的妈妈给了你所有需要带的东西的清单,并指示你在开始工作前把它们剪下来,这不是更好吗?电脑也是如此。(必须承认,我一直在等着写这个类比😊)

回到 1 和 0,让我们把 4 个独立的方程转换成下面的矩阵形式。现在我们的 4 个方程组合在一起,它们看起来像这样。

x_new = A * x + B * u 其中

从上面的矩阵方程中取出第一行

px _ new =[(1 * px)+(0 * py)+(delta _ t * VX)+(0 * vy)]+[(0.5 * delta _ t * delta _ t * acceleration _ x)+(0 * acceleration _ y)]

px_new = px + delta_t * vx + 0.5 *加速度 _x * delta_t 2

这和我们在把单个方程转换成矩阵形式之前想出来的是一样的。这里矩阵 A 和 B 只是代表位置、速度和加速度的运动学方程的矩阵。

哦,但是等等..嗯…妈妈在问..去……去…去杂货店(这次她道歉了)…所以你回说嘿,妈妈,我要去看足球比赛,我现在不能去。而且妈妈说所以告诉我( 预测 )你什么时候能走。和你回复我就进去 关于 *2 hrs。*那么,你问的这个对话有趣的部分是什么……嗯,是“关于”的部分。正如你能感觉到的,你有点不确定你什么时候能回去。你知道它将在 2 小时内,但有一点点+- 10(或 15 或选择一个数字)分钟的不确定性,你不确定。也许在比赛中增加了很多额外的时间,也许比赛变得无聊了(当你的球队正在输球时阅读它),你决定不等到结束,或者也许这是一场德比比赛中的伟大胜利,你想在比赛庆祝和专家分析后等待和观看。

这个不确定因素对计算机也适用。一个想法可能会进入你的脑海,卡尔曼滤波器有什么了不起的,上面提到的运动学方程已经知道几十年了,如果你喜欢,我们可以用它的矩阵形式,并开始预测。但是就像本杰明·富兰克林说的那样,生活中只有两件事是确定的:死亡和纳税。因此,当我们要求计算机预测车辆新状态的价值时,我们也需要询问它的不确定性。在卡尔曼滤波语言中,这种不确定性被表示为协方差矩阵。让我们将状态协方差矩阵表示为

p =[方差 _px,0,0,0],

[0,方差 _py,0,0],

[0,0,方差 _vx,0],

[0,0,0,方差 _vy]

其中,方差 _px、方差 _py、方差 _vx、方差 _vy 分别表示预测的 x 位置、y 位置、x 速度和 y 速度的不确定性。所有剩下的 0 项是说一个值的不确定性独立于另一个值,意思是说我的位置 x 不确定性与我在 y 方向的不确定性无关。这不需要在每种情况下都是正确的。在某些情况下,你所追踪的变量实际上可能是相互依赖的。但是我们将在这里使用简单的方法,并将其他值设为 0。这实际上使它成为一个“方差”矩阵,但协方差是更广泛使用的术语。

冒着让我们的方程变得有点复杂的风险,我想引入过程噪声协方差矩阵 q。在任何协方差矩阵计算中(在我们的例子中是矩阵 P),都可能有一定量的噪声需要加入其中,以便在估计中得出新的预测协方差。

由于卡尔曼滤波是一个连续的迭代过程,我们需要在每次从传感器获得新的读数时预测状态向量及其协方差矩阵,这样我们就可以将预测值(步骤 a)与传感器值(步骤 b)进行比较,并更新我们正在跟踪的车辆的信息(步骤 c)。我们已经有了更新状态向量的方程,更新协方差矩阵的方程如下所示。这样,我们用下面两个方程结束了预测的步骤 a。

状态向量:x = A * x + B * u

协方差矩阵:P = A * P * AT * Q

B.尺寸

现在,假设我们接收到一个传感器读数,显示我们正在跟踪的车辆的位置。实际上,操作顺序是,只有当我们收到传感器读数时,才触发卡尔曼滤波计算。传感器读数通常具有与每个读数相关联的时间戳。我们读取时间戳,计算最后一次读取时间戳和这次读取的时间戳之间的差异。使用 delta_t =两个读数之间的时间戳差值,按照上述说明进行预测,然后进入传感器输入的测量和更新部分。像激光雷达和飞行时间传感器这样常用传感器会给你关于车辆位置的读数,但不是它的速度。因此,我们的传感器读数将是矢量 z = [px,py]的形式。如前所述,我们需要将该测量值与步骤 a 中预测的值进行比较。但是查看两个向量(预测的状态向量 x 和测量向量 z),我们会发现两者的阶数不同。因此,为了将状态矩阵转换为与 z 相同的大小,我们引入了矩阵“H”。进入矩阵基础,要将一个 4 x 1 ' x' 矩阵转换成 2 x 1 ' z' 矩阵(同时保持前两个值不变并移除速度变量),我们使用一个 2 x 4 矩阵 h。因此,比较预测值和测量值的等式变为 y = z-Hx,这给出了两个值之间的差异。

在这一步,我们还将计算卡尔曼增益。该增益系数基本上用于确定车辆状态的最终值,在预测值和测量值之间选择一个合适的值。我们已经将预测值中的不确定性视为状态协方差矩阵 p。测量读数的相应不确定性矩阵是测量协方差矩阵,用字母 r 表示。我们的状态变量有 4 个变量(x,y 位置和速度),因此其协方差矩阵为 4 x 4 矩阵。如前所述,让我们考虑我们的传感器只给我们 x 和 y 方向的位置读数。在这种情况下,我们的测量协方差矩阵将是 2 x 2 的形状,如下所示。

r =[[方差 _ 输入 _ 位置 _ x _ 读数,0]

[0,方差 _ 输入 _ 位置 _ y _ 读数]

显然,在决定最终值时,我们希望更倾向于具有较少不确定性的值。在卡尔曼增益值中,我们通过计算预测值中的不确定度占总不确定度的百分比来比较预测和测量方法中的不确定度。换句话说

**卡尔曼增益=预测状态的不确定性/(预测状态的不确定性+测量读数的不确定性)。**我们知道预测状态中的不确定性是矩阵 P,测量值中的不确定性是矩阵 r。但正如您所见,两者大小不同。因此,我们使用 H 矩阵将 P 矩阵转换为正确的大小。这样,卡尔曼增益方程就变成= >

K = ( P * HT ) / ( ( H * P * HT ) + R)

用 4 x 4 P 矩阵和 2 x 2 R 矩阵计算卡尔曼增益所需的 h 矩阵如下所示

H = [ [1,0,0,0],

[0, 1, 0, 0] ]

还是那句话,P 矩阵周围 H 矩阵的填充只是为了矩阵运算,请不要让它吓到你。卡尔曼增益只是一个简单的百分比公式。

好了,有了预测值、测量值和卡尔曼增益值,是时候移动到更新状态了,在这里我们对状态向量 x 及其相应的协方差矩阵 p 进行最终更新。

C.更新

即使我想,我也不能让这一步变得复杂,所以我会给你最终状态向量的方程--> x = x+Ky。假设我们对预测值非常有信心,那么我们的协方差 P 将会有非常小的方差值。这反过来将使卡尔曼增益(即预测状态的不确定性/预测状态的不确定性+测量读数的不确定性)。)作为最终等式的小数字将是*小数字/(小数字+大数字)的形式。在这种情况下,如果我们考虑最终的 x 方程,我们取预测值,只将它的一小部分差值(即预测值和测量值之间的差值)加到测量值上。因为根据上述理论,卡尔曼增益将是一个小值,所以 x 的方程将是:x = x +(小数字 y)

如您所见,这将导致最终 x 更倾向于预测值,这与我们最初假设一致,即与测量值相比,我们对预测值有更高信心。类似地,更新协方差矩阵的等式为 P = (I-KH) P。同样,H 矩阵用于矩阵操作。

这样,我们就有了实现完整卡尔曼滤波器所需的所有工具,公式如下

A.预测:

a.X = A * X + B * u

b.P = A * P * AT * Q

B.尺寸

a.Y = Z — H * X

b.K = ( P * HT ) / ( ( H * P * HT ) + R)

C.更新

a.X = X + K * Y

b.P = ( I — K * H ) * P

与我的其他文章类似,我也想在这篇文章中加入玩具代码,但是这篇文章读起来很长。我肯定会在这个系列的后续部分中添加它,我计划使用卡尔曼滤波器完成传感器融合。

像往常一样,如果你喜欢我的文章,用喜欢和评论来表达你的欣赏。你也可以在 twitter 上找到我和我的其他文章

直到下一次…干杯!!

传感器融合第 2 部分:卡尔曼滤波器代码

原文:https://towardsdatascience.com/sensor-fusion-part-2-kalman-filter-code-78b82c63dcd?source=collection_archive---------3-----------------------

在第一部分中,我们在推导了卡尔曼滤波算法的基本方程后离开。为便于参考,在此再次陈述。

A.预测:
A . X = A * X+B * u
B . P = A * P * AT * Q
B .测量
A . Y = Z—H * X
B . K =(P * HT)/((H * P * HT)+R
c .更新

  1. X = X + K * Y
  2. P = ( I — K * H ) * P

在这篇文章中,我们将使用 Udacity 的 github handle 上免费提供的文本文件中的传感器读数,对上述等式进行编码。该文本文件(obj _ pose-Laser-Radar-synthetic-input . txt)包含来自激光和雷达的传感器读数,以及读数的时间戳和地面真实值。到目前为止,我们只介绍了基本的卡尔曼滤波算法,因此在这个编码练习中,我们将只使用上述输入文件中的激光读数。一旦我们在以后的文章中谈到“扩展卡尔曼滤波”,我们也将开始使用雷达读数。但是以我们目前对卡尔曼滤波方程的理解,仅仅使用激光读数就可以作为一个完美的例子,在编码的帮助下巩固我们的概念。

输入文本文件中捕获的传感器读数格式如下。

对于包含雷达数据的行,列有:sensor_type (R)、rho_measured、phi_measured、rhodot_measured、timestamp、x_groundtruth、y_groundtruth、vx_groundtruth、vy_groundtruth、yaw_groundtruth、yawrate_groundtruth。

对于包含激光雷达数据的行,列包括:传感器类型(L)、x 测量值、y 测量值、时间戳、x 地面真实值、y 地面真实值、vx 地面真实值、vy 地面真实值、yaw 地面真实值、yawrate 地面真实值。

有了这些信息,让我们开始编码吧,不要再拖延了。与任何 Python 文件一样,让我们首先导入所有需要的库

#**************Importing Required Libraries*************
import numpy as np
import pandas as pd
from numpy.linalg import inv

接下来,读取包含传感器读数的输入文本文件。

#*************Declare Variables**************************
#Read Input File
measurements = pd.read_csv('obj_pose-laser-radar-synthetic-input.txt', header=None, delim_whitespace = True, skiprows=1)

我将“skiprows”参数设为 1,因为当我们开始实施 KF 算法时,我们没有任何关于车辆状态的先验知识。在这种情况下,我们通常将状态默认为传感器输出的第一个读数。这正是我们将要做的。在下面显示的代码中,我们将通过从输入文件的第一行读取来初始化我们的状态 X 。由于这个读数已经被使用,我们在读取输入文件时简单地跳过它。除了状态向量 X 的初始值,我们还将使用输入文件中的第一个时间戳作为我们的 先前时间 正如上一篇文章所解释的,我们需要当前和以前的时间戳来计算 delta_t 。提供的时间戳以微秒为单位,我们将除以 10⁶.这有两个原因,第一,较小的数量更容易维护。第二,速度地面实况读数(以及我们代码中的速度值)是以秒为单位的。

# Manualy copy initial readings from first row of input file.
prv_time = 1477010443000000/1000000.0
x = np.array([
        [0.312242],
        [0.5803398],
        [0],
        [0]
        ])

接下来,我们初始化变量来存储地面真相和 RMSE 值。RMSE(均方根误差)用于相对于地面真实值来判断我们的算法的性能。

#Initialize variables to store ground truth and RMSE values
ground_truth = np.zeros([4, 1])
rmse = np.zeros([4, 1])

我们初始化矩阵 PA 。关于 PA 矩阵的详细结构,请参考第 1 部分中更深入的解释。基本上,矩阵 A 用于实现距离、速度和时间的运动学方程,矩阵 P 是状态协方差矩阵,具有作为其对角元素的 x、y、vxvy 的方差。这个初始 P 值的意思是,我们对我们的位置值具有高置信度(这是有意义的,因为我们已经从实际传感器读数中得到它),由相对低的方差值表示,而对速度值具有低置信度(这也是有意义的,因为我们不知道速度),由相对大的方差值表示。

#Initialize matrices P and A
P = np.array([
        [1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 1000, 0],
        [0, 0, 0, 1000]
        ])
A = np.array([
        [1.0, 0, 1.0, 0],
        [0, 1.0, 0, 1.0],
        [0, 0, 1.0, 0],
        [0, 0, 0, 1.0]
        ])

接下来我们定义 HI 矩阵,正如我在上一篇文章中解释的,它们将分别是 4 x 2 和 4 x 4 矩阵。我们定义矢量 Z ,由于我们的激光雷达读数将由 2 个位置读数(x 和 y)组成,因此它将是一个 2 x 1 矢量。

H = np.array([
        [1.0, 0, 0, 0],
        [0, 1.0, 0, 0]
        ])
I = np.identity(4)
z_lidar = np.zeros([2, 1])

我们定义测量协方差矩阵 R ,根据上一篇文章,它也将是一个 2×2 的矩阵。我们将在以后的文章中详细讨论如何获取 R 矩阵和 noise_axnoise_ay 的值。

R = np.array([
        [0.0225, 0],
        [0, 0.0225]
        ])

接下来我们定义 noise_axnoise_ay 和 matrix Q

noise_ax = 5
noise_ay = 5
Q = np.zeros([4, 4])

让我们花点时间来理解它们。如果我们重温本系列第一部分中定义的运动学方程,你可以看到在位置和速度项中有一个加速度因子。为了方便起见,在这里对它们进行了重写。

  1. Px(t+1)= Px+δ_ t * VX+0.5 * ax *δ_ t
  2. Py(t+1)= Py+δ_ t * vy+0.5 * ay *δ_ t
  3. Vx(t+1) = Vx + ax * delta_t
  4. Vy(t+1) = Vy + ay * delta_t

由于加速度未知,我们可以将其添加到噪声成分中,这种随机噪声可以解析地表示为上面推导的等式中的最后一项。因此,我们有一个随机加速度向量 v ,它由一个零均值和一个协方差矩阵 Q. 描述

向量 v 可以分解成两个分量:不包含随机变量的 4 乘 2 矩阵 G 和包含随机加速度分量的 2 乘 1 矩阵 a :

在卡尔曼滤波器的每次迭代中计算 delta_t,并且由于我们没有任何加速度数据,我们将加速度定义为具有零均值和标准差 noise_ax 和 noise_ay 的随机向量。基于我们的噪声向量,我们现在可以定义新的协方差矩阵 q。协方差矩阵被定义为噪声向量 v 乘以噪声向量 v 转置的期望值。所以让我们把这个写下来:

要了解更多关于“期望值”的信息,请观看汗学院的视频。由于 G 不包含随机变量,我们可以把它放在期望计算之外

ax 和 ay 被假定为不相关的噪声过程。这意味着 Q 中的协方差 sigma_axy 为零。

因此,在将所有内容合并到一个矩阵中后,我们获得了 4x 4 Q 矩阵:

在卡尔曼滤波器的每次迭代中,我们将按照上面的公式计算矩阵 Q。定义好所有变量后,让我们开始遍历传感器数据,并对它们应用卡尔曼滤波器。运行 for 循环直到测量长度,读取测量线,检查是否是激光雷达(‘L’)读数。

**#**********************Iterate through main loop********************
#Begin iterating through sensor data
for i in range (len(measurements)):
    new_measurement = measurements.iloc[i, :].values
    if new_measurement[0] == 'L':**

从当前读数中获取时间戳,通过与先前时间戳进行比较来计算时间变化,然后在下一次迭代中将当前时间戳替换为先前时间戳。

 **#Calculate Timestamp and its power variables
        cur_time = new_measurement[3]/1000000.0
        dt = cur_time - prv_time
        prv_time = cur_time**

计算 delta_t 的平方、立方和 delta_t 的四次方(代码中的“dt ”),这是计算 Q 矩阵所需的。

 **dt_2 = dt * dt
        dt_3 = dt_2 * dt
        dt_4 = dt_3 * dt**

用 delta_t 值更新矩阵 A。Delta_t 将乘以速度以得出位置值。

 **#Updating matrix A with dt value
        A[0][2] = dt
        A[1][3] = dt**

更新 Q 矩阵。如果你回头看看上面导出的 Q 矩阵方程,你可以很容易地找到下面提供的代码行。

 **#Updating Q matrix
        Q[0][0] = dt_4/4*noise_ax
        Q[0][2] = dt_3/2*noise_ax
        Q[1][1] = dt_4/4*noise_ay
        Q[1][3] = dt_3/2*noise_ay
        Q[2][0] = dt_3/2*noise_ax
        Q[2][2] = dt_2*noise_ax
        Q[3][1] = dt_3/2*noise_ay
        Q[3][3] = dt_2*noise_ay #Updating sensor readings
        z_lidar[0][0] = new_measurement[1]
        z_lidar[1][0] = new_measurement[2] #Collecting ground truths
        ground_truth[0] = new_measurement[4]
        ground_truth[1] = new_measurement[5]
        ground_truth[2] = new_measurement[6]
        ground_truth[3] = new_measurement[7]**

最后调用预测和更新函数。

 **predict()
        update(z_lidar)**

**现在让我们看看我们的 predict()函数,它与我们在本系列中使用的以下预测方程非常相似。在代码部分没有太多要解释的,它实际上只是派生公式的直接复制。
A .预测

  1. X = A * X + B * u
  2. P = A * P * AT * Q**
**#**********************Define Functions*****************************
def predict():
    # Predict Step
    global x, P, Q
    x = np.matmul(A, x)
    At = np.transpose(A)
    P = np.add(np.matmul(A, np.matmul(P, At)), Q)**

**继续定义 update()函数。我们将在该功能中实施“测量”和“更新”步骤。
B .测量
a . Y = Z—H * X
b . K =(P * HT)/((H * P * HT)+R
c .更新

  1. X = X + K * Y
  2. P = ( I — K * H ) * P**
**def update(z):
    global x, P    
    # Measurement update step
    Y = np.subtract(z_lidar, np.matmul(H, x))
    Ht = np.transpose(H)
    S = np.add(np.matmul(H, np.matmul(P, Ht)), R)
    K = np.matmul(P, Ht)
    Si = inv(S)
    K = np.matmul(K, Si)

    # New state
    x = np.add(x, np.matmul(K, Y))
    P = np.matmul(np.subtract(I ,np.matmul(K, H)), P)**

…至此,您已经完成了卡尔曼滤波算法的完整代码。尽管这看起来像是一小步,但它是传感器融合技术的许多高级版本的基础算法。如前所述,卡尔曼滤波器的所有变体都由我们在本系列中定义的相同预测、测量和更新状态组成。在更高级的版本中,唯一的区别是它们使用不同的运动学和传感器方程。在本系列中,我们也将一步一步地介绍它们。但此时此刻,让我们击掌庆祝完成经典卡尔曼滤波算法的基础步骤。你可以在我的 github repo 这里找到完整的代码和输入文件。

像往常一样,如果你喜欢我的文章,用喜欢和评论来表达你的欣赏。你也可以在 twitter 找到我和我的其他文章

下次再见,干杯!!

句子嵌入

原文:https://towardsdatascience.com/sentence-embedding-3053db22ea77?source=collection_archive---------0-----------------------

文献综述:

首先,让我们从单词嵌入开始,这些是单词在 n 维向量空间中的表示,以便语义相似(例如“船”-船只)或语义相关(例如“船”-水)的单词根据训练方法变得更接近。培训方法大致分为两部分:

  1. 使用文档作为上下文。( LSA ,话题模特)。他们捕捉语义关联。
  2. 使用单词作为上下文。(神经语言模型,分布式语义模型)。他们捕捉语义的相似性。

在平行线上,我们希望开发一些东西,可以捕捉句子之间的语义相似性或相关性,然后是段落,然后是文档。

现在暂时假设我们有单词向量。

获得句子表示的一种方法是将句子中包含的所有单词向量的表示相加,这被称为单词质心。并且两个句子之间的相似度可以通过 c 熵距离来计算。同样的事情可以扩展到段落和文档。但是这种方法忽略了很多信息,比如序列,并且可能给出错误的结果。比如:

  1. 你要去那里教书,而不是玩。
  2. 你要去那里玩而不是教书

这些将有相同的最终表现,但你可以看到,意义是完全不同的。

然后,通过引入编辑距离方法对其进行了一点微调,这被称为字移动器的距离。它来自于发表在 em NLP’14 上的论文“从单词嵌入到文档距离”。这里我们取句子 1 到句子 2 中每个单词的最小距离,并将它们相加。比如:

  1. 奥巴马在伊利诺伊州对媒体讲话
  2. 总统在芝加哥迎接媒体

Image taken from original paper

  • 奥巴马匹配总统
  • 向问候者说话
  • 媒体报道
  • 伊利诺伊到芝加哥

这种方法正在产生令人鼓舞的结果。论文在问答中使用单词嵌入的质心和单词移动器的距离进行生物医学文献检索,使用质心距离进行初始剪枝,然后使用 WMD 得到更好的结果。(注意 WMD 慢。是O(n*m),其中nsentence1的长度,msentence2的长度

但是我们看到,在这两种方法中,我们没有使用来自序列的信息。所以在这个领域也有很多研究。

论文中, 卷积神经网络用于句子分类其中曾提出 CNN 用于同样的事情。它在句子中使用了填充,使它们具有相同的维度- >使用单词嵌入来映射这些填充句子中的单词- >应用 CNN - >使用最大超时池- >馈送到全连接层- >获取表示。他们写道,使用 word2vec 初始化单词嵌入,然后通过反向传播进行微调,得到了比“不调整”和“随机初始化”更好的结果。

然后是微软研究院 2015 年发表的关于深度语义相似度模型的论文,本文使用不同类型的词向量,这里是基于 n-grams。例:对于 hello 这个词,他们会加上起始和结束标记,并分解成 n 个字母组,即 hello - > #hello# - > 。并以向量形式表示它,向量的大小为(272627(如果不使用哈希))(请注意,它与词汇大小无关,并概括了看不见的单词,对拼写错误具有鲁棒性)。他们将这些向量的序列(用于表示句子)放入他们的模型,该模型给他们一个语义向量,并且基于已知的这些句子的相似性或不相似性,他们被训练(弱监督)。在该模型中,他们使用了具有最大池的 CNN。CNN 提取局部特征,max pooling 层从中生成全局特征。我已经在 short science这里写了一篇关于这篇论文的小总结。

因此,在训练期间,句子与具有相似性(肯定)和不相似性(否定)的句子一起提供。该模型可以被训练用于最大化(文件,阳性的余弦相似性)-文件,阴性的余弦相似性)。他们使用了随机梯度下降法。

但是我们不能在这里使用 rnn 吗?在这里,它们将拥有所有文档的内存,并在查询时返回所需的文档。根据 MetaMind 的这篇论文,用于视觉和文本问题回答的动态记忆网络 ,其中他们使用 GRU 将数据编码为事实,并将问题编码为向量,然后使用问题向量并循环事实以生成上下文向量并更新记忆。基于记忆,它能够回答。我们可以用同样的方法来寻找文档的相似性。我已经在 short science 这里写了一篇关于这篇论文的小总结。

本文中提出的进一步的观点是:使用双向** GRUs(在本文中有更好的解释, " 具有再次读取和复制机制的有效摘要 "),以及使用句子嵌入而不是单词嵌入。**

然后还有一篇论文在这个领域有很强的基础, 句子和文档的分布式表示 s ,它来自谷歌,发表于 2014 年。它提出以与单词向量相同的方式学习段落向量,并将其用于无数任务,包括情感分析和信息检索。

如有任何疑问,请发邮件至 nishantiam@gmail.com给我。

用 Seq2Seq 简化句子

原文:https://towardsdatascience.com/sentence-simplification-with-seq2seq-1b20d05a4663?source=collection_archive---------5-----------------------

作为一名机器学习的学生,我喜欢阅读最近发表的 Arxiv 论文,并试图理解它们。在这里,我将尝试解释一篇给我留下深刻印象的论文,它使用一种新颖的序列到序列(Seq2Seq)模型来简化句子。

[## [1704.02312v1]用于句子简化的受限序列到序列神经模型

摘要:句子简化降低了语义复杂性,有利于有语言障碍的人。上一个…

arxiv.org](https://arxiv.org/abs/1704.02312v1)

在这篇论文中,中国北京大学的研究人员利用 seq2seq RNN 模型和注意方法来简化句子。他们将此与单词级替换相结合,产生了最先进的简化结果。

顺便问一下,你喜欢阅读最近的 ML 研究论文的简短摘要吗?查看arxiv . email,那可是个 tl 的每周简讯;本周最佳出版研究博士。

句子简化的任务对于提高可读性很重要。这有利于非母语人士、儿童以及患有自闭症和阅读障碍等语言障碍的个人。我的许多团队都接触过这个任务,大多数团队都使用基于规则的系统来尝试简化任务。有的用词级替换,简单的把复杂的词换成简单的词。本文试图利用神经机器翻译的最新发展来简化句子。

“序列到序列”递归神经网络(RNN)模型是最近提出的,并证明了神经机器翻译(NMT)的优秀结果。这个模型接受一个输入序列(一种语言的句子),并训练一个模型生成一个不同语言的输出序列。事实证明,这种模式比 NMT 大学以前的方法更有效,显然现在谷歌翻译也在使用这种模式。

研究人员使用了从维基百科上搜集的句子匹配数据集。这是由 David Kauchek 创建的,包括来自英语维基百科和简单英语维基百科的 137,000 对匹配句子。

建模过程通常可总结如下:

  1. 用一个复杂的单词代替原句中的一个简单的单词。
  2. 把句子分成两部分,从“简单”替换词处开始。例如:
  3. 就拿“他成为了一个有名的作文老师,有很多有名的学生”这句话来说。
  4. 作曲代替音乐。它变成了“…一个著名的音乐老师…”。
  5. 将替换词处的句子分成两部分。第一部分颠倒了。
  6. 第一部分成为“众所周知的一个成了他”
  7. 第二部分是“老师,有很多有名的学生”

然后,将每个单独的句子片段通过以下步骤:

  1. 取原句子部分,预处理成整数向量。他们使用一本 60000 字的词典。每个单词代表字典中的一个数字。未知单词由通用的“UNK”单词代替。
  2. 将输入句子的每个单词通过编码层:
  3. 将矢量化的单词通过单词嵌入层。
  4. 将嵌入层通过具有门控循环单位(GRU)细胞的双向 RNN (BiRNN)。

最后,将 BiRNN 的最终输出作为编码层的输出。

  1. 通过解码层传递最终的解码器状态,这是一个具有注意机制的 GRU RNN。
  2. 对于解码层中的每一步,通过 softmax 层传递 RNN 输出,以获得预测的最终字。
  3. 将两个生成的句子片段与替换单词组合,以创建最终生成的句子。

上述过程只是用一个复杂的单词代替一个更简单的单词。如果有多个需要替换的复杂单词,研究人员将对每个单词替换进行一次上述过程。所以如果有三个复杂的单词,他们会经历上述过程三次。他们会用第一个单词做一次,然后在替换了一个不同的单词后,获取输出并再次做整个过程。

Examples of outputs for different sentence simplification models. This paper’s approach is at the bottom.

上图显示了他们的最终模型(多约束 Seq2Seq)以及其他类似模型的输出。你可以看到许多模型根本没有简化句子,即使是一个简单的 Seq2Seq 模型。词汇模型只是用复杂的词代替简单的词,而不改变句子结构。词汇模型也只能将“一个键”变成“一个重要的”,而它应该是“一个重要的”。他们最终的模型不仅可以替换多个单词,而且可以重新排列句子,删除不必要的片段,语法正确,仍然保留原句的意思。

感谢阅读!最后一个不要脸的塞:check outarxiv . email,那可是个 tl 的周刊快讯;本周最佳出版研究博士。

情感分析:概念、分析和应用

原文:https://towardsdatascience.com/sentiment-analysis-concept-analysis-and-applications-6c94d6f58c17?source=collection_archive---------0-----------------------

情感分析是对文本进行上下文挖掘,识别和提取源材料中的主观信息,并帮助企业在监控在线对话的同时了解其品牌、产品或服务的社会情感。然而,社交媒体流的分析通常仅限于基本的情感分析和基于计数的指标。这类似于只触及表面,错过了那些等待被发现的高价值见解。那么,一个品牌应该如何抓住这个唾手可得的果实呢?

随着深度学习的最新进展,算法分析文本的能力有了很大提高。创造性地使用先进的人工智能技术可以成为进行深入研究的有效工具。我们认为,根据以下线索对客户关于某个品牌的对话进行分类非常重要:

  1. 顾客关心的品牌产品和服务的关键方面。
  2. 用户对这些方面的潜在意图和反应。

这些基本概念结合使用时,会成为一个非常重要的工具,用于以人类水平的准确度分析数百万次品牌对话。在这篇文章中,我们以优步为例,展示这是如何运作的。请继续阅读!

文本分类器——基本构件

情感分析 情感分析是最常见的文本分类工具,它分析收到的消息,并判断潜在的情感是积极的、消极的还是中性的。你可以输入一个你选择的句子,并通过这里的演示来判断潜在的情绪。

意图分析 意图分析通过分析消息背后的用户意图,并识别它是否与意见、新闻、营销、投诉、建议、赞赏或查询有关,从而加快游戏的进程。

Analyzing intent of textual data

上下文语义搜索(CSS)
这就是事情变得真正有趣的地方。为了获得可行的见解,了解用户讨论的是品牌的哪个方面是很重要的。例如:Amazon 想要隔离与以下内容相关的消息:延迟交付、账单问题、促销相关的查询、产品评论等。另一方面,星巴克希望根据信息是否与员工行为、新咖啡口味、卫生反馈、在线订单、商店名称和位置等相关来对信息进行分类。但是怎样才能做到呢?

我们引入了一种智能的智能搜索算法,称为上下文语义搜索(又名 CSS) 。CSS 的工作方式是,它将数千条消息和一个概念(如价格)作为输入,并过滤所有与给定概念紧密匹配的消息。下图展示了 CSS 如何代表了对业界使用的现有方法的重大改进。

Existing approach vs Contextual Semantic Search

过滤所有与价格相关的消息的传统方法是对价格和其他密切相关的词进行关键字搜索,如(定价、收费、$、已付)。然而,这种方法不是很有效,因为几乎不可能想到所有相关的关键字及其代表特定概念的变体。另一方面,CSS 只是将概念的名称( Price )作为输入,并过滤所有上下文相似的内容,即使没有提到概念关键字的明显变体。

对于好奇的人,我们想让他们看一下这是如何工作的。人工智能技术用于将每个单词转换为超空间中的特定点,这些点之间的距离用于识别上下文与我们正在探索的概念相似的消息。下面可以看到引擎盖下的可视化效果:

Visualizing contextually related Tweets

在下面的例子中,我们来看看 CSS 是如何工作的,以及它是如何处理与优步相关的评论的:

同样,看看这条推文:

在上述两种情况下,该算法将这些消息归类为与名为 P rice 的概念上下文相关,即使在这些消息中没有提到单词 Price

优步:深潜分析

全球估值最高的初创企业优步一直是共享经济的先驱。优步在全球 500 多个城市开展业务,为庞大的用户群提供服务,收到了大量用户的反馈、建议和投诉。通常,社交媒体是登记此类问题的最受欢迎的媒体。海量的传入数据使得分析、分类和生成见解成为一项具有挑战性的任务。

我们分析了数字媒体上发生的关于几个产品主题的在线对话:取消、支付、价格、安全和服务。

为了广泛覆盖数据来源,我们从优步官方脸书页面上的最新评论、提到优步的推文以及优步的最新新闻文章中获取数据。以下是所有渠道的数据点分布:

  1. 脸书:34173评论
  2. 推特:21603 条推特
  3. 新闻:第 4245 篇

分析用户对话的情感可以让你对整体品牌认知有所了解。但是,为了更深入地挖掘,借助上下文语义搜索进一步对数据进行分类是很重要的。

我们在同一个数据集上运行了上下文语义搜索算法,考虑了前面提到的类别(取消、支付、价格、安全和服务)。

脸谱网

情绪分析

Breakdown of Sentiment for Categories

值得注意的是,除了一个类别,所有类别的评论都有负面情绪。与价格相关的正面评论数量已经超过负面评论。为了更深入地挖掘,我们分析了这些评论的意图。作为一个社交平台,脸书的评论充斥着随机内容、新闻分享、营销和推广内容以及垃圾邮件/垃圾/无关内容。看看脸书评论上的意图分析:

Intent analysis of Facebook comments

脸书评论的意图分析

因此,我们删除了所有这些不相关的意图类别,并重现了结果:

Filtered Sentiment Analysis

每个类别的情感都有明显的变化。尤其是在价格相关评论中,正面评论数量从 46%下降到 29%。

这让我们看到了 CSS 如何从数字媒体中产生深入的见解。因此,一个品牌可以分析这样的推文,并从它们的积极点或从消极点获得反馈。

推特

情感分析

对抓取的推文也做了类似的分析。在最初的分析付款和安全相关的推文中有一种复杂的情绪。

Category wise sentiment analysis

为了了解真实的用户意见、投诉和建议,我们必须再次过滤不相关的推文(垃圾邮件、垃圾广告、营销、新闻和随机消息):

Filtered sentiment

与付款相关的推文数量明显减少。此外,针对类别安全(以及相关关键词)的正面推文数量大幅下降。)

此外,取消、支付服务(以及相关词汇)是推特上评论中谈论最多的话题。似乎人们谈论最多的是司机取消乘车和向他们收取的取消费。看看这条推文:

像优步这样的品牌可以依靠这种洞察力,并根据最关键的话题采取行动。例如,服务相关推文的正面推文比例最低,负面推文比例最高。因此,优步可以分析这些推文,并根据它们采取行动,以提高服务质量。

新闻ˌ消息

Sentiment Analysis for News headlines

可以理解的是,安全一直是新闻中谈论最多的话题。有趣的是,新闻情绪总体上是积极的,在每个类别中也是如此。

我们也根据新闻的受欢迎程度进行分类。流行度得分归因于文章在不同社交媒体渠道上的分享计数。以下是热门新闻文章列表:

  1. 优步首席执行官因批评离开特朗普顾问委员会
  2. #DeleteUber:用户对川普穆斯林禁令废 app 感到愤怒
  3. 优步员工也讨厌他们自己的企业文化
  4. 每次我们获得优步,我们就在传播它的社会毒素
  5. 司机在抗议和罢工期间前往 JFK 机场后,愤怒的消费者删除了优步的应用程序

结论

随着技术的进步,从社交媒体数据中获得有意义见解的时代已经到来。优步的案例研究让你一瞥上下文语义搜索的威力。您的组织是时候超越总体情绪和基于计数的指标了。公司最近一直在利用数据的力量,但要获得最深层的信息,你必须利用人工智能、深度学习和智能分类器的力量,如上下文语义搜索和情感分析。在 Karna ,您可以联系我们以获得我们技术的许可,或者获得定制的仪表板,以便从数字媒体中生成有意义的见解。你可以点击查看演示

parallel dots AI API,是由 ParallelDots Inc 提供的深度学习支持的 web 服务,可以理解大量的非结构化文本和视觉内容,为您的产品提供支持。你可以查看我们的一些文本分析API并通过填写此处的表格联系我们或者给我们 apis@paralleldots.com 写信。

R——好与不好——处理否定中的情感分析

原文:https://towardsdatascience.com/sentiment-analysis-in-r-good-vs-not-good-handling-negations-2404ec9ff2ae?source=collection_archive---------7-----------------------

Image credit: https://pixabay.com/en/eggs-colors-easter-holiday-spring-3398664/

情感分析是拥有未标记文本数据(没有分数或评级)的数据分析师最终试图从中提取一些见解的最明显的事情之一,同样的情感分析也是任何自然语言处理(NLP)爱好者的潜在研究领域之一。

对于分析师来说,同样的情感分析是一件痛苦的事情,因为大多数处理情感分析的原始包/库执行简单的字典查找,并根据正面和负面单词的出现次数计算最终的综合得分。但这往往会导致许多假阳性,一个非常明显的例子是“好”对“不好”——否定,通常是价移

考虑一下这句话:'我不太好'。任何原始的情感分析算法只会将这句话标记为肯定的,因为单词“good”显然会出现在肯定词典中。但是读这句话我们知道这不是一个肯定句。

虽然我们可以构建自己的方式来处理这些否定,但有几个新的 R-package 可以轻松做到这一点。泰勒·林克开发的[sentimentr](https://github.com/trinker/sentimentr)就是这样一个软件包。

视频教程

安装软件包

sentimentr 可以从 CRAN 安装,也可以从 github 安装开发版。

install.packages('sentimentr')
#or
library(devtools)
install_github('trinker/sentimentr')

为什么是 sentimentr?

这个包的作者自己解释了sentimentr做了什么而其他包没有做,为什么这很重要?

sentimentr 试图在保持速度的同时考虑变价词(即否定词、增强词、去增强词和转折连词)。简单地说,sentimentr 是一个扩充的字典查找。接下来的问题是为什么它很重要。”

情感评分:

sentimentr 提供了两个情感分析功能:1 .sentiment_by() 2。sentiment()

使用sentiment_by的给定文本的聚合(平均)情感分数

sentiment_by('I am not very good', by = NULL)element_id sentence_id word_count   sentiment
1:          1           1          5 -0.06708204

但是当我们有多个不同极性的句子时,这可能没有多大帮助,因此用sentiment进行句子级评分会有所帮助。

sentiment('I am not very good. He is very good')element_id sentence_id word_count   sentiment
1:          1           1          5 -0.06708204
2:          1           2          4  0.67500000

这两个函数都返回一个包含四列的数据帧:

1.element_id –给定文本的 ID /序列号
2。sentence_id–句子的 ID /序列号,在sentiment_by
3 的情况下等于 element_id。word_count–给定句子的字数
4。sentiment–给定句子的情感得分

提取情感关键词

extract_sentiment_terms()功能帮助我们提取关键词——正面的和负面的,这是情感得分计算的一部分。sentimentr 还支持管道操作符%>%,这使得编写多行代码变得更容易,赋值更少,代码也更简洁。

'My life has become terrible since I met you and lost money' %>% extract_sentiment_terms()
   element_id sentence_id      negative positive
1:          1           1 terrible,lost    money

情绪突出:

最后,highight()函数与sentiment_by()相结合,给出一个 html 输出,其中部分句子用绿色和红色突出显示,以显示其极性。相信我,这可能看起来微不足道,但它确实有助于在做演示时分享结果,讨论假阳性,并确定准确性方面的改进空间。

'My life has become terrible since I met you and lost money. But I still have got a little hope left in me' %>% 
  sentiment_by(by = NULL) %>%
  highlight()

输出截图:

Sentiment Highlight

尝试将sentimentr用于您的情感分析和文本分析项目,并在评论中分享您的反馈。此处使用的完整代码可在 my github 上获得。欲了解更多信息,请查看本数据营课程——R 中的情绪分析——整洁的方式

情绪分析:贾斯廷·特鲁多的推文

原文:https://towardsdatascience.com/sentiment-analysis-justin-trudeaus-tweets-e76bfc622b04?source=collection_archive---------9-----------------------

我在网上到处看到对特朗普推文的情绪分析。这是有道理的——没有一位总统、政治人物或任何人真正像特朗普那样使用 Twitter。阅读这些对特朗普推文的分析,他的情绪到处都是。但是你不需要一个文本处理工具来使用它,你只要听听他的演讲或者读读新闻就能明白。然而,这让我想到,我的总理贾斯廷·特鲁多的推特看起来像什么?他的推文在情绪上更平衡吗?他用英语发的微博和用法语发的微博有区别吗?我们来看看吧!

为了这个分析,我会看看一些基本的推文特征:来源,“转发”和“收藏”计数,以及英语和法语推文的总体情绪。虽然推文的来源和观点让我们深入了解特鲁多,但转发和最受欢迎的计数代表加拿大人说话。通过这一分析,我们将对我们的总理有更多的了解,对我们自己也有更多的了解。

加拿大不一样

我们先来看看加拿大人在 2016 年 12 月至 2017 年 10 月期间对特鲁多推文的反应。这当然考虑了所有以转发或收藏的形式与@JustinTrudeau 互动的 Twitter 用户,但我现在假设这些用户中的大多数是加拿大人。

这是一个非常有趣的结果。到目前为止,转发和收藏最多的英文推文是:

毫无疑问,这条推文获得了大量关注。这可能有很多原因。首先,加拿大可能是不同的。我们欢迎,加拿大人喜欢我们的总理宣传这一点。第二,响应可能来自非加拿大公民(这将使我上面的假设无效),也许来自难民自己。第三,这种反应可能主要是由美国人组成的。随着(当时)唐纳德·特朗普(Donald Trump)成为新的@POTUS,美国人可能会转发并喜欢这条推文,以此表示“看看加拿大有多不同。”

同样的法语推文获得了最多的转发,但另一条推文获得了最多的收藏。

最受欢迎的推文是:

事实上,这条推特比英文版获得了更多的转发。似乎法裔加拿大人,或者说法语的人,热衷于支持 LGBTQ 群体,并且喜欢从总理那里听到这些。这个帖子的收藏数量和转发数量之间的差距很奇怪——也许法裔加拿大人不喜欢转发这种事情?

来源和长度

接下来,我们来看看特鲁多的推文来源,以及它们的长度。

因此,特鲁多似乎使用 iPhone,但更喜欢在电脑上发推文。这与特朗普截然不同,他似乎更喜欢在手机上发推文。

现在,对于特鲁多的推文长度。

情感分析

完成基本的探索后,让我们继续进行情感分析。在这个分析中,我使用了 VADER 和 TextBlob,因为 VADER 针对社交媒体进行了优化,但是 TextBlob 针对法语进行了优化。我不仅想比较英文和法文的感悟,也想比较这两个包。

让我们先来看看使用 VADER 和 TextBlob 的结果。

这里的一个主要区别是,TextBlob 认为这两种语言的推文更加中性,而 VADER 认为特鲁多的英语推文更加积极。让我们将分析分为英语和法语,并再次比较 VADER 和 TextBlob,以便更加清晰。

在英语中,看起来 TextBlob 更经常分配正面的推文,但当推文对 VADER 是正面的时,它们是非常正面的。在法语中,这两个软件包产生了更多相似的结果。

最后我们来看看特鲁多推文的情绪,逐月来看。

有趣的是,与法语推文相比,使用 VADER 和 TextBlob 的英语推文给人的感觉更积极。法语是一门很美的语言,但英语只是更热情吗?或者这只是特鲁多倾向于发推特的方式,或者这可以归因于他对每种语言的掌握以及他更习惯的东西?很高兴看到这种情绪在两种语言和两种文本处理工具中都遵循相似的模式。看到 10 月份情绪的下降也很有趣——考虑到过去两天在埃德蒙顿和拉斯维加斯发生的可怕事件,这是有道理的。我们必须等着看这种下降趋势是否会继续。但如果是这样,这可能说明两件事:这可能是世界事件的反映,或者这可能意味着特鲁多作为总理感到疲惫。

感谢阅读!

这个分析的代码可以在 my github 上的一个 Jupyter 笔记本里找到。

原发布于 我的个人网站

印地语和马拉地语音译文本的情感分析

原文:https://towardsdatascience.com/sentiment-analysis-of-transliterated-texts-in-hindi-and-marathi-languages-c29eab19fae2?source=collection_archive---------0-----------------------

这个博客是关于我在自然语言处理领域的论文的陈述。情感分析对英语来说很容易。对于其他语言,如印地语或马拉地语来说,这有点困难,但不是很难。当用于其他语言的文字是罗马文字时,这就变得困难了。最困难的是当音译文本是多种语言的混合时。在我们的例子中,我们考虑英语-印地语和英语-马拉地语的两种组合。这种语言的混合被称为语码混合。通常其中一种语言(通常是罗马文字)用于文本表示。如何分析这种情况下的情绪?

普通情感分析

通常分析中涉及的步骤如下:

  1. 规范化单词标记
  2. 执行词性标签分析,以获取被标记为名词、形容词、副词和动词的单词。
  3. 使用 wordnet 获取标识符,使用 senti-wordnet 获取与这些单词相关的情感,以及我们在 POS 标签分析中找到的相应标签
  4. 将中的单词转换为特征:
  5. 删除停用词
  6. 去掉不重要的词,如除了形容词和副词之外的一切,因为它们在情感方面是最重要的
  7. 创建一个 ngram 特性,将单词与其上下文联系起来
  8. 将其输入分类器进行训练,然后对主题进行测试以计算准确度
  9. 交叉验证用于不过度训练
  10. 找到一个阈值来平衡过度训练和分析看不见的数据的一般性

混合代码通用方法的问题

虽然这些步骤比较复杂,我也错过了一些,但是一般的方法已经包含在上面的步骤中了。音译混合代码的唯一问题是它不能与上述步骤一起工作。为什么?因为音译的文字没有固定的语法,单词拼写也不正确。句子结构不遵循单一语言的特定规则。如果把每种语言的语块都拿出来,那么很多情况下;他们没有形成各自语言的正确语法。最后一部分由于语言规则的混合而发生。一个很好的例子是:缅因州 tujhe 祝你好运因为 tumse na hoga。在前面的陈述中,英语的用法遵循印地语的上下文语法,因此在这种情况下,它们的词性标注及其相关的情感是非常不明确的。由此得出结论,混合代码脚本需要一种不同的方法来实现这一目的,而这正是我的论文所要讨论的。

提议的方法

因为数字说明了千言万语,所以我让下面的数字来说明我为了进行情感分析而采取的方法。

上图给出了这种方法所需的所有重要步骤,下面再次列出,供那些对花时间在图上不感兴趣的人参考。

  • 看看单词 tokens 是一个表情符号还是一个众所周知的俚语,比如 lol 等等,然后用合适的语言作品来替换它们,比如😊会变成微笑,lol 会变成放声大笑。
  • 音译北印度语/马拉地语脚本(梵文)中的剩余单词,并在北印度语/马拉地语词典中查找其存在。检查拼写变化。如果找到了,就贴上标签。
  • 在英语词典中查找所有单词,并标记它们。如果与另一种语言存在平局,那么使用词频概率来打破平局。
  • 根据每种语言(印地语/英语)的语言标签,从 sentiwordnet 中循环得出每种语言的情感分数。除了马拉地语,目前还没有 sentiwordnet,在这种情况下,使用双语词典从印地语和英语中获取马拉地语单词的含义,然后按照这些语言的过程合并分数。
  • 最后,使用 ngrams 将单词转换为具有相应情感得分的特征,并对训练和测试数据进行交叉验证,以查看结果的准确性。

这些步骤实现起来要复杂得多,在使用 python Scikit-learn 实现这些步骤后,我能够得到如下图所示的结果。

最糟糕的是,即使是这些也不如针对单一语言的情感分析有效。对于印地语和英语,我最多能做到 50%以上的准确率,对于马拉地语和英语的组合,我能做到 80%的准确率。现在 80%看起来不错,但有一个警告。马拉地语/英语组合的问题是,固定单词的存在通常会扭曲数据。我使用的数据来自 youtube 评论,在积极和消极的群体中都有一些词,这往往是情绪极性的绝对指标。这使得系统工作,但事实上它真的不工作。我对结果并不感到自豪,但我很高兴我从中学到了很多。下次见。

原载于 2017 年 8 月 3 日【www.3371aspectz.co】

基于多项式朴素贝叶斯的微博情感分析

原文:https://towardsdatascience.com/sentiment-analysis-of-tweets-using-multinomial-naive-bayes-1009ed24276b?source=collection_archive---------3-----------------------

Based on illustration from http://eppsnet.com/2018/05/reflecting-on-mathematical-techniques/.

Web 2.0 的普及显著增加了在线交流。因此,它引发了自然语言处理领域,特别是情感分析领域的快速发展研究。信息过载以及评论和消息数量的增长促进了对高性能自动处理方法的需求。

本文致力于使用具有多项式分布的朴素贝叶斯分类器进行二元情感分析。我们简要概述了从概率模型构建分类器,然后进入数据预处理、训练和超参数优化阶段。我们将使用 Jupyter Notebook 用 Python 编写我们的脚本。

它是如何工作的

多项式朴素贝叶斯分类算法趋向于情感分析任务的一个基线解。朴素贝叶斯技术的基本思想是通过使用词和类别的联合概率来找到分配给文本的类别的概率。让我们简单看一下数学。

Bayes’ theorem spelt out in blue neon at the offices of Autonomy in Cambridge.

给定从属特征向量 (x₁,…,xn) 和类 Ck 。贝叶斯定理在数学上表述为以下关系:

根据“天真”的条件独立性假设,对于给定的类 Ck 矢量xi 的每个特征都是有条件独立于其他每个特征XJforI≠j..

因此,该关系可以简化为

由于***【p(x₁,…,xn)*** 是常数,如果特征变量的值是已知的,可以使用下面的分类规则:

为了避免下溢,可以使用对数概率。

各种朴素贝叶斯分类器之间的主要区别在于它们对 P(xi|Ck) 的分布所做的假设,而 P(Ck) 通常被定义为训练数据集中类 Ck 的相对频率。

多项式分布由针对每个类别***【Ck】***的向量 θk=(θk1,…,θkn) 来参数化,其中 n 是特征的数量(即,词汇的大小),并且 θki 是特征 的概率 P(xi|Ck)

参数 θk 通过最大似然的平滑版本,即相对频率计数来估计:

其中 Nki 是特征 i 出现在训练集 T 中类 k 的样本中的次数,而 Ny 是类 Ck 的所有特征的总数。平滑先验 α≥0 考虑了学习样本中不存在的特征,并防止了进一步计算中的零概率。设置 α=1 称为拉普拉斯平滑,而 α < 1 称为李德斯通平滑。

因此,最终决策规则定义如下:

加载情感数据

俄语推文的情感数据集[1]可在http://study.mokoron.com/获得。文件 positive.csv 和 negative.csv 分别包含带正标签和带负标签的推文。

import pandas as pd
import numpy as np# Read the data from CSV files
n = ['id', 'date','name','text','typr','rep','rtw','faw','stcount','foll','frien','listcount']
data_positive = pd.read_csv('positive.csv', sep=';',error_bad_lines=False, names=n, usecols=['text'])
data_negative = pd.read_csv('negative.csv', sep=';',error_bad_lines=False, names=n, usecols=['text'])# Create balanced dataset
sample_size = min(data_positive.shape[0], data_negative.shape[0])
raw_data = np.concatenate((data_positive['text'].values[:sample_size], 
                           data_negative['text'].values[:sample_size]), axis=0) 
labels = [1]*sample_size + [0]*sample_size

预处理数据

社交媒体网站中由人类生成的文本包含大量噪声,这些噪声会显著影响情感分类过程的结果。此外,根据特征生成方法的不同,每个新术语似乎都给特征空间增加了至少一个新的维度。这使得特征空间更加稀疏和高维。因此,分类器的任务变得更加复杂。

为了准备消息,在该程序中使用了文本预处理技术,如用关键字替换 URL 和用户名、删除标点符号以及转换成小写字母。

import redef preprocess_text(text):
    text = re.sub('((www\.[^\s]+)|(https?://[^\s]+))','URL', text)
    text = re.sub('@[^\s]+','USER', text)
    text = text.lower().replace("ё", "е")
    text = re.sub('[^a-zA-Zа-яА-Я1-9]+', ' ', text)
    text = re.sub(' +',' ', text)
    return text.strip()data = [preprocess_text(t) for t in raw_data]cc

训练多项式朴素贝叶斯

管道类用于使矢量器= >转换器= >分类器更容易使用。诸如 n-grams 范围、IDF 使用、TF-IDF 规范化类型和朴素贝叶斯 alpha 之类的超参数使用网格搜索来调整。所选超参数的性能是在模型训练步骤中未使用的测试集上测量的。

from sklearn.pipeline import Pipeline
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.model_selection import train_test_split, GridSearchCVtext_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', MultinomialNB())])tuned_parameters = {
    'vect__ngram_range': [(1, 1), (1, 2), (2, 2)],
    'tfidf__use_idf': (True, False),
    'tfidf__norm': ('l1', 'l2'),
    'clf__alpha': [1, 1e-1, 1e-2]
}

数据集被分成训练和测试子集。

x_train, x_test, y_train, y_test = train_test_split(data, labels, test_size=0.33, random_state=42)

最后启动了 10 重交叉验证的网格搜索。

from sklearn.metrics import classification_reportclf = GridSearchCV(text_clf, tuned_parameters, cv=10, scoring=score)
clf.fit(x_train, y_train)

print(classification_report(y_test, clf.predict(x_test), digits=4))

测试数据集的分类报告如下所示。

precision    recall  f1-score   support

          0     0.7397    0.7941    0.7659     37078
          1     0.7759    0.7183    0.7460     36792

avg / total     0.7577    0.7564    0.7560     73870

根据网格搜索结果,在开发集上找到的最佳参数集如下:clf__alpha=1tfidf__norm=l2tfidf__use_idf=Truevect__ngram_range=(1, 2)

结果

在开发集上训练的模型在评估集上展示了 F₁=0.765 。通过使用词干化、规范化、句法和语义特征等技术,分类度量可能会得到更大的提高。

Github 提供了源代码。

[## 俄语推文情感分析

使用嵌入 Word2Vec 的卷积神经网络(CNN)对俄语推文进行情感分析。…

github.com](https://github.com/sismetanin/sentiment-analysis-of-tweets-in-russian/blob/master/Sentiment%20Analysis%20of%20Tweets%20in%20Russian%20using%20Multinomial%20Naive%20Bayes.ipynb)

参考

  1. Y.Rubtsova,“为情感分类训练构建语料库”,《软件与系统》,第 109 卷,第 1 期,第 72–78 页,2015 年。
  2. 《朴素贝叶斯》,scikit-learn.org,2018 年。【在线】。可用:http://scikit-learn.org/stable/modules/naive_bayes.html。[访问日期:2018 年 8 月 26 日]。
  3. “使用文本数据”,scikit-learn.org,2018 年。【在线】。可用:http://sci kit-learn . org/stable/tutorial/text _ analytics/working _ with _ text _ data . html。[访问日期:2018 年 8 月 26 日]。

NBA 顶级球员推特账户的情感分析——第二部分推特数据清理

原文:https://towardsdatascience.com/sentiment-analysis-on-nba-top-players-twitter-account-part2-tweets-data-cleaning-aa2cf99519b3?source=collection_archive---------9-----------------------

<本文其他部分的快速链接>

Part1 数据采集

Part2 Tweets 数据清理

Part3 情感分析&聚类

Part4 绩效之间的相关性测试&情绪

摘要

深入研究社交网络上的文本处理

在这一部分,我们将清理推文,因为它们包含不必要的文本,我们也将处理特殊情况。

由于人们经常使用特殊的字符、标点符号或表情符号来表达他们的感受,因此删除除字母以外的所有内容并不是处理推文的最佳方式。例如:

“在中国,据说‘吃了金汤面,便得了金牌’!!明天,如果我一顿饭吃 9 个,也许我能拿到那份财富里的 MVP:)。🍜😋🏀”

上面的句子显然是一个强烈的积极反应,不仅仅是因为词汇,还因为像“!!"、“:)”和😋。如果抹去这些符号,整个表达可能会变得比以前弱得多,或者在最坏的情况下变成完全相反的意思。此外,许多推文只包含特殊字符,因为它们使用起来很方便。简单地把它们拿出来会导致一个巨大的问题。

第 2 部分的先决条件

文本处理

因此,我们只删除一些看起来确实不必要的单词。@ '提及:删除“@ username”(Twitter 中的网名)无论是来自转推还是原创推文。我们知道标记某人是分享强烈情感的一种方式,但我们不在这里讨论。
2。URL:删除所有可能的 URL 链接,因为我们不打算深入链接
3。停用词:去掉没有太大意义的常用词。标点符号:删除标点符号仍然很重要,但我们必须确保我们首先保留了重要的单词或符号,否则它们会被无意识地删除。

此外,我们将以下内容保留在原始格式中,因为我们相信它们需要纳入分析中。表情符号:😋,😢…等等
2。特殊字符:“:(”、“><”…等
3。标签的标签:(#) behappy…etc
4。一些标点:“!!"、“~”、“…”…等等

接下来,我们将开始处理我们的文本分为两部分,第一部分只是标记和删除不必要的单词。第二个是应用两种词干方法,这样我们可以减少实际上具有相同含义的独特单词。这是我做的清理函数:

如果 tweets_cleaner() 的输出是这样的。这里我们只是删除了@ '提及、URL 和一些很少有特殊意义的标点符号。注意,停用词处理在下一个函数中,因为我们需要在移除停用词之前对其进行标记。

如果 tokenization_and_stem() 的输出如下所示。您可以看到每种标记化和词干化方法之间的区别。现在我们可能会看到一些标记看起来毫无意义,例如“:)”变成了“:”和“)”。但是请记住,我们将再次把这个放回句子结构中!

现在,把记号列表放回句子结构中

最后,我们得到了干净的句子!back_to_clean_sent()只是将单词连接成一个句子。

  • sentence_tokenized:删除了停用词的已处理句子。
  • sentence_snowstemmeed:用 SnowballStemmer 方法处理去掉停用词的句子和词干处理。

这是第一个播放器的输出,去掉了一些停用词、标点符号和最有可能没有意义的特殊符号。请注意,在 NLP 中很难获得准确的干净句子,尤其是当我们不针对特定主题或领域时。

以上是对 tweets 的数据清理,第三章我们将实现情感分析和数据聚类。

NBA 顶级球员推特账户的情感分析(三)

原文:https://towardsdatascience.com/sentiment-analysis-on-nba-top-players-twitter-account-part3-sentiment-analysis-clustering-5e5dcd4d690f?source=collection_archive---------8-----------------------

情感分析和聚类

<本文其他部分的快速链接>

Part1 数据采集

Part2 推文数据清理

Part3 情感分析&聚类

Part4 绩效之间的相关性测试&情绪

摘要

终于到了主菜的时间了。让我们回顾一下上一部分的一些结果:

  • sentence_tokenized:处理去掉停用词的句子。
  • sentence_snowstemmeed:使用 SnowballStemmer 方法处理去掉停用词的句子和词干处理。

我们将对原始 tweets、sentence _ tokenized 和 sentence _ snowstemmeed 实施情感分析,以观察这些方法之间的差异并检查它们的效果。当谈到情感分析时,我们使用三种常见的类型,本章将选择基于规则的方法,因为它更容易应用,并且不需要实际的训练集来训练数据。

  • 基于规则的:基于一套预定义的规则和情感评分进行情感分析。
  • 自动:利用机器学习技术从数据中学习。
  • 混合的:结合基于规则和自动的方法。

稍后,我们尝试对玩家进行聚类,以查看每组玩家在 K-means潜在狄利克雷分配中是否有相似的词语使用行为。

第 3 部分的先决条件

我们使用一个名为Vader perspectivity的包,这是一个基于词汇和规则的情绪分析工具,专门用于社交媒体中的情绪分析,因为它在特殊字符上工作得很好,如表情符号和一些标点符号的组合。我们可以认为 lexicon approach 只是一个情感词典,我们只是根据每个单词搜索相应的情感得分,并且还考虑得分应该基于句子的每个长度和特征有多大的权重。

现在,你可能会想,每个人的情绪可能会非常不同。人们对同一个词有不同的表达。为了解决这个问题,软件包的创建者收集了大量的样本,并对每个单词的评分进行平均。

情感分析

然后,我们创建一个情感分析(),这只是一个使我们能够分析大量句子的方法:

以下是第一位玩家基于简单的标记化方法对每条推文的情感评分结果:

这里的复合得分是通过将词典中每个词的化合价得分相加,根据规则进行调整,然后归一化到-1(负得分的最大值)和+1(正得分的最大值)之间来计算的。按照惯例,复合得分≥ 0.05 视为积极情绪;≤ -0.05 是负面情绪;介于-0.05 和 0.05 之间的分数被视为中性。

现在让我们仔细看看原始推文、标记推文和词干推文的情感得分。下图显示了原始推文以及基于不同方法的评分。看出什么不同了吗?被处理过的句子现在往往有更强烈的情绪!

现在,我们根据前面的定义将复合得分转换为“”、“中性”、“”,并放入数据框中。

使聚集

在开始聚类之前,我们必须首先创建 TF-IDF 矩阵和模型。TF-IDF 指的是词频-逆文档频率,它是两个统计量的乘积,这两个统计量反映了一个词对集合或语料库中的文档有多重要:

为了简单起见,这里我们只使用带词干的句子并生成 TF-IDF 矩阵。 Tweets_mix 只是一个收集所有词干句子的列表,只有这样我们才能生成 TF-IDF 矩阵。

k 均值聚类

首先,我们实现了聚类的 K-means,在本文中我们选择了 3 个聚类:

接下来,输出玩家及其对应的集群:

请记住,我们试图将玩家分组,看看每组玩家在选择词汇时是否有相似的行为。换句话说,我们需要知道每个聚类的单词集。然而,根据前面的过程,我们使用词干化的单词来生成 TF-IDF 矩阵,这意味着每个聚类的单词集也是词干化的单词。

例如,如果聚类 1 显示“famli”和“happi”是他们最常用的词,我们知道“famli”等于“家庭”,“happi”等于“快乐”;虽然对我们来说并不总是那么简单。

为了解决这个问题,我们必须翻译回我们非常熟悉的单词。为此,我们创建了一个字典,比如{"happi" : "happy"},这样当我们计算频繁出现的词干时,就可以立即追溯到原来的单词。 docs_tokenizeddocs_snowstemmed 是包含根据每个玩家的标记化和词干化的单词的列表,我们将使用它们进行我们的原始单词翻译。

然后,我们输出每个玩家对应的聚类和他们经常使用的单词:

在输出中,我们可以看到像斯蒂芬·库里或安东尼·戴维斯这样的球员倾向于在推特上多次使用相同的特定词语。另一方面,像拉塞尔·维斯特布鲁克这样的球员通常会标记他所属的州。

请注意,当每个集群中的集群数量分布不均匀时,您可能会得到一个坏的集群。此外,这里的集群似乎没有太多的信息,但我们所说的只是为了证明我们也可以在 NLP 上实现集群。

潜在的狄利克雷分配(主题建模)

潜在狄利克雷分配 ( LDA )是一种生成模型,它使样本集由未观察到的组来解释,并显示为什么数据的某些部分彼此相似。在 LDA 中,每个文档可以被视为各种主题的混合,其中每个文档被认为具有通过 LDA 分配给它的一组主题。

假设观察值是 LDA 文档中的单词,那么我们说该文档是各种小主题的混合,每个单词的创建可归因于文档的一个主题,如下图所示:

source: Failure Prognosis of High Voltage Circuit Breakers with Temporal Latent Dirichlet Allocation

从数学的角度来看,基本的直觉是这样的:

在本文中,我们设置了 3 个组件,因为我们在 K-means 方法中也有 3 个聚类。 n_stop_words 表示我们希望看到每个主题中的前 3 个常用词。数字设置为 4 是因为索引问题,所以我们必须为 3 的结果加上 1。LDA 方法如下:

同样,下面是每个玩家对应集群的输出以及他们经常使用的单词:

对情感的分析和聚类就是这样。第四章我们要去检验选手的成绩之间是否存在相关性,在相关性测试之前做一些 EDA。

NBA 顶级球员推特账户的情感分析——第四部分

原文:https://towardsdatascience.com/sentiment-analysis-on-nba-top-players-twitter-account-part4-correlation-tests-between-f9bdbe224779?source=collection_archive---------19-----------------------

绩效和情绪之间的相关性测试

<本文其他部分的快速链接>

Part1 数据采集

Part2 推文数据清理

Part3 情感分析&聚类

Part4 绩效之间的相关性测试&情绪

摘要

经过漫长的过程,我们终于要看到球员在球场上的表现与他们的推特之间是否有任何统计相关性。现在让我们看看会发生什么!

第 2 部分的先决条件

在我们开始之前,可视化和相关性测试需要这些包:

数据可视化

在这里,我们将绘制一些图表,以便对每个玩家的情绪得分有一个简单的了解。可惜由于数据本身的限制,只有两个图看起来有点用。

首先,我们来看看 2016-2018 年选手的平均情绪得分。很明显,所有的玩家通常都发布积极的推文,这在现实中是很符合逻辑的,对吗?这里,我们在标记化方法和词干化方法中实现情感评分。

来自标记化方法的情感分数越浅,来自词干化方法的情感分数越深。词干法中的分数都较低,但不会对结果产生太大影响。

此外,我们绘制出每个玩家的每月情绪得分。下面的图有两条蓝色水平线,表示积极、中性和消极情绪。在-0.05 和 0.05 线之间为中性;以上为正;下方是负数。

绩效和情绪之间的相关性测试

最后,还记得我们的终极目标吗?我们很好奇球员赛前的情绪会不会和他们的表现有什么关联。

**可悲的是,我们的文章指出在皮尔逊相关性检验下它们之间没有相关性。**至少我们知道 NBA 球员在场上的时候都很专业。他们能够忘记除了游戏之外的一切!

这就是本文的全部任务。谢谢,喜欢就鼓掌!!

美国 Twitter 航空公司数据集上的情感分析—第 1 页,共 2 页

原文:https://towardsdatascience.com/sentiment-analysis-on-us-twitter-airline-dataset-1-of-2-2417f204b971?source=collection_archive---------3-----------------------

我想探索一些情感分析的概念,并尝试一些可以在数据分析和情感分析方面提供帮助的库。使用的数据集是“ *Twitter 美国航空公司情绪”*在 ka ggle:https://www . ka ggle . com/crowd flower/Twitter-Airline-sensation上很容易找到

这个数据集非常好,包含了 2015 年 2 月美国航空公司的推文,分为正面、负面和中性推文。负面推文也根据负面原因进行分类。
本帖分为两部分:

  • 第一部分:对数据集进行数据分析,找出最好和最差的航空公司,并了解在糟糕的航班情况下最常见的问题是什么
  • 第二部分:训练两个朴素贝叶斯分类器:首先将推文分类为正面和负面,第二个分类器根据原因将负面推文分类。这样就有可能用新的推文来更新第一点的统计数据。

这项工作有助于航空公司了解需要解决的问题。

对于这项工作的 Python 与:熊猫,jupyter 笔记本和 NLTK 将被使用。

Pandas 是一个开源库,为 Python 提供了高性能、易于使用的数据结构和分析工具。我将使用这个库来加载数据集并进行一些分析。

Jupyter notebook 对数据科学家非常有用,因为它是一个 web 应用程序,允许创建和共享包含实时代码、等式、可视化和说明性文本的文档。这样,共享工作就很容易了。

NLTK 是一个平台,用于构建使用人类语言的程序。用这个库来训练计算语言学的分类器是很简单的。

数据分析

好了,先从数据分析开始。观察数据集,我们可以发现许多列,但最重要的是:

  • 航空公司
  • 航空公司 _ 情绪
  • 消极原因

这个数据集不需要任何清理操作,但是对于我要回答的问题,一些转换是必要的。首先,有必要将推文分为三组:正面、负面和中性。然后我想找到 2015 年 2 月最好和最差的航空公司。之后,我想找出导致糟糕飞行的常见问题。为此,只考虑负面推文(显然!).

最差航空公司的结果如下:

最好的结果是:

从数据集中,不良飞行问题的等级是:

结论

所以糟糕的飞行的最重要的原因是由于客户服务…对公司来说不是很好…

在下一篇文章中,我将训练贝叶斯分类器来分析新的推文。

原载于 2017 年 9 月 28 日【devklaus.wordpress.com】

美国 Twitter 航空数据集上的情感分析—第 2 页,共 2 页

原文:https://towardsdatascience.com/sentiment-analysis-on-us-twitter-airline-dataset-2-of-2-9e23d8563441?source=collection_archive---------6-----------------------

在数据集上可以找到在最后一篇文章中所做的分析结果。但是现在,我的目标是让这些统计数据在每条微博上更新,或者每小时更新一次。因此,首先,有必要训练一个分类器,能够将新推文分为正面和负面。

选择的分类器是朴素贝叶斯分类器。该分类器是最简单的监督机器学习方法之一,并且结果是可接受的。

用于训练分类器的步骤如下:

  • 将 NLTK 与 punkt 一起使用
  • 定义了一组无用词(用 nltk 停用词和字符串标点符号)来正确标记推文
  • 将负面和正面的推文符号化,并定义特征
  • 用训练集制作了朴素贝叶斯情感分类器
  • 测试分类器并找到准确性

正如我在上一篇文章中所写的,NLTK 是一个非常强大的库,所以创建分类器很容易。转换成代码的步骤如下:

正如我们所见,分类器的准确率约为 86%,这个结果取决于用于训练的少量 tweets。我只用了 2000 条推文,因为这个数据集的正面推文只有大约 2400 条。负面推文的数量更高,但我不能使用所有这些推文。有必要用相同数量的正面和负面推文训练分类器,以避免引入偏差。

这项工作的最后一步是使用负面推文来训练一个分类器,以找出负面推文的原因。定义分类器的步骤与第一个分类器相同,但现在的子集只有负面推文。

在这项工作中,我试图只对负面推文的前两个原因进行分类,因为其他原因没有足够的数据。所有其他推文被归类为其他

对于这个分类器,达到的准确率是 69%,不太好。但是使用的推文数量只有 1000 和 400 来验证分类器。

结论

准确度为 86%的第一分类器是可接受的,因为人类的准确度约为 80%。但是第二种的精度是不能接受的,因为太低了。

如果我们考虑组合准确度(负面和正面的分类,以及负面推文的原因分类),它下降到 59%。

这些结果的主要原因是因为数据集几乎没有正面的推文,也没有针对每个负面原因的推文。不排除使用更复杂的分类器可以达到更好的结果。

原载于 2017 年 10 月 3 日【devklaus.wordpress.com】

通过 LSTMs 进行情感分析

原文:https://towardsdatascience.com/sentiment-analysis-through-lstms-3d6f9506805c?source=collection_archive---------4-----------------------

用不到 50 行代码构建您自己的模型

自然语言处理简介

语言将人类联系在一起。语言是我们向另一个人传达思想和感情的工具,在这个工具的帮助下,我们也能够理解他们的思想和感情。我们大多数人从 18 个月大到 2 岁左右开始说话。人们还没有完全理解人脑是如何在如此幼小的年龄掌握如此大量的知识的。但是,已经发现大多数语言处理功能发生在大脑的大脑皮层内。

情感分析背后的动机

人类自己无法理解我们的大脑到底是如何处理语言的。那么,我们有没有可能教会机器学习我们的语言呢??是的,通过广泛的研究,已经开发了许多方法来帮助机器理解我们的语言。NLP 或自然语言处理是关注人类语言和计算机之间交互的研究领域。自然语言处理的一个子问题是情感分析,即将一个陈述分类为正面或负面。将一个陈述分为正面或负面有什么用??我们以亚马逊网站为例。在亚马逊上,它的用户可以对产品发表评论,说明它是好是坏,甚至可以是中性的。现在,使用人工阅读所有的评论并获得客户对产品的总体反馈将是昂贵且耗时的。进入我们的机器学习模型。机器学习模型可以在大量数据中搅动,做出推论并对评论进行分类。使用这种 ML 模型,亚马逊可以通过客户评论来改进产品,从而为公司带来更多收入。

情感分析并不像看起来那么简单。如果你认为包含“好”、“棒极了”等词语的评论可以被归类为正面评论,而包含“糟糕”、“悲惨”等词语的评论可以被归类为负面评论,请再想想。E.x:“完全缺乏良好的品味”和“对快餐很好,但没什么特别的”分别代表负面和中性的反馈,即使它们含有“好”这个词。因此,正如我提到的,这项任务可能不像看起来那么容易。让我们继续我们将要处理的数据。

资料组

我们将查看来自亚马逊产品评论、IMDB 电影评论和 Yelp 评论的评论,以建立我们的情感分析模型。可以从这个链接下载数据。所有数据都已经标注,0 代表负反馈,1 代表正反馈。几行亚马逊数据看起来与下图相似。

密码

我们写点代码吧!

数据存在于不同的文本文件中。我们打开每个文件,阅读所有文本行,包括每个文本的标签。然后,我们将它们存储在一个名为“lines”的列表中。

在数据集中的每一行,我们有文本和后面的四个字符空间,我们有该文本的标签(0 或 1)。因此,我们取包含文本的第一部分,并将其添加到我们的特征(x)中,然后我们取标签,其末尾有' \n '。因此,它被删除,然后添加到我们的标签列表(y)。

Keras 有一个内置的 API,使得为计算准备文本变得更加容易。Tokenizer 类有 4 个属性,可用于准备要素。看一下下面的例子来理解 tokenizer 实际上做了什么。

## CODE
tokenizer = Tokenizer()texts = ["The sun is shining in June!","September is grey.","Life is beautiful in August.","I like it","This and other things?"]tokenizer.fit_on_texts(texts)print(tokenizer.word_index)tokenizer.texts_to_sequences(["June is beautiful and I like it!"])## OUPUT{'sun': 3, 'september': 4, 'june': 5, 'other': 6, 'the': 7, 'and': 8, 'like': 9, 'in': 2, 'beautiful': 11, 'grey': 12, 'life': 17, 'it': 16, 'i': 14, 'is': 1, 'august': 15, 'things': 10, 'shining': 13, 'this': 18}[[5, 1, 11, 8, 14, 9, 16]]

Tokenizer 为句子中的每个单词分配索引值,并且可以使用该索引值来表示新的句子。由于我们使用的文本语料库包含大量不同的单词,我们设置了一个上限,只使用最经常出现的 2500 个单词。

我们现在将文本转换成如上所示的数字序列,并填充数字序列。由于句子可以有不同的长度,它们的序列长度也会不同。因此,pad_sequences 查找最长的句子,并用 0 填充所有其他语句以匹配该长度。

## Pad Sequences Example
pad_sequences([[1, 2, 3], [3, 4, 5, 6], [7, 8]])
array([[0, 1, 2, 3],
       [3, 4, 5, 6],
       [0, 0, 7, 8]], dtype=int32)

我们将标签转换成一个热编码。这有助于 LSTM 网络预测文本的标签。现在,我们已经准备好了文本数据,我们可以将它分成训练样本和测试样本。80%的数据用于训练,20%的数据用于测试模型。

我们现在建立模型,编译它,训练它,测试它。该模型具有嵌入层。输入序列是文本的稀疏表示,因为词汇表将是巨大的,并且给定的单词将由大的向量来表示。如果我们能够建立一些序列的密集表示,网络就更容易预测。2500 个单词的单词嵌入/密集表示是通过嵌入层训练模型而得到的。然后,我们添加 LSTM 和密集层的模型。LSTM 细胞负责进行上下文推理,并帮助预测一个句子是否是肯定句。密集层输出每个类别的概率。我没有给出太多关于 LSTMs 的细节。想了解更多,请参考这个博客

输出

Training

Testing

您刚刚用 50 行代码构建了一个情感分类器。

使用 RNNs 的情感分析(LSTM)

原文:https://towardsdatascience.com/sentiment-analysis-using-rnns-lstm-60871fa6aeba?source=collection_archive---------0-----------------------

这里,我们使用评论的例子来预测情绪(尽管它可以更普遍地应用于其他领域,例如对推文、评论、客户反馈等的情绪分析)。这里的整体思想是,电影评论是由单词序列和单词顺序组成的,这些单词编码了许多对预测情感有用的信息。第一步是将单词映射到单词嵌入(参见帖子 12 了解更多关于单词嵌入的上下文)。步骤 2 是 RNN,它接收向量序列作为输入,并考虑向量的顺序来生成预测。

该网络的架构如下所示。

这里,我们将把单词传递给一个嵌入层。您实际上可以用 word2vec 训练一个嵌入,并在这里使用它。但是只要有一个嵌入层并让网络自己学习嵌入表就足够了。

从嵌入层,新的表现将被传递到 LSTM 细胞。这将增加网络的循环连接,这样我们就可以在数据中包含单词序列的信息。最后,LSTM 细胞将进入一个 sigmoid 输出层。我们使用 sigmoid 是因为我们试图预测这篇文章是否有积极或消极的情绪。输出层将只是一个具有 s 形激活函数的单一单元。

除了最后一个,我们不关心 sigmoid 输出,其他的可以忽略。我们将根据上一步的输出和训练标签来计算成本。

架构摘要:

将固定长度的评论编码为整数,然后转换为嵌入向量,以循环方式传递给 LSTM 层,并挑选最后的预测作为输出情感。

陷阱:

在我的实验中,我无法解释的一件事是,当我将单词编码为整数时,如果我随机为单词分配唯一的整数,我得到的最佳准确度是 50–55%(基本上,该模型并不比随机猜测好多少)。但是,如果对单词进行编码,使得最高频率的单词得到最低的数字,那么在 3-5 个时期内,模型精度为 80%。我的猜测是,这对于训练嵌入层是必要的,但是在任何地方都找不到原因的解释。

代码:

https://github . com/mchablani/deep-learning/blob/master/情操-rnn/情操 _RNN.ipynb

数据预处理:

将评论中的所有单词用整数编码。现在每个评论都是一个有序的整数数组。让每个评论固定大小(比如 200),这样较短的评论前面会填充 0,而较长的评论会被截断到 200。因为我们用 0 填充,所以单词到 int 的映射从 1 开始。标签被编码为“1”和“0”,分别代表“正”和“负”。

构建图表

lstm_size = 256
lstm_layers = 2
batch_size = 500
learning_rate = 0.001
embed_size = 300n_words = len(vocab_to_int) + 1 # Add 1 for 0 added to vocab# Create the graph object
tf.reset_default_graph()
with tf.name_scope('inputs'):
    inputs_ = tf.placeholder(tf.int32, [None, None], name="inputs")
    labels_ = tf.placeholder(tf.int32, [None, None], name="labels")
    keep_prob = tf.placeholder(tf.float32, name="keep_prob")# Sizeof embedding vectors (number of units in the embedding layer)
with tf.name_scope("Embeddings"):
    embedding = tf.Variable(tf.random_uniform((n_words, embed_size), -1, 1))
    embed = tf.nn.embedding_lookup(embedding, inputs_)def lstm_cell():
    # Your basic LSTM cell
    lstm = tf.contrib.rnn.BasicLSTMCell(lstm_size, reuse=tf.get_variable_scope().reuse)
    # Add dropout to the cell
    return tf.contrib.rnn.DropoutWrapper(lstm, output_keep_prob=keep_prob)with tf.name_scope("RNN_layers"):
    # Stack up multiple LSTM layers, for deep learning
    cell = tf.contrib.rnn.MultiRNNCell([lstm_cell() for _ in range(lstm_layers)])

    # Getting an initial state of all zeros
    initial_state = cell.zero_state(batch_size, tf.float32)with tf.name_scope("RNN_forward"):
    outputs, final_state = tf.nn.dynamic_rnn(cell, embed, initial_state=initial_state)with tf.name_scope('predictions'):
    predictions = tf.contrib.layers.fully_connected(outputs[:, -1], 1, activation_fn=tf.sigmoid)
    tf.summary.histogram('predictions', predictions)
with tf.name_scope('cost'):
    cost = tf.losses.mean_squared_error(labels_, predictions)
    tf.summary.scalar('cost', cost)with tf.name_scope('train'):
    optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)

配料和培训

def get_batches(x, y, batch_size=100):

    n_batches = len(x)//batch_size
    x, y = x[:n_batches*batch_size], y[:n_batches*batch_size]
    for ii in range(0, len(x), batch_size):
        yield x[ii:ii+batch_size], y[ii:ii+batch_size]epochs = 10# with graph.as_default():
saver = tf.train.Saver()with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    train_writer = tf.summary.FileWriter('./logs/tb/train', sess.graph)
    test_writer = tf.summary.FileWriter('./logs/tb/test', sess.graph)
    iteration = 1
    for e in range(epochs):
        state = sess.run(initial_state)

        for ii, (x, y) in enumerate(get_batches(train_x, train_y, batch_size), 1):
            feed = {inputs_: x,
                    labels_: y[:, None],
                    keep_prob: 0.5,
                    initial_state: state}
            summary, loss, state, _ = sess.run([merged, cost, final_state, optimizer], feed_dict=feed)
#             loss, state, _ = sess.run([cost, final_state, optimizer], feed_dict=feed)train_writer.add_summary(summary, iteration)

            if iteration%5==0:
                print("Epoch: {}/{}".format(e, epochs),
                      "Iteration: {}".format(iteration),
                      "Train loss: {:.3f}".format(loss))if iteration%25==0:
                val_acc = []
                val_state = sess.run(cell.zero_state(batch_size, tf.float32))
                for x, y in get_batches(val_x, val_y, batch_size):
                    feed = {inputs_: x,
                            labels_: y[:, None],
                            keep_prob: 1,
                            initial_state: val_state}
#                     batch_acc, val_state = sess.run([accuracy, final_state], feed_dict=feed)
                    summary, batch_acc, val_state = sess.run([merged, accuracy, final_state], feed_dict=feed)
                    val_acc.append(batch_acc)
                print("Val acc: {:.3f}".format(np.mean(val_acc)))
            iteration +=1
            test_writer.add_summary(summary, iteration)
            saver.save(sess, "checkpoints/sentiment_manish.ckpt")
    saver.save(sess, "checkpoints/sentiment_manish.ckpt")

学分:来自课堂讲稿:https://classroom.udacity.com/nanodegrees/nd101/syllabus

围棋中基于简单朴素贝叶斯分类器的情感分析

原文:https://towardsdatascience.com/sentiment-analysis-with-a-simple-naive-bayes-classifier-in-go-6c18a0134a1c?source=collection_archive---------12-----------------------

使用 Go 通过情感分析对文本进行分类

(credits: Chang Sau Sheong)

我最近在读 Pedro Domingos 的大师算法。这是一本引人入胜的读物,有一些有趣的想法。在书中,多明戈斯提出,机器学习算法可以归入 5 个部落之一——符号主义者、连接主义者、进化论者、贝叶斯主义者和类比主义者。每个部落都有自己的算法。符号主义者是逆向演绎(决策树),连接主义者是反向传播(神经网络),进化者是遗传编程(遗传算法),贝叶斯主义者是贝叶斯定理,类比主义者是支持向量机(SVM)。

当我在读关于贝叶斯人的那一章时,我记得大约 10 年前我在我的旧博客中写过一篇关于朴素贝叶斯分类器的博文。所以我把它挖了出来(我的旧博客现在处于休眠状态,已经很多年没碰过了),掸去灰尘,决定刷新和重温这个话题。

我想做一些事情。首先,我将在 Go 中重写它。Ruby 代码工作得非常好,但是重温旧代码并看看如何改进它总是感觉很好。第二,我将把它用于一个非常流行的目的——情感分析(稍后我会谈到这一点)。最后,我将使用适当的训练和测试数据集对其进行训练和测试(我之前的博客文章中没有这一项)。

贝叶斯定理

在我们开始学习贝叶斯定理之前,让我们回到基础知识,谈谈概率。概率是某件事情发生的可能性,在数学中我们将其表示为 0 到 1 之间的一个数字,其中 0 表示它永远不会发生,1 表示它永远会发生。

条件概率是一种特殊的概率,它受某些条件或某些背景信息的影响。例如,你可能会也可能不会和你的朋友出去(一种可能性),但这受天气影响——如果雨下得很大,你可能不想出去。所以你出去的概率是一个条件概率,基于天气。

Going out in the rain with your friends (credits: https://commons.wikimedia.org/wiki/File:Singin%27_in_the_Rain_trailer.jpg)

为了用数学来表示,我们假设不管发生什么,你出门的概率是A,坏天气的概率是B,你出门的条件概率,取决于天气是p(A|B),或者大声读出是“给定 B,A 的概率”。

一个联合概率是两个事件都实现的概率。在我们上面的例子中,你在恶劣天气下外出的概率是p(A and B)。你可能已经学过(或者从中学数学中有一些模糊的回忆)如果两个概率彼此独立,那么p(A and B) = p(A)p(B),即A的概率和BA的独立概率和B的独立概率的倍数。

然而我们刚刚了解到A实际上并不独立于B,所以p(A)实际上是p(A|B)的一个特例。如果下雨,会减少你外出的可能性。换句话说,更一般的数学描述是:

p(A and B) = p(A|B)p(B)

由于AB可以是一般化的任何事件,因此AB的合取概率是可交换的:

p(A and B) = p(B and A)

如果我们代入方程:

p(A|B)p(B) = p(B|A)p(A)

然后得到p(A|B)的条件概率:

Bayes’ Theorem

这就是所谓的贝叶斯定理(或贝叶斯定律或贝叶斯法则)。

情感分析

现在让我们看看我们想要解决的问题,然后再回头看看贝叶斯定理是如何被用来解决它的。情感分析是一种根据说话者或作者所说或写下的内容来判断其心理状态的技术。它通常用于挖掘社交媒体(推文、评论、评论等)对品牌、产品或服务的情感,因为手动挖掘太困难、太昂贵或太慢。情感分析也被用于政治,在竞选活动中衡量公众对某些话题的看法。

这是一个相当复杂的问题,有许多不同类型的算法可以使用,其中一些可能非常复杂。在我们的例子中,我们希望分析来自亚马逊、IMDB 和 Yelp 的不同文本评论,并了解情绪是积极的还是消极的。换句话说,这是一个分类问题,我们将基于贝叶斯定理构建一个分类器。

基于贝叶斯定理的文档分类

分类器就是对其他事物进行分类的东西。分类器是一个函数,它接收一组数据,并告诉我们数据属于哪个类别或分类。要对一个文本文档进行分类,我们要问——给定一个特定的文档,它属于这个类别的概率是多少?当我们找到给定文档在所有类别中的概率时,分类器挑选概率最高的类别,并宣布它为获胜者,也就是说,该文档最有可能属于该类别。

让我们将前面的数学公式转换成一个可用于文档分类的公式:

Bayes Theorem for document classification

在上面的公式中,p(category|document)就是我们要找的东西——给定一个文档,它属于这个类别的概率是多少?

类似地,p(document|category)是该文档存在于该类别中的概率,p(category)是该类别与任何文档无关的概率,p(document)是该文档与任何类别无关的概率。

我们真正需要的只是p(document|category)p(category)。我们可以去掉p(document),因为它对每个类别都是一样的。

那么我们如何找到p(document|category)?文档是由一串单词组成的,因此文档的概率是文档中所有单词的联合概率。给定一个类别的文档的概率是该文档中所有单词在一个类别中的联合概率。

一个词出现在一个类别中的概率很简单,那只是这个词在类别中出现的次数。连接部分非常棘手,因为单词不会随机出现在文档中,单词的顺序和外观取决于文档中的其他单词。那么我们如何解决这个问题呢?这就是朴素贝叶斯分类器朴素部分的用武之地。我们简单地忽略单词的条件概率,并假设每个单词都是相互独立的。换句话说(双关语),我们假设单词随机出现在文档中。做出这样的假设似乎非常愚蠢,但是让我们看看它是如何实现的。

概率p(category)相对容易,它只是一个类别中文档的数量除以所有类别中文档的总数。

这很简单。让我们来看看代码。

围棋中的朴素贝叶斯分类器

创建分类器

我们将开始在一个名为classifier.go的文件中创建一个通用的朴素贝叶斯文本分类器。

首先,我们创建了Classifier结构。

// Classifier is what we use to classify documents
type Classifier struct {
	words               map[string]map[string]int
	totalWords          int
	categoriesDocuments map[string]int
	totalDocuments      int
	categoriesWords     map[string]int
	threshold           float64
}

// create and initialize the classifier
func createClassifier(categories []string, threshold float64) (c Classifier) {
	c = Classifier{
		words:               make(map[string]map[string]int),
		totalWords:          0,
		categoriesDocuments: make(map[string]int),
		totalDocuments:      0,
		categoriesWords:     make(map[string]int),
		threshold:           threshold,
	}

	for _, category := range categories {
		c.words[category] = make(map[string]int)
		c.categoriesDocuments[category] = 0
		c.categoriesWords[category] = 0
	}
	return
}

在该结构中,words是表示已经由分类器训练的单词的映射图。大概是这样的(不完全是):

{
    "1": {
        "good": 10,
        "wonderful": 5,
        "amazing": 7,
    },
    "0": {
        "awful": 6,
        "loud": 4,
    }
}

totalWords字段是分类器中单词的总数,而totalDocuments是分类器中文档的总数。

categoriesDocuments字段是给出每个类别中文档数量的图:

{
    "1": 13,
    "0": 16,
}

categoriesWords字段是给出每个类别中单词数量的图:

{
    "1": 35,
    "0": 44,
}

稍后我会描述threshold

计数单词

分类器的核心实际上是对单词进行计数,所以接下来让我们来看看。我们有一个函数countWords可以做到这一点,它传入一个文档,并返回每个单词出现次数的地图。

var cleaner = regexp.MustCompile(`[^\w\s]`)
// truncated list
var stopWords = map[string]bool{"a": true, "able": true, "about": true, ..., "you've": true, "z": true, "zero": true}

// clean up and split words in document, then stem each word and count the occurrence
func countWords(document string) (wordCount map[string]int) {
	cleaned := cleaner.ReplaceAllString(document, "")
	words := strings.Split(cleaned, " ")
	wordCount = make(map[string]int)
	for _, word := range words {
		if !stopWords[word] {
			key := stem(strings.ToLower(word))
			wordCount[key]++
		}
	}
	return
}

// stem a word using the Snowball algorithm
func stem(word string) string {
	stemmed, err := snowball.Stem(word, "english", true)
	if err == nil {
		return stemmed
	}
	fmt.Println("Cannot stem word:", word)
	return word
}

首先,我们使用正则表达式清理文档,删除所有不是单词的内容(包括标点符号等)。然后我们将文档拆分成单词。

我们不需要文档中的所有单词,我们只需要关键词,所以我们删除了文档中任何常见的单词,例如,我们将忽略冠词,如 athe ,代词,如 heshe 等等。所以我们用一个停用词列表,过滤掉那些常用词。其余的将被放入小写,使关键一致。

很多词都有不同的变体,比如名词可以是复数(要一起算),动词可以有时态(要一起算)等等。为了不重复计算单词变化,我们使用一种叫做词干的技术。在我们的分类器中,我使用了一个词干分析器库,基于雪球算法雪球

最后,将单词计数相加并返回。

训练分类器

训练分类器实际上就是对训练数据集文档中的单词进行计数,繁重的工作由countWords函数完成。分类器中的Train方法简单地使用了countWords函数,并根据类别分配计数。

// Train the classifier
func (c *Classifier) Train(category string, document string) {
	for word, count := range countWords(document) {
		c.words[category][word] += count
		c.categoriesWords[category] += count
		c.totalWords += count
	}
	c.categoriesDocuments[category]++
	c.totalDocuments++
}

文档分类

这是实际行动开始的地方。在进入Classify方法之前,让我们再看一下等式:

p(category|document) = p(document|category)p(category)

我们将创建一个方法来计算每个概率。先说p(category)

// p (category)
func (c *Classifier) pCategory(category string) float64 {
	return float64(c.categoriesDocuments[category]) / float64(c.totalDocuments)
}

这是不言自明的——我们将类别中的文档数除以文档总数,得到该类别的概率。

接下来我们来看p(document|category)

// p (document | category)
func (c *Classifier) pDocumentCategory(category string, document string) (p float64) {
	p = 1.0
	for word := range countWords(document) {
		p = p * c.pWordCategory(category, word)
	}
	return p
}

func (c *Classifier) pWordCategory(category string, word string) float64 {
	return float64(c.words[category][stem(word)]+1) / float64(c.categoriesWords[category])
}

首先,我们使用countWords给出文档中的字数。这里我们实际上并不关心字数,我们只是想要文档中的关键词列表。对于每一个关键词,我们在类别中找到它的概率。这就是该关键字在类别中出现的次数除以类别中的总字数。例如,在训练分类器之后,假设对于类别1(它是肯定的),我们有 10 个单词“good”。而我们在类别1中总共有 100 个单词。这意味着该词在类别中的概率是0.1

我们对文档中的每个关键词都这样做,然后将所有这些概率相乘,这将是p(document|category)

最后,我们找到了p(category|document),这是相当琐碎的。

// p (category | document)
func (c *Classifier) pCategoryDocument(category string, document string) float64 {
	return c.pDocumentCategory(category, document) * c.pCategory(category)
}

现在我们有了每个类别的条件概率,我们把它们放在一个单一的地图中。

// Probabilities of each category
func (c *Classifier) Probabilities(document string) (p map[string]float64) {
	p = make(map[string]float64)
	for category := range c.words {
		p[category] = c.pCategoryDocument(category, document)
	}
	return
}

这将由我们的Classify方法使用。

// Classify a document
func (c *Classifier) Classify(document string) (category string) {
	// get all the probabilities of each category
	prob := c.Probabilities(document)

	// sort the categories according to probabilities
	var sp []sorted
	for c, p := range prob {
		sp = append(sp, sorted{c, p})
	}
	sort.Slice(sp, func(i, j int) bool {
		return sp[i].probability > sp[j].probability
	})

	// if the highest probability is above threshold select that
	if sp[0].probability/sp[1].probability > c.threshold {
		category = sp[0].category
	} else {
		category = "unknown"
	}

	return
}

我们的Classify方法根据概率对类别进行排序,并找出最重要的类别。但这还不是结束。顶级和二级之间的差别可能非常小。例如,让我们以将电子邮件分类为垃圾邮件和非垃圾邮件为例,假设概率是这样的-垃圾邮件是 51%,非垃圾邮件是 49%。该文档是否应归类为垃圾邮件?这取决于你希望分类器有多严格。

这就是threshold字段的原因,它是用于分离类别的阈值比率。例如,如果threshold1.5,这意味着具有最高概率的类别需要比第二高的概率高 1.5 倍。如果顶级类别没有达到阈值,我们将把它归类为unknown

我们已经完成了分类器,接下来让我们看看如何使用它。

使用朴素贝叶斯分类器的情感分析

在这篇博文中,我使用了 Dimitrios Kotzias 等人为论文“使用深度特征从群体到个体标签”创建的情感标签句子数据集。艾尔。KDD 2015。该数据集包含来自亚马逊、IMDB 和 Yelp 网站的 1000 条评论,标签为正面的1或负面的0。这些评论分别摘自产品、电影和餐馆的评论。

首先,让我们看看数据是如何设置的。

设置数据

我将每个数据集分为训练数据集和测试数据集,并使用训练数据集来训练分类器,使用测试数据集来验证分类器。这是通过setupData功能完成的。

// datasets
type document struct {
	sentiment string
	text      string
}

var train []document
var test []document

// set up data for training and testing
func setupData(file string) {
	rand.Seed(time.Now().UTC().UnixNano())
	data, err := readLines(file)
	if err != nil {
		fmt.Println("Cannot read file", err)
		os.Exit(1)
	}
	for _, line := range data {
		s := strings.Split(line, "|")
		doc, sentiment := s[0], s[1]

		if rand.Float64() > testPercentage {
			train = append(train, document{sentiment, doc})
		} else {
			test = append(test, document{sentiment, doc})
		}
	}
}

// read the file line by line
func readLines(path string) ([]string, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	return lines, scanner.Err()
}

我使用变量testPercentage来获取整个数据集作为测试数据集的百分比。这又被用来随机选择测试数据集中的一些记录。

创建文档分类器

一旦我们建立了数据集,我们开始用我们的参数创建分类器。

// parameters
var (
	testPercentage = 0.1
	datafile       = "amazon.txt"
	threshold      = 1.1
)

var categories = []string{"1", "0"}

func main() {
	setupData(datafile)
	fmt.Println("Data file used:", datafile)
	fmt.Println("no of docs in TRAIN dataset:", len(train))
	fmt.Println("no of docs in TEST dataset:", len(test))

	c := createClassifier(categories, threshold)

...

用训练数据集训练分类器

给定分类器,我们开始使用训练数据集来训练它。

...
	// train on train dataset
	for _, doc := range train {
		c.Train(doc.sentiment, doc.text)
    }
...

测试数据集上的测试分类器

在训练分类器之后,我们使用它在测试数据集上进行测试。

...
	// validate on test dataset
	count, accurates, unknowns := 0, 0, 0
	for _, doc := range test {
		count++
		sentiment := c.Classify(doc.text)
		if sentiment == doc.sentiment {
			accurates++
		}
		if sentiment == "unknown" {
			unknowns++
		}
	}
	fmt.Printf("Accuracy on TEST dataset is %2.1f%% with %2.1f%% unknowns", float64(accurates)*100/float64(count), float64(unknowns)*100/float64(count))
...

我们计算精确分类的数量,以及未知分类的数量。

在训练数据集上测试分类器

我们还对一些训练数据集进行了测试,以进行健全性检查。

..
	// validate on the first 100 docs in the train dataset
	count, accurates, unknowns = 0, 0, 0
	for _, doc := range train[0:100] {
		count++
		sentiment := c.Classify(doc.text)
		if sentiment == doc.sentiment {
			accurates++
		}
		if sentiment == "unknown" {
			unknowns++
		}
	}
	fmt.Printf("\nAccuracy on TRAIN dataset is %2.1f%% with %2.1f%% unknowns", float64(accurates)*100/float64(count), float64(unknowns)*100/float64(count))
...

我们来看看结果。

成绩还不算太差!你可能会意识到,如果你运行多次,你会得到不同的结果,这是因为在培训中使用的顺序和文件实际上很重要。您也可以尝试调整不同的参数,以查看分类器的行为。

结论

你可能会很惊讶(如果你还不知道的话)这样一个简单的算法实际上是如何表现得相对较好的。然而,这种特殊的做法有一个警告。首先,对使用的数据集进行清洗,选择明确的阳性或阴性。在现实世界中,情感分析充满了许多其他问题,真的不是一个简单的问题。然而,这一点只是为了表明贝叶斯定理可以成为你的工具箱中一个非常强大的工具。

源代码

你可以在 https://github.com/sausheong/gonb 的 Github 中找到这段代码

参考

  1. 我最初的博文大量引用了托比·塞格兰的《T2 编程集体智慧》一书
  2. 佩德罗·多明戈斯引人入胜的大师算法一书引发了这篇文章,值得再次提及
  3. 艾伦·唐尼的书认为贝叶斯很好地描述了贝叶斯定律,我在这篇博客文章中描述它时从书中得到了一些启示
  4. 我使用了 Kotzias 等人的论文“使用深度特征从组到个体标签”中的数据集。艾尔。KDD 2015

使用 PySpark 进行情感分析

原文:https://towardsdatascience.com/sentiment-analysis-with-pyspark-bc8e83f80c35?source=collection_archive---------1-----------------------

Photo by Chris J. Davis on Unsplash

Apache Spark 是我非常感兴趣但没有太多机会探索的工具之一。大多数时候,Pandas 和 Scikit-Learn 足以处理我试图建立模型的数据量。但这也意味着我还没有机会处理数 Pb 的数据,我希望为我面临真正大数据的情况做好准备。

我以前尝试过用 PySpark 进行一些基本的数据操作,但只达到非常基本的水平。我想在使用 PySpark 的过程中了解更多信息,更加得心应手。这篇文章是我为了更好地理解 PySpark 所做的努力。

Python 非常适合数据科学建模,这要归功于它众多的帮助实现数据科学目标的模块和包。但是,如果您处理的数据无法放入一台机器中,该怎么办呢?也许您可以在单台机器上实现仔细的采样来进行分析,但是使用像 PySpark 这样的分布式计算框架,您可以高效地实现大型数据集的任务。

Spark API 支持多种编程语言(Scala、Java、Python 和 R)。关于 Spark 的性能如何随运行它的语言而变化,存在争议,但是因为我一直使用的主要语言是 Python,所以我将重点讨论 PySpark,而不会过多地讨论我应该为 Apache Spark 选择什么语言。

Image courtesy of DataFlair

Spark 通过其 API 提供了三种不同的数据结构:RDD、Dataframe(这不同于 Pandas data frame)、Dataset。对于这篇文章,我将使用 Dataframe 和相应的机器学习库 SparkML。我首先决定了我想要使用的数据结构,这是基于来自 Analytics Vidhya 的帖子的建议。Dataframe 比 RDD 快得多,因为它有关联的元数据(一些关于数据的信息),这允许 Spark 优化查询计划可以从原帖中找到全面的介绍。

在 Databricks 上也有一个信息丰富的帖子,比较了 Apache Spark 的不同数据结构:“三个 Apache Spark APIs 的故事:rdd、DataFrames 和 Datasets ”。

然后我发现,如果我想处理 Dataframe,我需要使用 SparkML 而不是 SparkMLLib。SparkMLLib 与 RDD 一起使用,而 SparkML 支持 Dataframe。

还有一点需要注意的是,我将使用笔记本电脑在本地模式下工作。本地模式通常用于原型、开发、调试和测试。然而,由于 Spark 的本地模式与集群模式完全兼容,本地编写的代码只需几个额外的步骤就可以在集群上运行。

为了在 Jupyter 笔记本中使用 PySpark,您应该配置 PySpark 驱动程序,或者使用一个名为 Findspark 的包,使 Spark 上下文在您的 Jupyter 笔记本中可用。您可以通过命令行上的“pip install findspark”轻松安装 Findspark。让我们首先加载一些我们需要的基本依赖项。

除了我将附上的简短代码块,你可以在这篇文章的末尾找到整个 Jupyter 笔记本的链接。

import findspark
findspark.init()
import pyspark as ps
import warnings
from pyspark.sql import SQLContext

任何 Apache 编程的第一步都是创建 SparkContext。当我们想要在集群中执行操作时,需要 SparkContext。SparkContext 告诉 Spark 如何以及在哪里访问集群。这是连接 Apache 集群的第一步。

try:
    # create SparkContext on all CPUs available: in my case I have 4 CPUs on my laptop
    sc = ps.SparkContext('local[4]')
    sqlContext = SQLContext(sc)
    print("Just created a SparkContext")
except ValueError:
    warnings.warn("SparkContext already exists in this scope")

我将在这篇文章中使用的数据集是来自“感知 140 ”的带注释的推文。它源于斯坦福大学的一个研究项目,我在之前的 Twitter 情感分析系列中使用了这个数据集。由于我已经在我之前的项目过程中清理了推文,我将使用预先清理的推文。如果你想更详细地了解我采取的清理过程,你可以查看我以前的帖子:“用 Python 进行的另一次 Twitter 情绪分析——第二部分”。

df = sqlContext.read.format('com.databricks.spark.csv').options(header='true', inferschema='true').load('project-capstone/Twitter_sentiment_analysis/clean_tweet.csv')
type(df)

df.show(5)

df = df.dropna()
df.count()

在成功地将数据装载为 Spark Dataframe 之后,我们可以通过调用。show(),相当于熊猫。头部()。去掉 NA 之后,我们的 Tweets 只有不到 160 万条。我将把它分成三部分:培训、验证、测试。因为我有大约 160 万个条目,验证和测试集各有 1%就足够测试模型了。

(train_set, val_set, test_set) = df.randomSplit([0.98, 0.01, 0.01], seed = 2000)

HashingTF + IDF +逻辑回归

通过我之前使用 Pandas 和 Scikit-Learn 进行情感分析的尝试,我了解到 TF-IDF 与 Logistic 回归是一个相当强的组合,并且表现出稳健的性能,与 Word2Vec +卷积神经网络模型一样高。所以在本帖中,我将尝试用 PySpark 实现 TF-IDF + Logistic 回归模型。

顺便说一下,如果你想知道更多关于 TF-IDF 是如何计算的细节,请查看我以前的帖子:“用 Python 进行的另一个 Twitter 情感分析—第五部分(Tfidf 矢量器,模型比较,词法方法)

from pyspark.ml.classification import LogisticRegression
lr = LogisticRegression(maxIter=100)
lrModel = lr.fit(train_df)
predictions = lrModel.transform(val_df)from pyspark.ml.evaluation import BinaryClassificationEvaluator
evaluator = BinaryClassificationEvaluator(rawPredictionCol="rawPrediction")
evaluator.evaluate(predictions)

0.86!那看起来不错,也许太好了。因为我已经在 Pandas 和 SKLearn 中使用相同的数据尝试了相同的技术组合,所以我知道使用逻辑回归的 unigram TF-IDF 的结果大约有 80%的准确性。由于详细的模型参数,可能会有一些细微的差异,但这看起来太好了。

通过查看 Spark 文档,我意识到 BinaryClassificationEvaluator 所评估的默认情况下是 areaUnderROC。

对于二进制分类,Spark 不支持将准确性作为度量标准。但是我仍然可以通过计算匹配标签的预测数并除以总条目数来计算准确性。

accuracy = predictions.filter(predictions.label == predictions.prediction).count() / float(val_set.count())
accuracy

现在看起来似乎更合理,实际上,精确度比我从 SKLearn 的结果中看到的略低。

计数矢量器+ IDF +逻辑回归

还有另一种方法可以获得 IDF(逆文档频率)计算的词频。它是 SparkML 中的 CountVectorizer。除了特性(词汇表)的可逆性之外,它们在过滤顶级特性的方式上也有很大的不同。在 HashingTF 的情况下,这是由于可能的冲突而导致的维数减少。CountVectorizer 会丢弃不常用的标记。

让我们看看如果使用 CountVectorizer 而不是 HashingTF,性能是否会发生变化。

看起来使用 CountVectorizer 稍微提高了一点性能。

n 元语法实现

在 Scikit-Learn 中,n-gram 的实现相当容易。当调用 TfIdf 矢量器时,可以定义 n 元语法的范围。但是对于 Spark 来说,就有点复杂了。它不会自动组合来自不同 n-gram 的特征,所以我不得不在管道中使用 VectorAssembler 来组合我从每个 n-gram 获得的特征。

我首先试图从一元、二元、三元模型中提取大约 16,000 个特征。这意味着我总共将获得大约 48,000 个特征。然后,我实现了卡方特征选择,将特征总数减少到 16,000 个。

现在我准备运行上面定义的函数。

%%time
trigram_pipelineFit = build_trigrams().fit(train_set)
predictions = trigram_pipelineFit.transform(val_set)
accuracy = predictions.filter(predictions.label == predictions.prediction).count() / float(dev_set.count())
roc_auc = evaluator.evaluate(predictions)# print accuracy, roc_auc
print "Accuracy Score: {0:.4f}".format(accuracy)
print "ROC-AUC: {0:.4f}".format(roc_auc)

精确度有所提高,但是您可能已经注意到了,拟合模型花了 4 个小时!这主要是因为 ChiSqSelector。

如果我首先从 unigram、bigram、trigram 中分别提取 5460 个特征,最终总共有大约 16000 个特征,而没有卡方特征选择,会怎么样?

%%timetrigramwocs_pipelineFit = build_ngrams_wocs().fit(train_set)
predictions_wocs = trigramwocs_pipelineFit.transform(val_set)
accuracy_wocs = predictions_wocs.filter(predictions_wocs.label == predictions_wocs.prediction).count() / float(val_set.count())
roc_auc_wocs = evaluator.evaluate(predictions_wocs)# print accuracy, roc_auc
print "Accuracy Score: {0:.4f}".format(accuracy_wocs)
print "ROC-AUC: {0:.4f}".format(roc_auc_wocs)

这给了我几乎相同的结果,略低,但差异在第四位。考虑到它只需要 6 分钟,我肯定会选择没有 ChiSqSelector 的模型。

最后,让我们在最终的测试集上尝试这个模型。

test_predictions = trigramwocs_pipelineFit.transform(test_set)
test_accuracy = test_predictions.filter(test_predictions.label == test_predictions.prediction).count() / float(test_set.count())
test_roc_auc = evaluator.evaluate(test_predictions)# print accuracy, roc_auc
print "Accuracy Score: {0:.4f}".format(test_accuracy)
print "ROC-AUC: {0:.4f}".format(test_roc_auc)

最终测试集的准确率为 81.22%,ROC-AUC 为 0.8862。

通过这篇文章,我用 PySpark 实现了一个简单的情感分析模型。尽管这可能不是 PySpark 的高级应用,但我相信让自己不断接触新环境和新挑战是很重要的。探索 PySpark 的一些基本功能确实引发了我的兴趣(没有双关的意思)。

我明天(2018 年 13 月 3 日)将参加 Spark 伦敦会议,主题是“Apache Spark:深度学习管道、PySpark MLLib 和流中的模型”。我迫不及待地想深入探索 PySpark 世界!!

感谢您的阅读,您可以通过以下链接找到 Jupyter 笔记本:

https://github . com/tthustle sa/setiment _ analysis _ py spark/blob/master/opinion % 20 analysis % 20 with % 20 py spark . ipynb

用 Python 进行情感分析(第 1 部分)

原文:https://towardsdatascience.com/sentiment-analysis-with-python-part-1-5ce197074184?source=collection_archive---------0-----------------------

IMDb 电影评论分类

Photo by Denise Jans on Unsplash

情感分析是数据科学家需要执行的一项常见 NLP 任务。这是一个用 Python 创建准系统电影评论分类器的简单指南。本系列的后续部分将重点改进分类器。

本系列中使用的所有代码以及补充材料都可以在这个 GitHub 资源库中找到。

数据概述

在这项分析中,我们将使用来自 IMDb 的 50,000 条电影评论的数据集。这些数据由安德鲁·马斯汇编,可以在这里找到: IMDb 评论

数据被平均分割,25k 条评论用于训练,25k 条用于测试你的分类器。而且每套都有 12.5k 的正面和 12.5k 的负面评论。

IMDb 让用户从 1 到 10 给电影打分。为了给这些评论贴上标签,数据管理员将≤ 4 星的评论标为负面,将≥ 7 星的评论标为正面。5 星或 6 星的评论被排除在外。

第一步:下载并合并电影评论

如果你还没有,去 IMDb 评论点击“大电影评论数据集 1.0 版”。一旦完成,在你的下载文件夹中就会有一个名为aclImdb_v1.tar.gz的文件。

**快捷方式:**如果您想直接进行数据分析和/或对终端不太熟悉,我在这里放了一个这个步骤创建的最终目录的 tar 文件:合并的电影数据。双击这个文件应该足以解压它(至少在 Mac 上),否则终端中的gunzip -c movie_data.tar.gz | tar xopf —就会这么做。

拆包和合并

遵循这些步骤或者在这里运行 shell 脚本:预处理脚本

  1. 将 tar 文件移动到您希望存储这些数据的目录中。
  2. 打开一个终端窗口,cd到你放aclImdb_v1.tar.gz的目录。
  3. gunzip -c aclImdb_v1.tar.gz | tar xopf -
  4. cd aclImdb && mkdir movie_data
  5. for split in train test; do for sentiment in pos neg; do for file in $split/$sentiment/*; do cat $file >> movie_data/full_${split}.txt; echo >> movie_data/full_${split}.txt; done; done; done;

步骤 2:读入 Python

对于本演练中我们想要做的大多数事情,我们只需要我们的评论在 Python list中。确保将open指向存放电影数据的目录。

步骤 3:清理和预处理

这些评论的原始文本相当混乱,所以在我们进行任何分析之前,我们需要清理一下。这里有一个例子:

"This isn't the comedic Robin Williams, nor is it the quirky/insane Robin Williams of recent thriller fame. This is a hybrid of the classic drama without over-dramatization, mixed with Robin's new love of the thriller. But this isn't a thriller, per se. This is more a mystery/suspense vehicle through which Williams attempts to locate a sick boy and his keeper.<br /><br />Also starring Sandra Oh and Rory Culkin, this Suspense Drama plays pretty much like a news report, until William's character gets close to achieving his goal.<br /><br />I must say that I was highly entertained, though this movie fails to teach, guide, inspect, or amuse. It felt more like I was watching a guy (Williams), as he was actually performing the actions, from a third person perspective. In other words, it felt real, and I was able to subscribe to the premise of the story.<br /><br />All in all, it's worth a watch, though it's definitely not Friday/Saturday night fare.<br /><br />It rates a 7.7/10 from...<br /><br />the Fiend :."

**注意:**理解并能够使用正则表达式是执行任何自然语言处理任务的先决条件。如果你不熟悉它们,也许可以从这里开始:正则表达式教程

这是同样的评论现在的样子:

"this isnt the comedic robin williams nor is it the quirky insane robin williams of recent thriller fame this is a hybrid of the classic drama without over dramatization mixed with robins new love of the thriller but this isnt a thriller per se this is more a mystery suspense vehicle through which williams attempts to locate a sick boy and his keeper also starring sandra oh and rory culkin this suspense drama plays pretty much like a news report until williams character gets close to achieving his goal i must say that i was highly entertained though this movie fails to teach guide inspect or amuse it felt more like i was watching a guy williams as he was actually performing the actions from a third person perspective in other words it felt real and i was able to subscribe to the premise of the story all in all its worth a watch though its definitely not friday saturday night fare it rates a   from the fiend"

**注意:**有许多不同的、更复杂的方法来清理文本数据,它们可能会产生比我在这里所做的更好的结果。我希望本教程的第 1 部分尽可能简单。此外,我通常认为,在花费时间进行可能不必要的转换之前,最好用最简单的可能解决方案获得基线预测。

…向量化…

为了让这些数据对我们的机器学习算法有意义,我们需要将每个评论转换成数字表示,我们称之为矢量化

最简单的形式是创建一个非常大的矩阵,用一列来表示语料库中的每个独特的单词(在我们的例子中,语料库是所有 50k 篇评论)。然后我们将每个评论转换成包含 0 和 1 的一行,其中 1 表示与该列对应的语料库中的单词出现在那个评论中。也就是说,矩阵的每一行都非常稀疏(大部分是零)。这个过程也被称为一次热编码

步骤 4:构建分类器

既然我们已经将数据集转换成适合建模的格式,我们就可以开始构建分类器了。逻辑回归是我们使用的一个很好的基线模型,原因有几个:(1)它们易于解释,(2)线性模型往往在像这样的稀疏数据集上表现良好,以及(3)与其他算法相比,它们学习起来非常快。

为了简单起见,我只担心超参数C,它调整正则化

**注意:**我们用于训练和测试的目标/标签将是相同的,因为两个数据集的结构相同,其中第一个 12.5k 是正的,最后一个 12.5k 是负的。

看起来给我们最高精度的 C 值是0.05

列车最终模型

现在我们已经找到了 C 的最佳值,我们应该使用整个训练集训练一个模型,并评估我们在 25k 测试评论上的准确性。

作为一个理智的检查,让我们来看看正面和负面评论中最有区别的 5 个词。我们将通过分别查看最大和最小系数来做到这一点。

这就是了。一个非常简单的分类器,开箱后具有相当不错的准确性。

下次

在本系列的下一部分中,我们将研究更复杂的方法来提高分类器的性能。

  • 文本处理:词干化/词条化,将每个单词的不同形式转化为一个。
  • n-grams :除了单词标记(1-gram/unigram),我们还可以包含单词对。
  • 表示:代替简单的二进制向量,我们可以使用字数或 TF-IDF 来转换这些计数。
  • 算法:除了逻辑回归,我们还会看看支持向量机的表现。

点击这里查看:

[## 用 Python 进行情感分析(第 2 部分)

改进电影评论情感分类器

towardsdatascience.com](/sentiment-analysis-with-python-part-2-4f71e7bde59a)

感谢阅读!这是我在 Medium 上的第一篇帖子,所以请评论你的任何问题或建议。

基于文本挖掘的情感分析

原文:https://towardsdatascience.com/sentiment-analysis-with-text-mining-13dd2b33de27?source=collection_archive---------2-----------------------

了解如何准备文本数据并运行两个不同的分类器来预测推文的情绪。

Photo by Romain Vignes on Unsplash

在本教程中,我将探索一些用于情感分析的文本挖掘技术。首先,我们将花一些时间准备文本数据。这将涉及清理文本数据,删除停用词和词干。为此,Kaggle 上的 Twitter 美国航空公司情绪数据集非常适合合作。它包含 tweet 的文本和一个具有三个可能情感值的变量。

为了推断推文的情感,我们使用两个分类器:逻辑回归和多项式朴素贝叶斯。我们将使用网格搜索来调整两个分类器的超参数。

我们将用三个指标来比较性能:精确度、召回率和 F1 分数。

我们从导入包和配置一些设置开始。

import numpy as np 
import pandas as pd 
pd.set_option('display.max_colwidth', -1)
from time import time
import re
import string
import os
import emoji
from pprint import pprint
import collectionsimport matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="darkgrid")
sns.set(font_scale=1.3)from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.metrics import classification_reportfrom sklearn.naive_bayes import MultinomialNB
from sklearn.linear_model import LogisticRegression
from sklearn.externals import joblibimport gensimfrom nltk.corpus import stopwords
from nltk.stem import PorterStemmer
from nltk.tokenize import word_tokenizeimport warnings
warnings.filterwarnings('ignore')np.random.seed(37)

加载数据

我们读取了从 Kaggle 数据集下载的逗号分隔文件。我们打乱了数据帧,以防类被排序。对原始指数的permutation应用reindex方法有利于此。在这本笔记本中,我们将使用text变量和airline_sentiment变量。

df = pd.read_csv('../input/Tweets.csv')
df = df.reindex(np.random.permutation(df.index))
df = df[['text', 'airline_sentiment']]

探索性数据分析

目标变量

我们将预测三个类别标签:负面、中性或正面。

正如我们在下面的图表中看到的,分类标签是不平衡的。这是我们在模型训练阶段应该记住的事情。有了 seaborn 包的factorplot,我们可以可视化目标变量的分布。

sns.factorplot(x="airline_sentiment", data=df, kind="count", size=6, aspect=1.5, palette="PuBuGn_d")
plt.show();

Imbalanced distribution of the target class labels

输入变量

为了分析text 变量,我们创建了一个类TextCounts。在这个类中,我们计算文本变量的一些基本统计数据。

  • count_words:推文字数
  • count_mentions:其他 Twitter 账户的推荐以@开头
  • count_hashtags:标签字数,以#开头
  • count_capital_words:一些大写单词有时被用来“叫喊”和表达(负面)情绪
  • count_excl_quest_marks:问号或感叹号的个数
  • count_urls:推文中的链接数量,以 http(s)开头
  • count_emojis:表情符号的数量,这可能是情绪的一个好迹象
class TextCounts(BaseEstimator, TransformerMixin):

    def count_regex(self, pattern, tweet):
        return len(re.findall(pattern, tweet))

    def fit(self, X, y=None, **fit_params):
        # fit method is used when specific operations need to be done on the train data, but not on the test data
        return self

    def transform(self, X, **transform_params):
        count_words = X.apply(lambda x: self.count_regex(r'\w+', x)) 
        count_mentions = X.apply(lambda x: self.count_regex(r'@\w+', x))
        count_hashtags = X.apply(lambda x: self.count_regex(r'#\w+', x))
        count_capital_words = X.apply(lambda x: self.count_regex(r'\b[A-Z]{2,}\b', x))
        count_excl_quest_marks = X.apply(lambda x: self.count_regex(r'!|\?', x))
        count_urls = X.apply(lambda x: self.count_regex(r'http.?://[^\s]+[\s]?', x))
        # We will replace the emoji symbols with a description, which makes using a regex for counting easier
        # Moreover, it will result in having more words in the tweet
        count_emojis = X.apply(lambda x: emoji.demojize(x)).apply(lambda x: self.count_regex(r':[a-z_&]+:', x))

        df = pd.DataFrame({'count_words': count_words
                           , 'count_mentions': count_mentions
                           , 'count_hashtags': count_hashtags
                           , 'count_capital_words': count_capital_words
                           , 'count_excl_quest_marks': count_excl_quest_marks
                           , 'count_urls': count_urls
                           , 'count_emojis': count_emojis
                          })

        return df
tc = TextCounts()
df_eda = tc.fit_transform(df.text)
df_eda['airline_sentiment'] = df.airline_sentiment

查看 TextStats 变量与 class 变量的关系可能会很有趣。因此我们编写了一个函数show_dist,它为每个目标类提供了描述性的统计数据和图表。

def show_dist(df, col):
    print('Descriptive stats for {}'.format(col))
    print('-'*(len(col)+22))
    print(df.groupby('airline_sentiment')[col].describe())
    bins = np.arange(df[col].min(), df[col].max() + 1)
    g = sns.FacetGrid(df, col='airline_sentiment', size=5, hue='airline_sentiment', palette="PuBuGn_d")
    g = g.map(sns.distplot, col, kde=False, norm_hist=True, bins=bins)
    plt.show()

下面你可以找到每个目标类别的 tweet 字数分布。为简洁起见,我们将仅限于这个变量。所有 TextCounts 变量的图表都在 Github 的笔记本里。

  • 推文中使用的字数相当低。最大的字数是 36 个,甚至有只有 2 个字的推文。所以在数据清理过程中,我们必须小心,不要删除太多的单词。但是文字处理会更快。负面推文比中性或正面推文包含更多单词。
  • 所有推文至少有一次提及。这是基于 Twitter 数据中的提及提取推文的结果。就情感而言,提及次数似乎没有什么不同。
  • 大多数推文不包含哈希标签。所以这个变量在模型训练期间不会被保留。同样,对于情感,散列标签的数量没有差别。
  • 大多数推文不包含大写单词,我们看不到情绪分布的差异。
  • 积极的推文似乎使用了更多的感叹或问号。
  • 大多数推文不包含网址。
  • 大多数推文不使用表情符号。

文本清理

在我们开始使用 tweets 的文本之前,我们需要清理它。我们将在CleanText **课上做这件事。**在这个课程中,我们将执行以下操作:

  • 删除提及,因为我们也想推广到其他航空公司的推文。
  • 删除散列标签符号(#),但不要删除实际的标签,因为这可能包含信息
  • 将所有单词设为小写
  • 删除所有标点符号,包括问号和感叹号
  • 删除网址,因为它们不包含有用的信息。我们没有注意到情感类别之间使用的 URL 数量的差异
  • 确保将表情符号转换成一个单词。
  • 删除数字
  • 删除停用词
  • 应用PorterStemmer保留单词的词干
class CleanText(BaseEstimator, TransformerMixin):
    def remove_mentions(self, input_text):
        return re.sub(r'@\w+', '', input_text)

    def remove_urls(self, input_text):
        return re.sub(r'http.?://[^\s]+[\s]?', '', input_text)

    def emoji_oneword(self, input_text):
        # By compressing the underscore, the emoji is kept as one word
        return input_text.replace('_','')

    def remove_punctuation(self, input_text):
        # Make translation table
        punct = string.punctuation
        trantab = str.maketrans(punct, len(punct)*' ')  # Every punctuation symbol will be replaced by a space
        return input_text.translate(trantab) def remove_digits(self, input_text):
        return re.sub('\d+', '', input_text)

    def to_lower(self, input_text):
        return input_text.lower()

    def remove_stopwords(self, input_text):
        stopwords_list = stopwords.words('english')
        # Some words which might indicate a certain sentiment are kept via a whitelist
        whitelist = ["n't", "not", "no"]
        words = input_text.split() 
        clean_words = [word for word in words if (word not in stopwords_list or word in whitelist) and len(word) > 1] 
        return " ".join(clean_words) 

    def stemming(self, input_text):
        porter = PorterStemmer()
        words = input_text.split() 
        stemmed_words = [porter.stem(word) for word in words]
        return " ".join(stemmed_words)

    def fit(self, X, y=None, **fit_params):
        return self

    def transform(self, X, **transform_params):
        clean_X = X.apply(self.remove_mentions).apply(self.remove_urls).apply(self.emoji_oneword).apply(self.remove_punctuation).apply(self.remove_digits).apply(self.to_lower).apply(self.remove_stopwords).apply(self.stemming)
        return clean_X

为了展示清理后的文本变量的外观,这里有一个示例。

ct = CleanText()
sr_clean = ct.fit_transform(df.text)
sr_clean.sample(5)

高兴 rt 打赌鸟愿飞南方冬天
点 upc 代码检查 baggag 告诉 luggag vacat day tri 泳装
vx jfk la dirti 飞机不标准
告诉意味着工作需要估计时间到达请需要笔记本电脑工作感谢
当然业务去 els 航空旅行姓名凯瑟琳索特罗

文本清理的一个副作用是一些行的文本中没有任何单词。对于CountVectorizerTfIdfVectorizer来说,这不成问题。然而,对于Word2Vec算法来说,这会导致一个错误。有不同的策略来处理这些缺失的价值观。

  • 删除整行,但在生产环境中这是不可取的。
  • 用类似*[no_text]*的占位符文本估算缺失值
  • 当应用 Word2Vec 时:使用所有向量的平均值

这里我们将使用占位符文本进行估算。

empty_clean = sr_clean == ''
print('{} records have no words left after text cleaning'.format(sr_clean[empty_clean].count()))
sr_clean.loc[empty_clean] = '[no_text]'

现在,我们已经清理了推文的文本,我们可以看看最常用的词是什么。下面我们将展示前 20 个单词。出现频率最高的词是“逃”。

cv = CountVectorizer()
bow = cv.fit_transform(sr_clean)
word_freq = dict(zip(cv.get_feature_names(), np.asarray(bow.sum(axis=0)).ravel()))
word_counter = collections.Counter(word_freq)
word_counter_df = pd.DataFrame(word_counter.most_common(20), columns = ['word', 'freq'])fig, ax = plt.subplots(figsize=(12, 10))
sns.barplot(x="word", y="freq", data=word_counter_df, palette="PuBuGn_d", ax=ax)
plt.show();

创建测试数据

为了检查模型的性能,我们需要一套测试设备。对训练数据的评估是不正确的。您不应该在用于训练模型的相同数据上进行测试。

首先,我们将TextCounts变量与CleanText变量结合起来。最初,我在GridSearchCV中错误地执行了 TextCounts 和 CleanText。这花费了太长时间,因为每次运行 GridSearch 都要应用这些函数。只运行一次就足够了。

df_model = df_eda
df_model['clean_text'] = sr_clean
df_model.columns.tolist()

所以df_model现在包含了几个变量。但是我们的矢量器(见下文)将只需要clean_text变量。可以添加TextCounts变量。为了选择列,我编写了下面的类ColumnExtractor

class ColumnExtractor(TransformerMixin, BaseEstimator):
    def __init__(self, cols):
        self.cols = cols def transform(self, X, **transform_params):
        return X[self.cols] def fit(self, X, y=None, **fit_params):
        return selfX_train, X_test, y_train, y_test = train_test_split(df_model.drop('airline_sentiment', axis=1), df_model.airline_sentiment, test_size=0.1, random_state=37)

超参数调整和交叉验证

正如我们将在下面看到的,矢量器和分类器都有可配置的参数。为了选择最佳参数,我们需要在单独的验证集上进行测试。培训期间没有使用该验证集。然而,仅使用一个验证集可能不会产生可靠的验证结果。由于偶然的机会,您可能在验证集上有一个好的模型性能。如果您以其他方式分割数据,您可能会得到其他结果。为了得到更准确的估计,我们进行交叉验证。

通过交叉验证,我们可以多次将数据分成训练集和验证集。然后在不同的折叠上对评估度量进行平均。幸运的是,GridSearchCV 应用了现成的交叉验证。

为了找到矢量器和分类器的最佳参数,我们创建了一个Pipeline

评估指标

默认情况下,GridSearchCV 使用默认计分器来计算best_score_。对于MultiNomialNbLogisticRegression来说,这个默认的评分标准是准确性。

在我们的函数grid_vect中,我们额外生成了测试数据的classification_report。这为每个目标类提供了一些有趣的度量。这在这里可能更合适。这些指标是精确度、召回率和 F1 分数**。**

  • Precision : 在我们预测为某个类的所有行中,我们正确预测了多少?
  • 回想一下 : 在某个类的所有行中,我们正确预测了多少行?
  • F1 得分 : 精确度和召回率的调和平均值。

利用混淆矩阵的元素,我们可以计算精确度和召回率。

# Based on [http://scikit-learn.org/stable/auto_examples/model_selection/grid_search_text_feature_extraction.html](http://scikit-learn.org/stable/auto_examples/model_selection/grid_search_text_feature_extraction.html)
def grid_vect(clf, parameters_clf, X_train, X_test, parameters_text=None, vect=None, is_w2v=False):

    textcountscols = ['count_capital_words','count_emojis','count_excl_quest_marks','count_hashtags'
                      ,'count_mentions','count_urls','count_words']

    if is_w2v:
        w2vcols = []
        for i in range(SIZE):
            w2vcols.append(i)
        features = FeatureUnion([('textcounts', ColumnExtractor(cols=textcountscols))
                                 , ('w2v', ColumnExtractor(cols=w2vcols))]
                                , n_jobs=-1)
    else:
        features = FeatureUnion([('textcounts', ColumnExtractor(cols=textcountscols))
                                 , ('pipe', Pipeline([('cleantext', ColumnExtractor(cols='clean_text')), ('vect', vect)]))]
                                , n_jobs=-1) pipeline = Pipeline([
        ('features', features)
        , ('clf', clf)
    ])

    # Join the parameters dictionaries together
    parameters = dict()
    if parameters_text:
        parameters.update(parameters_text)
    parameters.update(parameters_clf) # Make sure you have scikit-learn version 0.19 or higher to use multiple scoring metrics
    grid_search = GridSearchCV(pipeline, parameters, n_jobs=-1, verbose=1, cv=5)

    print("Performing grid search...")
    print("pipeline:", [name for name, _ in pipeline.steps])
    print("parameters:")
    pprint(parameters) t0 = time()
    grid_search.fit(X_train, y_train)
    print("done in %0.3fs" % (time() - t0))
    print() print("Best CV score: %0.3f" % grid_search.best_score_)
    print("Best parameters set:")
    best_parameters = grid_search.best_estimator_.get_params()
    for param_name in sorted(parameters.keys()):
        print("\t%s: %r" % (param_name, best_parameters[param_name]))

    print("Test score with best_estimator_: %0.3f" % grid_search.best_estimator_.score(X_test, y_test))
    print("\n")
    print("Classification Report Test Data")
    print(classification_report(y_test, grid_search.best_estimator_.predict(X_test)))

    return grid_search

GridSearchCV 的参数网格

在网格搜索中,我们将研究分类器的性能。用于测试性能的一组参数如下所示。

# Parameter grid settings for the vectorizers (Count and TFIDF)
parameters_vect = {
    'features__pipe__vect__max_df': (0.25, 0.5, 0.75),
    'features__pipe__vect__ngram_range': ((1, 1), (1, 2)),
    'features__pipe__vect__min_df': (1,2)
} # Parameter grid settings for MultinomialNB
parameters_mnb = {
    'clf__alpha': (0.25, 0.5, 0.75)
} # Parameter grid settings for LogisticRegression
parameters_logreg = {
    'clf__C': (0.25, 0.5, 1.0),
    'clf__penalty': ('l1', 'l2')
}

分类器

这里我们将比较一下MultinomialNBLogisticRegression的性能。

mnb = MultinomialNB()
logreg = LogisticRegression()

计数矢量器

为了在分类器中使用单词,我们需要将单词转换成数字。Sklearn 的CountVectorizer获取所有推文中的所有单词,分配一个 ID,并统计每个推文中该单词的出现频率。然后,我们使用这个单词包作为分类器的输入。这一袋单词是一个稀疏的数据集。这意味着每条记录都将有许多零,代表没有在 tweet 中出现的单词。

countvect = CountVectorizer()# MultinomialNB
best_mnb_countvect = grid_vect(mnb, parameters_mnb, X_train, X_test, parameters_text=parameters_vect, vect=countvect)
joblib.dump(best_mnb_countvect, '../output/best_mnb_countvect.pkl')# LogisticRegression
best_logreg_countvect = grid_vect(logreg, parameters_logreg, X_train, X_test, parameters_text=parameters_vect, vect=countvect)
joblib.dump(best_logreg_countvect, '../output/best_logreg_countvect.pkl')

TF-IDF 矢量器

CountVectorizer 的一个问题是可能会有频繁出现的单词。这些词可能没有歧视性信息。因此它们可以被移除。 TF-IDF(词频—逆文档频率)可以用来对这些频繁出现的词进行降权。

tfidfvect = TfidfVectorizer()# MultinomialNB
best_mnb_tfidf = grid_vect(mnb, parameters_mnb, X_train, X_test, parameters_text=parameters_vect, vect=tfidfvect)
joblib.dump(best_mnb_tfidf, '../output/best_mnb_tfidf.pkl')# LogisticRegression
best_logreg_tfidf = grid_vect(logreg, parameters_mnb, X_train, X_test, parameters_text=parameters_vect, vect=tfidfvect)
joblib.dump(best_logreg_tfidf, '../output/best_logreg_tfidf.pkl')

Word2Vec

将单词转换成数值的另一种方法是使用Word2Vec。Word2Vec 将每个单词映射到多维空间中。它通过考虑一个词在推文中出现的上下文来做到这一点。结果,相似的单词在多维空间中也彼此接近。

Word2Vec 算法是 gensim 包的一部分。

Word2Vec 算法使用单词列表作为输入。为此,我们使用了nltk包的word_tokenize方法。

SIZE = 50X_train['clean_text_wordlist'] = X_train.clean_text.apply(lambda x : word_tokenize(x))
X_test['clean_text_wordlist'] = X_test.clean_text.apply(lambda x : word_tokenize(x))model = gensim.models.Word2Vec(X_train.clean_text_wordlist
, min_count=1
, size=SIZE
, window=5
, workers=4)model.most_similar('plane', topn=3)

Word2Vec 模型提供了所有 tweets 中的词汇。对于每个单词,你也有它的向量值。向量值的数量等于所选的大小。这些是每个单词在多维空间中映射的维度。出现次数少于min_count的单词不会保留在词汇表中。

min_count 参数的一个副作用是一些 tweets 可能没有向量值。当 tweet 中的单词在少于 min_count 的 tweet 中出现时,就会出现这种情况。由于 tweets 的语料库很小,在我们的案例中有发生这种情况的风险。因此,我们将 min_count 值设置为 1。

推文可以有不同数量的向量,这取决于它包含的字数。为了使用这个输出进行建模,我们将计算每条 tweet 的所有向量的平均值。因此,我们将拥有相同数量(即大小)的输入变量。

我们用函数compute_avg_w2v_vector来做这件事。在这个函数中,我们还检查 tweet 中的单词是否出现在 Word2Vec 模型的词汇表中。如果不是,则返回一个用 0.0 填充的列表。否则是单词向量的平均值。

def compute_avg_w2v_vector(w2v_dict, tweet):
    list_of_word_vectors = [w2v_dict[w] for w in tweet if w in w2v_dict.vocab.keys()]

    if len(list_of_word_vectors) == 0:
        result = [0.0]*SIZE
    else:
        result = np.sum(list_of_word_vectors, axis=0) / len(list_of_word_vectors)

    return resultX_train_w2v = X_train['clean_text_wordlist'].apply(lambda x: compute_avg_w2v_vector(model.wv, x))
X_test_w2v = X_test['clean_text_wordlist'].apply(lambda x: compute_avg_w2v_vector(model.wv, x))

这给了我们一个向量维数等于SIZE的序列。现在我们将分割这个向量并创建一个数据帧,每个向量值在单独的列中。这样,我们可以将 Word2Vec 变量连接到其他 TextCounts 变量。我们需要重用X_trainX_test的索引。否则,这将在以后的连接中产生问题(重复)。

X_train_w2v = pd.DataFrame(X_train_w2v.values.tolist(), index= X_train.index)
X_test_w2v = pd.DataFrame(X_test_w2v.values.tolist(), index= X_test.index)# Concatenate with the TextCounts variables
X_train_w2v = pd.concat([X_train_w2v, X_train.drop(['clean_text', 'clean_text_wordlist'], axis=1)], axis=1)
X_test_w2v = pd.concat([X_test_w2v, X_test.drop(['clean_text', 'clean_text_wordlist'], axis=1)], axis=1)

我们只考虑逻辑回归,因为我们在 Word2Vec 向量中有负值。多项式 lNB 假设变量具有多项式分布。因此它们不能包含负值。

best_logreg_w2v = grid_vect(logreg, parameters_logreg, X_train_w2v, X_test_w2v, is_w2v=True)
joblib.dump(best_logreg_w2v, '../output/best_logreg_w2v.pkl')

结论

  • 当使用计数矢量器的特性时,这两种分类器都能获得最佳结果
  • 逻辑回归优于多项式朴素贝叶斯分类器
  • 测试集上的最佳性能来自带有 CountVectorizer 特性的 LogisticRegression。

最佳参数:

  • c 值为 1
  • L2 正则化
  • max_df: 0.5 或最大文档频率 50%。
  • min_df: 1 或者这些词需要出现在至少两条推文中
  • ngram_range: (1,2),两个单词都作为二元语法使用

评估指标:

  • 测试准确率为 81.3%。这优于预测所有观察的多数类(这里是负面情绪)的基线性能。基线会给出 63%的准确度。
  • 这三个类别的精度都相当高。例如,在我们预测为负面的所有案例中,80%是负面的。
  • 中性类的召回率很低。在我们测试数据的所有中性案例中,我们只预测 48%是中性的。

对新推文应用最佳模型

为了好玩,我们将使用最佳模型,并将其应用于一些包含“@VirginAmerica”的新推文。我手动选择了 3 条负面和 3 条正面的推文。

多亏了 GridSearchCV,我们现在知道了什么是最好的超参数。因此,现在我们可以在所有训练数据上训练最佳模型,包括我们之前分离的测试数据。

textcountscols = ['count_capital_words','count_emojis','count_excl_quest_marks','count_hashtags'
,'count_mentions','count_urls','count_words']features = FeatureUnion([('textcounts', ColumnExtractor(cols=textcountscols))
, ('pipe', Pipeline([('cleantext', ColumnExtractor(cols='clean_text'))
, ('vect', CountVectorizer(max_df=0.5, min_df=1, ngram_range=(1,2)))]))]
, n_jobs=-1)pipeline = Pipeline([
('features', features)
, ('clf', LogisticRegression(C=1.0, penalty='l2'))
])best_model = pipeline.fit(df_model.drop('airline_sentiment', axis=1), df_model.airline_sentiment)# Applying on new positive tweets
new_positive_tweets = pd.Series(["Thank you @VirginAmerica for you amazing customer support team on Tuesday 11/28 at @EWRairport and returning my lost bag in less than 24h! #efficiencyiskey #virginamerica"
,"Love flying with you guys ask these years. Sad that this will be the last trip 😂 @VirginAmerica #LuxuryTravel"
,"Wow @VirginAmerica main cabin select is the way to fly!! This plane is nice and clean & I have tons of legroom! Wahoo! NYC bound! ✈️"])df_counts_pos = tc.transform(new_positive_tweets)
df_clean_pos = ct.transform(new_positive_tweets)
df_model_pos = df_counts_pos
df_model_pos['clean_text'] = df_clean_posbest_model.predict(df_model_pos).tolist()# Applying on new negative tweets
new_negative_tweets = pd.Series(["@VirginAmerica shocked my initially with the service, but then went on to shock me further with no response to what my complaint was. #unacceptable @Delta @richardbranson"
,"@VirginAmerica this morning I was forced to repack a suitcase w a medical device because it was barely overweight - wasn't even given an option to pay extra. My spouses suitcase then burst at the seam with the added device and had to be taped shut. Awful experience so far!"
,"Board airplane home. Computer issue. Get off plane, traverse airport to gate on opp side. Get on new plane hour later. Plane too heavy. 8 volunteers get off plane. Ohhh the adventure of travel ✈️ @VirginAmerica"])df_counts_neg = tc.transform(new_negative_tweets)
df_clean_neg = ct.transform(new_negative_tweets)
df_model_neg = df_counts_neg
df_model_neg['clean_text'] = df_clean_negbest_model.predict(df_model_neg).tolist()

该模型对所有推文进行了正确分类。应该使用更大的测试集来评估模型的性能。但是在这个小数据集上,它做了我们想要做的事情。

我希望你喜欢读这个故事。如果你做到了,请鼓掌。

情绪和影响者

原文:https://towardsdatascience.com/sentiment-influencers-1b43a9de0920?source=collection_archive---------22-----------------------

网络分析与情感分析相结合

几年前,我们开始了一场关于最大声的顾客是否真的像每个人——包括他们自己——认为的那样重要的辩论!客户服务部通常对最大声的抱怨者反应更快。这样方便吗?如何识别那些值得投入时间的抱怨者?

通过论坛帖子上的情绪分析,可以很容易地识别开心和不开心的用户。每个用户的影响程度也可以通过影响得分来衡量。有许多可用的影响分数。一个被广泛采用的是中心性指数。这个用例的想法是将情绪测量与影响分数相结合,并以这种方式识别那些具有高度影响的不满的客户/用户。然后,支持时间和资源应该重新分配给最有影响力和最不满意的客户或用户。

数据集

最初的用例指的是新产品的发布,旨在收集 beta 用户的意见。由于公司的隐私政策,不可能共享原始数据集,我们用一个公开的类似数据集来代替它:Slashdot 新闻论坛。

斜线圆点(有时缩写为“/”)是一个社会新闻网站,创办于 1997 年,面向科技。用户可以发布不同主题的新闻和故事,并接收其他用户的在线评论。

Slashdot 数据集收集了许多子论坛的帖子和评论,如科幻、Linux、天文学等。大多数用户使用他们的用户名发帖或评论,而一些用户匿名参与。最大的分论坛围绕政治展开,包含来自总共约 24,000 名用户的约 140,000 条评论和 496 篇文章。出于本使用案例的目的,我们重点关注“政治”分论坛。

Slashdot 数据集中的用户不完全是客户。然而,当谈论政治时,我们可以将政治话题视为产品,并像对待产品一样衡量用户的反应。

每个新帖子都被分配了一个唯一的线程 ID。标题、子域、用户、日期、主题和正文都引用这个线程 ID。为每个带有评论标题、用户、日期和正文的评论创建一个新的数据行,并附加来自种子帖子的主题 ID、帖子标题、帖子用户、帖子日期和帖子正文。在图 1 中,您可以在左边看到种子帖子数据,在右边看到相应评论的数据。请注意,多个评论可能会引用同一个种子帖子。

Figure 1. SlashDot Dataset. Data from seed post on the left; data from related comments on the right.

工作流程

在分析中,我们考虑了所有的非匿名用户。因此,第一步是删除用户名为“匿名”、为空、过长或没有文章 ID 的所有数据行。这发生在“预处理”元节点中。

Figure 2. The upper part of the final workflow, referred to as “Network creation and analysis,” calculates influence scores. The lower part, labeled “Text processing and sentiment analysis”, measures the sentiment of each forum user. This workflow is available on KNIME EXAMPLES Server under: 08_Other_Analytics_Types/04_Social_Media/02_NetworkAnalytics_meets_TextProcessing.

影响分数

我们希望通过调查用户之间的联系,找出谁是最有影响力的用户。因此,我们的目标是构建一个网络对象来表示用户交互。

第一步是准备边表作为网络的基础。边缘表有一个源列(文章的作者)和一个目标列(参考文章的作者)。边缘表是由图 2 所示的最终工作流的上部分支中的“Create edge table”元节点构建的。在这里,一个左外部连接将所有文章作者(源)和所有参考作者(目标)放在一起,如果有的话。GroupBy 节点统计从源到目标的每个连接的出现次数。过滤掉所有自动连接,即用户自己回答。

边缘表现在准备好被转换成一个网络对象。对象插入器节点将源用户和目标用户转换为节点,并通过一条边将它们连接起来,连接出现的次数作为值。

之后,名为“提取最大组件”的元节点将网络拆分为所有相连的组件。子网络然后基于它们的边和节点的总数被分类,并且只有最大的子网络被保留用于进一步的分析。最后,第二网络分析器节点计算中心和权威得分

网络分析器节点为社交媒体活动提供了一个很好的摘要。它在节点和边缘级别计算网络图上不同统计数据的数量。这种统计测量试图通过每个节点和边的连接数、它们的权重、它们的邻居、到它们邻居的距离以及类似的其他参数来建立每个节点和边的重要性。其中两个重要指标是中心和权威得分。

https://NLP . Stanford . edu/IR-book/html/html edition/hubs-and-authorities-1 . html中所述,hubs 和 authority 的概念植根于网页。有两种主要的网页作为广泛主题搜索的结果:

  • 关于这个话题的权威信息来源(当局)
  • 手工编制的链接列表,链接到关于该主题的权威网页。

中心本身并不是特定主题信息的权威来源,而是将您导向更权威的页面。中心/权威得分计算依赖于中心页面来发现权威页面。

为了计算中心和权限分数,网络分析器节点在 JUNG (Java 通用网络/图)框架中实现 HITS 算法

情感分析

现在我们想测量情绪,即根据积极和消极而不是权威来量化每个论坛用户。

图 2 中工作流的下部分支从每个论坛用户写的帖子或评论中提取文档列表。同时根据 MPQA 主观性词典从英语词典中导入两个词表:负面词和正面词。所有文档中的单词都被两个字典标记器节点标记为阳性或阴性,这取决于它们是否匹配这两个列表中的任何单词。未加标签的单词被认为是中性的。

每个正单词被赋予+1 值,每个负单词被赋予-1 值,每个中性单词被赋予 0 值。通过对每个用户写的所有文档的所有单词值求和,我们计算出用户情感得分。

请注意,这里使用绝对词频计算用户情感得分,而不考虑使用的字数。对于具有较长文档的语料库,即具有更大的字数差异的语料库,相对频率可能更合适。

最后,情绪得分在(平均值+标准差)以上的论坛用户被认为是积极的;情绪得分低于(平均值—标准差)的论坛用户被认为是负面的;介于两者之间的所有其他用户都被认为是中立的。积极用户用绿色表示,消极用户用红色表示,中性用户用灰色表示。

把所有的放在一起

将所有这些放在一起,一个 Joiner 节点将 authority 和 hub 分数与作者的情感分数连接起来。

一个散点图(Javascript)节点位于包装的元节点“散点图上的分数和情绪”内,它通过 y 轴上的中心分数、x 轴上的权威分数以及作为颜色的情绪分数来绘制论坛用户。

请注意,用红色表示的最大声的抱怨者实际上没有什么权威,因此不能被认为是有影响力的人。因此,这个情节似乎违背了你应该倾听和纵容最具攻击性的抱怨者的普遍信念。还要注意,最权威的用户实际上是中立的。这种中立性很可能是其他用户信任他们的原因之一。

散点图(Javascript)节点生成的散点图视图是交互式的。通过单击视图顶部的“选择模式”按钮,可以通过单击选择散点图上的单个点,或者通过在点周围画一个矩形来选择一组点。

Figure 3. Authors as points on a scatter plot with authority score on the x-axis and hub score on the y-axis. Authors with a positive sentiment score, i.e. sentiment score > (average + std dev), are color coded green. Authors with a negative sentiment score, i.e. sentiment score < (average — std dev), are color coded red. Authors with sentiment score in between are labelled as neutral and depicted in gray. In the upper right corner, there are the buttons for zooming and selection. The circled button enables point/author selection. The bigger point in the plot is the point that has been selected by single-click.

最终的工作流如图 2 所示,位于 KNIME EXAMPLES 服务器上的:08 _ Other _ Analytics _ Types/04 _ Social _ Media/02 _ network Analytics _ meets _ text processing

那么,我们做得怎么样?

论坛中的帖子和联系可以通过将它们简化为数字来进行分析,比如情感指标或影响力得分。在这篇博文中,它们一方面通过文本处理被简化为情感分数,另一方面通过网络图分析被简化为权威/中心分数。

这两种表示都产生有价值的信息。然而,当试图隔离最积极和最权威的用户以获得奖励以及最消极和最权威的批评者以获得损害控制时,这两者的结合被证明是无价的帮助。

承认

这篇博客文章是与菲尔·温特斯基利安·泰尔托拜厄斯·科特合作的一个项目的总结。更多详细信息,请参见 KNIME 白皮书“从社交媒体数据中创建可用的客户情报:网络分析与文本挖掘的结合”

可分离卷积——用很小的精度换取巨大的计算增益

原文:https://towardsdatascience.com/separable-convolutions-trading-little-accuracy-for-huge-computational-gains-77650add059?source=collection_archive---------25-----------------------

通常在卷积中,我们使用 2D 或 3D 内核滤波器,我们希望每个滤波器通过分别在所有 2 维或 3 维中卷积来提取某种特征。特别是在 2D 的情况下,我们试图在初始层提取简单的特征,在后面的层提取更复杂的特征。然而,如果我们愿意,我们可以将一个 2D 核分解成两个 1D 核,如下所示。

Separability Example

现在,我们可以把这两个 1D 核一个接一个地应用在一个图像上,而不是应用原始的 2D 核。通过这样做,我们实际上减少了用于卷积的参数数量,现在可以训练的参数更少了。此外,我们使用这些可分离的内核过滤器的顺序通常并不重要。客观地说,一个 5x5 内核过滤器有 25 个参数,而两个内核,一个 1x5 内核和一个 5x1 内核只有 10 个参数。

当然,参数的减少意味着我们可能不得不在我们学习的特征的复杂性上妥协。但是,如果你看下面的图片,你可以看到两个 1D 内核可以很容易地学习简单的功能,一个 2D 内核试图学习。并且,如果你试着想象这两个 1D 内核(如下所示),你可以看到它们应该能够以相当的准确度学习任何接近复杂的特征。在该图中,我们在左侧可视化了 1D 核“horz[c]”和“vert[r]”的权重,而右侧的图像显示了一个接一个地应用两个 1D 核所获得的最终权重的 3d 图。

Visualizing Separable Filters

这些可分离的卷积层通常可以非常有效和毫不费力地学习图像中简单到接近复杂的特征。因此,从直觉上来说,与尝试捕获复杂得多的要素的最终图层相比,在尝试捕获简单要素的初始图层中更多地使用这些可分离图层是有意义的。

我们也可以把这看作是调整我们网络的一种方式,其中我们试图只保留网络中真正独立的参数。通过这种方式,我们可以利用在每一层学习到的强大特征集来提高模型的计算效率。此外,通过尝试卷积和学习每个维度中的特征,可分离卷积尝试学习每个维度中的更多抽象特征。在某种程度上,它更侧重于在独立的个体维度中找到好的特征,然后最终将它们组合在一起,以最少的参数提取复杂的特征。

深度方向卷积是可分卷积的特例。在深度方向卷积中,我们首先使用 2D 滤波器(具有第三维的大小= 1)在 X 和 Y 维度上进行空间卷积,然后使用 1×1 滤波器在 Z 维度上进行信道方向卷积。下图显示了深度方向卷积在异常网络中的应用。

Xception Network

你可以在标题为“可分卷积基础介绍”的文章中读到更多关于可分卷积的内容。如果你想要更多关于可分卷积的形式证明,你也可以参考这里的更多关于 2D 可分卷积的数学证明,并有例子支持。

将医学艺术与人工智能分开

原文:https://towardsdatascience.com/separating-the-art-of-medicine-from-artificial-intelligence-6582f86ea244?source=collection_archive---------2-----------------------

人工智能需要数据。理想情况下,数据应该是干净、可信的,最重要的是准确的。不幸的是,医学数据远非如此。事实上,医学数据有时远非干净,而是非常肮脏。

考虑一下简单的胸部 x 光片,这是一种很好的老式的胸部前后 x 光片。医学诊断军械库中历史最悠久的放射技术之一,在世界范围内被数十亿人使用。事实上,数量如此之多,以至于放射科医生很难跟上庞大的数量,有时忘记阅读其中的 23,000 份。哎呀。

当然,如此受欢迎、屡试不爽的医学测试应该为训练放射学人工智能提供大量数据吧?显然有足够多的数据来进行一次像样的尝试,而且这项技术是如此的标准化和健壮,以至于肯定它只是在呼唤自动化?

A random anonymised chest X-ray taken from the NIH dataset. Take a look, and make a note of what you think you can see… there’s a test later.

不幸的是,有一个小而不方便的问题——人类。

人类放射科医生在解读胸部 x 光片和/或同意他们可以看到的发现方面非常糟糕,以至于数字图像附带的“报告”通常要么完全错误,要么部分错误,要么遗漏了信息。这不是人类的错…他们已经尽力了!当您的工作是在大约 30 秒内将数千个黑白像素处理成几个词的自然语言文本时,信息丢失和出现错误是可以理解的。撰写放射学报告是数据压缩的一种极端形式—您将大约 2 兆字节的数据转换为几个字节,实际上是以巨大的压缩比执行有损压缩。这就像试图通过一个 16K 的调制解调器播放一部电影,让某人用莫尔斯电码拍出正在发生的事情。更不用说这一切的主观性了。

不信我说放射科医生不好?让我们看看文献…

Swingler 等人表明,放射科医生在临床怀疑患有结核病的儿童 x 线片上发现淋巴结病变的总体敏感性为 67%,特异性为 59%。(这意味着他们只有大约 2/3 的时间发现某些东西,即使他们知道有问题,但只有一半以上的时间正确地找到了淋巴结。)

Taghizadieh 等人表明,放射科医生发现胸腔积液的灵敏度为 67%,特异性为 78%(肺部周围的液体——在 x 光片上呈白色固体,你会认为很难错过……)。

奎克尔等人发现有五分之一的病例漏掉了肺癌,尽管回想起来病变是完全可见的!在将近一半的病例中,癌症在随后的 x 光检查中至少两次被遗漏*。*

令人欣慰的是,研究确实表明医学训练使人比一般学生或外行人略胜一筹…

萨提亚等人显示,35%的非放射科初级医生无法区分心力衰竭和肺炎,18%无法诊断正常的 CXR,17%无法发现 3 厘米的右心尖肿块,55%无法识别慢性肺气肿的特征。高级临床医生在所有类别中表现更好。

起初,这可能看起来相当惊人!你可能会期望现代医学比在最多 2/3 的时间里把事情做对要好一点。嗯,实际上比那更糟…

放射科医生不仅不擅长写准确的 x 光胸透报告,而且在同样的 x 光胸透下,他们会写完全不同的报告。观察者之间的一致程度如此之低,真是可笑——一项研究显示, kappa 值为 0.2 (0 是糟糕的,1 是完美的)。另一项研究只是放弃了,并得出结论说“在肺炎患者中,对胸部 x 光的解释,尤其是最小的细节,完全取决于读者。”我想,主观性就是主观性。

前几天,我上了 Twitter 进行了一个简单的(完全不科学的)实验来证明这一点。

我让放射科医生看一张胸部 x 光片(取自匿名的 NIH 数据集),并在推特上发布他们的报告作为回应。我提供了一个简短的捏造的病史,不针对任何特定的疾病(54 岁,不吸烟,两周气短,门诊病人),以免他们对任何发现产生偏见。

大家表现如何?以下是一些回复示例:

就个人而言,人们的表现符合预期。他们做了一些正确的和一些可能不正确的观察,一些建议进一步用 ct 成像。但是人们同意吗?没有两个建议是完全相同的。有些很接近,但没有两份报告提到完全相同的发现或得出完全相同的结论。报告的发现范围从感染、腺病、高血压、肺气肿、癌症到肺结核。

然而,出现了一个总体趋势。如果你浏览所有的回复,就会发现某些发现比其他发现更容易被发现,包括左心尖结节、过度膨胀的肺和难以分辨的左心边界。我不知道这个胸部 x 光片的正确“读数”是什么(我甚至自己也做了一次,并给其他人写了一份不同的报告),但我倾向于同意这三个主要发现。来自 NIH 数据集的标签是从原始报告中挖掘的“结节”和“肺炎”。可悲的是,没有后续的 CT 或进一步的临床信息,所以我们永远不会知道真相。

(顺便说一句,这个帖子有了不同的转变,来自其他行业的医生也加入进来,提供了他们自己相当幽默的观点。如果你想笑,我推荐你读一读!是的,放射科医生作为一个团队做得更好。唷!)

我发现令人着迷的是,通过简单地改变一些周围的元数据,报告是如何发生变化的。例如,如果我有一天抽 40 支烟的历史,那么这些报告会更关注肺气肿和肺癌,而不是可能的肺炎吗?如果我说病人是 24 岁而不是 54 岁呢?如果我说他们有α-1 抗胰蛋白酶缺乏症呢?如果这张胸透照片来自撒哈拉以南的非洲会怎样?那么肺结核会是最常见的报告发现吗?

对图像的解释受到各种外部因素的影响,包括患者的人口统计、历史和地理。对于更复杂的成像模式(如 MRI)或操作者依赖的模式(如超声),问题甚至更严重,其中观察者误差甚至更高。

为什么所有这些都很重要?如果胸透报告不太准确怎么办?图像还在,所以没有数据真正丢失,是吗?

当你开始使用书面报告来训练放射学人工智能学习如何解释图像时,问题很快变得明显。斯坦福大学的机器学习团队已经完全做到了这一点,使用了 108948 张从 NIH 免费获得的带标签的胸部 x 光片。他们自豪地宣布他们的结果为在发现肺炎方面胜过放射科医生。现在,我完全支持前沿研究,我认为正是因为这个原因,像这样的数据集被公布于众是很好的…但我们必须非常小心我们如何解释基于这些数据的任何算法的结果,因为,正如我已经表明的那样,这些数据是不干净的。(我不是唯一的一个——请阅读卢克·奥克登-雷纳博士的博客详细检查数据集。)

如果你给人工智能的数据质量和人类的一样低,怎么可能训练出比人类更好的人工智能呢?我觉得不是…

它归结为一个简单的事实——胸部 x 光报告从未打算用于开发放射学人工智能。它们只被认为是一种观点,一种解释,一种创造性的有教养的猜测。阅读胸透与其说是一门科学,不如说是一门艺术。胸透既不是最终的诊断测试,也不是第一次,它只是达到临床终点的一系列诊断步骤中的一部分。胸部 x 光片本身并不能代替地面真相。事实上,它唯一的真正目的是充当一种“分流”的形式——普遍的临床问题是“这里有什么我需要担心的吗?”。这就是 x 光胸透的价值所在——回答“我应该担心吗?”,而不是“诊断是什么?”。也许斯坦福大学的研究人员一直试图回答一个错误的问题…

如果我们要开发一种能够真正“阅读”胸部 x 光片的人工智能,那么未来的研究应该集中在三个方面:

  1. 周围的元数据和找到一个地面真相,而不是依赖于一个人衍生的报告,没有产生数据挖掘的想法。理想的数据集应该包括所有患者的详细信息、流行病学、病史、血液测试、后续 CT 结果、活检结果、遗传学等。可悲的是,这种级别的验证匿名数据并不存在,至少不是机器阅读所需的格式。因此,基础设施应该投入到整理和验证这些元数据中,最少,最好是大规模的。
  2. 数据集的细致标记。我的意思是,为了提供机器学习就绪的数据,使用经过专门培训的领域专家,煞费苦心地彻底注释图像。专家的一致意见,以及准确的元数据,将明显优于使用随机的单一读者报告。谢天谢地,这是一些更有声誉的放射学人工智能公司正在做的事情。是的,它既昂贵又费时,但如果要达到最终目标,这是必要的。这就是我称之为的数据提炼过程,具体来说就是从 B 级到 A 级的阶段。跳过这一步,你将永远无法击败人类的表现。
  3. 标准化放射学语言。我的简单 Twitter 实验得到的许多回复使用不同的语言来描述大致相似的事情。例如,“实变”在很大程度上可以和“肺炎”互换。或者是?我们如何定义这些术语,什么时候应该用一个来代替另一个?人类语言存在巨大的不确定性,这延伸到了放射性语言。(放射科医生在医学界以其实践不确定性的技能而闻名,被称为“对冲”)。除非这种不确定性被消除,并且每一个可能的用例的术语都被认可,否则很难看到我们如何能走向数字天堂。正在努力引入一种标准化的语言( RadLex ),然而执业放射科医生的接受速度很慢,而且相当零散。我不知道这个问题的答案是什么,但我知道问题是语言!

在我们完成所有这些之前,人工智能在胸部放射摄影中唯一真正有用的价值充其量是提供分类支持——告诉我们什么是正常的,什么是不正常的,并强调哪里可能不正常。只是不要试图声称人工智能可以明确地告诉我们异常是什么,因为它不能比我们做得更准确,因为数据是脏的,因为我们这样做了。

现在,让我们把模糊的思维和创造性的解释留给我们人类,把医学的“艺术”从“人工智能”中分离出来,并开始专注于产生大量干净的数据。

如果你和我一样对人工智能在放射学和医学成像领域的未来感到兴奋,并想讨论这些想法,请联系我们。我在推特@drhughharvey

如果你喜欢这篇文章,点击推荐并分享它会很有帮助。

关于作者:

哈维博士是一名委员会认证的放射科医生和临床学者,在英国国民医疗服务体系和欧洲领先的癌症研究机构 ICR 接受过培训,在那里他两次获得年度科学作家奖。他曾在 Babylon Health 工作,领导监管事务团队,在人工智能支持的分诊服务中获得了世界第一的 CE 标记,现在是顾问放射科医生,皇家放射学家学会信息学委员会成员,以及人工智能初创公司的顾问,包括 Kheiron Medical。

区分牛排和咝咝声——在人工智能/人工智能领域,什么是“真实”的,什么是炒作

原文:https://towardsdatascience.com/separating-the-steak-from-the-sizzle-whats-real-and-what-s-hype-in-ai-ml-edd4acd0d287?source=collection_archive---------12-----------------------

人工智能(AI)和机器学习(ML)的世界近年来蓬勃发展,为寻求改善消费者体验的公司拓展了商业解决方案。随着深度神经网络和情感识别的进步,行业正在改善我们交流、创建内容和分析数据的方式。WorkFusion 已经在行业中取得了长足的进步,提高了人工智能在商业世界中的极限

然而,人工智能和人工智能的其他领域最近受到了大量的炒作,尽管它们仍处于早期阶段。虽然使用生成性对抗网络(GAN)改善网络安全的前景已经显示出一些希望,但该技术仍需数年才能开花结果。

这里有两个人工智能领域被夸大了,还有两个领域是真正的问题。

1)甘在信息安全

信息安全专家一直在探索 GAN 如何提高我们的在线安全,并取得了一些令人鼓舞的成果。新泽西斯蒂文斯理工学院和纽约理工学院的研究人员已经开发出使用 GANs 猜测密码的方法。

该小组开发了一个实验,通过其名为“PassGan”的密码猜测技术来查看泄露密码的数据,并发现该软件能够从这些帐户中猜出 47%的密码,这一比例高于 HashCat 和 John the Ripper 等竞争算法。这一发现是 GANs 的核心,GANs 本质上是一种神经网络,可以模拟任何数据分布,并提供与数据对应的输出。

来自纽约理工学院的 Paolo Gasti 将这项技术比作素描艺术家和试图揭开嫌疑人身份的目击者。从本质上来说,GANs 可以通过目击者的反馈不断完善嫌疑人的形象,理论上输出一个几乎相同的嫌疑人形象。

然而,康奈尔大学的一项研究发现,这些“机器人艺术家”仍然需要大量的微调,才能在图像、音乐、语音和散文的开发和分析中得到更广泛的应用。该小组发现,在开发这些算法的过程中缺乏系统和客观的评估指标,需要做更多的工作,以便以可承受的价格提供一致的数据输出。

2。更好地理解自然语言的细微差别

谈到自动语音系统和其他接受语音命令的计算机程序时,这些软件的设计仍然存在一个缺陷,使得这些算法很难准确理解这个人在说什么。尽管如此,开发人员已经在这一领域取得了一些进展,深度学习神经网络可以更准确地区分不同的语音和口音。

在未来的一年里,更多的企业将扩展他们的客户服务聊天机器人和其他理解自然语言命令的商业应用程序。这些机器人在理解人类语言方面也变得更加细致入微,并以更加连贯和全面的方式回应他们的查询,减少了消费者与这些机器人互动的时间和精力。

这一举措进一步代表了机器人流程自动化(RPA)在人工智能中的越来越多的使用及其推动行业前进的能力,正如 WorkFusion 必须提供的服务的情况一样。

3。药物发现中的人工智能

阿斯利康的研究人员写了一篇论文,讨论了通过使用递归神经网络和强化学习,使用人工智能来生成新分子。虽然该论文通过使用直方图、小提琴图和 t-SNE 图包含了数量惊人的可视化数据,但在其报告中有一个明显的遗漏。

该公司的所有测量都是通过比较人工智能生成的分子和自然分子来进行的,但他们未能测量人工智能生成的分子之间的距离。哈佛大学的一项研究也存在同样的缺乏辨别能力的问题,因为人工智能生成的分子并不相互比较。

这一遗漏意味着 AI 在生成新颖分子方面的作用还有很长的路要走。

4。解决精神健康问题的聊天机器人

虽然这个想法看起来有些牵强,但你可能很快就会有一个机器人顾问。人工智能在开发聊天机器人方面取得了一些进展,这些机器人可以识别一个人何时变得激动、沮丧或愤怒,并做出相应的调整。这项技术可以帮助提高客户服务能力和其他商业解决方案。

它还可能对改变精神健康治疗有很大帮助,因为这些顾问机器人不会有情绪偏见,同时还能回忆起你与他们互动的每个细节。一个名为 Karim 的心理治疗聊天机器人已经开始发挥作用,治疗患有 PTSD 和其他疾病的患者。这项技术也降低了精神健康治疗的成本。

底线…

人工智能和人工智能技术在过去几年里取得了长足的进步,将传统的商业实践转变为能够简化工作流程、提高公司投资回报率和节省管理费用的先进解决方案。尽管像信息安全(infosec)的甘(GAN)这样的技术已经显示出作为机器人艺术家的前景,但它们仍有很长的路要走。

在药物发现中使用人工智能是同一条船上的,产生了一些令人鼓舞的结果,但距离在医疗保健行业广泛采用还有几年时间。与此同时,聊天机器人和语音助手在区分语音命令的声音细微差别方面变得越来越有能力,同时还可以为客户和精神健康患者提供虚拟援助。

这是一个激动人心的时刻,因为这个行业正在不断重新定义我们的工作方式、沟通方式以及为各种规模的公司开发智能商业解决方案。

丝芙兰和数据科学—第二部分

原文:https://towardsdatascience.com/sephora-and-data-science-part-2-70540c89a602?source=collection_archive---------18-----------------------

继续我之前关于 Sephora.com 产品和客户可视化的博文,在这篇博文中,我将分享我的项目中的一些实验和结果。如果你喜欢在早期的博客上阅读更多内容,它突出了我为这个项目所做的可视化,其中包括各种客户概况的箱线图,以及产品的价格和评级分布。

[## 丝芙兰的数据可视化

对于我在熨斗学校的顶点项目,我决定把我对美丽世界的迷恋和…

medium.com](https://medium.com/datadriveninvestor/data-visualization-of-sephora-b2cc91b19b35)

对于我的项目的机器学习部分,我想知道如果给定一些关于产品的特征,如客户资料或产品信息,是否会有可以从电子零售商的数千个数据点中辨别出的模式。我的第一个目标是预测评论者对某个产品的推荐百分比的回归,我的第二个目标是找出某个产品是高于还是低于平均评级的分类。

起初,我想看看价格本身是否会成为决定一个产品将获得多少推荐的重要因素。直觉来自一个简单的相关矩阵,它表明价格对产品的推荐数量有轻微的负面影响。

feature correlation matrix

然而,价格本身并不构成一个强大的功能。一个简单的价格回归产生的预测比随机猜测更糟糕。加入了额外的特征,如用户资料信息和价格,该模型成为预测推荐计数的更有效的模型。使用梯度推进回归器,该模型能够对推荐产品的用户百分比做出相对准确的预测。这些模型的特征是客户概要信息,而这个模型最强的特征是价格。

决定推荐百分比回归的最强特征是价格,然而,用户简档特征,如黑发头发评论者的数量,也对回归预测有很大影响。与随机猜测相比,训练和测试分数的均方误差也表现得非常有效。随机猜测预测正确的基线为 2.6%,然而,模型预测作为测试分数校正了 55.35%。

梯度推进是另一种集成方法。该算法利用弱预测器的集成,也称为简单决策树,以类似于其他 boosting 集成方法的分阶段方式,并通过允许优化任意可微分损失函数来概括它们。简单来说,它以迭代的方式将一群弱学习者或树组合成一个强学习者。迭代阶段的目标是最小化均方误差。因此,在学习的每个阶段,模型都会从早期阶段的错误中学习,并变得越来越适合所提供的样本。像许多集成方法一样,该算法也可能过拟合,但是,因为它依靠弱学习器来优化预测,所以它能够最小化对所提供的特定样本的过拟合。

你可以在我的 Github 上阅读更多关于我的项目和代码的信息。我的下一篇博客将会更深入地介绍我的项目的分类部分,在这个部分中,我使用了产品描述和成分的文本来预测一个产品的评级性能是高于平均水平,还是低于平均水平。

伯克利 RISECamp:大规模部署深度分布式人工智能

原文:https://towardsdatascience.com/september-7-and-8-2017-marked-the-first-ever-risecamp-at-uc-berkeley-499df29267af?source=collection_archive---------5-----------------------

2017 年 9 月 7 日和 8 日标志着加州大学伯克利分校有史以来第一次 RISECamp。RISECamp 是一个为期两天的训练营,重点是分享来自 RISELab 的工作。缩写 RISE 在实验室的网站上有解释 :
安全执行的实时智能

RISELab 和著名的 amp lab(Apache Spark 的诞生地)之间的一个巨大差异是,重点从批处理转移到大规模实时决策。这种转变标志着学术界和工业界如何接近最先进的机器学习系统的趋势。虽然批处理适用于各种各样的问题,但实时决策系统能够在新的观察结果流入系统时进行即时学习。这些类型的系统也向真正的人工智能系统迈进了一步,而不是应用根据新观察结果离线训练的模型。

除了专注于构建能够做出实时决策的系统(利用强化学习),该营地还解决了许多试图大规模集成高级人工智能系统的组织所面临的其他挑战。这些挑战包括跨机器集群轻松分发代码、管理数据沿袭和治理、提供大规模预测,以及在构建依赖于敏感数据的高级系统时所需的固有安全性。

营地分为五个主要部分,分别应对这些挑战。在这篇文章中,我将总结这些章节的内容,并解释在夏令营期间在 RISELab 中构建的工具。

涵盖的主题

1.强化学习
2。预测发球:按比例计分
3。易开发性:让 ML 对非 CS 来说变得容易
4。在上下文中使用数据
5。安全:物联网授权——安全

RISECamp 堆栈

如果你做过任何类型的机器学习工作,那么这些话题应该会引起你的共鸣。来自学术界和工业界的一些最大的开源项目正在解决这些问题。虽然许多现有技术试图解决这些问题,但 RISELab 开发了一系列技术,可以一起使用来创建部署人工智能系统的端到端解决方案。

RISECamp 堆栈:

  • Ray :用现有代码扩展 RL 和 ML 算法进行分发
  • 削波器:预测发球;支持多种框架。水平可伸缩。实时决策的在线评分。
  • PyWren :无服务器架构;python api 无需管理集群
  • 地面:数据上下文服务
  • 浪潮:使用区块链的去中心化授权,聚焦物联网设备

强化学习

在更详细地讨论这些组件之前,我将提供一个关于强化学习的简短背景,以及它与更多监督和非监督学习方法的比较。

监督学习

这可以说是最流行的机器学习形式,因此它提供了一个很好的比较基础。监督学习用于解决现有数据中已知一些基本事实的问题。用于这类问题的数据将具有某种可被识别为“目标”的属性。对于一个老生常谈的经典例子,为了让监督学习系统预测贷款申请人是否应该获得贷款,历史数据需要一个字段来指示借款人是否偿还了贷款或违约。我们可以将此转化为一个二元分类问题,根据历史数据和“目标”标签,我们预测新的申请人是否会偿还贷款或违约。监督学习通常分为两大类——“分类”和“回归”。分类是当预测的目标是离散值(如偿还贷款或违约)时使用的术语。另一方面,回归问题试图预测一个连续值的目标(例如,预测房屋的价格)。

无监督学习

与监督学习相比,非监督学习没有基础事实。这意味着对于所有的历史数据,没有与手头问题相关的可用标签。无监督学习的一个主要例子是一种叫做聚类的技术。聚类的工作原理是获取数据并将数据分组/聚类/分段成组,这些组通过适合数据集的聚类算法计算为相似的组。这方面的一个具体例子是获取企业客户的所有历史数据,并根据他们行为的某些方面将他们分组。

强化学习

虽然强化学习(RL)是机器学习中一种独特的第三种方法,但它更接近于有监督的学习,而不是无监督的学习。尽管可能相似,但 RL 侧重于顺序决策,不像传统的监督学习那样针对单个时间点做出决策。一个常见的 RL 应用是机器人,其中代理与其环境进行交互,并需要实时做出决策。许多用于重复任务(例如在制造过程中)的机器人不需要强化学习,因为它们可以被显式编程来处理它们的任务,因为它们工作的环境极其有限。当机器人(在 RL 术语中:agent)具有变化的环境或需要在没有明确编程的情况下对任务做出决策时,强化学习在机器人学中大放异彩。为了将这种类型的用例更正式地构建为强化学习问题,我们需要定义一些核心概念。

  • 代理人:要么是一个模拟的演员,比如电子游戏中的对手,要么是一个物理设备,比如机器人或自动驾驶汽车
  • 状态:对代理在任意时间点所处环境的描述。这种描述取决于系统中提供给代理的输入。
  • 动作:在评估状态后,动作就是代理决定要做的事情。基于代理能够控制的内容来定义操作的范围。在自动驾驶汽车的例子中,这可以是加速度的量和车轮应该转动的程度
  • 奖励:RL 问题的这个组成部分是它与监督学习更紧密联系的部分。然后,根据代理采取的行动将奖励输入系统。回到自动驾驶汽车,奖励可以基于安全、平稳驾驶,或者在合理的时间内到达目的地(我们希望三者都达到)。
  • 环境:这是代理运行的世界。对于视频游戏中的模拟代理,这由游戏中强加的约束组成,这些约束规定哪些动作是可能的。在自动驾驶汽车的例子中,这是真实的世界,其中环境是汽车将要行驶的街道。

RL in action

有人可能会说,既然奖励是已知的,我们就有了基础事实,强化学习问题可以用监督学习技术来处理。虽然监督学习可以取得一些成功,但它在用新的训练数据实时更新模型方面存在不足。

持续学习是机器学习的另一个子集,它在观察值被错误分类时更新模型;它会随着时间的推移更新模型以提高性能。持续学习在决策方面也有不足之处,因为有时在做出许多其他决策之前,一个分数不能被理解为成功或失败。这方面的一个例子是一个代理人在玩国际象棋(或围棋)游戏,在知道最终标签(比赛的输赢)之前必须做出许多决定。解决符合这一模型的问题的最佳方法是强化学习,因为它调整所有决策的概率,而不是单个决策的概率。

光线

Ray 使得在一个机器集群上分发 Python 函数变得非常容易。这是通过使用 Ray Python 包来修饰函数或类,允许它们使用非常简单的语法并行执行来实现的。

来自 Ray 教程的一个例子展示了如何将一个现有的 Python 函数转换成一个在集群上并行运行的函数:

 # A regular Python function.def regular_function():
 return 1# A Ray remote function.
[@ray](http://twitter.com/ray).remote
def remote_function():
 return 1 

“remote_function()”前的“ @ray .remote”装饰符使其能够以允许并行处理的特殊方式被调用。调用此函数以并行方式运行使用以下语法:

 for _ in range(4):
 remote_function.remote()

就是这样!通过在函数名后调用`. remote()',函数将由范围(或列表)中的每一项并行执行,而不是顺序执行。这是一个没有参数的非常简单的函数,但是如果需要任何参数,它们会在“remote()”中传递,就像在不使用 Ray 的情况下调用“remote_function()”一样。

这涵盖了如何在集群中的核心或节点之间分配函数,使用 Ray 也可以很容易地从这个函数中获得返回值。以下代码片段也来自 Ray 教程,显示了传统函数返回和 Ray 远程函数返回的比较:

 >>> regular_function()
1>>> remote_function.remote()
ObjectID(1c80d6937802cd7786ad25e50caf2f023c95e350)>>> ray.get(remote_function.remote())
1 

这个简单的例子展示了一个远程函数返回一个对象(Python 的未来)。为了将其转换为实际值,对返回的对象使用简单的“ray.get()”调用来获得实际值。

这只是触及了 Ray 提供的东西的表面;但是它应该会引发一些关于这个库可以处理的潜在用例的想法。在 RISECamp 的上下文中,Ray 被用作工具,以并行方式处理任意数量的代理上的模拟强化学习策略,以加速模拟。许多其他用例,如超参数优化,也可以很容易地从使用像 Ray 这样的分布式处理系统中受益。

快速帆船

所以你用 Ray 模拟了一个给定 RL 问题的很多策略,找到了最优策略;现在怎么办?这是机器学习的一个古老问题,其中模型是由数据科学家建立的,需要找到一种进入生产环境的方法,以便为系统/应用程序/组织带来真正的价值。这是一个即使是先进的数据科学团队也会因为许多原因而陷入困境的领域。Clipper 提供了一个部署模型的框架,该框架由任何流行的开源机器学习库创建,可以以低延迟提供预测。查看 Clipper 的资源库,获取快速入门指南。

Clipper 的发展有点早,但是它有一个非常强大的方法来应对模型服务的挑战。IBM 开发了一款名为沃森机器学习的产品来应对这一挑战。Watson Machine Learning 提供了一个统一的界面,可以通过代码或 UI 驱动该界面来部署来自多个框架(SPSS、SparkML、Scikit-Learn 等)的模型。).通过使用单一工具来部署任何类型的模型,数据科学家可以灵活地使用他们想要的任何机器学习库,应用程序开发人员可以轻松地选择这些模型,以便轻松地嵌入到系统和应用程序中,进行实时决策。

鹩哥

就像我们在 Ray 中看到的那样,有许多用例,数据科学家需要将他们的过程分布在许多机器上。PyWren 是来自 RISELab 的另一个 Python 包,它专注于这个问题,考虑了不同的方法和目标。与 Ray 不同的是,PyWren 选择了无服务器架构,将 Python 函数推送到 AWS Lambda 上执行。PyWren 提供了一个用于 Lambda 的通用容器,它拥有最流行的数据科学 Python 库,无需额外定制。与 Ray 类似,PyWren 以一种非常简洁的方式实现了这一点,可以很容易地集成到现有的 Python 代码库中。

要查看它的运行情况,请看来自 PyWren 教程的代码片段:

 import pywrendef square(param):
 return param * paramparam_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]pwex = pywren.default_executor()
futures = pwex.map(square, param_list)
results_with_pywren_map = [f.result() for f in futures]

如果您在 Python 中使用过' map()',那么这个语法应该非常熟悉。传统“映射”和鹪鹩“映射”的区别在于,鹪鹩将函数映射到任意数量的 Lambdas 上。这为可以并行运行的分布式操作提供了一个经济高效且可水平扩展的解决方案。

因为这个代码示例很简单,所以我将更详细地介绍一个具体的用例。如今,许多数据团队利用云对象存储或亚马逊 S3 等块存储来存储数据集。团队可以将这些对象存储服务用于不同的目的,但是一个常见的模式是将容器/桶视为一个接收器,新的数据集作为一些数据管道的一部分写入其中。随着这些文件数量的增加,对每个文件应用一个函数可能是一个缓慢的过程。特别是如果使用类似循环的东西来迭代所有文件,从而线性地应用该函数。PyWren 通过利用 AWS Lambda 将函数清晰地映射到给定容器/桶中的所有文件,在这个用例中大放异彩。PyWren 使用非常简单的语法触发 Lambda 为每个文件应用普通的 python 函数。

地面

到目前为止,我已经介绍了机器学习的许多方面,但是还没有描述如何处理最核心的部分:数据。这就是在 RISELab 中发挥作用的地方。背景的介绍性解释提供了数据背景的基础知识:

地面数据上下文基础知识

-[A]应用上下文:描述如何解释原始位以供使用。
-【B】行为背景:关于真实的人或系统如何创建和使用数据的信息。
-【C】change Over Time:另外两种形式的数据上下文的版本历史。

通过考虑对数据管理很重要的不同上下文,Ground 提供了管理大型数据目录所需的完整视图。

波浪

最后但同样重要的是,RISELab 堆栈的组件解决了处理物联网设备的安全性和授权的挑战:Wave。

Wave 是最超出我专业范围的组件,但也是我认为最令人印象深刻的组件。我假设有相关性:-)。Wave 提供了一种新的方法,为基于名称空间、公钥和区块链的设备控制提供授权。如果你没有从这个博客中获得任何其他东西,请接受这个时髦的总结:我们正在使用云来训练区块链授权的深度强化学习人工智能系统。从 RISECamp 这里看一下波练习

总之,RISECamp 是一次令人惊叹的经历,与会者很幸运地看到了来自加州大学伯克利分校的下一代开源项目。RISELab 能够以模块化和互补的方式针对机器学习工程师面临的一些最常见的挑战,这给我留下了非常深刻的印象。我非常期待跟踪这里描述的每个项目,我鼓励你也这样做。

九月版:图像识别

原文:https://towardsdatascience.com/september-edition-image-recognition-529886b1b579?source=collection_archive---------7-----------------------

8 篇必读文章

Google tensor flow 物体检测 API 是实现图像识别最简单的方法吗?

Priya Dwivedi — 4 分钟阅读。

有许多不同的方法来进行图像识别。谷歌最近发布了一个新的 Tensorflow 对象检测 API,以推动计算机视觉无处不在。

如何用 TensorFlow 的物体检测器 API 训练自己的物体检测器

通过 Dat Tran — 8 分钟读取。

这是关于“用 Tensorflow 和 OpenCV 构建实时物体识别应用”的后续帖子,在这里我重点训练自己的类。具体来说,我在自己收集和标记的数据集上训练了自己的浣熊检测器。完整数据集可在 my Github repo 上获得。

使用 Keras 和直方图均衡化进行深度学习的图像增强

Ryan Allred — 12 分钟读取。

在这篇文章中,我们将回顾:图像增强:它是什么?为什么重要?Keras:如何使用它进行基本的图像增强。直方图均衡化:它是什么?怎么有用?实现直方图均衡化技术:修改 keras .预处理 image.py 文件的一种方法。

基于初始网的多标签图像分类

由 Radek Bartyzal — 6 分钟阅读。

Inception v3 是一个深度卷积神经网络,在 ImageNet 数据集上训练用于单标签图像分类。TensorFlow 团队已经准备了一个关于重新训练它的教程,根据我们自己的例子来区分一些类。

我从 Udacity 自动驾驶汽车纳米学位项目的第一学期中学到了什么。

Hadi N. Abu-Snineh — 12 分钟阅读。

我叫哈迪·阿布·斯内赫,来自约旦安曼。我曾在德国约旦大学学习机电一体化工程。我决定接受挑战,参加 Udacity 自动驾驶汽车项目。

智慧城市和图像识别

乔·汉森 — 6 分钟阅读。

图像识别和机器视觉对地方政府具有现实意义,可以帮助官员有效地整合和管理资产

电报机器人、我的早餐、水果和互动对话上的张量流对象检测

Nicolas Bortolotti——3 分钟阅读。

在本文中,我们将探索一个案例,其中我们使用张量流(对象检测 API)将图像中的对象检测与通过 bot 架构(电报平台)的交互相结合。

深度学习中不同类型卷积的介绍

由保罗-路易·普罗夫 — 6 分钟阅读。

让我给你一个快速概述不同类型的卷积和他们的好处。为了简单起见,我只关注 2D 卷积。

We need your support.

走向数据科学是一份独立的出版物。为了保持我们的开放和编辑自由,我们要求我们的支持者承诺一小笔捐款来帮助我们竞选。非常感谢!

我们也感谢最近加入我们的所有伟大的新作家南希·汉斯莱普拉萨德·阿金克亚卡森·福特达里亚·瓦亚达苏普里亚·尼甘古平雄钟弘成科林·麦克格鲁沙恩·巴克 马克斯·弗罗洛夫费德里卡·佩泽尔玉峰艾哈迈德·沙姆苏尔·阿雷芬达塔特马特·拉实验室帕拉德普·雷迪·拉马纳贾纳丹·谢蒂尼克·怀特阿伊奎斯特·罗德里格斯

九月版:机器学习案例研究

原文:https://towardsdatascience.com/september-edition-machine-learning-case-studies-a3a61dc94f23?source=collection_archive---------3-----------------------

人工智能、机器学习和深度学习的整个格局在过去五年里发生了快速变化。机器学习不再局限于实验室实验或研究论文,而是在不同领域的主流行业采用方面迅速加快了步伐。我们也开始在日常生活中看到甚至使用智能系统。其中包括 Google Now、Alexa、Siri 和 Cortana 等智能助手、自动驾驶汽车、专业游戏代理、聊天机器人、edge analytics 等等。我们人类也逐渐开始在日常生活中接受这样的智能系统和技术,不管围绕人工智能与人类的所有宣传。

人工智能是为了帮助我们自动化和解决复杂且经常重复的任务,帮助我们提高生产力和利润。因此,随着我们步入学习机器、数字化和自动化的新时代,不仅要理解统计建模和机器学习的理论概念,还要理解如何有效地应用这些工具来解决现实世界的问题,这一点非常重要。

“人工智能是新的电力……我们有足够的纸。停止出版,开始用科技改变人们的生活”——吴恩达

因此,现在是时候启动 【应用】 机器学习来解决不同行业领域复杂和简单的现实世界问题,包括金融、零售、科技、医疗保健、物流、运输甚至政府。了解如何应用和使用机器学习的最佳方式是查看业内机器学习案例研究的成熟策略和最佳实践。这个版本为您带来了一些应用机器学习解决各种有趣问题的最佳案例研究。我们希望你能从他们身上学到东西,走出去,做一些令人惊讶的事情!

Dipanjan (DJ) Sarkar ,数据科学家,作者& TDS 编辑

机器学习方法——构建酒店推荐引擎

苏珊李 — 5 分钟读完

所有在线旅行社都在争先恐后地满足亚马逊和网飞设定的人工智能驱动的个性化标准。此外,在线旅游世界已经成为一个竞争激烈的空间,品牌试图通过推荐、比较、匹配和分享来吸引我们的注意力(和钱包)。

Spotify 的“这是”播放列表:50 位主流艺术家的终极歌曲分析

詹姆斯·勒 — 15 分钟读完

每个艺术家都有自己独特的音乐风格。从献身于木吉他的艾德·希兰,到精通说唱艺术的德雷克。从能在流行歌曲中唱一些疯狂高音的阿黛尔,到在 DJ 台上创造 EDM 魔术的 Kygo。

通过无监督学习检验国际美食

通过本斯特姆 — 8 分钟读取

像很多人一样,我也是一个美食迷。我非常幸运,在一个吃饭都是从零开始的家庭长大。我妈妈做饭,因为她从德国移民到美国,我接触了很多美味的德国菜肴。

如何使用序列对序列模型创建神奇的数据产品

通过哈默尔侯赛因 — 17 分钟阅读

我从未想过我会用“神奇”这个词来描述机器学习技术的输出。当我被引入深度学习时,这种情况发生了变化,在深度学习中,你可以完成像识别图片中的物体分类两吨重的乐高玩具这样的事情。

销售员的进化:Python 的完整遗传算法教程

艾瑞克·斯托罗兹 — 8 分钟读出

从自然选择中汲取灵感,遗传算法(GA)是一种解决搜索和优化问题的迷人方法。虽然已经有很多关于遗传算法的文章(见这里的和这里的),但很少有人展示用 Python 一步一步实现更复杂问题的遗传算法。

使用 Python 进行时间序列分析和预测的端到端项目

苏珊李 — 9 分钟读完

时间序列分析包括分析时间序列数据的方法,以便提取有意义的统计数据和数据的其他特征。时间序列预测是使用模型根据以前观察到的值来预测未来值。

利用机器学习模拟世界杯比赛

通过罗德里戈·纳德 — 11 分钟阅读

世界杯正在进入一个新的阶段,很少有人能够预测小组赛的结果。现在是时候进入一个更加激动人心的阶段了,世界上最伟大的人将会面对面。本文的目标是,通过 Python 使用数据科学的力量,尝试揭示这些游戏将呈现的一些统计数据。

客户细分的聚类算法

Sowmya Vivek

在当今竞争激烈的世界中,了解客户行为并根据其人口统计和购买行为对客户进行分类至关重要。这是客户细分的一个重要方面,它允许营销人员在促销、营销和产品开发策略方面更好地针对各种受众群调整营销工作。

张量流中的 Seq2Seq 模型

原文:https://towardsdatascience.com/seq2seq-model-in-tensorflow-ec0c557e560f?source=collection_archive---------1-----------------------

Photo by Marcus dePaula on Unsplash

在这个项目中,我将在 TensorFlow 中建立一个名为**seq2seq model or encoder-decoder model**的语言翻译模型。该模型的目标是将英语句子翻译成法语句子。我将展示详细的步骤,他们将回答像how to define encoder modelhow to define decoder modelhow to build the entire seq2seq modelhow to calculate the loss and clip gradients这样的问题。

请访问 Github repo 了解 Jupyter 笔记本中更详细的信息和实际代码。它将涵盖更多的主题,如how to preprocess the datasethow to define inputshow to train and get prediction

这是 Udacity 深度学习纳米学位的一部分。一些代码/功能(保存、加载、测量精度等)由 Udacity 提供。然而,大部分是我自己实现的,每一节都有更丰富的解释和参考。此外,基础数字(关于模型)借用自 Luong (2016)

构建 Seq2Seq 模型的步骤

您可以将整个模型分成两个小的子模型。第一个子模型称为**【E】编码器 ,第二个子模型称为【D】解码器 。就像任何其他 RNN 架构一样,接受原始输入文本数据。最后,【E】输出一个神经表示。这是一个非常典型的工作,但是你需要注意这个输出到底是什么。【E】的输出将成为【D】**的输入数据。

这就是为什么我们称**【E】编码器,称【D】解码器【E】做出一个以神经表征形式编码的输出,我们不知道它到底是什么。它被加密了。【D】具有查看【E】**输出内部的能力,它将创建一个完全不同的输出数据(在本例中翻译成法语)。

为了建立这样一个模型,总共有 6 个步骤。我注意到要实现的功能与每个步骤相关。

(1)定义编码器模型的输入参数

  • enc_dec_model_inputs

(2)建立编码器模型

  • encoding_layer

(3)定义解码器模型的输入参数

  • enc_dec_model_inputsprocess_decoder_inputdecoding_layer

(4)为训练建立解码器模型

  • decoding_layer_train

(5)建立用于推理的解码器模型

  • decoding_layer_infer

(6)将(4)和(5)放在一起

  • decoding_layer

(7)连接编码器和解码器型号

  • seq2seq_model

(8)定义损失函数、优化器,并应用梯度剪切

Fig 1. Neural Machine Translation / Training Phase

编码器输入(1)、(3)

enc_dec_model_inputs函数创建并返回与建筑模型相关的参数(TF 占位符)。

输入占位符将输入英文句子数据,其形状为[None, None]。第一个None表示批量大小,批量大小未知,因为用户可以设置。第二个None表示句子的长度。setence 的最大长度因批次而异,因此无法用确切的数字进行设置。

  • 一种选择是将每批中所有句子的长度设置为最大长度。无论您选择哪种方法,您都需要在空位置添加特殊字符<PAD>。然而,对于后一种选择,可能会有不必要的更多<PAD>字符。

targets 占位符类似于 inputs 占位符,只是它将输入法语句子数据。

target_sequence_length 占位符表示每个句子的长度,所以形状是None,一个列张量,与批量大小相同。这个特定的值需要作为 TrainerHelper 的参数,以建立用于训练的解码器模型。我们将在(4)中看到。

max_target_len 获取所有目标句子(序列)长度的最大值。如你所知,我们在 target_sequence_length 参数中有所有句子的长度。从中获取最大值的方法是使用 tf.reduce_max

过程解码器输入(3)

在解码器端,我们需要两种不同的输入,分别用于训练和推理。在训练阶段,输入作为目标标签被提供,但是它们仍然需要被嵌入。然而,在推理阶段,每个时间步的输出将是下一个时间步的输入。它们也需要被嵌入,并且嵌入向量应该在两个不同的相位之间共享。

Fig 2. **<GO>** insertion

在本节中,我将为训练阶段预处理目标标签数据。这不是什么特别的任务。你所需要做的就是在所有目标数据前面加上<GO>特殊标记。<GO> token 是一种引导性的 token,比如说“这是翻译的开始”。对于这个过程,你需要知道 TensorFlow 的三个库。

TF _ slide

  • 提取张量的步长切片(广义 python 数组索引)。
  • 可以认为是分裂成多个张量与跨度窗口大小从开始到结束
  • 参数:TF 张量,开始,结束,步幅

TF 填充

  • 创建一个用标量值填充的张量。
  • 参数:TF 张量(必须是 int32/int64),要填充的值

TF concat

  • 沿一维连接张量。
  • 参数:一个 TF 张量列表(本例中为 tf.fill 和 after_slice),axis=1

对目标标签数据进行预处理后,我们会在后面实现 decoding_layer 函数时嵌入。

编码(2)

Fig 3. Encoding model highlighted — Embedding/RNN layers

如图 3 所示,编码模型由两个不同的部分组成。第一部分是嵌入层。一个句子中的每个单词将由指定为encoding_embedding_size的特征数量来表示。这一层赋予了单词有用解释更丰富的代表力。第二部分是 RNN 层。你可以利用任何种类的 RNN 相关技术或算法。例如,在这个项目中,多个 LSTM 单元在漏失技术应用后堆叠在一起。你可以使用不同种类的 RNN 细胞,如 GRU

嵌入层

RNN 层层

编码模式

解码—训练过程(4)

解码模型可以被认为是两个独立的过程,训练和推理。这不是因为它们具有不同的架构,而是因为它们共享相同的架构及其参数。这是因为他们有不同的策略来支持共享模型。对于这个(训练)和下一个(推断)部分,图 4 清楚地显示了它们是什么。

Fig 4. Decoder shifted inputs

当编码器使用TF contrib . layers . embed _ sequence时,它不适用于解码器,即使它可能要求其输入嵌入。这是因为相同的嵌入向量应该通过训练和推断阶段共享。TF contrib . layers . embed _ sequence运行前只能嵌入准备好的数据集。推理过程需要的是动态嵌入能力。在运行模型之前,不可能嵌入推理过程的输出,因为当前时间步的输出将是下一个时间步的输入。

我们如何嵌入?我们很快就会看到。然而,现在,你需要记住的是训练和推理过程共享相同的嵌入参数。对于训练部分,应该交付嵌入的输入。在推理部分,应该只传送训练部分中使用的嵌入参数。

先看训练部分。

  • [**tf.contrib.seq2seq.TrainingHelper**](https://www.tensorflow.org/api_docs/python/tf/contrib/seq2seq/TrainingHelper):training helper 是我们传递嵌入输入的地方。顾名思义,这只是一个助手实例。这个实例应该交付给 BasicDecoder,这是构建解码器模型的实际过程。
  • [**tf.contrib.seq2seq.BasicDecoder**](https://www.tensorflow.org/api_docs/python/tf/contrib/seq2seq/BasicDecoder):basic decoder 构建解码器模型。这意味着它连接解码器端的 RNN 层和由 TrainingHelper 准备的输入。
  • [**tf.contrib.seq2seq.dynamic_decode**](https://www.tensorflow.org/api_docs/python/tf/contrib/seq2seq/dynamic_decode):dynamic _ decode 展开解码器模型,以便 BasicDecoder 可以检索每个时间步长的实际预测。

解码——推理过程(5)

  • [**tf.contrib.seq2seq.GreedyEmbeddingHelper**](https://www.tensorflow.org/api_docs/python/tf/contrib/seq2seq/GreedyEmbeddingHelper):greedyembedinghelper 动态获取当前步骤的输出,并将其交给下一个时间步骤的输入。为了动态地嵌入每个输入结果,应该提供嵌入参数(只是一串权重值)。与此同时,GreedyEmbeddingHelper 要求提供与批量和end_of_sequence_id相同数量的start_of_sequence_id
  • [**tf.contrib.seq2seq.BasicDecoder**](https://www.tensorflow.org/api_docs/python/tf/contrib/seq2seq/BasicDecoder):同培训流程一节所述
  • [**tf.contrib.seq2seq.dynamic_decode**](https://www.tensorflow.org/api_docs/python/tf/contrib/seq2seq/dynamic_decode) : 同培训流程一节所述

构建解码层(3)、(6)

嵌入目标序列

构建解码器 RNN 层

  • 如图 3 和图 4 所示,解码器模型中的 RNN 层数必须等于编码器模型中的 RNN 层数。

创建一个输出层,将解码器的输出映射到我们的词汇表中的元素

  • 这只是一个完全连接的层,以获得每个单词在最后出现的概率。

构建 Seq2Seq 模型(7)

在本节中,将之前定义的函数、encoding_layerprocess_decoder_inputdecoding_layer放在一起,构建一个完整的序列到序列模型。

构建图形+定义损失,优化器,带梯度剪裁

seq2seq_model功能创建模型。它定义了前馈和反向传播应该如何流动。该模型可训练的最后一步是决定和应用使用什么优化算法。在本节中,TF contrib . seq 2 seq . sequence _ loss用于计算损失,然后 TF train。AdamOptimizer 用于计算损耗的梯度下降。让我们在下面的代码单元中检查每个步骤。

从检查点加载数据

  • (source_int_text,target_int_text)是输入数据,而(source_vocab_to_int,target_vocab_to_int)是用于查找每个单词的索引号的词典。
  • max_target_sentence_length 是源输入数据中最长句子的长度。在解码器模式下构建推理过程时,这将用于 GreedyEmbeddingHelper。

创建输入

  • enc_dec_model_inputs 函数的输入(输入数据、目标、目标序列长度、最大目标序列长度)
  • 超参数输入函数的输入(lr,keep_prob)

构建 seq2seq 模型

  • 通过 seq2seq_model 函数建立模型。它将返回 train _ logits(计算损失的 logit)和 inference _ logits(来自预测的 logit)。

成本函数

  • 使用 TF contrib . seq 2 seq . sequence _ loss。这个损失函数只是一个加权的 softmax 交叉熵损失函数,但它是特别设计用于时间序列模型(RNN)。权重应该作为一个参数明确提供,它可以由 TF sequence_mask 创建。在这个项目中, TF sequence_mask 创建[batch_size,max_target_sequence_length]大小的变量,然后马克斯只将第一个 target_sequence_length 元素的个数设为 1。这意味着零件的重量会比其他零件轻。

优化器

渐变裁剪

Fig 5. Gradient Clipping

  • 由于递归神经网络是臭名昭著的消失/爆炸梯度,梯度裁剪技术被认为是改善这一问题。
  • 这个概念真的很简单。您决定阈值以保持梯度在某个边界内。在这个项目中,阈值的范围在-1 和 1 之间。
  • 现在,您需要将这些概念性知识应用到张量流代码中。幸运的是,有这个 TF 渐变裁剪的官方指南 How?。在 breif 中,您通过调用 compute_gradients 从优化器手动获取梯度值,然后使用 clip_by_value 操作梯度值。最后,您需要通过调用 apply_gradients 将修改后的梯度放回到优化器中

关于我自己

我的深度学习背景是uda city { Deep Learning ND&AI-ndwith contentrations(CVNLP ,VUI)},Coursera Deep Learning . AI Specialization(AI-ND 被拆分成 4 个不同的部分,我是和之前版本的 ND 一起完成的)。还有,我目前正在服用 Udacity 数据分析师 ND ,目前已经完成 80%。

序列对序列学习

原文:https://towardsdatascience.com/sequence-to-sequence-learning-e0709eb9482d?source=collection_archive---------4-----------------------

序列到序列学习中,RNN 被训练将输入序列映射到不一定长度相同的输出序列

应用是语音识别、机器翻译、图像字幕和问答。

架构

Encoder — Decoder Architecture

编码器 RNN 读取输入序列并生成固定大小的上下文向量,该向量代表输入序列的语义摘要。

固定大小的上下文向量作为解码器 RNN 的输入。

固定大小上下文可以作为解码器 RNN 的初始状态提供,或者可以在每个时间步长连接到隐藏单元。这两种方式也可以结合使用。

编码器和解码器中的时间步长数不需要相等。

限制

这种体系结构的一个限制是很难用一个小维度的上下文向量来概括一个长序列。

如何解决?

可以使用可变长度的上下文向量代替固定大小的向量

注意机制可用于从输入序列的每个时间步长从编码器 RNN 产生矢量序列。解码器学习有选择地关注矢量**,以在每个时间步长产生输出。**

序列对序列模型:简介和概念

原文:https://towardsdatascience.com/sequence-to-sequence-model-introduction-and-concepts-44d9b41cd42d?source=collection_archive---------1-----------------------

如果我们从高层次来看,seq2seq 模型的主要组件包括编码器、解码器和中间步骤:

我们使用嵌入,所以我们必须首先编译一个“词汇表”列表,包含我们希望我们的模型能够使用或读取的所有单词。模型输入必须是包含序列中单词 id 的张量。

然而,有四个符号需要我们的词汇来包含。Seq2seq 词汇表通常为这些元素保留前四个位置:

  • < PAD > :在训练过程中,我们需要将我们的例子批量地反馈给网络。这些批次中的输入都需要具有相同的宽度,以便网络进行计算。然而,我们的例子长度不同。这就是为什么我们需要填充较短的输入,使它们与批处理的宽度相同
  • < EOS > :这也是批处理的另一个必要性,但更多是在解码器端。它允许我们告诉解码器一个句子在哪里结束,也允许解码器在输出中指出同样的事情。
  • <>:如果你在真实数据上训练你的模型,你会发现你可以通过忽略那些在你的词汇表中出现频率不够高、不值得考虑的单词来极大地提高你的模型的资源效率。我们用< UNK >代替那些。
  • < GO > :这是解码器第一个时间步长的输入,让解码器知道什么时候开始产生输出。

注意:可以使用其他标签来表示这些功能。例如,我见过用代替。因此,通过预处理和模型训练/推理,确保您使用的任何东西都是一致的。

为训练图准备输入稍微复杂一些,原因有两个:

1.如果我们向解码器提供我们的目标序列,而不管它的时间步长在训练运行中实际输出什么,这些模型会工作得更好。因此,与图中不同的是,我们不会在下一个时间步中将解码器的输出反馈给自身。

2.定量

最初的序列对序列论文之一 Sutskever 等人 2014 报告称,如果输入相反,模型性能会更好。所以你也可以选择颠倒单词在输入序列中的顺序。

在预处理过程中,我们执行以下操作:

  • 我们建立自己的独特词汇库(并计算出现的次数)
  • 我们用替换频率低的词
  • 创建一个对话的副本,用 id 替换单词
  • 我们可以选择现在将单词 id 添加到目标数据集,或者在训练时进行添加

学分:来自课堂讲稿:https://classroom.udacity.com/nanodegrees/nd101/syllabus

资源:

https://github.com/ematvey/tensorflow-seq2seq-tutorials

序列到序列教程

原文:https://towardsdatascience.com/sequence-to-sequence-tutorial-4fde3ee798d8?source=collection_archive---------3-----------------------

这是深度学习中最强大的概念之一,它始于翻译,但后来转移到了问答系统(Siri、Cortana 等)。)、音频转录等。顾名思义,它对从一个序列转换到另一个序列很有用。

背后的主要思想是,它包含一个编码器 RNN (LSTM)和一个解码器 RNN。一个用来“理解”输入序列,解码器用来“解码”“思想向量”并构建输出序列。

Seq2Seq LSTMs

思想载体真正强大的地方在于,你可以插入输出解码器,将其转换成任何语言。也就是说,你不需要在英语到法语的数据集上训练来从英语转换到西班牙语。你可以简单地插入一个解码器,这个解码器是从一个不同的设备(比如葡萄牙语到西班牙语)预先训练好的。至少这是背后的理论。可能取决于你训练它的时间,你的数据量等等。

我发现 tensorflow 中缺少 seq2seq 模型背后的文档,所以我编写了自己的模型,如下所示。我在 Tensorflow 文档中找到的最接近的是embedding_rnn_seq2seq,然而,它在实现这个函数方面并不明显。因此,我写了自己的seq2seq模型如下:

*# Tensor where we will feed the data into graph*
inputs = tf.placeholder(tf.int32, (**None**, x_seq_length), 'inputs')
outputs = tf.placeholder(tf.int32, (**None**, **None**), 'output')
targets = tf.placeholder(tf.int32, (**None**, **None**), 'targets')

*# Embedding layers*
input_embedding = tf.Variable(tf.random_uniform((len(char2numX), embed_size), -1.0, 1.0), name='enc_embedding')
output_embedding = tf.Variable(tf.random_uniform((len(char2numY), embed_size), -1.0, 1.0), name='dec_embedding')
date_input_embed = tf.nn.embedding_lookup(input_embedding, inputs)
date_output_embed = tf.nn.embedding_lookup(output_embedding, outputs)

**with** tf.variable_scope("encoding") **as** encoding_scope:
    lstm_enc = tf.contrib.rnn.BasicLSTMCell(nodes)
    _, last_state = tf.nn.dynamic_rnn(lstm_enc, inputs=date_input_embed, dtype=tf.float32)

**with** tf.variable_scope("decoding") **as** decoding_scope:
    lstm_dec = tf.contrib.rnn.BasicLSTMCell(nodes)
    dec_outputs, _ = tf.nn.dynamic_rnn(lstm_dec, inputs=date_output_embed, initial_state=last_state)
*#connect outputs to* 
logits = tf.contrib.layers.fully_connected(dec_outputs, num_outputs=len(char2numY), activation_fn=**None**) 
**with** tf.name_scope("optimization"):
    *# Loss function*
    loss = tf.contrib.seq2seq.sequence_loss(logits, targets, tf.ones([batch_size, y_seq_length]))
    *# Optimizer*
    optimizer = tf.train.RMSPropOptimizer(1e-3).minimize(loss)

完整的教程可以在这个视频(和代码(第 19 课)如果你想跳过视频):

看这里是我的关于机器学习和深度学习的课程(使用代码 DEEPSCHOOL-MARCH 到 85 折)。

深度学习中序列对序列模型的熟悉

原文:https://towardsdatascience.com/sequence-to-sequence-using-encoder-decoder-15e579c10a94?source=collection_archive---------9-----------------------

序列到序列模型是接受序列输入并输出序列的模型。

建筑

Sequence to Sequence

编码器 r 是一个 RNN,接收输入并将其编码成一个向量。

编码器的最后隐藏状态给出编码向量。

编码向量重复 n 次,其中n =输出的时间步长数。

解码器,也是 RNN,将编码矢量先前 状态作为输入,并给出输出。

编码器和解码器中的时间步长数不需要相等。

为什么是 Seq2seq?

当你想在看到整个输入句子后生成输出时,可以使用 seq2seq 模型。

例如,在机器翻译中,翻译句子中的第一个单词可能取决于输入句子中的最后一个单词。

图像字幕

在图像字幕中,生成图像的文本描述。

训练数据由带有相应标题的图像组成。

编码器现在被卷积神经网络所取代。来自最后一个隐藏状态的输出被提供给解码器 RNN。

使用 Dask、Amazon ECS 和 Python 的分布式数据预处理(上)

原文:https://towardsdatascience.com/serverless-distributed-data-pre-processing-using-dask-amazon-ecs-and-python-part-1-a6108c728cc4?source=collection_archive---------9-----------------------

Source: unsplash.com

机器学习模型的质量和准确性取决于许多因素。最关键的因素之一是在将数据集输入到从数据中学习的机器学习算法之前对数据集进行预处理。因此,为他们提供您想要解决的问题的正确数据是至关重要的。例如,一些算法不支持空值,应该在训练之前进行转换和处理。您还应该了解为什么会有缺失值,这些值是否有特定的模式,以及它们的影响是什么。

数据工程师和数据科学家经常使用来自 python 生态系统的工具,如 NumpyPandas 来分析、转换和可视化他们的数据,这些数据被设计为高性能、直观和高效的库。以快速和可伸缩的方式在小数据集上执行这样的操作并不困难,只要数据集能够适合单台机器的内存。然而,如果数据集太大,无法放入单台机器,数据工程师可能会被迫将他们的代码重写为更具可扩展性的工具,如 Spark 和 SparkML,这些工具可以由大型 EMR 集群提供计算支持。

为了克服这个问题,我使用了 Dask 。Dask 利用了人们对像 Pandas 这样的著名库的熟悉,你可以用它来开发代码,以可伸缩、并行和分布式的方式处理数据。

在本文中,我将讨论如何创建一个无服务器集群,以分布式和并行的方式预处理数据。我还使用了 Dask 分布式 集群,为分析和数据处理提供了高级并行性。为了实现大规模性能,同时优化成本并保持解决方案的灵活性,我将使用 AWS Fargate 构建一个无服务器集群,它不提供集群管理开销,只提供一个 API 调用来扩展和缩小集群,然后将集群与 Amazon SageMaker Jupyter 笔记本集成。(或任何其他首选 IDE)

Dask 分布式是什么?

dask . distributed*:*是一个轻量级的开源库,用于 Python 中的分布式计算。它还是一个集中管理的、分布式的、动态的任务调度器。Dask 有三个主要组成部分:

dask-scheduler 进程: 协调几个工人的动作。调度器是异步的和事件驱动的,同时响应来自多个客户端的计算请求并跟踪多个工作进程。

dask-worker 进程: 跨多台机器和多个客户端的并发请求。

dask-客户端进程: 它是 dask.distributed 用户的主要入口点

解决方案图表:

Solution Diagram and Architecture

我需要在 Juypter 笔记本和 Fargate 集群之间保持低延迟通信和简单的网络配置。因此,我在同一个虚拟私有云(VPC)中创建了笔记本和 Dask 分布式集群。

预部署步骤:

首先,作为先决条件,我需要创建一个弹性容器注册(ECR)存储库。为此,我转到 AWS 控制台- >弹性容器服务(ECS) - >选择存储库,然后“创建存储库”。

(您也可以跳过这一步,创建一个 github 资源库)

我们需要给它起一个名字——“dask,然后点击“下一步”:

然后,我们转到“入门”页面,在这里我们可以找到创建和推送容器映像的初始命令。

既然存储库已经准备好了,我将切换到一个 shell“终端”来下载、构建和标记容器映像,然后将其推送到 ECR。为此,我运行以下 shell 命令:

bash# git clone [https://github.com/wmlba/ECS-Dask.git](https://github.com/wmlba/ECS-Dask.git)bash# cd ECS-Dask; tar -xzf base-image.tar.gz; cd base-imagebash# `aws ecr get-login --no-include-email --region us-east-1`bash# docker build -t dask .bash# docker tag dask:latest <AWS Account ID>.dkr.ecr.us-east-1.amazonaws.com/dask:latestbash# docker push <AWS Account ID>.dkr.ecr.us-east-1.amazonaws.com/dask:latest

注意:为了运行上述命令,您需要在运行命令的机器上本地安装 Docker,并配置 AWS 凭证。

我使用的 docker 图片是从 dask 上发布的图片稍微修改的

构建映像需要几分钟时间,然后将其推送到在前面的步骤中创建的 ECR 存储库。您可以通过在 ECS 控制台中单击存储库名称来验证这一点。

部署解决方案

现在我已经准备好了映像,我需要按照以下步骤使用 CloudFormation 模板部署解决方案:

  1. 在你的账户中启动这个云信息模板。完成云形成堆栈大约需要 3-5 分钟

CloudFormation 堆栈将为 Dask worker 和 Scheduler 创建资源,例如:Fargate 集群、任务定义、服务和任务。它还将创建一个 IAM 执行角色和策略,以允许访问 Elastic Container Registry (ECR)存储库和 CloudWatch 日志组的日志。默认情况下,所有资源都将在 us-east-1 区域创建。

2.在“指定详细信息”页面上,我为集群指定了一个带有 NAT 网关的专用子网。Dask 调度程序和工作程序将通过专用网络进行通信,ECS 服务只需要 NAT 网关就可以从存储库中提取 ECR 映像。然后,选择下一步:

3.在选项页面上,选择下一步。

4.在查看页面上,查看并确认设置。确保选中该框,确认模板将创建具有自定义名称的 AWS 身份和访问管理(IAM)资源。要部署堆栈,选择创建。几分钟后,堆栈创建应该完成。

创建堆栈后,您还可以确认 ECS Dask 集群已部署并正在运行。您可以通过切换到 ECS 控制台->单击群集 - >单击 Fargate-Dask-Cluster 来验证这一点,在 tasks 选项卡上,应该有两个正在运行的任务:

现在 Dask 集群已经准备好了,我将创建 SageMaker Notebook,这样我就可以开始使用集群了。为此,我切换到 SageMaker 控制台->笔记本实例->创建笔记本实例**。**

然后,我将选择之前在 CloudFormation 模板中选择的相同 VPC 和子网:

注意:您可以选择任何其他子网和安全组,只要您启用 SageMaker 笔记本和 Dask 集群之间的访问。

然后,我通过点击新建->-conda _ python3 创建一个新的 python 3 笔记本。Dask 软件包默认安装在 SageMaker 笔记本上,但确保软件包更新到最新版本很重要。为了验证这一点,我将在笔记本上运行 conda update 命令:

注意:如果客户端版本低于调度器和工作器版本,您在启动客户端时会遇到错误。

下一步是创建客户端,并通过运行以下代码连接到 dask 集群:

请注意,我使用了使用 ECS 服务发现功能自动分配的调度程序的 DNS 名称,该功能使用 Route 53 自动命名 API 操作来管理 Route 53 DNS 条目

现在,让我们使用集群对数据执行一些操作,但在此之前,我会将集群中的工作线程数量增加到 7 个。为此,我在笔记本中运行如下命令:

几秒钟后,Fargate 控制台中的工作任务状态将为“正在运行”。我将重新启动 Dask 客户端,以确保我们利用了集群的并行性。

现在,我们有一个由 14 个 CPU 内核和 12 GB 内存组成的集群(7 个工作线程各有 2 个 CPU 内核和 2 GB 内存)。让我们做一些计算和内存密集型操作,并产生一些见解。我正在用数据加载 dask dataframe,计算行程距离,并根据乘客数量进行分组。

在 7 个不同的工作人员之间并行化任务并并行加载超过 10 GB 的数据后,大约 2.5 分钟后,结果开始显现。

可视化:

来自 Bokeh 服务器的调度器任务的屏幕截图,显示了在工人之间线程化的操作。可以在浏览器中从调度程序 IP 地址和端口 8787 访问仪表板:

以下屏幕截图显示了每个工作人员的资源(CPU 和内存)利用率:

现在你应该准备好做一些预处理魔术!

在第 2 部分,我将展示一些使用我们创建的 Dask 集群运行分析和预处理/特征工程和机器学习的代码。

感谢您阅读帖子。反馈和建设性的批评总是受欢迎的。我会阅读你所有的评论。

威尔

使用 TensorFlow-Serving 的 RESTful API 服务基于图像的深度学习模型

原文:https://towardsdatascience.com/serving-image-based-deep-learning-models-with-tensorflow-servings-restful-api-d365c16a7dc4?source=collection_archive---------1-----------------------

如何在网络中提供端到端的 Tensorflow 模型?

TensorFlow-Serving 是一个有用的工具,由于它的新近性和相当小众的用例,它没有太多的在线教程。在这里,我将展示一个解决方案,演示 TensorFlow 的端到端实现——在基于图像的模型上提供服务,涵盖从将图像转换为 Base64 到将 TensorFlow 模型服务器与深度神经网络集成的所有内容。

在本教程中,提供了一个最小的工作示例——这个实现可以很容易地扩展到包括 Docker 容器、Bazel 构建、批量推理和模型解耦。这里的主要焦点是理解使用 TensorFlow-Serving 的一般要求,独立于任何可选的附加功能。使用 TensorFlow-Serving 的 RESTful 版本,与 gRPC 版本相反,我们实现了 predict 函数,但是也可以使用 classify 和 regression。

如果你想在 Jupyter 笔记本上查看这个教程,请点击这里

概观

在最基本的层面上,TensorFlow-Serving 允许开发人员将客户端请求和数据与独立于客户端系统的深度学习模型相集成。这样做的好处包括客户端能够对数据进行推断,而不必实际安装 TensorFlow,甚至不必与实际模型有任何联系,并且能够用一个模型实例为多个客户端提供服务。

我们的管道将是这样的:

特别要注意的是,图像必须作为一个 Base64 编码的字符串从客户端传递到服务器。这是因为 JSON 没有其他方法来表示图像(除了张量的数组表示,这很快就会失控)。图像也必须作为张量从原型传递到生成器。这是可以修改的,但是最好保持任何预处理和后处理与模型本身分离。

计算机网络服务器

导出用于服务的 TensorFlow 模型可能是该过程中最令人困惑的部分,因为这涉及到几个步骤。

  1. 将图形导出为 ProtoBuf 格式。这将保存 GraphDef 和变量,并表示训练好的模型。为了导出基于图像的模型,我们必须在图形的开头和结尾注入位串转换层,因为我们要求我们的推理函数只处理张量。
  2. 将 ProtoBuf 包装在 SavedModel 中。这一步是必要的,因为 TensorFlow-Serving 的 RESTful API 是通过 SavedModelBuilder 实现的。我们将导入我们的 GraphDef,然后提取输入和输出的 TensorInfo 来定义我们的预测签名定义。

我们将使用 CycleGAN 作为使用示例。首先,导入一些有用的库:

import tensorflow as tf
import argparse
import sys
sys.path.insert(0, “../CycleGAN-TensorFlow”)
import model

在这里,我们实例化一个 CycleGAN 并注入我们的第一层。

graph = tf.Graph()

**with** graph.as_default():
    *# Instantiate a CycleGAN*
    cycle_gan = model.CycleGAN(ngf=64, norm="instance", image_size=64)

    *# Create placeholder for image bitstring*
    *# This is the injection of the input bitstring layer*
    input_bytes = tf.placeholder(tf.string, shape=[], name="input_bytes")

接下来,我们将位串预处理为一个浮点张量批,以便它可以在模型中使用。

**with** graph.as_default(): 
    input_bytes = tf.reshape(input_bytes, [])

    *# Transform bitstring to uint8 tensor*
    input_tensor = tf.image.decode_png(input_bytes, channels=3)

    *# Convert to float32 tensor*
    input_tensor = tf.image.convert_image_dtype(input_tensor,  dtype=tf.float32)

    *# Ensure tensor has correct shape*
    input_tensor = tf.reshape(input_tensor, [64, 64, 3])

    *# CycleGAN's inference function accepts a batch of images*
    *# So expand the single tensor into a batch of 1*
    input_tensor = tf.expand_dims(input_tensor, 0)

然后,我们将张量输入模型并保存其输出。

**with** graph.as_default():
    *# Get style transferred tensor*
    output_tensor = cycle_gan.G.sample(input_tensor)

后推理,我们将浮点张量转换回一个位串。这是输出层的注入:

**with** graph.as_default():    
    *# Convert to uint8 tensor*
    output_tensor = tf.image.convert_image_dtype(output_tensor, tf.uint8)

    *# Remove the batch dimension*
    output_tensor = tf.squeeze(output_tensor, [0])

    *# Transform uint8 tensor to bitstring*
    output_bytes = tf.image.encode_png(output_tensor)
    output_bytes = tf.identity(output_bytes, name="output_bytes")

    *# Instantiate a Saver*
    saver = tf.train.Saver()

既然我们已经将位串层注入到我们的模型中,我们将加载我们的火车检查点并将图保存为 ProtoBuf。在对该服务器进行编码之前,我对 CycleGAN 进行了 10,000 步的训练,并将检查点文件保存在我的本地机器上,我将在该会话中访问该文件。

*# Start a TensorFlow session*
**with** tf.Session(graph=graph) **as** sess:
        sess.run(tf.global_variables_initializer())

        *# Access variables and weights from last checkpoint*
        latest_ckpt = tf.train.latest_checkpoint("../CycleGAN-TensorFlow/checkpoints/20180628-1208")
        saver.restore(sess, latest_ckpt)

        *# Export graph to ProtoBuf*
        output_graph_def = tf.graph_util.convert_variables_to_constants(sess, graph.as_graph_def(), [output_bytes.op.name])
        tf.train.write_graph(output_graph_def, "../CycleGAN-TensorFlow/protobufs", "model_v1", as_text=**False**)

至此,我们完成了第一步!在第二步中,我们将把 ProtoBuf 包装在一个 SavedModel 中,以使用 RESTful API。

*# Instantiate a SavedModelBuilder*
*# Note that the serve directory is REQUIRED to have a model version subdirectory*
builder = tf.saved_model.builder.SavedModelBuilder("serve/1")

*# Read in ProtoBuf file*
**with** tf.gfile.GFile("../CycleGAN-TensorFlow/protobufs/model_v1", "rb") **as** protobuf_file:
    graph_def = tf.GraphDef()
    graph_def.ParseFromString(protobuf_file.read())

*# Get input and output tensors from GraphDef*
*# These are our injected bitstring layers*
[inp, out] = tf.import_graph_def(graph_def, name="", return_elements=["input_bytes:0", "output_bytes:0"])

接下来,我们定义我们的签名定义,它期望模型的输入和输出的张量信息。当我们保存模型时,我们会得到一个“No assets”消息,但是这没关系,因为我们的图和变量已经保存在 ProtoBuf 中了。

*# Start a TensorFlow session with our saved graph*
**with** tf.Session(graph=out.graph) **as** sess:
        *# Signature_definition expects a batch*
        *# So we'll turn the output bitstring into a batch of 1 element*
        out = tf.expand_dims(out, 0)

        *# Build prototypes of input and output bitstrings*
        input_bytes = tf.saved_model.utils.build_tensor_info(inp)
        output_bytes = tf.saved_model.utils.build_tensor_info(out)

        *# Create signature for prediction*
        signature_definition = tf.saved_model.signature_def_utils.build_signature_def(
            inputs={"input_bytes": input_bytes},
            outputs={"output_bytes": output_bytes},
            method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME)

        *# Add meta-information*
        builder.add_meta_graph_and_variables(
            sess, [tf.saved_model.tag_constants.SERVING],
            signature_def_map={
                tf.saved_model.signature_constants.
                DEFAULT_SERVING_SIGNATURE_DEF_KEY: signature_definition
            })

*# Create the SavedModel*
builder.save()

就是这样!命令行返回的是 SavedModel 的路径,它用于构建 TensorFlow 模型服务器。serve/1 中的“variables”文件夹将是空的,但这没关系,因为我们的变量已经保存在 ProtoBuf 中了。

截至 2018 年 7 月,Python 3 不支持 TensorFlow 服务,但有人提出了解决方案。安装 Python 3 TensorFlow 服务 API,包括:

pip install tensorflow-serving-api-python3

现在,我们可以用下面的命令从 bash 运行这个 TensorFlow 模型服务器:

tensorflow_model_server --rest_api_port=8501 --model_name=saved_model --model_base_path=$(path)

其中$(path)是服务器目录的路径。我的例子是/mnt/c/Users/Tyler/Desktop/tendies/minimum _ working _ example/serve。

客户

客户端的工作是接受图像作为输入,将其转换为 Base64,使用 JSON 将其传递给服务器,并解码响应。首先,导入一些有用的库:

**import** **base64**
**import** **requests**
**import** **json**
**import** **argparse**

我们将执行从高斯噪声图像到正弦噪声图像的风格转换。这是高斯图像:

首先,我们将打开图像并将其转换为 Base64。

*# Open and read image as bitstring*
input_image = open("images/gaussian.png", "rb").read()
print("Raw bitstring: " + str(input_image[:10]) + " ... " + str(input_image[-10:]))

*# Encode image in b64*
encoded_input_string = base64.b64encode(input_image)
input_string = encoded_input_string.decode("utf-8")
print("Base64 encoded string: " + input_string[:10] + " ... " + input_string[-10:])

发送到 TensorFlow 模型服务器的 JSON 数据必须以一种非常特殊的方式构建。这种方法将略有不同用于分类和回归。对于图像预测调用,我们的 JSON 主体必须如下所示:

{
  "instances": [
                  {"b64": "iVBORw"},
                  {"b64": "pT4rmN"},
                  {"b64": "w0KGg2"}
                 ]
}

因为我们只向服务器发送一张图片,所以这很简单。我们可以像这样创建 JSON 数据:

*# Wrap bitstring in JSON*
instance = [{"b64": input_string}]
data = json.dumps({"instances": instance})
print(data[:30] + " ... " + data[-10:])

这就是我们向 TensorFlow 模型服务器发送 POST 请求所需的全部内容。这是一个同步调用,所以客户端将暂停,直到它收到来自服务器的响应(当您想知道为什么您的代码在发布一个非常大的图像后停止时,这很有用)。

json_response = requests.post("http://localhost:8501/v1/models/saved_model:predict", data=data)

为了解释响应,我们以相反的顺序执行上述步骤。为了从 JSON 响应中获取 base64 编码的图像,我们必须访问:

  1. 对应于响应字典中“预测”的值。
  2. 结果数组中的第一个条目。
  3. 结果字典中对应于“b64”的值。

然后,我们将把这个值解码成一个原始的位串。

*# Extract text from JSON*
response = json.loads(json_response.text)

*# Interpret bitstring output*
response_string = response["predictions"][0]["b64"]
print("Base64 encoded string: " + response_string[:10] + " ... " + response_string[-10:])

*# Decode bitstring*
encoded_response_string = response_string.encode("utf-8")
response_image = base64.b64decode(encoded_response_string)
print("Raw bitstring: " + str(response_image[:10]) + " ... " + str(response_image[-10:]))

*# Save inferred image*
**with** open("images/sinusoidal.png", "wb") **as** output_file:
    output_file.write(response_image)

成功!这是合成图像,它在我们的原始图像上添加了正弦噪声模式。

结论

感谢跟随本教程;希望对你有帮助!这款笔记本基于我的 TensorFlow 分布式图像服务库的最小工作示例,您可以在这里下载。如果您有兴趣将这个库与 TensorFlow 对象检测 API 甚至您自己的模型集成在一起,请查看本文的续集。更多关于我的博文和信息,请访问我的网站

Scala 中的服务张量流模型

原文:https://towardsdatascience.com/serving-tensorflow-model-in-scala-6caeadbb2d55?source=collection_archive---------0-----------------------

Taken from here

Taken from here

问题

训练机器学习模型的过程只是将其投入生产的第一步。在一天结束时,数据科学团队签署模型,数据工程团队必须找出如何在生产环境中部署、使用、更新和维护模型。关于如何做到这一点,有两种可能的方法:

  • 通过 RPC/REST API 公开一个模型。在这种情况下,优势在于用于构建模型的语言/基础设施也可以用于服务 RPC/REST API。缺点是对模型的每个请求都是单独的 RPC 或 HTTP 调用,有自己的延迟。延迟对查询模型所用的平均时间设置了上限。
  • 在生产环境中已经可用的数据工程管道中直接使用该模型。在这种情况下,不存在额外延迟的问题,但是,最好的数据处理引擎/框架似乎不支持用于模型训练的同一组语言。例如,典型的场景是当数据科学团队使用 Python/TensorFlow 构建模型时,数据工程团队必须将其集成到 Spark/Scala/Java 堆栈中。

我将关注第二个选项,并描述如何在 Scala 中使用预先训练好的 TensorFlow 模型构建一个库。TensorFlow 已经提供了 Java API ,可以在 Scala 中直接引用和使用,但是非常低级和繁琐。

tfmodelserving 4s GitHub repo中可以找到包含这里描述的示例的结果库。

API 代数

无标签的最终方法是用来建立图书馆。更多细节可以在这里这里找到。这个想法是创建一个代数,它抽象了一个具体实现/解释器中使用的效果和类型。这个特征定义了 API 公开的一组操作:

F[_]是高级类型,表示具体实现使用的效果。这可能是未来的 Scalaz 任务,甚至是简单的尝试。trait 还定义了两种类型 TModel 和 TTensor。前者是一个模型类型,表示一个加载到内存中的模型,后者是一个张量类型。两种类型都必须由解释器来定义。此外,trait 定义了使用模型的几个基本操作:

  • load 用于从某个源(例如,从文件系统)加载模型。模型源是定义模型源的联产品类型:

  • 元数据从加载的模型中查询模型元数据。它返回 ModelMetadata,依次枚举此图可用的签名列表。签名的概念是从 TensorFlow 借用的,它定义了一个由模型公开的函数。例如,预测模型可能会公开由其输入和输出张量定义的签名。当给定一个输入张量时,该函数产生一个输出张量,该输出张量根据输入属于特定类别的概率。如果一个图支持多个任务,它可能会公开多个签名。以下是 ModelMetadata、SignatureMetadata 和 TensorMetadata 事例类的定义:

  • 张量函数从兼容的数据结构(如数组或列表)创建一个张量对象。如果为数据结构定义了隐式 TensorEncoder 类型类,则该数据结构是兼容的:

以下是 TensorEncoder 将二维数组转换为 TensorFlow API 张量对象的示例:

  • eval 是实际执行图形计算的函数。它需要一个模型对象、一个输出元数据和一个映射,输入张量元数据作为键,输入张量本身作为值。它返回包装成效果 F[_]的结果张量对象。该函数还需要 TensorDecoder 和 Tensor type 的 Closeable 类型类。TensorDecoder 将一个张量对象转换成数组、列表等数据结构形式的表示。:

需要可关闭的类型类来释放非托管对象。例如,TensorFlow API 对非托管对象 tensors 进行操作,当不再需要它们时,必须显式关闭它们,否则,它们将留在内存中,这可能会导致应用程序中的内存泄漏:

就是这样。API 已定义。下一步是为 TensorFlow 实现一个“解释器”。

张量流解释程序

TensorFlow 的解释器必须实现模型服务特性。我选择了 scala.util.Try 作为一个效果,这样所有的 API 函数都将返回打包到 Try 中的结果,并且为了便于理解,可以使用 scala 来编写 API 操作。下面是解释器的实现。它完成了与 TensorFlow Java API 交互的所有脏活:

此外,我们必须定义 TensorEncoder、TensorDecoder 和 Closeable 类型类:

只有一个字符串、一维和二维数组才有编码器和解码器。这是我执行几个示例并查看它是否有效所需的基本最小值。这可以扩展到任何其他兼容的数据类型。

使用示例#1

是时候用一个简单的例子来试试这个库了。首先,必须准备一个 TensorFlow 保存模型。对于这个例子,我使用了一个计算图,它简单地将一个矩阵乘以单位矩阵。根据单位矩阵的性质,输出矩阵应该等于输入矩阵。以下是构建图表并将其保存为 TensorFlow SavedModel 格式的 Python 代码:

它用单输入(' x ')和单输出(' y ')定义签名。生成的模型目录包含序列化图形以及变量快照:

Scala 代码将输入矩阵输入到模型中并获得结果矩阵:

下面是上面的应用程序产生的输出:

使用示例#2

第二个使用示例基于我在这里描述的如何构建的狗品种分类模型。它拍摄了一张狗的图像,并产生了前 5 个品种的概率:

为样本狗图像生成的输出:

结论

构建了一个合理的 Scala 库来处理 TensorFlow 模型。它可以用于在任何 Scala/Java 应用程序(例如 Apache Spark)中使用预训练的张量流模型来执行分类、预测等。

服务 TensorFlow 模型。无服务器

原文:https://towardsdatascience.com/serving-tensorflow-models-serverless-6a39614094ff?source=collection_archive---------0-----------------------

之前我写过,如何用 TensorFlow 服务模型用 Flask 包装它以提供 REST API。也可以用 Flask 直接托管模型,这在许多用例中也是非常可行的。所有这些技术都有一个共性——你需要将应用程序放在一个容器中,由你的云提供商运行它,维护一个服务器,并负责扩展。我们有 Docker 和 Kubernetes 这样的工具让我们的生活变得更轻松,但最终,你会有一个耗费金钱和时间的基础设施。

几年前,AWS 引入了无服务器应用程序的新概念,你不需要服务器来托管你的应用程序,你只需要编写一个代码,它会被调用来响应一些事件——T4。目前,它支持 Node.js、Java、Python 和 C#作为编程语言。我们也有替代方案,比如微软功能谷歌云功能,但微软只做 Python 的实验性支持,谷歌功能仍处于测试阶段。

无服务器,是什么?

我强烈推荐马丁·福勒的这篇关于无服务器架构的文章。我不能解释得更好了。简而言之,您完全依赖提供者服务来管理服务器逻辑和状态。当然,您编写一个后端代码,但是,与传统方法不同,您在无状态容器中运行它,并将它们的管理外包出去。

拥有无服务器应用程序的想法听起来很棒——您只需创建一个后端逻辑,AWS Lambda 将调用它来响应事件。例如,一个事件可以是 REST API 调用或在 S3 桶中写一些东西。然后使用提供的 Web UI 或 AWS CLI 将代码部署到 AWS Lambda,就这样。不用担心容器、扩展和其他基础设施相关的东西;亚马逊负责所有这些。

不幸的是,它并不适用于所有用例。它非常适合微服务架构和无状态 API。这意味着,如果您需要在 REST 请求之间保存任何东西,或者拥有某些东西的全局实例(例如,已初始化并准备好进行预测的机器学习模型),那么无服务器架构可能不是最佳选择。

服务 TensorFlow 模型无服务器?

无服务器方法对 TensorFlow 模型的服务有意义并带来优势吗?在我看来,如果你开发机器学习产品或服务,而不想在 Docker、Kubernetes 和所有这些东西上浪费时间,这是有意义的。

另一个要考虑的方面是成本。与 AWS EC2 实例不同,您是根据请求的数量和代码执行的时间来收费的。此外,如果您的代码利用其他 AWS 服务或传输数据(例如,从 S3 桶),您也将为此付费。详细信息可以在这里找到。我想在很多情况下,AWS Lambda 会是一个更便宜的选择。

考虑

如果您决定尝试 TensorFlow 模型的无服务器服务,请考虑以下因素。

加载模型

通常,您训练模型,保存它,并在 web 应用程序启动时加载。在无服务器的情况下,您只提供一个处理请求的函数,因此,理论上,您需要在每次函数调用时加载模型。幸运的是,根据的最佳实践,你可以解决这个问题,在 lambda 函数被调用之前全局加载模型。

功能生命周期

此外,如果您在第一次函数调用之前加载您的模型,则不能保证同一个函数实例保持活动状态并处理后续调用。这意味着 AWS 可以实例化您的函数,并在每次事件发生时加载模型。然而,我的测试表明,如果后续调用之间的时间差很小(几秒钟),实例会被重用,模型会保留在内存中。如果您预计工作量很大,那么重新加载模型将不是问题。否则,每个请求可能需要几秒钟才能得到响应。

限制

AWS Lambda 在大小和超时方面有一定的限制。请仔细检查。特别是在 TensorFlow 的情况下,您必须应用一些技巧来部署函数、加载模型和传输数据。我在下面提供细节。

履行

我创建了一个项目,演示如何使用 AWS Lambda 为 TensorFlow 模型提供服务。请随意复制、修改和用于商业和非商业目的,但我不提供任何担保和支持。在这里,我给出了一个简短的概述,并描述了模型部署的步骤和工具。

你需要什么

我假设一个知识,什么是 AWS 和如何使用它的管理控制台。开始之前,请确保您已经:

  • AWS 帐户
  • EC2 实例,自由层,Ubuntu 16.04
  • S3 桶容纳模型和数据。

我测试了以下配置和库:

准备

为了方便起见,我使用了 Anaconda ,在这里我为项目创建了 Python 2.7 环境。

  • 安装 Python 库——我为 PIP 安装提供了需求文件
  • 下载并安装 Node.js. npm 是安装包的一部分,不需要单独安装
  • 安装无服务器工具包,以便在 AWS Lambda 中更容易地部署代码
  • 或者,安装 Postman 来发布 REST 请求。

项目结构

项目存储库中,您可以找到以下文件:

  • gan_model.py :表示 gan 模型。它恢复保存到 Protobuf 模型,创建一个会话并初始化计算图。它提供了一种预测的方法
  • utils.py :包含帮助函数。最重要的是用于从自动气象站 S3 存储桶传输数据的那些
  • handler.py :实现一个被 AWS Lambda 调用的函数。此外,我们在这里导入预编译的依赖项(见下文)并创建模型实例
  • serverless.yml :无服务器工具包部署配置
  • settings.py :包含在项目范围内使用的常量
  • 我只在本地测试中使用它来检查数据传输和模型功能
  • requirements . txt:PIP 安装需求文件
  • env_var.sh :为本地测试导出环境变量的助手脚本
  • 卖主:在这里你可以找到一份自述文件。在本地,我们将额外的项目依赖项放入这个目录中进行部署。

准备项目相关性

AWS Lambda 为代码执行提供了 Python 环境。这个环境没有提供你可能需要的所有库。在我们的例子中,我们必须提供 TensorFlow、Numpy 等。并将它们与我们的代码一起部署。

问题是 AWSλ限制 —部署包大小不能超过 50 MB。但是 TensorFlow 的重量,也就是 ZIP 的重量,实在太重了。它包含了许多我们不需要的东西(TensorBoard、预编译的 Python 脚本等等)。所以我们必须运用一些技巧来克服这个障碍。我建议采取以下步骤:

  • 创建并启动 AWS EC2 实例,自由层,Ubuntu 16.04 64 位
  • 从终端连接到实例:
ssh <your instance name>.compute.amazonaws.com
  • 将 ZIP、虚拟环境和 TensorFlow 安装到其中:
sudo apt-get update
sudo apt-get install -y zip python-dev python-pip
export LC_ALL=C
pip install --upgrade pip
sudo pip install virtualenv
virtualenv tf_env
source tf_env/bin/activate
pip install tensorflow
  • 摆脱无用的东西和压缩依赖,我们需要:
touch ~/tf_env/lib/python2.7/site-packages/google/__init__.pycd ~/tf_env/lib/python2.7/site-packageszip -r ~/tf_env.zip . --exclude \*.pyc *.DS_Store /external/* /tensorflow/contrib/* /tensorflow/include/unsupported/* /tensorflow/examples/* /tensorboard/* /tensorflow_tensorboard-0.4.0rc3.dist-info/* /pip/* /pip-9.0.1.dist-info/*
  • 将依赖项复制到本地计算机:
scp ubuntu@<your instance name>.compute.amazonaws.com:~/tf_env.zip <somewhere at your local machine>/tf_env.zip
  • 终止 AWS EC2 实例。

现在我们有了 tf_env.zip 和部署到 AWS Lambda 的依赖项。

张量流模型准备

我们成功地开发并训练了一个模型,最终将其导出到 Protobuf 中,现在我们希望使用它进行预测。问题是——我们是将其作为部署包的一部分,还是从外部来源加载?

将模型和源代码一起部署的好处是——您将所有的东西都放在一个地方。但是有两个缺点——模型可能太大,无法通过 AWS Lambda 限制,当您更改模型时,您必须重新部署所有内容。

我强烈建议在外部保存您的模型,并从那个地方加载它。我在这个项目中做了什么:

  • 当我在 Udacity 学习的时候,我用我的样本模型进行了面部生成,我用生成式对抗网络进行了训练
  • 我将模型训练并导出到 Protobuf 中(我在这里描述了流程)并将模型压缩到 protobuf 文件变量目录中
  • 我创建了 AWS S3 桶,并上传了我的模型 ZIP 文件。重要说明—我的 S3 桶和 Lambda 函数在同一个 AWS 区域。这允许更快的传输和更容易的权限设置。

然后,我可以将我的模型从 S3 桶加载到我的 Lambda 函数中。

准备测试图像

Lambda 函数对街景门牌号进行预测。我决定把我的测试图像也上传到 S3 桶中,并从那里下载一个特定的图像进行预测。这意味着该函数获取桶名和图像名,下载图像并对其运行预测。

AWS Lambda 函数解释

主要的挑战是提供被 AWS Lambda 调用的函数和初始化步骤。让我们来看看 handler.py :

  • 首先,我们导入标准库:
import os
import sys
import json
  • 接下来,我们让 Python 环境知道,在哪里可以找到额外的项目依赖关系:
current_location = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(current_location, 'vendored'))
  • 只有现在我们才能导入加载我们的模型。我们从 S3 桶加载保存的模型——详情请查看 utils.py ,非常简单。
from gan_model import GANModel
import utilsmodel_dir = utils.create_model_dir()
utils.download_model_from_bucket(model_dir)
gan_model = GANModel(model_dir)
  • 我们提供一个带有特殊签名的 Lambda 函数。事件包含 AWS Lambda 提供的数据,我们希望 Python dict 在我们的例子中。上下文提供运行时信息,但是我们不在函数中使用它。
def predict(event, context):
  • 下面是一个对我们函数的 REST 请求的例子。 为无服务器安装返回的 URL, 在部署设置文件 serverless.yml 中设置。
{LambdaURL}/{stage}/predict?bucket=<your bucket>&key=<image file in bucket>
  • 该函数从 S3 桶下载图像并对其进行预测:
......image = utils.download_image_from_bucket(bucket_name, key)
results = gan_model.predict(image)......
  • 最后一件事是响应准备——我们提供 3 个最可能的数字,它们的概率为 JSON:
......def lambda_gateway_response(code, body):
    return {"statusCode": code,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps(body)}......results_json = [{'digit': str(res[0]), 'probability': str(res[1])} for res in results]......return lambda_gateway_response(
            200, 
            {'prediction_result': results_json})

就是这样。函数本身的创建要简单得多,因为所有的准备步骤都是:-)

部署

我们可以在 AWS Lambda 中使用提供的 Web UI 手动部署我们的功能,但是我强烈建议使用无服务器框架。它独立于云提供商,我鼓励您查看官方文档以了解详细信息。

首先,安装无服务器工具包:

sudo npm install serverless -g
serverless --version

您应该会看到工具包的安装版本。配置 AWS 凭证—我使用了 AWS 访问密钥。请查看官方 AWS 文档中关于管理凭证和访问密钥的内容。生成 AWS 访问密钥后,保存它们并导出到 shell 环境中:

export AWS_ACCESS_KEY_ID=<your-key-here>
export AWS_SECRET_ACCESS_KEY=<your-secret-key-here>

接下来,我们在 serverless.yml. 中定义部署配置。

  • AWS 作为提供者,Python 2.7 作为执行环境:
provider:
  name: aws
  runtime: python2.7
  • 环境变量:
environment:
  TF_AWS_MODEL_ZIP_FILE_NAME: gan_model.zip
  TF_AWS_MODEL_PROTOBUF_FILE_NAME: saved_model.pb
  TF_AWS_S3_MODEL_BUCKET_NAME: <bucket name that holds the model>
  • Lambda 函数执行角色的 AWS IAM(身份和访问管理)策略。它必须被添加以允许函数访问 S3 桶,在那里我们保存我们的模型和测试图像。以下是我的设置:
iamRoleStatements:
  - Effect: “Allow”
    Action:
      - "s3:GetObject"
    Resource:
      - "arn:aws:s3:::vb-tf-aws-lambda-model"
      - "arn:aws:s3:::vb-tf-aws-lambda-model/*"
      - "arn:aws:s3:::vb-tf-aws-lambda-images"
      - "arn:aws:s3:::vb-tf-aws-lambda-images/*"
  • 要响应的处理函数和事件—在我们的例子中是 HTTP GET 请求。当 AWS Lambda 收到请求时,它调用我们的函数来获得响应:
functions:
  predict:
    handler: handler.predict
    events:
      - http:
          path: /predict
          method: get

现在只需从终端执行部署命令…

cd <project root>
serverless deploy

…然后等到一切都部署完毕。在终端中,您会看到一个部署日志和关于已部署服务的信息。具体来说,您可以看到端点和函数:

endpoints:
  GET — [https://<address>.amazonaws.com/dev/predict](https://9cspjk5fg6.execute-api.us-west-1.amazonaws.com/dev/predict)
functions:
  predict: tensorflow-lambda-gan-dev-predict

如果要从 AWS 中删除该功能,请执行以下操作:

serverless remove

试验

对于测试,我使用 Postman,但是如果你愿意,你也可以使用你的浏览器。

现在我们得到了与这里的和这里的相同的结果,但是没有创建 Docker 容器,使用 Kubernetes 进行缩放,最终使用 Flask 进行服务。

结论

一开始,我相当怀疑预测服务的无服务器部署是否可行和有意义。我首先关心的是 Lambda 函数实例的重用——我们不希望每次收到请求时都重新加载模型。第二个问题是——我们如何克服 Lambda 限制,并使用 TensorFlow 这样复杂而庞大的库。

在做了一些研究并阅读了一篇非常有帮助的文章之后,我能够解决第二个问题。我的测试表明,在恒定负载下,函数被重用,模型很少被重载。

我的印象是——AWS Lambda 加快了开发周期,因为我们不关心容器化、缩放和应用服务器。一切都由云提供商管理。你可以快速上传一个新版本的模型,如果你使用 S3 桶来存储它。我没有展示这一点,但是对 S3 桶中模型的更新做出反应是可能的——这是一个可以由 Lambda 函数处理的额外事件。

另一方面,当 AWS 删除一个函数实例时,这是不可预测的。如果您的服务没有被广泛使用,那么每个请求需要几秒钟而不是几毫秒,这是事实。如果你能忍受,那很好,否则,你应该建立一个预热机制来模拟负载。

另一个方面——目前,将 TensorFlow 依赖项引入 AWS Lambda 确实很棘手。我个人不喜欢这样的黑客。

由于 TensorFlow 对于无服务器架构的不可预测性和未就绪性,我仍然倾向于在生产环境中使用全服务器方法。

更新 2018 年 10 月 26 日

最初,我使用 TensorFlow 1.4.0 作为我的预测函数的依赖项。从那时起,谷歌团队对 TensorFlow 框架进行了重大更新,我们必须稍微改变项目依赖性,为绕过 AWS Lambda 限制做准备。在 virtualenv 中安装 TensorFlow 后,我们执行以下命令

touch ~/tf_env/lib/python2.7/site-packages/google/__init__.pycd ~/tf_env/lib/python2.7/site-packagesfind . -name "*.so" | xargs stripzip -r ~/tf_env_l.zip . --exclude \*.pyc *.DS_Store /external/* /tensorflow/contrib/* /tensorflow/include/unsupported/* /tensorflow/examples/* /tensorboard*/* /pip*/* /setuptools*/* /wheel*/* easy_install*

创建具有所需依赖项的 ZIP 文件。最值得注意的动作是对所有目标文件执行剥离。这允许显著减小它们的尺寸。此外,我稍微清理了一下 zip 命令的参数。我用 TensorFlow 1.11.0 测试了一下,效果和预期一样。

Source: Google

从数据中设定面包店的促销策略

原文:https://towardsdatascience.com/setting-the-promotional-strategy-for-a-bakery-from-data-7e1cc93a2af?source=collection_archive---------10-----------------------

知道如何处理数据并提出正确的问题非常重要。在商业中,知道如何处理这些结果是至关重要的。第二步包括将图表、表格或统计数据从描述性的(“告诉我发生了什么”)转换为说明性的(“告诉我该怎么做”)。

出于这个原因,我们将经历一个基于数据发现来制定策略的项目。我们拥有的关于数据的唯一上下文是,它是来自面包店的交易数据。上面有号码、日期、时间戳和购买的物品。下面是一个快照:

我们的目标是增加已经在我们面包店销售给顾客的商品总量。

我们关注的是产品数量和收入,因为面包店通常有较高的固定成本和稳定的营业时间,这意味着增加对现有客户的高利润产品(如咖啡、面包、茶)的销售会带来更高的盈利能力,因为这些成本中的更多成本都可以在不增加劳动力、工时或空间的情况下得到弥补。如果我们有收入和盈利能力数据,我们可以在分析的基础上再增加一层,以模拟我们的战略对盈利能力的影响。

正如我将在下面的调查结果中详述的那样,我们实现该面包店目标的策略应该是:

  1. 在工作日上午 12 点之前,我们应该为顾客选择的**热饮(茶、咖啡或热巧克力)和早餐(吐司、蛋糕、松饼)**提供捆绑折扣。
  2. 在工作日的下午,我们应该提供:买一个三明治,喝茶可以打五折
  3. 周末,购买任意两件商品,第三件商品打 7.3 折

完整项目代码, 请点击此处

探索性数据分析

让我们从更好地理解数据开始。具体来说,我们想知道按商品购买的频率,以及这一频率在一天中的不同时间会如何变化。我们可以将所有这些信息简洁地嵌入到交互式条形图中:

Note: For conciseness, I’ve limited to the top selling items for each time period.

接下来,我们可以通过点击下图右上角的“播放”按钮来查看销售趋势。

显而易见,我们可以看到销售呈现出上升和下降的循环模式。让我们看看星期几能否解释这种差异:

事实上,看上面的两张图表,我们可以看到周末似乎可以解释大部分的价格上涨。

最后,我们将了解销售商品的数量如何随着一天中的时间、一周中的每一天以及一天中的每个小时而变化。

上述内容有助于我们进行剩余的分析,让我们了解最受欢迎的商品,以及这些商品在一天中的不同时间是如何变化的,并告诉我们应该制定一个策略,将一周中的不同日子和/或一天中的不同时间的销售差异考虑在内。

设定策略

现在我们对数据及其分布有了更好的理解,我们可以进入使用数据为决策提供信息的阶段。

在我们的战略发展中,有几个指导原则需要考虑:

  • 我们希望增加出售的商品数量,以此来激励那些不会购买的商品
  • 我们应该考虑那些我们知道会改变客户与我们互动方式的变量(例如,一天中的时间和一周中的日期)。
  • 最终输出应该提供如何行动的明确指示,为什么这一行动过程是可取的,它不应该对客户太混乱,也不应该对操作员太复杂。

通过交易数据,我们希望更好地理解下面的问题:购买哪些商品会导致购买哪些其他商品?

为了使这一点更加明确,我们想知道,例如,与任何顾客购买松饼的可能性相比,购买咖啡是否意味着顾客更有可能也购买松饼。

对于这类问题,有一种经过充分研究的方法,它被称为 Apriori 算法,它有三个主要组成部分:支持、信心和提升。

Apriori 帮助我们理解,对于一对物品,物品 2 被购买的频率(支持),如果物品 1 被购买,物品 2 被购买的可能性(置信度),以及在物品 1 被购买的情况下物品 2 被购买的比率的增加(提升)。

(更多阅读, 这是一篇优秀的文章 )。

考虑到这些,我们对如何解决这个问题有一些考虑:

  1. 我们可以寻找这样的项目对,其中项目 1 具有高支持度(即频繁购买),项目 2 具有低支持度,但是这两者具有高的组合寿命(购买项目 1 时,更频繁地购买项目 2)。
  2. 我们可以寻找支持度较低但提升力较高的商品(例如,我们希望鼓励购买商品 1,这种商品不经常购买,但会引发其他购买)。
  3. 我们可以寻找两种或两种以上经常单独购买,但不经常一起购买的产品,并将它们捆绑在一起,为客户提供更具吸引力的产品。

例如,我们将使用上述内容来考虑如何设置折扣(“以 50%的折扣购买项目 1 并获得项目 2”)或捆绑产品选项(“以低于项目 1 +项目 2 的价格获得项目 1 和项目 2”)。

同样,在日历层面,我们有几个问题需要考虑:

  1. 我们是否应该尝试在历史上销售额较低的日子(即周中)提高销售额?
  2. 我们是否应该在交易量已经较高的日子里尝试销售更多产品,因为我们的初始客户群较高(如周末)?
  3. 知道我们的交易量每小时都不一样,我们是否应该以一天中的时间为目标?

让我们绕一小段路,看看这些概念是如何实现的。下面我分享了我的 Dunkin Donuts 应用程序的 DDPerks 屏幕截图。让我们看看他们在宣传什么,为什么:

首先,我们看到打折的卡布奇诺或拿铁,但只有当我在下午 2 点到下午 6 点之间去的时候,他们才试图鼓励在特定的时间窗口访问,否则(可能)会有较低的销售额。

第二,有两个早餐三明治的价格降低到了 5 美元> DD's 正在采用产品捆绑来增加总订单价值

最后,如果我在周三使用他们的移动订购功能,可以获得 2 倍的积分。该公司鼓励某种类型的行为来展示产品功能,并可能更好地管理商店内的订单流。

此外,这些可能会根据位置和我与应用程序的交互进行个性化——我购买了什么以及购买的频率。如果你有这个应用程序,你的报价会有所不同吗?

战略

当评估 Apriori 算法的结果时,结合领域知识,我们可以采用以下策略:

  1. 在工作日上午 12 点前,以低于两者加起来的价格获得您选择的任何热饮(茶、咖啡或热巧克力)和早餐(烤面包、蛋糕、松饼)
  2. 在工作日的下午,买一个三明治,喝茶可以打五折。
  3. 周末,买任意两件,第三件 33 折

为什么?

关于第一点,我们知道,在工作日早晨,几乎所有推动最高提升(销售比率增加)的购买都是热饮和早餐的组合(见下表)。因为我们的结果因饮料和食物类型而异,这个选项足够宽泛,不会限制选择,也不会缩小这个选项的市场。此外,我们知道至少 70%的早上交易都是购买热饮**,这给了我们强大的初始购买基础。**

Apriori results for weekday mornings

对于工作日的下午,我们希望刺激原本不会发生的购买行为。为此,我们将查看具有最高综合升力的项目。结果依次是茶、咖啡和三明治。下午,三明治和茶卖得很好,但它们不常一起买。茶占交易的 17%,三明治占 12%,但它们合起来仅占交易的 2.5%。因此,考虑到茶也很受欢迎,但不是在购买三明治时,我们想要创建购买三明治(更高价值的项目)。我们希望创造这种多产品购买,这在历史上一直是一个单一的购买。

最后,对于周末,我们发现,相对于平日,有更多的多购买交易,推动购买第三个项目。

周末前 10 大购物驱动因素中有 50%是两件商品的前因,相比之下,工作日早上的这一比例为 20%

当有人已经买了两件东西,我们希望他们再买第三件,这在周末似乎更有可能。因此,我们可以想出一个朗朗上口、简单易懂的促销方式,比如“买两件,第三件打 33 折。”

Apriori results for weekends; note the 5 multi-item antecedents in the top 10.

测量结果

为了总结这些发现,我们希望实施这些策略,并在一段时间内测量结果。我们特别想看看上午平均门票大小的变化,下午组合茶和三明治的销售,以及周末每笔交易的商品数量。我们将寻找在每个细分市场中销售的商品数量是否有统计上的显著差异。

如果我们做到了,太好了!我们的策略奏效了,我们可以每隔几个月重新审视购买习惯和产品供应,以确定如何调整折扣和促销。

如果没有,没什么大不了的,我们可以重新设置为无折扣的基本情况,然后重新研究数据并与客户交谈。毕竟,测试和学习是在找到有效方法之前进行迭代和调整的重要方式。

即使它最初显示出积极的结果,战略和执行是持续的。我们不能因为它有效就假设它会永远有效。我们也不能因为它不起作用就认为它不是正确的行动方向。

结论

从分析转移到策略是具有挑战性的,因为你从确定的领域(“我看到这种情况发生”)转移到不确定的领域(“根据我看到的,我认为这种情况会发生”)。也就是说,在一个日益信息化的世界里,对批判性思维和数据解释的需求正在快速增长。

数据与领域专业知识和客户互动相结合,是一种经过检验的方法,可以为战略提供信念,并最终为从面包店到财富 500 强公司的每个人带来更好的业务成果。

如果您有任何想法或反馈,我希望在 jordan@jordanbean.com 或通过 LinkedIn 收到您的来信。

在 AWS 上设置和使用 Jupyter (IPython)笔记本电脑

原文:https://towardsdatascience.com/setting-up-and-using-jupyter-notebooks-on-aws-61a9648db6c5?source=collection_archive---------3-----------------------

If you are having trouble following this tutorial or want to use JupyterHub on AWS, I made an updated tutorial (YouTube, blog).

前阵子写了一个帖子,“在 AWS 上启动一个 Jupyter (IPython)笔记本服务器”。虽然这种方法允许多人只需一个密码就能访问服务器,但设置起来很复杂。大多数人只是想使用 Jupyter 笔记本使用他们的 AWS 资源,没有麻烦。有了这个,你就可以这么做了。

在 AWS 上启动 Jupyter 笔记本

  1. SSH 到您的 EC2 实例。如果你不知道如何做,或者想要参考,请参见本教程

SSH Command used in the Video

2.确保您已经安装了 Anaconda。如果你还没有安装,你可以使用这个教程来安装。

3.在终端中键入以下命令:

jupyter notebook --no-browser --port=8888

Expected Output of running the previous command

我们添加“—无浏览器”的原因是因为如果我们不这样做,您可能会得到类似“Jupyter Notebook 需要 JavaScript”的错误。说了这么多,如果你得到那个错误,你可以通过按Q忽略错误,然后按Y确认。

SSH 到你的 Jupyter 笔记本

4.打开一个新的终端,SSH 到你的 Jupyter 笔记本。您的命令应该类似于下面的命令。如果不知道怎么做,请看教程

ssh -i thisIsmyKey.pem -L 8000:localhost:8888 ubuntu@ec2–34–227–222–100.compute-1.amazonaws.com

-i指定用于公钥认证的备用标识文件。基本上对于本教程,我有我的关键在当前目录。

-L指定本地(客户端)主机上的给定端口将被转发到远程端(AWS)上的给定主机和端口。这意味着无论在 AWS 的第二个端口号(即8888)上运行什么,都会出现在本地计算机的第一个端口号(即8000)上。你应该把8888换成 Jupyter 笔记本运行的端口。99.9%的时间 Jupyter 将在端口 8888 上运行。可选地将端口8000更改为您选择的一个端口(例如,如果8000被另一个进程使用)。

5.打开浏览器,转到 localhost:8000

You should get something similar to this

6.(可选)如果你想使用不同的 conda 环境(包括在 Jupyter 笔记本中同时访问 Python 2 和 Python 3 环境的能力,请参见本教程)。

如果你有任何问题,请在这里,在 youtube 视频页面,或者通过 Twitter 告诉我!

在 AWS 中建立深度学习工作站

原文:https://towardsdatascience.com/setting-up-deep-learning-work-station-in-aws-ac99101bf5de?source=collection_archive---------8-----------------------

这是在 AWS 中设置机器的一步一步的指南,该机器可以执行复杂的深度学习任务,如图像分类或面部识别。

为什么不是我自己的机器

我也有同样的问题,直到我看到运行一个基本图像分类的算法有多慢。像张量流或 Theano 这样的深度学习框架在 CPU 上工作,但它更适合 GPU 计算。与 CPU 相比,算法在 GPU 中运行更快。

关于 CPU 与 GPU 的更多信息:

[## TensorFlow 简介— CPU 与 GPU

在本教程中,我们将在 TensorFlow 中进行简单的矩阵乘法,并将 GPU 的速度与

medium.com](https://medium.com/@erikhallstrm/hello-world-tensorflow-649b15aed18c)

有鉴于此,亚马逊提供了一个每小时 0.90 美元的 GPU 系统,它可以用来运行算法和机器来与所有的预配置。这里是一步一步的信息。

登录 Aws 后,从侧面菜单中选择 Ec2

选择启动实例。亚马逊提供所有必要的软件并维护它。我们可以从 Aws MarketPlace 中选择机器映像

镜像名称:深度学习 AMI 亚马逊 Linux 版

这将为您提供以下屏幕

选择图像,然后单击下一步选择 GPU 计算。

这一步将花费你 0.90 美元。但是有一些有趣的方法可以通过改变训练和测试之间的实例来降低成本。稍后会详细介绍。

您可以单击“下一步”,直到配置安全组,然后添加新安全组。

就是这样!!点击查看并启动。可以配置运行深度学习的机器。

有可能你可能会得到错误说,请求限制超过。您可以向 AWS 提出请求来解决这个问题。

要启动实例,请单击“连接”按钮,并按照说明进行操作。

通过最后一步,你就拥有了一台包含深度学习所需所有东西的机器。要使开发人员工具易于使用,还需要几个步骤。我的意思是,你必须配置 Jupyter 笔记本电脑,以便在外面可以方便地访问。

在命令中连接后,执行以下步骤

代码块的最后一行会生成这样的 SHA 键

sha1:806d 23 d9 C1 c8:2 da 90 b 513 b 6 AE 2 a 941 a 4 bdcf 6843 a3 A0 ea 5a 7

复制并保存在记事本中

然后回到终端类型

vi ~/。jupyter/jupyter _ notebook _ config . py

如果你不是 Vi 人,记住你需要按 I 开始插入内容,当你完成时,你可以点击然后最后退出 Vi esc :wq enter,同时保存你的更改(代表 write-quit)。

将密码更改为您在之前的步骤中复制的生成的 SHA1 密钥。

更新 Keras

Keras 会在 1。x 版本,但是很容易用一个简单的命令升级

sudo pip 安装 keras —升级—无 deps

现在您已经升级了,您可以通过以下方式启动 Jupyter 笔记本

Jupyter 笔记本

这将运行 jupyter 笔记本,可通过公共 IP 在互联网上访问。你可以在下面找到公共 IP

一旦完成,你可以创建一个空的笔记本和类型。

现在这一步已经完成了。你可以创造一个更好的世界。

在 Google Colab 中设置 Kaggle

原文:https://towardsdatascience.com/setting-up-kaggle-in-google-colab-ebb281b61463?source=collection_archive---------6-----------------------

一个简单的新手教程

我要所有的数据,现在就要!

Photo by Logan Fisher on Unsplash

你知道所有这些数据集在哪里,你也知道你想让它们去哪里,但你如何轻松地将你的数据集从 Kaggle 移动到 Google Colab,而没有很多复杂的疯狂?

让我给你看看!

发现快乐是 Google Colab 绝对是我开始深度学习、机器学习和人工智能以来所做的最聪明的事情之一。Google Colab 提供免费 GPU(真的!)卖给几乎所有想要的人。如果你刚刚开始,你需要上 Colab!我写了另一篇文章介绍第一次在 Colab 中设置,但是在 Colab 中设置和运行 Kaggle 真的应该有自己的文章。

Photo by Oscar Söderlund on Unsplash

尽管 Colab 非常用户友好,但在设置时,您可能需要一些细节方面的帮助。

事实证明,Kaggle 就是这些细节之一。

卡格尔需要一点技巧。一点爱。然而,如果你在寻找那些可爱的数据集,你会想要得到它!其实真的很简单;你只需要采取几个简单的步骤。如果您只想查看 GitHub 上的代码,然后继续您的一天(这里的事情可能会变得有点…冗长……),欢迎您这样做!

下面是我发现的第一次访问 Kaggle 数据的最简单方法:

入门

(一个小提示:为了能够访问 Kaggle 数据,你需要注册 Kaggle(免费!)并同意您想要参加的竞赛的条款和条件。)

首先,从卡格尔那里拿到你的令牌。

转到您的帐户页面(屏幕右上角的下拉菜单会带您到那里)。

然后向下滚动到 API 并点击“创建新的 API 令牌”

那就要下载一个名为 kaggle.json 的文件。确保您知道该文件在哪里!也许把它放在你能找到的地方…

只是一个建议。

打开该文件,您会看到类似如下的内容:

{“username”:”YOUR-USER-NAME”,”key”:”SOME-VERY-LONG-STRING”}

为将来的复制和粘贴准备好那个东西!

接下来,去 Colab 开始一个新的笔记本。我非常喜欢立即在 GPU 上运行,为此,请进入“运行时”下拉菜单,选择“更改运行时类型”,然后在“硬件加速器”下拉菜单中选择 GPU。然后点击保存。

接下来,您需要安装 Kaggle。这几乎就像把它安装在你的 Jupyter 笔记本上一样,但是 Colab 希望在你的代码开头有一个感叹号。只需运行:

!pip install kaggle

你可以使用!ls来检查你是否已经有一个名为 Kaggle 的文件夹,或者直接运行

!mkdir .kaggle

去创造一个。

接下来,您需要运行下面的单元格,但是请注意几件事情:

  • 这个没有感叹号
  • 你肯定想把用户名和密码改成你从下载的 Kaggle 文件中复制粘贴的那个!
import jsontoken = {“username”:”YOUR-USER-NAME”,”key”:”SOME-VERY-LONG-STRING”}with open('/content/.kaggle/kaggle.json', 'w') as file:
    json.dump(token, file)

我在运行这段代码时进行了复制粘贴,实际上遇到了一点麻烦。我不知道为什么,但我不得不删除并重新键入上面代码中的单引号,以使该单元格正常运行。如果您莫名其妙地弹出一个错误代码,那就试试吧!

接下来,运行

!cp /content/.kaggle/kaggle.json ~/.kaggle/kaggle.json

然后

!kaggle config set -n path -v{/content}

您将会得到一个类似如下的警告:

您可以通过运行以下命令轻松解决这个问题:

!chmod 600 /root/.kaggle/kaggle.json

在那之后,你应该能跑了

!kaggle datasets list

访问 Kaggle 数据集列表。

如果您正在寻找一个特定的数据集,您可以运行类似

!kaggle datasets list -s sentiment

以便列出例如标题中包含“情感”的数据集。

现在是时候开始享受真正的乐趣了!

下载数据

去 Kaggle,找到你想要的数据集,在那个页面上,点击 API 按钮(它会自动复制代码)。

您将把代码粘贴到下一个单元格中,但是要确保在单元格的开头添加感叹号,并添加-p /content来阐明您的路径。

!kaggle datasets download -d kazanova/sentiment140 -p /content

要解压缩文件,运行

!unzip \*.zip

欢迎来到数据镇!!!想看看吗?尝试跑步:

import pandas as pdd = pd.read_csv('training.1600000.processed.noemoticon.csv')d.head()

(当然,用数据集中的文件名替换上面的文件名。)

现在走出去,创造一些惊人的东西!

Photo by Fidel Fernando on Unsplash

如果有人用他们新得到的数据做了一些非常棒的事情,我想听听他们的想法!请在下面的回复中让每个人都知道你创造了什么,或者随时在 LinkedIn @annebonnerdata 上联系!

你可能也想看看我的其他一些文章!

[## Git 和 GitHub 入门:完全初学者指南

Git 和 GitHub 基础知识,供好奇和完全困惑的人使用(加上最简单的方法来为您的第一次公开…

towardsdatascience.com](/getting-started-with-git-and-github-6fcd0f2d4ac6) [## 如何用 GitHub 毫不费力地免费创建一个网站

GitHub Pages 入门:创建和发布免费作品集的快速简便指南…

towardsdatascience.com](/how-to-create-a-free-github-pages-website-53743d7524e1) [## Google Colab 入门

沮丧和困惑的基本教程

towardsdatascience.com](/getting-started-with-google-colab-f2fff97f594c) [## 深度学习简介

新手、新手和新手的神经网络。

towardsdatascience.com](/intro-to-deep-learning-c025efd92535) [## 如何构建准确率高于 97%的图像分类器

清晰完整的成功蓝图

medium.freecodecamp.org](https://medium.freecodecamp.org/how-to-build-the-best-image-classifier-3c72010b3d55) [## 数据清理和预处理完全初学者指南

如何在几分钟内为机器学习模型成功准备数据

towardsdatascience.com](/the-complete-beginners-guide-to-data-cleaning-and-preprocessing-2070b7d4c6d) [## 出色的模型部署初学者指南

一个清晰简单的路线图,让你的机器学习模型在互联网上,做一些很酷的事情

heartbeat.fritz.ai](https://heartbeat.fritz.ai/brilliant-beginners-guide-to-model-deployment-133e158f6717)

为数据分析设置我的第一个 Amazon Web Services (AWS)虚拟服务器

原文:https://towardsdatascience.com/setting-up-my-first-amazon-web-services-aws-virtual-server-for-data-analytics-4e62db34f874?source=collection_archive---------8-----------------------

今天终于加入了 AWS 的列车。作为我正在为一个客户进行的大数据分析项目的一部分,我需要托管一个云服务器来从 Twitter 和 Google 上挖掘数据,每天将它们保存在一个 CSV 文件中。通常,我会使用我的笔记本电脑作为这项任务的服务器,但由于这是一个商业项目,我可以将成本转嫁给客户,我必须使用一个可靠的负担得起的虚拟服务器。然后我去谷歌上搜索。我不想用微软 Azure,因为我的支付系统有问题,而且我听说 Azure 对于一个非常小的企业来说不是最好的口袋友好型选择。我偶然发现了阿里云服务,但不久我就接受了亚马逊网络服务。

设置真的很容易;比我想象的要容易,因为网上普遍认为 AWS 不像 Azure 那样简单易用。现在经历了这两者,我不同意。

我使用了 EC2 服务并创建了一个 t2-micro Windows Server 2012 R2 实例。

在通过远程桌面连接连接到服务器时,我为我的数据分析工作设置了它。我安装了微软 R OpenRStudio 用于我基于 R 的数据分析工作。我为我基于 Python 的分析工作安装了 AnacondaPyCharm 。下面是我的服务器设置的样子。

我甚至把我常用的工具钉在了任务栏上——Powershell、任务调度器、RStudio 和 PyCharm。

剩下的问题是如何估算我每月的花费,以及我是否需要自动启动/关闭服务器以节省计算时间/成本。启动/关闭决定的某些方面将取决于 Twitter 是否批准我不受限制地访问他们的 Tweet 数据库的请求,并且不收取我一些疯狂的费用。我已经提出了请求,他们要求我向他们提供一些信息,他们将使用这些信息来决定是否批准我的请求。我目前绕过每 15 分钟可以抓取多少条推文的限制的方法是每三个小时运行一次报废脚本,但我仍然认为我没有获得足够多的代表性推文,一些推文不断重复显示。

总的来说,我喜欢深入数据分析的新冒险。我会一直让你们知道我的进步,分享我的学习成果。

最初发表于【www.olafusimichael.com】

在 r 中为文本挖掘设置 Twitter。

原文:https://towardsdatascience.com/setting-up-twitter-for-text-mining-in-r-bcfc5ba910f4?source=collection_archive---------4-----------------------

Photo Credit : Pixabay

介绍

多年来,社交媒体已经成为数据挖掘的热点。每天都有话题趋势、活动进行和人们讨论不同的全球、大陆或国家问题。这是利用数据的一个主要目标。

在这篇文章中,我们把 Twitter 作为全球观点和情感的中心。我们开始从每天发布的数百万条推文中挖掘文本,以便能够理解正在发生的事情,甚至超越我们自己的时间线。

Twitter API 设置

要使用 twitter API,我们需要有一个 twitter 帐户。
通过https://twitter.com注册,前往https://apps.twitter.com/访问 twitter 开发者选项。

Click create New App

创建新的应用程序

**应用程序名称:**给你的应用程序一个唯一的名称。如果被占用,将通知您进行更改。
**应用程序站点:**如果你的应用程序还没有站点,这可以是一个到你的 Github 存储库的链接,应用程序代码就在那里。(像我一样)
回调 URL: 这是一个链接,成功或失败的消息从一个程序中继到另一个程序。它告诉程序在这两种情况下下一步去哪里。您可以将您的应用程序定向到任何可用的端口,我的端口是 1410。

应用凭据

这些对于帮助用户登录应用程序非常重要。
此设置中使用了四种主要凭证。
**消费者密钥:**该密钥向应用程序标识客户端。
**消费者密码:**这是用于服务器验证的客户端密码。
**访问令牌:**这是用来定义用户权限的用户标识。
**访问密码:**这是用访问令牌作为密码发送的。</李>
他们就是这样获得的。

App credentials

Generating Tokens

App Tokens

注意:这些证书应该是保密的,这就是为什么我在我的证书上画了阴影。瞧吧!我们设置了一个 API

r 工作室成立

R 使用了 twitteR 库,这是一个基于 R 的 twitteR 客户端,处理与 Twitter API 的通信。让我们花点时间感谢杰夫·金特里把这个图书馆建起来。

现在继续使用下面的代码安装这个库。

#from CRAN
install.packages(“twitteR”)#alternatively from the Github
library(devtools)
install_github(“geoffjentry/twitteR”)

上述两种方法的区别在于,第一种方法从 CRAN 站点下载包,并接受包名参数,而第二种方法从 GitHub 库安装包,并接受库名参数。点击阅读更多关于软件包和安装的信息

证明

Twitter 使用开放认证(OAuth)来授权访问信息。开放式身份验证是一种基于令牌的身份验证方法。我们来参考一下我们的四个凭据。

第一步

#load library
library(twitteR)#load credentials
consumer_key <- “****************”
consumer_secret<- “*******************”
access_token <- “*******************”
access_secret <- “************************” 

第二步

我们使用 setup_twitter_oauth 函数来设置我们的认证。 setup_twitter_oauth() 函数接收我们从上面设置的 API 生成的四个 twitter 凭证。

 #set up to authenticate
setup_twitter_oauth(consumer_key ,consumer_secret,access_token ,access_secret)

请按键盘上的 Y 键授权直接认证。

查询 Twitter

质疑就是简单地问一个问题。为了能够访问我们需要的数据,我们必须向 twitter 发送有意义的查询。有了 Twitter,我们可以获得从趋势、活动到账户的大量信息。我们有一系列的问题要问。
让我们在这个标签#rstats 上运行查询

#fetch tweets associated with that hashtag , 12 tweets-n in 
#(en)glish-lang since the indicated date yy/mm/ddtweets <- twitteR::searchTwitter(“#rstats”,n =12,lang =”en”,since = ‘2018–01–01’)#strip retweets
strip_retweets(tweets)

这段代码以列表的形式返回推文。 strip_retweets() 函数删除返回的 tweets 中的任何 retweets。

为了进一步分析这些推文,我们将考虑将返回的推文转换为数据帧,并在本地存储它们。

#convert to data frame using the twListtoDF function
df <- twListToDF(tweets)\#extract the data frame save it locally
saveRDS(df, file=”tweets.rds”)
df1 <- readRDS(“mytweets.rds”)

清理推文

通过查询,我们已经设法将结果存储到计算机上的数据框中。现在让我们检查这些数据,找出谁的转发量最高,并直接从我们的脚本中给他们一个大喊。
我们将使用 dplyr 库遍历该数据帧。

 library(dplyr)#clean up any duplicate tweets from the data frame using #dplyr::distinctdplyr::distinct(df1)

让我们利用 dplyr 动词来选择转发次数最多的 tweet 的 tweet、昵称、id 和转发次数,并将结果存储在一个名为 winner 的数据帧中。

winner <-df1 %>% select(text,retweetCount,screenName,id )%>% filter(retweetCount == max(retweetCount))
View(winner)

通过此备忘单查看更多关于 dplyr 的信息。

发送直接信息

为了通知我们的转发竞赛获胜者,我们将通过从获胜者数据帧中选取他们的句柄,从该脚本中向他们发送一条直接消息。
**DM send()**函数接收保存为屏幕名称的消息和用户名。

us <- userFactory$new(screenName= winner$screenName)
dmSend(“Thank you for participating in #rstats,Your tweet had the highest retweets” , us$screenName)

结论

我们刚刚从 twitter 中创建了第一个挖掘数据集,并使用它来找出我们的转发比赛获胜者。嗯,这只是我们能做的一个小例子,然而,有一个专栏包含来自挖掘的推文的文本,可以使用这个博客上以前文章的技术来分析这些文本。

这种挖掘的数据有更多的可能性,如情感分析和词频可视化。
我建议你通过这个 GitHub 查看一个 twitter 文本挖掘的实例。
关于本文的任何进一步的问题和评论,请通过 twitter 问我 @lornamariak
微博挖掘快乐!

在 5 分钟内设置您的数据科学和人工智能开发环境

原文:https://towardsdatascience.com/setting-up-your-data-science-and-ai-dev-environment-in-5-minutes-44804a324713?source=collection_archive---------6-----------------------

Kaggle、TensorFlow、PyTorch、MxNet 等等,只需几步!

Using datmo to get a new TensorFlow project setup in under a minute

无论您是第一次设置 TensorFlow 的数据科学爱好者新手,还是处理万亿数据的经验丰富的人工智能工程师,安装您的库、包和框架总是一场斗争。

虽然像 Docker 这样的容器化工具真正革新了软件的可复制性,但它们还没有在数据科学和人工智能社区中流行起来,这是有充分理由的!随着机器学习框架和算法的不断发展,很难找到时间来学习另一种开发工具,尤其是与模型构建过程没有直接联系的工具。

在这篇博文中,我将向您展示如何使用一个名为datmo的简单 python 包来为任何流行的数据科学和人工智能框架设置环境,只需几个简单的步骤。Datmo 利用 Docker 并简化流程,帮助您快速轻松地运行。

0.先决条件

1.安装 datmo

就像任何 python 包一样,我们可以使用以下命令从您的终端安装 datmo:

$ pip install datmo

2.初始化 datmo 项目

在你的终端中,cd到你想要开始建立模型的文件夹中。然后,输入以下命令:

$ datmo init

然后你会被要求为你的项目取一个名字和描述——你可以随意命名它!

3.开始环境设置

在名称和描述之后,datmo 将询问您是否想要设置您的环境——键入y并按下enter

4.选择系统驱动程序(CPU 或 GPU)

然后,CLI 将询问您的环境需要哪些系统驱动程序。如果你不打算使用 GPU,选择cpu

Select system drivers

5.选择一个环境

接下来,您将从众多预打包环境中选择一个。只需在提示中给出您想要使用的环境的编号或 ID。

Select an environment

6.选择语言版本(如果适用)

根据您计划使用的语言和版本,上面的许多环境都有不同的版本。

例如,在选择了keras-tensorflow环境后,我会看到下面的提示,询问我是想使用Python 2.7还是Python 3.5

Select a language version

7.启动您的工作区

您已经正确选择了您的环境,现在是时候启动您的工作区了。选择您想要使用的工作区,并在您的终端中输入相应的命令。

Jupyter 笔记本— $ datmo notebook

木星实验室— $ datmo jupyterlab

RStudio — $ datmo rstudio(在 R-base 环境中可用)

终端— $ datmo terminal

Opening a Jupyter Notebook and importing TensorFlow

你已经准备好了!第一次为新环境初始化工作空间时,需要花费一些时间来获取所有的资源,但是在连续运行时会明显加快。

一旦您的工作空间启动,您就可以开始导入包含在您选择的环境中的包和框架了!例如,如果用户选择了keras-tensorflow环境,那么import tensorflow将在您的 Jupyter 笔记本中开箱即用!

如果你正在使用 TensorFlow,你可以试试 datmo 文档中的这个例子来运行你的第一个 TensorFlow 图。

感谢您的阅读,我们希望您的软件环境设置变得更加简单!

我们的使命是最大限度地利用数据科学家从事数据科学的时间。

如果你想帮忙投稿、报告问题或请求功能,你可以在 GitHub 这里找到我们

为 AI 设置 Visual Studio 代码工具

原文:https://towardsdatascience.com/setting-up-your-visual-studio-code-tools-for-ai-76c89f3d6e3e?source=collection_archive---------3-----------------------

微软刚刚在去年 9 月的微软 Ignite 2017 上推出了一套与人工智能相关的新工具,其中一个工具就是Visual Studio Code Tools for AI

Visual Studio Code Tools for AI是一个构建、测试和部署深度学习/人工智能解决方案的扩展。它与 Azure Machine Learning 无缝集成,提供强大的实验功能,包括但不限于向不同的计算目标透明地提交数据准备和模型训练作业。

对于需要开发人工智能解决方案的开发人员来说,这实际上是一个有用的工具,同时仍然使用他们选择的代码编辑器,在我的例子中是 Visual Studio 代码。

入门指南

在我们真正开始用 VS 代码安装和设置扩展之前,我们首先需要创建一个 Azure 机器学习实验帐户和 Azure 机器学习模型管理帐户,这将允许我们稍后在 VS 代码中使用 sample explorer 创建一个项目。

登录到 Azure 门户网站

第一步是在 portal.azure.com 的登录你的 Azure 账户。如果你没有 Azure 账户,你可以点击这里获得免费试用。

创建一个 Azure 机器学习实验和模型管理帐户

进入 Azure 门户后,请执行以下操作:

  1. 点击“+新建”按钮
  2. 搜索“机器学习实验”

3.点击“创建”

4.填写机器学习实验信息

5.单击“Create ”,您应该能够看到服务已成功创建

要记住的事情:

  1. 如果您还没有“创建模型管理帐户”,请确保选中该帐户。
  2. “座位数”基本上是你可以添加到你的实验账户的 Azure 用户总数。
  3. 一个套餐只能有一个“DevTest”定价层的计划。
  4. 目前支持的位置是澳大利亚东部、美国东部 2 和美国中西部。

安装 Azure 机器学习工作台

一旦我们有了 Azure 机器学习实验和模型管理帐户设置,接下来我们要做的就是安装 Azure 机器学习工作台。

Azure Machine Learning work bench是一个桌面应用程序加上命令行工具,在 Windows 和 macOS 上都受支持。它允许您在整个数据科学生命周期中管理机器学习解决方案。

目前,Azure 机器学习工作台桌面应用程序只能安装在以下操作系统上:

  • Windows 10
  • Windows Server 2016
  • macOS Sierra(尚不支持 macOS High Sierra)

注意:Azure Machine Learning Workbench 还将下载并安装其他相关组件,如 Python、Miniconda、Azure CLI 等。

要安装 AML 工作台,您可以单击最近创建的机器学习实验服务,您应该能够看到以下内容:

然后,您只需点击您正在使用的特定操作系统,将安装程序下载到您的机器上。

注意:对于 macOS,在安装 AmlWorkbench 安装文件之前,首先需要使用自制软件安装openssl库。

$ brew install openssl
$ mkdir -p /usr/local/lib
$ ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/
$ ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/

在 Visual Studio 代码工具中安装和浏览项目示例

现在我们已经有了 Azure 机器学习帐户和 Azure 机器学习工作台设置,我们现在准备好为 AI 使用 Visual Studio 代码工具了

  1. 在这里下载 AI 扩展的 Visual Studio 代码,或者你可以在 VS 代码中的扩展上搜索它。
  2. 安装完成后,重启 VS 代码
  3. 打开命令调板(Windows 中的 CTRL + SHIFT + P 或 macOS 中的 COMMAND-P)
  4. 键入" > AI:Azure ML-log in ",这将在终端中显示一条消息,让您打开浏览器并输入提供的代码

5.一旦你成功登录你的账户,再次打开命令面板,输入" > AI:打开 Azure ML 样本浏览器"

注意:有时当您输入“AI: Open Azure ML Sample Explorer”命令时,VS 代码中没有发生任何事情,当您再次尝试输入该命令时,该命令将不会显示在命令调板中。要修复这个问题,只需重新启动 VS 代码,您应该能够再次看到该命令。

在 Azure 机器学习示例资源管理器中创建新项目

现在,我们将尝试使用 sample explorer 创建一个简单的项目,并在本地机器上测试它。

  1. 点击"安装"到简单线性回归项目
  2. 输入项目名称
  3. 进入项目安装文件夹
  4. 输入我们刚才使用 Azure 创建的帐户和工作区
  5. 成功创建项目后,您将能够看到以下文件:

6.您也可以检查readme.md文件,以了解正确运行项目所需安装的包。在这种情况下,我们必须安装matplotlib

# For macOS
$ pip3 install matplotlib# For Windows
$ conda install matplotlib 

提交作业并在本地训练模型

一旦我们安装了matplotlib包,我们现在将提交一个任务在本地训练模型。

  1. 你可以右击linear_reg.py文件,点击“AI:提交作业”

2.或者,你可以再次打开linear_reg.py,打开命令面板,输入“AI:提交作业”

3.确保选择“本地”作为您的配置

4.提交作业,您应该能够在终端中看到输出

那么你怎么看待 Visual Studio 的 AI 代码工具呢?就个人而言,当提交作业或准备将用于训练模型的数据时,我更喜欢使用 Azure Machine Learning Workbench,因为它对作业发生的事情有更好的可视化。以下是您在 AML Workbench 中运行任务时的情况:

如果你想了解更多关于 Visual Studio Code Tool for AI 的信息,你可以查看他们的 GitHub 库这里,如果你也对 AML Workbench 感兴趣,你也可以查看他们的文档这里

使用 Sparklyr 设置种子值

原文:https://towardsdatascience.com/setting-your-seed-value-with-sparklyr-56dba13b15f?source=collection_archive---------12-----------------------

几个月前,我做了一个关于可重复研究的雄心勃勃的报告。本演示的一部分包括演示如何使用 R 和 Sparklyr 包分析 Spark cluster 上的数据。

当您接受数据科学家培训时,您首先要学习的事情之一是设置一个种子值。设置种子位于创建预测模型时运行的每个脚本的顶部。写那一行代码变得反射性和第二天性,以至于你可能会忘记为什么要写它。

你写它是为了可复制性。我不会深入讨论如何和在哪里,但是任何时候你可能必须生成随机数,你要确保如果别人运行你的脚本,他们得到相同的结果。由于预测建模算法大量使用随机数发生器,所以你必须在你做的几乎每个项目中播种。通过运行下面的示例代码,可以看到 set seed 的效果。

当我为我的演示构建 Sparklyr 示例代码时,我尽职尽责地用我以前无数次做过的方式设置了种子。然而,这一次,我不太确定我是否应该这样做。我看到的示例代码没有在任何地方设置种子。我认为这只是一个疏忽,但我不确定。因为我是习惯的奴隶,所以我把它留在了家里。

在展示的那天晚上,一位火花专家在人群中。我知道她每天都和 Sparklyr 一起工作,所以我邀请她随时参与进来。果不其然,她指出 set seed 与 Spark 的工作方式并不像我想象的那样。后来,我们就这个问题进行了热烈的讨论;最重要的是,我们都不知道为什么它不起作用。

让我们回到几天前:我正在准备另一个讲座,这次是专门关于 Sparklyr 的。我想检查一下 set seed 的问题是否已经解决。我用谷歌搜索了这个问题,用了各种我认为会有所收获的关键词,但什么也没找到。然后,我做了任何一个有自尊的工程师都会做的事,走向了 Stackoverflow。

你可以在这里看到帖子,但是我想把答案和提问的背景放在一起。 user6910411 很好地给了我一个全面的回答,我会在这里完整地分享。

TL;DR:当你在 R 中使用 Spark 时,你在两个不同的地方工作——你的本地机器和 Spark 集群。set seed 在您的本地机器上。要在群集上设置种子,请使用 Sparklyr 函数中的参数。

一般来说,set.seed 在它应该在的地方工作得很好——在本地 R 会话中,也称为驱动程序(您调用 spark_connect 的地方)。它不起作用,而且由于许多原因,它不能跨执行器工作,包括不同的执行上下文(R、JVM)和/或不同的环境(使用 spark_apply 这样的方法)。

带火花包装器:

用 ml_*或者 ft_ 等方法。种子由 Spark 设置,通常使用种子参数公开。例如 ml_kmeans:

也可以为 RNG SQL 函数设置种子:

带执行器端 R 代码

据我所知,目前还没有任何选择。跨多台机器正确设置 RNG 种子将需要 API 来访问低级任务信息,并且即使假设没有其他不确定性来源,在异构环境中也可能是脆弱的。

然而

RNG 状态不是分布式系统中非确定性行为的唯一来源。因为在 Spark 中一般不保证任何特定的执行顺序,所以不同运行之间的结果可能不同,即使 RNG 状态设置正确。

总体:

如果你的目标是可重复的研究,你可能仍然可以使用 Spark,但它需要一个防御性的编程,有意识地建立集群,这不是你可以用内置工具做的事情,更不用说像 sparklyr 这样有限的高级包装器了。

在您的个人电脑上设置数据科学环境

原文:https://towardsdatascience.com/setup-a-data-science-environment-on-your-personal-computer-6ce931113914?source=collection_archive---------5-----------------------

了解在本地计算机上使用 Python、R、Git 和 Unix Shell 设置数据科学环境的各种选项。

在像 Datacamp 这样的在线交互式培训和教育平台上学习之后,下一步就是利用在 Python、R、Git 或 Unix Shell 中获得的技能,并在本地计算机上使用它。要知道你想要的各种项目需要安装什么并不总是容易的。本教程将让你知道你需要安装什么包,什么软件来开始使用各种技术。本教程将包括:

  • Anaconda Python 发行版的好处以及如何在您的操作系统上安装它。
  • 一起使用 R 和 RStudio 的好处以及如何在您的操作系统上安装它们。
  • Unix Shell 的优点以及如何在您的操作系统上使用它。
  • 使用 Git 的好处以及如何在您的操作系统上安装它。

就这样,让我们开始吧!

计算机编程语言

为了能够在本地计算机上使用 Python,首先需要安装它。有许多不同的 python 发行版,但是对于数据科学来说,Anaconda Python 发行版是最受欢迎的。

蟒蛇的好处

Anaconda 是一个包管理器、环境管理器和 Python 发行版,其中包含许多开源包的集合。Anaconda 的安装附带了许多软件包,如预装的 numpy、scikit-learn、scipy 和 pandas,这也是安装 Jupyter 笔记本的推荐方式。下图显示了 Jupyter 笔记本电脑的使用情况。Jupyter 笔记本包含代码和富文本元素,如图形、链接和等式。你可以在这里了解更多关于 Jupyter 笔记本的信息。

Anaconda 的其他一些好处包括:

  • 如果在安装 Anaconda 之后需要额外的包,可以使用 Anaconda 的包管理器 conda 或 pip 来安装这些包。这是非常有利的,因为您不必自己管理多个包之间的依赖关系。Conda 甚至可以轻松地在 Python 2 和 3 之间切换(你可以在这里了解更多)。
  • Anaconda 附带 Spyder,这是一个 Python 集成开发环境。集成开发环境是一种编码工具,它允许您编写、测试和调试您的代码,因为它们通常提供代码完成、通过突出显示的代码洞察力、资源管理和调试工具以及许多其他功能。还可以将 Anaconda 与其他 Python 集成开发环境(包括 PyCharm 和 Atom)集成在一起。您可以在这里了解更多关于不同 Python 集成开发环境的信息。

如何安装 Anaconda (Python)

下面是一些关于如何在您的操作系统上安装 Anaconda 的指南的链接。

在 Mac 上安装 Anaconda

在 Windows 上安装 Anaconda

r 编程语言

大多数人一般会将 RStudio 和 R 编程语言一起安装。RStudio 集成开发环境(IDE)通常被认为是使用 R 编程语言的最简单、最好的方式。

RStudio 的优势

R 编程语言的安装为您提供了一组来自 R 语言的函数和对象,以及一个允许您构建和运行命令的 R 解释器。RStudio 给你一个集成的开发环境,它与 R 解释器一起工作。

当您打开 RStudio 时,会出现如上图所示的屏幕。四个 RStudio 窗格中包含的几个功能是:(A)文本编辑器。(B)工作环境仪表板。(C)口译员。(D)帮助窗口和包管理系统。所有这些特性使得 RStudio 成为你在安装 r。

您可以在 Datacamp 的两个课程系列中了解更多有关 RStudio 的有用功能,使用 RStudio IDE ( 第 1 部分第 2 部分)。

如何安装 R 和 RStudio

以下是一些关于如何在您的操作系统上安装 R 和 RStudio 的指南链接。

在 Mac 上安装 R 和 R studio

在 Windows 上安装 R 和 R studio

Unix Shell

导航目录、复制文件、使用虚拟机等等是数据科学家工作的一部分。您经常会发现 Unix Shell 被用来完成这些任务。

Unix Shell 的一些用途

  1. 许多云计算平台都是基于 Linux 的(利用一种 Unix Shell)。例如,如果你想在 Google Cloud 上建立一个数据科学环境,或者在 Cloud (AWS EC2)中用 Jupyter 笔记本进行深度学习,这需要一些 Unix Shell 知识。有时候你可能会用到一个 Windows 虚拟机,但这并不常见。
  2. Unix Shell 提供了许多有用的命令,例如:wc命令,用于计算文件中的行数或字数;cat命令,用于连接/合并文件;headtail命令,用于帮助您选择大文件的子集。您可以在 8 用于数据科学的有用 Shell 命令中了解更多信息。
  3. 您将经常发现 Unix Shell 与其他技术集成在一起,您将在本文的其余部分看到这一点。

与其他技术的集成

您经常会发现 Unix Shell 命令集成在其他技术中。例如,在 Jupyter 笔记本中,经常可以在 Python 代码旁边找到 shell 命令。在 Jupyter Notebook 中,您可以通过使用!切换到 shell 来访问 shell 命令。在下面的代码中,shell 命令ls(列出当前目录中的所有文件)的结果被分配给 Python 变量 myfiles。

myfiles = !ls

下图显示了一些集成在工作流中的 Python 代码,用于组合多个数据集。请注意集成在 Jupyter 笔记本中的 Unix Shell 命令(包含在红色矩形中)。

请记住,上图中的代码并不是完成某项任务的独特方式,而只是您可能看到的 Unix 使用情况的一个小例子。如果你想学习如何使用 Unix 进行数据科学,Datacamp 有一门免费的课程介绍 Shell for Data Science 我推荐。这是一项被许多有抱负的数据科学家遗忘的技能,但在工作场所却是一项非常重要的技能。

Mac 上的 Unix Shell

Mac 自带 Unix 外壳,所以你通常不需要安装任何东西!重要的一点是,有各种各样的 Unix 系统有不同的命令。有时候你会发现你没有在另一个 Unix 系统上找到的 Unix 命令(比如wget)。类似于你如何通过 RStudio 和 Anaconda 拥有包管理器,Mac 可以拥有一个名为 Homebrew 的包管理器,如果你安装的话。下面的链接介绍了如何安装和使用家酿。

如何安装和使用家酿

Windows 上的 Unix Shell 命令

Windows 不附带 Unix Shell。请记住,Unix Shell 为您做的是为数据科学提供有用的命令。有许多不同的方法可以在 Windows 上获得这些有用的命令。您可以使用可选的 Unix 工具在 Windows 上安装 Git,这样您就可以在命令提示符下使用 Unix 命令。或者,你可以在 Windows 上安装Gnu(GOW)(10mb)Cygwin(100 MB),还有许多其他选项。

饭桶

Git 是使用最广泛的版本控制系统。版本控制系统记录一段时间内对一个文件或一组文件的更改,以便您可以在以后调用特定的版本。Git 是一项重要的技术,因为它真的能帮助你与他人合作,而且你会在很多工作场所发现它。学习 Git 的一些好处包括:

  • 使用 Git 控制的版本不会丢失,所以您可以随时查看程序的以前版本。
  • 当您的工作与他人的工作发生冲突时,Git 会通知您,因此很难(但不是不可能)意外覆盖工作。
  • Git 可以同步不同人在不同机器上完成的工作,因此它可以随着您的团队的发展而扩展。
  • 了解 Git 有助于用 R 和 Python 对包进行开源开发。

与其他技术的集成

Git 的一个很酷的地方是你经常会发现它与其他技术集成在一起。前面我提到过,RStudio 集成开发环境(IDE)通常被认为是使用 R 编程语言的最佳方式。RStudio 提供版本控制支持,大多数 Python 集成开发环境(IDE)都提供版本控制支持。

如果你想学习如何将 Git 用于数据科学,DataCamp 有一门免费课程介绍 Git 用于数据科学,我强烈推荐。

如何安装 Git

这里有一些关于如何在你的操作系统上安装 Git 的链接。

在 Mac 上安装 Git

在 Windows 上安装 Git

结论

本教程提供了一种在本地计算机上设置本地数据科学环境的方法。需要强调的重要一点是,这些技术可以而且经常集成在一起。如果你对本教程有任何问题或想法,欢迎在下面的评论中或通过 Twitter 联系我们。此外,请随意查看我的其他基于安装的教程,它们位于我的 Github 或我的媒体博客上。

原载于

为机器学习和深度学习设置 Python 环境

原文:https://towardsdatascience.com/setup-an-environment-for-machine-learning-and-deep-learning-with-anaconda-in-windows-5d7134a3db10?source=collection_archive---------1-----------------------

在过去的十年里,人们对机器学习和深度学习的兴趣激增。你会在计算机科学项目、行业会议和日常生活中的许多应用中看到机器学习。

我假设你已经知道机器学习,因此我不会解释什么和为什么。

因此,我发现许多初学者在安装库和设置环境时面临问题。当我第一次尝试的时候。所以这个指南完全是给新手看的。

在这个故事中,我将告诉您如何在您的系统上轻松设置 python 环境。我用的是 Windows,但是这个指南也适合 Ubuntu 和 Linux 用户。

完成本教程后,你将拥有一个工作的 Python 环境,开始学习和开发机器学习和深度学习软件。

PC 硬件设置

首先,要在任何数据集上执行机器学习和深度学习,软件/程序需要足够强大的计算机系统来处理必要的计算能力。因此,需要满足以下条件:

  1. 中央处理器(CPU) —英特尔酷睿 i5 第六代处理器或更高。AMD 同等处理器也是最佳选择。
  2. RAM —最低 8 GB,建议 16 GB 以上。
  3. 图形处理器(GPU) — NVIDIA GeForce GTX 960 或更高。AMD GPUs 无论如何都无法进行深度学习。有关用于深度学习的 NVIDIA GPUs 的更多信息,请访问https://developer.nvidia.com/cuda-gpus
  4. 操作系统 — Ubuntu 或者微软 Windows 10。我建议在继续之前将 Windows 10 更新到最新版本。

注:对于笔记本电脑,理想的选择是从任何合适的供应商处购买游戏笔记本电脑,如外星人、华硕、联想军团、宏碁掠夺者等。

让我们直接进入安装过程。我们要撞上岩石了😉

Nvidia GeForce 体验

该工具旨在更新您的 NVIDIA GPU 驱动程序,这样做要容易得多,如果您有 NVIDIA GPU,强烈建议安装该工具。

下载 NVIDIA GeForce 体验

目录

在本教程中,我们将介绍以下步骤:

  1. 下载蟒蛇
  2. 安装 Anaconda & Python
  3. 启动并更新 Anaconda
  4. 安装 CUDA 工具包& cuDNN
  5. 创建一个 Anaconda 环境
  6. 安装深度学习 API(tensor flow 和 Keras)

步骤 1:下载 Anaconda

在这一步中,我们将为您的平台下载 Anaconda Python 包。

Anaconda 是科学 Python 的一个免费且易于使用的环境。

  • 1.安装 Anaconda (Python 3.6 版本)下载

我用的是 Windows,你可以根据你的操作系统来选择。

步骤 2:安装 Anaconda

在这一步中,我们将在您的系统上安装 Anaconda Python 软件。

下载安装程序后,安装非常简单快捷。打开设置并按照向导说明进行操作。

#注: 它会自动用它安装 Python 和一些基础库。

根据您的系统,这可能需要 5 到 10 分钟或更长时间。

步骤 3:更新 Anaconda

打开 Anaconda 提示符,键入以下命令。不要担心,Anaconda 提示符和 cmd 是一样的。

**conda update conda
conda update --all**

步骤 4:安装 CUDA 工具包& cuDNN

  1. 安装 CUDA 工具包 9.0 或 8.0 下载

根据您的操作系统和 GPU 选择您的版本。

#版本支持: 这里有一个检查你的版本是否支持你的 Nvidia 显卡的指南

要下载其他版本,你可以点击这个链接:https://developer.nvidia.com/cuda-toolkit-archive

#注: 由于 TensorFlow 与 CUDA Toolkit 9.1 和 9.2 版本不兼容,建议使用 CUDA 9.0。请根据您的 Nvidia GPU 版本选择 CUDA 版本,以免出错。

**#注:**9.0 版本的人下载也可以在进行过程中出现错误的情况下安装给定的补丁。

2.下载 cuDNN 下载

下载 cuDNN 的最新版本。根据您的操作系统和 CUDA 选择您的版本。需要注册会员。别担心,您可以使用您的电子邮件轻松创建一个帐户。

将解压后的文件夹放入 c 盘,如下所示:

**C:\cudnn-9.0-windows10-x64-v7**

步骤 5:将 cuDNN 添加到环境路径中

  1. 使用( Win + R) 打开运行对话框,运行命令 sysdm.cpl
  2. 在窗口-10 系统属性中,请选择高级选项卡。
  3. 选择环境变量
  4. 将以下路径添加到您的环境中。
**C:\cudnn-9.0-windows10-x64-v7\cuda\bin**

步骤 6:创建一个 Anaconda 环境

在这里,我们将为我们的特定用途创建一个新的 anaconda 环境,以便它不会影响 Anaconda 的根。太神奇了!!不是吗?😛

打开 Anaconda 提示符,键入以下命令。

  1. 通过调用以下命令,创建一个名为“tensorflow”的 conda 环境(可以更改名称):
**conda create -n tensorflow pip python=3.6**

2.通过发出以下命令激活 conda 环境:

**activate tensorflow**
 (tensorflow)C:>  # Your prompt should change

第七步:安装深度学习库

在这一步,我们将安装用于深度学习的 Python 库,具体来说:TensorFlow,和 Keras。

  1. 张量流

TensorFlow 是机器学习的工具。虽然 TensorFlow 包含广泛的功能,但它主要是为深度神经网络模型设计的。

= >要安装 TensorFlow,请打开 Anaconda 提示符,键入以下命令。

要安装 TensorFlow 的 GPU 版本:

C:\> **pip install tensorflow-gpu**

要安装 TensorFlow 的纯 CPU 版本:

C:\> **pip install tensorflow**

如果您的机器或系统是唯一受支持的 CPU,您可以安装用于基本学习和练习的 CPU 版本。

= >您可以通过在 shell 上运行此程序来测试安装:

**>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello))**

关于入门和文档,您可以访问tensor flow网站。

2.

Keras 是一个高级神经网络 API,用 Python 编写,能够在 TensorFlowCNTKTheano 之上运行。

= >要安装 Keras,请打开 Anaconda 提示符,键入以下命令。

**pip install keras**

= >我们运行 Mnist_Mlp 试试。Py 在你的提示下。你也可以使用其他例子

打开 Anaconda 提示符,键入以下命令。

**activate tensorflow
python mnist_mlp.py**

关于入门和文档,您可以访问Keras网站。

下面是我用 Python 实现的数字识别的 Keras 标准全连接神经网络

还有其他一些著名的库,如 Pytorch、Theano、Caffe2 等,你可以根据自己的选择和用途来使用。

恭喜你!😉您已经在 Windows 上使用 TensorFlow,Keras(带 Tensorflow 后端)通过 GPU 成功创建了环境!

如果你喜欢这个故事,请点击👏按钮并分享,以帮助其他人找到它。你也可以给我买杯咖啡帮我给你写更多有趣的内容!

用熊猫重塑你的数据的七个简洁步骤或者我如何在 Excel 失败的地方使用 Python

原文:https://towardsdatascience.com/seven-clean-steps-to-reshape-your-data-with-pandas-or-how-i-use-python-where-excel-fails-62061f86ef9c?source=collection_archive---------0-----------------------

概念:多级索引、旋转、堆叠、应用、lambda 和列表理解

用熊猫重塑数据是什么样子的…

用熊猫重塑数据是什么感觉……

几周前,一位同事发给我一份电子表格,里面有关于公共卫生干预的数据,由许多选项卡组成,每个组织一个选项卡。任务是开发一个灵活的仪表板来研究这些数据。问题是数据是宽格式的,但我们需要长格式。以前,这可能只是另一个复制粘贴的手动任务和其他非常长且重复的任务,但是我决定使用 Python 的 Pandas 库来自动化这项任务,所以我开始开发脚本。不到 30 分钟,我就有了灵活的、可重用的代码,这为我节省了数小时不必要的手工劳动!

我想和你分享我的过程,以防它出现在你自己的工作中。我还将展示一些技巧,并详细解释方法。当然,我已经对数据进行了净化,并为隐私生成了伪数字,但是要处理的格式和概念仍然是相同的。这是我们将如何对待熊猫的路线图:

  1. 设置环境并加载数据
  2. 调查数据
  3. 解析不同的数据标签
  4. 标准化现有列并创建新列
  5. 使用“应用”和“λ”功能清理数据
  6. 通过旋转多级索引和堆叠将数据从宽到长整形
  7. 连接并将最终结果保存回 Excel

我们还将把它包装成一个简洁的函数,可以重用这个函数来自动执行这个任务并节省时间。我已经在我的 github 账户上发布了代码和数据。此外,请查看https://tichmangono.com/了解更多关于机器学习、Python 和公共卫生的想法。我们开始吧!

1.设置环境并加载数据

正如广告所说,我们只需要一个 Python 库来执行这个任务:Pandas!我们的数据是一个带有几个选项卡的 Excel 文件。我喜欢使用 Pandas 的 ExcelFile 对象功能,而不是 read 命令,因为它可以很好地处理多选项卡电子表格。

*# Import the relevant libraries...*
*# By the way, I am using Python 3*
**import** **pandas** **as** **pd**
*# Load the raw data using the ExcelFile object*
data = pd.ExcelFile('reshaping_data.xlsx')

2.调查数据

文件中有四个选项卡,每个选项卡代表一个组织的数据。

*# First, see the sheetnames available*
data.sheet_names Output: ['ABC_inc', 'HIJ_inc', 'OPQ_inc', 'XYZ_inc']

解析 ABC_inc organization 的第一个选项卡,我们可以看到,在将该格式用作标准数据框之前,还需要做一些工作。该数据包含公共卫生干预的目标。我们可以看到我们的列标题名称从第 6 行开始,并且我们有关于位置的信息(地区、省);参与的实体(合作伙伴、资金来源);以及目标年份(2017 年至 2020 年)。还要注意第 7 行是如何在数据中为每年的干预提供目标年龄组的额外信息的。数据主体从第 8 行开始向下。

*# Take a peek at the first 10 rows of the first tab*
data.parse(sheetname='ABC_inc', skiprows=0).head(10)

3.解析不同的数据选项卡

列出你的目标标签名。在我们的案例中,我们想要所有的。但是,如果您只想对其中的 2 个进行分析,那么您可以很容易地指定一个不同的列表。

tabnames = data.sheet_names

由于这些选项卡具有相似的格式,因此在本演示中我们将只使用其中的一个。最后,我们将把所有步骤合并成一个单一的、可重用的函数,并使用迭代将该函数应用于所有目标选项卡。然后我们将连接并保存结果。因此,将选项卡解析成数据帧 df,跳过顶部无用的空行。我总是使用“data.head()”来检查我的结果,并确保我的代码如我所愿。

i = 0
df = data.parse(sheetname=tabnames[i], skiprows=7)
df.head(2)

4.标准化现有列并创建新列

列出默认的列。我们将丢弃一些,但也会去掉其余的,以获得用于新列名的信息。我们需要保留特定年份、年龄组和组织的信息。

*# make a list of the header row and strip up to the 4th letter. This is the location and year information*
cols1 = list(df.columns)
cols1 = [str(x)[:4] **for** x **in** cols1]*# make another list of the first row,this is the age group information*
*# we need to preserve this information in the column name when we reshape the data* 
cols2 = list(df.iloc[0,:])
cols2 = [str(x) **for** x **in** cols2]*# now join the two lists to make a combined column name which preserves our location, year and age-group information*
cols = [x+"_"+y **for** x,y **in** zip(cols1,cols2)]
*# Assign new column names to the dataframe*
df.columns = cols
df.head(1)

*# Drop empty columns, Rename the useful columns*
*# Note when you drop, you should specify axis=1 for columns and axis=0 for rows*
df = df.drop(["Unna_nan"], axis=1).iloc[1:,:].rename(columns=    {'dist_nan':'district',                                              'prov_nan': 'province',                                                   'part_nan':'partner',                                                   'fund_nan':'financing_source'})df.head(2)

*# Engineer a new column for the organization, grab this name from the excel tab name*
*# This should read 'ABC inc' if executed correctly*
df['main_organization'] = tabnames[i].split("_")[0] + " "+ tabnames[i].split("_")[1]
df.main_organization.head(2)**Output:**
1    ABC inc
2    ABC inc
Name: main_organization, dtype: object

让我们暂停一下,看看目前为止我们的数据帧的结构。

df.info()

我们看到总共有 29 列。然而,目前,它们都具有“对象”数据类型,我们知道其中一些应该具有数字数据类型。我们还有冗余的“总计”列。请注意,列名仍然保留了多级信息,即特定列中的数据所属的年份和年龄组!这是本练习的一个关键方面,我们将在下一步中看到。在此之前,让我们稍微清理一下…

5.使用“应用”和“λ”函数清理数据

让我们删除更多的冗余列,并更改数据类型。

*# Make lists of the columns which need attention and use this as reference to execute*
*# You will notice that I use list comprehension every time I generate an iterable like a list or dictionary*
*# This is really amazing python functionality and I never want to go back to the old looping way of doing this!*
to_remove = [c **for** c **in** df.columns **if** "Total" **in** c] *# redundant*
to_change = [c **for** c **in** df.columns **if** "yrs" **in** c] *# numeric**# drop unwanted columns*
*# Notice that you need to specify inplace, otherwise pandas will return the data frame instead of changing it in place*
df.drop(to_remove, axis=1, inplace= **True**) *# Change the target column data types*
**for** c **in** to_change:
    df[c] = df[c].apply(**lambda** x: pd.to_numeric(x))

查看变化:

df.info()

看来成功了!

6.通过旋转多级索引和堆叠,从宽到长地重塑数据

现在,我最喜欢的部分——重塑数据!当涉及到数据时,这个功能给了你如此大的力量。鉴于电子表格和调查类型的数据在我的工作中非常流行,我经常使用它来清理和操作数据。对我来说,重塑数据就像是粘土,我正在亲手塑造它:)。因此,我们将在战略索引上使用旋转,然后使用堆叠来实现我们想要的形状。目前,数据是一种宽格式,但我们需要将其更改为长格式,以便我们可以轻松地将其传输到 Excel,长格式可以非常轻松地快速创建数据透视表和仪表板。

*# First, select the columns to use for a multi-level index. This depends on your data*
*# Generally, you want all the identifier columns to be included in the multi-index* 
*# For this dataset, this is every non-numeric column*
idx =['district','province','partner','financing_source'
,'main_organization']*# Then pivot the dataset based on this multi-level index* 
multi_indexed_df = df.set_index(idx)
multi_indexed_df.head(2)

在我们战略性设计的多级索引上旋转数据框后,我们现在将堆叠所有的数字列。这将使我们能够灵活地将数据恢复到我们希望的水平,就像 Excel 数据透视表一样。

*# Stack the columns to achieve the baseline long format for the data*
stacked_df = multi_indexed_df.stack(dropna=**False**)
stacked_df.head(25) *# check out the results!*

介意。吹了!我第一次看到这个的时候也是这种感觉。

*# Now do a reset to disband the multi-level index, we only needed it to pivot our data during the reshape*
long_df = stacked_df.reset_index()
long_df.head(3)

请注意,“level_5”列包含两条信息。这是从一开始就故意做的,以便在删除一些列和行时不会丢失任何信息。现在,让我们使用字符串操作来分离它们,然后删除任何冗余。

*# Make series of lists which split year from target age-group*
*# the .str attribute is how you manipulate the data frame objects and columns with strings in them*
col_str = long_df.level_5.str.split("_") 
col_str.head(3)**Output:**
0    [2017, 10-14yrs]
1    [2017, 15-29yrs]
2    [2017, 30+yrs]
Name: level_5, dtype: object*# engineer the columns we want, one columns takes the first item in col_str and another columns takes the second* 
long_df['target_year'] = [x[0] **for** x **in** col_str] 
long_df['target_age'] = [x[1] **for** x **in** col_str]
long_df['target_quantity'] = long_df[0] *# rename this column*
long_df.head(2)

*# drop the now redundant columns*
df_final = long_df.drop(['level_5', 0], axis=1)
df_final.head(2)

7.连接并将最终结果保存回 Excel

现在我们有了所有需要的成分,我们可以定义一个函数来自动调整形状,使用迭代将这个函数应用到我们想要的任意数量的选项卡上,然后最后将它保存到我们选择的电子表格中!请注意,在函数中,我组合了形状并添加了一个断言来检查输入是否正确,但代码基本相同。

*# Now define a function for doing the reshape*
**def** ReshapeFunc(excel_obj, i):
    *""" Takes in an excel file object with multiple tabs in a wide format, and a specified index of the tab to be parsed and reshaped. Returns a data frame of the specified tab reshaped to long format"""*

    tabnames = data.sheet_names
    **assert** i < len(tabnames), "Your tab index exceeds the number of available tabs, try a lower number" 

    *# parse and clean columns*
    df = excel_obj.parse(sheetname=tabnames[i], skiprows=7)
    cols1 = [str(x)[:4] **for** x **in** list(df.columns)]
    cols2 = [str(x) **for** x **in** list(df.iloc[0,:])]
    cols = [x+"_"+y **for** x,y **in** zip(cols1,cols2)]
    df.columns = cols
    df = df.drop(["Unna_nan"], axis=1).iloc[1:,:].rename(columns={'dist_nan':'district',                                   'prov_nan': 'province',                                                       'part_nan':'partner',                                                       'fund_nan':'financing_source'}) *# new columns, drop some and change data type*
    df['main_organization'] = tabnames[i].split("_")[0] + " "+ tabnames[i].split("_")[1]
    df.drop([c **for** c **in** df.columns **if** "Total" **in** c], axis=1, inplace= **True**) 

    **for** c **in** [c **for** c **in** df.columns **if** "yrs" **in** c]:
        df[c] = df[c].apply(**lambda** x: pd.to_numeric(x)) *# reshape - indexing, pivoting and stacking*
    idx = ['district','province', 'partner','financing_source'
,'main_organization'] multi_indexed_df = df.set_index(idx)
    stacked_df = multi_indexed_df.stack(dropna=**False**)
    long_df = stacked_df.reset_index()

    *# clean up and finalize*
    col_str = long_df.level_5.str.split("_") 
    long_df['target_year'] = [x[0] **for** x **in** col_str] 
    long_df['target_age'] = [x[1] **for** x **in** col_str]
    long_df['target_quantity'] = long_df[0] *# rename this column*
    df_final = long_df.drop(['level_5', 0], axis=1) **return** df_final

运行该功能

*# Check that our function works:*
check_df = ReshapeFunc(data, 2)
check_df.head(2)

酷!现在使用函数为每个选项卡创建一个数据框,将它们全部放入一个列表中,将它们连接成一个数据框,并将其保存回 Excel。

dfs_list = [ReshapeFunc(data, i) **for** i **in** range(4)]
concat_dfs  = pd.concat(dfs_list)
concat_dfs.to_excel("reshaping_result_long_format.xlsx")

这种长格式现在可以很容易地用于数据透视表,并通过透视描述性的非数字列的任意组合和聚合数字列来制作仪表板图表和分析。任务完成。

为了和我一起工作,请点击这里查看我的博客:【https://tichmangono.com/】

编码快乐!

人工智能世界峰会的七大趋势

原文:https://towardsdatascience.com/seven-trends-from-world-summit-ai-amsterdam-d642ede4da4c?source=collection_archive---------18-----------------------

上周,阿姆斯特丹举办了世界人工智能峰会。在这两天里,人工智能专家、行业成员、学术界和机构聚集在一起,分享和讨论人工智能方面最热门的新闻和想法。显而易见的是,这个领域比以往任何时候都更令人兴奋,而且仍在以惊人的速度增长。在这里,我提出了讨论过的七个主要话题。

The World Summit AI introduction

  • 公平 AI :随着机器学习的普及及其在几乎所有行业的应用,确保机器学习算法的公平性变得越来越重要。虽然我们知道在收集的数据中可能存在偏差,无论是由于内在偏差还是由于数据收集和生成,我们的机器学习模型都应该尽可能无偏。这些担忧已经存在很多年了,尤其是在保险和银行等行业,但问题正在各地浮出水面。就在上周亚马逊宣布将废弃其新的简历筛选引擎,原因是其中存在严重的性别偏见。控制模型偏差的建议解决方案有多种。目前一个很大的焦点是放在模型的可解释性上,我们将在下面的要点中展开。另一个强烈的话题,尤其是来自学术界的,与监管有关。这些法规将特别关注模型的透明度和公平性约束,包括输入数据和输出预测。在实践中,这可以作为一种新的机器学习模型,在有偏见的模型之上,使数据输入和预测输出无偏见。这些技术中的一些目前正在被探索,例如使用生成对抗网络的特定架构

An example of the structure for a fair ML model by Prof. Virginia Dignum

  • 模型可解释性:能够从机器学习模型中解释决策和预测的重要性是整个事件中反复出现的话题。这个想法是为了让模特感觉不那么像个黑匣子。可解释性的主要原因是模型责任。如果人工智能的公平性是一个问题,直接的后果是模型需要对它们做出的决定负责,需要对为什么做出某种预测做出解释。达到可解释性的两条主要途径是技术性的和规范性的。在技术方面,已经开发了多个框架来解释模型预测,如 LIMEELI5 。许多其他公司,比如 Alpha 和 T7,也在致力于开发新技术,有望带来更加透明的模型。另一条实现模型可解释性的途径是通过监管。这是学术界讨论和研究的一个非常活跃的话题。一些规定已经在计划中,并将很快到位,作为可解释机器学习 GDPR的一部分。其他方法建议要求模型是开源的,这样它们就可以被检查。然而,这似乎是一个很大的要求,而且,没有用于训练模型代码的数据可能没有多大意义。模型可解释性的另一个原因是模型不仅可以用于预测。例如,在预测性维护的情况下,通过预测来了解系统的状态以及是否需要干预。然而,通过模型解释,我们还可以获得关于需要评审的组件或者处于风险中的特定过程的更详细的信息。因此,如上所述的新技术的发展也将极大地有益于这些类型的应用。
  • 从研究到应用:在过去几年里,在谷歌和脸书等巨头的推动下,人工智能的研究飞速发展。强大的新技术或改进的旧技术,加上计算能力的提高,已经允许在图像分类和语音识别等领域取得巨大成果,通常超过人类的准确性。现在,来自世界人工智能峰会的普遍感觉是时候将人工智能的重点从研究转移到应用,让这些新技术得到应用,以获得价值。许多因素都表明了这一点。首先,人工智能的民主化努力,这将在下一点讨论。第二,对实际应用的极大关注,在许多会谈中都得到强调。在金融、自动驾驶无人驾驶机队和人造卫星方面取得了巨大成就。医疗保健行业仍然被认为很少受到人工智能革命的影响,同时也被认为是人工智能应用可以蓬勃发展的最佳行业之一。
  • AI 民主化:AI 技能的传播是大会最大的主题之一。来自谷歌的 Cassie Kozyrkov 解释了他们如何训练 17k(!!!)决策智能方面的员工,即应用人工智能解决业务问题。这使得基本上每个团队都有能力在他们的产品中实现机器学习驱动的功能。民主化也可以通过云服务来实现。IBM 和 Google 等云提供商允许通过简单的 API 调用来应用复杂而强大的算法。这为更多的观众提供了快速而廉价地应用新技术的机会,而无需深入的 ML 知识或花费时间来制作和训练深度神经网络。人工智能民主化还伴随着一个新的、更广泛的概念,即规划数据科学项目和组建团队来应用机器学习。
  • 团队的多学科方法:虽然行业越来越关注应用人工智能和民主化人工智能,但关注如何获得成功结果也很重要,即如何构建团队,使他们能够推动创新。关键的一点是需要多种多样的技能。特别是,机器学习研究人员需要嵌入到由面向业务的专家、软件工程师、数据工程师等组成的团队中。多学科是数据科学项目成功的关键。这是因为最佳 ML 算法的应用和选择只是问题的一部分。数据管道、关注正确的业务问题、产品集成也同样重要,并且需要多种技能才能出现在项目中。

The future of AI, from Cassie Kozyrkov

  • **以人工智能为导向的决策者:**随着人工智能在似乎每个行业和我们生活中越来越多的部分的大规模扩散,我们也需要领导者和决策者以人工智能为导向。首先,这是机器学习项目成功和人工智能成功传播的关键。其次,人工智能提供了从海量数据中分析和获取洞察力的工具,使决策者能够做出更快、更明智的决策。例如,ING 展示了他们的人工智能驱动的投资工具。这个工具可以扫描数百万的资产和投资策略,为投资组合经理提供以前无法想象的大量交易机会的概览。
  • 人工智能带来的好处:最后,大量的注意力被投入到能够使用人工智能来关注巨大的社会问题的重要性上。Telefonica 成立了一家 moonshot 公司, Alpha ,专注于解决健康问题,尤其是帮助人们重新获得对日常行为的有意识控制。来自牛津大学的 Luciano Floridi 教授专注于人工智能可能为人类和地球带来的风险,以及人工智能可能为每个人带来的巨大潜力:让我们的生活变得更好,将我们从枯燥乏味甚至危险的工作中解放出来,增强人类的能力,让我们更加亲近。

AI dangers and opportunities, from Luciano Floridi presentation

结论

世界峰会人工智能真的很鼓舞人心。该行业显然处于良好状态,而且似乎只会上升。AI 未来肯定是红火的。尽管如此,在保护个人及其隐私的同时,让每个人都能正确使用这一令人惊叹的技术仍有许多挑战、不确定性和问题需要解决。

鸣谢:我要感谢 booking.com 给我参加这个盛会的机会。

数据科学入门的几本好书

原文:https://towardsdatascience.com/several-great-books-for-getting-started-in-data-science-68279450c4f9?source=collection_archive---------5-----------------------

我在听一个关于数据科学和新闻的播客部分衍生的旧节目。一位主持人提到,我们现在生活在“数据科学教学和学习材料的黄金时代”。我完全同意这种说法。每个月,大多数出版商似乎都有关于这个主题的另一本书,人们也在撰写令人兴奋的博客帖子,讲述他们的所学和所做。

我想按照我接触它们的顺序,列出几本对我有帮助的书。希望你可以用它们来获得这个领域更广阔的视角,或许可以作为一种资源传递给其他想学习的人。

从数据中学习

我第一次发现从数据中学习是通过加州理工学院关于这个主题的课程。我仍然认为这是一篇优秀的文章,但是我不确定我是否会把它推荐给初学者。(对于刚刚进入主题的人,我可能会推荐列表中的下一个选择。)

然而,如果你有一点线性代数和概率的背景知识(足以阅读符号和查找事情的意思应该没问题),那么这绝对是一本入门的好书。从数据中学习让我第一次尝到了数据科学中使用的许多算法背后都有一些严格的数学理论。如果处理数据和观察结果表明这些方法有效,理论会告诉你为什么有效。

现在,理解一些关于理论的事情是很重要的,但是大多数时候,人们想知道它实际上能做什么。

数据挖掘技术:用于市场营销、销售和客户关系管理

我承认,在我阅读数据挖掘技术之前,我只是粗略地了解了什么是可能的。我知道最广泛使用的算法是用来评估风险的,比如信用评分。然而,我不太了解如何利用数据科学技术在营销领域获得收益。

我很欣赏作者在该领域的丰富经验,尤其是在大数据发展之前的经验。这本书清楚地表明,许多最有用的算法已经存在并使用了几十年。作者还从直接营销案例(印刷杂志和实体邮件)中提供了一些我没有考虑到的解释,例如排名算法,这种算法最初用于确定联系人名单的优先顺序,因为向人们邮寄纸张的成本很高。

最重要的是,我喜欢这些主题的广度,因为它们涵盖了几乎所有形式的营销算法,并且很好地向你提供了它们为什么重要的高层次观点。

从这本书中,你不会知道如何实现他们谈论的所有内容,但是你会知道哪些算法适合特定的任务。

这本书给了我一个更好的方法来思考一个项目的初始阶段,但我仍然需要一些帮助来学习如何交流数据以及如何将数据直接融入业务环境。

商业数据科学

我在度假的时候通读了这本(是的,我知道,我就是那种极客)。这并没有阻止我从其中汲取大量信息,了解数据科学如何应用于试图使用这些模型的公司。本书的大部分内容侧重于帮助您思考如何操作化运行和管理数据科学项目的流程,以及您可能期望从中获得什么结果。

除此之外,我认为它教会了我如何在公司更好地交流数据。能够谈论将一个项目付诸实施需要几个月的时间,并将其与备选方案进行权衡,是在一家想要赚钱的公司工作的基本要素。此外,如果你认为一个特定的项目是正确的选择,你需要能够通过沟通的好处来支持这个选择。

我想说,这是一本非常“底线”的书,但有时听听也没关系。如果您的优先事项包括将成本控制在收入之下,那么数据科学并不总是最热门的技术或最大的技术。然而,我仍然没有学到多少如何在日常工作中处理数据。为此,我不得不依靠我提交的最后一本书。

应用预测建模

这是一本关于 R 语言预测建模和使用作者开发的软件包的书。总的来说,我认为即使你最终没有使用 R 作为你分析数据的首选工具,你仍然会从这本书中学到很多。它充分展示了 caret 在一个项目中可以为您提供的强大功能,以至于您会在自己选择的工具中寻找相同的功能(或者希望为我们构建它的等价物)。

作为一个软件工具,caret 为你可能要求的任何预测任务(分类或回归)提供了一个一致的界面。一些人对 R 包的一个问题是算法的接口不是很一致。学习如何使用一个包并不总能在一个完全不同的包中得到相同的理解。Caret 通过给你同样的方法为许多不同的算法建立一个建模任务来解决这个问题。此外,它还可以自动执行多项任务,例如:

  • 数据分为训练集和测试集
  • 数据转换,如标准化或幂转换
  • 建模调谐和参数选择

本质上,它使得在 R 中工作很像使用 Scikit Learn ,但是有更多的选项和模型实现。

那么下一步是什么?嗯,在你阅读和学习新技能的时候,最好的办法是试着把这些技巧应用到你关心的问题上。也许下次你在会议上讨论公司的优先事项时,你需要围绕下一个数据项目展开对话,并将数据工作引向你的业务目标(商业数据科学)。当你集思广益,试图预测并在营销活动中使用可能的东西时,你需要概述可能的技术以及它们能为你提供什么(数据挖掘技术)。如果您正在评估候选算法准确执行任务的能力,您将需要从理论(从数据中学习)和实践(应用预测建模)的角度来衡量它们的有效性。

我希望这能帮助你在工作中应用数据科学,并给你在这个领域的视角。

这篇文章最初出现在我的个人博客这里

骑自行车还是不骑自行车?机器学习对旧金山自行车共享计划的可用性进行建模

原文:https://towardsdatascience.com/sf-bike-share-predictions-e15316ce300f?source=collection_archive---------5-----------------------

自行车共享项目正在世界各地的城市涌现,为专业人士和游客提供了灵活的交通方式。自行车共享系统通常建有“停靠站”,用户可以在那里借出和归还自行车。2013 年,旧金山推出了自行车共享计划,截至 2015 年,该计划在全市共有 70 个站点。

Imagine if cities had communal road bikes like this…!

自行车共享项目对项目所有者(城市)和使用者(骑手)都提出了挑战。例如,城市经常在车站之间手动重新分配自行车,以确保自行车和码头(归还自行车的槽)的可用性。城市也需要使用骑车人的数据来通知未来自行车站应该安装在哪里。对于用户来说,主要问题是:如果我现在离家/上班,到了最近的车站会有自行车吗?给定站点自行车的不确定性具有很强的商业含义,因为不可预测的自行车供应会阻碍骑行和停滞需求。这个项目关注自行车可用性的用户挑战。

该项目评估旧金山自行车共享系统的当前骑行趋势和预测自行车可用性(在请求后 30 分钟内)。这个项目的三个主要部分包括:探索性数据分析、一个简单的确定性模型和两个机器学习模型(一个具有时间和通勤特征,一个添加了天气数据)。在所有功能中,未来自行车可用性的最大预测因素是车站中的当前自行车,其次是周、月和通勤时间。在天气特征中,云层覆盖是最强的预测因素——如果你熟悉旧金山的天气,这并不奇怪!

具有高级特征工程的机器学习模型表现优于其他两个模型模型,误报率为 15%,误报率为 0.01%。

数据概述

使用了以下公开可用的数据(来源):

  • 状态:每分钟更新 70 个站点中每个站点可用的自行车数量和码头数量
  • 天气:旧金山湾区的 zip 级每日天气模式
  • 电台:每个电台的元数据(n = 70)
  • 行程:行程级别记录,包括日期、开始/结束时间、开始/结束站点 ID、开始/结束站点名称、自行车 ID、骑手订阅类型和行程持续时间

探索性数据分析

在按订阅类型(订阅者:月会员或年会员,客户:临时现收现付会员)对乘客进行分组后,我探索了季节性、每周和每日的乘客模式。所有的时间框架都强调了订户和顾客的不同模式,支持了订户是通勤者而顾客主要是游客的假设。

乘客量在 8 月/9 月/10 月达到高峰,在冬季假期前后会有一个淡季。这可能是由于旅游趋势或天气影响了休闲通勤者是否骑自行车(秋天是众所周知的旧金山最好的季节,冬天——当我们不在干旱的时候——非常潮湿)。

Daily (2013–2015) (left): Daily ridership increased since implementation. Customer ridership shows seasonal patterns, peaking in Aug/Sept/Oct and with a lull around the holidays. Annual (right): Subscriber ridership dips around holidays: week 22 (Memorial Day), 27 (July 4th), 36 (Labor day), 46/47 (Thanksgiving), & 51/52 (Christmas & New Years). Excluding holidays, ridership increases slightly in the first half of the year, peaking in summer (week 34/35) in ideal bike weather. Customer ridership also increases slightly with local maximum during holidays and a global max during Labor Day; rides start to drop off in the Fall.

Weekly (left): High weekday ridership for Subscribers with a large drop (~1/5) on weekends. Customers have a reverse trend with ~2x rides on weekends vs. the beginning of the week. Hourly (right): Subscribers show a distinct bi-modal daily usage pattern, with peaks during AM & PM commute hours, and a small increase during lunch. Customers get a later start (as one does on vacation), with steady usage 11am until the early evening.

假设

现在我们已经了解了数据和用户行为的大致趋势,下一步是建立一个简单的确定性模型来预测自行车的可用性。从骑车人的角度来看,自行车可用性是一个二元问题:自行车可用吗?是或否。因此,二元分类器是合适的。注意,从我的经验来看,并不是自行车共享系统中的所有自行车都可以使用。因此,稍微调整分类器,所有模型对在给定时间在一个站点是否有至少 2 辆自行车可用进行分类。

我们可以在上面的图表中看到,不同的站点呈现出不同的模式。例如,在居民区的车站,自行车在早上减少,在晚上增加。相反,靠近办公室的车站则相反。这证明了我们的预测模型的简化假设:我们可以为每个站建立独立的模型,从而明确地选择忽略不同站的行为之间的相关性。

数据管道

这三个模型都依赖于预处理步骤,如数据过滤、协调/简化数据类型和特征工程。为了支持更快的处理和更容易从内核崩溃中恢复(原始状态数据文件为 2.5 GB),实现了预处理 Python 脚本来持久化输出数据。总的来说,这些转换阶段构成了进入模型的数据管道。

  1. 将人类可读的时间戳转换为纪元毫秒。
  2. 生成一个测试数据集(用于简单模型),其中的行满足两个条件:(1)一个月中的第几天小于给定的一个月中的第几天(例如,如果 max_day_of_month <5,则返回的测试集包含每个月的第 5 天,约为 13%)。(2)星期几等于 ISO 格式的给定星期几(星期几= 3,因为当前确定性模型是为星期三计算的)。

对于两种机器学习模型(从步骤 1 的输出开始):

  1. 添加两个新列(1-适当的模型时间;2-t+30 分钟的真实自行车可用性),如果该行的时间戳在指定模型时间(在数组中)的 30 分钟内。否则,它将从数据集中删除该行。
  2. 将以下离散化日期时间列添加到数据集:ISO 星期几(1–7);ISO 月(1–12);通勤标志为 3 个二进制列;非上下班时间(1/0);AM 通勤(1/0)—7 点到 09:00 之间的状态更新;PM 通勤(1/0)—16:00 到 18:00 之间的状态更新。
  3. 在 t+30 分钟内添加一个站点的真实自行车数量。

模型结构

确定性模型

为了与我们最终建立的机器学习模型进行比较,让我们创建一个确定性模型来计算 30 分钟间隔内每站自行车可用性的变化。自行车可用性的变化使用最小二乘法进行近似计算,最小二乘法拟合一条曲线,使数据集中的因变量(自行车可用性)与线性函数(时间= x)预测的值之间的差的平方和最小化。为了建立模型,我使用上面确定的每日交通模式来定义适当的模型时间。基于高需求,模拟了以下 30 分钟的间隔:早上(7:30,8,8:30,9AM)和晚上(4,4:30,5,5:30,6PM)。为每个站点计算最小二乘拟合线,自行车可用性预测为:当前自行车可用性+(最小二乘线的斜率 x 30)。

popt_all_stations = []
row_headers = []

**for** i **in** station_ids:
    s = station_availability(i, n_bikes= n_bikes, dow= dow)       
    popt_single = []
    **for** j **in** start_times:
        start_time = pd.to_datetime(j)
        end_time = start_time + delta
        df = s.between_time(start_time.time(), end_time.time())
        xdata = df.index.minute
        ydata = np.array(df.bikes_available)
        popt, pcov = optimization.curve_fit(func, xdata, ydata)
        popt_single.append(popt[1])
    popt_all_stations.append(popt_single)
    row_headers.append(i)

*# reshape model ouput with time as column headers, station as index*
df = pd.DataFrame(popt_all_stations)
df.columns = start_times
df.index = row_headers

*# Convert model from minute-by-minute change in bike availabilty --> total change during* 
*# model window (e.g. the 16:00 model applies to status updates between 16:00 and 16:29)*model = df*29
model['station_id'] = model.index
model = pd.melt(model, id_vars = ['station_id'])
model.head()

下面我将所有型号一起评估。

简单机器学习模型

第一个机器学习模型使用简单的功能,根据状态时间戳设计:星期几、月份、通勤时间(非通勤、上午或下午)。预处理在数据管道中执行——主要是因为 Jupyter notebook 无法将未来自行车的可用性映射到状态表中的每一行。如上所述,对于骑车人来说,自行车可用性的问题是二元的;骑车人不在乎有多少辆自行车,而是在乎有没有一辆自行车。在这种情况下,我们将使用一个随机森林分类器,这将有助于稍后使用梳理出我们的功能的相对重要性。

输出是每个站一个模型(70);下面总结了每个模型特性的重要性。使用。describe(),我们还能够收集关于站点间特征重要性差异的见解。总的来说,当前自行车的可用性是未来自行车可用性的最具预测性的特征。在较小的程度上,月份和星期几是可以预测的。通勤时间并不重要。

pd.DataFrame(feature_imp, columns=X_train.columns).describe()

机器学习模型 2:高级特征工程

现在我们已经看到了一个基本的机器学习模型,下一步是添加更多复杂的功能,希望提高模型的性能。特别是,当通勤者选择他们的交通方式时,天气的各个方面(例如温度、降水)是关键的决定因素。在接下来的模型中,我们将引入大量的日常天气特征。

Could temperature and wind speed help predict bike demand? There are clear seasonal patterns that could feasibly drive bike usage.

与第一个 ML 模型一样,这个模型是特定于站点的。为了快速比较,为单个站点(站点#2)创建了天气增强模型。

随机森林的要素重要性方法显示了天气增强模型中要素的相对重要性(即原始 ML 模型要素以及附加的新天气要素)。我们看到,目前的自行车可用性仍然远远超出了未来自行车可用性的最佳预测。一周中的某一天、AM 通勤时间和非通勤时间也是原始模型中相当重要的特性。在新增的天气特征中,云量是最重要的特征,其次是最大露点、最小露点和最大湿度。在一个天气不可预测、云层覆盖臭名昭著的城市(我正看着你呢,卡尔),云层覆盖影响自行车骑行率(以及自行车的可用性)并不奇怪。

*如果你不熟悉旧金山,夏天的日常大雾是如此强烈和常见,以至于它被亲切地称为卡尔。

那么哪个“更好”呢?

要回答这个问题,我们必须就如何恰当地评估模型达成一致。由于严重的类别不平衡(例如,一个类别在数据中明显占多数),准确性(一个常见的默认评估指标)在这里不会出现。只有一小部分自行车站点在车型期间没有足够的自行车可用。事实上,96.6%的车站在给定时间段有自行车可用。因此,预测所有车站始终有可用自行车的分类器将有 96%的准确率…但这将是一个可怕的分类器。混淆矩阵提供了更好的评估指标。

Confusion matrix

从骑手的角度来看,最重要的指标之一是假阳性率:假阳性(错误归类为阳性的阴性事件的数量)与实际阴性事件总数的比率。换句话说:如果一个模型说自行车将在 30 分钟内可用,当用户到达时,实际上会有自行车吗?

Comparison of evaluation metrics for all three models (2 machine learned models, and one simple deterministic model).

对于用户最重要的指标——误报率和漏报率——这两个机器学习模型都优于简单的确定性模型。具体来说,天气增强随机森林模型在假阳性率(简单模型的 FPR 的三分之一)和假阴性率(0.01%对简单模型的 0.66%)方面远远优于简单模型。

可能的扩展

除了运行额外的机器学习分类器(例如 SVM、逻辑回归)进行比较,该数据集还具有进一步特征工程的巨大潜力,包括:

  • 自行车可用性的历史变化率(例如,简单模型中最小二乘方线的斜率)
  • 在前一个 x 分钟窗口中在车站开始/结束的乘车次数-提供车站受欢迎程度的洞察,否则会在车站状态更新中丢失(例如,如果一个行程在车站 A 开始,而另一个行程在车站 A 结束,则可用自行车的数量将是静态的)
  • 行程开始/结束时间流行度(例如,使用一阶导数找到当地最大和最小行程数)
  • 用每个气象站绘制 zip 级别的每日天气数据,而不是海湾地区的平均值。

[## 格西/跳板 _ 数据 _ 科学

有关数据和源代码(Jupyter 笔记本),请查看我的 github。

github.com](https://github.com/gussie/Springboard_data_science/tree/master/Bike_share_availability_classifier)

英国救护车服务与萨克拉门托市火灾的比较分析

原文:https://towardsdatascience.com/sfd-and-uk-comparative-analysis-of-ambulance-service-ed3581fbb1ec?source=collection_archive---------1-----------------------

“通过从供应方经济学转向需求方经济学找到可持续的解决方案”

执行摘要

1994 年,萨克拉门托市消防局接管了萨克拉门托市的救护车服务,并开始将病人运送到当地的急诊室。该计划取得了巨大的成功,包括缩短了救护车的响应时间,提高了患者护理水平,并通过运输计费为消防部门带来了新的收入来源。然而,在过去的 20 年里,对救护车的需求增加了,而每次呼叫的收入却下降了。需求增加的部分原因是市民对 911 救护车的期望发生了变化,因为 911 救护车可以为任何原因提供到医院的交通服务,包括重新配药。情况变得如此糟糕,以至于有些人经常拨打 911 叫救护车,因为他们有预约,但希望避免汽油和停车的费用。萨克拉门托市消防局(SFD)对救护车日益增长的需求的一贯反应是增加救护车的供应。SFD 从 1994 年的三辆救护车增加到 2016 年的十五辆。然而,增加救护车的成本可能很快超过萨克拉门托维持这一进程的能力。当救护车的供应无法满足需求时,由此产生的工作量会对人员、医院和危重病人造成伤害。
当救护车接到无生命危险的呼叫时,它们无法应对真正的紧急情况。每辆车平均要让一辆救护车停开 2 个小时,而用于救治非危重病人的救护车可能会给其他市民带来危险。继续这种做法对生命的威胁太大了。生命的风险、不断增加的成本和不断减少的收入表明,SFD 应该专注于减少对 911 救护车的需求,而不是增加供应。
我考察了英国的救护车服务,并与我们在萨克拉曼多的政策进行了比较分析。基于英国对优先调度、绩效衡量和高需求的使用,他们的挑战和解决方案与 SFD 的未来息息相关。
英国将绩效评估从“反应时间”转变为“患者结果”,并实施了“听和治疗”、“看和治疗”以及“治疗和运输”政策的解决方案。政策的转变使英国能够将 911 救护车的稀缺资源专用于危重患者,提高了急救护理的有效性和效率。
相对于反应时间,衡量病人的结果看起来像这样;如果一个脚趾疼痛的病人被救护车运送,到达医院时脚趾疼痛,出院时脚趾疼痛,那么就有一个中性的病人结果。反对以下情景;患者因严重气短被救护车运送,到达医院时有轻度气短,出院时无气短,则为阳性患者结果。
英国的演变本质上是从供给侧经济学向需求侧经济学的转变。换句话说,英国不是只关注增加救护车的供应,而是在关注危重病人需求的同时,采取措施减少对救护车的无谓需求。
我知道英国和萨克拉门托的政治环境大相径庭,每个地方都面临着独特的挑战。然而,对英国的一项分析显示,英国是一个非常繁忙的体系,正努力解决与 SFD 类似的问题,并最终通过从供应方经济学转向需求方经济学找到了一个可持续的解决方案。SFD 可以通过探索以下主题来学习英国的行动:
改变优先调度
制定包括每次事故成本、患者结果和投资回报的绩效衡量标准
根据上述绩效衡量标准制定数据驱动的政策决策
通过使用“倾听和治疗”政策来减少响应量
通过“观察和治疗”政策实施护理人员/医生发起的运输拒绝
使用替代形式的运输工具将合适的患者送往诊所。
SFD 勘探之外的任何行动都应包括医疗总监、市律师和工会的集中意见,以讨论该计划的潜在责任、成本和节约。

简介

1994 年,萨克拉门托市消防局接管了萨克拉门托市的救护车服务,并开始将病人运送到当地的急诊室。该计划取得了巨大的成功,包括缩短了救护车的响应时间,提高了患者护理水平,并通过运输计费为消防部门带来了新的收入来源。然而,在过去 20 年中,对救护车服务的需求和对服务的期望增加了,而收入却减少了。对救护车的需求和期望已经从仅用于紧急情况转变为任何需要的到医院的运输。情况变得如此糟糕,以至于人们经常拨打 911 叫救护车,因为他们希望避免油费和停车费。如你所知,病人拨打 911 搭车去医院配药的情况并不少见。
直到 2011 年,英国运营的救护车服务在规模、培训、绩效指标和响应模式方面与 SFD 非常相似。这项研究考察了英国的救护车服务,并与我们在萨克拉门托的政策进行了比较分析。英国经历了非常相似的救护车滥用问题,并在 2011 年颁布了一项名为“转变 NHS 救护车服务”的成功解决方案。
萨克拉门托市消防局(SFD)过去对救护车日益增长的需求的反应是增加救护车的供应。SFD 从 1994 年的三辆救护车增加到 2016 年的十五辆。然而,在过去的 20 年里,增加救护车的费用已经增加。
随着低影响呼叫需求的增加,收取合理费用的能力下降了。大多数 SFD 的救护车使用者都有联邦或州资助的健康保险;医疗或医疗保险。两者都提高了收取救护车运输费的要求,并降低了他们愿意为基本运输支付的金额。
最后,最大的问题是,当救护车致力于无生命危险的呼叫时,它们不能用于真正的紧急情况。每次运输平均需要救护车停运 2 小时。用于不便事件的救护车潜在地将其他公民置于危险之中。继续这种做法对生命的威胁太大了。生命的风险、不断增加的成本和不断减少的收入表明,SFD 应该专注于减少对 911 救护车的需求,而不是增加供应。

英国的救护车服务

英国有 6300 万人口,是世界上人口第 22 大国,面积略小于俄勒冈州。根据世界银行的数据,英国的人均 GDP 为 34000 美元,是世界上第 24 富裕的国家(比美国落后 14 位)。每平方英里 679 人,英国是世界上人口最多的 51 个国家(领先美国 131 位)。英国的救护车服务是国民医疗服务体系(NHS)的一部分,这是一个公共资助的医疗保健系统。救护车服务由 11 个地区性救护车服务机构提供,2009-2010 年的费用约为 19 亿英镑。NHS 由一般税收资助,向英国合法居民免费提供医疗服务。
大部分急救医务人员为(NHS)工作。通常,救护车配备有一名护理人员和一名紧急医疗技术人员(EMT)。英国的健康和护理专业委员会管理他们的护理人员和 EMT,其功能与 SFD 的 EMS 提供商非常相似。
2009-2010 年,救护车服务收到的紧急呼叫(英国 999,SFD 911)共计 640 万次,运送 470 万次。自 2007-08 年以来,英国的呼叫量平均每年增长 4%。与英国其他公共机构一样,NHS 的支出也受到国家审计局(NAO)的审查。NAO 独立于政府,向议会报告公共部门的效力和效率,如国民保健服务。
2011 年,NAO 对救护车服务进行了一次审计。其结果是对救护车服务进行了根本性的改革,目标是增加对危重患者的护理,同时每年节省约 7500 万英镑,成本下降约 4%。【2011 年之前,救护车响应分为三类;A-立即危及生命;B-严重但无生命危险;或 C-不会立即严重或危及生命。这些类别决定了响应时间目标,其中类别 A 要求响应时间在 75%的情况下少于 8 分钟。
NAO 2011 年的审计建议改变业务实践,尝试将适当的响应模式与需求相匹配。结果是三层系统;听与待,看与待,看与传达。本质上,审计建议接电话的人使用决策算法对电话进行分类,然后将结果类别与一个新的响应模型配对。例如,C 级呼叫将变成“听到并处理”呼叫。呼叫接听者会听取投诉,并提供除紧急救护车之外的替代解决方案。
此外,英国制定了新的绩效衡量标准,重点关注临床护理质量指标和效率节约目标。临床护理质量指标包括心肌梗死、心脏骤停和中风的结果。效率节约包括每名救护车工作人员的护理费用和每起事故的费用。

对比分析

由于英国的优先调度、性能测量以及来自非生命威胁呼叫的呼叫量增加,它与美国的密集城市(如萨克拉门托)非常相似。在 2011 年之前,英国将紧急呼叫的紧急程度分为三组:A 级-立即危及生命,B 级-严重但不立即危及生命,C 级-不立即严重或危及生命。这些类别确定了响应时间的目标,但最终未能确定响应的类型。为了减少总体响应时间,接听电话的人将每个电话作为 A 级开始,在真正审查电话之前假设最坏的情况。即使接电话的人在问了更多的问题后重新对电话进行了分类,救护车的反应已经开始了。换句话说,英国仍然会向 C 级呼叫发送最昂贵的响应模型,他们只是不希望他们那么快到达那里。结果,社区为非紧急电话付出了高昂的代价。
即使 SFD 的分类是相反的,D 级是威胁生命的,而 A 级不是立即的,SFD 使用相同的模型回应。像 2011 年之前的英国一样,每个呼叫都是在询问之前作为威胁生命开始的,每个响应都使救护车停止服务,这是最昂贵的响应模式。相比之下,在 2011 年审计后,英国停止了优先调度,并开始在发送和救护车之前审查呼叫,以更好地满足需求。因此,英国估计每年可节省 1 亿至 2.8 亿英镑,并改善患者的预后。
SFD 继续优先派遣的驱动力与英国相同;业绩计量。英国和 SFD 将每个呼叫视为威胁生命的原因是为了在 it 绩效评估中获得最高分;响应时间。

绩效指标

2011 年之前,英国的主要绩效指标是从电话响起到救护车到达现场的反应时间。响应时间驱使调度员通过将每个呼叫归类为威胁生命的呼叫来使救护车尽可能快地移动。意识到这一缺陷后,英国将绩效指标转换为病人结果、服务成本和不包括电话呼叫的响应时间。SFD 也有同样的缺陷,因为它衡量效率的主要指标是包括电话呼叫在内的响应时间。SFD 缺乏任何病人护理或成本效益表现措施,导致 SFD 每次都使用最昂贵的响应模型,而没有跟踪因所有救护车都被调度而错过的威胁生命的呼叫。
需求
与 SFD 类似,英国的救护车系统的呼叫量稳步增长。在 2007-08 年,英国救护车服务的呼叫量上升了 9 %,导致服务成本上升了 19%。结果,每次通话的费用增加了 10%。众所周知,SFD 的通话量和费用也在稳步增长,但是,自 2011 年审计以来,英国已经实施了多项计划来降低需求。
英国通过通话周期中的三个点来管理需求;闻而治,见而治,见而运。
heard and treat 允许调度员通过电话将呼叫转介给该地区的临床医生,而无需救护车。“聆听和治疗”减少了派遣次数,迅速处理了问题,救护车容量得到了更好的利用,救护人员受到的影响更小,并且患者被视为离家更近。最后,为了安全起见,听和治疗干预偏于谨慎,如果对严重性有任何疑问,发送一个响应模型。
SFD 没有切实可行的解决方案兼容听力和治疗。因此,SFD 的呼叫量持续增加,为病人提供的简单解决方案被推迟,救护车越来越少,救护人员超负荷工作,病人经常被运送到城镇的另一边。
观察和治疗使救护人员能够在现场解决事故,而不需要运送到急诊室。观察和治疗减少了救护车的总呼叫时间,有效地利用了人员培训,减少了对急诊室的影响,减少了治疗时间,并使患者离家更近。虽然从技术上讲,如果病人拒绝被运送,SFD 可以在现场“观察和治疗”病人,但这样做有很大的障碍。首先,病人必须坚持“看和治疗”政策,并签署一份法律表格,声明他们拒绝医疗建议,并坚持留在家中。第二,SFD 的非正式政策“你打电话,我们拖走”使这种思维定势制度化,即不管病人是否抱怨,都要把他们送到医院。SFD 的正式和非正式政策减少了对危及生命呼叫的救护车可用性,增加了急诊室的影响,增加了治疗时间,并可能将患者转移到整个城市。
除了英国实施的“倾听和治疗”政策和“观察和治疗”政策确保有更多的救护车可用于有生命危险的呼叫,并配备休息更好的医护人员之外,英国的“观察和运输”基本上与 SFD 相同。此外,英国还开通了一个“111”号码,为那些没有生命危险的来电者提供了另一个选择。“111”号码有助于确保有紧急需求的患者获得帮助,同时保证救护车资源可用于医疗紧急情况。
SFD 在 2010 年实施了类似的系统,名为“311”。然而,“311”只处理城市服务,如供水和街道,没有医疗需求的能力。缺乏“111”类型的系统迫使所有医疗请求通过 911 系统,并最终在最小的医疗问题上派遣救护车。
最后,英国已经建立了合作伙伴关系,以减少特定患者群体的来电。例如,跌倒占英国救护车呼叫的 10%。救护车服务部门和社会服务部门在一些地区建立了跌倒小组,为有重复呼叫风险的人提供建议和预防服务。
SFD 没有真正的合作伙伴来帮助重复拨打 911 的用户,例如该地区的无家可归者。许多无家可归者需要医疗服务,但不是三级救护车和急诊室。与英国等社会服务机构合作,转介高危患者,可以显著降低需求。

考虑

责任
应量化和审查因“倾听和治疗”政策或“观察和治疗”政策导致的延迟响应的责任。英国的医疗保健系统与美国的不同之处在于,它是一个由公共税收资助的国家医疗保健系统。由于延误治疗或运输的政策,患者遭受额外伤害或死亡的情况下的责任将在全国范围内蔓延,与萨克拉门托相反,诉讼可能会使萨克拉门托市面临巨额责任。应根据呼叫量和患者接触率来估计诉讼的可能性,以比较此类保单的潜在损失和潜在节省。

公众形象 改变消防部门的公众形象也是一个问题。目前,如果市民拨打 911,消防部门会不顾需要做出反应。这种一致性在社区和消防部门之间建立了信心和信任。一项新的“倾听和治疗”政策,即消防部门不向小型医疗救助派遣响应单位,可能会对社区支持和资金产生负面影响。

政治环境——劳工/行政人员 工会可能会因“倾听和治疗”或“观察和治疗”政策导致的来电量减少而感到威胁。工会的潜在反应可能看起来与直觉相反,因为这将减少其成员的工作量,但也可能减少对员工的需求,从本质上减少工作岗位。respond 模型中的任何政策变化都应提交给劳工,并最终得到劳工的认可。

如果任何新政策被证明在责任、信誉或政治货币方面更昂贵,它们可以很容易地被取消,并被当前的业务形式所取代。此外,新的政策可以分开,单独实施。例如,如果“听取并处理”策略耗费了太多的社区善意,则可以将其删除,并替换为该类别呼叫的“查看并处理”。

结论
目前,SFD 的功能与 2011 年前的英国非常相似;通过使用优先调度和依赖响应时间作为性能度量。然而,在 2011 年,英国发展并实施了新的程序,以减少需求,降低成本,并提高病人护理的质量。SFD 应该密切关注英国的救护车转型,并考虑这些政策是否适合我们的环境。

[## SFD 睡眠研究

“众所周知,一晚睡眠不足会对表现产生不利影响,并持续降低……

medium.com](https://medium.com/@esaylors/sfd-sleep-study-a494e669af42) [## 量化负面:消防服务的真正价值

我们在公共安全领域面临的最大挑战之一是以可量化的方式阐明我们的价值。这个挑战是…

medium.com](https://medium.com/@esaylors/quantifying-the-negative-the-true-value-of-the-fire-service-f1093e4bcfc2)

Shab Dev 故事#01:试图通过反向投影找到梯度下降的矩阵形式

原文:https://towardsdatascience.com/shab-dev-story-01-trying-to-find-the-matrix-form-of-gradient-descent-via-backprop-1c2bf7fdf5fe?source=collection_archive---------2-----------------------

如果我用错了一些数学概念,我提前道歉,并请你告诉我是哪些,以便改进这篇我主要为自己写的文章。

如果我们想要实现使用梯度下降训练的神经网络,学习如何执行反向传播是早期步骤之一。然后,如果我们想在游戏中更认真一点,我们将我们的向前传球矢量化/矩阵化,因为这使代码更清晰、更有效。现实很快赶上我们,因为由于矩阵和矩阵乘积,我们向后传递的链式法则不再起作用。因此,我们调用我们的神奇技能,通过重新排序表达式使矩阵的维度匹配来解决整个问题。至少,我是这么做的。

在这篇文章中,我们试图看看我们用矩阵演算得到的矩阵形式的梯度下降的表达式是否与我们使用某种魔法得到的表达式相同。这不是通过反向投影对梯度下降的介绍,我认为它主要面向那些试图理解数学的开发人员(没有数学背景)。

有什么问题?

假设我们有一个两层网络(一个隐藏,一个输出),并且我们使用矩阵来表示它的参数(即权重)作为它的输入,并且我们使用矩阵值激活函数:

这里,X 是包含小批量输入的矩阵(行是实例,列代表特征)。W1 和 W2 是分别包含属于隐藏层和输出层中所有神经元的所有权重的矩阵(一列代表一个神经元,下面的行是其权重)。较低的 sigma σ是我们的矩阵值激活函数(例如,它基本上将 sigmoid 函数应用于所有输入矩阵元素)。现在,如果我们想计算(小批量)梯度下降步骤的 W1 的更新值,该怎么办呢?

我当时做的是尝试对一些损失函数(例如 MSE)取 w.r.t 到 W1 的导数。我的结局是这样的:

This chain rule is not sound.

这根本行不通,事实上,矩阵产品行不通,因为矩阵没有好的维度,这是我当时不知道的事情,大约一年前😕。我试着反过来表达,试着添加 Hadamard 产品,但这些东西都不起作用。然后,我学习了矩阵转置操作,并开始变魔术般地使矩阵形状和乘积起作用,同时确保我将得到标量形式的损失函数 w.r.t W1 的权重的偏导数的等价表达式。这给了我:

The delta of W1 given after backprop.

几个月过去了,不久前我开始研究一个玩具 OCaml 神经网络库,即使我的数学水平在一年内略有提高,我自己也无法用微积分为上面的表达式找到真正的数学依据。即使是在数学方面,我认为一个开发者不应该在没有尝试理解的情况下使用如此基础的东西。Andrej Karpathy 的“是的,你应该理解 back prop”让我决定,我应该调查一个更好的理由来寻找平静。

寻找表达矩阵导数的方法

我们这里真正的问题是,有没有办法把一个成本函数 w.r.t 对 W1 求偏导数,更一般地说,有没有办法把一个矩阵值函数 w.r.t 对一个矩阵求导?

What’s the derivative?

我们可以说 F(X) w.r.t 对 X 的导数是一个具有 X 形状的矩阵:

Matrix derivative (wikipedia)

这个定义有些有趣。矩阵具有 X 的形状,这意味着我们的参数的更新将是直接的。然而,这个公式有一个缺陷:

是的,它不允许链式法则,没有链式法则->没有后退。

我们需要一个链式法则,这就是 JR. Magnus 和 H. Neudecker 在矩阵微分学(ch9.3) 中给我们提供的。他们争论一些不好的符号和一个表示矩阵导数的好符号。他们基本上说对矩阵取矩阵值函数 w.r.t 的导数有些不一致,并主张将雅可比矩阵推广到矩阵:

Formula 1. vec is the vec operator

如果 F(X) 具有形状 p x q 并且 X 具有形状 m x nvec(F(X)) 将是具有形状 pq 的列向量。 转置(vec(X)) 将是具有形状 mn 的行向量,因此雅可比矩阵将具有形状 pq x mn 。虽然雅可比矩阵不完全是对 X 的偏导数,但它包含了我们获取它所需的所有信息,最重要的是,它允许一个链式法则:

Formula 2. Derivative of a composition

注意我们也可以说,我们正在寻找的导数是一个四阶张量(正如维基百科所指出的),但我没有找到任何可理解的资源。

逐步展开链式法则

警告/!这部分几乎只包含数学,可能不是很有趣。
现在我们有了一种表达矩阵导数的方法,我们可以陈述我们目前正在寻找的东西:

这个雅可比矩阵将为我们提供更新 W1 以进行梯度下降所需的一切。现在,让我们一步一步地展开链式法则:

Step 1.

对于第一个块,我们可以看到我们正在寻找一个表达式的导数,该表达式只对矩阵 U(平方减法的占位符名称)执行元素级标量乘法。我们知道对于标量来说axw . r . txa(a为常数),但是对于矩阵来说我们有:

Formula 3. The derivative of the identity function is the identity matrix(dim is dimension of a vector).

也就是单位矩阵。因此,我们只需:

然后,对于第二块,我们寻找平方矩阵 V 的导数(平方是指元素乘积,而不是矩阵乘积):

Step 2.

为了表示矢量化 Hadamard 乘积的导数,我们将使用允许我们将其表示为矩阵乘积的属性,以便我们可以使用众所周知的乘积规则导数:

The Diag function takes a row vector and puts its elements along the diagonal of a square matrix full of zeros everywhere else.

Formula 3. Vectorized Hadamard product expressed as a matrix product.

Formula 4. Derivative of vectorized Hadamard product using formula 3

作为 A,在我们的例子中 B 和 X 都等于 V;因此,表达式简化为:

正如你在下面看到的,我们已经可以开始简化表达式了,但是让我们一次只做一件事。

Step 3.

对于第一步,我们可以看到我们正在对减法求导,这是我们需要的明显公式:

Formula 5. Derivative of subtraction

然后经过简单的应用,我们得到:

在展开链规则的损失函数部分后,我们的表达式看起来是这样的:

表达式已经开始变得相当长了,所以让我们把链式法则的展开部分放在一边,把注意力集中在前馈方面,一步一步地推导它:

Step 4.

由于σ(A)是一个基于元素的函数应用,因此我们有:

Formula 6. Derivative of element-wise function

其中σ'是它的导数。

Step 5.

下一步,我们想要一个矢量化矩阵乘积的导数,那么我们该怎么做呢?首先,让我们介绍一些公式:

Formula 7 & 8. Vectorized product of 3 matrices and its derivative.

这些公式的有趣之处在于它们允许使用已知的矩阵。但是当我们只有两个矩阵的乘积时,我们如何把它们应用到我们想要的偏导数上呢?这里有两个“窍门”:

nrow(X) is the number of rows in X

ncol(X) is the number of columns in X

我们在表达式的左侧添加一个带有单位矩阵的乘积,这允许我们使用上面的公式:

我们可能会问,是什么阻止了我们对两个矩阵之间的矢量化矩阵乘积求偏导数?好处是导数可以用已知的矩阵来表示,也因为我们不需要自己去推导。

Step 6.

这一步非常简单,因为我们重用了已经使用过的公式(公式 6)。现在最后一步:

Step 7.

为了使用我们的公式(8 ),我们需要 W1 在中间,为了做到这一点,这次我们添加一个矩阵乘积,单位矩阵在右边。既然我们已经展开了所有的前馈侧,我们可以看一看整体表达式:

这相当大,所以让我们尽可能地减少它:

Reducing the expression.

请注意,我们可以继续减少,例如一个单位矩阵的转置本身,诊断可以合并等…

更新权重

好了,现在我们已经展开了链式法则,剩下一个雅可比矩阵,我们如何使用它来更新 W1(以及我们的参数)?

A Jacobian matrix.

如你所见,每一列都包含向量的一个元素的导数,因此为了得到这个元素的“总”导数,我们需要对行求和,我们可以用一个行向量来完成,这个向量包含的列数与雅可比矩阵包含的行数一样多:

它给出了一个行向量,包含 W1 的每个元素的总导数 w.r.t。

为了更新 W1,我们需要得到一个具有相同形状的矩阵,因此我们需要的是 vec 的反函数:

The inverse of vec reshape a column vector into a matrix.

现在我们有了一个与 W1 形状相同的矩阵,其中包含损耗 w.r.t 对每个矩阵元素的导数。注意,我们已经转置了行向量,因为 vec 输出一个列向量。

最后,让我们看看更新 W1 的最终表达式:

让我们回忆一下通过匹配尺寸找到的表达式:

我们可以推导出表达式,并看到它们在理论上是等价的(我已经这样做了),但这篇文章已经包含了很多数学,我不确定它是否值得。但是不要担心,我们将在实现中从数字上检查它们是否等价。

回到背面投影

到目前为止,我们专注于展开链规则,但是永远展开链规则不是反向传播,反向传播是一种算法,而不是公式,在某种意义上,它是它的计算效率的化身。反向传播是从损失函数误差开始,通过层和神经元将“误差”反向传播到权重。

回想一下,下面是通过匹配尺寸获得的反投影形式:

和更新语句:

我们用矩阵运算找到的反投影形式是:

反向传播误差背后的直觉是,首先,我们有损失函数级别的误差,也就是说,在 *H(X)中损失随时间变化多少。*然后从输出层开始,回到第一个隐藏层,我们计算当前层神经元的误差。这是通过在下一层的误差(除了输出层 btw,因为误差来自损失函数而不是层)和激活函数相对于该层输入的导数之间执行矩阵乘积来完成的。然后对于这一层的权重,w1,总误差 w.r.t 权重是当前层的神经元及其输入的误差的乘积。

下面是我们的两层神经网络的反向传播步骤:

然后更新层的权重:

履行

以下要点是通过 XOR 问题的两种反向投影形式使用梯度下降训练的神经网络的数字实现。学习率为 1,我们不将 deltas 除以 1/4,以使神经网络收敛更快。 np.kron 是 Kronecker 乘积, np.diag 是 diag 函数, np.eye 返回一个单位矩阵。

我们应该使用哪种反投影形式

我发现矢量化的导数更容易使用,也更有教育意义;你可以看到,我们从来没有解决一个矩阵元素 Aij,我们所做的就是展开链规则。然而,当然,我们应该使用通过使形状匹配找到的形式,因为它在内存和性能方面更有效。诊断矩阵和克罗内克产品的成本很高。

结论

很多人担心人工智能,担心它可能被用于不良目的,但我认为我们不应该忽视这样一个事实,即开发人员将人工智能算法用作黑盒也可能会无意中导致人工智能做坏事。这就是为什么我认为我们,开发者,至少应该试着理解模型是如何工作的。不需要成为一个数学家伙,你甚至可以阅读论文,并向你的朋友谷歌寻求帮助!现在在这个领域所做的事情是惊人的(DRL,GANs… ❤).开始永远不会太晚,我个人只是在去年看了钢铁侠电影后才对神经网络和人工智能产生了兴趣😅。

对贝叶斯优化的浅见

原文:https://towardsdatascience.com/shallow-understanding-on-bayesian-optimization-324b6c1f7083?source=collection_archive---------1-----------------------

Sample data increases & Curve fitting gets improved.

预先知道的硬性条款

高斯过程

无噪声全局优化

噪声全局优化

采集功能

代理函数(/高斯过程)

随机的

贝叶斯回归

什么是高斯过程??

这是一个贝叶斯回归

——这是一种精确插值回归的方法。

——是线性回归的自然推广

  • 它指定了一个分配 功能

B 想象一下,如果我们不知道一个函数,我们通常会做什么?当然,我们会尝试用一些已知的先验知识来猜测或近似它。同样的想法背后是后验概率。这里的标准是我们有观察,其中的数据是一个记录接一个记录而来(在线学习),所以我们需要训练这个模型。训练好的模型显然会服从一个函数。我们不知道的那个函数将完全依赖于学习数据。所以我们的任务是找到最大化学习模式的超参数

我们这里有一些变量。一个是观察记录(特征+标签),第二个是参数,定义模型。

例如。

(比如说中的 like y = MX+c;m & c 是参数,y,x 是变量-标签&特征。我们有义务找到这些 m & c 来学习我们最好的模型)

贝叶斯优化有助于在众多模型中找到一个最佳模型。我们正在进行交叉验证。但是我们要在一个预先列表上尝试多少个样本来从中选择一个最好的模型。这就是为什么贝叶斯方法通过减少计算任务来加速这个过程,并且不期望人们帮助猜测数值。这种优化技术基于随机性概率分布。****

用我的话来说,第一个观测点来到模型。我们划清界限。那么下一点就来了。我们把这两点连接起来,从之前的曲线画一条调整过的线。第三点来了,所以我们画一条非线性曲线。当观察点的数量增加时,可能曲线的组合数量增加。这类似于统计学中的抽样定理,我们从样本参数中估计总体参数。

我们绘制了另一条直方图曲线以及非线性目标函数曲线。这表明,对于给定的目标函数曲线,在所有过去的观察值中, max 值将出现在哪里(找到 arg max)。

Histogram Curve, that is the Acquisition Function (includes different acq functions).

我们这里的目标是而不是用尽可能多的观察点将目标函数(未知)完全确定为一条曲线。相反,我们需要最大值的arg(max 函数的索引)。所以我们需要将注意力转向直方图函数。当目标函数曲线的可能组合增加时,直方图形成描述采集函数的分布。这是贝叶斯优化背后的思想。

记住,我们的目标,首先需要确定最大值的 arg,其次选择下一个最好的最大值,它可能在函数曲线上。

Many Random Ensemble Curves that we could draw from the above observed black samples.

我们在图中看到许多摇摆曲线。这告诉函数曲线的范围下一个点可以位于给定采样点的。方差给出了函数曲线上平均值的分布。

当我们通过将观测值叠加在未知函数曲线上进行估计时,那么这就是无噪声优化。但是当我们需要考虑噪声优化时,我们的未知函数会将观察点略微除以噪声误差值。

我们在许多测量下定义了采集函数,其中一些在这里,

1。PMAX

2。IEMAX

3。MPI =最大改善概率

4。MEI =最大预期改善值

5。UCB =置信上限

6。GP-对冲

MM =最大平均值

MUI =最大上限区间

采集标准 :- 接下来应该选择哪个样本

替代函数/响应面(模型)

  • 基于先前未观察到的点的后验超过。****
  • 参数可能基于先验。

采集功能:-

测量的是 改善的概率(PI)。

μ + =过去点中最佳 观察到的值。

我们正在寻找未知函数的最大值。但是在我们以往的观测当中,下一个 可能的最大值应该大于当前的最大观测值。

ε = 非常小的任意值表示高斯分布中的点。

我们的目标:-

Find the arg of the max of f(X)

PI(x) =发现未知函数下一个最大值高于最大观测值加上一些偏差的概率。

这只是高斯分布与最大观测值的阈值边界的 1D 积分。

对于未知函数中的每个点,我们考虑在每个点样本上垂直放置一个高斯分布。这个分布在未知函数的值上有均值&某个确定的方差。

我们把这个标准化在上面的 库什纳 1964 年 方程中。

探索&开发是解释一种现象和优化算法的常用术语。这两者之间存在一种权衡。因此,我们使用“采集函数”来平衡这种折衷。

我们的下一个选点(x ) 应该有高均值 ( 开采 ) & 高方差 ( 勘探)。

Choosing our next possible max point, with trade-off between Exploration & Exploitation.

因为我们在寻找高方差分布中的下一个点。这意味着探索 x 点。

高均值意味着我们选择了具有高偏移/偏差的下一个点(x ),因此我们应该给出一些开发权重来降低下一个点的均值。

The way we approach Bayesian Optimization.

上图给出了我们算法的一些直觉。红色曲线是我们的真实目标函数曲线。可惜我们不知道这个函数和它的方程。所以我们要用高斯过程来近似它。在我们的采样点(此处给出 4 个样本)中,我们绘制了一条与我们观察到的样本相符的直观/自信曲线。因此绿色区域显示了置信区域,在这里最有可能定位曲线点。根据上述先验知识,我们确定第二点( f+ )为最大观测值。所以下一个最大值点应该在它上面或者等于它。我们在这里画一条蓝线。下一个最大值点应该在这条线以上。因此,从 f+置信区域的相交点**,我们可以假设 f+ 以下的曲线样本应该与我们寻找 arg max 的目标一起被丢弃。因此,现在我们已经缩小了调查范围。对下一个采样点继续同样的过程。******

Data sample increases; comparison of different Acquisition functions with Curve Fitting.

参考:-

用机器学习塑造电子商务

原文:https://towardsdatascience.com/shaping-up-e-commerce-with-machine-learning-d64fa7b2e546?source=collection_archive---------3-----------------------

机器学习和人工智能已经流行了几年,但这个概念正在优步科技领域之外迅速变得熟悉并引起好奇心。这是有充分理由的。

人工智能是机器能够以我们认为“智能”的方式执行任务的更广泛的概念。机器学习是人工智能的一个当前应用,它基于这样一个想法,即我们应该能够让机器访问数据,并让它们自己学习。

你可能知道也可能不知道,机器学习已经影响到你的日常生活,几乎无处不在。你肯定已经在亚马逊上看到过它的概念,以及它的“个性化产品建议”。脸书用面部识别软件给照片中的人做标记。另一方面,你将在亚马逊上看到的另一个新颖的想法是它的“Dash”按钮,这是通过一个叫做物联网的概念的应用而成为可能的。

为你的电子商店实现机器学习技术是一个相对较新的可能性。然而,在过去的几年里,它仍然很容易被大大小小的商店老板们买到。任何知名的网上商店都不会考虑放弃 ML 的好处。

这是一颗神奇的子弹,把猜测工作从无限的营销活动中抽离出来。想象一下你的商店变成了一个水晶球。

除了最初的设置,一旦收集到足够的数据来使用它的算法,你就会开始享受销售的增长。当然,您需要花时间进行一些微调和维护,并且您可能希望及时添加更多功能。但是根据你的市场和产品,你的收入可能会上升 5-20%。

实施它的技术就像雇用一个销售代表。只是这个销售代表是沉默的,完全看不见的,小心翼翼地不被注意。更重要的是,这位销售代表不仅总是彬彬有礼,还能节省客户的时间。他们会很高兴通过网站上的个性化搜索结果和推荐块更快地找到想要的产品。在销售代表的亲自推动下,客户肯定会增加购买。此外,保留率更高。

当今电子商务中最常见的用例:

  • 个性化产品建议
  • 废弃购物车回收电子邮件
  • 搜索建议
  • 再营销和相似定位
  • 动态定价

个性化产品建议

亚马逊大约 50-60%的页面元素由产品和广告组成,这些产品和广告由机器学习算法组合在一起,产生个性化的产品推荐。这些街区已经成为这个地方的自然组成部分,并且增加了巨大的价值。

废弃购物车回收电子邮件

通过实施废弃购物车回收电子邮件,有可能进一步增加您的销售额。您的客户在废弃购物车中的相同产品将在他们的收件箱中提供给他们,这是另一个“水晶球”式的时刻。这些电子邮件还可以包括与现场推荐模块相同的个性化产品建议。

2017 年第 3 季度 SalesCycle 的一些全球统计数据:

  • 平均 76.8%的购物车被丢弃
  • 客户点击了 31.4%的购物车恢复电子邮件
  • 在这些被点击的电子邮件中,有 28.3%导致了销售
  • 11.6%的访问者继续在网站上购物

再营销和相似定位

个性化的产品推荐可以更进一步,超越你的网站和他们的收件箱,到达客户那里。和跨多个设备。与现场购物建议和电子邮件重新营销一样,你可以根据访问者浏览过的产品来确定他们的个人目标。此外,你还可以根据长相相似的人群吸引新客户。

搜索建议

大型零售商有数百万份产品清单。以易贝为例,它有 8 亿多种产品。当你登陆一个网站开始搜索产品时,过滤可能会让你失败,因为仍然有太多的选项需要浏览。

如果你的产品目录那么大,机器学习就变得无价了。ML 将根据您的性别、年龄和购买历史等因素对搜索结果进行排名。在它的帮助下,搜索结果将个性化,而不仅仅是匹配你用过的短语。此外,它还具有类似于谷歌的功能,可以在你打字时提供实时建议。

动态定价

航空公司是第一个接受动态定价的,比如瑞安航空。价格一天变化多次,所以如果你没有在第一次访问时预订,一旦你回到网站,你可能会遇到新的价格。价格波动可能意味着赢或输,取决于供求关系。

ML 如何在后台工作?

既然我们已经讨论了可能的使用案例,我们将很快看看引擎盖下,个性化和预测实际上是如何发生的。机器学习是一个概念,计算机算法通过无数次接触这些问题来解决问题,目的是找到解决方案。

ML 算法背后的逻辑是什么?通俗地说,

如果一个计算机程序在某类任务 T 和性能测量 P 上的性能(由 P 测量)随着经验 E 而提高,则称该程序从经验 E 中学习

如果你有点熟悉谷歌搜索的工作方式,那么你知道你会得到基于无限复杂算法的结果。这些考虑到你的位置,语言,以前的搜索历史和许多其他参数。就其核心性质而言,机器学习是类似的。它运行在智能和自我学习的预测 API 上。

机器学习分为三种类型:

  • 监督学习意味着期望的结果已经很清楚,样本数据已经标注了正确的答案。然后对算法进行“训练”,当输入新数据时,ML 会根据过去的经验给出结果。
  • 无监督学习意味着算法没有得到带有正确答案的预先标记的数据。例如,如果给定 ML 来随着时间分析一种语言,则算法开始检测模式。
  • 强化学习类似于无监督学习。没有提供带标签的数据,但分析后对结果进行了分级,这加强了预期的结果。

经过验证的结果表明,实施 ML 和 AI 后,收入至少会增加 60%。

新的电子商务浪潮和数据驱动的营销方法预示着电子零售商的新阶段。将持续评估当前状态。如果技术不再是限制因素呢?您的组织能够以多快的速度调整其策略以适应单个客户的需求?

分享你的 SageMaker 模型

原文:https://towardsdatascience.com/sharing-your-sagemaker-model-eaa6c5d9ecb5?source=collection_archive---------8-----------------------

本文原载于【blog.zakjost.com】

AWS 最近发布了 SageMaker ,它可以帮助你从零开始构建模型,到部署和扩展这些模型以用于生产。本文将假设您已经在 SageMaker 中运行了一个模型,并希望授予对另一个 AWS 帐户的访问权限,以便使用您的模型进行预测。

从父帐户向子帐户授予(有限)权限

在较高层次上,您需要创建一个有权调用端点的角色,然后授予子帐户对此角色的访问权限。为此,您需要孩子帐户的 12 位帐户 id。然后,按照以下步骤操作:

  • 登录父帐户控制台并导航到 IAM 服务
  • 创建名为“SageMakerExternalInvokeEndpoint”的新策略。粘贴以下策略。请注意括号中您需要输入的数据。
*{ "Version": "2012-10-17", "Statement": [ { "Action": ["sagemaker:InvokeEndpoint"], "Effect": "Allow", "Resource": "arn:aws:sagemaker:*:<parent   account_id>:endpoint/<endpoint name>” } ]}*
  • 单击“角色”并创建“SageMakerExternal”角色
  • 选择“另一个 AWS 帐户”并粘贴子帐户 id
  • 附加新的“SageMakerExternalInvokeEndpoint”策略(单击“策略类型”箭头“客户管理”,然后选择“SageMakerExternalInvokeEndpoint”)
  • 单击新角色并复制角色 arn,这将在后面的步骤中使用。

向子帐户授予“承担角色”策略

本部分将授予承担刚刚由子帐户创建的角色的能力。您将需要上述最后一步中的角色 arn。

  • 使用子帐户登录到控制台-> IAM
  • 如果您没有群,请创建一个。我把我的叫做“SagemakerTester”。如果您有现有用户,您可以将他们添加到组中。
  • 单击“权限”选项卡,展开“内联策略”箭头,然后创建组策略。添加此策略:
*{“Version”: “2012–10–17”, “Statement”: { “Effect”: “Allow”, “Action”: “sts:AssumeRole”, “Resource”: “<SageMakerExternal role arn copied above>“ }}*

使用 Boto3 中的假定角色

现在权限已经配置好了,您需要能够在尝试访问端点时承担这个角色。如果您使用的是 Boto3,代码将如下所示:

*# Get temporary assumed role credentialsclient = boto3.client('sts') #assumes you’ve configured boto with normal child account credentialsresponse = client.assume_role( RoleArn="<SageMakerExternal role arn copied above>", RoleSessionName="testSessionName", # this is arbitrary ExternalId=‘<parent account_id>’ )# Create boto client using temp credentialsclient = boto3.client( 'sagemaker-runtime', aws_access_key_id=response["Credentials"]["AccessKeyId"], aws_secret_access_key=response["Credentials"]["SecretAccessKey"], aws_session_token=response["Credentials"]["SessionToken"],)# Invoke endpointclient.invoke_endpoint( EndpointName=<endpoint_name>, Body=<data>)*

鲨鱼攻击—解释泊松回归的使用

原文:https://towardsdatascience.com/shark-attack-explaining-the-use-of-poisson-regression-449739bf96da?source=collection_archive---------4-----------------------

没有什么比鲨鱼袭击更能破坏佛罗里达群岛的理想夏季游泳了。除了令人印象深刻的背鳍、巨大的“白色”牙齿和普遍的恐慌之外,过去三十年间鲨鱼袭击对佛罗里达海岸线居民的涌入有多大影响呢?你会在哪里寻找数据?更重要的是,数据科学家会选择哪种算法来预测结果,为什么?

佛罗里达自然历史博物馆保存了国际鲨鱼袭击档案,记录了自 1957 年以来世界范围内无端的鲨鱼袭击(以及由此造成的死亡)。使用这些数据,我们可以通过检查攻击率的模式,使用泊松回归来预测沿海人口的变化,而不是人口变化与攻击次数直接相关的可疑假设。抛开双关语,让我们来看看什么是泊松回归,为什么这种方法是合理的选择,它的假设是什么,以及在依赖这种方法时我们应该采取什么预防措施。

泊松回归是回归分析的广义线性模型形式,由西蒙·丹尼斯·泊松于 1837 年提出,以支持他探索错误刑事定罪原因的工作。泊松回归,在处理分类数据时也称为对数线性模型,现在在大多数分析包中很常见,建议在需要对计数数据建模或构建列联表时使用。例如,这种模型可以有效地用于预测推特数据的转发,或各种操作条件下核电站的故障,或再次预测可识别的学生群体的考试成功率。

*这个模型的假设是什么?*泊松回归类似于逻辑回归,因为它也有一个离散的响应变量。该模型假设其期望值的对数可以通过未知参数的线性组合来建模。记录的事件以已知的恒定速率发生,并且与自先前事件以来的时间无关。更重要的是,该模型假设期望值(响应变量)具有泊松分布,而不是正态分布。换句话说,响应变量的可能值将是 0、1、2、3 等非负整数。

*泊松回归有哪些用例?*该模型可用于可观察事件随时间随机发生的随机过程。事件在给定时间间隔内至少发生一次的可能性与每个时间间隔的长度成正比。在每个时间间隔内,该事件发生两次或多次的可能性应该很小,如果有的话。接受这些假设,我们可以认为在固定的时间间隔(距离、面积或体积)内事件发生次数的概率分布符合泊松分布。

*使用泊松回归模型时,我们应该采取什么预防措施?*我想到了测试人群的三个潜在特征。作为一名数据科学家,您应该警惕数据中潜在的异构性——是否有多个流程生成预期值?过度分散是需要考虑的第二个异常现象——拟合模型的方差是否大于您假设的预期值?最后,数据样本是否反映了分散不足,即由于相邻子群的自相关,数据是否比二项式分布中预期的变化更小?

在建议的鲨鱼袭击案例中,泊松模型的选择是合理的,因为这种可怕事件相对罕见。正如 Jeffrey Simonoff 所建议的,我们可以应用一个广义线性模型,假设泊松模型使用对数链接来连接泊松均值μμ和随时间变化的速率。将拟合的平均值除以人口规模得到一个比率模型。为了提高模型的准确性,我们可以在种群方程中为种群大小的对数引入一个偏移项。因此,由于使用了对数链接,预测的时间趋势遵循指数模式,而不是线性模式。

Jeffrey Simonoff in his book Analyzing Categorical Data produced this summary output for the generalized model plus a transformed version — in this case the model predicts that the rate of shark attacks is rising by approximately 3% a year.[ii]

商业分析实践是商业分析学院的核心和灵魂。在我们在巴约纳的暑期学校,以及我们在欧洲的大师班,商业分析研究所专注于数字经济、数据驱动的决策、机器学习和视觉通信,将让分析为您和您的组织服务。

Lee Schlenker 是 http://baieurope.com 商业分析研究所的教授和负责人。他的 LinkedIn 个人资料可以在 www.linkedin.com/in/leeschlenker.[查看](http://www.linkedin.com/in/leeschlenker.)你可以在 https://twitter.com/DSign4Analytics[的 Twitter 上关注我们](https://twitter.com/DSign4Analytics)


【我】https://www.floridamuseum.ufl.edu/shark-attacks/

西蒙诺夫,杰弗里,2003,分析分类数据,施普林格

Shazam 高架线

原文:https://towardsdatascience.com/shazam-the-high-line-3090cb7c9fed?source=collection_archive---------5-----------------------

高铁每年有超过 400 万游客。今年春天,高线画廊举办了他们最新的艺术展览,突变。我们认为这将是一个尝试新概念的完美项目,Shazam for Objects。 HBO 的《硅谷》以他们最近的《Shazam for Food》报道了这一点。所以,让我们为艺术建造一个 Shazam,把高线的突变作为我们的试点项目。

这个概念很简单,拍一张艺术品的照片,查看更多关于艺术家和艺术品的信息。

构建工具

首先,我们需要训练一个模型来识别每一件艺术品。

An example of the images we used to train the model

我们已经用 Clarifai 的定制模型训练为客户项目构建了定制模型,并得到了一些鼓舞人心的结果,所以我们将使用它来创建分类器。下一步是收集训练数据来训练高线模型。分类器需要每个艺术品的标记图像。

Clarifai’s Custom Model Visual Interface

我们通过走高线并对每件艺术品拍摄大量照片来收集训练数据。我们训练了模型,经过一些简单的调试,我们能够对大多数艺术品进行 90%以上的可靠分类。

Prediction confidence is shown in the top right of this image

既然我们的分类器正确地识别了艺术品,我们需要为人们建立一个用户界面来使用分类器。

使其成为产品

最好的平台是像 Shazam 这样的独立增强现实应用程序,但我不想只为高端产品下载应用程序。让我们使用一个现有的平台,人们将在那里分享他们的照片。我们将使用 Twitter 来证明这个概念。如果一个人用# HighlineNYC 标签发推文,我们将运行定制模型,看看他们是否在寻找突变,如果是,是哪一块。Instagram 会是一个很好的平台,但他们的 API 对此限制太多。

正确鉴定艺术品,应该归还什么?现在,我们将回复作品的名称、艺术家以及您可以在哪里找到更多信息。这里的可能性无穷无尽,令人兴奋。在这种情况下,你必须真正专注,否则你会迷失在巨大的可能性中。

返回的信息格式(对于我们简短的文本和一个网址)将根据产品的平台而改变。例如,根据我们的经验,Twitter 中的链接工作得很好,因为它们可以将用户连接到比 140 个字符多得多的信息,或者使用脸书信使,最好为用户返回带有按钮的结构化卡片。一个专用的应用程序可以让你定制这一切。

尝试一下

让我们试试我们的新模型,在推特上发布关于在#Highline 或# HighlineNYC 查看这种新艺术的消息:

看来成功了!它认出了丹·巴德的装置棋。如果它不能识别艺术品会发生什么?我们通知用户,他们可以拍摄一张图片来了解更多信息:

厉害!那么下一步是什么?我们还可以用这个模型做什么?

扩展产品

该产品运行良好。艺术在视觉上足够独特,以至于分类器可以用很少的训练资源来识别它。这可以很容易地在其他装置、画廊和博物馆中重现。

有大量贴有标签的公共艺术品。我们不会一一列举,但这里有一个例子:

因此,Shazam for Art 很容易构建,并且能够以一种相当顺畅的方式接触到用户。我们还能建造什么?

下一步是什么?

Shazam for art 是一个有趣的开始,但是一旦你能够识别现实世界中的物体,你还可以做更多的事情。如果我们想要游戏化和个性化的高线体验呢?

艺术家可以将他们的作品扩展到物理空间之外,成为个性化的互动体验。如果你能玩一个异步人类象棋的互动游戏会怎么样。你可以拍一张棋盘的照片,它会告诉你下一步该怎么走。你拍下自己移动的照片,最后你可以把所有的照片拼接成一场漫长的夏季象棋比赛。

接下来…我们使用我们定制的计算机视觉和高线新突变装置来构建互动游戏。

第二部分将于本周晚些时候发布。

左移:授权即服务第 2 部分人工智能驱动的自动化

原文:https://towardsdatascience.com/shift-left-empowerment-as-a-service-part-2-ai-driven-automation-2403a15648a4?source=collection_archive---------10-----------------------

在第 1 部分“左移:支持即服务”中,我们探讨了左移通过接触更少、成本更低的交付渠道使 IT 服务更贴近员工的能力。决定实现左移只是第一步。那么,创建一个强大的 IT 服务组织的下一步是什么呢?将基于人工智能的自动化集成到一个更加数据驱动、更加注重商业价值的服务台。

在 ITSM.tools 最近进行的一项调查中,只有 26%的 ITSM 从业者认为他们的努力和价值得到了管理层的充分认可,只有 24%的受访者认为现有的 ITSM 最佳实践已经跟上了不断变化的 IT 和业务形势。

帮助每个团队成员掌控企业的发展目标,营造一个每个人都信奉 ITSM 价值观的环境。

自动化失速

自动化长期以来一直有望减少 IT 员工对重复性“维持正常工作”任务的依赖,并让 IT 部门腾出时间来处理更高价值的计划。然而,IT 员工缺乏自动化复杂 IT 流程所需的资源、能力和信任。

多年来,IT 部门发现,设计、构建和维护实现和维护任务和工作流自动化所需的代码和脚本可能需要大量的工作,更不用说确定它们是否与业务目标/KPI 保持一致了。

除了这一挑战,新工作方式的文化影响也会影响他们想要使用的设备、应用和系统。今天,自动化可能会在几天内过时,如果不是几小时的话。此外,IT 服务台的人员流动率往往很高,在保持工作流自动化和知识更新方面,这会耗费 IT 宝贵的时间和资源。

所有这些复杂性通常会导致 IT 组织发现传统的自动化方法弊大于利,会降低自动化速度,而不是加快自动化速度。

什么是基于人工智能的自动化?

基于人工智能的自动化提供了传统自动化的优势,减去了人工维护和人为错误的成本和工作量。

人工智能的一个关键好处是,它在跨多个记录系统的大量结构化和非结构化数据的基础上增加了认知能力(算法)。当与人工智能和机器学习相结合时,人类驱动的自动化允许 IT 组织在何时、何地以及如何提供服务方面做出更快、更准确的决策。

就左移而言,从人工智能系统中获得的知识和见解可以关联起来,并实时传播给 IT 支持人员、最终用户和系统。在人工智能的帮助下,IT 人员能够超越较低级别的任务(例如,解锁帐户和密码重置),转而执行对业务影响更大的任务。

当谈到自助服务(0 级)时,人工智能正在发展到这样一个阶段,在这个阶段,自主的虚拟代理可以维持越来越多的交互式对话,并执行情绪分析,以了解用户的感受(即不满意、沮丧和高兴),并相应地提出建议、执行流程和/或打开/发送票证。这消除了让 IT 人员专门处理日常任务的需要。

基于人工智能的自动化如何加速左移?

如今,员工发现 IT 服务不像消费者服务那样容易访问和使用。考虑到 IT 而设计的错综复杂的 SLA 和过程,对用户来说意味着漫长的等待时间和繁琐的手续。僵化的 ITSM 模式无法适应员工希望工作的时间、地点和方式的多样性,尤其是在下一代员工成长过程中,智能手机、平板电脑、社交媒体和即时获取信息已成为常态。

事实上,根据普华永道的一项调查,千禧一代倾向于对僵化的公司结构感到不舒服,并对信息孤岛感到厌烦。该调查强调,59%的千禧一代表示,在考虑工作时,雇主提供的最先进的技术对他们来说很重要,41%的人表示,他们更喜欢在工作中进行电子沟通,而不是面对面或甚至通过电话。

正如语音激活的人工智能助理(如 Siri、Alexa 和 Cortana)越来越多地被用于根据买家行为、购买决策和售后客户服务互动来更好地理解和优化消费者体验一样,基于人工智能的自动化也为 IT 提供了类似的好处。IT 组织可以利用这些技术与业务利益相关者建立更紧密的关系,并深入了解如何创造更具吸引力的服务体验。

基于人工智能的自动化通过使其能够识别和预测:

  • 交付和维护工作场所技术的最佳渠道、时间和实践
  • 可以通过接触较少、成本较低的交付渠道处理的手动和重复性流程
  • 哪些服务产生的查询最多,如何主动补救

在未来的博客中,我将讨论媒体围绕人工智能消除对人类的需求的炒作。然而,现在我只想说,试图让 it 专家脱离客户体验并实现自动化是不现实的,也不是所有的 IT 任务都可以完全自动化。

基于人工智能的自动化左移的目的是更好地利用和调整 IT 资源、组织数据和服务交付渠道。这对消费和提供商业服务的人来说都增加了 ITSM 的价值。

欠采样算法的缺点:CCMUT 和 E-CCMUT

原文:https://towardsdatascience.com/shortcoming-of-under-sampling-algorithms-ccmut-and-e-ccmut-10fd24f54852?source=collection_archive---------17-----------------------

什么、为什么、可能的解决方案和最终效用

在我以前的一篇文章中, 欠采样:不平衡数据的性能助推器 :

[## 欠采样:不平衡数据的性能助推器

在某些情况下,用于开发机器学习/深度学习模型的数据集通常是…

towardsdatascience.com](/under-sampling-a-performance-booster-on-imbalanced-data-a79ff1559fab)

我已经在成人人口普查数据上应用了基于聚类质心的多数欠采样技术(CCMUT) ,并证明了模型性能改进 w.r.t 最新模型,“成人人口普查收入水平预测的统计方法【1】。但是使用 CCMUT 开发的改进模型存在一个潜在的缺点。

CCMUT/E-CCMUT 的缺点:

所开发的模型给出了 90.78%的验证准确度,高于最先进的 88.16%。但是,在模型开发中,CCMUT 已经删除或欠采样了 68%的标签为 0 的实例(多数类实例)。因此,这 68%的实例既不包括在模型的训练集中,也不包括在模型的验证集中。因此,可以创建另一个数据集,测试集保存这些欠采样的实例,所有实例的标签都是 0。之后,在如此创建的测试集上测试经过训练和验证的模型。

令我十分惊讶的是,16810 个实例中只有 3 个被正确分类。这对开发出来的车型是一个很大的潜在威胁。而 Chakrabarty 和 Biswas [1]的最新模型在相同的 16810 个实例中正确地给出了16000 个,,从而保留了模型的通用性。现在的问题是,如果通过引入欠采样开发的模型导致了这样的错误,那么欠采样带来的性能改善究竟是什么?

是的,欠采样确实提高了性能。通过欠采样创建的模型的验证集有 3,151 个混合标签(0 和 1)的实例。在该验证集上,该模型从 3,151 个实例中正确分类了 2,861 个(90.78%的准确率),而当在这 3,151 个实例上测试时,最新技术从 3,151 个实例中给出了 2,589 个正确预测(82.16%的准确率)。因此,在这方面,性能肯定有所提升。但与此同时,还有一个表现不佳的典型案例。

退税原因:

这种缺点的主要原因在于 CCMUT 和 E-CCMUT 的成帧。这些算法是使用特征空间几何和聚类理论构建的。因此,欠采样实例实际上并不重要。它们是离群值,很有可能处于任何机器学习算法绘制的决策边界的错误一侧的边界或**。换句话说,这些实例可以被解释为难以正确分类的实例。所以,我只是倒回 CCMUT/E-CCMUT 算法工作声明,并进行修正:**

离聚类中心最远的数据点最难分类/预测,而离聚类中心最近的实例最容易分类/预测**。**

因此,在更容易分类/预测的实例中,CCMUT/E-CCMUT 表现得更好,从而提高了性能。但是当在难以分类的实例上测试时,CCMUT/E-CCMUT 表现不佳。这是因为在欠采样的情况下,训练集没有获得足够的难以分类/预测的实例,并且仅获得更接近多数类的聚类质心的实例,这些实例更容易分类/预测。当在这样的实例(困难的实例)上进行测试时,模型会完全混乱,并在大多数情况下预测错误的标签。

消除缺点的方法:

  1. 欠采样应该以很小的百分比进行(1-10%)。然后,模型开始学习一些难以分类的实例。但是,如果这不能在它自己的验证集中获得任何性能改进,它可能会失败。
  2. 欠采样之后是随机选择:这里,在欠采样少于 50%之后,在欠采样实例中,可以进行数据点的随机选择。那么这些随机选择的数据点可以包含在模型的训练集中。另外,未被随机选择的剩余欠采样实例可以形成测试集。****

我完全出于直觉设计了这些方法,这些方法背后没有数学依据。这些方法也不能总是在每个数据集上获得性能提升。

CCMUT/E-CCMUT 的效用在哪里?

排序程序(最易分类— — >难分类)在识别样本性质中起着非常重要的作用。因此,CCMUT/E-CCMUT 可用于数据集细化或数据清理**。如果数据集已准备好,但它包含噪声实例,这对机器学习模型开发可能是一种威胁。因此,数据集创建者/编译器( UCI / Kaggle )可以使用 CCMUT/E-CCMUT 对这类实例进行欠采样,从而有利于预测分析。**

撰写本文的动机

我要感谢 Victor Deplasse 作为我这篇文章背后的动力,他通读了我的文章“ 欠采样:不平衡数据的性能助推器 ”,并质疑欠采样算法 CCMUT 和 E-CCMUT 的一致性,因为我确信它们是完美的性能助推器。我还要感谢 TDS 团队给了我一个平台,让我以文章的形式交流我的想法,并得到我的读者的认可。

非常感谢数据科学!!!

参考文献

[1]查克拉巴蒂和比斯瓦斯,2018 年。成人人口普查收入水平预测的统计方法。 arXiv 预印本 arXiv:1810.10076

最有效的数据说书人说服,而不是告知

原文:https://towardsdatascience.com/should-data-stories-inform-or-persuade-2753330f3f37?source=collection_archive---------13-----------------------

Tempting the audience? Photo by Aaron Kato on Unsplash

转变思维,完善您的数据故事

在你创建一个数据故事之前,你需要一些指导方针,一些规则。你想变得有效率。你花了这么多时间来检查数据并确定它的含义。但是到底什么是数据故事呢?

我最近的目标是找到一个标准的数据故事定义。经过几个小时的研究,我明白了一百万种讲述更好的数据故事的方法,但仍然不知道这个数据故事的目的是提供信息还是说服他人。

为什么找到一个定义如此棘手?

数据叙事是一个包罗万象的短语吗?

不同的专家提出了几种定义。所有的定义都同意这是一个可视化分析数据结果的过程。一些描述包括像“影响业务”或“决定行动”这样的词,以表明这个故事需要一个说服的元素。其他人很乐意停留在“告诉别人你学到了什么”这一点上。

当你寻找例子时,它变得更加奇怪。我不会指名道姓,但这里是我的一些发现。

  • 一篇文章说,如果你有一个带有描述性标题的结构良好的图表,那么你就有一个数据故事。如果图表是米纳尔德的拿破仑俄国战役地图,这个例子可能是对的。
  • 一篇很有前途的文章提供了许多讲述数据故事的方法,但没有实现。它展示了几幅图表。这表明折线图是一个关于价值变化的数据故事。有一张图表显示了消极和积极的趋势。因为这是两个不同的数据故事。(或者这是一个带有点击诱饵标题的产品演示?)
  • 另一篇以谷歌视频为特色的文章被贴上了数据故事的标签。这段视频展示了一位女士在输入一个查询,一些时髦的人在跳舞,还有一段嘻哈音乐。视频从未呈现数据。消息“哟!谷歌爱自己,做查询”很明显。不是一个揭示的情节线和不是一个数据故事

有两种数据讲故事的方法吗?

完成研究后,我发现了两种数据故事类型——信息型和说服型。数据记者讲翔实的故事,营销人员讲有说服力的故事。

一个信息丰富的数据故事是纽约最嘈杂街区的地图。这个深入的数据故事通过几个图表编织了一个叙事。令人惊讶的事实是,某些社区对冰淇淋车的抱怨多于其他因素。

Trying to read on a busy street. Photo by Moses Vega on Unsplash

这很有趣,但并不令人信服。**“大城市很吵”**似乎并不奇怪。作者本·威灵顿解释了它们为什么吵闹。他的结论是“应该有人来解决这个问题。”所以,他有一个平台,但他没有提出任何改变的建议。感觉他在浪费我的时间。

找到令人信服的数据故事很难。我想起了已故的汉斯·罗斯林。他的数据故事说服观众让世界变得更美好。在他的数字是无聊的,人是有趣的谈话中,他用自己作为例子。他鼓励我们改变对家庭的看法。(他的书名透露了一个讲故事的好秘诀——讲的是人,而不是统计 。)

这个定义有共鸣吗?

如果你想把数据故事带入商业世界,用一个营销者的观点。我提供的数据解释了发生的事情,没有重点,甚至没有建议——这是新闻。

像威灵顿教授一样,我有一个平台,但没有一个观点。当我用数据证明一个观点并要求改变时,我是最有效的。

请击鼓。这是我的定义:

“数据故事以一种鼓励组织行动的方式结合了引人注目的数据、有价值的可视化和强有力的叙述。”

数据专业人员需要在工作中运用说服技巧。组织花费大量精力来组织他们的数据。在未来几年,将数据转化为导致变革的故事的能力至关重要。

我应该用 Kickstarter 来资助我的想法吗?

原文:https://towardsdatascience.com/should-i-use-kickstarter-to-fund-my-idea-2a56b40c9d44?source=collection_archive---------7-----------------------

image ” by rawpixel on Unsplash

我在实践中学习,所以我一直在寻找有趣的数据集来分析,这样我就可以不断建立我的数据分析技能集并展示它。自然,我很高兴在 Kaggle 上看到关于 Kickstarter 活动的数据集。我听说过很多关于 Kickstarter 作为一种为自己的企业融资的方式,我想知道它实际上是一种多么成功的方式。以下是从数据中获得的一些见解。

Kickstarter 活动通常是由美国人发起的。

其他公司位于北美、澳大利亚和西欧。Kickstarter 在亚洲(日本除外)、南美或非洲几乎没有业务。

The largest market for Kickstarter campaigns is the US with almost 300k campaigns, almost 10x the next largest market of Great Britain.

Kickstarter 作为众筹平台的受欢迎程度在 2014 年达到顶峰

我惊讶地发现,Kickstarter 活动在 2014 年达到顶峰,此后一直稳步下降,每季度约 8 千英镑。是什么导致了这样的下降?一种假设可能是由于 2014 年 2 月的数据泄露,这可能导致宣誓者和活动所有者对该公司失去信任。另一个假设是一个视频游戏开发商(克里斯·罗伯茨)在 2014 年年中公布的 WordPress 众筹插件。最后,这种下降也可能是由于竞争对手网站 GoFundMe 的崛起,该网站在 2014 年第四季度超过 KickStarter 成为最受欢迎的众筹网站。

成功达到 Kickstarter 目标的几率有多大?

大约三分之一,尽管它因 Kickstarter 的类别而异,并随着时间的推移而变化。

For every successful Kickstarter campaign, there are roughly two failed or canceled campaigns.

近年来,成功率已上升至 38%,但仍低于 2011 年 46%的峰值。

什么类型的活动最有可能成功?

漫画和舞蹈有超过 60%的成功几率。有趣的是,舞蹈是 2017 年美国最不受欢迎的 Kickstarter 类型,只有不到 300 个活动。

成功的竞选活动也有较高的支持者中位数。

在美国,成功竞选的每位支持者承诺的金额中值是 42 美元!大多数人的认捐额在 0-20 美元之间。

这些年来,认捐少于 20 美元的支持者人数一直在上升,而支持者总数却在下降。

Total number of backers per campaign has decreased recently

结论:

如果符合以下条件,Kickstarter 将是为你的想法提供资金的好方法:

  1. 你的想法与舞蹈或漫画有关
  2. 你有一个庞大的网络
  3. 你的目标很小
  4. 你期望每个支持者贡献大约 20 美元或更少。
posted @ 2024-10-13 15:16  绝不原创的飞龙  阅读(14)  评论(0编辑  收藏  举报