TowardsDataScience 博客中文翻译 2020(七百零四)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

PP-YOLO 超越 yolov 4——物体探测技术的进步

原文:https://towardsdatascience.com/pp-yolo-surpasses-yolov4-object-detection-advances-1efc2692aa62?source=collection_archive---------5-----------------------

注:我们也在博客上发表了 PP-YOLO 超越约洛夫 4 。百度发布 PP-YOLO,推送物体检测研究最新动态。

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

PP-YOLO 评估显示更快的推断(x 轴)和更好的准确性(y 轴)

PP-YOLO 评估指标显示,其性能优于目前最先进的目标检测模型 YOLOv4 。然而,百度的作者写道:

本文不打算介绍一种新颖的目标检测器。它更像是一个食谱,告诉你如何一步一步地建造一个更好的探测器。

让我们打开它。

YOLO 发展历史

《YOLO》最初是由 Joseph Redmon 创作的,用来探测物体。对象检测是一种计算机视觉技术,通过在对象周围绘制一个边界框并识别给定框所属的类别标签来定位和标记对象。与庞大的 NLP 变形金刚不同,YOLO 被设计得很小,使得在设备上部署实时推理速度

YOLO-9000 是 Joseph Redmon 发表的第二个“yolov 2”物体探测器,改进了探测器并强调了探测器推广到世界上任何物体的能力。

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

PP-YOLO 正在接受训练,以识别照片中不同的果蝇。

YOLOv3 对探测网络做了进一步的改进,开始将物体探测过程主流化。我们开始发布关于如何在 PyTorch 中训练 YOLOv3、如何在 Keras 中训练 YOLOv3、比较 YOLOv3 性能和 EfficientDet (另一种最先进的检测器)的教程。

然后,由于伦理问题,约瑟夫·雷德蒙退出了对象检测游戏。

自然,开源社区拿起了接力棒,继续推动 YOLO 技术向前发展。

YOLOv4 最近在今年春天由 Alexey AB 在他的 YOLO 暗网知识库中出版。YOLOv4 主要是其他已知计算机视觉技术的集合,通过研究过程进行组合和验证。点击这里深入了解 YOLOv4 。YOLOv4 纸读起来与 PP-YOLO 纸相似,我们将在下面看到。我们整理了一些关于如何在黑暗网络中训练 YOLOv4 的很棒的训练教程。

然后,就在几个月前 YOLOv5 发布。YOLOv5 采用了 Darknet(基于 C 的)培训环境,并将网络转换为 PyTorch。改进的训练技术进一步推动了模型的性能,并创建了一个伟大的、易于使用的、开箱即用的对象检测模型。从那以后,我们一直鼓励使用 Roboflow 的开发人员通过本 YOLOv5 培训教程将他们的注意力转向 YOLOv5,以形成他们的自定义对象检测器。

输入 PP-YOLO。

PP 代表什么?

PP 是百度写的深度学习框架 PaddlePaddle 的简称。

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

PaddlePaddle 在其网站上提供发行版。

如果 PaddlePaddle 对你来说是陌生的,那么我们是在同一条船上。PaddlePaddle 主要用 Python 编写,看起来类似于 PyTorch 和 TensorFlow。深入探究 PaddlePaddle 框架很有趣,但超出了本文的范围。

PP-YOLO 捐款

PP-YOLO 的论文读起来很像 YOLOv4 的论文,因为它是已知在计算机视觉中工作的技术的汇编。新的贡献是证明这些技术的组合提高了性能,并提供了一个烧蚀研究,每个步骤在多大程度上有助于模型前进。

在我们深入研究 PP-YOLO 的贡献之前,回顾一下 YOLO 探测器的结构是很有用的。

YOLO 探测器的剖析

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

PP-YOLO 物体探测网络的图形描述

YOLO 探测器分为三个主要部分。

YOLO 主干——YOLO 主干是一个卷积神经网络,它汇集图像像素以形成不同粒度的特征。主干通常在分类数据集(通常为 ImageNet)上进行预训练。

**YOLO 颈—**YOLO 颈(上面选择的是 FPN)在传递到预测头之前,合并和混合了 ConvNet 层表示。

YOLO 头 —这是网络中做出包围盒和类预测的部分。它由类、盒和对象的三个 YOLO 损失函数指导。

现在让我们深入了解一下 PP YOLO 的贡献。

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

PP-YOLO 中,每种技术的边际地图精度性能都有所提高

替换主干

第一种 PP YOLO 技术是用 Resnet50-vd-dcn ConvNet 主干替换 YOLOv3 Darknet53 主干。Resnet 是一个更受欢迎的主干,更多的框架为其执行进行了优化,并且它比 Darknet53 具有更少的参数。通过交换这个主干看到一个地图的改进对 PP YOLO 来说是一个巨大的胜利。

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

ResNet 中的图形描述

模型参数的 EMA

PP YOLO 跟踪网络参数的指数移动平均值,以在预测时间内保持模型权重的影子。这已被证明可以提高推断的准确性。

较大批量

PP-YOLO 将批量从 64 个增加到 192 个。当然,如果你有 GPU 内存限制,这是很难实现的。

丢弃块正则化

PP YOLO 在 FPN 颈部实施 DropBlock 正则化(在过去,这通常发生在主干中)。DropBlock 在网络中的给定步骤随机删除一块训练特征,以教导模型不依赖于关键特征进行检测。

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

丢弃块正则化技术——特征不随机地隐藏在块中(b)

欠条损失

YOLO 损失函数不能很好地转化为地图度量,它在计算中大量使用联合上的交集。因此,考虑到这个最终预测,编辑训练损失函数是有用的。这个剪辑也出现在了《T4》中。

IoU 感知

PP-YOLO 网络增加了一个预测分支,用于预测给定对象的模型估计 IOU。在决定是否预测对象时,包含这种 IoU 意识可以提高性能。

网格灵敏度

旧的 YOLO 模型在围绕锚盒区域的边界做出预测方面做得不好。为了避免这个问题,定义稍微不同的盒子坐标是有用的。这个技巧在 YOLOv4 中也有。

矩阵 NMS

非最大值抑制是一种去除用于分类的候选对象的过多建议的技术。矩阵 NMS 是一种并行排序这些候选预测的技术,可以加快计算速度。

CoordConv

CoordConv 的灵感来源于 ConvNets 在简单地将(x,y)坐标映射到一个热点像素空间时遇到的问题。CoordConv 解决方案允许卷积网络访问自己的输入坐标。CoordConv 干预用上面的黄色菱形标记。CordConv 论文中提供了更多详细信息。

中加国际学生合作计划

空间金字塔池是主干层之后的一个额外模块,用于混合和汇集空间要素。也在 YOLOv4YOLOv5 中实现。

更好的预训练脊柱

PP YOLO 的作者提炼出一个更大的 ResNet 模型作为主干。一个更好的预训练模型也能改善下游迁移学习。

PP-YOLO 是最先进的吗?

PP-YOLO 胜过结果 YOLOv4 发表于2020 年 4 月 23 日。

公平地说,作者指出这可能是一个错误的问题。作者的意图似乎不仅仅是“引入一种新的新型检测器”,而是展示仔细调整对象检测器以最大化性能的过程。这里引用论文的引言:

本文的重点是如何堆叠一些几乎不影响效率的有效技巧,以获得更好的性能……本文无意介绍一种新颖的对象检测器。它更像是一个食谱,告诉你如何一步一步地建造一个更好的探测器。我们发现了一些对 YOLOv3 检测器有效的技巧,可以节省开发人员试错的时间。最终的 PP-YOLO 模型将 COCO 上的 mAP 从 43.5%提高到 45.2%,速度比 YOLOv4

(强调我们的)

上面提到的 PP-YOLO 贡献将 YOLOv3 模型在 COCO 对象检测任务上的 mAP 从 38.9 提高到 44.6,并将推断 FPS 从 58 提高到 73。这些指标显示在论文中,以击败当前发布的 YOLOv4 和 EfficientDet 的结果。

在将 PP-YOLO 与 YOLOv5 进行对比时,似乎 YOLOv5 在 V100 上仍然具有最快的推理时间-精度性能(AP 与 FPS)权衡。然而,一篇 YOLOv5 论文仍有待发布。此外,已经表明,在 YOLOv5 Ultralytics 存储库上训练 YOLOv4 架构优于 YOLOv5,并且,使用 YOLOv5 贡献训练的 YOLOv4 将优于这里发布的 PP-YOLO 结果。这些结果仍有待正式发表,但可以追溯到GitHub 讨论

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

V100 GPU 上 COCO 数据集的 PP-YOLO 评估(注意 AP_50 列)

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

V100 GPU 上 COCO 数据集的 YOLOv5 评估(注意 AP_50 列)

值得注意的是,在 YOLOv4 中使用的许多技术(如架构搜索和数据扩充)并没有在 PP YOLO 中使用。这意味着,随着更多这些技术被组合和集成在一起,对象检测的技术水平仍有发展的空间。

不用说,实现计算机视觉技术是一个激动人心的时刻。

我应该从 YOLOv4 或者 YOLOv5 换成 PP-YOLO 吗?

PP-YOLO 模型展示了最先进的目标检测的前景,但是相对于其他目标检测器的改进是递增的,并且它是在一个新的框架中编写的。在这个阶段,最好的办法是通过在自己的数据集上训练 PP-YOLO 来得出自己的实证结果。(当您可以在数据集上轻松使用 PP-YOLO 时,我们会通知您,订阅我们的新闻简报。)

与此同时,我建议查看以下 YOLO 教程,让你的物体探测器离开地面:

一如既往——快乐训练!

实用人工智能:使用 BERT Summarizer、Wordnet 和 Conceptnet 从任何内容中自动生成选择题

原文:https://towardsdatascience.com/practical-ai-automatically-generate-multiple-choice-questions-mcqs-from-any-content-with-bert-2140d53a9bf5?source=collection_archive---------6-----------------------

如果你想在行动中尝试 MCQ 一代的现场演示,请访问 https://questgen.ai/

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

MCQs —图片来自 Pixabay

在本帖中,我们将看到如何从任何故事或文章中自动生成选择题。这是朝着自动生成你在初中/高中看到的 mcq 迈出的一步。

****输入:我们程序的输入将是一篇文章(下面 github 库中提供的示例文章),如下所示

*The Greek historian knew what he was talking about. The Nile River fed Egyptian civilization for hundreds of years. The Longest River the Nile is 4,160 miles long — the world’s longest river. It begins near the equator in Africa and flows north to the Mediterranean Sea ..............*

输出:

1) The Nile provided so well for  _______  that sometimes they had surpluses, or more goods than they needed.
	 a )   Angolan
	 b )   Algerian
	 c )   Egyptians
	 d )   Bantu

More options:  ['Basotho', 'Beninese', 'Berber', 'Black African', 'Burundian', 'Cameroonian', 'Carthaginian', 'Chadian', 'Chewa', 'Congolese', 'Djiboutian', 'Egyptian', 'Ethiopian', 'Eurafrican', 'Ewe', 'Fulani'] 

2) As in many ancient societies, much of the knowledge of  _______  came about as priests studied the world to find ways to please the gods.
	 a )   Malawi
	 b )   East Africa
	 c )   Somalia
	 d )   Egypt

More options:  ['Togo', 'Zimbabwe', 'Gabon', 'Ghana', 'Lake Tanganyika', 'Ottoman Empire', 'Mozambique', 'Iran', 'Israel', 'Saudi Arabia', 'Lebanon', 'Turkey', 'Iraq', 'Levant', 'Syria', 'Jordan'] 

3) The  _______  provided so well for Egyptians that sometimes they had surpluses, or more goods than they needed.
	 a )   Nyala
	 b )   Omdurman
	 c )   Nile
	 d )   Port Sudan

More options:  ['Khartoum', 'Nubian Desert', 'Darfur', 'Libyan Desert', 'Kordofan', 'Gulu', 'Buganda', 'Entebbe', 'Jinja', 'Lake Edward', 'entebbe', 'gulu', 'kayunga', 'Upper Egypt', 'Suez Canal', 'Aswan High Dam']

让我们开始看看如何利用最新的自然语言处理技术构建自己的 MCQ 生成器。

如果您想现场试用先进的 MCQ 发电机,请访问

所有的代码和 jupyter 笔记本都可以在-

*** [## ramsrigouthamg/Generate _ MCQ _ 伯特 _ 文字网 _ 概念网

使用 BERT 摘要、Wordnet 和…从任何内容或新闻文章中生成选择题

github.com](https://github.com/ramsrigouthamg/Generate_MCQ_BERT_Wordnet_Conceptnet)

首先在 jupyter 笔记本中安装必要的库。如果您遇到任何错误,只需修改版本并检查其他不兼容之处:

!pip install gensim
!pip install git+[https://github.com/boudinfl/pke.git](https://github.com/boudinfl/pke.git)
!python -m spacy download en
!pip install bert-extractive-summarizer --upgrade --force-reinstall
!pip install spacy==2.1.3 --upgrade --force-reinstall
!pip install -U nltk
!pip install -U pywsdimport nltk
nltk.download('stopwords')
nltk.download('popular')

伯特萃取摘要器

这里我们使用一个简单的库 Bert-extract-summarizer 为我们完成这项工作。我们从 Github repo 中的 egypt.txt 文件加载全部文本,并请求库给我们摘要文本。您可以使用比率、最大和最小句子长度等参数进行总结

from summarizer import Summarizerf = open("egypt.txt","r")
full_text = f.read()model = Summarizer()
result = model(full_text, min_length=60, max_length = 500 , ratio = 0.4)summarized_text = ''.join(result)
print (summarized_text)

我们得到原始文本的摘要部分作为输出:

The Nile River fed Egyptian civilization for hundreds of years. It begins near the equator in Africa and flows north to the Mediterranean Sea. A delta is an area near a river’s mouth where the water deposits fine soil called silt.......................

提取关键词

我们使用 python 关键字提取器(PKE)库,从原文中提取所有重要的关键字。然后只保留那些出现在摘要文本中的关键词。这里我只提取名词,因为它们更适合 mcq。此外,我只提取 20 个关键字,但你可以用这个参数(get_n_best)来玩。

输出为-

Original text keywords: ['egyptians', 'nile river', 'egypt', 'nile', 'euphrates', 'tigris', 'old kingdom', 'red land', 'crown', 'upper', 'lower egypt', 'narmer', 'longest river', 'africa', 'mediterranean sea', 'hyksos', 'new kingdom', 'black land', 'ethiopia', 'middle kingdom']Keywords present in summarized text: ['egyptians', 'nile river', 'egypt', 'nile', 'old kingdom', 'red land', 'crown', 'upper', 'lower egypt', 'narmer', 'africa', 'mediterranean sea', 'new kingdom', 'middle kingdom']

句子映射

对于每个关键词,我们将从摘要文本中提取出包含该词的相应句子。

样本输出为—

{'egyptians': ['The Nile provided so well for Egyptians that sometimes they had surpluses, or more goods than they needed.', 'For example, some ancient Egyptians learned to be scribes, people whose job was to write and keep records.', 'Egyptians believed that if a tomb was robbed, the person buried there could not have a happy afterlife.', 'nile river': ['The Nile River fed Egyptian civilization for hundreds of years.'],  'old kingdom': ['Historians divide ancient Egyptian dynasties into the Old Kingdom, the Middle Kingdom, and the New Kingdom.', 'The Old Kingdom started about 2575 B.C., when the Egyptian empire was gaining strength.'], }        .....................

生成 MCQ

在这里,我们从 Wordnet 和 Conceptnet 获得干扰物(错误答案选择),以生成我们的最终 MCQ 问题。

什么是干扰物(错误答案选择)?

如果让我们说*“历史学家将古埃及王朝分为旧王国、中王国和新王国。”*是我们的句子,我们希望将“埃及人”作为空白关键字,那么其他错误答案选项应该类似于埃及人,但不是埃及人的同义词。

Eg: *Historians divide ancient __________  dynasties into the Old Kingdom, the Middle Kingdom, and the New Kingdom*a)Egyptian
b)Ethiopian
c)Angolian
d)Algerian

在上述问题中,选项 b)、c)和 d)是干扰项。

我们如何自动生成这些干扰物?

我们采取两种方法一种是用 wordnet,另一种是用 conceptnet 来获取干扰物。

我们代码中使用的 Wordnet 方法:

给定作为句子和关键字的输入,我们首先获得单词的“意义”。

我用一个例子用“感”来解释一下。如果我们有一个句子“蝙蝠飞入丛林并降落在树上”和一个关键字“蝙蝠”,我们会自动知道这里我们谈论的是有翅膀的哺乳动物蝙蝠,而不是板球拍或棒球棒。尽管我们人类擅长于此,但算法并不擅长区分两者。这被称为词义消歧(WSD)。在 wordnet 中,“蝙蝠”可能有几个意思,一个是指板球拍,一个是指会飞的哺乳动物等等。因此函数 get_wordsense 试图获得给定句子中单词的正确含义。这并不总是完美的,因此如果算法缩小到一个错误的意义上,我们会得到一些错误。那么干扰物(错误的答案选择)也会是错误的。

一旦我们确定了这个感觉,我们就调用 get_distractors_wordnet 函数来获取干扰物。这里发生的事情是,假设我们得到一个像“ cheetah ”这样的词,并确定它的意义,然后我们去它的上位词。一个上位词是一个给定单词的更高层次的类别。在我们的例子中,猫科动物是猎豹的上位词。

然后我们去寻找所有属于猫科动物的猫科动物的下位词(子类),可能是豹、老虎、狮子。因此,对于给定的 MCQ,我们可以使用豹子、老虎、狮子作为干扰物(错误答案选项)。

我们代码中使用的概念网方法:

不是所有的单词都可以在 wordnet 中找到,也不是所有的单词都有上位词。因此,如果我们在 wordnet 上失败了,我们也会在 conceptnet 上寻找干扰物。get _ distractors _ conceptnet是用来从 concept net 中获取干扰项的主要函数。Conceptnet 并没有像我们在上面讨论 bat 的例子那样提供不同词义之间的区分。因此,当我们用一个给定的词进行查询时,我们需要继续使用 conceptnet 给我们的任何意义。

让我们看看如何在用例中使用 conceptnet。我们不安装任何东西,因为我们直接使用 conceptnet API。请注意,有一个每小时的 API 率限制,所以要小心。

给定一个像“California”这样的词,我们用它查询 conceptnet 并检索关系的“部分。在我们的例子中,“加利福尼亚”是“美国”的一部分。

现在我们去“美国”,看看它和其他什么事物有“部分”关系。那将是其他州,如“得克萨斯”、“亚利桑那”、“西雅图”等。因此,对于我们的查询词“加利福尼亚”,我们取出了干扰词“德克萨斯”、“亚利桑那”等

最后,我们生成如下输出:

#############################################################################
NOTE::::::::  Since the algorithm might have errors along the way, wrong answer choices generated might not be correct for some questions. 
#############################################################################

1) The Nile provided so well for  _______  that sometimes they had surpluses, or more goods than they needed.
	 a )   Angolan
	 b )   Algerian
	 c )   Egyptians
	 d )   Bantu

More options:  ['Basotho', 'Beninese', 'Berber', 'Black African', 'Burundian', 'Cameroonian', 'Carthaginian', 'Chadian', 'Chewa', 'Congolese', 'Djiboutian', 'Egyptian', 'Ethiopian', 'Eurafrican', 'Ewe', 'Fulani'] 

2) As in many ancient societies, much of the knowledge of  _______  came about as priests studied the world to find ways to please the gods.
	 a )   Malawi
	 b )   East Africa
	 c )   Somalia
	 d )   Egypt

More options:  ['Togo', 'Zimbabwe', 'Gabon', 'Ghana', 'Lake Tanganyika', 'Ottoman Empire', 'Mozambique', 'Iran', 'Israel', 'Saudi Arabia', 'Lebanon', 'Turkey', 'Iraq', 'Levant', 'Syria', 'Jordan'] 

3) The  _______  provided so well for Egyptians that sometimes they had surpluses, or more goods than they needed.
	 a )   Nyala
	 b )   Omdurman
	 c )   Nile
	 d )   Port Sudan

More options:  ['Khartoum', 'Nubian Desert', 'Darfur', 'Libyan Desert', 'Kordofan', 'Gulu', 'Buganda', 'Entebbe', 'Jinja', 'Lake Edward', 'entebbe', 'gulu', 'kayunga', 'Upper Egypt', 'Suez Canal', 'Aswan High Dam'] 

4) It combined the red  _______  of Lower Egypt with the white  _______  of Upper Egypt.
	 a )   Capital
	 b )   Crown
	 c )   Masthead
	 d )   Head

More options:  [] 

5) It combined the red Crown of Lower Egypt with the white Crown of  _______  Egypt.
	 a )   Upper Berth
	 b )   Lower Berth
	 c )   Upper

More options:  []

请注意,由于从 Wordnet 词义消歧(WSD)算法中提取的单词的错误含义,或者由于其局限性 conceptnet 用不同的含义识别它,可能会有许多错误。

可以改进的东西?

  1. 就像关系中的部分一样,在概念网中存在 IsA 关系,可以进一步探索以获得干扰物。

您可以将这些用于 IsA 关系-

query URL = “http://api.conceptnet.io/query?node=%s&rel =/r/IsA&end = % s&limit = 10”(link,link)

检索 URL = “http://api.conceptnet.io/query?node=/c/en/%s/n&rel =/r/IsA&start =/c/en/% s&limit = 5”(word,word)

**2。**因为每个关键词有多个句子,所以使用所有句子进行词义消歧(WSD ),并选择具有最高计数的词义。

**3。**可以替代地使用单词向量(word2vec,glove)作为给定单词的干扰子的方式。

*4。在将全文传递给 BERT summarizer 之前,可以对其使用代词消解(神经共指消解)。然后,任何带有代词的句子都应被解析,这样当以 MCQ 的形式呈现时,它看起来完整而独立。

祝 NLP 探索愉快,如果你喜欢它的内容,请随时在 Twitter 上找到我。

如果你想学习使用变形金刚的现代自然语言处理,看看我的课程使用自然语言处理生成问题

实用人工智能:以一种新颖的方式使用 NLP 单词向量来解决本地化问题

原文:https://towardsdatascience.com/practical-ai-using-nlp-word-vectors-in-a-novel-way-to-solve-the-problem-of-localization-9de3e4fbf56f?source=collection_archive---------43-----------------------

你将会看到单词嵌入(word2vec,glove 等)的最实际的用法。

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

作者图片

国王——男人+女人=王后

你可能见过传统的 word2vecGlove word 嵌入示例,显示国王+女人=王后。这里 Queen 将从给定单词 KingManWoman 的单词嵌入算法中返回。今天我们将看看如何使用这种结构来解决现实世界中的问题。

1。问题定义:

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

来自Flaticon.com的图标

美国的一家 edtech 公司在印度本土市场取得成功后,想把业务扩展到印度。在他们的题库中有一大套问题,它希望在进入印度市场时使用。****

但是有一个大问题。他们题库里的一个样本三等(年级)数学题是这样的——

弗兰克住在旧金山,伊丽莎白住在 T42。如果飞行时间是 2 小时如果早上8 点开始伊丽莎白什么时候到达弗兰克

一个住在印度的三年级孩子不会回答这个问题,因为这个问题涉及到的名字的地点他/她不太知道的- 弗兰克旧金山、**洛杉矶、**等等。

因此,如果我们改变这个问题以适应印度的环境,并重新表述它,那将是理想的

桑杰·维尔马住在班加罗尔,瑞哈住在孟买。如果飞行时间是 2 小时,那么如果瑞哈早上 8 点出发,她什么时候到达桑杰·维尔马?

这个概念叫做 汉化 。这是一种产品或想法带到不同的国家或地区的一般概念,尊重当地规范,习俗,以及任何其他偏好。我们的目标是与目标受众产生共鸣,因为内容是本地化的

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

作者图片

2.单词嵌入法:

现在让我们看看如何将我们最初的美国数学问题本地化到印度的环境中。

弗兰克住在旧金山,伊丽莎白住在洛杉机。如果飞行时间是 2 小时如果早上8 点开始伊丽莎白什么时候到达弗兰克

步骤 2.1: 我们的目标是提取所有需要本地化关键词。我们将使用空间命名实体识别来实现这一点。

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

提取的命名实体

步骤 2.2: 过滤掉与不相关的命名实体。例如,像数字(基数)和时间这样的实体在我们的例子中不需要本地化。

**过滤后的实体:**弗兰克,旧金山,伊丽莎白,洛杉矶

最有趣的部分来了。我们将使用 King-Man + Woman = Queen 框架来转换每个实体。代码将出现在接下来的章节中,但这里我们只展示概念。

**Frank**-USA+India = **Sanjay Verma
San Franciso**-USA+India = **Bangalore
Elizabeth**-USA+India = **Rekha
Los Angeles**-USA+India = **Mumbai**

**第 2.4 步:**我们回过头来,用它们的替换物来改变实体,得到-

桑杰·维尔马住在班加罗尔,瑞哈住在孟买。如果飞行时间是 2 小时,如果瑞哈早上 8 点开始,她什么时候到达桑杰·维尔马?

3.说够了,给我看看代码:)

[## 谷歌联合实验室

编辑描述

colab.research.google.com](https://colab.research.google.com/drive/1oGqwDgDgtBeiXoeaq1uvX-_KxLY8FzXp?usp=sharing)

查看完整干净的 Google Colab 笔记本,它展示了两个不同的本地化示例。第一个例子自动第二个简单 UI** 手动选择最佳替换。**

重要的部分再次在代码中显示(除了 Colab)

步骤 3.1 提取需要本地化的实体

import spacy
import pandas as pd
from spacy import displacy
from spacy.tokens import Span
nlp = spacy.load("en")original_input = **"Frank lives in San Francisco and Elizabeth lives in Los Angeles. If the flight time is 2 hrs when will Elizabeth reach Frank if she starts at 8am in the morning?"**
processed_input_text=nlp(original_input)
keyword_set = set()
entity_mapping = []
for token in processed_input_text.ents:
    if token.text not in keyword_set:
      keyword_set.add(token.text )
      entity_mapping.append((token.text,token.label_))
**print (entity_mapping)**
displacy.render(processed_input_text, style='ent', jupyter=True)# Now all entities cannot be localized. Example no need to localize numbers. So keep only relevant entities that need to be localized.
keep_entities_list = ['PERSON','GPE','FAC','ORG','PRODUCT','NORP','MONEY','LOC','WORK_OF_ART','LAW','LANGUAGE','QUANTITY']
finalized_entity_mapping = {}
for ent in entity_mapping:
  if ent[1] in keep_entities_list:
    finalized_entity_mapping[ent[0]] = []**print (finalized_entity_mapping)**

上述步骤的输出为—

**Unfiltered entities:** 
[('Frank', 'PERSON'), ('San Francisco', 'GPE'), ('Elizabeth', 'PERSON'), ('Los Angeles', 'GPE'), ('2', 'CARDINAL'), ('8am in the morning', 'TIME')]**Entities after filtering:** {'Frank': [], 'San Francisco': [], 'Elizabeth': [], 'Los Angeles': []}

步骤 3.2 初始化来自 Gensim 的 Google 新闻词向量并执行本地化

import gensim.downloader as api
model = api.load("word2vec-google-news-300") 
word_vectors = model.wv**Origin_country='USA' 
Target_country='India'**final_mapping ={}for word in finalized_entity_mapping: 
  word = word.strip()
  word = word.replace(" ","_")
  try:
    similar_words_list= model.most_similar(positive=[Target_country,word],negative=[Origin_country],topn=10)
    # Remove the scores for the retrieved choices
    similar_words_list = [choices[0].replace("_"," ") for choices in similar_words_list ]
    final_mapping[word.replace("_"," ")] = similar_words_list
  except:
    similar_words_list = []
    print (" Fetching similar words failed for ",word)
  print (word," -- Replacement suggestions -- ",similar_words_list)

上述步骤的输出为—

**Frank** -- Replacement suggestions --  ['Sanjay Verma', 'Sabyasachi Sen', 'JK Jain', 'Sunil Chauhan', 'Don', 'Sudip', 'Ajay Shankar', 'Robert', 'V. Srinivasan', 'Kanwar Sain']**San_Francisco** -- Replacement suggestions --  ['Bangalore', 'Kolkata', 'Mumbai', 'Chennai', 'Delhi', 'Hyderabad', 'Calcutta', 'San Franciso', 'Bombay', 'Bengaluru']**Elizabeth** -- Replacement suggestions --  ['Rekha', 'Nandita', 'Meera', 'Margaret', 'Katharine', 'Bhagirath', 'Monica', 'Lakshmi', 'Manisha', 'Anita']**Los_Angeles** -- Replacement suggestions --  ['Mumbai', 'Los Angles', 'Kolkata', 'Chennai', 'Bangalore', 'LA', 'Delhi', 'Hyderabad', 'Ahmedabad', 'Calcutta']

您可以看到每个单词及其首选替换选项。

步骤 3.3 打印替换输出

def localize(sentence,mapping):
  for k in mapping:
    sentence = sentence.replace(k,mapping[k][0])
  return sentenceprint('Original Sentence:')
print(original_input)localized_string =  localize(original_input,final_mapping)print('\nLocalized Sentence:')
print(localized_string)

输出是—

Original Sentence:
**Frank** lives in **San Francisco** and **Elizabeth** lives in **Los Angeles**. If the flight time is 2 hrs when will **Elizabeth** reach **Frank** if she starts at 8am in the morning?Localized Sentence:
**Sanjay Verma** lives in **Bangalore** and **Rekha** lives in **Mumbai**. If the flight time is 2 hrs when will **Rekha** reach **Sanjay Verma** if she starts at 8am in the morning?

太好了!我们终于在附近到达终点

但是如果显示的第一选择不是给定单词的正确替换呢?

为了解决这个问题,我们构建了一个小的 UI ,通过下拉菜单选择正确的选项。它显示在 Google Colab 笔记本的示例 2 下。

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

选择正确单词的用户界面

这个项目是由令人敬畏的实习生 Niharika Reddy 在我的指导下进行的,作为我的开源计划的一部分

基于群组的实时课程:自然语言处理的实用介绍

我正在和世界上最好的群组学习平台 Maven 一起进行为期 4 周的群组课程“NLP 实用入门”。如果你希望在 4 周内将自己从一名 Python 开发人员转变为一名具有实际项目经验的初级 NLP 开发人员,现在就抓住你的位置

使用自然语言处理的问题生成——教程

我推出了一个非常有趣的 Udemy 课程,名为“使用 NLP 生成问题”,扩展了这篇博文中讨论的一些技术。如果你想看一看,这里是链接

祝 NLP 探索愉快,如果你喜欢它的内容,请随时在推特上找到我。

商业中的实用人工智能

原文:https://towardsdatascience.com/practical-artificial-intelligence-in-business-a75066030692?source=collection_archive---------52-----------------------

商业可以通过了解 AI 是如何完成的来有效地使用 AI。

商业中的人工智能是实用的。当您考虑神经网络时,不要考虑抽象的数学结构,而是需要数据来学习业务流程以及如何在其中操作的计算机系统。

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

商业中的实用人工智能

商业中的数据科学和实用人工智能

数据科学不是一门真正的科学,它是一个实验领域,你需要不断地调整、测试、从头构建原型并重建你所拥有的。这是一个解决问题的框架,而不是一套特定的工具。这种使用神经网络的范例,类固醇上的统计数据,使得人工智能在实践和理论上都很复杂,具有如此广泛的应用,我们将在下一章中讨论。

那么数据科学或者人工智能目前是怎么做的呢?你可以将实际工作分成两部分,这两部分紧密相连:

  • 履行
  • 研究

实施阶段的重点是为特定的业务问题提供切实可行的解决方案。通过使用来自组织内部的数据,数据科学家实施机器学习模型来学习这些数据。这一阶段主要关注数据科学的工程方面:

  • 清理数据
  • 特征抽出
  • 统计分析
  • 训练神经网络
  • 设置虚拟机和一般环境。

研究阶段是寻找可能的调整、改进或现有方法的全新方法。它可能包括阅读科学论文、其他组织的白皮书、浏览 Github 上的开源代码、与机器学习工程师同事交谈、参加会议。目标是拓宽视野,找到新的战略来实施。

一般来说,实现和研究哪个先来是不可能的,因为数据科学家的第一步通常是构建第一个简单的模型,看看它如何处理给定的数据,然后寻找其他方法和增强。对于更难和更有吸引力的项目,机器学习工程师可能会从研究开始,阅读在网络上可能找到的主题,然后选择几个模型来实现和尝试。

然而,数据科学家花在计算机前的大部分时间,无论是阅读、编写代码还是训练机器学习模型。在企业中经常被误解的是,传统软件开发中通常的冲刺(精益启动方法)并不总是有利于找到需要深入思考的更复杂问题的解决方案。这就是为什么谷歌的 20%规则,允许 20%的休息时间去做软件工程师自己的项目,是如此富有成效。数据科学家需要修补和摆弄想法,以提高他们的创造力。

人工智能研究

人工智能研究社区可以分为三个部分:

  • 机器学习社区
  • 道德与社会团体
  • 工商业界

机器学习社区主要关注与构建机器学习模型相关的研究问题:从架构、数据到实现。计算机科学或 STEM 领域的博士学位是积极参与的必要条件。

伦理与社会社区关注人工智能研究和实践中应用的社会分支:从立法到人工智能研究目标的重要问题或限制。这个社区的人经常在大学的社会系、智库或者公共机构工作。

商业社区专注于将前沿研究应用于商业问题。这些领域可能包括制造业、药物设计、网络安全、视频游戏等。这里的研究人员大多在大型机构的研究实验室工作。在这些领域找工作时,博士学位不是必须的,但往往是一个额外的优势。

人工智能的研究生涯

如果一个人想成为人工智能的研究人员,标准的道路是通过大学,攻读计算机科学博士学位,然后成为助理教授或研究员。由于最近研究工作方式的变化,例如亚马逊、脸书、谷歌和类似的大型科技公司如何参与研究,新鲜出炉的博士直接进入在他们的研究实验室工作的科技巨头之一的情况经常发生。也有可能他们同时攻读博士学位并在这些公司中的一家工作,这对双方都有利:一家公司赞助一名博士,大学免除了费用,一名博士生有一份工作并做一些与行业相关的事情。

PhD 本身是一部讨论和解决一个公开问题或某个案例的专著,在已经确定的问题中使用新的方法,或者发明与现有知识相关的新问题。有些话题在特定时间比其他话题更流行,这与特定教授的兴趣或市场兴趣(钱在哪里)有关。通常在攻读博士学位期间,一个学生发表几篇论文,这些论文构成了博士论文的主体。

**从一个博士生的角度来看,最重要的是找到一个能接触到有趣问题、资金和研究小组的好导师。**有趣的问题将使他进行有意义的研究,资金将使他能够参加会议并在基础设施上花费很多,研究小组将是研究讨论的无价之宝。

参加会议是与科学家同事联系的好方法。最受欢迎和最负盛名的机器学习会议是 NIPS,神经信息处理系统年会。向 NIPS 提交论文的科学家数量每年增长 30%,这也显示了机器学习社区目前有多么活跃。

吸引人工智能人才到企业

从与学术界争夺人才的商业角度来看,关键的方面是创造一个充满活力的研究环境。分配空闲时间做任何研究都是一个好的解决方案,但关键是围绕该领域的资深人物建立一个研究小组。通常情况下,大型组织会从机器学习系聘请一名教授和他的博士生,作为快速启动研究社区的一种方式。例如,这就是优步从卡耐基梅隆大学机器人系挖人的做法。

对于银行或保险公司这样的老牌机构来说,一个大问题是以一种有吸引力的方式向潜在的机器学习员工展示自己。这里最关键的是要理解,吸引研究人员的是能够创新,有思想自由,开放的氛围和手头要解决的难题。没有人想一直被线性回归困住。提出太难的问题往往比提出太容易的问题更能吸引人才。

在 Kaggle(【www.kaggle.com】)上可以看到一个好问题的很好的例子,在那里,公司为他们的业务问题举办数据科学挑战,并为最佳参赛作品设置奖项。通常这些比赛有成千上万的队伍参加。其中最著名的一次是由网飞举办的一次竞赛,旨在改进他们的推荐算法。该竞赛的奖金为 100 万美元,吸引了大量观众,让网飞成为一家优秀科技公司的候选人,并为网飞提供了许多与他们的业务运营相关的新研究成果。

开源社区

从商业角度来看,机器学习中的开源社区很重要,但仍未被商业充分利用。许多研究成果在 GitHub 上是免费的,这是一个代码库,你可以拿起它,和其他部分一起使用,来构建你需要的独特的东西。从来没有建造一个原型像现在这样快速和便宜。开源社区也是潜在雇员的一个很好的来源,因为它准确地显示了一个人的能力。

从商业的角度来看,支持开源社区有很多好处:获得人才库,了解当前的研究。此外,它还能带来商机。回想一下 Red Hat 的模式,它负责维护 Linux,然后通过支持和定制来赚钱。最终,Red Hat 被 IBM 收购,这是迄今为止最大的技术收购之一,2019 年以 340 亿美元的价格完成。

GitHub 本身在 2018 年被微软以 75 亿美元收购,Kaggle 在 2017 年被谷歌收购。这不仅显示了开源社区对商业的重要性,而且实际上,如果你能够交付一个伟大的产品,并围绕它建立一个参与用户社区,你就可以通过开源努力来做生意。

从研究到应用

讨论了人工智能的研究是如何进行的,现在是时候关注应用了。假设您已经有了一个数据科学团队,并且对您想要解决的问题进行了初步研究,下一步就是收集和清理数据。如果您的大部分业务都是数字化的,可以方便地访问数据,那么这个过程可能会很短;如果您有许多来源要查看,并且数据远非干净(比如,以各种格式进行的客户调查),那么这个过程可能会很长而且很痛苦。如果是这样的话,预处理本身就是一项任务,需要一个单独的团队来完成。这对以后的所有工作都特别重要,所以不要忽视清洗数据。

将研究应用于业务应用意味着对来自您业务的数据使用机器学习模型,并衡量它们的表现与您通常解决手头问题的方式相比如何(例如,在业务流程、营销/销售、相关线索数量上花费的时间)。在收到数据后,你的机器学习工程师团队将制定衡量进展的指标,并开始实施(编码)机器学习算法,用你提供的数据填充它们。最终结果将是预测的准确性、自动化的业务流程或优化的计算。

**在实施阶段至关重要的是要有好的指标来比较模型(架构)、机器(基础设施)和用于培训和评估的数据。**理解结果为何如此与获得产生最佳结果的模型同等重要。

将解决方案扩展到更多数据并在生产中使用模型通常需要比机器学习人才更多的工程技术,因此需要雇用不同于研究阶段的人才库。然而,由于实施和研究是紧密结合的,最好是让研究人员和工程师一起密切合作。

总结一下,商业中实用的人工智能是通过以下循环完成的:

  1. 研究可能的机器学习模型
  2. 收集数据
  3. 使用模型收集数据
  4. 改善基础设施、数据和规模

在步骤 4 之后,我们再次回到步骤 1,有了关于模型在实践中如何工作以及哪些方面可以改进的反馈,研究人员可以寻找新的算法和方法来解决手头的问题。重复整个循环,直到满足流程开始时定义的指标。这就是为什么一开始就为机器学习实验建立一个框架是很重要的,即使它们后来会随着新的实验而改变。

这段文字摘自我即将出版的新书人工智能商业我之前的书关注的是找一份数据科学的工作

用 Python 实现机器学习的特征工程

原文:https://towardsdatascience.com/practical-code-implementations-of-feature-engineering-for-machine-learning-with-python-f13b953d4bcd?source=collection_archive---------23-----------------------

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

使用 Python 进行机器学习的特征工程—图片来自 Pixabay

Forbes 报道,数据科学家和机器学习工程师花费大约 60% 的时间在训练机器学习模型之前准备数据。大部分时间花在了特性工程上。

特征工程是转换和创建可用于训练机器学习模型的特征的过程。特征工程对于训练精确的机器学习模型至关重要,但通常具有挑战性并且非常耗时。

特征工程包括输入缺失值、编码分类变量、转换和离散化数值变量、删除或审查异常值、缩放特征等。

在本文中,我将讨论机器学习的特征工程的 Python 实现。我比较了以下开源 Python 库:

我将展示要执行的代码:

  • 缺失数据插补
  • 分类编码
  • 变量变换
  • [数]离散化

特征工程管道

大多数特征工程技术从数据中学习参数。例如,为了用平均值估算数据,我们从训练集中获取平均值。为了对分类变量进行编码,我们还利用训练数据定义了字符串到数字的映射。

许多开源 Python 包具有学习和存储设计特性的参数的功能,然后检索它们来转换数据。

特别是, Scikit-learnFeature-engine类别编码器共享了从数据中学习参数的方法 fit 和修改数据的方法 transform

Pandas 也有很多功能工程和数据准备的工具。然而,它缺乏存储学习参数的功能。正因如此,本文就不谈论熊猫了。

用于要素工程的 Python 库

Scikit-learnFeature-engine类别编码器共享 fittransform 功能,从数据中学习参数,然后转换变量。

然而,这些软件包在 I)输出、ii)输入和 iii)通用性方面存在一些差异。

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

用于要素工程的 Python 包之间的主要差异-由作者创建

输出:NumPy 数组对 Pandas 数据帧

特征引擎和分类编码器返回熊猫数据帧。Scikit-learn 返回 NumPy 数组。

NumPy 数组针对机器学习进行了优化,因为 NumPy 的计算效率更高。熊猫数据框架更适合数据可视化。

通常,我们希望了解特征工程转换如何影响变量分布以及它们与其他变量的关系。Pandas 是一个很好的数据分析和可视化工具,因此,返回 Pandas 数据帧的库在本质上对数据分析更“友好”。

如果我们选择使用 Scikit-learn,我们可能需要添加一两行代码来将 NumPy 数组转换成 Pandas 数据帧,以便继续进行数据可视化。

输入:数据切片与完整数据集

数据科学家对不同的变量子集应用不同的特征工程方法。

例如,我们只估算缺失数据的变量,而不是整个数据集。我们将对数字变量采用某些插补方法,对类别变量采用其他方法。

Python 库提供了选择我们想要转换的变量的可能性。

使用特征引擎类别编码器,我们选择要在转换器中转换的变量。

使用 Scikit-learn,我们需要使用一个特殊的转换器将数据集分割成所需的变量组。我们可以通过使用的 ColumnTransformer 或者 Feature-engine 的 SklearnWrapper 来实现。使用 Feature-engine 的 SklearnWrapper 的美妙之处在于输出是一个熊猫数据帧!

多才多艺

有时,我们不知道哪种转换技术返回的预测变量最多。应该做等宽还是等频离散化?我们应该用平均值、中间值还是任意数来估算?

大多数 Scikit-learn 转换器是集中式的,这意味着一个转换器可以执行不同的转换。例如,我们可以通过简单地改变 Scikit-learn 中 KBinsDiscretizer()的参数来应用 3 种离散化技术。另一方面,特征引擎为离散化提供了 3 种不同的转换器。

插补也是如此;通过更改 SimpleImputer()的参数,我们可以使用 Scikit-learn 执行不同的插补技术,而 Feature-engine 有几个转换器,每个转换器最多可以执行 2 种不同的插补变量。

使用 Scikit-learn,我们可以轻松地对特征工程变压器的参数进行网格搜索。使用特征引擎,我们需要事先决定要使用哪种转换。

在博客的其余部分,我将比较 Scikit-learn、特征引擎和类别编码器中缺失数据插补、分类编码、数学转换和离散化的实现。

缺失数据插补

插补包括用缺失值的概率估计值替换缺失数据。缺失数据插补方法有多种,每种方法都有不同的用途。

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

缺少数据—图片由 Willi HeidelbachPixabay 获得

如果你想了解更多关于这些技术,它们的优点和局限性,以及我们何时应该使用它们,请查看课程“机器学习的特征工程”。

Scikit-learn 和 Feature-engine 支持许多数值和分类变量的插补程序。

两个库都包含最常见插补技术的功能:

  • 均值和中位数插补
  • 频繁类别插补
  • 任意值插补
  • 添加缺失的指标

特征引擎还可以执行:

  • 随机样本插补
  • 完整的案例分析
  • 分布极值的插补

另一方面,Scikit-learn 在其功能中提供了链式方程 的 多元插补。

特征引擎转换器可以根据插补方法自动识别数值或分类变量。有了特征引擎,当我们估算数字变量或分类变量时,我们不会无意中添加一个字符串。使用 Scikit-learn,我们需要事先选择要修改的变量。

Scikit-learn 的 SimpleImputer(),只需调整策略fill_value 参数,即可执行所有插补技术。因此,我们可以自由地对插补技术进行网格研究,如 Scikit-learn 文档中的代码实现所示。相反,特征引擎具有至少 5 个不同的插补转换器。

在接下来的段落中,我们将首先进行中位数插补和最常见类别的插补。

均值/中位数插补

对于中位数插补,Feature-engine 提供了 MeanMedianImputer(),Scikit-learn 提供了 SimpleImputer()。

Feature-engine 的 MeanMedianImputer()自动选择训练数据集中的所有数值变量。另一方面,Scikit-learn 的 SimpleImputer()将转换数据集中的所有变量,如果在执行过程中有分类变量,它将产生一个错误。

特征引擎

下面,我们看到使用中位数作为插补的 MeanMedianImputer() 的实现。简单地将插补 _ 方法的“中值”替换为“平均值”,即可实现平均值插补。

import pandas as pd
from sklearn.model_selection import train_test_split
from feature_engine.imputation import MeanMedianImputer

# Load dataset
data = pd.read_csv('houseprice.csv')

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['Id', 'SalePrice'], axis=1),
    data['SalePrice'],
    test_size=0.3,
    random_state=0
    )

# set up the imputer
median_imputer = MeanMedianImputer(
    imputation_method='median',
    variables=['LotFrontage', 'MasVnrArea']
    )

# fit the imputer
median_imputer.fit(X_train)

# transform the data
train_t= median_imputer.transform(X_train)
test_t= median_imputer.transform(X_test)

特征引擎返回原始数据帧,其中只有数字变量被修改。欲了解更多详情,请访问 MeanMedianImputer()文档

sci kit-学习

使用简单估算器(),我们还可以通过其参数指定均值或中值估算方法:

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.impute import SimpleImputer

# Load dataset
data = pd.read_csv('houseprice.csv')

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['Id', 'SalePrice'], axis=1),
    data['SalePrice'],
    test_size=0.3,
    random_state=0
    )

# Set up the imputer
median_imputer = SimpleImputer(strategy='median')

# fit the imputer
median_imputer.fit(X_train[['LotFrontage', 'MasVnrArea']]) # transform the dataX_train_t = median_imputer.transform(
    X_train[['LotFrontage', 'MasVnrArea']]
    )X_test_t = median_imputer.transform(
    X_test[['LotFrontage', 'MasVnrArea']]
    )

如上所述,Scikit-learn 要求我们在将数据帧传递到插补转换器之前对其进行切片,而 Feature-engine 则不需要这一步。

前面代码块的结果是一个 NumPy 数组,其中有两个输入的数值变量。

频繁类别插补

频繁类别插补包括用变量的最频繁类别替换分类变量中的缺失值。

特征引擎

如果我们将插补方法参数设置为“频繁”,CategoricalImputer()会用其模式替换分类变量中的缺失数据。

我们可以指出要估算的变量,如下所示;否则,估算器将自动选择并估算训练数据集中的所有分类变量。

import pandas as pd
from sklearn.model_selection import train_test_split
from feature_engine.imputation import CategoricalImputer

# Load dataset
data = pd.read_csv('houseprice.csv')

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['Id', 'SalePrice'], axis=1),
    data['SalePrice'],
    test_size=0.3,
    random_state=0
    )

# set up the imputer
imputer = CategoricalImputer(
    imputation_method=’frequent’,
    variables=['Alley', 'MasVnrType']
    )

# fit the imputer
imputer.fit(X_train)

# transform the data
train_t= imputer.transform(X_train)
test_t= imputer.transform(X_test)

结果是一个原始变量的数据框架,其中显示的变量是估算的。

sci kit-学习

通过使用“最频繁”作为插补策略,简单插补器()也用于频繁类别插补。

请注意,SimpleImputer()的“最频繁”插补策略可以对数字变量和分类变量进行操作。所以我们需要非常小心。

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.impute import SimpleImputer

# Load dataset
data = pd.read_csv('houseprice.csv')

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['Id', 'SalePrice'], axis=1),
    data['SalePrice'],
    test_size=0.3,
    random_state=0
    )

# set up the imputer
mode_imputer = SimpleImputer(strategy='most_frequent')

# fit the imputer
mode_imputer.fit(X_train[['Alley', 'MasVnrType']])

# transform the data
X_train= mode_imputer.transform(
    X_train[['Alley', 'MasVnrType']]
    )X_test= mode_imputer.transform(
    X_test[['Alley', 'MasVnrType']]
    )

前面代码块的输出是一个 Numpy 数组,包含两列估算变量。

分类编码

机器学习模型需要数字格式的输入数据。因此,数据科学家需要将分类变量转换成数字变量。这些过程被称为分类变量编码。

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

分类变量以标签而不是数字作为值——来自 PixabayJozef Mikulcik 举例说明。

有许多方法可以对分类变量进行编码。我们选择的编码方法完全是数据环境和业务问题驱动的;我们如何表示和设计这些特性会对模型的性能产生重大影响。

Scikit-learn特征引擎分类编码器提供广泛的分类编码器。这三个库都提供了常用的编码器,比如一键编码和顺序编码,我们将在下面演示。

特征引擎和类别编码器还提供基于目标的编码方法,如目标均值编码和证据权重。

总的来说,分类编码器是分类编码领域的领跑者,提供了最广泛的编码技术。它们最初来源于大量的科学出版物。

分类编码器转换器支持 NumPy 数组和 pandas 数据帧输入格式,是完全兼容的 Scikit-learn 功能,可在管道中使用。除了上面提到的更普遍实现的编码器,类别编码器还提供一些特殊的用例编码器,包括:

在下面的段落中,我们将比较 3 个 Python 开源库中顺序编码的实现。

顺序编码

顺序编码用数字将类别标记为唯一类别的数量。对于具有 n 唯一类别的分类变量,序数编码会用从 0n-1 的整数替换类别。

特征引擎

Feature-engine 的 OrdinalEncoder()仅适用于分类变量,其中可以指明变量列表,否则编码器将自动选择训练集中的所有分类变量。

如果我们选择“任意”作为编码方法,那么编码器将按照标签在变量中出现的顺序分配数字(即先来先服务)。

如果我们选择“有序”,编码器将按照该标签目标值的平均值分配数字。目标平均值较高的标签将被分配数字 0,而目标平均值最小的标签将被分配 n-1。

import pandas as pd
from sklearn.model_selection import train_test_split
from feature_engine.encoding import OrdinalEncoder

# Load datasetdef load_titanic():
    data = pd.read_csv(
    'https://www.openml.org/data/get_csv/16826755/phpMYEkMl'
    )

    data = data.replace('?', np.nan)
    data['cabin'] = data['cabin'].astype(str).str[0]
    data['pclass'] = data['pclass'].astype('O')
    data['embarked'].fillna('C', inplace=True)

    return data

data = load_titanic()

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['survived', 'name', 'ticket'], axis=1),
    data['survived'],
    test_size=0.3,
    random_state=0
    )

# set up the encoder
encoder = OrdinalEncoder(
    encoding_method='arbitrary',
    variables=['pclass', 'cabin', 'embarked']
    )

# fit the encoder
encoder.fit(X_train, y_train)

# transform the data
train_t= encoder.transform(X_train)
test_t= encoder.transform(X_test)

前面代码块的输出是原始的 pandas 数据帧,其中选择的分类变量被转换成数字。

sci kit-学习

Scitkit-learn 的 OrdinalEncoder() 要求对分类变量的输入进行切片。在编码过程中,数字只是按照标签的字母顺序进行分配。

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OrdinalEncoder

# Load datasetdef load_titanic():
    data = pd.read_csv(
    'https://www.openml.org/data/get_csv/16826755/phpMYEkMl'
    )

    data = data.replace('?', np.nan)
    data['cabin'] = data['cabin'].astype(str).str[0]
    data['pclass'] = data['pclass'].astype('O')
    data['embarked'].fillna('C', inplace=True)

    return data

data = load_titanic()

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['survived', 'name', 'ticket'], axis=1),
    data['survived'],
    test_size=0.3,
    random_state=0
    ) # set up the encoder
encoder = OrdinalEncoder()

# fit the encoder
encoder.fit(
    X_train[['pclass', 'cabin', 'embarked']],
    y_train
    )

# transform the data
train_t= encoder.transform(
    X_train[['pclass', 'cabin', 'embarked']]
    )test_t= encoder.transform(
    X_test[['pclass', 'cabin', 'embarked']]
    )

前面代码块的输出是一个有 3 列的 NumPy 数组,对应于估算变量。

类别编码器

分类编码器’’ OrdinalEncoder()允许我们指定变量/列作为参数进行转换。如果我们知道类本身有某种真正的顺序,也可以传递一个可选的映射字典。否则,这些类被认为没有真正的顺序,数字被随机分配给标签。

import pandas as pd
from sklearn.model_selection import train_test_split
from category_encoders.ordinal import OrdinalEncoder

# Load datasetdef load_titanic():
    data = pd.read_csv(
    'https://www.openml.org/data/get_csv/16826755/phpMYEkMl'
    )

    data = data.replace('?', np.nan)
    data['cabin'] = data['cabin'].astype(str).str[0]
    data['pclass'] = data['pclass'].astype('O')
    data['embarked'].fillna('C', inplace=True)

    return data

data = load_titanic()

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['survived', 'name', 'ticket'], axis=1),
    data['survived'],
    test_size=0.3,
    random_state=0
    )

# set up the encoder
encoder = OrdinalEncoder(cols=['pclass', 'cabin', 'embarked'])

# fit the encoder
encoder.fit(X_train, y_train)

# transform the data
train_t= encoder.transform(X_train)
test_t= encoder.transform(X_test)

转换

数据科学家使用各种数学函数(如对数、幂和倒数)来转换数值变量,其总体目标是获得更“高斯”的分布。

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

数学变换——图片由 Gerd AltmannPixabay 获得

Scikit-learn 提供了 FunctionTransformer() ,原则上,它可以应用用户定义的任何函数。它将函数作为参数,或者作为 NumPy 方法,或者作为 lambda 函数。

相反,通过诸如 LogTransformer() 和 ReciprocalTransformer()之类的转换器,特征引擎支持使用单个特定转换器的数学转换。

说到“自动”转换,Scikit-learn 和 Feature-engine 都支持 Yeo-Johnson 和 Box-Cox 转换。虽然 Scikit-learn 通过改变“方法”参数将转换集中在 PowerTransformer() 中,但 Feature-engine 有两个单独的 Yeo-JohnsonBox-Cox 转换器。

如果转换在数学上不可行,例如 log(0)或 0 的倒数,Feature-engine 会返回一个错误,而 Scikit-learn 会引入 NaNs,这需要您在之后进行合理性检查。

在接下来的段落中,我们将比较对数转换和 Box-Cox 转换在两个包之间的实现。在演示中,我们使用来自 Kaggle 的房价数据集。

对数变换

对数变换包括对变量进行对数变换。

特征引擎

功能引擎的 LogTransformer()将自然对数或以 10 为底的对数应用于数值变量。它只适用于数值,正值。如果变量包含 0 或负值,转换器将返回一个错误。

与所有功能引擎的转换器一样,LogTransformer()允许我们选择要转换的变量。变量列表可以作为参数传递,或者,转换器将自动选择并转换所有数字变量。

import pandas as pd
from sklearn.model_selection import train_test_split
from feature_engine.transformation import LogTransformer

# Load dataset
data = data = pd.read_csv('houseprice.csv')

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['Id', 'SalePrice'], axis=1),
    data['SalePrice'],
    test_size=0.3,
    random_state=0
    )

# set up the variable transformer
tf = LogTransformer(variables = ['LotArea', 'GrLivArea'])

# fit the transformer
tf.fit(X_train)

# transform the data
train_t = tf.transform(X_train)
test_t = tf.transform(X_test)

sci kit-学习

Scikit-learn 通过其 FunctionTransformer() 将对数函数作为一个 NumPy 方法传递给转换器来应用对数转换,如下所示。

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import FunctionTransformer

# Load dataset
data = data = pd.read_csv('houseprice.csv')

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['Id', 'SalePrice'], axis=1),
    data['SalePrice'],
    test_size=0.3,
    random_state=0
    )

# set up the variable transformer
tf = FunctionTransformer(np.log)

# fit the transformer
tf.fit(X_train[['LotArea', 'GrLivArea']])

# transform the data
train_t = tf.transform(X_train[['LotArea', 'GrLivArea']])
test_t = tf.transform(X_test[['LotArea', 'GrLivArea']])

Box Cox 变换

Box-Cox 变换是一种通过使用变换参数λ来变换非正态变量的方法。

特征引擎

BoxCoxTransformer() 将 Box-Cox 变换应用于数值变量,仅适用于非负变量。

要修改的变量列表可以作为参数传递,或者 BoxCoxTransformer() 将自动选择并转换所有数值变量。

import pandas as pd
from sklearn.model_selection import train_test_split
from feature_engine.transformation import BoxCoxTransformer

# Load dataset
data = data = pd.read_csv('houseprice.csv')

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['Id', 'SalePrice'], axis=1),
    data['SalePrice'],
    test_size=0.3,
    random_state=0
    )

# set up the variable transformer
tf = BoxCoxTransformer(variables = ['LotArea', 'GrLivArea'])

# fit the transformer
tf.fit(X_train)

# transform the data
train_t = tf.transform(X_train)
test_t = tf.transform(X_test)

这个转换器实现的转换是 scipy.stats.boxcox 的转换,并作为熊猫数据帧返回。

sci kit-学习

Scikit-learn 通过其 PowerTransformer() 提供了 Box-Cox 和 Yeo-Johnson 变换。Box-Cox 要求输入数据必须是严格的正值。

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PowerTransformer

# Load dataset
data = data = pd.read_csv('houseprice.csv')

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['Id', 'SalePrice'], axis=1),
    data['SalePrice'],
    test_size=0.3,
    random_state=0
    )

# set up the variable transformer
tf = PowerTransformer(method=”box-cox”)

# fit the transformer
tf.fit(X_train[['LotArea', 'GrLivArea']])

# transform the data
train_t = tf.transform(X_train[['LotArea', 'GrLivArea']])
test_t = tf.transform(X_test[['LotArea', 'GrLivArea']])

与所有 Scikit-learn 转换器一样,结果以 NumPy 数组的形式返回。

[数]离散化

离散化将连续的数值变量划分为离散的和连续的区间,这些区间跨越了变量值的整个范围。离散化通常用于提高给定变量的信噪比,减少异常值的影响。

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

离散化意味着将连续变量分类为离散区间——由 PolskiPixabay 生成图像

Scikit-learn 提供了 KBinsDiscretizer()作为集中式转换器,通过它我们可以进行等宽、等频和 k 均值离散化。使用 KBinsDiscretizer(),我们可以通过在所有离散化技术上进行网格搜索来优化模型。

使用特征引擎,离散化过程通过单独的转换器实现。功能-引擎支持

  • 等宽离散化
  • 等频离散化
  • 决策树离散化
  • 任意离散化。

此外,Scikit-learn 允许我们只通过设置编码参数就可以直接对 bin 进行热编码。使用特征引擎,如果我们希望将容器视为类别,我们可以在离散化转换器的后端运行任何类别编码器。

在下面的段落中,我们将比较包之间的等频率离散化的实现。

等频率离散化

这种类型的离散化将变量分成预定义数量的连续区间。容器间隔通常是百分位数。

特征引擎

EqualFrequencyDiscretiser()将数值变量值分类为等比例观察值的连续区间,其中区间限制根据百分位数计算。

变量应被划分的区间数由用户决定。转换器可以将变量作为数字或对象返回(默认为数字)。

特征引擎所固有的,可以指示变量列表,或者离散化器将自动选择训练集中的所有数值变量。

import pandas as pd
from sklearn.model_selection import train_test_split
from feature_engine.discretisation import EqualFrequencyDiscretiser

# Load dataset
data = data = pd.read_csv('houseprice.csv')

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['Id', 'SalePrice'], axis=1),
    data['SalePrice'],
    test_size=0.3,
    random_state=0
    )

# set up the discretisation transformer
disc = EqualFrequencyDiscretiser(
    q=10,
    variables=['LotArea', 'GrLivArea']
    )

# fit the transformer
disc.fit(X_train)

# transform the data
train_t = disc.transform(X_train)
test_t = disc.transform(X_test)

EqualFrequencyDiscretiser()首先找到每个变量的区间边界,因为它符合数据。然后,它通过将值排序到区间来转换变量,并返回一个 pandas 数据帧。

sci kit-学习

Scikit-learn 可以通过其 KBinsDiscretizer() 转换器,将“策略”参数设置为“分位数”来实现等频率离散化。

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import KBinsDiscretizer

# Load dataset
data = data = pd.read_csv('houseprice.csv')

# Separate into train and test sets
X_train, X_test, y_train, y_test = train_test_split(
    data.drop(['Id', 'SalePrice'], axis=1),
    data['SalePrice'],
    test_size=0.3,
    random_state=0
    )

# set up the discretisation transformer
disc = KBinsDiscretizer(n_bins=10, strategy='quantile')

# fit the transformer
disc.fit(X_train[['LotArea', 'GrLivArea']])

# transform the data
train_t = disc.transform(X_train[['LotArea', 'GrLivArea']])
test_t = disc.transform(X_test[['LotArea', 'GrLivArea']])

默认情况下,NumPy 数组输出被一次性编码到一个稀疏矩阵中。这可以进一步配置,例如使用“encode”参数将设置为序号编码方法。

包扎

特征工程是端到端数据科学和机器学习管道中的一个重要组成部分。这是一个迭代过程,每个数据科学家都应该掌握,以优化模型性能。特征工程是非常耗时的,通过了解每个 Python 库的优点和优势来获得这些小小的效率肯定会在你的工作流程中积累起来。

参考

相关文章

本文是机器学习的特征工程系列文章的第八篇。您可以通过以下链接了解有关数据科学家如何预处理数据的更多信息:

  1. 机器学习的特征工程
  2. 变量转换
  3. 学习特征工程的优秀资源

实用 cy thon——音乐检索:短时傅里叶变换

原文:https://towardsdatascience.com/practical-cython-music-retrieval-short-time-fourier-transform-f89a0e65754d?source=collection_archive---------20-----------------------

你想知道更多关于 Cython 的事情吗?在本系列中跟随我,我将向您展示 C-Cython-Python 实现的实际例子

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

《时间的压缩》声谱图,最终幻想 8【https://www.youtube.com/watch?v=l75zjpDpAWs

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

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@stefanobosisio1/membership)

我非常喜欢 Cython,因为它吸取了两个主要编程领域的精华:C 和 Python。这两种语言可以以一种简单明了的方式结合在一起,以便为您提供计算效率更高的 API 或脚本。此外,用 Cython 和 C 编写代码有助于您理解常见 python 包(如sklearn)下的内容,让数据科学家更进一步,这与简单的import torch和预定义算法用法相去甚远。

在这个系列中,我将向你展示如何用 C 和 Cyhton 算法来分析音乐,下面是相应的sklearnscipy软件包作为参考。

这一课讲的是短时傅立叶变换或 STFT。这种算法广泛用于分析信号的频率及其随时间的演变。代码存储在以下存储库中:

[## ste boss/音乐 _ 检索

用于检索音乐信息的 python-c-cython 工具小套件

github.com](https://github.com/Steboss/music_retrieval/tree/master/stft)

这些代码对于理解如何构建 Cython 项目、在文件夹中细分代码以及安装最终的包非常有用。

此帖子包含亚马逊联盟计划的外部链接。

外行理论

如果您想立即接触这些代码,可以跳过这一部分。这只是对 STFT 及其理论的简单介绍。

傅立叶变换的主要方面是将信号映射(或者说绘制)到频域,指出构成信号本身的最重要频率。这种映射在许多领域具有广泛的含义:在生物医学工程(例如,研究心电图(ECG)中的频率贡献,以检测可能的疾病或心脏功能障碍 )、计算科学(例如,压缩算法,如mp3, jpeg【⁴)或金融(例如,研究股票价格、债券价格行为、⁵ )。这种映射也有利于研究音乐信号,因为可以检索和分析主要频率内容,例如,创建流派分类器或类似 Shazam 的应用程序(例如检查我的帖子)。然而,了解频率在时间和幅度上的演变有时是有趣和有帮助的,以便找到特定的噪声或在记录会话中均衡频率,或创建神经网络算法来将语音信号转换为文本(例如 DeepPavlov )。

在实践中,STFT 将时间信号分成等长的小段(window_length),然后计算每段的傅立叶变换。由此产生的分段频率内容可以相对于时间绘制,它被称为频谱图。

实际上,STFT 可以概括为以下几个步骤:

  • 获取一个输入信号(例如 mp3 文件)
  • 将信号乘以窗口函数(例如汉明函数)。这将有助于在每个片段的极端处计算傅立叶变换,以避免信号中可能的不连续性,这种不连续性可能会阻碍傅立叶变换计算
  • 沿着信号/时间滑动一个窗口和一个跳跃大小的窗口,并计算傅立叶变换

图 1 有助于更好地理解 STFT 做了什么。具有定义的幅度(以分贝为单位)和时间(以秒为单位)的输入信号被封装在大小为*窗口大小的 N 个窗口中。*每个 *HopSize,*窗口定义一个信号段,该信号段被傅立叶变换。输出频率(单位:赫兹)可以绘制成时间的函数。

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

图 1: STFT 的缩影。定义了窗口大小和跳跃大小。对于每个窗口段,计算傅立叶变换。频率内容可以显示为时间的函数

最后要记住的是奈奎斯特频率。如果查看频谱图,您会发现最大绘制频率是信号采样频率的一半,以避免傅立叶变换中的混叠问题。这意味着从信号中检索的 N 个复傅立叶系数中,具有采样频率 fs (例如,音频文件通常具有 44100 Hz 的采样频率)的只有一半是有用的,代表从 0 到 fs/2 的频率

要了解更多信息,我强烈推荐这些非常有价值和有用的书籍:

塞顿的 STFT:让我们玩得开心

行动(或活动、袭击)计划

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

图 2:从 Python 到 Cython 和 C 的实现示意图

图 2 显示了在 Cython 和 C 中实现 STFT 的行动计划。整个过程可以分为三个部分,分别使用 Python、Cython 和 C:

  1. Python 接口处理信号的输入/输出和操作:
  • scipypydub打开 mp3/wav 输入文件
  • 左声道和右声道被隔离,只分析channel[:,0]
  • 对信号进行填充,因此元素总数是 2 的幂,这提高了傅立叶变换库的性能fftw

2.Cython 接口将 Cython 输入转换为 memoryviews,然后可以很容易地将 memoryviews 作为指向 C 套件的指针传递:

  • 为了有一个具体的概念,图 3 展示了一个例子,它从一个长度为n_elements的零数组np.zeros中创建一个内存视图

图 3:在 Cython 中创建 memoryview 的例子

3.C 接口执行核心的 STFT 操作。简而言之:

  • fftw元素定义fftw3库域并进行规划。该计划是执行快速傅立叶变换所必需的:

图 4:用 C 语言初始化 fftw 元素和计划

  • 创建一个汉明窗口
  • 执行 STFT 循环:将输入块乘以汉明窗口,计算输出的快速傅立叶变换,存储一半结果。

需要强调的是,当前的结构确保计算最密集的操作在 C 代码中执行,然后所有信息返回给 Python。这可以降低计算成本——因为许多算法仅由 Python 实现,而不是用 C 语言实现——并提高 Python 代码的整体性能。

Python 脚本

代码:https://github . com/ste boss/music _ retrieval/blob/master/STFT/installer/tester . py

Python 脚本处理输入音频文件,并为将要执行的 STFT 准备所有信息。

首先,pydub可以用来打开和读取 mp3 文件,而scipy提供了一个内置功能来读取 wav 扩展名:

图 5:如何打开 mp3 和 wav 文件

然后,我们可以在代码中定义所有的“常数”,并调用 STFT:

图 Python 中关键参数的定义,准备 stft 调用

在图 6 中,定义了windowSizehopSize。如图 1 所示,这两个量可以重叠。一般来说,随着时间的推移,重叠越多,分析点越多,结果越平滑,但代价是更高的计算成本。总的来说,对于本教程,我们可以达到相同的大小,但尽可能自由地尝试。

Cython 代码

代码:https://github . com/ste boss/music _ retrieval/blob/master/STFT/installer/STFT . pyx

Cython 代码通常有两个扩展名:pyxpxd。前者是编写主代码的地方,而后者用于声明。在本教程中,我们将只使用pyx扩展,以便更熟悉 Cython,并且只需处理一段代码。

第一步是在 Cython 中导入我们的 c 代码——稍后我们将看到 c 代码是如何构造的:

图 7:在 Cython 中导入 c 代码

使用cdef extern from YOUR_C_CODE:声明导入 c 代码。接下来,我们要使用的 C 函数的名字,必须和所有类型一起声明,就像我们在 C 代码中一样。因此,函数stft返回一个数组作为指针,所以double*stft C 函数。参数是输入音频通道double *wav_data,最终 STFT 信号内的样本数量int samples,窗口和跳跃大小int windowSize, int hop_Size,采样频率和音频通道长度int sample_freq, int lengthsamples可以计算为:

samples = int((length/windowSize/2))*((windowSize/2)+1))

下一步是创建和声明我们的主函数。,它将在我们的 python 脚本中被调用(这里它的名字是play):

cpdef play(audData, rate, windowSize, hopSize):

cpdef声明下面的函数将包含 C 和 Python 代码和类型。如果我们想直接调用一个 Python 函数和用于声明一个纯 C 函数的cdef,进一步的选项是按照普通 Python 的def

第二个重要的概念是将所有参数传递给主stft C 函数,如图 8 所示

图 8:调用 c 函数 stft 传递 Cython 参数

基本上,内存视图可以很容易地传递给 C 函数,它们将被视为 1D 数组。首先,要创建 memoryview,必须定义类型和大小。图 8 的第 2 行和第 6 行显示了如何创建 1D 内存视图:cdef double[:] name_of_memory_view = content其中[:]定义了一个 1D 内存视图。最后,内存视图可以像第 8 行中对&audData_view[0]&magnitude[0]所做的那样作为&name_of_memory_view[0]传递给 C 函数。在接下来的教程中,我将更详细地向你展示如何处理 2D 内存视图并将它们传递给 C,因为这必须处理内存缓冲区。值得注意的是,在第 8 行中&magnitude[0]作为 0 的向量传递给 C。这允许处理 C 中已经初始化的指针,并用 STFT 值填充它们。

c 代码

code:https://github . com/ste boss/music _ retrieval/blob/master/STFT/c _ code/STFT . c

第一步是导入必要的库:

图 9:用于 STFT 算法的 C 库

fftw3是最重要的库,它允许计算快速傅立叶变换,以及余弦变换等等。

其次,我们需要定义一些常数,如 pi 值和汉明窗函数,来创建汉明窗值。这可以通过以下方式轻松实现:

图 10:为 PI 定义一个常量值和一个函数来创建汉明窗口

至此,我们可以开始玩fftw3了。如图 11 所示,我们需要为大小为windowSize的输入数据stft_data创建一个fftw_complex数组;一个与stft_data具有相同尺寸的输出数组fft_result用于存储傅立叶变换加窗信号,最后一个storage数组用于存储所有变换后的窗口,其尺寸为samples。为了允许fftw计算窗口输入信号的傅立叶变换,我们需要一个傅立叶平面对象,该对象在第 17 行以这种方式创建:

fftw_plan plan_forward;plan_forward = fftw_plan_dft_1d(number_of_elements_in_output, 
                                input_data_to_be_transformed, 
                                output_transformed_data, 
                                flag_for_forward_transform, 
                                flag_for_inverse_transform);

图 11:玩 fftw

最后一步是实现真正的 STFT 算法:

图 12: STFT 在实践中的 C

图 12 帮助您理解 STFT 是如何实现的。首先,用当前窗口大小的信号幅度值填充stft_data数组(第 10 行)。然后对这一段进行傅立叶变换,称为fftw_execute(plan_forward)。实际上,fftw_execute将触发上面定义的傅立叶变换计划的执行,以便变换当前输入并将结果保存在输出数组fft_result中。最后,一半的傅立叶样本保存在storage阵列中,稍后将返回给 Cython,并且chunkPositionhop_size/2更新,因此可以继续下一个窗口——还记得奈奎斯特频率吗?

此时,可以用来自storage的傅立叶变换信号填充magnitude数组,该数组是在 Cython 中创建的内存视图

图 13:填充内存视图大小并将其返回给 Cython

因此,量值将从 C 转移到 Cython。在 Cython 中,可以操作magnitude数组来返回一个 numpy 数组,可以用 Python 读取:

图 14: Cython 零件。magnitude memoryview 被转换成一个 numpy 数组,经过整形后返回给 Python

准备 setup.py 并安装所有东西

这是享受分析 STFT 之前的最后一步。为了在 Cython 中安装 create Python 包,我通常将我的代码分成两个文件夹:c_code,其中存储了stft.cinstaller,其中保存了pyx和 Python 文件。在installer文件夹中,我创建了setup.py文件,这是一个 Python 文件,用于安装和编译 Cython 和 C 代码。代码非常简单:

图 15:编译 Cython 和 C 代码的 setup.py 脚本

在图 15 的代码中,我们可以看到编译代码的主要元素是Extensionsetup。前者定义了当前扩展的名称stft.stftpyx文件列表[stft.pyx]、库列表和编译 C 代码所需的额外参数。特别是,在这种情况下,我们需要将fftw3m 指定为附加库,其中一个声明使用快速傅立叶变换库,另一个声明使用数学库(编译 C 代码时,通常将m添加为-lm,将fftw3 添加为-lfftw3)。额外的参数确保我们在编译 C 时有一个O3优化过程,而std=C99是通知编译器我们正在使用标准版本 C99。最后,setup存储包信息,即最终模块的名称——因此 Python 将当前模块作为import stft导入——版本控制、C 的扩展和 Cython 的任何指令。关于 Cython 指令,我建议你看一下指南

一旦代码准备好,我们就可以像下面这样运行setup.py:

python setup.py build_ext --inplace

build_ext是构建当前扩展的命令,--inplace允许在工作目录中安装当前包。

STFT 的有趣例子

代码:https://github . com/ste boss/music _ retrieval/tree/master/STFT/examples

研究 STFT 的一个很好的例子是 Aphex 双胞胎“方程式”音乐

如果我们分析 300 到 350 秒之间的声谱图:

start = 300*rate 
end   = 350*rate channel1 = audData[:,0][start:end]

设置windowSize=4096hopSize=4096音乐谱图中会出现一张恶魔的脸:

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

图 16:Aphex Twin 的“方程式”中隐藏的恐怖脸(30-40 岁之间)

我希望你喜欢这第一次对 Cython 的介绍:)如果有任何问题或意见,请发邮件给我,地址是:stefanobosisio1@gmail.com

文献学

  1. https://onlinelibrary.wiley.com/doi/full/10.1002/jmri.1160
  2. https://www . science direct . com/science/article/ABS/pii/s 0010482516302104
  3. https://www.scirp.org/html/4708.html
  4. https://www . roe . AC . uk/jawww/teaching/Fourier/compression . html
  5. http://citeseerx.ist.psu.edu/viewdoc/download?doi = 10 . 1 . 1 . 307 . 8732&rep = re P1&type = pdf

熊猫实用数据分析指南:直接营销

原文:https://towardsdatascience.com/practical-data-analysis-guide-with-pandas-direct-marketing-dfc2977a559d?source=collection_archive---------25-----------------------

如何洞察你的营销努力

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

活动发起人Unsplash 上的照片

Pandas 为数据分析和操作提供了许多功能和方法。在本帖中,我们将使用熊猫来深入了解直销数据集。

数据集可在 Kaggle 上获得。它包含通过直邮完成的营销活动的相关数据。我们将研究这个数据集,并试图了解哪些客户可能会花更多的钱。

让我们从将数据集读入数据帧开始。

import numpy as np
import pandas as pddf = pd.read_csv("/content/DirectMarketing.csv")
print(df.shape)
df.head()

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

(图片由作者提供)

数据由 1000 个观察值(即行)和 10 个特征(即列)组成。重点是“AmountSpent”列,它显示了客户到目前为止已经花了多少钱。

在我们开始分析之前,最好确保没有丢失值。

df.isna().sum()
Age              0
Gender           0
OwnHome          0
Married          0
Location         0
Salary           0
Children         0
History        303
Catalogs         0
AmountSpent      0
dtype: int64

“历史”列包含 303 个缺失值。这些用于表示客户尚未购买。我们可以检查列中的其他值,然后决定如何处理缺少的值。

df.History.value_counts()
High      255
Low       230
Medium    212
Name: History, dtype: int64

由于这是一个分类列,我们可以用单词“Nothing”替换缺失的值,表示还没有购买。

df.History.fillna("Nothing", inplace=True)df.isna().sum().sum()
0

花费的金额

我们首先检查“AmountSpent”列的统计数据。

print(f'The average money spent is {df.AmountSpent.mean()}. The median is {df.AmountSpent.median()}')The average money spent is 1216.77\. The median is 962.0

平均值远高于中值,这表明该列不具有正态分布。存在高值的异常值。因此,我们期望“花费金额”列具有右偏分布。

让我们用直方图来检查一下。

df['AmountSpent'].plot(kind='hist', figsize=(10,6))

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

花费金额柱状图(按作者分类的图片)

它与统计数据重叠。大多数观察值都在低位部分,少数异常值达到了高位。

年龄

年龄可能是一个重要的特征,因为直邮营销往往吸引老年人。groupby 函数将为我们提供一个概览。

df[['Age','AmountSpent']].groupby('Age').mean()

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

(图片由作者提供)

中老年人的平均消费金额比年轻人高得多。

我还想看看这场运动是否更侧重于老年人。我们可以检查发送到每个组的目录数量以及平均花费的金额。

df[['Age','Catalogs','AmountSpent']].groupby('Age').agg(['mean','count'])

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

(图片由作者提供)

计数显示了一个组中的观察次数。我们看到越来越多的中年人参与到这场运动中来。发送给年轻客户的平均目录数量略少于老年客户。

正如您所注意到的,我们可以通过向聚合函数传递一个列表来对组值应用多个聚合。

数值变量之间的相关性

在计算相关性之前,我将简单解释一下相关性对于变量的意义。

相关性是每个变量的标准差对协方差的归一化。协方差是一种定量度量,表示两个变量的变化彼此匹配的程度。更简单地说,相关性和协方差表示值是否倾向于以相似的方式变化。

协方差的标准化消除了单位。因此,在正相关的情况下,相关值总是在 0 和 1 之间,在负相关的情况下,相关值总是在 0 和-1 之间。

为了计算数值变量之间的相关性,我们将使用 pandas 的 corr 函数,并用热图可视化结果。

#importing visualization libraries
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inlineplt.figure(figsize=(10,6))
corr = df.corr()
sns.heatmap(corr, annot=True)

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

热图(图片由作者提供)

薪水和花费之间有很强的相关性。商品目录的数量也与消费金额成正相关。

另一方面,孩子的数量和花费的数量有一个小的负相关。

儿童

相关矩阵显示,子女人数和花费金额之间呈负相关。因此,随着儿童数量的增加,我们预计支出会减少。

我们也用 groupby 函数检查一下。我还将包括年龄栏。groupby 函数接受多列,并为每组类别创建一个组。

df[['Age','Children','AmountSpent']]\
.groupby(['Age','Children']).agg(['mean','count'])

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

(图片由作者提供)

总的来说,平均花费随着孩子数量的增加而减少。不过也有一些例外。

性别与婚姻

我们将检查性别和婚姻列中的几个指标。groupby 函数允许对不同的列应用不同的聚合函数。此外,我们可以重命名聚合的列。

用这个例子会更清楚。我想创建基于性别和婚姻栏的小组。然后我会计算:

  • 发送给每个组的平均目录数(平均值)
  • 每组购买的总数量(总和)

我还想适当地重命名这些列。下面是执行此操作的 groupby 语法:

df[['Gender','Married','AmountSpent','Catalogs']]\
.groupby(['Gender','Married'])\
.agg(
    Average_number_of_catalogs = pd.NamedAgg('Catalogs','mean'),
    Total_purchase_amount = pd.NamedAgg('AmountSpent','sum')
)

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

(图片由作者提供)

NamedAgg 方法用于重命名列。更改列名的另一种方法是 Pandas 的重命名功能。

这家零售商绝对应该把重点放在已婚人士身上。

位置

位置也可能是一个重要的指标。让我们根据位置检查“花费金额”列。

df[['Location','AmountSpent']].groupby('Location')\
.agg(['mean','count','sum'])

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

(图片由作者提供)

住在附近的顾客数量是住在远处的顾客数量的两倍多。然而,他们比住在附近的顾客平均花费更多。

零售商可能想多关注住在远处的人。

结论

我们可以更深入地挖掘数据集,并试图获得更多的洞察力。我们还没有检查一些功能。然而,技术是非常相似的。

这篇文章的主要目的是介绍在数据探索中使用的不同技术和方法。当然,熊猫提供了更多的功能和方法。学习和掌握它们的最好方法是大量练习。

我建议研究样本数据集,并尝试探索它们。有免费的资源可以让你找到样本数据集。例如,杰夫·黑尔这篇文章中列出了 10 个寻找数据集的好地方。

感谢您的阅读。如果您有任何反馈,请告诉我。

熊猫 EDA 实用指南

原文:https://towardsdatascience.com/practical-eda-guide-with-pandas-3463ea637609?source=collection_archive---------34-----------------------

学生在不同考试中的表现分析

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

杰斯温·托马斯Unsplash 上拍摄的照片

Pandas 是一个广泛使用的数据分析库,它提供了许多函数和方法来处理表格数据。易于使用的功能的丰富选择使得探索性数据分析(EDA)过程相当容易。

在本帖中,我们将探索 Kaggle 上可用的学生表现数据集。该数据集包含一些关于学生及其在某些测试中的表现的个人信息。

让我们从将数据集读入熊猫数据帧开始。

import numpy as np
import pandas as pddf = pd.read_csv("/content/StudentsPerformance.csv")df.shape
(1000,8)df.head()

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

(图片由作者提供)

有 5 个分类特征和 3 个不同测试的分数。目标是检查这些特征如何影响考试分数。

我们可以从检查考试分数的分布开始。熊猫的plot功能可用于创建核密度图(KDE)。

df['reading score'].plot(kind='kde', figsize=(10,6), title='Distribution of Reading Score')

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

(图片由作者提供)

阅读测试的分数呈正态分布。其他考试成绩和阅读考试差不多。

“种族/民族”栏包含 5 个群体。我想看看各组的平均考试成绩。groupby函数可以执行这项任务。最好也统计一下每组的学生人数。

df[['race/ethnicity','math score','reading score','writing score']].groupby('race/ethnicity').agg({'math score':'mean', 'reading score':'mean', 'writing score':['mean','count']})
.round(1)

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

(图片由作者提供)

如果想对不同的列应用不同的聚合函数,可以将字典传递给agg函数。因为所有测试的计数都是相同的,所以只对一列应用count 函数就足够了。

结果表明,从 A 组到 e 组,平均分稳步上升。

我们可以使用相同的逻辑来概括分类变量和测试分数之间的关系。

更进一步,可以创建嵌套组。让我们使用“性别”、“备考课程”和“数学成绩”列来做一个例子。学生将按性别分组,参加预备课程。然后,将计算每组的平均数学成绩。

df[['gender','test preparation course','math score']].groupby(['gender','test preparation course']).agg(['mean','count']).round(1)

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

(图片由作者提供)

备考课程对男性和女性的数学成绩都有积极的影响。总的来说,男性在数学考试中表现比女性好。

你可能已经注意到了代码末尾的round 函数。它只是将浮点数向上舍入到所需的小数点位数。

我们还可以检查两个分类变量中的组是如何相关的。考虑“种族/民族”和“父母教育水平”栏。每个种族群体的教育水平分布可能不同。

我们将首先创建一个数据框架,其中包含每个种族群体-教育水平组合的人数。

education = df[['race/ethnicity','parental level of education','lunch']].groupby(['race/ethnicity','parental level of education']).count().reset_index()education.rename(columns={'lunch':'count'}, inplace=True)education.head()

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

(图片由作者提供)

第三列可以是任何列,因为它仅用于对属于特定种族-教育水平组合的观察值(即行)进行计数。这就是我们将列名从“午餐”改为“计数”的原因。

“A 组”除“硕士”外,教育水平接近均匀分布。有许多选项可以将我们刚刚创建的教育数据框架可视化。我将 plotly 库的极线图。

import plotly.express as pxfig = px.line_polar(education, r='count', theta='parental level of education',color='race/ethnicity', line_close=True, width=800, height=500)fig.show()

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

(图片由作者提供)

它让我们了解了不同群体的教育水平分布情况。需要注意的是,这个极坐标图不能用来直接比较不同群体的教育水平,因为每个群体的学生人数并不相同。

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

(图片由作者提供)

C 组包含的学生最多。因此,我们使用这个极坐标图来检查每个组内的教育水平分布。

例如,“大专学历”是 c 组中最主要的教育水平。我们可以使用value_counts函数来确认结果。

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

(图片由作者提供)

另一个方便的比较类别的函数是pivot_table。它创建一个由类别组合组成的交叉表。让我们使用“写作分数”上的“午餐”和“父母教育水平”列来做一个例子。

pd.pivot_table(df, values='writing score',index='parental level of education', columns='lunch',aggfunc='mean')

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

(图片由作者提供)

分类变量(即列)被传递给索引和列参数,数值变量被传递给值参数。根据所选的聚合函数(aggfunc 参数),将计算这些值。

数据透视表显示,吃一顿标准午餐可能会提高写作考试分数。同样,随着父母教育水平的提高,学生的成绩往往会更好。

结论

我们发现了一些影响学生考试成绩的因素。当然,您可以检查许多不同的方法。然而,技术是非常相似的。

取决于你寻找什么,你使用的技术倾向于一个特定的方向。然而,一旦你习惯了使用熊猫,你就可以完成表格数据的任何任务。

感谢您的阅读。如果您有任何反馈,请告诉我。

实用的可解释人工智能:贷款审批用例

原文:https://towardsdatascience.com/practical-explainable-ai-loan-approval-use-case-f06d2fba4245?source=collection_archive---------49-----------------------

explainx 概述:开源、快速和可扩展的可解释人工智能 python 库

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

实用可解释的人工智能——构建可信、透明和公正的 ML 模型

黑盒人工智能

在负责执行关键任务的系统中,可解释性极其重要。例如,在医疗保健领域,如果科学家依赖人工智能模型来帮助他们判断病人是否会患癌症,他们需要 100%确定他们的诊断,否则这可能导致死亡,大量诉讼和信任方面的大量损害。本质上,这个问题是如此激烈,以至于可解释性位于这个问题的核心:数据科学家和人类操作员,在这种情况下,医生需要理解机器学习系统是如何表现的,以及它是如何做出决定的。

可解释的人工智能在金融或金融科技领域也很重要,特别是由于在信用评分、贷款审批、保险、投资决策等领域越来越多地采用机器学习解决方案。在这里,机器学习系统的错误决策也是有代价的:因此非常需要了解模型实际上是如何工作的。

使用黑盒人工智能增加了商业风险,并使企业面临严重的负面影响——从信用卡申请到确定疾病到刑事司法。

当我们从整体上看业务如何运作时,黑盒模型不可取的原因就变得更加清楚了:

对于业务决策者,数据科学家需要回答为什么他们可以信任我们的模型的问题,对于 IT 和运营,数据科学家需要告诉他们如果出现错误,他们如何监控和调试,对于数据科学家,他们需要知道他们如何进一步提高他们模型的准确性,最后,对于监管者和审计者,他们需要能够得到我们的人工智能系统是否公平的答案?

进入可解释的人工智能

可解释的人工智能旨在提供清晰透明的预测。一个端到端的系统,为用户提供决策和解释,并最终提供自动反馈,以不断改进人工智能系统。请记住,xAI 是由反馈高度驱动的,因此是人类和 AI 系统之间的双向交互。

最后要明白模型背后的原因,模型的影响,模型在哪里失效,提供什么建议。

Explainx:一个开源、快速、可扩展的可解释人工智能平台。

explainx 是由explainex . AI打造的开源可解释 AI 平台。用 python 编写的 Explainx 旨在帮助数据科学家解释、监控和调试黑盒 AI 模型——目的是帮助构建健壮、无偏见和透明的 AI 应用。

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

explainx 高级架构

在 explainex 架构中,explainex 在我们的 Jupyter 笔记本中的一行代码中提供了对最先进的可解释性技术的访问。

对于这个例子,我们将使用 FICO 提供的 HELOC 数据集。该数据集中的客户要求的信用额度在 5,000-150,000 美元之间。我们的工作是预测他们是否会在两年内按时付款。这个预测可以用来决定房主是否有资格获得信贷额度。

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

贷款申请审批— explainx.ai

对于此示例,我们将训练 CatBoost 分类器模型。培训完成后,我们将使用 explainx xAI 模块来解释我们的模型,并为业务用户构建一个便于理解的叙述!

让我们从打开我们的 Jupyter 笔记本并安装 explainx 库开始。您也可以通过下面的链接克隆存储库:

【https://github.com/explainX/explainx

pip install explainx

让我们导入相关的包:

from explainx import *
import catboost
from sklearn.model_selection import train_test_split

让我们加载并预处理数据集以进行模型构建。该数据集在 explainx 库中已经可用。

X, y = explainx.dataset_heloc()#split data into train and test
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.2, random_state=0

开始训练。为了这个教程,我们打算保持简单!

# Run catboost model
model = CatBoostClassifier(iterations=500,
                          learning_rate=.3,
                          depth=2)# Fit model
model.fit(X_train.to_numpy(), y_train)

训练完成后,我们可以简单地将测试数据传入 explainx 函数,并获得我们的解释!

explainx.ai(X_test, y_test, model, model_name="catboost")

一旦 explainx 开始运行,你需要做的就是将你的浏览器指向 http://127.0.0.1:8050 ,你会看到一个非常漂亮的用户界面,叫做explainex . dashboard .

App running on [https://127.0.0.1:8050/](https://127.0.0.1:8050/)

注意:如果您想以内联方式查看它,只需将 *mode="inline”* 参数传递到 explainx 函数中。

对于本教程,我们不会深入模型构建、模型度量和评估的本质。相反,我们将直接进入解释部分,这是本教程的主要目的。所以让我们开始打开黑匣子吧!

我们将在四个层面上处理该模型:

全局级别解释

局部预测解释

情况分析

功能交互和分布

全局级别解释

我们将使用总体特性重要性和总体特性影响图来给出模型的基本底层逻辑。

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

全局特征重要性

解释:这说明根据 CatBoost 模型,ExternalRiskEstimate, MSinceMostRecentInq and PercentTradesNeverDelq是对RiskPerformance.影响最大的前三个变量,这三个变量代表风险估计、信用查询和债务水平信息:评估风险时极其重要的类别。

这些信息让我们对特性的贡献有了一个大致的了解,但是要了解这些特性对RiskPerformance有正面还是负面的影响,我们需要参考特性影响图。

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

全球功能影响

这个图表让我们对模型逻辑有了更多的了解。我们可以清楚地观察到ExternalRiskEstimate对预测变量产生了积极的影响——将它推向“良好的信用风险表现”,这也符合我们的直觉。为此,我们必须使用一点我们在金融领域的知识:ExternalRiskEstimate是一些风险标记的合并版本(越高越好),因此我们自动了解到这个变量将总是积极地影响预测。然后我们有NumSatisfactoryTrades:“满意”账户(“交易”)的数量对良好信用的预测概率有显著的积极影响。

然而,在低端,拖欠变量将整体预测推向 0(在这种情况下,申请被拒绝)。这很有趣,我们甚至可以更深入地挖掘,看看这种不良行为的负面影响什么时候会消失?(要自己尝试的东西!)

现在,我们已经了解了每个特性如何影响预测,我们可以继续解释针对特定客户的单个预测。为此,我们将使用影响图或决策图来帮助我们获得特定预测的归因分数。为了进一步支持我们的分析,我们将计算最接近我们试图预测的相似轮廓。

局部预测解释

让我们为数据中第 9 行的客户解释一下。对于这个特定的客户,申请被批准是因为RiskPerformance是“好的”,并且我们的模型也对其进行了正确的分类!

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

客户编号 9 —本地预测解释

让我们探索一下模型逻辑:

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

对客户# 9 的本地功能影响

这张图表清楚地显示了三个积极的和三个消极的影响变量。根据该模型,MSinceMostRecentInq对变量有最积极的影响。这告诉我们,这个变量的值越大,就意味着自最近一次查询以来超过一个月没有惩罚。然后我们有了ExternalRiskEstimate,它再次在将预测推向“良好信用行为”方面发挥了积极作用。然而,PercentTradesNeverDelq对预测产生了负面影响:如果该变量的值非常小,可能会出现这种情况,因为该变量的值越小,获得良好信用评分的可能性就越低。

简而言之,这些发现符合我们的心理模型,因为每个变量的归因分数都是正确分配的。为了进一步支持我们的分析,我们将找到类似的客户!

Explainx 带有一个内置的原型分析功能,该功能提供了一个更加全面和综合的视图,说明为什么申请人的决定可能是合理的。

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

上表描述了与所选申请人最接近的五个用户概况。基于该方法分配给每个简档的重要性权重,我们看到零列下的原型是迄今为止最具代表性的用户简档。这从特征相似性中(直观地)得到了证实,其中该原型的超过 50%的特征(23 个中的 12 个)与我们想要解释其预测的所选用户的特征相同。此外,银行员工在查看原型用户及其特征时,会推测被批准的申请人属于 ExternalRiskEstimate 值较高的组。这个理由让银行员工在批准用户的申请时更有信心。

情况分析

现在,让我们探索不同的场景,看看模型的表现如何。我们可以在数据表中应用数据过滤器(不需要编写 SQL 查询来过滤您的数据),并非常容易地解释多个实例和场景。

当您试图理解特定集群或数据组的行为时,这是非常有用的。例如,我们想看看当ExternalRiskEstimate是> 60 而MSinceOldestTradeOpen大于 200 时,模型是否赋予用户相同的权重。

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

应用的数据过滤器—解释 x

从下面的图表中,我们可以清楚地看到外部风险估计的优势。

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

RiskEstimate > 60 和 TradeOpen > 200 时的功能影响

当外部风险估计值大于 60 时,它被视为一个积极的信号,也符合我们的内部心理模型:外部风险估计值实际上是单调递减的,这意味着随着外部风险估计值的增加,不良信用评分的概率下降!因此,在这个风险估计值大于 60 的集群中,我们将拥有更多获得信贷额度的优质客户。我们可以通过使用特征相互作用图,特别是部分相关性图来证实这一点:

特征交互和分布

部分相关图验证了我们的假设。在下图中,红色=良好的风险表现(信用额度扩大),银色=不良的风险表现(信用额度被拒绝)。

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

我们可以清楚地看到,随着外部风险评估值的增加,其对输出的影响也增加,我们有更多良好风险表现的实例。随着外部风险估计值的上升,我们看到红点的浓度越来越高,这很有意义!

结论

数据科学家可以使用 explainx 通过查看不同变量之间的交互以及它们如何影响整体预测来进一步探索模式。最后,让我们总结一下我们的发现,以便业务用户理解:

  • 根据 CatBoost 模型,ExternalRiskEstimate, MSinceMostRecentInq and PercentTradesNeverDelq是对RiskPerformance.影响最大的前三个变量
  • ExternalRiskEstimate对预测变量产生积极影响——将其推向“良好信用风险”,但违约变量将整体预测推向“不良信用风险”(在这种情况下,申请被拒绝)。
  • 对于我们的客户# 9,RiskPerformance = Good,ExternalRiskEstimate在将预测推向“良好信用行为”方面发挥了积极作用。然而,PercentTradesNeverDelq对预测产生了负面影响:如果该变量的值非常小,可能会出现这种情况,因为该变量的值越小,获得良好信用评分的可能性就越低。
  • 我们发现客户与我们的客户# 9 有着非常相似的行为和可变的价值观:这进一步加强了我们的假设。
  • 我们能够通过进一步研究 PDP 来验证模型的逻辑,PDP 清楚地向我们展示了增加ExternalRiskEstimate的值如何增加贷款批准的概率。
  • 数据科学家可以进一步探索类似的过程,并构建任何人都可以轻松理解的更全面的数据叙述。

我希望你们都喜欢这个案例研究。可解释性是极其重要的,在今天更是如此——因此,对数据科学家来说,展示你对人工智能如何工作的理解的能力是一项至关重要的技能。这才是人类真正的本质——AI 理解,AI 民主化。

下载讲解:https://github.com/explainX/explainx文档:https://explainx-documentation.netlify.app/

Python 中数据清理的实用指南

原文:https://towardsdatascience.com/practical-guide-to-data-cleaning-in-python-f5334320e8e?source=collection_archive---------25-----------------------

了解如何为机器学习算法准备和预处理数据

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

Ashwini Chaudhary 在 Unsplash 上拍摄的照片

在你进入机器学习(ML)算法的奇妙世界之前,有一个小问题,你可以通过它来预测未来:数据准备数据预处理

数据准备是臭名昭著的21 世纪最性感的工作 中不性感的部分。

由于 Python 和 r 中提供了各种专用的库和包,训练 ML 算法并利用它们来预测目标变量是很容易的事情。然而,在数据科学和 ML 世界中,垃圾进,垃圾出(GIGO)的古老格言仍然适用。

数据准备活动将原始数据转换成能够被 ML 算法有效和高效使用的形式、形状和格式。它是 ML 流程的重要组成部分,可以决定 ML 流程的成败。

从业者一致认为,构建机器学习管道的绝大部分时间都花在了特征工程和数据清理上。然而,尽管这个话题很重要,却很少被单独讨论。

数据清理只是数据准备活动的一个组成部分,数据准备活动还包括特征选择、数据转换、特征工程和降维。

根据定义,数据处理活动和数据清理对于每组原始数据都是独一无二的,因为实际的 ML 项目都有其固有的特性。尽管如此,某些活动是标准的,应该应用,或者至少在模型训练之前检查原始数据。

不管要修复的数据错误的类型如何,数据清理活动通常包括两个阶段:(1)错误检测,其中各种错误和违规被识别并可能由专家验证;以及(2)错误修复,其中应用对数据库的更新(或向人类专家建议)以将数据带到适合于下游应用和分析的更干净的状态。

警告!

在我们探索各种标准数据清理活动之前,需要注意一点。正如我在之前的一篇文章中提到的:在将你的整个数据分割成训练/测试/验证子集之后,应该对数值训练数据集执行以下所有操作,以避免数据泄露。只有这样,一旦您有了一个干净的训练数据集,如果需要,在测试(和验证)数据集和目标变量上重复相同的活动集。

在下面的所有代码片段中,按照常规符号,X_train指的是训练输入数据集。

基本数据清理

下面的操作应该成为你的 ML 项目的起点,应用到你得到的每一个数据。

识别并删除零方差预测值

零方差预测值是指在整个观测范围内包含单个值的输入要素。因此,它们不会给预测算法增加任何值,因为目标变量不受输入值的影响,这使得它们是多余的。一些 ML 算法也可能遇到意外的错误或输出错误的结果。

Pandas 提供了一个简短的函数来计算和列出 Pandas 数据帧中每一列的唯一值的数量:

X_train.nunique()

当要删除的列不多时,通过X_train.drop(columns=['column_A', 'column_B'], inplace=True)从 Pandas 数据帧中删除特定的列非常简单。使用多个零方差列实现相同结果的更可靠的方法是:

X_train.drop(columns = X_train.columns[X_train.nunique() == 1],
    inplace = True)

上面的代码将删除所有只有一个值的列,并更新X_train数据帧。

评估具有很少唯一值的列

对于唯一值很少的列(即低方差或接近零的方差),应该给予特别的考虑。这样的列不是要从数据集中删除的自动候选列。例如,按照设计,序数分类列不应该有大量的唯一值。

直觉上,我们可以天真地删除低方差列,但如果这样的预测器实际上对模型学习有帮助呢?例如,假设分类问题中的二元特征有许多 0 和几个 1(接近零的方差预测值)。当这个输入特征等于 1 时,目标变量总是相同的;然而,在该特征为零的情况下,它可以是任何一个可能的目标值。保留这个专栏作为我们的预测指标之一当然是有道理的。

因此,应该利用上下文考虑和领域知识来评估是否应该从我们的数据集中删除这样的低方差列。例如:

  • 考虑将它们编码为序数变量
  • 考虑将它们编码为分类变量
  • 考虑通过一些降维技术(如主成分分析(PCA ))来组合这些低方差列

我们可以手动计算每列中唯一值的数量占观察总数的百分比,如下所示:

from numpy import uniquefor i in range(X_traain.shape[1]):
    num = len(unique(X_train.iloc[:, i]))
    percentage = float(num) / X_train.shape[0] * 100
    print('%d, %d, %.1f%%' % (i, num, percentage))

上面的代码将打印出所有列的列表,以及唯一值的计数及其占观察总数的百分比。

或者,我们可以利用 scikit-learn 库的[VarianceThreshold](https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.VarianceThreshold.html) 类来识别并删除低方差列。使用VarianceThreshold类时要格外小心,因为它被设计用来删除低于参数化阈值的列。

处理重复数据

最有可能的是,应该从数据中删除重复的行,因为它们很可能是多余的。

Pandas 提供了一个简单的函数来检查数据帧中的重复行。请注意,这将只显示第二行(以及任何更高一级的行),因为被复制的第一行不被认为是重复的。

X_train[X_train.duplicated()]

如果在分析完重复记录后,您想继续删除它们,一行代码就可以实现:

X_train.drop_duplicates(inplace = True)

离群点检测

离群值是在给定数据集的上下文中看起来很少或不太可能的任何数据点。领域知识和主题专业知识对于识别异常值很有用。尽管考虑到异常值的上下文性质,没有标准的异常值定义,但是可以使用各种统计和绘图方法来识别和适当地处理它们。

与低方差列类似,异常值观察值不会自动删除。相反,这些应该进一步分析,以确定它们是否真的是异常的。

盒须图是直观显示数据框架中数值异常值的简单而基本的方法:

X_train.boxplot()

现在让我们来看看一些识别异常值的统计技术。

使用标准偏差(SD)

用于异常值检测的 SD 技术可以应用于呈现高斯或类高斯分布的所有数值特征。作为复习,回想一下:

  • 68%的正态分布观测值位于平均值的±1 SD 范围内
  • 95%的正态分布观测值位于平均值的±2sd 范围内
  • 99.7%的正态分布观测值位于平均值的±3 SD 范围内

以下代码行将选择并删除值大于每个数字列的指定 SDx 的所有行。3 SDs 是标准阈值;然而,2 个 SDs 可用于小数据集,4 个 SDs 可用于相对大的数据集。

使用四分位数间距(IQR)

我们可以使用 IQR 来识别输入要素中不符合正态或类正态分布的异常值。超出指定阈值的值(通常,高于第 75 百分位但低于第 25 百分位的 1.5 倍 IQR)将被过滤掉,以供进一步分析。

下面的代码片段将过滤掉阈值为 1.5 的所有数值列中的异常值。

本地异常因素(LOF)

从 scikit-learn 的文档,“LOF 算法是一种无监督的异常检测方法,它计算给定数据点相对于其邻居的局部密度偏差。它将密度远低于其相邻样本的样本视为异常值。”。原文可以在这里找到

[LocalOutlierFactor](https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.LocalOutlierFactor.html)fit_predict方法预测数据帧中的每一行是否包含数值异常值(-1)或(1)。有异常值的行标记为-1,否则标记为 1。下面是一个简单实用的例子:

关于 LOF 有一点需要注意:它不允许在传递给 predict 方法的数据中有空值或缺失值。

统计估算缺失值

只是重申一个显而易见的事实,丢失值在现实生活中并不少见。大多数 ML 算法无法处理缺失值,并且会在模型训练期间抛出错误。因此,数据集中这种丢失的值应该被丢弃(最天真的方法,并且要尽可能避免——数据是新的货币!)或以某种方式进行逻辑上的估算。

通常用于此类插补的某些有效描述性统计数据包括:

  • 列的平均值
  • 列的中值
  • 列的模式值
  • 其他一些共同的价值观

查找和检测缺失值或空值的一些简单方法是执行以下函数之一:

# display the count of non-null values in each column of a DF
df.info()# display the count of null values in each column of a DF
df.isnull().sum()

使用 Python 的内置函数统计输入缺失值非常简单。以下函数计算每一列的描述性统计数据,并使用计算出的统计数据填充该特定列中的所有空值:

# using mean to fill missing values
df.fillna(df.mean(), inplace = True)# using median to fill missing values
df.fillna(df.median(), inplace = True)# using mode to fill missing values
df.fillna(df.mode().iloc[0], inplace = True)# using a specific constant to fill missing values
df.fillna(0, inplace = True)

但是,请记住,描述性统计数据只能在训练数据集上计算;然后应该使用相同的统计来估算训练和测试数据中的任何缺失值。上述方法适用于简单的训练/测试分割;然而,当使用 k-fold 交叉验证评估模型时,这实际上变得不可能——因为分裂是在单个函数调用中多次完成和重复的。

Scikit-learn 的PipelineSimpleImputer来拯救我们了。

SimpleImputer的独立实现

[SimpleImputer](https://scikit-learn.org/stable/modules/generated/sklearn.impute.SimpleImputer.html)类通过以下步骤进行数据转换:

  • 使用要使用的描述性统计类型定义分类。均支持均值、中值、众数和特定的常数值
  • 拟合定型数据集,根据定型数据计算每列的统计信息
  • 将拟合的估算值应用于训练和测试数据集,以将第二步中计算的统计值分配给这两个数据集中的缺失值

下面是一个简单的演示:

用管道实现简单输入

Scikit-learn 的管道允许我们在单个步骤中应用最终估计器模型之前顺序执行多个数据转换。通过确保使用相同的样本来训练变压器和预测器,这可以防止数据“在交叉验证中从测试数据泄漏到训练模型中”(来自文档)。

最佳实践是在使用交叉验证时利用 Pipeline,如下所示:

一个简单的for循环也可用于分析SimpleImputer中所有四种不同的插补策略:

上面列出了每种估算策略的平均准确度分数。

使用 Pipeline,通过新的、具有潜在缺失值的实时数据来预测目标变量,如下所示:

# define pipeline
pipeline = Pipeline(steps=['i', SimpleImputer(strategy='mean')),
    ('m', RandomForestClassifier())])# fit the model
pipeline.fit(X, y)# predict on new data using the fitted model
pipeline.predict(new_data)

kNN 缺失值插补

除了使用描述性统计来估算缺失值,还可以使用 ML 算法来预测缺失值。简单的回归模型可用于预测缺失值;然而,k-最近邻(kNN)模型在实践中也被发现是有效的。

Scikit-learn 的[KNNImputer](https://scikit-learn.org/stable/modules/generated/sklearn.impute.KNNImputer.html)类支持 kNN 插补——其用法与SimpleImputer非常相似。就像SimpleImputer一样,在管道中实现之前,我将首先演示KNNImputer的独立使用。

用流水线实现 KNNImputer

现在,让我们看看如何在管道中实现它以进行有效的验证:

我们还可以应用一个for循环来检查多个k_neighbors参数,以根据我们的精度指标确定最佳参数:

使用包含缺失值的新实时数据来预测目标变量的方法与上述SimpleImputer中的方法相同。

结论

这就是我这次在 Python 中针对机器学习项目的具体数据清理任务。

如果您想讨论任何与数据分析和机器学习相关的问题,请随时联系 me

下次见——摇滚起来!

灵感和参考

机器学习大师的杰森·布朗利

[1]郑,a .,&卡萨里,A. (2018)。前言。在机器学习的特征工程:数据科学家的原则和技术(第 vii 页)。塞瓦斯托波尔,加利福尼亚州:奥赖利。

[2],国际货币基金组织,&楚,X. (2019)。引言。在数据清理(第 1 页)中。纽约:计算机协会。

实体解析实用指南—第 1 部分

原文:https://towardsdatascience.com/practical-guide-to-entity-resolution-part-1-f7893402ea7e?source=collection_archive---------13-----------------------

理解大数据

这是关于实体解析的小型系列文章的第 1 部分

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

照片由亨特·哈里特Unsplash 拍摄

什么是实体解析(ER)?

实体解析(ER)是在缺少连接键的情况下,在代表现实中同一事物的不同数据记录之间创建系统链接的过程。例如,假设您有一个在 Amazon 上销售的产品数据集,和另一个在 Google 上销售的产品数据集。它们可能有稍微不同的名称、稍微不同的描述、可能相似的价格和完全不同的唯一标识符。人们可能会查看这两个来源的记录,并确定它们是否涉及相同的产品,但这并不适用于所有记录。我们需要查看的潜在对的数量是 x G,其中 A 是亚马逊数据集中的记录数量,G 是谷歌数据集中的记录数量。如果每个数据集中有 1000 条记录,那么就有 100 万对要检查,而这只是针对 2 个相当小的数据集。随着数据集越来越大,复杂性会迅速增加。实体解析是解决这一挑战的算法,并以系统和可扩展的方式导出规范实体。

我为什么要关心 ER?

从数据中释放价值通常依赖于数据集成。通过整合关于感兴趣的实体的不同数据片段而创建的整体数据图,在为决策提供信息方面比部分或不完整的视图有效得多。例如,如果汽车制造商的保修分析师能够通过运行过程中产生的传感器读数,从供应链开始,到装配到车辆中,全面了解与相关零件相关的所有数据,她就可以更有效地诊断索赔。类似地,如果风险投资者对潜在公司的所有数据有一个综合的看法,从团队的质量到其在市场上的吸引力和围绕它的传言,她可以更有效地选择最佳投资。执法、反恐、反洗钱等众多工作流也需要集成的数据资产。然而,数据(尤其是第三方数据)的不幸现实是,它通常是特定应用程序或流程的耗尽物,并且它从未被设计为与其他数据集结合使用来为决策提供信息。因此,包含关于同一现实世界实体的不同方面信息的数据集通常存储在不同的位置,具有不同的形状,并且没有一致的连接键。这就是 ER 特别有用的地方,它可以系统地集成不同的数据源,并提供感兴趣的实体的整体视图。

我怎么呃?

概括来说,ER 有 5 个核心步骤:

  1. 源规范化 —清理数据并将不同的源协调到一个通用的要素(列)模式中,该模式将用于评估潜在的匹配
  2. 特征化和块密钥生成 —为块密钥创建特征,块密钥是可能在匹配记录之间共享的目标令牌,以将搜索空间从 N 限制为在计算上更易于管理的空间
  3. 生成候选对——使用阻塞连接键创建潜在的候选对。这本质上是块键上的自连接,通常使用图形数据结构来实现,单个记录作为节点,潜在的匹配作为边
  4. 匹配评分和迭代 —通过匹配评分功能决定哪些候选对实际匹配。这可以是基于规则的,但是通常更好地实现为学习算法,其可以在非线性决策边界上适应和优化
  5. 生成实体 —消除图形中不匹配的边,并生成已解析的实体和到各个源记录的关联映射

在接下来的几篇文章中,我将深入研究上面的每一个步骤,通过一个具体的例子,提供深入的解释,以及如何大规模实现它们的 PySpark 代码示例。

希望这是一次有益的讨论。如果您有任何意见或问题,请随时联系我们。Twitter|Linkedin|Medium

查看第 2 部分源标准化

实体解析实用指南—第 2 部分

原文:https://towardsdatascience.com/practical-guide-to-entity-resolution-part-2-ab6e42572405?source=collection_archive---------17-----------------------

源归一化

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

规范化数据就像锻造金属一样,需要精确和小心。照片由乔尼·古铁雷斯——乔尼博士多媒体Unsplash 上拍摄

这是关于实体解析的小型系列的第 2 部分。如果你错过了,请查看 第一部分

本系列的第 2 部分将重点关注实体解析的源规范化步骤,并将使用在这里获得的Amazon-Google products 数据集作为示例来说明思路和实现。本系列的其余部分也将参考这个例子。该数据集包含两个不同的产品目录,其中包含引用同一物理产品的记录。目标是系统地找出哪些记录是重复的,并且实际上是同一个实体。

这是示例数据的样子

谷歌产品

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

亚马逊产品

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

并且,具体来说,我们希望能够系统地将谷歌数据集中类似于 apple shake 4.1 数字合成软件 for mac os x effects 软件 的记录匹配到亚马逊数据集中的apple shake 4.1 视觉效果(mac) 。但首先,我们必须从源代码规范化开始。**

什么是源规范化,为什么它对 er 很重要?

在 ER 的上下文中,源规范化意味着

  1. 创建包含所有不同来源的统一数据集-这一点很重要,因为它允许您扩展到任意数量的输入来源,同时仍然保持一致的下游处理和匹配。
  2. 通过标准化数据类型(例如,确保空值实际上是空值而不是字符串空值)、统一格式(例如,所有内容都是小写)和删除特殊字符(例如,括号和圆括号)来清理数据,这消除了无关的差异,并可以显著提高匹配的准确性。

下面是为两个产品目录实现规范化的 PySpark 代码示例。注意,这是说明性的,而不是穷举的。

这种情况下的模式已经非常相似,因此创建统一的模式相对简单。请注意,您可能希望包含一个源和源 id 列来唯一标识记录,以防输入源之间存在 ID 冲突。

清理和标准化数据稍微复杂一点,具体的预处理方法在很大程度上取决于数据类型和所需的比较算法。在这个特殊的例子中,因为可用的元数据主要是文本和自然语言,所以比较可能需要依靠字符串相似性和 NLP 技术。因此,规范化像name, description 这样的字符串列并删除无关的字符是很重要的。

为了说明标准化过程,这里有一个清洗步骤前后产品名称的比较示例

**compaq comp. secure path v3.0c-netware wrkgrp 50 lic ( 231327-b22 )**

相对

**compaq comp secure path v3 0c netware wrkgrp 50 lic 231327 b22**

随着我们的数据集规范化,我们已经准备好解决特征化和阻塞

实体解析实用指南—第 3 部分

原文:https://towardsdatascience.com/practical-guide-to-entity-resolution-part-3-1b2c262f50a7?source=collection_archive---------12-----------------------

特征化和阻塞密钥生成

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

照片由 Honey Yanibel Minaya CruzUnsplash 上拍摄

这是关于实体解析的小型系列的第 3 部分。查看 第一部分 第二部分 如果你错过了

什么是特征化和阻塞,为什么它很重要?

在 ER 的上下文中,特征化意味着将现有的列转换为派生的特征,这些派生的特征可以通知不同的记录是否引用同一事物。分块意味着选择一个目标特征子集作为自连接键,以有效地创建潜在的匹配候选对。在我们的讨论中将这两个步骤分组的原因是块密钥通常是从特征中派生出来的。

良好的特征化能够实现高效的阻塞以及下游良好的匹配精度,因此它是 ER 过程的关键部分。这也是定义最少的一步,在这个过程中可以注入大量的创造力。

良好的分块可以极大地提高 ER 过程的效率,并且可以扩展到许多输入源和大型数据集。正如我们在 第一部分 中所讨论的,潜在候选对的论域是 N 与记录数。然而,并不是所有的候选对都值得评估。比如learning quickbooks 2007superstart fun with reading writing显然不是一回事,不应该包含在候选对中。解决这个问题的一种方法是使用更具体的阻塞键,例如产品的确切字符串名称,来创建候选对。这样,只有具有完全相同的标准化名称字符串的产品才会包含在候选对中。然而,这显然限制太多,会错过像learning quickbooks 2007learning qb 2007这样的潜在匹配。好的阻塞键选择对于有效地平衡好的效率和低的假阴性率之间的折衷是至关重要的。

如何实现特征化和模块化?

特征化,也许比 ER 中前面的步骤更重要,取决于源数据的类型和所需的下游比较算法。在这里,我们不会尝试提供一组详尽的可能技术,而是专注于 Amazon vs Google 产品的示例用例的说明性实现。在规范化的数据集中,我们有 4 列要处理,它们的特征是name, description, manufacturer, price。4 列中有 3 列是基于文本的,大部分识别信息都存储在其中。因此,我们将在这里集中大部分的特性化工作。有许多方法来特征化文本数据,但是在高层次上,它们通常归结为

  1. 标记化——例如将句子分解成单词
  2. 令牌标准化——例如词干词汇化
  3. 嵌入——例如 TF-IDF单词嵌入句子嵌入

对于我们的特定示例,我们将使用一个基本的 TF-IDF 模型,在该模型中,我们对文本进行标记,删除英语停用词,并应用 TF-IDF 矢量化。我们还将使用 Tensorflow 的 U 通用语句编码器模型,将名称和描述字符串转换成 512 维向量。

通过将这两个转换应用到name, description, manufacturer中的文本列,我们最终得到了许多丰富的特性,可以用来评估候选对之间的潜在匹配,以及帮助选择阻塞键。具体来说,TF-IDF 向量和句子编码向量在生成良好的块密钥方面非常有用。

正如我们上面讨论的,一个好的阻塞键是平衡特异性和假阴性率的东西。一个产品的全称是特定的,但也有非常高的假阴性率。我们可以通过在产品名称或描述中选择单个单词来解决这个问题。但是,重要的是要注意,就阻塞的目的而言,有些标记比其他标记更好。例如在learning quickbooks 2007中,quickbooks直观上是最好的阻挡键,其次是2007,再其次是learning。这是因为quickbooks是定义产品最有意义的关键词,2007是特定于产品版本的,而learning是一个非常通用的描述符。方便的是,这也正是 TF-IDF 试图系统测量的,并且learning quickbooks 2007的归一化 TF-IDF 令牌权重是quickbooks : 0.7,2007 : 0.51,learning : 0.5。如您所见,令牌的 TF-IDF 权重是一个不错的代理指标,可用于区分优先级和选择良好的阻塞密钥。

类似地,句子编码向量权重也告诉我们潜在向量空间中的哪个维度对句子的意义最显著,并且可以用于选择分块密钥。然而,在句子编码的情况下,具有最高权重的维度不直接映射到单词标记,因此可解释性较低。

实现上述内容的 PySpark 代码示例如下

上面的代码利用pyspark.ml库来

  1. 将 TF-IDF 变换应用于namedescriptionmanufacturer
  2. 根据 TF-IDF 令牌权重挑选出前 5 个令牌作为阻止密钥
  3. 使用通用语句编码器将namedescriptions转换为 512 维向量表示。我们在这里省略了manufacturer,因为它是稀疏的,并且作为一个英语句子也没有太多的语义意义。请注意,我们实际上并没有从编码中生成块密钥,但是类似于 TF-IDF 令牌的方法也可以很容易地应用到这里
  4. 将 top name 标记、top description 标记和 top manufacturer 组合成每个记录的一个块键数组。请注意,每条记录可以有一个以上的阻止键。这也是为了减少潜在匹配的假阴性率。

应用通用语句编码器的用户定义函数值得快速解包

# magic function to load model only once per executor
MODEL = None
def get_model_magic():
  global MODEL
  if MODEL is None:
      MODEL = hub.load("[https://tfhub.dev/google/universal-sentence-encoder/4](https://tfhub.dev/google/universal-sentence-encoder/4)")
  return MODEL[@udf](http://twitter.com/udf)(returnType=VectorUDT())
def encode_sentence(x):
  model = get_model_magic()
  emb = model([x]).numpy()[0]
  return Vectors.dense(emb)

这到底是在做什么,为什么有必要?Tensorflow hub 提供了一个预训练的模型,可以帮助用户将文本转换为矢量表示。这个模型不是分布式的,这意味着为了利用 Spark 这样的分布式计算框架,我们必须将它封装在一个用户定义的函数中,并使它在每个执行器节点上都可用。然而,我们不希望每次转换一段文本时都执行昂贵的load调用。我们只希望每个执行器加载一次,然后在分配给该节点的所有任务中重用。get_model_magic方法本质上是实现这一点的技巧。

现在我们已经有了我们的特征和阻塞键,我们准备好处理候选对生成和匹配评分

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值