TowardsDataScience 博客中文翻译 2019(三百四十二)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

衡量绩效:准确性

原文:https://towardsdatascience.com/measuring-performance-accuracy-db54b6dca250?source=collection_archive---------14-----------------------

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

这篇文章开始了一个关于性能指标的新系列,并简要讨论了最广为人知的方法:准确度= #正确/总数。要点:当数据集平衡时,准确性是最有用的。

考虑一组猫和狗的照片。您想要建立一个模型来确定照片是猫还是狗。假设你有一个总是猜“猫”的天真模型。下面是准确性如何根据数据的偏斜而变化:

正如你所看到的,如果数据集包含的猫的照片比狗的照片多得多,一个总是猜测“猫”的愚蠢模型的准确性仍然很高。这个模型对猫长什么样、狗长什么样一无所知,但如果只看精度,我们可能会认为模型表现不错。

在不平衡数据集上训练机器学习模型的一个风险是,该模型可能会学习总是输出多数类作为其预测。这不是一个有用的模型,但它会达到很高的精度。

以下是关于如何使用准确性来判断机器学习模型的提示:

  • 如果你的类是平衡的(相同数量的猫和狗),那么准确度是一个有用的性能指标
  • 如果你的类是不平衡的,那么计算“朴素模型准确度”为“多数类中的实例数/总实例数”然后,当你查看你的机器学习模型的准确性时,你可以将其与天真模型的准确性进行比较。
  • 如果你有 80 张猫的照片,20 张狗的照片,你的天真准确率是 80%;因此,在这个数据集上达到 80%的机器学习模型并不比天真的模型做得更好
  • 另一方面,一个达到 95%的机器学习模型学到了东西!
  • 如果您的类别不平衡,您还应该计算比准确度更能提供信息的性能指标,例如接收器操作特征下的面积(也称为 AUROC、AUC、c-statistic)或精确度-召回曲线下的面积(AUPRC)

为了准确就是这样!本系列关于性能指标的后续文章将讨论 AUROC 和 AUPRC。

图片来源:小猫小狗

原载于 2019 年 2 月 16 日http://glassboxmedicine.com

衡量业绩:AUC (AUROC)

原文:https://towardsdatascience.com/measuring-performance-auc-auroc-8c8bbfe9be91?source=collection_archive---------16-----------------------

受试者操作特征(AUROC)下的面积是一个性能指标,可用于评估分类模型。AUROC 会告诉您您的模型是否能够正确排列示例:

  • 对于临床风险预测模型,AUROC 告诉您随机选择的经历了某一事件的患者比随机选择的未经历该事件的患者具有更高的预测风险评分的概率( ref )。
  • 对于二进制手写数字分类模型(“1”对“0”),AUROC 会告诉您随机选择的“1”图像比随机选择的“0”图像具有更高的“1”预测概率

因此,【AUROC 是一个“区分”的性能指标:它告诉你模型区分案例(正面例子)和非案例(负面例子)的能力。)0.8 的 AUROC 意味着该模型具有良好的区分能力: 80%的时候,该模型将正确地为随机选择的有事件的患者分配比随机选择的无事件患者更高的绝对风险

如何解释 AUROC ( ref )

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

图:ROC 曲线(根据这幅漫画修改)

上图显示了一些 ROC 曲线示例。给定曲线的 AUROC 就是其下方的面积。

最差的 AUROC 是 0.5,最好的 AUROC 是 1.0。

  • 0.5 的 AUROC(上图中红色虚线下的区域)对应于抛硬币,即无用的模型。
  • 小于 0.7 的 AUROC 是次优性能
  • 0.70–0.80 的 AUROC 是良好的性能
  • 大于 0.8 的 AUROC 是极好的性能
  • AUROC 为 1.0(上图中紫色线下的区域)相当于一个完美的分类器

如何计算 AUROC

AUROC 计算为 ROC 曲线下的面积。ROC 曲线显示了跨不同决策阈值的真阳性率(TPR)和假阳性率(FPR)之间的权衡。有关 TPR、FPR 和决策阈值的回顾,请参见衡量绩效:混淆矩阵

在绘制的 ROC 曲线中(例如上一节的图),决策阈值是隐含的。决策阈值是显示为轴的而不是。AUROC 本身也没有明确显示;这意味着,显示的 ROC 曲线下的面积。

ROC 曲线的 x 轴是假阳性率,ROC 曲线的 y 轴是真阳性率。

  • ROC 曲线总是从左下角开始,即对应于决策阈值 1 的点(FPR = 0,TPR = 0 )(其中每个例子都被分类为阴性,因为所有预测的概率都小于 1)。)
  • ROC 曲线总是在右上角结束,即对应于决策阈值 0 的点(FPR = 1,TPR = 1 )(其中每个例子都被分类为阳性,因为所有预测的概率都大于 0)。)
  • 创建曲线的中间点是通过针对 1 和 0 之间的不同决策阈值计算 TPR 和 FPR 来获得的。对于一个粗糙的、有角度的“曲线”,你可以只使用几个判决阈值:例如判决阈值[1,0.75,0.5,0.25,0]。对于更平滑的曲线,您可以使用许多决策阈值,例如[1,0.98,0.96,0.94,…,0.08,0.06,0.04,0.02,0]的决策阈值。

下图显示了根据真实数据计算的 ROC 曲线,在 ROC 曲线的锯齿状本质中,使用离散决策阈值更容易理解:

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

(图来源)

为二元分类任务计算测试集 AUROC 的步骤:

  1. 训练你的机器学习模型
  2. 使用定型模型对测试集进行预测,这样测试集中的每个示例都有介于 0 和 1 之间的分类概率。
  3. 使用测试集的模型输出预测概率,计算不同决策阈值的 TPR 和 FPR,并绘制 ROC 曲线。
  4. 计算 ROC 曲线下的面积。

实际上,您不需要编写代码来手动计算 AUROC。许多编程语言中都有计算 AUROC 的函数。例如,在 Python 中,您可以执行以下操作:

导入 sklearn.metrics

fpr,tpr,thresholds = sk learn . metrics . roc _ curve(y _ true = true _ labels,y_score = pred_probs,pos _ label = 1)#正类为 1;负类为 0
auroc = sk learn . metrics . AUC(FPR,tpr)

首先,向函数 sklearn.metrics.roc_curve()提供基本事实测试集标签(作为向量 y_true)和模型的预测概率(作为向量 y_score ),以获得输出 fpr、tpr 和阈值。fpr 是具有针对不同阈值计算的假阳性率的向量;tpr 是具有不同阈值的计算的真阳性率的向量;thresholds 是一个带有实际阈值的向量,只是在您想要检查它的情况下提供的(在下一个函数中,您不需要显式的 thresholds 向量。)向量 fpr 和 tpr 定义了 ROC 曲线。然后将 fpr 和 tpr 向量传递给 sklearn.metrics.auc()以获得 AUROC 最终值。

何时使用 AUROC

对于不平衡数据,AUROC 比准确性更能提供信息。这是一个非常常见的性能指标,使用各种软件包很容易计算,因此为执行二元分类任务的模型计算 AUROC 通常是一个好主意。

了解 AUROC 的局限性也很重要。AUROC 可能对模型的性能“过于乐观”,这些模型是为反面例子比正面例子多得多的数据集构建的。许多真实世界的数据集都符合这一描述:例如,您可能会认为在从普通人群中抽取的数据集中,健康的人(“疾病阴性”)比患病的人(“疾病阳性”)多得多。)在这些真阴性支配真阳性的情况下,可能很难用 AUROC 来区分两种算法的性能。

为什么?在负样本比正样本多得多的情况下,假阳性数量的大幅提高只会导致假阳性率的小幅变化。这是因为假阳性率被计算为假阳性/(假阳性+真阴性),如果我们在分母中有大量的真阴性,那么仅仅通过改变假阳性就很难改变假阳性率。

假装算法 1 比算法 2 的假阳性少得多(即算法 1 更好)。如果数据有很多真阴性,算法 1 和算法 2 的假阳性率不会有太大差别,它们的 AUROCs 也不会有太大差别。

要点:AUROC 是一个有用的指标,但是你应该知道 AUROC 并没有捕捉到大量负面例子对算法性能的影响。另一个不会被真阴性“淹没”的性能指标是精确召回曲线下面积(AUPRC ),这将在以后的帖子中讨论。

本节的参考(也是额外深入讨论的重要资源):精确召回和 ROC 曲线之间的关系

如果我的模型预测了两个以上的类怎么办?

你可以分别计算每个类的 AUROC,例如,假设你的任务由许多不同的二进制分类任务组成:A 类与非 A 类,B 类与非 B 类,C 类与非 C 类等等。

命名法

受试者操作特征下面积的最常见缩写是“AUC”这是一个糟糕的术语,因为 AUC 只是代表“曲线下面积”(并没有具体说明什么曲线;ROC 曲线仅仅是隐含的)。因此,在这篇文章中,我更喜欢缩写 AUROC。你也可以看到 AUROC 被称为 c 统计量或“一致性统计量”

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

上图是一个 “auroch” ,不要和一个" AUROC ":)混淆。奥罗克牛是一种现已灭绝的牛,曾经生活在北非、欧洲和亚洲。(杜克+DS 的另一名成员带给你的自然琐事,他在一次关于“AUROC”缩写的讨论中让我想起了 auroch。)

结束了!请继续关注未来关于 AUROC 的表亲 AUPRC 的帖子。

原载于 2019 年 2 月 23 日http://glassboxmedicine.com

测量性能:AUPRC 和平均精度

原文:https://towardsdatascience.com/measuring-performance-auprc-e71819c26425?source=collection_archive---------14-----------------------

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

精确召回曲线下的面积(AUPRC)是一个有用的性能指标,用于在您非常关心寻找正面例子的问题设置中的不平衡数据。例如,您可能正在构建一个分类器来检测胸部 x 射线中的气胸,并且您希望确保找到所有气胸,而不会错误地将健康肺标记为气胸阳性。如果您的模型获得了完美的 AUPRC,这意味着您的模型找到了所有的阳性样本/气胸患者(完美回忆),而没有意外地将任何阴性样本/健康患者标记为阳性(完美精确)。“平均精度”是计算 AUPRC 的一种特殊方法。

如何解读 AUPRC

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

Figure: PR Curves, from scikit-learn

上图显示了一些 PR 曲线示例。给定类别的 AUPRC 就是其 PR 曲线下的面积。

解释 AUPRC 比解释 AUROC ( 接收器工作特性下的区域)要稍微棘手一些。这是因为 AUROC 的基线永远是 0.5——一个随机的分类器,或者一次抛硬币,会得到 0.5 的 AUROC。但是对于 AUPRC,基线等于阳性分数(斋藤等人),其中阳性分数计算为(#阳性样本数/总样本数)。这意味着不同的类别有不同的 AUPRC 基线。一个有 12%阳性的类的基线 AUPRC 是 0.12,所以在这个类上获得 0.40 的 AUPRC 是非常好的。然而,98%阳性的类的基线 AUPRC 为 0.98,这意味着在该类上获得 0.40 的 AUPRC 是不好的。

对于许多真实世界的数据集,尤其是医学数据集,阳性率通常小于 0.5,这意味着 AUPRC 的基线值低于 AUROC。因此,AUPRC 的绝对值通常小于 AUROC。例如,可以获得 0.8 的 AUROC 和 0.3 的 AUPRC。我认为这是 AUPRC 在文献中不像 AUROC 那样经常被报道的一个原因。获得 0.8 的性能“听起来更令人印象深刻”,尽管手头上更有意义的数字可能是 0.3 AUPRC。不要让趋势让你气馁;AUPRC 是一个关键的计算指标,适用于对阳性结果进行正确分类非常重要的问题,例如,根据实验室测试预测患者的诊断,或预测患者是否会出现并发症,或预测患者是否需要去医院。你可以同时报告 AUPRC 和 AUROC。

如何计算 AUPRC

AUPRC 计算为 PR 曲线下的面积。PR 曲线显示了不同决策阈值的精确度和召回率之间的权衡。

(注意,“回忆”是真阳性率(TPR)的另一个名称。因此,AUPRC 和 AUROC 都利用 TPR。有关 TPR、精度和决策阈值的回顾,请参见测量性能:混淆矩阵。)

PR 曲线的 x 轴是召回率,y 轴是精确度。这与 ROC 曲线相反,ROC 曲线的 y 轴是召回,x 轴是 FPR。类似于绘制的 ROC 曲线,在绘制的 PR 曲线中,决策阈值是隐含的,并且不显示为单独的轴。

  • PR 曲线开始于左上角,即对应于决策阈值 1 的点(召回= 0,精度= 1 )(其中每个例子都被分类为否定的,因为所有预测的概率都小于 1)。)注意,具有最大输出值的示例的基础事实标签(正或负)对 PR 曲线的外观有很大影响。
  • PR 曲线在右下角结束,这里 recall = 1,precision 较低。这对应于决策阈值 0(其中每个例子都被分类为肯定的,因为所有预测的概率都大于 0。)注意,接近零的召回精度的估计往往具有高方差。
  • 创建 PR 曲线的中间点是通过计算 1 和 0 之间的不同决策阈值的精度和召回率来获得的。对于一个粗略的“角度”曲线,你可以只使用几个决策阈值。对于更平滑的曲线,可以使用许多决策阈值。

为什么要看精度和召回率的权衡?同时考虑召回率和精确度是很重要的,因为您可以使用将所有内容标记为肯定的朴素分类器来实现完美的召回率(但精确度较差),也可以使用将所有内容标记为否定的朴素分类器来实现完美的精确度(但召回率较差)。

为了计算 AUPRC,我们计算 PR 曲线下的面积。有多种方法可以计算 PR 曲线下的面积,包括下梯形估计量、插值中值估计量和平均精度。

我喜欢用平均精度来计算 AUPRC。在 Python 中,平均精度的计算方法如下:

import sklearn.metrics
auprc = sklearn.metrics.average_precision_score(true_labels, predicted_probs)

对于此函数,您需要提供一个基本事实标签的向量(true_labels)和一个来自模型的相应预测概率的向量(predicted_probs)。) Sklearn 会利用这些信息为你计算平均精度。

在函数文档中,“平均精度”将精度-召回曲线总结为在每个阈值达到的精度的加权平均值,召回从前一个阈值的增量作为权重。[……]这种实现是不插值的,不同于使用梯形规则输出精度-召回曲线下的面积,后者使用线性插值,可能过于乐观。”

其他章节参考:Boyd 等人,“精确度-召回曲线下的区域:点估计和置信区间。”

AUPRC &真底片

PR 曲线的一个有趣特征是它们根本不使用真正的负值:

  • Recall = TPR =真阳性/(真阳性+假阴性)。回忆可以被认为是分类器将所有正例正确标记为正例的能力。
  • 精度=真阳性/(真阳性+假阳性)。精确度可以被认为是分类器不将阴性样本错误标记为阳性样本的能力(参考

因为 PR 曲线在任何地方都不使用真负值,AUPRC 不会被数据中的大部分真负值“淹没”。您可以在具有 98%负样本/2%正样本的数据集上使用 AUPRC,它将“关注”模型如何处理 2%正样本。如果模型很好地处理了正例,AUPRC 就会很高。如果模型在正面例子上表现不佳,AUPRC 将会很低。

具有讽刺意味的是,AUPRC 通常在其基线最低时最有用,因为有许多数据集具有大量真阴性,其目标是尽可能好地处理一小部分阳性。

如果我的模型预测了两个以上的类怎么办?

您可以假设您的任务由许多不同的二进制分类任务组成,并计算 A 类与非 A 类、B 类与非 B 类、C 类与非 C 类等的 AUPRC。

总结

  • AUPRC 的计算方法有很多种,包括平均精度。
  • 当一个模型找到所有的正例(完全回忆)而没有意外地将任何负例标记为正例(完全精确)时,它实现了完全 AUPRC。
  • AUPRC 的基线等于阳性分数。如果数据集包含 8%的癌症样本和 92%的健康样本,则基线 AUPRC 为 0.08,因此在这种情况下获得 0.40 的 AUPRC 是很好的!
  • 当你非常关心你的模型正确处理正例时,AUPRC 是最有用的。
  • AUPRC 的计算根本不涉及真负值。

关于特色图片

天平的特色图像从这里的修改为

原载于 2019 年 3 月 2 日【http://glassboxmedicine.com

衡量绩效:困惑矩阵

原文:https://towardsdatascience.com/measuring-performance-the-confusion-matrix-25c17b78e516?source=collection_archive---------19-----------------------

混淆矩阵是使用模型对数据集的预测来计算的。通过查看混淆矩阵,您可以更好地了解您的模型的优点和缺点,并且可以更好地比较两个备选模型,以了解哪一个更适合您的应用程序。传统上,混淆矩阵是使用模型对保留测试集的预测来计算的。

这是一个混淆矩阵:

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

列标签“实际阳性”和“实际阴性”是指数据集中的基本事实标签,即手写数字是真正的 1 还是 0,患者是否真正被诊断患有疾病(1)或不是(0),胸部 x 光片是否实际显示肺炎(1)或不是(0)等。

行标签“预测正”和“预测负”指的是您的模型的预测,即您的模型认为标签是什么。

注意混淆矩阵(TPs,FPs,FNs,TNs)内的条目是计数:

  • 真阳性(TPs):模型正确分类为阳性的阳性样本的数量
  • 真实否定(TNs):模型正确分类为否定的否定例子的数量
  • 假阳性(FPs):被模型错误分类为阳性的阴性样本的数量(即被错误分类为“阳性”的阴性样本)
  • 假阴性(FNs):被模型错误分类为阴性的阳性样本的数量(即被错误分类为“阴性”的阳性样本)

真阳性率和假阳性率

您可以使用混淆矩阵来计算真阳性率(TPR)和假阳性率(FPR)。稍后将需要 TPR 和 FPR 来计算接收机工作特性(AUROC)下的面积,AUROC 是一个流行的性能指标。

真阳性率=真阳性/所有阳性=真阳性/(真阳性+假阴性)

假阳性率=假阳性/全部阴性=假阳性/(假阳性+真阴性)

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

( ref

(在上面的公式中,FNR =假阴性率,TNR =真阴性率,这些是可以从混淆矩阵中计算出来的其他量。)

精度

你也可以使用混淆矩阵来计算精度。稍后将需要精度以及真实的阳性率(也称为“召回”),来计算精度-召回曲线下的面积(AUPRC),这是另一个流行的性能指标。

精度=真阳性/(真阳性+假阳性)

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

(参考)

决策阈值

决策阈值允许您将预测概率转换为预测标签。如果模型输出概率,则必须使用决策阈值将这些概率转换为预测标签。一旦你有了预测的标签,你就可以计算一个混淆矩阵。您还需要预测标签来计算 AUROC 和 AUPRC,使用不同的决策阈值进行计算。

“决策阈值”就是您选择用来与某个概率进行比较的数字,以决定该概率应该指示正类还是负类。

常见的决策阈值是 0.5,这意味着任何小于 0.5 的概率都被认为是否定类别的一部分,而任何大于 0.5 的概率都被认为属于肯定类别。

然而,实际上你可以选择任何你想要的决策阈值。您可以将决策阈值设为 0.99,这样一个例子的预测概率必须大于 0.99 才能被认为是“肯定的”。这意味着你的大多数例子会被认为是负面的。

极限决策阈值

如果选择决策阈值为 0,则每个示例都将被认为是正面的:

  • 这意味着每个例子要么是真阳性,要么是假阳性
  • 真正的正率将是 1 (TPR = TP / (TP + FN)但 FN = 0,所以 TPR = TP/TP = 1)
  • 假阳性率将是 1 (FPR = FP / (FP + TN)但是 TN = 0,所以 FPR = FP/FP = 1)
  • 精度的值将取决于数据的偏差。如果数据集中实际阳性和实际阴性数量相等,则精度为 0.5(精度= TP / (TP + FP) = 50 / (50+50) = 0.5)。如果实际阳性多得多,精度会大于 0.5;如果实际底片多得多,精度会小于 0.5。

如果选择决策阈值 1,则每个示例都将被认为是负面的:

  • 这意味着每个例子要么是真阴性,要么是假阴性
  • 真正的正率将是 0 (TPR = TP / (TP + FN)但是 TP = 0,所以 TPR = 0)
  • 假阳性率将是 0 (FPR = FP / (FP + TN)但是 FP = 0,所以 FPR = 0)
  • 从技术上讲,精度将是未定义的(精度= TP / (TP + FP) = 0/0)

如何选择决策阈值

决策阈值的选择取决于模型的下游应用。

例如:在某些医疗应用中,假阴性可能比假阳性更糟糕,例如,在皮肤病学照片的自动分类中,您不想错过一个黑色素瘤病例。在这种情况下,您希望选择较低的决策阈值,以便将更多的示例分类为阳性,这将降低您的假阴性率,但会增加假阳性率。

例子:想象一下,在一个社会中,预测模型被用来决定罪犯是应该被说服还是被释放。在这种情况下,假阳性可能比假阴性更糟糕,例如,如果模型错误地确定一个无辜的人有罪,并把那个人送进监狱,那就太糟糕了。(谢天谢地,这一场景仍在反乌托邦科幻小说中,至少目前如此……)

AUROC 和 AUPRC 曲线还可以帮助您直观地了解不同决策阈值导致的权衡,并帮助您为模型的下游应用选择一个好的决策阈值。

其他名称

  • 真正的阳性率也称为敏感度、回忆率或命中率
  • 精确度也称为阳性预测值(PPV)

混乱矩阵的更多细节

维基百科上有一篇关于混淆矩阵的伟大文章。它包括关于可以从混淆矩阵计算的其他量的更多细节,包括特异性(也称为选择性或真阴性率)和阴性预测值。

敬请关注未来关于 AUROC 和 AUPRC 的帖子,这两个都是机器学习模型非常有用的性能指标。

原载于 2019 年 2 月 17 日http://glassboxmedicine.com

营销分析——衡量客户终身价值(CLTV)

原文:https://towardsdatascience.com/measuring-users-with-customer-lifetime-value-cltv-94fccb4e532e?source=collection_archive---------13-----------------------

CLTV 客户生命周期作为营销技术堆栈

CLTV 测量到设备有效的营销策略

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

【https://sarit-maitra.medium.com/membership 号

C 客户生命周期价值(CLTV)是一项定量分析,是现代以客户为中心的商业场景中最重要的指标之一。多年来,它一直是直复营销的主要概念,并在营销领域得到越来越多的考虑。在这里,我们将试验一个可实施的 CLTV 模型,该模型对于市场细分和为获取、保留和交叉销售分配营销资源是有用的。模型的选择是基于系统的理论分类法和嵌入客户行为的假设。

数据收集:

相关数据总是任何预测的基础,CLTV 也不例外。以下是我们可能想要回答的一些例子/问题:

  • 每位特定顾客已经在你的商店消费了多少钱?
  • 每个特定的客户实际上已经成为客户多久了?
  • 每个特定客户的年龄是多少?年龄是客户画像的重要组成部分。
  • 每位顾客对折扣和优惠的反应如何?如果我们知道谁更有可能做出反应,我们就可以制定策略,将营销资金准确地花在这些人身上,并得到一个结果。

业务问题:

本文的目的在于研究下面提到的商业问题。我将演示如何使用线性回归为 CLTV 建立预测模型。

  • 如何识别最赚钱的客户?
  • 一个公司怎样才能提供最好的东西并获得最大收益?
  • 如何细分盈利客户?
  • 需要花费多少预算来获得客户?

计算 CLTV 的方法很少。

让我们用一些简单的等式:

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

  • *客户价值=平均订单价值(AOV)购买频率

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

  • 流失率:流失率是没有再次订购的客户的百分比。
  • 客户寿命= 1/流失率
  • 流失率= 1-重复率

让我们获取数据并深入了解数据中的信息。

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

数据的统计分布:

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

条形图清楚地显示,我们来自英国的业务数量最多。从描述性统计数据中,我们可以看出,这一部分的数量处于负值。这实际上是不可能的。这可能是订单取消或退货。因此,我们需要过滤大于零的数量。此外,我们还将为 CLTV 分析过滤所需的列。我们需要数据集中的 CustomerID、InvoiceDate、InvoiceNo、数量和单价。

data = uk_data[(uk_data[‘Quantity’]>0)]data=uk_data[[‘CustomerID’,’InvoiceDate’,’InvoiceNo’,’Quantity’,’UnitPrice’]]
data[‘TotalPurchase’] = uk_data[‘Quantity’] * uk_data[‘UnitPrice’]

现在,我们将计算(a)当前日期和每个客户最后一次购买日期之间的天数,(b)每个客户的订单数量,©每个客户的购买价格总和。还可以通过重命名列来进一步纯化数据。

data_group= data.groupby(‘CustomerID’).agg({‘InvoiceDate’: lambda date: (date.max() — date.min()).days,
 ‘InvoiceNo’: lambda num: len(num),
 ‘Quantity’: lambda quant: quant.sum(),
 ‘TotalPurchase’: lambda price: price.sum()})# Change the name of columns
data_group.columns=[‘num_days’, ’num_transactions’, ’num_units’, ’spent_money’]
data_group.head()

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

CLTV 使用公式:

现在,我们将使用前面提到的公式计算 CLTV。

# Average Order Value
data_group[‘avg_order_value’]=uk_data_group[‘spent_money’]/uk_data_group[‘num_transactions’]#Purchase Frequency purchase_frequency=sum(uk_data_group[‘num_transactions’])/uk_data_group.shape[0]# Repeat Rate
repeat_rate=uk_data_group[uk_data_group.num_transactions > 1].shape[0]/uk_data_group.shape[0]#Churn Rate
churn_rate=1-repeat_rate
purchase_frequency,repeat_rate,churn_rate

#Output: (90.37107880642694,0.9818923743942872,0.018762577

利润率和 CLTV:

让我们假设企业赚取 25%的利润。

# Profit Margin
data_group[‘profit_margin’]= data_group[‘spent_money’]*0.25# Customer Value
data_group[‘CLTV’]= data_group[‘avg_order_value’]*purchase_frequency)/churn_rate#Customer Lifetime Value
data_group[‘cust_lifetime_value’]=data_group[‘CLTV’]*data_group[‘profit_margin’]

CLTV 的预测模型:

现在我们将使用线性回归模型来预测 CLTV。在将数据推至回归模型之前,我们需要做一些数据准备。

uk_data['month_yr'] = uk_data['InvoiceDate'].apply(lambda x: x.strftime('%b-%Y')) # Extract month and year from InvoiceDate.

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

# creating a pivot table taking the columns as input, and groups the entries into a two-dimensional table in such a way that provides a multidimensional summation of the data.sale=uk_data.pivot_table(index=[‘CustomerID’],columns=[‘month_yr’],values=’TotalPurchase’,aggfunc=’sum’,fill_value=0).reset_index()sale[‘CLV’]=sale.iloc[:,2:].sum(axis=1) # sum all the months sale
sale.head()

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

现在,让我们为现有客户建立一个回归模型。我们需要一组因变量(y)和自变量(X)。因此,我们将把过去六个月的数据作为自变量,把三年的总收入作为因变量,然后按照通常的 ML 过程分割训练和测试数据。

X=sale[[‘Dec-2011’,“Nov-2011”, ‘Oct-2011’,“Sept-2011”,’Aug-2011',’Jul-2011']]
y=sale[[‘CLV’]]#split training set and test set
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)linreg = LinearRegression() # instantiate
linreg.fit(X_train, y_train) # fitting the model to the training datay_pred = linreg.predict(X_test) # make predictions on the testing setprint(linreg.intercept_)
print(linreg.coef_)

模型评估:

让我们打印 R 平方,这是由模型解释的方差的比例,平均绝对误差(MAE),均方误差(MSE),均方根误差(RMSE)。

print(“R-Square:”,metrics.r2_score(y_test, y_pred))
print(“MAE:”,metrics.mean_absolute_error(y_test,y_pred))
print(“MSE”,metrics.mean_squared_error(y_test, y_pred))
print(“RMSE:”,np.sqrt(metrics.mean_squared_error(y_test, y_pred)))

r 平方值:0.96486386866

梅伊:56860 . 68686868686

最小二乘误差 21 . 58686868686

RMSE:18966 . 868686868686

当部署模型时,ML 算法有助于理解模式;它还会根据客户的 CLTV 预测对他们进行分类。考虑到 CLTV 可以找出最有利可图的客户,营销策略在这里很重要,但我们如何从他们那里获利,将取决于所采用的营销策略。此外,忠诚度计划可以基于这些见解来制定。

局限性:

目前还不清楚如何使用回归模型来预测未来很长一段时间内的购买者行为动态,然后将其全部绑定到每个客户的现值。

购买行为需要两个阶段——(a)定义 RFM 变量 1 和(b)得出因变量的值。如果我们能够仅仅使用第一阶段的数据来预测未来的购买行为,那就更好了。此外,最令人感兴趣的是利用所有可用数据进行模型校准,而不使用任何数据来创建回归型分析的因变量。

RFM 变量只是潜在行为特征的不完善指标。不同的数据“切片”将产生不同的 RFM 变量值,从而产生不同的评分模型参数。当我们利用一个时期的观察数据来预测未来的行为时,这具有重要的意义。

结论

LR 接近完美地预测了普通顾客一生中的消费。CLTV 帮助设计一个有效的商业计划,也提供了一个扩大业务的机会。然而,正如已经讨论过的,很多将取决于营销策略来获取利润。一般来说,营销自动化平台管理客户生命周期。营销平台协调营销活动,同时也自动化销售线索和客户在渠道中的流动。营销部门使用这些软件应用程序来计划、协调、执行、管理和衡量他们在多个渠道的营销活动,并自动执行重复性任务。

我这里可以连接

MeCab 用法并将用户词典添加到 MeCab

原文:https://towardsdatascience.com/mecab-usage-and-add-user-dictionary-to-mecab-9ee58966fc6?source=collection_archive---------19-----------------------

这是一个英语 MeCab 教程,面向那些不在 - 说日语的人的程序员

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

Photo by David Emrich on Unsplash

如果你是一个在日本工作的 NLP 工程师,你一定听说过文本分割库 MeCab。这个库在日本的学术界和工业界都被广泛使用。如果你的母语不是日语,使用这个工具可能会有困难,因为文档大部分是由日本人写的。所以我写这篇教程来减轻负担。

装置

Environment:
- macOS Mojave 10.14.6
- Xcode: 11.0 
- python 3
- pip 19.1

安装 MeCab 和字典。没有这些依赖项,mecab-python3 就无法工作。

$ brew install mecab
$ brew install mecab-ipadic

您可以运行mecab命令来尝试交互界面

$ mecab
おはようございます
おはよう    感動詞,*,*,*,*,*,おはよう,オハヨウ,オハヨー
ござい   助動詞,*,*,*,五段・ラ行特殊,連用形,ござる,ゴザイ,ゴザイ
ます  助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
EOS

安装 SWIG 。我们必须安装这个库,否则,安装 mecab-python3 时会出现错误。

$ brew install swig$ swig -versionSWIG Version 4.0.1Compiled with clang++ [x86_64-apple-darwin18.6.0]Configured options: +pcrePlease see [http://www.swig.org](http://www.swig.org) for reporting bugs and further information

最后安装 mecab-python3。

$ pip install mecab-python3Collecting mecab-python3
  Downloading [https://files.pythonhosted.org/packages/97/9f/3e5755e0488f608e3c2d18a0f3524434ebf36904b8fd4eec74a3e84416a9/mecab_python3-0.996.2-cp36-cp36m-macosx_10_6_intel.whl](https://files.pythonhosted.org/packages/97/9f/3e5755e0488f608e3c2d18a0f3524434ebf36904b8fd4eec74a3e84416a9/mecab_python3-0.996.2-cp36-cp36m-macosx_10_6_intel.whl) (14.1MB)
     |████████████████████████████████| 14.1MB 2.4MB/s 
Installing collected packages: mecab-python3
Successfully installed mecab-python3-0.996.2

安装程序已完成。我们可以写个剧本试试。

import MeCab
mecab = MeCab.Tagger("-Ochasen") # Create a MeCab object
malist = mecab.parse("NECが二位、東芝がモトローラを抜いて二年ぶりに三位になる。") # morphological analysis
print(malist)# output
NEC  エヌイーシー    NEC  名詞-固有名詞-組織
が      ガ      が      助詞-格助詞-一般
二      ニ      二      名詞-数
位      イ      位      名詞-接尾-助数詞
、      、      、      記号-読点
東芝    トウシバ        東芝    名詞-固有名詞-組織
が      ガ      が      助詞-格助詞-一般
モトローラ      モトローラ      モトローラ      名詞-固有名詞-組織
を      ヲ      を      助詞-格助詞-一般
抜い    ヌイ    抜く    動詞-自立       五段・カ行イ音便        連用タ接続
て      テ      て      助詞-接続助詞
二      ニ      二      名詞-数
年      ネン    年      名詞-接尾-助数詞
ぶり    ブリ    ぶり    名詞-接尾-一般
に      ニ      に      助詞-格助詞-一般
三      サン    三      名詞-数
位      イ      位      名詞-接尾-助数詞
に      ニ      に      助詞-格助詞-一般
なる    ナル    なる    動詞-自立       五段・ラ行      基本形
。      。      。      記号-句点
EOS

添加用户词典

根据官方文件显示,添加自定义词典有 2 种方式,更改“系统词典”和添加“用户词典”。如果我们改变“系统字典”,我们必须编译字典并重新安装。所以我们选择添加一个新的“用户词典”。

确定格式

首先,我们必须将自定义词典写入一个 CSV 文件,格式如下。

表層形,左文脈 ID,右文脈 ID,コスト,品詞,品詞細分類 1,品詞細分類 2,品詞細分類 3,活用型,活用形,原形,読み,発音Surface type, left context ID, right context ID, cost, part of speech, sub POS 1, sub-POS 2, sub-POS 3, conjugation type, conjugation form, original form, ruby, pronunciation

Each line contains 13 features. For example, if we want to add noun words (活用しない語), like location, people’s name, we could write like below.

工藤,1223,1223,6058,名詞,固有名詞,人名,名,*,*,くどう,クドウ,クドウ

But if we want to add adjectives or verb (活用する語), we have to add all their conjugation type (活用型) and conjugation forms (活用形). See the below example for the adjective “いそがしい”.

いそがしい,120,120,6078,形容詞,自立,*,*,形容詞・イ段,基本形,いそがしい,イソガシイ,イソガシイ
いそがし,128,128,6080,形容詞,自立,*,*,形容詞・イ段,文語基本形,いそがしい,イソガシ,イソガシ
いそがしから,136,136,6079,形容詞,自立,*,*,形容詞・イ段,未然ヌ接続,いそがしい,イソガシカラ,イソガシカラ
いそがしかろ,132,132,6079,形容詞,自立,*,*,形容詞・イ段,未然ウ接続,いそがしい,イソガシカロ,イソガシカロ
いそがしかっ,148,148,6078,形容詞,自立,*,*,形容詞・イ段,連用タ接続,いそがしい,イソガシカッ,イソガシカッ
いそがしく,152,152,6078,形容詞,自立,*,*,形容詞・イ段,連用テ接続,いそがしい,イソガシク,イソガシク
いそがしくっ,152,152,6079,形容詞,自立,*,*,形容詞・イ段,連用テ接続,いそがしい,イソガシクッ,イソガシクッ
いそがしゅう,144,144,6079,形容詞,自立,*,*,形容詞・イ段,連用ゴザイ接続,いそがしい,イソガシュウ,イソガシュウ
いそがしゅぅ,144,144,6079,形容詞,自立,*,*,形容詞・イ段,連用ゴザイ接続,いそがしい,イソガシュゥ,イソガシュゥ
いそがしき,124,124,6079,形容詞,自立,*,*,形容詞・イ段,体言接続,いそがしい,イソガシキ,イソガシキ
いそがしけれ,108,108,6079,形容詞,自立,*,*,形容詞・イ段,仮定形,いそがしい,イソガシケレ,イソガシケレ
いそがしかれ,140,140,6079,形容詞,自立,*,*,形容詞・イ段,命令e,いそがしい,イソガシカレ,イソガシカレ
いそがしけりゃ,112,112,6079,形容詞,自立,*,*,形容詞・イ段,仮定縮約1,いそがしい,イソガシケリャ,イソガシケリャ
いそがしきゃ,116,116,6079,形容詞,自立,*,*,形容詞・イ段,仮定縮約2,いそがしい,イソガシキャ,イソガシキャ
いそがし,104,104,6080,形容詞,自立,*,*,形容詞・イ段,ガル接続,いそがしい,イソガシ,イソガシ

长元音

下面是一个长元音现象的演示。

今日,,,10,名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
労働,,,10,名詞,サ変接続,*,*,*,*,労働,ロウドウ,ロードー

“今日” and “労働” are the surface form. “10” is the cost. Lower cost means this word has a high frequency in the corpus. “名詞” is the POS tag. “一般” is the sub-POS tag, which can be ignored. The final three columns represent “original form”, “ruby”, and “pronunciation”. The ruby character means how a word should be pronounced. But in real conversation, people usually ignore the vowel letters (a e i o u, アイウエオ in Japanse) to pronounce a word easier. This phenomenon usually occurs with long vowels.

在下面的例子中,“ゥ”将被忽略。

キョウ -> キョー
ロウドウ -> ロードー

The Romanji of “今日” is “kyou”. The “o” and “u” are both vowels, so this is a long vowel. When we pronounce “今日”, “u” will be ignored. So the pronunciation becomes “kyo” and “o” produce as a long vowel, /uː/.

使用 CSV 文件扩充字典

对于下面的演示,我构建一个foo.csv文件并输入一些名词。

二位,,,10,名詞,一般,*,*,*,*,*,二位,ニイ,ニイ
三位,,,10,名詞,一般,*,*,*,*,*,三位,サンイ,サンイ

接下来我们需要编译这个 CSV 文件。

Mac(与自制软件一起安装)

$ cd /home/foo/bar # the path where the foo.csv exists
$ /usr/local/Cellar/mecab/0.996/libexec/mecab/mecab-dict-index \
-d /usr/local/lib/mecab/dic/ipadic \
-u foo.dic \
-f utf-8 \
-t utf-8 foo.csv reading foo.csv ... 2
emitting double-array: 100% |###########################################|

选项:

  • d:系统字典目录
  • u:输出用户词典的名称
  • f:CSV 文件的编码
  • t:输出用户字典文件的编码

确保用户字典创建成功。

$ ls 
foo.csv foo.dic

将 foo.dic 移动到一个新目录。

$ mkdir /usr/local/lib/mecab/dic/user_dict
$ mv foo.dic /usr/local/lib/mecab/dic/user_dict

接下来,我们需要添加路径到mecabrc文件。

vim /usr/local/etc/mecabrc

更改如下

; userdic = /home/foo/bar/user.dic
->
userdic = /usr/local/lib/mecab/dic/user_dict/foo.dic

如果您有多个用户字典文件,您可以将它们写在一行中。

userdic = /usr/local/lib/mecab/dic/user_dict/foo.dic, /usr/local/lib/mecab/dic/user_dict/foo2.dic, /usr/local/lib/mecab/dic/user_dict/foo3.dic

好了,就这些。

试试用户词典

$ echo "NECが二位、東芝がモトローラを抜いて二年ぶりに三位になる。" | mecabNEC  名詞,固有名詞,組織,*,*,*,NEC,エヌイーシー,エヌイーシー
が      助詞,格助詞,一般,*,*,*,が,ガ,ガ
二位    名詞,一般,*,*,*,*,*,二位,ニイ,ニイ
、      記号,読点,*,*,*,*,、,、,、
東芝    名詞,固有名詞,組織,*,*,*,東芝,トウシバ,トーシバ
が      助詞,格助詞,一般,*,*,*,が,ガ,ガ
モトローラ      名詞,固有名詞,組織,*,*,*,モトローラ,モトローラ,モトローラ
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
抜い    動詞,自立,*,*,五段・カ行イ音便,連用タ接続,抜く,ヌイ,ヌイ
て      助詞,接続助詞,*,*,*,*,て,テ,テ
二      名詞,数,*,*,*,*,二,ニ,ニ
年      名詞,接尾,助数詞,*,*,*,年,ネン,ネン
ぶり    名詞,接尾,一般,*,*,*,ぶり,ブリ,ブリ
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
三位    名詞,一般,*,*,*,*,*,三位,サンイ,サンイ
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
なる    動詞,自立,*,*,五段・ラ行,基本形,なる,ナル,ナル
。      記号,句点,*,*,*,*,。,。,。
EOS

We can see the “二位” and “三位” are recognized as a word.

如果我想知道成本,我们可以改变输出格式。%m是表层形式,%c是成本,%H是逗号分隔的词性、变位、阅读等列表。你可以在这些文件中找到更多细节, EN 版,和 JP 版

$ echo "NECが二位、東芝がモトローラを抜いて二年ぶりに三位になる。" | mecab -F '%m %c %H\n'NEC 13835 名詞,固有名詞,組織,*,*,*,*
が 3866 助詞,格助詞,一般,*,*,*,が,ガ,ガ
二位 10 名詞,一般,*,*,*,*,*,二位,ニイ,ニイ
、 -2435 記号,読点,*,*,*,*,、,、,、
東芝 1426 名詞,固有名詞,組織,*,*,*,東芝,トウシバ,トーシバ
が 3866 助詞,格助詞,一般,*,*,*,が,ガ,ガ
モトローラ 4897 名詞,固有名詞,組織,*,*,*,モトローラ,モトローラ,モトローラ
を 4183 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
抜い 7346 動詞,自立,*,*,五段・カ行イ音便,連用タ接続,抜く,ヌイ,ヌイ
て 5170 助詞,接続助詞,*,*,*,*,て,テ,テ
二 2914 名詞,数,*,*,*,*,二,ニ,ニ
年 8465 名詞,接尾,助数詞,*,*,*,年,ネン,ネン
ぶり 7451 名詞,接尾,一般,*,*,*,ぶり,ブリ,ブリ
に 4304 助詞,格助詞,一般,*,*,*,に,ニ,ニ
三位 10 名詞,一般,*,*,*,*,*,三位,サンイ,サンイ
に 4304 助詞,格助詞,一般,*,*,*,に,ニ,ニ
なる 5063 動詞,自立,*,*,五段・ラ行,基本形,なる,ナル,ナル
。 215 記号,句点,*,*,*,*,。,。,。
EOS

查看我的其他帖子 中等 分类查看
GitHub:
bramble Xu LinkedIn:徐亮 博客:bramble Xu

参考

使用 Python 中的深度学习库的媒体偏见检测

原文:https://towardsdatascience.com/media-bias-detection-using-deep-learning-libraries-in-python-44efef4918d1?source=collection_archive---------6-----------------------

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

Photo by Pablo García on Unsplash

我不止一次遇到过你能马上看出他们政治倾向的新闻故事。这是因为新闻媒体很可能总是有偏见。我在想,如果我们可以用眼睛识别这些模式,那么我们肯定可以建立一种算法,利用文本中的信息来识别书面媒体的偏见。在这份报告中,我将描述我是如何做到这一点的。我使用 Python 环境和 Tensorflow 和 Keras 构建了一个神经网络,能够很好地识别新闻故事是左倾还是右倾。我更进一步,试图不仅识别偏见,还识别故事的出口(或来源)。我将详细描述我用来构建和训练网络的方法,以及我用来可视化结果和性能的方法。开始了。

所有数据均来自 Andrew Thomson 创建的All News数据集。它是免费的,你可以随时下载。它被分成三个大的 CSV 文件,每个文件都包含一个如下所示的表格:

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

News Outlets raw table

因为我们只对内容和经销店名称感兴趣,所以我们将关注两列。列 3 包含出版物或经销店名称,而 9 包含内容。然后,我们需要提取这些信息并相应地存储起来,以便我们可以继续进行分析。但是首先,让我们导入所有需要的模块(如果需要,为最新版本修改您的代码,例如:TensorFlow 2):

Modules for the pipeline

上面描述的每个文件包含大约 50,000 个条目,因此为了加快分析速度,我们可以提取一部分数据。为了节省时间,我决定用这个简单的技巧随机选择大约 40%的文章(当然你可以改变):

p = 0.4
df = pd.read_csv('articles.csv',header=None,skiprows=lambda i: 1>0 and random.random() > p)

这将从 articles.csv 中提取一小部分数据,等于 p.

下一步可能是我们整个流程中最主观的一步。我们给新闻媒体分配了左或右倾向。为了简单起见,我决定每边只使用两个,并使用allsides.commediabiasfactckeck.com来分配他们的偏差。基于从这些网站和其他来源提取的信息,我决定将《大西洋》、《纽约时报》《纽约时报》《纽约邮报》、以及*《布莱巴特》*归为左偏。然后,我从原始文件中筛选出包含这些网点的所有行,使用:

创造了一系列的故事:

n_s = list(n_s_b.iloc[:,9].values) + list(n_s_p.iloc[:,9].values) \
 + list(n_s_a.iloc[:,9].values) + list(n_s_n.iloc[:,9].values)

请注意, n_s 是一个数组,它只包含根据从上述代码中提取的原始数组中的名称排序的所有故事的内容,因此布莱巴特邮报故事排在第一位,然后是大西洋纽约时报。

太好了!下一步做什么?一个重要的预处理步骤,特别是因为我们正在处理自然语言处理,是删除可能给分析增加噪声的单词。我决定删除经销店的名称,这通常在故事中被提及,因为它会给我们的分析增加“偏见”。这可以通过以下方式简单实现:

n_s = [word.replace('New York Post','') for word in n_s]
n_s = [word.replace('Breitbart','') for word in n_s]
n_s = [word.replace('New York Times','') for word in n_s]
n_s = [word.replace('Atlantic','') for word in n_s]

下一步是创建一个类数组。我们知道每个媒体有多少文章,也知道他们的政治偏见。我们可以创建两个数组,一个用于出口分类器,一个用于偏差分类器,其中:

如果您遵循这些方法,您可以看到 classes_All 是一个长度等于 n_s 的数组,它包含从 1 到 4 的整数,每个整数对应于四个出口中的一个,而 classes_Bias 包含 1 表示被认为向右倾斜的出口,包含 2 表示向左倾斜的出口(请参见前面的代码以进一步理解这一点)。像这样, n_s 是我们的特征数组(已经被清理过),因为它包含一个故事列表,这两个数组是我们的类数组。这意味着我们几乎完成了预处理。

关键的最后一步是将故事(实际新闻)转换成神经网络可以理解的东西。为此,我使用了来自 TensorFlow Hub 的令人惊叹的通用句子编码器,它可以将任何给定的句子(在我们的例子中,是一个新闻故事)转换为长度为 512 的嵌入向量,因此最终我们将得到一个大小为 number_of_stories X 512 的数组。这是通过以下方式完成的:

注:我以前用类似的方法对文学运动进行分类,如果你愿意,你可以在这里查看。

要计算嵌入矩阵,我们只需运行我们刚刚定义的函数:

e_All = similarity_matrix(n_s)

终于!我们完成了预处理! e_All 是我们的特征数组,而 classes_Allclasses_Bias 是我们的类数组。现在,我们已经准备好用 Keras 构建一个分类器了。

我不想花太多时间解释如何建立一个神经网络,在《走向数据科学》和许多其他来源中发表了许多实践文章,你可以阅读并跟随非常好的教程来这样做,⁴ ⁵.在这里,我将简单地介绍一个产生良好结果的架构。这个架构是之前许多迭代中的一个,也是我个人发现有效的一个。说了这么多,我们来深究一下吧!我构建的分类器如下所示:

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

News Bias classifier. Image rendered with ann-visualizer.

它有一个 512 个神经元的输入层(每个嵌入值一个)和两个 40 个神经元的隐藏层,每个隐藏层都有一个固定丢失分数为 0.25 的丢失层。它还有一个使用 Softmax 激活函数的输出层,其中有四个神经元对媒体出口进行分类,两个神经元对媒体偏差进行分类(此处未显示)。就代码而言,它看起来像这样:

Media Bias Classifier

对于这两种情况(出口和偏差),除了优化器的学习速率以及输出层中的神经元数量(四个或两个)之外,所有参数都是相同的。直观地说,更简单的解决方案(偏差情况下的二进制)应该更快地得到优化。为此,我决定使用 0.00015 的学习率进行出口分类,0.0005 的学习率进行偏差分类。

最后,在检查结果之前,我们需要将数据分成训练集和测试集。为此,我们将使用一个分层洗牌拆分器,所以看起来像这样:

这样做了,我们只需要训练网络。我们可以通过以下方式做到这一点:

现在我们准备检查结果!

我们先来看网点分类。训练后(在 8 核 CPU 机器上大约 15 分钟,不需要 GPU),验证和训练精度曲线如下所示(可视化代码在本文后面提供):

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

这是什么意思?嗯,首先,验证集的精度几乎是 0.80,这可以认为是好的。记住,这是来自四家媒体的准确性!也就是说,这个神经网络仅基于书面语义内容,就能以相对较好的性能识别出被报道新闻的来源,非常酷!现在让我们看看损失,以验证我们的模型是否合适:

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

由于两条曲线“看起来”一样(它们之间的差异很小),我们可以说,我们的神经网络已经学习了足够通用的规则,以避免过度拟合,但又足够具体,以在验证集上产生良好的性能,这是一种始终是 desirable⁶.的深度学习质量考虑到这一点,我们现在可以查看混淆矩阵以更深入地了解结果:

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

很明显,来自【新工作岗位】的新闻故事被分类得更准确,但这可能是因为这两个类别的代表性更高。我们可以尝试重采样的方法来平衡类,但现在我会保持这种方式,并回到我们的二进制分类任务重采样,在接下来的段落中描述。**

接下来,我们可以探索媒体偏见分类的结果。记住,这是一个二元分类器(要么向左倾斜,要么向右倾斜)。第一,精度和损耗曲线:

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

如果你问我,我会印象深刻!我们得到了几乎 0.9 的准确度,这意味着,有效地,如果一个新闻故事偏向左边或右边,我们可以很好地识别。混淆矩阵呢?

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

看起来不错,但很明显,左倾的报道没有被充分代表,因此准确性没有完全反映这里正在发生的事情。光是准确性就可能会误导人。另一个对不均匀的类别分布有帮助的度量是 F1 score⁷.我们可以很容易地用 sklearn 的内置函数来计算它,所以只需这样做就行了:

*from sklearn.metrics import f1_score
f1_score(y_test,news_DNN.predict_classes(X_test))*

这引发了:

*>>> 0.78*

很好,但不完美。我们可以尝试使用过采样器来平衡训练集 only⁸中的类,以获得更好的结果。我将使用惊人的 Python 库 imblearn 中的 SMOTE,所以只需在拟合之前添加这一行:

使用平衡数据进行训练后,混淆矩阵现在看起来像这样:

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

更平衡。F1 和精度呢?分别为 0.80 和 0.88。非常好!

注意:所有可视化都是使用 seaborn 完成的。下面是我编写的创建所有图形的代码:

Code to visualize results

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

Photo by AbsolutVision on Unsplash

在本文中,我向您介绍了我构建、训练和可视化新闻出口/偏见分类器的步骤,结果非常好。我们能够得到出口分类的相当准确的分数,这表明文本的性质本身就可能包含关于给定故事在哪里写的信息。对于这种规模的样本,很难得出精确的结论,但想法是存在的,我们可以使用 Keras、TensorFlow 和 Python 中的可视化库来对新闻故事进行分类。更值得注意的是,偏见可以与非常好的表现联系在一起,这意味着在某种程度上,书面媒体中的语义规则隐含着政治偏见。在某种程度上,我们从一开始就知道这一点,但有趣的是,我们注意到这些信息是存在的,并且使用适当的工具可以自动识别。你认为这种方法还能解决什么问题?

现在您已经有了工具,您可以复制代码并在自己的项目中使用它。

感谢阅读!

参考资料:

[1]媒体偏见图表,https://www.adfontesmedia.com/

[2]布达克、c .戈埃尔、s .、&饶、J. M. 公正与平衡?通过众包内容分析量化媒体偏见。 (2016) 舆情季刊80 (S1),250–271。

[3]Keras 深度学习简介,https://towards data science . com/Introduction-to-Deep-learning-with-Keras-17c 09 E4 f 0 EB 2

[4]使用 Keras 的实用机器学习,https://towards data science . com/Practical-machine-Learning-with-Keras-19 d0e 5b 2558

[5]使用 Keras 构建深度学习模型,https://towards data science . com/Building-A-Deep-Learning-Model-using-Keras-1548 ca 149d 37

[6]https://machine learning mastery . com/how-to-choose-loss-functions-when-training-deep-learning-neural-networks/

[7]准确度、精密度、召回率还是 F1?https://towards data science . com/accuracy-precision-recall-or-f1-331 FB 37 C5 CB 9

https://beckernick.github.io/oversampling-modeling/

民主党初选中的媒体偏见

原文:https://towardsdatascience.com/media-bias-in-the-democratic-primary-66ffb48084db?source=collection_archive---------13-----------------------

媒体中有两种类型的偏见在起作用,它们都造成了不公平:语气上的偏见和音量上的偏见。例如,一篇攻击贝托·奥罗克使用拉丁裔昵称的专栏文章在语气上带有偏见;一张候选人筹款信息图包括了除杨安泽之外的所有顶级筹款人*,这是中偏见的一个例子。*

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

One rating

这两种类型的偏置在 2016非常 可见 ,但是确定音量偏置比音调偏置要容易得多,所以我将主要使用五三十八中可用的数据,集中讨论音量偏置。除非另有说明,平均或合计投票数按照本文中的生成。即使在对民主党人普遍友好的“蓝色”媒体中,对不同候选人报道的基调也有很大差异,我目前的印象是蓝色媒体更喜欢不太可能当选的候选人,特别是伊丽莎白·沃伦

我将介绍几种衡量媒体偏见的方法,大部分是基于比较民意测验数字和媒体报道。

哪些候选人得到了更多的媒体报道,为什么?

媒体在数量上的偏见既普遍又不公平。然而,平等时间规则在很久以前就被废除了,候选人得到的报道量也大相径庭。民主党全国委员会曾试图公开表示赞同将辩论台上的候选人视为平等,但即使在辩论台上,候选人也没有获得平等的时间。

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

比较这两个职位是非常惊人的。乔·拜登在一周内获得的报道比乔·塞斯塔克在过去一年中获得的报道还多。然而,当我们考虑他们在民调数字、筹款和支持方面的差异时,媒体偏向于报道拜登作为领先者是可以理解的。

在某种程度上,这是不公平的;但这种不公平可以客观地基于这样一个事实:拜登比塞斯塔克更知名、更受欢迎。这是一场有利于领先者、不利于苦苦挣扎的竞争者的赛马偏见,而不是对塞斯塔克或拜登的偏见。

比较媒体报道和民意测验

大多数覆盖率差异的答案是投票。我认为在那之后剩下的就是媒体对特定候选人的支持和反对。

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

For legibility, candidates with aggregate polling less than 1% shown separately.

媒体报道既推动民意调查,也受民意调查的推动,因此从长远来看,两者密切相关。一些异常现象可以通过逐月分解数据来解释,比如汤姆·斯特耶在图表上的位置是一个迟到的候选人。然而,其他异常现象仍然无法解释。

从这一大背景来看,媒体显然更青睐伊丽莎白·沃伦而非伯尼·桑德斯,科里·布克而非贝托·奥罗克,以及许多其他候选人而非杨安泽。

在民调支持率较低的候选人的后场,来自内陆州的温和派(麦克·班尼、史蒂夫·布洛克、约翰·希肯卢珀和蒂姆·瑞恩)被忽视,而来自沿海州的政客(柯尔斯顿·吉利布兰德、杰伊·英斯利、埃里克·斯瓦尔韦尔和比尔·白思豪)则受到了青睐。然而——我要重复这一点——在低于 1%的范围内,很难对投票平均值的任何有意义的差异有任何信心。

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

Please note that the axes here are log-scaled, which means that the anomalies are very large anomalies.

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

Coverage is measured by total clips plus total stories from 538’s media tracking data. The exclusion of low polling weeks is quite significant for a handful of low-polling candidates, but is necessary to adequately show the relationship between the major candidates.

如果我们随着时间的推移更仔细地观察这些数字,它们通常在任何给定的一周和任何给定的一个月内相互关联。“赛马”覆盖面很广,大多数时候,大多数候选人在每个投票点都获得了类似的覆盖水平。

某一周或某一月的一些个别例外可以用新闻事件来解释。为了避免专注于任何单一新闻事件的影响,我将着眼于在一个中等或典型的一周内报道和投票之间的关系。当同一个候选人相对于他们的投票,一周又一周地重复和持续地被过度报道或报道不足时,媒体偏见是最简单的解释。

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

Median coverage per polling point; median difference between actual and predicted amount of coverage using a linear model; and median polling average.

民意测验和报道之间的关系并不完全相称;它倾向于在高端和低端偏离。这个问题的自然答案是做线性回归。

这向我们展示了两种略有不同但相关的媒体偏见的衡量标准。线性模型更可取,因为它考虑了更多的信息,并且不涉及除以接近零的数字。

从这两个指标来看,贝托·奥罗克显然受到了亏待,尽管他在民意调查中平均排名第七,但他的支持率在所有候选人中排名第二。我们同样可以强调杨安泽、史蒂夫·布洛克、乔·塞斯塔克和迈克·格拉维尔相对于他们的投票经常被低估。

在正面报道偏见方面,媒体更喜欢报道伊丽莎白·沃伦、科里·布克、柯尔斯顿·吉利布兰德和比尔·白思豪。或许值得注意的是,无论用哪种方法来衡量,皮特·布蒂吉格似乎都得到了恰到好处的覆盖。对于所有其他候选人来说,这些指标更加复杂;我们可以在其他候选人之间做出一些相对的决定,但不清楚他们在媒体报道量方面经历了净正面还是净负面的偏见。

候选人作为覆盖面的竞争者:评估每一个案例

这里我们谈到了几个主要问题。一个是民意调查和报道有一个很大的——但不是完全的——比例关系。我们能够自信地识别的异常是基于具有相对相似的投票数的候选人之间的成对比较。幸运的是,我们可以采用所有这些异常的成对比较,并使用它们来生成相对于投票的媒体偏向方向的评级。

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

根据我的分析,在数据中有 921 个案例,一个候选人在一周内得到的报道比另一个候选人少,尽管事实上他们在那一周和前一周的民调都更好。有一个很好的数学工具可以从一系列成对的比赛中梳理出竞争者的相对实力:它被称为 Elo 评级,以物理学家和国际象棋选手 Arpad Elo 命名。

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

Here, the polling average is determined by aggregating over all polls in the frame, so the figures are slightly different.

通过 Elo 评级公式进行 921 个两两比较,可以让我们衡量媒体对候选人无法解释的偏好。

有两个候选人的评分表明他们受到了媒体的强烈冷落:杨安泽(评分 675)和贝托·奥罗克(评分 836)。

尚不清楚第三名应该属于伯尼·桑德斯(1022)还是乔·拜登(958)。由于乔·拜登在每周的选举中都处于领先地位,他的支持率被人为压低了;他只能“输”给民调数字更低的候选人。温和派政治家作为一个群体往往低于平均水平。令人惊讶的是,这包括皮特·布蒂吉格(1068),他在这个主题的其他方面看起来接近平均水平。

值得注意的高评级候选人包括柯尔斯顿吉利布兰德(1408)和伊丽莎白·沃伦(1335);在仍在竞选的候选人中,伊丽莎白·沃伦显然是媒体的宠儿。用这种方法排名最高的候选人是埃里克·斯瓦尔维尔、比尔·白思豪、杰伊·英斯利和塞斯·莫尔顿。值得再问一次,重要程度是多少?

这些考生有多少故事和片段得与失?

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

如果我们将数据集中的 921 个两两比较,削减到每周,我们可以确定覆盖范围的最小变化,这将消除任何明显的冷落。这样做可以正确看待正音量偏差:塞斯·莫尔顿可能会被报道,而不是其他不知名的候选人,但几乎没有报道受到威胁。

根据这一标准,科里·布克脱颖而出,超过了克里斯汀·吉利布兰德和伊丽莎白·沃伦。最受冷落的候选人显然又是贝托·奥罗克和杨安泽。

关于媒体中音量偏差的地理位置的一个小说明

将候选人按其选区的地理位置(沿海大陆、内陆大陆、非毗邻地区或缺少以前的选区)进行分类显示了一个非常有趣的模式。

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

前十名候选人的选区是沿海州、区或城市,现在覆盖面更广了。内地考生被覆盖较少。这实际上是一个非常一致的划分;考虑到主要媒体的地理和人口统计,这也是可以理解的。

没有内地考生有明确的正体积偏差;最接近的是皮特·布蒂吉格和艾米·克洛布查尔,他们在大多数方面都接近中立。有没有沿海候选明确负体积偏差;最接近的是乔·拜登,尽管如此,他在报道竞争中绝对领先。

由于选举团的政治战场既不在 Acela 走廊,也不在西海岸,媒体的地理偏见可能会阻碍提名更有可能当选的候选人。

影响和效果

从上面的分析中,有几个明确的结论。首先,我们可以清楚地发现少数候选人似乎吸引了过多的媒体报道。与民调数字相近的候选人相比,伊丽莎白·沃伦、科里·布克、柯尔斯顿·吉利布兰德和比尔·白思豪都在媒体报道中占据显著位置。由于伊丽莎白·沃伦在“蓝色”媒体上的报道也一直是积极的,这可能助长了她的崛起。

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

其次,我们可以确定两位候选人明显受到了媒体偏见的影响。杨安泽和贝托·奥罗克都经历了媒体过度稀少和负面的报道…难怪贝托挣扎着选择退出,也难怪杨安泽的支持者抱怨#央媒封杀

根据他的筹款和民意调查,杨安泽早就应该成为公众讨论的一个重要部分。不这样做的后果是消极的。

第三,有一些知名度较低的候选人渴望得到报道,他们没有足够的时间向潜在选民宣传自己的观点。这包括已经退出的约翰·希肯卢珀和蒂姆·瑞恩;以及麦克·班尼、史蒂夫·布洛克、约翰·德莱尼和乔·塞斯塔克。所有这些候选人都有比皮特·布蒂吉格更典型的总统候选人背景。

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

Sanders’ polling is steady; Gabbard’s polling has been climbing in spite of (or perhaps because of) a recent spate of negative coverage.

第四,有一些证据支持伯尼·桑德斯和塔尔西·加巴德的支持者经常指责的语气偏见。这两位候选人和杨安泽似乎都不太可能退出。

显而易见的媒体偏见,如果继续下去,可能会对最终的民主党候选人造成伤害。民主党全国委员会可能面临另一轮关于试图操纵初选的指控。媒体本身也会因为在音量或语气上公然偏袒而失去信誉。

鉴于民主党全国委员会和“蓝色”媒体对偏见的指控是可信和有根据的,推动对进入初选的候选人进行公平、透明和公正的报道就更加重要了。

媒体监测 2.0:从数据到洞察

原文:https://towardsdatascience.com/media-monitoring-2-0-from-output-to-insight-ecf0d926b4ec?source=collection_archive---------30-----------------------

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

在营销和传播专业人士的生活中,媒体监控是热门且不可或缺的。测量就是了解,事实上在我们当前的时代,可能性是无穷无尽的。监控工具和数字解决方案的数量正在增长,如今一切都可以测量。所以我们必须注意到这一点,对吗?数据无处不在,收集、监控和分析数据从未如此简单。然而,我们现在面临挑战。我们如何应对假新闻?我们如何继续在我们的数据中找到相关性,并将其转化为理解,并最终转化为具体行动?在本博客系列的第 1 部分,我们将讨论媒体监控领域需要的转变,以及如何将这种转变应用到您的媒体监控策略中。

它从“为什么”开始

西蒙·西内克的黄金圈,谁没听说过?他认为,为了取得成功,作为一家公司,你必须从“为什么”这个问题开始,然后从那里赋予“如何”和“什么”以实质内容。这听起来很有逻辑,而且现在已经被许多组织所使用,但是仍然有很多人主要用“如何”和“什么”来交流。

这个模型很实用,因此很容易应用到其他策略和日常事务中。作为一名营销和传播专业人士,不断问自己为什么要做这些事情是很重要的。你为什么要做某些决定?为什么这是你的策略?您会选择哪些定位和分析主题,为什么?你为什么要通过核心信息 X 和 Y 以及媒介 Z 来传达这一点?

这也可以通过监测和测量来转化;为什么你甚至需要监控?为什么需要这个输出?你想要什么,你能用这个做什么?这对证明你的策略有什么帮助?

“为了监控而监控是没有用的,浪费时间、金钱和精力。”

衡量你想要衡量的东西,并正确地去做

从战略沟通目标和围绕这些目标形成的政策着手。可能这些没有被清楚地表达出来,这有助于观察整体的组织策略(也就是伞)。我们的定位是什么,我们为什么要这样做?我们如何通过交流赋予它实质内容,为此需要什么?从“为什么”开始可以确保更多地关注核心任务和战略规划,减少对当前问题的浪费。

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

这同样适用于监测及其实施。监控可以被视为“如何”,由“为什么”形成,并导致“什么”。但就其本身而言,它毫无意义。看看下面的例子:

X 组织

原因:可持续发展是我们 2019 年定位的重要支柱。我们希望创造更积极的媒体能见度和积极的基调,通过正确的媒体向正确的利益相关者传达正确的信息,并能够在必要时不断改进这些事情。
如何:监控媒体的可见性、影响力、情感、利益相关方、媒体来源和核心信息
如何:洞察主动活动和自有及盈利媒体的传播效果

如你所见,如果没有“为什么”,那么“如何”和“做什么”就没什么意义。此外,定义这一点不仅有助于您将更多的注意力放在媒体监控活动上,还可以创建内部支持来说服投资管理人员。毕竟,您提供了对监控所能提供的东西的洞察力。

获得更多洞察力和概览

为了使您的媒体监控活动具有针对性和相关性,将这些活动与沟通和/或业务战略和计划相协调是非常重要的。

以荷兰皇家航空公司为例,该公司在其网站上广泛交流对公司重要且相关的重要话题,以及所有这些问题的处理方式。

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

作为一名传播专业人员,使用这些类型的主题作为媒体监测的指南是有用的,以便深入了解围绕这些主题所做的努力的影响。作为一个组织,你的承诺和言论在多大程度上与你的实际行动相符?媒体在多大程度上(以正确的方式)采纳了你的核心信息,这些信息最终会到达正确的目标群体手中吗?通过这种方式,你可以更有针对性地进行监控,你会发现更容易找到真正重要的正确报告。

“控制媒体对自己的监控,而不是被过量的新闻淹没。”

因此,在荷航的案例中,需要监控媒体对“荷航小心”主题的影响,以及主动报道的比例或媒体中的核心信息。

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

从输出到洞察

一旦你把重点放在了你的媒体监测上,并与战略主题联系起来,提供一个背景也是很重要的。好东西,所有的主题和话题的监控,但是这个输出告诉我什么?我们做得好吗?我们走上正轨了吗?这是由什么驱动的?

只有当您能够集成数据输出并将其与目标和 KPI 联系起来时,它才会变得有趣。您可以根据这个来设置输出,以便能够判断您需要按下哪个按钮,或者使用这个输出来制定 KPI。对于后者,您可以使用监控作为构建 KPI 的基线度量。

如果我们使用前面提到的组织 X 的例子作为起点,从输出到洞察的转换看起来是这样的:

组织 X
产出:
假设 2019 年 1 月监测的产出为主题可持续性的 500 条消息(占媒体总报道量的 5%)。这些信息中有 15%是您自己主动/ PR(主动)的结果,10%是积极的语气。这三大核心信息似乎只在地区新闻网站上可见。

集成:
就其本身而言,上面的输出并不能说明什么。想到的问题大概是“那又怎样?”。这里是上下文;2019 年 1 月,组织 X 的目标是至少 10%的可持续发展主题报告,除此之外,关于前 3 个核心信息的 KPI 至少有 10%的主动报告、5%的积极情绪和全媒体可见性。

洞察力
通过在目标和 KPI 之间建立联系,结果立即有了意义。我们从建立这种联系中得到了什么启示?1 月份可持续发展的可见性低于预期(5%对 10%),但比预期更积极(15%对 10%)和更积极(10%对 5%)。换句话说,该公司的举措产生了影响,并以正确的语气采取了措施,但知名度仍然有限。此外,这显然与我们在媒体上的可见性目标和核心信息不匹配。为什么我们的核心信息似乎在地区新闻网站上传播得如此之好?我们可以采取什么措施来提高媒体在整个董事会中的知名度?

通过从“为什么”的角度来处理和组织媒体监督,你创造了相关性和价值,有了一个概览,并保持控制。这一转变非常重要,它将激励你更加关注战略项目和计划的影响,并向你所在组织的管理层展示这一点的附加价值。在本博客系列的第 2 部分中,我们将进一步阐述在管理层提供证据和创建内部支持的过程。

用卷积神经网络进行医学诊断

原文:https://towardsdatascience.com/medical-diagnosis-with-a-convolutional-neural-network-ab0b6b455a20?source=collection_archive---------15-----------------------

浅谈人工智能在医疗保健中的应用。

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

Image licensed from Adobe Stock

2018 年美国美国食品药品监督管理局批准使用一种叫做卷积神经网络的人工智能形式的医疗设备来检测糖尿病成年人的糖尿病视网膜病变( WebMD,2018 年 4 月)。医学图像处理代表了人工智能(AI)世界中的一些“低挂果实”,其使用才刚刚开始。人工智能有望将专业人士从数小时的乏味任务中解放出来。如果运用得当,它可以带来更好的患者结果和更低的医疗成本。

糖尿病视网膜病变是糖尿病患者失明的最常见原因,也是工作年龄成人失明的主要原因。总之,患有各种类型糖尿病的人都有风险,并且患糖尿病的时间越长,风险越大。这种疾病始于视网膜中微小血管的肿胀和微动脉瘤。在晚期病例中,这些受损的血管会导致生长因子的分泌,从而引发新血管的增殖。这些新血管生长在视网膜表面,并进入眼睛的玻璃体凝胶中。这些新血管很脆弱,可能会渗漏和出血,随着疤痕组织的积累,病情会变得更糟。视网膜脱落会导致视力受损和全盲,因此早期诊断至关重要(美国国家眼科研究所——糖尿病眼病相关事实)。

眼科医生诊断这种情况的一种工具是眼底照相术,它使用一种专门的相机来拍摄患者的视网膜照片。这是一个健康视网膜的图像:

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

Healthy Retina — Image licensed from Adobe Stock

这是一个被诊断为“增生性糖尿病视网膜病变”的视网膜,这是疾病阶段的最严重分类:

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

Proliferative Diabetic Retinopathy — Image licensed from Adobe Stock

在这种严重的情况下,很容易看到浅色的斑点,这是急性疾病的指标之一。在疾病的早期阶段,肿胀和微动脉瘤更难发现。幸运的是,这是一项非常适合人工智能的任务。

我的目标是创建一个卷积神经网络,这是几种最先进的人工智能方法之一,可以正确地将眼底图像分为五类:

  • 不存在 DR(糖尿病视网膜病变)
  • 轻度 DR
  • 温和的 d
  • 重度 DR
  • 增生性 DR

卷积神经网络(CNN)可以用先前已经被正确分类的图像的例子来训练。

我从位于印度泰米尔纳德邦钦奈的亚太远程眼科协会举办的一场竞赛中获得了这个项目的原始图片。该数据集包括 3,662 个预先分类的眼底图像,包括疾病所有阶段的实例。

为了大大简化 CNN 的工作方式,CNN 通过使用多层“节点”和无数次“分析”和“加权”结构、模式等迭代来学习。它在图像中识别。帮助它正确识别的结构/模式(例如,这是狗还是猫?)或分类(我的用例)图像被“奖励”较高的“权重”,而一个有害或无用的图像被“惩罚”较低的“权重”构建这些“层”和“权重”的方式有无数种,处理它们所需的计算能力从微不足道到不可能。有用的 CNN 没有被广泛使用,直到非常非常快的计算机和 GPU 变得更加便宜——这是最近的发展。

这张图展示了我用来评估 CNN 的两个指标:

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

从左到右代表迭代(在机器学习中称为“时期”),其中模型已经完成一次并生成预测。蓝线代表 CNN 对它“研究”的图像的预测的准确性,橙线代表对它没有“分析”但可以“自测”的图像的预测的准确性。当训练精度继续提高,但验证精度开始下降时,就是“过拟合”开始的时候。在这一点上,CNN 在识别它已经研究过的图像方面变得如此之好,以至于在对它没有“研究”过的图像进行分类方面变得“更差”一般来说,更高的验证准确性是目标,所以我们希望在验证准确性达到峰值时阻止 CNN 了解更多信息。如果 CNN 在这一点上的性能不够,则需要调整 CNN 中的一些或所有层和权重,以改善最终输出。

做出这些调整可能是一个非常复杂的过程。在我的 CNN 中,所有的图像都被缩小到只有 128 像素乘 128 像素的大小,然而 CNN 使用了超过 2700 万个“可训练的”参数。

CNN 的最终评估是使用一组 CNN 从未“见过”的眼底图像完成的。下图称为混淆矩阵,显示了 CNN 预测每个疾病阶段分类图像的准确程度:

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

Confusion Matrix

左上角的矩形显示,当 CNN 将一幅图像分类为“无 DR”时,其准确率为 98%,这是一个非常好的结果。不幸的是,当它预测“轻度 DR”时,只有 44%的时间是正确的。它似乎在区分“轻度”和“中度”类别的图像方面有最大的困难。46%的实际“轻度 DR”图像被错误地归类为“中度 DR”。我相信,通过对层和权重进行更多的“调整”,这种性能可以得到改善。

我对数据科学改善我们所有人生活的潜力充满热情,我期待着这些技术在现实生活中的应用。

这个项目的完整代码和数据集可以在我的 GitHub 库这里看到。

人工智能的好处——用于疟疾检测的医学图像分析

原文:https://towardsdatascience.com/medical-image-analyses-for-malaria-detection-fc26dc39793b?source=collection_archive---------27-----------------------

在这篇博客中,我们将讨论为什么疟疾检测对于早期检测薄血涂片中寄生细胞的存在是重要的,以及一些人对此的实践。

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

介绍

疟疾是一种致命的传染性蚊媒疾病,由疟原虫寄生虫引起。这些寄生虫通过受感染的雌性按蚊的叮咬传播。虽然我们不会深入了解这种疾病的细节,但疟疾有五种主要类型。

现在让我们看看这种疾病在下面的情节中有多致命的意义。

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

很明显,疟疾在全世界流行,尤其是在热带地区。这个项目的动机是支持这种疾病的特性和致命性。最初,如果被感染的蚊子叮咬,蚊子携带的寄生虫会进入你的血液,并开始破坏携带氧气的红细胞。通常,疟疾的主要症状有点像流感或病毒,一旦被蚊子叮咬,你通常会在几天或几周内感到不适。然而,这些致命的寄生虫会在你的身体里沉睡一年多而没有任何问题!所以,延误正确的治疗会导致并发症甚至死亡。因此,疟疾的早期有效检测将拯救生命。

解决问题的方法

尽管疟疾病毒没有以变异蚊子的形式出现,但它确实让人感觉像是一个变异问题。这种致命的疾病在世界不同地区已经达到流行病*、*甚至地方病的比例——每年在杀死大约 40 万人。在世界上的其他地方,它几乎不存在。一些地区特别容易爆发疾病——某些因素使得一个地区更有可能被疟疾感染。

  • 高度贫困
  • 缺乏适当的医疗保健
  • 政治不稳定
  • 疾病传播媒介的存在(例如蚊子)〔6〕

由于这些问题的混合,我们在构建模型时必须记住一些事情:

  • 可能缺少一个可靠的电源
  • 电池供电的设备具有较少的计算能力
  • 可能缺少互联网连接(所以在云上训练/存储可能很难!)

传统的疟疾检测方法

有几种方法和测试可用于疟疾的检测和诊断。

这些包括但不限于厚薄血涂片检查、聚合酶链反应(PCR)和快速诊断测试(RDT)。我不打算涵盖所有的方法,但事实是,传统的测试通常使用一种替代方法,特别是在高质量的显微镜服务不能轻易提供的情况下。

血液的显微镜检查是诊断疟疾最著名的方法。将患者的血液涂在载玻片上,并用造影剂染色,这有助于识别红细胞内的寄生虫。

一名训练有素的临床医生在 100 倍的放大倍数下检查 20 个微观视野,从 5000 个细胞中计数含有寄生虫的红细胞(世卫组织方案)。

感谢 Carlos Atico】关于数据科学见解的博客

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

因此,疟疾检测肯定是一个密集的手动过程,也许可以通过深度学习实现自动化,这是本博客的基础。

用于疟疾检测的深度学习

深度学习模型,或者如果我必须说得更具体一些,卷积神经网络(CNN)已经被证明在各种各样的计算机视觉任务中非常有效。虽然我们假设你对 CNN 有所了解,但如果你不了解,请点击这里的这篇文章,深入了解它们。简而言之,CNN 模型中的关键层包括卷积层和池层,如下图所示。

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

卷积神经网络(CNN)可以自动提取特征和学习过滤器。在以前的机器学习解决方案中,特征必须手动编程——例如,大小、颜色、细胞的形态。利用卷积神经网络(CNN)将大大加快预测时间,同时反映(甚至超过)临床医生的准确性。

CNN 从我们的数据中学习等级模式。因此,他们能够学习图像的不同方面。例如,第一卷积层将学习小的和局部的图案,例如边缘和拐角,第二卷积层将基于来自第一层的特征学习更大的图案,等等。

您可以浏览 Rajaraman 等人的一篇非常有趣的研究论文’ 预训练卷积神经网络作为特征提取器,用于改进薄血涂片图像中的寄生虫检测 。它解释了上述论文中提到的数据的六个预训练模型。在检测疟疾和非感染样本时获得 95.9%的准确率。

数据集解释

让我们看看这个问题集使用了什么数据,我非常感谢李斯特山国家生物医学通讯中心(LHNCBC)的研究人员,他们是国家医学图书馆(NLM)的一部分,他们仔细收集并注释了健康和受感染血液涂片图像的数据集。你可以从官方网站下载这些图片。

他们还推出了一个移动应用程序,可以在连接到传统光学显微镜的 andriod 智能手机上运行(Poostchi 等人,2018 年)。在孟加拉国吉大港医学院医院收集 150 名恶性疟原虫感染患者和 50 名健康患者的吉姆萨染色薄血涂片并拍照。智能手机的内置摄像头可以获取每个微观视野的幻灯片图像。这些图像由泰国曼谷的玛希多-牛津热带医学研究中心的专家幻灯片阅读者手工注释。

**注意:**现在,在我们开始之前,我想指出,我既不是医生,也不是医疗保健研究人员,我远不如他们有资格。不过,我确实对将人工智能应用于医疗保健研究感兴趣。本文的目的不是深入宣传人工智能将取代工作岗位并接管世界,而是展示人工智能如何有助于疟疾检测、诊断并通过低成本有效且准确的开源解决方案减少人工劳动。

这是我们训练数据的样子

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

**注:**我正在使用谷歌 colab 和代码将根据相同的,我建议大家使用谷歌 colab 的方便。

让我们来看看代码:

密码

初始化

%reload_ext autoreload
%autoreload 2
%matplotlib inline

google colab 上的虚拟机测试

如果谷歌的服务器很拥挤,你最终只能访问 GPU 的一部分。如果您的 GPU 与另一台 Colab 笔记本共享,您将看到可供您使用的内存量减少。

!/opt/bin/nvidia-smi
!nvcc --version

当我开始运行这里描述的实验时,我很幸运:我有 11441 MB 的 RAM!我的输出如下所示:

Mon Nov  4 05:40:26 2019       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.67       Driver Version: 418.67       CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 00000000:00:04.0 Off |                    0 |
| N/A   49C    P8    30W / 149W |      0MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Sat_Aug_25_21:08:01_CDT_2018
Cuda compilation tools, release 10.0, V10.0.130

导入库

在这里,我们导入所有必需的包。我们将使用 fast.ai V1 库,它位于 Pytorch 1.0 之上。fast.ai 库提供了许多有用的功能,使我们能够快速轻松地建立神经网络并训练我们的模型。

from fastai.vision import *
from fastai.metrics import error_rate
from fastai.callbacks import SaveModelCallback# Imports for diverse utilities
from shutil import copyfile
import matplotlib.pyplot as plt
import operator
from PIL import Image
from sys import intern   # For the symbol definitions

一些实用程序功能:导出和恢复

现在,这里有一个用于部署的导出网络和一个用于创建拷贝的导出网络

# Export network for deployment and create a copydef exportStageTo(learn, path):
    learn.export()
    # Faça backup diferenciado
    copyfile(path/'export.pkl', path/'export-malaria.pkl')

#exportStage1(learn, path)

恢复部署模型,例如为了继续微调

# Restoration of a deployment model, for example in order to continue fine-tuningdef restoreStageFrom(path):
  # Restore a backup
  copyfile(path/'export-malaria.pkl', path/'export.pkl')
  return load_learner(path)

#learn = restoreStage1From(path)

现在让我们下载 NIH 数据集,我们今天将在上面工作:

!wget  --backups=1 -q https://ceb.nlm.nih.gov/proj/malaria/cell_images.zip
!wget  --backups=1 -q https://ceb.nlm.nih.gov/proj/malaria/malaria_cell_classification_code.zip
!ls -al

wgetbackups=1 参数将允许您在下载失败的情况下多次重复命令行,而无需创建大量新版本的文件。

最后一行的输出应该是这样的:

total 690400
drwxr-xr-x 1 root root      4096 Nov  4 10:09 .
drwxr-xr-x 1 root root      4096 Nov  4 05:34 ..
-rw-r--r-- 1 root root 353452851 Apr  6  2018 cell_images.zip
-rw-r--r-- 1 root root 353452851 Apr  6  2018 cell_images.zip.1
drwxr-xr-x 1 root root      4096 Oct 30 15:14 .config
drwxr-xr-x 5 root root      4096 Nov  4 07:26 data
-rw-r--r-- 1 root root     12581 Apr  6  2018 malaria_cell_classification_code.zip
-rw-r--r-- 1 root root     12581 Apr  6  2018 malaria_cell_classification_code.zip.1
drwxr-xr-x 1 root root      4096 Oct 25 16:58 sample_data

让我们解压缩 NIH 细胞图像数据集:

!unzip cell_images.zip

这将产生一个非常大的详细输出,如下所示:

Archive:  cell_images.zip
   creating: cell_images/
   creating: cell_images/Parasitized/
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144104_cell_162.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144104_cell_163.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144104_cell_164.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144104_cell_165.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144104_cell_166.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144104_cell_167.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144104_cell_168.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144104_cell_169.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144104_cell_170.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144104_cell_171.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144348_cell_138.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144348_cell_139.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144348_cell_140.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144348_cell_141.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144348_cell_142.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144348_cell_143.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144348_cell_144.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144823_cell_157.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144823_cell_158.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144823_cell_159.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144823_cell_160.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144823_cell_161.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_144823_cell_162.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145042_cell_162.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145042_cell_163.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145042_cell_164.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145042_cell_165.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145042_cell_166.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145042_cell_167.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145422_cell_163.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145422_cell_164.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145422_cell_165.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145422_cell_166.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145422_cell_167.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145422_cell_168.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145422_cell_169.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145609_cell_144.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145609_cell_145.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145609_cell_146.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145609_cell_147.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145609_cell_148.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145609_cell_149.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145609_cell_150.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145609_cell_151.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145938_cell_167.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145938_cell_168.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145938_cell_169.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145938_cell_170.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145938_cell_171.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145938_cell_172.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145938_cell_173.png  
 extracting: cell_images/Parasitized/C100P61ThinF_IMG_20150918_145938_cell_174.png  
and .......... so on

准备您的数据

cell_images 文件夹的名称改为 train ,然后将 mv 放在一个新的 data 文件夹的上面,这样 fast.ai 就可以用它来自动生成 train,验证测试设置,不用再大惊小怪了

!mv cell_images train
!mkdir data
!mv train data

深入研究数据文件夹

如果还没有安装树命令,请安装它:

!apt install tree

让我们现在运行命令

!tree ./data --dirsfirst --filelimit 10

这将显示文件夹的树状结构:

./data
└── train
    ├── Parasitized [13780 exceeds filelimit, not opening dir]
    └── Uninfected [13780 exceeds filelimit, not opening dir]3 directories, 0 files

变量初始化

bs = 256                # Batch size, 256 for small images on a T4 GPU...
size = 128              # Image size, 128x128 is a bit smaller than most of the images...
path = Path("./data")   # The path to the 'train' folder you created...

创建培训和验证数据束

有了 fast.ai 就没必要了:如果你只有一个‘train’文件夹,你可以在创建 DataBunch 时通过简单地传递几个参数来自动分割它。我们将把数据分成一个训练集 (80%)和一个验证集 (20%)。这是通过*imagedatabunch . from _ folder()*构造函数方法中的 valid_pct = 0.2 参数完成的:

限制你的扩展:这是医学数据!你不要幻想数据…

例如,扭曲会让你的图像严重失真,所以不要这样做!

这个数据集很大,所以也不要旋转图像。让我们坚持翻转…

tfms = get_transforms(max_rotate=None, max_warp=None, max_zoom=1.0)
# Create the DataBunch!
# Remember that you'll have images that are bigger than 128x128 and images that are smaller,   
# so squish them all in order to occupy exactly 128x128 pixels...
data = ImageDataBunch.from_folder(path, ds_tfms=tfms, size=size, resize_method=ResizeMethod.SQUISH, 
                                  valid_pct = 0.2, bs=bs)
#
print('Transforms = ', len(tfms))
# Save the DataBunch in case the training goes south... so you won't have to regenerate it..
# Remember: this DataBunch is tied to the batch size you selected. 
data.save('imageDataBunch-bs-'+str(bs)+'-size-'+str(size)+'.pkl')
# Show the statistics of the Bunch...
print(data.classes)
data

print() 将输出转换和类:

Transforms =  2
['Parasitized', 'Uninfected']

最后一个中的数据命令将简单地输出 ImageDataBunch 实例的返回值:

ImageDataBunch;Train: LabelList (22047 items)
x: ImageList
Image (3, 128, 128),Image (3, 128, 128),Image (3, 128, 128),Image (3, 128, 128),Image (3, 128, 128)
y: CategoryList
Uninfected,Uninfected,Uninfected,Uninfected,Uninfected
Path: data;Valid: LabelList (5511 items)
x: ImageList
Image (3, 128, 128),Image (3, 128, 128),Image (3, 128, 128),Image (3, 128, 128),Image (3, 128, 128)
y: CategoryList
Uninfected,Parasitized,Parasitized,Parasitized,Parasitized
Path: data;Test: None

看一下扩充的数据集群

data.show_batch(rows=5, figsize=(15,15))

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

ResNet18

ResNet18 要小得多,所以我们会有更多的 GPU RAM。我们将再次创建数据批量,这次批量更大。

我也用过 ResNet50,它给出了 92%的准确率。

但是 ResNet18 非常适合这些数据,在这篇博客中,我们将使用它,

现在,创建学习者:

learn18 = cnn_learner(data, models.resnet18, metrics=error_rate)

如果您的 Colab 环境没有 ResNet18 的预训练数据,fast.ai 会自动下载它:

Downloading: "https://download.pytorch.org/models/resnet18-5c106cde.pth" to /root/.torch/models/resnet18-5c106cde.pth
46827520it [00:01, 28999302.58it/s]

让我们来看看这个模型:

learn18.modelThis will list the structure of your net. It is much smaller than the ResNet34, but still has a lot of layers. The output will look like this:Sequential(
  (0): Sequential(
    (0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
    (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (2): ReLU(inplace=True)
    (3): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
    (4): Sequential(
      (0): BasicBlock(
        (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace=True)
        (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
      (1): BasicBlock(
        (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace=True)
        (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (5): Sequential(
      (0): BasicBlock(
        (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
        (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace=True)
        (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (downsample): Sequential(
          (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)
          (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
      (1): BasicBlock(
        (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace=True)
        (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (6): Sequential(
      (0): BasicBlock(
        (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
        (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace=True)
        (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (downsample): Sequential(
          (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)
          (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True).......... and so on

让我们训练它

我们将再次使用 fit_one_cycle HYPO 训练策略。将训练限制在 10 个时期,以观察这个较小网络的行为:

learn18.fit_one_cycle(10, callbacks=[SaveModelCallback(learn18, every='epoch', monitor='accuracy', name='malaria18-1')])
# Save the model
learn18.save('malaria18-stage-1')
# export the model stage
exportStageTo(learn18, path)

下表显示网络学习到大约 96.1%的准确度,并且建议网络不应该被进一步训练:时段#8 和#9 之间的损失显示出 0.005 的减少,但是准确度保持不变,这表明网络已经开始过拟合。

epoch 	train_loss 	valid_loss 	accuracy 	time
0 	0.543975 	0.322170 	0.901107 	01:08
1 	0.354574 	0.198226 	0.927055 	01:07
2 	0.256173 	0.173847 	0.938487 	01:08
3 	0.197873 	0.157763 	0.943930 	01:09
4 	0.163859 	0.148826 	0.947197 	01:08
5 	0.143582 	0.142058 	0.948104 	01:08
6 	0.130425 	0.134914 	0.949918 	01:09
7 	0.118313 	0.132691 	0.951551 	01:09
8 	0.112078 	0.132101 	0.952459 	01:09
9 	0.107859 	0.131681 	0.952096 	01:09

让我们生成一个分类解释并查看混淆矩阵和损失曲线。

interp = ClassificationInterpretation.from_learner(learn18)losses,idxs = interp.top_losses()len(data.valid_ds)==len(losses)==len(idxs)

让我们来看看混淆矩阵:

interp.plot_confusion_matrix(figsize=(5,5), dpi=100)

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

让我们来看看损失:

learn18.recorder.plot_losses()

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

ResNet18 在大约 290 批次后开始有点过度拟合。

记住我们的 bs 在这里是 512,在 ResNet34 是 256。

微调模型

这里我们将介绍另一个 fast.ai HYPO:自动选择的可变学习率。我们将让 fast.ai 为每个历元和每个层选择使用哪个学习速率,提供一个我们认为足够的学习速率范围。我们将训练 30 个纪元的网络。

# Unfreeze the network
learn18.unfreeze()

learn18.fit_one_cycle(30, max_lr=slice(1e-4,1e-5), 
                    callbacks=[SaveModelCallback(learn, every='epoch', monitor='accuracy', name='malaria18')])
learn18.save('malaria18-stage-2')
# export fo deployment
exportStageTo(learn18, path)

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

在这里,我们的 fast.ai 模型经过一些微调后达到了大约 97%的准确率,这已经足够好了。

然而,验证失败,成为上一个时代更糟糕的。这表明我们从大约第 20 纪元开始就已经过度拟合

因此,如果我们要部署模型,请选择具有 20 个历元的模型,并注意这是最好的精度,至少对于此网络,我们可以使用不同的网络来获得更好的结果。

结果

interp = ClassificationInterpretation.from_learner(learn18)losses,idxs = interp.top_losses()len(data.valid_ds)==len(losses)==len(idxs)interp.plot_confusion_matrix(figsize=(5,5), dpi=100)

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

learn.recorder.plot_losses()

这比我们以前吃过的要好。让我们看看损失曲线:

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

在这里,我们看到网络似乎在 500 批次后开始过度拟合,这将证实我们从上面的结果表中推断的怀疑。如果你看上面的曲线,你会看到验证损失在训练的最后三分之一开始增加,表明这部分训练只是过度拟合了网络。

现在我将把这个任务交给你们,调整网络或使用任何技术来控制这种情况。

提示:在每个纪元后保存你的模型。

快乐学习

关注 MachineX 了解更多信息”

参考

基于概率层和 Grad-Cam 的医学图像分析

原文:https://towardsdatascience.com/medical-image-analysis-using-probabilistic-layers-and-grad-cam-42cc0118711f?source=collection_archive---------26-----------------------

解开卷积神经网络的“黑箱”

对医疗保健中用于图像分析的人工智能应用的兴趣正在快速增长。学术期刊中关于机器学习的出版物数量呈指数增长,因此在日常临床实践中已经实现了几种图像识别应用。准确的算法可以作为医生的额外诊断工具,以促进和加快工作流程,最重要的是,提高诊断过程的准确性。

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

图像分析算法应该被添加到医生的工具箱中,而不是被视为医学专家的潜在替代品。尽管医生关心并负责病人的健康,但大多数医生并不熟悉机器学习算法的数学细节。因此,医疗应用不应该充当“黑匣子”,而是提供关于模型如何得出其预测的额外信息。本博客展示了获取这些信息的两种可能的技术:概率层,可用于解决模型预测的不确定性,Grad-CAM 是一种展示哪些像素对模型结果贡献最大的方法。在这个博客中,我们将重点关注皮肤镜图像,但提出的技术也适用于其他医学领域(如放射学和病理学)。

基础架构

将使用 Kaggle 的 public HAM(“人对机器”)10000 数据集来说明这两种技术,该数据集包含 7 类色素性皮肤损伤的超过 10000 个图像,包括几种类型的皮肤癌(即黑色素瘤和基底细胞癌)和侵入性较小的类型,如良性角化病样损伤和生理性黑素细胞损伤。

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

Examples of images in the HAM10000 dataset

尽管数据集包含了年龄和位置等对皮肤病变分类有价值的附加特征,但出于说明的目的,本博客将仅关注成像数据。在左边的几个例子图像,所有获得的皮肤镜描述。

首先,使用具有预定义权重的 VGG16 架构来训练基本卷积神经网络。第一层的重量被冻结,只有最后 6 层被重新训练。添加了具有 softmax 激活功能的额外致密层。

在 10 个时期的训练之后,迁移学习模型产生了 82%的验证准确度。此时,模型的输出由一个数组组成,该数组表示图像属于 7 个类别中的每一个类别的概率(见下文)。

[[2.3303068e-09 1.2782693e-10 1.4191615e-02 1.8526940e-14 3.9408263e-02 9.4640017e-01 2.1815825e-11]]

这些预测已经可以在正确的方向上指导医生,但是模型的“思考”方法的附加信息将增加对这些深度学习模型的理解和信任。接下来的章节将说明概率层和 Grad-CAM 在这方面的价值。

概率层

向模型架构添加概率层是评估模型预测不确定性的一种有效方法。“正常”层和概率层之间的根本区别在于,概率层假设权重具有某种分布,而不是点估计。概率层通过变分推理逼近权值的后验分布。本质上,后验分布通过高斯分布替代函数来近似。在每次向前传递期间,概率层的权重从该代理分布中被采样。

因此,多次引入相同的输入将导致每次预测略有不同。在分类问题中,模型将产生每一类的概率分布。这种概率分布可用于评估模型预测的不确定性:如果不确定性有限,重复的预测将彼此非常接近,而预测的广泛分布意味着较大的模型不确定性。

本博客将重点介绍一个特定概率密集层(Flipout)的实现,使用 Tensorflow 概率模块可以轻松实现。我们使用相同的方法添加密集翻转层,而不是将普通密集层添加到预定义的 VGG16 网络。Flipout 的完整数学背景由 Wen 等人描述,可在的找到。

训练完模型后,我们的密集 Flipout 层的输出乍一看是相似的:一个数组表示 6 个类中每一个的概率。然而,如上所述,由于翻转层在每次向前传递时从分布中采样权重,所以同一图像的每次预测略有不同。通过多次重复对某一图像的预测,可以获得 7 类皮肤损伤中每一类的概率分布。

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

Density plots of two images passing through the network 100 times

左边的每幅图像显示了属于“黑色素细胞痣”(蓝色)或“黑色素瘤”(橙色)类别的图像的概率分布,这是通过将每幅图像通过网络 100 次而产生的。x 轴反映图像属于其中一个类别的概率,而图的高度表示分布密度。

医生的附加信息的价值可以用所描绘的密度图来说明。让我们看看左边的图:通过“正常”卷积神经网络传递第一幅图像将产生“黑色素细胞痣”(蓝色)类的低点估计和“黑色素瘤”(橙色)类的高点估计。概率翻转层能够评估这些预测的不确定性。具体来说,左图显示“黑色素细胞痣”类别的预测(低)概率变化很小。然而,“黑色素瘤”类别的分布有更多的变化,这意味着图像属于“黑色素瘤”类别的概率是相当不确定的。

总之,“正常的”卷积神经网络将为每一类提供一个概率,而包含概率翻转层的模型产生每一类的概率分布,因此可以用于评估模型预测的不确定性。医生可以使用这些额外的信息来更好地理解预测,并使用他/她的知识来确认或排除某个诊断。

Grad-CAM

梯度加权类激活映射(Grad-CAM)是一种从卷积神经网络的最终卷积层提取梯度的方法,并使用该信息来突出显示对图像属于预定义类的预测概率最负责的区域。

Grad-CAM 的步骤包括用随后的全局平均池提取梯度。添加了 ReLU 激活函数,以仅描绘对预定义类别有积极贡献的图像区域。可以在原始图像上绘制所得到的注意力地图,并且可以将其解释为用于识别模型“关注”的区域的视觉工具,以预测图像是否属于特定类别。鼓励对 Grad-CAM 背后的数学理论感兴趣的读者通过 https://arxiv.org/abs/1610.02391阅读 Selvaraju 等人的论文。

下面的代码演示了用我们的基本模型实现 Grad-CAM 的相对容易性。

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

这些图像展示了黑色素瘤的原始图像和使用 Grad-CAM 算法创建的叠加注意力图的相同图像。这些图像清楚地说明 Grad-CAM 产生了对日常临床实践有用的额外信息。该注意力图反映了皮肤损伤的哪些部分对模型的预测影响最大。这一信息可能对指导皮肤活检寻找可疑诊断的确认有价值。此外,如果该算法的预测是准确的,那么在不同的患者中重复使用该算法并结合视觉特征将增加医生对该算法预测的信任。

结论

卷积神经网络有可能为放射科医生、皮肤科医生和病理学家等几个医学专业提供额外的诊断工具。然而,仅仅提供类别预测的模型是不够的。我们认为,引入方法,如添加概率推理和 Grad-CAM,可以深入了解模型的决定性属性,因此对于医生理解并开始在日常临床实践中采用机器学习算法至关重要。

关于作者

Rik Kraan 是医学博士,在荷兰数据科学咨询公司 Vantage AI 担任数据科学家。请随时通过rik.kraan@vantage-ai.com联系

特别感谢 理查德 洛克

媒介合伙人计划计算作家收入的新模型——线性回归分析

原文:https://towardsdatascience.com/medium-partner-programs-new-model-for-calculating-writer-s-earnings-using-basic-linear-regression-bddf8ef7e431?source=collection_archive---------22-----------------------

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

2019 年 10 月 22 日,medium 公布了计算作家收入的新模型。根据这种新模式,**收益将根据媒介会员的阅读时间来计算。**你可以从这篇文章中找到更多关于新模式的信息: 改进我们计算作家收入的方式

新模式自 2019 年 10 月 28 日起生效。我查看了过去 5 天(2019 年 10 月 28 日至 2019 年 11 月 2 日)我在这种新模式下的收益。对于给定的故事,我很好奇,也很兴奋地想知道我的日常收入与媒体成员的阅读时间之间的关系,所以我转向数据分析来寻找答案。

1.使用新模型赚钱的所选故事的数据集

这是我的一些故事的数据集,这些故事使用新的模式赚了钱。

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

Daily earnings versus member reading time for selected stories using the new partner program model.

2.收入与会员阅读时间相关系数的计算

使用 Excel 中的 CORREL() 函数,我们发现相关系数为 0.93,表明收益与会员阅读时间之间存在较强的正相关关系。

3.基本线性回归分析

为了量化收入与会员阅读时间之间的关系,我们使用 Excel 进行了基本的线性回归分析。

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

通过简单的回归分析,我们发现了收入($)和会员阅读时间(分钟)之间的关系:

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

**注意:**这种关系仅适用于成员阅读时间在 11 分钟到 255 分钟的范围内,该范围用于训练模型。

我们使用拟合模型预测每日收入,使用会员阅读次数的原始训练数据,发现均方误差由下式给出:

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

4.使用归一化特征的线性回归

由于成员读取时间包含范围[11,255]内的值,我们决定在执行线性回归分析之前对我们的特征进行归一化。以下是使用归一化要素的线性回归分析的输出:

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

我们使用使用归一化特征的拟合模型,使用会员阅读次数的原始训练数据来预测每日收入,并发现均方误差由下式给出:

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

将其与我们的原始拟合进行比较,我们看到有轻微的改进,但是 MSE 值的差异并不太显著。

因此,基于我们的简单模型,我们已经证明了收入与会员阅读时间的关系如下:

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

该等式可用于预测会员阅读时间在[11,255]分钟范围内的收入。

5。每日收入可变性的来源

我认为收益的可变性可以用一个非常简单的模型来解释。根据对数据的观察,收入似乎是根据所有成员的平均每日阅读时间计算的。

由于每个成员每月支付 5 美元的费用,让我们假设 medium 使用 2 美元的维护费,这样剩下 3 美元的余额可用于支付给作者。

假设一个月有 30 天,这意味着一个成员每天的价值是 3 美元除以 30,即 0.1 美元。在所有会员平均每天阅读时间为 5 分钟的一天,收益率将为 0.1 美元除以 5 分钟或**$ 0.02/分钟**。然而,在所有会员平均每天阅读时间为 10 分钟的一天,收益率将是 0.1 美元除以 10 或0.01 美元/分钟

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

这个简单的模型可以解释收益率的每日变化。

总之,我们已经展示了如何使用合作伙伴计划的最新模型,使用简单的线性回归模型来预测作家的收入。随着越来越多的收入数据从新的媒体合作伙伴计划模型中获得,我们希望在未来扩展这种计算方法。

认识一下 Yauhen:白俄罗斯第一位也是唯一一位 Kaggle 特级大师。

原文:https://towardsdatascience.com/meet-yauhen-the-first-and-the-only-kaggle-grandmaster-from-belarus-ee6ae3c86c65?source=collection_archive---------18-----------------------

与 Yauhen Babakhin 的对话:H2O.ai 的数据科学家和 Kaggle 竞赛的特级大师。

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

竞争数据科学不仅仅是简单地应用算法来获得最佳模型。参加这些比赛的主要收获是,它们提供了一个学习和培养技能的绝佳机会。这些知识可以用于一个人的学术或职业生活中。 Kaggle数据科学竞赛最知名的平台之一,它提供了一个就一些最有趣的机器学习问题进行竞争的机会。经验丰富的人参加这些比赛。有些人做得非常好,并获得了卡格尔大师的称号。在这个系列中,我揭示了卡格尔大师们的惊人故事。

在本次采访中,我将与yau hen Baba Khin a Kaggle 竞赛特级大师、数据科学家H2O.a i. Yauhen 拥有应用数据分析硕士学位,在数据科学领域拥有超过五年的经验。Yauhen 恰好是白俄罗斯第一届 Kaggle 比赛的特级大师,在经典机器学习和深度学习比赛中都获得了金牌。

以下是我与雅亨对话的摘录:

  • 你是白俄罗斯第一位 Kaggle 比赛特级大师。Kaggle 最初吸引你的是什么,你是什么时候赢得第一次胜利的?

Yauhen: 我从 Edx 上的一门在线课程开始了我的数据科学之旅。作为课程的一部分,有一个 Kaggle 比赛,这是我第一次接触到 Kaggle 的概念。我在比赛中排名第 450 位(在公共排行榜上排名前 50 位),但这是一次很好的学习机会,也是继续学习数据科学的动力。大约六个月后,我参加了第二次 Kaggle 比赛,并在那里获得了银牌。

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

Yauhen’s Kaggle Profile

目前,我是白俄罗斯第一个也是唯一一个 Kaggle 特级大师,但是有很多 Kaggle 大师,数据科学社区发展非常快。

  • 你在经典的机器学习和深度学习比赛中都有金牌。你觉得哪些比赛更有挑战性?

Yauhen: 我会说所有的比赛都具有挑战性,但如果让我选择,我会说参加深度学习比赛相对更难。深度学习比赛需要很长的训练时间,所以不可能快速迭代。这使得评估所有的假设变得很困难,人们犯错误的可能性也小得多。

  • 你通常如何处理一个难题?

Yauhen: 我一般会在一个比赛推出后等一两个星期。如果竞争存在一些问题,如数据泄露、数据不正确等。,这些都位于前几周,节省了很多时间。

然后,就像其他人一样,我从探索性数据分析部分开始,然后是假设生成、建立本地验证,并尝试不同的想法和方法。通常,我会创建一个文档,存储所有这些想法、假设、论文和资源,我认为它们可以为这个特定的比赛服务。有时这样的文档甚至可以包含多达 20 页的文本。

除了上面的方法,我在比赛期间关注所有的论坛和核心讨论,以获得对同一问题的不同意见。

  • 您最近在 Kaggle days China 上发表了演讲,您谈了哪些话题,体验如何?

这是我第二次参加卡格尔节。五月,我参加了 Kaggle Days 的迪拜版,做了一个关于伪标签的演讲。这次在北京,我参加了一个关于“机器学习管道中的常见错误”的研讨会我准备了几条管道,观众必须找出其中的错误。

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

Yauhen(7 from L) with other H2O.ai Kaggle Grandmasters during H2O world New York

我喜欢卡格尔日的形式。它允许参与者参加卡格尔大师们举办的讲座和研讨会。此外,在活动的第二天,与会者将参加由 Kaggle 大师提供指导的 8 小时线下比赛。

  • 就数据科学而言,您最喜欢的资源是什么?你更喜欢哪种编程语言?

Yauhen: 随着机器学习和数据科学的飞速发展,很难跟踪每一种可能的资源。所以,我试着把自己限制在一个特定的领域或者一个我目前正在解决的特定问题上。

首先,我将命名为开放数据科学社区(ods.ai) 。它主要是一个讲俄语的 slack 社区,拥有大约 4 万名成员和几乎每个数据科学主题的频道。在这里,人们可以在几秒钟内快速获得任何数据科学概念的信息。然而,如果我需要更深入地理解任何材料,我会直接去找一些博客帖子、论文、youtube 视频等。

说到编程语言,我使用 R 语言开始了我的数据科学之旅,但现在我主要使用 Python

  • 作为 H2O.ai 的一名数据科学家,你的角色是什么?你在哪些具体领域工作?

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

Yauhen(3 from R) with other ‘Makers’ during the H2O Prague Meetup

Yauhen: 我目前在做计算机视觉领域的 AutoML 模型。H2O.ai 的无人驾驶人工智能已经可以处理表格、时间序列和文本数据。现在,我们正在前进,使用无人驾驶人工智能和图像数据来解决分类、分割、物体检测等问题

这个想法是,一旦用户提供了一个包含图像路径和图像标签的 CSV 文件,无人驾驶人工智能应该在时间限制下,自动从这些数据中建立最佳模型。这将需要自动化所有的超参数搜索,例如学习率、优化器、神经网络架构等。和训练过程,如时期数、扩充选择等。此外,这个过程在时间和内存使用方面应该是高效的。我们正在努力,并取得了一些积极的成果。

  • 你通过 Kaggle 学到的最好的东西有哪些是你在 H2O.ai 的专业工作中应用到的?

Yauhen: 我用影像资料参加过几次 Kaggle 比赛。它提供了一个很好的背景,让你知道什么想法在实践中最有效,哪些可以自动化。此外,我会继续阅读竞赛获胜者的解决方案,即使我没有参加某个特定的竞赛。

这样的实用技巧一般不会在任何书籍或在线课程中描述。这就是为什么 Kaggle 允许一个人保持在该领域发展的边缘,并不断改善我们的计算机视觉问题的 AutoML 管道。

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

Yauhen presenting a session on the capability of Driverless AI with image data at H2O World New York,2019

  • 你想在 ML 中应用你的专业知识吗?

我在很多领域都有丰富的经验,比如经典的机器学习、自然语言处理和计算机视觉。但是,我从来没有处理过音频数据。因此,应用一些技术来解决问题是很有趣的,例如音频记录的分类或自然语言理解等等。

  • 给刚刚开始或希望开始数据科学之旅的数据科学有志者一句忠告?

Yauhen: 在我看来,人们应该记住,数据科学之旅在理想情况下应该是理论知识和实践经验的结合。

仅仅阅读书籍、博客文章、浏览在线课程不会给你任何实践经验。你只能获得一些理论上的理解,而不能应用于实践。另一方面,直接进入应用程序也将成为一个猴子的工作。运行 simple fit()-predict()并盲目复制公共 Kaggle 内核,而不了解幕后发生了什么,也将使你一事无成。

所以,我会建议选一门好的网络课程,完成它所有的练习。此外,参加 Kaggle 竞赛,应用你刚刚从论文、书籍、博客等中学到的理论方法。通过这种方式,你会牢牢掌握基本原理,也会理解它们的实际用途。

这次采访是另一个很好的例子,展示了像 Yauhen 这样的人如何以系统的方式努力工作来实现他们的目标。他们定义了一条清晰的道路,并朝着他们的目标努力。从这次谈话中另一个很大的收获是,拥有良好的理论知识只在一定程度上有用。然而,真正考验你理解力的只有当你将所学付诸实践的时候。

阅读本系列的其他采访:

Meetup 总结:R 中的调查和衡量发展

原文:https://towardsdatascience.com/meetup-recap-survey-and-measure-development-in-r-2df3549e5af6?source=collection_archive---------28-----------------------

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

你有没有在医生那里做过调查或者参加过工作面试,并且想知道这些数据到底是用来做什么的*?关于如何从自我报告调查数据中可靠地测量“潜在”特质,如抑郁或忠诚,有一系列长期存在的方法,其中许多来自心理学。*

虽然测量是从人体运动学到教育等领域的一种常见方法,但它通常是在 SPSS 或 MPlus 等专有工具中进行的。关于 R 中的调查开发,确实没有太多的在线培训,但是该程序无法通过像[psych](https://cran.r-project.org/web/packages/psych/index.html)[lavaan](http://lavaan.ugent.be/)这样的包来进行。

整个夏天,我向大克利夫兰 R 用户会议小组介绍了以下长达一小时的 R 调查发展研讨会。视频和幻灯片在下面。您还可以在 RStudio Cloud 上访问演示中使用的所有代码、文件和资源。

幻灯片:

有群体间联系的成员更有可能在 NBA 在线论坛上使用负面语言

原文:https://towardsdatascience.com/members-with-intergroup-contact-are-more-likely-to-use-negative-language-in-online-nba-discussion-9f937837f0b1?source=collection_archive---------36-----------------------

本博客总结了我们的 CSCW 2019 论文" 野外的群际接触:表征 NBA 相关讨论论坛中群际与单群成员的语言差异。 ”由【】谭*。*****

近年来,人们越来越关注世界政治中的两极分化和部落主义。人们会将自己视为社会“部落”的成员,并对其他群体产生敌意。在社交媒体时代,Twitter、Reddit 和脸书等平台可能导致美国共和党和民主党进一步分裂。

为了减少偏见,在具有不同意识形态的人之间建立桥梁,一个建议的策略是让人们走出他们的“回音室】,鼓励与对立群体的群体间接触。这一策略已被证明在许多离线环境中有效,因为人际互动可以挑战人们对彼此的刻板印象。硅谷的一些服务提供商正在他们的社交媒体平台上试验这一策略。在 2018 年接受《华盛顿邮报》采访时,Twitter 首席执行官杰克·多西表示,他的公司正在测试一些功能,这些功能将在 Twitter 的时间表中推广不同的观点,以解决错误信息,减少“回音室”

然而,所提出的战略可能不会取得理想的结果。事实上,最近几项实验研究已经在网上平台上对它进行了测试,我们看到了相互矛盾的结果:群际效应既可以有效应,也可以有效应。在先前的研究中有这些矛盾的结果,我们相信观察研究允许研究人员在野外描述群体间接触的特征,并在不同的背景下提供有价值的补充证据。事实上,随着在线群体的出现,在相当长的时间内大规模观察群体间的联系和个人行为已经成为可能。

Reddit 上 NBA 相关社区的群际设置

我们利用 Reddit 的 NBA 相关论坛的现有结构来识别用户的群体从属关系和职业体育背景下的群体间联系,这是一个不同于政治的新领域。我们选择职业运动队的在线粉丝群作为我们的测试平台,原因如下:

  1. 职业体育在现代生活中起着重要的作用。美国民众 2015 年观看体育比赛的时间超过310 亿小时,2017–2018 年美国国家篮球协会(NBA)赛季的上座率达到2200 万
  2. 与政治环境类似,职业体育在本质上无疑是竞争性的。运动队的球迷可以把对方球队的球迷当成敌人,有时甚至会搞暴力。体育迷也倾向于认为媒体和来自对立球队的支持者很可能会对他们喜欢的球队有不公平的看法,就像意识形态不同的人一样。
  3. /r/NBA subreddit 致力于所有 NBA 球队的球迷之间就任何与 NBA 有关的讨论进行互动。它代表了一个开放和多样化的群体间接触的环境。更重要的是,/r/NBA 的一个独特机制,被称为 flair ,让我们可以轻松识别球迷的球队归属。

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

The illustration of NBA-related discussion forums (also known as subreddits) on Reddit.

上图说明了我们的框架。NBA 有 30 支球队,每支球队都在 reddit 上有自己的讨论论坛(以下简称 team subreddit),相应球队的球迷可以在这里聚集并讨论新闻、比赛和任何其他与球队相关的话题。中央的/r/NBA 标志代表/r/NBA,不同球队的球迷在这里进行团体间的接触。鉴于 team subreddit 和/r/NBA 的不同性质,我们首先定义两个设置:

  1. 团际设定:/r/NBA。
  2. 组内设置:每支球队的子区(如湖人的子区凯尔特人的子区)。

基于这两个设定,我们根据他/她在/r/NBA 中的行为(缺失)来确定一个球队的球迷是否暴露在群际接触中,我们称之为群际状态。总而言之,我们将球队的球迷分为以下两类:

  1. Intergroup(红色图标):在赛季中同时在附属球队 subreddit 和/r/NBA 发帖的球队球迷。
  2. 单组(蓝色图标):赛季中只在所属球队 subreddit 发帖而不在/r/NBA 发帖的球队球迷。

在比较之前,我们确保群际和单组成员在附属团队子群中的任何可观察特征上先验平衡,这表明对团队的忠诚度相似。为了实现这一点,我们采用匹配技术:对于每个单组成员,我们将他/她与来自同一附属团队的最相似的不匹配组间成员进行匹配,其中相似性是基于可观察的活动特征来测量的(查看我们的论文以了解详细信息)。

组内语言差异

我们发现群际成员比单组成员在他们所属的小组中更情绪化。这反映在他们对负面词汇、脏话和仇恨言论的使用上。举例来说,下图比较了所有团队(all)中组间成员和单组成员使用负面词汇的情况。我们在两个最大的(GSW,LAL)和最小的(DEN,ORL)子团队中看到了相同的趋势,这两个子团队是由至少有 100 个单组成员的团队中的订户数量排名的。我们进一步在右上角显示了所有 30 个团队的散点图,以说明我们的发现在团队之间是稳健的。此外,我们还比较了这两组成员之间的积极语言使用,但我们没有发现他们之间的一致差异(更多细节见我们的论文)。

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

The comparison of negative word usage between intergroup and single-group members in the 2018 season.

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

The top-10 over-represented words used by intergroup (red) and single-group (blue) members in the 2018 season.

为了进一步解释群际和单群成员在语言使用上的差异,我们确定了一个更有可能被群际和单群成员使用的区别词列表。上图显示,单组成员在附属团队 subreddit 中评论时更加友好和冷静,使用更多礼貌用语,如“同意”、“感谢”、“帮助”。此外,“座位”表明一些单组成员是当地球迷,因为他们经常讨论有关参加现场比赛的信息。相比之下,组间成员使用更多的脏话,谈论更多的裁判(可能是抱怨)。

不同层次的群际接触

****我们的观察研究表明,高水平群际接触的成员倾向于使用更多的负面语言,但群际接触水平如何影响负面语言的使用存在不同的机制。我们根据用户在组间设置(/r/NBA)中的评论分数,对所有 30 个团队子编辑中的用户进行分组,并为他们分配标签 1、2、3、4 或 5。较大的标签表明较高水平的群体间接触。我们还为单组成员分配标签 0。下图显示了不同群体间接触水平的成员之间的负面语言使用差异。群体间接触水平较高的成员通常在语言使用上更消极:他们倾向于使用更多的负面词汇和脏话,并在附属团队 subreddit 中产生更多的仇恨言论评论。然而,趋势不一定是线性的。例如,水平 1 的组间成员在左侧的消极词汇使用上与单组成员没有显著差异,而水平 5 的组间成员在两个图中都呈现出从先前水平的显著跳跃。

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

Negative and swear word usage of members with different intergroup contact levels in the 2018 season.

同一用户的组内行为与组间行为

到目前为止,我们已经证明了群际成员在他们所属的团队子群中使用更多的负面语言。但这是为什么呢?通过比较他们在组间环境和组内环境中的行为,我们发现他们在组间环境中使用更多的负面语言**,因为他们比在组内环境中使用更多的负面词汇和脏话,并产生更多的仇恨言论。请注意,这种比较自然适用于受试者:我们在两种情况下比较同一个人。我们的结果表明,尽管在附属团队 subreddit 中,群际成员比单群成员更情绪化,但他们并不像在群际环境中那样“令人发指”。相比较而言,当去 intergroup setting 与其他队组的粉丝对抗时,他们往往会有更多的负面互动,并互相 troll。**

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

Intergroup members use more negative words in the intergroup setting than in the intragroup setting in the 2018 season.

社交媒体会导致两极分化吗?

Twitter、Reddit 和脸书已经成为政治讨论和错误信息的重要平台。服务提供商正在设计新的功能,主动让人们接触到反对的观点。然而,所提出的解决方案可能会增加极化。与几十年的线下实验不同,这些实验大多表明对立团体成员之间长时间的亲密接触会产生积极影响,贝尔等人我们的工作的结果表明,在网上遇到来自对立团体的观点可能会使他们更加坚持自己的观点。通过研究群体间接触影响个体态度的可能机制,对这种对比有几种可能的解释。首先,在社交媒体上创建的评论通常很简短。这些没有足够上下文的短消息可能不会增强对对立群体的了解。第二,讨论结构可能会促进负面互动的传播。 Cheng 等人研究了上讨论的演变,表明讨论线索中现有的钓鱼评论显著增加了将来出现钓鱼评论的可能性。第三,社交媒体交流的匿名性和自发性可能不利于培养同理心。总之,根据环境和接触的性质,组间接触可能导致不同的结果。

我们能为不同的群体设计更好的在线论坛吗?

我们工作中的发现表明,社交平台设计者应该考虑在线塑造群体间联系的策略。正如上面所暗示的,推荐用户关注对立团体或对立观点的成员是不够的。需要试验更好的设计策略来鼓励民间和更广泛的群体间接触。考虑不同水平的群体间接触如何以不同方式缓和个人意见也是有益的。在群体间接触的背景下,内容适度可能是未来研究的一个有前途的领域。类似地,传播在线信息的一种强有力的方式是通过社会共识线索和在线认可(例如,支持票、赞)。然而,简单地推广最受欢迎的内容有时会有问题。早期研究表明,带有更多情感负载词的推文可能会受到喜爱或转发,政治家可能会有意使用这种策略来最大化 Twitter 上的影响。这种类型的行为会引起对立群体的负面反应,并推动整个讨论向更情绪化和可能两极分化的内容发展。因此,重要的是开发评论排名系统,认识到群体间的联系,并优先考虑建设性的互动。

Keras & Tensorflow 中基于深度卷积网络的模因文本生成

原文:https://towardsdatascience.com/meme-text-generation-with-a-deep-convolutional-network-in-keras-tensorflow-a57c6f218e85?source=collection_archive---------6-----------------------

这篇文章的目标是描述如何为文本生成构建一个深度的 conv 网络,但是比我读过的一些现有文章更有深度的 T2。这将是一个实用的指南,虽然我建议了许多最佳实践,但我不是深度学习理论的专家,也没有读过每一篇相关的研究论文。我将讨论数据清理、训练、模型设计和预测算法。

步骤 1:构建培训数据

我们将从中提取的原始数据集是来自 Imgflip meme 生成器用户的大约 1 亿条公共 Meme 说明。为了加快训练速度和降低模型的复杂性,我们只使用 48 个最流行的模因和每个模因正好 20,000 个标题,总共 960,000 个标题作为训练数据。然而,由于我们正在构建一个世代模型,因此标题中的每个字符都将有一个训练示例,总计约 45,000,000 个训练示例。这里选择了字符级生成而不是单词级,因为模因倾向于使用拼写和语法…呃…创造性地。此外,字符级深度学习是单词级深度学习的超集,因此如果你有足够的数据,并且你的模型设计足以学习所有的复杂性,则可以实现更高的准确性。如果你尝试下面的成品模型,你也会发现 char 级别会更有趣!

如果第一个模因标题是“制造所有模因”,则训练数据看起来如下。我省略了从数据库读取和执行初始清理的代码,因为它非常标准,并且可以通过多种方式完成。

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

training_data = [
    ["000000061533  0  ", "m"],
    ["000000061533  0  m", "a"],
    ["000000061533  0  ma", "k"],
    ["000000061533  0  mak", "e"],
    ["000000061533  0  make", "|"],
    ["000000061533  1  make|", "a"],
    ["000000061533  1  make|a", "l"],
    ["000000061533  1  make|al", "l"],
    ["000000061533  1  make|all", " "],
    ["000000061533  1  make|all ", "t"],
    ["000000061533  1  make|all t", "h"],
    ["000000061533  1  make|all th", "e"],
    ["000000061533  1  make|all the", " "],
    ["000000061533  1  make|all the ", "m"],
    ["000000061533  1  make|all the m", "e"],
    ["000000061533  1  make|all the me", "m"],
    ["000000061533  1  make|all the mem", "e"],
    ["000000061533  1  make|all the meme", "s"],
    ["000000061533  1  make|all the memes", "|"],

    ... 45 million more rows here ...
]
# we'll need our feature text and labels as separate arrays later
texts = [row[0] for row in training_data]
labels = [row[1] for row in training_data]

和机器学习中的大部分事情一样,这只是一个分类问题。我们将左边的文本字符串分类到大约 70 个不同的桶中,桶是字符。

我们来解一下格式。

  • 前 12 个字符是 meme 模板 ID。这使得模型能够区分我们正在喂它的 48 种不同的迷因。该字符串用零填充,因此所有 id 的长度相同。
  • 01是当前被预测文本框的索引,一般 0 是顶框,1 是底框,虽然很多模因更复杂。这两个空格只是额外的间隔,以确保模型可以将框索引与模板 ID 和 meme 文本区分开来。注意:关键是我们的卷积核宽度(见后文)不超过 4 个空格加上索引字符,也就是≤ 5。
  • 之后是迄今为止迷因的文本,用|作为文本框的结束字符。
  • 最后,最后一个字符本身(第二个数组项)是序列中的下一个字符。

在训练之前,对数据使用了几种清理技术:

  • 修剪开头和结尾的空白,用一个空格字符替换重复的空白(\s+)。
  • 应用最小长度为 10 个字符的字符串,这样我们就不会产生无聊的一个单词或一个字母的模因。
  • 应用 82 个字符的最大字符串长度,这样我们就不会生成超长的模因,因为模型将训练得更快。82 是任意的,它只是使整体训练字符串大约 100 个字符。
  • 将所有内容都转换成小写,以减少模型必须学习的字符数量,因为许多模因都是大写字母。
  • 跳过带有非 ascii 字符的 meme 标题,以降低模型必须学习的复杂性。这意味着我们的特征文本和标签都将来自大约 70 个字符的集合,这取决于训练数据恰好包括哪些 ascii 字符。
  • 跳过包含管道字符|的 meme 标题,因为它是我们特殊的文本框结尾字符。
  • 通过语言检测库运行文本,跳过不太可能是英语的迷因说明。提高了我们生成的文本的质量,因为模型只需学习一种语言,而相同的字符序列在多种语言中可以有不同的含义。
  • 跳过我们已经添加到训练集的重复迷因标题,以减少模型简单记忆整个迷因标题的机会。

我们的数据现在可以输入神经网络了!

步骤 2:数据张量化

这可能是也可能不是一个词。有趣的事实:显然,我们在深度学习领域是异教徒,因为我们称多维数组为张量,而不是数学术语“全息”,这是一种不需要特殊变换属性的广义张量。但无论如何,张量听起来比全息更酷;)

首先,这是我们下面要做的所有事情的 python 导入代码:

**from** keras **import** Sequential
**from** keras.preprocessing.sequence **import** pad_sequences
**from** keras.callbacks **import** ModelCheckpoint
**from** keras.layers **import** Dense, Dropout, GlobalMaxPooling1D, Conv1D, MaxPooling1D, Embedding
**from** keras.layers.normalization **import** BatchNormalization
**import** numpy **as** np
**import** util  # util is a custom file I wrote, see github link below

神经网络对数字的张量(向量/矩阵/多维数组)进行操作,因此我们需要相应地重构我们的文本。我们的每个训练文本都将被转换为一个整数数组(一个秩为 1 的张量),方法是用数据中找到的大约 70 个唯一字符的数组中的相应索引来替换每个字符。字符数组的顺序是任意的,但是我们选择按字符频率来排序,这样当改变训练数据量时,它会保持大致一致。Keras 有一个 Tokenizer 类,你可以用它来做这件事(char_level=True ),但是我写了自己的 util 函数,因为它们肯定比 Keras tokenizer 快。

# output: {' ': 1, '0': 2, 'e': 3, ... }
char_to_int = util.map_char_to_int(texts)# output: [[2, 2, 27, 11, ...], ... ]
sequences = util.texts_to_sequences(texts, char_to_int)labels = [char_to_int[char] for char in labels]

这些是我们的数据按频率顺序包含的字符:

0etoains|rhl1udmy2cg4p53wf6b897kv."!?j:x,*"z-q/&$)(#%+_@=>;<][~`^}{\

接下来,我们将使用前导零填充整数序列,使它们都具有相同的长度,因为模型的张量数学要求每个训练示例的形状都相同。(注意:我可以在这里使用低至 100 的长度,因为我们的文本只有 100 个字符,但是我希望以后所有的池操作都能被 2 整除。)

SEQUENCE_LENGTH = 128
data = pad_sequences(sequences, maxlen=SEQUENCE_LENGTH)

最后,我们将整理我们的训练数据,并将其分成训练集和验证集。洗牌(使顺序随机化)确保数据的特定子集不总是我们用来验证准确性的子集。将一些数据拆分到一个验证集中,可以让我们衡量模型在我们不允许它用于训练的例子上的表现。

*# randomize order of training data*
indices = np.arange(data.shape[0])
np.random.shuffle(indices)
data = data[indices]
labels = labels[indices]*# validation set can be much smaller if we use a lot of data* validation_ratio = 0.2 ifdata.shape[0] < 1000000 else0.02
num_validation_samples = int(validation_ratio * data.shape[0])

x_train = data[:-num_validation_samples]
y_train = labels[:-num_validation_samples]
x_val = data[-num_validation_samples:]
y_val = labels[-num_validation_samples:]

第三步:模型设计

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

我选择使用卷积网络,因为卷积训练简单快速。我确实短暂地测试了一个两层 LSTM,但每次训练的精度比 conv 网络差,即使是这么小的 LSTM,预测的时间也比宇宙的年龄长(好吧,可能只是感觉太长了)。生成敌对网络是具有巨大潜力的美丽生物,但将它们用于文本生成仍处于早期阶段,我的第一次尝试也乏善可陈。也许这将是我的下一篇文章…

好了,下面是在 Keras 中用来构建我们的 conv 网模型的代码:

EMBEDDING_DIM = 16model = Sequential()model.add(Embedding(len(char_to_int) + 1, EMBEDDING_DIM, input_length=SEQUENCE_LENGTH))
model.add(Conv1D(1024, 5, activation='relu', padding='same'))
model.add(BatchNormalization())
model.add(MaxPooling1D(2))
model.add(Dropout(0.25))
model.add(Conv1D(1024, 5, activation='relu', padding='same'))
model.add(BatchNormalization())
model.add(MaxPooling1D(2))
model.add(Dropout(0.25))
model.add(Conv1D(1024, 5, activation='relu', padding='same'))
model.add(BatchNormalization())
model.add(MaxPooling1D(2))
model.add(Dropout(0.25))
model.add(Conv1D(1024, 5, activation='relu', padding='same'))
model.add(BatchNormalization())
model.add(MaxPooling1D(2))
model.add(Dropout(0.25))
model.add(Conv1D(1024, 5, activation='relu', padding='same'))
model.add(BatchNormalization())
model.add(GlobalMaxPooling1D())
model.add(Dropout(0.25))
model.add(Dense(1024, activation='relu'))
model.add(BatchNormalization())
model.add(Dropout(0.25))
model.add(Dense(len(labels_index), activation='softmax'))

model.compile(loss='sparse_categorical_crossentropy', optimizer='rmsprop', metrics=['acc'])

那里发生了很多事情。下面是所有代码正在做的事情:

首先,该模型使用 Keras 嵌入将每个输入示例从 128 个整数的数组(每个表示一个文本字符)转换为 128x16 的矩阵。嵌入是一个层,它学习一种最佳方式来将我们的每个字符从表示为整数转换为表示为类似于[0.02, ..., -0.91]的 16 个浮点数的数组。这使得模型可以通过在 16 维空间中将字符相互靠近嵌入来了解哪些字符被类似地使用,并最终提高模型预测的准确性。

接下来,我们添加 5 个卷积层,每个卷积层的内核大小为 5,1024 个滤波器,以及一个 ReLU 激活。从概念上讲,第一个 conv 层正在学习如何从字符构造单词,后面的几层正在学习构造更长的单词和单词链(n-grams),每一层都比前一层更抽象。

  • padding='same'用于确保层的输出尺寸与输入尺寸相同,否则宽度为 5 的卷积会使内核每侧的层尺寸减少 2。
  • 选择 1024 作为过滤器的数量,因为它是训练速度和模型精度之间的良好折衷,通过反复试验来确定。对于其他数据集,我建议从 128 个过滤器开始,然后增加/减少两倍,看看会发生什么。更多的过滤器通常意味着更好的模型准确性,但是训练更慢,运行时预测更慢,并且模型更大。但是,如果您的数据太少或过滤器太多,您的模型可能会过拟合,精度会直线下降,在这种情况下,您应该减少过滤器。
  • 在测试了 2、3、5 和 7 之后,选择了内核大小为 5。内核 2 和 3 的表现更差,内核 7 与内核 2 和内核 3 相似,但速度更慢,因为需要多训练 7/5 个参数。在我的研究中,其他人已经成功地在各种组合中使用了大小为 3 到 7 的内核,但我的观点是,大小为 5 的内核通常在文本数据上表现不错,并且您可以随时在以后进行实验,为您的特定数据集挤出更多的准确性。
  • 选择 ReLU 激活是因为它快速、简单,并且非常适合各种各样的用例。我从阅读一些文章和研究论文中得出的结论是,Leaky ReLU 或其他变体可能会对一些数据集产生轻微的改善,但并不保证会更好,而且在较大的数据集上不太可能明显。
  • 在每个 conv 图层后添加批次归一化,以便基于给定批次的均值和方差对下一图层的输入参数进行归一化。深度学习工程师还没有完全理解这种机制,但我们知道标准化输入参数可以提高训练速度,并且由于消失/爆炸梯度,这对于更深的网络变得更加重要。原批次归一化论文成绩斐然。
  • 在每个 conv 图层后添加一点点遗漏,以帮助防止图层简单地记忆数据和过度拟合。Dropout(0.25)随机删除 25%的参数(将其设置为零)。
  • MaxPooling1D(2)被添加到每个 conv 层之间,以将我们的 128 个字符的序列对半“挤压”成后续层中的 64、32、16 和 8 个字符的序列。从概念上讲,这允许卷积过滤器从更深层的文本中学习更抽象的模式,因为我们的 width 5 内核在通过每个 max pooling 操作将维度减少 2 倍后将跨越两倍的字符。

在所有 conv 层之后,我们使用一个全局最大池层,它与普通最大池层相同,只是它会自动选择缩小输入大小的程度,以匹配下一层的大小。最后的层只是具有 1024 个神经元的标准密集(全连接)层,最后是 70 个神经元,因为我们的分类器需要输出 70 个不同标签中每个标签的概率。

model.compile 步骤非常标准。RMSprop 优化器是一个相当不错的全面优化器,我没有尝试为这个神经网络改变它。loss=sparse_categorical_crossentropy告诉模型,我们希望它进行优化,从一组 2 个或更多类别(也称为标签)中选择最佳类别。“稀疏”部分指的是我们的标签是 0 到 70 之间的整数,而不是每个长度为 70 的独热数组。对标签使用一个热阵列会占用更多的内存、更多的处理时间,并且不会影响模型的准确性。不要使用一个热标签!

Keras 有一个很好的model.summary()函数,可以让我们查看我们的模型:

_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
embedding_1 (Embedding)      (None, 128, 16)           1136
_________________________________________________________________
conv1d_1 (Conv1D)            (None, 128, 1024)         82944
_________________________________________________________________
batch_normalization_1 (Batch (None, 128, 1024)         4096
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 64, 1024)          0
_________________________________________________________________
dropout_1 (Dropout)          (None, 64, 1024)          0
_________________________________________________________________
conv1d_2 (Conv1D)            (None, 64, 1024)          5243904
_________________________________________________________________
batch_normalization_2 (Batch (None, 64, 1024)          4096
_________________________________________________________________
max_pooling1d_2 (MaxPooling1 (None, 32, 1024)          0
_________________________________________________________________
dropout_2 (Dropout)          (None, 32, 1024)          0
_________________________________________________________________
conv1d_3 (Conv1D)            (None, 32, 1024)          5243904
_________________________________________________________________
batch_normalization_3 (Batch (None, 32, 1024)          4096
_________________________________________________________________
max_pooling1d_3 (MaxPooling1 (None, 16, 1024)          0
_________________________________________________________________
dropout_3 (Dropout)          (None, 16, 1024)          0
_________________________________________________________________
conv1d_4 (Conv1D)            (None, 16, 1024)          5243904
_________________________________________________________________
batch_normalization_4 (Batch (None, 16, 1024)          4096
_________________________________________________________________
max_pooling1d_4 (MaxPooling1 (None, 8, 1024)           0
_________________________________________________________________
dropout_4 (Dropout)          (None, 8, 1024)           0
_________________________________________________________________
conv1d_5 (Conv1D)            (None, 8, 1024)           5243904
_________________________________________________________________
batch_normalization_5 (Batch (None, 8, 1024)           4096
_________________________________________________________________
global_max_pooling1d_1 (Glob (None, 1024)              0
_________________________________________________________________
dropout_5 (Dropout)          (None, 1024)              0
_________________________________________________________________
dense_1 (Dense)              (None, 1024)              1049600
_________________________________________________________________
batch_normalization_6 (Batch (None, 1024)              4096
_________________________________________________________________
dropout_6 (Dropout)          (None, 1024)              0
_________________________________________________________________
dense_2 (Dense)              (None, 70)                71750
=================================================================
Total params: 22,205,622
Trainable params: 22,193,334
Non-trainable params: 12,288
_________________________________________________________________

如果你不喜欢在脑子里做张量形状乘法,参数计数会特别有用。当调整我们上面讨论的超参数时,关注模型的参数计数是有用的,它粗略地表示了模型的学习能力总量。

第四步:培训

现在,我们将让模型进行训练,并使用“检查点”来保存沿途的历史和最佳模型,以便我们可以在训练期间的任何时间点使用最新的模型来检查进度和进行预测。

*# the path where you want to save all of this model's files* MODEL_PATH = '/home/ubuntu/imgflip/models/conv_model'
*# just make this large since you can stop training at any time* NUM_EPOCHS = 48
*# batch size below 256 will reduce training speed since* # CPU (non-GPU) work must be done between each batch
BATCH_SIZE = 256*# callback to save the model whenever validation loss improves* checkpointer = ModelCheckpoint(filepath=MODEL_PATH + '/model.h5', verbose=1, save_best_only=True)*# custom callback to save history and plots after each epoch* history_checkpointer = util.SaveHistoryCheckpoint(MODEL_PATH)*# the main training function where all the magic happens!* history = model.fit(x_train, y_train, validation_data=(x_val, y_val), epochs=NUM_EPOCHS, batch_size=BATCH_SIZE, callbacks=[checkpointer, history_checkpointer])

你只需要坐在这里,看着这个神奇的数字在几个小时内上升…

Train on 44274928 samples, validate on 903569 samples
Epoch 1/48
44274928/44274928 [==============================] - 16756s 378us/step - loss: 1.5516 - acc: 0.5443 - val_loss: 1.3723 - val_acc: 0.5891Epoch 00001: val_loss improved from inf to 1.37226, saving model to /home/ubuntu/imgflip/models/gen_2019_04_04_03_28_00/model.h5
Epoch 2/48
44274928/44274928 [==============================] - 16767s 379us/step - loss: 1.4424 - acc: 0.5748 - val_loss: 1.3416 - val_acc: 0.5979Epoch 00002: val_loss improved from 1.37226 to 1.34157, saving model to /home/ubuntu/imgflip/models/gen_2019_04_04_03_28_00/model.h5
Epoch 3/48
44274928/44274928 [==============================] - 16798s 379us/step - loss: 1.4192 - acc: 0.5815 - val_loss: 1.3239 - val_acc: 0.6036Epoch 00003: val_loss improved from 1.34157 to 1.32394, saving model to /home/ubuntu/imgflip/models/gen_2019_04_04_03_28_00/model.h5
Epoch 4/48
44274928/44274928 [==============================] - 16798s 379us/step - loss: 1.4015 - acc: 0.5857 - val_loss: 1.3127 - val_acc: 0.6055Epoch 00004: val_loss improved from 1.32394 to 1.31274, saving model to /home/ubuntu/imgflip/models/gen_2019_04_04_03_28_00/model.h5
Epoch 5/48
 1177344/44274928 [..............................] - ETA: 4:31:59 - loss: 1.3993 - acc: 0.5869

快进一下,下面是我们在每个时期的损失和准确性的一些闪亮的图表:

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

我发现,当训练损失/准确性比验证损失/准确性更糟糕时,这是模型学习良好而不是过度拟合的迹象。

顺便提一下,如果你使用 AWS 服务器进行培训,我发现最佳实例是 p3.2xlarge。这使用了他们截至 2019 年 4 月的最快 GPU(Tesla V100),该实例只有一个 GPU,因为我们的模型无法非常有效地利用多个 GPU。我确实尝试过使用 Keras 的 multi_gpu_model,但它需要使批处理大小更大才能真正实现速度提升,这可能会扰乱模型的收敛能力,即使使用 4 个 gpu,它也只能快 2 倍。4 个 GPU 的 p3.8xlarge 价格是 4 倍多,所以对我来说不值得。

第五步:预测

好了,现在我们有了一个模型,可以输出哪个字符应该出现在迷因标题中的概率,但是我们如何使用它从头开始创建一个完整的迷因标题呢?

基本前提是,我们用我们想要为其生成文本的任何迷因来初始化一个字符串,然后我们为每个字符调用一次model.predict,直到模型输出框尾文本字符|的次数与迷因中的文本框一样多。对于上面看到的“X All The Y”迷因,文本框的默认数量是 2,我们的初始文本应该是:

"000000061533  0  "

鉴于模型输出的概率为 70,我尝试了几种不同的方法来选择下一个角色:

  1. 每次选择得分最高的角色。这非常无聊,因为它每次都为给定的模因选择完全相同的文本,并且在模因中反复使用相同的单词。它一遍又一遍地吐槽“当你发现你的朋友是 X 所有 Y 迷因的最佳聚会”。它也喜欢在其他迷因中大量使用“最好的”和“派对”这样的词。
  2. 给每个角色一个被选中的概率,这个概率等于模型给它的分数,但前提是这个分数高于某个阈值(最高分的 10%对这个模型来说很好)。这意味着可以选择多个字符,但偏向于得分较高的字符。这种方法成功地增加了多样性,但较长的短语有时缺乏连贯性。这里有一个来自 Futurama Fry meme 的:“不知道她是说还是只是把我的一天放了”。
  3. 给每个角色一个相等的被选中的概率,但前提是它的分数足够高(最高分的 10%以上对这个模型效果很好)。此外,使用波束搜索在任何给定时间保持 N 个文本的运行列表,并使用所有字符得分的乘积,而不仅仅是最后一个字符的得分。这需要 N 倍的时间来计算,但在某些情况下似乎可以提高句子的连贯性。

我目前使用方法#2,因为它比波束搜索快得多,而且两种方法都给出了不错的结果。以下是一些随机的例子:

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

你可以自己玩最新的模型,从 imgflip.com/ai-meme 48 个迷因中的任何一个中产生。

下面是使用方法#2 进行运行时预测的代码。Github 上的完整实现是一个通用的波束搜索算法,因此只需将波束宽度增加到 1 以上,就可以启用波束搜索。

# min score as percentage of the maximum score, not absolute
MIN_SCORE = 0.1
int_to_char = {v: k for k, v in char_to_int.items()}def predict_meme_text(template_id, num_boxes, init_text = ''):
  template_id = str(template_id).zfill(12)
  final_text = ''
  for char_count in range(len(init_text), SEQUENCE_LENGTH):
    box_index = str(final_text.count('|'))
    texts = [template_id + '  ' + box_index + '  ' + final_text]
    sequences = util.texts_to_sequences(texts, char_to_int)
    data = pad_sequences(sequences, maxlen=SEQUENCE_LENGTH)
    predictions_list = model.predict(data)
    predictions = []
    for j in range(0, len(predictions_list[0])):
      predictions.append({
        'text': final_text + int_to_char[j],
        'score': predictions_list[0][j]
      })
    predictions = sorted(predictions, key=lambda p: p['score'], reverse=True)
    top_predictions = []
    top_score = predictions[0]['score']
    rand_int = random.randint(int(MIN_SCORE * 1000), 1000)
    for prediction in predictions:
      # give each char a chance of being chosen based on its score
      if prediction['score'] >= rand_int / 1000 * top_score:
        top_predictions.append(prediction)
    random.shuffle(top_predictions)
    final_text = top_predictions[0]['text']
    if char_count >= SEQUENCE_LENGTH - 1 or final_text.count('|') == num_boxes - 1:
      return final_text

你可以在 github 上查看所有代码,包括实用函数和一个样本训练数据文件。

第六步:???

第七步:显然,从人工智能生成的迷因中获利

结束了。

钢铁之躯:用经验贝叶斯估计寻找最佳点球手

原文:https://towardsdatascience.com/men-of-steel-finding-the-best-penalty-takers-with-empirical-bayes-estimation-aa0e126fb08b?source=collection_archive---------24-----------------------

当一切都归结为点球,你能相信谁?

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

Photo by Jannes Glas on Unsplash

可以说是足球比赛中最紧张的时刻,罚球是心理战:两个人,一个球和一个明显的进球机会。一个点球应该在职业水平上完成:句号。其他的都是失败。

这样的任务应该只要求拥有最冰冷血脉的玩家来完成。

有伟大的点球手,我们总是可以指望他们以惊人的节奏效率将球送到网后。还有一些人,他们令人沮丧的努力,注册商标的脚尖跑或近轨道打击,只是我们深感遗憾或无情嘲笑的来源。

你会认为罚点球很容易。或许花 5 分钟看这个视频。

那么谁是真正的超人:钢铁之躯呢?

你可以想象这将是一个简单的二级数学题。我们收集所有点球的记录,计算所有这些球员和 TADA 的相应转换率!

但是让我们看看真实的例子,看看这个简单的逻辑是如何失败的!!!

一方面,我们有克里斯蒂亚诺·罗纳尔多,他有五个金球奖,他的绰号“佩纳尔多”代表了他在球门前坚定不移的自我镇定,他有着令人印象深刻的 98 次点球中 85 次进球的记录(86.7%)。另一方面,我们有一个年轻的天才,阿森纳的尼古拉斯·佩佩,他最近对维拉的进球使他的进球总数达到 11 次成功 10 次(90.9%)。佩佩在点球上比罗纳尔多更好/更可靠吗?

当然,说那样的话会很可笑!!!

虽然年轻球员的得分比例略高,但这并不是很多证据:一个典型的球员几乎 80%的时间都可以得分,佩佩 90.9%的成功率可能是因为运气。另一方面,罗纳尔多有很多证据表明他高于普通球员。

我们如何系统地比较 85/98 和 10/11 这样的比率,并做出有意义的判断?

贝氏统计来救援:

我们发现这种困境的不仅仅是足球。由于低计数的不确定性,我们在处理成功/总数比率时肯定会出错。简单的解决办法就是设置一些门槛,过滤掉那些达不到最低要求的玩家。但这远非理想:我们丢弃了可能有用的信息。

让我后退一步,重新设计问题:我们想在某种程度上衡量一名球员天生的罚球能力。他的历史记录仅仅是对这种能力的估计。任务是根据他的历史记录更准确地评估他的能力。

我希望你能看到这是如何自然地把我们引向一个经典的贝叶斯设置:我们可以从对球员能力的一些的预先期望开始,通过 新证据更新它*——也就是说,用他的实际得分记录,我们得到对他真实能力的更实际的估计。*

为了更好地回顾贝叶斯框架,你可以看看我的其他文章:

* [## 贝叶斯统计如何说服我去健身房

一个有趣的旅程,进入线性回归理论与贝叶斯触摸(是的,我使用度量测量在这…

towardsdatascience.com](/how-bayesian-statistics-convinced-me-to-hit-the-gym-fa737b0a7ac) [## 寻找上帝的贝叶斯探索

贝叶斯定理和最基本问题的概率答案:“上帝存在吗?”

towardsdatascience.com](/a-bayesian-quest-to-find-god-b30934972473)

先验期望和经验贝叶斯;

我正踩在一颗地雷上。虽然贝叶斯设置有直观的意义,但要让人们在使用每个设置之前达成合理的一致几乎是不可能的。

一个人如何去具体说明他们先前的信念?尤其是如果你没有一个知情的猜测?一种方法可能是分配一个**“平坦先验”——一个你指定你的参数的每一个值都是同等可能的先验。另一种方法是使用经验贝叶斯**,其中你的数据用于估计先验。这里有一个问题:我没有事先对先验有一个固定的概念,而是在收集数据后查看数据并相应地估计先验分布,这样就可以避免所有的麻烦。

这种方法有很多优点。这很简单,而且它消除了(嗯,某种程度上)当我不得不选择自己的前科时可能产生的主观性。就我个人而言,我发现这种方法有助于我获得一定程度的稳定结果。平坦的先验或与数据不符的东西会导致奇怪的结果,例如负的后验概率。相信我,这并不少见。用经验贝叶斯我更有可能得到理智的答案。

听听著名统计学家布拉德利·埃夫隆对这种方法的看法:

自从我在 20 世纪 70 年代通过 Robbins 和 Stein 第一次接触以来,经验贝叶斯一直是我最感兴趣的话题。有时它仍然像魔法一样。[1]

DataCamp 的首席数据科学家大卫·罗宾逊也提供了一些很好的见解:

这基本上归结为我们有多少观察值:如果我们有很多,我们可以得到一个不太依赖于任何一个个体的好的估计。经验贝叶斯是对更精确的贝叶斯方法的一种近似(T0 )-----------------------就我们所拥有的数据量而言,这是一种非常好的近似。[2]

我知道,这感觉像是欺骗,而且确实如此。许多人认为先验信息是观测值的外生信息,因此批评使用实际数据来估计先验信息,因为这会低估建模误差。任何数据都会对使用相同数据来指定其某些特征的模型感到自满。

寻找先验—贝塔分布:

让我们看一下数据。

我收集了欧洲 6 个不同联赛 13 年的点球数据。看起来是这样的:

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

Records of penalty kicks — ranked by the total number of kicks taken. Our job is to ‘adjust’ the success ratio in order to compare these players.

如前所述,为了得到成功率先验的一个很好的近似值,我们将看看它的实际分布。

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

Left: the histogram of our actual penalty conversion rate . Right: The multiple shapes the Beta distribution can describe with its parameters. Source: Wikipedia

在这里,我们的任务是找到一个表征我们的经验惩罚转换率的分布:也就是说,(1)它在一个从 0 到 1 的范围内(没有负概率),(2)它需要灵活,在某种意义上,它可以代表我们在直方图中看到的东西,以及(3)如果当我们结合二项式分布的可能性时,它使我们的贝叶斯计算更容易——二项式分布描述了在试验中的成功次数(即:许多点球中的进球数),那就更好了。

瞧吧, 贝塔分布

贝塔分布在域[0,1]上,所以我们知道它不会比平坦先验差。它在域内高度灵活,其特征在于两个正的形状参数,分别用 αβ 表示(见上图)。

关于贝塔分布最好的部分是,它是二项分布的的共轭先验,这对我们的计算是个奇迹。我们可以从贝塔分布 B(α,β) 作为我们的先验开始,用来自二项分布的信息更新,其中sf失败(未命中),并且得到后验分布,其也是精确形式的贝塔分布* B(α + s,β + f) 这种分布的平均值是***【α+s)/(α+β+s+f)******

简直神奇!!!

我在这篇文章的结尾加入了一些数学知识,以防你不相信!

让我们继续寻找我们最好的点球手:

估计我们实际数据的先验:

现在我们已经有了一个清晰的分析框架,是时候将它应用到我们的真实数据集了。

首先,让我们对转化率数据集进行贝塔分布拟合。这可以很简单地用 r 来完成

用这个方法,我得到一个估计值 α = 9.29β = 2.93。让我们看看这个估计与我们的数据有多吻合。

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

显然,它并不完美,但我们现在可以继续努力。

使用我们的经验先验更新每个玩家的统计数据:

**我们现在可以继续,用我提到的公式找到每个玩家转换率的后验分布。即aβ分布形式 ***B(α + s,β+f)*其中 sf 分别是成功和失败的次数。后验均值将为 (α + s)/ (α + β +s+ f)。

例如,c 罗和佩佩的点球转换率的后验分布均值将为:

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

我们可以将他们的后验概率分布(与其他玩家一起)绘制如下:

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

The posterior distribution of penalty conversion rate for a few players

我们可以看到,罗纳尔多的强劲记录导致非常高的后验均值和狭窄的可信区间,而佩佩的后验均值转换具有更大的可信区间,因为他的数据较少。与此同时,格里兹曼和桑切斯在点球方面并不出色。

十佳点球手:

在应用了经验贝叶斯估计和贝塔二项式后验计算之后,让我来介绍一下过去 13 年里的前 10 名受罚者。

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

所以事实证明,最佳点球手是萨利霍维奇和罗西,紧随其后的是布代布、马克·诺布尔和莱万多夫斯基。著名的点球手:兰帕德,杰拉德,哈里·基恩并不像他们声称的那么好。有趣的是,我们可以看到,对于这些玩家来说,在我们应用这个程序后,他们的转化率缩小了。我们可以将原始比率和调整后的比率绘制在图上,以评估调整情况。这一部分的灵感来自大卫·罗宾逊的一篇了不起的文章[2]。

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

Plot of actual vs adjusted conversion ratios

水平虚线显示了先验分布的平均值——如果我们没有关于玩家的任何信息,我们应该猜测玩家的成功率。然后,我们有了对角线 y = x ,显示实际进球得分平均值等于后验调整的数据点。

有两个有趣的观察。首先,我们可以看到,高于先前均值的点往往会缩小,而低于均值的点会向上膨胀。第二,受收缩影响最小的点是与大量观测相关联的点。当你思考时,这是完全有意义的:如果我们通过观察有很多证据,我们可以依靠实际的估计;否则,相信我们的数据趋向于总体均值是很有价值的。

结论:

好了,我刚刚介绍了经验贝叶斯估计的概念:我们可以利用我们数据的总体分布作为先验,以获得每个平均值的更现实的估计。然后,我们使用共轭先验的强大概念来绕过在我们的过程中计算后验分布的复杂性。贝塔-二项式组合如此受欢迎,以至于你可以把它应用到许多场景中:篮球、点击进入的 A/B 测试、学校食堂评级等等。

出于本文的目的,我方便地忽略了许多复杂性。首先,我们可以看出,我们先验的 beta 分布几乎不太适合。事实上,我们可以用两个 Beta 分布来拟合双峰分布,根据玩家属于每个分布的可能性,将他们分配到两个不同的组中。

你可以查看我解决这个问题的代码

另一个复杂因素是,罚分转换率随着时间的推移而变化,并且在不同的联赛中有所不同。就我们考虑所有这些不同的因素而言,我们从简单的贝塔-二项式分布走了许多步,进入了 贝叶斯分层模型 的领域。这就是乐趣的开始!!!

附录:

本文的代码和更多内容可以在这里找到。

这是β-二项式共轭配对的一个简短证明。

设置很简单:我们观察一些成功计数 s ,我们认为它们遵循样本大小为 n 的二项式分布,成功率为我们的工作是找到给定 sr 的后验分布。

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

该是我们调用著名的贝叶斯公式的时候了——只针对连续变量:

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

似然函数 p(s|r) 和先验 遵循明确定义的二项式和贝塔分布。

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

然后,我们的工作就是插入并找到后验分布。

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

结果是一种β分布形式 B(α + s,β + f)

[1]统计视图。(2015 年 6 月 1 日)。经验贝叶斯对我来说是最吸引人的话题。有时它仍然像魔法一样:布拉德利·埃夫隆访谈。

[2]罗宾逊,D. (2015 年 10 月 1 日)。理解经验贝叶斯估计(使用棒球统计)*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值