深度学习能源前景的起伏
Vincent van Gogh, The Starry Night, 1889, MoMA The Museum of Modern Art
尽管在行业中被广泛采用,但我们对深度学习的理解仍然滞后。
[20]由[21]很好地总结,确定了四个研究分支:
- 非凸优化:我们处理一个非凸函数,但是 SGD 有效。为什么 SGD 甚至会收敛?
- 过度参数化和泛化:深度神经网络如何避免维数灾难?
理论家们一直认为,拥有成千上万个神经元的网络,以及它们之间数量级更多的单独加权连接,应该会遇到一个基本问题:过度参数化*【19】*
- 深度的作用:深度如何帮助神经网络收敛?深度和概括有什么联系?[21]
- 生成模型:为什么生成对抗网络(GANs)如此有效?我们可以用什么理论性质来稳定它们或避免模式崩溃?[21]
在这一系列文章中,我们将关注两个方面:
- 损失函数的拓扑分析
- 最小值的宽度或平坦度
1.损失函数拓扑
[1]是一个很好的起点:作者将深度神经网络的经验风险函数与 H-球形自旋玻璃模型联系起来。
自旋玻璃模型似乎是一个非常丰富的研究方向的伟大起点。我们应该走这条路吗?[4]普鲁登斯警告说:
这个基于损失函数拓扑的理论图有几个缺点。首先,机器学习的最终衡量标准是泛化精度,而不是最小化损失函数,损失函数仅捕捉模型与训练数据的拟合程度[……]其次,根据经验,较深的最小值比较浅的最小值具有较低的泛化精度
在继续我们关于损失函数拓扑的工作之前,让我们看看什么是极小值的平坦性。
2.最小值的平坦性
考虑[5]中讨论的图 X 中的卡通能源景观(经验损失函数)。
robust and non-robust minima [5]
[5]注意,在参数的贝叶斯先验下,比如分别在位置 x_robust 和 x _ non-robust 的固定方差的高斯分布,较宽的局部最小值比右边的尖锐谷具有更高的边缘化可能性。换句话说,[5]指出,位于更宽的局部最小值(如 x_robust)中的参数可能比全局最小值具有更高的损失,应该比那些简单地位于全局最小值的参数概括得更好[9]。
平坦度的定义是什么?[6]概述了宽度(平坦度)的定义。定义包括:
- 一个平坦的最小值作为权重空间中的一个大的连通区域,其中误差保持近似恒定【7】
- 着眼于临界点周围损失函数的局部曲率的定义。特别是编码在 Hessian 特征值中的信息(谱范数,迹线)〔5〕
- 局部熵[5]
我发现局部熵的概念在解释极小值的“平坦性”时非常有说服力和教育性。
从实践的角度来看,局部熵控制权重,这是显式正则化所尝试的:权重正则化(衰减)、丢弃和批量范数正则化。
平坦度=泛化?
在上一节中,通过查看局部熵,我们试图对定义一个好的解决方案的尝试有一个感觉。关于平面度的最佳定义仍然没有一致的意见。[6]指出
然而,当遵循平坦性的几个定义时,我们已经表明,平坦极小值应该比尖锐极小值概括得更好的结论在没有进一步的上下文的情况下不能照原样应用。以前使用的定义没有考虑到一些常用的深层架构的复杂几何结构。特别地,由对称性引起的模型的不可识别性允许人们改变最小值的平坦性而不影响它所代表的函数。此外,误差表面相对于参数的整个几何形状可以在不同的参数化下任意改变。本着[18]的精神,我们的工作表明,需要更加小心地定义平坦度,以避免所研究模型的几何形状退化。这种概念也不能脱离模型或输入空间的特定参数化
换句话说,平坦度的精确定义是一个活跃的研究课题,可以用来建立推广的充分必要条件[17]。
此外,虽然显式优化平坦度可能会有所帮助(正如我们在局部熵的情况下看到的),但从经验证据来看,DNN 和 SGD 可以完成这项工作,即使没有正则化的太多帮助。
What happens when I turn off regularizers? [16]
这鼓励了对深度学习经验损失函数的拓扑的研究。我们没有浪费时间去理解 Choromanska 等人的工作。H-球形自旋玻璃模型是非常有用的起点,并在深度学习研究人员的工作、统计物理学和随机矩阵理论之间建立了联系。
然而,正如作者自己在[11]中指出的,[1]依赖于相对粗糙的假设。然而,研究继续取得进展:[12]表明,在轻度过度参数化和类丢失噪声的情况下,具有一个隐藏层和分段线性激活的神经网络的训练误差在每个局部最小值处为零。[13]表明,在限制较少的假设下,每个局部最小值都是全局最小值,并且每个不是全局最小值的临界点都是鞍点。[12]和[13]中的结果得到了经验证据:例如,见[14],其中作者认为作为一阶特征,我们认为经验风险的景观只是一个(超)盆地的集合,每个盆地都有一个平坦的全局最小值
Over-parameterization? [15]
在下一篇文章中,我们将会看到[12],[13]以及麻省理工学院的 Tomaso Poggio 的工作([14],[15]);我们将尝试在损失函数拓扑研究、极小值平坦性和过度参数化的作用之间建立联系。
参考
[1] Choromanska,Anna 等人,“多层网络的损失表面”人工智能与统计。2015,链接
[2] Torben Krüger,讲义,研究生研讨会:随机矩阵、自旋眼镜和深度学习链接
[3]奥芬格、安东尼奥、热拉尔·本·阿鲁斯和 jiří·切尔内。"随机矩阵和自旋玻璃的复杂性."纯数学与应用数学通讯66.2(2013):165–201链接
[4]张,姚等,“机器学习中的能量-熵竞争与随机梯度下降的有效性”分子物理(2018):1–10链接
[5] Chaudhari,Pratik 等,“熵-sgd:偏向梯度下降进入宽谷” arXiv 预印本 arXiv:1611.01838 (2016)。链接
[6] Dinh,Laurent,et al .“ arXiv 预印本 arXiv:1703.04933(2017)链接
[7] Hochreiter、Sepp 和 Jürgen Schmidhuber。“平极小值。”神经计算9.1(1997):1–42。链接
[8] Martin,Charles“深度学习为什么有效:来自理论化学的观点”,MMDS 2016 链接
[9]] G. E. Hinton 和 D. Van Camp,《第六届计算学习理论年会论文集》(ACM,1993)第 5-13 页。
[10]内里·梅尔哈夫。"统计物理和信息理论."通信和信息理论的基础和趋势6.1–2(2010):1–212。链接
[11] Choromanska、Anna、Yann LeCun 和 Gérard Ben Arous。"公开问题:多层网络损耗面的景观."学习理论会议。2015 链接
[12] Soudry,丹尼尔和 Yair Carmon。“没有坏的局部极小值:多层神经网络的数据独立训练误差保证.” arXiv 预印本 arXiv:1605.08361(2016)链接
[13]川口健二。“没有可怜的局部极小值的深度学习。”神经信息处理系统的进展。2016.链接
[14]廖、、托马索·波焦。“理论二:深度学习中经验风险的前景.” arXiv 预印本 arXiv:1703.09833(2017)链接
[15]张,,等深度学习理论 sgd 的泛化性质。大脑、思维和机器中心(CBMM),2017 链接
[16]本·雷希特在 ICLR 2017 上的演讲,链接
[17] Sathiya Keerthi,深度神经网络中优化和泛化之间的相互作用,第三届真实世界机器学习年度研讨会,链接
[18] Swirszcz、Grzegorz、Wojciech Marian Czarnecki 和 Razvan Pascanu。“深度网络训练中的局部最小值.”(2016) 链接
[19] Chris Edwards,深度学习在噪音中寻找信号,ACM 通讯,2018 年 6 月,第 61 卷第 6 期,第 13-14 页链接
[20] Sanjeev Arora,走向深度学习的理论理解,ICML 2018 链接
[21] Arthur Pesah,更好理解深度学习的最新进展第一部分链接
城市声音分类第 1 部分:声波、数字音频信号
Photo by Sora Sagano on Unsplash
距离我上次发帖已经有一段时间了。到目前为止,我主要写的是 NLP,但我应该承认,我的关注点非常狭窄。到目前为止,我已经写了 19 篇帖子,其中 13 篇是关于 NLP 的,更具体地说是情感分析。尽管它包含了许多次要任务来达到情感分类器的目标,但最终目标仍然是情感分析。当然,我离专家还差得很远,还有很多东西要学,但是为了让我的数据科学学习更加多样化,我转向了另一种类型的数据。
除了我将附上的简短代码块,你可以在这篇文章的末尾找到整个 Jupyter 笔记本的链接。
音频数据
在我尝试任何事情之前,我想做的第一件事是更好地了解这个新朋友。什么是声音?为了对我将要处理的数据有一个基本的了解,我必须先了解基础知识。
这种声音是耳朵可以听到的空气中的压缩和稀薄的声音。声音是空气的运动。通常以波形表示,显示空气粒子随着时间的推移来回移动的情况。垂直轴表示空气如何相对于零位置向前或向后运动。横轴表示时间。
以上解释摘自 Youtube 视频。他很好地解释了声音、采样和奈奎斯特定理。但是等等,声音的波形看起来是上下移动,但是他说的是前后移动。我错过了什么?老实说,我在这里花了很长时间来理清头绪。可能是基础物理,但我在学校期间并没有太关注物理课。我从没想过这件事会回来困扰我。
从这里开始,这将是一个介绍性物理的回顾,所以如果你已经熟悉它,你可能会发现这篇文章的内容有点太基础了。
我们经常听到一个术语“声波”,是的,声音是一种波。那什么是“波”呢?波是振动,它将能量从一个地方转移到另一个地方,而没有物质被转移。根据波的不同特性,存在不同种类的波。这里我就说其中的两种:横波和纵波。
Image courtesy of www.difference.wiki
横波是一种介质粒子在垂直于能量传输方向的方向上移动的波。你可以想象一根拉伸的绳子,通过一端上下移动来发送波。纵波是一种波,其中介质的粒子在平行于能量传输方向的方向上移动。从上图可以想象,slinky 就是一个例子。在拉伸 slinky(一端固定)的情况下,如果您握住 slinky 的另一端并来回移动 slinky,这将传递一个看起来类似于上图左侧的波浪。
横波的一个例子是水,纵波的一个例子是声音。然后我就迷茫了。好的,我现在知道声音是纵波,但是为什么我看到所有的声音曲线看起来都像横波?
你可能看过上面的图。在上图中,A、C 是音高,440HZ、535.25HZ 是它们的频率。经过大量的谷歌搜索,我终于找到了。顺便说一句,如果这对你来说太初级了,我很抱歉。但对我来说,这是一个灵光乍现的时刻。
对该图的不正确理解是,当空气分子从声音发出的地方到声音被听到的地方穿越空间时,它们会上下运动。这就好像一个特定的分子从声音的源头开始,最后到达听者的耳朵里。这不是声波图中所描绘的。从声源传到听者耳朵的是能量,而不是空气分子本身。
当我们听到声音时,我们不会像风一样让空气分子撞击我们的耳朵。我们只是听到声音,那是因为空气是传输能量(声音)的介质,而介质本身并没有被传输。因此,我们从声波图中看到的波不是绘制空气的上下运动,而是绘制空气粒子的压缩和稀薄。声波图中看起来像波峰的实际上是空气分子靠得很近的压缩,看起来像波谷的实际上是稀疏,空气分子更分散。按照同样的逻辑,看起来像平衡(y 轴上的 0)的是声音产生之前的环境压力。
数据集:UrbanSound8K
有了对声音和声波图的基本理解,我们可以看一看我们的数据集。数据集名为 Urbansound8K。
https://serv . cusp . NYU . edu/projects/urban sound dataset/urban sound 8k . html
您可以找到有关如何绘制类和收集数据的更多信息,但为了让您对数据有一个简短的概述,“此数据集包含来自 10 个类的 8732 个带标签的声音摘录(< =4s):空调、汽车喇叭、儿童玩耍、狗叫、钻孔、发动机空转、枪击、手提钻、警笛和街头音乐
根据原始论文,声音节选自 www.freesound.org,并且已经预先整理成十叠以供交叉验证。
让我们先来看看元数据。
import pandas as pd
import numpy as npdata = pd.read_csv("UrbanSound8K/metadata/UrbanSound8K.csv")
data.shape
data.head()
元数据包含 8 列。
- 切片文件名:音频文件的名称
- fsID:从中提取摘录的录音的 FreesoundID
- 开始:切片的开始时间
- 结束:时段的结束时间
- 显著性:声音的显著性等级。1 =前景,2 =背景
- 文件夹:该文件被分配到的文件夹编号(1–10)
- classID:
0 =空调
1 =汽车喇叭
2 =儿童玩耍
3 =狗叫
4 =打钻
5 =发动机空转
6 =枪火
7 =手提钻
8 =汽笛
9 =街头音乐 - 类别:类别名称
音频数据已经被切片和摘录,甚至分配到 10 个不同的文件夹。一些摘录来自相同的原始文件,但不同的切片。如果来自某个记录的一个切片在训练数据中,而来自同一记录的不同切片在测试数据中,这可能会错误地增加最终模型的准确性。由于最初的研究,这也已经通过将切片分配到折叠中来处理,使得来自相同自由声音记录的所有切片进入相同的折叠中。
现在让我们看看每个折叠的类分布,看看数据集有多平衡。
appended = []
for i in range(1,11):
appended.append(data[data.fold == i]['class'].value_counts())
class_distribution = pd.DataFrame(appended)
class_distribution = class_distribution.reset_index()
class_distribution['index'] = ["fold"+str(x) for x in range(1,11)]
class_distribution
好的,看起来数据集不是完全平衡的。我们来看看总余额。
data['class'].value_counts(normalize=True)
与其他 8 个类别相比,有两个类别(汽车喇叭,枪支射击)的条目数量略少于一半。它看起来并不严重不平衡,所以目前,我已经决定不考虑这两个少数民族类的任何数据增加。
下面我定义了两个函数,首先获取 WAV 文件的完整路径名及其标签,然后用附加信息绘制波形,还可以用音频播放器播放声音文件。在我进入任何细节之前,让我们先绘制一个声音文件,看看它显示了什么。
fullpath, label = path_class('100263-2-0-117.wav')
wav_plotter(fullpath,label)
我已经简要地提到了声波的特征,但是我仍然没有看到数字音频信号的概念。没有对数字信号的理解,就很难理解所有这些信息的含义(采样率、比特深度等)。因此,请允许我绕道谈谈数字音频的基础知识。同样,如果这对你来说太初级,请随意跳过。
采样率、位深度
音频信号是连续的模拟信号,计算机不可能处理这种连续的模拟数据。它首先需要被转换成一系列的离散值,而“采样”就是这样做的。“采样率”和“位深度”是离散化音频信号时最重要的两个要素。在下图中,你可以看到它们与模数转换的关系。在图中,x 轴是时间,y 轴是振幅。“采样率”决定了采样的频率,“位深度”决定了采样的详细程度。
我们以 CD 为例。正常情况下,CD 的采样率为 44.1khz,深度为 16 位。首先,44.1khz 的采样率告诉我们每秒采样 44100 次。16 位告诉我们,任何样本都可以从与其幅度相对应的 65,536 个值中选取一个值。与 8 位相比,16 位的采样比 8 位的采样详细 256 倍。顺便说一下,如果你想知道为什么 CD 有 44.1khz 的采样率,我推荐我上面提到的同一个 Youtube 视频。它将让您对采样、混叠和奈奎斯特定理有一个直观的了解。
通道的数量告诉我们有多少个通道。当使用 2 个声道时,我们称之为立体声,当只使用一个声道时,我们称之为单声道。当然,单声道声音可以用多个扬声器播放,但它仍然是通过扬声器播放的信号的完全相同的副本。另一方面,立体声是用同一音频信号的两个不同输入通道录制的。我们通常看到的是左右立体声,这给了我们方向性、透视性和空间感。
现在我们有了一些重要的拼图来理解 WAVav 文件的元数据告诉我们什么。
采样率与 CD 质量相同,44.1khz,位深度也与 CD 质量相同。是立体声,从剧情上也能看出来。绿色表示一个通道,而蓝色表示另一个通道。这是一个 4 秒钟的剪辑。由于采样率为 44.1khz,持续时间为 4 秒,我们可以很容易地将 44100 乘以 4 计算出数据中的样本数,即 176400。
但坏消息是。再看一下 Urbansound8K 上的信息,有一条备注写着“WAV 格式的 8732 个城市声音的音频文件(见上面的描述)。采样率、位深度和声道数与上传到 Freesound 的原始文件相同(因此可能因文件而异)。”
啊哦。这意味着数据中可能有许多不同的采样率,这意味着即使持续时间相同,样本数量也会不同。这听起来不适合用来建立模型。此外,不同的位深度意味着它们可以取不同的取值范围。其中一些可能是立体声,而另一些是单声道。这听起来也不太好。
我花了大部分时间来复习声音信号的基本概念。在下一篇文章中,我将继续我的声音数据准备之旅,希望会涉及更多的编码。
感谢您的阅读。你可以从下面的链接中找到代码的 Jupyter 笔记本。
城市声音分类第 2 部分:采样率转换
Photo by Thomas Ribaud on Unsplash
这是我正在进行的城市声音分类项目的第二部分。你可以从下面的链接找到以前的帖子。
在上一篇文章的结尾,我刚刚意识到数据中的声音文件可能会有不同的采样率、位深度、不同文件的声道数。首先,让我从每个声音文件中提取这些信息,看看分布情况如何。
*除了简短的代码块之外,我还会在本文末尾附上整个 Jupyter 笔记本的链接。
声音数据格式调查
我在之前的帖子中没有解释清楚,但是在 WAVE 文件中,不仅有采样的声音数据,还有所有关于数据格式的信息。下图显示了 WAVE 文件中可用的信息类型。
Image courtesy of http://soundfile.sapp.org/doc/WaveFormat/
除了我在上一篇文章中定义的 path_class(从每个文件名构建完整的路径名)函数之外,我还将添加一个函数 wav_fmt_parser,以便从每个 WAVE 文件中提取我需要的三种信息,通道数、采样率、bit_depth。
现在,我们可以使用 wav_fmt_parser 函数向数据框添加额外的信息,以查看数据集中存在哪种不同的数据类型,以及它们是如何分布的。
wav_fmt_data = [wav_fmt_parser(i) for i in data.slice_file_name]
data[['n_channels','sampling_rate','bit_depth']] = pd.DataFrame(wav_fmt_data)
data.head()
data.sampling_rate.value_counts()
data.n_channels.value_counts()
data.bit_depth.value_counts()
从上面来看最令人担忧的是采样率。通道数可以通过仅从一个通道提取数据,或者取两个通道值的平均值来准备。比特深度是每个样本可以取的值的范围的问题,直觉上感觉可以通过考虑比特深度内它可以取的最大值和最小值来归一化这些值来准备。(警告:这只是我的直觉,我可能漏掉了一些陷阱。我越来越多地阅读和了解 DSP,我发现事情并不像我想象的那么简单)
采样率转换
我做采样率转换的原因是为了转换数据,使它们都具有相同的形状,并且易于用机器学习模型进行处理。但在现实生活中,采样率转换的用例要多得多。例如,典型的录音室录音音频为 192khz,要将此录音制作成 CD,应重新采样为 44.1khz 的 CD 采样率,不同的媒体可能有不同的采样率要求(DVD 的采样率为 48khz)。
我们看到大部分数据的采样速率为 44.1khz。假设我们想将数据重采样到 22.05khz,为什么呢?44.1khz 的音频质量更好,但对于声音分类来说,22.05khz 足以捕捉声音的差异。如果每个数据的大小变成其原始大小的一半,我们的模型将会更快。数据集中还存在其他采样速率,但首先让我们考虑最简单的情况,将音频从 44.1khz 重新采样至 22.05khz。
乍一看,这似乎并不复杂。22.05 正好是 44.1 的一半,由于采样率意味着从原始声音中获取样本的频率,感觉我们可以跳过每隔一个样本来获得原始采样率的一半。不要!我会告诉你当你这么做的时候会发生什么。
例如,让我们创建一个简单的正弦扫描。正弦扫描是一种信号,其频率随时间从起始频率变化到结束频率。如果我们创建一个起始频率为 20hz、结束频率为 22.05khz 的正弦扫描,持续 10 秒钟,我们可以听到音调随着时间的推移而增加的声音。
from scipy.signal import chirp
import soundfile as sffs = 44100
T = 10
t = np.linspace(0, T, T*fs, endpoint=False)w = chirp(t, f0=20, f1=22050, t1=T, method='linear')
sf.write('sine_sweep_44100.wav', w, fs)plt.figure(figsize=(15,3))
plt.specgram(w, Fs=44100)
plt.colorbar()
_=plt.axis((0,10,0,22050))
ipd.Audio('sine_sweep_44100.wav')
上面你看到的是正弦扫描的频谱图,x 轴是时间,y 轴是频率。通过播放实际的音频文件,你可以很容易地猜出声谱图显示的是什么。
它显示了随时间变化的频谱。由于我们的正弦扫描从 20hz 开始,您可以看到开始时红线从低电平开始,然后它的音调上升,直到达到 22.05khz。
如果我们简单地跳过每隔一个样本,将采样速率减半,会怎么样?
down_sampled = w[::2]
sf.write('sine_sweep_downsampled.wav', down_sampled, 22050)plt.figure(figsize=(15,3))
plt.specgram(down_sampled, Fs=22050)
plt.colorbar()
_=plt.axis((0,10,0,22050))
ipd.Audio('sine_sweep_downsampled.wav')
刚刚发生了什么??音调不再持续增加,而是先增加后减少。我唯一做的是跳过每隔一个样本,但我没有改变其他任何东西。
为了解释发生了什么,我们需要理解奈奎斯特采样定理。根据奈奎斯特定理,采样速率的一半,即奈奎斯特极限,是可以精确表示的最高频率成分。因此,在采样速率为 22.05khz 的信号中,它可以代表的最高频率为 11.025khz,但我们的原始正弦扫描频率(音高)增加到 22.05khz,因此所有那些无法用 22.05khz 采样速率(频谱范围为 11.025khz 至 22.05khz)表示的额外能量都进入了负频率,并产生了递减的正弦扫描。
在这种情况下,信号首先需要通过低通滤波器进行转换,然后每隔一个样本进行选择。取决于两个采样率的比率,这将使事情变得更加复杂。此外,在上采样的情况下,我们可能需要插值来获得原始采样信号中不包含的样本。
我之所以举上述例子,是为了向您展示在处理数字信号数据时的一些注意事项。但是这篇文章的目的不是为采样率转换创建一个新的包。那我们该怎么办?幸运的是,我们已经有了一个名为 Librosa 的很棒的库,它会为我们完成所有的转换,万岁!(Librosa 中实际的采样率转换部分由重采样默认完成,或者由 Scipy 的重采样完成)
利布罗萨
现在让我们从数据集中选择一个文件,用 Librosa 和 Scipy 的 Wave 模块加载同一个文件,看看它有什么不同。
data[data.slice_file_name == '100652-3-0-1.wav']
默认情况下, Librosa 的加载函数会将采样率转换为 22.05khz,同时将通道数减少到 1(单声道),并对数据进行归一化,使值的范围从-1 到 1。
import librosa
fullpath,_ = path_class('100652-3-0-1.wav')
librosa_load, librosa_sampling_rate = librosa.load(fullpath)
scipy_sampling_rate, scipy_load = wav.read(fullpath)
print('original sample rate:',scipy_sampling_rate)
print('converted sample rate:',librosa_sampling_rate)
print('\n')
print('original wav file min~max range:',np.min(scipy_load),'~',np.max(scipy_load))
print('converted wav file min~max range:',np.min(librosa_load),'~',np.max(librosa_load))
plt.figure(figsize=(12, 4))
plt.plot(scipy_load)
plt.figure(figsize=(12, 4))
plt.plot(librosa_load)
通过绘制从同一个源声音文件加载的两个数据,我们可以看到 Librosa 加载的数据已经减少到单声道(图上只有一条彩色线),而原始数据有两个声道(一个声道为绿色,另一个为蓝色)。
你猜怎么着。我对每种数据都有不同的采样速率、通道数量和不同的取值范围的所有担忧,都通过用 Librosa 加载声音数据完美地解决了!
我可以从一开始就使用 Librosa,甚至不用担心这些不同类型的 wave 文件格式,但通过研究 Librosa 在加载声音文件时实际上在做什么,现在我对不同的声音数据类型有了更好的理解,它们意味着什么。
我想我现在对我正在处理的数据有了很好的理解,接下来是有趣的部分,机器学习。在下一篇文章中,我将最终开始模型构建的第一阶段:特征提取。
感谢您的阅读。你可以从下面的链接中找到代码的 Jupyter 笔记本。
美国警察杀人:数据告诉我们什么
2015-2016 年警察杀人的探索性数据分析
Photo by Spenser Young on Unsplash
介绍
在这篇文章中,我们将分析美国最热门的政治话题之一,包括从制度种族主义到执法人员在社会中的角色等问题。但首先,我想请你帮个忙。在接下来的 10 分钟里,让我们把我们先入为主的关于什么是真的观念留在门口。先前的领域知识对于从数据中做出推论是至关重要的。但是,如果我们基于预先存在的信念建立我们的统计模型,我们就不太可能得到正确的答案,而更有可能提出错误的问题。那是我关于统计哲学的演讲。让我们开始吧。
背景和目标
由美国自由主义者和自由意志主义者推动、遭到坚定保守派强烈反对的越来越多的观点是,美国有一个有缺陷的执法系统,让太多无辜平民付出了生命代价。美国警察每年杀死大约 1000 人。如果我们将这一数字与芬兰等其他发达国家进行对比,2013 年芬兰警察只开了 6 枪,我们会看到一幅怪诞的画面。但是如果我们看看其他暴力犯罪和凶杀水平相似的国家,情况会变得更加模糊。在这个项目中,我们将把我们的范围限制在分析美国境内的警察杀人事件,并试图根据导致杀人的警察遭遇的数据得出有用的见解。事不宜迟,我们来挖掘一下数据。
使用的数据集
我们在这个项目中使用了 5 个数据集:
1)2016 年的警察杀人数据集
2)2015 年的相同框架数据集
3)2015 年 1 月至 6 月的数据集,其数据点少于 2)但事件的信息特征更多
4)2015 年美国各州人口和暴力犯罪事件数据集
5)包含 1000 多个美国城市统计数据的数据集
前两个是由英国报纸《卫报》的一个项目“统计的”编辑的。第三个由内特·西尔弗的五三八编辑。我从网站上收集了这三样东西,卡格尔。我自己定制了州人口的第四个数据集,减少了联邦调查局汇编的数据。第五组城市统计数据来自 www.simplemaps.com 的 T4。你可以在我的 GitHub 库上找到所有这些文件。
预处理:数据清理和特征工程
该项目将于 R 完成。数据可视化是 R 的主要优势之一,在这种分析中非常方便。我的编程脚本和情节在 GitHub 上公开。
**合并数据集:**我们使用的前两个数据集来自同一个来源,因此将它们合并在一起只需要一行代码。第三个数据集虽然相似,但来自不同的来源,因此我们需要解决其中的差异。尽管它拥有前两个版本的所有功能,但其中一些功能的命名略有不同。这一张还有其他特征,涉及发生杀戮的地区/区域的人口统计细节。我们不是试图将所有三个数据集合并在一起,而是将前两个数据集的较大合并数据集用于我们的大多数可视化,并在查看人口统计数据时专门使用第三个数据集。第四和第五组数据也将用于比较不同的州和城市在警察杀人方面的差异。
**删除和转换特征:**我们删除了 ID、姓名和街道地址等识别特征,因为它们对于每个案例几乎都是唯一的,不允许我们得出任何一般化的结论。我们还删除了日期功能:年、月和日。我检查以确保这些变量是均匀分布的,因此我们不会丢失任何有价值的信息。对于扩展特征数据集,我们还删除了任何用作发生凶杀的县/地区的名称/ID 的特征。这些值对于每个事件来说也是唯一的,并排除了一般趋势。我们确实留下了位置特征,例如城市、州、纬度和经度。当我们加载数据集时,这些要素中的许多以错误的格式导入到我们的数据框中。因此,我们必须手动检查数据集摘要,以确保数字特征确实保存为数字信息,分类特征保存为因子等,并在它们不正确时将其转换为正确的格式。
缺少值和数据子集:一小部分数据点缺少一些特征的值,比如经度和纬度。但是,当我们试图可视化某些特征时,与其将这些数据点从我们的数据框架中完全移除,不如相应地使用数据框架的子集来省略特定的数据点更有意义。
**特征提取:**接下来我们添加一些新的特征。我们将特征区域添加到我们的数据集中。根据谋杀发生的州,我们将数据点分配到美国的四个地区之一:西部、南部、中西部和东北部。我们还添加了另一个功能,年龄组,将死者分成不同的年龄组。
调整我们的特征后,我们的 5 个数据集具有以下特征:
A)具有扩展特征的 2015 年数据集- 467 起杀戮 1)年龄-死者年龄
2)性别-死者性别
3)种族-种族/死者种族
4)城市-事件发生的城市
5)州-事件发生的州
6)纬度-纬度,从地址地理编码
7)经度-经度, 从地址地理编码
8)执法机构-事件涉及的机构
9)原因-死亡原因
10)持有武器-死者如何/是否持有武器
11)地区-事件发生的美国地区
12)年龄组-死者所属的年龄组
13)份额 _ 白人-非西班牙裔白人人口的份额
14)份额 _ 黑人-黑人人口的份额, 不合并)15)份额 _ 西班牙裔-西班牙裔/拉丁裔(任何种族)人口的份额
16)p _ 收入-地区级个人收入中值
17)h _ 收入-地区级家庭收入中值
18)县收入-县级家庭收入中值
19)贫困率
20)尿酸-地区级失业率
21)大学-25+人口的份额与 BA
B)2015–16 数据集- 2226 杀戮-
数据集 A 的特征 1-12
***C)***2015 年各州数据集 -
1)各州 ID
2)人口
3)2015 年暴力犯罪事件
D)城市数据集 1)城市
2)州 ID
3)州名
4)人口
5)人口规模
6)人口密度
分析:地理可视化&地图
首先,我们将比较不同的州,然后看看警察杀人最多的城市。
y 轴代表 2015 年每个州的暴力犯罪数量,x 轴代表同一时期该州的警察杀人数量。这条直线穿过原点,它的梯度是美国的暴力事件总数除以杀人总数。在大多数情况下,这两个因素是成比例的,但也有异常值。俄克拉何马州、亚利桑那州和加利福尼亚州(在这两个统计数据中均领先一英里)的警察杀人率高得不成比例,这是由暴力事件造成的。另一方面,与暴力事件相比,纽约的杀人率低得不成比例。鉴于暴力事件与一个州的人口成比例,如果我们要为每个州的人口、暴力事件和杀戮创建一个 3D 散点图,我们会看到类似于穿过 3D 平面的直线的东西(它在我的 R 脚本中,但为了简单起见,我没有包括它)。
我们为 2015 年发生 10 起或更多警察杀人事件的城市绘制了类似的图。这次我们用城市的人口(适当)代替了暴力事件,我们仍然观察到类似的相关性,这并不奇怪,因为暴力犯罪事件通常也与城市人口成比例。纽约市比纽约州更是一个异数,就其人口而言,谋杀率低得不成比例。接下来,我们将在地块上放置一些地图,以便更好地显示位置。
地图方法- 对于所有的地图可视化,我们将使用 2015 年至 2016 年的大型数据集,并忽略阿拉斯加州和夏威夷州的杀戮,因此我们可以在地理上放大以查看更精细的细节。尽管遗漏了这两个州,我们仍然报道了美国 99%的谋杀案,所以我们没有遗漏太多信息。对于我们的地图,我们将利用 r 中的" ggplot2 “库。虽然这些绘图也可以使用” ggmap “库来完成,但我使用了” ggplot2 “和” sf "库的组合。如果你是一个有抱负的数据科学家,我强烈建议你学习如何充分利用这些 R 库。
对于第一张地图,我们正在查看 2015 年至 2016 年期间的所有警察杀人事件,圆点阴影表示死者的年龄。如果你注意到肯塔基、田纳西、弗吉尼亚和北卡罗来纳地区的点,似乎那些在那里被杀的人比其他地方被杀的人年龄稍大。第二个观点,如果你熟悉美国地图的话,应该很明显,那就是杀戮集中在城市,越大的城市越集中。这没什么好惊讶的。如果你看到下面的美国人口热图,你会注意到这两张图看起来有些相似。
Heat map representing US population density
现在让我们来看一个更小的数据子集,它只包含手无寸铁时被杀的人。这将是 389 人,或大约 17.4%的人在这两年中被杀害。
如果这些数据代表了现在仍在发生的事情,那么杀害手无寸铁的人似乎也是美国的一个普遍问题。枪击似乎也是这里死亡的主要原因(2015 年至 2016 年,枪击造成了超过 90%的死亡),羁押中死亡是第二大死亡原因。现在,让我们来研究一下种族/民族因素是如何影响这一情况的。
**
第一张地图涵盖了数据集中所有 8 个种族/族裔类别的杀人案件。但是因为群太多,有点难跟。因此,我们将我们的数据集子集化,只包括那些被杀害的“黑人”、“白人”、“西班牙裔/拉丁裔”或“土著美国人”。通过这样做,我们仍然保留了 95%以上的数据点,并获得了更清晰的视觉效果。似乎被杀害的白人遍布全国大部分地区。在巴尔摩、DC 和芝加哥犯罪猖獗的地区,黑人似乎占了死者的绝大部分。可以理解的是,西班牙裔/拉美裔在西班牙裔/拉美裔人口密集的州,如加利福尼亚、新墨西哥和得克萨斯州,占了更多的死者,也占了墨西哥边境城镇的大多数死者。南加州似乎是上述三个种族/民族的密集结合。印第安人的死亡似乎集中在亚利桑那州和新墨西哥州的印第安人保留地附近。
分析:条形图和直方图
停留在种族/民族的话题上,让我们快速地看一下不同的民族和种族是如何随着年龄而不同的。
遇害的阿拉伯裔美国人的平均年龄最低,而那些被归类为“未知”的人的平均年龄最高。但是这些群体没有大量的数据点。因此,让我们把注意力集中在构成大部分(几乎 95%)数据集的 3 个群体上:黑人、白人和西班牙裔/拉丁裔。我们可以看到这里也有明显的差异,所以让我们用一些直方图更深入地了解一下。
被杀害的西班牙裔/拉美裔人的年龄往往低于被杀害的白人,黑人的平均年龄最低。白人、西班牙裔/拉美裔和黑人的平均年龄分别为 38 岁、31 岁和 30 岁。然而,值得注意的是,这些群体的平均年龄分别为 42.9 岁、28.1 岁和 33.3 岁。这至少解释了为什么被杀害的白人群体的平均年龄最高。白人图表的尾端也延伸到更老的年龄,但可以理解的是,他们有更多的离群值,因为他们占了数据集的一半以上。同样值得注意的是,美国西班牙裔/拉美裔的中值年龄下降是因为他们社区的很大一部分是第一代移民,他们往往比美国的平均年龄更年轻。他们也倾向于比其他两个群体拥有更多的孩子。
继续谈论年龄这个话题,让我们来看看美国不同地区的情况是如何不同的,并通过更多的因素来缩小范围。
很难通过该图得出关于年龄和地区的结论,因为柱状图并不意味着显示实例的数量,而是侧重于按百分位数的细分。但是看起来(如果你检查一下数据就会发现)在中西部和西部死亡的人的年龄比在东北部和南部死亡的人要低。在所有地区,被杀害的持刀者的年龄都高于其对应部分(假设我们排除一小部分携带车辆的人,“其他人”,或案件“有争议”的人)。
枪击似乎是 90%以上案件的死因,确切地说是 2021/2226 起案件。除中西部地区外,所有地区在羁押中被杀者的年龄中位数(这是第二大死亡原因,共 82 起)都略高于被枪杀者。有趣的是,根据箱线图的上四分位数,死者被车辆撞击的案例涉及老年人。虽然他们只收集了一小部分数据,但这些病例数量巨大(总共 49 例,4 个地区各至少 9 例)。
让我们从我们在 538 数据集上找到的额外信息开始,按收入进行细分。请注意,这只是 2015 年 1 月至 6 月间死亡的不到 500 人的信息。首先,让我们看看收入。
这里需要注意的重要一点是,这些收入不是被杀害的个人的,而是居住在发生杀戮的地方的人们的收入。用消息来源的话说,“人口普查区域是通过使用 Bing 地图和 Google Maps APIs 将地址地理编码为纬度/经度,然后将点叠加到 2014 年人口普查区域上来确定的”。然而,我们确实看到了一些模式,表明相当数量的死者是在代表死者种族背景的县/市/地区被杀害的。在所有收入类别中,杀害土著美国人发生在收入最低的地区,而亚裔美国人则处于另一端。根据维基百科,2018 年每个种族/族裔的家庭收入中位数如下:亚裔-80,720,白人- 61,349,夏威夷土著和其他太平洋岛民-57,112,西班牙裔或拉丁裔(任何种族)-46,882,美洲印第安人和阿拉斯加土著- 39,719,黑人或非裔美国人- 38,555 。有趣的是,美洲原住民的收入似乎比黑人高。但是根据杀人事件的数据,美国原住民在低收入地区被杀的人数比黑人多。在许多其他事情中,这可能表明,要么许多黑人在没有黑人家庭占主导地位的社区被杀害,要么当土著美国家庭被归类为与土著阿拉斯加人相同的群体时,他们的国民收入得到了提高。为了更好地理解它,我们将偏离这个项目范围之外的数据,所以我将把这个任务留给那些好奇的人。值得注意的是,我们看到的分类中值收入都明显低于任何种族/民族的全国中值收入。对于我们的数据集,杀戮发生在中等家庭收入为 42,759 美元的地区。美国 2018 年家庭收入中值为 57112 美元。2015 年至 2016 年,不到 24%的警察杀人事件发生在家庭收入高于全国中位数的人口普查区。如果我们 2015-16 年的数据代表了美国警察杀人的总体情况,那么杀人事件更有可能发生在贫困地区。让我们来看看这些地区的贫困率。
类似的收入模式在小块土地上的贫困率中也可以看到,美洲原住民在最贫困的地方被杀害。众所周知,印第安人保留地的贫困率为 28.4 %,而所有印第安人的贫困率为 22%。这两个数字都远高于 12.7%的全国贫困率。现在让我们转到发生杀戮的地方的种族/民族人口统计。
超过 75%的白人死者是在非西班牙裔白人占 50%以上的社区被杀害的。据报道,黑人和西班牙裔/拉丁裔在他们各自的种族/民族背景的人比你在美国普通社区中发现的人占人口的比例相对较大的社区中也被杀害。
这个更有趣一点。看起来像是,出于某种原因,据报道,美洲原住民是在受教育程度较高的人群中被杀害的,而不是他们的同类。更有趣的是,如果我们看看黑人和西班牙裔被杀地区的大学教育水平,他们分别排在第二和第三位。我个人想不出好的假设来解释这种现象。如果你有答案,请随时告诉我。
现在,让我们离开该地区的人口统计数据,回到我们最初的 2015 年至 2016 年的一些堆积条形图数据集。在接下来的两个情节中,我们将探索一个我们还没有看到的特征,年龄组。
**
在讨论这两个图之前,我们应该注意到 38 名死者据报道年龄在 18 岁以下,而其他 2 个年龄组每个都有超过 1000 个数据点。由于 18 岁以下年龄组的数据样本量要小得多,因此从这个年龄组得出的推论比从其他两个年龄组得出的推论更不可能代表整个人口中发生的情况。话虽如此,让我们来看看图表。直觉上,年龄最大的一组白人比例最高是有道理的。在美国的老年人群中,白人的比例往往比 T2 人高。第二个挺有意思的。在这三个年龄组中,被杀害的未成年人携带武器或刀具的比例最低。18 岁以下年龄组的被杀者手无寸铁的比例也最高(26.3%)。请注意,这里没有足够的信息来得出这些统计数据反映了总体情况的结论。但是如果进一步分析发现它们具有代表性,就有理由担心了。
在上面的剧情中,我们看到了被不同地域杀死的人的“武装”状态。值得注意的是,每个地区被杀者中手无寸铁的比例高得惊人,不同地区之间的比例从 16.9%到 18.5%不等。
枪击似乎造成了每个种族的绝大多数死亡。第二大死因似乎更有趣一些。白人在羁押中的死亡率最低(不包括被杀害的 7 名阿拉伯裔美国人),而印第安人的死亡率最高。下一个情节也很有趣。
**如果我们假设我们的数据代表了当今警察杀人的总体趋势,那么被杀的黑人比其他任何种族/民族更有可能携带枪支(本案中有 49.1%)。这也意味着他们比其他种族/民族群体更不容易在被杀时持刀。更有趣的是,如果我们排除 7 名阿拉伯裔美国人,这将意味着黑人比任何其他种族/族裔群体更有可能在被杀时手无寸铁(2015-16 年被杀的黑人中有 20.9%没有武器)。这些见解,如果是真的,可以联系到备受争议的讨论,将黑人与拥有枪支联系起来的刻板印象是否会导致更多手无寸铁的黑人被杀。这使得一个完美的赛格威进入我们项目的下一部分。
讨论-理解种族偏见
为了给上面的图表提供数字,下面是 2015 年至 2016 年杀人总数的种族/民族汇总:
2015-16 警察杀害死者种族/民族:
- 阿拉伯裔美国人-7
-亚裔/太平洋岛民-45
-黑人-568
-西班牙裔/拉丁裔-378
-美洲原住民-34
-其他-1
-不详-43
-白人- 1150
你可能会注意到,黑人在死者中占了不成比例的大部分(超过 25%),而在美国总人口中仅占 12%。然而,试图纯粹基于这些统计数据找到有意义的结论将意味着我们忽略了它们背后的混杂因素。根据这份 FBI 报告,黑人男性的杀人率比白人男性高 8 倍。一个统计学新手可能会过早地得出结论,认为高犯罪率是黑人高死亡率的原因。但是,再一次,基于这样的零星数据得出关于种族/民族的结论不仅是不正确的,而且是危险的无知。我们将打破观察研究的黄金法则:相关性不等于因果关系。贫困率、教育背景和社会经济地位等更深层次的混杂因素可以更好地预测群体中的暴力犯罪事件。
如果你不确定什么是混杂因素,就去读读 这个 。这是一个既影响研究中的自变量又影响因变量的变量,如果不对其进行平衡,会导致研究人员得出错误的结论。例:吸烟者很可能喝咖啡,也很可能患胰腺癌。但是,如果一项调查喝咖啡影响的研究没有消除吸烟的影响,我们可能会错误地得出结论,喝咖啡会导致胰腺癌
如果我们有更多关于死亡个体的人口统计信息,我们将能够平衡几个混杂因素,并得出更好的结论。但是我们没有。这让我们面临一个最大的障碍:缺乏数据。没有一个全面跟踪所有警方互动的系统的问题是,我们只能获得导致杀戮的互动数据,即使这样,我们也只能获得不完整的数据。如果我们有关于警察与不同种族/民族的人有多少次互动的数据,以及其中有多少百分比导致了暴力/杀戮,我们就能更好地发现警察的偏见。目前,此类实例的数据只有在拥有数据的部门选择发布时才可用。那些选择这样做的部门可能根本不能代表美国警察部门的平均水平。正如你最近可能听说的,联邦调查局计划从 2019 年开始收集所有涉及警察使用严重暴力的案件的数据。在某种程度上,这种变化将允许更好的分析。但是,从警察局获得所有这些数据可能仍然不能给我们想要的直接答案。这是因为我们无法通过实验室环境下的随机试验找到确切的答案。在观察性研究中,我们必须确保消除所有的混杂因素,比如我前面提到的那些。这并不容易做到,因为可能有我们甚至没有想到的混淆因素。用研究警察偏见的心理学家和神经学家基思·佩恩的话说,“很难从经验上区分贫困、地理、种族、种族偏见和警察策略的影响”。
结论
*虽然最后一段提到的复杂性可能会让我们这些试图找到这个令人不安的问题的结论的人感到有点沮丧,但我们有理由充满希望。即使有当前的限制,我们也能够对这个问题形成重要的见解(就像我们在这个项目中提出的那样)。我将以最后一个想法来结束这篇文章。我相信只有两件事让我们无法找到正确的答案。首先是足够的数据,我们正在缓慢但稳步地实现这一目标。第二是有更多好奇的人愿意看这些数据并提出正确的问题。这个小组可能由像**你、*是的,你这样的人组成,如果你已经在文章中提到了。
感谢你到目前为止的阅读。我希望这篇文章教会你一些新的东西,无论是关于 R 的探索性数据分析还是关于美国警察暴力的问题。如果你认为这对你认识的其他人来说是有趣或有教育意义的,请与他们分享。如果你喜欢这篇文章,并有什么想和我分享的,请随时发表评论,通过电子邮件联系我,地址是 nadir.nibras@gmail.com 或 https://www.linkedin.com/in/nadirnibras/T5。我致力于改进我的方法、分析或数据集,所以如果你有任何建议,请随时评论或告诉我。如果你想关注我在数据科学方面的更多工作,请在 Medium 和 Linkedin 上关注我。
此外,如果你是数据科学或其在理解世界中的应用的粉丝,请联系我。和其他统计爱好者聊天总是很有趣,我很乐意在有趣的项目上合作:)
都柏林自行车站的使用模式
Locations of all Dublin Bike stations colour coded by their weekday usage patterns. Click here for the full interactive map.
自从我 5 年前来到这里,我已经是都柏林自行车的长期用户了,像许多其他用户一样,我有一个关于一天中不同时间哪个车站繁忙或安静的心理模型。我最近的车站是波多贝罗,我发现在上午 10 点左右很难找到自行车,但是步行到镇上,我找到自行车的机会就会大大增加。我想更详细地了解这一点,并找出是否有一些不同的行为类型,所有的车站都可以分类,以及这在城市中可能如何变化。自行车主要用于上下班,因此出现某种空间模式似乎是很自然的。正如你在上面的地图上看到的,我们可以把这些站分成三种不同的行为类型,我们得到了一些非常有趣的结果!
在这篇文章中,我将更多地解释我做了什么,这些模式是什么,以及一些技术背景。因为我这篇文章的目标读者是普通读者以及更多的技术人员,所以我将首先讨论这些发现,把技术方法留到后面。你也可以点击这里获得上面显示的完整交互地图和点击这里获得 github repo ,在这里我已经公开了我的代码和一些示例数据。
有哪些模式,它们是如何被发现的?
从 2017 年 1 月到 2017 年 8 月,我每隔 2 分钟从公共 API 收集数据,以建立一个规模相当大的历史数据集,从中我们可以计算出 108 个站点中每个站点的典型工作日使用情况。这将平均化雨天、冷天、特殊事件等的影响。由此,我们可以找到不同的行为模式,我们可以将每个站配置文件分类。为了做到这一点,我使用了一种叫做 k-means 聚类的方法,这种方法的工作原理是预先假设我们的数据可以分成“k”个不同的类别。然后,该算法试图找到描述数据分段的“k”个最佳平均模式。在我们的例子中,我选择了 k=3,因为它给出了美学上令人愉悦的结果,尽管像轮廓评分这样的方法更严格。我希望将我 2017 年 10 月在都柏林 PyData 发表的一篇演讲放到网上,这篇演讲用更多的技术细节解释了这一点。然后根据与三个简档最接近的匹配对每个电台进行分类。我们可以自由选择更高的值,但是由于可能类别的数量不断增加,结果变得更加复杂,但是我们希望行为特征更符合实际数据。
我用颜色标记了用这种方法发现的每一种不同的行为,并绘制在下图中。回想一下,这些是使用每个站的平均工作日使用量找到的,所以一天中的时间是沿着 x 轴的。我还使用了每个站点的百分比容量,而不是原始的自行车数量,来处理一些站点的容量高于其他站点的事实。
Average weekday usage for the three types of stations
显而易见,最接近绿线的车站通常用于早上进城到蓝色车站的通勤,因此我们自然会认为绿色车站位于住宅区,蓝色车站位于市中心。晚上,当人们下班回家时,情况正好相反。红色加油站一天有稳定的供应,不符合其他两种行为。
当我们在地图上绘制车站并按类别用颜色编码时,一幅非常有趣的画面出现了,如上面的图片所示(或者点击此处打开互动地图的标签)。通过仅根据站点的使用模式来表征站点,我们可以看到这也导致了高度的空间聚类。虽然这是你期望看到的,但我对集群的清晰程度感到惊讶——蓝色站集中在都柏林 2 区周围,那里有许多商业办公室,与中间的红色站接壤,绿色站在市中心以外的更多住宅区。
方法学
为了收集数据,我写了一个简短的 Python 脚本,在我的 Raspberry Pi 上运行,每 2 分钟查询一次 Dublin Bikes API,并附加到一个每日 CSV 文件中,然后每晚将这个 CSV 文件转储到 S3 桶中。我从 2017 年 1 月开始运行这个,直到 8 月下旬,我终于再次想起了这个项目的想法。
如前所述,我然后计算了 108 个站点中每个站点的平均工作日概况,然后使用 k-means 聚类来确定三个原型行为类别,我将根据这些类别对每个站点进行分类。我使用欧几里德距离来确定不同时间序列的相似性,这有点简单,一般不推荐用于时间序列数据。我认为这个问题很简单,只有 3 种行为类型,尽管有这个假设,我对我的结果很满意。如果需要更鲁棒的方法,可以使用更高级的方法,如动态时间弯曲。
这个映射是使用 Python 库 leaf 完成的,它充当 JavaScript 库传单的包装器。它使用起来相当容易,而且似乎在其他 Python 映射库中脱颖而出,因为它可以输出到 HTML 中,然后可以嵌入到网站中或独立托管。
就未来的工作而言,可以利用这些数据做更多的事情,比如工作日之间的差异和天气的影响。在查询 bikes API 以构建用于本文的数据集时,我同时收集了都柏林的天气数据,因此观察它对使用模式的影响并为每个站点构建一些预测模型会很有趣。像 ARIMAX 这样的模型应该可以很好地解决这样的问题。
无论如何,这就是现在,希望这是有趣的都柏林自行车用户和技术人员一样。点击这里查看 github 回购项目或在 Twitter 上点击我。
为你的企业使用人群计数人工智能模型
用数据做酷事!
背景
深度学习正在迅速将计算机视觉带入一个领域,企业可以开始在日常使用中集成强大的模型。过去,企业在采用人工智能方面面临的一些挑战——谁将建立和维护这些模型,我如何部署它们,它们是否足够准确——现在在 Unleashlive 的一个新平台中得到了解决,该平台旨在将模型开发者与最终用户联系起来。
我正在这个人工智能平台上推出一个人群计数模型。这个平台将允许企业通过我的模型运行他们的剪辑或图像或直播视频,并立即获得结果,而没有任何与设置环境或 GPU 相关的麻烦。你现在可以在释放云免费试用这个模型 1 小时。首次用户请建立一个新帐户。
人检测/计数模型是非常通用的,在许多领域都有应用。这里是我能想到的一些,以及我的应用程序使用 you tube 的一些视频的性能的一个小演示。
人计数器的有趣应用
- 零售
在零售业中,了解客流量对于组织过道中的商品、优化商店布局、了解高峰时段甚至潜在的防盗非常重要。你现在可以在商店里放一个摄像头,并将其连接到 Unleashlive AI 平台,获得可以被摄取和分析的实时数据。请参见下面的实际模型
People Counter — Retail
2.基础设施规划
许多企业或政府机构可以使用人员计数器来了解各种情况,如在给定时间公共场所有多拥挤,或者每天有多少人使用特定的街道交叉口等。
Traffic Count
3.安全
另一个广泛的应用领域是安全。如果你正在寻找一个迷路的人,或者如果一个企业想在启动一台大型机器之前确保一个区域没有人。在下面的图片中,我的模型可以追踪一个在内陆徒步旅行的人。
Safety application of people counter
关于人工智能模型的更多信息
这里使用的人群计数模型是一个更快的 RCNN 初始模型,在不同规模的自定义人群数据集上进行训练。与使用在 COCO 数据集上训练的模型相比,它的工作速度更快,精度更高。它适用于近距离和远距离拍摄的人群图像,以及不同背景和闪电条件下的图像。
我想在我的业务中使用这种模式
如果你对这篇文章感兴趣,并想尝试人数统计模型,那么请登录并在https://cloud.unleashlive.com/创建一个账户
您将能够激活该模型并对其进行测试!最棒的是,“释放”向所有新用户提供 1 小时免费试用:)
我是一名开发人员,我想添加一个模型
这也很简单。只需在“释放生活”上创建一个帐户,并在顶部的个人资料中启用开发者标志(“以开发者身份开始”)。这为您的测试建立了一个私有的沙箱。有 tensorflow 1.6 和对象检测经验者优先。
一旦您启用了您的帐户,“开发者”将出现在顶部的导航栏上。只需点击并选择“沙盒”,然后按照提供的指示。这是一个非常简单的过程。
了解更多
要了解更多关于 Unleashlive 平台和商业模式如何运作的信息,请查看以下常见问题:
http://developer.unleashlive.com/#a-i-apps-ecosystem
如果您有任何问题或需要帮助,请随时拨打getstarted@unleashlive.com联系我们。如果你对其他人工智能应用有想法,请在下面的评论中添加。
参考文献:
用 AWS Glue 和 Databricks Spark-XML 处理 XML
快速介绍 Glue 和一些 XML 处理技巧,这从来都不容易
如果您对数据的质量和结构有严格的规定,使用非结构化数据有时会很麻烦,可能会包括对数据进行控制的庞大的任务。
在本文中,我将分享我使用 Glue transformations 和 Databricks Spark-xml 库处理 XML 文件的经验。
AWS Glue 是 AWS 提供的 ETL 服务。它有三个主要组件,即数据目录、爬虫和 ETL 作业。因为爬虫帮助你提取你的数据的信息(模式和统计),数据目录被用于集中的元数据管理。使用 ETL 作业,您可以使用 Glue proposed 脚本或带有附加库和 jar 的自定义脚本来处理存储在 AWS 数据存储上的数据。
XML…首先,您可以使用 Glue crawler 来探索数据模式。由于 xml 数据大多是多级嵌套的,所以爬行的元数据表将具有复杂的数据类型,如结构、结构数组……并且您将无法使用 Athena 查询 xml,因为它不受支持。所以有必要将 xml 转换成平面格式。要展平 xml,您可以选择一种简单的方法来使用 Glue 的魔法(!),一个简单的技巧将其转换为 csv 格式,或者您可以使用 Glue transformations 来展平数据,稍后我将对此进行详细说明。
您需要小心展平,这可能会导致空值,即使数据在原始结构中是可用的。
我将给出一个替代方法的例子,根据您的用例选择哪一个取决于您。
- 爬网 XML
- 使用粘合作业转换为 CSV
- 使用 Glue PySpark 转换来展平数据
- 另一种方法是:使用 Databricks Spark-xml
数据集:【http://opensource.adobe.com/Spry/data/donuts.xml
代码片段:https://github.com/elifinspace/GlueETL/tree/article-2
0.将数据集上传到 S3:
从给定的链接下载文件,并转到 AWS 控制台上的 S3 服务。
Create a bucket with “aws-glue-” prefix(I am leaving settings default for now)
单击 bucket 名称,然后单击 Upload:(这是最简单的方法,您也可以设置 AWS CLI 以从本地机器与 AWS 服务交互,这需要更多的工作,包括安装 AWS CLI/配置等。)
点击添加文件,选择你想上传的文件,然后点击上传。
You can setup security/lifecycle configurations, if you click Next.
- 爬网 XML 元数据
首先,如果您知道 xml 数据中的标记可以选择作为模式探索的基础级别,那么您可以在 Glue 中创建一个定制的分类器。如果没有自定义分类器,Glue 将从顶层推断模式。
在上面的 xml 数据集示例中,我将选择“items”作为我的分类器,并像下面这样轻松地创建分类器:
转到 Glue UI,单击数据目录部分下的分类器选项卡。
“item” will be the root level for the schema exploration
我用分类器创建了爬虫:
Give the crawler a name and Select the classifier from the list
Leave everything as default for now , browse for the sample data location (‘Include path’)
添加另一个数据存储:否
您可以在 S3 存储桶上使用具有相关读/写权限的 IAM 角色,也可以创建一个新角色:
频率:按需运行
Choose the default db(or you can create a new one) and leave settings as default
查看并单击完成。
现在我们已经准备好运行爬虫了:选择爬虫并点击 Run Crawler,一旦状态为“ready ”,访问数据库部分并查看数据库中的表。
(Tables added :1 means that our metadata table is created )
转到表并过滤您的数据库:
单击表名,输出模式如下:
现在我们有了模式的概念,但是我们有复杂的数据类型,需要将数据扁平化。
2.转换为 CSV:
这很简单,我们将使用 Glue 提供的脚本:
转到 ETL 菜单中的作业部分并添加作业:
Name the job and choose the IAM role we created earlier simply(make sure that this role has permissions to read/write from/to source and target locations)
Tick the option above,Choose the target data store as S3 ,format CSV and set target path
现在是神奇的一步:(如果我们选择 parquet 作为格式,我们将自己进行展平,因为 Parquet 可以有复杂的类型,但对于 csv 来说,映射很容易显示。)
You can rename, change the data types, remove and add columns in target. I want to point that the array fields mapped to string which is not desirable from my point of view.
我把一切都保留为默认,审查,保存并继续编辑脚本。
粘附建议的脚本:
We can Run the job immediately or edit the script in any way.Since it is a python code fundamentally, you have the option to convert the dynamic frame into spark dataframe, apply udfs etc. and convert back to dynamic frame and save the output.(You can stick to Glue transforms, if you wish .They might be quite useful sometimes since the Glue Context provides extended Spark transformations.)
我在建议的脚本中添加了一些行来生成单个 csv 输出,否则输出将是基于分区的多个小 CSV 文件。
保存并单击“Run Job ”,这将带来一个配置检查,因此您可以将 DPU 设置为 2(最小的值)并按如下方式设置超时:
让我们运行并查看输出。您可以监视 Glue UI 中的状态,如下所示:
运行状态成功后,转到您的目标 S3 位置:
单击文件名并转到如下所示的“选择自”选项卡:
如果向下滚动,可以通过单击显示文件预览/运行 SQL(Athena 在后台)轻松预览和查询小文件:
The struct fields propagated but the array fields remained, to explode array type columns, we will use pyspark.sql explode in coming stages.
3.粘合 PySpark 转换用于取消嵌套
Glue 提供了两种 pyspark 变换:
- Relationalize:取消嵌套列、透视数组列、为关系操作(连接等)生成连接键。),生成帧列表
- UnnestFrame:取消框架嵌套,为数组类型的列生成 joinkey,生成一个包含所有字段(包括 join key 列)的框架。
我们将使用 Glue DevEndpoint 来可视化这些转换:
Glue DevEndpoint 是数据存储的连接点,用于调试脚本,使用 Glue Context 和 Sagemaker 或 Zeppelin 笔记本对数据进行探索性分析。
此外,您还可以从 Cloud9 访问这个端点,cloud 9 是基于云的 IDE 环境,用于编写、运行和调试您的代码。您只需要在 Cloud9 实例上生成 ssh 密钥,并在创建端点时添加公共 SSH 密钥。要连接到端点,您将使用端点详细信息中的“SSH 到 Python REPL”命令(在 Glue UI 中单击端点名称),用您在 Cloud9 实例上的位置替换私钥参数。
- 创建一个 Glue DevEndpoint 和一个 Sagemaker 笔记本:
我将把这个端点也用于 Databricks spark-xml 示例,所以从https://mvnrepository . com/artifact/com . data bricks/spark-XML _ 2.11/0 . 4 . 1下载 jar 文件到您的 PC,上传 jar 到 S3 并相应地设置“依赖 jars 路径”:
Name it and choose the IAM role we used before.If you have a codebase you want to use, you can add its path to Python library path.
您可以将所有其他配置保留为默认配置,然后单击 Finish。大约需要。端点准备就绪需要 6 分钟。
一旦端点准备就绪,我们就可以创建一个笔记本来连接它。
选择您的端点,然后从操作下拉列表中单击创建 Sagemaker 笔记本。笔记本创建完成后,需要几分钟时间准备就绪。
Name it, leave default settings and name the new IAM role , click Create Notebook
打开笔记本并创建一个新的 Pyspark 笔记本:
您可以从我们之前创建的 csv 作业中复制并粘贴样板文件,如下所示更改 glueContext 行,并注释掉与作业相关的库和代码片段:
You can either create dynamic frame from catalog, or using “from options” with which you can point to a specific S3 location to read the data and, without creating a classifier as we did before ,you can just set format options to read the data.
你可以在https://docs . AWS . Amazon . com/glue/latest/DG/AWS-glue-programming-ETL-format . html中找到更多关于格式选项的信息
- 关系化:
我在以下步骤中使用了由 from options 创建的框架:(即使您使用了 catalog 选项,输出也是一样的,因为 catalog 不会为数据保存静态模式。)
You can see that the transform returns a list of frames, each has an id and index col for join keys and array elements respectively.
如果看根表会更清楚。例如,填充在根表的这个字段中只有一个整数值,这个值与上面的根 _ 填充 _ 填充帧中的 id 列相匹配。
重要的是,我们看到“batters.batter”字段传播到多个列中。对于项目 2,“batters.batter”列被标识为 struct,但是对于项目 3,该字段是一个数组!。所以用胶水工作的难度就来了。
If you have complicated multilevel nested complicated structure then this behavior might cause lack of maintenance and control over the outputs and problems such as data loss ,so alternative solutions should be considered.
- Unnest 框架:
让我们看看这个转换将如何给我们一个不同的输出:
We can see that this time everything is in one frame but again “batters.batter” resulted in multiple columns , this brings uncertainty around the number of columns also. Considering an ETL pipeline, each time a new file comes in, this structure will probably change.
和 unnest 可以展开上层结构,但在展平结构数组方面无效。因此,由于我们不能在动态帧上应用 UDF,我们需要将动态帧转换为 Spark 数据帧,并在列上应用 explode,以将数组类型的列分散到多行中。我将把这部分留给你自己调查。
Moreover I would expect to have not two different spread of “batters.batter” and imho there could be an “array of structs” type column for this field and the “item 2” would have an array of length 1 having its one struct data.
最后… Databricks spark-xml:
这可能不是最好的解决方案,但这个软件包在控制和精度方面非常有用。一个很好的特性是,不可解析的记录也会被检测到,并且一个 _corrupt_record 列会被添加相关信息。
Now here is the difference I expected 😃 . You can see that “batters.batter” is an array of structs. Moreover for more reading options, you can have a look at https://github.com/databricks/spark-xml
Batters : No nulls, no probs
因此,您不需要考虑是否存在结构或数组列,您可以通过使用提取的模式来编写一个用于展开数组列的通用函数。
顺便提一下,我在 Glue 环境中使用了 Databricks 的 Spark-XML,但是您可以将它用作独立的 python 脚本,因为它独立于 Glue。
我们看到,尽管 Glue 提供了一行转换来处理半/非结构化数据,但是如果我们有复杂的数据类型,我们需要处理样本,看看什么符合我们的目的。
希望你喜欢它!
用因果图!
偶然的因果推断
这是关于数据科学因果关系系列的第二篇文章。你可以查一下第一个“数据科学中我们为什么需要因果关系?和下一个“观察不干预”。正如我们所说,目前有两个主要的框架来处理因果关系:潜在的结果和图表。在这里,我们将继续解释为什么因果推理是必要的,以及图形如何帮助它。
图形模型
图表是一个很棒的工具。通过图来模拟因果关系带来了一种合适的语言来描述因果关系的动态性。每当我们认为事件 A 是 B 的原因时,我们就在那个方向画一个箭头。
这意味着你的模型正在考虑从 A 到 B 的一个可能的因果关系。这从“A 是因果关系的主要来源”到“A 几乎不能解释关于 B 的任何事情”。具体来说,它包括 A 是 b 的原因而不是的情况。你可能会对现实建模过度,但模型不会是不正确的。这就是为什么,关键的假设是在你不放箭的时候出现的。在这种情况下,你声称变量之间是独立的,你应该能够论证和辩护为什么会这样。综上,假设越多,箭头越少。
谈论相关性是不够的
图表扩展了统计语言。最简单的例子就是相关性是对称的,而有向图则不是。我可以简单地写
下雨和地板潮湿之间的因果关系。反之, correlation(雨,湿地板)= correlation(湿地板,雨)。相关性是方向性盲的。如果要说因果关系,我们需要一种可以处理因果行为的语言。
就因果模型的公式而言,我们会写
湿地板:= f(雨,随机性)
这意味着潮湿的地板取决于雨水和其他一些随机变量(与雨水无关)。这里的关键是“:=”符号,这意味着雨影响潮湿的地板,而不是相反。这不是一个两边相等的数学方程,而是一个编程方程,其中湿地面的值是根据雨水计算的,但雨水的值不是根据湿地面设定的。
因果线性模型
线性模型是统计学的关键要素之一。通过因果透镜,他们很容易得出直接和间接影响的解释。首先,考虑下面的例子。一家飞机公司想将其业务扩展到一个新机场。他们选择一个机场,带上他们的飞机,设定价格,出售机票。在几个月的时间里,他们不断试验价格,直到达到一个有利可图的可持续价格。顾客在购买机票时,会考虑到从他们家到机场的距离以及航班的价格。由于他们是一家成长中的公司,他们在过去的 5 年里一直在这样做。这些事件可以通过下面的图表来描述,其中距离是与带来大部分客户的城市的距离,价格是月平均价格,航班是月平均航班数。
现在,他们想知道,对于他们想要合作的下一个机场,距离如何影响航班数量?通过观察数据,他们得出结论,在这种情况下,线性模型就足够了。然后他们执行线性回归,试图从距离和价格表达航班*。*
得到最终的线性模型
航班= -10 距离+ -5 价格
可以这样理解:固定一个特定的航班价格(比如 100 美元),如果你增加距离,航班数量将减少 10 个单位。但是,这不是你想要的!当你增加距离的时候,也会影响价格(不能固定)!你感兴趣的是当你改变一个单位的距离,又叫时航班改变了多少单位。**
从图形模型的角度来看,我们可以在每条边上放置一个线性模型,并具有以下方程组:
价格:= -3 距离+ Random_1
航班:= -10 距离+ -5 价格+随机 _2
现在我们看到距离到航班的两个影响:
- 直接效应 ( 距离 - > 航班):客户对距离的负面感知。
- **间接影响 ( 距离->-价格 - > 航班):距离的增加,迫使公司降低价格,从而产生航班的增加。
利用上面的公式,通过变量价格与距离的关系的替换,可以获得总效果:
航班:= -10 距离+ -5 价格+误差 _2 = (-10 + (-5)(-3))距离+随机 _3 = 5 距离+随机 _3
这种情况下的总效果是 5 (= -10 + (-5)(-3))。但这只是一个玩具例子。我们如何从数据中直接计算出总体效果?在这种情况下,您可以汇总所有直接和间接的影响,仅从距离表示航班。所以答案是只从距离对航班进行线性回归。
观察结论与第一次和最后一次回归分析有何不同。第一个得出的结论是距离对航班数量有负效应-10,而最后一个得出的结论是正效应 5!如果价格管理补偿了顾客对距离的负面看法,你仍然可以在寻找不太容易到达的机场时对航班数量产生积极影响。
结论:
- 如果您想计算总的影响,您应该从距离执行航班的回归(与第一次回归将所有变量放入计算中不同)。
- 使用图表有助于理解、推理和讨论整个分析。
数据本身不会说话
我们已经看到,为了计算距离对航班数量的影响,我们依赖于图表。现在想象一种不同的情况。航空公司,而不是上面描述的过程,他们已经进行如下:他们设置一个价格,在这个价格上他们想要设置他们的航班。之后,他们寻找一个他们认为能满足他们需求的机场。在这种情况下,我们将得到下图:
请注意,从距离到价格的箭头已经反转。在这种情况下,改变一个单位的距离根本不会改变价格!因此,如果我们想知道改变一个距离单位如何改变飞行中的一个单位,我们可以直接进行线性回归
航班= -10 距离+ -5 价格
答案是-10!这意味着数据生成的方式以及我们如何对这一过程建模非常重要。此外,这种知识不是来自数据,而是来自特定领域本身。我们最终可能会有两个相同的数据集,但是如果它们产生的方式不同,我们可能不得不以不同的方式来分析它们。
使用嵌入来预测临床研究的治疗领域
特定领域嵌入如何帮助分类
Image from Unsplash
临床研究是一个充满迷人概念的世界,其中存在大量可免费下载的数据集。我在understand(招聘)的任务之一是做一个概念验证,在大约 40 个手动定义的治疗领域中自动分类临床研究,如下所示:
Cardiology/Vascular Diseases
Dental and Oral Health
Dermatology
Genetic Disease
Hematology
Infections and Infectious Diseases
Musculoskeletal
Neurology
Nutrition and Weight Loss
Obstetrics/Gynecology
Oncology
Ophthalmology `
Pharmacology/Toxicology
Psychiatry/Psychology
Pulmonary/Respiratory Diseases
...etc...
可供参考的大约 289000 项研究可以在 ClinicalTrials.gov 的网站上找到。正如我们将在下面看到的,由于 CTTI ( *临床试验转化倡议)*提供了高质量的文档,人们可以下载完整的内容作为 CSV 文件或 Postgres 数据库供离线使用。特别是研究与一些医学术语相关联。
既然上述治疗领域是人工定义的,我们如何将它们与研究的医学术语联系起来?这就是 概念嵌入 的来源。下面介绍的所有代码都可以在 Jupyter 笔记本中找到
医学背景下的预训练嵌入
关于单词嵌入已经写了很多。这里有一个关于他们力量的很好的介绍。在本帖中,我们将使用预训练 ed 临床概念 嵌入将治疗区域映射到研究中。
美国国家医学图书馆(NLM)创建了统一医学语言系统(UMLS),这是一个令人难以置信的组织良好的医学概念和术语的来源,在其网站上有最好的描述:
UMLS 整合并分发关键术语、分类和编码标准以及相关资源,以促进创建更有效和可互操作的生物医学信息系统和服务,包括电子健康记录
特别是,一个核心概念是一个医学概念,像疟疾、放射疗法、肿瘤或白血病一样多种多样。每个概念由一个概念唯一标识符 (CUI)标识,并映射到各种医学术语的数据源,如我们将在下面使用的 MeSH (医学主题标题)。
这里有一个 富发布格式 (RRF)浏览器的截图,这是 UMLS 提供的一个强大的工具,从 NLM 获得许可证后就可以下载。可以通过单词搜索概念,并且可以找到与其他概念的关系:
Rich Release Format Browser
由 De Vine 等人从 348,566 份医学杂志摘要(由作者提供)中学习到的 UMLS CUIs 的预训练嵌入可以在此处下载,这要感谢 D. Sontag 等人在那里所做的出色工作(参见学习医学概念的低维表示)。以下是如何加载它们的方法,这要感谢令人敬畏的 gensim 库:
Load concept embeddings with gensim
正如所料,密切相关的概念的余弦相似性很高。例如,以下是与头痛或肝炎最接近的概念:
Most similar concepts
通过概念嵌入将研究与治疗领域联系起来
我们将通过以下途径将临床研究与概念嵌入的治疗领域联系起来:
- 从 AACT 的 browse_conditions.txt 文件中获取研究 MeSH 术语(医学主题词)
- 使用来自NLM 国家医学图书馆的文件将网格术语转换为其唯一标识符(又名代码
- 使用 UMLS 文件加载 UMLS 概念标识符(Cui)及其关联的网格代码。在这一点上,Cui 不再是抽象的。
- 手动将治疗区域与 UMLS 概念标识符(CUIs)相关联
- 使用预先训练的嵌入来找到 Cui(在 4 中找到)的区域。上图)与研究中的最相似(见 3。以上)
下图总结了一组数据源和转换:
1.获取与研究相关的网格术语
来自 ClinicalTrials.gov 的的 CTTI 提供了非常有条理和有记录的数据。可以从 CTTI 下载网站下载研究和相关数据。下面是我们感兴趣的数据子集(CTTI 提供的模式图):
病历报告在文件studies.txt
中,并链接到browse_conditions.txt
中的网格术语。下面是研究**NCT01007578**
关于动脉粥样硬化的网状术语的例子:
grep **NCT01007578** ./clinical-trials-gov/browse_conditions.txt1508569|NCT01007578|Atherosclerosis|atherosclerosis
1508570|NCT01007578|Peripheral Arterial Disease|peripheral arterial disease
1508571|NCT01007578|Peripheral Vascular Diseases|peripheral vascular diseases
1508572|NCT01007578|Arterial Occlusive Diseases|arterial occlusive diseases
加载这些内容并从病历报告 ID 到其网格术语集构建一个字典很容易。load_df()
是围绕熊猫的一个小包装器函数read_csv().
然后字典被构建:
2.将网格术语转换为它们的唯一标识符
r 相关的网格文件可以从国家医学图书馆下载。解析细节在笔记本里。
Build MeSH terms to MeSH codes dictionary
3.加载 UMLS 概念
我们现在将加载概念和源文件(MRCONSO.RRF
),这些文件来自大量 UMLS 文件这里。其格式在这里描述。在将这个 CSV 文件作为 pandas 数据框加载之前,我们可以通过只保留我们需要的列来将其大小(7148656 行,897Mb)减半。
Reduce Concepts File Size
short load_conso()
函数将缩减后的文件加载到数据帧中。查看相同的概念(相同的 CUI)如何映射到不同的源特定代码(不同的 SAB/代码):
MRCONSO.RRF excerpt
3.1 将网格代码映射到 Cui
从上面的数据框创建一个从网格代码到 CUIs 的映射。这将在以后用于将研究与概念 Cui 关联(通过网格代码)
Mapping MeSH codes to CUIs
然后我们使用 1 的结果。, 2.和 3.1 来构建概念 Cui 的研究标识符的字典。对于第一遍,我们删除引用了不在 CTTI 文件中的网格术语的病历报告:
3.2 将概念 Cui 映射到字符串
从上面的数据框创建一个从 CUIs 到相应字符串集的映射。这将在以后用于将治疗区域映射到 Cui:
Mapping CUIs to Descriptions
为了以后的评估目的,使用该映射将病历报告与由相关 Cui 的字符串组成的描述字符串相关联是有用的:
Study terms for Evaluation Purposes
4.手动将治疗区域与 UMLS 概念(Cui)相关联
治疗区域是手动定义的,以满足战略业务需求。因此,要把它们与研究联系起来,我们需要把它们与概念 CUIs 联系起来。这是这篇文章最棘手的部分。
主题专家了解每个领域,因此能够识别哪些字符串或描述与之相关。使用上面的cui_to_strings
字典,使用子字符串匹配很容易识别哪个 CUI 匹配哪个字符串。
例如,对于心脏病学区域,让我们尝试保留其术语集至少包含cardiodiolog
和cardiovascul
子字符串的所有 Cui(结果被截断):
Finding Cardiology’s Concepts (output truncated)
Cardiology Concepts (output truncated)
通过在两组嵌入向量上使用 Gensim 的KeyedVector.n_similarity()
,希望这组 Cui 与关于心脏病学的研究之间的相似性会很高。
在某些情况下,有必要要求术语来自多个集合。例如,对于区域感染和传染病,第一个集合[‘infectious’, ‘infected’, ‘infection’]
返回与感染相关的概念,但不一定是疾病。以下尝试给出了更好的结果:
Finding Infectious Diseases’ Concepts (output truncated)
在其他情况下,一些术语匹配来自非期望区域的 Cui。对于牙齿和口腔健康区域,使用[‘tooth cavit’, ‘caries’, ‘cavities’]
会从许多不需要的区域产生 Cui。关于与牙齿区域无关的一组腔相关的串,参见excluded_terms
参数。下面的最终结果似乎没有异常值:
5.使用概念嵌入将研究与治疗领域相匹配
这是所有东西放在一起的地方。从目前构建的结构来看,不难使用蛮力来保留与使用 Gensim 的KeyedVector.n_similarity()
的每项研究最相似的治疗区域:
- 这个概念来源于这项研究(字典
std_to_cuis
) - 这个概念来源于各个治疗领域
Matching studies with therapeutic areas
结果
结果可以用以下代码显示:
Studies matched to therapeutic areas
以下是不同治疗领域的典型结果摘录。由于空间限制,它被截断。如果它太小而无法在你的设备上阅读,那么笔记本包含了更多的结果,有助于在不执行代码的情况下查看它们(执行代码需要从 UMLS 获得下载文件的许可,这并不困难,我得到了 NLM 的热情支持)。
对结果的一些评论
尽管一些研究被错误分类,结果还是很有趣。通常关注误分类有助于理解哪个崔导致(或影响)了错误的选择。
当关注一个错误的分类时,总是关注第二个和第三个治疗区域,看看它们与第一个有多接近。例如,在下面的错误分类中,第二个(正确的)区域Trauma, 0.49841
与第一个(不正确的)区域Urology: 0.50133
非常相似。这告诉我们,结果并不总是那么糟糕,重点应该放在更糟糕的错误分类上。
study: NCT03677856terms: {'thoracic diseases', 'anesthetic drug', 'anesthesia agent', 'thoracic diseases [disease/finding]', 'anaesthetics', 'thoracic disorder', 'anaesthetic drugs', 'anaesthetic agent', 'anesthetics drugs', 'anesthetic agent', 'diseases, thoracic', 'anesthetic', 'agents, anesthetic', 'anesthetic agents', '[cn200] anesthetics', 'thoracic disease', 'disease thoracic', 'anesthetic drugs', 'disease, thoracic', 'thoracic dis', 'anesthetics', 'drugs, anesthetic', 'anesthestic drugs', 'drugs causing loss of sensation'}ranks: [('Urology', 0.50133), ('Trauma', 0.49841), ('Neurology', 0.49322), ('Dermatology', 0.48437), ('Obstetrics/Gynecology', 0.47121)]
在某些情况下,可能需要手动验证每个 CUI,并从特定治疗区域或研究中删除或添加一些 CUI,并找到导致不匹配的 CUI(借助 gensim 的相似性函数)。然后试着推断这个崔和其他人的互动来理解引起不一致的语义方面。笔记本收录了一些值得调查的误分类。
结论和可能的改进
- 获取每个治疗区域的 Cui 至关重要。这可能会变得棘手,如上面的例子所示(牙科或传染病)。
- 如果我们无法找到合适的折中方案,可以使用 NLM 的 RRF 浏览器(见上面的截图)浏览相关概念,并手动将每个 Cui 分配到一个有问题的治疗区域。有时一些概念重叠,相似性将无法给出好的结果。需要从负面案例开始进行更多的调整/调查。
- 进行集成:在这里使用另外两个可用的 CUI 嵌入(更小,但可能仍然是好的)希望它们可以弥补这里尝试的嵌入中缺少的概念。由于这些其他嵌入更小,预计不会有很大的改进。
- 如果不对病历报告进行分类比错误分类更好,请考虑对第一个区域和第二个区域之间的相似性差异使用阈值。只有当差异大于阈值时才预测治疗区域,因为第一和第二区域之间的间隔被认为足够宽。
用 K 近邻(KNN)找更好的公司。
介绍
大多数公司的问题是薪水的辞职,辞职的主要原因之一是他们对他们工作的地方不满意,无论是他们工作的团队,还是他们在同一个部门的办公室的员工,一个想法出现在脑海中,为什么不使用 KNN 对人们进行分类,这样我们就可以得到最好的工作地点,怎么样?在本文中,我将阐明这种分类是如何工作的。
我们将看看如何使用 K 最近邻算法来帮助我们完成这项劳动密集型任务。
下面是我们将要做的事情的概述:
- 获取不同特征的人之间关系的数据集。
- 根据从培训数据集生成的距离表计算两个薪资之间的距离。
- 使用分类器将新的薪水分类到正确的部门。
数据
首先,我们需要一个数据集。为此,我建议从具有不同特征的人之间的关系中获取数据,这些数据可以从任何地方、社交媒体、法庭案件等中提取…—该数据集是一个数据集合,如兴趣、性别、家庭状况、宗教、根源、个人详细信息等…).
如何计算距离
我们将使用一个表,该表根据对工资两个特征之间的理解来确定距离,该表对角线上的值为 0,因为具有相同特征的两个雇员很接近,这些值可以随时改变,并且是从现实生活中提取的,例如,如果 A 国对 B 国的种族歧视很严重,A 国的工资与 B 国的工资之间的距离就会很长。
在 KNN 中,将使用距离之和而不是欧氏距离。
例如:
假设我们有一个有 3 份薪水和 3 个办公室的公司。我们想多招三个工资,前提是每个员工进一个办公室。最终,我们将在公司获得 6 份工资,按每个办公室两名员工的比率计算。我们将使用我之前解释过的方法,把适合他们的新工资放到办公室里。
薪资清单:
Figure 1 : List of Salaries (old and new ones )
距离表:
Figure 2 : Distances between characteristics .
注意:表格上的数字是随机数字,它们没有任何依据。
在本例中,我们采用 3 个属性来计算距离、熟悉情况、根源和兴趣。
注意:为了得到好的结果,你应该使用许多属性。
这是公司的状态 1:
Figure 3 : the state of the company before adding the new salaries.
我们将 3 个新的薪水分类,他们是:克里斯,乔丹和亚当。
我们需要将每个员工放在每个办公室,因此我们需要计算每个新工资和每个旧工资之间的距离。
计算距离:
对于克里斯:
D(克里斯,杰克)=D(单身,已婚)+D(非洲,美洲)+D(体育,艺术)
=1+1.1+0.9=3
D(克里斯,卡莉)=D(单身,已婚)+D(非洲,亚洲)+D(运动,体育)
=1+1+0=2
D(克里斯,阿丽亚娜)=D(单身,离异)+D(非洲,欧洲)+D(运动,旅行)
=2+1.8+0.6=4.4
代表约旦:
D(乔丹,杰克)=D(已婚,已婚)+D(非洲,美洲)+D(艺术,艺术)
=0+1.1+0=1.1
D(乔丹,卡莉)= D(已婚,已婚)+D(非洲,亚洲)+D(艺术,体育)
=0+1+0.9=1.9
D(约旦,阿丽亚娜)= D(已婚,离异)+D(非洲,欧洲)+D(艺术,旅行)
=1.5+1.8+1.2=4.5
对于亚当:
D(亚当,杰克)= D(单身,已婚)+D(阿拉伯,美国)+D(体育,艺术)
=1+2+0.9=3.9
D(亚当,卡莉)= D(单身,已婚)+D(阿拉伯,亚洲)+D(体育,运动)
=1+0.9+0=1.9
D(Adam,Ariana) = D(单身,离异)+D(阿拉伯,亚洲)+D(体育,运动)
=1.5+0.9+0=2.4
根据图 2 计算距离后,我们得到:
Figure 4 : The final result of calculation.
根据表格和图表,我们可以这样对 3 名新员工进行分类:
克里斯会和卡莉在 2 号办公室。
乔丹将和杰克在 1 号办公室。
亚当会和阿丽亚娜在 3 号办公室。
Figure 5 : the state of the company after adding the new salaries.
在这种情况下,K = 1,因为我们每个办公室只有 1 份工资,所以 K 比率可以根据公司的规模而变化。
结论:
我们能够避免公司中新工资的随机分类,现在当新工资进入公司时,我们有了一些依据,我们希望将它放在正确的生态系统中,以提高员工的生产力,减少公司中的冲突。
使用 Kaggle 开始(并指导)您的 ML/数据科学之旅——为什么和如何
我经常被我的朋友和大学同学问到——“如何开始机器学习或数据科学”。
所以,这是我的答案…
之前,我并不确定。我会说类似这样的话:先学这门课,或者先读这篇教程,或者先学 Python(只是我做过的事情)。但是现在,随着我在这个领域越来越深入,我开始意识到我所采取的方法的缺点。
所以,后知后觉的我认为,最好的【进入】 ML 或者数据科学的途径可能是通过**。
在这篇文章中,我会告诉你为什么我会这样想,如果你被我的推理说服了,你该怎么做。
( 谨慎 ):我是学生。我的职业不是数据科学家或 ML 工程师。我绝对不是 Kaggle 的专家。所以,对我的建议/意见要有所保留。 😃)
但首先,让我介绍一下 Kaggle,并澄清一些对它的误解。
你可能听说过 Kaggle,它是一个为大联盟比赛提供令人难以置信的现金奖励的网站。
Competitions hosted on Kaggle with the maximum prize money (yes those are MILLION DOLLAR+ prizes!)
正是这种名声也导致了对平台的许多误解,并使新来者感到比他们应该开始的时候更加犹豫。
(哦,如果你以前从未听说过 Kaggle,请不要担心,因此,不要分享下面提到的任何误解。这篇文章仍然有完整的意义。就当下一节是我给你介绍 Kaggle 吧。)
误解:
- “ka ggle 是一个举办机器学习竞赛的网站”
这是对 Kaggle 的一个不完整的描述!我相信竞赛(以及它们非常丰厚的现金奖励)甚至不是 Kaggle 的真正瑰宝。看看他们网站的标题——
Competitions are just one part of Kaggle
除了主持Competitions
(它现在已经主持了大约 300 场)之外,Kaggle 还主持了三件非常重要的事情:
[**Datasets**](https://www.kaggle.com/datasets)
,甚至是那些与任何比赛都不相关的:它拥有 9500 多个数据集,相比之下只有 300 个比赛(在撰写本文时)。所以你可以通过选择任何你感兴趣的数据集来提高你的技能。
Some of the datasets that I find most interesting
- 它们只是 Kaggle 版本的 Jupyter 笔记本,反过来,它们只是一种真正有效的和酷的方式来分享代码以及大量的可视化、输出和解释。“Kernels”选项卡将带您到一个公共内核列表,人们使用这些内核来展示一些新工具或分享他们关于某些特定数据集(/s)的专业知识或见解。
[**Learn**](https://www.kaggle.com/learn/overview)
: 此选项卡包含免费的实用实践课程,涵盖了快速入门所需的最低先决条件。他们最大的优点是什么?—一切都是使用 Kaggle 的内核完成的(如上所述)。这意味着你可以互动和学习…不再被动阅读数小时的学习材料!
所有这些使得 Kaggle 不仅仅是一个举办比赛的网站。现在,它已经成为一个完整的基于项目的数据科学学习环境。我将在本节之后详细讨论 Kaggle 的这一方面。
2。“只有专家(博士或有多年经验的 ML 从业者)才能参加并赢得 Kaggle 竞赛”
如果你这样认为,我强烈建议你读读这个—
如果你深入人工智能世界,你肯定知道谷歌云拥有的平台 Kaggle
mashable.com](https://mashable.com/2017/07/28/16-year-old-ai-genius/)
TL;博士: 一个高中生成为了 Kaggle 竞赛的大师简直就是*(或者不那么简单,也许?)*跟随自己的好奇心,一头扎进比赛中。用他自己的话说,
“我不知道算法背后的所有数学,但就实际使用它而言,我认为对它的工作原理有一个逻辑理解要重要得多。”
3。“我应该在参加 Kaggle 比赛之前多做几门课程,学习先进的机器学习理念,这样我赢的机会更大”——
机器学习最重要的部分是探索性数据分析(或 EDA)和特征工程,而不是模型拟合。事实上,许多 Kaggle 大师认为新手太快转向复杂的模型,而事实是简单的模型可以让你走得很远。
正如阿尔伯特·爱因斯坦所说—
“任何聪明的傻瓜都能把事情变得更大更复杂。朝着相反的方向前进需要一点天赋和很大的勇气。”
此外,许多挑战都涉及结构化数据,这意味着所有数据都存在于整齐的行和列中。没有复杂的文本或图像数据。因此,简单的算法(没有花哨的神经网络)通常是这类数据集的获胜算法。在这种情况下,EDA 可能是一个成功的解决方案与其他解决方案的不同之处。
现在,让我们继续讨论为什么应该使用 Kaggle 开始学习 ML 或数据科学…
为什么要入门 Kaggle?
原因 1——准确了解开始行动的必要条件
Kaggle Learn 上的机器学习课程不会教你 ML 算法背后的理论和数学。相反,它只专注于教授那些在分析和建模数据集时绝对必要的东西。同样,那边的 Python 课程不会让你成为 Python 专家,但它会确保你知道的足够多,可以进入下一个阶段。
这可以最大限度地减少你需要花费在被动学习上的时间,并确保你已经准备好尽快接受有趣的挑战。
原因 2——体现了培养学习能力的精神
我相信做项目是如此有效,以至于你的整个学习都应该围绕着完成一个项目。我想说的是,与其在你学到一些东西后寻找一个相关的项目,不如从一个项目开始,学习你所需要的一切来实现这个项目。
正如惠特尼·约翰逊在音阶大师播客中所说,
“基本上,你,我,每个人,我们都想学习和跳跃,然后重复。”
我相信这样学习会更令人兴奋和有效。
(几周前,我写了一篇关于上述方法论的文章。其名为—如何(以及为什么)开始构建有用的、现实世界中没有经验的软件。所以,如果你还没有 😃,就去看看吧)**
I believe that this is also true for courses and tutorials
但是,当你没有一个可以跳跃的项目时,这个想法就完全失败了。做一个有趣的项目是困难的,因为…
答…很难找到一个有趣的想法 而找到数据科学项目的想法似乎更加困难,因为需要有合适的数据集。
b)…我不知道该如何处理我知识中的那些漏洞。有时候当我开始一个项目时,我觉得有太多的事情我还不知道。感觉连学习构建这个东西的前提条件都不知道。我是不是力不从心了?我如何着手学习我不知道的东西?那就是所有动力开始消失的时候。
c)…我经常被“卡住”,好像在建立过程中我不断碰到一个又一个的障碍。如果我能有一群人,知道他们会如何解决这个问题,那该多好。
以下是 Kaggle 如何为所有这些问题提供解决方案的方法—
Soln。a → [**Datasets**](https://www.kaggle.com/datasets)
和 [**Competitions**](https://www.kaggle.com/competitions)
: 大约有 300 个竞赛挑战,都附有它们的公共数据集,总共有 9500+个数据集(还有更多在不断添加)这个地方就像是数据科学/ ML 项目创意的宝库。
索伦。b → [**Kernels**](https://www.kaggle.com/kernels)
和 [**Learn**](https://www.kaggle.com/learn/overview)
: 让我告诉你内核是如何有帮助的…
所有数据集都有一个公共内核标签,人们可以在这里发布他们的分析,以造福整个社区。所以,任何时候当你觉得不知道下一步该做什么的时候,你可以通过查看这些内核来获得一些想法。此外,许多内核是专门为帮助初学者而编写的。
Soln。c → [**Kernels**](https://www.kaggle.com/kernels)
和 [**Discussion**](https://www.kaggle.com/discussion)
: 随着我上面刚刚描述的公共内核,每个比赛和每个数据集也有自己的讨论论坛。所以,你总有地方提问。
除此之外,“在竞赛期间,许多参与者会写一些有趣的问题,强调数据集中的特性和怪癖,一些参与者甚至会在论坛上发布性能良好的基准测试代码。比赛结束后,获胜者通常会分享他们的获胜方案”(一篇名为《向最优秀的人学习》的文章)**
原因#3 —解决实际问题的实际数据= >实际动机
Kaggle 上的挑战是由寻求解决他们遇到的真实问题的真实公司主办的。他们提供的数据集是真实的。所有的奖金都是真的。这意味着您可以学习数据科学/ ML,并通过解决现实世界的问题来实践您的技能。
如果你以前尝试过竞争性编程,当我说这些网站上的问题有时感觉太不现实时,你可能会有同感。我的意思是为什么我要写一个程序来找出一个数组中毕达哥拉斯三元组的个数?那有什么用呢!?
我并不是想断言这样的问题很容易;我发现它们非常难。我也不是想削弱存在此类问题的网站的重要性;它们是测试和提高你的数据结构和算法知识的好方法。
我想说的是这一切对我来说都太虚构了。当你试图解决的问题是真实的时候,你会一直想要改进你的解决方案。这将提供学习和成长的动力。这就是你参加 Kaggle 挑战赛的收获。
争论的另一方:“机器学习不是 Kaggle 竞赛”
我将不负责任地不提这场辩论的另一面,即认为 机器学习不是 Kaggle 竞赛 ,而 Kaggle 竞赛仅仅是 代表一种“旅游式 sh * t】的实际数据科学工作。
嗯,也许那是真的。也许真正的数据科学工作并不像 Kaggle 竞赛中采用的方法。我没有从事过专业工作,所以我知道的不多,无法做出评论。
但是我所做的,很多时候,是利用教程和课程来学习一些东西。每一次,我都觉得教程/课程和我的学习动机之间存在脱节。我会学习一些东西,只是因为它在教程/课程中,并希望它在某个遥远、神秘的未来派上用场。
另一方面,当我在做 Kaggle 挑战时,我有一种学习的实际需求。我有一个阶段,可以让我立即应用我所学到的东西,并看到它的效果。这就给了动力和粘合剂,让所有的知识都粘在一起。
如何开始:
拥有所有这些雄心勃勃的、真实的问题有一个不利的方面,那就是对于初学者来说,这可能是一个令人生畏的地方。我理解这种感觉,因为我自己最近也开始使用 Kaggle。但是一旦我克服了最初的障碍,我完全被它的社区和它给我的学习机会所折服。
所以,在这里我试着告诉你如何开始:
第一步。涵盖基本要素
选择一种语言: Python 或者 R 。
一旦你做到了这一点,前往 Kaggle Learn 快速了解该语言、机器学习和数据可视化技术的基础知识。
Courses on Kaggle Learn
第二步。找到一个有趣的挑战/数据集
我建议你在出发时选择一个游乐场比赛或更受欢迎的比赛。通过这种方式,你至少可以找到一些旨在帮助新来者的公共内核。
记住你的目标不是赢得比赛。就是学习和提高自己的数据科学/ ML 知识。
Select one of these if you are still unsure
第三步。探索公共内核
他们将帮助你了解这个领域的一般工作流程,以及其他人在这个竞赛中采取的特殊方法。
通常,这些内核会告诉你一些你在 ML/ Data Science 中不知道的东西。当你遇到一个不熟悉的术语时,不要气馁。
知道你需要知道的是走向知识的第一步。
它们只是你需要学习来帮助你成长的东西。但在此之前…
第四步。开发自己的内核
去做你自己的分析吧。用你目前的知识尽可能多地构建。在您自己的内核中实现您从前面的步骤中学到的任何东西。
第五步。了解您需要做的事情,然后回到第 4 步
现在,你来学习。有时,它只是一篇短文,而有时它可能是一个有内容的教程/课程。请记住,您需要返回到步骤 3,并在您的内核中使用您所学的内容。这样你就创造了所需的循环——“学习、跳跃和重复”!
第六步。通过返回到步骤 3 来改进您的分析
一旦你建立了一个完整的预测模型,你就到了这一步。所以,祝贺你!🎉
现在你可能想改进你的分析。要做到这一点,你可以回到第 3 步,看看其他人做了什么。可以给你改进模型的想法。或者,如果你觉得你已经尝试了所有的方法但是都碰壁了,那么在论坛上寻求帮助可能会有帮助。
An example of such a discussion
太好了!现在去做更多的挑战,分析更多的数据集,学习更新的东西!**
其他资源的链接
学习 Python:
Python 变得超级流行。这意味着有大量优秀的指南和教程可以帮助你开始学习这门语言。这是我第一次学习 Python 时使用的两个资源—
显然,这些并不是学习 Python 的权威资源列表,但这些是我刚开始学习时最有用的。
机器学习文章:
在你深入研究一个领域之前,你可能想知道它是关于什么的。所以,这里有几篇文章对机器学习进行了有趣的介绍—
- 《如何学习机器学习,自我启动的方式 》作者 EliteDataScience 一篇写得很好的文章,在介绍机器学习方面做得很好,甚至还设计了一个自学课程!
- Vishal Maini本指南面向所有人。将讨论概率、统计、编程、线性代数和微积分中的基本概念,但要从本系列中获益,并不需要事先了解它们。”********
- 《最好的机器学习资源 作者Vishal Maini本文是上面提到的系列的一部分。我单独提到它,是因为它有一套非常好的、全面的与 ML 相关的链接。
- 机器学习很好玩byAdam geit gey看完这个系列就知道 ML 有什么酷了。虽然它很有技术性,但它可以成为对该领域了解更多的动力来源。
数据科学博客:
这里有一些与数据科学相关的好博客,你可以去看看
编辑:发表这篇文章帮助我与世界各地令人惊叹的专业人士建立了数百种联系。
你想像我一样写作吗?
我开设了一门写作课程,教你如何在网上开始写作之旅。这就叫——清晰写作,清晰思考 而我是 免费赠送 !
Clear Writing, Clear Thinking — a free 5-week email course that’ll teach you how to write well
请在下面的评论区告诉我你的想法。
你可以在 Twitter 上关注我,或者在 LinkedIn 上联系我——我不会给你发垃圾信息。;-)
使用 nvidia-docker 为 R 和 Python 创建令人敬畏的深度学习环境
安装完整的支持 GPU 的深度学习环境(包括 RStudio 或 jupyter)和所有软件包需要多长时间?您必须在多个系统上这样做吗?在这篇博文中,我将向您展示我如何以及为什么使用支持 GPU 的 docker 容器来管理我的数据科学环境。在这第一篇文章中,你会读到:
- 为什么我的数据科学工作流完全转向容器
- docker 是什么,它与虚拟机相比如何(如果你已经知道,跳过它!)
- 我如何构建我的数据科学映像
- 如何在 GPU 支持下用 r-base、Keras 和 TensorFlow 构建容器
现状
您如何管理您的数据科学堆栈?我从来没有真正满意过我是如何做到的。在不同的机器上安装整个堆栈,包括我使用的所有包、GPU 支持、Keras 和 TensorFlow for R 以及底层的 Python 内容,是一个乏味而繁琐的过程。你最终会得到一个非常脆弱的工具链,而我是那种喜欢摆弄和破坏东西的人。这也有更多的负面影响。例如,不同机器上的环境不一样。我在至少三台不同的机器上进行数据科学研究:我的笔记本电脑,我的装有 GTX 1080 Ti 的工作站和 AWS 实例。我的开发环境和主机操作系统早就应该分离了。我一直都知道,虚拟机不是一个好办法,因为它们会产生很多开销,而且您必须提前分配所有想要使用的资源。
Docker 非常适合这个目的。它给你一个隔离的开发环境,保护你不把事情弄糟。当我看到英伟达 GPU 云(NGC)时,我知道这将解决我的问题。NGC 不是云服务,而是一个容器注册表,你可以在那里下载预构建和 GPU 支持的 docker 映像,这些映像针对不同的工作流进行了优化。有针对 TensorFlow,pytorch,caffe 等框架的图片。好的一点是:你不用关心任何驱动,框架或者包的安装。你可以马上启动 python,导入 TensorFlow,拷问你的 GPU。不幸的是,这些图像包含 NVIDIA 的专有软件来优化计算。你可以出于各种目的免费使用它,包括商业用途,但是你不允许重新发布他们的图片。这可能就是为什么你在像 Rocker 这样的项目中找不到它们的原因。你当然可以做的是发布 docker 文件,使用这些图像作为基础图像,这就是我在这篇博文中要做的。
为什么是 Docker?
如果你已经知道 Docker 是什么,以及它与虚拟机相比如何,你可以跳过这一节。我只给你一个简短的概述,有很多好的教程可以学习 Docker 是如何工作的。顺便说一下:我远不是 Docker 的专家,但你真的不需要成为这样的专家。看看下面这张图。左边显示了虚拟机是如何工作的:每个实例模拟一个完整的操作系统。对我来说,这从来都不是数据科学环境的选项。这会产生一些开销,但最重要的是,您必须提前分配资源,并且这些资源不会与您的主机系统共享。对于在同一台机器上使用主机作为通用系统和虚拟机进行数据科学的设置,这是不切实际的。
对于这种情况,使用容器隔离要好得多:它基本上只是一个隔离的文件系统。它使用你的主机系统的内核,这当然增加了很少的开销。不幸的是,对于 Windows 或 Mac 上的 Docker 来说,情况并非如此,因为它在底层使用的是 Linux 虚拟机。即使在我的笔记本电脑上,我也总是尝试完全切换到 Linux,正因为如此,我做到了。但是,即使你想坚持使用 Windows 或 Mac:你可能正在使用 Linux 的工作站或云实例。真正有趣的部分显示在图像的右侧:带有 nvidia-docker 运行时的容器。那些容器可以使用主机系统的 GPU。您只需要一个支持 CUDA 的 GPU 和主机系统上的驱动程序,仅此而已。
现在简单介绍一下 docker 的工作原理以及与之相关的术语。Docker 中最重要的两个概念是图像和容器。该图像包含创建容器的蓝图。它是分层构建的,可以只包含操作系统的基础知识,也可以包含更复杂的软件堆栈。容器是 docker 图像的一个实例。除了您可以访问您的主机系统的资源之外,它与虚拟机的感觉完全相同。因此,当您从一个映像启动 docker 容器(并告诉它是交互式的)时,您将进入一个 shell 环境,就像您登录到一个 VM 一样。容器启动速度也非常快。它几乎不可识别,而在虚拟机中,你必须启动操作系统。
要构建 docker 映像,您必须编写一个 docker 文件。有两种方式可以做到这一点:使用父映像或从头开始,只有当您想要创建新的基础映像时才需要这样做。在大多数情况下,您将使用基础映像作为父映像,并在此基础上构建您的软件堆栈。如果你想在 Ubuntu 16.04 上建立你的映像,你的 docker 文件的第一行应该是:FROM ubuntu:16.04
。获取图像最常见的方式是从 docker hub 获取图像,docker hub 是一个共享图像的平台。Docker 自动完成这项工作,或者您也可以使用 docker pull ImageName 手动提取图像。在 Ubuntu 和其他常用图像的情况下,有来自 docker 工作人员的官方维护图像。正如您将在下一节中看到的,您还可以从 docker hub 之外的其他存储库中提取图像。
获取 Docker 和 TensorFlow 容器
Docker 和 nvidia 运行时非常容易安装。以下命令使用 get.docker.com 的安装脚本安装免费的 docker 社区版。这个脚本可以在所有常见的 Linux 发行版上安装 docker(详情请看 get.docker.com 的):
*#Install docker via get.docker script*
curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh
要安装 nvidia-docker 运行时,您必须添加它们的软件包存储库,并安装和重新加载 docker 守护程序。我使用 Ubuntu 16.04 作为主机系统,但是这应该可以在任何使用 apt 的基于 debian 的发行版上工作。
*#Add the package repositories for nvidia docker*
curl -s -L [https://nvidia.github.io/nvidia-docker/gpgkey](https://nvidia.github.io/nvidia-docker/gpgkey) | \
apt-key add -curl -s -L [https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-docker.list](https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-docker.list) | tee /etc/apt/sources.list.d/nvidia-docker.listapt-get update
#*Install nvidia-docker2 and reload the Docker daemon configuration*
apt-get install -y nvidia-docker2 pkill -SIGHUP dockerd
要检查是否一切正常,您可以加载 cuda 映像并执行 nvidia-smi:
*#Test nvidia-smi with the latest official CUDA image*
docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi
该命令从 docker hub 下载 cuda 映像,基于该映像启动一个容器,在容器内执行命令 nvidia-smi,然后立即离开容器并删除它。您应该会看到类似这样的内容:
这意味着我的 GTX 1080Ti 在集装箱内可用!这个 cuda 图像是 NVIDIA 在 docker hub 上托管的图像之一。对于优化的深度学习容器,你必须注册英伟达 GPU 云( NGC ),它不是云服务提供商,而是类似于 docker hub 的容器注册表。它是免费的,你可以将这些容器用于你自己的或商业的目的,但是你不允许再分发它们。注册后,在左侧菜单中选择配置,并生成一个 API 密钥。有了这个键,你可以在 NVIDIA 注册表中注册 docker 安装。你应该把钥匙保存在安全的地方。使用 docker login nvcr.io 命令进行注册。作为用户名,您必须使用 o a u t h t o k e n ( 带 oauthtoken(带 oauthtoken(带符号!)和 API-Key 作为密码。现在,如果您使用以下命令,docker 应该下载优化的 TensorFlow 容器:
docker pull nvcr.io/nvidia/tensorflow:18.04-py3
我如何建造
我在创造我在不同阶段使用的环境。在第一张图中,我只是安装了 R-base、Python 和 R 的 Keras、R 的 TensorFlow 以及它们的依赖项。在下一张图中,我将在其上安装 RStudio-Server 和 jupyterlab。在第三张图中,我根据自己的需要定制了 RStudio,并安装了我想使用的所有包。
最后一步是安装更多的软件包。如果我意识到在工作会话期间我需要一个额外的包,我可以像在 RStudio 中那样自然地安装它。完成后,我将这个包添加到第四张图片中。如果我使用第三个,我每次都必须重新安装所有的软件包,这需要一些时间。使用 docker,您还可以提交对容器的更改。这也是永久安装新软件包的一种方式。我决定不这样做,以跟踪我添加到我的图像。分步创建这些容器还有另一个好处:您可以将图像用于不同的用例。例如,您可以使用 RStudio 图像创建一个神经网络并保存它。然后,您可以将这个模型加载到基本容器中,并创建一个基于 python 的 flask 微服务来部署它。或者你想做一个使用图像识别的闪亮应用程序。您可以使用 r-base 容器,添加 shiny 并部署它。或者您想为同事提供不同的定制 RStudio 版本。
安装 R-base 和 Keras
由于我们已经从 NVIDIA 获得了 TensorFLow 容器,现在我们可以开始构建 r-base 映像。构建 docker 映像本质上就是编写一个 shell 脚本,在您的映像中安装您想要的所有东西。就像我已经指出的,它被写在一个名为 Dockerfile *的文本文件中。*当您运行 docker build -t YourNameTag 命令时。在您的 docker 文件的文件夹中,docker 从您用 from 定义的基本映像启动一个容器,并在这个容器中运行您在 docker 文件中编写的内容。docker 在这个容器中执行什么是用 RUN 定义的。看看下面的 docker 文件:
FROM nvcr.io/nvidia/tensorflow:18.04-py3
LABEL maintainer="Kai Lichtenberg <kai@sentin.ai>"
*#Arguments*
ARG USER="docker"
ARG myUID="1000"
ARG myGID="1000"
*#Specifiy R and Keras Version*
ENV R_BASE_VERSION=3.4.4
ENV KERAS_VERSION=2.1.5
*#Set a user*
RUN groupadd --gid "${myGID}" "${USER}" \
&& useradd \
--uid ${myUID} \
--gid ${myGID} \
--create-home \
--shell /bin/bash \
${USER}
如果我在这个文件上运行 docker build,docker 会做以下事情:它基于我们下载的 TensorFlow 容器启动一个容器,添加一些环境变量(ARG 和 ENV)并创建一个组和一个用户。请注意,ARG 定义了仅在构建过程中可用的变量,您可以使用 docker build 命令为这些变量传递一个值。因此,当您使用 docker build-build-arg USER = Kai 启动命令时,默认的 USER="docker "将在构建过程中被覆盖。用 ENV 定义的变量是持久的,在从创建的映像启动的容器中也是可用的。下一步,我们安装 apt 所需的软件包:
*#Install packages needed*
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ed \
locales \
vim-tiny \
fonts-texgyre \
gnupg2 \
libcurl4-openssl-dev \
libssl-dev \
libssh2-1-dev \
sudo \
virtualenv \
&& rm -rf /var/lib/apt/lists/*
下一件事是安装 r。我用的是 CRAN 为 Ubuntu 提供的二进制文件。通常情况下,CRAN 很快就会发布最新版本,但目前(5 月 19 日)R 3.5 无法通过 CRAN 获得(阅读这里为什么)。我会等 3.5 出现在 CRAN 上。如果你非常想拥有 R 3.5,你可以像在这个docker 文件中一样安装它,并从源代码安装软件包。下一步中显示的安装与 Rocker 项目中的 r-base docker 文件相同。它正在安装 littler,这是一个方便的 CLI 接口,用于 R,r-base,r-base-dev 和 R-推荐用于 R_BASE_VERSION 环境变量中指定的 R 版本。它还在/usr/local/bin 中为 littler 创建了链接,使它在命令行中可用。
*#Add mirror*
RUN echo "deb [http://cran.rstudio.com/bin/linux/ubuntu](http://cran.rstudio.com/bin/linux/ubuntu) xenial/" >> /etc/apt/sources.list \
&& gpg --keyserver keyserver.ubuntu.com --recv-key E084DAB9 \
&& gpg -a --export E084DAB9 | apt-key add -
*# Install R-base (rocker/r-base with little modification)
# Now install R + littler, create a link in /usr/local/bin
# Set a default CRAN repo, make sure littler knows about it too*
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
littler \
r-cran-littler \
r-base=${R_BASE_VERSION}-* \
r-base-dev=${R_BASE_VERSION}-* \
r-recommended=${R_BASE_VERSION}-* \
&& echo 'options(repos = c(CRAN = "https://cran.rstudio.com/"), download.file.method = "libcurl")' >> /etc/R/Rprofile.site \
&& echo 'source("/etc/R/Rprofile.site")' >> /etc/littler.r \
&& ln -s /usr/share/doc/littler/examples/install.r /usr/local/bin/install.r \
&& ln -s /usr/share/doc/littler/examples/install2.r /usr/local/bin/install2.r \
&& ln -s /usr/share/doc/littler/examples/installGithub.r /usr/local/bin/installGithub.r \
&& ln -s /usr/share/doc/littler/examples/testInstalled.r /usr/local/bin/testInstalled.r \
&& install.r docopt \
&& rm -rf /tmp/downloaded_packages/ /tmp/*.rds \
&& rm -rf /var/lib/apt/lists/*
R 的 TensorFlow 和 Keras 包通过 reticulate 包连接到 python。这意味着我们需要为 R 和 python 安装两个包。两个 R 包都是通过 littler 提供的 github 安装例程安装的。因为我们使用的是 NVIDIA TensorFlow 映像,所以我们只需要关心 python 的 Keras(tensor flow 已经安装)。如果您以前使用过 Keras for R,您可能会注意到您必须调用函数 install_keras()来安装 python 后端。在我们的情况下,这已经完成了。唯一附加的事情是该函数创建了虚拟环境 r-tensorflow。在 python 中使用虚拟环境是一个很好的实践,尽管在 docker 容器中这是不必要的,因为它是双重隔离的。
*#Install tensorflow and keras*
ENV WORKON_HOME=/home/${USER}/.virtualenvs
RUN install2.r devtools remotes \
&& installGithub.r rstudio/tensorflow \
&& installGithub.r rstudio/keras \
&& virtualenv --system-site-packages /home/${USER}/.virtualenvs/r-tensorflow --python=python3.5 \
&& /bin/bash -c "cd /home/${USER}/.virtualenvs/r-tensorflow/bin/; \
source activate; \
pip3 --no-cache-dir install git+git://github.com/fchollet/keras.git@${KERAS_VERSION}"
好了,现在我们有了用 R 进行深度学习的基本图像!你可以在这里找到完整的档案。在下一部分中,我将使用 RStudio、jupyter 和定制来创建图像。如果你想获得这方面的更新,请在推特上关注我!
最初发表于 凯·利希滕伯格 。
使用 t-SNE 降低代谢组学数据集的维数
任何对代谢组学研究数据集有经验的人都会有需要降低其维数的经验。探索性分析所需的可视化极大地受益于将变量减少到可管理的数量。此外,一些变量可能是无信息的或多余的。当执行后面的统计分析或模型时,这些变量会增加计算时间,并会影响它们的性能。
降维可以基于信息特征的选择,或者基于更少数量的变量的合成,其最佳地保留了原始数据集中存在的信息。在代谢组学中执行维数减少的标准方法是主成分分析 (PCA)。然而,越来越多的新方法在减少变量数量时有望获得更好的性能。
一种趋势降维方法被称为 t 分布随机邻居嵌入 (t-SNE)。有多个在线例子显示了 t-SNE 优于 PCA 的优势(这里的例子)。然而,研究往往是根据以前是如何完成的来进行的。这种效应被称为路径依赖,会滞后研究效率,因为更好的方法会发现一些阻力,需要在该领域建立标准。我这篇博文的目的是展示 t-SNE 应用于代谢物定量数据集有多容易,以及应用它可能带来的好处。
MTBLS1 代谢研究包括对 48 名二型糖尿病患者的尿液样本和 84 份尿液对照样本之间的代谢差异的研究。存储库包含一个预处理代谢物量化数据集,包含 132 个观察值、188 个量化变量和一个标识符变量。许多变量是有噪声的,因为它们没有代表性的代谢物,或者是多余的,因为它们介导相同代谢物的信号。在 R 中,加载数据集和执行降维包括以下步骤:
库(tsne)
库(readxl)
ADG _ 变换 _ 数据< -读取 _ excel(" ADG _ 变换 _ 数据. xlsx ")
ADG _ 变换 _ 数据$主 id
= NULL
tsne _ ADG _ 变换 _ 数据= tsne(ADG _ 变换 _ 数据,困惑=50)
通过比较变量降维前后的样本分类,可以检验降维方法是否有效地综合了数据集的信息。预计更好的降维技术有助于提高样本分类的性能,因为它们以所选的分类算法能够更好地“理解”的方式分布和合成数据。
在原始数据集中进行随机森林分类时,样本分类时的出袋预测误差为 21.97%。当对输出维数不断增加的原始数据集执行 t-SNE 和 PCA 时,结果如下图所示(原始数据集中 21.97%的误差用黑线标记):
可以观察到通过 PCA 的维数减少几乎不能提高 MTBLS1 数据集中样本分类的性能。为了开始改善原始性能,需要将减少限制到至少 25 个变量。相比之下,t-SNE 帮助样本分类实现了低于 15%的误差。此外,它只需要略多于 10 个输出变量来实现这些好处。
这是一个 t-SNE 是一种非常有前途且易于应用的技术的例子,以在代谢组学研究中的样品分类期间实现更好的性能。
利用文本检索和搜索引擎技术进行税收分类
使用信息检索和人工智能(AI)技术来辅助财政分类(文本检索、信息检索、等级和产品税 HS 上应用的搜索)
摘要:使用 word2vec、BagofWords、unigram、bigram、标记化、文本相似性、OkapiBM25 +等技术来处理可用于税收分类建议的子项,如 TEC Mercosul(南美 HS(协调制度)本地定制)文本中所述,并根据搜索单词列表进行排序
正确的税收分类总是一个挑战。巴西版的共同对外关税文本有数万个单词,100 个章节,10,000 多个可用于分类的子项目,一个复杂且不总是统一的层次结构,此外还有章节注释、章节注释、总则等。在这项工作中,我们提议使用计算机来提高这些精确的数字,因为在这方面,计算机已经超过了人类(随着人工智能和机器学习的最新进展——人工智能机器学习和深度学习开始在处理文本的统计分析以及物体的视觉和识别方面达到我们,在某些情况下超过了人类)。
本文结构分为四个部分,相对独立。这样,读者可以直接跳到他最感兴趣的地方。第 1 部分处理概念部分,并对问题进行分析。第 2 部分和第 4 部分将更具技术性。如果您只想下载并测试演示本文概念的软件,可以直接阅读第 3 部分。
第 1 部分 —对技执委案文的分析以及对财政分类挑战的思考。首先是文字处理和选择路径。
第 2 部分—Python 编程语言中的测试和统计(带代码)。矢量化技术、二元模型、词干化、查询相似度和 OkapiBM25 +的应用。
第 3 部分——一个用 Java 编程语言开发的用户友好的全功能应用——在 GitHub 网站上有代码可以下载和“分叉”。
第 4 部分-讨论使用机器学习和其他技术的可能改进。
参考资料 —参考书目和在线资源
TEC/NCM——南方共同市场共同对外关税,将在第一部分中制定。
协调制度是 TEC 的国际版本,在第 1 部分也有解释。
第一部分
为了分析 TEC 文本,第一步是获取其最新版本。TEC 是一种法律规范,由 MDIC工业、外贸和服务部在巴西发布。MDIC 在下面的链接中以 Word 和 Excel 格式发布了 TEC 的最新版本。
【当前档案】www.mdic.gov.br MDIC
在 Word 中打开 TEC,我们可以开始分析它的结构。基本上,它有六个部分:
章节标题
缩写和符号
协调制度解释通则
补充通则
航空部门产品征税规则
南方共同市场共同术语(NCM)和共同税率
对于我们的工作来说,重要的部分是第六部分,依次划分如下:
章节(描述)
章节注释
章节(描述)
章节注释
表 NCM,描述,TEC
这里有一个附录和一个重要的观察:税收分类的任务是一项技术工作,它可能依赖于其他信息和具体知识,这些信息和知识不会写入技术执行委员会的文本,如冶金、化学或纺织方面的知识。除了关于税收分类规则的知识(在 TEC 中描述),语法和法律解释,产品分解混合案例,等等。因此,立法根据货物的税收分类(第 7.482 / 11 号法令第十九节第 15 条和 RFB 2014 年 5 月第 1464 号条例等)确定了税务机关(联邦税务局的财政审计员)。
还应当记住,我们现在所称的“TEC”是国际条约、传统、技术研究和标准的汇编,首先在世界海关组织签署的所谓的《布鲁塞尔国际公约》中的国际协调制度(HS)中进行汇编,然后扩大到南锥体共同市场 NCM——南锥体共同市场货物共同术语的经验和需要。此外,在巴西,还有 RIPI 的附加联邦法规—工业化产品税收法规以及 ICMS —州法规。
由于本文的总体重点不是财政分类或立法,我们不会深入探讨这个主题。一般分类问题暴露出来后才发现,在我们甚至研究 TEC 的文本之前,至少在现阶段,100%自动税收分类是一个乌托邦。这位作者设想的最佳解决方案是一个建议系统,非常类似于当我们在“谷歌”或另一个互联网搜索引擎上进行搜索时,我们从网页上收到的建议。
在这项工作中,所提出的系统将对 TEC 子项目进行“评分”,并以降序显示结果。毕竟有一万多种可能。然后我们会让计算机通过一个我们称之为“粗筛”的东西,我们只看几个排名更好的位置。如果运气好的话,我们可能只需要看看榜单的前三四名。
通过“运气”,我们也可以定义“正确”的问题。在这种情况下,问题是要分类的商品的描述。因此,当局(财政审计员)、进口商、制造商、技术助理、报关行、代理人或其他有责任描述商品的人必须这样做,以便正确识别产品并确定其正确的税收分类(RFB 680/2006 和海关条例第 711 条等)。
总之,我们可以从教学上把税收分类任务分成两步:描述产品;2.将描述插入正确的分类中。因为 TEC / NCM 是分等级的,我们可以用树来类比。通常,我们通过这棵树的树枝来寻找正确的位置。但是有一种可能性,我们正在看一个分支,而正确的项目在另一个分支,我们看不到它,因为我们在错误的分支中使用了非常相似的子项目。克服这种分层搜索是该系统的目标。
再打个比方,让我们想想一位埃及古物学者:在第一步中,他准确地定义了探险队要寻找的人工制品,并通过之前的研究描述了寻找的方式:人工制品怎么样,会是什么考古遗址,等等。第二步是探险本身。在这方面,团队被画廊,隧道等纠缠。你可以在一个房间里找到一件非常相似的艺术品,但是不要在隔壁房间里找,艺术品实际上是在那里被找到的。为了避免这种情况,我们的机器人将检查所有的房间,并根据与第一步中描述的工件的相似性对找到的工件进行评分。
该分数将基于描述所搜索内容的句子和每个 TEC 子项目之间的相似关系。
在税收分类的情况下,还有第三步,因为一个职位或章节或另一个职位或章节可能被排除在外,或者可能有一个条款或章节注释或其他类型的例外作为一般规则之一强加的条件。这项任务也可以通过自然语言处理技术实现自动化,但是这还不在 T2 的工作范围之内。
现在,我们所能理解的“TEC 的子项”。
分析“NCM 表,描述,TEC”部分,我们可以看到并不是所有的行在“TEC”列中都有值:
First page of TEC, Word version. Note the third column of the table
在屏幕上,我们可以很容易地注意到上面描述的结构(第二十章(描述),章节注释,NCM 表。我们还注意到,表中只有几行在第三列中有值(TEC%)。
因此,NCM 的结构是分等级的,按照协调制度:章(2 位数),位置(4 位数),子位置 1 和 2 (5 和 6 位数)。南方共同市场增加了两位数:项目和分项(分别为第 7 位和第 8 位)。只有包含 TEC 税率(以及 IPI 和 ICMS 自己的税率)的完整行、较高的订单才能用于税收分类。
但是回头看看表格,我们看到这些行中的描述字段通常是 Spartan。例如,分项 NCM 0102.21.10 只提到“怀孕或有脚印”,更糟糕的是,下面的 0102.21.90 只提到“其他”。
所以我们来创建一个概念,叫做“TEC List with full description”。这样,每个子项、项或子项都必须用其层次树的串联来描述。因此,我们知道,子目 0102.21.10 指的是“活牛——家畜——纯种配种动物”,子目 0102.31.90 指的是“活牛——水牛——纯种其他”。肯定比以前信息量大得多。我们仍然可以考虑在这个层次结构中添加章节的描述。
尽管每行提供的信息更多,但要搜索的单词总数会更大,因为许多单词会重复出现。还有,一些表格描述的字数本身就已经很大了,串联更多的描述会让一切变得更大。但是我们不能失去焦点:我们的目标是产生线条,以便计算机,而不是人类,寻找并包含单词的出现。在这一点上,计算机比我们人类好得多。这条被提议的线将被数字机器“消化”和(预)处理,它将只返回给人类它从 10,000 多个选项中寻找的“菲力”。
第二部分
GitHub 中提供了一个包含该文本所有代码的脚本。
classifier fiscal——这个 JAVA 系统使用文本中的搜索和处理技术来评分…
github.com](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://github.com/IvanBrasilico/ClassificadorFiscal&usg=ALkJrhhLSkthjCLrN65GJ4pSKq0h77GLhQ)
一般的想法放在第 1 部分(“创建带有层次树的级联描述的 TEC 列表,只用于带有非零值 TEC 列的表行。”),我们需要开始动手了。在 2017 年年中,要处理文本、字符、矢量,肯定没有比一个好的友好的 Python 脚本更快更有趣的方法了。
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.In The Zen of Python
此外,为了处理我们获得的数据,Python 生态系统有许多库,如 scikit-learn、NLTK、Theano、Tensor Flow,它们以最先进的形式实现了我们可能需要的许多算法。所以不用多此一举KeepingItSimple*****S*tupid(如果可以的话),我们开始工作吧!
第一项任务是分析文件的行,并考虑组装单词列表的处理。这将是一个简单的,逐行处理的文本文件。我们将尝试确定列表组合的标准,我们将制作“手指”,希望没有例外,文件的结构尽可能统一。我们称之为我们的 TEC 列表。然后,我们将通过创建一个包含完整描述的列表来处理第一个。我们称之为 TECResumo。
给定一组文档,第二步是提取你的“词汇”。这是应用“单词矢量化”和“BagofWords”技术的最重要部分。我们通过创建唯一单词的向量来遍历整个集合,并将它们称为 vocab。然后,对于 TEC 列表中的每一行,我们将组装一个与词汇表大小相同的向量。这将是一个名为 TEC vectors 的向量列表,包含每个单词的出现次数。使用“文本检索”中的技术术语,SUM 列表中的每一行都是一个文档,所有行构成一个集合。TTC 向量是每个文档的字数,而 vectorVocab 是集合的字数。这将是我们工作的核心。
*## Format of generated variables:
##
## TEC list: string list with each line of the text file
## listCapitulos: list of list containing title, description, and notes of each chapter
##NCM list: list list with each line containing the line code and after the description
##TECResumo list: string list containing the complete code and "complete" description of non-null TEC lines
## vocab: dict with key word and value occurrence count
##TEC vectors, vectorVocab: count of occurrences of the word per line and total count of occurrences of the word in the Collection
## In technical terms, each line of the list will be a collection document, vocab is the collection vocabulary*
第一步,处理 TEC 并创建我们的第一个列表“TEC 列表”的函数。第一个列表将与 TEC 的原始数据(原始数据)组合在一起,向用户显示与原始文件中完全一样的列表。使用 Word 本身或 LibreOffice 中的文件 tec * *—Word-complete . docx,我们将内容导出到文本文件。该文件将类似于下图:
TEC file in plain text format
我们需要做的是找到具有以下结构的行:第 1 行至少有两个数字和一个点,其中点在第 2 列或更大的列中,后面跟着一行只有文本。我们也将尝试提取章节和笔记,寻找以字母“Cap”开头的行,然后提取下一行直到“Note”行将标题和注释设置为“__ ”,以捕获注释。
首先,我们用文件的所有行组装一个列表
*def montaTEC ():
arq = open ("src / org / sort / resources / tec.txt")
TACfileset = arq.readlines ()
return TACWatchlist*
然后是章节列表
*def montaCapitulos (plistaTEC):
listCapitulos = []
r = 0
while (r <len (plistaTEC)):
line = plistaTEC [r]
if (line [0: 3] == "Cap"): #Search chapters
chapter = line
description = ""
r = r + 1
line = TEC list [r]
while (line [0: 4]! = "Note"):
description = description + line + ""
r = r + 1
line = TEC list [r]
notes = ""
r = r + 1
line = TEC list [r]
while (line [0: 4]! = "____"):
notes = notes + line + "\ n"
r = r + 1
line = TEC list [r]
list.append.append ([chapter, description, notes])
r = r + 1
return listCapitulos*
以下是 NCM 等级列表:
*def montaNCM (plistaTEC):
listNCM = []
r = 0
while (r <len (plistaTEC)):
line = plistaTEC [r]
if (len (line) <12):
i = line.find (".")
if ((i> = 2) and (line [0] .isnumeric ())):
r = r + 1
line2 = plistaTEC [r]
if (not line2 == "\ n"): # Eliminates number sequences (in part 5 TEC Taxation Rule for Products of the Aeronautical Sector)
if (not line2 [0] .isnumeric ()): # First test if line is not empty
ncm = line
description = line2
line3 = plistaTEC [r + 1]
tec = ""
if ((not line3) or (line3 [0] .isnumeric ())):
r = r + 1
tec = row3
listNC.append ([ncm.strip (), description.strip (), tec.strip ()])
r = r + 1
return listNCM*
最后,也是最重要的部分。汇集我们的“文档”,一个包含分类“可用”位置代码(第二列非零)的单词和字母(字符串)列表,以及整个层次结构的描述
*def montaTECResumo (plistaNCM): # Mounts TEC lines containing II with description containing concatenation of line description and "parents" - positions, subheadings, etc.
listTECResumo = []
r = 0
while (r <len (plistaNCM)):
line = plistaNCM [r]
II = line [2]
if (not II == ''): # Is a valid / "selectable" Classification, search for "parents"
code = line [0]
description = line [1]
s = r-1
while (True): #Loop DNA. Browse the "up" list by looking for the family tree ...
line = plistaNCM [s]
code2 = line [0]
description = line [1]
lcodigo = code [0: 2] + "." + code [2: 4]
if (lcode == code2):
description = description + "" + descricao2
listTECResumo.append (code + "" + description)
break
lcodigo = code [0: 6]
if (lcode == code2):
description = description + "" + descricao2
lcodigo = code [0: 7]
if (lcode == code2):
description = description + "" + descricao2
lcodigo = code [0: 8]
if (lcode == code2):
description = description + "" + descricao2
lcodigo = code [0: 9]
if (lcode == code2):
description = description + "" + descricao2
s = s - 1
if ((s == - 1) or ((rs)> 100)): # Exception found, abort!
listTECResumo.append (code + "" + description)
break
r = r + 1
return listTECResumo*
我们在这里已经编纂得够多了。所以,说好的编程实践已经过时了,可以写一些自动化测试,或者至少查看我们的结果。我们来做个小预告:
*def Display ():
listTEC = montaTEC ()
print ("RAW File")
print (TEC list [0:19])
print (TEC list [5001: 5020])listCapitulos = montaCapitulos (listTEC)
print ("Chapterlist")
print (ListCapitulos [1])
print (ListCapitulos [50])listNCM = montaNCM (listTEC)
print ("listNCM")
for line in listNCM [0: 9]:
print (line)
for line in listNCM [1001: 1010]:
print (line)print ("Assembling documents ...")
listTECResumo = montaTECResumo (listNCM)
print ("Total documents in collection:")
print (len (listTECResumo))
print ("First lines:")
for line in listTECResumo [0: 9]:
print (line)
print ("Some random lines:")
from random import randint
for i in range (1.10):
print (listTECResumo [randint (0, len (listTECResumo))])View ()(I.e.
======= RESTART: D: \ Users \ Brazil \ Downloads \ Sorts \ ncmutils.py =======
RAW file
\ n ',' \ n ',' \ n ',' \ n ',' \ n ',' \ n ' COMMON FOREIGN TARIFF (TEC) \ n ',' \ n ',' \ n ',' \ n ',' \ n ',' 'BRASIL \ n', '2 0 1 7 \ n']
\ N ', '10 \ n', '1003.90.80 \ n', '1003.90.10 \ n', 'Other \ n', \ n ',' , in grain \ n ', '10 \ n', '1003.90.90 \ n', 'Other \ n', '10 \ n ',' \ n ',' \ n ',' \ n ', '10 .04 \ n ',' \ n ',' 1004.10.00 \ n ']
listCapitulos
('Chapter 2', 'Meat and edible meat offal', '1 This chapter does not cover: \ n \ na) \ tFor items 02.01 to 02.08 and 02.10, products unfit for human consumption; \ n \ nb) \ tThe animal fats, bladders and stomachs (heading 05.04) or animal blood (headings 05.11 or 30.02); \ n \ nc) \ t Animal fat, excluding products of heading 02.09 (Chapter 15 ). \ n \ n ']
'For the purposes of subheadings 5209.42 and 5211.42, the expression "Denim fabrics" means woven fabrics of yarns of different colors, with a twill not exceeding 4, comprising broken twill (sometimes referred to as satin 4), with warp on the right side, the warp yarns having the same single color and those of the weft, whitened or dyed gray or a lighter shade than of the warp threads. \ n \ n ']
CNM list
['01 .01 ',' Live horses, crabs and mules']
['0101.2', '- \ tHawks:', '']
['0101.21.00', - 'Pure-bred breeding animals', '0']
['0101.29.00', '- \ tOutros', '2']
['0101.30.00', '- \' Asinos', '4']
['0101.90.00', '- \ tOutros', '4']
['01 .02 ',' Live bovine animals', '']
['0102.2', - 'Domestic animals:', '']
['0102.21', - 'Pure-bred breeding animals', '']
['0903.00.10', 'Simply shackled', '10']
['0903.00.90', 'Other', '10']
['09 .04 ',' Pepper of the genus Piper; chilies and peppers of the genus Capsicum or of the genus Pimenta, dried or crushed or ground.],
['0904.1', '- \ Pepper of the genus Piper:', '']
['0904.11.00', '- \ tNot crushed or powdered', '10']
['0904.12.00', '-' or powdered ',' 10 ']
['0904.2', - - Peppers and peppers (Capsicums of the genus Capsicum or of the genus Pimenta: ',' ']
['0904.21.00', - - - - - - - - - - - - - - - - - - - - - - -
['0904.22.00', '-' or 'powdered', '10']
Assembling documents ...
Total documents in collection:
10147
First lines:
0101.21.00 - Pure-bred breeding animals - Horses: Live horses and cousins.
0101.29.00 - Other - Horses: Live horses and asses, mules and hinnies.
0101.30.00 - Asinines Horses, sharks and mules, live.
0101.90.00 - Other Live horses and asses, mules and hinnies.
0102.21.10 Pregnant or bred breeding animals - Pure-bred breeding animals - Domestic bovine animals: Live bovine animals.
0102.21.90 Other - Pure-bred breeding animals - Domestic bovine animals: Live bovine animals.
0102.29.11 Breeding or breeding on foot For breeding - Other - Domestic bovine animals: Live bovine animals.
0102.29.19 Other For breeding - Other - Domestic bovine animals: Live bovine animals.
0102.29.90 Other - Other - Domestic bovine animals: Live bovine animals.
Some Random Rows:
5112.19.20 Of fine hairs - Other - Containing 85% or more by weight of wool or fine animal hair: Woven fabrics of combed wool or of fine animal hair.
5403.41.00 - Of viscose rayon - Other multiple or cabled yarn: Artificial filament yarn (other than sewing thread), not put up for retail sale, including artificial monofilament of less than 67 decitex.
5102.11.00 - Of Kashmir goat - Fine hair: fine or coarse animal hair, not carded or combed.
4107.92.10 Of bovine animals (including buffaloes) - Divided with the blossom side - Other, including strips: Leather further prepared after tanning or crusting and parchment-dressed leather, of bovine (including buffalo) or of equine, without hair on, whether or not split, other than leather of heading 41.14\.
2916.20.90 Cyclanic, cyclenic or cycloterpenic monocarboxylic acids, their anhydrides, halides, peroxides, peroxyacids and their derivatives, unsaturated acyclic monocarboxylic acids and cyclic monocarboxylic acids, their anhydrides, halides, peroxides and peroxyacids; their halogenated, sulphonated, nitrated or nitrosated derivatives.
5204.11.31 Of two ropes Of bleached or colored cotton yarn of a size not exceeding 5,000 decitex per single yarn - Containing 85% or more by weight of cotton - Not put up for retail sale: whether or not put up for retail sale:
8704.32.90 Other - Of a maximum permissible gross weight exceeding 5 tonnes - Other, with spark-ignition internal combustion piston engine (spark) *: Motor vehicles for the transport of goods.
5206.24.00 - Of a denomination less than 192,31 decitex but not less than 125 decitex (metric number exceeding 52 but not exceeding 80) - Single yarn of combed fibers: Cotton yarn (other than sewing thread) containing less than 85% by weight of cotton, not put up for retail sale.
8467.99.00 - Other - Parts: Tools, pneumatic, hydraulic or with self-contained electric or nonelectric motor,*
到目前为止,似乎一切都在按预期运行。理想的情况是,通过创建一个具有自动化测试的对象或函数,将一些样本行中人工生成的“基本事实”结果与我们的脚本生成的结果进行比较,来进一步完善这个测试。或者至少在更随机的位置浏览,并将它们与原始文件进行比较。
现在让我们组装向量。到目前为止,我们还没有处理文本中的单词,我们保留了与原始文本相同的内容,以供用户查看。既然“用户”将是计算机(在合计和排名中),我们必须记住,“章”、“章”、“章”、“章”和“章”对于计算机是不同的词。所以首先,在我们开始查找和比较单词之前,我们需要创建函数来“清理”特殊字符、标点符号等。并以最简单的方式对文本进行编码,以提高性能并避免意外。
*import re
from unicodedata import normalizedef remove_action (txt):
return normalize ('NFKD', txt) .encode ('ASCII', 'ignore'). decode ('ASCII')def only_read_and_numbers (raw):
raw = remove_acentos (raw)
clean = re.sub ("[^ a-zA-Z0-9]", "", raw)
return clean*
下一步,我们组装我们的词汇表,也就是说,搜索单词并只添加一次到我们的列表中。在这一步中,我们不仅仅是使用上述函数标准化单词,而是将所有字符都大写,去掉停用词* 和所有最多包含两个字符的单词。我们将利用 NLTK 库中的停用词*。*
*停用词
(停用词)是简单的日常词汇,在搜索引擎索引过程中没有相关性。在元标签中使用这些词可能会产生负面影响,降低关键字的密度。
HTP://www . seopedia . com . br/dicionario-SEO/let ra-s/
要开始使用 NLTK,除了安装库之外,还需要通过在 Python 提示符下键入来下载数据库。然后,在界面中,选择“Forest”和“Stopwords”包。如果没有安装 NLTK 库,通常只需在命令提示符下键入 pip install nltk。
***>>> import** **nltk**
**>>>** nltk.download ()*
现在让我们使用 Python 字典来构建我们的词汇表:
*import nltk
stopwords = nltk.corpus.stopwords.words ('portuguese')def montaDictVocabulario (plistaTEC):
vocab = {} # Traverses all NCM COM subitems with full description. Create vocabulary through this full description
index = 0
for line in (plistaTEC):
code = line [: 10]
description = line [11:]
list of words = description.split ()
for word in lists of words:
if ((len (word)> 2) and (stopwords.count (word) == 0)):
word = only_letras_e_numeros (word) # Take anything other than AB and 0-9
word = word.upper ()
if word not in vocab:
vocab [word] = index
index + = 1
return vocab*
接下来,字数统计向量的组装。让我们使用 numPy 库,它在阵列的组装和操作方面提供了高性能、灵活性和易用性:
*import numpy as np
# Scroll through all NCM COM subitems with full description. Create a vector dict for each TEC item. Create a vocabulary vector first
def montaVetores (plistaTEC, pvocab):
vectorVocab = np.zeros (len (pvocab), dtype = np.int16)
vectorsTEC = {}
for line in (plistaTEC):
code = line [: 10]
description = line [11:]
list of words = description.split ()
tecvector = np.zeros (len (pvocab), dtype = np.int16)
for word in lists of words:
word = only_letras_e_numeros (word) # Take anything other than AB and 0-9
word = word.upper ()
if word in pvocab:
index = pvocab [word]
tecvector [index] + = 1
vectorVocab [index] + = 1
vectorsTEC [code] = tecvector
return vectorsTEC, vectorVocab*
准备好了。我们的向量已经组装好了(这比看起来容易),我们有了一个词汇表,现在我们可以练习一下“了解你的数据”。所以我们来摘录一些统计数据。在函数视图()中添加一些行怎么样?
*print ("Mounting vectors ...")
vectorsTEC, vectorVocab = montaVetores (listTECResumo, vocab)
print ("Vocabulary Vector:")
print (vectorVocab.shape)
print ("Document Vector:")
print (len (TECs))
>>>
Assembling vocabulary ...
Total TEC Vocabulary words:
12787
Riding vectors ...
Vocabulary vector:
(12787)
Vector of documents:
10147*
所以我们在词汇表中总共有 12,787 个单词(唯一的),分为 10,147 行,可以用于税收分类。这是因为我们消除了停用词、标点符号、双字、方框等。对一个人来说,这当然是很多信息了。
让我们来看一些更有趣的统计数据:
*allwordsTEC = str (listTEC)
list of allTEC.split ()
print ("TEC word totals")
print (len (allTextText)) allwordsTECResum = str (listTECResumo)
list of all wordsTECResumo = allwordsTECResumo.split ()
print ("Total words from TEC's NCM lines with complete description (Collection of documents):")
print (len (allTextRecords)) print ("Mean of words per line (Collection of documents):")
print (len (listofTextRecords) / len (listTECResumo))print ("Number of documents in the collection:")
print (len (TECs))print ("Statistics of occurrences of words in vocabulary:")
format (vectorVocab.mean (), vectorVocab.min (), vectorVocab.max ())
>>>
Total TEC words:
170019
Total words from TEC's NCM lines with complete description (Collection of documents):
353167
Average words per line (Collection of documents):
34.80506553661181
Number of documents in the collection:
10147
Statistics of occurrences of words in vocabulary:
Average 18.51848900223143, min 1, max 8124*
好了,现在是时候创建您的浏览器,在单词搜索中排列这些行了:
*def pointerVector (ptexto, pvocab, pvetoresTEC, vectorVocab, weighted = False):
### For efficiency, select only the columns with words that occur in the search
## Therefore, first convert the TEC vectors list into a Dimension Matrix
## number ofTECs x size of the Vocabulary
After ## create an array of summing values query vocabulary columns
matrizVetores = np.asarray (list (pvetoresTEC.values ()), DTYPE = np.int16)
matrizCodigos = np.asarray (list (pvetoresTEC.keys ()) )
matrizSoma np.zeros = (len (pvetoresTEC))
wordlist = ptexto.split ()
explanation = ""
for word in wordlist:
word = somente_letras_e_numeros (word) # Strip everything is not AB and 0-9
word = palavra.upper ()
if the word in pvocab:
index = pvocab [word]
vector matrizVetores = [index :,]
explanation = explanation word + + '' + str (vetorVocab [index]) + '
matrizSoma = np.add (matrizSoma, vector)
indicesnaozero = np.nonzero (matrizSoma)
matrizTemp np.vstack = ((matrizCodigos [indicesnaozero] matrizSoma [indicesnaozero]))
. indices matrizTemp = [1:] argsort ()
indices indices = [:: - 1]
matrizCodigoePontuacao = matrizTemp [:, indices]
return matrizCodigoePontuacao, explanation*
最后,创建一个例程来测试搜索引擎:
*test = "T"
while (test = ""):
test = input ( "Enter a product-description words Enter simply Enter to end:.")
matrizPontos explains = pontuaVetores (test, vocab, vetoresTEC, vetorVocab)
print (explains)
ind = 5
if (ind> matrizPontos.shape [1]):
ind = matrizPontos.shape [1]
print ( "plus 5")
is in code (matrizPontos [0: ind]): it
is in line (listaTECResumo):
codigo2 = line [10]
if (code == codigo2):
print (line)>>>>>
Enter a product-describing words. Type simply enter to terminate: other tissues
OTHER TISSUES 8124 569
5 plus:
8517.62.79 Other Other emitting devices with embedded Digital Receiver - Machines for the reception, conversion, emission and transmission or regeneration of voice, images or other data, including switching and routing (forwarding *) - Other apparatus for transmission, transmission or reception of voice, images or other data, including apparatus for communication in networks wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN)): telephone sets including telephones for cellular networks or for other wireless networks; other devices for emission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN ))except devices
8517.62.93 Other personal receivers radio message Other - Machines for the reception, conversion, emission and transmission or regeneration of voice, images or other data, including switching and routing (forwarding *) - Other apparatus for transmission, transmission or reception voice, images or other data, including apparatus for communication in networks wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN)): telephone sets, including telephones for cellular networks or for other wireless networks; other devices for emission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN )), excluding devices
8517.62.59 Other apparatus for transmission or reception of voice, images or other data in wired network - Machines for the reception, conversion, emission and transmission or regeneration of voice, images or other data, including switching and routing (forwarding *) - other apparatus for transmission, transmission or reception of voice, images or other data, including apparatus for communication in networks wired or wireless network (such as a local area network (LAN) or wide area network (extended * ) (WAN)): telephone sets, including telephones for cellular networks or for other wireless networks; other devices for emission, transmission or reception of voice, images or other data,including apparatus for communication networks in a wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN)), excluding devices
8517.62.99 Other Other - Machines for the reception, conversion, emission and transmission or regeneration of voice, images or other data, including switching and routing (forwarding *) - Other apparatus for transmission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN)): telephone sets, including telephones for cellular networks and for other wireless networks; other devices for emission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN )), excluding devices
Other 8517.62.39 Other apparatus for switching - Machines for the reception, conversion, emission and transmission or regeneration of voice, images or other data, including switching and routing (forwarding *) - Other apparatus for transmission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN)): telephone sets, including telephones for cellular networks or for other wireless networks; other devices for emission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN )), excluding devices
Enter a product-describing words. Type simply enter to terminate: patterned knitted fabrics
WOVEN FABRIC 569 54 31 STAMPING
5 plus:
5407.10.19 Other rubber thread No - fabrics woven from high tenacity yarn of nylon or other polyamides or polyester yarn fabrics of synthetic filaments, including tissues obtained from the products of heading 5404\.
6001.21.00 - Cotton - rings fabrics: Pile fabrics (including woven fabrics called "long pile" or "the long") and tissue rings mesh.
5407.20.00 - Woven fabrics obtained from strip or the like Woven fabrics of synthetic filament yarn, including woven fabrics obtained from the products of heading 5404.
5407.30.00 - "Fabrics" mentioned in Note 9 Section XI Woven fabrics of synthetic filament yarn, including woven fabrics obtained from the products of heading 5404\.
5407.74.00 - Printed - Other fabrics containing at least 85% by weight of synthetic filament fabrics of synthetic filament yarn, including woven fabrics obtained from the products of heading 5404\.
Enter a product-describing words. Type simply enter to terminate: knitted polyester synthetic fiber fabrics printed
WOVEN FABRIC 569 839 SYNTHETIC FIBERS 54 281 74 polyester STAMPING 31
5 plus:
9001.10.20 beams and optical fiber cables - Optical fibers, bundles of cables and optical fibers Optical fibers and optical fiber bundles; optical fiber cables other than those of heading 85.44; polarizing material in sheets and plates; lenses (including contact lenses), prisms, mirrors and other optical elements, of any material, unmounted, other than glass not optically worked.
Other optical fibers 9001.10.19 - optical fibers, bundles of cables and optical fibers Optical fibers and optical fiber bundles; optical fiber cables other than those of heading 85.44; polarizing material in sheets and plates; lenses (including contact lenses), prisms, mirrors and other optical elements, of any material, unmounted, other than glass not optically worked.
9001.10.11 core diameter less than 11 micrometers (microns) Fiber Optics - Optical fibers, bundles of cables and optical fibers Optical fibers and optical fiber bundles; optical fiber cables other than those of heading 85.44; polarizing material in sheets and plates; lenses (including contact lenses), prisms, mirrors and other optical elements, of any material, unmounted, other than glass not optically worked.
5511.10.00 - synthetic staple fibers, containing at least 85% by weight of such fibers yarns of synthetic or artificial staple fibers (excluding sewing thread), packaged for retail sale.
6001.22.00 - Of man-made fibers - rings fabrics: Pile fabrics (including woven fabrics called "long pile" or "the long") and tissue rings mesh.
Enter a product-describing words. Enter simply Enter to end:*
嗯,上面你可以看到我们已经有一个搜索引擎。第一次搜索与我们想要的相差甚远。第二个变好了,第三个好了一点,以此类推。当我们使用搜索引擎时,我们总是不得不“精炼”搜索,并且,迭代地,我们更接近我们想要的。理解精致的关键在于其他 8124 面料 569 系列。这意味着“其他”一词在我们的系列和面料 569 中出现了 8124 次。在上一次调查中,我们进行了以下计数:织物 569 MALHA 54 纤维 839 合成纤维 281 聚酯 74 冲压 31
我们可以看到,有“非常常见”的词,“常见”的词,“不常见”的词和“罕见”的词。例如,扑热息痛只出现了 3 次。因此,单词“STAMPED”在一行中的出现应该比单词“FIBERS”在排名中计算更多的分数。因此,如果我们寻找衣服或织物,我们不会在第一个结果之间显示光纤。
现在,为了更好地解决问题,让我们调整与用户的交互方式,只搜索字数并进行一些查询:
*teste = "T"
while (teste!=""):
teste = input("Digite umas palavras-descrição de produto para ver suas ocorrências. Digite simplemente Enter para encerrar:")
matrizPontos, explica = pontuaVetores(teste, vocab, vetoresTEC, vetorVocab)
print(explica)
>>>>>
Digite umas palavras-descrição de produto para ver suas ocorrências. Digite simplemente Enter para encerrar:outros outras outro estampado estampados tintos tinto poliester poliesteres
OUTROS 8124 OUTRAS 3266 OUTRO 468 ESTAMPADOS 31 TINTOS 35 POLIESTER 33 POLIESTERES 74From the above results, we see that "OTHERS" is a super-frequent word, followed by "OTHERS". Already "STAMPED" occurs only 31 times, and "STAMPED" none. Already "POLYESTER" 33 AND "POLYESTERS" 74 times. To treat different versions of the same word as one, we will discuss the techniques below.
The solution to better score rankings is in a concept called TF-IDF. In a very short explanation, TF-IDF proposes to punctuate repetition in a document, and penalize repetition in the collection (most common word is worth less, rare is worth more).
Thus, we need to modify our score vector, which today contains only the word count, in a vector with the TF-IDF values. For this, in Python, we have the IDFTransformer package from the sklearn library:*
从上面的结果我们看到“别人”是一个超高频词,其次是“别人”。已经“盖章”只出现了 31 次,而“盖章”一次也没有。已经是“聚酯”33 和“聚酯”74 倍了。为了将同一个单词的不同版本视为一个,我们将在下面讨论这些技术。
更好的分数排名的解决方案在一个叫做 TF-IDF 的概念中。在一个非常简短的解释中,TF-IDF 建议对文档中的重复进行标点,并惩罚集合中的重复(最常见的词价值更低,罕见的词价值更高)。
因此,我们需要用 TF-IDF 值修改我们的得分向量,它现在只包含单词计数。为此,在 Python 中,我们有来自 sklearn 库的 IDFTransformer 包:
* [## sk learn . feature _ extraction . text . tfidftransformer-sci kit-learn 0 . 18 . 1 文档
使用 tf-idf 代替给定文档中某个标记的原始出现频率的目的是缩小…
scikit-learn.org](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfTransformer.html&usg=ALkJrhhAF1WN325_6Mv1Ye5Kq-UGYXj0uQ)
让我们看看 TfidfTransfomer 对向量的影响:
from sklearn.feature_extraction.text import TfidfTransformer
transformer = TfidfTransformer()
matrizVetores = np.asarray(list(vetoresTEC.values()), dtype=np.int16)
tfidf = transformer.fit_transform(matrizVetores)
matriz_tfidf = tfidf.toarray()print (matrizVetores [1:10])
print (matriz_tfidf [1:10])
>>>>
[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...,
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[1 1 1 ... 0 0 0]]
[[... 0\. 0\. 0\. 0\. 0\. 0.]
[... 0\. 0\. 0\. 0\. 0\. 0]
[0 ... 0 0., 0\. 0\. 0]
...,
[... 0\. 0\. 0\. 0\. 0\. 0.]
[... 0\. 0\. 0\. 0\. 0\. 0.]
[0.3453688 0.3453688 0.33742073\. .. 0\. 0\. 0.]]
为了比较结果,我们将创建一个稍加修改的评分函数(变化以粗体显示):
def pontuaVetores_tfidf (ptexto, pvocab, pvetoresTEC, vetorVocab = False weighted):
### For efficiency, select only the columns with words that occur in the search
## Therefore, first convert the TEC vectors list in a dimension Matrix
## númerodeTECs tamanhodoVocabulario x
## then create an array by adding the values of the query vocabulary columns
matrizVetores = np.asarray (list (pvetoresTEC.values ()), DTYPE = np.int16)
**from sklearn.feature_extraction.text import TfidfTransformer
transformer TfidfTransformer = ()
tfidf = transformer.fit_transform (matrizVetores)
matriz_tfidf = tfidf.toarray ()**
matrizCodigos = np.asarray (list (pvetoresTEC.keys ()))
matrizSoma np.zeros = (len (pvetoresTEC))
wordlist = ptexto.split ()
explanation = ""
for word in wordlist:
word = somente_letras_e_numeros (word) # Strip everything is not AB and 0-9
word palavra.upper = ( )
if the word in pvocab:
index = pvocab [word]
vector = **matriz_tfidf** [:, index]
explanation = explanation word + + '' + str (vetorVocab [index]) + '
matrizSoma = np.add (matrizSoma, vector)
indicesnaozero = np.nonzero (matrizSoma)
matrizTemp np.vstack = ((matrizCodigos [indicesnaozero] matrizSoma [indicesnaozero]))
. indices matrizTemp = [1:] argsort ()
indices indices = [:: - 1]
matrizCodigoePontuacao = matrizTemp [:, indices]
return matrizCodigoePontuacao, explanation
最后,我们通过重复上一次测试来查看结果,并列出超出 TEC 线的分数。看看下面的列表,你会发现结果有了很大的改善。“光纤”从第一个位置列表中消失了,它只是与我们所寻求的不太一致。此外,我们注意到“光纤”和下面的项目得分相同,所以排名实际上是随机的。
teste="tecidos de malha fibras sinteticas poliesteres estampados"
matrizPontos, explica = pontuaVetores(teste, vocab, vetoresTEC, vetorVocab)
print(explica)
ind = 5
if (ind > matrizPontos.shape[1]):
ind = matrizPontos.shape[1]
print("5 mais:")
for codigo in (matrizPontos[0, :ind]):
for linha in (listaTECResumo):
codigo2 = linha[:10]
if(codigo2==codigo):
print(matrizPontos[1, :ind])
print(linha)
>>>
TECIDOS 569 MALHA 54 FIBRAS 839 SINTETICAS 281 POLIESTERES 74 ESTAMPADOS 31
5 mais:
**['6.0' '6.0' '6.0' '5.0' '5.0']**
9001.10.20 Feixes e cabos de fibras ópticas - Fibras ópticas, feixes e cabos de fibras ópticas Fibras ópticas e feixes de fibras ópticas; cabos de fibras ópticas, exceto os da posição 85.44; matérias polarizantes em folhas ou em placas; lentes (incluindo as de contato), prismas, espelhos e outros elementos de óptica, de qualquer matéria, não montados, exceto os de vidro não trabalhado opticamente.
**['6.0' '6.0' '6.0' '5.0' '5.0']**
9001.10.19 Outras Fibras ópticas - Fibras ópticas, feixes e cabos de fibras ópticas Fibras ópticas e feixes de fibras ópticas; cabos de fibras ópticas, exceto os da posição 85.44; matérias polarizantes em folhas ou em placas; lentes (incluindo as de contato), prismas, espelhos e outros elementos de óptica, de qualquer matéria, não montados, exceto os de vidro não trabalhado opticamente.
**['6.0' '6.0' '6.0' '5.0' '5.0']**
9001.10.11 De diâmetro de núcleo inferior a 11 micrômetros (mícrons) Fibras ópticas - Fibras ópticas, feixes e cabos de fibras ópticas Fibras ópticas e feixes de fibras ópticas; cabos de fibras ópticas, exceto os da posição 85.44; matérias polarizantes em folhas ou em placas; lentes (incluindo as de contato), prismas, espelhos e outros elementos de óptica, de qualquer matéria, não montados, exceto os de vidro não trabalhado opticamente.
**['6.0' '6.0' '6.0' '5.0' '5.0']**
5511.10.00 - De fibras sintéticas descontínuas, que contenham pelo menos 85 %, em peso, destas fibras Fios de fibras sintéticas ou artificiais, descontínuas (exceto linhas para costurar), acondicionados para venda a retalho.
**['6.0' '6.0' '6.0' '5.0' '5.0']**
6001.22.00 -- De fibras sintéticas ou artificiais - Tecidos de anéis: Veludos e pelúcias (incluindo os tecidos denominados de “felpa longa” ou “pelo comprido”) e tecidos de anéis, de malha.test = "synthetic fiber fabrics knitted polyester patterned"
matrizPontos explains = pontuaVetores **_tfidf** (test vocab, vetoresTEC, vetorVocab)
print (explains)
ind = 5
if (ind> matrizPontos.shape [1]):
ind = matrizPontos.shape [1]
print ( "plus 5")
is in code (matrizPontos [0: ind]):
for line in (listaTECResumo):
codigo2 = line [10]
if (code == codigo2):
print (matrizPontos [ 1: ind])
print (line)
>>>>
WOVEN FABRIC 569 839 sYNTHETIC FIBERS 54 281 74 polyester STAMPING 31
5 plus:
**[ '1.5540693500933536' 1.2670506868422255 '1.2275553770539624'
"1.2042355691237416 '1.1558503446987298']**
6006.34.20 Of polyesters - Printed - Of synthetic fibers: Other knitted fabrics.
**[ '1.5540693500933536' 1.2670506868422255 '1.2275553770539624'
'1.2042355691237416' 1.1558503446987298 ']**
6006.44.00 - Printed - of artificial fibers: Other knitted fabrics.
**[ '1.5540693500933536' 1.2670506868422255 '1.2275553770539624'
'1.2042355691237416' 1.1558503446987298 ']**
5516.94.00 - Printed - Other: Woven fabrics of staple fibers.
**[ '1.5540693500933536' '1.2670506868422255' '1.2275553770539624'
'1.2042355691237416' '1.1558503446987298'**
] 6006.34.90 Other - Printed - Of synthetic fibers: Other knitted fabrics.
**[ '1.5540693500933536' 1.2670506868422255 '1.2275553770539624'
'1.2042355691237416' 1.1558503446987298 ']**
6003.30.00 - of synthetic fiber mesh fabrics width not exceeding 30 cm, excluding the positions 6001 and 6002.
这个算法的一个版本在我们的测试中表现出了更好的性能,Okapi BM25 +(更重要的[+]是由于我们收集的文档中单词数量之间的高度差异)。它是一个插值参数,用于减少短文档的惩罚。此外,让“b”参数默认 BM25 为 60%,而不是标准的 75%。“b”是一个线性插值参数,也有助于减轻短文档的损失。使用各种参数和超和最小化/消除实现的公式绘制排名。
要了解更多关于 TF-IDF 和 BM25 的信息,维基百科中有很棒的文章:
[## Tf-idf —维基百科,免费的百科全书
tf-idf 值(英文术语 frequency-inverse document frequency 的缩写,表示术语的频率…
pt.wikipedia.org](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://pt.wikipedia.org/wiki/Tf%25E2%2580%2593idf&usg=ALkJrhilUYhP0Th-U_nKHMpwAygLVtVFmA) [## Okapi BM25 —维基百科
在信息检索中,Okapi BM25 (BM 代表最佳匹配)是搜索引擎用来对搜索结果进行排序的排序函数
en.wikipedia.org](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://en.wikipedia.org/wiki/Okapi_BM25&usg=ALkJrhiBE-wbonyiPhC5mG9u8LNfazTniQ)
另一个有趣的解决方案是将相似的单词分组,处理复数,同一个单词的各种变体,等等:(other,Other,Another,stamped,embossed,printed,red,涤纶,涤纶…)。我们将尝试先从你的偏旁部首开始,而不是从词汇表中的整个单词开始。转换单词和减少变化的技术称为词汇化和词干化。我们可以把搜索词典想象成使用同义词词典,进一步缩小我们的词汇量。词干分析应用于系统的 Java 版本,dicionarizada 搜索将在不久的将来实现。
GitHub 上有一个 IPython 笔记本,用于使用 Python 测试词干和词尾。在伦敦可以买到葡萄牙斯特梅尔。
[## 茎干工
词干分析器从单词中去掉词缀,只留下单词词干。
www.nltk.org](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=http://www.nltk.org/howto/stem.html&usg=ALkJrhjepmqIkzhOYdSVPAU3PLOBiEAUjQ)
from nltk.stem import *
stemmer = SnowballStemmer("portuguese")
palavras = ['TECIDOS', 'TECIDO', 'FIBRAS', 'FIBRA', 'SINTETICO', 'SINTETICA', 'OUTROS', 'OUTRAS', 'OUTRA']
stems = [stemmer.stem(palavra) for palavra in palavras]
print(' '.join(stems))
lista = list (set(stems))
print(lista)
>>>>
tec tec fibr fibr sintet sintet outr outr outr
['fibr', 'tec', 'sintet', 'outr']
完成剧本并展示给观众看
[## IvanBrasilico/classicadorfiscal
分类或分类——这是一个 JAVA 系统,它利用了商业和加工方面的技术
github.com](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://github.com/IvanBrasilico/ClassificadorFiscal/blob/master/RanqueadorTEC.ipynb&usg=ALkJrhjn7E7rINwFizeFFoGK2c4HNpa0Bw)
为了继续开发这项工作并实现这些解决方案,Python 无疑是目前可用的最佳解决方案之一。然而,由于在我的工作中,Python 不是一种被广泛采用的开发语言,并且我目前参与了一个大型 Java 项目,甚至这个财政分类器也是该项目的一部分,因此从这一刻起,我将 Python 中的初始代码转换为 Java + Swing。有必要做一些调整,因为最初的版本使用了超过 1GB 的内存,我必须考虑一些优化,将内存的使用降低到 300MB 以下。代码变大了,性能稍微降低了,但是 Java 平台也有一些功能,特别是在界面设计方面,最终变得有用。
完整的代码(Java 和 Python 都有)在我的 GitHubhttps://github.com/IvanBrasilico/中
Java 版本已经实现了 BM25 +,参数调整、词干、二元模型以及其他改进。我打算在本文的第 4 部分尽快描述它们,并以 Python 版本实现它们。
第三部分
A nd sta 部分是使用 Java 实现系统的简要手册,可在 GitHub 上获得。
IvanBrasilico 有一个可用的存储库。在 GitHub 上关注他们的代码。
github.com](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://github.com/IvanBrasilico/&usg=ALkJrhhEt-hgkfDQjzz3RnBXL6QeoO-2Ew)
该系统使用搜索技术和处理文本来获得概率分数。
该系统完全嵌入运行,完全可以在任何安装了 Java 的计算机上使用,而无需访问网络。
它被并入 MDIC 出版的最后一个 TEC 的全文系统文件中。当加载时,系统执行一些预处理,即使用人工智能技术和语言处理(矢量化单词、TF-IDF、词干、二元模型等)来处理 TEC 的所有文本,并将其以各种结构化形式安装。
该系统提供了七个选项卡用于研究。下面分别介绍。
NCM 完整选项卡
显示未经预处理的原始 TEC 文本。
按钮“搜索文本” —按单词或部分单词搜索或滚动文本。重要的是要记住这个标签搜索是准确的,区分大小写和图形符号(例如:acentos)即“章”、“章”、“章”、“章”是不同的搜索。在 TEC 中拼写为“章”。
(这是加载后唯一可以立即使用的选项卡。另一个选项卡必须等待预处理结束,这可能需要 1 到 2 分钟,具体取决于所用的计算机)
NCM 搜索标签
显示 TEC 本身,分层显示,只有子标题的文本和代码,以及最终分类和进口关税配额。
按钮【搜索代码】-按代码或部分代码搜索。
章节选项卡
显示 TEC 的章节列表。在列表中选择一个章节,显示您的注释
建议选项卡
这个选项卡是真正使用算法“智能”的地方。TEC 将 sub 显示为“完整的”文本,即添加到所有高级位置的 sub 文本。此外,该子项的单词根据在文本中出现的次数对匹配搜索文本的单词进行评分。结果按分数排序,从最高到最低。
位置反馈
该选项卡与 anterir 相同,但显示子项的位置
按钮“搜索点” —搜索单词、点,并在“建议”选项卡中显示结果。
参数:
使用加权权重 TF / IDF (S / N)
而不是简单地对 TEC 行中的搜索词的出现次数进行计数,考虑“权重”对 TEC 中出现频率较低的词进行更多评分,并且还考虑每行中一个词的相对权重。
纯文本(S / N)
只查找输入的单词。对方框和图形符号不敏感。
词干(信噪比)
搜索字根。压印线匝 Estamp,红色线匝 TINT。
Bigrams (S / N)
只是寻找输入的单词。对方框和图形符号不敏感。按照输入的顺序,成对查找单词。“其他织物”、“薄纸”、“网布”等。
解释选项卡
显示搜索词和一些统计数据。它让你知道键入的单词是否在 TEC 中找到,以及找到的频率。适合细化和研究修正。例如,如果搜索“Tylenol”,该选项卡将不会显示统计数据,因为该词在 TEC 中不存在。如果您搜索“扑热息痛”信息,则会出现“扑热息痛”。总事件数:3”。同样,搜索“浮雕”返回“盖章”。总点击量:45”。没有复数形式的" Printed "不返回任何内容。
示例屏幕
在这里,我们开始了一个简单的搜索,只输入“其他组织”并点击“搜索分数”
请注意,将鼠标指针停留在列表项上,会打开一个小窗口,其中包含该行和在搜索行中找到的每个单词以及每个单词的分数。
第二步,我们开始细化我们的搜索。请注意,单词“fabric”和“red”得分较高。
在搜索中添加“棉花”一词
在这里,我们选择“解释”选项卡来了解每个分数的原因。每个单词的分数总是与它的总出现次数成反比。
查看“位置”选项卡的结果
修改对其他类型组织的搜索:
可以用感叹号(!)这个词搜索之前。因此,这个单词的分数将变成负数,包含这个单词的行将排到列表的末尾。
下面是“NCM 完成”标签,如果有疑问,您可以在这里检索 TEC 的完整文本
“搜索 NCM”选项卡分层显示 NCM。
“章节和注释”选项卡允许您更方便快捷地查询每个章节、描述和注释
在“统计章节 NCM”选项卡中,可以看到各章节中巴西进口的原产国百分比。
以下屏幕显示了其他研究、结果、统计数据和分数,以展示使用的可能性
取自报告的复杂描述在第三个列表中显示所需的结果。注意,这个结果主要不是因为这一行,在 TEC 的“环氧树脂”中使用了“环氧树脂”和“环氧树脂”这两个词。炮泥找到了激进分子,但没有找到“树脂”和“环氧树脂”这两个词。并不总是单独解决词干问题,因此查看每行分数的系统返回并优化搜索很重要。
细化的一个例子:把“垫圈”换成“垫圈”,或者找两个术语。去掉“金属”一词,只需要塑料。
在下面的例子中,词干分析也解决了搜索问题。尝试各种组合,直到在第一行找到想要的子项,这比向下滚动几行更有趣。
第四部分
这部分讨论已经实施的技术的替代和/或补充。
Java 版本在汇编词汇表时已经实现了词干分析、二元模型和单元模型,并且在排序时提供了组合这些方法的可能性。此外,还实现了与 NCM 国家历史统计数据相结合的可能性。还应用了词库和词干来减少词汇量。
其他可能性是使用聚类,通过 k-means 或其他方法或通过层次结构,对整个章节和位置评分,例如,索引反转数据库以允许搜索单词的部分;通过 PCA 等降维,然后用回归树、SVM 或者甚至普通或递归神经网络进行排序。
就使用排名中的其他数据而言,除了原产国,NCM 还可以通过大约日期的趋势生成制造商、经济区域、运输的统计数据,而不是几年的统计数据。
所有的技术都可以与“集合”或简单地将结果相乘的方法相结合。在乘法的情况下,一个好的做法是在标准化结果之前。示例:
克服集合“listaTECResumo”中的一些文档太短这一事实的一种方法是以已经为子项目创建的相同方式为位置创建文档,并以相同方式排序。然后把位置的分数乘以每个分项的位置。为了在不考虑字数的情况下平等对待,首先将结果标题列表标准化,并细分所有得分行以获得最高得分的文档得分(因此,列表的第一个位置将是 100%,第二个位置稍低,以此类推)。)
除了新的评分可能性、产品组合和 ensenblimg 之外,您还可以创建测试示例“地面实况”,然后使用机器学习来改进参数和/或通过使用精度和召回 F-score 的评估技术、应用加权排名评估(评估方法克兰菲尔德/加权平均精度和召回)来发现已经实施的方法中的缺陷。
一旦进行了测试和改进,GitHub 上将会提供其中的一些替代方案,并在本文中进行讨论。
参考
编辑描述
dl.acm.org](http://dl.acm.org/citation.cfm?id=2915031) [## 信息检索导论—剑桥大学出版社
类测试和连贯,这本教科书教经典和网络信息检索,包括网络搜索和搜索引擎。
www.cambridge.org](http://www.cambridge.org/catalogue/catalogue.asp?isbn=0521865719) [## 学习信息检索排名|刘铁燕|斯普林格
由于网络的快速增长和查找所需信息的困难,高效和有效的…
www.springer.com](http://www.springer.com/la/book/9783642142666) [## 文本挖掘和分析| Coursera
关于本课程:本课程将涵盖挖掘和分析文本数据的主要技术,以发现…
www.coursera.org](https://www.coursera.org/learn/text-mining) [## 文本检索和搜索引擎—伊利诺伊大学香槟分校| Coursera
关于本课程:近年来,自然语言文本数据急剧增长,包括网页、新闻…
www.coursera.org](https://www.coursera.org/learn/text-retrieval/) [## 机器学习课程简介| Udacity
免费课程模式识别的乐趣和利润开始免费课程机器学习是一个一流的门票…
www.udacity.com](https://www.udacity.com/course/intro-to-machine-learning–ud120)*