你必须能够回答的五个数据科学面试问题
《亚马逊/网飞/谷歌数据科学家面试问题内部指南》
Photo by Jon Tyson on Unsplash
为了不在同一个地方失败两次,并让自己对他人有用,我的这篇文章献给那些想要追随自己成为/提高数据科学家的热情的人。数据科学是一个需要不断提高技能集的领域,同时每天都要开发机器学习算法中的基本概念。所以,事不宜迟,让我们直接进入一些问题和答案,你可能在下次面试中有用。
问 问题 1 : 你能解释一下决策树的成本函数吗?
**答案:**在我们回答这个问题之前,需要注意的是,决策树是一种多功能的机器学习算法,可以执行分类和回归任务。因此它们的成本函数也不同。
分类类型问题的成本函数:
基尼系数是我们理解成本函数之前的一个重要概念,我先解释一下。
Equation I: Gini Impurity
其中" p" 是第 i 个节点的训练实例中 k 类实例的比率。那是什么意思?下面我们从一个例子来理解。图 1 显示了深度为 2 的 Iris 决策树的简单可视化。顶层是根节点。将训练集分成一组决策的概念在算法中相当简单。这里,举例来说,虹膜数据集被分成两个子集的基础上,一个单一的特征称为“花瓣宽度”在根节点。如果花瓣宽度小于或等于 0.8,则该算法将转到左侧的深度 1。如果不是,它就去深度 1,对。其中它基于“花瓣宽度”的附加特征进一步划分实例。深度 1,右节点具有 100 个实例的样本,并将 0 个实例应用于鸢尾-Setosa,将 50 个实例应用于鸢尾-Versicolor,将剩余的 50 个实例应用于鸢尾-Virginica。
Figure I: Iris Decision Tree, Source
因此,该节点的基尼系数为 0.5:
Figure II: Gini impurity calculation
类似地,在深度 1,左节点,基尼不纯度为零,因为所有训练实例都应用于相同的类。节点本质上是“纯”的。
既然明白了什么是基尼不纯,那就让我们进入答案的正题吧。决策树使用分类和回归树(CART)算法进行训练,这是基于一个简单的概念,即使用单个特征(k)和阈值(t)将数据集分成两个子集。在虹膜数据集中,特征是“花瓣宽度”,阈值是 0.8。它是如何选择 k 和 t 的?它搜索产生最纯子集的对(k,t)。因此,算法试图最小化的成本函数由下面的等式给出:
Equation II: Cost function of a classification type decision tree.
其中 G 左或右表示子集的基尼不纯度,而 m 表示子集的实例。
回归型问题的成本函数;
对于回归树,代价函数相当直观。我们使用残差平方和(RSS)。等式 III 显示了回归类型树的成本函数,其中“y”是地面真实值,“y-hat”是预测值。
Equation III: Residual Sum of Squares (RSS)
问 问题二: 共线性如何影响你的模型?
**答:**共线性是指两个或两个以上的预测变量彼此密切相关的情况。下面的图 2 显示了共线变量的例子。变量 2 严格遵循变量 1,皮尔逊相关系数为 1。所以很明显,当输入机器学习模型时,这些变量中的一个会表现得像噪音一样。
Figure 2: Example of collinear variables.
在回归型问题中,共线性的存在可能会成为问题,因为很难区分共线变量对响应的单独影响。或者换句话说,共线性降低了回归系数估计的准确性,并导致误差增加。这将最终导致统计量的下降,因此,在存在共线性的情况下,我们可能无法拒绝零假设。
检测共线性的简单方法是查看预测变量的相关矩阵。该矩阵中绝对值较大的元素表示一对高度相关的变量,因此数据存在共线性问题。不幸的是,并不是所有的共线性问题都可以通过检查相关矩阵来检测:即使没有一对变量具有特别高的相关性,三个或更多变量之间也可能存在共线性。这样的情况称为多重共线性。在这种情况下,评估多重共线性的更好方法是计算方差膨胀因子 (VIF),而不是检查相关矩阵。每个变量的 VIF 可以使用以下公式计算:
Equation IV: The Variance Inflation Factor (VIF)
其中 R 平方项是变量 *X,*对所有其他预测值的回归。如果 VIF 接近或大于 1,则存在共线性。当面临共线性问题时,有两种可能的解决方案。一是去掉多余的变量。这可以在不损害回归拟合的情况下完成。第二种解决方案是将共线变量组合成一个预测值。
问 问题三: 你会如何向一个外行人解释深度神经网络?
**答案:**神经网络(NN)的想法最初源于人脑,它是为了识别模式而设计的。NN 是一组通过机器感知、标记和聚类原始输入数据来解释感官数据的算法。任何类型的真实世界数据,无论是图像、文本、声音还是时间序列数据,都必须转换到包含数字的向量空间中。
深度神经网络中的“深度”一词是指神经网络由多层组成。这些层由进行计算的节点组成。node 是人脑中的一个神经元,当它遇到足够的刺激时就会触发。节点将来自原始输入的数据与它们的系数或权重相结合,这些系数或权重基于权重来抑制或放大该输入。然后,输入和权重的乘积在图 3 所示的求和节点处被求和,然后被传递到激活函数,该激活函数确定该信号是否应该进一步通过网络以影响最终结果,以及应该进一步通过网络到什么程度。节点层是一排类似神经元的开关,当输入通过网络时,这些开关打开或关闭。
Figure 3: An example of node visualization in neural network.
深度神经网络不同于早期版本的神经网络,如感知器,因为它们是浅层的,仅由输入和输出层以及一个隐藏层组成。
Figure 4: Deep neural network consists of more than one hidden layer.
问 问题四: 你的数据科学带回家项目的 3 分钟推介是什么?
**回答:**一个典型的数据科学面试流程从一个带回家的数据分析项目开始。我已经参加了其中的两次,时间跨度可能会根据带回家项目的复杂程度而有所不同。第一次,给我两天时间用机器学习和执行摘要解决一个问题。第二次给我两周时间解决问题。不用说,第二次是一个更困难的问题,我处理的是类不平衡数据集。因此,3 分钟的推销型面试问题可以让你展示你对手头问题的理解。请务必从你对问题的解读是什么开始;你解决问题的简单方法;你在你的方法中使用了什么类型的机器学习模型,为什么?通过吹嘘你的模型的准确性来结束这一切。
我相信这是面试中一个非常重要的问题,它能让你证明你是数据科学领域的领导者,并且可以用最新最棒的工具解决复杂的问题。
问:你所说的模型正则化是什么意思,你将如何在线性模型中实现正则化?
**答案:**正则化是一个用来约束你的机器学习模型的术语。限制或减少机器学习模型中的过拟合的一个好方法是具有更少的自由度。自由度越少,模型越难过度拟合数据。例如,正则化多项式模型的一个简单方法是减少多项式自由度的数量。然而,对于线性模型,正则化通常通过约束模型的权重来实现。因此,代替线性回归,岭回归、套索回归和弹性网模型有三种不同的方法来约束权重。为了完整起见,让我们先从线性回归的定义开始:
Equation V: Linear regression and model prediction
- y-hat 是预测值。
- n 是特征的数量。
- x_i 是第 n 个特征值。
- θ是模型参数,也称为特征权重。
线性回归模型的均方误差成本函数定义为:
Equation VI: Linear regression cost function.
其中 theta 是 theta 的转置(行向量而不是列向量)。
**岭回归:**是线性回归的正则化版本,即在成本函数中增加了额外的正则化项。这迫使学习算法不仅要适应数据,还要保持模型权重尽可能小。请注意,正则化项应该仅在训练期间添加到成本函数中。模型定型后,您希望使用未规范化的性能度量来评估模型的性能。
Equation VII: Ridge regression cost function.
超参数 alpha 控制您想要正则化模型的程度。如果α为零,那么岭回归只是线性回归。
**Lasso 回归:**最小绝对收缩和选择算子回归(简称 Lasso 回归)是线性回归的另一个正则化版本:就像岭回归一样,它在成本函数中添加了一个正则化项,但它使用了权重向量的 L1 范数,而不是 L2 范数的一半平方。
Equation VIII: Lasso Regression cost function.
Lasso 回归的一个重要特征是,它倾向于完全消除最不重要的要素的权重(即,将其设置为零)。换句话说,Lasso 回归自动执行特征选择并输出稀疏模型(即,具有几个非零特征权重)。
**弹性网回归:**这是脊和套索回归之间的中间地带。正则项是岭和套索正则项的简单混合,可以用“r”来控制。当 r=0 时,弹性网等价于岭回归,当 r=1 时,等价于套索回归。
Equation IX: Elastic Net cost function.
至少有一点点的正则化总是更可取的,并且通常应该总是避免简单的线性回归。岭是一个很好的默认值,但如果在特定数据集中只有少数要素有用,则应使用 Lasso。一般而言,弹性网优于套索,因为当要素数量大于实例数量或多个要素高度相关时,套索可能表现不稳定。
在本文中,我讨论了我个人在一次技术数据科学面试中面临的五个问题,我认为这些问题本可以做得更好。我强烈推荐阅读下面的资源,在日常生活中磨练你的基本概念。相信我,我一定一遍又一遍地阅读了这些概念,然而我在面试中却笨手笨脚地发现了它们。
如果你喜欢读这篇文章,请不要忘记投票支持它!
快乐学习!
关于人工智能和机器学习项目失败原因的五个假设
有大量的文章和发表的论文围绕着为什么人工智能/机器学习/自然语言处理项目从未进入“生产”或未能交付所提出的价值(Gartner 预测,到 2022 年,85%的人工智能项目将由于数据、算法或负责管理它们的团队的偏见而交付错误的结果)。以下是一些关于为什么人工智能项目失败的假设,以及一些关于公司对人工智能项目缺乏交付价值的反应(技术和组织)的观察。请注意,这些意见并不反映任何当前或以前的雇主,而是与各行业的数据科学家、工程师、产品经理和架构师对话的综合。
假设 1:数据科学的初始模型不可扩展,或者过于实验性,不适合内部或外部客户使用。
项目通常从这里开始,因为公司雇佣了一些用 Python 或 R 构建模型的数据科学家,但很快发现数据科学家和工程师的思维方式不同。从短期来看,这个问题通常通过让机器学习工程师或其他软件工程师获取代码、重写代码并遵循标准开发-运营流程来解决,以便扩展和部署应用程序。考虑到结果的随机性,质量工程也需要与任务相适应。在这个过渡期,业务用户(和/或他们的代理产品经理)可以被排除在流程之外,需求或底层数据可能会发生变化。
在组织上,一些公司采取了下一步措施,聘请工程师加入数据科学小组,以帮助数据科学家了解更多关于生产和部署的扩展。这种方法的目标是减轻切换过程。面临的挑战是,这个研究/工程组织可能会与生产支持工作流的其余部分隔离开来。“数据科学家不戴呼机随叫随到”。
假设#2:数据科学/ML 模型虽然出色且具有创新性,但不符合业务需求,或者过于脆弱,无法响应支持数据的变化。
在咨询集团的建议下,一些公司做出决定,为了促进创新,“创新团队”需要与他们周围的“非数字”文化隔离开来。但是,虽然孤立的创新团队可以带来巨大的实验机会,并且这些团队可以学习和开发有趣的解决方案,但当最终的项目需要“推向”市场或内部客户时,通常只有很少的采用。虽然该解决方案可能会满足特定的挑战,但用户的体验通常不是最佳的。如果数据发生变化,缺少一个不太复杂的模型作为后盾也是一个挑战。从好的方面来说,这项研究可以发表在其他数据科学家阅读的学术期刊上,以进一步了解整个行业。
为了应对这种不采用的问题,一些创新/数据科学团队可能会在他们的组织中增加产品营销人员,以在内部“推广”他们的工作,并尝试直接向客户推销他们的概念。
假设#3:人工智能计划由公司内部 IT 组织驱动,并继承了“瀑布”式的挑战。
作为“数字化转型”的一部分,一些公司将 AI 视为整体数据仓库计划的一部分,或作为客户管理或营销应用自动化工作的一部分。人工智能或机器学习对“标记”(适当标记)数据的需求意味着,公司还需要有一个相当成熟的分析和数据捕捉基础设施。虽然将人工智能和机器学习作为整个 it 数据项目的一部分似乎是合理的,但如果没有伴随的实验/原型计划,人工智能项目可能会因此被埋没。具有讽刺意味的是,当数据最终在数据管道中准备就绪时,客户的需求可能已经完全改变了(例如:在公司战略转向流媒体时围绕 CD 发行进行优化)。
假设 4:公司对交付人工智能/人工智能项目所需的时间没有耐心。
鉴于许多提议的人工智能/人工智能项目的成功和时间表的不确定性,它们甚至可能在有机会开始之前就夭折了。再加上技术的新颖性以及谷歌、亚马逊和微软的领先优势,结果是非直接面向消费者的企业公司可能会谈论人工智能,但首先从业务流程自动化工具开始,然后等待事情解决(为未来捕捉数据)。
假设 5:缺乏 AI/ML 项目的“产品”方法是项目失败和风险增加的核心。
产品经理/所有者在敏捷软件开发中的角色在软件开发中是很明确的。产品经理作为团队的一部分工作,团队包括 UX、工程、质量保证和项目管理。人工智能项目中似乎缺少的就是这种相同的“产品”思维模式。优秀的产品经理知道如何提出或找到最有价值的商业问题。有经验的产品经理是管理产品交付不确定性的专家。经验丰富的分析产品经理知道数据在哪里丢失或被掩埋。因此,今天的问题可能不是“我们需要的数据科学家都去哪里了?”,而是“知道如何提出正确问题的人工智能产品经理都去哪里了?”
概要:
从根本上说,AI/ML 项目不会成功,除非精通技术的产品经理采用同样的“敏捷”“精益”产品方法来应对风险、领土之争以及无法解决或回答业务问题的挑战。数据科学家和机器学习工程师需要成为产品开发团队的一部分。就像“设计思维”让 UX 加入软件开发团队一样,“人工智能思维”需要将人工智能研究整合到产品开发中。人工智能产品经理需要业务高管的支持,以指导商业价值评估过程,并平衡技术/数据科学议程。
虽然人工智能云平台的变革仍在继续,工具也在快速变化,但那些加强并培训或雇佣具备必要技术或数据技能的人工智能产品经理,并挑战他们与 UX 设计师、数据科学家、机器学习工程师、软件工程师组成的团队一起找到一个商业问题来回答的公司,在一位理解并能够理性沟通不确定性的项目经理的协调下,将是利用人工智能取得成功的漫长道路。
那些已经标记了数据流的公司,如电子商务和金融/支付领域的公司,已经领先一步,并为其他公司提供了如何扩展的良好模型,但只有通过提出正确的问题,并利用和扩展 ML/NLP/AI 来获得正确的答案,其中一些公司才能在未来几十年中领先一步。
实用人工智能发展的五个里程碑。
计算机从简单计算到识别癌症用了不到 80 年的时间。
Photo by Franck V. on Unsplash
当谈到机器学习和人工智能时,人们的意见不一。一些人认为,人们能够给计算机编程,让它们轻松地完成与人类相同的任务,这是不可避免的。其他人认为,计算机永远无法在智力、决策和感知方面接近人类。
无论这个领域的未来如何,机器学习并不神奇。事实上,在过去的 80 年里,它一直在稳步而显著地改变着我们的生活。进展相当令人着迷。
1959 年:计算机和跳棋
我们可以将第一个概念神经网络的根源追溯到 1943 年,以及沃伦麦卡洛克和沃尔特皮茨的工作。然而,机器学习原则的第一次现实应用发生在 1959 年,当时亚瑟·塞缪尔创建了第一个跳棋程序。
当时,大多数人在电脑上构建跳棋游戏的方式是靠蛮力。一种算法会在棋盘上走一遍,按顺序移动并搜索每一条可能的路径,直到游戏结束。唯一的问题是,T2 需要大约 13 年的时间才能让计算机暴力破解跳棋。这对战胜人类的努力来说没什么用。
塞缪尔决定写一个函数,在任意给定时刻评估棋盘上的情况,而不是搜索每条路径。该函数考虑了有多少棋子成为了“国王”,其他棋子离达到那个阶段有多近,以及每边总共还有多少棋子。然后,程序试图做出一个移动来优化函数值,并增加获胜的概率。
后来,塞缪尔还设计了一些机制,让计算机能够记住它已经处于的位置,以及这些位置最终是如何“奖励”的。
1997 年:机器在国际象棋中击败卡斯帕罗夫
1997 年,它变成了现实。一台计算机在人类发展的游戏中击败了排名第一的人类,为未来数年的人工智能研究定下了基调。这台机器叫做“深蓝”,它是 IBM 最伟大的发明之一。
在 1997 年的决赛之前,加里·卡斯帕罗夫在 1989 年遇到了“深蓝”的早期原型 ChipTest,并击败了它。研究人员又花了将近十年的时间来改进这个系统。当“深蓝”击败“大师”时,卡斯帕罗夫指责机器的创造者作弊,声称“深蓝”的决定具有人情味。
然而,很久以后,在他的 2017 TedTalk 中,卡斯帕罗夫分享了他对发展中技术的有利观点,并指出机器是对人类的补充,而不是竞争。
2009 年:统计猴子和体育新闻
在国际象棋中计算走法很酷。对已经生成的图像进行分类令人印象深刻。然而,一台能产生原创作品的电脑是一个爆炸。
统计猴,西北大学几名学生的项目,可以在大约两秒钟内写下任何一场棒球比赛的故事。该系统使用统计数据来计算游戏的结果、关键玩家和动态。在确定了故事应该是关于什么之后,Stats Monkey 使用了一个特定表情库,并拼凑了一个实际上听起来不像机器人的叙述。
2015 年:DeepMind 玩电子游戏
DeepMind 是一个可以自学玩电脑游戏的系统,而且是最擅长玩电脑游戏的人。DeepMind 于 2014 年被谷歌收购,是第一个成功的机器学习应用,允许计算机在 49 种不同的雅达利游戏机游戏上逐渐变得更好。
新颖之处在于算法。虽然编写 DeepMind 来玩某些游戏很容易,但创作者们的目标是更优雅和普遍适用的方法。他们想要一个可以从头学习的模型。
DeepMind 的联合创始人兼首席执行官戴密斯·哈萨比斯博士评论:“我们给系统的唯一信息是屏幕上的原始像素和它必须得到高分的想法。”
DeepMind plays Atari Breakout —YouTube
该系统的最终版本利用了深度学习,并在玩了几个小时后设法解决了游戏的机制。DeepMind 的成功不仅令人印象深刻,而且证明了在没有人类干预的情况下,编写一个从大量数据中学习并应用这些知识的计算机是可能的。
2018:人工智能识别皮肤癌
各种皮肤癌的早期检测对存活率极其重要。2018 年,人类医生在大约 86.6%的病例中成功检测到黑色素瘤。这意味着,在全球每年因黑色素瘤而死亡的 59,782 人中,大约有 8,011 人可能因为这一错误而死亡。
2018 年,来自德、法、美三国的研究人员制造了一种人工智能系统,可以在 95%的病例中正确识别恶性黑色素瘤。该模型也减少了对皮肤良性痣的误判。准确度可能会随着更多的训练而提高。
作为一种工具,机器学习非常有用。本文中涉及的五项开发只是利用该技术的数百万个非凡解决方案中的一小部分。通过更深入的观察,你会发现人工智能现在无处不在——从人脸识别和医学到商业分析、游戏和 YouTube 推荐算法。
这是一个完美的时机,不仅可以扩展我们在人工智能领域的专业知识,还可以精确地定制它,以解决我们这个时代最大的问题。
让你看起来像詹姆斯·布朗的五个蟒蛇动作
Photo by Start Digital on Unsplash
在我们作为数据科学家的日常生活中,我们经常使用各种 Python 数据结构,如列表、集合或字典,或者更一般地说,我们使用 iterables 和 mappings 。有时,转换或操作这些数据结构会变得非常代码化。这可能导致代码不可读,并增加引入错误的机会。幸运的是,有一个叫做 funcy 的简洁的 Python 模块可以帮助我们简化这些任务。在这篇短文中,我向您展示了普通的 Python 代码和相应的 funcy 函数,这些函数允许您用可读性更好的代码更高效地完成五个不同的任务。读完这篇文章后,我相信你会变得更有趣:)
省略/投影
有时您得到了一个字典,而您想继续使用该字典的一个子集。例如,假设您正在构建一个 rest API 端点,并且您只想返回模型属性的子集。为此,funcy 提供了两个功能,即省略和项目
**from** funcy **import** project, omitdata = {**"this"**: 1, **"is"**: 2, **"the"**: 3, **"sample"**: 4, **"dict"**: 5}**# FUNCY** omitted_f = omit(data, (**"is"**, **"dict"**))
**# PLAIN PYTHON**
omitted_p = {k: data[k]
**for** k **in** set(data.keys()).difference({**"is"**, **"dict"**})
}**# FUNCY** projected_f = project(data, (**"this"**, **"is"**))
**# PLAIN PYTHON** projected_p = {k: data[k] **for** k **in** (**"this"**, **"is"**)}
使用 funcy,您不仅需要键入更少的字符,还可以获得可读性更好、更少出错的代码。但是为什么我们需要两个功能呢?如果您想要保留的关键点数量小于您想要移除的关键点数量,选择项目否则选择忽略。
展平嵌套的数据结构
假设你有一个嵌套的数据结构,比如一个列表和列表的列表,你想把它变成一个列表。
**from** funcy **import** lflattendata = [1, 2, [3, 4, [5, 6]], 7, [8, 9]]**# FUNCY**
flattened_f = lflatten(data)**# PLAIN PYTHON**
**def** flatter(in_):
for e in in_:
**if** isinstance(e, list):
**yield** **from** flatter(e)
**else**:
**yield** eflattend_p = [e **for** e **in** flatter(data)]
如您所见,funcy 版本只有一行代码,而普通 Python 版本看起来相当复杂。我也花了一些时间来想出解决方案,我仍然没有 100%的信心。所以,我会坚持使用 funcy:)除了 list 版本 l flatten,funcy 还为 iterables 提供了一个更通用的版本,称为 flatten,没有 l 前缀。你会发现对于不同的函数。
分成块
假设您有一个包含 n 个条目的 iterable,并且您想要将它分成包含 k < n 个元素的块。如果 n 不能被 k 整除,则最后一个块可以小于 k。这就像有一个 n 个样本的训练集,您希望将其分成大小为 k 的批次来进行批处理
**from** funcy **import** lchunks
data = list(range(10100))**# FUNCY**
**for** batch **in** lchunks(64, data):
# process the batch
pass**# PLAIN PYTHON
from** typing **import** Iterable, Any, List**def** my_chunks(batch_size:int, data:Iterable[Any])->List[Any]:
res = []
**for** i, e **in** enumerate(data):
res.append(e)
**if** (i + 1) % batch_size == 0:
**yield** res
res = []
**if** res:
yield res
**for** batch **in** my_chunks(64, data):
# process the batch
**pass**
注意,我使用了 lchunks 版本来进行列表分区,而不是更通用的 chunks 版本来对可重复项进行分区。您所要做的就是传递您想要的批处理/块大小,以及您想要分区的 iterable。还有另一个 funcy 函数,叫做分区,它只返回那些正好有 k 个条目的块。因此,如果 n 不能被 k 整除,它将忽略最后一个。
组合多个词典
假设您有多个保存不同日期但相同对象的数据的字典。您的目标是将所有这些字典合并成一个字典,并使用特定的函数合并来自相同关键字的数据。在这里,funcy 的 merge_with 函数派上了用场。你只需要传入合并函数和所有你想合并的字典。
**from** funcy **import** merge_with, lcat
d1 = {1: [1, 2], 2: [4, 5, 6]}**# FUNCY VERSION**
merged_f = merge_with(lcat, d1,d2)**# PYTHON VERSION**
**from** itertools **import** chain
**from** typing **import** Callable, Iterable, Any, Dict
**def** _merge(func: Callable[[Iterable], Any], *dics:List[Dict])->Dict:
# Get unique keys
keys = {k **for** d **in** dics **for** k **in** d.keys()}
return {k: func((d[k] **for** d **in** dics **if** k **in** d)) **for** k **in** keys}merged_p = _merge(lambda l: list(chain(*l)), d1, d2)
还有一个函数 join_with ,它类似于 merge_with,但不是将每个字典作为单个参数传递,而是传递一个可迭代的字典。哦,我“偶然”潜入了另一个 funcy 函数 *lcat,*它将不同的列表合并成一个。
缓存属性
最后但同样重要的是,完全不同但非常有用的东西; cached_prope rty 装饰器。顾名思义,它使您能够创建只执行一次的属性,而不是缓存该执行的结果并在所有后续调用中返回该结果。我在构建数据集类时经常使用它,因为它给了我非常干净和易读的接口,同时减少了加载时间。
**from** funcy **import** cached_property
**import** pandas **as** pd**# Funcy Version**
**class** DatasetsF:
@cached_property
**def** movies(self) -> pd.Dataframe:
**return** pd.read_csv(**"the_biggest_movie_file.csv"**)**# PYTHON VERSION**
**class** DatasetsP:
**def** __init__(self):
self._movies = None@property
**def** movies(self) -> pd.Dataframe:
**if** self._movies **is** None:
self._movies = pd.read_csv(**"the_biggest_movie_file.csv"**)
**return** self._movies
结论
在这篇文章中,我向您介绍了 funcy,向您展示了它提供的一个非常小但很方便的功能子集。要快速了解所有功能,请查看此备忘单。我希望这篇文章能激励你学习一些 funcy 动作。它比我在这里向你展示的要多得多。感谢您的关注,如果有任何问题、意见或建议,请随时联系我。
为什么不能“让另一位数据科学家来做这件事”的五个理由
这句话证明了人们不知道数据科学到底是什么
你有没有参加过分析性问题被证明具有挑战性的会议或讨论?比如,你找不到合适的模型,或者你的数据格式有问题,或者领导对时间表不满意?
有时候我也遇到过这种情况。很正常。分析是复杂的,事情并不总是如你所希望和计划的那样发展。
但是,当人们认为这些问题的解决方案是“让我们找一个(另一个)数据科学家来做这件事”时,这让我抓狂。这种思维方式有太多的错误。它暴露了对什么是数据科学的基本误解,并暴露了对实践数据科学所需技能的缺乏重视。以下是为什么不能“让另一位数据科学家来做这件事”的几个原因。
1.数据科学家不是一个容易找到的资源
尽管该领域出现了爆炸式增长,而且现在提供了各种教育项目,但优秀的数据科学家并不容易找到。市场竞争激烈,对那些技术最熟练的人需求量很大。如果您足够幸运,在您的组织中有强大的数据科学家,他们的工作可能已经非常繁忙了。
“为了快速解决问题,让另一个数据科学家来做这件事通常意味着引入那些并不真正有资格自称为数据科学家的资源。比如有人几个月前上过一次在线 Python 课程,并且能说出机器学习这个词。那里有很多这样的人,但是让他们参与进来最终会拖延而不是帮助这项工作。如果目的是提供更多能力来帮助现有的数据科学家,可能会适得其反,因为他们将不得不花大量时间与知识基础非常低的人打交道。
2.数据科学家不是多面手
数据科学是一个异常宽泛的领域。有时你说你想要一个数据科学家,但实际上你需要的是一个数据工程师。有时候你需要一个 NLP 专家,或者一个会做 GLMs 的人。有时候你需要的更像是前端开发人员来构建应用程序。没有一个数据科学家能把每件事都做好。
“让另一个数据科学家来做这件事”不够规范,可能会导致 HR 让背景和技能与要解决的问题不匹配的临时或永久员工来做这件事。
3.数据科学家通常需要领域专业知识
类似于第 2 点,如果数据科学家没有知识领域来支持他们的技术技能,他们很少是有效的。与分析人才和人员或临床试验结果的工具和方法相比,分析金融风险的数据科学家将使用一套完全不同的工具和方法。
强大的数据科学家通常在其特定领域拥有一定水平的经验和专业知识。他们知道面临的典型数据问题,经常发生的特定统计现象。他们可以更流利、更快地处理这些问题。
“让另一个数据科学家去做”可能会给人们带来压力,让他们为了填补所需的能力而指派没有领域专业知识的人。这对工作质量和潜在的解决方案可能是毁灭性的。
4.数据科学家需要整合到工具链中
强大的工具链带来了如此多优质、高效的分析。语言、版本控制、敏捷跟踪以及发布和共享规范都是平稳的数据科学操作的一部分。许多数据科学家可能不熟悉正在使用的特定工具链,或者对任何工具链都没有经验。
“让另一个数据科学家去做”可能会使现有的工作流程面临风险或导致延迟,因为新的资源被投入到工作中,而这个人没有使用所用工具的经验。结合上述一些问题,这可能是非常危险的。
5.数据科学家并不是唯一需要解决这个问题的人
使用分析解决组织或业务问题需要的不仅仅是数据科学家。它需要来自业务方面的经验丰富的个人的参与,他们可以帮助判断什么应该建模,什么不应该建模,以及什么样的结果最有用。它需要能够帮助数据科学家区分工作中哪些部分是关键的,哪些部分在数据质量差或难以获得时可以放弃的人。
“让另一个数据科学家来做”通常会掩盖一个更深层次的问题,即业务方面没有足够的参与,以及现有的分析专业人员没有收到关于优先级和输出的足够指导。另一个数据科学家不会在这方面提供帮助。
数据科学家并不是万能的灵丹妙药。在一个问题上投入更多往往会使情况变得更糟,而不是更好。所以下次你听到有人说“让我们找一个(另一个)数据科学家来做吧”,不要害怕让他们来做!
最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在 LinkedIn 或Twitter上找我。
Image from Despicable Me, Illumination Entertainment/Universal Pictures
构建优秀的数据产品
连接→规划→实验→部署→发展
Photo by Tory Morrison on Unsplash
1.连接
与贵组织的主要利益相关者密切合作。了解你的客户。问他们:他们的目标是什么,他们需要什么?是什么阻碍了他们?数据如何帮助他们?确定棘手问题,并考虑特定问题的解决方案。尽早让别人成为你努力的一部分**。**
**用你自己的建议补充你客户的想法。**你能想到数据还能为他们做什么他们不知道的事情吗?例如,有没有一些过程可以利用机器学习的最新发展来实现自动化,而你的客户却不知道?
不悔的头脑风暴。通常,看似“坏主意”可以发展成有用的东西。即使你的大部分建议被拒绝,你也可能只剩下一个能为公司节省数百万美元的好主意。
**用人和数据连接人和数据。**您或您的组织中有哪些实际可用的数据?哪些数据源应该使用或与其他数据源结合使用,但目前没有使用?人们是否公开交流想法、经验和最佳实践?如果必要的平台不存在,创建它们。
2.计划
艾伦·凯利和 #beyondprojects 运动给了我们一种新的工作心态:持续思考。我们不是把所有事情都框定为一个有固定价值和固定结束日期的项目,而是围绕连续的、类似产品的工作流来组织自己。根据它们所传递的价值,它们出现、成长、萎缩或死亡,就像是“最能创造价值者的生存”。为了提高工作效率,我们根据价值和努力程度进行优先排序。在数据科学计划的开始阶段,低投入比高价值更重要,因为立竿见影会产生有价值的信任。
然而,好的规划是关于选择合适的方法,而不是遵循固定的路线:当今数字经济的市场动态使价值成为“移动的目标”,而大多数数据科学工作的实验性质阻碍了对时间框架的精确估计。这阻碍了长期规划,需要一种迭代方法。为了降低风险,我们一小步一小步地到创建一个最小可行产品 (MVP),我们获取客户反馈来学习和改进。
在敏捷数据科学宣言中,Russell Jurney 介绍了数据价值金字塔的概念:从数据记录到图表、报告、预测以及最终的行动,价值不断增加的数据使用层相互建立。在规划你的工作时请记住这一点:数据科学只有在导致行动时才是有效的,成为战略层面或微观决策的 it。因此,思考超越模型和分析:计划将数据科学产品整合到组织流程中和通过利用你的社交技能,确保你的结果“通过”。
3.实验
试试。失败。学习。重复一遍。重复一遍。重复一遍。然而:实验不是尝试随机的东西,而是发现什么可行或不可行,即通过经验发现成功之路。
在数字经济中,一个伟大的想法比你狭隘地追求当前任务而获得的百分之几的额外效率更有价值。花点时间开阔你的视野。结合不同的想法。了解最新的发展和创新。经常你会被卡住,但是现在不工作的东西可能在另一个时间派上用场。保持开放的心态,一路上会有很多有价值的见解向你走来。
与您的团队和更广泛的数据科学社区讨论和分享您的方法、想法、经验和成果,无论是在线还是离线。
4.部署
现在,最新的情况是,真正的数据科学家大放异彩:他们不仅有能力构建伟大的模型来满足真正的商业需求**,还能从这些模型中创造产品和服务。**
要么与软件工程师密切合作,要么学习他们的手艺,你将见证你的实验工作流程被剥离到最基本的部分,并作为 生产级应用重生。不要因为你在过去需要或者在遥远的将来可能会再次需要而保留界面或功能——在时机成熟时添加这些比从一开始就因为复杂而削弱你的产品更明智。不要扔掉你的探险笔记本,而是将它们存档。了解如何使用部署技术将这段代码付诸实施。
为了快速行动并在早期发布 MVP,与其他角色密切合作,例如产品所有者或系统管理员。设计自治和异质的团队**,包含所有必要的角色,不受组织边界的阻碍。共同责任感**是金:如果每个人不仅仅关心自己的部分,而是关心整个产品,人们将会目标一致地工作,务实地弥补责任差距。****
5.生长
秤你的产品。向前看:哪些改进、特性或改变会进一步增加它的成功?回顾过去:到目前为止,你能从这段旅程中学到什么?这对你下一步的努力有什么帮助?
传达您的结果和成功,为您的团队和您自己赢得“数据科学可信度”。你能给出一个你负责的节约或收入增长的数字吗?
好的工作会创造信任,这会给你更多的机会。从长远来看,你将从改变流程到改变思维方式,超越数据科学的范畴,展现真正的变革效应。
你错过什么了吗?完全不同意?请在评论中分享你的观点!
spaCy-IRL 值得一看的五次演讲
SpaCy-IRL 是一项为期两天的活动,于 2019 年 7 月 5 日至 6 日在柏林举行。它主要关注应用自然语言处理(NLP)。也就是说,用(通常)非基准数据解决新的 NLP 业务问题。在会议期间,讨论了用于解决行业问题的问题、方法和工具。我选择了我认为值得观看的 spaCy-IRL 2019 五大演讲。
约翰·戈德堡、巴伊兰大学和 AI2:自然语言处理中缺失的元素
Yoav 谈到了学术界和工业界之间有趣的差距。一方面,学术界的研究大多集中在需要大量数据和计算能力的深度学习模型上。另一方面,该行业仍然依赖于传统的 NLP 技术。在他的革命性愿景中,应用的 NLP 仍将依赖于人类的书面规则,但它们将在机器学习的帮助下编写,从而产生透明和可调试的模型。他用自己的观点描述了 NLP 中缺失的元素:
1。使用少量带注释的数据,在领域之间转移,并将知识整合到模型中。
2。NLP 构建块的符号表示,允许非专家直接交互。
3。“处理缺失的元素”。我们作为说自然语言的人或作家,在使用自然语言时会省略单词。例子:“她刚满 50 __”。例如,这挑战了我们的依存解析模型。
4。人类和机器的合作,以建立自然语言处理模型。这种合作将包括一个支持它的互动开发过程。
Yoav 还提到了理解深度学习模型正在做什么(“打破黑盒”)以及 NLP 中公平性和可解释性的重要性。
在我的研究中,在 Yoav 的指导下,我专注于第一个缺失的元素。特别是针对带有小注释的数据和域间传输的问题的解决方案。我最近的工作,发表在 NAACL 2019 上,解决了使用小噪音词典的单词嵌入对齐问题,这对于低资源语言和域转移非常重要。
二。Sebastian Ruder,DeepMind:开源 NLP 中的迁移学习
不久前,在 EMNLP 2018 上,我与 Sebastian 会面,讨论他的最后一篇论文之一,他可能不记得我了,但我非常兴奋。这一次,Sebastian 谈到了 NLP 中的迁移学习。在过去的几年里,迁移学习在 NLP 领域取得了巨大的进步,在我看来,这种积极的变化将能够解决许多行业用例特定的问题。在他的演讲中,Sebastian 强调了在 NLP 中使用迁移学习的天然优势,这是由于语言表示、结构相似性、任务交织(如语法和语义)以及带注释的数据很少这一事实。事实上,使用预先训练的语言模型(如:ELMo、BERT)已被证明有助于改善翻译、情感分析、命名实体识别、文本分类、问答等任务。Sebastian 的观点是,如果可用且与您的用例相关,请使用预训练模型,最重要的是,如果您在一种新类型的数据集上训练了一个模型,这可能对其他人分享它有用。他的理由不仅是社区驱动的,也是生态的。生态?!是的,Sebastian 引用了《T2》的这篇论文,训练一个语言模型比制造和使用一辆汽车消耗更多的二氧化碳。他建议使用集线器共享模型。中枢允许我们将机器学习模型作为自包含图(模型和参数)来共享。
“Training a language model uses more carbon dioxide than the manufacturing and lifetime use of a car”
三世。Rasa 的 Justina Petraitytė:在帮助船舶对话人工智能助理方面的经验教训
Rasa 通过提出对话式 NLU 的开源模型,使开发人员能够构建对话式人工智能系统。Justina 讨论了他们在开发 Rasa 时面临的挑战及其解决方案。其中有:预训练词向量的局限性;确认范围外的输入;和反馈回路;在我看来,Justina 为这些问题提出的解决方案非常具有启发性,这可以追溯到 Yoav 关于工业依赖于启发性解决方案的观点。对话式人工智能是应用自然语言处理的一个常见例子,所以我觉得听到 Rasa 面临的主要问题很有趣。
四。麦肯锡·马歇尔,巴林银行:资产管理中的 NLP
巴林正在他们的财务管理系统中应用 NLP。麦肯齐强调,投资研究不是完全自动化的,而是使用机器学习进行增强。她使用 prodigy 注释工具创建了一个数据集,专门解决他们处理公司名称词义歧义的问题。同样,我们可以看到为了支持当前的 NLP 模型,需要领域专家的介入。此外,她提到了使用二元案例情感分析的问题。
诉国际 RTI 公司彼得·鲍姆加特纳:应用自然语言处理:来自现场的教训
彼得谈到了他作为 NLP 专家与客户打交道的工作。首先,在谈到 NLP 行业问题时,他谈到了客户的不同需求。有时,客户不知道 NLP 的能力和解决的问题,有时他们被人工智能炒作所驱使或者误解了这个领域。第二,他提到 ML 项目更难管理,因为有更多的模糊性。为了传达不确定性和报告项目状态,他建议管理实验日志。Peter 还建议建立比喻,以便与非技术同事交谈。最后,Peter 提到了我们的工作交流的重要性,不仅在研究自然语言处理方面,而且在应用自然语言处理方面。他认为这样做的方法是通过博客。彼得说得对,研究人员有他们有组织的平台(主要是论文和会议)来分享他们的工作,但我相信现在工业界有同样多的机会,甚至有更多的人有兴趣听。聚会、讲座、github、kaggle(用于数据集发布)、博客,只是你如何分享你的工作的几个例子。
希望你喜欢这篇文章!
成功应用编程接口的五个技巧
Photo by Radowan Nakif Rehan on Unsplash
现在向世界发布一个基于云的应用编程接口(API)非常容易,它提供一些软件功能作为服务。因此,云 API 空间已经变得非常密集,因此,即使某个特定的 API 提供了潜在价值可观的服务,也有许多其他因素在决定该 API 是否会获得商业成功方面发挥作用。如果你正考虑带着你最新最棒的想法进入 API 市场,这篇文章提供了一些完全主观的建议,告诉你如何增加你的产品不被所有噪音淹没的机会。
这篇文章的一个版本也出现在 《自然语言工程杂志》 。
介绍
几年前,我被要求分析和比较一些基于云的文本分析 API。这项工作的一个间接结果是一对观点文章(见这里的和这里的和和),它们研究了市场上许多更知名的文本分析工具的功能。这些文章引起了我足够的兴趣,促使我发表了一篇更长更详细的对 35 个商业文本分析 API 的深入分析。
我给你这个背景是为了给这篇文章的重点建立一点可信度:在过去的几年里,我花了大量的时间探索和试验大约 50 种不同的 API。这样做的一个副作用是,我看到了各种各样的方法,从许多不同的方面使软件在云中作为服务可用。有些产品近乎完美,结合了高质量的工具和出色的用户体验;其他人,嗯,没那么多。
让我们假设一个软件服务的实际性能质量是给定的:如果一个工具没有做它应该做的事情,那么它将很难获得牵引力。但是性能是不够的:在决定一个 API 是否成功的过程中,还有许多其他的因素在起作用。在这篇文章中,我提请大家注意五个方面,我们可能会广泛地认为这是用户体验,它们影响了我对所遇到的工具的印象。
我对这些特征的重要性的评估不可避免地属于主观领域。但是,虽然不太可能每个人都同意我的观点,但我认为也不太可能只有我一个人有这种困扰。因此,与其冒着失去像我一样的潜在用户的风险,我想建议,下面讨论的问题至少值得任何打算进入 API 市场的人,或者,事实上,已经出现在该市场中的人花几分钟考虑。我认为,如果你避免这些失误,你的企业就有更大的成功机会。
我应该强调的是,这些观察都是在分析文本分析 API 的特定上下文中做出的,因此应该从这个角度来看待它们。但是我认为提出的观点对于许多其他种类的 API 都是相关的,所以我希望它们在这个狭隘的焦点之外还有一些价值。
背景设置的最后一项:你可能认为下面指出的一些问题是相当明显的。我有充分的证据,以存在证明的形式,它们显然不是对每个人都显而易见的。
1.有一个专业的网站
第一印象很重要。对于大多数潜在用户来说,你的网站将是了解你的 API 的入口,所以在这方面花费合理的努力是值得的。
不幸的是,一些 API 的网站看起来像是在 20 世纪 80 年代建立的,那时候使用 Emacs 或 vi 手工制作 HTML 很普遍。从那以后,网页设计和底层技术都在不断发展。现在,使用 WordPress 和 Wix 这样的平台,拥有一个看起来现代、设计良好且美观的网站变得非常容易,而不必自己编写所有简洁的功能。
当然,外表可能具有欺骗性。如果你确实从 20 世纪 80 年代就开始工作了,你现在可能已经很有成就了,你的技术在市场上已经得到了很好的证明。但是一个看起来像是用原始 HTML 创建的网站并不能鼓励我认为你在 API 中使用了最新的技术。这更可能让我怀疑你的技术是否也停留在 20 世纪 80 年代。
你不一定要成为一名网页设计师才能自豪地拥有一个令人敬畏的网站:如今,你可以通过 Fiverr 和 Upwork 等服务以相当低廉的价格获得优秀的设计技能。一旦你的网站建成,请一个独立的第三方用批判的眼光审视你的网站,并坚持让他们给你一个诚实的意见。
不言而喻,特别是如果你提供某种语言服务,但是一定要再三检查你的网站内容的拼写、语法和风格。
当然,欺骗性的外表是有利有弊的:我也见过一些非常惊人的网站,它们背后的产品非常有限。但是我敢打赌,寻找像您这样的工具的客户更有可能跳过似乎来自不同时代的网站。
2.让试用你的软件变得容易
让我很容易就能接触到你的 API 并进行测试。如今,大多数网站使用完全自动化的注册机制,潜在用户通过网络表单提供他们的姓名和电子邮件地址,并立即通过回复电子邮件获得一个 API 密钥,用于解锁可用的服务。唉,一些供应商选择引入更多的摩擦。最糟糕的是手动处理访问请求:请不要让我等上一两天,等你们那边的人来读他们的邮件并授予我权限。请不要让我填写一个长长的表格来解释我想如何使用你的 API。人生苦短,穿不了太紧的鞋子:我会放弃,转向另一个供应商。
当你发送一封带有 API 密匙的邮件时,确保你在邮件中提供一些指示,说明这些密匙是用于什么产品和网站的。我知道这听起来有点奇怪,但是如果你碰巧同时注册了一系列这些东西,那么从第三方订阅服务帐户收到一封电子邮件是没有帮助的,该帐户的名称与所讨论的 API 没有关系,并且实际上没有提到该密钥提供对什么产品或网站的访问。我仍然有一封邮件藏在我邮箱的底部,永远成为零收件箱的障碍。
3.提供有意义的试用访问
许多 API 都提供某种类型的试用访问,因此您可以在决定订阅或购买使用该服务之前进行试验和探索。这当然是好事。如果你不提供试用访问,我强烈建议你这样做:你的竞争对手很可能会这样做,所以不这样做,你就通过阻止产品自己说话来削弱你的营销努力。
API 的试用访问模型分为两大类,这两类都很常见。首先,您可以向用户提供对无限期免费订阅层的访问,该订阅层对可以进行的 API 调用的数量有所限制,或者对可以访问的特定功能有所限制(参见下面的提示 4)。或者,您可以让用户在有限的时间内免费访问全部或部分可用功能。
从用户的角度来看,免费层是更好的选择。我知道你可能不想承担无限数量的终身用户的风险,他们会慢慢耗尽你的资源,却从来不为他们付费。不幸的是,你正在竞争一个更大的领域,像谷歌、微软和亚马逊,有足够高的使用上限的免费层,你实际上可以构建重要的应用程序而不会产生费用。现实是,这些技术中有许多实际上是商品;因此,你现在令人敬畏的网站(见上面的提示 1)不太可能让我相信你是如此独特,以至于我会忍受限时试用。
尽管如此,如果限时试用是你必须要走的路,请至少提供一段合理的时间来试用产品。一周(我已经看到了,伙计)是不合理的:通常情况下,不可预见的情况将意味着在潜在客户有机会正确探索产品之前,试用期就到期了。比较明智的免费试用期是一个月。
理想情况下,您将通过自动订阅机制提供一个免费层。对点击次数施加限制是好的,只要它不是一个低得令人难以置信的数字:为了能够测试大多数 API,每月几千次点击是合理的。300 次免费点击(我不止一次看到过——300 这个数字是怎么回事?),另一方面,可能不值得麻烦地编写一个测试工具。
4.让我试试你所有的特征
有一种趋势——也许并不奇怪——把一个 API 的一些特性标得如此特别,以至于只有付费用户才能使用它们。这些通常是 API 的最新和最先进的特性。例如,一些供应商基于不同的底层技术区分特定功能的两个版本,新的和更好的版本(在撰写本文时,这通常是利用深度学习)禁止试用用户使用。
如果这些特性是你的产品区别于市场上其他产品的原因,你为什么不让潜在客户尝试一下呢?
保持你的收费模式简单也是一个好主意。大多数 API 提供一系列服务(例如,命名实体识别、情感分析和文本分类),并且出于记账目的,每个服务的使用都被算作单个 API 命中。但是一些供应商选择根据所调用的特定服务来收取不同数量的单位费用(因此,例如,分类可能比情感分析花费更多),或者甚至对包含特定类型的结果收取额外费用(例如,包含实体链接可能比简单的实体识别花费更多)。如果你试图计划一个免费试用上限下的测试制度,这只是一个头痛的来源。
5.提供体面的文件
许多 API 都没有被很好地记录,有时甚至非常严重。
例如,如果您提供一个命名的实体识别端点,该端点将类型分配给实体,那么指出识别的类型集是什么是很重要的。如果您提供文本分类服务,记录可以分配的类别集是很重要的。没有这种信息,就很难对 API 进行合理的测试。
如果对 API 的调用可以包含许多参数,记录它们是什么和它们的含义,以及默认值是什么。如果您的 API 返回一个大的属性集合,那么清楚地记录它们:当然,有时从它们的名字就可以很明显地看出,但是更清楚总是更好。如果不清楚返回的属性是什么,还不如不返回它。
我强烈建议使用正式的 API 文档框架。像 Swagger 这样的工具在强加文档的结构和规则方面帮助很大,尽管你仍然需要确保你不会落入提供与内容无关的功能描述的陷阱。给出完整的工作例子,最好是在一系列的编程语言。我的意思是完整的:我应该能够一字不差地剪切和粘贴您提供的示例,并让它们按原样运行,也许以插入个性化的 API 键为模。
为每个发布的 API 版本使用版本号是一个好主意——最好包含在管理信息中,管理信息是 API 返回数据的一部分——这样我就能知道什么时候发生了变化。
不要依赖博客文章作为 API 文档的单一来源。也就是说,博客文章可以为已经有良好文档记录的 API 增加重要的支持,并且有一些供应商在使用博客文章演示详细的用例等方面做得非常出色。
总结
我认为有些 API 的提供者不做我上面推荐的事情可能有合理的原因。
可能还有其他优先事项,这意味着你没有时间或资金来建立一个伟大的网站或更新一个你不久前建立的网站。很公平,但这可能是一种虚假的节约。
也许你的 API 如此特殊,以至于很难访问,或者对免费使用施加严格的限制,或者限制我可以尝试的能力,只会增加稀缺价值。但是很有可能,用不了多久,其他人就会抓住机会复制你的服务,并以更方便用户的方式提供它。
也许你的目标市场由不需要文档或明确例子的读心术者(或前雇员)组成。但我认为,这可能是一个比你原本可能吸引的目标市场更小的目标市场。
归根结底,这都是为了减少摩擦。如果你给潜在客户制造的麻烦比他们需要的稍微多一点点,他们就有可能在其他地方找到他们想要的东西。明显?或许;但是以上的错误仍然会一次又一次的发生。正如我在这篇文章开头所说的,我有存在证明。你知道你是谁。
最后一件事:如果你已经尝试过 API 业务,但是决定放弃它,并且你的 API 不再被支持,请把它拿下来。不要让它处于僵尸般的状态,亚马逊偶尔会收你 56 美分,你甚至不会注意到。在你的联系邮件上放一封自动回复邮件,告诉我你不打算回复,这样我就不会夜不能寐,担心你是否会回复我关于那个模糊名字的参数。
想了解商业自然语言处理领域的每周动态,本周在 NLP 注册 。
原载于 2019 年 9 月 26 日https://www.cambridge.org。
为开源软件做贡献的五个技巧
数据科学家的视角
Photo by Yancy Min on Unsplash
为开源软件(OSS)做贡献是一件值得的事情,尤其是对新的数据科学家来说。它有助于提高技能,在项目协作时提供宝贵的经验,并给你一个展示代码的机会。然而,许多数据科学家并不认为自己是受过正式训练的软件开发人员。这使得为 OSS 做贡献成为一个可怕的提议。
恐惧的一个来源是,似乎软件开发过程中的每一步,从设计到持续集成,都有一套在数据科学培训中经常被忽略的最佳实践。这让数据科学家感到装备不足,无法参与为软件开发人员量身定制的领域。已经有文件证明甚至一些熟练的软件开发人员在决定为 OSS 做贡献时也会焦虑,嗯,对于一个数据科学家来说,这种焦虑会成倍增加。
我们每天使用的几乎所有流行的数据科学库都是成功的 OSS 项目,有时由社区维护并经常改进。想到 Scikit-learn、PyTorch 和 TensorFlow。看,数据科学家可以写出高质量的代码!最终,数据科学家编写代码的目的是将模型交付生产或部署健壮的数据管道。既然我们正在编写软件,我们应该像其他软件项目一样坚持同样的标准。
在这篇文章中,我想分享一些我在过去几年开发数据科学软件中所学到的东西。我的目的是分享我希望有人在我开始数据科学之旅时与我分享的信息。希望犹豫是否开始的没有经验的数据科学家将使用这些提示,感觉被授权开始编写更好的数据科学代码,并尽早为 OSS 做出贡献。
- 找一个有经验的软件开发人员…
…请注意!这个项目对我的个人发展有着最大的影响。我目前所有的软件开发习惯都是以某种形式将有经验的软件开发人员融入到我的生活中的直接结果。值得注意的是,你不一定要和这些人成为最好的朋友。有经验的开发人员可以是你团队中的技术负责人、同学或当地聚会上的人。此外,有一些真正伟大的开发人员定期发推特,在论坛上发帖,写技术博客,并创建播客(我最喜欢的是 Talk Python )。尽最大努力找出不是数据科学家的人,因为他们可以为你提供在数据科学领域更难找到的观点。
这个提示的关键是听跟这些人搞。首先,问问自己,“他们为什么要实施这样的方法”?如果你不明白,就去查。如果你还是不明白(或者如果你明白了),给他们发一封电子邮件或者回复一条评论,让他们详细阐述他们的观点。很有可能,这些人在他们的决定背后有很好的理由。从软件开发的角度来看,在你的问题的上下文中看到或听到这些原因会让你更好地理解这个主题。我不建议你不断地追逐有经验的开发人员,尊重他们的时间和空间是很重要的。
2.开源社区并不是来抓你的
阻止人们为 OSS 做贡献的一个不幸的误解是,如果他们公开他们的代码,将会被嘲笑或奚落。大多数时候,这是不正确的。这和其他类型的社区没什么不同,几个害群之马就能毁了所有人的聚会。我为小型 OSS 项目、流行的 OSS 项目做出了贡献,甚至还维护了一些我自己的项目。在每一个场景中,每一次互动都是最起码的尊重,而且在大多数情况下,人们都很感激。在为 OSS 做了两年多的贡献之后,如果有人对我不尊重,那么在这一点上他们显然是局外人。
3.练习 git 等。
It’s never been easier to practice git, all the major hosting platforms allow users to create unlimited private repositories.
**一些人声称“不熟悉 git”或者仅仅是“不熟悉 GitHub”作为他们不为 OSS 做贡献的理由。这就是为什么第三个数字的标题包含“等”。GitHub、Bitbucket 和 GitLab 具有大量支持 git 工作流的功能,但本质上并不被视为“git”的一部分。因此,即使对于一个从未使用过 GitHub 的有经验的 git 用户来说,在熟练的道路上仍然有一个轻微的学习曲线。
不要在本地编写所有的项目,而是预留一些额外的时间来推进到上面提到的一个平台。将其设为私有,如果你愿意,你仍然可以安全地与朋友共享回购。在重定一个特性分支的基础后,练习发出 pull 请求或直观地检查 git 提交历史。更加熟悉私有存储库中的选项卡、按钮、工具和 git 工作流将会让您在处理公共贡献时更加自信。
你很难找到一个成功的数据科学项目不使用某种形式的版本控制来进行软件开发,git 恰好是最受欢迎的。因此,试着在日常项目中使用 git 工作流。然后,当在 OSS 项目上与人合作时,你不会被 git 工作流程的失误所困扰,你会把时间花在代码上。
4.使用 软件最佳实践
Kaggle 的数据科学家 Rachel Tatman 最近发布了一个视频和一个内核,概述了如何编写更专业的数据科学代码,因此我将建议遵循她的建议,在我们重叠的地方保持简短。当您与合作者互动时,这些都将使您的生活变得更加轻松,再次允许您专注于添加功能,而不是回去清理坏习惯。
4a。使变量名可读
其他数据科学家可能知道i
和j
是数组A
的元素,但是数学符号并不能转化为源代码中的信息变量名。我喜欢使用在重读源代码或别人第一次阅读时有意义的变量名。但是我会让 Will Koehrsen 为数据科学家的命名惯例提出建议。
4b。慷慨评论
不管他们是否意识到这一点,数据科学家经常实施一种叫做方法链的编码风格。当内存中有一个 DataFrame 对象时,我们通常知道下一步将一列转换成我们想要的格式的确切步骤。方法链接的一个缺点是链接很难调试,尤其是没有注释的时候。写评论的时候想想别人,记住,一个简短的评论可以帮你很大的忙。
4c。编写单元测试
你以后会感谢自己,或者无论是谁在审核你的拉取请求,都会感谢你。有时候单元测试对于小型的一次性数据科学项目来说没有意义。但是当你考虑扩展你的代码或者与他人合作时,单元测试变得更加重要。
当代码是模块化的时,它更容易测试,也就是说,编写函数的目的是执行一两个操作。下面是一个用 Python 规范化熊猫数据帧的函数的例子。此函数的单元测试断言平均值和标准偏差分别为 0.0 和 1.0。如果这个测试失败了,开发人员就知道“normalize_dataframe”方法出错了,并且知道从哪里开始调试。
Test that the normalize_dataframe function is working as expected.
4d。使用持续集成(CI)
恭喜你,你写了单元测试并把你的代码推送到 GitHub,但是几天后,有人报告说他们不能让你的代码在他们的机器上运行。CI 将有助于在这些问题成为 GitHub 上的问题之前发现它们。 Travis 是一个 CI 服务的例子,它直接与 GitHub 免费集成,用于公共回购。CI 服务允许您在容器化的环境中构建和测试代码。我建议为您打算与其他人合作的项目建立一个 CI 服务之一。
Travis interface showing a passing build with multiple versions of Python on a Linux kernel.
5.使用调试器
对于数据科学项目来说,使用带调试器的代码编辑器(有时称为集成开发环境(IDE ))似乎有些矫枉过正。但是一旦你学会了如何使用编辑器的调试器,它就会成为软件开发的强大工具。调试器允许用户执行代码直到一个断点,然后探索变量名称空间,这使得“调试”程序崩溃的原因变得更加容易。在放弃希望和切换回笔记本电脑之前,你应该给自己至少 30 天的时间来试用调试器进行开发。花点时间阅读教程,并询问更有经验的软件开发人员(可能来自技巧 1 ),他们是否可以带你调试下一个 bug。
Jupyter 笔记本是许多用户首次开始数据科学项目时的热门选择。笔记本是探索性数据分析和可视化的好工具,但是它们也有缺点,Joel Grus 在这里对其进行了评论。也就是说,这些单元不能乱序运行,它们对于初学者来说很难理解,并且会助长坏习惯。两个流行的 IDEpy charm和 VS Code 已经认识到笔记本的流行,最近直接在 IDE 中集成了对它们的支持。有希望的是,数据科学家将会为了笔记本支持而来到 ide,但是为了调试器而留下来。
奖励:乐于接受建设性的批评
请记住,OSS 是通过正式和非正式的代码评审来维护和改进的。人们会看你的代码,评论它,可能会要求你修改几行。如果你已经走了这么远,这不就是你一直在寻找的吗?有人花时间审查你的代码,并花费足够的精力去尝试和改进它。
随着您的软件开发技能的提高,您会遇到其他用户要求您修改代码,但是您可能希望保持原样。用你期望得到的尊重来捍卫你的决定,这和做一个明智的人没什么不同。
我希望这些建议对你有用。这些技巧是针对开源的,但也适用于商业数据科学家和开发人员。随着您对其中一些技术的熟练掌握,您应该会注意到,您在 OSS 环境中识别和修复 bug 或实现功能所需的时间减少了。通过现在投入时间成为一名更好的程序员,从长远来看,你将有更多的时间来解决世界上的数据科学问题。
数据科学编程入门的五个技巧
尽早投入时间和精力,它会让你日后成为一名伟大的程序员
如果你想成为一名真正的数据科学家,你需要会编码。这是无法回避的。有些人不喜欢这个想法,许多公司已经通过提供“自动化数据科学”产品来利用这种不适——我们会编写代码,所以你不必这么做。如果这些是你唯一的工具包,你就不是数据科学家。
强大的数据科学家的试金石是他们不害怕任何数据集或任何问题。他们可能不知道如何立即处理,事实上,他们不知道是很常见的。但是他们知道他们可以找到如何解决的方法,如果问题再次出现,他们最终可以产生整洁、高效、可重复的代码来处理问题。如果你想成为一名伟大的数据科学家,这就是你需要瞄准的心态。
一个强大的数据科学家的内在自信和能力很大程度上来自于他们最初是如何学习编码的。如果你刚刚开始,你如何开始最初的几周和几个月的学习对你是否会在以后的日子里茁壮成长至关重要。如果你采取懒惰的方法——*如何而不是为什么——*你会养成一些习惯,这些习惯会让你以后变得不自信和效率低下。如果你尽早开始工作— 了解如何做和为什么做— 随着时间的推移,你会逐渐开始感觉到自信的建立和能力的增长越来越快。
这里有五个小贴士可以帮助你在开始学习时有一个良好的开端。
1.选择正确的学习资源
人们以不同的方式学习。比如我不太擅长视频学习。我需要一份详细的书面叙述,我可以按照自己喜欢的节奏仔细分析和理解。
避免过于实用的来源——这意味着它们向你展示了该做什么,但没有解释为什么会有效。如果你复制粘贴一个方法来解决一个编码问题,而你不知道为什么这个方法有效,那么你就没有真正学到任何东西,因为如果以后再次出现类似的问题,你将不知道如何应用这个方法。
好的学习资源投入时间来分解方法的底层逻辑。最好的方法实际上是鼓励你通过提示和技巧自己编写方法,而不是给你现成的东西。深思熟虑的教育者会提供后续问题,要求你把你所学到的东西应用到另一个环境中,以证明你已经学得很好了。
很难在一个在线模块中找到所有这些内容,因此我建议您准备一个书面资源,以便用您选择的语言进行深入学习。如果你问朋友、同事或同学他们用什么,在接受他们的推荐之前,确保他们有类似的学习理念。
2.参与游戏
就像一个运动队在有奖金的情况下会更加努力一样,如果有激励,你会学得更好。激励是而不是学分,如果你完成了一个在线模块,你可以把它放在你的简历上。激励是真正的成就,它让你现在或未来的工作变得更好、更强——你和其他人可以明显地看到事情是如何因为你投入的工作而得到改善的。
举个例子,当我第一次学习编码时,我在自己的一个数据集上给自己设定了一个挑战。我的同事每年通过 Excel 处理几十万行数据。这是一项高度手动的工作,并且每年花费的时间越来越长,因为 Excel 一直在努力处理不断增长的数据集。
在我学习基础知识的同时,我也花时间将我的新知识应用到这个数据集上。这并不容易。我犯了很多错误,花了很长时间试图找出问题所在以及如何解决。但是这个反复试验的过程很重要,因为它迫使我接触到我正在学习的语言的内部运作,并深入了解它在幕后是如何运作的。
几周的工作产生了一个完全自动化的脚本,可以轻松处理这些越来越大的数据集——这让我和我的同事们既兴奋又敬畏。我的学习带来的切实好处是显而易见的,它给了我继续前进的动力和信心。
处理你自己非常熟悉的数据集是将早期学习付诸实践的最有效的方法之一。避免来自互联网的随机数据集,在那里你可能不理解变量代表什么或者各种操作是合理的和相关的。游戏里有皮肤就好多了。
3.错误是你的朋友,不是你的敌人
当你第一次学习时,你会犯很多错误。但是,如果你以正确的方式回应他们,这确实是一件好事。
无论您选择哪种语言,对于未受过训练的人来说,错误消息可能显得简洁或无用,但是多花一点时间在它们上面,十有八九,您会对您的命令不起作用的确切原因有一个相当好的理解。这一点很重要,因为如果你明白为什么这次没有成功,你就知道下次如何让它成功。
很多时候,我看到朋友和同事完全无视错误信息的内容,直接向我或其他人寻求帮助。由于我已经学会将错误消息视为我最好的数据科学朋友,所以我经常可以看一眼错误,然后直接告诉他们问题是什么。
当您看到错误消息时,请将其作为解决问题的主要途径。通常它会提到另一个功能或操作,你也需要深入了解,以了解哪里出错了。所有这些都是深入了解你所处环境的重要组成部分。
4.在添加附件之前,先学习您的基础语言
像 R 和 Python 这样的语言受益于丰富的附加组件和包生态系统,以帮助导入某些常见任务或问题所需的功能。但是注意不要太快地投入其中。这些软件包依赖于它们的基础语言,没有基础语言就无法运行。如果你变得过于依赖这些而没有对你的基础语言有一个像样的理解,你会让你自己的生活变得更加困难。
如果您不了解基础语言中的数据类型和数据结构是如何工作的,或者如果您不完全理解您的系统如何区分基础功能和导入功能之间的优先级,您可能会最终陷入各种各样的困境,您不知道如何摆脱困境。错误会突然出现,你不知道它们是什么意思。函数可能会产生一个完全出乎意料的输出,您对此一无所知。
在早期,我给自己设定了一个挑战,在尝试使用附加包之前,先用基本语言完成一项任务。在我学习之初,当我的操作相对简单时,这对我理解基础语言非常有益。我向任何处于学习初级阶段的人推荐这种方法。
5.拥抱社区
我喜欢在开源数据科学领域工作的一个主要原因是它的社区。不管你正面临什么问题,很有可能有人曾经面对过它,并能给你建议来帮助你学习。没有任何一本教科书能够涵盖你在学习过程中可能遇到的所有问题,所以随着你的学习进步,社区将逐渐成为你的重要资源。
新手可能会害怕社区,但是真的没有理由害怕。最大的沉默往往是理智的。这是个愚蠢的问题吗?我会受到尴尬的斥责吗?你的一点点思考和关心可以帮助减轻你的担忧。
首先,仔细选择你的社区。如果你是一个初学者,不要在 Twitter 标签上发布问题,这样会把问题推给有经验的程序员。找到与你的发展水平相匹配的在线群组和标签,并把你的问题导向那些人。
如果你使用的是更广泛的资源,比如 StackOverflow ,学习它的规则并遵循它们。如果你是一个初学者,你问的问题很有可能已经被回答了,所以在你考虑把它作为一个新问题发布之前,仔细搜索一下。如果你把它作为一个新问题发布,确保你是真正具体的,并提供一个你的代码的最小可复制的例子。如果你发布了一个没有例子的普通问题,你肯定会被批评,这是你应得的!
如果你的问题得到了回应,但你认为它太简短了——例如,有人只是发布了你需要的代码,却没有解释——不要害怕要求他们解释为什么它能工作。大多数回答者希望提供帮助,他们希望在平台上建立自己的声誉,因此他们通常愿意扩展他们的回答。
如果你正在开始你的数据科学学习之旅,并且你渴望在未来成为一名伟大的数据科学家,这些只是我推荐的几件事情。祝你在这激动人心的旅程中好运!
最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在 LinkedIn 或Twitter上找我。
ML 帮助广播公司实现新效率和重塑 CX 的五种方式
资料来源:unsplash.com
随着网飞和 Hulu 等广播巨头主导市场,赢得眼球并让观众持续关注你的视频内容绝非易事。但也不是不可能。人工智能和人工智能开发专家建议创建一个连贯的营销策略,并使用视频和图像分析技术的成功组合来取得成功。
自动广告检测
如果您的业务需求是让观众免受商业广告的烦扰,请实施高级视频分析。这种方法能够基于一组模式(如无声黑框或镜头切换率)准确识别广告插播,并自动删除它们以增强观看体验。
类似的机制可以用于驱动个性化广告。通过检查观众当前和过去的活动,并应用 ML-powered 视频内容分析,您可以获得有价值的见解,并可以轻松确定最佳广告类型、最相关的插入位置以及最佳的投放方式,从而最大限度地提高广告活动的效果。
智能异常发现
自动检测视频序列中的异常事件非常具有挑战性,因为这些事件的定义并不明确,但并非不可实现。
ML 专家使用卷积长短期记忆(Conv-LSTM)网络和其他集群化方法来预测视频序列的演变,并隔离异常内容,如故障、黑屏、人工文本等。
该流程以每帧 1 毫秒的 FHD 视频处理和全面的后处理为前提,可以轻松集成到您的 QC 工作流程中,以确保完美的内容交付。
严格的法规合规性
当您向全球数百万观众提供内容时,没有出错的余地。您不仅应该提供高质量的视频,还应该对其进行调整以符合特定国家/地区的特定法规。
手动操作会浪费时间和金钱,并增加出错概率。想想通过支持 ML 的 MAM 编排来自动化内容审核和法规遵从性流程。这包括全面的视频分析(通过对象和面部识别),以及在创纪录的时间内准确检测成人内容、暴力、种族主义、不良语言或敏感主题(如吸烟和饮酒)。
自动标记和删除因政治或宗教原因不合适的内容,使您始终严格遵守当地法规,同时保护您的品牌并改善观看体验。
智能内容个性化
在观看内容和观看方式上有如此多的选择,顾客变得比以往任何时候都更加挑剔。考虑到他们的观看行为正在快速变化,你应该准备好在内容、付费和订阅方面提供最相关的建议。
为了实现这一目标,首先要收集所有可用的数据,包括应用内用户行为、社交数据、电影元数据、电影受欢迎程度、排队项目、人口统计、位置、语言等等。下一步将利用最佳的 ML 方法,如聚类算法、马尔可夫链或关联规则,进行广泛的数据分析并自动提供个性化服务。
智能生成促销材料
ML 也是自动制作引人注目的营销材料的一个有前途的途径。分析观众的偏好,如最喜欢的类型和演员,以生成最佳的电影缩略图,预告和预告片。通过这种方式,您将能够增加内容消费并提高客户参与度。
如果你是一名体育广播员,考虑实施 ML 来创造亮点。神经网络将进行全面的实时场景、比分和事件检测,以及音频分析和球员跟踪,以立即生成引人入胜的比赛集锦,节省您繁琐的手动工作,提高您的运营效率。
最后的想法
ML 已经从一个炒作的话题发展成为带来长期利益的强大技术。因此,如果您愿意将您的服务提升到一个新的水平,请考虑构建一个强大的数据驱动型解决方案,能够自动化一系列业务运营,并为增强决策和客户体验提供可操作的见解。
在机器后面修理机器
为什么我们需要解决人类决策中的偏见以改善技术及其未来治理,以及如何做到这一点
Photo by Javier Allegue Barros on Unsplash
2017 年将人工智能偏见带入了主流意识,从那时起,公众的关注度只有激增。关于人工智能中偏见的原因,以及更令人烦恼的根除偏见的困难已经说了很多。这些评论大多承认机器偏见是人类偏见的反映;然而,很少有提议的解决方案真正解决了根本原因:人类。
这种缺席并不奇怪。偏见在我们这个物种的整个历史中一直存在;这将是一个需要解决的大问题。相比之下,从外部关注如何调整一个行为不端的人工智能要诱人得多。
或许是时候转移焦点了。在机器中复制我们的决策过程的好处之一是,我们有机会看到自己的映像,并从中学习。事实证明,我们从追踪人工智能偏见中学到的经验教训可以为解决我们自己不完美的人类决策中的偏见提供一个有用的框架。
为什么现在这种内部操作系统升级特别重要?毕竟,这么长时间以来,我们已经设法克服了偏见的负面影响。
两个因素使得这项工作变得紧迫。首先是一个并不太新的现象,但它正变得越来越明显:技术前所未有的可扩展性意味着设计中的任何错误都会产生相应规模的影响。第二个因素是,我们正处于技术治理的转折点。政府、技术专家和利益相关者——让我们称这个集体为“设计师”——正急切地开始一个新的监管阶段。
正如每次人工智能设计师创建一个系统,他们都冒着在其中建立盲点的风险,这些治理设计师也冒着将自己的盲点投射到他们提出的解决方案中的风险。当这种情况发生时,技术和监管技术的治理系统都有可能以难以控制的规模放大决策中的错误。
如果我们希望设计出解决技术意外后果的方案,并预见未来的问题,我们必须首先检查这些机器背后的机器:我们自己。
看到我们自己对人工智能的偏见
Background by Alina Grubnyak on Unsplash
在人工智能中引入偏见的许多方式中,有三种现象与检验我们自己的决策特别相关。(关于人工智能偏见的更多信息,请参见郝凯琳的总结这里。下面引用了一些段落。)
让我们来看看偏见是如何通过问题框架、处理盲点、狭隘的社会背景而引入的。
诬陷问题。当计算机科学家创建深度学习模型时,他们做的第一件事就是决定他们实际上想要它实现什么。例如,一家信用卡公司可能想要预测客户的信用度,但是“信用度”是一个相当模糊的概念。为了将其转化为可以计算的东西,公司必须决定是否想要,比如说,最大化其利润率或最大化得到偿还的贷款数量。然后,它可以在该目标的背景下定义信用度。该选择可能导致意想不到的后果或有害行为;如果利润最大化是目标,计算机可能会推荐掠夺性贷款。
…
未知的未知数 。偏差的引入在模型构建过程中并不总是显而易见的,因为您可能直到很久以后才意识到您的数据和选择对下游的影响。一旦你这样做了,就很难追溯性地找出偏见的来源,然后找出如何消除它。"
缺乏社会语境 。类似地,计算机科学家被教导构建问题的方式通常与思考社会问题的最佳方式不兼容。
毫不奇怪,这些人工智能设计错误听起来与人类决策中的偏见相似。
人类往往看不到更大的图景,我们狭隘的理解导致我们可能不会做出选择,如果我们有更好的数据,或者对我们的环境有更完美的理解。我们在不知道其下游影响的情况下做出选择;事实上,我们在不知道形成我们决定的上游影响的情况下做出选择。
一种思考方式是,我们的决策(D)是几个变量的函数:我们拥有的信息(I ),我们如何解释该信息的价值观+经验(ve ),以及给定情况下的优先级(P ),它赋予我们解释的不同元素以权重,并允许我们选择行动路线。我们有多少次可以说我们真正意识到了所有这些变量?
剧透:不常。我们意识到我们的一小部分决定、情感、行动和行为。此外,当我们做出决定时,我们的无意识情感认知经常与我们的有意识认知沟通,我们回溯性地运用有意识认知向自己解释我们是如何做出决定的。即使我们认为我们意识到了自己的过程,但我们通常并没有意识到。
[*人工智能偏见的另一个领域与人类认知有明显的对比是有缺陷的数据:有可能在数据集上训练人工智能,要么 1)不代表现实;2)反映现有的偏见;或者 3)在准备阶段变得有偏见,当设计者选择哪些属性对 AI 系统重要时。这篇文章的重点是解决社会背景,框定问题和盲点,但更多关于有缺陷的数据偏见如何表现的阅读,请参见犯罪和累犯用有缺陷的数据训练的预测工具中的性别和种族偏见。]
技术和治理中的意外后果
Background by Markus Spiske on Unsplash
监管人工智能并不是治理设计师让我们不完美的人类决策发挥作用的唯一空间。
技术方面的一系列治理挑战——尤其是在互联网方面——与日俱增。它包括从消失数据隐私的一切;对关注注意力经济和推荐算法播激进化;在维护言论自由和防止有害内容之间找到平衡;到假新闻和侵蚀信息完整性;到巨魔和机器人淹没真实的话语和延续在线骚扰(最重要的是,不成比例地影响妇女和少数民族);即使在我们开始处理直接选举干预之前,也要过滤那些孤立社区和冲击公民言论的泡沫。所有这些挑战都因以下事实而加剧:少数平台主导着在线媒体市场,威胁着内容选择的多样性,并引发其他垄断担忧。
委婉地说,这是我们的设计师需要应对的复杂挑战。为了迎接这一挑战,他们不仅要成为技术娴熟的程序员和法律从业者;他们还必须应对一系列棘手的道德、哲学和社会权衡。在这些不同的演员面前考虑一些棘手的问题。
私营公司的关键问题:
**在线平台应该保持一个自由开放的市场,让消费者成为自己消费的最终仲裁者吗?**或者他们应该参与主动 监管内容的以保护他们的消费者免受其产品有害副作用的影响?如果是后者,公司如何避免无意中滥用审查权?
用户 数据 的 商品化 是社会可持续的商业模式吗?公司应该在多大程度上优先考虑股东的财务回报,而不是外部性的定价(如保护消费者隐私或选举诚信)?
民主政府的关键问题:
政府应该如何权衡自由开放的互联网促进民主的效果与自由开放的互联网破坏民主的效果?考虑一下:美国、德国、英国、、欧盟委员会、法国、马来西亚和捷克已经在采取措施遏制假新闻和/或仇恨言论。然而,这种立法也可能被专制政府用来镇压民主,俄罗斯的情况很可能就是如此,该国在德国的 NetzDG 法通过后立即复制了该法;人权专家预计,俄罗斯会以关闭假新闻为幌子,用它来压制政府反对者。
在保护公民权利的过程中,政府应该如何确保他们自己的科技行动不会损害公民权利?
国际治理的关键问题:
主权原则和针对具体国家的规则是否应该适用于网络环境?即使在已经批准了联合国《公民权利和政治权利国际公约》第 19 条(全球知情权)的国家,寻求正义的公民也会面临同样的执法困难,这已经使国际治理领域变得复杂。
**当政府在国际市场上的要求违反了国内政府的法律时,企业应该如何应对?**例如,全球网络倡议成员和美国公司微软承诺保护用户的隐私权,以回应政府的监控要求;尽管如此,他们仍在人工智能方面与中国合作,这可能有助于中国已经很大的国家监控。微软并不孤单:所有希望在中国开展业务的国际公司都必须遵守其在国内存储数据的要求,允许中国安全部队访问关键的用户数据。
这些例子只是我们的设计师要解决的问题的一小部分。考虑到利害关系,我们不能在答案中加入偏见。我们需要设计师严格地询问他们自己的决策过程:他们正确地设计了问题吗?他们确信他们的信息没有缺陷吗?他们是否意识到自己的上下游盲点?最重要的是,他们是否将这些问题置于适当的社会背景下?
让我们探索一种方法,设计师可以确保他们的答案是“是”
沉浸作为解决偏见的一种手段
Photo by Alina Grubnyak on Upsplash
最近,一家科技公司派了一群高层领导去西弗吉尼亚州南部的一个小镇进行为期一周的学习考察。从表面上看,这个地点是一个奇怪的选择:该镇人口约 3000 人,网站数量微不足道,不是一个有意义的用户市场,尤其是对于一家在全球范围内衡量业务的公司而言。
随着来访的高管与当地企业主、政府官员和家庭交谈,他们与企业的联系开始显现。在自动化破坏了工作的主要来源(采矿)后,该地区遭到了破坏,来访的高管们发现自己沉浸在几代人的绝望感中,这种绝望感是由根深蒂固的缺乏机会造成的。神圣的 sht* ,他们中的几个人意识到,*我们即将在我们的自动驾驶上做同样的事情。其他人思考了围绕他们海外数据中心建造的城镇与美国公司城镇的残余部分之间的相似之处,当矿业公司突然搬到其他地方时,这些城镇遭到了破坏。*我们太专注于扩展,他们意识到,我们忘记了关注 对当地的影响。
这一经历促使人们对公司在世界上的角色和责任进行了严格的审查,最终导致这些高管的决策过程重新调整。
他们了解到的信息并不新鲜。事实上,一些访问者可能之前就已经把这些点联系起来了。然而,人类惊人地不擅长仅根据信息行动;经历和情感是一种更为可靠的方式,可以获得推动决策的理解。这些高管通过身临其境的体验拓宽了他们的社交范围,意识到盲点,并在这样做的过程中,不仅为他们的同事和最终用户,也为他们的行动所影响的更广泛的生态系统培养了同理心。
识别我们的社会背景是一种有效的方法,既能打破我们的偏见使之变得棘手的问题,又能预见不可预见的后果。
2017 年,一群可持续发展专家进行了一次类似的浸入式旅行。随着《巴黎协定》的通过,该集团取得了巨大的胜利,但在随后试图兑现该协定的承诺时,却遭遇了强烈的阻力。他们决定扩大自己的社交范围。在一个极度忠于煤炭行业的城镇沉浸了一周之后——游客们曾一度将煤炭行业视为死敌——该组织对挑战的框架开始发生变化。其中一位参观者是一家全球消费品公司的可持续发展主管,他是这样说的:我职业生涯的重中之重是“消灭煤炭”。我刚刚意识到,要实现我的目标,我的首要任务是为煤矿工人创造就业机会。 *
*他还打算保持其他优先事项,但他的观点的精神仍然存在:他觉得他一直以错误的方式思考问题。
该组织的首要目标是帮助世界实现碳排放承诺,这一目标并没有失去,但现在他们对这个问题的看法不同了。回到我们在人工智能偏见方面的课程:在沉浸之前,团队一直像一个被编程为清洁的机器人一样操作;不幸的是,如果它的设计师没有考虑到清洁这一直接目标之外的更广泛的环境,这个机器人可能会无意中打碎任何阻挡它的花瓶。同样,如果该组织忽视了其目标周围的大环境,他们的政策可能会产生意想不到的负面影响(即失业矿工)。更糟糕的是,这些副作用可能会在未来造成更大的后果【见:一个导致 2016 年选举结果的意外副作用的例子】。通过扩展他们的社会背景和重新构建问题,这个团队已经学会了重视和考虑他们所处的大环境。他们避开了一个打碎的花瓶。
在这两种情况下,反思和公开对话对于重新调整决策至关重要。每天,主持人都帮助来访的团队处理他们所经历的事情,梳理出对他们企业当前和未来运营的影响。通过这种高度结构化的过程,小组能够利用他们扩大的社会背景,注意到他们的盲点,并重新检查他们的选择的上游影响和下游影响。
这些沉浸是由领导人的探索领导的,这是一个专门提供这种内部重新校准的组织【披露:我已经为他们工作了近 5 年】。也就是说,有很多沉浸感导致人们在没有专业指导的情况下重新调整他们的决策。德里克·布莱克(Derek Black)是一名 13 岁的程序员,他设计了互联网上第一个也是最大的白人民族主义网站 Stormfront 的儿童页面。
德里克在家接受教育,几乎完全在白人至上主义意识形态的封闭世界中长大。他来自一个著名的白人至上主义者家族:(他的父亲唐·布莱克是风暴前线的创始人和三 k 党大巫师;他的教父大卫·杜克(David Duke)也是三 k 党大巫师),德里克从小就大量参与运动。许多人认为他会继承父亲和教父的衣钵,成为社区领袖。
这些故事反映了我们所有人都曾直观地经历过的一种现象,尽管没有那么戏剧化。更多的时候,扩大我们的社会背景是一种相当日常的体验,一种具有递增效应的体验:我们通过假期旅行,或在地铁通勤阅读材料的页面上,或者,事实上,通过地铁本身,体验扩大的背景。(不过,就我的家乡纽约地铁来说,这可能有点太沉浸了……)。
具有讽刺意味的是,我们在职业阶梯上爬得越高,获得的决策范围和影响力越大,我们拓宽社会背景的机会就越少。有时,这种隔离是物理上的:管理人员的一天被如此管理,以至于他或她直接从家出发,通过私人交通工具往返于办公室,很少遇到他/她所了解和控制的环境之外的世界。这种孤立也可能是智力上的:对高级决策者的时间有如此多的要求,让他们参与上述故事中描述的那种耐心的、非事务性的沉浸是一种反叛行为。更普遍的是,人们期望这些领导人的每一次参与都得到优化,以实现最大效用。
这样的权衡是短视的。最终,我们为根除偏见所做的投资会在我们今后避免的危机中获得回报。
接下来呢?
正如我们已经看到的,融入不同的社区是确保我们尽可能拥有最普遍视角的有效方式。当与开放、诚实的反思相结合时,它可以暴露盲点,并导致我们做出决定的方式发生变化。这个过程看起来像这样:
不幸的是,如上所述的沉浸法非常昂贵,而且可复制性有限。好消息是**的运营结构和政策可以复制一些沉浸的价值。**多元化团队、多利益主体治理和透明度是几个这样的结构或政策。
多样性:硅谷和国会山的同质性带来了一个重大风险,即盲点将蔓延到科技产品和治理解决方案中。改变 雇佣惯例和招聘有助于解决那些盲点,但这种修补不能解决所有问题。
为了收集更广泛的跨部门观点,公司已经开始尝试从公众或多学科委员会那里征求意见。这是正确的意图,但执行仍然有一些的缺陷有待解决。
技术专家和立法者会很好地关注 多利益主体监管 的例子,这种方法不仅带来了多样性的好处,还具有独特的灵活性、透明度和包容性。虽然没有单一的多利益主体模式,但这种方法在治理技术和其他领域的成功已经被反复证明。
最后,为决策过程提供透明度是一个重要的防故障措施。如果设计师没有充分根除内部偏见,如果正式的团队结构没有提供必要的思想多样性,那么透明度可以让更广泛的受众探究设计师的决策,潜在地捕捉偏见。增加透明度的努力已经开始,包括对“可解释的人工智能”(XAI)的研究,其中人工智能系统的决策过程被从其通常的黑箱中取出(尽管许多技术专家争论 XAI 的有用性)。治理和监管也应该采取同样的方法:设计者需要提供透明度,说明考虑了哪些权衡,以及他们如何在二者之间做出选择。
这里有许多其他杠杆可以实现偏差捕捉。关键是找到鼓励多角度、同理心和基于关系的合作的方法。不管我们采用什么方法,最重要的是:在我们要求我们的设计师灵活运用精确的、说教式的编码语言、法律或政策来设计解决方案之前,我们需要他们熟悉人类经验的复杂性、细微差别和多样性。通往流利的道路是通过解决内部偏见。
如果你有兴趣阅读更多关于人类偏见和人工智能的内容,特别是正在开发的捕捉偏见的工具,请查看詹妮弗·苏基斯的精彩作品 这里 。她举的 达里尔·戴维斯 的例子促使我把德里克·布莱克的故事包括进去。
感谢斯坦福 全球数字政策孵化器 对多利益主体方法和治理挑战的研究。
旗帜颜色可视化——从地理标志到传单,再到背面
在不影响质量的情况下,创建一个具有多种颜色的多边形。
我一直对数据可视化很感兴趣,并且我是一个长期潜伏者。2019 年 7 月 1 日,一个关于各大洲国旗颜色频率的帖子引起了很多人的兴趣。正是从那篇文章中,我有了做这种观想的想法。
这个想法很简单(执行起来并不简单),计算每面国旗的颜色比例,并用这些颜色在地图上标出每个国家。我有一个以前的项目,使用国旗颜色比例来制作原子图标,所以我知道我应该能够做到这一点。不幸的是,我错了,我花了三次尝试去正确地观想它。
在深入每个尝试的细节之前,这里是我使用的数据来源。
尝试 1 (Python + Geopandas):
在我以前的可视化(简单的 choropleth 地图)中,我一直使用 Geopandas。它可以非常容易地输出高质量的图像。
我做的第一件事是计算地图上每个国家的颜色比例。我修改了下面 StackOverflow 帖子中的代码,以满足我的需要。
for index,row in map.iterrows(): # map is the GeoPandas variable
country_code = map.loc[index,'ISO_A2'].lower()
country_data=[]
try:
flag_image = Image.open(FLAGS_DIR+country_code+".png")
except FileNotFoundError:
continue
flag_image = flag_image.convert("RGB")
pixels = flag_image.getcolors(flag_image.width * flag_image.height)
sorted_pixels = sorted(pixels, key=lambda t: t[0])
dominant_pixels = []
for pixel in pixels:
if pixel[0]*100/(flag_image.width * flag_image.height) > 5: #Top 5 colours only
dominant_pixels.append(pixel) for pixel in dominant_pixels:
percentage = pixel[0]*100/(flag_image.width * flag_image.height)
color = "#%02x%02x%02x" % pixel[1] # HEX Conversion
country_data.append({"color":color,"percentage":percentage})
data[country_code] = country_data
当试图给这些国家上色时,这个尝试出现了问题。Geopandas 不能使用多种颜色填充多边形。有一段时间,我想过妥协,只用最主要的颜色填充。实现这一点也很困难,我找到的最接近的可能解决方案是这个 Github 问题。
我无法填充最主要的颜色,所以我放弃了使用 Geopandas。
在上面坐了一会儿后,我想起 LeafletJS 使用 CSS 来设置地图的样式。因此,在将国旗颜色数据保存到 JSON 文件后,我开始了第二次可视化的尝试,现在是用活页 JS。
尝试 2:小册子
我对 LeafletJS 寄予厚望,在某种程度上,它是成功的。关于使用 CSS 支持渐变的传单,我几乎是正确的。
传单使 SVG 元素不支持 CSS 渐变,但他们自己的渐变元素。
我很容易就能涂上最主要的颜色,但是要做渐变却很难。
我必须为每个渐变创建元素,并将其链接到每个 SVG 路径。
我使用下面的代码向每个路径添加了国家代码
onEachFeature(feature,layer){
layer.options.className = "country " + feature.properties.ISO_A2.toLowerCase()
},
然后在传单地图的add\
事件上,添加了以下代码
.on("add",function(){
for(let pathElm of $(".country")){
classes = Array.from(pathElm.classList);
country = classes[classes.indexOf("country") + 1];
flag = flagData[country]
console.log(flag)
$("body").append(`<svg viewBox="0 0 10 10"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="${country}" gradientTransform="rotate(90)">
${flag.map((entry,index) =>{
return `<stop offset="${flag.slice(0,index+1).reduce((a,b)=>{return {percentage: a.percentage + b.percentage}}).percentage}%" stop-color="${entry.color}" />`
})}
</linearGradient>
</defs>
</svg>`);
$(pathElm)f.attr('fill',`url(#${country})`);
}
这能够产生我想要的渐变地图,但是在添加属性后,我在自然地球数据网站上看到了下面的免责声明
免责声明
自然地球矢量根据事实上的状态来绘制国家的边界。我们展示了谁实际控制了地面局势。请随意混搭我们的争议地区主题,以符合您特定的政治观点。
为了避免以后的问题,我决定添加争议地区的地图,并用白色填充。
这需要一点重构,但是我可以用下面的代码轻松地合并这两个地图。
L.map('mapid',{
center: [39.73, -104.99],
zoom: 5,
layers: [mapLayer,disLayer]
});
我以为我完成了,但是将地图导出到一个好的图像被证明是不可能的。我尝试了许多插件,但没有一个产生足够好的图像。一个想法出现在我的脑海中,关于从开发者工具中复制 SVG 并使用 Inkscape 产生一个好的图像,但传单为不同的缩放级别呈现不同的路径。当地图完全缩小并变得详细,但只有放大的部分被渲染时,路径不太详细。
这次尝试也失败了,但给了我另一个想法。将 Geopandas 数据帧转换为 SVG。
尝试 3: Python + GeoPandas(导出到 SVG)
在使用 LeafletJS 失败后,我带着另一个想法回到了 GeoPandas。将 GeoPandas 导出为 SVG,然后对其应用渐变。我最初的想法是从传单生成的地图添加梯度,但并不需要。
我将博客中的代码添加到我的第一次尝试的代码中,并修改它以满足我的需要。
# SOURCE: http://kuanbutts.com/2018/08/30/geodataframe-to-svg/
def process_to_svg_group(row,dis=False):
orig_svg = row.geometry.svg()
doc = minidom.parseString(orig_svg)
paths = doc.getElementsByTagName('path')
pathssvg = []
country_code = row['ISO_A2'].lower()
if row['NAME'] == 'France':
country_code = 'fr'
if row['NAME'] == 'Norway':
country_code = 'no'
for path in paths:
path.setAttribute('fill', 'url(#%s)'%(country_code))
path.setAttribute('stroke-width','0.1')
path.setAttribute('stroke','#000000')
path.setAttribute('opacity','1')
path.setAttribute('transform','scale(10,-10)')
pathssvg.append(path.toxml())
return ''.join(pathssvg)
processed_rows = []
def_rows = []
res_symdiff = gpd.overlay(gismap, dismap, how='difference')
for index,row in res_symdiff.iterrows():
country_data=[]
dominant_pixels = []
stops = []
country_code = row['ISO_A2'].lower()
if row['NAME'] == 'France':
country_code = 'fr'
if row['NAME'] == 'Norway':
country_code = 'no'
try:
flag_image = Image.open(FLAGS_DIR+country_code+".png")
except FileNotFoundError:
continue
flag_image = flag_image.convert("RGB")
# SOURCE: https://stackoverflow.com/a/52879133/4698800
pixels = flag_image.getcolors(flag_image.width * flag_image.height)
sorted_pixels = sorted(pixels, key=lambda t: t[0])
for pixel in sorted_pixels:
if pixel[0]*100/(flag_image.width * flag_image.height) > 1:
dominant_pixels.append(pixel)
print(dominant_pixels)
sum = 0
for x in dominant_pixels:
sum += x[0]
print(sum)
for pixel in dominant_pixels:
percentage = pixel[0]*100/sum
print(percentage)
color = "#%02x%02x%02x" % pixel[1]
perc = 0
if len(country_data) > 0:
for x in country_data:
perc += x['percentage']
stops.append('<stop offset="%s%%" stop-color="%s" stop-opacity="1"/><stop offset="%s%%" stop-color="%s" stop-opacity="1"/>'%(perc,color,perc+percentage,color))
country_data.append({"color":color,"percentage":percentage})
grad = '''<defs>
<linearGradient x1="0" x2="0" y1="1" y2="0" id="%s">
%s
</linearGradient>
</defs>
'''%(country_code,''.join(stops))
def_rows.append(grad)
p = process_to_svg_group(row)
processed_rows.append(p)
props = {
'version': '1.1',
'baseProfile': 'full',
'width': '100%',
'height': '100%',
'viewBox': '{}'.format(','.join(map(str, gismap.total_bounds))),
'xmlns': 'http://www.w3.org/2000/svg',
'xmlns:ev': 'http://www.w3.org/2001/xml-events',
'xmlns:xlink': 'http://www.w3.org/1999/xlink'
}
template = '{key:s}="{val:s}"'
attrs = ' '.join([template.format(key=key, val=props[key]) for key in props])
raw_svg_str = textwrap.dedent(r'''
<?xml version="1.0" encoding="utf-8" ?>
<svg {attrs:s}>
<g>{data:s}</g>
{grads:s}
</svg>
''').format(attrs=attrs, data=''.join(processed_rows),grads=''.join(def_rows)).strip()
with open('out/map.svg', 'w') as f:
f.write(raw_svg_str)
这能够产生地图
高质量地图
https://i.imgur.com/2RD4s6k.png
我用 Inkscape 添加了文本和背景
法国和挪威的奇特案例
在各种网站上分享地图后,许多人询问失踪的法国。我不擅长地理,但我相信我的代码不会漏掉一个国家。所以我做了一些调试和研究,发现我使用的 shapefile 没有存储法国和挪威的 ISOA2 数据。我的代码使用 ISO A2 数据将旗帜文件与地图进行匹配,因此缺少的数据会导致缺少的国家。我硬编码了几个 if 语句来包含国家,上面的代码为此进行了更新。
相关材料
打招呼:insta gram||Github|||脸书||推特 | 网站||博客
flappy Royale——通过 1000 轮练习提高成绩
背景
2013 年 5 月,一款名为 Flappy Bird 的极度病毒式手机游戏发布。这个游戏的前提极其简单——一只鸟拍打着翅膀飞过一个被有缝隙的管道包围的平台。触摸你死亡的任何管道,通过管道之间的缝隙拍打,你的分数增加一分。看似简单,但这个游戏实际上很难——对我来说。
The Original Flappy Bird
我记得我安装了这个游戏,然后在游戏中敲敲打打,却发现自己每次只能清理 1-2 个管道。我会看到其他几十个人清理 15、20、30 根管道,然后想知道我是否对自己的协调能力有极大的挑战。长话短说,经过无数次尝试后,我在同一天结束了愤怒辞职。
快进到 2019 年 7 月。我将在最后一天去中国西安看望我的祖父母,我的飞机将在晚上起飞。我看了一篇文章,提到了一款刚刚发布的新游戏,名为 Flappy Royale。和我 6 年前退出的游戏一样,这次他们加入了流行的皇家扭曲,所以我决定,为什么不再试一次?
Newly Released Flappy Royale
我最初玩 Flappy Bird 时发生的同样的事情在 Flappy Royale 中再次发生。遗憾的是,我每次只能清理 0-2 根管道。唯一的不同是,这一次有 100 名其他的时髦女郎和我一起玩,我也可以看到他们的进步,因为他们的排名很靠前。有了这种知名度后,我现在意识到我实际上并不是最差的 Flappy Bird 玩家,但实际上只是略低于我刚开始玩时的平均水平。现在有了下面的数据证明,我比平均水平略高😁。
查看我们的数据
为了基本了解我的性能如何随着时间的推移而提高,以及 Flappy Royale 的总体性能如何,我记录了 1000 次以上的尝试,清除了管道,并在 excel 中对 100 个同行进行了排名,并用 python 创建了一些简单的分析,希望大多数读者都能理解——
跟踪超过 1000 次尝试后每次尝试清除的管道
使用来自回归分析的数据,我生成了一条 Y = 1.88 + 0.00213X 的线。这意味着在开始时,我的技能水平是平均 1.88 管道清除我所做的每一次尝试。在 1000 次尝试的过程中,我取得了 0.00213 次额外管道清理的微小进步。这看起来很小,但是经过 1000 次的练习,我现在平均每次尝试清除 4 个管道,这是我开始时的两倍。下图显示了这一过程,每个点代表在 1000 次尝试中每次尝试清理的管道数量。回归线是黄色的,代表图表中的公式。
追踪每 1000 次尝试的同行排名
类似于对清除的管道使用回归分析,我对 100 个对等点实现的等级做了同样的事情,数字越小表示等级越好。我最初的平均等级是 56/100,每次尝试下降了 0.02,在 1000 次之后,我现在的平均等级是 37/100。这由线 Y = 55.97 + -0.0193X 表示。我翻转 Y 轴来表示等级值下降作为更好的结果,因此由上升趋势线显示,即使公式显示斜率为负。
Flappy Royale 的其他玩家表现如何?
Flappy Royale incorporated 的一个很棒的功能是一次创建 100 个玩家的回合,并报告你在这 100 个玩家中的表现。通过 1000 轮比赛,我能够收集足够的数据来了解 Flappy Royale 玩家的总体表现。结果是,能够清理 2 个管道使你刚好符合平均水平,清理 3 个管道使你接近前 38%,清理 4 个管道使你接近前 27%。我还幸运地清理了 5 个管道,收集了足够多的数据,这使我在清理管道的 87 次中平均排名前 20%。如果你想一直排在前 10 名,你可能想一次清理至少 8 个管道。下面是通过收集的数据表示这些结果的直方图。
Histogram representing the average rank of someone who is able to clear 2 pipes is right in the middle at 50
Histogram representing the average rank of someone who is able to clear 3 pipes is above average at 38
Histogram representing the average rank of someone who is able to clear 4 pipes is near top quartile
Players able to clear 5 pipes on average should be proud of themselves as they are in the top 20% of all players
If you want to be in the top 10% of all players, you will want to clear around 8 pipes on average
为了查看分析的来源,我在下面附上了我的备份—
Excel 文件-
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/bryfeng/personal-projects/blob/master/flappy%20data.xlsx)
分析-
flask:API 开发的捷径
Photo by Chris Ried on Unsplash
世界经历了巨大的转变;从在过程语言中将一段代码分离为函数到库的开发;从 RPC 调用到面向服务架构(SOA)中的 Web 服务规范,如 SOAP 和 REST。
这为 Web APIss 和微服务铺平了道路,在 Web API 和微服务中,提供特定问题解决方案的代码片段被公开(私下或公开),代码可以作为黑盒被 API 消费者访问,他们只需要知道所谓的接口,它定义了特定代码片段的输入和输出。
我们使用谷歌、脸书、推特直接登录许多系统,不需要注册每个特定的网站。感谢这些巨头提供公开可用的 Web APIs 进行授权,这使得开发者的生活以及用户的生活都变得非常轻松。
不要被上面这么多的陈述搞得不知所措。我相信在你读完它之前,你会对 API 有很好的理解。
现在,API 到底是什么?
我一直在说这个缩写 API(应用程序接口)。但是到底是什么呢?简而言之,它只是以这样一种方式公开的一小段代码,任何语言的任何应用程序,无论是 Java、Python 还是 Node.js,都可以简单地发送一个请求,以获得某些特定输入的一些输出。它只是底层应用程序和外部世界之间的接口。
Client and Target Application(Exposed as API) are in different languages, still can communicate
如上所示,客户使用不同的语言,但是他们将 API 称为黑盒,因为底层技术是在. Net 中。尽管如此,他们还是能够交流。所有客户端对特定请求的响应保持不变。可能是 json,也可能是 XML。
现在言归正传,为什么是 python,为什么是 flask?
Python and Flask combination makes API development very easy
在我的工作中,从事与机器学习相关的任务,我必须为一些特定的任务开发后端 API,其中大部分都与图像上传、下载和 GRPC 调用相关,并且要求在短时间内完成。
来自 JAVA 背景,当我接触 python 的时候,我发现做一门编程语言是如此的容易。没有样板代码,有丰富的库和语法(一开始可能会让你生气,但是你会意识到适当的缩进是如何导致开发出漂亮的代码片段的)。所以,这显然是对 python 的喜爱。最重要的是,当谈到机器学习和深度学习时,python 是杀手。
下一个任务是为 python 选择一个定义良好的框架,用于 API 开发。我有两个选择:Django 和 Flask(还有很多其他的选择,但是这两个是在很多支持下使用的)。我做了一些研究,我选择 flask 的原因是它比 Django 更 pythonic 化。所以,我也有这个问题的答案。现在是执行的时候了。因此,有了 Flask,后端在几天内就准备好了,所有的 API 都是作为 REST 调用开发的
那么,现在说得太多了,让我们把手放到装满蟒蛇的瓶子里。我知道这听起来很可怕。但是蟒蛇是无毒的,所以这是。相信我。
注意:期待这篇文章中的大量代码。原因是我不想只显示 hello world 类型的代码。因为很多网站已经这样做了,你不需要再看到一个同样的帖子。
在这里,我希望您对 Flask 和 python 有一个良好的体验,这样您就可以在您的应用程序中使用它们,这些应用程序需要一些常见的功能,比如在读取文件和上传文件后发送 json 响应。所以,系上安全带,开始编码吧。
让我们开发两个 Web-API,一个带有 GET ,一个带有 POST 。
获取 API:
**flask_simplified.py**from flask import json
from flask import Response
from flask_cors import CORS
from flask_api import FlaskAPIAPP = FlaskAPI(__name__)
CORS(APP)@APP.route("/getJsonFromFile/<filename>", methods=['GET'])
def get_json_response(filename): labels_dict = {}
response_dict = {}
try:
with open(filename, 'r') as labels:
labels_dict = json.load(labels) ***response_dict[STATUS] = "true***
***response_dict["labels_mapping"] = labels_dict
js_dump = json.dumps(response_dict)
resp = Response(js_dump,status=200,
mimetype='application/json')*** except FileNotFoundError as err:
response_dict = {'error': 'file not found in server'}
js_dump = json.dumps(response_dict)
resp = Response(js_dump,status=500,
mimetype='application/json') except RuntimeError as err:
response_dict = {'error': 'error occured on server side.
Please try again'}
js_dump = json.dumps(response_dict)
resp = Response(js_dump, status=500,
mimetype='application/json') return respif __name__ == '__main__':
APP.run(host='0.0.0.0', port=5000)
-------------------------------------------------------------------
上面的代码显示了如何使用 flask-API 创建一个简单的 GET 调用。您可能会觉得这里有很多代码。但是相信我。为了写好代码,你应该开始写好代码,并把它作为一种习惯。因此,它拥有你在编写代码时应该考虑的所有元素,比如适当的缩进(这对 python 来说是必要的),遵循 PEP8 python 约定并包括异常。
代码解释:
**APP = FlaskAPI(__name__):**
sends the __name__ to FlaskApi Constructor to instantiate Flask Api object, which will be used accross the application
**CORS(APP):** this might not be required for now but is required in case your client is browser(eg. javascript), then cross origin requests will be allowed by the server else you might get CORS related errors
下一部分解释负责服务请求的实际方法:
**@APP.route("/getJsonFromFile/<filename>", methods=['GET']):** defines the method type and uri to be hit by client for this method**def get_json_response(filename):** filename parameter should be kept same which transports the path parameter to the method parameter and is used accross this method**labels_dict = {}
response_dict = {}:** these are some local dictionaries created. labels_dict contains the key-value pairs in the labelsFile.json.
response_dict creates the actual json which contains either the labels_dict key or error key to be returned along with STATUS; depending on response.**try:
with open(filename, 'r') as labels:
labels_dict = json.load(labels)** Above code opens the file. This json file is loaded as key-value pair in labels_dict***response_dict["*LABELS_MAPPING*"] = labels_dict
js_dump = json.dumps(response_dict)
resp = Response(js_dump,status=200,
mimetype='application/json')*** *This is the most important part of code, which shows the Flask api returning response for the request. Response is the Flask's inbuilt way to sendback data to client.***Then comes Exceptions, which are self Explanatory****if __name__ == '__main__':
APP.run(host='0.0.0.0', port=5000)** When we run application as script, the Flask's inbuilt server starts on port 5000 due to APP.run
Here we instruct APP(which we defined already as Flask's instance), to run the server at 0.0.0.0(localhost/127.0.0.1) which is Flask's inbuilt WSGI server
如何测试我的第一个烧瓶应用程序?
测试起来真的很简单。只需保存代码并运行文件
python3 flask_simplified.py
您将看到类似这样的内容(如果脚本中没有错误) :
Flask Server running on 5000 port
如图所示,正在运行的服务器是 python 内置的 Flask server(APP.run 在 localhost:5000 启动服务器),显然不应该用于生产。必须使用 uwsgi 或 gunicorn 或任何其他 wsgi 生产服务器。我将有一篇单独的文章,介绍什么是 WSGI,以及如何在 uwsgi 应用服务器和 nginx 上安装和部署您的应用程序,并将其作为 web 服务器,以使其可以投入生产。
让我们使用下面的 cURL 命令对此进行测试:
curl localhost:5000/getJsonFromFile/labelsFile.json
其中 labelFile.json 内容可以是文件中的键值对,如下所示:
{"ironman":"1",
"deadpool":"2",
"thor":"3",
"captainAmerica":"4",
"angryYoungMan":"5",
"blackPanther":"6",
"Wolverine":"7",
"thanos":"snapItAll"
}"""don't mind; keeping ironman at 1 , fan detected. ;)"""
根据您提供的文件名,您应该会看到响应或异常。
Response:
{"LABELS_MAPPING": {"Wolverine": "7", "angryYoungMan": "5", "blackPanther": "6", "captainAmerica": "4", "deadpool": "2", "ironman": "1", "thanos": "snapItAll", "thor": "3"}, "STATUS": "true"}
发布 API:
对于 post 请求,可以使用 request.form[‘form_data’]从请求中提取 JSON 主体,并且应该提供 yes,methods = "POST "
如果我们用 post 请求来做一些事情,那将会更有趣,这在现实生活中更常用:上传图片到服务器
让我们上传一些图片到服务器(现在你有一些有趣的事情要做了)😃
在这一部分中,我将解释使用 upload 方法的 POST 调用,在这种方法中,文件可以随请求一起发送,并可以保存在服务器中。
**UPLOADING FILES:**
@APP.route("/uploadFiles", methods=['POST'])def upload_file():
"""uploads file to the server. This will save files to the
directory where server is running""" response_dict = {}
error_files = ""
new_filename = "" try:
new_filename = request.form['FILE_NAME']
**recieved_files = request.files.getlist(FILES_RECEIVED_LIST)**
for each_file in recieved_files:
each_file_name = each_file.filename
try:
**each_file.save(os.path.join(".", new_filename +
each_file.filename.replace(" ", "")))**
except RuntimeError as err:
print("\nError in saving file: %s :: %s",
each_file.filename, err)
error_files = error_files + "," + each_file.filename response_dict[STATUS] = "true"
response_dict[ERROR_FILES_LIST] = error_files
js_dump = json.dumps(response_dict)
resp = Response(js_dump, status=200,
mimetype='application/json') except RuntimeError as err:
response_dict = {'error': 'error occured on server side.
Please try again'}
js_dump = json.dumps(response_dict)
resp = Response(js_dump, status=500,
mimetype='application/json')
return resp
代码解释:
**new_filename = request.form['FILE_NAME']** FILE_NAME contains the filename in the request.(see the cURL request below) **recieved_files = request.files.getlist(FILES_RECEIVED_LIST)** FILES_RECEIVED_LIST contains the files in the request. (see the cURL request below) **for each_file in recieved_files:
each_file_name = each_file.filename** iterate through all the files recieved to save one by one try:
**each_file.save(os.path.join(".", new_filename +
each_file.filename.replace(" ", "")))** all files are saved to the path given by os.path(. will save in location where server is running ; you could give some absolute or relative path here. I am appending new_filename to each_file.filename where each_file.filename is actual name of file. You could replace the each_file.filename with new_filename) except RuntimeError as err:
**error_files = error_files + "," + each_file.filename** in case file is not saved, the error_files will contain all the filenames which are not saved which will be sent back to the client in json response**response_dict[ERROR_FILES_LIST] = error_files** contains ERROR_FILES_LIST key in json response which contains all the error files names seperated by ","
***Rest of the code is self explanatory***
这可以使用以下 cURL 请求来触发:
***curl -F "FILES_LIST=@./file1.jpg" -F "FILES_LIST=@./file2.jpg" -F "FILE_NAME=new_file" localhost:5000/uploadFiles***where file1.jpg and file2.jpg are two files to be uploaded and are present in the directory from where cURL request is triggered
您将看到文件在运行 Flask 服务器脚本的同一位置生成。
我的 GitHub 页面上有完整的代码:
在 GitHub 上创建一个帐户,为 tseth92/flask_simplified 开发做贡献。
github.com](https://github.com/tseth92/flask_simplified)
结论:
在这篇短文中,我试图解释如何使用 Flask 构建 API,使用 GET 请求处理读取 json 文件,使用 POST 请求处理在服务器中上传文件。因此,使用 Flask,在很短的时间内,并且很少花费精力编写一些有纪律的基本代码,您就可以在很短的时间内运行 API,用于在 vision 中短时间上市的应用程序。
下一步:
Docker 和 Containers 已经成为一个时髦的词汇。Docker 开源变得如此流行…
medium.com](https://medium.com/@tusharseth93/is-docker-really-worth-your-time-e86dbdf374d9)
我计划在另一篇关于的文章中进一步解释如何在一个生产就绪的服务器上构建这个应用程序,比如 uwsgi,并在其上运行 nginx
感谢阅读!!。对于任何建议,疑问或讨论,在评论区拍摄。
在 medium 和 GitHub 上关注我,获取即将发布的文章;直到那时,快乐的蟒蛇和好运:)
用于在线机器学习部署的 Flask 和 Heroku
介绍
感谢 Pandas、scikit-learn 和 Matplotlib 等库,使用 Python 中的简单机器学习(ML)算法开始探索数据集和进行一些初步预测相对容易。虽然,为了使这些训练好的模型在现实世界中有用,有必要分享它们,并使它们可以在网上访问,以做好预测的准备。只有这样,机器学习才能被用来造福社会。
我最近一直在使用 yei-Cheng 教授的输血服务中心数据集,我使用随机森林分类器实现了 91.1%的预测准确率。因此,我决定把这个模型放到我的个人网站上。为此,我使用了 Heroku 和 Python 库 Flask。
作为进一步的发展,我还决定使用 Android Studio 为我的个人网站创建一个 Android 应用程序,这样我的 ML 模型也可以在 Android 设备上运行。
瓶
(Source = https://kenya-tech.com/wp-content/uploads/2019/01/flask-python.png)
Flask 是一个用于为 Python 创建 web 应用的 Web 框架。在开发在线 ML 模型的情况下,这可以通过使用三个 python 文件来完成:
- model.py =在这个文件中,ML 模型应该被实现和训练。然后应该使用 Pickle 库保存训练好的模型,以便在网络上使用时用于给出实时预测。
- app.py =在这个文件中 Flask 用于处理我们从 request.py 获得的 POST 请求,然后返回结果。为此,使用 Pickle 库检索训练好的 ML 模型。
- request.py =用于向服务器请求特性并检索结果。
app.py 的一个基本例子可以是:
import numpy as np
from flask import Flask, request, jsonify, render_template
import pickleapp = Flask(__name__)# Code to load ML model@app.route('/')
def home():
return render_template(*“filename.html”*)@app.route('/ml-model', methods=['POST'])
def run_model():
# Code to use the trained model to make real time predictions
return render_template(*“filename.html”, result*)if __name__ == '__main__':
app.run()
如果我们想要添加一些 HTML、CSS 或任何其他类型的内容来改善模型的在线图形,可以通过在我们的 model.py 、 app.py 和 request.py 文件所在的同一个工作目录中创建一个 templates 文件夹来实现。这些文件必须包含在模板文件夹中,因为当调用 app.py 中的render _ template(" filename . html ")时,Flask 将默认只在模板文件夹中查找文件。
仅使用 Flask,我们就可以使用本地服务器在本地机器上运行我们的模型。如果我们想让我们的模型在网络上可用,我们可以将我们的 Flask 应用程序部署到一个在线平台上,比如 Heroku。
赫罗库
(Source = https://pbs.twimg.com/profile_images/689189555765784576/3wgIDj3j.png)
Heroku 是一个云平台,可用于部署网站和其他服务。为了使用 Heroku,有必要在你的机器上安装: Heroku 账号、 Heroku CLI 工具和 git。
依次地,有必要:
- 在我们的 Flask 应用程序所在的目录中创建一个 git 存储库。
- 登录我们的 Heroku 账户。
- 创建一个 Heroku 项目。
- 创建一个 requirements.txt 和 Procfile。
- 将目录中的所有文件添加到存储库中。
- 将应用程序推送到 web 上!
前三个步骤可以通过在命令提示符下依次运行以下命令来实现。
git init
heroku login
heroku create
创建 requirements.txt 文件需要告知 Heroku 运行 Flask 应用程序需要什么库。因此,在 requirements.txt 文件中,我们为每一行写一个所使用的所有库的名称。对于这个应用程序,Procfile 只需要包含一行文本(如下所示)。Procfile 需要让 Heroku 知道我们希望执行什么类型的应用程序。
web: gunicorn app:app
然后,可以通过在命令行中顺序运行以下命令来执行第五步和第六步。
git add .
git commit -m "Committing all the directory files to Heroku"
git push heroku master
heroku open
使用 heroku open 命令应该可以打开已经部署了 Flask 应用程序的网页。或者,通过在线登录我们的 Heroku 帐户,可以找到部署我们模型的链接。访问 Heroku 网站可能特别有用,尤其是在我们的 Flask 应用程序午餐期间出现任何问题的情况下。
结论
这是一个关于如何在线部署你的机器学习模型的简单介绍。如果你想了解更多关于如何使用 Flask 编写 Web 应用程序的信息,这里有一些有用的参考资料[1,2,3]。
我的在线机器学习模型在这里可以找到,我用来设计它的所有代码都可以在我的 GitHub 页面上找到。
联系人
如果你想了解我最新的文章和项目,请在媒体上关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:
文献学
[1]如何使用 Flask 构建 web 应用并部署到云上。萨尔瓦多·维拉隆。访问:https://www . freecodecamp . org/news/how-to-build-a-web-application-using-flask-and-deploy-it-to-the-cloud-3551 c 985 e 492/。
[2]教程:将机器学习模型部署到 web。剑桥火花,亚历山大罗伯逊。访问:https://blog . Cambridge spark . com/deploying-a-machine-learning-model-to-the-web-725688 b 851 c 7。
[3]使用 flask 部署一个机器学习模型。赫曼维亚斯。访问:https://hacker noon . com/deploy-a-machine-learning-model-using-flask-da 580 f 84 e 60 c。
Flask 数据科学应用程序
数据科学家一般在后端工作。构建一个交互式应用程序不是我的强项,但它可以是展示你所能做的工作的一个很好的方式。在这篇文章中,我将讨论一些创建 Flask 应用程序的技巧,这些技巧是我在为我的旅游推荐系统建立网站时学到的。
Photo by Goran Ivos on Unsplash
入门指南
在我们开始考虑美化我们的应用程序之前,你应该把你所有的功能放在一个单独的 py 文件中,而不是放在一个 Jupyter 笔记本中。这一步是必要的,因为 Flask 不能与 Jupyter 通信,但它可以与 py 文件通信。
知识库组织
存储库的组织对于部署到网站非常重要。在进入存储库时,应该有一个与存储库同名的文件夹。这个文件夹里应该是你的应用程序需要的所有东西。例如,一个推荐. py 对我的应用程序是必要的,但一个刮擦. py 不是,因为它只用于收集数据。
该文件夹中需要的另一个文件是 init.py. 这可以是一个空文件,但这允许在导入包时运行代码。最后,您将需要一个 web_app 文件夹。此文件夹将包含运行您的应用程序所需的文件,包括引导静态文件夹和模板文件夹。
travel_destination_recommendation
travel_destination_recommendation
__init__.py
recommend.py
web_app
__init__.py
static
templates
app.py
当您想要运行/测试您的应用程序时,您将在最高目录中的命令行中使用以下代码:
FLASK_APP = travel_destination_recommendation.web_app.app.py
在 app.py 中,您可以通过以下方式导入自定义函数:
from ..recommend import custom_functions
创建烧瓶应用程序
py 文件是我们从 flask 导入的地方。您想要导入一些工具:
- 瓶
- 请求(允许与 Javascript 通信)
- render_template(从 HTML 创建模板)
- jsonify(所有内容都需要以 JSON 格式返回)
from flask import Flask, request, render_template, jsonifyapp = Flask(__name__, static_url_path="")
你的应用需要有一些东西来展示。这是你的第一个函数。任何与 HTML 通信的函数都以 decorator @app.route(‘/’)开始。括号内是我们想要与之交互的 HTML 的标签。/本身代表主页。
[@app](http://twitter.com/app).route('/')
def index():
"""Return the main page."""
return render_template('theme.html')
我建议,尤其是对于第一个应用程序,开始时不要做任何设计。我从这个函数开始。它从文本框中获取文本并返回一个预测。
with open('model.pkl', 'rb') as f:
model = model.load(f)@app.route('/predict', methods=['GET','POST'])
def predict():
"""Return a random prediction."""
data = request.json
prediction = model.predict_proba([data['user_input']]) return jsonify({'probability': prediction[0][1]})
连接到 HTML
上面的这段代码连接到下面的 HTML,它创建了一个文本框和一个标记为“预测”的按钮
<html>
<head>
<title>Predict</title>
<script type="text/javascript" src="brython.js"></script>
<script type="text/javascript" src="brython_stdlib.js"></script>
</head>
<body onload="brython(1)">
<script type="text/python3">
from browser import document, ajax
import json
import warnings
def show_results(response):
if response.status==200:
document["result"].html = response.text
else:
warnings.warn(response.text)
def get_prediction(ev):
"""Get the predicted probability."""
req = ajax.ajax()
req.bind('complete', show_results)
req.open('POST', '/predict', True)
req.set_header('content-type','application/json')
data = json.dumps({'user_input': document['user_input'].value})
req.send(data)
document["predict_button"].bind("click", get_prediction)
</script>
<textarea id="user_input"></textarea>
<button id="predict_button">Predict!</button>
<div id="result"></div>
</body>
</html>
这是相当多的代码。我们来分解一下。我们要确保做的第一件事是将脚本设置为 brython。Brython 代表浏览器 python,允许在 Javascript 环境中使用 python。在脚本和正文中都设置这个。
我们希望我们的代码在脚本的主体中。我们需要两个独立的函数来收集数据和显示结果。在 show_result s 中,我们只想要一个结果,如果存在的话。在 if 语句中,我们引用 HTML 文档的 div id*“result”*,因为这是我们希望显示结果的地方。
在get _ prediction中,我们有参数 ev 表示事件。这意味着该函数将在特定事件发生时被调用(我们稍后将回到这一点)。
req.bind('complete ',show_results) 行将该函数连接到 show_results 函数。
下一行 req.open('POST ‘,’/predict ',True) 通过装饰器将这个函数连接到我们在 app.py 文件中创建的函数。
数据是我们可以传递给 app.py 文件的内容。注意,结果应该被转储为 JSON 格式。这一行有两个“用户输入”。字典中的那个是键,它在 app.py 函数中作为数据的一部分被引用。该数据通过 req.send(data) 线发送至 app.py 函数。文档[“user_input”]是文本框的 id。
既然函数已经完成,我们需要一个触发函数的事件。我们希望在点击预测按钮时进行预测。脚本中的最后一行用特定的 id 连接按钮,并将“click”绑定到函数 get_prediction。
结论
这是一个非常基础的 Flask app。随着时间的推移,通过小的改变,我们可以创建一个漂亮的应用程序。作为一名数据科学家,你不需要成为 web 开发的大师,但它可以成为一个有趣的工具来展示你的模型可以做什么。
感谢我的教练为我的烧瓶起点,检查他的垃圾邮件预测在这里。要查看一个详细的 Flask 应用程序,看看我的库。
花卉种类分类器
建立一个图像分类器来识别 102 种不同的花卉
人工智能深度学习卷积神经网络
Python py torch Numpy Matplotlib Jupyter 笔记本
Photo by John-Mark Smith on Unsplash
在这篇文章中,我概述了我开发的项目,该项目使我获得了 Udacity 深度学习纳米学位项目的奖学金。
My Badge of Approval
背景
我开发这个项目是作为由 Udacity 和脸书举办的 PyTorch 奖学金挑战评估的最终测试。
See the original announcement in this link
在这两个月的挑战中,我第一次接触了人工智能开发。除了观看视频和完成课堂上的评估,我还加入了一个私人 Slack 社区。因此,我可以与项目中的同行和教练联系,分享我的进步,获得反馈,提出问题,并帮助其他学者完成挑战。
挑战
构建深度学习模型,从图像中识别 102 种花卉。
最终应用程序接收用户提供的图像,并预测成为这些已知物种之一的可能性。
发展
加载数据
在此链接中找到的图像数据集包含了 7370 张在不同角度和光照下拍摄的花朵照片。
下面可以看到几个例子。
设置图像子集
我将图像随机分为三组:
Training : 6552 images / 205 batches
Validation: 409 images / 18 batches
Testing : 409 images / 18 batches
数据扩充
对于这个项目,我选择对训练集使用图像归一化和数据增强。
作为第一步,我在每个图像中随机选择四个变换中的一个,给定被选择的概率:
• 16,67% — Horizontal flip
• 16,67% — Vertical flip
• 33,33% — Random rotation, in a range of 360 degrees
• 33,33% — Keep the image untouched
在那之后,我在图像中进行了随机裁剪,并将它们的尺寸调整为 224x224 像素。
对于测试和验证集,我只调整了图像的大小,并对每张图像进行了 224x224 像素的中心裁剪。
构建分类器
为了检测图像中的特征,我使用了一个预先训练好的网络,可以在包 torchvision.models 中找到。经过在 ImageNet 数据集上的训练,这些模型可以识别图像中的大量特征。然而,在它们的最后部分附加的分类器将图像分类到除了包含在数据集中的花卉种类之外的类别中。
于是,瞄准最终目标,我选择了 ResNet-152 型号。我保留了它预先训练好的卷积层,并替换了它的分类器,建立了一个新的网络来将图像分类到新的类别中。
Representation of a ResNet with 34 layers
我的全新分类器是一个全连接的网络,包含一个 2048 节点的输入层、一个 1000 节点的隐藏层和一个输出层,用于将输入数据分类为 102 个类别。
一旦我建立了我的模型,是时候训练它了!
训练网络
在测试了许多优化器之后,我选择了 Adagrad。这是一个非常强大的优化下降训练损失非常快。然而,有必要对这种能力进行一些控制。否则,这种强度可能会转化为爆炸梯度,而不是收敛到最佳解决方案。为此,我引入了一个学习率调度器,我将在下一节详细介绍它。
Comparison of different optimizers
我将网络培训过程分为三个阶段,如下所述。
培训阶段 1:
这里的重点是训练分类器。
由于卷积层已经过预先训练,它们能够识别图像中各种各样的特征。所以,我冻结了他们的参数,禁止他们更新。因此,所有的努力都是为了调整分类器的权重。
为了限制 Adagrad 能力,我引入了一个调度器,以便在误差函数达到平稳状态时降低学习速率。学习率从 0.01 开始,在平稳期减少 0.1。一旦学习率低于 0.0001,这个阶段就被中断。
在这个训练阶段,执行了 39 个时期,在验证数据集中提供了 94.62%的准确度。
Epoch: 39: lr: 0.00010000 Training Loss: 0.412109
Validation Loss: 0.232272 Validation accuracy: 94.62%
训练第二阶段:
由于分类器已经知道要做什么,是时候微调卷积层的权重了!
为此,我解冻了所有网络参数,将学习率设置为 0.0001,并对整个模型进行了 20 个时期的训练。
在这个训练阶段结束时,验证准确率为 96.58%。
Epoch: 59: lr: 0.00010000 Training Loss: 0.201783
Validation Loss: 0.141651 Validation accuracy: 96.58%
训练第三阶段:
在这一点上,即使我已经获得了一个很好的结果,我决定推进我的网络的极限!
我将学习率降低到 0.000001,只是对分类器权重进行一些小的调整,并运行其他 10 个时期的训练。
然后,验证准确率达到了令人印象深刻的 97.07%。
Epoch: 69: lr: 0.00000100 Training Loss: 0.187415
Validation Loss: 0.142964 Validation accuracy: 97.07%
Parameters evolution within the whole training process
最终测试
在这一点上,网络在识别训练和验证图像方面足够准确,并以超人的准确性对它们进行分类。
该网络的最终测试是查看一个完全未知的数据集,以正确分类图像。
我想象不出比这更好的结果了!该网络以 99.27%的惊人准确率执行了这项任务,在 409 幅图像中只漏掉了 3 幅!
The network missed only 3 of 409 images
结果
作为最终结果,该网络接收一幅图像作为输入,并对该花的五个最可能的物种进行预测。
这个项目的一个实际应用例子是一个手机应用程序,它显示相机拍摄的花的名称。
您可以在下面看到一些输出示例。
请注意,网络不仅预测正确的类别,而且对此非常确定。
这个项目的所有代码都可以在我的 GitHub 配置文件中找到:
[## Silvio mori/uda city-深度学习-py torch-挑战-实验室
PyTorch 挑战实验室的代码存储库
github.com](https://github.com/silviomori/udacity-deeplearning-pytorch-challenge-lab)
深度学习中的流动张量和堆积参数
可训练参数计数的公式是作为层参数和输入特征的函数为几个流行层开发的。然后将结果与运行模型时 Keras 报告的结果进行核对……
深度学习模型是参数快乐的。可以肯定地说,他们从未遇到过他们不喜欢的参数!采用数百万个参数的模型太常见了,有些甚至达到数十亿个。感谢低级库,如 TensorFlow、PyTorch 等……对于繁重的工作,感谢高级库,如 Keras,对于易用性,现在很容易快速构建这样的模型。但是,了解这些参数是如何从基础知识中产生的,对于超越深度学习的黑箱方法非常重要。这就是这篇文章的目的——也许可以帮助某人回答一两个深度学习工程师角色的面试问题!
运行 Keras 的最有用的输出是进入/离开每一层的数据/张量的形状以及该层中可训练参数的计数。对于深度学习的常规实践者来说,这些信息可以快速确认 Keras 正在运行他们为其编程的内容。但对于那些刚接触深度学习的人来说,可能不会立即清楚这些是如何发生的。在这里,我们看看一些流行的层的内部工作,不太深,但足以得出参数的数量作为层参数的函数。我们调和了喀拉斯告诉我们的东西。这里有一个简要的概述。
- 选择一些常见的层,如密集层、嵌入层、RNN 层(LSTM/GRU)和卷积层(Conv1D/Conv2D)等。由于篇幅原因,我们将在本系列的下一篇文章中讨论卷积层。
- 对于每一层,开发可训练参数数量的公式,作为层特定细节的函数,如单元数量、过滤器及其大小、填充等…以及输入细节,如特征数量、通道等。我们进一步获得离开层的数据/张量的预期形状
- 运行 Keras 指南中描述的视频问答模型,并确认我们的公式/分析对于可训练参数和输出形状是正确的。
这里显示的片段的完整代码可以照常从 github 下载。
1.层次丰富
深度学习模型是一个连接层的网络,每一层都接受一个输入数据张量,并生成一个潜在不同形状的输出数据张量。每一层都使用大量的参数来完成它的工作,增加了模型中参数的总数。数据/张量在网络中从输入端到输出端流动,同时在流动过程中进行形状和内容的转换。在训练阶段,通过比较获得的和预期的输出来估计模型参数,然后反向驱动误差来更新这些参数,以便它们在下一批输入中做得更好。这是坚果壳中的深度学习——只是十亿维空间中的大规模优化练习!
Keras 为实例化各种层并连接它们以构建深度学习模型提供了高级 API。所有的计算都发生在这些层中。流行的层包括“面包和黄油”密集层,“图像快乐”卷积层,“序列尊重”递归层及其许多变体。有一些功能层,如池,不增加新的参数,但改变了传入张量的形状。存在不修改形状但添加新参数的归一化层。像 dropout 这样的层既不会添加新参数,也不会修改形状。你明白了——这是有原因的!此外,我们还可以编写自定义层。出于我们的目的,我们只关注几个流行的层。首先是一些定义和符号。
一个张量仅仅是一个多维数字矩阵,具有任意形状,如[n_1,n_2,n_3,…n_m]。一个向量是一个数字列表,因此像【n_1】一样有一个维度。显然,矢量是一维张量。然而,我们选择将向量写成[n_1,1],以强调它只是一个具有一列的矩阵,并且看到所有的点和哈达玛乘积都清晰地计算出来。
2.致密层
密集层是简单前馈网络的构造块。每个输入都连接到层中的每个单元,并且每个这样的连接都有一个关联的权重。另外每个单元都有一个偏差(如果 use_bias=True 在 Keras 中,默认)。下面的等式 1 描述了密集层的作用。基于可选择的激活函数 f,它简单地将输入向量 x 转换为输出向量 y 。
Equation 1. The weight matrix and the biases are the parameters in a Dense layer
例如,以下模型将具有通过运行模型验证的 32 * (784 +1) = 25120 可训练参数。
运行它,我们得到下面的输出和数据流图。
Layer (type) Output Shape Param #
=================================================================
Dense_Layer (Dense) (None, 32) **25120**
=================================================================
Total params: 25,120
Trainable params: 25,120
Non-trainable params: 0
Figure 1. Flow of a data tensor through a dense layer.
3.嵌入层
嵌入层几乎与密集层相同,但讨论起来非常重要,因为它们广泛用于准备文本输入。
一个嵌入层是一个密集层,没有偏置参数和身份作为激活函数。事实上,该层所做的只是矩阵乘法,其中矩阵条目是在训练期间学习的
在文本处理中使用嵌入层来提出单词的数字矢量表示。从 0 (或 1 ,如果 0 用于填充/屏蔽以允许可变长度的句子)到 nWords (或 nWords+1 ,如果 0 用于屏蔽),组成文本语料库的单词被分配整数索引。输入的句子/文本最多有个长度为的单词。每个字是一个 1-hot 编码向量。权重矩阵将长的 1-hot 编码向量转换成短的密集数值向量。换句话说,权重矩阵就是长度为 nUnits 的列的单词向量。
Equation 2. Embedding layer simply converts a long, sparse vector to a short, dense vector
以下嵌入层的代码片段将把 1024 * 256 = 262144 可训练参数添加到与下面的 Keras 报告相匹配的模型中。
运行我们得到的:
Layer (type) Output Shape Param #
=================================================================
Embedding_Layer (Embedding) (None, 25, 256) **262144**
=================================================================
Total params: 262,144
Trainable params: 262,144
Non-trainable params: 0
Figure 2. Each word in a 25 word (each a 1-hot vector) sequence gets converted to a 256 long numerical vector after passing through the Embedding Layer
4.循环层
递归图层适用于顺序非常重要的数据。例如,单词的顺序对于句子的意思及其分类是很重要的。并且图像帧的序列对于分类视频中的动作是重要的。
递归层的输入是固定长度的向量序列,每个向量代表该序列中的一个元素。当处理文本时,序列的元素是单词,并且每个单词通过嵌入层或外部提供的例如 FastText 表示为数字向量。还可以设想从视频中提供图像帧序列,其中每一帧首先通过卷积转换成矢量。
递归层将这个输入向量序列转换成一个输出向量,其大小等于该层中使用的单元数。在其众多变体中,LSTM 和 GRU 是最流行的递归层实现,我们在这里重点讨论它们。
4.1 LSTM
我们参考 Colah 的博客来了解定义发生在 LSTM 层的变换的方程式。下面的图 3 描述了 LSTM 细胞对输入的作用。
Figure 3. An LSTM cell uses four dense layers each contributing equal number of parameters to the model.
一个 LSTM 电池包含四个致密层(三个具有s 形激活,一个具有 tanh 激活),全部采用与 LSTM 电池相同数量的指定单元。如图 3 所示,这些密集层中的每一层都接受相同的输入,该输入是先前隐藏状态 h_(t-1) 和当前输入序列 x_t 的串联。但是他们都有自己的一套在训练中学习到的权重和偏好。因此每个都将向 LSTM 层贡献相同数量的可训练参数。以下等式描述了 LSTM 单元中输入的变换。
Equation 3. An LSTM cell has three dense layers with sigmoid activation and one with tanh activation, They all employ the same number of units and take the same input at each timestep.
以下代码片段发送的句子长度最多为 25 个单词,总词汇量为 1000 个单词。嵌入层将每个单词转换成一个 256 长的数字向量,产生一个[None,25,256]的输入到具有 128 个单元的 LSTM 层。我们的公式表明,LSTM 单元将贡献 4 * 128 * (128 + 256 +1) = 197120 个可训练参数。
运行上面的代码,我们看到我们的公式获得的参数 count 与 Keras 获得的相匹配。
Layer (type) Output Shape Param #
=================================================================
Embedding_Layer (Embedding) (None, 25, 256) 256000
_________________________________________________________________
LSTM_Layer (LSTM) (None, 128) **197120**
=================================================================
Total params: 453,120
Trainable params: 453,120
Non-trainable params: 0
Figure 4. Flow of word sequences through an Embedding and LSTM layers
4.2 GRU
在详细讨论了 LSTM 单元之后,我们可以轻松地讨论 GRU 单元,因为它们的想法是相似的。我们只需要这个图像就可以确定它给模型添加了多少参数。
Figure 5. The GRU cell has two dense layers with sigmoid activation and one with tanh. They all employ the same number of units and take the same-sized input at each timestep.
tanh 密集层与其他两个 sigmoid 密集层具有不同的输入。但是输入的形状和大小是相同的,这导致了上面的公式。如果我们像以前一样运行同样的代码,用 GRU 代替 LSTM,如下所示:
我们应该从下面的 Keras 中得到 3 * 128 * (128 + 256 + 1) = 147840 个与模型摘要相匹配的参数。
________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
Embedding_Layer (Embedding) (None, 25, 256) 256000
_________________________________________________________________
GRU_Layer (GRU) (None, 128) **147840**
=================================================================
Total params: 403,840
Trainable params: 403,840
Non-trainable params: 0
Figure 6. Flow of word sequences through an Embedding and GRU layers
5.摘要
我们开发了 Keras 中密集层、嵌入层、LSTM 层和 GRU 层中使用的参数数量公式。我们已经看到了为什么输入/输出张量形状对这些层的预期作用有意义。这是一个汇总表。
Table 1. Input/Output shapes and parameter counts for various layers
我们就此结束这篇相当短的帖子。我们将在本系列的下一篇文章中讨论卷积和一个综合的例子。
原载于 2019 年 6 月 6 日http://xplordat.com。
又失败了!浅谈叶
当你想到可视化的时候,有很多很多好的选择:当你蹦蹦跳跳的时候有条形图,当你大脑分散的时候有散点图,当你只想发泄情绪的时候有直方图,当然,还有甜点的饼状图。不过,今天我要说的是一个有用的图书馆,叫做“叶”,它使用起来特别有趣,因为它通过地图将所有信息融入你周围的真实世界。
例如,假设我有一个我附近所有比萨饼店的纬度和经度列表,但是我想更具体地了解这些数字的实际含义。我可以将这些列表输入到 leav 中,轻松地在地图上标出每个点。
不错!现在我清楚地知道在我附近哪里可以找到比萨饼店。但是假设我不只是想知道他们的位置,也许我还想知道每个人的一些信息。通过电脑魔术,这是很容易做到的!leav 使我们能够在每个点放置弹出信息,因此您可以在那里存储相关信息,等待被点击!
我今天想吃五星级披萨吗?大概吧。我今天想花大价钱买五星级披萨吗?大概不会,所以有这个功能让我提前知道就好了。
对你们很多人来说,这是一个非常熟悉的图像。你可以打开谷歌地图,只需打个响指就能看到这样的图像(或者,如果你反应快的话,可以质疑你所有的生活选择:P)。所以现在我给你看一些你在谷歌上看不到的东西。假设我们不再想知道最近的比萨饼店在哪里,假设我们想知道城镇某一地区的星巴克密度,而不是其他地区。
正如你所看到的,星巴克的“热点”在市中心,这是有道理的,因为客流量非常大。当你走得更远时,步行交通变得不那么常见,建筑物之间的距离也更远,所以星巴克的密度会降低。当你有太多的点需要单独查看时,叶子热图很有用,这让你可以看到点之间的关系,而不会因为无数的标记而使图像陷入困境。相当甜蜜!
到目前为止,我们一直使用默认的地图背景,但没有更多!follow 有很多可定制性。也许你已经厌倦了看到道路和城市,也许更少的信息对你的特定图形来说更重要,也许你正在重现拉里·哈里斯设计的经典棋盘游戏:轴心国和盟国,但规模更大。说你想要白纸黑字,为什么不呢?你的愿望就是叶的命令!
或者你已经喝完了所有你能喝的咖啡,吃了超出人类可能的比萨饼,你决定离开这个城市去一座休眠火山顶上寻找孤独。给你更多的力量!叶有一个地形选项,所以你可以通过一个更地理的镜头来看事情。看起来你还有一段路要走。一定要穿有脚踝支撑的鞋子!
当我们的朋友出发去寻找山里的空气、水泡和内心的平静时,我注意到我们地图上的标记开始变得有点乏味。您可能会猜测,leav 提供了可定制的标记,如果您猜到了这一点,那么您就对了!让我们来看看。
有很多不同的颜色和图标可供选择,还有更多可以在网上找到,比如 Font Awesome!
世界上最受欢迎和最容易使用的图标集刚刚得到了升级。更多图标。更多款式。更多选择。
fontawesome.com](https://fontawesome.com/?from=io)
叶子不仅仅有标记。也许你想看看每个点周围的大致区域。对于显示半径来说,一个很好的选择是圆形选项,这样您可以感受到哪些地方可能共享一个配送范围或类似的东西。
如您所见,leav 有许多非常好的优势。许多可用的定制:不同的地图风格和标记,不同的图标和颜色,它也很容易使用。我非常喜欢 clear,因为它有助于以一种清晰易懂的方式直观地分解位置信息。想象一下使用散点图或条形图来理解相同的信息,你可以做到,但在我看来这样更好。希望这能给你一些关于如何在你自己的项目中使用 follow 的想法。好了,我快没时间了,完全没有双关语了,所以现在就这样吧!
跟随和学习:用 Python 实验大小
Photo by Crissy Jarvis on Unsplash
你想改变你的网站布局,以获得更多的点击。你决定运行一个实验,让一个控制组看到通常的页面,然后一个实验组看到一个新的布局。
假设你当前的网站点击率(CTR)是 p_null=10%,我们想把这个值提高到 p_alt=12%。我们需要多少访问者来评估我们的结果?为了达到一个可靠的水平,你需要进行多长时间的实验?是 10 天还是 10 年?
实际意义不仅有助于在实验结束时做出决定,也有助于设定实验范围。假设我们假设的幂 𝛽 为 80%, p 值为 0.05,分别指第二类和第一类误差。
在本帖中,我们将首先使用模拟来探索这个概念,以建立直觉,然后使用分析方法。请随意查看 jupyter 笔记本了解更多信息。
模拟方法
在第一种方法中,我们依靠蛮力,通过多种样本大小。每个样本大小都有一个相关的功率水平,通过足够的模拟,我们可以缩小所需的最小样本大小。
第一类错误
在零假设下,我们将有一个临界值,对于这个临界值,I 型误差低于我们期望的水平。
- 计算两组在零假设下的比例差异的标准差,其中成功概率为 p_null (10%)。差异分布的方差是各个分布的方差之和。
- 使用 scipy.stats.norm 创建一个正常的连续变量,以 0 为中心,并使用上一步中的标准偏差进行缩放。
- 使用 scipy 上的百分点函数方法计算导致我们拒绝空值的分布临界值。
第二类错误
功效是在替代假设下分布的比例,它超过了我们以前获得的临界值。
- 计算所需可检测差异下的标准偏差差异(此处为 12%)。各个分布会有不同的方差:一个是零(10%),一个是备选项(12%)。
- 像上一部分一样,创建一个正常的连续变量,以(p_alt-p_null)为中心,并按上一步中的标准偏差进行缩放。
- 使用概率密度函数计算 II 型错误的概率。
Python 脚本
将所有这些放在 python 代码中,我们得到了下面的脚本。
通过迭代,我们发现,对于 80%的幂 𝛽 ,样本大小约为 2863。下图显示了零假设和测试假设下的分布。
分析方法
我们就拿上面的情节来注解一下我们实际看到的。
用于确定统计显著性的临界值 p *落在 p_null 和 p_alt 之间。因此,从 p_null 到 p_alt 的距离可以细分为两部分:
- 从 p_null 到 p*的距离
- 从 p_alt 到 p*的距离
我们可以用单尾测试的 z 值来表示这些距离。
对于从 p_null 到 p*的距离:
对于从 p *到 p_alt 的距离:
将两者相加,我们得到:
标准误差 SE 可以表示为:
其中:
- n =观察次数
- s_null =两组在零假设下比例差异的标准偏差
- s_alt =所需可检测差异下的标准偏差差异(此处为 12%)
代入并求解 n,观察值的数量由下式给出:
Python 脚本
用 python 代码实现上述功能,我们得到了下面的函数。请注意,我们在最后对样本量进行了四舍五入。
我们获得了与模拟方法相同的样本大小 2863!
统计模型
或者,我们可以使用免费的 python 包,如 StatsModel ,它假设一个双尾测试,并使用 Cohen 的 h 作为两个概率之间的距离度量。下面的代码简洁且易于实现。
我们获得了一个比前一种方法更大的样本量:3021。
结论
我们可以使用模拟、严格分析和专门的软件包来估计样本大小。网上有多个样本量计算器,我们可以用它们来获得类似的结果。
最后,所有的方法都应该给出我们可能需要多少观测值的一个很好的大概估计。这将会给我们一个实验的范围,我们需要多少时间,是否值得。
记住最终目标:建立一个切实可行的实验。
本文基于 Udacity 数据科学家纳米学位 所需的一个练习。我建议报名参加该课程,以便更深入地理解这里显示的主题。另外,可以随意查看 统计意义 上的这篇帖子。
跟随和学习:Python 的统计意义
Photo by dylan nolte on Unsplash
如果你使用互联网,你很有可能在不知情的情况下参与了某人的统计实验。它通常是一个微妙的变化,如页面的颜色、按钮的形状或一些额外的文本。
Google Analytics 为其客户提供以测试为中心的服务,以优化网络流量。在这篇文章中,我们想探索如何从玩具数据集中得出统计意义。
建议在进入本帖之前熟悉实验设计、二项分布和 p 值。请随意浏览笔记本了解更多信息。
数据
假设我们想要增加点击下载按钮的用户数量。看看下面的数据表:
条件列取两个值:
- 对照组为 0
- 1 个用于实验组
点击列也取两个值:
- 0 表示不下载
- 1 个用于下载
不变度量
这里的条件是我们的不变度量,我们希望测试组和对照组在理想情况下是不可区分的。如果这个条件不成立,那么我们就不能把我们的研究建立在可靠的信息上:我们想在两个几乎相同的组中测试一个类似的事件。
模拟方法
我们可以通过随机的 50/50 分割来模拟组的分配。这是如何做到的:
- 记录对照组/实验组的参与者人数
- 对该组执行伯努利试验
- 将结果与原始分布进行比较
- 报告异常值的比例
下面的代码块显示了我们可以模拟 n 次随机抽取并记录异常情况。
该脚本返回 0.613,表明两组之间的差异在统计上不显著。我们关于两组相同的假设是正确的。
分析方法
二项式分布的标准差由下式给出:
- n=样本量
- p =成功的概率
- q =故障概率= (1-p)
z 得分是标准偏差的度量,例如,z 得分为 2 表示我们距离平均值有 2 个标准偏差。在我们的例子中,z 分数由下式给出:
- x =对照组的人数
- μ=平均值
- σ =标准偏差
注意,我们需要通过加或减 0.5 对 x 进行连续性校正。一旦我们有了 z 值,我们就可以从 z 得分表中得到分布两边曲线下的面积。
多亏了大样本和中心极限定理,我们才能够完成上述步骤。下面的直方图显示了模拟中样本的分布,有助于我们的主张。
在 python 代码中,我们使用与上一部分相同的变量运行下面的代码块。
成功!我们获得与模拟相同的 p 值!
评估指标
现在我们来看一下评估指标,即点击率(CTR)。我们的测试组和对照组之间的点击量差异显著吗?
我们的零假设是,使用单尾检验,两组的 CTR 是相同的。
首先让我们用下面的代码块记录一些统计数据。
模拟方法
该方法类似于我们为不变度量所做的方法,但有一些变化:
- 对控制组进行伯努利试验,成功概率为 p_null
- 以 p_null 的成功概率对实验组进行伯努利试验
- 记录两次试验平均值的差异
这可以在 Python 中完成,如下所示:
这返回 0.0395 的 p 值<0.05, this means our result is statistically significant and we should reject the null hypothesis. Again the central limit theorem is at work here by looking at the distribution of the differences in means.
Analytical Approach
We need to evaluate the pooled CTR for the analytical solution. To get there we calculate the pooled standard deviation using the formula below.
In python code the process is:
We obtain the same p value as in the simulation approach and again reject the null hypothesis.
Conclusion
Through analytical and simulation approaches, we have reached the same conclusions for the invariant and evaluation metrics respectively.
We can now solve similar problems using either approach! How many observations do we need for our experiment is covered in a post on 实验规模我们使用类似的概念。
追随你对数据科学的热情
以你的兴趣谋生
我们在不同的场合都听说过很多次“追随你的激情”。但是在这篇文章中,我想阐明你如何在数据科学中追寻你的激情。关键就在这里:没有数据科学。无论你更喜欢深入挖掘深度学习、分析金融数据还是浏览网页,你都将在不同程度上以不同形式从事数据科学。如果你想在数据科学领域取得真正的成功,你必须承诺无论面临什么样的挑战,都要追随自己的热情。
Follow your passion and build an amazing career
数据科学最棒的就是激情!
当你对某事充满热情时,它会给你更大的自信和动力。激情有时可以让你摆脱常规,但它也是一个非常强大的工具。对某事的热情让你看到你的数据和你的数据集告诉你的东西。它还可以帮助你从不同的角度解决问题,甚至可以让你成为更好的数据科学家。激情也是为什么有些人永远无法以数据科学家为生,为什么有那么多坏科学家的一大原因。
这是什么意思?如果你对数据科学有热情,那么谋生和获得数据科学成功所需的知识会更容易。众所周知,这个领域对人才的需求越来越大。这就是为什么你应该努力找到你所在领域最好的数据科学工作的原因。
数据科学有许多领域
举几个例子来说,您可以进入许多领域:
- 数据挖掘
- 数据分析
- 数据可视化
- 机器学习
比如数据挖掘,就是一种挖掘数据的方法,可以用在很多领域。它可以用于分析信息和进行预测,以便开发软件、游戏等。它还可以用于识别数据中潜在的错误来源,并找出不同数据组之间的趋势。
此外,这些领域分成更小的领域。例如,您可以专注于图像的数据分析。
图像分析是一种数据分析技术,涉及使用与模式分析相同的技术来识别图像。
企业需要数据科学家
然后,你可以问自己是否有特定的业务领域,你想应用数据科学。这是与你的激情联系的最好方式。找到一个你想涉足的特殊领域——也许是零售业,也许你有金融或健康方面的诀窍。这里的选择是无限的。
作为一名数据科学家,随着职业生涯的进展,您需要不断学习和发展。一份工作必然会给你机会与世界上一些最优秀的人一起工作。你将要从事的一些项目需要大量的专业知识,你需要准备好从别人那里获得帮助。
放心吧!数据科学社区非常受欢迎。
另外,请查看我关于成为数据科学家的其他文章:
我很乐意帮忙!
思考的食粮——纸星期二
用于快速在线更新的新矩阵分解
每周二,我都会强调我在研究或工作中遇到的一篇有趣的论文。希望我的评论能帮助你在 2 分钟内获得论文中最多汁的部分!
基本思想
无数的项目已经证明,自 2006 年 Netflix 奖竞赛以来,矩阵分解(MF)是无与伦比的最强大的推荐生成算法之一。关键思想是将用户-项目交互矩阵分解成两个具有较低等级的子矩阵。
From amazon aws
通过分解交互矩阵,MF 以某种方式提取出潜在的特征,这些特征在描述用户和物品方面表现惊人的好。如果您想了解算法本身的更多信息,可以参考以下资源列表:
- https://data jobs . com/data-science-repo/Recommender-Systems-[网飞]。pdf
- https://www . cs . CMU . edu/~ mgormley/courses/10601-s17/slides/lecture 25-MF . pdf
- https://developers . Google . com/machine-learning/推荐
传统 MF 在实践中的一个问题是,当矩阵变得巨大时(想象亚马逊必须分解其用户-商品交互矩阵,这将是一个数百万乘数百万的矩阵),定期更新潜在特征变得不可行(当用户进行新的购买时,我们希望该交易稍微影响潜在向量)。我看到了贺湘南、张汉旺、Kan Min-Yen 和 Tat-Seng Chua 的一篇论文,名为用于隐式反馈在线推荐的快速矩阵分解。他们提出了一种叫做 eALS 的新方法,这种方法大大加快了在线更新过程。
下面是链接:https://arxiv.org/abs/1708.05024
作者提出了一种通过缓存重复使用的值来加速 ALS 的新方法,以及一种避免每次新更新到来时解决整个问题的新技巧。
from He et al 2017
为了使在线模型更有效地响应最新的输入,作者提出了一种权重策略。
from He et al 2017
from He et al 2017
论文中另一个有趣的提议是他们所谓的面向项目的缺失数据加权,它可以将领域知识整合到算法中。例如,如果一个用户从来没有购买过一个流行的物品,那么这个物品应该比一个未被浏览的稀有物品更像是负面反馈。
from He et al 2017
结果
作者根据经验证明,置信度参数 c(见上图)确实在一定程度上提高了性能。
from He et al 2017
新的相互作用参数 W 的影响(W 越高,意味着新的相互作用的权重越大)
from He et al 2017
最令我兴奋的结果是时间复杂度的显著改善。所提出的新方法比普通的交替最小二乘法快 100+倍,交替最小二乘法是一种众所周知的解决矩阵分解的方法(这是有意义的,因为 ALS 每次需要更新潜在向量时都需要解决整个问题,而 e ALS 仅在附加数据上工作,并且以更高的空间复杂度为代价)。
一些想法
我在暑期实习期间自己开发了一个推荐系统,在线更新让我很头疼。我很高兴这篇论文让我们离模型更近了一步,模型可以很容易地更新,并包含更多的领域知识。
思考的食粮——纸星期二
调和过度参数化与偏差-方差权衡
每周二,我都会强调我在研究或工作中遇到的一篇有趣的论文。希望我的评论能帮助你在 2 分钟内获得论文中最多汁的部分!
基本思想
数据过量可能是任何机器学习课程中最基本的方法之一。这个想法很简单——太适合训练数据(通常有很多参数)的模型在测试集上的表现往往很差。过度拟合通常发生在模型被大量参数化时,如具有太多分裂的决策树或未规范化的回归模型。
Picture from StackOverflow
在这篇文章中,我想强调一篇相当令人兴奋的论文。Mikhai Belkin,Daniel Hsu,马思远和 Soumik Mandal 在他们 2019 年的论文中证明了现代机器学习实践和偏差-方差权衡的调和表明,如果模型足够复杂(他们称之为双下降曲线),测试误差最终会再次下降。
from the paper: Belkin et al 2019
论文网址:【https://arxiv.org/pdf/1812.11118.pdf
结果
研究人员在几个著名的数据集(MNIST,CIFAR10,SVHN)上,在广泛的机器学习模型(神经网络和基于树的模型,RFF)上测试了这一想法,并获得了一致的结果。
from the paper: Belkin et al 2019
from the paper: Belkin et al 2019
from the paper: Belkin et al 2019
一些想法
巧合的是,我正在为我的本科论文研究神经网络的过度参数化,我看到了几篇论文从数学上证明了如何更容易优化更大的网络( Oymak 和 Soltanolkotabi 2019 )。在其他模型中看到类似的现象确实令人兴奋,更重要的是,过度参数化可以改善测试误差。也许这是升级工作站的完美借口,因为拥有一百万棵树的随机森林会给你更好的结果:)