TowardsDataScience-博客中文翻译-2020-七十二-

TowardsDataScience 博客中文翻译 2020(七十二)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

R 简介:线性代数

原文:https://towardsdatascience.com/intro-to-r-linear-algebra-2a4de2506c93?source=collection_archive---------8-----------------------

向量索引,特征向量求解器,奇异值分解,等等

r 是一种特别为数据分析、数据可视化和机器学习开发的非常强大的语言,这使得它成为任何有抱负的数据科学家的必学之作。

r 对线性代数尤其得心应手。它的内置数据类型(如向量和矩阵)与内置函数(如特征值和行列式解算器)和动态索引功能配合得很好。

这篇介绍 R 的文章将涵盖 R 中的以下线性代数主题实现:

向量

  • 向量分配
  • 向量运算
  • 生成序列
  • 逻辑向量
  • 缺少值
  • 索引向量

阵列和矩阵

  • 数组
  • 数组索引
  • 矩阵索引
  • 2 个数组的外积
  • 演示:2x2 个位数矩阵的所有可能的行列式
  • 数组的广义转置
  • 矩阵乘法
  • 特征值和特征向量
  • 奇异值分解和行列式
  • 最小二乘拟合和 QR 分解
  • 形成分块矩阵

向量

向量分配

r 操作数据结构,其中最简单的是数字向量。向量是有序的数字集合。要创建一个包含四个元素1234的向量x,可以使用连接函数c()

x <- c(1, 2, 3, 4)

赋值操作符<-用在这个场景中,指向被赋值的对象。在大多数情况下,<-可以与=切换。

也可以使用功能assign():

assign('x', c(1, 2, 3, 4))

运算符

也可以从另一个方向进行分配:

c(1, 2, 3, 4) -> x

向量运算

向量也可以有多种用途。

操作 y <- c(x, 0, x)会将向量1, 2, 3, 4, 0, 1, 2, 3, 4 分配给变量y

向量可以与常数自由相乘和相加:

v <- 2*x + y + 1

注意,即使xy长度不同时,该操作也有效。在这种情况下,R 将简单地循环使用 x(有时是分数),直到它满足 y 的长度。由于 y 是 9 个数字长,x 是 4 个单位长,x 将重复 2.25 次以匹配 y 的长度。

算术运算符+-*/^都可以使用。logexpsincostansqrt等等也可以。max(x)min(x)代表一个向量x的最大和最小元素,length(x)x中元素的个数。sum(x)给出x中元素的总和,而prod(x)给出它们的乘积。

mean(x)计算样本均值,var(x)返回样本方差。sort(x)返回一个向量,其大小与 x 相同,元素按升序排列。

生成序列

r 有很多生成数列的方法。1:30c(1, 2, …, 29, 30)相同。冒号作为表达式中的最高优先级,所以2*1:15将返回c(2, 4, …, 28, 30)而不是c(2, 3, …, 14, 15)

30∶1 可以用于反向生成序列。

seq()功能也可用于生成序列。seq(2,10) 返回与2:10相同的向量。在seq()中,用户还可以指定要执行的步长:seq(1,2,by=0.5)返回c(1, 1.5, 2)

类似的功能还有rep(),用各种方式复制一个对象。比如rep(x, times=5)会端到端返回x的五个副本。

逻辑向量

R 中的逻辑值有 TRUE、FALSE 和 NA。逻辑向量是由条件设定的。val <- x > 13val设置为与x长度相同的向量,条件满足时取值TRUE,条件不满足时取值FALSE

r 中的逻辑运算符有<<=>>===!=,分别表示小于、小于或等于、大于、大于或等于、等于、不等于。

缺少值

如果x的对应元素是NA,函数is.na(x)返回一个与x大小相同的逻辑向量。

x == NAis.na(x)不同,因为NA不是数值,而是不可用数量的标记。

第二种“缺失值”是由数值计算产生的,如0/0。在这种情况下,NaN(非数字)值被视为NA值;也就是说,is.na(x)将为NANaN值返回TRUEis.nan(x)只能用于识别NaN值。

索引向量

第一种索引是通过逻辑向量。y <- x[!is.na(x)]y设置为不等于NANaNx值。

(x+1)[(!is.na(x)) & x>0] -> zz设置为x+1中非NaNaN且大于 0 的值。

第二种方法是用一个正整数量的矢量。在这种情况下,这些值必须在设置{1, 2, …, length(x)}中。向量的相应元素被选择并以该顺序连接以形成结果。重要的是要记住,与其他语言不同,R 中的第一个索引是 1,而不是 0。

x[1:10]返回x的前 10 个元素,假设length(x)不小于 10。c(‘x’, ‘y’)[rep(c(1,2,2,1), times=4)]产生长度为 16 的字符向量,其中‘x’, ‘y’, ‘y’, ‘x’重复四次。

负整数向量指定要排除而不是包含的值。y <- x[-(1:5)]y设置为除了x的前五个值之外的所有值。

最后,当对象具有 names 属性来标识其组件时,可以使用字符串向量。有了水果<- c(1, 2, 3, 4),可以用names(fruit) <- c(‘mango’, ‘apple’, ‘banana’, ‘orange’)设置矢量水果的各个指标的名称。然后,可以用lunch <- fruit[c(‘apple’, ‘orange’)]按名称调用元素。

这样做的好处是字母数字名称有时比索引更容易记忆。

请注意,索引表达式也可以出现在赋值的接收端,其中只对向量的那些元素执行赋值。例如,x[is.na(x)] <- 0用值0替换向量x中的所有NANaN值。

再比如:y[y<0] <- -y[y<0]y <- abs(y)作用相同。代码只是用小于 0 的值的负值替换所有小于 0 的值。

阵列和矩阵

数组

数组是数据条目的下标集合,不一定是数字。

维度向量是非负整数的向量。如果长度是 k 那么数组就是 k 维的。尺寸从 1 到尺寸向量中给定的值进行索引。

向量可以被 R 作为数组使用,作为它的dim 属性。如果z是一个 1500 个元素的向量,赋值dim(z) <- c(100, 5, 3)将意味着z现在被视为一个 100 乘 5 乘 3 的数组。

数组索引

数组的单个元素可以通过给定数组名,后跟方括号中的下标来引用,下标由列分隔。

一个 3 乘 4 乘 6 的向量a可以通过a[1, 1, 1]调用它的第一个值,通过a[3, 4, 6]调用它的最后一个值。

a[,,]代表整个数组;因此,a[1,1,]a中取第一个二维横截面的第一行。

索引矩阵

下面的代码生成一个 4 乘 5 的数组:x <- array(1:20, dim = c(4,5))

数组由值的向量和矩阵的维数指定。首先从上到下计算值,然后从左到右计算值。

array(1:4, dim = c(2,2))会回来

1 3
2 4

而不是

1 2
3 4

索引矩阵中不允许负索引。NA和零值是允许的。

2 个数组的外积

对数组的一个重要操作是外积。如果ab是两个数值数组,那么它们的外积就是一个数组,其维数向量是由两个维数向量串联而成,其数据向量是由a的数据向量与b的数据向量的元素的所有可能乘积而成。用运算符%o%计算外积:

ab <- a %o% b

实现这一点的另一种方法是

ab <- outer(a, b, ‘*’)

事实上,任何函数都可以使用 outer()函数应用于两个数组。假设我们定义了一个函数f <- function(x, y) cos(y)/(1+x²)。该函数可以通过z <- outer(x, y, f)应用于两个向量xy

演示:2x2 个位数矩阵的所有可能的行列式

考虑 2 乘 2 矩阵的行列式[a,b;c,d]其中每个条目是从 0 到 9 的非负整数。问题是找到这种形式的所有可能矩阵的行列式,并用高密度图表示该值出现的频率。

换句话说,如果每个数字都是独立均匀随机选取的,求行列式的概率分布。

一个聪明的方法是使用 outer(0 函数两次。

d <- outer(0:9,0:9)
fr <- table(outer(d, d, ‘-’))
plot(fr, xlab = ‘Determinant’, ylab = ‘Frequency’)

第一行将 d 赋给这个矩阵:

第二行再次使用 outer()函数计算所有可能的行列式,最后一行绘制了它。

数组的广义转置

函数aperm(a, perm)可以用来排列数组 a,参数 perm 必须是整数{1,…, k 的排列,其中 ka 中下标的个数。该函数的结果是一个与 a 大小相同的数组,但是由perm[j]给出的旧维度变成了新的j-th维度。

一个简单的思考方法是矩阵转置的推广。如果A是一个矩阵,那么B就是A的转置:

B <- aperm(A, c(2, 1))

在这些特殊情况下,功能t()执行换位。

矩阵乘法

运算符%*%用于矩阵乘法。如果AB是相同大小的方阵,A*B是两个矩阵的元素乘积。A %*% B是点积(矩阵积)。

如果 x 是一个向量,那么x %*% A %*% x就是一个二次型。

crossprod()执行叉积;因此,crossprod(X, y)与操作t(X) %*% y相同,但效率更高。

diag(v),其中v是一个向量,给出一个对角矩阵,向量的元素作为对角元素。diag(M),其中m是一个矩阵,给出M的主对角线元素的向量(与 Matlab 中的约定相同)。diag(k),其中k为单个数值,通过k单位矩阵返回一个k

线性方程和反演

解线性方程组是矩阵乘法的逆运算。当...的时候

b <- A %*% x

在只给定Ab的情况下,向量x就是线性方程组的解。这可以用 R 快速解决

solve(A, b)

特征值和特征向量

函数eigen(Sm)计算对称矩阵 Sm 的特征值和特征向量。结果是一个列表,第一个元素名为 values,第二个元素名为 vectors。ev <- eigen(Sm)将该列表分配给ev

ev$valSm特征值的向量,ev$vec是对应特征向量的矩阵。

对于大型矩阵,如果使用表达式不需要计算特征向量,最好避免计算它们

evals <- eigen(Sm, only.values = TRUE)$values

奇异值分解和行列式

函数svd(m)采用任意矩阵参数m,并计算m的奇异值分解。这包括具有与m相同的列间距的标准正交列U的矩阵、其列间距是m的行间距的标准正交列V的第二矩阵以及正条目的对角矩阵D,使得

m = U %*% D %*% t(V)

det(m)可用于计算方阵的行列式m

最小二乘拟合和 QR 分解

函数lsfit()返回一个列表,给出最小二乘拟合过程的结果。像这样的任务

ans <- lsfit(X, y)

给出最小二乘拟合的结果,其中 y 是观察向量,X 是设计矩阵。

ls.diag()可用于回归诊断。

一个密切相关的函数是 qr()。

b <- qr.coef(Xplus,y)
fit <- qr.fitted(Xplus,y)
res <- qr.resid(Xplus,y)

这些计算出yfitX范围的正交投影,到res中正交补码的投影,以及b中投影的系数向量。

形成分区Matrices

矩阵可以通过函数cbind()rbind()从其他向量和矩阵中构建。

cbind()通过横向(按列)绑定矩阵形成矩阵,rbind()通过纵向(按行)绑定矩阵。

在赋值X <- cbind(arg_1, arg_2, arg_3, …)中,cbind()的参数必须是任意长度的向量,或者是具有相同列大小(相同行数)的列。

rbind()对行执行相应的操作。

感谢阅读!

我希望这篇关于 R 的介绍能够让您对 R 在线性代数中的强大功能有所了解。

强化学习导论:探索-利用困境

原文:https://towardsdatascience.com/intro-to-reinforcement-learning-the-explore-exploit-dilemma-463ceb004989?source=collection_archive---------30-----------------------

Javier Allegue Barros 在 Unsplash 上拍摄的照片

探索-利用困境

决定和困境是一枚硬币的两面。想象一个学生期待学习数据科学。他在网上搜索数据科学课程,它会返回哈佛、麻省理工、Coursera、Udemy、Udacity 等许多课程。现在,这里有一个难题:在给定所有课程/信息的情况下,他如何在初始阶段找出哪门课程最适合他?对他来说,在一个接一个地看完所有的课程大纲后决定最好的课程可能是理想的解决方案。在强化学习中,这是一种探索,人们收集信息以评估可能导致他在未来做出更好决定的情景。探索之后,他可能会决定从某个特定的课程中学习。这在强化学习中被称为利用,在强化学习中,人们可以在给定当前获得的知识或信息的情况下做出具有最高可能结果的最优决策。

勘探是一个必要的步骤,尽管这是一个劳动密集型和耗时的过程。因此,它提出了问题:我们应该探索多久?我们应该什么时候开始开发?我们应该开发多少?研究这些问题为我们提供了我们实际寻求的东西:“在探索足够多的选项的同时,确定要利用的最佳选项”。这就是强化学习中的探索-利用困境

多武装匪徒问题(MABP) 是探索-利用困境的经典例子,目标是调查一组选项中的最佳选项,然后利用所选选项。在 MABP 有多台机器(强盗),每台强盗都有不同的胜率。了解每台机器的胜率是一项挑战,因为玩多台机器需要花费金钱和时间。我们只想玩或利用有最高可能结果的机器,同时,我们应该探索所有的机器,找出胜率最高的机器。因此,出现了被称为 MABP 的探索-开发困境。

从商业到我们的日常生活活动,探索-利用困境几乎无处不在。我们应该看网飞或亚马逊上的哪部电影/电视剧——这是一个两难困境的真实例子。当我打开网飞或亚马逊 Prime 时,我通常会开始探索不同的电影/电视节目,以找到一个令人愉快的节目来观看或利用(不幸的是,我经常在长时间探索后失去了观看的兴趣!!!).另一个著名的例子是,我们应该去我们最喜欢的餐馆或尝试一个新的。

探索-剥削困境是如何解决的?

现在,我们知道了困境,下一步是——解决实际强化学习算法中的困境。有多种策略可以解决这一难题,即调查具有最高可能结果的最佳解决方案:

ε-贪婪法

ε-Greedy(ε-Greedy)是最常见和最简单的算法,通过随机选择来平衡探索和利用之间的权衡。假设我们在初始阶段探讨n选项。然后,通过ε-贪婪算法, (1- ε ) 百分时间我们贪婪地利用*n 个选项中的最佳选项 k ,在剩余的 e 百分时间内随机探索其他选项,以获得比先前最佳选项 k. 更好的决策***

ε递减法

ε减少类似于ε贪婪方法。ε贪婪方法中的ε保持固定,而在ε递减方法中,ε值随时间逐渐减小。随着ε值的减小,探索新选项的次数逐渐减少,这意味着最佳选项在此过程中变得更加确定。

阅读默罕默德·马苏姆博士(以及媒体上成千上万的其他作家)的每一个故事。

你的会员费将直接支持和激励穆罕默德·马苏姆和你所阅读的成千上万的其他作家。你还可以在 Medium 上看到所有的故事—【https://masum-math8065.medium.com/membership】

快乐阅读!

斯坦福大学 Pythoners 课程简介

原文:https://towardsdatascience.com/intro-to-stanfords-corenlp-and-java-for-python-programmers-c2586215aab6?source=collection_archive---------22-----------------------

在您的 Python 项目中安装、开始使用和集成 coreNLP Java 脚本。

你好。我回来了,我希望这是斯坦福大学 CoreNLP 图书馆系列文章的第一篇。在本文中,我将重点介绍这个库的安装,并为像我这样的 Java 新手介绍它的基本特性。我将首先通过命令行来完成安装步骤和一些测试。稍后,我将带您浏览两个非常简单的 Java 脚本,您可以轻松地将它们合并到 Python NLP 管道中。你可以在 github 上找到完整的代码!

梁杰森Unsplash 上拍照

CoreNLP 是一个工具包,用它你只需要几行代码就可以生成一个相当完整的 NLP 管道。该库包括所有主要 NLP 过程的预构建方法,如词性(POS)标记、命名实体识别(NER)、依存解析或情感分析。它还支持除英语之外的其他语言,尤其是阿拉伯语、汉语、德语、法语和西班牙语。

我是这个库的忠实粉丝,主要是因为它的情感分析模型是多么酷的❤(我将在下一篇文章中详细介绍)。然而,我明白为什么大多数人宁愿使用 NLTK 或 SpaCy 等其他库,因为 CoreNLP 可能有点矫枉过正。事实上,coreNLP 的计算成本可能比其他库高得多,对于浅层 NLP 进程,结果甚至不会明显更好。另外,它是用 Java 编写的,对于 Python 用户来说入门有点痛苦(但是它是可行的,正如您将在下面看到的,如果您不介意的话,它还有一个 Python API)。

  • CoreNLP 管道和基本标注器

coreNLP 的基本构建模块是 coreNLP 管道管道。管道获取输入文本,对其进行处理,并以 coreDocument 对象的形式输出处理结果。coreNLP 管道可以根据您的 NLP 项目需求进行定制和调整。属性对象允许通过添加、删除或编辑注释者来进行定制。

那有很多行话,所以让我们用一个例子来分解它。所有的信息和数据都来自官方的 coreNLP 页面。

coreNLP 基本管道——图摘自 coreNLP 现场

在上图中,我们有一个基本的 coreNLP 管道,默认情况下,当您第一次运行 coreNLP 管道类而不做任何更改时,就会运行这个管道。在最左边,我们有进入管道的输入文本,这通常是普通的。txt 文件。管道本身由 6 个标注器组成。这些注释器中的每一个都将按顺序处理输入文本,处理的中间输出有时被其他一些注释器用作输入。如果我们想通过添加或删除注释器来改变这个管道,我们可以使用 properties 对象。最终输出是一组注释,其形式为一个 coreDocument 对象

我们将在整篇文章中使用这个基本管道。稍后当我们看一个例子时,对象的性质将变得更加清楚。现在,让我们记下每个注释器做了什么:

  • 注释器 1:标记化 →将原始文本转换成标记。
  • 注释者 2:分句 →将原文分成句子。
  • 标注器 3:词性(POS)标注 →给记号分配词性标签,比如是动词还是名词。文本中的每个标记都将被赋予一个标签。

位置标记示例—图摘自 coreNLP 网站

  • 注释器 4:词条化 →将每个单词转换成它的词条,即它的字典形式。例如,单词“was”被映射为“be”。
  • 注释器 5:命名实体识别(NER) →当实体(人、国家、组织等)在文本中被命名时进行识别。它还能识别数字实体,如日期。

NER 示例—图摘自 coreNLP 网站

  • 注释器 6:依存解析 →将解析文本并突出显示单词之间的依存关系。

依存解析示例—图摘自 coreNLP 网站

最后,来自 6 个标注器的所有输出被组织到一个核心文档中。这些基本上是以结构化方式包含注释信息的数据对象。CoreDocuments 使我们的生活变得更容易,因为,正如您将在后面看到的,它们存储了所有的信息,以便我们可以用一个简单的 API 来访问它。

CoreDocument 的图形表示——图摘自 coreNLP 网站

  • 安装

你需要安装 Java。你可以在这里下载最新版本的。为了下载 CoreNLP,我遵循了官方指南:

  1. 使用 curl 或 wget 下载 CoreNLP zip 文件
curl -O -L http://nlp.stanford.edu/software/stanford-corenlp-latest.zip

2.解压缩文件

unzip stanford-corenlp-latest.zip

3.移到新创建的目录中

cd stanford-corenlp-4.1.0

现在让我们来看几个例子,以确保一切正常。

  • 使用命令行和 input.txt 文件的示例

对于这个例子,首先我们将打开终端并创建一个测试文件,我们将使用它作为输入。代码改编自 coreNLP 的官方网站。您可以使用以下命令:

echo "the quick brown fox jumped over the lazy dog" > test.txt

echo在 test.txt 文件上打印句子"the quick brown fox jumped over the lazy dog"

现在让我们在测试句子上运行一个默认的 coreNLP 管道。

java -cp “*” -mx3g edu.stanford.nlp.pipeline.StanfordCoreNLP -outputFormat xml -file test.txt

这是一个 java 命令,从类edu . Stanford . NLP . pipeline . stanfordcorenlp .加载并运行 coreNLP 管道,因为我们没有对该类进行任何更改,所以设置将设置为默认值。管道将使用 test.txt 文件作为输入,并将输出一个 XML 文件。

运行该命令后,管道将开始注释文本。你会注意到这需要一段时间……(一个 9 个单词的句子大约需要 20 秒🙄).输出将是一个名为 test.txt.xml 的文件。这个过程还会自动生成一个 XSLT 样式表( CoreNLP-to-HTML.xsl ),如果您在浏览器中打开它,它会将 xml 转换为 HTML。

在 Firefox 中显示的 XML 文件

似乎一切都很好!!我们看到标准管道实际上相当复杂。它包括了我们在上一节中看到的所有注释器:标记化、句子分割、语义化、词性标注、NER 标注和依存解析。

注意: 我用 Firefox 显示了它,然而我花了很长时间才弄明白如何做到这一点,因为显然在 2019 年 Firefox 不再允许这样做。可以通过进入 about:config 页面并将privacy . file _ unique _ origin设置更改为 False 来解决这个问题。如果对您不起作用,您可以选择 json 作为输出格式,或者用文本编辑器打开 XML 文件。

  • 使用交互式外壳模式的示例

对于我们的第二个例子,您也将专门使用终端。CoreNLP 有一个很酷的交互式 shell 模式,可以通过运行以下命令进入。

java -cp “*” -mx3g edu.stanford.nlp.pipeline.StanfordCoreNLP 

一旦进入这种交互模式,您只需键入一个句子或一组句子,它们将由基本的注释器动态处理!下面你可以看到一个如何分析句子“你好,我叫劳拉”的例子。

我们可以看到在终端中以不同格式打印的 XML 文件中看到的相同注释!你也可以用更长的文本来尝试。

  • 使用非常简单的 Java 代码的示例

现在让我们来看几个 Java 代码示例!我们将基本上使用 Java 创建和调整管道,然后将结果输出到一个. txt 文件中,该文件可以合并到我们的 Python 或 R NLP 管道中。代码改编自 coreNLP 的官方网站。

例 1

在我的 github 中找到完整的代码。我将首先带您浏览一下coreNLP _ pipeline 1 _ LBP . Java文件。我们开始导入所有需要的依赖项的文件。然后,我们将创建一个用于分析的文本示例。您可以将其更改为任何其他示例:

public static String text = "Marie was born in Paris."; 

现在,我们设置了管道,创建了一个文档,并使用以下代码行对其进行了注释:

// set up pipeline properties
Properties props = new Properties();// set the list of annotators to run
props.setProperty("annotators","tokenize,ssplit,pos,lemma,ner,depparse");// build pipeline
StanfordCoreNLP pipeline = new StanfordCoreNLP(props);// create a document object and annotate it
CoreDocument document = pipeline.processToCoreDocument(text);
pipeline.annotate(document);

文件的其余几行将在终端上打印出来,进行几次测试以确保管道工作正常。例如,我们首先获得输入文档的句子列表。

// get sentences of the document
        List <CoreSentence> sentences = document**.sentences()**;
        System.out.println("Sentences of the document");
        System.out.println(sentences);
        System.out.println();

注意,我们使用 document 对象上的方法.sentences()获得句子列表。类似地,我们在宾语句子上使用方法.tokens()得到句子的标记列表,在宾语 tok 上使用方法.word().lemma()得到单个单词和词条。

List<CoreLabel> tokens = sentence**.tokens()**;System.out.println("Tokens of the sentence:");
          for (CoreLabel tok : tokens) {
            System.out.println("Token: " + tok**.word()**);
            System.out.println("Lemma: " + tok**.lemma()**);
          }

要运行这个文件,你只需要把它保存在你的stanford-corenlp-4.1.0目录下,然后使用命令

java -cp "*" coreNLP_pipeline1_LBP.java

结果应该是这样的:

例二

第二个例子coreNLP _ pipeline 2 _ LBP . Java略有不同,因为它读取一个文件 coreNLP_input.txt 作为输入文档,并将结果输出到一个 coreNLP_output.txt 文件。

我们使用短篇故事狐狸和葡萄作为输入文本。这是一份有 2 段 6 句话的文件。处理过程将类似于上面的例子,除了这一次我们还将跟踪段落和句子的编号。

最大的变化将是关于读取输入和写入最终输出。下面的这段代码将创建输出文件(如果它还不存在)并使用 PrintWriter 打印列名…

File file = new File("coreNLP_output.txt");
    //create the file if it doesn't exist
    if(!file.exists()){
      file.createNewFile();}**PrintWriter** out = new **PrintWriter**(file);//print column names on the output document      out.println("par_id;sent_id;words;lemmas;posTags;nerTags;depParse");

…另一位将使用扫描仪读取输入文档。输入文档将被保存为一个字符串文本,我们可以像示例 1 中那样使用它。

**Scanner** myReader = new **Scanner**(myObj);while (myReader.hasNextLine()) {
          String text = myReader.nextLine();

运行文件coreNLP _ pipeline 2 _ LBP . Java并生成输出后,可以使用以下 python 代码将其作为 dataframe 打开:

df = pd.read_csv('coreNLP_output.txt', delimiter=';',header=0)

产生的数据帧将如下所示,并可用于进一步分析!

coreNLP 数据框架

  • 结论

正如你所看到的,coreNLP 非常容易使用,并且很容易集成到 Python NLP 管道中!你也可以把它直接打印到一个. csv 文件中,并使用其他分隔符,但是我遇到了一些烦人的解析问题。不管怎样,希望你喜欢这篇文章,并且记住完整的代码可以在 github 上找到。

在下面的帖子中,我们将开始讨论递归情感分析模型,以及如何在 coreNLP 和 Java 中使用它。请继续关注,了解更多关于✌科伦普的信息🏻

  • 参考书目

[## 概观

高性能人类语言分析工具,现在带有 Python 中的原生深度学习模块,可用于许多…

stanfordnlp.github.io](https://stanfordnlp.github.io/CoreNLP/index.html) [## [计] 下载

斯坦福 CoreNLP 可以通过下面的链接下载。这将下载一个大的(536 MB) zip 文件,其中包含(1)的…

stanfordnlp.github.io](https://stanfordnlp.github.io/CoreNLP/download.html) [## 管道

CoreNLP 的核心是管道。管道接收文本或 xml,并生成完整的注释对象…

stanfordnlp.github.io](https://stanfordnlp.github.io/CoreNLP/pipeline.html) [## CoreNLP API

下面是一小段代码,演示了在一些示例文本上运行完整的管道。它需要英国人…

stanfordnlp.github.io](https://stanfordnlp.github.io/CoreNLP/api.html) [## 命令行用法

注意:Stanford CoreNLP v.3.5+需要 Java 8,但也可以使用 Java 9/10/11。如果使用 Java 9/10/11,您需要…

stanfordnlp.github.io](https://stanfordnlp.github.io/CoreNLP/cmdline.html)

流式数据和 Apache Kafka 简介

原文:https://towardsdatascience.com/intro-to-streaming-data-and-apache-kafka-5a797231258f?source=collection_archive---------27-----------------------

流数据架构概述以及 Apache Kafka 如此受欢迎的原因

术语“大数据”不仅仅指数量和容量。生活在一个随时可以获得信息和即时通信的时代,数据架构已经转向面向流就不足为奇了。对公司来说,真正的价值不仅仅来自于坐拥大量收集的数据点,还来自于他们尽快(甚至是实时)提取可操作的见解的能力。以更快的速度处理数据使公司能够实时应对不断变化的业务环境。

不言而喻,在过去的十年中,能够捕获、保留和处理这种极其快速的信息流的应用程序(又名消息代理软件)一直在不断增长。截至 2020 年,Apache Kafka 是最广泛采用的信息中介软件之一(被网飞、优步、Airbnb 和 LinkedIn 等公司使用)来完成这些任务。这个博客将非常简要地概述流处理的概念、流数据架构以及为什么 Apache Kafka 获得了如此大的发展势头。

图片来源:Giphy

什么是流处理?

溪流加工最好被想象成一条河流。就像水在河流中流动一样,信息包也在无尽的流处理中流动。

根据 AWS,流数据的一般定义将是“由成千上万个数据源连续生成的数据,这些数据源通常同时发送数据记录,并且大小很小(千字节量级)”。

数据流在时间序列中工作得特别好,以便随着时间的推移找到潜在的模式。它在可以不断收集不同数据信号的物联网领域也大放异彩。其他常见的应用包括网络交互、电子商务、交易日志、地理定位等等。

实时处理和流处理之间有细微的区别:

  1. 就数据处理而言,实时处理意味着严格的截止日期。换句话说,事件时间非常重要,秒级的延迟是不可接受的。
  2. 流处理更多地是指在连续的数据流中的一种计算方法。从最后一天创建的所有脸书帖子中打印出来的应用程序实际上没有时间限制。然而,长期输出速率应该比长期输入速率更快(或至少相等),否则系统存储需求将无限增大。

流式数据架构

标准流数据架构由 3 个基本块组成:

  1. 消息代理。它从所谓的生产商那里收集流媒体数据。生产者可以跟踪任何事件,从指标,点击流,搜索等。然后,所有这些动作都被存储到 Apache Kafka 架构的原子构建块中,即主题和分区。Kafka 的一个关键优势是它能够并行化分区,从而提高整体吞吐量。这些信息随后被提供给消费者,消费者将以不同的方式使用这些输出。

图片来源:维基百科/卡夫卡消息代理

两个非常著名的新一代消息代理软件是 Apache Kafka 和 Amazon Kinesis,与 RabbitMQ 和 Active MQ 等老版本相对。

2.实时 ETL 工具

然后,原始数据被转换、清理和聚合,以便可以被基于 SQL 的系统使用,以便以后进行分析。

执行这些任务的一些最常用的平台是流处理器,如 Spark 流、Kafka 流等。这个阶段的结果可能是 API 调用、动作、警报等。

3.数据存储和分析

在我们的数据流处理器准备好数据后,我们必须对其进行存储和分析,以便提供有价值的见解。如此大量的数据可以存储在像亚马逊 S3 这样的廉价数据湖中,代价是延迟和 SQL 操作。或者像 Cassandra 和 Amazon Redshift 这样的数据仓库,它们比数据湖更难管理,但也更结构化。或者,它们也可以存储在消息代理本身的内存中(例如 Kafka ),但这比数据湖要贵 10 倍。

为什么卡夫卡如此受关注?

为了更好地理解流处理是如何产生的,让我们简单地看一下在阿帕奇卡夫卡之前数据处理是什么样子的。所有数据之前都存储在数据库或分布式文件系统中,将定期(1 小时、1 天等)对其进行分析和操作。

尽管这一模式已经运行了很长时间,并且仍有许多应用,但它也有一个根本性的缺陷。在一个数据价值随时间快速下降的世界里,它根本无法即时分析数据。

流处理就是获取和分析事件的,正如我们前面看到的,负责获取的主干由我们的消息代理软件组成,它能够接收所有这些数据信号,并使它们(几乎)立即可用。然而,创建一个多对多生产者对消费者的超高效系统并非易事,这正是 Linkedin 在 2008 年开始研究 Kafka 时必须面对的问题。其中一个主要问题是,生产者应该如何在私人会议中将信息直接传递给每个消费者,以及消费者如何在生产者编写数据时读取这些数据。

Linkedin 的项目(后来成为 Apache Kafka)解决了这个问题,并提供了一个分布式平台,能够在流记录发生时对其进行处理。

它基本上成为了现代流处理的主干,并且非常成功,以至于其他公司创建了他们的对手,如 Amazon Kinesis 和 Azure Event Hubs。

它受欢迎的核心是引入了一个面向日志的系统,而不是以前采用的批处理结构。日志是按时间顺序排列的、只需追加的一系列事件,消费者可以随时从中提取信息。来自购物车的日志中的数据事件的例子可以是添加项目、删除项目、结帐等。在 Kafka 中,消息被写在维护其日志的主题上,消费者可以从中提取数据。

图片来源:Apache Kafka 官方网站/仅附加日志结构

即使像 Rabbit MQ 和 ActiveMQ 这样的消息代理软件在 Kafka 之前就已经存在多年了,日志附加结构仍然允许处理数量惊人的事务。在 Kafka 中,每个消费者负责跟踪他们的活动,而在 RabbitMQ 这样的软件中,他们必须像队列一样工作,消息代理本身跟踪消费者的活动。

不得不说,卡夫卡并没有使以前的系统过时,它们仍然适用于其他建筑,它们只是更适合。Kafka 提供了更高的吞吐量,目前使像网飞这样的公司能够在高峰时间每秒处理 800 万个事件的数量级的令人难以置信的数据。

网络报废介绍:我们如何轻松找到我们想要的数据?

原文:https://towardsdatascience.com/intro-to-web-scrapping-how-can-we-easily-seek-the-data-we-want-d9f3d9359246?source=collection_archive---------59-----------------------

使用 BeautifulSoup、Regex 和 Seaborn visualization 分析影响 NBA 球队胜率的因素

来源:塞斯·里斯

那你为什么要读这个?坦白地说,我写这篇文章既是为了你,也是为了我自己。你看,我有一个豌豆大小的大脑,我希望写一篇这样的文章,作为我重温这些技术的日志。这也意味着我会把它写成一本儿童故事书,让我小小的豌豆脑袋去理解,也让你容易消化。尽情享受吧!

这个分析项目的目标是找出一个 NBA 球员的身体素质对他们球队的成功有多大的贡献。因此,我们将分析每支球队平均球员的身高、体重和身体质量指数,并与当前赛季的记录进行对比。当我们这样做的时候,我觉得有点恶作剧,就加上了 【名字的平均长度】 ,纯粹是为了满足我对它如何与其他属性匹配的好奇心。

1.创建 BeautifulSoup 对象

首先,为了创建 soup 对象,我们必须使用我们希望从中提取数据的 URL 创建一个请求对象。在我的例子中,URL 是:"https://www.nba.com/teams/(blank)",( blank)是所有 30 支球队的名字。因此,在循环创建我需要的对象之前,我创建了一个名为 teams 的 2D 列表。

**#snippet of teams list**
teams = [[‘atl’,’hawks’],[‘bos’,’celtics’],[‘bkn’,’nets’]]**#create request object**
for team in teams:
 url = “[https://www.nba.com/teams/](https://www.nba.com/teams/)" + team[1]
 r = requests.get(url)**#create soup object**
 soup = BeautifulSoup(r.text,’html.parser’)

2.寻找正确的除法容器

来源: NBA

下一步,我们将通过右击元素并选择‘Inspect’来访问我们的 URL 并检查页面的 HTML 结构。会出现一个类似上面照片的菜单,显示一长串 HTML 标签。搜索保存信息的特定分部或部门类别。从我的经验来看,大多数页面都将来自相同类别(例如,电影、产品)的列表包装在同一个类下。在这种情况下,我们要寻找的重复性容器是:

**#soup.find_all finds all containers with this specific section class**
all_div = soup.find_all(‘section’, class_=’nba-player-index__trending-item small-4 medium-3 large-2 team-’+team[0]+’-’+team[1])

3.控制爬网率

因为我们向多个页面发送请求,所以我们负责任地这样做是完全正确的。通过控制爬行速率,我们避免了站点被我们的请求堵塞,并允许服务器处理其他用户的请求。虽然这意味着我们的代码可能需要额外的一分钟来运行,但我们不太可能被禁止使用我们的 IP 地址。实践良好的报废道德总是很重要的!

**#control crawl rate**
sleep(randint(2,10))

我们通过使用以下函数来实现这一点:

  • **randint(2,10)**随机生成请求之间的等待时间,数值在 2-10 秒之间。可以更改这些参数以适合您的项目。

4.提取数据

  • 提取玩家名字

来源: NBA

第一个很简单。当将光标悬停在名称上时,我们可以看到,在容器内,数据属于
< p 类‘NBA-player-index _ _ name’>下,并嵌套在一个超链接 < a > 标签下。

*for container in all_div:

 name = **container.a.find(‘p’, class_=’nba-player-index__name’).text**
 output[‘Name’].append(name)*

**.a**代表<一个>标签
**.find****container.a**
**.text**下搜索这个类中出现的第一个元素,去掉任何标签,只留下文本

  • 提取玩家的位置、身高&体重

来源: NBA

对于剩余的数据字段,需要进行一些清理,我们将使用 正则表达式 筛选出我们想要的数据。与前面的例子不同,剩余的数据字段并不是单个 class 标记所独有的。

*details = **container.a.find(‘div’, class_=’nba-player-index__details’).text***

当我们使用 find() 函数时,**details**会将找到的所有文本放在一起,并返回给我们“向前 6 英尺 10 英寸| 200 磅”。
因此为了筛选出玩家的位置,我们使用**re.match()** 来匹配从开始到第一个非字母字符的所有字符。

*position = **re.match(‘[A-Za-z]+’,details).group(0)**
output[‘Position’].append(position)*

至于身高和体重,使用**re.findall('\d+',details)**会返回一个在**details** 内找到的整数列表。从那里,我做了适当的单位转换和身体质量指数计算。

*numbers = **re.findall(‘\d+’, details)**
height_in_inches = (int(numbers[0]) * 12) + int(numbers[1])
height = round(height_in_inches * 2.54)
output[‘Height (cm)’].append(height)

weight = round((int(numbers[2])/2.205),2)
output[‘Weight (kg)’].append(weight)

bmi = round((weight/(height/100)**2),2)
output[‘BMI’].append(bmi)*
  • 提取玩家姓名的长度

最后,我再次使用了 regex ,因为我意识到他们的名字中有很多是由连字符或其他特殊字符组成的。然而,我只想计算字母字符的数量。

*name_len = **len(re.findall(‘[A-Za-z]’, name))**
output[‘Length of Name’].append(name_len)*

4 分 39 秒后,这就是我们到达的地方!

5.准备用于分析的数据

有了上面的数据框架,我们现在可以总结他们各自团队的数据,并包括他们各自的胜率。

虽然我可以轻松地复制所有 30 个团队记录,但我决定直接从页面中删除它们,以保持数据的完整性。

来源:篮球-参考

***url = ‘**[**https://www.basketball-reference.com/leagues/NBA_2020_standings.html'**](https://www.basketball-reference.com/leagues/NBA_2020_standings.html')
r = requests.get(url)
soup = BeautifulSoup(r.text,’html.parser’)all_div = **soup.find_all('tr', class_='full_table')**
for container in all_div:
    if **len(output['Team']) < 30**:
        team = **container.th.a.text**
        output['Team'].append(team)
        record = **container.find('td', attrs={'data-stat': 'win_loss_pct'}).get_text()**
        record_formatted = float('0' + record)
        output['Record'].append(record_formatted)*
  • **soup.find_all('tr', class_='full_table')** 搜索我们在这个页面中寻找的所有
    < tr 类>标签。
  • **if len(output['Team']) < 30** 由于页面包含相同数据的重复记录,放置一个 if 语句,只检索前 30 条记录。
  • **container.find('td', attrs={'data-stat': ‘win_loss_pct'})** 与之前的 find 函数不同,在这里使用‘class’作为参数,在这里使用‘class’并不能帮助我们将输赢百分比与其他数据列区分开来,例如每场比赛的输赢/点数。在这种情况下, attrs (属性)允许我们指定使用哪个参数。
*for **height** in results_df.groupby(‘Team’)[‘Height (cm)’].mean():
 output[‘Height (cm)’].append(height)

for **weight** in results_df.groupby(‘Team’)[‘Weight (kg)’].mean():
 output[‘Weight (kg)’].append(weight)for **bmi** in results_df.groupby(‘Team’)[‘BMI’].mean():
 output[‘BMI’].append(bmi)

for **name_len** in results_df.groupby(‘Team’)[‘Length of Name’].mean():
 output[‘Length of Name’].append(name_len)

#convert output into dataframe
**summary_df** = pd.DataFrame(output)*

最后,我使用了。groupby() 在先前的数据帧上按各自球队对球员的统计数据进行分组,并将平均值添加到新的数据帧中。

6.分析趋势

有了这个新的数据框架,我们终于可以分析它们了。

**.corr()** 用于查找数据帧中所有列的成对相关性。相关性衡量两个变量之间的线性关联程度,并根据值解释其关系的强度: -1 负 r/s | 0 无 r/s |+1 正 r/s

然后,我创建了一个热图,以便更好地显示上面的值。正如我们所看到的,所有 4 个属性都与团队记录有微弱但积极的关系。

  • 重量+0.35
  • 身高+0.32
  • 名称长度+0.16
  • 身体质量指数+0.11

有趣的是,与身体质量指数相比,每个球员名字的平均长度具有更高的相关性。体重也是其他因素中最有可能促成球队获胜记录的因素。可以创建一个 jointplot ,如下图所示,让我们更好地了解这种关系。

每个数据点由一个点表示。绿色圆圈代表的数据符合重量级球队在常规赛中表现更好的观点。重量级球队很可能是因为前场阵容强大,比如密尔沃基雄鹿队和多伦多猛龙队,他们目前都取得了巨大的成功。红色圈出的点是异常值,不符合该假设。

我们的分析到此结束。然而,在未来,我希望通过使用历史冠军球队的数据,更深入地研究这个 NBA 项目。

7.最后的想法

如果你远道而来,感谢你一路阅读!我希望这个指南对你介绍网络报废有所帮助。

完整的代码集可以在 这里 找到。
如果您对本文有任何意见或问题,请随时在 Linkedin 联系我。

快乐编码!

SQL 中的窗口函数介绍

原文:https://towardsdatascience.com/intro-to-window-functions-in-sql-23ecdc7c1ceb?source=collection_archive---------12-----------------------

如何使用窗口函数跨一组行执行操作

照片由 R MoUnsplash 上拍摄

窗口函数可以帮助您在选择行上运行操作,并从原始查询中返回值。

术语窗口描述函数操作的行集合。窗口函数使用窗口中行的值来计算返回值。

窗口函数的一些常见用途包括计算累计和、移动平均、排名等。(图表)

窗口功能由OVER子句启动,并使用三个概念进行配置:

  • 窗口分区(**P**ARTITION BY ) -将行分组为分区
  • 窗口排序(ORDER BY ) -定义每个窗口中行的顺序或次序
  • 窗口框架(ROWS ) -使用指定行的偏移量定义窗口

对于本教程,我们将涵盖**PARTITION****ORDER BY**。我假设你有基本到中级的 SQL 经验。如果你没有,这里有一些很好的资源可以帮助你开始。

窗口函数与分组依据:

  • 窗口函数不会减少输出中的行数。
  • 窗口函数可以从其他行中检索值,而 GROUP BY 函数则不能。
  • 窗口函数可以计算累计和移动平均值,而 GROUP BY 函数则不能。

入门指南

我将与来自数据营的名为 summer_medal 的奥运奖牌榜一起工作。(如果你是一名拥有 edu 邮箱的学生,并且想要获得三个月的免费 Datacamp 访问— GitHub 学生开发者包)。

以下是该表的概述。

该表代表了从 1896 年到 2010 年的奥运会,包含了每个国家、运动、项目、性别和学科的所有奖牌获得者。

ROW_NUMBER()

如前所述,使用 OVER()标识窗口函数。本教程中的第一个函数是 ROW_NUMBER()。此函数为行中的每条记录分配一个编号。

SELECT
  athlete,
  event,
  **ROW_NUMBER() OVER()** AS Row_Number
FROM Summer_Medals
ORDER BY Row_Number ASC;

输出

我们可以看到,我们使用 ROW_NUMBER()创建了一个行号,并将其分配给所选的变量。我们将窗口函数别名为 Row_Number,并对其进行排序,这样我们就可以获得顶部的第一行编号。

行号为(),排序依据为()

我们可以结合ORDER BYROW_NUMBER来确定哪一列应该用于行号分配。让我们找到不同的运动,并根据字母顺序给它们分配行号。

SELECT
  sport,
  **ROW_NUMBER()** **OVER**(**ORDER BY** sport ASC) AS Row_N
FROM (
  SELECT DISTINCT sport
  FROM Summer_Medals
) AS sports
ORDER BY sport ASC;

划分依据

使用[PARTITION BY](https://www.geeksforgeeks.org/mysql-partition-by-clause/),您可以根据一列中的唯一值拆分一个表。当我们必须使用一个组中的其他行对该组中的单个行执行计算时,这很有用。该子句仅适用于 windows 函数,如- LAG()LEAD(),等。

什么是 LAG()?

SQL LAG()是一个窗口函数,输出当前行之前的一行。

这是一个很好的例子,说明了它与我们的数据之间的关系。让我们找出从 2004 年开始按性别分列的网球运动员,谁赢得了网球单打金牌,谁在前一年获胜。

这个问题有几个步骤。首先,我们想要创建一个 CTE,它允许您定义一个临时命名的结果集,该结果集在一个语句的执行范围内临时可用——如果您被困在这里,请访问我的另一篇 帖子 以了解更多信息。

因为我们希望在使用LAG()之前,我们的结果中有今年的获胜者。

**-- CTE for isolating gold medal tennis winners** WITH Tennis_Gold AS (
  SELECT
    Athlete,
    Gender,
    Year,
    Country
  FROM
    Summer_Medals
  WHERE
    Year  >=  2004 AND
    Sport = 'Tennis' AND
    event = 'Singles' AND
    Medal = 'Gold')**-- Window Function to find the lag and partition by gender** SELECT
    Athlete as Champion,
    Gender,
    Year,
    **LAG**(Athlete) OVER (**PARTITION BY** gender
                        ORDER BY Year ASC) AS Last_Champion
FROM Tennis_Gold
ORDER BY Gender ASC, Year ASC;

输出

我们可以看到,男性和女性的结果都在一列中输出——这就是分区的作用。我们承认有 3 名男性和 3 名女性获奖者。男性和女性的第一个赢家是在 2004 年,如果我们看右边,我们看到一个空,因为在这之前没有赢家,因为我们从 2004 年开始。使用LAGPARTITION BY有助于实现这一点。

让我们尝试使用铅()。

什么是铅()?

SQL LEAD()是一个窗口函数,输出当前行之后的一行——本质上与 LAG()相反。

让我们使用网球例子中的相同问题,但是相反,找到未来的冠军,而不是过去的冠军。

**-- CTE isolating tennis sport, gold medalists from the year 2004+**WITH Tennis_Gold AS (
  SELECT
    Athlete,
    Gender,
    Year,
    Country
  FROM
    Summer_Medals
  WHERE
    Year  >=  2004 AND
    Sport = 'Tennis' AND
    event = 'Singles' AND
    Medal = 'Gold')**-- Window function, using LEAD to find the NEXT champion** SELECT
    Athlete as Champion,
    Gender,
    Year,
    **LEAD**(Athlete) OVER (PARTITION BY gender
                        ORDER BY Year ASC) AS **Future_Champion**
FROM Tennis_Gold
ORDER BY Gender ASC, Year ASC;

输出

我们只需要把LAG改成LEAD,把别名改成未来冠军,就能达到相反的效果。

排名()

SQL RANKROW_NUMBER类似,只是它会将相同的数字分配给具有相同值的行,跳过后面的数字。还有一个DENSE_RANK,它给一个具有相等值的行分配一个数字,但不跳过一个数字。如果这一切看起来令人困惑,不要担心。下面是这种情况的并列对比。

请注意 3 种不同类型的柱。

  • Row_number —这里没有什么新东西,我们只是为查询中的每一个行添加值。
  • Rank_number —这里,我们给出了基于值的排名,但是请注意,我们没有排名 3 。相反,我们有两个 2,我们跳到排名 4。
  • Dense_rank —类似于 rank_number,但我们没有跳过秩 3,而是包括了它。

这就是RANKDENSE_RANK的主要区别。一个包括在联合排名数字之前的排名,一个不包括。

下面是我用来得到上表的代码。

-- ***CTE to get countries and number year particpated in selected countries.***WITH countries AS (
  SELECT
    Country,
    COUNT(DISTINCT year) AS participated
  FROM
    Summer_Medals
  WHERE
    Country in ('GBR', 'DEN', 'FRA', 'ITA','AUT')
  GROUP BY
    Country)-- ***Window functions to show different ranking choices.***
SELECT
    Country,
    participated,
    **ROW_NUMBER()**
        OVER(ORDER BY participated DESC) AS Row_Number,
    **RANK()**
        OVER(ORDER BY participated DESC) AS Rank_Number,
    **DENSE_RANK()**
        OVER(ORDER BY participated DESC) AS Dense_Rank
FROM countries
ORDER BY participated DESC;

最终结果

对窗口函数的介绍到此结束。windows 函数还有更多的功能,包括ROWSNTILE,以及集合函数(SUMMAXMIN等。).我将发布关于如何在 SQL 中更多地利用窗口函数的教程,所以请务必关注我的最新帖子。

LinkedinGithub 上与我联系

使用 Python 的 Yelp Web 抓取简介

原文:https://towardsdatascience.com/intro-to-yelp-web-scraping-using-python-78252318d832?source=collection_archive---------32-----------------------

蒂姆·莫斯霍尔德在 Unsplash 上的照片

像许多持有甚至与计算机编程无关的学位的程序员一样,我自 2019 年以来一直在努力自学编码,希望能在工作中取得成功。作为一名自学成才的开发人员,我对我所学的东西更加实际和有目标。这就是我特别喜欢网络抓取的原因,不仅它有各种各样的用例,如产品监控,社交媒体监控,内容聚合等,而且它很容易上手。

web 抓取的基本思想是从网站中提取信息片段,并将其导出为易于阅读的格式。如果你是一个数据驱动型的人,你会发现网络抓取的巨大价值。幸运的是,有免费的网页抓取工具可以自动抓取网页数据,无需编码。

网络环境比我们想象的更复杂。说到这里,我们需要投入时间和精力来维护抓取工作,更不用说来自多个网站的海量抓取了。另一方面,抓取工具使我们免于编写代码和没完没了地维护工作。

为了让您了解 python 抓取和网站抓取工具的优缺点,我将带您了解 python 的整个工作。然后我会用网络抓取工具来比较这个过程。

事不宜迟,让我们开始吧:

使用 Python 进行 Web 抓取

项目:

  • 网站:Yelp.com
  • 抓取内容:企业名称、评级、评论数、电话号码、价格区间、地址、邻居

你可以在这里找到完整的代码:https://github.com/whateversky/yelp

先决条件:

  • Python 3.7
  • py charm—用于快速检查和修复编码错误
  • Bejson —清理 json 结构格式

一般的刮擦过程如下所示:

  • 首先,我们创建一个蜘蛛来定义我们将如何从 Yelp 中执行和提取数据。换句话说,我们发送 GET 请求,然后设置规则让抓取器抓取网站。
  • 然后,我们解析网页内容并返回包含提取数据的字典。说到这里,我们告诉蜘蛛它必须返回一个 Item 对象或一个请求的对象。
  • 最后,导出从蜘蛛返回的提取数据。

我只关注蜘蛛和解析器。然而,在数据提取之前,我们当然需要理解 web 结构。在编码时,你还会发现自己一直在检查网页以访问 div 和类。要检查网站,请转到您最喜欢的浏览器并右键单击。选择“检查”并在网络下找到“XHR”选项卡。您将找到相应的列表信息,包括商店名称、电话号码、位置和评级。当我们展开“PaginationInfo”时,它显示每个页面上有 30 个列表,总共有 6932 个列表。现在让我们开始有趣的部分:

蜘蛛:

首先,打开 Pycharm 并建立一个新项目。然后建立一个 python 文件,命名为“yelp_spider”

获取页面:

我们创建一个 get_page 方法。这将传递一个包含所有列出的 web URLs 的查询参数,然后返回页面 JSON。注意,我还添加了一个用户代理字符串来欺骗 web 服务器,以绕过任何 scraper 检测。我们可以复制并粘贴请求头。这不是必须的,但是如果你倾向于反复抓取一个网站,你会发现它在大多数时候是有用的。

我补充。format 参数来格式化 URL,以便它返回一个遵循某种模式的端点,在本例中,是来自搜索结果“Bar in New York City”的所有列表页面

def get_page(self,start_number):

网址= "https://www.yelp.com/search/snippet?find _ desc = bars & find _ loc = New % 20 York % 2C % 20 ny % 2C % 20 United % 20 States & start = { } & parent _ request _ id = dfcaae 5 FB 7b 44685 & request _ origin = user " \。格式(起始编号)

获取详细信息:

我们刚刚成功地获取了列表页面的 URL,现在我们可以告诉 scraper 使用 get_detail 方法访问每个详细页面。

详细页面 URL 由域名和表示企业的路径组成。

Yelp 详细页面 url

由于我们已经收集了列表 URL,我们可以简单地定义 URL 模式,它包括一个附加到https://www.yelp.com的路径。这样,它将返回一个详细页面的网址列表

def get_detail(self,URL _ suffix):URL = " https://www . yelp . com/"+path

接下来,我们仍然需要添加一个标题,使刮刀看起来更人性化。对我们来说,进门之前敲门类似于一种常见的礼仪。

添加标题

然后我创建了一个与 IF 语句相结合的 FOR 循环来定位我们将要得到的标签。在这种情况下,标签包含企业名称、评级、评论、电话等。

创建一个循环

与返回 JSON 格式的列表页面不同,详细页面通常以 HTML 格式响应我们。因此,我去掉了标点符号和多余的空格,使它们在解析时看起来干净整洁。

解析:

当我们一个接一个地访问这些页面时,我们可以指示我们的蜘蛛通过解析页面来获得详细的信息。

首先,在同一个文件夹下创建第二个名为“yelp_parse.py”的文件。并从导入开始,执行 YelpSpider。

在这里,我添加了一个分页循环,因为有 30 个清单分布在多个页面上。“start_number”是一个偏移值,在本例中为“0”。当我们爬完当前页面时,数字会增加 30。以这种方式,逻辑将是这样的:

获取前 30 个列表

标页数

获取 31–60 个列表

标页数

获取 61–90 个列表…

页码

最后但同样重要的是,我创建了一个字典来将键和值与各自的数据属性配对,包括企业名称、评级、电话、价格范围、地址、邻居等等。

获取详细信息

用网刮工具刮:

使用 python,我们可以直接与 web 服务器、门户和源代码进行交互。理想情况下,这种方法会更有效,但需要编程。由于网站是如此多才多艺,我们需要不断地编辑刮板,以适应变化。Selenium 和木偶师也是如此,它们是近亲,但与 Python 相比,它们在大规模提取方面有局限性。

另一方面,网页抓取工具更加友好。让我们以 八解 为例:

Octoparse 的最新版本 OP 8.1 应用了 Train 算法,该算法在网页加载时检测数据属性。如果你体验过应用人工智能的 iPhone 人脸解锁,“检测”对你来说并不是一个陌生的名词。

同样,Octoparse 将自动分解网页并识别各种数据属性,例如,企业名称、联系人信息、评论、位置、评级等。

Octoparse 8 自动检测

以 yelp 为例。一旦网页被加载,它会自动解析 web 元素并自动读取数据属性。一旦检测过程完成,我们就可以在预览部分看到 Octoparse 为我们捕获的所有数据,漂亮而整洁!然后,您会注意到工作流已经自动创建。工作流就像一个刮的路线图,刮的人会顺着方向去抓取数据。

我们在 python 部分创建了同样的东西,但是它们没有像 Octoparse 那样清晰的语句和图形。编程更具逻辑性和抽象性,如果没有这方面的坚实基础,就不容易概念化。

但这还不是全部,我们还想从详情页中获取信息。这很容易。只需按照提示面板上的指南,找到“在下一页收集网络数据”

行动指南

然后选择 title_url,它会将我们带到详细页面。

提取详细信息页面

一旦我们确认了命令,一个新的步骤将自动添加到工作流程中。然后,浏览器将显示一个详细页面,我们可以单击页面中的任何数据属性。例如,当我们点击业务标题“ARDYN”时,提示指南会响应一组操作供我们选择。只需单击“提取所选元素的文本”命令,它将处理剩下的工作并将操作添加到工作流中。类似地,重复上述步骤以获得“评级”、“评论计数”、“电话号码”、“价格范围”、“地址”。

遵循指南并设置操作

一旦我们设置好了所有的东西,只要在确认后执行 scraper。

决赛成绩

最后的想法:使用 python 和 web 抓取工具进行抓取

它们都可以得到相似的结果,但性能不同。使用 python,在实现之前肯定需要做很多基础工作。然而,抓取工具在许多层面上要友好得多。

如果你是编程的新手,想要探索网页抓取的能力,尽管如此,一个 网页抓取工具 是一个很好的起点。当你踏进编码的大门时,有更多的选择和组合,我相信这将激发新的想法,使事情变得更加轻松和容易。

原载于 2020 年 6 月 12 日http://www . data extraction . io**

使用 Rayshader (R)介绍 3D ggplots

原文:https://towardsdatascience.com/introducing-3d-ggplots-with-rayshader-r-c61e27c6f0e9?source=collection_archive---------25-----------------------

视频教程

在 3D 绘图中显示香港房价

Rayshader 是一个强大的 R 包,支持 2D 和 3D 数据可视化。让我惊讶的是它显示 3D 图的细节,它提供了很多定制。最重要的是,它允许您直接将 ggplot2 对象转换为 3D 绘图。

照片由 cyda

在本演示中,使用了香港人口和房价数据。预处理数据和 R 脚本上传到我的 Github repo 。请随意下载并试玩。

照片由 cyda

包裹

光线着色器

功能

rayshader是一个用于在 R 中生成 2D 和 3D 数据可视化的开源包。rayshader使用基本 R 矩阵中的高程数据以及光线跟踪、球形纹理映射、叠加和环境遮挡的组合来生成美丽的地形 2D 和 3D 地图。除了地图,rayshader还允许用户将ggplot2物体翻译成漂亮的 3D 数据可视化。

模型可以旋转并交互检查,或者可以编写摄像机移动脚本来创建动画。也可以使用高质量的路径跟踪器rayrender来渲染场景。用户还可以创建电影景深后处理效果,将用户的注意力引导到图中的重要区域。3D 模型也可以通过内置的 STL 导出功能导出为 3D 可打印格式。

示范

  1. ggplot2生成 2D 地图
  2. rayshader将 2D 图转换成 3D 图

数据

人口数据. xlsx

照片由 cyda

real_estate_master_df.csv

照片由 cyda

任务一:用 **ggplot2**生成 2D 地图

library(sp)
hkmap = readRDS("HKG_adm1.rds") # geo data of HK map# Preprocessing
map_data = data.frame(id=hkmap$ID_1, Code=hkmap$HASC_1, Eng_name=hkmap$NAME_1)
map_data$Code = gsub('HK.', '', as.character(map_data$Code))
map_data = merge(map_data, district_name, by = 'Eng_name')
hkmapdf = fortify(hkmap)
map_data = merge(hkmapdf, map_data, by="id")
map_data = merge(map_data, population, by = "Chi_name")
map_data$Population = as.numeric(map_data$Population)library(ggplot2)
# Map
map_bg = ggplot(map_data, aes(long, lat, group=group, fill = Population)) +
  geom_polygon() + # Shape
  scale_fill_gradient(limits=range(map_data$Population), 
                      low="#FFF3B0", high="#E09F3E") + 
  layer(geom="path", stat="identity", position="identity", 
       mapping=aes(x=long, y=lat, group=group, 
                   color=I('#FFFFFF'))) + 
  theme(legend.position = "none", 
        axis.line=element_blank(), 
        axis.text.x=element_blank(), axis.title.x=element_blank(),
        axis.text.y=element_blank(), axis.title.y=element_blank(),
        axis.ticks=element_blank(), 
        panel.background = element_blank()) # Clean Everything
map_bg# Save as PNG
xlim = ggplot_build(map_bg)$layout$panel_scales_x[[1]]$range$range
ylim = ggplot_build(map_bg)$layout$panel_scales_y[[1]]$range$range
ggsave('map_bg1.png', width = diff(xlim)*100, height = diff(ylim)*100, units = "cm")

逐步解释:

hkmap = readRDS("HKG_adm1.rds") # geo data of HK map

要绘制任何地区的地图,您需要手头有位置数据。请先从 Github repo 下载 rds 文件。

library(ggplot2)
# Map
map_bg = ggplot(map_data, aes(long, lat, group=group, fill = Population)) +
  geom_polygon() + # Shape
  scale_fill_gradient(limits=range(map_data$Population), 
                      low="#FFF3B0", high="#E09F3E") + 
  layer(geom="path", stat="identity", position="identity", 
       mapping=aes(x=long, y=lat, group=group, 
                   color=I('#FFFFFF')))

ggplot2 是另一个很棒的 R 包,它提供了很多种类的图表,像条形图、饼状图、热图…你能想到的。在上面显示的脚本中,主要做了两件事。在线 scale_fill_gradient 上,地图中显示的多边形根据人口数据用颜色填充。颜色较深的地区意味着人口较多。然后,给每个区域一条边界线,就是显示的白线。

照片由 cyda

map_bg + 
  theme(legend.position = "none", 
        axis.line=element_blank(), 
        axis.text.x=element_blank(), axis.title.x=element_blank(),
        axis.text.y=element_blank(), axis.title.y=element_blank(),
        axis.ticks=element_blank(), 
        panel.background = element_blank()) # Clean Everything
map_bg

创建此图的原因是为我们将在任务 2 中完成的 3D 图准备背景图像。因此,我用主题去掉了所有的网格线,x 轴和 y 轴。

输出:map_bg.png

# Save as PNG
xlim = ggplot_build(map_bg)$layout$panel_scales_x[[1]]$range$range
ylim = ggplot_build(map_bg)$layout$panel_scales_y[[1]]$range$range
ggsave(‘map_bg.png’, width = diff(xlim)*40, height = diff(ylim)*40, units = “cm”)

最后, ggsave 用于导出 map_bg,其比例与绘图坐标一致。

任务 2:用 **rayshader**将 2D 图转换成 3D 图

real _ estate _ master _ df.csv 的数据是从香港房产刮来的。

# 2D Plot
library(ggplot2)
library(grid)
estate_price = ggplot(estate_df) + 
  annotation_custom(rasterGrob(hk_map_bg, width=unit(1,"npc"), 
                               height=unit(1,"npc")), 
                    -Inf, Inf, -Inf, Inf) + 
  xlim(xlim[1],xlim[2]) + # x-axis Mapping
  ylim(ylim[1],ylim[2]) + # y-axis Mapping
  geom_point(aes(x=Longitude, y=Latitude, color=apr_price),size=2) + 
  scale_colour_gradient(name = '成交呎價(實)\n(HKD)', 
                        limits=range(estate_df$apr_price), 
                        low="#FCB9B2", high="#B23A48") + 
  theme(axis.line=element_blank(), 
        axis.text.x=element_blank(), axis.title.x=element_blank(),
        axis.text.y=element_blank(), axis.title.y=element_blank(),
        axis.ticks=element_blank(), 
        panel.background = element_blank()) # Clean Everything
estate_price

逐步解释:

 annotation_custom(rasterGrob(hk_map_bg, width=unit(1,"npc"), 
                               height=unit(1,"npc")), 
                    -Inf, Inf, -Inf, Inf) + 
  xlim(xlim[1],xlim[2]) + # x-axis Mapping
  ylim(ylim[1],ylim[2]) + # y-axis Mapping

annotation_custom 用于将准备好的地图背景图像导入到绘图中。 xlim(xlim[1],xlim[2])ylim(ylim[1],ylim[2]) 固定地块的 x 轴和 y 轴,使其与 map_bg 相同。

geom_point(aes(x=Longitude, y=Latitude, color=apr_price),size=2) + 
  scale_colour_gradient(name = '成交呎價(實)\n(HKD)', 
                        limits=range(estate_df$apr_price), 
                        low="#FCB9B2", high="#B23A48") +

geom_point 将房地产价格的数据点添加到绘图中。

scale_colour_gradient 根据变量“apr_price”用颜色填充数据点,请注意这里使用的函数与任务 1 中使用的不同。(几何点的比例颜色渐变,几何多边形的比例填充渐变

cyda 拍摄的照片

*# 3D Plot
library(rayshader)
plot_gg(estate_price, multicore = TRUE, width = diff(xlim)*10 ,height=diff(ylim)*10, fov = 70, scale = 300)# Close Windows
rgl.close()*

将 2D 图转换为 3D 图的脚本非常简单。3D 绘图显示在 rgl 窗口中。不过,看完剧情记得关窗。由于 rgl 窗口的输出不会被删除,所以下一个图将与前一个图重叠。

cyda 拍摄的照片

希望你喜欢我的文章=)

想了解更多使用 rayshader 的方法,请到 rayshader 的官网。

如果你觉得我的文章有用,请在我的 linkedIn 页面上为我的技能背书,鼓励我写更多的文章。

最初发表于cydalytics.blogspot.com

介绍一个新的 pySpark 库:owl-data-sanitizer

原文:https://towardsdatascience.com/introducing-a-new-pysparks-library-owl-data-sanitizer-bcc46e1583e6?source=collection_archive---------37-----------------------

在拥有复杂管道的公司中实现数据质量民主化的库。

托德·斯泰特勒在 Unsplash 上拍摄的照片

数据质量是公司打造优秀产品的重要组成部分,无论您的技术团队有多强大,或者您的数据团队有多有才华,当您的数据不一致或错误时,您最终会得到一个糟糕的产品。因此,研究发现,由于糟糕的数据,公司平均每年损失1500 万美元

3 Cs:数据质量可以定义为以下各项组合:

正确性:就内容和结构的不一致性而言,您的数据有多正确。

完整性:结果中是否缺少记录?

比较:我可以将我的全部数据与源数据进行比较吗?

因此,我们开始向数据团队提问,询问他们为保证数据集的整洁性而遵循的流程,发现了一些启示:

  • 当我们问及传达数据质量规则的流程时,回答是这样的:“我们分享。xls 文件和截图”上来了。他们最终会得到多个版本的规则和报告。
  • 在大多数情况下,开发人员不理解业务规则,业务人员也不能编写数据质量规则,这证明了缺乏透明度。此外,业务规则的变化意味着代码和部署的变化。
  • 大数据的数据质量管道有时需要很长时间,并且在实时管道中不可用。
  • 例如,对于实时管道或每天接收分区数据的管道,无法检测到重要的流量变化。例如,您接收交易,金额的总和在没有任何预期原因的情况下翻倍。
  • 数据协调过程意味着在 ETL 情况下将数据与源进行比较,或者在代码更改的情况下将生产阶段进行比较,这个过程是手动完成的。
  • 在创建每个管道验证规则后,开发人员平均损失 1-2 天。在一些例子中,他们花了 1.5 周来解决问题。

因此,我们发现了一个问题:我们必须通过使数据质量控制集中化、民主化和智能化,使其成为所有数据驱动团队不可或缺的一部分。

为了开始这个过程,我们分析了如何帮助开发人员完成这个耗时的验证任务。在我们的例子中,由数据工程师、数据科学家和全栈开发人员组成的不同团队编写的大多数管道使用 pySpark 作为 ETL 框架,然后我们确定了两个惊人的库来执行数据质量断言, deequgreat expectations。

因此,两个库都允许基于列操作的数据集验证更加容易和快速。尽管如此,我们仍然缺少一些东西,民主化:数据工程师将不得不在编写数据测试人员和业务人员不理解的质量规则的过程中,下面列出了我们需求的缺点:

规则是如何编写的

在我们的例子中,数据规则是由业务人员或数据测试人员编写的,然后他们交付一个带有规则定义的文件,这应该被翻译成 deequgreat expectationsasserts。因此,需要额外的开发工作。然后,下面的问题出现了:

Spark 接受 SQL,

数据测试人员编写 SQL,

从业务人员绘制 UI 生成 SQL 是可能的,

为什么如果我们使用 SQL 编写规则,并避免中间的过程。

注意:关于 pySpark 支持, deequ 只适用于 scala 版本。

如何调试报告中的错误

deequgreat expectations 都在每一栏提供结果。因此,在报告中,您会发现列验证中的错误和一些错误示例。

举个例子:

源数据集。

规则:列名在【a,b】。

结果:断言错误,错误示例:[c,d,e](前 20 个示例)

这些结果非常有用。然而,当处理大数据(其中不匹配的值可能有数百万)时,一旦发现断言失败,该报告不足以发现问题。因此,您必须转到源数据并执行行操作。是的…,a)在该列有这些错误值的地方获取一些 id,b)然后连接源数据集,c)查看数据集中的其他列,以检测其他记录不一致的地方。然后下一个问题出现了:

如果报表以矩阵形式显示每列和每行的结果会怎样?

按行报告。 1 有误差时, 0 干净时。

通过这种方式,您不仅可以计算每一列的错误,还可以计算整行的错误,以便于调试和修复错误。此外,您可以很容易地获得以下报告:每列的错误数,每列的错误示例,有错误的行数,有错误的示例 id。

重复数据删除

两种框架都通过计算一列中唯一值的数量来验证重复数据删除。然而,在大数据中,这主要是一个行操作,它意味着查看多个列的组合(例如, IDNAME )在同一个数据集中出现了多少次。出现了以下问题:

如果重复验证收到一组列怎么办?

有时使用模糊匹配发现重复项,然后:

有时需要什么样的模糊算子?

树形结构

我们没有找到一种方法来验证树结构,例如,列 PARENT_ID 并将其验证为数据集中的有效 ID

如何进行数据对比和对账

最后,一种应用校验和比较的方法是:

  • 当我们重构管道时,首先部署到阶段,并与生产中的数据进行比较。
  • 数据有时会与目标相比较。
  • 将数据与前一天/月的数据进行比较,以查看变化。

我们没有找到在现有框架上实现这一点的简单方法。

建造一座新图书馆

对于那些面临同样挑战的人,我们决定基于 pySpark 编写一个小型库,用于数据质量验证民主化owl-data-sanitizer

[## 罗纳德-史密斯-天使/猫头鹰-数据-消毒剂

验证数据质量的 pyspark 库。为 Ronald-Smith-angel/owl-data-sanitizer 的开发做出贡献,创建一个…

github.com](https://github.com/ronald-smith-angel/owl-data-sanitizer)

让我们看一个家庭数据集的例子。

家庭数据集。

基于简单 SQL 的验证

您需要验证的唯一输入如下。yaml 文件:

示例 yaml 文件。

在这个文件中,我们遵循 3Cs 的概念,并添加了额外的配置变量。

源表: 节用源表的元数据和路径来传递结果。目前与以下人员合作:

  • 输入和输出配置单元表。
  • 输入和输出 S3 铲斗。
  • 输入输出文件系统路径。

除此之外,这里还添加了我们之前解释过的重复数据删除列。

正确性验证: 正确性验证是使用简单的 SQL 编写的,您现在可以验证您用 SQL 编写的所有内容,框架会使用 spark 自动完成计算它们的神奇工作。

示例:

ADDRESS is not null and ADDRESS != '' and ADDRESS != 'null' and
CHAR_LENGTH(ADDRESS) > 4

父子验证: 如前所述,我们需要验证我们的树结构。

完整性验证: 要验证您的数据有多完整,您可以使用两个选项。

a) 根据源数据集的计数进行验证,这意味着一个简单的 SQL 规则。

b) 在分区或微批处理数据集中,您可以对照阈值(例如最大 10%)验证数据计数相对于前一个分区或批处理是如何增长的。

比较相关表: 如前所述,比较数据是为了核对或验证。

使错误调试更容易的报告

作为使用配置运行 spark 作业的结果,将提供以下报告:

a)正确性基于矩阵的每列/行报告,如前所述。

b)完整性显示数据完整性的报告。

c) 最后,一份对比报告。

当使用文件系统运行时,还会显示 HTML 报告。对于我们的示例,这些报告是这样生成的:

a)正确性报告。

该报告显示每列有多少个错误,有多少行有错误(9 行中有 8 行有 ,至少有 1 行验证失败 ),并始终保留 ID 用于调试。

b)规则计数≤ 5 的完整性报告,这意味着错误( 1 )。

最后,将它与样本 diff 数据集进行比较,显示数据不同的地方。因此,它们将是第二个数据集中没有的 IDs 6 和 7:

比较报告。

测试集群中的库

安装该库非常简单:

pip 安装 owl-sanitizer-data-quality

您可以按照这个小型单元测试的结构编写一个基本示例,其中您可以控制输出 spark 数据帧:

**test_rules** = {
    "CODE": """CODE is not null and CODE != '' and CODE != 'null'""",
    "NAME": """NAME is not null and NAME != '' and NAME != 'null'""",
    "GENERAL_ID": (
        "GENERAL_ID is not null and GENERAL_ID != '' and GENERAL_ID != 'null' and"
        " CHAR_LENGTH(GENERAL_ID) < 4"
    ),
    "ULTIMATE_PARENT_ID": """ULTIMATE_PARENT_ID is not null""",
    "PARENT_ID": """PARENT_ID is not null""",
}

**parent_rules** = [
    ("GENERAL_ID", "ULTIMATE_PARENT_ID"),
    ("GENERAL_ID", "PARENT_ID"),
]

**completeness_rules** = {"OVER_ALL_COUNT": """OVER_ALL_COUNT <= 7"""}

**validator** = **DataframeValidator**(
    spark=spark,
    source_df=source_df,
    id_col_name="GENERAL_ID",
    correctness_rules_dict=test_rules,
    parent_children_validation_pairs=parent_rules,
    completeness_rules_dic=completeness_rules,
    comparable_dfs_list=[
        ("diff_df", grid_diff_df),
        ("diff_df_2", grid_diff_2_df),
    ],
)

**processed_df** = validator.**process**()

**comparable_df** = validator.**compare**()

或者简单地说,使用配置文件交付结果:

**from** spark_validation.dataframe_validation.dataframe_validator import **CreateHiveValidationDF**
from spark_validation.common.config import **Config**

**spark_session** = SparkSession.builder.enableHiveSupport().getOrCreate()
with open(**PATH_TO_CONFIG_FILE**) as f:
        config = Config.parse(f)
**CreateHiveValidationDF**.validate(spark_session, config)

使用该库执行验证,从一个大的 Hive 表中读取结果并将结果传递给 Hive,随后将它们索引到一个超集仪表板上。

示例架构。

未来的工作

owl-data-sanitizer 为基础,仍然缺少一个组件,包括规则创建和报告通知方面的业务人员。然后,我们添加一个前端组件,数据团队,包括测试人员和业务人员,可以在其中拖放数据质量规则。

在企业中引入人工智能:数据科学家的视角

原文:https://towardsdatascience.com/introducing-ai-in-enterprise-a-data-scientists-perspective-2c4990da16ff?source=collection_archive---------49-----------------------

作者图片

通过经验获得的知识。

在我在 Safran 工作期间,我意识到虽然有很多文章在谈论 ML/AI 背后的数学和统计数据,但很少有的文章足够全面,能够提到很多人在将 ML 引入企业时会陷入的陷阱。

"理论上,理论和实践之间没有区别——实际上是有区别的。"

这一系列文章是为两类人准备的,年轻的我——知道机器学习和统计学的技术基础,从 Kaggle challenges 中获得了经验,但没有在没有为 ML 建立基础设施的大型组织中工作过的人——或者希望通过使用 ML/数据科学为他们的业务增加价值的人。

引入新技术时,有许多事情需要考虑。

在这一系列文章的结尾,你将会对如何做有一个了解,这可以作为开始任何 ML 项目之前的一个检查清单。

1.从小处着手。

“所有有效的复杂系统都是从有效的简单系统进化而来的。如果你想建立一个有效的复杂系统,先建立一个更简单的系统,然后随着时间的推移对其进行改进。”—高尔定律。

在你的公司引入人工智能时,重要的是选择一个小项目,然后从那里开始。这样做将有助于你发现局限性、增长领域、优势和其他探索的可能性。您将深入了解您的数据生命周期、部署策略、基础架构要求等,并避免代价高昂的错误。

2.确定利益相关者和最终用户并与之沟通。

找出哪些人会受到这些变化的积极/消极影响。

弄清楚每个利益相关者需要的沟通水平和频率,管理并设定期望,让他们明白最好从小处着手并快速取得成功,而不是一头扎进深水区而不知所措。在项目的不同阶段持续沟通。

对公司中的主要影响者/高层管理人员设定明确的期望。

3.计算引入 AI 的利弊和局限性。

识别收益和风险有助于管理和设定预期,避免不履行。这里有一些你可以考虑。

不利因素:数据困难、技术问题、技能短缺、整合挑战。

优点:提高流程的整体效率,减少重复性任务中的人为错误,优化内部业务运营,帮助开拓新市场,实现重复性任务的自动化,让员工能够专注于其他问题领域。

限制:模型可解释性(根据使用的算法可能是一个挑战,这可能导致缺乏透明度)。必须对模型进行配置,以适应随时间变化的数据。

4.要有数据策略。

在 ML 领域有一个流行的谚语“垃圾进,垃圾出”,意思是你的模型和你放进去的数据一样好。

您必须确保满足数据质量、数量和安全性的要求。

在许多公司中,随着政策和法规的变化,收集数据的方法也在变化。很多时候,在某个时间点可能有用的东西可能不再有用了。

拥有一个健壮的数据管道有助于解决这类问题。

5.认识到操作的必要性。

一个有效的项目有各种各样的促成因素,例如计算硬件、为员工提供所需的技能和工具的培训、建立开发环境。

6.实施变革管理。

不幸的是,当许多人听到“人工智能”时,他们会想象机器人来接管他们的工作。

在界定人工智能是被视为“取代我们的工作”还是“通过消除我们工作中更单调的部分来解放我们”的过程中,管理发挥着关键作用。

让人们接受人工智能,并帮助他们期待它将为他们带来的切实利益。对于管理层来说,理解如何将人工智能融入到他们的流程中,并对此有一定的热情是很重要的。如果做不到这一点,就会在各个层面产生涓滴效应,导致抵制和不信任。

教育是采纳的关键,你可以采取一些措施来确保这是务实和深思熟虑的。

7.整合领域专家和数据科学团队。

任何长期运行的/遗留的系统在收集和处理数据的方式上都有很多怪癖,这些领域知识会对项目的成功产生巨大的影响。

部署一个人工智能系统的先决条件是需要对系统将要运行的领域有一个透彻的理解。领域专家提供决定项目成败的关键见解。

领域专家将不得不花费额外的时间来帮助你的 ML 团队理解过程的特殊性和变通方法,也可能不得不通过帮助制定数据集来投入。

他们还将确保所收集的关于该领域的数据是可信的,是洞察的基础。

8.在重新定义你的目标和里程碑时进行沟通。

随着项目的进展,你会发现实现目标的新方法,甚至可能最终修改最终目标。你可能会发现你计划好的事情不再是可行的前进方式。

除此之外,对已有流程的任何改变都将破坏通常的流程,你也必须对此负责。

与利益相关者沟通所有这些变化是至关重要的。

9.定义衡量项目成功/失败的标准。

保持所有利益相关者的参与对于项目的发展方向是非常重要的。如果你有一个所有利益相关者都理解的好的度量标准来量化你的成功,你就可以更容易地交流所取得的进展

10.确定人工智能在你的组织中的位置。

不同的公司使用不同的数据科学团队结构;有些公司的每个部门都有一名数据科学家,有些公司有一个统一的数据科学部门,而其他公司则是两者的混合体。

需要考虑的是,人工智能将在什么水平上增强您的流程,哪些部门将从引入中受益最多,从而以相对较低的努力产生较高的影响。

最终,你会发现什么对你有用,但重要的是要有最终目标。

11.有长远的眼光。

对公司未来的状态有一个愿景是非常重要的,综合上述所有要点。你将采取的步骤可能会有所不同,很有可能愿景也是如此。

随着你的发展和意识到对你的组织来说什么是必要的,肯定会有修改,但是只要你有一个看得见的最终目标,它就会阻止你在原地打转。

简单地遵循这 11 个步骤将帮助你在首次引入人工智能时避免许多陷阱。虽然所有这些步骤听起来很简单,但不要混淆简单和容易。

在以后的文章中,我计划详细阐述这个高层次的概述。要了解最新消息,你可以订阅我的时事通讯

你也可以在推特 @akshanarayan 上和我联系。

引入人工智能产品组合

原文:https://towardsdatascience.com/introducing-ai-powered-portfolio-4ac820fbcfeb?source=collection_archive---------20-----------------------

以及如何建立一个一步一步的教程!

Natasa Grabovac 在 Unsplash 上拍摄的照片

我的投资组合似乎太静态了。我应该做些什么来使它更具互动性和趣味性,同时还能应用我的 NLP 知识呢?

最近,我刚刚开发了一个人工智能投资组合,旨在提升我的静态网络投资组合。我嵌入了一个个人人工智能助手,它可以回答你关于我的问题,当然,有正确的反应!

无论你是招聘人员、同事,还是网上的任何人,如果你问“他”正确的问题,你会更了解我! (PS:“他”几乎知道我的一切)。

在这里随意与我的私人 AI 助手互动。在这篇文章中,我将给出一个如何开发自己的个人 AI 助手的分步教程。你所需要的只是 HTML、JavaScript 和 CSS!

引擎

在进入教程之前,让我向你介绍一下这个人工智能组合中使用的引擎:语义反应器USE-lite tensor flow-JS for QnA

卢卡斯·范·奥尔特在 Unsplash 上拍摄的照片

语义反应器

第一个引擎,语义反应器,是实验引擎。基本上,它是谷歌的一个插件,可以添加到你的谷歌表单中。它是用来做什么的?

为了展示使用 NLU 有多简单,我们创建了一个名为语义反应器的工具,它使用预先训练的语言模型,提供不同的排名方法,并具有一些高级功能。—谷歌人工智能

换句话说,这个附加组件为您提供了预先训练好的模型,可以随时用于您的实验!您可以将这些模型用于问答任务或测量语义相似度。

甚至有一些创新的游戏使用这个工具作为他们的实验引擎!

  1. 三个机器人之谜
  2. 塞曼特里斯
  3. 与虚拟的人工智能狐狸互动

你可以在这里和阅读更多关于语义反应器的内容。

将-Lite Tensorflow-JS 用于 QnA

第二个是部署阶段使用的主引擎。在我解释更多关于这个主引擎的信息之前,我先告诉你一点关于使用和 USE-Lite 模型的信息。

通用句子编码器(使用)是将任意给定的句子转换成 512 维句子嵌入的模型。然后,这些转换后的嵌入可以用作许多 NLP 任务的输入,例如文本分类、文本相似性分析、问答等等。

顾名思义,USE-Lite 只是原始使用模型的一个轻量级版本。

当您的计算资源有限时,这个精简版本非常适合使用。例如,设备上的推断。它很小,但在各种自然语言理解任务中仍然有很好的表现。— Tensorflow Hub 文档

最后,USE-Lite tensor flow-JS for Question/Answering 是一个将问答文本编码成 100 维嵌入的轻量级模型。

使用文件中所述,使用模式有两种变体。第一个使用深度平均网络,而第二个使用变压器架构。这里使用-Lite Tensorflow-JS 进行问答,使用 Transformer 作为其基础架构。

怎么会?

有 6 个步骤,你必须做,以建立自己的个人人工智能助理,我会指导你的每一个步骤!

1.从 G 套件市场安装“语义反应器”附加组件

你可以简单地从这里安装插件。确保您使用与 Google Sheets 帐户相同的 Google 帐户来安装附加组件。

语义反应器页面。[作者截屏]

2.在谷歌表单中列出所有可能的回答

安装完 Semantic Reactor 附加组件后,您可以打开 google sheets,然后列出所有可能的响应。

我可能的反应的例子。[图片由作者提供]

我可以建议你的一个小技巧是根据主题生成几个回复列表。

在我的例子中,我生成了六种不同的回复列表,其中一种是一般的回复列表,其余五种都是针对与我的专业工作经历相关的回复( Traveloka、Tokopedia、Do-It、Qlue Smart City、World Bank )。

3.启动“语义反应器”附加组件

一旦您列出了所有可能的响应,您就可以启动语义反应器插件了。

启动语义反应器插件。[图片由作者提供]

4.选择“本地”模型和“输入/响应”等级方法

如前所述,附件提供了几个预先训练好的模型。这里,我们将选择“本地”模型,因为它与我们将在部署阶段使用的模型相同。

我们必须选择“输入/响应”等级方法,因为我们将在 QnA 任务中使用此附加组件。

模型和排序方法选择。[图片由作者提供]

5.根据给“语义反应器”的查询来改进你的回答

最有可能的是,您的第一组可能的响应不能支持预先训练的模型为给定的查询返回合适的答案。实际上,我们可以尝试从数据集中预先训练的模型进行迁移学习。

但在这种情况下,我认为更明智的做法是提炼我们可能的反应,而不是花费我们的时间和硬件资源来进行迁移学习。正如阿尔伯特·爱因斯坦所说:

“让一切尽可能简单,但不要更简单。”

因此,你可以不断改进所有可能的答案,直到你看到结果足够好。

给定查询时可见。[图片由作者提供]

6.将 TensorFlow-JS 使用 Lite 模型嵌入到 HTML 文件中

一旦您确定了可能的响应列表,就可以在部署中使用该列表。语义反应器中的“本地”模型是一个通用的句子编码器精简模型,这是我们将在部署中使用的引擎。

首先要做的是从 CDN 加载 TensorFlow-JS 并使用模块。

然后,您可以定义函数,在给定查询的情况下,从响应列表中选择最佳响应。

最后,我们必须根据给定的查询选择要使用的函数或要使用的响应列表。我在这里使用了关键字匹配方法来选择我们应该使用的响应列表。

我用来构建这个个人人工智能助手的所有主要代码都基于以下三个来源:

  1. https://github . com/tensor flow/tfjs-models/blob/master/qna/demo/index . js
  2. https://github . com/tensor flow/tfjs-models/tree/master/universal-sentence-encoder
  3. https://github . com/Google/making _ with _ ml/blob/master/semantic _ ml/use _ sample . js

最后的话

Recal MediaUnsplash 上拍摄的照片

恭喜你坚持到了这一步!希望这篇文章发表后,我可以看到许多新的人工智能投资组合的开发。

如果你喜欢我的内容,请关注我的媒体账户,以获得我未来其他帖子的通知。在接下来的 3 个月里,我还会做一个关于强化学习的系列文章。你可以在这里查看第一篇

关于作者

Louis Owen 是一名数据科学爱好者,他总是渴望获得新知识。他获得了最后一年的全额奖学金,在印度尼西亚最好的大学之一Institut Teknologi Bandung攻读数学专业。最近,2020 年 7 月,他刚刚以优异的成绩从他的研究中毕业。

Louis 曾在多个行业领域担任分析/机器学习实习生,包括 OTA(Traveloka)、电子商务( Tokopedia )、fin tech(Do-it)、智慧城市 App ( Qlue 智慧城市 ),目前在 世界银行 担任数据科学顾问

查看路易斯的网站以了解更多关于他的信息!最后,如果您有任何疑问或要讨论的话题,请通过 LinkedIn 联系 Louis。

介绍亚马逊 SageMaker

原文:https://towardsdatascience.com/introducing-amazon-sagemaker-8061d0fc476d?source=collection_archive---------39-----------------------

说到 SageMaker

面向云的解耦数据科学解决方案

https://www . pexels . com/photo/白天蓝天白云下的玉米田-158827/

电脑。它们是棘手的事情——有些日子你会觉得不够,有些日子你会觉得比你需要的更多。您可能认为您只是在安装一个新的开源项目,但是四个小时后您仍然在和安装经理争论。你有一个很好的模型,但是没有一个框架来把它构建到应用程序中。现在,让我们重新想象一下这种体验,但是要使用专门为您构建的工具。欢迎,亚马逊 SageMaker。

亚马逊 SageMaker 是来自 AWS 的全托管机器学习解决方案。它将您的环境从开发、培训和部署中分离出来,使您能够分别扩展这些环境,并优化您的支出和时间。世界各地成千上万的开发人员正在以各种方式采用 SageMaker,有时是为了端到端的流程,有时是为了扩大培训工作,有时是为了死一般简单的 RESTful API 集成。在这里,我将带你了解我称之为 SageMaker classic 的主要方面,或者 SageMaker 的基本要素。

SageMaker 提供了一个托管的开发环境

SageMaker 从一个 notebook 实例开始,这是一个 EC2 实例,专门用于运行 Jupyter、您的环境以及您进行特性工程所需的任何额外代码。笔记本实例会自动配置您的 AWS 凭证,如 boto3 和 aws cli,因此您只需几行代码就可以轻松连接到您在 S3、红移、RDS、DynamoDB、Aurora 或任何其他位置的数据。为了将访问从您的笔记本实例扩展到其他 AWS 资源,只需确保更新分配给您的笔记本实例的 ExecutionRole。

SageMaker 笔记本实例

亚马逊 SageMaker 上的笔记本实例

SageMaker 提供了运行 Jupyter 的完全托管的 EC2 实例,有 10 多个环境、1400 多个包和数百个示例。

最好在一个较小的 EC2 实例上启动您的笔记本,一般来说 ml.t2.medium 是一个不错的选择。这是一台笔记本电脑每小时可以获得的最低金额。

但是一旦你开始钻研你的特性工程,当你意识到你实际上需要一个更大的实例或者更多的磁盘空间时,你可以轻松地调整托管你的笔记本的 EC2 实例的大小。你需要关闭它,更新设置,然后再次打开它。往返 7 分钟,但非常值得。

不要忘记关闭您的笔记本电脑,因为费用是按小时计算的,而不是按次计算的。通常最好是 实现一个 Lambda 函数来自动关闭这些 ,要么基于一天中的某个时间,要么根据笔记本本身的使用情况。

SageMaker 专门为您的每一款车型提供集群

现在有趣的部分来了——你可以在训练的时候为你的每个模型获得专用的 EC2 实例。这些被称为训练作业,无论你是使用 17 种内置算法中的一种,在 Docker 容器中引入自己的模型,还是在脚本模式下使用 AWS 管理的容器,你都可以配置它们。

亚马逊 SageMaker 上的培训工作

亚马逊 SageMaker 上的培训工作

关于你的培训工作的所有细节都被发送到 CloudWatch,并且你的模型工件在完成后被存储在 S3。

每个训练作业在 SageMaker 上都配置了一个 估算器 ,需要使用 17 种内置算法中的一种,没有任何限制。它们可能提供一些时间优势,因为通过使用它们,您编写的代码更少,但是如果您更喜欢使用 TensorFlow、MxNet、PyTorch、Sci-kit Learn 或任何框架来创建自己的模型,SageMaker 提供了一些示例来看看这是如何工作的

每个训练作业都记录在 AWS 控制台中,因此您可以很容易地看到您使用了哪个数据集、它在哪里、模型在哪里以及客观结果,甚至在您完成 6 个多月后也是如此。

SageMaker 会围绕您的模型自动创建一个 RESTful API

在别的地方训练你的模特?别担心!实际上,你可以把任何预先训练好的模型放在 SageMaker 上——只要你能把它放在 Docker 容器中,你就可以在 SageMaker 上运行它。

https://AWS . Amazon . com/blogs/machine-learning/load-test-and-optimize-an-Amazon-sagemaker-endpoint-using-automatic-scaling/

使用 SageMaker 围绕任何模型创建 RESTful API

如果您在脚本模式托管容器支持的框架中引入模型,AWS 会为您实现 API。

初始化您的端点的所有资源需要 7 分钟以上,所以如果您看到端点显示“Pending”状态,请不要担心如果您将它投入生产以响应常规流量,那么最好为高可用性 API 设置至少两个 EC2 实例。这些将位于 AWS 管理的负载平衡器之后,位于 API 端点本身之后,API 端点可以连接到接收应用程序流量的 Lambda 函数。

保持开启的端点也会变得昂贵,因此确保 实现一个 Lambda 函数 ,以便在它们不在生产环境中时定期关闭它们。您可以在这里随意试验,选择一个更小的 EC2 实例,但是仍然能够满足您的需求。端点自带自动扩展功能,您只需配置和负载测试这些

SageMaker 记录你所有的资源

默认情况下,SageMaker 会在控制台中为您记录所有培训作业、端点和超参数调整作业。每个作业都会向 CloudWatch 发出指标,因此您可以近乎实时地查看这些指标,以监控您的模型的训练情况。此外,通过 SageMaker Studio 提供的改进,您可以建立实验并监控这些实验的进展。

SageMaker Studio 提供实验管理,方便查看和跟踪项目进展。

在 SageMaker 中创建了一个实验之后,只需点击一个按钮,所有与之相关的作业就会在 Studio 中显示出来。

SageMaker Studio 在 re:Invent 2019 上公布,目前仍在公开预览中。这意味着 AWS 仍在微调解决方案,随着他们的开发,可能会有一些变化。因为预览版是公开的,任何拥有 AWS 帐户的人都可以在美国东部 2 区或俄亥俄州开设工作室,并开始使用。

资源

AWS 在机器学习方面的资源正呈爆炸式增长。GitHub 上为 SageMaker 托管了 250 多个示例笔记本,就在这里。数百个培训视频可供不同角色和经验水平的人免费使用点击这里。如果你想深入了解这篇文章中的任何内容,我亲自经历了在一个 11 视频系列中概述所有这些功能的麻烦,在这里主持。看看吧!

默认情况下,SageMaker 存在于每个 AWS 帐户中。你也可以创建自己的 AWS 账户,并在免费等级中进行实验。

黑客快乐!在 LinkedIn 上随时联系——我喜欢听你在自己的机器学习冒险中如何实现 SageMaker 的成功故事,所以继续吧!

维恩图 Python 包:Vennfig

原文:https://towardsdatascience.com/introducing-basic-venn-diagram-python-package-vennfig-fa3f8e4dcb36?source=collection_archive---------35-----------------------

在 Jupyter 或 Terminal 上用一行代码画一个维恩图

作者图片

**Table of Contents**[**Introduction**](#19c2)1\. [Installation:](#79a1)
2\. [Default Functions](#6842)
3\. [Parameters](#bc07)
4\. [A, B Venn Diagram](#d255)
5\. [A AND B, A NAND B Venn Diagram](#266d)
6\. [TRUE, FALSE Venn Diagram](#6746)
7\. [OR, NOR Venn Diagram](#4e16)
8\. [XOR, XNOR Venn Diagram](#d4dd)
9\. [NOT A, NOT B Venn Diagram](#3fd9)
10\. [A NOT B, B NOT A Venn Diagram](#fdf0)
11\. [Implication Venn Diagram](#a981)
12\. [Mutually exclusive Venn Diagram](#e045)
13\. [Complement Venn Diagram](#7fbc)
14\. [Subsets Venn Diagram](#36b7)
15\. [Terminal](#ce5a)[**Conclusion**](#18bf)

介绍

在上一篇文章中,我展示了如何使用[matplotlib_venn](https://github.com/konstantint/matplotlib-venn)绘制基本的维恩图。

每个图需要 40 行代码,所以我创建了我的第一个 Python 包,名为 Vennfig 。你可以用一行代码画一个基本的维恩图,但是足够灵活以满足你的需要。

安装:

您可以使用pip安装它:

pip install vennfig

在 Jupyter 上:

!pip install vennfig

你需要进口vennfig

import vennfig as v

默认功能

所有的 vennfig 函数。

下表显示了您可以使用的所有功能。

除了subsetsmut_exclusive函数,所有默认函数都显示两个维恩图,例如 A 和 B,A 和 B。

它们有默认的颜色、大小、字体大小、标题等。

因素

参数允许你修改你的文氏图。你可以在每个源代码中找到参数的描述。

示例:

import vennfig as v
v.a_b(subs=2, size=6, fill_color='#f5b705', bg_color='#f7edd0', 
    font_size=25, title_a='P', set_a='P', set_b='Q')

参数名称

subs 你想要显示的文氏图的标识符。

-1:默认(两者)
-2: A
-3: B

大小
Matplotlibfigsize。默认值为 15。

fill_color 默认颜色为‘天蓝色’。您可以使用其中一个字符{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'},它是蓝色、绿色、红色、青色、品红色、黄色、黑色和白色的缩写。您也可以使用十六进制 RGB 或 RGBA 字符串(例如,'#4287f5''#4287f580')。

BG _ color bg_color设置 matplotlib 的 facecolor,即背景色。

默认为'white'

font _ size
标题字体大小。默认为20

标题 _ a
左侧文氏图的标题。

标题 _b 标题为右侧文氏图。

set _ a
左侧设置标签。默认为'A'

设置 _b 右侧设置标签。默认为'B'

text_size 设置文本字体大小。默认值为 15。

让我们看看画维恩图有多容易。

[## 如何在 Docker 上运行 Jupyter 笔记本

不再有 Python 环境和包更新

towardsdatascience.com](/how-to-run-jupyter-notebook-on-docker-7c9748ed209f) [## 如何在 Jupyter 上画维恩图

使用 Matplotlib-Venn 的所有基本逻辑文氏图

towardsdatascience.com](/how-to-draw-venn-diagrams-on-jupyter-75c604b093ac)

文氏图

请在源代码中找到更多细节。

a、B 默认文氏图

a、B 维恩图设置参数。

A 和 B,A 和 B 维恩图

请在源代码中找到更多细节。

A 和 B,A 和 B 默认维恩图。

a 和 B 默认文氏图设置参数。

真假文氏图

请在源代码中找到更多详细信息。

真,假默认文氏图。

真实维恩图设置参数。

或,或非文氏图

请在源代码中找到更多细节。

也不是默认的维恩图。

NOR 维恩图设置参数。

异或,XNOR 文氏图

请在源代码中找到更多细节。

异或,XNOR 默认文氏图。

XOR 文氏图设置参数。

不是 A,不是 B 文氏图

请在源代码中找到更多细节。

不是 A,不是 B 默认文氏图。

不是 Q 维恩图设置参数。

A 不是 B,B 不是维恩图

请在源代码中找到更多细节。

A 不是 B,B 不是默认的维恩图。

P NOT Q 维恩图设置参数。

蕴涵维恩图

请在源代码中找到更多细节。

隐含默认文氏图。

Q ⇒ P Venn diagram setting parameters.

互斥文氏图

请在源代码中找到更多细节。

互斥默认文氏图。

互斥文氏图设置参数。

互补文氏图

请在源代码中找到更多细节。

补充默认文氏图。

补充文氏图设置参数。

子集文氏图

请在源代码中找到更多细节。

子集默认文氏图。

子集文氏图设置参数。

末端的

你可以用终端创建一个文氏图。

在终端上运行 vennfig。

您也可以使用pan来移动图表。

终端的输出

结论

让我知道你的想法。你可以在这里找到 Github repo。

请继续关注下一篇文章。

通过 成为 会员,获得媒体上所有故事的访问权限。

https://blog.codewithshin.com/subscribe

介绍 Company2Vec

原文:https://towardsdatascience.com/introducing-company2vec-helping-company-analysis-with-machine-learning-c6790d7a6bf5?source=collection_archive---------41-----------------------

数据科学/机器学习

用机器学习帮助公司分析

TLDR : 我在 Github 上为数据科学家创建了一个包,可以从公司名称生成一个公司的矢量嵌入图——详情请见 此处

开发包装的动机

几年前,我在一家做大量简历分析工作的公司担任机器学习的角色。我的任务是编写一个算法,根据一个人的简历预测他的下一个职位(详情见)。虽然我的算法不包括公司的推荐,但我很好奇它们是如何被包括在内的。我很快意识到这是一个非常困难的问题,公司里与我交谈过的其他人也证实了这一点。

从许多简历来看,原因显而易见。同一个公司可以有多种不同的写法。为巴克莱银行工作的人可以在他们的简历上输入“巴克莱”/“巴克莱银行”/“巴克莱资本”/“巴克莱资本”/“巴克莱银行”等等中的任何一个。但这仅仅是问题的开始。如何处理子公司?如何处理品牌名称与其有限公司名称不同的公司?缩写呢?

以类似的方式,过了一段时间,我在一家大型制造公司工作,该公司希望使用机器学习来帮助他们的销售线索生成。当我查看他们的现有客户名单时,我意识到同样的问题也存在。

什么是向量嵌入?

在任何下游机器学习任务中分析公司的最佳方式是创建公司向量嵌入。但是什么是向量嵌入呢?

嵌入是离散—分类—变量到连续数字向量的映射。例如,单词“book”可以用向量(1,2,3)来表示。这非常有用,因为它最多可以做 3 件主要的事情:

  1. 识别相似的单词/实体。例如,识别单词“cat”与单词“kitten”非常相似。
  2. 机器学习任务的输入,特别是自然语言处理
  3. 对于概念和类别之间关系的可视化——你能在下面的图片中看到相似的单词之间有相似的向量关系吗?

那么什么时候公司矢量嵌入会有用呢?下面是一些潜在的用例(当然还有很多)。

  1. 潜在客户——寻找与你过去的销售对象相似的公司
  2. 映射不同公司之间的关系(例如,客户-供应商关系)
  3. 分析同行业公司之间的差异
  4. 工作推荐
  5. …以及许多其他下游机器学习任务!

包装详情

为了帮助解决这个问题,我开发了一个 python 包来生成公司矢量嵌入——见这里的包和如何使用它的详细说明

照片由克莱门特 HUnsplash 上拍摄

在大多数情况下,你可能会想用这个,我认为你会有一个公司名称。鉴于缩写/首字母缩略词等的所有问题,该软件包使用一个搜索 API(每月最多 1000 次免费请求)来查找给定公司名称的公司网站。然后,该软件包使用 scrapy 对网站进行一次广泛而浅显的搜索。然后,将抓取的文本与预训练的手套向量嵌入相结合,以创建公司嵌入。

该软件包有两种用途。首先,有一个“快速启动”功能,可用于快速试验该包。如果你想大规模使用它,有一个 Klein web 应用程序和一个 Dockerfile(顺便说一下,由于 scrapy 的多线程工作方式,必须使用 Klein 而不是 Flask)。这可以用来封装一个 web 应用程序,然后部署到云上。

在以下情况下,此软件包工作正常:

  • 您不想付费访问公司信息数据库/没有时间根据该数据库的公司条目标准化名称
  • 这些公司通常用缩写形式表示。
  • 这些公司的网站大部分都是相当静态的内容,并且很好地概述了公司的业务

此包的限制

然而,这个包肯定不是完美的,是一个正在进行的工作。在以下情况下,它的效果不太好:

  • 如果大部分网站内容没有描述该公司,例如新闻网站
  • 如果没有网站(显然……)
  • 如果一家大公司使用相同的缩写/名称,使用缩写的小公司可能会很难被选中。

同样值得记住的是,如果网站上的大部分文本频繁更新,那么每次运行包时嵌入都会改变,影响您的下游分析。

结论

如果你是一名数据科学家,并在过去努力有效地分析公司,希望你会发现这很有用。一定要让我知道你的想法,并为帮助开发这个包做出贡献!

介绍 GeneAl:一个遗传算法 Python 库

原文:https://towardsdatascience.com/introducing-geneal-a-genetic-algorithm-python-library-db69abfc212c?source=collection_archive---------10-----------------------

在这篇文章中,我将介绍 GeneAl ,这是一个用遗传算法(GA)解决优化问题的 python 库。在这个过程中,我们将了解它们背后的理论,并通过 python 示例了解它们是如何工作的。

图片由阿雷克索查通过皮克斯巴伊

遗传算法(GA)是一种基于遗传学和自然选择原理的优化和搜索技术,本质上是模仿我们在生活中观察到的自然进化过程。他们的一般原则是基于这样的概念,即拥有一个由几个个体组成的初始群体,每个个体代表问题的一个特定解决方案,并允许它进化到一个最大化其整体适应度的状态,使用三个主要算子:选择交叉变异。我们将在下面更详细地研究这些方面。

遗传算法简直不可思议,因为它们可以应用于多种优化问题,并找到我们没有数学表达式的复杂函数的解决方案。然而,这是以计算复杂性为代价的,因为对于庞大的群体,我们必须评估每一代所有个体的适应度。如果适应度函数是昂贵的,算法运行将是缓慢的。

遗传算法可以分为二元连续,这取决于我们正在优化的问题的类型。潜在地,所有问题都可以被分解为用二进制串表示它们的变量(基因),但是一般来说,如果输入空间是实值的,那么使用连续 GA 更有意义。

由于连续 GA 的例子很少,这里显示的例子是针对 GA 版本的。

初始化

搜索从随机的 N 个个体开始。这些个体中的每一个都对应于一条染色体,它编码了一个基因序列,代表着我们试图优化的问题的特定解决方案。根据手头的问题,代表解决方案的基因可以是位(0 和 1)或连续的(实值)。下面显示了一个实值染色体的例子,它代表了一个具有 9 个变量(基因)的给定问题的解决方案。

个体染色体的例子

健身

每个个体的适应度定义了我们要优化的内容,因此,给定一个编码特定问题解决方案的染色体,其适应度将对应于特定个体作为问题解决方案的表现。因此,其适应值越高,该解决方案就越最优。

毕竟,个体的适应度分数是经过计算的,它们是经过排序的,因此可以选择最适应的个体进行交叉。

选择

选择是选择一定比例的个体相互交配并创造新后代的过程。就像现实生活中的自然选择一样,更健康的个体有更高的机会存活下来,因此,将他们的基因传递给下一代。虽然存在有更多个体的版本,但是通常选择过程匹配两个个体,创建成对的个体。有四种主要策略:

配对:这可能是最直接的策略,因为它只包括将最适合的染色体两两配对(将奇数行与偶数行配对)。

随机:这种策略包括从交配池中随机选择个体。

轮盘:这种策略也遵循随机原则,但是更健康的个体被选中的概率更高。

锦标赛:采用这种策略,算法先选出几个个体作为候选(通常是 3 个),然后选出最适合的个体。该选项的优点在于,它不需要首先按照适合度对个体进行分类。

下面的代码片段显示了轮盘策略的 python 实现。

交叉

这是产生新后代的步骤,新后代将取代种群中最不适合的个体。杂交个体背后的想法是,通过组合不同的基因,我们可能会产生更健康的个体,这将是我们问题的更好解决方案。或者没有,在这种情况下,这些解决方案不会延续到下一代。

为了执行实际的交叉,来自选择步骤的每一对被组合以产生两个新个体,这两个新个体都具有来自父母中每一个的遗传物质。执行交叉有几种不同的策略,所以为了简洁起见,我们只讨论其中一种。

假设我们有一个由 9 个变量定义的问题,如果我们有 2 个父母,我们随机选择交叉基因作为索引 3,那么每个后代将是每个父母的组合,如下图所示。

显示双亲如何杂交产生新后代的图表

每个后代的交叉基因根据以下规则计算:

计算新交叉基因的方程式

其中 β 将是 0 和 1 之间的随机数。下面给出了交叉的 python 代码。

突变

变异是我们在群体中引入新的遗传物质的过程,允许算法搜索更大的空间。如果没有突变,群体中现有的遗传物质多样性不会增加,而且由于一些个体在世代之间“死亡”,实际上会减少,个体倾向于非常快地变得非常相似。

就优化问题而言,这意味着在没有新的遗传物质的情况下,该算法可以在探索足够大的输入空间以确保我们可以达到全局最优之前收敛到局部最优。因此,变异在保持种群多样性方面发挥着重要作用,并使其进化为更适合问题解决方案的

我们可以做到这一点的最简单的方法是,给定一定的突变率,随机选择一些个体和一些基因,并为这些位置分配一个新的随机数。下面的图表和代码片段对此进行了举例说明。

个体中两个基因的突变

解算器

现在是时候把这一切联系起来了。使用我们上面定义的操作符,该算法现在可以解决这个问题,只需几行代码就可以实现该算法的实际主循环。该算法的流程图以及 python 中的示例实现如下所示。

遗传算法的流程图

介绍通用

GeneAl 是一个实现遗传算法的 python 库,可以用来解决许多优化问题。您可以使用提供的现成解算器类—binarygenalsolvercontinuousgenalsolver——或者创建一个从其中一个继承的自定义类,并实现覆盖内置方法的方法。它还支持解决著名的旅行推销员问题。

为了简洁起见,我们将只看到如何使用连续版本——与本文保持一致——但是要了解更多细节,请查看该项目的自述文件。

第一件事是安装软件包,这可以通过pip完成,如下所示:

pip install geneal 

安装完成后,就可以开始使用了。所以让我们看看如何使用continuousgenalsolver类。

作为最低要求,该类要求用户提供问题中存在的基因数量,以及提供自定义的适应度函数。为了方便起见,该库提供了一些可用于测试的默认适应度函数。

完成上述初始化后,该类将使用所有参数的默认值来解决问题。如果我们希望对算法运行有更多的控制,我们将希望调整这些,这可以如下所示:

最后,这个类允许用户指定问题的类型(如果可能的值是整数或浮点数)以及变量的限制,以便限制搜索空间。

这就完成了对这个库的简短介绍。如果你想知道更多,查看一下 GitHub 库,那里有更多的信息:)

感谢阅读!

引入广义积分梯度(GIG)

原文:https://towardsdatascience.com/introducing-generalized-integrated-gradients-gig-ecad6a03d77f?source=collection_archive---------23-----------------------

一种解释不同集成机器学习模型的实用方法

布莱克·惠勒在 Unsplash 上拍摄的照片

  • 集成机器学习模型 比单个 ML 模型单独提供更高的预测准确性 和稳定性,但集成模型很难用普通的可解释方法来解释和信任。
  • Zest AI 开发了一种新方法来解释复杂的集成模型,称为广义集成梯度,使它们可以安全地用于高风险应用,如信用风险承保。与其他方法不同,GIG 直接遵循一小组合理的规则,不需要任何武断的假设。

为什么需要新的信用分配方法

在全球经济中部署机器学习的所有方式中,影响最大的应用之一是信贷承销。机器学习被证明可以更好地预测借款人违约,增加需要贷款的人获得信贷的机会,并减少贷款中的偏见。但并不是所有的机器学习技术,包括监管较少的应用中的大量技术,都是透明的。许多被部署的算法会产生难以解释的结果。最近,研究人员提出了新颖而强大的方法来解释机器学习模型,特别是 Shapley 加法解释 (SHAP 解释者)和积分梯度 (IG)。这些方法提供了为模型用来生成分数的数据变量分配信用的机制。他们通过将机器学习模型表示为一个游戏来工作:每个变量都是一个玩家,游戏的规则是模型的得分函数,游戏的价值是模型给出的分数。合作博弈中的信用分配是一个众所周知的问题。

SHAP 使用各种方法来计算沙普利值,这在原子游戏中很有效,通过重新计算模型的结果来识别最重要的变量,每个变量都被系统地删除。当算法是一个神经网络,它运行无限小的小游戏,这些小游戏中没有一个是单独重要的,但它们在总体上是重要的,你需要积分梯度来解释一个模型。IG 使用 Aumann-Shapley 值来了解两个申请人之间模型分数的差异。它量化了每个输入变量对模型得分差异的贡献。毕竟,根据模型,有些变化比其他变化更重要,因此我们的任务是衡量模型认为哪些变化更重要或更不重要。

这两者本身都是伟大的创新,但都没有为实现最佳结果的混合型模式提供令人满意的信用分配。SHAP 包中实现的解释器要么要求变量在统计上是独立的,要么要求缺失值可以用平均值代替。这两者都不是金融服务业的新手。IG 要求模型处处可微,这对于决策树来说是不正确的,所以它只对像神经网络这样的模型有效。

谷歌、脸书和微软等大型科技公司多年来一直在利用集成 ML 的优势。他们使用树和神经网络以及一整套建模数学来构建模型,但他们不像金融服务公司那样在相同的监管约束下运营。银行和贷款机构将从将这些同类高级模型用于信贷承销和欺诈检测等应用中获益匪浅。(查看我们的最近的帖子介绍了一种叫做深度堆叠的新方法,这种方法为一家小型贷款机构带来了 1300 万美元的利润和一个更准确、更稳定的模型。)

所有的箭头都指向需要一种新的方式来解释复杂的、集合的 ML 模型,用于高风险的应用,如信贷和借贷。这也是 Zest AI 开发 GIG 的原因。

引入广义综合梯度

广义积分梯度 (GIG)是一种新的信用分配算法,它通过应用测度理论的工具,克服了 Shapley 和 Aumann-Shapley 的局限性。GIG 是 IG 的正式扩展,它可以为更广泛的模型准确分配信用,包括目前在机器学习领域使用的几乎所有评分功能。GIG 是严格计算每个变量对不同模型集合的贡献的唯一方法。

GIG 更好地解释复杂的 ML 模型是因为它避免了对数据做出不切实际和潜在危险的假设。GIG 直接遵循它的公理。使用 SHAP 和其他基于 Shapley 值的方法,您必须将输入变量映射到一个更高维的空间,以便让这些值为机器学习功能工作。这样的映射有无数种,并且不清楚哪种是正确的映射(如果有的话)。相比之下,GIG 完全由数学决定。

GIG 通过直接分段分析模型函数来分配信用,以回答问题“哪些输入变量导致了模型分数的变化?”它根据一个独特的公式来计算每个变量导致预测函数改变其得分的数量,通过沿从第一个输入到另一个输入的路径累积模型得分的变化来测量每个变量的重要性。

现实世界信用风险模型的应用

为了展示 GIG 的能力,我们用它来解释一个从真实世界贷款数据构建的混合集合模型。该模型,如下图所示并在前面引用,是 4 个 XGBoost 模型和 2 个神经网络模型的堆叠集合。

图 1:深度堆叠集成:训练数据用于训练多个子模型,其中一些可能是基于树的模型,如 XGBoost,其他是神经网络,然后使用神经网络将它们与输入一起集成到更大的模型中。

任何模型可解释性任务中的表格利害关系是精确量化模型中每个特征的重要性。我们进行了一系列实验(在我们的论文中进行了描述),这些实验表明 GIG 准确地量化了简单模型中变量的影响。实验基于输入数据的已知变化建立了一系列玩具模型,我们表明 GIG 能够准确地描述模型从故意修改的数据中学到了什么。这里,我们来看一个真实世界的应用程序。表 1 显示了图 1 中显示的更复杂集合的特征重要性。表格显示,GIG 甚至可以解释这个更复杂的真实世界模型。

表 1:图 1 所示集合的特征重要性。

除了计算整体特征的重要性,GIG 还允许您量化每个申请人和各种人群的特征重要性,例如表现最好和表现最差的贷款,或者导致男女申请人之间批准率差异的变量。

GIG 如何工作

正如我们之前提到的,GIG 是基于 IG 和 Aumann-Shapley 的一个差分信用分配函数。差异信用分配回答了输入的每次变化会在多大程度上引起模型分数变化的问题。您比较两个申请人之间的输入集以及模型为每个申请人返回的违约可能性(例如,一个申请人可能被拒绝,而另一个申请人可能被批准)。GIG 显示了每个输入变量对导致批准/拒绝决策的分数变化的影响程度。

让我们想象一下这一切是如何工作的。图 2 用绿色显示了一组批准的申请人,用红色显示了一组拒绝的申请人。被拒的申请人有很高的拖欠和破产率。被批准的申请人则相反。

图二。这个模型考虑了两个变量:破产和拖欠。获批的申请人破产率和拖欠率都很低。被拒绝的申请人破产率和拖欠率都很高。

像 GIG 这样的差别信贷分配功能通过比较每个被批准的申请人和每个被拒绝的申请人来解释两类申请人之间的差异:你基本上是在计算每对被批准和被拒绝的申请人之间拖欠和破产的差异,并取平均值。下面的图 3 展示了这一比较中的一对的过程。

图 3。红色的被拒绝的申请人和绿色的被批准的申请人之间的分数差异可以用拖欠率的差异和破产数的差异来解释。

这仅用于说明,图表中缺少模型分数。下面的图 4 显示了一个更真实的画面,它显示了模型分数如何随着拖欠和破产变量沿着被拒绝的申请人和被批准的申请人之间的路径而变化。IG 方法使用 Aumann-Shapley 值来计算违约和破产对批准和拒绝申请人之间的模型分数变化的影响。

图 4。这里,模型分数由 y 轴表示。x 轴和 z 轴代表拖欠和破产数量。沿着被拒绝的申请人(红点)和被批准的申请人(绿点)之间的路径的偏导数的积分代表每个变量(拖欠 x 和破产 z)对模型得分 y 的 Aumann-Shapley 贡献

一个模型可以有任何数量的维度,欧曼-沙普利将容纳它们。但正如我们之前所说,Aumann-Shapley 值只适用于像神经网络这样的平滑函数。图 5 展示了一个 Aumann-Shapley(以及 IG)无法解释的函数组合的简单例子。

图 5。函数组合示例。这里,离散组件用红色表示,表示在 x=1.75 处具有跳跃不连续性的决策树。连续部分以蓝色显示。这两个函数的组合以绿色显示。组合函数在 x=1.75 处包含跳跃不连续性,就像作为其一部分的离散函数一样。Shapley 或 Aumann-Shapley 无法充分解释这些功能,它们需要像 GIG 这样不同的东西。

GIG 首先枚举离散函数中的所有不连续点(例如,通过模型决策树的深度优先搜索),然后从每个不连续点的左侧和右侧计算离散函数的值。它根据这两个值的平均值分配分数,如下图 6 的左图所示。分配给连续零件的信用是使用 IG 计算的(图 6 的右图)。然后将离散和连续成分放回一起,以得到高度精确的组合成分。

图 6。GIG 的工作原理是,通过对离散部分左边和右边的值求平均值,然后将其与 Aumann-Shapley 对连续部分分配的信用相结合,来计算跳跃点的信用。

结论

集合模型比任何单独的建模方法产生更好的结果,但是迄今为止它们不可能被准确地解释。我们引入了一种新方法,广义积分梯度,这是在一小组合理的公理下,解释我们在机器学习的真实世界应用(如金融服务)中经常遇到的不同集合和函数组合的唯一方法。GIG 使得在你的贷款业务中使用这些先进的、更有效的模型成为可能,以制造更多的好贷款和更少的坏贷款,并且仍然向消费者、监管者和企业所有者解释结果。

最初的 GIG 论文是由 Zest AI 的约翰·梅里尔杰夫·沃德肖恩·卡姆卡杰伊·布齐克道格拉斯·梅里尔撰写的。

GitPlus 简介:Jupyter 的版本控制扩展

原文:https://towardsdatascience.com/introducing-gitplus-version-control-extension-for-jupyter-6aac3bd5a420?source=collection_archive---------47-----------------------

[图片与 undraw.io 的开放许可证一起使用]

没有简单的方法可以从 Jupyter UI 控制笔记本的版本。当然,你可以使用命令行& 来学习一些 git 命令来控制你的笔记本版本。但是并不是每个使用 Jupyter 的人都精通 git。因此我构建了 GitPlus ,一个 JupyterLab 扩展,它提供了直接从 JupyterLab UI 提交笔记本&创建 GitHub pull 请求的能力。

如何控制 Jupyter 笔记本的版本

安装 GitPlus 扩展时,它在 JupyterLab UI 中提供了一个新的菜单项Git-Plus。从那里,您可以提交笔记本文件或创建 GitHub pull 请求,如下面的演示视频所示。

从 Jupyter 创建 GitHub Pull 请求

从 Jupyter 创建&推送 GitHub 提交

它是如何工作的?

  • 扩展的服务器组件使用git python&GitHub API 来推送提交和创建拉取请求。
  • 扩展的客户端组件提供 UI 并调用服务器扩展上的适当端点。
  • 客户端组件查看 JupyterLab 中所有打开的文件,并确定哪些文件在 GitHub 存储库中。
  • 它允许您选择要向其推送提交或创建拉取请求的存储库。
  • 它捕获要提交的文件列表、提交消息,并将更改作为提交推送到远程存储库。
  • 在 pull 请求的情况下,它会创建一个新的分支并将更改推送到那里。这个新创建的分支与您的存储库的默认分支(通常是master)进行比较。
  • 在分叉存储库的情况下,在父存储库上创建拉请求。

装置

以下是安装说明。

限制

截至目前,GitPlus 只与 JupyterLab 合作。如果您有兴趣将其与经典 Jupyter UI 配合使用,请投票支持此功能请求。只有当有足够的兴趣时,我才愿意研究经典的 Jupyter 支持。

路标

将来 GitPlus 将能够,

  • 从 GitHub 提取更改
  • 在本地切换/创建 git 分支
  • 解决笔记本合并冲突(不影响底层 JSON)

结论

如果您是 Git 的新手,可能需要一些时间来适应所有的命令。即使您对 git 很熟悉,notebook JSON 也会产生意想不到的副作用。GitPlus 提供了易于使用的接口,可以从 JupyterLab UI 完成大多数常见的 git 任务。可以结合 ReviewNB 看视觉差异&写笔记修改意见。

黑客快乐!

原载于 2020 年 4 月 11 日【https://blog.reviewnb.com】

GraMi 简介 Grakn 的数据迁移工具

原文:https://towardsdatascience.com/introducing-grami-a-data-migration-tool-for-grakn-d4051582f867?source=collection_archive---------41-----------------------

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

如果你和我一样,没多久你就会对 Grakn 感到兴奋。如果你像我一样,最令人兴奋的部分是数据建模、规则推理及其查询和分析功能。

在经历了如何迁移数据的官方示例之后,我确信只有几天时间可以远离所有的乐趣。然后,我花了几周时间构建了一个可靠且健壮的数据迁移器,它具有以下特性:

  • 可扩展性和性能
  • 基本数据清理
  • 数据有效性
  • 记录
  • 故障恢复

它叫做 GraMi (Grakn Migrator)。如果你想,你也可以用它。

在 Github 上找到 GraMi

格拉米是什么?

GraMi 从文件中流式传输表格数据,并生成有效的 Graql insert 查询,然后提交到您选择的 Grakn 服务器。更具体地说:

数据输入:

  • 数据从文件中流出,以保持低内存占用
  • 支持任何表格数据文件(即:csv,。tsv,。*sv…),是否压缩

实体和关系迁移:

  • 迁移 Grakn 中任何可用类型的必需/可选属性(字符串、布尔、长整型、双精度、日期时间)
  • 迁移必需/可选的角色扮演者
  • 将类似列表的属性列作为 n 个属性迁移(Grakn 推荐)

数据清理和验证:

  • 基本数据清理(删除前导和尾随空格以及不一致的特殊字符)
  • 在写入 Grakn 之前,验证基于每个数据行的插入查询
  • 记录所有无效数据记录,以便于分析(例如,缺少属性/球员或数据记录格式不正确)

表现:

  • 在单线程和并行异步写入 Grakn 之间进行选择,以充分利用您的硬件配置

故障恢复:

  • 跟踪迁移进度,允许停止/重启和(硬件)故障恢复

为什么是格兰米?

数据输入:

  • 大多数数据将来自现有系统或结构化文件,并且大多数系统可以导出为表格格式
  • 如果您有大量数据,您会希望以压缩格式存储

实体和关系迁移:

  • 模板逻辑是为大型数据集复制的多种形式,大型数据集具有许多实体和必需/可选属性/参与者的关系以及具有属性列表的列

数据清理和验证:

如果你对数据很认真,你会使用大量的数据,并且非常关心数据的质量。所以你可能想:

  • 记录所有不符合模式和数据建模约束的行
  • 防止对 Grakn 的无效/空写入,浪费时间和无意义的迁移

性能:

  • 如果您有数百万条记录,就不能缓慢插入
  • 批处理和并行化代码并不简单,而且在 Grakn Discord 上经常被请求

故障恢复:

在处理大量不同质量的数据时,硬件和软件最终会出现故障/变得不可用,因此您需要跟踪迁移进度,并能够从中断的地方重新开始。

它是如何工作的

GraMi 要求你指定一个处理器配置文件(处理器配置)和一个数据配置文件(数据配置)。处理器配置充当你的模式、它的实体、关系、属性、播放器、值类型以及数据配置之间的粘合剂。数据配置描述了数据是如何格式化的,以及哪些列包含哪些模式概念。

配置约定:

  • 对于模式中指定的每个实体和关系,在处理器配置中必须至少有一个处理器(至少如果您希望 GraMi 插入它的话)
  • 每个数据文件只包含一个模式概念(即一个实体或关系以及它们相应的属性和参与者)
  • 每个数据文件必须包含具有唯一列名的标题行

在这篇文章中,我们将构建你可以在 github 上找到的 grami-example 项目。这是对 Grakn 的电话呼叫示例的详细描述,扩展到显示 GraMi 此时的所有功能。

从这个例子中可以看出,下面是如何使用处理器和数据配置将数据映射到模式的概述:

图 1 —使用 GraMi 的处理器和数据配置将数据映射到模式。

从左到右(模式到数据):

  • 给定一个模式概念(用黄色标记),在本例中是实体 person
  • 处理器配置定义了一个名为处理器,它创建了 schemaType 实体的实例。对于 person 的每个属性,我们指定属性的值类型以及是否需要将记录插入到 Grakn 中(read 中的 first-name ,蓝色的 nick-name )。注意:关键属性应该始终是必需的;但是,对于所有其他记录,如果缺少某些属性,这将使您能够排除对您的域没有用处的记录。
  • 数据配置包含每个数据文件的一个条目。每个文件映射到处理器配置中的处理器(黄色框),然后将数据文件中的每一列映射到所选处理器中的属性生成器。如果该列实际上是一个值列表(对于昵称,您可以指定列表分隔字符

辅导的

让我们来看一下扩展电话呼叫的例子(完整的项目,包括模式、数据和配置可以在这里找到)。

步骤 1-实体的处理器配置

对于我们模式中的以下实体(在这里找到完整模式):

对应的处理器配置条目将是:

  1. 你的处理者的 ID——这里是人——行 2
  2. 创建一个实体— 行 3
  3. 类型人— 第 4 行
  4. 具有以下属性:
  5. 您的属性生成器的 ID—这里的名字,w 是第 7 行
  6. 创建名字属性—第 8 行
  7. 值类型的字符串(其他可能是:long、double、boolean、datetime) —第 9 行
  8. 那是不需要的— 第 10 行
  9. 或者必填(在电话示例中,电话号码是必填的)—第 16 行

请注意,在为关系定义处理器配置时,将会考虑到实体的“播放”定义。对于实体,只需指定属性生成器。

对模式中的所有实体执行上述操作。点击查看电话示例的完整处理器配置。

步骤 2—关系的处理器配置

对于我们的模式中的以下调用关系:

对应的处理器配置条目将是:

  1. 你的处理器的 ID——这里调用——行 2
  2. 创建一个关系— 行 3
  3. 类型为的调用— 第 4 行
  4. 与以下玩家: —第 6 行
  5. 你的玩家生成器的 ID——此处呼叫者,w 第 7 行
  6. 匹配类型为 person 的实体—第 8 行
  7. 使用属性电话号码识别 —第 9 行
  8. 属于值类型字符串—第 10 行
  9. 插入作为扮演呼叫者的角色—第 11 行
  10. 对于每个调用记录-第 12 行,哪一个是必需的角色

所有关系及其参与者都是如此。如果一个关系有属性,如调用的情况,只需为每个属性添加属性生成器,如步骤 1 实体所述。

步骤 3-实体的数据配置

我们现在将数据映射到刚刚创建的处理器配置。让我们来看看我们的 person.csv 数据文件:

我们的数据配置条目如下所示:

  1. 对于迁移步骤“person”——第 1 行
  2. 我们指定文件路径——第 2 行
  3. 表格列的分隔字符—第 3 行
  4. 通过 ID 从处理器配置中选择处理器,这里是pperson—line 4
  5. 我们设置批次大小——见下文
  6. 以及用于迁移的线程的数量——见下文
  7. 然后,我们在数据文件中的列名和在处理器配置中指定的属性生成器之间提供一个映射
  8. 如果列包含值列表,您可以指定列表分隔字符 —第 21 行

使用 4 个线程的 2000 年批次大小意味着每批 2000 条记录中,每个线程将向 Grakn 写入和提交大约 500 个插入查询。

GraMi 根据插入查询的长度将其均匀地分配给线程,这样每个线程都有大致相同数量的实体/关系和属性/播放器要插入——这可以防止一个线程在处理下一批之前比其他线程花费更长的时间来关闭,从而防止 CPU 浪费。不均匀的 insert 语句通常是由包含属性列表的列造成的,其中每个列表的值的数量在记录之间有很大差异。

步骤 4-关系的数据配置

继续这些关系,我们现在通过我们的 calls.csv 数据文件来工作:

数据条目如下所示:

这里唯一的新东西是第 7-16 行,在这里我们定义了从包含唯一标识关系 call 的角色玩家的属性的到步骤 2 中的处理器配置中的适当玩家生成器的映射。

使用 GraMi

完成我们的处理器数据配置后,我们准备开始迁移。有两种使用 GraMi 的方法:作为 Maven/Gradle Java 项目中的依赖项或作为独立的可执行文件(适用于 Linux 和 Mac):

在您的 Maven/Gradle 项目中使用 GraMi

使用 Maven 导入 GraMi:

或者使用 Gradle 导入 GraMi:(参见完整的 build.gradle 这里)

然后,您可以在代码中使用 GraMi,如下所示:

布尔标志 cleanAndMigrate 设置为,如所示

GraknMigrator mig = new GraknMigrator(migrationConfig, migrationStatus, true);

如果存在,将删除模式和给定键空间中的所有数据。
如果设置为,GraMi 将根据迁移状态继续之前的迁移——这意味着它将从之前停止的地方继续(关于迁移状态的更多细节——见下文)。

至于吗

mig.migrate(true, true);

migrateEntitiesmigrateRelations 标志总共有四种可能性,分别为:

  1. 真,真 -迁移数据配置中的所有内容
  2. 真,假 -仅迁移实体(对调试有用)
  3. 假,假 -仅迁移模式(注意:如上所述的 cleanAndMigrate 标志也必须为真)
  4. 假,真 -不能迁移没有实体的关系-设置为与 3 相同。

在 Java 项目中配置 GraMi 日志记录

要获得对 GraMi 日志记录的控制,请将以下内容添加到 log4j2.xml 配置文件中:

为了跟踪迁移进度,GraMi 的建议日志级别是 INFO。对于更详细的输出,在你空闲的时候将级别设置为调试跟踪——以及错误报告...

使用 GraMi 作为 CLI 应用程序

在确保你的机器上安装了 Java 8 之后,在这里下载GraMi。解包后,您可以直接在/bin 目录下运行它,如下所示:

./bin/grami \
-d /path/to/dataConfig.json \
-p /path/to/processorConfig.json \
-m /path/to/migrationStatus.json \
-s /path/to/schema.gql \
-k yourFavoriteKeyspace \
-cf

只需确保您调整了文件的路径,并选择了您最喜欢的键空间。还要确保将 dataConfig.json 中指定的文件路径调整为本地路径。你可以在这里找到所有的数据和配置文件。

通过使用-h 标志,您可以找到 GraMi 的所有选项和标志:

图 2— GraMi CLI

格拉米伐木公司

GraMi 生成两个日志:应用程序日志和数据日志。

应用程序日志可让您跟踪迁移进度,如果发生异常,它会写出异常或给出软件崩溃原因的信息。对于成功的迁移,您可能会看到如下内容:

数据日志记录了与您的数据相关的所有问题。例如,当列应该是某种值类型,但不是时:

同样,所有违反数据有效性检查的数据记录(缺少必需的属性或玩家、空行等)都会被记录下来:

这使您可以快速找到数据文件中的问题,并在重试之前调整您的预处理(或者不调整,因为不应插入违反您的约束的记录,即需要的属性/球员)。

计划在下一个版本中为每个包含所有未插入 Grakn 的原始数据记录的数据文件创建一个相应的错误文件,这将进一步简化错误分析和修复。

GraMi 迁移状态

GraMi 通过记录为每个文件处理的数据记录数量来跟踪迁移过程。如果失败,GraMi 可以重新启动,或者跳过 -cf 标志(如果用作应用程序),或者在应用程序代码中将 cleanAndMigrate 设置为 false(见上文)。GraMi 将读取您的 migrationStatus.json 文件,可能如下所示:

如果一个文件已经被完整地处理,则 isCompleted 被设置为真。否则为假,文件中处理的行数记录在 migratedRows 下。如果继续中止的迁移,GraMi 将跳过所有已完成的文件和每个未完全迁移的文件中的迁移行(如上面的 call.csv 所示),然后继续下一个数据记录。欢迎您对此进行测试,方法是手动中止迁移,然后按照说明重新启动。

摘要

如果您已经按照上述教程进行了操作,并且从您的 Maven/Gradle 项目中或者通过使用 GraMi 作为独立的应用程序来运行示例迁移,那么您的应用程序日志 ( grami-log.log )应该与代码/应用程序运行的目录 ) 类似:

然后,您可以使用以下查询使用 Grakn Workbase 来浏览数据集:

match $e (caller: $caller, callee: $callee) isa call; get; offset 0; limit 5;

您应该会看到类似这样的内容:

图 3 —使用 Grakn 工作库探索电话呼叫

至此,您已经成功地完成了教程,现在可以使用 GraMi 获取您自己的数据了(希望不到几周)!

如果没有,请通过 Github 联系我或在下面留下评论…

链接和资源

Github 上的 Grakn

格拉克工作基地

GraMi on Github

Github 上的 GraMi 示例项目

贡献

GraMi 是在语义和知识图技术小组@ Bayer AG 的工程师@ Grakn Labs 的大力支持下建立的!

批准

GraMi 和GraMi-示例存储库包括在拜耳公司开发的软件。它是在 GNU-3 通用公共许可证下发布的。

信用

来自 FlaticonSmashicons 横幅中的图标。

Hiveplotlib 简介

原文:https://towardsdatascience.com/introducing-hiveplotlib-31014cefc7ac?source=collection_archive---------32-----------------------

通过蜂巢图在 Python 中实现更好的网络可视化

Hiveplotlib 是一个新的开源 Python 包,用于生成蜂巢图。

介绍hiveplotlib——一个用于生成蜂巢图的新的开源 Python 包。Hive Plots 最初是由 Martin Krzywinski 开发的,它生成定义明确的图形,允许对网络数据进行可解释的可视化探索。

hiveplotlib库在 Gitlab 上对所有人可见,其中文档包括对蜂巢图的进一步解释、示例(玩具数据和真实数据)以及完整的代码文档。

Hiveplotlib 可以通过pip安装:

$ pip install hiveplotlib

目前,我们只支持基于[matplotlib](https://matplotlib.org/)的可视化,但我们计划扩展 hiveplotlib,以用于交互式 Python viz 包,如[bokeh](https://docs.bokeh.org/en/latest/index.html)[plotly](https://plotly.com/)[holoviews](https://holoviews.org/).

运行时间

hiveplotlib很好地扩展到大型网络数据集。作为对合成数据的演示,让我们构建一个类似于hiveplotlib标志中的“o”的蜂巢图:

from hiveplotlib import hive_plot_n_axes, Node
from hiveplotlib.viz import hive_plot_viz_mpl
import numpy as np
import matplotlib.pyplot as pltnum_nodes = 20
num_edges = 80np.random.seed(0)*# build node data*
nodes = []
for i in range(num_nodes):
    temp_node = Node(unique_id=i,
                     data={'a': np.random.uniform(),
                           'b': np.random.uniform(),
                           'c': np.random.uniform()})
    nodes.append(temp_node)*# give the nodes simple int IDs*
node_ids = np.arange(num_nodes)*# build random edges*
edges = np.random.choice(np.arange(num_nodes),
                         size=num_edges*2).reshape(-1, 2)*# construct HivePlot instance, evenly spacing out nodes over 3 axes*
hp = hive_plot_n_axes(node_list=nodes, edges=edges,
                      axes_assignments=[
                          node_ids[:num_nodes//3],
                          node_ids[num_nodes//3:2*num_nodes//3],
                          node_ids[2*num_nodes//3:]
                      ], sorting_variables=["a", "b", "c"],
                      axes_names=["A", "B", "C"],
                      vmins=[0, 0, 0], vmaxes=[1, 1, 1],
                      orient_angle=-30)*# change the line kwargs for edges in plot*
hp.add_edge_kwargs(axis_id_1="A", axis_id_2="B",
                   c=f"C0", lw=3, alpha=1, zorder=1.5)
hp.add_edge_kwargs(axis_id_1="B", axis_id_2="C",
                   c=f"C2", lw=3, alpha=1, zorder=1.5)
hp.add_edge_kwargs(axis_id_1="A", axis_id_2="C",
                   c=f"C1", lw=3, alpha=1, zorder=1.5)fig, ax = hive_plot_viz_mpl(hive_plot=hp)
plt.show()

用 hiveplotlib 生成的蜂巢图的合成示例。

这段代码(减去导入语句)在笔记本电脑上运行大约需要 200 毫秒。如果我们只将上面的代码更改为num_nodes = 10000num_edges = 10000,运行时间会增加大约 1 秒。100,000 个节点和边在大约 10 秒内运行。

数据输入

为了使用 hiveplotlib,我们需要争论两个数据源,节点

节点

在我们的框架中设置一个节点只需要一个数据字典和一个 unique_id。这对于来自数据库查询的任何json输出(例如,通过pymongo来自 Mongo 数据库的查询)来说都是非常好的。pandas数据帧也可以通过df.to_dict(orient="records")轻松转换成这种格式。

优势

边存储为一个(n, 2) numpy.ndarray,其中边(如果有方向)从第一列移动到第二列。**

为了用真实数据演示代码,让我们看一个小而流行的例子:Zachary 的空手道俱乐部。

一个例子:扎卡里的空手道俱乐部

从 1970 年到 1972 年,韦恩·w·扎卡里观察到一个空手道俱乐部分裂成两个派别,一派支持俱乐部主席,被称为“约翰·A”,另一派支持一名教练,被称为“嗨先生”最终,这两个派别正式分裂成两个俱乐部。

这个经常使用的数据集包含 34 个俱乐部成员(节点)和一个记录,记录了在俱乐部正式分裂之前谁与谁在班级之外交往(边缘)。

让我们首先将以下工作的所有导入放在一个地方:

**from** **hiveplotlib** **import** Axis, Node, HivePlot
**from** **hiveplotlib.viz** **import** axes_viz_mpl, node_viz_mpl, edge_viz_mpl
**from** **matplotlib.lines** **import** Line2D
**import** **matplotlib.pyplot** **as** **plt**
**import** **networkx** **as** **nx**
**import** **numpy** **as** **np**# if you're in a jupyter notebook
%matplotlib inline

通过networkx抓取空手道俱乐部数据集很方便:

G = nx.karate_club_graph()

这个网络的可视化——在最初的论文[networkx](https://networkx.github.io/documentation/stable/auto_examples/graph/plot_karate_club.html),甚至维基百科——总是用一个圆形图来完成,所以让我们以此为起点:

*# color the nodes by faction*
color = []
**for** node **in** G.nodes():
    **if** G.nodes.data()[node]['club'] == "Mr. Hi":
        color.append("C0")
    **else**:
        color.append("C1")

fig, ax = plt.subplots(figsize=(10, 10))
plt.axis("equal")
nx.draw_circular(G, with_labels=**True**, node_color=color, ax=ax, node_size=1000)
ax.set_title("Zachary's Karate Club**\n**Circular Network Plot", fontsize=20)

*# legend*
john_a_legend = Line2D([], [], markerfacecolor="C1", markeredgecolor='C1',
                       marker='o', linestyle='None', markersize=10)

mr_hi_legend = Line2D([], [], markerfacecolor="C0", markeredgecolor='C0',
                       marker='o', linestyle='None', markersize=10)

ax.legend([mr_hi_legend, john_a_legend],
          ["Mr. Hi", "John A."],
          loc='upper left', bbox_to_anchor=(1, 1), title="Faction")
plt.show()

扎卡里空手道俱乐部的环形网络图

从循环图得出的结论

从这张图表中可以得出一个清晰而不令人惊讶的结论,那就是 Hi 先生(node 0)和 John A. (node 33)很受欢迎,但很难得出更多其他结论。

用大约 10 秒钟的时间看上面的图,然后问自己以下问题:

这两个派别在社会上的分离程度如何?确认蓝色和橙色之间存在联系需要多长时间?

这两个群体之间的联系是来自一般更社会化的人吗?

要回答第一个问题,我们当然可以更小心地在我们的图中排序这些节点,将橙色与蓝色分开,但第二个问题仍然很难。

设计蜂巢图

蜂巢图允许我们仔细选择放置节点的轴以及如何在这些轴上对齐节点。

因此,有许多必要的声明,但有一个更易解释的网络可视化的回报。

为了回答上述问题,我们将按照以下方式构建蜂巢图:

  • 我们将总共构建 4 轴——2 轴用于约翰 a 派,2 轴用于嗨先生派。使用重复轴可以让我们在结果可视化中以明确定义的方式看到内部派系的行为。
  • 我们将查看 3 组边缘 —约翰 a .派系内的边缘、嗨先生派系内的边缘以及两个派系之间的边缘。这就给了我们上面第一个问题一个明确的答案。
  • 我们将按照节点度为每个阵营排序一个轴。这让我们可以很好地回答上面的第二个问题,稍后会有更多的内容。

让我们首先计算所有节点的度,同时为 hiveplotlib 构建必要的数据结构:

edges = np.array(G.edges)

*# pull out degree information from nodes for later use*
node_ids, degrees = np.unique(edges, return_counts=**True**)

nodes = []
**for** node_id, degree **in** zip(node_ids, degrees):
    *# store the index number as a way to align the nodes on axes*
    G.nodes.data()[node_id]['loc'] = node_id
    *# also store the degree of each node as another way to
    #  align nodes on axes*
    G.nodes.data()[node_id]['degree'] = degree
    temp_node = Node(unique_id=node_id,
                     data=G.nodes.data()[node_id])
    nodes.append(temp_node)

接下来是hiveplotlib组件。让我们构建一个HivePlot()实例:

karate_hp = HivePlot()

*### nodes ###*

karate_hp.add_nodes(nodes)

*### axes ###*

axis0 = Axis(axis_id="hi_id", start=1, end=5, angle=-30,
             long_name="Mr. Hi Faction**\n**(Sorted by ID)")
axis1 = Axis(axis_id="hi_degree", start=1, end=5, angle=30,
             long_name="Mr. Hi Faction**\n**(Sorted by Degree)")
axis2 = Axis(axis_id="john_degree", start=1, end=5, angle=180 - 30,
             long_name="John A. Faction**\n**(Sorted by Degree)")
axis3 = Axis(axis_id="john_id", start=1, end=5, angle=180 + 30,
             long_name="John A. Faction**\n**(Sorted by ID)")

axes = [axis0, axis1, axis2, axis3]

karate_hp.add_axes(axes)

*### node assignments ###*

*# partition the nodes into "Mr. Hi" nodes and "John A." nodes*
hi_nodes = [node.unique_id **for** node **in** nodes
            **if** node.data['club'] == "Mr. Hi"]
john_a_nodes = [node.unique_id **for** node **in** nodes
                **if** node.data['club'] == "Officer"]

*# assign nodes and sorting procedure to position nodes on axis*
karate_hp.place_nodes_on_axis(axis_id="hi_id", unique_ids=hi_nodes,
                              sorting_feature_to_use="loc",
                              vmin=0, vmax=33)
karate_hp.place_nodes_on_axis(axis_id="hi_degree", 
                              unique_ids=hi_nodes,
                              sorting_feature_to_use="degree",
                              vmin=0, vmax=17)
karate_hp.place_nodes_on_axis(axis_id="john_degree",
                              unique_ids=john_a_nodes,
                              sorting_feature_to_use="degree",
                              vmin=0, vmax=17)
karate_hp.place_nodes_on_axis(axis_id="john_id",
                              unique_ids=john_a_nodes,
                              sorting_feature_to_use="loc",
                              vmin=0, vmax=33)

*### edges ###*

karate_hp.connect_axes(edges=edges, axis_id_1="hi_degree",
                       axis_id_2="hi_id", c="C0")
karate_hp.connect_axes(edges=edges, axis_id_1="john_degree",
                       axis_id_2="john_id", c="C1")
karate_hp.connect_axes(edges=edges, axis_id_1="hi_degree",
                       axis_id_2="john_degree", c="C2")

作为hiveplotlib可视化的扩展,我们还将拉出 John A .和 Mr. Hi 节点位置,在最终图形中用不同的颜色绘制它们。

*# pull out the location of the John A. and Mr. Hi nodes
#  for visual emphasis later*
john_a_degree_locations = \
    karate_hp.axes["john_degree"].node_placements
john_a_node = \
    john_a_degree_locations\
        .loc[john_a_degree_locations.loc[:, 'unique_id'] == 33,
             ['x', 'y']].values.flatten()

mr_hi_degree_locations = \
    karate_hp.axes["hi_degree"].node_placements
mr_hi_node = \
    mr_hi_degree_locations\
        .loc[mr_hi_degree_locations.loc[:, 'unique_id'] == 0,
             ['x', 'y']].values.flatten()

测绘

我们现在准备绘图:

*# plot axes*
fig, ax = axes_viz_mpl(karate_hp,
                       axes_labels_buffer=1.4)*# plot nodes*
node_viz_mpl(karate_hp,
             fig=fig, ax=ax, s=80, c="black")*# plot edges*
edge_viz_mpl(hive_plot=karate_hp, fig=fig, ax=ax, alpha=0.7,
             zorder=-1)

ax.set_title("Zachary’s Karate Club\nHive Plot", fontsize=20, y=0.9)

我们还将为 Hi 先生和 John A .添加一个突出显示节点,以及一个自定义图例以供参考,所有这些都使用标准的matplotlib:

*# highlight Mr. Hi and John. A on the degree axes*
ax.scatter(john_a_node[0], john_a_node[1],
           facecolor="red", edgecolor="black", s=150, lw=2)
ax.scatter(mr_hi_node[0], mr_hi_node[1],
           facecolor="yellow", edgecolor="black", s=150, lw=2)### legend ###*# edges*
custom_lines = [Line2D([0], [0], color=f'C{i}', lw=3, linestyle='-')
                **for** i **in** range(3)]

*# John A. and Mr. Hi nodes*
john_a_legend = Line2D([], [], markerfacecolor="red", 
                       markeredgecolor='black',
                       marker='o', linestyle='None', markersize=10)
custom_lines.append(john_a_legend)

mr_hi_legend = Line2D([], [], markerfacecolor="yellow",
                      markeredgecolor='black',
                      marker='o', linestyle='None', markersize=10)
custom_lines.append(mr_hi_legend)

ax.legend(custom_lines, ["Within Mr. Hi Faction",
                         "Within John A. Faction",
                         "Between Factions",
                         "John A.",
                         "Mr. Hi"],
          loc='upper left', bbox_to_anchor=(0.37, 0.35),
          title="Social Connections")

plt.show()

Zachary 的空手道俱乐部用 hiveplotlib 包可视化为一个蜂巢图。

蜂巢图的结论

让我们重温一下之前的问题:

这两个派别在社会上的分离程度如何?确认蓝色和橙色之间存在联系需要多长时间?

从这个图来看,派系内部的联系似乎比派系之间的联系多得多,但是我们可以清楚地看到绿色的派系之间的联系。

这两个群体之间的联系是来自更普遍的社会性的人吗?

派系间的联系和一般的社交能力之间似乎没有特别强的相关性。否则,只会在每个度数轴上较高的节点之间有绿色连接。

与圆形布局相比,生成这种蜂巢图可视化的设置成本当然更高——我们必须做出轴和排序决策。

然而,作为回报,我们可以生成明确的可视化,作为回答真正的研究问题的第一步。

Hiveplotlib 后续步骤

我们很高兴能继续开发这个项目。我们计划的后续步骤包括但不限于:

  • 扩展包以使用交互式 Python 可视化包。
  • 扩展排序过程(通过单调函数进行缩放,对分类数据进行排序)。
  • 在结果可视化中操纵单个边权重。
  • “分箱蜂巢图”——绘制边上节点分箱之间的连接,而不是单个节点到节点的边。

承认

感谢几何数据分析对该项目的开发和开源的支持。

我们还要感谢罗德里格·加西亚-埃雷拉对[pyveplot](https://gitlab.com/rgarcia-herrera/pyveplot)所做的工作,我们将其作为结构设计的起点。我们还翻译了他的一些实用方法用于这个资源库。

更多资源

参考

Krzywinski M,Birol I,Jones S,Marra M (2011 年)。蜂巢图——可视化网络的理性方法。生物信息学简报(2011 年 12 月 9 日,doi: 10.1093/bib/bbr069)。

扎卡里 W. (1977)。小团体中冲突和分裂的信息流模型。人类学研究杂志,33,452–473。

介绍 Hone:Julia 的模块化面向对象图形库

原文:https://towardsdatascience.com/introducing-hone-a-modular-object-oriented-graphing-library-for-julia-823b028b462a?source=collection_archive---------67-----------------------

为 Julia 对我的图形库的第一个版本进行最后的润色。

绘制数据可能非常令人兴奋,尤其是当你已经使用了一段时间的绘图功能,并且它最终以你想要的方式工作的时候。尽管仍然缺少许多参数,仍然有许多令人头痛的工作要做,但是有许多非常有前途的特性已经解决了。伴随着这些伟大的东西,第一版的《征服》也随之而来。现在您可以从 Github URL 将 Hone 添加到您的 Julia 环境中,

[## emmettgb/Hone.jl

模块化的形状,网格和线条容易预制快速绘图简单和轻型车床集成(即将推出)…

github.com](https://github.com/emmettgb/Hone.jl)

笔记本

第一部

第二部分

如果您一直关注这个小系列,您可能会记得,在上一篇文章中,我们在绘图软件中留下了两个大漏洞:

颜色和轴。

颜色

因为我们使用 meta 标签来保存我们所有的数据,所以将数据转换成字符串格式可能会非常繁琐,这使得设置形状的填充颜色比通常情况下更具挑战性。哪里有问题,哪里就有想法,我想尝试的下一个想法是把我之前的两个想法结合起来。看一下我们的 Circle 函数,我们可以看到这个特定的问题是如何在原本打算放在那里的 meta 中放了一个重要的洞。

function Circle(x,y,diameter,fillin)
   # composition = compose(context(), circle(x,y,diameter), fill(string(fillin))
   #     "compose(context(),circle(.5,.5,.1))
    tag = string("circle(",string(x),", ",string(y),", ",string(diameter),"fill(string(","))")
    tree() = introspect(composition)
    show() = composition
    x = x
    y = y
    update(x,y) =  string("circle(",string(x),",",string(y),',',diameter,",fill(string(",Symbol(fillin),")))")
    (var)->(show;composition;tree;tag;x;y;update;diameter)
end

我决定的第一件事是明确使用符号而不是字符串。我决定这样做,因为我认为这样会让我在将来出于其他目的需要调用这些对象的创建时不那么头疼。我们要做的第一件事是将我在第二部分中提到的正则表达式连接到我们的符号上。我们的符号还需要字符串类型断言,如下所示:

color = string("\"",string(fillin),"\"")

简单得很,现在我们所要做的就是重建我们的更新函数,它要么工作,要么不工作。

update(x,y) =  string("circle(",string(x),",",string(y),',',diameter,"), fill(", color , "),")

现在让我们画些东西来测试一下!

x = [5,6,5,5.25,5.5,5.8,5,20]
y = [7,7,4,3.8,3.7,3.8,4,20]
shape = Circle(.5,.5,.01,:blue)
b = Scatter(x,y,shape)

我可能把它画倒了…

现在让我们试着把颜色改成粉红色:

x = [5,6,5,5.25,5.5,5.8,5,20]
y = [7,7,4,3.8,3.7,3.8,4,20]
shape = Circle(.5,.5,.01,:pink)
b = Scatter(x,y,shape)

我休息的另一个特性是绘制 x 轴和 y 轴的能力。当然,轴只是从向量 2 (0,0)到向量 2 (1,0)为 X 轴,从向量 2(0,0)到向量 2(0,1)为 Y 轴绘制的简单直线。

这是我们留在“Line”对象中的代码,它允许我们这样做:

function Line(pairs, color)
    tree() = introspect(composition)
    show() = composition
    composition = compose(context(), line(pairs), stroke(string(color)))
    pairstring = ""
    for i in pairs
        s = string(i) * ","
        pairstring = pairstring * s
    end
    update(pairs) = string("line([",string(join(pairstring)),"]), stroke(",string(color) ,")", )
    (var)->(show;composition;tree;update;color;pairs)
end

这个函数遵循与 shape 函数相同的自然流程,首先进行合成,然后输入元信息,然后创建一个可调用的函数,用于返回一个标签。这个函数中最突出的部分可能是迭代循环,其中创建了一个空字符串,然后与坐标位置的各个向量连接起来。之所以这样做,是因为 Julia 的 NTuple-to-string 类型断言并不像您预期的那样工作,因此一个很好的解决方法是在一个循环内将单个 dim 转换为字符串,而不是整个变量。

这段代码中缺少的另一点是改变 meta 标记内部颜色的能力。为了解决这个问题,我当然会重复使用之前改变形状颜色的方法。第一步是将这一行添加到函数的第二步,其中定义了元表达式的各个部分。

color = string("\"",string(color),"\"")

相当简单…

现在我们可以将该字符串添加到更新函数中:

string("line([",string(join(pairstring)),"]), stroke(", color, "),")

既然我们的 Line 对象的 update 函数实际上正在工作(我希望如此),我们可以将逻辑添加到我们的 Scatter 类中来实际呈现线条。第一步是获取标签:

axisx = Line([(-1,-1), (-1,1), (1,1)],:blue)
   axisx_tag = axisx.update([(-1,-1), (-1,1), (1,1)])
    axisy = Line([(0,0), (0,1), (0,1)],:blue)
    axisy_tag = axisy.update([(0,0), (0,1), (0,1)])

与 Shape 对象不同,我们不能用 update 函数一致地调用同一个 line 对象。这是因为需要保留 update 函数,以便返回不会混淆整个类的内容。用不太宽泛的术语来说,如果我们要在这里添加一个回报:

然后,当我们运行函数“Line”来创建行时,我们将从更新函数中获得返回。考虑到这一点,尝试避免每个函数都返回一个值是非常明智的,这样我们仍然可以在不妨碍函数的情况下获得标签。问题是,只有在调用上面的迭代循环时,这些对才会被更新,您可能记得这是将数据转换为字符串所必需的。

现在是简单的部分;回到我们的 Scatter 函数,我们只需要在坐标解析器完成它的工作之前向表达式添加两行标记。

你可能已经注意到我硬编码了轴的颜色,这不是一成不变的,将来也不会是这样。在编程中,我从来不喜欢为了一个测试做不必要的事情。你可能还注意到我添加了一个“debug”参数,这只是为了让我更容易看到将要被计算的表达式,而不必添加临时打印。我认为这也可以帮助最终用户,因为这个库是模块化的,他们可能会自己构建很多东西。

所以让我们来测试一下吧!

观察

首先,您可能已经注意到,笔画也应用到了圆上。这可能是一个简单的解决办法,我只需要给我们的表达式添加一个新的上下文。另一个值得注意的是右下角的点。这一点之所以存在,是因为否则颠倒的笑脸会正好在图的边缘。我认为这明确说明了在散点对象中作为参数的边距的必要性。

绘制真实数据!

既然我们的散点图起作用了,是时候用一些真实的数据来测试它了!对于这个例子,我将使用我的小“WeatherHistory.csv ”,我不知道我从哪里获得的,也不知道我有多长时间了…

数据狂人的症状。

像往常一样,我们需要做的第一件事是用 CSV.jl 读入数据。

现在(不幸的是),我们需要显示参数 allcols 设置为 true 的数据。

数据筛选开始了…

找到我想要绘制的列后,我将它们放入名为“x”和“y”的变量中供我们使用。

x = df[Symbol("Wind Speed (km/h)")]
y = df[Symbol("Temperature (C)")]

接下来,我们需要创建我们想要用来绘制点的形状:

shape = Circle(.5,.5,.10,:lightblue)

然后我们可以把它代入我们的散射函数:

plot = Scatter(x,y,shape)

所以…这杀死了内核,但我不能说我感到惊讶。

事实上,它不仅杀死了我的内核,我认为它也杀死了韦兰。我的终端清空了,这意味着它 CD 回到了家里,彻底关闭了我的 Jupyter 服务器。

很奇怪。

在用 for 循环将 X 和 Y 数组的 dim 数限制到 700 之后(我打赌有一个默认函数我可以使用),我们终于有了输出!令人惊讶的是,这实际上并没有花费我预期的那么长时间。我还对函数进行了计时,这样我们就可以很好地了解计算速度和分配情况。

我决定做的下一件事是将它与 Plots.jl 进行比较,plots . JL 是用于在 Julia 中绘图的标准库。Plots 模块的问题在于它依赖于 GR、Plot.ly 和 Matplotlib。虽然这很有趣,因为它们都是非常不同的库,并且将它们放在一个模块中肯定很酷也很奇怪,但我不认为使用 Pythonic 代码在 Julia 中绘图对性能来说是个好主意。我做的第一件比较的事情是设置限幅器到 3000 暗,做一个相对基本的测试。结果如下:

对于 Plots.jl:

这些时间没有说明的另一件事是导入 Plots.jl 所花费的令人痛苦的时间。好消息是我的函数比 Plots.jl 快得多。虽然 clearly Plots 绘制了更多的线条,以及图例和轴标签,但我不认为从长远来看这有什么价值,尤其是在我修改函数并寻求更多优化之后。

结论

对于 Hone,我还有很多事情需要完成,因为它还处于生命的早期。我认为我现在所做的所有工作将会使添加新的特征和形状变得非常容易,因为所要做的只是添加一个元表达式。使用 meta 的另一个很大的优点是,每个单独的对象仍将存储在内存中,并完全可以由最终用户调整,因为它存储在 debug 设置为 true 时,您可能会想起打印的相同表达式中。我对 Hone 最大的担忧可能是性能。虽然现在我当然可以进行一些优化,但我担心大量的优化可能会导致整个模块的彻底返工,就像发生在车床上的情况一样。虽然这可能是不可避免的,因为我喜欢不断地改进我工作的软件,我非常希望不必重写模块。

刚刚绘制的阵列大约有 96,000 个观察值,这当然是一个很大的数字,

但应该不是不可能的。

我也打算尽我所能地挑战极限,所以从这里开始并不一定是一件好事,因为这意味着我面前可能有很多工作要做。重要的是要记住,这些也是可缩放的图形;这意味着我们可以预期,在没有拉动一些字符串的情况下,类似的光栅化输出库的性能会更差。

尽管它的问题和一些改进肯定是可以做的,我对它目前为止的表现非常满意,我期待着为这个包添加更多的功能和优化。

JDoc 简介:Jupyter 笔记本上的团队对话

原文:https://towardsdatascience.com/introducing-jdoc-team-conversation-on-jupyter-notebooks-78b5553d7804?source=collection_archive---------51-----------------------

团队在 GitHub 上查看 Jupyter 笔记本的简单方法

ReviewNB 中,我们已经支持 GitHub 提交/拉取请求的 Jupyter 笔记本视觉差异&评论。

今天我们发布了 JDoc,这是一个让团队在 GitHub 上查看笔记本的简单方法。您可以打开存储库中的笔记本&在任何笔记本单元格下开始讨论。观看此存储库或参与对话的团队成员将会收到通知(通过电子邮件),以便他们能够插话并推进对话。这个工作流程对于数据科学/ ML 团队来说非常有用,他们可以互相回顾彼此的工作,提出澄清性问题&并直接在笔记本电脑上提供反馈。

为什么是新功能?

我们在“拉”请求上提供笔记本审阅功能,这在许多情况下非常有效,但在某些情况下却不尽如人意。

  • 有时候你并不在乎笔记本的差异。例如,我提交了一个新笔记本,上面有一些特别的分析&想让我团队中的某个人审阅一下。为了评审而创建一个 pull 请求有点多余,因为这个文件(新添加的笔记本)没有区别&没有合并到主文档工作流事后评审(特别分析)。
  • 不是每个笔记本用户都精通 Git/GitHub。要求他们创建功能分支并打开拉取请求可能有点过分。有了 JDoc,作者只需将笔记本提交给 GitHub,就可以查看了。
  • 有时你想在特定笔记本上查看所有过去的讨论&导航到文件的不同版本。JDoc 通过其以笔记本为中心的同行评审方法&版本控制使这变得容易。

它是如何工作的?

  • 当您在 ReviewNB 上打开存储库时,您现在可以看到新的笔记本选项卡

  • 您可以打开笔记本并在任何笔记本手机上开始对话

  • 观看此存储库或参与对话的队友将在电子邮件中收到新的评论通知。当然,如果他们愿意,他们可以取消电子邮件通知。
  • 队友可以回复/解决/开始新的对话或浏览评论。还有一个变更标签,显示该笔记本的版本历史。

需要注意的重要事项

  • 有了拉式请求评论,你在 ReviewNB 上写的所有评论都会直接发布到 GitHub 上相应的 PR 上。有了 JDoc,你写的所有评论都用 ReviewNB 保存。这是因为 GitHub 没有提供任何直接在文件上发布注释的方式(GitHub 注释只允许在 commits/PRs 上发布)。当然,您的评论在 ReviewNB &中是安全的,存储库管理员可以请求机器可读导出他们报告中的所有评论。
  • 目前,如果您更改了存储库中的笔记本名称/路径,它将被视为一个新文件 &您将不会在其中看到旧的对话。这是因为用原始 git 数据检测文件重命名并不容易。将来,我们将提供一个 UI 来指定重命名,然后通过注释进行移植。
  • 由于 JDoc 就像是 Jupyter 的 Google Docs,所以在笔记本的整个生命周期中会产生很多对话。明智的做法是积极解决/删除旧的对话,以保持文档的整洁。

结论

JDoc 降低 Jupyter 笔记本同行评审的准入门槛。在某些情况下,它们比拉式请求审核更有意义,例如,您想要审核新添加的笔记本,或者您只想发布最终的笔记本版本进行审核,而不关心如何实现增量更新。

拉式请求评论仍然很值得一看视觉差异 &它们充当了讨论的奇妙容器。公关过程也有工程上的严格要求,因为最终结果是合并到母版

我希望你能结合公关审查的力量和 JDoc 的灵活性,达成一个适合你的团队的平衡。

黑客快乐!

原载于 2020 年 6 月 20 日 https://blog.reviewnb.com**

Julia 简介:数据科学中 Python 和 R 的替代方案

原文:https://towardsdatascience.com/introducing-julia-an-alternative-to-python-and-r-for-data-science-dcbf98346253?source=collection_archive---------2-----------------------

迎接面向科学计算、数据科学和机器学习的 21 世纪编程语言。

当有人对我说,有一个新的孩子在这个街区,在这种情况下,孩子=编程语言,我有点怀疑。有一段时间,我是一个重度 Python 用户,工作时看 8 小时,在家看 3-4 小时——我喜欢它,没有理由不喜欢它。

嗯,也许有几个…

可以想象,一天中有一半甚至更多的时间在用 Python 编程的人,在尝试新语言时可能会有点怀疑。不久前,有几个人试图说服我转到 R,我真的尝试过,但不喜欢它。

数据科学不仅仅是关于统计的,你还必须创建 API 和其他东西,这样最终用户才能以某种方式与你所做的东西进行交互,所以对我来说,选择编程语言而不是统计语言是很自然的。但你可能不同意,这没关系。

无论如何,让我们回到主题。 那么朱丽亚是什么呢? 根据快速网络搜索,Julia 是一种由麻省理工学院创建的高级、高性能、动态和通用编程语言,主要用于数值分析。该语言的工作始于 2009 年左右,第一次发布是在 2012 年。所以这种语言到现在已经有 8 年了,不是一个短时期,但肯定没有 Python 那么长。

那是一个相当的句子。你可以把它想象成 R 和 Python 的混合体,但是更快,因为它是一种编译语言。Julia 相对于 R 和 Python 的一些主要优势是:

  1. 它是编译过的——Julia 是实时(JIT)编译的,最好能接近或匹配 C 语言的速度
  2. 它可以调用 Python、C 和 Fortran 库——是的,你没看错,我们以后会更详细地探讨这个问题
  3. 并行化—Julia 中的并行化比 Python 中的更加精细

然而,举几个例子来说,每一个优点都有一个缺点:

  1. 数组索引从 1 开始——这对我来说太疯狂了
  2. 没有 Python 成熟
  3. 没有 Python 的那么多包——但是你可以通过 Julia 调用 Python 库

好的,我只希望你还在,因为现在我们将探索 Julia 编程语言的一些关键概念。然而,首先我们应该安装语言,对吗?

如何安装 Julia

在这一小节中,我们将快速浏览一下安装 Julia 的过程,并为 Jupyter 设置一个内核。如果你不使用 Jupyter,请随意下载你选择的编辑器插件。

让我们开始吧。打开下面的网址,点击那个写着下载的绿色大按钮。你将被要求指定你的操作系统,对我来说是 Windows x64,然后你可以下载文件。安装本身很简单,只需按几次下一步,你就可以开始了。

总之,我们还有一些工作要做。你需要打开 Julia 提示符,窗口应该是这样的:

现在输入下面两行:

using Pkg
Pkg.add("IJulia")

大约一分钟后,Julia 内核将配置有 Jupyter,我们可以通过打开 JupyterLab 来验证这一点,现在我已经有了 Julia 解释器和 Python 解释器:

太好了,现在创建一个 Julia 笔记本,你就可以开始享受乐趣了!

让我们探索一下基础知识

在新创建的笔记本中,您可以像使用 Python 一样定义变量:

默认情况下,变量值会被打印出来,为了避免这种情况,你可以把分号(;)在最后。如果你已经注意到,字符串需要用双引号括起来,因为单引号是为字符类型保留的。

您可以轻松地连接两个或更多字符串:

一开始乘法符号可能会很奇怪,但是你会习惯的。您还可以轻松检查任何给定变量(或值)的数据类型:

Julia 在数组的创建方面与 Python 类似(在某种程度上),您不必指定数据类型或元素数量:

但这并不意味着你不能:

您可以用类似的方式声明向量,只是不要用逗号(,)分隔项目:

以类似的方式,你可以声明多维数组:

现在我们已经讲述了一些基础知识。接下来,我想快速介绍一下如何与 Julia 一起处理数据

数据科学部分

首先,让我们安装 3 个库—用于处理 CSV 文件、数据可视化和一般数据框:

安装需要一分钟左右的时间,但安装完成后,我们必须在使用前导入它们:

好了,现在我们准备好了。对于一些快速的数据分析,我将使用 GitHub 上免费提供的 虹膜数据集 。让我们把它装进去,变点魔法:

如果您想知道,normalizenames param 将确保列名没有任何不需要的字符,比如点(。),这些将被替换为下划线(_)。

您可以像使用 Python 的 Pandas 库一样浏览数据。让我们看看如何获取前 5 行和后 5 行,以及快速统计摘要:

这还没有触及表面。你能想到的熊猫图书馆的任何东西,很可能在朱莉娅中有一个替代品。

是的,这种语言在策划方面也很神奇。看看这几行代码能够产生什么:

开箱即用,它看起来比我用 Matplotlib 制作的任何东西都要好。你也可以做一些新奇的事情,比如组合情节:

您还可以做更多的事情,但这超出了本文的范围。

在你走之前

毫无疑问,朱莉娅是一种令人惊叹的语言。这篇文章的目标是展示基础知识——无论是语言本身,还是它处理数据的能力。

在接下来的文章中,我将更深入地关注各个部分,同时考虑它与 Python 的不同之处,以及我认为这种不同是积极的还是消极的。现在,我要说的是,数据可视化功能远远超出了传统 Python 可视化库所能提供的。

我在其他问题上的立场如何,嗯,你将不得不继续关注来找出答案。感谢阅读。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

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

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

介绍 Label Studio,数据标签的瑞士军刀

原文:https://towardsdatascience.com/introducing-label-studio-a-swiss-army-knife-of-data-labeling-140c1be92881?source=collection_archive---------4-----------------------

专业的机器学习工具是构建成功的基于 ML 的产品的基础和脚手架。

当我在一家企业从事个人虚拟助理项目时,我自己也经历过工具的缺乏,这个项目被大约 2000 万人使用。我们的团队一直在寻找提高质量、处理边缘案例和测试假设的方法。这通常需要处理非结构化数据,对其进行标记,直观地检查和探索模型预测。我们将一套内部工具拼凑在一起,用成吨的样板代码工作一次。不用说,共享这些工具或试图扩展它或将其嵌入到主应用程序中几乎是不可能的。

一次又一次

而且,这个过程是关于产品的定量分析。在试图改进模型时,机器学习工程师严重依赖于在固定数据集上计算的精度/召回统计数据,而忽略了该数据集如何与实际的真实世界数据保持一致。最终,它会导致生产中的系统误差,这只能通过定性分析来识别,即用你的眼睛观察模型的预测。

在生产中我能信任我的模型吗?照片由黛比·兰福德拍摄

我和几个朋友在想,我们能做得更好吗?Label Studio 就是这样诞生的。它旨在为个人机器学习实践者节省原型/实验时间,以及为技术团队缩短 ML 产品发布生命周期

我们在工作时遵循的一些原则是:

  • 化繁为简。没有复杂的配置,易于集成到机器学习管道中。Label Studio 可以在不同的地方使用,具体取决于使用情况:

  • 可快速配置多种数据类型。10 分钟内准备好工具。应该有一种简单的方法在标记文本、音频或图像之间切换,甚至同时注释所有三种类型。

在左侧面板中添加组件,并立即预览界面和输入/输出。

  • 机器学习集成。它应该能够集成所有过多的机器学习框架和模型。ML 有许多不同约束的应用,Label Studio 必须足够灵活来处理它们并提供帮助,而不是复杂化。

如果这听起来很有趣,让我们安装它,让你开始运行!

我们开始吧

启动 Label Studio 非常容易:

pip install label-studio
label-studio start my_project --init

它会自动在您的浏览器中打开 web 应用程序。只需配置您想要标记的内容和方式。就是这样。

文本的命名实体识别

许多现有的标记框架只接受一种数据类型,每次学习一个新的应用程序变得很乏味。开箱即用 Label Studio 处理文本图像音频HTML 文档(称为对象组件),以及任何可以想象的注释任务组合,如分类回归标记跨越成对比较对象检测、“

让我们来探索如何为您的用例配置 Label Studio 服务器

配置贴标界面

Label Studio 的界面不是预先构建的。相反,你可以自己创建它,就像创建网页一样。但是你得到的不是 HTML 标签,而是基于 jsx 的组件。不要害怕!除非你想,否则你不需要写 JavaScript。组件知道如何根据它们的类型和名称进行连接。这是一个图像分类的例子,其中通过使用 toName 属性指定名称,将选择(注释组件)连接到图像(对象组件)。

用预期的输入和输出标记配置

注意美元符号变量 $url 。它指定该组件的值来自您的数据集,它期望带有关键字 url 的记录提供图像的 url。前进到设置页面,用我们在那里的例子玩一玩。或者如果你还没有在当地经营,你可以去看看游乐场

目前,大约有 20 个组件涵盖不同类型的标签,例如,图像的 Bbox 或文本的 NER。完整的列表可以在网站上找到。

数据导入和导出

配置好标注界面的外观后,您可以导入数据。web 导入支持多种格式:JSON、CSV、TSV 以及由这些格式组成的档案。您想要标记的每个数据点被称为一个任务。如果您的任务包含图像,您必须将它们保存在某个地方,并在数据键中公开 URL,就像上面例子中的{"url": "https://labelstud.io/opossum.jpg"}。然后,任务被加载到标签界面,等待您对其进行标签。

直接从文件系统导入数据集或使用 URL 上传,S3 集成即将推出

使用标签-工作室-转换器完成输出。这是一个库,可以采用基于内部 Label Studio JSON 的格式,并输出一些通用格式(JSON、CSV、TSV)或特定于模型的格式,如用于文本标记的 CONLL 或用于计算机视觉模型的 Pascal VOCCOCO

底层存储是普通文件。这使得集成变得非常容易,您只需要将数据放入 Label Studio 可以解析的格式中。您可以在网站上找到更多关于格式的信息。

好吧!现在你有了数据,你知道如何标记和如何导出,让我们来看几个用例,如何将 Label Studio 集成到你的管道中。

功能和使用案例

Label Studio 首先是一个数据标注工具,这使得它非常适用于所有基本的数据标注活动,如标注整个数据集或创建用于验证的基础事实标签。除了这些基础知识,这里还有一些对其功能非常独特的用例。

嵌入你的应用

对于某些应用,你能得到的最好的标签之一可能来自你产品的用户。你可以要求他们从头开始标记任务,或者提供一个模型预测并请求调整它。然后利用它来不断更新模型和提高应用程序的效率。

Label Studio 的独特之处在于,它是一个前端 NPM 包,可以包含在你的应用程序中。这里有一个例子:

收集用户反馈,灵感来自一个流行的视频共享服务

这里可以现场查看。或者看看要诀的来源。可以保存在本地,在浏览器中打开!

机器学习集成,连接模型

你可以通过使用 SDK 轻松地将你喜欢的机器学习框架与 Label Studio 连接起来。

SDK 创建可通过 URL 访问的微服务。它的框架是不可知的,并提供了集成示例。

这让你有机会使用:

  • 自动贴标。使用模型预测标注数据。通过任务预标记,以及使用伪标记进行进一步训练,有助于更快地进行注释
  • 不断学习。从数据流中持续注释和训练您的模型,潜在地改变注释目标
  • 主动学习。实现对要标记的任务的更智能选择的技术
  • 预测服务。即时创建和部署 REST API 预测服务

要了解更多关于起床和跑步的信息,请查看自述文件中的示例。

比较预测

您可以将来自不同模型体系结构或版本的多个预测加载到界面中,直观地验证、查找差异,并编辑您的模型所预测的内容:

来自不同模型的预测,并排比较它们

甚至更多

我们只讨论了我们自己发现令人兴奋的少数几个用例,以及我们看到 Label Studio 可以提供优于现有解决方案的优势的地方,但在我们撰写下一篇文章时,这里还有一些想法供您探索:

监控模型预测误差

你能永远相信你的模型预测吗?您如何理解什么时候是重新培训和重新部署模型的好时机?您可以将 Label Studio 集成到模型监控管道中。与上面的示例一样,您可以显示模型预测的多个版本,并检查预测质量是否有所下降。

(循环)预测管道中的人类

对于预测质量至关重要的应用,当模型不确定或充当低精度检测器时,可以使用 Label Studio 来调整模型预测。在这些场景中,模型预测首先被发送给注释器,注释器可以手动调整它。

从多人那里收集结果

Label Studio 支持每个任务多个结果(称为完成),如果您需要将同一个任务分发给许多注释者,然后验证或组合他们的结果,这是非常有价值的。它的工作方式类似于模型预测可视化,不同之处在于可以将完成设置为基础事实并进行编辑。

增量数据集标注

在将模型部署到生产环境中之后,或者在开发它的过程中,您可能会意识到多标注一个属性可以增强模型的结果。这可能是您想要测试的假设或预定义的策略——从少量属性开始,随着时间的推移添加更多属性。您可以使用 Label Studio 进行增量标注:修改标注配置并随时添加新类。

后续步骤

这仅仅是一个开始。我们计划覆盖越来越多的数据类型,并实现更多覆盖不同标签场景的组件。

我们总是很乐意了解更多可能的人在回路中的用例,并期待在 Label Studio 中实现它们。如果您有建议和/或反馈,请通过在 GitHub 上发帖或加入我们日益壮大的 Slack 社区与我们分享!

快乐贴标签!

Leya 简介:元统计 Lisp 类语言

原文:https://towardsdatascience.com/introducing-leya-the-meta-statistical-lisp-like-language-ef9012affbdb?source=collection_archive---------31-----------------------

我正在创造我梦想中的语言。

在过去的几周里,我一直在享受 GNU Common Lisp 的强大功能。在 Common Lisp 中,所有代码都包含一个列表,它是 list 中的一个数据类型。本质上,Lisp 程序只是列表中的一系列参数。首先,这使得 Lisp 成为元编程极其可行的语言。Lisp 的宏进一步增强了这种效果。Lisp 的宏使得从语言内部调用子进程和使用代码作为数据类型变得非常容易。这当然是非常有效的,不仅可以使你的代码干净、简洁、易读,而且可以自动化。

我正在构建的语言 Leya 是一个将这种方法论发挥到极致的计划。Lisp 很棒,但我确实不喜欢 Common Lisp 的某些地方:

  • 包裹绝对是一种痛苦。我想有一个简单的结构类似这样的导入功能:
(import :package)

在 Lisp 中,添加包绝对是一场噩梦。当然,这不一定是 Lisp 的错,因为这种语言是在 1958 年创造的,但这肯定是一个缺点。包作为一个简单的文件存储在任何外部环境的本地,并且必须直接从源代码加载。如果不考虑安装在系统范围内的 lib-dependency(例如-lib-SDL 2)不能在 Lisp 中使用,这可能并不奇怪。有替代方案,比如 beta 版 Quick Lisp 包,但是这些肯定不能替代一个有效的包管理器。

  • Lisp 实际上可以快得多,只要在后端做一些性能上的调整。

Lisp 具有强大的统计能力和惊人的速度!对于数据科学来说,这两者可能是致命的组合。事实是 Lisp 实际上可以比现在快得多。要理解这是为什么,我们需要理解一个叫做控制流的概念。每种语言都有一个控制流,控制流既可以“跳转”,也可以根据具体情况忽略。跳转是这里的关键词,因为无论何时进行跳转,程序的控制流都会随之改变。

默认情况下,控制流是垂直的,每个部分从 1 开始向上计数。这里有一个例子,写在 NASM 编译的汇编里:

_start:; Allocate our memory; Get the current brk address
        mov rax, 12 ; brk
        mov rdi, 0
        syscall; rax => alloc_ptr && heap_start
        mov [alloc_ptr], rax
        mov [heap_start], rax; (Allocate memory)
        mov rdi, rax
        ; 64 == 9 million;
        add rdi, 1000000; Syscall
        mov rax, 12
        syscall; Read the source code into memory
;   VVVVVVVVVVVV Recreate this with call reading_loop attached
;            for read evaluate print
    reading_loop:; Read from stdin
        mov rax, 0
        mov rdi, 0 ; stdin
        mov rsi, [alloc_ptr]
        mov rdx, 100000
        syscalladd [alloc_ptr], raxcmp rax, 0
        jne reading_loop
    ;   call reading_loop
    ; After the loop:; Save the end of the program
        mov rax, [alloc_ptr]
        mov [program_end], rax; Add a null terminator
        mov byte [rax], 0
        inc rax; Align pointer
    align_loop:
        mov rdi, rax
        and rdi, 0

好吧,这看起来像很多代码。

但是为了理解控制流,我们只需要看几个例子。每当调用“_start:”时,控制流被设置为降序,一个包含数字 0 的字节被放入内存。在“_start:”完成后,由于没有跳转或调用,控制流将继续下降,当它完成与内核的 syscall 通信时,它将进入位置 1:“reading _ loop:。”

在读取循环的最后,我们会看到三个命令:add、cmp、jne。首先,add 是做什么的?Add 将把我们在。bss 部分或。数据段添加到注册表 rax,它是 64 位高位注册表中的第一个位置。下一个命令 cmp 是 compare 的缩写。这将比较两个值,并根据标志的结果更改标志。在这个特殊的例子中,我使用存储在字节 0 的注册表标志,CF 标志。

(img src:https://www . slide share . net/safayethossain 3/assembly-flag-resister)

最后但同样重要的是 jne,这是一个条件跳转。如果满足这个标志,那么 jne 命令将通过将控制流保持在位置 1:“reading _ loop:.”来将控制流变成一个圆形

控制流实际上驱动了我们在日常语言中使用的大多数东西,以及我们使用的每个高级工具,例如循环、条件等。实际上通常会使用非常特殊的控制流。

(img src:【https://dzone.com/articles/how-draw-control-flow-graph】T2

当然,控制流不仅对我们想要做的事情非常重要,对性能也非常重要。你可能听说过 for 循环,一般来说,非常能够坦克性能。这是因为 for 循环使用至少四个位置的组合,并将根据添加的数据字节进行条件跳转(将字符长度存储在内存中,并将 cmp 值保存在内存中,循环数。)这意味着每次不满足最终迭代条件时,控制流将减少 2。假设我们在位置 3,每次 for 循环没有完成,我们就跳到位置 1,重复这个过程。

很明显,有很多方法可以通过调整控制流来提高性能。这个方法其实是朱莉娅想出来的,所以我不能居功;每当汇编编译器调用自身时,控制流就会不断地循环。这意味着在语言内部运行比汇编语言更有性能。这是因为汇编的进程在执行前由处理器读取。这类似于大多数语言的编译方式。

然而,当语言中最常用的核心函数是用语言本身编写的时候,就可以在运行时进行调用,而不需要另一次汇编。所以我们的目标是在一个单独的线程上运行一个已经分配、加载并标记了内存的代码。

结论

作为一种类似 Lisp 的语言,Leya 编程语言拥有 Lisp 的所有优点。轻松编译,用汇编器只汇编 3000 行左右的代码,一切都是列表,还有用宏进行元编程的轻松和流畅。

创建一种与另一种语言做同样事情的语言是有点愚蠢的,尽管我会第一个说构建编译器使我在汇编和编程方面做得更好。实际上,有一本有趣的书叫做《用 C 语言构建你自己的 Lisp 》,如果你想学习 C 语言,我建议你去看看。构建 Lisp 不仅能让你更好地学习 C 语言,或者帮助你学习 C 语言,而且我认为它还能让你更接近许多理解起来非常重要的计算机科学基础。

“Leya”这个名字的本意是解释它自己,而这种语言的构建意图完全不同:

机器学习的快速元编程。

“Leya”这个名字来源于术语 Lemma,它是一个论证或证明中的数学分离,也是中间的。这是我的原话,但这是谷歌的定义:

"论证或证明中的附属或中间定理."

这非常类似于编程中的宏指令。Y 来自于我们都知道并且喜爱的 Y,我们算法的目标。

因为 Lisp 是轻量级的,易于编译,所以 Lisp 是一种非常快速的编程语言。Lisp 通常被认为不能像 C 那样使用,但是它的语法非常高级,很容易习惯。Lisp 最难的一点是,为了使用它,你必须直接从传统的角度来思考所有的事情。从回报开始,一直到价值。通常我只在一个值被循环使用的特殊情况下设置一个变量,以避免多次计算。

感谢您阅读到最后,如果您想了解 Leya,请访问 Github:

[## emmettgb/Leya

Leya -火烈鸟的官方编程语言。通过在…上创建帐户,为 emmettgb/Leya 的发展做出贡献

github.com](https://github.com/emmettgb/Leya)

每天都有越来越多的问题涌现出来,慢慢地,但肯定地,问题正在得到解决。截至目前,我有大约六个项目,我一直在工作,所以开发一直很慢(请放心提交!)但是希望到最后,这种语言是我所有数据科学需求的理想选择。

简单介绍线性回归(最小二乘法)

原文:https://towardsdatascience.com/introducing-linear-regression-least-squares-the-easy-way-3a8b38565560?source=collection_archive---------28-----------------------

编码前理解

杰克·布吕克在 Unsplash 上的照片

线性最小二乘监督拟合技术是最简单和最常用的线性回归形式,为通过一组点找到最佳拟合直线的问题提供了解决方案。

我们的一般线性回归模型看起来像这样-

输入是一个特征向量 (x1,x2,⋯,xk)
输出是一个标量 y
该模型将输出与输入特征向量以线性关系联系起来:

y = w0+w1 * x1+w2 * x2+w3 * x3+…+wk * xk

w0 是偏差

我们为什么需要偏置?

在线性回归中,如果没有偏差项,我们的解必须经过原点。也就是说,当我们所有的特征都为零时,我们的预测值也必须为零。然而,这可能不是训练数据给出的答案。添加不依赖于任何特征的偏置权重允许由学习的权重描述的超平面更容易拟合不经过原点的数据。

偏置与无偏置

简单线性模型

现在,考虑一个非常基本的两变量线性模型。温度是自变量,我们希望找出温度对销售(因变量)的影响。

这 12 个数据点是(x,Y)的形式。x 坐标代表以摄氏度为单位的温度,Y 坐标代表以美元为单位的销售额。第一步是将数据可视化——绘制成图表(如上图所示)。在这种情况下,绘图是可能的,因为我们只考虑两个变量。

我们的目标是找到一条线,它是最适合上述数据的,如上图所示。

这条最佳拟合线是如何计算的?

任何一行都具有以下形式:

y = mx +c

其中 m 为直线的斜率(逆时针计算直线与 x 轴所成角度的tan)cy 截距。

这里 y 表示特定温度下的销售额 x.

因此,我们的 最佳拟合 线也将是 y = mx + c. 的形式

考虑第一个数据点(x1,Y1):

x1 : 实际温度值,单位为摄氏度

Y1 : 实际销售金额对应 x1

y1 = m * x1+c:根据最佳拟合线预测 x1 对应的销售值

E1 = y1 — Y1

E1 是第一个错误术语。

计算单个误差

注意:在统计学中,当我们使用术语“线性模型”时,我们不一定描述一条直线。

图中的两个形状都是“线性的”:

哪个是线性的?

“线性”在统计学中是用来描述我们正在使用的模型中的参数。线性意味着响应(y 变量)预期是解释变量(离散或连续)的线性组合。线性是指解释变量是可加的。

当我们说模型是线性的时,这种说法实际上是不完整的。线性回归需要指定和检查的是,如果模型是线性 w . r . t .参数 (w0,w1,w2,…,wk)。

回到错误上来。我们的目标是减少这些误差,从而最小二乘误差。

为什么我们使用“平方”误差,而不是误差的高次幂或绝对值?

这里有两个原因:

  1. 随着功率的增加,异常值的误差会放大更多。结果,越多的“最佳拟合”线将被拉向异常值,这将不再是最佳拟合。
  2. 最小化一个二次函数很容易——你只需要对它求导并将导数设置为零,这就产生了一个线性方程——我们有几个世纪的技巧来帮助我们解决这个问题。

通过缩放区域来直观地传达基础数据,从而提高地图的可视化效果

原文:https://towardsdatascience.com/introducing-mapscaler-42a57e68aead?source=collection_archive---------36-----------------------

使用 mapscaler 按人口或任何其他值缩放州或县,以实现 choropleth 数据可视化

如何根据人口或任何其他值缩放州或县,以实现 choropleth 数据可视化

许多使用颜色作为维度的地图可视化具有误导性。

社交数据经常被放在地图上(一个 choropleth),并用颜色来表示一些活动或行为。问题是,数据往往是关于,但在读者眼里,地图本来就是关于地区的。地图上最大的区域吸引了读者的注意力,而忽略了数据中有多少人与该区域相关。如果你显示的数据恰好是按区域标准化的,比如人口密度,这没什么,但是这通常不是我们可视化的目标。

问题是,数据往往是关于,但在读者眼里,地图本来就是关于地区的。

有时图表是更好的选择,但是大多数图表要么扭曲难以辨认,要么高度手工创建。因此,我创建了一个 Python 包,通过任何变量自动缩放任何地图的各个部分,没有任何重叠的形状,失真最小。

介绍贴图缩放器!您所需要的只是一个 GeoPandas 数据框架,包括一个列,其中包含用于缩放每个多边形的值。Mapscaler 将从那里开始做繁重的工作——将每个多边形缩放到适当的大小,然后重新排列它们(最低限度),直到它们不重叠。

这可以让你的地图对读者来说更加直观,而且出奇的漂亮!这里有一些例子来说明:

例子

1)美国各县

政治分析家喜欢用政治偏好来渲染地理。下面是一个典型的地图样式,使用的是 2000 年乔治·w·布什和阿尔·戈尔之间的总统选举数据:

这是一个差的形象化!目标是传达关于人们如何投票的信息,但这隐藏了一个完整的维度:并非所有这些县都有相等的投票人口!眼睛很容易被颜色比例所迷惑。2000 年的选举是历史上最接近的选举之一,只有 5 个选举人获胜!从这张地图上你永远也猜不到。一个更好的方法是根据投票的多少来划分各县。通过这种方式,读者可以了解有多少人投票给了哪个政党,也可以了解选民的地理分布情况:

如果您喜欢“气泡”而不是保留原始形状,mapscaler 也可以做到这一点:

2)美国各州

如果你有脸书,你(希望)知道他们追踪你带着手机去的任何地方。最近,脸书的“数据为好计划”发布了匿名数据,以证明新冠肺炎导致的流动性下降。在撰写本文时,你可以在链接找到一张地图,显示每个州有多少人留在原地:

资料来源:美国人口普查局,脸书良好计划数据

当大多数人看到这一点时,他们的目光会被吸引到美国中部色彩鲜艳的州,或者最多是中西部。毕竟,那是美国大部分地区的所在地!一个更好的地图应该按照人口比例来划分各州,以显示人口的实际分布情况:

资料来源:美国人口普查局,脸书良好计划数据

在后一张图中,你的视线被吸引到了德克萨斯州和沿海地区。这是应该的,因为那是大多数人真正生活的地方!这张地图,用同样的数据,讲述了一个更好的故事。

3)较小的地理区域

为了展示 mapscaler 的灵活性,这里有一个更局部的例子。北卡罗来纳州公共教育部公布了他们的支出;以下是 2018 年按县分列的用于残疾儿童的所有美元:

当然,在不知道孩子们实际上学地点的情况下,这张地图用处不大:

Mapscaler 可以用pip install mapscaler从 PyPi 下载。它还包括一些内置的地图,让你开始;我已经在官方文档中发布了一些示例代码。给我反馈或问题!

其他链接:

MIDAS 简介:图中异常检测的新基线

原文:https://towardsdatascience.com/introducing-midas-a-new-baseline-for-anomaly-detection-in-graphs-4311b8f7a737?source=collection_archive---------53-----------------------

图片来自 Github

在机器学习中,自动驾驶汽车、GANs 和人脸识别等热门话题经常占据媒体的大部分聚光灯。然而,数据科学家正在努力解决的另一个同样重要的问题是异常检测。从网络安全到金融欺诈,异常检测有助于保护企业、个人和在线社区。为了帮助改进异常检测,研究人员开发了一种叫做 MIDAS 的新方法。

迈达斯是什么?

在新加坡国立大学,博士生西达尔特·巴蒂亚和他的团队开发了 MIDAS,这是一种新的异常检测方法,在速度和准确性上都优于基线方法。

MIDAS 代表基于微簇的边缘流异常检测器。顾名思义,MIDAS 检测微团簇异常或图形中突然出现的可疑相似边缘组。MIDAS 的主要优势之一是它能够实时检测这些异常,速度比现有的最先进的模型快许多倍。

图中异常检测的真实用例

简而言之,异常检测是寻找偏离数据集中预期的模式或异常值的实践。它可以帮助我们找到并消除有害内容。“图中的异常检测是在无数系统中发现可疑行为的关键问题,”西达尔特说。"其中一些系统包括入侵检测、虚假评级和金融欺诈."

这项技术可以帮助 Twitter 和脸书等社交网络检测用于垃圾邮件和网络钓鱼的虚假个人资料。它甚至可以用来帮助调查人员识别网上的性侵犯者。“使用 MIDAS,我们可以在动态(时间演化)图中找到异常的边缘和节点,”西达尔特说。“在 Twitter 和脸书,推文和消息网络可以被视为一个时间演化图,我们可以通过找到这些图中的异常边缘和节点来发现恶意消息和虚假信息。”

异常检测的一些其他常见用例包括:

  • 垃圾邮件过滤器
  • 信用卡欺诈检测
  • 数据集预处理
  • 网络安全性
  • 社交媒体内容审核

MIDAS 优于最先进的方法

“异常检测是一个经过充分研究的问题,大多数提出的方法都集中在静态图上,”西达尔特说。但是,许多真实世界的图表本质上是动态的,基于静态连接的方法可能会遗漏图表和异常的时间特征

MIDAS 解决了实时检测异常情况的需要,以便尽快开始恢复,并减少恶意活动的影响,如欺诈性信用卡购买。

“此外,由于顶点的数量会随着我们处理边流而增加,我们需要一种在图形大小上使用恒定内存的算法,”西达尔特解释道。此外,许多应用中的欺诈或异常事件发生在微集群或突然到达的可疑相似边缘组中,例如网络流量数据中的拒绝服务攻击和锁步行为

“通过使用一个原则性的假设检验框架,”西达尔特说。" MIDAS 提供了假阳性概率的理论界限,这是早期的方法所不能提供的."

迈达斯是怎么测试的?

西达尔特和他的同事展示了 MIDAS 在社交网络安全和入侵检测任务中的潜力。他们使用以下数据集进行异常检测:

  • Darpa 入侵检测(450 万次 IP-IP 通信)
  • Twitter 安全数据集(2014 年有 260 万条与安全事件相关的推文)
  • 推特世界杯数据集(2014 年足球世界杯期间 170 万条推文)

为了比较 MIDAS 的性能,团队查看了以下基线:

  • RHSS
  • 色丹斯波特

然而,由于 RHSS 在 Darpa 数据集上的 AUC 测量值很低,为 0.17,该团队通过与 SEDANSPOT 进行比较来测量准确性、运行时间和真实世界的有效性。

结果呢

MIDAS 检测微团簇异常的准确率高达 48%,速度是当前基线方法的 644 倍。

“我们的实验结果表明,MIDAS 比基线方法高 42%-48%的准确率(就 AUC 而言),”西达尔特说。"此外,MIDAS 处理数据的速度比基线方法快 162644 倍."

改进 MIDAS:未来的工作

“我们已经将 MIDAS 扩展到 M-Stream:快速流式多方面群体异常检测,”西达尔特说。“在 M-Stream 中,我们检测具有分类和数字属性的多方面数据上的异常。”

西达尔特和他的团队表示,M-Stream 在准确性和运行时间方面也优于几个基准,包括流行的 Sklearn 算法,如隔离森林和局部离群因子。然而,他们与 M-Stream 的合作目前正在审查中。

“考虑到 MIDAS 的性能,我们认为它将成为一种新的基线方法,对异常检测非常有用,”西达尔特说。"此外,探索 MIDAS 如何在其他应用中发挥作用也将是一件有趣的事情."

如果你有兴趣了解更多关于迈达斯的知识,请查阅西达尔特的全文。你也可以在 Github 上下载代码和数据集。

要获得更多机器学习采访、指南和新闻,请查看下面的相关资源,不要忘记订阅我们的时事通讯。

原载于Lionbridge AI

介绍电影大亨:GCP 为好莱坞主持的产品创意

原文:https://towardsdatascience.com/introducing-movie-tycoon-a-gcp-hosted-product-idea-for-hollywood-733105c6f3e0?source=collection_archive---------56-----------------------

利用谷歌云平台上的自然语言处理和大数据帮助电影投资

按作者分类的图片—产品徽标

向好莱坞的潜在客户和投资者推销产品…**

产品背后的动机

电影和观众的关系已经有几十年的历史了。电影不仅反映了我们生活的社会,也塑造了流行文化和愿望。然而,在互联网时代,这种联系已经逐渐超越了票房、影院和电视领域,成为在线流媒体和电影股票交易。

哼!电影炒股?那是什么?让我解释一下…

好莱坞证券交易所是世界领先的娱乐证券市场。在 HSX.com 的,游客用一种叫做好莱坞美元的货币买卖名人和电影的虚拟股票。****

显然,人们正在以更新的方式参与电影。作为一个行业,好莱坞也越来越多地期待利用数据分析来为创意和商业决策提供信息,这一点在大西洋上一篇名为 大数据和好莱坞:爱情故事 的报道中得到了强调。

“我的梦想是,当好莱坞真正开始关注数据,大规模使用数据,并推动商业价值时。”IBM 高级分析全球负责人 Richard Maraschi

电影大亨

电影大亨为 HSX.com 的电影投资者提供投资方向和投资对象的建议。此外,目的是为创意人员提供一个工具来分析评论,并将其作为未来项目的反馈。通过这种方式,投资者可以确定投资影院业务的正确价格,影院所有者可以根据票房预测安排电影放映。

数据管道

图一。来自 HSX 和烂番茄的数据流进入中枢引擎

除了来自罗顿番茄的评论,以下数据点来自 HSX 的周末票房:

  • 电影名称
  • 标志
  • 周毛收入
  • 总额
  • 类型
  • 出厂日期
  • 剧院
  • 美国电影协会评级

数据架构

图二。数据架构和相关的数据收集工具

产品管道

在数据来源于允许在电影数据库上查询解决方案的 Hive,以及 python web 抓取工具被部署来构建用于执行自然语言处理的语料库之后,电影大亨利用 GCP 上的 Cloudera Hadoop 来创建 mapper-reducer 框架。

然后,所有数据被发送到 Jupyter Notebook 进行进一步分析,最终输出以 csv 文件形式发送到 Tableau,以便为最终用户创建仪表板。

图三。电影大亨的产品渠道

蜂巢工作流程

通过 HIVE SQL 计算作业,所有数据流都变得很容易获得。为了确保将所有新的票房电影数据纳入分析中,Movie Tycoon 中的整个工作流都是使用调度程序作业自动执行的,每个作业都在每周一上午 8:00 运行。

在试运行期间,自动计划程序大约需要 10 分钟。

图 4。配置单元工作流

可视化产品洞察

为了帮助电影投资者、编剧和制片公司,整个决策支持系统在 Tableau 上可视化,使用如下所示的实时仪表板。

图五。实时 Tableau 仪表板

最高票房收入出现在以下类型中:

  1. 行动
  2. 音乐的
  3. 家庭的

NLP 洞察

理解电影评论对产品的成功和稳健至关重要,它能对观众如何看待电影提出战略性和深刻的观察。内容作者将从这个尚未开发的数据源中获得巨大收益。在使用各种 NLP 技术进行详细分析后,发现以下主题会产生非常积极的情绪:

  • 故事
  • 表演
  • 精彩的戏剧

电影院 GIF 由詹姆士·柯伦

结论

再回到《大西洋月刊》的文章…

好莱坞的许多人希望,通过结合对内容和观众的深刻理解,电影公司将能够从一开始就选择和定制他们的电影,甚至可能找到某种编剧的神奇公式。

电影大亨将让你做到这一点,甚至更多,通过可扩展性云安全智能分析等功能来推动决策。它使好莱坞和观众之间的距离比以往任何时候都更近,同时利用现代数据科学和大数据工具来实现这些利益相关者之间的协同作用。**

更多的技术文档,你可以在这里查看相关的代码文件

介绍我的书:Python 金融烹饪书

原文:https://towardsdatascience.com/introducing-my-book-python-for-finance-cookbook-de219ca0d612?source=collection_archive---------19-----------------------

来源: Unsplash

我的短篇小说从中型文章到图书合同

在这篇文章中,我想分享我的故事,即写关于走向数据科学的文章是如何开始一场冒险的,并最终成为一本书。我还将描述我在这个过程中学到了什么,以及在这个过程中哪些工具帮助了我。开始吧!

它是如何开始的

2019 年 2 月的某个时候,一位收购编辑联系了我,问我是否有兴趣创作一本书。我已经写了几篇关于 Medium 的文章,我对这个项目的规模有点不知所措。然而,这听起来像是一个令人兴奋的想法,并且有可能扩大我小小的写作爱好。很快,我同意接受挑战。

这个提议

整个过程的第一步是求婚。出版商已经对这本书的总体主题(主题,而不是内容本身)有了想法,这将是一本什么类型的书,以及它应该面向谁。

这是一个提到书的格式的好地方。如标题所示,这是一本烹饪书,侧重于实践方法。每一章都包含一系列的方法,每一个都是分析师在金融领域工作时可能遇到的独立任务。

在写提案的时候,我可以自由选择我想在章节中包含的食谱。提案必须非常详细,对于每一个食谱,我必须包括标题,一个简短的总结,以及预期的页数。这被证明是相当棘手的,但我稍后将回到这一点。

经过几次反复,并结合了编辑的一些建设性反馈,提案准备好了,我签了合同,开始写作。

该过程

我收到了出版商的一些介绍性文件。它们包括一些关于这本书应该遵循的风格的一般信息,但也包括一些关于写作过程本身的提示。根据他们的说法,每天写 1-2 页,按时完成这本书应该不成问题。

至少对我来说,大多数时候事情看起来并不是那样。写书可以类似于拥有另一份工作,至少在时间上是这样。将两者结合起来并拥有足够的个人生活时间是一个挑战。

为了让我更轻松,我尽可能在上下班的路上做更多的工作。因为我每天要坐两次 40 分钟的火车,所以尽可能有效地利用这段时间是有意义的。之前我在那时候看书或者做文章,所以我已经习惯在这样的条件下工作了。

即使我在上下班途中一天写两次书,我也很少能写出足够的内容来填满 1-2 页的配额。大多数时候,我也在晚上工作。经常发生的情况是,在一天的工作和长途通勤之后,我实在太累了,以至于晚上做不了任何有建设性的事情。因此,相对于最初的时间表,我有一些延误。谢天谢地,编辑们在这个过程中给予了支持和鼓励。

从 2019 年 3 月到 2020 年 1 月初,我一直在写这本书。对于每一章,我都遵循类似的工作流程。首先,我为我正在写的那一章收集资料。然后,我开始陈述手头的问题,并编写解决它的代码。编码部分完成后,我会写食谱的介绍,并详细描述代码是如何工作的(一步一步)。在大多数食谱中,我还写了一个有更多的部分,其中包含了一些关于该食谱的更高级的主题,或者专注于该任务的另一种可能的方法。

大多数时候,我把食谱的内容和代码写在同一个 Jupyter 笔记本上。这似乎是最方便的,因为我会将所有内容(文本+代码)一次性转移到出版商的基于 Markdown 的文本编辑器中。然而,也有与之相关的问题。在下一节中会有更多的介绍。

另外值得一提的是,在写这本书的同时,大纲也发生了演变。我在提案中计划的一些食谱被合并在一起,一些被替换。我觉得真的很难写出一个在实际开始写的时候不会改变的提案。

我所学到的…

在这一小段中,我将描述我在写书时学到的一些要点,以及我本可以做得不同的地方。我将主要写过程本身,而不是特别写编码。

  • 在写提案时给出一个现实的页数比预期的要困难得多。我严重低估了每章所需的页数。首先,我没有考虑图像的大小,因为我不清楚每一章会有多少图像。第二,我低估了代码所占的空间。考虑到代码被分解成编号的步骤,并且每个步骤都有简短的描述,这极大地影响了页面数量。
  • 与出版商的编辑更频繁地核对事实。正如我之前提到的,我主要是在 Jupyter 笔记本上写章节的内容,在那里我也给出了给定任务的解决方案。当我以为我已经看完了的时候,我才把这一章移到了出版商的编辑那里。这种方法的问题是,我在 Jupyter 中没有真正的页面计数指标。因此,当我将所有内容转移到编辑器时,常常会远远超出目标。此外,当将代码移动到编辑器时,它通常不能很好地适应页面宽度,需要进一步的重构——在笔记本和编辑器之间来回切换。
  • 数据科学 9 个月真的很多,因为行业在不断发展。我从几个方面体验了这一点。首先,当我完成这本书时,一些 Python 库被重命名,这需要在多个章节中修改代码。第二,一些功能(关于下载数据)被弃用,因此,我删除了 2 个完整的食谱。第三,在写后面的章节时,我偶然发现了一些我想在前面的章节中使用的新的很酷的东西,但是,通常没有时间(和页数)来将它们合并到已经写好的部分中。最后一件事产生了多篇文章的想法,我希望很快发表:)
  • 代码需要多轮重构。原因包括修改格式(使其符合页面宽度),考虑库的变化等等。此外,当我在写作过程中进行开发时,我经常回到前面的章节来重构代码,以便它符合后面的标准。需要记住的一点是,修改代码不仅发生在 Jupyter 笔记本中,也发生在存储该书的出版商的编辑器中,因此正确更新这两个源是至关重要的。
  • 我必须学会的一件事是延迟满足。以中等文章为例,文章一写完,几秒钟之内就可以发表,我可以看到它的接受度。我知道,这是虚荣心作祟。但是这本书花了将近一年的时间才完成,并且需要一些决心。最后,交付了这本书的最终版本,并且正在进行印刷,这种满足感是巨大的,值得等待。此外,在写这本书的过程中,我设法找到一些空闲时间来准备一些文章。正如我之前提到的,我有很多想法。例如,我正在研究 Python 中用于回溯测试交易策略的库。虽然我在书中使用了一个库(并坚持使用它以保持一致性),但我对另一个库做了一些研究,如果不作为一系列文章来分享,那将是一种耻辱(由 this one 开始)。

让我生活更轻松的工具

  • 特雷罗——它允许我们创建看板风格的任务列表。这是一个组织项目的伟大工具,无论是个人使用还是整个团队使用。对于这本书,我创建了一个板,并把它分成几个部分,如积压,做,修订,完成,想法。这样,每当我想出一个新的想法或者想要跟踪我仍然需要重构的东西时,我可以很容易地使用 Trello 来组织任务。我也用它来组织我的博客写作:)
  • GitHub——可以说是最流行的版本控制平台。你可以在这里找到这本书的 GitHub 资源库
  • 语法上的——一个确保你的写作相对“正确”的伟大工具。通过显示潜在的错误,可以节省大量时间。然而,彻底阅读也很重要,因为语法上可能会错过一些复杂的边缘情况。Grammarly 也可以作为 Chrome 扩展安装,可以很好地与多个网站(包括媒体!).
  • 海明威应用 —这个网络应用非常适合分析文本并展示其复杂性。它提供了额外的帮助,指出哪些句子太长或太复杂,可以使用一些调整(例如,将它们分成两个独立的句子)。总的来说,海明威应用程序的建议使文本更容易阅读和理解。
  • draw . io——一个非常方便的创建出版物质量图表的工具。它作为一个浏览器拖放工具,提供了大量的图标和图像。最重要的是,它允许保存您的项目,再次加载它们进行可能的修改,并导出为多种格式(包括 PDF)。
  • Jupyter Notebook/Visual Studio Code—大部分时间,我都是用 Jupyter 笔记本(带 nb 扩展比如目录、拼写检查器等。)进行编码和编写。每当我需要准备一个单独的.py脚本时,我就使用 VS Code,这是我的首选文本编辑器。

这本书本身

在了解了所有关于过程本身的信息之后,是时候最终呈现这本书了。如前所述,书名是 Python 金融食谱,书中包含了 50 多个实用食谱。

这本书的目标读者是对 Python 有一定了解,同时也对量化金融/机器学习/深度学习有一定了解的人。在《食谱》中,我提供了所用技术背后的理论的高级概述,并经常参考论文/书籍进行深入阅读。但是一般来说,我着重解释 Python 中的实现,而不是底层理论。

本书分为 10 章:

第 1 章,金融数据和预处理,探讨金融数据与机器学习任务中常用的其他类型数据有何不同。我展示了如何从不同来源下载数据并对其进行预处理以供进一步分析。

第 2 章,Python 中的技术分析,演示了技术分析的一些基本知识,以及如何用 Python 快速创建优雅的仪表板。读者将能够从一些最常用的度量标准(如 MACD 和 RSI)中获得一些模式的洞察力。

第三章,时间序列建模,介绍时间序列建模的基础知识(包括时间序列分解和统计平稳性)。然后,我研究了两种最广泛使用的时间序列建模方法——指数平滑法和 ARIMA 类模型。最后,我提出了一种新的方法,使用脸书先知库中的加法模型对时间序列进行建模。

第 4 章,多因素模型,展示了如何在 Python 中估计各种因素模型。我从最简单的单因素模型开始,然后解释如何估计更高级的三因素、四因素和五因素模型。

第 5 章,用 GARCH 类模型建模波动率,向读者介绍使用(G)ARCH 类模型进行波动率预测的概念,如何选择最佳拟合模型,以及如何解释结果。

第 6 章,金融中的蒙特卡罗模拟,向读者介绍了蒙特卡罗模拟的概念,以及如何使用它们来模拟股票价格、欧式/美式期权的估值和计算 VaR。

第 7 章,Python 中的资产分配,介绍了现代投资组合理论的概念,并展示了如何在 Python 中获得有效前沿。然后,我看如何确定具体的投资组合,如最小方差或最大夏普比率。我还展示了如何评估这种投资组合的表现。

第 8 章,用机器学习识别信用违约,介绍了一个用机器学习预测信用违约的案例。本章介绍了从加载数据,通过各种预处理阶段,以估计分类器的完整管道。

第 9 章,金融中的高级机器学习模型,介绍了高级分类器的选择(包括堆叠多个模型)。此外,我还研究了如何处理类不平衡,使用贝叶斯优化进行超参数调优,以及从模型中检索特性重要性。

第 10 章,金融领域的深度学习,演示了如何使用深度学习技术来处理时间序列和表格数据。使用 PyTorch 训练网络(可能有 GPU 加速)。

结论

总的来说,我很高兴承担了这本书的写作,并为完成这本书感到自豪。这需要大量的努力和决心。在这个过程中,我有过怀疑的时刻,但是来自我亲密的人的支持帮助我度过了难关。

我希望这本书能对那些想学习如何使用 Python 解决金融领域实际问题的人有所帮助。如果你有兴趣购买这本书,你可以在亚马逊或者 Packt 的网站上买到。

如果你对这本书的写作过程有任何问题,或者对这本书本身有任何反馈,我很乐意在评论中阅读。你也可以在推特上联系我。

下次见!

介绍可观察的、自我记录的 ELT

原文:https://towardsdatascience.com/introducing-observable-self-documenting-elt-41aa8b124098?source=collection_archive---------26-----------------------

Virevol ai 是一款协同视觉购物 app。我们经营一个远程优先的精益团队,已经有 2 年多了。为了施展我们的魔法,我们带着大量的数据畅游。

我们每天从数百个数据源中获取数百万行数据,在这些数据上运行我们的模型,并以各种方式为它们提供服务。我们在谷歌堆栈上,有 GCP 云功能、服务、容器,你能想到的都有。它们触发关于文件丢弃、队列消息、挂钩和时间表的其他事件。一切都是基于事件的,只是及时供应(我们很吝啬)。

我们的头脑中有太多的数据路径需要保留。

有了可观察的 ELT,我们可以通过匹配日志、输入、涉及它的每个作业的版本,追踪数据的来源,直到每一行。我们可以用美元做 ELT 会计,这是大多数 CTO 的白日梦。这使我们能够返工花费更多的管道部分,而不是所有遗留代码。

这就是我们保持理智的方法。我们如何在保持数据质量的同时快速发货?

数据如何移动

ETL 是一系列批处理作业。当一个完成时,下一个被触发。有时是两个,有时是 Y 形连接成一个。

你会得到一个有向图。图表很简单。

图表从上到下排列(如果您愿意,也可以从左到右排列)。

照片由马克·巴萨拉Unsplash 上拍摄

当中间的某个步骤中断或花费太长时间时,复杂性就产生了。想想鲁布·戈德堡机器。

或者更糟,如果什么都没发生。你会在理解数据的过程中发现错误。

为了管理这种复杂的管道协调,人们使用了各种各样的工具——Luigi、dbt、Airflow 等。

这是一种非常自上而下的乐器演奏方式。

最终用户只关心最后一步。如果报告需要在上午 9 点发出,而数据还没有准备好,你会接到电话。那是你的 SLA。

如果一项服务需要每 10 分钟为用户更新一次推荐,这就是您的 SLA。

遗憾的是,最终用户对 Dag 或花哨的工具不感兴趣。

当事情发生时,一个泪流满面的初级开发人员试图在凌晨 3 点调试“为什么”。她加入公司是为了涉足神经网络。但是被引诱,转而做 ETL。更糟糕的是,它被一些人称为“数据看门人的工作”,而不是它应该有的“数据 Lorax”。

她费力地翻阅一些本该发生的事情的文件。如果写这个的人还在那里工作,那就有点懈怠了。然后查看日志来搞清楚事情。如果她真的幸运的话,甚至可能会有一份关于这份工作的最新手册。她从 Pagerduty 跳到 JIRA,跳到 wiki,跳到 github,跳到日志。

鸟儿在远处歌唱,迎接黎明的到来。

可观察的 ELT

我们引入了一个新概念,叫做全局跟踪标识符,简称 tid。

每个将转换数据的函数、批处理作业或服务都需要获得一个特定运行的 tid。

它提供所有旧的 tid、其版本和实例变量(例如 X-AppEngine-QueueName、X-Appengine-Taskname)。这些记录在 service_tracker 表的 BigQuery 中。

下面是 python 中调用的样子

它必须用这个 tid 记录运行。

完成后,它必须将该行的 last_tid 列追加到这个。如果它是一个新行,它还必须将 tid 列填充到该行。向下滚动到“渐变尺寸”部分进行优化。

这是已经部署的 Google 功能,它可以满足我们的所有需求。

它是如何工作的?

让我们画一张图来概括这些情况:

这里 A,B,C,…F,都是不同的过程。各取一物,醒来,发一物,关机。但是我们不需要任何地方都有这样的记录图表。

那么我们如何产生它呢?

从插入到 D 末尾的表行的角度来看,我们有 A 的 tid,D 的 last_tid 跟踪到[B],B 跟踪到[A]。

所以我们知道,A -> B -> D ->这一行。我们可以跟踪这里的每一行,以及生成它的代码版本。

我们来做一个更复杂的案例。

从插入到 F 末尾的表行的角度来看,我们有 A 的 tid 和 last_tid F,它们跟踪到[E,D]的 tid。我们可以追踪列表中提到的每一个 tid 来反转图表。

当有东西损坏(F)时,我们不会在数据仓库中为它获得一行。我们无畏的开发人员可以看看前面的运行,它将 F 引用为 prev_tid(它们有时间戳)。然后,她可以直接调试 F 运行的日志,并会在 e。

她可以做所有这些事情而不需要问任何人。你仍然需要服务 F 的操作手册,就在 github 里。

她从 pagerduty 转到 Google logging 和 github 寻找代码和问题。如果她发现服务有问题,她可以从那里更新并推送代码,这将触发 CI/CD 测试。

她可以用代码记录下来,并指出帮助她找到问题的 tid。该代码是最好的“当前”文档。该表是指向它的指针的时间序列。

我们还可以做更多的事情,我们可以审计每张桌子生产需要多长时间,以及生产链中的哪些工作导致了这种情况。我们可以计算出链何时改变(ML 作业 C 被插入到组合中)。

我们可以通过查看每个服务每次运行的成本来确定哪些遗留代码需要返工。这提供了一种新的优化方法。我们的优化不仅仅是通过“感觉”哪个代码最让我们厌烦,而是通过一个目标函数——成本。

把它想象成剖析一个程序,除了你看到的是函数和美元,而不是子程序计时。

我们来谈谈小而重要的细节,以获得更好的结果。

ELT not ETL

因为你的数据在云中,移动数据是你的账单中最大的份额。尽可能用 ELT 代替 ETL。数据将直接在服务器上转换并保存下来,只需要最少的传输。

因为另一个原因,它会更快。BigQuery 和大多数现代数据仓库正在它们的大型服务器集群上为您进行 map-reduce。您必须加快 k8s 实例的速度,才能在大负载下获得相同级别的性能。

为了获得最大的收益,请使用特定于数据库的 SQL,而不是抽象来转换数据。在这种情况下,编写 SQL 是合适的工具。克服它。

SQL 能有多复杂?作为一个练习,这里的是用 SQL 计算 tf-idf,只是为了好玩(实际上你可以使用类似 spaCy 的东西,因为你可能需要更多的步骤)。您也可以从示例中获得使 SQL 令人愉快的样式技巧。

对于可观察的 ELT,使用 Google 函数获取 tid 并从字典中运行参数化的 SQL。

类似这样的事情,

如果可以在 SQL 中全部完成,那么直接使用 merge 语句会更快(参见示例)。

哦,确保你有测试用例来测试你现在所有的 SQL。

渐变尺寸

我们用另外三个细节来美化生活。

一种是将每个表包装在视图后面。所以一个名为‘学生’的表就变成了‘v _ 学生’。这使得重构变得容易。这是我在租跑道的时候发现的,并保存了下来。

二是用一个版本的 SCD type 2

对于大多数重要的表,每一行都只是被追加,并按时间分区。顶部的视图使用 added_ts 上的 rank()给出了该表的最新版本。

这可能看起来很浪费,但它让我们保持理智,存储成本也没有人们想象的那么高。当旧分区变得太大时,我们总是可以丢弃它。

最后,每份工作都可以重新开始。这通常是大多数成熟数据团队的标准,我就不赘述了。

对于可观察的 ELT,我们必须发明一些新工具,但是我们不需要任何其他外部工具来进行协调。它与 Google Cloud 任务队列、Pub/Sub 和 Apache Beam pipes 共存。

到目前为止,我们很开心。一旦我们有了一个稍微大一点的团队为 10 亿客户服务,我们会让你知道我们是否还在。

这些想法也可以扩展到日志记录。我们最近在日志记录上看到了这个主题,并且很高兴尝试一下。

如果这给了你任何关于你自己的 ETL 流程的想法,我们很乐意听到你的意见。这种分散的方法应该有助于您更快地发货。

如果你喜欢解决具有挑战性的问题,并且是非传统的思考者,请联系

引入明显无代码的机器学习解决方案

原文:https://towardsdatascience.com/introducing-obviouslyai-no-code-machine-learning-solution-da528c81071c?source=collection_archive---------34-----------------------

最佳数据科学自动化。

几天前,来自apparent . ai的几个人联系我,介绍他们的服务——一个完全无代码的机器学习自动化工具。起初我有点怀疑,因为我总是对所谓的全自动解决方案持怀疑态度,但我决定试一试。我将在本文中分享我的想法,并讨论服务是否值得一试。

埃克托尔·j·里瓦斯Unsplash 上拍摄的照片

我发现很难看到像这样的工具自动化机器学习,并减少中小型公司对机器学习工程师的需求。原因有很多,但最大的原因是机器学习的目的是自动化其他职业,但我们已经成功地用机器学习自动化了机器学习。干得好。

这并不完全是一件坏事,因为我们现在可以专注于更重要的事情,而不是一个接一个地拟合算法,目的是挤压额外的 0.15%的精度。

那么,什么是明显的 AI 呢?

他们的主页上的英雄部分解释得很好:

一次单击即可构建 ML 算法、解释结果和预测结果的整个过程。

在玩了一会儿之后,我必须说它确实有用。那么,这里面有什么蹊跷?好问题。在这个时代,我们已经习惯了昂贵的解决方案,显然 AI 也不例外。它有一个非常不错的免费计划,仅限于不超过 50,000 行的 CSV 文件。这对于基础探索来说绰绰有余了。

我目前在免费计划中,对我的需求来说已经足够了。我们现在将通过一个具体的例子,用这项服务训练一个机器学习模型,你会看到整个事情是多么愚蠢简单。

在我们开始之前,我想做一个简短的免责声明。尽管的人显然要求我审查他们的服务,但我与他们没有任何关系,我也不会试图说服你转而使用付费账户。我说的一切纯粹基于免费版。

注册和设置

就在这一步,第一件怪事发生了。我已经打开了注册页面,并被提示输入一个电子邮件。奇怪的是,我的个人 Gmail 账户没有资格注册。

一个商业电子邮件帐户是必须的。

我有一个公司的商业电子邮件账户,所以这不是问题,但对你们中的一些人来说可能是一个障碍。我无法证实其他电子邮件提供商是否发生了同样的事情,但 Gmail 目前无法工作。奇怪。

然而,我已经完成了注册过程并验证了电子邮件地址,然后我看到了一个漂亮的仪表板:

有一些内置的样本数据集,但我想这些工作完美无缺。我们不会将这些用于我们的机器学习任务,而是将使用一个众所周知的葡萄酒数据集。让我们在下一部分建立一个模型。

建立模型

如前所述,这一步非常简单。首先要做的是上传数据集。我们将使用侧边栏上的添加数据集按钮来完成此操作:

单击后,应该会出现一个模态,我们可以在上面拖放(或单击以上传)数据集。记住这些约束(免费版):

  • 文件大小必须小于 25MB
  • 必须至少有 1000 行
  • 必须至少有 5 列

我们的葡萄酒数据集通过了所有这些条件,所以我们可以上传它:

上传完成后,我们将进入这个展示良好的探索模式:

从这里开始,我们只需要按照说明。让我们点击用于预测按钮。我们几乎完成了准备工作。在下一个模态窗口中,我们只需要选择目标变量:

就是这样!服务抱怨我们应该减少目标变量中唯一值的数量,但是我们可以忽略这一点。要完成,只需点击开始预测按钮。你要做的就是这些。

模型被训练。完成了。就这么简单。

这并不意味着这个模型是好的,所以我们将在下一节探讨它的表现。

模型评估

一旦模型经过训练,我们就会看到报告仪表板。它由几个部分组成:

  • 司机
  • 人物角色
  • 出口预测
  • 高级分析
  • 技术规格

我们将在这里探索其中的几个,第一个是驱动区域。

司机区

简单地说,这个区域告诉我们哪些变量对预测最重要,因此哪些变量的预测能力最强。在我们的例子中,变量densityalcoholfree_sulfur_dioxide是前 3 个:

格式美观,易于理解。我们继续吧。

导出预测区域

如果不对新的、以前看不见的数据进行预测,机器学习就没有意义。不幸的是,这正是免费版的不足之处。我们可以通过上传以前未见过的数据的 CSV 来进行预测——只有属性,没有目标变量。

免费版提供的就这些。对你来说可能已经足够了,但我期待看到更多。

付费版本得到的是 REST API 形式的模型的部署版本,这使得从任何编程语言进行预测都容易得多:

不幸的是,免费版不支持这个选项,但是你能责怪他们吗?

技术规格区

此区域显示有关模型的一些基本信息,例如使用了哪种算法,训练、测试和验证子集的准确度如何,等等:

这是一个很好的部分,可以让你对你的模型有一个基本的了解,但仅此而已。

显然,这篇介绍性文章到此就差不多了。让我们在下一部分总结一下。

在你走之前

简而言之,显然很棒,也是一个值得推荐的简单服务。对于中小型企业,我甚至可以将它视为唯一的数据科学解决方案,由一个或多个软件开发人员维护,他们通过几次点击来训练模型,并通过 API 调用来进行预测。

当然,数据科学团队可以提供更好的解决方案,但该团队可能每月花费数万美元,而该解决方案最昂贵的选项每月不到 200 美元。你算算。

从一开始就很明显,数据科学将成为软件工程的另一种风格,但正是像这样的服务改变了即使是最顽固的个人的想法。

你有什么想法?你试过了吗?欢迎在评论区留下你的想法。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

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

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

加入我的私人邮件列表,获取更多有用的见解。

简介 Profiler,作者:Auptimizer:为您的目标设备选择最佳的人工智能模型——无需部署

原文:https://towardsdatascience.com/introducing-profiler-select-the-best-ai-model-for-your-target-device-no-deployment-required-91a396c4bfeb?source=collection_archive---------54-----------------------

剖析器 是一个用于剖析机器学习(ML)模型脚本性能的模拟器。探查器可以在开发管道的训练和推断阶段使用。它对于评估部署到边缘设备的模型和脚本的脚本性能和资源需求特别有用。Profiler 是au optimizer的一部分。您可以从auoptimizer GitHub 页面 获取 Profiler,或者通过 pip 安装 auoptimizer。

我们为什么要建立 Profiler

在过去几年里,云中训练机器学习模型的成本大幅下降。虽然这种下降将模型开发推到了云上,但是仍然有重要的原因来训练、适应和部署模型到设备上。性能和安全性是两大因素,但成本节约也是一个重要的考虑因素,因为传输和存储数据的成本以及为数百万台设备构建模型的成本往往会增加。毫不奇怪,尽管云计算变得更加便宜,但针对边缘设备或边缘人工智能的机器学习继续成为主流。

为边缘开发模型为从业者带来了有趣的问题。

  1. 型号选择现在包括考虑这些型号的资源需求。
  2. 由于在回路中有一个设备,训练-测试周期变得更长,因为现在需要在设备上部署模型来测试其性能。只有当有多个目标设备时,这个问题才会被放大。

目前,有三种方法可以缩短型号选择/部署周期:

  • 使用在开发机器上运行的特定于设备的模拟器,不需要部署到设备上。警告:模拟器通常不能跨设备通用。
  • 使用目标设备自带的分析器。警告:他们需要将模型部署到目标设备上进行测量。
  • 使用 FLOPS 或乘加(MAC)运算等方法来给出资源使用的近似度量。警告:模型本身只是整个管道(还包括数据加载、增强、特征工程等)的一部分(有时是无关紧要的)。)

在实践中,如果您想要选择一个能够在目标设备上高效运行的模型,但是无法访问专用的模拟器,那么您必须通过在所有目标设备上部署来测试每个模型。

Profiler 有助于缓解这些问题。 Profiler 允许您在开发机器上模拟您的训练或推理脚本将如何在目标设备上执行。使用 Profiler,您可以了解 CPU 和内存的使用情况,以及目标设备上模型脚本的运行时间。

探查器的工作原理

Profiler 将模型脚本、它的需求和相应的数据封装到 Docker 容器中。它使用用户输入的计算、内存和框架约束来构建相应的 Docker 映像,因此脚本可以独立运行,不依赖外部。然后,可以轻松地对该映像进行缩放和移植,以简化未来的开发和部署。当模型脚本在容器中执行时,分析器跟踪并记录各种资源利用率统计信息,包括平均 CPU 利用率内存利用率网络 I/O块 I/O 。记录器还支持设置采样时间,以控制 Profiler 从 Docker 容器中采样利用率统计信息的频率。

获取分析器:单击此处

探查器如何帮助

我们的结果表明,Profiler 可以帮助用户为许多流行的图像/视频识别模型建立良好的模型运行时间和内存使用估计。我们在三种不同的设备上进行了 300 多次实验,这些设备包括各种型号(InceptionV3、SqueezeNet、Resnet18、mobilenet v2–0.25 x、-0.5x、-0.75x、-1.0x、3D-SqueezeNet、3D-shuffle net v2–0.25 x、-1.0x、-1.5x、-2.0x、3D-mobilenet v2–0.25 x、-0.5x、-0.75x、-1.0x、-2.0x)您可以在这里找到全套实验结果以及如何在您的设备上进行类似实验的更多信息

Profiler 的加入使 Auptimizer 更接近一种工具的愿景,这种工具可以帮助机器学习科学家和工程师为边缘设备建立模型。au optimizer 的超参数优化(HPO)功能有助于加快模型发现。Profiler 有助于选择正确的部署模型。它在以下两种情况下特别有用:

  1. 在模型之间做出决定——使用开发机器上的 Profiler 测量的模型脚本的运行时间和内存使用情况的排名表明了它们在目标设备上的排名。例如,如果在开发机器上使用 Profiler 测量时,Model1 比 Model2 快,那么在设备上 Model1 将比 Model2 快。只有当 CPU 满负荷运行时,这个排名才有效。
  2. 预测设备上的模型脚本性能—一个简单的线性关系将使用开发机器上的探查器测量的运行时间和内存使用情况与使用目标设备上的本机分析工具测量的使用情况联系起来。换句话说,如果一个模型在使用 Profiler 测量时运行时间为 x,那么它在目标设备上的运行时间大约为(a*x+b)(其中 a 和 b 可以通过使用本机分析工具分析设备上的几个模型来发现)。这种关系的强度取决于模型之间的架构相似性,但是,通常,为相同任务设计的模型在架构上是相似的,因为它们由相同的一组层组成。这使得 Profiler 成为选择最适合的模型的有用工具。

展望未来

分析器在不断发展。到目前为止,我们已经在选定的移动和边缘平台上测试了它的功效,用于运行流行的图像和视频识别模型进行推理,但还有更多需要探索。探查器可能对某些型号或设备有限制,可能会导致探查器输出和设备上的测量值不一致。我们的实验页面提供了更多关于如何使用 Profiler 设置您的实验以及如何解释结果中潜在的不一致的信息。确切的用例因用户而异,但我们相信 Profiler 适用于任何在设备上部署模型的人。我们希望 Profiler 的评估功能能够为资源受限的设备提供更精简、更快速的模型开发。我们很乐意听到(通过 github)您是否在部署期间使用 Profiler。

作者: Samarth Tripathi、Junyao Guo、Vera Serdiukova、Unmesh Kurup 和 Mohak Shah——LG 电子美国公司高级人工智能

PyLathe 简介:使用 Julia 在 Python 中使用车床

原文:https://towardsdatascience.com/introducing-pylathe-use-lathe-in-python-using-julia-6f67a7aaa6f9?source=collection_archive---------23-----------------------

什么是语言界限?

使用 PyLathe

Py 车床 0.1.0 已经在 Github 和 Python 包索引(PyPi)中正式发布。)当然,PyLathe 通过它将车床的美妙舒适带入了 Python,但也有一些警告,希望这些问题能在模型的未来版本中得到解决。要安装 PyLathe,就像使用 Pip 一样简单:

sudo pip(3) install PyLathe

注意:这个模块与 Python 2 不兼容。

在 0.1.0 之前的几次迭代中,您必须实例化您的 Lathe 包,并包含一个用于将添加到您的环境中的 Lathe 源文件的目录。所有这些都使得安装非常复杂,谢天谢地,现在已经改变了。从模块中,我们将需要一个名为“ClassicEnvironment”的类,来自库“Runtime”。

环境

环境是 Python 和 Lathe 之间面向对象的桥梁。“ClassicEnvironment”是一个使用系统范围的 Julia 环境来实例化 Julia 包的环境。虽然目前没有其他可用的环境,但在未来,虚拟环境和多环境都将可用。虚拟环境将在后端为 Julia 运行时即时创建一个虚拟环境。另一方面,多环境将允许在虚拟环境之间切换,包括全局环境。

营造环境

创建我们的环境的第一步是确保我们有正确的包。PyLathe 唯一依赖的 Python 包是 julia.py,所以我们需要它。好消息是包管理器 Pip 应该为您处理所有这些事情。也就是说,基于 Debian/Ubuntu 的发行版中的 julia.py 包有一个已知的缺陷。由于我使用 Fedora,这不会影响我,通过一些实验,它可能会得到解决。该问题源于 Debian 上的 Apt 包管理器将 Julia 可执行文件放在了与预期不同的目录中。

当然,安装 Julia 也是至关重要的,最好安装了车床和数据框架(车床依赖于它)。好消息是,如果你不知道如何做,或者不想做这一步,你不必做!只要能够找到 Julia 可执行文件,该模块就应该可以加载,并且会在初始化时安装车床。所以让我们

来自车床。运行时导入经典环境

应该注意的是,在这个包的早期版本中,没有测试,也没有异常处理,这是使用这个包最大的潜在障碍。

现在,我们可以像构建其他变量一样构建我们的环境:

在加载和初始化方面,就是这样!我们的环境已经完全加载完毕,随时可以运行!

构建工具

从这个环境中,我们现在可以通过首先为 Julia 构造一个包管理器(Pkg)来导入我们可能需要的任何 Julia 包。)这也很简单,代码如下:

pacman = env.pacman

然后我们可以像使用 Pkg 一样使用 pacman 变量,方法如下

Pkg.add()

虽然这是一个基本的、原始的版本,但是这种通过 Python 访问 Julia 的面向对象的方法无疑是非常酷的,并且在未来的虚拟环境中具有很好的可伸缩性。

为了导入一个车床模块,我们可以使用 import__()功能:

但是机器学习呢?

机器学习

处理数据

机器学习在 PyLathe 中的工作方式是完全正确的,很少有问题会危及这一点。这些问题中的一些可能会不时暴露出来,但在大多数情况下,并不是什么大不了的事情。关于使用 PyLathe 的好消息是现在我们在 Python 中,这带来了 Python 的巨大优势!

包装

这是一个正式的自由世界,因为现在我们不必自己写所有的东西。

所以我决定引进熊猫,并着手获取一个数据帧

df = pd.read_csv("path/to/my/csv")

如果你想使用这个数据集,或者像往常一样下载这个笔记本,这里有一个链接!

数据(直接)

笔记本(Github)

这就是熊猫更好的原因。

我喜欢在一个新的数据帧上做的第一件事,特别是像这样的快速拟合,是得到一个空计数。幸运的是,对于熊猫来说,这很容易:

df.isnull()。总和()

数据科学家的任务之一就是明智地处理未定义的值。考虑到这并不严重,我认为没有必要去填补这些缺失的值。幸运的是,眼尖的人可能已经意识到我的空值只在一列中。一部经典的新秀电影应该是

df = df.dropna()

但是不要那么做。如果我们现在放弃未定义的值,我们将丢失 517 个观察值。相反,我们可以删除该列,如下所示:

或者你可以像我一样,创建一个全新的数据框架:

统计数据

我决定从 Lathe.stats 执行一个简单的 f 检验,只是为了看看我假设可能相关的两个特征是否确实相关。首先,我使用条件掩码根据温度中心分离数据,然后应用它:

# This will create a boolean mask that
#    we can use to apply a filter to our
#  df
lowtemp = df['Temperature (C)'] <= 0
# Now we filter our dataframe:
temp_test_df = df[lowtemp]

然后通过我的环境导入统计数据:

stats = env.importStats()

然后应用 f 检验,看看我们在处理什么样的显著性。

测试/训练分离

在没有任何信心的情况下,我尝试通过从环境中导入来使用来自 Lathe.preprocess 的 TestTrainSplit 函数,没有人会感到惊讶:

它不起作用

当然,这是因为熊猫数据帧是 Python 构造的对象,而不是数据。为了解决这个问题,我试着使用字典:

那也失败了

当然有办法解决这个问题,通过构造一个 Julia DataFrames.jl DataFrame,然后通过函数传递它,唯一的问题是它将返回两个 DataFrames.jl DataFrames,而不是两个 Pandas DataFrames。所以,有了路障,

还是用 Sklearn 吧!

我还冒昧地设置了我们的 X 和 Y,这是很容易理解的(因为这对初学者来说不一定)。)我会说要小心数组形状,因为 Python 处理类型的方式可能有点不可靠,而车床是用 Julia 编写的,所以当然不遵守这一约束。例如,一个系列是一个列表(一个数组),但是可能需要被重新整形为一维数组,以便为 Sklearn 工作。

不要这样对皮拉思。

模型拟合

为了适应模型,我们需要从我们的环境中导入车床模型。我们用和其他人一样的方法做这件事,

# Import models into our environment
models = env.importModels()

我决定应用 Z 分数归一化算法,也称为标准标量。我们可以用最简单明了的方式在 Python 的两个 X 上调用它:

# Let's apply a standard scaler from Lathe.preprocess, as well:
trainX = preprocess.StandardScalar(trainX)
# (To both X's)
testX = preprocess.StandardScalar(testX)

如果你已经知道车床,我想这将是非常自然的。

现在使用 Lathe.models: predict 和 Lathe.models: LinearRegression,我们可以将我们的模型构造为一个 Python 对象,然后在没有 yhat 的情况下将其插入预测方法。

这个数据的方差看起来并没有那么高,但是这个模型确实是正确的。

最后的想法

首先,PyLathe——非常酷。虽然它还处于早期阶段,但是将不同的语言视为相同的语言绝对是非常棒的。我希望看到的未来改进包括:

  • 虚拟环境!
  • 速度——与运行本地 Julia 相比,调用 Julia 相当慢,这正是未来的计划。
  • 灵活性——进一步使用包管理器来利用更多的包与车床一起使用。

总的来说,虽然将来会有改进,但我真的很喜欢 PyLathe。PyLathe 很棒,因为它完全由 Julia 模块版本本身维护,并且无论在什么情况下都可以使用 Julia 的模块版本。如果您想了解车床的所有“特色”,包括正在开发的 Lathe.lisp 和未来的车床。r 包,这些链接可以在车床内部找到。

[## emmettgb/Lathe.jl

有关发布画布的信息,请访问项目选项卡 Lathe.jl 是用于预测建模的一体化软件包…

github.com](https://github.com/emmettgb/Lathe.jl/tree/Unstable)

介绍 Python 的 Functools 模块

原文:https://towardsdatascience.com/introducing-pythons-functools-module-2c4cba4774e?source=collection_archive---------15-----------------------

处理高阶函数和可调用对象

阿里安·达尔维什在 Unsplash 上拍摄的照片

介绍

functools 模块是 Python 标准库的一部分,它提供了一些有用的特性,使得使用高阶函数(返回一个函数或接受另一个函数作为参数的函数)变得更加容易。有了这些特性,您可以重用或扩展函数或可调用对象的效用,而无需重写它们。这使得编写可重用和可维护的代码变得非常简单。

根据当前的稳定版本,即 Python 3.8 系列,functools 模块包含 11 个函数,其中一些可能不可用,或者在早期或后期版本中工作方式不同。它们包括:

  1. 减少()
  2. lru_cache()
  3. 偏()
  4. partialmethod()
  5. singledispatch()
  6. singledispatchmethod()
  7. cached_property()
  8. total_ordering()
  9. 更新 _ 包装()
  10. wrapps()
  11. cmp_to_key()

我们将简要讨论每一个,然后借助例子,说明它们的用法和功能。

1.减少()

首先我们有一个经典。 reduce(function,sequence) 函数接收两个参数,一个函数和一个 iterable。它从左到右对 iterable 的所有元素累积应用 argument 函数,然后返回一个值。

简单地说,它首先将参数函数应用于 iterable 的前两个元素,第一次调用返回的值成为函数的第一个参数,iterable 的第三个元素成为第二个参数。重复这个过程,直到可迭代次数用完。

例如,reduce()可用于轻松计算列表的总和或乘积。

在第一个例子中 reduce(lambda a,b: a + b,[1,2,3,4]) 计算((1+2)+3)+4)并返回列表的总和 10。

2.lru_cache()

lru_cache()是一个 decorator,它用一个 memoizing callable 来包装一个函数,该函数用于保存一个函数调用的结果,如果用相同的参数再次调用该函数,则返回存储的值。当使用相同的参数定期调用昂贵的或 I/O 受限的函数时,它可以节省时间。

本质上,它使用两种数据结构,一个字典将函数的参数映射到结果,一个链表跟踪函数的调用历史。

在全 LRU 缓存中,代表最近最少使用的缓存,指的是在达到最大条目大小时丢弃最近最少使用的元素的缓存。如果 maxsize 设置为 None,则禁用 LRU 功能;如果 typed 为 True,则分别缓存不同数据类型的参数,例如, f(3)f(3.0) 将被明确缓存。

lru_cache()实用程序的一个例子可以在优化生成数字阶乘的代码中看到

在没有 @lru_cache 的情况下,阶乘函数需要大约 1.46 s 来运行,而另一方面,使用 @lru_cache,该函数只需要 158 ns。这相当于性能提高了近 100,000 倍——太神奇了!对吗?

通常,仅当您想要重用之前计算的值时,才应使用 LRU 缓存。因此,缓存需要在每次调用时创建不同可变对象的函数是没有意义的。此外,由于使用字典来缓存结果,函数的位置和关键字参数必须是可哈希的。

3.部分()

部分函数是具有一些预先分配的输入参数的派生函数。例如,如果一个函数有两个参数,比如" a" 和" b" ",那么可以从它创建一个分部函数,将" a" 作为预填充的参数,然后可以使用" b" 作为唯一的参数来调用它。Functool 的 partial()用于创建分部函数/对象,这是一个有用的特性,因为它允许:

  1. 复制已经传入了一些参数的现有函数。
  2. 以记录良好的方式创建现有功能的新版本。

让我们考虑一个简单的例子来说明这一点

我们首先基于 math.perm() 函数创建一个分部对象。在这种情况下,我们将 9 设置为第一个参数。因此,新创建的 permutation_of_nine 函数的行为就像我们调用 math.perm() 并将 9 设置为默认参数一样。在我们的例子中, permutation_of_nine(2)math.perm(9,2)做同样的事情。

需要注意的是, namedoc 属性是由程序员指定的,因为它们不是自动创建的

partial 函数还带有一些重要的属性,这些属性在跟踪 partial 函数/对象时非常有用。其中包括:

  • partial . args—返回预先分配给分部函数的位置参数。
  • partial . keywords—返回预先分配给分部函数的关键字参数。
  • partial.func —返回父函数的名称及其地址。

让我们看另一个说明这些特征的例子

偏旁非常有用。例如,在函数调用的管道序列中,一个函数的返回值是传递给下一个函数的参数。

4.partialmethod()

partialmethod() 返回一个新的 partialmethod 描述符,其行为类似于 partial ,只是它被设计为用作方法定义,而不是可直接调用的。你可以把它看作是方法的 partial()

也许一个例子最适合说明这一点。

我们首先创建一个动物类,它有一个属性物种和一个实例方法 _set_species() 来设置动物的物种。接下来,我们创建两个 partialmethod 描述符 set_dog()set_rabbit() ,分别用“狗”或“兔子”调用 _set_species() 。这允许我们创建动物类的一个新实例,调用 set_dog() 将动物的种类改为 dog,最后打印新的属性。

5.singledispatch()

在我们讨论这个函数之前,我们首先要弄清楚两个重要的概念,这很重要:

  • 第一个是通用函数,它是由对不同类型实现相同操作的多个函数组成的函数。呼叫期间使用的实现由调度算法决定。
  • 第二种是单一分派,这是一种通用函数分派的形式,根据单一参数的类型选择实现。

考虑到这一点,functool 的 singledispatch 是一个装饰器,它将一个简单函数转换成一个通用函数,其行为取决于其第一个参数的类型。用简单的语言来说,它用于函数重载

让我们来看一个实际例子。

我们首先定义一个函数 divide() ,它接受两个参数 ab ,并返回 a/b 的值。然而,分割字符串会导致一个 类型错误 ,为了处理这个问题,我们定义了 _ functions,它指定了 divide() 的行为,如果它是由字符串提供的话。注意,重载的实现是使用通用函数的 register() 属性注册的

6.singledispatchmethod()

它是一个装饰器,做的事情和 @singledispatch 完全一样,但是它是为方法而不是函数指定的。

考虑下面的例子。

Product 类的 prod 方法被重载以返回一个列表或集合的元素的乘积,但是如果提供了不同的类型,默认情况下,它会引发一个notimplementererror

7.cached _ property()

顾名思义, cached_property() 是一个装饰器,它将一个类方法转换成一个属性,该属性的值只计算一次,然后作为实例生命周期中的一个普通属性进行缓存。它类似于 @property ,除了它的缓存功能。这对于实例的计算开销很大的属性很有用,否则这些属性实际上是永久的。

在上面的例子中,我们有一个数据集类,它保存了一个观察值列表,并实现了计算方差和标准差的方法。问题是,每次调用这些方法时,都必须重新计算方差和标准差,这可能证明是非常昂贵的,尤其是对于大型数据集。 @cached_property 通过只计算和存储一次值来缓解这个问题,如果该方法被同一个实例再次调用,则返回该值。

8.total_ordering()

给定一个定义了一个或多个富比较排序方法即 _ lt_()、le()、_ _ gt _ _()eq() (对应 <、< =、>、> ==)。您可以定义一些比较方法, @total_ordering 会根据给定的定义自动提供其余的方法。重要的是,该类应该提供一个 eq() 方法。

例如,如果您想创建一个比较不同数字的类。您可能需要实现所有丰富的比较方法。然而,这可能是相当繁琐和多余的,要解决这个问题,你只能实现 _ eq_gt 方法,并使用 @total_ordering 来自动填充其余的。

不过有一个限制,使用 @total_ordering 会增加的开销导致执行速度变慢。此外,派生比较方法的堆栈跟踪更加复杂。因此,如果您需要高效的代码,明智的做法是自己显式地实现比较方法

9.更新包装器()

它更新包装函数的元数据,使之看起来像被包装的函数。例如,对于分部函数,update _ wrapper(partial,parent) 将更新分部函数的文档( doc )和名称( name )以匹配父函数。

10.换行()

这是一个方便调用 update_wrapper() 到修饰函数的函数。相当于运行partial(update _ wrapper,wrapped=wrapped,assigned=assigned,updated=updated)

举个例子,

11.cmp_to_key()

它将旧式的比较函数转换为关键函数。比较函数是任何可调用的函数,它接受两个参数,对它们进行比较,返回负数表示小于,返回零表示等于,返回正数表示大于。键函数是一个可调用函数,它接受一个参数并返回另一个值以用作排序键,一个例子是operator . item getter()键函数。sorted()min()max()ITER tools . group by()等工具中都用到关键函数。

cmp_to_key() 主要用作 Python 2 编写的支持比较函数的程序的转换工具。

让我们举一个例子,说明如何使用比较函数根据首字母对字符串列表进行排序,以说明 cmp_to_key() 的用法

结论

在本文中,我们已经学习了 functools 模块,希望您现在已经了解了如何使用它来实现高阶函数,并编写高度健壮、可读和可重用的代码。

祝你好运,编码愉快,愿 bug 在你的力量面前颤抖。

meme-arsenal 制作的图像

PyTorch 预测简介

原文:https://towardsdatascience.com/introducing-pytorch-forecasting-64de99b9ef46?source=collection_archive---------1-----------------------

PyTorch 预测示例

最先进的神经网络预测变得简单

我很高兴地宣布开源 Python 包 PyTorch 预测。对于数据科学从业者和研究人员来说,它使得用神经网络进行时间序列预测变得简单。

为什么准确预测如此重要?

预测时间序列在许多情况下都很重要,并且与机器学习实践者高度相关。举个例子,需求预测是许多用例的来源。几乎每个制造商都会受益于更好地了解对其产品的需求,从而优化生产数量。生产不足,你会损失收入,生产过度,你将被迫折价出售多余的产品。与此密切相关的是定价,它本质上是一种需求预测,特别关注价格弹性。定价几乎与所有公司都相关。

对于大量额外的机器学习应用,时间是至关重要的:预测性维护、风险评分、欺诈检测等。—你说吧。事件的顺序和它们之间的时间对于创建可靠的预测至关重要。

事实上,虽然时间序列预测可能不像图像识别或语言处理那样耀眼,但它在工业中更常见。这是因为图像识别和语言处理对该领域来说相对较新,通常用于推动新产品,而预测已经存在了几十年,是许多决策(支持)系统的核心。采用高精度机器学习模型,如 PyTorch 预测 中的模型,可以更好地支持决策制定,甚至使其自动化,往往会直接带来数百万美元的额外利润。

深度学习成为一种强大的预测工具

深度学习(神经网络)只是在最近才在时间序列预测方面超过传统方法,而且与图像和语言处理相比,差距较小。事实上,在预测纯时间序列(这意味着没有协变量,例如,价格对需求)时,深度学习仅在两年前就已经超越了传统的统计方法 [1]。然而,随着该领域的快速发展,与神经网络相关的准确性优势变得显著,这使得它们在时间序列预测中的应用越来越多。例如,最新的架构 N-BEATS 在 M4 竞赛数据集上显示,与下一个最好的非基于神经网络的方法(即统计方法的集合)相比,sMAPE 减少了 11%。这个网络也在 PyTorch 预报中实现。

此外,即使与其他流行的机器学习算法(如梯度提升树)相比,深度学习也有两个优势。首先,神经网络架构可以设计为具有对时间的固有理解,即它们自动在时间上接近的数据点之间建立连接。因此,它们可以捕捉复杂的时间依赖关系。相反,传统的机器学习模型需要手动创建时间序列特征,例如过去 x 天的平均值。这削弱了这些传统机器学习算法对时间依赖性建模的能力。第二,大多数基于树的模型通过设计输出阶跃函数。因此,它们不能预测投入变化的边际影响,而且,众所周知,在域外预测中它们是不可靠的。例如,如果我们只观察到 30 欧元和 50 欧元的价格,则基于树的模型无法评估价格从 30 欧元变为 35 欧元对需求的影响。因此,它们通常不能直接用于优化投入。然而,这通常是创建机器学习模型的全部目的——价值在于协变量的优化。与此同时,神经网络采用连续激活函数,尤其擅长高维空间的插值,即它们可用于优化输入,如价格。

什么是 PyTorch 预测?

PyTorch Forecasting 旨在通过神经网络简化现实世界案例和研究的时间序列预测。它通过提供最先进的时间序列预测架构来做到这一点,这些架构可以通过 pandas 数据框架轻松训练。

  • 这个高级 API 极大地减少了用户的工作量,因为不需要具体的知识来准备使用 PyTorch 进行训练的数据集。TimeSeriesDataSet类负责变量转换、缺失值、随机子采样、多历史长度等。您只需要提供 pandas 数据框架,并指定模型应该学习哪些变量。
  • BaseModel类提供了通用的可视化,比如显示预测与实际值和部分依赖图。培训进度以指标和示例的形式自动记录在 tensorboard 中。
  • 国家的最先进的网络实施预测有和没有协变量。它们还带有专用的内置翻译功能。例如,时态融合转换器 [3]在基准测试中击败了亚马逊的 DeepAR 36–69 %,提供了变量和时间重要性测量。在下面的例子中可以看到更多。
  • 存在许多多时段时间序列指标来评估多个预测时段的预测。
  • 为了实现可扩展性,网络被设计为与 PyTorch Lightning 一起工作,后者允许对 CPU 和单个及多个(分布式)GPU 进行开箱即用的培训。Ranger 优化器用于更快的模型训练。
  • 为了便于实验和研究,增加网络是很简单的。代码是专门为 PyTorch 专家设计的。他们会发现即使是复杂的想法也很容易实现。事实上,为了立即启用日志和解释功能,只需从BaseModel类继承并遵循 forward 方法输入和输出的约定。

首先,文档展示了端到端工作流中的详细教程。我还将在本文后面讨论一个具体的例子。

我们为什么需要这个包?

PyTorch 预测 有助于克服深度学习用法的重要障碍。虽然深度学习已经在图像和语言处理中占据主导地位,但在时间序列预测中却不那么重要。该领域仍由传统的统计方法(如 ARIMA)和机器学习算法(如梯度推进)占据主导地位,贝叶斯模型例外。深度学习尚未成为时间序列预测主流的原因有两个,所有这些都已经可以克服:

  1. 训练神经网络几乎总是需要 GPU,而 GPU 并不总是容易获得。硬件需求通常是一个重要的障碍。然而,通过将计算转移到云中,这个障碍是可以克服的。
  2. 神经网络比传统方法更难使用。时间序列预测尤其如此。缺少一个与流行框架协同工作的高级 API,如脸书的 PyTorch 或谷歌的 Tensorflow。对于传统的机器学习,sci-kit learn 生态系统的存在为从业者提供了一个标准化的界面。

这第三个障碍在深度学习社区被认为是至关重要的,因为它的用户友好性需要大量的软件工程。下面的推文总结了许多人的情绪:

深度学习实践者的典型观点

有些人甚至认为该声明微不足道:

简单来说, PyTorch 预测 旨在做fast . ai为图像识别和自然语言处理所做的事情。这极大地促进了神经网络从学术界向现实世界的扩散。 PyTorch Forecasting 试图通过为 PyTorch 提供一个可以直接使用 pandas dataframes 的高级 API 来做时间序列预测的等效工作。为了便于学习,与 fast.ai 不同,该软件包没有创建一个全新的 API,而是建立在成熟的 PyTorchpy torch LightningAPI 的基础上。

如何使用 PyTorch 预测?

这个小例子展示了这个包的强大功能及其最重要的抽象。我们将

  1. 创建训练和验证数据集,
  2. 训练时间融合变压器【2】。这是一个由牛津大学和谷歌开发的架构,在基准测试中击败了亚马逊的 DeepAR 36–69 %,
  3. 检查验证集的结果并解释训练好的模型。

:以下代码仅适用于 PyTorch 预报 0.4.1 版和 PyTorch 闪电 0.9.0 版。运行最新版本只需很少的修改。最新代码的完整教程可以在这里找到。

创建用于训练和验证的数据集

首先,我们需要将时间序列转换成 pandas 数据框架,其中每一行都可以用时间步长和时间序列来标识。幸运的是,大多数数据集已经是这种格式了。对于本教程,我们将使用来自 Kaggle 的 Stallion 数据集来描述各种饮料的销售。我们的任务是对库存单位(SKU)的销售量进行六个月的预测,即由代理机构(即商店)销售的产品。大约有 21 000 个月的历史销售记录。除了历史销售额之外,我们还有销售价格、代理机构的位置、特殊日子(如节假日)以及整个行业的销售量等信息。

from pytorch_forecasting.data.examples import get_stallion_datadata = get_stallion_data()  # load data as pandas dataframe

数据集的格式已经正确,但缺少一些重要的功能。最重要的是,我们需要添加一个时间索引,每个时间步长递增 1。此外,添加日期特性是有益的,在这种情况下,这意味着从日期记录中提取月份。

# add time index
data["time_idx"] = data["date"].dt.year * 12 + data["date"].dt.monthdata["time_idx"] -= data["time_idx"].min()# add additional features
# categories have to be strings
data["month"] = data.date.dt.month.astype(str).astype("category")
data**[**"log_volume"**]** **=** np**.**log**(**data**.**volume **+** **1e-8)**
data**[**"avg_volume_by_sku"**]** **=** (
    data
    **.**groupby**([**"time_idx"**,** "sku"**],** observed**=True)
    .**volume**.**transform**(**"mean"**)** )
data**[**"avg_volume_by_agency"**]** **=** (
    data
    **.**groupby**([**"time_idx"**,** "agency"**],** observed**=True)
    .**volume**.**transform**(**"mean"**)
)**# we want to encode special days as one variable and 
# thus need to first reverse one-hot encoding
special_days = [
    "easter_day", "good_friday", "new_year", "christmas",
    "labor_day", "independence_day", "revolution_day_memorial",
    "regional_games", "fifa_u_17_world_cup", "football_gold_cup",
    "beer_capital", "music_fest"
]data[special_days] = (
    data[special_days]
    .apply(lambda x: x.map({0: "-", 1: x.name}))
    .astype("category")
)# show sample data
data.sample(10, random_state=521)

来自数据帧的随机行样本

下一步是将数据框架转换成 PyTorch 预测数据集。除了告诉数据集哪些特征是分类的,哪些是连续的,哪些是静态的,哪些是随时间变化的,我们还必须决定如何归一化数据。这里,我们分别对每个时间序列进行标准标度,并指出值总是正的。

我们还选择使用过去六个月作为验证集。

from pytorch_forecasting.data import (
    TimeSeriesDataSet,
    GroupNormalizer
)max_prediction_length = 6  # forecast 6 months
max_encoder_length = 24  # use 24 months of history
training_cutoff = data["time_idx"].max() - max_prediction_lengthtraining = TimeSeriesDataSet(
    data[lambda x: x.time_idx <= training_cutoff],
    time_idx="time_idx",
    target="volume",
    group_ids=["agency", "sku"],
    min_encoder_length=0,  # allow predictions without history
    max_encoder_length=max_encoder_length,
    min_prediction_length=1,
    max_prediction_length=max_prediction_length,
    static_categoricals=["agency", "sku"],
    static_reals=[
        "avg_population_2017",
        "avg_yearly_household_income_2017"
    ],
    time_varying_known_categoricals=["special_days", "month"],
    # group of categorical variables can be treated as 
    # one variable
    variable_groups={"special_days": special_days},
    time_varying_known_reals=[
        "time_idx",
        "price_regular",
        "discount_in_percent"
    ],
    time_varying_unknown_categoricals=[],
    time_varying_unknown_reals=[
        "volume",
        "log_volume",
        "industry_volume",
        "soda_volume",
        "avg_max_temp",
        "avg_volume_by_agency",
        "avg_volume_by_sku",
    ],
    target_normalizer=GroupNormalizer(
        groups=["agency", "sku"], coerce_positive=1.0
    ),  # use softplus with beta=1.0 and normalize by group
    add_relative_time_idx=True,  # add as feature
    add_target_scales=True,  # add as feature
    add_encoder_length=True,  # add as feature
)# create validation set (predict=True) which means to predict the
# last max_prediction_length points in time for each series
validation = TimeSeriesDataSet.from_dataset(
    training, data, predict=True, stop_randomization=True
)# create dataloaders for model
batch_size = 128
train_dataloader = training.to_dataloader(
    train=True, batch_size=batch_size, num_workers=0
)
val_dataloader = validation.to_dataloader(
    train=False, batch_size=batch_size * 10, num_workers=0
)

训练时间融合转换器

现在是时候创建我们的模型了。我们用 PyTorch 闪电训练模型。在培训之前,您可以使用学习率查找器确定最佳学习率(参见文档中的示例)。

import pytorch_lightning as pl
from pytorch_lightning.callbacks import (
    EarlyStopping,
    LearningRateLogger
)
from pytorch_lightning.loggers import TensorBoardLogger
from pytorch_forecasting.metrics import QuantileLoss
from pytorch_forecasting.models import TemporalFusionTransformer# stop training, when loss metric does not improve on validation set
early_stop_callback = EarlyStopping(
    monitor="val_loss",
    min_delta=1e-4,
    patience=10,
    verbose=False,
    mode="min"
)
lr_logger = LearningRateLogger()  # log the learning rate
logger = TensorBoardLogger("lightning_logs")  # log to tensorboard# create trainer
trainer = pl.Trainer(
    max_epochs=30,
    gpus=0,  # train on CPU, use gpus = [0] to run on GPU
    gradient_clip_val=0.1,
    early_stop_callback=early_stop_callback,
    limit_train_batches=30,  # running validation every 30 batches
    # fast_dev_run=True,  # comment in to quickly check for bugs
    callbacks=[lr_logger],
    logger=logger,
)# initialise model
tft = TemporalFusionTransformer.from_dataset(
    training,
    learning_rate=0.03,
    hidden_size=16,  # biggest influence network size
    attention_head_size=1,
    dropout=0.1,
    hidden_continuous_size=8,
    output_size=7,  # QuantileLoss has 7 quantiles by default
    loss=QuantileLoss(),
    log_interval=10,  # log example every 10 batches
    reduce_on_plateau_patience=4,  # reduce learning automatically
)
tft.size() # 29.6k parameters in model# fit network
trainer.fit(
    tft,
    train_dataloader=train_dataloader,
    val_dataloaders=val_dataloader
)

在我的 Macbook 上,训练大约需要三分钟,但对于更大的网络和数据集,可能需要几个小时。在训练过程中,我们可以监控张量板,它可以用tensorboard --logdir=lightning_logs旋转起来。例如,我们可以监控训练集和验证集上的示例预测。如下图所示,预测看起来相当准确。如果你想知道,灰线表示模型在进行预测时对不同时间点的关注程度。这是时间融合转换器的一个特殊功能。

显示训练示例的 Tensorboard 面板

评估已训练的模型

训练之后,我们可以评估验证数据集和几个示例上的指标,以查看模型的表现如何。鉴于我们只对 21 000 个样本进行研究,结果非常令人放心,可以与梯度助推器的结果相媲美。

from pytorch_forecasting.metrics import MAE# load the best model according to the validation loss (given that
# we use early stopping, this is not necessarily the last epoch)
best_model_path = trainer.checkpoint_callback.best_model_path
best_tft = TemporalFusionTransformer.load_from_checkpoint(best_model_path)# calculate mean absolute error on validation set
actuals = torch.cat([y for x, y in iter(val_dataloader)])
predictions = best_tft.predict(val_dataloader)MAE(predictions, actuals)

从 sMAPE 的角度来看最差的表现,可以让我们了解模型在可靠预测方面的问题。这些例子可以为如何改进模型提供重要的指导。这种实际值与预测值的对比图适用于所有模型。

from pytorch_forecasting.metrics import SMAPE# calculate metric by which to display
predictions, x = best_tft.predict(val_dataloader)
mean_losses = SMAPE(reduction="none")(predictions, actuals).mean(1)
indices = mean_losses.argsort(descending=True)  # sort lossesraw_predictions, x = best_tft.predict(val_dataloader, mode="raw, return_x**=True)**# show only two examples for demonstration purposes
for idx in range(2):
    best_tft.plot_prediction(
        x,
        raw_predictions,
        idx=indices[idx],
        add_loss_to_title=SMAPE()
    )

验证集上两个最差的预测。白线表示变压器对给定时间点的关注程度。

类似地,我们也可以从我们的模型中看到随机的例子。PyTorch 预测的另一个特点是对训练好的模型进行解释。例如,所有的模型都允许我们容易地计算部分相关图。然而,为了简洁起见,我们将在这里展示时间融合转换器的一些内置解释功能。它通过设计神经网络来实现可变的重要性。

interpretation = best_tft.interpret_output(
    raw_predictions, reduction="sum"
)best_tft.plot_interpretation(interpretation)

不出所料,过去观察到的音量特征作为编码器中的首要变量和价格相关变量是解码器中的首要预测因素。也许更有趣的是,该机构在静态变量中仅排名第五。然而,考虑到第二个和第三个变量与位置有关,如果这两个变量不包括在模型中,我们可以预计代理机构的排名会高得多。

摘要

PyTorch Forecasting 训练一个模型并洞察其内部运作是非常容易的。作为从业者,您可以使用这个包来训练和解释开箱即用的最新模型。与 PyTorch Lightning 集成训练和预测是可扩展的。作为一名研究人员,您可以利用该包为您的架构获得自动跟踪和自省功能,并将其无缝地应用于多个数据集。

代码、文档和如何投稿

本教程的代码可以在本笔记本中找到:https://github . com/jdb 78/py torch-forecasting/blob/master/docs/source/tutorials/stallion . ipynb

安装 PyTorch 预测

pip install pytorch-forecasting

或者

conda install -c conda-forge pytorch-forecasting

GitHub 库:https://github.com/jdb78/pytorch-forecasting

文档(包括教程):https://py torch-forecasting . readthedocs . io

该软件包在允许商业使用的 MIT 许可下是开源的。非常欢迎投稿!请提前阅读投稿指南,以确保您的投稿被迅速合并。

相关著作

亚马逊的 Gluon-TS 旨在提供类似的界面,但与 PyTorch 预测相比有两个明显的缺点。首先,该包的后端是 MXNet ,一个受欢迎程度落后于 PyTorchTensorflow 的深度学习框架。第二,尽管它是一个强大的框架,但由于其复杂的对象继承结构和组件的紧密耦合,它可能很难掌握和修改。

参考

[1] S. SmylJ .阮冈纳赞A .帕斯夸M4 预测赛:引入全新混合 ES-RNN 车型 (2018)、https://eng.uber.com/m4-forecasting-competition

[2] B. N. Oreshkin 等人,N-BEATS: 可解释时间序列预测的神经基础扩展分析 (2020),学习表征国际会议

[3] B. Lim,S. O. Arik,N. Loeff 和 T. Pfister,用于可解释的多时段时间序列预测的时间融合变换器 (2019),arXiv:1912.09363

引入递归神经网络

原文:https://towardsdatascience.com/introducing-recurrent-neural-networks-f359653d7020?source=collection_archive---------28-----------------------

堆叠感知器不适合顺序任务。而是使用 RNNs。

作者图片

人工智能(AI)正在弥合技术和人类之间的差距,让机器自动从数据中学习东西,变得更加‘像人’;因此,变得更加“聪明”。在这种情况下,智能可以被认为是处理信息的能力,这些信息可以用来为未来的决策提供信息。这是理想的,因为人类可以通过识别旧的模式、发展新的联系,并以新的视角感知他们所学的东西来开发新的有效的过程,从而自发地将信息整合在一起。当与机器的计算能力相结合时,可以获得巨大的成果。

自动学习和计算效率的结合可以用深度学习来最好地描述。这是人工智能和机器学习(ML)的一个子集,其中算法用于确定数据中的模式,并开发一个目标函数,该函数将输入变量 x 最佳映射到目标变量 y 。这里的目标是自动提取未来决策所需的最有用的信息。深度学习模型非常强大,可以用来解决各种各样的问题;从预测学生通过课程的可能性,到使用 Face ID 识别个人的面部来解锁他们的 iPhones。

作者图片

深度学习模型建立在“神经网络”的思想之上,这就是允许模型从原始数据中学习的东西。简单来说,深度神经网络是通过堆叠感知器创建的,感知器是单个神经元。通过具有一组输入 x ,信息通过该系统向前传播,并且每个输入具有相应的权重 w 。输入还应包括独立于 x 的“偏置项”。给定手边的问题,偏差项用于相应地移动所使用的函数。然后将每个对应的输入和权重相乘,并计算乘积之和。然后,该和通过非线性激活函数,并且产生输出 y,

然而,这种“前馈”类型的模型并不总是适用的,并且它们的基本架构使得很难将它们应用于某些场景。例如,考虑一个模型,该模型被设计成在给定一个飞行物体的快照的情况下,预测该飞行物体接下来将去往何处。这是一个顺序问题,因为对象将随着时间的推移覆盖一段距离,并且对象的当前位置将取决于对象先前的位置。如果没有给出该物体之前位置的信息,那么预测该物体下一步的位置也不过是一个随机的猜测。

作者图片

让我们考虑另一个简单但重要的问题:预测下一个单词。这样做的模型现在很常见,因为它们被用在诸如自动填充和自动更正的应用程序中,并且它们通常被认为是理所当然的。这是一个连续的任务,因为最合适的“下一个单词”取决于之前的单词。前馈网络不适合这项任务,因为它需要一个具有特定长度的句子作为输入,然后预测下一个单词。但是,这是一个问题,因为我们不能保证每次输入的长度都相同,这样模型的性能就会受到负面影响。

解决这个问题的一个潜在方法是只查看这个输入句子的一个子部分,比如最后两个单词 maybe。这解决了可变长度输入的问题,因为不管总输入长度如何,模型将仅使用句子的最后两个单词来预测下一个单词。但这仍不理想,因为该模型现在无法考虑长期依赖关系。也就是说,考虑这样一句话“我在柏林长大,一年前才搬到纽约。我能说流利的……”。如果只考虑最后两个词,每种语言的可能性都是一样的。但是当考虑整个句子时,德语是最有可能的。

作者图片

克服这些问题的最好方法是拥有一个全新的网络结构;一个可以随时更新信息的系统。这是一个递归神经网络 (RNN)。这类似于感知机,随着时间的推移,信息通过一组输入在系统中转发, x ,每个输入都有一个权重, w 。然后将每个相应的输入和权重相乘,并计算乘积的总和。该和然后通过非线性激活函数,并且产生输出 y,

不同之处在于,除了输出,网络还产生内部状态更新, u 。然后在分析下一组输入信息时使用该更新,并提供也依赖于先前信息的不同输出。这很理想,因为信息会随着时间的推移在整个网络中持续存在。顾名思义,这个更新函数本质上是一个发生在顺序过程的每一步的递归关系,其中 u 是前一个 u 和当前输入 x 的函数。

作者图片

随着时间的推移,在 RNN 系统中循环的概念可能有点抽象,难以理解。另一种思考 RNN 的方式是随着时间的推移展开这个系统。也就是说,把 RNN 想象成一组奇异的前馈模型,其中每个模型通过内部状态更新链接在一起。像这样观察 RNN 可以真正提供一些关于为什么这种结构适合顺序任务的见解。在序列的每一步,都有一个输入、对该输入执行的某个过程和一个相关的输出。对于序列的下一步,前一步必须有一些影响不影响输入但影响相关输出。

如果我们回到飞行物体场景或单词预测场景,并使用展开的 RNN 来考虑它们,我们将能够更好地理解解决方案。在飞行物体的每个先前位置,我们可以预测一条可能的路径。预测路径随着模型接收到关于对象先前位置的更多信息而更新,并且该信息自我更新,然后馈入模型的未来序列。类似地,当句子场景中的每个新单词被输入到模型中时,就会生成新的可能单词组合。

作者图片

神经网络是人工智能和人工智能的重要组成部分,因为它们允许模型自动从数据中学习,并且它们将人类学习的一个版本与强大的计算能力相结合。然而,将非顺序结构应用于顺序任务将导致模型性能不佳,并且神经网络的真正能力将得不到利用。rnn 是人工学习系统,它基于以前的信息在内部更新自己,以便随着时间的推移预测最准确的结果。

参考文献:

DSpace . MIT . edu/bitstream/handle/1721.1/113146/1018306404-MIT . pdf?序列=1

Stanford . edu/~ sher vine/teaching/cs-230/cheat sheet-recurrent-neural-networks

wild ml . com/2015/09/recurrent-neural-networks-tutorial-part-1-introduction-to-rnns/

karpathy.github.io/2015/05/21/rnn-effectiveness/

其他有用的素材:

deeplearning.mit.edu/

neuralnetworksanddeeplearning.com/

towardsdatascience.com/what-is-deep-learning-adf5d4de9afc

towards data science . com/the-mathematics-behind-deep-learning-f 6 c 35 a 0 Fe 077

引入简化共享

原文:https://towardsdatascience.com/introducing-streamlit-sharing-b4f520e3d95?source=collection_archive---------43-----------------------

免费部署、管理和共享您的 Streamlit 应用

机器学习和数据科学代码易于共享,但难以使用。GitHub 充斥着模型、算法和数据集。但是代码是静态的。你能和模特一起玩吗?看到算法了吗?与数据互动?这样做需要遵循复杂的指令、安装包或阅读密集的代码片段。对此感到沮丧,我们决定我们需要一个简单的、可共享的“播放”按钮来播放机器学习代码。

这里有两个挑战。第一个是开发应用,让数据科学和机器学习代码互动。第二是分享这些应用程序,这样世界就可以体验你的工作。

一年前,我们通过发布 Streamlit 解决了第一个挑战— 创建— ,这是一个开源库,允许您将 Python 脚本转换为交互式应用。Streamlit 让您可以轻松演示算法、玩模型、操作数据,并将所有这些超能力结合到漂亮的应用程序中。反响是巨大的。我们刚刚完成了第一百万次下载。世界各地已经创建了成千上万的 Streamlit 应用程序。但是创建优秀的应用程序只能解决一半的问题。

轻松部署和共享您的简化应用

今天,我们通过宣布一个全新的 Streamlit 共享平台来应对第二个挑战— 共享。Streamlit 共享让您可以部署、管理和共享您的应用程序,这一切都是免费的!如果你有一个在 GitHub 上公开托管的 Streamlit 应用程序,你现在只需点击一下就可以与全世界分享它。

GitHub 和 Streamlit——一起更好

Streamlit 共享结合了 Streamlit 的精华和 GitHub 的精华。从 Streamlit 你可以得到一个简单的框架来创建极其丰富和有用的应用程序。从 GitHub 你继承了一个不可思议的社会协作框架。将你的 GitHub 链接粘贴到 Streamlit 的共享平台上,几乎立刻你就有了一个实时应用。或者,点击任何 live app 的菜单,在 GitHub 上查看其源代码。只需分叉和编辑代码即可免费协作。这是全球性的、可共享的、可分叉的、协作的数据科学!

无限的可能性

结合在一起,Streamlit 和 GitHub 实现了一个极其丰富多样的有用应用生态系统——从仪表盘到深度网络等等!(作为前卡耐基梅隆大学的学生,我们特别自豪的是,参加互动数据科学课程的学生现在使用 Streamlit 共享提交作业🤗)这里有一些很棒的共享 Streamlit 应用程序的例子,你现在就可以玩。

虽然这篇文章关注的是开源应用程序,但是 Streamlit 也被成千上万的公司用来构建复杂的内部数据工具。例如,优步在整个公司范围内部署了 Streamlit,使数据科学家能够在整个公司内共享他们的工作。 Streamlit for Teams 扩展 Streamlit 的共享平台,在您的企业中实现安全、无缝的应用部署、管理和协作。如果你感兴趣,请注册团队的 Streamlit 测试版。

获得简化共享的邀请

为了庆祝发布,我们将发布 1,000 份 Streamlit 共享邀请 随着我们服务器容量的增长,会有更多的邀请。如果您的收件箱中还没有邀请,请请求邀请,我们将很快为您发送邀请。

Streamlit 播放按钮

这种新的共享能力完成了 Streamlit 循环——从创建到共享,然后再返回。所以创造吧!与世界分享!让别人看到你的工作,分叉,合并,促成知识创造的循环。本着这种精神,我们提供最后一件礼物:这是我们的“播放”按钮。

这个全新的徽章帮助其他人找到并使用您的 Streamlit 应用程序。将它嵌入到 GitHub readme.md中,如下所示:

[![Streamlit App](https://static.streamlit.io/badges/streamlit_badge_black_white.svg)](https://share.streamlit.io/yourGitHubName/yourRepo/yourApp/)

谢谢你们用你们令人惊叹的创作激励了我们。我们很高兴看到你的建设和分享。🎈

我们细流 it 的所有人非常感谢社区中的所有人,特别是细流 it 的创始人,AshishCharlyfani lojos杰西还要特别感谢所有 launch app 的创作者,Alex、Dan、Ines | Explosion,最后还有 Tyler,他不仅创作了**Goodreads app,还创作了一个很棒的分享教程。******

介绍 Text 2 summary:Android 上的文本摘要(使用 TF-IDF)

原文:https://towardsdatascience.com/introducing-text2summary-text-summarization-on-android-674b62419019?source=collection_archive---------38-----------------------

📱移动机器学习

一个简单易用的库,用于在 Android 上生成文本摘要

出处。

互联网充斥着大量的数据。如果我们只谈论文本数据,这包括在线新闻、博客、故事和其他信息库。这里是文本摘要出现的地方。文本摘要模型的最终目标是以一种潜在的形式表现文本信息,这种潜在的形式损害了文本的语义。抱着这个想法,我开发了 Text2Summary ,一个 Android 应用的文本摘要器。

[## Shu bham 0204/text 2 summary-Android

Text2Summary API 使用设备上的方法在 Android 应用程序上执行文本摘要。它使用摘录文本…

github.com](https://github.com/shubham0204/Text2Summary-Android)

在这个故事中,我们讨论了 Text2Summary 的需求、安装和使用。

Text2Summary 有什么特别之处?

如果你想总结应用程序用户选择的大量文本,你面前有两个选择。要么创建一个抽象的文本摘要模型,要么创建一个提取的文本摘要模型。

在这里你可以理解上述方法的区别。简单明了地说,抽象模型就像一个人阅读给定的内容,然后自己写摘要。一个精挑细选的模特是一个只配有荧光笔的人,他会突出重要的句子,并对它们进行总结。

如果你有机器学习的背景,你可能想从 Seq2Seq NN 中创建一个抽象模型。如果你不是来自机器学习背景,Seq2Seq 可能会令人害怕。

这里是 Text2Summary,

Text2Summary 使用提取模型,这意味着它使用提供给它的文本的句子创建摘要。它使用一种 TF-IDF 算法从文本中获取最有意义的句子。这个算法比上图简单,并且在计算能力有限的 Android 设备上高效运行(与那些 GPU/TPU 马相比!).

听起来很酷。如何在我的 Android 项目中添加 Text2Summary?

首先,我们进入项目级的build.gradle文件。添加下面的 JitPack 仓库,

allprojects {
    repositories {
        // Other dependencies
        maven { url 'https://jitpack.io' }
    }
}

注意到最新发布的 Text2Summary 后,在你的 app 级build.gradle文件中添加依赖关系,

dependencies {
    // Other dependencies
    implementation 'com.github.shubham0204:Text2Summary-Android:alpha-02'
}

仅此而已。我们准备使用 Text2Summary!

如何在我的应用程序中使用 Text2Summary?

首先,获取您希望以String形式总结的文本。然后,使用Text2Summary.summarize()方法开始使用 API,

var summary = Text2Summary.summarize( text , compressionRate = 0.7 )

上面的 **compressionRate** 是什么?

它是文本的一部分,长度等于摘要长度。例如,如果您希望创建原始文本的 3/4 摘要,请使用 0.75 的压缩率。

您可能想从用户存储器上的File中读取文本,

val bufferedReader: BufferedReader = File( "poems.txt" ).bufferedReader()
val text = bufferedReader.use{ it.readText() }
val summary = Text2Summary.summarize( text , 0.7 )

从这里你应该能最大程度地了解 Text2Summary。但是等等。有没有遇到 UI 线程堵塞的情况?打Text2Summary.summarize()的时候活动是不是停了一会儿?

Text2Summary 需要执行各种操作,包括ArrayListHashmap。如果文本很大,UI 线程会停止一段时间。为了解决这个问题,使用summarizeAsync()执行文本摘要,

val callback = object : Text2Summary.SummaryCallback {
    override fun onSummaryProduced(summary: String) {
        // The summary is ready!
    }
}
Text2Summary.summarizeAsync( someLongText , 0.7f , callback  )

一些其他有用的资源

结束了

我希望你喜欢Text2Summary.在你的 Android 应用中使用它,并分享你的问题和建议。谢谢!

Neo4j 图形数据科学插件的预览,包含“图形算法:Apache Spark 和 Neo4j 中的实用示例”一书中的示例

原文:https://towardsdatascience.com/introducing-the-neo4j-graph-data-science-plugin-with-examples-from-the-graph-algorithms-19b831f66f2?source=collection_archive---------13-----------------------

在过去的几年里,数据科学领域获得了很大的发展。它已经成为商业和学术研究的重要组成部分。结合日益流行的图形和图形数据库, Neo4j 的人们决定发布图形数据科学 (GDS)插件。它是图形算法插件的继承者,即将被弃用。然而,这仍然是 GDS 的预览版,正式发布将在未来几周内进行。

那些熟悉图形算法插件的人会注意到,为了更平滑的过渡,语法没有太大的变化。为了展示所发生的变化,我准备了迁移指南,形式为 Apache Zeppelin 笔记本,可以在 GitHub 上找到。

Apache Zeppelin 的 Neo4j 连接器由 Andrea Santurbano 开发,他还设计了这个项目的漂亮主页笔记本,并帮助他出主意。在迁移指南中,我们使用了来自图算法的例子:由 Mark NeedhamAmy Hodler 撰写的 Apache Spark 和 Neo4j 书中的实际例子。由于这本书还演示了图算法的 Apache Spark 实现,我们决定也包括它们是合适的。在建立 Apache Spark 环境时,我遇到了与这本书的合著者相同的问题,他写了一篇关于这个问题的博文。大声喊马克!

以下是你可以从这个项目中期待的:

  • 16 本单图算法笔记本,包含 Apache Spark 中的实现以及到 GDS 的迁移指南
  • 《移植到 GDS》中的链接预测分析

Neo4j 图形数据科学和图形算法插件不兼容,因此它们不会在 Neo4j 的单个实例上协同工作。在这个项目中,我们使用了两个 Neo4j 实例来演示新旧语法。

为了更好地了解笔记本所提供的功能,我们现在将浏览 PageRank 示例笔记本。你将在这篇博文中看到的所有引文都是从上述书中摘录的。

PageRank 算法简介

每个图形算法都有一个主笔记本,其中包括算法及其用例的简短介绍。以下是对 PageRank 算法的介绍:

PageRank 是以谷歌联合创始人拉里·佩奇的名字命名的,他创建了 Page rank 来对谷歌搜索结果中的网站进行排名。基本的假设是,一个有更多传入和更有影响力的传入链接的页面更有可能是一个可信的来源。PageRank 测量节点的传入关系的数量和质量,以确定对该节点重要性的估计。在网络上具有更大影响力的节点被认为具有来自其他有影响力的节点的更多传入关系。

在主笔记本的底部,您会找到 Neo4j 和/或 Apache Spark 算法实现的链接。

Neo4j 中的 PageRank 实现

在实际的笔记本中,你会发现图形算法和图形数据科学算法的例子。尽管如此,为了这篇博文的清晰,我决定只展示新的 GDS 语法。

加载示例图表:

GitHub 上的示例图是一个 CSV 文件,可以使用LOAD CSV cypher 语句轻松获取。

// import nodes
WITH “[https://raw.githubusercontent.com/neo4j-graph-analytics/book/master/data/social-nodes.csv](https://raw.githubusercontent.com/neo4j-graph-analytics/book/master/data/social-nodes.csv)"
AS uri
LOAD CSV WITH HEADERS FROM uri AS row
MERGE (:User {id: row.id});// import relationships
WITH “[https://raw.githubusercontent.com/neo4j-graph-analytics/book/master/data/social-relationships.csv](https://raw.githubusercontent.com/neo4j-graph-analytics/book/master/data/social-relationships.csv)"
AS uri
LOAD CSV WITH HEADERS FROM uri AS row
MATCH (source:User {id: row.src})
MATCH (destination:User {id: row.dst})
MERGE (source)-[:FOLLOWS]->(destination);

我们可以通过使用下面的 cypher 语句来可视化 Zeppelin 中的示例图:

MATCH p=(:User)-[:FOLLOWS]->(:User)
RETURN p;

结果

Apache Zeppelin 中可视化的示例图

图形数据科学插件

创建预加载的命名图

推荐使用 GDS 库的方法是预加载命名图。投影图可以存储在内存中,以后可以通过任何图形算法使用其名称进行检索。这允许更有效的图形分析管道,其中我们在同一个内存图形上按顺序运行许多图形算法。

一般语法是:

CALL gds.graph.create('nameOfGraph','NodeLabel','RelationshipType')

在本例中,我们将使用以下 cypher 语句将图形加载到内存中:

CALL gds.graph.create(‘pagerank_example’, ‘User’, ‘FOLLOWS’);

流式传输算法的结果

算法结果流的一般语法是:

CALL gds.<algorithm>.stream()

对于 PageRank 示例,cypher 过程如下所示:

CALL gds.pageRank.stream(‘pagerank_example’,
    {maxIterations: 20, dampingFactor: 0.85}) YIELD nodeId, score
RETURN gds.util.asNode(nodeId).id AS name, score
ORDER BY score DESC LIMIT 10

结果

Neo4j 页面排名结果

正如我们所料,Doug 拥有最高的 PageRank,因为在他的子图中,所有其他用户都跟随他。虽然马克只有一个追随者,这个追随者就是
道格,所以马克在这个图中也被认为是重要的。重要的不仅仅是关注者的数量,还有那些关注者的重要性。

写回算法的结果

有时候,我们想把算法的结果写回图中,而不是流出来。写回算法的一般语法是:

CALL gds.<algorithm>.write({writeProperty:'pagerank'})

其中如果您想写回结果,参数writeProperty是强制的。这是为了防止对图形进行任何不必要的写入。

在我们的 PageRank 示例中,我们使用:

CALL gds.pageRank.write(‘pagerank_example’,
    {maxIterations: 20, dampingFactor: 0.85,     
     writeProperty:’pageRank’})

从内存中释放加载的图形

完成图形分析后,我们想使用下面的 cypher 语句从内存中释放 GDS 图。

CALL gds.graph.drop(‘pagerank_example’);

用 Apache Spark 实现的 PageRank

如前所述,这本书还提供了 Apache Spark 中图形算法的实现,所以我只是将它们复制到笔记本上。

加载示例图表:

在这个例子中,我们使用 GraphFrames 库来加载图表并计算 PageRank 中心性。

def create_social_graph():
    nodes = spark.read.csv(“spark-warehouse/social-nodes.csv”, header=True)
    relationships = spark.read.csv(“spark-warehouse/social-relationships.csv”, header=True)
    return GraphFrame(nodes, relationships)g = create_social_graph()

迭代次数固定的 PageRank

让我们看一个固定迭代方法的例子。
注意在 Spark 中,阻尼因子更直观地被称为
重置概率,具有相反的值。换句话说,本例中 reset
Probability=0.15 相当于 Neo4j 中的 dampingFactor:0.85。

results = g.pageRank(resetProbability=0.15, maxIter=20)
results.vertices.sort(“pagerank”, ascending=False).show()

结果

具有固定迭代次数的 Spark PageRank

结果类似于 Neo4j 的结果。

PageRank 的实现各不相同,因此即使排序相同,它们也会产生不同的
得分。Neo4j 使用值 1 减去阻尼因子来初始化节点
,而 Spark 使用值 1 初始化
。在这种情况下,相对排名(Pag 的目标是
eRank)是相同的,但是用于达到
这些结果的基础分值是不同的。

PageRank 直到收敛

现在,让我们尝试运行 PageRank 的收敛实现,直到它在设定的容差范围内逼近一个解决方案:

results = g.pageRank(resetProbability=0.15, tol=0.01)
results.vertices.sort(“pagerank”, ascending=False).show()

结果

带收敛策略的 Spark PageRank

每个人的 PageRank 分数与固定迭代次数变量略有不同,但正如我们所料,他们的顺序保持不变。

个性化页面排名

我们可以通过传入 sourceId 参数来计算给定节点的个性化 PageRank 分数。以下代码计算道格的 PPR:

me = “Doug”
results = g.pageRank(resetProbability=0.15, maxIter=20, sourceId=me)
people_to_follow = results.vertices.sort(“pagerank”, ascending=False)already_follows = list(g.edges.filter(“src = ‘{me}’”).toPandas()[“dst”])
people_to_exclude = already_follows + [me]people_to_follow[~people_to_follow.id.isin(people_to_exclude)].show()

结果

Spark 个性化页面排名

这个查询的结果可以用来为道格应该关注的人提供建议。请注意,我们还确保从我们的最终结果中排除道格已经关注的人以及他自己。

爱丽丝是道格应该追随的最佳人选,但我们也可以推荐迈克尔和布里奇特。

结论

再次感谢 Amy 和 Mark 编写了这本优秀的书,感谢 Neo4j 图表数据科学团队提供了如此出色的工具来帮助我们在图表中找到更多见解。正如我在这篇博文的介绍中提到的,目前这仍然是 GDS 插件的预览版,正式发布将在接下来的几周内进行。自己试试图形数据科学插件,请分享任何评论、反馈或建议。

一如既往,你可以在 GitHub 上找到这些笔记本。

介绍“向后走”:一种预测未来的新方法

原文:https://towardsdatascience.com/introducing-walk-backward-a-novel-approach-to-predicting-the-future-c7cf9e15e9e2?source=collection_archive---------28-----------------------

受够了及时验证!“向后走”使预测模型更加准确和可靠

"永远不要做预测,尤其是对未来的预测。"(k·k·斯坦克)

  1. 这幅画描绘的是马还是车?
  2. 该顾客在下周购买该商品的可能性有多大?
  3. 这个人会在下一年无法偿还贷款吗?
  4. 这句话怎么翻译成西班牙语?

这些问题或许可以用机器学习来回答。但是,问题 1 和问题 4 关注的是已经存在的事物(一张图片,一个句子),而问题 2 和问题 3 关注的是未来的事件,即尚未发生的事件。这有关系吗?的确如此。

事实上,我们都知道——首先作为人类,然后作为数据科学家——预测未来是很难的

从技术角度来看,这是由于概念漂移,这是一个非常直观的概念:现象随着时间而变化。由于我们想要预见的现象在不断变化,使用一个模型(基于过去的经验)来预测未来带来了额外的挑战

在这篇文章中,我将描述三种可能用于预测未来的机器学习方法,以及它们如何应对这些挑战。

  1. 及时:最常采用的方式。就结构而言,它深受概念漂移之苦。
  2. 向前走:在金融等一些领域常见,但在机器学习中还是不那么常见。它克服了及时的一些弱点,但代价是引入了其他缺点。
  3. 向后行走:一种新颖的方法,结合了及时行走和向前行走的优点,同时减少了它们的缺点。我在真实的、庞大的、杂乱的数据上试了试,结果证明效果非常好。

在文章的第一部分,我们将介绍这三种方法。在第二部分中,我们将在数据上尝试它们,看看哪一个效果最好。

第一种方法:“及时”

假设今天是 2020 年 10 月 1 日,你想预测下一个月(即从今天到 10 月 31 日)你公司客户流失的概率。

下面是大多数数据科学项目如何解决这个问题:

及时的方法。

注意:包含在 X 中的信息可以无限回溯(但是,在所有的图中,为了直观起见,只能回溯 4 个月)。

这种方法被称为“实时”,因为所有数据集(训练、验证和测试)都来自同一个时间点(在这种情况下,是 9 月)。通过培训、验证和测试,我们打算:

  • Train set(X _ Trainy_train ):模型将要学习的数据。
  • 验证集(X _ Validationy_validation ):用于提前停止的数据。在训练阶段,在每次迭代中,都会计算验证性能。当这种性能停止改善时,意味着模型已经开始过度拟合,因此训练停止。
  • 测试集 ( X_testy_test ):训练阶段从未使用过的数据。仅用于评估您的模型在未来的实际表现。

现在您已经收集了数据,您可以在训练集(9 月)上拟合一个预测模型(假设是 Xgboost)。在测试集上的性能如下:准确率为 50%,召回率为 60%。既然您对这个结果感到满意,您决定将这个结果传达给利益相关者,并在 10 月份进行预测。

一个月后,你去检查你的模型在十月份的实际表现。一场噩梦。准确率 20%,召回率 25%。这怎么可能呢?你做的一切都是对的。你验证了你的模型。然后你测试了它。为什么测试性能和观察性能相差如此之大?

过时了

问题是及时方法完全忽略了概念漂移。事实上,这个假设是含蓄地提出的:

时间背后的本质:参数(θ)不随时间变化。

在这个框架中,当模型被训练时实际上并不重要,因为 f(θ) 被假定为随时间恒定。不幸的是,现实中发生的事情是不同的。事实上,概念漂移使得 f(θ) 随着时间而变化。在公式中,这将转化为:

一个更一般(也更现实)的假设:参数取决于时间。

为了考虑这种影响,我们需要将我们的思维模式从及时转变为不及时。

第二种方法:“向前走”

超时的一种形式——主要用于金融——被称为“漫步”(阅读罗杰·斯坦的这篇文章以了解更多)。这个名字来源于这样一个事实,即模型是根据用于训练的数据在时间上向前验证和/或测试的。视觉上:

向前走的方法。

这种配置的优点是它模拟了模型的实际使用。其实模型是在t(8 月)进行训练,在t+1(9 月)进行评估。因此,这是 9 月份训练和 10 月份预测的一个很好的代理。

然而,当我在真实数据上尝试这种方法时,我注意到它有一些主要缺点:

  1. 如果您使用 8 月份训练的模型来预测 10 月份的情况,您将使用一个 2 个月前的模型!因此,十月份的性能会比使用 In-Time 时更差。实际上,这是因为最新的数据被“浪费”在测试上。
  2. 或者,如果您在 9 月重新培训模型,您将再次陷入及时。而且,最后估计 10 月份车型的预期表现也不会很容易。这样你就能回到起点。

总而言之,我喜欢超越时间的想法,但在我看来,步行前进是不值得的。

第三种方法:“向后走”

然后,这个想法出现在我的脑海中:有没有可能概念漂移在某种程度上随着时间的推移是“不变的”?换句话说,预测 1 个月的未来或 1 个月的未来会导致相同的表现吗?

如果是这样的话,我会一石二鸟(不,等等,三只鸟)。事实上,我会保留以下好处:

  1. 使用最新数据进行训练(如及时发生的,但不是提前发生的);
  2. 对模型在下个月的表现做出可靠的估计(如在 Walk-Forward 中发生的,但不是在 In-Time 中);
  3. 只训练一个模型(在实时中发生,但在步行中不发生)。

简而言之,我会保留每种方法的优点,同时消除它们的缺点。这就是我如何得到以下配置的:

向后走的方法。注:使用不同的时间窗口进行训练、测试和验证(即使是对相同的观测值)没有方法上的问题,只要预测窗口(在这种情况下,y _ trainy _ validationy _ test)不重叠。

我称之为“向后走”,因为它与向前走正好相反:训练基于最新的数据,而验证和测试基于以前的时间窗口。

我知道在 9 月份训练一个模型(并在 7 月份验证它),然后在 8 月份检查它的表现,甚至期望这是对它在 10 月份表现的一个很好的估计,这可能看起来很疯狂!这可能看起来像是我们乘坐德罗宁在时间上来回穿梭,但我保证我有一个很好的解释。

如果你喜欢哲学…

…然后是为什么倒着走有意义的哲学解释。我们来分解一下。

  1. 对于每组(训练、验证和测试),最好使用不同预测窗口。这对于避免验证数据或测试数据对模型的表现给出过于乐观的估计是必要的。
  2. 给定点 1。,9 月训练模特( t )是唯一合理的选择。这是因为该模型应该“学习一个与我们想要预测的世界尽可能相似的世界”。九月的世界( t )可能比过去任何一个月( t-1t-2 、…)更类似于十月的世界( t+1 )。
  3. 在这一点上,我们有一个 9 月份训练的模型,并想知道它在 10 月份的表现如何。应该选择哪个月作为测试集?八月是最佳选择。事实上,八月的世界( t-1 )与九月的世界( t )是“不同的”,正如十月的世界( t+1 )与九月的世界( t ) )是“不同的”。发生这种情况的原因很简单:十月和八月离九月同样遥远。
  4. 给分 1。, 2.第三。,使用 July ( t-2 )作为验证集是唯一的必然结果。

如果你不喜欢哲学…

…那么,也许,你喜欢数字。在这种情况下,我可以向您保证:我在一个真实的用例上尝试了这种方法,与及时和向前行走相比,向后行走获得了:

  1. 预测精度更高y _ future
  2. y_testy_future 上的性能差异较小(即 8 月观察到的精度是对 10 月实际获得的精度的更可靠估计);
  3. y_trainy_test 上的性能差异较小(即过拟合较少)。

基本上,数据科学家能要求的一切。

“我还是不相信你!”

没关系,我也是个多疑的人!这就是为什么我们会在一些数据上尝试及时、向前和向后,看看哪一个表现最好。

为此,我们将使用模拟数据。模拟数据是“在实验室”重现概念漂移并使结果可复制的一种便捷方式。这样,就有可能在更普遍的情况下检验向后行走的优越性是否得到了证实。

在实验室重现概念漂移

我们取 12 个时间点(2020 年 1 月到 2020 年 12 月的月度数据)。假设每个月有 50 个特征在 5000 个人身上被观察到。这意味着 12 个数据帧(x1,…,x12),每个数据帧具有 5000 行和 50 列。为了简单起见,这些列是根据正态分布生成的:

一旦 X 可用,我们就需要(因变量,或目标变量)。出于简单起见, y 将是一个连续变量(但是结果可以很容易地扩展到 y 是离散的情况)。

假定 Xy 之间为线性关系:

β s 由 t 索引,因为参数随时间不断变化。这就是我们如何在简化版的世界中解释概念漂移的。

特别是 β s 根据 ARMA 过程变化。这意味着【β(I)的波动不是完全随机的:它们取决于【β(I)本身的过去值。

ARMA 系数(和误差)的选择是基于一个保守的假设,即月与月之间的波动不是很大(注意,一个更激进的假设会更倾向于过时的方法)。特别的,我们假设 ar 系数为-0.3,MA 系数为 0.3,误差的标准差为 0.5。这些是前 6 个(50 个中的) β 的结果轨迹。

时间轨迹: β(1) β(6)**。**

这就是目标变量( y )的样子:

y 的分布。虚线分别代表第 25、50 和 75 百分位。

结果

现在我们有了数据,可以比较这三种方法。

由于这是一个回归问题( y 为连续变量),所以选择了平均绝对误差(MAE)作为度量。

为了使结果更加可靠,每种方法都在所有时间点上执行(以“滑动窗口”的方式)。然后,对所有时间点的结果进行平均。

这是结果:

实验的结果。绿色:所选 KPI 的最佳结果。红色:所选 KPI 的最差结果。

通常,预测模型好坏的最重要指标是在 y_future 观察到的性能。从这个角度来看,后退是最好的方法,因为它提供了最好的 MAE (3.98)

但不止如此。看一下 In-Time: MAE( 测试)平均 2.91,MAE( 未来)4.20。因此,在现实世界的用例中,您将向涉众传达您期望您的模型交付 2.91 的 MAE。但是一个月后你会观察到的实际表现是平均 4.19。这是一个巨大的差异(和巨大的失望)!

实际上,测试性能和未来性能之间的绝对差异,对于及时测试来说,平均是回溯测试的三倍(1.28 比 0.43)。因此,从这个角度来看,倒着走是目前为止最好的方法。

注意,在现实世界的用例中,这个方面可能比性能本身更重要。事实上,能够预测模型的实际性能——而不必等到下一阶段结束——对于分配资源和规划行动至关重要。

结果完全可重复。Python 代码在本笔记本中有。

作者通过 matplotlib (用于绘图)或 codecogs (用于乳胶配方)创建的所有图像。

感谢您的阅读!我希望这篇文章对你有用。

我感谢反馈和建设性的批评。如果你想谈论这篇文章或其他相关话题,你可以发短信给我我的 Linkedin 联系人

Adagradient & RMSprop 的介绍与实现

原文:https://towardsdatascience.com/introduction-and-implementation-of-adagradient-rmsprop-fad64fe4991?source=collection_archive---------28-----------------------

不同维度上的自适应学习率

在上一篇文章中,我们介绍了随机梯度下降和动量项,SGD 在传统梯度下降中增加了一些随机性,动量项有助于加速这一过程。然而,这两种方法都设定了固定的学习率:

上面显示了带有动量项的梯度下降,其中lr实际上对于不同维度上的所有参数都是固定的。对于频繁出现的参数,它可以很好地工作,这些参数也可以通过迭代频繁更新,但是对于与不频繁出现的特征相关联的参数,它将导致更新不足以达到最优。

与不经常出现的特征相关联的参数仅在这些特征出现时接收有意义的更新。给定一个递减的学习速率,我们可能会在这样一种情况下结束,其中共同特征的参数相当快地收敛到它们的最优值,而对于不频繁的特征,我们仍然不能在它们的最优值能够被确定之前足够频繁地观察它们。换句话说,对于频繁出现的特征,学习速率降低得太慢,或者对于不频繁出现的特征,学习速率降低得太慢。

Adagradient

Adagradient 是为解决上述问题而开发的,它根据每个参数的梯度和频率以不同的速度更新不同的参数。让我们看看这个公式:

您可能已经注意到,关键的区别是这里添加了s_t术语。对于不常见的特征或梯度较小的特征,它们的s_t会很小,但lr/sqrt(s_t + ϵ)会很大,这导致更新的步长较大。这为不同的参数给出了不同的更新速度,解决了统一学习率带来的弊端。

现在让我们实现它并将其应用到一个实际问题中。

我们要解决的问题和我们之前说过的一样,

其中我们试图找到a, b的最佳值,以最小化yf(x)之间的差异损失,并且上面计算了a, b的梯度。adagradient 的实现将是:

其中X, Y的输入值由下式得出:

实现应该是直接的,我们将s_a, s_b初始化为 0,为了绘制学习过程,我将中间值保存在列表中。

参数更新过程如下:

参数更新

学习率是这样的:

学习率更新

这里的lr/sqrt(s + ϵ)被认为是修正的学习率。

RMSprop

adagrad 的一个问题是,随着梯度随着时间的推移而累积,项s可能会变得无限长,这可能会导致学习步骤的急剧减少,并导致参数最终几乎不变。

RMSprop 旨在通过简单地对术语进行标准化来解决这一问题:

注意这里过去的梯度s_{t-1}被一个额外的参数γ所限制,其中γ通常取值 0.9。

除了s的更新,实现与 adagrad 类似。更新过程将是这样的:

参数更新

学习率是这样的:

学习率更新

这里我们看到a, b的学习率是振荡的,而不是单调下降的(你可以在这里检查的实现)。

到目前为止,我们已经学习了几种在优化过程中应用的技术。接下来,让我们将它们集合起来,衍生出另一个强大的工具— Adam

参考:

TensorFlow 2.0 简介

原文:https://towardsdatascience.com/introduction-on-tensorflow-2-0-bd99eebcdad5?source=collection_archive---------12-----------------------

Tensorflow 2.0 的一些功能的软介绍

来源:Keep-calm.net

在这篇文章中,我将介绍我在探索 TensorFlow 时的一些发现,这个想法将与 TensorFlow 一起围绕图像分类建立和监控 ML 模型,以及比我几周前建立的汽车数据集更好的数据集。

TensorFlow kezako?

TensorFlow 是 Google Brain 在 2011 年开始的一个研究项目,多年来在 Alphabet group 中非常受欢迎。该框架因其高度灵活的架构而在机器学习社区中广受欢迎,该架构可以利用不同类型的处理单元,如 CPUGPUTPU 来执行计算,而无需对运行代码进行大的修改。

该框架自 2015 年以来一直是开源的,似乎在世界各地都非常受欢迎,下载量超过 76 00 万次。Google 提供了多种 API 来与框架交互,如 Python、Javascript、C++、Java 和 Go。

TensorFlow 拥有多种工具来开发机器学习系统:

这套工具非常广泛,我真的建议你看一下上面的不同文档,这会给你一个很好的工具概述。

我只是想谈谈 TensorFlow,但我计划在几周内看看 Lite 和。js 工具(我订购了一个设备,在上面做了一些测试😉)

TensorFlow,如何建立 ML 模型?

为了与 TensorFlow 进行交互,最流行的 API 之一是 Python API(老实说,这是我更喜欢的一个),但是有两种途径可以与这个 API 进行交互:

  • 初学者使用一个叫做 Keras 的用户友好的顺序 API
  • 使用子类 API 的专家更加 pythonic 化

我附上你的两个 API 格式的例子快照

来源:张量流概述

对我来说,我真的建议使用 Keras,对于非 python 专家来说,它可能更容易阅读。这个 API 最初在 TensorFlow 1.x 版本中不是本地 API(因为 2.0 是本地的),必须单独安装才能访问它。

Keras 是一个 API,可以运行在各种 ml 框架之上,如 TensorFlow、CNTK 和 Theano,以帮助人们轻松地重用函数来构建层、求解器等,而无需深入 ML 框架(某种程度上是抽象层)。

让我们构建一些模型来测试这个框架。

模型构建

在这一部分中,我不打算解释我将要使用的模型的架构(可能在一篇特定的文章中)。要开始构建模型,我首先需要将框架与数据连接起来。

数据被划分到与训练集、验证集和测试集相关的文件夹中,在每个文件夹中,每个类别都有一个子文件夹,用于预测将用于该过程的所有图片。有一个图表来表示训练集中每类图片的分布。

验证和测试集中的类的重新划分与具有更少数据的训练集中的相同(训练 80%,验证 10%和测试 10%的完整数据集)。

为了使用模型中的数据,可以像在 TensorFlow 的教程中一样使用数据生成器,这里有代码的快速快照。

该代码的想法是:

  • 正常化图片(RGB 从 0–255 到 0–1 之间的值转换)
  • 调整图片大小
  • 为培训建立不同的批次

它需要应用于所有的文件夹,但在此之后,一切都准备好开始模型的训练。

在模型方面,我重用了 TensorFlow 教程的模型设计,并应用到了其他一些资源上。这些模型可以在以下列表中找到:

该模型的输入和输出已被修改以适应我的需要,但大部分代码来自所列的各种资源。再一次,这些模型只是用来测试框架的,它们对我的问题来说并不是最优的(还需要很多改进)。

通过执行数据生成和模型构建,几分钟后模型就准备好了。

现在让我们看看 TensorFlow 的监控组件。

模型监控

要监控您的模型,TensorFlow 有两种途径(对我而言):

  • 使用模型拟合操作的历史来访问已经计算的各种度量(在这种情况下是损失和准确性)
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']loss=history.history['loss']
val_loss=history.history['val_loss']

例如,使用 matplotlib,可以非常容易地使用历史的输出来绘制图形。

另一种方法是使用一个名为 Tensorboard 的组件,它是一个与 TensorFlow 相关的包,能够在跑步过程中实时收集各种指标,以构建模型(cf gif),可视化架构和数据等。

来源: Tensorboard 文档

最近,谷歌宣布能够通过 tensorboard.dev 计划与每个人共享仪表盘,例如,你可以在这个链接中找到一个与我在这个项目中的一些跑步相关的 tensorboard。

Tensorboad 是一个有趣的计划,他们在上次 TensorFlow 开发峰会上宣布了许多新功能,但老实说,我不是一个非常有经验的深度学习实践者,所以我不太支持这个对我来说看起来很复杂的组件,但我认为它可能是与 mlflow 相关联的数据科学工具箱的一个非常好的工具。

最后,我想介绍另一个组件 TensorFlow hub。

与 TensorFlow hub 共享模型

TensorFlow hub 诞生于 Google 的一个简单情况是,我正在阅读一篇关于神经网络架构的非常好的文章,这篇文章看起来非常有前途,但在调查过程中可能会出现许多问题,例如:

  • 如何才能重现这篇文章?
  • (以文中的回购为例)是模型的最后版本吗?
  • 数据在哪里?
  • (以文中的回购为例)使用这段代码安全吗?

TensorFlow hub 希望人们能够限制所有这些问题,并在 ML 开发上给予更多透明度。

TensorFlow hub 的一个非常有趣的功能是帮助人们用著名的健壮模型的组件来建立机器学习模型,这种方法是重用另一个模型的模型权重,它被称为迁移学习

使用 TensorFlow hub,您可以非常容易地重用另一个模型的几行代码组件,在下面的要点中,有一个我构建的代码示例,用于重用一个名为 Mobilenetv2 的模型的特征提取器,该模型在对象分类方面非常流行(主要受 TensorFlow 教程的启发)。

现在让我们总结一下这个分析

反馈

这第一次动手 TensorFlow 非常好,我发现教程做得很好,很容易理解,你可以很容易地用框架的 Keras API 建立神经网络。有很多组件我还没有测试,就像在这张截图上看到的那样

来源:张量流文档

我添加了一个机会来看看 TensorFlow Extended ( TFX ),这是谷歌建立机器学习管道的方法,我添加了一个 AWS EC2 实例的尝试,但该教程在某个点上崩溃了,但我邀请你观看罗伯特·克罗的精彩演讲,该演讲更详细地介绍了该工具。

这种方法看起来很有前景,我真的很好奇 TFX 和 Kubeflow (谷歌基于 Kubernetes 的另一个 ML 管道)之间将会存在什么样的互动。

我对 TensorFlow 唯一的担心/疑问是处理单元的使用,在我的测试中,我在 CPU 和 GPU 之间交替使用,但我对处理的监控没有显示处理单元充分发挥潜力(但我可能只是个新手)。

增加 TensorFlow 效率的另一个路径是使用 tfRecords ,但似乎数据管理仍然是一个热门话题(从我周围听到的),我发现了一个真正有趣的 Pydata 对话围绕着用 TensorFlow 管理 parquet 文件。

我围绕深度学习的下一个任务是:

  • 对脸书的 Pytorch 做一个简单的介绍,它似乎是 TensorFlow 的克星,这个框架在研究领域赢得了很多关注
  • 加速深度学习算法,以建立一个像样的汽车分类器
  • 了解这些深度学习模型在生产中的部署(数据管理、服务等)

3D 视觉简介

原文:https://towardsdatascience.com/introduction-to-3d-vision-d90f491207fc?source=collection_archive---------43-----------------------

找到你的智能手机的焦距(像素)

UnsplashShareGrid 拍摄的照片

在计算机视觉(CV)的世界里,有很多有趣的概念。在过去十年中,深度卷积神经网络在很大程度上主导了许多 CV 任务。在某些领域,CNN 在图像分类、物体检测和图像分割等方面比人类表现得更好。CNN 的最大优势是它们可以大规模运行,因此可以很好地利用个人和公司收集的大量图像数据!最近,变形金刚也在探索 CV 任务。然而,在这篇文章中,我们将关注计算机视觉的一个更“老派”的方面:3D 视觉。我确信 3D 视觉是我们在日常生活中遇到的东西——我的意思是,我们的眼睛基本上是利用这个原理工作的。本帖旨在介绍其背后的一些基本概念!

照片由内森·杜姆劳Unsplash 上拍摄

3D 视觉的关键功能之一是捕捉深度信息。对于单个相机,我们只有关于特定场景的 2D 信息,因此至少需要 2 个相机!(例如我们的眼睛!).在这个系列中,我将演示如何用智能手机摄像头完成 3 个简单的任务:

  • 找到你的智能手机相机的焦距
  • 使用两张照片恢复物体的深度
  • 从同一个地点拍摄同一场景的两张照片时,找出相机的旋转角度。

寻找焦距

相机的焦距如下图所示。这是照相机和镜头内部工作原理的简化。我们不难看出,通过测量一个物体的实高、实距和像高,就可以求出焦距。这些量通过以下公式相关联:

如果你记得你的高中物理课,这可能看起来很熟悉。现在,我们将比理论更进一步,尝试找出我们智能手机的焦距!可以按照步骤,自己尝试一下。

  1. 找一个已知高度的物体, H 。利用你的朋友/家人,或者你可以利用墙上的两点来测量距离。
  2. 从一定距离拍摄一张照片, D 远离物体。

我卧室的照片,墙上有两个画得很漂亮的十字架。

3.测量物体的图像高度, h 。你可以使用任何常见的图像编辑工具或图像浏览器,我在微软画图。用笔刷工具将鼠标悬停在十字上,我们可以得到下图左下方显示的图像坐标。

4.使用毕达哥拉斯定理从两点计算图像高度。对于我的照片,点是(1849,291),(1782,2954),计算的高度是 2664 像素。

5.使用上面的等式计算 f !确保 HD 的单位相同(我和世界上大多数人一样使用米)。

6.我用一加 6T 智能手机得到了 3566 像素的焦距。请在下面评论分享您的结果和手机型号!

结论/讨论

这是一个简短的帖子,描述了任何人如何通过抓拍照片来计算智能手机的焦距。这是一个很好的信息,因为我们可以交叉检查实际焦距与手机销售商/制造商给出的规格!此外,知道像素的焦距将允许我们做这个系列中的一些其他任务。

你也可以在不同的距离对不同的物体重复这个实验,拍多张照片。最后计算平均 f 值以减少误差。本系列的后续帖子将解释其他可以在智能手机上轻松完成的动手项目,敬请关注!

8 种基本数据结构介绍

原文:https://towardsdatascience.com/introduction-to-8-essential-data-structures-7ef867bd1dd?source=collection_archive---------45-----------------------

数据结构

了解最常见的数据结构背后的基本概念

Patrick Robert Doyle 在 Unsplash 上拍摄的背景照片

作为程序员,我们对数据结构的理解大多局限于在编程语言的更高抽象层次上使用它们。虽然我们知道如何使用特定的编程语言从不同的数据结构中存储和检索数据,但我们大多数人并不试图去解开这些数据结构的底层实现中发生了什么。

在大多数情况下,数据结构的表面知识足以以某种方式完成我们的工作。但是,在为给定任务选择最佳数据结构时,理解不同数据结构在较低级别的行为是至关重要的。在这篇文章中,我们将探究 8 种不同的数据结构,看看它们是如何处理数据的。

排列

数组数据结构存储固定数量的单一数据类型的数据。数组中的元素(项目)存储在一块连续的内存槽中。因此,数组中的元素被赋予连续的数字,从 0 或 1 开始,作为它们的“索引”。

人们可以使用唯一的索引随机访问存储在数组中的单个元素。使用索引访问元素的时间复杂度为θ(1)。以这种方式可以容易地实现读取或更新数组元素。因为数组元素的位置是连续的,所以与大多数其他数据结构相比,数组遍历更快。

向数组中插入数据或从数组中删除数据是一项相当复杂和耗时的任务。插入时,当前数组中的所有元素都被复制到一个新创建的大小增加的数组中,新元素被添加到新数组的末尾。删除也以类似的方式实现,以减小数组大小。

应用:

数组可以是多维的(数组的数组)。这使得数组成为存储矩阵和向量的好选择。数组经常用于实现其他数据结构,如列表、堆、栈和队列。

长队

队列数据结构类似于我们日常生活中看到的队列:第一个进入队列的人是第一个获得下一个退出队列机会的人。在编程世界版本的队列中,添加到队列中的每个新数据元素都存储在后端,从队列中移除的每个元素都从前端取出——基于先进先出的原则。

队列操作

  • 入队:将元素插入到队列的末尾。新添加的元素成为队列的最后一个元素。

  • 出列:从队列的前面删除一个元素。入队和出队操作的时间复杂度都是θ(1)。

  • Peek:读取队列前面的元素,而不删除或修改它。

应用程序

队列用于实现缓冲区。多线程使用队列来管理等待线程执行的任务。

堆栈与队列非常相似,但是它们是基于后进先出而不是先进先出来实现的。想象一堆菜,其中最后添加的菜是第一个要移除的菜。

堆栈操作

  • Push:在栈顶插入一个新元素。新添加的元素成为新的顶部元素。
  • 从栈顶移除一个元素。推送和弹出操作的时间复杂度均为θ(1)。
  • Peek:读取堆栈顶部的元素,而不删除或修改它。

应用程序

堆栈用于处理和评估数学表达式。它们也用于使用回溯过程的算法中。在递归编程中处理递归函数调用是另一个应用。

链表

链表是一种动态数据结构。这意味着存储在链表中的数据项的数量可以很容易地增加或减少。与固定大小的数组相比,这给了链表更多的灵活性。链表通过将每个项目存储为一个单独的对象来实现这种动态特性。

链表中的元素不必存储在连续的内存槽中,相反,每个元素(称为节点)存储一个指向下一个节点位置的指针。这些指针维护着与链表中独立节点的连接。除了指向下一个节点的指针,一个节点还存储一个数据字段。

链表中有两个重要的节点:头和尾。

  • Head:链表的第一个节点。
  • Tail:链表的最后一个节点。Tail 的指针值被设置为 null。

当向链表中插入新元素时,新的数据字段存储在内存中的特定位置,并且更新前一个节点中的指针以指向新节点。新节点存储先前存储在前一节点中的指针。

删除节点时,被删除节点之前的节点被赋予先前存储在被删除节点中的指针。

然而,对于链表,如果不从头开始遍历链表,就不能直接访问单个数据项。这使得访问操作的时间复杂度为θ(n)。

链接列表类型

  • 单链表:上面例子中显示的链表都是单链表。一个节点只包含一个指向下一个节点的指针。
  • 双向链表:双向链表中的节点包含指向给定节点前后节点的指针。可以在向前和向后两个方向上遍历列表。
  • 循环链表:尾部的指针指向头部而不是空。本质上,循环链表没有尾巴,只有一个头。

应用程序

链表用于实现数据结构,如堆栈、队列和图形。当执行多项式代数运算时,链表用于存储常数。

图表

一个图由有限数量的数据项组成,称为顶点(V) 。这些顶点中的一些对通过边(E) 相互链接。由一条边连接的两个顶点是彼此相邻的

可以使用不同的属性对图形进行分类。其中一种分类是有向图无向图

  • 在有向图中,连接两个顶点的边有一个起点和一个终点。当遍历图时,只能从起始顶点到结束顶点穿过边。

  • 在无向图中,一条边可以在两个方向上无限制地遍历。

应用

像脸书这样的社交媒体应用程序使用图表来表示用户的顶点和他们的友谊的边。谷歌页面排名算法使用图形来表示网页和连接它们的链接。谷歌地图使用图表来表示其交通系统中的道路网络。

二叉树

二叉树与有向图有一些相似之处。两者的区别在于,在二叉树中,数据存储在分层结构中,上层节点称为父节点,下层节点称为子节点。二叉树中的一个节点只能有一个父节点和最多两个子节点。

让我们来看几个与二叉树相关的术语。

  • 根:树顶部的节点。它没有父节点。
  • 叶子:树底部的一个节点。它没有子节点。
  • Key:存储在节点中的数据值。
  • 子树:由一个节点的所有后代组成的树

有许多特殊的二叉树,如二叉查找树树、Treap 树、二叉树和堆树。

二叉查找树

二叉查找树按排序顺序存储数据值。二叉查找树中节点左侧子节点的值必须小于父节点,右侧子节点的值必须大于父节点。

顾名思义,BST 的主要优点是能够快速搜索存储的数据。在 BST 中搜索存储元素的时间复杂度是 O(log n)。

应用程序

  • 二分搜索法树用于在编程语言中实现地图和集合对象
  • 二进制尝试用于存储路由表。
  • Treaps 用于无线网络。

许多

堆是二叉树的另一个特例。在堆中,根的键与其子的键进行比较,以特定的方式排列它们。有两种类型的堆。

  • 最大堆:父项的键大于或等于子项的键。根节点存储给定数据集中的最大值。
  • 最小堆:父级的键小于或等于子级的键。根节点存储给定数据集中的最小值。

假设我们得到了整数值(33,24,45,12,90,78,23,53)作为数据集。我们可以从这些数据中构造一个单独的最大堆和最小堆。

最小堆

最大堆

在堆中插入、删除和提取最大(或最小)函数的时间复杂度为 O(log n)。但是求最大值(或最小值)只有 O(1)的时间复杂度。

应用程序

堆用于实现堆排序算法。堆也用于实现优先级队列,因为堆的第一个元素总是存储具有最高(或最低)优先级的值。

哈希表

当我们希望保持在大型数据集上搜索和插入操作的速度时,哈希表是我们可以使用的最有效的数据结构之一。存储在哈希表中的每个数据值都与一个键相关联,如果我们知道这个键,就可以快速访问存储的值。设想一个学生注册系统,其中每个学生都有一个唯一的学号,可以用它作为一个键将他们的数据存储在一个散列表中。

哈希表使用数组来存储数据值。该键用于在存储值的数组中查找索引。但是哈希表如何将这些键和它们的值映射起来呢?

可以使用的方法之一是直接寻址。它使用一对一的映射:每个键指向其数据存储的确切位置。但是这种方法不能有效地使用内存,特别是当键-值对的数量增加并且键变得更大时。因此,哈希表使用哈希函数。

散列函数

哈希表使用哈希函数将数据值映射到它们的键。它将一定范围的键值转换为一定范围的数组索引。将密钥传递给哈希函数所生成的索引或值称为哈希值。下面是一个哈希函数的例子。

h(k) = k % m

  • h 是哈希函数
  • h(k) 是密钥 k 对应的哈希值
  • k 是关键
  • m 是哈希表的大小。对于 m 来说,一个好的选择是一个不接近 2 的幂的质数。

让我们考虑几个键的哈希值。考虑 m=20。

  • k=1001,h(k) = 1001%20 = 1
  • k=1055,h(k) = 1055%20 = 15
  • k=20123,h(k) = 20123%20 = 3

对于 k 值 1001、1055 和 20123,它们的关联值分别存储在哈希表中的索引 1、15 和 3 处。

考虑密钥 2021 的散列值,它是 1。我们之前看到,与键 1001 相关联的值存储在哈希表中的索引 1 处。当两个键生成的哈希值相似时,我们称之为碰撞。哈希表使用链接和开放寻址等技术来解决这种冲突问题。

哈希表的搜索和插入时间复杂度为 O(1)。

应用程序

哈希表用于实现数据库索引。编译器使用哈希表来识别编程语言中的关键字。计算机使用哈希表来链接文件名和它们的路径。

结论

本文提供了对我们作为程序员每天都要接触的 8 种数据结构的底层逻辑的基本介绍。了解了不同数据结构的独特属性后,从今天起,您在为您的编程任务选择最合适的数据结构时就可以更加小心了。但是记住,这只是一个基本的介绍。关于数据结构,你还可以做更多的事情,你也应该学习。

主动学习导论

原文:https://towardsdatascience.com/introduction-to-active-learning-117e0740d7cc?source=collection_archive---------12-----------------------

什么是主动学习?

这篇文章的目标是帮助揭开主动学习的神秘面纱,并展示它与标准的监督机器学习有何不同。

一、什么是主动学习?主动学习是一种机器学习框架,其中学习算法可以交互式地询问用户(教师或 oracle)以用真正的标签标记新的数据点。主动学习的过程也称为最优实验设计。

主动学习的动机是我们拥有大量未标记数据的场景。考虑训练一个图像分类模型来区分猫和狗的问题。每一个都有数百万张图片,但并不是所有的图片都需要用来训练一个好的模型。一些图像可能比其他图像提供更多的清晰度和信息。另一个类似的应用是对 Youtube 视频的内容进行分类,其中的数据本来就很密集,而且存在很多。

被动学习是一种标准框架,其中大量标记数据被传递给算法,这需要在标记整个数据集方面付出大量努力。

被动机器学习。

通过使用主动学习,我们可以有选择地利用像众包这样的系统,让人类专家有选择地标记数据集中的一些项目,但不必标记全部。该算法基于某种价值度量迭代地选择信息最丰富的示例,并将这些未标记的示例发送给标记 oracle,Oracle 将这些查询到的示例的真实标签返回给算法。

主动机器学习。鸣谢:受张懿主动学习的启发幻灯片

在某些情况下,主动学习比随机抽样表现得更好。下图展示了主动学习相对于随机选择的一个激励性的例子。整组数据点(红色三角形和绿色圆圈的集合)不是线性可分的。

鸣谢:图片来自 Burr Settles 主动学习幻灯片

主动学习的动机是理解到并非所有标记的例子都同样重要。通过对所有示例进行统一的随机采样,学习到的模型并不完全代表类别之间的划分。然而,主动学习选择靠近类边界的例子,并且能够找到更有代表性的分类器。先前的研究还表明,对于多类图像分类等任务,主动学习比标准随机选择有所改进[1,2,3,4]。

主动学习框架将数据的选择简化为确定数据集中哪些数据点信息量最大的问题。在主动学习中,信息量最大的数据点通常是模型最不确定的数据点。这需要各种度量来量化和比较示例的不确定性。

不同的主动学习框架

主动学习被认为是一种半监督学习方法,介于无监督使用 0%的学习样本和完全监督使用 100%的样本之间。通过迭代地增加我们的标记训练集的大小,我们可以实现更好的性能,接近完全监督的性能,而使用所有数据进行训练的成本或时间只有一小部分。

基于池的主动学习

在基于池的采样中,训练样本是从大量未标记的数据中选择的。从该库中选择的训练样本由 oracle 标记。

基于流的主动学习

在基于流的主动学习中,所有训练样本的集合作为流呈现给算法。每个示例都被单独发送给算法进行考虑。该算法必须立即决定是否标记该示例。从该池中选择的训练样本被 oracle 标记,并且在显示下一个样本以供考虑之前,该标签被算法立即接收。

不确定性度量

选择信息量最大的数据点的决定取决于选择中使用的不确定性度量。在基于池的采样中,主动学习算法选择信息最丰富的样本添加到不断增长的训练集中。

信息量最大的例子是分类器最不确定的例子。

这里的直觉是,模型最不确定的例子可能是最困难的例子——特别是位于类边界附近的例子。学习算法将通过观察困难的例子获得关于类边界的最多信息。

下面是在主动学习中使用的四种常见的不确定性测量方法,用于选择最有信息量的例子。

1.最小边际不确定性

最小边际不确定性是最佳与次佳不确定性的比较。最小边缘不确定性(SMU)是最可能类别的分类概率减去第二可能类别的分类概率[1]。这种度量背后的直觉是,如果最可能的类的概率明显大于第二最可能的类的概率,那么分类器对该示例的类成员关系更加确定。同样,如果最有可能的类的概率不比第二个最有可能的类的概率大多少,则分类器对该示例的类成员关系不太确定。主动学习算法将选择具有最小 SMU 值的例子。

2.最小置信不确定性

最小置信不确定性(LCU)是选择分类器对所选类别最不确定的例子。LCU 选择只查看最可能的类别,并选择分配给该类别的概率最低的示例。

3.熵减少

熵是随机变量不确定性的度量。在这个实验中,我们使用香农熵。香农熵具有几个基本性质,包括(1)均匀分布具有最大不确定性,(2)不确定性对于独立事件是可加性的,(3)添加零概率的结果没有影响,以及(4)具有特定结果的事件没有影响[6,7]。将类别预测视为结果,我们可以测量预测类别概率的香农熵。

熵值越高,表明概率分布的不确定性越大[1]。在每个主动学习步骤中,对于训练集中的每个未标记的示例,主动学习算法计算预测类概率的熵,并选择具有最高熵的示例。具有最高熵的例子是分类器对其类成员关系最不确定的例子。

4.最大边际不确定性

最大边际不确定性是最佳与最差不确定性的比较[5]。最大边缘不确定性(LMU)是最可能类别的分类概率减去最不可能类别的分类概率。这种度量背后的直觉是,如果最可能的类的概率明显大于最不可能的类的概率,那么分类器对该示例的类成员关系更加确定。同样,如果最可能类的概率不比最不可能类的概率大多少,那么分类器对该示例的类成员关系就不太确定。主动学习算法将选择具有最小 LMU 值的例子。

算法

下面的算法是一个基于池的主动学习[8]。基于流的主动学习可以类似地编写。

大规模分类任务中的一个主要瓶颈是训练分类器所需的大量训练样本。使用主动学习,我们可以通过有策略地选择特定的例子来减少教授分类器所需的训练例子的数量。

参考

[1] A. J. Joshi,F. Porikli 和 N. Papanikolopoulos,“用于图像分类的多类主动学习”, 2009 年 IEEE 计算机视觉和模式识别会议,佛罗里达州迈阿密,2009 年,第 2372–2379 页。

[2]郭,冼,雍睿,唐金辉,,“二维主动学习在图像分类中的应用”, 2008 年 IEEE 计算机视觉与模式识别会议,美国阿拉斯加州安克雷奇,2008,第 1-8 页。

[3]张怡园、汤绍清、吴国光和张振聪。“基于支持向量机概念的图像检索主动学习”, IEEE 多媒体汇刊,2005。

[4] A. Kapoor,K. Grauman,R. Urtasun 和 T. Darrell,“使用高斯过程进行对象分类的主动学习”, 2007 年 IEEE 第 11 届国际计算机视觉会议,里约热内卢,2007 年,第 1–8 页。

[5]https://becoming human . ai/accelerate-machine-learning-with-active-learning-96 ce a4 b 72 fdb

[6]https://towards data science . com/entropy-is-a-measure-of-an-determinance-e2c 000301 C2C

[7] L. M. Tiwari,S. Agrawal,S. Kapoor 和 A. Chauhan,“熵作为排队系统中不确定性的度量”, 2011 年全国研究生会议,吉隆坡,2011 年,第 1–4 页。

[8]https://towards data science . com/active-learning-tutorial-57c 3398 e34d

异常检测简介

原文:https://towardsdatascience.com/introduction-to-anomaly-detection-c651f38ccc32?source=collection_archive---------12-----------------------

哈雷戴维森在 Unsplash 上的照片

你有没有想过当某人的社交媒体账户、银行账户或任何其他账户/个人资料被黑客攻击时会发生什么?一些系统如何自动检测此类活动并通知相关机构或立即暂停帐户?这主要是通过称为异常检测(又名异常检测)的过程来完成的。事实上,上述特定示例被称为欺诈检测,它是异常检测在许多领域中的一个流行应用。因此,让我们深入了解异常检测术语。

异常检测或异常值检测是识别罕见项目、观察值、模式、异常值或与正常项目或模式显著不同的异常的过程。异常有时被称为离群值、新奇值、噪音、偏差或例外。根据一些文献,存在三类异常检测技术。分别是监督异常检测非监督异常检测、半监督异常检测

监督与非监督异常检测

异常检测最常见的版本是使用无监督的方法。在那里,我们使用未标记的数据集训练一个机器学习模型来适应正常行为。在这个过程中,我们做了一个重要的假设,即训练集中的大多数数据都是正常示例。但是其中可以有一些异常的数据点(比例很小)。那么任何明显不同于正常行为的数据点将被标记为异常。在监督异常检测中,将使用被标记为“正常”和“异常”的数据集来训练分类器。当一个新的数据点到来时,这将是一个典型的分类应用。这两种方法各有利弊。有监督的异常检测过程需要大量的正反例。获得这样的数据集将非常困难,因为异常的例子很少。即使您获得了这样的数据集,您也只能对收集的数据集中的异常模式进行建模。然而,在任何领域都有许多不同类型的异常,而且未来的异常可能与迄今为止看到的例子完全不同。任何算法都很难从异常的例子中学习;异常点是什么样子的。这就是无监督方法流行的原因。捕捉正常行为比捕捉许多不同类型的异常要容易得多

异常检测背后的术语

现在让我们深入探讨无监督异常检测背后的想法。在整篇文章中,该过程将被称为异常检测,而不是无监督的异常检测。在开始讨论异常检测算法之前,有一个叫做高斯(正态)分布的东西,这是整个算法的基础。在统计学中,高斯或正态分布是实值随机变量的一种连续概率分布形式。使用下面的公式计算概率函数。𝝁是平均值,𝝈^2 是方差。

概率分布关于其平均值是对称的,并且在整个实线上非零。正态分布有时被称为钟形曲线,因为密度图看起来像一个钟。

异常检测的基本思想是找到一个概率函数来捕捉正常行为,并发现一个概率阈值,使得远离该阈值的数据点被视为异常。考虑概率函数为 p(x ),阈值为ε,这可以描述如下。数据点用十字表示。

在基本的异常检测算法中,我们假设每个特征根据其自身的高斯分布分布,具有一些均值和方差。因此,使用训练数据集,我们针对特征 x1,x2,…,xn 拟合一组参数𝝁1,𝝁2,…,𝝁n 和𝝈12,𝝈22,…,𝝈n^2。然后概率函数 p(x)被计算为 x1 的概率乘以 x2 的概率乘以 x3 的概率,以此类推直到 xn 的概率。这就是异常检测的机器学习模型。当一个新的数据点进来时,我们简单地计算概率 p(x ),如果概率小于ε,就将其标记为异常。找到ε的正确值是一个优化目标,我不打算在本文中解释。

关于异常检测的更多信息

一个重要的事实是选择一组指示异常的特征。也就是选择一组特征,其中这些特征在出现异常时可能呈现异常大或异常小的值。另一方面,可能会有一些缺点,因为我们必须手动创建特征。此外,该算法只能检测少数异常情况。例如,当数据分布如下时,我们如何检测异常。

如您所见,使用高斯分布的早期模型将一些正常数据点标记为异常,将一些异常示例标记为正常数据点(上图中的蓝色边界)。事实上,我们需要为这种数据分布设置一个高级的边界(也许是紫色的边界)。使用多元高斯分布解决了这个特殊问题。在这里,不是将每个要素建模为各自的高斯分布并乘以概率,而是将所有要素建模为一个称为多元高斯分布的公共分布。

流行技法

今天,当实现异常检测算法时,您不必担心上述细节。像 scikit-learn(python)这样的流行库提供了更简单的方法来实现异常检测算法。下面是一些用于异常检测的流行技术。

  • 基于密度的技术(KNN、局部异常因子、隔离森林等)
  • 基于聚类分析的技术(KMeans、DBSCAN 等)
  • 贝叶斯网络
  • 神经网络、自动编码器、LSTM 网络
  • 支持向量机
  • 隐马尔可夫模型
  • 基于模糊逻辑的异常检测

一些应用

  • 欺诈检测(例如:网络、制造、信用卡欺诈等)
  • 入侵检测
  • 探伤
  • 系统健康监控
  • 检测生态系统干扰
  • 产品质量异常检测

结论

异常检测是一种发现罕见项目或数据点的技术,这些项目或数据点将与其余数据显著不同。尽管异常检测背后的术语使用了概率论和一些统计学,但有许多技术可以轻松实现异常检测算法。

BigQuery 中数组的介绍

原文:https://towardsdatascience.com/introduction-to-arrays-in-bigquery-d9f6bd84ce54?source=collection_archive---------25-----------------------

实际用例:字数统计

Joshua SortinoUnsplash 上的照片

我每天都在使用 BigQuery,不得不说它的速度和易用性令人惊叹。

我为什么喜欢 BigQuery?三个原因:

  1. 它无需服务器,完全受管理。除了我的疑问,我什么都不用想。
  2. 由于高效的压缩柱状存储,它的速度非常快。
  3. 它有一个现代化的用户界面:我可以从浏览器做任何事情,没有笨重的安装。

为了举例说明性能,这里有一个 18.5M 行的表:

让我们对它运行一个简单的正则表达式查询,提取所有问题的标题和正文,其中标题提到了以下编程语言之一:pythonrstatssql:

select title, body 
from `bigquery-public-data.stackoverflow.posts_questions` 
where regexp_contains(title, r"\b(python|rstats|sql)\b")

以下是输出结果:

我不知道你,但 21 秒处理 26.9 GB…我印象深刻。想知道那要花多少钱吗?BigQuery 每处理一 TB 收费 5 美元,因此查询成本为 26.9 / 1000 * 5 = 0.1345 美元。

至此,让我们直接开始使用 BigQuery 中的数组。

在 BigQuery 中使用数组

现在你可能已经猜到了,我们将会统计 StackOverflow 问题中出现的单词。但是在我们开始实际的例子之前,我想先介绍一下在 BigQuery 中使用数组的基础知识。

1.创建数组

在原型开发阶段,创建小的数组会很有用。例如:

select 
'Engineering' as role, 'Mike' as name, ['Java', 'C#'] as languages union all select 'Data science' as role, 'Vlad' as name, ['python', 'SQL', 'R'] as languages union all select 'Front-end' as role, 'Guillaume' as name, ['javascript', 'C#', 'HTML', 'CSS'] as languages

这为我们提供了以下输出:

注意数组是如何垂直嵌套在每行中的。

2.展平数组

如果我们想把这个嵌套结构变成一个普通的平面表,我们需要取消嵌套数组:

with T0 as 
(select 'Engineering' as role, 'Mike' as name, ['Java', 'C#'] as languages union all select 'Data science' as role, 'Vlad' as name, ['python', 'SQL', 'R'] as languages union all select 'Front-end' as role, 'Guillaume' as name, ['javascript', 'C#', 'HTML', 'CSS'] as languages) SELECT role, name, languages 
from T0 
CROSS JOIN UNNEST(T0.languages) as languages

CROSS JOIN UNNEST代码执行所谓的关联连接,这意味着它跟踪每个数组与哪一行相关联,这样就不会不必要地执行完全的交叉连接。

我们现在得到了更熟悉的扁平和重复结构:

3.索引数组

假设我们想知道每个程序员最后的语言是什么。BigQuery 中数组的索引有两种方式:基于 0 的索引(python 风格)用OFFSET或者基于 1 的索引(R 风格)用ORDINAL

我们将以ORDINAL为例,和ARRAY_LENGTH一起检索每个数组的长度。使用与上面相同的 T0 定义:

SELECT role, name, languages[ORDINAL(ARRAY_LENGTH(languages))] as last_language from T0

使用 BigQuery 统计单词

基础知识讲完了,让我们进入一个具体的数组用例。

我们希望有一种方法来统计问题标题中每个单词的频率,如果可能的话,还有一种方法来捕捉单词和问题标签之间的相关性。

将字符串转换成单词数组的一个关键函数是split函数。这里有一个例子:

select title, tags, split(title, ' ') as words 
from `bigquery-public-data.stackoverflow.posts_questions` limit 10

有趣的是,我们在上图中看到我们有一串标签。让我们把它也变成一个数组:

select 
title, 
split(tags, '|') as tags, 
split(title, ' ') as words 
from `bigquery-public-data.stackoverflow.posts_questions` limit 10

所以每行包含两个数组:

现在我们将交叉连接/取消嵌套两个数组,并过滤掉不感兴趣的单词,即长度小于 2 个字符的单词和一些常见的停用词:

with t0 as (select 
id, 
title, 
split(tags, '|') as tags, 
split(title, ' ') as words 
from `bigquery-public-data.stackoverflow.posts_questions`) select 
id, 
tag, 
word 
from t0 
cross join unnest(t0.words) as word 
cross join unnest(t0.tags) as tag 
where length(word) > 1 
and lower(word) not in ('me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', 'her', 'hers', 'herself', 'it', "it's", 'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', 'these', 'those', 'am', 'is', "isn't", 'are', 'was','were', "aren't", "wasn't", "weren't", 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 'can', "can't", 'will', "won't", 'just', "don't", 'should', "shouldn't", 'now', 'get')

这个查询运行了 24 秒,就这样,我们获得了所有相关标签和单词的笛卡尔积:

现在我们可以很容易地问,对于一个给定的标签,例如python(假设上一步的输出已经保存在表so中,在数据集temp内),哪些单词最能被表示出来:

select 
word, 
count(*) as frequency 
from `temp.so` where tag='python' 
group by word order by frequency desc

这是我们得到的结果:

或者我们可以反过来问什么标签与一个特定的单词相关联,例如flask:

select 
tag, 
count(*) as frequency 
from temp.so 
where word = 'flask' 
group by tag order by frequency desc

我们得到了:

更进一步

在这里,tf-idf 分析将有助于挑选出 python 相对于其他标记真正特有的内容。虽然超出了本文的范围,但这将是一个很好的副业。

数组构成了 BigQuery 的一个重要特性,我还期待着写一些其他的好东西。在我看来,BigQuery 是最令人印象深刻的大数据分析工具之一!

人工神经网络导论

原文:https://towardsdatascience.com/introduction-to-artificial-neural-networks-ac338f4154e5?source=collection_archive---------41-----------------------

莫里茨·金德勒在 Unsplash 上拍摄的照片

人工智能,顾名思义,就是通过让机器像人一样思考或行动,让机器具备人工智能。它正在快速前进,深度学习是其中的主要贡献者之一。

深度学习

它是机器学习的一个子领域,处理受大脑结构和功能启发的算法,称为人工神经网络。这些类似于中枢神经系统的结构,其中每个神经元相互连接。

图片来源:geospatialworld.net

英国数学家、乐购俱乐部卡的设计者克莱夫·亨比创造了一个短语数据是新的石油。如果数据是新的石油,数据库和仓库被认为是将数据推入互联网的石油钻塔,那么你可以想象深度学习是将原油转化为所有有用产品的炼油厂。我们不会耗尽数据,因为在互联网上做任何事情都会产生数据。

吴恩达幻灯片,版权所有

深度学习的一些应用包括:

  • 人脸检测和识别
  • 自动驾驶汽车
  • 语言翻译
  • 虚拟助手

履行

它是使用人工神经网络实现的。让我们详细探讨一下神经网络。

这是一种计算模型,其灵感来自人脑中生物神经网络处理信息的方式。深度神经网络的示例如下所示:

图片来源:sciencedirect.com

输入层

输入层由独立变量的输入组成。这些输入可以从外部源加载,如 web 服务或 CSV 文件。简单来说,这些变量被称为特征,例如,卧室的数量,房子的面积,离城市的距离被认为是你在购买房子时的特征。我们随机初始化接近零但不为零的权重。

砝码

权重在神经网络中起着重要的作用,每个节点/神经元都有一定的权重。神经网络通过权重进行学习,通过调整权重,神经网络决定某些特征是否重要。

隐蔽层

它们位于输入层和输出层之间。在这一层,神经元接受一组加权输入,并在激活函数的帮助下产生一个输出。

第一步:在这一步中,输入值和权重相乘,加上偏差,并一起求和。

步骤 2: 在该步骤中,我们应用激活函数,激活函数用于向神经网络引入非线性。这些神经元对输入数据应用不同的变换。深度学习中使用了许多激活函数,其中一些包括 ReLU、阈值函数、Sigmoid 和整流器函数。

第三步:在这一步中,它通过所有的隐藏层,然后传递到输出层。

输出层

这是神经网络的最后一层,从隐藏层的最后一个节点接收输入。该层可以是

  • 连续(股票价格)
  • 二进制(0 或 1)
  • 分类(猫、狗或鸭)

神经网络是如何工作的?

有两种方法可以让程序做你想做的事情

  1. 一种是硬编码,你告诉程序一些特定的规则和你想要的结果。
  2. 第二个是神经网络,你为程序或算法创建一个设施,使其能够理解自己需要做什么。

神经网络循环有两个阶段,一个是训练阶段,一个是预测阶段。寻找权重和偏差值的过程发生在训练阶段。神经网络处理我们的输入以产生预测的过程属于预测阶段。

我们可以认为神经网络的学习过程是一个传递和返回的迭代过程。传递是信息向前传播的过程,返回是信息向后传播的过程。

图片来源:slideshare.net

在前向传播中,网络暴露给数据。给定一些数据,我们计算输入值与指定权重的点积,然后将所有这些值相加,并将激活函数应用于隐藏层中的结果。

我们应用激活函数将非线性引入到网络中,以便它可以容易地映射数据。该节点充当下一层的输入层。如此重复,直到我们得到最终的输出向量 y ,它被认为是神经网络的预测。

获得的输出值称为预测值。为了了解模型的表现,我们将预测值与实际值进行比较,我们得到的差异称为误差,即成本函数。

损失函数与精度成反比,代价函数越少,精度越高,我们的目标是使损失函数最小。损失函数的公式可以描述如下

价值函数

计算损失函数后,我们将该信息反馈给神经网络,在神经网络中,该信息通过权重返回,权重被更新,这种方法被称为反向传播。这个过程重复几次,以便机器理解数据,并且将根据偏好分配特征的权重,最后,我们将处于通过最小化成本函数来实现我们的预测的阶段。

图片来源:slideshare.net

梯度下降

它是一种优化技术,用于通过最小化成本函数来改进基于神经网络的模型。这个过程发生在反向传播步骤中。它允许我们调整特征的权重以达到全局最小值。

图片来源:quantaneo.com

一些梯度下降算法是

  • 批量梯度下降
  • 随机梯度下降
  • 小批量梯度下降

总结整个概念

  • 我们需要初始化随机接近零但不是零的权重。
  • 将第一次观察输入到输入层。
  • 在这里,前向传播发生在神经元被激活的地方,并且向作为输出层的预测传播。
  • 我们使用损失函数比较实际值和预测值,误差值再次反馈给神经网络
  • 反向传播发生在误差值被反馈并反向传递的情况下,并且权重被更新以便最小化损失函数,这导致更好的预测。
  • 对数据集中的所有观测值重复上述步骤,或者在一批观测值之后进行更新。
  • 当整个数据集通过神经网络时,产生一个时期,执行更多的时期。

这就是现在,希望你喜欢阅读关于神经网络。在我的下一篇博客中,我将向你解释卷积神经网络。

面向初学者的人工神经网络介绍

原文:https://towardsdatascience.com/introduction-to-artificial-neural-networks-for-beginners-2d92a2fb9984?source=collection_archive---------17-----------------------

理解神经网络的概念

塞尔吉奥·索萨在 Unsplash 上的照片

介绍

ann(人工神经网络)是深度学习的核心,是机器学习技术的高级版本。人工神经网络具有通用性、适应性和可扩展性,使其适合处理大型数据集和高度复杂的机器学习任务,如图像分类(如谷歌图像)、语音识别(如苹果的 Siri)、视频推荐(如 YouTube)或分析客户情绪(如 Twitter 情绪分析器)。

神经生理学家沃伦·麦卡洛克和数学家沃尔特·皮茨在 1943 年首次介绍了人工神经网络。然而,安有它的起伏。1960 年后,随着支持向量机和其他强大的机器学习技术的进步,研究人员对神经网络的兴趣和兴奋程度有所下降,这些技术产生了更好的准确性,并具有更强的理论基础。神经网络很复杂,需要巨大的计算能力和时间来训练。然而,1990 年后,计算领域的进步(参考摩尔定律)以及随后强大的 GPU 卡的生产带来了一些兴趣。

图一。展示了随着数据量的增加,性能的变化。大多数算法对较小的数据集产生类似的性能测量,然而,一旦数据量扩展超过某个阈值,神经网络工作得最好。(图片由作者使用一个笔记开发)

分类算法

让我们尝试使用分类案例研究来分析一个神经网络。假设我们使用三个独立变量 X1、X2 和 X3,X1 代表贷款金额,X2 代表贷款期限,X3 代表婚姻状况。我们希望开发一种分类算法,该模型可以预测客户是否会违约(二元分类)。因此,这种情况下的等式将是 Z=X1w1 + X2w2 + X3*w3 + b,其中 w1、w2 和 w3 是与独立变量相关的权重,b 是偏差项,通常称为噪声/随机噪声。如果你熟悉 sigmoid 函数(用于逻辑回归),你会知道我们尝试对我们的数据建模,使其遵循下面概述的曲线。

图二。逻辑回归问题中使用的 sigmoid 曲线的图示。(图片由作者使用 Excel 和 Power Point 开发)

Y=1/(1+e^-Z).给出了 Sigmoid 函数 y 假设 Z=X1w1 + X2w2 + X3*w3 + b,并求解 Y,我们将得到 log(Y/(1-Y))= X1 * w1+X2 * w2+X3 * w3+b,其中我们试图计算每个客户的概率得分。计算如下所示。

图 3。使用 sigmoid 函数推导逻辑回归方程。(图片由作者开发)

一旦模型开始训练,我们需要优化成本函数,即减少实际值和预测值之间的误差。由于上述示例讨论了二元分类问题,这里的一般思想是对于被标记为违约者(比如标签 1)的客户,概率值应该尽可能地接近 1,类似地,对于被标记为非违约者(比如标签 0)的客户,预测的概率得分应该尽可能地接近 0。逻辑回归方程的成本函数和平均成本函数使用以下公式计算。

图 4。成本函数用于寻找逻辑回归的最佳参数估计。(图片由作者开发)

神经网络体系结构

为了使用神经网络实现相同的问题空间,我们需要创建基于神经元的结构。在进入架构之前,让我们看一下神经网络的一些组件。

  1. 输入层 —代表输入变量加上偏差项。因此,如果有 n 个输入变量,则输入层的大小为 n + 1,其中+ 1 是偏置项
  2. 隐藏的一层/多层——这些表示所有数学计算都在其中完成的神经元。注给定的神经网络可以在一个隐藏层或多个隐藏层中有多个神经元
  3. 激活功能 —在将信息传递给连续层之前,转换给定层的输出。激活函数是确定给定神经网络输出的数学方程。是隐层中每个神经元的一部分,决定与预测相关的输出
  4. 输出层——网络的最终“输出预测”
  5. 正向传播 —计算从输入层到输出层的每次迭代的输出
  6. 反向传播-通过分析用于优化模型输出的成本函数的导数,计算每次正向传播后的修正权重(w1、w2、w3 和 b1)
  7. 学习率 —确定每次反向传播后归因于每个权重和偏差项的百分比变化,即控制模型学习数据信息的速度

图 5。用于当前分类问题的单层神经网络的结构。(图片由作者开发)

那么在神经网络中会发生什么呢?

ANN 算法的思想是确定权重和偏差项的最佳值,使得误差函数尽可能最小。因此

  • 步骤 1 —权重 w1、w2、w3 和 b1 用一些随机值初始化
  • 步骤 2 —隐藏层使用给定的权重和输入变量计算概率得分。如果适用,应用激活函数(例如,sigmoid)
  • 步骤 3 —使用成本函数,并重复梯度下降算法来计算更新的权重。更新的权重被确定为权重(w)= w-α(dJ/dw),其中α是学习率,dJ/dw 是权重变化时成本函数的变化。类似地,bias (b) = b-alpha(dJ/db)
  • 步骤 4 —重复步骤 2 和 3,直到成本函数最小

图 6。具有多个隐藏层的人工神经网络(图片来自 GIPHY)。

[## 张量流-神经网络游乐场

这是一种构建从数据中学习的计算机程序的技术。它非常松散地基于我们如何思考…

playground.tensorflow.org](https://playground.tensorflow.org/#activation=sigmoid&batchSize=10&dataset=circle&regDataset=reg-plane&learningRate=0.03&regularizationRate=0&noise=0&networkShape=1&seed=0.54304&showTestData=false&discretize=false&percTrainData=70&x=true&y=true&xTimesY=false&xSquared=false&ySquared=false&cosX=false&sinX=false&cosY=false&sinY=false&collectStats=false&problem=classification&initZero=false&hideText=false)

为什么我们需要人工神经网络?

利用 Tensorflow 神经网络操场将提供对神经网络优于集成技术、逻辑回归或支持向量机的优势的更好理解。

图 7。使用 flower 数据集将数据点分类为各自的颜色。(图片由作者使用 Jupyter 笔记本开发)

在试图将不同的坐标(比如说 x 和 y)分类时,在二维空间中显示的代表花的图像变成它们各自的颜色。逻辑回归和神经网络用于将坐标分类成特定的颜色。逻辑回归处理决策边界,因此要理解逻辑回归在识别点的颜色方面的影响,识别决策边界是很重要的。逻辑回归的输出清楚地表明,该算法使用线性决策边界来将点分类到它们各自的颜色,因此最终错误地分类了许多数据点。具有一个隐藏层的神经网络产生改进的决策边界,从而导致更高的准确性。

图 8。说明了多个神经元对最终输出的影响。神经元数量越多,分类精度越好。(图片由作者使用 Jupyter 笔记本开发)

关于作者:高级分析专家和管理顾问,帮助公司通过对组织数据的商业、技术和数学的组合找到各种问题的解决方案。一个数据科学爱好者,在这里分享、学习、贡献;你可以在 LinkedIn Twitter上和我联系。

深度学习中的注意机制介绍——Eli 5 Way

原文:https://towardsdatascience.com/introduction-to-attention-mechanism-in-deep-learning-eli5-way-d6c2d799ef18?source=collection_archive---------30-----------------------

ELI5 项目机器学习

乔希·拉科瓦尔在 Unsplash 上的照片

在这篇文章中,我们将讨论作为注意力机制发展动力的编码器-解码器模型的一些局限性。之后,我们将讨论注意模型的概念及其在机器翻译中的应用。

注意:注意机制是一个稍微高级的话题,需要理解编码器-解码器和长短期记忆模型。请参考我以前关于编解码器型号LSTM 的文章

在我们讨论注意力模型的概念之前,我们先来回顾一下使用编码器-解码器模型的机器翻译任务。

引用说明:本文的内容和结构是基于我对四分之一实验室深度学习讲座的理解——pad hai

机器翻译—概述

让我们以使用 seq2seq 模型将文本从印地语翻译成英语为例,该模型使用编码器-解码器架构。编码器-解码器架构中的底层模型可以是从 RNN 到 LSTM 的任何东西。

在高层次上,encoder 只读取整个句子一次,并将来自先前隐藏的表示和先前输入的所有信息编码到一个编码向量中。然后,解码器在每个时间步长使用这种嵌入来产生新的单词。

这种方法的问题是,编码器只读取整个句子一次,它必须记住所有内容,并将句子转换为编码向量。对于较长的句子,编码器将无法记住序列的开始部分,从而导致信息丢失。

人类就是这样翻译一句话的吗?

你认为整个输入序列(或句子)在编码过程中的每个时间点都很重要吗?。我们可以特别强调某些单词而不是同等重视所有的单词吗?。注意力机制就是为了应对这些挑战而发展起来的。

我们人类试图通过只关注输入中的某些单词来翻译输出中的每个单词。在每个时间步,我们只从长句中提取相关信息,然后翻译特定的单词。 理想情况下,在每个时间步,我们应该只将相关信息(相关信息的编码)提供给解码器进行翻译。

注意机制—甲骨文

我们如何知道哪些词是重要的,或者我们需要给予更多的关注?。现在,假设我们有一个神谕来告诉我们在给定的时间步长 t 应该关注哪些单词。在神谕的帮助下,我们能否设计出更好的架构,以便将相关信息反馈给解码器?。

因此,对于每个输入单词,我们分配一个权重 α (范围在 0-1 之间),表示该单词在时间步长' t' 对输出的重要性。例如, α 12 表示第一个输入字在第二时间步对输出字的重要性。概括地说,表示法 α jt 表示在 tᵗʰ时间步长与 jᵗʰ输入字相关联的权重。

注意时间-步骤 2

例如,在时间步长 2,我们可以只对相应的单词表示以及权重 α jt 进行加权平均,并将其送入解码器。在这种情况下,我们不是将完整的编码矢量输入解码器,而是输入单词的加权表示。实际上,我们根据甲骨文给出的权重,对重要的词给予了更多的重视或关注。(感谢甲骨文!)

直觉上,这种方法应该比编码器-解码器架构的普通版本更好,因为我们没有用不相关的信息使解码器过载。

注意力模型

别被骗了,现实中,没有神谕。如果没有神谕,那我们怎么知道重量呢?。

符号:从现在开始,我们将 tᵗʰ时间步的解码器状态称为 St ,将 jᵗʰ时间步的编码器状态称为 hⱼ

必须从数据中学习参数 α jt。为了实现这一点,我们定义了一个函数,

注意力功能

计算中间参数的函数( e jt)有两个参数。让我们讨论一下这些参数是什么。在 tᵗʰ时间步长,我们试图找出 jᵗʰ字有多重要,因此计算权重的函数应该取决于字本身的矢量表示(即……hⱼ)和直到该特定时间步长的解码器状态(i.e…St-₁).

权重 e jt 捕捉 jᵗʰ输入字对于解码 tᵗʰ输出字的重要性。使用 softmax 函数,我们可以归一化这些权重,以获得我们的参数 α jt(范围在 0-1 之间)。

参数 α jt 表示聚焦在 jᵗʰ字上以产生 tᵗʰ输出字的概率。

注意力功能

在上一节中,我们已经讨论了如何使用一个高级函数来学习参数 α jt,该函数带有两个参数——tᵗʰ时间步长之前的解码器状态(St-₁)和单词的矢量表示(hⱼ).使用 softmax 对该函数的输出进行归一化,以获得 α jt。

在本节中,我们将定义 e jt 的参数形式,以便我们能够从数据中学习该参数。计算 e jt 最常用的参数形式或函数如下:

注意参数函数

为了学习参数 e jt,我们引入了额外的参数 Vₐₜₜ、Uₐₜₜ和 Wₐₜₜ.其中 Uₐₜₜ表示与编码器输入相关的权重,Wₐₜₜ表示与解码器隐藏状态相关的权重,Vₐₜₜ表示与解码器输出相关的权重。这些参数也将与编码器-解码器模型的其他参数一起被学习。

机器翻译——注意力机制

在上一节中,我们能够定义参数函数来学习权重( e jt,在规范化之前)以给予特定单词更多的关注。在本节中,我们将讨论使用注意机制的端到端机器翻译任务。

机器翻译—注意

在这项任务中,我们将输入内容从印地语翻译成英语。为简单起见,我们假设 RNN 的被用作编码器和解码器模型。但是你也可以用 LSTM 或者 GRU 的任何变体。

编码器

  • 当我们不加注意地将其与编码器-解码器架构的普通版本进行比较时,编码器的操作没有太大变化。
  • 在每个时间步长,每个字的表示被计算为前一个时间步长的输出和当前输入以及偏置的函数。
  • 最终隐藏状态 vector(sₜ)包含来自先前隐藏表示和先前输入的所有编码信息。
  • RNN 被用作编码器。

解码器

  • 在编码器-解码器模型的普通版本中,我们将整个编码向量传递到输出层,输出层解码成下一个可能单词的概率分布。
  • 我们不需要传递整个编码向量,而是需要使用我们在上一节中讨论的寻找 e jt 的有趣等式来寻找注意力权重。然后使用 softmax 函数归一化 e jt 权重,得到 α jt。
  • 一旦我们有了输入解码器的所有输入和与之相关的权重(感谢这个奇妙的等式!),我们将计算所有输入和权重的加权组合,以获得合成向量 Ct。
  • 我们将把加权组合向量 Ct 馈送给解码器 RNN,该解码器解码成下一个可能单词的概率分布。这种解码操作适用于输入中出现的所有时间步长。
  • 输出层是一个 softmax 函数,它将隐藏状态表示和与之关联的权重以及偏差作为输入。

不是吓人的功能。真的!!

这些模型被称为编码-出席-解码模型或也称为 Seq2Seq 与注意

推荐阅读—ELI5 项目机器学习

[## 编码器-解码器模型简介— ELI5 路

讨论编码器-解码器模型的基本概念及其在一些任务中的应用,如语言建模…

towardsdatascience.com](/introduction-to-encoder-decoder-models-eli5-way-2eef9bbf79cb) [## 长短期记忆和门控循环单位的解释——Eli 5 方式

在这篇文章中,我们将学习 LSTM 和格鲁工作背后的直觉

towardsdatascience.com](/long-short-term-memory-and-gated-recurrent-units-explained-eli5-way-eff3d44f50dd)

结论

在这篇文章中,我们讨论了机器翻译中编码器-解码器模型的普通版本的一些限制。对于较长的句子,编码器将无法记住序列的开始部分,从而导致信息丢失。之后,我们研究了如何只将相关信息提供给解码器,或者将更多注意力放在有助于在较长序列中保留信息的重要单词上。

从那里,我们讨论了参数函数,以了解在解码过程中给予某些单词更多重要性所需的注意力权重。最后,我们使用注意机制研究了端到端的机器翻译任务。

在我的下一篇文章中,我们将讨论使用 Pytorch 实现注意力机制。所以确保你在媒体上跟随着我,一旦它掉下来,你就会得到通知。

直到那时,和平:)

NK。

作者简介

Niranjan Kumar 是好事达印度公司的高级数据科学顾问。他对深度学习和人工智能充满热情。除了在媒体上写作,他还作为自由数据科学作家为 Marktechpost.com 写作。点击查看他的文章

你可以在 LinkedIn 上与他联系,或者在 Twitter 上关注他,了解关于深度学习和机器学习的最新文章。

参考资料:

贝叶斯决策理论简介

原文:https://towardsdatascience.com/introduction-to-bayesian-decision-theory-1532376ef986?source=collection_archive---------6-----------------------

图片来自 Seo et。阿尔(2006 年)

机器学习的统计方法

介绍

无论你是在建立机器学习模型还是在日常生活中做决策,我们总是选择风险最小的路径。作为人类,我们天生会采取任何有助于生存的行动;然而,机器学习模型最初并不是基于这种理解建立的。这些算法需要训练和优化,以选择风险最小的最佳选项。此外,重要的是要知道,一些风险决策如果不正确,可能会导致严重的后果。

图片由福布斯

考虑癌症检测的问题。根据患者的计算机断层扫描(CT)扫描,放射科医师可以确定肿瘤的存在吗?如果他们认为患者体内有肿瘤,那么医生需要判断肿瘤是良性还是恶性,以确定适当的治疗方法。因为这篇文章的目的是描述做出这些决定的统计方法,所以我将只专注于分解问题的第一部分:是否有肿瘤,是还是不是?

贝叶斯定理

在统计和概率的世界中,最著名的等式之一是贝叶斯定理(见下面的公式)。基本的直觉是,给定某个特征(即属性),某个类或事件发生的概率是基于特征值的可能性和关于感兴趣的类或事件的任何先验信息来计算的。这看起来有很多要消化,所以我将为你分解一下。首先,癌症检测是两类问题。第一类ω1 代表肿瘤存在的事件,ω2 代表肿瘤不存在的事件。

在先的;在前的

贝叶斯定理有四个部分:先验、证据、可能性和后验。先验(P(ω1),P(ω2))定义事件ω1 或ω2 在自然界发生的可能性。重要的是要认识到先验视情况而定。由于目标是检测癌症,可以有把握地说肿瘤存在的概率非常低:P(ω1)

可能性

从高层次来看,CT 扫描是指 x 射线以圆周运动的方式进行扫描。产生的关键指标之一是衰减,这是对 x 射线吸收的一种测量。密度越高的物体衰减越大,反之亦然。因此,与肺组织相比,肿瘤更可能具有高衰减。

假设您只查看衰减值,以帮助您在ω1 和ω2 之间做出决定。每个类别都有一个类别条件概率密度 p(x|ω1)和 p(x|ω2),称为似然性。下图显示了 p(x|ω)的假设类条件概率密度。这些分布是通过分析你的训练数据提取出来的;然而,让领域专家来检查数据的有效性总是好的。

照片来自杜达、哈特和斯托克公司的模式识别

证据

描述证据 p(x)的最佳方式是通过全概率法则。该定律指出,如果有互斥事件(例如ω1 和ω2),其发生概率总和为 1,则某个特征(例如衰减)的概率是所有互斥事件的概率乘以先验总和。

在后面的

使用贝叶斯定理的结果称为后验 P(ω1|x)和 P(ω2|x)。后验概率表示在给定测量值 x(例如衰减)的情况下,观察值属于ω1 或ω2 类(即肿瘤是否存在)的概率。每一次观察都得到每一类的后验概率,所有的后验概率总和必须为 1。关于我们试图解决的癌症检测问题,有两种后验概率。下图是后验值如何根据测量值 x 变化的假设场景。除了似然性和后验之间的联系,后验值还会受到先验 P(ω)的严重影响。

决策规则

现在,我们对贝叶斯定理有了很好的理解,是时候看看我们如何使用它来确定我们两个类之间的决策边界了。有两种方法可以确定患者是否存在肿瘤。第一种是基本方法,仅使用先验概率值来做出决策。第二种方法利用后验概率,它利用了先验和类条件概率分布。

利用先验知识

假设我们只根据自然的先验概率做出决策。这意味着我们忘记了贝叶斯定理中的所有其他因素。由于有肿瘤的概率 P(ω1)远小于没有一个 P(ω2),所以我们的模型/系统将总是决定每个患者没有肿瘤。即使模型/系统在大多数情况下是正确的,它也不会识别出实际上患有肿瘤并且需要适当医疗护理的患者。

利用后验概率

现在让我们通过使用后验概率 P(ω1|x)和 P(ω2|x)来采取更全面的方法。由于后验概率是贝叶斯定理的结果,先验的影响通过类条件概率密度 p(x|ω1)和 p(x|ω2)来减轻。如果我们的模型/系统正在寻找比普通组织具有更高衰减的区域,那么尽管存在自然的先验概率,肿瘤存在的概率也会增加。让我们假设一个特定区域有 75%的机会包含肿瘤,那么这意味着有 25%的机会根本没有肿瘤。这 25%的概率就是我们出错的概率,也就是风险。

结论

您刚刚学到的是贝叶斯决策理论的一个简单的单变量应用,通过使用多变量高斯分布代替证据和可能性,可以将其扩展到更大的特征空间。虽然这篇文章的重点是解决癌症检测的问题,但是贝叶斯定理在很多领域都有应用,包括投资、营销和系统工程。

资源

[1]徐英宇。(2006).针对内部人员非法机密访问的成本敏感访问控制。IEEE 情报与安全信息学会议录:2006 年 5 月 23-24 日。3975.117–128.10.1007/11760146_11.

[2]杜达,R. O .,哈特,P. E .,施托克,D. G. (2001 年)。模式分类。纽约:威利。国际标准书号:978–0–471–05669–0

[3] Glatter,r .,“覆盖肺癌高危人群低剂量 CT 扫描的医疗保险”,《福布斯》(2015 年)

贝叶斯推理简介

原文:https://towardsdatascience.com/introduction-to-bayesian-inference-18e55311a261?source=collection_archive---------33-----------------------

用一些理论和一步一步的例子来说明基础——疾病的诊断和参数估计

动机

想象一下下面的场景:你开着救护车去医院,必须在路线 A 和 b 之间做出选择,为了救你的病人,你需要在 15 分钟内到达。如果我们估算 A 路线需要 12 分钟,B 路线需要 10 分钟,你会选择哪个?B 路线似乎更快,为什么不呢?

目前提供的信息包括路线 A 和 B 的点估计。现在,让我们添加关于每个预测的不确定性的信息:路线 A 需要 12 分钟 1 分钟,而路线 B 需要 10 分钟 6 分钟。

现在看来,路线 B 的预测明显更加不确定,最终可能会超过 15 分钟的限制。在这里加入关于不确定性的信息,可以让我们改变决策,从走 B 路线到走 a 路线。

马克·克鲁兹在 Unsplash 上的照片

鸣谢:之前的例子是根据我在哥伦比亚大学Tamara Broderick 教程中的记忆。与这个例子相关的工作可以在[1]中找到。

更广泛地说,考虑以下情况:

  • 我们想要估计一个没有固定值的量,相反,它可以在不同的值之间变化
  • 不管真实值是否固定,我们都想知道我们估计的不确定性

救护车的例子旨在说明第二种情况。对于第一种情况,我们可以快速浏览一下诺贝尔经济学奖得主克里斯托弗·西姆斯的工作。我将简单地引用他的学生渡边俊昭 :

我曾经问过克里斯,为什么他喜欢贝叶斯方法。他以卢卡斯评论作为回答,该评论认为,当政府和央行政策改变时,模型参数也会改变,因此它们不应被视为常数,而应被视为随机变量。

对于这两种情况,贝叶斯推理可以用来将我们感兴趣的变量建模为一个整体分布,而不是一个唯一的值或点估计。

介绍

贝叶斯推理的核心是贝叶斯法则:

贝叶斯法则

给定条件概率的定义,这个规则可能看起来非常明显并且几乎是多余的,尽管它的使用不是立即清楚的:

条件概率定义

贝叶斯规则的推导

朱迪亚·珀尔是这样描述的,在的《何以见得》【2】:

(……)贝叶斯规则在形式上是他的条件概率定义的基本结果。但从认识论上来说,它远非初等。事实上,它作为一种规范性规则,根据证据更新信念。

的确,这个看似简单的概念受到了极大的关注。它的一些实际结果在于允许反转条件概率[从 P(B|A)到 P(A|B)],并且随着我们观察 B 的更多样本,更新我们对 A 可以取的值(即它的分布)的信念。

在我们深入例子之前,让我们先给贝叶斯法则的组成部分命名:

又是贝叶斯法则

让我们简单讨论一下每个组件的含义。希望下一节中的例子能让这些定义更加清晰。

假设我们有兴趣了解 A,但只能观察 B:

  • 之前的是我们在观察 b 的任何值之前,对“A 取每个可能值的可能性”的信念。换句话说,我们必须选择一个分布而不是 A,我们有机会结合专家知识(我们有先验的),或者如果我们一无所知,可以简单地选择均匀分布。**
  • 似然 表示“对于 A 的每个可能值,B 可以取的所有值的分布是什么”。于是我们定义了 B 上的一组分布,一个分布对应 A 的每个值,更具体地说,每个分布 P(B|A= a )是我们假设 A 等于某个值 a 后 B 的条件分布。
  • 证据 是我们观察到的东西的总体概率(我们观察到 B,可以看作 A 的证据)。一旦我们有了先验和似然性,就可以通过对 A 的所有可能值求和来计算,如下所示。这个量可能很难计算,需要近似计算技术,如蒙特卡罗或变分推断。

证据的计算(使用全概率法则)。如果 A 是连续的,求和就被一个积分代替。

  • 后验 ,这是我们在考虑了新观察到的证据 b 之后,对 A 的分布的新信念[通常与我们先前的信念 P(A)不同]。

此外,我们可以将分数似然 / 证据表示为似然比

注意,我们可以认为先验似然函数都是固定的,即它们是在我们开始观察 b 的样本之前选择的假设。在这种情况下,证据后验是我们的假设+观察的结果。

下面两个例子对我了解这些概念是如何实现的非常重要。

示例 1 —疾病和测试

功劳:下面这个例子的灵感来源于 朱迪亚珍珠 的《何以见得》【2】**

假设我们想要估计患疾病 D 的概率,给定我们的测试 t 的结果。如果我们知道 10%的人口患有 D,我们可以将其纳入我们的先验(如果我们知道患者的详细信息,我们可以使用更好地代表她的人口子集):

  • P(D=1)=0.1
  • P(D=0)=0.9

注意,D 只能取两个值(0 或 1——健康或生病),但是在其他问题中,我们的变量可以接受更多的离散值,甚至是连续值。

从历史数据中,我们还知道测试的可靠性——我们知道当患者患有糖尿病时测试失败的可能性,以及当患者没有糖尿病时。这将构成我们的可能性函数:****

  • p(T = 1 | D = 1)= 0.75;P(T=0|D=1)=0.25
  • p(T = 1 | D = 0)= 0.2;P(T=0|D=0)=0.8

这样,对于 d 的每个值,我们在 T 上有一个条件分布。

正如您所看到的,我们假设已知疾病的真实情况,知道测试正确的概率— P(T|D),但是我们感兴趣的是相反的情况[已知测试结果,患疾病的概率— P(D|T)]。这说明了能够反转条件概率的重要性,贝叶斯法则允许:

疾病/测试示例中的贝叶斯规则

假设我们做了一个测试,给出了一个肯定的结果 T=1。我们现在希望计算后验概率,即给定新信息后我们患病的更新概率。我们可以先计算一下证据:

  • P(T = 1)= P(T = 1 | D = 1) P(D = 1)+P(T = 1 | D = 0) P(D = 0)= 0.75 * 0.1+0.2 * 0.9 = 0.255**

为了输出 D 上的更新分布,现在让我们计算 D 可以假设的每个值:

  • P(D = 1 | T = 1)= P(T = 1 | D = 1) P(D = 1)/P(T = 1)= 0.75 * 0.1/0.255 = 0.29*
  • P(D = 0 | T = 1)= P(T = 1 | D = 0) P(D = 0)/P(T = 1)= 0.2 * 0.9/0.255 = 0.71*

自然,第二步在这里是多余的,但是在其他设置中,D 可以取 2 个以上的值。我们更新的分布表明,在得到阳性测试后,P(D=1)从 10%增加到 29%。如果我们要进行第二次测试,我们可以使用这个新的分布作为输入,而不是原来的先验 P(D)。如果新的测试再次为正(T=1),我们可以重复这个计算,进一步将 P(D=1)增加到 60%:

  • P(T=1)=0.750.29+0.20.71=0.36
  • P(D = 1 | T = 1)= P(T = 1 | D = 1) P(D = 1)/P(T = 1)= 0.75 * 0.29/0.36 = 0.6*

现在观察前面提到的似然比 ( 似然 / 证据)的含义也很有意思。这是我们之前的信念会增加或减少的比例。

希望这有助于理解更新信念时贝叶斯规则的机制。然而,对我来说,当谈论一个模型的参数时(例如克里斯托弗·西姆斯(Christopher Sims)对经济建模的研究,或许多机器学习应用),理解会发生什么似乎还不够。

示例 2 —二项式建模

转到一个更抽象的领域,贝叶斯规则可以用来估计模型参数的分布。例如,克里斯托弗·西姆斯(Christopher Sims)利用贝叶斯法则建立了一个政府和政策会发生变化的经济模型。在这种情况下,如果我们用一个分布来描述一个模型参数,我们可以比使用一个单一的值更精确地解释这种变化。

鸣谢:下面这个例子部分灵感来自于Antonio salmerón 的概率讲座。艾暑期学校 ( 幻灯片 视频 )

我们有一个二项式分布,代表 20 个二元实验的结果,每个实验都有成功的概率 p (比如说,20 次有偏硬币的投掷)。正如你可能猜到的,我们感兴趣的是从观测值 x 中估计参数 p (用 p 表示硬币有多偏向)。在这种情况下,我们考虑对 x 的一次观察,它告诉我们 20 次独立实验中有多少次观察成功——我们从掷硬币中得到了多少次反面。

x 的一次观察可以有 0 到 20 次成功之间的任何值。使用二项式分布的定义,我们可以构建 21 个不同的似然函数 P( x | p ),每个函数对应一个 x: 的值

给定 x=2,4,10 或 15,参数 p 的似然函数。用 2020 Wolfram Mathematica 生成

每条曲线的面积总和不需要等于 1,就像前面的例子 P(T = 1 | D = 1)+P(T = 1 | D = 0)= 0.75+0.2≠1 一样。这些曲线不是概率分布,因为对于 P( x |p),我们固定 x 并改变 p 。如果我们固定 p (例如 p =0.3)而改变 x ,那么这些值的总和必须为 1:

变量 x 的概率函数,给定 p=0.3。你可以在这个链接中更改剧情。2020 Wolfram Alpha LLC

为了提供额外的直觉,让我们把函数 P( x | p )看作有两个输入参数: xp 。如果我们允许两者同时变化,它看起来是这样的:

P(x|p)对于 x 和 P 的所有值。在橙色中,我们看到 P(x|p)与平面 p=0.3 的交点。用 2020 Wolfram Mathematica 生成

如果我们将 x 固定为一个观察值,我们就有了一个似然函数(我们沿着 x 轴对这个 3D 图进行切片,获得 1 条蓝色曲线),如果我们固定 p 我们就有了一个概率分布(我们沿着 p 轴对其进行切片,获得一条类似橙色的曲线)。在我们观察到 x 之后,我们固定该值,并获得相应的似然函数,以便与贝叶斯规则一起使用。

好了,在观察了 x 之后,我们几乎拥有了更新我们对 p 值的信念所需的一切!继续之前,请注意以下几点:

  • 使用频率方法,我们现在可以通过简单地选择最大化被观察的 x 的似然函数的 p 来获得 p 的一个点估计。
  • 这个例子可能比前一个更复杂。原因是我们的未观察变量从离散的(疾病=健康或患病)变成了连续的(p =到 1 之间的任何值)。出于这个原因,我们不能像我们在前面的例子中所做的那样[对于 D 的每个值,P(T =正| D)]枚举出 PP的每个可能值的可能性。我们可以得到 p 的任何特定值的可能性,但不能列出它们,因为在 0 和 1 之间有无限可能的值!
  • 在完成一个推断步骤后,我们也无法枚举所有 p 的后验概率,原因相同【以前 P(D | T =正)表示 D =健康,D =患病,但现在 p 在后验 P( p | x )中取很多值】。
  • 我们观察到的变量仍然是离散的,但它从两个可能的值(测试结果 T = 0 或 1)增加到 21 个(观察到的成功数 x = 0,1,2,…,20)。这也使得观想有点困难。在其他设置中, x 甚至可以是连续的。
  • 关于可能性这个词的一个随机事实是:拉丁语使用一个更加精确的术语——葡萄牙语中的verosimilhana。它的唯一含义是“某物与真理多么相似”。在每一种语言中,所选择的术语都避免使用概率,因为其值的总和可能不是 1。

最后,如果我们假设对于 p 在 0–1 之间的均匀先验,在观察到新的样本 x 后,我们就拥有了更新我们对 p 的信念所需的一切。

贝叶斯法则的组成部分,当对系统的参数θ建模时给定观测值 x [ 安东尼奥·萨尔梅龙

在这种特殊情况下(二项式似然均匀先验)后验很容易计算,从而得到快速准确的结果。然而,如果我们假设其他种类的似然函数先验,我们可能需要借助其他技术来计算我们的后验,例如变分推断。****

关于这个例子的一些最后说明:

  • 如果我们只想从贝叶斯规则中获得点估计,我们可以忽略分母的计算(证据)而不改变结果——我们可以简单地最大化分子。这叫做最大后验概率(MAP)** 。**
  • 除了忽略分母,我们在寻找点估计时也可以忽略前面的。这可以改变结果(与 MAP 相比),并且对应于频率主义方法— 最大似然估计(MLE)

在这篇文章中,我试图激发贝叶斯推理的使用,并阐明它的基本思想。对我来说,最令人困惑的部分是理解什么是必须先验提供的。除了在之前的之外,必须事先提供似然函数,但是这可能意味着非常不同的事情,比较起来很有趣:****

  • 在疾病/测试示例中,当评估各种患者(患病/健康)时,我们使用测试失败的固定概率作为可能性函数。这个概率以前是已知的(可能来自历史数据)。
  • 在二项式示例中,先前的知识相当于假设可能性表现为 20 个独立实验的二项式。21 个可能的似然函数中的每一个(类似于 2 种病人)都可以基于这一假设导出。

[1] D. Woodard,G. Nogin,P. Koch,D. Racz,M. Goldszmidt 和 E. Horvitz,使用移动电话 GPS 数据预测旅行时间可靠性(2017),运输研究 C 部分:新兴技术

[2] J. Pearl 和 D. Mackenzie,《为什么之书》(2018),基础图书公司。

贝叶斯逻辑回归简介

原文:https://towardsdatascience.com/introduction-to-bayesian-logistic-regression-7e39a0bae691?source=collection_archive---------5-----------------------

使用 Python 和 PyJAGS 进行贝叶斯分类方法的实践演示。

本文介绍了开始贝叶斯数据分析所需的一切。我们提供了如何使用 Python 使贝叶斯逻辑模型适合数据的分步指南。你将能够在不涉及数学的情况下理解贝叶斯分类的基本原理。

信用:苏菲·玛德琳

让我们通过一个简单的分类模型来回顾贝叶斯统计分析的基本概念。

数据

数据来自 1988 年孟加拉国生育调查,其中 1934 项观察来自城市和农村地区的妇女。该数据集的作者 Mn 和 Cleland 旨在确定生育率的趋势和原因,以及生育率和儿童死亡率的差异。

我们将使用这些数据来训练一个贝叶斯逻辑回归模型,该模型可以预测给定妇女是否使用避孕措施。

该数据集非常适合贝叶斯逻辑回归,因为在分析生育率时能够量化不确定性是决定人口规模、结构和组成的人口动态的主要组成部分(来源 1来源 2 )。

原始数据的副本可以在这里找到。每个妇女有四个属性,还有一个标签表明她是否使用避孕药。这些属性包括:

  • :女方所在区的识别码,
  • 城市:居住区域类型,
  • 存活子女:存活子女数,
  • 年龄平均值:女性的年龄(以年为单位,以平均值为中心)。

这些妇女被分成 60 个区。

需要一点预处理。我们将地区号码 61 映射到号码 54,这样地区就有序了,如下图所示。

逻辑回归

预测一个给定的妇女是否使用避孕药具是二元分类问题的一个例子。如果我们用 X 表示妇女的属性,用 Y 表示结果,那么使用避孕药具的可能性,P(Y=1) ,将遵循下面的逻辑函数。

来源:P. Protopapas,哈佛大学

结果取决于两个参数 β0 (截距)和 β1 (斜率)。截距使曲线向左或向右移动,而斜率控制 S 形曲线的陡度。如果𝛽 1 为正,则预测的𝑃 (Y=1) 从𝑋的小值的零变为𝑋的大值的一,并且如果𝛽 1 为负,则具有 𝑃(Y=1) 相反关联。

例如,如果𝛽 1 对于年龄预测值为阳性,这意味着老年妇女比年轻妇女更有可能使用避孕药具。年龄开始增加避孕药使用率的临界值将由 β0 决定。小数值的 β0 表示避孕措施在人群中广泛使用。

理解逻辑函数对于推动贝叶斯方法非常重要。你可以在下面的文章中了解更多关于经典逻辑回归的知识。

[## 深度学习为什么有效:解决一个农民的问题

在开始是神经元:梯度下降,反向传播,回归,自动编码器,细胞神经网络…

towardsdatascience.com](/why-deep-learning-works-289f17cab01a)

贝叶斯方法

通过将我们的数据拟合到逻辑方程,我们将能够估计出 β0𝛽1.的固定值然而,我们不知道我们对这些估计有多少信心。

此外,在现实生活中,𝛽0 通常会因地区而异。β0 在一些地区可能很小,但在另一些地区却很大。经典的逻辑回归模型仍将为所有区域提供单一值,这可能导致错误的结论。

在我们过去的一篇文章中,我们强调了机器学习中的不确定性问题,并介绍了贝叶斯方法的基本特征。我们温和地解释了概率在基于统计数据分析的推理中量化不确定性的明确使用。

[## 贝叶斯噩梦。解决了!

通过 Python PyMC3 中的示例和代码对贝叶斯数据分析进行了温和的介绍。

towardsdatascience.com](/bayesian-nightmare-how-to-start-loving-bayes-1622741fa960)

按照贝叶斯理论,理想情况下,我们希望在构建预测避孕药使用的模型时考虑先验信息。如果我们只使用逻辑方程,就没有直接的方法来包含我们对正在估计的那些参数的先验信念。

贝叶斯方法允许我们基于我们现实生活中的领域知识和常识,对截距和斜率做出事先的良好猜测。例如,我们可以说,根据经验,截距是从均值 μ =2、标准差 σ =1 的正态分布中得出的。我们还可以假设预测值城市生活子女年龄平均值的斜率分别为 4、-3 和-2。这个先前的信念总结如下。

给定上述描述我们先前信念的分布,我们可以使用所谓的生成模型生成模拟数据,如下图所示。

在这种情况下,生成模型是具有参数 p 的伯努利分布,这是妇女使用避孕药具的概率。 p 是上一节介绍的逻辑函数。

为了更好地理解生成模型的概念,让我们模拟二进制响应数据 Y 。我们通过使用先前的参数值和数据来做到这一点。

避孕药具的使用因地区而异吗?

为了对贝叶斯方法进行更多的实验,我们现在将指定一个变截距逻辑回归模型,其中截距因地区而异,我们将使其适合模拟避孕数据。

我们在 β0、β1、𝛽2𝛽3、上设置了信息性先验分布,这与我们用来生成模拟避孕数据的先验分布明显不同。我们的目标是估计用于模拟响应变量 Y 的真实参数值。

当我们有数据、先验和生成模型时,我们可以根据预测值(地区、城市、居住儿童、年龄平均值)和响应( Y )应用贝叶斯定理计算模型参数的后验概率分布

马尔可夫链蒙特卡罗 ( MCMC )是一类流行的算法,用于寻找模型参数的后验分布。由于有了库 PyJAGS ,用 Python 运行这样的算法变得非常简单。该过程从定义分布和先验开始,PyJAGS 从这些分布和先验开始执行采样,使用马尔可夫链将该过程导向我们手头的模拟数据。您可以在下面的代码中看到 MCMC 是如何工作的。

一个好的做法是绘制 MCMC 采样器的参数轨迹图。上面的轨迹图表明采样器确实收敛了。3 个马尔可夫链的平均值看起来大致相同。虽然链内有一点徘徊,但没有发散链的迹象。

现在,我们可以绘制参数的后验分布直方图。作为示例,我们仅显示了 β0 和第 10 区的曲线图。

我们记得用于生成模拟数据的 β0 的真实分布如下。

正如你在上面的图中看到的,10 区的真实 β0 参数包含在我们模型的后验分布中。事实上,这也是所有剩余参数的情况,这里没有显示。这一发现表明贝叶斯方法工作良好,我们现在可以继续将变截距模型拟合到实际的训练数据。

哪个区的女性最有可能使用避孕药具?

下面,我们再次运行 MCMC 采样器,这次使用训练数据。我们通过检查轨迹图来检查收敛性,就像我们对模拟数据所做的那样。看来采样器也聚集在这里。没有一条链看起来是发散的,因为它们看起来不相关,是独立随机抽样的。

现在可以为所有区域绘制模型参数 β0 的后验分布,如下所示。

我们知道, 𝛽0 的正值与相应地区的妇女最有可能使用避孕药具的概率增加有关。看上面的图,只有几个区的𝛽0 值为正。

负值与属于相应地区的妇女最有可能使用避孕药具的概率降低有关。大多数地区都属于这一类。

后验分布允许我们计算每个地区的 𝛽0 值的平均值和标准偏差,如上图所示。基于这些结果,我们可以得出结论,𝛽0 后验概率在各地区之间并不是均匀分布的。这一证据支持变截距模型,并导致以下发现:

属于第 16 区的妇女最有可能使用避孕药具。
属于第 11 区的妇女最有可能不使用避孕药具。

结论

贝叶斯逻辑回归的好处是,它给我们一个后验分布,而不是像经典的单点估计,也称为频率方法。

当结合先前的信念时,我们能够量化每个地区避孕药具使用点估计的不确定性。在本文中,我们还提供了一些关于 PyJAGS 的信息,PyJAGS 是一个用于贝叶斯推理的易于使用的 Python 库。

这一领域为未来的工作打开了一扇大门,特别是因为贝叶斯统计分析是从医疗诊断到选举预测等几项技术的核心。由内特·西尔弗于 2012 年出版的《信号与噪音》是将概率和统计应用于现实世界的艺术杰作。

最佳并行绘图 Python 库介绍:“HiPlot”

原文:https://towardsdatascience.com/introduction-to-best-parallel-plot-python-library-hiplot-8387f5786d97?source=collection_archive---------30-----------------------

作为 EDA 的首选工具,我们都应该重视的四个关键特征。

HiPlot 是脸书的 Python 库,支持高维数据表的可视化,于今年一月发布。它以复杂的互动平行剧情而闻名。

在此之前,先看看他们引人注目的演示视频。这解释了它的交互性有多高,这是我们做 EDA 时会很欣赏的。

快照来自他们的视频(https://ai . Facebook . com/blog/hip lot-高维-互动-情节-制作-简易#u_0_1v )。我们可以通过选择轴上的范围来限制数据子集中的图形。

,并在这里 用样本数据 玩转他们的演示 app。不要忘记选择轴上的范围,按住并移动以检查交互性。

HiPlot 不仅好看,而且有以下四个值得欣赏的特点:

  • 非常容易实现

使用他们的 hiplot 模块实现并行绘图实际上只需要一行代码,而且几乎不需要动脑筋。

  • 高度互动

从上面的演示视频可以看出,剧情互动性很强。点击几下鼠标,你就可以深入到数据的任何子集。

  • 跑得快

尽管看起来如此,但将大型数据集可视化为并行图的运行时间很短。让我们过会儿看这个。

  • 原生 HTML 渲染功能

他们准备了一个原生函数,把并行的情节变成 HTML 代码(万岁!!)制作的 HTML 页面可以下载为。html 文件或从 Flask 部署,几乎不需要额外的渲染工作。在下面的练习中,我试图通过 Flask 在 heroku 上运行它。

得益于这些优势,我相信 HiPlot 是数据分析项目中 EDA 的首选工具集之一,然后才是其他耗时的可视化工具。

让我们一个接一个地看看每一个好处。

虹膜数据入门

让我们看看使用著名的虹膜数据集让你开始使用 HiPlot 有多容易。

虹膜数据中的样本记录(【https://archive.ics.uci.edu/ml/datasets/iris】T4)

HiPlot 的安装和普通模块一样简单。只需使用 pip:

pip install -U hiplot

要使用外部 csv 文件,你甚至不必使用熊猫数据帧。他们准备了一个本地方法,直接从 csv 文件运行并行绘图Experiment.from_csv()。当需要使用 DataFrame 时,用Experiment.from_dataframe()代替。而且用 Jupyter 笔记本完全没问题。

import hiplot as hip
iris_hiplot = hip.Experiment.from_csv('iris.csv')
iris_hiplot.display()

这里是你将会看到的:

虹膜数据 HiPlot

HiPlot 是高度交互性的

一旦你开始玩,你会爱上 HiPlot 的。

正如你已经在上面的演示影片中看到的,这里有一些使用交互式图表的例子。

灰色矩形是我在每个变量中选择范围的地方。我们也可以通过按住并移动来移动范围。

用鼠标指向感兴趣的记录会立即在图表中突出显示该记录。

HiPlot 跑得快

为了测试运行时间以显示更大数据的并行图,我使用了 Kaggle FIFA 19 完整玩家数据集。这是一个来自视频游戏“FIFA 19”的数据集,顾名思义,这是一个足球游戏(或者你可以称之为 football),在这个游戏中,你可以作为一个真实的足球队的球队经理或者一个真实的足球运动员来玩。数据集包含了所有可玩角色的技能等级列表(例如,他们擅长头球、任意球等等。)行数为 18,207,列数为 89。第一排是来自阿根廷的梅西。

为了进行性能测试,我有意将数据大小增大 10 倍。我将 FAFA 19 数据集连接了 10 次,最终得到了 182,070 行。通常,可视化大型数据集需要时间来运行,并在图表显示后导致巨大的延迟。互动性?忘记并重新运行脚本!HiPlot 呢?

我在 182,070 行 x 89 列的数据集上运行 HiPlot,没有进行任何编辑。处理时间为 81 秒,显示图表需要额外的 5 分钟。我认为就它的大小来说,它够短了。

fifa = pd.read_csv('fifa19_data.csv',index_col='Unnamed: 0')
fifa_extended = pd.concat([fifa,fifa,fifa,fifa,fifa,fifa,fifa,fifa,fifa,fifa],axis=0,ignore_index=True,sort=False)
fifa_hiplot = hip.Experiment.from_dataframe(fifa_extended)
fifa_hiplot.display()

顺便说一下,这看起来有多乱…

HiPlot 更棒的一点是,数据大小不会对它的交互性造成太大损害。选择轴上的范围后,它试图只显示属于该范围的图。这一变化几乎在一秒钟内重新渲染了图形,与其他可视化工具相比,这是惊人的快。

测试选择范围。

本机 HTML 呈现功能

当我们想和其他人分享这个图时,我们可以在 notebook 上运行代码,然后复制并粘贴这个图,但是这样做去掉了图形的交互性。

HiPlot 有自己的原生 HTML 渲染函数Experience.to_html(),它返回 HTML 文件,其中只嵌入了一行代码。

为了简单起见,让我使用 FIFA 19 数据集中的原始行和较少的列。

fifa = pd.read_csv('fifa19_data.csv',index_col='Unnamed: 0')
fifa_small = fifa[['Age','Nationality','Value','Height', 'Weight', 'Crossing', 'Finishing', 'HeadingAccuracy', 'ShortPassing', 'Volleys', 'Dribbling', 'Curve', 'FKAccuracy', 'LongPassing', 'BallControl', 'Acceleration']]
fifa_hiplot = hip.Experiment.from_dataframe(fifa_small)
fifa_hiplot.display()

这段代码将生成一个新的。html 文件在您的本地与绘图。

_ = fifa_hiplot.to_html("fifa_hiplot.html")

现在您可以共享。html 文件直接与您的团队成员,让他们发挥周围的情节。

呈现为“fifa_hiplot.html

由于Experience.to_html()返回 html 代码,它甚至可以轻松地连接到 web 服务器并在外部部署绘图。

让我用弗拉斯克和赫罗库试试。正如我在这里解释了很多一样,我需要将四个文件推送到 GitHub 库,以便与 Heroku 应用程序同步。

  • fifa19_data.csv : FIFA19 数据集文件。
  • hiplot_fifa.py :运行和启动 Flask app 的 Python 代码。
import hiplot as hip
import pandas as pd
from flask import Flaskapp = Flask(__name__)[@app](http://twitter.com/app).route('/')
def fifa_experiment():
    fifa = pd.read_csv('fifa19_data.csv',index_col='Unnamed: 0')
    fifa_hiplot = hip.Experiment.from_dataframe(fifa[['Age','Nationality','Value','Height', 'Weight', 'Crossing','Finishing', 'HeadingAccuracy', 'ShortPassing', 'Volleys', 'Dribbling', 'Curve', 'FKAccuracy', 'LongPassing', 'BallControl', 'Acceleration']])

    return fifa_hiplot.to_html()if __name__ == "__main__":
    app.run()
  • requirements . txt:Heroku 安装必要模块的需求文件。
gunicorn==19.9.0
pandas==0.24.2
hiplot==0.1.12
Flask==1.1.1
  • proc file:Heroku 启动 app 时运行的启动命令。
web: gunicorn hiplot_fifa:app

同步代码文件并在 Heroku 上进行设置。打开 web 应用程序会显示以下 HiPlot 图表页面,可通过域名进行全球访问。

通过 Flask 部署 HiPlot 地块,由 Heroku 提供服务。

结尾注释

在这篇文章中,我介绍了 HiPlot(并行绘图的当前最佳选项)来启动 EDA,以了解变量交互概述。

它易于运行,交互性强,速度快,并且可以通过 HTML 文件或代码共享。

虽然数据科学项目肯定需要进一步的调查,如查看值的分布形状、输入缺失值等,但 HiPlot 将有助于开始数据预处理和理解。

Vaex 大数据简介—读取 12.5 亿行的简单代码

原文:https://towardsdatascience.com/introduction-to-big-data-a-simple-code-to-read-1-25-billion-rows-c02f3f166ec9?source=collection_archive---------39-----------------------

理解大数据

用 Python 高效读取和可视化 12.5 亿行星系模拟数据

如今,我们正在进入各种各样的时代。有人说,我们正处于颠覆时代。为了理解它,我们可以使用 Schwartz (1999)在他的书中的一个术语,数字达尔文主义。这个术语描述了我们正在进入一个时代,在这个时代,企业无法适应技术和科学的发展。数字平台和全球化改变了客户的范式,改变了他们的需求。

另一方面,有人说我们正在进入大数据时代。几乎所有学科都经历过数据激增。其中之一是天文学。全世界的天文学家意识到他们需要建造越来越大的望远镜或天文台来收集更多的数据。例如,在 2000 年初,一项名为 2 微米全天巡天( 2MASS )的全天巡天收集了大约 4.7 亿个天体。2016 年年中,天基望远镜 Gaia 发布了由约 17 亿个天体组成的第二次数据发布。天文学家是如何处理的?

在本文中,我们将讨论如何实际处理大数据。我们将使用来自盖亚宇宙模型快照的星系模拟数据( GUMS )。它有大约 35 亿个物体。你可以在这里访问它。例如,我们将只读取 12.5 亿行。

使用 Vaex 读取 10 亿行数据

首先,我必须感谢 Maarten Breddels 构建了 Vaex,一个读取和可视化大数据的 python 模块。它可以在一秒钟内读取 10 亿行。你可以在这里阅读文档

Vaex 将有效地读取 hdf5 和 arrow 格式的文件。这里,我们将使用一些 hdf5 文件。要在 Vaex 中读取文件,可以使用下面的代码

import vaex as vxdf = vx.open('filename.hdf5')

但是,如果您想同时读取一些 hdf5 文件,请使用以下代码

df = vx.open_many(['file1.hdf5', 'file2.hdf5'])

可以分析下图。

读取 12 亿行数据

变量文件是工作目录中所有 hdf5 文件的数组。你可以在 1 秒钟内查看阅读所有文件所需的时间。在下一行,我检查行的总数。是 12.5 亿行。

Vaex 中的算术运算和虚拟列

你也可以快速地对所有的行做一些算术运算。这是一个例子

Vaex ( 图像由 autho r)中的算术运算

Vaex 可以毫秒级进行算术运算,将其应用于所有行(12.5 亿)。如果要在 Vaex 数据框中分配一列,可以使用此代码

df['col_names'] = someoperations

这是一个例子

Vaex ( Image by autho r)中的算术运算

仔细看的话,代码和熊猫 API 差不多。Yups,据我所知,Vaex 和熊猫用的是同一个 API。您还可以像在 Pandas 中一样选择列,如下所示

df_selected = df[df.ag, df.age, df.distance]

回到上图,在第 14 行,添加了名为“new_col”的新列,这大约需要 2.07 毫秒。

1D 和 2D 宁滨

您是否需要将宁滨统计数据快速应用到您的大数据中?Vaex 也会是答案。要做一个 1D 宁滨并绘制它,您可以使用下面的代码

df.plot1d(x-axis, shape=(number_of_bin))

这是我们数据的例子

1D·宁滨与 Vaex ( 图片由 autho r 提供)

我们在 1D(直方图)中绘制列距离的面元数为 25。它会产生这样一个图形。Vaex 需要大约 2 秒钟来可视化 1D 图。

Vaex 中的 1D 图(直方图)

要应用 2D·宁滨并将其可视化,您可以使用以下代码

df.plot(x-axis, y-axis, shape(shape_x, shape_y))

以下是我们数据中要应用的示例

2D·宁滨和 Vaex

可视化一个 2D 图大约需要 4 分钟。这是非常可以接受的。你可以想象另一个模块在 2D 图的密度中可视化 12 亿行需要多长时间。它会给你一个这样的数字。

Vaex 中的 2D 密度图

结论

未来在这里,大数据时代已经到来。我们必须准备好所有需要的技术。准备工作之一是构建一个能够有效读取和可视化大数据的 Python 库。Vaex 将作为它的解决方案推出。它声称 Vaex 一秒钟可以读取 10 亿行。我希望你能学会这个故事中提到的例子,并详细阐述到你的数据中。

如果你喜欢这篇文章,这里有一些你可能喜欢的其他文章:

[## 使用 Matplotlib 实现 Python 数据可视化—第 1 部分

完成了从基础到高级的 Python 绘图的 Matplotlib 教程,包含 90 多个示例

towardsdatascience.com](/visualizations-with-matplotlib-part-1-c9651008b6b8) [## 使用 Matplotlib 可视化数据的 5 个强大技巧

如何使用 LaTeX 字体,创建缩放效果,发件箱图例,连续错误,以及调整框填充边距

towardsdatascience.com](/5-powerful-tricks-to-visualize-your-data-with-matplotlib-16bc33747e05) [## 用于科学绘图的 Matplotlib 样式

为您的科学数据可视化定制 Matplotlib

towardsdatascience.com](/matplotlib-styles-for-scientific-plotting-d023f74515b4) [## 在 Matplotlib 中创建色彩映射表

从颜色列表中创建和定制自己的色彩映射表的指南

towardsdatascience.com](/creating-colormaps-in-matplotlib-4d4de78a04b8) [## 在 Matplotlib 中自定义多个子情节

使用 subplot、add_subplot 和 GridSpec 在 Matplotlib 中创建复杂 subplot 的指南

towardsdatascience.com](/customizing-multiple-subplots-in-matplotlib-a3e1c2e099bc)

仅此而已。感谢您阅读这个故事。喜欢就评论分享。我还建议您关注我的帐户,以便在我发布新故事时收到通知。

参考文献:

[1]施瓦茨,E. I .,数字达尔文主义 (1999),百老汇图书公司

[2]张,赵,【大数据时代的天文学】 (2015),数据科学杂志

[3] Skrutskie,M. F .等人,两微米全天巡天(2MASS) (2006 年),《天文杂志》,131:1163–1183

[4]盖亚合作组织(Gaia Collaboration),T. Prusti 等人,盖亚任务 (2016)天文学和天体物理学 595,A1

[5] Robin,A. C .等人,盖亚宇宙模型快照 (2012)天文学和天体物理学 543,A100

机器学习中的因果关系介绍

原文:https://towardsdatascience.com/introduction-to-causality-in-machine-learning-4cee9467f06f?source=collection_archive---------1-----------------------

为什么我们需要机器学习中的因果关系(从商业角度)

马丁·亚当斯在 Unsplash 上的照片

尽管围绕人工智能进行了大肆宣传,但大多数基于机器学习(ML)的项目都专注于预测结果,而不是理解因果关系。事实上,在几个人工智能项目之后,我意识到 ML 非常擅长在数据中寻找相关性,但不是因果关系。在我们的项目中,我们尽量不陷入将相关性等同于因果关系的陷阱。

这个问题极大地限制了我们依靠 ML 进行决策的能力。从商业角度来看,我们需要能够理解数据之间因果关系的工具,并创建能够很好概括的 ML 解决方案。

在这篇文章中,我将介绍作为一家已经使用机器学习算法的公司,我们目前面临的问题,以及为什么从商业角度来看因果关系很重要。

机器学习的问题

基于机器学习的解决方案存在不同的问题。如您所知,ML 算法在当前状态下可能会有偏差,相对缺乏可解释性,并且在针对多种应用的训练数据集中归纳模式的能力方面受到限制。提高概括能力变得很重要。

泛化:模型适当适应新的、以前未见过的数据的能力,这些数据来自与用于创建模型的分布相同的分布。( 1 )

此外,当前的机器学习方法倾向于过度拟合数据。事实上,他们试图完美地学习过去,而不是揭示真实的/因果关系,这种关系将随着时间的推移继续存在。

在我所在的行业(医疗保健),我们的模型只是支持在疾病出现时出现症状,而疾病在症状出现时出现。

截至今天,更成功的人工智能系统是深度学习模型,利用更大的数据集和更多不同可能情况的例子。简单地依赖更多数据(大数据)可能很诱人,但这将是一个错误。

即使我们能观察到相关性,也不能证明因果关系。

朱迪亚·珀尔和达纳·麦肯齐的 原因之书。新的因果科学 凸显了当前机器学习解决方案的主要局限性和因果推理挑战。他们指出,大数据将解决我们面临的许多重大挑战的宣传是错误的。

因为深度学习(DL)过于关注没有因果关系的相关性,当问题离开非常狭窄的情况时,数据不会回答问题。实际上,许多真实世界的数据并不是以与我们用来训练人工智能模型的数据相同的方式产生的。换句话说,深度学习擅长发现数据方面的模式,但无法解释它们是如何联系在一起的。

大多数解决方案都无法超越数据集中的示例领域。

对于越来越多的商业应用,ML 发现相关性的能力已经足够了(例如:价格预测、对象分类、更好的定位等。).事实上,ML 系统擅长学习输入数据和输出预测之间的联系,但缺乏对因果关系或环境变化的推理。能够捕捉因果关系的 ML 模型将更具普遍性。

因果关系:一个事件、过程或状态(原因)促成另一个事件、过程或状态(结果)产生的影响,其中原因对结果负有部分责任,结果部分取决于原因。( 2

揭示复杂系统中不同现象的原因和影响的能力将有助于我们在医疗保健、司法和农业等不同领域建立更好的解决方案。事实上,当相关性被误认为因果关系时,这些领域不应承担风险。

因果推理和用例

首先,更好地定义这个术语是关键。作为人类,我们经常根据因果来思考——如果我们理解了事情发生的原因,我们就可以改变我们的行为来改善未来的结果。

换句话说,我们的目标是试图从数据中学习因果关系(什么是原因,什么是结果)。如前所述,在许多用例中,相关性已经足够了。然而,因果推理将使我们能够更进一步,并弄清楚如果我们决定改变我们模型中的一些基本假设会发生什么。

理解因果关系将使现有的人工智能系统更加智能和高效。例如,“想象一下,一个机器人知道掉落的东西会导致它们破碎,就不需要把几十个花瓶扔在地上,看看它们会发生什么事情了”。

此外,理解因果关系的能力将有助于我们创建商业模式以及专门帮助公司更好地理解其数据的新创业公司。例如,我们最近开始了一个项目,试图使用不同的来源来识别线索。我们相信因果关系会帮助我们根据我们从未想过的因素识别新的线索。

因果关系的层次/基于朱迪亚·珀尔的工作

从业务角度来看,我们正在考虑以下问题/场景:

#1: 在电子商务环境中,我们可以确定哪个特定因素对购买产品的决定影响最大。有了这些信息,我们可以更好地分配资源来改进特定的 KPI。我们还可以对不同因素对购买决策的影响进行排序。我们可以确定,如果给定的客户在过去两年中没有购买其他产品,他/她是否会购买特定的产品。

#2: 从更广泛的意义上来说,我们可以发现给定的商业策略如何避免负面影响,以及避免了哪些负面影响?我们还可以通过对我们的业务开发人员实施特定的培训计划来确定我们的销售额应该增长多少。特定培训计划的影响

在农业领域,我们经常试图预测今年农民的作物产量是否会降低。然而,使用偶然的推论,它将变得更好地理解我们应该采取什么步骤来增加收获。

在这些潜在的用例之外,机器学习中更多因果关系的发展是建立更像人类的机器智能(可能是人工通用智能)的必要步骤。

当前和未来的解决方案

迄今为止,确实存在一些解决方案。然而,当前的解决方案(例如:蒙特卡罗模拟、马尔可夫链分析、朴素贝叶斯、随机建模和一些开源包,如 DAGitty )在业务应用方面并没有达到我们的预期。

元学习因果结构 2019 年,Yoshua Bengio 和他的团队发布了一篇研究论文概述了一种方法。事实上,他们似乎正在研究一种能够识别简单因果关系的深度学习版本。他们使用了一个数据集,该数据集根据概率绘制了现实世界现象之间的因果关系,如吸烟和肺癌。他们还生成了因果关系的合成数据集。

换句话说,“产生的算法本质上形成了一个关于哪些变量有因果关系的假设,然后测试不同变量的变化如何符合理论”。( 4 )

结构方程建模 另一种值得一提的方法叫做结构方程建模。在不涉及太多细节的情况下,“Judea Pearl 建立的基础数学和图形模型的快速发展有助于因果关系工具的使用”( 5 )。

因果贝叶斯网络 这种方法估计一个数据集中所有变量之间的关系,可以认为是一种真正的发现方法。它能够同时发现多种因果关系。

基本上,它会产生一个直观的可视化地图,显示哪些变量相互影响,以及它们的影响程度。事实上,因果图模型使得同时模拟许多可能的干预成为可能。

因果贝叶斯网络需要大量数据来捕捉所有可能的变量。

要记住的另一个重要因素是,因果人工智能不是在黑盒中运行的。研究人员可以检查模型的推理,减少偏差的风险。

来源

从业务的角度来看,这种方法允许结合专家知识来应对纯数据驱动方法的可能限制。商业专家可以帮忙:

  • 对模型设置条件以提高其准确性,
  • 确定哪些变量应该进入模型
  • 帮助理解违反直觉的结果。

强化学习与因果关系

最后,我想提一下强化学习(RL)。如你所知,强化学习是一种利用与环境的互动进行渐进式学习的方法。

人工智能社区中的一些领军人物认为,RL 本质上是因果的,从这个意义上说,代理人用不同的动作进行实验,并通过试错来了解它们如何影响性能。这种类型的学习被称为“无模型”,因为它可以学习有效的行为,而不必学习世界如何工作的显式模型。

强化学习中,无模型算法是一种不使用与马尔可夫决策过程相关的转移概率分布(和奖励函数)的算法,在 RL 中,它代表要解决的问题。( 6 )

然而,它只是学习行动和表现之间的因果关系,而不是行动如何直接影响世界。例如,这可能包括学习翻转火上的满水桶来灭火,而不理解水和火之间的关系。

正如乔治·劳顿所提到的,“如果给代理一根软管而不是一桶水,它不从头学习就不知道该拿它怎么办,因为它没有学习到水和火之间的因果关系”。我认为 RL 更多的是测试一种信念,以在搜索空间中找到某个最佳点。

要了解更多信息,我推荐以下链接:

计算机视觉模型训练导论

原文:https://towardsdatascience.com/introduction-to-computer-vision-model-training-c8d22a9af22b?source=collection_archive---------25-----------------------

训练一个计算机视觉模型是一项复杂且反复进行的任务的一部分,这项任务通常看起来令人望而生畏。在 alwaysAI,我们希望让流程变得简单易懂。为了让你开始,我们汇编了一个用于计算机视觉应用的深度神经网络(DNNs)训练过程的概述。在本概述中,我们将重点关注监督学习,它使用带标签的训练数据来教导模型期望的输出是什么。本文介绍了模型训练过程的每一个组成部分,并将成为以后更深入的文章的上下文基础。

模特培训周期。

概观

本文涵盖了以下几个部分:

  • 模型的类型
  • 数据集生成
  • 数据集标注
  • 模特培训
  • 测试和使用

模型的类型

不同的计算机视觉模型帮助我们回答关于图像的问题。图像中有哪些对象?图像中的那些物体在哪里?物体上的关键点在哪里?每个对象属于哪些像素?我们可以通过构建不同类型的 dnn 来回答这些问题。然后,这些 dnn 可以用于解决一些问题,如确定图像中有多少辆汽车,一个人是坐着还是站着,或者照片中的动物是猫还是狗。我们在下面概述了一些最常见的计算机视觉模型及其用例。

注意:通常,计算机视觉模型输出由标签和置信度或分数组成,置信度或分数是对正确标记对象的可能性的一些估计。这个定义是有意模糊的,因为对于不同类型的模型,“信心”意味着非常不同的东西。

在描述不同类型的模型和它们的用例时,我们将概述一个虚拟衣柜的示例用例:一个让用户在购买之前虚拟试穿不同衣服的应用程序。

图像分类

图像分类试图识别图像中最重要的对象类别;在计算机视觉中,我们将每个类称为一个标签。例如,我们可以使用一个通用的分类模型,如' alwaysai/googlenet 【T3 ' ',来识别服装项目,如'跑鞋'或'运动衫',如下所示。该模型将图像作为输入,并且它将输出标签以及与其他标签相比该模型对于特定标签的置信度。此外,用于图像分类任务的 dnn 不提供图像中对象的位置,因此对于我们需要该信息的用例,例如为了跟踪或计数对象,我们需要使用对象检测模型,这是下一个描述的模型。

用于对服装项目进行分类的通用分类模型示例,包括跑鞋。

用于对毛衣分类的服装项目进行分类的通用分类模型示例。

目标检测

当目标的位置很重要时,通常使用目标检测n dnn。这些网络返回一组坐标,称为边界框,指定包含对象的输入图像区域,以及该边界框和标签的置信度值。对于我们的“虚拟衣柜”应用程序,我们需要一个想要试穿虚拟衣服的人的输入图像,然后我们需要找到图像中的人。为此,我们可以使用一个对象检测模型进行人物检测,如“ alwaysai/mobilenet_ssd ”,它将返回一个包围图像中每个人物的边界框,以及一个标签“人物”和一个输出的置信度值。可以区分人的对象检测模型的示例如下所示。

注意:知道物体在一帧中的位置可以让我们推断出图像的某些信息。例如,我们可以计算高速公路上有多少辆车来绘制交通模式。我们还可以通过将 分类模型搭载到 对象检测模型上来扩展应用程序的功能。例如,我们可以将图像中与检测模型中的边界框相对应的部分输入到分类模型中,这样我们就可以计算图像中有多少辆卡车和轿车。

两种检测模型的输出示例。在这种情况下,我们可以看到两个模型都可以检测到人,但一个模型能够检测到两种类型的水瓶,而另一个模型只发现了一个。

现在,我们已经看到了如何将衣服分类,例如鞋子或运动衫,我们可以检测图像中的人,但我们仍然需要能够让用户试穿衣服。这需要能够区分属于检测对象的像素和图像其余部分的像素,在这种情况下,我们需要使用分割,这将在接下来讨论。

图象分割法

如上所述,在一些任务中,理解物体的精确形状是很重要的。这需要为每个对象生成像素级边界,这是通过图像分割实现的。用于图像分割的 DNNs 通过对象类型(在语义分割的情况下)或单个对象(在实例分割的情况下)对图像中的每个像素进行分类。

注:目前 alwaysAI 平台支持语义切分。我们一直在寻求平台的增长,并在增加新的模型,包括执行实例分段的模型。

对于我们的虚拟衣柜应用程序,我们可以使用语义分割来区分属于人、毛衣或鞋子的像素。然后,我们可以用一个对象中的像素替换另一个对象中的像素,比如用用户想要试穿的新毛衣中的像素替换原始图像中的人穿着的毛衣。

注意:语义分割的一个流行用例是用于远程会议软件(如 Zoom 或微软团队)的 虚拟背景 :属于一个人的像素与图像的其余部分区分开来,并从背景中分割出来。

在我们的人的图像分割应用的例子中,我们看到图像分割使我们能够区分哪些像素属于图像中的每个对象。然而,图像分割并不能让我们推断出图像中物体的相对位置,例如人的手在哪里,或者汽车的尾灯和保险杠在哪里。为此,我们需要关于一个人特定区域的信息,比如说一个人的手和他们的头相比在哪里。这需要跟踪目标地标,这是我们将在这里讨论的最后一种模型类型。

目标标志检测

物体标志检测是对图像中捕捉物体重要特征的某些“关键点”的标记。对于我们的虚拟衣柜,我们可以使用一个姿势估计模型,如'alwaysai/human-pose【T1]',它可以识别身体的关键点,如臀部、肩膀和肘部,类似于下图所示,以帮助我们的用户进行装饰。我们可以使用眼睛关键点给虚拟衣柜中的人戴上眼镜或帽子,或者使用“脖子”关键点让他们试穿围巾。

注意:使用关键点的另一个有用的应用程序是在练习和运动中检查正确的形式。

使用“always ai/人类姿势”检测到身体关键点。

一般模型应用

计算机视觉模型可以应用于各种各样的应用。您可以建立一个分类模型来对狗展中的狗进行分类,或者建立一个检测模型来发现活检切片中的癌细胞。保护生物学家可以使用一个模型来检测特定科或属的存在,然后将输出输入到分类模型来确定物种,然后汇总这些数据来跟踪保护工作。语义分割用于自动驾驶汽车技术。对象检测模型可用于计算商品数量并生成杂货店的库存。计算机视觉应用的可能性是广泛的!

入门应用程序“semantic _ segmentation _ cityscape”的输出示例。

数据集生成

计算机视觉模型训练从组装高质量数据集开始。俗话说,“垃圾进来,垃圾出去”。但是什么构成了计算机视觉数据集的“垃圾”?在计算机视觉中,“推理”是我们用来将训练好的模型应用于输入以推断结果的术语。我们喜欢说“按你的意愿训练推理”。因此,对于高质量的计算机视觉数据集,一个很好的经验法则是它与将输入到训练模型中的真实世界数据相似。为了确保这一点,请考虑图像的角度、照明和天气、所需对象是否被遮挡、所需目标有多远、图像的分辨率和比例以及背景和前景。

数据集生成的类型

根据您的时间表和所需的用例,有几种不同的方法来生成数据集。如果您想要一个通用的检测模型立即适应原型应用程序,您可能想要尝试找到一个带有注释的现有数据集。相反,如果您想要一个能够很好地完成某项特定任务的模型,您可能需要收集自己的图像,这些图像要与该模型将要使用的环境更加相似。举例来说,如果你只是想要一个模型来检测一般的鸟类,你可能会使用一个预先存在的包含不同环境中鸟类的图像数据集;但是,如果您是我们前面描述的保护生物学家,并且您想要一个模型,该模型将用于从您设置的特定摄像机持续检测出现在饲料中的鸟类,您应该从该摄像机的视角收集图像来训练该模型。我们将在下面描述这两个选项,以及其他几个选项。我们还将讨论数据扩充,您可以使用它来增加任何数据集的大小。

使用现有的注释数据集

根据您希望模型检测的内容,可能会有免费的带注释的数据集供您使用,这可以大大减少训练和部署所需模型的时间。但是,通过这种方式,您对数据质量的控制会少得多,因为定型数据可能不像您将用作模型输入的数据那样接近,因此,您的模型的性能可能会受到影响。因此,这种方法可能最适合概念验证项目,并且您可能需要在以后根据您的特定应用程序生成您自己的特定数据集。

一些流行的现有数据集包括上下文中的公共对象(COCO)、PASCAL 可视对象类(VOC)、ImageNet 和 Google 的开放图像数据集 V6。一些公共数据集拥有非商业许可,因此请记住始终检查您使用的任何现有数据集的许可。

使用现有数据或收集您自己的数据

您可以通过录制视频、拍摄照片或在线搜索免费提供的视频和图像来编译自己的数据集。与从现有带注释的数据集中提取数据不同,您需要对收集的图像进行注释,然后才能将它们用于训练。有许多收集照片的流行网站,包括 Unsplash、Pixabay、Pexels 而且后两者还提供视频。在收集数据时,请记住前面概述的数据收集原则,并尝试使数据集尽可能接近您的推理环境,记住“环境”包括输入图像的所有方面:照明、角度、对象等。

考虑下面的图像来构建一个检测车牌的模型。虽然每张图片都包括一辆带牌照的汽车,但它们的内容却大不相同。第一个描绘了多辆汽车的夜间场景;第二张图片显示了一个较暗的场景,但仍然是白天,有雨;第三个有不止一辆车,包括人,更加像素化;第四个和另外两个的盘子风格不同。这些都是选择图像时需要考虑的变量的例子。

汽车和车牌的环境例子。

注意:由于大量几乎相同的图像不会增强您的模型,如果您的视频中每秒有许多帧,请对您的进行采样,以选择最适合您数据集需求的帧。

使用数字生成的数据集

生成数据集的另一种方法是使用合成数据,即计算机生成的数据。如果您自己无法收集足够的数据,可以使用这种技术。通过使用合成数据,尤其是在训练异常情况时,您可以生成比从现实世界中收集的数据集大得多的数据集,从而获得更好的性能。

合成图像。

数据扩充

最后,一项可用于增强当前数据集的技术是数据扩充。这包括获取现有的数据集图像并翻转、旋转、裁剪、填充或以其他方式修改它们,以创建足够不同的图像来构成新的数据点;这可以增加训练数据的多样性,并有助于避免过度拟合。许多深度学习框架(下面讨论)包括数据增强功能。

数据集标注

通常,注释是选择图像的一部分并将标签分配给该区域的过程。在图像分类的情况下,注释是通过将单个标签分配给整个图像而不是特定区域来完成的。注释数据是通过监督学习进行模型训练的输入。在基础图像中有许多注释和足够的变化的情况下,模型训练识别图像的区别特征,并学习检测感兴趣的对象、分类图像等。,这取决于被训练的模型的类型。

不同注释类型的示例。左上角高速公路上两辆汽车的实例分割;右上角的 3D 长方体盒子。公路示例中的直线标注显示在左下角,关键点标注显示在右下角。

注释的示例包括:绘制边界框或 3D 长方体框并为对象分配标签以用于对象检测,使用多边形轮廓跟踪对象以用于语义和实例分割,识别关键点和界标并为对象界标检测分配标签,以及识别直线,例如在车道检测中使用的直线。对于图像分类,图像按组放置,每组对应一个标签。

模特培训

概述

在数据被收集和注释之后,它们被用作模型训练的输入。数据被送入 DNN,然后输出预测:用于图像分类的标签,用于对象检测的标签和边界框,用于图像分割的标签图,以及用于地标检测的关键点集,所有这些都伴随着置信度。该模型将预测与注释进行比较,并对 DNN 进行调整以产生更好的预测。根据特定于每个培训课程或模型类型的各种指标,重复该过程,直到您有良好的表现。要为您的应用程序构建自己的计算机视觉模型,您可以从头开始构建自己的模型架构,也可以使用现有的架构。

转移学习和再培训

迁移学习利用在一般数据集上训练模型所获得的知识,并将其应用于其他可能更具体的场景。您可以采用已在大型通用数据集或与您的数据集相似的数据集上训练的现有模型,并在特定于您的用例的新标签上重新训练。例如,如果您正在构建一个检测垃圾的模型,您可以采用一个通用的对象检测模型,并在与您的用例相关的特定标签上对其进行训练,例如罐子、瓶子和卫生纸卷筒。后来,您意识到您希望能够检测外卖容器和餐具。然后,您可以收集并注释包含这些新对象的其他图像,将它们添加到原始数据集中,并使用这些附加标签训练模型。这有效地更新了模型,因此它可以应用于其他用例。

注意:模型重新训练有一个额外的优点,即需要的训练数据更少!

测试应用程序

最后,一旦你用你的训练数据建立了你的模型,你可以通过输入新的、未标注的图像来测试它,看看这个模型是否分类、检测等等。你期望的。例如,继续构建一个模型来检测外部摄像机输入的鸟类,您可以从摄像机收集一些新的视频素材,可能是一天中或不同天气期间的素材汇编,并实时检查模型的输出。虽然这不是一个自动化或量化的测试,但它使您能够快速识别模型表现不佳的任何缺点或边缘情况,例如在黎明和黄昏,或者下雨的时候。然后,您可以使用来自描述这些边缘情况的图像的注释来重新训练您的模型,或者至少了解模型表现最佳的特定环境。

在 AlwaysAI 上使用您的模型

AlwaysAI 使用户能够快速轻松地启动并运行计算机视觉模型,并将其部署到边缘。我们已经描述了 alwaysAI 模型目录中存在的一些模型,这些模型可用于构建我们在本文中作为示例强调的应用程序;你可以在这里看到目录中所有型号的描述。

我们的 API, edge IQ ,使您能够在您的应用中使用这些模型,而不依赖于硬件选择,并快速开发原型。通过使用相同的标准库,您可以按特定标签过滤、用预测标记图像、更改标记颜色、添加文本、交换媒体输入和输出、更改引擎或加速器等等。

使用 alwaysAI,您还可以将自定义模型上传到模型目录中,并将其添加到您的测试应用程序中,或者您可以简单地交换本地初学者应用程序中的培训输出文件,以快速测试您的新模型。

前往 alwaysai.co,注册使用我们的平台,今天就开始学习计算机视觉!

Andres Ulloa、Todd Gleed、Eric VanBuhler、谷嘉诚和 Vikram Gupta 对本文有贡献

用张量流介绍卷积神经网络(CNN)

原文:https://towardsdatascience.com/introduction-to-convolutional-neural-network-cnn-de73f69c5b83?source=collection_archive---------2-----------------------

本页面的部分内容转载自 Google 创建和共享的作品,并根据知识共享 4.0 归属许可中描述的条款使用。来源

几乎每一种行业都在使用机器学习。它帮助人们最大限度地减少他们的工作量,因为机器能够高性能地执行大多数人工任务。机器可以进行预测分析,如分类和回归(预测数值),以及驾驶汽车等需要某种智能的任务。

机器学习是人工智能的一部分,其中我们向机器提供数据,以便它可以 从数据 中学习模式,并且它将能够预测未来类似问题的解决方案。神经网络(NN) 灵感来自人脑的神经网络。计算机视觉是人工智能的一个领域,专注于与图像相关的问题。CNN 结合计算机视觉能够执行复杂的操作,从对图像进行分类到解决天文学的科学问题和建造自动驾驶汽车。。

杰弗里·辛顿(Geoffrey Hinton)说,“我认为人们需要明白,深度学习正在幕后使许多事情变得更好。”

所以问题是,这些机器如何学习处理图像?

它使用卷积神经网络来有效地完成这项任务。我们先来了解一下什么是卷积神经网络,又名 CNN

众所周知,图像是二维像素阵列。任何图像都可以根据其特征进行分类。SVM、决策树、随机森林等科学学习算法擅长解决分类问题,但无法从图像中提取合适的特征。

这就是卷积神经网络发挥作用的地方。CNN 是卷积层和神经网络的结合。

基本上任何用于图像处理的神经网络都包括以下层

  • 输入层,卷积层,汇集层,密集层。

卷积只不过是应用于图像以从中提取特征的过滤器。我们将使用这种不同的卷积来从图像中提取不同的特征,如边缘、高光图案。

卷积如何作用于图像。来源

这个卷积的作用是创建一个一定大小的过滤器(默认大小为 3X3)。创建过滤器后,它从图像的左上角开始执行元素乘法。逐元素乘法意味着将具有相同索引的元素相乘。将这些计算值相加以获得像素值,并将其存储在新矩阵中。我们将使用这个新生成的矩阵进行进一步处理。

Conv2D(32, 3, activation='relu') 
# 32 filters or convolutions of size 3 X 3, with *relu* as activation function. 

当我们继续在获得的矩阵上应用过滤器时,矩阵的大小减小。

新矩阵的大小=(旧矩阵的大小-滤波器大小)+1

当我们说卷积层大小是 32 时。这意味着将对图像应用 32 个随机生成的滤波器,从而为该图像输出 32 个特征矩阵。这些特征矩阵作为输入传递到下一层。

在应用卷积之后,还有一个概念叫做。池用于减小图像的大小。有两种类型的池:

  1. 最大池:从指定大小的矩阵中选择最大值(默认大小为 2 X 2)。这种方法有助于提取图像中具有高重要性或高亮显示的特征。

高亮度特征是具有高像素值的图像的一部分。

最大池大小为 2 X 2。来源

MaxPooling2D() # method for Max-pooling layer 
               # default size of matrix is 2 X 2

2.平均池:与最大池不同,平均池取池层矩阵(默认大小为 2 X 2)所有像素值的平均值。

平均池。来源

在上面的例子中,图像大小是 4 X 4,池大小是 2 X 2。从左上角像素开始。它将计算 2 X 2 块矩阵的平均值。对于第一个 2 X 2 块,输出值计算为(1+3+2+9)/4 = 15/4 =3.75。以类似的方式,将计算所有其他值。

AveragePooling2D()  # method for Average pooling layer
                    # default size of matrix is 2 X 2

在大多数情况下,使用最大池是因为它的性能比平均池好得多。

在任何一个神经网络中,第一层是输入层,最后一层是输出层。输入层包含所有的输入,这里图像是输入。这些图像作为输入被提供给第一卷积层。第一层的输出将作为第二层的输入,依此类推&。这个过程将持续到最后一层。

在定义神经网络时,第一卷积层需要作为输入传递给它的图像的形状。在传递图像之后,通过所有卷积层和池层,输出将被传递到密集层。

我们不能将卷积层的输出直接传递给密集层,因为卷积层的输出是多维形状的,而密集层需要一维 形状即一维数组的输入。

所以我们将在卷积层和密集层之间使用 Flatten()方法。Flatten()方法将多维矩阵转换为一维矩阵。在神经网络中,非线性函数被用作激活函数

线性函数图。来源

线性函数是最高指数为 1 的表达式。线性函数的图形是直线。

例如:Y= 2X +3。

非线性函数图。来源

非线性函数是最高指数大于 1 的表达式。非线性函数的图形不是直线,而是曲线。

例如:Y= X

密集层是神经元的简单层,其中每个神经元接收来自前一层所有神经元的输入,因此称为密集。密集层用于根据卷积层的输出对图像进行分类。

单个神经元的工作。一层包含多个这样的神经元。来源

神经网络中的每一层都包含神经元,这些神经元计算其输入的加权平均值,并且这个加权平均值通过一个非线性函数传递,这个非线性函数被称为一个“ 激活函数” 。该激活函数结果被视为神经元的输出。以类似的方式,对所有层的所有神经元执行该过程。

最后一层的输出将被视为该图像的输出。

#sample code for creating Convolutional Neural Networkmodel = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D())
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D())
model.add(layers.Conv2D(64, (3, 3), activation='relu'))model.add(layers.Flatten()) 
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))

这里,输出层有 10 个神经元具有 softmax 激活功能。 Softmax 激活功能在我们有 2 个或 2 个以上的类时使用。如果我们总共有 10 个类,那么输出层中的神经元数量将是 10。每个神经元代表一个类。

所有 10 个神经元将返回各自类别的输入图像的概率。具有最高概率的类别将被认为是该图像的输出。

同样,我们将所有图像传递到卷积层,然后传递到神经网络,它将为这些图像产生相应的输出。

model.summary()

summary()方法将显示模型的架构。

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 30, 30, 32)        896       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 15, 15, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 13, 13, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 6, 6, 64)          0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 4, 4, 64)          36928     
_________________________________________________________________
flatten (Flatten)            (None, 1024)              0         
_________________________________________________________________
dense (Dense)                (None, 64)                65600     
_________________________________________________________________
dense_1 (Dense)              (None, 10)                650       
=================================================================
Total params: 122,570
Trainable params: 122,570
Non-trainable params: 0
_________________________________________________________________

参数 (params)是权重和偏差,将用于 CNN 所有神经元的计算

当我们在一些图像上训练任何模型时,它将为所有参数(即权重和偏差)确定一些特定值,这些值用于处理图像和预测该图像的输出。

卷积神经网络主要用于二元和多类、多标签分类。有一些 p 重新训练的模型Inception、VGG16、VGG19、mobilenet 等,它们是一些研究人员在数百万张图像上训练它们以将图像分类到多个类别后创建的。这些模型已经学习了对图像进行分类的模式。如果你计划建立一个图像分类器,那么你也可以使用这些模型中的一个作为基础层,并在最后添加一些你选择的密集层。密集图层的数量将根据您的要求和输出类的数量而变化。

在本文中,我们做了卷积神经网络的基础知识,这是非常重要的建立图像分类模型的演练。在下一篇文章中,让我们看看如何使用预先训练的模型来构建一个图像分类器。

如果想查看更多关于卷积神经网络的内容,可以参考 Tensorflow 官网,此处

感谢阅读。😊

D-Tale 简介

原文:https://towardsdatascience.com/introduction-to-d-tale-5eddd81abe3f?source=collection_archive---------5-----------------------

用于交互式数据探索的 D-Tale 简介

D-Tale 是一个最近创建的图书馆(2020 年 2 月底),它允许我们可视化熊猫的数据框架。D-Tale 所做的是生成一个交互式图形界面,在这个界面中我们可以定义我们想要的数据外观,并按照我们的喜好对数据进行探索性分析。

你可以在这个链接看到 D-Tale 是如何工作的。本文中的图片是使用那个例子和我们自己的数据生成的,你可以在这里下载。

怎么跑?

首先,您必须使用以下命令安装它:

pip install --upgrade dtale

我们需要一个开放的 Python 实例来运行它,所以我们不能像使用熊猫档案那样轻松地共享它,我们将永远需要一个开放的 Python 解释器来使用它。由于它是一个非常新的库,这可能会随着以后的版本而改变,我们将能够从任何现代的网络浏览器导出一个 html 文件。

这是在本地启动 D-Tale 交互式应用程序的代码:

import dtale
import pandas as pd
df = pd.read_csv(‘data.csv’)
d = dtale.show(df)
d.open_browser()

就这样,用这个工具显示一个数据集只需要 5 行代码。现在让我们从它的图形界面来看看 D-Tale 能为我们做些什么。先考虑到是刚出的库(2020 年 2 月底),大概再过几个月就会有新的有趣功能。

D-Tale 特征

首先,D-Tale 向我们展示数据的方式和熊猫一样。唯一的区别是左上角的菜单,它允许我们对数据做很多事情,我们稍后会看到。有趣的一点是,在那个菜单旁边,它向我们显示了数据集的列数和行数。

单击任何列标题都会打开一个下拉菜单,为我们提供对数据进行排序的选项,并按照我们想要的方式显示数据。我建议您亲自尝试一下每个按钮是如何工作的。

在这个菜单中我们可以找到的最有趣的选项是描述,它向我们显示所选列的统计分析,以及列分析,它向我们显示所选列的直方图。

使用选项格式,我们可以定义数字的显示方式(小数位数、千位分隔符、红色负数……)

最后,我们可以使用最后一个选项过滤每一列的数据,我们可以只显示大于或小于某个数字的值,只显示某个范围内的值,或者只显示该列具有某个值的行。

在 D-Tale 主菜单中,您可以找到 D-Tale 中的所有选项。这就是 D-Tale 的魅力所在。

让我们看看每个菜单项的作用。先从来形容吧。这与我们可以从列标题中访问的选项相同,可以查看每个列的统计分析。

使用过滤器选项,我们可以过滤数据,只显示那些符合我们想要的特定条件的行。对于简单的过滤操作,使用上述的列过滤更容易。对于更复杂的过滤操作,我们可以使用这个工具。我们必须根据右边定义的代码编写过滤规则。

使用 Build Column 我们可以生成新列,例如我们定义一个新列,它是另外两个列的总和。

通过相关性它将向我们展示变量之间的相关性。

图表选项中,我们可以在可用的图表(线形、条形、散点图、圆形、文字云、热图、3D 散点图和表面)中生成我们想要的图形。

我们可以定义我们希望在每个图表中显示哪些变量,以及每个图表的几个更具体的参数,例如我们希望显示的最大值和最小值。

最后,最有趣的选项之一是热图。它根据每个单元格的值向我们显示数据表中的颜色。

我们在这里完成了这篇文章。我们将拭目以待这个库如何发展,以及它是否会在数据科学社区中流行起来。它肯定有一个充满希望的未来。

R 中的数据帧介绍

原文:https://towardsdatascience.com/introduction-to-data-frames-in-r-b9a6302d9a56?source=collection_archive---------37-----------------------

许多数据集存储为数据框。了解如何创建数据框、选择数据框中感兴趣的部分以及根据特定变量对数据框进行排序。

什么是数据框?

回想一下,对于 矩阵 来说,所有元素必须是相同的数据类型。然而,在做市场调查时,你经常会有这样的问题:

  • “你结婚了吗”或其他“是/否”的问题
  • “你多大了,”(numeric)
  • 你对这种产品有什么看法?或者其他‘开放式’问题(character)

输出,即回答者对上述问题的回答,是不同数据类型的数据集。处理包含不同数据类型而不是一种数据类型的数据集是很常见的。

数据框将数据集的变量作为列,将观察值作为行。

下面是一个 r 中内置数据帧的例子。

看一看数据集

处理大型数据集并不少见。当处理(极其)大的数据集和数据框时,您必须首先对数据集的结构和主要元素有一个清晰的了解。因此,只显示整个数据集的一小部分通常是有用的。

要在 R 中做到这一点,您可以使用函数[head()](https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/head)[tail()](https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/head)head()功能显示数据帧的第一部分。tail()功能显示最后一部分。这两个函数都打印一个名为“header”的顶行,其中包含数据集中不同变量的名称。

看一看结构

另一种快速查看数据的方法是[str()](https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/str)函数。str()功能显示数据集的结构。对于数据框,它提供以下信息:

  • 观察总数(例如 32 种车型)
  • 变量的总数(例如 11 个汽车特征)
  • 变量名的完整列表(例如mpgcy1 …)。)
  • 每个变量的数据类型(如num)
  • 第一次观察

当您接收到一个新的数据集或数据帧时,应用str()功能通常是第一步。在进行更深入的分析之前,这是更深入了解数据集的好方法。

为了研究[mtcars](https://www.rdocumentation.org/packages/datasets/versions/3.6.2/topics/mtcars)的结构,使用str()函数。

创建数据框

让我们构建一个描述太阳系八大行星主要特征的数据框架。假设一颗行星的主要特征是:

  • 行星的类型(类地行星还是气态巨行星)
  • 行星的直径相对于地球的直径。
  • 行星相对于地球自转的总和。
  • 行星是否有环(对或错)。

一些研究表明,以下几个向量是必要的:nametypediameterrotationrings。每个向量中的第一个元素对应于第一次观察。

# Definition of vectors
name <- c("Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune")
type <- c("Terrestrial planet", "Terrestrial planet", "Terrestrial planet", 
          "Terrestrial planet", "Gas giant", "Gas giant", "Gas giant", "Gas giant")
diameter <- c(0.382, 0.949, 1, 0.532, 11.209, 9.449, 4.007, 3.883)
rotation <- c(58.64, -243.02, 1, 1.03, 0.41, 0.43, -0.72, 0.67)
rings <- c(FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE)

要构建数据框,使用[data.frame()](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/data.frame)功能。作为参数,必须传递前面的向量:它们将成为数据帧的不同列。因为每一列都有相同的长度,所以传递的向量也应该有相同的长度。请记住,它们可能包含不同类型的数据。

为了构建行星数据框架,我们将使用data.frame()函数并传递向量nametypediameterrotationrings as arguments.

# Create a data frame from the vectors
planets_df <- data.frame(name, type, diameter, rotation, rings)

数据框有 8 个观察值和 5 个变量。

让我们研究一下新数据框的结构。回想一下,我们可以使用str()函数来实现这一点。

数据框元素的选择

与向量和矩阵类似,您可以使用方括号[]从数据框中选择元素。通过使用逗号,您可以分别指示从行和列中选择什么。例如:

  • my_df[1,2]选择my_df中第一行第二列的值。
  • my_df[1:3, 2:4]选择my_df中的第 1 至 3 行和第 2 至 4 列。

选择一行或一列的所有元素与选择矩阵完全相同。例如,my_df[1,]选择第一行的所有元素。

让你试试

planets_df 数据框中选择水星的直径(这与我们之前使用的数据框相同)。这是第一行第三列的值。接下来,选择火星上的所有数据(第四行)。

# Definition of vectors
name <- c("Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune")
type <- c("Terrestrial planet", "Terrestrial planet", "Terrestrial planet", 
          "Terrestrial planet", "Gas giant", "Gas giant", "Gas giant", "Gas giant")
diameter <- c(0.382, 0.949, 1, 0.532, 11.209, 9.449, 4.007, 3.883)
rotation <- c(58.64, -243.02, 1, 1.03, 0.41, 0.43, -0.72, 0.67)
rings <- c(FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE)# Create a data frame from the vectors
planets_df <- data.frame(name, type, diameter, rotation, rings)

解决办法

# Print out diameter of Mercury (row 1, column 3)
planets_df[1,3]# Print out data for Mars (entire fourth row)
planets_df[4,]

数据框元素的选择(2)

除了使用数字来选择数据框的元素,还可以使用变量名来选择数据框的列。

例如,假设您想要选择type列的前三个元素。使用第一种方法,您将使用

planets_df[1:3,2]

这种方法的一个可能的缺点是,您必须知道(或查找)列号type,如果有很多变量,这可能会变得很困难。因此,使用变量名通常更容易:

plantes_df[1:3, "type"]

让你试试

选择并打印出planets_df"diameter"栏中的前 5 个值。

# Definition of vectors
name <- c("Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune")
type <- c("Terrestrial planet", "Terrestrial planet", "Terrestrial planet", 
          "Terrestrial planet", "Gas giant", "Gas giant", "Gas giant", "Gas giant")
diameter <- c(0.382, 0.949, 1, 0.532, 11.209, 9.449, 4.007, 3.883)
rotation <- c(58.64, -243.02, 1, 1.03, 0.41, 0.43, -0.72, 0.67)
rings <- c(FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE)# Create a data frame from the vectors
planets_df <- data.frame(name, type, diameter, rotation, rings)

解决办法

# Select first 5 values of diameter column
planets_df[1:5, "diameter"]

只有带环的行星

通常,从数据框中选择特定变量会很有帮助。为此,您需要选择一整列。假设您想要选择第三个变量diameter的所有元素。您可以使用以下命令之一:

planets_df[,3]
planets_df[,"diameter"]

然而,有一条捷径。如果您的列有名称,您可以使用$符号:

planets_df$diameter

让你试试

从我们之前创建的planets_df数据框中选择rings变量,并将结果存储为rings_vector。打印出rings_vector看看你是否做对了。

# Definition of vectors
name <- c("Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune")
type <- c("Terrestrial planet", "Terrestrial planet", "Terrestrial planet", 
          "Terrestrial planet", "Gas giant", "Gas giant", "Gas giant", "Gas giant")
diameter <- c(0.382, 0.949, 1, 0.532, 11.209, 9.449, 4.007, 3.883)
rotation <- c(58.64, -243.02, 1, 1.03, 0.41, 0.43, -0.72, 0.67)
rings <- c(FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE)# Create a data frame from the vectors
planets_df <- data.frame(name, type, diameter, rotation, rings)

解决办法

# Select the rings variable from planets_df
rings_vector <- planets_df$rings

# Print out rings_vector
rings_vector

只有带环的行星(2)

假设你想用 R 来帮助你得到太阳系中有环的行星的数据。在上面,我们创建了包含以下内容的rings_vector:

> rings_vector
[1] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE

我们看到前四个观测值(或行星)没有环(FALSE),剩下的四个有(TRUE)。

为了更好地了解这些行星的名称、直径等,我们将使用rings_vector来选择四颗有环行星的数据。

# Select all columns for planets with rings
planets_df[rings_vector,]

在这里,我们学习了如何根据某个条件是否为真(有环或无环),从日期框架(planets_df)中选择一个子集,提取所有相关数据。

只有有环但更短的行星

通过使用[**subset()**](http://www.rdocumentation.org/packages/base/functions/subset) 函数作为快捷方式,我们可以做与上面完全相同的事情。subset 函数返回满足条件的向量、矩阵或数据帧的子集。

subset(my_df, subset = some_condition)

subset 函数接受几个参数。第一个参数my_df指定要添加子集的数据集。第二个参数是一个逻辑表达式,指示要保留的元素或行:缺少的值被视为 false。通过添加第二个参数,您为 R 提供了选择正确子集的必要信息和条件。

以前,为了得到有环行星的子集,我们使用了rings_vector

# Select the rings variable from planets_df
rings_vector <- planets_df$rings# Select all columns for planets with rings
planets_df[rings_vector,]

通过使用subset()函数,我们可以在不需要rings_vector的情况下得到完全相同的结果。

subset(planets_df, subset = rings)

让你试试

planets_df中选择直径小于地球的行星子集。你需要使用subset()功能。提示:因为diameter变量是行星直径相对于地球的相对度量,所以你的条件是diameter < 1

# Definition of vectors
name <- c("Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune")
type <- c("Terrestrial planet", "Terrestrial planet", "Terrestrial planet", 
          "Terrestrial planet", "Gas giant", "Gas giant", "Gas giant", "Gas giant")
diameter <- c(0.382, 0.949, 1, 0.532, 11.209, 9.449, 4.007, 3.883)
rotation <- c(58.64, -243.02, 1, 1.03, 0.41, 0.43, -0.72, 0.67)
rings <- c(FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE)# Create a data frame from the vectors
planets_df <- data.frame(name, type, diameter, rotation, rings)

解决办法

# Select planets with diameter < 1
subset(planets_df, subset = diameter < 1)

根据我们的输出,我们可以分析并确定三颗行星的直径小于地球。它们是水星、金星和火星。

整理

在数据分析中,根据数据集中的某个变量对数据进行排序通常很有帮助。这可以借助 r 中的函数[**order()**](http://www.rdocumentation.org/packages/base/functions/order)来完成。

该函数返回应用于变量(如向量)时每个元素的排序位置。例如:

> a <- c(100, 10, 1000)
> order(a)
[1] 2 1 3

在这个例子中,a中的第二个元素 10 是最小的元素,所以在order(a)的输出中 2 排在第一位。100 是a中的第一个元素,是第二小的元素,所以 1 在order(a)的输出中排在第二位。然后,a中的第三个也是最后一个元素 1000 是最大的元素,所以 3 在order(a)的输出中排在最后。

有了order(a)的输出,我们可以重组a,这样我们就可以得到一个排序后的输出:

> a[order(a)]
[1]   10  100 1000

对数据框进行排序

我们可以用order()函数做的一件有用的事情是排序我们的数据帧。假设我们想通过diameter对数据帧进行排序。也就是说,重新排列数据框,使其从最小的行星开始,以最大的行星结束。

我们首先必须使用planets_dfdiameter栏上的order()功能。让我们将结果存储为positions

# Use order() to create positions.
positions <- order(planets_df$diameter)

接下来,我们将使用方括号内的positions向量作为行索引来重新排列planets_df。我们将保留所有列。

# Use positions to sort planets_df
planets_df[positions, ]

瞧,我们现在有了一个基于直径的分类数据框。

笔记

所有图片,除非特别注明,均归作者所有。横幅图像是使用 Canva 创建的。

每位数据科学家的数据预处理指南

原文:https://towardsdatascience.com/introduction-to-data-preprocessing-67a67c42a036?source=collection_archive---------36-----------------------

(图片由作者提供)

终极数据科学指南

理解数据预处理的概念,并使用 scikit 学习库实现它们

数据是以无组织或有组织的形式收集的事实和数字、观察结果或对事物的描述。数据可以以图像、文字、数字、字符、视频、音频等形式存在。

什么是数据预处理

为了分析我们的数据并从中提取洞察力,在我们开始建立我们的机器学习模型之前,有必要处理数据,即我们需要将我们的数据转换为我们的模型可以理解的形式。因为机器不能理解图像、音频等形式的数据。

数据以算法可以轻松解释的形式(一种高效的格式)进行处理,并准确产生所需的输出。

我们在现实世界中使用的数据并不完美,它是不完整的、不一致的(有异常值和噪声值),并且是一种非结构化的形式。预处理原始数据有助于组织、缩放、清理(移除异常值)、标准化,即简化它以将数据馈送给机器学习算法。

数据预处理的过程包括几个步骤:

  • 数据清洗:我们使用的数据可能会有一些遗漏点(比如不包含任何值的行或列)或者有噪声数据(机器难以解释的无关数据)。为了解决上述问题,我们可以删除空的行和列,或者用其他值填充它们,并且我们可以使用像回归和聚类这样的方法来处理有噪声的数据。
  • 数据转换:将原始数据转换成适合模型的格式的过程。它可能包括分类编码、缩放、归一化、标准化等步骤。
  • 数据缩减:这有助于减少我们正在处理的数据的大小(便于分析),同时保持原始数据的完整性。

sci kit-用于数据预处理的学习库

Scikit-learn 是一个流行的开源机器学习库。这个库为我们提供了各种基本工具,包括用于随机森林、分类、回归的算法,当然还有用于数据预处理的算法。这个库是建立在 NumPy 和 SciPy 之上的,很容易学习和理解。

我们可以使用以下代码将库导入到工作区中:

import sklearn

为了包含预处理功能,我们可以使用以下代码:

from **sklearn** import **preprocessing**

在本文中,我们将重点介绍一些基本的数据预处理功能,如标准化、规范化、分类编码、离散化、缺失值插补、生成多项式功能、自定义转换器。

那么,现在让我们开始使用这些功能吧!

标准化

标准化是一种用于缩放数据的技术,使得数据的平均值为零,标准偏差为一。这里的值不限于特定的范围。当输入数据集的特征在其范围之间存在较大差异时,我们可以使用标准化。

(图片由作者提供)数据标准化的公式

让我们考虑下面的例子:

from sklearn import preprocessing
import numpy as np
x = np.array([[1, 2, 3],
[ 4,  5,  6],
[ 7,  8, 9]])
y_scaled = **preprocessing.scale**(x)
print(y_scaled)

这里我们有一个 3x3 维的输入数组,它的值在 1 到 9 之间。使用preprocessing中可用的scale功能,我们可以快速缩放我们的数据。

(图片由作者提供)缩放数据

这个库中还有另一个可用的函数StandardScaler,它帮助我们计算训练数据集的均值和标准差,并通过实现Transformer API对训练数据集重新应用相同的变换。

如果我们想在给定范围内缩放我们的特征,我们可以使用MinMaxScaler(使用参数feature_range=(min,max))或MinAbsScaler(不同之处在于每个特征的最大绝对值在MinAbsScaler中被缩放到单位大小)

from sklearn.preprocessing import MinMaxScaler
import numpy as np
x = **MinMaxScaler(feature_range=(0,8))**
y = np.array([[1, 2, 3],
[ 4,  -5,  -6],
[ 7,  8, 9]])
scale = x.**fit_transform**(y)
scale

这里,3x3 维数组的值在给定的(0,8)范围内缩放,我们使用了.fit_transform()函数,它将帮助我们稍后对另一个数据集应用相同的转换。

(图片由作者提供)指定范围内的缩放数据

正常化

标准化是在 -1,1 的范围内对数值进行缩放的过程,即将数值转换成一个通用的比例。这确保了数据集中的大值不会影响学习过程,并且对模型的学习过程具有类似的影响。当我们想要量化任何一对样本(如点积)的相似性时,可以使用归一化。

from sklearn import preprocessing
import numpy as np
X = [[1,2,3],
[4,-5,-6],
[7,8,9]]
y = preprocessing.normalize(X)
y

(图片由作者提供)归一化数据

这个模块也为我们提供了一个Transformer API的替代方案,通过使用实现相同操作的Normalizer函数。

编码分类特征

很多时候,我们使用的数据可能不具有连续形式的特征值,而是具有文本标签的类别形式。为了让机器学习模型处理这些数据,有必要将这些分类特征转换成机器可理解的形式。

该模块中有两个可用的函数,通过它们我们可以对我们的分类特征进行编码:

  • OrdinalEncoder: 这是将分类特征转换为整数值,以便该函数将每个分类特征转换为整数的一个新特征(0 到 n_categories — 1)。
import sklearn.preprocessing
import numpy as np
enc = **preprocessing.OrdinalEncoder**()
X = [['a','b','c','d'], ['e', 'f', 'g', 'h'],['i','j','k','l']]
enc.fit(X)
enc.transform([['a', 'f', 'g','l']])

这里,三个类别被编码为0,1,2,上述输入的输出结果是:

(图片由作者编码的数据)

  • OneHotEncode: 该编码器功能将每个具有n_categories可能值的分类特征转换为n_categories二进制特征,其中一个为 1,所有其他为 0。为了更好的理解,请看下面的例子。
import sklearn.preprocessing
import numpy as np
enc = **preprocessing.OneHotEncoder**()
X = [['a','b','c','d'], ['e', 'f', 'g', 'h'],['i','j','k','l']]
enc.fit(X)
enc.transform([['a', 'f', 'g','l']]).toarray().reshape(4,3)

(图片由作者编码的数据)

[数]离散化

离散化过程有助于我们将数据的连续特征分离成离散值(也称为宁滨或量化)。这类似于使用连续数据创建直方图(其中离散化侧重于将特征值分配给这些箱)。在某些情况下,离散化可以帮助我们在线性模型中引入非线性。

import sklearn.preprocessing 
import numpy as np
X = np.array([[ 1,2,3],
              [-4,-5,6],
              [7,8,9]])
dis = preprocessing.KBinsDiscretizer(n_bins=[3, 2, 2], encode='ordinal')
dis.fit_transform(X)

使用KBinsDiscretizer(),该功能将特征离散到k箱中。默认情况下,输出是一键编码的,我们可以用encode参数来改变。

(图片由作者提供)数据离散化

缺失值的插补

此过程用于处理数据中的缺失值(nan、空白等),方法是为它们赋值(基于数据集的已知部分进行输入),以便模型可以处理数据。让我们用一个例子来理解这一点:

from sklearn.impute import SimpleImputer
import numpy as np
impute = **SimpleImputer(missing_values=np.nan, strategy='mean')**
X = [[np.nan, 1,2], [3,4, np.nan], [5, np.nan, 6]]
impute.fit_transform(X)

这里,我们使用了SimpleImputer()函数来输入缺失值。该函数中使用的参数是missing_values来指定要估算的缺失值,strategy来指定我们希望如何估算该值,就像在上面的示例中我们使用了mean,这意味着缺失值将被列值的平均值替换。我们可以为strategy使用其他参数,如中位数、众数、most_frequent(基于列中特定值出现的频率),或者constant(一个常量)。

(图片由作者提供)输入缺失值

生成多项式要素

为了在我们的机器学习模型的结果中获得更大的准确性,有时在模型中引入复杂性(通过添加非线性)是好的。我们可以通过使用函数PolynomialFeatures()简单地实现这一点。

import numpy as np
from sklearn.preprocessing import PolynomialFeatures
x = **np.array([[1,2],
              [3,4]])**
nonl = **PolynomialFeatures(2)**
nonl.fit_transform(x)

(图片由作者)生成多项式特征

在上面的例子中,我们已经在PolynomialFeatures()函数中指定了2所需的非线性模型的阶数。输入数组的特征值从 (X1,X2)转换到(1,X1,X2,X1,X1*X2,X2)。

定制变压器

如果出于数据处理或清理等任何目的,需要使用特定的函数(python 中已有的)来转换整个数据,我们可以通过实现函数FunctionTransformer()并传递所需的函数来创建一个定制的转换器。

import sklearn.preprocessing 
import numpy as np
transformer = **preprocessing.FunctionTransformer**(np.log1p, validate=True)
X = np.array([[1,2,3],
              [4,5,6],
              [7,8,9]])
transformer.transform(X)

在本例中,我们使用了 log 函数来转换数据集值。

(图片来自作者)实现定制变压器

结论

我希望通过这篇文章,你能够理解机器学习模型中数据预处理的概念和需求,并且能够将这些概念应用到真实的数据集中。

为了更好地理解这些概念,我建议您尝试在 once 上实现这些概念。继续探索,我相信你会发现新的特性。

如果你有任何问题或意见,请发表在评论区。

查看完整的数据可视化指南和 NumPy 的基本功能:

[## 用 Python 实现数据可视化

Master python 的数据可视化库

towardsdatascience.com](/data-visualization-with-python-8bc988e44f22) [## NumPy 的备忘单:基本功能和鲜为人知的功能

学习你可能不知道的 NumPy 的各种基本功能(用代码)

towardsdatascience.com](/numpy-cheatsheet-for-essential-functions-python-2e7d8618d688)

最初发表于:【www.patataeater.blogspot.com】

Resources:
[https://scikit-learn.org/stable/modules/preprocessing.html#](https://scikit-learn.org/stable/modules/preprocessing.html#)

数据科学导论

原文:https://towardsdatascience.com/introduction-to-data-science-eb2498d1c5c7?source=collection_archive---------56-----------------------

亨特·哈里特在 Unsplash 上的照片

数据科学家——21 世纪最性感的工作

我相信你已经听过这句话,即使你不是像我一样的数据头脑。这是来自哈佛商业评论的主要出版物,作者是 Thomas H. DavenportDJ Patil ,他们谈到随着专注于大数据的技术的出现,数据变得越来越容易访问和驯服。如今,每一家大公司都在制定数据科学战略并改善他们的服务——亚马逊推出了推荐引擎,脸书推出了 feed 排名,谷歌推出了全套产品,还有许多其他公司。为了理解所有这些很酷的东西,让我们先浏览一下数据科学的基础知识,试着分解一下你在谷歌上搜索“数据科学”时会看到的大术语…

什么算是数据?

让我们从定义这一切的症结开始— 数据:

数据是信息的集合,通常由不同格式的片段组成

让我们以一个非常非常受欢迎的服务为例——网飞。人们都爱看电影,但每个人都有偏好。例如,假设我们正试图建立一个系统,根据人们的口味向他们推荐电影。有些喜欢动作片,有些喜欢惊悚片,有些可能是恐怖片、科幻片或喜剧片。这使得问题变得非常有趣,你希望你的系统能够正确处理这个问题——当我现在喜欢动作片的时候,你不会想推荐给我一部言情片吧!

现在,即使对一个人来说,让我们说让你给我推荐一部电影,你也会想知道我的品味,我的偏好,我的喜欢和不喜欢。所以你会问我问题:“你喜欢这个吗……..或者…..你喜欢这样吗?对此你怎么看?…我明白了…你喜欢有有趣故事情节的电影,当然还有动作片。基于此,我会建议你去看这些电影……”。

显而易见,在向我提出建议之前,你会先询问我的偏好,通过这个练习,你正在收集数据。

推荐引擎评级

同样对于推荐系统,我们将利用我们收集的关于个人电影品味的数据来训练它。这将类似于每当推荐系统看到某个模式时就指示推荐系统推荐哪种类型的电影。例如,它看到了钢铁侠、蜘蛛侠和美国队长——雷神可能是一个好建议,你觉得呢?

什么是大数据?

对于任何数据科学问题,我们能够收集大量相关数据是至关重要的。

当我们谈论大数据时,它通常涉及以上述方式形成的数据集,但其数量如此之大,以至于使用常用软件和工具管理和建模所需的时间和计算能力超过了可容忍的极限,因此增加了术语“大”。
当我们处理大数据时,数据的大小并没有真正的限制,数据量从兆兆字节到许许多多兆兆字节不等。它可以是结构化的,也可以是非结构化的,并且很难使用传统的数据库和软件技术进行处理。

信息存储容量时间表(EN.WIKIPEDIA.ORG

大数据的特征

有几种方法可以根据大数据的特征来定义大数据,其中最常见的是使用流行的大数据 4v。

体积 这就是数据的数量——加上‘大’的正当性。这决定了可以从数据中提取多少信息和见解。对于强大的系统,必须使用大量的数据来训练模型,以便模型能够表现得非常好。虽然拥有如此大量的数据令人惊叹,但你应该始终坚持的是,数据足够丰富。因此,虽然拥有一个人多年的电影数据总体来说是好的,但如果这些数据来自这个人的童年,它可能就没那么有用了。当我们想向成年人推荐电影时,我们也会包括儿童电影!

多样性 这个属性与我们正在处理的数据的性质和类型有关。我们可能会处理文本、图像、音频、视频或者可能带有时间戳的事件—结构化、非结构化、半结构化甚至复杂结构的数据。我们得出和实施的分析、见解和流程高度依赖于数据的多样性。这是因为拥有多种多样的数据需要同样多种多样的方法来存储和处理这些数据。

准确性 传入的数据虽然如上所述规模巨大,但如果不相关就没多大用处。我们接收到的数据质量极大地影响了我们的直觉和洞察力,以及我们的分析结果。例如,让我们回到电影推荐引擎。包含在分析中的数据必须是正确的,所以它不应该将电视节目作为我们最终数据集的一部分。我们正在向一个人推荐电影,而让电视节目成为我们对那个人的记录的一部分不仅是不必要的,而且是不正确的。虽然电视节目可以按类型分类,但这正是与电影相似之处的所在。他们有一个完全不同的结构——可能是 20 分钟或更长的剧集在连续的几季中组合在一起。

速度 数据生成和输入分析系统的速度在很大程度上决定了我们处理数据的方式。大数据通常是实时可用的,这种生成频率以及处理这种海量数据的频率是推动分析的两个最重要的因素。我们需要最新的数据来训练我们的推荐系统,我们希望尽快给出建议!

数据科学

根据维基百科,

科学是以可检验的解释和关于宇宙的 预言 的形式构建和组织 知识 的系统事业。

我相信你一定看过各种不同的主题,比如数据分析、机器学习、人工智能、自然语言处理等等。等等..数据科学可以被称为所有这些领域的总称——所有这些领域都涉及必须首先经过数据预处理管道的数据。数据被转换成一种现在适合我们运行分析模型的格式。如果你想了解更多,可以看看这篇文章:数据预处理

** [## 数据预处理

标签:当我们谈论数据时,我们通常会想到一些包含大量行和列的大型数据集。而那个…

thedatascienceportal.com](https://thedatascienceportal.com/data-preprocessing/)

你为什么问科学?
当解决数据科学中的任何问题时,所发生的是人们试图利用统计学、机器学习、数据分析和其他相关领域,以便使用相关数据分析和理解实际现象,然后将其呈现给世界,就像实际科学实验所发生的那样。首先观察问题,然后提出适当的假设,并反复试验以改进假设并得到更好的结果。任何结果的正确性都是由我们试图解决的问题类型决定的——根据特定问题的度量和 KPI。这正是在数据科学实验中发生的事情——在框定问题、进行实验以产生理解并将理解传达给世界其他地方方面,存在巨大的可能性。**

原载于 2020 年 4 月 25 日 https://thedatascienceportal.com。更多此类内容请访问数据科学门户网站!****

*** [## 数据科学门户

大家好,欢迎来到数据科学门户。这个空间致力于学习和理解所有令人兴奋的…

thedatascienceportal.com](https://thedatascienceportal.com/)***

Datapane 简介:构建交互式报表的 Python 库

原文:https://towardsdatascience.com/introduction-to-datapane-a-python-library-to-build-interactive-reports-4593fd3cb9c8?source=collection_archive---------6-----------------------

创建精美报告并与您的团队分享分析结果的简单框架

克莱班克斯Unsplash 拍摄的照片

动机

对于许多 Python 数据分析,有时您希望与其他人共享您的发现。展示您的工作将有助于您的团队和经理了解您的最新进展,并在您的网络中树立您作为数据科学家的声誉。我在这篇文章中提到了分享我的工作如何影响了我的职业生涯:

[## 当生活不给你喘息的机会,如何学习数据科学

我努力为数据科学贡献时间。但是发现新的策略使我能够提高我的学习速度和…

towardsdatascience.com](/how-to-learn-data-science-when-life-does-not-give-you-a-break-a26a6ea328fd)

但是仅仅分享是不够的。比方说,在清理完数据并创建了一些用于分析的图表后,您希望与他人分享您的发现。您最不想做的事情是与非技术人员(如您的利益相关者)分享整个代码或笔记本,并要求他们安装 Jupyter 笔记本和所需的环境,以查看您的发现,如下所示:

“就是这个。ipynb 文件。要查看这个文件,你需要pip install这些包。然后在 Jupyter 笔记本的命令行上键入。一旦你看到笔记本,运行所有的细胞,你应该能够看到数据和可视化”。

作为一种替代方法,您可以拍摄可视化效果的图片并将其放在一个面板中,但是查看者将无法对可视化效果进行太多的控制-他们将无法以交互方式使用它、浏览任何数据或更改输入参数。此外,每次他们需要更改时,您都必须手动创建另一个报告。

最佳策略是共享特定的面向用户的部分,而不设置环境。如果你能给他们发一个类似于 this 的链接给你的队友或利益相关者,那不是很好吗

在一个地方查看您的所有调查结果?

这时你需要一个像 Datapane 这样的 Python 框架。

什么是 Datapane?

Datapane 是一个 API ,面向用 Python 分析数据并需要一种方式来共享他们的结果的人。它提供了一种通过组件以编程方式创建报告的方法,这些组件包装了分析中的通用对象,例如:

创建后,报告可以发布到 web 上,在云中动态生成,或者嵌入到您自己的应用程序中,在那里可以浏览数据,并可以交互地使用可视化

Datapane 还允许您部署您的 Python 脚本和笔记本,以便其他人可以从他们的浏览器运行它们来生成报告,而不用担心代码、笔记本或设置 Python 环境。

我们来试试吧!

假设你有一个这样的脚本,有熊猫数据帧和牛郎星图

要创建报告,只需遵循以下步骤

  • 安装数据面板
pip3 install datapane
  • Datapane 上注册以获得您自己的令牌,并使用该令牌在您的终端上登录 Datapane
datapane login --server=https://datapane.com/ --token=yourtoken
  • 然后只需在您现有的分析中添加几行代码!

  • 运行脚本,瞧!一份关于 Datapane.com 的报告将自动为您创建!

https://datapane.com/khuyen/reports/stock_report_9eddadcd/

就是这样!现在你需要做的就是把这个链接分享给你的队友或经理

或者在社交媒体上分享

我还可以用 Datapane 做什么?

允许观众输入新参数

你不仅想让观众看到你的报告,你可能还想让他们能够与图表互动,并插入不同的参数,如

有了 Datapane,其他人可以生成您的报告,而不用担心代码、笔记本或设置 Python 环境。他们可以输入他们想要指定的参数作为输入,并且每次将接收到一个动态报告

要部署名为stock_report.py的脚本,创建如上所示的脚本,然后使用 Datapane 的 CLI:

datapane script deploy --script=stock_report.py --name=stock_report

关于如何部署脚本的更多说明,请参见这里的

在社交平台中嵌入报告

如果你是一个像我一样的中型作家或博客作者,你可能想嵌入一个表格或一个如下的图:

有了 Datapane,你可以通过简单地复制和粘贴 Datapane 上发布的 url 来将你的图表嵌入到 Medium 中。你也可以把它们嵌入到 Reddit、Confluence、opinion 或者你自己的网站中。

将文件和对象存储在数据面板上,以便在多个脚本中使用

Datapane 提供了一个 Blob API,允许您从任何 Python 或 CLI 环境中上传文件,并在您的脚本中或通过 CLI 访问它们。

假设您可以使用dp.Blob 将数据帧、文件或对象保存在blob.py中,使用

然后,如果您想在另一个脚本中加载它们,请使用

从报告中下载表格和图表

如果您的查看者想要下载您的表格或图表,他们可以通过报表中的 download 按钮轻松完成。

结论

恭喜你!您刚刚学习了一个新工具,它将与您喜欢的其他 Python 库一起添加到您的数据科学工作流中。

我希望这篇文章为您试用 Datapane 提供了一个良好的开端。你可以在这里了解更多关于数据面板的信息。如果您对这个工具有任何疑问,请在下面评论或在 LinkedIn 上给我发消息。

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上与我联系。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

[## 如何用 Altair 创建交互式剧情

在 5 行简单的 Python 代码中利用您的数据分析

towardsdatascience.com](/how-to-create-interactive-and-elegant-plot-with-altair-8dd87a890f2a) [## 如何用 Python 创建一个交互式创业成长计算器

使用 Python 为您的创业构建实用的度量

towardsdatascience.com](/how-to-create-an-interactive-startup-growth-calculator-with-python-d224816f29d5) [## 如何用 Voronoi 图找到最近的医院

给定一个美国医院的大数据集,我们如何快速找到最近的医院?

towardsdatascience.com](/how-to-find-the-nearest-hospital-with-voronoi-diagram-63bd6d0b7b75) [## 如何用 Github 组织你的数据科学文章

被新信息淹没?现在,您可以轻松地跟踪文章并为其创建自定义注释

towardsdatascience.com](/how-to-organize-your-data-science-articles-with-github-b5b9427dad37)

scikit-learn 决策树分类器简介

原文:https://towardsdatascience.com/introduction-to-decision-tree-classifiers-from-scikit-learn-32cd5d23f4d?source=collection_archive---------5-----------------------

将决策树分类器应用于虹膜数据集

照片由内特·格兰特Unsplash 拍摄

有很多文章解释了什么是决策树以及决策树的作用:

[## 决策树分类

决策树是对例子进行分类的简单表示。这是一种受监督的机器学习,其中数据…

medium.com](https://medium.com/swlh/decision-tree-classification-de64fc4d5aac) [## 基础知识:决策树分类器

对决策树如何工作和构建的直觉

towardsdatascience.com](/the-basics-decision-tree-classifiers-b0d20394eaeb) [## 决策树分类器解释

决策树分类器是一种简单的机器学习模型,用于分类问题。这是一个…

medium.com](https://medium.com/@borcandumitrumarius/decision-tree-classifiers-explained-e47a5b68477a)

因此,在这里,我将重点介绍如何在 iris 数据集上使用 python 中的 scikit-learn 库实现决策树,以及一些有助于分析算法性能的功能。

什么是量词?

分类器算法用于通过决策规则将输入数据映射到目标变量,并可用于预测和理解与特定类别或目标相关联的特征。这意味着这是一种受监督的机器学习算法,因为我们已经有了最终的标签,我们只是想知道如何预测它们。为了我们的目的,我们可以使用决策树分类器来基于以下特征预测我们所拥有的鸢尾花的类型:花瓣长度、花瓣宽度、萼片长度和萼片宽度。

什么是决策树?

决策树是一种树状结构,其中内部节点代表属性,分支代表决策规则,叶节点代表结果。这是通过根据属性选择度量将数据分成单独的分区来实现的,在这种情况下,属性选择度量是基尼指数(尽管如果我们愿意,我们可以将其更改为信息增益)。这实质上意味着我们每个分裂都旨在减少基尼不纯,基尼不纯根据错误分类的结果来测量节点的不纯程度。

实施决策树

我们首先希望将数据转换成正确的格式,以便创建决策树。这里,我们将使用来自sklearn datasets 数据库的 iris 数据集,它非常简单,是如何实现决策树分类器的展示。

来自scikit-learn的决策树分类器的好处是目标变量可以是分类的或数字的。为了清楚起见,给定 iris 数据集,我更喜欢保持花的分类性质,因为稍后解释起来更简单,尽管如果需要的话,标签可以稍后引入。因此,以下代码可用于在此导入数据集:

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris#load in the data
data = load_iris()
#convert to a dataframe
df = pd.DataFrame(data.data, columns = data.feature_names)
#create the species column
df['Species'] = data.target#replace this with the actual names
target = np.unique(data.target)
target_names = np.unique(data.target_names)
targets = dict(zip(target, target_names))
df['Species'] = df['Species'].replace(targets)

接下来我们要做的是提取我们的训练和测试数据集。这样做的目的是确保模型不是在所有可用的数据上进行训练,以便我们可以测试它在看不见的数据上的表现。如果我们使用所有数据作为训练数据,那么我们可能会过度拟合模型,这意味着它可能会在看不见的数据上表现不佳。

#extract features and target variables
x = df.drop(columns="Species")
y = df["Species"]#save the feature name and target variables
feature_names = x.columns
labels = y.unique()#split the dataset
from sklearn.model_selection import train_test_split
X_train, test_x, y_train, test_lab = train_test_split(x,y,
                                                 test_size = 0.4,
                                                 random_state = 42)

现在我们有了正确格式的数据,我们可以开始创建决策树,这样我们就可以尝试预测不同花的分类。为此,首先要做的是从sklearn包中导入DecisionTreeClassifier。更多信息可在找到

from sklearn.tree import DecisionTreeClassifier

接下来要做的是将它应用于训练数据。为此,将分类器分配给clf,并设置max_depth = 3random_state = 42。这里,max_depth参数是树的最大深度,我们控制它以确保没有过度拟合,并且我们可以容易地跟踪最终结果是如何实现的。random_state参数确保结果可以在进一步的分析中重复。

然后,我们将算法用于训练数据:

clf = DecisionTreeClassifier(max_depth =3, random_state = 42)
clf.fit(X_train, y_train)

我们希望能够理解算法是如何表现的,使用决策树分类器的一个好处是输出直观易懂,易于可视化。

这可以通过两种方式实现:

  1. 作为树形图:
#import relevant packages
from sklearn import tree
import matplotlib.pyplot as plt#plt the figure, setting a black background
plt.figure(figsize=(30,10), facecolor ='k')#create the tree plot
a = tree.plot_tree(clf,
                   #use the feature names stored
                   feature_names = feature_names,
                   #use the class names stored
                   class_names = labels,
                   rounded = True,
                   filled = True,
                   fontsize=14)#show the plot
plt.show()

图片来自作者

2)作为基于文本的图表

#import relevant functions
from sklearn.tree import export_text#export the decision rules
tree_rules = export_text(clf,
                        feature_names = list(feature_names))#print the result
print(tree_rules)#out:
|--- PetalLengthCm <= 2.45
|   |--- class: Iris-setosa
|--- PetalLengthCm >  2.45
|   |--- PetalWidthCm <= 1.75
|   |   |--- PetalLengthCm <= 5.35
|   |   |   |--- class: Iris-versicolor
|   |   |--- PetalLengthCm >  5.35
|   |   |   |--- class: Iris-virginica
|   |--- PetalWidthCm >  1.75
|   |   |--- PetalLengthCm <= 4.85
|   |   |   |--- class: Iris-virginica
|   |   |--- PetalLengthCm >  4.85
|   |   |   |--- class: Iris-virginica

它清楚地显示了算法的表现。在这里,第一次分裂是基于花瓣长度,小于 2.45 厘米的被识别为鸢尾-刚毛鸢尾,而大于 2.45 厘米的被分类为鸢尾-海滨鸢尾。然而,对于花瓣长度大于 2.45 的那些,会发生进一步的分裂,其中两个进一步的分裂以更精确的最终分类结束。

当然,我们不仅对它在训练数据上的表现感兴趣,还对它在看不见的测试数据上的表现感兴趣。这意味着我们必须使用它从测试值中预测类,这是使用predict()方法完成的。

test_pred_decision_tree = clf.predict(test_x)

我们感兴趣的是它在真阳性(预测为真,实际为真)、假阳性(预测为真,但实际为假)、假阴性(预测为假,但实际为真)和真阴性(预测为假,实际为假)方面的表现。

一种方法是在混淆矩阵中检查结果。混淆矩阵通过在一个轴上显示预测值,在另一个轴上显示实际值,让我们直观地看到预测标签和真实标签是如何匹配的。这有助于确定我们在哪里可能得到假阳性或假阴性,从而确定算法的执行情况。

#import the relevant packages
from sklearn import metrics
import seaborn as sns
import matplotlib.pyplot as plt#get the confusion matrix
confusion_matrix = metrics.confusion_matrix(test_lab,  
                                            test_pred_decision_tree)#turn this into a dataframe
matrix_df = pd.DataFrame(confusion_matrix)#plot the result
ax = plt.axes()
sns.set(font_scale=1.3)
plt.figure(figsize=(10,7))
sns.heatmap(matrix_df, annot=True, fmt="g", ax=ax, cmap="magma")#set axis titles
ax.set_title('Confusion Matrix - Decision Tree')
ax.set_xlabel("Predicted label", fontsize =15)
ax.set_xticklabels(['']+labels)
ax.set_ylabel("True Label", fontsize=15)
ax.set_yticklabels(list(labels), rotation = 0)plt.show()

正如这里可以看到的,从看不见的数据中,只有一个值未能从 Iris-versicolor 类中预测出来,这表明总体上该算法在预测看不见的数据方面做得很好。

测量性能

然而,为了测量性能,可以产生几个度量标准。

准确度

准确度分数是真阳性和真阴性占分配的标签总数的分数,计算如下:

sum(混淆矩阵中的对角线)/ sum(混淆矩阵中的所有方框)

metrics.accuracy_score(test_lab, test_pred_decision_tree)#out: 
0.9833333333333333

精密

这告诉我们有多少我们预测在某个类中的值实际上在那个类中。本质上,这告诉我们如何在假阳性方面表现。其计算方法如下:

真阳性(对角线上的数字)/所有阳性(列和)

#get the precision score
precision = metrics.precision_score(test_lab,
                                   test_pred_decision_tree, 
                                   average=None)#turn it into a dataframe
precision_results = pd.DataFrame(precision, index=labels)#rename the results column
precision_results.rename(columns={0:'precision'}, inplace =True)precision_results#out:                   **Precision**
    Iris-setosa        1.00
Iris-versicolor        0.95
 Iris-Virginica        1.00

召回

这告诉我们每个类中有多少值被赋予了正确的标签,从而告诉 use 它相对于假阴性的表现如何。其计算方法如下:

真正数(对角线上的数字)/所有赋值(行和)

recall = metrics.recall_score(test_lab, test_pred_decision_tree, 
                              average =None)
recall_results = pd.DataFrame(recall, index= labels)recall_results.rename(columns ={0:'Recall'}, inplace =True)
recall_results#out: **Recall**
    Iris-setosa        1.00
Iris-versicolor        1.00
 Iris-Virginica        0.94

f1

这是一个精度和召回规模的加权平均值,1 为最好,0 为最差。这使用了调和平均值,因此该值更接近较小的数字,并防止在一个参数高而另一个参数低的情况下高估模型的性能。其计算方法如下:

2 (精度召回)/(精度+召回)

f1 = metrics.f1_score(test_lab, test_pred_decision_tree, average=None)
f1_results = pd.DataFrame(f1, index=labels) f1_results.rename(columns={0:'f1'}, inplace=True)
f1_results#out: **f1**
    Iris-setosa        1.00
Iris-versicolor        0.97
 Iris-Virginica        0.97

当然,我们可以通过下面这段代码在一个输出中获得所有这些指标:

print(metrics.classification_report(test_lab,
                                    test_pred_decision_tree))#out: precision    recall  f1-score   support

    Iris-setosa       1.00      1.00      1.00        23
Iris-versicolor       0.95      1.00      0.97        19
 Iris-virginica       1.00      0.94      0.97        18

       accuracy                           0.98        60
      macro avg       0.98      0.98      0.98        60
   weighted avg       0.98      0.98      0.98        60

其中对每个类的支持仅仅是测试标签中每个类中出现的次数。

特征重要性

另一个有用的特性是计算最终树输出中每个特性的重要性。这是基尼指数或熵指数(在我们的例子中是基尼)由于给定特征的分割而降低的总量。这可以从以下方面获得:

#extract importance
importance = pd.DataFrame({'feature': X_train.columns, 
'importance' : np.round(clf.feature_importances_, 3)})importance.sort_values('importance', ascending=False, inplace = True)print(importance)#out: feature  importance
2  PetalLengthCm       0.589
3   PetalWidthCm       0.411
0  SepalLengthCm       0.000
1   SepalWidthCm       0.000

这表明花瓣长度是最重要的,因为第一次划分就是以此为基础的。但是,由于只运行了一个决策树,这并不意味着其他功能不重要,只是在此决策树中不需要它们。对于一个真实的视角,决策树必须运行多次(就像在一个随机的森林中一样)并且结果是聚合的。然后,可以将它与随机变量进行比较,或者基于某个标准删除特征。

改进模型

我们可以通过改变所使用的特征来尝试改进模型,但是我们也可以通过使用 GridSearchCV 来查看它如何响应超参数的变化。这通过对训练集的集合的多次运行执行算法来对模型执行交叉验证,并告诉我们模型如何响应。

出于我们的目的,我们可以改变max_depthmin_samples_split参数,它们控制树的深度,以及分割内部节点所需的样本数。

from sklearn.model_selection import GridSearchCVtuned_parameters = [{'max_depth': [1,2,3,4,5], 
                     'min_samples_split': [2,4,6,8,10]}]scores = ['recall']for score in scores:

    print()
    print(f"Tuning hyperparameters for {score}")
    print()

    clf = GridSearchCV(
        DecisionTreeClassifier(), tuned_parameters,
        scoring = f'{score}_macro'
    )
    clf.fit(X_train, y_train)

    print("Best parameters set found on development set:")
    print()
    print(clf.best_params_)
    print()
    print("Grid scores on development set:")
    means = clf.cv_results_["mean_test_score"]
    stds = clf.cv_results_["std_test_score"]
    for mean, std, params in zip(means, stds,
                                 clf.cv_results_['params']):
        print(f"{mean:0.3f} (+/-{std*2:0.03f}) for {params}")#out:Tuning hyperparameters for recallBest parameters set found on development set:

{'max_depth': 2, 'min_samples_split': 2}

Grid scores on development set:
nan (+/-nan) for {'max_depth': 2, 'min_samples_split': 1}
0.916 (+/-0.194) for {'max_depth': 2, 'min_samples_split': 2}
0.916 (+/-0.194) for {'max_depth': 2, 'min_samples_split': 3}
0.887 (+/-0.177) for {'max_depth': 2, 'min_samples_split': 4}
0.887 (+/-0.177) for {'max_depth': 2, 'min_samples_split': 5}
nan (+/-nan) for {'max_depth': 3, 'min_samples_split': 1}
0.916 (+/-0.183) for {'max_depth': 3, 'min_samples_split': 2}
0.916 (+/-0.183) for {'max_depth': 3, 'min_samples_split': 3}
0.906 (+/-0.179) for {'max_depth': 3, 'min_samples_split': 4}
0.916 (+/-0.183) for {'max_depth': 3, 'min_samples_split': 5}
nan (+/-nan) for {'max_depth': 4, 'min_samples_split': 1}
0.916 (+/-0.194) for {'max_depth': 4, 'min_samples_split': 2}
0.905 (+/-0.179) for {'max_depth': 4, 'min_samples_split': 3}
0.905 (+/-0.179) for {'max_depth': 4, 'min_samples_split': 4}
0.905 (+/-0.179) for {'max_depth': 4, 'min_samples_split': 5}

这告诉我们最好的超参数是max_depth =2min_smaples_split =2.其他要改变的超参数可以在这里找到

从而向您展示如何在实践中实现一个简单的决策树!

使用决策树的优点是易于理解和解释,可以处理数字和分类数据,限制不良预测的影响,并且我们可以提取它们的结构来可视化。当然,也有不利的一面,如果一个类占主导地位,它们可能会创建有偏见的树,我们可能会得到过于复杂的树,导致过度拟合,数据中的小变化可能会产生非常不同的结果。但是,它们在实践中非常有用,可以与其他分类算法(如 k-最近邻或随机森林)一起使用,以帮助做出决策和理解分类是如何产生的。

如果您喜欢您所阅读的内容,并且还不是 medium 会员,请考虑通过使用下面的我的推荐代码注册来支持我和平台上的其他作者:

[## 通过我的推荐链接加入媒体-菲利普·威尔金森

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

philip-wilkinson.medium.com](https://philip-wilkinson.medium.com/membership)

或者,如果你对我的其他故事感兴趣,请随意阅读下面的一些故事:

[## UCL 数据科学协会:Python 基础

研讨会 1: Jupyter 笔记本,变量,数据类型和操作

towardsdatascience.com](/ucl-data-science-society-python-fundamentals-3fb30ec020fa) [## 面向数据科学家的面向对象编程介绍

面向对象的基础知识,适合那些以前可能没有接触过这个概念或者想知道更多的人

towardsdatascience.com](/an-introduction-to-object-oriented-programming-for-data-scientists-879106d90d89) [## 随机森林分类器简介

预测 NBA 球员的位置——我们正在看到一个真正的“无位置”联盟吗?

towardsdatascience.com](/introduction-to-random-forest-classifiers-9a3b8d8d3fa7)

序列深度相似性学习导论

原文:https://towardsdatascience.com/introduction-to-deep-similarity-learning-for-sequences-89d9c26f8392?source=collection_archive---------23-----------------------

对用于相似性分类任务的深度学习技术的深入回顾。

罗曼·维涅斯在 Unsplash 上的照片

在这篇文章中,我将阐述相似性学习的一般概念,它涉及哪些过程,以及如何对其进行总结。然后,我将把这些概述的概念应用到带有问题相似性的序列相似性检测的上下文中。

目录

  1. 相似性学习概述
  2. 文本相似性学习
  3. 源代码(PyTorch 实现)

1.深度相似性学习综述

当一个人在进行相似性学习时,总是执行相同的过程:

具有相似性学习的数据处理流水线

正如本信息图中所解释的,任何涉及相似性学习的过程都围绕着 3 个主要概念:

  1. 特征向量中数据的变换
  2. 使用距离度量对矢量进行比较
  3. 距离的分类相似不相似

1 .通过编码器的转换

在大多数深度学习任务中,模型的第一层代表有时被称为“编码阶段”:它的作用是从输入数据中提取相关特征。

对于本文的其余部分,我们将编写如下编码函数:

编码函数符号的表示

根据输入,该编码器可以采用不同的形式,其中我们发现:

  • RNN 层用于序列的编码和对比;
  • CNN 层用于时间 / 空间数据(1D 卷积也可用于序列);

通常,输入数据被这些编码器还原成一个矢量后,我们将多层全连接神经元堆叠起来对这些提取的特征进行分类。在我们的例子中,我们使用这个向量作为我们数据的降维版本来计算与其他数据的距离。用数字来表示两个向量的不同,比用两个句子来表示要容易得多。

总而言之,编码器将使用任何类型的层的组合,这些层将充分地针对其输入数据,生成数据的潜在表示,这是一种压缩的、非人类可解释的信息向量。

自动编码器的图示

纵观深度学习的历史,已经创建了多种类型的架构来生成潜在向量。其中一些是:

  • 暹罗神经网络(科赫、泽梅尔和萨拉胡特迪诺夫,2015)
  • 多模态自动编码器(西尔伯勒和拉帕塔,2015 年)

在本文中,我们将进一步探索连体神经网络。

1.b 距离计算

一旦我们有了矢量化的输入数据,我们就可以使用距离函数来比较这两个向量。最受欢迎的距离是:

  • 曼哈顿距离
  • 欧几里德距离

两种最常用距离的比较

一旦计算出距离,我们可以设置一个阈值,超过该阈值,我们认为两个数据不相似,反之亦然,认为它们相似

1.c 距离分类

但是,根据输入数据的不同,设置此阈值可能会很复杂或耗时。为简单起见,我们可以使用另一个分类器,该分类器将给定一个输入距离,如果该距离是相似或不相似物体之一则进行分类。 我的选择是使用逻辑回归分类器:在我们对应的数据中找到一个线性间隔,以学习对我们的距离进行分类的阈值。

距离分类器的描述(这里是逻辑回归)

2.文本相似性学习

2 .背景

文本是一种极其难以处理的数据结构:虽然人们常说图像是通用的,但文本是文化的。不管是用的语言还是作者特有的词汇,文本都很难理解,即使对我们来说也是如此。

然而,在某些情况下,我们希望能够测量文本之间的相似性。例如,我们可能想知道:

  • 如果根据描述,两种产品是相同的
  • 如果两个问题是同一个事情。

这最后一个问题是我将在本文中用来谈论文本相似性问题的上下文:它源于 Kaggle (Quora 问题对),由 Quora 团队作为标记为重复或不重复的问题列表发布。

从 Quora 数据集中提取的问题的比较

1.a 所述,已经为相似性学习任务创建了多种架构。对于这个任务的上下文,我们将重点关注连体递归神经网络 (Thyagarajan,2015)

2.b 连体递归神经网络架构

连体递归神经网络是一种使用 RNN 堆栈来计算输入数据的固定大小的向量表示的神经网络。

我的暹罗网络的全局视图如下:

我的连体身材

我在 Quora 数据集上使用的架构代码是一个 BiLSTMs(双向 LSTM)堆栈,如下所示:

然后,下面的编码器类使用 BiLSTM 的堆栈:

2.c 对比损失

在该模型中,需要注意两个主要组件:

  • 它的架构;
  • 它的损失。

(Hadsell,Chopra 和 LeCun,2006) 中描述,对比损失的目标是训练模型将相似的数据放在一起(即最小化它们的距离)和不相似的数据彼此远离(即最大化它们的距离)。其公式如下:

对比损失公式

这个公式非常容易理解:

  • 当两个输入相似( Y =1)时,只保留左边的项,距离为平方。因此,最小化损失意味着最小化输入之间的距离,迫使模型学习相似物体的相似表示。
  • 当两个输入不同( Y =0)时,仅保留正确的项,使用 max 函数。该 max 函数教导模型将两个输入的距离推至大于或等于余量超参数 m

损失函数图(y=0 时为橙色,y=1 时为蓝色)

3.源代码

该项目的源代码可以在 Github 的以下链接中找到:https://github.com/dimartinot/Text-Semantic-Similarity/

我在所有 3 组数据(train、val 和 test)上实现了 76%到 79%的准确率以及 0.83 的 AUC 分数。

最重要的文件是:

参考文献

Koch g .,Zemel r .和 Salakhutdinov r .,2015 年。用于一次性图像识别的连体神经网络。 ICML 深度学习工场。

西尔贝雷和拉帕塔,2015 年。用自动编码器学习基础意义表征。计算语言学协会第 52 届年会会议录,第 721–732 页。

Thyagarajan,2015 年。用于学习句子相似性的连体递归结构。

Quora。2017. Quora 问题对Kaggle

哈德塞尔,拉伊亚&乔普拉,苏米特&勒昆,扬。2006.通过学习不变映射进行降维。

为什么辍学在深度神经网络中如此有效

原文:https://towardsdatascience.com/introduction-to-dropout-to-regularize-deep-neural-network-8e9d6b1d4386?source=collection_archive---------23-----------------------

数据科学,深度学习

辍学是减少深层神经网络依赖性的一种简单方法

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

在本文中,您可以探索 dropout,正则化 vs dropout 的优缺点是什么,Dropout 方法在深度学习中如何工作,在深度学习中使用 Dropout 的有效方法是什么,以及如何在深度神经网络中实现 Dropout?

什么是深度学习的辍学生?

Dropout 意思是在神经网络中,去掉被掩盖的、明显的单元。在神经网络中,放弃是一种非常流行的克服过度拟合的方法。

深度学习框架现在越来越深入。有了这些更大的网络,我们可以实现更好的预测准确性。然而,几年前却不是这样。深度学习有一个过度适应的问题。

那时,大约在 2012 年,Hinton 在他们的论文中提出了通过在训练过程的每次迭代中随机排除特征子集来退出的想法。这个概念彻底改变了深度学习。我们在深度学习方面取得的成就有很大一部分要归功于辍学。

Clarisse CrosetUnsplash 上拍摄的照片

转正 vs 退学的利弊?

辍学之前,一个重要的研究领域是正规化。在神经网络中引入正则化方法,例如 L1 和 L2 权重罚值,始于 2000 年代中期。尽管如此,这些调整并没有完全解决过度拟合的问题。

Wager 等人在他们 2013 年的论文中指出,在学习特征权重方面,辍学正则化优于 L2 正则化。

dropout 方法在深度学习中是如何工作的?

Dropout 是一种在训练过程中丢弃随机选择的神经元的方法。他们被任意“退学”。这意味着它们对下游神经元激活的贡献在正向传递中暂时消失,任何权重刷新都不会应用于反向传递中的神经元。

你可以想象,如果神经元在训练过程中偶然退出网络,另一个神经元将不得不介入并处理对缺失神经元进行预测所需的描述。这被认为会导致网络学习各种独立的内部表示。

尽管辍学已经成为一种非常成功的技术,但其成功的原因在理论层面上还没有得到很好的理解。

来源:自己的工作

我们可以看到标准的前馈传递:权重乘以输入,加上偏差,并将其传递给激活函数。等式的第二种排列方式阐明了如果我们让学生退学会是什么样子:

  • 生成删除掩码:伯努利随机变量(示例 1.0 *(NP . random . random((size))> p)
  • 使用屏蔽来断开一些神经元的输入。
  • 利用这个新的层来增加权重和偏差
  • 最后,使用激活功能。

所有的权重在潜在的指数数量的网络上共享,并且在反向传播期间,只有“稀疏网络”的权重将被刷新。

深度学习中使用 Dropout 的有效方法有哪些?

●根据(Srivastava,2013) Dropout,神经网络可以与随机梯度下降一起训练。对于每个迷你批次中的每个训练案例,独立完成退出。辍学可以利用任何激活功能,他们的实验与逻辑,双曲正切,矫正线性单位产生了可比的结果,但需要不同的训练时间,矫正线性单位是最快的训练。

● Kingma 等人,2015 年推荐的辍学要求指出辍学率,即放弃一个神经元的概率。辍学率通常利用网格搜索进行优化。此外,作为贝叶斯正则化的一个特殊例子,变分丢失是高斯丢失的一个精致的翻译。这种方法允许我们调整辍学率,并且原则上可以用于为每一层、神经元甚至权重设置单独的辍学率。

●由(Ba 等人,2013)进行的另一个实验,增加深度学习算法中的隐藏单元的数量。辍学正则化的一个值得注意的事情是,它实现了大量隐藏单元的相当普遍的性能,因为所有单元都有相等的概率被排除。

深度神经网络如何实现 dropout?

●通常,利用 20%-50%的神经元的小丢弃值,其中 20%提供了一个很好的起点。太低的概率具有不显著的影响,并且在系统的欠学习中价值太高的结果。

●当 dropout 在一个更大的网络中使用时,你可能会显示出改进执行的迹象,允许模型有更多的机会学习免费的描述。

●在接近(明显的)时使用叉头,就像隐蔽单元一样。在系统的每一层利用辍学已经证明了巨大的成果。

参考

  • n . Srivastava,g . hint on,a . krijevsky,Sutskever,I .和 r . Salakhutdinov,2014 年。辍学:防止神经网络过度拟合的简单方法。《机器学习研究杂志》,第 15 卷第 1 期,第 1929-1958 页。

  • hint on,G.E .,n . Srivastava,Krizhevsky,a .,Sutskever,I .和 Salakhutdinov,R.R .,2012 年。通过防止特征检测器的共同适应来改进神经网络。arXiv 预印本 arXiv:1207.0580。

●韦杰,王,梁,2013。作为适应性调整的辍学训练。神经信息处理系统的进展(第 351-359 页)。

●北卡罗来纳州斯利瓦斯塔瓦,2013 年。用辍学改进神经网络。多伦多大学,182(566),第 7 页

●金玛博士、t .萨利曼斯和 m .韦林,2015 年。变分丢失和局部重新参数化技巧。神经信息处理系统进展(第 2575-2583 页)。

巴和弗雷分别于 2013 年出版。用于训练深度神经网络的自适应丢失。神经信息处理系统进展(第 3084-3092 页)。

现在,把你的想法放到 Twitter、Linkedin 和 Github 上吧!!

同意或不同意 Saurav Singla 的观点和例子?想告诉我们你的故事吗?

推文 @SauravSingla_08 ,评论 Saurav_Singla ,明星 SauravSingla 马上!

DVC 介绍:机器学习项目的数据版本控制工具

原文:https://towardsdatascience.com/introduction-to-dvc-data-version-control-tool-for-machine-learning-projects-7cb49c229fe0?source=collection_archive---------20-----------------------

就像 Git 一样,但是有数据!

照片由弗兰基·查马基Unsplash 上拍摄

动机

作为一名数据科学家,您可能会尝试不同的代码、数据和模型组合。因此,对您的代码、数据和模型进行版本化是非常重要的,这样您就可以重现过去的实验。

但是您如何对您的代码、数据和模型进行版本化呢?

Git 是控制代码版本的一个很好的平台,但是对数据和模型进行版本控制并不理想,原因有二:

  • GitHub 有一个 100MB 的严格文件限制,所以上传一个中等大小的二进制文件很容易超过这个限制。
  • 用 GitHub 比较不同版本数据的变化很乱。我曾经在使用后手动接受超过 100 次的数据更改,这是一种痛苦。

如果你可以将数据存储在你最喜欢的存储服务中,比如亚马逊 S3、谷歌驱动、谷歌云存储或你自己的本地机器,同时还能对你的数据进行版本控制,这不是很好吗?这正是 DVC 派上用场的时候。

什么是 DVC?

DVC 是一个用于数据版本控制的系统。它本质上类似于 Git,但用于数据。有了 DVC,你可以把不同版本数据的信息保存在 Git 中,而把原始数据保存在其他地方。

更好的是,DVC 语法就像 Git!如果你已经知道 Git,学习 DVC 是轻而易举的事。

为了理解如何使用 DVC,让我们从一个例子开始。我将使用我的存储库作为本文的例子。您可以通过克隆存储库来跟进。

从用 pip 安装软件包开始

pip install dvc

或与康达

conda install -c conda-forge dvc

在此找到安装 DVC 的更多方法的说明。

开始

安装好 DVC 后,在 Git 项目中,通过运行

dvc init

.dvc/.gitignore.dvc/config被创建。提交此更改

git commit -m "Initialize DVC"

这是我的数据目录的结构

data
├── processed
│   ├── test_text.txt
│   ├── train_label.txt
│   ├── train_text.txt
│   ├── val_label.txt
│   └── val_text.txt
└── raw
    ├── mex20_test_full.txt
    ├── mex20_train_labels.txt
    ├── mex20_train.txt
    ├── mex20_val_labels.txt
    └── mex20_val.txt

要开始跟踪一个文件或目录,使用dvc add

要跟踪数据目录,请使用

dvc add data

添加的文件或目录的信息将存储在名为data.dvc.dvc文件中。这是一个小的文本文件,它存储如何访问原始数据的信息,但不存储原始数据本身。

因为这个文本文件很小,所以可以像源代码一样用 Git 进行版本控制。

现在只需像提交源代码一样提交dvc文件。确保在之前将 [data](https://github.com/khuyentran1401/Machine-learning-pipeline/blob/master/.gitignore) 添加到 [.gitignore](https://github.com/khuyentran1401/Machine-learning-pipeline/blob/master/.gitignore)中,以避免提交数据。

git add data.dvc
git commit -m "add data"

远程存储数据

酷!现在我们创建了一个文件来存储关于原始数据的信息。下一步是确定在哪里存储数据

就像我们如何使用git add remote来存储远程存储库的 URL 一样,我们也想使用dvc remote add来存储远程存储库的位置。

DVC 允许我们在谷歌驱动、亚马逊 S3、Azure Blob 存储、谷歌云存储、阿里云 OSS、SSH、HDFS 和 HTTP 上存储我们的数据。既然我假设每个人都有 Google Drive,那么让我们来学习如何在 Google Drive 上存储我们的数据

首先在 Google Drive 上创建一个文件夹

一旦我们创建了一个文件夹,我们的链接将是这样的https://drive . Google . com/drive/folders/1 ynnbbt-4j 0 IDA 0 ekyqqzzbc 93 juuubvh

只需添加到 DVC 的链接来存储远程存储的位置

dvc remote add -d remote gdrive://1ynNBbT-4J0ida0eKYQqZZbC93juUUbVH

-d代表默认。关于存储器的信息将保存在.dvc/config

[core]remote = remote['remote "remote"']url = gdrive://1ynNBbT-4J0ida0eKYQqZZbC93juUUbVH

现在只需提交配置文件

git commit .dvc/config -m "Configure remote storage"

并将数据推送到 Google Drive

dvc push

就是这样!现在所有的数据都被推送到 Google Drive 。查看[dvc remote add](https://dvc.org/doc/command-reference/remote/add)了解在其他存储服务中存储数据的更多方法。

要将我们已经提交的变更推送到我们的远程存储库,请键入

git push origin <branch>

获取数据

您的数据存储在安全的地方。但是现在你或者你的队友想要访问这些数据,你或者你的队友应该怎么做?

它是直接向前的。就像平常一样使用git pull来改变代码。现在您的本地目录中已经有了.dvc文件。

要检索数据,只需输入

dvc pull

从远程存储器中提取数据。就是这样!

如果您按照教程进行操作,并且您的本地机器中仍然有data目录,请删除它,看看dvc pull如何从远程存储中检索您的数据。

更改

要进行更改,请使用

dvc add data
git commit data.dvc -m 'Data updates'
dvc push
git push origin <branch>

它是直截了当的,不是吗?

在不同版本之间切换

使用 DVC 的全部意义在于,我们可以在不同版本的数据之间切换。那么我们到底该怎么做呢?同样,就像我们用 Git 在不同版本的代码之间切换一样,使用dvc checkout在不同版本的数据之间切换

git checkout <...>
dvc checkout

例如,如果我们想切换到以前版本的数据,请键入

git checkout HEAD^1 data.dvc
dvc checkout

现在,当数据恢复到以前的版本时,使用

git commit data.dvc -m "revert to previous version"

保存更改。

基本上,我们用git chechout切换到我们代码的另一个版本。dvc checkout.dvc文件和目录的相应版本从.dvc/cache恢复到工作区。

很酷不是吗?

结论

恭喜你!您刚刚学习了如何使用 DVC 控制不同版本的数据!如果您仍然犹豫是否将 DVC 用于您的数据科学项目,那么是时候尝试一下了。语法类似于 Git。使用:

  • dvc add跟踪文件
  • dvc push将数据推送到远程存储器
  • dvc pull从远程存储器中提取数据
  • dvc checkout下载其他版本的数据

您和您的队友将会很高兴使用上面的简单命令行将您的数据更改保存在 Git 中,同时将您的数据存储在您最喜欢的存储服务中!

请在这里随意使用本文中的代码

[## khuyentran 1401/机器学习管道

本报告提供了一个如何将 MLflow 和 Hydra 整合到您的机器学习项目中的示例…

github.com](https://github.com/khuyentran1401/Machine-learning-pipeline)

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 T2 Twitter 上与我联系。

这个回购如果你想检查我写的所有文章的代码。在 Medium 上关注我,了解我的最新数据科学文章,例如:

[## 如何用 Faker 创建假数据

您可以收集数据或创建自己的数据

towardsdatascience.com](/how-to-create-fake-data-with-faker-a835e5b7a9d9) [## 如何在数据科学项目中利用 Visual Studio 代码

直到发现一种新的有效方法,我们才意识到我们是多么低效

towardsdatascience.com](/how-to-leverage-visual-studio-code-for-your-data-science-projects-7078b70a72f0) [## VSCode 中数据科学家的 4 大代码查看器

让 YAML、JSON、CSV 和 Jupyter Notebook 为你工作,而不是与你作对

towardsdatascience.com](/top-4-code-viewers-for-data-scientist-in-vscode-e275e492350d) [## Hydra.cc 简介:配置数据科学项目的强大框架

尝试不同的参数和模型,而无需花费数小时来修改代码!

towardsdatascience.com](/introduction-to-hydra-cc-a-powerful-framework-to-configure-your-data-science-projects-ed65713a53c6) [## 模式介绍:验证数据的 Python 库

验证您的数据变得更加复杂!

towardsdatascience.com](/introduction-to-schema-a-python-libary-to-validate-your-data-c6d99e06d56a)

编码器-解码器模型简介— ELI5 路

原文:https://towardsdatascience.com/introduction-to-encoder-decoder-models-eli5-way-2eef9bbf79cb?source=collection_archive---------9-----------------------

ELI5 项目机器学习

Unsplash 上由 Kouji 鹤拍摄的照片

大家好,欢迎来到我的博客“编解码模型介绍——Eli 5 Way”。我叫 Niranjan Kumar ,是好事达印度公司的高级数据科学顾问。

在本文中,我们将讨论编码器-解码器模型的基本概念及其在一些任务中的应用,如语言建模、图像字幕、文本推导和机器音译。

引用注: 本文的内容和结构是基于我对四分之一实验室深度学习讲座的理解——pad hai

在我们讨论编码器-解码器模型的概念之前,我们先回顾一下语言建模的任务。

语言建模—概述

语言建模是预测下一个单词/字母的任务。与 FNN 和 CNN 不同,在序列建模中,当前输出依赖于先前输入,并且输入的长度不固定。

给定“t-1”个单词,我们感兴趣的是基于先前的单词或信息来预测 iᵗʰ单词。让我们看看如何使用递归神经网络解决语言建模问题。

语言建模— RNN

我们来看看 WhatsApp 中自动完成的问题。当你打开键盘输入时,你注意到字母 I 是信息第一个字符的建议。在这个问题中,每当我们键入一个字符,网络就试图根据先前键入的字符来预测下一个可能的字符。

该函数的输入用橙色表示,并表示为一个 x ₜ.与输入相关联的权重使用向量 U 来表示,并且单词的隐藏表示( s) 作为先前时间步长的输出和当前输入以及偏差的函数来计算。隐藏表示的输出( s) 由下面的等式给出,

一旦我们计算了输入的隐藏表示,来自网络的最终输出( y ₜ)是隐藏表示的 softmax 函数(表示为 o ),以及与其相关联的权重和偏差。

编码器-解码器模型—语言建模

在这一节中,我们将看到我们是如何在不知道的情况下,在语言建模的问题中使用编码器-解码器模型的。

在语言建模中,我们感兴趣的是根据以前的信息找到 iᵗʰ词的概率分布。

编码器型号

  • 第一个时间步长的 RNN 输出作为输入与原始输入一起输入到下一个时间步长。
  • 在每个时间步长,单词的隐藏表示( s ₜ₋₁ ) 被计算为前一时间步长的输出和当前输入以及偏置的函数。
  • 最终隐藏状态 vector(sₜ)包含来自先前隐藏表示和先前输入的所有编码信息。
  • 这里,递归神经网络充当了一个编码器

解码器模型

  • 一旦我们将编码的向量传递到输出层,输出层就解码成下一个可能单词的概率分布。
  • 输出层是一个 softmax 函数,它将隐藏状态表示和与之关联的权重以及偏差作为输入。
  • 由于输出层包含了线性变换和偏置运算,因此可以称为简单的前馈神经网络。
  • 前馈神经网络充当解码器。

编码器-解码器应用

在这一节中,我们将讨论编码器-解码器模型的一些应用

图像字幕

图像字幕是根据图像上显示的内容自动生成字幕的任务。

  • 在图像字幕中,我们将通过卷积神经网络传递图像,并以特征表示向量的形式从图像中提取特征。
  • 预处理后的特征表示向量通过 RNN 或 LSTM 生成字幕。

  • CNN 用于对图像进行编码
  • 然后,RNN 被用来从嵌入的句子中解码

文本蕴涵

文本蕴涵是确定一段给定文本 T 是否包含另一段称为“假设”的文本的任务。

举个例子,

输入:外面下雨。

输出:地面潮湿。

在这个问题中,输入和输出都是字符序列。因此,编码器和解码器网络都是 RNN 或 LSTM。

机器音译

音译——“用另一种语言或文字书写同一个单词”。翻译会告诉你另一种语言中单词的意思,而音译不会告诉你单词的意思,但会帮你发音。

输入:印度

输出 : इंडिया

编码器

  • 输入的每个字符都作为输入被输入到 RNN,方法是将字符转换成一个独热向量表示。
  • 在编码器的最后一个时间步长,所有先前输入的最终隐藏表示将作为输入传递给解码器。

解码器

  • 解码器模型可以是 RNN 或 LSTM 网络,它将对状态表示向量进行解码,并给出每个字符的概率分布。
  • softmax 函数用于生成每个字符的概率分布向量。这又有助于生成完整的音译单词。

从这里去哪里?

如果想用 Keras & Tensorflow 2.0 (Python 或 R)学习更多关于神经网络的知识。查看来自 Starttechacademy 的 Abhishek 和 Pukhraj 的人工神经网络。他们以一种简单化的方式解释了深度学习的基础。

推荐阅读—Eli 5 项目机器学习

[## 长短期记忆和门控循环单位的解释——Eli 5 方式

在这篇文章中,我们将学习 LSTM 和格鲁工作背后的直觉

towardsdatascience.com](/long-short-term-memory-and-gated-recurrent-units-explained-eli5-way-eff3d44f50dd) [## 递归神经网络(RNN)解释 ELI5 方式

使用 RNN 的序列标记和序列分类

towardsdatascience.com](/recurrent-neural-networks-rnn-explained-the-eli5-way-3956887e8b75) [## 理解卷积神经网络 ELI5 方法

了解卷积运算和 CNN 的

towardsdatascience.com](/understanding-convolution-neural-networks-the-eli5-way-785330cd1fb7)

结论

在这篇文章中,我们通过 RNN 和 FNN 讨论了如何在语言建模的任务中使用基本的编码器-解码器模型。之后,我们讨论了编码器-解码器模型在解决一些复杂任务中的应用,如机器音译、文本蕴涵。

在我的下一篇文章中,我们将讨论注意力机制。因此,请确保您在 Medium 上跟随我,以便在它下降时得到通知。

直到那时,和平:)

NK。

作者简介

Niranjan Kumar 是好事达印度公司的高级数据科学顾问。他对深度学习和人工智能充满热情。除了在媒体上写作,他还作为自由数据科学作家为 Marktechpost.com 写作。点击查看他的文章

你可以在 LinkedIn 上与他联系,或者在 Twitter 上关注他,了解关于深度学习和机器学习的最新文章。

免责声明 —这篇文章中可能有一些相关资源的附属链接。你可以以尽可能低的价格购买捆绑包。如果你购买这门课程,我会收到一小笔佣金。

参考文献:

  1. 深度学习—帕德海
  2. 理解翻译与音译
  3. 深度学习(CS7015)

集成学习简介

原文:https://towardsdatascience.com/introduction-to-ensemble-learning-27af286ac470?source=collection_archive---------24-----------------------

装袋和增压技术概述

图:团结成长理念

“弱者团结起来也变得强大。” —弗里德里希·冯·席勒

这是集合方法背后的基本思想。弱学习器,也称为基础模型,被有策略地组合在一起,形成一个强学习器,称为集成模型。集成模型使用多种学习算法来解决特定的分类/回归问题,该问题不能由它的任何组成学习器单独有效地学习。

组合弱学习器的不同技术在如何聚集这些弱学习器中的每一个的输出以获得最终输出方面有所不同。我们将研究两种实现集合模型的流行技术:

  1. 制袋材料
  2. 助推

在继续之前,让我们直观地理解这些技术对模型性能的影响。一个好的机器学习算法理论上被期望在学习训练数据时实现低偏差和低方差。然而,实现两者是不可能的,这被称为偏差-方差权衡。这两种误差源(偏差/方差)都妨碍了模型对训练数据进行归纳,从而无法对看不见的数据进行有效处理。

偏差是由算法做出的错误假设引起的误差。这会导致模型错过训练数据中的特征和目标输出之间的关系(欠拟合)。

方差是由对训练数据中微小波动的敏感性引起的误差。这将导致模型从训练数据中学习噪声(过拟合)。

集合方法用于根据基础模型的弱点来减少偏差或方差。根据我们试图减少的误差源,选择不同的组合技术。

打包(引导汇总)

Bagging 涉及在不同的训练数据集上并行训练弱学习模型,并使用某种平均方法组合这些基础模型的结果。

1。采样

当我说多组训练数据时,你肯定在想这将需要大量的训练数据来馈送多个数据饥渴的深度学习网络。但我们需要的只是一组训练数据的多个样本。这可以使用一种叫做自举的技术来实现。

Bootstrapping 是一种从原始数据中进行采样的统计方法,其中样本几乎是独立的,并且代表原始数据分布(大约独立于原始数据分布,并且与原始数据分布相同)。

2。培训

假设我们从大小为 N 的原始数据集生成 L 个大小为 N 的样本,并进行替换。然后,我们在通过自举生成的这些 L 个样本中的每一个样本上训练 L 个同质基础模型。

3。聚集

现在我们有了来自 L 基本模型的预测,我们需要使用某种平均方法来汇总这些预测。在回归问题的情况下,我们可以找到基础模型预测的字面平均值,以此来弥补集合模型的预测。

Y = ( y1+y2+y3+…+yL ) / L

对于分类问题,如果我们让基本模型返回类别标签,那么一种聚合方式是将每个弱分类器返回的类别视为投票,并且具有最高票数的类别由集成模型返回— 硬投票

Y = max ( y1,y2,y3,…,yL)

另一方面,如果我们有返回每个类别概率的基础模型,那么一种方法是从所有基础模型中找到每个类别预测的平均值,并且具有最高平均概率的类别由集合模型返回— 软投票

Y = max [ P(y1),P(y2),P(y3),…,P(yL) ]

什么时候用什么时候不用装袋?

  • 装袋方法主要集中在减少方差,不影响偏倚。因此,当基础模型具有高方差和低偏差时,选择这种技术,这通常是对于复杂数据具有高自由度的模型的情况(例如:深度决策树)。
  • Bagging 不适用于具有高偏差和低方差的模型,因为组合不太适合训练数据(欠拟合)的基础模型的结果在聚合时不会改变结果。
  • 具有高自由度(复杂数据)的模型需要更多的训练时间。由于基本模型是并行训练的,训练每个基本模型所花费的时间相当于训练它们中的任何一个,使得 bagging 成为集成方法的一个好选择。

增压

Boosting 涉及逐步训练弱学习者,每次,模型直观地将其努力集中在它的前任难以学习的观察上。

基本模型以非常自适应的方式组合以形成集合模型。集合模型是组成基本模型的加权和。主要有两种流行的元算法,它们与弱学习者的聚集方式有着明显的不同。它们都旨在以迭代方式优化集合模型。

  1. 自适应增强(Adaboost)
  2. 梯度推进(阿达格拉德)

自适应增压

每个基础学习者更新数据集中每个观察值的权重。对 L 学习器重复下面的步骤,其中每个基本模型试图使用权重来纠正其前一个模型的错误。

(I)在弱学习者被训练之后,数据集中的每个数据点被分配一个表示分类准确性的权重。即,具有较高准确度的数据点将被分配较低的权重,反之亦然。

(ii)这个加权数据集然后被用作下一个弱学习者的训练集。该学习者将直观地更加关注具有较高权重的数据点,并尝试对它们进行正确分类。

(iii)对于错误分类的样本,结果数据集被重新加权,并被用作下一个学习者的输入。

梯度增强

每个基础学习器更新数据集中的观察值。像在 Adaboost 中,下一个模型取决于前一个模型的误差。顾名思义,我们使用梯度下降顺序组合弱学习者。每个基本模型都试图将数据拟合到与我们迄今为止从集合模型获得的误差梯度相反的方向。

西ᵢ =西ᵢ-₁ — (α * ∇东ᵢ-₁)

W ᵢ是基本模型 I 的权重,α是步长,E ᵢ-₁是基本模型(i-1)的误差。

对于数据集中的每个观察值,我们计算观察值和预测值之间的差异。这些值被称为伪残差。它们指示下一个学习者应该更新的方向,以获得正确的值。

  1. 最初,我们将伪残差设置为已知目标的平均值。
  2. 对于每个弱学习算法 I,我们预测在(i-1)中获得的伪残差。
  3. 由此获得的伪残差是后续弱学习器的目标。

伪残差= Yᵗᵃʳᵍᵉᵗ - Yᵖʳᵉᵈ

什么时候用什么时候不用升压?

  • 一般使用低方差高偏差的模型,自由度少(例如:浅层决策树)。
  • 与并行训练模型的 bagging 不同,这里的模型是顺序训练的。依次训练几个复杂的模型会使计算变得昂贵。

参考文献

[1]伊恩·古德菲勒、约舒阿·本吉奥、亚伦·库维尔——深度学习。

[2]约瑟夫·罗卡,集合方法:装袋,助推,堆垛

[3]使用拍卖创建的数字。

如果你想过来打个招呼,请通过LinkedIn|Twitter|Github与我联系。

进化策略简介

原文:https://towardsdatascience.com/introduction-to-evolution-strategy-1b78b9d48385?source=collection_archive---------27-----------------------

用进化策略训练无反向传播神经网络

在这篇文章中,我们将学习在 MNIST 手写数字数据集上使用 Python 中的进化策略从头开始训练一个无反向传播的神经网络。这个简单的实现将帮助我们更好地理解这个概念,并将其应用于其他合适的设置。我们开始吧!

目录
1。数值优化
2。进化策略
3。普通实现
4。Python 从头实现
5。结尾注释

数值优化

几乎所有的机器学习算法都可以归结为一个优化问题。在 ML 算法中,我们更新模型的参数以最小化损失。例如,每个监督学习算法都可以写成,θ_ estimate = arg min𝔼[l(y,f(x,θ))],其中 x 和 y 分别表示特征和目标,θ表示模型参数,f 表示我们试图建模的函数,l 表示损失函数,它衡量我们的拟合程度。梯度下降算法也称为最速下降法,已经证明在大多数情况下可以很好地解决这类问题。这是一种求可微函数局部极小值的一阶迭代算法。我们采取与当前点的损失函数的梯度的负值成比例的步长,即θ_new = θ_old — α*∇ L(y,f(x,θ_old))。牛顿法是另一种二阶迭代法,它以较少的迭代次数收敛,但由于需要计算损失函数(海森矩阵)的二阶导数的倒数,计算量很大,即θ_new = θ_old — [∇ L(y,f(x,θ_old))]^(-1) * ∇ L(y,f(x,θ_old))。我们正在使用梯度搜索参数,因为我们相信它将引导我们朝着减少损失的方向前进。但是我们能在不计算任何梯度的情况下搜索最优参数吗?其实解决这个问题的方法有很多!有许多不同的无导数优化算法(也称为黑盒优化)。

来源:谷歌图片

进化策略

梯度下降不一定总能解决我们的问题。为什么?简而言之,答案是局部最优。例如,在强化学习的稀疏奖励场景中,代理在一集结束时收到奖励,就像在国际象棋中,结束奖励分别为赢或输游戏的+1 或-1。万一我们输掉了比赛,我们就不知道我们是玩得可怕还是只是犯了一个小错误。回报梯度信号很大程度上是无信息的,会让我们陷入困境。我们可以求助于诸如进化策略(es)之类的无导数技术,而不是使用噪声梯度来更新我们的参数。在这种情况下,以及在我们不知道目标函数的精确解析形式或不能直接计算梯度的情况下,ES 工作得很好。

在 OpenAI 的这篇论文中,他们展示了 ES 在分布式计算环境中更容易实现和扩展,它在稀疏回报的情况下不受影响,并且具有更少的超参数。此外,他们发现,与传统的强化学习算法相比,专家系统发现了更多样的策略。

ES 是一种受自然启发的优化方法,它使用随机突变、重组和选择来应用于包含候选解的个体群体,以便迭代地进化出更好的解。它对于非线性或非凸的连续优化问题非常有用。

在专家系统中,我们不太关心函数及其与输入或参数的关系。数百万个数字(模型的参数)进入算法,并且它吐出 1 个值(例如,监督设置中的损失;强化学习情况下的奖励)。我们试图找到这些数字的最佳集合,为我们的优化问题返回好的值。我们正在优化一个关于参数θ的函数 J(θ),只是通过对它求值,而不对 J 的结构做任何假设,因此命名为“黑盒优化”。下面就来深挖一下实现细节吧!

普通实现

首先,我们随机生成参数,并对其进行调整,使参数稍微工作得更好。数学上,在每一步我们取一个参数向量θ,并通过用高斯噪声抖动θ来产生一群,比如说 100 个稍微不同的参数向量θ₁,θ₂…θ₁₀₀。然后,我们通过运行模型独立评估 100 个候选中的每一个,并基于输出值评估损失或目标函数。然后,我们选择前 N 个性能最佳的精英参数,N 可以是 10,取这些参数的平均值,称之为我们迄今为止的最佳参数。然后,我们重复上述过程,通过将高斯噪声添加到迄今为止获得的最佳参数中,再次生成 100 个不同的参数。

从自然选择的角度考虑,我们正在随机创建一个参数(物种)群体,并根据我们的目标函数(也称为适应度函数)选择表现良好的顶级参数。然后,我们通过取它们的平均值来结合这些参数的最佳质量(这是一种粗略的方法,但仍然有效!)并称之为我们的最佳参数。然后,我们通过添加随机噪声使该参数突变来重建种群,并重复整个过程直到收敛。

来源:改编自 Lur 专题百科全书,通过维基共享资源

伪码:

  1. 使用高斯分布随机初始化最佳参数
  2. 循环直至收敛:
    —通过将高斯噪声添加到最佳参数
    来创建参数θ₁,θ₂…θ₁₀₀群体——评估所有参数的目标函数并选择前 n 个最佳性能参数(精英参数)
    —最佳参数=平均值(前 n 个精英参数)
    —在每次迭代结束时以某个因子衰减噪声(在开始时,更多的噪声将有助于我们更好地探索,但是当我们到达收敛点时,我们希望噪声最小以便不偏离)

来源:https://en.wikipedia.org/wiki/CMA-ES。图片基于尼古拉·汉森和其他人的工作。
球形优化景观用 f 值相等的实线描绘。在这个简单的例子中,群体(点)在几次迭代后集中于全局最优。

从头开始 Python 实现

让我们通过 Python 中的一个简单例子来更好地理解。我试图添加一些与数值稳定性相关的细节。请看评论!我们将从加载所需的库和 MNIST 手写数字数据集开始。

# Importing all the required libraries
import numpy as np
import matplotlib.pyplot as plt
import tqdm
import pickle
import warnings
warnings.filterwarnings(‘ignore’)
from keras.datasets import mnist# Machine Epsilon (needed to calculate logarithms)
eps = np.finfo(np.float64).eps# Loading MNIST dataset
(x_train, y_train), (x_test, y_test) = mnist.load_data()# x contains the images (features to our model)
# y contains the labels 0 to 9# Normalizing the inputs between 0 and 1
x_train = x_train/255.
x_test = x_test/255.# Flattening the image as we are using 
# dense neural networks
x_train = x_train.reshape( -1, x_train.shape[1]*x_train.shape[2])
x_test = x_test.reshape( -1, x_test.shape[1]*x_test.shape[2])# Converting to one-hot representation
identity_matrix = np.eye(10) 
y_train = identity_matrix[y_train]
y_test = identity_matrix[y_test]# Plotting the images
fig, ax = plt.subplots(2,5)
for i, ax in enumerate(ax.flatten()):
 im_idx = np.argwhere(y_train == i)[0]
 plottable_image = np.reshape(x_train[im_idx], (28, 28))
 ax.set_axis_off()
 ax.imshow(plottable_image, cmap=’gray’)

plt.savefig(‘mnist.jpg’)

这是图像的样子,

MNIST 手写数字数据集样本图像

我们将从定义我们的模型开始,这将是一个只有正向传递的单层神经网络。

def soft_max(x):'''
 Arguments: numpy array

 Returns: numpy array after applying 
 softmax function to each
 element '''

 # Subtracting max of x from each element of x for numerical
 # stability as this results in the largest argument to 
 # exp being 0, ruling out the possibility of overflow
 # Read more about it at :
 # [https://www.deeplearningbook.org/contents/numerical.html](https://www.deeplearningbook.org/contents/numerical.html)

 e_x = np.exp(x — np.max(x))

 return e_x /e_x.sum()class Model():'''
 Single layer Neural Network

'''

 def __init__(self, input_shape, n_classes):

 # Number of output classes
 self.n_classes = n_classes

 # Parameters/Weights of our network which we will be updating
 self.weights = np.random.randn(input_shape, n_classes)

 def forward(self,x):

 '''
 Arguments: numpy array containing the features,
 expected shape of input array is
 (batch size, number of features)

 Returns: numpy array containing the probability,
 expected shape of output array is
 (batch size, number of classes)

 '''

 # Multiplying weights with inputs
 x = np.dot(x,self.weights)

 # Applying softmax function on each row
 x = np.apply_along_axis(soft_max, 1, x)

 return x

 def __call__(self,x):

 '''
 This dunder function
 enables your model to be callable

 When the model is called using model(x),
 forward method of the model is called internally

 '''

 return self.forward(x)

 def evaluate(self, x, y, weights = None):

 '''Arguments : x — numpy array of shape (batch size,number of features),
 y — numpy array of shape (batch size,number of classes),
 weights — numpy array containing the parameters of the model

 Returns : Scalar containing the mean of the categorical cross-entropy loss
 of the batch'''

 if weights is not None:

 self.weights = weights

 # Calculating the negative of cross-entropy loss (since
 # we are maximizing this score)
 # Adding a small value called epsilon 
 # to prevent -inf in the output

 log_predicted_y = np.log(self.forward(x) + eps)

 return (log_predicted_y*y).mean()

我们现在将定义我们的函数,它将一个模型作为输入并更新它的参数。

def optimize(model,x,y,
 top_n = 5, n_pop = 20, n_iter = 10,
 sigma_error = 1, error_weight = 1, decay_rate = 0.95,
 min_error_weight = 0.01 ):

 '''
 Arguments : model — Model object(single layer neural network here),
 x — numpy array of shape (batch size, number of features),
 y — numpy array of shape (batch size, number of classes),
 top_n — Number of elite parameters to consider for calculating the
 best parameter by taking mean
 n_pop — Population size of the parameters
 n_iter — Number of iteration 
 sigma_error — The standard deviation of errors while creating 
 population from best parameter
 error_weight — Contribution of error for considering new population
 decay_rate — Rate at which the weight of the error will reduce after 
 each iteration, so that we don’t deviate away at the 
 point of convergence. It controls the balance between 
 exploration and exploitation

 Returns : Model object with updated parameters/weights

 '''

 # Model weights have been randomly initialized at first
 best_weights = model.weights

 for i in range(n_iter):

 # Generating the population of parameters
 pop_weights = [best_weights + error_weight*sigma_error* \
 np.random.randn(*model.weights.shape)

 for i in range(n_pop)]

 # Evaluating the population of parameters
 evaluation_values = [model.evaluate(x,y,weight) for weight in pop_weights]

 # Sorting based on evaluation score
 weight_eval_list = zip(evaluation_values, pop_weights)

 weight_eval_list = sorted(weight_eval_list, key = lambda x: x[0], reverse = True)

 evaluation_values, pop_weights = zip(*weight_eval_list)

 # Taking the mean of the elite parameters
 best_weights = np.stack(pop_weights[:top_n], axis=0).mean(axis=0)

 #Decaying the weight
 error_weight = max(error_weight*decay_rate, min_error_weight)

 model.weights = best_weights

 return model# Instantiating our model object
model = Model(input_shape= x_train.shape[-1], n_classes= 10)print(“Evaluation on training data”, model.evaluate(x_train, y_train))# Running it for 200 steps
for i in tqdm.tqdm(range(200)):

 model = optimize(model, 
 x_train,
 y_train, 
 top_n = 10, 
 n_pop = 100,
 n_iter = 1)

 print(“Test data cross-entropy loss: “, -1*model.evaluate(x_test, y_test))
 print(“Test Accuracy: “,(np.argmax(model(x_test),axis=1) == y_test).mean())

# Saving the model for later use
with open(‘model.pickle’,’wb’) as f:
 pickle.dump(model,f)

结果:经过 200 次迭代训练后,测试准确率约为 85%,交叉熵损失约为 0.28。这相当于用反向传播训练的单层神经网络。注意,这里我们甚至没有使用 decay,因为 n_iter 设置为 1。

结尾注释

ES 实现起来非常简单,不需要梯度。仅仅通过将噪声注入到我们的参数中,我们就能够搜索参数空间。尽管为了便于理解,我们已经解决了一个监督问题,但它更适合强化学习场景,在这种场景中,人们必须通过采样来估计预期回报的梯度。

希望你喜欢阅读这篇文章!

更多的技术博客也可以查看我的网站:深挖 ML

参考资料和进一步阅读:

OpenAI 博文

奥托罗的博客

莉莲的博客

进化算法简介

原文:https://towardsdatascience.com/introduction-to-evolutionary-algorithms-1278f335ead6?source=collection_archive---------12-----------------------

关于如何用 Python 编写进化算法来解决优化任务的实用介绍。

Johannes Plenio 在 Unsplash 上拍摄的照片

介绍

自然选择进化是一种科学理论,旨在解释自然系统如何随着时间的推移进化成更复杂的系统。自然选择的进化需要四个主要因素:

  • 繁殖:生物需要能够繁殖和产生后代,以延续其物种。
  • 遗传:后代在某种程度上需要像他们的父母。
  • 变异:群体中的个体需要彼此不同。
  • 适应度的变化:个体之间的差异应该导致其繁殖成功(适应度)的变化。

在进化算法中,一个适应值可以被用来作为一个向导来指示我们离一个解决方案有多近(例如,值越高,我们离我们想要的目标就越近)。通过将群体中具有相似适合度的所有元素更紧密地组合在一起,并将所有不相似的元素进一步分开,我们可以构建一个适合度景观(图 1)。进化算法面临的一个主要问题是在适应度范围内存在局部最优。事实上,局部最优可能会误导我们的算法,使其达不到我们期望的全局最大值,而偏向于次优解。

图 1:健身景观示例[1]

使用变异操作符,如交叉和变异,就有可能跳过一个山谷,达到我们想要的目标。

如果使用突变,我们允许组成个体的随机元素发生突变的小概率。作为一个例子,如果我们把一个个体表示为一个位串,使用突变,我们允许一个个体的一个或多个位随机改变(例如,把 1 改变为 0,反之亦然)。

当使用 crossover 时,我们将两个元素作为父元素,并将它们组合在一起,生成一个全新的后代(图 2)。

图 2:不同类型的交叉[2]

在本文中,我将向您介绍两种不同的方法来实现进化算法,以解决一个简单的优化问题。这些相同的技术(如本文结尾所示)可以用来处理更复杂的任务,如机器学习超参数优化。本文中使用的所有代码都可以在我的 GitHub 库的链接中找到。

爬山者

爬山法是一种随机局部搜索方法,可用于解决优化问题。

该算法可通过以下步骤实现:

  1. 创建一个随机个体(例如,一个位串,一串字符,等等)。
  2. 对个体进行某种形式的随机突变。
  3. 如果这种突变导致个体的适应度增加,那么用新的个体替换旧的个体,并反复重复这一过程,直到我们能够达到我们期望的适应度分数。相反,如果一个突变没有导致适应度的增加(例如有害的突变),那么我们丢弃我们突变的个体,保留原来的个体。

举个简单的例子,假设我们知道一个由 12 个 1 组成的位串所代表的基因型代表了一个群体中一个元素所能达到的最佳组合。在这个例子中,我们的适应度分数可以简单地用一个人的位串中 1 的数量来表示(位串中 1 的数量越大,我们就越接近我们想要的分数)。

为了实现我们的爬山器,我们首先需要创建一个函数来变异我们的个体。在这种情况下,我们将允许 30%的概率,我们每个单独的位可能会发生突变。

最后,我们现在可以创建我们的爬山者并测试它,给一个初始健康水平为零的个体作为输入。

Fitness: 12  
Resulting Individual: ['111111111111']

进化算法

爬山者的一个主要问题是,为了避免陷入局部极小值,可能需要多次运行该算法。事实上,使用不同的初始化条件,我们的初始个体可能被放置在离局部最优值更近或更远的地方。

进化算法旨在通过使用群体而不是单个个体(利用并行性)以及通过使用交叉和变异作为我们的变异机制(使我们的算法可能更容易逃脱局部最小值)来解决这个问题。

这两个附加功能可以使用下面两个函数在 Python 中实现(按照我们之前的例子)。

因为在这种情况下,我们有一个完整的个体群体,我们现在可以利用不同的技术来决定哪些个体最好进行交叉和变异,以便更接近我们的最终目标。选择技巧的一些例子是:

  • 健身比例选择。
  • 基于等级的选择。
  • 比武选拔。

当使用适应度比例选择时,我们创建一个假想的轮子,并将其分成 N 个部分(其中 N 表示群体中的个体数量)。每个人得到的轮盘份额的大小与每个人的健康程度成正比。

最后,在车轮圆周上选择一个固定点,并旋转车轮。然后,位于固定点前面的轮子区域被选为我们选择的个体。然后,轮子可以旋转我们想要的任何时间,以便选择多个个体,然后用于交叉和变异。

下面是一个如何在 Python 中实现适应度比例选择的简单示例。

通过使用 4 个个体的群体并绘制结果,可以复制图 3 中的图。

图 3:健身比例选择

当使用适合度比例选择时,如果其中一个元素与其他元素相比具有更高的适合度,则其他元素几乎不可能被选择。为了解决这个问题,我们可以使用等级比例选择。

等级选择根据个体的适应性对其进行排序(例如,最差的个体得到等级 1,第二差的个体得到等级 2,依此类推)。使用这种方法,车轮上的股份实际上会更均匀地分布。

使用基于时间等级的选择,使用 4 个个体的群体再次绘制结果,给出了如图 4 所示的结果。

图 4:基于等级的选择

最后,我们可以使用锦标赛选择作为替代方法。在这种情况下,我们可以从群体中随机选择 N 个个体,并从这些元素中选择最好的成为我们选择的元素。然后,根据我们想要从总体中选择的元素数量,可以迭代地重复相同的过程。

现在,我们终于拥有了创建进化算法的所有必要元素。有两种主要类型的进化算法可以实现:稳态(有替换的繁殖)和世代(无替换的繁殖)。

在稳态算法中,一旦我们产生新的子代,它们会立即被放回原始群体,一些不太适合的元素会被丢弃,以保持群体大小不变。下面提供了使用基于等级的选择的稳态进化算法的例子。

在世代进化算法中,一旦新的后代产生,就会被放入新的种群。在预定数量的代之后,这个新的种群成为我们当前的种群。下面提供了使用基于等级的选择的世代进化算法的例子。

TPOT

进化算法可以使用 TPOT 自动机器学习库在 Python 中实现。TPOT 建立在 scikit-learn 库的基础上,可用于回归或分类任务。

进化算法在机器学习中的主要应用之一是超参数优化。例如,让我们想象我们用一些预定义的超参数创建了一群 N 个机器学习模型。然后,我们可以计算每个模型的准确性,并决定只保留一半的模型(表现最好的模型)。我们现在可以生成一些子代,这些子代具有与最佳模型相似的超参数,从而再次得到一群 N 个模型。在这一点上,我们可以再次计算每个模型的准确性,并重复定义数量的代的循环。通过这种方式,只有最好的模型会在流程结束时保留下来。

如果您有兴趣了解更多关于超参数优化的信息,更多信息请点击这里

联系人

如果你想了解我最新的文章和项目,请在 Medium 上关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

文献学

[1]机器人形态和控制的进化优化—在六足机器人平台的设计中使用进化算法。托尼斯·尼加德。访问:https://www . researchgate . net/figure/An-example-a-fair-simple-三维健身景观-including-two-local _ fig 2 _ 323772899

[2]无线网络中的遗传算法:技术、应用和问题。 Usama Mehboob 等人访问:https://www . research gate . net/figure/Illustration-of-examples-of-one-point-two-point-and-uniform-crossover-methods-Adapted _ fig 5 _ 268525551

极限学习机简介

原文:https://towardsdatascience.com/introduction-to-extreme-learning-machines-c020020ff82b?source=collection_archive---------5-----------------------

理解 ML

不要急着介绍什么是榆树。真的是创新还是只是迭代?

榆树是什么?

ELM(极限学习机)是前馈神经网络。由 G .黄于 2006 年“发明”。

正如原论文中所说:

因此在 E LM 中出现了“极端”这个短语(但是这个名字的真正原因可能会因来源而异)。

为什么 ELM 不同于标准神经网络

ELM 不需要基于梯度的反向传播来工作。它使用摩尔-彭罗斯广义逆来设置其权重。

首先,我们看标准 SLFN(单隐层前馈神经网络):

单隐层前馈神经网络,来源:丁下 CC BY 3.0

这很简单:

  1. 将输入乘以权重
  2. 添加偏差
  3. 应用激活功能
  4. 重复步骤 1-3 的层数次
  5. 计算产量
  6. 反向传播
  7. 重复一切

ELM 删除了第 4 步(因为它总是 SLFN),用矩阵求逆代替第 6 步,并且只做一次,所以第 7 步也消失了。

更多细节

在进入细节之前,我们需要看看 ELM 输出是如何计算的:

其中:

  • l 是隐藏单元的数量
  • n 是训练样本的数量
  • 是隐藏层和输出之间的权重向量
  • w 是输入层和隐藏层之间的权重向量
  • g 是激活函数
  • b 是通孔向量
  • 输入向量中的 x

这与标准神经网络中的反向传播非常相似,但如果你仔细观察,你会发现我们将隐藏层和输出之间的权重命名为 Beta。这个β矩阵是一个特殊的矩阵,因为它是我们的伪逆矩阵。我们可以缩短等式,写成:

其中:

其中:

  • m 是输出的数量
  • H 称为隐层输出矩阵
  • t 是训练数据目标矩阵

学习背后的理论(如果你愿意,可以跳过这一部分)

现在我们必须挖掘迪普网络背后的理论,以决定下一步该做什么。

如果一个函数是光滑函数,那么它就是无限可微的

我不打算证明这些定理,但是如果你感兴趣,请参考 ELM-NC-2006 第 3 页的进一步解释。

现在我们要做的是定义我们的成本函数。基于我们对四层前馈神经网络的能力的假设:四层对三层我们可以看到,如果输入权重和隐藏层偏差可以随机选择,则 SLFN 是线性系统。

因为我们 ELM 是一个线性系统,所以我们可以创建优化目标:

为了近似求解,我们需要再次使用 Rao 和 Mitra 的工作:

现在我们可以算出,因为 H 是可逆的,我们可以计算βhat 为:

学习算法

在经历了一些困难的数学之后,我们现在可以定义学习算法了。算法本身相对简单:

如果你对 python 的实现感兴趣,请查看这个资源库:

https://github.com/burnpiro/elm-pure

下面是该模型在 MNIST 数据集上工作的预览:

https://github . com/burn piro/ELM-pure/blob/master/ELM % 20 example . ipynb

正如你所看到的,一个简单版本的 ELM 在 MNIST 数据集上达到了 91%的准确率,在英特尔 i7 7820 x T12 T13 CPU 上训练网络需要大约 3 秒。

性能比较

在本节中,我将使用原始论文中的指标,与之前的 MNIST 示例相比,您可能会惊讶于一些训练持续了多长时间,但请记住原始论文发表于 2006 年,网络是在 奔腾 4 1.9GHz CPU 上训练的。

数据集

结果

我们现在可以忽略训练时间,因为梯度下降显然比矩阵求逆需要更长的时间。该结果表中最重要的信息是精度节点。在前两个数据集中,您可以看到作者使用不同大小的 BP 来获得与 ELM 相同的结果。第一种情况下 BP 网络的规模比第二种情况下小 5x2x 。这会影响测试时间(运行 100 个节点的神经网络比运行 500 个节点的神经网络更快)。这告诉我们我们的方法在逼近数据集时有多精确。

很难在流行的数据集上找到任何 ELM 网络的测试,但我已经设法做到了。这里有一个关于 CIFAR-10MNIST 的基准测试

其中:

我没有找到 ELM 的训练时间,所以没有办法将它们与其他网络的结果进行比较,但所有这些乘数( 20x30x )都是基于 CIFAR-10 上 ELM 1000 的训练时间的相对差异。如果在 ELM 1000ELM 3500 之间有 30 倍的时间增长,那么你可以想象训练拥有 15000 个神经元的 DELM 需要多长时间。

结论

ELMs 不如传统的神经网络精确,但在处理需要对网络进行实时再训练的问题时,可以使用 ELMs。我马上要写另一篇文章描述榆树的演变和用法。现在,由你来创造一个关于这些网络的观点。

榆树背后有很多争议,我不是评判的最佳人选。我将把你转到带有描述的维基百科页面

参考资料:

  • 光-黄斌,秦-朱钰,徐志敬。极限学习机:理论与应用,2006 年https://www.ntu.edu.sg/home/egbhuang/pdf/ELM-NC-2006.pdf
  • 罗正荣,米特拉,矩阵的广义逆及其应用,韦利,纽约,1971。
  • D.《矩阵:理论与应用》,施普林格,纽约,2002 年。
  • 南 Tamura,M. Tateishi,四层前馈神经网络的能力:四层对三层,IEEE Trans。神经网络 8(2)(1997)251–255。

原载于https://erdem . pl

R 中的因子介绍

原文:https://towardsdatascience.com/introduction-to-factors-in-r-dd752f732c94?source=collection_archive---------28-----------------------

因素在数据分析中起着至关重要的作用。学习如何创建、子集化和比较它们。

什么是因子?

因子指用于存储分类变量的统计数据类型。分类变量属于有限数量的类别。另一方面,连续变量可以对应一个无限个数值。

区分您使用的是分类变量还是连续变量非常重要,因为统计模型对这两种类型的处理是不同的。

分类变量的一个例子是性别。在大多数情况下,您可以将类别限制为“男性”或“女性”。虽然在某些情况下你可能会包括额外的类别(无论是考虑到染色体变异、雌雄同体的动物,还是不同的文化规范),但你总会有有限的类别数量。

要在 R 中创建因子,使用[**factor()**](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/factor)函数。factor函数用于将一个向量编码为一个因子(因子的其他术语是“类别”和“枚举类型”)。例如,sex_vector包含 5 个不同个体的性别:

sex_vector <- c("Male", "Female", "Female", "Male", "Male")

很明显有两类(因子等级):“男性”和“女性”。

函数factor()将矢量编码为一个因子:

factor_sex_vector <- factor(sex_vector)

下面是 factor()函数的一个实例。

分类变量的类型

有两种不同类型的分类变量:

  • 一个名义分类变量,它是一个没有隐含顺序的分类变量。不可能说“一个比另一个更有价值”例如,考虑类别"Elephant""Giraffe""Donkey""Horse"。不可能说一个站在另一个之上或之下。
  • 一个有序分类变量,它有一个自然排序。考虑类别:"Low""Medium""High"。很明显"Medium"排名比"Low"高,"High"排名比"Medium"高。

注意 R 是如何构造和打印名义变量和顺序变量的。

r 以不同的方式构造和打印名义变量和顺序变量。对于名义变量,没有排序,所以 R 打印它们时没有指明任何排序。

# Animals
[1] Elephant Giraffe  Donkey   Horse   
Levels: Donkey Elephant Giraffe Horse

对于顺序变量,R 使用<表示顺序。

# Temperature
[1] High   Low    High   Low    Medium
Levels: Low < Medium < High

因素水平

有时,出于清晰或其他原因,更改数据集中特定因子级别的名称会有所帮助。您可以使用[**levels()**](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/levels) 功能完成此操作:

levels(factor_vector) <- c("name1", "name2", ...)

例如,假设来自调查的原始数据包含一个关于回答者性别的问题,并且只记录了两个类别:"M""F"

survey_vector <- c("M", "F", "F", "M", "M")

在收集数据时,用缩写记录性别可能很方便(尤其是用笔和纸),但一旦到了分析数据的时候,就会变得令人困惑。此时,为了清晰起见,您可能希望将因子级别更改为"Male""Female",而不是"M""F"

注意:你分配等级的顺序很重要。levels(factor_survey_vector)输出[1] "F" "M"。如果在创建矢量时没有指定因子的级别,R会自动按字母顺序分配给它们。为了正确地将"F"映射到"Female""M"映射到"Male",等级应按此顺序设置为c("Female", "Male")

我们将数据中默认的“F”和“M”级别改为“女性”和“男性”。

总结一个因素

[**summary()**](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/summary)函数给出了变量内容的快速概览:

summary(my_var)

假设我们想确定在我们的向量中每个因素水平有多少个响应。我们可以使用summary()函数来确定这一点。

在这种情况下,summary(factor_survey_vector)显然比 summary(survey_vector)更有用

因素比较

当你试图比较一个因素的元素时会发生什么?在factor_survey_vector中,您有一个具有两个级别的因子:"Male""Female"。但是它们之间的相对价值是怎样的呢?

让我们测试一下male是否大于(> ) female

默认情况下,当您试图比较因子中的值时,R 返回 NA,因为这个想法没有意义。

有序因子

对于无序(或名义)因子级别,如"Male""Female",比较运算符(如大于运算符)没有意义,R 会返回一条警告消息来反映这一点。

默认情况下,r 为因子的级别赋予相等的值。然而,并不一定是这种情况。有时你还会处理那些在类别之间有自然顺序的因素。这样的因素被称为序数因素。在这种情况下,我们必须将这个信息传递给 r。

假设你想评估五个分析师的表现。要做到这一点,你跟踪他们的速度作为"slow""medium""fast"。您会得到以下结果:

  • 分析师 1 是中等水平,
  • 分析师 2 很慢,
  • 分析师 3 很慢,
  • 分析师 4 是中等,和
  • 分析师 5 速度很快。

我们的第一步是构建一个包含五个条目的向量,并将速度因子分配给每个分析师。

# Create speed_vector
speed_vector <- c("medium", "slow", "slow", "medium", "fast")

speed_vector应转换为序数因子,因为其类别具有自然排序。也就是说,"fast"大于"medium",然后"medium"大于"slow"

默认情况下,factor()函数将speed_vector转换成一个无序因子。要创建一个有序因子,需要两个额外的参数:orderedlevels

factor(some_vector, ordered = TRUE, levels = c("lev1", "lev2", ...))

通过将参数ordered设置为TRUE,可以表明该因子是有序的。使用参数levels,你可以按正确的顺序给出因子的值。

让你试试

从速度向量创建有序向量。因子的正确排序是c("slow", "medium", "fast")

解决办法

# Create speed_vector
speed_vector <- c("medium", "slow", "slow", "medium", "fast")# Convert speed_vector to ordered factor vector
factor_speed_vector <- factor(speed_vector, ordered=TRUE, levels=c("slow", "medium", "fast"))# Print factor_speed_vector
factor_speed_vector
summary(factor_speed_vector)

比较有序因子

您可以通过使用众所周知的操作符来比较一个有序因子的不同元素。例如,要比较第一个因子向量的元素是否大于第二个因子向量的第一个元素,可以使用大于运算符(>)。

factor_vector1[1] > factor_vector2[1]

让你试试

假设‘二号数据分析师’抱怨‘五号数据分析师’拖慢了整个项目。检查他们的陈述是否属实。

解决办法

# Create factor_speed_vector
speed_vector <- c("medium", "slow", "slow", "medium", "fast")
factor_speed_vector <- factor(speed_vector, ordered = TRUE, levels = c("slow", "medium", "fast"))# Factor value for second data analyst
da2 <- factor_speed_vector[2]# Factor value for fifth data analyst
da5 <- factor_speed_vector[5]# Is data analyst 2 faster than data analyst 5?
da2 > da5

结果告诉我们,数据分析师 2 在抱怨数据分析师 5,而事实上是他们拖慢了一切。

笔记

所有图片,除非特别注明,均归作者所有。横幅图像是使用 Canva 创建的。

联合学习简介和挑战

原文:https://towardsdatascience.com/introduction-to-federated-learning-and-challenges-ea7e02f260ca?source=collection_archive---------6-----------------------

联邦学习和挑战简介

下一代人工智能建立在围绕“数据隐私”的核心理念之上。当数据隐私是一个主要问题,并且我们不信任任何隐瞒我们数据的人时,我们可以转向联合学习,通过私人构建智能系统来构建保护隐私的人工智能。

联邦学习就是将计算转移到数据上。全球共享模型被购买到数据所在的位置,例如智能手机。通过将模型移动到设备上,我们可以将模型作为一个整体进行集体训练。

有了这个概念,任何人都可以直接或间接地在他们的设备上参与联合学习,例如,智能手机和物联网设备等边缘设备可以受益于设备上的数据,而数据永远不会离开设备,特别是对于计算受限的设备,通信是较小设备的瓶颈。

从构建任何智能系统同时保护任何个人隐私的角度来看,将计算转移到数据的概念是一个强大的概念。

图一。您的手机会根据您的使用情况在本地对型号进行个性化设置 A)。许多用户的更新被聚集 B)以形成对共享模型的一致变更 C)之后重复该过程。(图由谷歌人工智能博客提供)

联合学习也分为三类,如“

水平联合学习在所有设备上使用具有相同特征空间的数据集,这意味着客户端 A 和客户端 B 具有如下 A)所示的相同特征集。垂直联合学习使用不同特征空间的不同数据集来联合训练如下 b)所示的全局模型。例如,客户端 A (Amazon)拥有关于客户在 Amazon 上购买的电影的信息,客户端 B (IMDB)拥有关于客户的电影评论的信息,使用来自不同域的这两组数据集可以更好地为客户服务,使用电影评论信息(IMDB)向在 Amazon 上浏览电影的客户提供更好的电影推荐。最后,联合迁移学习是与预训练模型一起使用的垂直联合学习,该预训练模型在类似的数据集上被训练以解决不同的问题。联合迁移学习的一个这样的例子是训练个性化模型,例如针对用户过去的浏览行为的电影推荐。

图二。联合学习的分类。a)横向学习,b)纵向学习,c)迁移学习(图由链接

联合学习是如何工作的

联邦学习围绕着名为“、FedAvg”[3]的联邦平均算法。FedAvg 是 Google [3]为解决联邦学习问题制定的第一个标准联邦学习算法。此后,FedAvg 算法的许多变种如“ FedProx ”、“ FedMa ”、“ FedOpt ”、“脚手架等..已经被开发来解决[2]中的许多联合学习问题。

下面描述了 FedAvg 算法如何在较高层次上工作。

在每一轮 FedAvg 中,目标是最小化全局模型 w 的目标,其中只是本地设备损耗的加权平均之和。

  1. 随机采样客户端/设备的子集。
  2. 服务器向每个客户端广播其全局模型。
  3. 并行地,客户端对它们自己的损失函数运行随机梯度下降(SGD) ,并将结果模型发送到服务器进行聚合。
  4. 然后,服务器将其全局模型更新为这些局部模型的平均值。
  5. 然后对于 n 这样的通信循环重复该过程。

联合学习的挑战

这种有用的技术带来了大量需要解决的挑战[2,4]。我认为需要解决的一些最重要的挑战是从[4]中挑选出来的以下四点(该列表绝非详尽无遗)。

  1. 噪声和准确性之间的权衡:使用差分隐私(DP) ,我们可以将噪声添加到数据中,以增强隐私保护。然而,与 DP 我们牺牲了模型的性能。因此,需要在添加适量噪声和不损害模型性能之间进行权衡。
  2. 系统和统计异构:在异构设备上进行培训是一项挑战,无论设备类型如何,确保在所有设备上有效地扩展联合学习非常重要。统计信息的不相似性是指一个设备不能导出全局统计模式,因此一个设备的总体、样本或结果与其他设备的不同。
  3. 通信瓶颈:将模型带到设备的通信成本应该适度低,因为它可能会影响 FL 环境,其中一个设备可能会由于通信瓶颈而瘫痪,这反过来会拖延联合训练过程。有几项工作致力于解决通信瓶颈,如丢弃掉队者(未能在指定时间窗口内计算训练的设备),以及建模压缩/量化以降低带宽成本。
  4. 中毒:中毒有两种形式, 1。数据中毒:在联合训练过程中,多个客户端可以通过贡献它们的设备上训练数据来参与,并且很难检测/防止恶意客户端发送恶意/伪造数据来毒害训练过程,这反过来毒害模型。 2。模型中毒,与数据中毒相反,恶意客户端在将收到的模型发送回中央服务器进行聚合之前,通过篡改其梯度/参数来修改模型,因此,在聚合过程中,全局模型可能会因无效梯度而严重中毒。
  5. 效率和隐私之间的权衡:使用安全多计算(SMPC)和差分隐私(DP) 提高了联邦学习中的隐私保护能力,然而,这种保护伴随着成本和效率之间的权衡。使用 SMPC ,客户端将在发送回中央服务器之前加密模型的参数,因此加密需要额外的计算资源,这将损害训练模型的效率。使用 DP ,噪声被添加到模型和数据中,因此损失了一些精度。因此,在联邦学习中,在 SMPCDP 之间找到一个合适的平衡是一个公开的挑战。

结论

联邦学习仍然是一个相对较新的领域,有很多研究机会可以让保护隐私的人工智能变得更好。这包括诸如系统异构统计异构隐私问题、沟通效率等挑战。。这带来了联合学习中的许多开放问题,在联合学习被业界广泛采用之前,这些问题需要作为一个整体来解决。

参考文献:

[1] 联合学习:没有集中训练数据的协同机器学习

[2] 联邦学习的进展和公开问题

[3] 从分散数据进行深度网络的通信高效学习

[4] 一项关于联合学习的安全性和隐私性的调查

基于高斯函数的图像恢复

原文:https://towardsdatascience.com/introduction-to-gans-877dd689cac1?source=collection_archive---------20-----------------------

实践教程

利用生成对抗网络恢复图像质量。

马文·迈耶Unsplash 上拍摄的照片

自 Goodfellow 等人于 2014 年在 NIPS 推出以来,GANs(生成对抗网络)已经在深度学习和计算机视觉领域掀起了风暴。GANs 的主要思想是同时训练两个模型;一个生成器模型 G 捕获某一数据分布,另一个鉴别器模型 D 确定样本是来自原始分布还是来自 G

GAN 框架就像一个两人的最小最大游戏。 G 不断改进,生成更逼真、质量更好的图像。 D 提高了确定图像是否由 G 创建的能力。训练 GAN 可以完全通过反向传播来完成,这极大地简化了训练过程。通常,通过从 GD 的定期切换来执行训练,以防止两个模型中的巨大性能差距。

图像恢复

为了更详细地解释 GANs,我们将使用图像恢复的例子,使用来自 fast.ai 的第 7 课-v3 的代码。您可以在 Google Colab 上制作笔记本的副本,并在通读时自己运行代码,以获得更多的实践经验!一个优点是,我们只需要一个未标记的图像数据集来创建图像恢复模型。该模型的目的是恢复低分辨率图像和去除简单水印。以下是映像恢复过程的简要概述:

  1. 决定要使用的数据集。在本帖中,我们将使用牛津-IIIT 宠物数据集,这是在 CC 4.0 许可下公开提供的
  2. 通过对图像进行某些变换来“美化”数据集。
  3. 预先训练一个带有 UNet 架构的生成器网络,将伪造的图像转换回原始图像。
  4. 生成可用于预训练评论家的初始恢复图像集。
  5. 预先训练一个批评家网络,将生成的图像分类为“假的”,将原始图像分类为“真的”。
  6. 训练整个 GAN 结构,根据 GAN 文件从发生器切换到批判器。
  7. 最后,我们将获得一个生成器网络,可用于恢复其他质量较低的图像!

数据集生成

为了创建一个带标签的数据集,我们使用一个随机函数来“简化”我们的图像,下面是应用的变换:

  • 添加随机文本/数字
  • 通过调整到较小的分辨率,然后调整回原始分辨率来降低图像质量

下面是左边的复制图片和右边的原始图片。我们可以看到质量严重下降,一些图像中添加了随机数水印!

来自牛津 Pets 数据集的复制图像(左)、原始图像(右)。

预培训生成者和评论家

利用该数据集,我们对 UNet 模型进行预处理,以产生原始图像,并将经过处理的图像作为输入。这是使用均方误差损失来训练的。 ResNet34 被用作主干,这也是在 ImageNet 上预先训练的,这样我们可以节省一些计算时间!以下是仅经过 5 个纪元(在 Google Colab 免费 GPU 上大约 10 分钟)后预训练生成器网络的结果:

预训练发电机网络的结果

我们观察到生成器模型能够部分恢复一些图像质量。此外,大多数带水印的数字都被模型删除和填充了!对于仅仅 10 分钟的训练时间来说,这已经是相当不错的表现了。但是画质还是有较大差距;显然,简单的均方误差损失不足以执行完整的图像恢复。

为了预先训练批评家,我们简单地使用上面的生成器输出,并将它们放入一个目录中。评论家将从目录名中检索标签,并将学会将这些图像分类为真实或虚假。以下是来自一批 critic 预训练数据集的一些样本:

具有原件(标记为图像)和赝品(标记为 image_gen)的评论家预训练数据集

甘培训

在这一部分,我将只简要说明甘训练的细节,而不是把重点放在直觉和技巧,以提高其稳定性。对于完整的解释,约瑟夫·罗卡有一大篇T3关于它!

为了训练 GAN,我们需要在更新生成器 G 和鉴别器/鉴别器 D 之间交替。 G 将使用对抗性损失进行训练,该损失描述了生成的样本欺骗 D 的可能性。均方误差损失也用于确保 G 不会开始产生看起来根本不像原始图像的样本。 D 被单独训练使用相同的对抗性损失,但是与 G 相比,试图将这个损失项推向另一个方向。在训练 D 时,我们希望最大化 D 正确分类真假样本的可能性。

GAN 的训练过程非常复杂,并且需要大量的计算时间。这就是我们进行预培训的原因。预训练模型(甚至在低于标准的生成样本上)允许模型 GD 以合理的网络参数开始。这是双重优势,因为它减少了培训失败的机会,也缩短了培训时间!

结果

在这里,我们展示了经过大约 80 个时期的训练(在 Google Colab 上将近 3 个小时)后生成的一些样本。利用简单的 UNet 模型和短的训练过程,我们能够恢复大部分图像质量并去除简单的水印。在下面的例子中,我们看到图像质量有了显著提高。数字水印也被几乎完美地去除了!但是,一些细节,如猫的头部和面部的精细纹理已经模糊了。

结论

尽管随机图像生成是当今的热门话题,但 GANs 并不局限于这些生成任务(人脸、风景、绘画等)。如果我们跳出框框思考,有许多创造性的应用,GANs 在其中同样有效!除了图像质量恢复,另一个很酷的例子是图像彩色化,我们可以通过相同的过程生成一个变色的数据集,并使用它来训练我们的 GAN。

生成模型和判别模型介绍

原文:https://towardsdatascience.com/introduction-to-generative-and-discriminative-models-9c9ef152b9af?source=collection_archive---------15-----------------------

Pawel Nolbert 在 Unsplash 上拍摄的照片

简介

最近我在工作中做了一个演示,在那里我解释了如何使用条件随机场(CRF) 解决一些问题。由于我的同事对 CRF 知之甚少,我有几张幻灯片专门介绍这个算法背后的理论。当我准备理论幻灯片时,我觉得有责任将 CRF 与概念上类似的算法隐马尔可夫模型(HMM) 进行比较。已知 CRF 是判别模型,而 HMM 是生成模型。我必须更新我对监督机器学习方法分类的知识,特别是生成模型。现在我想简单地分享一下我对生成模式和判别模式之间区别的理解。

生成模型 是一大类机器学习算法,通过对联合分布 P(y,x) 建模来进行预测。

判别模型 是一类有监督的机器学习模型,通过估计条件概率 P(y|x)进行预测。

为了使用生成模型,应该解决更多的未知数:必须估计每个类的概率和给定类的观察概率。这些概率用来计算联合概率,最后联合概率可以作为条件概率的替代来进行预测。

为了估计条件概率 P(y|x ),生成模型比判别模型有更多的步骤

判别模型采取了一种更简单的方式:它只是直接估计条件概率。

每种模式都有许多优点和缺点。我只是注意到生成模型可以用来生成新的样本,但是它需要更多的数据。给定相同数量的数据,判别模型通常优于生成模型,但是它不知道特征之间的依赖性,因为它与预测无关。因此,判别模型不能产生新的样本。

现在让我们仔细看看生成模型的概念。

生成模型

正如我前面所展示的,要做出预测,条件分布 P(y|x) 就足够了。但由于 P(y|x) = P(y,x) / P(x) ,其中 P(x) 为常数对于给定的 x 所有可能的 y ,使用联合分布 P(y,x) 进行预测是有效的。

通过模拟联合分布 P(y,x) 意味着对于每一对(),概率 P(易、)是已知的(被模拟)。一开始,我甚至有点难以理解这是怎么可能的——X的可能值的范围可能是巨大的,所以建议每个的概率是不现实的,更不用说一对()了。应该怎么做呢?**

首先。贝叶斯定理!它将联合概率 P(y,x) 的计算分解为另外两种类型的概率的计算:类概率P(y)*和给定类的观察概率 P(x|y)。*

P(y,x) = P(y) * P(x|y)

它有什么好处?这样至少更容易计算出概率 P(y) ,因为它可以通过计算类别频率从数据集进行估计。 P(x|y) 比较棘手,因为通常 x 不只是一个特征,而是一组特征: x = xi,…,xn ,它们之间可能存在依赖关系。**

P(x | y)=пP(Xi | y,x1,xi-1,xi+1,xn)

通常特征之间的依赖关系是未知的,特别是当它们出现在复杂的星座中时( y,x1,xi-1,xi+1,xn) )。

那么估计 P(x|y) 应该怎么做呢?为此,有以下诀窍:

第二。胡乱假设!或者仅仅是一些假设,使得 P(x|y) 的估计易于处理。朴素贝叶斯分类器可以作为具有这种假设的生成模型的完美例子,这使得 P(x|y) 的计算更容易。也就是说,它具有特征之间的独立性假设 xi,…,xn。

P(x | y)=пP(Xi | y)

通过这种放松,对 P(x|y) 的估计是易处理的,因为每个 P(xi|y) 都可以通过独立于其他特征找到离散特征 xi 的频率或者使用高斯分布来估计,如果特征 xi 是连续的。

结论

现在你可以看到,为了使用生成模型,你应该准备好估计两种类型的概率 P(y)P(x|y)。同时,判别模型直接估计条件概率 P(y|x) ,这通常更有效,因为人们不估计特征之间的依赖性,因为这些关系不一定有助于目标变量的预测。

函数优化的遗传算法和 Python 实现简介

原文:https://towardsdatascience.com/introduction-to-genetic-algorithm-and-python-implementation-for-function-optimization-fd36bad58277?source=collection_archive---------9-----------------------

图片由来自 Pixabay威廉·弗伦奇拍摄

这里,在这篇文章中,我将尝试给你一个遗传算法如何工作的想法,我们将实现函数优化的遗传算法。那么,我们开始吧。

遗传算法是一种基于搜索的优化技术。它经常用于寻找最优或最接近的最优解。它是由霍兰德引进的。它基于达尔文的自然选择理论。在解释遗传算法如何工作之前,让我先解释一下达尔文的自然选择理论。在他的理论中,他将自然选择定义为“一个特征的每一个微小的变化,如果有用的话,被保留下来的原则”。这个概念简单而有力:最能适应环境的个体更有可能生存和繁衍。[ 维基百科 ]有时这个理论被描述为“适者生存”。那些比其他人更适合的人有机会在这场进化中生存下来。遗传算法就是关于这个的。它模仿自然选择的过程来寻找最佳解决方案。

在遗传学中,我们将使用一些生物学术语,如群体、染色体、基因、选择、交叉、突变。现在,首先,让我们试着理解这些术语的含义。

群体、染色体、基因

在这个过程的开始,我们需要初始化这个问题的一些可能的解决方案。群体是给定问题的所有可能解决方案的子集。换句话说,我们可以说群体是一组染色体。染色体是解决当前问题方法之一。每条染色体都是一组基因。

为简单起见,我们可以将染色体描述为一个字符串。因此,我们可以说群体是一些字符串的集合(每个字符是一个二进制值,或者是 0,或者是 1)。字符串中的每个字符都是一个基因。

为了开始遗传算法的过程,我们首先需要初始化种群。我们可以用两种方法初始化群体。第一个是随机的,第二个是启发式的。用一些随机群体开始算法总是更好。

适应度函数

初始化种群后,我们需要计算这些染色体的适应值。现在的问题是这个适应度函数是什么,它是如何计算适应度值的。

作为一个例子,假设我们有一个方程,f(x) = -x + 5。我们需要有最大值且约束为 0≤x≤31 的解。

现在,让我们考虑一下,我们有一个随机的四条染色体的群体,如下所示。我们的染色体长度是 5 as 2⁵=32,0≤x≤31。

我们的适应度函数将计算每个染色体的函数值,如问题陈述中所述:

对于第一条染色体,01110 表示整数 14。所以,f(x) = -(14*14) + 5 = -191。

对于第二条染色体,10101 表示整数 21。所以,f(x) = -(21*21) + 5 = -436。

对于第三条染色体,00011 表示整数 3。所以,f(x) = -(3*3) + 5 = -4。

对于第四条染色体来说,10111 在整数上意味着 23。所以,f(x) = -(23*23) + 5 = -524。

亲代选择

亲本选择通过使用由适应度函数计算的染色体的适应度值来完成。基于这些适应值,我们需要选择一对具有最高适应值的染色体。

有许多方法适合度计算喜欢轮盘赌轮选择,等级选择。

在轮盘赌轮选择中,具有最高适应值的染色体具有最大的可能性被选为亲本。但是在这个选择过程中,可以选择更低的。

在等级选择中,染色体根据它们的适应度值从高到低排序。作为一个例子,根据上面计算的那些适应值,我们可以从高到低排列那些染色体,如第 3 >第 1 >第 2 >第 4。因此,在选择阶段,将基于从适应度函数计算的适应度值来选择第三和第一染色体。

交叉

交叉用于通过产生子代或后代来改变一代代染色体的编程。亲代染色体用于创建这些后代(生成的染色体)。

为了创造后代,有一些方法,如单点杂交,两点或多点杂交。

对于单点杂交,首先,我们需要选择一个点,然后在亲代染色体之间交换被该点分割的这些部分,以产生后代。你可以使用颜色组合,以便于理解。

对于两点交叉,我们需要选择两个点,然后交换比特。

最后,这些新的后代被添加到种群中。

变化

突变给种群带来多样性。有不同种类的突变,如位翻转突变、交换突变、倒位突变等。这些太简单了。

在比特翻转突变中,只需选择一个或多个比特,然后翻转它们。如果所选位为 0,则将其转换为 1,如果所选位为 1,则将其转换为 0。

在交换位突变中,选择两个位并交换它们。

在逆突变中,只需反转位。

遗传算法在 Python 中的实现

让我们尝试用 python 实现函数优化的遗传算法。

问题陈述

假设我们有一个方程,f(x) = -x + 5。我们需要有最大值且约束为 0≤x≤31 的解。使用概率 0.2 来选择初始群体。

你可以在这里 找到完整的代码

初始人口

随机初始化优于启发式初始化。因此,这里随机初始化用于群体初始化。

*#initialize population*
import random
best=-100000
populations =([[random.randint(0,1) for x **in** range(6)] for i **in** range(4)])
print(type(populations))
parents=[]
new_populations = []
print(populations)

健身功能

适应性函数计算染色体的适应性值。适应度函数的功能取决于问题的要求。

*#fitness score calculation ............*
def fitness_score() :
    global populations,best
    fit_value = []
    fit_score=[]
    for i **in** range(4) :
        chromosome_value=0

        for j **in** range(5,0,-1) :
            chromosome_value += populations[i][j]*(2**(5-j))
        chromosome_value = -1*chromosome_value if populations[i][0]==1 else chromosome_value
        print(chromosome_value)
        fit_value.append(-(chromosome_value**2) + 5 )
    print(fit_value)
    fit_value, populations = zip(*sorted(zip(fit_value, populations) , reverse = True))
    best= fit_value[0]

fitness_score()

选择

基于适合度分数选择最适合的染色体。这里使用等级选择过程。

def selectparent():
    global parents
    *#global populations , parents*
    parents=populations[0:2]
    print(type(parents))
    print(parents)
selectparent()

交叉

在选择了最合适的亲本后,需要进行杂交来产生后代。这里使用单点交叉。

def crossover() :
    global parents

    cross_point = random.randint(0,5)
    parents=parents + tuple([(parents[0][0:cross_point +1] +parents[1][cross_point+1:6])])
    parents =parents+ tuple([(parents[1][0:cross_point +1] +parents[0][cross_point+1:6])])

    print(parents)

突变

交叉完成后,进行变异以保持一代到另一代的多样性。在这里,我们将单点位翻转突变。

def mutation() :
    global populations, parents
    mute = random.randint(0,49)
    if mute == 20 :
        x=random.randint(0,3)
        y = random.randint(0,5)
        parents[x][y] = 1-parents[x][y]
    populations = parents
    print(populations)

我们需要多次迭代整个过程,直到找到我们的最佳解决方案。

你会在 卡格尔 上找到完整的代码。

参考

  1. 遗传算法—变异
  2. 遗传算法——交叉
  3. 遗传算法—亲本选择
  4. 遗传算法—种群初始化

最后,感谢您的阅读。感谢您的任何反馈。

R 中的 ggplot2 简介

原文:https://towardsdatascience.com/introduction-to-ggplot2-in-r-4db4f720f505?source=collection_archive---------26-----------------------

使用 ggplot2 包中的数据可视化技术快速入门。

什么是数据可视化?

是以图形、图标、演示等方式可视化数据的实践。它最常用于将复杂的数据转化为非技术受众易于理解的见解。

如果你是数据可视化的新手,这是一本可以作为起点的好书——用数据讲故事

如果你有兴趣学习更多关于 Python 数据可视化的知识,可以看看我的另一个教程——Python 中的Matplotlib

R 是什么?

r 是一种主要用于统计分析的编程语言。它是金融和医疗保健行业的常用分析工具。

R 提供了多种多样的统计(线性和非线性建模、经典统计测试、时序分析、分类、聚类、…)和图形技术,具有高度的可扩展性。

R 入门的绝佳资源,

  1. 代码学院
  2. guru99
  3. R 之书

什么是 ggplot2?

ggplot2 是来自tidy verse的 R 包。它的流行归因于在高抽象层次上定制图形和删除或改变图中组件的简单性。

如果您有兴趣了解更多信息,请查阅这本书— 用 ggplot2 实现 R 中的数据可视化

ggplot 中的绘图语法遵循构建图形的简单分层方法。

  1. 数据
  2. 美学——变量
  3. 几何样式-这是您定义图形样式的地方
  4. 用于定制的附加层—标题、标签、轴等。

结构看起来像这样。

ggplot(data = Example_Data) +
       aes(x = Variable_1, y = Variable_2) +
       geom_bar()   #this is an example of a bar plot sysntax

对于本教程,我将假设您对 R 概念有基本的工作熟练程度。

我们开始吧!

准备好我们的环境

首先,我们需要安装 tidyverse 和 ggplot2 包。

install.packages(c("ggplot2", "tidyverse")

接下来,我们需要加载 ggplot2 库。

library(ggplot2)

条形图

对于数据,我们将使用一个名为 reviews 的数据集。文件已经读入我们的环境。评论数据集收集了来自 4 个主要评论网站的电影评论,分别是 Fandango、烂番茄、IMDB 和 Metacritic。

我们感兴趣的输入是,

  1. 数据= 评论
  2. 美学= (x 轴=评分网站,y 轴=平均评分)
  3. 几何样式=条形图

要创建一个显示每个网站平均评分的条形图,我们可以执行以下操作。

ggplot(data=reviews) +
    aes(x = Rating_Site, y = avg) +
        geom_bar(stat = 'identity')

直方图

直方图向我们展示了一个值出现的频率。下面是一个直方图,显示了我们的点评数据集中评分的频率分布。请注意,添加了一些附加层。

ggplot(data = reviews) +
    aes(x = Rating, **fill** = "red") +
        **geom_histogram**(bins=30) +
        **labs**(title = "Distribution of Ratings")

其他步骤:

  1. 填充——我们在美学层使用它来指定我们想要的颜色。
  2. geom_histogram() —这里我们定义我们想要一个直方图。
  3. 实验室——为了添加标题,我们为标签使用了一个新图层。

在这里,我们可以看到,我们改变和增加了 3 个新的层。ggplot 使得根据我们的个人喜好定制图形变得非常容易。

箱线图

箱线图是可视化描述性统计的另一个优秀工具。如果您想了解更多关于 boxplots 的信息,请查看这篇来自数据科学作家伙伴的文章

下面是一个箱线图,显示了所有评级网站的分布情况。

ggplot(data=reviews) +
    aes(x=Rating_Site, y = Rating, **color = Rating_Site**) +
        **geom_boxplot**() +
            labs(title="Comparison of Movie Ratings") +
                theme(**panel.background** = element_rect(fill = "white"), **legend.position**="none")

现在我们看看这个箱线图,我们已经改变或添加了一些新的层。

  1. 颜色—颜色允许我们定制元素的线条边框,这里我们选择传入变量 rating_site。这使得每个盒子的颜色彼此不同。
  2. geom _ box plot()-陈述图形的样式
  3. panel.background —这允许我们移除灰色背景并用白色填充它。我个人倾向于白色背景,但是根据你想要表达的内容,有时候不同颜色的背景会更有用。
  4. legend.position —这里我声明移除图例标签。为什么?如果我让图例可见,它只会说明它所指的每个盒状图的颜色是哪个 rating_site。这是重复的,因为很明显 xlabels 已经向我们显示了 rating_site。

总的来说,我们可以看到代表 Fandango 评级的方框在 y 轴上比其他网站的要高。相比之下,烂番茄盒子更长,这意味着评级更加分散。

概观

ggplot 是 r 中最强大的可视化工具之一。一旦您深入研究这个主题,您就会发现您可以拥有多少可定制性来创建丰富多彩、详细生动的图形。

在 ggplot 库中以及其他流行的 r 库中有更多可用的图形,值得探索所有不同的选项并找到适合您的编码和分析风格的库。

请继续关注——我将分享更多关于在 ggplot 中创建其他图形的教程。

GitHub 操作简介

原文:https://towardsdatascience.com/introduction-to-github-actions-7fcb30d0f959?source=collection_archive---------14-----------------------

对于数据科学家来说

看到那些绿色的扁虱真是太好了

如果您是 DevOps 和 CI/CD 世界的新手,GitHub 操作可能会有点混乱,所以在本文中,我们将探索一些特性,看看我们可以使用该工具做些什么。

从 CI/CD 的角度来看,GitHub 动作和工作流的主要目标是在每次有变化的时候测试我们的软件。这样我们可以发现错误,并在错误出现时立即纠正。

今天我们将学习更多关于 GitHub 动作的知识,并学习如何使用 Bash 脚本和 Python 来使用它们。很好,我们开始吧!

GitHub 操作与工作流

首先,最好说明一下 GitHub 动作和工作流之间的区别。正如 GitHub Actions 文档所述,Actions 是“单个任务,您可以组合它们来创建工作并定制您的工作流”。另一方面,工作流是“定制的自动化流程,您可以在您的存储库中设置这些流程,以便在 GitHub 上构建、测试、打包、发布或部署任何项目”。换句话说:

  • 工作流:在您的存储库上运行的自动化流程;工作流可以有许多 GitHub 动作
  • GitHub 动作:单个任务;它们可以用 Docker、JavaScript 编写,现在也可以用新的复合运行步骤编写 shell 脚本;您可以编写自己的动作或使用其他人创建的动作

编写我们的第一个工作流

让我们首先创建一个没有动作的工作流,以便理解它是如何工作的。工作流是使用 YAML 文件定义的,您必须将它们存储在存储库根目录下的.github/workflows目录中。

要创建工作流,我们需要定义以下内容:

  • 事件 触发工作流
  • 机床 每项工作都要运行
  • 构成工作流的作业 (作业包含一组执行单个任务的步骤,默认情况下并行运行)
  • 步骤 每项工作都要运行

工作流的基本语法是:

  • on —触发工作流的事件
  • runs-on机床每项工作应该运行
  • jobs —构成工作流的作业
  • steps任务每个作业应该运行的任务
  • run命令该步骤应该运行

首先,我们需要定义触发工作流的事件。在这个例子中,我们想在每次有人推送到存储库时说声问候。

一个工作流运行由一个或多个作业组成。每项工作都在runs-on指定的机器上运行。该机器可以是 GitHub 托管的运行程序,也可以是自托管的运行程序。我们将使用 GitHub 托管的 runner。

一个作业包含一系列被称为步骤的任务。步骤可以运行命令、运行安装任务或运行操作。每个步骤都可以有一个使用操作系统外壳的 run 命令。这里我们要回显一个信息。

迷惑?让我们看看它是如何工作的。继续在 repo 上的.github/workflows中创建一个first_workflow.yml文件,然后粘贴以下代码:

# your-repo-name/.github/workflows/first_workflow.ymlname: First Workflow **on:** push **jobs:**                         
  first-job:                           
    name: Say hi                           
    **runs-on**: ubuntu-latest                           
   ** steps**:                           
    - name: Print a greeting                             
      **run**: echo Hi from our first workflow!

现在,如果您将此文件提交到您的存储库,点击它并转到 GitHub 网站上的 Actions 选项卡,您可以看到新的工作流,检查所有运行并查看输出:

我们第一个工作流程的输出

在我们的第一个工作流中使用动作

行动是单独的任务,我们可以从三个来源使用它们:

  • 在与工作流相同的存储库中定义的动作
  • 公共存储库中定义的动作
  • 发布的 Docker 容器图像中定义的动作

它们在我们的工作流程中作为步骤运行。为了调用它们,我们使用了uses语法。在本例中,我们将使用由 Mike Coutermarsh 编写的打印 ASCII 艺术文本的动作。因为它是在公共存储库中定义的,所以我们只需要传递它的名称:

# your-repo-name/.github/workflows/first_workflow.ymlname: First Workflowon: push jobs:                         
  first-job:                           
    name: Say hi                           
    runs-on: ubuntu-latest                           
    steps:                           
      - name: Print a greeting                             
        run: echo Hi from our first workflow!   

      - name: Show ASCII greeting                             
        **uses: mscoutermarsh/ascii-art-action@master**   
        **with:**                               
          text: 'HELLO!'

with语法是由动作定义的输入参数的映射。结果如下:

ASCII 艺术动作的结果

将 Python 与工作流结合使用

作为数据科学家,我们在日常生活中会使用大量的 Python,所以学习如何在我们的工作流程中使用它是一个好主意。设置特定版本的 Python 或 PyPy 是将 Python 与 GitHub 操作结合使用的推荐方式,因为它“确保不同运行者和不同版本 Python 之间的一致行为”。为此,我们将使用一个动作:setup-python

之后,我们可以像通常在机器上一样运行命令。在这里,我们将安装 Scrapy 并运行一个脚本来获取一些关于 GitHub 操作的 TDS 帖子,看看它是如何工作的。因为我们想从我们自己的库中运行一个脚本,所以我们也需要使用checkout动作来访问它。让我们创建一个新作业来运行脚本:

# your-repo-name/.github/workflows/first_workflow.ymlname: First Workflowon: push jobs:                         
  first-job:                           
    name: Say hi                           
    runs-on: ubuntu-latest                               steps:                           
      - name: Print a greeting                             
        run: echo Hi from our first workflow!  

      - name: Show ASCII greeting                             
        uses: mscoutermarsh/ascii-art-action@master    
        with:                               
          text: 'HELLO!'                                                            **get-posts-job:**                           
 **name: Get TDS posts**                           
    runs-on: ubuntu-latest         steps:                             
      - name: Check-out the repo under $GITHUB_WORKSPACE                               
        **uses: actions/checkout@v2  **       

      - name: Set up Python 3.8                               
        **uses: actions/setup-python@v2    **                           
        with:                                 
          python-version: '3.8'          

      - name: Install Scrapy                               
        **run: pip install scrapy  **       

      - name: Get TDS posts about GitHub Actions                                 
        **run: scrapy runspider posts_spider.py -o posts.json**

我想把刮下来的帖子保存到一个文件里,所以我们来学习一下怎么做。

持续工作流数据

一个工件是在工作流运行期间产生的一个文件或文件集合。我们可以将工件传递给同一个工作流中的另一个作业,或者使用 GitHub UI 下载它。

让我们下载文章中的 JSON 文件,看看它是如何工作的。为了处理工件,我们使用了upload-artifactdownload-artifact动作。要上传工件,我们需要指定文件或目录的路径以及工件的名称:

# your-repo-name/.github/workflows/first_workflow.yml# [...]get-posts-job:                            
    name: Get TDS posts                            
    runs-on: ubuntu-latest steps:                             
      - name: Check-out the repo under $GITHUB_WORKSPACE                               
 uses: actions/checkout@v2        

      - name: Set up Python 3.8                               
        uses: actions/setup-python@v2                              
        with:                                 
          python-version: '3.8'          

      - name: Install Scrapy                               
        run: pip install scrapy         

      - name: Get TDS posts about GitHub Actions                                 
        run: scrapy runspider posts_spider.py -o posts.json ** - name: Upload artifact                      
        uses: actions/upload-artifact@v2                        
        with:                                 
          name: posts                                 
          path: posts.json**

现在我们可以使用 GitHub UI 下载该文件:

下载藏物

创建您的第一个动作

可以使用 Docker 容器、JavaScript 创建动作,也可以使用 shell 脚本创建动作(复合运行步骤动作)。复合运行步骤动作的主要用例是当您有许多 shell 脚本来自动化任务,并且编写一个 shell 脚本来组合它们比 JavaScript 或 Docker 更容易时。

一个动作的三个主要组成部分是runsinputsoutputs

  • runs(必需) 配置动作代码的路径和用于执行代码的应用程序。
  • inputs(可选) 输入参数允许您指定操作在运行时期望使用的数据
  • outputs(可选) 输出参数允许你声明一个动作设置的数据

动作的文件名必须是action.ymlaction.yaml。让我们使用 GitHub Docs 中的例子,创建一个打印“嘿[用户]”消息的动作。因为这是一个复合动作,我们将使用using: "composite"语法:

# action.ymlname: 'Hey From a GitHub Action'description: 'Greet someone'**inputs:
  user:**  # id of input
    description: 'Who to greet'
    required: true
    default: 'You'runs:
  **using: "composite"**
  steps: 
    - run: echo Hey ${{ inputs.user }}.
      shell: bash

如果在与工作流相同的存储库中定义了一个动作,我们可以使用./path-to-action-file来引用它。在这种情况下,我们需要访问存储库中的文件,所以我们也需要使用checkout动作。

如果动作是在公共存储库中定义的,我们可以使用特定的提交、发布版本或分支来引用它。

从同一个存储库中运行操作

# .github/workflows/use-action-same-repo.ymlname: Action from the same repoon: push 
                                                                        jobs:                                 
  use-your-own-action:                           
    name: Say Hi using your own action                           
    runs-on: ubuntu-latest                           
    steps:                             
      **- uses: actions/checkout@v2**

      **- uses: ./** # the action.yml file is in the root folder                           
        with:                                
         user: 'Déborah'

从公共存储库中运行操作

# .github/workflows/use-action-public-repo.ymlname: Action from a public repositoryon: push 
                                                                        jobs:                                 
  use-your-own-action:                           
    name: Say Hi using your own action                           
    runs-on: ubuntu-latest                           
    steps:                                               
      **- uses: dmesquita/github-actions-tutorial@master  **                          
        with:                                
         user: 'Déborah'

这是为了我们的巡演。您还可以在工作流中使用变量和秘密缓存依赖关系来加速它们,以及连接数据库和服务容器来管理工作流工具。

在本指南中,我们没有使用 CI 最酷的功能之一,即经常测试,这样我们就可以在流程的早期发现 bug。但是我认为在做之前理解动作和工作流程是很好的。我希望现在开始使用 CI 工具会更容易,我计划在接下来的教程中这样做。

你可以看到我们在这里使用的所有代码:https://github.com/dmesquita/github-actions-tutorial

今天就到这里,感谢阅读!

梯度下降简介:权重初始化和优化器

原文:https://towardsdatascience.com/introduction-to-gradient-descent-weight-initiation-and-optimizers-ee9ae212723f?source=collection_archive---------13-----------------------

如何修改梯度下降算法以获得更好的性能?

梯度下降是所有机器学习和深度学习方法背后的主要驱动算法之一。随着时间的推移,这种机制在几个方面经历了几次修改,以使其更加健壮。在这篇文章中,我们将讨论其中的两个。为此,你需要一个非常清晰的直觉,知道什么是梯度下降,以及它是如何运作的。如果你对这个话题有任何疑问或困惑,请随时访问我的文章。

挑战

  1. 损失函数的结构差异

让我们来学习两种类型的曲线。

凸曲线

这是一条凸曲线。它有一个单一的全局最小值。所以,无论我们在哪里初始化任何点,我们都可以使用梯度来达到全局最小值。如果我们考虑点作为我们的权重,曲线作为损失函数,我们可以很容易地使用损失函数关于权重的导数收敛到损失函数的最小值。

非凸曲线

这是一条非凸曲线,现在,这里如果我们从曲线上的任何一点(x,y)使用梯度下降,我们不确定会达到全局最小值。我们可能会陷入局部最小值。例如,(x1,y1)可能会卡在跟随它的局部最小值,但是(x2,y2)会很容易到达全局。所以,这里点的位置很重要。

非凸特征。

一条非凸曲线有三个点,这将是有趣的。鞍点,即类平台区域、局部和全局最小值。所有这些点都会有

dy/dx=0

现在,如果我们考虑 x 作为权重,y=f(x)作为损失函数,dL/dW=0

到目前为止,我们一直使用梯度下降方程,

因此,如果 dL/dW 为 0,权重保持不变,我们将陷入次优状态。由于函数复杂,这类非凸曲线在神经网络中非常常见。

现在让我们来讨论一些其他的问题,关于梯度下降算法。

2.爆炸和消失渐变

在神经网络中,如果我们使用非常深的网络,我们会遇到一个称为消失和爆炸梯度的问题。我们已经看到,在神经网络中,我们得到一个等式

并且通过几个激活函数 f(x)和 g(x)发送这个。通过多次执行这样的运算,我们得到了复杂的方程。举个例子,

我们在我之前的文章中已经看到了这一点。我们可以看到,我们将权重乘以几倍。层数越多,乘法次数越多。

现在,如果权重被初始化为非常高的值,梯度值将爆炸,这被称为爆炸梯度问题。类似地,如果权重的值很低,则由于与非常小的值反复相乘,梯度值几乎消失。这就是所谓的消失梯度问题。

3.不同类型梯度下降技术的行为。

在我之前的文章中,我们谈到了三种梯度下降技术。

  1. 批次梯度下降:此时,整个批次被一起输入到模型中,对整个数据集进行预测,误差计算如下:

因此,它获取批次中所有样本的误差,并计算所有误差的总和。现在,由于它将整个集合放在一起,所以在一个时期中,它只更新一次权重。此外,由于我们每次都使用相同的批次,集合的分布不会改变,因此每次更新时权重分布也保持相似。如果我们想象下降的过程,

它看起来会像这样。

对于更高维的权重,我们用轮廓来表示。第一个图显示了 2d 平面中的梯度运动。第二个图显示了使用等高线显示的复杂函数的梯度移动,第三个图显示了损失函数的收敛。

因此,我们可以看到梯度下降相当平稳,损失函数收敛很快。这里,在批量下降的情况下,我们必须发送整个批量,如果它有一百万个条目,它在计算上将是非常低效的。所以,我们需要转向不同的东西。

2.随机梯度下降:这里训练集的一个样本一次通过模型。因此,误差计算如下

误差=(y 实际值-y 预测值)

它非常快。它在每次误差计算后更新权重。如果集合中有 100 个样本,则在一个时期中,SGD 会在模型预测每个样本后更新权重 100 次。现在,每一次,它尝试一个新的样本,在大多数情况下,这个样本将不同于前一个,相应地,权重的分布也将相应地变化。假设可能存在异常值,对于该异常值,特征值分布是不同的,相应地,该样本的权重分布将会变化,并且它将不同于先前的样本。所以,梯度下降会有点嘈杂。它的视觉效果会是这样的,

所以,我们可以看到,这里它也收敛了,但是下降变得有点嘈杂。这种噪声使得随机梯度下降的梯度下降缓慢。

什么是噪音?

I 显示本应下降的高度 II 显示 SGD 下降。我们可以看到,除了水平分量之外,还有一个垂直分量。这个垂直分量负责减慢速度。它被称为噪音。

3.小批量梯度下降:这里我们将整个训练数据集分成更小的小批量,并使用它们进行训练。因此,如果在训练集中有 100 个数据,我们将 25 个作为我们的采样大小,我们将获得 4 个小批量。误差计算如下:

其中 k 是一批样品的数量。因此,在每个历元中,为 4 个批次计算误差,并更新 4 次。这里也有一个噪声问题,但与 SGD 相比要小一些。如果我们想象一下,我们会得到,

我们会得到这样的东西。我们可以看到,有噪声,但它比 SGD 小得多。但是为了加速梯度下降,我们需要尽可能地去除噪声,并尽可能地抑制运动的垂直分量。

因此,我们列出了梯度下降机制的三个重要挑战。

现在,让我们看看解决方案。

解决方法

  1. 重量初始化

权重初始化方法用于解决我们的第二个问题,即爆炸和消失梯度问题。

我们知道我们的神经元在方程上工作,

其中 n 是特征的数量以及相应的权重的数量。我们试图以这样的方式初始化权重,

(W1,W2,……..Wn) = 1/n

因此,对于对应于每个特征的权重,我们将权重初始化为

W=a/sqrt(n)

其中‘a’是常数,并且‘a’在 1 到 n-1 之间变化。这防止权重被初始化得太大或太小。

2.优化师

为了解决第一个和第三个问题,我们使用称为优化器的算法。有几个优化器已经开发了两个主要目标。

  1. 优化学习速度
  2. 抑制垂直运动以加速梯度下降。

在我们讨论优化器之前,让我们来看看一个叫做指数加权平均的概念。

加权平均值

在图表中,深蓝色的点是数据点。现在,我们可以看到数据点是随机分布的,因此噪声很大。为了减少噪声并提取分布的一些实际趋势,我们使用了一种称为移动平均考虑的技术。

比方说,在股票营销中,为了决定一只股票价值的变化,我们经常看它在过去几天的表现。如果我们考虑过去 10 天的价值,它被称为 10 移动平均线,以此类推。这给了我们一种近似,并有助于减少随机性。

类似地,在这种情况下,为了获得第 n 个时间单位的值,我们考虑最后几个时间单位的加权平均值以及当前值。为什么我们称之为加权呢?我们这样称呼它是因为它包含了一个常数,当我们移动到更远的时间单位时,那个时间单位的值对我们当前时间单位值的影响开始减小。

这是我们将使用的等式。这里 V 是时间 t 的加权平均值,X 是时间 t 的数据值。现在,参数β据说是我们取多少天平均值的近似值。

通常情况下,我们取β的值为 0.9。0.9 值对应于我们正在计算的移动平均天数。

平均天数= 1/(1-β)

现在,如果我们必须用β0.9 计算 50 天的加权平均值

这是计算,因此我们为不同时间单位的影响提供不同的权重。(0.9) ⁰变得非常小,并且在此之后不再起作用。这是计算值的方式。

当我们取值 0.9 时,我们得到图像中的红线。它给出了我们数据点的一个相当好的近似值。绿线代表β= 0.5。它是 2 倍单位平均值,因此它非常快地适应了数据点的变化,并且仍然具有高度的噪声,而蓝色对应于 0.98 beta 值。平均 50 天,所以需要很多时间来适应。

但是,这里有一个问题,在 t=1,估计出来很差。如果 X1=10

那么,V1 = 0.9×0+0.1×10 = 1。

当 V0=0 时。所以,我们使用一种叫做的偏差修正

这样做是为了得到较低 t 值的正确近似值。对于较高的 t 值,beta)^t 变得很小,不重要

(1- (beta)^t)= 1

Vt=Vt/1

所以,值保持不变。

随动量梯度下降

这种技术使用加权平均法来稳定垂直运动以及次优状态的问题。

如果我们看到图像,我们会看到,它显示了下降过程中引入的噪音运动。现在,如果我们分解每个运动,我们将得到两个分量,右运动和垂直运动。现在,当我们取加权平均值时,例如 1 和 2、3 和 4,实际上在彼此相反的方向上的垂直运动都是相反的,这抑制了垂直方向上的运动幅度,但是水平运动对所有人都是相同的。所以水平运动加速了,因为这些运动积极地累积起来解决了我们的问题。

等式变成了,

这个“Vdw”叫做力矩。

更新等式变成:

另一个需要注意的是,当 dL/dW=0 时,W(旧)不再等于 W(新)。它还有一个防止下降进入次优状态的因素。

AdaGrad 优化器

自适应梯度优化器使用一种在训练期间修改学习率的技术。它以较高的学习速率开始,随着学习速率的收敛而降低。可以看出,这种方法有助于更好地收敛,并且当我们接近最小值时,它采取非常小的步骤并且非常小心地移动,因此几乎没有超过最优点的机会。这也有助于避免鞍点和局部最小值。

因此,它使用一个修改的学习率参数来适应随时间的变化。

因此,它将学习速率α变为α。我们将阿尔法定义如下。

如果我们看到第二个方程,它是所有梯度的平方和,直到这个单位。在第一个等式中,我们可以看到,它从一个固定的学习速率α开始。ε值是 10^-8,它是防止分母为 0 的值。

随着时间单位的流逝,随着(nu)值的增加, alpha 值变小。因此,t 值越大,nu 值越大,alpha 值越小,学习速率越小,向最小值前进的步伐越短。

RMSProp

在 Adagrad 中,仍然存在一个问题,即 nu 值变得非常大,并且 dL/dW 的突然变化也影响学习参数。因此,在 RMSProp 中还引入了加权平均值来计算 nu 值。不过,这里加权平均的β值取为 0.999。

所以,方程式是:

而且,

因此,RMSProp 使用加权平均法调节学习率参数。

亚当优化器

Adam 或自适应力矩优化器基于 RMSprop 和 SGD 与力矩和偏差校正的使用。

它使用方程式。

Adam 优化器是最健壮的优化器,也是最常用的。它优化了学习速率,并引入矩来解决梯度下降中的挑战。

结论

在本文中,我们已经讨论了梯度下降的挑战和使用的解决方案。我们也详细谈过几个优化器。

希望这篇文章有所帮助。

使用 PyTorch 的线性回归示例的梯度下降介绍

原文:https://towardsdatascience.com/introduction-to-gradient-descent-with-linear-regression-example-using-pytorch-dbf7a9540d78?source=collection_archive---------34-----------------------

机器/深度学习中广泛使用的优化方法。

杰里米·毕晓普在 Unsplash 上的照片

介绍

在机器学习中,通常情况下,我们需要找到一个损失函数(或成本函数)的最小值。梯度下降法是一种广泛应用的优化方法。

在这篇文章中,我将通过一些例子讨论梯度下降法,包括使用 PyTorch 的线性回归。

结石

求函数最大值或最小值的一种方法是求斜率为零的点。函数的最大值或最小值将是函数的导数等于零的解。

以这个函数为例:

f(x)= x * * 2–5x+5,图片由作者提供

该函数的导数为:

所以设 f'(x) = 0,我们可以求出 x=2 为解。这意味着函数的斜率在 x=2 时等于零,函数的最小值是 f(2)=1。

这种方法找到了解析解,然而,在实际应用中有时很难将这种方法应用于复杂函数。因此,我们需要数值方法来寻找近似解,梯度下降法就是其中一种方法。

梯度下降

梯度的数学解释可以在这个环节中找到。

对于一维函数 f(x),梯度表示为 f'(x)。对于多维函数,表示如下。

来自 wiki :如果函数的梯度在 p 点不为零,那么梯度的方向就是函数从 p 开始增加最快的方向,梯度的大小就是那个方向的增加率。

梯度下降试图通过下降到梯度的相反方向来接近函数的最小值。

它迭代地更新参数(这里是 x)来寻找解。所以首先,我们需要一个解的初始猜测(x0),然后基于初始猜测计算梯度,然后基于计算的梯度更新解(x)。可以用这个公式来解释:

t 是迭代次数,r 是学习率。

所以,首先,我们有一个初始猜测 x0,通过上面的等式,我们可以找到 x1:

然后通过 x1,我们可以找到 x2:

通过多次重复这一过程(历元),我们应该能够找到参数(x ),其中函数在其最小值。

示例 1:

让我们以前面的函数为例:

并将其应用于梯度下降方程

重新排列:

让我们设定学习率= 0.1,初始猜测值 x0=7。然后,我们可以轻松地更新和计算 x1、x2、x3…以及 f(x1)、f(x2)、f(x3)…

在本例中:

可以看到参数(x)接近 2,函数接近最小值 1。

让我们把它放在图表上:

梯度下降(学习率= 0.1)(图片由作者提供)

如果我们用一个更小的学习率(0.01)呢?

梯度下降(学习率= 0.01)(图片由作者提供)

正如所料,达到最小值需要更多的迭代。

如果我们把学习提高到 0.3,它比 0.1 更快达到最小值。

梯度下降(学习率= 0.3)(图片由作者提供)

如果我们把它进一步提高到 0.7,它就开始超调了。

梯度下降(学习率= 0.7)(图片由作者提供)

如果我们把它增加到 1,它根本达不到最小值。

梯度下降(学习率= 1)(图片由作者提供)

所以学习率对梯度下降非常重要。如果太小,就需要大量的迭代,如果太大,就可能达不到最小值。

现在,我们对梯度下降如何工作有了一个概念,让我们尝试将其应用到一个简单的机器学习模型——线性回归。

示例 2 —线性回归:

线性回归示例

线性回归是一种寻找两个变量之间线性关系的方法。它找到一条线,

描述图中所示的数据点。m 是直线的斜率,c 是截距。任务是找到最符合数据点的直线(m 和 c)。

损失函数

我们使用均方误差(MSE)来度量线和数据点的误差。

它对点和线之间的差的平方和进行平均。

我们可以重新排列等式:

我们想找到 m 和 c,它们给出了 MSE 的最小值。

梯度下降

就像前面的例子,我们需要找到梯度。

然后我们可以用这个等式来更新 m 和 c:

同样,我们需要对 m 和 c 的初始猜测,让我们从 m=0 和 c=0 开始,学习率= 0.0001

#Gradient Descentfor i in range(epochs):
   Y_pred = m*X + c
   d_m = (-2/n) * sum(X * (Y - Y_pred))
   d_c = (-2/n) * sum(Y - Y_pred)
   # Update m
   m = m - r * d_m
   # Update c
   c = c - r * d_c
   mse=(1/n) * sum((Y - m*X + c)**2)

可以基于梯度更新 m 和 c。让我们把它放在图表上。

梯度下降-线性回归例子,学习率= 0.0001。(图片由作者提供)

同样,仔细选择学习率是重要的,如果学习率增加到 0.01,计算将不会收敛。

梯度下降-找不到最佳 m 和 c,学习率= 0.01。(图片由作者提供)

在这个简单的例子中,我们自己通过对函数的求导来计算梯度,这对于更复杂的问题可能会变得困难。幸运的是,PyTorch 提供了一个工具来自动计算几乎任何函数的导数。

Pytorch 方法

让我们定义这条线:

**def** f(x, params):
    m, c= params
    **return** m*x + c

损失函数——均方误差:

**def** mse(preds, targets): **return** ((preds-targets)**2).mean()

再次,我们由 m=0 开始,c=0,这里的 需要 grad() ,这里是用来计算梯度的。

params = torch.zeros(2).requires_grad_()

然后我们可以根据第一个参数预测 y 值,并画出来。

preds = f(X_t, params)

Pytorch 梯度下降-初步猜测。(图片由作者提供)

然后我们可以计算损失:

loss = mse(preds, Y_t)

以及 PyTorch 函数的梯度:

loss.backward()

之后,我们可以检查梯度:

params.grad

它返回一个张量,即梯度:张量([433.6485,18.2594])

然后,我们使用梯度和学习率更新参数:

lr = 1e-4
params.data -= lr * params.grad.data
params.grad = **None**

并使用这些新参数预测 y:

Pytorch 梯度下降—第二纪元(图片由作者提供)

我们需要多次重复这个过程,让我们制作一个函数:

**def** apply_step(params):
  preds = f(X_t, params)
  loss = mse(preds, Y_t)
  loss.backward()
  params.data -= lr * params.grad.data
  params.grad = None
  return pred

然后我们可以跑几个纪元。看起来随着时间的推移,损失在减少。

把它放在图表上

Pytorch 的梯度下降(图片由作者提供)

就是这个!通过使用 PyTorch,我们可以轻松地计算梯度,并为机器和深度学习模型执行梯度下降。

感谢阅读。

图算法简介:Python 中的广度优先搜索算法

原文:https://towardsdatascience.com/introduction-to-graph-algorithm-breadth-first-search-algorithm-in-python-8644b6d31880?source=collection_archive---------17-----------------------

照片由 Unsplash 上的甘帕尼·库马尔拍摄

入门

清晰理解可视化广度优先搜索算法

图表形式的数据存在于许多流行和广泛使用的应用程序中。网络爬虫、计算机网络、关系数据库和社交网络都是很好的例子。图搜索算法对于计算机科学的任何部分都是重要的。同样,这对于许多编码面试来说也是重要和有用的。

有几种不同的图形搜索算法可用。这是最简单的图搜索算法之一,也是许多其他图算法的一种原型。今天我将详细解释广度优先搜索算法,并展示广度优先搜索算法的一个用例。以下是这篇文章的要点:

  1. 广度优先搜索算法如何处理视觉效果
  2. 用 Python 开发算法
  3. 如何用这个算法找到任意节点到源节点的最短路径。
  4. 时间复杂度

我们开始吧!

广度优先搜索算法的工作原理

一个图有两个元素。顶点和边。

鉴于,

一个图 G = (V,E),

其中 V 是顶点,E 是边。

广度优先搜索算法系统地逐层探索边,以发现从给定的源顶点 s 可到达的每个顶点。

以下是广度优先搜索流程的步骤:

  1. 有一个起始顶点 s。
  2. 用开始顶点 S 作为级别 1 初始化级别集。
  3. 探索另一个顶点从开始就可以到达。这些顶点将被视为级别 2。
  4. 这样顶点就会一层一层的打开。

以下是这些步骤的直观演示:

这里,我们有六个顶点,u,v,w,x,y,z 和七条边 ux,uv,vx,vy,xy,wy,wz。

将顶点 u 视为源顶点或起始顶点。现在看下图他们是怎么一级一级打开的。

源顶点是 u 是 level 1。我们查一下我们能从 L1 去哪里。从图中可以看出,‘u’有一条直接通向 v 和 x 的路径,所以,它们是 2 级。

现在,我们在节点 x 和 v 中。x 和 v 只能直接访问 y。因此,y 是第 3 层。 从 x 和 v 两方面,我们可以去 u 也。但是我们忽略了已经访问过的节点。

y 只能直接访问 w。所以,w 是第四级。我们也可以从 y 到 v 和 x,但是它们已经被访问过了。所以,我们再也不用担心他们了。

最后 w 可以到 z,z 是 level5。

Python 中的算法

在我们深入算法之前,让我们先做一个邻接表。也就是说,创建一个字典,其中每个节点都是一个键,链接到它的节点都是存储在列表中的值。

例如,节点 u 链接到节点 v 和 x。因此,它将表示为:

'u': ['v', 'x']

这里的“u”是“v”和“x”的父代。

我们还需要对所有其他节点进行同样的操作。邻接表将看起来像这样:

adj = {
    'u': ['v', 'x'],
    'x': ['u', 'v', 'y'],
    'v': ['u', 'x', 'y'],
    'y': ['w'],
    'w': ['y', 'z'],
    'z': ['w']
    }

接下来,我们需要初始化几个变量:

变量来跟踪我们已经访问过的节点,

“级别”变量来跟踪我们当前所处的级别,

“parent”变量来存储节点的父节点。

“traversal_output”来列出经过的节点。

最后,我们将使用一个队列来开发这个算法。Python 有一个内置的队列,我们可以导入并使用它。

from queue import Queue
visited = {}
level = {}
parent = {}
traversal_output = []
queue = Queue()

开始时,将“已访问”字典中的所有节点设置为“False ”,将“父”字典中的所有节点设置为“None ”,并将级别设置为-1。

for node in adj_list.keys():
        visited[node] = False
        parent[node] = None
        level[node] = -1

如图,假设来源是‘u’。首先,使用 visited[s] = True,使用 level 0 并在队列中添加“u”。

s = "u"
visited[s] = True
level[s] = 0
queue.put(s)

循环来了!

在这个阶段,我们需要访问链接到源节点“u”的节点。我们将它列在上面的邻接表中。对于它们中的每一个,将它们设置为已访问,将它们的级别升级为比源节点的级别高一级,将它们的父节点设置为“u”,最后将它们添加到队列中。

然后对它们的子节点重复同样的操作。以下是完整的循环:

while not queue.empty():
    u = queue.get()
    traversal_output.append(u)
    for v in adj_list[u]:
        if not visited[v]:
            visited[v] = True
            parent[v] = u
            level[v] = level[u] + 1
            queue.put(v)
print(traversal_output)
print(visited)
print(level)
print(parent)

输出:

['u', 'v', 'x', 'y', 'w', 'z']
{'u': True, 'x': True, 'v': True, 'y': True, 'w': True, 'z': True}
{'u': 0, 'x': 1, 'v': 1, 'y': 2, 'w': 3, 'z': 4}
{'u': None, 'x': 'u', 'v': 'u', 'y': 'v', 'w': 'y', 'z': 'w'}

Traversal_output 显示我们遍历了所有节点。

对于每个节点,第二行中的 visited 为 true。

在第三行中,我们有所有节点的级别。请对照上面的图片。

在第四行,我们有所有节点的父节点。“u”是源节点。所以,“u”没有父代。

将所有代码组合起来,放入一个函数中:

def Breadth_first_search(adj_list):
    visited = {}
    level = {}
    parent = {}
    traversal_output = []
    queue = Queue()
    for node in adj_list.keys():
        visited[node] = False
        parent[node] = None
        level[node] = -1
    s = "u"
    visited[s] = True
    level[s] = 0
    queue.put(s)
    while not queue.empty():
        u = queue.get()
        traversal_output.append(u)
        for v in adj_list[u]:
            if not visited[v]:
                visited[v] = True
                parent[v] = u
                level[v] = level[u] + 1
                queue.put(v)
    return traversal_output, visited, level, parent

调用这个函数并传递邻接表' adj '会给你同样的输出。

寻找最短的距离

该算法可用于寻找从源到任何其他节点的最短路径。怎么会?

看,我们知道每个节点的父节点。从任何一个节点,我们通过父节点不断回溯,最终会回到源节点。对吗?

比如说,我想从源节点‘u’找到最短路径‘w’。让我们看看,谁是 w 的父母。是 y。y 的父代是‘v’,然后 v 的父代是‘u’。所以,最短路径是 u,v,y,w。

检查图片,看看你是否认为这是最短的路径。

我们可以从上面定义的函数中找到每个节点的父节点。

traversed, visited, level, parent = Breadth_first_search(adj)

下面是查找最短路径的代码

v = "w"
path = []
while v is not None:
    path.append(v)
    v = parent[v]
path.reverse()
print(path)

输出:

['u', 'v', 'y', 'w']

时间复杂度

我们这里只有两个元素。顶点和边。

注意,小心。我们只访问每个顶点一次。在 for 循环中,我们忽略已经访问过的顶点。假设 V 是顶点的集合。

我们在这里使用了一个无向图。对于无向图,我们可以双向访问。我们可以从“u”到“v ”,也可以从“v”到“u”。在上面的邻接表' adj '中,你可以看到一个节点可以出现不止一次。我们最多会遍历一条边两次。设 E 是边的集合,在最坏的情况下,它将穿过边 2E 次。Som 最坏情况下的总时间 V+2E。

时间复杂度可以表示为 O(V+E ),因为系数包含在 O 中。

结论

我试图解释,width _ first _ search 算法如何使用视觉效果工作,用 Python 开发了该算法,如何使用 width _ first _ search 算法找到最短路径,以及该算法的时间复杂度。我希望你现在清楚了。

欢迎在推特上关注我,喜欢我的 T2 脸书页面。

更多阅读:

[## 清晰理解深度优先搜索算法及其 Python 实现:图算法

借助清晰的视觉效果进行学习。还要学习人们在深度优先搜索算法中常犯的一个错误

towardsdatascience.com](/clear-understanding-of-depth-first-search-algorithm-and-its-python-implementation-graph-algorithm-3e87d8f1a9ea) [## Numpy 的终极备忘单

对学习也有好处

towardsdatascience.com](/an-ultimate-cheat-sheet-for-numpy-bb1112b0488f) [## 熊猫数据可视化的终极备忘单

熊猫的所有基本视觉类型和一些非常高级的视觉…

towardsdatascience.com](/an-ultimate-cheat-sheet-for-data-visualization-in-pandas-4010e1b16b5c) [## Python 中从头开始的完整异常检测算法:分步指南

基于概率的异常检测算法

towardsdatascience.com](/a-complete-anomaly-detection-algorithm-from-scratch-in-python-step-by-step-guide-e1daf870336e) [## 学习机器学习和深度学习的优质免费课程

顶级大学高质量免费课程的链接

towardsdatascience.com](/great-quality-free-courses-to-learn-machine-learning-and-deep-learning-1029048fd0fc) [## 使用 Lambda、Map、Filter 和 Sorted 进行高效的 Python 编程

使用数字、字符串和字典列表的快乐编程

towardsdatascience.com](/efficient-python-programming-with-lambda-map-filter-and-sorted-cfdf536afc36) [## 置信区间的完整指南,以及 Python 中的示例

对统计学中一个非常流行的参数——置信区间及其计算的深入理解

towardsdatascience.com](/a-complete-guide-to-confidence-interval-and-examples-in-python-ff417c5cb593)

图形挖掘和分析简介

原文:https://towardsdatascience.com/introduction-to-graph-mining-and-analytics-fac18515ea3e?source=collection_archive---------35-----------------------

你好。在这篇文章中,我将分享一些关于图形挖掘和分析的有趣故事/应用。

不是每个人,甚至是数据科学家每天都在处理与图形相关的问题/工具。所以人们可能会问的第一个问题是:什么是图?第二:为什么了解图形分析和算法很重要?第三:图挖掘和分析的一些应用是什么?让我们逐一回答这些问题,如果你想进一步探索图算法,我还会在最后附上一些好的资源。现在,让我们开始吧。

什么是图?

解释简单图形的涂鸦(图片由作者提供)

图形表示实体及其关系。每个实体由一个节点表示,它们之间的关系由一条边表示。这里每个实体(节点)是一个人,边表示关系有多“密切”(你可以给边加权来反映这一点。例如,在上面的涂鸦中,吉姆、艾米丽和雅各布位于等腰直角三角形的顶点。我们假设两边的权重为 1,斜边的长度为√2。经理汤姆位于斜边的中点,因此与其他所有人的距离相等,都是√2/2。现在,我们可以说,Tom 与他的三个直接下属有相同的“亲密度”,Jim 与 Jacob 和 Emily 有相同的“亲密度”,而 Jacob 和 Emily 自己的关系水平最高。).

现实生活中还有其他图表的例子。社交网络、网页、健康提供者网络等。并且该图可以进一步分为有向图和无向图。有向图意味着存在关于关系的方向,例如网页。无向图意味着实体之间的关系是相互的,例如,友谊网络。

为什么了解图形分析和算法很重要?

一句话,图表分析帮助我们研究互联数据,并帮助揭示模式,尤其是大数据中的社区。图形算法是图形分析中使用的工具。

考虑上面的涂鸦,但在一个更大的社交网络中。我们能找到社区中每个人都互相认识的社区吗(也称为强连接组件)?一旦我们确定了这些社区,我们能找到其中最有影响力的成员吗?到达那个人的最少人数是多少?此外,如果一个新人被添加到图表中,我们可以对这个新成员属于哪个社区进行分类吗?有趣的问题要解决,不是吗?

为了解决上述问题,我们需要引入图算法。例如,为了检测社区,我们需要引入三角形计数和聚类系数,以及标签传播和 Louvain 模块性。为了找到图中从一个成员到另一个成员的最小跳数,我们需要引入最短路径算法。图形算法的细节超出了本文的范围,但是你可以参考下面的参考资料获得更多信息。

图挖掘和分析有哪些应用?

有许多应用程序使用图形分析,我鼓励你自己多读一些。这里我要讲两个应用。一个是 PageRank,另一个是欺诈检测。

PageRank。 PageRank (PR)是谷歌搜索使用的一种算法,用于在其搜索引擎结果中对网页进行排名。我们知道网页是相连的,可以建模为有向图(节点之间的关系有方向)。为什么导演?这种关系不是相互的,因为我在帖子中指出了 neo4j 图书的链接,但他们可能不会指向我的链接。简单来说,PageRank 算法根据有多少网页指向一个网页,以及这些网页的影响力有多大,对该网页进行迭代排序,直到分数收敛。

欺诈检测。 之前我们在一张图中谈到了社区检测。这有助于检测网络中的欺诈行为。异常实体应该表现出不属于任何强连接组件的模式,或者与图中的其他实体具有很高的距离。例如,考虑那些为吸引用户点击而创建的欺诈性网页。它们很可能是“孤岛”,很少被其他网站引用,也很少被其他网站引用。

以上是对图形挖掘和分析的快速介绍。我鼓励你在业余时间读一些书,并欢迎给我任何意见/建议。

一些关于图形分析的好资源

(TigerGraph 在 youtube 上举办的图形大师网络研讨会。

(neo4j 网站上免费赠送的《图形算法》一书。https://neo4j.com/lp/book-graph-algorithms

使用 DeepWalk 介绍图形神经网络

原文:https://towardsdatascience.com/introduction-to-graph-neural-networks-with-deepwalk-f5ac25900772?source=collection_archive---------19-----------------------

让我们通过讨论该领域的开创性工作之一——DeepWalk,来建立对图形神经网络(GNN)的原因和内容的直觉。我们将把它与 word2vec 联系起来,并通过在图上试验现有的实现来结束。

Unsplash 的 urielsc26

介绍

图形神经网络是当前的热门话题[1]。这种兴趣肯定是合理的,因为 gnn 都是关于向量空间中图形的潜在表示。将实体表示为向量并不是什么新鲜事。在 NLP 中有许多像 word2vec 和手套嵌入这样的例子,它将一个单词转换成一个向量。使这种表示强大的是(1)这些向量在它们之间结合了相似性的概念,即彼此相似的两个词在向量空间中倾向于更接近(点积很大),以及(2)它们在不同的下游问题中具有应用,如分类、聚类等。这就是 GNN 有趣的地方,因为有很多方法可以将一个单词或图像嵌入到矢量中,GNN 为图形奠定了基础。在本帖中,我们将讨论这样做的初始和基本方法之一——DeepWalk[2]

图表 101

图形或网络用于表示关系数据,其中主要实体称为节点。节点之间的关系由边来表示。通过添加多种类型的节点、边、边的方向,甚至边的权重,可以使图变得复杂。

图 1:空手道数据集可视化@网络知识库[3]。

图 1 显示了一个图表示例。该图是空手道数据集[4],它表示大学空手道俱乐部成员的社会信息。每个节点代表俱乐部的一个成员,每个边代表俱乐部的两个成员之间的联系。左边的信息栏显示了几个图形属性,如节点数、边数、密度、度数等。网络库[3]包含了许多来自不同领域的网络,并提供了可视化工具和基本统计数据,如上所示。

相似节点的概念

因为矢量嵌入背后的思想是突出相似性,我们将考虑相似节点的一些定义。两个节点可以通过多种方式被称为相似的,例如它们是否具有相似性——入度计数、出度计数、平均度或邻居数量等。一个有趣的概念是考虑节点的邻居,它们共享的邻居越多,它们就越相似。在纯文本中,节点是由它所保持的公司定义的。如果两个节点有非常相似的公司,那就是非常相似。这种通过位置来表示实体的想法并不新鲜。自然语言处理中单词嵌入的基础是基于这样一条格言:“单词由它所保持的上下文来表示”。这两个领域如此相似,很明显,第一直觉是利用 NLP 中的现有技术,通过某种方式将单词上下文的概念转换为节点的邻居,将其移植到图域。一种现有的技术是 word2vec,我们将简要讨论它。

Word2Vec

需要用 word2vec (w2v)走一段弯路,才能完全欣赏和理解 DeepWalk 背后的思想。Word2Vec 是一种将单词表示为向量的单词嵌入技术。每一个向量都可以看作是\(R^{D}\)空间中的一个点,其中\(D\)是每一个向量的维数。需要注意的一点是,这些向量并不是随机分布在向量空间中的。它们遵循一定的属性,相似的单词如比完全不相关的单词如坦克彼此相对更接近。在向量空间中,这意味着它们的余弦相似性得分更高。与此同时,我们甚至可以观察到像king - man + woman = queen这样的著名类比,这些类比可以通过这些词的表示向量的向量相加来复制。

图 2:向量空间表示单词向量的位置以及它们之间的关系,以展示类比国王-男人+女人=王后

虽然这种表示不是 w2v 所独有的,但它的主要贡献是提供了一个简单而快速的基于神经网络的单词嵌入器。为此,w2v 将训练转化为一个分类问题,其中给定一个单词,网络试图回答哪个单词最有可能在给定单词的上下文中找到。这种技术正式称为 Skip-gram,其中输入是中间词,输出是上下文词。这是通过创建一个 1 层深度神经网络来实现的,其中输入单词以一位热编码格式馈送,输出是 softmax,理想情况下对上下文单词具有较大的值。

图 3: SkipGram 架构(摘自 Lil'Log [7])。它是一个 1 层深度神经网络,输入和输出为一个热编码。输入-隐藏权重矩阵包含单词嵌入。

训练数据是通过在大型文本(可以是文章或小说,甚至是完整的维基百科)的语料库上滑动一个窗口(某个窗口大小)来准备的,对于每个这样的窗口,中间的单词是输入单词,上下文中的剩余单词是输出单词。对于向量空间中的每个输入单词,我们希望上下文单词靠近,而其余的单词远离。并且如果两个输入单词将具有相似的上下文单词,则它们的向量也将接近。这是 Word2Vec 背后的直觉,它通过使用负采样来实现。训练后,我们可以观察到一些有趣的事情——神经网络的输入隐藏层之间的权重现在表示我们想要在单词嵌入中使用的概念,这样,具有相同上下文的单词在向量维度上具有相似的值。并且这些权重被用作单词嵌入。

图 4:来自 Wevi 的 5D 单词嵌入的热图可视化[5]。颜色表示单元格的值。

图 4 中的结果来自一个很酷的交互式 w2v 演示 Wevi [5]的训练 5D 单词嵌入。像(果汁、牛奶、水)和(橘子、苹果)这样显而易见的词有相似的向量(一些维度被同样照亮——红色或蓝色)。感兴趣的读者可以去[7]详细了解建筑学和数学。此外,建议[5]对 word2vec 后面的引擎进行出色的可视化。

深度行走

DeepWalk 采用了和 w2v 相同的训练技术,即跳格训练。但是还有一件重要的事情要做,那就是创建训练数据来捕捉图形中的上下文概念。这是通过随机漫步技术完成的,我们从一个节点开始,随机地去它的一个邻居。我们重复这个过程\(L\)次,这是随机行走的长度。在这之后,我们重新开始这个过程。如果我们对所有节点都这样做(并且对每个节点做\(M\)次),我们在某种意义上已经将图形结构转换成类似于用于训练 w2v 的语料库的文本,其中每个单词是一个节点,并且它的上下文定义了它的邻居。

实现 1:作者代码

DeepWalk 的作者在这里提供了一个 python 实现。自述文件中提供了安装详细信息和其他先决条件(windows 用户可能会遇到一些安装和执行问题)。CLI API 公开了几个算法和优化参数,

  • input需要包含图形信息的输入文件的路径。一个图可以用几种格式存储,一些著名的(并且被代码支持)是邻接表(node-all_neighbors list)和边表(有边的节点-节点对)。
  • number-walks每个节点随机行走的次数。
  • representation-size每个节点最终嵌入的维度。也是 skipgram 模型中隐藏层的大小。
  • walk-length每次随机漫步的长度。
  • window-sizeskip gram 训练中的上下文窗口大小。
  • workers优化参数定义为训练生成的独立进程的数量。
  • output输出嵌入文件的路径。

作者也提供了示例图,其中之一是我们的空手道俱乐部数据集。它以邻接表的格式存储。

图 5:空手道俱乐部数据集邻接表的前 5 行。节点用数字表示。在每一行中,第一个节点名是中心节点,其余节点是它的邻居(它们有一条边)。

现在让我们读取图形数据并创建节点嵌入,

deepwalk --input example_graphs/karate.adjlist --number-walks 10
--representation-size 64 --walk-length 40 --window-size 5 
--workers 8 --output trained_model/karate.embeddings

这执行了从开始到结束的分析,包括从文件中加载图形,生成随机遍历,最后在遍历数据上训练 skip-gram 模型。通过使用额外的--max-memory-data-size 0参数运行该脚本,该脚本还存储了行走数据,如下所示。

图 6:为空手道俱乐部数据集生成的随机行走语料库的前 5 行。节点用数字表示。每条线代表从第一个节点开始的一次随机行走。当我们设置 walk length = 40 时,每行(walk)有 40 个节点。同样,当我们设置遍历数= 10,总节点数= 34 时,总共生成 10*34=340 个随机遍历。

最后,我们得到包含图中每个节点的矢量嵌入的输出嵌入文件。该文件看起来像,

图 7:节点嵌入输出的前 3 行。第一行是带有节点和嵌入维度统计信息的标题。从第二行开始,第一个数字是节点名,随后的数字是提到的节点的矢量嵌入。

实施 2:空手道俱乐部

新发布的 python 实现——KarateClub[6]提供了一个简单得多的 API。要做同样的一套动作,我们需要做的就是跟着做。

# import libraries
import networkx as nx 
from karateclub import DeepWalk
# load the karate club dataset
G = nx.karate_club_graph()
# load the DeepWalk model and set parameters
dw = DeepWalk(dimensions=64)
# fit the model
dw.fit(G)
# extract embeddings
embedding = dw.get_embedding()

DeepWalk类也扩展了作者的代码所公开的相同参数,并且可以进行调整以进行所需的实验。

图 8:KarateClub[6]中 DeepWalk 实现公开的参数。

实验

为了查看 DeepWalk 的运行情况,我们将选择一个图,并可视化网络以及最终的嵌入。为了更好地理解,我创建了一个由 3 个完整的图组成的并集,每个图都有一些额外的边来连接。

图 9:3 个完整图的并集。我们可以想象 3 个集群,其中节点 0 到 9 属于集群 1;10 到 19 到组 2,20 到 28 到组 3。

现在,我们将创建图的深走嵌入。为此,我们可以使用 KarateClub 包,通过在默认设置下运行 DeepWalk,我们可以获得 128 维的嵌入。为了形象化这一点,我使用了降维技术 PCA,它将 R ⁸的嵌入缩小到 r。我还将在边上绘制嵌入的 128D 热图。

图 10:左图—主成分分析减少了(从 128D 到 2D)图的节点嵌入。右图—原始 128D 嵌入式产品的热图。

在左图中有清楚的节点分离,这表示嵌入的向量空间。这展示了 DeepWalk 如何将图形从力布局可视化转换为向量空间可视化,同时保持一些结构属性。热图还暗示了图形到 3 个聚类的清晰分离。

另一个需要注意的重要事情是,当图形不复杂时,我们也可以使用低维嵌入。这不仅减少了维数,而且改善了优化和收敛,因为在 skip-gram 中有较少的参数要训练。为了证明这一点,我们将创建大小仅为 2 的嵌入。这可以通过设置 DeepWalk 对象dw = DeepWalk(dimensions=2)中的参数来完成。我们将再次想象同样的情节。

图 11:左图:图中的节点嵌入(大小=2)。右图:嵌入的热图。

两个图再次暗示了图中相同数量的集群,并且所有这些仅使用了 1%的先前维度(从 128 到 2,即~1%)。

结论

作为这个类比的答案NLP - word2vec + GraphNeuralNetworks = ?可以说是 DeepWalk(是吗?🙂),这就引出了两个有趣的点,(1) DeepWalk 在 GNN 的影响可以类比 Word2Vec 在 NLP 的影响。这是真的,因为 DeepWalk 是第一批使用神经网络进行节点嵌入的方法之一。这也是一个很好的例子,说明了来自另一个领域(这里是 NLP)的一些成熟的 SOTA 技术是如何移植到一个完全不同的领域(这里是图)并应用的。这就引出了第二点,(2)正如 DeepWalk 不久前发表的(2014 年——只有 6 年,但却是人工智能研究的一生),目前,有很多其他技术可以用来以更好的方式完成这项工作,如 Node2Vec,甚至是 GraphSAGE 等图形卷积网络。也就是说,从基于神经网络的 NLP 开始,word2vec 是最好的起点,我认为 DeepWalk 在同样的意义上是基于神经网络的图形分析的良好开端。也是本文的主题。

干杯。

参考

[1]easy AI——GNN 可能是人工智能的未来

[2] DeepWalk — 论文 | 代码

[3] 网络知识库

[4]扎卡里空手道俱乐部—KONECT 项目

[5] Wevi —文字嵌入可视检查器

[6]空手道俱乐部— 论文 | 代号

[7] Lil'Log —学习单词嵌入

图形表示学习简介

原文:https://towardsdatascience.com/introduction-to-graph-representation-learning-a51c963d8d11?source=collection_archive---------24-----------------------

入门

图上机器学习的主要概念和挑战

延斯·约翰森Unsplash 上拍摄的照片

近年来,图形表示学习的受欢迎程度激增。只有几个活跃的研究人员的时代已经成为遥远的过去。今天,我们看到谷歌或 Twitter 等顶级公司在这一领域进行了大量投资。

令人惊讶的是,许多可用的数据可以被建模为图表。以 Reddit 上的在线社交互动为例。我们可以将每个用户表示为一个连接到其他用户的节点。但是,我们如何分析这种数据,甚至应用机器学习呢?

在图形表示学习中,我们旨在回答这些问题。在这篇文章中,我们将看看图形表示学习的主要概念和挑战。

图表基础

从图中创建邻接矩阵。图片作者。

让我们从基础开始,好吗?

我们将图定义为一组顶点,这些顶点之间有连接(边)。有许多类型的图,例如,它们可以是有向的、无向的或无环的。

为了使图形对任何算法都有用,我们需要将它们转换成数字形式。为了实现这一点,我们可以使用邻接拉普拉斯矩阵度矩阵,它们提供了图形的方便的矩阵表示。每个顶点和每个连接也可以有一个定义其属性的特征向量。

在[1]中可以找到对图的很好的介绍。一旦你对基础知识相当有信心,学习更高级的概念是有好处的,比如图同构图着色

图的特征提取技术

节点级特征的一个例子,即中心性测量。左图说明了特征向量的中心性。右边的例子说明了程度中心性。【来源】

图形特征提取背后的主要思想是以一种更方便的、类似向量的格式来表示关于局部和全局图形结构的信息。我们同样对提取单个顶点的属性信息以及它们之间的连通性感兴趣。

从图中提取的特征可以分为三种类型:节点级、图级和邻域重叠特征。

对于节点级特征,我们的目标是为每个顶点生成一个特征向量。一些最流行的特征提取方法是节点度、中心性方法或聚类系数。为了计算这些特征,我们可以使用来自顶点的最近邻居的信息,或者来自更远的 K 跳邻居的信息。

我们也可以采取更一般的方法,为整个图创建一个特征。它被称为图形级特征。这可以通过邻接矩阵等基本特征来实现,也可以通过 Weisfeiler-Lehman 或 Graphlet 内核等更复杂的迭代方法来实现。

图的最后一种特征提取是邻域重叠特征。它们是专门为提取节点之间的连接信息而设计的。它们可以进一步细分为局部和全局方法。前者描述了两个节点之间的邻域的相似性,而后者描述了某些节点是否属于图中的同一社区(即一组密集聚集的节点)。

你可以在这篇文章中找到对特征提取技术的深入解释。

图上的预测任务

预测顶点的动物类型。图片作者。图标按图标 8

在图上使用机器学习的主要问题是节点是相互连接的。这打破了独立数据点的假设,这迫使我们使用更精细的特征提取技术或新的机器学习模型来处理这个问题。

预测任务在图上的定义也有很大不同。我们可以将其分为 4 种主要类型:节点分类、链接预测、整个图的学习和社区检测。

节点分类的目的是预测图中顶点的属性。链接预测也非常相似,但它预测两个顶点之间的链接(连接)的属性。这些任务被称为半监督学习,因为该图将同时包含训练和测试数据

学习整个图形是最直观的方法。我们将整个图形作为输入,并基于它生成预测。它非常类似于标准的机器学习回归和分类任务。

最后,对于社区检测,我们的目标是识别图中密集的顶点簇。

如果你想了解更多关于图表上的预测任务,请看这里的。

图形神经网络

由 Duvenaud 等人创建的第一个图形神经网络架构之一。它是一种消息传递神经网络。 【来源】

为了重新定义图上的神经网络,我们必须提出全新的深度学习架构[2]。

最简单的架构是消息传递神经网络。在这里,前向过程的一个等效过程是来自顶点邻域的要素的迭代聚合。每个聚合操作都被视为一个层。在 n 次迭代之后,我们使用一个最终的聚合操作将所有信息提取为一个向量/矩阵。

我们也可以在图上定义图卷积神经网络。它们可以分为空间方法和光谱方法。空间方法是最直观的方法:我们定义一个核来对图形进行卷积,类似于 CNN。频谱方法稍微复杂一些:我们考虑傅立叶域中的图形,并集中处理通过图形传播的信号。

生成图模型

这些模型的目的是创建具有所需属性的新图。这里,我们希望模型的输出是一个图[2]。但是我们为什么需要生成图表呢?

首先,我们可以使用这些图表作为机器学习模型的基准数据[2]。例如,如果我们想要检测社区,我们可以创建一个生成图模型,该模型可以创建具有社区的图。通过定义这些模型,我们还可以知道生成图的特定实例的可能性有多大。

鄂尔多斯-雷尼模式就是一个很好的例子。这是一个非常简单的模型,它将两个任意节点之间的连接概率指定为 r. 通过这个参数,我们可以控制生成的图的连接密度。

更复杂的模型包括随机块模型、优先附件和不同的变分自动编码器方法。在2中可以找到对这些模型的详细解释。

几句遗言

图上的机器学习并不简单。我们已经看到,大多数标准的机器学习方法都必须重新定义到图形域中。图形上的特征提取、预测任务与正常的机器学习问题非常不同。我们希望通过创建处理图表数据的新技术,我们可以充分利用图表中的信息,并创建性能更好的模型。

关于我

我是阿姆斯特丹大学的人工智能硕士学生。在我的业余时间,你可以发现我摆弄数据或者调试我的深度学习模型(我发誓这很有效!).我也喜欢徒步旅行:)

如果你想了解我的最新文章和其他有用的内容,以下是我的其他社交媒体资料:

参考

[1] 罗宾·j·威尔逊的图论

[2] 林子幸·汉密尔顿的《图形表示学》一书

分层建模简介

原文:https://towardsdatascience.com/introduction-to-hierarchical-modeling-a5c7b2ebb1ca?source=collection_archive---------9-----------------------

使用贝叶斯分层模型对自然聚集的数据建模

此分析中不同组之间的系数分布

介绍

在我们的数据集中发现不完全独立的样本并不罕见。数据集中的样本通常形成聚类或组,在这些聚类或组中共享一些属性。这通常需要在建模时特别注意,以构建可靠的模型,原因有两个。首先,对于像最大似然估计这样的统计分析过程,样本的独立性是一个重要的假设。第二,我们希望在我们的模型中捕捉预测因素对不同群体的影响的变化,这种变化被称为背景效应。

一个常用的例子,我发现足以理解这种情况是学生在学校的表现。在有多个班级学生的学校里,学生的学业表现受到他们个人能力(称为固定效应)和他们所在班级(称为随机效应)的影响。也许被分配到某个班级的老师比其他人教得更好,或者班级中高比例的聪明学生为学生创造了一个竞争环境,让他们表现得更好。

处理这种情况的一种方法是为每个类构建多个模型,称为。但是这种方法并不总能产生可靠的结果。比如学生很少的班级对应的模型,会很误导人。一个单独的非 pooled 模型可能无法充分拟合数据。我们想在这两个极端之间找到一个折中的中间地带——部分统筹。这就把我们带到了贝叶斯分层建模,也称为多级建模。

在这种方法中,参数在不同级别的组中相互嵌套。粗略地说,它给出了未汇集和汇集模型估计的加权平均值。分层建模是贝叶斯推理和统计建模中最强大而简单的技术之一。在这篇文章中,我将用一个实际的例子来介绍这个想法。注意,这篇文章并没有涉及贝叶斯分析的基础。该示例的源代码可以在 GitHub 的笔记本中找到。

数据

用于说明的数据集类似于上面的学生示例,只是我们试图找到来自不同学校的学生的数学成绩。在我们的例子中,我们使用作业完成情况作为预测指标。你可以在这里找到原始数据,在这里找到 csv 版本

第一眼

绘制学生相对于家庭作业的数学成绩,以及的未拟合的 OLS 回归拟合给了我们这个结果:

具有非 pooled 回归拟合的数据样本

可视化学校层面的数据揭示了一些有趣的模式。我们还绘制了适合每个学校的汇集的回归线和未汇集的回归线,以供参考。为了简单起见,我们使用 OLS 回归。

合并回归的数据样本适合不同的组

该图显示了各组之间关系的变化。我们还注意到,在某些组中,作业完成率较高的少数数据点(可能的异常值)对估计值有很大影响。

层次模型

我们将使用 PyMC3 构建我们的贝叶斯层次模型。我们将在我们的组级参数上构建超优先级,以允许模型在组间共享学生的个人属性。

该模型可以表示为 yᵢ = αⱼᵢ + βⱼᵢxᵢ + εᵢ,

或者用概率符号表示为 y∞n(αⱼ+βⱼx,ε)。

对于这个模型,我们将使用随机斜率β和截距α。这意味着它们将随每组而变化,而不是整个数据的恒定斜率和截距。概率模型的图示如下所示。

本例中使用的分层模型的图形表示

虽然我在这里通过目测样本的总体分布来选择我的先验,但是使用无信息的先验也会导致类似的结果。下面的代码片段定义了所使用的 PyMC3 模型。

with pm.Model() as model:
    # Hyperpriors
    mu_a = pm.Normal('mu_a', mu=40, sigma=50)
    sigma_a = pm.HalfNormal('sigma_a', 50)

    mu_b = pm.Normal('mu_b', mu=0, sigma=10)
    sigma_b = pm.HalfNormal('sigma_b', 5)

    # Intercept
    a = pm.Normal('a', mu=mu_a, sigma=sigma_a, shape=n_schools) # Slope
    b = pm.Normal('b', mu=mu_b, sigma=sigma_b, shape=n_schools)

    # Model error
    eps = pm.HalfCauchy('eps', 5)

    # Model
    y_hat = a[school] + b[school] * homework

    # Likelihood
    y_like = pm.Normal('y_like', mu=y_hat, sigma=eps, observed=math)

我们将使用 NUTS 采样器从后验分布中抽取样本。

with model:
    step = pm.NUTS()
    trace = pm.sample(2000, tune=1000)

对应于每个学校的轨迹图以及斜率和截距的后验分布如下图所示。

分层模型的轨迹图

每组截距和斜率的后验分布

我们可以看到不同学校系数估计值的差异。我们还可以清楚地解释与分布估计相关的不确定性。下面的后验预测回归(灰色)线是从每组估计值的后验分布中取样的,给出了关于数据的模型的更好的图像。

分层模型的后验预测拟合

请注意,显示负斜率的组通常具有更高的不确定性。该模型在群体级别的噪声敏感度和学生级别的全局估计值之间找到了一个折衷点(在 IDs 7472、7930、25456、25642 中很明显)。这意味着我们必须对从这些群体的模型中得出的决定更加谨慎。我们还观察到,随着更多的数据和更小的偏差,贝叶斯模型收敛到该组(ID 62821)的 OLS 模型,如预期的那样。我们还可以通过绘制从mu_amu_b的回归线来检查学生级别关系(这里我省略了)。

不同模型的交叉验证将显示层次建模方法的优越性。交叉验证可以在两个级别执行:

  1. 在一个小组中找出学生,并根据其预测进行评估。
  2. 支持整个团队并评估其预测。请注意,这在池模型中是不可能的。

我在这里不进行验证,因为这里使用的频率主义者和贝叶斯模型不能进行公平(或简单)的比较。但是 CV 可以通过用贝叶斯线性回归代替 OLS 回归并比较它们的模型的均方根偏差(RMSD)来执行。

结论

贝叶斯分层建模可以用自然聚集的数据产生健壮的模型。它们通常允许我们建立简单和可解释的模型,而不是像集成或神经网络这样常用于这种复杂数据的频繁技术。尽管模型中的参数数量增加了,它们也防止了过度拟合。这篇文章仅仅是对层次模型的介绍,其固有的简单性允许我们实现特定于我们的数据的模型的不同变体(例如:添加子组,使用更多的组级预测器)并进行不同类型的分析(例如:寻找级别之间的相关性)。

资源

[## GLM:分级线性回归- PyMC3 3.8 文档

本教程改编自达内·埃尔伯斯和托马斯·威奇的博客文章《两全其美…

docs.pymc.io](https://docs.pymc.io/notebooks/GLM-hierarchical.html) [## pymc 3-pymc 3.8 文档中的(广义)线性和分层线性模型

让我们生成一些斜率已知的数据,截取并拟合一个简单的线性 GLM。glm.linear_component()函数…

docs.pymc.io](https://docs.pymc.io/notebooks/GLM.html) [## 1.9 分层逻辑回归| Stan 用户指南

最简单的多级模型是分层模型,其中数据被分组到不同的类别(或…

mc-stan.org](https://mc-stan.org/docs/2_24/stan-users-guide/hierarchical-logistic-regression.html)

A.Gelman 等人,《贝叶斯数据分析》(2013 年),第 5 章,CRC 出版社

感谢您的阅读!我将感谢任何关于这个帖子的反馈。

你可以在 Linkedin 上联系我,在 GitHub 上关注我。

Hive 简介

原文:https://towardsdatascience.com/introduction-to-hive-859ba31a5769?source=collection_archive---------20-----------------------

Hive & SQL 编码初学者指南

图像信用—Confusedcoders.com

本文主要关注 Hive、它的特性、用例以及 Hive 查询。因为许多 DML 和 DDL 查询与 SQL 非常相似,所以它可以作为任何 SQL 新手的基础或构建块。

Apache Hive 通常被称为构建在 Apache Hadoop 之上的数据仓库基础设施。最初由脸书开发,用于查询他们每天大约 20TB 的输入数据,目前,程序员使用它对存储在 HDFS (Hadoop 分布式框架系统)等文件系统中的大型数据集进行特别查询和分析,而无需了解 map-reduce 的细节。Hive 最好的部分是查询被 Hive 引擎隐式地转换成高效的链式 map-reduce 作业。

蜂巢的特点:

  • 支持不同的存储类型,如纯文本、csv、Apache Hbase 等
  • 数据建模,如创建数据库、表格等。
  • 易于编码;使用类似 SQL 的查询语言 HiveQL
  • ETL 功能,例如提取、转换和将数据加载到表中,以及连接、分区等。
  • 包含内置的用户定义函数(UDF ),用于操作日期、字符串和其他数据挖掘工具
  • 无论布局如何,非结构化数据都显示为看起来像表格的数据
  • 自定义映射器、缩减器和 UDF 的插件功能
  • Hadoop 上的增强查询

Hive 的使用案例:

  • 文本挖掘 —具有便捷结构的非结构化数据,通过 map-reduce 进行覆盖和分析
  • 文档索引 —为多个文档分配标签以便于恢复
  • 业务查询 —查询大量历史数据以获得可操作的洞察,例如交易历史、支付历史、客户数据库等。
  • 日志处理 —处理各种类型的日志文件,如通话日志、网络日志、机器日志等。

Hive 中的编码

我们将使用一个名为“transaction”的表来了解如何在 Hive 中查询数据。事务表包含属性 id、item 和 sales。

以下是任何编程语言的一些最佳编码实践。

[## 对于数据科学的工作,你的编码技能够好吗?

5 编码嗅探如果你在数据科学行业工作,你必须知道

towardsdatascience.com](/are-your-coding-skills-good-enough-for-a-data-science-job-49af101457aa)

配置单元中的 DDL 命令

DDL 是数据定义语言的简称,它处理数据库模式和描述,说明数据应该如何驻留在数据库中。一些常见的例子有

创建表格

  • 创建表—创建表事务(id INT,item STRING,sales FLOAT);
  • 在特定位置存储表格—创建表格事务(id INT,item STRING,sales FLOAT)行格式分隔字段,以“\001”终止,存储为文本文件位置
  • 对表进行分区—创建由(id INT)分区的表事务(id INT,item STRING,sales FLOAT)

翻桌

  • 删除表交易记录;

改变表格

  • 将表事务重命名为 transaction _ front _ of _ stores
  • 添加列—ALTER TABLE transaction ADD COLUMNS(customer _ name STRING);

显示表格

  • 显示表格;

描述表格

  • 描述交易记录;
  • 描述扩展交易记录;

配置单元中的 DML 命令

DML 是数据操作语言的简称,它处理数据操作,包括最常用的 SQL 语句,如 SELECT、INSERT、UPDATE、DELETE 等。它主要用于存储、修改、检索、删除和更新数据库中的数据。

加载数据

  • 从外部文件加载数据——加载数据本地路径“<file_path>”【覆盖】到表;</file_path>
  • 将数据本地路径“/documents/datasets/transaction . CSV”[OVERWRITE]加载到表事务中;
  • 从单独的表写入数据集—插入覆盖表事务 SELECT id,item,date,volume FROM transaction _ updated

选择指令

select 语句用于从数据库表中提取数据。主要用于查看记录、选择必需的字段元素、获取不同的值以及显示任何筛选、限制或分组操作的结果。

要从事务表中获取所有记录:

从交易记录中选择*;

要从事务表中获取不同的事务 id:

从交易记录中选择不同的 id;

极限语句

与 Select 语句一起使用,限制编码人员希望查看的行数。任何事务数据库都包含大量数据,这意味着选择每一行都会导致更长的处理时间。

SELECT *从交易限额 10;

过滤语句

SELECT * FROM 销售额> 100 的交易;

Group by 语句

Group by 语句用于汇总不同级别的数据。设想一个场景,我们希望按商品计算总销售额。

选择项目,SUM(sales)作为按项目分组的交易中的销售额;

如果我们想过滤掉所有销售额至少为 1000 英镑的商品。

按销售额> 1000 的项目从交易组中选择项目,SUM(sales)作为销售额;

加入配置单元

为了组合和检索多个表中的记录,我们使用了 Hive Join。目前,Hive 支持两个或更多表的内、外、左和右连接。语法类似于我们在 SQL 中使用的语法。在我们看语法之前,让我们了解不同的连接是如何工作的。

配置单元中的不同联接

SELECT A . * FROM transaction A { LEFT | RIGHT | FULL } JOIN transaction _ date B ON(A . ID = B . ID);

注意事项:

  • 配置单元不支持 IN/EXISTS 子查询
  • 配置单元不支持不包含相等条件的连接条件
  • 可以连接多个表,但要组织好表,使最大的表出现在序列的最后
  • 如果对于每个表,在 join 子句中使用了相同的列,则 Hive 会将多个表的连接转换为单个 map/reduce 作业

优化配置单元中的查询

为了优化 hive 中的查询,这里有 5 条你应该知道的经验法则

  1. 默认情况下,分组、聚合函数和连接发生在 reducer 中,而过滤操作发生在 mapper 中
  2. 使用 hive.map.aggr=true 选项直接在地图任务中执行第一级聚合
  3. 根据正在执行的任务类型设置映射器/缩减器的数量。对于筛选条件,请使用 set mapred . mapper . tasks = X;对于聚合操作:设置 mapred . reduce . tasks = Y;
  4. 在连接中,序列中的最后一个表通过 reducers 进行流式传输,而其他表则被缓冲。 组织表格,使最大的表格出现在序列的最后
  5. 流表和地图连接可用于加速连接任务

想了解更多关于 Python 可视化的知识吗?

[## 数据可视化:用 Python 中的图表说出来

使用 matplotlib、pyplot 和…的 python 可视化最佳实践和概念的完整实践指南

towardsdatascience.com](/data-visualization-say-it-with-charts-in-python-138c77973a56) [## 现代分析的黎明——了解商业智能的一些最新趋势…

基于调查的方法来确定每个数据科学家都应该知道的 BI 工具

towardsdatascience.com](/the-dawn-of-modern-analytics-a-look-into-some-of-the-recent-trends-of-business-intelligence-fc12cdf41cae)

关于作者:高级分析专家和管理顾问,帮助公司通过对组织数据的商业、技术和数学的组合找到各种问题的解决方案。一个数据科学爱好者,在这里分享、学习、贡献;可以和我在 上联系 推特

Hydra.cc 简介:配置数据科学项目的强大框架

原文:https://towardsdatascience.com/introduction-to-hydra-cc-a-powerful-framework-to-configure-your-data-science-projects-ed65713a53c6?source=collection_archive---------31-----------------------

尝试不同的参数和模型,而无需花费数小时来修改代码!

照片由贾斯特斯·门克Unsplash 拍摄

动机

玩不同的特征工程方法和机器学习模型很有趣,但在获得好的结果之前,你很可能需要调整你的特征工程方法和调整你的机器学习模型。

例如,在下面的速配数据中,考虑到它们不是重要的特征,你可能想去掉iid, id, idg, wave, career。但是在对数据做了更多的研究之后,你意识到career将是预测两个人是否会有下一次约会的一个重要特征。所以你决定不放弃career专栏。

如果您正在进行硬编码,这意味着将数据直接嵌入到脚本的源代码中,如下所示

并且您的文件很长,您可能需要一段时间来找到指定删除哪些列的代码。如果从一个只包含数据信息的简单文本中修复列,而不使用像这样的其他 python 代码,这不是很好吗?

这时你需要一个配置文件。

什么是配置文件?

配置文件包含定义运行程序的设置的纯文本参数。一个好的做法是避免在 python 脚本中硬编码,而在配置文件中保留与数据相关的所有信息,比如删除哪些列、分类变量

这种做法不仅节省了您在脚本中搜索特定变量的时间,而且使您的脚本更具可重复性。

例如,我可以对完全不同的数据重用这段代码,因为代码中没有指定列名。为了让代码为新数据工作,我需要做的就是修改我的配置文件中的列名!

配置文件的通用语言是 YAML。YAML 是所有编程语言的人性化数据序列化标准。语法易于阅读,几乎与 Python 相似。在这里找到更多关于 YAML 语法的信息。

Hydra.cc 简介

我希望上面的简短解释能帮助你理解配置文件的重要性。但是我们如何访问配置文件中的参数呢?

有一些工具可以读取配置文件,比如 PyYaml ,但是我最喜欢的是 Hydra.cc 。为什么?因为它允许我:

  • 无缝更改我在终端中的默认参数
  • 在不同的配置组之间切换
  • 自动记录结果

让我们了解如何开始使用 hydra.cc,并探索使用这一强大工具的好处。

开始

安装 Hydra.cc

pip install hydra-core --upgrade

让我们从一个具体的例子开始:

例如,如果您有如下所示的配置文件,其中包含关于数据路径、编码、管道类型和目标列的所有特定信息

您需要做的就是将装饰器@hydra.main(config_path='path/to/config.yaml')添加到将使用配置文件的函数中。确保在函数中添加config来访问配置文件。

现在,您可以使用配置文件中的任何参数了!如果你想知道目标的名字,

target: match

你所需要做的就是调用config.target来得到字符串‘匹配’!

请注意,您不需要将单词“match”用引号括起来。如果它是一个单词,YAML 文件会将其视为一个字符串。

简单命令行应用程序

Hydra.cc 允许您在终端中覆盖配置文件中的默认参数。例如,如果您想要将机器学习模型从决策树切换到逻辑回归

您不需要重写配置文件。您可以在运行文件时在终端中键入变量的替代参数

python file.py model=logisticregression

并且模型会切换到 logistic 回归!

更好的是,如果您的配置文件很复杂,Hydra.cc 还允许您通过制表符结束来更容易地访问文件中的参数!你可以在这里找到关于标签完成的细节。

在不同的配置组之间切换

为了保持配置文件的简短和结构化,您可能希望为不同的模型创建不同的文件以及它们的参数,如下所示

您可以在命令行上指定要定型的模型的配置文件

python file.py model=logistic

现在,您可以在不同的模型之间切换,并轻松访问它们的超参数!

自动记录

如果你想记录跑步的结果,记录是很重要的。但是由于设置成本,许多人不使用 Python 日志记录。Hydra.cc 根据一天的情况,自动创建所有结果并保存在“输出”文件夹中

每个日文件夹都是根据小时和分钟来组织的。您将看到与您的运行相关的所有日志,以及用于该运行的配置文件!

如果您碰巧更改了您的配置文件,并且不记得您用来生成某个输出的配置文件是什么样子的,您可以查看当天的文件夹来找出答案!

在这里找到更多关于伐木的信息

因为在运行 hydra decorator 包装的函数时,您位于输出目录中,所以如果您想要访问父目录中的其他文件,请确保使用utils.to_absolute_path('path/to/file')

Current working directory  : /Users/khuyentran/dev/hydra/outputs/2019-10-23/10-53-03Original working directory : /Users/khuyentran/dev/hydrato_absolute_path('foo')    : /Users/khuyentran/dev/hydra/footo_absolute_path('/foo')   : /foo

结论

恭喜你!您已经了解了配置文件的重要性以及如何无缝配置您的数据科学项目。我发现,当我将所有与数据相关的信息都放在一个单独的文件中时,会更有条理。我还发现,当我所需要做的就是调用python file.py variable=new_value.时,试验不同的参数会更容易。我希望通过在数据科学实践中结合配置文件和 Hydra.cc,您也能获得同样的好处。

下面是使用 hydra.cc 和 config 文件的示例项目

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上与我联系。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如

[## 你应该从 Jupyter 笔记本转向脚本的 5 个理由

使用脚本帮助我认识到 Jupyter 笔记本的缺点

towardsdatascience.com](/5-reasons-why-you-should-switch-from-jupyter-notebook-to-scripts-cb3535ba9c95) [## 如何用 Faker 创建假数据

您可以收集数据或创建自己的数据

towardsdatascience.com](/how-to-create-fake-data-with-faker-a835e5b7a9d9) [## 如何使用 HyperDash 远程监控和记录您的机器学习实验

培训需要很长时间才能完成,但你需要去洗手间休息一下…

towardsdatascience.com](/how-to-monitor-and-log-your-machine-learning-experiment-remotely-with-hyperdash-aa7106b15509) [## 如何在数据科学项目中利用 Visual Studio 代码

直到发现一种新的有效方法,我们才意识到我们是多么低效

towardsdatascience.com](/how-to-leverage-visual-studio-code-for-your-data-science-projects-7078b70a72f0) [## 如何在一行代码中跨不同环境共享 Python 对象

为建立与他人分享你的发现的环境而感到沮丧?以下是如何让它变得更简单

towardsdatascience.com](/how-to-share-your-python-objects-across-different-environments-in-one-line-of-code-f30a25e5f50e)

IBM 联邦学习简介:一种在私有数据上训练 ML 模型的协作方法

原文:https://towardsdatascience.com/introduction-to-ibm-federated-learning-a-collaborative-approach-to-train-ml-models-on-private-data-2b4221c3839?source=collection_archive---------42-----------------------

在训练来自不同来源的数据时,如何保证数据的安全?

IBM Research 刚刚在 Github 上发布了 IBM 联邦学习。如果您一直在寻找一种方法,在保持数据私密的同时,利用从多个资源收集的数据来提高模型训练,那么这个框架非常适合您。本文将解释为什么需要联邦学习以及如何开始使用该框架。

照片由晨酿Unsplash 拍摄

动机

当训练一个机器学习模型时,我们通常知道你的数据看起来如何,数据的分布和统计。

但是在现实世界中,我们可能会使用不同来源的数据,却不知道这些数据是什么样的。为什么?因为数据安全在不同的企业中很重要。

例如,一个航空联盟想要模拟新冠肺炎最近的事件将如何影响航班延误。在航空联盟中,我们有几家不同的航空公司,它们拥有不同的数据。因为这些航空公司是竞争对手,所以原始数据不能在每个航空公司之间共享。但是航空联盟需要用组合数据来训练模型!

可能还有其他非竞争原因,例如:

  • 对于一些企业来说,将数据移动到一个位置可能不切实际或成本高昂,尤其是在数据生成速度很快或数据量很大的情况下。
  • 即使在同一家公司,客户数据库也可能位于不同的国家,数据不能被带出这个国家。
  • 由于监管和保密的原因,金融公司不能共享交易数据,医疗机构也不能共享患者数据。

那么解决办法是什么呢?这就是我们需要联合学习的时候。

什么是联合学习?

联合学习(FL)是一种训练机器学习模型的方法,不需要与中央实体共享数据集。在联合学习中,模型是在多方之间协作训练的。各方可以保留他们自己的训练数据集,但是仍然能够参与共享的联合学习过程。

IBM 数据科学和人工智能会议 4 中检索的图像

各方之间的学习过程通常使用单个集合器。一个汇总者将与各方沟通并整合培训过程的结果。

例如,神经网络的过程可以是:

  • 各方对其训练数据运行本地训练过程,与聚合器共享其模型的权重。
  • 然后,这些权重将使用融合算法聚合所有各方的权重向量。
  • 然后,将合并后的模型发回给各方进行下一轮训练。

联合决策树算法可以在聚合器中增长树,并基于各方的数据集向各方查询(请求)计数信息。

FL 的整个过程都是为了保证在不共享各方原始数据的情况下,从数据集合中创建一个健壮的机器学习模型!

但这是最优的吗?

虽然 FL 不需要集中管理培训数据,但它也带来了一些新的变化,例如:

  • 数据集异质性:分布的差异、各方不同的数据集大小、不同的属性(即一家航空公司的富客户可能比另一家航空公司多)。因此,整个训练数据集没有共同的属性,如预处理方法、微调算法和模型性能评估。
  • 隐私:一些联合学习场景要求不同的参与方(或者甚至是聚合方)不能基于在训练过程中交换的消息(例如,权重)得出关于彼此训练数据的见解
  • 技能: FL 需要从机器学习到分布式系统再到密码学的不同技能。很难找到具备所有这些技能的员工。

理想情况下,我们希望在没有部署难度的情况下解决上述问题,尽可能避免打开端口等耗时的过程。

幸运的是,IBM Federated Learning框架解决了上述所有挑战,并且能够轻松地将 FL 集成到高效的机器学习工作流中。

了解一个框架的最好方法就是去玩它!我们需要不止一个政党来检验这一点。但是不要担心,我们可以模拟多方试图从不同的机器训练他们的数据的场景!培训的效果如何?敬请期待,静观其变。

IBM 联合学习

下面的步骤可以在 IBM Federated learning Github repo 的设置部分找到

设置

从克隆这个 repo 开始。然后转到创建的文件夹。

安装所有要求。我真的强烈推荐这个项目使用康达装置。

conda create -n <env_name> python=3.6
conda activate <env_name>

通过运行以下命令安装 IBM FL 包:

pip install <IBM_federated_learning_whl_file>

分割样本数据

这个例子解释了如何在 CNN 上运行联合学习,在 MNIST 数据上用 Keras 训练实现。

我们需要不止一个政党来观察 FL 是如何工作的。我们可以使用generate_data.py在任何集成数据集上生成样本数据。例如,我们可以运行:

python examples/generate_data.py -n 2 -d mnist -pp 200

该命令将从 MNIST 数据集中生成各有 200 个数据点的两个交易方。

创建配置文件

要运行 IBM federated learning,您必须拥有聚合器和各方的配置文件。每个配置文件都包含有关各方的信息。您可以使用generate_configs.py脚本生成这些配置文件。

例如,您可以运行:

python examples/generate_configs.py -m keras_classifier -n 2 -d mnist -p examples/data/mnist/random

这个命令将为keras_classifier模型生成配置,假设有两方。-p是当事人数据的路径。

开始学习

现在把你自己放在每个政党和聚合者的位置上。请记住,在现实生活中,各方和聚合者不会看到彼此的屏幕,但他们会在培训过程中进行协调

启动聚合器

要启动聚合器,请打开一个终端窗口,运行之前设置的 IBM FL 环境。

  1. 在终端运行中:
python -m ibmfl.aggregator.aggregator examples/configs/keras_classifier/config_agg.yml

其中提供的路径是聚合器配置文件路径。

2.然后在终端中,键入START,并按回车键。这意味着聚合器开始接受来自其他方的连接。

登记当事人

要注册新的参与方,请为每个参与方打开一个新的终端窗口,运行之前设置的 IBM FL 环境。

  1. 在终端运行中:
python -m ibmfl.party.party examples/configs/keras_classifier/config_party0.yml

其中提供的路径是参与方配置文件的路径。

2.在每一方的终端中,键入START并按回车键。这意味着该方开始接受来自聚合器的连接

3.然后在每一方的终端中,键入REGISTER并按回车键。这意味着各方加入 FL 项目

火车

要启动联合培训,请在聚合器终端中键入TRAIN,然后按 enter 键。

同步

要在各方之间同步模型,请键入SYNC

救援

要保存模型,在您的聚合器终端中键入SAVE,并按 enter 键。

瞧啊。现在每个派对的模型都保存到你的文件夹里了。在真实的场景中,每一方将只看到他们的一个模型文件。

现在我们有了可以用于预测的模型!

停止

记住在聚合器终端和当事人终端都键入STOP来结束实验过程。恭喜你!您的团队刚刚完成培训过程,但没有透露您的数据。

预言;预测;预告

假设你是 0 方,要用模型预测你方的测试数据,你需要做的就是加载模型,预测你方的测试数据。

厉害!你的队伍获得 0.81 的 f1 分数。您不仅保护了您的数据,还获得了一个强大的机器学习模型!

但是 FL 车型相比本土车型性能如何?

我将使用来自 IBM 数据科学和人工智能会议 4 的截图来比较两者之间的性能

IBM 数据科学和人工智能会议 4 中检索的图像

如您所见,第 1 方本地模型性能的所有指标,包括准确度、f1、精确度和召回率,都高于本地模型性能!通过合并来自其他来源的数据,您可以获得一个更可靠的模型来预测您所在政党的数据。

结论

恭喜你!您刚刚学习了如何在不共享数据的情况下,在数据集的组合上训练机器学习!最重要的是,设置培训不需要高级技能。

您所需要做的就是在您的项目文件中添加一个配置,指定相关的信息,比如连接、数据、模型。然后在终端上使用一些简单的命令行,同时设置和训练各方。

Github 库以及该框架的文献可以在这里找到。您也可以使用 IBM 联邦学习松弛渠道直接联系框架的开发团队。

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedInTwitter 上和我联系。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

[## 我收集了超过 1k 的顶级机器学习 Github 配置文件,这就是我的发现

从 Github 上的顶级机器学习档案中获得见解

towardsdatascience.com](/i-scraped-more-than-1k-top-machine-learning-github-profiles-and-this-is-what-i-found-1ab4fb0c0474) [## Datapane 简介:构建交互式报表的 Python 库

创建精美报告并与您的团队分享分析结果的简单框架

towardsdatascience.com](/introduction-to-datapane-a-python-library-to-build-interactive-reports-4593fd3cb9c8) [## 如何用 Voronoi 图找到最近的医院

给定美国医院的大型数据集,我们如何快速找到最近的医院?

towardsdatascience.com](/how-to-find-the-nearest-hospital-with-voronoi-diagram-63bd6d0b7b75) [## 如何在数据科学项目中利用 Visual Studio 代码

直到发现一种新的有效方法,我们才意识到我们是多么低效

towardsdatascience.com](/how-to-leverage-visual-studio-code-for-your-data-science-projects-7078b70a72f0) [## 如何用支持向量机学习非线性数据集

支持向量机简介及其在非线性数据集上的应用

towardsdatascience.com](/how-to-learn-non-linear-separable-dataset-with-support-vector-machines-a7da21c6d987)

知识图嵌入简介

原文:https://towardsdatascience.com/introduction-to-knowledge-graph-embedding-with-dgl-ke-77ace6fb60ef?source=collection_archive---------10-----------------------

了解知识图嵌入和两个流行的模型,以产生他们与 DGL 柯

作者:赛勒斯·瓦希德,郑达,乔治·卡里皮斯和巴拉吉·卡马科蒂:AWS AI

知识图(KGs)已经成为一种有效的方法来集成不同的数据源,并为搜索等应用程序建模底层关系。在亚马逊,我们用 KGs 来表示产品之间的层级关系;亚马逊音乐和 Prime Video 上的创作者和内容之间的关系;以及 Alexa 问答服务的信息。以嵌入形式从知识仓库中提取的信息用于改进搜索、推荐产品和推断缺失的信息。然而,很难从具有数百万个节点和数十亿条边的图中训练 KG 嵌入。

亚马逊最近推出了 DGL 客,一个用简单的命令行脚本简化这一过程的软件包。使用DGL-克,用户可以比竞争技术快 2-5 倍的速度为非常大的图形生成嵌入。DGL-KE 通过配置硬件、数据采样参数和损失函数,为用户提供了选择用于生成嵌入和优化性能的模型的灵活性。然而,为了有效地使用这个包,理解嵌入是如何工作的以及计算它们的优化是很重要的。这个由两部分组成的博客系列旨在提供这些信息,并让你准备好开始利用DGL-柯

什么是图表

图形是用来表示事物及其关系的结构。它由两组组成—一组节点(也称为顶点)和一组边(也称为弧)。每条边本身连接一对节点,表明它们之间存在关系。这种关系既可以是无向,例如捕获节点之间的对称关系,也可以是有向,捕获非对称关系。例如,如果一个图被用来模拟社交网络中的人的友谊关系,那么边将是无向的,因为它们被用来指示两个人是朋友;然而,如果该图用于模拟人们在 Twitter 上如何相互关注,那么这些边将是有向的。根据边的方向性,一个图可以是有向的无向的。

图形可以是同质异质。在同构图形中,所有节点代表相同类型的实例,所有边代表相同类型的关系。例如,社交网络是由人和他们的联系组成的图,所有人都代表相同的实体类型。相反,在异构图中,节点和边可以是不同的类型。例如,用于对市场中的信息进行编码的图将具有买方卖方产品节点,这些节点通过想买已买的客户,以及是销售的边连接。

最后,另一类对知识图特别重要的图是多图。这些图在同一对节点之间可以有多条(有向)边,也可以包含环。这些多重边通常是不同类型的,因此大多数多重图是异构的。注意,不允许这些多条边和自循环的图被称为简单图。

什么是知识图

在之前的市场图示例中,分配给不同节点类型(买方、卖方、产品)和不同关系类型(想买、已经买、是客户的、是销售的)的标签传达了关于特定域的节点和关系代表什么的精确信息(通常称为语义 ) 。一旦该图被填充,它将对我们关于该市场的知识进行编码,因为它涉及到所包括的节点和关系的类型。这样的图是知识图的一个例子。

知识图(KG)是一种有向异构多重图,其节点和关系类型具有特定于领域的语义。KGs 允许我们将知识编码成一种人类可以理解的形式,并且可以进行自动分析和推理。kg 正在成为一种流行的方法,以通过不同类型的关系连接的不同类型的实体的形式来表示不同类型的信息。

使用 kg 时,我们采用了一种不同于图中使用的传统顶点和边的术语。知识图的顶点通常被称为实体,有向边通常被称为三元组,并且被表示为( h,r,t )元组,其中 h 是头部实体, t 是尾部实体, r 是将头部实体与尾部实体相关联的关系。注意,术语关系在这里指的是关系的类型(例如,想要购买、已经购买、是客户的和是销售的之一)。

现在让我们用石膏来考察一个民族和他们生活的世界。

场景:
玛丽汤姆兄妹,他们都是 素食者 ,谁 土豆奶酪。玛丽和汤姆都在亚马逊的工作。是汤姆的 同事 的一个小子。让事情变得复杂的是,乔 爱着 玛丽,但我们不知道这种感觉是否得到了回报。

来自 魁北克并以他的家乡菜 Poutine 为傲,这是由 土豆、奶酪和肉汁组成的 。我们还知道,肉汁 以某种形式含有

乔很兴奋地邀请汤姆共进晚餐,并偷偷地邀请了他的兄弟姐妹玛丽。他的计划从一开始就注定要失败,因为他打算为素食的兄弟姐妹提供他最喜欢的魁北克菜 Poutine。

哦!顺便说一下,一个地理琐事:魁北克 位于 的一个的同名省 又位于加拿大* 。*

这个场景中有几个关系没有明确提到,但我们可以简单地从给出的信息中推断出来:

  • 玛丽是汤姆的同事。
  • 汤姆是玛丽的同事。
  • 玛丽是汤姆的妹妹。
  • 汤姆是玛丽的哥哥。
  • Poutine 有肉。
  • Poutine 不是素菜。
  • 玛丽和汤姆不吃布丁。
  • 布丁是一道加拿大菜。
  • 乔是加拿大人。
  • 亚马逊是玛丽、汤姆和乔的工作场所。

一些有趣的负面结论对我们来说似乎是直观的,但对机器来说却不是:

  • 土豆不喜欢玛丽。
  • 加拿大不是来自乔。
  • 加拿大不在魁北克

  • 我们研究的是一个知识图,一组具有不同关系类型的节点:
  • 一对一:玛丽是汤姆的兄弟姐妹。
  • 1 对 N: Amazon 是 Mary、Tom 和 Joe 的工作场所。
  • n 对 1:乔、汤姆和玛丽在亚马逊工作。
  • N 对 N:乔、玛丽和汤姆是同事。

对于这些关系,还有其他的分类观点:

  • 对称:乔是汤姆的同事,汤姆也是乔的同事。
  • 反对称:魁北克位于加拿大意味着加拿大不能位于魁北克。

图 1 显示了一个 KG,它描述了 Mary 的世界。有关如何使用示例的更多信息,请参考嵌入的代码

知识图嵌入

*知识图嵌入是知识图中实体和关系的低维表示。它们提供了一个可用于推断关系的总体 KG 的概括上下文。在上面想象的玛丽的世界中,嵌入提供了关于玛丽、乔和汤姆之间关系的洞察力。在更大和更密集的 KG 中,嵌入可以提供关于分子属性相互作用的见解,以加速药物发现或聚集游戏网络中骗子的用户行为。

计算知识图嵌入,使其满足某些性质;也就是说,它们遵循给定的 KGE 模型。这些 KGE 模型定义了不同的得分函数,其测量两个实体相对于其在低维嵌入空间中的关系类型的距离。这些得分函数用于训练 KGE 模型,使得通过关系连接的实体彼此靠近,而未连接的实体远离。

有很多流行的 KGE 模型如 TransETransRRESCALDistMultComplExRotatE ,这些模型定义了不同的得分函数来学习实体和关系嵌入。DGL-柯使得这些实现可以通过命令行脚本中的一个简单的输入参数来实现。在这篇文章中,我们介绍并比较 TransE 和 TransR 这两种常用方法,为读者提供一些关于模型和权衡的直觉

TransE
基于平移的嵌入模型(TransE) 是一种代表性的平移距离模型,它将实体和关系表示为维度 Rd 的相同语义空间中的向量,其中 d 是具有降低维度的目标空间的维度。源空间中的一个事实被表示为一个三元组(h,r,t),其中 h 是头部的缩写,r 是关系的缩写,t 是尾部的缩写。该关系被解释为平移向量,使得通过关系 r 连接的嵌入实体具有短距离。[3, 4]*

就向量计算而言,这可能意味着向关系添加头部应该接近关系的尾部或 h+r ≈ t。

TransE 执行线性变换,评分函数是以下各项之间的负距离:

**

运输

TransE 不能涵盖非一对一的关系,因为它只了解相似性的一个方面。TransR 通过将关系空间与实体空间分离来解决这个问题,其中 h,t ∈ ℝᵏ和$r ∈ ℝᵈ.语义空间不需要具有相同的维度。在多关系建模中,我们学习每个关系的投影矩阵 M∈ℝᵏˣᵈ,它可以将实体投影到不同的关系语义空间。这些空间中的每一个都捕获了与不同关系相关的实体的不同方面。在这种情况下,使用学习的投影矩阵 Mᵣ作为 hᵣ=hMᵣ和 tᵣ=tM ᵣrespectively.,将具有关系 r 的头节点 h 和尾节点 t 投影到关系空间中图 4 展示了这个投影。

*让我们用一个例子来探讨这个问题。玛丽和汤姆是兄妹兼同事。他们都是素食者。乔也在亚马逊工作,是玛丽和汤姆的同事。TransE 可能最终为 Mary、Tom 和 Joe 学习到非常相似的嵌入,因为他们是同事,但不能识别(不是)兄弟姐妹关系。使用 TransR,我们学习投影矩阵:M_sibling、M_colleague 和 M _ 素食者,它们在学习类似(非)兄弟的关系方面表现得更好。

TransR 中的 score 函数类似于 TransE 中使用的函数,度量 h+r 和 t 之间的欧氏距离,但是距离度量是每个关系空间的。更正式地说:*

*TransR 相对于 TransE 的另一个优势是它能够提取组成规则。提取规则的能力有两个主要好处。它提供了更丰富的信息和更小的存储空间,因为我们可以从其他规则中推断出一些规则。

权衡
TransR 中更具表现力的投影带来的好处增加了模型的复杂性和更高的数据传输率,这对分布式训练产生了不利影响。TransE 要求每个关系有 O( d )个参数,其中 dd 是 TransE 中语义空间的维度,包括实体和关系。由于 TransR 将实体投影到维度为 kk 的关系空间,因此每个关系将需要 O( kd )个参数。根据 k 的大小,这可能会大幅增加参数的数量。在探索 DGL-柯的过程中,我们将检验DGL-柯在显著提高知识嵌入计算效率方面的优势。[5], [7]*

关于在DGL-克中其他实现的详细概述,请查看我们的文档。

下一步是什么?

在这篇博文中,我们介绍了知识图嵌入(kge)的概念,它们是如何工作的,以及生成 kge 的两种流行方法。在我们的下一篇文章中,我们将探索如何加速与DGL-柯的训练。

参考

  1. http://semantic-web-journal.net/system/files/swj1167.pdf
  2. 孙志清,智,建,和。旋转:通过复杂空间中的关系旋转嵌入知识图。澳大利亚统计局/1902.10197,2019 年。
  3. 知识图嵌入:方法与应用综述,毛振东,,李国。DOI 10.1109/TKDE.2017.2754499,IEEE 知识与数据工程汇刊
  4. transE: Antoine Bordes、Nicolas Usunier、Alberto Garcia-Duran、JasonWeston 和 Oksana
    Yakhnenko。翻译用于多关系数据建模的嵌入。神经信息处理系统进展 26。2013.
    5。译者:、林、、孙茂松、、。用于知识图完成的学习实体和关系嵌入。2015 年第 29 届 AAAI 人工智能会议论文集。
  5. 重新校准:马克西米利安·尼克尔、沃克·特雷斯特普和汉斯·彼得·克里格尔。多关系数据集体学习的三向模型。《第 28 届国际机器学习会议论文集》,ICML,2011 年 11 月。
  6. 调查论文:Q. Wang,Z. Mao,B. Wang 和 L. Guo,“知识图嵌入:方法和应用调查”,载于 IEEE 知识与数据工程汇刊,第 29 卷,第 12 期,第 2724-2743 页,2017 年 12 月 1 日。
  7. 主持人:杨碧山、赵文涛、、高剑锋和。在知识库中嵌入用于学习和推理的实体和关系。《学习表征国际会议论文集(ICLR)
    2015,2015 年 5 月。
  8. 复合:特鲁永,约翰内斯·韦尔布尔,塞巴斯蒂安·里德尔,埃里克·高西尔和纪尧姆·布沙尔。简单链路预测的复杂嵌入。更正,abs/1606.06357,2016。
  9. 孙志清,智,建,和。旋转:通过复杂空间中的关系旋转嵌入知识图。澳大利亚统计局/1902.10197,2019 年。

NumPy 线性代数导论

原文:https://towardsdatascience.com/introduction-to-linear-algebra-with-numpy-79adeb7bc060?source=collection_archive---------12-----------------------

带示例的基本概念和操作

张家瑜Unsplash 上拍照

数据以许多不同的格式收集,从数字到图像,从类别到声波。然而,我们需要用数字表示的数据,以便能够在计算机上进行分析。机器学习和深度学习模型需要大量数据。它们的性能高度依赖于数据量。因此,我们倾向于收集尽可能多的数据,以便建立一个稳健而准确的模型。随着数据量的增加,用标量完成的操作开始变得低效。我们需要矢量化或矩阵运算来有效地进行计算。这就是线性代数发挥作用的地方。

线性代数是数据科学领域中最重要的课题之一。在这篇文章中,我们将介绍线性代数中的一些基本术语,并使用 Python 的科学计算库 NumPy 进行示例。

线性代数中有不同类型的对象(或结构):

  • 标量:单一数字
  • Vector:数字数组
  • 矩阵:数字的二维数组
  • 张量:N 维数组,其中 n > 2

让我们为每个对象创建一个例子。我将跳过“标量”,因为它只是一个数字。我们首先导入 numpy:

import numpy as np

有 4 个元素的向量:

2x4 矩阵:

2x2x4 张量:

就 numpy 表示而言,向量是一维数组,矩阵是二维数组,张量是 n 维数组(n>2):

我们也可以用 numpy 创建更高维的数组,但是这些很难可视化。让我们创建一个四维数组,每个维度的大小为 2。

数组的总大小是每个维度的大小的乘积。T2 的印刷版本:

我们已经介绍了基本结构。现在是时候讨论可以在这些结构上完成的基本操作了。

向量运算

  • 当向量与标量相乘时,向量的每个元素都与标量相乘:

  • 另一个常见的操作是点积。两个向量的点积是关于位置的元素乘积的和。一个向量的第一个元素乘以第二个向量的第一个元素,依此类推。这些积的和就是点积,可以用 np.dot() 函数来做。

点积是矩阵乘法的重要部分,我们将在本文后面讨论。

  • 向量的元素求和与减法是通过标准的数学运算完成的。

矩阵运算

矩阵乘法是线性代数中一种广泛使用的运算。解线性方程组时,矩阵乘法非常方便。在复杂的机器学习和深度学习模型中,许多矩阵乘法都是在幕后进行的。优化算法执行大量矩阵乘法来寻找模型参数。因此,这是一个必须知道的操作。

在我们深入研究矩阵乘法之前,最好先了解矩阵的一些性质。矩阵是一个二维数组。如果两个维度中的元素数量(大小)相同,那么我们就有了一个方阵。

单位矩阵是一个在主对角线上包含 1,在所有其他位置包含 0 的方阵。

我们用行数和列数来定义矩阵的形状。例如,下面的矩阵 A 有 3 行 4 列。索引从零开始,所以我们可以通过 A[0]访问第一行,通过 A[:,0]访问第一列。可以通过传递行索引和列索引来访问特定的元素。例如,A[1,1]给出了第二行第二列的元素。

两个矩阵的矩阵乘法基于一个矩阵的行与另一个矩阵的列的点积。乘积矩阵的每个元素是第一个矩阵中的一行和第二个矩阵中的一列的点积。考虑下面的矩阵 A1 和 A2。A1 的第一行是[2,2],A2 的第一列是[1,4]。这两个向量的点积是(2x1)+(2x4)=10,这是乘积矩阵在位置[0,0]的元素。A1 的第三行和 A2 的第三列的点积给出了位置[2,2]处的元素,即 12。

因为第一个矩阵的行乘以第二个矩阵的列,所以第一个矩阵的行数必须等于第二个矩阵的列数。如果我们将 mxn 矩阵(m 行,n 列)乘以 nxk 矩阵,则乘积矩阵的形状为 mxk:

因此,矩阵乘法是不可交换的,这意味着我们不能在乘法中交换矩阵的顺序。因此,AB 不等于 BA。

当我们把一个矩阵和它的相乘,我们得到单位矩阵。因此,

请注意,不是所有的矩阵都有逆矩阵。对于具有逆矩阵的矩阵,它必须是方阵(即行数等于列数)。然而,并不是所有的方阵都有逆矩阵。

如果一个方阵有一个逆,称为可逆非奇异。如果一个方阵没有逆矩阵,它就是一个奇异矩阵。非方阵没有逆矩阵。

单位矩阵的一个重要特征是它在相乘时不会改变矩阵。所以,AI = A .我们用 numpy 确认一下:

正如我们所看到的,对于单位矩阵来说,顺序无关紧要。当从右或左相乘时,它不会改变矩阵。因此,矩阵的左逆等于右逆:

矩阵的逆的逆本身是:

求矩阵的逆矩阵有不同的方法。一种方法叫做排除法。这很简单,但我会把它留到另一篇文章中,以免这篇文章太长。

对矩阵的一个基本操作是转置,这意味着交换行和列。可以使用一个字母(T)和 numpy 来完成:

我们已经讨论了线性代数中的一些基本概念。当然,还有更复杂的概念和操作。然而,从基础到高级一步一步地积累知识总是一个好的做法。

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

线性回归简介

原文:https://towardsdatascience.com/introduction-to-linear-regression-141cde7a46b2?source=collection_archive---------21-----------------------

创建线性回归模型之前要采取的步骤。

在我们开始研究线性回归之前,我想强调在开始处理数据之前理解问题的重要性。我们经常看到统计学家开始谈论斜率、分布和其他实际分析,而没有将问题公式化。正如阿尔伯特·爱因斯坦曾经说过的那样,“问题的表述往往比解决问题更重要,而解决问题可能仅仅是数学或实验技巧的问题”。因此,像所有其他数据分析执行一样,我们需要通过与问题专家合作来制定问题,以便了解特定领域的背景、分析的目标、输出的一致性,并进一步将问题整合到统计术语中。

理解数据收集与制定问题同样重要,因为某些收集过程会对数据产生影响,如果不了解收集过程的某些方面,我们可能会在分析结束时得出错误的结论。理解数据收集的最佳实践有:

  • 查看数据是否是从设计好的调查中收集的。
  • 探索无响应。我们没有得到回复的某些数据可能对问题和我们的分析非常重要。
  • 查找是否有任何缺失值或可能的数据错误,并执行健全性检查。
  • 如有必要,查看测量单位是如何设置和执行标准化的。
  • 看看定性变量如分类变量是如何编码的。

一旦我们明确了我们的问题并理解了数据是如何收集的,我们就可以执行清理和初始数据分析。我们可以简化为:

  • 看数值变量的汇总。
  • 参见变量的分布
  • 寻找可能的相关性
  • 探索任何可能的异常值
  • 用数据健全性寻找数据错误
  • 确保数据类型正确。

线性回归的使用

回归简单地给出了数据集中两个或多个变量的线性关系。我们有一个因变量(或预测变量),与自变量(响应变量)有关系。

我们来复习一些例子,看看能否找到变量之间的关系。在回顾这些数据集时,我们还将讨论为了正确使用线性回归,我们需要做出的某些假设或需要满足的某些条件。

我们的第一组数据是关于英国青少年赌博的。

由于我们没有赌博领域的任何物理背景,我们可以创建一个示例问题陈述来指导我们的分析。这可以简单地理解为“为什么英国青少年赌博?”或者“收入或地位对英国青少年的赌博习惯有影响吗?”或者“教育能帮助减少英国青少年的赌博吗?

我们的数据集中没有缺失值。查看汇总统计数据可以给我们一些提示,看是否有任何数据错误。例如,有些人不在赌博上花钱。我认为这是可信的。最低收入为每周 0.6 英镑。这有意义吗?由于我们没有看到任何明显的错误,如“0”收入或“2”性价值,让我们假设做调查的人准确地收集了这些数据。

基于我们之前定义的问题陈述(“收入或地位对英国青少年的赌博习惯有影响吗?例如),自变量或响应变量“y”为“gamble”。我们可以看到赌博和收入之间有一些线性关系。我们确实看到了语言和地位之间的一些其他相关性,例如,然而,由于我们试图找到一个特定问题的解决方案,我们可以将重点放在赌博反应变量和收入相关变量(预测因素)上。

在我们开始创建回归模型、预测值、误差、截距或斜率之前,我们应该看看作为预测变量的收入和作为响应变量的赌博之间的当前关系是否满足线性回归所需的某些假设和条件。

为了让我们创建线性回归模型,我们需要确保关系是线性的,误差意义是独立的,残差不相互影响,并且它们不遵循特定的模式,收入和赌博之间存在同方差,以便数据看起来不像漏斗和误差分布的正态性,其中观察值主要围绕预测值并且均匀分布。

我发现解释这些假设最简单的方法是通过可视化。以下四张图解释了数据集需要满足线性回归的每个假设。

当我们查看我们的回归线和每个观察值的位置时,我们可以看到存在某种程度的线性,误差彼此不相关,残差没有创建任何看起来像漏斗的模式,并且它们呈正态分布。这意味着,随着我们的独立变量收入增加,赌博支出(我们的依赖反应变量)也会增加。收入和赌博之间有一个明确的正线性关系。

我们不会在本文中进一步扩展我们的分析和创建回归模型,因为这意味着是对线性回归的介绍,但是我们可以以类似的方式探索其他数据集。

让我们来看看另一项研究,我们观察了 97 名患有前列腺癌的男性,他们将接受根治性前列腺切除术。

正如我们所看到的,我们肯定需要理解变量描述,并且必须咨询前列腺相关领域的专业知识,以便完全阐明问题。下面是每个变量的描述;

  • lcavol:癌症卷
  • 体重:癌症体重
  • 年龄:年龄
  • lbph:良性前列腺增生量
  • svi:精囊侵犯
  • lcp:包膜穿透
  • 格里森:格里森得分
  • pgg45:格里森得分 4 或 5 的百分比
  • lpsa:前列腺特异性抗原

让我们假设问题陈述是“男性有哪些特定的属性会导致前列腺癌?”。这些数据来自一项研究,该研究检测了即将接受根治性前列腺切除术的男性的前列腺特异性抗原水平和许多临床指标之间的相关性。这意味着我们的 y 反应变量(因变量)是 lpsa:前列腺特异性抗原。

我们有 97 个观察值,9 个属性。当我们查看最小值和最大值时,我们唯一有疑问的变量是 svi:精囊侵犯和 pgg45:百分比 Gleason 评分 4 或 5。不幸的是,在没有任何医学专业知识的情况下,我们无法确认这些值是否有意义,或者可能是数据错误。因此,我们假设创建这个数据集的统计学家收集了准确的数据。

当我们查看变量之间的相关性时,请记住我们关注的是 lpsa 的定义响应变量,我们看到癌症体积具有最强的相关性。

当我们观察每个观察值在线性线周围的分布时,我们看到了线性、误差的独立性、同方差性和正态性。我们可以坚定地说,lcavol 自变量和 lpsa 因变量之间存在正的线性相关关系。

结论

不管统计分析,我们需要首先制定一个问题陈述,并了解数据的收集。我们可以通过与领域专家、调查员或商业利益相关者的合作来做到这一点。通过遵循数据汇总统计的简单步骤,如数值变量、分布、相关性、异常值、数据错误和数据类型的汇总,我们可以指出数据错误并定义包括线性回归在内的分析方法。为了能够准确地使用线性回归,我们需要确保满足线性回归条件。因为我们不是从研究人员的角度,而是从数据分析师或数据科学家的角度来看数据,所以我们不一定要对每个条件进行每个测试,而是通过查看某些分布图来假设这些条件。

R 中的列表介绍

原文:https://towardsdatascience.com/introduction-to-lists-in-r-ff6469e6ca79?source=collection_archive---------27-----------------------

列表可以包含不同类型的组件。了解如何创建、命名和子集化这些列表。

什么是列表,为什么需要列表?

有几种数据结构可以用来保存数据:

  • 向量(一维数组)—向量可以保存数值、字符或逻辑值,但它们的元素必须都是相同的数据类型。
  • 矩阵(二维数组)——就像向量元素一样,矩阵可以保存数字、字符或逻辑值;但是,它们的元素必须都是相同的数据类型。
  • 数据框(二维对象)——数据框可以保存数字、字符或逻辑值。在一个列中,所有元素必须具有相同的数据类型,但是不同的列可以具有不同的数据类型。
  • 列表(超级数据类型)——列表允许不同的对象,如矩阵、向量、数据框和其他列表,以有序的方式聚集在一个名称(列表的名称)下。这些对象不需要以任何方式相关联。因此,你几乎可以在列表中存储任何东西。

创建列表

我们使用函数[**list()**](http://www.rdocumentation.org/packages/base/functions/list) 来构造一个列表:

my_list <- list(comp1, comp2, ...)

list()函数的参数是列表组件(comp1, comp2,...)。它们可以是矩阵、向量、其他列表等。

假设我们想要创建一个列表(my_list),它包含以下列表组件:my_vectormy_matrixmy_df

# Vector with numerics from 1 up to 10
my_vector <- 1:10# Matrix with numerics from 1 up to 9
my_matrix <- matrix(1:9, ncol = 3)# First 10 elements of the built-in data frame mtcars
my_df <- mtcars[1:10,]

为了构建这个列表,我们再次使用了list()函数:

# Construct list with these different elements:
my_list <- list(my_vector, my_matrix, my_df)

创建命名列表

给列表中的组件命名可以确保我们不会忘记它们代表什么。我们可以在构建列表的过程中或者之后命名我们的组件。举个例子,

# Name components directly during list construction.
my_list <- list(name1 = your_comp1, 
                name2 = your_comp2)

创建一个包含名为name1name2等组件的列表。为了在我们创建列表后给它们命名,我们使用了names()函数,就像我们使用 vectors 一样。这将完成我们上面做的同样的事情:

# Use names() function to name list after construction
my_list <- list(your_comp1, your_comp2)
names(my_list) <- c("name1", "name2")

给你试试

my_list的组件添加名称。对于my_vectormy_matrixmy_df,可以分别使用vecmatdf的名称。

# Vector with numerics from 1 up to 10
my_vector <- 1:10# Matrix with numerics from 1 up to 9
my_matrix <- matrix(1:9, ncol = 3)# First 10 elements of the built-in data frame mtcars
my_df <- mtcars[1:10,]# Construct list with these different elements:
my_list <- list(my_vector, my_matrix, my_df)

解决办法

# Vector with numerics from 1 up to 10
my_vector <- 1:10# Matrix with numerics from 1 up to 9
my_matrix <- matrix(1:9, ncol = 3)# First 10 elements of the built-in data frame mtcars
my_df <- mtcars[1:10,]# Adapt list() call to give the components names
my_list <- list(my_vector, my_matrix, my_df)
names(my_list) <- c("vec", "mat", "df")# Print out my_list
my_list

给你尝试(2)

为电影“闪灵”创建一个列表,它包含三个组件:

  • moviename —带有电影标题的字符串(存储在mov中)
  • 演员 —主要演员名字的向量(存储在act中)
  • 评论 —包含一些评论的数据帧(存储在rev中)
# Character variable for movie name
mov <- "The Shining"# Vector for the names of the movie actors
act <- c("Jack Nicholson", "Shelley Duvall", "Danny Lloyd", "Scatman Crothers", "Barry Nelson")# Data frame of the movie reviews
scores <- c(4.5, 4.0, 5.0)
sources <- c("IMDb1", "IMDb2", "IMDb3")
comments <- c("Best Horror Film I have Ever Seen", "A truly brilliant and scary film from Stanley Kubrick", "A masterpiece of psychological horror")
rev <- data.frame(scores, sources, comments)

不要忘记相应地命名列表组件(电影名称、演员和评论)。

不要忘记相应地命名列表组件(名称是电影名称、演员和评论)。

解决办法

# Character variable for movie name
mov <- "The Shining"# Vector for the names of the movie actors
act <- c("Jack Nicholson", "Shelley Duvall", "Danny Lloyd", "Scatman Crothers", "Barry Nelson")# Data frame of the movie reviews
scores <- c(4.5, 4.0, 5.0)
sources <- c("IMDb1", "IMDb2", "IMDb3")
comments <- c("Best Horror Film I have Ever Seen", "A truly brilliant and scary film from Stanley Kubrick", "A masterpiece of psychological horror")
rev <- data.frame(scores, sources, comments)# Shining List
shinning_list <- list(moviename = mov, actors = act, reviews = rev)
shinning_list

从列表中选择元素

列表通常由许多元素和组件组成;因此,从其中获取单个元素、多个元素或一个组件并不总是简单的。

选择组件的一种方法是使用组件的编号位置。例如,要选择第一个组件(位置1,我们将使用:

my_list[[1]]

注意,这与向量和矩阵不同,向量和矩阵使用单方括号[]而不是双方括号[[]]

我们也可以使用组件的名称来代替位置。我们可以使用[[]]或与$一起使用。例如,以下两种情况都将从shining_list中选择reviews组件。

shining_list[["reviews"]]
shining_list$reviews

有时,您希望深入构件并从选定的构件中选择特定的元素。例如,假设我们想要从shining_list的 actors 数组中选择第一个元素。数组actors是第二个组件,因此可以使用shining_list[[2]]来访问它。由于这个组件也被命名,我们可以使用shining_list$actors来获得相同的结果。

因为我们想要从那个组件中选择第一个元素[1],我们将使用shining_list[[2]][1]shining_list$actors[1]

让你试试

给定下面的shining_list,选择actors向量并打印出来。然后从这个向量中选择第二个元素并打印出来。

# Character variable for movie name
mov <- "The Shining"# Vector for the names of the movie actors
act <- c("Jack Nicholson", "Shelley Duvall", "Danny Lloyd", "Scatman Crothers", "Barry Nelson")# Data frame of the movie reviews
scores <- c(4.5, 4.0, 5.0)
sources <- c("IMDb1", "IMDb2", "IMDb3")
comments <- c("Best Horror Film I have Ever Seen", "A truly brilliant and scary film from Stanley Kubrick", "A masterpiece of psychological horror")
rev <- data.frame(scores, sources, comments)# Shining List
shinning_list <- list(moviename = mov, actors = act, reviews = rev)

解决办法

# Print out the vector representing the actors
shining_list$actors# Print the second element of the vector representing the actors
shining_list$actors[2]

挑战:创建另一个列表

这里有一个挑战来检验你所学到的东西!

假设你已经找到了另一部更近的杰克·尼科尔森电影《无间道》的评论。

这部电影的演员是:

  • 莱昂纳多·迪卡普里奥
  • 马特·达蒙
  • 杰克·尼科尔森
  • 马克·沃尔伯格
  • 维拉·法梅加
  • 马丁·辛

以下是评论:

  • 会再看一遍——4.61
  • 太神奇了!— 5
  • 我喜欢——4.81 分
  • 最佳电影之一— 5
  • 迷人的情节— 4.2

将关于电影的所有信息(如片名、演员和评论)收集到一个变量中会很有用。由于这些数据是不同的类型,我们必须将它们组合在一个列表变量中。

现在,利用上面给出的信息,你要做的是:

  • 创建一个名为movie_title的变量,包含电影的标题。
  • 创建一个名为movie_actors的向量,包含上面列出的演员的名字。
  • 创建两个向量,称为scorescomments,包含来自上面显示的评论的信息。
  • 求复习分数的平均值(scores向量),保存为avg_review
  • 创建一个名为reviews_df的 reviews 数据框架,它结合了scorescomments
  • 创建一个名为departed_list的列表,包含movie_titlemovie_actors,评审数据框为reviews_df,平均评审分数为avg_review,并将其打印出来。

解决办法

# Use the given movie information above to define the movie title and movie actors
movie_title <- "The Departed"
movie_actors <- c("Leonardo DiCaprio", "Matt Damon", "Jack Nicholson", "Mark Wahlberg", "Vera Farmiga", "Martin Sheen")# Use the reviews information above to defined defined the comments and scores vectors
scores <- c(4.6, 5, 4.8, 5, 4.2)
comments <- c("I would watch it again", "Amazing!", "I liked it", "One of the best movies", "Fascinating plot")# Save the average of the scores vector as avg_review
avg_review <- mean(scores)# Combine scores and comments into the reviews_df data frame
reviews_df <- data.frame(scores, comments)# Create and print out a list, called departed_list, which contains movie_title, movie_actors, reviews_df, and avg_review
departed_list <- list (movie_title, movie_actors, reviews_df, avg_review)
departed_list

笔记

所有图片,除非特别注明,均归作者所有。横幅图像是使用 Canva 创建的。

机器翻译导论

原文:https://towardsdatascience.com/introduction-to-machine-translation-5613f834e0be?source=collection_archive---------43-----------------------

自然语言处理笔记

自然语言处理专业课程 1 第 3 周笔记

布鲁诺·沃尔夫Unsplash 上拍摄的照片

之前,我们已经介绍过情感分析向量空间模型。本周我们将学习如何进行机器翻译,但是通过练习如何找到相似的单词向量,我们也将知道如何执行文档搜索,这样我们将一举两得。

要访问我在 Coursera 上关于自然语言处理专业化的所有笔记,请访问关于走向数据科学的自然语言处理系列部分。

转换单词向量

向量空间模型的帖子中,我们讨论了单词向量以及它们如何捕捉单词的重要属性。由于这一点,我们可以使用这些词向量来对齐两种不同语言的词,以获得一个基本的翻译程序。

机器翻译是从一个单词(句子或文档)开始,将其翻译成另一种语言的任务—参见图 1

图 1 :机器翻译的任务是从一种语言翻译成另一种语言。图像中显示的示例显示英语→法语。(图片由作者提供)

如果我们要让一个人来执行这项任务,我们首先要找到一个会说两种语言的人,并让他们创建一个英语和法语单词的大列表(使用图 1 中的例子),这可能是一项非常耗时的任务。

另一方面,如果我们希望机器执行这项任务,我们首先计算与每种语言相关的单词嵌入,然后检索该语言的一个单词的特定单词嵌入,例如,我们可以检索英语单词 cat,然后想出一种方法将英语单词嵌入转换为在法语单词向量空间中有意义的单词嵌入。有了翻译语言中的这个单词向量(在我们的场景中是法语向量空间),我们将找到与该单词最相似的向量,这些向量将成为我们翻译的候选单词。在我们的示例场景中,我们希望提出单词“chat ”,因为这是 cat 的法语单词— 图 2 提供了对该任务的可视化解释。

图 2 :机器翻译任务的视觉呈现(图片由作者提供)

但是我们如何实现你所说的转变呢?太好了。如果你记得在线性代数中,取矩阵 A(1x2 矩阵)和矩阵 B(2 x2 矩阵)的点积,得到的矩阵 C 将是 1 x2 矩阵。也就是说,我们需要找到一个矩阵, R,,我们可以用它来转换我们的英语单词嵌入, X ,找到想要的法语单词嵌入, Y 。—参见“ 如何乘矩阵 ”来刷新你的记忆。

图 3 :问题陈述的定义(图片由作者提供)

:为此,我们初始化一个随机矩阵, R ,并执行梯度下降来求解 R ,目标是最小化 XR 和 Y 之间的距离。此外,我们不需要所有英语单词 X 到法语单词 Y 的映射,因为一个子集就足够了。如果模型在子集上做得很好,它也可以用来推断不属于原始训练集 x 的单词。

当然,一旦执行了这个步骤,我们需要找到单词向量的最近邻居,因为转换的英语单词不一定与法语单词向量空间中的任何单词向量相同,但重要的是它在法语单词向量空间中。

在这种情况下,我们应该搜索法语单词,以找到与我们通过转换创建的单词相似的单词。一种方法是使用 K-最近邻算法,我们已经在“ 从头开始算法:K-最近邻 ”系列中广泛讨论了该算法。

[## 从头开始的算法:K-最近邻

从头开始详述和构建 K-NN 算法

towardsdatascience.com](/algorithms-from-scratch-k-nearest-neighbors-fe19b431a57)

您可能还记得 K-Nearest Neighbors 算法中的“对于我们来说,要确定 K 个最接近新实例的记录,我们必须对所有实例进行测量”,这对于找到最接近我们要翻译的单词的实例是不必要的,因为将会有一些向量与我们拥有的单词向量完全不同。因此,我们必须找到一种方法来将向量空间划分为区域,因此我们在区域内进行搜索。

如果我们要将数据组织到区域中,以便我们可以有效地在这些区域中搜索相似的向量,我们必须引入哈希表。哈希表对于任何涉及数据的工作都是有用的工具。

哈希表

我们可以通过一些相似性函数将数据分组到桶中——参见图 4

图 4 :将数据分组到桶中(图片由作者提供)

除了映射到每个桶的形状是单词向量而不是形状之外,将我们的文本数据分组到桶中以便我们在各个区域中执行 K-最近邻居搜索的任务类似于上面的示例。

因此,将我们的单词向量映射到散列值需要我们找到一个称为“散列函数的映射,它将我们的向量映射到散列值,即散列函数(向量)→散列值。

然而,需要注意的是,我们的目标是将相似的词向量放入相同的桶中。为此,我们需要做一些叫做“位置敏感散列”的事情。位置敏感哈希是一种哈希方法,它非常关心基于项目在向量空间中的位置来分配项目。

位置敏感散列法

当在高维空间中实现 K-最近邻时,位置敏感散列是一种非常重要的技术,这主要是因为它降低了寻找 K-最近邻的计算成本。根据维基百科的说法,它可能被定义为一种算法技术,以高概率将相似的输入项散列到相同的“桶”中。

如果我们想知道一些向量是否靠得很近,我们首先用平面划分向量空间,这有助于我们根据向量的位置将它们分成子集。

图 5: 2d 向量空间示例(图片由作者提供)

紫色平面将空间分割成位于其上方或下方的向量。我们突出显示的浅蓝色向量似乎都在紫色平面上方,而灰色向量在(我不知道确切的颜色)深蓝色平面上方。因此,这些平面可以帮助我们根据它们的位置将向量分成散列,方法是在平面的法向量和代表我们数据的向量之间进行点积,这将为我们提供相对于平面的相对位置。

然而,如果我们应该把我们的数据分成可管理的区域,我们可能要使用不止一个平面。对于每个平面,我们可以确定一个向量是在该平面的+侧还是-侧。因此,我们最终会得到多个信号,每个平面一个信号,利用这些信息,我们必须找到一种方法,将所有这些信号组合成一个哈希值,该哈希值将定义向量空间内的一个特定区域。

: 什卡·古普塔写了一篇关于地区敏感哈希的精彩文章,我推荐你去看看更全面的解释。

近似最近邻居

我们无法确切知道哪组平面是划分我们的随机平面的最佳方式,因此为了在我们的不确定性中变得更舒适,一种解决方案可能是创建多组随机平面,以便我们可以将向量空间划分成多个独立的哈希表组。

我们现在可以利用不同组的随机平面来帮助我们找到一组好的友好邻域向量或 k-最近邻。

图 6 :随机平面集合;紫色向量表示英语单词向量到法语单词向量的转换。突出显示的颜色表示根据随机平面已经被分配到相同散列桶的向量。(图片由作者提供)

通过将多组随机平面用于位置敏感散列,我们有了一种更健壮的方式来搜索向量空间,以寻找作为最近邻居的潜在候选的一组向量。我们称之为“近似最近邻”,因为我们没有搜索整个向量空间——为了效率,我们牺牲了精度。

搜索文档

有了更快版本的 K-Nearest Neighbors,我们还可以执行各种其他任务,例如文档搜索,它包括在大量文档中搜索与查询相关的文本。

为了将一个文档表示为一个向量,我们可以从获取单词向量的总和开始——参见图 7

图 7 :将文档表示为向量。(图片由作者提供)

要执行这项任务,我们只需为文档和查询创建向量,并应用 KNNeighbors 来查找与我们的查询最相似的文档。

包裹

谢谢你读到这篇文章的结尾。这就结束了自然语言处理专业的课程 1。到目前为止写的所有笔记,请访问自然语言处理笔记 —寻找我在课程 2 上的笔记。

如果你有兴趣开始自己的博客,或者你想在 2021 年认真对待博客,请订阅我的 Youtube 频道,每周更新关于如何开始你的旅程。如果你已经开了一个博客,里面可能还有对你有用的东西,所以我会订阅,这样你就不会错过了!—首个视频将于本周日发布!

[## 库尔蒂斯·派克斯

欣赏您喜爱的视频和音乐,上传原创内容,并在上与朋友、家人和全世界分享这些内容…

www.youtube.com](https://www.youtube.com/channel/UCu6zdBQhvEY5_j-ifHWljYw?view_as=subscriber)

一如既往,让我们在 LinkedIn 上继续对话…

[## Kurtis Pykes -数据科学家-自由职业者,自由职业者| LinkedIn

在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有 3 个工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)

机器翻译导论

原文:https://towardsdatascience.com/introduction-to-machine-translation-9cb0e93e7cb?source=collection_archive---------38-----------------------

从传统的机器学习到先进的深度学习方法

来源:https://pixabay.com/

来源: 我是跟随斯坦福大学关于深度学习的自然语言处理的课程后写的这篇文章。本课程在 YouTube 上有 的介绍,本文的大部分内容都来自于此。

需求: 在深入研究本文之前,我会建议你确保自己了解自然语言处理和深度学习的基础知识。如果你从未听说过解析或者单词嵌入,你可以阅读 这篇教程 。如果你从未听说过神经网络(尤其是递归神经网络)或反向传播,我建议你阅读这篇文章作为介绍。

介绍

我们亲爱的星球被 7000 多种语言所丰富,感谢科技,我们生活在一个越来越全球化的世界。翻译已经成为沟通的支柱,让人们可以建立各种联系。要真正了解翻译的重要性,这里有一个关键数字:2015 年,谷歌翻译每天处理 1000 亿个单词。我们用机器翻译解决的范例如下:

给我们一个源语言(比如法语)和一个目标语言(姑且说英语)。我们的目标是将一个句子从源语言翻译成目标语言。

从数学上来说,我们希望找到给定法语句子 x 的最佳英语句子 y。这可以用概率来表示:

传统机器学习翻译系统

统计机器翻译(SMT) 于 90 年代推出,试图从数据中学习概率模型。

我们可以使用贝叶斯法则分解我们试图求解的方程(见上文):

使用贝叶斯规则的概率公式

  • P(x|y)被称为翻译模型,在平行语料库上训练。这个模型知道法语单词或英语单词如何相互翻译。
  • P(y)被称为语言模型,在纯英语语料库上训练。语言模型是一个可以预测下一个单词的系统。

法语和英语句子对齐的图示

为了训练翻译模型,我们正在寻找法语和英语表达之间的对齐。这种排列(见图)远非微不足道。一个法语单词可以与一系列英语单词对齐(一对多对齐),一系列法语单词也可以与一个英语单词对齐(多对一对齐)。经过许多步骤的构建,排列看起来像这样。

等式的另一部分是通过语言模型获得的。对于每一个单词,你在目标语言中都有潜在的候选词。我们使用语言模型来选择听起来不错的候选词。

总结这些 SMT 模型,它们是好的系统,但极其复杂。它们一直使用到 2014 年,需要大量人力来维护。例如,你需要为你想翻译的所有语言建立一个对比表。

2014 年,机器翻译界出现了深度学习。

深度学习拯救世界

神经机器翻译(NMT) 是机器翻译领域的一次革命,主要是因为它使用了单一的神经网络架构。这种架构被称为序列到序列,涉及两个 rnn:一个编码器和一个解码器

编码器 RNN 将产生源句子的编码,而解码器 RNN 是一个语言模型,根据编码产生目标句子。

一个基于 RNN 的翻译模型的图示

与 SMT 相反,这里我们直接计算 P(y|x):

每一项都是给定到目前为止翻译的单词和源句子 x 的下一个目标单词的概率。与 SMT 相比,这是一个很大的优势,因为这个过程很简单。

消失/爆炸梯度问题

在训练阶段,我们通过反向传播得到梯度。但在实践中,梯度下降并不是很有效,除非我们小心谨慎。问题是,我们需要学习长时间窗口内的依赖性,梯度可能会爆炸或消失。这个著名的问题发生在任何使用基于梯度的优化技术的网络中。更多详情,请参见本课程。

为了解决这个问题,我们可以使用简单的技巧:

  • 渐变裁剪:基本上,我们通过重新缩放来防止渐变爆炸。
  • 输入反转:训练远距离依存关系非常困难,比如输入句子的第一个单词和输出句子的第一个单词之间。我们可以通过颠倒输入句子中单词的顺序来解决这个问题。这个原理用于双向 rnn。
  • 身份初始化:如果你的网络计算身份函数,梯度计算将非常稳定,因为雅可比矩阵就是身份矩阵。这表明,我们可以通过鼓励计算接近恒等函数来保持稳定。有了这个窍门,激活功能都恢复了。

或者,我们也可以改变编码器/解码器 rnn 的架构:

  • 长-短时记忆(LSTM):
    它使用 4 个门,旨在使长时间记忆信息变得容易,直到需要为止。阅读这篇文章了解更多关于 LSTM 的信息。
  • 门控递归单元(GRU):
    GRU 是 LSTM 的一个更简单的变体,用于解决消失梯度问题。它使用两个门。详见本文。与 LSTM 相比,GRU 的参数更少,因此计算效率更高,需要的数据更少。

GRU 插图— 图像来源

BLEU:评估翻译的分数

一般来说,在机器学习中,评估算法的性能非常简单。然而,当涉及到翻译时,问题要复杂得多。BLEU(双语评估替读)是一种用于评估机器翻译文本质量的算法。它将机器翻译与一个或几个人工翻译进行比较,并计算 0 到 1 之间的相似性得分。完全匹配的得分为 1,而完全不匹配的得分为 0。BLEU 评分是当今最常用的基准指标。尽管这一指标并不完美,但它具有易于解释和计算的优点。

布雷特·乔丹在 Unsplash 上的照片

但是 BLEU score 面临一个主要问题:它是不可微的,因此基于梯度的优化方法不能直接应用。在训练阶段的优化损失和测试阶段的评估标准之间存在不匹配。

神经机器翻译在统计翻译上的五大胜利:

  1. 单个神经网络的端到端训练。所有参数都被优化以最小化网络输出的损失函数。
  2. 分布式表示允许更好地利用单词和短语的相似性。
  3. 更好地利用上下文。
  4. 更流畅的文本生成。
  5. 需要更少的人工工程。以前,单词和短语在很大程度上是独立翻译的,现在我们将整个输入句子视为一个翻译单元

还有两个缺点

  1. 隐藏表示的固定尺寸。编码器的最后一个向量必须捕捉句子的全部含义。这在大句子的情况下可能是个问题。此外,输入的一个单词可能需要更多的关注,因为它对翻译有影响。我们将看到注意力机制如何解决这个问题。
  2. 没有零炮翻译。只有系统在训练阶段发现两种语言之间的翻译,才能进行翻译。这个问题被谷歌的多语言神经机器翻译系统解决了。

注意机制:

我们让模型学习如何为每个输出时间步长生成一个上下文向量,而不是将输入序列编码成一个固定的上下文向量(即。每个单词)。一个评分功能会对编码器 RNN 产生的每个位置进行评分,并指出应该注意的地方。这允许解码器网络“聚焦”在编码器输出的特定部分

注意力显著提高了 NMT 的表现。另一个优点是,由于注意力的分布,它提供了可解释性。

这种架构用于谷歌神经机器翻译系统的核心,或 GNMT:

注意机制图解—来源:https://ai . Google blog . com/2016/09/a-neural-network-for-machine . html

谷歌的多语言神经机器翻译系统

为了解决零镜头翻译问题,GMNMT 引入了一个简单的数据调整,即在原始的神经机器翻译架构中添加一个人工令牌来指示所需的目标语言。

假设我们用 Japanese⇄English 和 Korean⇄English 的例子训练了一个多语言系统,如动画中的蓝色实线所示。我们能在系统从未见过的语言对之间进行翻译吗?这方面的一个例子是朝鲜语和日语之间的翻译,其中 Korean⇄Japanese 的例子不向系统显示。令人印象深刻的是,答案是肯定的。它可以生成合理的 Korean⇄Japanese 译文,尽管从未有人教过它这么做。我们称之为“零镜头”翻译,如动画中黄色虚线所示。

插图零投学习—来源:https://ai . Google blog . com/2016/11/Zero-shot-translation-with-Google . html

结论

机器翻译介绍到此结束,希望你喜欢这篇文章!机器翻译是一个很有意思的领域,绝不是解决了。在我们能够翻译的语言的多样性以及翻译的质量方面仍有改进的余地。

神经网络背后的数学简介

原文:https://towardsdatascience.com/introduction-to-math-behind-neural-networks-e8b60dbbdeba?source=collection_archive---------0-----------------------

由作者使用创建

让我们深入研究神经网络和深度学习背后的数学

今天,通过开源机器学习软件库,如 TensorFlowKerasPyTorch ,我们可以只用几行代码创建一个神经网络,即使结构非常复杂。话虽如此,神经网络背后的数学对我们一些人来说仍然是一个谜,拥有神经网络和深度学习背后的数学知识可以帮助我们理解神经网络内部发生的事情。它也有助于架构选择、深度学习模型的微调、超参数调整和优化。

介绍

很长一段时间,我忽略了理解神经网络和深度学习背后的数学,因为我没有很好的代数或微积分知识。几天前,我决定从头开始,推导神经网络和深度学习背后的方法论和数学,以了解它们如何以及为什么工作。我也决定写这篇文章,对我这样觉得很难理解这些概念的人会有用。

感知器

感知机——由 Frank Rosenblatt 于 1958 年发明,是最简单的神经网络,由 n 个输入、仅一个神经元和一个输出组成,其中 n 是我们数据集的特征数量。通过神经网络传递数据的过程被称为前向传播,在感知器中执行的前向传播在以下三个步骤中解释。

第一步:对于每一次输入,将输入值 xᵢ 与权重 wᵢ 相乘,并将所有相乘后的值相加。权重——代表神经元之间连接的强度,并决定给定输入对神经元输出的影响程度。如果权重 w₁的值大于权重 w₂,则输入 x₁对输出的影响将大于 w₂.

输入和权重的行向量分别为 x = [x₁,x₂,…,xₙ]和 w = [w₁,w₂,…,wₙ】,它们的 点积 由下式给出

因此,总和等于矢量 xw点积**

第二步:将偏差 b 加到相乘值的总和上,我们称之为 z 。大多数情况下,偏置(也称为失调)是必需的,它将整个激活函数向左或向右移动,以产生所需的输出值。

步骤 3 :将 z 的值传递给一个非线性激活函数。激活函数——用于将非线性引入神经元的输出,没有激活函数,神经网络将只是一个线性函数。此外,它们对神经网络的学习速度有重大影响。感知器具有二元阶跃函数作为其激活函数。然而,我们将使用 s igmoid — 也称为逻辑函数作为我们的激活函数。

其中 σ 表示 s igmoid 激活函数,正向延拓后得到的输出称为预测值t28】ŷ。

学习算法

学习算法由两部分组成——反向传播和优化。

反向传播:反向传播,简称误差反向传播,是指计算损失函数相对于权重的梯度的算法。然而,该术语通常用于指代整个学习算法。在感知器中执行的反向传播在以下两个步骤中解释。

步骤 1 :使用损失函数来估计我们离期望的解决方案有多远。通常,回归问题选择均方误差作为损失函数,分类问题选择交叉熵。让我们来看一个回归问题,它的损失函数是均方误差,它是实际值* (yᵢ)和预测值 ( ŷᵢ)之差的平方。*

为整个训练数据集计算损失函数,并且它们的平均值被称为成本函数* C 。*

为了给我们的感知机找到最佳的权重和偏差,我们需要知道成本函数是如何随着权重和偏差而变化的。这是在梯度* s ( 变化率)的帮助下完成的——一个量如何相对于另一个量变化。在我们的例子中,我们需要找到成本函数相对于权重和偏差的梯度。*

让我们使用偏导数计算成本函数 C 相对于权重 wᵢ 的梯度。由于成本函数与权重 wᵢ没有直接关系,我们使用链式法则

现在我们需要找到以下三个梯度

让我们从 c ost 函数(C) 相对于预测值* ( ŷ)的梯度开始*

设 y = [y₁,y₂,… yₙ]和 ŷ =[ ŷ₁,ŷ₂,… ŷₙ]为实际值和预测值的行向量。因此,上述等式简化为

现在让我们找出预测值相对于 z 的梯度。这会有点长。

z 相对于重量 wᵢ 的倾斜度为

因此我们得到,

偏见呢?—偏置理论上被认为具有恒定值的输入 1 。因此,

优化:优化是从一组可用选项中选择最佳元素,在我们的例子中,是选择感知器的最佳权重和偏差。让我们选择梯度下降作为我们的优化算法,其改变权重偏差,与成本函数相对于相应权重或偏差的梯度的负值成比例。学习率* ( α )是一个超参数,用于控制权重和偏差变化的幅度。*

如下更新权重和偏差,并重复反向传播和梯度下降,直到收敛。

最后的想法

我希望你已经发现这篇文章很有用,并且理解了神经网络和深度学习背后的数学。我在这篇文章中解释了单个神经元的工作。然而,这些基本概念通过一些修改适用于所有类型的神经网络。

R 中矩阵的介绍

原文:https://towardsdatascience.com/introduction-to-matrices-in-r-dc009e3cdbb3?source=collection_archive---------49-----------------------

学习如何创建矩阵,了解如何用它们做基本的计算。

什么是矩阵?

矩阵是排列成固定数量的行和列的相同数据类型(数字、字符或逻辑)元素的集合。二维矩阵仅适用于行和列。

R 中的[**matrix()**](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/matrix)函数创建一个矩阵。考虑下面的例子:

matrix(1:9, byrow=TRUE, nrow = 3)

这将构造一个包含 3 行的矩阵,包含 1 到 9 的数字,按行填充。

matrix()功能中:

# Row-wise  # Column-wise
   1 2 3        1 4 7
   4 5 6        2 5 8
   7 8 9        3 6 9
  • 第三个参数nrow表示所需的行数。nrows=3表示矩阵应该有三行。

还有其他论点,如:

  • ncol表示所需的列数。

从向量创建矩阵

让我们来分析一下《星球大战》系列的票房数字。

下面是三个向量,每个向量定义了前三部《星球大战》电影之一的票房数字。每个向量的第一个元素表示美国票房收入,第二个元素表示非美国票房(来源:维基百科)。

# Box office Star Wars (in millions)
new_hope <- c(460.998, 314.4)
empire_strikes <- c(290.475, 247.900)
return_jedi <- c(309.306, 165.8)

要从这三个向量构建一个矩阵,我们首先需要将这三个向量合并成一个。

box_office <- c(new_hope, empire_strikes, return_jedi)

然后我们使用matrix()函数构建一个矩阵。第一个参数是向量box_office,包含所有票房数字。接下来,我们必须指定nrow=3byrow=TRUE来构建按行填充 3 行的矩阵(第一列代表美国收入,第二列代表非美国收入)。

star_wars_matrix <- matrix(box_office, byrow=TRUE, nrow=3)

总的来说,代码应该是这样的。

结果矩阵将是一个 3 行乘 2 列的“表格”。

命名矩阵

向矩阵的行和列添加名称通常有助于记住矩阵中存储的内容。它不仅有助于读取数据,还有助于从矩阵中选择某些元素。我们可以通过使用函数colnames()rownames()来实现这一点。

rownames(my_matrix) <- row_names_vector
colnames(my_matrix) <- col_names_vector

要按区域和标题命名列,需要表示这些名称的向量。

# Vectors region and titles, used for naming
region <- c("US", "non-US")
titles <- c("A New Hope", "The Empire Strikes Back", "Return of the Jedi")

要用region向量命名star_wars_matrix的列,必须使用colnames()

# Name the columns with region
colnames(star_wars_matrix) <- region

要用titles向量命名star_wars_matrix的行,必须使用rownames()

# Name the rows with titles
rownames(star_wars_matrix) <- titles

您的代码现在应该像这样:

# Box office Star Wars (in millions)
new_hope <- c(460.998, 314.4)
empire_strikes <- c(290.475, 247.900)
return_jedi <- c(309.306, 165.8)# Construct matrix
star_wars_matrix <- matrix(c(new_home, empire_strikes, return_jedi), nrow = 3, byrow = TRUE)# Vectors region and titles, used for naming
region <- c("US", "non-US")
titles <- c("A New Hope", "The Empire Strikes Back", "Return of the Jedi")# Name the columns with region
colnames(star_wars_matrix) <- region# Name the rows with titles
rownames(star_wars_matrix) <- titles# Print out star_wars_matrix
star_wars_matrix

使用 colnames()和 rownames()函数后,矩阵现在被标记。

备选方案:使用 dimnames 参数

矩阵的dimnames属性可用于命名矩阵的行和列。dimnames属性接受长度为 2 的list,分别给出行名和列名。也就是说,

dimnames = list(row_vector,column_vector)

所以,在构造矩阵时,我们可以直接标记它。

# Construct star_wars_matrix
box_office <- c(460.998, 314.4, 290.475, 247.900, 309.306, 165.8)
star_wars_matrix <- matrix(box_office, nrow = 3, byrow = TRUE, dimnames = list(c("A New Hope", "The Empire Strikes Back", "Return of the Jedi"),c("US, "non-US")))

计算行总计

一部电影的一个重要统计数据是它的全球票房数字。要计算三部《星球大战》电影的总票房收入,你需要确定美国收入和非美国收入的总和。

函数rowSums()计算矩阵每行的总数,并创建一个新的向量:

rowSums(my_matrix)

让你试试

计算三部电影的全球票房数字。

解决办法

# Construct star_wars_matrix
box_office <- c(460.998, 314.4, 290.475, 247.900, 309.306, 165.8)
star_wars_matrix <- matrix(box_office, nrow = 3, byrow = TRUE, dimnames = list(c("A New Hope", "The Empire Strikes Back", "Return of the Jedi"),c("US, "non-US")))# Calculate worldwide box office figures
worldwide_vector <- rowSums(star_wars_matrix)

我们得到每部电影的总票房收入,而不考虑地区。

向矩阵中添加列

您可以使用[cbind()](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/cbind)功能向矩阵添加一列或多列,该功能按列将矩阵和/或向量合并在一起。例如:

big_matrix <- cbind(matrix1, matrix2, vector1, ...)

让你试试

在上一个练习中,您计算了包含三部电影的全球票房收入的向量。然而,这个向量还不是star_wars_matrix的一部分。将此向量作为新列添加到矩阵中,并将结果赋给新矩阵。

解决办法

# Construct star_wars_matrix
box_office <- c(460.998, 314.4, 290.475, 247.900, 309.306, 165.8)
star_wars_matrix <- matrix(box_office, nrow = 3, byrow = TRUE, dimnames = list(c("A New Hope", "The Empire Strikes Back", "Return of the Jedi"),c("US, "non-US")))# Calculate worldwide box office figures
worldwide_vector <- rowSums(star_wars_matrix)# Bind the new variable worldwide_vector as a column to star_wars_matrix
all_wars_matrix <- cbind(star_wars_matrix, worldwide_vector)

all_wars_matrix 现在包括美国收入、非美国收入以及这两项的总和。

添加一行

要添加列,可以使用[**cbind()**](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/cbind)。要添加一行,可以使用[**rbind()**](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/cbind)rbind()函数接受一系列向量或矩阵参数,并按行组合它们。举个例子,

big_matrix <- rbind(matrix1, matrix2, vector1, ...)

让你试试

就像你用原三部曲的数据创建star_wars_matrix一样,用前传三部曲的类似数据创建第二个矩阵。

然后使用rbind()来合并两个矩阵,首先是原三部曲的数据,然后是前传的数据。

解决办法

# Construct star_wars_matrix
box_office <- c(461.0, 314.4, 290.5, 247.9, 309.3, 165.8)
star_wars_matrix <- matrix(box_office, nrow = 3, byrow = TRUE, dimnames = list(c("A New Hope", "The Empire Strikes Back", "Return of the Jedi"), c("US", "non-US")))# Construct star_wars_matrix2
box_office2 <- c(474.5, 552.5, 310.7, 338.7, 380.3, 468.5)
star_wars_matrix2 <- matrix(box_office2, nrow = 3, byrow = TRUE, dimnames = list(c("The Phantom Menace", "Attack of the Clones", "Revenge of the Sith"), c("US", "non-US")))# Combine both Star Wars trilogies in one matrix
all_wars_matrix <- rbind(star_wars_matrix, star_wars_matrix2)

新的矩阵应该按地区列出原版和前传的收入。

计算列总计

类似于我们如何使用rowSums()来计算每行的总和,我们也可以使用[**colSums()**](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/colSums)来计算矩阵每列的总和。

rowSums(my_matrix)

让你试试

使用之前练习中构建的all_wars_matrix,计算整个传奇在美国和非美国地区的总票房收入。

解决办法

# Total revenue for US and non-US
total_revenue_vector <- colSums(all_wars_matrix)

矩阵元素的选择

与向量类似,方括号[]可用于从矩阵中选择一个或多个元素。因为矩阵是二维的,所以需要逗号来分隔行和列。例如:

  • my_matrix[1,2]选择第一行第二列的元素(第 1 行,第 2 列)
  • my_matrix[1:3, 2:4]返回包含第 1 行到第 3 行、第 2 列到第 4 列的数据的矩阵。

要选择一行中的所有元素,在列后不需要数字。要选择一列的所有元素,在该列前不需要数字。

  • my_matrix[,1]选择第一列的所有元素。
  • my_matrix[1,]选择第一行的所有元素。

让你试试

计算所有电影的平均非美国收入(提示:选择all_wars_matrix的整个第二列,并使用mean()函数)。

解决办法

# Select the non-US revenue for all movies
non_us_all <- all_wars_matrix# Average non-US revenue
mean(non_us_all)

我们的平均收入为 3.4797 亿美元。

给你尝试(2)

计算传奇故事前两部电影的平均值。

解决办法

# Select the non-US revenue for the first two movies
non_us_some <- all_wars_matrix[1:2,2]# Average non-US revenue for the first two movies
mean(non_us_some)

前两部电影的平均非美国收入为 2.8115 亿美元。

矩阵运算

标准运算符,如+-/*等。它处理向量,也以元素的方式处理矩阵。

例如,2 * my_matrixmy_matrix的每个元素乘以 2。

也可以将一个矩阵乘以另一个矩阵。例如,my_matrix1 * my_matrix2创建一个矩阵,其中每个元素都是my_matrix1my_matrix2中相应元素的乘积。

让你试试

假设一张电影票的价格是 5 美元。确定每个地理区域有多少观众去看了每部电影。(提示:简单地用票房数字除以票价就会得到游客数量)。

解决办法

# Estimate the visitors
visitors <- all_wars_matrix / 5

给你尝试(2)

假设票价随着时间的推移而上涨。给出一个票价矩阵,确定所有电影的美国和非美国游客的估计数量。

# Construct ticket_prices_matrix
ticket_prices <- c(5.0, 5.0, 6.0, 6.0, 7.0, 7.0, 4.0, 4.0, 4.5, 4.5, 4.9, 4.9)
ticket_prices_matrix <- matrix(ticket_prices, nrow = 6, byrow = TRUE, dimnames = list(c("A New Hope", "The Empire Strikes Back", "Return of the Jedi","The Phantom Menace", "Attack of the Clones", "Revenge of the Sith"),c("US", "non-US")))

票价矩阵。

解决办法

# Estimated number of visitors
visitors <- all_wars_matrix / ticket_prices_matrix

给你试试(3)

计算美国访问者的平均数量(提示:您需要完成第二个才能尝试)

解决办法

# US visitors (Select the entire first column)
us_visitors <- visitors[,1]# Average number of US visitors
mean(us_visitors)

美国访问者的平均数量可以使用均值函数来确定。

笔记

所有图片,除非特别注明,均归作者所有。横幅图像是使用 Canva 创建的。

MCMC 简介

原文:https://towardsdatascience.com/introduction-to-mcmc-1c8e3ea88cc9?source=collection_archive---------22-----------------------

什么是蒙特卡洛近似法,Metropolis 算法是如何工作的?

Metropolis 算法的图示。作者图片

概率建模如今风靡一时,但当我第一次了解它时,总有一件事困扰着我。许多贝叶斯建模方法需要计算积分,我看到的任何成功的例子似乎都使用高斯或伯努利分布,原因很简单,如果你试图使用比这更复杂的东西,这将成为一个分析噩梦(甚至是棘手的)。将贝叶斯建模限制在“表现良好的”分布的小子集会极大地阻碍您对问题进行良好建模的能力,因此我们想出克服这种限制的方法是很重要的。

蒙特卡洛近似法

如果我不想解析地计算一些讨厌的积分,我该怎么做?输入蒙特卡罗近似值。

我们知道,我们可以通过使用目标分布的样本并计算它们的样本均值来计算期望值。为什么这很重要?那么,除了积分,还有什么是期望呢…

连续随机变量的期望。同样的过程也适用于离散,通过改变求和的积分。作者图片

由于中心极限定理,这种估计积分的方法有一些很好的保证。首先,这是期望的无偏估计,其次,我们可以计算估计的方差。

使用蒙特卡罗样本计算积分当然很好,但是我们如何从目标分布中抽取样本呢?绘制高斯或均匀样本很容易,但是任何更难和 np.random 的东西都会让你不及格。

抽取样本的最简单方法是使用逆 CDF 方法,但这依赖于对逆 CDF 函数的访问,该函数通常没有很好的分析形式,只对一维随机变量有意义。

Metropolis 算法是许多马尔可夫链蒙特卡罗(MCMC)采样方法的构建模块之一。当您只能访问目标发行版的 pdf 时,它允许我们提取样本。

MCMC 方法附带了一个警告,即我们不再获取独立的样本,因此我们不能保证我们的估计方差随着我们获取的样本数量的增加而减少。如果独立抽取样本,中心极限定理告诉我们,我们估计的方差将与样本数(N)成反比地减少。对于 MCMC,我们可以通过将样本数从 N 调整到 N_eff 来忽略这一点。N_eff(几乎)总是小于 N,并且与链中样本的相关程度有关。

大都市抽样

Metropolis 算法的步骤如下:

1\. Sample a starting point uniformly from the domain of the target distribution or from the prior distribution.2\. Calculate the pdf at that point.3\. Make a proposal for the new sample by taking a step from the current position in accordance with some state transition function.4\. Calculate the new pdf value.5\. Calculate the value of new pdf / old pdf.6\. If the ratio is greater than 1, accept the step.7\. If the ratio is less than 1:
    1\. Sample a uniform random variable.
    2\. If the ratio greater than the random sample, accept the step.8\. Else reject the proposal, add the current position as a sample and take a new step.

请注意,5–8 中描述的过程相当于根据概率为 min(1,p(新)/p(旧))的伯努利概率接受样本,请记住这一点,以便以后使用…

为什么大都会抽样有效?

对于任何 MCMC 方法,我们希望确保一个称为详细平衡或可逆性的属性。

明细余额。作者图片

如果π满足这个条件,那么π就是马尔可夫链 (1) 的平稳分布。我们可以通过对等式两边求和来证明这一点。如果我们能保证详细的平衡,那么我们也知道我们是从马尔可夫链的平稳分布中取样,我们将把它指定为我们的目标分布。

这种对详细平衡的直觉是,由于从状态i到状态j的概率‘质量’转移与从状态j到状态i的转移相同,所以在链的每次转移之后,我们保持在稳定分布。

那么现在让我们展示 Metropolis 算法如何满足这个条件…

为了找到 p(i,j)使得它满足详细平衡,我们首先提出任意的“跳转”概率 q(i,j),然后通过只接受概率为α(i,j)的“跳转”来获得 p(i,j)。当一个“跳转”被拒绝时,状态保持 j=i。这种“接受”思想不是 Metropolis 算法所独有的,并且存在于 MCMC 的大多数变体中。

跳跃概率推导。作者图片

这取决于α是有效的概率分布。所以α的有效形式是:

大都会-黑斯廷斯台阶。作者图片

如果跳动概率是对称的,那么这可以简化为:

大都会台阶。作者图片

否则,它可以保留其完整形式,称为 Metropolis-Hasting MCMC。

现在我们可以保证详细的平衡,我们可以让马尔可夫链机器接管。如果马尔可夫链是遍历的(所有状态都是不可约的),那么在某个点上,该链将到达平稳分布,并且我们能够从目标分布中提取样本。

您可能还注意到,由于α是π(j)/π(i)的函数。这意味着目标分布不需要标准化。这在使用 Metropolis 进行贝叶斯后验估计时特别有用,因为证据项很难计算。

实施说明

Metropolis 算法的常见版本称为“随机行走 Metropolis ”,其中建议的状态是当前状态加上具有零均值和协方差矩阵σ I 的多元高斯。σ应选择为足够大,以便剔除足够多的样本。这是为了确保目标分布的良好探索。

第二个需要注意的是老化的概念。在马尔可夫链达到稳定分布之前采集的样本应该被移除,因为在马尔可夫链收敛之前,它们不代表目标分布。确定应该移除多少样本有些困难,但一般来说,会移除 10–20%的样本(或 10–100 个有效样本)。

让我们在 Numpy 建造它

为了简单起见,这里我们实现随机漫步大都会。

def metropolis(pi, dims, n_samples, burn_in=0.1, var=1):
    theta_ = np.random.randn(dims)*var samples = []
    while len(samples) < n_samples:
        theta = theta_ + np.random.randn(dims)*varratio = pi(theta)/pi(theta_)
        if np.random.rand(1) < ratio:
            sample = theta
            theta_ = theta
            samples.append(sample)
        else:
            sample = theta_
            samples.append(sample) samples = np.array(samples)
    return samples[int(samples*burn_in):,:]

我们可以看到这在两个高斯分布的和上的表现(注意这是一个非标准化的分布)。

from scipy.stats import multivariate_normaldef make_pdf(mean1, mean2, cov1, cov2): pdf1 = multivariate_normal(mean1, cov1)
    pdf2 = multivariate_normal(mean2, cov2) def pdf(x):
        return pdf1.pdf(x) * pdf2.pdf(x) return pdfpdf = make_pdf(
    [3, 3],
    [-1, -1],
    np.array([[1,0.1],[0.1,1]], dtype=float),
    np.array([[1,0.1],[0.1,1]], dtype=float),
)samples = metropolis(pdf, 2, 1_000, 0.1)

两个多元高斯和的大都会样本。作者图片

上面的 gif 显示了算法如何遍历分布,偶尔在分布的两种不同模式之间跳跃。注意,这也突出了 Metropolis 算法的一个弱点,它处理多模型分布相对较差。这是因为,为了探索一种新的模式,步长必须足够大,以便从一种模式转换到另一种模式。这要么需要一个大的步长,要么需要模式接近的分布。诸如哈密尔顿 MCMC 的修改可以对此有所帮助,但是一般来说,这是大多数 MCMC 方法的问题。

附加“阅读”

消息传递神经网络简介

原文:https://towardsdatascience.com/introduction-to-message-passing-neural-networks-e670dc103a87?source=collection_archive---------5-----------------------

在图表上发送信息的神经网络

照片由 Ryul DavidsonUnsplash 上拍摄

相关文章

W 欢迎来到图形神经网络的世界,在这里我们在图形上构建深度学习模型。你可能认为这很简单。毕竟,难道我们不能重用使用正常数据的模型吗?

不完全是。在图中,所有的数据点(节点)都是相互连接的。这意味着数据不再是独立的,这使得大多数标准的机器学习模型无用,因为它们的推导强烈地基于这一假设。为了克服这个问题,可以从图中提取数字数据,或者使用直接处理这类数据的模型。

创建直接在图上工作的模型是更可取的,因为我们获得了关于它们的结构和属性的更多信息。在本文中,我们将研究专门为这种类型的数据设计的架构之一,消息传递神经网络(MPNNs)。

多面模特

安德鲁·西曼在 Unsplash 上拍摄的照片

在这个模型被标准化为一个单一的 MPNN 框架之前,几个独立的研究人员已经发表了不同的版本。这种类型的结构在化学中特别受欢迎,有助于预测分子的性质。

Duvenaud 等人(2015)在[1]中发表了关于这一主题的第一批工作之一。他使用消息传递架构从图形分子中提取有价值的信息,然后将其转换为单个特征向量。当时,他的工作是开创性的,因为他使架构可区分。事实上,这是第一个可以在图形上操作的卷积神经网络架构。

Duvenaud 等人(2015)在[1]中创建的消息传递架构。他将该模型定义为一堆可区分的层,其中每一层都是另一轮的消息传递。修改自[1]

李等人(2016)在[2]中对此架构进行了另一次尝试。在这里,他们关注图的顺序输出,例如在图[2]中寻找最优路径。为了实现这一点,他们将 GRU(门控循环单元)嵌入到他们的算法中。

尽管这些算法看起来非常不同,但它们有相同的基本概念,即在图中的节点之间传递消息。我们将很快看到如何将这些模型组合成一个单一的框架。

将模型统一到 MPNN 框架中

节点 V1 的消息传递架构的一个非常简单的例子。在这种情况下,消息是邻居隐藏状态的总和。更新函数是消息 mh1 之间的平均值。作者创建的 Gif

毕竟,MPNN 背后的想法在概念上很简单。

图中的每个节点都有一个隐藏状态(即特征向量)。对于每个节点 V t,我们将所有相邻节点的隐藏状态和可能的边与节点 V t 本身聚合在一起。然后,我们使用获得的消息和该节点的先前隐藏状态来更新节点 V t 的隐藏状态。

有 3 个主要等式定义了图上的 MPNN 框架[3]。从相邻节点获得的消息由以下等式给出:

从相邻节点获得消息。修改自[3]。

它是 Mt 从邻居获得的所有消息的总和。Mt 是一个任意函数,它依赖于相邻节点的隐藏状态和边缘。我们可以通过保留一些输入参数来简化这个函数。在上面的例子中,我们只对不同的隐藏状态 h w. 求和

然后,我们使用一个简单的等式更新节点 V t 的隐藏状态:

使用先前的隐藏状态和新消息更新节点的状态。修改自[3]。

简单地说,节点 V t 的隐藏状态是通过用新获得的消息 m v 更新旧的隐藏状态而获得的。在上述示例的情况下,更新函数 Ut 是先前隐藏状态和消息之间的平均值。

我们重复这个消息传递算法指定的次数。之后,我们到达最后的读出阶段。

将获得的隐藏状态映射到描述整个图的单个特征向量中。修改自[3]。

在这一步中,我们提取所有新更新的隐藏状态,并创建描述整个图的最终特征向量。然后,该特征向量可以用作标准机器学习模型的输入。

就是这样!这些是 MPNN 的基础。这个框架非常健壮,因为我们可以根据我们想要实现的目标来定义不同的消息和更新功能。我建议查看[3]更多信息,MPNN 模型的不同变体。

在哪里可以找到模型的实现

照片由尼克·费因斯Unsplash 上拍摄

MPNN 是作为少数深度学习库的一部分实现的。以下是我能找到的几种不同实现的列表:

总结

MPNN 框架标准化了由几个研究人员独立创建的不同的消息传递模型。该框架的主要思想由消息、更新和读出功能组成,这些功能在图中的不同节点上操作。有不同的 MPNN 模型共享这一功能,但他们定义不同。

感谢阅读,希望对你有用!

关于我

我是阿姆斯特丹大学的人工智能硕士学生。在我的业余时间,你可以发现我摆弄数据或者调试我的深度学习模型(我发誓这很有效!).我也喜欢徒步旅行:)

如果你想了解我的最新文章和其他有用的内容,以下是我的其他社交媒体资料:

参考

[1] 用于学习分子指纹的图上的卷积网络

[2] 门控图序列神经网络

【3】量子化学的神经信息传递

LibROSA 和 Beat Saber 音乐信息检索简介

原文:https://towardsdatascience.com/introduction-to-music-information-retrieval-with-librosa-and-beat-saber-48daedb8653e?source=collection_archive---------17-----------------------

音乐信息检索简介

https://hdwallsource . com/beat-saber-video-game-HD-wallpaper-67665 . html

在这篇文章中,我将举例说明过去几周以来我围绕音乐信息所做的一些工作,这些工作应用于一个特定的游戏 Beat Saber。

击败赛博·凯扎科?

Beat Saber 是 Beat Games 于 2018 年发布的虚拟现实(VR)节奏游戏,顺便说一下,Beat Games 最近被脸书收购。游戏的原理是在你的虚拟现实耳机中,你沉浸在一个 3d 世界中,你必须摧毁积木并避免障碍(与播放的歌曲保持一致)。我邀请你观看他们在 youtube 频道上发布的最后一个视频,以了解游戏背后的逻辑。

对我来说,这是一个展示 VR 有多酷的游戏,对于对 VR 好奇的人来说,这是一个必须尝试的游戏(市场上大多数耳机上都有 gamer)。

这个游戏有一个由 beat games 制作的曲目列表,它们很酷,但在 PC 上有一个社区正在为这个游戏(UGC)开发他们选择的歌曲,这个用户发布内容的主要地方是bsaber.com

该网站似乎被 Beat Games 所容忍,我认为这是游戏流行的原因。

几周前,我决定在这个网站上建立一个歌曲的刮刀(与我的上一篇文章中的工作相同,仍然不是所有者,所以不共享),用于多种用途:

  • 在这个地方,我有一个市场,用户在那里对内容进行建议和评级,所以这是一个围绕推荐引擎建立数据集的完美地方
  • 当我看着网站的大量目录时,我最喜欢的歌曲都不在这里,所以为什么不从现有的歌曲中建立一个 ML 系统,可以根据你想要使用的歌曲建立等级。

关于这最后一点,当我向我的一些朋友介绍我的想法时,他们将我重新引向了 OXAI 和他们的 DeepSaber 项目的工作,是的,就是这个(他们取得的成就令人难以置信)。我计划在未来使用他们已经完成的工作来帮助我构建我的系统(但仍需要在深度学习方面取得进展)。

我对推荐器和生成器的第一个假设是直接分析社区制作的曲目和歌曲,让我们从歌曲开始。

情况描述

Python 中最流行的音乐分析包之一叫做 libROSA ,我邀请你观看 Brian McFee 在这个包中的演讲。

对于本文,我使用的是 0.7 版本的软件包。

为了说明音乐分析的概念,我主要参考了:

  • 在 Meinard Muller 的书音乐处理基础中找到的定义/模式似乎是音乐处理领域的参考

https://www.springer.com/gp/book/9783319219448

  • Youtube 频道 3Blue1Brown 在解释科学概念方面做得非常出色(上帝啊,我希望当我还是一名工程学学生的时候就有这样的资源)

  • 这个优秀的知识库是由 Steve Tjoa 制作的,他是我极力推荐的谷歌工程师;这是混合 libROSA,穆勒的书和其他围绕音乐信息检索的资源。

我决定选两首歌做我的金妮猪:

  • 过去十年中发行的最酷的电子歌曲之一是 M83 的午夜城市
  • 另一首,你会讨厌我的是扔硬币给你的巫师 Sonya Belousova & Giona Ostinelli(我知道这首歌是你脑海中的,但现在它回来了)

这两首歌有不同的风格,我认为它们可能是一个好的开始,因为它们的用户评论是 bsaber.com 上的商品。让我们开始对歌曲进行分析。

音乐信息检索

在 Beat Saber 关卡背景中使用的歌曲可以看到(像所有歌曲一样)有音频信号。我们来看一些概念。

振幅

声音产生一个振动的物体,导致空气分子的位移和振荡,产生局部区域的压缩和稀薄,在穆勒的书中,对这种现象有一个清晰的说明。

音乐处理基础——音乐表现

声音记录相当于捕捉特定时刻的气压振荡(捕捉的周期性称为采样率 sr)。在 LibROSA 中要构建这种图,可以使用以下命令:

import librosa # To load the file, and get the amplitude measured with the sampling rate amplitude, 
sr = librosa.load(path_song)  

# To plot the pressure-time plot 
librosa.display.waveplot(amplitude, sr=sr)

而对于我们两首歌,有他们的压力-时间情节。

正如我们所看到的,两首歌有不同的波形,M83 的歌曲看起来比《巫师》的歌曲有更多的相位(在开始和大约两分钟的时间里有“平静”期)。这个可视化提供了一个很好的例子,但是让我们放大(在歌曲中间)。

正如我们看到的午夜城市看起来更复杂(嘈杂?)就振幅的振荡而言,那首《巫师》(但仍记得那是在歌曲的特定时期)

现在,我们可以用 Beat Saber level 来分析一些更具体的东西,但一个重要的事实是,这些信号相当复杂,也许简化它们会有所帮助,所以让我们给我的朋友 Fourier 打电话。

傅里叶变换

傅立叶变换背后的原理是结合多个信号分解一个复信号。我不想做过程背后的所有理论(学校噩梦),但我邀请你观看 3Blue1Brown 就此主题制作的优秀资源(感谢我在英国的同事提供的链接),这是 20 分钟,但值得。

变换的想法是检测隐藏在歌曲中的简单信号并估计它们的强度。为了利用 libROSA 的这个操作,您可以很容易地使用这段代码。

### # Build the Fourier transform 
X = librosa.stft(amplitude) # Apply a conversion from raw amplitude to decibel 
Xdb = librosa.amplitude_to_db(abs(X)) # Build a spectrogram librosa.display.specshow(Xdb, sr=sr, x_axis="time", y_axis="hz")

这个代码为我们提供了一个名为 spectrogram 的图表,它是时间与频率的关系图,色标与信号功率(由频率定义)相关。这是我们两首歌的声谱图。

正如我们所见,两首歌曲共享一个非常不同的声谱图:

  • 《午夜城市》看起来是一首由比《巫师》更高频率的信号组成的歌
  • 巫师看起来比午夜城市更吵闹;我不知道如何解释我所看到的

这种轮廓在《巫师》中出现过,但不像这张。但是,信号甚至分解复杂,难以分析(因为他的复杂性)。为什么不把它分解在伴奏和人声之间。

人声和伴奏分离

为了做到这一点,我可以使用 libROSA 包中的预制脚本,但是当我开始从事这个项目时,我的研究将我引向了 Deezer 的一篇科技博客文章,这篇文章开源了一个工具调用 spleeter。

Deezer 于 2019 年底发布了基于 TensorFlow v1 的这款产品。我没有找到 ISMIR 2019(围绕音乐信息检索的大型会议)期间的论文或演示文稿。如果你想在午夜城市上听到分离的结果(这很好)并抛硬币,你需要去这个链接下载 spleeter 文件夹中的分离文件。

振幅观点的影响是什么?

从一般的观点来看,信号不太复杂,但噪声仍然很大。(zoom 仍在说明这一点)。

尽管如此,我认为这种分离在基于歌曲的振幅构建音轨的上下文中是有用的。

让我们现在开始交叉数据从节拍军刀轨道和歌曲。

俯冲在拍子军刀的侧面

从 bsaber.com 下载的文件中,我有我之前分析过的歌曲和关卡(包括音符障碍等等)。).对于这篇文章,我只是要分析正常的轨道和这个轨道上每秒发布的笔记数量(不是那种笔记)。

正如我们所看到的,歌曲中每秒显示的音符上有多个相位,但让我们在此图中添加歌曲的振幅。顺便说一下,为了比较每秒的振幅,我需要每秒进行一次聚合(振幅绝对值的平均值)。

演奏的音符数量似乎高度依赖于信号的振幅。在《午夜之城》中,我们可以用 0 音符来区分平静的时期和振幅更大的更激烈的时期。对于巫师来说,分析不太清楚,但我们仍然可以在笔记幽灵中看到一些相位。现在让我们把注意力放在声乐上。

从这个分析来看,午夜城市的音轨看起来并没有受到歌词的影响,对于巫师来说,一分钟左右的人声有明显的影响。最后,我将在播放音符的情况下穿过声谱图(我仍然需要每秒进行一次汇总,在这种情况下我决定取最大值)。

从《午夜城市》的声谱图来看,似乎出现了一个有趣的模式,频率较高的歌曲的区域似乎比频率较低的歌曲更少 0 音符时刻。

对于巫师来说,声谱图可能不太有表现力。

总的来说,以我的观点来看,声谱图的分析可以给出令人兴奋的见解,这可能有助于建立一个基于歌曲的音轨模型。

结论

这篇文章是对音乐分析的简要介绍;这是一个值得挖掘的领域,试图围绕这个领域建立像推荐引擎或轨迹生成器这样的系统将会很有趣。

https://media.giphy.com/media/xTiN0CNHgoRf1Ha7CM/giphy.gif

关于这些主题的后续步骤:

  • 构建一个更强大的刮刀,围绕用户评级收集更清晰的数据
  • 对所有歌曲进行全局分析(基于收集的所有新数据)
  • 深入分析 OXAI 围绕轨道建设所做的工作(他们的系统最初是基于 Dance Dance Revolution
  • 深入音乐信息检索会议,了解关于这个主题的更多信息
  • 建立一些推荐引擎…

朴素贝叶斯分类器简介

原文:https://towardsdatascience.com/introduction-to-naive-bayes-classifier-f5c202c97f92?source=collection_archive---------23-----------------------

Jorge Franganillo 在 Unsplash 上的照片

朴素贝叶斯是一个术语,统称为基于贝叶斯定理分类算法。对于门外汉来说,分类算法是那些用于将新的观察结果分类到预定义类别中的算法。例如,假设您是伦敦一家大银行的数据分析师,您希望根据历史数据来预测客户是否会在银行贷款上欺诈。

你一定想知道这个名字中有“Bayes”,因为这个算法是基于 Bayes 定理的,但是为什么是“Naive”?是因为算法“幼稚”还是“哑巴”?不要!!该算法并不“愚蠢”,但事实上,它有时比一些非常复杂的算法更有效。该算法是“幼稚的”,因为它基于一个一般假设,即一个类中某个特定特征的存在是独立于同一类中某个其他特征的存在。例如,如果一个客户有不良信用记录、申请人收入低等等,他/她可以拖欠银行贷款。这两个特征独立地影响候选人违约的概率,也就是说,一个特征的存在与另一个特征无关。

如果有些术语你听起来不熟悉,不要灰心丧气。这一系列文章的目的是以最简单的方式解释机器学习算法。因此,在本系列结束时,您将能够非常轻松地构建自己的机器学习模型。所以让我们继续这篇关于朴素贝叶斯分类器的文章。

贝叶斯定理!!贝叶斯定理到底是什么?

贝叶斯定理是一个非常流行的数学公式,用于根据可能与事件相关的条件的先验知识来确定事件的条件概率。

等等!条件概率到底是什么?

假设另一个事件已经发生,这是一个结果发生的可能性。例如,从一副 52 张牌中抽取两张不替换的牌。假设抽的第一张牌也是 a,那么第二张牌是 a 的概率是多少?

因此,P(抽第一张王牌)=王牌总数/纸牌总数= 4/52

p(抽第二张 a)= 3/51(这是因为在第一次抽牌后,我们的牌组中只剩下 3 张 a,牌的总数也减少到 51 张)。这就是条件概率的含义。第二个事件取决于第一个事件的发生。

回到贝叶斯定理。它在数学上由以下公式给出:

图 1:贝叶斯定理[图片由作者提供]

现在我们对贝叶斯定理有了一个很好的理解。让我们继续了解它在分类问题中的用途。

朴素贝叶斯直觉

问题:试着预测一个信用分数为 180 的候选人是否会拖欠贷款。考虑下面的频率表来计算违约的可能性。

图 2:频率表[图片由作者提供]

我们可以按照下面的步骤来计算概率。由于候选人的信用分数为 180,让我们预测一下(100–200)的标签。

步骤 1:计算每个类别的先验概率(是和否)

p(是)= 11/29 = 0.379

p(100–200)= 10/29 = 0.345
第二步:找到每个类的每个属性的似然概率

p(100–200 | Yes)= 6/11 = 0.545
第三步:利用贝叶斯定理计算后验概率

P(是| 100–200)= P(100–200 |是)* P(是)/P(100–200)

= 0.545 * 0.379/0.345 = 0.5989 = 0.599
第四步:做预测

因为,候选人违约的概率超过 50%(这是假设的显著性水平,它可以根据用例而不同),我们可以说候选人将违约。

端到端朴素贝叶斯分类器

了解了朴素贝叶斯分类器的工作原理后,让我们尝试使用 sklearn 基于它构建一个分类模型。Sklearn 或 scikit-learn 是一个用 python 编写的开源机器学习库。

出于本文的目的,我们将使用 social_network_ads 数据集。在这个问题中,我们将根据年龄和预计工资,通过点击社交媒体上向他/她显示的广告来预测用户是否购买了产品。所以让我们开始吧。

步骤 1:导入基本库

步骤 2:导入数据

图 3:自变量和因变量概览[图片由作者提供]

步骤 3:数据预处理

在数据预处理步骤中,我们首先将数据集分为训练集(80%)和测试集(20%)。接下来,我们使用标准标量完成了一些基本的特征缩放。标准标量以平均值为 0、标准差为 1 的方式转换数据。

第四步:模特训练

步骤 5:模型测试和评估

图 4:困惑矩阵[图片由作者提供]

混乱矩阵让我们知道我们的模型有多好。它描述了一个分类模型在一组已知
真值的测试数据上的性能。混淆矩阵中的每一行代表一个实际类别,而每一列代表一个预测类别。

第六步:视觉化

图 5:朴素贝叶斯分类模型的可视化

这一步不是必需的。它只是提供了一个概念,说明模型是如何对数据点进行分类的。

包裹

在这篇文章中,我们学习了朴素贝叶斯分类器背后的数学原理,并使用 sklearn 建立了一个模型。在接下来的文章中,我们将学习一些其他的分类算法作为这个系列的一部分,比如逻辑回归,决策树等等。敬请关注。

甲壳虫乐队和泰勒·斯威夫特的自然语言处理介绍

原文:https://towardsdatascience.com/introduction-to-natural-language-processing-with-the-beatles-and-taylor-swift-2a06055cbc14?source=collection_archive---------35-----------------------

使用不同的技术操作非结构化数据,如标记化、词条化、停用词、TF-IDF。

利物浦的披头士雕像。来源

自然语言处理是一个有趣的领域,因为消除输入句子的歧义以产生机器表示语言是发人深省的。看看著名的格劳乔·马克斯的笑话:

一天早上,我射杀了一头穿着睡衣的大象。我永远不知道他是怎么穿上我的睡衣的。

在人的层面上,这句话有几种解读。但是计算机几乎不可能理解。

尽管如此,NLP 的学习曲线并不陡峭,而且可能很吸引人。在这个项目中,我将用披头士和泰勒斯威夫特的歌词来解释自然语言处理的初级水平。最终目标是比较披头士和泰勒·斯威夫特的歌词的用词,看看我们能否将它们聚类。要实现这一目标,有 6 个步骤:

  • 过滤和清洗
  • 标记化
  • 词干化、词汇化、停用词
  • 矢量化
  • 词频—逆文档频率(TF-IDF)
  • 可视化

0)导入歌曲:

你不需要运行代码来理解这个博客。但是如果你对它感兴趣,你可以在这里找到我的 Github 库。该文件夹的树形结构为:

  • main.ipynb
  • 数据->(披头士-> 10 首歌),(泰勒斯威夫特-> 10 首歌)

甲壳虫乐队:爱我吧,我想牵着你的手,在我的吉他轻轻哭泣的时候,一起来吧,一些事情,埃莉诺·里格比,生活中的一天,不要让我失望,救命,嘿,裘德

泰勒斯威夫特(Taylor Swift):嫌隙,你需要冷静下来,秀气,男人,你属于我,很快你就会好起来,看你让我做什么,我!,爱情故事,22。

import glob
TheBeatle=glob.glob("Data/TheBeatle/*.txt")
TaylorSwift=glob.glob("Data/TaylorSwift/*.txt")
filenames=TheBeatle+TaylorSwift

我们需要一首歌来做测试,让我们看看“嘿,裘德”的前 4 行

with open('Data/TheBeatle/HeyJude.txt') as f:
    test_song = f.readlines()
    test_song = test_song[:4]
    print(test_song)>>> ["Hey Jude, don't make it bad\n", 'Take a sad song and make it better\n', 'Remember to let her into your heart\n', 'Then you can start to make it better\n']

太好了,我们刚刚完成了项目的第一步。

1) 过滤和清洗

我们需要问自己的第一个问题是我们要清洁什么。我们的目标是降低句子的复杂性,删除无意义的字符。要更改为不同的歌曲,请查看filenames列表并选择歌词对应的目录。从这一点来说,我把链接改为‘Data/TaylorSwift/YouNeedToCalmDown.txt'作为例子,因为它的内容有更多有趣的字符需要清理。让我们来看看泰勒·斯威夫特的《你需要冷静》的前几行。

["You are somebody that I don't know\n", "But you're takin' shots at me like it's Patrón\n", "And I'm just like, damn, it's 7 AM\n", "Say it in the street, that's a knock-out\n"]

我们需要删除\n和一些标点符号,如果他们存在。我们想把号码留在那里,它可能表明歌手的风格。小写所有的单词使其易于处理,但可能会使专有名词变成常规名词。我们还需要把你是这个词转换成你是,我是我是,那是那是,采取,但这一步将在后面的步骤中实现。

import stringpunctuations = list(string.punctuation)
punctuations.remove("'") #Not include the apostrophe
punctuations+="\n"def clean_song(song):
    cleaned = []
    for line in song:
        for symbol in punctuations:
            line = line.replace(symbol, '').lower()
        cleaned.append(line)
    return cleanedclean_song(test_song)[:4]>>> ["you are somebody that i don't know",
 "but you're takin' shots at me like it's patrón",
 "and i'm just like, damn, it's 7 am",
 "say it in the street, that's a knock-out"]

注意,我想把撇号'留在那里,因为去掉它可能会使一个单词变得毫无意义

2) 标记化

标记化是将字符串、文本标记化或拆分成一系列标记的过程。我们可以把记号看作是部分,就像单词是句子中的记号,句子是段落中的记号一样。

标记一个单词最简单的方法是split()方法,它将一个字符串转换成一个字符串数组。然而,这种方法有一个问题。像don’tTaylor’s这样的单词是两个不同单词的组合。很难列出适用于所有情况的所有拆分规则。因此,我们需要 NLTK 标记器的帮助。NLTK 代表自然语言处理工具包。它是文本处理的一站式商店,每个人都可以使用。让我们看看 NLTK 函数word_tokenize,看看它对一个随机的句子做了什么。

from nltk import word_tokenizesentence= "I'm dangerous. Don't underestimate!!!"
print(word_tokenize(sentence))
print(sentence.split(" "))>>>['I', "'m", 'dangerous', '.', 'Do', "n't", 'underestimate', '!', '!', '!']
>>>["I'm", 'dangerous.', "Don't", 'underestimate!!!']

注意word_tokenize将否定形式的*verb* 拆分为verb + n’t。它还将感叹号和点号从单词中分离出来。在这种情况下,我们已经在前面的部分照顾到了标点符号,但重复是可以的。下面是接收歌曲的干净版本并对其进行标记的函数:

def tokenize(song):
    joined_song = ' '.join(song) #Join sentences together
    tokenized_song = word_tokenize(joined_song)
    return tokenized_song

3)词干化、词汇化、停用词

根据 Geek to Geek 的说法,词干化是产生词根/基本词的形态变体的过程。词尾变化是将一个词的不同屈折形式组合在一起的过程,因此它们可以作为一个单项进行分析。

几个例子展示了每种方法对我们工作的不同影响,并决定了我们想要包含哪种方法

from nltk.stem import PorterStemmer  
from nltk.stem import WordNetLemmatizer 

ps = PorterStemmer() 
lemmatizer = WordNetLemmatizer()# choose some words to be stemmed 
words = ["takin'", "knock-out", "don't", "dangerous","working", "apples", 'better', 'died' ] 

for w in words: 
    print(w,":", ps.stem(w),lemmatizer.lemmatize(w,pos ="v"))>>> 
takin' : takin' takin'
knock-out : knock-out knock-out
don't : don't don't
dangerous : danger dangerous
working : work work
apples : appl apples
better : better better
died : die die

第一列是我们文本中的单词,后面是词干词条列。词干是处理单词的一种简单方法。它只是根据某些特定的规则截断单词,将其转换为词根。有时候会把单词搞得很乱。我们不希望apples变成appl。这就是为什么我做不选炮泥的原因。

另一方面,词汇化之后是更复杂的规则。注意在方法中lemmatizepos ( 词性)改成了“v”(动词)。所以died变成了die。如果我们把pos改成"n"apples就会变成apple。如果我们把pos改成"a"(形容词),better就会变成good。我们可以过滤许多其他层,但是为了更简单,我将依次应用“a””v”“n”层。

停用词:停用词是我们可以简单忽略的常用词(如“the”、“A”、“an”、“in”),因为它们不会给我们的分析带来任何价值。下面的代码显示了我们如何从nltk导入停用词列表

from nltk.corpus import stopwordsstopwords_list = stopwords.words('english')
print(len(stopwords_list))
print(stopwords_list[:10])
print(stopwords_list[35:45])>>>179
>>>['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', "you're"]
>>>['what', 'which', 'who', 'whom', 'this', 'that', "that'll", 'these', 'those', 'am']

有 179 个停用词,但我不想全部使用。对于这个项目,我认为代词可能表明作者对这首歌的观点。例如,我在本文中使用“我们”,因为我希望读者和我在同一页上。你和我在歌曲中重复的词可能表明这首歌实际上是作者的故事。泰勒·斯威夫特因写她过去恋情的爱情故事而闻名,这可能是她与披头士的区别。然而,第 35 个停用词可能就没那么有趣了

我还创建了几个不在列表中的停用词。我知道该补充些什么,因为我尝试过不同的歌曲来理解缺失了什么。让我们为我们已经讨论过的内容创建一个函数:

from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizerstopwords_list = stopwords.words('english')
stopwords_list=stopwords_list[35:]
stopwords_list+=["n't", "it", "'s","'m", "'re","'"]
lemmatizer = WordNetLemmatizer()def lemmatize_remove_stopwords(tokenize_list):
    lemmatized_words=[]
    for w in tokenize_list:
        w=lemmatizer.lemmatize(w,pos ="a")
        w=lemmatizer.lemmatize(w,pos ="n")
        w=lemmatizer.lemmatize(w,pos ="v")
        lemmatized_words.append(w)
    song_noStopword = [i for i in lemmatized_words if i not in stopwords_list]
    return song_noStopwordprint(lemmatize_remove_stopwords(tokenize(test_song))[:23])>>> ['you', 'somebody', 'i', 'know', 'you', 'takin', 'shoot', 'me', 'like', 'patrón', 'i', 'like', 'damn', '7', 'say', 'street', 'knockout']

4) 矢量化和计数频率

有了一个非常好的可以清理和标记歌曲的函数后,我们的下一步是计算每个单词出现的次数。该函数将接收一个令牌列表,并返回唯一的令牌及其计数。注意,在后面一步,我们要比较所有歌曲的相似度。因此,t 第二个输入(可选)应该是所有歌曲的唯一令牌。我们来看看下面的功能:

def vectorize_and_freq(song, vocab=None):

    if vocab:
        unique_words = vocab
    else:
        unique_words = list(set(song)) #initial bag of word dictionary
    song_dict = {i:0 for i in unique_words} 

    for word in song:
        song_dict[word] += 1

    return song_dictoutput_=lemmatize_remove_stopwords(tokenize(test_song))
output_=vectorize_and_freq(output_)
list(output_.items())[:10]>>> [('le', 1), ('But', 6), ('okay', 1), ('bone', 1), ('calm', 8), ('When', 1), ('must', 1), ('your', 2), ('see', 1), ('like', 7)]

太棒了。你差不多完成了。现在到了项目中最重要的一步。

4)词频—逆文档频率(TF-IDF)

TF-IDF 是两个单独指标的组合,即 TF 和 IDF。当我们有多个文档时,使用 TF-IDF。这个想法是一个单词在一种类型的文档中出现的次数比其他的多。这一步的最终目标是有一个包含 20 首歌曲的表格,其中的列是所有文档中唯一的 vocabs。每列中的值是由 TF-IDF 公式分配的每个单词的相应权重

a)术语频率

顾名思义,我们希望找到单词t在单个文档中的出现率。让我们创建词频函数,并显示在整首歌中最常见的前 10 个词。

def term_frequency(BoW_dict):
    total_word_count = sum(BoW_dict.values()) 

    for ind, val in BoW_dict.items():
        BoW_dict[ind] = val/ total_word_count

    return BoW_dict#Apply different function 
output_=clean_song(test_song)
output_=tokenize(output_)
output_=lemmatize_remove_stopwords(output_)
output_=vectorize_and_freq(output_)
ouput_=term_frequency(output_)#Sort the output_ dictionary by values and then keys
ouput_=sorted(ouput_.items(), key = lambda kv:(kv[1], kv[0]),reverse=True)for i in ouput_[:5]:
    print(i)>>> ('you', 0.1542056074766355)
>>> ('ohoh', 0.14018691588785046)
>>> ('need', 0.056074766355140186)
>>> ('like', 0.04672897196261682)
>>> ('i', 0.037383177570093455)

term_frequency's函数只是一个标准化的vectorize_and_freq函数,在一首歌中使用 vocabs。

b)逆文档频率

逆文档频率取文档总数与包含单词t的文档数之比的自然对数:

def inverse_document_frequency(dicts_list):
    #0 : Total Number of Document
    num_doc=len(dicts_list)

    #1: Find all the unique words for all the document
    vocab_set=[]
    for d in dicts_list:
        for word in d.keys():
            vocab_set.append(word)
    vocab_set=set(vocab_set)

    #2: Number of document with t in it
    idf_t = {i:0 for i in vocab_set} #initial lize the list

    for word in idf_t.keys():
        docs = 0
        # Find number of doc for each word
        for d in dicts_list:
            if word in d:
                docs += 1

        # Compute idf for each t
        idf_t[word] = np.log((num_doc/ float(docs)))

    return idf_t

在分别计算了每个 TF 和 IDF 之后,让我们将它们组合在一起

def tf_idf(dicts_list):
    # Vocab for corpus
    doc_tf_idf = {}
    idf = inverse_document_frequency(dicts_list)
    full_vocab_list = {i:0 for i in list(idf.keys())}

    # Create tf-idf list of dictionaries, containing a dictionary that will be updated for each document
    tf_idf_list_of_dicts = []

    # Now, compute tf and then use this to compute and set tf-idf values for each document
    for doc in dicts_list:
        doc_tf = term_frequency(doc)
        for word in doc_tf:
            doc_tf_idf[word] = doc_tf[word] * idf[word]
        tf_idf_list_of_dicts.append(doc_tf_idf)
    return tf_idf_list_of_dicts

该函数获取每首歌曲的词汇字典列表,并为每首歌曲中的每个词汇创建相应的“tf-idf”权重。注意,这些权重不能为 0,因为 TF 和 IDF 项总是大于 0。

最后,我们希望将我们创建的所有函数组合成一个元函数:

def main(filenames):
    # Iterate through list of filenames and read each in
    cvad = [] #count vectorized all documents
    for file in filenames:
        with open(file) as f:
            raw_data = f.readlines()
        # Clean and tokenize raw text
        ouput_ = clean_song(raw_data)
        ouput_ = tokenize(ouput_)
        ouput_=lemmatize_remove_stopwords(ouput_)  
        ouput_ = vectorize_and_freq(ouput_)
        cvad.append(ouput_)
    # tf-idf representation of everything
    tf_idf_all_docs = tf_idf(cvad)

    return tf_idf_all_docstf_idf_all_docs = main(filenames)print("Number of Dimensions: {}".format(len(tf_idf_all_docs[12])))
for key, value in list(tf_idf_all_docs[15].items())[20:25]:
    print(key,value)>>> Number of Dimensions: 712
>>> let 0.003921735518976991
>>> happy 0.016807190459810554
>>> get 0.006288801694780355
>>> your 0.01002310915754525
>>> think 0.0033410363858484165

这个主函数的输出是 20 首歌曲的列表,每个单词对应一个 tf-idf 权重。20 首歌里有 712 个 vocabs(词根)。上面的输出显示了泰勒·斯威夫特的《微妙》中一些词汇的 tf-idf 权重。

可视化

我们的目标是把这 20 首歌画在一个可视化的空间里。然而,有 712 个维度。谈到降维,我想到的有两种方法:主成分分析(PCA)T-分布式随机邻居嵌入(t-SNE)。PCA 侧重于保持数据点从高维到低维的方差,而 t-SNE 侧重于相似点的概率分布。因此 t-SNE 更适合这个项目。

让我们定义将数据转换为 2D 的 t-SNE 实例:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.manifold import TSNEnp.random.seed(4)
tf_idf_all_docs = main(filenames)
tf_idf_vals_list= [list(i.values()) for i in tf_idf_all_docs] 
TSNE_2d = TSNE(n_components=2)
data_2d = TSNE_2d.fit_transform(tf_idf_vals_list)

请注意,我将种子更改为 4,因为在不同的运行中可能会有不同的结果。原因是不像 PCA,t-SNE 有一个非凸的目标函数。使用随机启动的梯度下降优化来最小化目标函数。让我们来看看我们歌曲中的 2D 情节:

TheBeatle = data_2d[:10]
beatle_x = [i[0] for i in TheBeatle]
beatle_y = [i[1] for i in TheBeatle]TaylorSwift = data_2d[10:]
ts_x = [i[0] for i in TaylorSwift]
ts_y = [i[1] for i in TaylorSwift]fig = plt.figure(figsize=(20,10))
ax = fig.add_subplot(222)
ax.scatter(beatle_x, beatle_y, color='g', label='The Beatles')
ax.scatter(ts_x, ts_y, color='r', label='Taylor Swift')
ax.legend()
plt.show()

这是 4 号种子的结果

种子=4 的 t-SNE 2D 地图。资料来源:Huy Bui

该图没有真正显示清晰的集群。让我们试试 10 号种子

种子=10 的 t-SNE 2D 地图。资料来源:Huy Bui

这些点更加分散。关于这个结果,我们可以总结出几点:

  • 也许我们没有足够的歌曲
  • 也许预处理步骤没有真正概括每个歌曲作者的特征
  • 首先,也许没有太大的区别。
  • 也许我们可以做更多的特色工程。但是这超出了本文的范围。

有很多不确定性,但我们肯定知道的一件事是,NLP 需要很多思想和技术来产生一些有意义的东西。

摘要

在这个项目中,我们学习了自然语言处理中的一些基本概念,如标记化、词干化、词汇化、TF-IDF,以及各种删除停用词和可视化结果的策略。

感谢阅读!

神经网络导论—第 1 部分

原文:https://towardsdatascience.com/introduction-to-neural-networks-part-1-3bb27a8d314a?source=collection_archive---------17-----------------------

入门

理解最早的模型:感知器和 Adaline

乌列尔 SCUnsplash 上的照片

WAI 的目的是什么?毫无疑问,这是为了满足人类使用不同的概念、模型和技术创造类似人类的机器的渴望,这些概念、模型和技术仍在不断改进,因为你越成长,你的需求就越大。1943 年,沃伦·麦卡洛克和沃尔特·皮茨用电路模拟了一个简单的神经元,由此产生了模拟人类神经元或者换句话说创造一个人造神经元的想法。当然,这只是人工神经网络(ANN)历史上的一小部分。如果你想知道更多,那就看看这个。

动机

多年来,AI 了解了许多不同的模型,例如:

  • 一元/多元线性回归
  • 一类/多类的逻辑回归(分类)(一对多技术)

所有这些提到的模型之间的共同因素是它们的线性,它们只能应用于可线性分离的数据,这实际上是导致创建神经网络模型的原因之一,即使最早的模型也是线性分类器(线性分隔符)。本质上,它过去是,现在仍然是一种试图模仿大脑的算法,大脑是迄今为止我们知道的最强大的学习机器。

作者图片

所以,在开始理论之旅之前,我们先来了解一下什么是前馈神经网络

  • 前馈神经网络:是一种神经网络,其中节点(定义如下)之间的连接不形成循环。不同于它的后代递归神经网络 (RNN)(在以后的文章中可以看到)。本文讨论的模型属于前馈神经网络类型。

感知器,根

一个单层神经网络,一个线性阈值单元( LTU ) / 门( LTG ),甚至一个神经元……随便你怎么称呼。人类神经元是一种从其他细胞接收电信号作为输入并基于此输出信号的细胞。这个神经元使用数值来做完全相同的工作,这就是数学成为你最好的朋友的时候!

如果你熟悉前面提到的线性分类器,那么你肯定知道什么是假设函数,什么是决策边界代表什么。如果没有,让我快速介绍一下:

  • 假设:最能描述目标的函数称为 Y
  • 决策边界:最佳拟合线,能够根据不同的类标签分离数据。每个分类器的目标是找到决策边界。注意,在二进制分类中, i t 是 之间的战斗。一

模型描述如下:

  • 输入值(X): 单样本 x特征向量(属性)x₁…xₙ
  • 权值(W): 称为θ(theta)偶尔,一个向量的参数用来形成不同节点之间的连接,每个权值都与一个输入相关联,并显示它将对输出产生多大的影响。**
  • 偏置(b): 节点 x₀ ,带有**1的常数值。即使所有输入都为空,也能保证神经元的激活。**
  • 净输入(net): 权重和输入的点积,很多时候叫做 z

  • 激活函数:阈值函数 g(z) ,使感知器成为二元分类器(2 类标签函数)。阈值表示为 θ

为了简化 g(z)我们把 θ 带到左边,认为它是与偏差相关联的参数【w₀】【g(z)z 变成:**

********

  • 输出(假设):激活函数的结果,简称为【o(x)这也是假设的结果【h(x)**

2D 决策边界图解—作者图片

感知器训练规则…谢谢罗森布拉特

假设权重已经用小数字随机初始化,第一个样本 x 正在运行感知器模型,最终输出指示一个错误的类,现在该怎么办?这是 AI 吗?

幸运的是没有,该模型将通过改进值在每次迭代中学习,因此它可以使用 Rosenblatt 在 1959 年引入的以下训练/学习规则来更好地执行:**

  • 学习率:一个超参数 ,它控制每次更新模型权重时响应估计误差而改变模型的程度。传统值为 0.10.01 ,始终在 01 的范围内。

感知器分类器示意图——由 mlxtend 拍摄

现在,我们已经为算法做好了准备:

****- Random initialization of the weights, with small numbers
- For each epoch:
  - For each training sample xϵX**:
     .** Calculate output value o(x)
     .  For i from 1..n:
           w*ᵢ =* w*ᵢ +* ∆w*ᵢ*****

这个小怪物实际上能够表示各种功能,如 And、Or、Nand、Nor、m-of-n…还有很多。但也有很多情况下它会失败,例如 XOR 函数,因为这个函数不是线性可分的,所以模型将无法为它找到正确的决策边界,并且会无限地使用相同的权重留在循环内,除非你组合多个感知器,换句话说,形成感知器的网络(不能推广到所有线性不可分的数据):

如果我们给上面显示的每个逻辑操作分配一个感知器,我们将使用三个已经训练好的模型(而不是)来训练一个复杂的感知器。更多详情,请查看出。

感知器模型仍然是上面提到的麦卡洛克-皮茨神经元的计算版本,它当然不能满足现代人工智能的要求。这就是为什么 Adaline 出现了!!(不是电影)

自适应线性神经元时代(Adaline)

和感知器一样的结构,不同的引擎!

WidrowHoff1960 年开发,被认为是许多复杂的机器学习算法的基础,如逻辑回归和支持向量机(SVMs)。还有一个二元分类器和一个线性分隔符。

  • 激活函数:净输入【z】的线性函数(恒等函数)记为【x】**
  • 仍然需要使用阈值函数 g(z)
  • 与感知器模型不同,Adaline 使用连续输出 z 来学习模型权重。这比仅仅利用预测类标签要有效得多。

Adaline 分类器示意图—由 mlxtend 成像

Adaline 类似于应用线性回归,唯一的区别是使用阈值函数将最终输出转换为分类输出。该模型使用所谓的代价函数 J(w) 来估计其误差。这背后的逻辑是,最佳拟合线被定义为最小化误差平方和(SSE) 的线。误差被认为是数据点(一个样本)与拟合线(判定边界)的垂直偏差(残差)。在这个阶段,一些细节可能看起来有点模糊,但如果你继续阅读,将会得到进一步的解释。

其中 X 是训练样本的集合, y(x) 一个训练样本的目标Xo(X)是连续输出(净输入) z**

  • 成本函数是误差平方和()除以 2,以便于推导过程。

2D 线性回归模型中垂直偏差的图示-图片由作者提供

优化…我们来了

我们讨论了成本函数,并且碰巧提到了术语最小化…因为误差函数存在的主要原因是最小化误差,因此得名!

我们认为有两种主要方法可以做到这一点:

  • 正规方程(封闭解)
  • 标准/随机梯度下降

在本文中,我们将涵盖标准和随机梯度下降技术。该过程是直接的,我们在每次迭代中计算成本函数的值,通过在特定点 ( w,J(w) ) 寻找正切值(偏导数)向函数的全局最小值前进一步,并使用Delta 规则更新权重。当达到全局最小值(或局部最小值)时,循环停止(零导数)。

嗯..德尔塔法则…这是怎么回事?

还记得在感知器中,权重是如何根据 Rosenblatt 的学习规则更新的吗,与 Adaline 中的前提相同,但公式不同。

  • 减号表示我们正朝着成本梯度的相反方向前进一步,如图所示。

梯度下降

现在我们已经到了推导部分,如果你只对结果表达式感兴趣,你可以跳过它。否则,推导过程如下:

成本函数的偏导数 J(w) w.r.t 各权重 wᵢ (i ϵ 1..n) 是:

********

梯度下降—由 mlxtend 成像

标准梯度下降(物品)

称为 Batch-GD 模式,用于在处理整个数据集后更新权重,因此步长较大。然而,它不能保证找到全局最小值,并且如果代价函数是非凸的,它可能容易收敛到局部最小值。

****- Random initialization of the weights, with small numbers
- For each epoch : **.** Calculate output value o(x)for each training sample xϵX
  .  Calculate cost gradient ∇J
  .  For i from 1..n :
        w*ᵢ =* w*ᵢ +* ∆w*ᵢ*****

随机梯度下降

也被称为迭代/在线模式,用于计算成本梯度并在每个训练样本之后更新权重,这使得即使成本函数是非凸的,也更有可能找到全局最小值。因此,收敛需要更多的时间(达到最小成本)。

****- Random initialization of the weights, with small numbers
- For each epoch :
  - For each batch training sample xϵX **:
     .** Calculate the output value o(x)
     .  Calculate cost gradient ∇J
     .  For i from 1..n :
           w*ᵢ =* w*ᵢ +* ∆w*ᵢ*****

让 GD 算法收敛更快的方法

  • 在大规模机器学习系统中,通常使用小批量,这是 GDSGD 之间的折衷。SGD 产生更平滑的收敛。
  • 当特征相差数量级时,特征缩放提供数值稳定性,使得更有可能使 GD 收敛得更快。存在各种方法,例如最小-最大归一化标准化

检查学习率值

本节展示了绘制学习曲线对于梯度下降算法的重要性。有时,当 GD 没有很好地收敛或者根本没有收敛时,问题可能出在你选择的学习率值上。

  • 太大:算法可能超过最小值并发散,如左图所示。
  • 太小:可能需要太多的历元来收敛(小步),并且可能导致局部最小值而不是全局最小值。

学习率较大和较小的 GD 行为

决策边界方程

当您有一个二维输入向量时,分隔线方程的类型为:

其中 a 称为斜率by 轴截距。******

先将净输入 z 设置为0;******

如果把【x₁】x₂、w₀ 分别换成 y、a、b、C ,看起来就像是一条线的标准方程。******

下一步是寻找 x 轴截距y 轴截距,这样你就得到直线上的两点,这样你就可以最终找到斜率,即**

摘要

神经网络的两个初始模型是:

  • 感知器
  • 自适应线性神经元

相似之处:

  • 线性分类器
  • 二元分类器
  • 阈值函数的使用

差异:

  • 感知器模型使用其预测的类别标签(分类输出)和 感知器学习规则 来学习其系数(权重)。
  • 另一方面,Adaline 使用其连续结果和 delta 规则 以获得更高的准确性。

如果 GD 算法在几个纪元后仍然停滞不前,那么您可能需要考虑调整您的学习率值以获得更好的性能。

[1]:阿卜杜勒·拉森。(2020 年 7 月)。https://morioh.com/p/1d9e1c91f4a3 的 FNN 和 CNN 使用 Pytorch

[2]:帕布。(2018 年 7 月 3 日)。了解超参数及其优化技术https://towards data science . com/understanding-hyperparameters-and-its-optimization-techniques-f 0 debba 07568 #:~:text = In % 20 statistics % 2C % 20 hyperparameter % 20 is % 20a,Model % 20 parameters % 20 vs % 20 hyperparameters

[3]:杰森·布朗利。(2020 年 9 月 12 日)。了解学习率对神经网络性能的影响https://machine Learning mastery . com/understand-the-dynamics-of-Learning-Rate-on-deep-Learning-Neural-networks/

NLP 介绍——第 1 部分:用 Python 预处理文本

原文:https://towardsdatascience.com/introduction-to-nlp-part-1-preprocessing-text-in-python-8f007d44ca96?source=collection_archive---------19-----------------------

欢迎来到 NLP 入门!这是 5 篇系列文章的第一部分。这篇文章将展示一种预处理文本的方法,使用一种叫做单词包的方法,其中每个文本都用它的单词来表示,而不管它们出现的顺序或嵌入的语法。预处理时,我们将完成以下步骤:

  1. 象征化
  2. 正常化
  3. 删除停用词
  4. 计数矢量
  5. 转换到 tf-idf 表示

💤这些术语对你来说像是胡言乱语吗?不要担心,当你读完这篇文章的时候,他们已经不在了!🎓

萨法尔·萨法罗夫在 Unsplash 上拍摄的照片

0.Python 设置🔧

我假设读者(👀是的,你!)可以访问并熟悉 Python,包括安装包、定义函数和其他基本任务。如果你是 Python 的新手,这个是一个入门的好地方。

我已经使用并测试了 Python 3.7.1 中的脚本。在我们开始之前,让我们确保你有合适的工具。

⬜️确保安装了所需的软件包:pandas, nltk & sklearn

我们将使用以下强大的第三方软件包:

  • 熊猫:数据分析库,
  • nltk: 自然语言工具包库和
  • sklearn: 机器学习库。

⬜️ 从 nltk 下载“停用词”和“wordnet”语料库

下面的脚本可以帮助你下载这些语料库。如果您已经下载了,运行此程序将通知您它们是最新的:

import nltk
nltk.download('stopwords') 
nltk.download('wordnet')

1.数据📦

为了使事情易于管理,我们将使用微小的文本数据,这将允许我们监视每一步的输入和输出。对于这个数据,我选择了情景喜剧老友记中乔伊为钱德勒和莫妮卡的婚礼准备的演讲稿。

他的演讲是这样的:

part1 = """We are gathered here today on this joyous occasion to celebrate the special love that Monica and Chandler share. It is a love based on giving and receiving as well as having and sharing. And the love that they give and have is shared and received. And
through this having and giving and sharing and receiving, we too can share and love and have... and receive."""part2 = """When I think of the love these two givers and receivers share I cannot help but envy the lifetime ahead of having and loving and giving and receiving."""

如果你没有看到我提到的部分,YouTube 上有一些短视频(关键词:乔伊的婚礼致辞)。我认为乔伊的表演和莫妮卡和钱德勒的反应绝对让这个演讲比单纯的文字有趣多了。写这个帖子给了我一个很好的借口来反复观看这个场景,我无法满足它。🙈

2.最终代码📃

首先,让我们用包和数据准备环境:

# Import packages and modules
import pandas as pd
from nltk.stem import WordNetLemmatizer
from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords
from sklearn.feature_extraction.text import TfidfVectorizer# Create a dataframe
X_train = pd.DataFrame([part1, part2], columns=['speech'])

其次,让我们定义一个文本预处理函数,将其传递给 TfidfVectorizer :

def preprocess_text(text):
    # Tokenise words while ignoring punctuation
    tokeniser = RegexpTokenizer(r'\w+')
    tokens = tokeniser.tokenize(text)

    # Lowercase and lemmatise 
    lemmatiser = WordNetLemmatizer()
    lemmas = [lemmatiser.lemmatize(token.lower(), pos='v') for token in tokens]

    # Remove stopwords
    keywords= [lemma for lemma in lemmas if lemma not in stopwords.words('english')]
    return keywords

最后,让我们利用前面定义的函数对文本数据进行预处理:

# Create an instance of TfidfVectorizer
vectoriser = TfidfVectorizer(analyzer=preprocess_text)# Fit to the data and transform to feature matrix
X_train = vectoriser.fit_transform(X_train['speech'])# Convert sparse matrix to dataframe
X_train = pd.DataFrame.sparse.from_spmatrix(X_train)# Save mapping on which index refers to which words
col_map = {v:k for k, v in vectoriser.vocabulary_.items()}# Rename each column using the mapping
for col in X_train.columns:
    X_train.rename(columns={col: col_map[col]}, inplace=True)
X_train

tf-idf 矩阵(未显示所有列)

Ta-da❕我们将文本预处理成特征矩阵。这些脚本在没有任何解释的情况下有意义吗?让我们在下一节通过例子来分解和理解开头提到的 5 个步骤。

3.最终代码分解和解释🔍

第一步:标记化

💡 " 给定一个字符序列和一个定义好的文档单元,标记化就是把它分割成小块的任务,叫做标记,也许同时扔掉某些字符,比如标点符号。

在这一步,我们将把一个字符串 part1 转换成一个记号列表,同时去掉标点符号。我们有许多方法可以完成这项任务。我将通过使用 nltk: 中的 RegexpTokenizer 向您展示一种方法

# Import module
from nltk.tokenize import RegexpTokenizer# Create an instance of RegexpTokenizer for alphanumeric tokens
tokeniser = RegexpTokenizer(r'\w+')# Tokenise 'part1' string
tokens = tokeniser.tokenize(part1)
print(tokens)

让我们来看看令牌是什么样子的:

代币

我们看到每个单词现在是一个单独的字符串。你注意到同一个词有不同的用法了吗?例如:单词的大小写可以不同:“and”和“and”或它们的后缀:“share”、“shared”和“sharing”。这就是标准化的由来。

第二步。正常化

💡 把一个词规格化就是把它转换成它的词根形式。

词干分析和词条解释是规范化文本的常用方法。在这一步中,我们将使用 lemmatisation 将单词转换为它们的字典形式,并通过将所有单词转换为小写来消除大小写差异。

🔗如果你想了解更多关于词干和词尾的知识,你可能想看看这个系列的第二部分。

我们将使用 nltk 中的 WordNetLemmatizer 来对我们的令牌进行符号化:

# Import module
from nltk.stem import WordNetLemmatizer# Create an instance of WordNetLemmatizer
lemmatiser = WordNetLemmatizer()# Lowercase and lemmatise tokens
lemmas = [lemmatiser.lemmatize(token.lower(), pos='v') for token in tokens]
print(lemmas)

前题

这些单词现在被转换成它的字典形式。例如,“分享”、“分享”和“共享”现在都只是“分享”。

# Check how many words we have
len(lemmas)

我们有 66 个单词,但不是所有的单词对文本意义的贡献都是相同的。换句话说,有些词对关键信息不是特别有用。这就是停用词出现的地方。

第三步。删除停用词

💡停用词是常见的词,对文本的意义没有什么价值。

想一想:如果你必须用三个词尽可能详细地描述你自己,你会包括“我”还是“我”?如果我让你在乔伊演讲中的关键词下面划线,你会划‘a’还是‘the’?大概不会。I、am、a 和 The 都是停用词的例子。我想你明白了。

根据文本涉及的领域,可能需要不同的停用词集。在这一步,我们将利用 nltk 的停用词语料库。您可以定义自己的停用字词集,或者通过添加适合文本领域的常用术语来丰富标准停用字词。

让我们先稍微熟悉一下的常用词:

# Import module
from nltk.corpus import stopwords# Check out how many stop words there are 
print(len(stopwords.words('english')))# See first 5 stop words
stopwords.words('english')[:5]

在写这篇文章的时候,nltk 的停用词语料库中有 179 个英语停用词。一些例子包括:“我”、“我”、“我的”、“我自己”、“我们”。如果您很想看到完整的列表,只需从最后一行代码中删除[:5]

注意这些停用词是如何小写的?为了有效地删除停用词,我们必须确保所有单词都是小写的。在这里,我们已经在第二步中这样做了。

使用列表理解,让我们从列表中删除所有停用词:

keywords = [lemma for lemma in lemmas if lemma not in stopwords.words('english')]
print(keywords)

关键词

# Check how many words we have
len(keywords)

去掉停用词后,我们只有 26 个词,而不是 66 个,但要点仍然保留。

现在,如果您向上滚动到第 2 部分(最终代码)并快速查看一下preprocess_text函数,您将会看到这个函数捕获了步骤 1 到 3 中所示的转换过程。

第四步。计数矢量

💡 Count vectorise 是将一组文本文档转换成一个 token counts 的矩阵

现在让我们来看看步骤 3 中关键词中每个单词的计数:

{word: keywords.count(word) for word in set(keywords)}

关键词计数

“给予”这个词出现了三次,而“快乐”只出现了一次。

这就是计数矢量器对所有记录所做的事情。计数矢量器通过 n 将文本转换成一个 m 的矩阵,其中 m 是文本记录的数量,n 是所有记录中唯一的标记的数量,矩阵的元素指的是给定记录的标记的计数。

在这一步,我们将把文本数据帧转换成计数矩阵。我们将把我们的自定义预处理器函数传递给计数矢量器:

# Import module
from sklearn.feature_extraction.text import CountVectorizer# Create an instance of CountfVectorizer
vectoriser = CountVectorizer(analyzer=preprocess_text)# Fit to the data and transform to feature matrix
X_train = vectoriser.fit_transform(X_train['speech'])

输出特征矩阵将是稀疏矩阵形式。让我们将它转换成具有适当列名的 dataframe,使它更易于阅读:

# Convert sparse matrix to dataframe
X_train = pd.DataFrame.sparse.from_spmatrix(X_train)# Save mapping on which index refers to which terms
col_map = {v:k for k, v in vectoriser.vocabulary_.items()}# Rename each column using the mapping
for col in X_train.columns:
    X_train.rename(columns={col: col_map[col]}, inplace=True)
X_train

计数矩阵(未显示所有列)

一旦我们将其转换为数据帧,列将只是索引(即从 0 到 n-1 的数字),而不是实际的单词。因此,我们需要重命名这些列,以便于解释。

当向量器适合数据时,我们可以从vectoriser.vocabulary_中找到单词的索引映射。此索引映射的格式为{word:index}。要重命名列,我们必须将键值对切换到{index:word}。这在第二行代码中完成,并保存在col_map中。

在代码末尾使用 for 循环,我们使用映射重命名每一列,输出应该类似于上表中的内容(由于空间限制,只显示了部分输出)。

从这个矩阵中,我们可以看到“give”在 part1(行索引=0) 中被提及 3 次,在 part2(行索引=1) 中被提及 1 次。

在我们的例子中,我们只有 2 条记录,每条记录只包含少量的句子,所以计数矩阵非常小,稀疏性也不高。稀疏性是指矩阵中所有元素中零元素的比例。当您处理包含数百、数千甚至数百万条记录(每条记录都由富文本表示)的真实数据时,计数矩阵可能会非常大,并且大部分包含 0。在这些情况下,使用稀疏格式可以节省存储内存,并加快进一步的处理。因此,在现实生活中预处理文本时,您可能并不总是像我们这里举例说明的那样将稀疏矩阵转换成数据帧。

第五步。转换到 TF-IDF 表示

💡 tf-idf 代表词频逆文档频率。

当转换为 tf-idf 表示时,我们将计数转换为加权频率,其中我们通过使用一个名为逆文档频率的权重,对不太频繁的词赋予更高的重要性,对较频繁的词赋予较低的重要性。

🔗我已经在系列的第三部分中专门写了一个单独的帖子来详细解释这一点,因为我认为它应该有自己的一节。

# Import module
from sklearn.feature_extraction.text import TfidfTransformer# Create an instance of TfidfTransformer
transformer = TfidfTransformer()# Fit to the data and transform to tf-idf
X_train = pd.DataFrame(transformer.fit_transform(X_train).toarray(), columns=X_train.columns)
X_train

在最后一步中,我们确保输出仍然是正确命名的数据帧:

tf-idf 矩阵(未显示所有列)

既然我们已经分别理解了第 4 步和第 5 步,我想指出,使用 TfidfVectorizer 有一种更有效的方法来完成第 4 步和第 5 步。这是使用以下代码完成的:

# Import module
from sklearn.feature_extraction.text import TfidfVectorizer# Create an instance of TfidfVectorizer
vectoriser = TfidfVectorizer(analyzer=preprocess_text)# Fit to the data and transform to tf-idf
X_train = vectoriser.fit_transform(X_train['speech'])

要将这个稀疏矩阵输出到具有相关列名的 dataframe 中,您知道该怎么做(提示:参见我们在步骤 4 中所做的)。

介绍完所有步骤后,如果您再次回到第 2 部分(最终代码)中的脚本,是否会比您第一次看到时更熟悉?👀

Gabriel Beaudry 在 Unsplash 上拍摄的照片

您想访问更多这样的内容吗?媒体会员可以无限制地访问媒体上的任何文章。如果你使用 我的推荐链接成为会员,你的一部分会费会直接去支持我。

感谢您花时间阅读这篇文章。我希望你从阅读它中学到一些东西。其余帖子的链接整理如下:
◼️ 第一部分:Python 中的文本预处理
◼️ 第二部分:引理和词干化的区别
◼️ 第三部分:TF-IDF 解释
◼️ 第四部分:Python 中的监督文本分类模型
◼️ 第五部分:Python 中的无监督主题模型(sklearn) 【T29

快乐预处理!再见🏃💨

4.参考📁

NLP 介绍-第 2 部分:引理满足和词干的区别

原文:https://towardsdatascience.com/introduction-to-nlp-part-2-difference-between-lemmatisation-and-stemming-3789be1c55bc?source=collection_archive---------48-----------------------

你想知道引理满足和词干的区别吗?如果你很想知道答案,这篇文章将试图解释它。

照片由 Unsplash 上反推

1.定义📗

引理和词干是规范化文本以获得单词的词根形式的不同技术。Christopher D. Manning、Prabhakar Raghavan 和 Hinrich Schütze 在他们的著作中对这两个概念做了如下简明的定义:信息检索导论,2008:

💡 “词干化通常指一种粗糙的启发式过程,即砍掉词尾,希望在大多数时候都能正确实现这一目标,通常还包括去除派生词缀……词干分析器使用特定于语言的规则,但是它们比词汇分析器需要更少的知识…”

💡 “词汇化通常是指利用词汇和词的形态分析来恰当地做事情,通常旨在仅去除屈折词尾并返回词的基本形式或词典形式,这就是所谓的词汇……一个词法分析器,它需要完整的词汇和词法分析来正确地对单词进行词法分析…”

如果这是你第一次阅读这些定义,他们可能不会马上点击。因为这些定义相当丰富和密集,所以慢慢地、仔细地、反复地阅读是有帮助的。如果你读完这篇文章后回来,希望这些定义会更有意义。

简化概述:词干化使用预定义规则将单词转化为词干,而词条化使用上下文词库派生词条词干不一定总是有效单词,而词条将总是有效单词,因为词条是单词的字典形式。

正如我们很快将在示例中看到的,这两种技术有时会产生相同的输出。

2.Python 设置🔧

本节假设您已经访问并熟悉 Python,包括安装包、定义函数和其他基本任务。如果你是 Python 的新手,这个是一个很好的开始。

我已经使用并测试了 Python 3.7.1 中的脚本。在使用代码之前,让我们确保您有合适的工具。

⬜️确保安装了所需的软件包:熊猫和 nltk

我们将使用以下强大的第三方软件包:

  • 熊猫:数据分析库和
  • nltk: 自然语言工具包库

⬜️从 nltk 下载“wordnet”语料库

下面的脚本可以帮助你下载这个语料库。如果您已经下载了它,运行它将通知您它是最新的:

import nltk
nltk.download('wordnet')

3.输出比较🔍

在我们深入例子之前,您应该知道有不同类型的词干分析器和词尾分析器可用。正如您所料,一种类型的词干分析器可能与其他类型的词干分析器有所不同。对于 lemmatisers 来说也是如此。

在我们的例子中,我们将使用来自 nltkPorterStemmer、LancasterStemmerWordNetLemmatizer 来规范化单词。

💡PorterStemmer:**最常用的词干分析器之一。它基于波特词干算法。更多信息,查看官方网页:【https://tartarus.org/martin/PorterStemmer/】

💡Lancaster stemmer:它基于 Lancaster 词干算法,有时会产生比 PorterStemmer 更激进的词干。

💡【WordNet lemma tiser】:使用 WordNet 词汇数据库。如果在 WordNet 中找不到输入单词,则返回不变的输入单词。

让我们创建一个函数,使用以下三种方法对单词进行规范化:

**# Import packages
import pandas as pd
from nltk.stem import PorterStemmer, LancasterStemmer, WordNetLemmatizer# Instantiate stemmers and lemmatiser
porter = PorterStemmer()
lancaster = LancasterStemmer()
lemmatiser = WordNetLemmatizer()# Create function that normalises text using all three techniques
def normalise_text(words, pos='v'):
    """Stem and lemmatise each word in a list. Return output in a dataframe."""
    normalised_text = pd.DataFrame(index=words, columns=['Porter', 'Lancaster', 'Lemmatiser'])
    for word in words:
        normalised_text.loc[word,'Porter'] = porter.stem(word)
        normalised_text.loc[word,'Lancaster'] = lancaster.stem(word)
        normalised_text.loc[word,'Lemmatiser'] = lemmatiser.lemmatize(word, pos=pos)
    return normalised_text**

我们将从 10 个任意名词开始,并比较它们的规范化形式:

**normalise_text(['apples', 'pears', 'tasks', 'children', 'earrings', 'dictionary', 'marriage', 'connections', 'universe', 'university'], pos='n')**

你可以看到词干并不总是一个有效的单词,而词条却是。大学和宇宙一旦被毁灭,看起来是一样的,但一旦被毁灭,情况就不同了。你有没有注意到上面的词干都不是以 e 结尾的?可能是因为词干的一个规则是去掉结尾的 e 吗?让我们用一些以“e”结尾的单词来检验这个假设:

**normalise_text(['pie', 'globe', 'house', 'knee', 'angle', 'acetone', 'time', 'brownie', 'climate', 'independence'], pos='n')**

不完全是,有些词干是以 e 结尾的。虽然这个假设不成立,但我想指出的是,词干提取有可观察到的趋势,因为它们是基于规则的。

如果我让你建议一些规则来规范各种形式的动词,你会推荐什么?是去掉后缀“ing”还是“ed”?如果有两个辅音,前面有一个元音,那么你会把最后一个辅音也去掉吗?诸如此类…

虽然我不熟悉底层算法的复杂细节,但使用上述规则进行词干提取似乎是实际词干提取的过度简化版本,从计算和语言的角度来看,它将利用更加复杂和深思熟虑的规则。

现在,让我们来看看一些动词:

**normalise_text(['wrote', 'thinking', 'remembered', 'relies', 'ate', 'gone', 'won', 'ran', 'swimming', 'mistreated'], pos='v')**

虽然“思考”和“游泳”在所有三个规格化器中以完全相同的方式规格化,但其他一些动词有不同的输出。例如,你有没有注意到 lemmatiser 如何将不规则动词如“ate”和“gone”进行了合理的转换,而 stemmers 却没有。我认为这是因为为这些少数例外情况定制规则很棘手。我希望到目前为止,这些简短的例子已经让您了解了词干分析器和词汇分析器是如何规范化单词的。

4.速度比较🐎

在研究词干匹配和词干匹配时,我遇到了许多资源,这些资源声称词干匹配比词干匹配更快。然而,当我在我的计算机上对一个样本数据测试三个规格化器时,我观察到完全相反的情况:

**from nltk.corpus import movie_reviews
from nltk.tokenize import RegexpTokenizer# Import data
reviews = []
for fileid in movie_reviews.fileids():
    tag, filename = fileid.split('/')
    reviews.append((tag, movie_reviews.raw(fileid)))
sample = pd.DataFrame(reviews, columns=['target', 'document'])# Prepare one giant string 
sample_string = " ".join(sample['document'].values)# Tokenise data
tokeniser = RegexpTokenizer(r'\w+')
tokens = tokeniser.tokenize(sample_string)%%timeit 
lemmatiser = WordNetLemmatizer()
[lemmatiser.lemmatize(token, 'v') for token in tokens]**

**%%timeit 
porter = PorterStemmer()
[porter.stem(token) for token in tokens]**

**%%timeit 
lancaster = LancasterStemmer()
[lancaster.stem(token) for token in tokens]**

正如你所看到的,从这个快速评估中,lemmatiser 实际上更快,甚至当我们用平均+/- 3 个标准差来比较一个范围时。因此,Lemmatiser 看起来更有利,因为它规范化得更合理,运行速度更快。在下一节中,我将分享两个有效的引理满足技巧作为奖励。

请注意,本帖中没有提到的其他词干分析器和词干分析器可能会给我们一个不同的故事。

5.有效引理满足的两个技巧💡

5.1.词性标签💬

如果您查看规范化示例名词和动词的代码片段,您会注意到两者之间的pos参数有所不同。这个参数指的是一个单词的词性标签,它在单词如何被词汇化的过程中起着重要作用。词性标签向 lemmatiser 提供单词的上下文。让我们看一些例子:

**lemmatiser = WordNetLemmatizer()
print(f"Lemmatising 'remembered' with pos='v' results in: {lemmatiser.lemmatize('remembered', 'v')}")
print(f"Lemmatising 'remembered' with pos='n' results in: {lemmatiser.lemmatize('remembered', 'n')}\n")
print(f"Lemmatising 'universities' with pos='v' results in: {lemmatiser.lemmatize('universities', 'v')}")
print(f"Lemmatising 'universities' with pos='n' results in: {lemmatiser.lemmatize('universities', 'n')}")**

如您所见,为了有效地规范化带有WordNetLemmatizer的单词,为每个单词提供正确的pos参数是很重要的。

5.2.情况🔠 🔡

此外,单词的大小写也很重要:

**print(f"Lemmatising 'Remembered' with pos='v' results in: {lemmatiser.lemmatize('Remembered', 'v')}")
print(f"Lemmatising 'Remembered' with pos='n' results in: {lemmatiser.lemmatize('Remembered', 'n')}\n")
print(f"Lemmatising 'Universities' with pos='v' results in: {lemmatiser.lemmatize('Universities', 'v')}")
print(f"Lemmatising 'Universities' with pos='n' results in: {lemmatiser.lemmatize('Universities', 'n')}")**

大写时,单词即使有正确的pos也保持不变,因为它们被视为专有名词。💭

照片由帕特里克·福尔Unsplash 拍摄

您想访问更多这样的内容吗?媒体会员可以无限制地访问媒体上的任何文章。如果你使用 我的推荐链接成为会员,你的一部分会费会直接去支持我。**

感谢您花时间阅读这篇文章。我希望你学到了一些关于引理满足和词干的知识。读完这篇文章后,如果你再翻一遍定义,你会觉得比第一次读的时候更有意义吗?👀其余帖子的链接整理如下:
◼️ 第一部分:Python 中的文本预处理
◼️ 第二部分:引理和词干化的区别
◼️ 第三部分:TF-IDF 解释
◼️ 第四部分:Python 中的监督文本分类模型
◼️ 第五部分:Python 中的无监督主题模型(sklearn) 【T29

正常化快乐!再见🏃💨

4.参考📁

NLP 介绍-第 3 部分:TF-IDF 讲解

原文:https://towardsdatascience.com/introduction-to-nlp-part-3-tf-idf-explained-cedb1fc1f7dc?source=collection_archive---------30-----------------------

词频-逆文档频率,也称为 tf-idf…💤

你觉得这听起来像胡言乱语吗?但你希望不会?在这篇文章中,我将首先演示如何使用 sklearn 将文本数据矢量化到 tf-idf,然后展示如何在没有任何软件的情况下自己完成的一步一步的过程。希望 tf-idf 在这篇帖子结束后,你会更清楚!🎓

JESHOOTS.COM 在 Unsplash拍照

1。定义📗

首先,让我们熟悉一些定义,以确保我们对每个概念的含义保持一致:

  • tf 和 tf-idf 被分成两个变体:一个基于 count (_raw),另一个基于 percentage 以使事情更清楚。

    • IDF 的一个更通用的定义是一个权重,它提高不太频繁的术语的权重,降低较频繁的术语的权重。然而,我选择了一个简单的定义,因为根据所使用的公式,一个术语的最低权重可以是 1。无论哪种方式,在 tf-idf 中,与 tf 相比,频率较低的术语权重较高,频率较高的术语权重较低。

括号中的例子显示了本文中使用的数据集的参考。

为了便于管理,我们将从这些句子中创建两个小文档,这将允许我们监控每个步骤的输入和输出:

d1 = 'I thought, I thought of thinking of thanking you for the gift'
d2 = 'She was thinking of going to go and get you a GIFT!'

如果你想知道为什么我选择了这两个句子,我必须想出一个最小的例子,在它们被预处理后,转换成我理想的末端向量,然后向后想。一个绕口令派上了用场!

2.带 sklearn 的 TF-IDF💻

本节假设您已经访问并熟悉 Python,包括安装包、定义函数和其他基本任务。如果你是 Python 的新手,这个是一个很好的入门地方。

2.0.Python 设置🔧

我已经使用并测试了 Python 3.7.1 中的脚本。在使用代码之前,让我们确保您有合适的工具。

⬜️确保安装了所需的软件包:熊猫和 nltk

我们将使用以下强大的第三方软件包:

  • 熊猫:数据分析库,
  • nltk: 自然语言工具包库和
  • sklearn: 机器学习库。

⬜️从 nltk 下载“停用词”和“wordnet”语料库

下面的脚本可以帮助你下载这些语料库。如果您已经下载了,运行它会通知您它是最新的:

import nltk
nltk.download('stopwords')
nltk.download('wordnet')

2.1.定义文本处理功能

首先,让我们用包和数据准备环境:

# Import packages and modules
import pandas as pd
from nltk.stem import WordNetLemmatizer
from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords
from sklearn.feature_extraction.text import TfidfVectorizer# Create a dataframe
X_train = pd.DataFrame({'text': [d1, d2]})

从现在开始,我们将把‘X _ train’作为我们的语料库(不管它有多大),把两个句子作为文档。第二,我们需要一个文本处理函数来将它传递给 TfidfVectorizer :

def preprocess_text(text):
    # Tokenise words while ignoring punctuation
    tokeniser = RegexpTokenizer(r'\w+')
    tokens = tokeniser.tokenize(text)

    # Lowercase and lemmatise 
    lemmatiser = WordNetLemmatizer()
    lemmas = [lemmatiser.lemmatize(token.lower(), pos='v') for token in tokens]

    # Remove stopwords
    keywords= [lemma for lemma in lemmas if lemma not in stopwords.words('english')]
    return keywords

🔗如果你需要解释,我已经在系列的第一部分中详细解释了这个功能。这个预处理程序将把文档转换成:

d1 = [‘think’, ‘think’, ‘think’, ‘thank’, ‘gift’]
d2 = [‘think’, ‘go’, ‘go’, ‘get’, ‘gift’]

2.2.使用 TfidfVectorizer 向 tf-idf 矢量化

最后,对语料进行预处理:

# Create an instance of TfidfVectorizer
vectoriser = TfidfVectorizer(analyzer=preprocess_text)# Fit to the data and transform to feature matrix
X_train = vectoriser.fit_transform(X_train['text'])# Convert sparse matrix to dataframe
X_train = pd.DataFrame.sparse.from_spmatrix(X_train)# Save mapping on which index refers to which words
col_map = {v:k for k, v in vectoriser.vocabulary_.items()}# Rename each column using the mapping
for col in X_train.columns:
    X_train.rename(columns={col: col_map[col]}, inplace=True)
X_train

一旦脚本运行,您将得到以下输出:

tf-idf 矩阵

Tada❕我们已经将语料库矢量化到 tf-idf!数据现在是机器学习模型可接受的格式。

让我们看看有或没有看不见的术语的测试文档是如何转换的:

d3 = “He thinks he will go!”
d4 = “They don’t know what to buy!”# Create dataframe
X_test = pd.DataFrame({‘text’: [d3, d4]})# Transform to feature matrix
X_test = vectoriser.transform(X_test['text'])# Convert sparse matrix to dataframe
X_test = pd.DataFrame.sparse.from_spmatrix(X_test)# Add column names to make it more readible
for col in X_test.columns:
    X_test.rename(columns={col: col_map[col]}, inplace=True)
X_test

preprocess_text被应用时,测试文档将转换成:

d3 = [‘think’, 'go'] # *vectoritiser is familiar with these terms*
d4 = [‘know’, ‘buy’] # *vectoritiser is not familiar with these terms*

tf-idf 矩阵

这是您在 X_test 转换时所期望看到的吗?虽然我们在 d3 中出现了一次“go”和“think ”,但你有没有注意到“go”相对于“think”的权重是如何增加的? d4 取全 0 值这个事实对你有意义吗?你是否注意到矩阵中的项数取决于训练数据,就像任何其他的 sklearn 变形金刚一样?

3.TF-IDF -自己动手📝

我认为当我们开始寻找引擎盖下的东西时,事情会变得更有趣。在这一节中,我们将手动进行转换,这不是很有趣吗?😍

如果你喜欢数学,我鼓励你按照这个指南手动计算问题,或者更好的是,在继续下面的答案之前尝试自己计算。在下面的例子中,行代表文档或语料库,列代表术语。

3.1.原始术语频率表

🔒问题:按文档统计每个术语的原始术语频率

💭提示:看预处理后的 d1d2 以及 tf_raw 的定义。

🔑答案:

下表总结了每个术语在文档中出现的次数。例如:我们在文档 1 中看到“think”出现了 3 次,但在文档 2 中只出现了一次。列的数量由语料库中唯一术语的数量决定。这一步其实就是 sklearn 的 count vector ser做的事情。

3.2.术语频率

(此步骤仅用于比较最终输出。)

🔒问题:按文档计算每个词的词频

💭提示:一个术语在文档中占多大比例?(第%行)

🔑答案:

术语“思考”占了文献 1 中 60%的术语。

3.3.文档频率

🔒问题:统计每期的文档频率

💭提示:有多少个文档包含特定的术语?

🔑回答:

术语“get”仅在文档 1 中出现,而术语“think”在两个文档中都出现。

3.4.逆文档频率

这是第一次计算的地方。
➗公式:在该公式中, n 代表文档数。

🔒问题:计算每项的 idf

🔑答:IDF看起来是不是和 df 有点反?

sklearn 中,可以从拟合的tfidf 矢量器中访问 idf_ 属性。

🔍例题计算:下面,我已经提供了一个例题计算。通过复制相同的逻辑,您可以将它作为其余术语的指南:

3.5.原始术语频率与文档频率相反

➗公式:

🔒问题:按文档计算每个术语的 raw tf-idf (即加权计数)。

🔑答案:

🔍示例计算:

3.6.术语频率与文档频率成反比

➗公式:

🔒问题:通过文档计算每项的 tf-idf

🔑答案:

🔍 示例计算:

Yay❕我们已经获得了完全相同的结果!值得注意的是,如果您在中间步骤的任何地方进行了舍入,由于舍入误差,您的最终答案可能与上面提供的答案不完全匹配。

📌 练习:看看能不能计算出 d3d4tf-idf ,并与上一节 sklearn 的输出相匹配。

💭 提示: (1) Count tf_raw - terms 指的是来自训练数据的术语,(2)使用我们构建的 idf 计算 tf-idf_raw,(3)计算 tf-idf。仅对培训中的术语执行这些步骤。

sklearn 中的tfidf vectorTfidfTransformersmooth_idf=True 时,该方法复制输出。如果您将该参数更改为 False ,您将不得不通过从分子和分母中取出+1 来稍微调整 idf 公式。

在我们总结之前,让我们比较一下文档 1 的 tftf-idf :

因为“gift”和“think”出现在所有文档中,所以它们在两个表中的相对权重是相同的。然而,“感谢”只出现在文档 1 中,因此与“礼物”或“思考”相比,它在 tf-idf 中的相对频率更高。因此,这展示了 tf-idf 如何提高较少文档中的术语的权重,降低较多文档中的术语的权重。

📌 练习:自己分析文献 2。

显然,手动计算更容易出错,并且不太可能适用于具有数百、数千甚至数百万文档的真实语料库。非常感谢 sklearn 贡献者提供了这样一种有效的方式,用短短几行代码将文本转换成 tf-idf 。此处显示的手动计算仅用于举例说明使用软件时的底层实现。如果您想自己从工具而不是从 sklearn 复制输出,可能需要对公式进行调整,但总体思路应该是相似的。我希望这些解释是有用和有见地的。

Leone VenterUnsplash 上拍照

您想要访问更多这样的内容吗?媒体会员可以无限制地访问媒体上的任何文章。如果您使用 我的推荐链接成为会员,您的一部分会费将直接用于支持我。

感谢您花时间阅读这篇文章。我希望你从阅读它中学到一些东西。其余帖子的链接整理如下:
◼️ 第一部分:Python 中的文本预处理
◼️ 第二部分:词法分析和词干分析的区别
◼️ 第三部分:TF-IDF 解释
◼️ 第四部分:Python 中的有监督文本分类模型
◼️ 第五部分:Python 中的无监督主题模型(sklearn)
◼️ 第五部分

快乐变身!再见🏃💨

4.参考📁

自然语言处理导论第 4 部分:Python 中的监督文本分类模型

原文:https://towardsdatascience.com/introduction-to-nlp-part-4-supervised-text-classification-model-in-python-96e9709b4267?source=collection_archive---------23-----------------------

这篇文章将向你展示一个构建基本的监督文本分类模型的简化例子。如果这听起来有点胡言乱语,让我们看看一些定义:

💡监督: 我们知道样本数据中每个文本的正确输出类 💡 文本: 输入的数据是以文本格式 💡分类模型: 使用输入数据预测输出类的模型
每个输入文本也称为“文档”,输出也称为“目标”(术语,不是商店!😄).

监督文本分类模型现在听起来更有意义吗?也许吧?在有监督的文本分类模型中,我们将在这篇文章中关注一种特殊的类型。在这里,我们将建立一个受监督的情感分类器,因为我们将在具有二元目标的电影评论上使用情感极性数据。

照片由 Clément HUnsplash 上拍摄

0.Python 设置🔧

本文假设您已经访问并熟悉 Python,包括安装包、定义函数和其他基本任务。如果你是 Python 新手,这个是入门的好地方。

我已经使用并测试了 Python 3.7.1 中的脚本。在我们开始之前,让我们确保你有合适的工具。

⬜️确保安装了所需的软件包:熊猫,nltk & sklearn

我们将使用以下强大的第三方软件包:

  • 熊猫:数据分析库,
  • nltk: 自然语言工具包库和
  • sklearn: 机器学习库。

⬜️从 nltk 下载“停用词”、“wordnet”和电影评论语料库

下面的脚本可以帮助你下载这些语料库。如果您已经下载了,运行此程序将通知您它们是最新的:

import nltk
nltk.download('stopwords') 
nltk.download('wordnet')
nltk.download('movie_reviews')

1.数据准备🔡 ➡ 🔢

1.1.导入示例数据和包

首先,让我们通过导入所需的包来准备环境:

import pandas as pdfrom nltk.corpus import movie_reviews, stopwords
from nltk.stem import WordNetLemmatizer
from nltk.tokenize import RegexpTokenizerfrom sklearn.model_selection import train_test_split, cross_val_score, cross_val_predict, GridSearchCV
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import SGDClassifier
from sklearn.pipeline import Pipeline
from sklearn.metrics import confusion_matrix, accuracy_score

我们将把 movie_reviews 标记的语料库从 nltk 转换成熊猫数据帧,脚本如下:

# Script copied from [her](# https://stackoverflow.com/questions/46109166/converting-categorizedplaintextcorpusreader-into-dataframe)e
reviews = []
for fileid in movie_reviews.fileids():
    tag, filename = fileid.split('/')
    reviews.append((tag, movie_reviews.raw(fileid)))
sample = pd.DataFrame(reviews, columns=['target', 'document'])
print(f'Dimensions: {sample.shape}')
sample.head()

您将看到数据框架有两列:一列用于目标、极性情绪,另一列用于 2000 条评论的评论(即文档)。每个评论要么被标记为正面评论,要么被标记为负面评论。让我们检查目标类的数量:

sample[‘target’].value_counts()

每个类(即‘pos’,‘neg’)各有 1000 条记录,完全平衡。让我们确保这些类是二进制编码的:

sample['target'] = np.where(sample['target']=='pos', 1, 0)
sample['target'].value_counts()

这看起来不错,让我们继续划分数据。

1.2.分区数据

谈到数据分区,我们有两种选择:

  1. 将样本数据分成三组:训练验证测试、,其中训练用于拟合模型,验证用于评估过渡模型的适合度,测试用于评估最终模型的适合度。
  2. 将样本数据分成两组:训练测试其中训练进一步分成训练和验证集 k 次使用 k 倍交叉验证,测试用于评估最终模型的适合度。用 k 重交叉验证:
    :第一个 : 被拆分成 k 块。
    第二:将模型拟合到剩余的 k-1 件后,取一件作为验证集,评估中间模型的适合度。
    第三:重复第二步 k-1 多次,每次使用不同的件用于验证组,剩余的件用于序列组,这样序列的每件仅用作验证组一次。

这里的中间模型指的是在比较不同机器学习分类器以及为给定分类器尝试不同超参数以找到最佳模型的迭代过程中创建的模型。

我们将使用第二个选项对样本数据进行分区。让我们先把一些测试数据放在一边,这样我们就可以检查最终模型对未知数据的概括程度。

X_train, X_test, y_train, y_test = train_test_split(sample['document'], sample['target'], test_size=0.3, random_state=123)print(f'Train dimensions: {X_train.shape, y_train.shape}')
print(f'Test dimensions: {X_test.shape, y_test.shape}')# Check out target distribution
print(y_train.value_counts())
print(y_test.value_counts())

我们有 1400 个文档在训练中,600 个文档在测试数据集中。目标均匀地分布在训练和测试数据集中。

如果你对关于数据分区的这一节有点困惑,你可能想要查看这篇很棒的文章来了解更多。

1.2.预处理文档

是时候对训练文档进行预处理了,也就是把非结构化的数据转换成数字的矩阵。让我们使用一种称为单词包的方法对文本进行预处理,其中每个文本都由它的单词表示,而不管它们出现的顺序或嵌入的语法,步骤如下:

  1. 象征化
  2. 正常化
  3. 删除停用词
  4. 计数矢量
  5. 转换到 tf-idf 表示

🔗我已经在系列文章的第一部分中提供了预处理步骤的详细解释,包括下面代码块的分解。

这些连续的步骤是通过下面的代码块完成的:

def preprocess_text(text):
    # Tokenise words while ignoring punctuation
    tokeniser = RegexpTokenizer(r'\w+')
    tokens = tokeniser.tokenize(text)

    # Lowercase and lemmatise 
    lemmatiser = WordNetLemmatizer()
    lemmas = [lemmatiser.lemmatize(token.lower(), pos='v') for token in tokens]

    # Remove stop words
    keywords= [lemma for lemma in lemmas if lemma not in stopwords.words('english')]
    return keywords# Create an instance of TfidfVectorizer
vectoriser = TfidfVectorizer(analyzer=preprocess_text)# Fit to the data and transform to feature matrix
X_train_tfidf = vectoriser.fit_transform(X_train)
X_train_tfidf.shape

🔗如果你不确定什么是 tf-idf,我已经在系列第三部中提供了详细的解释。

一旦我们预处理了文本,我们的训练数据现在是以稀疏矩阵格式存储的 1400 x 27676 特征矩阵。这种格式提供了有效的数据存储,并加快了后续过程。我们有 27676 个特征代表来自训练数据集中的唯一单词。现在,训练数据已经准备好进行建模了!

2.模拟ⓜ️

2.1.基线模型

让我们使用随机梯度下降分类器建立一个基线模型。我选择了这个分类器,因为它速度快,并且适用于稀疏矩阵。使用 5 重交叉验证,让我们将模型与数据进行拟合并对其进行评估:

sgd_clf = SGDClassifier(random_state=123)
sgf_clf_scores = cross_val_score(sgd_clf, X_train_tfidf, y_train, cv=5)print(sgf_clf_scores)
print("Accuracy: %0.2f (+/- %0.2f)" % (sgf_clf_scores.mean(), sgf_clf_scores.std() * 2))

假设数据是完全平衡的,我们希望尽可能正确地预测两个标签,我们将使用准确性作为评估模型适合度的度量。然而,根据目标的分布和类的相对误分类成本,精度并不总是最佳的度量。在这种情况下,其他评估指标如精确度、召回率或 f1 可能更合适。

最初的表现看起来还不错。基线模型可以在大约 83% +/- 3%的时间内准确预测。

值得注意的是,使用的默认指标是cross_val_score 中的准确度,因此我们不需要指定它,除非您想明确地这样说,如下所示:

cross_val_score(sgd_clf, X_train_tfidf, y_train, cv=5, scoring='accuracy')

让我们通过查看混淆矩阵来进一步理解这些预测:

sgf_clf_pred = cross_val_predict(sgd_clf, X_train_tfidf, y_train, cv=5)
print(confusion_matrix(y_train, sgf_clf_pred))

这两类预测的准确性是相似的。

2.2.尝试提高性能

本节的目的是找到最佳的机器学习算法及其超参数。让我们看看我们是否能够通过调整一些超参数来改进模型。我们将把大多数超参数保留为其合理的默认值。在网格搜索的帮助下,我们将使用下面指定的超参数的每种组合运行一个模型,并交叉验证结果,以感受其准确性:

grid = {'fit_intercept': [True,False],
        'early_stopping': [True, False],
        'loss' : ['hinge', 'log', 'squared_hinge'],
        'penalty' : ['l2', 'l1', 'none']}
search = GridSearchCV(estimator=sgd_clf, param_grid=grid, cv=5)
search.fit(X_train_tfidf, y_train)
search.best_params_

这些是上面指定的超参数的最佳值。让我们使用所选超参数的这些值来训练和验证模型:

grid_sgd_clf_scores = cross_val_score(search.best_estimator_, X_train_tfidf, y_train, cv=5)
print(grid_sgd_clf_scores)
print("Accuracy: %0.2f (+/- %0.2f)" % (grid_sgd_clf_scores.mean(), grid_sgd_clf_scores.std() * 2))

与基线相比,模型拟合度稍好(小 yay❕).

为了节省时间,我们将为最终模型选择这些超参数组合,这一部分到此为止。然而,本节可以进一步扩展,尝试不同的建模技术,并使用网格搜索找到模型超参数的最佳值。

📌练习:看看是否可以通过使用不同的建模技术和/或优化超参数来进一步提高该模型的准确性。

2.3.最终模型

现在我们已经完成了模型,让我们将数据转换步骤和模型放入管道:

pipe = Pipeline([('vectoriser', vectoriser),
                 ('classifier', search.best_estimator_)])pipe.fit(X_train, y_train)

在上面显示的代码中,管道首先将非结构化数据转换为特征矩阵,然后将预处理后的数据拟合到模型中。这是一种将基本步骤放在一个管道中的优雅方式。

让我们在测试集上评估模型的预测能力。这里,我们将把测试数据传递给管道,管道将首先预处理数据,然后使用之前拟合的模型进行预测:

y_test_pred = pipe.predict(X_test)
print("Accuracy: %0.2f" % (accuracy_score(y_test, y_test_pred)))
print(confusion_matrix(y_test, y_test_pred))

最终模型对未知数据的精确度约为 85%。如果这个测试数据代表了未来的数据,那么考虑到我们到目前为止所付出的努力,这个模型的预测能力是相当不错的,你不这样认为吗?不管怎样,恭喜你!您刚刚构建了一个简单的监督文本分类模型!🎓

摄蜻蜓大街的 Unsplash

您想访问更多这样的内容吗?媒体会员可以无限制地访问媒体上的任何文章。如果您使用 我的推荐链接成为会员,您的一部分会费将直接用于支持我。

感谢您花时间阅读这篇文章。我希望你从阅读它中学到一些东西。其余帖子的链接整理如下:
◼️ 第一部分:Python 中的文本预处理
◼️ 第二部分:词法分析和词干分析的区别
◼️ 第三部分:TF-IDF 解释
◼️ 第四部分:Python 中的有监督文本分类模型 ◼️ 第五部分:Python 中的无监督主题模型(sklearn)
◼️ 第五部分

快乐造型!再见🏃💨

3.参考📁

对象检测简介

原文:https://towardsdatascience.com/introduction-to-object-detection-943f21e26063?source=collection_archive---------38-----------------------

从图像分类到目标检测

入门指南

基本的图像分类模型相对简单。给定一幅图像作为输入,目标是将它归类为许多可能的输出类别之一。该架构通常(但不一定)是一系列卷积层和汇集层,其末端是一个或多个线性层,最终输出层具有与类数量相同的节点/神经元数量。输出层中的每个节点代表一个类,并且将为该最终层训练模型,以给出给定输入图像属于相应类的概率。

说明性图像分类

上图是一个多类影像分类示例,其中输出相互排斥,即所有输出概率总和为 1。另一种变化是多标签分类,其中每个概率都相互独立,一个图像可以被标记为多个类别,就像将类型与电影海报相关联一样。

目标

虽然这种图像分类能力具有许多应用,但是大多数真实世界的应用需要的不仅仅是单个图像的这种分类。如果您将自动驾驶汽车视为一个例子(注意:真正的自动驾驶解决方案可能更复杂,但出于说明目的,请使用这个例子),它要求我们:

  1. 确定所识别的物体在图像中的位置。例如:如果识别的行人在正前方或旁边
  2. 识别多个对象。例如:一个单一的图像可以有多辆汽车,许多行人,交通灯等
  3. 识别对象的方向。例如:汽车的前部面向,后部背向(例如,汽车向我们驶来或面向我们停放)

完成所有这些需要做的比图像分类模型多一点。在本帖中,我们将着眼于实现前两个目标。

思维练习

那么,除了分类之外,我们如何确定由边界框坐标定义的对象的位置呢?当存在多个物体时,我们如何确定它们?

我们想要确定位置的方法是通过识别对象的边界框的坐标。我们的目标是获得边界框的坐标,通常是通过识别角或中心的坐标以及边界框的高度和宽度。

附注:另一种方法是获取已识别对象实例的掩码。对于已识别的对象,遮罩为我们提供了作为已识别实例一部分的所有像素。图 1 示出了这两种输出选项(为了便于理解,使用了多对象检测图示)。虚线表示边界框输出,而彩色对象表示我们希望在给定输入图像的情况下得到的遮罩输出。

图 1 :使用包围盒的对象检测与使用遮罩的实例分割

让我们做一个简单的思考练习,从几个约束开始,这将简化思考,稍后再回来移除它们。第一,假设所有的物体都是固定的宽度和高度(比如 20px * 20px)。第二,让我们假设这些对象从 0 或者 20 的倍数开始。即它们的左上坐标将是 0 或 20 的倍数(即左上坐标将是 0,0 或 0,20 或 20,40 或 40,40 等)。

有了这两个约束,确定对象精确位置的一种方法是在图像上想象一个网格,每个单元的大小为 20*20。现在,我们要做的就是像图像分类一样,对网格中的每个单元评估分类概率。所有类别概率高于阈值的单元格都是对象所在的位置!

现在,当我们去除预先确定的尺寸和位置的两个约束时,很明显,我们必须有一个网格系统来帮助我们确定各种尺寸、长宽比和位置的盒子。这些箱子有时被称为锚箱。有不同的方法来解决产生不同大小/位置的锚盒的问题,我们将看看一些众所周知的方法。

同样重要的是要注意,在这个简单的思考练习中,我们直接在图像上想象网格系统和锚定框,但从技术上讲,我们将在表示图像的特征图上这样做,就像图像通过的基本网络的最后一层。

图 2 :检测包围盒需要评估不同大小、长宽比和位置的盒子

YOLO

例如,Yolo ( paper link )将输入图像分成一个 S × S 的网格。正如我们上面所做的,每个网格单元不仅被评估类别概率,而且一组“B”边界框和这些框的置信度分数也被一起预测。

换句话说,盒子不是像我们简单的思考练习中那样预先确定的,而是随着单元的类别概率一起预测的。每个边界框由 5 个预测组成:x,y,w,h 和置信度。前四个与坐标有关,最后一个,置信度反映了模型对盒子包含对象的置信度以及盒子坐标的精确度。

此外,确定对象的框坐标的责任属于对象中心所在的网格单元。这有助于防止多个单元格确定同一对象周围的框。但是每个单元仍然预测多个边界框。这些框中的一个被认为“负责”预测对象,基于该预测,在训练期间,哪个预测具有最高的当前值 IOU 。在训练过程中,这导致每个单元中不同的边界框专门用于预测物体的特定大小、长宽比或类别,从而提高整体回忆。

这些预测被编码为 S × S×(B∫5+C)张量(S×S 是网格维度,B 是网格中每个单元将确定的框,5 是每个框做出的预测,即 x、y、w、h 和置信度,C 是模型可以识别的 C 类对象的概率)。

图 3 : Yolo 插图,此处摘自原图的第二部分。左边是生成两个边界框和 7 个类别概率的 4 x 4 网格的图示。

(同 solid-statedisk)固态(磁)盘

单次多盒检测器(SSD) ( 纸链接)不会凭空预测盒子,而是从一组默认盒子开始。它使用几个不同比例的特征地图(即几个不同大小的网格,如图 4 中的所示的 4 x 4、8 x 8 等)以及每个网格/特征地图中每个单元不同纵横比的一组固定默认框。对于每个默认框,该模型随后计算“偏移量”以及类别概率。偏移量由 4 个数字 cx、cy、w 和 h 组成,给出了实际框相对于默认框的中心坐标、宽度和高度的偏移量。

SSD 在将对象基础事实框与默认框相匹配的策略上也有所不同。没有一个单独的默认框负责并匹配一个对象。相反,默认框与任何高于阈值(0.5)的 IOU匹配。这意味着,对于与对象重叠的多个默认框,将会预测到高分,而不是只要求其中一个框负责。

图 4 : SSD 框架来自原文此处。说明了多个(两个)匹配猫的蓝框和一个匹配狗的红框。匹配框也来自不同的特征地图,即网格大小。

更快的 RCNN

与 Yolo 和 SSD 不同,更快的 RCNN ( paper link )及其前身采用了两步方法。快速 RCNN 部署一个单独的区域建议网络,专门用于首先确定锚盒。接下来是一个快速的 R-CNN 检测器,它使用了提出的区域。

在区域建议网络(RPN)中,在基本网络的输出上应用小滑动窗口(卷积)。如果基础网络的输出是 n*m 个通道,则 nm 就相当于我们的网格,对 n * m 个特征图中的每个位置(即细胞)进行评估。根据不同尺寸和长宽比的“k”个锚箱对每个位置进行评估。对于每个锚盒,确定 2 个类别预测和 4 个盒坐标。这两类预测表明盒子中的对象是背景还是前景(即有或没有对象)。4 个框坐标是典型的中心 x、y 以及宽度和高度。对于训练 rpn,我们给每个锚点分配一个二进制类标签(是否为对象)。保留具有最高 IOU 的锚和具有高于 0.7 的 IOU 重叠的锚。

特征图中落在方框内的部分是感兴趣区域,在 ROI 汇集层之后,这些感兴趣区域被提供给分类器。

图 5 :此处原纸更快的 RCNN。左侧是完整网络的示意图,包括区域提案网络。右边是如何使用锚定框的滑动窗口到达区域提议(框提议)的图示。

应用

我们已经研究了这些流行的模型是如何解决目标检测问题的。对于每一个模型,都有一些我们在这里没有涉及到的细微差别,但是希望这篇文章仍然给出了一个关于这个问题是如何解决的一般概念。虽然知道这很好,但如果你更倾向于在应用程序中使用对象检测,那么检查一些可用的选项: torchvision 模型Tensorflow 对象检测 API 和 py torch poweredDetectron 2

介绍构建机器学习系统中的数据失配、过拟合和欠拟合

原文:https://towardsdatascience.com/introduction-to-overfitting-underfitting-and-data-mismatch-in-building-machine-learning-systems-52f1225a8a35?source=collection_archive---------28-----------------------

https://unsplash.com/@ikukevk 凯文·Ku 的照片

在文章“最重要的机器学习方法的初级读本”中,我概述了该领域常用的不同机器学习方法。这里考虑三个主要方面:

  • 人工监督:详细阐述了监督、非监督、半监督和强化学习是如何工作的,特别是在预定义结果的形状方面。
  • 在线学习与批量学习:讨论增量学习“即时”和基于静态数据集训练模型之间的区别。
  • 基于实例的学习与基于模型的学习:强调了阐明与先前值的显式比较与开发模型用于概括的逻辑的学习方法的差异。

当构建机器学习系统时,需要执行几个步骤来产生一个健壮的解决方案,该解决方案不仅可以做出准确的预测,还可以对潜在的问题给出正确的答案。一个典型的机器学习工作流程包含以下步骤:

  • 问题定义
  • 数据收集
  • 探索性数据分析
  • 特征工程
  • 训练/测试分割
  • 模型选择和培训
  • 交互效度分析
  • 模型精度评估
  • 超参数调整/模型改进
  • 模型部署
  • 模型再训练

这种工作流程会带来一些挑战。特别是在从 EDA模型改进的步骤中,需要回答一些关键问题:

  • 数据是否足够?
  • 模型需要多少数据?
  • 数据代表真实世界吗?
  • 哪些功能适合?
  • 数据记录是否完整?
  • 哪种机器学习方法合适?
  • 模型应该有多复杂?
  • 这个模型能做出准确的预测吗?

针对这些问题,主要任务是数据的选择和增强以及模型的选择、训练和改进。这些挑战可以分为两组:与数据相关的挑战和与模型相关的挑战。

虽然这两组之间存在依赖关系,但本文讨论了主要的数据和模型挑战,并解释了如何识别和解决它们,最终目标是提高机器学习系统的性能。

1)数据挑战

数据科学家花费 80%的工作来寻找、清理和组织数据,这表明输入数据对于机器学习模型产生有意义的结果是多么重要。

数据量

与人类学习程序相比,人类学习程序通常在很少的训练样本下就能很好地工作,当前的机器学习算法需要大量数据才能很好地执行。一般规则是“问题和应用的方法越复杂,就需要越多的数据作为训练的输入”。当机器学习系统缺乏大量数据时,过度拟合可能会发生(在模型挑战下解释),因为算法会拾取模式,而这些模式实际上只不过是噪声。由于缺乏数据,真实的模式可能无法被发现。

代表数据

与训练数据相关的一个关键方面是,它需要代表生产数据,即在部署机器学习解决方案的真实世界应用中出现的数据。如果生产数据完全不同,结果很可能是无用的。这适用于基本上所有类型的模型,无论它们是基于监督的还是非监督的学习、批量或在线学习以及基于实例或模型的学习。

在实践中,收集代表真实世界的数据集是一项挑战。像采样噪声(=数据中的随机性)这样的问题会有很大的影响,尤其是对纯粹随机形成的、不具有代表性的小样本而言。如果数据收集很容易,并且训练数据集足够大,那么采样偏差仍然可能发生。这是由于使用不准确的采样方法造成的。

数据质量

“垃圾输入-垃圾输出”是一个经常使用的谚语,但对于机器学习解决方案的数据质量来说仍然是正确的。当在真实世界的产品和服务的上下文中操作训练数据时,训练数据的质量会极大地影响模型结果的质量。经过大量修改的艰苦工作产生了高质量的数据:

  • 误差校正:通过对数据采集过程的充分了解,可以理解并手动修复误差。
  • 异常值去除:可以从数据集中去除严重偏离的值,即由于不良数据采集方法导致的值。
  • 噪声平衡:可以添加更多的数据来考虑噪声并使其变得不相关。
  • 缺失数据插补:不完整的数据记录可以通过填充剩余系列值的中间值进行插补,或者在时间序列分析中,填充周围值的平均值。

如果数据无法修复,则应完全删除数据记录或要素以保护模型的准确性,因为缺失值通常会产生不利影响。如果模型加载了低质量的训练数据,那么它几乎不可能在检测目标模式方面表现良好。

相关特征

对相关特征的分析超越了数据的原始形态,更多的是深入其含义。这是在机器学习工作流程的特征工程阶段解决的。

为了实现对特定机器学习问题的最佳可能预测,模型必须在最相关的特征上进行训练。应该排除不相关的特征,因为它们无助于做出准确的预测,而是扭曲了过程。

作为特征工程的一部分,两个主要步骤有助于构建适当的特征集合:

  • 特征选择:分析特征并选择最有用的特征以进行准确预测,即通过查看相关矩阵。
  • 特征提取:揭示特征之间的相互关系,并通过组合或增强现有特征来开发新特征(即在降维过程中使用)。

机器可读性

除了上述挑战,数据的机器可读性也是最大化机器学习模型准确性的关键。对于不同的特征数据类型,包括数字、分类和序号、日期和时间以及文本和图像数据,机器可读性有特定的标准。随着在机器学习流水线中的特征工程步骤期间执行特征预处理,数据格式被调整以确保机器可读性。

一些特征预处理方法是特定于数据类型的,一些是独立的。以下列表概述了需要熟悉的重要方法:

  • 特征缩放或标准化:重新缩放(如最小-最大缩放)在最小值为 0、最大值为 1 的范围内分配数值。标准化(例如 Z 值标准化)会围绕平均值 0 和方差 1 重新排列要素的值。特征缩放主要针对非树模型优化结果。
  • 异常值剔除:尽管异常值剔除是在数据质量下讨论的错误数据采集的结果,但在本节中也被视为机器可读性的一种改进措施。离群值会大大降低机器学习模型准确处理其余数据的能力。
  • 等级转换/整数编码:通过等级转换,一系列有序数据点内的分类值可以转换为具有机器可读整数数据类型的数值等级。
  • Log 变换: Log 变换用于提高机器学习模型对高度可变数据的性能。取每个数据值的对数,使分布更接近钟形,并消除偏斜。如果分布大致呈对数正态分布,则可以应用对数变换。
  • One-hot-encoding: 为分类特征的每个出现值创建一个新变量,该变量可以取值 0 和 1。当一个特征是分类的和整数的,但同时值没有被排序时,一次热编码用于避免较差的性能或意外的结果。

2)模型挑战

机器学习模型必须经过测试和优化,以确保其产生的预测质量良好。投入生产的不成熟的模型可能会导致结果不充分以及产品或服务的用户不满意。

提高模型质量的一种方法是将数据分成不同的子组,以基于每个步骤中使用的不同数据来构建测试管道。常见的方法是将用于模型开发的数据分为训练集和测试集。典型的比例是 80/20,80%是训练集,20%是测试集。分割取决于总数据集的大小。当数据集非常大时,将测试集份额降低到 20%以下就足够了。包含生产数据后,分割过程产生三个数据集:

  • 培训用数据
  • 测试数据
  • 生产数据

一旦模型建立在训练集上,就可以测量训练误差,这是模型在训练集本身上达到的精度——这也称为偏差。当模型在训练数据上表现不佳时,这通常是由拟合不足引起的。在这种情况下,模型的复杂性太低,以至于无法捕获手边数据集中的逻辑。

当模型在初始训练后应用于测试数据时,可以评估泛化误差(=模型未见过的新案例的误差率)。这是通过将测试集的模型预测与测试集的预测标签的真实值进行比较来执行的。当模型在训练数据上表现良好但在测试数据上表现不佳时,这可以被描述为方差,并且通常是由过度拟合引起的。

第三种模式,即数据不匹配,已经在数据挑战部分中定义,这通常是将测试模型应用于现实世界中的生产数据时出现错误的原因。

过拟合

过度拟合是高泛化误差的常见原因。这意味着模型在训练数据中有过度解释的模式,并且调整得太好。

由于数据经常是基于大量的机会和噪声收集的,所以模型不适合收集每一个小模式。当这样做时,它无法区分哪部分数据是要检测的真实模式的一部分,哪部分只是噪声。过度拟合通常发生在模型太复杂、数据集太嘈杂或太小的时候。可以通过以下措施解决:

降低机器学习模型的复杂度

  • 通过选择更简单的模型类型(=低次多项式模型代替复杂的深度神经网络)或不同的模型架构(即其他神经网络类型)
  • 通过减少模型的参数(低次多项式或线性模型代替高次多项式模型)
  • 通过应用 L2 或 L1 正则化或剔除来约束模型
  • 通过将提前停止添加到模型中,以便在目标错误率(即从生产目标/KPI 中扣除的比率)时停止学习

改变/微调输入模型的数据

  • 通过减少特征数量或选择更多相关特征进行训练
  • 通过简单地收集更多的数据,只要它是可用的并且计算能力不是问题
  • 通过降低噪声(=修复/平衡误差并消除异常值)

欠配合

拟合不足指的是模型对于它所训练的数据集来说过于简单,因此产生的结果很差。可以解决的杠杆类似于过度装配,但通常是以相反的方式拉动。

增加机器学习模型的复杂度

  • 通过选择更复杂的模型类型(=多项式模型而不是线性模型,一个神经网络有更多的层/神经元)或不同的模型架构(例如其他 ANN 类型)
  • 通过减少先前可能已经应用的约束(例如,L2 和 L1 正则化、丢弃)

改变/微调输入模型的数据

  • 通过选择基于误差分析更相关的特征
  • 通过增加特征使其基于特征工程方法更加相关(即特征也可以被规则化)

总结

在机器学习工作流中,采取几个步骤来训练由学习算法驱动的模型,以最终对未来做出预测。这包括从问题陈述和数据收集到最终的模型建立和改进的步骤。作为最终产品,该模型应该能够推广到新的情况,并在实际应用程序的生产环境中做出有益的预测。

机器学习模型的结果受许多因素的影响。两个主要群体是数据和模型挑战。在数据挑战的背景下,需要关注的关键问题是:

  • 数据量
  • 典型资料
  • 数据质量
  • 特征相关性
  • 机器可读性

车型制造流程相关的两个关键挑战是:

  • 过度拟合
  • 欠拟合

虽然这些因素经常被认为是重要的,但这个列表并不详尽,除了本文之外,还应该考虑其他途径。《Scikit-Learn、Keras 和 TensorFlow 的机器学习实践:构建智能系统的概念、工具和技术》一书是一个很好的来源,该书对讨论的内容和实践练习提供了更多的深度。

熊猫应用简介,应用地图和地图

原文:https://towardsdatascience.com/introduction-to-pandas-apply-applymap-and-map-5d3e044e93ff?source=collection_archive---------1-----------------------

一个直观的熊猫教程,教你如何使用apply()applymap()应用一个函数,以及如何使用map()替换值

熊猫应用()应用地图()和地图()介绍

在数据处理中,经常需要对某一行或某一列执行操作(如统计计算、拆分或代入值)以获得新的数据。编写一个 for 循环来遍历 Pandas DataFrame 和 Series 可以完成这项工作,但这似乎不是一个好主意。for 循环往往有更多的代码行,更少的代码可读性和更慢的性能。

幸运的是,熊猫已经内置了很好的方法来帮助你完成目标!在本文中,我们将看到如何使用apply()applymap()执行操作,以及如何使用map()替换值。

首先,你应该知道 DataFrame 和 Series 会有这三种方法中的一些或全部,如下:

而熊猫官方 API 参考建议:

  • [**apply()**](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html)用于沿数据帧或的轴对系列的值应用函数
  • [**applymap()**](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.applymap.html)用于将函数应用于数据帧的元素。
  • [**map()**](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.map.html?highlight=map#pandas.Series.map)用于将序列中的每个值替换为另一个值。

用于演示的数据集

在我们深入细节之前,让我们首先创建一个数据框架进行演示。

import pandas as pddf = pd.DataFrame(**{ 'A': [1,2,3,4], 
                   'B': [10,20,30,40],
                   'C': [20,40,60,80]
                  }**, 
                  index=[**'Row 1', 'Row 2', 'Row 3', 'Row 4'**])

应用数据集、应用地图和地图演示

如何使用 apply()?

Pandas apply()用于沿数据帧或的轴对序列的值应用函数

让我们从一个简单的例子开始,对每一行求和并将结果保存到新的列“D”

# Let's call this "custom_sum" as "sum" is a built-in function
def **custom_sum**(row):
    return row.sum()df[**'D'**] = df.apply(**custom_sum**, **axis=1**)

这是输出

df 的结果[' D ']= df . apply(custom _ sumaxis=1 )

你真的明白刚才发生了什么吗?

让我们来看看df.apply(**custom_sum**, **axis=1**)

  • 第一个参数**custom_sum**是一个函数。
  • 第二个参数axis是指定函数应用于哪个轴。0用于将函数应用于每一列,而1用于将函数应用于每一行。

让我用更直观的方式来解释这个过程。第二个参数axis = 1告诉熊猫使用行。因此,custom_sum应用于每一行,并返回一个新的序列,每一行的输出作为值。

有了对每行总和的理解,每列总和就正好用axis = 0来代替

df.**loc['Row 5']** = df.apply(custom_sum, **axis=0**)

到目前为止,我们一直在谈论数据帧上的apply()。同样,apply()可以用在数值序列上。例如,将列“C”乘以 2,并将结果保存到新列“D”

def multiply_by_2(val):
    return val * 2df[**'D'**] = **df['C']**.apply(**multiply_by_2**)

注意df[‘C’]用于选择列“C ”,然后用唯一的参数multiply_by_2调用apply()。我们不再需要指定轴,因为 Series 是一个一维数组。返回值是一个序列,并由df[**‘D’**]分配给新的列 D。

序列上 apply()的输出

将 lambda 与 apply 一起使用

您也可以将 lambda 表达式与 Pandas apply()函数一起使用。

数据帧每行总和的λ当量:

df['D'] = df.apply(**lambda x:x.sum()**, axis=1)

数据帧每列总和的λ当量:

df.loc['Row 5'] = df.apply(**lambda x:x.sum()**, axis=0)

以及在一系列上乘以 2 的λ当量:

df['D'] = df['C'].apply(**lambda x:x*2**)

带有结果类型参数

result_typeapply()中的一个参数,设置为'expand''reduce''broadcast'以获得所需类型的结果。

在上面的场景中,如果result_type被设置为'broadcast',那么输出将是由custom_sum值替代的数据帧。

df.apply(custom_sum, axis=1, **result_type='broadcast'**)

结果被广播到帧的原始形状,原始索引和列被保留。

为了将result_type理解为'expand''reduce',我们将首先创建一个返回列表的函数。

def cal_multi_col(row):
    return **[row['A'] * 2, row['B'] * 3]**

现在将此函数应用于数据帧列,将result_type作为'expand'

df.apply(**cal_multi_col**, axis=1, **result_type='expand'**)

输出是列名为 01 的新数据帧。

为了将它添加到现有的数据帧中,结果必须保存在一个变量中,这样列名就可以被res.columns访问。

**res** = df.apply(cal_multi_col, axis=1, result_type='expand')
df[**res.columns**] = **res**

输出是:

result_type='expand '的输出

接下来,用result_type作为'reduce'在 DataFrame 列中应用该函数。result_type='reduce''expand'正好相反,如果可能的话返回一个序列,而不是展开列表式的结果。

df[**'New'**] = df.apply(cal_multi_col, axis=1, **result_type='reduce'**)

result_type='reduce '的输出

如何使用 applymap()?

applymap()仅在数据帧中可用,用于整个数据帧中的元素操作。它已经过优化,在某些情况下比apply()快得多,但在进行任何更繁重的操作之前,最好将其与apply()进行比较。

例如:输出数字平方的数据帧

df.applymap(np.square)

如何使用 map()?

map()仅在序列中可用,用于将序列中的每个值替换为另一个值。为了理解map()是如何工作的,我们首先创建一个系列。

**>>>** s = pd.Series(['cat', 'dog', np.nan, 'rabbit'])
**>>>** s
0      cat
1      dog
2      NaN
3   rabbit
dtype: object

map()接受一个dict或一个Series。在dict中找不到的值被转换成NaN,除非dict有默认值(如defaultdict):

**>>>** s.map(**{'cat': 'kitten', 'dog': 'puppy'}**)
0   **kitten**
1    **puppy**
2      NaN
3      **NaN**
dtype: object

它还接受一个函数:

**>>>** s.map('I am a *{}*'.format)
0       I am a cat
1       I am a dog
2       I am a nan
3    I am a rabbit
dtype: object

为避免将该函数应用于缺失值(并将其保持为NaN),可使用na_action='ignore':

**>>>** s.map('I am a *{}*'.format, na_action='ignore')
0     I am a cat
1     I am a dog
2            NaN
3  I am a rabbit
dtype: object

摘要

最后,这里总结一下:

对于数据帧:

  • apply():当您想要沿行或列应用一个函数时使用。axis = 0用于列,axis = 1用于行。
  • applymap():用于整个数据帧的逐元素操作。

对于系列:

  • apply():当你想对数列的值应用一个函数时使用。
  • map():用于将每个值替换为另一个值。

你可能会对我的其他一些熊猫文章感兴趣:

更多可以从我的 Github 中找到

尽情享受吧!

大概就是这样。感谢阅读。

熊猫简介

原文:https://towardsdatascience.com/introduction-to-pandas-cc3bc6355155?source=collection_archive---------44-----------------------

达米安·帕特考斯基在 Unsplash 上拍摄的照片

使用 Pandas API 增强您的 Python 数据科学技能

andas 是一个用来分析、组织和结构化数据的 API。它在 Python 社区中被广泛接受,并在许多其他包、框架和模块中使用。Pandas 有各种各样的用例,非常灵活地为机器学习、深度学习和神经网络模型准备输入数据。使用 DataFrames 和 Series 等工具,您可以创建多维的集合和序列。这允许更大的索引和切片能力。Pandas 是开源的,是一个 BSD 许可的库。因此,让我们看看如何用 Pandas 构建、操作和组织您的数据。

[## 熊猫

pandas 是一个快速、强大、灵活且易于使用的开源数据分析和操作工具,构建于…

pandas.pydata.org](https://pandas.pydata.org/)

本文中我的 GitHub repo 代码可以在这里找到:

[## 第三只眼-电子人/熊猫简介

github.com](https://github.com/third-eye-cyborg/Intro_to_Pandas)

推荐的先决条件

[## Python 编程语言的简史

Python 编程语言是一种通用的编程语言,它已经在主流编程语言中占有一席之地

medium.com](https://medium.com/python-in-plain-english/a-brief-history-of-the-python-programming-language-4661fcd48a04) [## Python 基本概述

Python 有许多独特的特性,这些特性帮助它成为现在的样子。这些功能包括:

medium.com](https://medium.com/python-in-plain-english/python-basic-overview-76907771db60) [## Python 初学者完全参考指南

Python 是一种很好的初学者语言,但也适合高级用户。我将深入核心…

medium.com](https://medium.com/python-in-plain-english/python-beginners-reference-guide-3c5349b87b2) [## Python 的最佳 ide 和文本编辑器

我无法告诉你正确的 IDE(集成开发环境)对任何编程项目有多重要。只是…

medium.com](https://medium.com/analytics-vidhya/the-best-ides-and-text-editors-for-python-872ff1176c92) [## 如何在 Python 中与 API 交互

本文介绍了如何用 Python 编程语言处理 API 调用。

towardsdatascience.com](/how-to-interact-with-apis-in-python-10efece03d2b) [## Anaconda 发行版概述

科学 Python 发行版将改变你研究数据科学的方式。

towardsdatascience.com](/an-overview-of-the-anaconda-distribution-9479ff1859e6) [## PEP 8 风格指南概述

让您的 Python 代码具有风格。

towardsdatascience.com](/an-overview-of-the-pep-8-style-guide-5672459c7682) [## 探索 Python 中的设计模式

如何在您的编程体验中实现可重用模型?

towardsdatascience.com](/exploring-design-patterns-in-python-be55fbcf8b34)

目录

安装熊猫

Pandas 通过 PIP 或 Anaconda 发行版进行安装。

pip install pandas
conda install pandas

Pandas 集成了许多表格文件类型,并且擅长通过将这些文件类型转换成 Pandas 数据帧来处理它们。Pandas 中的 DataFrames 是一种特定类型的数据表。您可以操作数据、处理时间序列数据、绘制图表、重塑数据结构、合并数据、排序数据和过滤数据。

您可以将熊猫导入到 Python 代码中,如下所示:

import pandas as pd # the 'as pd' part is not necessary but is typically the standard for importing this library. 

创建熊猫数据框有多种方法。您可以将字典、列表、表格数据和 Pandas 系列对象转换成数据框架,也可以使用pd.DataFrame()方法创建它们。Series 对象就像一个单列数据框架。因此,你可以想象数据帧是一个或多个系列的集合。您可以使用pd.Series()创建一个系列对象。

探索熊猫系列

熊猫系列的基本构造是这样的。

pd.Series([1, 2, 3, 4])

通常,您会希望通过分配一个变量名来命名您的系列。

my_series = pd.Series([1, 2, 3, 4])

您可以将命名的 Pandas 系列分配给数据帧,如下所示。

first_series = pd.Series([1, 2, 3, 4])
second_series = pd.Series(['one', 'two', 'three', 'four'])my_df = pd.DataFrame({ 'First': first_series, 'Second': second_series })print(my_df)[out]
   First Second
0      1    one
1      2    two
2      3  three
3      4   four

探索熊猫数据框架

你可以把许多文件类型转换成熊猫数据帧。这里有一些更常用的方法。

[**read_csv**](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html#pandas.read_csv)(filepath_or_buffer[, sep, …])
[**read_excel**](https://pandas.pydata.org/docs/reference/api/pandas.read_excel.html#pandas.read_excel)(*args, **kwargs)
[**read_json**](https://pandas.pydata.org/docs/reference/api/pandas.read_json.html#pandas.read_json)(*args, **kwargs)
[**read_html**](https://pandas.pydata.org/docs/reference/api/pandas.read_html.html#pandas.read_html)(*args, **kwargs)

您还可以使用这些更常用的方法来操作文件类型的数据。

# Excel [**ExcelFile.parse**](https://pandas.pydata.org/docs/reference/api/pandas.ExcelFile.parse.html#pandas.ExcelFile.parse)([sheet_name, header, names, …])
[**ExcelWriter**](https://pandas.pydata.org/docs/reference/api/pandas.ExcelWriter.html#pandas.ExcelWriter)(path[, engine])# JSON
[**json_normalize**](https://pandas.pydata.org/docs/reference/api/pandas.json_normalize.html#pandas.json_normalize)(data[, record_path, meta, …])
[**build_table_schema**](https://pandas.pydata.org/docs/reference/api/pandas.io.json.build_table_schema.html#pandas.io.json.build_table_schema)(data[, index, …])

您还可以在数据帧上使用一些方法来帮助正确地组织和操作数据。我建议阅读文档,了解所有可以用数据帧做的事情,但这些是一些更常用的方法和属性。

[## 数据框架- pandas 1.1.3 文档

返回表示数据帧维数的元组。

pandas.pydata.org](https://pandas.pydata.org/docs/reference/frame.html)

# constructor [**DataFrame**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html#pandas.DataFrame)([data, index, columns, dtype, copy])[**DataFrame.head**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.head.html#pandas.DataFrame.head)([n])
[**DataFrame.tail**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.tail.html#pandas.DataFrame.tail)([n])
[**DataFrame.values**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.values.html#pandas.DataFrame.values)[**DataFrame.dtypes**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.dtypes.html#pandas.DataFrame.dtypes)[**DataFrame.columns**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.columns.html#pandas.DataFrame.columns)[**DataFrame.size**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.size.html#pandas.DataFrame.size)[**DataFrame.shape**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.shape.html#pandas.DataFrame.shape)[**DataFrame.axes**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.axes.html#pandas.DataFrame.axes) [**DataFrame.index**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.index.html#pandas.DataFrame.index)[**DataFrame.loc**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.loc.html#pandas.DataFrame.loc)[**DataFrame.iloc**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.iloc.html#pandas.DataFrame.iloc)[**DataFrame.keys**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.keys.html#pandas.DataFrame.keys)()
[**DataFrame.filter**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.filter.html#pandas.DataFrame.filter)([items, like, regex, axis])
[**DataFrame.dropna**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.dropna.html#pandas.DataFrame.dropna)([axis, how, thresh, …])
[**DataFrame.fillna**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.fillna.html#pandas.DataFrame.fillna)([value, method, axis, …])
[**DataFrame.sort_values**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sort_values.html#pandas.DataFrame.sort_values)(by[, axis, ascending, …])
[**DataFrame.sort_index**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sort_index.html#pandas.DataFrame.sort_index)([axis, level, …])
[**DataFrame.append**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.append.html#pandas.DataFrame.append)(other[, ignore_index, …])
[**DataFrame.join**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.join.html#pandas.DataFrame.join)(other[, on, how, lsuffix, …])
[**DataFrame.merge**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.merge.html#pandas.DataFrame.merge)(right[, how, on, left_on, …])
[**DataFrame.update**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.update.html#pandas.DataFrame.update)(other[, join, overwrite, …])
[**DataFrame.to_period**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_period.html#pandas.DataFrame.to_period)([freq, axis, copy])
[**DataFrame.tz_localize**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.tz_localize.html#pandas.DataFrame.tz_localize)(tz[, axis, level, …])
[**DataFrame.plot**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html#pandas.DataFrame.plot)([x, y, kind, ax, ….])
[**DataFrame.from_dict**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.from_dict.html#pandas.DataFrame.from_dict)(data[, orient, dtype, …])
[**DataFrame.to_pickle**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_pickle.html#pandas.DataFrame.to_pickle)(path[, compression, …])
[**DataFrame.to_csv**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html#pandas.DataFrame.to_csv)([path_or_buf, sep, na_rep, …])
[**DataFrame.to_sql**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_sql.html#pandas.DataFrame.to_sql)(name, con[, schema, …])
[**DataFrame.to_dict**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_dict.html#pandas.DataFrame.to_dict)([orient, into])
[**DataFrame.to_excel**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_excel.html#pandas.DataFrame.to_excel)(excel_writer[, …])
[**DataFrame.to_json**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_json.html#pandas.DataFrame.to_json)([path_or_buf, orient, …])
[**DataFrame.to_html**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_html.html#pandas.DataFrame.to_html)([buf, columns, col_space, …])
[**DataFrame.transpose**](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.transpose.html#pandas.DataFrame.transpose)(*args[, copy])

数据帧有五个参数dataindexcolumnsdtypecopy

数据帧被用作许多机器学习、深度学习和神经网络模型的输入。对 EDA(探索性数据分析)也有好处。至少了解和使用 Pandas 中的基本知识是大多数 Python 数据科学项目的必备条件。

在 Pandas 中处理数据(示例)

我将使用 Kaggle 上列出的太阳黑子数据集。月平均太阳黑子总数| 1749—2018 年 7 月

[## Kaggle:你的机器学习和数据科学社区

Kaggle 是世界上最大的数据科学社区,拥有强大的工具和资源来帮助您实现您的数据…

www.kaggle.com](https://www.kaggle.com/) [## 雀斑

月平均太阳黑子总数-1749 年至 2018 年 7 月

www.kaggle.com](https://www.kaggle.com/robervalt/sunspots)

作者 GitHub 要点

确认:

SIDC 和康德尔。

数据库来自 SIDC——太阳影响数据分析中心——比利时皇家天文台太阳物理研究部。 SIDC 网站

[## 知识共享- CC0 1.0 通用版

此页面有以下语言版本:CC0 1.0 通用版(CC0 1.0)公共领域专用公地…

creativecommons.org](https://creativecommons.org/publicdomain/zero/1.0/)

结论

熊猫库是 Python 中一个非常棒的工具。这篇文章只是介绍了使用 Pandas API 可以完成的事情的冰山一角。当开始使用 Python 处理数据时,您可以开始看到 Pandas 提供的真正功能。学习 Pandas 及其工作原理可以让您更好地控制输入数据,从而提高您在数据科学方面的 Python 体验。这不仅在探索数据时会给你更多的灵活性和能力,而且在直接使用它来实现你的编程、计算或科学目标时也会给你更多的灵活性和能力。我希望这能帮助任何想学习 Python 中的 Pandas API 的人。编码快乐!

熊猫数据帧简介

原文:https://towardsdatascience.com/introduction-to-pandas-dataframes-b1b61d2cec35?source=collection_archive---------16-----------------------

照片由吴镇男·麦金尼Unsplash 上拍摄

使用 pandas 处理、清理和选择数据

Pandas 是一个 python 包,设计用于快速灵活的数据处理、操作和分析。Pandas 有许多基本的数据结构(一种数据管理和存储格式)。如果您正在处理二维标签数据,即既有列又有带行标题的行的数据—类似于电子表格,那么 DataFrame 就是您将在 Pandas 中使用的数据结构。

二维数据结构——熊猫数据框架

在下一篇文章中,我将介绍这个包中一些最常见的数据处理和操作方法。

数据

在整个教程中,我将使用来自机器学习竞赛网站 drivendata.org 的数据集。数据集可以从这里下载。

数据集包括用于拟合机器学习模型的一组训练数据和用于进行预测的测试数据文件。出于本文的目的,因为我只执行预处理和分析,所以我将只使用训练数据。

读取数据

使用 Pandas 处理数据的第一步是将数据读入编辑器,在本文中,我将使用 Jupyter 笔记本。

Pandas 为大多数类型的数据导入提供了方法。

要从 CSV 文件中获取数据,您可以使用**pandas.read_csv()** 功能。我们使用的数据集中的要素(值)和标注位于不同的文件中,因此我们将同时读取它们,稍后将学习如何将它们合并在一起。

import pandas as pdtrain_values = pd.read_csv('train_values.csv')
train_labels = pd.read_csv('train_labels.csv')

Pandas 还具有从各种其他来源读取数据的功能,包括:

  • Excelpandas.read_excel()
  • JSON——pandas.read_json()
  • SQLpandas.read_sql()
  • 谷歌大查询——pandas.read_gbq()

合并和连接

在从事数据科学项目时,您正在处理的数据通常位于多个文件中和/或来自多个来源。因此,经常会有需要组合数据集的时候。有很多方法可以让你做到这一点,熊猫为每一种都提供了一种方法。

合并

如果您以前有过使用 SQL 查询的经验,那么这个方法将会非常熟悉。合并是通过公共标识符将两个数据集连接在一起的过程,类似于 SQL 中的连接。

在我们的数据集的例子中,我们有一个 train_values 数据集和一个 train_labels 数据集,每行都有相同的building_id,称为键。

merge 函数有许多参数,但是我们需要注意的三个参数是 howon 。在这里可以找到所有的论点和解释。

how 参数指的是确定哪些键应该出现在结果数据集中的方法。例如,值数据集中的行可能不会出现在标签数据集中。如果是这种情况,我们需要确定保留哪些行。 how 参数有四个变量。

  • left-此参数将仅保留左侧数据框中的关键点。
  • —这将只保留右数据帧的关键帧。
  • 外部 —将保留两个数据帧的所有关键字,包括不匹配的行。
  • inner —将保留两个数据帧的所有关键字,但不会包括不匹配的行。

下面的代码通过在on参数中使用building_id的内部连接来连接两个数据帧。

train_data = pd.merge(train_values, train_labels, how='inner', on=['building_id', 'building_id'])

串联

pandas 中的**concat()** 函数是组合数据帧的另一种方法。然而,**concat()**并没有加入一个公共键,而是通过将列添加到列或者将行添加到行来有效地将数据帧粘合在一起,这被称为

由于我们的两个数据集具有完全相同的索引,我们可以使用 concat 函数将它们组合起来,作为 merge 的直接替换。在下面,我们将两个数据帧作为一个列表传递,并指定 axis=1,这告诉函数我们想要在列上连接。在我们的例子中,concat 的缺点是,building_id列出现了两次。

train_data_concat = pd.concat([train_values, train_labels], axis=1)

处理缺失数据

数据集中最常见的问题之一是缺失数据。Pandas 有多种方法来处理数据帧中的缺失值。

对于缺失数据的处理,我们有很多选择。

  • 删除任何列中包含缺失数据的所有行。
  • 删除包含丢失数据的一列或多列。
  • 用合理的替代值估算缺失值这可能是 0,也可能是列中剩余数据的中间值。

熊猫有办法做到每一点。

首先检测是否有缺失值熊猫有**isna()** 功能。如果值丢失,则返回,否则返回。我们可以用它来确定每列缺失值的数量,如下所示。

train_data.apply(lambda x: sum(x.isna()) / len(train_data))

我们的数据集实际上没有任何丢失的值,但是让我们通过一些例子来说明如果有丢失的值,我们将如何处理它们。

熊猫函数 **drop_na()**删除包含缺失值的行或列(取决于您选择的参数)。该函数采用您设置为 0 的轴参数来删除行,设置为 1 来删除列。

替代功能**fillna()**。该函数将用您选择的值替换缺失的值。您可以用固定值(如 0)替换,也可以使用计算方法(如平均值)。还可以通过为每列传递一个值字典,将不同的值应用于不同的列。

下面的代码用该列的模式填充任何缺少的值。

train_data_numeric = train_data.apply(lambda x: x.fillna(x.mode()),axis=0)

选择数据

在数据分析和预处理过程中,会有很多时候需要选择数据的子集。您可能希望选择特定的列、行的子集或基于特定条件创建数据的子集。Pandas 提供了执行这些任务的各种方法。

要根据标签或位置从数据框中选择数据的子集和行,pandas 有两种方法 lociloc

loc 方法根据索引标签选择行。让我们快速看一个例子。

这是我们的数据框。索引是位于building_id列左侧的数字列。

在 pandas 中,我们总是从 0 开始计数,所以如果我们想使用 loc 选择前三行,我们运行下面的代码。

subset_loc = train_data.loc[[0, 1, 2]]
subset_loc.head()

这给了我们前三行。

iloc 方法通过索引位置选择行。例如,如果用户不知道索引或者如果索引不是数字的,可以使用这种方法。

选择前三行看起来非常类似于 loc 方法。

subset_iloc = train_data.iloc[[0, 1, 2]]
subset_iloc.head()

为了根据特定条件选择行,我们可以使用**where()**函数。这非常类似于 SQL 查询中的 where 子句。下面是几个例子。

基于布尔条件选择数据。下面的代码只选择列has_superstructure_cement_mortar_brick中的值为 1 的行。

has_cement_mortar_brick = train_data[train_data['has_superstructure_cement_mortar_brick'] == 1]
has_cement_mortar_brick.head()

根据数值条件选择数据。下面的代码只选择了age列的值大于 50 的行。

has_age_greater_than_50 = train_data[train_data['age'] > 50]
has_age_greater_than_50.head()

您可以组合多个条件,如下所示。

two_conditions = train_data_concat[train_data['has_superstructure_cement_mortar_brick'] == 1 & (train_data['age'] > 50)]
two_conditions.head()

本文简要介绍了 pandas 数据框和一些最常见的任务。熊猫用户指南是一个很好的参考点,可以在图书馆找到更多关于这些和其他可用方法的信息。如果你有兴趣了解更多关于如何用 Pandas 软件包分析数据的信息,我写了另一篇文章,可以在这里找到。

感谢阅读!

我每月都会发一份简讯,如果你想加入,请点击此链接注册。期待成为您学习旅程的一部分!

各种 SQL 查询的 Pandas 等价物介绍

原文:https://towardsdatascience.com/introduction-to-pandas-equivalents-of-various-sql-queries-448fb57dd9b9?source=collection_archive---------22-----------------------

一个直观的教程,适用于初学者和将职业道路转向数据科学的人

卡斯帕·卡米尔·鲁宾在 Unsplash 上的照片

有一些关于 SQL 查询的熊猫等价物的很棒的文章,例如:

它们是很棒的文章,但是,它们都假设读者已经熟悉了 SQL 。事实证明,情况并非总是如此,尤其是对于初学者和将职业道路转向数据科学的人。

本文旨在向零编码技能人员介绍 Pandas 查询。在本文中,每一节都以对特定 SQL 查询的介绍开始,然后是 Pandas 等价物,从而使我们对该方法的理解更加深刻和方便。

数据集准备

本文使用安德森鸢尾花(iris) 数据集进行演示。该数据集包含五个属性下的一组 150 条记录:萼片长度萼片宽度花瓣长度花瓣宽度、(从 sklearn 数据集称为目标)。

首先,让我们导入库并从 scikit-learn 库中获取虹膜数据集。你也可以从 UCI 虹膜数据集下载。

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris

为了演示,我们只取 6 个记录(每个类 2 个记录):

iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)# Convert datatype to float
df = df.astype(float)# append "target" and rename it to "label"
df['label'] = iris['target']# Use string label instead
df['label'] = df.label.replace(dict(enumerate(iris.target_names)))# Select first 2 records from each label
df_setosa = df[df['label'] == 'setosa'].head(2)
df_versicolor = df[df['label'] == 'versicolor'].head(2)
df_virginica = df[df['label'] == 'virginica'].head(2)
iris = pd.concat([df_setosa, df_versicolor, df_virginica])# For simplicity, change columns name from 
#    | sepal length (cm) | sepal width (cm) | petal length (cm) | petal width (cm) | label |
#  to the below
iris.columns = ['sepal_l', 'sepal_w', 'petal_l', 'petal_w', 'label']iris

iris 数据集中的 6 条记录

1.选择数据(选择)

从数据集中选择数据通常用于检索和预览数据。

例如:预览虹膜数据的萼片宽度花瓣长度花瓣宽度 列,显示前 2 条记录。

在 SQL 中,SELECT语句用于从数据库中选择数据。这是通过使用您想要选择的列的逗号分隔列表来完成的(或者使用*来选择所有列):

*SELECT **sepal_l, sepal_w, petal_l, petal_w** 
FROM iris 
**LIMIT 2***

在 Pandas 中,列的选择是通过将列名列表传递给数据帧来完成的:

*search = iris[**['sepal_l', 'sepal_w', 'petal_l', 'petal_w']**].**head(2)***

Pandas 列选择的输出

2.选择带条件的数据(其中)

在实践中,您经常希望检索满足某些指定条件的记录,这通常由过滤器来完成。

单一条件

例如,检索标签为“virginica”的所有数据**

在 SQL 中,过滤是通过一个WHERE子句完成的

*SELECT * 
FROM iris 
**WHERE label='virginica'***

在 Pandas 中,数据帧可以用多种方式过滤,最广泛使用的是布尔索引:

*search = iris[**iris['label']=='virginica'**]*

使用布尔索引选择 Pandas 列的输出

多个条件和

在某些情况下,您可能希望检索满足多个条件的记录。

例如,检索标签为“virginica”且花瓣长度≥ 5.5 的所有数据**

在 SQL 中,如果由AND分隔的所有条件都为真,则可以将WHERE子句与AND运算符结合起来显示记录。

*SELECT * 
FROM iris 
**WHERE label='virginica'AND petal_l >= 5.5***

在 Pandas 中,可以使用&操作符将等价的 AND 条件传递给数据帧:

*search = iris[**(iris['label']=='virginica')** **&** 
              **(iris['petal_l'] >= 5.5)**]*

具有多个条件和的 Pandas 列选择的输出

多重条件或

对于这些案例,您希望提取满足任何条件的记录。

例如,检索花瓣长度≥ 5 或间隔长度≥ 6 的所有数据**

在 SQL 中,类似于AND运算符,OR运算符可以与WHERE结合使用,如果OR分隔的任何条件为真,则显示记录。

*SELECT * 
FROM iris 
**WHERE petal_l >= 5OR sepal_l >= 6***

在 Pandas 中,可以使用|操作符将等价的 OR 条件传递给数据帧:

*search = iris[**(iris['petal_l'] >= 5) |** 
              **(iris['sepal_l'] >= 6)**]*

熊猫的产量或状况

3.处理缺失值(NULL 或 NaN)

在现实世界中,许多有趣的数据集都会丢失一些值。不同的编程语言使用不同的方法来指示缺失值。对于数据库和熊猫:

  • 缺失值在数据库中通常显示为NULL
  • [NaN](/working-with-missing-values-in-pandas-5da45d16e74) ,一个特殊的浮点值,在 Pandas 中用来表示一个缺失值。

选择缺少值的记录

在某些情况下,您希望只查看字段缺少值的记录。

例如,检索丢失花瓣长度的所有数据

在 SQL 中,我们可以使用IS NULL操作符来测试NULL

*SELECT * 
FROM iris 
**WHERE petal_l IS NULL***

在 Pandas 中,方法isna()可用于检查缺失值

*search = iris[**iris['petal_l'].isna()**]*

过滤掉缺失的值

在某些情况下,您希望只看到有值的记录。

例如,检索花瓣长度为的所有数据不丢失**

在 SQL 中,IS NOT NULL运算符可以用来过滤掉缺失的值

*SELECT * 
FROM iris 
**WHERE petal_l IS NOT NULL***

在 Pandas 中,等价的查询可以用方法notna()来完成

*search = iris[**iris['petal_l'].notna()**]*

4.排序结果(排序依据)

当从数据集中查询数据时,您可能还希望结果以排序的顺序返回。

按升序排列

例如,从 iris 数据集中检索花瓣 _l ≥ 4 的所有数据,按标签列升序排序**

在 SQL 中,ORDER BY关键字用于按升序(ASC)对结果集进行排序。

*SELECT * 
FROM iris 
WHERE petal_l >= 4 
**ORDER BY label ASC***

在 Pandas 中,可以使用带有参数by=’label’ascending=True的方法sort_values()来完成等效的查询

*search = iris[iris['petal_l'] >= 4]**.sort_values(by='label', ascending=True)***

熊猫的输出用 ASC 排序 _value

按降序排列

例如,从 iris 数据集中检索所有花瓣 _l ≥ 4 的数据,按标签列降序排序。**

在 SQL 中,ORDER BY关键字用于按降序(DESC)对结果集进行排序。

*SELECT * 
FROM iris 
WHERE petal_l >= 4 
**ORDER BY label DESC***

在 Pandas 中,可以使用带有参数by=’label’ascending=False的方法sort_values()进行等效查询

*search = iris[iris['petal_l'] >= 4]**.sort_values(by='label', ascending=False)***

熊猫产量与 DESC 排序 _ 值

5.更新记录(更新)

有时,我们需要修改数据集中的现有记录。

例如:将所有 sepal_length = 7 且 sepal_width = 3.2* 的记录的标签更新为virginica*

在 SQL 中,UPDATE语句和SET运算符一起用于修改现有记录

****UPDATE** iris 
**SET label = 'virginica'** 
WHERE sepal_l = 7 AND sepal_w = 3.2**

在 Pandas 中,loc()可以用来有条件地访问行,并返回指定的列label。之后,我们可以将所有记录的值设置为 virginica

**iris.**loc**[**(iris['sepal_l'] == 7) & 
        (iris['sepal_w'] == 3.2), 'label'**] = 'virginica'**

更新熊猫的现有记录

6。记录分组(分组依据)

在某些情况下,我们希望对具有相同值的记录进行分组。

例如:查找每个标签中的记录数

在 SQL 中,GROUP BY语句将具有相同值的行分组到汇总行中,

**SELECT label, count(*) 
FROM iris 
**GROUP BY label****

在 Pandas 中,SQL 的GROUP BY操作使用类似命名的groupby()方法来执行。

**search = iris**.groupby('label')**.size()**

熊猫中的分组记录

拥有多项统计数据

对于需要多个统计数据的情况

例如:查找每个标签的平均萼片长度和最大花瓣长度

在 SQL 中,我们可以使用一些内置的数学函数来完成任务:

**SELECT label, **avg(sepal_l)**, **max(petal_l)** 
FROM iris 
**GROUP BY label****

在熊猫身上,agg()可以用来同时应用多种功能:

**search = iris.groupby('label').**agg(
       { 'sepal_l': np.mean, 'petal_l': np.max})****

Pandas 中具有多个统计数据的分组记录

7.删除记录

从数据集中删除记录是数据处理的主要要求之一。

例如:删除花瓣宽度= 1.7,花瓣长度≥ 5 的记录

在 SQL 中,DELETE语句用于删除现有记录

****DELETE** FROM iris 
**WHERE petal_w = 1.7 AND petal_l >= 5****

在熊猫身上,对等的方法是drop()。而给定的参数应该是匹配记录iris[(iris[‘petal_w’] == 1.7) & (iris[‘petal_l’] >= 4)].**index** 的索引。

**drop = iris.drop(**iris[(iris['petal_w'] == 1.7) 
                      & (iris['petal_l'] >= 4)].index**)**

8.从多个数据集查询数据(连接)

到目前为止,我们一直在查看来自单个数据集的查询。在现实世界中,基于相关列组合来自两个或更多数据集的记录是很常见的。官方称这种查询为 Join。

有 4 种不同类型的连接

  1. ****内部连接:返回在两个数据集中具有匹配值的记录
  2. ****左(外)连接:返回左数据集中的所有记录,以及右数据集中的匹配记录
  3. ****右(外)连接:返回右数据集中的所有记录,以及左数据集中的匹配记录
  4. ****完全(外部)连接:当左或右数据集中有匹配时,返回所有记录

来源于https://www.w3schools.com/sql/sql_join.asp

在我们深入细节之前,让我们创建一个新的数据集 country ,它记录了在哪里发现了这种花:

**country = pd.DataFrame(**{ 'label': ['virginica', 'versicolor'],
                  'country': ['US', 'Germany']**})**

组成一个数据集国家

请注意,我们没有标签“setosa”的国家记录

内部连接

例如:根据标签检索在 iris 和 country 数据集中具有匹配值的所有记录

**SELECT * FROM iris 
**INNER JOIN** country 
**ON iris.label = country.label****

在 Pandas 中,当您想要基于相关列连接两个数据帧时,方法merge()会提供参数。默认情况下,它执行内部连接。

**inner = pd.**merge(iris, country, on='label')****

基于标签的内部连接的结果

左外部连接

例如:根据标签从 iris 中检索所有记录,并从国家中检索匹配的记录。

**SELECT * FROM iris 
**LEFT OUTER JOIN** country
**ON iris.label = country.label****

相当于熊猫:

**left = pd.merge(iris, country, on='label', **how='left'**)**

左外部连接的结果

右外部联接

例如:根据标签从国家/地区检索所有记录,并从 iris 检索匹配的记录。

**SELECT * FROM iris 
**RIGHT OUTER JOIN** country 
**ON iris.label = country.label****

相当于熊猫:

**right = pd.merge(iris, country, on='label', **how='right'**)**

右外部联接的结果

完全外部连接

例如:当 iris 或国家数据集中存在匹配时,根据标签检索所有记录。

**SELECT * FROM iris 
**FULL OUTER JOIN** country
**ON iris.label = country.label****

相当于熊猫:

**full = pd.merge(iris, country, on='label', **how='outer'**)**

完全外部连接的结果

9.组合多个查询的结果(联合)

在数据处理中,将两个或多个查询的结果组合成一个结果也很常见。为了组合结果,每个查询必须具有相同数据类型的相同数量的列。

为了演示,让我们从 iris 构建两个数据集。注意,我们还创建了一个如图所示的重复记录。

**iris_a = iris[0:3]
iris_b = iris[2:]**

具有重复记录的 iris_a 和 iris_b

允许重复值

在 SQL 中,可以使用UNION ALL 运算符来允许重复值

**SELECT * FROM iris_a WHERE label = 'versicolor' 
**UNION ALL** 
SELECT * FROM iris_b WHERE label = 'versicolor'**

在熊猫中,对应的方法是concat(),默认情况下它允许所有的副本。

**union = pd.**concat**([iris_a[iris_a['label']=='versicolor'], iris_b[iris_b['label']=='versicolor']])**

UNION All 允许重复的结果

没有重复值

在 SQL 中,UNION操作符只选择不同的值

**SELECT * FROM iris_a WHERE label = 'versicolor' 
**UNION** 
SELECT * FROM iris_b WHERE label = 'versicolor'**

在熊猫中,你可以将[**concat()**](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.concat.html#pandas.concat)[**drop_duplicates()**](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.drop_duplicates.html#pandas.DataFrame.drop_duplicates)结合使用。

**union = pd.**concat**([iris_a[iris_a['label']=='versicolor'], iris_b[iris_b['label']=='versicolor']])**.drop_duplicates()****

移除重复项的联合结果

尽情享受吧!

仅此而已。感谢阅读。

我们一直在谈论缺失的价值观。如果你想了解更多关于在 Pandas 中使用缺失值的信息,这里有一篇文章你可能会感兴趣。

** [## 处理熊猫中缺失的值

关于 Pandas 中缺失值以及如何使用内置方法处理它们的教程

towardsdatascience.com](/working-with-missing-values-in-pandas-5da45d16e74)**

PGM 1:概率图形模型介绍

原文:https://towardsdatascience.com/introduction-to-probabilistic-graphical-models-7d2c0b4bef19?source=collection_archive---------20-----------------------

概率图形模型世界的快速简单入门

由作者创建,用于说明贝叶斯网络中的节点和边

概率图形模型(PGM)提供了一种图形表示来理解一组随机变量(RVs)之间的复杂关系。

RVs 表示节点,它们之间的统计相关性称为边。上面显示了一个概率图形模型的例子。

我在上面强调了“复杂”这个词;让我们了解一下房车之间的复杂程度:

假设我们有 n 辆房车:X1,X2…Xn。让我们举一个非常简单的例子,假设每个 RV 只能取 2 个可能的值,即我们有一组二进制 RV。

现在,学习概率图形模型的关键目标是学习由 P(X1,X2,..Xn)为一组随机变量。我们注意到,随着 2^n 状态的增加,n 个二元 RVs 分布的复杂性增长到指数级。

建立直觉的例子:

RVs 及其关联借助一个示例进行解释:

如果患者带着一些症状(例如发烧)去看医生,医生为调查症状和可能的致病原因而询问的问题可以被描述为 RVs。

医学诊断是 PGM 的应用之一;照片由国家癌症研究所Unsplash 上拍摄

这些问题可能采取如下形式:

  • 发烧多少天了?
  • 食欲不振?
  • 发烧级别——高还是低?
  • 头疼还是头晕?
  • 病史?

补充说明:上面描述了两种变量——连续变量和离散变量。我们稍后将对此进行更多讨论,但在这一点上需要注意的是,连续变量和离散变量的共同存在会导致混合/混合网络(通常难以建模)。

因此,基于这些属性(又名 RVs)之间的关联,医生可能会建议进一步的行动方案,要么是一些药物,要么是一些测试,以某种概率得出结论

这里出现了一个需要更多强调和讨论的重要方面——概率。虽然我们大概知道没有机器学习模型或专家(在我们的情况下,是医生)可以在任何时候都 100%准确地预测输出,但让我们明白其中的一些原因,如下所述:

  • 对世界的一知半解:无论医生对可能的原因调查得多好,总有一定程度的不确定性。这主要是因为我们并不完全了解世界上所有的国家。
  • 噪音:测试结果可能会有噪音观察的成分,并清楚地表明它们可以被信任的程度。
  • 建模限制:即使有一些可能的疾病以发热为初步症状,但在建立模型时,几乎不可能考虑所有这些因素。

我们为什么需要 PGM,它在机器学习世界中处于什么位置?

  • PGM 提供了一种结构,在这种结构中,我们可以利用 独立性属性 以更紧凑的方式表示高维数据。
  • 它是对某些未观测变量,给出 观测变量 的证据,得出 推论 的有力工具。

总之,PGM 以联合分布的形式提供了一种基于图形的表示,对 RVs 之间的潜在关联进行了紧凑建模

我在上面强调了一些术语(对你来说可能是新的),所以在我们继续之前,让我简单扼要地解释一下,以便更容易保持联系:

独立性属性:

让我们从概率的世界来重温一下独立事件的概念。a 和 B 是独立的事件,如果:

P(A)= P(A | B);这意味着知道事件 B 的发生并不能告诉我们任何关于事件 a 发生的事情。

让我们把这个概念推广到随机变量。例如,X 和 Y 是独立的随机变量,如果:

很好,现在我们理解了独立性,但是在理解一个复杂的结构时,我们如何从中受益呢?

  • 它使我们更容易从系统的其余部分中独立地理解特定属性的特征。话虽如此,但在复杂网络中很少会遇到独立的情况。
  • 因此出现了条件独立的概念,即两个 RV 在观察到第三个 RV 时变得独立。
  • 现在,可以合理地假设条件独立的概念在如何计算和表示网络结构方面带来了显著的节约。

推论:

由于概率图形建模的结果,我们已经了解了属性/RVs 的联合概率分布,最困难和唯一的任务之一是计算一个或多个变量的边际密度和条件密度。

简而言之,推断是在给定观察变量的状态的情况下,对一组变量(即未观察变量)的条件密度的计算。

图形模型的类型:

1) 贝叶斯网络:通过有向无环图来表示结构。这类网络中变量之间概率影响的流动有明确的方向。箭头的存在意味着两个变量之间的因果关系,这由条件概率分布(CPDs)表示。

示例:开头所示的图形网络代表贝叶斯网络

2) 马尔可夫网络:马尔可夫网络中的底层图是无向的。由于这个网络中的边没有任何方向,因此缺少因果关系。因此,我们只能根据相似度*来表示哪个组合更有可能出现,这不一定在 0 和 1 之间,不像贝叶斯网络。*

示例:与示例(开头所示)类似的马尔可夫网络如下:

马尔可夫网络

应用:

PGM 广泛应用于信息提取、语音识别、医疗诊断、计算机视觉等领域。

还有一个应用,我将使用“pgmpy”演示 PGM 的实现。但在此之前,我打算写一系列的帖子,以清晰的方式解释先决条件的概念。

所以,敬请期待,快乐阅读。

参考文献:

概率图形模型介绍

原文:https://towardsdatascience.com/introduction-to-probabilistic-graphical-models-b8e0bf459812?source=collection_archive---------2-----------------------

克林特·王茂林在 Unsplash 上拍摄的照片

概率图形模型(PGMs) 是使用图形对复杂的联合多元概率分布进行编码的统计模型。换句话说,PGM 捕获相互作用的随机变量之间的条件独立性关系。这是有益的,因为多年来在各个领域中已经积累了许多关于图的知识,特别是在分离图上的子集、集团和函数方面。这些知识可以在 PGMs 中重用。此外,人们可以很容易地将 PGM 可视化,并快速了解模型结构。

通过了解 PGM 的图形结构,可以解决诸如推理(计算一个或多个随机变量的边际分布)或学习(估计概率函数的参数)之类的任务。给定一些数据,人们甚至可以尝试学习图形本身的结构。

在这篇文章中,我将简要描述 PGM 的两种风格,有向图模型(dgm),也称为贝叶斯网络(BNs)和无向图模型(ugm)或马尔可夫随机场(MRF)。我将解释这些模型之间的区别,并提供两者的例子。在这篇文章的最后一部分,我将看看 bn 和 MRF 之间的转换。我还将简要介绍 PGMs 中的推理和参数估计。我会在适当的地方提供更多相关信息的链接。

有向图形模型

顾名思义,有向图模型可以用一个图来表示,图的顶点作为随机变量,图的有向边作为它们之间的依赖关系(见下图)。

图 DGMs 的两个例子。虽然(A)中的模型是循环的,但是(B)是 DAG 并且可以表示贝叶斯网络。

边缘的方向决定了一个随机变量对另一个影响。如果该图不包含循环(在一个封闭链中连接的多个顶点),它通常被称为有向无环图(DAG)** 。可以使用诸如置信传播(BP) 或变量消除之类的算法精确地对这些图进行推断。**

贝叶斯网络

DGM 的一个例子是贝叶斯网络(BN) 。贝叶斯网络是一个 DAG ,其顶点(随机变量)代表模型的可观察变量或潜在变量。

BN 有向边(“箭头”)代表条件分布。例如,如果顶点的值是二进制的,则条件分布可以是伯努利分布。在连续值的情况下,条件分布可以是高斯分布。联合概率分布被公式化为条件概率或边际概率的乘积。

例如,当对下雨或洒水装置开启时给出的湿草概率建模时,我们可以使用这样的 DAG 来表示它:

图 2:贝叶斯网络的例子。它编码了以下逻辑:草地潮湿的概率取决于打开洒水器和雨水。洒水装置开启的概率本身取决于降雨(下雨时你不会打开洒水装置)。

这个 DAG 表示(分解的)概率分布

,其中 R 为随机变量,为降雨, S 为洒水器, G 为湿草。通过检查图表,您很快就会看到模型中唯一的独立变量是 R 。其他两个变量取决于降雨和/或洒水喷头的概率。通常,BN 的联合分布是给定其父节点的每个节点的条件概率的乘积:

由于大多数节点的父节点远少于节点总数,所以图通常是稀疏的

虽然这不是必需的,但是 BNs 经常被用来建模因果关系。如果 BN 中的边的方向代表因果性,那么 Judea Pearl 引入的因果 do-calculus 允许人们通过执行模拟干预来修改图表,并预测外部干预的影响(如果你想了解更多,请参见这篇伟大的文章)。

BNs 中的推理

让我们回到湿草的例子,算出草是湿的概率,即边际概率 p(G) 。这项任务被称为推理。为了确定一个变量的边际概率,通常你必须对图中的所有双亲求和。在这种情况下,边际概率是

在这种情况下,我们需要综合所有因素。然而,对于更复杂的图形,利用稀疏图形结构,有可能从总和中提取一些因子并大大简化计算

我们可能感兴趣的另一个任务是计算假定不下雨,草地会湿的条件概率。在这种情况下,我们将如下进行:

在这种情况下,我们只需要对 S 进行边缘化,因为 R 已经被假定为给定的。这个程序叫做变量消除。变量消去法是一种精确的推理算法。它还可以用于计算出网络的状态,通过简单地交换最大函数的和,具有最大概率。它的缺点是,对于大型 bn,它可能在计算上很难处理。在这些情况下,可以使用近似推理算法,如吉布斯采样拒绝采样

弄清楚 BNs 中的独立性

给定一个节点,我们如何确定一个 BN 中的两个节点是否独立?为了回答这个问题,让我们引入 d-分离的概念。

d 分离有 3 个规则:

  • 如果两组节点 XY 之间没有单向路径(不考虑其方向性的任何边序列),则它们是 d 分离的。

图 3:规则 1。

在本例中,节点 ac 是 d 连接的,而 adbd 是 d 分离的,因为 bd 都是 c 的父节点。

  • XY 是 d 分隔的,给定另一组节点 Z ,如果 Z “阻塞”它们之间的任何单向路径。

图 4:规则 2。

在这种情况下, b 阻断了 ac 之间的路径,导致它们被 d 分离。

  • 如果一个碰撞体或者它的后代在集合 Z 中,它打破了它的双亲的 d 分离。

图 5:规则 3。

这个需要一些解释:碰撞器是一个有两个或更多父节点的节点。如果对撞机被观察到,它的双亲,虽然之前是独立的,却变成了依赖的。例如,如果我们正在处理二元变量,对撞机的知识使其双亲的概率或多或少。在上图中, b 打破了 ac 之间的 d 分离。

无向图模型(ugm)或马尔可夫随机场(MRF)

与贝叶斯网络类似,MRF 用于使用图形描述随机变量之间的依赖关系。然而,MRF 使用无向边而不是有向边。它们也可能包含周期,不像贝叶斯网络。因此,MRF 可以描述与它们的贝叶斯网络对应物不同的依赖关系集合。请注意,MRF 不是 dgm 的超集,因为有些关系(如因果关系)只能由 dgm 描述。

贝叶斯网络的边表示条件依赖,而MRF 的无向边表示图中派系的联合概率。看看下面的 MRF:

图 6:有三个派系的 MRF 的例子。

该图描述了 3 个不同集团中 6 个变量的联合概率函数。因此,它分解为以下分布乘积:

MRF 的一个基本属性是它们满足成对的、局部的和全局的马尔可夫属性。这些性质与 BNs 的 d-分离规则有着深刻的联系。特别地,d-分离定义了有向图上的马尔可夫性质。

成对马尔可夫性质表明,给定所有其他变量,两个不相邻的变量是有条件独立的:

,其中 X_aX_b 定义任意两个不相邻的变量,X_ G 是所有变量的集合。

局部马尔可夫性质引入了变量的邻域的概念:

,其中 N(a)X_a 的邻域。换句话说,任何变量都有条件地独立于给定其邻域的任何其他变量。

最后,全局马尔可夫性质表明,给定一个分离子集 X_S ,任何变量集合 X_A 都独立于任何其他集合 X_B :

一般来说,成对马尔可夫性质来自局部马尔可夫性质,而局部马尔可夫性质又来自全局马尔可夫性质。然而,对于严格正概率分布,这些陈述是等价的。

MRFs 的另一个重要结果是 Hammersley-Clifford 定理 :非正式地,该定理陈述了满足一个(或等价地所有)马尔可夫性质的严格正概率分布可以表示为 Gibbs 测度。因此,吉布斯测度是在图的集团上分解的严格正函数:

,其中 Z 是适当的归一化常数(也称为配分函数), c 是图的(最大)团, ϕ 是团上的因式分解函数(不一定归一化),而 X 是随机变量的集合。

MRF 的例子

MRF 的一个非常常见的例子是隐马尔可夫模型(HMM):HMM 描述了一个具有周期性观察的动态系统。系统在每个时间步改变隐藏状态。因此, i 时刻的状态仅取决于 i-1 时刻的状态,即 HMMs 模型马尔可夫过程。此外,在时间 i 的观察仅直接取决于时间 i 的状态。

图 7:嗯。隐藏状态表示为 S1–S4,相应的观察值为 o1-o4。

由 HMM 建模的联合概率分布是:

其中 SO 分别为状态和观测随机变量, T 为时间步数。hmm 上的推理非常简单:因为图具有链状结构,所以可以使用动态编程算法进行推理。例如,在给定所有观察值o _【0:T】的情况下,计算系统在时间 i 处于状态 s 的概率可以使用算法来计算。类似地,给定观察值的最可能的隐藏状态序列由 维特比算法 计算。

MRF 还经常用于图像处理等领域,在这些领域中,它们描述了各个像素之间的关系。例如,它们可以通过要求相邻像素具有相似的亮度来加强期望解决方案的某种平滑度。二进制图像平滑(松弛)的一个流行模型是 伊辛模型 。伊辛模型将图像中的每个像素视为图形中的一个节点,嵌入到一个与相邻像素相连的网格中:

图 8:具有势 J1 和 J2 的伊辛模型。

伊辛模型假设每个节点可以有两种状态:σ ϵ {-1,1}。特定状态的能量由下式描述:

,其中 σ_i 表示节点 i 的状态,第一个总和覆盖网格中的所有邻居, J_ij 是节点 ij 之间的相互作用, h_i 是单个节点能量的因子(先验概率)。J_ij 可以是正的,鼓励相邻节点具有相同的符号,也可以是负的,使它们具有相反的符号。系统的联合吉布斯分布由下式给出:

取这个表达式的对数,表达式分解成图的集团。因此,我们可以看到,根据哈默斯利-克利福德定理,这个模型确实是一个 MRF。不幸的是,分母中的归一化因子通常很难计算,这使得近似推断成为涉及伊辛模型的问题的选择方法。

BNs 和 MRF 之间的等价性

贝叶斯网络和马尔可夫随机场有什么关系?难道我们不能用一个或另一个来表示概率分布吗?如何才能建立等价?人们可以通过简单地改变箭头的方向来把 BN 转换成 MRF。然而,这是不正确的,因为 dgm 和 ugm 编码的独立性关系是不同的。例如,考虑下面的贝叶斯网络和通过移除箭头获得的 MRF:

图 9 😦 A)中的 BN 和通过移除箭头生成的 MRF(B)。正确的道德化的 MRF 显示在(C)中。

从上图可以看出,A 和 B 处的图并没有编码相同的条件独立关系:给定节点 b ,节点 ac 根据第三个 d-分离规则并不独立。然而,( B)中的 MRF 不包含这种依赖关系,因为在 ac 之间没有连线。我们可以通过一个叫做 道德化 的程序来解决这个问题。这被恰当地命名为:尽管节点 ac 有一个共同的子节点,但它们并没有通过连接而“结合”。通过将 ac 结合,我们弥补了这种不一致。然而,如果没有给出 b ,我们也会失去独立性的一部分,即在 ac 之间。因此,图表变得更一般,推理可能更复杂。****

逆过程(从 MRFs 移动到 BNs)称为 三角测量 。请注意,这个过程比说教更复杂,因为最终的 BN 可能比原来的 MRF 大得多。具体来说,MRF 中所有具有 4 个或更多顶点的闭合环都必须划分成三角形。通过执行三角测量,我们得到了所谓的弦图。类似于道德化,三角测量也会导致独立信息的丢失。然而,三角测量用于多种推理算法,因为在一般图上是 NP 难的问题在弦图上往往变得容易。作为使用道德化三角剖分的算法的例子,让我们提一下 连接树算法

结论

概率图形模型提供了一种模拟随机变量之间关系的方法。最近,由于神经网络的普遍存在,它们已经有点失宠了。然而,我认为它们在未来仍然是相关的,特别是因为它们非常容易解释和直观。它们还允许对因果关系进行建模,甚至可能对学习高级概念的表示有用(参见 Yoshua Bengio 的本文)。在我看来,找到一种将神经网络与图形模型结合起来的方法,可能对推进整个人工智能领域非常有用。

流程挖掘简介

原文:https://towardsdatascience.com/introduction-to-process-mining-5f4ce985b7e5?source=collection_archive---------2-----------------------

照片由UXUnsplash 上拍摄

了解流程挖掘的基础知识,以及如何在 Python 中使用流程发现算法

目前,我们日常使用的大多数应用程序/网站都对我们如何使用它们非常感兴趣。这是因为他们想从用户的行为中学习和改进,以吸引或留住更多的用户。

想象一下你最喜欢的电商 app。最有可能的是,你可以自由浏览该公司提供的产品,并且时不时地你会被轻轻推着创建一个帐户,以便实际购买一些东西。为了真正成为注册用户,你经常需要提供一些关于你的信息(每个服务的信息量相差很大)。经过几次筛选后,你就可以开始购买了。

免责声明:上面的描述是一种简化,许多电子商务零售商采用不同的方式让用户注册,例如,要求在支付订单之前的最后一步注册,或者为了您的方便,在订购后友好地提供保存您的详细信息,以便您下次可以更快地订购。

后台发生的事情是数据科学家/分析师的工作,他们分析用户的旅程,并可能创建某种类型的漏斗分析 —对一系列事件的映射和分析,这些事件导向一个定义的目标,如完成注册或进行购买。漏斗分析是一个伟大而直观的工具,用于识别每个阶段的下降,并计算转化率。下面您可以看到一个展示漏斗的仪表板示例。

来源:维基百科

我们可以使用漏斗分析来确定用户旅程的哪一步导致最高的下降,然后花费一些额外的资源来调查原因并潜在地改进它,以留住更多的用户。

在一个简单的世界里,漏斗足以理解用户行为。然而,生活并不那么简单,许多应用程序/网站提供复杂的非线性体验。这就是为什么我们可以用一组额外的分析来补充漏斗分析,其中之一就是流程挖掘。

在本文中,我将简要概述进程挖掘的主题,并演示最流行的进程发现算法。我还会推荐额外的资源来进行更深入的阅读。

什么是流程挖掘?

在回答这个问题之前,我们首先需要定义构建模块——流程本身。我们所说的过程是指我们为了实现某个目标而执行的一系列离散的活动或事件。继续前面的例子,我们可以将注册所需的每个屏幕作为注册过程中的一个单独事件,目标是充分使用给定应用程序的服务。

流程挖掘是一套通过分析流程执行过程中产生的事件数据来获取流程知识并从中提取洞察力的技术。流程挖掘的最终目标是发现、建模、监控和优化底层流程。

流程采矿的潜在优势:

  • 流程发现—将事件日志转换为流程模型。
  • 一致性检查——调查模型和现实生活中发生的事情之间的差异。通过这种方式,公司可以识别与模型的偏差,并确定其严重性/成本。
  • 吞吐量分析/瓶颈检测—说明事件执行的强度(通过完成特定事件所花费的时间来衡量),以便确定潜在的瓶颈。这种分析可用于通过最小化吞吐量/开销时间来改进与时间相关的 KPI。

Python 中的进程发现算法

在这一部分中,我们将介绍一些最流行的流程挖掘算法,并将它们应用于 Python 中的一个玩具数据集。为此,我们将使用pm4py库(Python 的流程挖掘,如果你想知道的话)。

同样值得一提的是,对于许多研究人员/从业者来说,领先的流程挖掘软件是 ProM (自由软件)或 Fluxicon 的 Disco (商业软件)。还有 R 包,例如bupaR生态系统中的processmapR

数据准备—事件日志

流程挖掘基于事件日志。我们可以将事件日志描述为一系列事件。在大多数情况下,只要流程得到任何 IT 系统的支持,它就会生成某种由用户完成的操作的日志。例如,日志可以包含用户在应用程序中执行的所有操作。

为了执行进程发现,数据集必须包含以下 3 种类型的信息:

  • 案例 ID —通过流程的实体的唯一标识符。一个常见的例子可能是用户的唯一 ID,尽管有许多可能是有效的(这取决于用例)。
  • 事件——流程的一个步骤,是我们正在分析的流程的一部分的任何活动。
  • 时间戳——用于性能评估和确定事件的顺序,可以是用户进入/退出给定事件的时间(或者实际上两者都是)。

此外,我们可以包括更详细的信息,如资源、国家、用户群等。通过利用额外的信息,我们能够进行更详细的分析。

对于本文,我们使用由pm4py的作者提供的玩具数据集。你可以从他们的 GitHub 下载数据集(running-example文件)。首先,我们加载所有需要的库。

我必须说进口某些模块在pm4py不是最干净的,例如与scikit-learn相比。除非有一个非常强有力的理由这样组织图书馆,我真的希望它在未来将被简化。

然后,我们导入数据。在流程挖掘中,两种最常见的数据格式是 CSV 和 XES。后者成为存储事件日志的标准格式。你可以在这里阅读更多信息

在下表中,我们可以看到第一个案例的日志片段。在这个例子中,资源是完成动作的人(可能代表某个客户)。

请特别注意表格中的命名约定。在这些列中有一些重复,所以你可以清楚地看到它们是如何被重命名的,以便与pm4py中的算法配合得更好。指示案例 ID 的默认名称是case:concept:nameconcept:name是事件,最后time:timestamp是相应的时间戳。如果列不是这样命名的,我们总是可以使用pd.DataFramerename方法来重命名它们。有关正确指示案例列的更多信息,请参见本部分文档

使用这个小数据集的好处是,我们实际上可以检查整个日志,并计算出我们头脑中发生了什么。这样,解释创建的流程图将会容易得多。你可以在这里找到更多事件日志的例子。

阿尔法矿工

Alpha Miner 是最著名的进程发现算法之一。简而言之,该算法扫描轨迹(事件日志中的序列)的排序关系,并构建足迹矩阵。然后,它将矩阵转换成一个 Petri 网 (一种图)。这个视频包含了更详细的算法描述。

运行 Alpha Miner 会产生以下结果:

  • 一种 Petri 网模型,其中所有的转换都是可见的、唯一的,并且与分类事件相对应。
  • 初始标记——它描述了执行开始时 Petri 网模型的状态。
  • 最后的标记——它描述了执行结束时 Petri 网模型的状态。

使用 Petri 网表达的流程模型共享一个定义良好的语义:流程的执行从初始标记中包含的事件开始,到最终标记中包含的事件结束。

该算法的一些特征:

  • 它不能处理长度为一或二的循环,
  • 不可见的和重复的任务不能被发现,
  • 发现的模型可能不健全(关于流程挖掘中模型健全性的定义,请参考此视频),
  • 它不能很好地处理噪声。

为了用 Python 实现该算法,我们运行以下代码:

以下 Petri 网的结果是什么:

绿色圆圈代表初始标记,橙色圆圈代表最终标记。使用数据集的第一种情况,我们可以跟踪:注册请求->彻底检查->验票->决定->拒绝请求。

为了在流程图上提供更多的信息,我们可以添加关于事件频率的信息。我们不需要重新运行算法,我们只需向可视化工具添加一个参数。

这一次,我们在痕迹中看到最常采取的步骤。

Alpha Miner 有一个改进版本,叫做 Alpha+ Miner,它可以额外处理长度为 1 和 2 的循环。

直接跟随图

第二类流程模型是直接跟随图。在这类模型中,节点表示日志中的事件,而如果日志中至少有一个跟踪,其中源事件之后是目标事件,则有向边连接节点。

这些有向边与一些额外的指标配合得很好,例如:

  • 频率—目标事件跟随源事件的次数。
  • 性能—某种聚合,例如,两个事件之间经过的平均时间。

在最基本的变体中,我们可以通过运行以下代码行,从事件日志中创建一个直接跟踪图:

在此图中,我们在有向边的顶部添加了频率。我们可以看到,这个图与从 Alpha Miner 获得的 Petri 网有显著的不同。这是因为这种类型的图表显示了所有的联系,而不是试图找到事件遵循的一些规则。

或者,我们可以通过使用性能度量来修饰边缘。通过使用PERFORMANCE变量,我们显示了两个节点之间经过的平均时间。

启发式挖掘器

启发式挖掘器是阿尔法挖掘器算法的改进,作用于直接跟随图。它提供了一种处理噪声和寻找公共结构的方法。该算法的输出是一个启发式网络——一个包含活动和它们之间关系的对象。关于算法的更多细节,请看这段视频

注意:启发式网络可以转换成 Petri 网。

该算法的一些特征:

  • 将频率考虑在内,
  • 检测短循环和跳过事件,
  • 并不保证发现的模型是可靠的。

我们使用以下代码片段中的所有默认设置运行启发式挖掘器:

该图的解释与上面生成的直接跟随图非常相似。我们还可以看到,这些连接类似于 Alpha Miner 的 Petri 网所显示的流程。值得一提的是,启发式网络的形状高度依赖于算法的超参数集。

现在,让我们基于启发式挖掘器生成一个 Petri 网。

生成的模型比 Alpha Miner 生成的模型复杂得多。

感应采矿机

归纳挖掘器算法是阿尔法挖掘器和启发式挖掘器的改进。最大的区别在于,它保证了一个具有良好适应值的合理过程模型(通常保证完美的重放)。

该算法的基本思想是在事件日志中找到一个显著的拆分(有不同类型的拆分:顺序、并行、并发和循环)。在找到分裂之后,算法在子日志(通过应用分裂找到)上递归,直到识别出基本情况。归纳挖掘器不在 Petri 网上工作,而是在流程树上工作(我们可以将它们转换成 Petri 网,我们很快就会看到一个例子)。这个视频直观地描述了算法如何工作,以及 Petri 网和流程树之间的区别。

该算法有多种变体,其中一种是 IMDFc,它避免了子日志上的递归,而是使用直接跟随图。有关该算法的更多信息,请参考[6]。

为了从我们的事件日志创建流程树,我们运行以下代码:

其中->是序列运算符,X 是唯一选择,*是循环。在下一个代码块中,我们将流程树转换成一个更熟悉的 Petri 网。

结论

在本文中,我简要概述了流程挖掘作为一种在商业中使用的有用技术。我确实认为,在典型的数据科学家的技能组合中,这绝对不是一项主流技能,但成功实施流程挖掘实际上可以为许多公司带来显著的增值。

我没有详细讨论过程挖掘算法的技术细节,因为至少有足够的材料可以写一系列的文章。对于那些对所有这些图表是如何创建的本质细节感兴趣的人,我可以推荐 Coursera 上的 过程挖掘:数据科学在行动 。它是由流程采矿之父 Wil van der Aalst 教授讲授的,因此向专家学习才有意义。此外,您可以查看[3]以获得更多资源。

您可以在我的 GitHub 上找到本文使用的代码。一如既往,我们欢迎任何建设性的反馈。你可以在推特上或者评论里联系我。

觉得这篇文章有趣?成为一个媒介成员,通过无限制的阅读继续学习。如果你使用这个链接成为会员,你将支持我,不需要你额外付费。提前感谢,再见!

如果您喜欢这篇文章,您可能还会对以下内容感兴趣:

[## Python 中群组分析的分步介绍

学习如何进行群组分析,以更好地了解顾客的行为

towardsdatascience.com](/a-step-by-step-introduction-to-cohort-analysis-in-python-a2cbbd8460ea) [## 论度量的专制和度量的固定

在一个充满指标的世界里,我们需要清楚地认识到那些弊大于利的指标

towardsdatascience.com](/on-the-tyranny-of-metrics-and-metric-fixation-b4c1d44b5f6c)

参考

[1]Sebastiaan j . van Zelst:Python 中的流程挖掘| PyData Eindhoven 2019—https://www.youtube.com/watch?v=i6NGHvZyHXY

[2] 过程挖掘:数据科学在行动 | Coursera。

[3]http://www.processmining.org/

https://www.futurelearn.com/courses/process-mining

[5]魏茨,A. J. M. M .,范德阿尔斯特,W. M .,,德梅德罗斯,A. A. (2006 年)。用启发式挖掘算法进行过程挖掘。埃因霍温技术大学。代表 WP166 ,1–34。https://pdfs . semantic scholar . org/1c C3/d62e 27365 b 8d 7 ed 6 ce 93 b41 c 193d 0559d 086 . pdf

[6]李曼斯、法兰德和范德阿尔斯特(2015 年)。有保证的可扩展流程发现。在企业、业务流程和信息系统建模(第 85-101 页)。斯普林格,查姆。—http://www . process mining . org/_ media/blogs/pub 2015/BPM ds _ directly-follows _ mining . pdf

PyMC3 简介:概率编程的 Python 包

原文:https://towardsdatascience.com/introduction-to-pymc3-a-python-package-for-probabilistic-programming-5299278b428?source=collection_archive---------11-----------------------

简介

我们经常在天气预报节目中听到这样的话:明天下雨的几率是 80%。那是什么意思?通常很难给这种说法赋予意义,尤其是从频率主义者的角度来看:没有合理的方法来无限(或非常大)次重复下雨/不下雨的实验。

贝叶斯方法为这种类型的陈述提供了一个解决方案。下面这句话摘自《T2 概率编程》一书&黑客的贝叶斯方法,完美地总结了贝叶斯观点的一个关键思想。

贝叶斯世界观将概率解释为事件中可信度的度量,也就是说,我们对事件的发生有多有信心。

换句话说,在贝叶斯方法中,我们永远不能绝对肯定我们的信念,但可以明确地说我们对相关事件有多有信心。此外,随着收集的数据越来越多,我们可以对自己的信念更加自信。

作为一名科学家,我被训练成相信数据,并且总是对几乎所有事情都持批评态度。自然地,我发现贝叶斯推理相当直观。

然而,使用贝叶斯推理通常在计算和概念上具有挑战性。通常,需要进行大量冗长而复杂的数学计算才能完成任务。即使作为一名数学家,我偶尔也会觉得这些计算很乏味;尤其是当我需要快速浏览我想要解决的问题时。

幸运的是,我的导师奥斯汀·罗奇福德最近向我介绍了一个叫做 PyMC3 的奇妙软件包,它可以让我们进行数字贝叶斯推理。在本文中,我将通过一个具体的例子来快速介绍 PyMC3。

一个具体的例子

假设我们有一枚硬币。我们翻转三次,结果是:

[0, 1, 1]

其中 0 表示硬币落在尾部,1 表示硬币落在头部。我们有信心说这是一枚公平的硬币吗?换句话说,如果我们让θ是硬币返回正面的概率,那么证据是否足够有力的支持θ=12 的说法?

除了上述实验的结果,我们对硬币一无所知,所以很难说什么是肯定的。从频率主义者的角度来看,θ的点估计值

虽然这个数字有意义,但 frequentist 方法并不能真正提供一定程度的可信度。特别是,如果我们做更多的试验,我们很可能得到θ的不同点估计。

这就是贝叶斯方法可以提供一些改进的地方。这个想法很简单,因为我们对θ一无所知,我们可以假设θ可以是[0,1]上的任何值。在数学上,我们之前认为θ遵循均匀(0,1)分布。对于那些需要复习数学的人,Uniform(0,1)的 pdf 由下式给出

然后,我们可以利用证据/我们的观察来更新我们对θ分布的看法。

让我们正式调用 D 作为证据(在我们的例子中,它是我们掷硬币的结果。)根据贝叶斯规则,后验分布计算如下

其中 p(D|θ)是似然函数,p(θ)是先验分布(本例中为均匀分布(0,1))。)这里有两条路可以走。

显式方法

在这个特殊的例子中,我们可以手工做所有的事情。更准确地说,给定θ,我们在三次掷硬币中得到两个正面的概率由下式给出

假设 p(θ)=1。接下来,我们评估支配者

通过一些简单的代数,我们可以看到上述积分等于 1/4,因此

备注:通过同样的计算,我们还可以看到,如果θ的先验分布是一个参数为α,β的贝塔分布,即 p(θ)=B(α,β),样本量为 N,其中 k 为 head,则θ的后验分布由 B(α+k,β+N k)给出。在我们的例子中,α=β=1,N=3,k=2。

数值逼近

在显式方法中,我们能够通过使用共轭先验显式计算θ的后验分布。然而,有时共轭先验用于简化计算,它们可能不反映现实。此外,寻找共轭先验并不总是可行的。

我们可以通过使用马尔可夫链蒙特卡罗 (MCMC)方法来近似后验分布,从而克服这个问题。这里的数学非常漂亮,但就本文的唯一目的而言,我们不会深究它。相反,我们将解释如何使用 PyMC3 实现这个方法。

为了运行我们的代码,我们导入以下包。

import pymc3 as pm
import scipy.stats as stats
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
from IPython.core.pylabtools import figsize

首先,我们需要初始化θ的先验分布。在 PyMC3 中,我们可以通过下面几行代码来实现。

with pm.Model() as model:
    theta=pm.Uniform('theta', lower=0, upper=1)

然后我们用观察到的数据来拟合我们的模型。这可以通过下面几行代码来完成。

occurrences=np.array([1,1,0]) #our observation 
with model:
    obs=pm.Bernoulli("obs", p, observed=occurrences) #input the observations
    step=pm.Metropolis()
    trace=pm.sample(18000, step=step)
    burned_trace=trace[1000:]

在内部,PyMC3 使用 Metropolis-Hastings 算法来逼近后验分布。trace 函数决定了从后验分布中抽取的样本数。最后,由于算法在开始时可能不稳定,所以仅在一定的迭代周期后提取样本是有用的。这就是我们代码中最后一行的目的。

然后,我们可以绘制从后验分布获得的样本直方图,并将其与真实密度函数进行比较。

from IPython.core.pylabtools import figsize
p_true=0.5
figsize(12.5, 4)
plt.title(r"Posterior distribution of $\theta$")
plt.vlines(p_true,0, 2, linestyle='--', label=r"true $\theta$ (unknown)", color='red')
plt.hist(burned_trace["theta"], bins=25, histtype='stepfilled', density=True, color='#348ABD')
x=np.arange(0,1.04,0.04)
plt.plot(x, 12*x*x*(1-x), color='black')
plt.legend()
plt.show()

我们可以清楚地看到,数值近似值非常接近真实的后验分布。

如果我们增加样本量,会发生什么?

正如我们之前提到的,我们获得的数据越多,我们对θ的真实值就越有信心。让我们通过一个简单的模拟来检验我们的假设。

我们将随机投掷一枚硬币 1000 次。然后,我们使用 PyMC3 来近似θ的后验分布。然后,我们绘制从该分布中获得的样本的直方图。所有这些步骤都可以通过下面几行代码来完成

N=1000 #the number of samples
occurences=np.random.binomial(1, p=0.5, size=N)
k=occurences.sum() #the number of head#fit the observed data 
with pm.Model() as model1:
    theta=pm.Uniform('theta', lower=0, upper=1)with model1:
    obs=pm.Bernoulli("obs", theta, observed=occurrences)
    step=pm.Metropolis()
    trace=pm.sample(18000, step=step)
    burned_trace1=trace[1000:]
#plot the posterior distribution of theta. p_true=0.5
figsize(12.5, 4)
plt.title(r"Posterior distribution of $\theta for sample size N=1000$")
plt.vlines(p_true,0, 25, linestyle='--', label="true $\theta$ (unknown)", color='red')
plt.hist(burned_trace1["theta"], bins=25, histtype='stepfilled', density=True, color='#348ABD')
plt.legend()
plt.show()

这是我们得到的。

如我们所见,后验分布现在以θ的真实值为中心。

我们可以通过取样本的平均值来估算θ。

burned_trace1['theta'].mean()0.4997847718651745

我们看到这真的很接近真实答案。

结论

正如我们所见,PyMC3 很好地执行了统计推断任务。此外,它使得概率编程变得相当容易。

参考文献。

[1]https://github . com/CamDavidsonPilon/probabilical-Programming-and-Bayesian-Methods-for-Hackers

Python 类简介

原文:https://towardsdatascience.com/introduction-to-python-classes-da526ff745df?source=collection_archive---------14-----------------------

面向对象编程的综合实践指南

Edvard Alexander lvaag 在 Unsplash 上拍摄的照片

类是 Python 最基础的部分。原因在于面向对象编程的概念。

Python 中的一切都是对象比如整数、列表、字典、函数等等。每个对象都有一个类型,对象类型是使用类创建的。

课程有:

  • 数据属性:定义创建一个类的实例需要什么
  • 方法(即过程属性):定义如何与类的实例交互

方法就像函数一样,但是它们属于一个特定的类。属性可以被认为是与类交互的接口。

类的一个优点是我们不需要知道它是如何被创建的。我们可以通过数据属性和方法来使用它。例如,为了使用 scikit-learn 中的线性回归模型,我们只需导入 linear regression 类。

from sklearn.linear_model import LinearRegression

我们只需要知道如何使用 LinearRegression 类或与之交互。我们对它是如何产生的不感兴趣。这是抽象的概念。行为已定义,但实现是隐藏的(如果您愿意,可以看到它)。

这个帖子可以被认为是对类的全面介绍。我们将通过许多例子来解释它们的特点。在实现一个类时,还需要记住一些提示。

我们还将做几个例子来解释继承,这是面向对象编程中一个非常重要的概念。

创建一个类

让我们首先创建一个名为“Person”的简单类。

class Person(object):
    def __init__(self, age, name):
        self.age = age
        self.name = name

init 是一个特殊的方法,在创建类的实例时自动运行。参数代表数据属性。自我就是实例本身。你可以用任何词来代替“自我”,但使用“自我”是一种非常普遍的做法。

年龄和姓名是另外两个数据属性。因此,Person 类的每个实例都有年龄和姓名数据属性。

我们创建了 Person 类的一个实例。

p1 = Person(24, "John")print(type(p1))
<class '__main__.Person'>

print(p1)
<__main__.Person object at 0x7f67faac9ba8>

type 打印出一个对象的类型(即类)。因此,p1 是 Person 类型的实例。

当我们打印 p1 时,Python 返回对象的类型和内存位置。但是,我们可以通过在我们的类中实现 str 方法来改变它。

让我们把这个人的名字和年龄打印出来。

class Person():
    def __init__(self, age, name):
        self.age = age
        self.name = name def __str__(self):
        return "<" + self.name + "," + str(self.age) + ">"

如果我们现在打印一个 Person 类型的对象,我们将得到名字和年龄。

print(p1)
<John,24>

我们可以访问对象的数据属性,如下所示:

p1 = Person(24, "John")print(p1.name)
Johnprint(p1.age)
24

我们也可以用同样的方式改变属性:

p1 = Person(24, "John")print(p1.age)
24p1.age = 28print(p1.age)
28

但是,不建议使用这种方法。相反,我们可以实现获取和设置属性值的方法(也称为 getters 和 setters)。

让我们为年龄属性做这件事:

def set_age(self, age):
    self.age = agedef get_age(self):
    return self.age

注意:我每次只写新的部分,而不是写整个类的定义。

set_age 方法用给定的值更新一个人的年龄。get_age 方法只返回 age 属性的值。self 参数表示实例本身。

p2 = Person(26, "Emily")print(p2.get_age())
26p2.set_age(27)print(p2.get_age())
27

我们调用了对象上的方法。另一种选择是在类上调用它。

p2 = Person(26, "Emily")print(Person.get_age(p2))
26Person.set_age(p2, 27)print(Person.get_age(p2))
27

如果要使用此选项,请确保在方法内部传递对象的名称。

为了让这些方法返回值,我们需要使用括号。否则,您将得到如下消息:

p1 = Person(36, "Edward")print(p1.get_age)
<bound method Person.get_age of <__main__.Person object at 0x7fe33bf08eb8>>

我们可以为我们的类定义方法。记住方法就像函数一样,但是与特定的类相关联。

让我们定义一个计算两个人物年龄差的方法。

def age_diff(self, other):
    diff = self.age - other.age
    return abs(diff)

它接受两个对象,并返回它们之间年龄差的绝对值:

p1 = Person(22, "Ashley")
p2 = Person(26, "Max")print(p1.age_diff(p2))
4print(Person.age_diff(p1, p2))
4

创建子类(继承)

我们将创建另一个基于 Person 类的类。在面向对象编程中,有一个概念叫做继承

类似于现实生活中的传承。我们的大部分基因组来自我们的父母。我们继承了他们。因此,我们和父母有相似之处。

继承与类的工作方式相同。当我们创建一个子类时,它从父类继承属性(数据的和过程的)。但是,我们可以自由添加或覆盖这些属性。

让我们创建一个名为 MarriedPerson 的新类。它将是人的子类。除了年龄和姓名数据属性之外,它还具有配偶姓名和子女数量属性。

下面是包含 init 方法的类定义:

class MarriedPerson(Person):
   def __init__(self, age, name, spouse_name, number_of_children=0):
      Person.__init__(self, age, name)
      self.spouse_name = spouse_name
      self.number_of_children = number_of_children

这里有两个要点:

  1. 父类的名称写在括号中,这样 python 就知道 MarriedPerson 类继承了 Person 类的所有属性。
  2. 因为已经在 Person 类中定义了 age 和 name 属性,所以我们可以复制 Person 类的 init 方法。我们只需要定义额外的属性。

:我们可以自由手工为子类定义每个数据属性。使用 parent 的 init 是可选的。

注意:我们也可以在 init 方法中继承父类的属性,如下所示:

class MarriedPerson(Person):
   def __init__(self, age, name, spouse_name, number_of_children=0):
      super().__init__(age, name)
      self.spouse_name = spouse_name
      self.number_of_children = number_of_children

我们现在可以创建一个 MarriedPerson 对象(这个类的一个实例)。

mp1 = MarriedPerson(26, 'Max', 'Ashley', 2)print(mp1)
<Max,26>

如您所见,print 函数只打印已婚者的姓名和年龄。原因是 MarriedPerson 类从 Person 类继承了 str 方法。

我们可以覆盖它。

class MarriedPerson(Person):
   def __init__(self, age, name, spouse_name, number_of_children):
      Person.__init__(self, age, name)
      self.spouse_name = spouse_name
      self.number_of_children = number_of_children def __str__(self):
      return "<" + self.name + "," + "married to " +
      self.spouse_name + ">"

如果我们现在打印一个 MarriedPerson 对象,我们将看到姓名和配偶姓名。

mp1 = MarriedPerson(26, 'Max', 'Ashley', 2)print(mp1)
<Max,married to Ashley>

我们创建了一个方法来返回两个 Person 对象之间的年龄差(age_diff)。因为我们从 Person 对象继承,所以我们可以对 MarriedPerson 对象使用该方法。

mp1 = MarriedPerson(26, 'Max', 'Ashley', 2)
mp2 = MarriedPerson(29, 'Emily', 'John', 1)print(mp1.age_diff(mp2))
3

我们可以为数据属性指定默认值。例如,一个已婚的人可能没有孩子。因此,我们可以将默认值设置为 0。

class MarriedPerson(Person):
   def __init__(self, age, name, spouse_name, number_of_children=0):
      Person.__init__(self, age, name
      self.spouse_name = spouse_name
      self.number_of_children = number_of_children

除非另外指定,否则 number_of_children 属性将获得值 0。

mp1 = MarriedPerson(26, 'Max', 'Ashley', 2)
mp2 = MarriedPerson(29, 'Emily', 'John')print(mp1.number_of_children)
2print(mp2.number_of_children)
0

下面是 Person 和 MarriedPerson 类的最终版本:

人物类(图片由作者提供)

已婚人士类(图片由作者提供)

结论

关于 Python 类还有很多内容要介绍。例如,类变量和实例变量之间的区别是一个重要的话题。

然而,我们在这篇文章中讨论的内容将会让你对工作和创建类感到舒适。可以认为是全面的介绍。

随着你不断练习,你会学到更多。

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

面向数据科学的 Python 简介

原文:https://towardsdatascience.com/introduction-to-python-for-data-science-6d1dba7c305c?source=collection_archive---------31-----------------------

面向初学者的简单交互式教程

诺德伍德主题公司在 Unsplash 上拍摄的照片

在本帖中,您将了解存储和操作数据的强大方法,以及开始进行自己的分析的有用的数据科学工具。首先,我将向您介绍我们的朋友 Python 和一个名为数据科学的领域,然后我们将开始互动练习。在动手操作教程部分,我们将通过以下主题 列出 函数 、以及 方法 。我等不及了,让我们开始吧!

计算机编程语言

Python 是一种通用编程语言,在数据科学中越来越受欢迎。Python 还能让您快速工作,更有效地集成系统。世界各地的公司都在利用 Python 从他们的数据中收集知识。官方 Python 页面如果你想了解更多

数据科学

数据科学继续发展,成为技术专业人员最有前途和最受欢迎的职业道路之一。如今,成功的数据专业人士明白,他们必须超越分析大量数据的传统技能、数据挖掘和编程技能。

如今,我们与科技设备进行的几乎每一次互动都包含数据——比如我们在亚马逊购买的商品、脸书订阅、网飞推荐,甚至是我们用来登录手机的面部识别。

[## Python 中的简单人脸检测

如何使用 OpenCV 库检测图像中的人脸

towardsdatascience.com](/simple-face-detection-in-python-1fcda0ea648e)

如果你像我一样是视觉学习者,这里有一个来自 YouTube 的 5 分钟的短片。该视频包含一些详细的信息,但它会让您了解数据科学的全貌。

什么是列表?

列表是方括号中逗号分隔的项的集合。Python 中列表的好处是列表中的项目可以是不同类型的项目。列表是强大的。您可以很容易地更改、添加或删除列表中的元素。

在这一步中,您将学习存储、访问和操作列表中的数据:这是高效处理大量数据的第一步。让我们做一些练习。

改变列表元素

my_list = ['hello', 'world, 3.14, 5]my_list[2] = 27my_list

更改列表元素

添加列表元素

my_list = ['hello', 'world, 3.14, 5]new_list = my_list + ['add' , 'me']my_list

添加列表元素

删除列表元素

new_list = ['hello', 'world, 3.14, 5, 'add' , 'me']del(new_list[0])new_list

移除列表元素

什么是函数?

函数是可重用的代码。我把它们看作是环境友好的代码:)不用写完整的代码,你可以放入一个函数,在你需要运行代码的任何时候调用那个函数。函数用于解决特定的任务。目标是减少解决挑战性问题所需的代码量!

在 Python 中,有一些内置函数,你可以不用定义它们就能使用它们。它们已经创建好,可以使用了。

以下是一些内置函数:

  • max() :返回列表中最大值的元素
  • min() :返回列表中最小值的元素
  • len() :返回列表或字符串的长度
  • index() :返回列表中元素的索引。(这是一个方法,将在函数之后介绍)

最大()和最小()

请记住,要使用最大值和最小值函数,列表中的元素必须是相同的类型。同样,在比较字符串值时,它会检查它们的 ascii 值。如果你没有听说过 Ascii 表,你可以谷歌一下。

my_list = [1, 2, 3.4, 12]max(my_list)min(my_list)

最大值和最小值

Len()

如果我们想得到整个列表的长度,括号中的值就是列表的长度。如果我们想得到一个特定元素的长度,这个元素将会在括号之间。

my_list = ['hello', 'world, 3.14, 5]len(my_list)len(my_list[0])

长度

方法

方法内置于函数中,可以为特定类型的元素调用。例如,列表对象有自己的方法,字符串对象有自己的方法。我将向您展示每种类型的几个例子,让您了解方法是如何工作的。

列出方法

Index 方法返回特定元素的索引号。count 方法返回列表中特定元素的数量。

my_list = ['hello', 'world, 3.14, 5]my_list.index('hello')my_list.count(3.14)

列出方法

字符串方法

方法在将字符串的第一个字母大写后返回元素。和 replace 方法在用另一个字符串替换特定字符串后返回元素。

name = 'leo'name.capitalize()name.replace('o', 'onardo')

字符串方法

感谢你阅读这篇文章,我希望你今天喜欢并学到了一些新东西。如果您在执行代码时有任何问题,请随时回复。我非常乐意帮忙。你可以找到我发表的关于数据科学 Python 的其他文章。保持安全和快乐的编码!😃

跟随我的博客走向数据科学以获得灵感。

更多相关内容

[## 清理 Python 中的数据(数据类型)

使用 pandas 操作数据类型的简单说明

medium.com](https://medium.com/python-in-plain-english/cleaning-data-in-python-data-types-46f9ebf2feef) [## Python 中的排序和子集化

使用 Pandas 进行动手数据分析

towardsdatascience.com](/sorting-and-subsetting-in-python-f9dd2e14caa0)

Python Heapq 模块简介

原文:https://towardsdatascience.com/introduction-to-python-heapq-module-53534feda625?source=collection_archive---------19-----------------------

关于如何使用 Python 的 heapq 模块的简单介绍

一个是二叉树的一个特例,其中父节点与它们的子节点的值进行比较,并相应地进行排列。如果你看过我以前的一篇名为 8 常见数据结构的文章,每个程序员都必须知道有两种类型的堆;最小堆和最大堆。

[## 每个程序员都必须知道的 8 种常见数据结构

数据结构是一种在计算机中组织和存储数据的专门方法,以这种方式我们可以执行…

towardsdatascience.com](/8-common-data-structures-every-programmer-must-know-171acf6a1a42)

python 的 heapq 模块实现了堆队列算法。它使用最小堆,其中父堆的键小于或等于其子堆的键。在本文中,我将介绍 python heapq 模块,并通过一些示例向您展示如何将 heapq 用于原始数据类型和具有复杂数据的对象。

图片来自 Pixabay凯伦·阿诺德

Heapq 函数

假设你知道堆数据结构是如何工作的,我们来看看 Python 的 heapq 模型提供了哪些功能。

  • heappush(heap,item) —将值 item 推入
  • heappop(heap) —弹出并返回堆中的最小值
  • heappushpop(heap,item) —将值 item 推入并返回中的最小值
  • 堆(x) —将列表 x 转换成堆
  • heap preplace(heap,item) —弹出并返回中的最小值,然后将值 item 推入

使用原始数据类型的 Heapq 示例演练

让我们看一些使用不同 heapq 函数的例子。首先你要导入 heapq 模块。

import heapq

考虑下面给出的示例列表a

>>> a = [52, 94, 13, 77, 41]

如果我们把这个列表放大,结果将如下。请注意,堆积是就地完成的。

>>> heapq.heapify(a)
>>> print(a)
[13, 41, 52, 77, 94]

请注意,第 0 个索引包含所有值中的最小值,即 13。

让我们把值 10 放到我们的堆里。

>>> heapq.heappush(a,10)
>>> print(a)
[10, 41, 13, 77, 94, 52]

请注意,添加了 10,因为 10 是可用值中的最小值,所以它在第 0 个索引中。

现在让我们从我们的堆里跳出来。

>>> print(heapq.heappop(a))
10
>>> print(a)
[13, 41, 52, 77, 94]

当我们从堆中弹出时,它将从堆中移除最小值并返回它。现在值 10 已经不在我们的堆中了。

让我们看看 heappushpop()函数是如何工作的。让我们把值 28。

>>> print(heapq.heappushpop(a,28))
13
>>> print(a)
[28, 41, 52, 77, 94]

您可以看到 28 被推送到堆中,最小值 13 从堆中弹出。

现在让我们试试 heapreplace()函数。让我们将值 3 放入堆中。

>>> print(heapq.heapreplace(a,3))
28
>>> print(a)
[3, 41, 52, 77, 94]

您可以看到,最初最小的值 28 被弹出,然后我们的新值 3 被推入。新堆值 3 中的第 0 个索引。请注意 heappushpop()和 heapreplace()函数中 push 和 pop 操作顺序的不同。

如何在 Heapq 中使用对象?

在前面的例子中,我已经解释了如何将 heapq 函数用于整数等原始数据类型。类似地,我们可以使用带有 heapq 函数的对象来对复杂数据(如元组甚至字符串)进行排序。为此,根据我们的场景,我们需要一个包装类。考虑这样一种情况,您希望存储字符串,并根据字符串的长度对它们进行排序,从最短到最长。我们的包装类将如下所示。

class DataWrap:

    def __init__(self, data):
        self.data = data  

    def __lt__(self, other):
        return len(self.data) < len(other.data)

__lt__函数(它是比较运算符的运算符重载函数;>、≥、==、<和≤)将包含比较字符串长度的逻辑。现在让我们试着用一些字符串做一个堆。

# Create list of strings
my_strings = ["write", "go", "run", "come"]# Initialising
sorted_strings = []# Wrap strings and push to heap
for s in my_strings:
    heapObj = DataWrap(s)
    heapq.heappush(sorted_strings, heapObj)# Print the heap
for myObj in sorted_strings:
    print(myObj.data, end="\t")

打印堆中项目的输出如下。

go	come	run	write

注意最短的单词go在堆的前面。现在,您可以通过包装字符串来尝试其他 heapq 函数。

使用 Heapq 实现最大堆

我们可以使用 heapq 轻松实现最大堆。你所要做的就是改变__lt__函数中的比较运算符,将最大值排在前面。让我们用字符串和它们的长度来试试前面的例子。

class DataWrap:

    def __init__(self, data):
        self.data = data  

    def __lt__(self, other):
        return len(self.data) > len(other.data)# Create list of strings
my_strings = ["write", "go", "run", "come"]# Initialising
sorted_strings = []# Wrap strings and push to heap
for s in my_strings:
    heapObj = DataWrap(s)
    heapq.heappush(sorted_strings, heapObj)# Print the heap
for myObj in sorted_strings:
    print(myObj.data, end="\t")

注意长度比较在DataWrap类的__lt__函数中是如何变化的。打印这个堆中的项目的输出如下。

write	come	run	go

注意,现在最长的单词write在堆的前面。

最后的想法

我希望在使用 heapq 模块实现的过程中,这篇文章对您有所帮助。请随意使用提供的代码。

感谢您的阅读!

干杯!

参考

[1] heapq —堆队列算法— Python 3.8.3rc1 文档(https://docs.python.org/3/library/heapq.html)

推荐系统介绍- 1:基于内容的过滤和协同过滤

原文:https://towardsdatascience.com/introduction-to-recommender-systems-1-971bd274f421?source=collection_archive---------1-----------------------

格伦·卡斯滕斯-彼得斯在 Unsplash 上拍摄的照片

像网飞、亚马逊和 Youtube 这样的服务是如何向用户推荐商品的?

我们都用过像网飞、亚马逊和 Youtube 这样的服务。这些服务使用非常复杂的系统向他们的用户推荐最好的商品,以使他们的体验更好。但是,他们是如何实现如此伟大的系统的?在本文中,我们将看看这个问题的答案。

推荐人的组成程序:

推荐器通常有 3 个组成部分:

  1. 候选生成:这种方法负责在给定一个由数千个项目组成的大池的情况下,生成更小的候选子集推荐给用户。
  2. 评分系统:候选生成可以由不同的生成器完成,因此,我们需要标准化所有内容,并尝试给子集中的每个项目分配一个分数。这是由评分系统完成的。
  3. 重新排名系统:评分完成后,系统会考虑其他附加约束条件,以产生最终排名。

候选生成系统的类型:

  1. 基于内容的过滤系统
  2. 协同过滤系统

基于内容的过滤系统:基于内容的推荐系统试图猜测用户的特征或行为。

最后两栏动作片和喜剧片描述了电影的类型。现在,给定这些类型,我们可以知道哪些用户喜欢哪个类型,因此,我们可以根据他/她对该类型电影的反应来获得与该特定用户相对应的特征。

一旦我们知道了用户的喜好,我们可以使用生成的特征向量将他/她嵌入到嵌入空间中,并根据他/她的选择推荐他/她。在推荐过程中,相似性度量(我们稍后会谈到)是根据项目的特征向量和用户以前记录中的偏好特征向量来计算的。然后,推荐前几名。

基于内容的过滤在向一个用户推荐时不需要其他用户的数据。

协同过滤系统:协同不需要给出项目的特征。每个用户和项目都由一个特征向量或嵌入来描述。

它自己为用户和项目创建嵌入。它将用户和项目嵌入到同一个嵌入空间中。

它在推荐特定用户时会考虑其他用户的反应。它记录特定用户喜欢哪些项目,以及具有与他/她相似的行为和爱好的用户喜欢哪些项目,以向该用户推荐项目。

它收集用户对不同项目的反馈,并使用它们进行推荐。

用户-项目交互的来源

隐性反馈:根据用户的点击、搜索和购买等行为,记录用户的好恶。它们大量存在,但没有发现负面反馈。

显式反馈:用户通过对某个项目做出反应或对其进行评级等动作来指定他/她喜欢或不喜欢的东西。它有正反馈和负反馈,但数量较少

协同推荐系统的类型:

基于记忆的协同过滤(Memory-based collaborative filtering):主要是记住用户-项目交互矩阵,以及用户对它的反应,即用户对项目的评分。不存在这样的维度减少或模型拟合。主要是两个部分:

用户-用户过滤:在这种情况下,如果一个用户 A 的特征与另一个用户 B 相似,那么 B 喜欢的产品就会被推荐给 A。作为一种陈述,我们可以说,“喜欢与你相似产品的用户也喜欢那些产品”。所以这里我们推荐利用两个用户的相似性。

现在,如果一个用户 A 的行为像其他用户 B、C 和 D 一样,那么对于产品 x,A 的评级由下式给出:

其中 Rxu 是用户 u 给予 x 的评级,i=0 到 n 是表现出与 u 相似行为的用户。现在,所有 n 个用户与用户 u 的相似程度不同。因此,我们找到一个加权和来提供评级。

这里的权重是使用的相似性度量。

现在,用户在评级时表现出一些行为差异。一些是慷慨的评价者,其他的不是,即,可能一个用户在范围 3 到 5 中评价,而其他用户在 1 到 3 中评价。因此,我们计算用户提供的所有评分的平均值,并从 Ri 中减去该值,以便标准化每个用户的评分。

物品-物品过滤:这里,如果用户 A 喜欢一个物品 x,那么,在性质上与 x 相似的物品 y 和 z,那么 y 和 z 被推荐给用户。作为陈述,可以说“因为你喜欢这个,所以你也可能喜欢那些”。

这里也使用相同的等式

其中 R 是用户 u 给产品 x 的评分,它是 u 给类似产品 x 的评分的平均值。这里我们也取一个加权平均值

其中权重是产品之间的相似性。

相似性度量

它们是用于确定一个向量与给定向量相似程度的数学度量。

最常用的相似性度量:

  1. 余弦相似度:向量之间的余弦角。
  2. 点积:向量的余弦角和大小也很重要。
  3. 欧几里德距离:两个向量之间的元素平方距离
  4. 皮尔逊相似性:这是一个由下式给出的系数:

基于模型的协同过滤:这里不需要记住矩阵。从矩阵中,我们试图了解特定用户或项目的行为。我们使用降维或使用聚类算法来压缩大的交互矩阵。在这种类型中,我们拟合机器学习模型,并尝试预测用户会给一个产品多少评级。有几种方法:

  1. 聚类算法
  2. 基于矩阵分解的算法
  3. 深度学习方法

聚类算法:他们通常使用简单的聚类算法,如 K-最近邻算法,根据所使用的相似性度量来查找给定用户或项目嵌入的 K 个最近邻或嵌入。

基于矩阵分解的算法:

思路:像任何一个大数都可以分解成更小的数一样,用户-物品交互表或矩阵也可以分解成两个更小的矩阵,这两个矩阵也可以用来生成回交互矩阵。

因此,我们生成因素矩阵作为用户和项目的特征矩阵。这些特征矩阵充当每个用户和项目的嵌入。为了创建特征矩阵,我们需要降维。

说吧,

有 4 个用户和 5 个项目,用户和项目放置根据域 D1 说,流派如果项目是电影。我们可以说它们不能很好地分开,整个事情看起来非常一般化。

作者图片

因此,我们增加域的数量或添加一个域,在此基础上我们可以对用户和项目进行分类。

作者图片

现在,使用这两个域,我们可以很容易地对项目和用户进行适当的分类,因此,( x,y)对可以用作它们的特征向量或嵌入。因此,我们的矩阵是因式分解。

表 1

上面的交互表被转换成:

表 2

因此,我们的任务是找到(x,y)值,使表 2 中生成的数字尽可能接近实际的相互作用矩阵。一旦我们找到所有的(x,y)值,我们也可以找到丢失的值。现在,缺少值是因为用户没有对项目进行评级。所以,如果生成的值很好,我们可以推荐给用户。这里只显示了 x 和 y 两个域,实际上可以有非常多的域。域数越多,特征向量越大,嵌入空间越大。

现在,特征向量中的特征数量取决于有多少个域或特征(一个域中表示一个特征),我们需要考虑清楚地表示用户和项目。因此,我们基本上需要找到用户和项目分布的主要组成部分。寻找主成分意味着降维,即使用尽可能少的特征清楚地表示分布。

降维可以通过几种方法实现:

  1. 奇异值分解:奇异值分解
  2. PMF:概率矩阵分解
  3. NMF:非负矩阵分解

如果我们观察表 2,x1.x6+y1.y6 是项目 1 嵌入向量乘以[ x6,y6 ]的点积,即用户 1 的嵌入向量的转置。

所以,表 2 中的每个单元格,

用户对项目 u 的评级 v= U .转置(V)

降维:创建特征向量

表 3

1 表示用户对项目做出了反应或对其进行了评级,0 表示用户没有做出反应。这里 1 的数量远大于 0 的数量。在现实世界中,实际上 0 的数量远大于 1 的数量。所以,它们大多是稀疏矩阵。

我们的目标函数,也就是我们这里需要最小化的函数是:

r(i,j)=1 可以从表 3 中找到。这暗示了已经对项目 I 做出反应或评级的用户 j。如果 r(i,j)=0,则用户 j 没有对项目 I 进行评级

因此,这意味着我们正在尝试最小化表 1 中给定的原始评级 A(i,j)和从表 2 中获得的值之间的差异,乘以用户和项目的特征向量。这有助于优化特征向量。

对于奇异值分解,

其中,Aij 是表 1 中的小区额定值,u,v 是算法产生的值。现在,由于矩阵的稀疏性,奇异值分解在这里表现不佳。

SVD 由 R = UσV 给出,其中 U 是 n×d 维的项目矩阵,即总共 n 个项目,V 具有 m×d 维,即总共 m 个用户,σ是 d×d 对角矩阵,用于乘法兼容性。d 是每个用户和项目的特征向量的大小。

在奇异值分解中,矩阵分解为

作者图片

其中 N 是项目的数量,M 是用户的数量,d 是特征向量的维度或大小。

中间的是对角向量。

NMF: 非负矩阵分解之所以如此,是因为这里的矩阵没有负的分量,即评分永远不可能是负的。未评级的被认为是 0

表 4

因此,NMF 只使用观察到的或评级的。因此,它将函数修改为:

这对于稀疏矩阵表现得更好。

它将向量分解为:

作者图片

其中 N 是用户数量,M 是项目数量,d 是特征向量的维度或大小。

矩阵分解还有另一种形式。叫做加权矩阵分解。它将损失函数修改为:

这里,我们包括两个评级项 w0 和 w1,并试图优化评级项和非评级项。未评级的被认为是零,所以,((Ui。Vj)-0)2 用于优化非额定或零个。W0 和 W1 是超参数,我们需要谨慎选择。

最小化目标函数

最常用的最小化算法包括:

加权交替最小二乘法:如果我们专注于这个问题,我们可以发现两个独立的问题:找到最佳描述项目的最佳嵌入,以及最佳描述用户的最佳嵌入。

现在,让我们分解并逐个查看问题,

  1. 如果我们有项目的特征矩阵或向量,就像我们对基于内容的系统所做的那样,我们可以通过注意用户如何反应或评价具有不同特征向量的项目来容易地找到用户嵌入或特征集。

所以,我们的目标函数变成了:

其中 Vj 是用户的特征向量,λ项是用于优化用户嵌入的正则化项,给定每个项目 I 的项目嵌入或特征向量 Ui

2.现在,如果我们有了用户特征或知道用户如何行为或反应,我们就可以从每个用户对项目的反应或评价中找到项目的最佳特征或嵌入向量。

我们的目标函数是:

其中 Ui 是项目的特征向量。我们需要找到给定用户向量 Vj 的 Ui。

现在,在矩阵分解中,我们需要找到 U 和 v。因此,WALS 算法通过在上述两个方程之间交替来工作。

  • 固定 U 并求解 v。
  • 定 V,解 u。

现在,问题是这两个方程不是同时凸的。要么等式 1 是凸的,要么等式 2 是凸的,但不是组合的。因此,我们在这里不能达到全局最小值,但是已经观察到,达到接近全局最小值的局部最小值给了我们在全局最小值处的优化结果的良好近似。所以,这个算法给了我们一个近似的结果。

挑战:

  1. 给定(用户,项目)对的模型预测是相应嵌入的点积。因此,如果在训练期间没有看到一个项目,系统就不能为它创建嵌入,也不能用这个项目查询模型。这个问题通常被称为冷启动问题

这个问题通常用两种方法解决:

  1. WALS 的投影
  2. 启发生成新鲜项目的嵌入

2.侧面特征很难包括在内。次要特征是那些可能影响推荐的特征,例如对于一部电影,U/PG 分级可以是次要特征或国家。

结论

在本文中,我们研究了两种基本类型的过滤机制。在我的下一篇文章中,我将谈论基于深度学习的协同过滤,并尝试通过一些应用。

快乐学习!!!。

posted @ 2024-10-15 13:41  绝不原创的飞龙  阅读(124)  评论(0)    收藏  举报