介绍 PCFGs,最左边的推导,乔姆斯基 NF,CKY 算法和许多其他可怕的单词变得简单
写这篇文章的想法是非常自发的,只要我现在工作的主要领域是命名实体识别和从原始多语言文本中提取高级数据;概率上下文无关文法绝对不是我感兴趣的类型(二叉树结构一点也不吸引我),我也不是用 PCFGs 开发一些应用程序的专家。然而,了解这样一个概念对每个自然语言处理科学家来说都是一个很好的实践,所以我为什么不应该花一些时间来研究 PCFG 的基本思想和细节呢?
请不要期望这篇文章是对上下文无关语法世界的“深度探索”,并解释先进的方法论;这只是对想知道它如何工作以及我们在哪里使用它的人的介绍。
上下文无关文法的定义
基本上,我们可以将 CFG 视为元组,由 4 个元素组成: G = (N,E,R,S) ,其中
- N 是所有非终端符号的集合(在我们的例子中是 POS 标签);
- E 是所有终端符号(单词)的集合;
- R 是以下形式的规则集:
- S 是卓越的开始符号。
如果规则由 2 个元素组成(非终结来自 N 和终结或非终结来自 N 和 E 的并集),那么它是一元规则。如果规则由左边的非终结符和任意长度的终结符和非终结符的序列组成,那么它是一个混合规则。
解析树的定义(最左边的派生)
如果给我们一个上下文无关的语法,那么最左边的派生是来自 E* (由来自 E 的字符串组成的所有可能序列的集合)的一个字符串序列,它形成一个句子。我们正在为索引为 i 的每个 s 检索该字符串,方法是获取索引为 i-1 的 s ,并挑选 N 中最左边的非终结符 X ,并用一些 β 更新它,其中我们在 R 中有一个规则 X → β。
解析树不是一个复杂的概念,但是它们有不同的重要术语,值得解释和讨论。
- 每个最左边的派生总是以从 E*开始的索引为 n 的字符串 s 结束;
- s 用指数 n 表示导数的产率;
- 如果至少有一个 yield 为 s,则来自 E的字符串 s 在语言中。*
概率解析树的定义(概率上下文无关文法)
这个概念解释起来也很简单,但是它背后有很多符号背景。让我们假设,我们的上下文无关文法是不明确的:给定一个上下文无关文法,我们可以有许多产出。对于给定的语法,我们如何考虑什么产量是最好的?正确的答案总是一个——概率。
- 索引为 G 的 T 是文法 G 下所有可能的最左导子的集合;
- 对于从 T 到索引为 G 的任何导子 T,我们写 yield(t)来表示来自 E的字符串 s,这是 T(T 中的单词序列)的 yield;*
- 对于来自 E的给定句子 s,我们用 T(s)来指代集合:*
- 如果句子 s 至少有一棵解析树,我们说它是语法的。
我们的主要想法是扩展我们的定义,给出可能导数的概率分布。
求导的概率大于零的条件要满足(我们不能有求导是很符合逻辑的,这是完全不可能的):
而且全概率的条件也要满足(概率的和法则;不同的派生是不同的事件,它们一起形成一个结果):
现在,有了这 2 个公式,我们可以将概率上下文无关文法定义为 G = (N,E,R,S) + set(q (α→β))。
这个集合中的每一个元素都是在一个最左边的推导中选择规则α→β的条件概率 q (α→β),假设被展开的非终结点是 α。
现在,我们可以用新的符号以这种方式重新制定全概率规则(现在,我们将 α 视为我们可以拥有的任何最左侧推导的根):
关于导数大于零的概率的想法也保持不变,只是替换了相同的概念:
给定规则集 q (α→β)的整个解析树的概率由联合概率规则定义:
从语料库中导出 PCFG 为了从预定义的语料库中生成先前的概率上下文无关语法,我们需要规则 q (α→β)上的一些概率分布。为了得到它们,我们可以使用最大似然估计,公式如下:
这基本上是条件概率估计的简单定义。我们可以使用拉普拉斯平滑和其他技术来更好地计算我们的概率,这取决于我们正在处理的任务和语料库。
乔姆斯基范式
这种范式背后的思想是,我们的 PCFGs 中使用的每个规则都应该采用以下形式之一:
它只意味着这样一个事实:如果一个节点都不是来自 N 的终端,那么它可以有两片叶子;如果它是来自 E 的终端(单词),那么它可以有一片叶子。
CKY 算法
我认为这个概念是光子晶体光纤光栅理论中最复杂的部分;然而,它的输入是解析树,它显示了我们试图从给定语法的句子中找到的句法依赖。
CKY 算法的目标是找到给定句子和 PCFG 的最可能的分析树;它通过逐步选择最可能的树结构来解决这个问题。
我觉得前面的伪代码不是很好理解,所以我尽量在上面做些小说明。
该算法可以非正式地分为两步:初始化和优化。
初始化部分意味着从语法上给我们正在处理的句子中的每个非终结符赋值;如果有一个以上的终端导致当前的非终端,那么我们要记住他们两个。因此,想象中的“三角形表”的底部填充了起始终端正上方的非终端。
优化部分是 3 个嵌套 for 循环的结构:对于我们正在处理的每个跨度,对于句子的每个开始和结束(结束被定义为开始+跨度)我们正在寻找非结束,这是最可能的树的根,它支配从开始到结束的范围内的子元素(在前面的循环中计算)。使用从+ 1 开始到-1 结束范围的分割点递归地找到最大非终结符(以找到所有可能的单词组合)。
CKY 有不同的变体,可能定义选择非终结点是选择拆分点之前的前一步,以及相反的情况;作者可能会声称我们只是在寻找一个解析树的结构,但是使用 CKY,我们也可以找到最可能的 PCFG 的概率。
结论
我希望这篇文章对不熟悉创建解析树的读者有用,以便理解它的语法结构并能够估计它的概率;我不认为这篇文章对有经验的数据科学家和 NLP 专家有帮助。
说到我的个人经验(我没有很多年的经验),我可以说我从来没有见过真正的解析树在真实数据上运行;人们应该始终明白,这个概念作为理论基础是重要的,但在实践中很少使用。
我见过的解析树的最佳实现来自 NLTK 它的所有工作都做得很好(老实说,这是一个科学软件包应该做的)。
感谢任何形式的反馈,为新的帖子和像这样的小笔记提供了很多灵感。
推荐系统简介
协同过滤方法:最近邻和矩阵分解
“我们正在离开信息时代,进入推荐时代。”
像许多机器学习技术一样,推荐系统基于用户的历史行为进行预测。具体来说,它是基于过去的经验来预测用户对一组项目的偏好。为了建立推荐系统,最流行的两种方法是基于内容和协同过滤。
基于内容的方法需要项目自身特征的大量信息,而不是使用用户的交互和反馈。例如,它可以是电影属性,如类型、年份、导演、演员等。或者可以通过应用自然语言处理提取的文章的文本内容。协同过滤,另一方面,除了用户对一组项目的历史偏好之外,不需要其他任何东西。因为它是基于历史数据的,所以这里的核心假设是,过去同意的用户将来也会同意。就用户偏好而言,它通常由两类来表达。显式评分,是用户给一个项目的评分,如泰坦尼克号的 5 颗星。这是来自用户的最直接的反馈,表明他们有多喜欢一个项目。隐性评分,间接暗示用户偏好,如页面浏览量、点击量、购买记录、是否听某首音乐曲目等等。在这篇文章中,我将仔细研究一下协同过滤,它是推荐系统的一个传统而强大的工具。
最近邻域
协同过滤的标准方法被称为最近邻算法。有基于用户的 CF 和基于物品的 CF,我们先来看基于用户的 CF 。我们有一个 n × m 的收视率矩阵,用户 uᵢ,i = 1,…n 和项目 pⱼ,j=1,…m。现在,如果目标用户 I 没有观看/评价项目 j,我们想要预测评价 rᵢⱼ。该过程是计算目标用户 I 和所有其他用户之间的相似性,选择前 x 个相似用户,并且取这些具有相似性的 x 个用户的评价的加权平均值作为权重。
Source: https://dzone.com/articles/recommendation-engine-models
虽然不同的人在给予评级时可能有不同的基线,但有些人倾向于给予高分,有些人即使对项目满意也非常严格。为了避免这种偏差,我们可以在计算加权平均值时减去每个用户对所有项目的平均评分,并将其添加回目标用户,如下所示。
计算相似度的两种方法是皮尔逊相关和余弦相似。
基本上,这个想法是找到与你的目标用户最相似的用户(最近的邻居),并对他们对某个项目的评分进行加权,作为目标用户对该项目评分的预测。
在对项目和用户本身一无所知的情况下,当两个用户给同一个项目相似的评价时,我们认为他们是相似的。类似地,对于基于项目的 CF ,当两个项目从同一个用户收到相似的评级时,我们说它们是相似的。然后,我们将通过计算目标用户对大多数 X 个相似项目的评分的加权平均值来对该用户的项目进行预测。基于项目的 CF 的一个关键优势是稳定性,即给定项目的评分不会随着时间的推移而发生显著变化,这与人类的口味不同。
Source: https://medium.com/tiket-com-dev-team/build-recommendation-engine-using-graph-cbd6d8732e46
这种方法有相当多的局限性。当邻居中没有人评价你试图为目标用户预测的项目时,它不能很好地处理稀疏性。此外,随着用户和产品数量的增长,计算效率也不高。
矩阵分解
由于稀疏性和可扩展性是标准 CF 方法面临的两个最大挑战,因此出现了一种更先进的方法,将原始稀疏矩阵分解为具有潜在因子/特征和较少稀疏性的低维矩阵。那就是矩阵分解。
除了解决稀疏性和可伸缩性的问题,还有一个直观的解释为什么我们需要低维矩阵来表示用户的偏好。一位用户给电影《阿凡达》、《地心引力》和《盗梦空间》打了高分。它们不一定是 3 个独立的意见,而是表明该用户可能喜欢科幻电影,并且可能有更多该用户喜欢的科幻电影。与特定电影不同,潜在特征是由更高层次的属性来表达的,在这种情况下,科幻类别是潜在特征之一。矩阵分解最终给我们的是,一个用户与一组潜在特征有多大程度的契合,一部电影与这组潜在特征有多大程度的契合。与标准的最近邻相比,它的优势在于,即使两个用户没有对任何相同的电影进行评级,如果他们分享相似的潜在品味,仍然有可能找到他们之间的相似性,这也是潜在的特征。
要了解一个矩阵如何分解,首先要了解的是奇异值分解(SVD) 。基于线性代数,任何实矩阵 R 都可以分解为 3 个矩阵 U、σ和 V。继续使用电影示例,U 是 n × r 用户潜在特征矩阵,V 是 m × r 电影潜在特征矩阵。σ是包含原始矩阵的奇异值的 r × r 对角矩阵,简单地表示特定特征对于预测用户偏好有多重要。
要通过降低绝对值对σ值进行排序,并将矩阵σ截断到前 k 维(k 个奇异值),我们可以将矩阵重构为矩阵 A。k 的选择应确保 A 能够捕捉原始矩阵 R 内的大部分方差,因此 A 是 R 的近似值,A≈R。A 和 R 之间的差异是期望最小化的误差。这正是主成分分析的思想。
当矩阵 R 稠密时,U 和 V 可以很容易地解析分解。然而,一个电影评级矩阵是超级稀疏的。尽管有一些填补缺失值的插补方法,但我们将求助于一种编程方法来处理这些缺失值,并找到因子矩阵 U 和 V。我们不是通过 SVD 对 R 进行因子分解,而是尝试直接找到 U 和 V,目的是当 U 和 V 相乘时,输出矩阵 R’是 R 的最接近的近似值,而不再是稀疏矩阵。对于推荐系统,这种数值近似通常通过非负矩阵分解来实现,因为评级中没有负值。
参见下面的公式。查看特定用户和项目的预测评级,项目 I 被记为向量 qᵢ,而用户 u 被记为向量 pᵤ,使得这两个向量的点积是用户 u 对项目 I 的预测评级
我们如何找到最优的 qᵢ和 pᵤ?像大多数机器学习任务一样,损失函数被定义为最小化错误成本。
rᵤᵢ是来自原始用户项目矩阵的真实评级。优化过程是寻找由向量 pᵤ组成的最优矩阵 p 和由向量 qᵢ组成的最优矩阵 q,以最小化预测收视率 rᵤᵢ’和真实收视率 rᵤᵢ.之间的平方和误差此外,L2 正则化已被添加,以防止用户和项目向量的过度拟合。添加偏差项也很常见,它通常有 3 个主要部分:所有项目的平均评级μ,项目 I 的平均评级减去μ(记为 bᵤ),用户给出的平均评级 u 减去 u(记为 bᵢ).
优化
一些优化算法已被广泛用于解决非负因式分解。备选最小二乘法就是其中之一。由于在这种情况下损失函数是非凸的,所以没有办法达到全局最小值,但它仍然可以通过找到局部最小值来达到很好的近似。替代的最小二乘法是保持用户因子矩阵不变,通过对损失函数求导并将其设置为 0 来调整项目因子矩阵,然后在调整用户因子矩阵的同时设置项目因子矩阵不变。通过来回切换和调整矩阵来重复该过程,直到收敛。如果您应用 Scikit-learn NMF 模型,您将看到 ALS 是默认的求解器,也称为坐标下降。Pyspark 还提供了非常简洁的分解包,为 ALS 本身提供了更多的调整灵活性。
一些想法
协同过滤为推荐系统提供了强大的预测能力,同时需要最少的信息。然而,它在某些特定情况下有一些限制。
首先,潜在特征所表达的潜在品味实际上是不可解释的,因为元数据没有与内容相关的属性。以电影为例,在我的例子中,它不一定是像科幻那样的类型。可以是配乐有多励志,剧情有多好等等。协同过滤缺乏透明度和这一级别的信息的可解释性。
另一方面,协同过滤面临冷启动。当一个新的项目出现时,直到它必须被大量的用户评级,该模型才能够做出任何个性化的推荐。类似地,对于尾部没有获得太多数据的项目,模型倾向于给它们较少的权重,并通过推荐更受欢迎的项目来产生受欢迎程度的偏差。
使用集成算法来构建更全面的机器学习模型通常是一个好主意,例如通过添加一些可解释的关键词维度来组合基于内容的过滤,但我们应该始终考虑模型/计算复杂性和性能改善有效性之间的权衡。
统计测试介绍——谁想成为一名程序员?
在 kaggle 闲逛时,我遇到了 2016 年新编码器调查数据集。这是一项针对学习编码的人的调查。
该调查包括一个问题,询问参与者他们感兴趣的工作角色是什么。我很好奇,想知道一个新程序员的年龄和他梦想的工作角色之间是否有联系。
在这篇文章中,我将尝试回答这个问题。这篇文章将是一篇技术文章,我将带你浏览数据探索,如何处理我们的研究问题,以及为了找到答案可以使用哪些统计测试。
首先,让我们导入一些东西:
import numpy as np
import pandas as pd
import scipy.stats
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inlinedata = pd.read_csv('2016-FCC-New-Coders-Survey-Data.csv')
对于我们的研究问题,没有说明年龄的受访者对我们来说没有价值。然而,那些指定了年龄但没有指定工作角色的受访者确实给了我们关于新程序员年龄的一般信息。
data = data[data['Age'].notnull()]
data['JobRoleInterest'] = data['JobRoleInterest'].fillna('unspecified').map(lambda job: job.strip())
让我们来考察一下受访者的大致年龄:
data['Age'].plot.hist(title='ages (N=%d, mean=%.2f, median=%.2f)' % (len(data), data['Age'].mean(), data['Age'].median()),
bins=100)
我们可以看到数据看起来几乎正常。平均值大于中位数,根据非参数偏度定义,这意味着分布具有右偏度。这意味着学习编程的老年人比年轻人多(平均年龄约为 29 岁)。
有趣的是,当我写这篇文章的时候,我的妻子也在学习编码;她 29 岁,是平均年龄。我想这会帮助我记起…
向下钻取
让我们探讨一下受访者群体的平均年龄,每个群体都是由感兴趣的工作角色定义的。
average_ages = pd.DataFrame([{
'job': group,
'N': len(data.loc[rows]),
'average age': data.loc[rows]['Age'].mean()
} for group, rows in data.groupby('JobRoleInterest').groups.items()]).sort_values(by='average age')
sns.barplot(data=average_ages, x='average age', y='job', hue='N', palette='Blues_d')
每个组都有一个长度等于该组平均年龄的条形。组越大,条形的颜色越浅。
我选择关注质量保证工程师团队。他们的平均年龄比其他群体大,大约 32 岁。理解这种影响是否是由于偶然,或者也许成为 QA 工程师的愿望更有可能与平均年龄较大的人联系在一起是很有趣的。
我来解释一下“由于偶然”是什么意思。请记住,我们的数据有限。它只讲述了一小部分新编码者的故事。具体来说,我们只有 91 个 QA 工程师的数据。事实上,有更多的新程序员想成为 QA 工程师:有些人没有参与调查,有些未来的新程序员甚至还没有开始学习编码。32 年是新的编码员 QA 工程师样本的意思是。我们很想知道新程序员 QA 的人口平均数是否大于其他新程序员的人口平均数。我们没有全部人口的数据,所以我们能做的最好的事情就是估计他们的平均值。我们通过使用样本均值来实现这一点。样本均值是一个随机变量;这取决于我们得到的样品。我们可以得到一些 QA 工程师的其他样本,样本均值会有所不同。另一方面,总体均值是分布的一个非随机参数。
给定我们拥有的新编码样本,有两种互补的可能性:
- QA 群体的平均年龄等于一般新编码者群体的平均年龄。
- 他们是不同的。
样本支持第二个选项,但这可能是偶然的(尤其是因为 QA 样本量很小)。接下来,我们将使用统计测试来量化观察到这种偶然差异的可能性。
统计框架
对于外行读者来说,许多统计测试的工作方式如下:首先陈述一个零假设,这是可以描述这个世界的默认选项。在我们的例子中,无效假设是 QA 工程师的平均年龄和其他新程序员的平均年龄没有区别。然后,提出另一个假设。在我们的情况下,另一种选择是差异确实存在。然后,计算检验统计量(数据的函数)。假设零假设为真,检验统计量的分布是已知的,并且可以计算观察检验统计量的现有值的概率。这个概率叫做 p 值。如果 p 值小于我们在进行实验之前决定的显著性水平(例如 0.01),则零假设被拒绝,取而代之的是替代假设。
z 检验
假设年龄呈正态分布,我们可以使用 Z 检验。请注意,即使它们不是正态分布,我们也可以利用中心极限定理,并利用平均年龄近似正态分布的事实。
如果我们知道平均年龄的标准偏差,我们可以通过以下方式归一化平均年龄:
x̄是观察到的平均年龄。μ是假设零假设为真时的预期平均年龄。在我们的例子中,我们选择一般新编码者样本的平均年龄 29.18 为μ。注意,有更好的估计μ的方法,也有更合适的统计检验,例如双样本 T 检验,为了简单起见,我选择不在本文中描述。为了简单起见,我将坚持 29.18。因为我有很多数据,我认为这是一个足够好的估计。
Z 是一个标准的正态随机变量:Z∞N(0,1)。因此,给定 x̄的观测值,我们可以计算它的概率,看看它是否低于一个合理的阈值。如果是的话——我们将拒绝无效假设。
z 检验假设我们知道σ。我们不知道。不要绝望,测试救援!
t 检验
t 检验和 Z 检验一样,区别是不知道σ。它的工作原理如下:
s 是年龄的样本标准差。s/√N 为平均年龄的样本标准差(其中 N 为样本数)。你可以在这里阅读它是如何产生的。
您可以看到该统计数据与在 Z 测试中计算的数据非常相似…T 统计数据根据 T 分布进行分布。每当一个正态分布的随机变量的方差未知时,就会出现 t 分布。
它有一个参数叫做自由度。我不会对此进行详细说明,但直观地说,它捕捉了用于估计参数的数据量。在我们的例子中,σ是被估计的参数,自由度是 n1。
随着自由度接近无穷大,t 分布接近正态分布。
我们将使用scipy
来计算这个概率:
qa = average_ages[average_ages['job'] == 'Quality Assurance Engineer'].iloc[0]
t_score = float(qa['average age'] - data['Age'].mean()) / (data['Age'].std() / np.sqrt(qa['N']))
degrees_of_freedom = qa['N'] - 1
p_value = 1 - scipy.stats.t(df=degrees_of_freedom).cdf(t_score)
print 'The p-value is', p_value>>> The p-value is 0.000551459304572
这个数字相当小。这意味着 QA 工程师平均年龄与总人口平均年龄的偏差不到百分之十的概率是由于偶然。如果我们选择 0.01 的显著性水平——这是一个常见的选择,我们会拒绝零假设。
让事情变得复杂一点,你应该注意到我刚才做的叫做单侧检验:我们计算了观察到大于或等于观察值的 T 值的概率。我们实际上关心两个方向上的差异:如果 QA 工程师的平均年龄明显小于预期值(零假设),这也将是有趣的。在 T 检验中,通过将计算出的 p 值乘以 2(由于分布的对称性)来检验两个方向上的显著差异,从而得出
print "The two sided test's p-value is", p_value * 2>>> The two sided test's p-value is 0.00110291860914
仍然重要…
模拟
统计学家喜欢统计测试。它们功能强大,但有两大缺点:
- 他们对数据进行假设。在我们的例子中,样本平均年龄并不正常。近似正态,所以 T 检验结果是近似值。不过还是很不错的一个…
- 有时他们会让你测试一些类似的东西,但不完全是你想要的。在我们的例子中,这不是真的:我们感兴趣的是平均差异,而这正是 T 检验所提供的。如果我们想测试一些更复杂的东西,而没有对用例进行经典的统计测试,我们会有麻烦。
为了解决这两个问题,我们可以使用模拟。我们首先计算观察数据的一些统计数据——就像以前做的那样。我们没有计算观察统计值的概率,而是模拟了许多假设零假设为真的实验。我们计算实验中产生一个统计量的部分,这个统计量至少和我们以前计算的统计量一样极端。
让我解释一下为什么模拟有效:如果一个人选择使用假设得到满足的统计检验,计算出的 p 值就是观察到一个统计数据的真实概率,该统计数据至少与从实际数据计算出的统计数据一样极端,假设零假设为真。我们可以把它当作伯努利试验,其中 p 值是成功的概率。执行模拟就像多次运行伯努利试验。运行模拟的目标是估计成功的概率,即 p 值。使用 MLE 方法,我们简单地估计这个概率是成功的分数。随着模拟次数接近无穷大,该估计量接近真实 p 值。
让我们在我们的例子中尝试这种方法:零假设表明 QA 工程师的平均年龄和普通新编码员的平均年龄没有区别。这意味着 QA 工程师小组观察到的平均年龄也可以被新编码员的任何随机小组观察到。所以这正是我们要做的:我们将随机抽取一个与 QA 工程师小组规模相同的小组,并计算他们的平均年龄与一般新编码员平均年龄之间的差异:
observed_diff = abs(qa['average age'] - data['Age'].mean())
num_of_simulations = 100000
num_of_extreme_values = sum(abs(data.sample(n=qa['N'])['Age'].mean() - data['Age'].mean()) >= observed_diff
for _ in range(num_of_simulations))
p_value = float(num_of_extreme_values) / num_of_simulations
print 'The p-value is', p_value>>> The p-value is 0.0007
我们得到了相似的结果,但是有点不同。请注意,我们运行的模拟越多,结果就越精确(它将趋向于真实的 p 值)。
为什么它不同于 T 检验方法?因为 T 检验假设数据是正态的,而它只是近似正态的。
在过去,计算机速度很慢,计算能力很昂贵,所以运行模拟没有太大意义。然而,如今它确实有意义——至少在某些情况下。这是一个很好的方法,应该在需要的时候使用。这里的是一篇很棒的帖子,它进一步讨论了模拟方法。
多重测试问题
你们中的一些人可能已经注意到我的分析是有问题的:它引发了多重测试问题。只有在检查数据后,我才注意到 QA 工程师的平均年龄高于其他组的平均年龄。然后我做了一个统计测试,看看这是否是由于偶然。问题是,因为我们有多个组,我们检查的组越多,一个组在平均年龄上有显著差异的可能性就越大。有很多方法可以解释这个问题。一种选择是在不同于提出假设的数据集上测试假设。其他选项包括相应地调整显著性水平。
含义
这个分析有什么含义吗?首先要区分统计意义和实际意义。这可能有统计学意义:观察到的数据不仅仅是偶然的结果,差异确实存在。
实际意义意味着我们观察到的差异具有实际意义:人们可以据此采取行动。实际意义取决于手头的问题。
在我们的案例中,我认为与观察到的平均年龄差异没有太大关系……如果一般新程序员的平均年龄是 20 岁,而 QA 是 40 岁,我们可以建议新程序员的学校应该改变 QA 轨道的时间表,因为 QA 学生可能有孩子在家里等着他们。
【www.anotherdatum.com】这个帖子最初是我在 发的。
为 UCI 机器学习库引入简单直观的 Python API
为 UCI 机器学习门户引入简单直观的 API,用户可以在其中轻松查找数据集描述,搜索他们感兴趣的特定数据集,甚至下载按大小或机器学习任务分类的数据集。
介绍
UCI 机器学习数据集库是机器学习教育学领域的一个传奇。对于初学者和高级学习者来说,这都是一个*‘逛商店’*。它是数据库、领域理论和数据生成器的集合,由机器学习社区用于机器学习算法的经验分析。这个档案是 1987 年由加州大学欧文分校的大卫·阿哈和其他研究生创建的 ftp 档案。从那时起,它就被世界各地的学生、教育工作者和研究人员广泛用作机器学习数据集的主要来源。作为档案影响的一个标志,它被引用了 1000 多次,使其成为所有计算机科学中被引用次数最多的 100 篇“论文”之一。
也就是说,导航门户可能会有点令人沮丧和耗时,因为对于您感兴趣的数据集,没有简单直观的 API 或下载链接。您必须跳过多个页面才能进入您正在寻找的原始数据集页面。此外,如果您对特定类型的 ML 任务(例如回归或分类)感兴趣,并希望下载与该任务对应的所有数据集,则没有简单的命令来完成此任务。
我很高兴为 UCI ML 门户网站推出一个简单直观的 API,用户可以在这里轻松查找数据集描述,搜索他们感兴趣的特定数据集,甚至下载按大小或机器学习任务分类的数据集。
从这里下载/克隆
这是一个麻省理工学院许可的开源 Python 3.6 代码库,它提供了允许用户以交互方式使用 UCI ML 数据集的函数和方法。从我的 Github 页面这里 下载/克隆/分叉代码库。
必需的包/依赖项
运行这段代码只需要三个广泛使用的 Python 包。为了便于安装这些支持包,我的 repo 中包含了 setup.bash 和 setup.bat 文件。只要在您的 Linux/Windows shell 中执行它们,您就准备好了!
怎么跑?
确保你连接到互联网:-)然后,只需下载/克隆 Gitgub 回购,确保有支持包安装。
**git clone https://github.com/tirthajyoti/UCI-ML-API.git {your_local_directory}**
然后转到您克隆 Git 的your_local_directory
,在您的终端上运行下面的命令。
**python Main.py**
将打开一个菜单,允许您执行各种任务。这是菜单的截图,
当前支持的特性和功能
目前实施了以下功能…
- 通过搜索整个门户,构建包含数据集的名称、描述和 URL 的本地数据库
- 通过爬取整个门户来构建数据集的名称、大小、机器学习任务的本地数据库
- 搜索并下载特定数据集
- 下载前几个数据集
- 打印所有数据集的名称
- 打印所有数据集的简短描述
- 搜索数据集的单行描述和网页链接(了解更多信息)
- 根据数据集的大小下载数据集
- 基于与数据集相关联的机器学习任务下载数据集
示例(搜索和下载特定数据集)
例如,如果您想下载著名的数据集 Iris,只需从菜单中选择选项 3,输入存储的本地数据库的名称(以加快搜索速度),瞧!您将下载 Iris 数据集并将其存储在目录中名为“Iris”的文件夹中!
示例(使用特定关键字搜索数据集)
如果您通过选择选项 7 使用关键字进行搜索,那么您将得到所有数据集的简短的一行摘要,这些数据集的名称与您的搜索字符串匹配(甚至部分匹配)。您还将获得这些结果的相关网页链接,这样,如果您愿意,您就可以进一步探索它们。下面的屏幕截图显示了使用术语Cancer
进行搜索的示例。
如果想绕过简单的 API,使用低级功能
如果您想绕过简单的用户 API,使用底层功能,欢迎您这样做。这是它们的概要。首先,导入必要的包,
from UCI_ML_Functions import *
import pandas as pd
read_dataset_table()
:从 URL“https://archive . ics . UCI . edu/ml/datasets . html”中读取数据集的表格,并对其进行进一步处理,以进行清理和分类。
clean_dataset_table()
:接受原始数据集表格(DataFrame 对象)并返回一个清除了未知数量样本和属性的条目的清理版本。还使指示与数据集相关联的主要机器学习任务的“默认任务”类别列合理化。
build_local_table(filename=None,msg_flag=True)
:读取 UCI ML 门户并构建一个包含名称、大小、ML 任务、数据类型等信息的本地表。
filename
:用户可以选择的可选文件名。如果未选择,程序将选择一个默认名称(“UCI 表. csv”)。msg_flag
:控制详细程度。
build_dataset_list()
:浏览 UCI ML 数据集页面,建立所有数据集的列表。
build_dataset_dictionary()
:浏览 UCI ML 数据集页面,建立一个包含所有数据集名称和描述的字典。还存储对应于数据集的唯一标识符。下载器功能需要该标识符字符串来下载数据文件。通用名称不起作用。
build_full_dataframe()
:构建包含所有信息的数据框架,包括下载数据的 url 链接。
build_local_database(filename=None,msg_flag=True)
:读取 UCI ML 门户网站,并建立一个本地数据库,其中包含名称、摘要、数据页面 URL 等信息。
filename
:用户可以选择的可选文件名。如果未选择,程序将选择一个默认名称(“UCI 数据库. csv”)。msg_flag
:控制详细程度。
return_abstract(name,local_database=None,msg_flag=False)
:通过搜索给定的name
,返回特定数据集的一行描述(以及获取更多信息的网页链接)。
local_database
:本地存储(即在同一目录下)的数据库(CSV 文件)的名称,其中包含有关 UCI ML repo 的所有数据集的信息。msg_flag
:控制详细程度。
describe_all_dataset(msg_flag=False)
:调用build_dataset_dictionary
函数并打印所有数据集的描述。
print_all_datasets_names(msg_flag=False)
:调用build_dataset_dictionary
函数并从中打印所有数据集的名称。
extract_url_dataset(dataset,msg_flag=False)
:给定数据集标识符,此函数提取实际原始数据所在页面的 URL。
download_dataset_url(url,directory,msg_flag=False,download_flag=True)
:从给定 url 中的链接下载所有文件。
msg_flag
:控制详细程度。download_flag
:默认为真。如果设置为 False,则仅创建目录,但不启动下载(出于测试目的)。
download_datasets(num=10,local_database=None,msg_flag=True,download_flag=True)
:下载数据集,放在以数据集命名的本地目录下。默认情况下,仅下载前 10 个数据集。用户可以选择要下载的数据集数量。
msg_flag
:控制详细程度。download_flag
:默认为真。如果设置为 False,则仅创建目录,但不启动下载(出于测试目的)。
download_dataset_name(name,local_database=None,msg_flag=True,download_flag=True)
:通过搜索给定的名称下载特定的数据集。
local_database
:本地存储(即在同一目录下)的数据库(CSV 文件)的名称,其中包含有关 UCI ML repo 的所有数据集的信息。msg_flag
:控制详细程度。download_flag
:默认为真。如果设置为 False,则仅创建目录,但不启动下载(出于测试目的)。
download_datasets_size(size='Small',local_database=None,local_table=None,msg_flag=False,download_flag=True)
:下载满足“大小”标准的所有数据集。
size
:用户想要下载的数据集的大小。可能是以下任何一种:“小号”、“中号”、“大号”、“超大号”。local_database
:本地存储的数据库(CSV 文件)的名称,即存储在同一目录中,其中包含 UCI ML repo 上所有数据集的名称和 URL 信息。local_table
:本地存储的数据库(CSV 文件)的名称,即存储在同一目录中,其中包含 UCI ML repo 上所有数据集的特征信息,即样本数量、对数据集执行的机器学习任务的类型。msg_flag
:控制详细程度。download_flag
:默认为真。如果设置为 False,则仅创建目录,但不启动下载(出于测试目的)。
download_datasets_task(task='Classification',local_database=None,local_table=None,msg_flag=False,download_flag=True)
:下载符合用户输入的 ML 任务标准的所有数据集。
task
:用户想要下载数据集的机器学习任务。可能是以下任何一种:- “分类”、“推荐系统”、“回归”、“其他/未知”、“聚类”、“因果发现”。
local_database
:本地存储的数据库(CSV 文件)的名称,即在同一目录中,包含 UCI ML repo 上所有数据集的名称和 URL 信息。local_table
:本地存储的数据库(CSV 文件)的名称,即存储在同一目录中,其中包含 UCI ML repo 上所有数据集的特征信息,即样本数量、要对数据集执行的机器学习任务的类型。msg_flag
:控制详细程度。download_flag
:默认为真。如果设置为 False,则仅创建目录,但不启动下载(出于测试目的)。
如果您有任何问题或想法要分享,请通过tirthajyoti【AT】Gmail . com联系作者。你也可以查看作者的 GitHub 资源库 中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。如果你像我一样对机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。
引入自定义分类器—构建您自己的文本分类模型,无需任何训练数据
介绍
机器学习最成功的范例之一是监督学习,它让你通过从大量训练样本中学习来建立一个泛化模型。监督学习广泛用于自然语言处理中,以构建多类或多标签文本分类器,用于解决各种用例,如垃圾邮件检测、情感分析、情感分析、客户意图分析等…任何熟悉构建文本分类模型的过程的人都知道它包括下面列出的三个步骤:
准备训练数据:训练数据,也称为标记数据,是特定领域案例的语料库,这些案例用分类器期望分类的标签进行人工注释。
**训练文本分类模型:**然后选择合适的机器学习算法,在标注数据集上训练模型。我们已经在之前的博客中介绍了一些建立情感分析模型的技术。
**测试和验证:**标记数据集的一部分被留出,用于测试和验证训练好的模型,以评估其泛化能力。
当我们没有足够的标记数据来完成任务训练一个可靠的模型时,传统的监督学习范式就会崩溃。现实世界中的文本分类项目经常面临最大的障碍,即访问大量数据并手动注释它们。因此,大多数现实世界的项目都陷入了第一步。那些跨越了第一个障碍的人通常会发现他们的数据要么不充分,要么偏向某些类别,导致最终的人工智能模型中出现偏差。
什么是自定义分类器?
深度学习中的许多研究都是针对从更少的数据中学习更好的表示,其中一个令人兴奋的领域是零射击学习。引用 Ian Goodfellow 在他的 Quora 回答中的话——“零射击学习是指尽管没有收到任何关于任务的训练样本,却能够解决一项任务。”换句话说,想象一下预测一条推文的情绪,而不提供任何带有该情绪标签的推文的训练示例。
ParallelDots 的内部研究团队提出了他们自己的文本分类零镜头学习范式,并发布了一篇题为“一次训练,随处测试:文本分类零镜头学习”的研究论文。你可以在这里看论文。
此外,为了兑现我们让人工智能触手可及的承诺,我们决定将这项令人兴奋的研究成果转化为商业应用,因此推出了一个新的 API,让您可以利用零触发学习的全部功能来进行文本分类用例。我们称之为自定义分类器,因为它可以让你建立自己的文本分类器的定义,自定义类别。这是我们在开发前沿人工智能解决方案的过程中迈出的革命性一步,让用户在不需要建立任何训练数据的情况下开发和集成自定义文本分类模型。
通过示例学习—构建样本文本分类模型
由于不需要训练数据,这也降低了建立文本分类模型的成本和时间。有了所有的背景知识,让我们试着看看自定义分类器的运行情况。
在下面的截图中,我们从我们网站上的自定义分类器演示页面中截取了一个体育标题,并定义了五个类别,我们希望将这个标题分为世界政治、体育、宗教、娱乐和商业。
正如您从结果中看到的,体育类别在所有类别中具有最高的概率得分,因此是我们输入文本中最有可能的类别。请注意,我们在测试时定义了类别,底层的人工智能模型并没有在这些类别上进行明确的训练。
接下来,我们尝试将运动类别进一步细分为不同的类别,如足球、高尔夫等。看看我们的分类器能否理解它们。
我们再次看到,分类器准确地识别了体育类别,而没有对它们进行明确的训练。我希望现在您已经开始了解这项技术的潜力。
最后一步,让我们试着将我们的足球类别进一步细分为全球不同类型的联赛,看看我们的分类器是否能正确预测。
确实神奇!我们的分类器也正确地选择了联盟。
总之,自定义分类器让您对文本分类的未来有所了解,在这种情况下,将一段文本可靠地分类到自定义类别中只需要很少或不需要训练示例。这种能力将开启无限的可能性,并赋予众多休眠的文本分析项目新的生命,这些项目由于缺乏训练数据或训练资源而永远不会看到光明的一天。
设置自定义分类器
设置自定义分类器非常简单,可以通过下面提到的三个简单步骤来完成:
- 注册免费的 ParallelDots API 账户,登录到你的仪表盘。
- 导航到仪表板中的自定义分类器部分,提供一个示例文本并定义一些类别来分析您的文本。默认情况下,你将处于测试模式,让你调整你的类别列表多次,你想免费。
- 一旦您对分类准确性感到满意,单击 Publish 部署您的分类器以供生产使用,并获取分类器 id。一旦发布,您将能够通过 API 端点访问您的自定义分类器。
自定义分类器的 API 文档可以在这里获得。一个 Excel 加载项功能将很快可用,以便从 MS Excel 中使用它。
在这篇博文中,我们介绍了一种新的文本分类模式,我们希望我们的用户能够从中受益匪浅。我们已经看到一些令人兴奋的用例被我们的用户通过自定义分类器解决,比如对招聘信息进行分类、对新闻文章进行分类、处理开放式调查反馈等。通常,分析原始数据的第一步是将它分类到您关心的类别中,并监控一段时间内的趋势,以获得可操作的见解。
自定义分类相对于标准文本分类的优势
在分析客户之声等非结构化数据时,情感分析等标准文本分类模型并不总是足以获得整体视图。另一方面,自定义分类器可以让您将这些数据分类到我们关心的更细微的类别中。例如,使用自定义分类器,快餐连锁店老板可以将通过社交媒体从客户那里收到的反馈分类为价格、氛围、员工行为、食品质量等类别。更好地了解她需要改进业务的哪些方面。使用简单的情绪分析,她可能知道她的业务总体情况如何,但可能会错过一些关键趋势,如员工行为和客流量之间的关系。自定义分类器的潜力是对文本进行分类,而不仅仅是情绪标签(正面、负面或中性),这样你不仅可以知道你的产品得到了多少负面反馈,还可以知道用户在这些负面陈述中谈论了什么。
我们相信定制分类器可以使没有数据科学背景的用户能够构建和部署他们自己的分类器,并获得相对于竞争对手的优势。它还将帮助企业从根本上转变为数据驱动的组织,并将最终加速人工智能和机器学习的产业化。你也可以在这里探索更多文本分类博客。
parallel dots AI API,是由 ParallelDots Inc 提供的深度学习支持的 web 服务,可以理解大量的非结构化文本和视觉内容,为您的产品提供支持。你可以查看我们的一些文本分析应用程序接口(API )( T7 ),在这里填写表格(T8 )( T9)或者给我们 apis@paralleldots.com 写信。
简介:数据好奇,时事通讯
经过长时间的中断,我的最佳数据资源的每周综述以一种新的形式回来了。
TL;博士:我正在把综述移到每周电子邮件时事通讯上。订阅 这里 如果你很投入的话。如果你有疑问,或者想了解新版本的更多信息,请继续阅读。
去年,我开始在 Medium 上发布我最喜欢的数据故事、数据集和数据可视化的每周综述(阅读旧版本此处了解一下味道)。在这个过程中,我收集了大量的灵感。但是现在,我想尝试一些不同的东西。
这是独家新闻
新的“数据好奇”将更加关注策展。
更少的数量,只有最好的。足够容易理解,比如说,一封电子邮件。
它还将优先考虑科学领域的数据发展。
当你专注于你感兴趣的东西时,数据项目总是更有趣。对我来说,是科学、环境和技术。因此,期待大量的酷的东西,但少一点政治(尽管在那个领域也有大量伟大的数据工作)。
我将寻找与环境、空间、教育、健康、技术和自动化相关的数据驱动内容。这些天我也少做新闻,多做数据项目开发:所以自然就少了新闻性。
出于学习目的,我正在添加更多的内容。
关于数据处理,我最喜欢的一点是社区有多开放。我花了无数的时间受益于其他人的教程和演练。因此,作为一种向前推进的方式,我将包括一些我自己的教程,以及我在其他地方找到的与数据科学和数据可视化相关的有用的学习资源。
关于《新方向》的最后一点:最重要的是,我希望这篇时事通讯能激发一些好奇心。最好的发现是通过问大量的问题发现的。最好的数据项目是从提出正确的问题开始的。
因此,与之前的三部分文章格式不同,每封邮件都将涉及几个主要部分:
阅读
我的 top 在一个与数据相关的主题上挑选了一些有趣的想法。
探索
最好的数据可视化不只是讲述一个故事,而是讲述多个故事。这一部分将包括一周的数据,这些数据提供了重要的洞察力/影响力。
分析
当我想学习一项新的数据相关技能时,手头有实践数据集总是很方便的。在这里,我将每周分享一个有趣的数据集,供您参考。
学习
在过去的一年里,我花了更多的时间来发展我在 Python 和数据科学方面的技能。我可能会分享与这两者相关的文章,但偶尔他们会更关注数据可视化(如 d3.js 和 bokeh)。
这将是一次疯狂的旅程。所以我需要你的反馈!您可以随时在这里提交(也会在每封邮件的页脚)。如果有足够的需求,我会尽最大努力改编和改变每份简讯的内容。
在这里注册每周数据灵感
DAX 简介—数据分析表达式
DATAAanalysis Expression 是一个函数的集合,可以用来执行一个任务并返回一个或多个值。虽然这听起来与任何其他编程语言都非常相似,但 DAX 只是一种公式或查询语言。DAX 是微软在 2009 年左右开发的,用于微软的 PowerPivot,当时是作为 Excel (2010)插件提供的。它现在非常受欢迎,因为它现在是 Power BI 的首选语言,并且也受到表格 SSAS 的支持。由于 DAX 在 Power BI 中被广泛使用,所以在本文中,我将重点放在 DAX for Power BI 上,但是它也可以应用于其他适用的工具。
Power BI logo
Power BI 是一种商业智能工具,它可以从数百个数据源中获取数据,准备数据,并生成漂亮的交互式报告和仪表盘,提供令人信服的见解。它提供了一套服务来引入数据,构建仪表板或报告,并与所需人员共享。虽然 Power BI 相对较新,但它的核心在某种程度上已经酝酿了很长时间。它基于 SSAS (SQL Server Analysis Services)、Power Pivot、Power View 和 Power Query,其中一些是免费的 Excel 插件。
DAX usability in Power BI Desktop
在 Power BI 的整个套件中,DAX 主要用于转换导入 Power BI 的数据模型和/或为可视化添加新的度量。这些函数用于创建计算列或度量,以帮助进行报告。
DAX 还通过在数据模型级别提供行级安全性(RLS)来保护发布的报告和仪表板。
计算列
计算列在数据模型中创建,在列级别逐行计算,存储在数据模型中,成为其所在表的一部分。计算列也会消耗更多内存。计算列通常表示为 Table[Column]。
措施
顾名思义,度量是聚合,DAX 有助于根据数据模型创建额外的度量,以帮助进行报告/可视化。这些 DAX 函数动态运行,也称为动态聚合,因此不与数据模型一起存储。由于度量是在查询时计算的,因此会消耗额外的 CPU。一个测度简单的表示为【测度】。
语法
Syntax of a DAX function
聚合函数
DAX 聚合函数聚合表中行上的列或表达式,用于度量中。DAX 提供了很多内置的聚合函数,这里有一个引用列表。
举例:
Customer Table
平均销售额=平均(客户[销售额])
平均销售额现在将返回 500。
‘X’聚合函数
X 聚合函数对表中的行进行迭代和聚合,与聚合函数相同,唯一的区别是 X 版本的聚合函数对表达式而不是表中的列进行聚合。
举例:
Customer Table
平均销售额=AVERAGEX(客户,[销售额]*[数量])
平均销售额现在将返回 1433.34。
VAR 函数
命名变量存储表达式的结果,该结果可以作为参数传递给其他表达式。变量减少了代码中的冗余,并通过避免创建新的计算列来提高性能。
举例:
An example of variable in DAX
时间智能功能
时间智能函数在商业智能中非常有用,并且在简单函数中执行复杂计算时可以节省时间。这些函数处理日期和时间字段,根据不同级别的时间段产生各种计算。这里有一个时间智能功能的列表。
文本功能
文本函数对表中的列进行操作,以连接、搜索或操作字符串,并返回整个或部分字符串。这里有一个文本函数的列表。
表格功能
表函数返回完整的表而不是值。它们通常与其他函数结合使用,以迭代返回的结果表中的每一行。
假设您有一组相关的表,并且需要基于两个或更多的表执行计算。在这种情况下,一些表函数非常有用。这里有一个表函数列表。
函数 FILTER 根据提供的表达式返回当前表的子集,并返回一个表作为结果。
举例:
Orders Tables
SuperStore = FILTER (Orders,Orders[产品名称] = "Newell 317 ")
这将创建一个名为 SuperStore 的新表,其中只包含 Newell 317 产品,如下所示。
SuperStore Table
函数 RELATEDTABLE 返回表格中与当前表格相关的所有行。
举例:
Customer Table
订单计数= COUNTROWS(RELATEDTABLE(‘超市’))
Outro
虽然这只是对 DAX 的简单介绍,但 DAX 中还有许多其他有用的功能,它们将使分析师或开发人员的工作变得更加轻松。
这里有一些学习 DAX 的优秀资源
介绍深度学习和神经网络——新手的深度学习(1)
Source: Allison Linn, Microsoft
关注我的 推特 了解更多关于深度学习创业公司的生活。
欢迎来到我的系列菜鸟深度学习的第一篇帖子,作者是我,一个菜鸟。我是作为强化学习策略来写的,以便更好地处理和消化知识。但是如果你是深度学习的新手,那么这也适合你,因为我们可以像新手一样一起学习!
(你也可以在我的网站 上阅读 这篇帖子,该网站支持 LaTeX with MathJax
Source: deepinstinct.com
深度学习可能是目前最热门的技术话题之一。大公司和年轻的创业公司都在这个奇特的领域淘金。如果你认为大数据很重要,那么你应该关心深度学习。经济学家说数据是 21 世纪的新石油。如果数据是原油,数据库和数据仓库是在互联网上挖掘和抽取数据的钻机,那么就把深度学习想象成炼油厂,最终把原油变成所有有用和有洞察力的最终产品。地下可能隐藏着许多“化石燃料”,市场上有许多钻机和泵,但是没有合适的提炼工具,你将得不到任何有价值的东西。这就是为什么深度学习很重要。这是数据驱动的大图景的一部分。
好消息是,我们不会用完数据,我们的“精炼机”越来越好。今天,在网上做任何事情都会产生数据。因此,与石油不同,数据是“可持续的”,并且在“爆炸式”增长。与此同时,只要数据不是垃圾,深度学习就不会有垃圾。因此,数据越多越好。(查看 Trent McConaghy 在区块链上的帖子,为 AI 提供解决方案,让数据拥有声誉!).
此外,这个“炼油厂”正在改善软件和硬件。深度学习算法在过去几十年中得到了改善,世界各地的开发人员为开源框架做出了贡献,如 TensorFlow、Theano、Keras 和 Torch,所有这些都使人们可以轻松地构建深度学习算法,就像玩乐高积木一样。由于世界各地游戏玩家的需求,GPU(图形处理单元)使我们能够利用深度学习算法以省时的方式构建和训练模型,并取得令人印象深刻的结果!所以,对于所有不喜欢你的孩子玩游戏的父母来说:游戏也有好的一面…
深度学习:秘方
你可能已经读过新闻,知道深度学习是许多令人兴奋的发展背后的秘方,并使我们许多最疯狂的梦想甚至噩梦成真。谁会想到 DeepMind 的 AlphaGo 可以在最深的棋盘游戏中击败最好的围棋选手之一 Lee Sedol,这种游戏号称比整个宇宙中的原子还多。很多人,包括我,都没想到会这样。这似乎是不可能的。但它现在就在这里。深度学习正在最具挑战性的棋盘游戏中击败我们。AI 什么时候觉醒?有些人认为这很快就会发生。
Lee Sedol vs. AlphaGo in 2016, Source: The New Yorker
我们还没有谈到由深度学习驱动的其他令人印象深刻的应用程序,如谷歌翻译和 Mobileye 的自动驾驶。你说吧。我是不是忘了提到深度学习在诊断癌症方面也打败了医生?深度学习擅长许多错误率低于人类的任务!不仅仅是自动化那些无聊的东西,还有有趣的东西。唉,我们凡人…
亲爱的总统先生,不是外国人。是自动化。
以下是深度学习在真实情况下可以执行的一般任务的简短列表:
- 识别人脸(或更一般的图像分类)
- 阅读手写数字和文本
- 识别语音(不再需要自己抄写采访)
- 翻译语言
- 玩电脑游戏
- 控制自动驾驶汽车(和其他类型的机器人)
还有更多。暂停一下,想象一下深度学习可以实现的所有事情。这是惊人的,也许有点可怕!
区别:人工智能、机器学习和深度学习
好吧,等一下。你可能已经在你的社交媒体新闻中看到过像人工智能( AI )、机器学习( ML )和深度学习( DL )这样的术语满天飞。都有什么区别?他们指的是同一件事还是什么?问得好。在我们深入到深度学习之前,重要的是逐步建立这些术语的概念框架。
粗略地说,下图展示了这三个概念之间的关系。深度学习是机器学习的一个子领域,机器学习是人工智能的一个子领域。奥菲尔·萨姆森和 T2 都写过关于他们的好故事。检查这里的和这里的和。
Source: Nvidia
先来讨论一下包罗万象的 AI。你可能已经知道了图灵测试。如果一个人在向计算机提出一些书面问题后,不能分辨出这些书面回答是来自另一个人还是计算机,那么计算机就通过了图灵测试。根据人工智能:现代方法,Peter Norvig 和 Stuart Russell 定义了计算机为了通过图灵测试必须具备的 4 种能力:
- **自然语言处理:**用英语成功交流
- **知识表示:**存储计算机读取的内容
- **自动推理:**利用存储的知识回答问题并得出新的结论
- **机器学习:**适应新环境,识别新模式
啊,有个术语叫“机器学习”!ML 是关于用数据集训练学习算法,如线性回归、KNN、K-Means、决策树、随机森林和 SVM,以便算法可以学习适应新的情况,并找到可能有趣和重要的模式。同样,ML 是数据驱动的。学习算法有很多奇怪的术语?别担心,我也不全认识。所以以后我们一起学习。
对于训练 ML,数据集可以被标记,例如,它带有一个“答题卡”,告诉计算机什么是正确的答案,比如哪些电子邮件是垃圾邮件,哪些不是。这被称为监督学习,并且像线性回归和 KNN 这样的算法被用于这样的监督回归或分类。其他数据集可能没有被标记,您实际上是在告诉算法(如 K-Means)将它在没有任何答案的情况下找到的或聚类模式与相关联。这叫做无监督学习**。这里有一个关于栈溢出的监督与非监督学习的很好的答案,这里也有一个来自 Olivia Klose 博客的关于监督与非监督的帖子。**
Source: http://oliviaklose.com/
Norvig 和 Russell 还提到了另一项名为总图灵测试的测试,该测试通过物理模拟进一步检验了计算机的感知能力。要通过这一关,计算机需要:
- **计算机视觉:**感知周围的物体
- **机器人学:**操纵物体并四处移动
那么 DL 现在怎么样了?还记得上一节深度学习擅长的一般任务吗?像人脸或手写文本识别这样的事情与计算机视觉有关,因为你要将图形输入计算机进行分析。其他任务如语言翻译或语音识别与自然语言处理(NLP)有关。因此,DL 是 ML 的一个分支,因为它也有一套学习算法,可以对数据进行训练和学习,更具体地说 DL 由神经网络驱动。此外,DL 可以在机器学习领域之外执行,并帮助其他领域,如计算机视觉和 NLP,以便有希望人工智能有一天可以通过图灵测试和总图灵测试!
但是神经网络到底是什么?它是在模仿真实神经元细胞的行为吗?还是某种神奇的黑盒子?对于你们中的一些人来说,到目前为止提供的信息可能有点太多了,所以让我们休息一下,查看一些免费的在线资源,看看哪些适合你:)之后,我们将直接进入神经网络。
中途奖金:宝贵的资源
神经网络和 DL 往往隐藏在一层神秘的面纱后面。所有与该主题相关的技术术语可能会让初学者感到非常困惑。由于 DL 将在未来自动化许多任务并取代许多工人,我个人认为我们都保持开放的心态和好奇心来学习新技术是很重要的。DL 可以代替从事手工重复性工作的工人。但是 DL 不能代替科学家或工程师构建和维护 DL 应用程序。
目前,互联网上已经有许多关于这个主题的很棒的课程、教程和书籍,例如(不详尽或按特定顺序):
- 迈克尔·尼尔森的神经网络和深度学习
- 杰弗里·辛顿的用于机器学习的神经网络
- 古德费勒、本吉奥、库维尔的深度学习
- 伊恩·特拉斯克的摸索深度学习,
- Francois Chollet 的用 Python 进行深度学习
- Udacity 的深度学习纳米学位(不免费但高质量)
- Udemy 的深度学习 A-Z($ 10-$ 15)
- 斯坦福的 CS231n 和 CS224n
- Siraj Raval 的 YouTube 频道
这个清单还在继续。大卫·文丘里为自由代码营写了一篇文章,列出了更多的资源。点击查看。
在自我教育的时代,我们真的很幸运。顺便问一下,你听说过那个来自芝加哥的高中生阿布·卡德吗?这个孩子自学了机器学习和深度学习框架 Tensorflow,并帮助将乳腺癌的诊断提高到 93%-99%的实时准确率!他登上了谷歌 I/O 2017。下面是一个来自谷歌的关于他的故事的鼓舞人心的视频。
Source: Google
感知机:数字逻辑的前奏
好吧,我希望阿布·卡迪尔的故事让你对学习感到兴奋!让我们进入这篇文章的第二个主题:神经网络介绍。中国古代哲学家老子曾经说过:
“千里之行,始于足下。”
所以我们将用一个非常简单的神经网络来开始和结束这篇文章。听起来很酷?神奇吧。
尽管有了新的名声,神经网络领域一点也不新鲜。1958 年,美国心理学家弗兰克·罗森布拉特(Frank Rosenblatt)试图建造一台“像人脑一样感知、识别、记忆和反应的机器”,并将这台机器称为“感知机”。但是罗森布拉特并没有凭空发明感知机。实际上,他站在巨人的肩膀上,从沃伦麦卡洛克和沃尔特皮茨在 20 世纪 40 年代的作品中获得了灵感。天哪,这使得神经网络,或者更具体地说,感知器,成为这个快速变化的技术世界中的恐龙。
Rosenblatt and Perceptron, Source: The New Yorker
所以我们来看看什么是感知机。首先,看看下面的神经元细胞:树突是神经细胞的延伸(在图的左下角)。它们接收信号,然后将信号传输到细胞体,细胞体处理刺激并决定是否向其他神经元细胞触发信号。如果这个细胞决定触发信号,细胞体上称为轴突的延伸将触发轴突末端向其他细胞的化学传输。在这里你不需要记住任何东西。我们不是在研究神经科学,所以对它如何工作有一个模糊的印象就足够了。
Original Source: thinglink.com
A Single Perceptron
现在,上图是一个感知器的样子。很像上面的神经细胞图,对吧?确实如此。感知器和其他神经网络的灵感来自我们大脑中的真实神经元。请注意,它只是受到的启发,并不完全像真正的神经元一样工作。感知器处理数据的过程如下:
- 在左侧,你有带下标 1,2,…,m 的 x 的神经元(小圆圈)携带数据输入。
- 我们将每个输入乘以一个权重 w,也标有下标 1,2,…,m,沿着箭头(也称为突触)到中间的大圆圈。于是 w1 * x1 , w2 * x2 , w3 * x3 等等。
- 一旦所有的输入都乘以一个权重,我们将所有的输入相加,并加上另一个预先确定的数字,称为偏差。
- 然后,我们将结果进一步向右推。现在,我们在矩形中有了这个阶跃函数。它的意思是,如果步骤 3 的结果是等于或大于 0 的任何数字,那么我们得到 1 作为输出,否则,如果结果小于 0,我们得到 0 作为输出。
- 输出为 1 或 0。
请注意,或者,如果您将 bias 移动到激活函数中等式的右侧,如 sum(wx) ≥ -b ,则此 -b 称为阈值。因此,如果输入和权重之和大于或等于阈值,则激活触发 1。否则,激活结果为 0。选择有助于你更好理解的,因为这两种表达方式是可以互换的。
Illustration of using Threshold Value instead of Bias
我在下面添加了另一个感知器图,这次每一步都用了颜色。完全理解它并记住每一步发生的事情非常重要,因为当我们谈论更复杂的神经网络结构时,我们将忽略未来图表中的中间步骤:
Procedures of a Perceptron labeled in colors
- 输入被输入感知器
- 权重乘以每个输入
- 求和然后加上偏置
- 激活功能被应用。注意,这里我们使用阶跃函数,但是还有其他更复杂的激活函数,如 sigmoid、双曲正切( tanh )、整流器( relu )和更多的。不要担心,我们将在未来涵盖其中的许多内容!
- 输出要么触发为 1,要么不触发为 0。注意我们用 y 帽 来标注我们的感知器模型产生的输出
将来,我们有时可能会简化我们的感知器如下,而不提及步骤 3 和 4。我们刚刚谈到的这种感知器也是一种单层感知器,因为我们直接将输入处理成输出,中间没有任何多层神经元:
Simplified Representation of Perceptron
感知器:直觉
好吧,你现在知道感知器是怎么工作的了。这只是一些机械的乘法,接着是求和,然后是一些激活……瞧,你得到了一个输出。是啊,这怎么会接近人类大脑中的神经元呢?
为了理解感知机,让我们看一个不一定真实的简单例子。假设你看了我的帖子后很有动力你需要决定是否学习 DL。有 3 个因素会影响你的决定:
- 如果掌握 DL 后你会赚更多的钱(是:1,否:0)
- 相关的数学和编程容易吗(是:1,否:0)
- 您可以立即在 DL 上工作,而不需要昂贵的 GPU(是:1,否:0)
我们使用 *x1、x2、*和 x3 作为每个因素的输入变量,并为每个因素分配一个二进制值(1 或 0 ),因为答案只是简单的“是”或“否”。假设到目前为止你真的很喜欢 DL,并且你愿意克服你一生对数学和编程的恐惧。你也有一些储蓄,现在投资一个昂贵的 Nvidia GPU 来训练你的 DL 模型。假设这两个因素同等不重要,因为你可以在它们之间做出妥协。但是,你花了那么多时间和精力学 DL,真的是想赚更多的钱。所以有了高预期的投资回报,如果事后赚不到更多的$$$就不会把宝贵的时间浪费在 DL 上。
在了解了你的决策偏好后,让我们假设你在学习 DL 后有 100%的概率赚更多的钱,因为市场上有很多需求,但供应却很少。所以 x1 = 1 。假设数学和编程超级难。所以 x2 = 0 。最后,假设你必须有 Titan X 这样强大的 GPU,那么 x3 = 0 。好了,我们已经准备好输入,也可以初始化权重。我们选 w1 = 6,w2 = 2,w3 = 2 。权重越大,对应的输入越有影响力。所以既然你决定学 DL 最看重钱, w1 > w2 和 w1 > w3 。
我们将假设阈值 *threshold = 5,*这相当于说偏置项 bias = -5 。我们把它们加起来,加上偏差项。关于使用感知器来确定你是否会学习 DL 的过程,请检查以下内容。
注意阈值为 5,我们只有赚更多的钱才会学习深度学习。就算数学既轻松( x2 = 1 )又不需要花钱买 GPU ( x3 = 1 ),以后赚不到更多的钱还是不会去学 DL。请参见下图:
现在你知道偏差/阈值的诀窍了。这个 5 的高阈值意味着感知器必须满足你的主导因素才能触发 1 的输出。否则,输出将为 0。
有趣的是:改变权重和阈值/偏差将导致不同的可能决策模型。例如,如果我们将阈值从 threshold = 5 降低到 threshold = 3,那么输出为 1 的可能性更大。现在,对于输出= 1 的最低要求为:
- 你以后会赚更多的钱,所以 x1 = 1 保证你学习 DL的决定,而不管到 x2 和 x3 的值
- 或者说,数学很容易,不需要买 GPU,所以 x2 = x3 = 1 也保证了你决定学习 DL 而不管值到 x1
为什么你可能已经知道了;)以下是解释:
没错。现在门槛降低了,所以其他两个因素可以激励你学习 DL,即使你赚更多钱的前景已经消失。现在,我鼓励你玩玩权重 w1、w2 和 w3 ,看看你学习 DL 的决定会如何相应地改变!
感知机:在行动中学习
为什么要在这个例子中摆弄砝码呢?因为这有助于你理解感知器是如何学习的。现在,我们将使用这个例子以及输入和权重来说明单层感知器,并看看尽管它有局限性,但它能实现什么。
在一个真实的 DL 模型中,我们被给予输入数据,我们不能改变它。同时,在你训练你的神经网络模型之前,偏置项被初始化。假设我们假设偏差是 7。现在,让我们假设以下输入数据,以便(1)。你会赚更多的钱。DL 的数学和编程会很难,还有(3)。是的,你必须花 1400 美元买一个 GPU 来处理 DL,而且最重要的是, 我们假设你实际上想要学习深度学习, 我们将其命名为 期望输出 以了解感知机应该如何正确预测或确定:
让我们进一步假设我们的权重初始化如下:
因此,对于输入数据、偏置和输出标签(所需输出):
好的,我们知道你的神经网络的实际输出与你想要研究 DL 的真实决定不同。那么,考虑到实际输出和期望输出之间的差异,神经网络应该做些什么来帮助自己学习和改进呢?是的,我们不能改变输入数据,我们现在已经初始化了我们的偏差。所以我们唯一能做的就是告诉感知器调整权重!如果我们告诉感知器将 w1 增加到 7,而不改变 w2 和 w3 ,那么:
调整权重是我们感知机学习过程的关键。并且具有阶跃函数的单层感知器可以利用下面列出的学习算法在处理每组输入数据之后调整权重。尝试用这个算法自己更新权重:)这差不多就是单层感知器的学习方式。
顺便说一下,现在我们已经完成了这个不太现实的例子,我可以告诉你,你不需要买一个 GPU。如果你作为初学者训练较小的数据集,你很可能不需要 GPU。然而,当你开始用大量图像文件训练更大的数据集时,你可以使用云服务,如 AWS 、 Floyd ,可能还有谷歌 TPU 。
此外,DL 的数学并不简单,但也不是不可逾越的。大多数情况下,我们只会遇到一些矩阵运算和基本的微积分。但是记住,没有什么能让你脱颖而出的东西是容易学的。这里有一段引自的话:
“做我们知道如何做好的事情是令人愉快的,这与刻意练习的要求正好相反。我们应该坚持寻找我们不擅长的,而不是做我们擅长的。然后,我们确定那些会让我们变得更好的痛苦、困难的活动,并一遍又一遍地做这些事情。如果导致伟大的活动既容易又有趣,那么每个人都会去做,他们不会区分最好的和其他的。”
所以对于那些像我一样害怕数学和编程的人,我希望这句话能给你一些勇气,让你继续学习和实践:)
感知器:局限性
尽管公众早期有一些感觉,但由于其局限性,感知器的受欢迎程度悄悄地消失了。1969 年,马文·明斯基和西蒙·派珀特讨论了这些限制,包括感知器无法学习 XOR(异或)门(因此基本上一个具有阶跃函数的 单层感知器无法理解天气必须要么热要么冷,但不能同时热和冷的逻辑)。这些逻辑门,比如 And、OR、NOT、XOR,都是非常重要的概念,为你的计算机提供动力;)TutorialsPoint 有一个逻辑门列表,如果你想了解更多。在这里勾选。
当然,后来人们意识到 多层感知器能够学习异或门的逻辑,但它们需要一种叫做 反向传播 的东西,以便网络从试验和错误中学习。毕竟,记住深度学习神经网络是数据驱动的。如果我们有一个模型,而它的实际输出与**期望输出不同,**我们需要一种方法,沿着神经网络反向传播误差信息,告诉权重调整并以某个值修正它们自己,以便在一轮又一轮的测试后,模型的实际输出逐渐接近期望输出。
事实证明,对于涉及不能从输入的线性组合中产生的输出的更复杂的任务(因此输出是非线性的或不可线性分离的),阶跃函数将不起作用,因为它不支持反向传播,这要求所选择的激活函数具有有意义的导数。
Source: mathnotes.org
某微积分讲:阶跃函数是一个线性激活函数,其导数对于除零点以外的所有输入点都为零。在零点,导数是未定义的,因为函数在零点是不连续的。所以虽然这是一个非常简单和容易的激活功能,但它不能处理更复杂的任务。继续阅读,你会发现更多。
线性与非线性
什么!?那么什么是线性组合?还有为什么感知器学不会异或门?这越来越令人困惑了。没问题,这里有一个解释:
想一想我们之前的例子。用 3 个二进制输入来表示你在学习 DL 后是否赚了更多的钱,如果涉及的数学和编程容易与否,如果你可以在不投资昂贵的硬件的情况下学习 DL,我们总共有 2 = 8 组可能的输入和输出。利用权重( *w1 = 6,w2 = 2,w3 = 2),*和 *bias = -5,*我们得到了下面的一组( x1,x2,x3 ):
- (1,0,0)-> sum+bias = 6–5 = 1,期望输出= 1
- (1,1,0)-> sum+bias = 8–5 = 3,所需输出= 1
- (1,1,1) ->总和+偏差= 10–5 = 5,期望输出= 1
- (1,0,1)-> sum+bias = 8–5 = 3,所需输出= 1
- (0,1,1)-> sum+bias = 4–5 =-1,期望输出= 0
- (0,1,0)-> sum+bias = 2–5 =-3,期望输出= 0
- (0,0,1)-> sum+bias = 2–5 =-3,期望输出= 0
- (0,0,0)-> sum+bias = 0–5 =-5,期望输出= 0
因此,从字面上看,如果我们从随机权重开始,而不是从( w1 = 6,w2 = 2,w3 = 2 )的随机权重开始,我们的感知机将尝试学习调整并找到理想的权重( w1 = 6,w2 = 2,w3 = 2 ),这将正确地将每组( x1,x2,x3 )的实际输出匹配到期望的输出。其实我们可以在一个 3D 空间里用一个平面把这 8 个可能的集合分开,比如 x1 = 0.5 的平面。这种类型的分类问题,你可以画一个平面来分隔不同的输出(或在 2D 为输出画一条线),这是我们的单层感知器可以解决的问题。
A plane separating the 4 sets to the left from the 4 to the right
A Plane separating the 4 sets to the left from the 4 to the right
希望你能想象一下上面 8 组输入分开的平面。由于( x1,x2,x3 )的集合涉及一个三维空间,这可能有点挑战性。但一般来说,具有线性激活函数的单层感知器可以学习分离一个数据集,就像下图中的图表 A,可以用一条 y = ax + b 的线来分离。但是,如果数据集只能像图表 B 那样被一个圆非线性地分开,我们的感知机将会表现得很糟糕。
Source: Sebastian Raschka
为什么会这样呢?我从栈溢出为你复制粘贴一个报价。你也可以在这里查看答案和。
激活函数不可能是线性的,因为具有线性激活函数的神经网络仅在一层深度有效,不管它们的结构有多复杂。网络输入通常是线性变换(输入*权重),但是现实世界和问题是非线性的。为了使输入数据非线性,我们使用称为激活函数的非线性映射。激活函数是决定特定神经特征存在的决策函数。它映射在 0 和 1 之间,其中 0 表示该特征不存在,而 1 表示该特征存在。不幸的是,权重中发生的小变化不能反映在激活值中,因为它只能取 0 或 1。因此,非线性函数在这个范围内必须是连续的和可微的。神经网络必须能够接受从-无穷大到+无穷大的任何输入,但在某些情况下,它应该能够将其映射到范围在{0,1}或{-1,1}之间的输出,因此需要激活函数。激活函数中需要非线性,因为它在神经网络中的目的是通过权重和输入的非线性组合产生非线性决策边界。”-用户 7479
那么为什么具有阶跃函数的单层感知器不能学习异或门呢?看看下面的图表。左边是 XOR 逻辑图,右边是来自 XOR 门的 2 个不同结果(1 和 0)的笛卡尔表示。
Source: https://stackoverflow.com/a/35919708/6297414
事实上,我们不可能用一条直线来区分白点和黑点。我们需要更强大的东西来让神经网络学习 XOR 门逻辑。我很快会写更多关于这个话题的文章。
概述
深度学习是一个令人兴奋的领域,它正在迅速改变我们的社会。我们应该关心深度学习,至少了解它的基础知识是很有趣的。我们还介绍了一个非常基本的神经网络,称为(单层)感知器,并了解了感知器的决策模型是如何工作的。
我们的单层感知器加上一个阶跃函数对于简单的线性可分二分类工作良好。但仅此而已…因为它对涉及非线性输出的更复杂的问题不太适用。我知道这听起来有点令人失望,但我们接下来将详细介绍它们!
接下来将是一个关于神经网络的新帖子和隐藏层(听起来很棒吧?)和一个名为s 形函数的新激活函数。如果空间允许,我们将触及梯度下降和反向传播,这是智能神经网络要学习的关键概念。敬请关注(这里是第二个帖子的链接) 😃
现在,祝贺你跟帖到目前为止,你已经学到了很多!保持动力,我希望你在深度学习中获得乐趣!如果你迫不及待地想看我的文章,请查看以下免费资源,了解更多信息:
我们专注于手写识别,因为这是学习神经系统的一个极好的原型问题…
neuralnetworksanddeeplearning.com](http://neuralnetworksanddeeplearning.com/chap1.html) [## 用于视觉识别的 CS231n 卷积神经网络
斯坦福 CS231n 课程材料和笔记:视觉识别的卷积神经网络。
cs231n.github.io](http://cs231n.github.io/)
享受学习!
你喜欢这次阅读吗?别忘了关注我的 推特 !
Jupytext 简介
Jupyter 笔记本是包含代码、叙述和情节的交互式文档。它们是试验代码和数据的绝佳场所。笔记本很容易分享,GitHub 上的 2.6M 笔记本正好说明笔记本有多受欢迎!
Jupyter 笔记本很棒,但是它们通常是巨大的文件,具有非常特殊的 JSON 文件格式。让我们来介绍一下 Jupytext ,这是一个 Jupyter 插件,它以纯文本文件的形式读写笔记本:Julia、Python、R scripts、Markdown 或 R Markdown 文档。
Jupyter 笔记本作为文本文件
我们编写了 Jupytext 来处理 Jupyter 笔记本,就像我们处理文本文件一样。使用 Jupytext ,
- 在您最喜欢的文本编辑器或 IDE 中重构笔记本(例如用普通的 Python 脚本来表示)成为了一个真正的选择,
- 将笔记本直接写成脚本或降价是另一种选择
- 使用 Git 在 Jupyter 笔记本上进行协作变得非常简单。
笔记本的文本表示集中在我们实际书写的部分:单元格输入。我们重视投入甚于产出。通常,它们是笔记本中唯一我们想要版本控制的部分。输入比输出轻得多(通常是千字节比兆字节)。
我们也重视产出。使用配对笔记本可以保存输出。在该配置中,除了脚本或 Markdown 文档之外,Jupyter 还将笔记本保存为传统的.ipynb
文件。文本表示可以在 Jupyter 之外编辑。在 Jupyter 中重新加载笔记本时,单元格输入来自文本文件,匹配的输出来自.ipynb
文件。
作为脚本编辑的 Jupyter 笔记本
在第一个动画中,我们展示了如何使用您最喜欢的文本编辑器或 IDE 来编辑您的 Jupyter 笔记本。在浏览代码、编辑和执行单元或单元片段以及调试方面,ide 比 Jupyter 更方便。
动画脚本:
- 我们从 Jupyter 笔记本开始。
- 笔记本包括一幅世界人口图。剧情图例没有按照人口递减的顺序排列,我们会解决这个问题。
- 我们希望将笔记本保存为一个
.ipynb
和一个.py
文件:我们向笔记本元数据添加一个"jupytext_formats": "ipynb,py",
条目。 - Python 脚本可以用 PyCharm 打开:
- 在代码和文档中导航比在 Jupyter 中更容易。
- 控制台便于快速测试。我们不需要为此创建细胞。
- 我们发现数据帧的列顺序不正确。我们更新相应的单元格,并得到正确的绘图。
- Jupyter 笔记本在浏览器中刷新。从 Python 脚本加载修改后的输入。输出和变量被保留。我们最终重新运行代码并得到正确的图形。
脚本和降价作为 Jupyter 笔记本
有了 Jupytext ,每一个 Julia、Python 或者 R script、R Markdown 或者 Markdown 文档都变成了一个潜在的 Jupyter 笔记本。把你的笔记本写成文本,需要的时候在 Jupyter 中呈现出来。
在下面的动画中,
- Jupyter notebook(不是 lab,敬请关注)将我们的普通 Python 脚本作为 Jupyter notebook 打开。
- 从 Jupyter 中保存会给其他未更改的文件添加一个 YAML 头。
- 向笔记本添加一个单元格会带来一个非常简单的区别。
- 刷新笔记本会保留变量,但不会保留输出。输出不存储在文本文件中。
- 我们通过向笔记本元数据添加一个
"jupytext_formats": "ipynb,py",
条目,将脚本与传统的 Jupyter 笔记本配对。当我们保存时,会创建一个新的ipynb
文件。 - 由于有了
ipynb
文件,当笔记本刷新或重新加载时,输出会保留下来。
Jupyter 笔记本协作
你试过合并 Jupyter 笔记本吗?您应该使用 nbdime,或者准备好面对不可读的笔记本:NotJSONError 如果合并的 JSON 中缺少逗号或括号!
有了 Jupytext ,在笔记本上协作就像在脚本上协作一样简单。
只签入文本版本。享受简单的合并和有意义的差异!
安装 Jupytext
Jupytext 在 pypi 上有售。安装 python 包并将 Jupyter 配置为使用 Jupytext 的内容管理器:
# Get Jupytext from pip
pip install jupytext --upgrade# Append this to .jupyter/jupyter_notebook_config.py c.NotebookApp.contents_manager_class="jupytext.TextFileContentsManager"# And restart your notebook server
jupyter notebook
通过在笔记本元数据中添加"jupytext_formats": "ipynb,py",
(用您喜欢的扩展名替换py
),将 Python 脚本与您的 Jupyter 笔记本相关联,或者将ipynb
文件与您的 Python 脚本相关联(为了方便保存单元格输出)。如果您计划在 Jupyter 之外编辑文本文件时保持 Jupyter 打开,请通过在单元格中运行%autosave 0
来关闭 Jupyter 的自动保存。
参考
将 Jupyter 笔记本作为文本使用的想法并不新鲜。Python 中实现的可选转换器包括:
- 笔记 : Jupyter 笔记本作为减价文件,
- ipymd : Jupyter 笔记本作为 Markdown 文档,Python 脚本,OpenDocument 文件,
- ipymd 的一个分支增加了对 R Markdown 和 R HTML 笔记本的支持,
- pynb :作为 Python 脚本的 Jupyter 笔记本。
我们怀着极大的兴趣关注着 Atom 的 Hydrogen 插件,以及 Visual Studio 代码的 Jupyter 扩展。这些扩展将脚本(带有明确的单元格标记,我们希望在 Jupytext 中在某个点支持这些标记)转化为类似于笔记本的交互式环境。
感谢
Jupytext 是我第一个重要的开源贡献。从事开源项目是一次很棒的经历。我问了很多问题,非常感谢这些有帮助的回答、建议和合作。
特别是,我要感谢 Gregor Sturm 提出了一个伟大的想法,让我们可以将 T21 的笔记本和传统的 Jupyter 笔记本配对,并感谢他对这个项目的反馈。Eric Lebigot 和 Franç ois Wouts 关于如何推进和沟通项目的建议非常有帮助。最后,我要感谢早期的测试人员花时间在 Jupyter 笔记本和 Jupytext 上尝试新的协作方式。
反馈
Jupytext 很大程度上归功于用户的反馈。欢迎提出建议和问题:请在我们的 GitHub 项目中使用问题跟踪器,以便对程序或文档提出改进建议。那里见!
介绍 K-FAC
大规模深度学习的二阶优化方法
Photo by Nareeta Martin on Unsplash
在本文中,我总结了 Kronecker-factored 近似曲率(K-FAC) (James Martens et al .,2015),深度学习最高效的二阶优化方法之一。
概观
曲率的繁重计算限制了二阶优化方法在深度学习中的应用数量。Kronecker-factored approximated Curvature(K-FAC)是由多伦多大学的 James Martens 和 Roger Grosse 在 ICML2015 中提出的一种深度学习的二阶优化方法,通过 Kronecker 因子分解来逼近曲率,降低了参数更新的计算复杂度。得益于包括 K-FAC 在内的高效二阶方法,ML 研究人员现在开始重新审视二阶方法快速收敛对于减少深度学习训练时间的好处。
自然梯度下降
自然梯度下降(NGD) 是由甘利顺一(Shun-Ichi Amari)在 1998 年提出的一种基于信息几何的优化方法。NGD 通过使用费希尔信息矩阵(FIM) 作为损失函数的曲率,正确地获得损失情况,并且在“迭代”方面比简单的一阶方法(例如随机梯度下降)收敛得更快。因此,人们可以把 NGD 看作二阶优化的有效实现。
给定 x ,输出条件概率为 y 的概率模型的 FIM 定义如下:
Fisher information matrix (Empirical Fisher)
这个取数据期望值的定义叫做 经验费希尔 (当你使用小批量时,你计算其中数据的平均值来得到 FIM)。在图像分类任务中,由于人们经常使用负对数似然的平均值作为损失函数,因此可以将 FIM 视为损失函数的曲率的近似。下面的等式显示了 FIM 和负对数似然损失 E(θ)的 Hessian 之间的关系:
The loss function
The Hessian of the loss function and the relationship between the FIM
NGD 的更新规则是:
The update rule of Natural Gradient Descent (NGD)
这里,FIM 的逆过程应用于损失梯度,FIM 预处理的梯度称为自然梯度。对于 N 的参数,FIM 的大小是 N×N,深度学习中使用的神经网络往往具有大量的参数(例如,用于 ImageNet 分类的 AlexNet 中的 6000 万个参数),因此 FIM 的逆是难以处理的,并且它限制了 NGD 在深度学习中的应用数量。
自然梯度近似方法
近年来,一些作品提出了近似(或避免)反演 FIM 的方法,深度学习研究者重温了 NGD 的“快速收敛”。
粗略地说,有三种近似方法(我引用了这篇文章进行这种分类。)
- 近似 Fisher 信息矩阵(以便逆矩阵易于计算)
- 重新参数化,使 FIM 更接近单位矩阵。
- 直接逼近自然梯度。
The three approaches for approximating NGD
使用克罗内克因子分解(K-FAC)的近似
Approximation of (inverse of) FIM by K-FAC
可以将 K-FAC 视为自然梯度近似方法之一,其对应于“1。近似 Fisher 信息矩阵(这样逆矩阵容易计算)”。特别地,与其他自然梯度近似方法相比,它是基于数学原理的最有效的近似方法。
首先,K-FAC 块对角化 FIM,其中每个对角块对应于神经网络每层的参数。例如,K-FAC 将三层网络的 FIM 近似为具有三个块的块对角矩阵。
接下来,K-FAC 用两个矩阵的 Kronecker 积来近似每个块(称为 Kronecker 因式分解)。
Kronecker product of two matrices
最后,K-FAC 使用矩阵的 Kronecker 积的临界性质:
The inverse of Kronecker product = Kronecker product of the inverse matrices
简而言之,K-FAC 将 FIM 的逆近似为块对角矩阵,其中每个对角块是微小克罗内克因子的逆(与 FIM 相比)。
为了阐明克罗内克因子的大小(你可以降低多少求逆的复杂度),我解释一下克罗内克因子分解的机制。以一个全连接层为例,你可以看到如何因式分解 FIM 的一个对角块(为方便起见,称为 Fisher 块)对应于这个层。第 I 层中的 Fisher 块表示为
The Fisher block of i-th layer (i-th diagonal block of the FIM)
(期望值的符号被简化。)其中∇i 是第 I 层参数的梯度。通过使用反向传播方法,这是一种在深度神经网络中计算梯度的有效方法,对数似然的梯度(对于每个样本)被表示为两个向量的克罗内克乘积:
利用这种关系,费希尔区块可以转化为“克罗内克乘积的期望值”的形式:
K-FAC 将“克罗内克积的期望值”近似为“期望值的克罗内克积”(克罗内克因式分解)。
Kronecker factorization of a Fisher block by K-FAC
如上所述,Kronecker 因式分解显著降低了 Fisher 块逆运算的计算复杂度。以图像分类领域经常使用的架构 AlexNet 为例,可以更清晰地看到这种效果。下图显示了 Alex net for ImageNet(1000 类分类)的所有层和最后一层(全连通层)的矩阵大小的比较结果。
AlexNet for Imagenet (1,000 classification)
总结到目前为止,可以说 K-FAC 是一种自然梯度近似方法,它执行以下三个过程。
- 通过费希尔信息矩阵的块对角化(每个对角块对应于每一层),忽略“跨层参数”的相关性。
- 还有一种使用分块三对角的方法(考虑相邻层参数的相关性)。
- 通过对每个对角块(Fisher 块)的 Kronecker 分解,忽略每层中“输入”和“输出梯度”之间的相关性。
- 通过 1,2 的近似,有效地计算费希尔信息矩阵的逆矩阵,以产生自然梯度。
在这里,我为全连接层引入了 K-FAC,但是在卷积层的 K-FAC 中,除了 2 之外,还应用了更多的近似。(参考论文。)
最后,以图像数据集 CIFAR-10 的分类任务(10 类分类)为例,说明了 K-FAC 的有效性。下图显示了随机梯度下降法(SGD)、无任何近似的自然梯度下降法(NGD)和 K-FAC 的训练曲线的比较。
The comparison of training of ConvNet for CIFAR-10 dataset. Solid line: train, dashed line: validation
你可以看到 NGD 在“迭代次数”上比 SGD 收敛得快,但是在 NGD,每次迭代的计算时间很长,所以你也可以看到“经过的时间”比 SGD 晚。另一方面,K-FAC 在“迭代次数”方面很好地再现了 NGD 的训练曲线,并且在“经过的时间”方面也比“SGD”快
这种快速收敛促使引入了 K-FAC 等自然梯度近似方法,但 K-FAC 在 ImageNet 等大规模深度学习中的应用受到限制,之前没有人针对 SGD 验证过有效性。
K-FAC 的应用
- 递归神经网络(RNN)
,
詹姆斯·马滕斯,吉米·巴,
ICLR2018。 - 强化学习
基于克罗内克因子自然梯度的最近策略优化实证分析,
宋家明,吴,
arXiv:1801.05566【cs .AI],2018 年 1 月。 - 贝叶斯深度学习
噪声自然梯度作为变分推理,
张国栋,孙升阳,大卫·杜文瑙,罗杰·格罗斯,
arXiv:1712.02390【cs .LG],2018 年 12 月。
K-FAC 的实现
- 张量流
https://github.com/tensorflow/kfac - py torch
https://github.com/yaroslavvb/kfac_pytorchT21【在本帖中介绍) - 链轮
https://github.com/tyohei/chainerkfac
结论
在本文中,我解释了自然梯度法的近似方法之一 K-FAC 的概要。我牺牲了数学的严谨性,致力于直观的理解。
pydbgen 简介:一个随机数据帧/数据库表生成器
通常,SQL 或数据科学的初学者都很难轻松访问大型样本数据库文件()。DB 或**。sqlite** )用于练习 SQL 命令。如果有一个简单的工具或库来生成一个包含多个表的大型数据库,并用自己选择的数据填充,岂不是很棒?
当你开始学习和实践数据科学时,通常最大的担忧不是算法或技术,而是原始数据的可用性。幸运的是,网上有许多高质量的真实数据集可供尝试很酷的机器学习技术。但是,从我个人的经验来看,我发现在学习 SQL 的时候,情况并非如此。现在,对于数据科学来说——对 SQL 有一个基本的熟悉几乎和知道如何用 Python 或 r 编写代码一样重要,但是访问一个足够大的包含真实数据(比如姓名、年龄、信用卡、SSN、地址、生日等)的数据库。)远不如访问 Kaggle 上专门为机器学习任务设计或管理的玩具数据集常见。
如果有一个简单的工具或库来生成一个包含多个表的大型数据库,并用自己选择的数据填充,岂不是很棒?
除了数据科学的初学者之外,即使是经验丰富的软件测试人员也会发现拥有一个简单的工具是很有用的,在这个工具中,他们只需要几行代码就可以生成任意大的数据集,其中包含随机的(伪造的)但有意义的条目。
我很高兴介绍一个轻量级的 Python 库,叫做 pydbgen 。你可以在这里阅读关于套餐的详细信息。我将在这篇短文中讨论类似的细节。
pydbgen 到底是什么?
这是一个轻量级的纯 python 库,可以生成任意有用的条目(例如,姓名、地址、信用卡号、日期、时间、公司名称、职位、车牌号码等)。)并将它们保存在 Pandas dataframe 对象中,或者作为数据库文件中的 SQLite 表,或者保存在 MS Excel 文件中。
怎么安装?
它(当前版本 1.0.5)托管在 PyPI (Python 包索引库)上。记住你需要安装 Faker 来完成这项工作。所以,只要输入,
pip install pydbgen
注意,它目前只在 Python 3.6 上测试过。它在 Python 2 安装上不起作用。
怎么用?
你必须启动一个pydb对象来开始使用它。
import pydbgen
from pydbgen import pydbgen
myDB=pydbgen.pydb()
之后,您可以访问由**pydb**
对象公开的各种内部函数。例如打印随机美国城市,
**myDB.city_real()**
>> 'Otterville'for _ in range(10):
print(**myDB.license_plate()**)
>> 8NVX937
6YZH485
XBY-564
SCG-2185
XMR-158
6OZZ231
CJN-850
SBL-4272
TPY-658
SZL-0934
如果你只是说’城市’而不是’城市 _ 真实’,你会得到虚构的城市名称:)
print(myDB.gen_data_series(num=8,data_type='city'))
>>
New Michelle
Robinborough
Leebury
Kaylatown
Hamiltonfort
Lake Christopher
Hannahstad
West Adamborough
如何用随机条目生成熊猫数据帧?
您可以选择要生成多少数据和什么数据类型。注意,所有内容都以字符串/文本的形式返回。
testdf=**myDB.gen_dataframe**(5,['name','city','phone','date'])
testdf
产生的数据帧如下所示:
如何生成数据库表?
您可以选择要生成多少数据和什么数据类型。注意,数据库的所有内容都以 text/VARCHAR 数据类型返回。您可以指定数据库文件名和表名。
**myDB.gen_table**(db_file='Testdb.DB',table_name='People',
fields=['name','city','street_address','email'])
这将生成一个. DB 文件,可用于 MySQL 或 SQLite 数据库服务器。生成的数据库表在 DB Browser for SQLite 中打开,如下所示:
如何生成 Excel 文件?
与上面类似,只需使用下面的代码生成一个带有随机数据的 Excel 文件。注意,“simple_phone”设置为 False,从而生成复杂的长格式电话号码。这对于试验更复杂的数据提取代码来说很方便!
myDB.gen_excel(num=20,fields=['name','phone','time','country'],
***phone_simple=False***,filename='TestExcel.xlsx')
结果文件看起来像…
一个很酷的方式来生成随机电子邮件 id 的废料使用?
pydbgen 中的一个内置方法是realistic_email
,它从种子名称生成随机的电子邮件 id。你能想到这种方法在网络上的任何用途吗?你不想给出你真实的电子邮件 ID,而是一些相近的东西。
for _ in range(10):
print(myDB.realistic_email('Tirtha Sarkar'))
>>
Tirtha_Sarkar@gmail.com
Sarkar.Tirtha@outlook.com
Tirtha_S48@verizon.com
Tirtha_Sarkar62@yahoo.com
Tirtha.S46@yandex.com
Tirtha.S@att.com
Sarkar.Tirtha60@gmail.com
TirthaSarkar@zoho.com
Sarkar.Tirtha@protonmail.com
Tirtha.S@comcast.net
未来改进和用户贡献
当前版本是 1.0.5,可能包含许多 bug。如果你注意到任何和你的程序在执行过程中崩溃(除了你的错误输入),请让我知道。此外,如果你有很酷的想法来贡献源代码,那么 Github repo 全部为你开放。一些问题很容易浮现在脑海中,
- 我们能否将一些机器学习/统计建模与这个随机数据生成器集成在一起?
- 生成器是否应该增加可视化功能?
可能性无穷无尽,令人兴奋……
如果您有任何问题或想法要分享,请联系作者在tirthajyoti【AT】Gmail . com。你也可以查看作者的 GitHub 资源库 中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。如果你像我一样对机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。
介绍 ReviewNB:Jupyter 笔记本的代码审查
我们很高兴地宣布 ReviewNB ,这是一款帮助您对 Jupyter 笔记本进行版本控制&的工具。
问题
Jupyter 非常适合数据探索,但是很难超越这个范围&使用它进行协作。将 Jupyter 笔记本电脑与现代版本控制系统(如 Git)配合使用存在以下挑战:
- 笔记本差难读。因此我们不能在 GitHub 上做代码审查
- 由于笔记本文件的 JSON 格式,合并远程更改很困难。ipynb)
- 没有简单的方法来分享反馈&围绕笔记本电脑进行讨论
- 重现笔记本结果并不容易
- 测试笔记本代码单元并不容易
解决办法
ReviewNB 旨在从差异、代码审查和协作入手解决这些问题
- 我们为笔记本电脑打造了一流的视觉差异。更多例子在我们的主页上。
Visual Diff for Jupyter Notebooks
- 您可以在 repo 中浏览 GitHub 提交、拉取请求或打开笔记本文件&在笔记本单元格上写评论以提出改进建议、寻求澄清,或者只是为您同事的工作鼓掌!
Conversation Threads to Track All Ongoing Discussions
它是如何工作的?
- ReviewNB 是 GitHub marketplace 上提供的 GitHub 应用(我们的应用通过 GitHub 的验证)
- ReviewNB 与 GitHub APIs 通信,以获取在提交或拉取请求中所做的笔记本更改。我们以并排差异的格式向用户展示这些变化。所有笔记本内容(降价、代码、图像、公式)都以 Jupyter UI 中的方式呈现。这种视觉差异比笔记本常见的混乱 JSON 差异更具可读性。
- 您还可以在 pull 请求中的笔记本单元格上,甚至在独立的笔记本文件上写注释。您的队友将会收到评论的电子邮件通知&任何人都可以表达他们的想法。
工作流程
ReviewNB 使用起来超级简单。它不需要任何本地安装或配置。人们可以在不到一分钟的时间内在他们的 GitHub 库上开始使用它。
- 任何人都可以通过 GitHub 登录并选择 ReviewNB 有权访问的存储库(需要大约 30 秒)。
- 登录后,您可以在存储库上浏览提交或拉取请求。
Browse notebooks, commits & pull requests on ReviewNB
- 就是这样!您可以开始看到任何提交或拉请求的可视差异,并开始与您的同事进行讨论!
为我们的路线图做出贡献
我们在露天建造。你可以查看即将推出的新功能,为它们投票,甚至申请一个新功能。
暂时就这样吧!在我们的网站上有更多的信息,还有一个精心制作的常见问题解答部分供你询问其他问题。我们还为有兴趣自行运行 ReviewNB 的公司提供自托管选项。如果你有任何问题,我可以在 amit@reviewnb.com 找到你。试试 ReviewNB,让我知道你对它的看法!
原载于 2018 年 10 月 24 日blog.amirathi.com。
与 tsalib 图书馆的 Tensors 成为朋友
tldr: [tsalib](https://github.com/ofnote/tsalib)
是为张量定义维度名称和命名形状表达式的库。允许变量上的形状标签、形状断言和使用名称的直观形状转换。使用任意张量库。显式形状注释加速了深度学习程序的调试,并提高了开发人员的生产率和代码可读性。
源代码可在 github 资源库 获得。
更新(2019 年 11 月):检查我们的库 tsanley 到注释和动态检查命名的形状。使用 tsanley,您可以避免编写显式的形状断言,并自动注释您想要重用的第三方深度学习代码。
编写操纵张量的深度学习程序(例如,使用numpy
、pytorch
、tensorflow
、keras
…)要求你仔细记录张量变量的形状。当你编写更复杂的程序时,在你的头脑中思考这些图形变得越来越困难。例如,当创建一个新的RNN
细胞或设计一种新的attention
机制或试图做一个非平凡的预训练架构的手术(resnet101
,densenet
)。不幸的是,没有在代码中跟踪形状的原则性方法——大多数开发人员求助于编写嵌入代码中的特别注释来跟踪张量形状。
例如,考虑一下最近流行的来自 Google 的 BERT 模型实现的片段。注意每条语句是如何被其input
和output
形状标记的。没有这种明确的形状跟踪,实际上不可能编写和调试复杂的张量程序。
Code from BERT implementation from Google.
同样,考虑 tensorflow 教程中的这个 CNN 模型。注意每个语句是如何用其input
和output
形状来标记的,以帮助开发人员。因为形状可能是动态的,所以这些注释同时包含了参数 (batch_size)和常量 (28)。
随着网络架构变得复杂,这些注释对于保持开发人员的理智以及其他人理解和扩展代码变得非常重要。不幸的是,没有对这些注释的本地支持,工程师们继续编写特别注释来填补空白。事实上,从业者一直在向 T21 寻求更好的支持。
张量形状注释
美国运输安全管理局图书馆 ( tsalib
)来帮你了。
- 该库允许您定义自定义维度变量( B =Batch, C =Channels,…)以及它们的张量形状表达式。
tsalib
不触及代码所依赖的张量库的内部——适用于任何张量库(numpy
、tensorflow,
、pytorch
等等)。- 直接在代码中用其形状表达式标注张量变量,作为一级类型标注。
- 您可以使用 TSA 直接构建(清晰的)形状变换(
reshape
、permute
、axis
索引)和简洁的矩阵/张量运算——稍后将详细介绍。
这里是使用 TSAs 的简单张量程序(代码在这里可用)。注意变量a
、b
和c
是如何用它们的形状标注的。形状标注,例如(2,B,D)
既可以包含常量,也可以包含命名的尺寸变量 ( B
、D
)。请注意代码是如何立即变得更具可读性的——您可以简单地浏览一下形状注释,发现由numpy
函数执行的形状转换(即使您不熟悉 API)。
尺寸变量,形状表达式
该库背后的核心思想是维度变量及其表达式。
[tsalib](https://github.com/ofnote/tsalib)
允许你为你的架构声明自定义维度变量,在形状注释中使用它们,并像普通 Python 变量一样对它们执行算术运算。- 声明包括可选的大小默认值和简写名称。用 dim 变量(
B
、D
)替换您的配置参数(batch_size
、embed_dim
)。在代码的所有部分只使用 dim 变量。
TSA 在很多方面都很有用。
- 当编写新的转换或修改现有模块时,它们帮助我们快速地交叉检查和调试变量形状。
- TSA 作为有用的文档来指导其他人理解或扩展你的模块。
- 周围有明确的形状是有益的,原因有几个(见下文)。
- TSA 不会以任何方式影响程序的性能或正确性。您可以根据需要或多或少地添加注释。
示例:带 TSAs 的 Resnet
这里有一个更复杂的例子,一个来自pytorch
torchvision
库的resnet
模块。这个模块是多个resnet
实现的基础:resnet{18,34,50,101,152}
。现在,通过查看__init__
和_make_layer
模块很难获得对架构的任何洞察,即使你直觉地非常了解架构。因此,你也不能理解forward
函数。
Resnet Implementation (Pytorch)
现在,让我们看看带注释的forward
函数。无需了解各组件层的细节,TSA 允许您发现模块的预期输入(图像)的形状x
以及它如何被每一层转换。如果您正在重用该模块,例如在SSD
中用于对象检测,或在U-Net
中用于分割,您可以一目了然地读出所有中间层的形状。
请注意在命名维度上编写算术表达式的能力是多么有帮助。配置变量(num_classes
)可以直接在形状中使用。同样,很明显,架构是通过块扩展变量Ex
来参数化的(在较小的 resnetss 中为 1,在较大的 resnet 中为 4)。
基于注意力的架构,例如 Transformer,也深受不透明问题的困扰。参见TSA lib/examples/open ai _ transformer . py(注释从 AllenNLP 的实现开始)了解 TSA 如何显著影响代码的可读性。同样,通过浏览前进模块,我们可以快速了解架构。解剖一个多头注意力架构现在是小菜一碟!
形状变换,速记符号
一旦代码中有了维度变量,我们就可以利用它们来进一步提高代码的生产率和清晰度。我们可以使用维度变量直接指定视图和置换转换。例如,这就是从 AllenNLP 库中在原始openai_transformer.py
中实现merge_heads
的方式。
现在,我们可以使用tsalib
简洁地编写它。所有形状都是显式的,不再需要代码操作。通过使用它们的速记string
表示代替元组,形状注释可以变得更加简洁,例如用'bcd'
代替(B,C,D)
。tsalib
允许使用快捷键来指定转换。在这里阅读更多。
在所有张量库(numpy,pytorch,tensorflow)中拥有类似 TSA 的原生支持将对从业者极为有益。然而,这可能涉及到严重的 重新设计。相比之下,TSA 是独立于库的、轻量级的和即插即用的。你可以从今天开始在你的深度学习项目中使用它们!
一定要给[tsalib](https://github.com/ofnote/tsalib)
一次机会,并给我发送反馈——通过 twitter 联系我,或者直接给我发电子邮件。
库内部
类型注释(或类型提示)是 Python 3 中一个受支持的可选特性。随着 Python 3 的改进和被广泛采用,对注释和类型检查的支持也在改进。例如, AllenNLP 的人在他们的代码中使用类型和形状注释,并且推荐作为最佳实践。
tsalib
内部使用一个奇妙的符号表达式库[sympy](https://www.sympy.org/)
来构建和转换表达式。sympy
是它唯一的依赖。
**关于我:**我是一名独立的计算机科学研究员、工程师和演讲者,喜欢提炼复杂的技术并将其转化为可消费的产品。我在学术界、工业界和初创公司都工作过。我帮助公司理解和应对复杂、不断发展的人工智能空间,并构建基于深度学习的解决方案,以最大化投资回报。如果你喜欢这篇文章,请鼓掌并发表你的评论。你可以关注我,在这里阅读我的其他文章,在 linkedin 上找到我,或者直接发邮件给我。
TFServe 简介:用于 tensorflow 模型推理的简单易用的 HTTP 服务器
机器学习最有趣(也是最有趣)的部分是利用你花时间训练的模型。虽然有很多关于如何训练模型的资源,但我们经常发现很难弄清楚如何部署一个使用训练好的模型进行推理(即进行预测)的系统。TFServe 是一个框架,旨在通过 HTTP 服务器以简单和容易的方式为 tensorflow 模型提供服务。
TFServe 是构建在 apistar 之上的微框架。要安装它,只需运行:
$ pip install tfserve
如何使用 TFServe?
让我们从这个常见的场景开始。你已经发现了一个惊人的 Tensorflow Inception CNN 模型,该模型由 Google 在 ImageNet 上训练。您 希望构建一个使用该模型进行推理的 HTTP 服务。
从描述中可以看出,该模型接收 224x224 的标准化 RGB 图像,并返回最可能的类(从 ImageNet 中的 1000 个类中)。你下载模型,得到一个frozen_graph.pb
(或者类似的)文件。
现在怎么办?关于如何让它运行的说明涉及到关于模型架构(你对此一无所知)、TF 服务或其他工具的知识。运行 HTTP 服务器进行推理有多难?这里是 **tfserve**
发挥作用的地方:
你需要 5 个零件:
- 模型文件:可以是
.pb
文件,也可以是包含ckpt
文件的模型目录。 - 输入张量名称:图形输入张量的名称。
- 输出张量名称:图形的输出张量名称。
encode
: python 函数,接收请求体数据并输出一个dict
映射输入张量名称到输入 numpy 值。decode
: python 函数,接收一个dict
映射输出张量名称到输出 numpy 值并返回 HTTP 响应。
输入和输出张量名称?
您可能知道,每个张量流图张量都有一个唯一的名称。这个名称是在创建图形时声明的。你需要向tfserve
指定输入张量的名称。输出张量也是如此。
但是我已经从一些 Tensorflow repo 下载了这个模型,我不知道输入/输出张量的名称!
不要惊慌。只需使用 tfserve.helper.estimate_io_tensors
函数了解可能的 i/o 张量供您选择。
举个例子,
> import tfserve import helper
> helper.estimate_io_tensors("frozen_model.pb")Possible INPUT tensors:
import/img:0
Possible OUTPUT tensors:
pred/out:0
pred/softmax_out:0
*太好了!*我将需要
import/img:0
作为我的输入张量,需要pred/softmax_out:0
作为我的输出张量(这将是一个多类概率分布)。
编码功能
实现一个函数,该函数接收 HTTP 请求主体数据并输出一个将输入张量名称映射到输入numpy
值的dict
。
在图像分类示例之后,encode
函数将接收 HTTP 请求主体中提供的二进制数据,并应输出一个映射“import/img:0
”到 224x224 标准化 RGB numpy
图像的dict
:
def encode(request_data):
with tempfile.NamedTemporaryFile(mode="wb", suffix=".jpg") as f:
f.write(request_data)
img = PIL.Image.open(f.name).resize((224, 224))
img = np.asarray(img) / 255.
return {"import/img:0": img}
解码功能
实现一个函数,该函数接收将输出张量名称映射到输出值并返回 HTTP 响应。
在图像分类示例之后,decode
函数将接收到一个将“pred/softmax_out:0
”映射到一个 1000 大小的数组的dict
映射,该数组具有分类概率。我希望返回一个 JSON 对象,如下所示:
{
class: "german shepard",
prob: 0.98,
}
它包含关于最可能的类的信息。
然后,decode
功能将会是:
def decode(outputs):
p = outputs["pred/softmax_out:0"]
index = np.argmax(p)
return {
"class": index_to_class_name(index),
"prob": float(p[index])
}
运行服务器
您现在可以运行提供上述所有 5 个部分的服务器(模型路径、输入张量、输出张量、 *encode*
和 *decode*
函数):
from tfserve import TFServeAppapp = TFServeApp("frozen_graph.pb", ["import/img:0"],
["pred/softmax_out:0"], encode, decode)app.run('127.0.0.1', 5000, debug=True)
如何向模型发送实际图像?
服务器将在127.0.0.1:5000
启动并运行。为了运行模型,您应该向/
发送一个**POST**
请求,并将二进制图像作为请求体。您应该得到在decode
函数中实现的 JSON 响应。
Using the server through Postman
您可以在请求正文中提供任何类型的数据。你只需要在encode
函数中正确处理它,就可以得到图形的输入张量。
此外,您可以在 HTTP 响应中返回任何类型的数据(例如,除了 JSON 对象之外,它还可以包含带有分段信息的二进制图像)。您只需要在decode
函数中构建响应。
结论
有了tfserve
,运行一个 tensorflow 训练好的模型真的简单又容易。只需提供模型路径、输入/输出张量名称、将请求数据转换成输入张量的encode
函数和将输出张量转换成响应的decode
函数。就是这样!tfserve
会处理剩下的。
有关更多信息,请访问项目网站!
将 TF 模型作为 HTTP API 简单方便地提供。通过在…上创建帐户,为 iitzco/tfserve 的发展做出贡献
github.com](https://github.com/iitzco/tfserve)
*喜欢这个项目吗?*在 github 回购上留个⭐!
引入人工智能定义的基础设施
(AiDI)——因为这不再仅仅是关于软件
软件定义的基础设施(SDI)是数据中心和云环境中最流行和持续的趋势之一,它通过基于脚本和源代码开发基础设施来提高基础设施的灵活性。然而,SDI 越来越成为达到目的的一种手段,因为自动化、复杂的算法以及智能系统正在导致人工智能定义的基础设施(AI 定义的基础设施——AiDI)。
空间数据基础设施并没有消亡,它只是达到目的的一种手段
SDI 从硬件层抽象出软件。因此,智能不再在硬件组件中实现,而是被移到软件堆栈中。SDI 以软件和高度自动化为基础,旨在无需人工干预的情况下构建和控制基础设施。
典型的 SDI 环境,例如云基础设施,是通过开发脚本或源代码来构建的。该软件包括配置整个基础设施环境所需的所有命令,包括运行在基础设施上的应用程序和服务。基于 SDI 的基础设施独立于特定的硬件环境工作。因此,一个完整的基础设施可以通过软件进行交换,而不考虑底层的硬件组件。SDI 是当今云基础设施环境的基础的一个原因。
然而,SDI 一点也不聪明!它基于静态源代码,包括用于自动采取某些动作的硬编码命令。
了解人工智能定义的基础设施(AIDI)
软件定义的基础架构是构建和运行动态 IT 环境的一个重要概念。然而,SDI 仅限于静态源代码以及负责为环境编写脚本/代码的开发人员和管理员的技能。此外,SDI 仅在一定程度上是动态的,因为它不能理解或了解它正在运行的自身环境。
人工智能定义的基础设施(AI-defined infra structure-AiDI)通过必要的复杂算法、机器学习和人工智能来增强 SDI,从而为 SDI 提供智能。AiDI 允许 SDI 建立和运行自我学习和自我修复的基础设施环境。因此,在没有人工交互的情况下,人工智能定义的 IT 基础设施环境能够
- 根据工作负载要求部署必要的资源,并在不再需要时取消资源分配。
- 不断分析每一个基础设施组件不断变化的行为和状态,从而了解自身。
- 通过自主采取行动,根据单个基础架构组件的状态做出反应或主动采取行动,从而使整个基础架构进入无错误状态。
人工智能定义的基础设施无法与经典的自动化软件相比,后者通常使用预定义的脚本。人工智能定义的基础设施利用公司的现有知识,自动独立地执行它。然而,像每一个新生的有机体一样,人工智能定义的基础设施需要训练,但之后可以自主工作。因此,基于学到的知识,可以解决干扰——甚至通过连接过去的适当事件来主动解决未预期的事件。因此,人工智能定义的基础设施实时监控和分析所有响应组件,以基于其现有知识识别和解决问题。解决的事件越多,基础架构知识就越丰富。人工智能定义的基础设施的核心是一个基于知识的架构,可以分析事件和变化,并自主制定策略来解决问题。
此外,人工智能定义的基础设施包含社区以
- 吸收外部专家的知识,变得更加聪明。
- 与其他人工智能定义的基础设施环境连接,以链接、组合和共享他们的知识库。
- 不断扩大知识池。
- 优化知识。
总而言之,人工智能定义的基础设施是一个智能系统,它最初由外部知识驱动,可以在没有人类交互的情况下自主学习和决策。
AIDI 只是整个人工智能定义的企业堆栈的一部分
人工智能定义的基础设施是当今 IT 运营的重要组成部分,为人工智能支持的企业奠定了基础。然而,最重要的是,它使 it 部门能够将基础架构行为从今天的半动态环境转变为真正的实时 IT 环境。
这种规划、构建、运行和维护整个基础架构的自主方式让 IT 运营和开发人员能够以最高效的方式部署 IT 资源,如服务器、存储、网络、数据库和其他现成的服务——利用不止一位专家而是整个 IT 运营团队的知识。此外,IT 运营正从纯粹的资源消费者转变为完全自动化和智能化 IT 体系的协调者和管理者。端到端人工智能就绪企业的基础。
Weacast 简介
Weacast 是一个新的开源平台,用于收集、展示和利用天气预报数据。
为什么选择 Weacast?
现在每天都可以从主要的气象机构获得天气预报数据。当前的天气观测结果通过一个被称为数据同化的过程被输入到数字计算机模型中,以产生对未来天气状况的预测。这些模型从海洋向大气顶部输出数百种其他气象要素,如温度、降水、结冰条件等。例如,下面的动画图像代表了来自 NOAA 的 GFS 天气预报模型的典型输出。
WeacastWeacast(WeacastWeaforecast的快捷方式)旨在提供 web 服务和可视化工具,以简单的方式和格式收集、展示和利用天气预报数据。事实上,尽管公开可用的天气预报数据来自许多不同的来源,采用许多不同的专用协议/格式(例如 WCS 、 GeoTIFF 、 GRIB 等)。),使得在 web 应用程序中消费变得不那么容易,尤其是在客户端。此外,预报数据通常覆盖大片大陆地区,包含数百个要素,如温度、风等。但是一些通常是特定业务用例所需要的。最后但并非最不重要的一点是,预测数据本质上是动态的,因此用最近可用的数据更新您的应用程序始终是一项乏味的任务。
广播哲学
Weacast 是天气预报模型不可知的,也就是说,它主要公开了一个极简框架,可以按需添加预报数据源,以插件式架构扩展其功能。然后,这些数据可以通过简单的 REST/Websocket 服务以 JSON 格式在 Weacast 中获得,并可以使用内置的 web 应用程序进行可视化。
当前支持的插件如下:
Weacast 的目标不仅仅是提供粗略的预测数据,它还包括一些工具,通过以下方式获取您自己的业务数据:
- 探查预测数据,提取或分析您感兴趣的地点的相关数据(如机场、城市、商店等。)
- 查询您探测到的数据,找出哪些位置符合特定的天气条件
- 在特定地点满足某些天气条件时发出警报。
怎么品尝?
首先,您可以根据我们的 Weacast web app 模板来看看我们的展示区,更具体地说:
- 可视化预测数据
This short video demonstrates how Weacast can be used to gather forecast data from different models to visualize and predict wind in different locations.
- 探索预测数据
This short video demonstrates how Weacast can be used to explore forecast data and future wind prediction using a timeline widget.
- 探测预测数据
This short video demonstrates how Weacast can be used to probe your own business data to find locations matching target weather conditions. Using runways data, first are found airports with a target wind direction, then runways with a target wind direction relative to their own orientation.
This short video demonstrates how Weacast can be used to probe your own business data or any location in the world to obtain time series of any forecast elements.
然后你可以试着安装你自己的演示。要全面了解它是如何工作的,请阅读我们的在线文档并开始开发您自己的基于 Weacast 的应用程序!
生产准备好了吗?
Weacast 已经足够可靠,可以在现实世界的应用中使用,因为它主要依赖于一小组经过良好测试的模块: weacast-core 、wea cast-ar page、 weacast-arome 、 weacast-gfs 、 weacast-probe 。虽然这个社区还很新但是为一个大的行业玩家开发的应用已经在生产了。
里面是什么?
Weacast 是可行的,主要由以下堆栈提供支持:
熊猫基础数据分析介绍(慕尼黑私人住宅市场数据集)
这篇文章是上一篇文章(此处链接到媒体)的延续,在那篇文章中,我解释了我为了买房而确定慕尼黑房产市场价值的目标。
因为我得到了数据,在慕尼黑买房子是不可能的,我没有(可能永远也不会)赚到足够的钱来真正意识到这一点,但这些数据仍然很有趣,以便快速浏览熊猫的数据分析。
第一篇文章真正关注的是清理数据,因为为了实现正确的数据分析,您需要干净的数据。否则,在运行代码时,您会遇到很多问题。此外,我真的很喜欢这句话:“垃圾进来,垃圾出去”
如果你不清理你的数据,那么你可能会分析错误的数据点,给你错误的结果。
在这篇文章中,我们将深入探讨熊猫图书馆在数据集分析和一些可视化方面能为你做些什么。我喜欢习语的*【一图胜千言】*。我也非常直观,所以它真的有助于描绘你在数据集中看到的东西。
Pandas 方法概述
在最开始的时候,通过导入数据集的最新版本(你已经清理或从我的 github 帐户中获取的),你可以通过一些方法开始,这些方法会给你一些信息。
import pandas as pd
df = pd.read_csv('data_immo.clean.csv', delimiter='\t')
df.head(1).T ## I like the transpose function as it gives you a better view
using the transpose on one line allows you to see easily type of data and column name
df.describe() ## Always worth checking
你可能已经注意到了,我们对每一列都有相同的计数。多亏了我们的清理,所有剩下的数据都可供我们找到一些有趣的信息。
现在您可能已经意识到,这个数据集是一个时间序列,这意味着有一个类似时间戳的列,这将使您能够看到数据集随时间的演变。这对我们的分析很有用,可以看出是否有进化。
为了设置时间序列,我们需要使用某种方法来确定哪一列包含此信息,以及如何将其转换为 pandas 数据帧。
您可能希望(但不是必须)导入 datetime 库并转换 date_year_month 列。
如果我们想从我们将从这个翻译创建的日期时间列中实际做其他事情,我们导入日期时间。
import datetime
df['date'] = pd.to_datetime(df['date_year_month'],format= '%Y%m') ## This will create a new column that contains your datetime element
##Let's not stop here and analyze the different element identified in that column
df['date'].value_counts() ##Unique values and number of occurences
我们看到 2016 年 4 月、2017 年 5 月和 12 月
的数值较低。
我们需要记住这一点,以免在那一个月得出结论。没有足够的数据来做出任何假设。
从对你的数据集有一个想法开始,你可以实现一些简单的可视化,以便分析你的数据集或只是一个系列。
如果我们想看到价格的分布,我们可以实现这种盒子绘图
ax = df['price'].plot(kind='box', title='box plot visualization - price') #return an object from matplotlib
ax.set_ylabel('price')
ax.set_xlabel('data set')
oh oh… what are those data points near 0 ?
在这里,您可以看到大多数值(25–75%)在 210 k 和 500 K€范围内。
但你也可以看到一些额外的点,更重要的是,似乎有数据点要清理。我们有它的价格,但它是 0,这是不可能的,即使我真的很喜欢这个。
df[df['price'] == df['price'].min()] ## look for the data that match the minimum.
## In case you want to have some margin against the minimum, you can do something like this
df[df['price'] < df['price'].min()*1.1] ## Will take everything below 10% more than the minimum.
## it doesn't work in our case as our minimum is 0 but we can set a hardcap nothing below 50K.
df[df['price'] < 50000]
让我们暂时保存它们,我们以后可以使用这些数据。
我们只是将它们从主要分析中移除,并将它们保存在一个单独的数据框架中。
df_0_price = df[df['price'] < 50000].copy()
df_0_price.reset_index(inplace=True,drop=True) ## let's reset their index
df = df[df['price'] > 50000]
df.reset_index(inplace=True,drop=True) ## let's reset their index
df['price'].plot(kind='box')
This is a lot better
我认为这部分是你在实际工作中所做的一个很好的例子。即使您已经花了一些时间清理您的数据集,当您意识到分析时,您总是会发现一些要清理的东西。这是你真正挖掘数据的时候,你会经常遇到这种情况。重新清理数据。
回到分析,熊猫的一个有趣的方法是看两个变量之间是否有相关性。
为了做到这一点,您可以在 2 个系列之间使用 corr()。
df[['date_year_month','price']].corr()
## returns 0.42 : So positive correlation, price are increasing with time
## note that we are taking the 'date_year_month' data that are a number such as 201801 so it increased over time.
df[['rooms','price']].corr()
## returns 0.093 : No correlation between price and number of rooms.
## But this can be biased by the few number of different room number.
df['rooms'].value_counts()
## returns 3 values 2 (821), 3 (24), 4 (8).
## The over representation of 2 rooms will bias the correlation here.
对您的数据做的一件有趣的事情是通过按分类数据对元素进行分组来反转视图。如果你懂一点 SQL,你会直接对“分组”这个词挠痒痒。是的,熊猫有 groupby 功能,而且很容易使用。
我们可以做的一个有趣的分析是查看每个邮政编码的平均价格。为了有真正的比较,我们将采取每平方米的价格(价格 _ 表面)。
这将返回一个 groupby 对象,最好将它存储在一个变量中。
df_groupby_zip = df.groupby('zip')['price_surface'].mean() ## The good thing is that you can do a groupby on multiple elements.
df_groupby_zip_room = df.groupby(['zip','rooms'])['price'].mean()
这个方法其实很厉害。在这种状态下,它提供了更清晰的视图和查看数据的新方法。你也可能会说“这很好,它摆脱了复杂性,但我想知道实际上发生了什么”
如果我告诉你,你可以使用这种方法来查看发生了什么(聚合了多少数据点),但在一个命令中添加了更多的计算,会怎么样?
df_groupby_zip_agg = df.groupby('zip').agg({'price_surface' : ['mean','count','max']})
什么???在一条线上?
是的,很容易获得每个邮政编码的每平方米平均价格、数据点的数量以及每个群体聚集的最大值。的。agg 绝对是你需要记住的。
正如您可能已经猜到的那样,它只要求我们在字典中添加另一个列名,以便实际考虑另一个列(使用您想要应用于它的适当计算)。
问题出现在这里,因为 price_surface 列将有一个多重索引,这不容易处理。
我用来从 price_surface 数据类型中只选择一列的方法是使用。loc[]选择。
df_groupby_zip_agg.loc[:,('price_surface','mean')]
熊猫可视化
Pandas 集成了 matplotlib 以实现一些简单的可视化。
您已经看到了箱线图,这是一个非常有趣的数据集分布视图。在本文的下一部分,我们将看到如何创建这样的可视化来查看您的数据集。
为了看到可视化效果,您需要编写这行代码:
%matplotlib inline #will generate the graph in your console
正如我之前解释的,我们的数据集很酷的一点是它是一个时间序列。
要真正获得这类数据,您需要将 datetime 列放在索引中。
一旦你这样做了,所有的情节将以时间序列的方式生成。
ddf = df.set_index('date')
ddf_gby_mean = ddf.groupby('date').mean()
ddf_gby_mean[['price_room','price']].plot()
simple visualization
这是一个非常基本的绘图。
你可以改变类型,使用种类属性,但是你可以使用更多的属性。对我来说最有用的是:
- 种类:决定情节的类型,我最喜欢的是 barh 或 bar。
- figsize:使用一个元组来调整图形的大小
- 标题:给你的图表起一个标题
- cmap:使用不同的颜色地图,链接到一些文档
ddf_gby_mean[['price_room','price']].plot(kind='area',title='price per room & price overtime',figsize=(10,7),cmap='tab20')
How better is it ?
你可以清楚地看到从 2016 年 11 月开始的数据集的演变。
我们得到了一个更高的平均价格,这可能是因为最高价格已经提高了。我可以告诉你这是事实,但让我们看看数据来证实这一点。
graph = pd.DataFrame(df.groupby('date').agg({'price':['max','count']})) ##setting a new view with groupby
ax = graph.loc[:,('price','max')].plot(kind='line',title='Maximum price per month',figsize=(13,6))
您可以清楚地看到,我提高了我期望的最高价格。这是因为慕尼黑的物价太高,没有其他选择。
熊猫图形表示非常有用,将帮助您更好地理解您的数据。但是,您也可以使用具有一些高级可视化表示其他绘图库。这个主题本身值得再写一篇博文,但是让我们看看另一篇,它非常容易使用,并且对于额外的图形可视化非常强大:seaborn
import seaborn as sns
sns.relplot(x="construction_year", y="price", hue='rooms',sizes=(20, 400), alpha=.7, height=10, data=df)
很容易通过建筑年份和房间数量来显示价格吗?我们可以看到,市场上的大多数报价(在我的价格范围内)都在 1960 英镑到 1990 英镑之间。甚至有一些建筑预计建造时间会持续到 2020 年。
总的来说,绘图函数的使用通常来自 matplotlib 的包装。因此,您应该真正开始了解这个库是关于什么的,这样您就可以更好地整合它提供的可能性。
我希望这篇文章有助于了解如何使用 pandas 进行基本的数据分析。我计划涵盖更多的主题和可视化,但这已经变得很长了。我会回来的;)
贝叶斯线性回归简介
解释线性建模的贝叶斯方法
贝叶斯与频率主义者的辩论是我觉得观看比参与更有趣的学术辩论之一。我认为学习两种统计推断的方法并在适当的时候应用它们会更有成效,而不是狂热地跳到某一方。按照这种思路,最近,我一直在努力学习和应用贝叶斯推理方法,以补充我的研究生课程中涵盖的频率统计。
在应用贝叶斯推理中,我首先关注的领域之一是贝叶斯线性建模。学习过程中最重要的部分可能只是向他人解释一个想法,这篇文章是我试图介绍贝叶斯线性回归的概念。我们将简要回顾线性回归的 frequentist 方法,介绍贝叶斯解释,并查看应用于简单数据集的一些结果。我在这篇文章中没有提到代码,但是它可以在 Jupyter 笔记本的 GitHub 上找到。
频率线性回归概述
线性回归的 frequentist 观点可能是您在学校中熟悉的观点:该模型假设响应变量(y)是权重乘以一组预测变量(x)的线性组合。完整的公式还包括一个误差项,以说明随机采样噪声。例如,如果我们有两个预测值,等式是:
y 是响应变量(也称为因变量),β是权重(称为模型参数),x 是预测变量的值,ε是一个误差项,表示随机采样噪声或模型中未包含的变量的影响。
线性回归是一个简单的模型,使其易于解释:β_0 是截距项,其他权重β显示了增加预测变量对响应的影响。例如,如果β_1 为 1.2,那么 x_1 每增加一个单位,响应将增加 1.2。
我们可以使用矩阵方程将线性模型推广到任意数量的预测值。将常数项 1 添加到预测值矩阵以说明截距,我们可以将矩阵公式写成:
从训练数据学习线性模型的目标是找到最好地解释数据的系数β。在 frequentist 线性回归中,最好的解释是指最小化残差平方和(RSS)的系数β。RSS 是已知值(y)和预测模型输出(ŷ,发音为 y-hat,表示估计值)之间的总平方差。残差平方和是模型参数的函数:
对训练集中的 N 个数据点求和。我们在此不再赘述细节(查看此参考文献了解推导过程),但该方程具有模型参数β的封闭形式解,可将误差降至最低。这被称为β的最大似然估计,因为在给定输入 X 和输出 y 的情况下,这是最有可能的值。以矩阵形式表示的封闭解为:
(同样,我们必须将“帽子”放在β上,因为它表示模型参数的估计值。)不要让矩阵数学把你吓跑了!感谢像 Python 中的Scikit-learn这样的库,我们通常不必手工计算(尽管编写线性回归代码是一个好的实践)。这种通过最小化 RSS 来拟合模型参数的方法被称为普通最小二乘法 (OLS)。
我们从 frequentist 线性回归中获得的是仅基于训练数据的模型参数的单一估计。我们的模型完全由数据提供信息:在这个视图中,我们需要知道的模型的一切都编码在我们可用的训练数据中。
一旦有了β-hat,我们就可以通过应用我们的模型方程来估计任何新数据点的输出值:
以 OLS 为例,我们可以对 15000 次锻炼观察的持续时间和消耗的卡路里的真实世界数据进行线性回归。下面是通过求解模型参数的上述矩阵方程获得的数据和 OLS 模型:
有了 OLS,我们得到了模型参数的一个单个估计,在这种情况下,就是线的截距和斜率。我们可以写出 OLS 提出的方程:
calories = -21.83 + 7.17 * duration
根据斜率,我们可以说,每增加一分钟的锻炼,就会多消耗 7.17 卡路里。这种情况下的截距并没有那么有帮助,因为它告诉我们,如果我们运动 0 分钟,我们将燃烧-21.86 卡路里!这只是 OLS 拟合过程的一个产物,该过程找到最小化训练数据上的误差的线,而不管它在物理上是否有意义。
如果我们有一个新的数据点,比如说锻炼持续时间为 15.5 分钟,我们可以将它代入等式,得到燃烧卡路里的点估计值:
calories = -21.83 + 7.17 * 15.5 = 89.2
普通最小二乘法为我们提供了输出的单点估计,我们可以将其解释为给定数据的最有可能的估计。然而,如果我们有一个小的数据集,我们可能希望将我们的估计表示为可能值的分布。这就是贝叶斯线性回归的用武之地。
贝叶斯线性回归
在贝叶斯观点中,我们使用概率分布而不是点估计来制定线性回归。响应 y 不是作为单个值来估计的,而是假设从概率分布中提取的。响应从正态分布取样的贝叶斯线性回归模型为:
输出 y 由以平均值和方差为特征的正态(高斯)分布产生。线性回归的平均值是权重矩阵的转置乘以预测矩阵。方差是标准差σ的平方(乘以单位矩阵,因为这是模型的多维公式)。
贝叶斯线性回归的目的不是找到模型参数的单个“最佳”值,而是确定模型参数的后验分布。不仅响应是由概率分布生成的,而且模型参数也被假定来自一个分布。模型参数的后验概率取决于训练输入和输出:
这里,P(β|y,X)是给定输入和输出的模型参数的后验概率分布。这等于数据的似然性 P(y|β,X)乘以参数的先验概率并除以归一化常数。这是贝叶斯定理的一个简单表达式,贝叶斯推理的基础:
让我们停下来想想这意味着什么。与 OLS 相反,我们有一个模型参数的后验分布,它与数据的可能性乘以参数的先验概率成正比。在这里,我们可以观察到贝叶斯线性回归的两个主要好处。
- **先验:**如果我们有领域知识,或者对模型参数应该是什么的猜测,我们可以将它们包括在我们的模型中,不像 frequentist 方法那样假设关于参数的所有知识都来自数据。如果我们事先没有任何估计,我们可以使用无信息先验来获得正态分布等参数。
- **后验:**执行贝叶斯线性回归的结果是基于数据和先验的可能模型参数的分布。这使我们能够量化我们对模型的不确定性:如果我们有更少的数据点,后验分布将更加分散。
随着数据点数量的增加,似然性会冲掉先验,在无限数据的情况下,参数的输出会收敛到从 OLS 获得的值。
将模型参数公式化为分布概括了贝叶斯世界观:我们从最初的估计开始,我们的先验,随着我们收集更多的证据,我们的模型变得不那么错误。贝叶斯推理是我们直觉的自然延伸。通常,我们有一个初始假设,当我们收集支持或反对我们想法的数据时,我们改变了我们的世界模型(理想情况下,这是我们推理的方式)!
实现贝叶斯线性回归
在实践中,对于连续变量,评估模型参数的后验分布是困难的,因此我们使用抽样方法从后验中抽取样本,以近似后验。从分布中抽取随机样本来近似分布的技术是蒙特卡罗方法的一个应用。蒙特卡洛采样有多种算法,最常见的是马尔可夫链蒙特卡洛的变体(关于 Python 中的应用,参见本文)。
贝叶斯线性建模应用
我将跳过这篇文章的代码(有关 PyMC3 中的实现,请参见笔记本),但实现贝叶斯线性回归的基本过程是:指定模型参数的先验(在本例中我使用了正态分布),创建一个将训练输入映射到训练输出的模型,然后让马尔可夫链蒙特卡罗(MCMC)算法从模型参数的后验分布中抽取样本。最终结果将是参数的后验分布。我们可以检查这些分布来了解发生了什么。
第一个图显示了模型参数的后验分布的近似值。这些是 1000 步 MCMC 的结果,意味着该算法从后验分布中提取了 1000 步。
如果我们将斜率和截距的平均值与 OLS 的进行比较(OLS 的截距为-21.83,斜率为 7.17),我们会发现它们非常相似。然而,虽然我们可以使用平均值作为单点估计,但我们也有模型参数的一系列可能值。随着数据点数量的增加,该范围将缩小并收敛到一个单一值,该值代表模型参数的更大置信度。(在贝叶斯推理中,变量的范围被称为可信区间,它的解释与频率推理中的置信区间略有不同)。
当我们想要显示贝叶斯模型的线性拟合,而不是只显示估计值时,我们可以绘制一系列线,每条线代表模型参数的不同估计值。随着数据点数量的增加,线条开始重叠,因为模型参数中的不确定性减少了。
为了演示模型中数据点数量的影响,我使用了两个模型,第一个模型使用了 500 个数据点,左边显示了结果拟合,右边的模型使用了 15000 个数据点。每个图显示了从模型参数后验中提取的 100 个可能的模型。
Bayesian Linear Regression Model Results with 500 (left) and 15000 observations (right)
当使用较少的数据点时,拟合中有更多的变化,这代表了模型中更大的不确定性。对于所有的数据点,OLS 和贝叶斯拟合几乎是相同的,因为先验被数据的可能性冲掉了。
当使用我们的贝叶斯线性模型预测单个数据点的输出时,我们也得不到单个值,而是一个分布。下面是运动 15.5 分钟消耗卡路里数的概率密度图。红色垂直线表示来自 OLS 的点估计。
Posterior Probability Density of Calories Burned from Bayesian Model
我们看到,燃烧卡路里数的概率峰值在 89.3 左右,但完整的估计是一个可能值的范围。
结论
不要在贝叶斯与频率主义的辩论(或任何争论)中偏袒任何一方,学习这两种方法更有建设性。这样,我们可以在正确的情况下应用它们。
在我们只有有限的数据或有一些先验知识要在我们的模型中使用的问题中,贝叶斯线性回归方法既可以包含先验信息,又可以显示我们的不确定性。贝叶斯线性回归反映了贝叶斯框架:我们形成一个初始估计,并在收集更多数据时改进我们的估计。贝叶斯观点是一种直观的看待世界的方式,贝叶斯推理是一种有用的替代方式。数据科学不是站在哪一边,而是找出工作的最佳工具,掌握更多技术只会让你更有效率!
一如既往,我欢迎反馈和建设性的批评。可以通过推特 @koehrsen_will 联系到我。
来源
- https://www . quant start . com/articles/Bayesian-Linear-Regression-Models-with-pymc 3
- http://twiecki.github.io/blog/2013/08/12/bayesian-glms-1/
- https://wise odd . github . io/tech blog/2017/01/05/Bayesian-regression/
- PyMC3 简介
贝叶斯网络简介
贝叶斯网络是一种概率图形模型,使用贝叶斯推理进行概率计算。贝叶斯网络旨在通过用有向图中的边来表示条件依赖,从而对条件依赖以及因果关系进行建模。通过这些关系,人们可以通过使用因子有效地对图中的随机变量进行推断。
可能性
在深入到底什么是贝叶斯网络之前,首先回顾一下概率论是很有用的。
先记住随机变量 A_0,A_1,…,A_n 的联合概率分布,记为 P(A_0,A_1,…,A_n),由概率的链式法则,等于 P(A_1 | A_2,…,A_n) * P(A_2 | A_3,…,A_n) * … * P(A_n)。我们可以认为这是分布的分解表示,因为它是局部概率的 N 个因子的乘积。
接下来回想一下两个随机变量 A 和 B 之间的条件独立给定另一个随机变量 C,等价于满足以下性质:P(A,B|C) = P(A|C) * P(B|C)。换句话说,只要 C 的值已知且固定,A 和 B 就是独立的。另一种表述方式是 P(A|B,C) = P(A|C ),我们稍后会用到。
贝叶斯网络
使用我们的贝叶斯网络指定的关系,我们可以通过利用条件独立性来获得联合概率分布的紧凑、分解的表示。
贝叶斯网络是一个有向无环图,其中每条边对应一个条件依赖,每个节点对应一个唯一的随机变量。形式上,如果连接随机变量 A 和 B 的图中存在一条边(A,B ),则意味着 P(B|A)是联合概率分布中的一个因子,所以我们必须知道 B 和 A 的所有值的 P(B|A ),才能进行推断。在上面的示例中,由于 Rain 具有进入 WetGrass 的边,这意味着 P(WetGrass|Rain)将是一个因子,其概率值在条件概率表中 WetGrass 节点的旁边指定。
贝叶斯网络满足局部马尔可夫性质,该性质声明给定其父节点,节点有条件地独立于其非后代。在上面的例子中,这意味着 P(洒水喷头|多云,雨)= P(洒水喷头|多云),因为洒水喷头有条件地独立于它的非后代,雨,给定多云。这一性质使我们能够将上一节中使用链式法则得到的联合分布简化为更小的形式。简化后,贝叶斯网络的联合分布等于所有节点的 P(node|parents(node))的乘积,如下所示:
在较大的网络中,这一特性使我们能够大大减少所需的计算量,因为一般来说,相对于网络的整体规模,大多数节点的父节点很少。
推理
贝叶斯网络上的推理有两种形式。
第一种是简单地评估网络中每个变量(或子集)的特定赋值的联合概率。为此,我们已经有了联合分布的分解形式,所以我们简单地使用提供的条件概率来评估该产品。如果我们只关心变量的子集,我们将需要边缘化那些我们不感兴趣的变量。在许多情况下,这可能导致下溢,因此通常取该乘积的对数,这相当于将乘积中每一项的单独对数相加。
第二,更有趣的推理任务,是找到 P(x|e),或者,在给定其他变量赋值的情况下,找到变量子集(x)的某个赋值的概率(我们的证据,e)。在上面的示例中,可以找到 P(sprayer,WetGrass | Cloudy ),其中{ Sprinkler,WetGrass}是我们的 x,而{Cloudy}是我们的 e。为了计算这一点,我们使用了 P(x|e) = P(x,e) / P(e) = αP(x,e)这一事实,其中α是归一化常数,我们将在最后计算该常数,使得 P(x|e) + P( x | e) = 1。为了计算 P(x,e ),我们必须将没有出现在 x 或 e 中的变量的联合概率分布边缘化,我们将它们表示为 y。
对于给定的示例,我们可以如下计算 P(洒水喷头,湿草|多云):
我们将以同样的方式计算 P( x | e ),只是将 x 中变量的值设置为 false 而不是 true。一旦 P( x | e)和 P(x | e)都计算出来,我们就可以解出α,它等于 1 / (P(x | e) + P( x | e))。
请注意,在较大的网络中,Y 很可能相当大,因为大多数推理任务将只直接使用变量的一个小子集。在这种情况下,如上所示的精确推理计算量非常大,因此必须使用一些方法来减少计算量。一种更有效的精确推断方法是通过变量消除,它利用了每个因素只涉及少量变量的事实。这意味着求和可以重新排列,以便在该变量的边缘化中只使用涉及给定变量的因子。或者,许多网络甚至对于这种方法来说都太大了,所以使用近似推理方法,例如MCMC;这些提供的概率估计比精确推断方法需要更少的计算。
熊猫清洗数据介绍(私人慕尼黑 Housemarket 数据集)
一开始我就开始用 python 做数据分析之外的其他事情。我是一名技术 SEO 顾问,想要使用一个爬虫(或构建一个),但不知道任何编程语言,python 看起来是开始的完美语言…
现在,我更喜欢 python,因为它的多功能性可以做我刚才提到的事情,还可以轻松实现数据分析。
如果我们能把这两个世界融合在一起会怎么样?当我手腕受伤时,我创作了我的第一个爬虫,它并不漂亮,它是用一只手写的,但是很有效。
现在我正在看数据,我想这将是一个很好的简单的例子,说明如何使用 python(主要是 Pandas)来使用您收集的数据,或者您可以使用的数据。
慕尼黑的房产市场
我现在住在慕尼黑,我真的很喜欢这个城市,在我职业生涯的初期,我去过很多地方(纽约/旧金山/台湾/巴黎),我很快想到我需要一些数据来帮助寻找我的家。如果我想在某个地方购买,你需要支付的不是一个小数目,很可能是一大笔钱,所以你需要用一些确凿的数据来支撑你的愿望。
我用我的小爬虫独自收集慕尼黑周围房产市场的数据。它仍然是一个手动程序,因为当我创建它时,我不知道也没有时间让它成为一个全天候运行的云原生应用程序。
我可能会尝试改进它,使它成为云原生的,这样我就可以监控它。如果我成功了,这将是一篇博文。我在上的博客数据分析。
与此同时,我一次又一次地运行这个爬虫,有些人可能会说是以一种随机的方式;) .
慕尼黑的房市贵,不是一点点,是真的贵。
所以我在做我的爬虫,以便找到一个符合我预算的家。大部分是公寓(因为房子不在我的预算之内),位于慕尼黑地区。
所以从这个分析的偏见开始,这里有一些:
- 我寻找“最多 4 个房间的公寓”
- 我寻找“高达 60 万€”的公寓(大约 69 万美元)
- 我找的是“离慕尼黑中心最多 20 公里”。
- 我看了公寓是在一楼还是在楼上,但我没有看具体的楼层。
我将我的数据保存为 csv 格式,你可以在我的 github 账户上找到:https://github.com/pitchmuc/munich_housemarket.git
了解熊猫的数据
当我有数据集要查看时,我首先做两件事:
- 我观察数据集的大小。
- 我看数据集的类型。
对我来说,数据集不是很大(150 kb),所以我的电脑处理起来没有问题。如果它再大一点,我会把它分割成最大 100MB 的块,这样我就可以轻松地播放和测试我的脚本了。然后我会生成一个健壮的脚本来处理您的所有数据。
当您对您的完整数据集(即:5GB)执行分析时,您希望在花费数小时运行您的分析并发现它没有达到您想要的效果之前,确保这是可行的。
您必须处理的数据类型可以是:
- clean:你只需要导入它
- 半干净:您必须导入它,并处理一些丢失的数据。
- 一点也不干净:你必须清理一下,导入它并处理掉丢失的数据。
在我们的例子中,我已经设法获得了相当干净到半干净的数据,但是仍然需要进行一些清理。
在下面的步骤中,你将看到如何用 python 熊猫实现基本的清洁:
导入您想要使用的库。在我们的例子中,你想要熊猫和熊猫。
import pandas as pd #naming convention
import numpy as np #naming convention
在您的环境中导入数据集。
在我的例子中,我使用的是 ipython(或者叫做 jupyter notebook)。我真的很喜欢这种探索的环境。当事情变得严重时,我通常会去找 Spyder。
df = pd.read_csv('data_immoscout.csv',delimiter='\t') # df is going to be our dataframe. (place where we store all the data). I used tab as delimiter.
看看你掌握的数据。使用。head()函数将给出你的数据的预览。
df.head() ## use df.head(20) to get 20 lines
在 df.head()之上,您还可以尝试查看数据被处理的确切类型。
为了做到这一点,你可以使用
df.dtypes ##it will give you something like this :
index0 int64
terrace object
bedrooms object
construction_year object
date_month int64
date_year int64
date_year_month object
floor object
rooms object
price_room object
price_surface object
price object
surface object
zip int64
dtype: object
查看您拥有的列的类型非常重要,因为这通常会让您了解数据存储的类型。或者应该存储数据的类型。
df.columns # will give you something like : Index(['index0', 'terrace', 'bedrooms', 'construction_year', 'date_month', 'date_year', 'date_year_month', 'floor', 'rooms', 'price_room', 'price_surface', 'price', 'scout_id', 'surface'], dtype='object')
由此我可以给你一些关于这些数据的解释,但是通过 dtypes 和 head()来看这些数据实际上应该已经给了你这样的想法:
- index0:这是表格的索引
- 露台:有没有露台
- 卧室:有多少间卧室
- 建造年份:什么时候建造的
- date_month:一年中实现爬网的月份
- date_year:实现爬网的年份
- date_year_month:实现爬网的月份和年份
- 地板:到底是不是底楼?
- 房间:房间数量
- 价格 _ 房间数:公寓价格除以房间数
- 价格 _ 表面:公寓价格除以表面
- 价格:公寓的价格
- 表面:平面的表面
- zip:公寓的邮政编码
当你开始处理这些数据时,你要做的第一件事是确保它们在系统中被正确识别。
什么叫“正确的方式”?
正确的做法是:数字看成数字,字符串看成字符串,日期看成日期,NaN 看成 NaN。
什么是南?
南代表“不是一个数”。了解这一点非常重要,因为这是我们在最终处理它们之前想要清理的数据类型。
正如你可能已经看到的,有几行实际上写的是 NAN。是公认的南吗?为了查看你有多少 NaN,你可以使用这个非常有用的函数:
df.isna().sum() ## The result will look like this :index0 0
terrace 0
bedrooms 0
construction_year 0
date_month 0
date_year 0
date_year_month 0
floor 0
rooms 0
price_room 0
price_surface 0
price 0
surface 0
zip 0
dtype: int64
这意味着在您当前的数据集(或数据帧)中没有可识别的 NaN。
‘NAN’只是我实际运行爬虫时设置的一个字符串。
然后,您将用 NaN 的正确定义替换“NAN”字符串。为了做到这一点,我们将使用 numpy 库,您只需要这样使用它:
df.replace('NAN',np.NaN,inplace=True)When we have done that, we will then see different result on the previous method : df.isna().sum() ## The result will look like this :index0 0
terrace 0
bedrooms 319
construction_year 49
date_month 0
date_year 0
date_year_month 0
floor 113
rooms 34
price_room 35
price_surface 212
price 1
surface 211
zip 0
dtype: int64
在这里,我们开始了解这些数据的实际情况。
你看,我们缺少很多卧室信息的数据。
在接下来的步骤中,我们的任务是尽可能减少 NaN。
我们将尝试假设一些不同的策略来填充这里的 NaN。
如果你想看到你的数据集的整体质量,你实际上可以使用一些计算。
像这样:
(df.isnull().sum() / len(df))*100 ## result will look like this :index0 0.000000
terrace 0.000000
bedrooms 36.708861
construction_year 5.638665
date_month 0.000000
date_year 0.000000
date_year_month 0.000000
floor 13.003452
rooms 3.912543
price_room 4.027618
price_surface 24.395857
price 0.115075
surface 24.280783
zip 0.000000
dtype: float64
所以我提供的数据并不完美,但你可能会看到很多比这更糟糕的数据。
了解数据:36.7%的行没有卧室信息。
真正令人不安的是,我们遗漏了一个特定数据点的价格信息。
价格真的很难预测,但让我们看看是什么数据,我们可能会有所发现:
df[df['price'].isna()].T ##the result will look like this :367index0 4terrace yesbedrooms NaNconstruction_year 2016 date_month 8date_year 2016date_year_month 2016_08floor NaNrooms 5price_room NaNprice_surface NaNprice NaNsurface 209zip 81479
你会发现我们遗漏了价格和卧室数量。
我们有两种选择:
- 用我们掌握的信息预估价格(5 室,209 平米,建造年份:2016 年)
- 从数据集中移除此线
在我们的案例中,2016 年建造的 200 平方米可能会超出我的数据集限制(<600 K€). I will then remove the line from the data set.
From my extract, I saw that the index of that line is 367.
我可以通过以下简单操作删除该线:
df.drop(df.index[367],inplace=True)
但是如果你有不止一个索引,你怎么管理呢?
你只需要大声说出你的病情指数:
df.drop(df[df['price'].isna()].index,inplace = True)
由于我们正在删除无用的信息,我们可以借此机会删除 index0 列,因为您可能已经看到 pandas 会自动为您的数据帧生成一个索引。
为了完全删除一列,你需要实现这个动作:
df.drop(['index0'],axis=1,inplace=True) #axis = 1 make sure that you are deleting column
现在我们想让熊猫识别正确的数据类型。
拥有正确的数据类型将允许我们实现对数值类型(int 或 float)的数值运算。
如果我们有正确的数据类型集,我们将能够以更好的方式处理 NaN。
我建议总是将数值设置为 int。
为什么 int ?因为它更容易处理和解释,但你可以试着让一切都浮动起来。
浮点数可以表示整数(2.0 == 2)但整数不能表示某些浮点数(2.1!= 2)
一个简单的循环可能是这样的:
for col in list(df.columns): # for each column
try:
df[col] = df[col].astype(int) #try to set it as int
except:
df[col] = df[col].astype(str) # if not sucessful try to set it as string
当您实现这个操作时,您可以看到并不是所有的列都被更改为数字。
这主要是因为某些列不是整数而是浮点数。(所以一个小数)
你可以实现另一个循环:
for col in list(df.columns):
if df[col].dtypes == object:
try:
df[col] = df[col].astype(float)
except:
df[col] = df[col].astype(str)Then by doing a simple overview, your data start to look like something you can work :df.dtypes # it will show something like this :
Out[32]:
terrace object
bedrooms float64
construction_year float64
date_month int32
date_year int32
date_year_month int32
floor object
rooms float64
price_room float64
price_surface float64
price int32
surface float64
zip int32
dtype: object
填充 NaN
现在我们已经准备好处理不同类型的数据,我们将使用我们的大脑来处理不同的数据类型并填充 NaN 值。
如前所述,在进行任何分析之前,您可能想要感觉缺失值的最大值,以便计算最大值。
填写楼层栏你应该还记得,这一栏告诉我们这是不是底层。
通过这个简单的方法,你可以看到不同的值和它们出现的次数。
df['floor'].value_counts() ### Should show something like this :up floor 687
nan 112
ground floor 69
Name: floor, dtype: int64
您需要做的是计算楼上和楼下之间的分布,并将该分布应用于其余数据。你可以很容易地计算出底层公寓的数量约占本栏的 10%。
因此,我们需要用“底层”值替换 na 的 1/10。
我们可以通过简单地创建一个函数来实现:
def fill10pct():
if np.random.random_integers(0,9) == 0:
return 'ground floor'
else:
return 'up floor'
然后,您需要将它应用到您的行:
for index, value in df.iterrows():
if df.loc[index,'floor']=='nan':
df.loc[index,'floor'] = fill10pct()
您可以运行 df[‘floor’]。value_counts()来检查是否保持了分布。
填充房间现在我们将尝试填充房间。
我们将在这里尝试一种不同的技术。我们有一些信息可以帮助我们确定总共有多少个房间。
有卧室信息,所以在德国的邮政公寓中,卧室是唯一从房间数中分开统计的房间。
也就是:三室是指两个卧室,一个大房间,一个厨房和一个卫生间。
所以我们可以说房间的数量是卧室的数量+1,但是如果我们没有卧室的数量呢?那么,为了简单起见,我们可以说房间的数量是 2。这是我能拿到的最低工资。为此我们将创造我们的 2 个条件(有或没有若干卧室)
conditions = [ (df['rooms'].isnull()) & (df['bedrooms'].isnull()), (df['rooms'].isnull()) & (df['bedrooms'].notnull())]
choices = [2,df['bedrooms']+1]
df['rooms'] = np.select(conditions, choices, default=2)
我们将使用 numpy select 函数来决定应用哪个选项
df['rooms'] = np.select(conditions, choices, default=2)
当你知道怎么做时,这很容易。:)它太简单了,所以我们将把它做得更健壮一点,并在其中集成曲面。我们会说,如果表面大于 75 平方米,我们将设置房间数为 3。
conditions =[
(df['rooms'].isnull()) & (df['bedrooms'].isnull()) & (df['surface'].isnull()),
(df['rooms'].isnull()) & (df['bedrooms'].isnull()) & (df['surface']>75),
(df['rooms'].isnull()) & (df['bedrooms'].notnull()), ] choices = [2,3,df['bedrooms']+1]
df['rooms'] = np.select(conditions,choices,default=2)
填充卧室
填充卧室其实是相反的逻辑。如果你有房间的数量,你实际上可以猜出卧室的数量。
这一次,我们将使用从 numpy 中选择的方法:
df['bedrooms'] = np.where(df['bedrooms'].isnull(), df['rooms']-1, df['bedrooms'])
填充表面
对于表面,我们缺少 211 个数据点。我们可以有相同的策略,而不是房间的数量。外推现有公寓的表面以填充表面的缺失值。如果我们能得到 2、3 和 4 房间公寓的平均面积,我们就能给这些房间分配平均值。为了实现这一点,我们将使用熊猫最重要的功能之一。组由组成。
df.groupby(['rooms'])['surface'].mean() ##it should give you something like :
2.0 89.988924
3.0 91.100000
4.0 100.40000
有趣的是,你的 2 室和 3 室公寓的平均面积没有太大差别。很可能我们的数据没有那么干净,一些三室公寓被当成了两室公寓。
conditions = [
(df['rooms']==2 & df['surface'].isnull()),
(df['rooms']==3 & df['surface'].isnull()),
(df['rooms']==4 & df['surface'].isnull()) ]
choices = [90,91.1,100]
df['surface'] = np.select(conditions,choices,default=90.5)#default in between 2 and 3 rooms
填写建造年份
在这个例子中,这是相当困难的,因为建造年份可能是随机的。你无法根据之前的数据猜测建造年份。
在这种情况下,为了不虚报数据,我会选择用这个维度的含义来填补空白。
这是另一种你可以在熊猫身上快速使用的方法:
df['construction_year'].fillna(df['construction_year'].mean(),inplace=True)
填充剩余的…
正如你在做 df.isnull()时可能注意到的。sum()其他一些列有 NaN,但它们实际上是其他列的计算结果。所以你只需要用你的主列重新计算,所有的 NaN 就会消失。
如果您正在使用 Python 和 Pandas 进行数据分析,我希望这篇关于如何清理数据的教程能够对您有所帮助。
这是处理数据的一个非常重要的部分,如果您计划进行机器学习,清理数据并从 NaN 数据点中创造价值是机器学习最重要的方面之一。
如标题所示,我们将有第二篇文章,在那里我们实际分析数据,我们可能会尝试做一些可视化。
不要犹豫,评论并给出你的提示来分析这个数据集。
如上所述,数据集(干净的和不干净的)和 Jupyter 笔记本都在我的 Github 账户上:https://github.com/pitchmuc/munich_housemarket