TowardsDataScience-博客中文翻译-2020-八十三-

龙哥盟 / 2024-10-14 / 原文

TowardsDataScience 博客中文翻译 2020(八十三)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

基于 Keras 的医学图像分割:U-net 架构

原文:https://towardsdatascience.com/medical-images-segmentation-using-keras-7dc3be5a8524?source=collection_archive---------9-----------------------

了解如何构建肝脏分割算法。包括数据预处理、建模和结果可视化的教程。

Olga Guryanova 在 Unsplash 上的照片

[## soribadiaby/深度学习肝脏分割

目的:目的是通过计算机视觉在病人扫描图像上自动描绘肝脏。使用的方法是…

github.com](https://github.com/soribadiaby/Deep-Learning-liver-segmentation)

介绍

医学图像分割是自动或半自动检测 2D 或 3D 图像内边界的过程

医学图像的分割长期以来一直是一个活跃的研究课题,因为人工智能可以帮助对抗许多疾病,如癌症。自动、精确和快速地执行这项任务将有助于专家的工作,并且能够用可靠的方法更好地治疗病人。

在这篇文章中,我们将看到如何在实际的病人扫描数据集上使用 U-net 架构自动分割肝脏。希望你会喜欢它。

数据

此处提供 NifTi 格式的数据。NifTi(神经成像信息学技术倡议)是一种开放的文件格式,通常用于存储使用磁共振成像方法获得的脑成像数据。有一个叫做 nibabel 的 Python 包,我们将用它来处理这种数据。

我们将使用的数据集由 20 个 3D 医学检查组成,它包含源图像以及每个图像的肝脏分割模板。这些数据来自法国的 IRCAD 医学研究中心。

来源: ircad

为了执行我们的任务,我们显然不会只使用 20 个数据(这在深度学习中真的很少)。为了增加我们的数据,我们将使用轴向二维切片。

模型

我们将训练一个 U-net 架构,一个完全卷积的网络。这种体系结构的原理是在通常的收缩网络层中添加上采样操作符,而不是池。

这允许网络学习上下文(收缩路径),然后学习定位(扩展路径)。由于跳过连接,上下文信息被传播到更高分辨率的层。所以我们有和输入一样大小的图像:

U-net 架构

公制的

作为度量,我们使用骰子系数(与 Jaccard 系数非常相似)。它是衡量两个样本相似性的统计指标:

骰子系数公式

设置交集

在这个图中我们可以清楚地看到:如果 dice 系数等于 1,就表示我们比较的两个样本完全相等!所以越接近 1 越好。

现在我们已经建立了框架,我们可以开始项目了。

项目结构

在您的项目文件夹中创建一个“原始”文件夹:

项目结构

在“原始”文件夹中,创建一个“测试”文件夹和一个“训练”文件夹。

然后将数据分成两组(训练和测试,通常我们对训练集使用 13 个样本,对测试集使用 7 个样本),并将它们放在相应的目录中。

我们将在最后两部分看到“data.py”和“train.ipynb”中写什么。

数据预处理

预处理部分在深度学习任务中至关重要,因为神经网络需要某种格式的数据。

在这一部分中,我将向您展示将数据转换为 numpy 数组的 python 代码,我们将把这些数组提供给神经网络。为此,我们将把三维数据转换成二维数据。然后把他们救进来”。npy”格式,以便在进一步的培训中使用。

data.py

现在我们已经准备好了数据,让我们进入最后一步:培训!

用 Keras 训练神经网络

在这一部分中,我将向您展示设置架构、训练神经网络并将结果存储在文件中的笔记本(代码灵感来自这个回购),请不要犹豫参考注释以了解代码:

train.ipynb

多亏了“mark_boundaries”函数,我们将能够看到带有黄色标记的分割结果。

结果

终于有结果了!我们的工作得到了回报,这些曲线代表了 20 个时期的训练和测试骰子系数。测试的骰子系数几乎达到了 0.87,这是相当令人满意的。

骰子在时代上的系数

你会在“preds”目录中看到这种代表 2D 切割的结果。用黄色标出的是由算法预测的肝脏:

分割结果

我们现在可以在几秒钟内分割数千次扫描!一项需要专家花费更长时间的任务。

结论

最后,我们使用骰子系数几乎达到 0.87 的 U-net 架构成功地训练了我们的神经网络!

改进轨迹:

  • 通过堆叠二维分割图像来重建三维扫描。
  • 通过沿几个斜轴制作二维切片,将数据放大更多

希望这篇文章对你有用。感谢阅读。

医学文本分析技术及其应用

原文:https://towardsdatascience.com/medical-text-analytic-techniques-and-its-applications-c7419c7c1f6?source=collection_archive---------25-----------------------

国立癌症研究所在 Unsplash 上的原始照片

介绍

医疗保健行业的技术进步帮助我们生成了越来越多的数据,据估计,2020 年生成的全球医疗保健数据为 2,314 艾字节,比 153 艾字节的 153 艾字节有所增加[1]。这些数据来自多个来源,如 EHR(电子健康记录)、临床研究、患者的物联网(IoT)、门诊患者的医疗记录、患者的远程医疗记录和聊天记录。这些数据的很大一部分采用非结构化叙述文本的形式,描述了医疗程序,如临床记录、出院总结、临床监测表或放射报告[2]。

这些非结构化的叙述性文本由为患者提供护理的医生、护士、药剂师和工作人员编写,并提供超出传统出院总结的更多细节。这些笔记是在护理过程中生成的,并拥有详细信息,如患者病情的进展、护理计划、医疗和家族史,以及许多其他临床属性。

随着这些类型的数据量的增加,使得计算机系统难以以可用的格式分析数据,并且消耗了医疗专业人员的时间来从中提取有价值的信息,因此,这些信息的自动分析的出现对于医疗专业人员来说是至关重要的,以便改善患者的临床结果并降低医院的运营成本。此类工作的例子包括医院再入院的预测、高危患者不良反应的识别以及个性化疾病风险预测的创建[3]

这些非结构化文本的自动分析可以在医学文本分析技术的帮助下完成。文本分析是检查大量文档以从文档中发现新信息或知识的过程,它识别医疗记录中的事实、关系和断言,并将其转换为结构化形式,该形式可以进一步集成到数据库、数据仓库或商业智能仪表板中,并由医疗专业人员用于描述性、规定性或预测性分析。

一、命名实体识别(NER)

医学命名实体识别(NER)是指自动识别不同文本数据块中的医学术语的任务[5],它主要用于从临床笔记中提取重要的实体类别,如临床发现、程序和药物名称及其剂量[6]。NER 通常是一个两阶段的过程,其中第一阶段包括检测和确定文本中的实体,第二阶段包括选择和提取实体。[8]NER 在医疗领域的应用示例包括从以不同语言编写的临床报告中提取医疗概念,发现与时间表达、个人数据匿名化相关的概念,以及最后分析医疗实体之间关系的提取[7]。

作者图片

二。假设生成和知识发现

自然语言处理经常被用来发现文本数据中新的假设和隐藏的知识。它为医疗保健专业人员提供了重要的见解,可用于他们的日常实践和研究工作。这项技术有助于检测患者的风险因素、症状和危急事件,并有助于卫生专业人员做出决策。这种技术的示例应用是从科学文章和基于健康的网络社交媒体的内容中检测和识别不良药物事件(ADE)[9],通过病历文本对转移性前列腺癌患者的不同疼痛进行分类和研究[10]。

来源:[10]使用医疗记录文本的自然语言处理对转移性前列腺癌患者的疼痛进行纵向分析

三世。文本摘要

自动摘要是指一个或多个文档的主要主题被识别并简明准确地呈现的过程。[4]这允许医疗保健专业人员以摘要短文本的形式获得诸如 EHR 临床记录、入院记录等文件的要点,因此减少了时间量,提高了生产率,并使其对分析大量信息时出现的主观性不太敏感。应用示例包括摘要系统,该系统允许从医学新闻文章中自动生成摘要[11]以及通过从与支持临床医生信息需求相关的研究论文摘要中提取句子来对临床信息进行摘要[12]。

来源:使用 BART 模型的 COVID 研究论文摘要

四。文本分类

文本分类是指从海量数据中发现文本并将其分类的自动过程,它在文本数据检索和挖掘中起着至关重要的作用。[13]健康相关文本的分类被认为是文本分类的更具挑战性的情况,因为医学文本通常包含标准化的医学术语,其指的是医学领域中的一些概念或缩写,例如血压 140/65。除此之外,病历中经常有语法不好的句子。[14]文本分类的示例应用包括临床警报或风险因素分类、自动诊断分类、患者分层、不良事件分类、电子健康记录分类、症状学分类、通过意见和情感分析挖掘的健康挖掘器[4]

图 5:病历中 ICD-10 疾病的自动编码。作者图片

结论:

随着医疗保健向 EHR 的转移,医学文本分析的前景一片光明。医学文本分析的不断进步为患者提供了更好的护理质量,降低了医院和全国范围内的医疗保健成本,最后为患者提供了更多的医疗保健可及性。卫生保健专业人员和卫生政策制定者必须了解这项技术提供的好处,并制定一个坚实的计划将这项技术纳入日常实践。本文介绍了医学领域中不同类型的文本分析术语数据集,随着资源的丰富,医学专业人员和健康信息学可以利用这些现有的资源,开始以低得多的成本在他们的实践中实施医学文本挖掘。

最后,将新的实践或技术融入医疗保健行业不是一项简单的任务,尤其是当这个行业涉及到患者的生命和隐私时,必须克服许多挑战,例如现有设施的准备、法律和伦理、患者隐私以及更高管理层的支持。作者希望医疗行业能够克服这些挑战,因为这项技术可以帮助无数的生命,节省大量的金钱。

感谢您的阅读!

参考文献:

[1] M. Zwolenski 和 L. Weatherill,“数字宇宙丰富的数据和物联网不断增加的价值”,《澳大利亚电信和数字经济杂志》,2014 年第 2 卷第 3 期。

[2] K. Feldman,N. Hazekamp,N. V. Chawla,“挖掘临床叙事:所有文本不相等”,2016 年 IEEE 医疗保健信息学国际会议(ICHI),2016。

[3]穆尼奥斯,伊莎贝尔&赞布拉纳,玛丽亚·罗萨里奥。(2013).将本体论应用于术语:优势与劣势。赫尔墨斯:商业语言与交流杂志。51.65–77.10.7146/hjlcb.v26i51.97438

【4】“什么是文本挖掘、文本分析和自然语言处理?”语言学,2020 年 8 月 14 日。【在线】。可用:https://www . linguamatics . com/what-text-mining-text-analytics-and natural-language-processing。 【访问时间:2020 年 11 月 13 日】。

[5] M. S. Simpson 和 D. Demner-Fushman,“生物医学文本挖掘:近期进展调查”,挖掘文本数据,第 465–517 页,2012 年。

[6] P. Corbett 和 A. Copestake,“基于置信度的化学命名实体识别的级联分类器”,BMC 生物信息学,第 9 卷,第 S11 期,2008 年。

【7】卢克,卡门&卢娜,何塞·玛丽亚&卢克,玛丽亚&文图拉,塞巴斯蒂安。(2018).医学文本挖掘的研究进展。威利跨学科评论:数据挖掘和知识发现。9.10.1002/widm.1302

[8] G. Popovski,S. Kochev,B. Seljak,T. Eftimov,“FoodIE:一种基于规则的食品信息提取命名实体识别方法”,第八届模式识别应用与方法国际会议论文集,2019。

【9】taf ti AP,Badger J,LaRose E,Shirzadi E,Mahnke A,Mayer J,Ye Z,Page D,Peissig P (2017)利用生物医学文献发现药物不良事件:一次大数据神经网络冒险。JMIR 医学信息学 5(4)

[10] N. H. Heintzelman、R. J. Taylor、L. Simonsen、R. Lustig、D. Anderko、J. A. Haythornthwaite、L. C. Childs 和 G. S. Bova,“使用病历文本的自然语言处理对转移性前列腺癌患者的疼痛进行纵向分析”,《美国医学信息学协会杂志》,第 20 卷,第 5 期,第 898–905 页,2013 年。

【11】萨卡尔,卡迈勒。(2009).利用领域知识进行医学领域的文本摘要。国际工程趋势杂志。1.

[12] S. R. Jonnalagadda,G. D. Fiol,R. Medlin,C. Weir,M. Fiszman,J. Mostafa,H. Liu,“从 Medline 引文中自动提取句子以支持临床医生的信息需求”,《美国医学信息学协会杂志》,第 20 卷,第 5 期,第 995–1000 页,2013 年。

[13]f . Sebastiani,“自动文本分类中的机器学习”,ACM 计算调查,第 34 卷,第 1 期,第 1–47 页,2002 年。

[14] L. Qing,w .,d .雪海,“一种新的基于神经网络的医学文本分类方法”,《未来互联网》,第 11 卷第 12 期,第 255 页,2019。[15]马尼伊卡、楚伊、布朗、布欣

基于卷积神经网络的医学 x 射线⚕️图像分类

原文:https://towardsdatascience.com/medical-x-ray-️-image-classification-using-convolutional-neural-network-9a6d33b1c2a?source=collection_archive---------1-----------------------

从无到有构建 x 线肺炎检测的 CNN 模型

图片来自维基媒体

在本文中,我们将创建一个 CNN 模型,它可以将 X 射线图像分类为肺炎病例或正常病例。

web 应用已经部署到 streamlit share:https://share . streamlit . io/smarthardk 10/Xray-classifier/main/web app . py

目录

  1. 数据集
  2. 初始化
  3. 准备数据
  • 3.1 数据扩充
  • 3.2 加载图像

4.卷积神经网络

  • 4.1 必要的进口
  • 4.2 CNN 架构
  • 4.3 拟合模型

5.评价

1 数据集

我们将用于图像分类的数据集是胸部 X 射线图像,它包括两个类别,肺炎和正常。这个数据集由 Paulo Breviglieri 发布,是 Paul Mooney 最受欢迎的数据集的修订版。数据集的这个更新版本在验证集和测试集中具有更平衡的图像分布。数据集被组织成 3 个文件夹(train、test、val ),并包含每个图像类别不透明度(即&正常肺炎)。

总观察值(图像):5856
训练观察值:4192(正常 1082 例,肺部阴影 3110 例)
验证观察值:1040(正常 267 例,肺部阴影 773 例)
测试观察值:624(正常 234 例,肺部阴影 390 例)

首先,我们将使用 Kaggle API 直接从 Kaggle 中提取数据集。为此,我们需要创建一个 API 令牌,它位于 Kaggle API 选项卡下的 Account 部分。点击“创建一个新的 API 令牌”,一个 json 文件将被下载。
运行下面几行代码来安装所需的库并上传 json 文件。

! pip install -q kaggle
from google.colab import files
files.upload()
! mkdir ~/.kaggle
! cp kaggle.json ~/.kaggle/
! chmod 600 ~/.kaggle/kaggle.json

当提示“选择文件”时,上传下载的 json 文件。运行下一行代码将下载数据集。要获得数据集 API 命令来下载数据集,单击 Kaggle 数据集页面的数据部分中的 3 个点,然后单击“复制 API 命令”按钮并用!将其粘贴

! kaggle datasets download -d pcbreviglieri/pneumonia-xray-images

因为我使用 Google Colab 来运行这个项目,所以数据集 zip 文件被下载到 Sample Data 文件夹中。现在,通过运行下面几行代码,我们使用 zipfile 库将文件夹和文件解压缩到所需的目标文件夹。

import zipfilezf = "/content/pneumonia-xray-images.zip"
target_dir = "/content/dataset/cnn/pneumonia_revamped"zfile = zipfile.ZipFile(zf)
zfile.extractall(target_dir)

现在我们的数据集已经准备好了,让我们开始吧!

Gif via GIPHY

2 初始化

让我们看看我们的数据集目录树。

content
└───dataset
    └───cnn
        └───pneumonia_revamped
            ├───test
            │   ├───Normal
            │   │   ├───image1.jpg
            │   │   └───image2.jpg
            │   └───Opacity
            │       ├───image1.jpg
            │       └───image2.jpg
            ├───train
            │   ├───Normal
            │   │   ├───image1.jpg
            │   │   └───image2.jpg
            │   └───Opacity
            │       ├───image1.jpg
            │       └───image2.jpg
            └───val
                ├───Normal
                │   ├───image1.jpg
                │   └───image2.jpg
                └───Opacity
                    ├───image1.jpg
                    └───image2.jpg

在这部分代码中,我们将定义目录路径,导入一些需要的库,并定义一些我们将在项目的后面部分经常使用的公共常量参数。

#Some Basic Importsimport matplotlib.pyplot as plt #For Visualization
import numpy as np              #For handling arrays
import pandas as pd             # For handling data#Define Directories for train, test & Validation Set
train_path = '/content/dataset/cnn/pneumonia_revamped/train'
test_path = '/content/dataset/cnn/pneumonia_revamped/test'
valid_path = '/content/dataset/cnn/pneumonia_revamped/val'#Define some often used standard parameters
#The batch refers to the number of training examples utilized in one #iteration
batch_size = 16 #The dimension of the images we are going to define is 500x500 img_height = 500
img_width = 500The dimension size of 500 or more than 500 with batch size greater than 16 may result in a crash as the RAM gets completely used in such cases. A lower dimension size with greater batch size is one of the options to try.

3 准备数据

3.1 数据扩充

我们将通过执行一些图像增强技术来人为地增加图像训练数据集的大小。

图像增强通过创建现有训练集图像的修改版本来扩展数据集的大小,这有助于增加数据集变化并最终提高模型预测新图像的能力。

from tensorflow.keras.preprocessing.image import ImageDataGenerator# Create Image Data Generator for Train Set
image_gen = ImageDataGenerator(
                                  rescale = 1./255,
                                  shear_range = 0.2,
                                  zoom_range = 0.2,
                                  horizontal_flip = True,          
                               )# Create Image Data Generator for Test/Validation Set
test_data_gen = ImageDataGenerator(rescale = 1./255)

Gif via GIPHY

使用tensorflow.keras.preprocessing.image库,对于训练集,我们创建了一个图像数据生成器,它将定义的参数随机应用于训练集,对于测试&验证集,我们将重新调整它们,以避免事先操纵测试数据。

定义一些图像数据发生器参数:-

  1. rescale—每个数字图像由一个值在 0 到 255 之间的像素创建。黑色为 0,白色为 255。因此,重新调整原始图像像素值的比例数组,使其介于[0,1]之间,这使得图像对整体损失的贡献更加均等。否则,更高像素范围的图像导致更大的损失,并且应该使用更低的学习率,更低像素范围的图像将需要更高的学习率。
  2. shear_range —图像的形状是剪切的变换。它固定一个轴,并以某个角度拉伸图像,该角度称为剪切角。
  3. zoom_range —图像以小于 1.0 的倍率放大。图片缩小了 1.0 倍以上。
  4. horizontal_flip—一些图像被随机水平翻转
  5. vertical_flip —一些图像随机垂直翻转
  6. roataion_range —随机地,图像在 0°到 180°范围内旋转一定角度。
  7. width_shift_range —水平移动图像。
  8. height_shift_range —垂直移动图像。
  9. brightness_range —亮度 0.0 对应绝对无亮度,1.0 对应最大亮度
  10. fill_mode —将图像中缺少的值填充到最接近的值、包裹值或反射值。

除了重新缩放之外,这些变换技术被随机应用于图像。所有图像已被重新缩放。

3.2 加载图像

图像数据生成器有一个名为 flow from directory 的类,用于从包含图像的文件夹中读取图像。返回目录操作符类型tensorflow.python.keras.preprocessing.image.DirectoryIterator

train = image_gen.flow_from_directory(
      train_path,
      target_size=(img_height, img_width),
      color_mode='grayscale',
      class_mode='binary',
      batch_size=batch_size
      )test = test_data_gen.flow_from_directory(
      test_path,
      target_size=(img_height, img_width),
      color_mode='grayscale',
      shuffle=False, 
#setting shuffle as False just so we can later compare it with predicted values without having indexing problem 
      class_mode='binary',
      batch_size=batch_size
      )valid = test_data_gen.flow_from_directory(
      valid_path,
      target_size=(img_height, img_width),
      color_mode='grayscale',
      class_mode='binary', 
      batch_size=batch_size
      )

Found 4192 images belonging to 2 classes. Found 624 images belonging to 2 classes. Found 1040 images belonging to 2 classes.

它接受的一些参数定义如下:-

  1. directory —使用的第一个参数是我们之前定义的 train,test &验证文件夹的路径。
  2. target_size —目标尺寸是您的输入图像的尺寸,每个图像将被调整到这个尺寸。我们之前已经将目标尺寸定义为 500 x 500。
  3. color_mode—如果图像是黑白或灰度设置为“灰度”,或者如果图像有三个颜色通道设置为“rgb”我们将使用灰度,因为这是 x 光图像。
  4. batch_size —生成器批量生成的图像数量。我们之前将批量定义为 16。我们选择 16,因为图像的大小太大,无法处理 RAM。
  5. class_mode —如果您只有两个类别要预测,则设置“二进制”,如果您没有设置为“分类”,如果您开发了一个自动编码器系统,则输入和输出很可能是同一个图像,在这种情况下设置为“输入”。这里我们将它设置为二进制,因为我们只有 2 个类要预测。

让我们看看我们从数据扩充中获得的一些列车组图像

Gif via GIPHY

plt.figure(figsize=(12, 12))
for i in range(0, 10):
    plt.subplot(2, 5, i+1)
    for X_batch, Y_batch in train:
        image = X_batch[0]        
        dic = {0:’NORMAL’, 1:’PNEUMONIA’}
        plt.title(dic.get(Y_batch[0]))
        plt.axis(’off’)
        plt.imshow(np.squeeze(image),cmap=’gray’,interpolation=’nearest’)
        break
plt.tight_layout()
plt.show()

查看列车组的一些图像

Gif via GIPHY

嗯,我不能仅仅通过看这些图片来判断哪一个是肺炎病例,哪一个是正常病例。为此,我需要一个放射学学士学位,需要 2 到 4 年时间,仅第一年就要花费 466 万卢比。 好吧,不要担心,作为一个数据科学从业者,你可以教计算机分辨它们之间的区别。 我们有希望在这方面达到很高的精确度,否则就是放射科医师的学位了。

4 卷积神经网络

CNN 架构的例子由维基媒体

用一句话告诉我什么是 CNN—它是一种人工神经网络,能够在图像中定位或检测模式。

最大共享示例由维基媒体

解释 CNN 架构内部的情况— CNN CNN 架构基于多层卷积。卷积层接收输入并转换图像中的数据,然后将其作为输入传递给下一层。这种变换称为卷积运算。我们需要为每个卷积层定义过滤器的数量。这些滤镜检测边缘、形状、曲线、对象、纹理甚至颜色等图案。它检测到的更复杂的图案或物体的层次更深。本质上,滤镜是图像内核,我们可以定义为 3×3 或 4×4,这是一个应用于图像整体的小矩阵。我们将池层与卷积层一起使用,目标是对输入表示(图像)进行下采样,通过保留子区域绑定中的最大值(激活的特征)来降低其维数。在输入矩阵中移动的像素数量称为步幅。当步幅为 1 时,我们一次将过滤器移动 1 个像素。当步幅为 2 时,我们将过滤器一次移动 2 个像素,依此类推。较大的过滤器尺寸和跨度可用于将大图像的尺寸减小到中等尺寸。

GIPHY 的卷积运算示例

好吧,如果你讨厌数学,所有这些复杂的数学运算都是在幕后进行的,我们需要做的就是定义超参数和层。如果你热爱数学并想了解这些数学运算是如何工作的,你可以参考参考资料部分的链接。

YT 上有一个很棒的视频,他们试图创建人类神经网络。

锁定并加载我们开始创建的 CNN 架构。

Gif via GIPHY

4.1 必要进口

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,Conv2D,Flatten,MaxPooling2D
from tensorflow.keras.callbacks import EarlyStopping,ReduceLROnPlateau

4.2 CNN 架构

开始构建 CNN 模型之前需要注意的事项:-

  1. 总是从一个较低的过滤值开始,如 32,然后逐层增加。
  2. 用 Conv2D 层和 MaxPooling 层构建模型。
  3. 内核大小最好是奇数,如 3×3。
  4. Tanh,relu 等。可用于激活功能,但 relu 是最优选的激活功能。
  5. input_shape取最后一个尺寸的图像宽度&高度作为颜色通道。
  6. 在 CNN 层和添加 ANN 层之后平坦化输入。
  7. 如果问题超过 2 类,则使用激活函数作为最后一层的 softmax,将单位定义为类的总数,并使用 sigmoid 进行二进制分类,并将单位设置为 1。

注意:-您可以随时试验这些超参数,因为没有我们可以确定的固定值。

cnn = Sequential()cnn.add(Conv2D(32, (3, 3), activation="relu", input_shape=(img_width, img_height, 1)))
cnn.add(MaxPooling2D(pool_size = (2, 2)))cnn.add(Conv2D(32, (3, 3), activation="relu", input_shape=(img_width, img_height, 1)))
cnn.add(MaxPooling2D(pool_size = (2, 2)))cnn.add(Conv2D(32, (3, 3), activation="relu", input_shape=(img_width, img_height, 1)))
cnn.add(MaxPooling2D(pool_size = (2, 2)))cnn.add(Conv2D(64, (3, 3), activation="relu", input_shape=(img_width, img_height, 1)))
cnn.add(MaxPooling2D(pool_size = (2, 2)))cnn.add(Conv2D(64, (3, 3), activation="relu", input_shape=(img_width, img_height, 1)))
cnn.add(MaxPooling2D(pool_size = (2, 2)))cnn.add(Flatten())cnn.add(Dense(activation = 'relu', units = 128))
cnn.add(Dense(activation = 'relu', units = 64))
cnn.add(Dense(activation = 'sigmoid', units = 1))cnn.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])

现在我们已经开发了 CNN 模型,让我们深入看看这里发生了什么。

cnn.summary() Model: "sequential_1" _________________________________________________________________ Layer (type)                 Output Shape              Param #    ================================================================= conv2d_3 (Conv2D)            (None, 498, 498, 32)      320        _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (None, 249, 249, 32)      0          _________________________________________________________________ conv2d_4 (Conv2D)            (None, 247, 247, 32)      9248       _________________________________________________________________ max_pooling2d_4 (MaxPooling2 (None, 123, 123, 32)      0          _________________________________________________________________ conv2d_5 (Conv2D)            (None, 121, 121, 32)      9248       _________________________________________________________________ max_pooling2d_5 (MaxPooling2 (None, 60, 60, 32)        0          _________________________________________________________________ conv2d_6 (Conv2D)            (None, 58, 58, 64)        18496      _________________________________________________________________ max_pooling2d_6 (MaxPooling2 (None, 29, 29, 64)        0          _________________________________________________________________ conv2d_7 (Conv2D)            (None, 27, 27, 64)        36928      _________________________________________________________________ max_pooling2d_7 (MaxPooling2 (None, 13, 13, 64)        0          _________________________________________________________________ flatten_1 (Flatten)          (None, 10816)             0          _________________________________________________________________ dense_2 (Dense)              (None, 128)               1384576    _________________________________________________________________ dense_3 (Dense)              (None, 64)                8256       _________________________________________________________________ dense_4 (Dense)              (None, 1)                 65         ================================================================= Total params: 1,467,137 Trainable params: 1,467,137 Non-trainable params: 0 _________________________________________________________________

口译模式总结

# Hyperparameters of Conv2D
Conv2D(
    filters,
    kernel_size,
    strides=(1, 1),
    padding="valid",
    activation=None,
    input_shape=(height,width,color channel)
    )# Hyperparameters of MaxPooling2D 
MaxPooling2D(
    pool_size=(2, 2), strides=None, padding="valid"
    )

图像的输入形状是我们之前定义的高度&宽度(500,500,1)。并且1代表颜色通道,因为图像是灰度的,所以它的颜色通道是 1,对于 rgb 图像是 3。

(none,500,500,1)在这里,Keras 增加了一个额外的维度none,因为批量大小可以变化。

在第一个Conv2d层卷积操作中,对(500,500)的图像使用(3,3)内核大小,步长和膨胀默认设置为 1,填充设置为“有效”,它输出(500-3+1 , 500-3+1 ) = (498,498)的输出大小,我们定义的过滤器数量为 32,输出形状现在为(None,498,498,32)

现在,在第一个 Max Pooling 层中,我们已经将内核大小定义为(2,2),默认情况下,(2,2)会将其应用到图像大小的输入中,我们得到的是((498–2//2)+1,(498–2//2)+1))= (249,249)

展平层采用所有通道上的所有像素,并创建一个 1D 矢量,而不考虑批次大小。因此,(13, 13, 64)的输入被拉平为(13*13*64) = 10816的值。

参数值由第一层的(3*3*1*32)+(32) = 320给出的(kernel_height * kernel_width * input_channels * output_channels) + (output_channels)计算。

整流线性激活函数或短期 ReLU 是分段线性函数,如果为正,则直接输出输入,否则输出零。校正的线性激活函数克服了消失梯度的问题,允许模型更快地学习和更好地执行。

填充— "SAME":输出尺寸与输入尺寸相同。这要求滤波器窗口滑动到输入映射之外,因此需要填充。"VALID":滤波窗口停留在输入图内的有效位置,输出尺寸缩小filter_size - 1。不会出现填充。

激活函数-简单地说,激活是一种添加到人工神经网络中的函数,用于帮助网络学习数据中的复杂模式。当与我们大脑中基于神经元的模型进行比较时,激活功能在一天结束时决定对下一个神经元做什么。由于分类在两个类之间,我们将对最后一层使用 sigmoid 激活函数,该函数返回值在 0 到 1 的范围内。对于 2 个以上的类,我们可以使用 softmax 激活功能。

定义模型编译

  • 学习率——训练时,随机梯度下降的目标是最小化训练集的实际值和预测值之间的损失。减少损失的途径需要几个步骤。Adam 是一种自适应学习率方法,这意味着它计算不同参数的个人学习率。
  • 损失函数-由于这是一个二元分类,我们将在训练期间使用二元交叉熵来评估损失。如果有 4 个以上的类,我们会选择分类交叉熵。
  • 度量—准确性—计算实际标签与预测值相等的频率。它将测量训练和验证的损失和准确性。

可视化 CNN 模型

from tensorflow.keras.utils import plot_modelplot_model(cnn,show_shapes=True, show_layer_names=True, rankdir='TB', expand_nested=True)

绘制 CNN 架构

4.3 拟合模型

定义回调列表

根据一些度量标准(monitor)和条件(mode, patience)调用EarlyStopping来停止历元。这有助于避免过度拟合模型。在这里,我们告诉停止基于val_loss指标,我们需要它是最小的。patience表示在达到最小 val_loss 之后,在接下来的迭代中,如果 val_loss 在 3 次迭代中的任何一次中增加,则训练将在该时期停止。

当指标停止改善时,降低学习率。一旦学习停滞,模型通常会受益于将学习速度降低 2-10 倍。这种回调监控一个数量,如果在“耐心”次数内没有看到改进,则学习率降低。来源

early = EarlyStopping(monitor=”val_loss”, mode=”min”, patience=3)learning_rate_reduction = ReduceLROnPlateau(monitor=’val_loss’, patience = 2, verbose=1,factor=0.3, min_lr=0.000001)callbacks_list = [ early, learning_rate_reduction]

分配类别权重

为每个类分配类权重是一种很好的做法。它强调少数类的权重,以便模型能够平等地从所有类中学习。

from sklearn.utils.class_weight import compute_class_weight
weights = compute_class_weight('balanced', np.unique(train.classes), train.classes)
cw = dict(zip( np.unique(train.classes), weights))
print(cw)

{0: 1.9371534195933457, 1: 0.6739549839228296}

现在一切都准备好了,进入最后一步训练💪

Gif via GIPHY

我们传递给 model.fit 的参数是训练集、epochs as 25、用于计算 val_loss 和 val_accuracy 的验证集、类权重和回调列表。

cnn.fit(train,epochs=25, validation_data=valid, class_weight=cw, callbacks=callbacks_list)

训练模型

看起来早期停止在 val_loss =14.9%和 val_accuracy = 94.6%的第 10 个历元停止。

5 评估

让我们直观地看到所有指标在整个时期生命周期中的进展

pd.DataFrame(cnn.history.history).plot()

绘制度量进度

我们在测试数据集上获得的准确率是 91%

test_accu = cnn.evaluate(test)print('The testing accuracy is :',test_accu[1]*100, '%')

39/39 [==============================] — 50s 1s/step — loss: 0.3132 — accuracy: 0.9119 The testing accuracy is : 91.18589758872986 %

让我们预测测试数据集,并详细查看一些性能测量指标来评估我们的模型。

preds = cnn.predict(test,verbose=1)

39/39 [==============================] — 46s 1s/step

因为最后一层的激活函数是 sigmoid,所以该模型给出 0 到 1 范围内的预测,而不是 0 或 1 的精确分类。因此,我们将 0.5 到 1 范围内的所有值分类为 0,将小于 0.5 的值分类为 1。注(0 表示正常情况,1 表示肺炎情况)

predictions = preds.copy()
predictions[predictions <= 0.5] = 0
predictions[predictions > 0.5] = 1

混淆矩阵

混乱矩阵的例子由维基媒体

让我们来解释混淆矩阵的输出。左上(TP)表示被正确预测为正常病例的图像数量,右下(TN)表示被正确预测为肺炎病例的图像数量。作为肺炎病例,右上表示不正确预测但实际上是正常病例的图像的数量,左下表示不正确预测但实际上是肺炎病例的正常病例图像的数量。

Gif via GIPHY

??还在困惑困惑矩阵??

解释二元或多类分类的混淆矩阵的简单方法是查看我们是否在从左到右的对角线像元中获得最大值,在其余像元中获得最小值。

from sklearn.metrics import classification_report,confusion_matrix
cm = pd.DataFrame(data=confusion_matrix(test.classes, predictions, labels=[0, 1]),index=["Actual Normal", "Actual Pneumonia"],
columns=["Predicted Normal", "Predicted Pneumonia"])import seaborn as sns
sns.heatmap(cm,annot=True,fmt="d")

混淆矩阵

分类报告

  • 精度=真阳性/(真阳性+假阳性)
  • 回忆=真阳性/(真阳性+假阴性)
  • F1 = (2 精度召回)/(精度+召回)
print(classification_report(y_true=test.classes,y_pred=predictions,target_names =['NORMAL','PNEUMONIA']))

分类报告

让我们用百分比% 可视化一些预测图像

test.reset()
x=np.concatenate([test.next()[0] for i in range(test.__len__())])
y=np.concatenate([test.next()[1] for i in range(test.__len__())])
print(x.shape)
print(y.shape)#this little code above extracts the images from test Data iterator without shuffling the sequence# x contains image array and y has labels dic = {0:'NORMAL', 1:'PNEUMONIA'}
plt.figure(figsize=(20,20))
for i in range(0+228, 9+228):
  plt.subplot(3, 3, (i-228)+1)
  if preds[i, 0] >= 0.5: 
      out = ('{:.2%} probability of being Pneumonia case'.format(preds[i][0]))

  else: 
      out = ('{:.2%} probability of being Normal case'.format(1-preds[i][0]))plt.title(out+"\n Actual case : "+ dic.get(y[i]))    
  plt.imshow(np.squeeze(x[i]))
  plt.axis('off')
plt.show()

测试数据预测

此代码块给出了单个图像的百分比预测,可以通过指定其路径直接从您的驱动器加载。

在导入图像后,我们必须在这里重新创建所有的数据预处理步骤,就像我们之前将测试集输入模型以获得预测一样。对于预处理,我们需要导入tensorflow.keras.preprocessing.image类。

  1. 导入图像,定义尺寸为(500,500),颜色通道为灰度。
  2. 将图像转换为数组,将它除以 255 进行缩放,将维度扩展到轴= 0,因为我们的模型需要 4 个维度,如前所述。
  3. 最后我们来预测一下案情!

让我们用我的 X 射线对我们的模型做一些实地测试

# Testing with my own Chest X-Ray
hardik_path = '/content/drive/My Drive/unsegregated /IMG_20201023_204205928~2.jpg'from tensorflow.keras.preprocessing import imagehardik_img = image.load_img(hardik_path, target_size=(500, 500),color_mode='grayscale')# Preprocessing the image
pp_hardik_img = image.img_to_array(hardik_img)
pp_hardik_img = pp_hardik_img/255
pp_hardik_img = np.expand_dims(pp_hardik_img, axis=0)#predict
hardik_preds= cnn.predict(pp_hardik_img)#print
plt.figure(figsize=(6,6))
plt.axis('off')
if hardik_preds>= 0.5: 
    out = ('I am {:.2%} percent confirmed that this is a Pneumonia case'.format(hardik_preds[0][0]))

else: 
    out = ('I am {:.2%} percent confirmed that this is a Normal case'.format(1-hardik_preds[0][0]))plt.title("Hardik's Chest X-Ray\n"+out)  
plt.imshow(np.squeeze(pp_hardik_img))
plt.show()

哈迪克的胸部 x 光片

Phew 。我的胸部 x 光检查似乎一切正常。现在轮到你诊断胸透了。

干得好!我们刚刚创建了一个 CNN 模型,可以以 91%的准确率将 X 射线图像分类为肺炎病例或正常病例。

Gif via GIPHY

感谢你在这个漫长的旅程中陪伴我,我们刚刚为₹省下了 466 万卢比 x 4 年的放射学家学位,现在我们能够对 x 光进行分类。

关注我的社交活动

链接到我关于这个项目的笔记本:colab.research.google.com

我的 LinkedIn 个人资料:https://www.linkedin.com/in/hardik-deshmukh/

我的其他媒体文章:https://medium.com/@smarthardik10

我的 GitHub:https://github.com/smarthardik10

部署在 streamlit 上的应用程序:

https://share . streamlit . io/smarthardk 10/Xray-classifier/main/web app . py

参考

[1]https://stack overflow . com/questions/61060736/how-to-interpret-model-summary-output-in-CNN

[2]https://towards data science . com/a-guide-to-a-efficient-way-to-build-neural-network-architectures-part-ii-hyper-parameter-42 efca 01 e5d 7

[3]https://medium . com/@ RaghavPrabhu/understanding-of-convolutionary-neural-network-CNN-deep-learning-99760835 f148 #:~:text = Strides,with%20a%20stride%20of%202 。

[4]https://machine learning mastery . com/rectified-linear-activation-function-for-deep-learning-neural-networks/

[5]https://stack overflow . com/questions/37674306/what-the-difference-than-same-and-valid-padding-in-TF-nn-max-pool-of-t

[6]https://deep lizard . com/learn/playlist/plzbt5o _ S2 Q7 lw i2y 8 _ qtvuxzedl 6 qu

[7]https://towards data science . com/Adam-latest-trends-in-deep-learning-optimization-6be 9a 291375 c

[8]https://towardsdatascience . com/everything-you-need-known-to-know-about-activation-functions-in-deep-learning-models-84ba 9f 82 c 253

中世纪城市化:用 Python 模拟城市动态

原文:https://towardsdatascience.com/medieval-urbanism-modelling-city-dynamics-with-python-3f835555976a?source=collection_archive---------58-----------------------

中世纪城市的等级制度是否压制了城市社会经济生活?

阿德里安·图丁在 Unsplash 上拍摄的照片

有这篇文章代码的 Jupyter 笔记本可以在这里找到,原始文章这里。

城市是如何成长的?

大城市是否只是小城市的放大版仍然是一个悬而未决的问题。这是一个重要的问题。为了规划更好的城市,我们需要更好地理解地理、城市经济、社会和物理网络以及政治制度如何共同带来城市的发展或衰落。为了实现这一目标,需要对城市住区如何随着时间的推移而演变有一个透彻的看法。实质性研究声称,将在“现代性”、“资本主义”和工业革命中获胜的社会、经济、政治和组织结构及其创新植根于并发展自中世纪的欧洲定居点。另一方面,中世纪的城市在性质上有所不同:更小,农业,生产力更低,技术更简单,没有有组织的市场经济。与现代城市的类似结构相比,封建政府、教会和行会等严格的等级制度对中世纪城市的社会和经济生活的组织产生了更大的影响。这种影响表现在隔离的公司社会中,在这种社会中,社会团体限制了个人和家庭的社会和经济交往及机会。现代西方思想、人员和货物的“自由流动”与中世纪的城市格格不入。

这两种不同的、乍看上去相互矛盾的观点提出了一个经验性的问题:中世纪的城市与现代城市有本质上的不同吗?或者说,从中世纪到现代城市,城市进程、形式和功能是否存在连续性?

这不仅仅是一个有趣的问题,提出这样的问题对于建立一个广泛的、有历史依据的城市化理论非常重要。在本帖中,我们将缩小所提问题的范围,并试图找出教会或行会等等级制度是否限制和约束了影响城市经济和空间增长的社会融合和互动。我们将查看加州 173 座中世纪城市的建成区和常住人口的数据集。公元 1300 年,用简单的统计技术揭示它们之间的关系,并解释与来自定居比例理论的两个模型相关的结果。第一个模型最初是为描述现代城市而开发的,它将城市的建成区作为其人口规模的函数,将城市视为嵌入空间的无约束、无等级的社会经济网络。由于中世纪制度对社交网络的影响,第二种模式建立在第一种模式的基础上,增加了对社会和经济互动的限制。后一个模型预测,如果这种限制性影响很强,城市的聚集效应将很弱,这在建筑面积和人口之间的关系中是显而易见的。

城市的空间和社会组织模式

一方面,人们可以把中世纪的城市想象成一个自组织的、无等级的社会和空间网络实体。如果是这样的话,人与人之间的互动只受到交易、运输、机会成本,以及个人需求、技能和资源之间所谓的匹配成本的限制。在这样的网络中,任何两个人之间的互动都不受限制,可以自由进行。我们将把这种城市视角称为社会反应器模型。然而,如前所述,诸如教会、封建当局、行会、家庭关系等等级制度。,在中世纪的城市中发挥了巨大的权力和控制力。这构成了一个假设的基础,即这些制度强烈地规范了不同社会群体之间的联系,因此限制了促进经济生产率、思想流动以及知识和创新创造的社会互动。我们将把这种城市视图称为结构化社会互动模型,并讨论相应的数学模型,该模型基于捕获所提及的社会和经济规则的分层图。然后,我们将对现有数据进行统计分析,并通过从这些模型的角度解释数据分析的结果来检验我们的假设。

社会反应器模型

大多数城市社会经济理论,包括地理和城市规划的经典模型背后的基本思想是“空间平衡”的概念。在威廉·阿隆索(William Alonso)提出的最简单的形式(T1)中,它指出,在一个城市中,个人和企业通过在土地租金、交通成本和经济偏好之间取得平衡来选择他们的位置,给定可用的资源。这通常会导致单中心的空间组织,城市中心的土地价格最高——就可达性和低交通成本而言,这是最有利的位置——随着远离市中心而降低。另一方面,城市或住区规模理论与阿隆索模型具有相同的基本要素,只是它提供了一个更精确的建模框架,通过一个规模指数将城市的微观过程和物理结构与其人口联系起来,如下所述。住区规模理论背后的核心思想是,所有人类住区——无论规模或社会经济复杂性如何——在总体形式和功能方面都有基本的数量相似性。这来自社会集聚带来的多层次收益,无论是经济专业化、创新、共享基础设施、共同劳动力、国防、宗教还是贸易。本质上,他们模拟了一个城市的各种社会经济特征与其人口之间的关系。城市经济学模型和城市规模理论之间的一个关键区别是用社会经济互动网络取代了经济学中常见的生产或效用函数。

也就是说,让我们推导出一个城市的人口 N 与其建成区 A 之间的预期关系。与经典的城市经济模型不同,我们不必假设一个放射状的单中心城市结构。为了做到这一点,我们权衡了社会经济互动给个人带来的平均收益和相关的交通成本:

在等式中, G 是每次互动的净收益乘以一个人在一段时间内走过的区域。鉴于中世纪与现代城市在社会关系、经济生产率和创新方面的差异, G 可能会随着时间的推移而发生显著变化。 ϵ 是每单位长度的运动成本,它是技术(步行、骑马等)的函数。).另一个描述城市中个体互动成本的因素是分形维数,它描述了人们探索城市的方式。对于 H=1 来说,个体通过线状轨迹在城市中移动,而对于 H→2 来说,他们将城市作为一个区域进行彻底的探索。在相反的极限 H→0 中,个人仍然被限制在一个地方(轨迹是一个静态点),城市实际上不再是一个相互作用的社会经济网络。通过一些简单的高中代数调整,我们得到:

其中 α:=2/(H+2)a:=(G/ϵ)^α 。这个简单的结果描述了城市住区的一些最重要的特性。首先,如果社会交往的收益相对于交通成本来说很小,就像中世纪城市的情况一样,那么前因子 a 将会很小,城市将会非常密集。还要注意的是,如果 H=0 ,如隔离定居点可能发生的情况,总建筑面积 A 将与人口成比例,不会产生任何聚集效应。对于 H=1 ,可以得到特殊的指数值 α=2/3 ,这种情况被描述为无定形的定居模型,因为它忽略了城市中的任何空间结构和组织。在这样的聚居地,人口密度 n 随着人口规模n(n)= n/a(n)= a^(−1)迅速增加。

然而,到目前为止,我们还没有考虑到这样一个事实,即城市住区不是作为空白的各向同性画布组织起来的,而是通过感兴趣的地点和使通向它们成为可能的网络(街道、运河、小路)组织起来的。这意味着城市中社会经济互动的有效空间由其接入网络定义。总网络面积 A_n 可以从人口密度 N/A 中导出:

a _ n(n)∞n_d=a^(1/2)其中 d 是个体间的平均距离 d=(A/N)^(1/2).此外,

其中 δ = H/2(H+2)a_0=la^(1/2) 。这里的 l 是捕捉每个感兴趣位置(如门和入口)的网络宽度的长度标尺。对于 H=1 ,我们得到 1 的指数δ = 5/6

对于剩余的分析,社会反应器模型的两个方面是特别有趣的。首先,该模型预测城市的建成区面积应随其人口平均以指数 2/3 ≤ α ≤ 5/6 增长,其中 2/3 的下限对应于无定形的各向同性元素,通常为小城镇,而 5/6 的上限对应于城市中物质基础设施的作用和精细测量。第二个方面与管理社会互动的等级制度有关,这是我们接下来要关注的。

结构化社会互动模式

现在,让我们看看政治机构和社会团体如何在城市中的个人之间的社会和经济互动中引入进一步的约束,以及它们的影响如何改变上一节中描述的标度定律。我们要做的基本上是建立一个模型,从城市中完全自由的社会融合转向隔离社会群体的等级结构,减少这些群体之间的自由社会互动。这些结构可以是正式的,如行会、教区,也可以是非正式的,如家庭关系或种族关系。

在上图中, A 展示了一个非结构化的社交网络,任何人都可以自由地与他人联系,唯一的限制是移动的成本。这样的网络结构意味着连通性随着城市人口规模的增加而迅速增加,平均度为k(n)= k0n^δ,δ∾1/6。相反, B 显示了一个结构化的社会经济网络,其中社会互动由社会团体和政治机构(黑色方块)调节,并且在层级的每一级,可能会受到因素 s < 1 的抑制。这意味着,与另一个人的联系层次越高,社会互动的积极影响就越会在每一个层次上被削弱。当等级制度的总体效果是减少社会可能性,从而减少聚集效应,迫使面积与人口的比例指数更接近 1。

事实上,等级结构也可以被建模为通过减少互动成本来促进社会互动,例如,通过减少犯罪或充当中心场所,促进创新,如现代城市中的大学。但这是一个不同的故事,我们不会在这里讨论它。

上图中的层次结构 Bh 级参数化,在每一级我们假设 b 连接是可能的,类似于树形图中的分支因子。 b 和城市人口 N 之间的关系则由 h(N) = log_b N 给出。

我们现在可以推导出一个人可以拥有的互动次数,因为他的接触是通过更高层次的群体或社会机构进行的。这里重要的参数是社会视野r = sb 。如果 rr>1,或者说有效接触率大于 1,那么这个城市作为一个互动的社会经济网络就不会分崩离析。因为,这个城市被分成不同的团体,由各自的机构决定。

我们从考虑一个典型人的联系数量开始。在层级的第一级,有 b 可能的连接,在第二级有 b+sb ,在第三级有 b+sb+(sb)^2 等等。然后,在给定的阻尼水平下,一个人的交互总数 s ,是有限几何级数的和

如果你不记得高中代数课上的内容,你可以在下面的附录中找到复习资料。对于非常小的 s ,我们有 r < < 1k _ s(n)= b/(1sb)≅b,这意味着所有的相互作用基本上局限于家庭,根本没有城市作为社会经济关系的网络!相比之下,对于接近 1 的 s ,我们有 r > 1 ,我们可以写成:

由于城市人口 N 与总的基础设施网络面积成比例, A_n 乘以典型人的平均连接性, k_s(N) ,并且由于 h=log_b N ,我们得到

其中:θ = ∣ lns/lnb ∣.注意,当 s→1 时,指数 θ 变为零,使得社会群体的影响变得无关紧要。我们还记得,由于城市生产率与其连通性,a _ n = a _ 0n(1−δ)∞n(1−δ)成正比,因此我们得到

在相反的极限中,当社会机构过度限制时,我们得到A _ N∾N,导致随着城市的增长,人口密度没有增加( n =常数)。这表明了限制社会机会的等级制度如何减少甚至可能消除社会经济集聚效应、空间密集化以及城市本身。一句话:如果我们在任何城市系统中观察建筑面积与人口的线性比例,我们可以确定正式或非正式等级制度的社会经济限制可能在起作用的情况。

中世纪城市数据的统计数据分析

在我们的腰带下有一点理论,让我们在四个不同的政治“城市系统”的 173 个城市住区的数据集中揭示城市建成区和人口之间的统计关系:德国、意大利北部、法国、比利时和英格兰:

让我们首先绘制数据集中所有城市的建成区与人口的关系图:

正如典型的城市规模一样,我们看到了面积和人口的高度倾斜分布。由于一个合理的假设是人口和建筑面积都不能太大,我们可以通过取两个变量的自然对数来安全地转换数据,从而使它们“正常化”,而不会因为厚尾而冒有偏差回归结果的风险。

好多了!既然这四个地缘政治集团可能有不同的社会经济结构,我们应该对它们加以控制。让我们按城市系统来划分情节:

现在,我们本质上定义以下普通最小二乘模型:

其中 i 是指定城市系统中城市的指数, ϵ 表示 i.i.d .高斯分布误差。请注意,这只是上面讨论的社会反应器模型的对数变换版本,并且 β 与原始模型中的比例系数 α 相同。准备好数据后,让我们首先一起运行所有城市的模型。以下是回归结果:

我们看到,感兴趣的估计参数缩放系数 β 为 0.714,位于 2/3 和 5/6 之间!这是中世纪城市人口和面积的统计分布与城市规模理论相一致的第一个暗示。在我们继续之前,让我们首先运行一些诊断测试,以确保我们没有异方差或正态性问题。我们可以从剩余曲线开始:

很好,看起来很随意。对于异方差性,即误差项的方差在不同观测值之间不相同的情况,我们将使用 Breusch-Pagan 检验,它本质上是卡方检验。跳过数学,重要的是,如果我们获得一个小的 p 值(< 0.05),这表明我们有异方差,应该解决这个问题。幸运的是,我们获得了 0.644 的 p 值,因此我们可以安全地假设同伦方差。

为了检查正态性,我们看一下 Q-Q 图:

并发现与正态假设非常吻合。

现在让我们继续运行四个不同的模型,每个模型对应一个地缘政治城市系统。从四个城市系统的 Breusch-Pagan 测试中获得的所有 p 值都远大于 0.05,所有四个模型的 Q-Q 图如下所示:

在不违反我们的回归假设的情况下,我们在对数空间中为四个城市系统绘制了回归线:

估计的缩放系数为

  • 英国: 0.73
  • 法国和比利时: 0.79
  • 德国: 0.75
  • 意大利北部: 0.72

即使将置信区间考虑在内,估计的标度系数在地缘政治城市系统中也非常相似,如社会反应堆模型预测的那样 2/3≤α≤5/6 ,并且没有一个系数是 ≥5/6 ..由于这个原因,我们无法从统计上发现明显的证据,证明等级制度限制了中世纪城市的社会经济互动。当然,由于系数大致落在 2/3≤α≤5/6 范围的中间,一些社会经济抑制仍然可能发生。尽管如此,一致的估计比例系数与现代城市的比例系数非常接近,并没有衰减到 1。这表明中世纪城市的等级制度对城市社会经济互动没有明显的限制性影响,至少在结构化互动模型预测的框架内是如此。

结论

尽管存在许多结构、社会和经济差异,中世纪城市住区至少有一个与现代城市相同的基本属性:在给定的城市系统中,较大的城市比较小的城市密度更大。总体而言,数据显示,城市地区的人口增长速度并没有超过社会反应器或结构化互动模型的预测,这表明没有证据表明中世纪城市的社会经济连通性和聚集效应受到了限制性抑制。尽管等级制度在中世纪城市盛行,而且在今天的西方城市中似乎并不占主导地位,但我们可以将这一结果解释为拒绝中世纪社会制度的强烈隔离作用的直观想法。这意味着西欧城市的等级制度。公元 1300 年并没有在很大程度上限制社会融合、经济整合,或者人员、思想和信息的自由流动。这些发现表明,在基本结构层面上,中世纪城市的微观社会经济过程与现代城市的基本相似。尽管有许多结构、功能和文化上的差异,中世纪和当代的城市似乎都被描述为随着它们的发展而在空间上变得越来越密集的社会网络。所有这些都表明,通过现代都市主义可以更好地理解过去的城市,但通过中世纪甚至古代的都市主义也可以更好地理解现代城市。随着历史数据的数量和质量不断提高,我们可以预期情况会是这样。

附录

对于 r≠1 ,一个几何级数的前 n 项之和为

其中 a 是级数的第一项, r 是公比。我们可以推导出总和 s 的公式如下:

分析笔记本电脑上的大数据

原文:https://towardsdatascience.com/medium-data-on-your-laptop-in-2020-e986468a577f?source=collection_archive---------45-----------------------

处理大于内存的数据的技术。

Filiberto Santillán 在 Unsplash 上的照片

大数据自 2005 年左右就已经存在了。当时,如果你想操纵大数据,Hadoop 是热门的新玩具。然而,最有可能的是,您必须建立自己的内部集群,花几周或几个月的时间配置所有东西,然后才能真正对数据进行处理。

如今,情况不同了,就像所有与技术相关的事情一样,对大数据工具的访问已经民主化。

具体来说,有三件事发生了变化:

  1. 内存成本一直在下降,这意味着如今数据科学笔记本电脑上 24GB 或 32GB 的内存非常普遍。
  2. 所有大数据基础设施在诸如 AWS 或 GCP 这样的云平台上都可以轻松使用。
  3. 尽管大数据在过去被 Java 或 Scala 所主宰,但在几个成熟的专用库的帮助下,python 已经成为这个世界上的一流公民。

在本大数据系列的第一章中,我们将看到 2020 年大数据项目有哪些本地选项,以及您应该根据您的用例选择哪一个。

有时,您可以在笔记本电脑上做任何需要做的事情,尤其是当您处理的是介质数据(几十 GB)时。好处是您可以立即开始。这种情况与两种情况相关:

1.您可以缩小数据

事实上,处理大数据最简单的方法是……将其转换成较小的数据,并在本地进行处理。

亚取样

作为第一个例子,假设您有数十亿个点跟踪道路上用户的驾驶速度,并且您想知道速度分布是什么样子,或者基于驾驶模式构建保险索赔的预测模型。在这种情况下,一种明智的方法是对数据进行子采样,假设您可以使其小到足以容纳您的内存,但又大到足以具有统计代表性。因此,如果您的数据库中有 100,000 个用户,每个用户每秒钟都有一个数据点,他们在路上,您可以对您的数据进行子采样,对于 10K 用户的随机子集和数据库中的特定月份,每 10 秒钟只获取一个数据点。

让我们看看数字是什么样子的。假设您有:

  • 100,000 名用户,每名用户每秒钟可获得 1 个数据点
  • 假设每个数据点包含 5 或 6 个字段(某种 ID,2 个位置字段和 2 个速度向量字段),每个数据点总计约 200 字节
  • 每个用户平均每天驾驶 1 小时,总计每天 3600 个数据点,每月 100K 个数据点
  • 数据的总大小:(100K 用户)x(每月 100K 数据点)x(每个数据点 200 字节)=每月 200GB

200GB 显然不是您通常会在笔记本电脑上处理的东西,但是采用前面的方法(对于 10K 随机选择的用户,每 10 秒 1 个数据点)会将它降低到 2GB!

虽然它可能不会给你一个尽可能精确的图片,但对于最初的探索,甚至是一个模型的 MVP 来说,它肯定是绰绰有余的。

组块

有时,您希望应用于数据的处理或分析自然会被分成多个独立的步骤。例如,您可能想要生成月度报告,或者您想要按州或城市计算一些统计数据。

在这种情况下,只下载当前分析阶段(正在分析的当前月份或当前地理位置)所需的数据,对其执行分析,然后继续下一次迭代,每次都交换内存中的数据,而不是增加分配的内存大小,这是很有意义的。

只要您不介意等待整个流程按顺序完成运行,或者如果您只需要更新它而不是每次从头开始重新运行它,这种迭代方法是很有趣的。

无论您使用子采样还是分块,大数据都存储在某个地方的数据仓库中,您可以对其进行查询,但您永远不会将它完全放在您的笔记本电脑上。

向下铸造

向下转换是将 64 字节浮点列转换为 32 字节浮点列的过程,假设您不介意精度上的小损失。您还可以向下转换 64 字节的长整数,特别是当您有像年或年龄这样的东西时,它们真的不需要那么多空间!

最后,pandas 最近引入了category dtype,对于分类数据非常有用,代替了默认的object(或字符串)dtype。不同之处在于,新的category dtype 只为分类变量的每个唯一值保留空间,而默认的object dtype 为每个值保留空间。

通过使用astype函数,您可以在读取数据后向下转换您的列,但是最好您可以使用dtype参数在read_csv函数调用中指定您的列的类型。

2.您可以使用库来处理大于内存的数据

假设子采样或分块不能满足您的需求。让我们以由 100 只股票组成的 ETF(交易所交易基金)为例,你必须找到该 ETF 的确切波动率,给定这 100 只股票中每只股票的每日收盘价。上面的选项(子采样、分块或向下转换)都不令人满意,因为在这种情况下,您希望尽可能精确。

解决方案是使用一个可以处理核外计算的库,这意味着它可以计算统计数据或处理存储在硬盘上的数据,根据需要将数据移入和移出内存。

对于统计计算,使用 Vaex

👉读取数据

在计算大量表格数据的统计数据时,Vaex 的速度非常快。Vaex 的另一个非常好的特性是能够在数据框上创建虚拟列,也称为表达式。它们不会占用任何内存空间,Vaex 会根据需要动态使用它们。

要安装 vaex,假设您已经安装了 python,只需运行:pip install vaex,但是确保您是以 admin 身份运行的。

Vaex 与 HDF5 配合得非常好,因此如果您从一个大的 CSV 文件或一堆 CSV 文件开始,您首先要做的是将它们转换为一个 HDF5 文件。下面是执行此操作的代码:

在这种情况下,我们简单地使用import glob并将第一行替换为:

for i, chunk in enumerate([pd.read_csv(file) for file in glob.glob('folder/path')]):

然后你可以用df = vaex.open('bigfile.hdf5')连接你的数据。

👉用 Vaex 计算统计

从那里,计算统计数据就像:df.<statname>(<expression>, [binby=], [limits=])一样简单。

几个例子:

  • 计算数据帧中A列的平均值:df.mean(df.A)或等效的df.mean(df.A, limits='minmax')
  • 只计算 0 到 10 之间的平均值:df.mean(df.A, limits=[0, 10])
  • 同时做上面两个例子:df.mean(df.A, ['minmax', [0, 10]])
  • 计算仅包括中间 99%值的平均值(即排除左侧的 0.5%和右侧的 0.5%):df.mean(df.A, limits='99%')
  • 我们也可以用字符串名来指代列:df.mean('A')
  • 或者我们可以即时构建表达式:df.mean('A + 10*B')
  • 我们可以使用参数binby按 bin 计算统计量,参数应该是一个表达式列表:df.mean('A', binby=['B'])
  • 当使用宁滨时,您可以通过使用 shape 参数来控制箱的数量,shape 参数是维度值的列表,例如,df.mean('A', binby=['B'], shape=4)将使用 4 个箱返回 B 的每个箱的平均值 A。如果使用多个表达式进行绑定,您可以通过提供单个形状值来获得正方形网格,也可以提供一个形状值列表(每个宁滨表达式一个形状值)。
  • 我们可以将 Vaex 表达式传递给numpy函数,它将返回一个新的 Vaex 表达式,例如df.newA = np.clip(np.log(df.A), 0, 1)。这里我们也在数据帧中存储新的表达式。

下面是您可以计算的可用统计信息列表:countmeanstdvarcovcorrelationmedian_approxmodeminmaxminmaxmutual_information。API 文档可以在这里找到。

使用方括号([]): df_negative = df[df.x < 0]过滤数据帧,然后我们可以在过滤后的数据帧上执行上面的任何计算(或下面的绘图)。

👉用 Vaex 操作数据

a .加入数据

我们可以用 Vaex 做左、右和内连接。语法很简单:dfA.join(dfB, left_on='a', right_on='b', how='left|right|inner')

b .分组和汇总

这里有一个来自 Vaex 教程的例子,展示了分组/聚合功能,包括控制计算列的名称:df.groupby(by='x', agg={'mean_y': vaex.agg.mean('y'), 'max_z': vaex.agg.max('z')}

您会注意到聚合函数在vaex.agg模块内部。可用的功能有:countfirstmaxminsummeanstdvarnunique

👉用 Vaex 绘图

Vaex 提供了一个简单的 API 来绘制大量数据的统计数据。两个主要的函数是plot1dplot2d,它们被从一个 dataframe 对象中调用。例如:

  • 用 x 的值来画 E 的平均值:df.plot1d(df.x, what='mean(E)', limits='99%')。请注意,这些限制适用于 X 轴,并且有一个值为 64 的默认shape参数(即默认情况下,X 值将被分成 64 个箱)。
  • 或者,我们可以使用vaex.stat.<statistic>语法来利用制表符结束。上面的例子可以改写为:df.plot1d(df.x, what=vaex.stat.mean(df.E), limits='99%')
  • 如果您已经计算了想要绘制的统计数据,您应该传递grid参数(带有结果表达式)而不是what
  • 对于 2d 绘图:df.plot(df.x, df.y, what=vaex.stat.mean(df.E)**2, limits='99%'),它将输出如下内容:

👉使用 Vaex 进行高级绘图

可以通过传递轴的表达式对列表(默认情况下显示为列)和/或“what”列表(默认情况下显示为行)来输出多个图。

例如,df.plot([['x', 'y'], ['x', 'z']], what=[vaex.stat.count(), vaex.stat.mean(df.E)])将输出一个网格 2x2 的图。

我们可能希望显示不同数据子集的图。在这种情况下,前面提到的过滤数据的方法(使用括号并将结果赋给变量)将是低效的,更好的方法是使用selection参数。因为默认情况下选择会在同一个图表上过量绘制,所以我们可以使用visual参数进行定制。例如,要将选择显示为列,将不同的表达式显示为行:

df.plot([['x', 'y'], ['x', 'z']], what=vaex.stat.count(), selection=[None, df.E > 0], visual=dict(column='selection'))

👉带 Vaex 的超级琴弦

Vaex 可以对字符串列应用一系列操作。这些操作可以通过使用df.string_column.str.<operation>语法来调用。操作列表可以在这里找到。一些最有用的是contains(用于子串检测)和match(用于正则表达式匹配),连接字符串列的cat,以及不言自明的startswith / endswith

如果您打算以后使用云集群,请使用 Dask

Dask 是 python 世界中著名的大数据处理库。我要直截了当地说,如果你只处理中等数据,也就是说,你的数据集是以千兆字节为单位的,Vaex 每次都会在性能方面击败 Dask。

然而,Vaex 被设计为在单台计算机上工作。目前没有多节点内置功能。另一方面,Dask 使用统一的 API 提供单节点和多节点功能。如果在迁移到云之前,您只想在本地进行一些测试或试验,那么这是一个巨大的优势。

Dask 的另一个特性是它试图模仿 python 数据科学家熟悉的许多库:当然是 pandas,还有 scikit-learn 和其他库。这使得学习曲线几乎不存在。例如,在 Dask 中读取 CSV 文件非常简单:

import dask.dataframe as dd df = dd.read_csv(filepath, blocksize=25e6) #25MB chunks

如果您的机器上有 n 个内核,您可以调整块大小(也取决于您的总可用 RAM)来优化运行时,尝试读取 n 个块中的数据。Dask 可以轻松地从各种来源(本地或远程)读取各种格式(CSV、parquet、hdf5 等)的数据。).

这在某些方面是一个优势,但从长远来看,它也可能是一个约束,因为 scikit-learn 中的一些设计选择并不是最好的。

需要注意的另一个警告是 Dask 的apply方法要求用户指定输出的类型和名称。这不是一个巨大的烦恼,只是一些需要注意的事情。

最后,我非常喜欢 Dask Distributed ,这是一个用于 python 分布式计算的轻量级库。在云中设置非常容易,我在这里写了一个关于的主题。

下期保持联系!我将探索面向大数据的云技术:Spark、Bigquery、Dataflow 等等。

作为一名有抱负的数据科学家,你应该关注的中型作家

原文:https://towardsdatascience.com/medium-writers-you-should-follow-as-an-aspiring-data-scientist-13d5a7e6c5dc?source=collection_archive---------27-----------------------

我最喜欢的 10 个数据科学博主,让你的学习之旅更轻松。

图片由 Pixabay 的 esudroff 提供

简介

这是我关注的 10 位数据科学作家/影响者的列表。是的,我也关注和阅读其他人的作品,但是如果我必须把范围缩小到前 10 名的话,这将是我的清单。

我分享这些是因为我相信所有有抱负的数据科学家也会从阅读他们的文章中受益匪浅。

名单主要由媒体作家组成。我在最后添加了一个非媒体博客,因为我相信他的工作很好地补充了列表的其余部分。

我已经整理了列表,所以你可以直接链接到作者的页面。此外,我还添加了每位作者的我最喜欢的文章,以及我认为他们的作品与众不同的简短描述。

威尔·科汉森

中等: @williamkoehrsen

我最喜欢的帖子: 关于如何用统计数据撒谎的课程

我喜欢 Will 的文章,也喜欢他用简单易懂的方式解释数据科学概念的能力。他写了很多文章,针对的是初级数据科学家,但也有一些文章解释了更高级的主题。

此外,他已经是一个媒体作家有一段时间了,在此期间,他发表了很多文章。因此他的博客有很多值得学习的内容。

卡西·科济尔科夫

中等:@科济尔科夫

我最喜欢的帖子: 为赶时间的人统计(看嵌入式 YouTube 视频!)

凯西是谷歌决策智能部门的负责人。这应该足够立刻跟踪她了。处于这种位置的人肯定会有很多有价值的信息可以分享。

在她的文章中,她使用了大量的类比来解释这些概念,这样一个正常人就可以理解了。还有,她的一些博文配有短小的视频,带来了问题的本质。

饶彤彤

中等: @tonester524

我最喜欢的帖子: 了解随机森林

Tony 定期撰写关于不同数据科学主题的高质量文章。

他的独特之处在于,仅仅一年多时间,他就从一名财务顾问转行成为了一名数据科学家。他从训练营和自学开始了他的旅程,所以在这些话题上也有很多建议。

雷贝卡·维克里

中等: @rebecca.vickery

我最喜欢的帖子:Scikit 简单指南——学习管道

丽贝卡是媒体上的另一位普通作家。她分享了许多数据科学教程,作为一名自认为是数据科学家的人,她分享了许多有助于你学习该主题的好资源。

她还发送每月简讯,所以你应该注册获取她的最新文章。

丹尼尔·伯克

中: @mrdbourke

自主持博客:www.mrdbourke.com

我最喜欢的帖子: 用 Pytho 学习机器学习和数据科学的 5 个初学者友好步骤 n

丹尼尔无疑是我最喜欢的数据科学作家之一。他创造了自己的机器学习学位!他的博客专注于数据科学,也提供了大量的生产力技巧。

我喜欢他的博客的另一个原因是,他似乎是一个真正的人,他不仅写数据科学,还强调工作生活平衡和日常活动的重要性。他的博客口头禅是:吃,动,学,做。

埃里克·刘易森

中:@ eryk . lewinson

我最喜欢的帖子:Python 中基于技术分析的算法交易

Eryk 写了很多关于数据科学的文章!如果你曾经思考过如何利用数据科学解决自动交易或金融问题,你应该看看他的帖子。

尽管他的大多数文章都与金融相关,但他也写了数据科学的其他领域。

本杰明·奥比·塔约博士

中号:@本雅明比

我最喜欢的帖子:10 年自学数据科学——彼得·诺维格(谷歌机器学习主管)的 3 堂课

Benjamin 是另一位数据科学作家,他涵盖了各种主题。有抱负的数据科学家会发现他的文章有用且激励人心。

此外,他还写了他作为数据科学家作家的旅程。他写了几篇文章,讲述他是如何开始写作的,以及他作为博客写手的最新进展。我发现这很鼓舞人心,我会推荐给任何考虑开始自己的博客冒险的人。

拉胡尔·阿加尔瓦尔

中:@ Rahul _ Agarwal

我最喜欢的帖子: 用这 10 种资源成为 2020 年的数据科学家

Rahul 是一名拥有数年经验的数据科学家。他定期发布数据科学家的文章,这些文章主要适合有抱负的或初学者的数据科学家。他擅长用简单易懂的方式解释复杂的概念和技术。

他在 Medium 上写作,但也有一个博客,你可以订阅这个博客来获取他的最新帖子。

杰森·布朗利

博客:https://machinelearningmastery.com/

我最喜欢的帖子: 调整分类机器学习算法的超参数

贾森不写或媒体,但我喜欢他的文章,所以我决定把他列入名单。对我来说,他的网站是一个我发现了很多机器学习和数据科学教程的地方,这些教程写得很好,非常有帮助。我无数次使用他的教程来学习新概念或交叉验证我当前的知识。

西拉杰·拉瓦尔

中: @siraj_raval

YouTube:【https://www.youtube.com/c/SirajRaval/videos

我最喜欢的视频:4 分钟搭建一个神经网络

Siraj 是人工智能学院的创始人,并制作了关于不同人工智能概念的令人惊叹的视频。如果你是视觉学习者,你应该看看他的 YouTube 频道。你会喜欢内容和他的能量。

Siraj 已经制作了许多视频,涵盖了深度学习的主题。看了他的视频后,这些概念变得如此简单,令人惊讶。他还教授如何使用人工智能来创建自己的企业。非常鼓舞人心!

总结

如果你读到这篇文章的结尾,你就已经知道了我最喜欢的 10 个数据科学博客作者。

我希望你会发现它很有用,看看它们,并希望成为他们的一些工作的爱好者。

快乐阅读!

原载于 about Data blog . com:2020 年 7 月 3 日作为一个有抱负的数据科学家你应该关注的媒介作家

PS:我正在 Medium 和上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的* 邮件列表 每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入。***

下面还有一些你可能喜欢的帖子:

** [## 9 大 Jupyter 笔记本扩展

改进笔记本电脑功能,提高您的工作效率

towardsdatascience.com](/top-9-jupyter-notebook-extensions-7a5d30269bc8) [## 熊猫概况和探索性数据分析的第一行代码!

了解如何为自动 EDA 安装和使用 pandas profiling

towardsdatascience.com](/pandas-profiling-and-exploratory-data-analysis-with-line-one-of-code-423111991e58) [## 9 熊猫有效数据分析的可视化技术

学习如何使用折线图、散点图、直方图、箱线图和其他一些可视化技术

towardsdatascience.com](/9-pandas-visualizations-techniques-for-effective-data-analysis-fc17feb651db) [## python 中的 lambda 函数是什么,为什么你现在就应该开始使用它们

初学者在 python 和 pandas 中开始使用 lambda 函数的快速指南。

towardsdatascience.com](/what-are-lambda-functions-in-python-and-why-you-should-start-using-them-right-now-75ab85655dc6)**

米娜:谷歌的新聊天机器人

原文:https://towardsdatascience.com/meena-googles-new-chatbot-657241cf5595?source=collection_archive---------10-----------------------

一个更像人类的多功能聊天机器人

谷歌最近发表了一篇关于其新聊天机器人 Meena 的论文。谷歌在设计和方法上击中了所有的要害。虽然底层技术并不是全新的,但就构建聊天机器人而言,这似乎是正确的方向,聊天机器人真正多功能,在交互方面更像人类。

聊天机器人的兴起

聊天机器人是一种人工智能系统,它通过文本消息或语音与用户进行交互。最近聊天机器人的应用有了巨大的增长。事实上,根据 T2 的一些估计,聊天机器人市场有望增长到 94 亿美元。

聊天机器人有很多使用案例——例如,客户服务、电子商务服务商、食品配送等。大多数大公司都有自己版本的聊天机器人,比如苹果的 Siri,谷歌的谷歌助手,亚马逊的 Alexa 等等。

也有很多框架可以帮助你构建自己的聊天机器人应用程序,例如开源框架 RASA ,谷歌 DialogueFlow ,IBMWatson,或者微软 Bot 框架

尽管聊天机器人有所增长,但当前大多数解决方案仍面临一些主要挑战:

  1. 基于封闭域/规则的:大多数聊天机器人都是封闭域的,这意味着它们只在特定的域内工作。这些机器人寻找某些关键字来找出用户的意图,一些基于规则的系统在引擎盖下确定应该根据意图采取什么行动。虽然这些系统仍然有用,但它们不是通用的,并且需要大量特定领域的工作才能运行
  2. 非对话式:聊天机器人的圣杯是互动应该看起来像人类。对于当前的大多数系统来说,这几乎是不可能的
  3. 非多回合:大多数聊天机器人在给出响应时没有考虑到多重交互(用户和聊天机器人通过轮流进行交互)的更大背景,这再次导致交互时的非人类体验。

米娜

Meena 是一个基于 Transformer seq2seq 架构的多回合、开放域聊天机器人(你可以阅读 this 了解更多关于 Transformers 的信息),以端到端的方式训练。它的规模很大,包含 2.6 亿个参数,并在 300GB+文本数据上进行训练。Meena 试图通过其方法和设计来解决上一节中强调的挑战。

以下是这篇论文的一些主要亮点:

  1. 训练数据:米娜接受公共领域社交媒体对话的训练。每个会话被转换成一个(上下文,响应)对,其中“上下文”表示“响应”消息之前的多达 7 条消息。总数据包括 40B 个字和 341 GB 的文本数据。
  2. 模型架构 : Meena 基于 Evolved Transformer (ET)架构,是在原有 Transformer 架构的基础上进化而来的 NAS 架构。该模型具有 1 个 ET 编码器模块和 13 个 ET 解码器模块。
  3. 模型训练:模型在一个 TPU v3 吊舱上进行了长达 30 天的训练(2048 个 TPU 核心!!)
  4. 将现有的研究向前推进:Meena 中使用的大多数概念,例如——开放域性质、端到端训练、transformer seq2seq 架构等,在过去已经以某种形式进行了尝试。只是大了很多(训练数据,模型大小),好了很多(架构,解码)。
  5. 评估指标:很难评估聊天机器人的性能,因为没有唯一的正确答案。根据作者的说法,这篇论文的主要贡献之一是设计了一个评估指标,他们称之为敏感性和特异性 平均值 (SSA)。它应该是模拟一个对话是否会被称为一个基于人类判断的好的对话。
  6. 敏感性和特异性平均值(SSA) : 对于给定的响应,SSA 被定义为人类是否认为该响应有意义(合理)和具体(这不是类似“我不知道”或“这很好”的一般响应)的二元指标的平均值。
  7. 培训目标:定义一个评估最终绩效的指标是不够的,因为我们还需要定义一个模型在培训时试图优化的衡量标准。作者的另一个主要成就是证明了 NLP 中常用的度量“困惑”与模拟人类判断的 SSA 度量相关。因此,优化模型以自动减少困惑会使它更受人类欢迎。

结果

米娜 vs 人类和其他夏博特。来源谷歌博客

在作者定义的 SSA 指标上,Meena 的得分为 79%,低于人类 86%的水平,但它仍然比其他许多受欢迎的聊天机器人要好。当然,其他聊天机器人没有记住新的 SSA 指标(作者提出的),但当前的方法仍然值得称赞,因为它不是手工制作的,而是以端到端的方式训练的。

摘要

谷歌对 Meena 的做法和结果令人兴奋。虽然要建造在专业知识和多功能性方面与人类一样好的聊天机器人还有很多工作要做,但 Meena 似乎是朝着正确的方向迈出了一步。

认识一下火灾探测推特机器人 Aggi🔥🛰️

原文:https://towardsdatascience.com/meet-aggi-the-fire-detection-twitter-bot-a1e3089bf7ea?source=collection_archive---------57-----------------------

我造了一个推特机器人,它可以在卫星图像中探测火灾。继续阅读,了解更多。

@AggiBot 是一个 Twitter 机器人,它使用最新的 Landsat-8 卫星图像来探测和可视化活跃的火灾。现在在推特上直播了。

早在 2018 年,当我第一次看到推特上流传的加州野火的照片时,我就决定建立 Aggi。我想知道这是否可以用编码、算法和卫星自动完成!

编码和算法(来源)

在遥感中,近红外(NIR)和短波红外(SWIR)波段通常用于可视化活跃的火灾和/或烧伤疤痕。所以我开始试验 Sentinel-2 和 Landsat-8 卫星的近红外/SWIR 波段。来自两次任务的数据是公开的,并且具有非常相似的光谱轮廓(见图 1)。我最初的实验显示了两者都很有希望的结果。然而,使用 Landsat-8 数据获得了更一致的结果,所以我最终在最终产品中使用了它。

图 1 ( 来源)

@AggiBot 是做什么的?

@AggiBot 分析最新的 Landsat-8 图像,寻找活跃的火灾。每当检测到火灾时,火灾的可视化图像就会发布到 Twitter 上(参见图 2 中的示例)。

图 2 ( 来源)

目前, @AggiBot 监控着 13 个不同国家 1500 多万平方公里的土地(见图 3)。目标是扩大到监测至少 10%的地球陆地面积,或 5100 多万平方公里。

图 3 ( 来源)

它是如何工作的?

@AggiBot 运行在 AWS 上,所以它一直在监听来自 Landsat 的 S3 桶的 SNS 通知。每次推送新场景时,会自动触发以下事件序列:

  1. 从 AWS 获取场景数据(影像+元数据)。
  2. 生成场景的逐像素二元火焰遮罩。
  3. 发现和定位现场的单个火灾。
  4. 使用谷歌反向地理编码 API 将探测到的火灾坐标转换为人类可读的地址。
  5. 使孤立的火可视化(RGB 和假彩色)。
  6. 最后,发微博!

源代码完全是用 Python 写的,使用了 Rasterio 和 OpenCV 等库。

到目前为止有趣的发现

Just last week the Nishinoshima 西之島 volcanic eruption in Ogasawara, Tokyo, Japan was detected on July 4th (See Figure 4).

图 4 ( 来源)

另一个有趣的例子来自巴西马托格罗索州的6 月 10 日和 6 月 26 日的地点都检测到了火灾。从燃烧模式和谷歌地图上出现的植被来看,这似乎是某种形式的雨林砍伐(见图 5)。

图 5(2020–06–10,2020–06–26)

常见问题(FAQ)

  • @ AggiBot 的目的是什么?宣传野火是我们星球面临的一个环境问题。
  • @ AggiBot 多久能探测到一场火灾?取决于新的 Landsat-8 场景何时可用。一般 8~12 小时。
  • @ AggiBot 能预测未来的火灾吗?不,这不可能!
  • @ AggiBot 能探测到的最小的火是什么?面积为 20 Landsat-8 像素,或 18000 平方米的火灾。
  • @ AggiBot 的检测是否经过验证?不,他们不是。事实上,假阳性经常发生。
  • @ AggiBot 是开源的吗?还没有。但是正在努力。

TL;博士;医生

  • 我建造了一个 Twitter 机器人,它使用卫星图像来探测和可视化活跃的火灾。
  • 它运行在自动气象站上,使用最新的 Landsat-8 图像。
  • 现在在推特上直播:https://twitter.com/aggibot

认识谷歌 Meena

原文:https://towardsdatascience.com/meet-google-meena-11c26849e12a?source=collection_archive---------7-----------------------

贾里德·阿兰戈在 Unsplash 上的照片

技术

谷歌人工智能的最新聊天机器人技术

几年前,当我看到桑德尔·皮帅介绍 Google Duplex 时,不寒而栗。那个预约接线员,美得吓人。那辆嗯嗯很神奇。

今天,我刚刚读到谷歌人工智能的新聊天机器人叫做 Meena 。它被描述为

多回合开放域聊天机器人对从公共领域社交媒体对话中挖掘和过滤的数据进行端到端训练

我们来分解一下

多回合指参与者之间一个来回的对话。还记得 Lisa (Google Duplex)试图和真人预约理发的对话吗?这种对话可以被归类为多回合,因为机器人不会失去上下文,保持有意义并完成任务。

开放域意味着聊天机器人可以谈论的话题没有任何限制。这个想法是让聊天机器人更像人类。像人类一样说话。有了足够大的数据集,聊天机器人应该可以做到。即使没有上下文,人类也能找到一种合理的方法来扩展对话。这就是聊天机器人开放域名的意义。

一个吓人的笑话

这或多或少将是文明的终结,不是吗?你们都听说过这个笑话,对吧?没有吗?这就是——世界上最杰出的科学家创造了第一台 AGI 计算机(或计算机网络)。他们问 AGI 的第一个问题是— 上帝存在吗? 情报回应— 有,现在就有!

挖掘过滤 —对数据进行语言处理和过滤。挖掘和过滤的目的是,首先,从文本中提取有意义的数据(有意义的词或有更多权重的词或定义上下文的词),其次,从句子中过滤掉所有的噪音,所有不必要的垃圾。数据挖掘(和过滤)本身是一个非常广泛的研究领域,其中涉及到语言学、语言理论、形式语法等等。

谷歌人工智能的博客文章说

训练的目标是最小化困惑,预测下一个单词(在这种情况下,是对话中的下一个单词)的不确定性。其核心是进化的变形金刚 seq2seq 架构,这是一种由进化神经架构搜索发现的变形金刚架构,用于改善困惑。

对于统计学家、ML 工程师和数据科学家来说,这些词可能很容易理解。但不是每个人都这样。评估语言模型不严格地说就是检查模型的准确性。有许多方法可以评估一个语言模型。

评估告诉我们语言模型的好坏

概括地说,有两种语言评价模式

  1. 外在评估模型 —所发生的是,你让两个相互竞争的语言模型经历相同的测试/任务,如机器翻译、语音识别、语法纠正等等。然后,你评价哪个表现更好。缺点是评估这些模型需要大量的时间和资源。因此,替代方案如下。
  2. 内在评估模型 —外在模型所做的是基于语言模型的外在事物进行评估,即使用模型完成一些任务,将模型应用于特定用例或应用。内在模型针对语言模型的本质。在内在模型中用作度量的一个东西是困惑。一个例子是香农游戏——它简单地问了一个问题语言问题能多好地预测给定句子中的下一个单词?还有其他方法可以根据内在属性评估模型。

所以,困惑只是一个统计模型,是用内在属性来评估语言模型。

简单来说,整个想法就是猜测给定的不完整句子中的下一个单词,并看看模型预测的有多好。这就是困惑背后的想法。困惑度越低,模型越好。

Google Meena 的评测还用什么

在谷歌人工智能的博客上阅读这篇深度文章,他们声称米娜的敏感度和特异性平均值(SSA) 只比人类低 7%。

你还记得乔姆斯基的著名句子结构吗?

无色的绿色想法疯狂地沉睡

他试图展示语言中的漏洞,以及语言是如何拥有句法和语义的。句法就是语法。语义就是意义。语法不难。语义是。使用乔姆斯基的方法,机器可以在没有太多意义的情况下写出语法正确的句子。今天它可以做到这一点。它做得不太好的是— 有意义。这就是整个努力的意义所在。

SSA 的目标是语义——聊天机器人的响应有多大意义?以及它对正在进行的对话有多具体。因此,敏感性(或意义)和特异性(对话的上下文)是测试语言模型好坏的一个很好的书面指标。

从本质上来说,敏感性和特异性平均值(SSA) 是由谷歌创建的一个指标,用于衡量对话聊天机器人以一种敏感和特定的方式对对话做出回应的能力。就像人类一样。为了测试 Meena,它与市场上其他流行的开源聊天机器人进行了对话。Google AI 的博客上说,

为了计算 SSA,我们众包了与正在测试的聊天机器人的自由形式对话——Meena 和其他知名的开放域聊天机器人,特别是 Mitsuku 、 Cleverbot 、 XiaoIce 和 DialoGPT 。

与谷歌 Meena 的对话。

谷歌声称 Meena 比当今市场上最好的生成模型更好,这种模型叫做 GPT-2 ,由埃隆·马斯克和山姆·奥特曼创建并支持 OpenAI 。这是从中得到的一些结果—

OpenAI 在几个数据集上的 GPT-2 性能指标。摘自 OpenAI 的网站。阅读本了解详情。

关于 SSA 指标的更多信息还有待了解。但是当谷歌说他们做得更好的时候,人们可能会相信他们。他们以前交付过令人惊奇的东西。

谷歌在博客文章的结尾写道:

虽然我们在这部作品中只关注感性和特异性,但其他属性如*和* 真实性 在后续作品中也值得考虑。此外,解决模型中的安全性和偏见是我们的一个重点领域,鉴于与此相关的挑战,我们目前不会发布外部研究演示。然而,我们正在评估与外部化模型检查点相关的风险和好处,并可能选择在未来几个月内使其可用,以帮助推进该领域的研究。

我希望他们强调真实性,强调安全性和偏见。那是最重要的。

这对我们的未来意味着什么?

我们甚至不会注意到这项技术何时成为我们日常生活的一部分。这绝对是谷歌研究人员的一项伟大成就。更好的是,他们正在考虑解决这些模型中的安全性、真实性和偏见。这也是 OpenAI 的基础。虽然,他们的想法是一个人(谷歌)手中的权力太大了,所以如果 AGI 在不久的将来成为现实,如果我们能够通过开源最好的人工智能代码来分配这种权力,那会更好。

我把这个留给你,显然是——

那个令人不寒而栗的电话。

Head 这里为我写更多关于技术的文章。

见见 Lena——一个简单的人工智能无代码聊天机器人。

原文:https://towardsdatascience.com/meet-lena-a-simple-ai-no-code-chatbot-8ac006c92a45?source=collection_archive---------27-----------------------

微软 POWER 平台解决方案

用微软的 Power 虚拟代理构建一个简单的聊天机器人,无需代码

照片由德鲁·比默在 Unsplash 上拍摄

Power Virtual Agent (Power VA)是微软称为 Power Platform 的低代码和数据平台的最新成员,它允许你不用代码就可以构建人工智能支持的聊天机器人。

准备好自己构建一个机器人了吗?在这个介绍故事中,我将指导你注册、创作并在你的个人网站上发布这个机器人,完全不需要任何代码。

注册 Power VA

进入 Power Virtual Agents 营销页面,选择开始免费。使用您的 Microsoft 工作或学校帐户登录,或者注册(如果您没有)。

一旦你注册并登录,你可以给你的机器人一个名字。我叫我的莉娜

向莉娜问好

我们首先定制机器人的问候行为。在开始页面点击自定义您的问候语按钮。

这就把我们带到了所谓的创作画布,在这里你可以改变你的机器人的流程和行为。使用创作画布非常简单。用你自己的对话框随意调整你的机器人的个性。根据需要删除不必要的步骤。

因为我希望我的机器人回答关于我的问题,所以我在主问候消息中反映了这一点。完成自定义问候行为后,点击保存按钮。

接下来,从菜单中选择主题。把主题看作是处理特定内容的对话流的封装——可以说是主题

Power VA 自带两种类型的话题。首先,有一些系统主题,你很少或根本无法控制。这些是像问候和再见这样的谈话的主要组成部分。稍后请随意探索它们。

第二,有用户主题你可以完全从零开始构建或者基于所谓的经验。这些预构建的用户主题用于向您展示概念,作为一种互动学习。

我们现在不需要它们,所以我们将关闭所有的课程

现在是时候定义我们自己的用户主题了。我们使用 Power VA 的建议主题功能,而不是从头开始。该功能能够抓取任何给定的网站,并尝试根据其内容“猜测主题。这方面最好的例子是一个典型的公司或产品网站上的常见问题。

出于这个介绍的目的,我使用了我的个人网站,上面有关于我的简介和简短的传记。看看 VA 能从中提取出什么力量。请随意使用您自己的网站或网络上的任何其他内容。

点击建议主题,输入您希望 Power VA 抓取的网址链接,点击添加。您可以添加多个网站以获得更多建议。准备好之后点击开始

根据网站的数量和大小,此过程可能需要几分钟,如进度消息所示。

爬行完成后,Power VA 会根据网站内容告诉你它建议了多少个主题。点击标签建议查看摘录。

正如你从截图中看到的,Power VA 很好地从我的个人网站中发现了最重要的信息,并且很好地命名了它们。

现在是时候一个一个的打磨爬行出来的结果了。这包括决定我们是否希望保留建议并将其作为用户主题添加,或者我们是否希望删除它。

选择任何建议并单击其名称,查看发现的确切内容。在我的例子中,你可以看到它是如何很好地提取我的简历的。然而,它不知道用户将如何要求它离开触发短语和一个无意义的条目。

我们必须通过点击添加到主题并编辑来改进这一点。

首先,我们检查抓取的内容,并立即注意到我们必须更新名称并从列表中删除无意义的触发短语。

此外,我们添加了至少 3-5 个不同的短语,用户可能会使用它们来查询这些内容。

提示:在编写触发短语时,最好遵循以下简单规则:

  • 句子开头的大写字母
  • 其他的都用小写
  • 不要用标点符号(。, ?!:😉
  • 至少使用 3-5 个触发短语,并尽可能清晰地表达出来

当你完成所有的重命名和措辞后,点击保存主题按钮。对您想要保留的所有其他建议重复此步骤。

在测试我们的机器人之前,我们必须启用新添加的用户主题。为此,我们使用每个主题旁边的状态开关将所有打开

现在是时候测试我们的机器人了。

点击左下角的测试你的机器人并说“Hi”来观看你调整后的问候对话框出现。问任何其他问题,看看你的机器人是否正确理解它。

随意测试机器人,并即时改进。您可以单击聊天旁边的创作画布上的节点,并立即编辑它们。

此外,请注意聊天上方的主题之间的轨迹切换,当启用时,会将创作画布的上下文动态切换到正确的主题,允许您快速改进您的机器人。

发布你的机器人

发布我们的机器人超级容易。

进入发布菜单,点击发布按钮。确认发布,就大功告成了。她上场了!

在我们最终使用我们的机器人之前,我们需要了解它可以在各种不同的渠道上使用,比如定制网站、Skype、微软团队、脸书甚至电子邮件。要查找这些频道,请点击发布页面上的转到频道

出于本指南的目的,我们将把我们的 bot 添加到一个定制网站中,基本上是将其嵌入为一个 iframe。如果你手头没有自定义网站,你可以简单地使用开箱即用的演示网站来展示结果。

点击自定义网站复制嵌入代码到您的自定义网站。

或者,如果你想在没有真实网站的情况下测试,使用jsfiddle.net。参见本文末尾的奖金部分。

我已经选择在我的个人网站上嵌入这个机器人,作为一个实验性的功能。使用一点 CSS,你可以在本文的结尾找到,它看起来像下面这样。

搞定!你做得很好!

我希望这能让您对使用 Power Virtual Agent 能做什么有一个好的印象。还有更多的发现,但这是现在。

就这样吧。

—塞巴斯蒂安

奖励:使用jsfiddle.net进行测试

没有网站?只需将 iframe 内容从 Power VA 复制到 jsfiddle.net 的 HTML 面板。从第二个奖励提示中获取 iframe 样式,并将其复制到 CSS 面板。点击运行并查看您的机器人运行情况。

额外收获:iframe 的样式

现在,将我们的机器人嵌入到一个定制网站中是通过使用一个 iframe 来完成的,这个 iframe 在内容本身的样式方面非常有限。下面的代码片段确实设计了 iframe 嵌入本身的样式,但是没有它的内容。

见见 Plotly Mapbox。地理数据可视化的最佳选择

原文:https://towardsdatascience.com/meet-plotly-mapbox-best-choice-for-geographic-data-visualization-599b514bcd9a?source=collection_archive---------17-----------------------

PLOTLY |地理|数据可视化|数据科学| PYTHON

探索性数据分析和交互式仪表板演示的逐步指南

使用 Plotly 的地理数据可视化示例(在本文中)

我遇到过几个包含地理数据的项目,我一直在寻找地理可视化的最佳工具。作为一名 Python 用户,我尝试过 Pyplot 的底图、GeoPandas、Folium 和 Bohem,但它们都没有给我满意的体验。

终于,在我找到 Plotly 之后,我的寻找结束了。更具体的说,Plotly 的 Mapbox 包。在今天的这篇文章中,我将演示一个使用 Plotly Mapbox 的地理数据可视化的快速入门,并展示为什么你也应该考虑使用它。

为什么是 Plotly?

  • 视觉上吸引人。你必须努力让它看起来很丑😜。
  • 选择控制的粒度。您有很大的自由来控制可视化效果。
  • 互动很好玩。它对于 EDA 和仪表板演示都很方便。
  • 不同语言(R、Python、Javascript)的不同产品线,稳定发布的版本。
  • 学习速度不是很快。按理说,但是自己判断。
  • 关注大数据。通过 datashader ,Plotly 可以处理数百万行的数据可视化。
  • 开源。它是免费的!!!

Plotly Maxbox 适合你吗?

从我的经验来看,如果

  • 您是 Python 用户
  • 你熟悉数据可视化工具,如 plt,sns
  • 您需要交互式数据可视化,或者您想尝试一下
  • 你喜欢免费的东西

那么,Plotly Maxbox 极有可能是你的正确选择。

在我们进入代码之前,我想再提一件关于交互式数据可视化的事情。有些人认为交互式数据可视化仅仅是为了酷的效果,它仅仅是为了表现。对于其他应用,如探索性数据分析(EDA),静态图就足够了。

然而,对于地理可视化而言,无论是数据科学家还是受众,通常都需要改变地图的比例(例如,通过放大和缩小)来充分理解信息;静态的情节是不够的。

事不宜迟,让我们进行地理可视化。

第一个例子:快速启动

# import packages
import pandas as pd
import plotly.express as px
import numpy as np# get data
url = '[https://raw.githubusercontent.com/kefeimo/DataScienceBlog/master/2.geo_plot/df_mapbox_demo.csv'](https://raw.githubusercontent.com/kefeimo/DataScienceBlog/master/2.geo_plot/df_mapbox_demo.csv')
df_plot_tmp = pd.read_csv(url)
df_plot_tmp.head()# two-line code
fig = px.scatter_mapbox(df_plot_tmp, lat="latitude", lon="longitude", color="gender", zoom=3, mapbox_style='open-street-map')
fig.show()

提示:点击“编辑图表”按钮,有更好的交互体验。

第二个示例:使用地图框 tilemap

在上面的例子中,我们使用“open-street-map”作为后端 tilemap。(回想一下,我们定义了 mapbox_style='open-street-map '。)但实际上,我发现 Plotly 默认的 Mapbox 底图更有吸引力。为此,我们需要使用一个 Mapbox 访问令牌。(一个 Mapbox 访问令牌大概是这样的:PK . eyj 1 ijo ibxxxxxxxxxxxxxx .这里免费申请公共访问令牌。)

mapbox_access_token =  'Your token...'
px.set_mapbox_access_token(mapbox_access_token)
fig = px.scatter_mapbox(df_plot_tmp, lat="latitude", lon="longitude", color="gender", zoom=3,
#                        mapbox_style='open-street-map',
                       )
fig.show()

温馨提示:令牌错误会得到一个空剧情。(它就在那里,但你看不见。)要解决这个问题,请仔细检查您的令牌验证,或者返回使用 mapbox_style='open-street-map '。(此外,使用 mapbox 时,请确保互联网已连接。)

wrong_token = 'xxx'
px.set_mapbox_access_token(wrong_token)
fig = px.scatter_mapbox(df_plot_tmp, lat="latitude", lon="longitude", color="gender", zoom=3,
#                        mapbox_style='open-street-map',
                       )
fig.show()

第三个例子:使用参数

我们可以根据需要进一步指定参数(看看它与 seaborn 有多相似)。

我认为值得一玩的东西有:

  • 颜色(类似于 seaborn 中的色调)
  • 大小
  • 缩放,居中,(控制渲染地块时的第一个视图)
  • 宽度、高度

而事情没有给我一个满意的结局是:

  • 文字(使用此功能时,散射会不知何故消失。“hover_name”也是一种选择)

备注:

  • 没有形状控制
  • 同样,当你使用颜色时,取决于它是连续的还是分类的,你可能想要进一步的颜色连续比例(类似于调色板)或者指定类别顺序,颜色离散顺序
  • 当你玩 size 的时候,你也可以玩 size_max
  • 通过设置渲染器,您可以选择在笔记本(默认)或另一个窗口(renderer='browser ')中打开绘图。
# px.set_mapbox_access_token(mapbox_access_token)
fig = px.scatter_mapbox(df_plot_tmp, lat="latitude", lon="longitude", 
                        color="gender", 
                        size='hour', size_max=6, 
                        category_orders={'gender':list(df_plot_tmp.gender.unique())},
                        color_discrete_sequence=['#2b83ba', '#fdae61'],
#                         hover_data=1,
#                         hover_name='hour',
#                         text='hour',

                        zoom=3.3,
#                         zoom=2.8,
                        center=dict(lon=105, lat=38),
                        width=900*1.5, height=500*1.5,)
fig.show()
fig.show(renderer="browser")

为了巩固我们的理解,让我们用 age_cate 作为颜色说明符。

在这个例子中

  • 查看如何指定类别顺序
  • 查看如何指定调色板(注意在 scatter_mapbox 中,颜色需要以十六进制指定,所以我们需要通过某种排序将颜色解析为十六进制)

提示:虽然 Plotly 有自己的调色板,但是对于 python 来说,我发现选择调色板的简单方法是使用 seaborn sns.color_palette(),所有可用的调色板都可以在 colorbrewer 中找到。

from matplotlib.colors import to_hex
import seaborn as sns# px.set_mapbox_access_token(mapbox_access_token)
fig = px.scatter_mapbox(df_plot_tmp, lat="latitude", lon="longitude", color="age_cate", 
#                         size="hour", size_max=15,
                        category_orders={'age_cate':['A22-', 'A23-26', 'A27-28', 'A29-31', 'A32-40', 'A40+']},
                        color_discrete_sequence=[to_hex(c) for c in sns.color_palette('BrBG_r', 6)],  

                        zoom=2.5,
                        center=dict(lon=105, lat=38, ),
                        width=900, height=600,)
fig.show()

接下来,玩连续/数字颜色。

# play with the color: continous/numerical
# px.set_mapbox_access_token(mapbox_access_token)
fig = px.scatter_mapbox(df_plot_tmp, lat="latitude", lon="longitude", color="hour", 
#                         size="hour",
                        color_continuous_scale=px.colors.cyclical.Twilight, 

                        zoom=2.5,
                        center=dict(lon=105, lat=38, ),
                       width=900,
                        height=600,)
fig.show()

您可能会遇到的问题

到目前为止,您应该已经掌握了使用 Plotly 进行交互式地理数据散点图的基本知识。现在让我们讨论一些常见的问题和潜在的迂回。

一个问题是关于重叠。

有时,数据集本身会导致重叠。您可能已经注意到坐标数据(即纬度、经度)为 0.01。在 tilemap 上绘图时,这很容易导致重叠。请注意,没有抖动选项。我们可能需要手动将抖动添加到数据中。(不知何故,我认为抖动对于交互式散射可视化来说不是微不足道的,因为抖动参数必须随着比例的改变而相应地改变(例如,放大和缩小)。如果要将抖动应用于交互式绘图,我们可能需要一种自适应抖动方法。)

在我看来,要克服重叠,一个现成的解决方案是调整散布大小(例如,减小散布大小以减轻重叠)。但是对于 px.scatter_mapbox,在 4.8.1 Plotly 版本中,我们不能用 int 来指定大小(不管纪录片里怎么说)。但是有一些方法可以解决这个问题,例如,在数据框中创建一个列来指定散布大小。

尝试以下代码:

‘Hack’尺寸参数。

# px.set_mapbox_access_token(mapbox_access_token)
fig = px.scatter_mapbox(df_plot_tmp, lat="latitude", lon="longitude", 
                        color="gender", 
                        size='size_for_plot', size_max=2, 
                        category_orders={'gender':list(df_plot_tmp.gender.unique())},
                        color_discrete_sequence=['#2b83ba', '#fdae61'],
#                         hover_data=1,
#                         hover_name='hour',
#                         text='hour',

                        zoom=2.8,
                        center=dict(lon=105, lat=38),
                        width=900, height=600,
                        title='modified scatter size')
fig.show()

手动添加抖动

# px.set_mapbox_access_token(mapbox_access_token)
fig = px.scatter_mapbox(df_plot_tmp, lat="lat_jitter", lon="lon_jitter", color="age_cate", 
#                         size="size_for_plot", size_max=3,
                        category_orders={'age_cate':['A22-', 'A23-26', 'A27-28', 'A29-31', 'A32-40', 'A40+']},
                        color_discrete_sequence=[to_hex(c) for c in sns.color_palette('BrBG_r', 6)],  

                        zoom=10,
                        center=dict(lon=116.4, lat=39.9, ),
                        width=900, height=600,
                        title='add jitter')
fig.show()

从这篇文章中学到什么

  • 试试 Plotly Mapbox,因为它提供了吸引人的可视化效果,它很有趣,它是免费的,并不难开始。
  • px 代表 Plotly.express,从那里开始比较容易。
  • 如何解决重叠的问题?

下一步是什么?

  • 尝试其他 Mapbox 包,例如 px.choropleth_mapbox
  • 看看 go ('go '代表' plotly.graph_objs ')
  • 试试去吧。Scattermapbox()',这给了你更多的控制

这是一个结合了散点图框和下拉列表的例子。(代码: gender_dropbox.py )

会见数据专家

原文:https://towardsdatascience.com/meet-the-data-experts-22345ada9929?source=collection_archive---------56-----------------------

通过蜘蛛图展示数据分析专家的不同能力。

介绍

你有没有想过那些“数据人”每天都在做什么?可能是你的女儿、丈夫、同事或导师,但每次他们讨论他们的工作时,你的眼神都是闪烁其词。数据科学、数据分析以及所有这些“数据”术语都有模糊和重叠的定义。最重要的是,许多组织的招聘信息会将半打数据技能放在一起,用于所有的职位。这些往往是不现实的。这篇文章是我试图通过 BS 排序,并为每个“数据专家”分配适当的类别。他们主要受到谷歌、亚马逊、苹果和脸书招聘信息的影响。如果有人应该知道这些角色的正确定义,那就是科技巨头。

这些分类将帮助你了解每个人的优点和缺点,以及应该向每个人提出什么样的问题。它还将帮助任何有抱负的数据分析专业人士,他们希望了解哪种工作路径对他们最有意义。这些职位经常重叠,每个人都是独一无二的,但这应该作为一个指南,在定义这些角色时方向是正确的。

定义数据专家

拥有数据专业知识的人有几十种不同的工作角色;然而,大多数职位倾向于与以下十个职位紧密匹配:

数据专家打分

每项技能都按照 1-5 分的标准进行评分(5 分为最佳)。1 不代表这个人在这方面不熟练。这些分数与组织内的其他数据分析角色相关。让我们建立六个技能集,并对每个角色进行评分:

1.)领域专业知识——理解洞察和分析对业务的影响。

2.)数据操作——能够编写干净的代码或者配置一个能够接收、操作、分析、建模和可视化数据的工具。深度比广度更重要,因为技术技能很容易在工具之间转换。

3.)沟通技巧——向非技术观众解释复杂技术概念的能力。

4.)管理能力——需要情商、强大的社交技能,以及向团队每个成员传达明确职责的能力。必须是能够管理直接下属的领导。

5.)数据库——了解存储数据的系统,包括数据模型设计、数据库、数据仓库和数据管道。这包括 SQL 和 NoSQL 数据库以及云的知识。

6.)统计 -统计和机器学习模型的知识,包括适当的假设、用例,以及可以在数据集之外做出的结论。这包括统计学和机器学习软件工具(如 R、Python 和 SAS)方面的知识。

可视化数据专家

图像来源:ggplot2 以呈现图表

假设
——分析师的职位靠近业务(例如业务分析师、政策分析师等)。).
-数据科学家图表显示了他们能力的上限(即“独角兽”)

解读图表

上述图表被称为蜘蛛(或雷达)图。点从“网”的中心移动到特定类别的边缘的时间越长,该类别的价值就越高。

从数据角色表和蜘蛛图中,您可以得出以下结论:

-分析师可以使用各种工具快速获得一些见解,但可能难以处理大数据。数据工程师往往拥有最强的计算机科学背景。
-不出所料,统计学家对机器学习和统计模型(即统计学)的理解是最好的。
——统计学家和应用机器学习工程师极其相似。
——“完美”的数据科学家可以做到这一切。然而,大多数数据科学家只是应用机器学习工程师或统计学家,只是名称上有所改变。
-你在组织层级中的位置越高,你往往对概念有更好的理解,但你的技能可能会在粒度级别下滑(例如,使用新库的数据争论)。

来源

这篇文章的主要灵感来自于谷歌首席决策科学家 Cassie Kozyrkov 写的一篇博客。数据分析角色和评分的定义主要受领先技术公司的空缺职位的影响,包括谷歌、亚马逊、脸书和苹果。

以下网站帮助我在 R 中创建了蜘蛛图:
https://www . rdocumentation . org/packages/fmsb/versions/0 . 7 . 0/topics/radar chart
https://www.r-graph-gallery.com/142-basic-radar-chart.html

认识熊猫最难的功能,第一部分

原文:https://towardsdatascience.com/meet-the-hardest-functions-of-pandas-part-i-7d1f74597e92?source=collection_archive---------15-----------------------

用熊猫重塑数据框

掌握pivot_table()stack()unstack()的时间和方式

来自 Pexels 的 Binyamin Mellish 照片

介绍

下面是最糟糕的情况:你在看付费课程,讲师在讲某个话题。然后,突然,他引入了一个全新的函数,说“这个函数/方法在这种情况下是完美的,它非常简单,所以只需查看其文档以了解更多细节”。你说 OK,去文档,连自己在看什么都不知道。

你感到沮丧,去读一些文章或 StackOverflow 线程,有时回来时感觉更糟。相信我,每个人都会这样。这篇文章专门讨论硬pandas函数的情况。

大多数资料没有涵盖pandas的一些高级功能的原因主要是它们非常具体。当您学习基本的方法和函数时,您将在它们自己的上下文中学习它们,就像在玩具数据集上一样。对于较难的函数,它们很难解释,并且很难创建它们有用的上下文。

这种功能通常在更有经验的科学家的工具箱中。当你以这样的方式使用它们时,它们会产生不同,函数用一行代码很优雅地解决了你遇到的问题。这个帖子讲的就是他们三个:pivot_table()stack()unstack()

[## 通过我的推荐链接加入 Medium-BEXGBoost

获得独家访问我的所有⚡premium⚡内容和所有媒体没有限制。支持我的工作,给我买一个…

ibexorigin.medium.com](https://ibexorigin.medium.com/membership)

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

[## 阿尔法信号|机器学习的极品。艾总结的。

留在循环中,不用花无数时间浏览下一个突破;我们的算法识别…

alphasignal.ai](https://alphasignal.ai/?referrer=Bex)

可点击的目录(仅限网络)

1.简介
2。设置
3。 Pandas pivot_table(),与 groupby()
4 比较。熊猫栈()
5。熊猫解散()

每个函数第一次出现时,我都给它们的文档加了超链接。请查看更多详细信息。

设置

Pandas pivot_table(),与 groupby()比较

应该有一种——最好只有一种——显而易见的方法来做这件事。

以上是引用 python 的禅宗。Python 希望一个问题只有一个明显的解决方案。但是,pandas刻意回避了这一点。往往在pandas中,一个操作有几种方式。

[pivot_table()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.pivot_table.html)就是一个例子。它是groupby()功能的完整替代,有时甚至是更好的替代。不同的是结果的形状。groupby()返回一个Series对象,而pivot_table()给出一个易于操作的数据框架。

让我们用这两个函数来解决一个问题并给出解决方案。我将从seaborn加载tips数据集:

tips = sns.load_dataset('tips')
tips.head()

我们想找出每个性别所有账单的总和:

让我们比较一下这两个函数的语法。在groupby()中,我们将想要分组的列放在括号中,在pivot_table()中,等价的参数是index。在groupby()中,为了选择要聚合的列,我们使用带括号的子集,而在pivot_table()中,我们将其传递给values。最后,为了选择聚合函数,我们在groupby()中使用方法链接,而pivot_table()提供了aggfunc参数。

当我写一篇关于 DS 和 ML 的项目设置的文章时,我研究了很多笔记本。我发现令人惊讶的是,许多人使用groupby()并使用.reset_index()函数将groupby()的结果转化为数据帧,让我们进一步探索以找出原因:

result = tips.groupby('sex')['total_bill'].sum().reset_index()
result

如果你使用pivot_table(),你不必使用reset_index()将结果转换成数据帧。groupby()结果不像数据帧那样容易处理。让我们看看如何按多列分组和用多个函数聚合:

tips.groupby(['sex', 'day'])['total_bill']\
            .agg([np.mean, np.median, np.sum]).reset_index()

tips.pivot_table(values='total_bill', 
                 index=['sex', 'day'], 
                 aggfunc=[np.mean, np.median, np.sum])

两个函数都返回多列的数据帧。但是,尽管对于单个列来说pivot_table()更好,但是对groupby结果使用reset_index()会给出更好的数据框架。也许这就是 Kagglers 更喜欢groupby()的原因。

pivot_table()中,有时你可以用columns参数代替index(或者有时两者都用)将每组显示为一列。但是如果您向columns传递多个参数,结果将是一个只有一行的长数据帧。

groupby()pivot_table()的另一个区别是fill_value参数。有时,当您按多个变量分组时,不会有匹配的结果单元格。在这种情况下,groupby()会放置NaN s,但在pivot_table()中,您可以控制这种行为:

tips.head()

你想在什么时候使用pivot_table()?正如我之前说过的,它有时可能是groupby()的更好选择。说到语法也是个人喜好。一个明显的例子是选择pivot_table(),因为它有一些groupby()中没有的其他参数。我已经报道了fill_value,但是还有其他类似margins的。你可以在文档中了解更多信息😁。

请阅读文章的第二部分,了解计算分组汇总统计数据的函数之间的更多差异:

[## 认识熊猫最难的功能,第二部分

掌握交叉表的时间和方式()

towardsdatascience.com](/meet-the-hardest-functions-of-pandas-part-ii-f8029a2b0c9b)

熊猫栈()

使用时,[stack()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.stack.html)返回带有多级索引的整形数据帧。最内层是通过旋转数据框架的列来创建的。我们最好从一个例子开始。为了更好地理解,我将加载cars数据集并对其进行子集化:

让我们看看如何透视数据帧,使列现在成为索引:

当我们在这个数据帧上使用stack()函数时,结果会有多级索引,name为外层,weighthorsepower为内层:

这里,原始数据帧只有一个单级列名。这就是结果数据帧是pandas.Series而不是数据帧的原因。

记住stack()函数总是将列旋转到内部级别索引。如果没有剩余的列,意味着如果最终数据是一个系列,stack()将不起作用。我们来试试上面的Series:

stacked_cars.stack()AttributeError: 'Series' object has no attribute 'stack'

stack()的一个更复杂的例子是当列名作为多级索引给出时。让我们回到我们的一个数据透视表:

如您所见,列名有两个层次。您可以访问具有多级名称的列,如下所示:

让我们在这个数据帧上使用stack(),看看会发生什么:

multi_name.stack()

现在,total_bill这个内层列名变成了一个索引。您可以控制要堆叠的列级别。让我们看看如何堆叠外层列名:

multi_name.stack(level=0)

如您所见,使用不同的级别会产生不同形状的数据帧。默认情况下,level设置为 1。

熊猫解散堆叠()

顾名思义,[unstack()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.unstack.html)做的和stack()完全相反。它采用多级索引Series或数据帧,并将索引转换为列。如果我们拆分堆叠的汽车系列,我们将获得原始数据框架:

>>> print('Unstacked Dataframe:')
>>> stacked_cars.unstack()Unstacked Dataframe:

也许,拆垛最明显的用例是当我们使用groupby()函数时。虽然当我们按一个变量分组时,这一过程是不可能的,但拆分证明对按多个变量分组非常有用。让我们回到我们的tips数据集:

tips.head()

结果是一个具有 4 级索引的序列。这不是我们想要的。让我们拆分一下,以便更容易使用:

multiple_groups.unstack()

结果还是多级索引。这是因为unstack()一次只在一个索引级别上工作。让我们再次调用它来获得具有单一索引级别的数据帧:

multiple_groups.unstack().unstack()

我想你已经看到了unstack()groupby()一起使用的效果。多级索引总是很难使用。除非万不得已,否则尽量避开它们。一种方法是使用unstack()

虽然stack()不常用,但我还是向你展示了它的基本语法和一般用法,以便你更好地掌握unstack()

包裹

这个帖子只有大约 3 个功能。在不久的将来,我计划为其他功能编写类似的文章,这些功能可能有点难以理解并集成到日常使用中。所以,请继续关注!

如果你喜欢这篇文章,请分享并留下反馈。作为一名作家,你的支持对我来说意味着一切!

阅读更多与主题相关的文章:

[## 认识熊猫最难的功能,第二部分

掌握交叉表的时间和方式()

towardsdatascience.com](/meet-the-hardest-functions-of-pandas-part-ii-f8029a2b0c9b) [## 认识熊猫最难的功能,第三部分

形状像果冻的桌子有熊猫旋转()和融化()

towardsdatascience.com](/shape-tables-like-jelly-with-pandas-melt-and-pivot-f2e13e666d6) [## 我习惯如何将数据与熊猫绑定

您可能只使用了默认值

towardsdatascience.com](/how-i-customarily-bin-data-with-pandas-9303c9e4d946) [## 掌握连接:Pandas 合并、连接、追加方法

从半连接/反连接到验证数据合并

towardsdatascience.com](/masteriadsf-246b4c16daaf) [## 来自 Kagglers:DS 和 ML 的最佳项目设置

来自顶级 Kagglers 的项目成功最佳实践的集合

towardsdatascience.com](/from-kagglers-best-project-setup-for-ds-and-ml-ffb253485f98)

认识熊猫最难的功能,第二部分

原文:https://towardsdatascience.com/meet-the-hardest-functions-of-pandas-part-ii-f8029a2b0c9b?source=collection_archive---------1-----------------------

用熊猫重塑数据框

掌握crosstab()的时间和方式

介绍

我记得自己在 DataCamp 上参加了一个名为“Seaborn 中级数据可视化”的课程。它为 DV 教授了非常棒的情节和方法。当谈到热图时,不知从哪里冒出来的讲师介绍了一个全新的pandas功能crosstab()。然后,赶紧说:“crosstab()是一个很有用的函数,可以计算交叉制表表……”

我在那里迷路了。显然,我的第一反应是查看该函数的文档。我刚刚开始觉得我可以处理 Matplotlib 之后的任何文档,但是…我错了。甚至这些例子都是在numpy阵列上给出的,而我本应该使用该死的函数创建热图🤦‍♂️.

在我练习过之后,我知道这也是其他人会为之奋斗的事情。所以,我在这里写了一整篇文章。

在本文的最后一部分,我谈到了为什么有些课程不教你crosstab()这样的高级功能。很难创建这样的函数有用的上下文,同时保持初学者的水平。此外,大多数课程使用小型或玩具数据集。此类功能的优势在更复杂的数据科学环境中更为明显,通常由更有经验的用户使用pandas

在这篇文章中,我将教你如何使用crosstab(),以及你选择它而不是其他类似函数的情况。尽情享受吧!

[## 通过我的推荐链接加入 Medium-BEXGBoost

获得独家访问我的所有⚡premium⚡内容和所有媒体没有限制。支持我的工作,给我买一个…

ibexorigin.medium.com](https://ibexorigin.medium.com/membership)

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

[## 阿尔法信号|机器学习的极品。艾总结的。

留在循环中,不用花无数时间浏览下一个突破;我们的算法识别…

alphasignal.ai](https://alphasignal.ai/?referrer=Bex)

可点击的目录(仅限网络)

∘ 简介
∘ 设置
∘ 熊猫交叉表(),基础知识
∘ 熊猫交叉表()与 pivot_table()和 groupby()的比较
∘ 熊猫交叉表(),进一步定制
∘ 熊猫交叉表(),多个分组

你可以在 this GitHub repo 上下载这篇文章的笔记本。

设置

对于样本数据,我将使用 Seaborn 内置的diamonds数据集。它足够大,并且具有可以用crosstab()概括的变量:

从现在开始,在每个函数的文档第一次出现时,我都使用了超链接。

熊猫crosstab(),基础知识

像许多计算分组汇总统计数据的函数一样,[crosstab()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.crosstab.html)处理分类数据。它可用于将两个或多个变量分组,并为每个组的给定值执行计算。当然,这样的操作使用[groupby()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.groupby.html)[pivot_table()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.pivot_table.html)是可能的,但是正如我们将在后面看到的,crosstab()给你的日常工作流程带来了许多好处。

crosstab()函数接受两个或多个列表、pandas系列或 dataframe 列,并默认返回每个组合的频率。我总是喜欢从例子开始,这样你可以更好地理解定义,然后我会继续解释语法。

crosstab()总是返回一个数据帧,下面是一个例子。数据框是来自diamonds的两个变量的交叉列表:cutcolor。交叉制表只是指取一个变量,将其分组显示为索引,取另一个变量,将其分组显示为列。

语法相当简单。index用于将变量分组并显示为索引(行),与columns相同。如果没有给定聚合函数,每个单元格将计算每个组合中的观察值数量。例如,左上角的单元格告诉我们有 2834 颗 理想切割的 钻石,颜色代码为 D

接下来,对于每个组合,我们希望看到它们的平均价格。crosstab()提供values参数,以引入第三个数值变量进行汇总:

现在,每个单元格包含每种切割和颜色组合的平均价格。为了告诉我们要计算平均价格,我们将price列传递给values。请注意,您必须同时使用valuesaggfunc。否则,您将得到一个错误。我还用round()把答案四舍五入了。

即使它有点高级,当您将它们传递到seaborn的热图中时,您将充分利用crosstab()表的好处。让我们在热图中查看上表:

seaborn可以自动将crosstab()表格变成热图。我将注释设置为True,并用颜色条显示热图。seaborn还为列名和索引名添加样式(fmt = 'g'将数字显示为整数,而不是科学记数法)。

热图更容易解读。你不希望你的终端用户看着满是数字的表格时眼睛流血。所以,我会在需要的时候把每个crosstab()结果放到热图中。为了避免重复,我创建了一个有用的函数:

熊猫交叉表()与 pivot_table()和 groupby()的比较

在我们开始更有趣的东西之前,我想我需要澄清计算分组汇总统计的三个函数之间的区别。

我在文章的第一部分的中提到了pivot_table()groupby()的区别。对于crosstab(),三者的区别在于语法和结果的形状。让我们使用所有三个来计算最后一个crosstab()表:

数据透视表的输出

交叉表的输出

我想你已经知道你的最爱了。groubpy()返回一个序列,而另外两个返回相同的数据帧。然而,可以将groupby系列转换成相同的数据帧,如下所示:

如果你不理解pivot_table()unstack()的语法,我强烈建议你阅读文章的第一部分。

说到速度,crosstab()pivot_table()快,但都比groupby()慢得多:

如你所见,即使与unstack()链接在一起,groupby()也比其他两个快 3 倍。这告诉我们,如果您只想分组和计算汇总统计数据,那么您应该使用相同的 ol' groupby()。当我链接其他方法如 simple round()时,速度差异甚至更大。

剩下的比较将主要是关于pivot_table()crosstab()。如您所见,两个函数的结果形状是相同的。两者的第一个区别是crosstab()可以处理任何数据类型。

它可以接受任何类似数组的对象,如列表、numpy数组、数据框列(是pandas系列)。相比之下,pivot_table()只对数据帧有效。在一个有用的 StackOverflow 线程中,我发现如果你在一个数据帧上使用crosstab(),它会在后台调用pivot_table()

接下来是参数。有些参数只存在于一个中,反之亦然。第一个最受欢迎的是crosstab()normalizenormalize接受这些选项(来自文档):

  • 如果通过allTrue,将对所有值进行标准化。
  • 如果通过,index将对每行进行标准化。
  • 如果通过columns将对每一列进行标准化。

让我们看一个简单的例子:

数量最多的钻石是带有 理想切工 和色码 G 的。

如果通过all,对于每个单元格,pandas将计算总量的百分比:

如果通过,indexcolumns,则按列或行执行相同的操作:

按行规范化。看来在几乎所有类型的钻石切工中,它们的最高编号都有颜色代码 G

按列规范化。热图再次显示,在数据集中,对于每种颜色代码,理想切割的钻石数量要高得多。

crosstab()中,您还可以使用rownamescolnames在函数中直接更改索引和列名。您不必在之后手动操作。当我们一次按多个变量分组时,这两个参数非常有用,稍后您将会看到。

参数fill_value只存在于pivot_table()中。有时,当您按许多变量分组时,不可避免地会有NaN s。在pivot_table()中,您可以使用fill_value将它们更改为自定义值:

但是,如果您使用crosstab(),您可以通过在数据帧上链接fillna()来实现同样的事情:

熊猫交叉表(),进一步定制

crosstab()的另外两个有用参数是marginsmargins_name(两者也存在于pivot_table()中)。当设置为True时,margins计算每行和每列的小计。让我们看一个例子:

pandas自动添加最后一行和最后一列,默认名称为All。控制行为:

如果normalize被设置为True,右下角的单元格将始终包含观察的总数或 1:

请注意,如果将margins设置为True,热图是没有用的。

熊猫crosstab(),多组

对于indexcolumns参数,可以传递多个变量。结果将是一个带有多级索引的数据帧。这次让我们插入所有的分类变量:

对于指数,我通过了colorcut。如果我将它们传递给columns,结果将是一个有 40 列的数据帧。如果您注意的话,多级索引如预期的那样被命名为cutclarity。对于存在多级索引或列名的情况,crosstab()有方便的参数来更改它们的名称:

您传递一个相应名称的列表来将索引名称更改为rownames。对于控制列名的colnames,过程是相同的。

让我惊讶的一件事是,如果你把多个函数传递给aggfuncpandas会抛出一个错误。再说一次,StackOverflow 上的人认为这是一个 bug,已经超过 6 年没有解决了。如果你有任何想法,请在评论中留下,这样我们都可以学习🙌。

最后要注意的是,在pivot_table()crosstab()中,都有一个dropna参数,如果设置为True,则删除所有NaN的列或行。

如果你喜欢这篇文章,请分享并留下反馈。作为一名作家,你的支持对我来说意味着一切!

阅读更多与主题相关的文章:

[## 认识熊猫最难的功能,第一部分

掌握 pivot_table()、stack()、unstack()的时机和方式

towardsdatascience.com](/meet-the-hardest-functions-of-pandas-part-i-7d1f74597e92) [## 认识熊猫最难的功能,第二部分

掌握交叉表的时间和方式()

towardsdatascience.com](/meet-the-hardest-functions-of-pandas-part-ii-f8029a2b0c9b) [## 认识熊猫最难的功能,第三部分

形状像果冻的桌子有熊猫旋转()和融化()

towardsdatascience.com](/shape-tables-like-jelly-with-pandas-melt-and-pivot-f2e13e666d6) [## 掌握连接:Pandas 合并、连接、追加方法

从半连接/反连接到验证数据合并

towardsdatascience.com](/masteriadsf-246b4c16daaf) [## 我习惯如何将数据与熊猫绑定

您可能只使用了默认值

towardsdatascience.com](/how-i-customarily-bin-data-with-pandas-9303c9e4d946) [## 来自 Kagglers:DS 和 ML 的最佳项目设置

来自顶级 Kagglers 的项目成功最佳实践的集合

towardsdatascience.com](/from-kagglers-best-project-setup-for-ds-and-ml-ffb253485f98)

遇见奇妙机器人

原文:https://towardsdatascience.com/meet-wondybot-ae5301261cf?source=collection_archive---------69-----------------------

梁杰森在 Unsplash 上的照片

这是一个软件开发人员如何构建聊天机器人来帮助管理股票投资组合的故事。由 LUIS、Bot Framework、Azure 等免费微软工具提供支持。

什么是奇妙机器人

简单来说,WondyBot 就是一个聊天机器人(不,真的)。我的梦想是创建一个聊天机器人,跟踪我的股票和股票投资组合,提醒我任何价格变化,给我公司的详细信息和新闻,分析和推荐新的潜在机会。关键是所有的功能都可以使用成熟的用户界面,比如 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 和 Facebook Messenger。

这个概念很好,令人兴奋,所以我直接开始工作。这是我的第一个错误。我试图创造所有的功能,完美的第一次。我浪费了太多时间瞄准最终产品,而不是把它作为一个学习平台。我开始创建一个能够做任何事情的后端 API,然后我陷入了困境,因为我既没有知识也没有经验知道聊天机器人应该如何端到端地工作。

我后退了一步;我着手进行概念验证(POF)。

WondyBot 1.0 (POF)

我想实现的第一部分是,根据要求,以电报形式返回公司简介。这包括 3 个关键要求:

  1. 允许与电报机器人通信。
  2. 理解用户的意图。
  3. 检索上市公司的市场数据。

1 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 可以让你创建一个免费的机器人,甚至不需要离开他们的应用程序,你所要做的就是和他们出色地命名为 的机器人父亲 "交谈。然后我利用 webhooks 和“ 电报创建了一个. Net 核心控制台应用程序。Bot " NuGet 包。我使用 这个演练 让我的 C#代码与我的电报机器人对话,创建了一个简单的 echo 机器人:

丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 Desktop(左)已经向命令行(右)发送了一条消息,在那里返回文本。作者图片

但是,本演练在尝试响应用户输入时使用了一组 IF/ELSE 语句。它给了我们一个起点,但是对用户来说会很痛苦,对开发者来说更是如此。

2 怎么才能绕过这个——进入路易斯 T5!这是微软的自然语言理解产品。外面有几个,其中一个是 IBM Watson 我的朋友( Stephen Chapendama )在他的无代码聊天机器人尝试中走了这条路,你可以在这里 阅读它

那么,路易斯是怎么工作的?机器学习、自然语言处理和自然语言理解的神奇结合。使用 LUIS,您可以训练您的应用程序理解用户的自然语言,然后将意图和任何实体返回给您。你必须生成一个模型,其中包括给它用户输入的例子,但从那时起,它就像触及一个端点一样重要。 这个视频 帮我搞定了 LUIS 的设置。

从 LUIS 端点返回的消息,包括意图(“GetCompanyDetails”)和实体(“companyName”)。图片作者。

正如你在上面看到的,LUIS 的回答是干净的(如果你已经用一个好的模型训练过它)。我们可以使用意图来调用一个方法,然后将实体作为变量传入。例如,像“ GetCompanyDetails ”这样的意图和像“ companyName ”这样的实体…

3 基于 这篇文章 ,我用 Finnhub 作为我的市场数据源。同样,您调用一个端点,API 返回一些数据,基本功能是免费的。我想返回一个更全面的公司简介,所以对公司详细信息的每个请求都涉及到对 Finnhub 的多次 API 调用。结合 Finnhub 数据和应用程序的其余部分,我可以生成以下输出:

我们如何通过 LUIS 和 Finnhub API 获取公司详细信息的示例。图片作者。

WondyBot 2.0 (MVP)

我们的 POC 通过运行本地控制台应用程序为我们提供了简单的功能,但我们可以做得更好,对吗?对于这一部分,我们希望构建一个最小可行产品(MVP),我们将遵循以下任务:

  1. 允许用户和机器人之间的对话。
  2. 将前端 Bot 和后端 API 分开。
  3. 云中的主机。

1 没有办法问后续问题,比如“你是说…?”。坚持微软的主题,我研究了他们的 Bot 框架 ,功能似乎非常适合。最大的吸引力之一是能够使用通道;处理与第三方应用程序(如 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨、Teams、Facebook Messenger)的所有连接。

最初的 微软的例子 对于 Bot 框架来说是如此容易直接在 Azure 中设置,不需要任何代码。然而,当谈到延长这一点,我不知所措。其他 微软示例YouTube 演练 甚至一个 Pluralsight 课程 都无法让我通过编写一个 Bot 框架应用程序。也许我会在以后重新审视这一点…

最终偶然发现了来自微软的 Bot 框架作曲 。这是一个无代码的解决方案,而且它有 LUIS 的内置功能,让你可以直接发布到 Azure。我按照 这个教程 让我在这里启动并运行。

转移到 Bot 框架意味着我能够干净地将我的关注点分开。我的意思是,我将原来的 Finnhub 功能重构为一个专用的 API,可以直接从 Bot 框架中调用。这与 MVC 架构有些相似之处,其中 M odel 是我们的专用 API,Vview 是 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 UI,Ccontroller 是 Bot 框架部分。

在我开发 API 的时候,我还添加了一种计算 Jaro-Winkler 距离的方法,使用了" F23。string similarity“nu get 包。这使得用户不必完全按照列出的那样输入公司名称,也不必处理任何拼写错误。

WondyBot 2.0 中 GetCompanyDetails 函数的数据流。作者图片

3 我对 Azure 的体验比较基础。令人欣慰的是,微软团队已经使得从 Bot Framework Composer 和 Visual Studio 直接发布到 Azure 变得非常容易。

当从 Composer 部署到 Azure 时,您需要在发布应用程序之前执行一些初始步骤。 这个演练 给你所有你需要的信息,不管你有没有 Azure 资源设置。

关于 API 到 Azure 的部署,在 Visual Studio 2019 内,可以设置连续部署。这使得部署代码更改变得快速而简单;您所要做的就是在源代码控制中提交您的主分支。对于这一部分,我的代码库在 GitHub 中,连接到 Azure DevOps 管道。这个来自微软的指南帮助了我。

尽管我在 Azure 中托管的所有东西都是免费的,但我在用默认设置设置资源时还是被发现了几次。如果你不确定,在你意外地积累了昂贵的账单之前,只需检查 Azure 中每个资源的服务计划。幸运的是,第一个月,微软会给你一些免费的学分。我的建议是,在这最初的一个月里,投入进去,尽可能多地玩。

完成所有这些步骤后,我就可以免费构建和托管这个 MVP 了。功能是基本的,但它确实完成了我们设定的目标:

向用户展示 WondyBot 的外观。图片作者。

接下来的步骤

WondyBot 的路线图是继续开发,增加额外的功能,如用户帐户和价格检查器。但是在我们看到这一点之前,我们需要解决当前机器人的一些问题。这些包括利用缓存来减少 FinnHub API 调用,以及为我们的。Net 核心 API。我将在接下来的几周内做出这些改变,随后会有帖子发布。

在这篇文章中,我们已经讲述了我如何制作我的第一个聊天机器人的基本步骤。在这篇文章中有很多链接,其中大部分都是有用的教程或例子,引导我到了这个阶段。我学到了很多,但我仍然觉得这只是第一步,我非常期待 WondyBot 的继续发展。

如果你正在尝试这样做,并且发现了一种新的或不同的做事方式,请在评论中告诉我们。

认识你新的最好的探索性数据分析朋友

原文:https://towardsdatascience.com/meet-your-new-best-exploratory-data-analysis-friend-772a60864227?source=collection_archive---------28-----------------------

来源: Unsplash

轻松创作,丰富见解

可视化通常在数据科学和模型构建过程中发挥最小的作用,然而探索性数据分析的创造者 Tukey 特别提倡大量使用可视化来解决数字指标的局限性。

每个人都听说过——也理解——一张图片等于一千个单词,按照这种逻辑,数据的可视化至少相当于几十个统计指标,从四分位数到均值到标准差到均值绝对误差到峰度到熵。哪里有丰富的数据,当它被可视化时就能被最好地理解。

探索性数据分析是为了调查数据而创建的,强调可视化,因为它提供了更多的信息。这篇短文将介绍可视化 EDA 中最有用的工具之一,以及如何解释它。

Seaborn 的pairplot是神奇的:最简单地说,它为我们提供了数据中单变量和双变量关系的丰富信息可视化表示。例如,考虑下面两个用一行代码sns.pairplot(data)创建的pairplot(第二个添加了hue=’species’作为参数)。

基于这些观察到的属性,有如此多的关于数据的信息需要收集,无论是分类的成功(类之间有多少熵/重叠)、特征选择过程的潜在结果、方差,还是模型的最佳选择。pairplot 就像是多维空间的展开。

通常,人们会止步于一行代码对图,但是通过多几行甚至几个字的代码,我们可以收获更多的信息和见解。

首先,pairplots 可能会变得非常大。要选择要显示的变量子集,使用vars参数,该参数可以设置为一个变量名列表。例如,sns.pairplot(data,vars=[‘a’,’b’])将只给出两列‘a’‘b’之间的关系,即aaabbabb。或者,可以指定x_varsy_vars(分别列出)作为每个轴的变量。

设置前两个图(设置vars参数)的结果是图的对称网格:

第三个图将 y 分量设置为仅一个变量‘sepal_length’,将 x 分量设置为数据的所有列。这将返回该列和所有其他列之间的交互。请注意,对于第一列(当它与自身配对时)和第五列(当它与分类变量配对时),散点图不是合适的图。我们稍后将探讨如何处理这个问题。

通过在你的 pairplot 中添加一个kind=’reg’关键字,你可以得到数据的线性回归拟合。这是对数据的线性度和方差的一个很好的衡量,可以决定选择哪种类型的模型,有监督的和无监督的。此外,由于成对图是对称的,为了 a)消除图的混乱和 b)减少长时间的加载时间,设置corner=True删除右上半部分,这是一个重复。

回归图—左侧,角图—右侧

然而,pairplot在简单直观地显示变量之间的关系方面能力相对有限。它仅仅是一个访问pairgrid的接口,T5 才是“pairplot背后真正的生成器。通过pairgrid正确处理可视化可以产生有价值的结果。

seaborn 中的网格被初始化为一个变量,最常见的是g(用于网格)。例如,我们可以写g=sns.PairGrid(data)。当网格被初始化时,它们完全是空的,但是很快就会被可视化填充。网格是一种以高效和简洁的方式访问和可视化数据的跨特征方面的方法。

我们可以使用映射方法用数据填充网格。例如,调用g.map(sns.scatterplot)用散点图填充网格。我们也可以传入模型的参数:在g.map(sns.kdeplot,shade=True)中,shade 是sns.kdeplot的一个参数,但是它可以在映射中指定。由于这是一个网格,所有的数据都被整理出来;我们只需要调用情节的类型。

注意对角线仍然是散点图。我们可以通过对不在对角线上的图使用g.map_offdiag(sns.scatterplot)和对在对角线上的图使用g.map_diag(plt.hist)来改变这一点。请注意,我们可以使用其他库中的绘图对象。

我们可以做得更好。由于上半部分和下半部分是相同的,我们可以使用g.map_upperg.map_lower改变上半部分和下半部分之间的绘图类型。在本例中,我们通过改变 seaborn 回归图中的order参数regplot,来比较二次回归和线性回归对相同数据的拟合。

要指定色调,我们可以将hue=’species’参数添加到 PairGrid 的初始化中。注意,我们不能做类似于g.map(sns.scatterplot, hue=’species’)的事情,因为映射只是数据的可视化,而不是数据的再处理。所有的数据都是在网格初始化时处理的,所以所有与数据相关的东西都必须在那时处理。

Pairgrids 通常用于构建复杂的图,但对于 EDA 而言,所涵盖的操作应该足够了。

通过多几行代码,您已经能够最大化从 pairplot 和 pairgrids 中获得的信息。这里有一些建议,可以让你从中获得尽可能多的洞察力。

  • 寻找可用于提高模型性能的曲率和变换(例如 Tukey 的幂阶梯)。
  • 根据功能在整行或整列中的表现来处理功能。例如,petal_widthpetal_length在沿着它们指定的轴分离类方面表现很好,在所有其他特性方面也很好。对于sepal_width来说就不一样了,在那里沿着它们的轴有很多重叠。这意味着它提供的信息更少,这可能是我们运行特征重要性的好理由,如果它在预测能力方面提供的提升可以忽略不计,则删除它。
  • 找出回归拟合中有多少数据点发生了变化(您也可以尝试不同的程度),以直观地了解数据的稳定程度。如果数据点与拟合相差很大和/或拟合程度必须很高才能很好地拟合数据,使用标准化或规范化等方法可能会有所帮助。
  • 花相当多的时间查看数据的可视化二元表示,玩比较和图表类型。你可以对你的数据做无数的操作,EDA 的目的不是给你答案,而是激发你采取特定行动的兴趣。数据每次都不一样;没有适合所有尺寸的标准程序。

文章正文中的所有数字均由作者创作。

感谢您的阅读,请在回复中告诉我您的想法!

如果你对最新的文章感兴趣,可以考虑订阅。如果你想支持我的写作,通过我的推荐链接加入 Medium 是一个很好的方式。干杯!

[## 大多数人都不知道的 5 个鲜为人知的海边小镇

但是真的应该知道

medium.com](https://medium.com/analytics-vidhya/5-lesser-known-seaborn-plots-most-people-dont-know-82e5a54baea8) [## 用一行代码彻底美化可视化效果:设计情节

制作吸引人的情节从未如此容易

medium.com](https://medium.com/analytics-vidhya/drastically-beautifying-visualizations-with-one-line-styling-plots-35a5712c4f54)

Mekko 图表

原文:https://towardsdatascience.com/mekko-charts-f38311c576e2?source=collection_archive---------39-----------------------

为什么和如何

图片由来自 Unsplash 的 Khara Woods 提供

有不同类型的可变宽度条形图,但有两种是最流行的:1)条形图;2) Marimekko 图。

它们在以下方面有所不同:T2 条形图 (BMc)像一个“标准”条形图,但它的条形是可变宽度的,而 T4 条形图 (Mc)像一个 100%堆积条形图,但它的条形是可变宽度的。

为什么:它们用于显示数据集中每个类别的两个数值变量;目标是在类别之间进行比较,而不是在数字变量之间。它们广泛用于仪表板或营销和销售演示中,其中的类别通常是产品、区域、部门、细分市场等。数字变量通常是销售额、利润、成本、利润、增长率等。它们不适合用于分布、关系或长期趋势分析。

如何:是一个类似于标准条形图的二维图形,矩形条通常以垂直方向排列。纵轴有一个数字刻度(在 Marimekko 图上为 100%),代表一个定量变量。横轴可以是数字,也可以是类别。如果是数字,每个矩形的宽度与第二个定量变量的值成比例,有不同的颜色和标识它的图例。如果是分类的,每个条形的宽度也表示第二个定量变量的值。

每个类别的矩形宽度通常不同。用数字或百分数表示横轴上的数值变量总是很方便的。这些值通常显示在上基线上。

与标准条形图不同,条形之间没有空间(注意不要将 Mekko 图与直方图混淆[https://towards data science . com/Histograms-why-how-431 a5 cfbfcd 5])。在 BMc 和 Mc 中,水平轴的整个宽度被占据

Mekko 条形图是传统条形图的替代产品,可让您减少商业演示中图表的数量。为了实现这一点,图表通过条形的高度对一个数字变量进行编码,通过条形的宽度对另一个数量变量进行编码。下图显示了 Mekko 条形图的示意图:数字垂直轴;带有可变宽度条形的水平轴,每个条形代表一个不同的类别。产品线、部门或区域是横轴上显示的类别示例。销售额、成本或利润可以是用矩形宽度表示的数字变量。

图 1:条形图的示意图。用 Vizzlo 创建,有权限(#1)。

Marimekko 图表是分组条形图的一种替代方法,可以减少商业演示中的数量:它们显示与主要类别中的子组或子类别相关的数字信息。因此,这种类型的可视化允许我们为每个类别和每个子类别显示两个数值。

它们通过将整个矩形区域分成更小的矩形来占据它。每个类别又分为由堆叠矩形表示的子类别。这些矩形中的每一个都对数据集的每个子类别的数值进行编码。它们在视觉上相当于堆叠条形图,除了具有不同高度的矩形段之外,我们现在还具有可变的条形宽度。

图表的垂直轴显示百分比刻度,而水平轴被标准化为占据图表的整个宽度,在条形之间不留任何空白。

图 2:marime kko 图。用 Vizzlo 创建,有权限(#1)。

图 2 在一张图中描述了一家公司的年收入,分为不同的品牌,以及对应于不同地区的百分比。可以看到 Marimekko 图的特征要素:一个矩形区域被分成宽度不同的较小矩形;垂直堆叠的矩形;占据图表整个宽度的水平轴;带有百分比刻度的垂直轴;最高基线上每个品牌的总收入;不同的条形宽度允许计算每个品牌对总收入的相对贡献。

单词来源:Marimekko 是一个芬兰纺织品牌,拥有大量多样的形状图案,以及简单明亮的颜色和风格(#2)。

警告:

条形图和 Marimekko 图都难以阅读和解释,因为它们基于受众通过比较区域来解码数字信息的能力。重要的是要记住,人类擅长评估距离,而不擅长计算面积。此外,随着矩形数量的增加,我们对不同区域进行适当比较的能力下降。

Marimekko 图和堆积条形图有同样的缺点:a)子类别的数量有一个实际的限制,超过这个限制可视化就变得困难了;b)最好的比较是在较低和较高基线附近的子类别之间进行。随着我们远离它们,子类别之间的差异变得很难评估。

小心重复使用 Mekko 图:记住矩形棒线非常“沉重”,是主要的视觉标记。

请注意,观众通常非常熟悉传统的条形图,但不熟悉可变宽度的条形图。如果您的演示中有 Mcs 或 BMC,请花些时间向观众解释它们的具体特点,以免影响故事的讲述。

Marimekko 图表不能显示负值,也不能将绝对值和相对值结合起来。

一些可视化工具允许您在垂直和水平布局之间切换。然而,在通常的实践中,使用垂直布局,因为水平布局会不必要地使故事讲述复杂化。

不要混淆 Mcs 和 spineplots 。从最严格的定义来看, spineplot 是一个一维的水平堆叠条形图,用于显示列联表(#3)中两个交叉分类的分类变量的频率、比例或百分比。出现这种混乱是因为一些 spineplots 可视化工具允许垂直方向,他们称之为马赛克图。该术语也被错误地归因于 Marimekko 图表,但应该保留给那些允许通过可变宽度矩形检查两个或更多分类变量之间关系的图表。

我没有在 Python 中找到允许直接绘制 Mcs 或 BMC 的绘图函数。一个堆栈溢出用户编写了一个策略,使用 Matplotlib 使用条形图绘制条形 Mekko 图,每个条形的宽度使用宽度参数(#4)单独修改。我对他的代码做了一些小的修改,得到了下图,一个非常接近条形图的图。

另一方面, statsmodels 的 12.0 版本允许从列联表(stats models . graphics . mosaic plot . mosaic)创建镶嵌图形。下图和绘制该图的代码可在 statsmodels 组织的以下页面中找到:

https://www . stats models . org/stable/generated/stats models . graphics . mosaic plot . mosaic . html

如下图所示,镶嵌图在水平轴和垂直轴上都显示了分类变量(#5):

总结:与 Mekko 图表相关的最重要的概念在于它们能够恰当地加权 一个数值变量的大小。传统条形图的所有变体(标准、分组、堆叠、重叠等。)对所有类别使用相同的条形宽度,因此只能通过单个数值变量的长度或高度进行比较。Mekko 图表中的变量宽度允许我们在一个图表中显示第二个数值变量的相对值。相比之下,它们的视觉效果较低:到达受众的编码信息的准确性和清晰度相对较低。

如果你对这篇文章感兴趣,请阅读我以前的:

"直方图,为什么&如何,讲故事,提示&扩展"

[## 直方图,为什么和如何

讲故事、技巧和扩展

towardsdatascience.com](/histograms-why-how-431a5cfbfcd5)

“关于条形图你需要知道的一切”

[## 条形图,为什么和如何

对于这种无处不在的图表类型,需要避免的基础知识、技巧和陷阱

medium.com](https://medium.com/nightingale/bar-graphs-why-how-8c031c224c9f)

参考文献

第一名:https://vizzlo.com/

2:https://en.wikipedia.org/wiki/Marimekko

3:福克斯,n .,“说 Stata: Spineplots 和他们的亲属”,Stata 杂志(2008),8,1 号,第 105-121 页

4:https://stack overflow . com/questions/57164333/matplotlib-bar-me kko-chart 中不同宽度和颜色的条形图

5:https://www . stats models . org/stable/generated/stats models . graphics . mosaic plot . mosaic . html

墨尔本 Datathon 2019 赢家乳品店

原文:https://towardsdatascience.com/melbourne-datathon-2019-winners-dairy-6b1ecf1d8c4d?source=collection_archive---------68-----------------------

作者照片

免责声明:这是一个关于“WeCane”在墨尔本数据马拉松比赛的旅程中分享的经验的过期博客。读者可以期望了解我在提交中成功采取的步骤。

去年我有一个目标:赢得墨尔本数据马拉松比赛。

我的第一个任务是建立一个伟大的团队:

一个伟大的团队是这样的:团队成员有实现共同目标的正确动机、互补的技能组合以及良好的沟通和信任。为了建立一个团队,我需要了解我能带来什么价值,以及我们作为一个团队获胜所需的技能。

我对自己的分析思维、解决问题的技能和商业敏锐度充满信心,这些都是通过在各种项目和不同行业中的工作积累起来的。

我知道我可以将一个业务问题组织成一个技术问题,并创建一个具有合适价值主张的产品线框。以我的研究背景,我确信我可以找到合适的机器学习方法来解决任何数据问题。

我寻找的补充技能是软件开发技能、精致的视觉设计技能和数据工程技能,这些都是构建一个伟大的产品所需要的。

我联系了我信任的人,非常幸运的是,我的团队中有雷倩、Rohan Kirpekar 和 Anh Phuong Tran。王乐天、萨蒂扬·库马尔和胡厅也是该团队的一员,在构思、研究和数据工程方面做出了一定的贡献。我还要特别感谢 Deepak Kumar Singh 和 Akshit Vijay,他们在产品开发过程中向我们提供了咨询和帮助。

队员介绍:

  • 雷,软件开发人员,有十二年产品开发经验。
  • Rohan 是一名经验丰富的技术顾问,拥有计算机科学背景。
  • Anh 是一名热衷于数据可视化的数据分析师。
  • 乐天是一名有心理学背景的数据工程师。
  • Satyam 是一名热情的数据分析师,有许多创造性的想法。
  • Ting 是一名商业分析师,拥有解决问题和提供咨询的经验。

有了正确的团队和祝福我们的朋友的支持,我非常有信心我们拥有获胜的所有必要因素。

第二步是确定具体的问题陈述并设计解决方案

这部分是最让我兴奋的,因为我喜欢创造性地解决问题。我对处理新问题和研究任何可能的解决方案感到非常兴奋。给我们的问题陈述是构建一个使用时空数据(卫星数据)的应用程序,帮助昆士兰的甘蔗农。澳大利亚 95%的糖产于昆士兰州,甘蔗是仅次于小麦的第二大出口作物,为澳大利亚经济贡献了 25 亿美元。成长数据和 ANZ 银行是这份出色的问题陈述的设计者。

我喜欢这个问题陈述,因为我从事过卫星图像处理的工作,利用数据科学革新农业是我一生的使命。

没有太多的延迟,我们的团队开始工作;在我们最初的几次会议中,我们完全致力于构思和思考我们可以为农民或银行家建立的可能的解决方案。

我们尝试了各种想法,从土地剖面监测到依赖天气预报的产量计算。

只是在进行市场调查后,我们遇到了农业融资没有固定指导方针的主要问题,这导致银行的运营成本高,农民的贷款审批延迟。到 2024 年,全球糖需求预计将达到 1.996 亿吨。因此,为了满足日益增长的需求,向甘蔗种植者提供适当的融资至关重要。因此,我们的目标是建立一个解决融资问题的产品。

我们决定结合预测收益估计和贷款风险估计这两个想法来为解决方案应用程序创建 MVP。

作者照片

第三步弄脏(脏)数据

现在我们进入文章中数据科学有趣的部分。我不知道你是否曾经处理过卫星数据,但这是一种与任何其他数据格式完全不同的体验,你有图片,你有时间,然后你有云。那些该死的云,我们花了前两个月的大部分时间来识别和清除这些云,以创建一系列无云的图像,可用于产量预测。

我们首先用 python 从头开始创建云检测和移除的代码,进展并不顺利。在我们谷歌 StackOverflow 上的调试过程中,我们发现了令人难以置信的 python 库‘Sentinal Hub’。该库一手将我们的测试和原型制作时间减少了 10 倍。在找到这个库之前,我们面临着在我们的吝啬鬼笔记本电脑上处理大量高维数据的问题。我们还升级到使用 Colabs 免费 GPU,以减少实验不同设置的云检测和删除算法的时间。

在尝试了各种技术一段时间后,我们开始看到高质量的结果可以释放图像。下一步是将图像转换成用于建模的面板数据序列。

与此同时,我们不得不筛选出那些已经收获甘蔗的地区。因此,我们使用种植数据提供的代码来生成甘蔗掩膜,并且只使用 sentinal two 卫星所有波段的两年数据作为我们建模的输入数据。

为了提高产量预测的准确性,我们将每个卫星数据切片分成更小的 8x8 立方体,并存储像素和波段信息及其坐标。

雷是这个问题建模部分的主要负责人。她尝试了线性回归和 Arima 等经典回归模型,后来又尝试了 xgboost 和 Random forest 等决策树模型。

每种建模技术的性能:

1.)Arima 没有意识到数据的复杂性

2.)基于样条的线性回归—低估且无法确定数据结构的复杂性

3.)Xgboost —表现优于 Arima 和线性回归,但总是低估

4.)随机森林—能够了解数据结构的复杂性,预测值接近真实值

请参见下面我们解释建模实验和结果的演示:

Prezi 演示文稿嵌入|由作者创建

使用 2016-2017 年数据训练模型并测试 2018 年的实际产量,比较了预测的准确性。当模型的准确性在合理的误差范围内时,我们停止了进一步的实验。然后使用相同的建模技术在 2017-2018 数据集上训练模型,以预测 2019 年的值。

第四步工具设计和开发

我不会深入讨论这一部分的细节,但我可以给出我们在开发该工具时遵循的基本设计架构:

数据源(Sentinal hub)——如前所述,数据来自 Sentinal hub

Flask API(后端)—我们决定使用 flask API,因为所有的处理和分析都是在 python 中完成的,并且便于集成

HTML、Javascript、CSS(前端)

Heroku(部署)-原型应用的简单部署

要查看该工具的实际运行情况,请单击下面的链接

【https://sugarcaneapp.herokuapp.com/loan 号

第五步演示

来到决赛阶段是一个很大的荣誉,因为有这么多有才华的参与者的美丽作品。我非常钦佩我们决赛选手的创造力。

介绍分为两部分。一个是制作一个 5 分钟的视频来解释该工具,另一个是 10 分钟的演示来解释该工具的优点以及我们是如何构建该工具的。我们在一天前聚在一起练习我们的最后一次演讲,这很棒,尽管在演讲前的最后几分钟有些紧张,但我很高兴我们的表演完美无瑕。我要再次感谢我的团队成员雷、Anh 和 Rohan,感谢他们的辛勤工作和坚持不懈。

https://www.youtube.com/watch?v=W9-CfppFx7g

希望你喜欢这篇长文,并为你明年的数据马拉松参赛作品提供一些想法。

最后,我们仍在努力改变农民的生活,如果你感兴趣,请联系我们。迪帕克·辛格和我正在进行“Krishiguru”项目,我们的目标是提供可以用于农业部门更好决策的见解。

你可以在 https://www.facebook.com/KrishiGuruIndia 的脸书页面找到我们:。

相关阅读:

数据通指南

墨尔本数据通网站

第一名获奖者博客

迷因视觉:对迷因进行分类的科学

原文:https://towardsdatascience.com/meme-vision-framework-e90a9a7a4187?source=collection_archive---------36-----------------------

图像识别并不总是需要神经网络;使用更简单的模型可以实现效率和准确性

以电视节目中的角色为特色的迷因,在公平使用原则下,出于教学目的在此复制是允许的

作为一个文化和科学的人,我决定建立一个识别迷因的模型。这个问题比图像网竞赛简单得多,因此一个更简单的解决方案是合适的。我将通过比较“Meme Vision”框架和ResNet-50(2015 年 Image-Net 的获胜者)来证明这一点。

方法:模因愿景框架

在以前的文章中,我解释了径向直方图方法;

[## 径向颜色直方图

当颜色、构图和计算对你的计算机视觉问题都很重要时——径向减少表示…

towardsdatascience.com](/radial-color-histograms-a3ab0441516)

(TL;DR —它测量图像每个部分的颜色分布)

下面我们来看看这是如何将图像缩小到非常低的维度的。

基本径向颜色直方图示例,每个颜色通道有 3 个面元和 4 个段(给出 4*3 =108 个特征)

最终的迷因愿景模型使用了几个额外的步骤:

  • 从 RGB 转换到 HSV-当在 HSV 调色板中查看时,颜色退化对计算机来说不是问题。
  • 像素计数的对数转换有助于关注细微差异。
  • 每个通道使用 8 个箱(而不是 3 个)来区分相似的颜色阴影,这将产生 2048 个特征(而不是 108 个)。
  • 将这些特征馈入线性支持向量机。

如何制作和测试你自己的 MemeVision 模型

使用此程序包处理的径向颜色直方图特征。(下面用于比较的 ResNet-50 传输是使用 Tensorflow 实现的)。

结果:Meme Vision vs ResNet-50 转移

将 Meme Vision 的性能与基于 ResNet-50 的神经网络进行比较(仅训练最后一层 80 个时期)。所使用的数据集由 115 个标签下的 5716 个模因组成 —我们只使用 20%进行训练,其余的作为测试集。

毫不奇怪,在迷因愿景框架下,训练和预测的速度要快几个数量级。准确性的差异并不重要,如果让神经系统训练更长时间,它肯定会胜过迷因视觉。

数据集:

[## 迷因的分类和标签

从 Reddit 抓取图像和元数据,然后使用图像识别进行分类

www.kaggle.com](https://www.kaggle.com/gmorinan/memes-classified-and-labelled)

结论:重点是什么?

首先,如果你在一年时间里从 Reddit 抓取了 40 万张图片(像我一样),然后使用 meme Vision 模型对每个 Meme 进行分类(像我一样),然后交叉引用与每个图片相关的元数据(像我一样),那么你就能够计算出每个 Meme 随着时间推移的相对受欢迎程度(见下文)。我的下一篇文章将更深入地研究这种迷因流行度分析的结果,以及一个具有重大文化意义的惊人发现。

其次,也是这篇文章的重点,如果我开始使用一个更复杂的模型,我所做的事情会更难。不可否认,在一些困难的边缘情况下,需要一个神经网络来识别一个迷因(例如,迷因被转换成黑白的)。但迷因愿景的要点是速度——它可以用来快速采摘所有低垂的果实,将困难的案例留给更强大、更昂贵的模型。

所以下次你遇到问题时,你的第一个想法是考虑实现由 Geoffrey Hinton(深度学习的教父)设计的胶囊网络……也许停下来想一想“我的问题真的像 Geoffrey Hinton 正在解决的那样复杂吗?”。

这与我在 机医科技 的工作无关。

Python 中的记忆化

原文:https://towardsdatascience.com/memoization-in-python-57c0a738179a?source=collection_archive---------1-----------------------

记忆入门

来源

记忆化(Memoization)是唐纳德·米基(Donald Michie)在 1968 年引入的一个术语,它来自拉丁语单词备忘录(要记住)。记忆是计算机科学中使用的一种方法,通过存储(记住)过去的计算来加速计算。如果使用相同的参数进行重复的函数调用,我们可以存储以前的值,而不是重复不必要的计算。在这篇文章中,我们将使用记忆化来寻找斐波那契数列中的项。

我们开始吧!

首先,让我们定义一个递归函数,我们可以用它来显示斐波纳契数列中的第一个 n 项。如果你对递归不熟悉,可以看看这篇文章:Python 中的递归

提醒一下,斐波纳契数列是这样定义的,每个数字都是前两个数字的和。例如,斐波纳契数列的前 6 项是 1,1,2,3,5,8。我们可以将递归函数定义如下:

def fibonacci(input_value):
    if input_value == 1:
        return 1
    elif input_value == 2:
        return 1
    elif input_value > 2:
        return fibonacci(input_value -1) + fibonacci(input_value -2)

这里我们指定了基本情况,即如果输入值等于 1 或 2,则返回 1。如果输入值大于 2,则返回对前两个斐波那契值求和的递归函数调用。

现在,让我们打印前 10 个术语:

for i in range(1, 11):
     print("fib({}) = ".format(i), fibonacci(i))

这似乎运行良好。现在,让我们尝试显示前 200 个术语:

for i in range(1, 201):
     print("fib({}) = ".format(i), fibonacci(i))

我们将会发现,在 fib(20)之后,后续计算将会比之前的计算花费更长的时间。这是因为每次后续计算我们都在做重复的工作。

考虑递归函数如何计算每一项:

纤维(1) = 1

纤维(2) = 1

纤维(3) =纤维(1) +纤维(2) = 2

纤维(4) =纤维(3) +纤维(2) = 3

纤维(5) =纤维(4) +纤维(3) = 5

注意,对于 fib(5 ),我们重复 fib(4)和 fib(3)的计算。如果我们有办法在计算时记住/存储这些值,我们就会避免重复计算。这就形成了记忆法的动机。

现在让我们浏览一下实现记忆化方法的步骤。为了继续,让我们初始化一个字典:

fibonacci_cache = {}

接下来,我们将定义记忆函数。首先,我们检查作为字典键的输入是否存在于字典中。如果键存在,我们返回对应于输入/键的值:

def fibonacci_memo(input_value):
        if input_value in fibonacci_cache:
            return fibonacci_cache[input_value]

接下来,我们定义基本案例,它们对应于前两个值。如果输入值是 1 或 2,那么我们将该值设置为 1:

def fibonacci_memo(input_value):
    ... if input_value == 1:
        value = 1
    elif input_value == 2:
        value = 1

接下来,我们考虑递归情况。如果输入大于 2,我们将该值设置为等于前两项之和:

def fibonacci_memo(input_value):
    ...
    elif input_value > 2:           
        value =  fibonacci_memo(input_value -1) + fibonacci_memo(input_value -2)

最后,我们将该值存储在字典中并返回该值:

def fibonacci_memo(input_value):
    ...
    fibonacci_cache[input_value] = value
    return value

完整的功能是:

def fibonacci_memo(input_value):
    if input_value in fibonacci_cache:
        return fibonacci_cache[input_value]
    if input_value == 1:
            value = 1
    elif input_value == 2:
            value = 1
    elif input_value > 2:           
            value =  fibonacci_memo(input_value -1) + fibonacci_memo(input_value -2)
    fibonacci_cache[input_value] = value
    return value

现在,让我们尝试用新函数显示前 200 个术语:

for i in range(1, 201):
     print("fib({}) = ".format(i), fibonacci_memo(i))

在运行我们的脚本时,我们看到我们相当快地到达了序列中的第 200 项。

有一种更简单的方法可以用更少的代码实现记忆化。让我们考虑一下我们最初的递归函数:

def fibonacci(input_value):
    if input_value == 1:
        return 1
    elif input_value == 2:
        return 1
    elif input_value > 2:
        return fibonacci(input_value -1) + fibonacci(input_value -2)

我们可以从“functools”模块导入一个名为“lru_cache”的装饰器,它允许我们缓存我们的值。该名称代表“最近最少使用的缓存”。使用这个装饰器,我们可以获得与‘Fibonacci _ memo’方法相同的性能:

from functools import lru_cache[@lru_cache](http://twitter.com/lru_cache)(maxsize = 1000)
def fibonacci(input_value):
    if input_value == 1:
        return 1
    elif input_value == 2:
        return 1
    elif input_value > 2:
        return fibonacci(input_value -1) + fibonacci(input_value -2)for i in range(1, 201):
     print("fib({}) = ".format(i), fibonacci(i))

我们看到我们实现了相似的性能。我就讲到这里,但是我鼓励你自己去研究代码。

结论

总之,在这篇文章中,我们讨论了 python 中的记忆方法。首先,我们展示了在计算斐波纳契数列中的许多项之后,递归函数的简单实现是如何变得非常慢的。然后,我们定义了一个新方法,在这个方法中,我们将过去计算的值存储在一个字典中。这导致了计算的显著加速。然后我们讨论了“lru_cache”装饰器,它允许我们用更少的代码实现与“fibonacci_memo”方法相似的性能。如果你有兴趣了解更多关于记忆化的知识,我鼓励你去看看苏格拉底的 YouTube 教程。我希望你觉得这篇文章有用/有趣。这篇文章中的代码可以在 GitHub 上找到。感谢您的阅读!

Python 中的内存管理和垃圾收集

原文:https://towardsdatascience.com/memory-management-and-garbage-collection-in-python-c1cb51d1612c?source=collection_archive---------2-----------------------

伯纳德·赫曼特在 Unsplash 上的照片

引用计数和分代垃圾收集

如果您在学习 Python 时有以下问题,那么您就来对地方了:

  • Python 中是如何管理内存的?
  • 什么是垃圾收集?
  • 哪些算法用于内存管理?
  • 什么是循环引用?
  • Python 对象是如何存储在内存中的?

让我们看看我能否回答这些问题以及本文中的其他问题:

我从基础开始。

Python 是一种动态类型语言。

当我们在 Python 中给变量赋值时,我们不声明变量的类型。它说明了程序运行时变量的种类。其他语言,如 C、C++、Java 等..在给变量赋值之前,有一个严格的变量声明。

正如你在下面看到的,我们只需要给一个对象分配一个变量,Python 就会检测这个对象的类型。

Python 动态检测对象的类型。图片由作者用 Canva 制作

Python 对象是如何存储在内存中的?

在 C、C++和 Java 中,我们有变量和对象。Python 有名字,没有变量。Python 对象以名称和引用的形式存储在内存中。名称只是一个对象的标签,所以一个对象可以有多个名称。引用是指向一个对象的名称(指针)。

每个 Python 对象都有三样东西。

Python 对象有三样东西:类型、值和引用计数。当我们给一个变量命名时,它的类型会被 Python 自动检测出来,正如我们上面提到的。值在定义对象时声明。Reference count 是指向该对象的名称数。

每个 Python 对象都有三样东西。图片由作者用 Canva 制作

垃圾收集:

垃圾收集是在对象不再使用时释放内存。这个系统销毁未使用的对象,而为新对象重用它的内存槽。你可以把这想象成电脑中的回收系统。

Python 有一个自动化的垃圾收集。它有一个算法来释放不再需要的对象。Python 有两种方法从内存中删除不用的对象。

1.引用计数:

引用总是被计数并存储在内存中。

在下面的例子中,我们将 c 赋值为 50。即使我们赋一个新的变量,对象是一样的,引用计数增加 1!因为每个对象都有自己的 ID,所以我们打印对象的 ID 来查看它们是相同还是不同。

图片由作者用 Canva 制作

当我们像下面这样改变 a 的值时,我们创建了一个新对象。现在, a 指向 60,bc指向 50。

当我们将 a 改为 none 时,我们创建了一个 None 对象。现在前面的整数对象没有引用了,它被垃圾回收删除了。

我们将 b 分配给一个布尔对象。之前的整数对象没有被删除,因为它仍然有一个被 c 引用的对象。

图片由作者用 Canva 制作

现在我们删除 c 。我们将对 c 的引用计数减一。

图片由作者用 Canva 制作

如上所述, del() 语句并没有删除对象,它删除了对象的名字(和引用)。当引用计数为零时,对象被垃圾回收从系统中删除。

参考计数的商品和次品:

通过引用计数进行垃圾收集有优点也有缺点。比如容易实现。程序员不必担心删除不再使用的对象。但是,这种内存管理对内存本身是不利的!该算法总是计算对象的引用数,并将引用数存储在内存中,以保持内存的清洁,确保程序有效运行。

到目前为止,一切看起来都很好,但是…

有问题!

引用计数垃圾收集中最重要的问题是它在循环引用中不起作用。

什么是循环引用或引用循环?

这是一种物体指向自身的情况。最简单的循环引用是将一个列表附加到自身。

最简单的循环引用。图片由作者用 Canva 制作

单独的引用计数不能销毁具有循环引用的对象。如果引用计数不为零,则不能删除该对象。

这个问题的解决方案是第二种垃圾收集方法。

2.分代垃圾收集:

分代垃圾收集是一种基于跟踪的垃圾收集。它可以中断循环引用并删除未使用的对象,即使这些对象是自己引用的。

分代垃圾收集是如何工作的?

Python 跟踪内存中的每个对象。程序运行时会创建 3 个列表。第 0、1 和 2 代列表。

新创建的对象放在第 0 代列表中。为要丢弃的对象创建一个列表。检测到参考周期。如果一个对象没有外部引用,它将被丢弃。在此过程后幸存的对象被放入第 1 代列表中。相同的步骤适用于第 1 代列表。第 1 代列表中的幸存者被放入第 2 代列表中。第 2 代列表中的对象会一直保留在那里,直到程序执行结束。

分代垃圾收集。图片由作者用 Canva 制作

结论:

Python 是一种高级语言,我们不必手动进行内存管理。Python 的垃圾收集算法对于打开内存空间非常有用。垃圾收集在 Python 中以两种方式实现:引用计数和分代。当对象的引用计数达到 0 时,引用计数垃圾收集算法会立即清理该对象。如果你有一个循环,引用计数没有达到零,你等待分代垃圾收集算法运行并清理对象。虽然程序员不需要考虑 Python 中的垃圾收集,但是理解幕后发生的事情是很有用的。

希望我能回答文章开头的问题。对于您找不到答案的问题:

延伸阅读:

  1. Python 中的可变和不可变对象。

这里的是一篇冷门却很棒的媒体文章

2.如何理解 Python 中的变量?

这里是一篇关于元组的有趣文章。

3.本地和全局命名空间。

这里是来自 realpython.com 的详细解释

4.跟踪垃圾收集。

这里的是指向“基于轨迹的算法”的维基百科链接。

5.堆栈和堆内存。

这里是 geekforgeeks 对“变量如何存储”的解释。

联系我

如果你想了解我的最新文章,请在 Medium 上关注我。你可以在 LinkedIn 上与我联系,并在seymatas@gmail.com 给我发电子邮件!

非常感谢您的任何建议和意见!

精神疾病和大脑动力学

原文:https://towardsdatascience.com/mental-illness-and-the-dynamics-of-the-brain-cb41033fb650?source=collection_archive---------31-----------------------

神经网络如何帮助发展精神病学

由 Unsplash 上的萨莎·弗里明德拍摄的照片

我想我们现在都知道大脑是一个复杂的物体。

它由 800 亿个神经元连接而成,突触连接的数量惊人(估计有一千万亿个,这个数字太大了,隐喻已经没什么用处了)。每个突触都有自己复杂的子结构,信号从全身各处传入,各种化学物质四处漂浮,改变了传入信号的处理和重定向方式,不同的区域相互抑制和刺激,以在决定它们构成的人类的行为和感觉方面占据上风。

像大脑这样复杂的系统必须处理似乎无穷无尽的不同而复杂的任务,并且配备了如此大量的参数(突触连接、神经递质水平、外部刺激的结构、来自身体的感觉、短期和长期记忆),这些参数必须平稳地相互作用以保证系统的功能,很明显,很多事情都可能出错。

当复杂性大量存在时,复杂的问题必然会出现。

此外,考虑到大脑是由进化的幻想虚构出来的,而不是由聪明的工程师以自上而下的方式建造的(就像计算机或智能手机一样),新的大脑区域似乎是随机出现的,旧的区域被重新发挥功能以服务于新的目的,令人惊讶的是它的工作效果如此之好。

心理健康问题

越来越清楚的是,心理健康是一个非常重要的话题,而且它不会很快消失。据估计,在 T4,40%的人(在现代西方社会)会有心理健康问题,需要在一生中接受治疗。随着美国抑郁症发病率、阿片类药物致死率和自杀率的上升,预期寿命在很长一段时间内首次下降,这是一个无可回避的话题。

在我更深入地探讨这个问题之前,有一个警告:在适当理解精神疾病的原因时,有一条微妙的线要走,我认为我们的社会在很大程度上没有做到这一点。传统上,心理健康问题的原因与大脑没有太大关系。人们被认为被邪恶的灵魂和魔鬼所控制。有时他们被指责为缺乏品格(就像第一次世界大战中成千上万因怯懦而被处决的饱受炮弹惊吓和精神创伤的士兵一样)或缺乏职业道德,等等。

现在我并不支持对许多精神疾病如抑郁症的纯机械论观点。正如约翰·哈里的《失去的联系》中所述,一个人抑郁可能有许多不同的原因,可能是现代社会越来越孤立,缺乏远见,创伤或悲伤没有得到处理。精神病发作同样与发病前的创伤事件密切相关。在某些情况下,精神“疾病”自然会出现(参见关于“丧亲排除”的争议),而将一切归咎于功能失调的大脑太容易了,是忽略了大脑背后的人的心理方面和情况。

但在其他情况下,我认为同样清楚的是,心理学的观点是没有用的,或者说并不总是找到正确治疗方法的最佳角度,至少一些精神疾病可以用大脑本身的功能障碍来最好地解释。治愈一个人的最佳方法是像对待任何其他疾病一样看待一种精神疾病:找出问题的生理根源,找到恢复健康功能的最佳干预措施,并通过药物或治疗手段应用这种干预措施。

大脑是一个动力系统

让我们从两个核心假设开始:

  1. 大脑是一个复杂的动力系统,伴随着所有的困难。
  2. 神经动力学是大脑的计算语言。在大脑的动态、它执行的计算和它的涌现行为之间有一种因果关系。因此,动力系统的特性与认知有着内在的联系。

非线性动力系统伴随着一些反直觉的,难以预测的效应,这些效应是由许多相互作用的反馈回路引起的。这意味着,如果我们真的想对大脑中发生的事情进行建模,我们需要建立非线性动力学模型,这些模型可以捕捉非线性神经动力学效应,如神经元尖峰脉冲、群体振荡(alpha/beta/gamma…)、相位编码(通过相对于相位移动信号来编码信息)、混沌活动模式,甚至只是随时间变化的行为。进一步值得注意的是,不仅网络动力学是动力系统,而且每个单独的神经元都可以被视为其自身的动力系统(参见霍奇金-赫胥黎模型),因此动力学在大脑的所有尺度上都起作用(单个神经元、几个神经元、大脑区域之间、在整个大脑的尺度上……)

天气是复杂非线性动力系统的另一个流行例子(混沌理论被洛伦兹有效地发现,试图模拟天气)

这一切听起来非常复杂,但我们没有选择:很可能大脑中的许多功能障碍都与改变的大脑动力学有关,所以如果我们想了解疾病,我们需要了解动力学。

幸运的是,机器学习提供了一些有前途和可扩展的方法来帮助我们建立非线性动态模型。

递归神经网络

递归神经网络(RNNs)是人工神经网络(ann)的一个亚型,由一组称为神经元的连接的有向单元形成。这些神经元可以根据各自连接的强度相互连接并传递输入。然后,该单元的输入之和通过激活函数运行,以给出其输出。

rnn 还包括时间序列,允许它们通过在单元之间通信来展现动态。rnn 并不局限于建模大脑:可以证明它们是动态通用的,这意味着它们可以在非常一般的条件下 模拟任何其他动态系统 。我已经更详细地描述了它们的近似能力有多强:

* [## 递归神经网络的力量

…以及它们如何让我们在给定正确数据的情况下学习几乎任何动态系统

towardsdatascience.com](/the-power-of-recurrent-neural-networks-1ef056dae2a5)

这使它们成为研究一般动力系统的有力工具。为了更好地理解这是如何工作的,让我们看一个简单的例子。

Hopfield 网络

Hopfield 网络是 RNN 的一个非常简单的版本,由 John Hopfield 在 1982 年推广开来。

它由一组二元阈值单元组成,这些单元都用权重 w_ij 相互连接,权重可以是正的(兴奋性),也可以是负的(抑制性)。可以被认为是要么发射要么不发射的神经元(每个单元要么具有值“1”要么具有值“0”,因此得名二进制单元)。

它们的放电取决于通过所有其他神经元流入它们的输入是否超过它们的阈值。整个网络的状态由神经元列表来表征,这些神经元具有相应的数字 1 或 0 编码,如果它们正在放电或不放电(假设对于四个单元,它可能是 0010)。

当神经元相互“交谈”时,它们的激活会随着时间而变化(因此对于下一个时间步,网络的激活可以用 0100 来表征,然后是 1100,依此类推)。

Hopfield 网络中的学习

照片由 Jordane Mathieu 在 Unsplash 上拍摄

混合着面包屑的热乎乎的液体刚接触到我的味觉,我就打了一个寒颤,我停下来,全神贯注于正在发生在我身上的不寻常的事情[……]突然,记忆显露了出来。味道是周日早上在康布雷,当我去她的卧室向她说早上好时,我的阿姨 Léonie 给我的一小块玛德琳,先在她自己的一杯茶或 tisane 里蘸一下。在我品尝它之前,小玛德琳的景象没有让我想起任何事情。全都来自我的一杯茶。
马赛尔·普鲁斯特对时间的研究

关于 Hopfield 网络的巧妙之处在于,它们形成了一个非线性动态系统,该系统总是收敛于 稳定吸引子状态,即它们的动态不再随时间变化的状态。

这意味着,例如,在运行一段时间后,网络永远保持在 1100,单元 1 和 2 启动,单元 3 和 4 不启动。

Hopfield 网络的一个很酷的地方是,你可以教它们根据你开始时的某个初始状态(比如模式 0101)收敛到一个期望的最终状态。当学习模式时,Hopfield 网络节点通过一组学习规则递增更新。这些学习规则可以相当简单: 赫比学习 【一起放电的神经元】可以用来训练一个 Hopfield 网络。

网络在训练期间进入的吸引子状态然后与网络被训练的输入模式相关联。这意味着你可以有效地 在网络的动态中存储信息 (可以存储的不同模式的数量与网络的规模成比例)。更好的是:在训练阶段之后,我们可以向网络“展示”它所学习的 (更多细节在此)模式的一个 不完整版本,并且它仍然设法 恢复相同的吸引子状态

如果这还没有让你想起什么(呵呵),这有点像 联想记忆 。想象在人群中瞥见一张脸,闻到一股熟悉的气味。

就像普鲁斯特著名的玛德琳的形象一样,整个记忆世界被一个微妙的线索重新激活(这也让你想起 30 秒前你看到了一张玛德琳的照片)。

能源景观

从物理学的角度来看,我们可以认为有一个描述网络所有可能状态的能量图。

Hopfield 网络的能量函数(物理学家可能会非常高兴地注意到,这与伊辛模型哈密顿量极其相似)。

网络的能量景观由学习过程以这样的方式形成,即最终状态对应于该景观的最小值。想想另一个简单的动力系统:一个球在一片丘陵和山谷中滚动。过了一段时间,当球的速度用尽时,它会停在谷底。根据球的起始位置,它会在一个局部最小值中结束。 这个谷(=吸引子),基于起点,就是网络记得的。

网络在训练期间通过的能量景观。由 SA 记入 Mrazvan22 / CC

在更复杂的景观中, 几个亚稳态最小值可以共存 。在 嘈杂的系统 中,如大脑,总有一些能量流入流出(这样球会不断地摆动),这些通过跃迁概率连接起来(这有点像量子阱势中的隧道,其中物体可能突然看起来从一个山谷“跳跃”到另一个山谷),这取决于能量景观的形状及其山谷的深度/浅度。

这个网络在能源格局中“滚动”,直到达到最小值。照片由 Waranont (Joe) 在 Unsplash 上拍摄

所有这些关于能量景观和吸引子的讨论可能看起来过于抽象,但我认为它们提供了一个相对直观的例子,说明大脑可能如何使用网络动力学进行编码。正如我们将看到的,它们与实际的认知功能有关:像不动点和线吸引子这样的神经网络的吸引子状态被认为在工作记忆中起作用,并且与海马中的模式完成有关,并且也被用于建模,例如决策。应该注意的是,如果你以一种聪明的方式塑造吸引子的景观,原则上你也可以实现复杂的思想或行为序列。

令我着迷的是,在机器学习和神经科学的交汇处,非常抽象的概念如何通过应用于我们自己的大脑如何工作的问题而突然变得易于理解。

精神疾病和网络动力学

现在让我们回到正在讨论的话题,从动力系统的角度考虑什么样的神经功能和结构异常可能是精神疾病的基础。

网络的能量景观,以及因此其吸引物盆地的浅度由网络参数调节。网络参数的神经科学等价物是受体密度、神经递质水平、随机通道状态转换等…

因此,改变它们就改变了吸引子的动力学,从而改变了 认知功能 。例如,多巴胺 D1 水平被认为增加了吸引子 的 稳定性,而多巴胺 D2 则是 做着相反的 。因此,多巴胺可以在认知灵活性和工作记忆和目标定向之间进行调节,认知灵活性由平坦的吸引子盆地支持,吸引子盆地使状态之间的移动变得容易,因此,在认知表征之间移动,工作记忆和目标定向通过将认知状态保持在深盆地中来保护它们。

让我们自己的网络动力学跳跃到更有雄心的思路,从长远来看,我们可能会发现如何将网络属性与个性类型和涌现现象联系起来,如创造性思维。这也可以被带入贝叶斯大脑假说的背景中,其中能源景观中盆地的深度与源于对世界的高级信念的预测精度相关(甚至可以帮助解释为什么迷幻药在治疗精神疾病方面显示出前景)。

例如,如果多巴胺能调节出现问题,认知功能会发生什么?

在精神分裂症中,多巴胺能功能在大脑的某些部分被强烈改变。非常平坦的山谷,可以适度地鼓励创造性思维和认知灵活性,在病理情况下会导致几乎完全由噪音驱动的漫无目的的思想漫游,甚至导致幻觉。**

已经调查了其他例子:这篇论文指出了 OCD(强迫症)中的强迫观念和强迫行为与过度深层吸引器之间的联系,这可能是由异常高的谷氨酸水平引起的。

一些精神疾病的特征是看起来不可能“接近”一个人,通过外部干预和刺激改变他或她的精神状态。我们可以再次从吸引子状态的角度来考虑这个问题:如果 大脑的动态状态被困在相当于马里亚纳海沟 的神经底部,那么需要很大的努力才能再次从那里出来。

从网络动力学的角度来看,可以有效地研究的精神疾病的列表很长,包括广泛传播的问题,如 ADHD 、抑郁期间的沉思或 PTSD、,在所有这些问题中,吸引子动力学在某种程度上被推出了健康且功能良好的平衡。

这对治疗意味着什么

所有这一切不仅有趣,而且对治疗具有重要意义:如果我们理解了导致疾病的动力学变化,这可能会开辟全新的途径,以改变网络参数为基础进行有时天真地违反直觉的干预,从而恢复相关的动力学。

例如,由 D2 受体亲和力引起的改变可以通过改变突触钠电流来进行修正,就像直接处理多巴胺受体一样有效,而从药理学的角度来看,这些类型的 干预可能更简单、更便宜

精神健康方面的一个问题是,许多药物都是以一种暗箱操作的方式服用的(以非常受欢迎的锂为例,这种药物已经使用了 50 年,没有人真正知道它为什么有效)。

拥有问题的实际 因果模型 总是一个好主意,因此我们可以闭环到大脑活动的递归神经网络模型:虽然我们需要注意构建过于简单的模型,但从大脑数据(如 fMRI、EEG 或尖峰脉冲串)中学习神经网络模型以提取其潜在的动力学是朝着更深入地理解问题的动力学根源迈出的有希望的一步,为更有效的治疗铺平了道路。

诊断和预后

照片由欧文比尔德在 Unsplash 拍摄

最后,神经网络不仅有助于对大脑本身进行建模,还可能以不同的方式派上用场:RNNs 允许对任何类型的时间序列数据进行预测。

如果所讨论的时间序列指的是,比如说,一个病人的病史或在不同时间测量的一些神经数据,它可以用来预测疾病的轨迹。这对于发现早期干预非常重要,而且对于预测某个患者的干预效果也非常重要。考虑到智能手机可以收集的潜在有用数据的巨大财富,人们正在尝试将与 RNNs 整合并分析它们,以使它们对精神病学有用。

深度神经网络也被用于诊断(不仅用于精神疾病,还用于其他疾病,如癌症诊断等等)。有理由乐观地认为,它们将在未来的医学中发挥重要的、有希望是有益的作用。

正如我在开始时提到的,我不认为精神疾病总是从一个纯粹的“简化论者”的角度得到最好的解决,毫无疑问有重要的心理因素在起作用。但我也相信,动态的“硬科学”视角会非常有帮助。我认为,我们面临的挑战是找到正确的平衡,从长远来看,这将为我们提供最佳和最有效的疗法,最终实现我们所有人的愿望:减少精神疾病造成的巨大痛苦,并将我们的社会变成更幸福、更健康的地方。*

使用机器学习的在线零售卖家的 Mercari 价格推荐

原文:https://towardsdatascience.com/mercari-price-recommendation-for-online-retail-sellers-979c4d07f45c?source=collection_archive---------23-----------------------

作为自我案例研究的一部分,对 Kaggle 中的 mercari 数据集进行回归实验和二次研究——使用 Python 的应用人工智能课程

目录

  1. 商业问题
  2. 使用机器学习/深度学习来解决业务问题
  3. 评估指标(RMSLE)
  4. 探索性数据分析
  5. 特征工程(生成 19 个新特征)
  6. 现有解决方案
  7. 我的改进模型实验
  8. 摘要、结果和结论
  9. 未来的工作
  10. 链接到我的个人资料— Github 代码和 Linkedin
  11. 参考

图片来源—https://unsplash.com/photos/Q1p7bh3SHj8

1.商业问题

本案例研究基于 2018 年由在线购物应用 Mercari 举办的一场 Kaggle 比赛。链接到卡格尔比赛—https://www.kaggle.com/c/mercari-price-suggestion-challenge。

你可以在我的 github 档案中找到我的全部代码(链接在这篇博客的末尾)。

Mercari 是一个在线销售应用程序(与印度的 Quikr 非常相似)。卖家在商店上传他们想要出售的二手/翻新产品。当他们在 Mercari 应用程序上上传产品时,他们想知道他们应该卖多少钱。这有助于卖家在实际销售之前对产品进行定价/估价。

卖家上传商品信息,如商品名称(文本格式)商品描述(文本格式)、商品品牌、商品类别、商品状况、发货状态。当他们在 Mercari 应用程序上上传这些产品信息时,作为回报,他们会得到推荐 价格

本案例研究的目标是在给定产品属性的情况下,预测产品列表的价格。

来源—https://www . ka ggle . com/c/mercari-price-suggestion-challenge/

2.使用机器学习/深度学习来解决业务问题

使用机器学习技术可以最好地解决这个问题,这基本上是一个回归建模任务,它基本上查看相似的历史产品信息/属性以及销售价格,并相应地建议价格。

让我们查看一行训练数据并理解它的字段。(整个训练数据包含~140 万个物品清单)

样品项目列表

数据集由以下字段组成—

  1. 名称 —这是卖家正在列出的产品的项目名称/产品名称。(文本格式)
  2. 项目条件 id —包含(1,2,3,4,5)之一的值。基本上,它是一个代表物品状况的数字,范围从 1 到 5。
  3. 类别 —包含项目的 产品类别分类 作为三级层次结构(用'/'分隔符分隔)。在上面的例子中,电子产品为 1 级,计算机&平板电脑为 2 级,组件&零件为 3 级。
  4. 品牌 —所列商品的品牌。60%的行是空的。
  5. 发货 —包含布尔型— 1,0。‘1’表示运费由卖家支付,‘0’表示卖家不支付。
  6. 物品描述— 包含物品的详细文字描述。其中包含尽可能多的关于产品状况、特性和所有其他相关信息的信息。自然,我们可以想象这些信息与我们非常相关,因为价格取决于功能、某些功能的工作条件等。这将是一个有趣的 深度 NLP 任务来解决。
  7. 价格(待预测)—这是我们案例中待预测的价格。包含 0 到 2009 之间的浮点值。

熊猫数据框——训练数据截图

3.评估指标(RMSLE)

注意——这里不是 RMSE。是 RMSLE

比赛使用的评估标准基本上是一个分数。 RMSLE 代表均方根对数误差。我找到了一篇很棒的博文,这篇博文解释了 RMSE 和 RMSLE 之间的差异,以及在什么情况下 RMSLE 更适合用作回归任务的评估指标—https://medium . com/analytics-vid hya/root-mean-square-log-error-RMSE-vs-RM LSE-935 c6cc 1802 a

来源——towardsdatascience.com

代码— RMSLE 分数

总结一下这篇博文中关于为什么在这里使用 RMSLE 作为衡量标准的几点

  1. 当你低估而不是高估时,RMSLE 的惩罚更多— 换句话说,RMSLE 用在这个项目中,意思是如果你对某些项目给出更高的价格建议是可以的,但如果你低估了实际价格,这是不可接受的。如果我们预测不足,RMSLE 将显著增加,相比之下,如果我们预测过量,RMSLE 将显著增加。我认为这对于这个案例研究来说是有商业意义的,因为我们可能会对某些物品给出比实际价格更高的估价,但如果我们低估了一件物品的价格,这就不好了,因为买家可能不想在这种情况下出售。
  2. RMSLE 可以缓冲数据中异常值的影响 —如果您在 RMSE 进行评估,由于 RMSE 的平方误差惩罚,数据集中某些具有非常高价格值的项目实际上可能会扭曲模型,而 RMSLE 对高价值汽车的惩罚仅比低价值汽车略高,因为 RMSLE 在度量中有一个对数项来缓冲这种影响。
  3. RMSLE 只考虑相对误差而不考虑绝对误差(因为对数项),所以 9 对 10 的预测和 900 对 1000 的预测都具有相同的相对误差。

来源—https://www . ka ggle . com/c/ASHRAE-energy-prediction/discussion/113064

4.探索性数据分析

我们总是建议,在开始预测建模之前,首先要很好地理解数据。这是一项极其重要的任务。让我们浏览一下数据,获得一些信息和见解:

物品列表的价格分布

这里的价格遵循一个 对数正态分布 。从一个现有的 Kaggle 内核中,我发现 Mercari 只允许 3 到 2000 之间的价格列表。因此,我们将筛选这些项目列表。如果你看到下面的图表,即使 99.9 百分位值也在 400 左右。拐点出现在那之后。我们可以构建价格板(根据 5 百分位板)来更好地分析商品列表的价格分布。

项目条件、运输状态的价格差异

发货状态是二进制— (1,0)。1 代表运费由卖方支付。0 表示运费不是由卖家支付。我们可以查看一下 小提琴的剧情 下面的剧情。我们可以看到,“0”的价格比“1”的价格略高(尽管我认为情况会相反,因为我的假设是,如果卖家已经支付了运费,那么价格应该会略高)。但是 的差异有统计学意义 吗? —我们可以进行单向 ANOVA 测试,以达到 5%的显著性,这表明装运状态下的价格差异确实具有统计显著性。

代码—统计检验

数据分析——运输状态中的价格变化

下面对项目条件进行了类似的分析。这里的价格差异在统计上也很显著。在这两个特征中没有发现缺失值。

数据分析-项目条件 ID 中的价格变化

不同类别的价格差异

此处的类别功能出现在“/”分隔值中。大多数类别有 3 级分隔符。(见下图)。因此,这里的命名法是第 1 类/第 2 类/第 3 类,其中第 1 类是高级类别,后面跟着第 2 类 & 第 3 类是次级类别。

代码片段—拆分类别级别

**import seaborn as sns**
sns.set(rc={'figure.figsize':(8,6)}, style = 'whitegrid')
sns.barplot(x = "count", y="cat1", data=df_cat1_counts,palette="Blues_d")

按类别级别 1 盘点物料

让我们使用 词云 来看看本专栏中出现了哪些类型的词。此外,让我们使用 violin plots 分析跨类别的价格分布。

sns.set(rc={'figure.figsize':(19,7)})
sns.violinplot(x="cat1", y="log_price", data = df_train)
plt.title('Violin Plots - Price variation in cat1')
plt.show()

类别价格-小提琴图

**import** **matplotlib.pyplot** **as** **plt**
**from** **wordcloud** **import** **WordCloud** wordcloud = WordCloud(collocations=**False**).generate(text_cat)
plt.figure(figsize = (12,6))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.title('WordCloud for Category Name')
plt.show()

类别名称— Wordcloud

不同品牌的价格差异

该功能包含约 4800 个品牌(其中 60%的行缺少)。数据框架中列出了顶级品牌(按数量排列)。我们可以看到,前 1000 个品牌(约 25%的顶级品牌)约占产品列表的 97%。(接近一个 幂律分布 )

不同的品牌有不同的价格分布(如预期)。品牌应该出现在最相关的特征中,因为产品的价格是产品品牌的一个非常重要的功能。如下图所示,遵循长尾偏态分布。

4800 个品牌的平均价格分布

了解项目名称和项目描述的内容

让我们通过绘制他们的文字云来理解。(但是经过一些文本预处理

**# reference - Applied AI Course (Code for Text Preprocessing)
import re
from tqdm import tqdm_notebook****def** decontracted(phrase):
    phrase = re.sub(r"won't", "will not", phrase)
    phrase = re.sub(r"can\'t", "can not", phrase)
    phrase = re.sub(r"n\'t", " not", phrase)
    phrase = re.sub(r"\'re", " are", phrase)
    phrase = re.sub(r"\'s", " is", phrase)
    phrase = re.sub(r"\'d", " would", phrase)
    phrase = re.sub(r"\'ll", " will", phrase)
    phrase = re.sub(r"\'t", " not", phrase)
    phrase = re.sub(r"\'ve", " have", phrase)
    phrase = re.sub(r"\'m", " am", phrase)
    **return** phrase**def** text_preprocess(data):
    preprocessed = []
    **for** sentance **in** tqdm_notebook(data):
        sent = decontracted(sentance)
        sent = sent.replace('**\\**r', ' ')
        sent = sent.replace('**\\**"', ' ')
        sent = sent.replace('**\\**n', ' ')
        sent = re.sub('[^A-Za-z0-9]+', ' ', sent)
        *# https://gist.github.com/sebleier/554280*
        sent = ' '.join(e **for** e **in** sent.split() **if** e **not** **in** stopwords)
        preprocessed.append(sent.lower().strip())
    **return** preprocessed

上面的图表看起来不错——它给出了最常出现的单词的信息。

使用潜在狄利克雷分配(LDA)的主题建模

让我们也做一些 的题目造型使用潜狄利克雷分配 不涉及细节,这基本上是一个无监督的算法,在整个文本语料库中找到句子谈论的主题。这个分析的灵感来自于这个 Kaggle 内核— 链接

让我们来看一些由生成的主题(通过将相似的单词/句子分组到主题中 LDA 算法就是这样做的)。在我们的例子中,当应用于项目描述特性时,LDA 做得相当不错。

LDA 代码

LDA 的结果

话题 0 最有可能指的是珠宝——(项链、手链、链子、黄金)。同样,主题 3 指的是服装——(衬衫、耐克、男士、女士)。主题 7 指的是配饰— (皮革、包、钱包)等。因此,我们很好地理解了“项目描述”专栏所谈论的内容,以及其中呈现的各种主题的摘要。这个特征将是一个非常重要的价格预测器,因为它包含了与物品状况、新度、产品的详细特征等相关的信息。

我的第一直觉是,这将是一个深度 NLP 任务,需要使用某种形式的 LSTM 神经网络 来解决。

5.特征工程(生成新特征)

这是 ML 系统中最重要的部分之一。受此启发 Kaggle 内核 链接 产生了一些新特征。

特征工程(集合 1)-情感得分

这里的假设是,商品描述中传达的情感越好,买家愿意为该商品支付的价格越高。我预计商品描述的情感分数和价格之间存在正相关关系。

**from** **nltk.sentiment.vader** **import** **SentimentIntensityAnalyzer** def generate_sentiment_scores(data):
    sid = SentimentIntensityAnalyzer()
    scores = []
    for sentence in tqdm_notebook(data): 
        sentence_sentiment_score = sid.polarity_scores(sentence)
        scores.append(sentence_sentiment_score['compound'])
    return scores

特征工程(集合 2)-分组价格统计

我借用了这个 Kaggle 内核的这段代码片段— 链接 。这基本上是通过将(类别、品牌、运输)特征组合在一起并生成价格统计数据来获得价格统计数据的,这些价格统计数据是平均值中值标准值。偏差、、变异系数基于 2 个标准的预期价格范围。偏离平均值等。这是有意义的,因为我们基本上是在查看一组商品的历史价格,并将它们输入到特性集中,假设它们可能与当前价格密切相关。

特征生成的代码

特征工程(集合 3)-项目描述文本统计

我再次借用上面发布的同一 Kaggle 内核链接中的这段代码。代码基本上从项目描述栏创建新功能,如字数、特殊字符数、数字数等。

代码-描述特征

Co 将新生成的功能与价格相关联

最重要的问题是,这些新功能是否与价格密切相关——为此,我们可以绘制相关热图。

***#ref =*** [***https://datatofish.com/correlation-matrix-pandas/***](https://datatofish.com/correlation-matrix-pandas/)# df_corr contains all the newly generated features
corrMatrix  = df_corr.corr()
plt.figure(figsize = (18,9))
sns.heatmap(corrMatrix, annot=**True**)
plt.show()

关联热图(新生成的要素)

正如我们从上面的热图中看到的,3 个特征与价格输出有很强的相关性,相关性> 0.5。生成的平均、最小预期、最大预期价格特征似乎最为显著。我们将只保留这 3 个新功能。

6.现有解决方案

有许多不同方法的核心,其中一些包括—

  1. CNN 带手套进行单词嵌入——内核链接。这使用 CNN 模型对项目名称、项目描述以及分类特征进行单词嵌入,以使其通过密集 MLP。模型给出的 RMSLE 得分为 0.41(第 35 位)
  2. 稀疏的 MLP — 内核链接。这使用稀疏 MLP 通过文本的 Tfidf 矢量化和分类要素的一次热编码来生成输出。模型给出的均方根误差为 0.38(第一名)
  3. 岭模型— 内核链接。对 Tfidf 文本要素使用简单的岭回归来生成预测。模型给出的均方根误差为 0.47
  4. LGBM 模型— 内核链接。使用 LightGBM 回归器给出 0.44 的输出分数。

7.我的改进模型实验

数据准备

我们可以使用原始训练数据拆分成训练/测试,测试数据大小为 25%。

**from sklearn.model_selection import train_test_split** df_train = pd.read_csv('train.tsv',sep = '**\t**')
df_train_model,df_test_model = train_test_split(df_train,test_size = 0.25)

数据编码

输入特征包括分类和文本特征,以及 3 个新生成的数字特征。分类编码包括一个热门编码器,标签二进制化器。文本编码涉及 Tfidf 和 Count (BOW)矢量器。数字编码涉及使用 StandardScaler 进行标准化。

如 ed a 部分所述,输出变量——价格涉及对数变换。

**import numpy as np**
y_train  = np.log1p(df_train['price'])

用 GridSearchCV 改进岭回归

我们可以从用 L2 正则化建立一个简单的线性模型开始,这基本上被称为岭回归。该模型在测试数据上给出了 0.474 的 RMSLE。请注意,solver = 'lsqr '用于更快的训练,训练该模型不到一分钟。

**%%time
from** **sklearn.linear_model** **import** **Ridge** ridge_model = Ridge(solver = "lsqr", fit_intercept=**False**)
ridge_model.fit(X_train, y_train)
preds = np.expm1(ridge_model.predict(X_test))

我们可以尝试在这个模型上使用GridSearchCV看看是否可以提高分数。

**from** **sklearn.model_selection** **import** **GridSearchCV**
parameters = {'alpha':[0.0001,0.001,0.01,0.1,1,10,100,1000,10000],
              'fit_intercept' : [False],
              'solver' : ['lsqr']}

gs_ridge = GridSearchCV(estimator = Ridge(),
                        param_grid = parameters,
                        cv = 3, 
                        scoring = 'neg_mean_squared_error',
                        verbose = 100,
                        return_train_score = True,
                        n_jobs = -2)
gs_ridge.fit(X_train, y_train)

正如我们在下面看到的,当使用三重交叉验证时,alpha=10 给出最低的交叉验证分数。但是在使用这个模型的时候。RMSLE 仅从 0.474 降低到 0.472 ,这并不是非常显著的改进。注意在下面的图表中,使用了 10 的对数标度,因为在进行网格搜索时,所有的超参数α值都是 10 的幂。

超参数图

LightGBM 回归模型的超参数调整

代码片段— LGBM 模型

lgbm_params_1 = {'n_estimators': 900, 
                 'learning_rate': 0.15,
                 'max_depth': 5,
                 'num_leaves': 31, 
                 'subsample': 0.9,
                 'colsample_bytree': 0.8,
                 'min_child_samples': 50,
                 'n_jobs': -2}

我们可以通过调整超参数来改进模型,通过增加估计器降低学习速率不限制最大深度、增加叶子数量等来稍微过度拟合。通过调整这些,模型从 0.50 提高到 0.47 ,这确实是一个显著的进步,尤其是在 Kaggle 比赛中,而且得分是以对数标度(RMSLE)进行的。尽管这个模型有点过度拟合,我们可以通过在最后建立一个集合来减少模型的方差,正如我们将看到的。LightGBM 的主要问题是培训时间——在我的 16 GB RAM 的桌面上运行需要将近 2-3 个小时。

lgbm_params_2 = {'n_estimators': 1500,
                 'learning_rate': 0.05,
                 'max_depth': -1,
                 'num_leaves': 50,
                 'subsample': 0.8,
                 'colsample_bytree': 0.8,
                 'min_child_samples': 50,
                 'n_jobs': -1}

LSTM 神经网络(第 1 版)

这是第一个直觉,我们可以安全地假设该模型将工作良好,因为我们的大部分数据都以文本的形式出现在项目名称和项目描述中。此外,所有新生成的 17 个数字特征都已作为输入传递给数字特征。我的假设是,如果这些特征相关或不相关,神经网络会自己学习——所以不会损害模型。

下面附上的是第一个 LSTM 模型-正如您在下面看到的,文本和分类特征首先通过嵌入层,然后展平以连接成密集的神经网络结构。

**from** **tensorflow.keras.utils** **import** **plot_model
from** **IPython.display** **import** **Image**
plot_model(baseline_lstm_model, to_file='baseline_lstm_model.png', show_shapes=True, show_layer_names=True)
Image(filename='baseline_lstm_model.png')

LSTM 模型 1

上述模型在 60 个周期后给出的 RMSLE 为 0.48 ,当与 adam optimizer 一起使用时,val 损失未能显著改善。下面是生成上述 LSTM 模型 1 的代码。

LSTM 网络文本句子填充长度的选择

我们可以通过绘制句子长度的分布来选择句子长度。

代码片段—填充长度选择

从代码中我们可以看到,在项目描述列中只有 0.59%的行的句子长度超过 125。这意味着几乎所有的句子长度都属于这个范畴,我们可以用它来选择句子长度。

**>>>select_padding(train_desc,tokenizer_desc,"Item Descriptions",125)****Output :**
Total number of words in the document are  138419
0.5927708414700212  % of rows have sentence length >  125

直方图—句子长度

LSTM 神经网络(第 2 版)

在这个模型中,我们将名称、描述、品牌、类别中的文本连接起来,并创建了一个文本特征。我还选择了与价格高度相关的 3 个数字特征作为数字输入。该模型给出的均方根误差为 0.47

LSTM 模型 2

通过添加更多层来构建稀疏 MLP 模型的 2 个变体

获胜者的解决方案模型使用简单的 MLP 模型,其中要素的稀疏输入表示只有 4 个图层。与 LSTM/LGBM 模型相比,该模型能够以更好的方式学习特征交互,因此结果良好。为了避免过度拟合,我在实验中在此基础上增加了几层,同时加入了辍学和批处理规范化。在构建了两个这样的模型之后,我们可以使用某种形式的组装来组合它们。

正如你在上面看到的,这个模型非常简单。三款 MLP 车型的 RMSLE 得分分别为 0.415、0.411

最终集合模型

在构建了许多这样的模型之后,我们可以以某种方式将它们组合起来,以提供更好的性能。我们可以使用交叉验证方法来获得最佳的集成模型组合。然而,对于我的最终模型,我决定只使用山脊模型和 MLP 模型,因为它们训练起来更快(< 15 mins), whereas LSTM and LGBM models individually took > 3 小时)。

在上面的方法中,我们在这里所做的是获取我们想要集成的 2 个模型的预测,并以给出最佳 RMSLE 的方式为每个模型分配权重——我们可以使用交叉验证来找到这一点。当我们对(2 个岭模型+ 2 个 MLP 模型)的集合进行此操作时,我们得到的 RMSLE 为 0.408 ,显著低于所有单个模型。

preds_final=ensemble_generator(preds_final_ridges,preds_final_mlps)

集成的权重选择

岭型车型的大约 0.1 权重和 MLP 车型的剩余 0.9 权重给出了最好的分数。

preds_f = 0.1*preds_ridge + 0.9*preds_mlps

8.摘要、结果和结论

下面是所有训练模型和获得的 RMSLE 分数的总结。正如我们所见,合奏模型是赢家。

模型摘要

在 Kaggle 中对看不见的测试数据集进行最终提交给出了 RMSLE 分数 0.39 ,这将在 top 1%排行榜中出现。

****

Kaggle 提交

可视化预测和误差

从下图可以看出,大约 55%的点有误差< 5 and ~76% of points have errors < 10. This is one of the way we can visualize the distribution of errors. Here 误差=(实际—预测)

柱状图——误差分布

我们可以做的另一个图是绘制对数(绝对误差)图,因为我们已经完成了对数标度的价格建模。在下图中,x 轴是对数(Abs 误差),左边的 y 轴代表该误差的点数(蓝色 histgoram)。橙色线给出了右侧 y 轴上的累积点数。我们可以看到,~ 99%的点都有 Log(Abs 误差)< 4

9.未来的工作

我们可以在这方面做更多的实验来进一步改进预测—

  • 使用 hyperas 库来微调神经网络架构,以进一步提高性能
  • 对文本数据使用其他矢量化方法,如 DictVectorizer() 生成文本特征
  • 对文本数据上的单词嵌入使用卷积层

10.链接到我的个人资料— github 代码和 linkedin

你可以在 github 链接 找到我的完整代码。如果你想讨论,可以在我的 linkedin 个人资料 链接 上联系我。你也可以帮我接通 debayanmitra1993@gmail.com 的电话。

11.参考

  • https://www . Applied ai course . com/course/11/Applied-Machine-learning-course
  • https://medium . com/unstructured/how-I-lost-a-silver-medal-in-kaggles-mercari-price-suggestion-challenge-using-CNN-and-tensor flow-4013660 fcded
  • https://www . ka ggle . com/thykhuely/mercari-interactive-EDA-topic-modeling
  • https://www . ka ggle . com/valkling/mercari-rnn-2 ridge-models-with-notes-0-42755
  • https://www . ka ggle . com/lopu hin/mercari-golf-0-3875-cv-in-75-loc-1900-s
  • https://www.kaggle.com/apapiu/ridge-script
  • https://www . ka ggle . com/tunguz/more-effective-ridge-lgbm-script-l b-0-44823
  • https://www . ka ggle . com/gspmoreira/CNN-glove-single-model-private-l b-0-41117-35 号
  • https://www.youtube.com/watch?v=QFR0IHbzA30

基于机器学习回归的价格预测——案例研究

原文:https://towardsdatascience.com/mercari-price-suggestion-97ff15840dbd?source=collection_archive---------0-----------------------

电子商务中的人工智能

Mercari 价格建议挑战

这篇文章详细描述了我解决回归问题的方法,这也是一个流行的 Kaggle 竞赛。希望你觉得有用并喜欢阅读:)

图片来自咖啡豆来自 Pixabay

人工智能是当今所有主要电子商务公司不可或缺的一部分。随着过去二十年信息产业的发展和人工智能领域的广泛研究,企业已经开始探索使用最先进的机器学习算法和深度神经网络来自动化各种活动的方法。许多 IT 巨头和初创企业已经在这一领域迈出了一大步,并拥有专门的团队和资源来研发尖端的人工智能应用。今天的在线零售平台广泛由人工智能驱动的算法和应用程序驱动。从仓库的库存管理和质量检查到网站上的产品推荐和销售统计数据,所有活动都在不同程度上使用了机器学习。

业务问题和挑战

图片来源: Movas Global 通过 KindPNG

Mercari 是日本最大的社区购物网站。为了实现一个节约使用全球资源、人人都能过上富裕生活的社会,该公司在日本和美国开发了一个跳蚤市场应用程序“Mercari ”,让个人能够轻松、安全地买卖商品。Mercari 面临的挑战是建立一种算法,在其应用程序上自动向卖家建议正确的产品价格。

预测产品的价格是一项艰巨的挑战,因为非常相似的产品有微小的差异,如不同的品牌名称、附加规格、质量、产品需求等。会有非常不同的价格。例如,其中一件毛衣售价 335 美元,另一件售价 9.99 美元。你能猜出哪个是哪个吗?

图片来源:https://www . ka ggle . com/c/mercari-price-suggestion-challenge/overview

当产品种类繁多时,价格预测变得更加困难,这在大多数在线购物平台上都很常见。Mercari 的卖家可以在应用程序上列出几乎任何东西。预测在线平台上几乎所有商品的价格都极具挑战性。

让我们从机器学习的角度来看这个问题。

ML 问题

Mercari 提供了用户输入的产品文本描述,包括产品类别名称、品牌名称和商品状况等细节。使用这些数据,我们必须想出一个模型,尽可能准确地预测 Mercari 上列出的产品的价格。这看起来像一个标准的回归问题。

性能指标和业务限制

我们必须有一个尺度来衡量我们的模型性能的好坏。在机器学习术语中,我们将这种尺度称为性能度量或简称为度量。有各种度量来测量回归模型的性能,例如平均绝对误差、均方误差、均方对数误差、 最大残差、中值绝对误差、决定系数(R)等
对于这个问题, Kaggle 使用均方根对数误差(RMSLE) 。RMSLE 越小,我们的模型越好。RMSLE 的计算公式为

图片来源:https://www . ka ggle . com/c/mercari-price-suggestion-challenge/overview/evaluation

  • 最准确地预测价格是我们的首要商业目标。
  • 在这个问题中没有低延迟限制。一旦产品在应用程序上列出,我们不需要立即建议它的价格。然而,我们也不能花几个小时或几天来预测价格。

现有方法

  1. 第 18 位解 : 总体思路是先训练一个 FM_FTRL 模型,再训练一个 LightGBM 模型,用两者的系综得到最终的预测。
  2. Mercari Golf:0.3875 CV in 75 LOC,1900s:4 个 MLP 模型的集合,每个模型具有相同的架构,但显然在 2 个不同的数据集上进行训练。

了解了约束、业务目标和我们需要解决的问题后,是时候动手了。

1.数据概述

数据可以从 Kaggle 竞赛页面下载。有两个文件 train.tsvtest.tsv 和一个 Kaggle 提交模板 sample_submission.csv. 解压缩后数据总大小为 1.03 GB。

这些文件由产品列表组成。这些文件用制表符分隔。 train.tsv 有 1482535 行, test.tsv 有 3460725 行。训练和测试文件都有以下数据字段

  • train_idtest_id -列表的 id
  • name -清单的标题
  • item_condition_id -卖方提供的物品的状况
  • category_name -清单的类别
  • brand_name
  • price -物品的销售价格。这是我们将要预测的目标变量。单位是美元。该列在test.tsv中不存在,因为这是我们将要预测的。
  • shipping - 1 如果运费由卖方支付,0 如果由买方支付
  • item_description -物品的完整描述

数据表中的称为数据点,而称为特征/变量。在这篇博客中,我将交替使用数据点这两个词。与特征/变量相同。

以下是来自训练数据的样本。

我们看到数据中有一些空值 (NaN)。我们会用‘失踪’来代替这些。同样,我们将列category_name 中的三个值的列表拆分成三个新列gencat_name, subcat1_name, subcat2_name例如,一个带有 category_name= 【男士、上衣、t 恤】 的数据点会有 gencat_name= 男士 ,subcat1_name= 上衣 ,以及 subcat2_name= T 恤

2.探索性数据分析

让我们从一个机器学习工程师的角度来看看训练数据,看看我们是否能得出一些有用的推论。这将使我们对解决问题的方法有一个合理的想法。

2.1.基础 EDA:分析训练数据列

名称

**train.name.describe()**count     1481661
unique    1224596
top        Bundle
freq         2232
Name: name, dtype: object

原始数据(预处理前)中有 1,224,596 个唯一的产品名称。最常见的产品名称是“Bundle”、,出现在 2232 个数据点中。

项目条件标识

不同项目条件下的产品数量

大多数物品处于状态 1T42 状态。很少有项目处于状态 5。

品牌名称

**train.brand_name.describe()**count     1481661
unique       4808
top       missing
freq       632336
Name: brand_name, dtype: object

按产品数量排名的前 15 大品牌

brand_name 缺失大量(42.68 %)数据点。

gencat_name

产品类别计数

  • 这些产品分布在 10 个大类中。这一栏对于一些产品是空白的,这些已经被放入一个单独的类别中不见了。
  • 大量的产品属于女性产品。这可能是因为通常情况下,女性比男性更倾向于购物。
  • 6314 个数据点,即 0.43 %的列车数据缺少 gencat_name 。

subcat1_name,subcat2_name

**train.subcat1_name.describe()         train.subcat2_name.describe()**count              1481661            count                  1481661
unique                 114            unique                     871
top       Athletic Apparel            top    Pants, Tights, Leggings
freq                134321            freq                     60152

除了 10 个大类之外,还有 114 个产品子类,这些产品又可能属于 871 个子类。简而言之, subcat1_name 从更广的意义上讲述了物品的类别,而 subcat2_name 则更深入一层,给出了关于物品具体是什么的更多细节。回想一下示例 【男士、上衣、t 恤】下图显示了按商品数量排列的前 15 个子类别。

属于不同子类别的产品数量

价格

这是我们训练数据中的目标变量或“y”。我们需要对测试数据进行预测。它的价值范围很广,从 3 美元到 2009 美元不等。然而,大多数商品的价格都低于 200 美元,正如下面的图表和百分位值所示。

价格分布:PDF (左)、箱线图(右)

0 percentile value is 3.0
10 percentile value is 7.0
20 percentile value is 10.0
30 percentile value is 12.0
40 percentile value is 14.0
50 percentile value is 17.0
60 percentile value is 20.0
70 percentile value is 26.0
80 percentile value is 34.0
90 percentile value is 51.0
100 percentile value is  2009.0
90 percentile value is 51.0
91 percentile value is 55.0
92 percentile value is 58.0
93 percentile value is 62.0
94 percentile value is 67.0
95 percentile value is 75.0
96 percentile value is 85.0
97 percentile value is 99.0
98 percentile value is 122.0
99 percentile value is 170.0
100 percentile value is  2009.0
  • 97%的数据点价格低于 100 美元。
  • 极少数(仅 1%)数据点的价格超过 170 美元。

2.2.单变量分析:特征(列)和目标变量‘y’之间的相关性

让我们根据不同数据列的值来探究商品价格是否有任何趋势。这将有助于我们决定哪些列在确定商品价格时比其他列更有用。

价格随项目条件的变化

我用简单的箱线图来观察一个物品的价格是如何随着物品的状况而变化的。
注意,在箱线图中,方框的下边界表示 25ᵗʰ百分位,上边界表示 75ᵗʰ百分位,方框内的线表示 50ᵗʰ百分位或中位数。

  • 根据物品的情况,价格会有轻微的变化。
  • 当我们从条件 1 到条件 4 时,中间价格下降。
  • 条件 5 中的项目似乎有更高的价格,可能是因为它们是昂贵的项目,如电子产品。

价格随项目类别(gencat_name)的变化

观察下图中各种类别的箱线图和平均价格,我们可以说属于不同产品类别的商品价格存在一些差异。

价格随项目子类别(subcat1_name)的变化

属于不同子类别的项目的中间价格

某些类别产品的价格差异很大。例如,属于电脑、平板电脑、照相机、摄影、婴儿车、乐器、等的物品。与属于纸制品、儿童、办公用品、交易卡、等的物品相比是昂贵的。

这表明类别和子类别将成为决定商品价格的重要因素。

3.清理数据:预处理

3.1。预处理文本特征

我已经做了一些基本的文本预处理,如删除非字母数字字符,正则表达式,停用词等。从名称项目 _ 描述。代码如下。

3.2.预处理类别

这类似于文本预处理。我已经删除了空格,并将符号' & '(和)替换为' _ '(下划线)。我做这种清理是为了获得精确的一键分类编码,这将在特征部分解释。

3.3.预处理价格:删除无效条目

Removed 874 rows

4.从数据中提取特征

机器只理解数字,它不直接理解我们人类可以阅读的字母或文本。这意味着我们需要将文本和分类数据转换成数字。这个过程被称为特征提取或特征化。有几种与不同类型的数据相关的特征提取技术,我们将在本节中看到其中的一些。

4.1.手工制作的特征:特征工程

基于我的直觉和对现有方法的研究,我提出了以下特征,我认为这些特征在确定一件物品的价格时会很有用。使用这些特性没有标准规则,这些纯粹是基于直觉的想法,可能因问题而异。因此,这些被称为手工制作的特征或工程特征。
下表提供了特性的名称。描述这些特性的含义及其计算方式。

我们来看看上面的功能是不是真的有用。

对一些工程特征的单变量分析

使用 seaborn regplot 绘制了以下图,该图试图拟合一个简单的线性模型,并绘制了单变量(特征与目标)散点图上的拟合直线/平面方程。

example code:
sns.regplot(x=’brand_mean_price’, y=’price’, data=train,
            scatter_kws={‘alpha’:0.3}, line_kws={‘color’:’orange’})

诸如 brand_mean_price、brand_median price、subcat2_mean_price、subcat2_median_price 等特征显示出强烈的线性趋势。因此,它们在确定商品价格时似乎是有用的。

4.2.训练,交叉验证的测试分割

出于交叉验证的目的(检查训练的模型是否在看不见的数据上工作良好),我将我们的数据以 90:10 的比例分成 train 和 cv。我将在列车上训练我们的模型,并在 cv 上验证它们。
注意,已经使用 NumPy 的 log1p()函数将目标变量 price 转换为对数标度。这样做是为了我们可以使用均方根误差作为度量,而不是显式定义复杂的度量 RMSLE。(因为 RMSLE 只不过是对数值的 RMSE)

Train size: (1332967, 58), CV size: (148108, 58), Test size: (3460725, 58)

4.3.将分类特征转换为数字:一键编码

一键编码是一种矢量化方案,其中分类变量中的每个类别都被转换为长度等于数据点数的向量。对于属于与向量相对应的类别的每个数据点,向量包含值 1,否则包含 0。为了更好地理解,请看下面的例子。

图片来源: DanB via Kaggle

我已经将所有分类变量( brand_name,gencat_name,subcat1_name,subcat2_name )转换为它们的独热编码向量。示例代码如下所示:

请注意,分类变量 item_condition_idshipping 已经包含数值,无需将其转换为向量。

4.4.将文本特征转换为数字:TF-IDF 矢量器

TF-IDF(术语频率-逆文档频率)是一种统计度量,用于评估单词与文档集合中的文档的相关程度。这是通过将两个度量相乘来实现的:一个单词在一个文档中出现的次数,以及该单词在一组文档中的逆文档频率。你可以在这里阅读更多关于 TF-IDF 和它的数学细节。

在计算语言学和概率领域中,一个 n -gram 是来自给定文本或语音样本的 n 项的连续序列。这些项目可以是音节、字母、单词等。这取决于应用(在我们的例子中是单词)。尺寸为 1 的 n 克称为“一克”,尺寸为 2 的称为“二克”,依此类推。

我已经将 nameitem_description 编码成一元、二元和三元的 TF-IDF 向量。请注意,一起使用 1,2,3-gram 将导致 TF-IDF 矢量器的字典中有大量的单词,并且使用所有这些单词将导致非常高维的向量。为了避免这种情况,我将名称的维度数量限制为 250k ,将项目 _ 描述向量的维度数量限制为 500k

5.为模型准备数据

5.1.数字特征的列规范化

规范化的主要目的是将不同列中的数字数据缩小到相同的比例,以便模型不会因少数列中的巨大差异而出现偏差。我在这里使用了最小-最大归一化(代码如下)。

5.2.将所有特征合并到一个稀疏矩阵中

我们将为我们的模型提供一个输入矩阵 X_train,它包含我们在上一节中提取的所有特征,以及一组相应的目标值 y_train。因此,我们需要首先通过并排连接所有的特征向量来构建 X_train。

Train size: (1332967, 755695), CV size: (148108, 755695), Test size: (3460725, 755695)

现在,我们的数据可以输入到模型中了。开始建模吧。

6.建模:机器学习模型

我将逐一训练以下回归模型,并评估它们在验证数据上的性能:

  • 岭回归r:L2 正则化的线性最小二乘

  • SVM 回归r:RBF 核支持向量回归。

  • LightGBM 回归器 :使用基于树的学习算法的梯度推进模型。

要了解这些型号的更多信息并阅读文档,请单击型号名称。

6.1.里脊回归

岭是具有 l2 正则化的线性最小二乘模型。换句话说,就是用 l2 正则化的线性回归。
山脊模型的过拟合或欠拟合取决于参数 alpha ,可通过如下所示的超参数调谐将其调谐至正确的值。

RMSLE for alpha =  1 is 0.45166601980352833
RMSLE for alpha =  2 is 0.44431546233122515
RMSLE for alpha =  3 is 0.4424425182737627
RMSLE for alpha =  3.5 is 0.44171501703551286
RMSLE for alpha =  4 is 0.44154616529145424
RMSLE for alpha =  4.5 is 0.4415286167861061
RMSLE for alpha =  5 is 0.44161632764828285
RMSLE for alpha =  6 is 0.4421832813533032
RMSLE for alpha =  7 is 0.44267468278758176

使用最佳超参数训练模型并测试

Best alpha:  4.5                            **Train RMSLE: 0.383449898
Cross validation RMSLE:  0.441528616**

SelectKBest:从分类和文本特征中选择前 48k 个特征

当数据是高维的时候,我们将进一步尝试的模型需要花费大量的时间来训练。因此,我只从文本 TF-IDF 向量和分类 one-hot 编码向量中选择前 48,000 个特征。

我将这些与数字特征、岭模型的预测(y_pred 用作特征)连接起来,并在我的模型中使用它们。

Train size: (1332967, 48049), CV size: (148108, 48049), Test size: (3460725, 48049)

6.2.SVM 回归

SVR 是线性回归的高级版本。它在 d 维空间中找到一个超平面,该超平面清楚地对数据点进行分类。

类似于线性回归中的α,SVR 中的 C 是通过超参数调整找到的。

Best C:  0.3
SVR(C=0.3, epsilon=0.1, gamma='scale',kernel='rbf', max_iter=200)**Train RMSLE: 0.441563037
Cross validation RMSLE:  0.457637217**

6.3.随机森林回归

用较高的 N 估计值(N)训练随机森林回归方程花费了大量的时间,却没有给出任何结果。由于这个原因,我们用较少的估计量来训练它。正如你所猜测的,结果并不令人满意。

**RMSLE for N=10 is 0.487657647**	 elapsed time:0:46:21.136700
**RMSLE for N=20 is 0.472606976**	 elapsed time:2:02:11.229545

6.4.LightGBM 回归

Light GBM 是一个基于决策树算法的快速、分布式、高性能梯度提升框架,用于排序、分类和许多其他机器学习任务。由于它是基于决策树算法的,所以它以最适合的方式在叶子上分割树,而其他 boosting 算法在深度上分割树。因此,当在浅色 GBM 中生长在相同的叶子上时,叶子方式的算法可以比深度方式的算法减少更多的损失,因此导致更好的准确性。而且,它出奇的快,因此有了‘光’这个词。

LightGBM 的超参数调整已经通过使用 RandomizedSearchCV 的三重交叉验证完成。

{'colsample_bytree': 0.44583275285359114, 'learning_rate': 0.09997491581800289, 'max_depth': 12, 'min_child_weight': 1.7323522915498704, 'n_estimators': 1323, 'num_leaves': 123}
**Train RMSLE: 0.319789825
Cross validation RMSLE:  0.424231390**

6.5.比较模型的性能

  • LGBM 的验证分数(RMSLE=0.42423)是上述所有模型中最好的。
  • 我把 Ridge 和 LGBM 的预测提交给了 Kaggle。我们用 Ridge 得到了最好的分数,RMSLE=0.45444
  • LGBM 评分(RMSLE=0.45785)与 Ridge 评分非常接近。

7.最终解决方案:使用多层感知器进行回归

经典的机器学习模型似乎工作得相当好,但我们应该有更好的性能才能获得好的 Kaggle 分数。大多数现有方法采用了一些或其他深度学习模型,如卷积神经网络(CNN)、递归神经网络(RNNs)或两者的组合。深度学习模型的性能似乎明显优于经典的 ML 模型,这鼓励我尝试一个基本的深度学习模型,MLP。

7.1。预处理

我对训练和测试数据做了如下处理:

  • 标准文本预处理(词干提取、填充 NAs)
  • 名称品牌名称串联成一列,名称。
  • 名称项目 _ 描述类别 _ 名称串联成一列,文本

7.2.矢量化

  • 名称的 Tfidf 1-gram 矢量化。
  • 文本进行 1-gram、2-gram 矢量化处理。
  • 分类特征的一键编码项目 _ 条件 _id发货

7.3。MLP 模型建筑

选择 MLP 而不是 CNN 或 RNN 的原因是:

  • 快速训练,可以 afford 隐藏大小 256,而不是 32-64 的 RNN 或 Conv1D。
  • MLP 捕捉文本和分类特征之间的相互作用。
  • 巨大的方差给出了单一模型类型的强集合。

我已经训练了完全相同架构的 4 个高方差模型,并最终对这些模型进行集成以获得最终预测。这和 RandomForest 的套袋差不多。对于 4 个模型中的 2 个,我通过将所有非零值设置为 1 来二进制化输入数据。这就像用二进制 CountVectorizer 而不是 TF-IDF 获得一个额外的数据集。

我使用 Adam optimizer,学习率为 0.003,初始批量大小为 512,并为 2 个时期训练模型,在每个时期将批量大小加倍。对于二进制输入,我以同样的方式训练了 3 个时期。

7.3.模型性能评估和 Kaggle 提交

有了上面的模型,我得到了一个验证 RMSLE= 0.3848 ,相比我之前所有的模型有了很大的提升。

在私人排行榜上,使用该模型在 Kaggle 上的最终提交分数为 0.39446。
虽然比赛很久以前就结束了,但将这个分数放在排行榜上使我在私人和公共 LB 中都处于第 5 位(前 0.2%)。

对现有方法的改进

  • 为了获得更好的结果,我对 MLP 架构以及学习速度和批量大小等参数做了一些修改。对于非二进制数据的模型,我还将历元数从 3 改为 2,因为它从第 3 个历元开始过度拟合。
  • 我没有采用简单的平均值,而是采用了 4 个模型/运行预测的加权平均值。
  • 为了简化代码,也因为我使用了 Google Colab( 使用 GPU 的训练比使用多核 CPU更快),我一个接一个地训练模型,不像原始内核中的池处理。

与源代码内核中的 0.3875 相比,我得到的验证 RMSLE 是 0.3848。

不太顺利的事情

  • 随机森林花了太多的时间来训练,因此我不得不放弃这个模型。
  • 在 MLP,我也尝试使用辍学(0.1,0.2,0.3,..0.5),但模型表现更好,没有辍学,因此删除他们。(我得到了一个验证 RMSLE 为 0.3872 的退出数据)。
  • 我还试验了不同的激活单元(‘tanh’,‘sigmoid’,‘linear’,‘relu’)。“relu”的表现明显好于其他所有产品。

未来的工作

  • 使用深度学习是有成效的,并在测试数据上取得了非常好的成绩。可以尝试 LSTMs、卷积神经网络等更复杂的模型。
  • 我们可以通过在隐藏层中添加额外的层和更多的单元来试验更复杂的 MLP。
  • 其他矢量化方案,如 Wordbatch 可以用 ML 模型进行试验。
  • 像 FTRL 和 FM_FTRL 这样的回归模型也可以尝试。

结论

做这个案例研究既有趣又是一次很好的学习经历。感谢你阅读我的博客,我希望这能给你带来一些价值。我在这个博客中包含了最少的代码。完整代码请参考我的 GitHub 资源库中的 ipython 笔记本Mercari-Price-Suggestion-Challenge。我希望听到您的反应、建议或疑问。你可以在 LinkedIn 上和我联系。这是我的简介。

参考

  1. https://blog . explorative . io/a-practical-guide-of-explorative-data-analysis-with-linear-regression-part-1-9f3a 182 D7 a 92
  2. https://www . ka ggle . com/c/mercari-price-suggestion-challenge/overview
  3. https://www . ka ggle . com/c/mercari-price-suggestion-challenge/discussion/50252
  4. https://www . ka ggle . com/lopu hin/mercari-golf-0-3875-cv-in-75-loc-1900-s
  5. https://www . Applied ai course . com/course/11/Applied-Machine-learning-course

在 Python & R 中合并数据框

原文:https://towardsdatascience.com/merge-data-frames-in-python-r-725c0f874147?source=collection_archive---------35-----------------------

下面是一个简单的 Python 和 r 中数据帧合并的备忘单。

蒂姆·约翰逊在 Unsplash 上拍照

M 生成数据框是数据处理人员的必备技能。然而,当从一种编码语言转换到另一种时,很难正确地记住命令。

在这篇文章中,我将为 Python 和 R 中的合并函数总结一个简单干净的备忘单,这类似于我以前的文章中的。此外,我将在合并多个数据框时对 Python 和 R 进行比较。

注意,为了并排比较命令行,我将只使用 Python 中的 PandasR 中的基本函数。有些综合库,比如 R 中的 dplyr ,就没有考虑。

当你必须同时使用两种语言时,我希望这篇文章和备忘单对你有所帮助。

要使用的玩具数据集。

我们使用阿伦艾弗森和特雷西麦格雷迪的真实投篮命中率作为我们的玩具数据集。

r 输出 1

Python 输出 1

我们可以看到数据框中有三列,“季节”、“Pos”和“TS”,分别代表赛季指数,场上位置,真实投篮命中率。

四种类型的合并。

主要有四种类型的合并策略,包括基于用于合并的公共键(列)的内连接、外连接、左连接和右连接。

“内部连接”意味着只取两个数据框的键列中元素的交集。我们可以使用文氏图来表示“内部连接”,如下所示。

内部连接图

下面是 R 和 Python 的代码。

r 内部连接

Python 内部连接

从上面的表格中我们可以看到,只显示了艾弗森和麦迪都打过的赛季。

接下来让我们看看“外部连接”策略。“外部连接”采用两个数据框的键列中的元素的联合。

外部连接图

下面列出了在 R 和 Python 中执行“外部连接”的代码。

r 外部联接

Python 外部连接

我们可以看到,两种语言都向原始数据帧中没有的关键元素填充了“NA”值。这张表显示了一个球员参加比赛而另一个球员没有参加的赛季。

“左连接”只接受第一个表的键列中的元素,而不考虑第二个表的键列中的元素。

左连接图

这里列出了 R 和 Python 中“左连接”的代码。

R 中的左连接

Python 中的左连接

“右连接”是“左连接”的反义词。

右连接图

下面列出了用 Python 和 R 进行“右连接”的代码。

右连接

Python 右连接

这四种类型的合并构成了“合并”用法的主要部分。区分参数以选择 R 和 Python 中的合并策略很重要。R 中使用的参数是“by.x”和“by.y”,而 Python 中的参数是“how”。注意,如果“by.x”和“by.y”在 R 中需要相同的赋值,我们可以使用单个参数“by”来代替。

合并多列上的两个数据框。

有时,我们需要合并基于多个列的两个数据框。我们唯一需要做的事情是将列名列表传递给相应的参数。

R 中的多列合并

在 Python 中合并多个列

在上面的例子中,我们感兴趣的是当两个球员在同一个赛季(“赛季”)中在相同的位置(“Pos”)比赛时,球员的统计数据比较。

合并多个数据框。

在另一种情况下,我们对合并两个以上的数据帧感兴趣。我们绝对可以写一个很长的命令来逐个合并它们,但是更好的方法可以是“”函数。

假设我们有另一个关于科比真实投篮命中率的数据框架,我们想把它与艾弗森和麦迪的数据框架合并在一起。

合并 R 中的多个数据帧

这里在 R 的“ Reduce 函数中,我们需要定义一个合并两个数据帧的函数并将其作为第一个参数,然后传递一列数据帧作为“”函数的第二个参数。**

在 Python 中合并多个数据框

这里在 Python 的“ reduce 函数中,与 r 中的非常相似,我们需要定义一个通过 lambda 合并两个数据帧的函数。而且我们还需要将一列数据帧传递给“”函数。

用 R 和 Python 合并数据框的备忘单。

下面是在 R 和 Python 中合并数据框的简单备忘单。

裕丰小抄

就是这样!希望这篇帖子能对你有所帮助。

感谢您的阅读!如果喜欢文章,请 关注我上媒 。以下是我之前在数据科学发表的一些文章:**

*** [## 是否在我的模型中考虑多重共线性?

简要讨论是否有必要修复特征空间中的多重共线性。我希望它会…

towardsdatascience.com](/consider-multicollinearity-in-my-model-or-not-7aca16e74773) [## 使用三种机器学习模型基于勒布朗数据的端到端游戏预测方案

综合指导一个二元分类问题使用三个不同的分类器,包括逻辑…

towardsdatascience.com](/end-to-end-project-of-game-prediction-based-on-lebrons-stats-using-three-machine-learning-models-38c20f49af5f) [## NBA 球员统计数据 R 包“ggplot2”中数据可视化的实践指导

应用于 NBA 数据的 R 数据可视化工具“ggplot2”的 6 分钟之旅。

towardsdatascience.com](/hands-on-guidance-of-data-visualization-in-r-package-ggplot2-of-nba-players-stats-d812ed272d66)***

用 Python 合并字典的 5 种方法

原文:https://towardsdatascience.com/merge-dictionaries-in-python-d4e9ce137374?source=collection_archive---------0-----------------------

编程;编排

Python 3.9 中合并 Python 字典和新运算符的不同方式

图片来自 Clker-Free-Vector-Images 来自 Pixabay

在 Python 中,字典是一种数据结构,它包含键-值对形式的元素,其中键用于访问字典的值。Python 字典是无序和可变的,即字典的元素可以改变。

在本文中,我们将探索合并两个或更多字典的五种不同方法,以及一种粗略的方法。

对于本文,让我们创建两个字典d1d2,我们希望将它们连接成一个字典:

d1 = {'India': 'Delhi',
      'Canada': 'Ottawa',
      'United States': 'Washington D. C.'}

d2 = {'France': 'Paris',
      'Malaysia': 'Kuala Lumpur'}

粗暴的方式

通过用第一个字典迭代第二个字典的键值对,可以合并两个字典。

d3 = d1.copy()
for key, value in d2.items():
    d3[key] = value

print(d3)
Output:

{'India': 'Delhi',
 'Canada': 'Ottawa',
 'United States': 'Washington D. C.',
 'France': 'Paris',
 'Malaysia': 'Kuala Lumpur'}

现在,让我们看看合并字典的更干净、更好的方法:

方法 1:使用更新方法

Dictionary 有一个方法 update() ,该方法将 dictionary 与其他 dictionary 中的条目合并,并覆盖现有的键。

d4 = d1.copy()
d4.update(d2)

print(d4)
Output:
{'India': 'Delhi',
 'Canada': 'Ottawa',
 'United States': 'Washington D. C.',
 'France': 'Paris',
 'Malaysia': 'Kuala Lumpur'}

update 方法修改当前字典。因此,在对字典进行操作之前,您可能需要创建字典的副本。

方法 2:使用解包操作符

我们可以通过简单地使用解包操作符(**)将字典合并在一行中。

d5 = {**d1, **d2}

print(d5)
Output:
{'India': 'Delhi',
 'Canada': 'Ottawa',
 'United States': 'Washington D. C.',
 'France': 'Paris',
 'Malaysia': 'Kuala Lumpur'}

我们也可以用这种方法合并多个字典。

{**dict1, **dict2, **dict3}

方法 3:使用集合。链式地图

这可能是最不为人知的合并字典的方法。集合模块中的
ChainMap 类将多个字典组合在一个视图中。

from collections import ChainMap
d6 = ChainMap(d1, d2)

print(d6)
Output:
ChainMap({'Canada': 'Ottawa',
          'India': 'Delhi',
          'United States': 'Washington D. C.'},
         {'France': 'Paris',
          'Malaysia': 'Kuala Lumpur'})

这个方法返回一个 ChainMap 类的对象。我们仍然可以像使用任何其他词典一样使用这个对象。例如d6[’India’]将返回'Delhi’

然而,在两个字典中有相同键的情况下,这个方法将返回第一个字典的值,这与从第二个字典返回值的其他方法不同。

x = {'A': 1, 'B': 2}
y = {'B': 10, 'C': 20}

z = ChainMap(x, y)
z['B']

# outputs 2

方法 4:打开第二本字典

我们可以通过打开第二本字典来合并字典。

d7 = dict(d1, **d2)

print(d7)
Output:
{'India': 'Delhi',
 'Canada': 'Ottawa',
 'United States': 'Washington D. C.',
 'France': 'Paris',
 'Malaysia': 'Kuala Lumpur'}

但是,只有当第二个字典的键是字符串时,这种方法才有效。

x = {1: 'A', 2: 'B'}
y = {3: 'C', 4: 'D'}

z = dict(x, **y)
Output:
TypeError: keyword arguments must be strings

方法 5:使用合并运算符

Python 3.9 在dict类中引入了合并操作符(|)。使用 merge 操作符,我们可以在一行代码中组合字典。

d8 = d1 | d2

print(d8)
Output:
{'India': 'Delhi',
 'Canada': 'Ottawa',
 'United States': 'Washington D. C.',
 'France': 'Paris',
 'Malaysia': 'Kuala Lumpur'}

我们还可以通过使用更新操作符(|=)来合并字典。

d1 |= d2

资源

本文中使用的代码片段可以在我的 GitHub 页面上找到。

让我们连接

领英:https://www.linkedin.com/in/jimit105/
GitHub:https://github.com/jimit105
推特:https://twitter.com/jimit105

合并数据:熊猫丢失输出

原文:https://towardsdatascience.com/merging-data-the-pandas-missing-output-dafca42c9fe?source=collection_archive---------26-----------------------

详细命令行界面输出的图像。有时需要详细的输出。有时候不会。图片来源:“Via Design Pickle”——更多关于属性。

给新接触合并熊猫数据的人的快速提示

TLDR:有时你想要罗嗦。有时候不会。阅读下面的提示来生成额外的输出,这将有助于评估 Pandas 中合并操作的成功。

介绍

我的第一个统计编程语言是 Stata,它有点冗长。然后学了 Python,当然也包括熊猫,也没那么啰嗦。像这样的转变可能会很艰难。本文讨论了我学到的一种技术,这种技术对于任何对合并操作之后的数据探索感兴趣的人都很有用。

在第一部分中,我将展示 Pandas 中的合并操作是如何产生零自动化输出的。在接下来的部分,我将解释为什么这样的输出是有用的。最后,在最后我将解释如何复制输出。

Stata 宠坏你:丢失的输出

Stata 往往比其他编程语言更加冗长。当执行如下图所示的合并时,Stata 会立即提供输出,并创建一个名为 _merge 的指示变量,该变量可以帮助评估合并操作是否成功。

Stata 中合并操作的图像及其默认输出。图片来源:“作者截屏”——更多关于属性。

将上面 Stata 的输出与下面 Python 的输出进行比较。很棘手,对吧?Python 没有输出。此外,没有指示变量。不是默认的。在下一节中,我将解释为什么这个输出和指示器变量是有用的。

Pandas 中合并操作的图像,以及它缺少默认输出。图片来源:“作者截屏”——更多关于归属。

为什么输出和指标是有用的

在上面给出的例子中,我合并了两个数据源。这两个数据源并不完全匹配。

第一个数据源是高等教育机构的列表(其中包括一些不是机构的“机构”类型,它们是其他的东西,包括一个称为“行政单位”的类别)。

第二个数据源是注册数据。当然,合并并不是完美的匹配,因为没有行政单位的注册数据。在 Stata 中,下面的代码和输出开始显示合并操作不完美的原因。

探究合并操作结果的交叉制表图。图片来源:“作者截屏”——更多关于属性的。

具体来说,没有一个行政单位有注册信息。然后,出于某种原因,一些其他类型的机构有时也不报告注册信息。这个列表可以帮助划分和计划与评估合并操作成功相关的工作。

下一节演示如何用 Python 复制这个输出。

如何复制产出和指标

下面的代码复制 Stata 的输出和相关的指示器。注意增加了指示器选项。

此外,还增加了一个 how 选项。各种合并类型超出了本文的范围,因此简而言之,添加 how 选项将包括来自两个数据集的列。

简单的值计数为探索合并结果提供了一个起点,如下所示。以下代码和输出进一步演示了如何将指示器变量与其他变量结合使用,以进一步评估合并结果。

探究合并结果的值计数和交叉制表的图像。图片鸣谢:“作者截屏”——更多关于归属。

再次看到这里,没有一个行政单位有招生信息。与上面的列表一样,这个列表可以帮助划分和计划与评估合并操作成功相关的工作。

结论

在本文的第一部分中,我们展示了在 Python 中,合并操作之后,如何实现零自动化输出。在第二部分,本文解释了为什么这样的输出是有用的。最后,本文还解释了如何复制该输出。

[## 加入我的介绍链接媒体-亚当罗斯纳尔逊

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

adamrossnelson.medium.com](https://adamrossnelson.medium.com/membership)

感谢阅读

如果你喜欢我要说的,可以在 adamrossnelson.medium.com 的找到更多。

感谢阅读。把你的想法和主意发给我。你可以写信只是为了说声嗨。如果你真的需要告诉我是怎么错的,我期待着尽快和你聊天。推特:@ adamrossnelson| LinkedIn:亚当·罗斯·纳尔逊 |脸书:亚当·罗斯·纳尔逊。

在 Python 3.9 中合并字典

原文:https://towardsdatascience.com/merging-dictionaries-in-python-3-9-3b0409aa91a8?source=collection_archive---------2-----------------------

Python 初学者

语法简洁的 Python 字典

丹尼尔·科内斯基在 Unsplash 上的照片

Python 3.9 中有一个改变游戏规则的新特性,允许你在处理 Python 字典的同时,编写更多可读紧凑代码。

Python 版本

你现在用的是哪个版本的 Python?3.7?3.5?还是还是 2.7?上次我们介绍了 Python 3.8 中的 6 个新特性,即使是初学者也应该注意。如果你还没有读过这篇文章,可以去看看。

[## Python 3.8 中针对 Python 新手的 6 项新特性

请做好准备,因为 Python 2 不再受支持

towardsdatascience.com](/6-new-features-in-python-3-8-for-python-newbies-dc2e7b804acc)

Python 3.9 现在正处于开发的 alpha 阶段,许多新特性已经被提出并被接受!它将在 2020 年 5 月进入测试阶段,届时将不会提出任何新功能。

第一个稳定版本将于 2020 年 10 月发布。你可以在这里找到发布时间表。

有一个新功能涉及字典。

Python 词典

Dictionary 是 Python 中一个非常独特的数据结构。一个字典包含多个元素,每个元素是一个键-值对。例如,让我们用两个元素初始化一个字典d1。关键字'name'的值为'Tom',而关键字'age'的值为 20。

d1 = {'name': 'Tom', 'age': 20}

我们现在有一本存储 20 岁的汤姆的信息的字典。

Roman Bürki 在 Unsplash 上拍摄的照片

假设出于某种原因,你收集了更多关于汤姆的信息,比如他的平均绩点和婚姻状况。你现在有了另一本叫做d2的字典。

d2 = {'gpa': 4.0, 'is_single': True}

您希望将这两本词典合并在一起,因为它们都包含关于同一个人 Tom 的不同信息。

问题是— 如何用 Python 合并两个字典?

1.笨拙的方式

您可以使用带有语法dict_name[key]= value的赋值操作符=在现有字典中插入一个新元素。

d1 = {'name': 'Tom', 'age': 20}
d1['sex'] = 'Male'# d1 == {'name': 'Tom', 'age': 20, 'sex': 'Male'}

因此,在不使用任何特定于字典的方法的情况下,想到的第一个方法是编写一个 for-loop ,使用 iterable .items()遍历每个键值对,然后将键值对插入新字典dnew

d1 = {'name': 'Tom', 'age': 20}
d2 = {'gpa': 4.0, 'is_single': True}
dnew = dict()for key, value in d1.items():
    dnew[key] = value
for key, value in d2.items():
    dnew[key] = value# dnew == {'name': 'Tom', 'age': 20, 'gpa': 4.0, 'is_single': True}

尽管如此,合并字典应该是非常简单和直接的事情,并且应该在一行代码中完成。

照片由沙哈达特·拉赫曼在 Unsplash 上拍摄

我们可以做得更好。好多了。

2.默认方式

实际上有一个内置的方法,可以用另一个词典d2来‘更新’一个词典d1

dnew = d1.copy()
dnew.update(d2)

一个缺点是.update()就地修改了字典。您需要首先通过复制d1来创建一个新的字典dnew。这种“内置”方法违背了使用方便的内置方法合并词典的目的。

我们能在一行代码中完成合并吗?是啊!

3.“整洁”的方式

Python 从 3.5+版本开始支持字典解包**。您可以通过解包两个字典的元素来创建一个新的“合并”字典。

dnew = {**d1, **d2}

这种解包方法成为从 Python 3.5+合并字典的事实方法。然而,这种语法对你们中的一些人来说可能很难看,对我们大多数人来说肯定不直观。第一次看到它时,你能猜出它的意思吗?

还有另一种简洁的方法可以在一行中实现字典合并。它看起来也不直观。

dnew = dict(d1, **d2)

照片由普贡达兰干清真寺在 Unsplash 拍摄

Python 3.9 中的简洁方式

Python 3.9 引入了新的和干净的(!)使用联合运算符** |合并字典的方法。相当整洁。**

dnew = d1 | d2# dnew == {'name': 'Tom', 'age': 20, 'gpa': 4.0, 'is_single': True}

这个 union 操作符实际上在 Python 中并不新鲜。它可用于“合并”两个集合。一个集合是一个无序且未索引的集合,也是用花括号写的。

a = {1, 2, 3}
b = {3, 4, 5}
print( a | b )
# {1, 2, 3, 4, 5}

扩充赋值

对于两个列表或两个值ab , a += ba = a+b的简称。

这种增强的赋值行为也适用于字典联合操作符。这意味着d1 |= d2相当于d1 = d1 | d2

警告

集合是无序的。字典是插入有序的(来自 Python 3.6)。换句话说,词典 记住了 插入条目的顺序。

这意味着字典联合是不可交换的 T21。这意味着d1 | d2d2 | d1将会产生具有不同项目顺序的合并字典。

感谢您的阅读!Python 3.9 中还有其他新特性,包括对变量注释的更新。不知道那是什么?查看以下关于静态类型和注释的文章。

** [## Python 中的静态类型

轻松进行类型检查

towardsdatascience.com](/static-typing-in-python-55aa6dfe61b4)

如果您想收到我的新文章的更新,您可以使用下面的滑块订阅我的时事通讯:

如果您对 Python 感兴趣,以下文章可能会有用:

[## 我希望我能早点知道的 5 个 Python 特性

超越 lambda、map 和 filter 的 Python 技巧

towardsdatascience.com](/5-python-features-i-wish-i-had-known-earlier-bc16e4a13bf4) [## Python 初学者应该避免的 4 个常见错误

我很艰难地学会了,但你不需要

towardsdatascience.com](/4-common-mistakes-python-beginners-should-avoid-89bcebd2c628)

快乐编码!**

信息疲劳 vs FOMO。人工智能如何帮助解决有意义交流的困境

原文:https://towardsdatascience.com/message-fatigue-vs-fomo-how-ai-can-help-to-solve-the-dilemma-of-meaningful-communication-cd9a187130a2?source=collection_archive---------34-----------------------

你在做什么 GIF By Gifnews

在当今的数字世界中,每个人都可以轻松访问互联网。由于访问方便,我们都想了解世界各地正在发生的活动并保持更新。这些活动涵盖新闻和体育更新、政治评论、商业和经济新闻头条,以及通过 Instagram、Twitter、Snapchat 和脸书等社交媒体渠道与朋友互动。通过跟踪所有这些事件,我们使自己受制于通常所说的信息过载。实际上,我们正淹没在网上铺天盖地而来的信息浪潮中。我们大部分时间都在网上度过,很难有足够的时间在家陪家人。换句话说,你的生活中没有任何个人空间。

另一方面,有些人试图大大减少他们参与任何在线活动的时间。事实上,有些人干脆一了百了,给自己下了一个禁止网上交流的禁令。人们做出这个决定是为了享受他们的个人空间,而不是成为信息过载的牺牲品。然而,远离互联网,推而广之,不使自己跟上当前世界的发展在 FOMO 达到顶峰,这就是对错过的恐惧。

信息过载和 FOMO 之间存在着明显的冲突,大多数人都在努力在这两种现象之间取得平衡。

什么是信息过载?

术语“信息过载”,也就是通常所说的“信息焦虑”和“信息肥胖”,是指当你拥有大量关于某个特定问题的信息时,你在了解该问题并有效地做出决策时所面临的问题。这就是我们所说的信息过载的教科书定义。通俗地说,当你每天接收大量信息时,就会产生信息过载。

当今世界信息过载的常见原因包括:

  • 不断创造大量新信息
  • 在互联网上复制和共享信息的便捷性
  • 你接收信息的媒介大幅增加:电视、广播、印刷媒体、社交媒体、电子邮件、网站等等
  • 没有简单明了的方法来快速处理和评估不同的信息源
  • 网上有大量相互矛盾和冲突的信息

为了防止接触过多的信息,现代千禧一代试图以各种方式应对信息过载。其中一些方法包括取消在线杂志订阅,删除一些不必要的社交媒体账户,以及过滤进入你电子邮件收件箱的信息。然而,网上的大量信息只能进行一定程度的过滤。因此,这些策略通常被证明不足以应对信息过载的压力。

文字感叹 GIF

什么是 FOMO(害怕错过)?

FOMO(害怕错过)是一个真实的现象,如今已经变得非常普遍。FOMO 会对你产生负面影响,给你的生活带来很多压力。了解 FOMO 实际上是什么,如何在你的生活中识别它的症状,以及如何处理它是非常重要的。

对错过的恐惧是一种感知或感觉,你周围的人比你过着更好的生活,或者比你过得更开心。它包含一种怨恨和嫉妒的感觉,并对你的自尊产生负面影响。由于 Instagram、Twitter 和脸书等社交媒体的存在,错过机会的恐惧往往会加剧。例如,当你看到你的朋友在周末聚会并且玩得很开心的照片时,你会感到无助,因为你错过了很多乐趣。

如果你对以下问题的回答是“是”,那么你可能是害怕错过的受害者:

  • 你害怕别人比你有更多有价值的经历吗?
  • 当你的朋友在没有你的情况下玩得很开心,或者他们没有邀请你去他们的聚会时,你会感到焦虑吗?
  • 当你不知道你的朋友在做什么时,你会感到不安吗?
  • 你会全天候监视你的朋友吗?
  • 当你错过了和朋友约会的机会时,你会感到困扰吗?

第二幕 GIF

人们如何处理信息过载与害怕错过的困境?

完全忽略了这个问题

有些人没有意识到,甚至忽视了,害怕错过和信息超载之间的两难困境确实存在。他们试图在个人生活和网络活动上投入同等的时间,同时兼顾这两项任务。然而,大多数人未能在两者之间取得平衡,这最终导致情绪和精神疲劳。为了增进你的人际关系,时不时地进行数字排毒是很重要的。

关闭大卫·施莱格里的插图

采用时间管理策略

这是人们常用的一种技术,这样他们就可以两全其美(个人空间和在线交流)。这是如何工作的,你为自己制定一个时间表,表明你每天将花多少时间与家人互动,一天中的哪一部分将用于上网冲浪和与外界联系。你要确保不要超过任何一项活动的时间限制。有几款手机应用可以用来限制你的屏幕时间,从而更有效地管理你的时间。

然而,以这种方式有效地管理你的时间需要自律。这是当代大多数成员所缺乏的积极品质。

使用双重账户

这是千禧一代使用的另一种流行策略。个人分别为工作目的和私人交流建立单独的社交媒体账户(Whatsapp 和脸书)。你可以使用 Whatsapp 上的个人群组与家人进行私人通信,而工作组/账户则被用作与同事进行官方互动的媒介。

您也可以在这些帐户之间切换。这使你能够同时满足个人和职业需求。

谷歌商店上有几个应用可以帮助你有效管理双重账户。

社交媒体发 GIF 短信

基于人工智能(AI)的聊天机器人如何解决这一困境?

人工智能聊天机器人是解决信息过载和 FOMO 之间困境的理想灵丹妙药。这些聊天机器人利用了机器学习算法,足以承受你在线活动的冲击,以便你可以花足够的时间与家人在一起。例如,人工智能聊天机器人可以代表你与 Facebook Messenger 上的个人通信。如果您是一个组织,并且每天都要处理几个客户查询,这将非常方便。人工智能聊天机器人的设计是为了在不需要你干预的情况下满足所有这些问题。因此,你有更多的时间和你的亲戚联系,和你的家人共度美好时光。同样,基于人工智能的聊天机器人可以代表你与你联系人列表中的所有人联系。这为您省去单独回复每封邮件的麻烦。

这些聊天机器人还可以通知你全球当前发生的所有活动,以便你随时与外界保持联系,即使你在家与家人在一起。

帕勒洛特斯制作的会说话的 GIF 动画

基于人工智能的聊天机器人世界的最新发展

基于人工智能的聊天机器人领域的最新趋势包括

人工智能聊天机器人日益流行

自诞生以来,人工智能语音机器人最近获得了很大的吸引力。文本通信通常会很枯燥。因此,语音机器人是与您的客户互动和高效互动的完美解决方案。此外,支持语音的聊天机器人使您能够为您的消费者提供实时、可靠的数据洞察。语音机器人提供了更加个性化的体验,增强了客户体验。

通过人工智能聊天机器人实现自动支付

允许用户直接通过实时聊天或 Facebook Messenger 进行支付是人工智能聊天机器人技术领域的最新发展之一。然而,这项技术仍处于萌芽阶段,要全面实施还需要时间。其工作原理是,您可以通过 Messenger 直接购买您的产品。人工智能聊天机器人将在整个交易过程中为你提供便利。

不用说,AI 聊天机器人技术在未来将发挥举足轻重的作用。利用这项技术让你的生活变得更轻松、更便捷,这是符合你的最佳利益的。在当今这个互联互通的世界里,我们非常渴望有人或东西能够处理我们在 Messenger 中的聊天,这样我们就可以享受一次数字休息。像 AIBRO 这样基于人工智能的聊天机器人系统可以代表你与 Facebook Messenger 上的联系人通信,特别是当我们很忙、在度假、睡觉或驾驶你的汽车时。

介绍 AIBRO ,个人聊天机器人创作系统

或者,您也可以使用输入法信使。这是一个应用程序,可以让你更有效地整理你的电报聊天,并提供神经机器人生成的短语,你可以用它作为回应。

除了 AIBRO 和 iMe Messenger,你还可以使用其他流行的 AI 聊天机器人和软件系统,如沃森助手和 Bold360 来对抗信息过载和 FOMO。

沃森助手本质上是一种人工智能产品,允许你将对话式交互部署到任何设备或应用程序中。这个虚拟助手知道什么时候从知识库中精确地搜索答案,什么时候将用户引导到人类。

Bold360 是另一个流行的软件系统。作为智能客户互动解决方案,Bold360 利用 NLU(自然语言理解)从第一次互动开始就理解客户的需求。这种直观的平台提供电子邮件、消息和实时聊天,可以带来非常个性化的实时体验。

消息中的消息

原文:https://towardsdatascience.com/message-in-a-message-44b89090b3b8?source=collection_archive---------48-----------------------

探索语言的深层隐写术

Ste ga no graph y / stegəˈnägrəfi /(名词):将消息或信息隐藏在其他非机密文本或数据中的做法。

剧情简介:使用深度学习可以有效地隐藏语言中的敏感信息,而不会引起窃听者的怀疑。这对于安全通信具有重要意义。

编辑 09/06/20: 查看文末为机器生成的总结!很快会有更多的人朝这个方向前进。😃

隐写术多年来一直用于以隐藏的方式交流信息。一个自然的问题:这和密码学有什么不同?难道密码学不是一个研究得很好的领域吗?在这个领域中,两个人的目标是在不被窃听者发现的情况下相互共享信息。事实上,这两个领域非常相似,但隐写术有一个有趣的特性,它将信息共享提升到了一个完全不同的水平:信息被共享,而窃听者甚至不知道任何秘密正在被共享。比如说 Shor 算法(用量子计算机在多项式时间内破解 RSA 加密)如果连解密什么都不知道有什么用?

隐写术长期以来一直与绘画和视觉艺术联系在一起。画家经常在作品中隐藏签名、自画像和其他秘密信息,作为“内部笑话”。这方面的一个例子是杰森·布拉克的“壁画”,其中波洛克将他的整个名字隐藏在作品的弯曲部分。

上图:杰森·布拉克的壁画(1943 年)。在知识共享协议 CC BY-ND 2.0 下许可的图像。下图:艺术史学家亨利·亚当斯的签名分析。

然而,直到最近,图像的计算隐写方法(如在. jpg 文件的末尾附加比特或应用数学函数来选择 RGB 像素值)都很容易检测和发现,而手工制作的方法很难并且不可扩展。

2017 年,Shumeet Baluja 在他的论文“在平视下隐藏图像:深度隐写术”[1]中提出了将深度学习用于图像隐写的想法。在本文中,第一神经网络(隐藏网络)接收两个图像,一个封面和一个消息。隐藏网络的目的是创建第三图像,即容器图像,其在视觉上类似于封面图像,并且能够被第二神经网络(显示网络)使用,以经由显示的图像重建消息图像(不知道原始消息或原始封面)。损失由封面和容器图像的相似程度以及消息和显示图像的相似程度来定义。几个月后,Zhu 等人扩展了这个概念,允许将任意数据编码到图像中[2]。结果令人震惊:网络能够创建看起来非常像封面的容器图像,但允许揭示网络非常接近地重建信息。

简化中提出的架构隐藏图像:深度隐写术。作者图片

虽然这个结果非常有趣,但我们认为专门针对图像的隐写术的效用是有限的。

问题来了:这种方法在其他信息领域有什么限制?

更具体地说,目标是以文本和音频T21 的形式将这种方法应用于人类语言领域,这可以作为实现这种通用信息程序的垫脚石。

用于书面语言和其他文本信息的深度隐写术

文本更难执行隐写术:图像密集而文本稀疏;图像不会受到像素值微小变化的太大影响,而文本会受到标记值微小变化的极大影响。虽然存在用于进行基于文本的隐写分析的各种方法,但是它们面临着巨大的挑战:(1)经典的基于启发式的方法通常容易解码,因为它们利用固定的、容易可逆的规则,以及(2)当前的方法没有利用文本的任何结构属性,导致隐藏的消息在语义上对人类来说不正确或不连贯。

最近的深度学习方法[3,4,5,6]依赖于使用生成模型来隐藏无意义单词分组中的“秘密”文本。这里,我们想建议使用基于转换器的方法来同时解决这两个问题。我们探索使用转换器将所需的秘密文本与一些人类可读的、连贯的封面文本相结合,以生成新的容器文本,该容器文本既正确地编码了其中的隐藏消息,又与封面文本几乎相同,保留了封面文本的原始语义结构和易读性。除了用于编码的转换器之外,我们还利用第二个转换器模型来解码容器文本并恢复隐藏的消息。

来自尼尔斯·阿克曼(Nils Ackermann)的《1D 对 2D 有线电视新闻网》,该节目在知识共享协议 CC BY-ND 4.0 下获得许可

由于变压器体积庞大,我们首先用一种更简单的基于 1D 卷积字符的方法 CharCNN [7]来测试我们的运气。

在这种基于字符的方法中,其思想是模型将学习一串文本中字符选择的统计特征,并以发送信号的方式修改字符,通过字符的添加、替换或删除来捕获隐藏的信息。

考虑一个简单的例子,其中消息是两位的。为了传递秘密消息,我们的函数是容器消息的长度模 4。更具体地说,让 l 表示容器消息中的字符数。 l ≡ 0 (mod 4)得 00, l ≡ 1 (mod 4)得 01, l ≡ 2 (mod 4)得 10, l ≡ 3 (mod 4)得 11。该模型将相应地从封面移除或添加字符来传达秘密消息。在实践中,我们希望我们的模型更健壮,通过容器文本产生更复杂的秘密消息。这种方法在隐写和重构度量上都给出了一些可识别的结果。

我简直不敢相信自己的眼睛,我在森林里看到的一切远远超出了我的想象。

秘密:明天日落时分在河边见面。

集装箱:我现在把我的行李放在一个房间里,从房间的远处到我想象的地方。

被揭露的秘密:tt 的第一次旅行。

令人惊讶的是,这些信息仍然可以被解码(尽管很明显消息已经被修改)。

在这一领域出现了一个有趣的(可能尚未解决的)信息论问题:给定一个信息领域(如图像、文本等)。),一般情况下一个模型在给定的封面信息中能隐藏多少秘密信息?我们开始看到,随着更大的秘密消息输入大小和静态隐藏消息大小,模型隐藏信息和重构隐藏消息的时间越来越困难。每项任务有多好取决于我们如何在损失函数中对这两项任务进行加权。

接下来,我们决定研究一个更大的模型来执行文本隐写术。我们提出的解决基于文本的隐写术挑战的主要方法包括利用两个 NMT(神经机器翻译)模型:一个变换器模型对隐藏消息进行编码,另一个模型对其进行解码。我们假设,这种基于转换器的方法可能成功地在封面文本中编码秘密文本,以产生与封面文本的语义结构紧密匹配的容器文本。这样做的另一个好处是不需要定制数据集:任何句子或短语的集合以及随机生成的秘密消息都可以。

在这种情况下,盖子和容器之间的“相似性”是什么意思?我们不再有像编辑距离或像素值之间的 L2 范数这样的简单度量。在我们的新方案中,句子“不要吃,我的朋友!”还有“不要吃我的朋友!”意思完全不同,而“不要吃,我的朋友!”和“请戒食,我真正关心的人!”有类似的意思。为了确定相似性的度量,我们利用 BERT(BI directionalEn coderRpresentations fromTtransformers【8】),这是一个预训练的语言模型,可以将句子表示为实值向量(使用[SEP] token 的向量),其中两个向量之间的余弦相似性是句子在意义上有多相似的良好指示。

在神经语言隐写术【6】中呈现的结果,与我们自己的工作最密切相关,表明最先进的基于转换器的语言模型,如 GPT-3,可以用来生成令人信服的封面文本来隐藏秘密信息。在我们的实现中,我们的第一个 NMT 变换器模型读入连接的秘密消息(基数为 10 的四位数)和封面文本,并继续将它们翻译成容器文本。我们的第二个转换器读入容器文本,并将其翻译成原始秘密消息的重构。同样,我们使用的损失函数包括封面文本和容器文本之间的相似性函数的线性组合(使用 BERT 来产生 Loss_Stego),以及重构的秘密消息和原始秘密消息之间的编辑距离。损失函数被(有点幽默地)表述为

其中 c 是封面实例, c 是容器实例, s 是秘密消息, s 是重构的消息。损失函数中的 αβ 是我们可以设置或改变的参数,作为时期或损失率变化的函数。我们将隐写文本(或容器文本)和封面文本之间关于意义的相似性定义为由预训练的 BERT 基模型生成的两个序列的嵌入的余弦相似性。

我们发现我们使用的模型,一个关注隐藏网络和显示网络的 LSTM seq2seq 模型,不足以生成好的容器,并且在重构秘密消息时有缺陷。亏损迅速收敛,亏损相当高。我们还假设,低损失可能是 BERT 的生成对抗模型的结果:找到对人类无意义的句子,但根据 BERT 的评估,这些句子在嵌入封面文本时具有小的余弦相似性。下面是一个输出示例:

封面:庆祝你有机会吃这个。

秘密 : 8 4 4 4。

容器:祝福脚踏安瓿 mbi mbi 贾坎德安瓿去核实质性实质性宁静踏实默多克小聪明 germane obeng。

泄露的秘密:8 4 1 4。

尽管这个例子很弱,但我们也认为,有了足够强大 NMT 模型和足够的计算能力,我们将开始在文本和一般信息上观察到有用的自然语言隐写术。这种技术可能会彻底改变存在敌对窃听者的通信,特别是在普通密码协议快速解密的量子时代。这个实现是留给那些拥有大量计算能力人的未来工作。(seq2seq 型号的代码可在本专栏中查看。)

用于语音和其他音频信息的深度隐写术

虽然对文本进行深度隐写可能还有很长的路要走,但对声音信息(声音文件)的类似方法肯定是触手可及的。为什么文本比图像更难以执行隐写术的核心区别在于文本是稀疏的:在一行文本中,每个单词都可以用一个自然数来表示,并且在给定的句子中通常不超过 100 个单词。然而,图像是密集的:也就是说,一幅图像由大量的像素表示,每个像素有 16777216 个可能的值(对于 RGB 图像)。

声波的密度类似,取决于它们的表现方式。我们来看看声波信息的两种表现方式:频谱图波形图

  1. 声谱图是音频的视觉表示。具体而言,信号随时间变化的频谱在频谱图中由时间序列热图的颜色和强度表示。下面是我自己说“这是一个秘密信息:我的秘密信息”的声谱图。为了本文的视觉效果,我们将重点放在光谱图上。
  2. 波形是作为时间函数的声音信号的图形形状。波形可以用示波器可视化,以分析诸如振幅、频率、上升时间、时间间隔、失真等属性。

我发声的声谱图“这是一个秘密信息:我的秘密信息”。图片作者。

正如 所提出的在众目睽睽之下隐藏图像:深度隐写术【1】声谱图可以作为一幅图像使用其 2D 特征图声谱图进行操作,声谱图可以进行线性或对数缩放。秘密消息可以是图像、文本或其他音频数据。从声音中提取频谱图有三种主要方式:1)短时傅立叶变换(STFT),滤波器在线性频率轴上均匀分布;2)对数 STFT,与 1)相同,但是具有在对数频率轴上等间隔的滤波器,以及 3)随机矩阵变换(RMT);与 1)和 2)相关,但是用随机矩阵 R 代替离散傅立叶变换矩阵。

这里,我们可以使用 2D U-Net 架构[9]来学习频谱图的隐写术。

用于将秘密图像编码到封面音频中的 U-Net 架构。图片作者。**

我们还可以使用卷积模型来学习原始音频波形(STFT)的隐写术,正如 Kreuk 等人在 2020 年 7 月的Hide and Speak:Towards Deep Neural Networks for Speech Steganography【10】中提出的那样,结果令人印象深刻。在这两种情况下,深度学习模型训练过程大体上是相同的:隐藏器网络和揭示器网络必须以这样的方式并行训练,即隐藏器网络能够生成在听觉上类似于给出的封面音频的容器音频数据(实际上,这种被扰乱的容器音频具有一点点“模糊”的声音),然后可以被揭示器网络用来揭示也给出的秘密音频。

端到端地,使用该系统创建的产品可以在训练隐藏器和展示器网络之后被使用,如图所示:

声谱图法深度音频隐写的系统流程。图片作者。**

如图所示,Bob 试图将我的图像隐藏在声谱图中。隐藏器模型接收频谱图和秘密消息,产生具有小扰动的结果修改频谱图。这个声谱图通过互联网发送给 Alice,Alice 使用 revealer 模型将容器声谱图转换成重建的(稍微修改的)秘密图像。音频 STFT 波形上的卷积架构实现了类似的过程。

将图像隐藏在声谱图内(左)和将声谱图隐藏在声谱图内(右)的示例。图片作者。**

总结一下…

深度隐写术对于安全通信以及信息机器学习云提供商的水印和服务责任具有重要意义。这些只是初步的、未发表的结果,尚未整合到任何类型的产品中,但它们为深度隐写术在未来保护我们信息安全的潜力提供了一个充满希望的视角。

感谢 Mario Srouji、Dian Ang Yap、Michele Catasta、Brad Efron、Ashish Kundu、Mustafa Canim 和 Christopher Manning 的参与和贡献!

我在 LinkedIn 、 Medium 和 Twitter 上。

机器生成的摘要

正如承诺的那样,这是机器生成的摘要,经过最小程度的编辑(替换这里和那里的[UNK]标记,大写单词,删除多余的空格…除了段落选择之外没有经过精心挑选!).这是我正在做的另一个项目…更多即将推出。原文 2400+字。

总结(473 字):

人们多年来一直使用隐写术以隐藏的方式交流信息。它很早就与绘画和视觉艺术联系在一起,Baluja 在他的论文中提出了将深度学习用于图像隐写的想法。第一个神经网络接收两个图像来创建第三个图像,第二个神经网络可以使用第三个图像来通过显示的图像显示消息。几个月后,et 扩展了这个概念,允许将任意数据编码到图像中。

对于书面语言,其思想是模型将学习一串文本中字符选择的统计轮廓,并以通过字符或字符向隐藏信息发送信号的方式修改它们。当前的方法依赖于使用生成模型来隐藏隐藏的消息。新方法使用第二个模型将所需文本与一些连贯的封面文本组合起来,以创建容器文本。l 表示容器中的字符数。该模型将从封面上移除或添加字符来传达秘密。该方法已经给出了一些可识别的结果,但是信息仍然是隐藏的。

对秘密消息进行深入分析的主要方法包括两个模型:一个读入隐藏的消息,另一个将它翻译成容器文本。损失函数由封面文本和容器文本之间的相似性函数的线性组合组成,以创建秘密消息。关注隐藏网络的模型不够强大,不足以生成好的容器,并且在秘密方面有缺陷。低损失可能是用于寻找相似性小的句子的生成对抗模型的结果。一个足够强大有力的模型,足够多的人,就会开始观察有用的自然语言。实现是留给那些有很多钱的人的未来工作。

文本对文本执行深度隐写比对图像更难。图像由大量的文字来表示。波也有类似的表示。深度学习模型的训练过程基本相同:一个隐藏器网络和一个展示器网络。它能够生成类似于它被给予的封面音频的容器音频数据。然后,网络可以使用它来揭示秘密音频。使用该系统创建的产品可以在训练遮瑕膏之后和训练秘密时如图所示使用。一个模特正试图把我的照片藏在一个声谱图遮瑕模型里。该模型通过互联网发送给某人,该人使用该模型将容器转换成重构的谱图显示秘密。

深度隐写术可以在云中保护人们的信息安全。

[1] Baluja,S. (2017 年)。在众目睽睽之下隐藏图像:深度隐写术。在神经信息处理系统的进展(第 2069–2079 页)。

[2]朱,j .,卡普兰,r .,约翰逊,j .,,L. (2018)。隐藏:用深层网络隐藏数据。在欧洲计算机视觉会议(ECCV)* (第 657-672 页)。*

[3]杨志林,郭,徐清泉,陈志明,黄耀峰,张耀军(2018)。RNN-隐写术:基于递归神经网络的语言隐写术 IEEE 信息取证与安全汇刊,14 (5),1280–1295。

[4]t .方、j aggi m .和 Argyraki k .(2017 年)。用 LSTMs arXiv 预印本 arXiv:1705.10742 生成隐写文本。

[5]张春燕和克拉克(2010 年)。使用自动生成的释义进行语言隐写。在人类语言技术:2010 年计算语言学协会北美分会年会(第 591-599 页)。

[6]齐格勒,z .,邓,y .,&拉什,A. (2019)。神经语言隐写术 arXiv 预印本 arXiv:1909.01496

[7]张,x,赵,j .,,乐存,Y. (2015).用于文本分类的字符级卷积网络。在神经信息处理系统的进展(第 649–657 页)。

[8] Devlin,j .,Chang,M. W .,Lee,k .,& Toutanova,K. (2018 年)。 Bert:用于语言理解的深度双向转换器的预训练。 arXiv 预印本 arXiv:1810.04805

[9] Ronneberger,o .,Fischer,p .,& Brox,T. (2015 年 10 月)。 U-net:生物医学图像分割的卷积网络。在国际医学图像计算和计算机辅助介入会议(第 234-241 页)。斯普林格,查姆。

[10] Felix Kreuk、Yossi Adi、Bhiksha Raj、Rita Singh 和 Joseph Keshet。(2020).隐藏和说话:走向语音隐写术的深度神经网络。

元分析:背景和 Python 管道

原文:https://towardsdatascience.com/meta-analysis-background-and-python-pipeline-bccaf4fde362?source=collection_archive---------51-----------------------

背景

在研究中,我们通常以文章的形式发布我们的结果,其中发现与统计分析一起报告,这提供了一种评估观察到的效果的强度和合理性的方法。

虽然统计分析对任何研究论文都是至关重要的,但仅从一项研究得出结论可能不是最好的方法。

例如,一个人可能有一个太小的样本,而仍然得出结论的结果。小样本限制了你对所观察到的效应得出有意义结论的能力(用统计学术语来说,你缺乏能力)。通常(不幸的是,不是典型的),人们使用预先收集的数据(或使用其他公布的数据集)运行先验功效分析。也就是:"根据我们对想要研究的过程的了解,我们期望的影响大小是多少?”。使用历史数据有助于您对预期结果做出有根据的猜测,进而允许您计算所需的样本量。这背后的数学并不太复杂,但我不会在这里详细介绍。一些开源软件如 T2 钟佐泓 T3 允许你进行这种计算。

或者,您可能正在查看一组非常特殊的数据,大部分是由异常值创建的(通常,这将由足够大的统计能力来决定),因此您观察到的真实情况将不是您认为您的样本所来自的总体真实情况。

或者,你也可能对你的统计数据做了一些错误的事情。我自己记得运行 ANOVAs,非参数测试和相关性,需要满足一些假设,没有事先检查这些假设。糟糕的酒,糟糕!

元分析方法

现在,当研究类似过程的多篇论文发表时,一个有用的做法是一起回顾它们,看看每篇论文中独立收集的数据是否出现了趋势。这些所谓的“系统综述”对于概述某一特定过程中未探索的领域非常有用,这反过来将指导研究人员收集必要的数据来填充分布中缺失的部分。

另一种方法,也许更进一步,是进行荟萃分析。这与系统回顾的不同之处在于,元分析不仅仅是回顾给定过程的当前知识,还量化统计效应的强度,并提供总体评估。

方法

数据通常采用分布的形式,它有一些参数,如平均值和标准差。你可以对这些分布做所有的事情,比如将它们与某个值进行比较(单样本测试,t-测试或 Wilcoxon,如果参数假设得到满足;) )或者将它们与一些其他分布(成对测试、t-测试或 Mann-Whitney)等进行比较。

这非常有用,因为您可以判断这些分布是否彼此显著不同(尽管这种频繁主义方法也有一些缺点,但那是关于贝叶斯统计的另一篇文章)。

统计显著性是观察到的两个分布之间的差异是由于偶然因素引起的概率。如果 p 值大于任意选择的阈值(即α水平,通常等于 0.05),则假设观察到的差异可以用数据中的随机噪声来解释。

问题是,对于足够大的样本,统计测试通常会发现显著的差异,有时甚至是更低的α水平。这些看似重要的微小差异对研究结果来说往往是无用的,从中无法得出有意义的结论。事实上, p- 值不仅取决于效应的大小,还取决于样本的大小,这使得报告其他度量变得至关重要。这就是为什么从事统计比较的作者不仅应该报告 p 值,还应该报告分布之间的大小差异。

用雅各布·科恩的话说:

统计显著性是结果中最没意思的地方。你应该用数量来描述结果——不仅仅是一种治疗对人们有没有影响,而是它对人们的影响有多大。

一个经常被引用的说明这个问题的例子是一项医生健康研究,该研究调查了阿司匹林是否有助于预防心肌梗死(MI)。研究人员测试了大约 22000 名受试者,发现阿司匹林与心肌梗死的减少有关,显著性水平为 p 值…

Gene V. Glass 的话概括了一个很好的结论:

研究调查的主要产品是一个或多个效应大小的测量,而不是 P 值。

效应大小的提取

效果大小(ES)是一种总结观察到的效果强度的方法。通常,您的数据将采用分布的形式,具有平均值和标准差等参数(我假设读者知道这些概念)。因为我在这篇文章中使用的数据是基于这些参数的,所以我在下面描述了数据准备的分析管道。

假设您的第一项研究使用了两个不同的独立组,每个组都有一个平均值(M)和一个标准差(SD)。很容易将该数据转换成所谓的标准化效应大小,由下面的简单等式给出:

其中MSDn分别为每个分布 1 & 2 的均值、标准差和样本量。

请注意,通常情况下,平均值的标准误差(SEM)以数据的图形表示形式提供。然后,您可以使用以下公式转换到SD:

假设您筛选的第二项研究在两个不同的时间点(如治疗前和治疗后)使用了同一组。在这里,你是在处理一个主题内的设计,而不是主题间的设计。在这种情况下,您可以使用以下等式计算ES:

其中,Mt是平均初始测量值(通常是基线),M(t+i)是第二个时间点的测量值,SDt是初始测量期间分布的标准偏差,SD(t+i)是第二个测量点分布的标准偏差,N代表该组的样本量

效应大小的标准化

为了使所有测量具有相同的度量并便于解释,效应大小可以转换为相关系数,称为r,遵循以下等式:

在某些情况下,论文中实际提供了相关的统计数据,在这种情况下,可以使用以下等式:

在某些情况下(通常在旧出版物中),既没有可用的统计信息,也没有数据的图形表示,只报告了p值。在这种情况下,如果您报告了 p 值,则可以使用 z 得分,使用以下公式:

其中z是 z 分数值,N是样本量。你可以从 z-score 表中提取出z-scores,比如这个。但是请记住,p-值取决于组大小,应该谨慎评估。

组合效应大小和比较

在某种程度上,我们遇到了麻烦,因为随着距离 0 越来越远,r的值变得越来越倾斜。为了补偿这种影响,我们可以使用此处描述的费歇尔变换对影响大小进行标准化,遵循以下等式:

其中r是通过上述方法计算的效应大小。按照惯例, 𝑍𝑟 可以转换回 r 以便于解释。

如果你处理的是低样本量,这可能会在你的分析中产生一些偏差(< 20 or 10 in each group, see Nakagawa & Cuthill,2007 ),我们使用 Hedges & Olkin,1985 提出的公式计算了无偏 𝑍𝑟 (zru)值:

随机和固定效应模型

当进行元分析方法时,有必要使用固定效应或随机效应统计模型。固定效应模型假设所有效应大小测量相同的效应,而随机效应模型考虑了研究间效应的潜在差异。由于选择的模型会影响汇总估计的解释,因此可以通过进行异质性测试来测试使用哪个模型,从而生成等式中描述的Q-statistic。14.Q值是效果大小的离差的度量。该测量遵循具有k-1自由度的卡方分布,其中 k 是效应大小的总数。这个模型假设每个效应的方差大小( 𝑣𝑖

,情商。10)由固有采样误差引起的方差组成( 𝑣 0,等式。11 & 12),加上随机分布可变性的其他来源( 𝑣𝑟 ,等式 12)。为了估计这些值,您可以使用公式 10 至 15,这些公式由( Lipsey & Wilson,2001;中川&卡特希尔,2007 ):

作为对Q statistic的补充,我们可以使用等式提供 I^2 统计。16,它衡量了研究之间的差异百分比,这是由于真正的异质性,而不是机会。

其中 Q 通过等式计算。14,df 是效应大小数减 1,百分比值越高表明异质性越高。通常,I 将以百分比表示,并且可以有一个与之相关的p-值,如果该值显著,将表明大量的异质性,并为随机模型效应提供进一步的支持。

计算效应大小的置信区间

对于每个变量及其不同水平,可以使用方程计算平均效应大小、95%置信区间(CI)和 zscore 值。16,17,18,19。见 Nakagawa & Cuthill,2007 关于这个主题的更多信息,并注意还有其他建议的方法来比较这些值。

荟萃分析的额外辅助计算

在进行元分析时,可能还需要进行其他分析。特别是,文件抽屉分析(允许估计一个人可能需要多少更多的效应大小来消除任何发现的总体元分析效应)和漏斗图(允许评估发表偏倚)可能是令人感兴趣的。我不会谈论这些,但是如果你想在你的数据上运行这些,你可以看看 JASP。

最终注释

就是这样!所有这些方法都是我们从本文引用的参考资料中丢弃的。你应该持批评态度,在盲目应用它之前,想想它意味着什么。我自己在理解背后的一些逻辑时仍然有些困难(例如,等式(9)对我来说仍然有点模糊)。我也真的推荐你尝试阅读贝叶斯元分析,这可能是解决这个问题的一个非常强大的方法;)

这种方法背后的大部分数学都用 Python 编码在这个库中。这是正在进行的东西,所以如果你发现任何错误,请随时评论或联系!

如果你感兴趣的话,我还有一篇的博客文章,我会在那里浏览代码。

感谢阅读!

元标签和堆叠

原文:https://towardsdatascience.com/meta-labeling-and-stacking-f17a7f9804ec?source=collection_archive---------4-----------------------

📈Python for finance 系列

如何提高你的机器学习分数

由戴夫·甘迪根据公共领域专用许可拍摄的照片

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指南 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

警告:这里没有神奇的公式或圣杯,尽管一个新的世界可能会为你打开大门。

注 1: 如何安装mlfinlab包没有错误信息可以在这里找到

注 2: 如果你正在读马科斯·普拉多的 【金融机器学习进展】 7。是第五章关于 的细分特征 8。 数据标注 是第三章关于三重关卡的方法。和 9。 元标注是第 50 页第 3.6 章。****

注 3 : 由于算法或评估程序的随机性或数值精度的差异,您的结果可能会有所不同。但是我确实发现很多人取得了更高的分数,因为他们以 错误的 方式标准化了他们的训练和测试数据。在这篇文章的最后,我将揭示高分的大秘密。

📈Python For Finance 系列

  1. 识别异常值
  2. 识别异常值—第二部分
  3. 识别异常值—第三部分
  4. 程式化的事实
  5. 特征工程&特征选择
  6. 数据转换
  7. 微小差异特征
  8. 数据标签
  9. 元标签和堆叠

介绍

元标签已经在我的写作清单上坐了很长时间了。它是一个有用而强大的机器学习工具,可以收集在任何数据科学家的工具箱中,不管你使用的是什么模型。不幸的是,我几乎没有找到任何关于这个话题的像样的教程。而堆叠是一种流行的 集成方法 用于匹配学习。堆叠包括训练一个学习算法来组合其他几个学习算法的预测。正如我们所知,集成学习的基本思想是促进比单独从任何组成学习算法获得的更好的预测性能。这是一种“群体智慧”方法,从几个模型中提取信息,形成一组高度准确的结果。根据这个定义,元标记也应该属于集成方法。

虽然堆叠和元标记有一些相似之处,但它们是根本不同的。堆叠基本上包括两个步骤。首先,使用可用数据训练所有其他算法,然后使用其他算法的所有预测作为附加输入,训练组合器算法以进行最终预测。堆叠的过程是:

  1. 建立第一个基础模型,得到预测
  2. 用阈值过滤预测
  3. 将预测与输入合并为新的输入
  4. 建立第二个模型,并用新的输入对其进行训练
  5. 用第二个模型预测

很简单,我们可以把它看作是给我们的训练数据增加额外的特征。

而元标记利用了两层模型,但目的不同。根据 Marcos Lopez de Prado 在他的书《金融机器学习进展》第三章第 50 页(除了这本书,网上没有太多有用的信息)。

当你想获得更高的 F1 分数时,元标签尤其有用。首先,我们建立一个实现高召回率的模型,即使精度不是特别高。第二,我们通过将元标记应用于由主要模型预测的阳性来校正低精度。

中心思想是创建一个学习如何使用主模型的辅助 ML 模型。这导致了改进的性能指标,包括:准确度、精确度、召回率和 F1 分数等。

在马科斯的书中,元标签之所以如此有效的原因是:

二进制分类问题提出了 I 型错误(假阳性)和 II 型错误(假阴性)之间的折衷。一般来说,增加二元分类器的真阳性率将倾向于增加其假阳性率。二元分类器的接收器操作特征(ROC)曲线根据接受更高的假阳性率来测量增加真阳性率的成本。

一般来说,元标记的过程是这样的:

  1. 建立第一个基本模型,获得预测
  2. 用阈值过滤预测
  3. 将预测与 x_train 合并作为新的输入
  4. 将预测与 y_train 合并为一个新标签
  5. 建立第二个模型,并用新的输入和标签对其进行训练
  6. 用第二个模型预测
  7. 基本模型预测和元模型预测交集的最终预测结果。

元标签是我花了大量时间试图找出应用这种方法的最佳方式的主题。但是仍然有太多的未知,例如:

  1. 元标签指标是否依赖于?

当我们评估一种方法时,这实际上取决于我们选择哪些指标,以及您对模型架构、超参数等的优化程度..

2.能否适用于不同的车型?****

由于这种方法将使用两种不同的模型,模型差异是我们需要考虑的另一个问题。

3.元标签只适用于某些数据吗?

关于这个话题的参考文献大多来自时序数据,那么非序列数据呢?

诸如此类,但是这些问题都是关于元标签的局限性,这也是我在本文中想要探讨的。但是由于这篇文章的长度限制,我可能无法涵盖所有的内容。

元标记与集成方法的区别,尤其是堆叠,在于元标记将来自主要模型的预测添加到特征和标记中,而堆叠仅将其用作新特征。我可以理解那些额外的特征(预测)是由用来做预测的模型来表示的。但是为什么要在标签中使用呢?尽管这可能就是元标签这个名字的由来。最重要的是,在标签中加入预测是否有信息泄露?嗯,我想肯定会有从初级模型到次级模型的泄漏,这是为了得到更好的分数。

由于可以在网上找到许多关于集成学习的讨论,特别是堆叠,元标记很少得到足够的研究。因此,本文将集中讨论元标记及其与堆叠的比较。

图书馆

下面是本文中使用的库。

**'''Main'''
import numpy as np
import pandas as pd'''Data Viz'''
import matplotlib.pyplot as plt
import seaborn as sns#plt.style.use('seaborn')
plt.rcParams['figure.figsize'] = [16, 9]
plt.rcParams['figure.dpi'] = 300
plt.rcParams['font.size'] = 20
plt.rcParams['axes.labelsize'] = 16
plt.rcParams['axes.titlesize'] = 18
plt.rcParams['xtick.labelsize'] = 12
plt.rcParams['ytick.labelsize'] = 12
plt.rcParams['font.family'] = 'serif'
%matplotlib inline'''Data Prep'''
from sklearn import preprocessing as pp
from scipy.stats import pearsonr
from sklearn.model_selection import train_test_split
from sklearn.model_selection import StratifiedKFold'''Metrics'''
from sklearn.metrics import log_loss, accuracy_score, f1_score
from sklearn.metrics import precision_recall_curve, average_precision_score
from sklearn.metrics import roc_curve, auc, roc_auc_score
from sklearn.metrics import confusion_matrix, classification_report'''Algos'''
from sklearn.linear_model import LogisticRegression
import lightgbm as lgbimport tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.callbacks import ReduceLROnPlateau,EarlyStopping**

数据

为了研究元标记和堆叠,我们可以通过sklearn.datasets.make_classification().生成一个虚拟的二进制分类数据集,但是使用真实的数据集更有趣。我们这里使用的数据集是 ULB 机器学习小组的 信用卡欺诈检测 。我们先快速看一下数据。

**#pd.read_csv can read the url and unzip the zipped file at
#same time, but will take a few seconds, just be patient.url = "[https://clouda-datasets.s3.amazonaws.com/creditcard.csv.zip](https://clouda-datasets.s3.amazonaws.com/creditcard.csv.zip)"
data_original = pd.read_csv(url) 
data_original.head()**

✍Tip!

pd.read_csv() 可以同时读取网址和解压压缩文件。我们不再需要任何其他函数或库来完成这项工作。

数据集包含 28 个匿名要素、1 个“数量”要素、1 个“时间”要素和 1 个目标变量类。该数据集显示了两天内发生的交易,其中 284,807 笔交易中有 492 笔欺诈。这些特征被匿名化以保护客户的隐私,这是 PCA 变换的结果,因为数据集在公共域中。唯一没有被 PCA 转换的特征是“时间”和“数量”。特征“时间”包含数据集中每个事务和第一个事务之间经过的秒数。特征“金额”是交易金额,该特征可用于依赖于示例的成本感知学习。特征“类”是响应变量,“0”作为目标变量对应于非欺诈情况,而目标变量中的“1”对应欺诈情况。

**data_original.info()**

变量之间也有最小的相关性——这可能是 PCA 变换变量的结果。

**#see the cluster and corralation of features and classes
def plot_corr(data = data_original):

    ax1 = data.corrwith(data.Class).plot.bar(figsize = (20, 10),
         title = "Correlation with class",
         fontsize = 18, color='r',
         rot = 45, grid = True)
    ax1.title.set_size(28)

    sns.set(style="white")
    cmap = sns.diverging_palette(220, 20, as_cmap=True)

    corr =data.corr()
    sns.clustermap(corr,cmap=cmap,
                  linewidths=1,linecolor='w')

plot_corr();**

****

我之所以选择这个数据集,是因为从这个数据集无论是精度还是召回率都很难达到高分。该数据集非常不平衡,因为在 284,807 笔交易中有 492 笔(0.17%)欺诈。该数据集中 99.83%的交易不是欺诈性的,而只有 0.17%是欺诈性的。

**val_counts = data_original[['Class']].value_counts()
ax = sns.barplot(x=val_counts.index,
                 y=val_counts/len(data_original))
ax.set(title=f'Frequency Percentage by {val_counts}',
       xlabel='Class',
       ylabel='Frequency Percentage');**

面对如此少量的欺诈性数据,我们必须小心我们的数据处理和模型选择。算法可以很容易地通过预测所有的测试数据是欺诈性的来欺骗我们。随着 99.9%的数据集是负面的(非欺诈),网络将巧妙地预测所有是负面的,导致超过 99%的准确性。结果看起来很好,但没有用。

这就是为什么除了准确性之外,我们还需要更好的指标。

衡量标准

结果质量没有单一的最佳衡量标准,问题域和数据决定了合适的方法。

大多数机器学习使用准确度作为默认度量,如果我们使用准确度作为度量,正如我们所知,准确度是真阴性和真阳性的总和除以总数据集大小。考虑到真实的负值压倒真实的正值,准确性可能非常高,但不会表明您的模型对欺诈性数据进行分类的能力。也就是说,由于概念简单、易于实现和用途广泛,有一些度量方法被普遍采用。因为我们不知道哪一个最适合这个数据集,所以我将在本文中列出它们。

  • 准确(性)
  • 平均精度
  • 地下区域
  • 精确
  • 召回
  • f1-分数
  • 困惑 _ 矩阵
  • 精确回忆曲线
  • 曲线下面积

下面将对每个指标做一些介绍。当然,在网上可以找到大量关于度量的资料。如果你已经知道他们中的大部分,我们仍然可以在跳到下一部分之前刷新我们的记忆。

1.召回率、精确度和 AUC ( 曲线下面积 ) ROC

我把这三个指标放在一起,因为它们有很好的相关性。

根据 Wikipedia,precision 是正确结果的数量除以所有返回结果的数量,而 recall 是正确结果的数量除以应该返回的结果的数量。

而下面这张图比 1000 字更好的解释了这两个概念。

精确和召回来自维基百科

接收算子特征(ROC)是曲线下的面积,其中 x 是假阳性率(FPR ), y 是真阳性率(TPR ),通常用于呈现机器学习中二元决策问题的结果。AUC 是 ROC 曲线下的面积,代表召回(TPR)和特异性(FPR)之间的权衡。与其他指标一样,AUC 介于 0 和 1 之间,0.5 是随机预测的预期值。

AUC-ROC 曲线是在各种阈值设置下对分类问题的性能测量。ROC 是概率曲线,AUC 代表可分性的程度或度量。它告诉我们模型在多大程度上能够区分不同的类。

与精确召回曲线不同,ROC(接收者操作者特征)曲线最适用于平衡数据集。

来源

AUC 接近 1,这意味着它具有良好的可分性。差模型的 AUC 接近 0,这意味着它具有最差的可分性度量。事实上,这意味着它在往复结果。

一篇关于这个话题的文章可以在这里找到。此外,一个很好的 ROC 和 AUC 视频可以从 Josh Starmer 的 StatQuest 中找到。

2.平均精度

平均精度是一个用来概括精度-召回曲线(PR AUC)的单一数字,它使得比较不同的模型成为可能。PR AUC 是曲线下的面积,其中 x 是召回率,y 是精确度。平均精度(AP)的一般定义是找到上述精度-召回曲线下的面积。

精确度和召回率总是在 0 和 1 之间。因此,AP 也在 0 和 1 之间。

这里是一篇关于这个话题的好文章。

然而,当处理高度倾斜的数据集时,精确召回(PR)曲线给出了一个算法性能的 更丰富的 画面。 当 AUC 和 AP 都被重新调整到位于[0,1]时,AP 大约是 AUC 乘以系统的初始精度。

3。F1 分数

传统的 F 值或平衡 F 值( F1 值)是精度和召回率的 调和平均值 。我们计算 F1 分数作为精度的调和平均值,并回想一下如何实现这一点。虽然我们可以取两个分数的简单平均值,但调和平均值更能抵抗异常值。因此,F1 分数是一个平衡的度量,它恰当地量化了跨许多领域的模型的正确性。

F1 得分

F1 分数适用于 ROC 曲线的任何特定点。该点可以代表例如二元分类器中的特定阈值,因此对应于特定的精度和召回值。

请记住,F1 分数是一种既代表召回率又代表准确率的聪明方法。对于要高的 F1 分数,精确度和召回率都应该高。

因此,ROC 曲线针对各种不同水平的阈值,并且对于其曲线上的各个点具有许多 F1 分数值。

4。混乱矩阵

对于如此高度不平衡的数据集,混淆矩阵没有多大意义。我将它添加到度量集合中,仅供参考。它可以通过下表自我解释:

  • 真阳性(TP): 这些是我们预测是的病例(他们有疾病),他们确实有疾病。
  • 真阴性(TN): 我们预测没有,他们没有这种病。
  • 假阳性(FP): 我们预测是的,但他们实际上并没有患病。(也称为“第一类错误”)
  • 假阴性(FN): 我们预测没有,但他们确实有疾病。(也称为“第二类错误”)

我在一个函数中总结了所有的指标,以便稍后调用。

**def metrics_summary(true_label, prediction_prob, Threshold=0.5):

    #basically, slearn provides all the functions for metrics. average_precision = average_precision_score(true_label
    ,prediction_prob)
    fpr, tpr, thresholds = roc_curve(true_label, prediction_prob)
    areaUnderROC = auc(fpr, tpr)

    prediction_int = prediction_prob > Threshold

    accuracy = accuracy_score(true_label, prediction_int)

    print(f'accuracy: {accuracy}')
    print(f"average_precision: {average_precision}")
    print(f'areaUnderROC: {areaUnderROC } \n')
    print('*'*60)
    print(' '*20, 'classification_report')
    print('*'*60, "\n")
    print(classification_report(true_label, prediction_int))

    print('*'*60)
    print(' '*20, 'confusion_matrix \n')
    print('*'*60, "\n")
    display(confusion_matrix(true_label, prediction_int))
    print("\n")

    # precision_recall_curve and areaUnderROC 
    precision, recall, thresholds = precision_recall_curve( \
                                true_label, prediction_int)

    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16,9))

    ax1.step(recall, precision, color='k', alpha=0.7, where='post')
    ax1.fill_between(recall, precision, step='post', 
    alpha=0.3,color='k') ax1.set_xlabel('Recall', fontname="Arial", fontsize=24)
    ax1.set_ylabel('Precision', fontname="Arial", fontsize=24) 
    ax1.tick_params(labelsize=20)

    ax1.set_title('Precision-Recall curve: Average Precision \
    = {0:0.2f}'.format(average_precision), fontsize=24,
    fontname="Arial")        

    ax2.plot(fpr, tpr, color='r', lw=2, label='ROC curve')
    ax2.plot([0, 1], [0, 1], color='k', lw=2, linestyle='--')
    ax2.tick_params(labelsize=20)
    ax2.set_xlabel('False Positive Rate', fontname="Arial",
    fontsize=24)
    ax2.set_ylabel('True Positive Rate', fontname="Arial",
    fontsize=24)
    ax2.set_title('areaUnderROC = {0:0.2f}'\
            .format(areaUnderROC), fontsize=24, fontname="Arial",)    
    ax2.legend(loc="lower right", fontsize=24, fancybox=True) 
    # Adjust the subplot layout, because the logit one may take 
      more space
    # than usual, due to y-tick labels like "1 - 10^{-3}"
    # plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10,
    # right=0.95, hspace=0.25,wspace=0.35)**

这些评估指标非常重要。这有点像数据科学家和商业人士之间的接口。对于大多数只听说过 AI 但从未在任何模型上训练过的人来说,他们不会太关注像 log loss、交叉熵和其他成本函数这样的东西。这就是为什么我们需要指标来直观地向业务人员解释结果。尽可能简单地向非数据科学家传达复杂结果的能力是应用数据科学家需要掌握的基本技能之一。

模型

以下是我将要探讨的三种模式:

  1. 逻辑回归
  2. lightBGM
  3. DNN

我选择这三个模型的原因是它们高度不相关。独立解决方案需要相对不相关。如果它们非常相关,一旦将它们放入一个集合模型,其中一个的优势将反映其余的优势,劣势也是如此。我们看不到通过合奏实现多样化的好处。

在我们进入模型之前,仍然有一些事情需要做,即,基于特征的标准化、输入和标签分离以及分割训练和测试数据。

**#Normalize training and testing data
def scale_data(x_train, x_test=None):   
    features_to_scale = x_train.copy().columns
    scaler = pp.StandardScaler()
    print(scaler.fit(x_train[features_to_scale]))

    x_train.loc[:, features_to_scale] = \
    scaler.transform(x_train[features_to_scale])

    #normalize test dataset with the mean and std of train data set 
    x_test.loc[:, features_to_scale] = \
    scaler.transform(x_test[features_to_scale])

    return x_train, x_test#seperate input and labels    
def get_x_y(data=data_original):
    data_x = data.copy().drop(['Class', 'Time'], axis=1)
    data_y = data['Class'].copy()

    return data_x, data_y#split the train and test data
def data_split(data_x, data_y):
    x_train, x_test, y_train, y_test = \
          train_test_split(data_x,data_y,test_size=0.25,
          stratify=data_y,random_state=2020)      

     return  x_train, x_test, y_train, y_test#put all together
def data_process(data=data_original):
    data_x, data_y = get_x_y(data)

    x_train, x_test, y_train, y_test \
    = data_split(data_x, data_y)

    #do not touch the test data by any means!!!!
    x_train, x_test = scale_data(x_train, x_test)

    return  x_train, x_test, y_train, y_test**

✍Tip!

由于数据集高度不平衡,scikit-learn 的train_test_split()函数中的参数stratify =data_y来得非常方便。数据在一瞬间以分层的方式被分割。

你可能注意到我用 data_original,x_test_orignal,y_test_orignal 作为变量名。我想把这三个子数据集放在一边,因为这些原始数据会有很多调整,我们不想以任何方式弄乱测试数据。

**x_train, x_test_original, y_train, y_test_original \
= data_process(data_original)x_train.shape, x_test_original.shape, \
y_train.shape, y_test_original.shape**

训练数据集有 213605 条事务记录和 29 个特征,而测试数据集有 71202 条事务记录和 29 个特征。

**print(f'No. of fraud in test dataset:\
      {x_test_original[y_test_original==1].shape[0]}')**

在测试数据集中的 71202 条交易记录中,只有 123 条记录是欺诈性的。

✍Tip!

注意,测试数据是通过训练数据的均值和标准差来标准化的。你不应该在你的工作流程中使用任何根据测试数据计算的数量,即使是简单的数据标准化。 换句话说,永远不要碰你的测试数据!

数据准备好了,指标确定了,模型来了:

  1. 模型 1 (逻辑回归)
**def build_model_1(x_train, y_train):

    logitreg_parameters = {'C': np.power(10.0, np.arange(-9, 1)),
                           'solver' : ('lbfgs', 'liblinear') }

    model_1 = LogisticRegression(#solver='liblinear',
                                 class_weight='balanced', 
    #uses the values of y to automatically adjust weights

                                 warm_start=True,
    #reuse the solution of the previous call to fit
     as initialization
                                 max_iter = 300,
    #Maximum number of iterations taken for the solvers to converge.
                                 random_state=2020, 
    #so results can be reproduced
                                 ) logitreg_grid = GridSearchCV(model_1, param_grid = \
           logitreg_parameters,scoring = 'f1', n_jobs = 1, cv=5)          

    logitreg_grid.fit(x_train, y_train)

    return logitreg_gridmodel_1 = build_model_1(x_train, y_train)**

开始时,由于本文不是关于获得最佳分数,我使用了来自 sklearn 的逻辑回归的默认设置。精度分很低,0.07 左右。使用相同的默认设置,一些在线教程在使用逻辑回归的相同数据集上显示了非常高的精确度。然而,他们处理测试数据的方式是有问题的。为了得到更好的结果,使用了GridSearchCV来搜索最佳参数。

****

我得到的最好成绩是

**model_1.best_score_**

使用以下设置:

**model_1.best_estimator_**

让我们检查测试数据集的结果和指标得分:

**# 0 and 1 two clasese
y_pred_prob_test_1 = model_1.predict_proba(x_test_original)[:,1]
# number of fraud is 123 in test dataset
y_pred_int_test_1 = y_pred_prob_test_1 > Threshold
pd.Series(y_pred_int_test_1).value_counts()**

相当不错,记住欺诈交易的数量是 123。

**metrics_summary(y_test_original, y_pred_int_test_1)**

****

2。型号 2 (LightBGM)

对于 lightBGM,我进一步指定 1/4 的训练数据作为验证数据集。

**#prepare data 
x_train_, x_cv, y_train_, y_cv = \
train_test_split(x_train, y_train,
                test_size=0.25,
                stratify=y_train,
                random_state=2020)def build_model_2(x_train, y_train, x_cv, y_cv ):
    #most of the parsmeters are default
    params_lightGB = {
    'task': 'train',
    'application':'binary',
    'num_class':1,
    'boosting': 'gbdt',
    'objective': 'binary',
    'metric': 'binary_logloss',
    'metric_freq':50,
    'is_training_metric':False,
    'max_depth':4,
    'num_leaves': 31,
    'learning_rate': 0.01,
    'feature_fraction': 1.0,
    'bagging_fraction': 1.0,
    'bagging_freq': 0,
    'bagging_seed': 2018,
    'verbose': 0,
    'num_threads':16
    } lgb_train = lgb.Dataset(x_train, y_train)
    lgb_eval = lgb.Dataset(x_cv, y_cv, reference=lgb_train) model_2 = lgb.train(params_lightGB, lgb_train,
                    num_boost_round=2000,
                    valid_sets=lgb_eval,
                    early_stopping_rounds=200,
                    verbose_eval=False)
    return model_2x_train_.shape, y_train_.shape, x_cv.shape, y_cv.shape**

结果还不错,没有进行进一步的超参数调整。

**model_2 = build_model_2(x_train_, y_train_, x_cv, y_cv)y_pred_prob_test_2 = model_2.predict(x_test_original)
y_pred_int_test_2 = y_pred_prob_test_2 > Threshold
pd.DataFrame(y_pred_int_test_2).value_counts()**

**metrics_summary(y_test_original, y_pred_int_test_2)**

****

与模型 1 相同,准确率非常高(99.9%),精确度很好(93%),而召回率适中(77%)。

3。模型 3 (深度神经元网络)

对于深度神经元网络(DNN),我使用了两个回调,EarlyStopping()和 ReduceLROnPlateau()来获得更好的结果。同样,由于结果还不错,所以没有实现超参数调优。( Keras-tuner 确实不错,可以查一下我以前的文章更好的了解。)

**callbacks = [EarlyStopping(monitor='loss', patience=3), \
                 ReduceLROnPlateau(monitor='val_loss', factor=0.2, \
                                   patience=3, min_lr=0.001)]def build_model_3(x_train, y_train, x_cv, y_cv, input_dim=29): 
    model_3 = Sequential([
                Dense(input_dim = input_dim, units = 32, 
                      activation  = 'relu'),
                Dense(units = 16, activation =  'relu'),
                #Dropout(0.5),
                Dense(units = 8, activation =  'relu'),
                Dense(units =1, activation = 'sigmoid'),]) model_3.compile(optimizer = 'adam', 
                 loss = 'binary_crossentropy', 
                 metrics = ['accuracy'])

    model_3.fit(x_train, y_train, 
              validation_data = (x_cv, y_cv),
              batch_size = 64, 
              epochs = 50,
              callbacks=callbacks)

    return model_3**

这是一个简单的 3 层 DNN,具有较小的单元数(32,16,8)以避免过度拟合。

⚠️Warning

DNN 对输入特征非常敏感。如果将时间特征添加到训练数据中,结果会有些奇怪。但是一旦你去掉时间特性,它就恢复正常了。

现在我们可以在模型 3 上训练我们的数据。

**model_3 = build_model_3(x_train_, y_train_, \
x_cv, y_cv, input_dim=29)
y_pred_prob_test_3 = model_3.predict(x_test_original)y_pred_int_test_3 = y_pred_prob_test_3 > Threshold
y_pred_int_test_3.shape
pd.DataFrame(y_pred_int_test_3).value_counts()** 

**metrics_summary(y_test_original, y_pred_int_test_3)**

****

在没有任何超参数调整的情况下,结果类似于优化的模型 1 逻辑回归。一般来说,如果我们包括来自不同机器学习家族的类似强解(例如一个来自随机森林,一个来自神经网络),这些解的集合将导致比任何独立解更好的结果。这是因为每个独立解决方案都有不同的优点和缺点。通过将独立的解决方案整合在一起,一些模型的优势(T2)弥补了其他模型的劣势,反之亦然。到目前为止,来自 3 个非常不同的模型的结果似乎满足了我们对堆叠和元标记的要求。

让我们现在集合那些模型。

堆垛

因为叠加有点像向输入数据添加新特征,而新特征来自于主模型的预测。我们首先做一个特征工程来堆叠所有的数据。

**def data_stack( x, y, m_1=model_1, m_2=model_2, m_3=model_3):
    #All required parameters must be placed before any 
     default arguments.
    '''
    x: features
    y: labels
    m_1, m_2, m_3: 3 models

    '''
    # build a container to hold all the prediction from 3 models
    pred_all = pd.DataFrame(data=[], index=y.index) pred_1 = m_1.predict_proba(x)[:,1]
    pred_1_df = pd.DataFrame(pred_1, index=y.index) pred_2 = m_2.predict(x,num_iteration=m_2.best_iteration)

    pred_2_df = pd.DataFrame(pred_2, index=y.index) pred_3 = m_3.predict(x).reshape(x.shape[0]) #to 1D shape
    pred_3_df = pd.DataFrame(pred_3, index=y.index) # join all the predictions together
    pred_all = pred_all.join(pred_1_df.astype(float),
                             how='left',rsuffix="0")\
                       .join(pred_2_df.astype(float),
                             how='left',rsuffix="1")\
                       .join(pred_3_df.astype(float),
                             how='left',rsuffix="2")
    pred_all.columns = ['pred_1', 'pred_2','pred_3']
    # final training data will be the merge of training data 
      and all the predictions
    x_pred = x.merge(pred_all, \
                    left_index=True, right_index=True)

    return x_pred**

现在,将新特征(来自 3 个模型的预测)添加到训练数据集中。

**x_train_stack = data_stack(x_train, y_train)
x_train_stack.shape**

然后,相同的过程应用于测试数据集。

**x_test_stack = data_stack(x_test_original, y_test_original)
x_test_stack.shape**

由于我们在之前的数据集中添加了新的要素,因此查看这些新要素之间的相关性会很有意思。

****

我们确实看到初级模型的预测高度相关,这并不奇怪。来自第一模型的信息泄漏到第二模型中,因为它们共享相同的训练数据。只要测试数据是完整的,我们将更喜欢更多的信息流入第二个模型,以获得更好的结果。****

现在我们需要经历所有那些乏味但必要的数据过程。

**#normalize training and testing data
x_train_stack, x_test_stack = scale_data(x_train_stack,  x_test_stack)#split the traning data to train and validation
x_train_stack_, x_cv_stack, y_train_, y_cv_ = \
train_test_split(x_train_stack, y_train,
                test_size=0.25,
                stratify=y_train,
                random_state=2020)
#stratify mean samplling with the ratio of each class percentage in #all data.x_train_stack_.shape, x_cv_stack.shape, y_train_.shape,  y_cv.shape**

不过,说到堆叠,有一些重要的注意事项。如果独立的解决方案同样强大,集合将比任何独立的解决方案具有更好的性能。但是,如果其中一个解决方案比其他解决方案好得多,集合的性能将等于最佳独立解决方案的性能;不合格的解决方案对整体性能没有任何贡献。

  1. 型号 2 (lightBGM)作为二级型号

由于模型 2 (lightBGM)的精度迄今为止最高,我们将使用模型 2 作为第二模型。

**model_2_stack = build_model_2(x_train_stack_, y_train_, x_cv_stack, y_cv_)
y_pred_prob_test_2_stack = model_2_stack.predict(x_test_stack)
y_pred_int_test_2_stack = y_pred_prob_test_2_stack > Threshold
pd.DataFrame(y_pred_int_test_2_stack).value_counts()**

这里,在没有堆叠的情况下,在相同模型上的 102 个病例的比较中确定了 120 个阳性结果。

**metrics_summary(y_test_original, y_pred_int_test_2_stack)**

****

召回率从 0.77 提高到 0.85,f1 分数和平均准确率也有适度的提高。

2。第三款 DNN 作为第二款

如果我们把 DNN 作为第二个模型会发生什么?

**model_3_stack = build_model_3(x_train_stack_, y_train_, \
                        x_cv_stack, y_cv_, input_dim=32)y_pred_prob_test_3_stack = model_3_stack.predict(x_test_stack)
y_pred_int_test_3_stack = y_pred_prob_test_3_stack > Threshold
y_pred_int_test_3_stack.shape
pd.DataFrame(y_pred_int_test_3_stack).value_counts()**

同样的模型,88 比 116,结果不太乐观,这表明精确度更高,召回率更低。

**metrics_summary(y_test_original, y_pred_int_test_3_stack)**

****

不出所料,精度更高(0.95),但召回率很低(0.68)。

3。模型 1 作为二级模型的逻辑回归

没想到会有更好的结果,纯粹好奇。

**model_1_stack = build_model_1(x_train_stack, y_train)model_1_stack.best_score_**

结果看起来很有希望。

**y_pred_prob_test_1_stack = model_1_stack.predict_proba(x_test_stack)[:,1]# 0 and 1 two clases
y_pred_int_test_1_stack = y_pred_prob_test_1_stack > Threshold
pd.Series(y_pred_int_test_1_stack).value_counts()**

**metrics_summary(y_test_original, y_pred_int_test_1_stack)**

****

几乎所有的指标都有或多或少的改进,实际上,与 lightBGM 或 DNN 作为第二个模型相比,结果并不太差。

现在,让我们去元标签。

元标记

因为元标记将需要向输入和标记添加新的特征。我写了另一个函数来处理这个问题。

**def data_meta(id, x, y, model):
    #get prediction from model 1
    pred_prob_meta = model.predict_proba(x)[:,1]
    pred_prob_meta = pd.Series(pred_prob_meta, \
                               index=x.index,
                               name=f'pred_{id}_meta')
    pred_int_meta = pred_prob_meta > Threshold
    y_meta = pd.Series(y & pred_int_meta, name=f'y_train_meta_{id}')
    x_meta = x.join(pred_int_meta)

    return x_meta, y_meta pred_prob_meta = model.predict_proba(x)[:,1]
    pred_prob_meta = pd.Series(pred_prob_meta, \
                               index=x.index,
                               name=f'pred_{id}_meta')
    pred_int_meta = pred_prob_meta > Threshold
    y_meta = pd.Series(y & pred_int_meta, name=f'y_train_meta_{id}')
    x_meta = x.join(pred_int_meta)

    return x_meta, y_meta**
  1. 第一个型号:logreg,第二个型号:lightBGM

准备好数据后,对于第一个实验,我将使用逻辑回归作为主要模型,lightBGM 作为次要模型。

**x_train_meta_1, y_train_meta_1 = \
data_meta(1, x_train, y_train, model_1)
x_train_meta_1.shape, y_train_meta_1.shape**

再次,让我们检查元数据的相关性。

**plot_corr_xy(x_train_meta_1, y_train_meta_1);**

****

标签和添加的功能之间的相关性非常强(从模型 1 预测)。高皮尔逊相关系数表明更多的信息从第一模型泄漏到第二模型中。

现在,再一次,我们需要经历所有那些乏味但必要的数据处理。

**# test data
x_test_meta_1, y_test_meta_1 = \
data_meta(1, x_test_original, y_test_original, model_1)
x_test_meta_1.shape, y_test_meta_1.shape**

然后标准化测试和训练数据集。

**x_train_meta_1, x_test_meta_1 = scale_data( \
                                x_train_meta_1, x_test_meta_1)**

并拆分训练数据集以再次获得验证数据。

**x_train_meta_1_, x_cv_meta_1, y_train_meta_1_, y_cv_meta_1 = \
train_test_split(x_train_meta_1, y_train_meta_1,
                test_size=0.25,
                stratify=y_train_meta_1,
                random_state=2020)
#stratify mean samplling with the ratio of each class percentage in #all data.x_train_meta_1_.shape, x_cv_meta_1.shape, y_train_meta_1_.shape,  y_cv_meta_1.shape**

做完这些,我们终于可以去看模特了。

**model_2_meta_1 = build_model_2( \
    x_train_meta_1_, y_train_meta_1_, x_cv_meta_1, y_cv_meta_1)y_pred_prob_test_2_meta_1 = model_2_meta_1.predict(x_test_meta_1)
y_pred_int_test_2_meta_1 = y_pred_prob_test_2_meta_1 > Threshold
pd.DataFrame(y_pred_int_test_2_meta_1).value_counts()**

在我们有了元模型的预测之后,我们将结果与主模型的预测结合起来。

**final_pred_2_meta_1 = y_pred_int_test_2_meta_1 &  y_pred_int_test_1
pd.DataFrame(final_pred_2_meta_1).value_counts()**

看起来没什么区别。让我们看看所有的指标。

**metrics_summary(y_test_original, final_pred_2_meta_1)**

****

现在的结果在精确度和召回率之间更加平衡了。精确度、召回率和 f1 分数以及其他指标分别从 0.93、0.77、0.84 提高到 0.96、0.81、0.88。

2。第一款车型:logreg,第二款车型:DNN

由于第一个模型仍然是逻辑回归,所以不需要更新数据。我们直接去看模型吧。

**#if you receive an error message, try to run the data process again.
model_3_meta_1 = build_model_3( \
    x_train_meta_1_, y_train_meta_1_, \
    x_cv_meta_1, y_cv_meta_1, input_dim=30)y_pred_prob_test_3_meta_1 = model_3_meta_1.predict(x_test_meta_1)
y_pred_int_test_3_meta_1 = y_pred_prob_test_3_meta_1 > Thresholdpd.DataFrame(y_pred_int_test_3_meta_1).value_counts()**

同样,最终结果将是主要预测和次要模型预测的交集。

**# combine the  meta prediction with primary prediction
final_pred_3_meta_1 = y_pred_int_test_3_meta_1.flatten() & y_pred_int_test_1final_pred_3_meta_1.shape**

嗯,我真的开始怀疑最后一步的必要性了。

****

好吧,精确度确实提高了,但代价是召回率降低了。就像 DNN 作为第二个模型的堆叠方法一样,但是稍微好一点。

以 DNN 为第二模型的元标签

将 DNN 作为第二个模型进行堆叠

3。第一款:logreg + lightBGM,第二款:DNN

堆叠方法的工作方式让我想知道,如果我将模型 1 和模型 2 都作为主要模型,而将模型 3 作为最终模型,会发生什么?这会改善最终结果吗?让我们这样试一试。

因为这一次我们将有额外的功能需要添加到输入中,所以我重新编写了数据处理函数。

**def data_meta_2(id, x, y, m_1, m_2):
    '''
    id: the id of new columns
    x: input features
    y: labels
    m_1: model 1, here logreg
    m_2: model 2
    '''
    pred_prob_meta_1 = m_1.predict_proba(x)[:,1]
    pred_prob_meta_1 = pd.Series(pred_prob_meta_1, \
                                 index=x.index,
                                 name=f'pred_{id}_meta')
    pred_int_meta_1 = pred_prob_meta_1 > Threshold

    pred_prob_meta_2 = m_2.predict(x)
    #as DNN give 2D prediction that needs to be flatten to 1D for
    #combination
    pred_prob_meta_2 = pd.Series(pred_prob_meta_2.flatten(), \
                                 index=x.index,
                                 name=f'pred_{id+1}_meta')
    pred_int_meta_2 = pred_prob_meta_2 > Threshold

    y_meta = pd.Series(y & pred_int_meta_1 & pred_int_meta_2, \
                       name=f'y_train_meta_{id}')
    x_meta = x.join(pred_int_meta_1).join(pred_int_meta_2)

    return x_meta, y_meta**

然后,我们将该函数应用于训练数据和测试数据。

**#meta_1_2: meta data from 1 model and 2 model
x_train_meta_1_2, y_train_meta_1_2 = \
data_meta_2(1, x_train, y_train, model_1, model_2)x_test_meta_1_2, y_test_meta_1_2 = \
data_meta_2(1, x_test_original, y_test_original, model_1, model_2)**

并再次进行归一化。

**x_train_meta_1_2, x_test_meta_1_2 = \
scale_data(x_train_meta_1_2, x_test_meta_1_2)**

并分割训练数据以给出验证数据集。

**x_train_meta_1_2_, x_cv_meta_1_2, y_train_meta_1_2_, y_cv_meta_1_2 = \
train_test_split(x_train_meta_1_2, y_train_meta_1_2,
                test_size=0.25,
                stratify=y_train_meta_1_2,
                random_state=2020)
#stratify mean samplling with the ratio of each class percentage in #all data.x_train_meta_1_2_.shape, x_cv_meta_1_2.shape, \
y_train_meta_1_2_.shape,  y_cv_meta_1_2.shape**

好,让我们在模型 3 上训练我们的数据。

**model_3_meta_1_2 = build_model_3( \
    x_train_meta_1_2_, y_train_meta_1_2_, \
    x_cv_meta_1_2, y_cv_meta_1_2, input_dim=31)y_pred_prob_test_3_meta_1_2 = model_3_meta_1_2.predict(x_test_meta_1_2)
y_pred_int_test_3_meta_1_2 = y_pred_prob_test_3_meta_1_2 > Thresholdpd.DataFrame(y_pred_int_test_3_meta_1_2).value_counts()**

**# combine the  meta prediction with primary prediction
final_pred_3_meta_1_2 = \
y_pred_int_test_3_meta_1_2.flatten() & \
y_pred_int_test_1 & y_pred_int_test_2
pd.Series(final_pred_3_meta_1_2).value_counts()**

很有可能,最后一步不会改变这个高度不平衡的数据集。让我们看看最后的分数。

**metrics_summary(y_test_original, y_pred_int_test_3_meta_1_2)**

****

将 DNN 作为第二个模型或独立的 DNN 与叠加法相比,所有指标都更好。但不如第二代的 lightBGM。

4。第一款:logreg + DNN,第二款:lightBGM

由于 lightBGM 作为第二个模型似乎比其他模型更好,这是我最不想尝试的组合。我们需要再次重新处理数据集。

**#meta_1_3: meta data from 1 model and 2 model 
#process the train dataset
x_train_meta_1_3, y_train_meta_1_3 = \
data_meta_2(1, x_train, y_train, model_1, model_3)#meta_1_3: meta data from 1st model and 3rd model 
#process the test dataset
x_test_meta_1_3, y_test_meta_1_3 = \
data_meta_2(1, x_test_original, y_test_original, model_1, model_3)#normalize the dataset
x_train_meta_1_3, x_test_meta_1_3 = \
scale_data(x_train_meta_1_3, x_test_meta_1_3)#do a train, validation split
x_train_meta_1_3_, x_cv_meta_1_3, y_train_meta_1_3_, y_cv_meta_1_3 = \
train_test_split(x_train_meta_1_3, y_train_meta_1_3,
                test_size=0.25,
                stratify=y_train_meta_1_3,
                random_state=2020)**

现在,我们可以开始训练我们的模型。

**model_2_meta_1_3 = build_model_2( \
    x_train_meta_1_3_, y_train_meta_1_3_, \
    x_cv_meta_1_3, y_cv_meta_1_3)**

并预测测试数据。

**y_pred_prob_test_2_meta_1_3 = model_2_meta_1_3.predict(x_test_meta_1_3)
y_pred_int_test_2_meta_1_3 = y_pred_prob_test_2_meta_1_3 > Threshold
# combine the  meta prediction with primary prediction
final_pred_2_meta_1_3 = \
y_pred_int_test_2_meta_1_3 & \
y_pred_int_test_1 & y_pred_int_test_3.flatten()
pd.Series(final_pred_2_meta_1_3).value_counts(**

**metrics_summary(y_test_original, final_pred_2_meta_1_3)**

****

结果比上一个好。

使用 LightBGM 作为第二个模型 logreg + DNN 第一个模型的元标签

将 DNN 作为第二模型 logreg + BGM 第一模型的元标签

特征重要性

正如我们现在所知,堆叠和元标记有点像向训练数据添加额外特征的特征工程方法。但是这些增加的新功能与原来的功能相比有多重要。感谢 scikit-learn 中的feature_importance()函数,我们现在可以实现这个函数来了解这些特性的重要性。

**def plot_feature_importance(model, X , importance_type = 'split'):
    feature_imp = pd.DataFrame({'Value':model.
                               feature_importance(importance_type),
                               'Feature':X.columns})
    f, ax = plt.subplots(figsize=(40, 30))
    ax.set_title(f'LightGBM Features Importance by \
                 {importance_type}', fontsize=75, fontname="Arial")     
    ax.set_xlabel('Features', fontname="Arial", fontsize=70)
    ax.set_ylabel('Importance', fontname="Arial", fontsize=70)  
    ax.tick_params(labelsize=50)

    sns.barplot(x="Value", y="Feature",
                data=feature_imp.sort_values(by="Value", 
                ascending=False), ax=ax)**

根据定义,有两种重要类型,“分割”和“获得”。如果为“分割”,结果将包含该特征在模型中使用的次数。如果为“增益”,则结果包含使用该功能的拆分的总增益。让我们看看他们两个。

**plot_feature_importance(model_2_meta_1_3, x_train_meta_1_3_)**

**plot_feature_importance(model_2_meta_1_3, x_train_meta_1_3_, 'gain')**

两种重要性类型都表明元数据远比原始特征重要。我们可以看到,同样的结果也适用于我们的最佳模型。

**plot_feature_importance(model_2_meta_1, x_train_meta_1_)**

**plot_feature_importance(model_2_meta_1, x_train_meta_1_, 'gain')**

高分的假象

根据特征重要性值,我们知道,从特征在模型中使用的次数(“分割”)和使用该特征的分割的总增益(“增益”)的角度来看,主模型的预测对第二个模型的结果影响最大。我们还知道,从相关图来看,主要模型的预测与标签(“类别”)具有非常高的相关性(~0.9)。

此外,我们知道将会有信息从主模型泄漏到第二模型,尽管这是优选的。

因此,如果从测试数据到训练数据有轻微的泄漏,泄漏的信息将通过上述方式被放大。像 DNN 这样的模特真的很擅长走捷径,挑选信息,给高分。

让我用代码展示给你看。

**#normalize all the data in one go.
scaler = pp.StandardScaler()
data_x.loc[:, features_to_scale] = scaler.fit_transform(data_x[features_to_scale])#split training and testing dataset afterwards.
x_train_cv, x_test, y_train_cv, y_test = train_test_split(data_x, data_y, test_size=0.25,stratify=data_y,random_state=2020)**

如果在将数据拆分为训练数据集和测试数据集之前一次性对所有数据进行归一化,则使用的平均值和标准差来自训练数据和测试数据。来自测试数据集的一些信息将与训练数据集共享,然后通过元标记放大。

使用逻辑回归和 DNN 作为主要模型,使用 lightBGM 作为第二模型,以下是测试数据的得分。

****

请注意,这些分数是由没有优化和默认设置的基本模型获得的。在数字上看起来不错,但对未知数据没用。

摘要

总之,最好的结果是使用元标记,lightBGM 作为第二模型,logistic 回归作为主要模型。

将 BGM 作为第二模型、logreg 作为第一模型的元标签

稍加努力,我们可以取得更好的成绩。额外的提高可能看起来并不引人注目,但在一些比赛中,当第一名和第二名的分数如此接近时,这就是输赢的交易。

我想用我最喜欢的关于指标的两条定律来结束这篇文章:

"当一个度量成为目标时,它就不再是一个好的度量."

——古德哈特定律

“社会决策中使用的量化社会指标越多,就越容易受到腐败的压力”

——坎贝尔定律

参考

  1. 洛佩兹·德·普拉多的《金融机器学习的进展》简介

2.衡量业绩:AUC (AUROC)

3.盗版者的准确度、精确度、召回率和其他分数指南

4.平均精度

5.如何用 Python 计算特征重要性

元学习:学会学习

原文:https://towardsdatascience.com/meta-learning-learning-to-learn-a0365a6a44f0?source=collection_archive---------20-----------------------

元学习算法将来可能会改变

机器学习的广泛创新

米卡·鲍梅斯特在 Unsplash 上的照片

为了成功地理解和研究新概念或新观点,人们通常在日常生活中使用一个例子。

与机器相比,它们学习新技能的速度更快,效率更高;行动、想象和解释。

例如,看过几次蝴蝶和蚂蚁的孩子能很快认出它们。同样,掌握如何驾驶自行车的青少年很可能会通过有限的演示发现如何骑摩托车。然而,机器学习算法需要数百个模型来标记和训练,以提供类似的准确性。

介绍

在计算机科学中,元学习是机器学习的一员,可以定义为学会学习。它是一种自动算法,应用于元数据,以识别学习如何在解释困难时变得灵活,从而增强现有算法的性能或学习算法本身( Thrun & Pratt,1998Andrychowicz 等人,2016 年

本研究从元学习过程的角度研究进化算法和神经网络的使用。首先解释进化算法的过程,以避免过度拟合,其次是神经网络的概念。最后,总结了进化算法和神经网络由于元学习技术的关系。

元学习算法通常使人工智能(AI)系统有效地学习,以更鲁棒的方式适应条件的变化,并推广到更多的任务。它们可以用来优化模型的架构、参数以及它们的组合。这项研究专注于一种称为神经进化的特定元学习技术,也称为学习神经架构的进化算法

进化学说

进化生物学家查尔斯·达尔文几十年前参观了加拉帕戈斯群岛,并注意到一些鸟类似乎是从单一基因群体进化而来的。如图 1 所示,它们有着共同的标准特征,即它们独特的喙形,这源于它们独特的 DNA ( Steinheimer,2004 )。

Steinheimer (2004)断言 DNA 是控制细胞复制的蓝图。假设是每个物种都退出到一个流行的自然选择理论中。这个过程是算法性的,可以通过创建进化算法来模拟。

图一。达尔文雀喙的多样性。图片来自维基百科

此外,进化算法随机变异一些成员,试图找到更多合格的申请人。这个过程根据需要重复无数次迭代。实际上,在这种情况下,他们可以表示为几代人。这些步骤都受到达尔文自然选择理论的刺激。它们都是被称为进化计算的算法的一部分。

进化策略

目前,神经网络可以执行对人类来说可能具有挑战性的任务,如果它们提供大量训练数据的话。这些网络的最佳架构并不简单,需要进行大量的反复试验。事实上,研究人员一直在努力改进架构,这些年来,这些架构被逐步交付到更新的级别。

研究人员发现,一家著名的科技公司优步正在使用神经进化方法,他们开始采用进化策略通过与雅达利游戏相结合来帮助提高他们服务的性能。

“甚至一个非常基本的几十年前的进化策略也提供了可比较的结果;因此,更现代的进化策略应该被认为是现代深度强化学习(RL)算法的潜在竞争方法”(这样等人,2017⁴;Chrabaszcz,Loshchilov &胡特,2018⁵ 。

图二。标准策略和探索之间的性能结果比较。图片由 优步艾研究室 2017

在图 2 中,优步人工智能实验室用几款雅达利游戏进行了测试。这个线形图描述了标准进化策略之间的比较以及对算法的进一步探索。似乎超参数中的各种调整给出了显著的奖励值。奖励金额的数量显著增加,从 0 到 30 以上。

在前 200 代数字中,两种策略中的奖励值都快速上升到 5,并稳定地保持在 300 代数字以上。然后,它从 320 代数量急剧增长到最大 800 代数量。

数据扩充

在当代工作中,深度学习模式的出现主要与收集的数据的数量和多样性有关。实际上,除了发现最新的数据存在之外,数据增强识别出用于训练模型的可用数据的显著增强的唯一性。数据扩充有几个例程,分别是裁剪、填充、水平翻转(图 3)。

这些技术经常被用于训练深度神经网络( Shorten & Khoshgoftaar,2019⁶ )。事实上,大多数神经网络的训练时间策略都使用基本类型的数据扩充。

图 3。使用裁剪、填充和水平翻转的数据扩充示例。图片由 Keras

“使用 CIFAR-10 数据集,我们的模型获得的最佳分类精度不在前 10 种方法之列。这使得所提出的架构成为嵌入式系统的理想选择,而不是性能最佳的方法”(恰利克&德米尔西,2018⁷ )

尽管如此,加拿大高级研究所(CIFAR-10)卷积神经网络(CNN) 成功应用了图像分类问题。此外, Cubuk、Zoph、Mane、Vasudevan 和 Le (2019)⁸ 解释了数据集上的最新精度,如具有自动增强功能的 CIFAR-10 是一种创新的自动数据增强方法。

李,周,陈,李()研究表明,元学习的研究通常集中在数据和模型设计上,元学习优化器、随机梯度下降(SGD) 等例外情况似乎仍然属于模型优化的范畴。在图像数据的环境中,数据扩充是最容易识别的。这些图像放大通常涉及水平翻转和小幅度的旋转或平移。

讨论

在两个相互交织的过程中,即生命间学习和生命内学习,存在着一种综合的相互作用。把生命间的学习看作是通过自然选择的进化过程。相比之下,生命内学习与动物在其整个存在过程中如何学习有关,例如识别物体、学习交流和行走

此外,进化算法可以反映为生命间的学习,而神经网络可以被认为是生命内的学习。进化算法和神经网络很可能是在深度强化学习技术中实现优化算法的主要因素。

进化算法

Bingham,Macke 和 Miikkulainen (2020) ⁰ 强调进化算法有四个主要特征,即网络层数、每层神经元数、激活函数和优化算法。

这些开始于用随机权重初始化多个神经网络,以生成群体。接下来是使用图像数据集训练每个网络的权重,然后测试它在分类测试数据方面的表现有多强。此外,另一个特征是在测试集上应用分类精度并实现适应度函数来决定得分最高的网络作为下一代的成员。

另一方面,进化算法过滤掉表现最差的网络并将其淘汰。最后,它们的特点是选择一些得分较低的网络,这在优化网络时在局部最大值中可能是有价值的。这些技术是防止过度适应的一种进化方式。

神经网络

神经网络试图模拟生物神经系统的信息处理能力,如图 4 所示。人体由数万亿个细胞体组成,被称为细胞核的神经系统细胞被训练通过电化学手段传递消息或信息。

图 4。生物神经人脑系统。图片由艾商

简单来说,神经网络是连接的输入和输出单元的集合,其中每个连接都有一个关联的权重(图 5)。神经网络通过混合来自其母网络的随机参数集合来生成新网络。一个实例可以有相同数量的层作为一个原点,而它的其余参数来自不同的父对象。这个过程反映了生物学在现实生活中的工作方式,并帮助算法收敛到一个优化的网络上。

随着网络参数复杂性的增加,进化算法产生指数级加速。 Krizhevsky、Sutskever 和 Hinton (2017) 提到这个过程需要大量的数据和计算能力,并使用数百个 GPU 和 TPU 数天。它被初始化为 1000 个相同的没有隐藏层的卷积神经网络。然后通过进化过程,准确率较高的网络被选为父代,复制和变异产生子代,其余的被淘汰。

图 5。神经网络图。图片由 MC 提供。艾

在后来的实践中,神经网络利用了一组固定的重复模块,称为细胞。细胞的数量保持不变,但每个细胞的结构随着时间的推移发生了变化。他们还决定使用一种特定的正则化形式来提高网络的准确性。

他们没有淘汰得分最低的网络,而是排除了最老的网络,不管它们得分多高,最终提高了准确性,并从头开始训练。这种技术选择神经网络,当它们与进化算法一起被重新训练时,保持准确。

结论

元学习是学会学习的过程。此外,人工智能(AI)优化了一个或多个其他 AI。

这项研究的结论是,进化算法使用来自进化手段的概念,并模仿查尔斯·达尔文假说,例如,突变和自然选择,来解释复杂的难题。

相反,一种称为神经进化的元学习技术可能利用进化算法来单独优化神经网络。尽管元学习目前非常流行,但在现实生活问题中利用这些算法仍然极具挑战性。

然而,随着不断进步的计算能力、专用的机器学习硬件和元学习算法的进步,这些可能会变得更加可靠和值得信赖

**References**#1 [Learning to Learn](https://www.springer.com/gp/book/9780792380474)#2 [Learning to learn by gradient descent by gradient descent](http://papers.nips.cc/paper/6460-learning-to-learn-by-gradient-descent-by-gradient-descent)#3 [Charles Darwin’s bird collection and ornithological knowledge during the voyage of H.M.S. “Beagle”, 1831–1836](https://link.springer.com/article/10.1007/s10336-004-0043-8)#4 [Deep Neuroevolution: Genetic Algorithms Are a Competitive Alternative for Training Deep Neural Networks for Reinforcement Learning](https://arxiv.org/abs/1712.06567)#5 [Back to Basics: Benchmarking Canonical Evolution Strategies for Playing Atari](https://arxiv.org/abs/1802.08842)#6 [A survey on Image Data Augmentation for Deep Learning](https://link.springer.com/article/10.1186/s40537-019-0197-0)#7 [Cifar-10 Image Classification with Convolutional Neural Networks for Embedded Systems](https://ieeexplore.ieee.org/document/8612873)#8 [AutoAugment: Learning Augmentation Strategies From Data](http://openaccess.thecvf.com/content_CVPR_2019/html/Cubuk_AutoAugment_Learning_Augmentation_Strategies_From_Data_CVPR_2019_paper.html)#9 [Meta-SGD: Learning to Learn Quickly for Few-Shot Learning](https://arxiv.org/abs/1707.09835)#10 [Evolutionary Optimization of Deep Learning Activation Functions](https://arxiv.org/abs/2002.07224)#11 [ImageNet classification with deep convolutional neural networks](https://dl.acm.org/doi/10.1145/3065386)

元流:构建和管理现实生活中的数据科学项目

原文:https://towardsdatascience.com/metaflow-build-and-manage-real-life-data-science-projects-1bd5f9a07acd?source=collection_archive---------18-----------------------

不需要数据操作;独立构建、改进、运营和部署端到端数据工作流。

Learning Rate 是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。订阅这里!

如今,数据科学家可以利用他们掌握的工具做任何事情。主要云提供商提供对象存储架构和流行的 SQL 数据库管理系统作为服务,基础架构管理只需一个配置文件,调度程序可以随时随地执行任何作业。

然而,这些都不容易设置,不容易利用其优势并在其上构建。在数据科学的世界里,你很少遇到对 DevOps 工具感到舒适的人,甚至很少遇到愿意自学的人。

数据科学项目的层次

这是元流试图缓解的问题之一。它提供了一个以人为中心的框架,帮助科学家和工程师构建和管理现实生活中的数据科学项目。该框架最初在网飞开发,并在 AWS re:Invent 2019 上开源。

AWS re:Invent 2019 上的 Metaflow 演示

在这个故事中,我们将介绍元流的基本概念,并提供展示其潜力的简单代码示例。

基本原则

元流遵循数据流编程范式,其中程序被设计为一个有向图,数据从一个操作移动到下一个操作。这种设计很自然地出现在数据科学项目中,其中管道的概念是一种合理且常见的抽象。Metaflow 还自动负责版本控制,并提供了一种简单的、声明性的方式来管理依赖性和计算资源。

在接下来的部分中,我们将考虑一个简单的实验,我们创建一个随机数据集作为一个数字数组,并对其执行若干操作。我们将讨论如何使用简单的线性流程,以及如何并行化工作,以利用可用资源并提高性能。

线性流动

线性流动是最直接的过渡类型。数据以连续的方式从一个操作流向下一个操作。

线性流动

首先,每个流必须有一个开始和一个结束节点。因此,元流运行将寻找一个开始节点来启动执行,并寻找一个结束节点来标记终止。每个节点都被认为是一个步骤,并在代码中如此标注。

在下面的例子中,我们在开始节点初始化一个随机数据集,在中间节点计算它的平均值,在结束节点打印结果。

在这个简单的线性示例中,您将看到如何定义步骤,使用self.next()方法和之前计算的参考变量从一个步骤前进到下一个步骤。

要运行这个作业,您可以在终端中执行python metaflow_1.py run,预计计算时间不到一秒。当然,这是为了展示 Metaflow 的一些基本功能,并不是什么有价值的东西。让我们来看一个更复杂的例子。

创建分支

为了创建一个更复杂的示例,让我们定义一个数字数组并执行三个操作:

  • 找出数组中的质数
  • 找出数组中的奇数
  • 找出数组中的偶数

我们希望并行执行这些操作;因此,我们需要在图中创建分支。最终的数字应该如下图所示。

元流分支

元流可以在分布式环境中的多个 CPU 内核或多个实例上执行并行操作。最后,每一步都必须结合起来,以产生一个统一的结果,我们可以把这个流程传递下去。现在,让我们用 python 来实现它。首先,我们定义一些方便的函数,以便能够找到素数、奇数和偶数。

接下来,我们可以在图表中调用这些函数。

通过在self.next()方法中传递三个参数,我们让 Metaflow 知道我们想要并行调用这些操作,创建一个分支。最后,我们必须加入每个分支操作的结果。因此,我们需要从分支内部的每一步指向self.join方法。

join方法接受一个额外的参数inputs。这个变量是一个object,它存储来自每个分支操作的结果。使用这个对象,您可以以一种简单的、面向对象的方式检索每个操作的变量。

也就是说,我们有两个问题。首先,查找质数的函数并没有得到最佳实现。但这是故意的,这样我们就可以有一个执行时间更长的方法。

第二个问题是搜索奇数和偶数的两个函数会立即返回结果。因此,并行化这些操作不会给我们带来任何好处。相反,我们的代码的性能比简单的顺序方法更差,因为我们必须考虑元流图带来的开销。事实上,一个简单的 python 脚本需要大约 2 分钟来返回结果,而在我的设置中,Metaflow 脚本要多花 20 秒。那么,我们能做得更好吗?当然啦!我们可以任意嵌套树枝!

为每一个

如果我们能进一步并行化素数搜索会怎么样?我们可以。在 Metaflow 中我们可以任意嵌套分支,也就是说,你可以在一个分支内部分支。考虑到这一点,让我们再次设计我们的图表。

嵌套分支

缺少的是能够并行化负责动态查找素数的操作,并行化到本地可用的任意数量的 CPU 核心,或者分布式环境中的任意数量的机器。这就是foreach关键字的用武之地。下面我们可以看到实现这个图的 python 代码。

这个脚本中有两个新概念。首先,Parameter对象允许我们将选项传递给元流脚本。我们现在可以通过执行python <file_name>.py run --cores 4来运行这个脚本。这个选项将使用 NumPy 的便利函数array_split()把我们的数据集分成四个块。

foreach关键字为 iterable 中的每个元素创建一个并行执行。在这种情况下,为分割数据集中的每个数组创建一个并行操作。如果我们使用默认的数字cores,我们将数据集分成四个更小的集合,并并行执行prime方法四次。我们刚刚把执行时间缩短到 35 秒!

结论

Metaflow 是一个以人为中心的数据科学框架,最初由网飞开发。它旨在通过抽象基础设施细节并为开发人员提供一种直观的方式来构建他们的程序,从而促进构建和部署现实生活中的数据科学项目的过程。在这个故事中,我们展示了当地的故事,它的能力。准备好在 AWS 上投入并扩展您的数据科学项目了吗?从官方网站上的教程部分开始。

我叫 Dimitris Poulopoulos,是希腊比雷埃夫斯大学BigDataStack的机器学习研究员和博士(c)。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲中央银行、经合组织和宜家等主要客户设计和实施人工智能和软件解决方案。如果你有兴趣阅读更多关于机器学习、深度学习和数据科学的帖子,请在 twitter 上关注我的* LinkedIn@ james2pl**。***

宏基因组学——谁在那里,他们在做什么?

原文:https://towardsdatascience.com/metagenomics-who-is-there-and-what-are-they-doing-9f204342eed9?source=collection_archive---------13-----------------------

深入了解微生物群落的数据

你知道你的身体里藏着大约 100 万亿个细菌吗?据估计,一个人的肠道(胃)里大约有一两磅细菌1。你家后院也是一样。土壤中可能生活着许多种类的细菌,它们有助于丰富土壤(例如:硝化细菌产生植物所必需的硝酸盐)。这些微观群落有非常多样的生态系统,研究它们的组成和行为可以为我们提供有价值的见解。在这篇文章中,我将提供一个关于宏基因组学的基本介绍,宏基因组学是对从微生物群落中获得的遗传物质的研究。

图片来自阿雷克索查来自皮克斯拜

什么是宏基因组学?

宏基因组学是将现代基因组技术直接应用于研究自然环境中的微生物群落,而不需要对单个物种进行分离和实验室培养[2]。

不同的微生物群落可以在土壤、海洋、泥浆、森林、太空甚至人体中找到。可以在这些环境中发现的微生物可以包括细菌、病毒/噬菌体、微生物真核生物(例如:酵母)和蠕虫(例如:蠕虫和线虫)。

为什么是宏基因组学?

现在你一定想知道我们怎么能研究这些我们甚至看不见的微小生物。研究它们的传统方法是获取样本,将它们放在培养皿中,观察是否有任何东西生长,分离培养物,然后进行测序。然而,大多数细菌物种不能用这种传统方式培养。所以在宏基因组学中,我们所做的是直接从微生物群落中获取样本,并对它们进行测序。

宏基因组学有助于发现在医学、农业、能源、食品和营养等许多领域具有新功能的新型天然产物、抗生素和酶。

宏基因组学中的两个主要问题

每个宏基因组学研究都会遇到两个主要问题[4];

  1. 谁在那里?
  2. 他们在做什么

当我们考虑问题“谁在那里”时,我们想要识别样本中存在的微生物种类。问题“他们在做什么”意味着我们必须确定他们的功能和行为。

猎枪与靶向宏基因组学

一旦你从环境中获得了样品,你就必须准备好样品库以便于分析。创建用于分析的库的两种当前方法是

  1. 靶向宏基因组学:靶向多个生物体和样本共有的基因组的特定区域(例如:16S rRNA 和 18S rRNA)。它提供了更精确、更深入的数据,但可能会导致某些目标区域的不均衡扩增。
  2. 鸟枪法宏基因组学:能够测序你样本中的一切。它对所有生物来说都是完美的。它为基因内容(尤其是 DNA )提供了更高的分辨率,但会产生非常复杂的数据集。

鸟枪法宏基因组分析

如图 1 所示,处理宏基因组数据集[4]有三种主要方法。

  1. 标记基因分析:将序列与称为标记基因的分类学或系统发育学信息序列数据库进行比较,比较其相似性,并对序列进行分类学注释。最常用的标记基因是核糖体 RNA (核糖核酸)基因,它们只有一个拷贝,在微生物基因组中很常见。
  2. 宁滨:将序列聚类到与分类组相对应的相似组中,例如种、属或更高级别。
  3. 组装:将你的样本中所有的小序列放在一起,形成代表基因组的更长的序列。查看我的前一篇文章,获得关于排序和组装的基本概念。一篇更详细的文章将在未来发表。

图一。用于鸟枪法宏基因组学分析的方法

靶向宏基因组学

为了进行靶向宏基因组学,从样品中提取遗传物质,并基于感兴趣的区域对感兴趣的基因进行 PCR 扩增[5]。为此目的最常用的基因是 16S 核糖体 RNA 基因。这个基因被称为“通用系统发育标记”。它存在于所有活的微生物中,包含一个单一的拷贝。

图二。16S rRNA 分析的基本流程

让我们考虑人类皮肤的 16S rRNA 基因分析(图 2)的基本工作流程[6]。首先,采集样本,提取 DNA。接下来,对细菌 16S rRNA 基因进行 PCR 扩增,并对扩增的样品进行测序。最后,使用各种工具处理和分析得到的数据。我们可以确定微生物群落的操作分类单位(OTUs)、群落结构和功能角色。

两个著名的 16S rRNA 分析流水线包括qimeMothur

最后的想法

目前,我正在做与宏基因组学相关的研究。我读过的文章和我目前所做的事情启发了我写这篇文章。宏基因组学是一个相当新的领域,目前被认为是一个热门话题。我发现宏基因组学非常迷人,充满了研究问题和新发现。对于那些对追求生物信息学和计算基因组学领域的更高研究感兴趣的人,我希望你发现我的文章是一个有用的起点。

如果你错过了我的“从生物信息学开始”系列,你可以阅读下面列出的链接中的文章,以了解生物信息学的基础知识。

[## 生物信息学入门

生物信息学这个词在当今的科学界正在发生巨大的转变。这个词似乎是由两个…

towardsdatascience.com](/a-dummies-intro-to-bioinformatics-e8212ed7c09b) [## 从生物信息学开始——DNA 核苷酸和链

在我介绍生物信息学的第一篇文章中,我提到我们将会学到很多关于 DNA,RNA…

towardsdatascience.com](/starting-off-in-bioinformatics-dna-nucleotides-and-strands-8c32515271a8) [## 从生物信息学开始——RNA 转录和翻译

在我之前的文章中,我已经介绍了 DNA 以及如何将 DNA 变成蛋白质。不要忘记检查它们,因为…

towardsdatascience.com](/starting-off-in-bioinformatics-rna-transcription-and-translation-aaa7a91db031) [## DNA 序列数据分析——从生物信息学开始

在我之前的文章中,我已经介绍了 DNA、核苷酸及其排列的基础知识。你可能想知道…

towardsdatascience.com](/dna-sequence-data-analysis-starting-off-in-bioinformatics-3dba4cea04f)

感谢您的阅读。我想听听你对这个新兴领域的看法。

干杯!

参考

[1]关于生活在你肠道中的微生物的 6 个令人惊讶的事实(https://www . health line . com/health-news/strange-six-things-you-not-know-you-Gut-Microbes-090713 # 1)

[2]凯文·陈和利奥·帕切特。 PLOS 计算生物学微生物群落全基因组鸟枪法测序的生物信息学。第 1 卷 2005 年

[3] D.R .加尔萨和 B.E .杜蒂赫。从培养到未培养的基因组序列:宏基因组学和微生物生态系统建模细胞和分子生命科学 (2015) 72: 4287

[4]托马斯·夏普顿。鸟枪法宏基因组数据分析导论。植物科学前沿【2014 年 6 月 16 日

[5]宏基因组学——概述|科学直接主题(https://www . science direct . com/Topics/biochemistry-genetics-and-molecular-biology/宏基因组学)

[6]乔、肯尼迪和孔庆东。研究技术变得简单:皮肤研究中的细菌 16S 核糖体 RNA 基因测序。皮肤病学调查杂志第 136 卷,第 3 期,2016 年 3 月,第 e23-e27 页

基于机器学习的系统的变形测试

原文:https://towardsdatascience.com/metamorphic-testing-of-machine-learning-based-systems-e1fe13baf048?source=collection_archive---------23-----------------------

理解大数据

测试自动驾驶汽车和其他基于 ML 的系统的技术

与传统软件相比,测试基于机器学习(ML)的系统需要不同的方法。对于传统软件,规范及其与实现的关系通常非常明确:“当用户键入有效的用户名和匹配的密码时,他们就成功登录了”。非常容易理解,具有确定性,并且易于编写测试用例。

基于 ML 的系统完全不同。基于 ML 的系统不是基于显式编程语句的明确定义的输入和逻辑流,而是基于潜在的巨大输入空间,这些空间具有来自大部分黑盒组件(模型)的概率结果。在本文中,我看一下变形测试,这是一种越来越流行的技术,用来解决一些基于 ML 的系统测试挑战。我将介绍一些最新的研究,并展示不同应用领域的例子。

这两幅图像可用于表示 ML 系统的一些变形测试。请继续阅读,了解如何做到这一点..:)图片作者。

变质测试

变形测试(MMT)最初是在很久以前提出的,至少可以追溯到 (Chen1998 )。在软件测试研究领域工作了很长一段时间后,我一直将 MMT 视为一种好奇心,很少有真正的用例。然而,在基于 ML 的系统中,它似乎很好地找到了自己的位置。

MMT 的一般思想是根据输入之间的一般关系、这些输入及其输出的一般变换来描述系统功能,而不是作为特定输入到特定输出的映射。

过去用于变形测试的一个典型例子来自测试搜索引擎(例如,周 2016 )。由于搜索引擎现在实际上是基于自然语言处理(NLP)/ML 的系统,它们也很适合本文的主题。为了说明这个概念,我在谷歌上运行了两个查询(2020 年 10 月):

一个谷歌查询“汽车”及其细化版本“自动驾驶汽车”。图片作者。

第一个查询只是一个词“汽车”。第二个查询向第一个查询添加了另一个单词“autonomous”。所以现在查询变成了“自动驾驶汽车”。限制性搜索关键字的添加是输入转换(或“变形”,在精神或元变形测试中)的一个例子:

示例输入转换:将原始输入(查询)更改为更受限制。图片作者。

为了对测试结果进行检查(测试预言),我们定义了一个匹配关系,当应用输入转换时,它应该保持:

示例输出(变形)关系:限制越多的查询返回的结果越少。图片作者。

在这种情况下,将限制性搜索词(“autonomous”)添加到前面的查询(“car”)会改变结果集,将其限制在一个较小的集合中。从 83 亿个结果到 1.59 亿个。变形测试不会指定这些确切的值,而是指定关系“限制查询导致更少的搜索结果”。并且可以生成几个(种子)输入(搜索查询)、用于转换的相关限制性关键字,并运行查询和检查变形关系(限制查询产生较少的结果)。关于 MMT 与搜索引擎的更多详情,见( Zhou2016 )。

以上是变形测试所指的一个例子。您以某种方式转换 ( 变形)您的输入,同时定义一个关系,该关系应该从先前的输入(及其输出)保持到新变形的输入(及其输出)。关键概念/术语是:

  • 变形/变换:以你定义的变形关系应该保持的方式修改种子输入
  • 变胞关系:输入的定义变换应该对输出有已知的/可测量的影响。检查转换后这种关系是否成立是变形测试的测试预言。( 测试预言 是对测试结果做出裁决的机制的总称)
  • 种子输入:用作测试初始输入的输入,需要转换。如果您知道种子输入的输出,您可以使用它来定义一个更严格的关系(输出应该是正确的)。但是,即使没有种子输出,您仍然可以定义一个关系检查,但是可能会稍微宽松一些(输出应该是相似的,但是您不知道它是否正确)。

更一般地,变形测试是指定义这样的转换,并观察它们对结果的影响(变形关系)。有效性和适用性则取决于这些定义的完善和广泛程度。我将在接下来的章节中给出更多具体的例子。

问题空间

为什么要使用变形测试?我将用自动驾驶汽车的例子来说明这一点。自动驾驶汽车最近经历了大量的开发,获得了大量的资金,具有安全关键要求,并且高度依赖于机器学习。这可能也是为什么他们在 MMT 研究中受到如此多的关注。树立了很好的榜样。

例如,特斯拉自动驾驶仪收集数据(或者在我写这篇文章的时候收集了数据..)从几个前置、后置和侧面摄像头,一个雷达和 12 个超声波传感器。在每个时刻,它必须能够处理所有这些数据,以及以前的测量结果,并提出符合最高安全标准的推理。这种真实世界的输入空间非常大。想想我在之前的办公室附近拍摄的两张相隔几天的照片:

同一个地方,相隔几天。图片作者。

就在这两张图片中,可以看到许多变化。雪/无雪、阴影/无阴影、道路标记/无标记、连接道路可见、停车场可见、其他汽车等等。然而,在所有这些条件下,人们期望能够安全地航行。为了更好地说明这个问题,我很快想到了该领域的一些变体示例:

自主车辆中的 ML 算法需要考虑的几个项目示例。图片作者。

除此之外,人们可以很容易地将其扩展到不同的位置、道路形状、对象类型、桥梁、火车,...其他传感器有其他考虑,每个位置都不一样,等等。

在基于 ML 的系统应用的不同领域中,人们需要能够识别相似的问题场景,以及它们的相关组合,以便能够测试它们。手工构建测试集来覆盖所有这些(对我来说)是不现实的努力。

自动驾驶汽车的变形测试

变形测试可以帮助更好地覆盖领域,如上述自动驾驶汽车问题空间。由于人们对此很感兴趣,因此也提出了许多方法,我将在这里描述其中的一些。

覆盖图像变化

( Tian2018 )中的 DeepTest 工作使用从驾驶汽车中捕获的真实图像的变换来产生新的图像。在这种情况下,变形属性是:

  • 种子输入:来自车载摄像头的真实图像。
  • 变形变换:移动、倾斜、模糊、缩放、缩放、加雾、加雨等。论原始意象
  • 变形关系:自动驾驶决策应在变换后的相同输入图像上显示最小的差异。

下面用一些简单的例子说明了这一点,这些例子使用的是我以前办公室外的道路图像。在下面,我通过简单地在这个位置旋转相机一点来“转换”图像。然后我添加了箭头来说明系统应该如何“预测”应该选择的路径。此处的箭头是手动添加的,仅用于说明:

换个角度看,现实世界的路径应该还是一样的(或者接近)。图片作者。

和同样的,但与雪域地面(两个转换在下面相比,上面;添加雪+旋转):

有雪和没有雪,路径应该是相同的(或接近的)。图片作者。

当然,没有人会期望手工创建大量这样的图像(或转换)。相反,可以使用自动化转换工具。例如,有几个用于图像增强的库,最初是为了帮助增加机器学习中的训练数据集大小而创建的。下图显示了在上面的原始非雪图像上运行的几个这样的增强:

自动生成的早期道路图像的放大/变换。图片作者。

所有这些增强/变换的图像都是使用 Python imgaug 图像增强库从之前显示的同一原始源图像生成的。有些也许可以用更先进的增强方法来改进,但大多数已经相当有用了。

一旦生成了这些变换,就可以检查生成的图像上的变形关系。例如,系统应该提出非常相似的驾驶路径,在加速、转向等所有变换上具有最小的差异。或者更复杂的检查,如果可以定义的话,例如定义已知的参考路径(如果存在的话)。

同样,这个转换和检查变形关系的过程就是 MMT 的目的。它通过自动化复杂系统的一些测试过程来帮助实现更高的覆盖率和可信度,否则很难扩展到大的输入空间。

基于氮化镓的 MMT 变换

生成输入转换的更高级的方法是应用不同的基于 ML 的技术来构建转换本身。在图像增强中,一种这样的方法是(GANs)。GANs 在自动驾驶汽车上的应用见( Zhang2018 )。在他们的工作中,GANs 被训练在不同的天气条件下转换图像。例如,拍摄道路的晴天图像,并将其转换为雨天或雾天的图像。

理由是 GAN 生成的天气效果和操作比更传统的合成变换更真实。( Zhang2018 )使用NVidia UNIT(Liu 2017)工具包训练和应用 GAN 模型,使用 YouTube 视频等输入进行训练。

说明 GAN 结果的图像可在单位网站上获得,以及在他们的谷歌相册中的更高分辨率。我推荐去看一看,挺有意思的。单位网站上的小图看起来很有说服力,但仔细观察相册中的大图会发现一些局限性。但是,成绩还是相当可观的,而且这还是几年前的事了。我希望随着时间的推移,这些技术会进一步改进。总的来说,使用机器学习来产生转换似乎是 MMT 中一个非常有前途的领域。

激光雷达变换

除了摄像头,系统还可以使用许多可能的传感器。在自动驾驶汽车中,一个这样的系统是激光雷达,使用基于激光的传感器测量到物体的距离。在(周 2019 )中介绍了在百度 Apollo 自动驾驶汽车系统中对激光雷达数据应用变形测试的研究。

该系统首先识别感兴趣区域(ROI),即“可驾驶”区域。然后,它识别并跟踪该区域中的对象。该系统由多个组件组成:

  • 对象分割和边界识别:发现并识别 ROI 中的障碍物
  • 物体跟踪:跟踪障碍物(运动)
  • 顺序类型融合:随着时间的推移平滑障碍类型(通过使用时间相关数据,随着时间的推移进行更一致的分类)

( Zhou2019 )研究侧重于对象识别组件的变形测试,特别是在激光雷达点云的微小变化中分类与误分类的鲁棒性。在这种情况下,激光雷达点云只是激光雷达系统报告看到的测量点的集合。这些云可以非常详细,测量的点的数量非常大( Zhou2019 )。

下图说明了这种情况(参见( Zhou2019 )对于来自实际汽车的逼真激光雷达图像,我在这里只是使用我自己的图纸来说明大致的想法。我用较深的颜色标记了感兴趣区域,并以圆形的方式添加了一些点来说明激光雷达扫描。绿色方框表示较大的障碍物(如汽车),较小的红色方框表示较小的障碍物(如行人):

我的激光雷达图像的涂鸦:)。图片由作者提供,使用来自 Pixabay 的openclipbart的汽车图片。

这种情况下的变形关系和转换是:

  • 变形关系**:在向激光雷达点云添加少量噪声之前和之后,应识别相同的障碍物(物体)。
  • ****变换:添加噪声(指向激光雷达点云)
  • ****种子输入:来自汽车的实际激光雷达测量

下图说明了这种类型的变形变换,添加的点用红色标记。我只是将它们添加到一个随机位置,在这种情况下,在 ROI 之外,因为这也是( Zhou2019 )中的示例:

我用红色添加了点的转换激光雷达图像的涂鸦。图片由作者提供,使用了来自 Pixabay 的openclippart的汽车图片。

上面是一个非常简单的转换和变形关系来检查,但我发现通常简单的工作最好。

总之,这里的 MMT 方法采用现有的激光雷达数据,并以添加的激光雷达数据点的形式向其添加一些噪声。与现实世界相比,这种噪声在( Zhou2019 )中被描述为潜在的昆虫、灰尘或传感器噪声。添加的噪波数量也被描述为占总点数的非常小的百分比,以使其更加真实。

( Zhou2019 )中的变形实验表明,在点云中的 ROI 区域之外添加少量点足以导致分类器(变形关系检查)失败。

因此,( Zhou2019 )报告与百度 Apollo 团队讨论了他们的发现,获得了对这些问题的承认,以及百度团队如何将一些测试数据纳入他们的训练数据集。这可能是一种有用的方法,因为变形测试可以被视为生成可用于训练的新数据的一种方式。然而,我认为在任何一种情况下都不应该简单地放弃测试,即使重新使用一些数据进行进一步的 ML 模型训练。稍后将详细介绍。

机器翻译的变形测试

不是每个人都从事自动驾驶汽车,因此其他领域的例子对于更广泛的洞察力很重要。在自动驾驶汽车之外,用基于 ML 的 NLP 技术测试自动语言翻译近年来受到了一些关注(例如, He2020 , Sun2020 )。我发现(He2020)的论文特别清晰明了,所以我在这里使用他们的方法作为翻译测试变形属性的示例:

  • ****种子输入:要翻译的句子
  • ****转换:将输入句子中具有特定词性(POS)标签的单词替换为具有相同词性标签的另一个单词。例如,一个动词与另一个动词。最后,使用另一个 NLP 模型(本例中为 Google 的 BERT )来“预测”一个合适的替换候选单词。
  • ****变胞关系:转换输出的结构应该与原始输入的原始翻译输出句子结构相匹配。大的偏差表明潜在的错误。测试 oracle 度量是原始输入与转换输入的自动翻译的输出句子结构的差异。

这里有一个使用谷歌翻译的说明性例子,以及我(当时)从这篇文章中挑选的一个句子。将这句话从英语翻译成芬兰语:

将一句英语翻译成芬兰语。图片作者。

屏蔽一个单词(名词)进行变形转换。图片作者。

使用 BERT 预测一个单词来替换被屏蔽的单词(一个“适合”屏蔽的单词)。检查变胞关系是否成立。这里很好。你只需要相信我,我是芬兰人:)。图片作者。

上面显示了变形转换以及如何检查已定义的变形关系。在这种情况下,句子结构保持良好(在我看来,作为一个母语为芬兰语的人),结果是好的。我手动执行了这些实验来说明这个概念,但是无论自动化与否,测试过程都是一样的。总的来说,尝试一些不同的句子,谷歌翻译实际上工作得很好。对他们来说很好。

老实说,我在上面的例子中并没有真正使用 BERT,因为这只是我需要用来说明这个概念的一个例子。我只是选了一个(对我来说)有意义的词。然而,如果需要的话, HuggingFace 拥有 BERT 和许多其他类似模型的非常好且易于使用的实现。我自己也用它们完成过许多其他任务。与汽车示例中的图像增强库非常相似,NLP 库已经走过了漫长的道路,如今许多基本的应用程序都非常简单和容易。

关于机器翻译的 MMT 的更多细节,我推荐查阅论文,尤其是( He2020 )是非常可读的。这里特别有趣的一点是,使用另一种基于 ML 的方法来帮助构建转换,类似于基于 GAN 的自动驾驶汽车方法。

医学图像的变形测试

作为第三个应用领域的示例,在 (Ding2017 )中介绍了如何将变形测试应用于医疗领域中基于 ML 的系统。这使用 MMT 来测试现有高分辨率生物细胞图像的变体。

在 (Ding2017 )中,定义了许多与生物细胞(线粒体等)的各个方面相关的变形关系。)以及对图像进行的操作。我缺乏医学领域的专业知识来更详细地分析转换或变形关系,并且这篇论文没有非常清楚地为我描述这些。但我相信我的不了解在这里其实是很有用的一点。

这种情况下的变形测试相关元素(据我所知):

****种子输入:现有的医学图像(实际上,该论文在这一点上以及许多其他方面都非常不清楚,但它作为一个领域示例)

****变换:添加、删除、变换等。线粒体的数量。

****变形关系:变换后图像的算法输出中的元素(线粒体)之间的关系应与定义的关系相匹配(例如,在添加新的元素后连接一些元素)。

对我来说,这个例子强调了在许多情况下,细微差别、变形关系和转换需要深入的领域理解。这需要不同团体之间的广泛合作,这在应用基于 ML 的方法时很常见(以我的经验)。汽车、驾驶和语言翻译是我们都很熟悉的日常工作。许多专家领域,比如本例中的,就不那么好了。这就是为什么我认为这是一个有用的例子来突出我缺乏领域专业知识。

有趣的是, (Ding2017 )还提到使用传统的测试技术,如组合测试、随机化和类别划分,来增强初始输入种子集。下面关于无人机的例子也是这种情况。

无人驾驶飞机的变质试验

作为最后一个示例领域,在( Lindvall2017 )中介绍了一种结合基于模型的测试、仿真和变形测试的方法,用于测试自主无人机的基于 ML 的飞行制导系统。

无人机被定义为具有一组传感器,包括气压计、GPS、相机、激光雷达和超声波。许多传感器,非常类似于自动驾驶汽车的例子。为无人机控制定义的变形关系:

  • 在相似的运行中,行为应该是相似的
  • 世界坐标的旋转应该没有影响
  • 坐标转换:不同坐标下的相同场景应该没有影响
  • 障碍位置:不同位置的相同障碍应该有相同的路线
  • 障碍形成:类似于位置,但多个障碍在一起
  • 障碍物接近度:总是在规定的范围内
  • 无人机速度:速度应该保持在规定的范围内
  • 无人机高度:高度应该保持在规定的范围内

以下是这种系统变形测试环境的属性:

  • ****种子输入:基于模拟的环境模型,使用基于模型的方法生成
  • ****转换:见上图;无人机相对于环境和障碍物或障碍物群的旋转和坐标变化等
  • ****检查:参见上文

测试环境生成器用于定义无人机的(模拟)测试环境,有效地生成变形测试的种子。变形转换可以被视为对该环境的修改,并且最终检查测试上述定义的变形关系是否成立。定义了各种场景来将这些结合在一起,包括起飞、返回家园、着陆等。

也许这里最有趣的部分是使用基于模型的测试方法来构建种子输入本身,包括测试环境。这似乎是一个非常有用的方法,可以在可能的领域获得进一步的覆盖。

另一个相关的观察是使用场景将元素组合在一起形成一个更大的测试场景,也跨越时间。这很重要,因为无人机或汽车或许多其他系统不能孤立地考虑单个输入,而是必须考虑一系列事件,并将其用作上下文。在变形测试中也需要考虑这个时间方面。

不同时间的对立输入和关系

对抗性输入

机器学习中经常单独讨论的一种特定类型的转换是对抗输入,这在( Goodfellow2018 )中有广泛描述。一般来说,对抗性输入旨在欺骗机器学习算法做出错误的分类。来自( Goodfellow2018 )的一个例子是欺骗一辆自动驾驶汽车(surprise)将停车标志分类错误,并可能导致事故或其他问题。

产生这种对立的输入可以被看作变形转换的一个例子,具有相关的关系,即输出不应该由于对立的输入而改变,或者改变应该最小。

通常,这种对抗性测试需要特别定制的数据来触发这种错误分类。在真实的驾驶场景中,汽车传感器没有被篡改,可能更难产生这种纯粹的敌对效果。然而,也有一些研究和方法,如( Zhou2020 )将此考虑到现实世界的案例中。稍后会有更多的介绍。

除了自动驾驶汽车,数字化改变或定制的敌对输入可能是一个更大的问题。例如,在网络安全日志分析或自然语言处理等领域,提供定制的输入数据可能更容易。我还没有在现实世界中看到这方面的实际例子,但我希望一旦技术成熟,变得更容易获得,更多的实际观察将浮出水面。

许多关于对抗性元素的工作,如( Goodfellow2018 )都有对抗性修改的单个输入(图像)的例子。真实的系统往往没有这么简单。例如,当汽车行驶时,图像(以及其他传感器数据)和需要基于该数据做出的决策会不断变化。这就是( Zhou2020 )这篇论文讨论的自动驾驶汽车。

跨时间的关系

在许多情况下,除了单一输入之外,随时间推移的输入序列与基于 ML 的系统更相关。开车经过一个标志(或数字广告牌..),随着时间的推移,系统必须处理与环境相关的所有不同位置处的所有传感器数据。在这种情况下,相机视角。对于其他传感器(激光雷达等),输入和输出数据会随着时间以类似的方式变化。

下面是两个帧间隔很短时间的例子。在真实的视频流中,每秒会有大量的变化和图像(以及其他输入):

(相同)输入概念随时间的变化。图片作者。

不仅角度会改变,而且在这种类型的测试(和实现)中,时间作为一个上下文应该被更普遍地考虑。我们要经过标志了吗?朝着它?通过它?我们已经停下来了吗?场景里还有什么?诸如此类。

(周 2020 )从对抗性输入生成的角度对这一话题进行了研究。在现实世界中,您不太可能直接操纵图像数据,但可能会受到修改后的交通标志、数字广告牌或类似设施上的敌对输入的影响。这是他们( Zhou2020 )关注的重点。

下面的例子说明了任何这样的修改也需要如何随着图像随时间而改变(与计算单个特定改变的输入相对于随时间移动的真实世界物理数据相比):

如果使用生成的对立元素进行测试,它们应该随着时间的推移相对于图像的其余部分发生变化。这里是蓝盒子的角度和大小。图片作者。

这种时间方面的重要性不仅仅体现在对抗性输入上。例如,我之前讨论的所有图像增强(天气效果等)都将受益于在真实驾驶场景(图像序列)中的应用,而不仅仅是一张图像。这毕竟是汽车在现实世界中必须面对的问题。

(周 2020 )中的测试预言也从两个不同的角度考虑了对抗性输入的效果:强度概率。也就是说,在对抗性变化的情况下,你可以在汽车的转向中引起多大的偏差,以及在对抗性输入的情况下,你可以引起这些偏差的可能性有多大。

除了汽车和视频流,时间序列在其他领域也很常见。讨论的无人机场景就是一个例子。其他示例包括处理链接的文本段落、股票市场中较长周期的信号,或者温度和风速等基本传感器信号。

最小化测试集

虽然自动化变形测试可能非常简单(一旦你确定了你的领域关系并构建了工作转换…),但是潜在的输入空间,转换的数量以及它们的组合可能会迅速增长。因此,MMT 中的测试选择很重要,就像其他类型的测试一样。

( Tian2018 )中介绍了一种解决这一问题的方法,该方法采用了贪婪搜索策略。从图像和转换的种子集开始,将转换及其组合应用于输入(图像),并测量所实现的神经元激活覆盖。如果它们增加了覆盖率,只要它们提供了增加覆盖率的一些阈值,那么“好的”组合将与其他输入和转换一起被添加回种子集,以用于后续的回合。如此反复,直到定义了结束阈值(或实验次数)。非常类似于更传统的测试方法。

( Tian2018 )中的覆盖率是根据 ML 模型中不同神经元的激活来测量的。他们为不同的神经网络架构建立覆盖标准,例如卷积神经网络、递归神经网络和密集神经网络。还提出了可以使用的各种其他覆盖标准,例如在( Gerasimou2020 )中关于评估不同神经元在分类中的重要性的标准。

当越来越多易于应用的工具可用于这种类型的 ML 模型覆盖度量时,这将是一种非常有用的方法。然而,我没有看到人们普遍编写他们自己的神经网络覆盖测量工具。

与传统软件测试的关系

除了测试套件优化,更广泛地考虑 MMT 与整个软件和系统测试的关系也很重要。MMT 擅长于测试和验证基于 ML 的系统的许多方面,这些系统在本质上更具有概率性和黑箱性。至少获得对它们更高的信心/保证。

然而,即使在基于 ML 的系统中,ML-part 通常也不是单独工作的孤立组件。相反,它消耗输入,产生输出,并使用 ML 模型处理复杂的数据集。我前面提到的组合的、等价划分的和基于模型的方法是一些例子,说明了基于 MMT 的方法如何与整体的、更传统的系统测试一起应用。

正如我提到的百度阿波罗案例及其激光雷达测试数据生成,其中一个反馈是使用变形测试数据进行进一步的 ML 训练。总的来说,这似乎是一个有用的想法,获得更多的训练数据总是好的。根据我构建基于 ML 的系统和训练相关 ML 模型的经验,每个人总是想要更多的训练数据。

然而,我认为不应该简单地将所有 MMT 测试数据转储到训练数据集中。经过训练的模型将从给定的数据中学习,并且可以在分割测试集上测试一般准确性。这是孤立测试特定 ML 模型的典型方法。然而,在实践中,分类不会是 100%准确的,并且一些项目最终会被错误分类,或者具有低置信度分数。这些进一步馈入整个系统,结合其他输入或过程,可能会产生意想不到的反应。使用特定的输入运行特定的(基于或不基于 MMT 的)测试有助于准确地突出哪些数据导致了问题,这种行为如何随时间变化,等等。如果您只是将 MMT 测试放入训练集并忘记它,您将失去这种可见性的好处。

除了 MMT 之外,还有其他有趣的方法来为基于 ML 的系统测试定制传统的测试技术。一个具体的方法是 A/B 测试(评估不同选项的好处)。在基于 ML 的系统中,这也可以是从人类用户或操作系统回到测试和训练的反馈回路。特斯拉阴影模式是一个有趣的例子,其中基于 ML 的自动驾驶系统做出连续的驾驶决策,但这些决策从未被实际执行。相反,它们与在这些情况下的实际人类驾驶员选择进行比较,这用于改进模型。类似的方法很常见,系统可以从人类的纠正中学习,例如基于人类与系统的交互来调整搜索引擎结果和机器翻译。你也在改变/变形这个系统,但是以不同的方式。这也将成为 MMT 的一个有趣的种子输入源,以及变形关系的 oracle 数据(例如,人类用户采用的驱动路径)。

结论

测试基于机器学习的系统是与更传统的系统不同的挑战。算法和模型没有明确的输入和输出规范,无法简单地测试和验证。两者的潜在空间往往相当巨大且嘈杂。变形测试是一种非常有用的技术,可以通过合理的努力获得对其操作的信心。与传统测试技术相比,它不是一种替代方法,而是一种补充方法。

在本文中,我给出了几个将 MMT 应用于不同领域的例子。虽然不同领域的应用需要不同的考虑,但我相信可以得出一些普遍有用的指导原则,以帮助在基于 ML 的系统上执行 MMT:

  • ****变形转换:这些不需要非常复杂,但是简单的就能带来很好的好处,比如给激光雷达云添加一些随机的点。考虑相同的输入在其预期的使用环境中会如何变化,以及这样的变化如何以最少(或合理)的努力作为转换来实现。
  • ****变形关系:为了建立这些关系,我们需要问我们如何改变 ML 输入,它应该对输出有什么影响?有时这需要深厚的领域专业知识来识别最相关的变化,例如在医学领域的例子中。
  • 测试预言:**它们检查所执行的转换是否产生了可接受的(有效的)输出。需要考虑诸如如何表示变化(例如,转向角变化、句子结构变化)、可能定义某些错误的概率、错误的严重性以及转换后潜在输出之间的距离度量(例如,转向角计算)。也就是说,这些值可能不是固定的,而是在一个连续范围内。
  • 时间关系:在许多系统中,输入和输出并不是单一的,但是整个系统在一段时间内的性能很重要。这可能还需要问时间如何影响系统,以及在变形关系序列中应该如何考虑时间的问题。总体测试场景 作为更广泛的上下文、时间相关和其他方面的提供者,在这里考虑是有用的。**
  • ****测试数据:你能使用用户与系统的交互作为转换和变形关系的自动测试输入源吗?想想特斯拉阴影模式,谷歌搜索结果,以及来自环境和用户的输入,并使用对这些输入的反应。

正如一些例子所讨论的,我看到的一个有趣的趋势是使用基于 ML 的算法来为基于 ML 的系统产生或增强(基于 MMT 的)测试。在 NLP 领域中,这通过使用 BERT 作为工具来构建用于测试自然语言翻译的变形转换来显示。在自动驾驶汽车领域,通过使用基于 GAN 的网络来创建图像属性之间的转换,例如不同的天气元素和一天中的时间。

总的来说,ML 领域似乎仍在快速发展,MMT 已经有了一些有用的方法,并且有望在未来几年内有更成熟的工具。如果没有良好的工具支持来进行测试(数据生成、模型覆盖度量等),找到具有所有这些专业知识(测试、机器学习、领域细节等)的人,并为每个系统重新实现它,似乎是一个相当大的挑战,如果没有良好的工具和方法支持,有时会是不必要的高强度工作。

今天就到这里,这太长了,所以如果有人设法读到这里,我会印象深刻:)。如果你有测试基于 ML 的系统的经验并愿意分享,我有兴趣在评论中听到和学习:)

用 Julia 中的 Compose 对坐标解析器进行元编程

原文:https://towardsdatascience.com/metaprogramming-a-coordinate-parser-with-compose-in-julia-a0d163c6fb21?source=collection_archive---------46-----------------------

在函数式编程语言中结合 Oop 和 Meta

(茱莉亚计算标识由https://juliacomputing.com/提供)

介绍

在 Julia 机器学习包王朝内部,特别缺乏好的绘图库。幸运的是,我很快就要为 Julia 发布我的第一个图形库版本 Hone.jl 了。Hone 非常酷,因为它使用了一种独特的面向对象编程的函数式方法,还使用了一些非常酷的元编程。

这个想法

(笔记本)

我对这个项目成果的愿景是用函数式语言进行面向对象的图形化。我想这样做的原因是在每个对象的基础上将函数与可变数据结合起来。这个想法的伟大之处在于,你可以将对象组合在一起,以获得完全自定义的绘图体验。如果我们要分别创建所有的对象,用 compose 将它们组合成一个矢量图形是不可能的。相反,我想使用元编程将元数据从一个对象传递到下一个对象,这样就可以通过命令以字符串的形式传输。

面向对象

为了将面向对象的范例引入到 Julia 中,我使用了一种我在车床. jl 上工作时熟悉的方法,您可以阅读更多相关内容

这里:

[## 我如何使用面向对象的函数来进行机器学习

我如何以及为什么将面向对象的范例应用于 Julia 机器学习。

towardsdatascience.com](/how-im-using-functional-oop-for-machine-learning-533c1d764628)

为了完成这项工作,我们需要创建一个函数,用数据和函数构造一个未命名的类型。在 Julia 中,我们可以通过将这个短语添加到我们的函数中来实现,以便返回一个包含我们的方法的对象,作为存储在对象内部的数据。

 ()->(sttring;tree)
end

在定义了要放入类型的数据后,我们可以简单地将这个短语添加到函数中。

function printerobject(sttring)
    tree() = println(sttring)
    ()->(sttring;tree)

使用这种方法需要注意的一点是,Julia 求值中的类型赋值将创建一个包含数据的盒子,而不是创建一个包含数据的对象。这既是一件好事也是一件坏事,因为除了它所携带的数据之外,我们无法以任何其他方式来辨别这个物体的类型。为了减轻这个确切的问题,我决定去元。

如果有一件事在 Julia 中处理得绝对令人难以置信,那就是元编程。元编程是使用数据作为语法代码的编程。为了在 Julia 中这样做,您实际上不再需要像以前那样导入任何东西。现在不是做,

使用 Meta

你可以简单地使用包元。我喜欢这个,因为它保留了朱莉娅的分段。在 Julia 中进行元编程时,你真的只需要两个相对直接的方法。首先,您需要通过元解析器运行您的代码,以便将它转换成表达式。表达式是 Julia 中的一种类型,可以通过 eval 方法轻松计算。Julia 通过在符号类型中创建表达式并使用其中的代码作为数据来实现这一点。

零件

(src =https://www.pikrepo.com/fprqp/brown-piece-of-puzzle

规划项目的一个很好的方法是首先概述所有将一起工作以产生最终结果的组件。首先也是最重要的是物体,第一次我将使用一个标准的圆。最重要的是,对象需要能够存储元数据,不幸的是,元数据可能需要修改,所以必须是可变的。另一个核心组件将是圆组合成的对象,即情节本身。这是拼图的另一个关键部分,坐标解析器。坐标解析器需要从提供的数组中获取数据,并将其与我们的对象中包含的元数据相结合。

该对象

如前所述,我想为我的第一个物体画一个简单的圆。下面是我们可以使用 compose 制作一个圆的代码:

using Compose
compose(context(),circle(.5,.5,.1)))

在合成中,上下文只是一个合成的集中节点,该合成中的所有对象都附着于该节点。我们可以将这个组合写入对象的初始化函数中:

function Circle(diameter,x,y)
    composition = compose(context(), circle(x,y,diameter))
    ()->(composition)
end

这将输出一个只存储数据组合的新对象,但是通过一个简单的插件,我们可以添加显示我们的组合的能力:

function Circle(diameter,x,y,fillin)
    composition = compose(context(), circle(x,y,diameter))
    show() = composition
    ()->(show;composition)
end

现在我们可以使用 Circle.show()来显示我们的圆。

我想添加的另一个很酷的东西是能够查看这个组合中所有连接图形的树。为此,我们将像以前一样使用 introspect()方法:

function Circle(diameter,x,y,fillin)
    composition = compose(context(), circle(x,y,diameter))
    show() = composition tree() = introspect(composition)
    ()->(show;composition)
end

这里我们看到我们的组合,它连接到我们的上下文节点,然后是我们的形状。在这个树视图中,组合用桃点标记。现在我们已经完成了基础工作,我们应该将这个项目的元端添加到我们的新对象中。

为了理解我们需要在事物的元端完成什么,在通过百分比计算器运行数据后,我写了一个字符串,其中包含我们想要的内容,百分比计算器将在解析器中发挥作用。

using Base.Threads
# If we use .5 for x and y, notice how we get our return perfectly centered.
#    We use a percentage of the total length.
# Let's do one manually with those xs and ys.
"""This function will allow for automatic 
calculation of percentages for a coordinate plane"""
function percentagecalc(x,y)
    xmax = maximum(x)
    ymax = maximum(y)
    newx = []
    newy = []
    [@threads](http://twitter.com/threads) for i in x
        dim = i / xmax
        append!(newx, dim)
    end
    [@threads](http://twitter.com/threads) for i in y
        dim = i / ymax
        append!(newy, dim)
    end
    return(newx,newy)
end

通过元解析器运行它,然后对它进行评估。

我们的目标是自动创建该字符串。

我决定创建一个名为 update()的函数作为我们类型的子函数。

function Circle(x,y,diameter,fillin)
    composition = compose(context(), circle(x,y,diameter), fill(fillin))
   #     "compose(context(),circle(.5,.5,.1))
    tag = string("circle(",string(x),",",string(y),",",string(diameter),")")
    tree() = introspect(composition)
    show() = composition
    x = x
    y = y# ========================================================
    update(x,y) =  tag = string("circle(",string(x),",",string(y),",",diameter,")")# ==============================================
    (var)->(show;composition;tree;tag;x;y;update;diameter)
end

为了用来自散点图解析器的数据更新 x 和 y 的值,update 函数获取 x 和 y 并更新元标记。这似乎是正确的做法,但是这段代码会给我们带来一个小问题。

坐标分析器

我们的散点对象中最简单但最重要的部分是坐标解析器。首先,坐标解析器必须根据坐标平面内的最高值计算每个数字的百分比。许多图形 API 实际上都是这样做的,其中屏幕被划分为百分点,缩放是通过将一个位置除以分辨率来实现的,以获得屏幕上的准确位置。我们可以通过获取两个坐标平面中的最大值来做到这一点:

topx = maximum(x)
topy = maximum(y)

然后我们可以做一个快速的迭代循环,将这些值换算成百分比。

x = [z = z / topx for z in x]
y = [z = z / topx for z in x]

将来,将它与解析器结合起来可能更有意义,因为这是一个额外的迭代循环(我们不能放在线程上)。对于迭代解析,zip 显然是最简单的选择。

for (i, w) in zip(x, y)
        shape.update(i,w)
        exp = shape.tag
        expression = string(expression,string(exp))
    end

把所有的放在一起

既然我们已经对所有相关元素进行了普查,我们可以将它们放在一起。我们将使用坐标解析器设置我们的散布方法,

function plot(x,y,shape)
   topx = maximum(x)
    topy = maximum(y)
    x = [z = z / topx for z in x]
    y = [z = z / topx for z in x]
    expression = string("compose(context(),")
    for (i, w) in zip(x, y)
        shape.update(i,w)
        exp = shape.tag
        expression = string(expression,string(exp))
    end
    expression = Meta.parse(string(expression, ")"))
    eval(expression)
end

我们的形状物体,

function Circle(x,y,diameter,fillin)
    composition = compose(context(), circle(x,y,diameter), fill(fillin))
   #     "compose(context(),circle(.5,.5,.1))
    tag = string("circle(",string(x),",",string(y),",",string(diameter),")")
    tree() = introspect(composition)
    show() = composition
    x = x
    y = y
    update(x,y) =  tag = string("circle(",string(x),",",string(y),",",diameter,")")
    (var)->(show;composition;tree;tag;x;y;update;diameter)
end

以及伴随它们的元标签。在创建我们的对象并通过 scatter 函数运行它之后,我们得到了这样的回报:

"没有匹配的方法*(core.box,core.box)"

因此,显然我们有一个问题,它很好地描述了以未命名类型保存不可变数据的问题。如果我们返回到解析器函数并注释掉 eval()方法,我们可以看到解析后的元标记抛出了这个错误。

存储在我们的“类”中的数据被放入一个 Julia 中。考虑到我们想要“未装箱的数据”,这是一个相当大的负面影响然而,隧道的尽头有光明。当我们在坐标解析器内部调用 shape.update()方法时,对象内部的数据(只能私下变异)被更改,然后在下一行读取。我们可以使用这个函数获取数据而不从对象访问它的一种方法是使用一个返回。

为了测试这一点,我首先像以前一样创建了我们的标准问题形状:

circ = Circle(.5,.5,.5,"orange")

然后返回并修改对象以返回元标记。我必须先生成变量,否则,我们会在常规函数上得到一个字符串的返回。

function Circle(x,y,diameter,fillin)
    composition = compose(context(), circle(x,y,diameter), fill(fillin))
   #     "compose(context(),circle(.5,.5,.1))
    tag = string("circle(",string(x),",",string(y),",",string(diameter),")")
    tree() = introspect(composition)
    show() = composition
    x = x
    y = y
    update(x,y) =  tag = string("circle(",string(x),", ",string(y),", ",diameter,")");return(tag)
    (var)->(show;composition;tree;tag;x;y;update;diameter)
end

做这个测试表明,使用 return 确实解决了这个问题,但是现在有了 return 的问题,为了解决这个问题,我认为最好使用一个简单的条件。下面是我对更新函数的改进:

update(x,y) =  bravo = true;tag = string("circle(",string(x),", ",string(y),", ",diameter,")"); if bravo == true return(tag); bravo = false end

“bravo”是一个 bool 类型,它跟踪我们是否正在更新标签,以便我们可以确定是否要返回标签。一个很好的思考方式是将“bravo”想象成该功能的“on”灯。如果 bravo 为真,那么 update()函数正在运行——这是我们唯一需要这个返回的时候。

而且现在我们的表情看起来还不错!

结论

嗯,算是吧……我们当中目光敏锐的人可能已经注意到,这些圈子正在增加,而不是添加到上下文中,幸运的是,这个问题应该不会花太长时间来解决。然而,不幸的是,它将不得不等待第二部分!在下一部分中,我计划将每个四分位数作为一个对象添加指导原则,以及文本对象。真正令人印象深刻的是,在 Julia 中使用元编程可以表现出多大的表现力。

Julia 中图形类的元编程(下)

原文:https://towardsdatascience.com/metaprogramming-a-graph-class-in-julia-90a90e8ab45b?source=collection_archive---------60-----------------------

回来看我再次陷入朱丽亚精神错乱。

在 Julia 中使用面向对象编程确实很有趣,但是我认为函数式语言中的面向对象编程和 Julia 类似 Lisp 的元能力的结合为这样的东西建立了一个真正强大而充分的联系。

第一部

笔记本

有什么新鲜事?重构。

如果您还记得,我们离开时遇到了一个小问题:我们不小心将对象的元标签放在了一起。下面是我们的代码:

function Circle(x,y,diameter,fillin)
    bravo = false
    composition = compose(context(), circle(x,y,diameter), fill(fillin))
   #     "compose(context(),circle(.5,.5,.1))
    tag = string("circle(",string(x),", ",string(y),", ",string(diameter),")")
    tree() = introspect(composition)
    show() = composition
    x = x
    y = y
    update(x,y) =  bravo = true;tag = string("circle(",string(x),", ",string(y),", ",diameter,")"); if bravo == true return(tag); bravo = false end
    (var)->(show;composition;tree;tag;x;y;update;diameter)
end
function plot(x,y,shape)
   topx = maximum(x)
    topy = maximum(y)
    x = [z = z / topx for z in x]
    y = [z = z / topx for z in x]
    expression = string("compose(context(),")
    for (i, w) in zip(x, y)
        exp = shape.update(i,w)
        expression = string(expression,string(exp))
    end
    expression = Meta.parse(string(expression, ")"))
    eval(expression)
end

所以很接近了,但显然有一些关键问题需要解决,所以当我重新投入工作时,我做的第一件事就是重构这两个函数。首先,我们的乘法问题。元编程的一个缺点是,您的错误与您的问题有很大的不同,并且会误导您的问题。我认为这个问题是由元代码中某处缺少逗号引起的。如果你在上面的更新函数中查看我们的代码,在那个括号后面需要有一个逗号。添加后,嘣,坐标解析通过罚款。

此外,我选择通过简单地将函数设置为一个字符串来缩短函数,而不是使用条件。每当我编程时,随着时间的推移,一切都会变得更好,我没有意识到我可以这样做,这让我感觉很不好。区别如下:

update(x,y) =  string("circle(",string(x),',',string(y),',',diameter,"), ")update(x,y) =  bravo = true;tag = string("circle(",string(x),", ",string(y),", ",diameter,")"); if bravo == true return(tag); bravo = false end
    (var)->(show;composition;tree;tag;x;y;update;diameter)

第二个是原件

新功能

T 今天,我计划创建我们的第一组轴,并允许在函数中使用颜色,就像符号一样。轴应该不会花很长时间,但做元可能会很费时间。至于颜色串,我有一个很好的主意。所以我要做的第一件事就是把这两件事合二为一,用我的想法在一个新的函数上画出线条。当我处理这样一个新函数时,我会想到 I.O。我们需要从这个函数得到的唯一输出是元数据,即组合成表达式然后被解析的字符串。我想说的是,编写代码字符串并填充参数是一种非常酷的做事方式。也许我刚刚脱离了函数式编程的深渊…

增加一个 X 和 Y 轴,我认为会相对简单。首先,我们当然需要画一条线的能力。这个组合需要的输入是一个坐标对数组,然后是线条的颜色。

当访问字典键时,有一个小技巧可以将它们作为字符串访问,只需使用 Symbol()将字符串转换为符号。我的计划与此正好相反,使用 string()转换一个符号。我们需要这样做的原因是,我们不能用元编程来解析 Julia 内部的字符串,但是简单地将数据包含在一个符号中,然后在执行时将其转换为字符串就解决了这个问题。我还添加了我们的标准基本函数库。

function Line(pairs, color)
    tree() = introspect(composition)
    show() = composition
    composition = compose(context(), line(pairs), stroke(string(color)))
    (var)->(show;composition;tree)
end

现在来测试一下:

有点难以看清,但我们确实在那里划了一条线!接下来,我们将使用 update()函数添加元数据,它可能被更改为 tag()或类似的内容。一般来说,这就是我们想要用元数据创建的内容:

颜色…?

在元编程中,一个令人惊讶的困难挑战是字符串参数。不幸的是,似乎我们也不能使用反斜杠和正则表达式来摆脱这种情况…我的解决方法是将符号用作字符串,类似于我之前展示的 DataFrames.jl 技巧:

array_from_dict = dictionary[Symbol("Has Spaces")]

但是为了做到这一点,我们将需要做完全相反的事情,而不是断言符号的字符串类型,这样就有可能连接一个变量字符串,而不用将其解析为变量。这是必需的,因为当解析为变量而不是原始数据时,变量当然是未定义的。例如,如果我们要在正常作文之外制作一个表达式:

如您所见,当我们的颜色组合成一个字符串时,它返回未定义。我们的目标是让字符串保留该数据周围字符串的引用。在无数次尝试经典符号到字符串断言之后,我无法实现我最初的想法。虽然它在某些尝试中确实工作得很好,但我无法让它在我的实际类型中工作,所以继续我的下一个想法,

字符。

char 是一种需要保存一个字节数据的数据类型。一个字符串实际上是由单独的字符组合在一起组成的。在 Julia 中,我们可以像访问数组中的 dim 一样访问字符串中的字符:

这是区分字符串和整数在结构层次上的内在差异的一个很好的方法。信不信由你,一个整数也可以包含在一个字节的数据中,但这个字节将保存整个数字,而不是数字中的一个字符。

number = 156
println(156[1])156

当然,你可以像访问字符串中的字符一样访问数组中的 dim,这就是为什么我总是重申字符串比乍看上去更像数组。就我的想法而言,最简单的方法是将字符串分隔符作为字符添加到表达式中,但这很有可能不会按计划进行。第二种选择是编写一个字符串解析器,它可以迭代地将我们的数据转换成一个连续的字符串。

对于我的第一个测试,我尝试了最简单的方法,你可以在上面看到它是如何完成的。在解析和评估之后,这是我获得的输出:

这看起来不太好。

您可能想知道为什么我不简单地使用带有元字符的正则表达式。嗯…

我们不能将表达性的字符串连接成单一的字符串类型。

我现在决定做的是让颜色稍微休息一下,然后继续前进,但是我们肯定会在我的下一篇文章中回来讨论它们!

在回顾我的函数并修改后,我很快意识到开始的循环肯定是设置 y 等于 x,这里表示为:

function plot(x,y,shape)
   topx = maximum(x)
    topy = maximum(y)
    x = [z = z / topx for z in x]==========================================================
    y = [z = z / topx for z in x] # <- What????==========================================================    expression = string("compose(context(),")
    for (i, w) in zip(x, y)
        exp = shape.update(i,w)
        expression = string(expression,string(exp))
    end
    expression = Meta.parse(string(expression, ")"))
    eval(expression)
end

在纠正了这个问题之后,我终于能够策划我的秘密信息了:

结论

我当然希望我们今天有功能性的颜色和轴,但是看起来这些故事变得很长很快!不管怎样,我对计划的进展很满意,尽管我遇到了很多障碍。我从这个项目中得到了很多乐趣,也确实学到了很多。注意安全,呆在家里,保持健康!

Hone.jl 的元编程网格和标签

原文:https://towardsdatascience.com/metaprogramming-grids-and-labels-for-hone-jl-f434c8dc24ad?source=collection_archive---------67-----------------------

Hone.jl

为 Julia 修复我的网格并将轴标签添加到我的图形库中

上次我们停止了 Hone.jl 的工作,这是一个模块化的、面向对象的图形库,它使用元编程来提供一个可扩展的平台,我们遇到了相当多的问题。首先,网格绘制得非常不准确,这使得它们实际上毫无用处。这也产生了额外的障碍,因为标签不能被添加到这样的网格中。我们得到的图看起来像这样:

此外,尽管这些点与我们标绘的坐标正确对齐,但它们肯定没有与我们的轴和网格对齐。这是因为合成插图的原点并不是数据科学家通常认为的图形的原点。相反,Y 轴的原点实际上在左上角。因此,例如在(5,5)处绘制的点将位于左上角而不是左下角。

另一件事,我想戏剧性地改变 Hone 是整个方式的阴谋组装。以前,元表达式会被扔在一起,在一个又长又乱的元编程混乱中解析。我想改变这一切。Hone 的整个思想围绕着模块化。必要时,您应该能够轻松地从其他地方添加不同的网格,或者甚至为一些不同的结果运行不同的坐标解析器。然而,以现在的散射函数的方式,这是完全不可能的。

笔记本

上一篇文章

https://github.com/emmettgb/Hone.jl

修复我们的电网

也许我在 Hone 中遇到的最突出和最可怕的问题是网格。网格是根据框架的尺寸划分绘制的,这可能非常简单。数学是这样的:

function Grid(divisions,frame=Frame(1280,720,0mm,0mm,0mm,0mm),colorx=:lightblue,colory=:lightblue,thickness=.2)
    xlen = frame.width
    ylen = frame.height
    division_amountx = xlen / divisions
    division_amounty = ylen / divisions
    total = 0
    Xexpression = "(context(), "
    while total < xlen
        total = total + division_amountx
        linedraw = Line([(0,total),(xlen,total)],:lightblue,thickness)
        exp = linedraw.update(:This_symbol_means_nothing)
        Xexpression = string(Xexpression,string(exp))
    end

这当然是初看起来可以工作的代码。首先,我们得到框架的宽度和高度,并除以我们的分割数。之后,我们迭代地为每一行添加每个表达式,直到我们达到框架的宽度或高度。我们在 while 循环中这样做,当然,当总长度小于相应帧的宽度或高度时,它保存控制流。

那么问题是什么呢?

我认为真正的问题在于,一个非常小的矛盾或问题会在未来造成一个非常大的问题。X 轴的分割量通过将宽度除以网格中的分割数来计算。这里的问题是,X 网格线与 Y 轴上代表值的线相对应,而 Y 轴上的值正好相反。我们如何解决这个问题?虽然有时可能会令人困惑,但这可以通过简单地颠倒我们的 X 和 Y 来解决

function Grid(divisions,frame=Frame(1280,720,0mm,0mm,0mm,0mm),colorx=:lightblue,colory=:lightblue,thickness=.2)
    xlen = frame.width
    ylen = frame.height
    division_amountx = ylen / divisions
    division_amounty = xlen / divisions
    total = 0
    Xexpression = "(context(), "
    while total < xlen
        total = total + division_amountx
        linedraw = Line([(0,total),(xlen,total)],:lightblue,thickness)
        exp = linedraw.update(:This_symbol_means_nothing)
        Xexpression = string(Xexpression,string(exp))

同样,当我们面临为网格创建标签的挑战时,我们也需要遵循这个想法。本例中所做的更改只是将 ylen 划分为 division_amount X,将 xlen 划分为 division_amount Y。结果,我们得到了一个漂亮的网格,如下所示:

网格标签

现在我们有了工作网格和标签类型,我想创建的下一个类型当然是 X 轴和 Y 轴的标签。我们将从参数开始。我们有两个选择来获得网格位置,我们可以

  • 将它们保存在网格类型中
  • 或者重新计算它们。

虽然将它们保存到网格类型可能会使我们在参数方面更容易使用,但我相信这将使将来实现更多的自定义功能变得更加困难。这样做的部分问题是 GridLabels 并不意味着是一个将许多元素组合到一个框架中的总结功能,而是一个可以从框架中添加或删除的功能。在这方面,它更类似于 HDraw.jl 文件中的许多方法,而不是 HPlot.jl 文件中的方法。我们的网格标签也需要我们的 x 和 y 值来生成标签本身。

function GridLabels(x,y,grid,buffer=20)
    frame = grid.frame
    xvals = grid.xvals
    yvals = grid.yvals
    topy = maximum(y)
    topx = maximum(x)
    tag = "(context(), "

我们可以获得框架,我们将需要从网格类型的一些计算。在这个函数的最初版本中,我决定尝试将网格位置的值存储在以下类型中:

for value in xvals
        lbl = value / frame.height * topy
        grlbl = Label(string(lbl),buffer - 5, value)
        tag = string(tag,grlbl.tag)
    end
    for value in yvals
        lbl = value / frame.width * topx
        grlbl = Label(string(lbl),value, buffer - 5)
        tag = string(tag,grlbl.tag)
    end
    tag = string(tag,")),")
    composition = Meta.parse(tag)
    show() = eval(composition)
    ()->(tag;xtags;show)

这是通过获取相对于框架高度的值的百分比来完成的,网格的数学是基于这个百分比的。重要的是要记住,任何对象在 Hone 中的位置与它上面的帧成正比,就像在大多数图形工作中一样。然后,我们将这个百分比乘以 topx 中的最高值。在有四条网格线的例子中,我们将有 0.25 条递增到 1 条,每条乘以标签数据中的最大值,以及位置分辨率中的最高值。然而,我发现在网格类型中存储这样的数据会产生更多的问题,而不是解决方案。

然而,在我的第二次修改中,我修改了这个想法,创造了一些更好的东西:

function GridLabels(x,y,grid,label = "X",buffer=20)
   frame = grid.frame
    divamountx = grid.division_amountx
    total = divamountx
    topx = maximum(x)
    topy = maximum(y)
    xlabels = []
    while total < (divamountx * grid.divisions)
        percentage = frame.height / total
        curr_label = topx * percentage
        push!(xlabels,(curr_label, total))
        total += divamountx
        print(total)
    end
    xtags = ""
    for (key,data) in xlabels
        textlabel = Label(string(round(key)), 40 , data, "", 3)
        xtags = string(xtags, textlabel.tag)
    end
    tag = xtags
    ()->(tag;xtags)
end

在我解释了我对 h one 库的另一个问题的失望之后,最终产品将会揭晓…

非模块化绘图

如果你曾经瞥了一眼 Hone 中的 scatter 函数,并了解到其中的一些代码与 Hone 背后的方法论直接矛盾,那么你肯定不是唯一一个这样做的人。我认为,与其让函数来做诸如解析坐标或向图中添加线条之类的事情,不如一次一个地将代码片段硬编码到函数中来做这些事情,这将是一个绝妙的主意。参观展品 A:

_arrayscatter 函数。

function _arrayscatter(x,y,shape=Circle(.5,.5,25),
        features = [Grid(3), Axis(:X), Axis(:Y)],
        frame=Frame(1280,720,0mm,0mm,0mm,0mm), 
        buffer = 90)
    fheight = frame.height - buffer
    fwidth = frame.width - buffer
    topx = maximum(x)
    topy = maximum(y)
    expression = string("")
    # Coordinate parsing -------
    for (i, w) in zip(x, y)
        inputx = (i / topx) * fwidth
        inputy = (w / topy) * fheight
        exp = shape.update(inputx,inputy)
        expression = string(expression,string(exp));
    end
    points = transfertype(expression);
    frame.add(points);
    for feature in features
        frame.add(feature);
    end
    composition = eval(expression);
    show() = frame.show()
    tree() = introspect(composition)
    save(name) = draw(SVG(name), composition);
    get_frame() = frame
    add(obj) = frame.add(obj)
    (var)->(show;composition;tree;save;get_frame;add;x;y;points)
end

这个函数不仅有点难看,它还需要自己独特的类型,以便将自己的标签传输到帧中。它不是一个由输入自动生成的对象集合,它本身是一些对象,旁边还有一个对象集合。在 Hone.jl 的背景下,Hone.jl 的理念是什么;这完全说不通。我对此采取的第一个行动是创建一个完全独立的函数来创建轴类型:

function Axis(orientation=:X, axiscolor = :gray, frame=Frame(1280,720,0mm,0mm,0mm,0mm), buffer = 90)
    if orientation == :X
        pairs = [(buffer,frame.height - buffer), (frame.width,frame.height - buffer)]
    else orientation == :Y
        pairs = [(buffer,0),(buffer, frame.height - buffer)]
    end
    axis = Line(pairs,axiscolor)
    tag = axis.update([pairs])
    (var)->(tag)
end

这是相对简单的!接下来,我决定对坐标做同样的事情,以便进一步精简函数。

function Points(x, y, frame=Frame(1280,720,0mm,0mm,0mm,0mm), buffer = 90, shape=Circle(.5, .5, 25))
    fheight = frame.height - buffer
    fwidth = frame.width - buffer
    topx = maximum(x)
    topy = maximum(y)
   tag = string("")
    # Coordinate parsing -------
    for (i, w) in zip(x, y)
        inputx = (i / topx) * fwidth
        inputy = (w / topy) * fheight
        exp = shape.update(inputx,inputy)
        tag = string(tag,string(exp))
    end
    tag = string(tag)
    show() = eval(Meta.parse(string("compose(context(), ", tag,")")))
    (var) -> (tag)
end

在所有的复制、粘贴和轻微的重构之后,我们有了一个可爱的小函数,如下所示:

function _arrayscatter(x, y,
        shape=Circle(.5,.5,25),
        features = [Grid(3), Axis(:X), Axis(:Y)],
        buffer = 90,
        frame=Frame(1280,720,0mm,0mm,0mm,0mm), 
        )
    points = Points(x, y, frame, buffer, shape)
    frame.add(points)
    for feature in features
        frame.add(feature);
    end
    show() = frame.show()
    tree() = introspect(composition)
    save(name) = draw(SVG(name), composition);
    get_frame() = frame
    add(obj) = frame.add(obj)
    (var)->(show;composition;tree;save;get_frame;add;x;y;points)
end

我喜欢这一点,因为它更侧重于作为对象的对象和作为对象的持有者的框架,而不是整个数组散点图是我们将对象分解成元表达式以及其他类型的组合。有了这些解决方案,我还注意到了另一个问题。如果您还记得,Compose 的起始点肯定不是您所期望的位置。它不在左下方,而是在左上方。结果,我们的许多 y 坐标被颠倒,因此与我们的新网格标签不匹配。

为了解决这个问题,我简单地用高度减去我们的新值,并把它作为我们的输入 y。

function Points(x, y, frame=Frame(1280,720,0mm,0mm,0mm,0mm), buffer = 90, shape=Circle(.5, .5, 25))
    fheight = frame.height - buffer
    fwidth = frame.width - buffer
    topx = maximum(x)
    topy = maximum(y)
   express = string("")
    # Coordinate parsing -------
    for (i, w) in zip(x, y)
        inputx = (i / topx) * fwidth
        inputy = (w / topy) * fheight
        **inputy = fheight - inputy**
        println(inputx)
        println(inputy)
        exp = shape.update(inputx,inputy)
        express = string(express,string(exp))
    end
    tag = express
    show() = eval(Meta.parse(string("compose(context(), ", tag,")")))
    (var)->(tag;show)
end

结论

在对 Hone 库做了所有这些伟大的工作之后,我很兴奋地向你展示从 0.0.5 版本开始的新的默认绘图!

在我个人看来,这里的改善是超乎戏剧性的。首先,我们有准确表示的数据,没有颠倒,没有在错误的地方。这个可视化的 X 和 Y 都是[5,10,15,20],这正是该图所显示的。最重要的是,我们可以使用新的直线网格和网格标签来查看我们在实际数据周围的位置!

我对 Hone.jl 现在所处的位置以及它很快将会出现的位置感到非常兴奋!还有很多工作要做,但我希望图形架构的基础已经非常接近完成,我所有的错误修复都不需要再存在了!(在完美的世界里。)尽管偶尔会遇到困难,但我从这个项目中学到了很多,我非常兴奋地看到它在我的项目中的有效性以及其他人对它的使用!

组织病理学图像扫描中转移癌检测

原文:https://towardsdatascience.com/metastatic-cancer-detection-in-histopathological-image-scans-de4eeb570a8?source=collection_archive---------27-----------------------

使用机器学习来预测癌症是否在显微图像中。

癌症的可怕故事

癌症仍然是世界上最致命的疾病之一,每年导致超过 1000 万人死亡。癌症如此致命的原因之一是,如果不管它,即使是很短的一段时间,它可能已经接管了一个生物系统。早期诊断是战胜癌症的关键,而机器学习正在彻底改变早期诊断。

机器学习能够推断出人类无法推断的模式。这包括在图像中寻找非常抽象的模式。使用机器学习的能力,可以创建一个模型来从图像扫描中的非癌细胞中推断出癌细胞。卷积神经网络也可以帮助解决这个问题,因为它们非常适合在图像扫描等空间敏感数据中寻找关系。

转移癌

癌症通常始于身体的原发部位,然后恶性扩散。源自身体原发部位的癌症是转移性癌症。从本质上说,继发性癌症是原发性癌症的直接结果。那么为什么我们要寻找继发性癌症而不是根本原因呢?因为当扫描全身时,更容易推断出继发性癌症,并且当某人患有癌症时,转移性癌症通常少量遍布全身。发现转移性癌症就像一个指标,可以确定某人是否在身体的其他地方患有严重的癌症。

具体来说,转移癌可以在身体的不同器官中发现。我们可以检查组织病理学图像扫描,这是人体内器官和细胞的显微图像。组织病理学图像扫描具有人体正在观察的部位的不同细胞的大量细节,并且可以检查不同的疾病。然而,在这些扫描中很难判断是否存在癌症,因为我们并不都是癌症研究领域的专家。机器学习可以用来解决这个问题,告诉组织病理学图像扫描中是否存在转移癌。

组织病理学图像扫描

机器学习+卷积神经网络

机器学习就是让机器学习如何执行特定的任务。代替给出明确的指令,机器学习创建自己的指令。实际上,所有这些指令都是数学值。机器学习模型只是一个可微分函数,它接受预定义数量的输入,使用变量(权重)对输入执行操作,并产生输出。这就好比 y = mx + bx 是模型的输入, mb 是变量(权重),而 y 是输出。机器算法必须优化 mb 权重,以便在给定任何输入时,它将始终产生所需的输出。我们如何优化我们的变量?基本上有两个步骤,产生损失和反向传播。

损失函数

损失函数是表示模型表现有多差的函数。损失越大,模型表现越差。我们可以通过使用标记的数据来生成损失。我们可以给 x 的模型输入,让它根据自己的权重产生自己的输出。因为我们已经标记了数据,所以我们知道模型的输出应该是什么。我们可以比较模型的输出和真实的输出,看看有什么不同。例如,模型的输出可能是 3,而实际输出可能是 5。本例中的损耗可能是 2,这是两个输出之间的距离。我们希望模型总是产生 0 的损失,这意味着我们需要最小化损失函数

反向传播

反向传播是回到模型的权重并改变它们以最小化损失函数的过程。它通过获取损失函数并计算其梯度来做到这一点。梯度是所产生损耗的瞬时变化率,查看梯度,我们可以找到梯度的最低点,此时重量产生的损耗较低。这被称为梯度下降,是许多机器学习算法的关键。我们可以重复这个过程,直到我们的损失越来越小,而我们的模型越来越好。通常,一个模型会有数千个权重,因此在生成输出时,模型会变得非常精确。

梯度下降可视化

卷积神经网络

卷积神经网络采用了上述机器学习的所有原则,还结合了一种可以分析空间数据(如图像和音频)的方法。它使用过滤器,这是一种使用权重扫描输入数据的机器学习算法。过滤器是扫描输入数据的权重网格,每次扫描时,将权重乘以输入。由于图像也只是数值网格,卷积过滤器可以很容易地越过它们。在一个卷积之后或者当它完成扫描图像时,扫描的结果(乘积)被汇集在一起。池化基本上是用一种更小更简洁的方式表示输入数据,并包含所有重要的特性。从本质上来说,卷积神经网络所做的是,它们推导出图像的特殊特征,并将它们放在一起。

要获得更容易理解的解释,请查看我写的这篇更详细解释卷积神经网络的文章。

转移癌检测模型

数据

用于创建模型的数据是 Kaggle 上的 组织病理学癌症检测 标记数据。它带有超过 150,0 00 张组织病理学扫描图像,每张图像都标有 1 或 0。0 表示图像中没有常见的转移癌,1 表示图像中有转移癌。每个图像是 96 像素乘 96 像素乘 3 个颜色通道(红、蓝、绿)。我们可以用 96×96×3 的网格值来表示每幅图像。

数据示例

型号

该模型的概念是基于机器学习的原则,并针对手头的任务进行定制。

卷积层用于图像的特征提取,以概括癌症图像的样子和非癌症图像的样子。这些层是 2D 卷积神经网络,这意味着卷积层采用值的 3D 矩阵(图像的表示)。

最大池层采用卷积层创建的特征地图,并对其进行概化。这是通过对图像中的每个 3x3 方块取最大值来实现的。这样,当特征图被提供给神经网络的其他部分时,它可以更容易地计算出图像是否包含癌症。

分散在整个网络中的辍学层是为了确保模型学会执行任务,而不仅仅是记住数据。它通过在损失计算过程中关闭某些权重来实现这一点,这导致精度稍低,但可以推广到大量图像。

最后,密集层理解特征图,实际上计算出是否有癌症。最后一层包含一个节点或输出,可以是 0 或 1。0 表示没有癌症,1 表示有癌症。损失函数将使用它来计算损失,反向传播将优化这些层中的权重。

该模型包含超过5100 万+ 个参数,这意味着它可以达到非常好的精确度。

损失函数+优化

用于该模型的损失函数是分类交叉熵损失。该损耗采用模型输出并执行对数函数,然后乘以实际损耗。它使用对数函数,因为当你开始得到真正的答案时,损失会成倍增加。

用于这个模型的优化器是 Adam 优化器。这个优化器执行常规的反向传播,但是当它越来越接近损失函数的全局最小值时,它减慢它优化的速度以防止超过最小值。这是一个非常标准的优化函数。

培训

该模型训练了超过 10 个时期或在整个数据集上执行了批 100 个图像中的 10 次反向传播。20%的图像用于验证或确保模型正在训练。经过几个小时的训练,模型完成了。

结果在……

该模型获得了 80%的癌症检测准确率。也就是说,80%的预测是正确的。这里有几个例子:

该模型的示例

总的来说,该模型工作得非常好,在检测癌症时是一个可行的选择。

参考资料:

https://mc.ai/gradient-descent-and-its-types/(渐变下降图像)

Python 中的方法:数据科学家的基础

原文:https://towardsdatascience.com/methods-in-python-fundamentals-for-data-scientists-6a9393b2c2e7?source=collection_archive---------47-----------------------

用一个具体的例子来理解基础!

制造者在 Unsplash 上 NESA 的照片

Python 类可以保存以下函数:

  • 一个类的一部分(类方法)
  • 实例的一部分(实例方法)
  • 既不属于类也不属于实例(静态方法)

每种方法都有不同的用例。如果你理解了基本原理,你就可以非常清晰地编写面向对象的 Python 代码。

这篇文章将向你介绍这些方法的基础知识和它们的用例。

让我们用 Python3 编写一个包含所有三种方法类型的简单示例的类;

import pandas as pd
import random*class* CSVGetInfo:
**""" This class displays the summary of the tabular data contained in a CSV file """****# Initializer / Instance Attributes**
*def* __init__(*self*, *path*, *file_name*):
 CSVGetInfo.increase_instance_count()
 self.path = path
 self.file_name = file_name**# Instance Methods**
*def* display_summary(*self*):
 data = pd.read_csv(self.path + self.file_name)
 print(self.file_name)
 print(data.head(self.generate_random_number(10)))
 print(data.info())**# Class Methods** @*classmethod
def* increase_instance_count(*cls*):
 cls.instance_count += 1
 print(cls.instance_count)@*classmethod
def* read_file_1(*cls*):
 return cls("/Users/erdemisbilen/Lessons/", "data_by_artists.csv")@*classmethod
def* read_file_2(*cls*):
 return cls("/Users/erdemisbilen/Lessons/", "data_by_genres.csv")**# Static Methods**
@*staticmethod
def* generate_random_number(*limit*):
 return random.randint(1, limit)if __name__ == '__main__':
 data_by_artists = CSVGetInfo.read_file_1()
 data_by_genres = CSVGetInfo.read_file_2() data_by_artists.display_summary()
 data_by_genres.display_summary()

照片由 Skylar Sahakian 在 Unsplash 上拍摄

实例方法

实例方法是类结构中最常用的方法。任何在类结构中定义的函数都是一个实例方法,除非用 decorators 声明。所以,你不需要装饰器来定义实例方法。

**# Instance Method***def* display_summary(*self*):
 data = pd.read_csv(self.path + self.file_name)
 print(self.file_name)
 print(data.head(self.generate_random_number(10)))
 print(data.info())

它们采用一个隐式参数, self 表示方法被调用时实例本身。

借助self参数,实例方法可以访问实例变量(属性)和同一对象中的其他实例方法。

何时使用实例方法

实例方法是类结构的核心,它们定义了类的行为。

我们可以使用特定于实例的数据来执行实例方法中定义的任务。他们可以在 self 参数的帮助下访问实例中包含的唯一数据。

在我们的示例中,我们有两个 CSVGetInfo 类的实例,它们分别存储不同的文件名值“data_by_artists.csv”和“data _ by _ genres.csv”。display _ summary(self)的实例方法通过访问每个实例特有的值来执行任务。

由 Travis Gergen 在 Unsplash 上拍摄的照片

类方法

代替实例方法接受的 self 参数,类方法接受一个 cls 隐式参数。 cls 代表类本身,而不是类(对象)的实例。

***# Class Methods**@*classmethod
def* increase_instance_count(*cls*):
 cls.instance_count += 1
 print(cls.instance_count)@*classmethod
def* read_file_1(*cls*):
 return cls("/Users/erdemisbilen/Lessons/", "data_by_artists.csv")@*classmethod
def* read_file_2(*cls*):
 return cls("/Users/erdemisbilen/Lessons/", "data_by_genres.csv")*

因此,类方法不能修改对象的状态,因为我们需要 self 参数来这样做。相反,他们可以修改对该类的所有实例都有效的类状态。

类方法的编写类似于任何其他方法,但用 '@classmethod' 修饰,并采用 cls 参数。

何时使用类方法

您不必为了使用类方法而创建实例,因为类方法直接绑定到类,而不是绑定到特定的实例/对象。

因此它们用于管理类级操作,如下所列;

  • 实例创建:类方法可用作对象的工厂,以简化设置和实例化工作。
  • 实例管理:我们可以限制一个类可以创建的实例数量。
  • 班级水平查询:它们可以用来提供有关班级的有用信息,例如;创建的实例数。
  • 测试
  • 例子:类方法可以提供类用法的例子,这样其他人可以很容易地理解如何使用类。

静态方法

静态方法不带任何隐式参数。由于不能带 selfcls 参数,所以既不能修改对象状态,也不能修改类状态。

它们就像带有 '@staticmethod' 修饰的类的名称空间内的独立方法。

***# Static Methods**@*staticmethod
def* generate_random_number(*limit*):
 return random.randint(1, limit)*

潘晓珍在 Unsplash 上拍照

何时使用静态方法

由于静态方法是完全独立的代码,它们不能访问类中的任何东西。它们主要使用传递给它们的参数来处理实用程序任务。因此,它们被用作助手或实用函数。

关键外卖

使用 decorators 并正确地标记方法可以让其他人更好地理解我们的意图和类结构。随着其他人更好地理解我们的类架构和正确分配的装饰器,其他开发人员不正确使用我们的类的可能性就更小了。它提供了维护的好处,并有助于防止错误和失误。

结论

在这篇文章中,我解释了 Python 中方法类型的基础。

这篇文章中的代码和使用的 CSV 文件可以在我的 GitHub 库中找到。

我希望这篇文章对你有用。

感谢您的阅读!

研究设计方法——观察研究和调查

原文:https://towardsdatascience.com/methods-of-study-designs-observational-studies-surveys-22f0a04c7446?source=collection_archive---------16-----------------------

了解如何利用真实世界的例子设计研究,以进行有效的数据分析

如今,数据对于研究一个特定的主题是非常重要的。因此,我们应该注意以正确的方式记录数据,以避免得到错误的结果/推断。此外,我们应该对这些数据进行正确的研究/实验,从中得出正确的结论。我们将在这里简要讨论这些方法。

研究尤其可以用 3 的方式进行,这里我们只讨论其中的两种:

  1. 观察性研究:我们感兴趣的变量被记录为自然发生的,没有任何实验者/研究者的干涉。假设我们想推断学生在学习期间是否更喜欢听音乐以获得更好的记忆。我们召集了一些学生,让他们记录下在过去/前一周他们是否在学习时听了音乐,以提高记忆力。另一种方法是,我们要求他们记下在未来一周的学习中是否在听音乐。

在这两种情况下,我们记录的是学生在学习时的自然行为/倾向,我们不会以任何方式干涉他们的行为,比如强迫他们听音乐等。所以我们可以称这项研究为观察研究

再次注意,在第一个场景中,我们记录过去的事件。所以我们称之为 回顾性观察研究 。在第二个场景中,我们正在记录未来的事件,所以我们称之为 前瞻性观察研究

在观察性研究中,可能有一个或多个我们没有考虑的外部变量的影响,但会严重影响我们的结果。这样的一个变量也被称为。举个例子,假设我们要观察哪种方法对公民戒毒比较理想——a .)咨询医生后服用一些药物/抗药或者 b.) 干脆什么都不做或者不遵医嘱。**

令人惊讶的是,我们的结果显示,什么都不做会给出更好的结果。这可能是因为那些什么都不做也不去看医生的人有更强烈的愿望/意志力去戒掉毒品。于是欲望在这里变成了潜伏变量

潜在变量对学习的影响

2.抽样调查:在这里,个人通过某种方式向研究者报告他们自己对于被测变量的值。这些手段包括人员挨家挨户走访并记录观察结果,通过电子邮件发送问卷电话访谈网络调查、等。

偏差 在调查中是一个大问题。收集数据/记录的方法中的不公平被称为偏差。这是调查中的一个严重问题,会导致从收集的数据中得出错误的推论。

让我们首先讨论一下我们在调查中遇到的一些常见类型的偏见:

****便利偏差或便利样本:完全根据进行调查的人的便利来选择。假设您想从购买了某个特定产品的顾客那里获取反馈。但是为了方便起见,您只要求前 50 名买家提供反馈。现在它是错误的,因为它可能是最后几个买家得到了有缺陷的产品。所以我们忽略了他们。最好的办法是随机选人。

****志愿者/自选偏见:这里个人自己选择成为调查的一部分。假设,一项调查正在进行,以计算一个特定地方的平均收入。参与者必须到调查中心来记录他们的收入。显然,成功和高收入的人会自发去记录他们的收入,但低收入的人可能会羞于透露他们的收入。在这里,只有高收入人群自愿参与调查,因此我们无法获得特定地区平均收入的真实估计值。

****无响应偏差:个人未完成或返回其调查响应表或拒绝回答。在上面的例子中,低收入人群拒绝成为调查的一部分,导致了无回答偏差。

回答偏差:**个人参加了调查,但没有正确回答问题。假设在一次选举后,进行了一项调查,打电话给人民,问他们是否投了票。现在调查后发现,说的人比公开记录多很多。很明显,这里许多参与者撒谎了,也就是说,尽管没有投票,他们还是说,因为他们想被认为是这个国家的负责任的公民,因为所有负责任的公民都投票。**

覆盖面不足偏差:**调查不包括目标人群中特定群体的适当代表性。假设学校当局正在进行一项调查,评估每个年级的教师质量。但是他们忘了包括 7 年级和 8 年级。所以并不是一所学校的所有年级都包括在调查中。这就是欠报道偏差

调查中的问题类型:

  1. 开放性问题:**它可以有无限的答案。你最喜欢的学习主题是什么?它可以有很多答案,从非常笼统的像计算机科学到非常具体的像深度学习。**
  2. ****封闭式问题:意在有具体答案。你最喜欢的话题是什么?是机器学习、深度学习还是强化学习?

在为调查提出问题时,应该记住:

a.开放式问题限制较少,但答案/回答可能难以概括。

b.封闭式问题有很高的机会出现偏差。

c.问题应该是中立的,它不应该影响任何即将到来的问题的答案,容易理解,应该能够从参与者那里获得诚实的回答。

****注:有时候在为问题提供的选项中我们经常会看到类似“不知道”或者“选择不回答”的选项。前者用在参与者不知道这个话题或者已经忘记这个话题的时候。

选择不回答当被问到敏感/冒犯/尴尬的问题时使用。对于任何与医疗或艾滋病相关的调查,他们都会问你在性交时会采取什么保护措施?许多人可能会觉得回答这个问题很尴尬。

你经常去 Amazom.com 吗?你经常沉迷于网上购物吗?”

它将两个问题合二为一,因此参与者选择答案可能会感到困惑,因为许多参与者会使用Amazon.com但很少网上购物,而其他人则经常网上购物,但来自其他网站,如 Snapdeal 等。

参考:

  1. 假人统计
  2. 斯坦福·利古尼塔的统计推理课程。
  3. Udacity Bertelsman 奖学金挑战赛讲座-数据跟踪

估计客户流失风险的方法

原文:https://towardsdatascience.com/methods-to-estimate-customer-churn-risk-ce877c12407f?source=collection_archive---------21-----------------------

图片来源:Shutterstock

介绍

企业总是对研究客户的流失行为感兴趣。了解客户流失可以识别与客户离开潜在相关的因素,但也可以作为一种预测力量来识别处于风险中的客户,并主动吸引他们 防止 客户流失。根据您的领域和用例,有各种方法来模拟客户流失。这篇文章将探索 3 种独特的方法来建立客户流失模型:

  1. RFM 分割
  2. 基于分类器的预测
  3. 基于生存的模型

RFM 分割

最简单的方法是将客户分成不同的部分或“角色”。该方法很简单,因为它只使用了 3 个特征: R 频率、 F 频率和 M 一元值。营销中最常用的这些术语大致定义如下:

最后一个维度旨在确定这些回访的意义或价值如何?如果度量单位是购买,那么货币价值可以简单地是客户的平均购买价格。

你可以使用购买或参与作为行动单位,这取决于你的商业模式是基于顾客再次购买(如电子商务、SaaS B2B)还是顾客再次参与(如 Instagram、twitter)。衡量参与度的货币价值可能需要事先对参与度的类型进行一些权衡(即,上传一张图片可能比简单地登录和滚动浏览提要更有意义)。

下面是尺寸的直观表示,这些尺寸是为您的所有现有客户计算的。

建立排名

下一阶段是奇迹发生的地方。目标是为每个维度存储值。请记住,存储桶越多,组合就越多,因此细分的粒度就越高。

下图反映了一个简单的 1-2-3 级评分。R-F-M 维度中的任何一项得分为“1”为最高等级,得分为“3”为最低等级。

注意:1–2–3 分组的目的是简化分段。您可以修改层的 编号 和不同百分位的层的 大小

解读细分市场

数字编码的 R-F-M 值是一个巧妙的技巧,有助于根据层次开发人物角色:

细分策略—红色文本表示“有风险”的客户细分

请注意,红色文本行通常是您的高风险部分。得分为“3–1–1”的客户是指有一段时间没有购买产品(因此得分为“3”)但经常购买且购买量相当大的客户。该客户可能正处于客户流失的风口浪尖…

限制

  • 低粒度—分数不是单个客户独有的,而是细分市场独有的
  • 需要指定层数(即 1–2–3 或 1–2–3–4 等)
  • 难以添加其他特征(如营销、人口统计等)来为细分市场提供额外的维度。

下一种方法将演示传统的机器学习模型如何在提供粒度级别的同时包括附加功能。

基于分类器的预测

第二种也是更常见的方法是通过训练监督算法(如随机森林、逻辑回归等)来预测客户流失。).这种方法提供了比 RFM 方法更大的粒度,因为每个客户都有一个基于其数据的唯一预测值。

准备数据至关重要

为了训练更好的模型,在拟合之前对数据进行适当的准备是至关重要的。当然,目标变量是二进制的(即,搅动或仍然活动),并且需要在某个时间点对特征进行快照。

例如,您可以获取截至 2020 年 1 月 1 日在该时间点活跃的客户的详细信息。这些细节可以包括人口统计/公司地理,客户任期,与你的产品的参与程度,以及营销属性。您的目标变量是二进制的,标记客户是否在 1 月 1 日到当前日期之间的任何时间结束了交易。

示例数据结构

一旦如上所示准备好数据,模型训练就变得相当简单了。您可以像使用任何分类器一样训练/测试模型。

限制

尽管这种方法为每个客户提供了一个流失风险评分,但与任何方法一样,它也有局限性:

  • 很容易破坏数据集准备用于训练的方式
  • 外部利益相关者可能更难理解
  • 流失事件是而不是随着时间建模/研究的(没有 审查 )

上面的最后一个限制是微妙但重要的。最后一种方法提供了一种解决方案来解释这种审查的概念。

基于生存的模型

基于生存的模型最初是为了研究寿命而开发的,例如人口和国家的寿命。它的用例首先扩展到医疗领域。生存模型允许我们研究尚未观察到事件的人群中的事件发生时间。就像医学专家不会等到所有病人都去世后才研究药物对寿命的影响一样,企业也不应该等到所有客户流失后才能对流失行为进行评估和建模。这种处理未被观察到的数据的概念被称为 审查

建立一些直觉

为了围绕审查的重要性建立一些直觉,让我们假设你想要估计你所有客户的平均流失时间。

红线是搅动的顾客;蓝线是活跃客户

使用上面可视化的数据,

平均流失时间是多少?

方法 1(错误):

忽略所有仍然活跃的客户(蓝线),只忽略那些被搅动的客户的平均任期(红线)。

这种方法夸大了你的平均流失时间,因为你忽略了大多数还没有流失的客户,他们的任期超过 10 天。

方法二(也是错的):

尝试纠正方法 1,取所有客户(蓝色和红色)的持续时间,但对于活跃客户,由于他们尚未流失,您假设他们的流失时间为当前的持续时间。这种方法虽然比方法 1 好,但仍然夸大了平均流失时间。例如,下图假设时间已经过去,你现在站在时间=30。请注意,自从您上次观察以来,又有 3 个用户进行了搅动(虚线),但是您的许多客户仍然没有搅动。

生存模型精确地处理了这种不可观察事件的概念。

生存回归模型

最简单的回归模型是卡普兰-迈耶生存函数。这个模型只需要两个参数;持续时间事件。持续时间只是确定客户活动的总时间(天数、月数等)。该事件是二进制的,并且指示客户是否已经转变或者仍然活跃。持续时间表示客户的当前年龄(如果他们仍然活跃)或他们搅动的年龄。

然而,在大多数情况下,除了持续时间之外,我们还想使用客户的其他特性。生存回归模型可用于回归其他特征(如人口统计、产品使用等)。),就像我们使用基于模型的分类器一样。有各种类型,但一个简单的回归模型是考克斯比例风险模型。

局限性:

  • 对许多数据科学家和分析师来说可能是一个新概念
  • 非技术风险承担者可能难以理解

结论

烤蛋糕的方法不止一种。根据您的需求和资源,不同的客户流失建模方法最适合您的业务。在许多情况下,旨在为领导层提供信息的静态、一次性的流失研究可以通过更简单的自上而下的方法实现,如 RFM 模型。生存模型可以实现更动态、更实时的客户评分,这可以解释审查制度。

对于刚刚开始评估客户流失并需要“MVP”解决方案的组织来说,从简单的 RFM 模型开始,并根据使用您的模型的个人继续构建额外的复杂性和可扩展性。

资源

  • RFM 分割
  • 用 python 实现生存分析

度量很重要

原文:https://towardsdatascience.com/metrics-matter-b282c20d5eab?source=collection_archive---------45-----------------------

分类模型的评估标准

图片作者。

在创建分类模型时,评估模型预测或识别实际结果的能力非常重要。对于监督分类模型,有几个标准的模型评估方法来为模型改进提供信息,它们是:

  • 准确(性)
  • 精确
  • 回忆
  • 特征
  • F1 分数
  • 罗马纪元

下面,我描述了每个评估指标,并提供了一个二进制分类示例,以便于理解。

混淆矩阵

注:此矩阵中包含的数字是针对此示例制作的。它们不是基于实际的大学毕业成绩。图片作者。

创建混淆矩阵始终是模型评估的第一步。混淆矩阵中包含许多指标,有助于理解模型的表现。

真阳性:左上角显示模型做出的正确阳性预测的数量。在本例中,该模型准确预测了 3,253 名学生将在入学后的六年内从大学毕业。

真阳性率: TP/(TP + FN)

假阴性(也称为第二类错误):矩阵的右上角显示了模型做出的错误负面预测的数量。在这个例子中,模型预测这些学生不会在入学后的六年内毕业,但他们确实毕业了。

假阴性率: FN/(FN + TP)

假阳性(也称为 I 型错误):左下角说明了模型做出的假阳性预测的数量。在这种情况下,该模型错误地预测了 674 名学生将在入学后的六年内完成大学学业,而实际上他们并没有在六年内毕业。

假阳性率: FP/(FP+TN)

真阴性:右下角显示模型做出的正确阴性预测。同样,使用这个例子,该模型准确地预测了 296 名学生将不会在入学后的六年内完成大学学业。

真阴性率: TN/(TN + FP)

对于以下每个评估指标,我将继续使用大学毕业作为例子来理解如何评估模型性能。应该注意的是,下面显示的数字和图形是假设的,只是为了便于理解。在下面呈现的每张图片中,我描绘了六年后的大学毕业、大学未完成学业以及模型预测:

  • 实际毕业:下图中的暗红色图标描绘的是六年内实际从大学毕业的人。
  • 未完成学业:下图中的浅粉色图标描绘了在大学入学六年内未完成大学学业的人数。
  • 预测毕业:下图中的毕业帽表示模型预测某个学生将在六年内大学毕业。

准确(性)

在所有正面和负面的预测中,有多少是正确的?

(TP + TN) / (TP + FP + TN + FN)

图片作者。

模型准确性是一个简单的度量标准,它告诉我们对于每个单独的观察,模型做出了多少正确的正面和负面预测。当类别平衡时(即,当每个实现的结果在数据中被同等地表示时),准确性可能是一个有用的度量。然而,当它们不平衡时,预测模型可以通过简单地预测主导类来容易地获得高准确度分数。在上面的例子中,通过预测所有学生不会在六年内从大学毕业,该模型可以达到 80%的准确性。

精确

在所有积极的预测中,有多少是正确的?

TP/(TP + FP)

图片作者。

精度可以作为一种有用的度量,用于了解模型预测正类的能力。然而,精度不能告诉我们有多少积极的结果被错过了。如果模型预测有 700 名学生将在六年内从大学毕业,并且这些预测的学生中有 500 名确实毕业了,则模型将显示大约 70%的精度分数。然而,我们不能从中看出的是,1000 名学生实际上在六年内从大学毕业,而这个模型将这些学生排除在评估之外。为了更好地理解模型识别真实结果的能力,我们来看看下一个指标。

回忆

在所有实际的积极结果中,模型预测有多少是积极的?

TP / (TP + FP)

图片作者。

召回通常也被称为敏感度真阳性率。回忆有助于我们更好地理解模型如何有效地识别积极的结果。precision 告诉我们有多少预测的六年制毕业生实际毕业,recall 告诉我们有多少模型准确预测的毕业生将毕业。例如,如果 1000 名学生毕业,并且模型正确预测其中 450 人将毕业,那么它的回忆分数将为 45%——比精确分数差得多!因此,在评估模型性能时,精确度和召回率似乎都很重要。

特征

在所有实际的负面事件中,模型预测有多少是负面的?

TN / (TN + FP)

图片作者。

特异性,也被称为真阴性率,与回忆相反。回忆告诉我们模型预测积极结果的程度,而特异性告诉我们模型预测消极结果的程度。假设大约有 500 名学生没有真正毕业,而模型预测他们中的 250 人不会毕业。这将返回 50%的特异性分数。在这种情况下,特别是,我们实际上可能会优先考虑特异性优化,因为我们可能更关心正确预测那些不会在六年内从大学毕业的学生,以便我们可以更好地瞄准额外的支持,以确保他们毕业。

f1-分数

精确度和召回率的调和平均值。

2 * [(召回精度)/(召回+精度)]*

一般来说,F1 分数是一个很好的高级指标,因为它包含了精确度和召回率。理想情况下,如果需要精确和召回之间的平衡,可以优化 F1 分数。例如,在预测大学毕业时,我们希望创建一个模型,该模型能够准确地预测积极的结果,并捕捉如上所述的实际积极结果的总体。当班级严重失衡时,F1 分数也是一个很好的衡量标准。在优化 F1 分数的过程中,人们可以期望提高模型捕捉积极结果的能力。与精确度和召回率一样,F1 的分数在接近 1 时是最优的。

ROC(受试者操作特征)/ AUC(曲线下面积)

ROC 曲线显示了真阳性率(回忆/灵敏度)与假阳性率(特异性)的比较。最佳 ROC 曲线是 ROC 曲线下面积(AUC)接近 1 的曲线。这个分数可以解释为 模型对正面预测的排序高于随机负面预测的概率

图片作者。

像 F1 分数一样,AUC 作为性能的单一数字分类器是有用的,并且即使当存在高等级不平衡时也是有用的。AUC 也是比例不变的,这意味着人们不需要缩放他们的数据来评估模型的性能。人们可以将所有特征保持在它们的原始度量中。虽然,如果为了性能而优化,扩展数据是最佳实践。

AUC 也是分类阈值不变的,这意味着 AUC 可以用作性能的有效测量,而不管选择哪个决策阈值。然而,如果理解这个阈值如何影响精确度和召回率对于改进模型是必要的,F1 分数可以作为模型评估的更好的度量。

选择最佳评估指标

当决定如何评估一个模型时,必须考虑他们试图回答的问题,以及他们是否愿意优先考虑他们的模型如何捕捉积极结果或他们的模型如何捕捉消极结果。在上面的例子中,我可能会基于特异性分数优化模型,因为我有兴趣预测谁不太可能在六年内从大学毕业。或者,如果有人试图预测谁可能处于信用卡违约的风险中,他们可能会根据回忆分数或 F1 分数来优化他们的模型,以降低错过正面案例的可能性。在这种情况下,如何评估他们的模型取决于模型的用例。

用简单的英语理解回归模型的高级度量

原文:https://towardsdatascience.com/metrics-to-understand-regression-models-in-plain-english-part-2-12d362dd39d9?source=collection_archive---------30-----------------------

ML 概念解释

数据科学面试官希望对这些指标有直观的理解

马库斯·斯皮斯克在 Unsplash 上的照片

在之前的一篇文章中,我讨论了 MAE、MSE、RMSE、RMSLE 和 R-Squared。这篇文章是关于调整的 R 平方,预测的 R 平方,残差图,变量的 P 值,回归系数,F 统计量。

调整后的 R 平方:

在之前的文章中,R 平方被解释为模型解释的变化量,或者回归模型与均值模型相比有多好。虽然此指标量化了模型的表现,但有一个限制,即它总是随着模型输入参数数量的增加而增加。即使通过添加一堆完全不相关的特征来随机减少误差(回归线的误差平方和),人们也可以通过这种方式不断增加 R 平方,这基本上与统计数据有关。

为了解决这一限制,可以使用调整后的 R 平方度量,其中调整基于自由度。

来源:www.graphpad.com

在 R 平方公式中,如果使用每单位自由度的 SSresiduals 和 SStotal 而不是 SSresiduals & SStotal,则计算调整后的 R 平方度量。如果额外的特征被添加到具有相同的 n 的回归模型中,那么 n-K (K 是要估计的参数的数量)将下降 SSresidual 上升,总体上降低调整后的 R 平方。为了使这个额外的变量在不损害调整后的 R 平方的情况下带来一些值,它应该在一定程度上减少分子中的 SSresidual。分母是均值模型的误差平方和,因此只有 1 个参数需要估计。 n-K 就是这里的 n-1

什么时候用这个?如果要比较两个具有不同参数数量的模型,可使用调整后的 R 平方进行比较。或者,如果您通过添加更多的特性来迭代一个模型,这个度量可以用来查看添加的新特性是否带来了一些价值。

如果你已经知道什么是自由度?请跳过。

简单来说,它可以被认为是一个人拥有的关于数据的额外信息。如果有三个未知数和三个方程,使用线性代数可以计算出这三个未知数是什么。但是,如果三个未知数有三个以上的方程,就不可能找到完全满足所有方程的三个未知数。所以,最佳不完美解决方案的目标是。

为了说明,

解三个方程

如果是这种情况,x,y,z 的值除了在这里得到的值之外,不能取其他值。对于这三个值,没有变化的自由,因此自由度为 0。如果我们引入另一个具有相同数量变量的观测值或方程,我们就引入了变异。现在,x,y,z 有一些自由度,有多少自由度? n-K 单位。需要三个方程来获得 x、y、z 值,但任何超过这个数的数据都是自由度。

预测的 R 平方:

这是一个很好的衡量标准,可以看出你的模型是否过度拟合,或者换句话说,你的模型是否适合新的观察。如果你听说过交叉验证评估技术,你可以看到这个指标与那个方法有多么相似。

最初,残差平方和(PRESS) 需要计算如下

  1. 除了所有可用的数据之外,继续观察,假设总共有 n 行。
  2. 建立一个有 n-1 行的模型
  3. 使用该模型来预测遗漏观察目标变量
  4. 计算观察值和预测值之间的平方差,这就是本例中的误差
  5. 重复上述四个步骤,直到每一个数据点都作为一个测试用例,并获得 n 个错误
  6. 将这 n 个误差相加得到压力

一旦我们得到压力,用它来代替 R 平方公式中回归的误差平方和,得到

预测 R = 1 —(按下/SSEM)

关于 R 平方的更多信息,查看此

残差图:

通常,X 轴为预测值,y 轴为误差或残差的散点图称为残差图(残差中的 X 轴也可以是任何其他自变量)。你观察到的散射看起来应该是随机的,如下图所示

(X 轴和 Y 轴上的值可以标准化,而不是实际值)

如果该图似乎具有定义的形状,如圆锥或曲线,我们可以说模型误差随着输入值的增加而增加。该模型的主要目标是从信号+噪声中捕获信号,并在残差图中显示噪声。噪音应该是嘈杂的。如果它有一个模式,这意味着我们没有完全捕捉信号。

p 值:

我想可以肯定的是,您已经在回归输出中遇到了以下内容。

这里每个系数都有一个与之相关的 P 值。在假设检验中,P 值基本上用于拒绝/不拒绝零假设。但是它在这里做什么?

这通常不会被明确提及,但是假设检验也发生在这里。回归方程中的每个系数对输出/预测都有一定的影响,从无影响到最大影响不等。因此,零假设和替代假设可以表述如下

H0:零假设:系数(x)对产出没有影响

Ha:替代假设:系数(x)对输出有一些影响

如果 p 值小于某个阈值(0.05。0.01.0.1),这意味着我们可以拒绝零假设,并说系数/特征/预测器对输出有一些影响。如果 p 值大于阈值,则特征在统计上不显著,因此对预测没有贡献。(这可能是另一个小帖子,以实际了解这个 p 值是如何计算的)**

回归系数:

当你看到这样的回归方程时

y = a0x0 + a1x1 + a2x2 …(anxn)

回归系数 a0,a1,a2..对预测 y 有不同程度的贡献。当一个预测变量(x0,x1,x2…)发生单位变化,而其余预测变量保持不变时,这些系数中的每一个都代表预测值或预测值的变化。

举个例子,

y(房价)= 150 * x1(平方英尺)+ 1300 * x2(卧室数量)+ 1251 * x3(浴室数量)+ 1214

*在这里,如果你有上面的等式来估计房价,两个相同平方英尺和相同数量的卧室但不同数量的浴室的房子将只有不同的 x3 值,房价的差异将是 1251 *(x3(home 1)-x3(home 2))。如果这个 1251 (预测变量的差是 1,那么它是一个单位变化,1251 将代表预测值或房屋价格的变化。

我已经看过了常用的指标,但还有很多可以讨论的。如果有什么可以为这篇文章增色的,请评论。

另外,我推荐阅读 neptune.ai 的另一篇博文:https://Neptune . ai/blog/performance-metrics-in-machine-learning-complete-guide

显微镜染色差异及其评估方法

原文:https://towardsdatascience.com/microscopy-stain-variations-and-how-to-estimate-them-baca29f57ee9?source=collection_archive---------65-----------------------

对整个载玻片图像进行显微图像处理

马森科的方法是如何工作的

如果你看过一些组织的显微图像(组织病理学图像),你一定注意到它们有各种不同的颜色。即使使用相同的染色化学物质(染色剂),视觉外观也会受到许多因素的影响,如果你用算法处理这些图像,这很容易成为一个大问题。

组织病理学中的默认染色是两种化学物质的组合:苏木精和曙红。第一个负责所有酸成分(例如,存在于细胞核中的 DNA)的暗紫色(或蓝色),而第二个负责给予周围组织结构的粉红色。它看起来像这样:

乳房组织的组织病理学图像。感谢柏林福的 C. Bertram 和 R. Klopfleisch 提供整张幻灯片图片。图片作者。

我已经提到过,不同图像的颜色差异很大。让我们简单地讨论一下这是为什么:

这个游戏中的一个主要角色是由染色化学物质本身扮演的。取决于浓度、染色持续时间甚至温度。为了稳定这些条件,使用了自动染色机。为了展示组织在染色剂中停留时间的影响,请看下图:

犬皮肤肥大细胞肿瘤的组织学图像,用 H&E 染色。左图代表在苏木精中放置 2 分钟的组织,而右图代表在苏木精中放置 12 分钟的组织(感谢 C. Bertram 提供显微镜载玻片,图像来自作者)

两幅图像都代表了完全相同的肿瘤切片,如概览缩略图所示。然而,右边的图像具有更强的蓝色成分(由苏木精溶液中更长的染色时间引起)。

如果我们想要处理这些图像,这些变化通常会造成问题。特别是当我们只有少量案例时,有时很难让我们的识别算法稳健,特别是如果它们具有高模式识别能力,例如通过使用深度网络。

为了减轻这种情况,原则上有两种方法:

  1. 我们可以在将图像送入处理流水线之前对其进行归一化(污点归一化)
  2. 我们可以通过人工增加其输入端的染色可变性(染色增强)来使模式识别系统更加健壮。

对于这两者,能够估计数字显微镜载玻片中两种标准颜色的染色强度并将其修改为代表标准化染色(在标准化的情况下)或代表许多不同的染色是有帮助的。

让我们回顾一下马森科 等人【1】对此的方法。虽然一开始可能有点难以理解,但这是一个非常聪明的方法,真的值得我们关注。

虽然图像通常以红色、绿色和蓝色通道给出,其中较亮的图像代表较高的数字,但污渍本质上是完全相反的:横过 CCD 传感器的光线中的污渍越多,颜色越深。正如你从放射学中可能知道的,光也将遵循比尔-朗伯定律,并随着组织的密度呈指数衰减。马森科等人因此将图像中的每个像素转换为负对数表示(光密度,OD)。

在这一步之后,我们就有了两种染色成分的线性叠加——这对于分离它们来说真是太酷了!此外,更高的数字现在代表更多的污点(因此颜色更深)。

原始图像,红色、绿色和蓝色空间中的像素(中间)和光学密度颜色空间中的像素(右侧)。(图片由作者提供)

在去除太低的值(仅仅是没有组织存在的明亮背景)之后,我们现在可以尝试估计染色成分。

为此,他们首先估计由两个染色向量跨越的 3D 空间中的 2D 平面。他们为此使用的奇异值分解生成了一个新的坐标系,其中第一个分量跨越了主方差(然而,它还不是我们要寻找的染色颜色之一)。每个像素的每个 OD 值都被投影到新的坐标系中。

这一点的美妙之处在于,如果我们通过去除第三个分量来固有地去除噪声(因为我们只使用了前两个特征向量)。为什么允许我们这样做?因为我们知道图像主要只是由苏木精和曙红(H&E)染色的颜色。相当酷。

让我们看一下同样的图像,但为了简单起见,只是在 2D:

所有图像像素的 OD RGB 表示,带有特征向量(奇异值分解的结果)。在右边你会发现同样的数据,但是被投影到特征向量所跨越的平面上。在这里,我们可以确定实际的染色向量。(图片由作者提供)

你可能会注意到,我已经在这张图片中添加了两个染色向量。它们代表我们的特征向量所跨越的坐标系中的最大角度和最小角度。为什么?因为它们本身跨越了自己的坐标系——实际的 H&E 坐标系。

在这张图片中,你可以很好地看到颜色值实际上是这两个分量的线性叠加。我已经告诉过你,我们现在可以通过计算一个稳健的最小和最大角度来非常容易地估计这些(在上图中用红色箭头表示)。你可能会说,如果我们有一些噪声,最小值和最大值很少是鲁棒的。这是一个非常好的观点,也是为什么马森科等人使用分位数(通常是 1%和 99%)的原因。

但是为什么恰恰是最小和最大的角度呢?因为在一个无噪声的世界中,元件的污染不会低于零,这正是这些最大角度之外的区域所代表的。

在下一篇文章中,我们将讨论如何使用 Python 实现这一点——以及如何在大图像上实现这一点,比如我们现在在显微镜中使用的整张幻灯片图像。

[1]:马森科,马克,等(2009)IEEE 生物医学成像国际研讨会:从纳米到宏观。

微软数据科学面试问答!

原文:https://towardsdatascience.com/microsoft-data-science-interview-questions-and-answers-69ccac16bd9b?source=collection_archive---------6-----------------------

微软面试中一些数据科学问题的演练

如果这是你喜欢的那种东西,成为第一批订阅 我的新 YouTube 频道在这里 !虽然还没有任何视频,但我会以视频的形式分享很多像这样的精彩内容。感谢大家的支持:)

背景

我现在对数据科学感兴趣大概有三年了。在我大学的第二年,我的朋友非常支持我进入数据科学的愿望,尽管我有商业背景。

他非常支持我,他给我转发了一份面试问题清单,这是他的朋友被微软要求获得数据科学合作职位时提出的问题。我记得当我最初浏览这些问题时,我觉得我在阅读另一种语言——看起来完全是胡言乱语。

几年后,我觉得自己对数据科学的基础有了更好的理解,所以我决定尝试回答这些问题!总共有 18 个问题,但我将只回答本文中的前 9 个问题——请关注剩下的面试问题!

面试问题

微软数据科学面试的面试问题

注意:我不能 100%保证这些是微软问的。 然而 ,我想即使在他们不在的情况下,这仍然会是一个很好的锻炼!此外,我完全有权利相信我的朋友向我提供了有效的问题。

问:你能解释一下朴素贝叶斯的基本原理吗?你是怎么设定门槛的?

答:朴素贝叶斯是基于贝叶斯定理的分类模型。它最大的假设(也是为什么它被称为“天真”)是,它假设给定类,特性是有条件独立的,但事实通常不是这样。(感谢Alex Murphy的澄清!)

要设置阈值,您可以使用交叉验证来基于多个阈值确定模型的准确性。然而,根据不同的场景,您可能需要考虑假阴性和假阳性。例如,如果您试图对癌症肿瘤进行分类,理想情况下,您会希望确保没有假阴性结果(当有癌症肿瘤时,模型会说没有癌症肿瘤)。

问:你能解释一下 SVM 吗?

答:SVM 代表支持向量机,是一种监督机器学习模型,通常用作非概率二进制分类器[1],但也可以用于回归。专注于最简单的用例,在两个类别之间进行分类,支持向量机找到两个数据类别之间的超平面或边界,使两个类别之间的差距最大化(见下文)。这个超平面然后被用来决定新的数据点是属于一个类别还是另一个类别。

分离两类数据的超平面示例

然而,超平面通常不像上面的图像那样明显和线性。有时,超平面可能难以确定,并且相当非线性。这时,更复杂的主题如核函数、正则化、gamma 和边距开始发挥作用。

你可以在这里了解更多关于支持向量机和内核的信息。

问:如何检测一个观察值是否是异常值?

答:有两种常用方法来确定观察值是否为异常值:

Z 值/标准偏差:如果我们知道一个数据集中 99.7%的数据位于三个标准偏差之内,那么我们可以计算一个标准偏差的大小,将其乘以 3,并确定超出该范围的数据点。同样,我们可以计算给定点的 z 分数,如果它等于+/- 3,那么它就是异常值。
注意:使用该方法时,需要考虑一些意外情况;数据必须呈正态分布,这不适用于小数据集,并且过多异常值的存在会影响 z 值。

四分位距(IQR): IQR,用于构建箱线图的概念,也可用于识别异常值。IQR 等于第三个四分位数和第一个四分位数之差。然后,如果一个点小于 Q1-1.5 * IRQ 或大于 Q3 + 1.5*IQR,则可以确定该点是否为异常值。这达到大约 2.698 个标准偏差。

照片来自迈克尔·加拉尼克

其他方法包括 DBScan 聚类、隔离森林和稳健随机采伐森林。

问:什么是偏差-方差权衡?

答:偏差代表一个模型的精度。具有高偏差的模型往往过于简单,导致拟合不足。方差表示模型对数据和噪声的敏感度。具有高方差的模型导致过度拟合。

照片来自 Seema Singh

因此,偏差-方差权衡是机器学习模型的一个属性,其中较低的方差导致较高的偏差,反之亦然。一般来说,可以找到两者的最佳平衡,使误差最小化。

问:基本的统计问题,如方差、标准差等…

答:方差标准差都衡量一个数据集相对于其均值的分散程度。区别在于标准差是方差的平方根。

如果你想了解更多关于基础统计学的知识,请点击 查看我的统计小抄

问:讨论如何从产品用户群中随机选择一个样本。

答:可以使用一种叫做简单随机抽样的技术。简单随机抽样是一种无偏的技术,它从一个较大的数据集中随机抽取个体的子集,每个个体被选中的概率相等。这通常是在没有替换的情况下完成的。

有了熊猫,可以用。sample() 进行简单的随机抽样。

问:描述一下渐变增强的工作原理。

答:梯度提升是一种集成方法,类似于 AdaBoost,本质上是通过在损失函数中使用梯度来迭代构建和改进先前构建的树。最终模型的预测是所有先前模型预测的加权和。它如何一个接一个地改进自己的模型有点复杂,所以我在下面提供了一些链接。

了解渐变升压机渐变升压解释

问:什么是 L1 和 L2 规范?两者有什么区别?

答:L1 和 L2 范数是两种不同的正则化技术。正则化是添加附加信息以防止过度拟合的过程。

实现 L1 范数的回归模型称为套索回归,实现 L2 范数的模型称为岭回归。两者的区别在于岭回归采用权重的平方作为损失函数的惩罚项,而 Lasso 回归采用权重的绝对值。

更多关于差异的细节可以在这里阅读*
阅读更多关于 L1 和 L2 的规范* 这里

问:什么是中心极限定理(CLT)?如何确定分布是否正态?

答:统计如何提供 CLT 的最佳定义,它是:

“中心极限定理表明,无论总体分布的形状如何,随着样本量的增加,样本均值的抽样分布都接近正态分布。”[2]

中心极限定理的直观解释

有三种一般的方法来确定一个分布是否正态。第一种方法是用直方图直观地检查。更准确的检查方法是计算分布的偏斜度。第三种方法是进行正式测试来检查正态性——一些常见的测试包括 Kolmogorov-Smirnov 测试(K-S)和 Shapiro-维尔克(S-W)测试。本质上,这些测试将一组数据与样本的均值和标准差相同的正态分布进行比较。

问:可以用什么算法来总结 twitter feed?

答:对于这个问题,我不确定答案,所以我联系了我的朋友 Richie,他是加拿大贝尔公司的数据科学家!

总结课文有几种方法,但首先,理解问题很重要。“摘要”可以指情感或内容,并且摘要的级别和复杂程度可以不同。我会亲自和面试官澄清他们到底在寻找什么,但这并不意味着你不能做出假设(这是他们无论如何都想看到的)。

假设面试官正在寻找一些最有趣的代表性推文,例如,你可以使用 TF-IDF(term-frequency-inverse document frequency)。

例如,每个人都在谈论伊朗和美国之间的现状,所以你可以想象像“战争”、“导弹”、“特朗普”等词。频繁出现。TF-IDF 旨在给予那些更频繁出现的词更多的权重(即重要性),并减少推文中诸如“the”、“a”、“is”等词的影响。

感谢阅读!

如果你喜欢我的工作,想支持我…

  1. 支持我的最好方式就是在媒体T21【这里上关注我。
  2. 成为第一批在TwitterT2 上关注我的人之一。我会在这里发布很多更新和有趣的东西!**
  3. 此外,成为第一批订阅我的新 YouTube 频道 这里!
  4. LinkedIn 上关注我这里。
  5. 在我的邮箱列表 这里报名。
  6. 看看我的网站,terenceshin.com

更多相关文章

* [## 更多微软数据科学面试问题和答案

微软面试中一些数据科学问题的另一个演练

towardsdatascience.com](/more-microsoft-data-science-interview-questions-and-answers-f9ee8337072c) [## 谷歌的数据科学面试脑筋急转弯

作为谷歌数据科学面试的一部分,他们喜欢问一些他们称为“解决问题”的问题…

towardsdatascience.com](/googles-data-science-interview-brain-teasers-7f3c1dc4ea7f) [## 数据科学家的 5 个常见 SQL 面试问题

帮助您发展 SQL 技能,在任何面试中胜出

towardsdatascience.com](/5-common-sql-interview-problems-for-data-scientists-1bfa02d8bae6) [## 数据科学家的 40 个统计面试问题和答案

为你的面试复习统计知识的资源!

towardsdatascience.com](/40-statistics-interview-problems-and-answers-for-data-scientists-6971a02b7eee) [## 亚马逊的数据科学家面试实践问题

一些亚马逊面试问题的演练!

towardsdatascience.com](/amazon-data-scientist-interview-practice-problems-15b9b86e86c6)

参考

[1] 支持向量机,维基百科

[2] 中心极限定理,定义及例题步骤简单,*统计如何**

大数据时代的微软 Excel

原文:https://towardsdatascience.com/microsoft-excel-in-the-era-of-big-data-401e67ca28a5?source=collection_archive---------3-----------------------

我们在学校从没学过这个…

图片:微软图标/卷须/行为

这是一个我们都已经知道并在日常生活中使用的工具。为了构建报告、创建图表甚至安排项目,我们使用 Microsoft Excel 做任何事情。

但我们从未真正学会使用它。虽然对大多数人来说这不是一个主要问题,但这开始给那些必须处理复杂管道和系统的数据处理人员带来问题。

如果我们了解如何构建高效且一致的电子表格会怎么样?不仅仅是为了更接近这种工程材料,通过更高效、一致性和再现性的设计来加强这些文件对我们的日常工作也有很多好处。

微软 Excel 及常见误用

当 Redmond 公司在 1985 年发布 Microsoft Excel 时,它已经取得了成功。新的个人电脑市场相当开放,随着 Windows 3.0 的推出,Excel 的销量超过了 IBM 的主要竞争对手 Lotus 1–2–3。

从那时起,超过 85%的个人电脑市场安装了 Windows。因此,Excel 和所有的办公套件是最常用的软件。

这一成功并不令人惊讶:微软 Excel 易于使用,汇集了许多功能,并有一个简单的用户界面。每个人都可以使用它,它随处可见。我们还想要什么?

其实做一个几乎所有人都能用的产品,带来的是一些同行。

Excel 不是在学校学的。每个人都可以使用它,因此每个人都可以用不同的方式使用 Excel。没有明确定义的共识或良好做法。事实上,我们从小学开始就没有意识到这种工具,这导致我们在进入职业世界时缺乏知识。

Excel 不可自动化。尽管 Excel 中嵌入了一种可编程语言——Visual Basic,但要实现繁重任务的自动化并与其他软件进行通信仍然很困难。而且,它还是留给内部人士的。

Excel 不可扩展。我们处于大数据时代,因此处理无法在 Excel 中加载的大型文件是很常见的。一切都取决于你的计算能力。在专用服务器上运行微软软件似乎也很困难。同样,它不是为这种用途设计的。

Excel 不可复制。最后但同样重要的是。当你收到一个 Excel 文件,里面有很多汇总数据、颜色、缩写或公式,很难理解所有这些东西是如何设置和收集的。Excel 不会保存构建此类文件所涉及的任何工作流状态。

房子里的数据团队

在过去的二十年里,这四点并不是大问题。

但与此同时,一个“新”领域开始腾飞。随着计算机资源的发展,公司发现他们现在拥有大量数据,但不知道如何处理这些数据。

一整套新的职位被创造出来:数据科学家、数据分析师、数据工程师、机器学习工程师、数据开发人员等等。关键词是数据,这些新职位的主要目标是从这些大量的数据中创造价值。

有了这些新奇的东西,一大群工具被创造出来,用来构建数据管道,更好地可视化数据,或者创建允许预测未来值的数学模型。

但是大部分数据仍然保存在 Excel 文件中。此外,开发的工具有时使用起来很复杂,只有训练有素的工程师才能操作它们。

因此,这里仍然存在一种差距。一方面,有很多人仍然使用电子表格作为他们的主要工具之一,另一方面,工程师们必须处理复杂的管道,而且还要处理这些杂乱的文件。

因此,在清理这些文件,然后将它们集成到整个数据管道的过程中,会浪费大量的时间和金钱。数据团队由学习数学、计算机科学等的优秀人才组成…

在实践中,工程师也不学习 Excel,他们只知道计算机和他们的数据管道,所以他们可以与它讨价还价。然而,与他们在这段时间内可以做的事情相比,这并没有增加价值。

如果让工程师去处理这些杂乱的文件,我们试着从头开始学习如何创建和维护干净的文件,会怎么样?通过遵循简单的规则,我们可以构建高效、可复制和自动化的文件,并停止创建令人困惑的电子表格。

简洁地清理电子表格

下面是一个常见电子表格的示例:

常见的电子表格。

虽然它看起来设计得很好,但从可复制的角度来看,它并不可复制。

从这个简单的例子中,我们将描述构建一个计算机容易理解的文件的最佳实践。

第一行不对应特定字段。此处应替换为“年份”、“类型”、“产品”、“数量”。这就是所谓的“标题”。

用颜色和字体形状格式化单元格。虽然添加颜色和粗体/斜体文本对眼睛来说很方便,但对电脑来说没什么用。此外,这些排列不是目标,对文件的理解可能因用户而异。

将不同性质的数据放在同一行。和上面一样,这看起来很方便,但实际上,每一行必须只包含一次观察的信息。同样,聚合总体值(如 total 或 average)与其他值位于同一行通常不是一个好主意。这是不一致的,也是计算机无法理解的。

合并单元格。同样的事情:每一行必须只包含一个数据观察的信息。

在相同的工作表或标签中分隔表格。在不同的标签中区分年份是一种常见的做法,以使表格更容易阅读,但它不会被只读取一张表格的计算机读取。

这些是简单的规则,不是吗?以下是应用这些准则后的结果。

整洁的电子表格。

两全其美

如果你不在技术领域工作,你可能会说这不是一个非常有用的电子表格。你说对了一部分。通过这种设计,我们不能处理像 sums 或 average 这样的聚合值,而且查找特定值也不太方便。

尽管如此,还是有办法处理这样的文件,甚至改进以前的设计。

保持一张表格,数据整洁。首先,始终保留一张表格,其中的数据按照我们上面演示的方式进行格式化。这样,数据科学家或任何使用特定软件的人将能够加载文件,而无需事后处理。

在另一个表或应用程序中处理和聚集数据。要计算总和、添加过滤器、创建图表或任何其他数据处理,只需打开另一个工作表,做任何您想做的事情。把这个空间看做一个实验室,在这里你可以用数据做实验并建立你的报告。这样,您可以保护原始数据。

此外,你可能想使用或学习其他工具。如今,有许多用户友好的工具来创建仪表板或报告。它们提供了很好的设计选项,并包含了许多构建和导出报告的功能。

如果你想更进一步,你可以使用这些数据人员每天使用的工具。这些大多是像 Python 或 R 这样的可编程语言,它们带来了更多的自由和可再现性。因为它实际上是代码,所以创建图表和报告的整个工作流程都被保存了。因此,你可以共享代码,任何人都可以编辑它以适应他的需要。

虽然它比 Excel 更复杂,但高度的自由度允许你构建任何你想要的东西。最后但同样重要的是:它是免费的。

这只是一点小小的适应

改进这些文件的设计有两个主要优势:

首先,你要帮助技术人员。不仅仅是利他主义,它还可以加快工程师建立数据管道的速度,从而增加洞察力的数量,为公司带来更多价值。

此外,通过在团队甚至公司范围内应用这些规则,我们最终可以用一种更加统一的“语言”来处理这些文件,从而更好地理解和操作整个公司的数据。

现在是 2020 年,我们都在人工智能、大数据、机器学习等方面听到这些流行词汇,但并不真正知道这是什么。事实上,它从数据开始,在每个人手里和他们的电脑里。

微软恶意软件检测(R 级)

原文:https://towardsdatascience.com/microsoft-malware-detections-r-classification-46bf5355f930?source=collection_archive---------53-----------------------

检查导致计算机被感染的因素,并比较三种不同的预测模型:带逻辑回归的 LASSO 正则化、随机森林和梯度推进决策树(GBDT)。

由 KOBU Agency 在 Unsplash 上开发的一款游戏

团队成员 : Lukas Tuong ,叶晨,王佳义,景岩乔

一/导言

随着信息产业和相关技术的发展,计算机和其他机器在任何行业的生产中变得越来越重要,保持机器处于安全状态并且不被任何类型的恶意软件感染是安全部门面临的最大挑战。恶意软件行业仍然是一个组织良好、资金充足的市场,致力于规避传统的安全措施。一旦计算机被恶意软件感染,犯罪分子会以多种方式伤害消费者和企业。为了保护企业和消费者客户的计算机,预先降低个人数据泄露的风险,微软非常重视这个问题,并调查了机器被感染的因素,以改进他们的安全系统。从微软收集的数据集包含每台机器的各种属性和每台机器的实际感染状态,由微软的端点保护解决方案 Windows Defender 生成,该解决方案旨在满足某些业务约束,既涉及用户隐私,也涉及机器运行的时间段。

逻辑回归模型是一种经典的机器学习模型分类,当因变量是二分的(二元)时,它是一种合适的回归分析。与所有回归分析一样,逻辑回归是一种预测性分析,用于描述数据并解释一个因变量和一个或多个自变量之间的关系。给定数据集中的因变量(响应)是机器上是否检测到恶意软件,因此逻辑回归模型是此分析中的基本模型。在追求高维数据集预测的更高精度时,偏差和方差之间的权衡无时不在。给定的数据集包含 83 列和 50k 多行。正则化回归是一种在高维数据集上拟合回归模型时避免过度拟合风险并减少模型方差而不显著增加偏差的方法。最小绝对收缩和选择算子(LASSO)正则化方法适用于具有多个高度相关预测因子的模型,以去除冗余特征,以便于模型解释做出决策。

决策树是一种通过基于特征分割数据来对观察结果进行分类的模型,但当研究人员面临各种类型的特征或大量数据时,它具有弱点,尤其是在大数据中。决策树的复杂性严重降低了预测模型的效率和准确性。随机森林是分类分析中的一种机器学习方法,它由大量单独的决策树组成,作为一个整体发挥作用。研究人员从每棵树上收获分类预测,并基于多数投票方法决定哪个是最重要的分类。为了优化预测,研究人员通常使用自举方法。另一种非常适合基于决策树的分类领域的机器学习算法方法是梯度推进决策树(GBDT)模型。它是使用增强技术的模型的集成,本质上是将弱分类器组合起来形成一个更强的分类器。具体地,在这种情况下,弱分类器是不同的决策树,因此 GBDT 模型的结果可以被认为是这些决策树的组合。提升过程是连续的,它将随后的树连接到在过去产生的预测中有误差的先前的树,以便在组合过程中逐渐减小预测误差。此外,GBDT 模型不会将单棵树的结果作为最终结果。因此,它也可以用来解决过拟合问题。

这项研究的目标是预测机器被恶意软件感染的概率,并确定影响感染的最重要因素,以便微软开发人员采取措施,在未来改进他们的系统。此外,这也是一个更好地了解各种分类方法的理论和性能的机会,如简单逻辑回归、带 Lasso 正则化的逻辑回归模型、随机森林和梯度推进决策树方法,并进一步探索大量预测因子和分类响应变量之间的关系,并进一步根据研究结果进行预测。

II/数据和方法:

数据描述:

数据是从位于 Kaggle 的微软竞赛中检索的,并执行了数据清理流程。原始数据集包含 8,921,483 个观察值,具有机器的 82 个不同特征和一个响应变量,即机器是否被恶意软件感染(有感染:编码为 1,无感染:编码为 0)。在调查缺失值的频率和每个要素的维度分布后,缺失值水平较高(缺失值的百分比超过 75%)或维度高度不平衡的要素将被删除。例如,没有一台机器看起来有 Beta 软件,因此功能 is Beta(Beta 软件是否出现在每台机器上)被删除,在此分析中研究了 50 个变量。

本研究中假定的重要特征是:

引擎版本: 引擎的版本。

AvSigVersion:反病毒特征码数据库的版本。**

*****avproductstateigner:*机器上使用的杀毒软件的状态。

Wdft _ IsGamer:该机是否为游戏机。**

城市标识符: 机器所在的地方。

国家标识符: 机器所在的国家。

OS ver:当前操作系统的版本。**

OS platform:操作系统所使用的平台。**

被保护: 机器上是否有杀毒产品。

防火墙 :是否在机器上建立了防火墙。

HasTpm:机器是否有可信平台模块。**

智能屏幕: 智能屏幕在机器上启用。

Census _ SystemVolumeTotalCapacity:机器上安装的系统卷的大小。**

Census _ OsBuildRevision:机器上最新版本的操作系统。**

平台 :安装在机器上的平台。

Census _ TotalPhysicalRAM:随机存取存储器的数量。**

Census _ HasOpticalDiskDrive:机器是否有光驱。**

Census _ o edition:当前操作系统的版本。**

Census _ IsTouchEnabled:机器是否为触控设备。**

方法:

逻辑回归模型。

a.总结逻辑模型,并根据 95%置信区间的 P 值选择具有显著贡献的预测因子。

b.画出因变量的预测概率。

LASSO 正则化方法:Logistic 回归模型。

a.用所有选定的预测值绘制交叉验证曲线。

b.确定最小化平均交叉验证误差的λ值和最小均方误差的一个标准误差内的λ值,以使用 lasso 正则化方法识别最佳逻辑回归模型。

随机森林模型。

a.将目标特征编码为因子。

b.将数据集分成 6 个树组,并将每个组分成训练集和测试集。

c.将随机森林分类适合 6 棵树的训练集。x 是因变量,y 是结果,ntree 表示要生长的树的数量,结果为 500 棵树。

d.以二进制格式显示预测结果,生成矩阵并比较 6 组不同的数据,以确定最佳决策树。

梯度推进决策树(GBDT)模型。

a.标签编码:标签编码将值转换为 0 到 n-1 之间的数字,其中 n 是不同标签的数量。

b.频率编码:频率编码是标签编码的特例。基于频率对特征值进行编码。转换后的值是介于 0 和 m 之间的数字,其中 m 是频率大于或等于 2 的值的数量。

III/分析和讨论:

Logistic 回归分析:

预测公式可通过对多个预测值进行逻辑回归,在 95%的置信区间内构建,如下所示:

****(has detections)的预测 logit = 0.7084 * platform windows 8+0.9071 * SkuEditionEduation+0.9809 * SkuEditionEnterprise+1.366 * SkuEditionHome+2.108 * SkuEditionInvalid+0.933 * SkuEditionPro+0.3086 * is protected+0.1395 * Wdft _ is gamer+0.7202 * app version。(1)

根据等式 1,机器感染几率的对数与 9 个特征相关(p 值< 0.05). All features have a coefficient greater than 0, which suggests that these features enhance the probability of the machine getting infected. The feature IsProtected (whether each machine has any active anti-virus products) and Wdft_IsGamer (whether the user of each machine is a gamer) have the lowest p value, therefore these two features are most critical factors increasing the probability of the machine having infections.

The goodness-of-fit statistics assess the fit of a logistic model against actual outcomes (i.e., whether a machine has infections). Adjusted R-squared value is 0.028, suggesting around 2.8% of the observations can be explained by the model. The large AIC value (80695) and Residuals (59748) also show the inefficacy of the model.

Table 1: Confusion Matrix (Logistic Regression Model) (图片作者

*1:被恶意软件感染的机器。

*0:未被恶意软件感染的机器。

采用混淆矩阵来评估逻辑回归模型的性能。表 1 表明,大约一半未被感染的机器被预测为未被感染,大约三分之二被感染的机器被逻辑回归模型正确分类。预测的总体成功率为 58.07%。第一类错误(未受感染的机器被错误预测)相对高于第二类错误(受感染的机器被错误分类为未受感染),这在某些方面捍卫了该模型,因为将受感染的机器分类为未受感染比反之风险更大。

图 1:结果变量的预测概率,HasDetections ( 作者图片)

概率预测图显示了每台机器被恶意软件感染的预测概率以及实际的恶意软件检测状态。Y 轴是检测到的概率,X 轴是从 60,000 台机器的最低值到最高值的感染概率。曲线在概率 0.5 附近比较平坦,说明模型的预测效率不高,与上面的小 R 平方值一致。

使用 LASSO 正则化方法的逻辑回归分析:

图 2:均方误差与(λ)的对数的关系。(图片作者)

根据图 3,均方误差的值随着λ值的增加而增加,并且第一虚线为正则化方法选择了两个λ值。较小的λ导致最小的均方误差,并且λ在一个标准偏差内,这导致具有最少特征的模型。应用 lambda 为 0.00265 的套索正则化过程来移除多余的变量。通过将 Lasso 正则化方法应用于逻辑回归模型来调整预测公式,如下所示:

(HasDetections)的预测 logit = 0.1017 * platform windows 8+0.0843 * is protected+0.0169 * Wdft _ is gamer

从等式 1 到等式 2,几个特征被缩减为零。人们注意到,在 Lasso 正则化之后,只有三个特征显示出重要性:platform Windows 8(Windows 8 平台)、IsProtected(每台机器上是否有任何反病毒产品)和 Wdft_IsGamer(每台机器的用户是否是游戏玩家)。所有这三个特征以正系数增加了机器被恶意软件感染的风险。

表 2:混淆矩阵(采用 Lasso 正则化方法的 Logistic 回归模型)。(图片作者)

在执行套索正则化方法后,与表 1 所示的简单逻辑回归模型的结果相比,准确率提高了约 0.1%。然而,产生的最大 R 平方值约为 0.039,这表明该模型无效。

随机森林模型:

图 3:混淆矩阵(随机森林模型)。(图片作者)

在随机森林中,数据集被分成 6 棵树,每棵树的输入数量略有不同(500-1000 行),以测试输入的大小是否会实际影响预测率。从图 3 中可以看出,行数最少(4883 个输入)的树 1 的成功率最高,为 57.04%。观察的数量越多,树 6 (6265 个输入)的成功率越低,树 6 只能成功预测 55.91%的测试集。因此,在所有树中,I 类错误(错误地将机器分类为受感染的机器,而实际上它不是)的数量大于 II 类错误(错误地将受感染的机器分类)的数量,这降低了错误预测的严重性。

图 4 表示测试集中的实际检测状态,上面的表示预测结果。置信水平被设置为较低的 0.45 和 0.475,并且还被设置为 0.55,以便比较成功率的结果。使用树 1 作为优化的基础,成功率随着故障区域置信水平的变化而波动。尽管如此,优化成功率最高的仍然是原始树 1,成功率为 57.04%。任何高于或低于 0.5 的置信度都会降低随机森林预测模型的成功率。因此,置信水平通常分布在 0 和 1 之间,平均值为 0.5。然而,类型 II 误差从原始树 1 (15.83%)减少到阈值为 0.55 的树 1 的优化 3(10.84%)。因此,置信度为 0.55 的优化案例 3 将被视为成功率降低 0.3%的更有用的决策树。

梯度推进决策树(GBDT)模型:

数据集被随机分为训练集(70%)和测试集(30%),每个集包含大约相等数量的受感染机器和未受感染机器。训练集用于建立模型,以便可以预测测试机器被感染的概率(1 =有感染,0 =没有感染)。大于 50%的概率意味着机器预计会被感染,而低于 50%的概率不会被感染。

表 3:混淆矩阵(有 60,000 个观察值的 GBDT 模型)。(图片作者)

表 4:GBDT 模型的精度、召回率和 F1 值(有 60000 个观察值)。(图片作者)

根据表 3,8841 台未被感染的机器中有 4555 台被正确分类,8965 台被感染的机器中有 3609 台被正确分类,预测准确率为 55.66%。精确度和召回率衡量预测模型的性能,比例越高表示性能越好,准确率越高。理论上,模型的修改旨在提高查准率和查全率,但提高查准率总是导致查全率降低,反之亦然。因此,精确度和召回率的结合,F1 分数,被用来更好地评估模型。从表 4 中可以看出,在每组受感染或未受感染的机器中,F1 分数都小于 60%,这表明该模型很难解释这些观察结果。表 5:混淆矩阵(有 100,000 个观察值的 GBDT 模型)。

表 5:混淆矩阵(有 100,000 个观察值的 GBDT 模型)。(图片作者)

表 6:GBDT 模型的精度、召回率和 F1 值(有 10 万个观察值)。(图片作者)

在具有 100,000 个观察值的较大数据集上采用了 GBDT 模型,准确率提高了约 2.68%,如表 5 所示。此外,对于感染和未感染的病例,F1 得分都高于 55%,这证实了具有更大量数据的模型的更好的功效。

图 5:特征的重要性显示出显著的贡献(有 60,000 个观察值)。(图片作者)

图 6:显示显著贡献的特性的重要性(有 100,000 个观察值)。(图片作者)

梯度推进决策树(GBDT)模型生成在模型拟合过程中使用的每个特征的频率,并且具有较高频率的特征被认为具有较高的重要性。绘制了两个 GBDT 模型的条形图,以直观显示这些功能对机器被感染的可能性的影响。图 5 中最重要的前三个特性是 CountryIdentifier(每台机器所在的国家),LocaleEnglishNameIdentifier(微软定义的机器语言代码,即英语= 1033。)和 GeoNameIdentifier(机器所在的地理区域),它们都与机器的位置相关。Census _ SystemVolumeTotalCapacity(安装在机器上的系统卷的大小)、CountryIdentifier(每台机器所在的国家)和 Census_OsBuildRevision(机器上操作系统的最新版本,即 Windows 10 =1909 的最新版本)似乎是贡献较高的前三个功能。随着观察数量的不同,每个特性的重要性从图 5 到图 6 都发生了变化。然而,没有足够的证据表明图 6 中的前三个特征能够以相对较低的成功率给出精确的预测。

四、结论和建议:

从上面讨论的结果可以得出结论,Lasso 逻辑回归模型是该数据集的最佳预测模型,具有最高的 58.18%的成功率,而被认为是分类机器学习的最佳模型之一的随机森林在优化之前和之后在所有三个模型中具有最低的成功率。此外,梯度推进决策树(GBDT)模型不是以较小的准确率(57.34%)预测每台机器被感染的概率的合适方法。发现 r 编程语言在处理包含超过 1000 个唯一值的变量时性能有限。此外,在 Python 中对具有更多高维特征的 GBDT 模型进行了相同的处理,从而获得了 62.02%的更高准确率。

提取过程中的错误概率。由于计算机和 R 编程语言的限制,本研究中使用的观察值仅占整个数据集的 6.7%左右,这使得结果很难代表整个数据集。选择了更大的样本来优化 GBDT 模型,它确实将准确率提高了 2.68%,这证实了样本大小的重要性。尽管我们随机抽取了等量受感染和未受感染机器的数据集,但仍可能有其他因素可以解释最终结果,例如,这些机器的某些属性可能会按特定顺序记录。

缺乏透明性、保密性和不可解释的特征。在 83 个原始列中,只有大约一半被选择用于此分析。这是由于许多特征没有被清楚地详细解释、编码,甚至对于所有的观察都是缺失的。其中一个例子是地理特征。所有国家都以保密的方式进行编码,因此无法研究每个国家的机器被恶意软件感染的概率。这些地理要素被排除在随机森林预测之外,因为它们的每个变量都有 200 多个唯一值,而 Random Forest 函数只能分配 53 个。

为了进行进一步的研究,研究人员应该在具有大量内存的计算机上使用 Python 执行这些模型,以利用整个数据集,并专注于在该分析中显得重要的特征。这可以是研究位于相同位置或固定的具有大量类别的其他特征之一的那些机器以获得更精确的预测结果的替代方式,并且可以选择不同的观察组来验证机器的每个属性的显著性。

****Github:https://Github . com/lukastuong 123/R-Projects/tree/master/Project-% 20 微软% 20 恶意软件% 20 预测

****参考文献:

1.布朗施泰因,A.** (2019)。在 Python 中训练/测试分割和交叉验证。检索自https://towardsdatascience . com/train-test-split-and-cross-validation-in-python-80 b 61 beca 4 b 6**

2.在 R. (** 未注明)中计算分类评价指标。检索自https://blog . revolution analytics . com/2016/03/com _ class _ eval _ metrics _ r . html**

3.微软恶意软件预测。(未标明)。从 https://www.kaggle.com/c/microsoft-malware-prediction/data取回

4.微软恶意软件预测。(未标明)。检索自https://www . ka ggle . com/c/Microsoft-malware-prediction/discussion/84065

5.Openspecs-Office。(未注明)。[MS-OE 376]:LCID 7.6.2.39 的第 4 部分(区域 ID)。检索自https://docs . Microsoft . com/en-us/open specs/office _ standards/ms-OE 376/6c 085406-a698-4e 12-9d4d-C3 b 0 ee 3d BC 4a

6.人。** (2019)。Rstudio,它可用于大型数据集(9gb)吗?检索自https://community . r studio . com/t/r studio-is-it-useable-for-large-dataset-9gb/21138/7**

7.尤尔托奥卢,N.** (2018)。http://www . History Studies . net/dergi//比林西-雅顿-萨瓦辛达-比尔-阿萨伊斯-索鲁努-塞宾卡拉希萨尔-埃尔梅尼-伊斯亚尼 20181092a4a8f.pdf. 历史研究国际历史杂志,10(7),241–264。doi:10.9737/历史 2018.658**

微软的“人工智能为地球”:人工智能如何帮助保护物种

原文:https://towardsdatascience.com/microsofts-ai-for-earth-how-ai-helps-protect-species-3c8191f2b83d?source=collection_archive---------39-----------------------

利用人工智能的潜力确保物种保护。微软的“AI for Earth”资助计划致力于这一目标,并支持阿拉斯加濒危物种保护的研究团队。

在她的职业生涯之初,作为一名动物学家,艾琳·莫兰对她的日常生活有着不同的看法。动物学家通常坐在她的电脑前,而不是坐在阿拉斯加的海岸上,收集各种海洋生物的数据,以便研究它们的栖息地,并在未来能够更好地保护它们。数以千计的航空照片必须进行分析和评估。在她不断寻找濒危物种的过程中,对信息的评估通常需要很长时间,甚至在研究工作期间,这些信息也经常过时。需要一种更有效的解决方案。

评估:几小时而不是几个月

她与美国国家海洋和大气管理局(NOAA)的同事一起,提出了利用人工智能监控灰海豹数量的想法。研究小组首先为他们的飞机配备了更强大的相机,以拍摄高分辨率的航空照片。根据拍摄的照片,该团队开发了能够详细识别动物的算法,例如,从环境中区分海豹。这项技术现在使研究小组能够在几小时内记录海豹数量,而不是几个月。

聚焦本质:物种保护策略

对于微软的“AI for Earth”来说,研究小组的任务也是新的,因为尽管有许多模型可以识别图像中的人,但当时还没有技术可以识别海豹、熊或鲸鱼的图像。随着时间的推移,NOAA 和微软之间的图像和相关数据量增加了。合作之初,定期交换硬盘。如今,Azure 云连接显著改善了数据交换。此外,现在有一个扩展的机器学习培训,因此 NOAA 现在能够评估海豹种群的实时数据。

对于 Moreland 和她的团队来说,使用人工智能意味着一件高于一切的事情:时间。是时候制定保护策略并重新关注实际的研究工作了。

白鲸:人工智能探测到声音信号

当 Moreland 和她的研究小组在阿拉斯加沿海地区进行研究时,西雅图大学大气和海洋联合研究所(JISAO)的科学家 Manuel Castellote 正在研究阿拉斯加湾的白鲸。

由于航拍海洋动物几乎从未成功过,Castellote 专注于声学方法来建立鲸鱼的运动模式。一大优势:白鲸通过声音信号相互交流。为此,他们使用了广泛的曲目:从嗡嗡声到吱吱声,再到非常高的啁啾声,频率范围非常广,从 0.7 到 20 千赫。

为了能够识别鲸鱼信号,开发了一套算法,其命中率应该达到 99%,从而大大超过人工评估。

人的因素

卡斯特洛特还打算利用这项技术来调查“人类噪音”对鲸鱼行为的影响程度。“人类的噪音可以掩盖鲸鱼用来寻找食物和彼此交流的关键信号。如果这些动物不能进食、交配或繁殖,数量就不会增加,”卡斯特洛在微软的博客中说。“所以我们认为噪音是一个大问题,这也是我们关注的焦点。”

“人工智能拯救地球”项目目前在 71 个国家支持 435 个项目。

微软在硬件领域日益增长的主导地位

原文:https://towardsdatascience.com/microsofts-bright-future-8c75f2e4dd38?source=collection_archive---------20-----------------------

Surface Book 3 代表了微软的光明未来

免责声明 1:我拥有微软和苹果的一些股份。还有,这不是理财建议。

免责声明 2:苹果公司在年度报告中将所有 Mac 销售归为一类,标为 Mac。包括台式机销售。在这个分析中,我假设 Mac 是笔记本电脑销售的主要代表——谁会拥有苹果台式机呢?

2017 年 12 月,我冒险从使用苹果的 Macbook Pro 跳槽到微软的 Surface Book 2。从那时起,我就没有回头。与 Macbook Pro 相比,Surface Book 2 的创新性让我惊喜不已。在功能方面,微软超越了自己:它可以兼做一个巨大的 15 英寸平板电脑。它有一个强大的 NVIDIA 显卡,用于游戏和图形/视频编辑。它还集成了触摸屏,因此您可以轻松地与数字笔配对。在与苹果的竞争中,微软发现了一个强大的利基市场,开始开拓市场份额:功能价值。我认为这个广告将会为微软赢得很多未来的客户。Surface Book 3 是突出该公司成功的一个很好的例子。

Surface Book 3 的隆重发布

我最欣赏微软 Surface Book 3 发布的部分是,他们将 Surface Book 2 用户记在了心里。其中一个原因可能是因为微软对 Surface 的策略是增长,而苹果的策略更侧重于保留。这个假设是基于我对苹果和微软笔记本电脑收入和市场份额的分析。

2019 年,苹果净营收约为 2610 亿美元。其中,近 260 亿美元来自 Mac 产品的销售(这包括台式机——但我们不要拿苹果的台式机成功开玩笑)。这大约是他们收入的 10%。相比之下,微软 2019 年的总收入为 1260 亿美元,而 Surface 系列占其中的近 60 亿美元(这也包括微软的 Surface Studio,这是一款桌面产品——可能不是收入的很大一部分),或约为 5%。

我使用微软和苹果的 2019 年笔记本电脑收入数字创建的简化市场规模图表。

从市场规模的角度来看(假设笔记本电脑市场只有微软和苹果),苹果占 81.4%,而微软占 18.6%——基于 2019 年的笔记本电脑收入。作为市场份额的少数股东,微软有更多的机会通过专注于高端笔记本电脑购买者来增加其份额,并将其转化为 Surface 买家。另一方面,苹果将经历更慢的增长(基于百分比),因为它已经是成熟市场的市场领导者。这不仅体现在收入上,还体现在复合年增长率或 CAGR 上。

5 年 CAGR 比较:微软与苹果。我设计的。数据来源:各公司的年度报告。

微软 Surface 系列的收入增长令人印象深刻。五年来,微软的 Surface 销量 CAGR 增长了 41.2%,而苹果的 Mac 销量增长了 3.2%。很容易对比,可以看出微软的增长率要好得多。但是要避免这种诱惑,要认识到苹果从 2006 年开始销售 MacBooks。另一方面,微软是在 2013 年进入的,因此它可以更积极,由此产生的积极增长率是可以理解的。然而,这是令人印象深刻的增长,表明微软的 Surface 产品一直很受欢迎。

本着占领更多市场份额的精神,微软正专注于说服更多人购买 Surface Book 3。微软似乎更专注于将外部用户转化为 Surface 爱好者,而不是迫使其 Surface Book 2 用户购买新发布的 Surface Book 3,这可能导致糟糕的用户体验和潜在的客户流失。证据如下:

这是 Surface Book 2 还是 3?光看是看不出来的。来源:微软官网

  1. Surface Book 2 和 Surface Book 3 的设计是一样的。一眼望去,没人能确定他们眼前的版本是 Surface Book 2 还是 Surface Book 3。
  2. Surface Book 3 的内部硬件规格令人印象深刻,但对于现有的 Surface Book 2 用户来说,这不是升级的必备产品。显卡从 NVIDIA 1060 升级到 NVIDIA 1660,内存从 16GB 增加到 32GB,对于离群的高级用户来说非常好。尽管如此,对于大多数用户来说,16GB 和 NVIDIA 1060 已经足够等待 Surface Book 4 甚至更高版本了。
  3. 对于没有 Surface Book 2 的用户来说,购买 Surface Book 3 是有吸引力的,因为它具有前面提到的功能以及价格范围,与新一代 Macbook Pro 相比具有竞争力。下表列出了微软和苹果各种产品的价格范围。平均而言,微软的笔记本电脑产品(1831 美元)比苹果的(平均 2662 美元)便宜约 30%。具体来说,虽然 Surface Book 3 在仅比较基础价格时比 Macbook Pro 贵,但 Surface Book 的 max-spec 版本(3400 美元)比 Macbook Pro 的 max-spec 版本(6099 美元)便宜 44%。不过,Macbook Pro 的 max-spec 版本配备了两倍的内存(64GB)和四倍的磁盘空间(8TB)。当标准化规格(2TB 和 32GB RAM)时,Surface Book 3 便宜 500 美元,即 12.8%。

从苹果到 T2【微软的各种笔记本电脑选择的价格范围列表。从各自官方网站收集的数据。

这可能是一个巧合,微软正在采取这些措施来建立一个策略,方便地让现有的 Surface Book 爱好者满意。尽管如此,我认为他们是最有计算能力的。

微软在蚕食市场份额

我设计的笔记本电脑市场份额的简化可视化,只看微软和苹果。基于 2013-2019 年间各公司各自年报的收入数据。

自从微软在 2012 年 10 月发布第一代 Surface 以来,微软一直在大举蚕食笔记本电脑的市场份额。上面的图表显示了从 2013 年到 2019 年的六年间市场份额的变化(尽管只是基本的市场份额,假设微软和苹果是整个笔记本电脑市场)。在推出第一款 Surface Book 后的一年里,微软占了 3.8%——到 2019 年,这一比例增长了近 5 倍,达到 18.6%。

评论家可能会看着市场份额图抱怨说,只看微软和苹果并不是全貌,也不能保证微软甚至直接与苹果竞争。嗯,是的,我还没有从塞特亚·纳德拉本人那里得到直接确认,说有直接竞争的意图。但不管竞争是否是有意的,效果是可以感觉到的。看看下面的时间线。

苹果收入同比变化,与微软的发布保持一致。根据苹果公司提交的年度报告更改数据。来自维基百科的微软产品公告。面创 1,面书 1 ,面书 2

将苹果笔记本电脑的收入变化与微软的发布时间表叠加起来,我们可以看到微软笔记本电脑产品的发布确实对苹果笔记本电脑的销售产生了一些潜在的影响。2013 年和 2016 年两次最糟糕的收入变化也是在微软发布主要笔记本电脑之前:分别是第一代 Surface 和第一代 Surface Book。2018 年,苹果笔记本电脑出现小幅负增长。在它之前,微软公布了 Surface Book 2。但是谁知道呢——有可能所有这些事件只是纯粹的巧合。

微软硬件采用的其他潜在催化剂

iMessage 的价值不断下降

当我在 2017 年放弃我的 Macbook Pro 时,最让我害怕的是我正在断绝集成的便利性。通过只使用苹果产品,我可以在不同设备之间无缝切换;例如,我可以在手机上开始 iMessage 对话,然后跳到我的笔记本电脑上继续,反之亦然。

快进到 2020 年,我唯一一次使用 iMessage 是为了接收短信验证码。随着大量通信软件的出现,我所有的实时文本对话都开始进入 WhatsApp、Facebook Messenger、Discord、微信和 Slack。所有这些应用都与操作系统无关,所以无论我使用的是 Mac 还是 Windows PC,我都可以从移动设备跳到桌面设备。

资料来源:统计局

趋势是远离 iMessage,这不仅仅是一个人的问题。其他通信技术的全球采用正在快速增长。Whatsapp 2020 年用户达到 20 亿。Slack 在 2019 年第四季度增长到超过 1200 万日活跃用户。中国移动应用微信的日活跃用户已经超过10 亿。这些趋势不应该太令人惊讶,因为每个不使用苹果产品的人都可以使用这些应用程序无缝地从移动设备跳到桌面和其他设备。减少对苹果专属 iMessage 的依赖,也减少了对整个苹果生态系统的依赖。

当前的经济状况

尽管这两家公司都是国际性的,但其收入的最大部分仍来自北美。下图分解了苹果 2019 年的营收。这些数据是从苹果提交给 SEC 的 2019 年度报告中收集的。2019 年,其全部收入的 44.9%来自北美。微软 2019 年收入的 51.4%来自美国。

数据来源:苹果 2019 年年报。我设计的图表。

北美,尤其是美国目前的经济状况,是世界已经熟悉的。5 月 7 日, CNN 报道“自三月中旬以来,五分之一的美国工人申请失业救济。”当人们还在争论这个国家是否陷入衰退时,CNN 也报道说“美国已经陷入衰退”

不管国家的经济支出类别是什么,事实仍然是人们对支出持谨慎态度,特别是由于不确定的工作条件(冻结招聘、修订报价、裁员和休假),加上令人失望的股市表现(尽管它似乎正在良好地复苏)。这个国家何时重新开放存在不确定性,这增加了把钱留在口袋里而不是消费的压力。虽然这种支出的缩减起初似乎对微软或苹果不是好兆头,但也有两件事要记住。首先是口红效应。

“口红效应是一种理论,即当面临经济危机时,消费者会更愿意购买价格较低的奢侈品。例如,人们会买昂贵的口红,而不是买昂贵的毛皮大衣。潜在的假设是,即使出现危机,消费者也会购买奢侈品。当消费者对经济的信任度下降时,消费者会购买对其可用资金影响较小的商品。在化妆品市场之外,消费者可能会被昂贵的啤酒或体积更小、价格更低的产品所诱惑。

来源: 维基

我觉得苹果在这方面有优势。在奢侈品技术方面,它的品牌认知度比微软更强。我刚才说的话没有消息来源;你可以把它当作一个强烈的观点,但我认为没有多少人会不同意它。对于那些认为苹果品牌是“负担得起的”奢侈品的人来说,他们可能会在经济低迷时期继续购买苹果产品。但我也认为这将是少数购买者。

衰退期间的大多数购买者更有可能是那些购买必需品的人。这次购买有点不同,因为奢侈品的联想并不那么重要;相反,人们倾向于做出更明智的决定。我认为微软在这方面有优势,因为它的价格范围和上述功能。也就是说,经济环境对两家公司都不理想,所以总体来说不是一件好事。但这是一个机会,无论多么小,对于微软来说,这都是一个赢得用户的机会,这些用户开始重新考虑他们下一次购买昂贵的 Macbook Pro。

为什么人们不想购买微软硬件

苹果生态系统(不包括 iMessage)

虽然 iMessage 不再重要(之前讨论过),但苹果生态系统的其余部分可能会产生一些依赖性,甚至是厂商锁定。例如,订阅 iCloud 并将其用作云存储可能会锁定用户继续购买苹果产品,因为 iCloud 在他们之外并不容易使用。

此外,隔空投送等苹果专用功能的重度用户可能会享受到只需在手机和桌面之间点击一下就能分享图像和视频的便利。像我这样的失败者,拥有苹果和微软的产品,需要额外点击几次(在 Slack 或电子邮件上给自己发送照片和视频,然后在我的桌面上打开)。虽然额外的几次点击听起来并不多,但它加起来会对用户体验产生很大的影响。

用户体验

用户体验是这样一种东西,如果你没有考虑过,那么仅仅听到它听起来是不可思议的。用户体验专家知道著名的谷歌声称如果一个移动网站不在三秒钟内加载,超过 50%的用户会离开。三秒钟起初听起来并不多,尤其是对于拨号时代的老手(在 AIM 上打我一下)。

但是如果你不相信这一点,那么下次你解锁你的手机,在你点击任何东西之前数到三。我打赌你会不耐烦的。我们很焦虑,尤其是在从技术中获得我们想要的东西的时候。像苹果这样的公司非常努力地让我们的事情变得非常简单,所以当谈到获得我们想要的东西时,当然有一个高标准——无论是加载时间,点击量,还是只是理解如何使用某些东西。

苹果在交付漂亮、极简的硬件设计和出色的用户体验方面做得非常出色。这就是为什么我仍然坚持使用 iPhones,我也没有任何转行的打算。不过,微软已经采取了一些非常积极的举措来改善用户体验和漂亮的设计。在这一点上,我不会说微软与苹果相比在这方面有所欠缺,但微软将不得不花费更多的资源来说服新的潜在客户,让他们相信它在这个领域同样出色。

下一个前沿

我很兴奋地看着微软未来几年的发展,我希望 Surface 产品的战略是微软想要为自己绘制的整体道路的一瞥。从财务上来说,Surface 的推出获得了巨大的成功。在功能方面,微软有策略地推动新一代 Surface Book 的发布,不要迫使现有用户升级,这可能会显得过于激进。该公司正在推进一项大胆而令人尊敬的战略,该战略正在发挥作用。

微软的数据科学家面试问题

原文:https://towardsdatascience.com/microsofts-data-scientist-interview-questions-4c6f3a62ef64?source=collection_archive---------5-----------------------

查看数据科学家职位空缺,华盛顿 此处

谈到技术,微软无疑是最大的玩家之一。当涉及到面试微软或任何巨头时,你都要从头开始。随着 Azure、AI 工具的出现,以及对机器学习的高度依赖,微软是数据科学行业领域的新兴大玩家。微软正在慢慢主导云计算行业。也就是说,微软当然需要雇佣比以往更多的数据科学家。

在过去的五年里,微软一直是数据科学家职位最大的招聘池之一。参加过微软的面试后,我写下面试时的环境变得更容易了。相信我,这并不可怕!微软让你感觉很舒服。招聘经理为你提供建议,招聘人员和团队成员确保你带着新知识离开面试现场。

在这篇博客中,我将详细介绍微软数据科学家的角色和职责、资格、面试筛选、典型的“微软问题”等等…

主要职责描述

典型的角色或职责部分包括以下几点:不是全部,而是一部分。现在,看一下这个角色的描述是非常重要的,因为你可能想在开始之前在你的简历中加入一些关键词。

  1. 执行数据挖掘、统计研究、客户细分、剖析和建模,为业务需求提供解决方案,并支持长期数字营销战略
  2. 通过利用复杂的数据源网络,执行统计分析、群组研究、机器学习和预测建模。
  3. 每天组织和讨论大型数据集,对客户行为数据、转换和活动数据进行分析,以帮助企业识别模式、驱动因素并创建预测模型。
  4. 与业务利益相关者合作,将洞察力转化为行动
  5. 研究和评估来自不同来源的大量数据(例如,在线和离线数据、调查数据、行为数据、商业数据、文本数据等)。)来识别统计模式,形成建模的思路。
  6. 进行探索性数据分析、机器学习、数据挖掘和统计,从大量行为数据中获得可操作的见解,从而构建解决方案。
  7. 通过应用先进的 ML 技术进行实体提取、评分和主题聚类,构建文本分析解决方案。
  8. 创建有意义的演示和分析,讲述一个关注洞察力而不仅仅是数据的“故事”
  9. 通过应用数据科学定义和衡量成功的 KPIs 指标,帮助提高转化率或客户满意度。
  10. 提供以数据为中心的分析领导力,促进数据驱动的决策制定

资格

经历&资历

  1. 需要数据科学、经济学、分析学、统计学、计算机科学或相关学科的学士/硕士学位
  2. 需要 2 年以上处理来自不同数据源的大量数据的机器学习工作经验(对于实习生职位,这不包括在内)
  3. 强大的理论/算法背景,非常了解如何应用先进的统计技术来解决实际问题。
  4. 至少在以下一个领域有丰富的知识和经验:数据挖掘,机器学习,统计分析,受控实验
  5. 有从事大数据和 ML 技术的经验——Azure ML、Cosmos/Hadoop、Databricks、R、Python、SQL、SAS
  6. 优秀的沟通和演示技巧,能够以简单易懂的故事/可视化方式向管理层和大型团队解释复杂的数据
  7. 自我激励,能够独立工作并跨团队工作
  8. 批判性思维和解决问题的技能
  9. 强大的组织和优先排序技能

面试回合

这因角色、地点、团队、角色(全职还是实习)和许多其他因素而异。一般来说,微软坚持 3 轮筛选。

  1. 与招聘经理进行 30 分钟的电话面试
  2. 45-60 分钟的团队音频/视频访谈
  3. 最终摊牌:45-60 分钟——现场面试/视频面试

不管你用什么方式与微软沟通,你都可以肯定地期望自己在编码。语言是你的选择,但你必须编码!

下面我整理了一份之前在微软数据科学家面试中被问到的所有面试问题的清单。2019 年 10 月我为微软面试时,我列出了这个问题列表,现在,这个列表是为准备微软面试的任何人准备的。

当我准备这些问题时,我相信并准备好自己去期待一系列完全不同的问题。但令我十分惊讶的是,我被问到了其中的 3 个问题。再说一次,这不是微软面试的圣经。这更取决于你会和哪个团队合作。如果是核心人工智能或深度学习工作,问题可以更具体地针对该领域。

我会说,让我们看一个“初级数据科学家面试问题”列表。

你可以肯定的一个问题是从你的简历中解释一个你做过的项目/论文。基本上,他们会要求你解释你列出的项目或论文,并试图围绕该项目提出问题;你学到了什么,面临的问题,解决方案,围绕它的一般问题。这是他们评判你能力的时候。这应该是一个令人欣慰的地方,在这里你可以谈论你所做的事情。但是不要低估它。围绕它也会有困难的问题。

我的一个项目让我处理中等规模的数据集,在解释那个项目中做了什么时,有人问我— “如果你有大量未标记的数据和一小组正标记的数据(没有负标记可用),你能想出一些使用这个数据集学习分类器的策略吗?您如何决定将哪个模型应用于您的数据?

问题

  • 为什么神经网络在工作,为什么它是一个蓬勃发展的领域?
  • 什么是混淆矩阵?如何向一个非统计学的人解释?什么是假阳性和假阴性?
  • 随机森林、套索和岭回归是如何工作的?套索和山脊的区别。
  • 写一个函数来检查一个特定的单词是否是回文。
  • 在整数列表中寻找子序列的最大值。
  • 从有偏差的硬币中产生公平的硬币。
  • 从一个以概率 p 和(1-p)返回 1/0 的函数生成 7 个等概率整数。
  • ROC 曲线和敏感性、特异性、混淆矩阵的含义是什么?
  • 给定一个时间序列数据集,你将如何预测未来值?
  • 如何向客户解释一个深度学习模型?
  • 什么是 P 值?你将如何向团队中的非技术人员解释 p 值?
  • 如何通过玩一些计算技巧来更快地计算逆矩阵?
  • 描述梯度增强的工作原理。
  • 在应用机器学习算法之前,描述数据争论和清理的步骤。
  • 如何处理不平衡的二元分类?
  • 如何检测一个新的观察值是否是异常值?什么是偏差-方差权衡?
  • 解释支持向量机(SVM)。
  • 合并 k(本例中 k=2)个数组并排序。
  • 如何最好地从 500 万个搜索查询中选择一个有代表性的样本?
  • 西雅图的三个朋友告诉你下雨了。各有 1/3 的说谎概率。西雅图下雨的概率有多大?
  • 你能解释一下朴素贝叶斯的基本原理吗?你是怎么设定门槛的?
  • 你能解释一下什么是 MapReduce 以及它是如何工作的吗?
  • 如何检测一个新的观察值是否是异常值?
  • 讨论如何从产品用户群中随机选择一个样本。
  • 在整数列表中寻找子序列的最大值。
  • 你会怎么总结一个 twitter feed?
  • 在应用机器学习算法之前,解释数据争论和清理的步骤。
  • 如何处理不平衡的二元分类?
  • 如何测量数据点之间的距离?
  • 定义方差。
  • 箱形图和直方图有什么区别?
  • 你如何解决 L2 正则化回归问题?
  • 如何通过玩弄一些计算技巧来更快地计算逆矩阵?
  • 如何不用计算器进行一系列计算?解释这些步骤背后的逻辑。
  • 数据可视化的好坏有什么区别?
  • 你如何找到百分位数?为它写代码。
  • 从一系列值中找出最大和子序列。
  • L1 和 L2 有什么不同的正规化指标?
  • 你能解释一下朴素贝叶斯的基本原理吗?你是怎么设定门槛的?
  • 如何检测一个观察值是否是异常值?
  • 什么是偏差-方差权衡?
  • 讨论如何从产品用户群中随机选择一个样本。
  • k-means 收敛到全局解吗?如果有,能否给出直觉?如果没有,有什么策略可以让我们使用 k-means 得到更好的聚类?
  • 与测试数据相比,训练数据的准确性有多重要?
  • 你说的装袋助推是什么意思?所涉及的分类器的关键区别是什么?

这些是随着时间的推移积累的一些问题,不一定期望你所有的问题都来自这里,但至少我有三个问题。所以现在,当你在不久的将来参加微软的面试时,一定要在你的书签中加入这个故事来练习这个列表。

感谢您的阅读!我希望你喜欢这篇文章。一定要让我知道你在微软的数据科学面试中有什么问题。

面试愉快!

免责声明:本文表达的观点仅代表我个人,不代表严格的观点。

了解你的作者

拉什是芝加哥伊利诺伊大学的研究生。她喜欢将数据可视化,并创造有见地的故事。她是用户体验分析师和顾问、技术演讲者和博客作者。

用于视频中人体动作识别的 MiCT-Net

原文:https://towardsdatascience.com/mict-net-for-human-action-recognition-in-videos-3a18e4f97342?source=collection_archive---------31-----------------------

如何使用跨域剩余连接混合 3D 和 2D 卷积

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

最近,微软的一组研究人员发表了一篇论文[1],介绍了一种混合 3D/2D 卷积神经网络架构,用于视频中的人体动作识别。该论文报告了在 UCF-101 和 HMDB-51 数据集上的最新性能,同时通过使用比以前工作少一半的 3D 卷积降低了模型复杂性。

作者观察到,3D ConvNets 在这项任务中表现出令人失望的性能,因为它们很难训练,并且它们的内存要求限制了它们的深度。他们的架构被称为混合卷积管道网络或 MiCT-Net,解决了将 2D-CNN 主干网的效率与关键位置引入的额外 3D 残差卷积相结合的想法,以生成更深入、更丰富的特征地图。

作者的源代码是不公开的,这篇文章是我试图复制他们的一些工作的结果,这使我使用 ResNet 主干在 PyTorch 上实现了 MiCT-Net,并将其命名为 MiCT-ResNet。我的代码可以在这个库上获得,并且可以在你自己的项目中免费使用。

混合三维/2D 卷积管

MiCT 模块是基于 2D 和 3D 卷积可以相互补充以提高整体网络性能的观察而构建的。

一方面,2D·康文内特可以学习深度空间表示,但却无法从视频中学习时间结构,而这种时间结构是区分相似类别所必需的。

另一方面,3D ConvNets 在提取时空特征方面很有效,但很难堆叠成深度网络,因为解空间的指数增长使得它们很难优化。

从[1]中借用的 MiCT 块的图示,它利用跳过连接来组合 3D 和 2D 卷积。

作者的想法是通过将有限数量的 3D 卷积层与 2D-CNN 主干混合,结合两个世界的最佳之处。如上所述,3D 和 2D 卷积以两种方式混合:

在 2D 卷积的输入和输出之间添加了 3D 卷积。这种 3D 卷积在时间级别上增加了另一个级别的特征学习。这两个分支的特征然后用跨域元素式求和来合并。该操作降低了时空融合的复杂性,因为 3D 卷积分支仅学习剩余的时间特征,即视频中物体和人的运动,而空间特征通过 2D 卷积学习。

然后,在求和之后附加 2D 卷积,以在每一轮时空融合期间提取更深的特征。

MiCT 块实现

网络输入是表示为大小为 NxCxDxHxW 的 5 维张量的小批量视频剪辑,其中 N 表示小批量大小, C 频道数量, D 剪辑持续时间, HW 分别表示空间域中的高度和宽度。

当 3D 和 2D 卷积对不同大小的张量进行运算时,第一个问题立即出现:3D 卷积需要 5D 输入张量,而 2D 卷积需要 4D 输入张量。同样,3D 和 2D 卷积的输出不能直接相加。

因此,我们需要在跳过连接和融合操作之前,例如,从 5D 到 4D 来回变换张量。幸运的是,5D 视频张量只不过是图像序列的小批量,可以堆叠在一起形成一个更大的 4D 小批量,大小为 (NxD)xCxHxW

_to_4d_tensor 函数实现了这种变换,并通过 depth_stride 参数指定了可选的时间下采样。

_to_5d_tensor 函数执行逆变换,采用 4D 输入张量和指定要恢复的序列长度的深度参数。

现在,我们已经准备好使用下一个代码片段来研究 MiCT 块的向前传递。第一部分在填充输入张量之后执行 3D 卷积,以使 3D 卷积处理当前帧和接下来的几帧。接下来,我们执行第一次 2D 卷积,并将结果与 5D 空间中的 3D 卷积的输出相融合。最后,我们执行第二次 2D 卷积,并将结果作为 5D 张量返回,以备下一个 MiCT 块处理。

MiCT-ResNet 架构

这篇论文使用了一个从《盗梦空间》中得到灵感的自定义主干。它由 4 个 MiCT 块组成,每个块包含几个初始块。我选择使用 ResNet backbone,以便能够与 3D-ResNet 比较结果,并受益于 ImageNet 上预先训练的权重。

MiCT-ResNet-18 架构本质上是一个增加了五个 3D 剩余卷积的 ResNet-18。

如上面使用最浅的 ResNet 主干 ResNet-18 所示,该架构使用五个 3D 卷积,一个在网络入口处,一个在四个主要 ResNet 块的开始处。BasicBlock 是标准的 ResNet 块。为了清楚起见,省略了每个卷积之后的批标准化和 ReLU 层。

如果您不熟悉 PyTorch 中的 ResNet 实现,这篇文章提供了一步一步的引导,让您快速上手。

UCF-101 数据集

UCF-101【3】是著名的逼真动作视频的动作识别数据集,收集自 YouTube,有 101 个动作类别。所有视频的大小都是 320x240,每秒 25 帧。

需要注意的一点是,尽管每个类别有 13320 个视频和 100 多个剪辑,但对于这项任务来说,这是一个相对较小的数据集,容易过度拟合。所有的剪辑都取自只有 2.5k 的清晰视频。例如,同一个人弹钢琴的一个视频被剪切成 7 个剪辑。这意味着与每个片段中的动作由不同的人在不同的闪电条件下执行相比,差异要小得多。

从[3]中借用了 15 个人类动作的示例帧。

实验环境

实验的目标是在训练数据有限的情况下比较 MiCT-ResNet 和 3D-ResNet 的性能。大规模数据集(如动力学)的预训练不在范围之内。

为了便于结果比较,两个网络都基于 ResNet-18 主干网,时间跨度为 16,空间跨度为 32。权重由 ImageNet 预训练权重初始化。对于 3D-ResNet,通过沿时间维度重复 N 次 2D 滤波器的权重来引导 3D 滤波器,并通过除以 N 来重新缩放它们

为了支持每批大量视频剪辑的训练,模型的输入大小设置为 160x160。沿着时间维度对每个视频进行随机下采样,并且随机选择一组 16 个连续帧。该序列根据需要循环以获得 16 个帧剪辑。在测试时,选择视频的前 16 帧。

SGD 优化器的学习率为 1e-2,批处理大小为 128。应用权重衰减、丢失和数据增加来减少过拟合。关于培训程序的更多细节可以在资源库中找到。

结果

根据标准的前 1 名和前 5 名精度对模型进行评估。所有结果是 UCF-101 的三个标准分裂的平均值。 MiCT-ResNet-18 领先 1.5 个点,同时快了 3.1 倍,这证实了作者的方法的有效性。

性能对比。内存大小是针对一个批次大小给出的。

在第二个实验中,MiCT-ResNet 的时间跨度从 16 减少到 4,并且在不同数量的剪辑长度上测试该网络。对于 300 帧的序列,实现了 MiCT-ResNet-18 的 69.3 Top-1(交叉验证)精度和 MiCT-ResNet-34 的 72.8 Top-1(交叉验证)精度的最佳结果。

MiCT-ResNet-18 和 MiCT-ResNet-34 验证精度与视频长度的函数关系。

最后

我们看到,在 UCF-101 数据集上,与深度 3D 卷积网络相比,混合 3D 和 2D 卷积是提高性能的好策略。MiCT-ResNet 提供了更高的准确性和更快的推理速度。

然而,不可能对这两种架构的相对性能给出明确的结论。与微软在 MiCT-Net 上的工作平行,谷歌 DeepMind 的另一个团队已经表明[2]在像 Kinetics 这样的非常大的视频数据集上预先训练 3D-ConvNets 大大提高了它们在像 UCF-101 这样的迁移学习任务上的性能。

因此,如果这两种架构都在 ImageNet 和 Kinetics 上进行了预训练,那么如何比较这两种架构仍是一个未决问题。让我知道,如果你有访问动力学数据集,并愿意提供答案!

参考文献

[1]周,孙,查志军,曾文伟.MiCT:用于人体动作识别的混合 3D/2D 卷积管,2018 年 6 月。

[2] J .卡雷拉和 a .齐塞曼。Quo Vadis,动作识别?新模型和动力学数据集,2018 年 2 月。

[3] K. Soomro,A. Roshan Zamir 和 M. Shah, UCF101:来自野外视频的 101 个人类行动类别的数据集,CRCV-TR-12–01,2012 年 11 月。

午夜黑客 2:使用文档嵌入的上下文搜索和表情分组

原文:https://towardsdatascience.com/midnight-hack-episode-2-contextual-search-grouping-of-emojis-using-document-embedding-9bee5bbed6cc?source=collection_archive---------35-----------------------

引文:http://www.satandigital.com/apps/EmojiPlot/

你好。!!欢迎来到我又一个愚蠢的项目。

所以前几天我在用 Whatsapp 的时候,发现这个用关键词查找表情符号的很酷的小功能真的很有趣。现在,我很确定他们没有使用机器学习来实现这一点,这很可能是硬编码关键词和表情符号的简单映射。

但是,如果你能更进一步,不把搜索功能局限于那些预定义的关键词,而是根据搜索关键词的上下文含义来搜索表情符号,那会怎么样呢?

懒得通读?你可以在这里查看表情图:http://www.satandigital.com/apps/EmojiPlot/

该图具有缩放和平移功能。单击并拖动鼠标进行缩放,使用 shift 键进行平移。

并且抓取的数据集托管在这里:https://github.com/AtomicSpider/Emoji-Dataset

该项目有 4 个部分:

  1. 准备表情数据集

  2. 生成表情符号的矢量或数字表示

  3. 在 2D 空间绘制表情符号

  4. 编写搜索脚本

  5. 准备表情数据集:

一个简单的谷歌搜索把我带到了 https://unicode.org/,那里有所有表情符号、图像、Unicode ids、base64 数据 URIs 和名字的综合列表。

我编写了一个简单的 web 抓取脚本来下载所有的图像和元数据,并创建了一个主数据集 JSON,它也引用了图像文件。

数据集可以在这里找到:https://raw . githubusercontent . com/atomic spider/e moji-Dataset/master/Dataset/Dataset . JSON

生成表情数据集的脚本

2。生成表情符号的矢量或数字表示:

我遇到了word 2 vec一个两层的神经网络,它可以提取单词并生成单词的多维向量表示。

word2vec、 doc2vec 的文档等效,工作原理类似。doc2vec 获取文档或一组单词,并生成它的多维向量表示。

我决定使用 doc2vec,从表情符号名称中提取关键词,并为每个表情符号生成 300 维向量。

表情符号名称可以直接用作 doc2vec 模型的输入,但我继续使用 nltk (自然语言工具包)从名称中删除停用词以实现更好的准确性。

生成表情矢量的脚本

3。2D 空间的剧情表情符号:

酷!!!现在我们有了矢量数据,绘图应该很容易,对吗?对吗??

引用:图片来自 giphy.com(https://giphy.com/gifs/the-office-mrw-d10dMmzqCYqQ0)

事实上,这部分花了我不少时间才弄明白。第一个问题是:你如何绘制 300 维的向量?

经过相当多的研究,我决定使用tSNE并减少生成的表情向量的维数。

对!!!现在我们有了绘图数据,用表情符号生成一个简单的散点图就很容易了,对吗?对吗??对吗???

引用:图片来自 giphy.com(https://media.giphy.com/media/26DOzMVt4i9GzzxyE/source.gif)

问题是,我想用表情符号作为分散点的自定义标记。遗憾的是 python 对此没有很好的支持。

R 中有一个库, ggplot 可以和dill/e mogg一起使用来生成表情符号标记,但是剧情看起来不太好。此外,没有平移和缩放功能。****

所以我决定使用high charts导出数据和绘图。感谢我的同事 Vinoth,他帮助我弄清楚了如何在 HighCharts 中使用自定义标记。

导出高图表绘图的数据

用于绘制表情散点图的 Javascript 代码

引文:http://www.satandigital.com/apps/EmojiPlot/

剧情页面可以在这里进入:

正如你所看到的,我们采用的方法能够很好地对表情符号进行分组。可以看到所有的旗帜在左边组合在一起,动物在中间上方,食物在右上方,表情符号在右边等等。

4。写一个搜索脚本:

对于从关键词中搜索表情符号,我们可以使用相同的 doc2vec 模型将搜索关键词转换为向量,并从表情符号向量列表中找到该向量的最近邻居。

结果:

如果你在 WhatsApp 的表情键盘上搜索快乐情绪,它不会产生任何结果。

引用:截图来自我的手机

但是通过我们的方法,我们能够用上下文信息搜索相关的表情符号,而不是硬编码的关键字映射。

引用:截图来自我的笔记本电脑

我的失眠之夜就此结束😁。

如何像老板一样迁移到雪花

原文:https://towardsdatascience.com/migrating-to-snowflake-like-a-boss-6163293f0bcb?source=collection_archive---------32-----------------------

顺利迁移需要知道的 3 件事

形象承蒙 碧玉人儿 上的泼溅。

告诉我这是否让你想起了什么:你的老板确信 雪花 数据的未来 并告诉你的团队你需要从你的数据仓库迁移到这个崭新的解决方案,这是你生活中最需要的。将存储与计算隔离开来将为您的公司节省大量资金,此外,您的副总裁还可以生成新奇的仪表板供您的首席执行官跟踪。

云数据仓库平台雪花,让数据团队可以轻松存储和使用数据。与传统的存储解决方案不同,雪花支持大量的数据类型和商业智能工具,并使内部和外部团队能够在整个 ETL 管道中轻松协作。作为一个关系数据库,雪花还可以支持大多数结构化和非结构化数据类型。

像您的副总裁一样,我的许多客户对迁移到像雪花这样的云存储和计算解决方案的前景感到兴奋,但他们不知道从哪里开始。正确的做法是:我能够找到几篇关于从红移迁移到雪花的文章,但是很少有关于从其他解决方案中进行极地跳水的。

像雪花一样,没有两个数据栈是一模一样的,各有各的资产,复杂性, 需求 。雪花使得跨各种数据库和数据类型的管理和协作变得容易。(图片由 伦负担 于 Unsplash。)

在与现场的几个迁移者交谈后,我分解了一些较少讨论的团队迁移到雪花的注意事项,不管您从哪里开始:

1.告别分区和索引。

与其他数据仓库不同, Snowflake 不支持分区或索引。相反,雪花自动将大表分成微分区,用于计算每列包含的值域的统计数据。这些见解决定了您实际需要数据集的哪些部分来运行您的查询。

对于大多数实践者来说,这种从索引到微分区的范式转换真的不应该成为问题(事实上,许多人选择迁移到雪花,因为这种方法减少了查询延迟)。但是,如果您在当前的生态系统中有分区和索引,并且正在迁移到“集群”模型,那么您需要一个合理的方法。安全迁移的一些提示:

  1. 记录当前的数据模式和沿袭。当您需要交叉引用旧数据生态系统和新数据生态系统时,这将非常重要。
  2. 分析你当前的模式和血统。接下来,确定这个结构及其对应的上游源和下游消费者是否对数据迁移到雪花之后的使用方式有意义。
  3. 选择合适的集群键。这将确保您团队的访问模式具有最佳的查询性能。

只要您对数据有可见性,告别分区和索引就没什么好担心的。

2.预期(并接受)语法问题。

我采访的几个数据团队反复强调语法问题是任何云仓库迁移不可避免的组成部分,迁移到雪花也不例外。

一位数据分析师特别指出了将用于处理 ETL 的 SSIS 包从她的 SQL 服务器转换到雪花的困难,这承认SSIS 包不容易与他们的解决方案集成。这种错误不仅令人沮丧,而且大大减缓了她的迁移,导致不可预见的成本和资源限制。

虽然像 DBT 这样的建模解决方案有助于验证数据集,但是哈希、时间戳和日期等函数的格式在新旧版本的数据之间往往不一致。

此外,雪花是区分大小写的,所以检查查询中的比较问题很重要。由于这些问题,一些公司可能会检查并重构所有被迁移的 SQL 行。

语法错误成为传统行业公司的一个更大的痛点,例如金融服务或医疗保健( ICD10 代码,我正在看着你),这些行业长期依赖传统解决方案和手动、易错的数据输入。简单地迁移到云并不能解决这些问题。正如一家公共部门咨询公司的数据分析师告诉我的那样:“即使你雇佣了令人惊奇的人,并把最好的数据字典放在他们面前,他们也可能无法告诉你这一切意味着什么。”

您越早接受语法错误作为过程的一部分,就越容易识别这些不一致的趋势和模式,从而加快它们的解决。

3.经常监控你的数据。

与语法错误类似,数据问题甚至会导致最平稳的雪花迁移失败,一旦您连接上商业智能工具,就会产生错误或误导性的分析。通常这些会导致无声的错误,直到下游的消费者在报告或仪表板中发现问题时才会被注意到。如果你幸运的话,那是一个内部用户——如果你不幸运的话,那可能是你上周刚入职并试图给他们留下深刻印象的新的重要客户。

我们在一家数字营销咨询公司采访的另一位分析师指出,很难确保新旧数据仓库之间的全面数据定义。在她公司的新雪花仓库出现一些数据错误后,她决定通过开发两个并行数据分析层来测试他们数据的可靠性,一个是她的传统仓库,另一个是通过雪花。使用 Looker 为两个堆栈生成指标,他们很快确定了两个仓库之间实际上存在不一致,每组指标呈现不同的数据量。

当升级你的数据仓库时,确保你也在升级你的团队运作的方式,从语法并发这样的小事一直到数据质量和可靠性。

您在这一迁移上投入了大量资金(理应如此!),如果数据本身不可信,那么浪费这些数据是愚蠢的。

掌握您的迁移

如果您从索引和分区转移,预计语法问题,并优先考虑数据质量,您将实现更无缝的雪花迁移,促进更轻松的协作,并为您的组织提供真正的业务价值。

迁移到雪花意味着您的团队拥有更大的灵活性和可伸缩性,以及为您的客户提供更快、更可靠的洞察力——如果您做得好,它还可以为您的整个组织带来力量倍增。

别担心:你也会给你的老板留下深刻印象。我保证。

想了解更多,伸手 巴尔摩西

本文由蒙特卡洛首席执行官 巴尔·摩西 、蒙特卡洛首席技术官&Lior GAVI sh共同撰写。

新冠肺炎时期时装业股票的表现和弹性

原文:https://towardsdatascience.com/milan-paris-fashion-industry-stock-performance-resilience-during-covid-19-49502ec040fe?source=collection_archive---------32-----------------------

商业智能

探索米兰和巴黎证券交易所的趋势

图片由皮克斯拜的 Gerd Altmann 提供

世界正在遭受一个看不见的敌人的袭击,新冠肺炎已经永远改变了我们的生活,我们被完全封锁,我们不得不对我们的生活方式和业务做出重大改变,病毒的影响正在蔓延,扰乱了米兰和世界其他地方的日常生活,切断了购物,扰乱了全球供应链,房地产市场,威胁着经济,无论几周前可能存在的危机管理应对指南现在似乎来自另一个时代,这种情况迫使每个人实时发展和调整他们的策略和创造力。

根据麦肯锡&公司发布的一份报告,全球超过 40%的奢侈品生产发生在意大利,所有的意大利工厂已经暂时关闭。

因为股票市场不得不自己处理一些重大的变化。在这个项目中,我们将构建一个 Python 脚本来分析新冠肺炎对米兰和巴黎证券交易所股票价格的影响。我们将探索市场上一些最大的时尚公司的表现,看看它们在新冠肺炎风暴中表现得好坏。我们将把意大利疫情爆发前的股票价格作为参考,并与几周后至 4 月 21 日的相同股票价格进行比较。我们将通过进行不同的分析和计算多种股票的每日价格变化来做到这一点。之后,我们将尝试探索股票价格与意大利每日新增冠状病毒病例数之间的关系。

接受调查的公司有:

  1. AEF。MI ( Aeffe 米兰证券交易所)
  2. MONC。MI(米兰证券交易所)
  3. 公元前。米(布鲁内洛·库奇内利在米兰证券交易所上市)
  4. SFER。米(在米兰证券交易所)
  5. 托德。米( Tod's 集团在米兰证券交易所上市)
  6. MC。PA ( LVMH 集团在巴黎证券交易所上市)
  7. CDI。PA ( 克里斯汀·迪奥在巴黎证券交易所上市)
  8. KER。PA ( 开云集团在巴黎证券交易所上市)

注:要查看代码并接触数据集,请访问我在GitHub上的个人资料,如果您有兴趣探索更多项目,请查看我的第一个项目关于 机器学习 ,第二个项目关于 房地产市场新冠肺炎的颠覆。

让我们开始,看看我们的数据集。我们选择调查接近的价格。

调整后的收盘价准确地反映了扣除任何公司行为后的股票价值。它被认为是该股票的真实价格,经常在检查历史回报或对历史回报进行详细分析时使用。

请注意,由于雅虎财经有时会面临网络问题,可能会遗漏一些日子,如一年的第一天。

  • 我们要做的第一件事是试图调查整个时间段内每家公司股票的最高和最低调整收盘价。我们将使用一个柱状图来显示数据,我们还将使用一个对数标度来表示可调收盘价格,从而将这些值标准化为一个统一的标度。通常通过数据规范化,数据集内的信息可以以可视化和分析的方式进行格式化。

在上面的表示中,股票可以分为两组:可靠的股票和不稳定的股票。可靠的股票是指在指定的时间段内,最小调整收盘价和最大调整收盘价之间没有太大差异的股票。例如:开云、LVMH、克里斯汀·迪奥、Moncler。然而,不稳定的股票是那些在最低和最高收盘价之间变化最大的股票。例如:Aeffe

  • 现在让我们试着把数据分成两部分,爆发前和爆发后,以更深入地研究趋势。

现在很清楚的是,一旦新冠肺炎风暴来袭,大多数新冠肺炎时代之前的股票收盘价的波动性都会发生变化。

  • 在接下来的分析中,我们将尝试获取回报。回报被定义为股票价格随时间的变化,可以用价格变化或百分比变化来表示。正回报代表利润,而负回报标志着亏损。我们将使用 Python 库中的一个内置函数来完成这项工作。

请注意,分析中的第一天(30–12–2019)被删除,因为我们测量的是第二天(02–01–2020)的回报

现在让我们探索最小和最大回报日期。

有趣的是,这些股票中的大多数在 2020 年 3 月 12 日达到了最低回报。在那一天,美国宣布全国进入紧急状态,而意大利在之前的四天里每天的死亡人数都是世界上最高的(包括高峰期的中国)。

所有公司的最高回报率也是在 3 月份。有趣的是,在 3 月 24 日 Trump 宣布美国将“很快开始营业”。

现在,我们将尝试把收益分成两个数据集,新冠肺炎前后,然后我们将对股票收益应用标准差。

在接下来的图表中,如果股票出现在图表的右端,它们被认为是不稳定的,具有很大的标准差,而如果它们出现在左边,它们应该被认为是可靠的。

很明显,克里斯汀·迪奥(Christian Dior)受到的影响最大,由于疫情,它从最可靠的股票变成了最不稳定的股票。然而,Brunello Cucinelli (BC)在此期间取得了最大的进步,反过来,更积极的举措也发生在 Moncler,Kering 身上,而 LVMH 保持不变。

为了详细说明新冠肺炎对每只股票价格的影响,我们将每只股票的每日价格除以参考行,在我们的示例中,参考行是 2 月 21 日(注意第一行)。这将使我们对他们每个人的表现有更清楚的了解。

我们可以很容易地看到新冠肺炎对股票价格的影响。例如,我们看到像 Aeffe 这样的公司在 3 月 13 日的收盘价比 2 月 21 日的收盘价低 44%。

同样,Brunello Cucinelli 的股价折价 19 %, Moncler 的折价 21%,表现优于路威酩轩集团和开云集团。

现在我们有数据支持的证据表明新冠肺炎对股票价格有巨大的影响。但是之前的时期呢?那是病毒第一次从中国武汉传播到意大利的时候?

让我们重新创建从 12 月 30 日到 2 月 21 日的相同分析。

除了 Aeffe,似乎对于大多数股票来说,病毒的爆发对股票价格的影响最小,因为欧洲几乎没有病例,而中国有数千例。同样值得注意的是,Brunello Cucinelli 取得了巨大的增长,这可能与 1 月 7 日他们发布的去年初步数据有关,净收入增长了 9.9%,这使得该公司的股票在意大利证券交易所上涨了 7.6%。

然而,新冠肺炎停止了布鲁内洛·库奇内利的增长,因为他们最近报告第一季度收入下降。

现在让我们一起想象整个时期。

令人惊讶的是,在面对新冠肺炎风暴时,Moncler 的股价表现令人印象深刻。

现在是时候将新冠肺炎的数据纳入我们的分析了。我们将添加 2 月 24 日至 4 月 21 日期间意大利每日新增感染病例的相关数据(因为没有关于 21 日、22 日、23 日每日数字的数据)。

我们可以清楚地看到这样的趋势,在大多数情况下,新冠肺炎案例的数量增加了,股票价格降低了。

最后,我们可以用热图来表示这种相关性。

在这张热图中,如果我们检查最后一行,我们可以看到,有些公司,如克里斯汀·迪奥和布鲁内洛·库奇内利,这种关系强于 70%,这意味着当每日感染病例数增加时,这些公司的股价会下降。

结论

由于新冠肺炎,股票市场波动很大,由于许多公司对其风险敞口或供应链的可见性有限,这种影响更大,因此,困难时期可能是你自身实力的反映,今天的公司明白他们对客户、员工和利益相关者负有责任,要在财务和社会方面取得成功。

许多品牌以大胆的方式做出回应,让利益相关者有理由相信他们将度过这场危机,共同前进。尽管 3 月 13 日大多数股票价格都出现了大幅下跌,但迄今为止,来自 Moncler 股价的数据显示了出色的表现,这表明业务和品牌的弹性和灵活性,其次是巨头 LVMH 和开云集团。

“目标感”:“你公司的战略必须阐明实现财务业绩的途径。然而,为了保持这种表现,你还必须了解你的业务对社会的影响,以及广泛的结构性趋势——从工资增长缓慢到自动化程度提高到气候变化——对你的增长潜力的影响。”—贝莱德首席执行官拉里·芬克在 2018 年致首席执行官的年度信中

参考

  • 3 月 12 日消息
  • 3 月 24 日消息
  • Github 科技股分析

编者注: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

千禧年自杀|概率转折点分析

原文:https://towardsdatascience.com/millennial-suicides-an-analysis-about-change-1bf3294a9030?source=collection_archive---------46-----------------------

一个简单而有意义的概率 Pyro 模型来揭示随时间的变化点。

孤独。一张由萨莎·弗里明德在 Unsplash 上拍摄的照片

媒体的一个深刻观点和观察是,从 20 世纪 80 年代到 21 世纪初,英国年轻人的自杀率有所上升。你可能会在新闻、和出版物中找到它,或者它只是被大众接受的事实。但是你怎么能让它变得可测量呢?

让假设变得有形

为了使这种说法可检验,我们寻找数据,并在英国国家统计局找到了自杀率的概况,特别是英格兰和威尔士。

https://www . ons . gov . uk/visualizations/DVC 661/sizes/index . html

一般来说,在日常生活、商业或学术中,一种基本的问题是什么时候发生了变化。你假设随着时间的推移,一些事情已经发生了根本性的变化。为了证明你必须量化它。所以你得到一些关于主题的数据,并建立一个模型来显示值发生变化的点以及它们的大小。我们将研究如何做到这一点。

特别是千禧年自杀事件

根据手头的数据,我们取了千禧一代年龄组的平均值。为了简单起见,这意味着年龄在 25 到 35 岁之间。给定我们的数据集,我们可以将 20 世纪 80 年代以来千禧一代的平均自杀人数可视化如下:

suicide_millenials_df = suicide_data[suicide_data.Age.isin(range(23,35))].groupby(["Year"]).mean().reset_index()
# round values to closest integer
suicide_millenials_df["Suicides"] = suicide_millenials_df.Suicides.round()
suicide_millenials_df.head()

数据帧的头部应该是什么样子。

图 1—1981 年至 2017 年英格兰和威尔士 25 至 35 岁年龄组的平均自杀率(每 10 万人)。

从这些数据中,我们可以清楚地看到,随着时间的推移,直到 2000 年代初,数据稳步上升,然后下降,直到 2010 年代。我们好奇的一面想知道这到底是什么时候发生的,这样我们就可以出去寻找根本原因以及与那些影响趋势相关的潜在问题。让我们建立一个模型,找出究竟在哪一年中会出现实质性的变化。为了寻找一个特定的变化点,我们将使用烟火苹果作为一个概率框架。

怎么做

选择的方法是泊松回归,我们的变化率来自正半高斯。我们将使用【2】中描述的数学基础。这需要:多年来的均匀先验分布 T ,半正态分布(高斯的正侧)的变化率 μ 用反转括号表示。看着这些数据,我们为我们的比率设置了一个大的范围,因为我们想要捕捉从 75 到 130 的变化——大约 50。最后,我们通过泊松回归找到观察到的自杀率。

注:回归需要我们从正态分布中取样。

T∞U(1981,2017),μ_ 0∞N+(0,50),μ_ 1∞N+(0,50),N _ T∞泊松(μ_[t>T])

这些参数是可以调整的——也许你会寻找不同尺度的变化,无论是随着时间的推移还是影响的大小。人们可能会考虑半柯西分布的更极端的值或简单的增加/减少规模。

烟火模型

def model(years, suicides):
    σ = pyro.param('σ', torch.ones(data_len))
    T = pyro.sample('change', dist.Uniform(1981, 2017))
    grp = (years > T) * 1
    # Independent events 
    with pyro.plate('rate', 2):
        μ = pyro.sample('μ', dist.HalfNormal(scale=50))
    y_obs = pyro.sample('obs', dist.Normal(μ[grp], σ), obs=suicides)

grp 给出了括号中μ的指数。
然后从正态分布中对模型观测值进行采样,考虑μ和比例=σ=1(模型中的最后一行)。
在运行这个模型之前,我们使用 PyTorch 将数据帧转换成可读取的张量,如下所示:

years = torch.from_numpy(suicide_millenials_df.Year.values)
suicides = torch.from_numpy(suicide_millenials_df.Suicides.values)
data_len = len(suicide_millenials_df)

对于拟合过程,我们利用 MCMC 方法进行贝叶斯推理。我们采样 1000 次迭代,让采样器老化 300 次迭代。

SAMPLES = 1000
WARMUP = 300
nuts_kernel = NUTS(model)
mcmc = MCMC(nuts_kernel, num_samples=SAMPLES, warmup_steps=WARMUP)
mcmc.run(years, suicides)

我们特别使用不干涉的坚果取样器进行推断,并为我们的 Pyro 参数找到值,并建议您也这样做。注意,与变分推理方法相比,MCMC 需要时间。训练后,我们发现相对较高的接受概率约为 91.2%,步长ϵ ≈0.00198。

通过检查模型摘要,我们可以看到一切正常,没有出现偏差。虽然我们的 R-hat 值有点高。

现在,有了这些样本,我们可以显示一段时间内最频繁发生变化的时间:

图 2 —跨年度变化点出现的直方图。

我们继续绘制给定时间内的不同速率,以说明发生变化的点。

def pl(pt):
    grp = (years > pt['change']) * 1
    line = plt.plot(years, pt['rate0'] * (1 - grp) + pt['rate1'] * grp, 
      color='red', alpha=0.005) df.apply(pl, axis=1)

图 3—1000 个样本随时间的变化率(红线)。从 1995 年到 1996 年,出现了下降趋势。

图 4——另一条随时间变化的比率为红线。我们看到在 1986 年至 1989 年期间发生了三起事件,这些事件表明了这种变化。运行 2000 个样本,1000 个就足够了。

首先,我们用 1000 个样本运行前面描述的模型。这揭示了 1995 年前后的变化点(见图 3 ),表明即将到来的下降趋势。这个比率用红线表示。这里,模型量化了更好发展的变化点
我们再次尝试运行模型,为此我们采集了 2000 个样本,模型收敛于 1986 年到 1989 年的时间范围,这是另一个转折点。这标志着上升趋势的潜在转折点。如果我们想揭示千禧一代自杀率上升背后的原因,我们必须在那个时间范围或更早的变化中寻找原因,其影响已经在这个时间范围内表现出来。
可复制性注意:为你的 MCMC 推理设置一个随机种子或初始参数,这样你就可以复制你的发现。****

开放式问题

我们已经表明,随着时间的推移,不仅仅发生一种变化。有一个增加比率的点数范围和一个减少比率的点数范围。人们可以扩展模型以获得一个以上的变点,使μ成为三维的或拟合一个完全不同的模型。

总结模型

我们已经展示了如何从数据中获得时间变化的具体公式及其潜在概率。这被直接翻译成 Pyro,通过取样,我们可以推断出具体的变化点和这些变化发生的年份。

概率编程是一个强大的引擎。

完整的笔记本可以在这里找到:

** [## RMI chae 1/烟火研究

github.com](https://github.com/RMichae1/PyroStudies/blob/master/changepoint_analysis.ipynb)

这个问题的严重性

尽管这是数据科学的一篇介绍性文章,但自残和死亡是一个严肃的话题。万一你或你爱的人受到影响,那里有帮助和资源。所以我在这里给你们留下这样的信息:**

参考

  1. 英国国家统计局。 中年一代最容易死于自杀和药物中毒 。自杀率数据集。2019.
  2. C.谢勒。 贝叶斯变点检测用 PyMC3 2018。
  3. 米(meter 的缩写))霍夫曼,盖尔曼。 不掉头采样器。 JMLR v15。2014 年。

小心詹森差距

原文:https://towardsdatascience.com/mind-the-jensen-gap-c54e0eb9e1b7?source=collection_archive---------34-----------------------

当在预测之前转换数据时,学习如何在返回到原始尺度时发现偏差

图片来源: WillMcC (已修改)

背景

在 Kaggle 的 M5 预测-准确性竞赛中,平方根转换毁了我团队的许多预测,并导致在最后时刻进行选择性的修补工作。尽管的结果很好,但我们被提醒“重构偏差”会困扰原始尺度的预测,即使是平方根这样的普通变换。

平方根变换

对于泊松数据,平方根的基本原理是它是方差稳定变换;理论上,值的平方根近似正态分布,具有恒定的方差和平均值,即原始平均值的平方根。这是一个近似值,正如维基百科所说的,其中“收敛到常态(随着[原始均值]增加)的速度远远快于未转换的变量。

想象一下,你决定在一个计数数据场景中求平方根,感觉很好,确信收敛到正态是“快速的”。然后,对平方根转换数据的平均值进行建模,然后获得平方根级别的预测。在某些时候,特别是在预测场景中,你必须回到最初的规模。这可能需要对模型估计的平均值求平方。M5 竞赛提醒人们,这种方法可能而且将会失败。

詹森差距

詹森不等式陈述了对于凸函数,在期望处求值的函数小于或等于该函数的期望,即 g(E[Y]) ≤ E[g(Y)]。对于凹函数,这个不等式是颠倒的。

同样的,詹森间隙定义为差值 E[g(Y)]-g(E[Y]),对于凸函数 g. ( 作为题外话,注意当 g ( x )是平方函数时,詹森间隙【T32)

当把 g ( x )作为平方函数,把 Y平方根作为随机变量时,詹森间隙就变成 E[Y]-E[sqrt(Y)]。因为数量是正,我们的重建平均值将向下偏移。为了进一步了解这个差距的大小,我们转向泰勒展开式。

泰勒展开至近似偏差

对于Mathematics stack exchange提示“泊松随机变量平方根的期望值”,投稿人 Hernan Gonzalez 解释了一个随机变量关于其均值的泰勒展开,如下图所示。

注意,展开至少需要原始分布的几个中心矩。对于泊松,前三个只是平均参数。

忽略均值估计量也是一个随机变量,我们可以通过逆变换运行上面的期望,即平方它,以了解任何泊松均值在原始尺度上的偏差(代数不在这里,但它在演示代码的第 34 行中计算)。)同样,利用随机变量平方根的性质,可以用同样的方法直接分析g(x)=x^2。这开启了偏差修正的可能性,这是一个有趣的命题,尽管它有自己的假设和复杂性。

近似分解

在他的回答接近尾声时,Gonzalez 提到,只有当原始泊松的平均值比 1 大很多时,近似"才有用,并在评论中澄清这是必要的,以便"总和的项快速减少。”这是从原始术语后的均值被提升到负幂得出的。

在 M5 竞赛中,许多商品的平均销售额都大大低于 1,因此使用平方根变换会导致糟糕的表现。为了了解这在实际样本中是如何发生的,下一节将通过模拟来研究这一现象。

示范

在本节中,我们使用黄土平滑器在原始比例和平方根比例上创建模型,并对后者的平均估计值进行平方。对于平均值为 20 和 0.2 的模拟泊松数据,我们绘制两组预测并检查偏差。代码不到 50 行,可以在 Nousot 的公共 Github 库中找到。

当平均值为 20 时

对于泊松随机变量的均值为 20 的情况,再转换偏差为负(如詹森不等式所说),但也相对较小。在代码中,计算泰勒展开的前两项,并与平方根标度上的经验偏差进行比较。分别在-0.027 和-0.023,比较接近。

当平均值为 0.20 时

对于泊松随机变量的平均值为 0.20 的情况,情况就大不相同了。虽然延森不平等总是成立的,但相对而言,延森差距现在很大。此外,泰勒近似法已经完全失效,前两个偏差项总和为 0.419,而经验偏差为-.251(仍在平方根范围内)。

讨论

大卫·沃顿(David Warton)在 2018 年发表的论文“ 为什么你不能为小计数 摆脱困境”表明了对小均值计数数据进行标准假设的无望。对于 M5 稀疏的时间序列来说,求平方根没有什么好处,反而会损失很多。至少,我们应该区别对待这些系列。(关于我们对卡尔曼滤波器的使用, Otto Seiskari 的建议当模型被错误指定时,通过交叉验证进行调整尤其引人注目)。

沃顿的论文对一般转换的用户有一些严厉的言辞。我仍然相信,如果一个转换让你更接近标准假设,你的代码运行得更快,你享受更好的属性,那么它是值得考虑的。但是需要对数据环境中的转换属性进行诚实的探索,而这不是免费的。

通常,变换(及其逆变换)要么是凸的,要么是凹的,因此詹森不等式将保证以詹森间隙的形式出现偏差。如果你想知道为什么你从来没有听说过它,那是因为它经常被认为是近似误差。根据高等(2018) ,

“计算一个难以计算的[函数的期望]出现在从统计力学到机器学习理论的各种场景的理论估计中。解决这一问题的常用方法是……证明误差(即詹森差距)对于应用来说足够小。”

当使用转换时,理解逆转换的属性(在数据的上下文中)是值得的。外面很危险。注意脚下,小心延森沟!

GPU 上数据科学家的最小熊猫子集

原文:https://towardsdatascience.com/minimal-pandas-subset-for-data-scientist-on-gpu-d9a6c7759c7f?source=collection_archive---------15-----------------------

所有这些小而强壮的熊猫,来源

使用 GPU 进行数据预处理

对于 pandas 来说,数据操作轻而易举,它已经成为 it 的一个标准,许多并行化库,如 Rapids 和 Dask,都是按照 Pandas 的语法创建的。

有时,我会写一些我经常使用的熊猫功能的子集。 在这篇文章中,我将讨论在 GPU 上使用 cuDF 处理 Python 中的大多数数据操作案例。

通篇都是一些零星的建议。

PS: 为了进行基准测试,下面所有的实验都是在一台 128 GB RAM 的机器和一台 24 GB RAM 的泰坦 RTX GPU 上完成的。

什么是 Rapids CuDF,为什么要使用它?

cuDF 基于 Apache Arrow 列内存格式构建,是一个 GPU 数据帧库,用于加载、连接、聚合、过滤和其他操作数据。

简单地说,Rapids CuDF 是一个旨在为 GPU 带来 pandas 功能的库。除了 CuDF 之外,Rapids 还提供了对 cuML 和 cuGraph 的访问,它们分别用于在 GPU 上处理机器学习算法和图形。

这有什么好处呢?

典型的 GPU 有超过 2000 个 CUDA 核心。当使用 Dask 或多处理进行并行化时,Pandas 可以使用您的机器拥有的 8 个核心或 16 个 CPU 核心。现在,这些 CPU 内核的能力各不相同,但 CUDA 内核可以快速完成简单的计算,因此可以为我们提供显著的加速。

我的 GPU 泰坦 RTX 有大约 4600 个核心。这意味着我应该能够使用 GPU 并行化我的计算。

但问题是,编写运行 GPU 的代码很难。而 Rapids CuDF 解决了这个问题。

在我们进一步讨论之前,这里有一个简单的例子来说明 cuDF 如何帮助您。在这里,我试图得到我的随机数据帧中所有列的平均值,该数据帧有 1 亿行和 5 列。

使用 cuDF 加速了大约 350 倍!!!代码基本保持不变。请记住,我使用的是 128 GB 内存的系统。

安装— RAPIDS cuDF

所以现在我们确信 cuDF 是有益的,安装 RAPIDS 最简单的方法就是去站点并使用发布选择器工具检查你需要什么。

对我来说,安装命令是:

conda install -c rapidsai -c nvidia -c conda-forge -c defaults rapids=0.11 python=3.7 cudatoolkit=10.1

对于启动或学习,您也可以从 Google Colab 笔记本开始,它预装了所需的 RAPIDS 环境。

在本帖中,我将使用美国事故数据集来展示 CuDF 数据框架的能力。

使用 CuDF 读取数据

我们做的第一件事是读取数据源。我们可以从本地文件系统读取 cudf 中的数据

import cudf
gdf = cudf.read_csv('US_Accidents_May19.csv')

当我使用pd.read_csv功能读取时,这个命令花费了大约 1 秒,而不是 13 秒

我们也可以使用以下方式从 pandas 数据帧中读取数据:

pdf = pd.read_csv('US_Accidents_May19.csv')
gdf = cudf.DataFrame.from_pandas(pdf)

在这种情况下,我们可以将 cuDF 数据框架转换回 Pandas 数据框架,以便在需要时利用更成熟的 Pandas 生态系统。

pdf = gdf.to_pandas()

数据快照

看到一些数据总是有用的。首先,让我们尝试简单的 Head 和 Tail 命令:

您可以使用简单的headtail命令来指定行数。

# top 5 rows
gdf.head()# top 50 rows
gdf.head(50)# last 5 rows
gdf.tail()# last 50 rows
gdf.tail(50)

您还可以使用以下命令查看简单的数据帧统计信息。

# To get statistics of numerical columns
gdf.describe()

您也可以使用普通函数,如:

print(gdf['TMC'].mean())# no of rows in dataframe
print(len(gdf))# Shape of Dataframe
print(gdf.shape)---------------------------------------------------------------
207.35274265463238
2243939
(2243939, 49)

推荐: 一般用 Jupyter 笔记本工作, 我特别注意让笔记本的前几个单元格包含这些数据的快照 。这有助于我随时看到数据的结构。如果我不遵循这个实践,我会发现我在代码中重复了很多次.head()命令。

处理数据框架中的列

a.选择列

与熊猫一样,CuDF 允许您以两种方式选择列。像df.Title一样使用点运算符,像df['Title']一样使用方括号

我更喜欢第二个版本。为什么?

从长远来看,使用方括号版本会更好,这有几个原因。

  • 如果您的列名包含空格,那么点版本将不起作用。例如,df.Revenue (Millions)不会工作,而df['Revenue (Millions)]’会。
  • 如果您的列名是countmean或任何预定义的函数,它也不会工作。
  • 有时您可能需要在列名上创建一个 for 循环,其中列名可能在变量中。在这种情况下,点符号将不起作用。例如,这是可行的:
colname = 'height'
df[colname]

虽然这不会:

colname = 'height'
df.colname

相信我。省几个字不值得。

建议:停止使用点运算符

b.获取列表中的列名

它也像熊猫一样工作。

columnnames = cuda_df.columns

c.指定用户定义的列名:

有时您想根据自己的喜好更改列名。我不喜欢我的列名中有空格或括号,所以我这样更改它们。

d.设置特定列的子集:

有时,您只需要处理数据帧中的特定列。例如,分离数字列和分类列,或者移除不必要的列。假设在我们的例子中,我们只需要几列

gdf = gdf[['ID', 'Source', 'TMC', 'Severity', 'Start_Time', 'End_Time','Start_Lat', 'Start_Lng', 'End_Lat', 'End_Lng']]

e.查看列类型:

调试时非常有用。如果您的代码抛出一个错误,说您不能添加一个strint,您将希望运行这个命令。

gdf.dtypes

在 CuDF 中应用和 Lambda

applylambda是我在熊猫身上学到的最好的东西。每当我为新的列或过滤器构建复杂的逻辑时遇到困难,我就会使用applylambda。让我们看看是否可以在 CuDF 中使用它们。

a.创建列

您可以通过多种方式创建新列。

如果你想要一个列是列的和或差,你可以使用简单的基本算法。

gdf['Somecol'] = (gdf['TMC'] + gdf['Severity']/10)/2

您也可以使用applymap对系列进行简单应用:

def somefunc(x):
    return x+2
gdf['Somecol'] = gdf['TMC'].applymap(somefunc)

但是有时我们可能需要围绕使用多个列创建新列来构建复杂的逻辑。

举个例子,假设我们要根据 Lats 和 Longs 计算哈弗线距离。

我们怎么做呢?

每当我遇到这样的问题,我就使用apply/lambda。让我首先向你展示我将如何用熊猫来做这件事。这里的许多代码摘自这篇文章。

为了在 CuDF 中做同样的事情,我们必须使用apply_rows对多行应用一个函数。

看看哈弗辛距离函数的结构是如何变化的,以及我们如何用不同的方式来称呼它。注意这个函数以hDistance为参数,所以我们甚至在函数调用中指定了输出。

在后端,它使用 Numba 进行计算。

现在这一切都很好,但有几个警告:

  • 它不接受字符串作为输入,所以如果你想使用字符串列,你不能。这是 CuDF 特性列表中的内容。
  • 只有 CUDA python 支持的一些函数可以使用,而不是所有的 python 函数。支持功能的完整列表在这里。

那么我们为什么要使用它呢?在这个特殊的例子中,熊猫用了 48 秒,而 CuDF 只用了 295 毫秒。这是一个 160 倍的加速。

b.过滤数据帧

熊猫使数据帧的过滤和子集化变得相当容易。您可以使用标准运算符和&,|,~运算符对数据帧进行过滤和子集化。你可以用 cuDF 做同样的事情。

# Single conditiondf_dis_gt_2 = gdf[gdf['hDistance']>2]# Multiple conditions: ANDAnd_df = gdf[(gdf['hDistance']>8) & (gdf['TMC']>200)]# Multiple conditions: OROr_df = gdf[(gdf['hDistance']>8) | (gdf['TMC']>200)]# Multiple conditions: NOTNot_df = gdf[~((gdf['hDistance']>8) | (gdf['TMC']>200))]

很简单的东西。

数据帧上的聚集:groupby

groupby会出现很多次,每当你想聚集你的数据。Pandas 通过groupby功能让您高效地做到这一点,比如:

df.groupby(list of columns to groupby on).aggregate({'colname':func1, 'colname2':func2}).reset_index()

你必须担心提供两个主要的信息。

  • 列列表至groupby on,和
  • 列和要应用于这些列的函数的字典

reset_index()是一个重置数据帧索引的函数。每当我执行 groupby 时,我总是使用这个函数,您可能会认为它是 groupby 操作的默认语法。

有益的是,cuDF 的语法保持不变。

gdf_gby = gdf.groupby(['Traffic_Calming','Sunrise_Sunset']).agg({'TMC':'mean','Severity':'mean'}).reset_index()

告诫: 我先试了一下np.mean这个函数,没用。它只提供基本功能summeanminmax

处理多个数据帧:连接和合并:

a. Concat

有时我们从不同的来源获得数据。或者有人带着多个文件来找你,每个文件都有特定年份的数据。

我们如何从这些多个数据帧中创建单个数据帧?

这里我们将人工创建用例,因为我们只有一个文件。我们首先使用已知的基本过滤操作创建两个数据帧。

severity_lt_3 = gdf[gdf['Severity']<3]
severity_gte_3 = gdf[gdf['Severity']>=3]

这里我们从两个数据帧开始:severity_lt_3 包含严重性小于 3 的事故信息,severity_gte_3 提供严重性大于或等于 3 的事故信息。我们希望创建一个包含两种事故的单一数据框架。

fullseverity = cudf.concat([severity_lt_3,severity_gte_3])

b.合并

您将遇到的大多数数据永远不会出现在单个文件中。其中一个文件可能包含特定电影的评级,另一个文件可能提供电影的投票数。

在这种情况下,我们有两个需要合并的数据帧,这样我们就可以在一个视图中拥有所有的信息。

这里我们将人工创建用例,因为我们只有一个文件。我们首先使用已知的基本列子集操作创建两个数据帧。

accident_times_dataframe = gdf[['ID','Start_Time','End_Time']]
accident_locations_dataframe = gdf[['ID','Start_Lat','Start_Lng','End_Lat','End_Lng']]

我们需要在一个数据框架中包含所有这些信息。我们该怎么做?这个语法也和熊猫一样。

information_df = cudf.merge(accident_times_dataframe,accident_locations_dataframe,on='ID',how='left')

我们为这个合并函数提供了四个属性——第一个 DF、第二个 DF、在哪一列上连接以及连接标准:['left','right','inner','outer']

就计时而言,当我们使用 cudf 进行连接时,我们再次获得了 10 倍的加速。

推荐: 我通常最后总是用left join。你很少需要使用outerright.来连接,实际上无论何时你需要做一个right 连接,你实际上只需要一个左连接,在合并函数中数据帧的顺序是相反的。

结论

CuDF 是朝着正确方向迈出的一步,因为它提供了用于数据处理的 GPU,这占用了数据科学管道中的大量时间。

这里我试着说一下我经常使用的 cuDF 中的一些功能。NVIDIA 的人正在尝试实现更多的东西,所以请看看文档。

虽然熊猫的一些功能还没有实现, 但这不应该阻止我们利用已经为时间关键型应用和 Kaggle 实现的功能。

就我自己而言,在我的数据准备笔记本中,我在 cudf 和 pandas 数据框架之间切换了多次。

每当我有点赶时间的时候,它确实帮了我很大的忙。

我希望这篇文章对你有用,值得你花时间。我试图让这尽可能简单,但你可能总是问我或查看文档中的疑问。

全部代码都发布在我的 Github Repo 中,我在那里保存了我所有帖子的代码。你可以在 Kaggle 找到数据。

另外,如果你想学习更多关于 Python 3 的知识,我想从密歇根大学调出一门关于学习中级 Python 的优秀课程。一定要去看看。

我以后也会写更多这样的帖子。让我知道你对他们的看法。在关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。

面向数据科学家的 PyTorch 最完整指南

原文:https://towardsdatascience.com/minimal-pytorch-subset-for-deep-learning-for-data-scientists-8ccbd1ccba6b?source=collection_archive---------9-----------------------

图片由денисмарчук来自 Pixabay

进行深度学习时需要的 PyTorch 的所有功能。从实验/研究的角度来看。

PyTorch 现在已经成为创建神经网络的事实标准之一,我喜欢它的界面。然而,对于初学者来说,掌握它有点困难。

我记得几年前,在做了大量实验后,我选择了 PyTorch。说实话,我花了很多时间才学会,但我很高兴我从 Keras 转到了 PyTorch 。py torch 具有高度的可定制性和 pythonic 语法,使用起来非常愉快,我会向任何想用深度学习来做一些繁重工作的人推荐它。

因此,在本 PyTorch 指南中, 我将尝试用 PyTorch 减轻一些初学者的痛苦,并介绍一些在用 Pytorch 创建任何神经网络时需要的最重要的类和模块。

但是,这并不是说这只是针对初学者的,因为 我还将谈到py torch 提供的高度可定制性,并将谈到定制图层、数据集、数据加载器和损失函数

如果你想充分发挥 Pytorch 的能力,Exxact Corporation 有一系列基于人工智能的工作站和服务器,起价 3700 美元,配有几个英伟达 RTX 30 系列 GPU,3 年保修和深度学习软件堆栈。

我们去喝点咖啡吧,☕ ️and,开始吧。

如果你想看某一部分,这里有一个目录表。

张量∘1。创建一个张量t5】∘2。张量运算
nn。模块
一言关于图层
数据集和数据加载器
∘ 了解自定义数据集
∘ 了解自定义数据加载器
训练神经网络
损失函数
∘ 自定义损失函数
优化器
使用 GPU

张量

张量是 PyTorch 中的基本构建模块,简单来说,它们是 NumPy 数组,但在 GPU 上。在这一部分,我将列出一些我们在处理张量时最常用的运算。这绝不是你能用张量做的一个详尽的操作列表,但是在进入更令人兴奋的部分之前,理解什么是张量是有帮助的。

1.创建一个张量

我们可以用多种方法创建 PyTorch 张量。这包括从 NumPy 数组转换为张量。下面只是一个小要点和一些例子,但是你可以用张量做更多的事情,就像你可以用 NumPy 数组一样。

2.张量运算

还是那句话,在这些张量上你可以做很多运算。完整的功能列表可在这里找到。

注:py torch 变量是什么?在 Pytorch 的早期版本中,张量和变量曾经是不同的,提供不同的功能,但现在变量 API已弃用,变量的所有方法都与张量一起工作。所以,如果你不知道他们,没关系,因为他们是不需要的,如果你知道他们,你可以忘记他们。

nn。组件

Fernand De Canne 在 Unsplash 上拍摄的照片

有趣的部分来了,我们现在要谈论一些在创建深度学习项目时 Pytorch 中最常用的构造。nn。模块可以让您将深度学习模型创建为一个类。你可以从nn.Module继承,将任何模型定义为一个类。每个模型类必然包含一个__init__程序块和一个forward通道块。

  • __init__部分,用户可以定义网络将要拥有的所有层,但还没有定义这些层如何相互连接。
  • forward传递块中,用户定义数据如何在网络中从一层流向另一层。

因此,简单地说,我们定义的任何网络看起来都像:

这里,我们定义了一个非常简单的网络,它接受大小为 784 的输入,并按顺序通过两个线性层。但是需要注意的是,在定义向前传递时,我们可以定义任何类型的计算,这使得 PyTorch 高度可定制以用于研究目的。例如,在我们疯狂的实验模式中,我们可能使用了下面的网络,在那里我们任意地附加我们的层。在这里,我们将第二个线性层的输出添加到第一个线性层(跳过连接)后再次发送回第一个线性层(老实说,我不知道这将做什么)。

我们还可以检查神经网络前向传递是否有效。我通常这样做,首先创建一些随机输入,并通过我创建的网络传递。

x = torch.randn((100,784))
model = myCrazyNeuralNet()
model(x).size()
--------------------------
torch.Size([100, 10])

关于层的一句话

Pytorch 非常强大,实际上您可以使用nn.Module自己创建任何新的实验层。例如,我们可以创建自己的自定义线性层,而不是使用上面 Pytorch 中的预定义线性层nn.Linear

你可以看到我们如何在nn.Parameter.中包装我们的权重张量,这样做是为了使张量被认为是一个模型参数。来自 PyTorch 文档:

参数是[*Tensor*](https://pytorch.org/docs/stable/tensors.html#torch.Tensor)的子类,当与*Module*一起使用时,它们有一个非常特殊的属性——当它们被指定为模块属性时,它们会被自动添加到参数列表中,并且会出现在*parameters()*迭代器中

正如您稍后将看到的,model.parameters()迭代器将是优化器的一个输入。但稍后会详细介绍。

现在,我们可以在任何 PyTorch 网络中使用这个自定义层,就像任何其他层一样。

但是话又说回来,如果 Pytorch 没有提供许多在各种神经网络架构中经常使用的现成层,它就不会被如此广泛地使用。一些例子是:[nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html#torch.nn.Linear)[nn.Conv2d](https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html#torch.nn.Conv2d)[nn.MaxPool2d](https://pytorch.org/docs/stable/generated/torch.nn.MaxPool2d.html#torch.nn.MaxPool2d)[nn.ReLU](https://pytorch.org/docs/stable/generated/torch.nn.ReLU.html#torch.nn.ReLU)[nn.BatchNorm2d](https://pytorch.org/docs/stable/generated/torch.nn.BatchNorm2d.html#torch.nn.BatchNorm2d)[nn.Dropout](https://pytorch.org/docs/stable/generated/torch.nn.Dropout.html#torch.nn.Dropout)[nn.Embedding](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html#torch.nn.Embedding)[nn.GRU](https://pytorch.org/docs/stable/generated/torch.nn.GRU.html#torch.nn.GRU)/[nn.LSTM](https://pytorch.org/docs/stable/generated/torch.nn.LSTM.html#torch.nn.LSTM)[nn.Softmax](https://pytorch.org/docs/stable/generated/torch.nn.Softmax.html#torch.nn.Softmax)[nn.LogSoftmax](https://pytorch.org/docs/stable/generated/torch.nn.LogSoftmax.html#torch.nn.LogSoftmax)[nn.MultiheadAttention](https://pytorch.org/docs/stable/generated/torch.nn.MultiheadAttention.html#torch.nn.MultiheadAttention)[nn.TransformerEncoder](https://pytorch.org/docs/stable/generated/torch.nn.TransformerEncoder.html#torch.nn.TransformerEncoder)[nn.TransformerDecoder](https://pytorch.org/docs/stable/generated/torch.nn.TransformerDecoder.html#torch.nn.TransformerDecoder)

我已经将所有层链接到它们的来源,在那里您可以阅读关于它们的所有内容,但是为了显示我通常如何试图理解一个层和阅读文档,我将在这里尝试查看一个非常简单的卷积层。

因此,Conv2d 层需要一个高度为 H、宽度为 W 的图像作为输入,并带有Cin通道。现在,对于 convnet 中的第一层,in_channels的数量是 3(RGB),out_channels的数量可以由用户定义。最常用的kernel_size是 3x3,常用的stride是 1。

为了检查一个我不太了解的新图层,我通常会尝试查看该图层的输入和输出,如下图所示,我将首先初始化该图层:

conv_layer = nn.Conv2d(in_channels = 3, out_channels = 64, kernel_size = (3,3), stride = 1, padding=1)

然后通过它传递一些随机输入。这里 100 是批量大小。

x = torch.randn((100,3,24,24))
conv_layer(x).size()
--------------------------------
torch.Size([100, 64, 24, 24])

因此,我们根据需要从卷积运算中获得输出,并且我有足够的信息来说明如何在我设计的任何神经网络中使用这一层。

数据集和数据加载器

在训练或测试时,我们如何将数据传递给我们的神经网络?我们肯定可以像上面那样传递张量,但 Pytorch 也为我们提供了预先构建的数据集,使我们更容易将数据传递给我们的神经网络。您可以查看 torchvision.datasets 和 torchtext.datasets 提供的完整数据集列表。但是,为了给出数据集的具体示例,假设我们必须使用文件夹将图像传递到图像神经网络,该文件夹包含以下结构的图像:

data
    train
        sailboat
        kayak
        .
        .

我们可以使用torchvision.datasets.ImageFolder数据集获得如下示例图像:

这个数据集有 847 幅图像,我们可以使用索引来获取图像及其标签。现在我们可以使用 for 循环将图像逐个传递给任何图像神经网络:

for i in range(0,len(train_dataset)):
    image ,label = train_dataset[i]
    pred = model(image)

但那不是最优的。我们想做批处理。 我们其实可以多写一些代码,批量追加图片和标签,然后传递给神经网络。但是 Pytorch 为我们提供了一个实用的迭代器torch.utils.data.DataLoader来实现这一点。现在我们可以简单地将我们的train_dataset包装在数据加载器中,我们将获得批量而不是单个的例子。

train_dataloader = **DataLoader**(train_dataset,batch_size = 64, shuffle=True, num_workers=10)

我们可以简单地使用批处理进行迭代:

for image_batch, label_batch in train_dataloader:
    print(image_batch.size(),label_batch.size())
    break
------------------------------------------------------------------
torch.Size([64, 3, 224, 224]) torch.Size([64])

所以实际上,使用数据集和数据加载器的整个过程变成了:

在我之前关于使用深度学习进行图像分类的博客文章中,你可以在这里看看这个具体的例子。

这很棒,Pytorch 确实提供了很多现成的功能。但是 Pytorch 的主要功能来自其巨大的定制性。如果 PyTorch 提供的数据集不适合我们的用例,我们也可以创建自己的自定义数据集。

了解自定义数据集

为了编写自定义数据集,我们可以利用 Pytorch 提供的抽象类torch.utils.data.Dataset。我们需要继承这个Dataset类,并需要定义两个方法来创建自定义数据集。

  • __len__:返回数据集大小的函数。在大多数情况下,这个代码很容易编写。
  • __getitem__:将索引i作为输入并返回索引i处的样本的函数。

例如,我们可以创建一个简单的自定义数据集,从文件夹中返回一个图像和一个标签。请注意,大多数任务都发生在__init__部分,我们使用glob.glob来获取图像名称并进行一些常规预处理。

另外,请注意,我们在 __getitem__方法中一次打开一个图像,而不是在初始化时打开。在__init__中没有这样做,因为我们不想把所有的图像都加载到内存中,只需要加载需要的图像。

我们现在可以像以前一样使用这个数据集和实用程序Dataloader。它就像 PyTorch 提供的前面的数据集一样工作,但是没有一些实用函数。

了解自定义数据加载器

这一部分有点高深,在阅读这篇文章时可以跳过,因为在很多情况下都不需要。但是我在这里添加它是为了完整性。

假设您希望向处理文本输入的网络提供批处理,只要批处理中的序列大小保持不变,网络就可以接收任意长度的序列。例如,我们可以有一个可以处理任意长度序列的 BiLSTM 网络。如果你现在不理解其中使用的图层,那也没关系;只知道它可以处理大小可变的序列。

该网络期望其输入为形状(batch_sizeseq_length),并与任何seq_length一起工作。我们可以通过向模型传递两个不同序列长度(10 和 25)的随机批次来检查这一点。

model = BiLSTM()
input_batch_1 = torch.randint(low = 0,high = 10000, size = (100,**10**))
input_batch_2 = torch.randint(low = 0,high = 10000, size = (100,**25**))
print(model(input_batch_1).size())
print(model(input_batch_2).size())
------------------------------------------------------------------
torch.Size([100, 1])
torch.Size([100, 1])

现在,我们希望为这个模型提供紧密的批次,这样每个批次都具有基于批次中最大序列长度的相同序列长度,以最小化填充。这有一个额外的好处,使神经网络运行更快。事实上,这是在卡格尔举行的 Quora 无诚意挑战赛中获胜的方法之一,在那里运行时间至关重要。

那么,我们该怎么做呢?让我们先编写一个非常简单的自定义数据集类。

此外,让我们生成一些随机数据,我们将使用这个自定义数据集。

一个随机序列和标签的例子。序列中的每个整数对应于句子中的一个单词。

我们现在可以使用自定义数据集:

train_dataset = CustomTextDataset(X,y)

如果我们现在尝试在这个数据集上使用带有batch_size > 1 的 Dataloader,我们将会得到一个错误。这是为什么呢?

train_dataloader = DataLoader(train_dataset,batch_size = 64, shuffle=False, num_workers=10)
for xb,yb in train_dataloader:
    print(xb.size(),yb.size())

发生这种情况是因为序列具有不同的长度,而我们的数据加载器期望我们的序列具有相同的长度。请记住,在前面的图像示例中,我们使用变换将所有图像的大小调整为 224,因此我们没有遇到这个错误。

那么,我们如何遍历这个数据集,使得每一批都有长度相同的序列,但不同的批可能有不同的序列长度呢?

我们可以在 DataLoader 中使用collate_fn参数,让我们定义如何在特定的批处理中堆叠序列。要使用它,我们需要定义一个函数,它将一个批处理作为输入,并根据批处理中的max_sequence_length返回(x_batchy_batch)填充的序列长度。我在下面的函数中使用的函数是简单的数字运算。此外,该函数被适当地注释,以便您可以理解发生了什么。

我们现在可以将此collate_fn与我们的数据加载器一起使用,如下所示:

train_dataloader = DataLoader(train_dataset,batch_size = 64, shuffle=False, num_workers=10,**collate_fn** **=** **collate_text**)for xb,yb in train_dataloader:
    print(xb.size(),yb.size())

请注意,这些批次现在具有不同的序列长度

这一次它将工作,因为我们已经提供了一个定制的collate_fn.,并看到现在这些批次具有不同的序列长度。因此,我们将能够像我们希望的那样,使用可变的输入大小来训练我们的 BiLSTM。

训练神经网络

我们知道如何使用nn.Module.创建神经网络,但是如何训练它呢?任何需要训练的神经网络都有一个类似于下图的训练循环:

在上面的代码中,我们运行五个时期,并且在每个时期中:

  1. 我们使用数据加载器遍历数据集。
  2. 在每次迭代中,我们使用model(x_batch)向前传递
  3. 我们使用loss_criterion计算损失
  4. 我们使用loss.backward()调用反向传播损失。我们根本不用担心梯度的计算,因为这个简单的调用为我们做了所有的事情。
  5. 使用optimizer.step()采取优化步骤来改变整个网络中的权重。这就是使用在loss.backward()调用中计算的梯度来修改网络权重的地方。
  6. 我们通过验证数据加载器来检查验证分数/指标。在进行验证之前,我们使用model.eval().将模型设置为评估模式。请注意,我们不会在评估模式下反向传播损耗。

到目前为止,我们已经讨论了如何使用nn.Module创建网络,以及如何通过 Pytorch 使用定制数据集和数据加载器。所以让我们来谈谈损失函数和优化器的各种可用选项。

损失函数

Pytorch 为我们最常见的任务提供了各种损失函数,比如分类和回归。一些最常用的例子是[nn.CrossEntropyLoss](https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html#torch.nn.CrossEntropyLoss)[nn.NLLLoss](https://pytorch.org/docs/stable/generated/torch.nn.NLLLoss.html#torch.nn.NLLLoss)[nn.KLDivLoss](https://pytorch.org/docs/stable/generated/torch.nn.KLDivLoss.html#torch.nn.KLDivLoss)[nn.MSELoss](https://pytorch.org/docs/stable/generated/torch.nn.MSELoss.html#torch.nn.MSELoss).你可以阅读每个损失函数的文档,但是为了解释如何使用这些损失函数,我将通过[nn.NLLLoss](https://pytorch.org/docs/stable/generated/torch.nn.NLLLoss.html#torch.nn.NLLLoss)的例子

NLLLoss 的文档非常简洁。如中所示,此损失函数用于多类分类,并基于文档:

  • 预期的输入需要大小为(batch_size x Num_Classes ) —这些是我们创建的神经网络的预测。
  • 我们需要输入中每个类的对数概率——为了从神经网络中获得对数概率,我们可以添加一个LogSoftmax层作为网络的最后一层。
  • 目标需要是类别数量在(0,C-1)范围内的类别的张量,其中 C 是类别的数量。

因此,我们可以尝试将这个损失函数用于简单的分类网络。请注意最后一个线性图层后的LogSoftmax图层。如果你不想使用这个LogSoftmax层,你可以直接使用[nn.CrossEntropyLoss](https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html#torch.nn.CrossEntropyLoss)

让我们定义一个随机输入传递到我们的网络来测试它:

# some random input:X = torch.randn(100,784)
y = torch.randint(low = 0,high = 10,size = (100,))

并通过模型得到预测:

model = myClassificationNet()
preds = model(X)

我们现在可以得到损失为:

criterion = nn.NLLLoss()
loss = criterion(preds,y)
loss
------------------------------------------
tensor(2.4852, grad_fn=<NllLossBackward>)

定制损失函数

定义你的自定义损失函数也是小菜一碟,只要你在损失函数中使用张量运算,你应该没问题。例如,这里是customMseLoss

def customMseLoss(output,target):
    loss = torch.mean((output - target)**2)     
    **return** loss

你可以像以前一样使用这个自定义损耗。但是请注意,我们这次没有使用 criterion 实例化损失,因为我们已经将它定义为一个函数。

output = model(x)
loss = customMseLoss(output, target)
loss.backward()

如果我们愿意,我们也可以用nn.Module把它写成一个类,然后我们就可以把它当作一个对象来使用。下面是一个 NLLLoss 自定义示例:

优化者

一旦我们使用loss.backward()调用得到梯度,我们需要采取一个优化步骤来改变整个网络中的权重。Pytorch 使用torch.optim模块提供了各种不同的现成优化器。比如:[torch.optim.Adadelta](https://pytorch.org/docs/stable/optim.html#torch.optim.Adadelta)[torch.optim.Adagrad](https://pytorch.org/docs/stable/optim.html#torch.optim.Adagrad)[torch.optim.RMSprop](https://pytorch.org/docs/stable/optim.html#torch.optim.RMSprop)以及应用最广泛的[torch.optim.Adam](https://pytorch.org/docs/stable/optim.html#torch.optim.Adam).

要使用 PyTorch 中最常用的 Adam 优化器,我们可以简单地用以下代码实例化它:

optimizer **=** torch.optim.Adam(model.parameters(), lr=0.01, betas=(0.9, 0.999))

然后在训练模型时使用optimizer**.**zero_grad()optimizer.step()

我不讨论如何编写定制优化器,因为这是一个不常见的用例,但如果你想有更多的优化器,请查看 pytorch-optimizer 库,它提供了许多其他在研究论文中使用的优化器。此外,如果你想创建自己的优化器,你可以使用 PyTorch 或py torch-optimizer中实现的优化器的源代码来获得灵感。

来自 pytorch-optimizer 库的其他优化器

使用 GPU/多个 GPU

到目前为止,我们所做的一切都是在 CPU 上进行的。如果你想使用 GPU,你可以使用model.to('cuda')将你的模型放到 GPU 中。或者想用多个 GPU,可以用nn.DataParallel。这里有一个实用函数,它检查机器中的 GPU 数量,并在需要时使用DataParallel自动设置并行训练。

我们唯一需要改变的是,如果我们有 GPU,我们将在训练时将数据加载到 GPU。这就像在我们的训练循环中添加几行代码一样简单。

结论

Pytorch 用最少的代码提供了很多可定制性。虽然一开始可能很难理解整个生态系统是如何用类来构建的,但最终,它是简单的 Python。在这篇文章中,我试着分解了你在使用 Pytorch 时可能需要的大部分内容,我希望读完这篇文章后对你来说更有意义。

你可以在我的 GitHub repo 上找到这篇文章的代码,我在这里保存了我所有博客的代码。

如果你想学习更多关于 Pytorch 的基于课程的结构,看看 IBM 在 Coursera 上的深度神经网络与 PyTorch 课程。还有,如果你想了解更多关于深度学习的知识,我想推荐这门关于计算机视觉中的深度学习的优秀课程

谢谢你的阅读。将来我也会写更多初学者友好的帖子。在关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter@ mlwhiz联系

此外,一个小小的免责声明——这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。

** [## 通过我的推荐链接加入 Medium-Rahul Agarwal

作为一个媒体会员,你的会员费的一部分给了你所阅读的作家,你可以在…上看到所有的故事

mlwhiz.medium.com](https://mlwhiz.medium.com/membership)**

假装你熟悉伯特的最低要求

原文:https://towardsdatascience.com/minimal-requirements-to-pretend-you-are-familiar-with-bert-3889023e4aa9?source=collection_archive---------33-----------------------

通过将元数据从文本中分离出来,BERT 将使你的项目更有价值和创造性

杰里米·毕晓普在 Unsplash 上的照片

一波又一波对数据科学技术的炒作日复一日地高涨。你们中的许多人可能已经厌倦了通过大大小小的宣传来为一项新的提议带来解决方案,或者在会议中假装自己熟悉新的人工智能技术。本文的目标是没有强大数据科学背景的管理人员、初级数据科学家和对 NLP 感兴趣的开发人员,目标是帮助他们用最少的知识熟悉 BERT,并问“我们能在这个项目中使用 BERT 吗?”在头脑风暴会议中聪明地。

目录

  1. 为什么我们现在要学习 BERT 并使用它?
  2. 伯特是如何深入浅出地工作的?
  3. BERT 给你的项目带来了什么价值?
  4. 我们在哪里可以了解更多关于伯特的信息?

1.为什么我们现在要学习 BERT 并使用它?

由于炒作和有偏见的成功故事,推迟学习数据科学领域的新技术有时是一个好策略。先说我关于“现在”的简短回答。BERT 是由谷歌在 2018 年开发并发布的,经过两年的时间,围绕这种方法的开源社区已经成熟,我们可以使用他们开发的令人惊叹的工具箱。我们应该了解 BERT,因为它缓解了模型训练效率方面的问题,不像 Culurciello 在RNN/LSTM 的陨落中讨论的传统递归神经网络。我们应该使用 BERT,因为得益于 Hugging Face 的框架,它很容易微调和使用模型,并且我们可以通过对您的代码进行小的修改,从 BERT 切换到其他最先进的 NLP 模型——有时只需要几行修改。

2.伯特是如何深入浅出地工作的?

BERT 的正式名称有点长,它代表来自变压器的双向编码器表示。先说最后一个词,这是最重要的。 Transformer 是一种神经网络架构,BERT 及其衍生产品继承了类似的架构。与递归神经网络不同,变压器不需要按顺序处理输入序列。这意味着 Transformer 在处理句子的中间或结尾之前,不需要处理句子的开头。另一方面,RNN 需要处理订单中的输入;因此,它产生了瓶颈。这个特性给了 Transformer 在模型训练期间运行并行化更多的自由。

那么,我们来看第一个词双向。如果体系结构是定向的,那么它要么从左到右要么从右到左处理输入。BERT 摆脱了按顺序处理输入的魔咒,并且 BERT 可以根据一个单词的所有环境来了解它的上下文。这种方法被称为掩蔽语言模型,不同于通过预先给定单词作为输入来预测下一个单词来创建语言模型的传统方法。

来自 BERT 的剩余部分是编码器表示。在开始解释之前,让我问一个问题。你认为什么时候一个人很好地理解了一句话?我认为仅仅理解一个句子中词汇的含义是不够的。一个合理的答案是当某人理解一个句子的上下文时。那么,如何判断一个人是否理解上下文呢?对我来说,一个可测量的、介绍性的方法是某人是否理解指示代词的来源,如句子中的“它”、“这个”或“那个”。BERT 包括编码器来理解单词的上下文。编码器的架构彼此相同,每个都由两个组件组成:自关注和前馈神经网络。除了这些因素,我将只关注自我关注。

让我用一句“动物没有过马路是因为太累了。”展示自我注意机制如何解释“它”我们知道“它”指的是这句话中的“动物”,并且它被 BERT 预训练模型正确地解释如下。

来源:杰伊·阿拉姆的《变形金刚》

现在,我们知道自我关注有能力理解单词之间的关系,但下一个问题是它解释得有多好。为了回答这个问题,我把原来的句子修改为“动物没有过马路是因为”而不是“太累了。”正如你在下面的图片中看到的,最强的联系存在于“动物”和“它”之间,这与我的预期不同。

图片由作者通过谷歌托管的 Tensor2Tensor 笔记本修改原文。

每个伯特的编码器都有多个自我关注头,我的期望是其中一个自我关注头会捕捉到“它”和“街道”之间的关系,因为“街道”太宽了。尽管 BERT 有能力理解上下文,但对于相对简单的句子,它还不是完美的。作为免责声明,我使用预训练的 BERT 验证了我的假设,但其他 BERT 衍生产品会表现得更好,因为训练数据集的大小增加了,其架构也有所改善。如果你有兴趣了解自我关注和多头关注机制是如何一步一步工作的,请阅读杰伊·阿拉姆的《图解变形金刚》。

3.BERT 给你的项目带来了什么价值?

BERT 的成功应用是文本分类、问题回答和情感分析。这些成果还不够成熟,但是我们也可以将 BERT 应用于命名实体识别和文本摘要。关于自然语言生成,最成功的模型是微软开发的基于转换器的生成语言模型图灵-NLG 。如果你需要从文本中梳理出模式,比如电子邮件、文档和客户评论,我建议在实验阶段应用 BERT 及其衍生工具。

我已经列出了 BERT 的常见应用,BERT 肯定是一个很好的方法,但请不要搜索一种方法可以解决的项目,因为 BERT 或其他 NLP 模型的真正价值是为业务部门及其客户创建新的元数据。像电子邮件分类这样的项目作为 BERT 的应用是直观的,但是对于许多业务问题来说,电子邮件的类别可能是中间产品而不是最终产品。在实践中,这种中间产品将通过与传统方法相结合,为您的项目带来更多的价值。

例如,如果您对客户流失分析感兴趣,您可以使用 BERT 从客户和代理之间的文本通信中提取元数据,例如客户情绪、代理对客户的响应质量以及问题类别。此外,您可以将所有或部分这些元数据与其他传统元数据相结合,例如交互的新近性和频率、代理的响应时间以及客户花费的金额。除了客户流失分析之外,我们还可以进行营销分析,根据客户各自面临的分类问题或挑战的组合,建议交叉销售或追加销售,从而使用 BERT 提供的元数据提高客户满意度。当然,我们可以利用客户报告的这些问题组合,通过创建针对故障的假设来改进自己产品的质量/功能。然后,我们可以跟踪分类问题的分布随时间的变化,以测试所提出的假设是否正确。我相信,通过以创造性的方式将元数据连接成点,我们可以为业务部门和客户提供更高的价值。我不会在本文中提及,但由于解决方案需要复杂的开发和操作流程,因此 MLOps 或 ML 管道的概念变得更加重要。

4.我们在哪里可以了解更多关于伯特的信息?

让我分享这些链接来加深你对 BERT 的理解,因为我的帖子只涉及了最基本的概念。

面向经理、开发人员和初级数据科学家

  1. 杰伊·阿拉莫的《变形金刚图》

这是我最喜欢的博文,也是最好的下一步。如果你对线性代数感到不舒服,你可以跳过这篇文章中间的矩阵计算,以大局为重。

2.深度学习 2019 —杰瑞米·霍华德的图像分类

该系列没有涵盖 BERT,但仅观看第一个视频就可以帮助您体验深度学习的现代框架,以及与四年前使用 TensorFlow 不同,微调模型是多么容易。此外,如果你对课程的数量感到不知所措,你不需要观看所有的视频,因为课程 1、2 和 4 需要通过图像分类和 NLP,这是需要覆盖的最小领域。

面向开发人员和初级数据科学家

3.杰伊·阿拉姆的《word 2 vec》

这是杰伊·阿拉姆的又一篇好文章。我很难理解高维度的单词嵌入,比如 256 或 512。这篇文章通过展示许多可视化的例子,让我了解了二维单词嵌入的概念。

4.克里斯·麦考密克伯特研究系列

我更喜欢 Jay Alammer 的博客来理解这些概念,因为它具有创造性的视觉表现。但是,如果您喜欢从视频和代码中学习,本系列将更适合您,因为 Chris McCormick 使用 Jupyter 笔记本来展示如何实际实现这些概念的示例。

交互式可视化中重叠标签的最小化

原文:https://towardsdatascience.com/minimizing-overlapping-labels-in-interactive-visualizations-b0eabd62ef0?source=collection_archive---------47-----------------------

一个非常有效的,贪婪的自动标签放置算法,具有惊人的效果。

美国每个州每天新新冠肺炎病例的可视化,没有标签放置算法。

用户控制和实时数据可视化最具挑战性的领域之一是标签放置。在我的许多可视化中,我试图设计标签不可能重叠的可视化——完全避免这个挑战性的问题——但在我最近的可视化中,这不是一个选项。

我的新冠肺炎疫情的 91-DIVOC 可视化允许用户通过使用 d3.js 库构建的交互式可视化来查看来自 T2 约翰霍普金斯大学的最新冠状病毒数据。由于可视化使用每天更新多次的数据,再加上用户能够浏览数据并创建超过 10 亿个不同的可视化,一切都必须以编程方式呈现。

有多种约束条件,这些约束条件对于许多线形图可视化来说是常见的,它们组合在一起使得可读标签具有挑战性:

  • 可能有数百条不同的线,都在同一个 x 位置结束。
  • 有些行比其他行更重要。在 91-DIVOC 可视化中,用户可以“突出显示”一个或多个国家,线条变暗、变粗,标签变大。
  • 大多数用户使用移动设备,限制了可用的计算资源。

在不使用任何标签放置的情况下,具有几个突出显示的状态的每日新新冠肺炎病例的可视化显示了多个不可读的突出显示的标签和更多不可读的非突出显示的标签。

常用方法:力定向图

具有三个标签的力定向图标签放置算法的仿真步骤。第三步,弗吉尼亚和密西西比的标签被分开。

解决标签放置的一个常见方法是使用 d3.js 的“力”组件,它实现了一个力定向图。力定向图是一种基于物理的模拟,其中所有元素相对于其他元素都具有“吸引力”或“排斥力”。在标签放置算法的情况下,每个元素都被给予来自其他元素的轻微排斥力,导致模拟在可能创建可读标签时将元素相互推开。当模拟达到稳定的最终状态时,结果非常好,这是一种可靠的方法。

不幸的是,力有向图。力定向图的运行时间与输入 O(n)成立方增长,并且元素密集的区域在收敛之前需要大量的计算能力。在使用力定向图标签放置算法的早期实验中,花费在运行力定向图上的时间比花费在处理和渲染可视化的整个剩余部分上的时间更多。是时候寻求新的解决方案了。

快速解决方案:“渲染或微移”

随着令人沮丧的缓慢力导向图的失败,关键是任何解决方案的运行时间最短。为了尽可能节省处理时间,每个标签的放置都归结为一个决定,即“渲染”或“微移”:

  1. 如果该区域中当前没有呈现标签,呈现标签。这个决定是即时的,位置永远不会改变。
  2. 如果另一个先前渲染的标签已经被渲染并与新标签重叠,轻推该标签以尝试找到更好的位置。

“渲染或微移”标签放置策略,显示了三个标签的放置,包括“密西西比”标签的微移。

“轻推”标签的过程试图将标签放置到高于或低于预定位置的标签高度。如果没有找到合适的位置,标签将在其原始位置呈现,从而创建重叠的标签。(将标签推离预期位置往往会导致数据和数据标签之间的视觉不连续。)

由于标签仅被考虑一次,该算法在线性时间 O(n)中运行,并且将被描述为标签放置的“贪婪算法”。

结果

在实现了这个算法之后,结果对于算法的速度来说是惊人的。下面,你可以看到的两个高亮标签都是可读的40 多个非高亮标签也是可读的。

美国每个州每天新新冠肺炎病例的可视化,带有“渲染或摆动”标签放置。

当考虑数据可视化中的标注放置时,考虑不需要全球定位的计算成本低廉的解决方案。虽然这种解决方案不能确保每个标签都不会重叠,但它极大地改善了简单的标签放置,并极大地提高了具有几十或几百个标签的任何可视化的可读性。

(你可以在我的 visualization 91-DIVOC #01:“新冠肺炎指数传播的交互式可视化”上使用这种标签放置算法查看可视化效果。)

通过自然语言处理减少收件箱中的销售邮件

原文:https://towardsdatascience.com/minimizing-sales-emails-in-my-inbox-with-natural-language-processing-38296b562da7?source=collection_archive---------61-----------------------

每天我打开收件箱都会看到几十封我不认识的人发来的未读邮件,要求给我 15 分钟时间,让他们帮我解决这个或那个问题。

2011 年,亚伦·罗斯(Aaron Ross)的书《可预测的收入》(forecast Revenue)推广了这一概念,向 B2B 潜在客户发送冰冷的电子邮件,要求会面,这已经成为全球 B2B SaaS 公司的主要增长策略。事实上,秘密已经泄露,每个人(显然还有他们的母亲)都在发送潜在客户邮件来招揽生意。(例如,参见 30 个保证建立关系的销售潜在客户电子邮件模板。)而且理由很充分——这很有效!

那么,当每个 B2B 公司向世界各地的每个潜在客户发送电子邮件时,会发生什么?我们的收件箱变得更加嘈杂,让我们更难专注于重要的电子邮件。

可预测的收入带来了什么?

即使是强大的电子邮件服务,如 Gmail 和 Outlook,也不会将这些 SDR 电子邮件归类为垃圾邮件。这是可以理解的,因为特别提款权不是在兜售伟哥、要求资金转移等等。Gmail 的“推广”过滤器呢?没有帮助。销售代表经常通过销售支持技术使用他们公司的 Gmail 或 Outlook 电子签名发送电子邮件,例如 Outreach,这似乎绕过了常见的“简讯”过滤器。

如果不加控制,SDR 电子邮件将继续入侵收件箱,降低相关内容的关注度。

回收收件箱

为了应对这一困境— ,但实际上是作为开发我的 NLP、Docker 和微服务技能的借口, —我设计、编码并部署了一个 SDR 电子邮件检测器,可通过 API 端点访问。

该系统通过 OAuth 连接到用户的 Gmail,确定收到的电子邮件是否是from_SDR,并将这些电子邮件移动到一个特殊的文件夹中“稍后阅读”如果电子邮件不是from_SDR,那么它会将分类邮件留在主收件箱中。

构建 SDR 电子邮件检测器

垃圾邮件检测与我的项目最为相似。这里有许多方法,从使用“单词包”计数矢量化的简单朴素贝叶斯方法到使用双向递归神经网络进行单词嵌入的复杂深度学习模型。尽管我尝试了上述所有方法,但本文将重点关注使用 TF-IDF 矢量化的线性 SVM 实现。

获取培训数据

无论采用哪种方法,应用机器学习最重要的部分是(1)获得良好的数据,以及(2)为训练和测试准备数据。

获取训练数据相对简单。我在收件箱里过滤了与销售相关的关键词,查看了数千封电子邮件。如果邮件来自销售开发代表(SDR),我会在邮件中添加标签SDR。大约八个小时后,我在收件箱里标记了 1000 封 SDR 邮件:

然后,我从收件箱里取出了 4000 封非 SDR 电子邮件。我故意对非 SDR 电子邮件进行过采样,以再现现实世界中发生的类别不平衡,同时注意到需要有足够的SDR信号(例如,我的数据的 20%),以便我的分类器学习一些有意义的东西。

接下来,我启动了 Google Colab 笔记本电脑,将电子邮件下载到熊猫数据框中。

service对象创建一个到 Gmail API 和目标收件箱的连接。(注意,您需要设置一个谷歌云平台账户来注册一个应用程序并获得一个client_secret.json。)

然后,我编写了一个函数来获取大量与查询匹配的消息:

上面的函数返回了一个邮件 id 数组,该数组必须从 Gmail API 中迭代获取。为此,我编写了以下函数,该函数调用每条消息并解析正文、发件人、主题、日期/时间和其他有趣的字段。假设能够查询标签(例如,label:SDR来检索我收件箱中的所有 SDR 电子邮件),我提前知道电子邮件数组是y_true=1还是y_true=0,这是我的函数用来标记 Dataframe 中每一行的参数:

但是还有一个函数需要定义,这是迄今为止最棘手的:get_email_data(message_id)。这一重要功能将 Gmail 编码的回复转换成可以解析并保存到数据帧中的文本。这绝不是完美的,因为我来是为了了解的电子邮件有多复杂多样。您将注意到正确解析电子邮件所需的嵌套逻辑和多部分遍历,因为如果电子邮件包含附件、HTML、明文和其他边缘情况,它们的编码会有所不同。

最后,我导入了pickle来保存我的数据帧,这帮助我节省了 API 调用和重新获取相同数据的时间:

基础工作完成后,我决定做一些功能工程,如果收件箱用户从未给发件人发送过邮件,就添加一个等于 1 的cold_contact标志:

我还试验了其他特性(比如 sender/return_path 不匹配,以及统计之前 90 天、60 天、30 天内发送的电子邮件数量等等),但是我将省去您查看这些代码的麻烦,因为它们并没有显著提高我的模型的性能。

以下是我的数据框架中的一些示例行和列:

使用自然语言处理训练 SDR 电子邮件检测器

有了电子邮件数据,我必须将电子邮件处理成一种便于分类的格式。如上所述,有许多方法可以做到这一点,我选择使用术语频率-逆文档频率矢量化来表示每封电子邮件的正文。

引用单页教程的话:

通常,tf-idf 权重由两项组成:第一项计算归一化项频率(tf),aka。单词在文档中出现的次数,除以该文档中的总单词数;第二项是逆文档频率(IDF ),计算为语料库中文档数量的对数除以特定术语出现的文档数量。
。。。
考虑包含 100 个单词的文档,其中单词 cat 出现 3 次。cat 的频率项(即 tf)则为(3 / 100) = 0.03。现在,假设我们有 1000 万个文档,其中 1000 个文档中出现了单词 cat。然后,逆文档频率(即 idf)计算为 log(10,000,000 / 1,000) = 4。因此,tf-idf 重量是这些量的乘积:0.03 * 4 = 0.12。

将每封电子邮件想象成矩阵中的一行,其中电子邮件的每个单词是一个特征(例如,一列),其值由上面的公式给出。例如:

问题来了:我要存储(即内存问题)和分析(即 CPU 时间)数百万字/列的数据吗?不。诀窍是预处理电子邮件,这样我就能得到更少、更高的信号词。

预处理电子邮件文本

Jay Patel 提供了关于如何将原始文本转换为机器学习算法可以矢量化和消费的形式的深度报道和示例。我跟随他的领导,编写了这些函数来删除 HTML、标点符号和低信号词:

您会注意到上面代码中的lemmatizer。这个概念超出了这篇文章的范围,但是值得一提的是,lemma tion是减少书面文本维数的另一种方法,以便运行运行运行运行运行等。,都简单地用一个词来表示:

为了将上面的功能付诸实践,我使用了 Sam T 在这篇文章中描述的 ColumnTransformers。在这里,我定义了一个转换器,它接受一个带有“body”列的数据帧,并使用上面确定的清理函数处理每一行:

重要的是,这个转换器使用remainder='passthrough'来保存和传播管道中的其他数据帧列。清理邮件正文变得轻而易举。我只需要运行功能clean_text_CT_passthrough.transform(some_dataframe)

但是更好的是,我可以使用 SKLearn 管道和 ColumnTransformers 链接多个预处理步骤。例如,在此代码片段中,我重新调整了 dataframe 的单个列,使其与 TF-IDF 矢量化计算的值范围成比例:

例如,在一个版本中,我尝试添加了一个功能,可以计算每封电子邮件中的字数。虽然文本矢量化是在 0 →1 的数量级上,但字数在 0 → 1,500 的范围内,并且在没有重新调整的情况下,该模型由于过分强调字数特征而失败。与其他列一样,上面的函数将字数重新调整到 0 → 1 的范围。

最后,我执行了单词矢量化,并将这些列组合成一个单独的向量,以便进行分类。

得到的对象classification_pipe.fit.predict和其他你期望从 SKLearn 分类器中得到的函数。这些是可用的,因为我在第 8–9 行定义了一个分类器,并在第 24 行将其添加到管道中。

把所有的放在一起

我从存储的 pickle 中加载了电子邮件数据,并将身体重铸为string。接下来,我创建了一个训练/测试数据分割,将stratify=y_df.y_true传递给train_test_split函数,这样我的分割将使用类似的类不平衡作为我的目标变量进行采样。然后,我使用训练数据调用了classification_pipe.fit函数。最后,我使用 F1 分数和其他指标评估了我的模型的性能:

以下是优化文本预处理、TF-IDF 矢量器和 SVM 参数后我的模型的结果:

F1 得分:98.34%
AP: 95.06%
精度:97.09%
召回率:97.40%

尽管总有进一步优化的空间,但鉴于 F1 的高分(98.34)和我起步时的显著进步(83.44),我觉得这是一个很好的停止点。

后续步骤:部署模型

为了构建本文开头描述的系统,我的 Gmail 小程序应该通过 API 调用这个模型。这是本系列下一篇文章的重点。在那里,我将我的模型容器化,部署到 AWS ECR,并使用 Chalice 构建一个 web 可访问的 API 端点。

为了避免上面冗长的代码片段,我把大部分的import语句放在了这个要点中。如果您运行这里描述的代码,请务必检查并包含这些内容。

让这个帖子成为可能,要感谢的人太多了。以下是几个对我的冒险有重大指导意义的例子: Sie Huai Gan (关于 Niaves Bayes 和深度学习垃圾邮件分类器), Paul Blankley (关于评估指标), Mikko Ohtamaa (关于电子邮件解析), Alain Spineux ( 解释电子邮件部分),Zac Stewart( Mathieu Blondel(在上使用管道、转换器和 GridSearchCV ), Sam T (在管道上使用自定义转换器), Ken Syme (在 ColumnTransformer 中组合文本和表格数据), Jay M. Patel (在 NLP 的文本预处理上), Ryan Cranfill (在管道中添加自定义函数预处理文本 Michelle Fullwood (关于管道和特征联合),以及 Benjamin Bengfort , Rebecca Bilbro , Tony Ojeda (关于通过管道进行文本矢量化)。 感谢大家花时间分享你们的知识!

最小化成本函数:梯度下降

原文:https://towardsdatascience.com/minimizing-the-cost-function-gradient-descent-a5dd6b5350e1?source=collection_archive---------2-----------------------

梯度下降算法在 python 中是如何工作和实现的?

Gabriel 在 Unsplash 上拍摄的照片

想象你在一座山顶上,想要下山。可能有许多可用的路径,但您希望以最少的步数到达底部。你如何能想出一个解决方案?为了回答这个问题,我们将解决梯度下降问题。

梯度下降是最简单的算法之一,不仅用于线性回归,而且用于机器学习的许多方面。几个想法建立在这个算法上,它是机器学习的一个关键和基础的部分。

这个音符的结构:

  • 梯度下降
  • 将梯度下降应用于线性回归
  • 梯度下降变体
  • 案例研究

这是一张很长的便条。喝杯咖啡或茶,我们开始吧。

快速回顾一下我上一篇笔记:

上一篇笔记的评论

所以我们有了假设函数,我们有了一种方法来衡量它与数据的吻合程度。我们现在需要估计假设函数中的参数θ0 和θ1。

这里是问题设置。假设我们有一个函数 J,为θ0,θ1。我们想在函数 J 的θ0 和θ1 上最小化(θ0,θ1)。事实证明梯度下降是解决这个普遍问题的算法。我们将从θ0 和θ1 的一些初始猜测开始。它们是什么并不重要,但一个常见的选择是我们把θ0 设为 0,θ1 设为 1。在梯度下降中,我们要做的是不断改变θ0 和θ1 一点点,试图减少 J(θ0,θ1),直到风力达到最小值,或者可能达到局部最小值。

梯度下降是一种有效的优化算法,试图找到成本函数的局部或全局最小值。

全局最小值与局部最小值

局部最小值是我们的函数低于所有邻近点的点。不可能通过制造无穷小的步长来降低成本函数值。

全局最小值是获得我们函数的绝对最小值的点,但是全局最小值在实际中很难计算。

成本函数 vs 梯度下降

我们可能会争辩说,如果成本函数和梯度下降都用于最小化某个东西,那么区别是什么,我们可以使用其中一个而不是另一个吗?

嗯,一个成本函数是我们想要最小化的东西。例如,我们的成本函数可能是训练集的误差平方和。梯度下降是一种求多元函数最小值的方法。

所以我们可以使用梯度下降作为工具来最小化我们的成本函数。

假设我们有一个包含 n 个变量的函数,那么梯度就是长度为 n 的向量,它定义了成本增长最快的方向。所以在梯度下降中,我们沿着梯度的负值到达成本最小的点。在机器学习中,成本函数是我们应用梯度下降算法的函数。

我假设读者已经熟悉微积分,但是在这里我将提供一个微积分概念如何与最优化相关的简要概述。所以不要担心朋友,只要和我在一起…这是一种直觉!

机器学习在优化问题中使用导数。导数用于决定是否增加或减少权重来增加或减少目标函数。如果我们能计算一个函数的导数,我们就知道朝哪个方向去最小化它。

一些符号

导数快速复习

假设我们有一个函数 y = f(x)。f’(x)导数给出了 f(x)在 x 点的斜率,它规定了如何调整输入的微小变化,以获得输出的相应变化。假设,f(x) = 1/2 x

我们可以用导数符号相反的小步长来减少 f(x)。当 f'(x) = 0 时,导数不提供关于移动方向的信息。f'(x) = 0 的点称为临界点。

收敛的概念 是一个定义明确的数学术语。这意味着“最终”一系列元素越来越接近单一值。那么一个算法收敛意味着什么呢?从技术上讲,收敛的不是算法,而是算法正在处理或迭代的值。为了说明这一点,假设我们正在编写一个算法,打印圆周率的所有数字。

我们的算法开始打印如下数字:

x0 = 3.1
x1 = 3.14
x2 = 3.141
x3 = 3.1415
x4 = 3.14159
...

正如我们所看到的,该算法打印出接近圆周率的递增数字。我们说我们的算法收敛于π。而我们把这样的函数叫做凸函数(像碗的形状)。现在,让我们考虑梯度下降的公式:

梯度下降公式

我们通过对成本函数求导(函数的切线)来实现这个公式。切线的斜率是该点的导数,它会给我们一个前进的方向。我们沿着下降速度最快的方向逐步降低成本函数。每一步的大小由参数α (alpha)决定,称为学习率

学习率决定了梯度下降算法的步长。

为了有效地达到局部最小值,我们必须适当地设置我们的学习率参数α,不能太高也不能太低。根据初始点在图上的开始位置,它可能会在不同的点结束。通常,学习率的值是手动选择的,通常从 0.1、0.01 或 0.001 开始。

来源:ML-速成班

在这种情况下,梯度下降的计算时间太长;我们需要提高学习率。

来源:ML-速成班

如果我们的学习曲线只是上上下下,没有达到最低点,我们应该尝试降低学习速度。

来源:ML-速成班

注意:

  • 如果学习率太大,损失会四处反弹,可能达不到局部最小值。
  • 如果学习率太小,那么梯度下降将最终达到局部最小值,但是需要很长时间来达到这个目的。
  • 如果梯度下降正常工作,成本函数应该随时间降低。

我们如何将这个想法形象化?

假设我们在莱尔山(约塞米蒂国家公园的最高点),我们沿着河边的小路徒步下山。这里的梯度下降工作正是我们的目标——到达山的最底部。Mount Lyell 是在空间中绘制的数据,代表目标函数的曲面,我们移动的步长是学习率。山上的最低点是函数的成本达到最小值的值(我们的模型呈现更高精度的参数α)。

还假设莱尔山的形状是这样的,河流不会停在任何地方,会直接到达山脚(像一个碗状)。在机器学习中,我们会达到我们的全局最小值。然而,现实生活中并非如此。这条河在下降的过程中可能会遇到很多坑。它可能被困在坑中,无法向下移动,这是机器学习中的一个局部最小值

当我们在山谷中时,我们没有办法再下山了。我们可以说我们已经融合。在机器学习中,当梯度下降不能再降低成本函数并且成本保持在同一水平附近时,我们可以说它已经收敛到最优。收敛的迭代次数可能变化很大。

这里的要点是初始值和学习率。根据我们从第一点开始的位置,我们可能会到达不同的局部最优值。此外,根据我们迈出的步伐的大小(学习速度),我们可能会以不同的方式到达山脚。这些值对于决定我们是到达山脚(全局最小值)还是被困在坑里(局部最小值)很重要。

所以我们知道梯度下降是一种寻找函数最小值的优化算法。我们如何将算法应用于线性回归?

要应用梯度下降,这里的关键术语是导数。

  1. 取成本函数,对θ0 和θ1 取偏导数,看起来是这样的:

为了求偏导数,我们保持其他变量不变。比方说,我们想对θ0 求导,我们只把θ1 当作常数,反之亦然。

但是为什么我们要在方程中使用偏导数呢?这样我们就有办法衡量我们的假设函数与数据的吻合程度。我们需要估计假设函数中的参数(θ0 和θ1),也就是说,我们想知道θ0 和θ1 的变化率值。在微积分中,偏导数将函数的变化率表示为一个变量的变化,而其他变量保持不变。我们将关于θ0 和θ1 的偏导数应用于成本函数,以将我们指向最低点。

2。将它们重新插入我们的梯度下降算法

要找到最佳最小值,重复步骤,对θ0 和θ1 应用不同的值。换句话说,重复这些步骤直到收敛。

寻找θ0 和θ1 的最优值的过程,就是最小化我们的导数。

因此,为了在迭代的下一步求解梯度,我们使用更新的θ0 和θ1 值迭代通过我们的数据点,并计算它们的偏导数。这个新的梯度告诉我们在当前位置的成本函数的斜率,以及我们应该移动以更新参数的方向。我们更新的大小是由学习率控制的。

梯度下降的利弊

  • 一个简单的算法,易于实现,每次迭代都很便宜;我们只需要计算一个梯度
  • 然而,它通常很慢,因为许多有趣的问题不是强凸的
  • 不能处理不可微的函数(最大的缺点)

梯度下降变体

根据用于计算梯度的数据量,有三种类型的梯度下降方法:

  • 批量梯度下降
  • 随机梯度下降
  • 小批量梯度下降

批量梯度下降

  • 在批量梯度下降中,为了计算成本函数的梯度,我们计算训练数据集中每个示例的误差,然后求和。只有在评估完所有示例后,才会更新模型。
  • 如果我们有 1000 个样本,或者在最坏的情况下,一百万个样本,会怎么样?梯度下降算法需要运行一百万次。所以批量梯度下降不太适合大型数据集。

正如我们所见,批量梯度下降在这里不是一个最佳解决方案。它需要大量的计算资源,因为整个数据集需要保留在内存中。因此,如果我们只需要向最小值移动一步,我们应该计算一百万次成本吗?

随机梯度下降

  • 在 SGD 中,我们在每次迭代中使用一个训练样本,而不是使用整个数据集来对每步进行求和,也就是说,SGD 对每个观察值执行一次参数更新。因此,它只需要一个来执行参数更新,而不是遍历每个观察值。

注意:在 SGD 中,在 for 循环之前,我们需要随机打乱训练样本。

  • SGD 通常比批量梯度下降更快,但是它到达最小值的路径比批量梯度下降更随机,因为 SGD 一次只使用一个例子。但是我们对路径不感兴趣,只要它给我们最少和更短的训练时间就可以了。
  • SGD 广泛用于大型数据集训练,计算速度更快,并且可以允许并行模型训练。

小批量梯度下降

  • 小批量梯度下降是浴梯度下降和随机梯度下降的结合。
  • 小批量梯度下降在每次迭代中使用 n 个数据点(而不是 SGD 中的一个样本)。

案例研究:

我们已经了解了实现线性回归所需的一切。现在是时候看看它在数据集上是如何工作的了。通过用 Python 实现一个简单的线性回归,我学到了很多。我希望你看完我的笔记后能学到一两件事。

我从国家海洋和大气管理局下载了波士顿的天气报告。你可以在 Kaggle 上搜索比赛、数据集和其他解决方案。我们的数据集包含气象站每天记录的天气状况信息。信息包括平均温度(TAVG)、季节至今的冷却度天数(CDSD)、该期间的极端最高温度(EMXT)、季节至今的加热度天数(HDSD)、最高温度(TMAX)、最低温度(TMIN)。在本例中,我们希望将输入要素作为最低温度来预测最高温度。

让我们用 Python 弄脏自己的手,好吗?

资料来源:giphy.com

  1. 导入所有需要的库:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as seabornInstance
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
%matplotlib inline

2.使用 pandas 导入 CSV 数据集:

df = pd.read_csv(‘climate.csv’)
df.dropna(inplace = True)

我们使用 dropna()函数来删除丢失的值。

3.检查数据集中的行数和列数。

df.shape

我们应该收到输出(903,9),这意味着我们的数据包含 903 行和 9 列。

通过使用 describe()函数,我们可以看到数据集的统计细节:

df.describe()

4.可视化我们的数据集,看看我们能否手动找到数据之间的任何关系。

fig,(ax1) = plt.subplots(1, figsize = (12,6))
ax1.scatter (X, y, s = 8)
plt.title (‘Min vs Max Temp’)
plt.xlabel(‘TMIN’)
plt.ylabel(‘TMAX’)
plt.show()

5.将数据分为“属性”和“标签”。

属性是自变量,而标签是因变量,其值将被预测。在我们的数据集中,我们只有两列。我们想根据 TMIN 记录来预测 TMAX。因此,我们的属性集将由存储在 X 变量中的“TMIN”列组成,标签将是存储在 y 变量中的“TMAX”列。

X = df[‘TMIN’].values.reshape(-1,1).astype(‘float32’)
y = df[‘TMAX’].values.reshape(-1,1).astype(‘float32’)

6.将 80%的数据分割成训练集,而将 20%的数据分割成测试集。

test_size 变量是我们指定测试集比例的地方。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

7.训练我们的算法。

为此,我们需要导入 LinearRegression 类,实例化它,并调用 fit()方法以及我们的训练数据。

h = LinearRegression()
h.fit(X_train,y_train)
print(h.intercept_) # to retrieve theta_0
print(h.coef_) # to retrieve theta_1

对于θ_ 0,结果应该是大约 16.25,而对于θ_ 1,结果应该是大约 1.07。

8.做一些预测。

为此,我们将使用我们的测试数据,看看我们的算法预测百分比分数的准确性如何。

y_pred = h.predict(X_test)
compare = pd.DataFrame({‘Actual’: y_test.flatten(), ‘Predicted’: y_pred.flatten()})
compare

实际值和预测值的比较

从上表中我们可以看出,预测的百分比与实际的百分比很接近。让我们用测试数据画一条直线:

fig,(ax1) = plt.subplots(1, figsize = (12,6))
ax1.scatter (X_test, y_test, s = 8)
plt.plot(X_test,y_pred, color = ‘black’, linewidth = 2)\
plt.show()

预测与实际图非常接近,这表明方差值很小。

9.实施线性回归

#pick some random value to start with
theta_0 = np.random.random()
theta_1 = np.random.random()def hypothesis (theta_0,theta_1,X):
    return theta_1*X + theta_0def cost_function (X,y,theta_0,theta_1):
    m = len(X)
    summation = 0.0
    for i in range (m):
        summation += ((theta_1 * X[i] + theta_0) - y[i])**2
    return summation /(2*m)def gradient_descent(X,y,theta_0,theta_1,learning_rate):
    t0_deriv = 0
    t1_deriv = 0
    m = len(X)

    for i in range (m):
        t0_deriv += (theta_1 * X[i] + theta_0) - y[i]
        t1_deriv += ((theta_1 * X[i] + theta_0) - y[i])* X[i]theta_0 -= (1/m) * learning_rate * t0_deriv
    theta_1 -= (1/m) * learning_rate * t1_deriv

    return theta_0,theta_1def training (X, y, theta_0, theta_1, learning_rate, iters):
    cost_history = [0]
    t0_history = [0]
    t1_history = [0]

    for i in range(iters):
        theta_0,theta_1 = gradient_descent(X, y, theta_0, theta_1, learning_rate)
        t0_history.append(theta_0)
        t1_history.append(theta_1)
        cost = cost_function(X, y, theta_0, theta_1)
        cost_history.append(cost)
          if i%10 == 0:
              print ("iter={}, theta_0={}, theta_1={}, cost= {}".format(i, theta_0, theta_1, cost))return t0_history, t1_history, cost_history

对于 2000 次迭代,我们选择学习率等于 0.01,并绘制我们的成本函数 J

t0_history, t1_history, cost_history = training (X, y, theta_0, theta_1, 0.01, 2000)#Plot the cost function
plt.title('Cost Function J')
plt.xlabel('No. of iterations')
plt.ylabel('Cost')
plt.plot(cost_history)
plt.ylim(ymin=0)
plt.xlim(xmin=0)
plt.show()

我发现了一个很酷的方法,用 Matplotlib 的动画来可视化我们的数据。模型需要 449 次迭代才能非常接近最佳拟合线。

import matplotlib.animation as animationfig = plt.figure()
ax = plt.axes()# set up our plot
plt.ylabel(“TMAX”)
plt.xlabel(“TMIN”)
plt.title(‘Linear Regression’)
plt.scatter(X, y, color =’gray’,s =8)
line, = ax.plot([], [], lw=2)
plt.close()#Generate the animation data,
def init():
    line.set_data([], [])
    annotation.set_text('')
    return line, annotation# animation function.  This is called sequentially
def animate(i):
    #print(i)
    x = np.linspace(-5, 20, 1000)
    y = past_thetas[i][1]*x + past_thetas[i][0]
    line.set_data(x, y)
    annotation.set_text('Cost = %.2f e10' % (past_costs[i]/10000000000))
    return line, annotationanim = animation.FuncAnimation(fig, animate, init_func=init, frames=np.arange(1,400), interval=40, blit=True)from IPython.display import HTML
HTML(anim.to_html5_video())

就是这样!

在这篇笔记中,我们学习了最基本的机器学习算法——梯度下降。我们在 Scikit-Learning 机器学习库的帮助下实现了一个简单的线性回归。在下一篇笔记中,我们将重点介绍多元线性回归。

任何努力最难的部分是开始,你已经度过了,所以不要停止!

来源:memgenerator.net

幸运的是,线性回归在几乎所有的机器学习课程中都有很好的教授,并且有相当数量的可靠资源来帮助我们理解线性回归模型的不同部分,包括背后的数学。如果你发现自己想要了解更多,下面是更多的资源。

  1. 优化学习率
  2. 消除深度学习中所有不好的局部极小值(康奈尔大学)
  3. 消除深度学习中所有不好的局部极小值(麻省理工学院)
  4. 什么是收敛?
  5. 为什么要可视化梯度下降优化算法?
  6. 案例分析— Moneyball —线性回归
  7. 将您的数据分为培训和测试 (80/20)
  8. 两个变量梯度下降的偏导数
  9. 要处理的免费数据: Lionbridge AI ,数据集搜索

使用 Python 和 Javascript 创建目标数组的最少函数调用次数

原文:https://towardsdatascience.com/minimum-numbers-of-function-calls-to-make-target-array-with-python-and-javascript-a354eb8fddcb?source=collection_archive---------42-----------------------

使用 Python 和 Javascript 解决方案:解决中等 leetcode 问题

理解问题

创建目标数组的最小函数调用次数是 leetcode 的一个中等问题,我希望你已经仔细阅读了这个问题并尝试解决它。这个问题要求你得到最少的运算次数,以便得到想要的数组。现在的问题是,我们怎样才能做这样的运算来计数它的个数,以尽可能少的方式到达目标数组。

最初的想法

让我们以这个例子为例,将[2,2]作为目标数组,我们想知道到达该数组的最少操作数。因此,我们从[0,0]开始,将每个元素加 1(现在是 2 次运算)达到[1,1],然后将整个数组乘以 2 (1 次运算)达到我们想要的目标数组[2,2],因此我们有 3 次运算来达到本例中所需的数组,如下所示:

图片由作者

但是很难从[0,0]移动到[2,2],因为可能会错误地猜测我们想要到达的下一个数组。我们可以更好地从[2,2]向后移动到[0,0],如下所示:

图片由作者

在这种情况下,我们可以用除法代替乘法,用减法代替加法,如橙色所示,我们最终会得到相同数量的运算。

更好的路径

所以现在我们有两个主要的操作要做:除法和减法。似乎当数组中的所有元素都可以被 2 整除时,我们会使用除法,但如果是奇数,我们会使用减法。整数除法可以让我们不用担心奇数的存在,因为偶数和奇数将被除法运算,剩下的就是对每个存在的奇数的运算次数,这可以通过计算余数来完成。任何数被 2 除的余数不是 1 就是 0。如果是 1,我们表示这个数是奇数,然后我们知道这是一个操作。

以下是用 Python 和 Javascript 计算整数除法和余数的一些脚本:

计算机编程语言

java 描述语言

承认

Python 代码是我和我最好的朋友 Nour 的共同作品。他实际上在 gist 上做出了贡献,解释了在 leetcode 上发现的更有效的解决方案,请参见这个奇妙的 gist :

动机是

  • Array.prototype.some() ‍
  • 创建目标数组的最小函数调用次数| Leetcode 1558 ‍
  • Python 中的 map()、filter()和 reduce()并举例
  • 映射、过滤和缩小 ‍
  • JavaScript 中带余数的整数除法?

更多的解决问题?

你可能想看看更多解决问题的东西:)

[## 用 Python 和 Javascript 实现图论中到达所有节点的最小顶点数

用图论解决一个中等 leetcode 问题

medium.com](https://medium.com/swlh/minimum-number-of-vertices-to-reach-all-nodes-by-graph-theory-with-python-and-javascript-642b8134799e) [## Python 和 Javascript 中正则表达式的千位分隔符

在 Python 和 Javascript 解决方案中使用正则表达式:解决千位分隔符这一简单的 leetcode 问题

medium.com](https://medium.com/analytics-vidhya/thousand-separator-by-regular-expressions-with-python-and-javascript-7edf8ed7e331) [## 用 Python 动态编程实现彩色矩形

使用 Python 解决方案的动态编程:让我们学习如何考虑彩色矩形,一个 1800 点…

medium.com](https://medium.com/an-idea/colored-rectangles-by-dynamic-programming-with-python-a20576a44610)

最初发布

[## EzzEddin 使用 Python 和 Javascript 创建目标数组的最小函数调用数…

创建目标数组的最小函数调用次数是 leetcode 中的一个中等问题,我希望你已经阅读了…

www.ezzeddinabdullah.com](https://www.ezzeddinabdullah.com/posts/minimum-numbers-of-function-calls-to-make-target-array-with-python-and-javascript)

在 LinkedIn 上挖掘数据

原文:https://towardsdatascience.com/mining-data-on-linkedin-9b70681b1467?source=collection_archive---------5-----------------------

使用职称、同事等

照片由格雷格·布拉在 Unsplash 上拍摄

LinkedIn 是一个专注于职业和商业关系的社交网站。在这篇文章中,我将介绍一些挖掘数据的方法。

  • 使用 LinkedIn OAuth 凭据发出 LinkedIn API 请求。
  • 将 LinkedIn 连接下载为 CSV 文件。
  • 做一些数据分析。

在我们开始之前,请记住,所有要求您安装python3-linkedin库的教程现在都不起作用了。

p̶i̶p̶ ̶i̶n̶s̶t̶a̶l̶l̶ ̶p̶y̶t̶h̶o̶n̶3̶-̶l̶i̶n̶k̶e̶d̶i̶n̶

不要在下面的代码上浪费时间。

p̶i̶p̶ ̶i̶n̶s̶t̶a̶l̶l̶ ̶p̶y̶t̶h̶o̶n̶3̶-̶l̶i̶n̶k̶e̶d̶i̶n̶f̶r̶o̶m̶ ̶l̶i̶n̶k̶e̶d̶i̶n̶ ̶i̶m̶p̶o̶r̶t̶ ̶l̶i̶n̶k̶e̶d̶i̶n̶
̶
̶A̶P̶I̶_̶K̶E̶Y̶ ̶=̶ ̶'̶w̶F̶N̶J̶e̶k̶V̶p̶D̶C̶J̶t̶R̶P̶F̶X̶8̶1̶2̶p̶Q̶s̶J̶e̶e̶-̶g̶t̶0̶z̶O̶4̶X̶5̶X̶m̶G̶6̶w̶c̶f̶S̶O̶S̶l̶L̶o̶c̶x̶o̶d̶A̶X̶N̶M̶b̶l̶0̶_̶h̶w̶3̶V̶l̶'̶
̶A̶P̶I̶_̶S̶E̶C̶R̶E̶T̶ ̶=̶ ̶'̶d̶a̶J̶D̶a̶6̶_̶8̶U̶c̶n̶G̶M̶w̶1̶y̶u̶q̶9̶T̶j̶o̶O̶_̶P̶M̶K̶u̶k̶X̶M̶o̶8̶v̶E̶M̶o̶7̶Q̶v̶5̶J̶-̶G̶3̶S̶P̶g̶r̶A̶V̶0̶F̶q̶F̶C̶d̶0̶T̶N̶j̶Q̶y̶G̶'̶
̶R̶E̶T̶U̶R̶N̶_̶U̶R̶L̶ ̶=̶ ̶'̶h̶t̶t̶p̶:̶/̶/̶l̶o̶c̶a̶l̶h̶o̶s̶t̶:̶8̶0̶0̶0̶'̶
̶
̶a̶u̶t̶h̶e̶n̶t̶i̶c̶a̶t̶i̶o̶n̶ ̶=̶ ̶l̶i̶n̶k̶e̶d̶i̶n̶.̶L̶i̶n̶k̶e̶d̶I̶n̶A̶u̶t̶h̶e̶n̶t̶i̶c̶a̶t̶i̶o̶n̶(̶A̶P̶I̶_̶K̶E̶Y̶,̶ ̶A̶P̶I̶_̶S̶E̶C̶R̶E̶T̶,̶ ̶R̶E̶T̶U̶R̶N̶_̶U̶R̶L̶,̶ ̶l̶i̶n̶k̶e̶d̶i̶n̶.̶P̶E̶R̶M̶I̶S̶S̶I̶O̶N̶S̶.̶e̶n̶u̶m̶s̶.̶v̶a̶l̶u̶e̶s̶(̶)̶)̶
̶p̶r̶i̶n̶t̶ ̶a̶u̶t̶h̶e̶n̶t̶i̶c̶a̶t̶i̶o̶n̶.̶a̶u̶t̶h̶o̶r̶i̶z̶a̶t̶i̶o̶n̶_̶u̶r̶l̶ ̶ ̶#̶ ̶o̶p̶e̶n̶ ̶t̶h̶i̶s̶ ̶u̶r̶l̶ ̶o̶n̶ ̶y̶o̶u̶r̶ ̶b̶r̶o̶w̶s̶e̶r̶
̶a̶p̶p̶l̶i̶c̶a̶t̶i̶o̶n̶ ̶=̶ ̶l̶i̶n̶k̶e̶d̶i̶n̶.̶L̶i̶n̶k̶e̶d̶I̶n̶A̶p̶p̶l̶i̶c̶a̶t̶i̶o̶n̶(̶a̶u̶t̶h̶e̶n̶t̶i̶c̶a̶t̶i̶o̶n̶)̶

创建 LinkedIn 应用程序

首先,我们需要创建一个 LinkedIn 应用程序,去 https://www.linkedin.com/developers/apps参观并遵循指南。我创建了一个名为MyLinkedIn的应用程序。

我们需要通过向页面管理员发送 URL 来获得公司验证。下面是我的例子中的 URL。

[https://www.linkedin.com/developers/apps/verification/05ab9ce8-766e-46d5-a922-5778df7db07e](https://www.linkedin.com/developers/apps/verification/05ab9ce8-766e-46d5-a922-5778df7db07e)

如果没有公司来验证您的申请,请创建一个新的公司。

如何获得 LinkedIn 的 API 访问权限?

LinkedIn 提供了一项服务,让人们通过基于 OAuth 的 API 将他们的 LinkedIn 档案和网络带到你的站点或应用程序中。

通过使用 Python 来使用 LinkedIn 的 API,您不需要安装任何库,只需要如下导入库。

import requestsimport stringimport random

下一步是获得 API 访问权,记下客户端 ID 和密码。

编写一个脚本来获取访问令牌。

# Copy the client ID, secret, and redirect URI in the fields below
CLIENT_ID    = '...'
CLIENT_SECRET = '...'
REDIRECT_URI = 'http://localhost:8000'

# Generate a random string to protect against cross-site request forgery
letters = string.ascii_lowercase
CSRF_TOKEN = ''.join(random.choice(letters) for i in range(24))

# Request authentication URL
auth_params = {'response_type': 'code',
               'client_id': CLIENT_ID,
               'redirect_uri': REDIRECT_URI,
               'state': CSRF_TOKEN,
               'scope': 'r_liteprofile,r_emailaddress,w_member_social'}

html = requests.get("https://www.linkedin.com/oauth/v2/authorization",
                    params = auth_params)

# Print the link to the approval page
print(html.url)

# Click the link below to be taken to your redirect page.

在我的情况下,链接如下,只需点击它。

您将通过点击allow按钮进入,如下所示。LinkedIn 在授予对您的应用程序的访问权限(给予适当的权限)后,会将用户重定向回您的网站的 URL。

LinkedIn 在授予对您的应用程序的访问权限(给予适当的权限)后,会将用户重定向回您的网站的 URL。

这意味着 authorization_code 的值是AQQ3C.......JR7mSw,它是在&code=…之后的代码,但不包括&state=…。将此访问令牌传递给应用程序。

AUTH_CODE ='AQQ3C.......JR7mSw'

ACCESS_TOKEN_URL = 'https://www.linkedin.com/oauth/v2/accessToken'

qd = {'grant_type': 'authorization_code',
      'code': AUTH_CODE,
      'redirect_uri': REDIRECT_URI,
      'client_id': CLIENT_ID,
      'client_secret': CLIENT_SECRET}

response = requests.post(ACCESS_TOKEN_URL, data=qd, timeout=60)

response = response.json()

access_token = response['access_token']

print ("Access Token:", access_token)
print ("Expires in (seconds):", response['expires_in'])

它显示的结果如下。

我们检索 LinkedIn 的个人资料

发出 HTTP 请求以检索个人配置文件。

import json

params = {'oauth2_access_token': access_token}
response = requests.get('https://api.linkedin.com/v2/me', params = params)

print(json.dumps(response.json(), indent=1))

它将返回我的 LinkedIn 个人资料。有许多字段选择器可以让客户端从 API 获取更多信息。

我们还可以显示特定的字段

请参见 https://developer.linkedin.com/docs/fields/positions的部分,了解可以被传入以检索附加配置文件信息的附加字段选择器的详细信息。(LinkedIn API 限制了可以查询的数据,例如,你不能再使用该 API 来检索你在 LinkedIn⁴的关系列表)。

params = {'oauth2_access_token': access_token,
          'fields': ["localizedFirstName,localizedLastName,id"]}
response = requests.get('https://api.linkedin.com/v2/me', params = params)

print(json.dumps(response.json(), indent=1))

在这里,我们得到了localizedFirstName文件和localizedLastName文件。它返回的结果如下。

我们可以使用字段选择器语法来请求 API 的附加细节。

params = {'oauth2_access_token': access_token,
          'fields': ['lastName:(preferredLocale:(country,language))']}
response = requests.get('https://api.linkedin.com/v2/me', params = params)

print(json.dumps(response.json(), indent=1))

它显示了结果。

我们可以下载您的个人资料数据,并读入 CSV 格式的连接数据

去下载你的 LinkedIn 数据 https://www.linkedin.com/psettings/member-data here⁵:。

一旦收到请求,LinkedIn 将准备好您的个人资料档案,您可以下载。这是我的 csv 文件(名为Connections.csv)。

最后,我们做了一些数据分析

现在,您已经对如何访问 LinkedIn 的 API 有了基本的了解,让我们深入一些更具体的分析。

首先,我们加载数据文件。

import os
import csv

CSV_FILE = os.path.join('./', 'resources', 'Connections.csv')

csvReader = csv.DictReader(open(CSV_FILE), delimiter=',', quotechar='"')
contacts = [row for row in csvReader]

它指向我们的“Connections.csv”文件。现在,我们试图知道有多少人在谷歌工作。

workingAtGoogle = 0

for contact in contacts:
    for t in contact['Company'].split('/'):
        if (t == 'Google'):
            workingAtGoogle = workingAtGoogle+1
print('There are %d people who are working at Google.' % (workingAtGoogle))

我有 129 个在谷歌工作的熟人。

接下来,我们在寻找我的关系中有多少 CEO?

whoareceos = 0

for contact in contacts:
    for t in contact['Position'].split('/'):
        if (t == 'CEO'):
            whoareceos = whoareceos+1

print('There are %d people who are CEOs.' %(whoareceos))

它显示在我的连接中有 253 人是 CEO。

我们还试图将 LinkedIn 网络可视化。使用pandas库加载数据文件。

import pandas as pd

df = pd.read_csv(CSV_FILE)
print(df.head())

它列出了我的连接如下。

它包括我网络中每个人的电子邮件、当前职位和公司,以及他们何时成为我网络的一部分。

分析我们连接的时间。

import plotly.express as px

fig = px.scatter(df, x="First Name", y="Connected On")
fig.show()

因为打印多行 CSV 文件显然不是可视化或理解我的网络的最佳方式。我使用 plotly.express 库在一个地方可视化我的整个网络。

fig = px.treemap(df, path=['Position', Company'], width=1200, height=1200)

fig.show()

很简单,对吧?我们学习了如何获得对 LinkedIn 的 API 访问。我们也做一些 API 请求。最后,我们在 LinkedIn 连接中做了一个简单的数据分析。

参考

[1]http://developers.linkedin.com/documents/authentication

[2]https://docs . Microsoft . com/en-us/LinkedIn/consumer/integrations/self-serve/sign-in-LinkedIn?上下文= LinkedIn/消费者/上下文

[3]https://developer.linkedin.com/docs/fields/positions

[4]https://developer . LinkedIn . com/blog/posts/2015/developer-program-changes

[5]https://www.linkedin.com/psettings/member-data

从混沌中挖掘秩序:自然语言处理与图论的巧妙融合

原文:https://towardsdatascience.com/mining-order-from-chaos-the-ingenious-and-creative-fusion-of-nlp-graph-theory-954b10e2f976?source=collection_archive---------59-----------------------

资料来源:Unsplash

为什么基于图表的方法如此美妙

机器学习算法从一开始就被设计用来处理数字。对于可以很容易地转换成数字形式的数据,这种方法效果很好;无论是图像还是声音,这类问题的解决方案都被迅速开发和部署。然而,有一个领域还没有完全被机器掌握——语言,因为它显然是人类的。

将语言转换成数字的可行方法最终总是会丢失信息。例如,考虑 TF-IDF 矢量化,这是一种非常标准的文本到数字转换方法,对于非常简单的任务来说足够好,但无法理解语言的细微差别,如讽刺、上下文、文化参考、习语和具有多重含义的单词。即使有了像 BERT 这样的里程碑式的解决方案,自然语言处理可能仍然是机器学习领域中最有改进空间的领域。

或许,为了解决这样一个充满例外和细微差别的独特问题,机器学习工程师需要找到更具创造性的解决方案——毕竟,不是每个问题都可以通过使用神经网络变体来解决或可行地部署。以图论为例,它是一个经常被忽视或抛弃的数学领域,由莱昂哈德·欧拉在 1736 年通过思考柯尼希斯堡的七座桥问题而创立。图论和自然语言处理似乎不太可能一起工作,但它们确实一起工作了——在这两项研究的惊人巧妙和创造性的融合中,它们的交叉为 NLP 和机器学习作为一个整体的更多样化的解决方案铺平了道路。

除非另有说明,所有图片均由作者创作。

可以说,知识(语义)图是数据科学中最迷人的概念之一。知识图的应用、扩展以及从混乱的非结构化文本中挖掘秩序的潜力确实令人兴奋。

该图由节点和边组成,其中节点表示实体,边表示关系。图中没有实体可以重复两次,当图中有足够多的实体时,每个实体之间的联系可以揭示信息世界。

只是有了几个实体,有趣的关系就开始出现了。一般来说,实体是名词,关系是动词;例如,“美国是北约的成员”将对应于图形关系“[实体美国]到[实体北约]和[关系成员]”。仅仅使用三到四个信息句子的文本,就可以构建一个基本的知识图表:

想象一下一篇完整的维基百科文章,甚至一整本书所包含的知识量!人们可以利用这些丰富的数据进行详细的分析;例如,确定最重要的实体或实体在接收端最常见的动作或关系。不幸的是,虽然构建知识图对人类来说很简单,但却不可扩展。我们可以构建简单的基于规则的自动图形生成器。

为了演示知识图构建的自动化,考虑一位伟大的计算机科学家和人工智能创始人艾伦·图灵的传记专家。既然我们已经确定实体是名词,动词是关系,那么让我们首先将文本分成块,每个块包含两个对象之间的关系。

一个简单的方法是用句子来分隔,但更严格的方法是用子句来分隔,因为在一个句子中可能有许多子句,因此也有关系(“她遛狗去公园,然后她买了食物”)。

识别所涉及的对象(实体提取)是一项更加困难的任务。考虑“图灵测试”:这是一个嵌套实体的例子,或者一个实体在另一个实体的名字中。虽然词性标注对于单个单词的名词来说已经足够了,但是对于多个单词的名词,还需要使用依存解析。

依存句法分析的任务是识别一个句子并给它分配一个基于句法的结构。因为依存关系树是基于语法而不是逐词的,所以它不在乎一个对象由多少个词组成,只要它被其他结构(如动词(' proposed ')或过渡短语(' as a…')所包围。它还被用来寻找联系两个对象的动词,系统地遵循它认为是句子的句法和语法规则。人们也可以使用类似的方法将代词(“他”、“她”、“他们”)与它所指的人联系起来(代词解析)。

值得一提的是,人们还可以通过添加同义词来构建知识图;为了简单起见,教程通常会显示同一个单词重复多次的例子,但是对人类来说,重复使用同一个单词是如此的被轻视,以至于作者积极地寻找同义词(与另一个单词意思相同的单词)。一种方法是使用赫斯特模式,该模式以加州大学伯克利分校计算语言学研究员兼教授马蒂·赫斯特命名。在她广泛的研究中,她发现了一组重复出现的模式,可以可靠地用来提取信息。

这些赫斯特模式经常出现,尤其是在像维基百科或百科全书这样的大型文本存储库中。通过记录所有这些词的含义和关系以及名词-动词-名词关系,知识图表将拥有大量的信息和理解。毕竟,人类识别与其他事件或物体相关的物体并与之互动(“嘿,我在篮球锦标赛上赢得了那个奖杯!”).

使用各种简单的规则,可以从一段文本创建一个完整的知识图。从理论上讲,在维基百科上创建的知识图比任何一个人都聪明,因为它理解某些对象与其他对象的关系和上下文,因此能够建立一个关于各种主题的更深层次知识的详细武器库。

基于一段文本的示例知识图。随着更多信息的加入,它将呈指数级增长。

然而,语言中总有例外,使用基于规则的方法来创建知识图似乎已经过时了。一种更现代的基于神经网络的方法可能能够构建一个知识图,该知识图对文本的古怪和转折具有更强的鲁棒性和适应性。

文本摘要是自然语言处理的重要组成部分。虽然肯定有许多重型方法可以做到这一点,如编码器-解码器模型,但与基于图形的方法相比,它可能会矫枉过正,甚至性能更差。文本摘要的关键是选择文本的重要方面并对它们进行编辑。这被称为文本摘要的提取方法;这种方法不是生成新的文本,而是在文档中找到最重要的句子。

一旦在文本上创建了知识图表,它将可能是巨大的。毕竟,图的大小随着每个额外的节点呈指数增长,并且图中有大量的细节和细微差别。这允许应用图归约算法,该算法根据几个因素来计算节点的“中心性”,这些因素包括与其他节点的连接的频率和权重,以及它们所连接的节点的属性。然后根据句子中元素和关系的重要性给每个句子打分,分数最高的几个句子将进入最后的总结。

这种方法很棒,原因有几个:

  • 它是无人监管的。与另一种流行的提取摘要方法不同,其中训练分类器(很可能是神经网络)来预测一个句子是否应该被包括在摘要中,它不受训练标签中缺乏丰富性或客观性的限制。
  • 它适用于所有语言。创建知识图并利用其成果是普遍的,因为它强调关系,而不一定是实体名称的价值。这对于许多其他的 NLP 框架来说是不可能的。
  • 它可以按主题分开。图形建模的美妙之处在于,你会在语义图中发现集群,每个集群代表一个特定的主题。我们可以确保该算法不会被一个流量很大的主题分散注意力,同时还有其他突出的但联系较少的聚类(主题),因为它的目标是中心性。

图论在自然语言处理中的潜力令人眼花缭乱——例如,文档的相似性(其中每个文档都是一个节点)或文本的动态聚类。文本数据的图论实现也非常容易理解,并且有能力改变文本挖掘和分析的领域。在 NLP 的范围之外,图论在研究疾病和网络的影响方面变得越来越重要。

是时候发挥创造力,开始探索了。

如果你喜欢,

你可能也会喜欢我关于机器学习的一些其他文章。

[## 注入随机性如何提高模型精度

自举聚合的魔力

medium.com](https://medium.com/swlh/how-injecting-randomness-can-improve-model-accuracy-11cdc04b3eeb) [## 如果整流线性单元是线性的,它们如何增加非线性?

神经网络最喜欢的功能背后的直觉

medium.com](https://medium.com/analytics-vidhya/if-rectified-linear-units-are-linear-how-do-they-add-nonlinearity-40247d3e4792)

挖掘电信产品推荐

原文:https://towardsdatascience.com/mining-telecom-product-recommendations-cfe455f3e563?source=collection_archive---------30-----------------------

传统推荐系统在电信行业的应用原则

摘要

在当前信息过载的时代,人们越来越难找到相关内容。推荐系统已经被引入来帮助人们从大量的选择中检索潜在有用的信息。它是一个基于数据分析向用户推荐产品、服务和信息的系统,在解决信息爆炸问题方面变得越来越重要。

近年来,在为电子商务、电子学习和电子治理中的各种基于网络的应用提供个性化推荐服务的方向上,已经采取了重要的步骤。然而,令人惊讶的是,尽管这一系统是必需的,但至今仍未出现在电信部门。因此,本博客探讨了电信公司对推荐系统的需求,以帮助其客户在线选择最合适的电信计划/产品。博客以开发和实现电信产品/服务的个性化推荐系统作为结尾,从数据中挖掘关联规则,为新客户找到合适的电信产品包/计划/产品。

介绍

尽管人工智能(AI)无疑有能力改变电信行业,但它在很大程度上仍是一个新兴领域。然而,我认为电信公司在利用人工智能技术方面处于独特的有利地位,这主要是因为他们已经习惯于处理人工智能和机器学习(ML)所依赖的海量数据。由于这不是一时的时尚,所以电信公司必须与人工智能进行长期博弈,并考虑探索较少的领域,以释放新的收入流。

人工智能和人工智能需要大量的数据才能正常工作,但数据也必须有足够的质量。如果没有适当数量的高质量数据,人工智能或 ML 模型推荐的决策就不太可能准确或成功。

从积极的一面来看,电信公司确实可以访问大量数据,可能比大多数其他行业的公司都要多。然而,困难在于捕获正确的数据集,并以 ML 所需的粒度存储它们。

以传统的方式收集高质量的数据是一回事,但是以特定的方式获取这些数据是另一回事,您可能需要以特定的方式来解决一个用例。如今,大多数电信运营商的网页都有大量的选择,这使得客户越来越难找到自己想要的产品。

如果同一个网页可以根据现有客户过去的选择,自动向您推荐各种附加产品/捆绑包,您不认为这将非常重要吗?

需要电信推荐系统

将传统推荐系统的概念应用于电信行业(来源-https://bit.ly/3f4XhA3

可以根据其他用户的选择对推荐系统进行微调,以迎合用户简档/偏好。该系统的优点是通过应用信息过滤算法,基于特定用户的显性和隐性偏好,向他们建议正确的项目(基础计划或附加产品)。我用来实现的算法叫做 Apriori。

算法描述

Apriori 算法——它只是对客户交易数据库的研究,以确定不同计划/产品的购买之间的依赖关系。

换句话说,就是“什么配什么”的学问。

客户交易的详细信息的可用性导致了自动寻找存储在数据库中的项目之间的关联的技术的发展。示例—网络运营商在其数据库中收集关于每个计划/基础包以及附加产品的客户交易的数据。这种数据库由大量交易记录组成,其中每个记录列出了客户购买的基础计划或附加产品。

实施步骤

第一步

通过使用 Python 对客户交易数据执行基本 EDA,很可能会观察到某些基础包/计划比其他包/计划出现得更频繁。因此,作为第一步,显示一个流行的基础包列表是个好主意。假设所有数据都存储在 pandas dataframe 'df '中,我们可以使用下面的代码获得流行的基础包/计划列表。

df["BASE_PACKAGE_NAME"].value_counts()

第二步

使用 Python 将这些数据转换成每个记录都列出用户购买的所有商品的表单不会有太大的困难。

客户交易数据库快照

在这个阶段,我们想知道某些组的商品是否总是一起购买,这可以在 Apriori 算法的帮助下找到。

#Convert the dataframe to a list
records = df.values.tolist()#Generate association rules with required 
#minimum support, confidence and lift
from apyori import apriori
association_rules = apriori(records, min_support=0.3346, min_confidence=0.20, min_lift=3, min_length=3)
association_results = list(association_rules)

Apriori 算法中有四个性能指标。这些参数用于排除结果中支持度和置信度分别低于最小支持度、置信度、提升或长度的关联规则。

  1. min_support —介于 0 和 1 之间的浮点值;用于选择支持值大于参数中指定值的项目。

2。min_confidence —介于 0 和 1 之间的浮点值;用于筛选可信度大于参数中指定的可信度阈值的规则。

3。min_lift —指定入围规则的最小提升值。

4。min_length —指定希望在关联规则项目集中看到的最小项目数。

min_support、min_confidence 和 min_lift 参数的最佳值可以通过尝试不同的值并检查它们是否在项集之间产生有效的关联来设置。

第三步

以可理解的格式获取关联规则可能是一个挑战;以下是我如何克服的。请注意,‘前任’是在数据中找到的项目,而‘继任者’是结合前任找到的项目。

#Create a dataframe with all the necessary information
df = pd.DataFrame(columns=('Items','Predecessor','Successor','Support','Confidence','Lift'))Support =[]
Confidence = []
Lift = []
Items = []
Predecessor= []
Successor=[]for RelationRecord in association_results:
    for ordered_stat in RelationRecord.ordered_statistics:
        Support.append(RelationRecord.support)
        Items.append(RelationRecord.items)
        Predecessor.append(ordered_stat.items_base)
        Successor.append(ordered_stat.items_add)
        Confidence.append(ordered_stat.confidence)
        Lift.append(ordered_stat.lift)df['Items'] = list(map(set, Items))                                   
df['Predecessor'] = list(map(set, Predecessor))
df['Successor'] = list(map(set, Successor))
df['Support'] = Support
df['Confidence'] = Confidence
df['Lift']= Lift#Sort the dataframe based on confidence 
df.sort_values(by ='Confidence', ascending = False, inplace = True)

第四步

如果“前任”列值等于客户从流行套餐列表中选择的基础套餐名称,则通过挑选“继任者”列中的项目来提供正确的推荐。

#Picking the records for a particular plan/base_package that has been selected by the customer on the GUI
package_name = "1GB/Day(24 day Validity)"index=[]
for key, value in df["Predecessor"].iteritems(): 
    if len(value) == 1 and package_name in value:
        print(key,value)
        index.append(key)

recommendations = df[df.index.isin(index)]

瞧啊。

产品推荐列表

请注意,频繁购买百分比是置信度参数的度量,它是由前面提到的 Apriori 算法计算的。

结论和未来工作

作为电信行业的一员,我已经有将近 5 年的时间了,我看到任何人工智能项目都有各种各样的技术和组织问题;这并不奇怪,因为人工智能是一个不切实际的东西,你需要给组织一些有形的东西。因此,从概念到实际项目的飞跃,或者从试点人工智能概念验证项目到实际部署是一个进一步的挑战。这篇博客中描述的关联规则挖掘方法证明了自动化相似性分析的好处,并且在我看来是电信公司的基本业务用例。非常重要的是,要清楚地了解这种投资的成功要素。

更进一步,上述实现仅限于为通过 web-GUI/kiosk 订阅网络的新客户提供推荐。该模型可以通过在初始阶段添加聚类算法向现有/新客户提供推荐来改进;这将根据年龄、工资、地理数据等对客户进行细分。此外,Apriori 算法的一些缺点是生成的规则太多,并且项目集的罕见组合往往会被忽略,因为它们不满足最低支持要求。使用更健壮的算法将有助于解决这个问题。

感谢您的阅读!

参考

[1]https://www.appliedaicourse.com/

[2]电信和人工智能:创造人工智能驱动的电信行业需要什么——2019 年 5 月,由 STL Partners 主办,诺基亚提供支持。

[3]北京农业信息技术研究中心和北京计算机科学技术学院的研究文章——利用缺失数据提高 Top-𝑁Recommendation 性能。

[4]研究文章 IEEE Communications Magazine 的预测性电信网络管理的推荐系统架构。

挖掘 Twitter 数据

原文:https://towardsdatascience.com/mining-twitter-data-ba4e44e6aecc?source=collection_archive---------10-----------------------

社交媒体内部

来自 cnbc.com的劳伦·费纳的照片

Twitter 是一种微博和社交网络服务,用户在这里发布内容并与帖子互动,即所谓的“推文”。今天,Twitter 已经普及了标签的使用,作为一种分组对话的方式,并允许用户关注特定主题的对话。

目标

每天有超过 5 亿条推文,你可以想象这个平台的信息有多丰富。这个项目的目标是收集和分析 twitter 数据,以发现有趣的信息和隐藏的模式。

这篇文章是我完成这项任务的经验的“技术反映”。我将展示并简要解释相关的代码片段以及我的分析结果。以下是我认为值得讨论的关键步骤的概述。

概述

  1. 证明
  2. 数据收集
  3. 数据清理和预处理
  4. 建模和分析
  5. 结论

认证

在这个应用程序中,使用行业标准 OAuth 流程执行身份验证步骤,该流程涉及用户、消费者(应用程序)和资源提供者(Twitter)。这里的关键是,用户名和密码等凭证的交换只发生在用户和资源提供者之间。所有其他交易所都是由代币驱动的。

甲骨文OAuth 程序照片

  • 创建一个 Twitter 开发者账户。您需要一个开发者帐户来访问 twitter API。一旦您创建了一个应用,您就可以生成消费者密钥消费者秘密访问令牌访问秘密
  • 我选择 tweepy 作为我的 Twitter API 客户端,并且我选择为我的令牌创建环境变量,因为它提高了安全性并且是语言不可知的。以下是我如何设置我的 twitter 客户端。
import os
import sys
from tweepy import API
from tweepy import OAuthHandlerdef get_twitter_auth():
 **#set up twitter authentication**# Return: tweepy.OAuthHandler objecttry:
        consumer_key = os.environ['TWITTER_CONSUMER_KEY']
        consumer_secret = os.environ['TWITTER_CONSUMER_SECRET']
        access_token = os.environ['TWITTER_ACCESS_TOKEN']
        access_secret= os.environ['TWITTER_ACCESS_SECRET']
    except KeyError:
        sys.stderr.write("TWITTER_* environment variables not set\n")
        sys.exit(1)
    auth = OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_secret)
    return authdef get_twitter_client():
 **#Setup twitter API client.**# Return tweepy.API objectauth = get_twitter_auth()
    client = API(auth)
    return client

数据收集

初步设置后。我可以立即开始收集数据并与 API 交互。

与 twitter 的 REST API 交互

  • 所有 REST 端点都允许你“回到过去”,这意味着我们能够搜索已经发布的推文。

与 twitter 的流媒体应用编程接口互动

  • 流式 API 展望未来。一旦你打开了一个连接,你就可以让它保持开放并及时向前。通过保持 HTTP 连接打开,我们可以在发布时检索所有符合过滤标准的推文。
  • 这通常是下载大量推文的首选方式。
  • 就我而言,我想调查 2019 年 12 月美伊紧张局势期间用户之间的实时对话,所以我决定播放所有带有趋势标签的推文,如#USIran #USvsIran #Iranattacks

下面是我如何实现一个定制的流监听器。

class CustomListener(StreamListener):
 **""" Custom StreamListener for streaming twitter data."""**def __init__(self, fname):
        safe_fname = format_filename(fname)
        self.outfile = "stream_%s.jsonl" % safe_fnamedef on_data(self, data): #called when data is coming through. This method simply stores data as it is received in a .jsonl file. Each line in this file will contain a single tweet in json format try:
            with open(self.outfile, 'a') as f:
                f.write(data)
                return True
        except BaseException as e:
            sys.stderr.write("Error on_data: {}\n".format(e))
            time.sleep(5)
        return True
                                **...**if __name__ == '__main__':
    query = sys.argv[1:] # list of CLI argumentsquery_fname
    query_fname = ' '.join(query) # string
    auth = get_twitter_auth()
    twitter_stream = Stream(auth, CustomListener(query_fname))
    twitter_stream.filter(track=query, is_async=True)

数据清理和预处理

因此,在流了大约一个小时后,我设法收集了来自用户的 13,908 条谈论美伊紧张局势的推文。我将这些推文存储在一个. jsonl 文件中,现在是预处理文本的时候了。以下是我执行的一些预处理任务:

使用 nltk 库进行标记化

记号化是指将文本流分解成单词、短语、符号等记号。tweet 的内容包括表情符号、用户提及、hasthags、URL 等。因此,在使用 nltk 库时,我将展示如何使用 TweetTokenizer 类作为工具来适当地标记 twitter 内容。

停止字清除

停用词没有内容承载,所以我们需要删除它们。这类词包括冠词、副词、符号、标点符号等。频率分析显示,这些字符串在文档中出现的频率最高。

正常化

规范化用于聚合同一单位中的不同术语。执行大小写规范化将有助于自动将这些字符串与最初不同的大小写进行匹配,以便它们可以聚合在同一术语下。

import sys
import string
import json
from collections import Counter
from nltk.tokenize import TweetTokenizer
from nltk.corpus import stopwords
import matplotlib.pyplot as pltdef process(text, tokenizer=TweetTokenizer(), stopwords=[]):
    """ Process tweet text:
        - Lowercase
        - tokenize
        - stopword removal
        - digits removal
        Return: list of strings
    """text = text.lower()
    tokens = tokenizer.tokenize(text)
    return [tok for tok in tokens if tok not in stopwords and not tok.isdigit()]if __name__ == '__main__':
    fname = sys.argv[1]
    tweet_tokenizer = TweetTokenizer()
    punct = list(string.punctuation)
    stopword_list = stopwords.words('english') + punct + ['rt', 'via', '...']tf = Counter()
    with open(fname, 'r') as f:
        for line in f:
            tweet = json.loads(line)
            tokens = process(text=tweet['text'], tokenizer=tweet_tokenizer, stopwords=stopword_list)
            tf.update(tokens)
        for tag, count in tf.most_common(20):print("{}: {}".format(tag, count))**#plot results**y = [count for tag, count in tf.most_common(20)]
    x = range(1, len(y)+1)plt.bar(x, y)
    plt.title("Term frequencies used in US-Iran Stream Data")
    plt.ylabel("Frequency")
    plt.savefig('us-iran-term-distn.png')

建模和分析

在上面的片段中,我通过创建我收集的 tweets 中最常用的 20 个术语的术语分布的可视化表示来开始分析。

前 20 个常用术语和术语分布

继续分析,我在数据集中搜索每个人都在谈论的关键人物,找到他们被提及的频率。

提及频率结果

有了这些信息,我就确切地知道我可以开始调查哪些概要文件来接收更相关的提要。然而,令人震惊的是,realdonaldtrump 在与此问题相关的热门用户提及中排名第八。

时间序列分析

  • 时间序列是由给定时间间隔内的连续观察值组成的数据点序列
  • 它可以用来重新排序推文,并跟踪用户对实时事件(如体育、政治选举、新闻)的反应

在这个应用程序中,我执行了一个时间序列分析,以监控随着更多关于这个话题的新闻发布,用户是如何发 tweet 的。在我看来,在我上传视频的一个小时内,用户们一直在积极地发关于这个话题的推文,在上午 10:45 左右收集了 200 条推文

用户、关注者和朋友

我决定探索一些顶级用户的个人资料、关注者名单和“关注者”(或朋友),以进行进一步分析。以下是我如何从 twitter 上获取这些信息的。

**#get followers for a given user**fname = "Twitter_Profiles/{}/followers.jsonl".format(screen_name)
    with open(fname, 'w') as f:
        for followers in Cursor(client.followers_ids, screen_name=screen_name).pages(max_pages):
            for chunk in paginate(followers, 100):
                users = client.lookup_users(user_ids=chunk)
                for user in users:
                    f.write(json.dumps(user._json)+"\n")
            if len(followers) == 5000:
                print("More results available. Sleeping for 60 seconds to avoid rate limit")
                time.sleep(60)**#get friends for a given user**fname = "Twitter_Profiles/{}/friends.jsonl".format(screen_name)
    with open(fname, 'w') as f:
        for friends in Cursor(client.friends_ids, screen_name=screen_name).pages(max_pages):
            for chunk in paginate(friends, 100):
                users = client.lookup_users(user_ids=chunk)
                for user in users:
                    f.write(json.dumps(user._json)+"\n")
            if len(friends) == 5000:
                print("More results available. Sleeping for 60 seconds to avoid rate limit")
                time.sleep(60)**# get user's profile**
    fname = "Twitter_Profiles/{}/user_profile.json".format(screen_name)
    with open(fname, 'w') as f:
        profile = client.get_user(screen_name=screen_name)
        f.write(json.dumps(profile._json, indent=4))

衡量影响力和参与度

  • 参与度指标提供了对用户对推文和其他内容的反应的评估,通常是为了增加流量而创建的。在 twitter 上,用户通过点赞或转发的方式参与,这为推文提供了更多的可见性
  • 了解用户的影响力包括结合用户的推文参与度统计数据分析用户的覆盖范围。
**#Build up a list of followers**
    followers_file1 = 'Twitter_Profiles/{}/followers.jsonl'.format(screen_name1)
    followers_file2 = 'Twitter_Profiles/{}/followers.jsonl'.format(screen_name2)with open(followers_file1) as f1, open(followers_file2) as f2:
        reach1 = []
        reach2 = []
        for line in f1:
            profile = json.loads(line)
            reach1.append((profile['screen_name'], profile['followers_count']))
        for line in f2:
            profile = json.loads(line)
            reach2.append((profile['screen_name'], profile['followers_count']))**#Load basic statistics**
    profile_file1 = 'Twitter_Profiles/{}/user_profile.json'.format(screen_name1)
    profile_file2 = 'Twitter_Profiles/{}/user_profile.json'.format(screen_name2)
    with open(profile_file1) as f1, open(profile_file2) as f2:
        profile1 = json.load(f1)
        profile2 = json.load(f2)followers1 = profile1['followers_count']
        followers2 = profile2['followers_count']tweets1 = profile['statuses_count']
        tweets2 = profile['statuses_count']sum_reach1 = sum([x[1] for x in reach1]) #sum up all of a user's followers, followers
    sum_reach2 = sum([x[1] for x in reach2])
    avg_followers1 = round(sum_reach1/ followers1, 2)
    avg_followers2 = round(sum_reach2/ followers2, 2)**#Load the timelines for two users to observe the number of times their tweets have been favorited**
    timeline_file1 = 'user_timeline_{}.jsonl'.format(screen_name1)
    timeline_file2 = 'user_timeline_{}.jsonl'.format(screen_name2)
    with open(timeline_file1) as f1, open(timeline_file2) as f2:
        favorited_count1, retweet_count1 = [], []
        favorited_count2, retweet_count2 = [], []
        for line in f1:
            tweet = json.loads(line)
            favorited_count1.append(tweet['favorite_count'])
            retweet_count1.append(tweet['retweet_count'])for line in f2:
            tweet = json.loads(line)
            favorited_count2.append(tweet['favorite_count'])
            retweet_count2.append(tweet['retweet_count'])
  • 完整的脚本可以在我的 GitHub 上找到

挖掘社交社区

  • 一个社会群体是一群有着共同条件的人,比如地理区域,相同的宗教信仰,或者有着相同兴趣的人。
  • 明确的社区 —有共同兴趣的人明确知道他们是否属于某个社区,并且通常了解所述社区中的其他成员是谁。
  • 隐性社区——当成员拥有共同的兴趣,但彼此之间没有明确而紧密的联系时,隐性社区就出现了

在下一节中,我将演示我如何分析用户数据,以便将一堆用户资料分成组,目的是发现用户的隐含社区。

聚类分析

聚类分析是一种机器学习技术,用于以这样一种方式对项目进行分组,即同一聚类中的对象彼此相似,而与其他聚类中的对象不相似。以下是该脚本的一些关键要点。

  • 我用了 K-means 算法来达到这个目的。
  • 每个用户简档被表示为一个向量。基于用户描述,我使用 TF-IDF 方法来衡量一个词在给定上下文中的权重/重要性
  • 我们可以限制 tfidf 矢量器提取的要素数量(通过显式指定 max_features 或指定 min_df 和 max_df 的范围)。基于文档频率排除特征的想法是为了避免不具有代表性的特征。限制它们也可以用来加速计算。
  • ngram 是 n 个项目的连续序列,在这个上下文中,它指的是被标记为单词序列的文本。使用 ngrams 的好处是它能够捕捉短语。
  • 下面是我如何根据用户 bios 进行聚类分析的。
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeansdef get_parser():
    parser = ArgumentParser("Clustering for followers")
    parser.add_argument('--filename') 
    parser.add_argument('--k', type=int) 
    parser.add_argument('--min-df', type=int, default=2) 
    parser.add_argument('--max-df', type=float, default=0.8) 
    parser.add_argument('--max-features', type=int, default=None) 
    parser.add_argument('--no-idf', dest='user_idf', default=True, action='store_false') 
    parser.add_argument('--min-ngram', type=int, default=1) 
    parser.add_argument('--max-ngram', type=int, default=1) 
    return parserif __name__ == '__main__':
    parser = get_parser()
    args = parser.parse_args()
    if args.min_ngram > args.max_ngram:
        print("Error: incorrect value for --min--ngram ({}): it cant be higher than \
        --max--value ({})".format(args.min_ngram, args.max_ngram))
        sys.exit(1)
    with open(args.filename) as f:
 **#load data**users = []
        for line in f:
            profile = json.loads(line)
            users.append(profile['description'])
 **#create vectorizer**
        vectorizer = TfidfVectorizer(max_df=args.max_df,
                                    min_df=args.min_df,
                                    max_features=args.max_features,
                                    stop_words='english',
                                    ngram_range=(args.min_ngram, args.max_ngram),
                                    use_idf=args.user_idf)**#fit data**
        X = vectorizer.fit_transform(users)
        print("Data dimensions: {}".format(X.shape))**#perform clustering**
        km = KMeans(n_clusters=args.k)
        km.fit(X)
        clusters = defaultdict(list)
        for i, label in enumerate(km.labels_):
            clusters[label].append(users[i])**#print 10 user description of this cluster**for label, description in clusters.items():
            print("--------- Cluster {}".format(label+i))
            for desc in description[:10]:
                print(desc)

聚类分析的结果

因此,您可以看出,该脚本在根据用户个人资料中的简历对用户进行细分方面表现得相当不错。我在这个例子中使用了我的 twitter 个人资料,你可以看出我的社区中有一些投资者、技术爱好者、企业家和宗教人士。这让我想起了一句流行的话——“给我看你的朋友,我就知道你是谁” 。该脚本还可以用来更深入地研究其他用户的个人资料,以发现他们所属的隐含社区。

图形挖掘和会话分析

当许多用户参与对话时,一个“回复”网络就出现了。下图展示了 twitter 上的一个对话模型,节点是 tweets,边是“回复”关系。

对话模型

自然,这种结构可以很容易地映射到图形数据结构。该模型的一些关键要点:

  • 一对多基数
  • 没有周期

出于这些原因,我建立了一个有向无环图的模型,并使用这个图的属性和图论中的算法来挖掘对话。下面是我使用的图形挖掘技术的代码片段。

import sys
import json
from operator import itemgetter
import networkx as nxdef usage():
    print("Usage")
    print("python {} <filename>".format(sys.argv[0]))if __name__ == "__main__":
    if len(sys.argv) != 2:
        usage()
        sys.exit(1)fname = sys.argv[1]
    with open(fname) as f: #takes in a jsonl file of tweets as input
        graph = nx.DiGraph()
        for line in f:
            tweet = json.loads(line)
            if 'id' in tweet:
                graph.add_node(tweet['id'],
                                tweet=tweet['text'],
                                author=tweet['user']['screen_name'],
                                created_at=tweet['created_at'])
                if tweet['in_reply_to_status_id']:
                    reply_to = tweet['in_reply_to_status_id']
                    if reply_to in graph and tweet['user']['screen_name'] != graph.node[reply_to]['author']:  #if the user is not replying to themselves
                        graph.add_edge(tweet['in_reply_to_status_id'], tweet['id'])

**#Print some basic stats**print(nx.info(graph))**#Find most replied tweet** 
        sorted_replied = sorted(graph.degree(), key=itemgetter(1), reverse=True)most_replied_id, replies = sorted_replied[0]
        print("Most replied tweet ({} replies:".format(replies))
        print(graph.node[most_replied_id])**#Find longest conversation (longest path)**
        print("Longest discussion:")
        longest_path = nx.dag_longest_path(graph)
        for tweet_id in longest_path:
            node = graph.node[tweet_id]
            print("{} (by {} at {})".format(node['tweet'], node['author'], node['created_at']))
  • 节点的入度:给定 tweet 的回复数量
  • 根:对话的开始
  • 叶子:谈话的结束
  • 最长路径算法:用于查找最长对话的 tweet。
  • 我使用 networkX 库,因为它提供了图形结构的高效计算

动态地图

最后,为了总结我的分析,我通过在地图上绘制它们,创建了这些推文来自哪里的可视化表示。

地理数据的提取

使用 GeoJSON 库,我从一个流文件中提取了每条 tweet 的几何数据。我用这个地理数据的 geo.json 扩展名创建了一个输出文件

**#read dataset of tweets in jsonl file and produce a geoson file** associted with geographical data
import json
from argparse import ArgumentParserdef get_parser():
    parser = ArgumentParser()
    parser.add_argument('--tweets')
    parser.add_argument('--geojson')
    return parserif __name__ == "__main__":
    parser = get_parser()
    args = parser.parse_args()**#Read tweet collection and build geo data structure.**
    with open(args.tweets, 'r') as f: #read dataset of tweets
        geo_data = {
        'type' : "FeatureCollection",
        'features' : []
        }for line in f:
            tweet = json.loads(line)
            try:
                if tweet['coordinates']:
                    geo_json_feature = {
                        "type" : "Feature",
                        "geometry": {
                        "type" : "Point",
                        "coordinates" : tweet['coordinates']['coordinates']
                        },
                        "properties": {
                        "text" : tweet['text'],
                        "created_at" : tweet['created_at']
                        }
                    }
                    geo_data['features'].append(geo_json_feature)
            except KeyError:
                #Skip if json doc is not a tweet (errors, etc)
                continue
 **#Save geo data**
    with open(args.geojson, 'w') as fout:
        fout.write(json.dumps(geo_data, indent=4))

创建动态地图

我使用了 leav 库来生成一个交互式地图。优点是,HTML 无缝地处理 python 数据结构与 Javascript、HTML 和 CSS 组件之间的转换。

from argparse import ArgumentParser
import folium
from folium.plugins import MarkerCluster
import jsondef get_parser():
    parser = ArgumentParser()
    parser.add_argument('--geojson')
    parser.add_argument('--map')
    return parserdef make_map(geojson_file, map_file):tweet_map = folium.Map(Location=[50, 5], max_zoom=20)marker_cluster = MarkerCluster().add_to(tweet_map)geodata= json.load(open(geojson_file))for tweet in geodata['features']:
        tweet['geometry']['coordinates'].reverse()
        marker = folium.Marker(tweet['geometry']['coordinates'], popup=tweet['properties']['text'])
        marker.add_to(marker_cluster)**#Save to HTML map file**
    tweet_map.save(map_file)if __name__ == '__main__':
    parser = get_parser()
    args = parser.parse_args()
    make_map(args.geojson, args.map)

动态地图(缩小)

动态地图(放大)

正如你所看到的,这个脚本可视化了人们在 NBA 传奇人物科比·布莱恩特去世时发微博的不同地点。该脚本将来自特定区域的用户推文聚集在一起,并精确定位每条推文发布的确切位置。

这些结果是在事件公开后几个小时,从 15 分钟的推特风暴流中产生的。您可以在这里 查看完整的 地图并与之互动

结论

这都是为了挖掘 Twitter 数据。我真的很喜欢参与这个项目。我的 GitHub 上有完整的源代码,可以提供给任何对实现这个项目感兴趣的人。

挖掘 Covid19 上的 Twitter 话语

原文:https://towardsdatascience.com/mining-twitter-discourse-on-covid19-a2b6df66daee?source=collection_archive---------50-----------------------

通过自然语言处理技术和社会网络分析理解电晕话语

学分:eloutput.com

介绍

当 3 月 11 日世界卫生组织宣布新冠肺炎为疫情时,推特上出现了一个关于它的重大活动。这是一个预期的现象,因为社交媒体平台可以帮助实时跟踪自然灾害。在这方面,Twitter 似乎是了解这种情况下会发生什么的首选场所,以至于它已经更新了其新冠肺炎政策,声称将删除误导性的推文,这些推文可能“煽动人们采取行动,引起大范围的恐慌、社会动荡或大规模混乱”

在本帖中,我们将使用一些数据科学技术来研究围绕这种新型病毒的 Twitter 话语。出于这个原因,我们使用了这个数据集,它包含了大约 2700 万条使用冠状病毒相关标签的推文。即:

#冠状病毒,#冠状病毒爆发,#冠状病毒大流行,#covid19,#covid_19,#epitwitter,#ihavecorona。

考虑到这一点,我们尝试回答以下问题:

  • 更多关于冠状病毒的推文是否表明公众意识和严重性增强,并导致公众更容易接受限制传播的措施,如社会距离,从而减少感染?
  • 一些标签比其他的传播得更快吗?
  • 推特用户倾向于讨论(推特回复)或分享(引用的推特)吗?
  • 人们在推特上谈论特定的症状吗?

我们用一些基本的社交网络分析(第 1 部分)和 NLP(第 2 部分:即将到来)来做这件事。在这个项目中已经实现了不同的技术和任务,例如,文本处理、测量图形度量、使用 word2vec 嵌入文本分类模型、最大似然迭代学习、应用 SVD 进行降维等等。我们在 Github 上提供这个报告中的所有结果和代码。

虽然结果并不像我预期的那样,但总体来说,这次练习和学习值得我花时间去做。我学到了很多东西,提高了自己的黑客技能,应用了以前从未用过的技术。

探索性分析

首先,我们得到数据。Kaggle 提供了一个 API 来下载数据集,我准备了这个笔记本提供了一个详细的指南,提供了使用 API 访问数据集的必要步骤。数据摘录如下:

一些基本数据证实,世卫组织在 3 月 11 日宣布爆发疫情,在推特上引发了巨大的活动。下图显示了不同国家的每日推文量,其中美国的推文数量占全球推文总量的大部分。然而,从那时起,这种活动开始减少。

[## 各国的推文数量| Julian lb | plot ly 制作的折线图

Julianlb 的交互式图表和“按国家划分的推文数量”数据是一个折线图,显示了巴西、加拿大、西班牙…

chart-studio.plotly.com](https://chart-studio.plotly.com/~JULIANLB/5.embed)

一条 tweet 可以有两个属性。它可以是对另一条推文的回复和/或引用(如带有个人评论的转发)。否则,它只是一条简单的推文。人们可以使用这些属性来查看辩论(回复)或分享(引用/转发)是否解释了 Twitter 上围绕特定主题的活动。我们做到了这一点,但我们没有比较主题,而是比较了国家。下面的图表显示了不同国家的被引用、回复和推文总数。

下面的气泡图显示了相同的见解。

你可以在这里找到该图的互动版本:

[## 回复与引用散点图(占总数的%)

Julianlb 的“回复 vs 引用散点图(占总数的百分比)”的交互图和数据是 a;有回复(占总数的%)

chart-studio.plotly.com](https://chart-studio.plotly.com/~JULIANLB/52.embed)

第 1 部分:社会网络分析

我们的第一种方法涉及图论。你会在这个笔记本中找到本节所做分析的所有代码。学习图论的一些很酷的资源是:

  • Jure Lecsovek 的课程关于用图形进行机器学习
  • 有趣的阿尔伯特-拉斯洛·巴拉巴希的网络科学数字书。

我们继续对数据进行预处理。这尤其包括提取与每条推文相关的标签,并删除重复的标签。在第 2 部分中,我们将过滤掉非英语推文,并进行一些文本清理(即,删除符号、提及、URL、标点和停用词),以便我们可以训练 Word2Vec 模型(使用预处理的语料库将允许我们将推文转移到向量空间),而在第 3 部分中,我们将使用原始文本训练语言模型。

在下面的示例中,您可以大致了解数据经过预处理后的样子:

既然我们已经解析了与每条 tweet 相关联的标签,我们可以从共享一个公共标签的 tweet 创建回复网络。这种网络将由表示图的结构的边的列表组成,即回复的源和目的地用户。例如,下面的数据帧显示,用户 45993399 回复了用户 976542720 一条与标签#社交消失相关的推文。

这些链接/关系在下图中显示为一个网络,节点大小根据节点度数而变化。

在创建更多的图表之前,我们应该先看看语料库中最流行的标签(见下图)。

我们选择‘stayat home’,‘lockdown’,‘social distanding’,‘flattenthecurve’,‘masks 4 all’,‘trump’作为我们在分析中感兴趣的标签。然而,我们不会一次使用所有的推文来创建图表。相反,我们迭代地计算它们,将每天出现的新边添加到图形中。通过这种方式,我们可以看到标签图是如何随时间演变的。

为了跟踪每个图的结构演变,并将它们相互比较,我们基于图论中的共同属性来计算一些度量:

  • 节点数量:唯一用户的数量
  • 边数:用户之间的链接数或回复数(不加权)
  • 直径:网络中所有计算出的最短路径中最长的一条。
  • 平均度:边的数量除以节点的数量。
  • 度数等级:对数标度的度数直方图
  • 分类系数:分类系数表示网络中的节点倾向于连接到其他相似的节点。在这种情况下,我们计算链接节点对之间的度的皮尔逊相关系数。 r 的正值表示相似程度的节点之间的相关性,而负值表示不同程度的节点之间的关系。

可以计算许多其他有趣的度量,如平均路径长度 h、中心性度量、聚类系数。但是这些都是计算量很大的,所以我们将只使用前面提到的指标。

此外,我们为此分析设计了一个特定的指标,其正式定义如下。我们称之为“添加到图表中的新边”:

其中 G_t 是时间 t 和 V(G)处的图,E(G)是图 G 的顶点(节点)和边。

下图显示了我们的分析结果。从 3 月 4 日到 4 月 29 日,我们每天都计算所有网络的指标。

Plotly 中的一个交互式破折号被用来单独可视化标签指标(见下面的链接)

[## Hashtags Networks Metrics |由 Julianlb | plotly 制作的折线图

Julianlb 的“Hashtags Networks Metrics”的交互式图表和数据是一个折线图,显示了 stayathome、lockdown…

chart-studio.plotly.com](https://chart-studio.plotly.com/~JULIANLB/14.embed)

结果

首先,值得注意的是,与其他网络相比,#trump 的网络平均度显著增加,而其独特节点的数量减少。网络的直径也是如此。回想一下,直径是网络中最长的路径,我们可以推断#trump tweets 的到达范围比#flattenthecurve 要低。一个可能的原因是#trump 网络中的节点倾向于与和它们邻居相连的节点相连,我们可以通过看到更高的分类系数来支持这一假设。此外,与其他网络相比,#trump 的网络度具有较少的低度节点(连接数),而具有较多的高度节点。如果对网络的简并度进行分析,这个结果会更加丰富,这可能会给我们一些证据,证明巨魔可能部分解释了这种活动。

在相反的方向,#flattenthecuved 具有很大的扩散,达到最高直径,考虑到它的节点数和平均度较低。同样,#mask4all 是最小的网络,它的传播速度非常快,几天之内就达到了其他网络的平均直径。

Julian Lopez baas ch是一位经济学家转型的数据科学家,对人工智能充满热情。他获得了理学硕士学位。布宜诺斯艾利斯 Torcuato Di Tella 大学经济学学士和理学硕士。巴塞罗那 Pompeu Fabra 大学的智能交互系统。你可以在 Twitter Linkedin上找到他,或者你可以在他的 网站 上找到他的更多作品。

少数派报告是现实吗?

原文:https://towardsdatascience.com/minis-minority-report-a-reality-pt-1-2-813104fcf1f?source=collection_archive---------28-----------------------

使用数据和机器学习在犯罪发生之前预测犯罪

马特·波波维奇在 Unsplash 上的照片

鸣谢:我与 Bryan Bruno 和 Ksenia Luu 一起在西北大学为我们的研究生项目 capstone 进行犯罪预测项目。

注意:这是深入犯罪预测世界的两部分系列的第一部分。这第一部分将进入犯罪数据的初始 EDA,第二部分将深入应用人工智能来预测高犯罪率地区,甚至在它发生之前。

回到 2002 年,我看到汤姆·克鲁斯和他的预防犯罪小组在人们实际犯罪之前就逮捕他们。一个如此牵强的想法,以至于我在有生之年都没有想到会有这样的事情发生。现在,随着我们继续我们的人工智能革命之旅,海量数据和处理能力不仅变得更容易获得,而且获得成本也更低,“犯罪前”的现实正变得不那么反常。好吧好吧好吧。我们不要想得太多。这里涉及到人权问题(你知道,在被证明有罪之前是无辜的)。因此,这个想法,至少相对于我们当地的警察(联邦政府可能与我们的反恐工作关系更密切),可能仍然有点遥远。然而,不远的将来是找到更多的方法来利用我们拥有的与以前犯下的罪行有关的所有数据,并用其他数据来源丰富这些数据,以更好地了解未来可能发生更多类似罪行的地点和时间。这最终会导致警官更有效的安置、时间安排和日常工作,因为他们可以更科学地确定何时、何地以及为什么将他们的警官集中在他们社区的特定区域。最终结果不仅是更有效地利用我们的执法时间,而且是一个更安全的社区。真正的共生关系。

随着我们继续步入人工智能时代,每个行业都开始理解和利用人工智能的力量。无论是推荐产品或电视节目,预测欺诈,优化供应链,预测职业运动员的受伤情况,还是预测机器故障,仅举几例,我们正在看到人工智能在各地得到应用。如果没有某种形式的人工智能,当今社会几乎没有什么问题是无法解决或优化的。人工智能的力量是巨大的。然而,正如《蜘蛛侠》中的本叔叔所说的那样,“能力越大,责任越大”并不是所有的行业都承担了采用人工智能的能力和潜力的全部责任。一个这样的行业是执法部门。更具体地说,是我们尊贵而卑微的地方警察局。

我首先要说的是,我不会因为当地警方对游戏的反应稍慢而责怪他们。他们通常预算较少,使用陈旧的数据系统,当他们理所当然地将所有注意力放在周围社区的福祉和安全上时,他们几乎没有时间去挖掘数据和数字。由于这种差距,将数据科学(即数据科学)引入他们的日常世界是一个巨大的机会。

事不宜迟,让我们直接进入数据。我住在美丽的城市明尼阿波利斯,所以很自然,我会调查发生在明尼阿波利斯的犯罪事件。该市在位于的 opendata 网站上提供了超过 10 年的历史犯罪数据。在下载和阅读了 10 年的犯罪数据集后,我准备好了……在对数据进行了大量的清理和预处理,如格式化、命名、子集、分组、连接、删除空值等之后……你们得到了你们都去过的图片,完成了。然后我就购买了(很便宜!)从 openweathermap 开始,明尼阿波利斯 30 多年的每小时天气数据。目的是让我可以加入这些数据,看看明尼阿波利斯的天气如何影响犯罪的每小时模式。提示一下,因为这里真的很冷,有时真的很热,天气会在这一切中起很大的作用。总之,我有一个超过 200,000 行的相当大的数据集。

首先,让我们看看犯罪在过去 10 年中是如何波动的,是否有任何季节性或周期性的行为。

明尼阿波利斯的犯罪率在过去 10 年里与日俱增

显然,这里有一些季节性的行为。我想知道这是否与我们在“Minne-snowta”中必须应对的极端温度有关。嗯嗯。

明尼阿波利斯市过去 10 年的临时犯罪统计

有趣的是,天气似乎确实对犯罪有一些影响,因为极端情况下犯罪最少,然而,在这里看到一个双模态结构有点令人惊讶。我的猜测是更正常的钟形曲线,但这肯定会要求更深入地探究可能导致这种情况的原因。那星期几和一天中的时间呢?这些与犯罪有潜在的关联吗?

也许有点令人惊讶的是,我们认为周一、周二和周三是犯罪率最高的日子——非常有趣!也许更多的盗窃和入室行窃,因为人们回去工作,把他们的房子和/或汽车留在无人看管的地方?

正如预期的那样,我们看到犯罪在一天中的不同时间波动很大。它在中午到下午 2 点的时间段达到高峰,在凌晨 2 点到 6 点左右逐渐消失,显然所有的罪犯都想睡个好觉。

犯罪类型呢?嗯,看起来明尼阿波利斯有很多盗窃癖,因为“其他盗窃”、“机动车盗窃”、“住宅入室盗窃”、“汽车大盗窃”和“入店行窃”是最常见的五种犯罪(我注意到可能有机会将一些类似的犯罪归为更广泛的类别,如“暴力犯罪”、“盗窃/抢劫”、“汽车相关犯罪”等)。取决于分类模型做得有多好)。

现在,让我们来了解一下哪里是犯罪发生最多的地方。当然,有些社区比其他社区更值得关注。

好的,这些是明尼阿波利斯犯罪率最高的 15 个街区。西部市中心是明尼阿波利斯市中心的心脏,这里的犯罪率绝对是最高的。太好了!除非你不是明尼阿波利斯人,否则你根本不知道这些街区在哪里!这就是谷歌地图的用武之地。幸运的是,python 有一个名为 gmaps 的伟大包来处理谷歌地图。这允许您绘制 google 地图并在地图上对数据进行分层,以便从地理角度交互式地查看数据集的不同元素。它对于创建地理热图非常有用,这正是我要做的。我将首先通过创建一个以明尼阿波利斯市的质心为中心的谷歌地图来创建基础图层。实例化基础地图后,我将创建一个热点图图层,放置在显示明尼阿波利斯市“盗窃”犯罪热点图的基础图层之上。

(注意:在用 python 创建谷歌地图时,你需要创建一个谷歌 API 密匙来验证你对谷歌的请求。最好将这个 API 键保存在全局环境变量中,而不是硬编码。gmaps 的一大资源就是 这里 )。

使用谷歌地图的明尼阿波利斯犯罪热图

瞧啊。这漂亮地绘制了一个交互式热图,您可以更好地从视觉上了解明尼阿波利斯市的高犯罪率地区。在本案中,我们关注的是与“盗窃”相关的犯罪。不幸的是,我不能在 Medium 中嵌入具有该功能的地图(据我所知),但你们已经明白了要点。

最后,也是为了好玩,我将使用 geopandas 读取明尼阿波利斯警区的形状文件(也可以在他们的 opendata 站点上找到)。这样做的目的不是展示什么令人兴奋的东西,而是展示如何轻松地将形状文件读入 python,从而在 EDA 中获得一些潜在的有价值的视觉发现。

明尼阿波利斯警区

如您所见,geopandas 使得在 python 中导入和使用形状文件变得非常容易。它们最终表现得和正常的熊猫数据帧非常相似,这太棒了!因此,我们在明尼阿波利斯有五个区,第三区的总面积最大(随后是最高的总犯罪率),第一区的每平方英尺犯罪率最高,因为这个区覆盖了我们整个市区,所以它比所有其他区的人口密度都高。请注意,我做了一些进一步的分析,以获得我没有包括在这里的见解。这张图显示了明尼阿波利斯的选区在地理上是如何划分的。

很明显,在 EDA 中还有很多方法可以分割和可视化这些数据,但是为了简洁起见,我不会一一列举。真正的意图是给你一个想法,我们如何开始思考重要的犯罪预测——不仅仅是明尼阿波利斯,而是任何大都市。我还想引入更多的数据源来进一步丰富这个数据集,并确保我可以从机器学习模型中获得高质量的预测。说到 ML,这将是所有这一切的下一个阶段,最终目标是高质量的机器学习(或者甚至深度学习,如果我们想疯狂的话!)模型,准确预测未来犯罪高发区。我希望你能留下来!

Github 链接->https://github . com/michaelhaugan/NWU-研究生-课程/树/硕士/顶点

MissForest:最佳缺失数据插补算法?

原文:https://towardsdatascience.com/missforest-the-best-missing-data-imputation-algorithm-4d01182aed3?source=collection_archive---------17-----------------------

作者创建的图像。

告别 KNN-估算

缺失数据经常困扰现实世界的数据集,因此输入或填充缺失值具有巨大的价值。不幸的是,标准的“懒惰”插补方法,如简单地使用列中值或平均值,效果并不好。

另一方面,KNN 是一种基于机器学习的插补算法,已经取得了成功,但需要调整参数 k ,此外,容易受到 KNN 的许多弱点的影响,如对离群值和噪声敏感。此外,根据具体情况,这种方法的计算成本可能很高,需要存储整个数据集并计算每一对点之间的距离。

MissForest 是另一种基于机器学习的数据插补算法,它基于随机森林算法。该算法的创造者 Stekhoven 和 Buhlmann 在 2011 年进行了一项研究,在随机引入缺失值的数据集上比较了插补方法。MissForest 在所有指标上都优于所有其他算法,包括 KNN 估算,在某些情况下超过 50%。

首先,使用中位数/众数插补填补缺失值。然后,我们将缺失的值标记为“Predict ”,将其他值标记为训练行,这些训练行被输入到一个随机森林模型中,该模型被训练为基于Score预测Age。然后填充为该行生成的预测,以生成转换后的数据集。

假设数据集被截断。作者创建的图像。

这种遍历缺失数据点的过程会重复几次,每次迭代都会改进越来越好的数据。这就像站在一堆石头上,同时不断增加更多的石头来提升自己:模型使用它当前的位置来进一步提升自己。

该模型可以在接下来的迭代中决定调整预测或者保持预测不变。

作者创建的图像

迭代继续进行,直到满足某个停止标准或经过一定次数的迭代。一般来说,数据集在四到五次迭代后会变得很好,但这取决于缺失数据的大小和数量。

使用 MissForest 有很多好处。首先,它可以应用于数字和分类的混合数据类型。对分类数据使用 KNN 估算需要首先将其转换为某种数值度量。这个尺度(通常是 0/1,带有虚拟变量)几乎总是与其他维度的尺度不兼容,所以数据必须标准化。

类似地,不需要预处理。由于 KNN 使用了朴素的欧几里得距离,所以各种各样的操作,如分类编码、标准化、规范化、缩放、数据分割等。以确保它的成功。另一方面,随机森林可以处理这些方面的数据,因为它不像 K 近邻那样对特征关系进行假设。

MissForest 对噪声数据和多重共线性也很稳健,因为随机森林有内置的特征选择(评估熵和信息增益)。当数据集的预测值较弱或要素之间的相关性较大时,KNN 估算法的预测结果较差。

KNN 的结果也在很大程度上取决于 k 的值,这必须通过一种基本上是无所不能的方法来发现。另一方面,随机森林是非参数化的,因此不需要调整。它还可以处理高维数据,并且不像 KNN 估算那样容易受到维数灾难的影响。

另一方面,它也有一些缺点。首先,尽管它占用的空间较少,但如果数据集足够小,运行 MissForest 的成本可能会更高。另外,它是一个算法,而不是一个模型对象;这意味着它必须在每次估算数据时运行,这在某些生产环境中可能行不通。

使用 MissForest 很简单。在 Python 中,可以通过missingpy库来完成,它有一个类似于sklearn的接口,并且有许多与RandomForestClassifier / RandomForestRegressor相同的参数。完整的文档可以在 GitHub 这里找到。

模型的好坏取决于数据,因此必须妥善处理数据集。下次需要估算缺失数据时,考虑使用 MissForest!

感谢阅读!

如果你对最新的文章感兴趣,可以考虑订阅。如果你想支持我的写作,通过我的推荐链接加入 Medium 是一个很好的方式。干杯!

缺失数据对冰淇淋销售与温度相关性的影响

原文:https://towardsdatascience.com/missing-data-effects-on-the-correlation-between-ice-cream-sales-and-temperature-f4bb2b3fcde1?source=collection_archive---------23-----------------------

Freepik 上的用户 6694312 的照片

处理缺失数据的最佳实践

缺失数据存在于许多现实世界的数据集中。在这里,我分享一个最好的技术来处理这个问题。

每当我遇到一个没有丢失数据的数据集时,我会立刻开始对的数据完整性和数据清理产生怀疑,据说数据清理是事先完成的。

我们永远不应该闭上眼睛,避免处理缺失的数据。我们需要调查和理解为什么我们可能没有缺失数据,和/或为什么我们有缺失数据。在任何情况下,问一问也无妨,但此外,真正关心我们处理的数据是我们的责任

两个经验法则:总是质疑没有缺失数据的数据集!同样,总是质疑数据集缺失数据!

虽然人们可能会认为没有缺失数据是一件好事,事实也确实如此,但现实情况是发现数据集缺失数据是非常常见的。出现这种现象的原因多种多样,了解原因对于缓解这一问题非常重要。我们今天的重点将是我们可以用来更好地管理丢失数据的技术,而不是为什么会发生这种情况。

特别是,我们将关注数值的缺失数据,因为这通常是处理缺失数据时的瓶颈,也是很多人出错的地方。

也就是说,基本上有两种主要方法来处理这种常见问题:

在存在缺失数据的地方(比如行和列)丢弃观察值。

b ----利用插补,根据某种统计指标或其他参数,在空白处填入数值。

缺失数据揭晓

在探索任何数据集时,首先要做的事情之一就是寻找丢失的值。一旦您检测到 NAs(缺失值)的存在,您希望努力理解它们缺失的原因,以及获取“原始”数据的努力是否值得。或者即使有这样做的可能性。你必须尽快决定取舍。

事实是,无论您使用何种技术来处理丢失的数据,都不会比拥有原始数据更好。所以,如果你有办法,努力获得一个没有缺失数据的数据集总是好的(这听起来很天真,是吧?!).

在首次评估从未见过的数据集时,您可以遵循以下三个基本步骤——假设它有缺失数据:

I-获取缺失数据的总数。建立处理它们的初始阈值。这将取决于数据集的大小和性质,这里没有“一刀切”的解决方案。例如,如果全部缺失数据只占全部数据的大约 1%,您可能想要决定丢弃那些观察值。请记住,每次删除要素和/或观测值时,您都有可能降低您的分析能力。

II——探究我们丢失数据的原因。一种方法是进行一项名为“利特尔完全随机缺失(MCAR)测试”的测试。该测试将检查缺失数据是否完全随机缺失。

III —检查缺失数据的模式。常见的模式有任意(随机)和单调(系统)。要检查模式,您可以绘制一个图表来帮助您可视化缺失的数据。通常,倾向于随机模式的任意是我们发现最多的。

好了,现在我们已经了解了一点皮毛,让我们回到处理缺失数据的两个主要策略。

A——在存在缺失数据的情况下删除观察值

我注意到许多研究论文在面对缺失数据时采取了这种方法。在许多情况下,人们决定放弃特性和观察。我猜这似乎是一个“安全的地方”,但事实是,通过删除数据,我们减少了优化分析的机会。因为有些数据集很难获得,所以我们希望尽可能避免丢弃观察值和特征。

我们应该做的是,测试不同的技术,并寻找可以产生更好结果的输出。为此,考虑你试图回答的问题,以及你试图解决的问题。完美的世界是没有缺失数据,但事实是:真实世界的数据,最有可能的是,会有缺失数据,没有一种完美的方式或技术来处理这个问题。

b——利用插补,根据某种统计指标或其他参数,用一个值填充空白空间。

这就是事情变得有趣的地方。有不同的插补技术可供我们选择。插补可能很可怕,在某些情况下并不理想。这是一个崎岖的地形,也许是人们更喜欢放下数据的原因之一。

在下一节中,我们将进行一项实验,看看处理缺失数据的三种不同方法会如何影响,例如,两个变量之间的相关性:给定年份的温度和冰淇淋销售额。

实验

照片由 Freepik 上的 stolyevych_yuliya 拍摄

在这个实验中,我向您展示了三种处理缺失数据的实用方法:

1-删除存在缺失数据的行。

2-使用平均值/中值输入缺失数据的值。

3-使用最大似然估计输入数据。

这个想法是为了展示这三种技术是如何影响冰淇淋销售和温度之间的相关性的。而且,我们会看到最坏的和最好的一个来使用。我提醒你,我们必须明白每个数据集都是独一无二的,所以,如果你在不同的数据集上尝试,你可能会得到不同的结果。

思路是打开讨论,给出思路,一定要 实验 之前,致盲,挑一个手法。

在下表中,您将看到一年中所有月份的登记值。我们有温度(华氏)和月销售额(美元)的所有值。如您所见,没有丢失值。

这是我们的出发点,也是我们在面对缺失数据时决定如何处理时,用来分析上述技术影响的基准。

表 1——冰淇淋月销售额和各月温度。数据来源可以在这里找到。

下面是原始数据集的一些基本统计数据(没有 NAs)。你不会在这里看到标准差,因为我想保持简单明了。然而,根据您选择的处理缺失数据的技术,您也可以预期它对标准差(和方差)的影响。

表 2 —基本统计数据

此外,这里有一个图,这样我们可以更好地形象化事件随时间的变化:

图 1 —冰淇淋销售和温度随时间的变化。

单看这两个图,就能看出一个很强的格局。两条线互相模仿。换句话说,如果一个上升,另一个也会上升,反之亦然。我不会在这里探究因果关系和相关性之间的概念。

但是温度和销量的相关性大概是 0.96 。这是一个非常强的相关性。在这种情况下,它是高度正相关的。点击此链接此处了解更多信息。

我不会在这篇文章中涉及共线性,但是值得一提的是,如果我们正在处理一个回归模型,我们将不得不调查共线性。在接下来的图中,我们可以找到相关分数和其他见解,如我们正在研究的这两个变量的分布。

图 2 —成对

我们可以通过绘制下面的散点图,用置信区间来更好地形象化这种强相关性。当我们开始处理这个数据集时,这将是一个需要记住的重要情节。

图 3—相关图

好吧,这都是非常基本的分析。许多人会认为,如果温度升高,冰淇淋的销量也会增加。到目前为止没什么特别的,对吧?!

做所有这些的目的只是为了展示在一个“完美的”数据集上执行的分析。我所说的完美,只是指没有丢失数据。现在我们知道真正的数字是什么样的了。

当我们第一次得到一个有缺失值的数据集时,问题是如果我们有所有的数据(没有 NAs ),我们永远不会知道事情看起来会像一样。这就是我做所有这些初步评估的原因,向你展示“完美世界”。

1-删除存在缺失数据的行。

继续我们的实验,我们知道在数据集中引入缺失值。例如,查看下表,您会注意到我们不知道三月份销售了多少(例如,“月销售额”列在三月份为 NA)。

表 3 —引入缺失值(NAs)。

在这种方法中,我们将删除任何一行——在本例中是 month——在任何一列中缺少数据。这种方法也被称为“完全案例分析”。问题是,在这个过程中,我们最终丢弃了我们拥有的原始数据。

如下所示,删除所有 NAs 后,三月份的所有数据都不见了。最重要的是,我们现在有更少的观察。我们有 7 个,而不是 12 个。

表 4 —删除 NAs 后

原来,现在温度和销量的相关性是 0.85 。虽然,我们可以说这种新的相关性仍然很强,但这已经是一个显著的下降了。

问题是,当你用一个真实的数据集删除变量时,你永远不知道你损失了多少。在这里,我们能够测量一点点,并了解丢弃变量会如何影响您的分析。

看看删除 NAs 后的下一个图:

图 4 —删除 NAs 后成对出现

根据一般经验,如果丢失的数据量很小,我们应该决定删除变量。大概是 1%左右。显然,这不是一成不变的,你必须不断尝试。

2-使用平均值/中值输入缺失数据的值。

我承认我对此有罪。我的意思是,谁以前没用过均值中位数输入数据?!这是一个人想到的最直观的想法之一。但是请从现在开始,不要再用这种方法了。

“我们是认真的,但我保证我们不刻薄”——洛德

使用用于删除 NAs 的同一个表,我们知道用平均值填充缺失值如下:

表 5 —缺少值的基本统计数据

请记住,使用平均值中位数,结果是非常相似的。为了简单起见,我只展示了使用平均值的例子。但是,使用中间值也是不好的——尽管通常危害较小。

表 6-用平均值填充缺失值

如上所示,我们保留了相同数量的观察值——12 个月——但是使用均值的效果是毁灭性的。

我们的相关性直线下降。现在,温度和销售额之间的相关系数为 0.36 。见下文:

图 5 —用平均值填充 NAs 后成对出现

简而言之,我们可以假设这两个变量之间不再有很强的相关性。这就是在这个特定的实验中,使用平均值对我们的数据集的影响。

这完全影响了我们的分析。看看下面这张图:

图 6-无显著相关性

假设你在卖冰淇淋。如果你知道接下来一周左右气温会上升,通常情况下,你会为你的销售增加做好准备。但是,由于我们得到的这种微弱的相关性,你不能再到处去买太多的冰淇淋了!

那是因为置信区间太大了。虽然你仍然可以期望增加你的销售额,但你不能在这上面下太大的赌注。仅这一点就使决策过程变得复杂。

在这种情况下,人们可能会发现自己“不得不”赌博,而这绝对是我们不想做的事情!

我是说,永远不要用卑鄙的手段!

3-使用最大似然估计输入数据。

我们能做得更好吗?我们当然可以!

输入数据的最佳方法之一是最大似然估计(MLE)。这种方法“为具有(潜在)缺失值的多元正态数据寻找均值向量和方差-协方差矩阵的最大似然估计。”得到协方差分数后,我们需要将它从协方差转换成相关性。在此查看文档。

正如我们在下面看到的,我们得到了温度[2]和销售[3]之间的关联分数为 0.93

表 7 —使用最大似然估计后的相关性

使用这种方法的缺点是我们没有太多可用的文档。然而,实验是编写和做所有这些测试的全部意义。

还有其他可用的方法,我没有时间在这里介绍,如鼠标(使用链式方程的多重插补)。更多此处。

一言以蔽之,没有处理缺失数据的神奇公式。我们想要的是,减轻任何给定数据集中缺失数据的影响。

结论

最大的收获是,我们必须尝试不同的方法来处理缺失数据。在这里起作用的,在不同的数据集上可能不起作用(真的吗?).

我的目标是引起人们对这个问题的关注,因为人们经常忽视它。他们选择了一种方法,并与之结合。尝试不同的事情,看看什么能给你最好的结果,这总是好的。

我们在这里看到,使用意味着,是最差的方法;但是利用 MLE 是最好的方法。剔除缺失值比使用均值要好。

局限性之一是因为这个数据集太小,而且相关性很强,所以很难得出合理的结论。例如,即使删除了数据,相关性仍然很强。当在不同的数据集上尝试这种技术时,情况可能不是这样。

下次当您遇到包含 NAs 的数据集时,请考虑一下您可以更好地处理它的可能性。只是永远不要考虑使用平均值或中间值。求你了。

额外收获:一个简单的最佳实践

警告!这个例子中的数据和我们到目前为止讨论的内容无关。

让我确保在处理缺失数据时,特别是在引入插补时,强调一个 良好实践

不幸的是,许多人在输入数据时,不管用什么方法,都倾向于填充原始特征(行/列)中缺失的值。这样做的问题是,假设您将数据传递给其他人来处理,她/他将永远不会知道我们丢失了数据,他们也不会知道您使用的方法。最重要的是,你也可以忘记你对数据集做了插补。遵循这个简单的技巧可以帮助您获得整洁的文档处理。

如果你还是不明白,这里有一个我想出来的例子(这都是哑的/虚构的数据):

表 8—缺失数据最佳实践

分解这张桌子:

想象一下,假设你销售一些电子产品,出于某种原因,你没有笔记本电脑的价格。您决定应用一些插补(IMP)来填充该空间,但不是直接在价格列上这样做,而是创建一个新列 Price_IMP ,并用一个值填充该空白空间。接下来,创建一个附加特征— Price_IMP_Y/N —作为应用插补的快速眼点的二进制指示器。瞧啊。你只是创造了一个简单的方法来跟踪插补。

如何命名你的新特性取决于你和你的团队。这里的要点是,无论何时你使用插补,你必须以某种方式指明,并保持原始特征的完整性。别忘了透露你用了什么方法,为什么。

缺失数据插补

原文:https://towardsdatascience.com/missing-data-imputation-5c664ad77ef?source=collection_archive---------13-----------------------

关于如何处理缺失数据插补的概念和技术

来源:https://pixabay.com/pt/

在的上一篇文章中,称为 缺失数据的问题 我介绍一下这个问题的基本概念。在本文中,我将解释一些关于如何为其他值替换缺失值的技巧。

归罪的想法既诱人又危险。它之所以诱人,是因为它可以诱使用户进入一种愉快的状态,相信数据毕竟是完整的;它之所以危险,是因为它将问题足够小,可以以这种方式合法处理的情况和应用于真实和估算数据的标准估计值存在重大偏差的情况混为一谈[Little and Rubin,2019]。

简单数据插补

从本质上讲,简单数据插补是一种用于为每个缺失项目插补一个值的方法。根据 Little 和 Rubin [2019]的说法,简单数据插补可定义为缺失值预测分布的平均值或提取值,需要一种基于观察数据创建插补预测分布的方法,并定义了生成该分布的两种通用方法:显式建模和隐式建模。

在显式建模中,预测分布基于正式的统计模型,例如多元正态分布,因此假设是显式的。显式建模的例子有平均插补、回归插补、随机回归插补。

在隐式建模中,重点是算法,这意味着一个底层模型。假设是隐含的,但仍然需要仔细评估,以确保它们是合理的。这些是隐式建模的例子:热卡插补、替换插补和冷卡插补。

显式建模

1- 平均值插补:缺失值被替换为特定单元或类内形成的所有数据的平均值。这种技术不是一个好主意,因为平均值对异常值等数据噪声很敏感。Tavares 和 Soares [2018]将其他一些技术与均值进行了比较,并得出均值不是一个好主意的结论。

2- 回归插补:缺失值替换为对该单元观察到的项目的缺失项目回归生成的预测值。均值插补可被视为回归插补的特殊情况,其中预测变量是对均值进行插补的单元格的虚拟指标变量[Little and Rubin,2019]。

3- 随机回归插补:缺失值替换为回归生成的预测值加上反映预测值不确定性的残差。正态线性回归和逻辑回归模型就是例子。

隐式建模

1- 热卡插补:这种情况下的想法是,在执行数据插补之前,使用一些相似性标准对数据进行聚类。这是最常用的技术之一。

2- 替换:这种技术在调查环境中更方便,包括用当前样本中未观察到的替代单位替换无响应单位。

3- 冷板插补:该技术包括替换外部来源的一个常数的缺失值,例如来自同一调查的先前实现的值。这种技术类似于替换,但是在这种情况下,使用常数值,并且在替换技术中,可以使用不同的值来替换丢失的值。

4- 复合方法(混合):该技术建议结合不同的其他技术来预测似是而非的值。例如,结合热卡和回归插补来预测缺失值(这种方法与下面显示的方法略有不同)。

多重数据插补

单一插补用单一值替换未知缺失值,然后将其视为真实值[Rubin,1988]。因此,单一插补忽略了不确定性,几乎总是低估方差。多重插补通过考虑插补内的不确定性和插补间的不确定性,克服了这个问题。

多重数据插补方法为每个缺失值产生 n 个建议。这 n 个值中的每一个都被指定为似是而非的值,并且创建 n 个新的数据集,就好像在每个数据集中发生了简单的插补一样。通过这种方式,一个表中的一列生成 n 个新的数据集,使用特定的方法对这些数据集进行逐个分析。这些分析在第二步中被组合,生成或合并该数据集的结果。图 1 说明了这些概念,多重插补流程的步骤如下:

1-对于在数据集记录中具有缺失值的每个属性,生成一组要估算的 n 值;

2-对每个数据集执行统计分析,该数据集是通过使用在前一项中生成的 n 个替换建议之一而生成的;

3-将所执行分析的结果进行组合,以产生一组结果。

图 1:多重插补示意图,其中 m 是插补次数。来源:改编自[Schaferand Graham,2002 年]

我在文献中没有发现选择 n 的数目的共识,并且由于为每个新的似是而非的值生成了大量的数据集,因此为 n 选择一个高的数目可能对整个过程没有执行性。

复合数据插补

由 Soares [2007]提出,复合插补是一类插补技术,它在预测待插补的新值之前,结合执行 KDD(数据库中的知识发现)过程中使用的一个或多个任务。例如,组合执行像 k-means 这样的聚类算法和/或像 PCA 这样的选择特征算法,然后执行一些机器学习算法来预测新值。这种技术可用于单次或多次插补。Soares[2007]还介绍了缺失数据插补委员会的概念,即在所有预测中,用某种统计方法评估更合理的值。

综合插补流程基于以下要素的定义:

  • ᵢ:数据库知识发现过程中的一项任务。
    例子:T =特征选择,T =聚类,T₃ =关联规则的创建,T₄ =插补,等等。
  • →:定义 KDD 任务优先顺序的运算符。表达式 XY 表示任务 X 在任务 Y 之前。
    举例:聚类→插补表示聚类任务将先于插补任务。
  • E( v ,b):从数据库 b 中输入一个属性 v 过程中使用的策略 E( v ,b)用 t→t→……→t表示,其中 T 必然是一个插补任务。
  • α:插补过程中使用的算法。
    举例:α=均值,α= k 近邻算法。
  • 定义
    算法应用优先顺序的操作符。表达式αα意味着在算法α之前应用算法α
  • P( v ,b):从数据库 b 中输入属性 v 的过程中使用的插补方案,P( v ,b)用
    ααα表示,其中α必然是
    插补的算法。
    例:ααα₃代表
    算法的顺序应用α= k 形心算法,α=主成分分析,α₃= k 近邻算法。
  • ψ ᵢ: 应用α算法的实例,根据参数θᵢ=ᵢ₁,θᵢ₂,…,θᵢₚ}. ψᵢ = f(Aᵢ,θᵢ)
  • I(v,B):数据库 B 的属性 v 的插补计划的实例,由算法应用的 q 个实例的有序序列表示。ψψ……ψₚ,其中ψ这必然是
    插补算法应用的一个实例。
  • ε(I( v,B)): 运行计划
    属性 v 的实例时的误差的度量。

插补计划假定的插补值集合将由该计划所有实例中平均误差最低的实例值组成(ε(p(v)=ε(I(v)),其中ε(I(v)<ε(I

这样,我们可以将复合插补定义为在补充数据库 B 的属性 v 中缺失数据的过程中应用一种或多种策略。

级联数据插补

Ferlin [2008]提出的级联插补法考虑了之前的数据插补法,以执行下一次插补法。先前补充的数据组在级联效应中被重新用于后面组的插补。采用这种分而治之的方法,可以简化估算过程,提高估算的数据质量。在你的实验中,Ferlin [2008]利用了 Soares [2007]提出的方法,并在输入数据之前执行一个 KDD 任务(在她的例子中是聚类)。图 2 说明了这些概念。

图 2:级联插补概念。来源:改编自[费林,2008 年]

在本文中,我展示了一些处理缺失数据插补的技术和概念。这类问题没有解决方法。因此,必须对每个病例进行研究,以确定更好的治疗方法。在接下来的文章中,我将展示一些数据插补的结果。

参考

  1. 斯查费和格雷厄姆(2002 年)。缺失的数据:我们对技术现状的看法。心理学方法,7(2):147。
  2. Little,R. J .和 Rubin,D. B. (2019 年)。缺失数据的统计分析,第 793 卷。
  3. Tavares,R. d. S .,卡斯塔涅达,r .,Ferlin,c .,Goldschmidt,r .,Alfredo,L. V. C .,Soares,J. d. A. (2018)。关于起诉法官的程序。塞尔索·苏科·达·丰塞卡·塞费特/RJ,第 1-6 页。
  4. 鲁宾博士(1988 年)。多重插补概述。美国统计协会调查研究方法部分的进展,第 79-84 页。Citeseer。
  5. 你听到了吗 j。(2007 年)。数据挖掘中的预处理:一项补充比较研究。博士论文。系统工程与计算。ufrj 2007。
  6. 费林克劳迪娅。多元计费:级联方式。里约热内卢,RJ,2008 年。

如何用 Python 和 KNN 处理缺失数据

原文:https://towardsdatascience.com/missing-value-imputation-with-python-and-k-nearest-neighbors-308e7abd273d?source=collection_archive---------16-----------------------

使用机器学习算法处理缺失数据

缺失值插补并不是一项很难完成的任务。方法范围从简单的平均值插补和完全删除观察到更先进的技术,如小鼠。如今,更具挑战性的任务是选择使用哪种方法。今天我们将探索一种简单而高效的估算缺失数据的方法——KNN 算法。

背景照片由 freepik 创作

KNN 代表K-最近邻,这是一种基于定义的最近邻数量进行预测的简单算法。它计算要分类的实例与训练集中所有其他实例之间的距离。您可以从这里了解如何从头开始实现它:

[## 让我们从头开始制作一个 KNN 分类器

你只需要一点钱和一点时间。包括源代码。

towardsdatascience.com](/lets-make-a-knn-classifier-from-scratch-e73c43da346d)

顾名思义,我们不会将该算法用于分类目的,而是用于填充缺失值。本文将使用房价数据集,这是一个简单而著名的数据集,只有 500 多个条目。这里可以下载。

这篇文章的结构如下:

  • 数据集加载和浏览
  • KNN 插补
  • 估算优化
  • 结论

数据集加载和浏览

如前所述,您可以通过链接下载房屋数据集。此外,确保你已经进口了熊猫熊猫。这是前几行的样子:

作者图片

默认情况下,数据集的缺失值非常少,一个属性中只有五个缺失值:

作者图片

让我们改变这一点。这不是你通常会做的事情,但是我们需要更多的缺失值。首先,让我们创建两个随机数数组,范围从 1 到数据集的长度。第一个数组有 35 个元素,第二个有 20 个元素(任意选择):

i1 = np.random.choice(a=df.index, size=35)
i2 = np.random.choice(a=df.index, size=20)

下面是第一个数组的样子:

作者图片

你的数组会有所不同,因为随机过程是随机的。接下来,我们将用 NANs 替换特定指数的现有值。方法如下:

df.loc[i1, 'INDUS'] = np.nan
df.loc[i2, 'TAX'] = np.nan

现在让我们再次检查丢失的值—这一次,计数不同:

作者图片

这就是我们从估算开始所需要的。让我们在下一节做这件事。

KNN 插补

整个插补归结为 4 行代码,其中一行是库导入。我们需要来自sklearn.imputeKNNImputer,然后以一种众所周知的 Scikit-Learn 方式创建它的一个实例。该类需要一个强制参数—n_neighbors。它告诉估算者参数 k 的大小。

首先,让我们选择一个任意的数字 3。我们稍后将优化这个参数,但是 3 已经足够好了。接下来,我们可以在我们的估算器上调用fit_transform方法来估算缺失数据。

最后,我们将把得到的数组转换成一个pandas.DataFrame对象,以便于解释。代码如下:

from sklearn.impute import KNNImputer

imputer = KNNImputer(n_neighbors=3)
imputed = imputer.fit_transform(df)
df_imputed = pd.DataFrame(imputed, columns=df.columns)

那不是很容易吗?现在让我们检查缺失值:

作者图片

不出所料,一个都没有。然而,还有一个问题——我们如何为 K 选择正确的值?

估算优化

由于目标变量是连续的(MEDV),该住房数据集旨在通过回归算法进行预测建模。这意味着我们可以训练许多预测模型,其中缺失值用不同的 K 值进行估算,并看看哪一个执行得最好。

但是首先,进口。我们需要从 Scikit-Learn 获得一些东西——将数据集分成训练和测试子集,训练模型,并验证它。我们选择了随机森林算法进行训练,但是这个决定又是任意的。RMSE 被用于验证:

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error

rmse = lambda y, yhat: np.sqrt(mean_squared_error(y, yhat))

以下是执行优化所需的步骤:

  1. 迭代 K 的可能范围——1 到 20 之间的所有奇数都可以
  2. 使用当前 K 值进行插补
  3. 将数据集分成训练和测试子集
  4. 符合随机森林模型
  5. 在测试集上预测
  6. 使用 RMSE 评估

这听起来很多,但归结起来大约有 15 行代码。以下是片段:

def optimize_k(data, target):
    errors = []
    for k in range(1, 20, 2):
        imputer = KNNImputer(n_neighbors=k)
        imputed = imputer.fit_transform(data)
        df_imputed = pd.DataFrame(imputed, columns=df.columns)

        X = df_imputed.drop(target, axis=1)
        y = df_imputed[target]
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

        model = RandomForestRegressor()
        model.fit(X_train, y_train)
        preds = model.predict(X_test)
        error = rmse(y_test, preds)
        errors.append({'K': k, 'RMSE': error})

    return errors

我们现在可以用修改后的数据集(3 列中缺少值)调用optimize_k函数,并传入目标变量(MEDV):

k_errors = optimize_k(data=df, target='MEDV')

就是这样!k_errors数组看起来像这样:

作者图片

或者,直观地表示:

作者图片

看起来 K=15 是给定范围内的最佳值,因为它产生的误差最小。我们将不讨论错误的解释,因为这超出了本文的范围。让我们在下一部分总结一下。

离别赠言

缺失数据插补很容易,至少是编码部分。是推理让它变得困难——理解哪些属性应该被估算,哪些不应该被估算。例如,由于客户没有使用该类型的服务,可能会丢失一些值,因此进行插补毫无意义。

咨询领域专家并研究该领域永远是一条路要走。实际的编码很容易。

加入我的私人邮件列表,获取更多有用的见解。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership)

原载于 2020 年 10 月 21 日 https://betterdatascience.com

可能的任务——强化学习与现实世界相遇

原文:https://towardsdatascience.com/mission-possible-reinforcement-learning-meets-the-real-world-296b21ec672b?source=collection_archive---------48-----------------------

将科幻变成科学事实

增强学习被视为实现更智能和更自主的机器的最有前途的途径之一。人工智能在优化和创造新用例方面的进步是不可否认的,这使它今天成为一种商品。在复杂数据中发现模式的能力和在巨大数据集上进行推理的能力导致了全球行业的采用。

从学术研究到广泛应用的用例的转变非常快。一旦一种新的算法或计算机芯片被公之于众,你就会听说另一种技术已经宣布将在今年的下一个季度发布。在这种眩晕中,有三种类型的机器学习,即监督学习、非监督学习和强化学习。到目前为止,前两者在业内得到了最广泛的采用。这些方法利用了企业中常见的庞大数据集,使其看起来像是自然的进步。

强化学习是人工智能的第三大支柱

T 学习的第三个领域是利用软件代理,在一个环境中执行动作以获得最大的回报。这是强化学习(RL)的领域,它甚至需要更多的数据来进行训练和学习。为了利用 RL,你需要一个提供持续数据流的环境,以向软件代理提供反馈,这是 RL 概念的一部分。有了大量的传感器和高维连续的输入向量,所需的数据需求可能会非常巨大。为了获得有用的结果,您通常不能依赖历史数据,但是您需要创建一个进行培训的模拟环境。

插图由基里尔·戈斯蒂耶夫制作

努力是巨大的,但可能的收获是难以置信的大。强化学习被视为创造真正智能的机器的一种方式,这些机器能够以类似人类的方式解决问题。它被视为自动驾驶、飞行和游泳的正确钥匙。它将使机器人使用更复杂的模式移动,并帮助机器理解它们被要求做什么。在涡轮机或电网等复杂系统中,在拥有巨大高速和实时数据流的优化企业环境中,强化学习理解模式并得出有意义的结论。

现在 RL 在发生什么?

我们即将把劳动力成本降至零,这听起来好得令人难以置信。不再需要对工厂和生产设施进行监督,员工不再暴露在危险的工作场所。尽管其他深度学习方法具有优先权和当前的成功,强化学习社区也是一个非常活跃的社区。2020 年将会有大量的学术研究、有前途的用例以及早期的工业应用。

当我们谈论算法研究时,主要的强化方法是深度强化学习。算法不断得到优化,它们的性能根据已建立的算法进行测试。最近两个成功的算法是 deep Q networks (DQN)和 Soft Actor Critic (SAC)。

DQN 算法是谷歌 Deep Mind 的 AlphaGo 系统的一部分,该系统在 2015 年的围棋比赛中击败了李·塞多尔。这种成功的 DQN 导致了进一步的算法,如双 DQN (DDQN),决斗 DDQN,或 DDRQN-AD。这个 DDRQN-AD,是“具有动作发现的深度分布式递归 Q 网络”的缩写,例如,在中国广东被应用。在那里,对互联电网的安全和经济运行进行了优化测试。

插图由基里尔·戈斯蒂耶夫制作

另一个不能绕过的算法是 SAC。大量的研究和实验显示了这种方法的优越性,它在探索中培养了更多的自由。软行动者评价算法最大化 RL 策略中的“熵”。这是一个丰富环境预期回报的策略。因此,它给了策略更多的随机性,这有助于机器人更好地移动连续和离散的动作。

利用基于 SAC 的算法,谷歌和加州大学伯克利分校在不到两个小时的时间里训练了一个四条腿的机器人。这个机器人还学会了归纳,所以它可以对以前看不见的事物和情况做出反应。本例中的学习速度表明,在可行的时间内,非模拟环境中的真实世界学习是可能的。

RL 的工业用例

对于重工业来说,许多用例已经准备好利用强化学习。石油和天然气、采矿和离散制造业是启动这一趋势的三个主要领域。最突出的是自主运动。在工业中,物品必须一直被移动,并且这种运输经常发生在危险或有害的环境中。RL 是开发在复杂地形中表现良好的车辆的最适合的方法。因此,我们将看到无人机在现场进行检查,拖运卡车和火车运输覆盖层和矿石。这些系统超越了传统的自动导引车(AGV)。经过 RL 培训的智能自动驾驶汽车具有灵活的导航、自主调度功能,并且它们一直在优化自己。一个很好的例子是自主水下航行器(AUV)的自适应控制。所有这些系统都可以遵循更高的抽象命令和指令。

第二批主要用例是实时过程管理和能量流的优化。电网世界的一切都可以用 RL 来优化。从微网的运行和维护到紧急控制程序的优化,RL 可以应用于所有的控制流程。供暖、通风和空调系统(HVAC)是优化的另一个备选方案,因为能源消耗是所有工业场所的一个巨大成本因素。

插图由基里尔·戈斯捷耶夫制作

RL 发挥效用的第三大领域是机器人的复杂运动和短训练时间。机器人和辅助机器存在于工业活动的所有领域。大多数机器人和自动化系统做非常简单和重复的任务。下一个重大进展是机器人可以像人类工人一样流畅灵巧地移动。例如,当你看到屠宰场的体力劳动时。在复杂结构的屠宰动物上发生了许多危险的切割和剁碎。每一块肉都是不同的,为了优化生产,工人们需要大量的操作经验。有了 RL,机器人将学会像他们的人类同事一样挥舞刀具。当你看到以传统方式为工业机器人编程这一单调乏味的任务时,你会发现有很多优化的空间。通过 RL,机器人可以像运动员在健身房跟随教练一样跟随人类的运动。老师拿起机器人的手臂,以正确的方式移动它。机器人根据自己的能力跟踪并优化给定的运动。

此外,RL 帮助工厂运输,优化管道和运输路线的流程,甚至自动化钻井过程。它可能会在工业过程控制应用以及车载路由、车队管理、车间调度和其他优化任务中经过仔细测试。

【2020 年工业采用

到今天的,强化学习还没有在全行业应用。然而,有许多现成的解决方案可供使用。有人工智能驱动的平台和供应商已经拥有使用 RL 的工业客户。有许多单独的解决方案正处于试验阶段的最后阶段。这些解决方案远远超出了原型设计,并且已经在现场得到了证明。总之,RL 采用有两种主要方法。

一方面,有工程和高科技公司为具体的工业问题开发单独的解决方案。最广泛的解决方案是完成任务的特定自动驾驶汽车。一个特殊的例子是无人侦察机。它们非常受欢迎,因为无人机技术相当成熟,检查有效载荷已经证明自己可以用于工业用途。这些解决方案可能不会专注于 RL 技术的前沿,但它们提供了用例的优化,并创造了新的价值主张。尽管这些方法没有考虑到强化学习研究的最新进展,但它们显示了强化学习应用的可行性。

插图由基里尔·戈斯蒂耶夫制作

另一方面,还有像 pathmind 或 bons.ai 这样的平台提供商。他们从生态系统的角度提供强化学习服务。这些 IT 公司为特定行业的应用提供算法和数据管理方面的专业知识。他们制定企业解决方案来支持每个公司的主题专家。这有助于专家的日常工作,并支持优化项目。

2020 年,RL 的主要应用是自动驾驶汽车和企业或网络解决方案。电网和企业人工智能显示了与纯 IT 最密切的联系,并且实施障碍较低。他们需要较少的传统工程操作。然而,超级智能机器人和高度专业化的解决方案正在路上,并超越了原型。

总的来说,人工智能新发展的进展速度非常快。强化学习的改进速度也是如此。尽管最近一年人工智能的炒作高峰已经过去,但 2020 年有望在机器学习方面取得大量卓有成效的发展。由于人工智能在过去几年中创造了巨大的吸引力,许多技术和算法已经准备好应用于工业领域。然而,对于大公司来说,从试点项目到企业范围的整合还有很长的路要走。核心员工需要发展大量的能力,一些破坏性的人工智能方法需要改变生产和业务流程。

超越宣传或何时选择加入

从技术领导者那里,没有人在等待。埃隆·马斯克(Elon Musk)正在与特斯拉公司(Tesla Inc .)一起推动整个行业。这是可能的,因为自动驾驶硬件和软件的核心技术由特斯拉自己掌握。因此,他们可以毫不延迟地将最新的更新集成到人工智能算法中。他们控制着数据。

谷歌的母公司 Alphabet Inc .正在各个领域推动人工智能的极限。他们创造了像 AlphaZero 这样超越人类优秀的展示。微软正在将人工智能技术和解决方案带到所有行业,并关心他们的需求。这些例子只是 IT 行业巨头扶植 AI 发展的巅峰。

然后,每天都有无数人工智能初创公司提出新的解决方案。他们正在解决专门的问题,并通过新的方法帮助节约成本和优化生产。这个市场仍在快速增长。因此,任何公司都不能忽视对这些新选项的评估。

人力劳动

对公司来说,最重要的问题之一无疑是生产的未来。如何进一步优化生产流程,如何节约更多成本?在这方面,劳动力成本仍是主要因素之一。尽管存在所有劳动力都可能被机器人取代的神话,但在一个互联高效的生产工厂,工作岗位发生了重大变化。员工失去了他们传统的工作,但他们需要接受新的挑战。

当决定从人工智能系统和强化学习开始时,必须训练强化学习系统。所以,机器人培训需要一种文化和技能。这将重工业从在恶劣环境中小心保护员工并给予他们大量休息时间的负担中解放出来。这些工人现在需要作为训练员和监工。这改变了工作时间,因为许多轮班可以由机器人单独完成。但所有这些都必须以明智的方式来完成,以保持高水平的操作性能。

插图由基里尔·戈斯蒂耶夫制作

害怕落后

人工智能的高速变化和新解决方案的涌现可能会给决策者带来一些压力。他们不能忽视人工智能技术,因为实现性能飞跃的机会太大了。独立于对 RL 解决方案和基于新技术的生态系统的评估,所有企业都应该采取一些基本活动和预防措施。

公司范围的数据源应该导致单一的数据湖。数据湖是一种数据库结构,其中所有传入的和历史的数据被收集成一个池。数据湖的布局需要为未来的人工智能项目做准备,因为它是所有项目依赖的来源。

而更重要的一步是要有一些人准备维护和了解公司自己的数据湖。这样,最先进的人工智能(包括强化学习创新)与公司自身专业知识之间的差距不会扩大。当决定在 AI 中进行时,公司至少必须准备好开始 RL 项目。这些准备步骤有助于为未来的发展保留更多的选择。

另一个重要的任务是评估你自己的速度。调查公司的优势和劣势。看看你的员工,估计他们拥抱人工智能的意愿和能力。这让你对新的 RL 系统的实施速度以及需要计划的其他培训活动有了更深入的了解。通过这种方式,您将找到适合您企业的正确步伐。

不可避免的领域

RL 的最新进展尤其体现在其应用的主要领域。如果没有强化学习,你就无法想象自动驾驶汽车和机器人。这里的实际价值在生产现场和许多其他任务不能否认。解决方案已经准备好进行部署。

今天使用 RL 的第二个领域是电源管理和能量流。HVAC 系统和微电网可以通过基于 RL 的控制系统轻松升级。在这方面,中国公司尤其领先。RL 控制系统显示了其在管理可持续能源方面的优势。随着气候变化的影响与日俱增,行业法规和要求越来越严格,RL 为合规性提供了良好的解决方案。

大问题

在时刻,强化学习正在从学术和研究向现实世界的原型和试点项目过渡。有了成功推出 RL 项目所需的能力和员工资质,让一切运转起来总是需要相当多的时间。

插图由基里尔·戈斯蒂耶夫制作

那么,在您的企业中,什么时候开始强化学习是合适的呢?用 RL 解决问题和优化流程时,你应该付出多少努力?对于您的特定使用情形,您如何利用承诺来提高性能?

这是个个别问题,需要深入分析。压力很大,IT 公司每个季度都在提供新的 RL 解决方案。一个可靠的计划和早期评估似乎是你强化学习策略的一个好方法。今天,RL 不是现成的解决方案。一些 RL 模块和组件可以立即集成为黑盒,但更深层次的转变需要时间。有可能落后,但等待他人证明解决方案也是一个可行的选择。然而,你需要为在这个快节奏的世界中采取行动做好准备。


完整的参考列表可在这里找到。

我作为数据科学家所犯的错误

原文:https://towardsdatascience.com/mistakes-ive-made-as-a-data-scientist-e38f8c314ac6?source=collection_archive---------11-----------------------

21 世纪最性感工作的 10 种摸索方法

照片由来自佩克斯的古斯塔沃·福林拍摄

数据科学可能会有压力,但也非常有益和有利可图。

一些活动是我们效率的倍增器(例如:拒绝使用空闲时间)。

做其他活动也能事半功倍。

以下是我犯过的错误,这些错误要么阻碍了我个人的职业生涯,要么阻碍了我公司的职业生涯。

不了解数据科学工作的不同类型

我曾以“数据科学家”的身份加入一家公司,希望做预测建模。但最终还是写了后端应用代码。这是我的错。

我之前的数据科学角色专注于构建模型,我错误地认为新角色会类似。

在“数据科学”的保护伞下有许多类型的工作。再加上糟糕的工作描述,你就有了困惑的秘诀。

来自 Indeed 的 3 份不同的数据科学工作

浏览一下数据科学的帖子,你会发现工作可以分为几类:

  • 商业智能
  • 数据分析
  • ML 工程
  • 数据工程
  • 软件工程

在接受一份工作之前,试着了解它的细节。探查你正在面试的团队中的某个人是你最好的选择。否则,你可能很快就要找新工作了。

没有导师

在没有外界帮助的情况下,我花了一个月的时间为一个 ML 问题绞尽脑汁。当一位新导师建议研究一种特定的技术时,我只用了一周就解决了这个问题。

我不知道我不知道的事情。也就是说,我对现存的 NLU 技术并不熟悉。但我的导师有博士学位和该领域的工作经验。

你不知道你不知道什么。

初创公司通常会让你在你不擅长的领域工作。当你不知道相关技术的词汇时,很难找到解决方案。

没有高级工程师或导师的帮助,任何人都不应该在像人工智能这样的高科技领域工作。这是一个巨大的乘数。

项目失败时不承认

在花了 2 周的时间用一个新模型替换现有模型后,现有模型仍然有更好的性能。

我没有减少损失,而是又花了两周时间进行投机性的管道调整,希望能有所改善。没用。我们扔掉了新模型,还有浪费的两个星期。

时间盒让我停下来。一个失败项目挫伤了我的自尊心,让我继续前进。

Timebox,不要 scopebox。

  • 领先的精益软件开发

我们这些孤立在数据科学团队中的人无法全面了解公司的优先事项。我们可以增加价值的项目数不胜数。有些人会失败,我们必须继续前进。

如果你在一个非关键项目上超过了规定的时间,并且更多的时间不能保证它的成功,放弃它通常是明智的解决方案。

项目结束后不写汇报笔记

我创业时的优先事项发生了变化,我回到了一年半前放弃的 NLP 项目上。没有关于尝试过的方法或研究的文档,所以我又从头开始。

鉴于初创公司的优先事项不断变化,放弃一个项目,然后在晚些时候再回来做是很常见的。

其他时候项目失败了,我们不记得为什么,管理层想再次尝试同样的事情。

保留一个失败/正在进行的项目的中央存储库被低估了。参考已提交的代码、研究链接以及对已尝试内容的注释,将有助于您在重新开始项目时快速恢复。

拖延寻求帮助

我讨厌浪费人们的时间。我倾向于在回去寻求进一步的建议之前,详尽地尝试来自资深人士/顾问的每一个建议。为此我推迟了会议。教科书式的完美主义者。

过早请求帮助和过晚请求帮助只有一线之隔。

如果有人同意做你的顾问,他们想帮助你。他们也有经验知道什么时候你在错误的道路上走得太远,即使你不知道。

获得建议,尝试,跟进。

如果你能自己解决问题,你就不需要他们了。

我意识到有些人完全不考虑问题就寻求帮助——这一点不适合他们。

不承认你一无所知

早在我的机器学习生涯之前,我在喝咖啡时遇到了我的第一位人工智能导师。

导师:你以前实现过机器学习吗?我:神经网络导师:你用过哪些框架?我:嗯。Python。

事实上,我对 ML 的所有了解都是从吴恩达的深度学习课程中学到的。但我想听起来聪明点。

我们最终在一起工作。也就是说,不要假装你知道你不知道的事情。有实地经验的人在一英里外就能闻到胡说八道。帮助承认自己弱点的人也更容易。

没有项目的学习

我花了几个月的时间阅读我已经不记得的技术和理论。笔记和未命名的 Jupyter 笔记本不可避免地会丢失。

另一方面,我回想起每一次我将学到的东西整合到一个工作应用程序中,发布 Jupyter 代码,或者写一篇博客文章。

后者的另一个好处是很容易返回并引用工作代码。

让自己对你花时间学习的所有东西的某种产出负责。

开发与探索的错误平衡

隐射了 多臂土匪 的问题, 剥削 是使用你知道的技巧,而 探索 是尝试新的技巧。你两者都需要。

变得对一些机器学习库过于舒适也有它的缺点。你开始在你已经知道的技术范围内看到所有的 ML 问题。

在我的特定场景中,一个我从未听说过的库远远超过了我的 hacky Sklearn 实现。

当开始一个新问题时,采取第一原则的方法来避免探索不足。

不编写可重用的函数

一个面试任务需要建立一个标准的 NLP 管道,包括通常的疑点(清理、词条化、向量化、模型选择等)。

鉴于完成任务的时间有限,我希望我已经准备好了可导入的管道模块。

我花了几个小时才完成这个项目,而不是看起来像个神童一样在 30 分钟内完成。虽然我通过了面试阶段,但这是很难的时候,它本来是容易的。

我选择一个懒惰的人去做艰苦的工作。因为一个懒惰的人会找到一个简单的方法去做。
——比尔·盖茨

如果您发现自己在 Jupyter 笔记本上不止一次地编写相同的代码,请帮自己一个忙,编写自己的可重用模块。

低估领域知识的重要性

我已经建立了使用错误功能的机器学习管道。我曾在一些公司工作过,这些公司生产他们行业不需要的产品。

接触一个行业,拥有领域知识是软件开发中最被低估的部分。

领域知识比编码技能更难获得。它是在野外工作多年后建成的。

  1. 当心对领域知识不感兴趣的工程师。在某个时候,他们会碰壁。
  2. 只有当至少一个创始人在产品所面向的行业有丰富的经验时,才加入一家初创公司。

结论

职业生涯不会长到让你自己犯所有的错误。如果我们能互相学习就更容易了。

工作稳定已经成为过去,但我们仍然可以通过多做正确的事情,少做错误的事情来达到顶峰。

希望你喜欢阅读我所犯的错误。

作为一名数据科学家,你摸索过吗?

减轻机器学习中的偏差:MLFairnessPipeline 简介

原文:https://towardsdatascience.com/mitigating-bias-in-machine-learning-an-introduction-to-mlfairnesspipeline-42e007dce0a5?source=collection_archive---------59-----------------------

Pixabay 在 Pexels 上拍摄的照片

机器学习中的偏差

偏见有许多不同的形式,影响着所有的人群。它可以是隐式的,也可以是显式的,通常很难检测到。在机器学习领域的偏见往往很微妙,很难识别,更不用说解决了。为什么这是一个问题?机器学习中的隐性偏见具有非常真实的后果,包括拒绝贷款、更长的刑期以及对弱势群体的许多其他有害结果。设计模型的数据科学家和运行模型的计算机可能不会对某个特定群体产生明显的偏见,那么偏见是如何产生的呢?无论是种族、性别、宗教、性取向,还是其他形式的认同,在导致不利结果的群体和因素之间都存在着相关性。这是一个典型的相关性与因果性的问题,对于成为这种范式受害者的人群来说,这是一个现实世界的后果。MLFairnessPipeline 有两个用途:

1.发现对弱势群体的偏见

2.减轻对弱势群体的偏见,并在不牺牲性能和分类准确性的情况下提供更公平和公正的预测

什么是 MLFairnessPipeline?

MLFairnessPipeline 是一个端到端的机器学习管道,具有以下三个阶段:

1.预处理—因子重新加权

2.处理中——对抗性去偏神经网络

3.后处理—基于剔除选项的分类

图一。多公平管道方案设计

MLFairnessPipeline 在上述三个阶段中的每一个阶段都消除了偏差。受保护的属性用于将数据分为特权组和非特权组。该属性本质上可以是任何特征,但最常见的用例是种族和性别。流水线保持精度和性能,同时减少偏差。

这种划分的一个很好的用例是设计决定刑期的模型。在确定刑期时,对个人再次犯罪的可能性进行了计算,并给予了非常重的考虑。由于系统性的种族偏见,少数民族经常被预测为更有可能再次犯罪,因此如果我们试图在这种情况下减轻偏见,我们将使用“种族”作为我们的受保护属性,并将非洲裔美国人和西班牙裔美国人视为弱势群体,将高加索人视为特权群体,因为他们经常获得更有利的结果和优惠待遇。

预处理

在模型被训练之前,在我们的受保护属性和组被选择之后,特征被重新加权以有利于弱势组,从而在训练模型之前给他们一个提升。在上面的使用案例中,当评估重新犯罪的可能性时,高加索人比少数民族多 10-15%的可能获得有利的结果。重新加权后,这种 10-15%的有利结果差异将减少到 0。

图二。重新加权前后有利结果的平均值

进行中

在预处理之后,我们进入正在处理的阶段,在那里进行学习并建立我们的模型。MLFairnessPipeline 然后使用 TensorFlow 建立一个神经网络,并利用对抗性去偏置。这实际上需要两个模型:一个由用户指定,以尝试从一组特征中预测指定的结果,第二个对抗模型基于训练模型的结果来尝试和预测受保护的属性。这样做的目的是确保受保护的属性和结果之间的单向关系,从而确保受保护的属性不会根据结果被猜到。通过打破受保护的属性和结果之间的联系,我们确保了在有利和不利的群体之间有一组更平等的结果。

图 3。对手模型功能的可视化表示

使用对抗去偏置,我们的目标是使我们的对手模型难以基于最终预测来预测受保护的属性

后处理

我们管道中的第三个也是最后一个阶段是后处理。现在我们有了一个训练好的模型和一组预测,后处理阶段利用基于拒绝选项的分类在决策边界附近的特权和弱势群体之间交换结果。通过定义决策边界,用户可以指定交换结果的阈值。如果特权群体的成员在决策界限之上的阈值内,意味着提供了有利的结果,则他们与得到不利结果但仍在界限之下的阈值内的弱势群体的成员交换。这种预测的交换增加了对弱势群体有利的额外推动,以提供一组更公平的预测。

图 4。决策边界的表示以及 ROC 如何在非特权群体和特权群体之间交换预测

【MLFairnessPipeline 如何衡量成功?

为了从公平的角度判断性能,MLFairnessPipeline 提供了关键公平指标的测量,并将模型性能与由几种流行的机器学习分类算法组成的对照组进行比较。选定的测量如下:

图 5。使用的公平性度量表

控制组中当前支持的分类器是 XGBoost 分类器、KNeighbors 分类器、随机森林、AdaBoost 分类器和 GradientBoost 分类器。下面是一组样本图表,比较了我们的对照组和 fair 分类器在上述样本用例中的性能。

图 6。将对照组与公平分类器进行比较的分类准确度

此图比较了上述样本用例中与再次犯罪的可能性相关的准确性。我们看到所有型号都有相似的性能

图 7。对照组分类器与公平分类器相比的统计奇偶差异

该图比较了我们的对照组和我们的公平分类器的统计奇偶差异。我们看到,在我们的控制组中有一个非常重的特权群体的偏好,但在我们的公平分类器中几乎完全平等的分裂

图 8。对照组和公平分类者之间的均等机会差异

在我们的对照组中,我们看到了机会均等差异的巨大差异,偏向特权群体,但我们的公平分类器实际上显示了对弱势群体的偏见

结论

总之,MLFairnessPipeline 为数据科学家提供了检测和减轻其模型中多种形式偏差的机会,同时保持相同程度的准确性和性能

使用 Excel 降低终端用户计算风险

原文:https://towardsdatascience.com/mitigating-end-user-computing-risk-with-excel-4108a5e6acad?source=collection_archive---------29-----------------------

您可以拥有强大的 EUC 策略,同时还能使用 Excel!(图片作者本人)

越来越多的公司开始重视与终端用户计算或 EUC 相关的风险。简而言之,终端用户计算是指允许终端用户在他们可用的规定解决方案之外执行复杂计算的任何系统。

金融行业的一个典型例子是,一名交易员在 Excel 中开发了自己的交易模型,然后使用该模型在市场上进行交易。这个模型在公司的风险系统之外,因此风险管理团队或模型验证团队没有办法验证这个模型,他们甚至可能不知道它的存在。

有几个引人注目的案例,复杂的 Excel 电子表格被发现有错误,后来这些企业损失了数百万美元。

需要指出的是,在绝大多数情况下,用户不会使用终端用户计算来有意规避雇主制定的政策或程序。最常见的动机是,最终用户最了解他们试图解决的问题,而且他们通常最有能力解决该问题,并使用他们可用的工具。

为什么终端用户计算会成为一个问题

管理层、其他最终用户和潜在客户接受并信任作为最终用户计算结果(如 Excel)生成的报告和数据。

计算中的错误很难追踪,并且在电子表格的情况下,可以在同一报告的不同版本之间传播。即使一个用户发现并修复了一个电子表格中的错误,又有多少次同样的错误被复制并粘贴到其他表格中呢?

测试电子表格中编写的代码实际上是不可能的。在 Excel 中,VBA (Excel 的脚本语言)嵌入在电子表格中,因此不能像专业软件开发中的标准做法那样进行测试。

在 EUC 环境中编写的代码不能被有效地审计。当代码嵌入到电子表格中时,没有一个中心位置可供您查找用于运营业务的代码,这些代码分散在不同用户和团队的不同电子表格中,通常很少对代码的质量和正确性负责。

对于个人来说,构建他们自己的复杂“主表”并不少见,其中包含了他们执行工作所需的一切。有了它,他们的工作效率非常高,一切都很好,但是当那个人不得不把工作移交给别人的时候,会发生什么呢?突然,他们小心翼翼维护了多年的电子表格被揭露出来——一个没有人敢碰的纸牌屋!

对我来说很好!(图片维基共享资源

目标是什么?

在某些软件开发圈子里,最终用户有时被视为敌人。如果你是一名开发人员,你可能会想,禁止使用 Excel 将是一个好的解决方案,但让我解释一下为什么不是。

为什么最终用户首先使用 Excel?Excel 是一个非常强大的工具,它可以帮助他们比没有它更有效地完成工作,这就是他们使用它的原因!

如果我们把 Excel 拿走,他们电子表格中的每一个小功能都将被许多不同的应用程序所取代。为了有效地工作,所有这些应用程序都需要巧妙地集成在一起。此外,每当用户需要做一些特别的计算或者用一个新的想法做实验时,就需要开发人员编写新的功能来执行。您有多余的开发资源来处理这个问题吗?

即使这是可行的(许多公司都在尝试),问问你自己,这对最终用户来说是更好还是更坏?如果你还不知道这个问题的答案,那就等着“导出到 Excel”按钮被添加到你的新应用程序中吧!现在你有两个问题——你有更多的东西要维护你有 Excel 电子表格!

那太好了…你现在能添加一个“导出到 Excel”按钮吗?(图片作者本人)

所有这些中真正重要的是什么?

  • 为最终用户提供一套工具来帮助他们执行
  • 确保关键代码经过测试和可审计
  • 保持对 Excel 之外的业务逻辑和数据的控制
  • 保持一定程度的灵活性而不危及结果的完整性、可审核性和可再现性。

有什么解决办法?

如果我们不把 Excel 当作一个具有内置函数的工具来执行低级操作(这可能会很快失去控制),而是把 Excel 当作一个前端或交互式计算器来实现高级功能,专门为最终用户的需求而构建,会怎么样呢?

Excel 电子表格中常见的错误来源是从另一个系统复制和粘贴数据。从多个不同的系统或其他电子表格中复制数据时尤其如此。跟踪电子表格中使用的数据的来源和完整性是一个难题。

想象一下,如果 Excel 具有从这些外部系统直接检索数据的功能,而不是复制和粘贴所需的数据。不再有复制和粘贴错误,数据的来源从所使用的函数中是清楚的,并且数据的完整性得到了保证,因为它是直接来源的。

复杂的 Excel 电子表格的其他主要问题是笨拙的 VBA 代码和像意大利面条一样的单元格关系。这些是使用太低级的功能来实现复杂结果的副产品。如果我们可以用专门为解决我们特定领域的问题而设计和构建的高级功能来代替这些功能,会怎么样呢?

例如,您不必编写 VBA 代码或创建一个充满中间结果的复杂表格来计算一组现金流的 IRR,您可以使用 Excel 内置的“IRR”或“XIRR”函数。其他问题呢,比如利率互换的定价?最终用户不需要创建一个电子表格来完成这个重复的任务,这无疑会涉及到不可测试的 VBA 代码的使用,如果给他们提供一个高级功能来执行这个特定的计算会怎么样呢?

使用高级域特定函数降低了 Excel 工作簿本身的复杂性。复杂性转移到了这些工作表函数上,如果编写得当,这些函数可以被测试、审计并分发给需要它们的每个人。通过将这些高级功能保持在特定工作簿之外,可以轻松地将修复和更新部署到每个人,而不必修改每个单独的工作簿。

编写一个 Excel 加载项并没有你想象的那么难!

我们上面描述的编写自定义 Excel 函数是通过编写 Excel 插件实现的。

传统上,只有两种方法来编写 Excel 加载项;在 VBA 或 C 或 C++中。如今,有更多的选项可供选择,许多不同的编程语言都有解决方案,包括 Python 、 Java 、 C# 、 JavaScript 、 Scala 、 Kotlin 、 Clojure 甚至 D 。

在 VBA 编写插件确实比在工作簿中直接嵌入 VBA 有一些优势。VBA 加载项可以编写一次,供多个用户和工作簿使用,但它仍有一些缺点。VBA 插件很难测试,并且保存为二进制文件,不适合版本控制系统。这些问题中有一些是由橡皮人 VBA 解决的,所以如果你有特别的需要继续使用 VBA,那当然值得一看。

为了与现有系统集成,您可以选择一种流行的插件技术,与您正在使用的语言兼容。不要提供“导出到 Excel”按钮或计划报告,而是将数据作为具有查询或过滤数据选项的 Excel 函数。减少在 Excel 中完成的工作量将使您的工作簿更简单,因此更容易理解。

  • Python : PyXLL,【https://www.pyxll.com】T4
  • Java 和其他 JVM 语言 : Jinx,https://exceljava.com
  • C# : Excel DNA,https://excel-dna.net

Python 是目前非常流行的选择。这很容易学,但是一旦你开始学习,你会发现这门语言有很大的深度,而且几乎每个领域都有大量的第三方软件包。它的开发人员友好的语法适合那些刚刚起步的人。大多数已经熟悉 VBA 的用户不会觉得这个转变太令人畏惧,并且会发现他们的努力得到了丰厚的回报。

Java 和 C#是企业环境中最常用的两种语言。在完全相同的环境中,Excel 的使用率最高!使用这些语言来扩展 Excel,使其具有特定于企业最终用户需求的高级功能,这是一种轻松的方式,可以减少对高度复杂的 Excel 电子表格的依赖,同时保持最终用户高度灵活的工作方式。

无论您选择哪种语言,将代码移出 Excel 都会打开单元测试、回归测试、持续部署的大门,并最终让您的最终用户计算回到掌控之中。

Python 是一个受欢迎的选择,部分原因是有大量高质量的包可用。(图片作者本人)

最后一点:部署

为了确保每个最终用户访问为他们编写的功能的正确版本,需要一种为他们部署更新的方法。

例如,如果在几个电子表格使用的函数中发现一个错误,在进行了充分的测试之后,需要让使用该函数的每个人都可以使用该更改。由于代码是在 Excel 插件中,而不是在每个工作簿中重复,所以现在任务更简单,更不容易出错。

最简单的部署方法是在共享网络驱动器上托管 Excel 加载项。当您需要进行更改时,可以更新加载项,每个人在重新启动 Excel 时都会获得最新版本。这依赖于每个人在使用 Excel 时都能访问网络驱动器,网络驱动器的任何中断都会导致加载项不可用。这可能并不适用于所有情况,您可能会考虑更好的部署方法。

PyXLL(用于 Python)和 Jinx(用于 Java 和其他 JVM 语言)都支持定制脚本,以便于自我更新。每次 Excel 启动时,这可用于下载和安装最新版本的外接程序。

  • 分发 Python 代码
  • 扫把星启动脚本

用 Excel-DNA 编写的 C#外接程序可以打包到一个 MSI 中,该 MSI 可以使用组策略进行部署。

  • Excel-DNA Wix 安装程序
  • 使用组策略远程安装软件

(图片作者本人)

概括起来

随着业务逻辑和数据访问作为高级功能向 Excel 用户公开,电子表格的复杂性大大降低。将这些函数从单个工作簿中释放出来,并将其作为 Excel 加载项进行部署,这样可以:

  • 与现有系统的集成
  • 电子表格中使用的代码的自动化测试
  • 集中式版本控制
  • 持续部署

通过确保最终用户拥有他们需要的工具,最终用户在 Excel 中的计算问题得以缓解。Excel 外接程序的开发周期通常比自定义应用程序的开发周期快得多,因为添加新功能时不需要更改用户界面。这大大减少了新功能的影响时间。留在 Excel 中可以提高工作效率,尤其是在任务多变、需要分析和实验的情况下。维护一个具有高级功能的 Excel 插件可以确保电子表格不会失控。

减轻职业分类中的性别偏见

原文:https://towardsdatascience.com/mitigating-gender-bias-in-occupation-classification-805edb389729?source=collection_archive---------40-----------------------

公平和偏见

图卷积网络的一个新应用

阿格尼耶斯卡哈里塔约翰娜·梅尔 娜塔莎·巴特**

由 pch.vector / Freepik 设计

随着越来越多的证据表明,基于自然语言处理(NLP)的机器学习模型的一些输出可能会传播社会偏见,我们研究了在工作传记的职业分类中减轻性别偏见。通过图形卷积网络的新颖使用,我们发现通过去除诸如“她”之类的明确性别指标,职业预测中的性别偏见减少了。然而,仍然存在明显的差距,强调需要进一步研究去偏向这一自然语言处理任务。我们训练过的模型和分析的演示可以在 Github 上找到。

背景

相关工作研究了通过调整算法、去偏差单词嵌入和去偏差训练语料库来减少 NLP 任务中的性别偏差。我们关注去偏向训练语料库。德阿尔蒂加等人(2019 年)发现,通过清理性别指标,词袋、快速文本词嵌入和深度递归神经网络在职业分类中存在显著的性别差距。通过姚等人(2018)的文本图卷积网络(TextGCN)的新颖使用来扩展这项研究,我们显式地利用了关于我们的训练语料库的全局结构的信息,并联合学习单词和文档嵌入,从而捕获更多的潜在信息。

我们的数据

在我们的实验中,我们考虑了德阿尔蒂加等人(2019)的生物偏见数据集的子集,它由传记和取自每个传记第一句话的相应职业标签组成。该子集包括具有 28 个不同职业标签的 97,798 个传记,其中第一句在分类任务中被排除。虽然教授是最频繁的职业(35136 本传记),最不频繁的职业是私人教练 (332 本传记)。女性传记的比例从 12.3% ( 说唱歌手)到 93.5% ( 营养师)不等。

按职业和性别分列的传记分布情况

TextGCN 模型

TextGCN 将一个具有对应于单词和传记的节点的单一异构图作为输入。因此,图中的节点数等于人物传记的数量加上词汇的字数。如果一个单词存在于一个文档中,则构建任何单词-文档边缘,并使用 TF-IDF(频率-逆文档频率)对其进行加权。类似地,如果词对语义相似,则构建词-词边缘,这通过正的逐点互信息值来测量。我们性能最好的 TextGCN 架构由一个包含 200 个单元的隐藏层组成。在图卷积之间,使用 ReLU 激活,并且 softmax 函数用作最终分类器。目标函数是所有标记传记的交叉熵损失。

TextGCN 架构

结果

我们将性别差距定义为在给定职业和性别的情况下,个人职业被正确预测的概率的性别差异。例如,模型的性别差距是女性模型被预测模型的概率减去男性模型被我们训练的模型预测模型的概率。对于一些职业,我们观察到性别差距接近于零,比如记者。然而,对于其他职业,我们观察到性别差距远非零,比如外科医生。总体而言,显而易见,对于妇女任职人数不足的职业,性别差距往往是负面的,反之亦然,这意味着性别差距和性别失衡之间存在正相关关系。相关系数为 0.73。

按职业分列的女性概率的性别差距

去除明确的性别指标缩小了性别差距,如下图所示,我们的最佳拟合线有一个较浅的梯度。此外,我们的相关系数降低到 0.69。然而,在性别失衡更加明显的特定职业中,性别差距仍然很大。因此,虽然删除性别指标减少了我们预测中的性别偏见,但要完全消除这一任务的偏见,还有更多工作要做。

有无性别指标的性别差距比较

结论

近年来,基于 NLP 的机器学习方法在越来越多的任务中得到了广泛应用,如自动决策、推荐任务和阅读理解。随着这些系统在我们的日常生活中变得越来越普遍,它们从仅仅是被动的系统转变为对社会产生更积极的影响,影响哪些媒体文章出现在订阅源上或人们看到哪些招聘广告。在招聘中,我们已经证明了职业分类器可以做出带有性别偏见的预测。取消明确的性别指标只能缓解这种偏见。我们希望我们的文章能引起对去偏向 NLP 任务的进一步研究的需要。为了消除职业分类的偏差,我们接下来将对 BERT、ALBERT 和 RoBERTa 的预测进行对比分析。

参考

[1]德-阿尔蒂加、玛利亚&罗马诺夫、阿列克谢&瓦拉赫、汉娜&查耶斯、珍妮弗&博格、克里斯蒂安&乔尔德乔娃、亚历山德拉&盖依克、沙欣&肯塔帕迪、克里希纳拉姆&卡莱、亚当。(2019)." Bios 中的偏差:高风险环境中语义表征偏差的案例研究."120–128.https://arxiv.org/abs/1901.09451

[2]梁耀、毛成胜和罗原。(2018)."用于文本分类的图形卷积网络."https://arxiv.org/abs/1809.05679

**[3]生物偏差数据集,德阿尔蒂加等人(2019 年),【https://github.com/Microsoft/biosbias **

tf.keras 模型的混合精度训练

原文:https://towardsdatascience.com/mixed-precision-training-for-tf-keras-models-4fb7500fd37a?source=collection_archive---------53-----------------------

生产中的机器学习

了解如何为tf.keras模型整合混合精度训练,以加快模型训练时间。

探索为文章进行的实验的交互式仪表板。

在本文中,我们将了解如何将混合精度(MP)训练整合到您的 tf.keras 训练工作流中。混合精度训练是 NVIDIA 在本文中提出的。它让我们能够以更快的速度训练大型神经网络,而网络性能的下降为零或非常小。这是我们将要报道的-

  • 为 tf.keras 模型合并混合精度训练的几个选项
  • 执行混合精度训练时要记住的事项
  • 这些选项的实践示例
  • 使用权重和偏差(W&B)来比较不同混合精度训练实验的结果

如果你想了解混合精确训练的细节,我强烈推荐以下资源:

  • Sylvian Gugger 的混合精确训练
  • 本期 PyCon SG 2019 教程作者 Timothy Liu
  • 英伟达的混合精度训练

我们开始吧!

点击查看代码。

tf.keras (TensorFlow 2)中加入混合精度训练

TensorFlow 2.0 提供以下选项,帮助您轻松整合混合精度训练-

  • TF . train . experimental . enable _ mixed _ precision _ graph _ rewrite
  • TF . keras . mixed _ precision . experimental . losscale optimizer
  • TF . keras . mixed _ precision . experimental . set _ policy

根据我的经验,我发现后两种方法更有效。然而,为了激活混合精度训练,需要一些配置。我们将在后面的章节中看到它们。但在此之前,让我们讨论一些使用混合精度训练时要记住的要点。

使用 MP 训练时要记住的事项

请注意,您无法通过现成的 MP 培训获得显著的绩效提升。使用 MP 训练时,我们需要记住一些要点-

  • 例如,MP 培训仅在 NVIDIA GPUs 的 Volta 一代、特斯拉 V100、特斯拉 T4 上受支持。
  • 为了能够从 MP 培训中获得最大收益,您应该将它与大型网络变压器、ResNet50 等一起使用。网络的架构(即网络包含的层、激活的种类)在这里扮演着重要的角色。我无法在 VGG16 这样的网络上获得任何性能提升。
  • 维度(批次、通道、图像大小、密集节点)应该是 8 的倍数。
  • 使用计算机视觉模型时,使用分辨率越高的图像越好。

使用 tf.keras 进行混合精确训练

在本节中,我们将看到一些使用tf.keras进行混合精确训练的实践例子。正如我在开始提到的,你可以在这个报告中找到完整的实验。

数据集简介

我的实验数据来自于 Vidhya Hackathon 的分析。给你一组像下面这样的图片,你需要预测给定船只的类别-

先睹为快

图像的‍The 标签被给出如下编码

训练集中有 6252 个图像,测试集中有 2680 个图像。不幸的是,测试集中的图像完全没有标记(在黑客马拉松中应该如此)。在实验中,我只使用了 6252 张图片。

数据集的格式如下-

其中,train.csvtest _ApKoW4T.csv 分别包含训练图像和测试图像的名称。

现在我们已经对数据集有了一个大致的介绍,我们可以继续探索实际操作的例子。

为 MP 培训设置明确的策略

tf.keras.mixed_precision.experimental.set_policy 允许我们设置网络各层的默认策略。这里的策略是指特定层的dtype。有多种方法可以在 tf.keras 中为层设置策略-

  • 如果在定义网络之前指定了tf.keras.mixed_precision.experimental.set_policy("mixed_float16"),网络各层的默认策略将是mixed_float16,即网络中的所有计算将在float16进行,而参数将在float32进行。然而,请记住,包含 softmax 激活函数的层的计算应在float32中完成,以避免数值不稳定。
  • 除了设置层的默认策略之外,您还可以做一些更具体的事情,比如

代码取自本例

现在,为了能够使用混合精度的策略,您需要启用 XLA 编译器(XLA 编译器的介绍可以在这里找到),就像这样— tf.config.optimizer.set_jit(True)。注意,这应该在每个会话的基础上完成,也就是说,如果你计划使用 XLA 编译器(在大多数情况下你真的应该)你需要为每个新的会话启用它。

在开始实验之前清除任何现有的会话也是一个好主意,以防止不可预见的问题-

启用 XLA 编译器后,我们设置各层的默认策略,如下所示— tf.keras.mixed_precision.experimental.set_policy(‘mixed_float16’)。我们现在可以定义我们的模型-

我们在预训练的 ResNet50 网络上添加了一个(多)分类头。注意模型的输入应该在T9。还有,看看密层的dtype。现在,当我在我的 GCP 笔记本电脑实例(由特斯拉 T4 组成)上用上述数据训练网络时,我得到了以下结果

作为健全性检查,我在没有混合精度配置的情况下训练了相同的网络,我得到了以下结果

你可以看到训练时间的提高!让我们来看一些最重要的指标:

图表可用此处

上面的一组图表为我们提供了关于以下指标的信息,这些指标也来自不同的实验(您可以通过一点努力看到实验的名称)

  • 准确(性)
  • 失败
  • 训练时间

可以清楚地看到,混合精度训练确实允许更快地训练我们的网络,而没有任何性能损失。请注意,默认情况下,W & B 不会跟踪“ training_time ”,但它就像下面的代码块一样简单:

你可以记录很多其他的东西,比如表格,图片,音频等等。如果您有兴趣探索这一领域,请点击此处查看文档。W & B 也允许我们用神奇的命令%%wandb 在我们的 Jupyter 笔记本中生成上面的图(在这里阅读更多)但是我喜欢将这些图与我的笔记本分开。

此外,我使用您在跑步页面上获得的“添加可视化”按钮创建了以下散点图,以捕捉“训练时间与损失”的趋势。

图表可用此处

创建散点图是一件简单的事情几个击键你就可以轻松完成。

如您所料,该图也是交互式的。

现在让我们探讨一下tf.keras中进行 MP 训练的第二种选择。

MP 培训的损失比例

损失缩放在 MP 训练中是一个重要的概念,因为它防止了在计算中可能发生的降低精度的数值下溢。为了能够使用tf.keras.mixed_precision.experimental.LossScaleOptimizer,你需要通过tf.config.optimizer.set_experimental_options({“auto_mixed_precision”: True})启用混合精度,同时启用 XLA 编译器。确保回顾一些重要的事情如果你在定制训练循环中使用损失比例,你可能需要遵循。我们可以使用上一节中看到的相同模型,为了插入损耗比例,我们将执行以下操作-

就是这样!在这种情况下,您应该可以获得与策略类似的性能。

比较我们实验的权重和偏差(W&B)

混合精度不仅能提高训练速度,还能减少模型的内存占用。因为你没有完全使用双精度或者单精度。但这可能不是那么明显,因为我们在这里处理的数据较少。如果是一个更大的数据集(例如,500 MB 的数据集),差异会非常明显。但是从总体上看你的机器学习模型的内存占用总是非常实用的。W & B 让这一点变得非常容易想象。在我的项目页面,对于像这种的单独运行,你会得到一个名为系统的标签。它为你提供了一系列信息,比如-

图表可用此处

除了上述与您的系统相关的指标,您还可以在底部获得关于 GPU 内存使用的信息。在我的实验中,我使用了 TensorFlow 的数据 API,它允许与数据加载、预处理等相关的计算。要在您的 GPU 上执行(如果可用)。这真正将 tf.data 与 ImageDataGenerator 等其他替代产品区分开来,因为它不支持 GPU 计算。您可以使用 GPU 内存使用情况的图表进行这种比较。

下图显示了不同实验中的 GPU 使用情况-

正如你所看到的,不同风格的混合精度训练在 GPU 使用方面往往遵循相似的模式。当我不使用混合精度时,GPU 实际上得到了更好的利用。这可能会提示开发人员进一步钻研,找出提高 GPU 利用率的方法。但是在 GPU 利用率和模型性能之间总是有一个折衷,并且它会随着项目的不同而变化。

以下是一些综合图表,代表了所有必要的实验材料-

可用图表此处

图表的图例是不同的运行(一次运行=一个实验)。使用混合精度训练时,打开 XLA 编译器非常重要。从上图可以看出,在没有 XLA 编译器的情况下,如果使用混合精度训练,模型训练将更加耗时。

作为一名机器学习实践者,你将被期望更多地关心像这样的方面。

对于每一次不同的跑步,我们都有一个专用的日志页面,在那里我们可以获得本地的训练日志

可用日志此处

谢谢大家!

谢谢你陪我到最后。我希望您能从这篇文章中受益,并将混合精度训练融入到您自己的实验中。别忘了让我知道结果!

我要感谢 W&B 团队的 Lavanya,她仔细审阅了代码和文章本身。她的反馈非常有帮助。

基于项目相似性和协同过滤的混合推荐系统

原文:https://towardsdatascience.com/mixed-recommender-system-mf-matrix-factorization-with-item-similarity-based-cf-collaborative-544ddcedb330?source=collection_archive---------11-----------------------

推荐系统

在电子商务、零售、新闻组或音乐应用等行业中,推荐系统是客户生命周期五大支柱中最重要的方面之一——接触、获取、开发/培养、保留和保留。今天,从电子商务行业(电子邮件/现场产品推荐)到在线广告(在合适的时间提供合适内容的个性化建议,以匹配用户偏好),推荐系统是影响用户在线旅程和获得增强的客户洞察力的最重要的组件之一。因此毫不奇怪,亚马逊网站收入的 35%来自其推荐引擎。在本文中,我们将讨论使用混合方法来提高电子商务平台的推荐系统质量——结合两个构件。

推荐引擎算法

推荐引擎的基本原理是使用过去的用户行为和产品/项目特征过滤数据,或者使用合适的算法捕捉两者之间的交互,并向用户推荐最相关的项目。根据特定的业务需求和策略,有许多方法,因此也有许多算法。在不深入细节的情况下,以下是几个选项,虽然没有按照复杂程度的顺序(从最原始到最高级)列出所有选项。

a) 基于人气:非个性化,向每一个用户推荐最受欢迎的产品。冷启动阶段(当有足够的数据可用时)的良好解决方案

b) 基于内容:基于内容特征的用户好恶分类器。

c) 协同过滤:

I)用户-用户协同过滤:基于用户对之间的相似性得分,使用合适的距离度量(余弦相似性、欧几里德距离、皮尔逊相关等)挑选最相似的用户,并推荐这些相似用户以前喜欢或购买过的产品。

ii)项目-项目协同过滤:这里计算每对项目之间的相似性得分。使用这个基于特定用户/用户群过去偏好的评分矩阵,推荐类似的产品。

d) 矩阵分解(MF): MF 是第一代基于机器学习/模型的方法。基本思想是通过分解用户-项目矩阵(过去的用户-项目交互)来找到用户和项目的嵌入(潜在因素表示)。虽然详细的讨论超出了本文的范围,但是矩阵分解是一种基于线性代数技术将一个巨大的矩阵分解成其组成部分的方法。这是一种可以简化更复杂的矩阵运算的方法,这些运算可以在分解的矩阵上执行,而不是在原始矩阵本身上执行,并且与 PCA、SVD 等技术相似。

矩阵分解

在推荐系统环境中,分解发生在从大规模用户-项目矩阵(有时称为评级矩阵)到单个用户和项目矩阵。让我们假设我们必须用评级矩阵 R(MxN)、用户矩阵 U 和项目矩阵 I 找到 k 个潜在特征/因素,然后根据以下方式进行分解:

R=U∑I ,其中:

n 是电影的总数

k 是总的潜在特征/因素

r 是 MxN 用户-电影评级矩阵,其中 M 和 N 分别是用户和项目的总数。

u 是 Mxk 用户嵌入矩阵

I 是 Nxk 项嵌入矩阵

σ是 kxk 对角矩阵,它代表潜在特征的基本权重

这个分解任务可以使用不同的 ML 算法来实现,例如 ALS(交替最小二乘法)、BPR(贝叶斯个性化排序)、LMF(逻辑矩阵分解)等。

其他嵌入方法:基于 ML 的嵌入技术,如 node2vec 、prod2vec 等

f) 深度学习和强化学习(RL)技术:这些技术是新的,仍处于实验阶段,如基于深度神经网络的推荐、自动编码器、马尔可夫决策过程(MDP)等。

业务问题和数据:

业务问题是为在线用户开发一个处理数千种产品(sku)的电子零售商推荐引擎,原始数据可以在这里找到。在对数据进行预处理、添加用户操作(此处为“点击”)并删除所有缺失的用户标识后,我们有以下字段。

a) sessionId:唯一索引

b)用户标识

c) itemId

d)行动

e)时间范围:对于每个会话 Id 是唯一的

精确地基于过去的用户行为(点击/浏览),我们需要从成千上万的可能选项中为每位顾客推荐个性化的 20 种产品,这些产品是他们在下一次在线会话中最有可能点击的。在大多数情况下,作为最终客户转化/销售之旅的重要指标,在线零售商确实关心点击、浏览、印象等,以更好地了解用户。

虽然基本解决方案是一种基于流行度的方法(非个性化和静态的最流行项目列表),但目标是提高影响业务顶线的推荐质量。

在这种情况下,有必要讨论推荐系统中的数据类型。

a) 显性反馈数据:顾名思义就是用户给产品的一个确切数字。一些显式反馈的例子是网飞用户对电影的评分,亚马逊用户对产品的评分。显式反馈考虑了用户关于他们喜欢或不喜欢某个产品的意见。虽然显式反馈数据可以量化,但显式反馈很难收集,因为它们需要用户的额外输入——想想你上次在网飞上给电影评级是什么时候?此外,人们通常会根据极端的感受来评价一部电影或一件物品——要么是他们真的喜欢这个产品,要么是他们讨厌它。

显性与隐性反馈

b) 隐式反馈数据:隐式反馈不直接反映用户的兴趣,但它充当用户兴趣的代理,推荐系统世界中可用的大多数数据都是隐式反馈数据。隐式反馈数据集的例子包括浏览历史、链接点击、歌曲播放次数计数、用户滚动网页的百分比。

如上所述,在我们的情况下,数据显然是用户行为的隐含反馈数据,作为用户偏好的代理。

解决方法:

在找到具体的解决方案之前,让我们先研究一下我们的数据。

因此,在大多数情况下,用户只与少数几个项目进行交互(< 5),反之亦然。

为了在基于基础流行度的系统上开发更好的推荐引擎,我们探索了以下选项:

a)基于纯 CF:我们在用户-用户协同过滤上尝试了项目-项目相似性/项目-项目 CF 方法,用户喜好随时间变化,因此用户-用户相似性矩阵。随着时间的推移,项目间的相似性保持不变。然而,读者也可以尝试用户-用户 CF。

b)基于纯 MF:基于 ALS 算法的 MF 方法。

c)混合推荐:按顺序混合 MF 和项目-项目 CF。在 MF-ALS 之后,使用项目-项目余弦相似性进一步过滤中间结果。值得探索其他基于距离的方法,如欧几里德、皮尔逊相关等。

列车验证设计:

模拟 A/B 测试环境来测量性能生产。我们将数据分成基于每个用户时间戳的训练验证。采用除最后一个时间戳之外的所有时间戳来训练算法,并预测每个用户的前 20 个产品。然后,我们验证每个用户在各自的最后时间戳中的预测与实际用户动作。

评估指标:

当我们提到建议的质量时,我们主要关心以下几点:

c)k 处的平均倒数排名(MRR ):因为产品推荐算法根据用户偏好生成列表,所以项目排名很重要,并且是评估返回有序列表的系统的度量。在我们的例子中,MRR 20 岁。

d)标准化折扣累积收益(NDCG):除了地图/相关性测量,NDCG 进一步调整推荐列表评估。作为推荐系统/信息检索的上下文,NDCG 是一个重要的度量,因为它能够利用一些项目比其他项目“更”相关的事实。高度相关的项目应该在中等相关的项目之前,中等相关的项目应该在不相关的项目之前。

这些指标的详细概述可在这里找到。

e) AUC:作为排名列表解决方案,我们测量两个列表之间的 AUC——预测列表和实际列表,每个用户有 20 个项目,然后取所有用户的平均值。

方法:

带有代码和数据的详细解决方案框架可以在这个 github 库中找到。

A) 在根据时间戳将数据分成训练-验证之后,我们只包括那些用户 Id,它们同时出现在训练和验证数据集中以获得公平的评估。

B)数据转换:我们需要将类似数据的顺序事务转换为合适的用户-项目矩阵,其中包含每个用户的每个项目交互的计数。这与单词袋(BoW)方法中的术语频率矩阵相同。此外,在数据探索过程中,我们注意到有很高的稀疏性,这在推荐系统中是很常见的。在实际商业场景中,存储和处理如此庞大的矩阵是不可能的。所以我们需要将大的用户项矩阵转换成稀疏格式。

C) 算法选择:在基于流行度的解决方案之上,我们探索了三个选项:

基于纯余弦相似性的项目-项目 CF :基于用户与产品领域的交互,我们计算项目 par 的相似性(项目向量对之间的距离)分数,并最终计算余弦相似性矩阵。然后,相似性矩阵(12620×12620)和用户项目矩阵(5352×12620)之间的矩阵点积生成所有用户的项目分数(每个用户的 12620 个分数的列表),并且为每个用户挑选前 20 个产品解决了该问题。

纯 MF :首先,我们使用 ALS 算法将用户-项目矩阵(5352 X 12620)分解为 32 个潜在维度嵌入矩阵,用于用户(5352 X 32)和项目空间(12620 X 32)。然后,与项目-项目 CF 相同的方法生成用户-项目得分矩阵(5352 X 12620 ),然后为每个用户挑选 20 个项目。

该过程的核心是 ALS,它是 OLS(普通最小二乘法)损耗最小化的修改版本,根据以下等式:

在哪里

x 和 y: 随机初始化潜在因素维度的用户和项目矩阵。这些将交替更新以最小化平方误差,因此该算法被称为 ALS。

rui: 评分,在我们的例子中统计用户 u 和物品 I 之间的交互

α和 Cui: Cui 或置信度值——可以定义为价值或我们赋予交互(用户 u 和项目 I)的值。随着用户 u 点击(一个事件)项目 I 的计数增加,交互权重增加,因此算法对特定交互的置信度增加,并且该置信度以乘数 α的线性比例增加。

λ: 正则化减少过拟合(我们用 0.1)。

pui: 一个用户对一个项目 I 的二进制偏好 u .如果我们知道偏好就 1,如果我们不知道偏好就 0。

c)MF 和 item-item CF 的混合:这种混合方法进一步提升了整体性能。直观地,它不仅学习用户-项目的潜在特征,而且还为每个用户加入项目相似性组件,以进一步细化推荐。

详细方法

在从 ALS-MF 算法获得分解的用户嵌入(5352 X 32)和项目嵌入(12620 X 32)之后,我们在个体用户嵌入向量(1 X 32)和项目嵌入之间应用余弦相似性技术,以获得最终得分列表(1 X 12620)。在对最终得分列表进行排序之后,挑选出前 k 个项目为每个用户创建最终推荐列表(1×20 ),并且在所有用户中重复产生最终推荐矩阵(5352×20)。这个解决方案的神奇之处在于

虽然该解决方案比独立的 MF-ALS 产生更好的质量推荐,但是它没有显著的额外计算成本,因为繁重的计算部分-ALS-MF 训练仅被执行一次来创建嵌入。这里 CF 过程-余弦相似度计算不涉及大量计算,因为它是针对每个用户级别完成的,不像通常的余弦相似度(项目-项目 CF)跨越整个用户-项目宇宙。

性能赋值

在最终的混合解决方案中,我们实现了 40.12%的用户平均匹配率,比纯 MF 推荐提高了近 9%。尽管大部分智能在于在 MF 过程中创建嵌入,CF(针对每个用户的产品对的进一步基于余弦相似性的过滤)为推荐引擎增加了显著的额外提升。如果我们看 AUC 数字 67.5%(从纯 MF 方法改进 6.5%),与二元分类(只有 2 个选项)相反,这里有 12620 个选项的巨大产品空间,这对企业来说是相当不错和乐观的结果。

性能比较

要点和未来之路:

为了进一步提高质量,以下几个策略值得探讨:

a)不同的 MF/嵌入生成算法:使用贝叶斯个性化排序优化(BPR)标准的嵌入生成涉及成对的项目(两个项目的用户特定顺序)来为每个用户提出更个性化的排序,因此可能产生比 ALS 更好的推荐。还有其他算法,例如 LMF、基于网络的嵌入(例如 node2vec)等。都值得探索。

b)超参数调整:除了算法之外,嵌入生成中的另一个关键因素是要计算的潜在因子 k 的数量,它是一个超参数。使用适当的搜索可以找到 k 的最佳值。另外正则化因子要避免过拟合要谨慎选择。另一个对照肝脏是乘数α的线性标度。

c)其他深度学习和基于 RL 的算法:虽然处于萌芽阶段,但仍然值得探索。

推荐引擎是一个多方面的问题,根据业务和组织数据科学成熟度和定位的复杂性,有许多不同的方法来解决同一问题。并不总是设计一个非常复杂的推荐系统和维护开销会为企业带来相应的投资回报。

混合 Pytest Fixture 和 unittest。硒测试的测试用例

原文:https://towardsdatascience.com/mixing-pytest-fixture-and-unittest-testcase-for-selenium-test-9162218e8c8e?source=collection_archive---------33-----------------------

登录到一个网站,通过密码和测试无处不在

Joshua Sortino 在 Unsplash 上拍摄的照片

在我早期的文章中,我介绍了使用 pytest fixture 来传递 Selenium 测试函数的参数。但是有一个问题。我们必须在每个测试函数中编写登录函数。但是我们想要的是一次登录,到处测试。

问题是

如果要测试play.py中的几个函数,就要在每个测试函数中写登录函数。代码将变得非常多余,如下例所示。

def test_foo(params):
    # login
    driver = webdriver.Chrome()
    ...

    # test foo function
    ...def test_bar(params):
    # login
    driver = webdriver.Chrome()
    ...

    # test bar function
    ...

我们想登录一次,到处测试,就像下面的例子。

class TestFtseLinks(TestCase):
  def setUp(self):
  self.driver = webdriver.Chrome()

 def test_foo(self):
  self.driver.find('xxxxx')

 def test_bar(self):
  self.driver.find('xxx')

在我以前的帖子中,我尝试混合使用 unittest。TestCase 和 pytest fixture,但失败。

不过,这次我来介绍一下解决方案。

解决方法:在conftest.py中写一个驱动类

目录树:

test
├── conftest.py
└── test_play.py

conftest.py中,我们必须将每个选项编写为 pytest.fixture 函数。我们编写一个dirver_class函数来登录我们的目标网站。

test_play.py中,我们可以直接用self.login.driver驱动。

测试输出:

查看我的其他帖子 中等 一分类查看
GitHub:
荆棘徐 领英: 徐亮 博客:

参考

  • 使用标记 将 pytest 夹具混合到unittest.TestCase子类中
  • https://stack overflow . com/questions/54030132/how-to-use-pytest-to-pass-a-value-in-your-test-using-command-line-args
  • https://stack overflow . com/questions/50132703/pytest-fixture-for-a-class-through-self-not-as-method-argument/50135020 # 50135020
  • https://docs . pytest . org/en/latest/unittest . html # using-autouse-fixtures-and-access-other-fixtures

广义混合转移分布模型

原文:https://towardsdatascience.com/mixture-transition-distribution-model-e48b106e9560?source=collection_archive---------52-----------------------

介绍 MTDg 模型和用于训练它们的 Python 包

本文旨在概述广义混合转移分布(MTDg)模型的概念,并介绍我开发的mtd-learn Python 包。你可以在这里找到对模型的更广泛的介绍(在这篇文章中没有完整介绍,因为 Medium 不支持数学符号),在这里找到包存储库。

广义混合转移分布模型

广义混合转移分布(MTDg)模型是由 Raftery 于 1985 年提出的[1]。它最初的目的是近似高阶马尔可夫链(MC),但它也可以作为一个独立的模型。MTDg 模型的主要优点是,与马尔可夫链模型的指数增长相比,其独立参数的数量随阶数线性增长。

定义

MTDg 模型是一系列随机变量 (Xn) ,使得:

其中 it…i0 ∈ Nλ是权重向量, Q(g) 是表示第 g 个滞后和当前状态之间的关联的 m ⨯ m 矩阵。

模型要产生概率,必须满足以下条件:

MTDg 模型的对数似然函数由下式给出:

其中 n 表示数据集中的转换数量。

MTDg 模型直觉

您可以将 MTDg 模型视为后续滞后的转移概率的加权平均值。以下示例显示了如何根据订单 3 MTDg 模型计算转移 B->C->A->B 的概率:

作者图片

独立参数的数量

根据[1],MTDg 模型的独立参数个数等于 lm(m-1) + l — 1 。在[2]中,Lebre 和 Bourguignon 证明了独立参数的真实个数等于 (ml — m + 1)(l — 1) 。由于mtd-learn包使用了在【2】中提出的估算方法,参数的数量是用最新的公式计算的。

对于马尔可夫链,参数个数等于 mˡ(m-1) 。您可以在下面找到参数数量的比较:

作者图片

用法示例

让我们分析 1999 年 1 月 5 日至 2020 年 4 月 10 日期间美元和欧元汇率的变化模式。你可以在这里找到数据集。由于 MTDg 模型在离散状态下工作,因此变化分为四组:

  1. 0 _ BIG _ DROP 超过 0.5%的下降
  2. 1 _ 下降—低于 0.5%的下降
  3. 2 _ 上升—不到 0.5%的上升
  4. 3 _ 大幅上涨—涨幅超过 0.5%

先说进口:

import pandas as pd
import numpy as npfrom mtdlearn.mtd import MTD
from mtdlearn.preprocessing import PathEncoder, SequenceCutter

然后是分组代码:

df = pd.read_csv('euro_usd.csv')
df['Change'] = df.Closing_rate.diff()
df['Change_enc'] = np.nan
df.loc[df.Change < 0.0, 'Change_enc'] = '1_DROP'
df.loc[df.Change < -0.005, 'Change_enc'] = '0_BIG_DROP'
df.loc[df.Change >= 0, 'Change_enc'] = '2_RISE'
df.loc[df.Change >= 0.005, 'Change_enc'] = '3_BIG_RISE'
df.dropna(inplace=True)df.Change_enc1       0_BIG_DROP
2       0_BIG_DROP
3       3_BIG_RISE
4       0_BIG_DROP
5       0_BIG_DROP
           ...    
5516        1_DROP
5517    3_BIG_RISE
5518        1_DROP
5519    3_BIG_RISE
5520        2_RISE

现在我们需要将pd.Series转换成一种更加mtd-learn友好的格式。你可以使用SequenceCutter类来做这件事。我们从order=2开始。

order = 2sc = SequenceCutter(order)
x, y = sc.transform(df.Change_enc.values)x
array([['0_BIG_DROP>0_BIG_DROP'],
       ['0_BIG_DROP>3_BIG_RISE'],
       ['3_BIG_RISE>0_BIG_DROP'],
       ...,
       ['1_DROP>3_BIG_RISE'],
       ['3_BIG_RISE>1_DROP'],
       ['1_DROP>3_BIG_RISE']], dtype='<U21')y
array(['3_BIG_RISE', '0_BIG_DROP', '0_BIG_DROP', ..., '1_DROP',
       '3_BIG_RISE', '2_RISE'], dtype=object)

我们可以看到每个状态(在向量y中)在x中都有一个两元素序列。例如,两个第一变化0_BIG_DROP0_BIG_DROP之后是3_BIG_RISE状态。

这些值需要编码成整数。我们可以用PathEncoder类来实现:

pe = PathEncoder(order)
pe.fit(x, y)
x_tr, y_tr = pe.transform(x, y)x_tr
array([[0, 0],
       [0, 3],
       [3, 0],
       ...,
       [1, 3],
       [3, 1],
       [1, 3]])y_tr
array([3, 0, 0, ..., 1, 3, 2])

您可以访问编码字典:

pe.label_dict
{'0_BIG_DROP': 0, '1_DROP': 1, '2_RISE': 2, '3_BIG_RISE': 3, 'null': 4}

注意,有一个null标签专用于缺失值。

要适应模型,只需创建MTD类对象并适应它:

model = MTD(order=order)
model.fit(x_tr, y_tr)
log-likelihood value: -7547.882973125838

您可以检查信息标准的值:

print(f"AIC: {model.aic.round(1)}, BIC: {model.bic.round(1)}")
AIC: 15137.8, BIC: 15276.7

并做出预测:

model.predict(np.array([[0, 0], 
                        [1, 3]]))
array([2, 1])model.predict_proba(np.array([[0, 0], 
                              [1, 3]])).round(3)
array([[0.239, 0.239, 0.306, 0.215],
       [0.217, 0.315, 0.275, 0.192]])

让我们运行order=3的全部代码:

order = 3
​
sc = SequenceCutter(order)
x, y = sc.transform(df.Change_enc.values)pe = PathEncoder(order)
pe.fit(x, y)
x_tr, y_tr = pe.transform(x, y)model = MTD(order=order, n_jobs=-1, number_of_initiations=100)
model.fit(x_tr, y_tr)
print(f"AIC: {model.aic.round(1)}, BIC: {model.bic.round(1)}")log-likelihood value: -7535.536495080953
AIC: 15131.1, BIC: 15329.5

AIC 显示我们应该选择order=3,但是 BIC 却说order=2。正如西格尔定律所说:“一个有手表的人知道现在是什么时间。一个有两只表的人永远不确定。”,所以在检查其值之前选择您的标准:)

我们可以将其与马尔可夫链的性能进行比较:

order = 2
model = MTD(order=order)
model.fit(x_tr, y_tr)
log-likelihood value: -7528.058152541998
AIC: 15152.1, BIC: 15469.7order = 3
model = MarkovChain(order=order)
model.fit(x_tr, y_tr)log-likelihood value: -7421.656650869228
AIC: 15227.3, BIC: 16497.5

无论我们在这里选择哪个标准,MTDg 模型似乎比马尔可夫链更能概括。

摘要

广义混合转移分布模型是有限状态马尔可夫链的一种简洁的替代方法。现在mtd-learn包提供了在 Python 中使用它们的简单方法。该软件包正处于早期开发阶段。欢迎任何贡献或功能请求。您可以在下面的参考书目部分找到关于模型的更多资源。

使用latex.codecogs.com生成乳胶配方

文献学

  1. BERCHTOLD,RAFTERY,高阶马尔可夫链和非高斯时间序列的混合转移分布模型,2002 年。,统计科学第 17 卷,第 3328–356 页
  2. LEBRE,BOURGUIGNON,混合转移分布模型估计的 EM 算法,统计与基因组实验室,埃夫里大学,埃夫里,2009 年
  3. 混合转移分布模型的估计。1999 年,华盛顿大学统计系第 352 号技术报告

ML 101:线性回归

原文:https://towardsdatascience.com/ml-101-linear-regression-bea0f489cf54?source=collection_archive---------25-----------------------

最简单,但是最有效的 ML 方法之一!

你有没有想过科学家如何预测天气之类的事情,经济学家如何预测未来经济的表现,或者机器人如何推断推文的情绪?秘制酱是一种叫做机器学习的技术。与统计学密切相关,机器学习是在给定数据的情况下寻找模式的艺术和科学。然后,这些模式被用于对重要结果进行预测,或者阐明观察到的数据背后的关系。

监督学习是机器学习的一个分支,它处理查看一些变量(x)来预测另一组变量(y)。这要求我们有一个既有 X 变量又有 Y 变量的数据集。这是世界上最常见的机器学习类型。

今天,我们将学习最基本也是最重要的一种监督学习模型:线性回归回归 的任务是预测一个变量将取的精确数值。例如,预测一个地方的确切温度,预测将购买视频游戏的顾客数量等。

线性回归模型的一个有趣的应用是理解一种商品的价格如何随时间变化。让我们来看看自 1980 年以来美国每年的橙子价格。一磅脐橙的价格以美元显示。有两列:年份和价格。粗略地看一下,我们就知道价格每年都在上涨,但更难讲的是过去 40 年中年份和价格之间的精确关系。

虽然查看电子表格很有用,但是以图形方式可视化数据可以揭示更多的模式。让我们在 2D 图上画出这些点,X 轴是年份,Y 轴是价格。正如我们之前所说的,我们想通过只看 X 变量来预测 Y 变量。

线性回归背后的假设是 X 变量(在这种情况下是年份)的影响在一段时间内是恒定的。也就是说,1990 年到 1991 年的物价涨幅和 2005 年到 2006 年的物价涨幅是一样的。这就是线性回归“线性”的原因。需要说明的是,在现实世界中,数据是杂乱的,永远不会如此清晰地符合一个模型。然而,线性回归在许多实际情况下工作得非常好。

我们现在的任务是找到一条穿过我们观察到的数据中所有点的线。我们可以用许多不同的线来拟合这些数据。我们控制的两个参数是截距和斜率,截距是直线在 Y 轴上与 Y 轴相交的点,斜率是沿着 X 轴移动时直线上升的程度。

我们如何选择合适的线来建模数据?

如果我们的点沿着一条完美的线,那么你可以连接任何点,你会得到正确的线,但因为数据往往是“噪音”我们将不得不做一些别的事情。最佳线是由一个叫做“普通最小二乘法OLS 的过程给出的。这个方法告诉我们,你要选择一条线,使每一点和这条线之间的距离最小。点与线之间的距离称为“误差”因此,我们希望降低我们生产线的总误差。

现在我们有了一条误差最小的线,我们可以预测 2020 年橙子的价格。我们要做的就是在 X 轴上找到 2020,然后从那里画一条直线到我们的线性回归线,然后从那里画一条直线到 Y 轴。Y 轴上的读数告诉我们预测价格是多少!

现在来点更酷的!我们可以用不止一个变量来预测价格。让我们尝试使用两个变量:年份和前一年的降雨量。现在我们在三维空间中,我们将把年份放在 x 轴上,前一年的降雨量放在 z 轴上,价格放在 y 轴上。

现在,我们将为数据拟合一个平面,而不是一条直线。逻辑还是一样的。我们需要一个平面,它本身和它需要建模的数据点之间的误差最小。

为了得到预测,我们需要做的就是在 X 轴上找到 2020 年,在 Z 轴上找到 2019 年的降雨量,然后找到 Y 轴读数!就是这样!你现在知道如何做线性回归了!

现在让我指出这种方法的一些缺点。线性回归对异常值非常敏感。假设你有一些错误的数据,其中有一点偏离很远,那么你会得到一条向该点倾斜的线,而不是真正捕捉到真实的模型。因此,在运行线性回归之前,确保数据是干净的,并且剔除异常值是很重要的。

移除异常值之前和之后

线性回归非常强大。虽然很简单,但是很管用!

快乐学习!

ML-代理 1.0 /入门

原文:https://towardsdatascience.com/ml-agents-1-0-getting-started-4864102ecf6e?source=collection_archive---------52-----------------------

来源:https://github.com/Unity-Technologies/ml-agents

为什么现在是 Unity 机器学习入门的最佳时机。

Unity 的机器学习框架 ML-Agents 刚刚发布了 1.0 版本。作为一个已经关注这个框架进展一段时间的人,这是一个令人兴奋的消息,你也应该感到兴奋。

如果你想看视频,看看这个:

在 1.0 版本中,ML-Agents 在 Unity 的包管理器中可用,这意味着你可以直接从 Unity 编辑器中安装它。此外,您现在学习的语法在将来可能不会有很大的变化。对于不想在每次新版本发布时都重新学习所有内容的初学者来说,这是一个巨大的解脱。

入门指南

要开始使用,您只需下载 Unity 2018.4 或更高版本。就这样,暂时的。稍后,我们将安装 Python 来训练我们自己的网络,但是对于推理(运行模型), Unity 是我们所需要的。首先,让我们开始一个新项目并安装软件包。

确保“高级”选项卡下的“显示预览包”已启用

只需选择 ML-Agents 包并点击安装。相信我,这从来没有这么容易过,这很好。

为了更快地开始,我们还需要下载示例。遗憾的是,软件包管理器(Unity,请❤)中没有可选的示例下载,所以我们必须下载资源库。解压缩并打开下载的 repo,打开项目下的 Assets 文件夹,并简单地将 ML-Agents 文件夹拖到编辑器中。现在,在“示例”下,您可以找到 3DBall 场景。如果我们打开它并按下 play,我们可以看到它已经与 Unity 预先训练的机器学习模型一起工作。这个框架的简单性是它最大的优势。

蓝色代理人试图在他们的头顶平衡球

如你所见,蓝色代理人非常完美地平衡了球。这个行为不是硬编码的,是学来的。我们将很快训练我们自己的版本。

基础知识

现在让我们深入一点,看看这个东西是如何工作的。在这个场景中有 12 个代理——他们都非常相似,只是用来加速和稳定训练。如果我们打开一个,我们可以看到它包含一个名为 Agent 的子游戏对象——这就是神奇的🧙‍♂️发生的地方。这个游戏对象上的两个重要脚本是“行为参数”脚本和“Ball3DAgent”脚本。

代理和行为

在 ML-Agents 框架中,代理是参与者,它们所链接的行为决定了它们如何行动。一个代理需要一个行为才能发挥作用,但是多个代理也可能链接到同一个行为,这在许多情况下非常方便,比如对抗性的自我游戏。

代理负责收集观察结果、执行行动和分配奖励。另一方面,行为接收收集的观察和奖励,并负责决定要执行的动作。

有三种类型的行为:

  • 启发式,这是游戏中人工智能的经典工作方式。程序员想出人工智能应该表现的方式,然后把它们硬编码进去。它可以很好地工作,但它在适应不断变化和复杂的环境方面存在问题。当然,机器学习也更有趣😉。
  • 学习行为是我们所追求的。这是人工智能目前使用机器学习进行训练的时候。在训练过程中,会生成一个神经网络模型。以便在训练结束后使用这个生成的模型。使用最后一种行为:
  • 推理是学习模型被应用但不被改变的地方——所以人工智能不会学习。

有很多方法来设置你的代理人,也有更多的方法来训练他们,这极大地改变了结果,但我们只能介绍这么多。

现在我们已经有了一些基础知识,让我们开始训练我们自己的模型。我们将只使用默认设置,现在,调整以后。

训练模型

为了训练我们自己的模型,我们需要先安装一些先决条件。确保您安装了 Python 3.6.1+。如果没有,点击这里。那么你所要做的就是简单的

pip3 安装 ml 代理

你完了!不再安装。现在,将 cd 放入先前下载的 repo 中,执行以下命令:

ml agents-learn config/trainer _ config . YAML—run-id = MyFirstAITraining

等待几秒钟。如果一切按预期进行,消息“通过按下 Unity 编辑器中的播放按钮开始训练。”这正是我们要做的。

祝贺你,你现在正在训练人工智能🎉 🎉🎉

简历

如您所见,ML-agent 的入门非常简单。要掌握这个框架,你需要掌握一些复杂的概念,但这是以后的事了。希望这对你有帮助!

查看我的 Youtube 频道的人工智能相关内容。

和平✌️

ML 工程师正在失去他们的工作。无论如何要学 ML

原文:https://towardsdatascience.com/ml-engineers-are-losing-their-jobs-learn-ml-anyway-87e19523cd9b?source=collection_archive---------0-----------------------

意见

对于那些专注于创造价值而不是精通技术的人来说,未来是光明的

照片由 Pexels 的 bongkarn thanyakij 拍摄

免责声明:这是一篇观点文章。我很乐意在评论中听到你的想法和反驳。

这个领域充满了悲观和沮丧。

招聘被冻结。

…一些人假设投资者将对人工智能彻底失去希望。谷歌已经冻结了对人工智能研究人员的招聘。优步解雇了他们人工智能团队的一半研究人员……拥有人工智能技能的人将远远多于人工智能工作。
--芯片呼延-

我们面临经济衰退。

人们都在谈论一个 艾冬

在关键时刻,人工智能(AI)、机器学习(ML)和数据科学(DS)最先进入是有道理的。对大多数企业来说,它们是奢侈品。

但这并不意味着未来不光明。

如果你创造了价值。

AI 寒冬不会影响大部分 AI/ML/DS 岗位

人工智能冬天是人工智能研究资金和兴趣减少的时期。

但是我们大多数人不做研究。我们阅读论文,获得想法和创新...但是我们使用现有的技术。

此外,构建 ML 驱动的产品的流行程度并不一定与研究成果的数量相关。

如果说有什么不同的话,那就是越来越多的研究没有得到应用。有趣的是,工业界仍在实施几十年前发明的机器学习。

“人工智能驱动的”产品现在更受欢迎是因为 ML 更平易近人,而不是因为新的研究。

你不需要前沿人工智能来解决问题

事实正好相反。

经典算法+领域知识+小众数据集将解决大多数真实问题,而不是深度神经网络。我们大多数人都没有在研究自动驾驶汽车。

我在“ 民主化 AI 无关紧要,数据孤岛化,反正怎么建一个 AI 公司 ”里写过这个。

在我看来,与解决问题的心态和一般开发技能相比,专注于极端技术能力在大型科技公司之外被高估了。

除了技术之外,还有大量枯燥的/手工的工作,这些工作早就应该自动化了。而且不需要突破。

使用机器学习,但专注于创造价值而不是改变世界

当你解决了一个问题(任何问题),大家都赢了。

硅谷欺骗了我们,让我们相信我们应该发射月球火箭,而不是改善我们的当地社区和我们认识的人的生活。

我爱优步,它改变了世界。但是如果让优步生存下去每个季度要花费 50 亿美元,那可能就有问题了。

是的,有些公司是长线投资,将影响 70 亿人。但是更简单的改进,比如减少“无聊”行业中的数据输入错误,也会创造价值。

学习 ML 是对抗 AI 恐惧的最好方法

我们听说自动化杀死了工作岗位,因为没有什么比恐惧更有卖点。不是因为技术失业即将来临。

拿起机器学习。然后尝试概念化,训练和部署一个模型来解决一个实际问题。你很快就会明白这有多难,其次,我们离 AGI 接管还有多远。

基础设施超级不发达,真实数据很乱。

当你从 Kaggle 下载一个 CSV 来训练一个特定问题的模型时,99%的工作已经替你完成了。

如果更多的人这样做,他们晚上会睡得更好。

让 ML 变得简单的工具有缺口

在过去的 10 年中,易用性比任何算法突破都更有利于 ML 的采用。

我们几乎已经到了软件工程师可以使用开箱即用的组件拼凑一个 ML 解决方案的地步,但这还不够容易。

随着工具的进步,我们将会看到不那么纯粹的 ML 工作,但是使用 ML 解决各种问题的软件工程师会大量增加。更多“科技”之外的公司受益。

如果你成为一名为 ML 制造伟大工具的工程师,我将永远感激你。

  • 芯片呼延

ML 正在推动全世界的价值,但我认为我们仅仅触及了表面。等到合适的工具来了。

先做软件工程

除非你有人工智能相关学科的高级学位,否则帮你自己一个忙去学软件工程。然后移入 AI。

学习软件工程就像获得技术领域的 MBA 学位(当时 MBA 很有价值)。您将学习基础知识,创建全栈解决方案,并理解促进 ML 的代码。

随着行业格局的转变,就业机会也更多了,转行也更容易了。

许多软件工程师在 ML/DS 领域获得了成功。但是你很少看到相反的情况。

结论

围绕人工智能有大量的炒作。任何上涨都会带来“下跌”,但如果我们有所准备,这并不一定是件坏事。

如果我们专注于开发通用技能集(包括 ML),解决实际问题,创造价值,总会有事情让我们去做。

最大似然估计

原文:https://towardsdatascience.com/ml-estimation-gaussian-model-and-linear-discriminant-analysis-92d93f185818?source=collection_archive---------28-----------------------

高斯模型和线性判别分析

背景

最大似然估计(ML Estimation,MLE)是统计领域常用的一种强有力的参数估计方法。最大似然法的思想是估计模型的参数,其中给定的数据是可能获得的。在这一节中,我将从模式识别方法中介绍 MLE 的重要性。我们为什么需要 MLE?它在模式识别过程中是如何工作的?

统计模式识别

模式识别是机器学习的一个分支。它是识别给定模式对应的类别的过程。这里,模式是指可用于定义任何空间或序列可观测数据是否在同一组中的特征。范畴是指模式识别的结果,意为一组相同或相似的模式。在统计模式识别中,提取给定训练样本的统计特征并用于形成识别过程。

模式识别的目标相当于确定一个多类别的鉴别器函数。为了生成一个性能良好的鉴别器函数,需要几个标准,例如最大后验概率判定规则、最小鉴别器误差判定规则、贝叶斯判定规则。在本帖中,我们重点以最大后验概率决策规则为例。在下面的解释中,我们致力于使用最大后验概率决策规则来定义给定输入数据 x 的相应类别 y。

最大后验概率决策规则

为了定义给定输入 x 的类别 y,自然要选择一个类别,在该类别中该输入属于它的可能性最高。这意味着选择具有后验概率 p(y|x)的最大值的类别。

这种决策规则称为最大后验概率规则。这与将决策区域设置为

根据贝叶斯理论,后验概率可以写成以下形式。由此,最大后验概率规则等价于最大条件概率 p(x|y)和先验概率 p(y)的乘积。

因此,需要估计条件概率 p(x|y)和先验概率 p(y)来获得后验概率 p(y|x)。

为什么我们需要参数估计?

由于类别 y 是一个离散型随机变量,我们可以简单地估计先验概率

然而,用这种方法估计连续型随机变量输入 x 是不可能的。例如,假设输入 x 具有高斯分布。为了定义 x 的条件概率,我们需要期望值和标准变化值作为参数。这就是为什么需要 MLE 等参数估计方法的原因。

MLE 的定义

由有限数量的参数形成的一组概率密度函数被称为参数模型。我们称为 q(x;θ)参数模型,其中θ是参数。

当逼近概率密度函数时,很自然地确定参数值,使得我们拥有的训练样本是最有可能出现 的 。这里,在参数 theta 下,我们考虑当前训练样本 x_i (i=1,…,n)发生的概率。作为参数θ的函数,这个概率被称为似然并被写为L(θ)。在独立同分布假设下,可能性为**

在最大似然估计方法中,我们找到使似然值最大化的参数θ的值。用最大似然法得到的最佳参数θ写为

当参数模型 q(x;θ)可由θ导出,下面的等式为真。这个方程被称为似然方程。这是最大似然估计答案的必要条件而不是充分条件

在大多数情况下,求解似然方程是复杂的。作为一种解决方案,使用对数似然法。因为对数函数是单调增加的,所以对数似然和似然中的最佳参数是相同的。

高斯模型

高斯模型是具有高斯分布的参数模型。d 维模式 x 的高斯模型通常以下列形式给出。

\μ和\适马是高斯模型的参数。\适马是正定对称矩阵。高斯模型的一个重要特征是参数μ和适马分别是概率分布的期望值和方差-协方差矩阵。

高斯模型的极大似然估计

现在,我们以高斯模型为例。假设我们有 n 个样本数据{x_i} (i=1,…,n)。我们将使用这些输入来估计高斯模型的参数。

首先,模型的可能性和对数可能性是

接下来,似然方程可以写成

求解这些方程,我们最终获得估计的参数

这同样适用于样本均值和样本方差-协方差矩阵。

下图显示了使用 8000 个样本点对高斯模型应用 MLE 的结果。

类别的后验概率

回到我们在定义给定输入数据的相应类别时的问题。我们通过计算 p(y|x)来选择概率的最大值,使得给定的数据 x 属于类别 y,从而找到这个类别。正如上一节所讨论的,我们的问题是估计条件概率 p(x|y)。

假设我们的观测数据用高斯模型表示。现在,利用之前提到的 MLE,我们可以通过下式估计每个类别 y,p(x|y)的条件概率

。{mu}_y 和{适马}_y 是属于 y 类模式的估计期望值和方差-协方差矩阵

考虑到上一节提到的这个估计的 p(x|y)和 p(y ),我们现在可以计算后验概率了。为了使计算更简单,我们使用对数后验概率 log p(y|x)。n_y 是类别 y 中的样本数,n 是样本总数。c 是与变量 y 无关的常数。

最后,为了定义模式 x 的相应类别,我们为类别集中的所有 y 计算 log p(y|x ),并选择具有最大值的一个。

线性判别分析

为避免复杂化,我们假设每一类的方差-协方差矩阵相等,常见的方差-协方差矩阵为\适马。

根据这一假设和上述讨论,公共方差-协方差矩阵的估计为

使用这种估计,对数后验概率现在可以写成

作为一个例子,现在假设类别的数量是 2。在这种情况下,决策边界是一组后验概率相等的点,意思是 p(y = 1 |x)= p(y = 2 |x)。决策边界可以写成

这可以简化为

可以说决策边界是样本 x 的超平面。这种确定决策边界的方法称为 Fisher 线性判别分析。

例子

假设样本数据 x 在 2d 空间中。这里我们将做实值的线性判别分析。

训练样本

训练样本数据如下图所示,其中“x”表示类别 1,“+”表示类别 2。这里,我们在每个类别中使用 n1(=200)和 n2(=200)个样本。这些训练样本是用总体均值=(2,2)和(-2,-2)的高斯分布,总体方差-协方差矩阵[1,0;0,9].

人口参数

模型

与前面的讨论相同,我们用高斯模型近似数据,其中两个类别的方差-协方差矩阵相等。

估计

使用最大似然估计,每个类别的期望值和方差-协方差矩阵的估计为

估计参数(样本参数)

根据线性判别分析部分的结果,给定数据的判定边界为

讨论

现在,让我们看看样本数量如何影响决策边界。
我们在[10,5,1,1/5,1/10]中对 n1/n2 值进行测试。

n1/n2 = 10

n1/n2 = 5

n1/n2 = 1

n1/n2 = 1/5

n1/n2 = 1/10

从这些结果中我们可以看出,当 n1/n2 >1 (n1> n2)时,将类别 1 的模式归入类别 2 的错误比类别 2 的模式少。在 n1

结论

最大似然估计在基于生成模型的模式识别中起着关键作用。正如我们在将 ML 估计应用于高斯模型中所讨论的,参数的估计与样本期望值和方差-协方差矩阵相同。这在统计估计中直观上很容易理解。然而,作为讨论部分的结果,样本的数量影响估计的准确性,这导致对模式识别(在这种情况下是线性判别分析)的性能的影响。因此,使用平衡的样本数据来避免过度适应识别过程的任何类别是至关重要的。

在这篇文章中,我们只讨论了高斯模型。然而,在现实生活的数据分析中,我们需要根据数据的自然特征为数据定义一个特定的模型。在不久的将来,我将介绍“最大似然估计中的模型选择”。

源代码

参考

[1] Masashi Sugiyama,统计机器学习—基于生成模型的模式识别(2019)

从零开始的 ML(决策树)

原文:https://towardsdatascience.com/ml-from-scratch-decision-tree-c6444102436a?source=collection_archive---------25-----------------------

从头开始构建决策树

来源:https://unsplash.com/photos/t1PaIbMTJIM

在这篇和接下来的两篇文章中,我将尝试从代码的角度解释经典的机器学习算法。我总觉得如果你能编写一个 ML 算法的简单实现,那么你的理解就很扎实了。

由于这是 ML 从零开始系列的第一篇文章,我将从分类的角度开始讨论 DT(决策树),因为它非常流行且易于理解。本文的结构是,首先我们将从代码和理论的角度来理解 DT 的构造块,然后最后,我们将这些构造块组装成一个简单的 DT,我们将在 Iris 数据集上测试它。

基尼指数

在构建 DT 时,最重要的选择之一是分割节点的标准,尽管我们有几个选择,但我们将使用基尼指数进行演示。
描述如下:

对于给定的节点,它被定义为

基尼系数= 1 -总和(prob[i]^2)

因此,在计算了左右节点的基尼指数之后,我们对左右节点进行加权平均,这就成为了父节点的基尼指数,它将用于分割节点。

左节点值/左右节点总值左节点 gini 杂质+右节点值/左右节点总值右节点 gini 杂质**

我们已经完成了分割部分,现在我们将使用它来构建一棵树,因为我们首先创建一个函数,它将根据给定的数据生成一个新的节点。

创建节点

这个函数检查每个特性的每个值以找到最佳分割值,我们也可以使用随机分割技术。在所有这些计算之后,它返回一个使用节点类创建的节点(左边提到了完整的代码)。

该函数还检查一些其他约束,如最小基尼值,即节点基尼值应该至少大于用户设置的最小基尼值,以继续分裂,如果不是,则该节点被认为是叶节点。它还检查存在的样本的最小数量,即,如果存在的总数据点小于最小样本,则该节点也被认为是叶节点。

构建树

现在让我们转向构建树方法,它以递归的方式构建树。这个函数还使用了一些标准,例如最大深度(由用户设置,以确保我们只在特定深度构建树)

遍历树

只有一种方法可以打印整个树结构。只是对 DT 的一个有序遍历。

因此,我们现在已经制定了 DT 的所有构建模块,现在让我们结合起来,尝试理解 DT 的完整流程以及代码。

完整流程-

  1. 创建根
  2. 以递归方式为根构建左子树
  3. 以递归方式为根构建右子树
  4. 存储->预测

这个简单的实现不需要改变默认参数,就能给出 95%的准确率。虽然我没有检查过度拟合和其他问题,因为这篇文章并不关注这一点。一个模块一个模块的运行,破解它。如果有错误,请告诉我。希望你们玩得开心!

ML 从零开始:K-最近邻分类器

原文:https://towardsdatascience.com/ml-from-scratch-k-nearest-neighbors-classifier-3fc51438346b?source=collection_archive---------19-----------------------

Maksym Kaharlytskyi 在 Unsplash 上的照片

KNN 分类算法的完整指南,在这里我们将看到如何从头实现一个基于 KNN 的机器学习模型,同时理解其背后的数学原理。

当涉及到通过机器学习解决分类问题时,有各种各样的算法可供选择,几乎可以用于任何数据类型或人们可能要处理的利基问题。这些算法选择可以大致分为两组,如下所示。

  1. 参数算法:属于这一类别的算法依赖于代数数学方程,使用一组权重和偏差(统称为参数),以预测给定数据集的最终离散结果。模型大小,即模型中可训练参数的总数,可以从仅仅几个(例如,在传统机器学习算法的情况下)变化到数百万甚至数十亿(如在人工神经网络的情况下通常看到的)。
  2. 非参数算法:这类分类算法相当独特,因为它们 根本不使用任何可训练参数 。这意味着,为了生成预测,与它们的参数对应模型不同,这一类别中的模型不依赖于一组权重和偏差,或者对数据有任何假设。相反,为了预测一个新数据点的目标类别,模型使用某种比较技术来帮助它们确定最终结果。

今天,在本文中,我们将详细研究这样一种非参数分类算法——K-最近邻(KNN)算法。

这将是一个基于项目的指南,在第一部分,我们将了解 KNN 算法的基础。接下来是一个项目,我们将使用基本的 PyData 库(如 NumPyPandas )从头实现一个 KNN 模型,同时理解算法的数学基础。

所以系好安全带,让我们开始吧!

KNN 分类器基础

KNN 分类(作者图片)

首先,KNN 算法是经典的监督机器学习算法之一,能够进行二元多类分类非参数从本质上来说,KNN 也可以用作回归算法。 然而,就本文的范围而言,我们将只关注 KNN 的分类方面。

KNN 分类一目了然-

→监督算法

→非参数

→用于回归和分类

→支持二元和多类分类

在我们进一步讨论之前,让我们首先分解定义并理解我们遇到的几个术语。

  • KNN 是一个“有监督的”算法——通俗地说,这意味着用于训练 KNN 模型的数据是一个有标签的数据。
  • KNN 用于“二元”和“多类分类”——在机器学习术语中,分类问题是这样一个问题,给定一系列离散值作为可能的预测结果(称为目标类),模型的目的是确定给定数据点可能属于哪个目标类。对于二元分类问题,可能的目标类的数量是 2。另一方面,多类分类问题,顾名思义,有 2 个以上可能的目标类。KNN 分类器可以用来解决任何一种分类问题。

做完这些,我们对 KNN 有了一个大致的概念。但是现在,一个非常重要的问题出现了。

KNN 分类器是如何工作的?

如前所述,KNN 是一种非参数算法。因此,训练 KNN 分类器不需要通过迭代多个时期的训练数据以优化一组参数的更传统的方法。

相反,KNN 的实际培训过程恰恰相反。训练一个 KNN 模型包括简单地将所有的训练数据实例同时装入(或保存)计算机存储器,这在技术上需要一个单一的训练周期。

完成此操作后,在推断阶段,模型必须预测全新数据点的目标类,模型只需将新数据与现有的训练数据实例进行比较。最后,基于这个比较,模型将这个新的数据点分配给它的目标类。

但是现在另一个问题出现了。我们正在谈论的这种比较到底是什么,它是如何发生的?坦白地说,这个问题的答案隐藏在算法本身的名字中——K-最近邻

为了更好地理解这一点,让我们更深入地了解一下推理过程是如何工作的。

  • 作为第一步,我们的 KNN 模型计算这个新数据点到“拟合的”训练数据内的每个数据点的距离。
  • 然后,在下一步中,该算法选择“k”个训练数据点,这些训练数据点根据计算的距离最接近这个新数据点。
  • 最后,该算法将作为我们的新数据点的最近邻居的这些“k”点的目标标签进行比较。在这些 k 个邻居中具有最高频率的目标标签被分配为新数据点的目标类别。

这就是 KNN 分类算法的工作原理。

关于数据点之间距离的计算,我们将使用欧几里德距离公式。我们将在下一节中理解这种距离计算,我们将从头开始编写我们自己的基于 KNN 的机器学习模型。

现在进入有趣的,实用的部分!我们将从快速浏览我们正在通过项目解决的问题陈述开始。

理解问题陈述

对于这个项目,我们将致力于著名的 UCI 红酒数据集.) 。这个项目的目的是创建一个可以预测红酒样本质量的机器学习解决方案。

这是一个多类分类问题。目标变量,即葡萄酒的“质量”,接受一个范围从 0 到 10 的离散整数值,其中质量分数 10 表示葡萄酒的最高质量标准。

现在我们已经理解了问题,让我们从项目开始,导入所有必要的项目依赖项,包括必要的 PyData 模块和数据集。

导入项目依赖关系

第一步,让我们导入所有必要的 Python 模块。

现在,让我们导入数据集。

快速浏览数据集(图片由作者提供)

现在我们已经导入了数据集,让我们试着理解数据中的每一列表示什么。

理解数据

下面是对数据集中所有单个列的简要描述。

数据集的描述(图片由作者提供)

正如我们前面所讨论的,“质量”列是这个项目的目标变量。数据集中的其余列表示将用于训练模型的特征变量。

现在我们知道了数据集中不同的列代表什么,让我们继续下一部分,我们将对数据进行一些预处理和探索。

数据争论和 EDA

数据争论(或预处理)包括分析数据,看看它是否需要任何清理或缩放,以便为训练模型做准备。

作为数据预处理的第一步,我们将检查数据中是否有需要处理的空值。

列描述和空值计数(作者图片)

正如我们所看到的,在我们的数据集中没有空值。这是一件好事,因为我们不必处理任何丢失的数据。现在,让我们看一下数据的统计分析。

从上面给出的统计分析中一个突出的观察结果是,在我们的数据集中不同列的值的范围中有一个明显的不一致。更清楚地说,一些列中的值的顺序是 1e-1 ,而在少数其他列中,值可以高达顺序 1e+2 。由于这种不一致性,在训练模型时可能会出现特征权重偏差。这基本上意味着,某些特征最终可能会比其他特征对最终预测的影响更大。因此,为了防止这种重量不平衡,我们将不得不调整我们的数据。

对于这种扩展,我们将标准化我们的数据。 标准化 通常指重新调整数据,使每个特征列的平均值为 0,标准差为 1(单位方差)。

以下是标准缩放的数学公式。

现在我们知道了数学公式,让我们继续用 Python 从头开始实现它。

步骤 1 :分离特征矩阵和目标数组。

步骤 2 :声明标准化功能。

步骤 3 :对特征集进行标准化。

标准化数据(图片由作者提供)

这样,我们就完成了数据的标准化。这将最有可能照顾体重偏差。

现在,对于我们的数据争论和 EDA 部分的最后一部分,我们将看看数据集的目标列中的值的分布。

目标标签数量(作者图片)

上图中的一些观察结果是-

  • 在我们的数据中,大多数葡萄酒样品被评为 5 和 6 级,其次是 7 级。
  • 没有一款酒的评分高于 8 或低于 3。这意味着极高品质(9 或 10)或极低品质(0、1 或 2)的葡萄酒样品可以被认为是一种假设的理想情况,或者说数据可能受到采样偏差的影响,其中极高品质的样品在调查中没有任何代表性。
  • 当我们注意到大多数葡萄酒样品被评为 5 或 6 级时,我们最后一个关于数据中取样偏差的假设得到了进一步加强。
  • 根据这些数据训练的模型将产生有偏差的结果,更有可能将葡萄酒样品归类为质量等级 5 或 6,而不是 3 或 8。要了解更多关于抽样偏差或如何处理它,请查看我的文章。

既然我们已经完成了对数据的探索,让我们进入项目的最后一部分,在这里我们将使用 NumPy 对多类分类器 KNN 模型进行编码。

建模和评估

作为建模过程的第一步,我们首先将数据集分成训练集和测试集。这样做是因为在相同的数据上训练和评估你的模型被认为是一种不好的做法。

让我们看看如何使用 Python 实现分割数据集的代码。

步骤 1:声明 split 函数。

步骤 2:在我们的标准化数据集上运行分割函数。

分叉的形状(图片由作者提供)

现在我们已经创建了我们的训练和验证集,我们将最终看到如何实现模型。

根据我们到目前为止所学的知识,下面是创建 KNN 模型的步骤。

第一步:训练模型- 正如我们前面读到的,在 KNN 的例子中,这仅仅意味着将训练数据集保存在内存中。我们在创建培训和验证数据拆分时已经做到了这一点。

步骤-2:计算距离- 作为 KNN 算法中推理过程的一部分,计算距离的过程是一个迭代过程,其中我们从训练数据中的每个单个数据点计算测试数据中的数据点(基本上是数据实例/行)的欧几里德距离。

距离的计算(图片由作者提供)

现在,让我们了解欧几里德距离公式是如何工作的,以便我们可以为我们的模型实现它。

  • 让我们考虑两个数据点 A 和 b

→A=【A0, a 1, a 2, a 3,… a n】,其中 a i 是表示数据点 a 的特征。

同样, B= [ b 0, b 1 ,b 2 ,b 3 ,…。b n】。

因此,使用以下公式计算数据点 A 和 B 之间的欧几里德距离

欧几里德距离公式(图片由作者提供)

现在让我们用 Python 实现这个距离计算步骤。

  • 步骤-2.1 :声明 Python 函数计算两点之间的欧氏距离。

  • Step-2.2 :声明一个 Python 函数,计算训练数据中每一点的距离

在我们进入下一步之前,让我们测试一下距离函数。

正如我们所看到的,我们的距离函数成功地计算了测试数据中第一个点与所有训练数据点的距离。现在我们可以进入下一步了。

步骤 3:选择 k 个最近的邻居并进行预测- 这是推断阶段的最后一步,其中算法基于步骤 2 中计算的距离选择 k 个最接近测试数据点的训练数据点。然后,我们考虑这些 k 个最近邻点的目标标签。出现频率最高的标签被指定为测试数据点的目标类别。

让我们看看如何用 Python 实现这一点。

步骤-3.1 :定义 KNN 分类功能。

步骤 3.2 :在我们的测试数据集上运行推理。

预测值数组(图片由作者提供)

至此,我们完成了建模和推理过程。最后一步,我们将评估模型的性能。为此,我们将使用一个简单的精度函数来计算我们的模型做出的正确预测的数量。

让我们看看如何在 Python 中实现精度函数。

步骤 1 :定义精度函数。

第二步:检查我们模型的准确性。

初始模型精度

步骤 3 :与使用 Scikit-Learn 库构建的 KNN 分类器的准确度进行比较。

Sklearn 精度,k 值与 scratch 模型相同

这里有一个有趣的观察!虽然我们的模型表现得不是很好(只有 57%的正确预测),但它与 Scikit-Learn KNN 模型具有完全相同的准确性。这意味着我们从头定义的模型最不能复制预定义模型的性能,这本身就是一项成就!

不过,我相信我们可以在一定程度上进一步提高模型的性能。因此,作为我们项目的最后一部分,我们将找到超参数‘k’的最佳值,我们的模型对此给出了最高的精度。

模型优化

在我们实际寻找最佳 K 值之前,首先让我们理解 K 值在 K-最近邻算法中的重要性。

  • KNN 算法中的 k 值确定了在确定测试数据点的类别时要考虑的训练数据点的数量。
  • 低 k 值的影响:如果 k 值非常低,比如 1 或 2,模型将对数据中的异常值非常敏感。离群值可以定义为数据中不遵循数据中一般趋势的极端情况。正因为如此,模型的预测变得非常不稳定。
  • 高 k 值的影响:现在,随着 KNN 算法中 k 值的增加,观察到一个奇怪的趋势。首先,观察到算法的稳定性增加。其中一个原因可能是,当我们考虑更多的邻居来预测测试数据点的目标类时,由于多数投票,离群值的影响减少了。然而,随着我们继续增加 k 值,在某个点之后,我们开始观察到算法的稳定性下降,并且模型精度开始恶化。

下图大致描述了 KNN 分类器模型的 k 值和稳定性之间的关系。

k 值与稳定性(图片由作者提供)

现在,让我们最后评估一系列不同 k 值的模型。具有最高精确度的一个将被选为我们模型的最终 k 值。

不同 k 值下的模型精度(图片由作者提供)

我们可以看到,k 值 1 的精度最高。但是正如我们之前讨论的,对于 k=1,模型将对异常值非常敏感。因此,我们将使用 k=8,它具有第二高的精度。让我们观察 k=8 的结果。

如您所见,我们在这里获得了性能提升!仅仅通过调整超参数“k ”,我们的模型的精确度就提高了近 3%。

这样,我们的项目就结束了。

最后,让我们快速总结一下今天所学的内容,以及本课的一些要点。

结论

本文对 K 近邻分类算法进行了深入的分析。我们知道该算法如何使用数据实例之间的欧几里德距离作为比较标准,并在此基础上预测特定数据实例的目标类。

在本指南的第二部分,我们主要使用 Python 和 NumPy,一步步地从头开始创建 KNN 分类模型。

虽然我们的模型不能提供一流的性能,但至少我们能够匹配预定义的 Scikit-Learn 模式的性能。现在,虽然我们能够通过超参数优化将模型的准确性提高 60%,但性能仍然不理想。

这与数据的结构有很大关系。正如我们之前观察到的,数据中存在巨大的采样偏差。这无疑影响了我们模型的性能。性能不佳的另一个原因可能是数据中有大量异常值。所有这些把我们带到了一个非常重要的部分,我把它留到了最后,在那里我们将会看到 KNN 分类算法的优点和缺点。

KNN 的优势-

  • 正如我们之前讨论的,作为一种非参数算法,KNN 不需要多个训练周期来适应训练数据中的趋势。因此,KNN 的训练时间几乎可以忽略不计,事实上,它是训练速度最快的机器学习算法之一。
  • 与其他更复杂的分类算法相比,KNN 的实现非常简单

KNN 的缺点-

  • 说到推理,KNN 是非常计算密集型。对于每个测试数据实例的推断,算法必须计算它与训练数据中每个单点的距离。在时间复杂度方面,对于 n 个训练数据实例和 m 个测试数据实例,算法复杂度评估为O(m×n)
  • 随着维度(即特征总数)和数据集规模(即数据实例总数)的增加,模型规模也随之增加,进而影响模型的性能和速度。因此,对于高维、大规模数据集,KNN 不是一个好的算法选择。
  • KNN 算法对数据中的异常值非常敏感。即使数据集内的噪声略有增加,也可能会严重影响模型的性能。

到此,我们终于结束了今天的学习。在我的另一篇文章中,我已经直接让一堆机器学习算法互相对垒了。在那里,您可以查看 KNN 相对于其他分类算法(如逻辑回归、决策树分类器、随机森林集成等)的表现。

顺便说一下,这是我的 ML 从零开始系列的第四篇文章,其中我详细介绍了不同的机器学习算法及其数学基础。如果您有兴趣了解更多,本系列的其他文章是-

[## ML 从零开始-多项式逻辑回归

你的多项逻辑回归完全指南,又名 Softmax 回归

towardsdatascience.com](/ml-from-scratch-multinomial-logistic-regression-6dda9cbacf9d) [## 使用 PyTorch 的多项式回归(从头开始)

说到预测分析,回归模型被证明是最具成本效益的方法之一。当……

towardsdatascience.com](/polynomial-regression-using-pytorch-from-scratch-500b7887b0ed) [## 数字线性回归模型

在这个项目中,我们将看到如何创建一个使用多元线性回归算法的机器学习模型。

towardsdatascience.com](/linear-regression-model-with-numpy-7d270feaca63)

链接到项目 GitHub 文件

如果你喜欢这篇文章,并且想在 ML from Scratch 系列中继续看到更多的文章,确保你点击了下面的按钮。

快乐学习!

ML 从零开始-多项式逻辑回归

原文:https://towardsdatascience.com/ml-from-scratch-multinomial-logistic-regression-6dda9cbacf9d?source=collection_archive---------13-----------------------

图片来源-Unsplash.com

你的多项逻辑回归完全指南,又名 Softmax 回归

当涉及到现实世界的机器学习时,大约有 70% 的问题是基于分类的,在可用的特征集的基础上,你的模型试图预测在一组给定的类别(离散的可能结果)中,你的目标变量可能属于哪个类别。今天,在本文中,我们将了解多项逻辑回归,这是一种经典的监督机器学习算法,能够进行多类分类,即当有两个以上可能的离散结果类时,预测目标变量的结果。

这是一个基于项目的指南,在其中我们将看到如何从头开始编写 MLR 模型,同时理解允许模型进行预测的数学方法。

对于这个项目,我们将致力于著名的 UCI 克利夫兰心脏病数据集我们将从头开始创建一个 ML 模型,该模型使用多项逻辑回归,能够预测患者心脏病的严重程度。

多项式逻辑回归基础

在我们开始实际的项目之前,让我们首先熟悉 MLR 背后的基本思想——它是什么,它做什么,以及它是如何操作的?

到底什么是多项逻辑回归?

你可以把多项逻辑回归看作是类固醇上的逻辑回归(更具体地说,是二元逻辑回归)。而二进制逻辑回归可以预测二进制结果(例如,是或否,垃圾邮件或非垃圾邮件,0 或 1 等。),MLR 可以预测 k 个可能结果中的一个,其中 k 可以是任意正整数。

为特征集预测的结果是 k 个可能结果之一

MLR 是如何工作的?

多项式回归函数是一种统计分类算法 。这意味着,一旦我们为函数提供了一组要素,模型就会执行一系列数学运算,将输入值归一化为遵循概率分布的值向量。

MLR 函数根据给定的特征集计算可能的目标类的概率

  • 我们给模型的输入是一个特征向量, X ,包含特征X1, x 2x 3 …..xn。
  • 我们得到的输出是一个概率向量 Y ,包含 y 1y 2Y3Yk对于 k 目标类的概率。
  • 这里,y1+y2+y3…+yk= 1,由于一个系统中所有可能事件的总概率总是 1。

最后,概率最高的结果将是给定特征集的预测结果。

现在的问题是,MLR 函数到底是如何将特征集转换成概率值的?在我们的项目中,我们会努力理解这一点。

导入项目依赖关系

在我们开始这个项目之前,让我们首先导入所有必要的模块和包。

现在,我们将导入数据集。根据数据源,数据集没有列名。因此,我们将把 header 属性设置为 None,然后根据源上的可用信息手动设置列名。

显示数据集的屏幕截图

理解数据

现在我们已经导入了数据集,让我们试着理解每一列的含义。

这里, num 列是我们的目标变量,值的范围从 0(没有疾病)到 4(心脏病的高几率)。

既然我们已经确切地知道了我们的数据集代表什么,让我们继续下一步。

数据预处理

现在,让我们分析数据,看看是否需要清理或修改。作为数据预处理的第一步,我们将检查是否有任何空值需要处理。

正如我们所看到的,列 cathal 有 4 个和 2 个'?'分别取值。这些是我们需要处理的空值。由于这两列都由分类值组成,我们将用各自列的中值替换空值。我们还将把这两列类型转换为‘float 64’值。

现在我们已经清理了数据,让我们看看数据集的统计分析。

数据集的统计分析

观察数据后,我们可以看到数据需要缩放,因为我们的值在范围 (1,1e+2)内。我们缩放数据的主要原因是,由于我们将使用随机梯度下降来优化我们的模型参数,缩放可以显著提高我们的优化器的速度和准确性。

这里,我们将使用标准比例来标准化数据。 标准化 通常是指重新调整数据,使平均值为 0,标准差为 1(单位方差)。以下是标准缩放的数学公式。

这里,

  • μ =一列中所有值的平均值
  • σ =列的标准偏差

现在,让我们在代码中实现它。第一步是将数据集分为目标数组和要素数组。

特征矩阵和目标向量的形状

现在,让我们定义标准缩放的函数。

我们现在将对我们的特性集执行标准化。

正如我们所看到的,每个特性列的标准偏差现在是 1,正如标准缩放所预期的那样。我们已经成功地标准化了我们的功能集。

这样,我们就完成了数据争论的过程。随着数据的清理和标准化,现在让我们开始研究我们的模型。

从头开始构建模型

正如我们前面看到的,MLR 模型将特征向量作为输入,然后根据这些特征计算可能结果的概率。那么 MLR 模型到底是怎么做到的呢?让我们在这一节中找出 MLR 模型的编码位置。

多项式回归函数由两个功能层组成

  1. 线性预测函数(也称为逻辑层)
  2. Softmax 函数(也称为 softmax 层)

首先,让我们看看线性预测函数的作用。下面给出了线性预测函数的公式。

如果你仔细观察,这类似于我们用于线性回归模型的函数。它基本上做的是在范围(- ∞, + )内映射我们的目标变量的每个可能结果的分数。

这有点类似于 log odds( logit function ),将一个事件的赔率映射到范围(- ∞, + )。因此,线性预测函数也称为 logit 函数。

现在,我们将看到线性预测函数的代码。

步骤 1 -为我们的模型创建随机权重和偏差(因为我们有 5 个可能的目标结果和 13 个特征,k = 5,m = 13)。

第 2 步 -定义线性预测函数。

现在,让我们测试一下特征矩阵的功能。最终输出应该是一个 303 x 5 的矩阵,因为我们的数据集中有 303 个特征集,目标变量有 5 个可能的结果。

正如我们所看到的,这个函数工作得很好。现在进入下一步,将 logit 分数转换成概率值。这就是 softmax 函数发挥作用的地方。下面给出了 softmax 算法的公式。

softmax 函数的作用是对每个可能结果的 logit 分数进行归一化,使得归一化的输出遵循概率分布。

通俗地说,softmax 函数将一个特性集的可能结果的 logit 得分转换为概率值。

现在,让我们为我们的模型定义 softmax 函数。

既然我们已经定义了 softmax 函数,那么让我们将这两个函数合并成一个多项式函数用于我们的模型。

现在,让我们对我们的特征集执行逻辑回归。

现在让我们检查我们的模型的准确性。由于权重和偏差是随机生成的,我们不能指望我们的模型在此刻非常准确。

初始模型精度

正如我们所看到的,初始模型精度只有 16%左右,这是非常差的,甚至不能考虑这个模型在现实生活中进行任何心脏病预测。

因此,我们需要优化我们的模型参数,以提高其准确性。

模型优化

在我们进一步优化我们的模型之前,我们应该首先将数据集分成测试集和训练集。在同一个数据集上进行训练和测试被认为是一种不好的做法,因为它会严重影响模型的真实性能。

让我们定义 train_test_split 函数,将数据集分成训练和测试数据。然后,我们将在数据集上运行它。

训练特征、训练目标、测试特征和测试目标的大小

现在我们有了独立的训练和测试数据集,我们将把测试数据集放在一边,只用于测试目的。所有的训练和优化都将在训练数据集上执行。

现在我们离优化模型只有一步之遥了。在开始优化之前,我们有几个问题要回答。我们计划优化模型的标准到底是什么?甚至优化的目的到底是什么?

答案是——我们希望优化模型,以减少模型产生的信息损失。由于优化的标准是信息损失,我们需要为我们的模型定义一个损失函数。

对于多项式回归函数,通常我们使用交叉熵损失函数。下面给出了交叉熵损失函数的公式。

现在让我们定义交叉熵损失函数。

既然我们已经定义了损失函数,我们将最终定义优化器算法。下面给出了随机梯度下降运算的公式。

图像来源

关于这方面的更多细节,请参考这个来源。下面给出的是 SGD 算法的代码。

现在我们已经准备好了优化器函数,我们将为我们的模型运行它。

我们现在已经到了项目的最后一步。

“我们已经到了最后阶段!”

现在,我们将使用通过运行优化器函数获得的更新权重和偏差来测试我们的多项式逻辑回归模型。

注意——测试将在测试数据集上进行,而不是在训练数据集上进行。

正如我们所看到的,我们的模型在测试数据上显示了大约 67%的准确性。虽然这比我们最初获得的 16%有了显著的提高,但仍有足够的改进空间。

您可以通过调整超参数(学习率、训练次数等)来进一步提高精确度。)或者通过使用不同的缩放或优化算法来尝试该过程。记住,你尝试的越多,你学到的就越多!

这样,我们的项目就结束了。

以下是关键要点-

  • 从头开始编写多项式逻辑回归模型。
  • MLR 模型中涉及的数学。

更多像这样有趣的项目,请查看我的简介。

我只是机器学习和数据科学领域的新手,所以任何建议和批评都将真正帮助我提高。

点击以下链接,继续关注更多 ML 内容!

数据集和 Jupyter 笔记本的 GitHub repo 链接-

[## aman Sharma 2910/多项式回归-Scratch _ heart disease prediction

在这个项目中,我从头开始编写了一个 MLR 模型,可以用来预测心脏的存在(和严重程度)。

github.com](https://github.com/amansharma2910/MultinomialLogisticRegression-Scratch_HeartDiseasePrediction)

参考

  • 多项逻辑回归— 维基百科
  • Logit 函数— [维基百科](https://en.wikipedia.org/wiki/Logit#:~:text=In statistics%2C the logit (%2F,.)
  • Softmax 函数— 维基百科
  • 交叉熵函数-MachineLeariningMechanic.com

ML impossible:使用 Vaex 和 Scikit-Learn 在 5 分钟内在您的笔记本电脑上训练 10 亿个样本

原文:https://towardsdatascience.com/ml-impossible-train-a-1-billion-sample-model-in-20-minutes-with-vaex-and-scikit-learn-on-your-9e2968e6f385?source=collection_archive---------1-----------------------

汤姆·克鲁斯尝试在没有 Vaex 的情况下进行机器学习。(版权所有:派拉蒙影业)

让您的笔记本电脑感觉像一台超级计算机。

“数据是新的石油。”不管你是否同意这种说法,收集和利用数据的竞赛已经持续了一段时间。事实上,今天的科技巨头有一个共同点,就是他们有能力充分利用他们收集的大量数据。他们有知识、人力和资源来分析数十亿个数据点,大规模训练和部署各种机器学习模型,然后影响我们星球上无数的人。

创建一个简单的机器学习服务也不是一件小事。即使我们忽略数据收集和扩充步骤,我们仍然需要理解数据,适当地清理数据,创建有意义的特征,然后训练和调整模型。接下来是一系列的验证步骤,有望更好地理解数据和模型。重复这个过程,直到模型满足业务目标,然后投入生产。然而,在实践中,这一过程可能会无限期地继续下去。

想象一下,我们有一个包含超过10 亿个样本的数据集,我们需要用它来训练一个机器学习模型。由于数量庞大,探索这样的数据集已经变得棘手,而重复清洗、预处理和训练步骤成为一项艰巨的任务。诸如此类的挑战通常通过分布式或云计算来解决。虽然这是当今的标准方法,但与在本地机器上工作相比,它可能非常昂贵、耗时,而且不太方便。

在这篇文章中,我将展示任何人如何以快速有效的方式在十亿个样本上训练机器学习模型。您的笔记本电脑就是您需要的所有基础设施。只要确保它插上电源就行了。

问题:预测出租车行程持续时间

例如,假设我们想帮助一家出租车公司预测在纽约市的行程需要多长时间。我们将使用纽约市出租车数据集,其中包含 2009 年至 2015 年间由可识别的黄色出租车进行的超过10 亿次出租车旅行的信息。原始数据由纽约市出租车豪华轿车委员会(TLC)提供,可以从他们的网站(T3)上下载(T2)。如果你只是对作为本文基础的 Jupyter 笔记本感兴趣,你可以 点击这里

使用 Vaex 进行数据准备

为了操作大量数据,我们将使用 Vaex ,一个 Python 开源数据帧库。利用内存映射、延迟评估和高效的核外算法等概念,Vaex 可以轻松处理那些太大而无法放入 RAM 的数据集。

让我们从打开数据开始。为了方便起见,我将 7 年的出租车数据合并到一个文件中。即使文件在磁盘上大于 100GB,用 Vaex 打开它也是即时的:

打开一个内存映射文件是即时的(119 毫秒!)与 Vaex 。如果你本地没有,你可以从 AWS 上下载。

检查数据也一样快。由于数据是内存映射的,Vaex 立即知道在哪里查找,只读取需要的部分。对于如下所示的简单预览,只从磁盘中读取前 5 行和后 5 行。

出租车数据集的预览。实际上只有前 5 行和后 5 行是从磁盘中读取的。

使用 Vaex 处理纽约出租车数据集相当简单,尽管它的磁盘容量超过 100GB,包含超过 11 亿条记录。本文回顾了 Vaex 的基础知识,并对这个完全相同的数据集进行了探索性的数据分析。

在开始之前,让我们将数据分成一个训练集和一个测试集。我们将按年份进行划分,这样 2015 年进行的旅行将构成测试集,而在此之前的所有旅行将构成训练集。数据集是按年份排序的,因此我们可以通过对数据帧进行切片来进行拆分。

创建训练集和测试集。Vaex 数据帧的切片不会复制数据,而只会创建一个引用。

请注意,执行上述代码单元不会产生数据的内存副本。对 Vaex 数据帧进行切片会产生浅拷贝,该浅拷贝仅引用原始数据的适当部分。

数据争论

这个练习的目的是预测出租车旅行的可能持续时间。一次旅行的持续时间在数据集中并不容易获得,但是从接送的时间戳来计算是微不足道的。

从现有列创建新列不需要额外的内存,而且是即时的。

在上面的代码示例中计算行程距离会产生一个虚拟列。创建这样的列不消耗内存,因为它们只存储定义它们的表达式,并且只在必要时才进行计算。

现在,让我们从训练集中过滤出异常值和错误的数据样本。本文中的探索性数据分析可以作为如何做到这一点的指南,因此如果您想了解这些过滤选择背后的基本原理,请查看。

过滤出 Vaex 数据帧只需几秒钟,不需要额外的内存,即使它有数十亿行。

过滤背后的主要思想是移除异常值和可能的错误数据输入,因此模型不会被少数异常样本“分散”注意力。应用所有过滤器后,训练集“仅”包括 812,816,595 次出租车旅行。

在这个阶段,我们可以开始设计一些有意义的特性。因为所有的特性都是虚拟列,所以我们不需要关心内存的使用,因此可以自由地进行实验和创新。让我们从提取拾取时间戳的几个特征开始。

从提货日期和时间中提取一些有用的特征。

现在,让我们创建几个计算要求更高的特性。其中之一是上下车点之间的距离,我们称之为“弧距”。第二个特征是出租车行程的方向角,即出租车是否从其起点向其目的地正北方或西北方行进的指示。

通过 Numba 或 CUDA 的即时编译可以加速计算要求高的表达式的评估。

注意函数调用末尾的.jit_numba方法。通过 Numba 进行实时编译,可以加速计算开销很大的表达式的求值。如果你的机器配备了更新的 NVIDIA 显卡,你可以通过调用.jit_cuda方法使用 CUDA 来获得额外的提升。通过在一些表达式上使用.jit_numba,在其他表达式上使用.jit_cuda,您可以同时利用 CPU 和 GPU 来获得最高性能。

数据转换(vaex.ml)

在我们将数据传递给任何模型之前,我们需要确保它被适当地转换,以便充分利用它。Vaex 包含了vaex.ml包,它实现了各种常见的数据转换,比如 PCA、分类编码器和数字定标器。所有的转换都用熟悉的 scikit-learn API 调用,在核外并行执行。

让我们把重点放在接送地点。在美国的许多城市,街道形成网格状。这在曼哈顿地区清晰可见。提高模型性能的一个想法是在装载和卸载位置应用一组 PCA 变换。这将导致由许多上下车点跟踪的街道与自然地理轴(经度和纬度)对齐,而不是与它们成一个角度。

使用 vaex.ml,在近 10 亿个样本上安装几个 PCA 变压器大约需要半分钟。

注意,当使用vaex.ml时,将整个数据帧传递给转换器的.fit.transform.fit_transform方法,而转换所应用的特性是在实例化转换器时指定的。最重要的是,.transform方法返回 DataFrame 的浅层副本,其中转换的结果以虚拟列的形式存储。这使我们很容易看到 PCA 变换的结果。

将原始位置与 PCA 变换后的上下车位置进行比较。

让我们将注意力转移到我们之前定义的“提货时间”、“提货日”和“提货月”特性上。这些特征的关键属性是它们在本质上是周期性的,即一月与二月和十二月一样接近。因此,我们将使用在vaex.ml中实现的CycleTransformer,它本质上将每个特征视为极坐标(ρ=1,φ)中单位圆内的角度φ。然后,变换器计算半径ρ的 𝑥𝑦 投影,从而为每个特征获得两个新分量。这个技巧完美地保留了不同值之间的相对距离,因为它只是一个坐标变换。你可以在这篇文章中读到更多关于这种方法的内容。

使用 vaex.ml.CycleTransformer 对循环特征进行编码可以完美地保留不同值之间的相对距离。

我们将同样的技巧应用于方向角,因为它也是一个循环特征。让我们画出从“pickup_time”列中得到的特性,以说服我们自己这些转换是有意义的。

“拾取时间”特征的 𝑥𝑦 投影的密度图。

我们看到变换后的特征产生了一个完美的单位圆。请注意,与普通挂钟不同,所有 24 小时都显示在圆圈上。比如“午夜”有坐标 (x,y) = (1,0),“6 点”在 (x,y) = (0,1),而“正午”在 (x,y) = (-1,0)。

最后,我们只有一个连续的特征,“弧距离”,我们没有注意到。我们将简单地对其应用标准缩放。

使用 vaex.ml 对连续要素进行标准比例变换。

现在我们已经完成了所有的预处理任务,我们可以创建一个最终的特征列表,用于训练模型。

用于训练模型的特征子集。

训练模型:Vaex+sci kit-learn

在这个阶段,我们为模型训练阶段做好了准备。虽然vaex.ml还没有实现任何预测模型,但它确实提供了 Python 生态系统中几个流行的机器学习库的接口,如 scikit-learn 和 xgboost 。通过 Vaex 使用这些模型的好处是,在进行数据清理、特征工程和预处理时不会浪费任何内存,从而最大限度地利用 RAM 来训练模型。

对于目前的问题,如果我们要实现我们打算用于培训的所有功能,我们仍然需要比典型的笔记本电脑或台式电脑上可用的内存多得多的内存。为了避免这个问题,我们将使用通过 scikit-learn 获得的[SGDRegressor](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDRegressor.html)SGDRegressor属于 scikit 中的预测模型家族——了解除了通常的.fit之外,还实现了一个.partial_fit方法。这使得模型可以在批量数据上进行训练,本质上使其脱离核心。

使用在vaex.ml中实现的包装器,可以轻松地从 Vaex 数据帧向 scikit-learn 模型发送批量数据。使用非常简单。首先实例化 scikit-learn 中的SGDRegressor,同时以标准方式设置其参数。然后实例化在vaex.ml中实现的IncrementalPredictor,同时提供主模型、特性名称列表、目标列的名称和批处理大小。原则上,任何模型都可以使用,只要它有一个.partial_fit方法并遵循 scikit-learn API 约定。通过批量大小,可以控制 RAM 的使用。可选地,还可以指定时期的数量,即,每个批次中的数据被模型看到多少次,以及是否应该被混洗。最后,我们在IncrementalPredictor实例上调用.fit方法,在这里我们传递训练集数据帧。

使用 Vaex 和 scikit-learn 在大约 10 亿个样本上训练一个模型既简单又快速。

非常值得注意的是,Vaex + scikit-learn 组合导致我的笔记本电脑(MacBook Pro 15”,2018,2.6GHz 英特尔酷睿 i7,32GB RAM)的总训练时间仅为 7 分钟。这包括对所用的 14 个特征进行动态评估,所有这些特征都是虚拟色谱柱,以及训练 scikit-learn 模型。此外,使用上面显示的一组参数,RAM 的使用从来没有超过 4 GB,这给我留下了足够的空间来运行 Slack。

上面显示的完全相同的设置也由 Maarten Breddels 在他的联想 Thinkpad X1 Extreme 笔记本电脑(英特尔酷睿 i7–8750h,32GB RAM)上运行,培训阶段花费了不到 5 分钟!

在运行 Linux 的 Lenovo Thinkpad X1 Extreme 笔记本电脑(英特尔酷睿 i7–8750h,32GB RAM)上训练 SGDRegressor 不到 5 分钟。

IncrementalPredictor不仅仅是一个将 Vaex 数据帧传递给 scikit-learn 模型的便利类。它还是一个vaex.ml转换器,这意味着.transform方法返回一个包含模型预测的数据帧的浅层副本作为虚拟列。这是在vaex.ml中实现的任何模型包装器的情况。这不仅不需要额外的内存,而且还可以非常方便地对结果进行后处理,甚至进行集成,以及计算各种性能指标和诊断图,稍后我们将会看到。

vaex.ml 中的所有模型包装器都是变形金刚。

最后,让我们将预测限制在模型训练数据的范围内。这样做是为了防止对一些奇异的特征值组合进行不实际或不切实际的持续时间估计。因此,让我们将任何小于 3 分钟的预测设置为 3,将任何大于 25 分钟的预测设置为 25。

vaex.ml 模型包装器的输出是一个虚拟列,这使得后处理变得容易,或者用于创建诊断图或计算指标。

管道呢?

既然模型已经训练好了,我们想知道它在测试集上的表现如何。您可能已经注意到,与其他库不同,我们没有显式地创建一个管道来传播所有的数据清理和转换步骤。事实上,在 Vaex 中,当用户对数据进行探索和转换时,管道会自动创建。每个 Vaex 数据帧包含一个状态,它是一个可序列化的对象,包含应用于它的所有转换:过滤、创建新的虚拟列、列转换)。

回想一下,我们创建的所有特征,连同 PCA 变换的输出、缩放和预测模型输出,包括对预测的最终修补,都是虚拟列,因此存储在训练数据帧的状态中。因此,为了计算测试集上的预测,我们所需要做的就是将该状态应用于该测试集数据帧,并且所有的转换将被自动传播。

将来自训练的状态应用到测试集导致过滤器和虚拟列的自动传播。

状态也可以被序列化并从磁盘中读取,这大大简化了模型部署的任务。

Vaex 数据帧的状态很容易序列化并从磁盘中读取。这在部署模型时非常有用。

模型诊断

既然行程持续时间预测对于训练集和测试集都是可用的,那么让我们来计算一些性能指标。由于这是一个回归问题,我们将计算平均绝对误差和均方误差。

计算训练集和测试集的绝对误差和均方差。

请注意,上图中显示的 4 个统计数据的计算花费了大约 4.5 分钟。考虑到计算需要评估所有特征,然后传递到模型以获得预测,这是非常令人印象深刻的,并且这是对训练集和测试集之间的超过 10 亿个样本进行的,超过两次。

在测试集上评估的平均绝对误差刚好超过 3.5 分钟。这是否是一个可以接受的错误,你也许应该咨询一下纽约市的出租车常客或出租车司机。我们不应该从表面上接受这样的统计数据,因此让我们创建两个诊断图。让我们画出实际行程持续时间与估计行程持续时间的分布,以及预测持续时间的绝对误差。

左图:测试集的实际行程持续时间与估计行程持续时间的密度图。右图:测试集的预测持续时间的绝对误差。

虽然我们看到实际和估计的出行持续时间之间有很强的相关性,但上图的左图也显示了模型估计值系统地偏向更高的值。一个潜在的原因是训练特征和目标变量的非高斯分布。也可能有一些异常值会对模型性能产生负面影响,尽管之前进行了过滤。另一方面,在估算出租车行程持续时间时,或许有点悲观也没那么糟糕。

右边的面板显示了每个绝对误差箱的跳闸次数。事实上,测试集中 77%的行程持续时间的绝对误差小于 5 分钟。虽然目前的模式可能是一个很好的起点,但仍有很大的改进空间。好消息是,有了 Vaex,我们有了一个工具,可以让我们发挥创造力,以令人难以置信的高效方式尝试许多功能和预处理组合。

说到模型,SGDRegressor的训练实例作为IncrementalPredictor的属性是很容易得到的。可以很容易地访问它,并且我们可以使用它来检查用于训练模型的特征的相对重要性。

用于定型模型的功能的相对重要性。

生产呢?

想象一下,我们设法消除了模型中的所有怪癖,并且在彻底验证之后,它已经准备好投入生产了。原则上,使用 Vaex 很容易做到这一点。所需要的只是将状态存储在生产环境中。然后,该状态可以很容易地应用于输入的 Vaex 数据帧,并且预测将很容易获得。

回想一下,状态不仅会记住所有创建的虚拟列,还会记住应用了哪些过滤器。因此,如果要查询某个样本的预测,而该样本是训练集的一部分时会被过滤掉,则在预测时也会被过滤掉,因此该样本会“消失”。实际上,样本不可能就这样丢失,许多生产案例要求我们总是返回至少某种预测,不管查询是什么。

为了克服这个障碍,我们可以利用这样一个事实,即在 Vaex 中,过滤后的数据帧实际上仍然包含所有的数据,加上一个定义哪些行被过滤掉,哪些行被保留的表达式。在其他常见的库中,比如 Numpy 和 Pandas,我们只能过滤掉更多的行,而在 Vaex 中,我们实际上可以通过在过滤器中使用“or”操作符来取回行。

让我们为我们的问题实现这个想法。我们将名为“生产”的变量添加到训练数据帧中,并将其值设置为False。然后,我们添加一个额外的过滤器,在这种情况下,它只是变量的值。然而,现在我们使用“or”而不是默认的“and”操作符,这种操作符在类似于df3 = df2[df2.x < 5]的情况下使用。想法很简单:如果最后一个过滤器被设置为False,它将不会对任何其他过滤器产生影响,因为它的操作模式是“或”。然而,如果它被设置为True,这可以通过修改“生产”变量的值来实现,它将使所有其他过滤器无效,因此任何数据点都可以通过。

如何借助 Vaex 数据帧中的变量启用或禁用过滤器的示例。

上面的代码块显示了我们如何包含和修改“production”变量,以便在需要时禁用过滤器。我们可以很容易地确认,在这种情况下,测试数据帧包含的样本数与我们执行训练/测试分割时一样多,并且对每个样本都有预测。在这种情况下,计算平均绝对误差给出了 13 分钟的较高结果,这并不奇怪,因为该模型没有经过良好的训练,无法为现在是测试集一部分的许多异常值或错误样本提供预测。

我们对未来的愿景

我希望我设法向您展示了使用 Vaex 创建机器学习管道是多么容易和方便,即使训练数据超过 10 亿个样本,并占用超过 100 GB 的磁盘空间。我相信你会发现更多创造性的方法来使用 Vaex 来改进本文中提出的模型,以及为各种其他问题和用例创建许多新的模型。

我们, Vaex 团队相信,在未来,数据科学和机器学习可以通过免费和开源的工具方便高效地下载,即使是“大”数据。我们的目标是让 Vaex 更好地与 Python 数据科学堆栈的支柱相集成,并在将 Vaex 和 scikit-learn 更紧密地结合在一起方面投入了相当大的努力。敬请期待,肯定还有更精彩的东西往这边来!

数据科学快乐!

ML in Production-1:Amazon sage maker-AWS,设置、培训和部署!

原文:https://towardsdatascience.com/ml-in-production-1-amazon-sagemaker-aws-setup-train-and-deploy-896086848cde?source=collection_archive---------29-----------------------

"那些像生命流动一样流动的人知道他们不需要其他力量."老子

浮冰,斯瓦尔巴特群岛~ Roshini Johri(图片由作者提供)

将大规模的机器学习系统投入生产,并建立一个漂亮的流线型基础设施,其中的功能库只是流动,这已经成为我的一个新的困扰(也许这就是作为一个 10 年的机器学习老手对你所做的..你只是想狗屎工作)

最近,我与伦敦women in machine learning社区一起开始了一个关于学习和教授如何做到这一点的系列,分为三部分,以实现不同的机器学习工作流程。这是我演讲后写的文章。这篇文章假设了机器学习模型的基本知识,并更多地关注于在生产中设置工作流和部署。在这个系列的第一部分,我们将在亚马逊 Sagemaker 上进行设置。我们将使用 sklearn 的波士顿住房数据集。

机器学习生命周期

让我们花点时间来看一下机器学习的生命周期。简化的机器学习生命周期看起来像:

机器学习生命周期

现在是第一部分,数据准备,实际上应该是生产工作流程的数据预处理和特征工程。

  • 获取数据:这是一个过程,您将从 repos、ETL 等中读入数据,将数据移动到一个位置,以形成您的训练数据的原始版本。
  • 清理数据:这个阶段主要是做一些基本的清理工作,比如类型转换、空处理、确保字符串/类别等的一致性
  • 准备/转换:特征转换、衍生、高阶特征,如交互特征、编码等。

下一阶段涉及建模和评估阶段:

  • 训练模型:在这个阶段你的数据应该以特征向量和标签的形式分割成训练、验证和测试。在这个阶段,您将读取这些数据, 在您的训练集上训练您的模型,调整到验证集并在测试集上测试 !这也是您保存模型工件以进行评估和记录的阶段。
  • 评估模型:评估阶段,“我的模型做得对吗”阶段是最重要的阶段之一,我觉得我们从来没有在这个阶段花足够的时间。特征工程和模型评估将帮助您了解模型性能。句号。多注意你的模型评估指标,并选择正确的指标。

最后但同样重要的是,我们阅读这篇文章的真正原因是部署!万岁。

  • 部署到生产:这是您准备将您的模型发布到野外的阶段。添加所需的调度,并注意概念漂移和模型衰减(由于底层分布的变化而导致的性能变化)
  • 监控/收集/评估数据:模型性能、输入/输出路径、错误度量、日志、模型工件等都将被打上时间戳并记录下来,应该为完美的管道建立围绕模型选择的监控度量和警报/报告!

以上,是一个简化但漂亮的机器学习管道。激动吗?欣喜若狂?你应该害怕。在我看来,组织应该把这作为一句口头禅。现在让我们看看如何用 Amazon Sagemaker 设置一个。

亚马逊 Sagemaker

现在,第一步从创建一个 AWS 账户)开始。如果您已经熟悉 Amazon 提供的实例类型(ec2 实例),这会有所帮助。如果没有,请从这里开始。Sagemaker 实例针对运行机器学习(ML)算法进行了优化。实例的类型也取决于区域和可用区域。

https://aws.amazon.com/sagemaker/pricing/instance-types/

如果您觉得阅读太多关于实例类型的细节令人厌烦,那么开始吧:

开始 ML 的好实例: ml.m4.xlarge(非自由)

开始 DL 的好实例: ml.p2.xlarge(非自由)

AWS Sagemaker EC2 实例具有与之关联的默认配额。你可能不总是得到 20,这也因地区而异。根据您可能需要请求和增加的用例。这可以通过与 AWS 支持中心一起创建案例来完成。请在这里查看更多信息

Sagemaker 笔记本实例

现在要启动 sagemaker 笔记本实例,请转到 aws 帐户服务来搜索 sagemaker。进入 sagemaker 页面后,单击 create notebook instance。这将如下所示:

笔记本实例:命名笔记本并选择实例类型

下一步是选择 IAM 角色。简单的第一次尝试就是创建一个新的角色并选择 none 作为 s3 存储桶,除非有一个您想要读取的 s3 存储桶。此外,此时应该有一个选择 git 存储库的可选选项。向下滚动并点击创建笔记本实例。

笔记本实例:选择 IAM 角色

您可以看到正在创建的笔记本的状态,一旦准备就绪,您可以选择 jupyter 或 jupyter lab。

笔记本实例已创建!选择 Jupyter/JypyterLab

如果您需要克隆您的 git 存储库,从 jupyter 树的右上角打开终端,在那里显示 new,然后执行以下操作:

cd SageMakergit clone myFunSagemakerRepo

太好了!这应该为您设置了一个笔记本实例和一个 git hub 存储库。我们现在可以开始有趣的部分了!

Sagemaker 会话和角色

初始化 sagemaker 会话和角色

我们将使用 load_boston()方法从 sklearn 获取数据集。然后,我们将把这个数据集分成训练、验证和测试。

#load the data
boston_data = load_boston()#Training data
X_bos_pd = pd.DataFrame(boston_data.data, columns=boston_data.feature_names)#Target
Y_bos_pd = pd.DataFrame(boston_data.target)#Train/Test split
X_train, X_test, Y_train, Y_test = sklearn.model_selection.train_test_split(X_bos_pd, Y_bos_pd, test_size=0.20)#Train/Validation split
X_train, X_val, Y_train, Y_val = sklearn.model_selection.train_test_split(X_train, Y_train, test_size=0.33)

一旦创建了训练、验证和测试数据集,就需要将它们上传到 s3(简单存储服务)桶,以便 sagemaker 容器可以在执行训练作业时访问它们。最好用前缀指定位置,最好是型号名称和版本,以确保路径整洁。上传后,您可以从您的控制台转到 s3 服务并进行检查。

prefix = 'boston-xgboost-example'**test_location** = session.upload_data(os.path.join(data_dir, 'test.csv'), key_prefix=prefix)
**val_location** = session.upload_data(os.path.join(data_dir, 'validation.csv'), key_prefix=prefix)
**train_location** = session.upload_data(os.path.join(data_dir, 'train.csv'), key_prefix=prefix)

检查 s3 中的存储桶创建

Sagemaker 培训工作

在 sagemaker 中训练机器学习模型涉及到创建一个训练作业。我们将使用 xgboost 模型。请检查此处链接的文档,以确保您查看了 sagemaker 的要求和语法。

培训工作组件

要培训 sagemaker 模型,第一项任务是创建一个培训作业,包括以下内容:

  • 培训/验证的 S3 位置(注意:这应该是 csv 文件)
  • 模型的计算资源(这不同于我们用于笔记本电脑的资源)
  • 输出 S3 位置(模型工件)
  • 内置模型的停靠路径(见此)

模型估计器

  • 为了训练一个模型,我们需要创建一个模型估计器。这将包含关于如何训练模型的信息(配置)。更多详情请看这里:估算器
  • 我们将使用名为 get_image_uri 的 SageMaker 实用程序方法来获取内置算法的容器路径
  • 估计器初始化如下所示。这里我用了一个付费的例子。
container = get_image_uri(session.boto_region_name, 'xgboost')#xgboost estimator
xgb_estimator = sagemaker.estimator.Estimator(
container, 
role,      
train_instance_count=1,                                                                            train_instance_type='ml.m4.xlarge',                                                 output_path='s3://{}/{}/output'.format(session.default_bucket(), prefix),
sagemaker_session=session
)

模型超参数

  • 任何模型训练方法的关键部分,在我们开始训练之前,我们需要调用估计器的 set_hyperparameters 方法。xgboost 超参数见此:xgboost _ 超参数
  • 当估计器都设置好了,下一个开始训练的方法是 fit
xgb_estimator.set_hyperparameters(max_depth=5,
                        eta=0.2,
                        gamma=4,
                        min_child_weight=6,
                        subsample=0.8,
                        objective='reg:linear',
                        early_stopping_rounds=10,
                        num_round=200)train_s3 = sagemaker.s3_input(s3_data=train_location, content_type='csv')
validation_s3 = sagemaker.s3_input(s3_data=val_location, content_type='csv')xgb_estimator.fit({'train': train_s3, 'validation': validation_s3})

模型评估

  • SageMaker 使用一个 transformer 对象来评估模型。(文档)
  • transformer 对象像 estimator 对象一样,需要知道实例计数以及它需要转换的测试数据的类型和格式。为了让 transformer 以批处理的方式评估测试数据,我们需要让它知道将文件分解成块的行的分割类型。
xgb_transformer = xgb_estimator.transformer(instance_count = 1, instance_type = 'ml.m4.xlarge')xgb_transformer.transform(test_location, content_type='text/csv', split_type='Line')xgb_transformer.wait()

现在,为了将我们的数据从 s3 移回我们的笔记本进行分析,我们复制了它(我在 udacity 上学到的一个小技巧)

!aws s3 cp --recursive $xgb_transformer.output_path $data_dir

现在我们来评估!

Y_pred = pd.read_csv(os.path.join(data_dir, 'test.csv.out'), header=None)

y_pred 对 y_test

模型部署

通过高级 api 的模型部署非常简单。我将展示一个如何部署我们刚刚培训过的上述模型的示例。

#call deploy method to start an endpoint instance xgb_predictor = xgb_estimator.deploy(initial_instance_count=1, instance_type='ml.m4.xlarge')xgb_predictor.content_type = 'text/csv'
xgb_predictor.serializer = csv_serializerY_pred = xgb_predictor.predict(X_test.values).decode('utf-8')#DON'T FORGET TO SHUT DOWN/CLEAN UP WHEN YOU ARE DONE!
  • 与我们评估 transformer 对象的方式类似,我们可以对部署的模型做同样的事情,这是我们在生产环境中真正想要做的事情,以保存能力日志并比较不同运行的结果以及 概念漂移 (可能导致模型衰退的底层数据分布的变化)。
  • 根据测试集的大小,我们可以决定数据应该一次发送还是分块发送。
  • Xgb predictor 需要知道文件的格式以及要使用的序列化程序的类型。

这是在 AWS Sagemaker 上尝试建立第一个 ml 工作流的非常简单的方法。我建议在转向复杂之前坚持超级简单!我们将在稍后的帖子中处理较低级别的 api,并真正进入细节,但为了获得基本的理解并建立对新框架的舒适感,请使用一些简单的数据集尝试这些设置,并尝试不同的可用模型。

家政

请记住:

删除端点和端点配置

删除模型

删除 s3 存储桶

如果不使用笔记本实例,请将其停止

SageMaker 文档:

开发者文档可以在这里找到:https://docs.aws.amazon.com/sagemaker/latest/dg/

Python SDK 文档(也称高层方法)可以在这里找到:【https://sagemaker.readthedocs.io/en/latest/】

****Python SDK 代码可以在 github 上找到这里:https://github.com/aws/sagemaker-python-sdk

一如既往地乐于助人,回答问题并渴望反馈!请让我知道你是否喜欢这个流程,简单/复杂等等。

用于数据准备的 ML 基础设施工具

原文:https://towardsdatascience.com/ml-infrastructure-tools-for-data-preparation-70d79e70f8d4?source=collection_archive---------27-----------------------

数据准备-机器学习工作流程的第一阶段

作者的 ML 基础设施平台图

几乎每个行业的企业都在采用人工智能(AI)和机器学习(ML)。许多企业都在期待 ML 基础设施平台,以推动他们在业务中利用人工智能的运动。了解各种平台和产品可能是一项挑战。ML 基础设施空间拥挤、混乱且复杂。有许多平台和工具跨越模型构建工作流程中的各种功能。

按作者列出的 ML 工作流阶段图

为了理解生态系统,我们大致将机器学习工作流分为三个阶段——数据准备、模型构建和生产。了解工作流程每个阶段的目标和挑战有助于做出明智的决策,确定哪些 ML 基础设施平台最适合您的业务需求。

机器学习工作流程的每个广泛阶段(数据准备、模型构建和生产)都有许多垂直功能。其中一些功能是更大的端到端平台的一部分,而一些功能是一些平台的主要焦点。

由于模型是从数据中构建和学习的,因此构建模型的第一步是数据准备,即从数据中提取模型输入的过程。有许多工具可以帮助数据科学家获取数据、转换数据以及向数据集添加标签。在这篇博文中,我们将深入了解数据准备的目标是什么,组织在 ML 工作流的这一阶段面临的挑战,以及数据科学家何时决定进入工作流的下一阶段。

什么是数据准备?

问任何一个数据科学家,他们都会告诉你他们花了很多时间在数据准备上。管道的数据准备阶段用于将原始数据转换为用于训练模型的模型输入特征。特征是对提供实际模型输入的已清理数据的变换。

在管道的早期阶段,原始数据来自组织中不同的数据存储和湖泊。下一阶段涉及数据处理,以清理、转换和提取特征,从而在特征选择阶段生成一致的输入。处于使用 ML 基础设施前沿的大型科技公司(谷歌、脸书、优步等)通常会有集中的功能存储,因此许多团队可以在没有重复工作的情况下提取价值。

数据准备阶段包括多个步骤:获取数据、确保完整性、添加标签和数据转换以生成要素。

采购数据

获取数据是第一步,通常也是第一个挑战。数据可以存在于不同的数据存储中,具有不同的访问权限,并且可能散布着个人身份信息(PII)。

数据准备的第一步包括从正确的地方获取数据,并整合组织内不同数据湖中的数据。如果模型的输入、预测和实际值是在不同的时间段接收的,并存储在不同的数据存储中,这可能会很困难。设置公共预测或事务 ID 有助于将预测与其实际值联系起来。

此阶段通常涉及数据管理、数据治理和法律,以确定哪些数据源可供使用。此阶段的工作角色通常包括数据工程师、数据科学家、法律人员和 IT 人员。

数据存储领域的 ML 基础设施公司示例:Elastic Search、Hive、Qubole

完全

一旦数据来源,需要对完整性进行一系列检查,以确定收集的数据是否可以转化为有意义的特征。首先,了解可供使用的历史数据的长度很重要。这有助于了解模型构建者是否有足够的数据用于训练目的(一年的数据等)。拥有具有季节性周期和已识别异常的数据可以帮助模型建立弹性。

数据完整性还可以包括检查数据是否有正确的标签。许多公司在原始数据的清洁度方面存在问题。同一件事可以有多个标签。将会有一些数据未被标记或被错误标记。许多供应商提供数据标注服务,这些服务采用技术和人员的组合来向数据添加标签并清理问题。

数据标注中的 ML 基础设施公司示例: Scale AI,Figure Eight,LabelBox,Amazon Sagemaker

检查所看到的数据是否是有代表性的分布也很重要。数据是在一段不寻常的时间内收集的吗?这是一个更难的问题,因为它是特定于业务的,并且数据会随着时间的推移而不断变化。

数据处理

一旦收集了数据,并且有足够的带有适当标签的数据,就可以进行一系列的数据转换,从原始数据转换为模型可以理解的特征。该阶段特定于企业使用的数据类型。对于分类值,通常使用一键编码。对于数值,可以有某种形式的基于数据分布的规范化。这个过程的一个关键部分是理解您的数据,包括数据分布。

数据处理还可以包括额外的数据清理和添加数据质量检查。由于模型依赖于它们所训练的数据,因此通过删除重复事件、索引问题和其他数据质量问题来确保干净的数据非常重要。

一些数据争论公司允许数据科学家、业务分析师和数据工程师定义转换规则,以清理和准备数据。这些公司从无代码、低代码到以开发者为中心的平台。

最后,对训练数据进行持续的数据质量检查,以确保今天干净的数据明天也会干净。

数据准备是模型性能的组成部分。要获得完整、干净的数据有很多挑战。从数据源到所有数据转换,构建训练数据集的所有工作都要进行,因此很难跟踪所有可能影响模型性能的版本化数据转换。随着组织的发展,具有通用数据转换的功能库可以减少重复工作和计算成本。

数据角力中的 ML 基础设施公司: Trifacta,Pixata,Alteryx

数据处理领域的 ML 基础设施公司: Spark、DataBricks、Qubole、Hive

数据版本化、特征存储领域的 ML 基础设施公司&特征提取: Stealth Startups、Pachyderm、Alteryx

数据准备后会发生什么

在某些情况下,一旦数据科学家准备好数据,数据准备和模型构建之间的交接就由包含已处理数据的数据文件或要素存储构成。在其他情况下,移交是不固定的。在大型组织中,数据工程团队负责将数据转换成数据科学家可以用于建模的格式。

在许多托管笔记本中,如 Databricks 托管笔记本、Cloudera 数据科学工作台、Domino 数据实验室笔记本,数据准备工作流与模型构建并不分离。特征选择依赖于数据,因此函数开始模糊数据准备和模型构建之间的界限。

笔记本电脑管理领域的 ML 基础设施公司 : Databricks、Cloudera Workbench、Domino、Stealth Startups

下一个

我们将在 ML 工作流程的模型构建部分对 ML 基础设施公司进行更深入的研究。

联系我们

如果这个博客引起了你的注意,并且你渴望了解更多关于机器学习可观察性和模型监控,请查看我们其他的博客和 ML 监控上的资源!如果您有兴趣加入一个有趣的 rockstar 工程团队,帮助模型成功生产,请随时联系我们,并在此处找到我们的空缺职位!

用于模型构建的 ML 基础设施工具

原文:https://towardsdatascience.com/ml-infrastructure-tools-for-model-building-464770ac4fec?source=collection_archive---------17-----------------------

建模——ML 工作流的第二阶段

作者的 ML 基础设施平台图

几乎每个行业的企业都在采用人工智能(AI)和机器学习(ML)。许多企业都在期待 ML 基础设施平台,以推动他们在业务中利用人工智能的运动。了解各种平台和产品可能是一项挑战。ML 基础设施空间拥挤、混乱且复杂。有许多平台和工具跨越模型构建工作流程中的各种功能。

为了理解生态系统,我们大致将机器学习工作流分为三个阶段——数据准备、模型构建和生产。了解工作流程每个阶段的目标和挑战有助于做出明智的决策,确定最适合您业务需求的 ML 基础架构平台。

作者的 ML 基础设施平台图

机器学习工作流程的每个广泛阶段(数据准备、模型构建和生产)都有许多垂直功能。其中一些功能是更大的端到端平台的一部分,而一些功能是一些平台的主要焦点。

在我们的上一篇文章中,我们深入探讨了 ML 工作流程的数据准备部分。在那篇文章中,我们讨论了专注于数据准备功能的 ML 基础设施平台。在这篇文章中,我们将更深入地研究模型构建。

什么是模型构建?

建模的第一步是从理解业务需求开始。该模型解决了什么样的业务需求?这一步从 ML 工作流程的计划和构思阶段开始。在这个阶段,类似于软件开发生命周期,数据科学家收集需求,考虑可行性,并为数据准备、模型构建和生产创建一个计划。在这一阶段,他们使用数据来探索他们在规划阶段考虑过的各种模型构建实验。

特征探索和选择

作为这个实验过程的一部分,数据科学家探索各种数据输入选项来选择特征。特征选择是为机器学习模型寻找特征输入的过程。对于新模型,这可能是一个理解可用数据输入、输入的重要性以及不同候选特征之间的关系的漫长过程。这里可以做出许多决策,以获得更易解释的模型、更短的训练时间、获取特征的成本以及减少过拟合。找出正确的特征是一个不断迭代的过程。

特征提取领域的 ML 基础设施公司:Alteryx/Feature Labs,Paxata(DataRobot)

模型管理

数据科学家可以尝试多种建模方法。某些类型的模型比其他模型更适合某些任务(例如,基于树的模型更容易解释)。作为构思阶段的一部分,模型是否有监督、无监督、分类、回归等都是显而易见的。然而,决定什么类型的建模方法、什么超参数和什么特征取决于实验。一些 AutoML 平台会尝试许多具有不同参数的不同模型,这有助于建立基线方法。即使手动完成,探索各种选项也可以为模型构建者提供关于模型可解释性的见解。

实验跟踪

虽然在各种类型的模型中有许多优点和折衷,但一般来说,这个阶段涉及许多实验。有许多平台可以跟踪这些实验、建模依赖和模型存储。这些功能被广泛地归类为模型管理。一些平台主要关注实验跟踪。其他拥有培训和/或服务组件的公司拥有模型管理组件,用于比较各种模型的性能、跟踪培训/测试数据集、调整和优化超参数、存储评估指标以及实现详细的沿袭和版本控制。与 Github for software 类似,这些模型管理平台应该支持版本控制、历史传承和可再现性。

这些不同的模型管理平台之间的权衡是集成的成本。一些更轻量级的平台仅提供实验跟踪,但可以轻松地与当前环境集成,并导入到数据科学笔记本中。其他的需要一些更繁重的集成,需要模型构建者转移到他们的平台上,这样就有了集中的模型管理。

在机器学习工作流程的这一阶段,数据科学家通常会花时间在笔记本上构建模型、训练模型、将模型权重存储在模型存储中,然后在验证集上评估模型的结果。有许多平台可以为培训提供计算资源。根据团队希望如何存储模型对象,模型也有许多存储选项。

ML 基础架构 AutoML: H20,SageMaker,DataRobot,Google Cloud ML,微软 ML

实验跟踪中的 ML 基础设施公司:Weights and Biases、Comet ML、ML Flow、Domino、Tensorboard

模型管理领域的 ML 基础设施公司:Domino 数据实验室、SageMaker

超参数选项中的 ML 基础设施公司。:Sigopt、权重和偏差、SageMaker

模型评估

一旦在具有所选特征的训练数据集上训练了实验模型,就在测试集上评估该模型。该评估阶段涉及数据科学家试图了解模型的性能和需要改进的地方。一些更高级的 ML 团队将有一个自动化的回溯测试框架,用于评估历史数据上的模型性能。

每个实验都试图超越基线模型的性能,并考虑计算成本、可解释性和归纳能力之间的权衡。在一些更受监管的行业中,该评估过程还可以包括外部评审者的合规性和审计,以确保模型的可再现性、性能和要求。

ML 基础设施模型评测:Fiddler AI,Tensorboard,Stealth Startups

ML 基础设施预发布验证 : Fiddler AI, [Arize AI](https://arize.com/platform-overview/)

一个平台来统治他们

许多以汽车或模型制作为中心的公司,为每件事推销一个单一的平台。它们正在竞争成为企业在数据准备、模型构建和生产中使用的单一人工智能平台。这些公司包括 DataRobot、H20、SageMaker 和其他一些公司。

这一组分为低代码和以开发人员为中心的解决方案。Datarobot 似乎专注于无代码/低代码选项,允许 BI 或财务团队从事数据科学项目。这与 SageMaker 和 H20 形成了鲜明的对比,它们似乎迎合了数据科学家或开发者优先团队的需求,而后者是当今更常见的数据科学组织。这两种情况下的市场都很大,可以共存,但值得注意的是,并非所有的 ML 基础设施公司都向相同的人或团队销售。

该领域的许多新进入者可以被认为是 ML 基础设施食物链特定部分的最佳解决方案。最好的类比是软件工程领域,在这里你的软件解决方案 GitHub、IDE、生产监控都不是相同的端到端系统。它们是不同的软件是有原因的;它们提供非常不同的功能,具有明显的区别。

挑战

与软件开发并行不同,模型的可再现性通常被认为是一个挑战。这主要是由于缺乏对模型训练数据的版本控制。

理解该模型的性能有许多挑战。如何比较实验并确定哪个版本的模型是性能和权衡的最佳平衡?一个折衷可能是想要性能稍差的模型,但是更容易理解。一些数据科学家使用内置的模型可解释性特征,或者使用 SHAP/莱姆探索特征重要性。

另一个性能挑战是不知道你在这个实验阶段的模型性能将如何转化为现实世界。这可以通过确保训练数据集中的数据是模型在生产中可能看到的数据的代表性分布来最好地缓解,以防止过度适应训练数据集。这就是交叉验证和回溯测试框架有用的地方。

接下来会发生什么?

对于数据科学家来说,确定模型何时可以投入生产的标准非常重要。如果在生产中部署了一个预先存在的模型,那么可能是在新版本的性能更高的时候。无论如何,设定一个标准对于将实验实际转移到真实世界环境中是很重要的。

一旦模型被训练,模型图像/权重被存储在模型存储中。这通常是负责将模型部署到产品中的数据科学家或工程师可以获取模型并用于服务的时候。在某些平台中,这种部署甚至可以更简单,可以用外部服务可以调用的 REST API 来配置部署的模型。

下一个

我们将在 ML 工作流程的生产环节对 ML 基础设施公司进行更深入的研究。

联系我们

如果这个博客引起了你的注意,并且你渴望了解更多关于机器学习可观察性和模型监控,请查看我们的其他博客和 ML 监控上的资源!如果您有兴趣加入一个有趣的 rockstar 工程团队,帮助模型成功生产,请随时联系我们,并在此找到我们的空缺职位!

用于生产的 ML 基础设施工具(第 1 部分)

原文:https://towardsdatascience.com/ml-infrastructure-tools-for-production-1b1871eecafb?source=collection_archive---------14-----------------------

生产 ML——模型工作流程的最后阶段

作者的 ML 基础设施平台图

几乎每个行业的企业都在采用机器学习(ML)。许多企业都在期待 ML 基础设施平台,以推动他们在业务中利用人工智能的运动。了解各种平台和产品可能是一项挑战。ML 基础设施空间拥挤、混乱且复杂。有许多平台和工具跨越模型构建工作流程中的各种功能。

为了理解生态系统,我们将机器学习工作流大致分为三个阶段——数据准备、模型构建和生产。了解工作流程每个阶段的目标和挑战有助于做出明智的决策,确定哪些 ML 基础设施平台最适合您的业务需求。

作者的 ML 基础设施平台图

机器学习工作流程的每个阶段(数据准备、模型构建和生产)都有许多垂直功能。一些平台涵盖整个 ML 工作流程的功能,而其他平台则专注于单个功能(例如:实验跟踪或超参数调整)。

在我们的上一篇文章中,我们深入探讨了 ML 工作流的数据准备和模型构建部分。在本帖中,我们将更深入地探讨生产。

什么是生产?

将一个模型投入生产,感觉就像跑完一场马拉松后穿过终点线。在大多数现实环境中,准备数据、模型训练以及最终完成研究过程可能需要很长时间。然后是将模型投入生产的艰难过程,这可能涉及复杂的部署管道和服务基础设施。将模型投入生产的最后阶段包括检查模型是否准备好投入生产,打包模型进行部署,将模型部署到服务环境中,以及在生产中监控模型 &数据。

到目前为止,生产环境是模型生命周期中最重要的,也是最少被讨论的部分。这是模型接触业务的地方。这是模型做出的决策实际上改善了结果或给客户带来了问题的地方。数据科学家花费大部分时间和精力的训练环境仅由模型在真实世界中看到的样本组成。

从研究到生产

机器学习操作化的一个独特挑战是从研究环境到真正的生产工程环境的移动。Jupyter 笔记本,最常见的模型开发之家,表面上是一个研究环境。在一个控制良好的软件开发环境中,工程师拥有版本控制、测试覆盖分析、集成测试、在代码签入时运行的测试、代码评审和可再现性。虽然有许多解决方案试图将软件工程工作流程的片段引入 Jupyter 笔记本电脑,但这些笔记本电脑首先是一个为快速灵活的实验而设计的研究环境。此外,并非所有数据科学家都是软件工程师,而是拥有跨越多个领域的背景,如化学工程、物理学家和统计学家,这是生产 ML 的核心问题之一:

生产 ML 中的核心挑战是将一个模型从研究环境提升到软件工程环境同时仍然交付研究的结果。****

在这篇博文中,我们将强调将研究提升到具有一致性、可再现性和可观察性的产品所需的核心领域,这是我们对软件工程的期望。

模型验证

注意:模型验证是而不是,以免与验证数据集混淆。

快速回顾数据集:模型是使用多个数据集构建和评估的。训练数据集用于拟合模型的参数。验证数据集用于在调整超参数时评估模型。测试集用于评估最终模型的无偏性能,通过提供一个未用于调整超参数或以任何方式用于训练的数据集。

什么是模型验证?

您是一名数据科学家,您已经在测试集上构建了一个性能良好的模型,可以满足您的业务目标。现在,你如何验证你的模型将在生产环境中工作

模型验证对于交付可在生产中工作的模型至关重要。模型不是线性代码。它们基于历史训练数据构建,部署在依赖实时输入数据的复杂系统中。模型验证的目标是测试模型假设,并展示模型在大量不同环境下的工作情况。这些模型验证结果应该被保存并引用,以便在生产环境中部署时比较模型性能。

模型可以以各种不同的方式部署到生产环境中,从研究到生产的转换可能会在许多地方引入错误。在某些情况下,将一个模型从研究阶段迁移到生产阶段可能会涉及到将基于 Python 的 Jupyter notebook 翻译成 Java 生产代码。虽然我们将在下一节中深入讨论模型存储、部署和服务,但需要注意的是,一些操作化方法会带来额外的风险,即研究结果与生产结果不匹配。Algorithmia、SageMaker、Databricks 和 Anyscale 等平台正在构建平台,试图让研究代码直接转移到生产中,而无需重写代码。

在软件开发生命周期中,单元测试、集成测试、基准测试、构建检查等有助于确保软件在部署到生产环境中之前经过不同的输入和验证。在模型开发生命周期中,模型验证是在模型投入生产之前运行的一组通用且可重复的测试。

工业中模型验证的现状

如今,模型验证在行业中的机器学习团队中各不相同。在监管较少的用例/行业或不太成熟的数据科学组织中,模型验证流程只涉及构建模型的数据科学家。数据科学家可能会向更广泛的团队提交他们在 Jupyter 笔记本上构建的模型的代码评审。团队中的另一名数据科学家可能会发现任何建模问题。此外,模型测试可能由一组非常简单的保持测试组成,这些测试是模型开发过程的一部分。

更成熟的机器学习团队已经建立了大量的测试,这些测试既可以在代码签入时运行,也可以在模型部署之前运行。这些测试可能包括功能检查、数据质量检查、切片模型性能、模型压力测试和回溯测试。在回测的情况下,生产就绪模型被提供以前的历史生产数据,理想情况下在一大组看不见的数据点上测试模型。

在金融科技和银行业等受监管行业,验证过程可能非常复杂,甚至可能比实际的模型构建过程还要长。模型风险管理有独立的团队,专注于评估模型及其输出的风险。模型验证是一个独立的团队,它的工作是打破模型。这是一个内部审计功能,旨在强调和发现模型崩溃的情况。与软件工程世界平行的是 QA 团队和代码审查过程。

模型验证检查

不管是什么行业,在将模型部署到生产环境中之前,都需要做一些检查。这些检查包括(但不限于):

  • 整体和部分的模型评估测试(准确性、RMSE 等)
  • 预测分布检查将模型输出与以前的版本进行比较
  • 特性分布检查将非常重要的特性与以前的测试进行比较
  • 特征重要性分析,用于比较模型用于决策的特征变化
  • 对随机和极端输入噪声的灵敏度分析
  • 模型压力测试
  • 偏见和歧视
  • 标注错误和要素质量检查
  • 数据泄漏检查(包括时间旅行)
  • 过度装配和装配不足检查
  • 对历史数据进行回溯测试,以比较和基准测试性能
  • 特性管道测试,确保研究和生产之间没有特性中断

侧重于模型验证的 ML 基础设施工具提供了执行这些检查或分析来自检查的数据的能力——以可重复和可再现的方式。它们使组织能够减少操作模型的时间,并像交付软件一样自信地交付模型。

支持模型验证的 ML 基础设施平台示例:Arize AI、SAS(金融)、其他创业公司

模型合规性和审计

在监管最严格的行业中,可能会有一个额外的合规和审计阶段,由内部审计师甚至外部审计师对模型进行审查。ML 基础设施工具关注于法规遵循和审计团队,通常关注于维护模型清单、模型批准和围绕模型的文档。他们与模型治理一起工作,执行关于谁有权访问什么模型、模型必须通过哪一层验证以及在整个组织中调整激励的策略。

ML 基础设施示例:SAS 模型验证解决方案

连续交货

在设置为持续交付和持续集成的组织中,在以下情况下运行上述验证检查的子集:

  • 代码被检入—持续集成
  • 一个新的模型已经准备好生产-连续交付

持续集成测试可以在代码签入时运行,通常更像单元测试。当模型准备好投入生产时,通常会运行一组更大的验证测试,这些测试范围更广,可能包括回溯测试。随着团队试图根据模型漂移度量不断地进行再培训或者自动再培训,模型的持续交付验证变得更加重要。

许多工具,比如 ML Flow,支持与 CI/CD 测试和记录工件集成的模型管理工作流。这些工具集成到 GitHub 中,以支持提取/存储正确的模型,并存储由 Github 操作启动的结果。

支持连续交付的 ML 基础设施平台示例:数据块、ML 流、CML

下一个

关于人工智能的可操作性,我们将深入探讨许多讨论不足且极其重要的话题!接下来,我们将继续深入生产 ML,并讨论模型部署、模型服务和模型可观察性。

联系我们

如果这个博客引起了你的注意,并且你渴望了解更多关于机器学习可观察性和模型监控,请查看我们其他的博客和 ML 监控上的资源!如果您有兴趣加入一个有趣的 rockstar 工程团队,帮助模型成功生产,请随时联系我们,并在此处找到我们的空缺职位!

ML 生产基础设施工具

原文:https://towardsdatascience.com/ml-infrastructure-tools-for-production-part-2-model-deployment-and-serving-fcfc75c4a362?source=collection_archive---------10-----------------------

第 2 部分—模型部署和服务

作者图片(阿里泽·艾)

几乎每个行业的企业都在采用机器学习(ML)技术。企业期待 ML 基础设施平台帮助他们最好地利用人工智能(AI)。

了解各种平台和产品可能是一项挑战。ML 基础设施空间拥挤、混乱且复杂。有许多平台和工具,它们在模型构建工作流程中各有各种功能。

为了理解 ML 基础设施生态系统,我们可以将机器学习工作流大致分为三个阶段——数据准备、模型建立和生产。数据准备是指处理和扩充数据以供模型使用,而模型构建是指基于数据构建模型,生产将模型预测集成到业务中。

了解工作流程每个阶段的目标和挑战可以帮助您做出最明智的决策,确定最适合您业务需求的 ML 基础架构平台。

按作者列出的 ML 工作流阶段图

机器学习工作流程的每个阶段(数据准备、模型构建和生产)都有许多垂直功能。一些平台涵盖了 ML 工作流程中的所有三项功能,而其他平台则侧重于单一功能(例如,实验跟踪或超参数调整)。

在我们之前的文章中,我们研究了 ML 工作流的数据准备和模型构建部分。我们开始深入生产 ML,并详细讨论了模型验证。在这篇文章中,我们将更深入地研究生产,并关注模型部署和服务。

模型部署和服务

一旦模型被训练、构建和验证,最后就是部署和服务模型的时候了!在 ML 的最后一步中,前面步骤的所有工作最终被数据驱动的模型所使用。

团队需要做出的第一个决定是他们是否应该构建一个模型服务器。过去五年中部署的大多数模型都是自制的服务方法。然而,最近几年,使用 ML 模型的公司已经不再从零开始构建一切。事实上,考虑到上市的模型服务器的数量,我们预测从头构建一切的方法将会发生巨大的变化。

模型的模型服务选项通常分为几种不同的类型:

  • 内部构建的可执行文件(PKL 文件/Java) —容器化和非容器化
  • 云 ML 提供商——亚马逊 SageMaker、Azure ML、谷歌 AI
  • 批处理或流:托管和本地— Algorithmia、Spark/Databricks、Paperspace
  • 开源——tensor flow Serving、Kubeflow、Seldon、Anyscale 等。

对于给定的团队来说,哪一个是正确的选择?在决定模型服务选项时有许多考虑因素。以下是团队问自己的几个问题,以确定哪一个是最适合他们的 ML 选项:

要考虑的关键问题

  1. 组织的数据安全要求是什么?

对数据安全性有严格要求的组织可能需要内部 ML 解决方案。一些不错的选择是 Algorithmia、Seldon、Tensorflow、 Kubeflow、或自制的专有解决方案。一些提供商(如 Algorithmia)具有下文详述的安全特定功能集。对于那些不太需要安全性但需要更多远程访问/虚拟化的组织来说,云解决方案可能是更好的选择。

2。团队需要模型服务的托管还是非托管解决方案?

诸如 Algorithmia、SageMaker、Google ML、Azure、Paperspace 之类的托管解决方案对于 IT 人员较少的公司来说是个好主意。Kubeflow、 Seldon、Tensorflow Serving、Anyscale 等非托管解决方案可能更适合更多的技术组织。

3。组织中的每个团队都将使用相同的部署选项吗?

即使一个团队选择了服务选项,整个组织也很少使用相同的服务方法。拥有像 ML-Flow 这样的通用模型管理平台仍然有助于弥合差距。

4。最终的模型是什么样的?是否已经建立了接口?

如果已经部署了一个模型,那么去掉模型服务系统并用一个新的模型服务器替换它可能没有意义。替换已经部署的模型的容易程度可能取决于所选择的模型服务器及其与其他系统、API 和特性管道的集成。

5。模型可执行文件在哪里?(例如,毫升流或 S3 桶)

易于集成到 ML-Flow 或模型存储系统是一个重要的考虑因素。

6。需要 GPU 推理吗?

基于性能需求对使用 GPU 服务器的预测可能会驱使您选择云提供商或内部部署的 Algorithmia

7。是否有单独的特征生成管道,或者它们是否集成到模型服务器中?

取决于你的特性管道部署在哪里,比方说,亚马逊网络服务(AWS),这可能会引导你使用 SageMaker。这可能是使用 SageMaker 的更常见原因之一,因为数据已经部署在 AWS 中。

部署详情

基于用于构建模型的框架,跨组织和项目的模型的格式可以不同。一些示例格式包括分类器的权重/参数的 pickle 图像、Tensorflow SavedModel 对象、Pytorch 模型、Keras 模型、XGBoost 模型、Apache TVM、MXNet、ONNX 运行时等。

实施

有许多方法可以实现 ML 模型。这些模型可以集成到更大系统的代码库中,作为微服务部署,甚至可以在设备上运行。如果模型是集成到一个更大的系统中的代码,那么模型的接口就是一个简单的函数调用。如果模型在它自己的服务/可执行文件或服务器中,它可以被看作是一个服务。这些服务有定义良好的 API 或接口来将输入传递给模型并获得响应。上面描述的模型服务器接受以上面的格式生成的经过训练的模型工件,并允许您将它部署到生成定义良好的 API 的容器化模型服务器。

集装箱化

现代的服务器方法是将模型可执行文件容器化,这样模型就有了一个通用的接口和一个通用的方法来支持它们。当部署时,模型从模型管理系统(例如 ML-Flow )中被提取到一个容器中。有许多方法可以实现这一点,要么为你的公司构建一个定制容器,使用开源解决方案,如 KubeFlow 或Seldon AI,要么使用常见的云提供商工具,如 AlgorithmiaSageMakerAzureGoogle AI

实时或批量模式

另一个需要考虑的重要部署问题是,是使用实时/在线模型还是批处理模型。在线模型用于需要即时预测并接受实时应用输入的情况。如果这不是一个要求,批量推断可能是合适的。

许多服务平台允许您构建单个模型,并具有不同的部署选项(批处理或实时)来支持两种类型的服务机制。

在模型服务器中需要寻找的东西

轻松扩展 :

随着应用程序预测量的增长,最初的单一服务器支持预测的方法很容易被淹没。模型服务器更有用的功能之一是能够简单地将服务器添加到预测服务中,而无需重新构建或生成大量额外的模型操作工作。

金丝雀 A/B 框架 :

canary A/B 框架允许开发人员向一小部分用户推出软件,以执行 A/B 测试,从而找出软件的哪些方面最有用,并为用户提供最佳功能。部署后,一些团队将 A/B(金丝雀)模型与生产模型并行运行,最初只预测新模型的一小部分流量。这是在将新模型部署到整个预测卷之前的一个简单测试。我们交谈过的许多团队都自行构建了他们自己的 A/B 测试框架。也就是说,一些模型服务器解决方案也支持开箱即用的简单 A/B 部署,例如,通过点击一个按钮来选择 B 模型的流量百分比。

合奏支持:

将多个模型放在同一个服务器上或者轻松连接模型之间的预测(推理)流的能力可能是一个重要的考虑因素。大多数情况下,模型响应会被最终应用程序所消耗,但是随着系统变得越来越复杂,一些模型的输出会成为另一个模型的输入。在快速预测响应的情况下,可能需要协同定位模型。

回落支持 :

当您将新模型部署到生产中时,您可能会发现性能急剧下降。在性能下降期间,拥有不同的模型(可能是以前的版本或非常简单的模型)的能力在这种情况下非常有用。

安全:

如果安全性对组织来说非常重要,那么一些平台已经有了非常成熟的安全特性集。这些涵盖了一系列安全需求,主要集中在:访问权限、应用程序安全、网络安全和内存安全。生产中的模型需要从系统中的某个地方获取数据/输入,并且需要生成其他系统使用的预测/输出。有权访问预测的应用程序可能无权访问输入数据。此外,如果应用程序在 Kubernetes 托管的模型中使用 Python 包,许多公司希望确保这些包不是公共包。最后,如果您在共享内存环境中运行,如 GPU,您将需要评估您在内存加密和访问方面的数据保护措施。一些平台,如 Algorithmia、拥有更为成熟的安全特性集,可为各种情况提供解决方案。

特征管道支持:

在容器化的解决方案中,输入到特征的转换可能驻留在容器本身中,或者可能有单独的特征转换管道。基础设施越大,输入到特征的转换就越有可能是一个管道或特征存储系统,对容器的输入进行预处理。

在服务层,也有一些新的平台,如 Tecton AI,这些平台专注于功能服务。全球功能库允许团队轻松地将功能管道直接部署到生产环境中——最大限度地减少功能管道错误,并允许团队利用跨公司的功能构建。

监控:

一些模型服务器支持基本的监控解决方案。一些服务器支持对服务基础设施、内存使用和其他操作方面的监控。我们的观点是,这种类型的原始模型操作监控和可视化对于模型横向扩展很重要,但不具有可观察性。我们显然是有偏见的,但是我们认为真正的模型可观测性实际上是一个独立的平台。

用于部署和服务的示例 ML 基础设施平台包括 Datarobot、H2O.ai、Sagemaker、Azure、Google Kubeflow、Tecton AI。

模型可观测性与模型监控

似乎任何人都可以进行监控——绿灯是好的,红灯是坏的。您可以设置警报,如果某个值低于某个水平,就会触发向员工发送电子邮件。

然而,如果是这样的话,亚马逊云手表就会杀死 Datadog。

这里的问题是——当你收到警报时,你会怎么做?

我们的观点是,监控解决方案和可观察性平台之间的区别在于无缝排除故障和找出问题的能力。在人工智能生态系统中,这些问题表现为将人工智能研究与工程联系起来的问题。该平台是自下而上地设计来解决问题的,还是在一些预先存在的图表上附加了一个警报系统?故障排除模型+现实世界中的数据是一个庞大而复杂的空间。这就是为什么可观测性平台被从头开始设计以帮助研究和工程团队共同解决这些问题。

为什么模型服务器不适合观察:

模型服务器没有正确的数据点来链接分析模型所需的复杂层。模型服务器缺少基本数据,例如训练数据、测试运行、预编码的热特征数据、真实/标签事件等等。在特征数据的情况下,对于我们工作过的许多较大的模型,用于故障排除的数据管道的插入点是与模型服务器非常不同的技术。最后,许多组织拥有的模型服务方法与生产中的模型一样多,他们不太可能转移到一台服务器上来管理所有的方法。当您拥有相互提供数据的混合模型,但是您想要一个内聚的图片时,会发生什么呢?

软件基础设施也是如此;您的基础设施可观察性解决方案并不依赖于基础设施本身。

下一个

我们希望您喜欢 ML 基础设施系列!接下来,我们将深入探讨生产人工智能。关于人工智能的可操作性,我们将深入探讨许多讨论不足且极其重要的话题!

联系我们

如果这个博客引起了你的注意,并且你渴望了解更多关于机器学习可观察性和模型监控,请查看我们其他的博客和 ML 监控上的资源!如果您有兴趣加入一个有趣的 rockstar 工程团队,帮助模型成功生产,请随时联系我们,并在此处找到我们的空缺职位!

ML,ML,谁是他们所有人的冠军?

原文:https://towardsdatascience.com/ml-ml-who-is-the-champion-of-them-all-1a4d253e86ad?source=collection_archive---------37-----------------------

使用机器学习预测停赛后的欧洲冠军联赛 2019/20 冠军

亚历克斯·莫托克在 Unsplash 上的照片

过去的几个月对包括我在内的数百万球迷来说一定不容易。作为皇马的铁杆球迷,我已经一遍又一遍地观看了罗纳尔多、劳尔的集锦,试图实现我最喜欢的一面却被新冠肺炎带去的兴奋。不过好消息是,足球又回来了:三周前,欧足联宣布,从四分之一决赛开始,欧洲冠军联赛(UCL)将于八月初回归,所有赛程都是单淘汰制,放出所有赛程抽签。这对我来说是一个好消息,因为几个月来我一直在想皇马将如何在曼彻斯特卷土重来,现在是见证的时候了。

然而,问题是,复出的可能性有多大?

所以在上周,我带着这个问题开始了一个机器学习项目,研究 UCL 比赛回来后会如何进行。在这个项目中,我研究了谁将最终成为潜在的冠军,谁可以被命名为“获胜的失败者”,最重要的是,皇家马德里可能会走多远。在文章的其余部分,我将展示我是如何独自从头到尾完成这个项目的,同时分享任何有趣的发现。

数据收集

我需要的数据是在长时间停赛前的比赛中产生的所有信息。因此,我在fbref.com用 Scrapy 收集了 2019/2020 UCL 的所有数据。这包括资格赛,小组赛,以及在二月和三月进行的几次淘汰赛。

装置/结果的截图(来源于作者)

一般来说,数据分为两类:一类是比赛中的球队名称及其最终得分(如上面的标题所示),另一类是关于球队的详细数据,这些数据分别来自守门员、射门、控球等几个方面。老实说,我当时不知道我收集的所有数据是否会被使用,但我只是把它们都保留下来,以避免再次上网。我将在下一节讲述我是如何决定应该使用哪些特性的。

传递数据(来源于作者)

拍摄数据(来源于作者)

数据清理和预处理

所以我的下一步是使用收集的数据配置熊猫数据框架。如上所述,不确定是否应该利用数据集的所有功能。它们中的一些只是一种性质,但被描述成集合形式和平均形式。例如,Gls 和 Gls/90 分别代表总目标和平均目标。因此,我只是提取了反映球队平均表现的特征,下图说明了我保留的特征:

其余专栏(来源于作者)

尽管这种特征选择不能 100%消除多重线性。也许在一些剩余的特征之间,即使它们有不同的名称,它们也是高度相互依赖的。这可以通过绘制特征之间的关联热图来揭示:

所选功能的热图(来源于作者)

显然,存在着一些很强的相关性。我的解决方案是通过先验成分分析进行降维。在执行 PCA 之前,我需要将 fixture 表与特征集合并,因为我假设匹配双方的数据是我的模型的输入。

至于先验成分的数量,我也进行了一点测试,结果是前 14 个先验成分已经能够解释 95%以上的信息。考虑到之前我们总共有超过 80 个输入变量,这是令人印象深刻的。

第一个先验成分的累积方差(来源于作者)

建模

我选择了四个模型进行比较:逻辑回归、XGBoosting、决策树、高斯混合模型。我使用均方根误差(RMSE)作为衡量标准,对它们进行了 5 次交叉验证,发现 XGBoosting 的表现优于任何其他同类产品。

四种模式在 RMSE 方面的比较(来源于作者)

现在我需要获得最佳的预测结果。为此,我使用贝叶斯优化调整了性能最佳的 XGBoosting 的参数。

贝叶斯优化(来源于作者)

优化把性能从 2.84 左右提升到了 2.74,现在剩下的就是预测未来游戏的结果了。

夹具支架(来源于作者)

在上图中,右半边的四支球队已经进入了四分之一决赛,而左边的球队本月还有第二回合的比赛。因此,括号中的数字表示双方在 16 强赛中的总得分,而括号外的数字表示他们在第二回合的得分。值得注意的是,非常奇怪的是,剩余比赛的所有结果都是主场 2: 1 客场,这在现实中几乎不会发生。这不会是一个准确的预测,一定有什么我错过了,需要修复。

改进

我花了一段时间重新思考整个过程,并注意到问题来自于数据的不平衡。足球是一种在一场比赛中不太可能有很多进球的运动。换句话说,一场多进球少的比赛往往会频繁发生。据我观察,不考虑主客场差异,1:1、2:1、2:0 是本赛季 UCL 迄今为止成绩表上最常见的比分。也就是说,一支球队在大多数比赛中最多只能进 2 个球。

匹配结果分布(来源于作者)

一局一方的比分分布(来源于作者)

然而,也存在一些比赛,如 4:4 和 7:2,尽管它们只发生过一次。这使得我的预测有偏差,因为模型被欺骗了,倾向于用最频繁的样本之一来标记游戏。

这个问题有两个解决方案:缩小数据集或过采样。切断数据集也会带走数据集中的部分信息,考虑到我的数据集规模很小,这绝对不是一个理想的选择。然后我只有一个选择。

我尝试了名为“ imlearn 的 python 包,因为 imlearn 没有启用多标签分类的过采样,所以我的替代方案是将 RandomOverSampling 应用于一场比赛的得分(一列),而不是双方得分的多少(两列)。这样,我将每场比赛的结果视为一个标签,并均等地填充其中的每一项。

过采样后的匹配结果分布(来源于作者)

现在我需要做的就是重复下面的步骤。

现在结果看起来不错!(来源于作者)

我需要控制的最后一个因素是分类模型的参数。根据我的观察,由贝叶斯优化调整的参数是不稳定的,这意味着它们在不同的优化中可能是不同的,因此由模型生成的预测也是不同的。为了有一个相对可靠的值,我通过运行整个预测超过 300 次来模拟比赛,以计算每一方赢得奖杯的可能性有多大。

上述模拟的结果如下图所示:

基于 XGBoosting 的逐轮概率

结论

总而言之,现在我可以回答我在开始这个项目时就想到的问题了:

  1. 曼城是最具统治力的球队,有超过 50%的机会赢得奖杯;巴黎圣日耳曼在排行榜上排名第二,这要归功于它相对容易的右半区。
  2. RB 莱比锡将是最有可能夺冠的失败者。此外,不要忘记那不勒斯:据估计,他们有 46%的机会进入四分之一决赛,22%的机会进入半决赛。所以小心了,梅西和莱万多夫斯基!
  3. 虽然我不愿意接受这一点,但我应该承认,皇马在曼彻斯特的回归就像是大联盟模式的不可能完成的任务:我们只有 0.33%的机会活过这一轮,实际上没有机会走得更远。

思想

这是一个完全由我自己完成的项目,当时我没有其他事情来消磨时间,所以我想一定有什么事情我没有更好地考虑。就我而言,在这个项目中有 3 个方面我应该做得更好:

  1. 数据的时效性。如果你足够仔细地阅读这篇文章,你一定记得我用来预测的仅仅是本赛季 UCL 的数据。然而,事情是这样的,UCL 的最后一场比赛已经是大约 5 个月前了,事情会在这 5 个月里发生变化。换句话说,我没有考虑最近的表现。仅以 Real 为例。众所周知,他们在小组赛和第一回合的比赛中表现不佳。城市。但自西甲重启以来,他们没有输过一场比赛(10 胜 1 平),获得国内冠军。鉴于如此激烈的表现,你仍然有信心瓜迪奥拉的球队会毫不留情地淘汰齐祖的球队吗?
  2. 拉断路器。当出现“平局”时,比如说,双方在单淘汰赛中得分相同,或者,他们在双淘汰赛中得分相同,客场进球相同,我不知道如何判断哪一方应该晋级。我所做的只是在它们之间随机选择一个。从我的立场来看,收集那些在以前的原因中延伸到加时赛甚至点球大战的比赛数据是解决这个问题的关键。
  3. 单个球员对比赛的影响。在整个项目中,我只考虑了团队的宏观表现,但从未考虑过他们的球员。忽视他们可能会怀疑预测模型的准确性:一些球员已经被转移,不再能够为他们以前的球队效力。例如,蒂莫·韦尔纳,这样一个危险的前锋为德国队 RB Leipzig 贡献了 6 个进球(包括助攻),而整个球队迄今为止总共只有 14 个进球。所以可以肯定地说,他转会切尔西肯定会带来奢华的数据,可能还有莱比锡的火力。

这就是我第一个关于 UCL 冠军预测的数据科学项目。多么奇妙的经历啊!如果你喜欢读故事,请给我一个掌声,点击关注按钮,这是你对我最大的鼓励。如果你对我的实现感兴趣,可以访问我的 Kaggle 内核,网址是https://www . ka ggle . com/anzhe Meng/19-20-UCL-champion-prediction。

最后,哈拉马德里和纳达马斯!

由曼努埃尔·诺鲍尔在 Unsplash 上拍摄的照片

ML Ops 挑战、解决方案和未来趋势

原文:https://towardsdatascience.com/ml-ops-challenges-solutions-and-future-trends-d2e59b74dc6b?source=collection_archive---------15-----------------------

我的 MLOps NYC 演讲摘要,主要的 AI/ML &数据挑战以及如何用新兴的开源技术解决它们

AI 和 ML 实践不再是研究机构或技术巨头的奢侈品,它们正在成为任何现代商业应用程序不可或缺的一部分。据分析师称,大多数组织未能成功交付基于人工智能的应用程序,并陷入了将数据科学模型(在样本或历史数据上进行测试)转化为处理现实世界和大规模数据的交互式应用程序的过程中。

一种称为 MLOps 的新工程实践应运而生,以应对这些挑战。顾名思义,它结合了 AI/ML 实践和 DevOps 实践,其目标是创建数据和 ML 密集型应用程序的持续开发和交付(CI/CD)。

最近端到端数据科学平台提供商和开源 MLOps 技术开发商 Iguazio 与主要云提供商、领先企业和技术巨头一起举办了 MLOps NYC 活动。议程是讨论不同的方法、最佳实践,并开始为 MLOps 创建协作和标准化。

我的会议总结了 MLOps 当前面临的挑战以及我们将在不久的将来看到的趋势(参见 12 分钟的视频)。

挑战

根据不同的调查,数据科学团队不做数据科学,他们将大部分时间花在数据争论、数据准备、管理软件包和框架、配置基础设施以及集成各种组件上。这些任务可以概括为功能管理任务和 MLOps 任务(即 ML 的 DevOps)。

MLOps 挑战

数据科学起源于研究机构,后来被用于生成报告和检测堆积如山的数据中的异常。为了在事件和数据发生时智能地做出反应,将数据科学融入每个商业应用的新兴趋势正在机器学习实践中产生根本性的变化。

与研究或事后数据分析不同,业务应用程序需要能够处理实时和不断变化的数据,它们必须全天候运行,必须满足适当的响应时间,支持大量用户,等等。曾经的目标——生产一个 ML 模型——今天只是将数据科学引入生产的漫长过程中的第一步(如下图所示)。许多组织低估了将机器学习整合到生产应用程序中所需的工作量。这导致整个项目半途而废(75%的数据科学项目从未投入生产)或消耗比最初预期多得多的资源和时间。

数据挑战

数据科学家从样本数据开始,他们在 Jupyter 笔记本上工作或使用 AutoML 工具来识别模式和训练模型。在某一点上,他们需要在更大的数据集上训练模型。这是事情开始变得困难的时候。他们可能会发现,大多数处理 CSV 文件并将数据加载到内存中的工具都无法大规模工作,他们需要重新设计一切以适应分布式平台和结构化数据库。

许多时间花费在从原始数据创建特征上,并且在许多情况下,相同的特征提取工作为多个项目或者由不同的团队重复进行。每当数据集发生变化、导出的数据和模型发生变化,或者需要重复实验以获得所需的精度时,开销就会进一步放大。

当数据科学团队尝试将模型部署到生产中时,他们发现真实世界的数据是不同的,并且他们不能对总是在变化的数据使用相同的数据准备方法。延迟或计算能力限制需要一个完全不同的数据管道,它依赖于流处理、快速键/值和时间序列数据库来提供实时特征向量。

在纽约 MLOps 大会上,优步、推特和网飞讨论并分享了他们构建在线和离线特征库的经验,这是他们数据科学平台的基本组成部分。

解决方案和未来趋势

在我的会议中,我概述了行业的愿景,以克服上述挑战。解决这些挑战的方法是:

  1. 从第一天起就使用可扩展和生产就绪的数据科学平台和实践。
  2. 尽可能采用自动化和更高层次的抽象。
  3. 为协作和重用而设计。

无服务器 ML 函数

我们消除 ML 管道复杂性的方法是采用无服务器“ML 函数”的概念。无服务器技术允许您编写代码和规范,这些代码和规范会自动转换为自动扩展的生产工作负载。直到最近,这些还仅限于无状态和事件驱动程序工作负载,但现在有了我们展示的新的开源技术(MLRun+Nuclio+KubeFlow) ,无服务器功能可以应对实时、超大规模数据分析和机器学习的更大挑战。

打包、扩展、调整、检测和连续交付的步骤是完全自动化的,解决了每个组织的两个主要挑战:

  1. 显著缩短上市时间
  2. 尽可能减少完成项目所需的资源和技能水平

ML 函数可以很容易地链接起来产生 ML 管道(使用 KubeFlow )。它们可以生成后续阶段将使用的数据和特征。下图演示了用于创建实时推荐引擎应用程序的管道:

过渡到微服务和函数式编程模型支持协作和代码重用。用户可以在不中断管道的情况下逐步扩展和调整功能,同时只消耗适量的 CPU、GPU 和内存资源。 Kubernetes 和 KubeFlow 在这个架构中扮演着核心角色,调度合适的资源,扩展工作负载,管理管道。

Iguazio 的首席架构师&联合创始人 Orit Nissan-Messing 在圣地亚哥举行的 KubeCon + CloudNativeCon 2019 上通过现场演示介绍了 Nuclio ML 功能和 MLRun 架构(观看她的视频以了解有关这一挑战和克服挑战的方法的更多信息)。

内置功能存储

第二个挑战是构建、管理和使用离线和在线功能的复杂性。优步、网飞等数字巨头都在内部建立了“特色商店”来克服这一问题。大多数组织负担不起或者不具备从零开始构建功能存储的技能,并且需要它成为他们使用的数据平台的一个组成部分。

我们可以使用连接到共享在线+离线数据存储库的 ML 函数构建特征库,并使用元数据管理和自动化对其进行包装,如下图所示。

摘要

计划将 ML 和 AI 纳入其应用程序的组织必须以最终目标为出发点,并通过采用 MLOps(即持续集成和部署(CI/CD)和 DevOps 实践)为其数据科学活动构建生产,这样他们可以获得敏捷性,并可以服务于现实世界的在线应用程序。

如果没有适当的抽象和自动化,MLOps 和 data op 可能会消耗资源并导致重大延迟,这些挑战将导致数据科学优化的“无服务器”、SaaS 产品、ML 功能市场和托管功能商店的兴起。

押注正确的技术非常重要,这种技术是开放的,使用 Kubernetes 及其庞大的生态系统,而不是特定于点或云的解决方案。

对于我的 12 分钟视频:

ML Ops:作为工程学科的机器学习

原文:https://towardsdatascience.com/ml-ops-machine-learning-as-an-engineering-discipline-b86ca4874a3f?source=collection_archive---------1-----------------------

随着 ML 从研究到应用商业解决方案的成熟,我们是否需要提高其运作过程的成熟度

所以,你的公司决定投资机器学习。你有一个才华横溢的数据科学家团队,他们制作模型来解决几年前还无法解决的重要问题。所有的性能指标看起来都很棒,演示让人们惊讶不已,高管们问你多久能有一个模型投入生产。

你认为应该很快。毕竟,你已经解决了所有的高级科学、数学问题,所以剩下的就是例行的 IT 工作了。能有多难?

很难,事实证明。Deeplearning.ai 报告称“只有 22%使用机器学习的公司成功部署了一个模型”。是什么让它如此艰难?我们需要做些什么来改善这种情况?

我们先来看一下根本原因。

挑战

在传统软件开发的世界中,一套被称为 DevOps 的实践已经使得在几分钟内将软件交付生产并保持其可靠运行成为可能。DevOps 依靠工具、自动化和工作流来抽象掉意外的复杂性,让开发人员专注于需要解决的实际问题。这种方法如此成功,以至于许多公司已经驾轻就熟,那么我们为什么不能简单地继续为 ML 做同样的事情呢?

根本原因是 ML 和传统软件有一个根本的区别: ML 不仅仅是代码,它是代码加数据。ML 模型,即您最终投入生产的工件,是通过将算法应用于大量训练数据而创建的,这将影响模型在生产中的行为。至关重要的是,模型的行为还取决于它将在预测时接收的输入数据,而这是您无法提前知道的。

ML =代码+数据

虽然代码是在受控的开发环境中精心制作的,但是数据来自于那个被称为“真实世界”的无穷无尽的熵源。它永远不会停止变化,你无法控制它将如何变化。思考它们之间关系的一个有用的方法是,将代码和数据视为生活在不同的平面上,它们共享时间维度,但在所有其他维度上是独立的。ML 过程的挑战是以可控的方式在这两个平面之间建立一座桥梁。

代码和数据独立发展。我们可以认为它们是具有共同时间维度的独立平面。

这种基本的脱节导致了几个重要的挑战,任何试图将 ML 模型成功投入生产的人都需要解决这些挑战,例如:

  • 缓慢、脆弱且不一致的部署
  • 缺乏再现性
  • 性能下降(培训服务偏差)

由于“数据”这个词在本文中已经使用了几次,您可能会想到另一个可以拯救我们的学科:数据工程。你可能是对的:数据工程确实提供了重要的工具和概念,对于解决生产中的 ML 难题是不可或缺的。为了破解它,我们需要结合来自 DevOps 和数据工程的实践,添加一些 ML 特有的实践。

因此,ML Ops 可以由这个交集来定义:

ML Ops 是机器学习、DevOps 和数据工程的交集

因此,我们可以将 ML Ops 定义如下:

ML Ops 是一套结合了机器学习、DevOps 和数据工程的实践,旨在可靠高效地在生产中部署和维护 ML 系统。

现在让我们更详细地看看这实际上意味着什么,通过检查可用于实现 ML Ops 目标的个体实践。

练习

混合团队

因为我们已经确定生产一个 ML 模型需要一系列的技能,这些技能目前被认为是独立的,为了成功,我们需要一个混合的团队,这些团队一起涵盖了所有的技能。当然,一个人可能在所有这些方面都足够优秀,在这种情况下,我们可以称那个人为全面的 ML 操作工程师。但现在最有可能的情况是,一个成功的团队应该包括一名数据科学家或 ML 工程师、一名 DevOps 工程师和一名数据工程师。

该团队的确切组成、组织和头衔可能会有所不同,但最重要的是要认识到,单靠一名数据科学家无法实现 ML Ops 的目标。即使一个组织包括所有必要的技能,如果他们不密切合作,它也不会成功。

另一个重要的变化是,数据科学家必须精通基本的软件工程技能,如代码模块化、重用、测试和版本控制;让一个模型在凌乱的笔记本上工作是不够的。这就是为什么许多公司都采用 ML 工程师的头衔,强调这些技能。在许多情况下,ML 工程师实际上正在执行 ML Ops 所需的许多活动。

ML 管道

数据工程的核心概念之一是数据管道。数据管道是应用于源和目标之间的数据的一系列转换。它们通常被定义为一个图,其中每个节点是一个转换,边代表依赖关系或执行顺序。有许多专门的工具可以帮助创建、管理和运行这些管道。数据管道也可以称为 ETL(提取、转换和加载)管道。

ML 模型总是需要某种类型的数据转换,这通常是通过脚本甚至笔记本中的单元格来实现的,这使得它们难以可靠地管理和运行。切换到适当的数据管道在代码重用、运行时可见性、管理和可伸缩性方面提供了许多优势。

由于 ML 训练也可以被认为是一种数据转换,所以很自然地将特定的 ML 步骤包含在数据管道本身中,将其变成一个 ML 管道。大多数模型需要两个版本的管道:一个用于培训,一个用于服务。这是因为,通常情况下,数据格式和访问它们的方式在每个时刻都有很大的不同,特别是对于实时请求的模型(与批量预测运行相反)。

Kubeflow 管道中 ML 管道的可视化表示

ML 管道是一个纯代码工件,独立于特定的数据实例。这意味着可以在源代码控制中跟踪它的版本,并通过常规的 CI/CD 管道自动化它的部署,这是 DevOps 的核心实践。这使我们能够以结构化和自动化的方式连接代码层和数据层:

ML 管道连接数据和代码以产生模型和预测

注意,有两个不同的 ML 管道:训练管道和服务管道。它们的共同点是,它们执行的数据转换需要产生相同格式的数据,但是它们的实现可能有很大的不同。例如,训练管道通常在包含所有特征的批处理文件上运行,而服务管道通常在线运行,并且仅接收请求中的部分特征,从数据库中检索其余部分。

然而,确保这两个管道的一致性是很重要的,因此应该尽可能地重用代码和数据。一些工具可以帮助实现这一目标,例如:

  • 像 TensorFlow Transform 这样的转换框架可以确保基于训练集统计数据的计算(如归一化的平均值和标准差)是一致的。
  • 要素存储是存储不属于预测请求的值的数据库,例如根据用户历史计算的要素。

模型和数据版本控制

为了具有再现性,一致的版本跟踪是必不可少的。在传统的软件世界中,版本控制代码就足够了,因为所有的行为都是由它定义的。在 ML 中,我们还需要跟踪模型版本,以及用于训练它的数据和一些元信息,如训练超参数。

模型和元数据可以在像 Git 这样的标准版本控制系统中进行跟踪,但是数据通常太大且易变,因此效率不高且不实用。避免将模型生命周期与代码生命周期捆绑在一起也很重要,因为模型训练经常在不同的时间表上进行。还需要对数据进行版本化,并将每个训练好的模型与所使用的代码、数据和超参数的确切版本联系起来。理想的解决方案是专门构建的工具,但是到目前为止,市场上还没有明确的共识,并且使用了许多方案,大多数基于文件/对象存储约定和元数据数据库。

模型验证

另一个标准的 DevOps 实践是测试自动化,通常以单元测试和集成测试的形式出现。通过这些测试是部署新版本的先决条件。拥有全面的自动化测试可以给团队很大的信心,大大加快生产部署的步伐。

ML 模型更难测试,因为没有模型给出 100%正确的结果。这意味着模型验证测试本质上必须是统计的,而不是二元的通过/失败状态。为了决定一个模型对于部署来说是否足够好,我们需要决定要跟踪的正确的度量以及它们的可接受值的阈值,通常是凭经验,并且经常通过与以前的模型或基准进行比较。

跟踪整个验证集的单一指标也是不够的。正如好的单元测试必须测试几个案例一样,模型验证需要针对数据的相关部分(称为切片)单独进行。例如,如果性别可以直接或间接地成为模型的相关特征,则跟踪男性、女性和其他性别的单独指标。否则,模型可能存在公平性问题,或者在重要部分表现不佳。

如果您设法以自动化和可靠的方式验证模型,以及 ML 管道的其余部分,如果对用例有意义,您甚至可以关闭循环并实现在线模型训练。

数据有效性

一个好的数据管道通常从验证输入数据开始。常见的验证包括文件格式和大小、列类型、空值和无效值。这些对于 ML 训练和预测都是必要的,否则你可能会以一个行为不端的模型结束,并挠头寻找原因。数据验证类似于代码域中的单元测试。

除了任何数据管道执行的基本验证之外,ML 管道还应该验证输入的高级统计属性。例如,如果某个要素的平均值或标准偏差在不同的训练数据集之间发生了很大的变化,则可能会影响训练模型及其预测。这可能是数据实际变化的反映,也可能是数据处理方式导致的异常,因此检查并排除可能污染模型的系统错误非常重要,必要时可以修复它们

TensorFlow 数据验证中的统计数据剖析示例

监视

监控生产系统对于保持其良好运行至关重要。对于 ML 系统,监控变得更加重要,因为它们的性能不仅取决于我们可以控制的因素,如基础设施和我们自己的软件,还取决于我们无法控制的数据。因此,除了监控标准指标,如延迟、流量、错误和饱和度,我们还需要监控模型预测性能。

监控模型性能的一个明显挑战是,我们通常没有经过验证的标签来比较我们的模型预测,因为模型是在新数据上工作的。在某些情况下,我们可能有一些间接的方法来评估模型的有效性,例如通过测量推荐模型的点击率。在其他情况下,我们可能不得不依赖于时间段之间的比较,例如,通过每小时计算正面分类的百分比,如果它偏离该时间的平均值超过百分之几,则发出警报。

就像在验证模型时一样,为了能够检测出影响特定部分的问题,跨部分(而不仅仅是全局)监控指标也很重要。

摘要

随着 ML 从研究走向应用商业解决方案的成熟,我们也需要提高其运作流程的成熟度。幸运的是,我们可以从 ML 之前的学科中扩展许多实践。

下表总结了 ML Ops 的主要实践,以及它们与 DevOps 和数据工程实践的关系:

这是一个全新的令人兴奋的学科,其工具和实践可能会快速发展。在 ML 中开发和应用生产技术肯定有很多机会。

参考

  • Kaz Sato——谷歌云上的 ML 运营最佳实践(Cloud Next’19)
  • Kaz Sato——什么是 ML Ops?面向 ML 的开发运维最佳实践(云计算下一个 2018 年)
  • kube flow——Kubernetes 的机器学习工具包
  • tensor flow Extended(TFX)——用于部署生产 ML 管道的端到端平台
  • 机器学习的规则:ML 工程的最佳实践

ML Privacy Meter——量化机器学习模型隐私风险的综合工具

原文:https://towardsdatascience.com/ml-privacy-meter-a-comprehensive-tool-for-privacy-attacks-on-your-ml-model-b4d3f2e05cb4?source=collection_archive---------52-----------------------

马库斯·斯皮斯克在 Unsplash 上的照片

由于计算能力的提高,以及训练模型的大量数据的可用性,深度学习越来越多地用于解决跨领域的问题。随着深度学习的日益普及,这些模型变得更加健壮、安全和隐私变得至关重要。

然而,研究表明,深度学习和机器学习模型在训练不当时,往往容易出现各种类型的隐私漏洞。其中一种攻击是成员推断攻击[1],攻击者试图推断某些数据是否是训练集的一部分。用于训练模型的数据通常取自真实世界的数据,例如用于图像分类问题的真实图像,或者用于医疗诊断应用的实际用户的病历。因此,泄漏此类数据的模型可能会威胁到数据集个体成员的隐私。

ML 隐私测量仪 [2]是一种分析机器学习模型如何容易受到成员推理攻击的工具。该工具在经过训练的目标模型上生成攻击,假设对模型进行黑盒或白盒访问,以获得攻击的推理准确性。白盒攻击可以利用目标模型参数的梯度、中间层输出或模型预测来推断输入的训练集成员资格,而黑盒攻击仅使用目标模型预测来识别成员资格[3]。通过生成推理模型来执行攻击,该推理模型使用可用于某些数据的目标模型组件,并返回该数据的训练集成员的概率。

安装工具

安装 ML Privacy Meter 的先决条件是 Python 3.6。和 TensorFlow 2.1。首先安装工具的依赖项,然后安装工具。

pip 安装-r 要求. txt
pip 安装-e .

攻击模型 该工具提供了攻击给定训练模型的方法。用户需要提供模型权重文件、用于训练模型的数据以及完整的数据集。

该工具假设用户有一个已经训练好的 Keras 模型,以及它的数据集和用于训练的数据集子集。数据文件的格式可以在“数据集/自述”文件中找到。keras 模型可以使用 Keras 的 keras.load_model()函数通过传递模型文件直接加载,也可以按照下面代码片段中给出的方式进行初始化,使用 Keras 的 load_weights()函数加载训练好的权重文件。

我们加载要分析的完整目标 Keras 模型及其参数和权重。

然后,我们通过提供完整的数据集和用于训练的数据集来创建攻击处理程序。攻击处理程序提取数据,并为攻击模型的训练集和测试集创建批次。

attack_data()函数中使用的参数是:

  • dataset_path:指向。txt 数据集文件。(项目的“数据集”目录中提供了下载和创建示例)
  • member_dataset_path:用于创建目标模型的 numpy 数据文件的路径。(项目的“数据集”目录中提供了下载和创建示例)
  • batch_size:训练推理模型时使用的批量大小
  • attack_percentage:用于训练推理模型的训练数据的百分比。
  • normalization : Boolean,如果数据需要规范化,则设置为 true。这将计算中值和标准偏差以标准化数据。这些值可能会被“tutorials/attack_alex.py”示例中给出的值覆盖。
  • input_shape:模型输入数据的形状

接下来,初始化 whitebox 类以生成推理模型组件。对于白盒攻击,用户可以提供他们想要利用的层的梯度,以及白盒攻击者可以访问的神经网络的其他参数。对于黑盒攻击,只有最终层的输出可用于攻击参数。
在下面的例子中,进行了白盒攻击,其利用了最后一层的梯度和模型的最后两层的输出。还使用了输出损耗值、实际标签的一键编码(参见下面的函数参数描述)。
最后,调用 train_attack()函数来执行实际的攻击,并生成结果。在此期间,根据给定的参数,要利用的模型组件用于训练攻击模型。

initialize()函数中使用的参数有:

  • target_train_model:用于训练攻击模型的目标分类模型
  • target_attack_model:用于评估攻击模型的目标分类模型
  • train _ datahandler:target_train_model的 data handler
  • 优化器:用于训练攻击模型的优化器操作。支持“sgd”、“adam”、“adadelta”、“adagrad”、“momentum”和“rmsprop”。
  • layers_to_exploit:中间输出将被利用的层索引的列表。对于黑盒攻击,这个值应该包含最后一层的索引。
  • gradients_to_exploit:将利用其梯度的层索引的列表。层索引取自模型中具有可训练参数的层。
  • exploit_loss:用于指定是否将利用目标模型的损失值的布尔值。
  • exploit_label:用于指定是否将利用独热编码标签的布尔值。
  • learning_rate:优化器的学习速率
  • 时期:训练攻击模型的时期数。

攻击执行后,可以在日志文件夹和控制台中查看攻击结果。

Alex net CIFAR-100 攻击的端到端示例

为了像 Nasr 等人[3]中那样执行攻击,使用了在 CIFAR-100 数据集上训练的 Alexnet 模型。可以在模型上执行白盒攻击,同时利用梯度、最终层输出、损失值和标签值。
首先,从[教程/模型](https://github.com/privacytrustlab/ml_privacy_meter/tree/master/tutorials)目录下载预训练的模型,并放在项目的根目录下。
解压 tutorials/models/Alex net _ pre trained . zip-d .

预训练的 CIFAR-100 Alexnet 模型(从 Pytorch 转换为 Keras)

注意:用户也可以训练自己的模型来攻击类似于 tutorials/alexnet.py 中的例子,然后执行脚本来下载所需的数据文件。这将下载数据集文件和训练集文件,并将其转换为工具所需的格式。
cd 数据集
chmod+x download _ cifar 100 . sh
。/download _ CIFS ar 100 . sh

然后,执行主攻击代码以获得结果。
python 教程/attack_alexnet.py

文件中的“attackobj”初始化 meminf 类和攻击配置。以下是可在功能中更改的一些配置示例。
注:根据 CIFAR-100 分布,代码明确设置了图像归一化的平均值和标准偏差。
1。白盒攻击-利用最终图层梯度、最终图层输出、损失值和标签值(默认)

attack obj = ml _ privacy _ meter . attack . meminf . initialize(
target _ train _ model = CMO dela,
target _ attack _ model = CMO dela,
train _ data handler = datahandlerA,
attack _ data handler = datahandler,ew
layers_to_exploit=[26],
gradients_to_exploit=[6],
device=None)

2.白盒攻击—利用最后两个模型层输出、损失值和标签值

attack obj = ml _ privacy _ meter . attack . meminf . initialize(
target _ train _ model = CMO dela,
target_attack_model=cmodelA,
train _ data handler = data handlera,
attack _ data handler = data handler,
layers_to_exploit=[22,26],
device=None)

2.黑盒攻击—利用最终层输出和标签值

attack obj = ml _ privacy _ meter . attack . meminf . initialize(
target _ train _ model = CMO dela,
target_attack_model=cmodelA,
train _ data handler = datahandlerA,
attack _ data handler = datahandler,
layers_to_exploit=[26],
exploit_loss=False,
device=None)

ML 隐私测量仪,可从https://github . com/privacytrustlab/ML _ Privacy _ Meter/tree/master/tutorials获得

参考文献

[1] Shokri,Reza 等,“针对机器学习模型的成员推理攻击” 2017 年 IEEE 安全与隐私(SP)研讨会。IEEE,2017。

[2] ML 隐私计:通过机器学习模型量化信息泄露的工具。在 https://github.com/privacytrustlab/ml_privacy_meter有售

[3]纳斯尔、肖克里和胡曼萨德。深度学习的综合隐私分析:2019 年 IEEE 安全与隐私研讨会上被动和主动白盒推理攻击下的独立和联合学习。

每个数据工程师都应该知道的 ML 编程技巧——第 2 部分

原文:https://towardsdatascience.com/ml-programming-hacks-that-every-data-engineer-should-know-part-2-61c0df0f215c?source=collection_archive---------44-----------------------

现实世界中的 DS

数据科学家和机器学习从业者的更广泛的备忘单。

Bermix 工作室在 Unsplash 拍摄的照片

这篇文章是下述文章的续篇。

[## 每个数据工程师都应该知道的 ML 编程技巧——第 1 部分

数据科学家和机器学习从业者的更广泛的备忘单。

towardsdatascience.com](/programming-hacks-that-every-data-engineer-should-know-part-1-fb7cd436c40)

在上面的帖子中,我提出了一些重要的编程要点,在执行机器学习实践时要知道并牢记在心,以使您的实现更快更有效。接下来我们会看到更多这样的黑客。让我们开始吧。

11.操作宽长数据帧:

转换宽到长数据和长到宽数据最有效的方法分别是 pandas.melt()和 pandas.pivot_table()函数。除了这些函数之外,您不需要其他任何东西来将长而宽的数据相互转换。

a.宽到长(融化)

>>> import pandas as pd
# create wide dataframe
>>> df_wide = pd.DataFrame(
...    {"student": ["Andy", "Bernie", "Cindy", "Deb"],
...     "school":  ["Z", "Y", "Z", "Y"],
...     "english": [66, 98, 61, 67],  # eng grades
...     "math":    [87, 48, 88, 47],  # math grades
...     "physics": [50, 30, 59, 54]   # physics grades
...    }
...  )
>>> df_wide
  student school  english  math  physics
0    Andy      Z       66    87       50
1  Bernie      Y       98    48       30
2   Cindy      Z       61    88       59
3     Deb      Y       67    47       54
**>>> df_wide.melt(id_vars=["student", "school"],
...               var_name="subject",  # rename
...               value_name="score")  # rename**
   student school  subject  score
0     Andy      Z  english     66
1   Bernie      Y  english     98
2    Cindy      Z  english     61
3      Deb      Y  english     67
4     Andy      Z     math     87
5   Bernie      Y     math     48
6    Cindy      Z     math     88
7      Deb      Y     math     47
8     Andy      Z  physics     50
9   Bernie      Y  physics     30
10   Cindy      Z  physics     59
11     Deb      Y  physics     54

b.长到宽(数据透视表)

>>> import pandas as pd
# create long dataframe
>>> df_long = pd.DataFrame({
...         "student":
...             ["Andy", "Bernie", "Cindy", "Deb",
...              "Andy", "Bernie", "Cindy", "Deb",
...              "Andy", "Bernie", "Cindy", "Deb"],
...         "school":
...             ["Z", "Y", "Z", "Y",
...              "Z", "Y", "Z", "Y",
...              "Z", "Y", "Z", "Y"],
...         "class":
...             ["english", "english", "english", "english",
...              "math", "math", "math", "math",
...              "physics", "physics", "physics", "physics"],
...         "grade":
...             [66, 98, 61, 67,
...              87, 48, 88, 47,
...              50, 30, 59, 54]
... })
>>> df_long
   student school    class  grade
0     Andy      Z  english     66
1   Bernie      Y  english     98
2    Cindy      Z  english     61
3      Deb      Y  english     67
4     Andy      Z     math     87
5   Bernie      Y     math     48
6    Cindy      Z     math     88
7      Deb      Y     math     47
8     Andy      Z  physics     50
9   Bernie      Y  physics     30
10   Cindy      Z  physics     59
11     Deb      Y  physics     54
**>>> df_long.pivot_table(index=["student", "school"], 
...                     columns='class', 
...                     values='grade')**
class           english  math  physics
student school                        
Andy    Z            66    87       50
Bernie  Y            98    48       30
Cindy   Z            61    88       59
Deb     Y            67    47       54

12.交叉制表:

当您需要总结数据时,交叉制表在汇总两个或更多因素并计算值的频率表中起着重要作用。它可以用 pandas.crosstab()函数来实现,该函数还允许在使用“normalize”参数打印输出时找到归一化的值。

>>> import numpy as np
>>> import pandas as pd
>>> p = np.array(["s1", "s1", "s1", "s1", "b1", "b1",
...               "b1", "b1", "s1", "s1", "s1"], dtype=object)
>>> q = np.array(["one", "one", "one", "two", "one", "one",
...               "one", "two", "two", "two", "one"], dtype=object)
>>> r = np.array(["x", "x", "y", "x", "x", "y",
...               "y", "x", "y", "y", "y"], dtype=object)
**>>> pd.crosstab(p, [q, r], rownames=['p'], colnames=['q', 'r'])**
q  one    two   
r    x  y   x  y
p               
b1   1  2   1  0
s1   2  2   1  2# get normalized output values
**>>> pd.crosstab(p, [q, r], rownames=['p'], colnames=['q', 'r'], normalize=True)**
q        one                 two          
r          x         y         x         y
p                                         
b1  0.090909  0.181818  0.090909  0.000000
s1  0.181818  0.181818  0.090909  0.181818

13.Jupyter 主题:

Python 中最好的库之一是 jupyterthemes,它允许您更改和控制大多数 ML 从业者使用的笔记本视图的样式。不同的主题,如黑暗模式、光明模式等。或者定制样式是大多数程序员的首选,它可以在 Jupyter 笔记本中使用 jupyterthemes 库来实现。

# pip install
$ pip install jupyterthemes# conda install
$ conda install -c conda-forge jupyterthemes# list available themes
$ jt -l
Available Themes:
   chesterish
   grade3
   gruvboxd
   gruvboxl
   monokai
   oceans16
   onedork
   solarizedd
   solarizedl# apply the theme
jt -t chesterish# reverse the theme
!jt -r

你可以在 https://github.com/dunovank/jupyter-themes 的 Github 上找到更多相关信息。

14.将分类变量转换为虚拟变量:

使用 pandas.get_dummies()函数,您可以直接将 DataFrame 中的分类特征转换为虚拟变量,并使用 drop_first=True 删除第一个冗余列。

>>> import pandas as pd
>>> df = pd.DataFrame({'A': ['a', 'b', 'a'], 'B': ['b', 'a', 'c'],
...                     'C': [1, 2, 3]})>>> df
   A  B  C
0  a  b  1
1  b  a  2
2  a  c  3**>>> pd.get_dummies(df[['A','B']])**
   A_a  A_b  B_a  B_b  B_c
0    1    0    0    1    0
1    0    1    1    0    0
2    1    0    0    0    1**>>> dummy = pd.get_dummies(df[['A','B']], drop_first=True)
>>> dummy**
   A_b  B_b  B_c
0    0    1    0
1    1    0    0
2    0    0    1# concat dummy features to existing df **>>> df = pd.concat([df, dummy], axis=1)** >>> df
   A  B  C  A_b  B_b  B_c
0  a  b  1    0    1    0
1  b  a  2    1    0    0
2  a  c  3    0    0    1

15.转换成数字:

在将数据集加载到 pandas 中时,有时数值列被作为对象类型,并且不能在其上执行数值操作。为了将它们转换成数字,我们可以使用 pandas.to_numeric()函数并更新现有的系列或 DataFrame 中的列。

>>> import pandas as pd
>>> s = pd.Series(['1.0', '2', -3, '12', 5])
>>> s
0    1.0
1      2
2     -3
3     12
4      5
dtype: object**>>> pd.to_numeric(s)**
0     1.0
1     2.0
2    -3.0
3    12.0
4     5.0
**dtype: float64****>>> pd.to_numeric(s, downcast='signed')**
0     1
1     2
2    -3
3    12
4     5
**dtype: int8**

16.分层取样/分割:

当分割数据集时,我们有时需要在数据分割中获得样本总体。当数据集中的类不够平衡时,它会更有效。[**sklearn.model_selection**](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.model_selection)。train_test_split() 函数中,名为“分层”的参数可与目标类特征一起设置,以正确分割不同类的数据,其比率与未分割数据集中的比率相同。

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = **train_test_split**(X, y,
                                                    **stratify=y**, 
                                                    test_size=0.25)

17.按类型选择要素:

在大多数数据集中,我们有两种类型的列,即数值型和非数值型。我们经常需要只提取数据集中的数字列或分类列,并对其执行一些可视化功能或自定义操作。在 pandas 库中,我们有data frame . select _ dtypes()函数,它从给定的数据集中选择与指定数据类型匹配的特定列。

>>> import pandas as pd
>>> df = pd.DataFrame({'a': [1, 2] * 3,
...                     'b': [True, False] * 3,
...                     'c': [1.0, 2.0] * 3})
>>> df
   a      b    c
0  1   True  1.0
1  2  False  2.0
2  1   True  1.0
3  2  False  2.0
4  1   True  1.0
5  2  False  2.0**>>> df.select_dtypes(include='bool')**
       b
0   True
1  False
2   True
3  False
4   True
5  False**>>> df.select_dtypes(include=['float64'])**
     c
0  1.0
1  2.0
2  1.0
3  2.0
4  1.0
5  2.0**>>> df.select_dtypes(exclude=['int64'])**
       b    c
0   True  1.0
1  False  2.0
2   True  1.0
3  False  2.0
4   True  1.0
5  False  2.0

18.随机搜索 CV:

RandomizedSearchCV 是来自[sklearn.model_selection](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.model_selection)类的一个函数,用于确定上述学习算法的随机超参数集,它为每个提供的超参数随机选择不同的值,以对每个选择的值进行调整和应用交叉验证,并使用搜索时提供的不同评分机制确定其中的最佳值。

>>> from sklearn.datasets import load_iris
>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.model_selection import RandomizedSearchCV
>>> from scipy.stats import uniform
>>> iris = load_iris()
>>> logistic = LogisticRegression(solver='saga', tol=1e-2, 
...                               max_iter=300,random_state=12)
>>> distributions = dict(C=uniform(loc=0, scale=4),
...                      penalty=['l2', 'l1'])**>>> clf = RandomizedSearchCV(logistic, distributions, random_state=0)** >>> search = clf.fit(iris.data, iris.target)**>>> search.best_params_**
{'C': 2..., 'penalty': 'l1'}

19.神奇功能—%历史记录:

笔记本中的一批先前运行的命令可以使用“%history”神奇功能来访问。这将提供所有以前执行的命令,并且可以提供自定义选项来选择特定的历史命令,您可以使用“%history?”来检查这些命令在朱庇特笔记本里。

In [1]: import math

In [2]: math.sin(2)
Out[2]: 0.9092974268256817

In [3]: math.cos(2)
Out[3]: -0.4161468365471424In [16]: %**history** -n 1-3
   1: import math
   2: math.sin(2)
   3: math.cos(2)

20.下划线快捷键(_):

在 python 中,可以使用带下划线的 print(_)函数直接打印解释器最后发送的输出。这可能没什么帮助,但是在 IPython (jupyter notebook)中,这个特性已经被扩展了,您可以在 print()函数中使用 n 个下划线来打印任何 n 个最后的输出。例如,带有两个下划线的 print(__)将给出倒数第二个输出,跳过所有没有输出的命令。

另外,另一个是下划线,后跟行号,打印相关的输出。

In [1]: **import** **math**

In [2]: math.sin(2)
Out[2]: 0.9092974268256817

In [3]: math.cos(2)
Out[3]: -0.4161468365471424In [4]: **print**(_)
-0.4161468365471424

In [5]: **print**(__)
0.9092974268256817**In [6]: _2**
Out[13]: 0.9092974268256817

目前就这些。在接下来的几个部分中,我将介绍更多这些每个数据工程师都应该了解的重要技巧/功能。

敬请关注。

[## 是什么让逻辑回归成为一种分类算法?

对数优势,基线的逻辑回归解释。

towardsdatascience.com](/what-makes-logistic-regression-a-classification-algorithm-35018497b63f)

豪伊·R 在 Unsplash 上拍摄的照片

感谢阅读。你可以在这里找到我的其他机器学习相关的帖子。

希望这篇帖子有用。我感谢反馈和建设性的批评。如果你想谈论这篇文章或其他相关话题,你可以在这里或在 LinkedIn 给我发短信。

[## 线性回归中的假设你可能不知道。

模型应该符合这些假设,以产生与数据的最佳线性回归拟合。

towardsdatascience.com](/assumptions-in-linear-regression-528bb7b0495d)

数字分析师必备的 ML 技术第 1 部分:关联分析

原文:https://towardsdatascience.com/ml-techniques-to-optimise-digital-analytics-part-1-association-analysis-2ab198d56181?source=collection_archive---------40-----------------------

介绍可以帮助您优化数字分析价值链的机器学习技术

跨数字分析价值链的数据科学流程。作者图片

企业用户越来越倾向于自助进行基本的数字分析和报告。如果你是一名数字分析师,现在就开始扩展/转向数据科学将是一个明智的举动,并且能够提供比基本分析和仪表板更多的东西。

这是我学习、应用并最终分享这些数据科学技术知识的动机,在“数据科学”成为热门词汇之前,这些技术已经成为增量数据分析的一部分。

我的方法是解释这个概念和它所涵盖的用例。我将强调先决条件,并通过一个很好的例子来跟进。我的示例实现将用 r 编程。

在第 1 部分中,我将谈论关联分析更通俗地称为购物篮分析。这种分析与零售和其他设置相关,用户可以从购物车中添加并最终购买多种产品。目的是更好地了解什么样的产品或物品搭配得好,并利用这些信息进行更好的交叉销售、商品推销或有针对性的优惠。

关联:查找搭配在一起的项目

照片由大卫·维克斯列尔在 Unsplash 上拍摄

关联分析是一种统计技术,可以帮助您识别产品之间的顶级关联规则。

什么是关联规则?食品杂货交易的一个例子是,关联规则是{花生酱,果冻} => {面包}形式的建议。它说,根据交易,预计面包最有可能出现在包含花生酱和果冻的交易中。这是对零售商的建议,数据库中有足够的证据表明,购买花生酱和果冻的客户最有可能购买面包。

关联分析只是在数据中搜索其统计数据令人感兴趣的项目组合。它帮助我们建立规则,规定类似于“如果 A 发生,那么 B 也可能发生。”

但是,我们必须寻找的这些有趣的统计数据是什么,我们应该如何设置它们的值/阈值?

关联参数(有趣的统计!)

首先,我们需要考虑复杂性控制:可能会有大量的同时发生,其中许多可能只是由于偶然,而不是一个可概括的模式。控制复杂性的一个简单方法是设置一个约束,即这些规则必须应用于某个最小百分比的数据——假设我们要求规则至少应用于所有事务的 0.01%。这被称为协会的支持

我们在联想中也有“可能”的概念。如果顾客买了果冻,那么她可能会买面包。同样,我们可能希望为我们找到的关联要求某个最低程度的可能性。当 A 出现时 B 出现的概率;它是 p(B|A),在关联挖掘中被称为规则的置信度(不要与统计置信度混淆)。因此,我们可能会说,我们要求置信度高于某个阈值,比如 5%(这样,在 5%或更多的时间里,A 的买家也会购买 B)。

仅仅将支持和信心作为一个参数可能会误导篮子中过于常见/受欢迎的项目。更有可能的是,受欢迎的项目是同一个篮子的一部分,只是因为它们受欢迎,而不是其他任何东西。我们需要某种程度的“惊奇”来进行关联分析。升力和杠杆是提供这种情况的两个参数。A 和 B 共现的提升是我们实际上看到两者在一起的概率,相比之下,如果它们彼此无关(独立),我们会看到两者在一起的概率。就像我们看到的升力的其他用途一样,大于 1 的升力是看到 A 也“增加”看到 B 的可能性的因素。另一种方法是查看这些量之间的差异,而不是它们的比率。这个措施叫做杠杆

所以,对于交易中的任何 A 和 B 项

Support=p(A⋂B)

置信度=p(A|B)或 p(A⋂B)/p(A)

Lift(A,B)=p(A⋂B)/p(A)p(B)

Leverage(A,B)=p(A⋂B)−p(A)p(B)

作为一名购物篮分析师,你的工作是寻找提升值大于 1 的规则,这些规则有高置信度值支持,通常也有高支持度。

其他应用

因为我们在这一点上使用市场篮子作为类比,我们应该考虑拓宽我们对可能是一个项目的想法。为什么我们不能把任何我们可能感兴趣的东西放进我们的“篮子”里呢?例如,我们可以将用户的位置放入购物篮,然后我们可以看到购买行为和位置之间的关联。对于实际的购物篮数据,这些有时被称为虚拟商品,以区别于人们在商店放入购物篮的实际商品。关联分析发现并告诉我们具有统计意义的观察结果,如“如果 A 发生了,那么 B 也可能发生。”现在,我们可以替换 A 和 B 的任何东西,前提是它们发生在一起(可以被晒)。

根据上述逻辑,除了在线电子商务中的交叉销售机会,我们还有其他几个关联分析的应用。它可以帮助我们回答以下问题:

  • 篮子中的产品组合有哪些季节性或品牌因素?关联分析强调的产品组合可能因不同行业而异。例如,它可以是旅游运营商的出发地和目的地城市。
  • 对于在移动设备上购物的客户来说,产品组合是否有所不同?他们或多或少会购买哪些产品?

Apriori 算法

关联规则挖掘有几种算法实现。其中最关键的是 Rakesh Agrawal 和 Ramakrishnan Srikanth 的 apriori 算法,他们在论文中介绍了这种算法。

Apriori 算法是计算统计中一种常用的技术,它识别支持度大于预定义值(频率)的项集,并根据这些项集计算所有可能规则的可信度。

Apriori 算法在 arules 包中实现,可以在 r

处理

该算法将事务数据作为输入。交易是指顾客在零售店的一次购物。通常,交易数据可以包括购买的产品、购买的数量、价格、折扣(如果适用)和时间戳。一项交易可以包括多种产品。在某些情况下,它可以注册进行交易的用户的信息,其中客户允许零售商通过加入奖励计划来存储他的信息。对于挖掘,首先将交易数据转换为二进制购买关联矩阵,其中列对应于不同的项目,行对应于交易。矩阵条目表示特定交易中某个项目的存在(1)或不存在(0)。

示例实现

关联挖掘基于概率度量,因此从分析中生成可靠的见解通常需要大量的事务性数据。如果没有高度可扩展的存储和计算资源,大型数据集很难处理。通常,您将使用基于云的架构从您的数据湖中获取数据,但是内在的原则将保持不变,您的目标将是以事务格式获取数据以应用此规则。r 有连接到大多数系统的包,您甚至可以使用 SQL 进行数据交换。

让我们考虑下面的场景-

一家零售商正在策划一场大规模的营销活动来促进销售。他竞选的一个方面是交叉销售策略。交叉销售是向客户销售额外产品的做法。为了做到这一点,他想知道哪些物品/产品可以搭配在一起。有了这些信息,他现在可以设计他的交叉销售策略。他希望我们为他提供前 N 名产品协会的推荐,这样他就可以从中挑选并加入到他的活动中。

我们将实施一个项目,将关联规则挖掘应用于零售数据集,最终目标是推荐交叉销售商品。这个项目基于 Instacart 在 2017 年发布的一个数据集。他们发布了超过 300 万份匿名订单,供机器学习社区亲自尝试。我将使用子集训练数据集进行关联规则挖掘(假设我们的交叉销售用例)。我们将不得不进行一些初始的数据争论,以获得期望的事务格式。有关数据集的相关信息,请参考以下引文。

该项目的完整代码参见 github 。

这是代码的分解-

加载所需的库

**library**(dplyr)
**library**(arules)
**library**(arulesViz)

数据争论

我们提供了两个文件。一个订单 csv,包含约 131,000 个订单,带有订单 ID 和产品 ID 观察结果,以及一个带有产品 ID 和产品名称映射的产品文件。首先,我们将创建一个包含订单 ID 和相关产品名称的事务数据集。

*# Orders csv*
file1.path = "./order_products__train.csv"
orders = read.csv(file1.path)
head(orders)

作者图片

*# Products csv*
file2.path = "./products.csv"
products = read.csv(file2.path)
head(products)

作者图片

将两者结合起来,形成一个单一的交易数据集-

*# Combining both of them and forming a single transaction dataset -*
data = left_join(orders, products, by = "product_id") %>% select(order_id, product_name)
head(data,50)

作者图片

让我们快速浏览一下我们的数据。我们可以计算独特交易的数量和独特产品的数量:

*# We can count the number of unique transactions and the number of unique products*
data %>%
 group_by('order_id') %>%
 summarize(order.count = n_distinct(order_id))

作者图片

data %>%
 group_by('product_name') %>%
 summarize(product.count = n_distinct(product_name))

作者图片

我们有 131209 笔交易和 39123 个单个产品。没有关于交易中购买的产品数量的信息。我们使用 dplyr 库来执行这些聚合计算,这是一个用于在数据帧上执行高效数据辩论的库。

将其写回 csv

*# writing it back to csv*
write.table(data,file =  "./data.csv", row.names = FALSE, sep = ";", quote = FALSE)

关联规则挖掘

我们从读取存储在数据框中的事务开始,并创建一个名为 transactions 的 arules 数据结构。

*# create an arules data structure called transactions*
data.path = "./data.csv"
transactions.obj <- read.transactions(file = data.path, format = "single",
 sep = ";",
 header = TRUE,
 cols = c("order_id", "product_name"),
 rm.duplicates = FALSE,
 quote = "", skip = 0,
 encoding = "unknown")

查看用于创建 transactions 对象的函数 read.transactions 的参数。对于第一个参数 file,我们传递来自零售商的交易的文件。第二个参数 format 可以取两个值中的任意一个,single 或 basket,这取决于输入数据的组织方式。在我们的例子中,我们有一个包含两列的表格格式——一列代表我们事务的唯一标识符,另一列代表我们事务中存在的产品的唯一标识符。这种格式被 arules 命名为 single。有关所有参数的详细描述,请参考 arules 文档。

在检查新创建的事务对象 transaction.obj 时:

*# inspecting the newly created transactions object transaction.obj*
transactions.obj## transactions in sparse format with
##  131209 transactions (rows) and
##  39121 items (columns)

我们可以看到有 131209 笔交易,39121 个产品。它们与 dplyr 输出的先前计数值相匹配。

我们可以探索最频繁的项目,即出现在大多数事务中的项目,反之亦然——最不频繁的项目和出现在更少事务中的项目?

arules 包中的 itemFrequency 函数帮助了我们。此函数将交易对象作为输入,并生成各个产品的频率计数(包含此产品的交易数量):

data.frame(head(sort(itemFrequency(transactions.obj, type = "absolute"), decreasing = TRUE), 10)) *# Most frequent*

作者图片

data.frame(head(sort(itemFrequency(transactions.obj, type = "absolute"), decreasing = FALSE), 10)) *# Least frequent*

作者图片

在前面的代码中,我们使用 itemFrequency 函数打印了数据库中最常用和最不常用的项目。itemFrequency 函数生成所有项目及其相应的出现频率和事务数量。我们将排序函数包装在 itemFrequency 上来对输出进行排序;排序顺序由递减参数决定。当设置为 TRUE 时,它根据项目的事务频率按降序对项目进行排序。最后,我们使用 head 函数包装排序函数,以获得前 10 个最频繁/最不频繁的项目。

香蕉产品是 18726 笔交易中出现频率最高的。如果我们将 type 参数设置为 relative 而不是 absolute,itemFrequency 方法也可以返回事务的百分比,而不是绝对值。

这个项目的目的是关注方法而不是结果。如果你要参考数据集来源,数据集包括来自许多不同零售商的订单,是 Instacart 生产数据的严重偏向子集,因此不是他们的产品、用户或购买行为的代表性样本。

检查项目频率分布的另一个方便的方法是将它们直观地绘制成直方图。arules 包提供了 itemFrequencyPlot 函数来可视化项目频率:

*# itemFrequencyPlot function to visualize the item frequency*
itemFrequencyPlot(transactions.obj,topN = 25)

作者图片

项目频率图应该给我们一些关于我们应该保持的支持阈值的概念。通常,我们应该在长尾开始的地方选择一个支持阈值。

现在我们已经成功地创建了事务对象,让我们继续将 apriori 算法应用于这个事务对象。

apriori 算法分两个阶段工作。发现频繁项集是关联规则挖掘算法的第一步。一组产品 id 称为一个项目集。该算法多次进入数据库;在第一遍中,它找出所有单个项目的交易频率。这些是阶为 1 的项目集。我们将在这里介绍第一个利息衡量标准,Support。

现在,在第一遍中,算法计算每个产品的交易频率。在这个阶段,我们有 1 阶项目集。我们将丢弃所有低于支持阈值的项目集。这里的假设是,交易频率高的项目比交易频率非常低的项目更有趣。支持度非常低的项目不会在未来产生有趣的规则。使用最频繁的项目,我们可以将项目集构造为具有两个乘积,并找到它们的事务频率,即两个项目都存在的事务的数量。我们再次丢弃低于给定支持阈值的所有两个乘积项集(阶数为 2 的项集)。我们继续这种方式,直到我们用尽他们。

*# Interest Measures*
 support <- 0.005
*# Frequent item sets*
 parameters = list(
 support = support,
 minlen = 2, *# Minimal number of items per item set*
 maxlen = 10, *# Maximal number of items per item set*
 target = "frequent itemsets")
 freq.items <- apriori(transactions.obj, parameter = parameters)

作者图片

arules 使用 apriori 方法来获取最频繁的项目。这个方法有两个参数,一个是 transaction.obj,另一个是一个命名列表。我们创建一个名为 parameters 的命名列表。在命名列表中,我们有一个支持阈值条目。我们将支持阈值设置为 0.005,即交易的 1%。我们通过查看之前绘制的直方图确定了这个值。通过将目标参数的值设置为频繁项集,我们指定我们期望该方法返回最终的频繁项集。Minlen 和 maxlen 设置了我们期望在项目集中有多少项目的下限和上限。通过将我们的 minlen 设置为 2,我们说我们不想要阶数为 1 的项集。在第 1 阶段解释 apriori 时,我们说过该算法可以对数据库进行多次遍历,并且每次后续遍历都会创建阶为 1 的项集,大于前一次遍历。我们还说过,当找不到更高阶的项目集时,apriori 就结束了。我们不希望我们的方法运行到最后,因此通过使用 maxlen,我们说如果我们到达 10 阶的项目集,我们就停止。apriori 函数返回项集类型的对象。

检查创建的对象(在这种情况下是 itemset)是一种很好的做法。仔细观察 itemset 对象,应该可以了解我们最终是如何使用它的属性来创建项目集的数据框架的:

str(freq.items)

作者图片

通过调用函数 label 并传递 freq.items 对象,我们检索项目名称:

*# Let us examine our freq item sites*
 freq.items.df <- data.frame(item_set = labels(freq.items)
 , support = freq.items@quality)
head(freq.items.df,10)

作者图片

让我们进入第二阶段,我们将从这些项目集中归纳出规则。是时候引入我们的第二个兴趣指标了,信心。让我们从算法第一阶段给出的列表中选取一个项目集,{Banana,Blueberries}。

这里我们有两条可能的规则:

香蕉= >蓝莓:香蕉出现在一个事务中强烈表明蓝莓也会出现在同一个事务中。蓝莓= >香蕉:蓝莓出现在一个事务中强烈暗示香蕉也会出现在同一个事务中。在我们的数据库中,这两条规则被发现为真的几率有多大?我们的下一个兴趣指标——信心指数,将帮助我们衡量这一点:

confidence <- 0.2 *# Interest Measure*

 parameters = list(
 support = support,
 confidence = confidence,
 minlen = 2, *# Minimal number of items per item set*
 maxlen = 10, *# Maximal number of items per item set*
 target = "rules"
 )
rules <- apriori(transactions.obj, parameter = parameters)

作者图片

我们再次使用先验方法;但是,我们将参数命名列表中的目标参数设置为 rules。此外,我们还提供了一个置信度阈值。在使用返回的对象规则调用方法 apriori 之后,我们最终构建了我们的数据框架 rules.df,以便方便地浏览/查看我们的规则。让我们看看我们的输出数据帧 rules.df。对于给定的置信度阈值,我们可以看到算法抛出的规则集:

*# output data frame, rules.df*
rules.df <- data.frame(rules = labels(rules), rules@quality)
head(rules.df)

作者图片

Lift 也反映为数据框架中的另一个兴趣指标。

好了,我们已经成功地实现了我们的关联规则挖掘算法;我们深入了解了算法如何分两个阶段生成规则。我们已经研究了三个利益衡量标准:支持、信心和提升。最后,我们知道 lift 可以用来向我们的零售客户进行交叉销售推荐。

给定规则 A => B,我们解释了 lift 计算 A 和 B 一起出现的次数比预期的要多。还有其他方法来测试这种独立性,如卡方检验或费雪检验。arules 软件包提供了进行 Fisher 或卡方独立性检验的重要方法。根据我们希望执行的测试,参数方法可以采用 fisher 或 chisq 的值。

*# is.significant method to do a Fisher test of independence*
is.significant(rules, transactions.obj, method = "fisher")##  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [15] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [29] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [43] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

我们已经编写了一个名为 find.rules 的函数,该函数返回给定事务和支持度/置信度阈值的前 N 个规则的列表。我们对前 10 条规则感兴趣。我们将使用杠杆值进行推荐。

*# top N rules*
find.rules <- **function**(transactions,topN = 10){

 other.im <- interestMeasure(rules, transactions = transactions)

 rules.df <- cbind(rules.df, other.im[,c('conviction','leverage')])

 *# Keep the best rule based on the interest measure*
 best.rules.df <- head(rules.df[order(-rules.df$leverage),],topN)

 **return**(best.rules.df)
 }cross.sell.rules <- find.rules(transactions.obj)
cross.sell.rules$rules <- as.character(cross.sell.rules$rules)
cross.sell.rules

作者图片

前四个条目的提升值为 2 到 4,表明产品不是独立的。这些规则有大约 2%的支持度,系统对这些规则有 30%的置信度。但是等等,杠杆呢?这些项目有大约 1 个百分点的杠杆作用。无论是什么推动了这种同时出现,都会导致一起购买这两种商品的可能性增加一个百分点,超出我们的预期,仅仅因为它们是受欢迎的商品。这对于交叉销售决策来说足够了吗?也许是或不是...这是一个商业决定。

在这个例子中,我们建议零售商在交叉销售活动中使用这些顶级产品,因为考虑到 lift 值,如果顾客拿起一个{Organic Hass Avocado},他很可能会拿起一袋{Organic 香蕉}。

我们还包括了另一个利益衡量标准——信念。

定罪:定罪是确定规则方向的一种措施。与 lift 不同,定罪对规则方向很敏感。定罪(A => B)不同于定罪(B => A)。信念,以其方向感,给了我们一个暗示,将有机哈斯鳄梨的顾客作为交叉销售的目标,会产生更多的有机香蕉袋的销售,而不是相反。

想象规则

plot.graph 函数用于可视化我们根据杠杆值列出的规则。它在内部使用一个名为 igraph 的包来创建规则的图形表示:

**library**(igraph)*# visualize the rules*
plot.graph <- **function**(cross.sell.rules){
 edges <- unlist(lapply(cross.sell.rules['rules'], strsplit, split='=>'))

 g <- graph(edges = edges)
 plot(g)
}
plot.graph(cross.sell.rules)

作者图片

加权交易

在纯粹的使用中,arules 包使用项目集中项目的频率来度量支持度。我们可以通过明确地为不同的交易提供权重来取代这一点,然后可以取代支持措施。这样做可以允许我们在关联规则中硬编码某些产品,即使它们可能不频繁(通过给包含它们的事务分配更多的权重)。

在 arules 包中,weclat 方法允许我们使用加权事务来基于这些权重生成频繁项集。我们通过 str(transactions.obj)事务对象中的 itemsetinfo 数据帧引入权重。

如果显式权重不可用,我们可以使用一种叫做超链接诱导主题搜索(HITS)的算法来为我们生成一个。HITS 算法的基本思想是分配权重,使得具有许多项目的事务被认为比具有单个项目的事务更重要。

arules 包提供了方法(HITS)。例如,我们可以使用点击量生成权重,然后使用 weclat 方法进行加权关联规则…

*# The arules package provides the method (HITS)*
weights.vector <- hits( transactions.obj, type = "relative")
weights.df <- data.frame(transactionID = labels(weights.vector), weight = weights.vector)head(weights.df)

作者图片

引用

  • Instacart 在线杂货购物数据集 2017”,于 2020 年 3 月 9 日从https://www.instacart.com/datasets/grocery-shopping-2017访问

ML 时间序列预测的正确方法

原文:https://towardsdatascience.com/ml-time-series-forecasting-the-right-way-cbf3678845ff?source=collection_archive---------6-----------------------

用机器学习预测未来的端到端指南

作者 马里奥 & 洛伦佐

照片由 Aron 视觉效果在 Unsplash 上拍摄

介绍

将机器学习(ML)技术应用于时间序列预测并不简单。一个主要的挑战是在通常被称为预测中使用 ML 模型来实际预测未来。没有预测,时间序列分析就变得无关紧要。

这个问题源于数据的时间结构,因为与标准的 ML 项目不同,在新的数据点上应用预先训练的模型来获得预测是不够的,但是,正如我们将在本文中看到的,需要额外的步骤。****很少有使用 ML 在线进行时间序列预测的例子是真正端到端的,因为它们专注于在可用数据上测试模型,而忽略了预测部分。

这篇文章展示了一个完整的例子——从特征工程到使用不同策略预测未来——一个常见问题的例子,例如预测工厂内公用事业(例如变压器)的能耗。在开始之前,让我们简要地澄清一些术语。

时间序列分析

时间序列分析是一个广泛的领域,已被应用于许多不同的问题,从计量经济学到地震和天气预测。一般来说,时间序列方法可以根据预期结果分为两类:

  • ****时间序列预测:预测是时间序列分析中最常见的做法。给定一个时间序列,这些技术旨在使用一个计算模型预测具有一定置信区间的未来值。
  • ****时间序列分类:给定一个时间序列,这些技术旨在从时间序列中提取相关的聚集特征,以确定它是否属于某一类。时间序列分类的一个例子是分析 ECG 记录,以了解它们是取自健康患者还是患病患者。这些方法更类似于标准的 ML 分类。

这里,我们只处理时间序列预测。我们将我们的问题限制为预测一个单变量时间序列在未来执行多步预测

如果你想深入时间序列分析,以及如何针对你的具体问题选择合适的模型,可以参考这篇优秀的文章。

数据集

我们考虑的数据集包括从 2019 年 7 月到 2020 年 1 月的大约 7 个月期间,某工业公用事业单位的小时能源消耗率千瓦时。能量测量是从安装在意大利一家真实工厂中的传感器获得的。数据通过随机常数乘法匿名化。让我们绘制数据的不同视图。

数据集的不同视图。从上到下顺时针我们有原始时间序列,其值的分布,自相关和部分自相关函数。

在左上图中,我们看到了能耗随时间变化的原始行为。如图标题所示,扩展的 Dick-Fuller (ADF)检验的 p 值很好地表明时间序列是平稳的。

右上面板显示了能耗的数值分布。数据值似乎遵循缓慢衰减的泊松分布,其中高于 50 千瓦时的高值能耗比低值(10 至 40 千瓦时)更不可能。这是预期的行为,因为连续运行的工业设施的能源消耗通常具有相当恒定的平均值,由于产量增加或维护窗口而具有零星的峰值。

下图显示了自相关(ACF)和部分自相关(PACF)函数。参见此处了解更多关于它们对时间序列分析重要性的细节。ACF 显示,时间序列在 24 小时(灰色水平线)具有季节性成分,自相关峰值不随时间而降低,表明该成分的强度。PACF 证实了这一点。

基于 XGBoost 的机器学习预测

对于我们的预测问题,我们选择 XGBoost 算法,使用这个流行的 Python 实现。与其他基于树的 ML 方法相比,XGBoost 对于时间序列问题来说是快速而准确的,正如几个 Kaggle 竞赛和其他在线作品所示(例如,参见此处或此处)。

为了将时间序列预测任务转化为有监督的机器学习问题,我们需要生成特征。实际的时间序列值被用作 ML 模型的目标。我们可以将时间序列的特征类型分为 3 类:

  • 滞后特征**:它们利用原始时间序列本身作为具有一定偏移的特征,通常称为滞后。可以通过查看部分自相关函数的值来自动选择滞后。特别地,我们仅将 PACF 大于 0.2 的滞后作为特征,相当于滞后的 5%相关性。这里是创建这些功能的 Python 代码片段。

  • ****标准时间序列特性:标准时间序列特性,如小时、周末、季节等。使用一些关于数据的领域知识,我们还可以构建额外的时间序列特性,例如,在我们的例子中,每个时间戳的当前工人班次。

  • ****外生特征:外生特征本身就是时间序列,是外部的,即不依赖于要预测的时间序列。在我们的例子中,外部变量可能是外部温度。在这篇文章中,我们不考虑他们。

我们使用标准管道来训练和测试 XGBoost 模型,该模型具有 80/20 训练测试分割、滚动时间窗口交叉验证以及使用[hyperopt](https://hyperopt.github.io/hyperopt/)库的超参数优化。最佳模型在交叉验证中产生的平均百分比误差(MAPE)为 14.302,在小得多的测试集上预测时为 8.378。测试集上的预测值和主要特征的相应重要性系数如下所示。

XGBoost 模型对具有相应特征重要性直方图的测试进行预测。

用 ML 模型进行多步预测

ML 模型结果是可接受的,我们的工作就完成了。不完全是!我们在介绍中提到,从模型中获得满意的结果并不足以获得可操作的结果。类似于标准的监督 ML 问题,我们希望对未知数据点使用模型,在我们的情况下,未知数据点是未来时间段 : ,最终我们希望预测未来。预测未来的时间段数通常被称为预测范围

与标准最大似然模型不同,标准最大似然模型可以直接应用于新数据,时间序列问题的时间结构使得预测更加复杂。有几种策略可以实现多步预测,在这里可以找到对这些方法的很好的介绍。在这篇文章中,我们比较了两种最广泛使用的策略,并展示了它们在上面讨论的 ML 模型中的实现。我们选择 48 个时间段的预测范围,对应于提前 2 天预测

递归策略

递归预测策略仅使用为一步预测预训练的单个模型。在每个预测步骤中,该模型用于预测下一步,然后将从预测中获得的值输入到同一个模型中,以预测下一步(类似于递归函数,因此得名)等等,直到达到期望的预测范围。递归策略是最便宜的预测方法,因为它使用相同的模型。然而,从长期来看,这并不是最佳策略,因为它会在每一步累积预测误差。出现这个问题是因为先前的预测值被用于构建当前步骤的特征空间。

下面的代码片段实现了 ML 模型的递归策略。

直接战略

直接预测策略对每个预测步骤使用不同的 ML 模型。更具体地说,每个模型都是使用作为目标的时间序列来训练的,该时间序列被移动了期望数量的时间段到未来。例如,想象一个人想要训练一个提前 4 步的模型。在这种情况下,目标时间序列中的每个时间戳相对于特征集中的相应时间戳提前 4 步选择。通过这种方式,我们创建了一个经过训练的模型,用于预测未来的 4 个步骤。对所有预测步骤重复相同的程序。对于前面要执行的每个额外步骤,训练/交叉验证集的大小会稍微减小。

上面概述的直接方法不会在每次预测时产生误差累积,但它的计算成本较大,因此不适合大范围的预测。此外,它不能模拟预测之间的统计关系,因为每个时间步使用的模型是独立的。顺便说一下,后一个问题可以通过使用一个神经网络来解决,该网络被训练成一次输出多个预测-每个未来时间段一个-它也学习过程中的关系。

这里实施一个简单的直接预测我们的 ML 模型。

预测结果

最后,让我们来看看上述两种策略在预测未来方面的比较。我们将数据集的过去 48 小时视为未来,这样我们就有真实的数据来与预测进行比较。请注意,在现实世界的问题中,未来是无法预知的!

通过查看这两种方法的 MAPE 分数,直接方法比递归方法表现得更好,误差大约低 15%。

仅仅查看这些值不足以评估预测质量。让我们画出这两种预测。

对于这个相对较短的时间范围,两种策略在初始预测步骤中的表现相似。然而,大约 24 小时后,递归策略开始偏离直接策略。这很可能是由于误差累积开始影响递归方法的结果。误差累积也可能产生递归预报所显示的更强的波动。然而,直接策略所产生的改进并不显著,不足以证明其使用的合理性。在时间序列模型的生产部署中,通常最好使用不太精确的方法,这种方法需要更少的计算工作量,例如递归策略。

总之,请记住,目前的方法只是基本的预测策略。已经投入了大量的研究工作来设计更精确和可控的预测技术,其中一个例子就是这里所描述的修正策略。

如果你喜欢这篇文章,并且有任何意见、建议或批评,请联系我们(洛伦佐或马里奥)。这篇文章的完整代码可以在 Github 上找到。

机器学习工程师 vs 数据科学家(数据科学结束了吗?)

原文:https://towardsdatascience.com/mlevsds-3c89425baabb?source=collection_archive---------1-----------------------

vs 数据分析师 vs 研究科学家 vs 应用科学家 vs…

在 Metis,在给学生们做了我的演讲后(来源:我)。

你好,我是杰森

我是硅谷的一名数据科学家(我们将在本文后面详细介绍),我喜欢学习新东西!

介绍

伙计,这个话题在我脑子里藏了很久了。但是因为有太多的事情可能要涉及,我无法让自己完成这项艰巨的任务。但是,由于“原地避难”的顺序,我被困在房间里,没有东西可以浪费时间,我最终决定完成它。

自 2013 年以来,随着其受欢迎程度的爆炸式增长,数据科学行业已经发生了巨大的变化,但正在慢慢融合为更具体的角色。不可避免地,这在它的成长过程中造成了混乱和不一致的工作职能。例如,似乎有许多不同的职位具有完全相同的角色,或者相同的职位具有不同的角色:

分析数据科学家,机器学习数据科学家,数据科学工程师,数据分析师/科学家,机器学习工程师,应用科学家,机器学习科学家…

这样的例子不胜枚举。甚至对我来说,招聘人员也向我寻求数据科学家、机器学习(ML)专家、数据工程师等职位。显然,这个行业很困惑。差异如此之大的众多原因之一是公司对数据科学的需求和用途大相径庭。不管什么原因,数据科学领域似乎正在分支并合并成这几个顶级类别:分析软件工程、数据工程研究。不管类似的标题怎么说,通常都属于这几类。这种专业化在能够负担得起的大型科技公司中最为真实。

在本文中,我们将首先了解数据科学行业的整体趋势,然后更深入地比较 ML 工程师和数据科学家。我并不打算提供一个广泛的历史,而是叙述我作为一名数据科学家生活在硅谷时的所见所闻。甚至当我在 2017 年写我的文章 如何无学位的数据科学 的时候,我对数据科学的看法也是截然不同的。

去年,我应邀在 Metis boot camp 给数据科学学生做了一个简短的演讲,当时我谈到了这个话题。我想利用这个机会解释一下不同之处,帮你找到最适合你的角色。让我们看看这个行业是仍在蓬勃发展还是以数据告终,因为这是数据科学家的工作,对吗?(可能不会)。无论如何,我希望你会发现它有用和信息丰富。

数据科学产业趋势

在我们深入探讨之前,先看看我在 LinkedIn 上找到的以下两个职位描述。试着猜猜这些描述是为了什么标题。我用红色标出了一些要点:

这是我去年在 LinkedIn 上找到的。有点过时,但仍然正确(来源:LinkedIn 和脸书)。

很不一样,对吧?令人惊讶的是,这两个职位都是数据科学家。左边是脸书,右边是艾西。我并不是说一个比另一个好。主要的一点是看他们有多大的不同。

以上描述的职位名称。脸书(左)和 Etsy(右)(来源:LinkedIn 和脸书)。

即使在工作中,人们也在积极讨论如何定义数据科学家。我见过有人把数据科学家描述成计算机科学博士或者新数据分析师。这是因为不同的公司使用术语数据科学家表示非常不同的职位。然而,我相信这个行业一直在学习变得更具体,有更专业的角色,而不是将一切都归入数据科学的广阔范围。

那么,数据科学家可以暗示哪些不同的角色呢?很大程度上,我认为他们是软件工程师、数据分析师、数据工程师、应用/研究科学家。我见过我的朋友拥有相同的数据科学家头衔,但他们的角色是四个之一。看看我在下面创建的图表。在数据科学的早期,数据科学家可能包括所有这四种角色。然而,今天的职位正变得越来越具体和专业化,如下图所示。

数据科学家趋势(来源:我)。

《哈佛商业评论》预见到了吗?

这种趋势令人惊讶吗?根据著名文章 数据科学家:21 世纪最性感的工作 没那么多:

数据科学家最基本、最通用的技能是编写代码的能力。这可能在五年后就不那么真实了,那时会有更多的人在他们的名片上有“数据科学家”的头衔。

正如这篇文章所建议的,作为一名数据科学家,你没有多少理由成为一名优秀的程序员。以前,用于分析大而讨厌的数据的工具和方法不像以前那样容易访问和用户友好。这要求数据科学家在其他技能的基础上拥有相对较强的工程技能。但是用于 ML 和数据科学的工具发展很快,现在比以往任何时候都更容易访问,这样你只需要几行代码就可以访问最先进的(SOTA)模型。这使得将角色划分为分析或工程更容易。现在,我们不必像以前一样,为了成为数据科学家而专注于学习所有的分析、工程和统计。

例如,脸书引领了数据分析师职位向数据科学家转变的趋势。这是一个自然的过程,因为随着数据量的增加和更具挑战性的数据问题,需要更多的技能和培训来执行良好的分析。不仅是脸书,苹果、Airbnb 等许多其他公司也一直在明确区分分析/产品数据科学家和 ML 数据科学家。

公司规模如何影响角色

值得一提的是,专业化更多发生在大型科技公司。与各种规模的科技公司都需要软件工程师不同,并非所有这些公司都需要专业的研究科学家或 ML 工程师。有几个数据科学家可能就足够了。因此,在较小的公司中,仍然有数据科学家可能同时担任这四种角色。

今天的经验法则是,大公司的数据科学家(方)通常类似于高级分析师,而小公司的数据科学家更类似于 ML 工程师。这两个功能都很重要,也是必需的。展望未来,我将坚持我的新定义,即数据科学家意味着分析功能。

不同的数据科学家以及如何选择他们

在下面的图表中,我试图展示一个与上图相似的图片,但是对四个函数有更详细的描述。这些描述并不完美,但你可以参考一下。

DS 的四大支柱(来源:我)。

求职——选择哪个标题,如何准备?

如果你试图进入这个领域,无论是作为一名 ML 工程师还是数据科学家,你可能会想你应该选择哪一个。让我列出四个与 ML 相关的主要角色的简单(和刻板)描述来帮助你澄清。虽然我没有亲自担任过所有这些职位,但我从各个领域的朋友那里学到了一些真知灼见。我还在括号里提供了潜在的面试内容(就当是四轮面试吧)。

  1. 数据科学家:你想分析大数据,设计实验和 A/B 测试,建立简单的机器学习和统计模型(例如使用 sklearn)来驱动商业战略吗?这个角色不太结构化,有更多的不确定性,你将推动项目的叙述。(面试:1 个大概/统计,1 个 Leetcode,1 个 SQL,1 ML)。
  2. ML 工程师:您是否希望在生产中构建和部署最新的机器学习模型(例如 Tensorflow、PyTorch)?您的重点不仅仅是构建模型,而是运行和支持您的模型所需的软件。你更多的是一个软件工程师(SWE)。(面试:3 Leetcode,1 ML)。
  3. 研究科学家:你有计算机科学的博士学位,并且在 ICLR 有几份 ML 出版物吗?你想突破 ML 研究的界限吗?当你的论文被引用时,你会兴奋吗?这些是稀有品种,你已经知道你是谁。这些人中的大多数最后都去了谷歌或脸书。此外,没有博士学位也可以进入 it 行业,但不幸的是,这种情况很少见。(访谈:1 Leetcode,3ML/研究)。
  4. 应用科学家:你是 ML 工程师和研究科学家的混血儿。你关心代码,但也关心使用和推动最先进的(SOTA)机器学习模型。(面试:2 个 Leetcode,2 ML)。

显然,这些描述并不详尽。但是在和朋友聊天,看很多职位描述的时候,我发现这些想法很普遍。如果你不确定你要申请的职位,这里有一些小贴士可以帮助你了解更多:

  • 阅读职位描述:老实说,头衔并不重要。它可能被称为同一个“数据科学家”,但工作描述可能会大不相同。
  • LinkedIn 梗:如果你不确定苹果的数据科学家是什么样的,就简单翻翻苹果数据科学家在 LinkedIn 有什么样的背景。是不是大部分都是 CS 博士?本科生?他们有什么样的培训?这将有助于你获得更好的想法。
  • 面试:如果你认为你的角色是一个技术角色,但却没有参加编码面试,你可能不会得到一个技术角色。你的面试内容反映了工作性质。

ML 工程师 vs 数据科学家

(来源:我)

好吧,那很久了。现在回到我们的话题。近年来,我开始听到人们对数据科学工作的负面评价。有几个原因是,越来越多的数据科学家工作似乎不再有很酷的机器学习因素,似乎更容易获得。也许五年前,大多数职位描述要求至少有硕士学位才能获得数据科学家的工作,但现在不再是这样了。不管人们认为数据科学(至少是过去的)已经结束的原因是什么,让我们来看一些数据。

以下数据和图表来自全球知名的薪资数据库引擎薪资忍者。它搜索基于在美国的外国工人的 H1-B 数据库。你会看到 2014 年到 2019 年之间,职位名称中要么有“数据科学家”要么有“机器学习工程师”的职位的平均工资和数量。

比较数据科学家和 ML 工程师趋势(来源:Me)。

你对结果感到惊讶吗?尽管这两个职位的平均工资相似,但你可以看到数据科学家的平均工资在 2015 年和 2016 年有所下降。也许这就是人们所说的数据科学家的好日子结束了。从纯粹的数量上来说,数据科学比 ML 工程大很多,但是你可以看到 ML 工程师增长更快,薪水更高。

为了让你开心,我提供了一个汇总统计数据,是我从本文中讨论的几个角色的薪水忍者那里收集的。我做了过去六年的总体总结(第一张表)和 2019 年最近一年的子集(第二张表)。最后,我只包含了一个公司的表,微软(第三个表)。

少数 ml 相关岗位汇总统计(来源:我)。

我学到了一些有趣的见解:

  • 总体而言,数据分析师比数据科学家多,但这在 2019 年发生了逆转!这可能是数据分析师被更名为数据科学家的标志吗?
  • ML 工程师的薪酬略高于数据科学家,但该领域的 ML 工程师要少得多。这是因为 ML 工程师的官方头衔往往只是软件工程师
  • 研究科学家的平均水平低得惊人。我发现这是因为数据库可以包括许多其他类型的科学家,而不仅仅是那些从事技术 ML 研究的科学家。这就是为什么我只为一家科技公司提供了一张表格来减少这种噪音。不出所料,研究人员登上了微软薪酬最高的宝座。
  • 我对这位数据工程师 130 万美元的底薪感到惊讶。这太疯狂了。也许你应该考虑那个职业。
  • 请记住,这个数据集只包括基本工资,股票通常在技术领域发挥着巨大的作用。此外,它也没有描绘出就业市场的全貌。然而,考虑到我们在科技行业有多少外国工人,这应该仍然是一个很好的代表。

根据这些数据,我不能说数据科学行业已经破产。它仍在增长,但可能更侧重于分析。从我的观察来看,似乎确实有更多的数据科学工作需要更少的先决条件,但这不是一件坏事。

结论

我谈了很多事情,但我希望你和我在一起。我写这篇文章是因为我自己对这个行业正在发生的变化感到困惑。此外,人们似乎对什么是数据科学有很多不同的看法。不管谁对谁错,希望你能看清趋势,自己决定。

最后,不要因为一份工作或一个行业的平均工资更高,或者因为一些流行词汇而选择它。不管你的头衔是数据科学家、ML 工程师还是数据分析师。如果有人说数据科学家是工程师或分析师并不重要,因为两者都可能是真的。

虽然根据薪酬来比较职位很容易,但选择一个你喜欢并擅长的职位更重要。专注于你所做的实际工作,确保它适合你。仅仅因为平均工资可能较低,并不意味着你实际上得到的报酬会更少。正如你之前看到的,我讨论的所有角色都有很高的最高工资。

在结束之前,您可以参考一些其他资源来了解更多信息:

  • Airbnb 的 一份数据科学工作并不适合所有人 文章:我认为 Airbnb 在组织数据科学工作家庭方面做得最好的工作之一,本文对此进行了详细解释。他们不是有一个模糊的数据科学家头衔,而是有三个分析、算法和推理的轨道。
  • 到底什么是数据科学?YouTube 上霍马的一位数据科学家 说:他很好地按照公司规模解释了不同类型的数据科学家。你还会更好地了解大型科技公司的分析数据科学家们在做什么。

再次感谢您的阅读。我的愿望是,这篇文章给了你一些见解,让你在研究数据科学和机器学习的世界时不会迷失。一如既往,如果你有任何问题,请在下面评论。在这个艰难的时刻,我祝你一切顺利,希望这篇文章对你有用。下次见。

如果你觉得无聊,可以看看我以前的文章和项目。

  • 中等 : 如何数据科学无学位
  • : 作为数据/研究科学家如何保持最新
  • Medium : 我如何在 5 周内用 Django 构建并部署我的第一个 Web 应用
  • 中等: 四年内做过软件工程师、机器学习工程师、数据科学家。这些是我的主要收获。
  • YouTube : 用深度学习打败脸书的文字闪电战游戏。
  • 项目:查看我的最新项目www . Salary . Ninja及相应文章 欢迎来到薪金忍者
  • 查看我正在看的书: 我的书单 。我在用 html、CSS 和 Javascript 做这个的时候很开心。

2020–06 更新:

  • 这篇文章是 KDnuggets.com 的特稿。感谢您的支持和关注!:https://www . kdnugges . com/2020/06/machine-learning-engineer-vs-data-scientist . html # . xvtzyrhrx 8s . LinkedIn

2021–11 更新:

  • 我有一篇新文章:我如何用我的前四篇中型文章赚了 2000 多美元。请检查一下!

MLflow 第 1 部分:MLflow 入门!

原文:https://towardsdatascience.com/mlflow-part-1-getting-started-with-mlflow-8b45bfbbb334?source=collection_archive---------22-----------------------

MLflow 101

使用这个方便的工具,帮助您迈出机器学习生命周期流程的第一步

朋友们,你们好!我们带着另一个快速提示回到这里,因为我试图保持这些帖子快速,这实际上是与 MLFlow 相关的一系列提示的第一部分。本着完全透明的精神,MLFlow 对我来说是相当新的,因此在接下来的几周内,我将与大家一起学习一些东西。如果您想了解我的代码,请查看我的相关 GitHub 库的链接。

我敢肯定你脑子里的第一个问题是,什么是 MLflow?简而言之, MLflow 是一个开源平台,旨在帮助简化机器学习生命周期过程。同样,我仍在学习它的所有功能,但它似乎提供了许多有前途的功能,我很高兴在未来的帖子中探索这些功能。这些事情包括创建模型注册中心、将模型作为 API 轻松部署等等。老实说,我不知道这个子系列会持续多久,但我想我们会从这个简洁的工具中获得很多!

但是当然,我们都得从某个地方开始。我们将一步步走进这个世界,为将来的职位做好准备。也就是说,我们将采用一种非常简单的方法来创建和记录一个非常简单的模型。在开始之前,我们需要安装 MLflow,它就像运行以下 pip 命令一样简单:

pip install mlflow

在过去的几篇文章中,我们一直在使用泰坦尼克号数据集,但这一次,我们将偏离使用经典的红酒质量数据集🍷。现在,我个人不是一个葡萄酒爱好者(一般来说也不是一个酒精爱好者),但对于你们这些葡萄酒鉴赏家来说,我想你们会像《泰坦尼克号》一样喜欢这个数据集,如果不是更多的话,因为它不是基于一个巨大的悲剧!

我们之所以要更改此数据集,是因为此数据集中的所有要素本质上都是数值型的,因此我们实际上不需要进行任何要素工程来使其适合模型。当然,我不能保证我们会得到高质量的结果,但是至少我们可以得到一个简单的模型,并且运行起来,而不需要数据清理的麻烦。我们唯一要做的就是导入数据,并在训练集和验证集之间适当地拆分数据,如下所示:

# Loading data and prepping for training
df_wine = pd.read_csv('../data/wine/train.csv')X = df_wine.drop(columns = 'quality')
y = df_wine[['quality']]X_train, X_val, y_train, y_val = train_test_split(X, y, random_state = 42)

(哦,顺便说一下,我觉得有必要说今天的帖子或多或少是 MLflow 的第一个教程的副本,但我故意简化了很多,并在这里更彻底地解释我的简化。)

现在是我们开始步入 MLflow 世界的时候了。我将继续粘贴下面的脚本的剩余部分,并解释每一部分是做什么的。

# Defining model parameters
alpha = 1
l1_ratio = 1# Running MLFlow script
with mlflow.start_run():# Instantiating model with model parameters
    model = ElasticNet(alpha = alpha,
                       l1_ratio = l1_ratio)# Fitting training data to the model
    model.fit(X_train, y_train)# Running prediction on validation dataset
    preds = model.predict(X_val)# Getting metrics on the validation dataset
    rmse = mean_squared_error(preds, y_val)
    abs_error = mean_absolute_error(preds, y_val)
    r2 = r2_score(preds, y_val)# Logging params and metrics to MLFlow
    mlflow.log_param('alpha', alpha)
    mlflow.log_param('l1_ratio', l1_ratio)
    mlflow.log_metric('rmse', rmse)
    mlflow.log_metric('abs_error', abs_error)
    mlflow.log_metric('r2', r2)# Logging model to MLFlow
    mlflow.sklearn.log_model(model, 'model')

在“mlflow.start_run()”下,前几行代码您应该已经非常熟悉了。这里,我们只是用提供的参数实例化一个模型,根据参数拟合训练数据,然后用我们新训练的模型和验证数据集获得预测结果。通过验证数据集中记录的预测结果和实际结果,我们可以获得均方根误差、平均绝对误差和 R2 分数的适当指标。到目前为止,这里没有什么新东西。

现在是我们开始涉足新领域的时候了。幸运的是,我认为简单地阅读代码本身就足够了。伐木时间到了,朋友们!在我们的代码中,我们将记录三件不同的事情:模型的参数、来自验证集的度量以及模型本身。随着我们下面对 UI 的探究,这样做的原因将很快变得显而易见。

运行这段代码后,您会注意到一个名为“mlruns”的新目录应该出现在您运行代码的位置附近。当你第一眼看到它的时候,它可能看起来很奇怪,但是如果你深入挖掘,你会找到你真正关心的东西。值得注意的是,您应该能够挖掘出您刚刚记录的所有内容,包括序列化的模型工件本身。

现在,在我们进入下一节之前,我想记下我在 Jupyter 笔记本和基本 Python 脚本中运行了这段代码。你不需要这样做,但这将有助于理解为什么我现在注意到这一点。

好了,现在有趣的部分来了!在命令行中,导航到“mlruns”上面的目录。(如果您刚刚运行了 Python 脚本,您应该已经在那里了。)运行以下命令,您应该会看到以下屏幕:

mlflow ui

如果你像我一样,这个界面可能看起来很熟悉,因为它似乎在幕后使用 Gunicorn 来提供这个 UI。您会注意到,在我的例子中,UI 似乎是在 localhost:5000 上提供的。打开你最喜欢的浏览器,导航到那个地址。这是您应该看到的屏幕。

很整洁,是吧?请注意,该表中显示了两次运行。如果您查看这些运行的源代码,您会注意到其中一个是从我的 mlflow-wine.py Python 脚本运行的,而另一个是从 iPykernel 运行的,这当然是我的 Jupyter 笔记本!此外,您将在接下来的几列中看到我们的模型参数,最后您可以在最后一组列中看到模型指标。

接下来,点击“开始时间”下的超链接,打开其中一个模型。这是你应该看到的。

同样,我们看到了像模型参数和验证指标这样的东西,但是我们在这里也看到了其他附加的东西,比如持续时间和相关的 git 提交。我不能在一个屏幕截图中捕获所有的内容,但是如果你从这里向下滚动,你也可以直接从 UI 中导航到模型工件本身,我认为这实在是太酷了!

这就是第一次介绍的全部内容!我们在这里仅仅触及皮毛,所以我期待在接下来的几篇帖子中与大家一起学习,继续共同探索 MLflow。希望你喜欢这个快速介绍!很快再次见到你们。😃

MLflow 第 2 部分:将跟踪服务器部署到 Minikube!

原文:https://towardsdatascience.com/mlflow-part-2-deploying-a-tracking-server-to-minikube-a2d6671e6455?source=collection_archive---------8-----------------------

MLflow 101

在 Minikube 上运行的单个服务器中创建一个用于记录和跟踪模型工件的点

10/15/20 更新:在撰写本系列的下一篇文章时,我发现了几个妨碍我正确部署 Minikube 的错误。为此,我更新了一些内容,让您可以使用一个工作实例!😃

欢迎回来,朋友们!我们继续关注 MLflow 上的迷你系列。如果你错过了第一部分,一定要在这里查看。第一篇文章是关于 MLflow 的日志基本参数、度量和工件的超级基础介绍。这只是让我们将这些项目记录到本地机器上的一个位置,这不是一个理想的做法。在公司环境中,理想情况下,您希望将所有这些东西记录到一个集中的、可重用的位置。这就是我们今天要解决的问题!当然,你可以在这个链接找到我在 GitHub 上的所有代码。

所以要明确的是,我们将涉及一些高级主题,这些主题需要一些关于 Docker 和 Kubernetes 的知识。我个人计划以后再写关于这些的文章,但是现在,如果你想快速开始使用 Docker 和 Kubernetes,我推荐以下资源:

  • Docker 101 教程
  • 学习 Kubernetes 基础知识

现在,如果你知道 Kubernetes,你很可能熟悉 Minikube,但如果你不熟悉,Minikube 基本上是一个小虚拟机,你可以在本地机器上运行,启动一个沙盒环境来测试 Kubernetes 的概念。一旦 Minikube 建立并运行,对于那些在合法的 Kubernetes 环境中工作过的人来说,它看起来会非常熟悉。设置 Minikube 的说明在本页中有很好的记录,但是为了让 Minikube 工作,我们需要在这篇文章的后面添加一些额外的东西。

在继续之前,我认为一张图片胜过千言万语,所以下面是我们将在这里建造的建筑的一张小图片。

好的,右边是我们的小型环境。同样,Minikube 是合法的 Kubernetes 环境的高度代表,所以 Minikube 中的所有东西都是我们在任何 Kubernetes 工作区中看到的。因此,我们可以看到 MLflow 的跟踪服务器部署在部署内部。该部署通过将服务连接到入口与外部世界进行交互(这就是为什么在我们的图片中入口跨越内部和外部),然后我们可以在 web 浏览器中查看跟踪服务器界面。很简单,对吧?

好的,第一步是创建一个 Docker 映像,用于构建 MLflow 跟踪服务器。这真的很简单,我个人已经上传了我的公众形象,以防你想跳过这第一步。这是我个人 Docker Hub 中的图片。)Dockerfile 将简单地构建在一个基本的 Python 映像之上,安装 MLflow,并设置适当的 entrypoint 命令。看起来像这样:

# Defining base image
FROM python:3.8.2-slim# Installing packages from PyPi
RUN pip install mlflow[extras]==1.9.1 && \
    pip install psycopg2-binary==2.8.5 && \
    pip install boto3==1.15.16# Defining start up command
EXPOSE 5000
ENTRYPOINT ["mlflow", "server"]

你知道这里的流程:建造并推进到 Docker Hub!(或者就用我的。)

我们 10-15-20 更新开始的地方!

好的,在这篇文章的前一次迭代中,我试图使用一个简单的 PVC 来存储元数据和工件。事实证明这并不容易。相反,我们将不得不做一些额外的跑腿工作来让它在 Minikube 上运行。为此,我们将为后端元数据配置一个 Postgres 存储,并为工件配置一个名为 Minio 的对象存储。(下面有更多关于 Minio 的内容,以防你没听说过。)如果这两件事听起来都让你望而生畏,那没关系!您可以简单地使用我的代码来启动和运行。

好吧,让我们来解决 Postgres 的部署问题。以下是 K8s 清单代码:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mlflow-postgres-config
  labels:
    app: mlflow-postgres
data:
  POSTGRES_DB: mlflow_db
  POSTGRES_USER: mlflow_user
  POSTGRES_PASSWORD: mlflow_pwd
  PGDATA: /var/lib/postgresql/mlflow/data
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mlflow-postgres
  labels:
    app: mlflow-postgres
spec:
  selector:
    matchLabels:
      app: mlflow-postgres
  serviceName: "mlflow-postgres-service"
  replicas: 1
  template:
    metadata:
      labels:
        app: mlflow-postgres
    spec:
      containers:
      - name: mlflow-postgres
        image: postgres:11
        ports:
        - containerPort: 5432
          protocol: TCP
        envFrom:
        - configMapRef:
            name: mlflow-postgres-config
        resources:
          requests:
            memory: "1Gi"
            cpu: "500m"
        volumeMounts:
        - name: mlflow-pvc
          mountPath: /var/lib/postgresql/mlflow
  volumeClaimTemplates:
  - metadata:
      name: mlflow-pvc
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 100Mi
---
apiVersion: v1
kind: Service
metadata:
  name: mlflow-postgres-service
  labels:
    svc: mlflow-postgres-service
spec:
  type: NodePort
  ports:
  - port: 5432
    targetPort: 5432
    protocol: TCP
  selector:
    app: mlflow-postgres

因此,我不会一行一行地介绍所有内容,但在 1000 英尺的高度上,我将启动一个 Postgres 实例,它具有 100 兆字节的存储空间,并在代码顶部定义了适当的配置信息。如果你愿意,你可以改变这些变量。记住,我们只是在这里学习,所以这些变量显然是暴露的。在现实世界中,这是一个巨大的安全问题,所以如果您打算将它用于合法部署,请不要听从我的建议。

好了,部署好之后,我们就可以开始处理我们的对象存储了:Minio。现在,如果你像我一样对 Minio 完全陌生,它基本上是一个对象存储,你可以部署到 K8s,基本上模仿亚马逊网络服务(AWS)的 S3 服务。其部署语法如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mlflow-minio
spec:
  selector:
    matchLabels:
      app: mlflow-minio
  template:
    metadata:
      labels:
        app: mlflow-minio
    spec:
      volumes:
      - name: mlflow-pvc
        persistentVolumeClaim:
          claimName: mlflow-pvc
      containers:
      - name: mlflow-minio
        image: minio/minio:latest
        args:
        - server
        - /data
        volumeMounts:
        - name: mlflow-pvc
          mountPath: '/data'
        env:
        - name: MINIO_ACCESS_KEY
          value: "minio"
        - name: MINIO_SECRET_KEY
          value: "minio123"
        ports:
        - containerPort: 9000
---
apiVersion: v1
kind: Service
metadata:
  name: mlflow-minio-service
spec:
  type: NodePort
  ports:
  - port: 9000
    targetPort: 9000
    protocol: TCP
  selector:
    app: mlflow-minio
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: mlflow-minio-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.il/add-base-url: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - host: mlflow-minio.local
    http:
      paths:
        - backend:
            serviceName: mlflow-minio-service
            servicePort: 9000
          path: /
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mlflow-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 100Mi

因此,从高层次来看,我们正在部署一个 Minio 对象存储,由一个拥有 100 兆数据的 PVC 提供支持。您还可以在部署的环境变量中看到,我们定义了访问密钥 ID 和秘密访问密钥。这些与 AWS 的 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY 非常相关。现在,在进入下一步之前,你必须正确配置你的机器的入口,在我最初的帖子中,我在下面分享了如何做。(我懒得在这里重新输入,所以为 ingress 做一个 CTRL+F,我相信你会找到它!)

好的,如果您正确配置了入口,并在浏览器中导航到 mlflow-minio.local,您应该会看到这个闪屏。

在相应的字段中,键入我们在 Minio 部署中定义的访问密钥和秘密密钥。(如果你和我保持一致,那分别是“minio”和“minio123”。)点击回车键进入下一个屏幕。

好的,在我的例子中,我已经创建了“桶”,我们将使用它来存储我们的工件。对于您来说,只需单击 UI 右下角的 orangish 加号,选择“创建新桶”,并将您的新桶命名为“mlflow”即可。

唷!好了,我们已经设置好了后端的东西!是时候让实际的服务器开始运转了!

我将主要坚持使用这里的部署清单。大多数语法对您来说都很熟悉。这里唯一需要注意的是我们将传递给建筑 Docker 图像的参数。让我先向您展示一下我的部署清单。

# Creating MLflow deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mlflow-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mlflow-deployment
  template:
    metadata:
      labels:
        app: mlflow-deployment
    spec:
      containers:
      - name: mlflow-deployment
        image: dkhundley/mlflow-server:1.0.3
        imagePullPolicy: Always
        args:
        - --host=0.0.0.0
        - --port=5000
        - --backend-store-uri=postgresql://mlflow_user:mlflow_pwd@10.98.160.170:5432/mlflow_db
        - --default-artifact-root=s3://mlflow/
        - --workers=2
        env:
        - name: MLFLOW_S3_ENDPOINT_URL
          value: [http://mlflow-minio.local/](http://mlflow-minio.local/)
        - name: AWS_ACCESS_KEY_ID
          value: "minio"
        - name: AWS_SECRET_ACCESS_KEY
          value: "minio123"
        ports:
        - name: http
          containerPort: 5000
          protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: mlflow-service
spec:
  type: NodePort
  ports:
    - port: 5000
      targetPort: 5000
      protocol: TCP
      name: http
  selector:
    app: mlflow-deployment
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: mlflow-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.il/add-base-url: "true"
spec:
  rules:
  - host: mlflow-server.local
    http:
      paths:
        - backend:
            serviceName: mlflow-service
            servicePort: 5000
          path: /

这里需要指出几个关键点。首先,Postgres 实例在“args”中用其 IP 地址引用。我通过运行以下命令获得了该 IP 地址:

kubectl get services

这会给你这个屏幕:

您会注意到 mlflow-postgres-service 的 CLUSTER-IP 与我的服务器部署清单中的内容直接相关。无论你的服务显示什么,你都需要更新你的 IP,因为它可能和我的不一样。(说实话……我觉得有一种编程方式可以做到这一点,但我真的不知道该怎么做。)还要注意我们是如何将 Minio 称为后端服务器的。对你来说,我们确实在使用类似 AWS 的环境变量可能看起来很奇怪,但是,嘿,这就是它的工作方式!

好了,现在我们已经成功部署了一切,是时候让我们的 Minikube 入口工作了。如果你在一个合法的 Kubernetes 环境中工作,你可能不会有这个问题,但是 Minikube 在这里可能有点棘手。老实说,这最后一部分花了我好几天才弄明白,所以我很高兴终于把这些知识传授给你了!

让我们再看一眼 YAML 入口:

# Creating the Minikube ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: mlflow-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.il/add-base-url: "true"
spec:
  rules:
  - host: mlflow-server.local
    http:
      paths:
        - backend:
            serviceName: mlflow-service
            servicePort: 5000
          path: /

这其中的大部分你应该很熟悉。在我们的示例中,我们将在 mlflow-server.local 上提供 MLflow 跟踪服务器的 UI。对您来说可能比较陌生的一点是那些注释,它们是绝对必要的。没有它们,您的入口将无法正常工作。我特意把下面的图片贴到 Twitter 上,试图让人们帮我解决黑屏问题。这很令人沮丧。

呸,真是一团糟!经过反复试验,我终于发现上面提供的特定注释配置是有效的。老实说,我不能告诉你为什么。_(ツ)_/

但是等等,还有呢!默认情况下,Minikube 没有设置为开箱即可处理入口。为了做到这一点,你需要做一些事情。首先,在 Minikube 服务器运行之后,运行以下命令:

minikube addons enable ingress

很简单。现在,您需要设置您的计算机,以通过我们在入口中设置的 mlflow-server.local 主机引用 Minikube 集群的 IP。要获取 Minikube 的 IP 地址,只需运行以下命令:

minikube ip

把它复制到你的剪贴板上。现在,下一部分对你来说可能是全新的。(至少,对我来说是这样!)就像您可以为 Linux 创建别名命令一样,您显然也可以创建从 IP 地址到 web 地址的别名关系。这非常有趣,因为我了解到这是您的浏览器将“localhost”翻译为您的本地 IP 地址的地方。

要导航到需要这样做的位置,请运行以下命令:

sudo nano /etc/hosts

您应该会看到一个类似这样的屏幕:

因此,您可以在顶部看到我刚才提到的本地主机。打开这个接口,粘贴您的 Minikube 的 IP 地址(在我的例子中是 192.168.64.4 ),然后粘贴 MLflow 服务器和 Minio 工件存储的主机名,在我们的例子中分别是 mlflow-server.local 和 mlflow-minio.local。

好的,如果你做了所有正确的事情,你应该已经准备好了!导航到您选择的浏览器,打开http://ml flow-server . local .如果一切顺利,您应该会看到一个熟悉的屏幕。

这就是这篇文章的全部内容,各位!我不想给你们带来太多负担,所以在我们的下一篇文章中,我们将从这里开始,在这个共享的跟踪服务器上记录一两个实践模型,看看它是否工作。在接下来的两篇文章中,我们将进一步展示如何从这个跟踪服务器部署模型。所以说实话,这篇文章的内容可能没有那么迷人,但我们正在铺设火车轨道,它将在接下来的几篇文章中让一切真正飞起来。

在那之前,感谢你阅读这篇文章!请务必查看我以前关于其他数据科学相关主题的文章,下周我们将看到更多 MLflow 内容!

MLflow 第 3 部分:将模型记录到跟踪服务器!

原文:https://towardsdatascience.com/mlflow-part-3-logging-models-to-a-tracking-server-54b6aa3cd00f?source=collection_archive---------20-----------------------

MLflow 101

将您的参数、指标、工件等记录到 MLflow 跟踪服务器

嘿,朋友们,欢迎回到我们关于 MLflow 系列的另一篇文章。如果这是你看到的第一篇文章,你想了解一下,请点击这里查看之前的文章:

  • 第 1 部分:MLflow 入门!
  • 第 2 部分:将跟踪服务器部署到 Minikube!

和往常一样,如果你想看这篇文章中提到的代码,请务必点击这里查看我的 GitHub repo。

这篇最新的文章将建立在第 2 部分的基础上,所以如果你错过了,请一定要看看。简单回顾一下我们在那篇文章中所做的,我们在本地机器上用 Minikube 为 Kubernetes 部署了一个 MLflow 跟踪服务器。在幕后,MLflow 跟踪服务器由 Postgres 元数据存储和名为 Minio 的类似 AWS S3 的工件存储支持。那篇文章内容丰富,所以我很乐意分享这篇文章,相比之下,这篇文章简单多了。唷!

我个人更喜欢图片,而不是静态的解释,所以结合我们在上一段中提到的内容,这个架构图像总结了我们将如何在这个特定的帖子中与 MLflow 进行交互。(如果你不熟悉图标,大象是 PostgreSQL,红色的火烈鸟图标是 Minio。)

作者创建的图像

当然,在我们上一篇文章中,我们已经在图片的右侧做了所有的事情,所以这篇文章的重点是你需要为客户机上的 Python 文件包含什么。当然,巧合的是,由于我们使用 Minikube,所有的东西都托管在本地机器上,但是如果你使用合法的 Kubernetes 环境,你的客户端很可能与 MLflow 跟踪服务器分开。

这段代码实际上非常简单,其中很多内容对您来说肯定很熟悉。部分是因为其中很多是基本的机器学习内容,部分是因为在阅读本系列的第 1 部分时,您可能已经看到了其中的大部分内容。因为代码非常简单,所以我将把全部内容粘贴到这里,并介绍一些您可能不熟悉的特殊内容。

# Importing in necessary libraries
import os
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.linear_model import ElasticNet
import mlflow
import mlflow.sklearn# PROJECT SETUP
# ------------------------------------------------------------------------------
# Setting the MLflow tracking server
mlflow.set_tracking_uri('[http://mlflow-server.local'](http://mlflow-server.local'))# Setting the requried environment variables
os.environ['MLFLOW_S3_ENDPOINT_URL'] = '[http://mlflow-minio.local/'](http://mlflow-minio.local/')
os.environ['AWS_ACCESS_KEY_ID'] = 'minio'
os.environ['AWS_SECRET_ACCESS_KEY'] = 'minio123'# Loading data from a CSV file
df_wine = pd.read_csv('../data/wine/train.csv')# Separating the target class ('quality') from remainder of the training data
X = df_wine.drop(columns = 'quality')
y = df_wine[['quality']]# Splitting the data into training and validation sets
X_train, X_val, y_train, y_val = train_test_split(X, y, random_state = 42)# MODEL TRAINING AND LOGGING
# ------------------------------------------------------------------------------
# Defining model parameters
alpha = 1
l1_ratio = 1# Running MLFlow script
with mlflow.start_run():# Instantiating model with model parameters
    model = ElasticNet(alpha = alpha,
                       l1_ratio = l1_ratio)# Fitting training data to the model
    model.fit(X_train, y_train)# Running prediction on validation dataset
    preds = model.predict(X_val)# Getting metrics on the validation dataset
    rmse = mean_squared_error(preds, y_val)
    abs_error = mean_absolute_error(preds, y_val)
    r2 = r2_score(preds, y_val)# Logging params and metrics to MLFlow
    mlflow.log_param('alpha', alpha)
    mlflow.log_param('l1_ratio', l1_ratio)
    mlflow.log_metric('rmse', rmse)
    mlflow.log_metric('abs_error', abs_error)
    mlflow.log_metric('r2', r2)# Logging training data
    mlflow.log_artifact(local_path = '../data/wine/train.csv')# Logging training code
    mlflow.log_artifact(local_path = './mlflow-wine.py')# Logging model to MLFlow
    mlflow.sklearn.log_model(sk_model = model,
                             artifact_path = 'wine-pyfile-model',
                             registered_model_name = 'wine-pyfile-model')

在顶部,您会注意到我们首先必须确保脚本指向正确的跟踪服务器。当我们在上一篇文章中部署我们的跟踪服务器时,你可能记得我们在 URI mlflow-server.local 后面有跟踪服务器本身,并且工件存储(minio)在 mlflow-minio.local 后面提供。提醒一下,Minio 故意模仿 AWS 的 S3,所以如果你想知道为什么我们要设置类似 AWS 的环境变量,这就是为什么。

在加载数据并进行一些基本建模后,我们归结到所有 MLflow 跟踪的优点。MLflow 在这里非常灵活,所以你会注意到我们正在记录/上传所有这些伟大的东西,包括…

  • 因素
  • 韵律学
  • 我们用来运行这个模型的代码
  • 训练数据本身
  • 模型本身

说到最后一个,您会注意到一些关于模型命名的特殊语法。这是因为除了在工件注册中心获得模型工件之外,MLflow 还将在其 MLflow 模型注册中心创建一个正式的模型。我们将在下面简要地介绍一下,但是我们将在以后的文章中进一步探讨。(敬请期待!)

好了,如果一切正常,您需要做的就是运行以下命令:

python mlflow-wine.py

我已经多次运行了这个文件,所以这里是我的终端显示的输出。如果您是第一次运行这个程序,您会看到一些类似的东西,但很明显只是一个微小的不同:

Registered model 'wine-pyfile-model' already exists. Creating a new version of this model...
Created version '3' of model 'wine-pyfile-model'.

还有朋友,真的是这样!但是在我们结束这篇文章之前,让我们进入 UI,看看一切都正常工作。打开你的浏览器,跳到 mlflow-server.local,你会看到一个类似这样的屏幕:

如果您阅读了本系列的第 1 部分,这看起来会非常熟悉。点击相应的超链接,打开其中一个运行。如果一切正常,您应该看到您刚刚记录的所有适当的信息,包括我们刚刚创建的模型工件。不错!

第 1 部分中我们没有涉及的另一件事是位于 UI 左上角的新 Models 选项卡。单击它,您应该会看到类似这样的内容:

这个用户界面很酷。您不仅可以提供模型的全面描述,还可以将模型的特定版本设置为不同的阶段。例如,您可以将“版本 2”设置为转移,“版本 3”设置为生产,“版本 1”设置为归档。这个功能真的很棒,当我们在未来的帖子中探索更多东西时,它会非常方便。

当然,尽管 UI 很棒,但我们真的应该以编程方式做所有事情,MLflow 在这方面也有我们的支持。但是我认为我们今天在一个很好的地方停下来,所以我们将继续并结束。在下一篇文章中,我们将从一个更加程序化的角度来看如何与这个 UI 交互,然后在接下来的两篇文章中,我们将展示如何将这个模型注册表中的模型部署到一个真实的生产环境中,从而真正开始使用 gas。在此之前,感谢阅读!注意安全,朋友们!

mlmachine -干净的 ML 实验,优雅的 EDA 和 Pandas 管道

原文:https://towardsdatascience.com/mlmachine-clean-ml-experiments-elegant-eda-pandas-pipelines-daba951dde0a?source=collection_archive---------23-----------------------

来自 Pixabay 的像素体系的图像

多层机器

这个新的 Python 包加速了基于笔记本的机器学习实验

TL;博士

mlmachine 是一个 Python 库,用于组织和加速基于笔记本的机器学习实验。

在本文中,我们使用 mlmachine 来完成原本需要大量编码和工作的操作,包括:

  • 数据输入和特征类型识别
  • 简单、优雅的探索性数据分析
  • 熊猫进出管道

查看这篇文章的 Jupyter 笔记本。

在 GitHub 上查看项目。

查看 mlmachine 系列的其他条目:

[## ml machine-group by inputr、KFoldEncoder 和倾斜校正

这个新的 Python 包加速了基于笔记本的机器学习实验

towardsdatascience.com](/mlmachine-groupbyimputer-kfoldencoder-and-skew-correction-357f202d2212) [## mlmachine -众包特征选择

这个新的 Python 包加速了基于笔记本的机器学习实验

towardsdatascience.com](/mlmachine-crowd-sourced-feature-selection-50cd2bbda1b7)

什么是 mlmachine?

笔记本通常充当数据科学家的草稿纸。机器学习实验往往会变成一系列杂乱无序的硬编码块。即使花时间编写通用功能,这些功能也是孤立的,无用地与新项目隔离开来。

mlmachine 是一个 Python 包,它有助于进行整洁有序的基于笔记本的机器学习实验,并完成实验生命周期的许多关键方面。

mlmachine 的中枢是**Machine()**级。**Machine()**对象保留数据集、目标数据和特征元数据。更重要的是,**Machine()**对象有许多内置方法,用于快速执行机器学习实验工作流的关键部分。

以下是我们将详细探讨的 mlmachine 功能的几个核心领域:

  1. 数据摄取& **mlm_dtype** 识别
  2. 探索性数据分析 -下面是一个例子,展示了为一个特性创建一个可视化和数据汇总面板是多么容易:

彻底的 EDA,简单的执行

3.熊猫友好的变压器和管道——看看简单地将 mlmachine 实用程序**PandasTransformer()**包裹在**OneHotEncoder()** 周围是如何维护我们的**DataFrame**:

mlmachine 包含大量旨在节省时间和提高模型性能的功能,同时保持我们的工作流程整洁有序。

让我们开始吧。

机器类-有许多辐条的轮毂

数据摄取

我们首先实例化一个**Machine()** 对象:

让我们打开刚才做的东西。使用规范的 Titanic 数据集,我们通过以下方式实例化一个名为**mlmachine_titanic****Machine()** 对象:

  • 将整个数据集作为一个**DataFrame**传入
  • 指定包含目标变量的列
  • 将监督学习任务指定为分类任务

**mlmachine_titanic** 最基本的目的是维护我们的观察数据集和我们的目标值。我们的数据集存储为**DataFrame** ,可以通过调用**mlmachine_titanic.data**来访问:

我们的目标变量存储为一个名为 Pandas **Series**的变量,可以通过调用**mlmachine_titanic.target**轻松访问:

如果需要,目标值将被自动标记编码。

我们还将几个包含特性名称的列表传递给参数,如**identify_as_continuous****identify_as_nominal**。让我们来看看这些参数的用途。

传销数据类型:为熊猫数据类型添加功能含义

Pandas dtypes 描述了包含在一个列中的值,但是不考虑这些值的实际含义。名词性范畴、序数范畴、连续数字、计数……通常不可能单独从熊猫数据类型中做出这些区分。

在 mlmachine 生态系统中,这些区别被称为**mlm_dtypes**。mlmachine 编目,最重要的是,随着数据集在特征工程中的发展而更新* **mlm_dtypes**。*

我们的数据集存储为**mlmachine_titanic.data**,有一个名为**mlm_dtypes**的元数据属性:

这个字典是 mlmachine 工作流的基石,渗透到了包的所有功能中。注意字典的键。根据我们在实例化**Machine()**对象时提供的指导,**mlm_dtypes**存储每个特性的 mlm dtype。

字典键使得引用某种类型的所有特性变得特别容易,而不必键入特性名称。这样做的实际好处是显而易见的,尤其是当我们考虑的数据集比这个巨大的数据集还要大的时候。

在本文中,我们将在两个关键领域利用这种效率:

  • 探索性数据分析
  • 转换和管道

让我们在介绍 mlmachine 的探索性数据分析功能时使用**mlm_dtypes**

因为 EDA 很繁琐,而且永远都用不完

我们都为执行粗略的 EDA 而感到内疚,如果有的话(“让我们开始模型训练吧!”).即使有了所有优秀的 Python 可视化库,EDA 也需要进行大量的设置。我们都在做的事情是,第一百次编写那些相同的、稍加修改的函数。记住哪种可视化类型最适合哪种特征类型以及特征/目标类型的组合并不容易。

跳过 EDA 绝对是一个错误,因此 mlmachine 的一部分功能致力于快速制作既有益又好看的面板。

分类特征面板

我们在介绍中看到了一个名为“apolloed”的分类特性的 EDA 面板。让我们超越这个例子,使用我们的**mlm_dtypes**字典为我们在**mlmachine_titanic.data**中的所有分类特征快速生成面板:

**eda_cat_target_cat_feat()**为分类目标环境中的分类或计数特征生成 EDA 面板。顶部有三个汇总表:

  1. 特性摘要——类别中每个级别的简单计数,以及每个级别在特性中所占的百分比。
  2. 功能与目标摘要-类别中每个级别的计数,按目标中的类分组
  3. 目标比例-特定特征级别值的百分比,按目标中的类分组。

该面板包括三个可视化。从左至右:

  1. 分类特征的树形图。
  2. 分类特征的条形图,按目标分面。
  3. 按目标分面的 100%水平堆积条形图。

轻松扩展到多类问题

现在让我们使用**eda_cat_target_cat_feat()**为一个多类示例生成一个面板。我们将使用 Scikit-learn wine 数据集来可视化一个名为“alcalinity_of_ash”的数字特征,该数字特征已被分成 5 个箱,实际上使其成为一个分类列:

面板的每个组件都相应地适应该数据集中的多类问题。

连续特征面板

现在让我们看看 mlmachine 可以对数字特征做些什么:

**eda_cat_target_num_feat()** 是一个方法,在分类目标的上下文中为数字特征生成一个面板。在顶部,我们展示了三只熊猫**DataFrames**:

  1. 特性概要——我们通过执行标准的**df.describe()**命令得到的所有概要统计数据,加上“缺失百分比”、“偏斜”和“峰度”。
  2. 特征与目标摘要-数字特征的计数、比例、平均值和标准差,按目标中的不同类别分组。
  3. 统计测试——如果目标列只有两个类,则报告 z 测试(或 t 测试,在小样本的情况下)的结果和相关的 p 值。

汇总表下面是一个包含四种可视化效果的面板。从左上角开始,从左到右:

  1. 数字特征的单变量分布图。
  2. 数字特征的 QQ 图。
  3. 由目标分面的数值特征的二元分布图。
  4. 由目标分面的水平方框图。

对多类问题的另一种毫不费力的扩展

**eda_cat_target_num_feat()**还能轻松适应多类问题。让我们看另一个简单的例子:

我们再次使用 Scikit-learn wine 数据集用同样的最少代码创建这个面板。请注意变化:

  1. “功能与目标概要”表展开以反映所有三个类别。
  2. 分面图扩展以可视化所有三个类。
  3. x 轴和 y 轴刻度标签是小数,而不是整数。这种修改是基于被可视化的数据的规模而动态发生的。更少的格式化时间,更多的探索时间。

mlmachine 为 EDA 引入了大量的简单性和动态性。现在让我们看看 mlmachine 是如何促进熊猫友好的 ML 实验工作流程的。

熊猫进出管道

Scikit-learn 拆卸熊猫数据帧

**DataFrame**放入 Scikit-learn 转换器的一个主要缺点是底层 NumPy 数组周围的**DataFrame**包装器的丢失。这个问题在像**PolynomialFeatures()**这样的变形金刚身上尤为突出:

如果我们认为我们已经通过访问**poly.get_feature_names()**属性战胜了这个 transformer,那么当我们看到输出时,我们会非常失望:

没什么帮助。

因此,我们失去了以下能力:

  • 轻松对转换后的数据集执行 EDA
  • 训练模型后评估特征重要性
  • 使用模型可解释性方法,如 SHAP 或莱姆
  • 仅仅识别哪些列是哪些列

当然,我们可以将 NumPy 数组反馈到一个**DataFrame**,并做任何需要的事情来使列匹配,但是……这是一件多么麻烦的事情。

变形金刚,现在有了数据框架

mlmachine 利用一个名为**PandasTransformer()**的类来确保如果一个**DataFrame**传入一个变压器,另一端会出现一个**DataFrame**

我们所要做的就是用**PandasTransformer()**包装**PolynomialFeatures()**,然后我们得到一个**DataFrame**,在另一边有有意义的列名:

就这么简单。

既然我们已经看到了如何在执行单个转换时保留我们的**DataFrame**,那么让我们在此基础上使用 Scikit-learn 的**Pipeline()****FeatureUnion()**功能来一次对多组特征执行多个操作。

PandasFeatureUnion & data frame selector-直观、熟悉、灵活

香草特色联盟

Scikit-learn 包含一个名为**FeatureUnion()**的类。引用文档中的话,**FeatureUnion()**“连接多个 transformer 对象的结果…这对于将几个特征提取机制合并到一个 transformer 中很有用。”

对于将不同的数据处理操作应用于不同的要素,这是一个非常好的工具。例如,我们可能希望表示估算连续特征和模式估算分类特征:

不幸的是,**FeatureUnion()**也遭受了和其他变形金刚一样的缺点——它返回一个 NumPy 数组。这就是**PandasFeatureUnion()**前来救援的地方。

PandasFeatureUnion & data frame selector

就像我们需要**PandasTransformer()**来保留**DataFrame()**后变换一样,我们需要**PandasFeatureUnion()**来维护最终的**DataFrame**后拼接。

基本示例

我们从这里重新开始,再次实例化一个名为**mlmachine_titanic****Machine()**对象。然后我们使用 mlmachine 的**PandasFeatureUnion()**类创建一个**DataFrame**友好的、**FeatureUnion**风格的管道,称为**impute_pipe**。这里是输出,仍然在一个**DataFrame**:

具体来说,我们对有空值的三个不同列执行三种不同类型的插补:

  • 用平均值估算“年龄”
  • 用模式估算“已装船”
  • 用常数值(X)输入“客舱”。

敏锐的观察者会注意到每条管道中存在另一个类别。这个类是**PandasFeatureUnion()**工作流的一个基本元素,根据它的使用方式有不同的用途。在第 30、34 和 38 行,**DataFrameSelector()**用于选择 union 的特定分支的列。使用**include_columns** 参数按名称选择列。

在第 42 行,我们做了一些不同的事情。由于按照设计,**FeatureUnion()**操作作用于特定的列并连接结果,我们将只剩下转换后的列,无需进一步干预。

这就是为什么**DataFrameSelector()**可以灵活选择所有列,除了那些指定的列。通过**exclude_columns**参数,我们选择除我们估算的特征之外的所有特征。这确保了我们保留完整的数据集。

现在我们已经填充了空值,让我们使用**PandasFeatureUnion()**工作流前进到稍微复杂一点的预处理步骤。如果对**mlm_dtypes**的目的有任何疑问,现在将变得更加清楚。

不太基本的例子

我们现在有了一个带有编码列的**DataFrame**,它们都被明确命名为:

让我们把这个**PandasFeatureUnion**一个分支一个分支:

  • “名义”管道——这里我们看到了**DataFrameSelector()**的灵活性。首先,我们通过将**[“nominal”]**传递给**include_mlm_dtypes** 参数来选择所有名义列。**DataFrameSelector()**直接引用**mlm_dtypes**进行栏目选择。其次,我们通过将特征名称传递给**exclude_columns**参数来排除“Cabin”(也是一个名义特征)。**DataFrameSelector()**通过选择除“客舱”之外的所有标称列来协调我们的包含/排除规格。最后,我们将选择的列传递给**OneHotEncoder()**,包装在**PandasTransformer()**中。**
  • “序数”管道——我们再次使用了**DataFrameSelector()**参数**include_mlm_dtypes**,这次是为了选择所有序数列。然后我们将结果传递给**OrdinalEncoder()**,用**PandasTransformer()**包装。我们还提供编码说明。当我们实例化我们的**Machine()**对象时,我们传入了一个名为**ordinal_encodings**的字典,**mlmachine_titanic**将它存储为一个属性。我们将这个字典的值包装在一个列表中,并将其传递给**OrdinalEncoder()**参数**categories**。这将确保在编码过程中执行所需的层次结构。
  • “bin”管道-我们再次使用**include_mlm_dtypes**选择所有连续特征,并将结果传递给**KBinsDiscretizer()**,包装在**PandasTransformer()**中。
  • “diff”管道——最后一步是重新组合任何在联合操作中会丢失的特性,并删除任何我们不再需要的特性。我们对**mlm_dtypes**属性执行列表理解以删除“Cabin ”,并将**mlmachine_titanic.ordinal_encodings**的键附加到结果中。这将确保原始的标称和序数特征在转换的数据集中是而不是,但是我们保留“小屋”。注意,我们没有排除连续列,尽管我们用**KBinsDiscretizer()**转换了这些特性。原因很简单——我们希望在数据集中保留原始的连续列。

我们用熟悉的**fit_transform()**方法来称呼**encode_pipe**

更新 mlm_dtypes

因为数据集中有了新的特性,所以最好的做法是在**fit_transform()**之后加上**update_mlm_dtypes()**

正如本文前面提到的,我们可以更新**mlm_dtypes**来反映**data**属性的当前状态。让我们来看一个前后对比,清楚地看到**mlm_dtypes**字典是如何变化的:

我们更新的**mlm_dtypes**字典在右边。我们看到没有标称列“apollowed”和“Sex ”,取而代之的是虚拟列的名称,如“apollowed _ C”和“Sex_male ”,由**PandasTransformer(OneHotEncoder())**产生。还要注意,“nominal”键仍然包含“Cabin”特性,我们选择在这里不处理它。

“ordinal”键包含我们的 binned 版本的“Age”和“Fare ”,以及“Pclass ”,它的命名方式清楚地表明了所应用的编码类型。

每当我们修改**data**时,我们简单地调用**update_mlm_dtypes()**,而**mlm_dtypes**会自动更新以反映数据集的当前状态。唯一真正的工作是从一开始就确定每个特性的 mlm dtype,这是我们每次都应该做的事情。

让我们通过利用**mlm_dtypes**字典来对我们的新特性快速执行一点 EDA,从而得出结论。这一次,我们将遍历所有的顺序功能:

我们覆盖了很多领域,但我们才刚刚开始探索 mlmachine 的功能。

查看 GitHub 库,并继续关注其他专栏条目。

mlmachine -众包特征选择

原文:https://towardsdatascience.com/mlmachine-crowd-sourced-feature-selection-50cd2bbda1b7?source=collection_archive---------54-----------------------

图片由阿雷克索查从皮克斯拜发来

多层机器

这个新的 Python 包加速了基于笔记本的机器学习实验

TL;速度三角形定位法(dead reckoning)

mlmachine 是一个 Python 库,用于组织和加速基于笔记本的机器学习实验。

在本文中,我们使用 mlmachine 来完成原本需要大量编码和工作的操作,包括:

  • 众包特征重要性估计
  • 通过迭代交叉验证的特征选择

查看这篇文章的 Jupyter 笔记本。

在 GitHub 上查看项目。

并查看过去的 mlmachine 文章:

[## mlmachine -干净的 ML 实验,优雅的 EDA 和 Pandas 管道

这个新的 Python 包加速了基于笔记本的机器学习实验

towardsdatascience.com](/mlmachine-clean-ml-experiments-elegant-eda-pandas-pipelines-daba951dde0a) [## ml machine-group by inputr、KFoldEncoder 和倾斜校正

这个新的 Python 包加速了基于笔记本的机器学习实验

towardsdatascience.com](/mlmachine-groupbyimputer-kfoldencoder-and-skew-correction-357f202d2212)

众包特征重要性估计

技术目录

以下是特征重要性估计技术的非穷尽列表:

  • 基于树的特征重要性
  • 递归特征消除
  • 顺序向前选择
  • 顺序向后选择
  • f 值/ p 值
  • 差异
  • 目标相关性

这一系列技术来自几个不同的库。理想情况下,我们使用所有的这些技术(在适用的情况下)来广泛理解每个特征在机器学习问题中扮演的角色。这是一系列繁琐的任务。

即使我们花时间去执行每一种方法,不同的执行会导致不同的变量,使整体评估变得乏味。

mlmachine 的**FeatureSelector()**类使得运行上面列出的所有特性重要性评估技术变得容易。此外,我们可以同时对各种估计量和各种度量进行这样的操作。让我们看看 mlmachine 的运行情况。

准备数据

首先,我们应用数据预处理技术来清理数据。我们将首先创建两个**Machine()**对象——一个用于训练数据,另一个用于验证数据:

现在,我们通过输入空值并应用各种宁滨和编码技术来处理数据:

这里是输出,仍然在一个**DataFrame**:

特征选择器

我们的**DataFrame**已经被估算,以多种方式编码,并且有几个新特性。我们准备好迎接**FeatureSelector()**

示例 1 -评估员类别

为了实例化一个**FeatureSelector()**对象,我们传递训练数据、标签和一个评估者列表。这个估计器列表可以包含估计器类名、实例化模型的变量或两者的组合。在这个例子中,我们传递了**LogisticRegression()****XGBClassifier()**的类名,这利用了估计器的默认设置。

我们的**FeatureSelector()**对象包含上述每个特性重要性技术的内置方法,以及一个名为**feature_selector_suite()**的方法,该方法将所有技术合并到一次执行中。

为了执行**feature_selector_suite()**,我们将“准确性”传递给参数**sequential_scoring**,将 0 传递给参数**sequential_n_folds**。这些参数影响顺序向后/向前算法。我们还将**save_to_csv**设置为 True,以将结果**DataFrame**保存到 CSV。这是我们的结果:

**DataFrame**中,一些列捕获指标的值,包括 F 值、P 值、方差、目标相关性和基于树的特征重要性。其余的列根据底层算法捕获选择或消除某个特征的顺序。

示例 2 -实例化模型

这是另一个例子。这一次,我们使用包含**RandomForestClassifier()**类和三个实例化模型的估计器列表来实例化**FeatureSelector()**。每个**RandomForestClassifier()****max_depth**超参数的不同值来实例化。最后,我们将“roc_auc”而不是“accuracy”作为我们的评分标准传递给**sequential_scoring**

注意,在这个**DataFrame**中,我们有递归特性消除和基于树的特性重要性的列,它们是专门为我们的评估列表中的实例化模型命名的。

我们已经整理了一份描述特性重要性的摘要,但是我们才刚刚开始。

众包

将所有这些信息放在一个地方的价值是显而易见的,但是为了实现对特征重要性的众包式、集合式评估,我们首先需要将这些值标准化。这样便于排名。

除了将价值观放在同一尺度上,我们还需要确保始终如一地处理价值观的方向性。例如,高 F 值表示重要特征,而低 p 值表示重要特征。

mlmachine 让这一切变得简单。**FeatureSelector()**包含一个名为**feature_selector_stats()**的方法,它逐列应用这个排序。作为一个额外的好处,**feature_selector_stats()**添加了几个描述每个特性排名的汇总统计列,并自动按照最佳排名对特性进行排序。

请注意这次更新的**DataFrame**(延伸到屏幕外)中的 3 个关键差异:

  1. 原始**DataFrame**中每列的值现在显示为等级,其中较低的值表示较高重要性的特性。
  2. **DataFrame**的左侧插入额外的汇总统计栏。
  3. **DataFrame**按平均排名升序排序。

根据这一总结,这些模型中最重要的前三个特征是“票价”、“性别”的平均目标编码版本和“年龄”。

在这个例子中,我们执行了第二步**feature_selector_stats()**,但是我们可以通过将**feature_selector_suite()**中的**add_stats**参数设置为 True 来跳过这一步。

通过迭代交叉验证的特征选择

特性重要性本身是一个好的开始,但是我们的最终目标是只为我们即将到来的模型训练阶段选择最有意义的特性。

我们的分级和排序的特性重要性总结是下一步的基础。为了评估每个子集,**FeatureSelector()**使用了一种类似于递归特征消除的方法:

  • 使用交叉验证训练具有所有特征的模型
  • 获取训练和验证数据集的平均性能
  • 从剩余的可用特征中移除最不重要的(1 倍步长)特征
  • 重复此操作,直到特性列表耗尽

为了确定“最不重要”,我们依赖于已排序的特征重要性汇总。每次我们删除功能时,我们会从剩余的功能中删除排名最低的功能。

简历摘要

让我们看看 mlmachine 的运行情况:

我们的**FeatureSelector()**对象包含一个名为**feature_selector_cross_val()**的方法。这将执行迭代特征子集评估并存储结果。让我们回顾一下参数:

  • **feature_selector_summary**:我们排名排序后的功能重要性汇总
  • **estimators**:我们想要用来评估特性的评估器列表
  • **scoring**:一个或多个评分标准
  • **n_folds**:交叉验证程序中的折叠数
  • **step**:每次迭代后要移除的特征数量
  • **save_to_csv**:指定是否将结果保存在 CSV 中

让我们回顾一下我们的结果:

**DataFrame**的每一行,我们可以看到单个评估者基于特定评分标准对某个特性子集的性能。“删除的功能”列描述了从全部功能集中删除了多少功能。记住,在每次迭代之后,**feature_selector_cross_val()**删除(1 x 步)最不重要的特征,其中重要性基于**feature_selection_summary**的排名和排序。

可视化性能曲线

**FeatureSelector()**还有一个内置方法,用于可视化每个子集的训练和验证分数:

在这里,我们可以看到 4 个**RandomForestClassifier()**模型的训练和验证准确性分数趋势。每个图表标题都清楚地告诉我们最佳验证准确性分数,以及达到该分数时从完整功能集中删除了多少功能。

结果摘要

最后,FeatureSelector()中有几个实用程序可以帮助我们总结和利用交叉验证程序的结果。

首先,方法**create_cross_val_features_df()**总结了每个模型在获得最佳验证分数时所使用的特性:

我们的特性构成了这个**DataFrame**的索引,我们的估计器被表示为列。在每个特征/估计值对的交叉点,X 表示该特征是否用于达到最佳验证分数的子集中。“计数”列合计了使用某个特性的评估者的数量,而**DataFrame**在该列中按降序排列。

第二,方法**create_cross_val_features_df()**为每个模型编译最佳特征子集,并在字典中返回结果。估计量是关键,相关值是包含每个估计量的最佳特征子集的列表。

该字典有助于在模型训练阶段快速利用这些特征子集。

最后

mlmachine 使得执行各种各样的特征重要性估计技术变得容易,并且有助于彻底的筛选过程来为各种估计器确定最佳特征子集。

查看 GitHub 库,并继续关注其他专栏条目。

ml machine-group by inputr、KFoldEncoder 和倾斜校正

原文:https://towardsdatascience.com/mlmachine-groupbyimputer-kfoldencoder-and-skew-correction-357f202d2212?source=collection_archive---------32-----------------------

图片由 Gerd Altmann 从 Pixabay 拍摄

多层机器

这个新的 Python 包加速了基于笔记本的机器学习实验

TL;速度三角形定位法(dead reckoning)

mlmachine 是一个 Python 库,用于组织和加速基于笔记本的机器学习实验。

在本文中,我们使用 mlmachine 来完成原本需要大量编码和工作的操作,包括:

  • 缺少值-评估和分组估算
  • KFold 编码——无泄漏的奇异编码
  • Box、Cox、Yeo & Johnson - Skew 校正器

查看这篇文章的 Jupyter 笔记本。

在 GitHub 上查看项目。

查看 mlmachine 系列的其他条目:

[## mlmachine -干净的 ML 实验,优雅的 EDA 和 Pandas 管道

这个新的 Python 包加速了基于笔记本的机器学习实验

towardsdatascience.com](/mlmachine-clean-ml-experiments-elegant-eda-pandas-pipelines-daba951dde0a) [## mlmachine -众包特征选择

这个新的 Python 包加速了基于笔记本的机器学习实验

towardsdatascience.com](/mlmachine-crowd-sourced-feature-selection-50cd2bbda1b7)

缺少值-评估和分组估算

让我们首先实例化两个**Machine()**对象,一个用于我们的训练数据,另一个用于我们的验证数据

评估

每个**Machine()**对象包含一个以表格和图形形式总结缺失的方法:

默认情况下,这个方法作用于与**mlmachine_train**相关联的**data**属性。让我们对验证数据集做同样的事情:

接下来,我们需要确定在训练数据中是否有缺失值的特征,而不是验证数据,反之亦然。这告诉我们应该如何设置我们的转换管道。例如,如果某个特征在验证数据集中有缺失值,但在训练数据集中没有,我们仍然希望在训练数据上对该特征进行拟合变换,以学习插补值,从而应用于验证数据集中的空值。

我们可以观察上面的表格和图像来比较两个数据集中的缺失状态,但是这可能很繁琐,尤其是对于大型数据集。相反,我们将利用我们的**Machine()**对象中的一个方法。我们简单地将验证数据集传递给**mlmachine_titanic_train**的方法**missing_col_compare**,该方法返回一个双向缺失汇总。

这里的关键观察是“Fare”完全填充在训练数据中,而不是验证数据中。我们需要确保我们的管道知道如何根据训练数据估算这些缺失值,尽管事实上训练数据在该特征中没有缺失任何值。

GroupbyImputer

mlmachine 包括一个名为**GroupbyImputer()**的转换器,它可以轻松执行 Scikit-learn 的**SimpleImputer()**提供的相同基本插补技术,但增加了根据数据集中的另一个特征进行分组的能力。让我们看一个例子:

在上面的代码片段中,我们指的是由“SibSp”分组的 input“Age”。我们将“Age”传递给**null_column**参数以指示哪一列包含空值,并将“SibSp”传递给**groupby_column**参数。**strategy**参数接收与 Scikit-learn 的**SimpleImputer()**相同的指令-“均值”、“中值”和“最频繁”。

为了检查学习到的值,我们可以显示对象的**train_value**属性,这是一个包含类别/值对的**DataFrame**:

**GroupbyImputer()**使用这些对来估算“年龄”中缺失的值。在不太可能的情况下,如果**groupby_column**中的某个级别在**null_column**中只有空值,那么与该级别相关的缺失值将被估算为整个特征的平均值、中值或众数。

归罪

现在我们将在**PandasFeatureUnion()**中使用**GroupbyImputer()**来估算训练和验证数据集中的空值。

此时,我们已经估算了所有的空值。这里是输出,仍然在一个**DataFrame**:

**GroupbyImputer()**在这个**PandasFeatureUnion()**操作中出现了两次。在第 4 行,我们通过特征“SibSp”分组来估算平均“年龄”值,在第 8 行,我们通过特征“Pclass”分组来估算平均“票价”值。

“上船”和“船舱”的估算以简单的方式完成——“上船”简单地用模式估算,“船舱”用常数值“X”估算。

最后,我们在**mlmachine_titanic_train.data****fit_transform()****PandasFeatureUnion()**,并通过在**mlmachine_titanic_valid.data**上调用**transform()**来完成填充我们的空值。

KFold 编码——无泄漏的奇异编码

基于目标值的编码技术,如均值编码、CatBoost 编码和证据权重编码,经常在 Kaggle 竞赛中讨论。这些技术的主要优点是它们使用目标变量来通知编码特性的值。然而,这也带来了将目标信息泄露到编码值中的风险。

KFold 交叉验证有助于避免这个问题。关键是将编码值仅应用于折叠外观察值。这种可视化说明了一般模式:

由 Pourya 在介质上拍摄的照片

  • 将验证子集从训练数据集中分离出来。
  • 从训练数据和相关联的目标值中学习编码值。
  • 仅将学习值应用于验证观察。
  • 对 K-1 剩余的折叠重复该过程。

KFoldEncoder

mlmachine 有一个名为**KFoldEncoder()**的类,它通过选择一个编码器来促进 KFold 编码。让我们使用一小部分功能来看看这是如何工作的。

我们希望对两个特征进行目标编码:“Pclass”和“Age”。由于“年龄”是一个连续的特征,我们首先需要将值映射到 bin,这实际上是一个有序的分类列。我们在下面简单的PandasFeatureUnion中处理所有这些:

该操作返回“Age”的装箱版本,以及原始的“Age”和“Pclass”特性。

接下来,我们使用包 category_encoders 提供的均值编码、CatBoost 编码和证据权重编码对“Pclass”和“Age_binned_5”进行目标编码。

让我们回顾一下关键的**KFoldEncoder()**参数:

  • **target**:我们**mlmachine_titanic_train**对象的目标属性
  • **cv**:交叉验证对象
  • **encoder**:目标编码器类

**KFoldEncoder()**学习训练数据上的编码值,并将这些值应用于失调观测值。

对于验证数据,过程更简单:我们计算应用于训练数据的平均出格编码,并将这些值应用于所有验证观察。

Box、Cox、Yeo & Johnson——我们的偏斜校正器

评价

正如我们有一个快速评估缺失的方法一样,我们也有一个快速评估偏斜的方法。

**skew_summary()**方法返回一个**DataFrame**,它总结了每个特性的偏斜,以及一个“Percent zero”列,它告诉我们特性中为零的值的百分比。

菱形校正

mlmachine 包含一个名为**DualTransformer()**的类,默认情况下,它将 Yeo-Johnson 和 Box-Cox 变换应用于指定的特征,目的是纠正倾斜。Box-Cox 变换自动寻找使对数似然函数最大化的λ值。

由于 Box-Cox 变换要求特征中的所有值都大于零,当违反此规则时,**DualTransformer()**应用两个简单特征调整中的一个:

  • 如果要素中的最小值为零,则该要素中的每个值在变换前都会增加 1。
  • 如果最小值小于零,则每个特征值将增加该特征中最小值的绝对值,再加上变换前的 1。

让我们使用**DualTransformer()**来看看我们是否可以最小化原始“年龄”特征中的偏差:

**DualTransformer()**增加了“Age_BoxCox”和“Age_YeoJohnson”功能。让我们再次执行**skew_summary()**,看看**DualTransformer()**是否解决了我们原始特性中的倾斜:

“Age_BoxCox”和“Age_YeoJohnson”的偏斜度分别为 0.0286 和 0.0483。

最后

我们刚刚学习了如何使用 mlmachine 来执行新颖的插补技术、奇异的分类特征编码和有效的偏斜校正。

查看 GitHub 库,并继续关注其他专栏条目。

基于贝叶斯优化的多机超参数整定

原文:https://towardsdatascience.com/mlmachine-hyperparameter-tuning-with-bayesian-optimization-2de81472e6d?source=collection_archive---------32-----------------------

图片来自 Pixabay 的托尔斯滕·弗伦泽尔

多层机器

这个新的 Python 包加速了基于笔记本的机器学习实验

TL;速度三角形定位法(dead reckoning)

mlmachine 是一个 Python 库,用于组织和加速基于笔记本的机器学习实验。

在本文中,我们使用 mlmachine 来完成原本需要大量编码和工作的操作,包括:

  • 一次多估值器的贝叶斯优化
  • 结果分析
  • 模型再现

查看这篇文章的 Jupyter 笔记本。

在 GitHub 上查看项目。

并查看过去的 mlmachine 文章:

[## mlmachine -干净的 ML 实验,优雅的 EDA 和 Pandas 管道

这个新的 Python 包加速了基于笔记本的机器学习实验

towardsdatascience.com](/mlmachine-clean-ml-experiments-elegant-eda-pandas-pipelines-daba951dde0a) [## ml machine-group by inputr、KFoldEncoder 和倾斜校正

这个新的 Python 包加速了基于笔记本的机器学习实验

towardsdatascience.com](/mlmachine-groupbyimputer-kfoldencoder-and-skew-correction-357f202d2212) [## mlmachine -众包特征选择

这个新的 Python 包加速了基于笔记本的机器学习实验

towardsdatascience.com](/mlmachine-crowd-sourced-feature-selection-50cd2bbda1b7)

一次多估值器的贝叶斯优化

贝叶斯优化通常被描述为超越穷举网格搜索的进步,这是正确的。这种超参数调整策略通过使用先验信息来通知给定估计器的未来参数选择而成功。查看 Will Koehrsen 关于 Medium 的文章,获得关于该包的精彩概述。

mlmachine 使用 hyperopt 作为执行贝叶斯优化的基础,并通过简化的工作流将 hyperopt 的功能性向前推进了一步,该工作流允许在单个流程执行中优化多个模型。在本文中,我们将优化四个分类器:

  • **LogisticRegression()**
  • **XGBClassifier()**
  • **RandomForestClassifier()**
  • **KNeighborsClassifier()**

准备数据

首先,我们应用数据预处理技术来清理数据。我们将首先创建两个**Machine()**对象——一个用于训练数据,另一个用于验证数据:

现在,我们通过输入空值和应用各种宁滨、特征工程和编码技术来处理数据:

这里是输出,还在一个**DataFrame**:

功能重要性摘要

作为第二个准备步骤,我们希望为每个分类器执行特征选择:

穷举迭代特征选择

对于我们最后的准备步骤,我们使用这个特征选择概要对每个估计量的越来越小的特征子集进行迭代交叉验证:

从这个结果中,我们提取每个估计量的最佳特征集的字典:

关键字是估计器名称,相关值是包含每个估计器的最佳性能特征子集的列名的列表。以下是**XGBClassifier()**的键/值对,它仅使用了 43 个可用特征中的 10 个来实现验证数据集上的最佳平均交叉验证准确性:

有了经过处理的数据集和最佳特征子集,是时候使用贝叶斯优化来调整 4 个估计器的超参数了。

概述我们的特征空间

首先,我们需要为每个估计量的每个参数建立我们的特征空间:

字典最外层的键是分类器的名称,用字符串表示。关联的值也是字典,其中键是参数名,表示为字符串,值是从中选择参数值的超点采样分布。

运行贝叶斯优化作业

现在,我们准备运行我们的贝叶斯优化超参数调优工作。我们将使用一个属于我们的**Machine()**对象**exec_bayes_optim_search()**的内置方法。让我们看看 mlmachine 的运行情况:

让我们回顾一下参数:

  • **estimator_parameter_space**:我们上面设置的基于字典的特征空间。
  • **data**:我们的观察。
  • **target**:我们的目标数据。
  • **columns**:可选参数,允许我们对输入数据集特征进行子集划分。接受功能名称列表,该列表将同等地应用于所有估算器。还接受一个字典,其中键表示估计器类名,值是与相关估计器一起使用的功能名称列表。在这个例子中,我们通过传入由上面的**FeatureSelector()**工作流中的**cross_val_feature_dict()**返回的字典来使用后者。
  • **scoring**:待评估的评分标准。
  • **n_folds**:交叉验证程序中使用的折叠数。
  • **iters**:运行超参数调整过程的总迭代次数。在这个例子中,我们运行了 200 次实验。
  • **show_progressbar**:控制进程中进度条是否显示和主动更新。

任何熟悉远视的人都会想知道目标函数在哪里。mlmachine 抽象掉了这种复杂性。

过程运行时间取决于几个属性,包括硬件、使用的估计器的数量和类型、折叠次数、特征选择和采样迭代次数。运行时可能会很长。因此,**exec_bayes_optim_search()**自动将每次迭代的结果保存到一个 CSV 文件中。

结果分析

结果汇总

让我们从加载和检查结果开始:

我们的贝叶斯优化日志保存了每次迭代的关键信息:

  • 迭代次数、估计量和评分标准
  • 交叉验证汇总统计数据
  • 迭代训练时间
  • 使用的参数字典

该日志为我们分析和评估贝叶斯优化过程的有效性提供了大量数据。

模型优化评估

首先也是最重要的,我们想看看性能在迭代过程中是如何提高的。

让我们通过迭代来可视化**XGBClassifier()**损失:

每个点代表我们 200 个实验之一的表现。需要注意的关键细节是,最佳拟合线有一个明显的向下斜率——这正是我们想要的。这意味着,与之前的迭代相比,每次迭代的模型性能都会有所提高。

参数选择评估

贝叶斯优化最酷的部分之一是看到参数选择是如何优化的。

对于每个模型和每个模型的参数,我们可以生成两个面板的视觉效果。

对于数字参数,如**n_estimators****learning_rate**,双视觉面板包括:

  • 参数选择 KDE,过度强调理论分布 KDE
  • 通过迭代散点图和最佳拟合线进行参数选择

对于分类参数,如损失函数,双视觉面板包括:

  • 参数选择和理论分布条形图
  • 通过迭代散点图选择参数,按参数类别分面

让我们回顾一下**KNeighborsClassifier()**的参数选择面板:

内置方法**model_param_plot()**循环遍历估计器的参数,并根据每个参数的类型显示适当的面板。让我们分别看一下数值参数和分类参数。

首先,我们将查看数字参数**n_neighbors**的面板:

在左侧,我们可以看到两个重叠的核密度图,总结了实际参数选择和理论参数分布。紫色线对应于理论分布,正如所料,这条曲线是平滑和均匀分布的。蓝绿色线对应于实际的参数选择,很明显,hyperopt 更喜欢 5 到 10 之间的值。

在右侧,散点图显示了迭代过程中的**n_neighbors**值选择。随着贝叶斯优化过程在 7 左右的值上磨砺,最佳拟合线稍微向下倾斜。

接下来,我们将查看分类参数**algorithm**的面板:

在左侧,我们看到一个条形图,显示了参数选择的计数,按实际参数选择和理论分布选择分面。代表理论分布选择的紫色条比代表实际选择的蓝绿色条更均匀。

在右侧,散点图再次显示了迭代过程中的**algorithm**值选择。在迭代过程中,“ball_tree”和“auto”的选择明显减少,而“kd_tree”和“brute”更受青睐。

模型再现

顶级模型识别

我们的**Machine()**对象有一个名为**top_bayes_optim_models()**的内置方法,它根据我们的贝叶斯优化日志中的结果为每种估计器类型确定最佳模型。

使用这种方法,我们可以根据平均交叉验证分数来确定每个估计量的前 N 个模型。在这个实验中,**top_bayes_optim_models()**返回下面的字典,它告诉我们**LogisticRegression()**在第 30 次迭代中确定了它的顶级模型,**XGBClassifier()**在第 61 次迭代中,**RandomForestClassifier()**在第 46 次迭代中,**KNeighborsClassifier()**在第 109 次迭代中。

将模型投入使用

为了重新实例化一个模型,我们利用了我们的**Machine()**对象的内置方法**BayesOptimClassifierBuilder()**。为了使用这个方法,我们传递我们的结果日志,指定一个估计类和迭代次数。这将使用存储在日志记录中的参数实例化一个模型对象:

这里我们看到了模型参数:

**BayesOptimClassifierBuilder()**实例化的模型使用**.fit()****.predict()**的方式应该感觉很熟悉。

让我们以一个非常基本的模型性能评估来结束本文。我们将在训练数据和标签上拟合此**RandomForestClassifier()**,使用训练数据生成预测,并通过将这些预测与实际情况进行比较来评估模型的性能:

任何熟悉 Scikit-learn 的人都应该有宾至如归的感觉。

最后

mlmachine 使得一次有效地优化多个估计器的超参数变得容易,并且便于模型改进和参数选择的可视化检查。

查看 GitHub 库,并关注其他专栏条目。

MLOps:两条蓝色管道的故事

原文:https://towardsdatascience.com/mlops-a-tale-of-two-azure-pipelines-4135b954997?source=collection_archive---------42-----------------------

Azure 上的连续 AI

卢克·范·德·维尔登

目标

MLOps 寻求通过持续集成、持续培训和持续交付机器学习系统来提供新鲜可靠的人工智能产品。当新数据变得可用时,我们更新 AI 模型,并使用 DevOps 实践部署它(如果改进的话)。 Azure DevOps pipelines 支持此类实践,是我们的首选平台。然而,人工智能或机器学习专注于 AzureML ,它有自己的管道和工件系统。我们的目标是在一个端到端的解决方案中结合 DevOps 和 AzureML 管道。我们希望不断训练模型,并有条件地将它们部署在我们的基础设施和应用程序上。更具体地说,我们的目标是持续更新 Azure 函数中运行的 PyTorch 模型。

图片来自 Pexels

解决方案概述

下图显示了我们的目标解决方案。顶部显示了三个触发器。对基础设施代码的更改会触发 Terraform 基础设施管道。对函数的 Python 代码的更改会触发 Azure 函数部署管道。最后,调度上的新数据触发模型训练管道,如果新模型执行得更好,则该管道用新模型进行功能的有条件部署。

DevOps 绿色和青绿色、天蓝色橙色,图片由作者提供

1 个 DevOps 基础设施管道

在 DevOps 管道中,我们几乎可以组织 Azure 云的任何方面。它们允许可重复和再现的基础设施和应用程序部署。一些关键特征是:

  1. 支持自动化几乎所有的 Azure 服务
  2. 卓越的秘密管理
  3. 与 Azure DevOps 集成,用于团队协作和规划

1.1 管道作业、步骤和任务

DevOps 管道是用 YAML 编写的,有几个可能的组织层次:阶段、作业、步骤。阶段由多个作业组成,作业由多个步骤组成。在这里,我们将重点放在作业和步骤上。每个作业都可以包含一个执行条件,并且它的每个步骤都包含一个特定于某个框架或服务的任务。例如,部署基础设施的地形任务或者管理秘密的 Azure KeyVault 任务。大多数任务需要一个链接到我们 Azure 订阅的服务连接,才能被允许访问和更改我们的资源。在我们的例子中,我们使用 Azure CLI 任务完成的身份验证,使用正确的凭证运行 Python 脚本,以与我们的 AzureML 工作区进行交互。

1.2 基础设施即代码

使用 Terraform 和 Azure Resource Manager 之类的工具来管理我们的基础设施有很好的理由,我们将尽量不在这里重复。对我们来说重要的是,这些工具可以从我们的 DevOps 管道中重复启动,并且总是导致相同的结果基础设施(幂等)。因此,我们可以经常启动基础设施管道,而不仅仅是在基础设施代码发生变化时。我们使用 Terraform 来管理我们的基础设施,这需要适当的服务连接。

以下 Terraform 定义(代码 1)将使用其存储帐户和标准应用服务计划创建一个函数应用服务。我们将它包括在内,因为记录的 Linux 示例对我们不适用。对于完整的无服务器优势,我们能够部署在一个消费计划(弹性)上,但是用于 Terraform 的 azurerm provider 似乎有一个干扰性的 bug,阻止我们在这里包括它。为简洁起见,我们没有包括应用 Terraform 的 DevOps 管道步骤,而是参考了相关的文档。

# Code 1: terraform function app infrastructure
resource "azurerm_storage_account" "torch_sa" {
  name                     = "sa-function-app"
  resource_group_name      = data.azurerm_resource_group.rg.name
  location                 = data.azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}resource "azurerm_app_service_plan" "torch_asp" {
  name                      = "asp-function-app"
  location                  = data.azurerm_resource_group.rg.location
  resource_group_name       = data.azurerm_resource_group.rg.name
  kind                      = "Linux"
  reserved                  = truesku {
    tier = "Standard"
    size = "S1"
  }
}resource "azurerm_function_app" "torch" {
  name                      = "function-app"
  location                  = data.azurerm_resource_group.rg.location
  resource_group_name       = data.azurerm_resource_group.rg.name
  storage_account_name       = azurerm_storage_account.torch_sa.name
  storage_account_access_key = azurerm_storage_account.torch_sa.primary_access_key
  app_service_plan_id       = azurerm_app_service_plan.torch_asp.id
  storage_connection_string = 
  os_type                   = "linux"
  version                   = "~3"

  app_settings = {
    FUNCTIONS_EXTENSION_VERSION = "~3"
    FUNCTIONS_WORKER_RUNTIME = "python"
    FUNCTIONS_WORKER_RUNTIME_VERSION = "3.8"
    APPINSIGHTS_INSTRUMENTATIONKEY = "<app_insight_key>"
  }
  site_config {
    linux_fx_version = "PYTHON|3.8"
  }
}

2 AzureML 管道

除了 Databricks 和传统的 HDInsight 集群,AzureML 是在 Azure 上进行数据科学的方法之一。我们使用 Python SDK for AzureML 来创建和运行我们的管道。在 AMLCompute 目标上设置 AzureML 开发环境和运行训练代码我在这里解释。在那篇博客的第 2 部分中,我描述了 AzureML 环境和估计器,我们将在接下来的章节中使用它们。AzureML 管道将预处理与估算器结合起来,并允许使用 PipelineData 对象进行数据传输。

一些好处是:

  • 可复制人工智能
  • 重用数据预处理步骤
  • 管理步骤之间的数据依赖关系
  • 注册 AI 工件:模型和数据版本

2.1 管道创建和步骤

我们的估算器包装了一个 PyTorch 训练脚本,并向它传递命令行参数。我们通过用 EstimatorStep 类(代码 2)包装管道来添加一个估计器。

# Code 2: wrap estimator in pipeline step
from azureml.core import Workspace
from azureml.pipeline.steps import EstimatorStep

from tools import get_compute
from model import train_estimator

workspace = Workspace.from_config()
model_train_step = EstimatorStep(
    name="train model",
    estimator=train_estimator,
    estimator_entry_script_arguments=[],
    compute_target=get_compute(workspace, CLUSTER_NAME),
)

为了创建一个 AzureML 管道,我们需要传入实验上下文和一个按顺序运行的步骤列表(代码 3)。我们当前估算器的目标是向 AzureML 工作空间注册一个更新的模型。

# Code 3: create and run azureml pipeline
from azureml.core import Experiment, Workspace
from azureml.pipeline.core import Pipelinedef run_pipeline():
    workspace = Workspace.from_config()
    pipeline = Pipeline(
        workspace=workspace, 
        steps=[model_train_step, model_evaluation_step]
    )
    pipeline_run = Experiment(
        workspace, EXPERIMENT_NAME).submit(pipeline)
    pipeline_run.wait_for_completion()

2.2 模型工件

PyTorch(和其他)模型可以用 Model 类序列化并注册到 AzureML 工作区。注册一个模型将它上传到集中的 blob 存储,并允许它以 Docker 容器的形式发布到 Azure Docker 实例和 Azure Kubernetes 服务。我们希望保持简单,将 AzureML 模型注册视为工件存储。我们的估计器步骤加载一个现有的 PyTorch 模型,并根据新获得的数据对其进行训练。每次管道运行时,这个更新的模型都以相同的名称注册(代码 4)。型号版本会自动递增。当我们在没有指定版本的情况下检索我们的模型时,它将获取最新的版本。在每次模型迭代中,我们决定是否要部署最新的版本。

# Code 4: inside an azureml pipeline step
import torch
from azureml.core import RunMODEL_PATH = "./outputs/model.p"updated_model = train_model(model, data)
torch.save(updated_model, MODEL_PATH)run_context = Run.get_context()
run_context.upload_file(model_path, model_path)run_context.register_model(
    model_name="pytorch_model",
    model_path=model_path,
    description=f"updated model: {run_context.run_id}",
)

3 结合 AzureML 和 DevOps 管道

3.1 DevOps 以管道为中心的架构

在我们的 MLOps /连续人工智能方法中,DevOps 渠道处于领先地位。它比 AzureML 管道有更好的秘密管理和更广泛的功能。当新数据可用时,DevOps 管道启动 AzureML 管道,并等待它完成是否部署模型的条件决策。这个决定是基于该模型与以前的最佳模型相比的性能。当使用 cron 触发器预期有新数据时,我们定期调度模型 DevOps 流水线。

DevOps 绿松石、天蓝色橙色,图片由作者提供

3.2 从 DevOps 启动 AzureML

Azure CLI 任务使用我们的服务连接对任务进行身份验证,该服务连接可以访问我们的 AzureML 工作区。Python 脚本使用这种访问来创建工作空间和实验上下文,以允许我们使用 AzureML SDK 运行管道。我们等待 AzureML 管道完成,超时时间可配置。DevOps 总超时时间为 2 小时。博客的最后讨论了这一点的含义。显示了一个基本的 Python 脚本(代码 5),它从代码 3 开始启动 AzureML 管道。

# Code 5: calling our run function form Code 3
from aml_pipeline.pipeline import run_pipelinerun_pipeline()

这个脚本从 AzureCLI 任务(代码 6)启动,用于所需的身份验证。注意:我们需要一个拥有 Azure 订阅级别权限的帐户来与 AzureML 交互,即使是最基本的操作,比如下载模型,这并不理想。

# Code 6: launch the azureml pipeline with a devops task
- task: AzureCLI@2
  name: 'amlTrain'
  displayName: 'Run AzureML pipeline'
  inputs:
    azureSubscription: $(serviceConnection)
    scriptType: bash
    scriptLocation: inlineScript
    inlineScript: 'python run_azure_pipeline.py'
    workingDirectory: '$(System.DefaultWorkingDirectory)/aml_pipeline'

3.3 devo PS 中的条件模型部署

根据定义,用最新数据训练的更新模型不会表现得更好。我们想根据最新型号的性能来决定是否部署它。因此,我们希望传达我们将模型从 AzureML 部署到 DevOps 管道的意图。为了向 DevOps 上下文输出一个变量,我们需要向 Python 脚本的 stdout 中写入一个特定的字符串。

在我们的实现中,AzureML 管道中的每一步都可以通过创建以下本地空文件“outputs/trigger”来触发部署。“输出”目录是特殊的,Azure 自动将其内容上传到中央 blob 存储,可通过 PipelineRun 对象和 ML studio 访问。AzureML 管道完成后,我们检查 PipelineRun 中的步骤是否存在触发文件(代码 7)。基于此,输出变量作为任务输出变量写入 DevOps 上下文(代码 7)。

# Code 7: expanded run function with devops output variable
def run_pipeline():
    workspace = Workspace.from_config()
    pipeline = Pipeline(
        workspace=workspace, 
        steps=[model_train_step, model_evaluation_step]
    )
    pipeline_run = Experiment(
        workspace, EXPERIMENT).submit(pipeline)
    pipeline_run.wait_for_completion()

    deploy_model = False
    steps = pipeline_run.get_steps()
    for step in steps:
        if "outputs/trigger" in step.get_file_names():
            deploy_model = True
    if deploy_model:
        print("Trigger model deployment.")
        print("##vso[task.setvariable variable=deployModel;isOutput=true]yes") else:
        print("Do not trigger model deployment.")
        print("##vso[task.setvariable variable=deployModel;isOutput=true]no")

4 将模型和代码部署到 Azure 功能

4.1 有条件开发运维部署作业

我们已经培训了一个新模型,并希望部署它。我们需要一个 DevOps 作业来处理部署,它根据我们的 AzureML 培训管道的输出有条件地运行。我们可以访问上面描述的输出变量,并在作业的条件子句中执行等式检查。下面的代码 8 显示了在部署作业的情况下,我们如何从前面的训练作业中访问任务输出变量。

# Code 8: Conditional deploy job based on train job output
- job: deploy_function
  dependsOn: train
  condition: eq(dependencies.train.outputs['amlTrain.deployModel'], 'yes')
...

4.2 检索最新型号版本

为了从 AzureML Workspace 中检索最新的模型,我们使用 Azure CLI 任务来处理所需的身份验证。在其中,我们运行一个 Python 脚本,该脚本附加到我们的 AzureML 工作区,并在保存我们的函数的目录中下载最新的模型(代码 9)。当我们部署我们的函数时,这个脚本被调用来用我们的 Python 代码和需求打包我们的模型(代码 10,任务 3)。因此,每个模型版本都意味着一个功能部署。

# Code 9: retrieve latest model for devops deployment of function
import os
import shutilfrom azureml.core import Model, WorkspaceMODEL_NAME = "pytorch_model"workspace = Workspace.from_config()
model_path = Model.get_model_path(MODEL_NAME, _workspace=workspace)os.makedirs("./model", exist_ok=True)
shutil.copyfile(model_path, "./model/model.p")

4.3 将模型和代码部署到我们的功能应用程序

azure-functions-core-tools 支持功能应用的本地开发和部署。对于我们的部署,函数构建代理用于安装 Python 需求并将包复制到函数应用程序。有一个专门的 DevOps 任务用于功能部署,你可以探索一下。目前,我们在 DevOps 构建代理(Ubuntu)上安装 azure-functions-core-tools 并使用它发布我们的功能(代码 10,步骤 5)有了更好的体验。

# Code 10: devops pipeline template for function deployment
parameters:
  - name: serviceConnection
    type: string
  - name: workingDirectory
    type: string
  - name: funcAppName
    type: stringsteps:
  - task: UsePythonVersion@0
    inputs:
      versionSpec: '3.8'
  - task: Bash@3
    displayName: 'Install AzureML dependencies'
    inputs:
      targetType: inline
      script: pip install azureml-sdk
  - task: AzureCLI@2
    displayName: 'package model with function'
    inputs:
      azureSubscription: ${{ parameters.serviceConnection }}
      scriptType: bash
      scriptLocation: inlineScript
      inlineScript: 'python ../scripts/package_model.py'
      workingDirectory: '${{ parameters.workingDirectory }}/torch_function'
  - task: Bash@3
    displayName: 'Install azure functions tools'
    inputs:
      targetType: inline
      script: sudo apt-get update && sudo apt-get install azure-functions-core-tools-3
  - task: AzureCLI@2
    displayName: 'publish and build the function'
    inputs:
      azureSubscription: ${{ parameters.serviceConnection }}
      scriptType: bash
      scriptLocation: inlineScript
      workingDirectory: '${{ parameters.workingDirectory }}/torch_function'
      inlineScript: func azure functionapp publish ${{ parameters.funcAppName }} --python

讨论

在这篇博客中,我们展示了一个管道架构,它支持 Azure 上的连续人工智能,只需要最少的移动部件。我们遇到的其他解决方案添加了 Kubernetes 或 Docker 实例来发布 AzureML 模型,供面向前端的功能使用。这是一个选项,但是它可能会增加您团队的工程负荷。我们确实认为添加数据块可以通过协作笔记本和更多的交互式模型培训来丰富我们的工作流程,尤其是在项目的探索阶段。AzureML-MLFlow API 允许您从 Databricks 笔记本中注册模型,并在那时挂钩到我们的工作流。

全模型训练

我们的重点是增量更新的模型训练,训练时间以小时或更少来衡量。当我们考虑以天为单位的完整模型训练时,流水线架构可以扩展到支持非阻塞处理。如上所述,数据砖块可以是 GPU 上的平台全模型训练。另一个选择是使用 Azure Datafactory 运行 AzureML 管道,这适合于长时间运行的数据密集型作业的编排。如果经过训练的模型被认为是可行的,则可以触发后续的 DevOps 管道来部署它。一个低技术含量的触发选项(具有有限的身份验证选项)是与每个 DevOps 管道相关联的 http 端点。

用例

人工智能不是我们方法的唯一用例,但它是一个重要的用例。相关的用例是在 streamlit 上运行的交互式报表应用程序,它可以包含必须更新的知识表示。机器学习模型、交互式报告和来自数据湖的事实协同工作,以通知管理层或客户并导致采取行动。感谢您的阅读。

原载于https://codebeez . nl

MLOps:建立持续的培训和交付渠道

原文:https://towardsdatascience.com/mlops-building-continuous-training-and-delivery-pipelines-6d03fc86cf0e?source=collection_archive---------48-----------------------

JJ·英在 Unsplash 上的照片

你会学到什么

这篇文章旨在帮助你开始构建健壮的、自动化的 ML 管道(在预算范围内!)用于自动重新训练、跟踪和重新部署您的模型。它包括:

  • MLOps 运动的起源和目标概述;
  • 介绍几个关键的 MLOps 概念:
  • 使用 GitHub 操作和 Google Cloud 功能设置持续培训/持续交付(CT/CD) ML 管道的教程。

教程部分旨在利用免费(或几乎免费的 T2)服务,所以跟随它最多花你几便士。如果您正在开发一个 MVP,并且需要一些 ML 基础设施,但是想要避免 AWS SageMaker 或 Azure ML 部署的价格和技术开销,您可能会发现这个例子也很有用。最后,如果你有兴趣了解教程是如何组合起来为你自己端到端地运行它的,你应该看看本系列中关于将轻量级 ML 模型部署为无服务器函数的前一篇文章。

和往常一样,对于那些想要深入了解代码的人来说,请查看这里的 GitHub 工作流文件(.github/workflows/pipeline.yml):

[## markdouthwaite/无服务器-scikit-learn-demo

一个提供演示代码的存储库,用于部署基于轻量级 Scikit-Learn 的 ML 管道心脏病建模…

github.com](https://github.com/markdouthwaite/serverless-scikit-learn-demo)

如果你知道什么是 ML Ops,只是想按照教程,请随意跳过。

什么是 MLOps?

在过去十年左右的时间里,通常被称为“DevOps”的运动已经在软件工程领域获得了大量的专业追随者,大量专门的 DevOps 角色在世界各地的开发团队中涌现出来。这一运动的动机是将软件开发(Dev)的各个方面与操作(Ops)软件活动的元素相结合,目的是在持续的基础上加速可靠的、工作的软件的交付。

DevOps 运动支持者的一个主要关注点是建立和维护持续集成和持续交付(CI/CD)管道。在实践中,设计良好且实施干净的 CI/CD 管道为团队提供了持续修改其软件系统的能力,以(原则上)显著减少新软件补丁和功能的价值实现时间,同时最小化与发布这些补丁和功能相关的错误和中断带来的负面风险。运行这种交付机制的成熟实现的团队通常每小时发布一次更新(或者更快!)能够在变更引入 bug 时快速、干净地回滚变更(尽管大多数这些应该在管道中的某个地方被捕获)。

相比之下,发布软件的“传统”方法本质上是为预定义的发布窗口(可能是每周、每月或每季度)储备补丁和特性。虽然这种方法并不是一致认为一个糟糕的方法,但它确实在发布窗口周围引入了很多压力,会在产品集成和发布过程周围产生很多复杂性,并最终增加了严重服务中断的风险,进而损害品牌。

这和机器学习有什么关系?

在这一点上,你很可能会想‘这一切都很好,但这与机器学习有什么关系?’。就像成功的商业软件产品一样,成功的商业机器学习(ML)项目需要ML 服务的用户信任他们消费的服务的有效性稳定性。重要的是,这必须持续进行——可能一次持续数年。

因此,临时模型培训和评估活动需要大量人工干预,类似于数据科学团队的“传统”软件交付流程——这在数据科学领域是司空见惯的——可能会给服务的生命周期带来严重的技术和业务风险,应被视为特别有害的技术债务形式。

与成功的商业软件产品非常相似,成功的商业机器学习(ML)项目要求 ML 服务的用户信任他们所消费的服务的有效性稳定性

这就是 MLOps 的用武之地。这个新生的运动可以被视为 DevOps 运动的超集:它的目标是在持续的基础上加速可靠的、工作的 ML 软件的交付。因此,它以与 DevOps 非常相似的方式关注 CI/CD 管道,但也增加了这些 CI/CD 问题的特定变化。最值得注意的是,持续培训(CT)的概念被加入到组合中。你问 CT 是什么?

这里的目标是允许 ML 从业者快速自信地将他们最新最好的模型部署到生产中,同时保持依赖它们的服务的稳定性。

入门指南

ML 世界越来越认识到需要有能力自主开发和部署“生产级”ML 解决方案的团队——特别是在以产品为中心的 ML 应用中——以及由此产生的拥有组织孤立的 ML/技术能力的潜在技术(和商业)风险。在许多方面,这与更广泛的软件工程社区认识到“传统”软件应用程序的类似需求(和风险)的知识是一致的。

与之前更广泛的软件工程生态系统一样,ML 工具链正在商品化:进入门槛(成本、专业知识)正在逐渐降低,市场竞争越来越激烈。

这种认识导致了一个围绕上述许多问题的新兴生态系统。每个月都有新的工具和平台推出,明确针对 ML/MLOps 挑战。正如之前更广泛的软件工程生态系统一样,ML 工具链正在商品化:进入壁垒(成本、专业知识)正在逐渐降低,市场竞争越来越激烈。对于那些希望开始使用 MLOps(或一般意义上的 ML)的人来说,这是一个非常令人兴奋的参与时机:你可以花很少的成本走很长一段路来拥有“生产就绪”的 ML 管道。以下是方法。

创建 ML 管道

好了,该上教程了!

这里展示的 ML 管道是使用 GitHub 的工作流自动化工具 GitHub Actions 构建的。如果你注册了 GitHub 账户,你就可以免费使用这个功能。有使用和资源限制(如你所料),但是作为一个免费软件,这些限制出奇的慷慨。如果你能保持你的模型相对轻量级,你可以单独在免费提供的基础上构建一个小产品,所以对于那些有一些很酷的 MVP 想法的人来说,这可能是一个很好的起点。另外,如果免费资源不能满足你的需求,你也可以创建“自主”行动。

那么这里给出的管道示例将会做什么呢?该管道将是一个基本的 CT/CD 管道,构建在上,即上一篇文章中讨论的无服务器 ML 示例之上。如果你还没有读过,值得一读:

* [## 无服务器 ML:大规模部署轻量级模型

将 ML 模型作为可伸缩的 API“部署到生产中”可能会很棘手。这篇文章着眼于一个选择,使模型…

走向科学,来吧](/serverless-ml-deploying-lightweight-models-at-scale-886443d88426)

具体而言,管道将:

  1. 设置您的环境并安装依赖项。
  2. 下载数据集的最新可用版本。
  3. 在最新数据集上训练和评估模型的新版本。
  4. 上传新模型和评估结果。
  5. 如果前面的步骤成功,那么触发新模型作为 API 的重新部署。

此外,您将看到如何安排这个工作流作为cron作业定期运行(再次使用 GitHub 操作)。

开始之前

如果您想运行管道(和代码示例),您需要注册一个 Google Cloud 帐户。在撰写本文时,您的帐户中将增加 300 美元的信用点数。这将比在本教程中运行代码的成本更多(无论如何,这基本上是免费的!).您可以在此找到更多信息:

[## GCP 免费等级免费扩展试用和永远免费|谷歌云

20 多种免费产品免费体验热门产品,包括计算引擎和云存储,最高可达…

cloud.google.com](https://cloud.google.com/free)

接下来,你应该创建一个库的 到你的个人 GitHub 账户。完成这些后,您需要设置几个 GitHub 秘密来允许您的管道访问您的 Google 云服务。你可以在 GitHub 文档中找到如何设置秘密。具体来说,您需要添加:

  • GCP_PROJECT_ID -唯一的谷歌云项目 ID。你可以在谷歌云控制台找到你的项目 ID。如果您不确定,Google 提供了一个找到这个值的文档。
  • GCP_SA_KEY -服务账户(SA)密钥。这是一个安全密钥,用于访问项目中的特定云服务。在本例中,为了简单起见,您将使用一个具有提升权限的默认 SA。在实践中,您应该考虑创建一个特权减少的服务协议。您需要为您的 SA 创建一个新密钥,并将其作为一个秘密复制到 GitHub。同样, Google 有一个关于如何生成这个密钥的详细文档。

注意:和机密/安全信息一样,不要和任何人分享你的 SA 密钥!理想情况下,当您完成这个示例时,删除它(当然,除非您想在自己的项目中继续使用它)。

设置好之后,你需要启用你的谷歌云构建、云功能和云存储 API。要做到这一点,只需浏览谷歌云控制台左侧的导航栏,并选择相关的云服务。如果相关的 API 没有被激活,当你点击服务的时候,你可以选择激活它。

最后,在下面的管道定义中,您需要在您的 Google 云存储中定义一个唯一的bucket 名称。示例管道定义(如下)中使用的名称是pipeline-example。您应该在分叉之后,但在尝试运行示例之前,用您自己的 bucket 的名称替换它。此外,您会想要将存储库中的datasets/default.csv数据集上传到{your-bucket-name}/heart-disease/dataset.csv

现在,不管是好是坏,是时候来点 YAML 了——云的语言。

管道定义

管道被定义为 YAML 文件。如果你想看得更透彻,你也应该看看 GitHub 的工作流文件格式介绍。如果你喜欢 YAML,这可能很容易做到,但不管怎样,下面是它的分解方式:

0.作业设置和调度

文件的这一部分将工作流命名为Train and Deploy(这将是 GitHub 在 GitHub UI 中显示您的工作流的方式),然后提供将触发您的管道运行的事件触发器。在这种情况下,您会看到有两个触发器:pushschedule

push的情况下,管道将在每次更新您的存储库的master分支时运行(具体的分支可以在branches字段中列出)。实际上,这意味着每次您将存储库中的代码变更合并到master中时,管道将重新训练模型并重新部署它。这对于将代码变更立即传播到活动的 ML 服务是非常有用的。

对于schedule触发器,您只需为您的管道设置一个cron运行时间表。换句话说:管道运行的固定时间表。下面提供的示例值将在每个工作日早上 08:00 运行管道。如果你不确定如何配置一个cron时间表,这里有一个很棒的交互式编辑器供你使用。

name: Train and Deploy

on:
  push:
    branches:
      - master
  schedule:
    - cron:  '0 8 * * MON-FRI'

随意摆弄其他触发器。此外,你也可以编写自定义触发器,如果你觉得有趣的话。这些自定义触发器可以帮助您建立一个“真正的”事件驱动架构。只是一个想法。

1.环境设置

现在是无聊但非常重要的一步。键train定义了步骤的名称。在这里你有一个单一的工作。在这里,您必须定义将要运行作业的虚拟机(runs-on)。在这个例子中,我们使用了ubuntu-latest。接下来,定义作业中的每个steps

第一,actions/checkout@v2跑了。这将运行 GitHub 提供的checkout动作。这将克隆并检出您的存储库的默认(通常是master)分支。

接下来,作业设置gcloud 命令行工具。这一步使用 Google Cloud 提供的动作让你的生活变得更简单。这允许后续步骤访问gcloudgsutils命令行工具。稍后,您将使用这些工具从/向 Google Cloud 下载/上传数据,并重新部署您的模型 API。

在这之后,您有两个 Python 相关的步骤。第一部分设置了一个基本的 Python 3.7 环境。第二步安装顶层requirements.txt文件中的所有依赖项。这样,您的工作就可以正确地运行您的管道了。现在是有趣的部分。

train:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2

    - name: Setup GCP client
      uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
      with:
        version: '290.0.1'
        project_id: ${{ secrets.GCP_PROJECT_ID }}
        service_account_key: ${{ secrets.GCP_SA_KEY }}
        export_default_credentials: true

    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: 3.7

    - name: Install Python dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt

请注意,run键允许您在虚拟机的 shell 中执行命令——这里是默认的 Ubuntu shell。

2.下载数据集

首先,作业从pipeline-example桶下载最新的可用数据集。在实践中,管道将在提供的路径上获得最新版本的数据集。这允许您创建一个独立于数据管道来加载和转换数据集,以便 ML 管道在下次运行时拾取。

- name: Download the latest dataset
      run: |
        gsutil cp gs://pipeline-example/heart-disease/dataset.csv datasets/default.csv

你会看到该步骤使用了gsutil,谷歌的云存储命令行实用程序。这让你可以从谷歌云复制文件。简单!

3.训练和评估模型

现在作业已经加载了最新的数据集,是时候运行“核心”训练任务了。在这种情况下,这与前面的无服务器 ML 教程中给出的例子相同。

- name: Run training task
      run: |
        python steps/train.py --path=datasets/default.csv

另外,steps/train.py脚本将以下元数据和指标写入artifacts/metrics.json路径。正如您将看到的,这也会上传到 Google Cloud,因此您可以查看模型性能(和训练持续时间)如何随时间变化。这可以派上用场!

metrics = dict(
    elapsed = end - start,
    acc = acc,
    val_acc = val_acc,
    roc_auc = roc_auc,
    timestamp = datetime.now().strftime(TIMESTAMP_FMT)
)

新训练的模型被写入artifacts/pipeline.joblib。这也将上传到谷歌云存档。

4.上传模型和指标

下一步是将您的新模型和指标推送到 Google 云存储。您将看到管道上传了三个文件:

  • latest.joblib——这款车型的‘最新’版本。这将是管道生产的最新“有效”模型。
  • ${{ env.GITHUB_RUN_ID }}.joblib -上述模型的存档版本(由生产它的唯一 GitHub 运行 ID 标识)。
  • metrics/${{ env.GITHUB_RUN_ID }}.json -上述模型指标的存档版本(由产生它的唯一 GitHub 运行 ID 标识)。可以按创建日期对它们进行排序,以生成显示模型性能随时间变化的时间序列。
- name: Upload new model and associated metrics
      run: |
        gsutil cp artifacts/pipeline.joblib gs://pipeline-example/heart-disease/models/latest.joblib
        gsutil cp artifacts/pipeline.joblib gs://pipeline-example/heart-disease/models/${{ env.GITHUB_RUN_ID }}.joblib
        gsutil cp artifacts/metrics.json gs://pipeline-example/heart-disease/models/metrics/${{ env.GITHUB_RUN_ID }}.joblib

现在你有了一个新的模型,一些指标,所有这些都整齐地存档在谷歌云存储中。

5.重新部署云功能

最后,完成所有这些工作后,是时候重新部署您的最新模型了。

- name: Deploy model as Cloud Function
      run: | 
        gcloud functions deploy heart-disease --entry-point=predict_handler --runtime=python37 --project=${{ secrets.GCP_PROJECT_ID }} --allow-unauthenticated --trigger-http

这将触发您的模型的云功能与您的最新模型一起重新部署。如果你想了解传递给gcloud的参数是做什么的,请确保查看本系列的前一篇文章。几分钟后,你的新型号将被投入使用。

收尾工作

仅此而已。如果您的管道成功完成,您将能够为每个成功的步骤看到一个漂亮的绿色勾号列表。

现在,您已经有了一个自动化的管道来加载新数据、重新训练模型、归档新模型及其指标,然后按照固定的时间表重新部署您的模型 API。很酷,是吧?

后续步骤

这只是一个婴儿 ML 管道。你可以做很多事情让它变得更复杂。一些初步想法可能是:

  • 创建一个云函数,当模型性能下降到给定值以下时,它会在上传模型指标时触发,以通知您(可能通过 Slack 或电子邮件)。
  • 如果评估结果比先前的模型(或者一些测试用例)更差,添加一个步骤来中止模型重新部署。
  • 添加自定义云函数触发器,以便在数据集更新时运行工作流(而不是在固定的基础上运行,这可能是不必要的)。
  • 添加一个 StreamLit 控制面板,以便随时查看模型和指标。

如果你有任何问题,请随时联系我们!

进一步阅读

如果您有兴趣了解更多关于 MLOps 的信息,以下是一些您可能会感兴趣的链接:

原载于https://mark . douthwaite . io*。**

MLOps:即将到来的闪亮之星

原文:https://towardsdatascience.com/mlops-the-upcoming-shining-star-dcf9444c493?source=collection_archive---------10-----------------------

构建全栈机器学习系统的正确路径。MLOps 是简化 ML 生命周期管理的新兴实践。

为什么我不应该优先考虑建立“完美模型”呢?

在进一步阅读之前,我建议你先看一下这篇文章。它详细讨论了所有相关的问题。

开发 ML 应用程序时通常会遇到的主要障碍有:

生产机器学习模型的当前挑战

复杂模型抽象边界

传统的软件工程实践表明,使用封装和模块化设计的强大抽象边界有助于创建可维护的代码,在这些代码中很容易进行单独的更改和改进。但是在 ML 的情况下,执行严格的动作变得困难,因为它依赖于外部数据。

数据依赖

数据依赖比代码依赖花费更多

在数据科学家沙盒中,将数据输入培训和评估阶段完成的步骤在现实场景中可能会有很大不同。根据用例,数据随时间变化和缺乏规律性会导致 ML 模型性能不佳。

简单到复杂的管道

训练一个简单的模型,并将其用于推理和生成预测是获得业务洞察力的简单方法,但这是不够的。在现实世界中,需要规律性,时间模型需要根据从数据湖中提取的新数据进行重新训练。因此,将会有许多模型&由人来决定选择哪一个模型用于生产。在联邦管道中,维护变得更加困难。

配置债

任何大型系统都有广泛的可配置选项,包括使用哪些功能、如何选择数据、各种算法特定的学习设置、潜在的预处理或后处理、验证方法等。在一个正在积极开发的成熟系统中,配置的行数可以远远超过传统代码的行数。每个配置行都有可能出错。

再现性债务

我们可以重新运行实验并获得类似的结果是很重要的,但设计真实世界的系统以实现严格的可重复性是一项艰巨的任务,因为随机化算法、并行学习中固有的非确定性、对初始条件的依赖以及与外部世界的交互。

生产 ML 风险

如果 ML 模型在预期范围内执行,则总是存在 ML 模型不执行的风险,并且需要持续的监控和评估。实时数据指标,如准确度、精确度、召回率等。无法使用,因为实时数据没有标签。

流程和协作

在生产中,ML 需要多种能力来处理生产级 ML 系统,如数据科学家、数据工程师、业务分析师和运营。不同的团队将关注不同的结果。数据科学家将专注于提高准确性和检测数据偏差,业务分析师希望提高 KPI,运营团队希望看到正常运行时间和资源。与数据科学家沙箱不同,生产环境有许多对象,如模型、算法、管道等。难以处理,它们的版本控制是另一个问题,需要对象存储来存储 ML 模型,而源代码控制库不是最佳选择。

什么是 MLOps?

MLOps 建立了一种文化和环境,在这种文化和环境中,ML 技术可以通过优化 ML 生命周期来自动化和扩展 ML 计划以及优化生产中 ML 的商业回报,从而产生商业利益。MLOps 具有数据科学家和服务的混合能力

MLOps 支持不同用户(如数据科学家、数据工程师、业务分析师和 ITOps)在 ML 操作上的协作,并支持 ML 操作对业务应用的影响或 ROI(投资回报)的数据驱动的持续优化。

为什么是 MLOps?

从上面的内容可以很清楚地看出,在人工智能的现代时代,什么是对“MLOps”的需求,什么导致了这种混合方法的兴起。现在从“是什么”前进到“为什么”让我们来解释一下最初导致使用 MLOps 的原因。

多个管道的协调

  • 机器学习模型的开发不是单一的代码文件任务。相反,它涉及不同管道的组合,这些管道各司其职。
  • 预处理、特征工程模型训练和模型推理等主要过程的流水线。参与到机器学习模型发展的大局中。
  • MLOps 在这些多管道的简单编排中起着重要作用,以确保模型的自动更新。

管理 MLOps 的整个生命周期

  • 机器学习模型的生命周期由不同的子部分组成,这些子部分应被单独视为一个软件实体。
  • 这些子部分有自己的管理和维护需求,通常由 DevOps 处理,但使用传统的 DevOps 方法管理它们是一项挑战。
  • MLOps 是一种新出现的技术,它包括人、过程和技术的组合,为快速和安全地优化和部署机器学习模型提供了优势。

扩展 ML 应用

  • 如题目前面所说,模型的开发不是一个需要担心的问题,真正的问题在于规模化的模型管理。
  • 同时管理数以千计的模型是一项非常繁琐和具有挑战性的任务,它测试模型的大规模性能。
  • 通过使用 MLOps,它可以自然地扩展管理生产中数以千计的模型管道。

保持 ML 健康

  • 在 ML 模型部署之后保持 ML 健康是后处理中最关键的部分。这是至关重要的,以便 ML 模型可以操作和管理完美。
  • MLOps 通过自动检测不同的漂移(模型漂移、数据漂移)提供最新的 ML 健康方法。
  • 它可以提供在系统中使用最新的边缘切割算法来检测这些漂移的能力,从而可以在这些漂移开始影响 ML 健康之前避免它们。

持续集成和部署

  • 持续集成和部署是整个唯一的目的之一,这导致了在任何软件产品开发过程中使用 DevOps。
  • 但是由于 ML 模型的可操作性的规模,很难使用用于其他软件产品的持续集成和部署的相同方法。
  • MLOps 可以帮助使用不同的专用工具和技术,以确保 ML 模型领域的持续集成和部署服务。

模型治理

  • 在模型治理下,MLOps 可以通过大规模监控属性来提供丰富的模型性能数据。
  • 它还能够拍摄管道快照,用于分析关键时刻。
  • 此外,MLOps 下的日志记录设施和审计跟踪可用于报告和合规性的连续性。

MLOps 和 DevOps 有什么不同?

  • 数据/模型版本化!=代码版本
  • 模型重用与软件重用完全不同,因为模型需要基于场景和数据进行调整。
  • 当重用一个模型时,需要进行微调。把学习转移到 it 上,这就导致了一个培训管道。
  • 再训练能力需要随需应变,因为模型会随时间衰减。

我们来谈谈全栈机器学习开发,好吗?

因为你可能已经有了要点,但是让我们谈论一些细节。

  • 开发一个 ML 系统不仅仅是开发一个模型,而是更多。配置、数据收集、部署、服务等(如上面的摘要所示)。
  • 因此,为了快速但安全、高度可信但通用、开发友好但生产友好,我们需要在 ML 开发中复制所有软件开发的最佳实践。
  • 正如 DevOps 正在帮助软件开发进入全栈开发一样,MLOps 也将帮助 ML 开发进入全栈 ML 开发。

将 Mlops 纳入 ML 开发将始终确保对 ML 系统的信心。

我将发布一个关于构建正确的全栈式 ML 系统的新系列。我会随时通知你……😃

“你应该永远攀登”MLOps 的 10 条戒律

原文:https://towardsdatascience.com/mlops-thou-shalt-always-scale-10-commandments-of-mlops-152c11e711a5?source=collection_archive---------45-----------------------

对基础设施的十项要求,允许您以持久、轻松和灵活的方式部署 ML 应用程序。

取自 Pixabay

如果你现在从事任何类型的机器学习,并且你曾经想过将你正在研究的人工智能投入生产,那么这篇文章就是为你准备的。无论你是(首席)数据科学家、数据工程师、产品负责人还是其他任何参与机器学习的人,我都可能会读到你对下一个挑战的想法。

假设你的团队已经训练了一个惊人的模型,优化了所有的超参数,并且发布了一些令人印象深刻的预测,如果你可以这么说的话!是时候让它挣脱办公室服务器的枷锁,走出测试版,进入现实世界了。然而,有一件事让你夜不能寐:你如何确保你的 ML-pipeline 在生产中一直平稳运行?您是应该建立自己的服务器,还是最好将其交给外部机构?面对如此多的供应商,您如何确定哪种服务最适合您呢?你绝对需要考虑的事情是什么?

MLOps

你应该考虑的事情被称为 MLOps :这个新兴领域完全专注于封装 ML 模型的基础设施,确保发布到生产顺利进行,没有麻烦。MLOps 也被描述为 ML、DevOps 和数据工程的交集。

机器学习+ DevOps +数据工程的横截面= MLOps。由 UbiOps 设计

虽然这个领域仍然相对较新,但还没有一个适用于所有规模的明确的“最佳实践”。然而,对于 ML 的健壮部署,有一些明显的需求是必要的。为了能够为你的 ML 设计一个架构,重要的是首先要知道它应该有什么能力,以及它在哪里可以使你的生活更容易。无论 ML 应用程序是由复杂的、多面的 ML 体系结构组成,还是由一行代码组成,对 ML 管道基础设施的要求都是一样的。

本文概述了一个流畅的 ML 基础设施的最重要的需求,换句话说:

MLOps 的 10 条戒律

1。汝应始终缩放

这可能是或者应该是一个显而易见的问题,但是仍然是:你的架构应该允许你以一种灵活的方式控制资源。您永远不知道您的管道将来会占用多少(或几个)资源,因此基础设施应该总是适当地(自动地)扩展。这允许您的管道处理波动的数据量/请求数,并且还将防止您在将来必须调整它以更有效或更好地伸缩。此外,由于未使用的资源会自动关闭,因此无需担心为未使用的资源付费。

2。你会安全的

适当的 ML 基础设施的一个非常重要的特征是处理安全性的方式。一些公司甚至认为这是他们选择的关键特征,因为隐私法规变得越来越严格,而且(敏感)数据泄露在你公司的简历上看起来不太好。考虑数据的安全性(将数据上传到云,而不是数据不离开公司服务器),当然也要考虑您宝贵的 ML intel 的安全性。

3。你的目标是标准化

也许 ML 基础设施最容易被忽视的一个方面是,它为您提供了标准化管道部署的机会,与“常规”软件部署没有什么不同。

在软件工程中,有一些关于如何在团队中编写代码的设计模式,一个部署迫使团队走到一起彻底测试和检查代码,从而尽早发现错误并提高整体质量。ML-deployment 不必与众不同,因为它提供了测试和基准测试新管道的机会,并且标准化部署带来了 ML 代码编写和部署的结构。ML 基础设施为您的团队提供了一个以固定方式编写代码的框架,使其在应用程序之间保持一致,这极大地提高了质量并改进了工作流程。最后,标准化部署为自动部署铺平了道路:在上传并通过测试之后,新管道将自动部署到生产中。对于总是需要根据最新数据进行(重新)训练的系统来说,这可能会很方便:为您省去每天早上 05:00 手动部署管道的麻烦。

4。尊重您的数据集成

基础设施应该毫不费力地与您现有的数据管道和存储集成。在大多数情况下,进出管道的数据迁移越少越好。将数据存储在正在处理的地方不仅节省了时间和金钱,还最大限度地降低了数据泄露的风险。如果这根本无法实现,基础架构应该能够轻松集成到您现有的数据工程管道中,并且应该提供足够的选项来连接到您的存储。

5。你不应该低估监控的重要性

正如模型/管道在训练时很重要一样,在生产过程中监控其性能对于保持结果的绿色性仍然至关重要。我不仅谈论 ML 指标,如准确性和 F1 分数,还谈论基础设施性能指标,如延迟(运行请求时基础设施增加的时间)和错误:我的所有管道都可用吗,或者有错误吗?如果处理一个请求的时间突然从 0.01 秒上升到 52 秒,这表明有问题。数据科学团队和 IT 部门应该能够对管道进行监控,因为这两个部门在维护系统健康方面都扮演着重要角色。

6。你应该灵活选择软件和编程语言

如果您选择接受基础设施提供商提供的服务,请确保检查他们支持什么软件。没有什么比被供应商锁定,却发现自己选择的软件包或语言不受支持更令人沮丧的了。您的代码应该决定基础结构,而不是相反。基础设施是否非常僵化,是否只允许供应商预先选择的包?或者在 Python 模型和基于 R 的模型之间切换就像点击按钮一样简单吗?

7。您将拥有零停机发布

在应用程序不停机的情况下部署 ML-pipelines 听起来是不是像一个梦?有了好的 MLOps 基础设施,就触手可及。如果您的基础架构允许多个相同的环境并行运行,这是可以实现的。生产管道将在生产环境中运行,同时可以对在测试环境中运行的模型进行测试和调整。然后,当截止日期到来时,部署一个新版本只需切换环境,停机时间最少甚至根本不用停机。这同样适用于管道中重新训练的模型:基础设施应该只允许您用重新训练的模型替换旧的模型,并保持其余的模型不变,而不会中断通过管道的数据流。

8。你应该有版本控制和数据沿袭追踪

这一点与您的管道的监控有关(戒律 5),但是有一个区别:监控允许您查看性能是否以及何时下降,版本控制/数据沿袭跟踪允许您准确地查明是哪个模型版本或数据批次导致了性能下降。因为 ML 应用程序经常将代码、模型和数据交织在一起,所以跟踪代码+模型和数据是很重要的。此外,这将使并排比较不同版本的模型变得更加容易。

9。考虑你的复杂性/透明度

优秀的 MLOps 基础设施的一个指标是它是否将复杂的(云)基础设施抽象化,以便即使没有太多基础设施知识的人也可以轻松部署模型。然而,它也不应该是这样一个“黑箱”,当错误发生时,没有办法告诉什么是错的,为什么。深入了解基础设施的内部流程是调试问题的必要条件。因此,透明度和复杂性之间的适当平衡至关重要。如果您的 ML 基础设施依赖于外部服务提供商,请确保检查是否有日志记录系统,该系统可以指示内部正在发生的事情。

10。你应该有低延迟

这取决于您的使用情形,但如果实时预测是必要的,则不能有 15 秒的基础架构相关延迟。基础设施的延迟通常取决于模型/管道如何在内部存储和旋转,如何检索数据,以及如何再次返回结果。一定要检查应用程序上基础设施的额外延迟,因为不同服务之间的延迟可能会有很大差异。

由 UbiOps 制定的 MLOps 十诫

作为一名数据科学家,您可能正在阅读这篇文章,并且想知道:“我为什么要关心 MLOps?我已经做出了模型,将它投入生产难道不是 it 团队的工作吗?”对于拥有独立 IT /数据科学部门的大型公司来说,这可能是真的,但对于大多数以数据科学起步的公司来说,现实是设计算法的人也将是部署算法的人,这使得对 MLOps 的良好了解变得非常宝贵。此外,很有可能对方不像你一样了解你的管道以及如何将它部署到生产中。让他们跟上速度需要付出很大的努力,而从一开始就共同努力设计一个好的 MLOps 架构将节省两个部门的时间,并可能减少许多挫折。

您的基础设施是否为您服务?

在设计或选择 MLOps 基础设施时,需要考虑很多因素,一开始可能会让人不知所措。记住没有业务案例是相同的,重点可以放在部署周期的不同方面,这也是很好的。也许对你的应用程序来说,快速运行比始终可用更重要?或者,只要提供自动化部署,基础架构就不必透明?

无论您的团队是仍处于 ML 应用程序产品化的起步阶段,还是已经有了一个合适的基础设施,考虑一下您的基础设施是否仍然让您的生活变得轻松(或者至少不会比它更困难)总是好的。最佳的 MLOps 基础设施可满足您的需求;您不应该根据基础设施来调整您的需求。基础设施服务提供商的市场仍在不断扩大,当您的服务不符合要求时,最好再看看。

你想和类似的话题保持同步吗?关注 我们的博客 上媒或 网站。

使用功能商店的 MLOps-hops works

原文:https://towardsdatascience.com/mlops-with-a-feature-store-816cfa5966e9?source=collection_archive---------6-----------------------

TLDR;如果人工智能要嵌入到企业计算系统的 DNA 中,企业必须首先重新调整他们的机器学习(ML)开发流程,以包括 ML 资产(特征和模型)的自动化测试、版本控制、治理和存储。这篇博客详细介绍了如何用特性库实现 MLOps 过程。

什么是 MLOps?

MLOps 是一个最近的术语,描述了如何应用 DevOps 原理来自动化 ML 系统的构建、测试和部署。连续交付基金会的 SIG-MLOps 将 MLOps 定义为“DevOps 方法的扩展,将机器学习和数据科学资产作为 DevOps 生态中的一等公民”。MLOps 旨在统一 ML 应用程序开发和 ML 应用程序的操作,使团队更容易更频繁地部署更好的模型。Martinfowler.com 将 MLOps 定义为:
“一种软件工程方法,在这种方法中,跨职能团队基于代码、数据和模型,以小而安全的增量生产机器学习应用程序,这些应用程序可以在短的适应周期内随时重现并可靠发布。”

MLOps 的目标是尽可能快地获得一个完整的工作 ML 系统,并进行增量更改以改进该系统,测试功能和模型,以增强您在不破坏下游模型消费者的情况下进行小更改的能力的信心。

与 DevOps 相比,MLOps 的具体挑战是如何测试、版本化、存储、管理和使用 ML 系统中产生的两个主要资产:特性模型。相比之下,DevOps 关心的主要资产是源代码。

DevOps 与 MLOps

由源代码更改触发的传统 DevOps CI/CD 工作流。

Git 是世界上最流行的源代码版本控制系统。它用于跟踪源代码随时间的变化,并支持不同版本的源代码。对版本控制的支持是自动化和持续集成 (CI)解决方案的先决条件,因为它能够以全自动的方式对任何环境进行可重复的配置。也就是说,我们假设提供环境所需的配置信息存储在版本控制系统中,以及我们将要测试的系统的源代码。通常,在使用 DevOps 时,每次提交 Git 都会触发包的自动创建,只需使用版本控制中的信息就可以将这些包部署到任何环境中。

在许多 DevOps 设置中, Jenkins 与 Git 一起用作自动化服务器,以可控和可预测的方式构建、测试和部署您的版本化代码。Jenkins 遵循的 CI/CD 管道的典型步骤是:提供测试虚拟机(VMs 容器,将代码签出到机器上,编译代码,运行测试,打包二进制文件,以及部署二进制文件。对于 Java,这涉及到运行一个像 maven 这样的构建工具来编译、测试和打包 Java 二进制文件,然后再将二进制文件部署到某个登台或生产系统中。对于 Docker 化的应用程序,这意味着编译 Docker 文件,然后构建 Docker 映像并将其部署到 Docker 注册表中。

MLOps:特征工程和模型训练的 CI/CD 工作流可以由源代码或数据的变化触发。

也许 MLOps 最具定义性的特征是需要管理数据和代码,以便为训练模型提供可重现的工作流。Git 不适合作为对大量数据进行版本控制的平台。

然而,Git 和 Jenkins 对于 MLOps 来说是不够的,在 MLOps 中,构建过程涉及运行复杂的分布式工作流,我们需要**版本化代码版本化数据来确保可复制的自动化构建。但是数据不是管理特征和模型的正确抽象层次。

特征是特征存储中的可变数据 —用于创建特征的新数据应该不断到达,否则使用这些特征进行推理的模型将不再创造任何价值。特征还具有模式、自定义元数据,并且在被模型用于训练或推断之前可能需要特定于模型的转换。(特定于模型的转换发生在特征存储之后(例如标准化一个数字特征),因此特征数据可以更容易地在不同模型之间重用)。特征数据也应该被验证,例如,使用像远大前程这样的框架。

模型是模型注册表中不可变的数据。模型是版本化的,可以通过推理或训练管道安全地下载和缓存。模型还具有用于治理的模式和定制元数据(例如,描述如何以及在哪里可以使用模型)。还应该对模型进行验证,以确保它们在看不见的数据上有足够好的性能,没有偏差(通过测试模型在不同测试数据切片上的表现),并且对非分布特征值具有鲁棒性。

Hopsworks 特征库(和模型注册表)

特性库使您能够将您的整体 ML 管道重构为 3 个管道,每个管道都可以以自己的节奏运行:一个特性管道、一个训练管道和一个推理管道。

功能存储解决了整体式 ML 管道的以下问题:

  • 通过在不同模型中启用功能重用,实现功能的发现和重用;
  • 为相同的特性启用双离线/在线 API:对用于训练和批量推断的特性数据的高吞吐量批量访问,以及对在线模型的特性的低延迟读取;
  • 确保特征、训练和推理管道中转换的一致性——用于计算特征的函数的单个定义在三个不同的管道中重复使用;
  • 确保训练数据中特征的时间点正确性(确保没有数据泄漏);
  • 分离特征、训练和推理管道,以便操作管道(特征、推理)可以以它们自己的节奏运行,并且训练可以按需完成。

F‍eature 管道公司

特征管线与数据管线共享许多相同的最佳实践 DevOps 实践。数据/特征的一些自动测试类型包括:

  • 所有特性化代码的单元测试和集成测试(当代码被推送到 Git 时,Jenkins 可以运行这些测试);
  • 测试特征值是否在预期范围内;
  • 测试特性的唯一性、完整性和独特性;
  • 测试特性分布是否符合您的期望;
  • 测试每个特征和标记之间的关系,以及单个信号之间的成对相关性;
  • 测试每个功能的成本;
  • 测试个人身份信息不会泄露到功能中(自定义测试)。

当特征存储可用时,特征管线的输出存储在特征存储中称为特征组的表中。理想情况下,目标数据接收器将支持版本化数据,例如在 Apache 胡迪的 Hopsworks 功能存储中。在 Hopsworks 中,特征管线将数据向上插入(插入或更新)到现有的特征组中,其中特征组是一起计算的一组特征(通常是因为它们来自相同的后端系统,并且通过一些实体或键相关)。每次为要素组运行要素管道时,它都会在汇胡迪数据集中创建一个新的提交,并且还可能会更新在线数据库中的最新要素值。

模型培训渠道

在模型验证步骤中执行的自动化测试类型包括:

  • 在看不见的数据上测试模型的性能,
  • 测试模型在不同数据切片上的表现以检查偏差,
  • 测试模型对非分布特征值的稳健性。

推理管道—特征监控和预测监控

可以监控特征的漂移——与特征数据的参考窗口相比,特征数据的检测窗口中有意义的(也可能是统计上显著的)变化。类似地,模型预测可以与结果进行比较,以查看预测性能是否有有意义的变化。乔希·托宾很好地描述了在这里寻找什么。

图片来自[https://concept-drift.fastforwardlabs.com/

在上图中,我们可以看到,我们有时可以直观地比较漂移数据的分布。在 Hopsworks 要素存储中,我们仅有的实际数据集是要素组和训练数据集。当一个特征组(或一个特征组的子集)是参考窗口时,我们可以检测特征组漂移。当在其上训练的模型的训练数据集是参考窗口时,我们可以检测模型的特征漂移。**

特征组转移是在数据被写入特征存储之前,模型的特征漂移是为了识别已部署模型的特征分布中的漂移,而概念漂移是为了测试模型的陈旧性。

上图显示了监控基础设施可以识别的三种不同类型的漂移:

  • 特征存储中特征的特征漂移,在特征存储中,我们监控将要写入特征组的特征分布的变化;
  • 已部署模型的特征漂移,其中我们监控模型的推断数据窗口与模型的训练数据的特征分布相比的漂移;
  • 概念漂移模型产生的预测变得越来越差(例如,与模型评估期间相比,您根据看不见的数据评估模型性能)。

摘要

我们现在已经介绍了一个基于 MLOps 原则的端到端 ML 管道和一个特性库。对管道代码或新到达的数据的更新使得变化能够被持续地测试,并且模型能够被持续地更新和部署到生产中。我们展示了特征库如何使整体的端到端 ML 管道分解成特征管道和模型训练管道。我们还讨论了如何利用现代数据湖框架(如 Apache 胡迪)实现数据版本控制。在下一篇博客中,我们将更详细地介绍 ML 管道和可重复实验 Hopsworks,以及如何轻松地将管道从开发环境迁移到生产环境。我们还将展示如何使用 Airflow 开发特征管道和模型训练管道。

Hopsworks 入门

  • app . hops works . ai(5 分钟后开始)
  • docs.hopsworks.ai
  • www.hopsworks.ai

参考

  • 机器学习的特征库
  • hops works 功能商店
  • 斯卡利等人,你们的 ML 测试成绩是多少?ML 生产系统的规则
  • Baylor 等人,TFX:基于 TensorFlow 的生产规模机器学习平台
  • CDF 特殊兴趣小组— MLOps
  • 机器学习的连续交付

本文于 2020 年 3 月首次发表,并于 2023 年 2 月 21 日进行了大量编辑。这篇文章的原文可以在 逻辑时钟的博客 上找到。

ml type——程序员打字练习

原文:https://towardsdatascience.com/mltype-typing-practice-for-programmers-ae580cce693f?source=collection_archive---------29-----------------------

mltype

mltype 是一个提高打字技巧的命令行工具。它通过一点点深度学习做到了这一点。

如果你点击了这篇文章,希望能学到一些关于静态类型、类型注释或类似的东西,那么这篇文章是不合适的。我在这篇文章中谈论的打字是你用键盘做的事情。或者准确地说

用打字机或计算机写作的行为或技巧。

动机

几个月前,我决定学习触摸打字!我知道你在想什么…"你打字比以前快了吗?所有的痛苦都值得吗?"我肯定会说是和是。然而,互联网上充满了类似的前后推荐书,我不打算写另一个。

我想说的是,我真的很惊讶,用编程语言练习触摸打字的资源如此之少。快速谷歌搜索后,你可能会发现以下网站:

  • http://www.speedcoder.net/
  • 【https://typing.io/

虽然上述网站有多个优点,但让我指出它们的一些缺点

  • 缺乏可变性和惊喜元素
  • 手动选择源文件和相应的行
  • 不可定制
  • 不自由(typing.com)
  • 还不够无聊——难道不能在终端里做吗?

基于上面提到的原因,我决定试一试,自己写一个打字练习软件: mltype

它是做什么的?

简而言之,就是一个命令行工具(用 Python 写的)。它使用神经网络来生成看起来像编程语言(或普通语言)的文本。此外,它还提供非机器学习功能,如从文件或标准输入中读取文本。

如果你想知道它背后是什么样的“神经网络”,我会鼓励你去(重新)读一读安德烈·卡帕西的《循环神经网络的不合理有效性》。mltype 在后台做着或多或少相同的事情。准确的说,有一个字符级的语言模型。它给出了前一个字符在下一个字符上的概率分布。最重要的是,它试图向用户隐藏训练和推理的所有复杂和枯燥的细节。从现有模型生成文本和训练新模型都可以在一个命令中完成。

下面是一些不同编程语言的例子。生成它们的所有模型和许多其他预训练模型都可以下载(参见 github 上的 README.md)。

例子

C++

计算机编程语言

想试试吗?

如果你想了解更多并亲自尝试,请访问下面的链接!

  • github:【https://github.com/jankrepl/mltype
  • 文件:https://mltype.readthedocs.io/en/latest/

浏览器中的 MNIST

原文:https://towardsdatascience.com/mnist-in-the-browser-f03cc4f055a1?source=collection_archive---------53-----------------------

将复杂的人工智能模型部署到浏览器(以及更远的地方)非常容易。

多年来,在实践中使用人工智能模型一直是一个挑战。是的,确实存在许多很好的例子,但根据我们的经验,大多数公司首先面临的挑战是整合数据,然后是构建和验证有用的模型,最后是将这些模型部署到最需要的地方(无论是内部、云中还是边缘)。

然而,在过去几年中,这些挑战变得越来越容易。它们中没有一个是微不足道的,但是这个过程的每一步都有大量的工具。甚至在浏览器中部署相对复杂的卷积神经网络也变得相当简单:让我来分享一下如何实现。

1.训练模型:手写数字识别

为了演示 CNN 在浏览器中的部署,我们选择了一个 CNN 经常擅长的简单任务:图像识别。为了便于演示,我们将重点放在众所周知的 MNIST 数据集上。本教程展示了如何使用微软的认知工具包来训练一个具有相当令人印象深刻的性能的模型。然而,你并不真的需要自己训练模型;在 ONNX 模型动物园可以直接下载ONNX 格式的。

ONNX 是一种开放格式,用于表示机器学习模型。这是存储使用不同工具(pyTorch、tensorflow、sklearn 等)创建的训练模型(包括预处理和后处理)的一种非常统一的方式。).

2.模型转换:易于部署的 WebAssembly。

既然我们已经有了一个经过训练的数字识别模型,我们想在浏览器中直接使用它。这样做的一个选择是使用 javascript ONNX 运行时(ONNX.js) 。然而,我们更喜欢首先将 ONNX 转换成一个 WebAssembly 可执行文件(。WASM)部署前。

虽然 ONNX.js(以及其他边缘设备可用的 ONNX 运行时)可能看起来更容易,但由于跳过了向 WebAssembly 的传输步骤,ONNX 运行时通常比 WASM 运行时大得多,执行起来也更慢(参见 Wasmer 收集)。我们建议感兴趣的读者参考这篇文章,了解 ONNX.js 和 WebAssembly 运行时比较的更多细节。在任何情况下,根据我们的经验,目前可用的(各种)ONNX 运行时在实际(边缘)生产环境中比简单、独立的 WebAssembly 二进制文件更难维护和管理。

scascalable提供了(大部分)ONNX 到。不到一美元的 WASM(前 100 次转换是免费的)。描述转换过程的详细教程可以在这里找到。实际上,它就像上传。ONNX 文件到 web 窗体。

Scailable 目前支持 ONNX 1.3 到。WASM;对 ONNX 1.7(包括 IR 5 和 OPS 13)的支持即将到来。

转换之后,我们得到了一个非常小的(472 Kb) 。WASM 可执行的可以用来进行数字识别。

3.浏览器中的模型部署(带后备)。

在转换到 WebAssembly 之后,CNN 的实际部署是小菜一碟。大多数浏览器支持运行现成的 WebAssembly 和由。这里描述了由 Scailable 创建的 WASM。因此,如果您熟悉 javascript,自己编写I/O 相对容易。然而,使用 Scailable-Webnode 可能更容易;最低限度。将运行的 WASM 运行时。WASMs 由 Scailable 尽可能在浏览器中创建,如果浏览器不支持 WebAssembly,则在云中创建。

将所有这些放在一起,我们得到了以下实现:

实现出人意料地精简和快速,并且模型的性能不相上下。你可以在这里尝试一下(显然,查看该页面的源代码,看看 UX 是如何完成的)。

包裹

像 ONNX 这样的中间表示,以及像 WebAssembly 这样有效、快速和可移植的编译目标,正在缓慢但肯定地改变我们在各种目标上部署 AI 的方式。这太棒了。对我们来说,上述过程很有吸引力,原因有很多:

  • 性能: WebAssembly 速度超快,运行在一个微小的容器中。在计算预测和最小内存占用时,它提供了接近本机的性能。
  • 可移植性: ONNX 允许从几乎任何现代数据分析工具中存储任何模型(包括预处理和后处理管道),并且随后 WebAssembly 二进制文件可以在任何地方有效地运行。
  • 隐私:我们经常在隐私敏感的情况下部署模型;在这些情况下,我们希望模型的输入数据保留在本地(例如,在医院)。我们不是四处发送敏感数据,而是四处发送模型。
  • 治理:与 ONNX 运行时(或用于创建模型推理的 docker 容器)相比,它的巨大优势在于它是独立的。WASM 二进制文件很容易进行版本控制和检查。我们可以保证模型预测的有效性,而不必担心它的周围环境(python 版本、库等)。).

希望这个小教程(以及其中的参考资料)对其他人入门有用!

放弃

值得一提的是我自己的参与:我是 Jheronimus 数据科学院的数据科学教授,也是 Scailable 的联合创始人之一。因此,毫无疑问,我对 Scailable 有既得利益;我有兴趣让它成长,这样我们就可以最终将人工智能投入生产并兑现它的承诺。这里表达的观点是我自己的。

移动数据收集:它是什么和它能做什么

原文:https://towardsdatascience.com/mobile-data-collection-what-it-is-and-what-it-can-do-714dae3e0a18?source=collection_archive---------21-----------------------

数据收集并不是什么新鲜事,但移动设备的引入让它变得更加有趣和高效。在移动技术出现之前,我们需要使用笔和纸在现场记录信息,或者手动将其输入计算机来组织信息。但现在,移动数据收集意味着信息可以在来源处以数字方式记录在移动设备上,无需在收集信息后输入数据。

来自 FineReport

1.什么是移动数据收集?

移动数据收集是一种借助移动设备收集不同类型信息的方法。它帮助我们节省时间、金钱和人力资源。节省无数纸张,更环保。有时,通过这种非接触方式在现场收集数据增加了人员的安全性。

2.移动数据收集如何帮助企业?

2.1 移动数据采集效率更高,保证数据准确性。

在手机上填写移动表单更快,并最大限度地减少了手动数据输入错误。用户可以从列表、单选按钮、复选框或扫描的数据中选择数据,而不必手动输入信息。

移动表单的列表和单选按钮

此外,移动数据收集包括基于数据类型和必填字段的自动数据验证。数据验证和更少的手动输入有助于减少错误并节省大量时间。

移动数据收集的数据验证

2.2 移动数据收集实时跟踪收集过程并管理团队。

您可以随时随地更新移动表单的变化(设备和用户之间自动同步)。您可以在几分钟内在线调整相应的移动表单,所有团队成员都可以立即访问相同的信息。

移动数据收集有助于实时查看收集的数据并监控项目。您可以使用权限来管理团队角色(项目经理、外业工作队、分析师……),以控制谁可以收集或更新数据,从而简化任务分配和决策。

3.移动数据收集的例子

移动数据采集可以应用于任何行业和任何工作流程。

最近全世界都在关注中国的冠状病毒疫情。事实上,这种病毒已经逐渐影响到其他国家。在这种危机下,及时收集人员信息成为防控病毒的重要一环。只有及时了解疫情,才能及时部署防控措施。

为此,我做了 8 个移动数据录入模板,可以应用于以下五个场景,帮助组织和企业收集信息。下面,我将具体解释为什么此时移动数据采集更高效、更安全。

3.1 健康信息收集

  • 旅行计划登记

冠状病毒的大规模爆发发生在中国的春节。在此期间,大量的人在全国范围内迁移。因此,我们需要统计学生或员工的旅行情况:是否有武汉(病毒起源)接触史或与武汉人有过接触。通过广泛的调查和及时的隔离,我们希望将病毒扼杀在摇篮中。

  • 健康登记

通过对个人身体状况的调查,可以提高人们对疫情情况的了解,及早识别患者,送医院治疗。

3.2 远程办公

为了减少人群聚集,阻断病毒传播,中国很多公司已经开始允许员工在家办公。为此,我们可以制作人事考勤移动表单,让员工在手机上打卡。企业可以由此获取员工所在地信息,从而了解某个员工所在城市的疫情情况。通过这种移动数据采集产生的考勤数据,方便 HR 统计。例如,下面的移动表单是一个远程办公环境调查。

  • 远程办公环境调查

3.3 出入境登记

在这次病毒危机中,各个地区都采取了人员出入限制。人员进出需要登记。传统的纸笔登记存在相互感染病毒的风险,管理人员无法实时查看出入记录。于是我做了一个移动报名表,实现电子注册。参观者只需使用一部手机就可以在线填写登记表,管理人员也可以在手机上查看实时访问记录,方便出现问题时排除故障。

3.4 库存管理

现在,世界正在向中国捐赠大量物资。库存的管理尤为重要。如何有效地管理仓库的进入、货物的交付和材料的及时分发也成为问题。我们可以使用移动数据采集来简化物料仓库流程管理。

  • 输入仓库

  • 耗材使用

3.5 医院管理

疫情期间,医院除了需要企业和社区进行数据收集外,还需要高效地进行防疫统计,如患者信息收集、患者日增加量、病历和报告、材料申请等。

  • 患者信息输入

  • 医疗用品需求登记

注:本文中所有的移动表格都是用 BI 报告和仪表板软件 FineReport 制作的。这个工具是由我工作的数据研究所开发的。个人使用完全免费。您可以 下载它 练习制作移动表格、图表、报告和仪表板。

结论

移动数据收集无疑提高了业务运营效率。实践证明,这种方法可以提高数据收集的速度和准确性、服务提供的有效性以及员工的绩效。

借助移动数据收集,每个团队成员都可以做更多工作,做出明智的业务决策。团队中的每个人都可以立即访问收集到的信息,并迅速采取行动。因此,不要犹豫,尝试移动数据收集,我向你保证,它会让你的生活更轻松,并使你免受与数据丢失和错误相关的问题。

[## Lewis Chou -区域经理- FineReport 报告软件| LinkedIn

查看世界上最大的职业社区 LinkedIn 上的 Lewis Chou 的个人资料。刘易斯有 3 份工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/lewis-chou-a54585181/)

如果你想获得这些移动数据收集模板,你可以在 LinkedIn 上联系我,我很乐意与你分享。

您可能也会对… 感兴趣

[## 数据可视化在对抗新型冠状病毒的战斗中有什么帮助?

我为五种情况设计了仪表板,以帮助监控冠状病毒爆发的情况,并执行…

towardsdatascience.com](/what-can-data-visualization-help-in-the-battle-against-the-novel-coronavirus-bad9b2c7fb2b) [## 2019 年 6 大数据分析工具

谈到数据分析工具,我们总是有疑问。这么多数据分析有什么区别…

towardsdatascience.com](/top-6-data-analytics-tools-in-2019-4df815ebf82c) [## 动态图表:让您的数据移动

动态图表给我们一种直观和互动的体验。这篇文章将解释什么是动态图表和…

towardsdatascience.com](/dynamic-charts-make-your-data-move-19e540a06bd3)