TowardsDataScience 博客中文翻译 2016~2018(二十三)
R 中的高级图像处理
**‘ImageMagick’**是著名的开源库之一,可用于编辑和操作不同类型的图像(光栅&矢量图像)。是一个绑定到“ImageMagick”的 R 包,用于在 R 中进行高级图像处理,作者是耶鲁安·奥姆斯。
magick 支持 png、jpeg、tiff 等多种常见图像格式,以及旋转、缩放、裁剪、修剪、模糊、翻转、注释等操作。
这篇文章旨在帮助你开始使用magick
来处理、编辑和操作 R 中的图像,这些图像可以是从文件格式转换(例如,png 到 jpeg)到注释 R 图形输出的任何内容。
magick
可用在曲柄上,也可用在 ropensci 的 github 上。
#installing magick package from CRAN
install.packages('magick')
#from Github ropensci library - note: requires RTools
devtools::install_github('ropensci/magick')
让我们加载库,用image_read()
从互联网上读取我们的第一张图片
#Loading magick package
library(magick)#reading a png image frink image
frink <- image_read("https://jeroen.github.io/images/frink.png")
#reading a jpg image ex-President Barack Obama from Wikipedia
obama <- image_read('https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/President_Barack_Obama.jpg/800px-President_Barack_Obama.jpg')
确保你已经安装了一个更新版本的curl
包,可以成功读取上面提到的图像。
我们可以通过image_info()
获得读取图像的基本细节
#image details
image_info(obama)
image_info(frink)
image_info(obama)
format width height colorspace filesize
1 JPEG 800 999 sRGB 151770image_info(frink)
format width height colorspace filesize
1 PNG 220 445 sRGB 73494
与 RStudio 通信,magick
允许您在 RStudio 查看器窗格中打印/显示图像。
#displaying the image
print(obama)
无论你是一名网络开发人员,还是正在制作一套幻灯片,图像文件格式转换都是我们最终要做的操作之一,这实际上是使用magick
的image_write()
的一行程序。
#Rendering JPG image into SVG
image_write(obama, path = 'obama.svg', format = 'svg')
下面是我们从维基百科读到的奥巴马图片的 PNG 格式:
但是你可能会想,“嘿!这只是基本的图像处理。你没说这是高级的吗?”是的,随着好消息而来的是先进的东西,即magick
支持管道%>%
操作器。
这是我们将要做的:
#Applying Charcoal effect to Obama's image
#and compositing it with frink's image
#and finally annotating it with a text
image_charcoal(obama) %>%
image_composite(frink) %>%
image_annotate("CONFIDENTIAL", size = 50, color = "red", boxcolor = "pink",
degrees = 30, location = "+100+100") %>%
image_rotate(30) %>%
image_write('obama_with_frink.png','png')
给出以下输出:
输出图像看起来如何?很有艺术感不是吗?)!
但这并不是科学家每天都想做的事情,相反,我们玩的是图,大多数时候想注释 R 图形输出,这里是你如何用magick
的image_annotate()
做到这一点
library(ggplot2)
img <- image_graph(600, 400, res = 96)
p <- ggplot(iris) + geom_point(aes(Sepal.Length,Petal.Length))
print(p)
dev.off()
img %>% image_annotate("CONFIDENTIAL", size = 50, color = "red", boxcolor = "pink",
degrees = 30, location = "+100+100") %>%
image_write('conf_ggplot.png','png')
给出此输出图像:
这只是对magick
所能做的事情的一瞥。从字面上看,在 magick 中还有很多魔法。亲自尝试一下,并在评论中分享你的想法。这里使用的代码可以在我的 github 上找到。如果你对用 Python 建立深度学习的专业知识感兴趣,可以看看这个 Datacamp 课程。
参考文献:
1.Magick Ropensci2。 Magick CRAN 文档 3。奥巴马形象功劳 4。 Frink Image Credit
使用计算机视觉技术的自动车辆的高级车道检测
在早期的 项目 中,我使用 Canny 和 Hough 变换分别检测颜色强度和置信度的变化,以检测车道线。该项目使用基于早期技术的高级技术,通过使用不同颜色空间和梯度的阈值、滑动窗口技术、扭曲透视变换和多项式拟合来检测车道线。如果你只对最终结果感兴趣,请跳转至 视频 。关于详细的讨论,请继续阅读。
实现本项目目标的一系列步骤如下:
- 计算摄像机校准矩阵和失真系数。
2.对原始图像应用失真校正。
3.使用颜色变换、渐变等。,以创建阈值化的二进制图像。
4.应用透视变换生成图像的“鸟瞰图”。
5.检测车道像素并拟合以找到车道边界。
6.确定车道的曲率和车辆相对于中心的位置。
7.将检测到的车道边界扭曲回原始图像,并显示车道曲率和车辆位置的数值估计。
让我们更深入地研究上面的每一个步骤,以详细理解这个过程。
- 计算摄像机校准矩阵和失真系数。
所有的相机都使用镜头,镜头的一个问题是它们有一些径向失真。为了消除这种失真,我在棋盘图像上使用 OpenCV 函数来计算正确的相机矩阵和失真系数。这可以通过找到图像内的内角并使用该信息来消除图像失真来实现。图 1 显示了左边的棋盘图像和右边检测到的该图像内的内角。
Fig 1. Calculating the camera matrix and distortion coefficients by detecting inside corners in a chessboard image (Source: Udacity)
失真矩阵用于消除校准图像的失真,并证明校准是正确的。图 2 中所示的示例显示了应用校准以消除棋盘图像失真后的前/后结果。
Fig 2. Before and after results of un-distorting a chessboard image (Source: Udacity)
2。对原始图像应用失真校正。
在步骤 1 中收集的相机校准数据可以应用于原始图像,以应用失真校正。图 3 中显示了一个示例图像。与棋盘图像相比,可能更难看出对原始图像应用扭曲校正的效果,但是如果您更靠近图像的右侧进行比较,当您查看应用扭曲校正时沿着树木轻微裁剪的白色汽车时,这种效果会变得更加明显。
Fig 3. Before and after results of un-distorting an example image (Source: Udacity)
3。使用颜色变换、渐变等。,以创建阈值化的二进制图像。
这一步骤背后的想法是创建一个图像处理管道,其中车道线可以被算法清楚地识别。通过尝试不同的渐变、阈值和色彩空间,有许多不同的方法可以找到解决方案。我在几幅不同的图像上试验了这些技术,并结合使用了阈值、色彩空间和渐变。我决定采用以下组合来创建我的图像处理管道:HLS 颜色空间中的 S 通道阈值和 HSV 颜色空间中的 V 通道阈值,以及检测车道线的梯度。图 4 示出了最终二进制阈值图像的例子,其中车道线清晰可见。
Fig 4. Before and after results of applying gradients and thresholds to generate a binary thresholded image (Source: Udacity)
4。应用透视变换生成图像的“鸟瞰图”。
图像具有透视性,这使得图像中的车道线看起来像是在远处会聚,即使它们彼此平行。当该透视被移除时,更容易检测车道线的曲率。这可以通过将图像转换为 2D 鸟瞰图来实现,其中车道线总是彼此平行。由于我们只对车道线感兴趣,我在原始未失真的图像上选择了四个点,并将透视转换为鸟瞰图,如下图 5 所示。
Fig 5. Region of interest perspective warped to generate a Bird’s-eye view (Source: Udacity)
5。检测车道像素并拟合以找到车道边界。
要检测车道线,有多种不同的方法。我使用了卷积,它是两个独立信号的乘积之和:窗口模板和像素图像的垂直切片。我使用了一个滑动窗口的方法来应用卷积,这将最大化每个窗口中的热点像素的数量。窗口模板在图像上从左向右滑动,任何重叠值相加在一起,产生卷积信号。卷积信号的峰值是像素重叠最高的地方,并且是车道标志最可能的位置。已经使用了多种方法来识别经矫正的二进制图像中的车道线像素。左线和右线已经被识别并用曲线多项式函数拟合。图 6 中示出了具有用滑动窗口方法和多项式拟合重叠识别的线像素的示例图像。
Fig 6. Sliding window fit results (Source: Udacity)
6。确定车道的曲率和车辆相对于汽车中心的位置。
我测量了车道线的位置,并估计了道路弯曲的程度,以及车辆相对于车道中心的位置。我假设摄像机安装在汽车的中央。
7 .。将检测到的车道边界扭曲回原始图像,并显示车道曲率和车辆位置的数值估计。
来自校正图像的拟合已经被扭曲回到原始图像上,并且被标绘以识别车道边界。图 7 展示了车道边界被正确识别并扭曲回到原始图像。图 8 中示出了具有车道、曲率和距中心的位置的示例图像。
Fig 7. Lane line boundaries warped back onto original image (Source: Udacity)
Fig 8. Detected lane lines overlapped on to the original image along with curvature radius and position of the car (Source: Udacity)
上述过程应用于视频的每一帧,关键步骤的最终结果显示在不同的帧中:
概要:
这种解决方案在正常照明条件下工作良好。然而,它需要改进以解决不同的用例。可以改进的一个例子是车道的一部分是新铺设的,而车道的另一部分是旧铺设的道路,颜色不同。在由于阳光直射而导致摄像机出现眩光的情况下,以及在车道线看起来被冲刷而使其更难检测的其他高对比度情况下,该算法也需要改进。这些类型的情况可以通过动态调整图像的对比度来解决,以确保图像中的车道线不会被洗掉,并确保该算法在所有照明条件下都具有良好的动态范围。在道路弯曲且有坡度的情况下,很难正确地扭曲图像,这可能会给算法带来问题。这个问题也可以通过为每个图像帧创建动态感兴趣区域来解决。这些是我以后需要探索的一些事情,以现有算法为基础,使其对于不同的用例都是健壮的。
如果你对技术细节感兴趣,可以查看我的 Github 资源库。
参考:所有的图片和视频都来自 Udacity,作为他们 SD 汽车纳米学位项目的一部分。原始图像上的增强信息是由我生成的,这是我开发的代码的输出。
使用 SQL 进行高级查询,节省您的时间
Photo by Kalen Emsley on Unsplash
是的,SQL 仍然存在
在处理电信数据的这些年里,我的代码片段文件夹收集了很多可重用的例子。它不是关于“从表 1 中选择”,我说的是查找和处理或删除重复值,从同一表内的每组数据中选择前 N 个值,在组内重排记录,但保持组排序,查找最长的左匹配,将数字扩展 N 位等等。
今天,我想分享这些片段,并解释它是如何工作的。我使用 Microsoft SQL Server,并在查询中使用 T-SQL,但我确信有可能找到其他 DBMS 的替代方案。如果没有,请联系我,我们会一起努力找到它🙂
在这篇文章中,我准备了一张表格,上面是用假号码和真实国家打来的假电话,所以如果你试图重复同样的交易,那是行不通的😀(好吧,除了英国,他们真的有+44 国家代码,但我不确定我用的号码是否存在)
处理重复
从表中只选择唯一值的最快、最简单的方法是使用 DISTINCT 关键字
SELECT DISTINCT *
FROM [test].[dbo].[12162018_FakeCalls]
通过指示我们想要检索的列,我们可以只根据数字和国家选择唯一的值。
SELECT DISTINCT NumberFrom, CountryFrom, NumberTo, CountryTo
FROM [test].[dbo].[12162018_FakeCalls]
但是我们丢失了来自其他列的信息。
我们还可以通过 GROUP BY、HAVING 和 COUNT(*)找到重复项
SELECT NumberFrom, CountryFrom, NumberTo, CountryTo, count(*) as dups
FROM [test].[dbo].[12162018_FakeCalls]
GROUP BY NumberFrom, CountryFrom, NumberTo, CountryTo
HAVING COUNT(*) > 1
ORDER BY dups desc
我知道,在 SQL 数据库中不应该出现重复,你应该使用唯一的 id,约束和索引。但是有时候你只是执行一些测试,或者第一次做一些计算,做一些实验——副本就出现了。或者您的记录有不同的 id,尽管您知道应该删除其中的一个。在这些情况下你会怎么做?很久以前,我在 stackoverflow 上发现了这个解决方案,保存了下来,从那时起,我每天至少使用它几次(重复是很常见的,具体取决于工作)。WITH statement 和 ROW_NUMBER()是我的救星。
WITH CTE AS
(
SELECT NumberFrom, CountryFrom, NumberTo, CountryTo, Duration, id, RN = ROW_NUMBER()OVER(PARTITION BY NumberFrom, CountryFrom, NumberTo, CountryTo ORDER BY CountryFrom)
FROM #t
)
SELECT *
FROM CTE WHERE RN > 1
我已经将原始数据复制到临时表#t 中,因为删除后“撤销”不起作用,呵🙂我们看到了与 GROUP BY 相同的结果,尽管所有列都是如此。现在,我们可以在这里执行删除,并根据我们对重复的定义删除所有重复值。
WITH CTE AS
(
SELECT NumberFrom, CountryFrom, NumberTo, CountryTo, Duration, id, RN = ROW_NUMBER()OVER(PARTITION BY NumberFrom, CountryFrom, NumberTo, CountryTo ORDER BY CountryFrom)
FROM #t
)
DELETE FROM CTE
WHERE RN > 1;SELECT *
FROM #t
在这种情况下,PARTITION BY 将作为重复定义,例如,通过 ORDER BY,我们可以删除持续时间较短/较长的呼叫,或开始时间较早/较晚的呼叫,或者您在其他列中可能发现的任何情况。请注意,ORDER BY 子句在这里是必须的,所以如果您没有任何特定的排序条件,只需在那里输入任何字段。
选择组内的前 N 条记录
我相信你已经知道怎么做了:d .是的,再用 ROW_NUMBER()。该函数将对我们的数据进行分区,并为一个组中的每条记录分配一个编号,因此我们只需指定我们想要选择前 N 名中的哪个范围:前 10 名?— RN = 3 且 RN
让我们只选择拨打电话的国家组(‘country from’)中名称以相同字母开头的前 2 名记录,并按组内持续时间对值进行排序。(我已经将相同的数据插入临时表 3 次,以便更好地查看差异)
WITH CTE AS
(
SELECT NumberFrom, CountryFrom, NumberTo, CountryTo, Duration, id, RN = ROW_NUMBER()OVER(PARTITION BY LEFT(CountryFrom,1) ORDER BY Duration ASC)
FROM #t
)
SELECT *
FROM CTE;
看看德国和希腊是如何被归为一类,而爱尔兰和意大利又是如何被归为另一类。并仅选择每个组中第二个记录:
WITH CTE AS
(
SELECT NumberFrom, CountryFrom, NumberTo, CountryTo, Duration, id, RN = ROW_NUMBER()OVER(PARTITION BY LEFT(CountryFrom,1) ORDER BY Duration ASC)
FROM #t)
SELECT *
FROM CTE
WHERE RN = 2;
在组内随机播放记录
实际上,这种技术在任何情况下都可以用来混洗记录,不仅是在组内,而且因为我们已经开始使用 groups、ROW_NUMBER 和语句,所以我决定让它稍微复杂一点。我不知道在你生命中的任何一个时期,你是否需要在一个团队中洗牌,但是如果出现这种情况,你知道如何去做。同样,这是我日常工作的一部分,我知道这是一项罕见的任务:)所以回到查询。我们将使用相同的分组条件,为了进行混排,将组合使用函数 ABS() —用于获取作为参数传递的数字的绝对值的函数,CHECKSUM() —返回通过表行或表达式列表计算的校验和值的函数,以及 NEWID() —创建 uniqueidentifier 类型的唯一值。阅读时,你可能会想——管它呢?但我告诉你,它起作用了。看:
WITH CTE AS
(
SELECT NumberFrom, CountryFrom, NumberTo, CountryTo, CallStarted, Duration, id, RN = ROW_NUMBER()OVER(PARTITION BY LEFT(CountryFrom,1) ORDER BY ABS(CHECKSUM(NewId())) % 1000000 DESC)
FROM [test].[dbo].[12162018_FakeCalls]
)
SELECT *
FROM CTE;
对于少量数据来说,这可能不是那么明显,但是最令人兴奋的是,每次运行这个查询时,它都会重新排序。所以在第二次运行后:
你可能注意到了,波兰是第一个记录,西班牙是第二个。
今天到此为止。关于 ROW_NUMBER()的一些提示对我的工作很有帮助,我希望对其他人也有帮助。
尽管它不包括机器学习、人工智能、图像识别、模型调整、深度神经网络或数据科学领域出现的任何其他花哨术语,但使用 SQL 处理数据仍然是数据科学的一部分。仍然有许多数据专业人员使用这种语言和关系数据库。伙计们,别忘了我们的根。
感谢你的阅读,保持冷静,专业,祝你有美好的一天。
原载于 2018 年 12 月 16 日【sergilehkyi.com4 种不同语言(EN、es、UA、RU)
超越 DQN/A3C:高级强化学习综述
我最喜欢深度强化学习的一点是,与监督学习不同,它真的真的不想工作。用神经网络解决计算机视觉问题可能会让你达到 80%的目标。在 RL 问题上扔一个神经网络可能会在你面前炸掉一些东西——而且每次你尝试的时候它都会以不同的方式炸掉。
RL 中的许多最大挑战围绕着两个问题:我们如何有效地与环境互动(例如探索与开发,样本效率),以及我们如何有效地从经验中学习(例如长期信用分配,稀疏的奖励信号)。在这篇文章中,我想探索深度 RL 研究中试图解决这些挑战的几个最新方向,并与人类认知进行特别优雅的类比。我特别想谈谈:
- 分层 RL,
- 记忆和预测建模,以及
- 结合无模型和基于模型的方法。
这篇文章将首先快速回顾两个典型的深度 RL 算法——DQN 和 A3C——为我们提供一些直观的参考,然后深入研究一些最近的论文和上述类别中的突破。
审查:DQN 和 A3C/A2C
免责声明:我假设你对 RL 有一些基本的了解(因此不会提供关于这两种算法的深入教程),但是即使你不是 100%了解它们是如何工作的,这篇文章的其余部分仍然是可以访问的。
DeepMind 的 DQN (deep Q-network) 是将深度学习应用于 RL 的首批突破性成功之一。它使用神经网络来学习经典 Atari 游戏(如 Pong 和 Breakout)的 Q 函数,允许模型直接从原始像素输入到动作。
在算法上,DQN 直接借鉴了经典的 Q 学习技术。在 Q 学习中,状态-动作对的 Q 值或“质量”是通过基于经验的迭代更新来估计的。本质上,随着我们在一个状态中采取的每一个动作,我们可以使用我们收到的即时奖励和我们的新状态的价值估计来更新我们的原始状态-动作对的价值估计:
训练 DQN 包括最小化时间差异误差或 TD 误差的 MSE(均方误差),如上所示。DQN 为深度神经网络调整 Q 学习所采用的两个关键策略是:
- 体验重放,其中每个状态/动作转换元组(s,a,r,s’)被存储在存储器“重放”缓冲器中,并被随机采样以训练网络,允许训练数据的重复使用和连续轨迹样本的去相关;和
- 使用单独的目标网络(上述等式中的 Q_hat 部分)来稳定训练,因此 TD 误差不是根据训练网络中不断变化的目标来计算的,而是根据由大部分固定的网络生成的稳定目标来计算的。
随后,DeepMind 的 **A3C(异步优势演员评论家)**和 OpenAI 的同步变体 A2C,推广了一种非常成功的基于深度学习的方法演员评论家方法。
行动者-批评家方法结合了政策梯度方法和学习价值函数。对于 DQN,我们只有学习价值函数——Q 函数——我们遵循的“政策”只是在每一步采取最大化 Q 值的行动。对于 A3C,就像其他的 actor-critic 方法一样,我们学习两种不同的功能:策略(或“actor”)和价值(即“critic”)。该策略基于采取该行动的当前估计的优势来调整行动概率,并且价值函数基于通过遵循该策略收集的经验和奖励来更新该优势:
从上面的更新中我们可以看到,价值网络学习了一个基线状态值V(s _ I;θ_v) 我们可以用它来比较我们当前的回报估计 R,以获得“优势”,策略网络通过经典的增强算法基于该优势来调整行动的对数概率。
A3C 的真正贡献来自它的并行和异步架构:多个参与者-学习者被分派到环境的不同实例中;它们都与环境交互并收集经验,并将它们的梯度更新异步地推送到一个中心“目标网络”(一个从 DQN 借鉴来的想法)。后来,OpenAI 向 A2C 展示了异步性实际上并不会提高性能,事实上还会降低采样效率。不幸的是,这些架构的细节超出了本文的范围,但是如果分布式代理让你兴奋,就像它们让我兴奋一样,请确保你查看了 DeepMind 的IMPALA——对于扩大学习非常有用的设计范例。
DQN 和 A3C/A2C 都可以是强大的基线代理,但当面对更复杂的任务、严重的部分可观测性和/或行动与相关奖励信号之间的长时间延迟时,他们往往会受到影响。因此,RL 研究的整个子领域已经出现来解决这些问题。让我们进入一些好的东西:)。
分层强化学习
分层 RL 是一类强化学习方法,它从多层策略中学习,每层策略负责在不同的时间和行为抽象级别进行控制。最低级别的策略负责输出环境动作,而较高级别的策略可以自由地操作更抽象的目标和更长的时间范围。
为什么这如此吸引人?首先,在认知方面,研究长期以来认为人类和动物的行为是由等级结构支撑的。这在日常生活中是很直观的:当我决定做饭时(顺便说一下,基本上从来没有,但为了便于讨论,让我们假设我是一个负责任的人),我能够将这项任务分成更简单的子任务:切菜、煮意大利面等。没有忘记我做饭的首要目标;我甚至能够交换子任务,例如煮饭而不是做意大利面,来完成同样的目标。这暗示了现实世界任务中固有的层级和组合性,其中简单的原子动作可以被串在一起、重复和组合以完成复杂的工作。近年来,研究甚至发现了 HRL 成分和前额叶皮层内特定神经结构之间的直接联系。
在技术研发方面,HRL 特别有吸引力,因为它有助于解决我在第二个问题中提到的两个最大的挑战,即如何有效地从经验中学习:长期信用分配和稀疏的奖励信号。在 HRL,因为低级策略根据高级策略分配的任务从内在奖励中学习,所以尽管奖励很少,原子任务仍然可以被学习。此外,由高级策略开发的时间抽象使我们的模型能够处理时间扩展体验上的信用分配。
那么它是如何工作的呢?有许多不同的方法来实现 HRL。Google Brain 最近的一篇论文采用了一种特别干净简单的方法,并为数据高效训练引入了一些不错的非政策修正。他们的模型叫做 HIRO。
μ_hi is the high-level policy, which outputs “goal states” for the low-level policy to reach. μ_lo, the low-level policy, outputs environment actions in an attempt to reach that goal state observation.
想法是这样的:我们有两层政策。高级策略被训练以最大化环境回报 r。每 c 时间步,高级策略采样一个新的动作,这是低级策略要达到的“目标状态”。低级策略被训练来采取环境动作,这些环境动作将产生类似于给定目标状态的状态观察。
考虑一个简单的例子:假设我们正在训练一个机器人按照一定的顺序堆叠彩色立方体。如果任务成功完成,我们最终只能获得一个+1 的奖励,而在所有其他时间点,奖励为 0。直觉上,高层策略负责提出需要完成的子目标:也许它输出的第一个目标状态是“观察你面前的红色立方体;下一个可能是“观察红色立方体旁边的蓝色立方体;然后“观察红色立方体上的蓝色立方体。”低级策略在环境中摸索,直到它提出产生这些观察所必需的动作序列,例如,拿起蓝色立方体并将其移动到红色立方体之上。
HIRO 使用 DDPG (深度确定性策略梯度)训练目标的变体来训练低级策略,其内在回报被参数化为当前观察和目标观察之间的距离:
DDPG 是另一个开创性的深度 RL 算法,它将 DQN 的思想扩展到了连续的动作空间。这是另一种行动者-批评者方法,它使用政策梯度来优化政策,但不是像 A3C 那样根据优势来优化政策,而是根据 Q 值来优化政策。因此,在 HIRO,最小化的 DDPG 邻近误差变成:
同时,为了使用非策略经验,用非策略修正训练高级策略。想法是这样的:为了提高样本效率,我们希望使用某种形式的重放缓冲区,比如 DQN。然而,旧的经验不能直接用于训练高层政策。这是因为低级策略在不断学习和变化,所以即使我们以与旧经验相同的目标为条件,我们的低级策略现在也可能表现出不同的动作/转换。HIRO 提出的政策外纠正是追溯性地改变政策外经验中的目标,以最大化观察到的行动顺序的可能性。换句话说,如果重放经验表明旧代理采取了动作( x,y,z )以达到目标 g ,我们发现目标 g̃ 将使当前代理最有可能采取那些相同的动作( x,y,z ),即最大化动作序列的对数概率:
高层次的政策随后被训练成 DDPG 版本的行动、新目标和环境回报。
HIRO 当然不是接近 HRL 的唯一途径。封建网络是一个更早的相关工作,它使用一个习得的“目标”表示,而不是原始的状态观察。事实上,研究中的许多变化源于学习有用的低级子政策的不同方法;许多论文使用了辅助或“代理”奖励,还有一些论文尝试了预训练或多任务训练。与 HIRO 不同,这些方法中的许多需要一定程度的手工工程或领域知识,这固有地限制了通用性。另一个最近探索的选择是使用基于人口的训练(PBT) ,另一个我个人很喜欢的算法。本质上,内部奖励被视为额外的超参数,PBT 在训练过程中学习这些超参数在“进化”人群中的最优进化。
HRL 现在是一个非常受欢迎的研究领域,很容易与其他技术相结合(查看这篇论文结合 HRL 和模仿学习)。然而,就其核心而言,这只是一个真正直观的想法。它是可扩展的,具有神经解剖学的相似性,并解决了 RL 中的一系列基本问题。就像其他优秀的 RL 一样,训练起来会很棘手。
记忆和注意力
现在让我们谈谈解决长期信用分配和稀疏奖励信号问题的其他一些方法。具体来说,我们来说说最明显的方式:让代理人真正擅长记忆事物。
深度学习中的记忆总是很有趣,因为尽管研究人员可能会尝试(事实上,他们也确实在尝试),但很少有架构能打败一个调整良好的 LSTM。然而,人类的记忆并不像 LSTM 那样工作;当我们处理日常生活中的任务时,我们回忆并关注特定的、与环境相关的记忆,除此之外别无其他。当我回到家,开车去当地的杂货店时,我用的是过去 100 次驾驶这条路线的记忆,而不是如何从卡姆登镇到伦敦皮卡迪利广场的记忆——即使这些记忆在最近的经历中是新鲜的。从这个意义上来说,我们的记忆看起来几乎可以通过上下文来查询:根据我在哪里和我在做什么,我的大脑知道哪些记忆对我有用。
在深度学习中,这是外部的、基于键值的内存存储背后的驱动论点。这个想法并不新鲜;神经图灵机,我读过的第一篇也是最喜欢的论文之一,用一个可微分的外部存储器来增强神经网络,可通过向量值的“读”和“写”头访问特定位置。我们可以很容易地想象这被扩展到 RL,在任何给定的时间步,一个代理被给予与其当前状态相关的环境观察和记忆。这正是最近的 MERLIN 架构的延伸。
MERLIN 有两个组件:一个基于记忆的预测器(MBP) 和一个策略网络。MBP 负责将观察值压缩成有用的低维“状态变量”,直接存储到键值存储矩阵中。它还负责将相关内存传递给策略,策略使用这些内存和当前状态来输出操作。
这个架构看起来可能有点复杂,但是请记住,策略只是一个经常性的净输出操作,MBP 实际上只做 3 件事:
- 将观察结果压缩成有用的状态变量 z_t 以传递给策略,
- 将 z_t 写入存储矩阵,以及
- 获取其他有用的记忆传递给政策。
流水线看起来像这样:输入观察首先被编码,然后通过 MLP 馈送,其输出被添加到下一个状态变量上的先验分布,以产生后验分布。这个后验分布以所有先前的动作/观察以及这个新的观察为条件,然后被采样以产生状态变量 z_t。接下来,z_t 被馈入 MBP 的 LSTM,其输出用于更新先验,并通过向量值“读密钥”和“写密钥”从存储器读取/写入,这两者都是作为 LSTM 隐藏状态的线性函数产生的。最后,在下游,策略网利用来自内存的 z_t 和 read 输出来产生一个动作。
一个关键的细节是,为了确保状态表示是有用的,MBP 也被训练来从当前状态 z_t 预测奖励,因此学习到的表示与手头的任务相关。
梅林的训练有点复杂;由于 MBP 的目的是作为一个有用的“世界模型”,一个棘手的目标,它被训练来优化变分下限(VLB)损失。(如果你对 VLB 不熟悉,我发现这篇文章相当有用,但你真的不需要它来理解梅林)。VLB 的损失有两个组成部分:
- 下一个状态变量的先验概率分布和后验概率分布之间的KL-散度,其中后验概率还取决于新的观测值。最小化这个 KL 确保这个新的状态变量与先前的观察/动作一致。
- 状态变量的重建损失,其中我们试图重现输入观察(如图像、先前动作等。)并基于状态变量预测奖励*。如果这种损失很小,我们已经找到了一个状态变量,它是观察的精确表示,并且对于产生给予高回报的行动是有用的。*
这是我们最后的 VLB 损失,第一项是重建,第二项是 KL 散度:
政策网络的损失是我们上面讨论的 A3C 的政策梯度损失的一个稍微花哨的版本;它使用一种称为广义优势估计算法的算法,其细节超出了本文的范围(但可以在 MERLIN 论文的附录的第 4.4 节中找到),但它看起来类似于下面显示的标准政策梯度更新:
一旦经过训练,MERLIN 应该能够通过状态表示和记忆对世界进行预测建模,并且它的策略应该能够利用这些预测来采取有用的行动。
梅林并不是唯一一个使用外部记忆存储的深度 RL 作品——早在 2016 年,研究人员就已经在 MQN 或记忆 Q 网络中应用这一想法,以解决《我的世界》的迷宫——但这种使用记忆作为世界预测模型的概念有一些独特的神经科学牵引力。另一个 Medium post 在探索这个想法方面做了很好的工作,所以我不会在这里重复,但关键的论点是,我们的大脑很可能不像大多数神经网络所解释的那样,充当“输入-输出”机器。相反,它的功能是预测引擎,我们对世界的感知实际上只是大脑对我们感官输入原因的最佳猜测。神经科学家阿米尔·塞斯很好地总结了赫尔曼·赫尔姆霍茨 19 世纪的理论:
大脑被锁在一个骨质头骨里。它接收到的都是模棱两可、嘈杂的感官信号,只与世界上的物体间接相关。因此,感知必须是一个推理过程,在这个过程中,不确定的感官信号与之前对世界的期望或“信念”相结合,形成大脑对这些感官信号原因的最佳假设。
梅林基于记忆的预测器旨在实现预测推理的这一目的。它对观察结果进行编码,并将它们与内部先验结合起来,以生成一个“状态变量”,该变量捕获输入的一些表示(或原因),并将这些状态存储在长期记忆中,以便代理可以在以后对它们采取行动。
代理人、世界模型和想象力
有趣的是,大脑作为预测引擎的概念实际上将我们带回了我们想要探索的第一个 RL 问题:我们如何有效地从环境中学习?毕竟,如果我们不直接从观察到行动,我们应该如何最好地与我们周围的世界互动和学习?
传统上在 RL 中,我们既可以进行无模型学习,也可以进行基于模型的学习。在无模型 RL 中,我们学习将原始环境观察直接映射到值或动作。在基于模型的 RL 中,我们首先学习基于原始观察的环境的转换模型,然后使用该模型来选择动作。
The outside circle depicts model-based RL; the “direct RL” loop depicts model-free RL
能够基于一个模型进行计划比在无模型学习中必须从纯粹的试错中工作要高效得多。然而,学习一个好的模型通常是非常困难的,并且由于模型的不完善而产生的复合误差通常会导致代理的不良性能。出于这个原因,deep RL 的很多早期成功(比如 DQN 和 A3C)都是无模型的。
也就是说,早在 1990 年的 Dyna 算法中,无模型和基于模型的 RL 之间的界限就已经模糊了,在该算法中,学习的模型被用来生成模拟的经验,以帮助训练无模型策略。现在在 2018 年,一种新的“想象力增强的代理”算法被引入,直接结合了这两种方法。
在想象增强代理(I2A) 中,最终策略是无模型组件和基于模型组件的函数。基于模型的组件被称为代理对世界的“想象”,由代理内部学习的模型推出的想象轨迹组成。然而,关键是基于模型的组件在末端也有一个编码器,它聚集想象的轨迹并由解释,使代理能够在必要时学会忽略它的想象。从这个意义上说,如果代理发现它的内部模型正在投射无用和不准确的轨迹,它可以学习忽略该模型,继续使用它的无模型手臂。
上图描述了 I2A 的工作方式。观察首先被传递给无模型和基于模型的组件。在基于模型的组件中, n 不同的轨迹是基于在当前状态下可能采取的 n 种可能的动作而“想象”出来的。这些轨迹是通过将动作和状态输入到内部环境模型中,转换到新的想象状态,在该状态下采取最大的下一个动作等等而获得的。经过提炼的想象策略(通过交叉熵损失与最终策略保持相似)选择下一步行动。在一些固定的 k 步骤之后,这些轨迹被编码和聚集在一起,并与无模型组件的输出一起被馈送到策略网络中。至关重要的是,编码允许政策以最有用的方式解释想象的轨迹——适当时忽略它们,提取可用的非奖励相关信息,等等。
该策略通过标准策略梯度损失与优势进行训练,类似于 A3C 和 MERLIN,因此现在看起来应该很熟悉:
此外,在实际策略和内部模型的假想策略之间添加了策略提取损失,以确保假想策略选择与当前代理类似的动作:
I2A 优于许多基准,包括 MCTS(蒙特卡罗树搜索)规划算法。它还能够在实验中表现良好,其中其基于模型的组件被有意限制为做出较差的预测,这表明它能够在必要时权衡模型的使用以支持无模型方法。有趣的是,具有较差内部模型的 I2A 实际上最终略微优于具有良好模型的 I2A,作者将其归因于随机初始化或最终提供某种形式的正则化的嘈杂内部模型,但这肯定是进一步研究的领域。
无论如何,I2A 是迷人的,因为在某些方面,它也正是我们在这个世界上的行为方式。我们总是根据我们所处环境的一些心理模型来规划和预测未来,但我们也倾向于意识到我们的心理模型可能完全不准确——尤其是当我们处于我们从未见过的新环境或情况下。在这种情况下,我们通过试错法进行,就像无模型方法一样,但我们也使用这种新的体验来更新我们的内部心理模型。
现在有很多工作在结合基于模型和无模型的方法。Berkeley AI 提出了一个时间差异模型(TDM) ,它也有一个非常有趣的前提。这个想法是让代理设置更多的时间抽象目标,即“在 k 时间步骤中处于 X 状态”,并学习那些长期模型转换,同时最大化每个 k 步骤中收集的奖励。这让我们在行动的无模型探索和基于模型的高层次目标规划之间实现了平稳过渡——如果你仔细想想,这有点让我们回到了分层 RL 中的直觉。
所有这些研究论文都专注于同一个目标:实现与无模型方法相同(或更好)的性能,并具有与基于模型的方法相同的样本效率。
结论
深度 RL 模型真的很难训练。但由于这一困难,我们被迫提出了一系列令人难以置信的策略、方法和算法,以利用深度学习的力量解决经典(和一些非经典)控制问题。
这篇文章是对 deep RL 的一个非常、非常不完整的调查——有很多研究我还没有涉及,还有更多我甚至不知道。然而,希望这种在记忆、层次和想象力方面的零星研究方向提供了一瞥,让我们可以开始解决该领域中一些反复出现的挑战和瓶颈。如果你认为我错过了一些重要的东西,我可能是——让我在评论中知道是什么吧。:)同时,祝 RL 黑客快乐!
使用 Python、Matplotlib 和 Seaborn 实现高级体育可视化
如何从最具竞争力的游戏中获得有价值的见解的详细教程
Photo by Lukas Blazek on Unsplash
“一张照片的最大价值在于它能迫使我们注意到我们从未想过会看到的东西。”
你已经在新闻中看到了这一切:媒体大肆宣传体育分析时代的到来,商业广告描绘了像袖珍计算器这样的大数据工具,专家使用多维相机收集体育运动员每一滴汗水的细节**输入你童年时代的英雄名字:L .梅西、勒布朗·詹姆斯、汤姆·布拉迪等 * *并将他们的表现提高 10 倍。
虽然显然我们还没有完全实现,但体育分析已经在帮助球队做出决策方面取得了很大进展,这些决策传统上是由“直觉”感觉或对过去传统的坚持做出的,如选择哪些球员、交易、发展、教练以及使用哪种系统。
在这篇博客文章中,我不会开发一种算法来预测托特纳姆有多大可能(不太可能)进入英超前四,或者如何为 2018 年建立一支完美的喷气机队。相反,我将介绍一些可视化技术,这将有助于我们准备引人注目和有见地的图表,以吸引你的体育爱好者同伴。
注意:
- 尽管我的例子只限于足球和 FIFA 世界杯,但这些技巧适用于任何运动和比赛。
- 你可以在这里找到这个教程的所有源代码。
Details of all shots France team attempted across their 7-match World Cup campaign. You will be able to create this visualization by the end of this tutorial. Original image of Mbappe is by adi-149 via DevianArt
1.获取数据:
坏消息:这通常是最难的部分
虽然你可以毫无困难地收集体育赛事的统计数据(足球比赛中的进球,篮球比赛中的投球,等等。),通常很难找到一场特定足球比赛或网球比赛的详细、详细的数据集。跟踪球场上的球员,尤其是像足球或篮球这样的高节奏、高强度的运动,是一项艰巨的任务,尽管利润非常丰厚。SportVu 或 Opta Sports 等公司通过向团队、体育咨询公司或研究中心出售这些备受追捧的信息来赚钱。
“每场比赛,我们都有三个人使用[……]球场图形上的实时视频:一个人观看主队比赛,另一个人观看客场比赛,第三个人基本上是一名数据检查员。”
—西蒙·巴努布,Opta 营销总监
我们的无名英雄
最近,Statsbomb 宣布公开发布了最近三个足球联赛的每场比赛的详细比赛,第二精确的数据集:国家女子足球联盟(美国),英国足球协会女子超级联赛(英格兰),以及 2018 年国际足联世界杯。你可以免费访问他们的数据集这里。
数据集都是 json 格式的,所以您需要将原始数据集解析成一种关系格式,以便于检索和操作。
json_normalize() 是一个非常方便的工具,因为它可以自动将 json 结构“规范化”成扁平的关系结构。
在本教程中,我们将专注于 2018 年国际足联世界杯。我鼓励您在开始分析之前阅读数据集的文档。毕竟,理解你的数据是最重要的。
2。画足球场:
首先,让我们用 Matplotlib 画一个简单的足球场。
这看起来很多,但是让我们一行一行地解开 draw_pitch() 函数。该函数接受一个 ax 参数,它是 Matplotlib 中 add_subplot() 函数的输出。然后,它添加几个具有预定义尺寸的对象来重新创建一个足球场的图像,包括中心圆、罚球区、6 码框和球场中的弧线。一旦我们定义了这个函数,我们调用与标准 Matplotlib 一起的图形函数如下:
A nice football pitch constructed with no more than rectangles, circles and arcs
3.使用通道图和热图提升您的可视化程度:
2018 FIFA 世界杯最震撼的瞬间是什么?
Image by Дмитрий Садовников via Wikipedia
有许多竞争者,但很少有人能打败当时的卫冕冠军德国队被韩国队淘汰出世界杯的那一刻。有痛苦,有眼泪,当然,也有批评。令人清醒的失败的后果是德国 10 号人物梅苏特·厄齐尔的离开,他承担了几乎所有的责任,既因为他的表现,也因为他在世界杯前与土耳其总统埃尔多安的会晤。听听拜仁主席乌利·赫内斯对厄齐尔说了些什么:
“他多年来一直在玩 s游戏,现在他和他的 s表演隐藏在这张照片之外。”
但是,他有那么坏吗?
让我们看看他在广受批评的对阵韩国的比赛中的表现。我想绘制一张热图和传球图来捕捉他在 90 分钟内的表现,并评估他对德国队进攻端的影响(无论是积极的还是消极的)。
先来一张过关图
我们加载 json 文件,并在 Panda 中进行一些基本的数据清理,以获得一个只包含梅苏特·厄齐尔路过事件的数据集。
What our condensed dataset looks like. You can extract more information: pass_complete_status, etc.
这个数据集非常有意义,也就是说,人们可以发现厄齐尔在比赛中尝试了多达 95 次传球,其中有 7 次非常犀利,这对于一名攻击型中场来说是非常令人印象深刻的,或者说他在比赛中把球传给托尼·克罗斯(19 次)和马尔科·罗伊斯(18 次)。就通行证地图而言,我们只关心通行证的开始和结束位置
下面的代码允许我们将传球作为箭头覆盖到我们的球场上
Looks pretty good but we can do even better. I will come back to how a little tweak can make this plot a lot more informative
用热图追踪活跃区
俱乐部内部和媒体分析师使用足球热图来说明球员所在的区域。它们实际上是玩家位置的平滑散点图,可以很好地显示玩家在球场不同位置的效率。虽然可能会有一些关于它们有多大用处的争论(它们不会告诉你动作/运动是好是坏!),它们通常非常具有美感和吸引力,因此很受欢迎。
现在,如果我们回到梅苏特·厄齐尔,他面临的一个主要批评是低覆盖率,因为我们很少看到他发起铲球或争抢控球权,因此,正如他们所说的,“低水平的工作率”。
但事实真的是这样吗?
让我们在 Matplotlib 上使用 Seaborn 绘制一个热图,以可视化梅苏特厄齐尔在德国与韩国比赛的 90 分钟内的参与。代码的语法非常简单。我们使用 kdeplot,它将绘制厄齐尔位置的散射点的核密度估计。
哇!!!那看起来非常…反气候。毕竟,图表想要告诉你什么?我看到了一些坐标,显然这些轮廓图似乎表明厄齐尔在颜色较深的区域更活跃。
我们还能做得更好吗?
是的,答案是我们可以结合(1)球场,(2)传球图和(3)热图,以便对厄齐尔在比赛中的表现有一个更全面的看法
Notice that I also color the passes differently, as the blue arrows indicate passes made in the first half, and the red arrows second half
现在我们可以更全面地了解梅苏特·厄齐尔在比赛中的表现。一些即时的观察结果:
- 他几乎只防守对手的半场,所以对他缺乏防守心态的批评不是完全没有根据的。但问题是,他是否有望以 1 比 1 获胜,并作为凸轮回收球?
- 他在下半场更多的向前和直接传球,与上半场更多的保守和向后传球形成对比。可能有两个原因:(1)下半场德国队内部有一种普遍的紧迫感(2)引进马里奥·戈麦斯作为中锋确实为厄齐尔的关键传球提供了一个出口,因为我们看到总共有 6 次传球直接传入禁区,是他在上半场的三倍。
我发现有趣的是蒂莫·韦尔纳的传球路线,他开始是德国队的单前锋,然后在下半场的大部分时间里与马里奥·戈麦斯搭档。
令人惊讶的是,他在两边花了很多时间,而你会认为中锋在 18 码区占据了更多的空间。这部分解释了德国进攻线在比赛中的无效性,因为他们的前锋线(Werner,Reus,Goretzka,然后是 Muller,Gómez)挤在边路,但未能在禁区内占据空间,从而为厄齐尔和 Kroos 等组织者提供了很少的出口将球送入 18 码禁区。
4。测试你的技能:法国远程努力的案例
我的一个朋友非常确信,法国世界杯成功的关键是他们不懈地试图用远射打破防线。想想本杰明·帕瓦尔在四分之一决赛中对阿根廷的那个精彩进球
我们可以再次尝试想象法国队的所有射门,以确定他们的大多数进球是来自禁区外还是禁区内?
如果我只是按照到目前为止显示的方法,这就是我得到的
Shot taken by France team during the World Cup campaign
这很好。但是,我们可以做更多的工作,使可视化更有吸引力和洞察力。具体来说,我做了两个小调整:
(1)由于我们只关注镜头,这些镜头都是在球场的一侧记录的,所以我将只画出球场的右半边
(2)由于我们只关心射击的起点,我们可以扔掉箭头,只把射击想象成散点图,其中 x,y 是尝试射击的位置。
现在看起来好多了。我们可以马上看到,法国队在禁区内的射门次数和他们在禁区外的射门次数一样多。虽然在一定程度上,这确实支持了法国队比平时付出更多远射努力的论点,因为我们预计禁区外的射门密度会低得多。无论如何,看起来很有趣的是,短期和长期的努力看起来是一样的客观。
在我的 Jupyter 笔记本中,你还可以找到更多的技术,比如叠加密度图和将图像包含到你的可视化中。再多几行代码,您就可以轻松地生成这样的可视化效果:
你可以在这里找到本教程的所有源代码
本项目使用的数据由 Statsbomb 发布,并在此向公众公开
使用 react-vis 实现高级可视化
使用 Voronois、单程渲染和画布组件获得惊人的用户体验
所以你已经开始用 react-vis 做一些数据可视化,你已经建立了一些你自己的图表,也许你已经读过shyanovska Nataliia的精彩介绍用 react-vis 做数据可视化,或者甚至可能建立了一个仪表板。是时候学习一些处理更大数据量和更复杂 UI 交互的技术了。在这篇文章的过程中,我们将看到如何使用单程渲染,画布部件,去抖动状态更新,和 Voronois。系好安全带,这将是一次疯狂的旅程!
首先,您可以使用 create-react-app 设置 scaffold a new app,然后在终端中运行
npm install react-vis --save
# we will also be using a few additional libraries
# so install these too
npm install --save d3-fetch d3-scale d3-scale-chromatic debounce simplify-js
也就是说,我为我的应用程序使用了稍微不同的配置,你可以在这里查看(以及整篇文章的代码)。
获取和准备数据
学习如何做任何事情的一个传统技巧是模仿大师,这篇文章也不例外。我们将探索纽约时报 2016 年的可视化“斯蒂芬库里的 3 分记录”。
这张图表有 752 行——每一行代表一名 NBA 球员,他们在每场比赛中的三分球命中率都排在前 20 位
www.nytimes.com](www.nytimes.com/interactive…)
在这个可视化中有很多事情正在发生!每一行显示了一个特定的球员在特定的赛季中投中三分球的次数。这个信息可以通过一个动态的鼠标指针来访问,鼠标指针同时会突出显示特定的玩家年份,并提供一个工具提示来准确描述用户所停留的行。
我们的第一步将是获取数据。令人愉快的是,NYT 为这篇文章提供了 CSV 格式的数据,所以我们可以很容易地通过查看 chrome 中的网络选项卡来获取这些数据,如下所示。下载完数据文件后,将它放在应用程序中的某个地方,我将它放在一个名为 data 的文件夹下,并将其命名为“nyt-rip.csv”。
Capturing the CSV data that we will be using for our visualization by watching the network tab on Chrome. Refreshing the page triggers a lot of network calls, we then filter the network history to only CSV’s, and save the relevant file by double clicking it.
这个 csv 的格式有点不方便,它有球员 id、球员姓名、年份以及本赛季每场比赛的三次投掷次数等列。让我们把它整理成一种更容易使用的格式:
const nonNumericRows = {
player: true,
pname: true,
year: true
};// reformats input csv so that each row
// has details about the corresponding player
// and an array of points describing that players record
export function cleanData(data) {
return data.map(row => {
// extract all of the columns for
// this row that update that players score
const gameData = Object.keys(row)
.filter(key => !nonNumericRows[key] && row[key] !== 'NA')
.map((key, x) => ({x, y: Number(row[key])})); // return a formatted object to manipulate
return {
player: row.player,
pname: row.pname,
year: row.year,
height: gameData[gameData.length - 1],
gameData
};
});
}
太好了,现在我们有了一种机制来以可用的方式格式化我们的数据。在我们编写实用函数的同时,让我们也编写一个来获取数据域:
export function getDataDomain(data) {
const {min, max} = data.reduce((acc, player) => {
return player.gameData.reduce((mem, row) => {
return {
min: Math.min(mem.min, row.y),
max: Math.max(mem.max, row.y)
};
}, acc);}, {min: Infinity, max: -Infinity});
return [min, max];
}
将这两个函数放入 utils.js 文件中,我们就可以开始比赛了。
第一种天真的方法
为了给我们随后的优化做好准备,我们先来看一个简单的方法。在我们的数据集中有 750 个球员年,所以我们只有 750 个系列。当我们悬停在它们上方时,让我们重新绘制线条并突出显示选中的线条。相当合理!这里有一个简单实现的完整过程,之后我将详细介绍并描述每个部分:
哦,一下子这么多!但是如果把它分成几块就很容易处理了。当我们的组件准备好挂载时,它做的第一件事是通过 d3-fetch csv 函数调用数据,然后我们清理数据并将其保存到状态,以便在不久的将来接收。
componentWillMount() {
csv('data/nyt-rip.csv')
.then(data => this.setState({
data: cleanData(data),
loading: false
}));
}
如果数据还没有被加载,我们通过拒绝尝试渲染我们的组件来开始我们的渲染功能,而只是返回一个加载消息(尽管你可以很容易地给 show 一个旋转器或者使用像 placeloader 这样的花哨东西)。接下来,我们使用上一节中的 getDataDomain 函数构建一个由 d3-scale-chromatic 支持的色标。在本文中,我们主要感兴趣的是重建原始 NYT 可视化的感觉(而不是确切的外观),所以这里我们使用了不同的色标,并放弃了一些额外的图表装饰。
const {loading, highlightSeries, data} = this.state;
if (loading) {
return <div><h1>LOADING</h1></div>;
}const dataDomain = getDataDomain(data);
const domainScale = scaleLinear().domain(dataDomain).range([1, 0]);
const colorScale = val => interpolateWarm(domainScale(val));
最后,我们来看图表的实际渲染。我们首先查看所有的数据行,为每个数据行创建一个 LineSeries,并定义一个基本的交互技术。接下来,我们添加一个 LabelSeries 来突出显示沿 y 轴和 x 轴的某些点,并使用特殊格式来匹配 NYT 图形给出的标签。
<XYPlot {...layout}>
{data.map((player, idx) => {
const playerHighlightString = `${player.pname}-${player.year}`;
return (
<LineSeries
key={idx}
strokeWidth="4"
curve="curveStepBefore"
data={player.gameData}
onSeriesMouseOver={() =>
this.setState({highlightSeries: playerHighlightString})}
onSeriesMouseOut={() =>
this.setState({highlightSeries: null})}
stroke={
playerHighlightString === highlightSeries ? 'black' :
colorScale(player.gameData[player.gameData.length - 1].y)
}
/>);
})}
<LabelSeries
data={data.filter(row => labelMap[`${row.pname}-${row.year}`])}
style={{fontSize: '10px', fontFamily: 'sans-serif'}}
getY={d => d.gameData[d.gameData.length - 1].y}
getX={d => 82}
labelAnchorX="start"
getLabel={d =>
`${d.pname} - ${d.gameData[d.gameData.length - 1].y}`}/>
<XAxis
style={{ticks: {fontSize: '10px', fontFamily: 'sans-serif'}}}
tickFormat={d =>
!d ? '1st game' : (!(d % 10) ? `${d}th` : '')}/>
</XYPlot>
敏锐的读者会注意到,我们使用了两个常量,它们是从一个单独的 constants.js 文件中导入的,为了逻辑上的方便,将它们提取出来:
export const desiredLabels = [
{pname: 'Brian Taylor', year: 1980},
{pname: 'Mike Bratz', year: 1981},
{pname: 'Don Buse', year: 1982},
{pname: 'Mike Dunleavy', year: 1983},
{pname: 'Larry Bird', year: 1986},
{pname: 'Danny Ainge', year: 1988},
{pname: 'Michael Adams', year: 1989},
{pname: 'Michael Adams', year: 1990},
{pname: 'Vernon Maxwell', year: 1991},
{pname: 'Vernon Maxwell', year: 1992},
{pname: 'Dan Majerle', year: 1994},
{pname: 'John Starks', year: 1995},
{pname: 'Dennis Scott', year: 1996},
{pname: 'Reggie Miller', year: 1997},
{pname: 'Dee Brown', year: 1999},
{pname: 'Gary Payton', year: 2000},
{pname: 'Antoine Walker', year: 2001},
{pname: 'Jason Richardson', year: 2008},
{pname: 'Stephen Curry', year: 2013},
{pname: 'Stephen Curry', year: 2014},
{pname: 'Stephen Curry', year: 2015},
{pname: 'Stephen Curry', year: 2016}
];export const layout = {
height: 1000,
width: 800,
margin: {left: 20, right: 200, bottom: 100, top: 20}
};export const NUMBER_OF_GAMES = 82;
export const MAX_NUMBER_OF_THREE_POINTERS = 405;
综上所述,这看起来像是:
相当酷!然而,响应性不是很好,当我们接近它们时,线条不会突出显示,浏览器明显出现滞后。这种策略也阻止了我们在边上添加工具提示(虽然我们可以这样做,但是当我们悬停在不同的元素上时会有很多抖动)。一定有更好的办法!
更好的建筑
到目前为止,我们一直在使用 SVG 线渲染我们的系列。虽然这种方法很容易推断 UI 的状态,但每次都重新绘制所有的线条确实效率很低。这是因为每一行都被建模为一个非常详细的 DOM 节点,这对浏览器来说非常重要。为了减轻这一重量,我们可以使用内置的 react-vis 帆布系列 LineSeriesCanvas。Canvas 的渲染速度往往比 SVG 快得多,但在 DOM 中没有相同的详细表示,这意味着任何交互都必须手工完成。显然,将这个新的系列放到我们天真的解决方案中会使整个页面更快,但是我们会失去我们的动态交互性。
为了解决这个问题,我们将图表分成两个部分,一个处理交互性,另一个处理其他所有的事情。这是由 React 只为已经更新的组件执行渲染功能的想法所激发的。
The organization of our chart component after breaking out the interactive parts into a separate component
通过这个架构,我们将有一个组件来呈现画布线条,还有一个组件来呈现高亮线条和高亮工具提示。从而有效地将快速渲染的元素与昂贵或耗时渲染的元素分开。布局的一些伪代码:
<div className="relative">
<NonInteractiveParts />
<InteractiveParts />
</div>
我们希望这些组件看起来是一个漂亮的图表,所以我们给了交互部分 css 属性
position: absolute;
top: 0;
这允许交互部分“位于”非交互属性之上,从而完成外观。
静态部分
我们现在真的有所进展了。注意到图表的静态部分与我们在简单方法中的非常相似;只是一个装着一些系列的容器。为了简洁起见,我们可以将上面演示的根组件和画布部件合并成一个组件,因为它们中的每一个都只呈现一次。
这个新部件与我们的第一个非常相似。我们的 mounting 步骤做了一些额外的工作来促进交互组件的呈现——稍后会详细介绍——并调用我们即将成为交互组件的。但是除此之外,没有太大的变化!
互动部分
酷的东西来了。我们在上面看到,我们在 componentWillMount 步骤中额外准备了一些数据,以便为交互式组件做好准备,让我们看一下更详细的情况:
componentWillMount() {
csv('data/nyt-rip.csv')
.then(data => {
const updatedData = cleanData(data);
const playerYearMap = updatedData.reduce((acc, row) => {
const {pname, year, gameData} = row;
acc[`${pname}-${year}`] = gameData[gameData.length - 1].y;
return acc;
}, {}); const playerMap = updatedData.reduce((acc, row) => {
acc[`${row.pname}-${row.year}`] = row;
return acc;
}, {});
this.setState({
data: updatedData,
loading: false,
allPoints: buildVoronoiPoints(updatedData),
playerYearMap,
playerMap
});
});
}
我们清理的数据和以前一样,吱吱作响,很好用。接下来,我们引入一个名为 playerYearMap 的新变量,这个对象的键等于球员年唯一标识符,值等于每个球员达到的三分的最大分数。这将用于简化标签和工具提示的定位。类似地,我们引入一个 playerMap,它也有球员年份标识符作为键,但这次是整行作为值。这将允许当我们将鼠标放在事物上时快速/持续地查找行。
最后一个新变量称为 allPoints,由一个名为 buildVoronoiPoints 的函数生成。我想知道那会是什么?这是函数(它存在于 utils 中):
export function buildVoronoiPoints(data) {
return data.reduce((acc, {player, pname, year, gameData}) => {
return acc.concat({
player,
pname,
year,
x: 41,
y: gameData[gameData.length - 1].y
});
}, []);
}
这将为每个球员在该球员最大三分点数的“高度”区域的中心创建一个单点。我们可以用它来创建一个 Voronoi 图。Voronoi 是空间平面分割,使得形成点的集合,其中每个点包含在其自己的单元内。我们保证每个点将与其他点隔离。这个属性对鼠标悬停有很大的影响,因此用户一次只能将鼠标悬停在一个点上。
A colored in voronoi diagram, source wikipedia
我们正在模仿在最初的 NYT 图形中发现的鼠标悬停设置,在那里飞机被分成带状,这样当你上下移动鼠标时,当前选择的玩家年份会改变,当你左右移动鼠标时,它保持不变。我们可以通过使用 Voronoi 和我们之前特别构建的所有点来重建这种行为。一旦实现,voronoi 单元的布局将如下所示:
(When we’re done we will remove the stroke attribute from the Voronoi cells shown here, that way our user is none the wiser about our mouse over technique 😉)
相当酷!现在我们已经准备好查看交互式组件的代码了。
就像我们天真的方法一样,让我们一次看一个有趣的部分。让我们从房间里的大象开始:
<Voronoi
extent={[
[0, y(MAX_NUMBER_OF_THREE_POINTERS)],
[width, height - margin.bottom]
]}
nodes={allPoints}
polygonStyle={{
// UNCOMMENT BELOW TO SEE VORNOI
stroke: 'rgba(0, 0, 0, .2)'
}}
onHover={row => {
const player = playerMap[`${row.pname}-${row.year}`];
if (!player) {
this.setState({
highlightSeries: null,
highlightTip: null
});
return;
}
this.debouncedSetState({
highlightSeries: player.gameData,
highlightTip: {
y: player.gameData[player.gameData.length - 1].y,
name: row.pname
}
});
}}
x={d => x(d.x)}
y={d => y(d.y)}
/>
这个无害的组件接受一个点列表,并直接在 dom 中构建一个 voronoi 图。与 react-vis 中的其他组件相比,它的属性签名有点不正常(您需要提供一个刻度,范围),所以要小心!在这个组件中值得注意的另一件事是使用了 debouncedSetState 函数,正如您从上面所注意到的,我们必须通过以下方式来定义它:
componentWillMount() {
this.debouncedSetState = debounce(newState =>
this.setState(newState), 40);
}
该函数利用了称为去抖的 lodash 函数,该函数防止函数被调用超过特定频率(在本例中为每 40 ms 一次)。防止这种类型的超快速状态改变对我们是有利的,因为我们不希望每次用户做出很小的动作就导致状态改变。这将导致抖动和不必要的重绘!为了掩盖这一点点延迟,我们通过在 LineSeries 上包含动画道具来添加动画。
综上所述,我们得到:
Our pan-ultimate draft of the visualization
模一些小的造型触摸,就是这样!它运行平稳,准确地再现了在原始可视化中发现的交互。相当酷!
还有一点
我们已经很好地模拟了最初的 NYT 可视化的功能,但是现在我们想知道:我们能做得更好吗?他们展示的鼠标悬停功能是合理的,但是它有点笨拙,因为重叠,阻止你将鼠标悬停在每个玩家身上。如果我们能以一种明智的和有效的方式来简化它,我们会很高兴。这个问题的答案,而且,如果我们真的是诚实的,大多数问题,是使我们的 Voronoi 更加细致入微。
一个简单的膝跳是为每个数据点建模创建 Voronoi 单元。虽然这样做是完全可能的,但是会产生大量的细胞。如果在 750 名玩家的赛季中有 82 场比赛,那将是 61,500 个不同的单元!根据一般经验,浏览器最多只能处理几千个 SVG 元素,所以我们需要更加聪明。
一个强大的解决方案是通过简化我们的每一行来开发数据集的简化模型。令人愉快的是,有大量关于线条简化的工作,比如非常优秀的 Vladimir Agafonkin/monner 的 simplify-js 库。许多这类工作的出现是因为制图员对保存海岸线和其他不规则地理实体的粗糙边缘的简化形状感兴趣。但是我们会把它用在不同的地方。
mourner’s simplify-js demo page, simplifying complex lines.
我们将简化每个球员的年线,这样我们就可以得到他们的线的要点,没有太多的细节。我们通过在 utils 文件中添加另一项内容来让 simplify-js 处理我们的数据,从而执行了这个想法:
const betterThanCurryLine = simplify(stephCurryRecord, 0.5)
.map(({x, y}) =>
({x, y: y + 20, pname: 'Stephen Curry', year: 2016}));const SIMPLICATION = 3;
export function buildVoronoiPointsWithSimplification(data) {
return data.reduce((acc, {player, pname, year, gameData}) => {
return acc.concat(
simplify(gameData, SIMPLICATION).map(({x, y}) => ({player, pname, year, x, y}))
);
}, betterThanCurryLine);
}
作为视觉化主义者,我们的第一个冲动是想看看这些简化是什么样子,瞧:
Visualization of the simplification of our model in preparation for a modest robust voronoi strategy (left) compared to the unsimplified data (right). On the left we that there is an (comparatively) jagged line above all of the others, this line is used to specially tune the character of the resulting voronoi. Curry’s record breaking trajectory plays a big role in the user’s experience of this chart, so it is necessary to provide some extra polish to make sure interactions with that line really shine.
有了所有这些东西,我们终于可以看到最终的 voronoi 图了。请看:
The user experience of using our line-simplified voronoi technique (left), and a visualization of what’s going on under the hood (right).
结论
在这篇文章中,我们看到了如何使用 react-vis 重建出版物质量的交互式数据图形。这涉及到使用各种各样的交互式可视化技术,包括画布渲染、单程渲染、去抖动、Voronois 和线简化,作为追踪线系列的机制。并不是每个可视化都需要这么多的优化和高级技术,但是我们知道很多关于我们的数据和目标行为,所以我们能够按照我们想要的方式进行调整。
在构建我们的可视化时,我们大量使用了 react-vis 的一些特性,但是本文中讨论的思想适用于任何基于 web 的可视化框架。你可以很容易地用普通的 d3 、符号或者任何其他可用的可视化工具来实现这些技术。
如果你想看上下文中的代码,看看这个报告。如需更多高级示例,请查看 react-vis 文档的图表部分或我的一些个人作品,比如这个的,或者这个的,或者甚至是这个的。
快乐观想!
少数镜头学习的进展:一次有指导的旅行
Source: worldarchery.org/sites/defau…
少数镜头学习是目前机器学习的一个令人兴奋的领域。深度神经网络从大量数据集中提取复杂统计数据和学习高级特征的能力已经得到证明。然而,当前的深度学习方法存在样本效率低下的问题,这与人类的感知形成了鲜明对比——即使是孩子也能在看到一张图片后认出长颈鹿。微调预先训练的模型是实现高采样效率的一种流行策略,但这是一种事后手段。机器学习能做得更好吗?
少投学习旨在解决这些问题。在这篇文章中,我将通过深入研究三篇前沿论文来探索一些近期在少投学习方面的进展:
我将从简单解释 n-shot,k-way 分类任务开始,这些任务是少投学习的事实上的基准。
我已经在一个 Github 资源库 中转载了这些论文的主要结果。你可以查看 这篇文章 来了解我实施这项研究的经历。
n 镜头,k 路任务
一个算法执行少镜头学习的能力通常通过它在 n 镜头、k 路任务上的性能来衡量。它们的运行方式如下:
- 给模型一个查询样本,该样本属于一个新的、以前未见过的类
- 也给出了一个支持集, S ,由 n 个例子组成,每个例子来自 k 个不同的看不见的类
- 然后,该算法必须确定查询样本属于哪个支持集类
A 1-shot, 20-way task from the Omniglot dataset. The query sample is in top-center.
匹配网络
Vinyals et al.
虽然之前有很多关于深度学习的少量方法的研究,但 Matching Networks 是第一个对 n-shot,k-way 任务进行训练和测试的*。这种方法的吸引力很简单——对相同的任务进行训练和评估,让我们以端到端的方式优化目标任务。诸如暹罗网络的早期方法使用成对验证损失来执行度量学习,然后在单独的阶段使用学习的度量空间来执行最近邻分类。这不是最佳的,因为初始嵌入函数被训练成在不同的任务上最大化性能!然而,匹配网络将嵌入和分类结合起来,形成端到端的可微分最近邻 分类器。*
匹配网络首先将高维样本嵌入到低维空间中,然后执行由下面的等式描述的最近邻分类的一般化形式。
Equation (1) from Matching Networks
这意味着模型的预测 y^ 是支持集的标签 y_i 的加权和,其中权重是查询示例 x^和支持集样本 x_i 之间的成对相似性函数 a(x^,x_i】。该等式中的标签 y_i 是独热编码的标签向量。
注意,如果我们选择 a(x^,x_i) 作为与查询样本最接近的 k 个样本的 1/k ,否则我们恢复 k 最近邻算法。需要注意的关键点是,如果注意函数 a(x^,x_i) 是可微的,那么匹配网络是端到端可微的。
作者选择嵌入空间中简单的 softmax over cosine 相似度作为他们的注意函数 a(x,x_i)。他们用于少数镜头图像分类问题的嵌入函数是 CNN,它当然是可微分的,因此使得注意力和匹配网络完全可微分!这意味着用典型方法(如随机梯度下降法)端到端地拟合整个模型是很简单的。
Attention function used in the Matching Networks paper
在上面的等式中,c 表示余弦相似度,函数 f 和 g 分别是查询和支持集样本的嵌入函数。对该等式的另一种解释是,支持集是一种记忆形式,并且在看到新样本时,网络通过从该记忆中检索具有相似内容的样本的标签来生成预测。
有趣的是,支持集和查询集嵌入函数 f 和 g 不同的可能性是开放的,以便给予模型更多的灵活性。事实上,Vinyals 等人正是这样做的,并引入了全语境嵌入或简称为 FCE 的概念。
他们认为嵌入函数的短视本质是一个弱点,因为支持集 x_i 的每个元素被 g(x_i) 以独立于其余支持集和查询样本的方式嵌入。他们建议嵌入函数 f(x^) 和 g(x_i) 应该采用更一般的形式 f(x^,S) 和 g(x_i,S) 其中 S 是支撑集。这背后的原因是,如果两个支持集项目非常接近,例如,我们正在执行狗品种之间的细粒度分类,我们应该改变样本嵌入的方式,以增加这些样本的可分辨性。
在实践中,作者使用 LSTM 来计算支持的 FCE,然后注意使用另一个 LSTM 来修改查询样本的嵌入。这带来了可观的性能提升,但代价是引入了更多的计算,并且对支持集的任意排序也稍显乏味。
总之,这是一篇非常新颖的论文,它发展了完全可微神经邻居算法的思想。
原型网络
Class prototypes c_i and query sample x.
在原型网络中,Snell 等人以类原型的形式应用了引人注目的归纳偏差,以实现令人印象深刻的少数镜头性能——在没有 FCE 复杂性的情况下超过了匹配网络。作出的关键假设是存在嵌入,其中来自每个类别的样本围绕单个原型表示聚集,该原型表示简单地是单个样本的平均值。这个想法简化了 n > 1 的情况下的 n 镜头分类,因为分类是通过取最接近的类原型的标签来简单地执行的。
Equation (1) from Prototypical Networks — calculating class prototypes. S_k is the support set belonging to class k and f_phi is the embedding function.
本文的另一个贡献是在度量学习中使用欧几里德距离超过余弦距离的有说服力的理论论证,这也证明了使用类均值作为原型表示的合理性。关键是要认识到平方欧几里得距离(而不是余弦距离)是一种特殊的距离函数,称为 Bregman 散度。
考虑寻找一簇点的质心的聚类问题,使得质心和所有其他点之间的总距离最小化。已经证明如果你的距离函数是一个 Bregman 散度(比如平方欧几里德距离),那么满足这个条件的质心就是聚类的平均值——然而余弦距离不是这种情况!当将一组点表示为单个点时,该质心是使信息损失最小的点。
这种直觉得到了实验的支持,因为作者发现,通过从余弦到欧几里德距离的交换,质子和他们自己的匹配网络的实现都得到了全面的改善。
原型网络也服从于**零触发学习,**人们可以简单地直接从类的高级描述中学习类原型,比如带标签的属性或自然语言描述。一旦你做到了这一点,你就有可能把新的图片归类为一个特定的类别,而不必看那个类别的图片。在他们的实验中,他们只根据颜色、形状和羽毛图案等属性对鸟类图像进行零拍摄物种分类。
我非常喜欢这篇文章,因为它在本文中所有方法的典型基准测试中实现了最高的性能,同时也非常优雅,最容易复制。干得好斯内尔等人!
模型不可知的元学习(MAML)
芬恩等人采取了一种非常不同的方法来进行少量学习,通过学习一种可以快速适应新任务的网络初始化——这是一种形式的元学习或学习到学习。这种元学习的最终结果是一个模型,它可以在一个新任务上达到高性能,只需一个简单的常规梯度下降步骤。这种方法的高明之处在于,它不仅可以用于监督回归和分类问题,还可以用于使用任何可微分模型的强化学习!
Figure 1 from Model-Agnostic Meta-Learning. Theta represents the weights of the meta-learner. Gradient L_i are the losses for tasks, i, in a meta-batch and the starred theta_i are the optimal weights for each task.
MAML 不像大多数深度学习算法那样在批量样本上学习,而是在批量任务上学习,也称为元批量。对于元批处理中的每个任务,我们首先使用基本元学习者的权重初始化一个新的“快速模型”。然后,我们计算梯度,从而根据从该任务中抽取的样本更新参数,并更新快速模型的权重,即,对快速模型的权重执行典型的小批量随机梯度下降。
The weight update due to a single task T_i. Alpha is a learning rate hyperparameter.
在参数更新之后,我们从相同的任务中采样一些更多的看不见的样本,并计算元学习者的更新权重(又名快速模型)在任务中的损失。最后一步是通过从*更新后的权重中获取损失总和的梯度来更新元学习器的权重。*这个实际上是取梯度的梯度,因此是二阶更新——MAML 算法通过展开的训练过程进行微分。
Weight update for meta-learner. Beta is a learning rate hyperparameter and p(T) is the distribution of tasks.
这是关键的一步,因为这意味着我们在梯度步骤后优化基础车型的性能,也就是说,我们在优化快速简单的梯度下降。这样做的结果是,元学习者可以通过梯度下降在小至每类一个例子的数据集上进行训练,而不会过度拟合。
来自 OpenAI 的一篇后续论文提供了一些有价值的直觉,解释了为什么使用梯度更新的泰勒展开可以工作。他们得出的结论是,MAML 不仅最小化了任务分布的期望损失,而且最大化了同一任务的梯度更新之间的期望内积。因此,它是优化批次之间的一般化。
Results of a Taylor expansion analysis from “On First-Order Meta-Learning Algorithms” by Nichol et al.
上述方程组显示了 MAML 梯度的期望,一阶简化的 MAML (FOMAML)和爬虫,一阶元学习算法在同一篇论文中介绍。 AvgGrad 项代表任务损失,而 AvgGradInner 项代表概括项。注意,对于学习速率中的领先顺序α,所有算法都执行非常相似的更新,其中二阶 MAML 将最高权重放在一般化项上。
也许 MAML 的唯一缺点是二阶更新,因为计算损失的二阶导数是非常内存和计算密集型的。然而,一阶简化(例如 FOMAML 和爬虫)产生非常相似的性能,这暗示二阶更新可以用更新权重上的梯度来近似。
然而,高计算要求与模型不可知的元学习是一篇出色的论文,为机器学习开辟了令人兴奋的新道路这一事实无关。
少数镜头学习领域正在取得快速进展,尽管仍有许多有待学习,但我相信该领域的研究人员将继续缩小机器和人类在少数镜头学习这一挑战性任务上的表现之间的差距。我希望你喜欢阅读这篇文章。
我已经在一个 Github 资源库 中转载了这些论文的主要成果。如果你已经有了足够的概念,并且想要一些有趣的技术细节和代码,你可以查看 这篇文章 来了解我实施这项研究的经验。
少数镜头学习的进展:在 PyTorch 中再现结果
少镜头学习是机器学习的一个令人兴奋的领域,旨在缩小机器和人类在从少量样本中学习的挑战性任务中的差距。在我的上一篇文章中,我提供了三篇前沿论文的高度概括——我假设你已经读过,已经熟悉这些论文,或者你自己正在复制它们。
在这篇文章中,我将向您介绍我在 Omniglot 和 miniImageNet 数据集上复制这些论文的结果的经验,包括路上的一些陷阱和绊脚石。每篇论文都有自己的章节,在其中我提供了一个 Github gist 和 PyTorch 代码来对论文描述的模型执行单个参数更新。要训练模型,只需将该函数放入训练数据的循环中。为了简洁起见,省略了数据集处理等不太有趣的细节。
再现性非常重要,它是任何声称是科学的领域的基础。这让我相信,机器学习中代码共享和开源的盛行确实令人钦佩。虽然仅发布代码是不可复制的(因为可能存在实现错误),但它向公众开放了研究人员的方法,更重要的是加速了该领域其他人的研究。鉴于此,我要感谢这些论文的作者分享他们的代码,以及任何其他开源他们实现的人。
【github.com/oscarknagg/… 的 Github 回购
Things don’t always go to plan. Just see this training curve of a failed MAML implementation for example!
数据集
有两个图像数据集用于评估少镜头学习算法。第一个是 Omniglot 数据集,它包含 20 张图片,每张图片包含来自 50 个字母表的大约 1600 个字符。这些影像通常为 28x28 灰度,这也是该数据集通常被称为 MNIST 转置的原因之一。
Samples from the Omniglot dataset.
第二个是 miniImageNet 数据集,它是 ImageNet 的一个子集,旨在成为一个更具挑战性的基准,而不像完整的 ImageNet 数据集那样繁琐。miniImageNet 由 60,000 张 84x84 的 RGB 图像组成,每类 600 张图像。
Samples from the miniImageNet dataset before taking center crop and resizing to 84x84
在这两种情况下,训练集和验证集中的类是不相交的。我没有使用与原始论文相同的培训和验证拆分,因为我的目标是不要将它们复制到最后一分钟的细节。
匹配网络
在匹配网络中,Vinyals 等人引入了一种完全可微分的最近邻分类器的概念,这种分类器既经过训练又经过了少量任务的测试。
匹配网络算法可以总结如下:
- 首先,使用编码器网络(本例中为 4 层 CNN)嵌入所有样本(查询和支持集)。这是由 model.encode()执行的(第 41 行)。
- 可选地计算完整的上下文嵌入(FCE)。考虑到支持集,LSTM 将原始嵌入作为输入,并输出修改的嵌入。这是由 model.f()和 model.g()执行的(第 62 和 67 行)。
- 计算查询样本和支持集之间的成对距离,并使用 softmax 进行归一化(第 69 到 77 行)
- 通过用标准化的距离对支持集标签进行加权平均来计算预测(第 83–89 行)
一些需要注意的事项:
- 在这个例子中, x 张量首先包含支持集样本,然后是查询。对于 Omniglot,它将具有 shape (n_support + n_query,1,28,28)
- 前一篇文章中的数学是针对一个查询样本的,但实际上匹配网络是用一批大小为 q_queries * k_way 的查询样本训练的
我无法使用余弦距离复制这篇论文的结果,但当使用 l2 距离时却成功了。我相信这是因为余弦距离被限制在-1 和 1 之间,这就限制了注意力函数( a(x^,x_i) 下面)可以指向支持集中的特定样本的数量。由于余弦距离是有界的 a(x^,x_i) 永远不会接近 1!在 5 路分类的情况下, a(x^,x_i) 的最大可能值是exp(1)/(exp(1)+4 * exp(-1))≈0.65。当使用余弦距离时,这导致非常慢的收敛。
我认为有可能使用余弦距离来重现结果,或者使用更长的训练时间,更好的超参数,或者像余弦距离乘以常数因子这样的启发式方法。鉴于距离的选择不是论文的关键,使用 l2 距离的结果非常好,我决定省去调试工作。
原型网络
在原型网络中,Snell 等人使用由 Bregman 发散理论激发的引人注目的归纳偏差来实现令人印象深刻的少数镜头性能。
原型网络算法可以总结如下:
- 嵌入所有查询和支持示例(第 36 行)
- 计算类原型,取每个类嵌入的平均值(第 48 行)
- 预测是查询样本和类原型之间距离的软最大值(第 63 行)
我发现这篇论文非常容易复制,因为作者提供了全套的超参数。因此,在 Omniglot 基准测试中,我可以轻松地实现大约 0.2%的性能,在 miniImageNet 基准测试中,可以实现几%的性能,而不需要我自己进行任何调整。
元不可知元学习(MAML)
在中,MAML 芬恩等人介绍了一种强大且广泛适用的元学习算法,来学习一种能够快速适应新任务的网络初始化。在本文的三篇文章中,这篇文章是最难也是最值得复制的。
MAML 算法可以总结如下:
- 对于元批量任务中的每个 n-shot 任务,使用基本模型的权重创建一个新模型,也就是元学习者(第 79 行)
- 通过随机梯度下降,使用任务中样本的损失更新新模型的权重(第 81–92 行)
- 计算同一任务中更多数据的更新模型的损失(第 94-97 行)
- 如果执行一阶 MAML,用来自第 3 部分的损失梯度更新元学习器权重。如果执行二阶 MAML,计算该损失相对于原始权重的导数(第 110+行)
PyTorch 最大的吸引力在于它的亲笔签名系统。这是一段神奇的代码,记录了对火炬的操作。Tensor 对象,动态构建这些操作的有向无环图。反向传播就像调用*一样简单。*在最终结果上倒退()。为了计算和应用元学习者的参数更新,我不得不学习更多关于这个系统的知识,现在我将与你分享。
一阶 MAML —梯度交换
通常,在 PyTorch 中训练模型时,您会创建一个与特定模型的参数相关联的优化器对象。
from torch.optim import Adam
opt = Adam(model.parameters(), lr=0.001)
当调用 opt.step() 时,优化器读取模型参数的梯度,并计算这些参数的更新。然而,在一阶 MAML 中,我们将使用一个模型(快速权重)计算梯度,并将更新应用于不同的模型,即元学习者。
对此的解决方案是以 torch 的形式使用 PyTorch 的一个未充分利用的功能。Tensor.register_hook(钩子)。注册一个钩子函数到一个张量,这个钩子函数将在计算这个张量的梯度时被调用。对于元学习器中的每个参数张量,我注册了一个钩子,该钩子简单地将梯度替换为快速权重上的相应梯度(gist 中的第 111–129 行)。这意味着当 opt.step() 被调用时,快速模型的梯度将用于根据需要更新元学习器权重。
二阶 MAML-亲笔签名的问题
当我第一次尝试实现 MAML 时,我实例化了一个新的模型对象(torch.nn.Module 的子类)并将它的权重值设置为元学习者的权重。然而,这使得不可能执行二阶 MAML,因为在火炬的眼中,快速模型的权重与元学习者的权重是分离的。这意味着当我调用optimizer . step()(要点中的第 140 行)时,元学习者权重的自动签名图是空的,没有执行更新。
# This didn't work, meta_learner weights remain unchanged
meta_learner = ModelClass()
opt = Adam(meta_learner.parameters(), lr=0.001)task_losses = []
for x, y in meta_batch:
fast_model = ModelClass()
# torch.autograd loses reference here!
copy_weights(from=meta_learner, to=fast_model)
task_losses.append(update_with_batch(x, y))meta_batch_loss = torch.stack(task_losses).mean()
meta_batch_loss.backward()
opt.step()
这个问题的解决方案是 functional_forward() (第 17 行),这是一个有点笨拙的方法,它使用 torch.nn.functional 手动执行与模型类相同的操作(卷积、最大池等)。这也意味着我必须手动执行快速模型的参数更新。其结果是torch . autograded知道将梯度反向传播到元学习者的原始权重。这导致了一个惊人的大签名图。
PyTorch autograd graph for 1st order MAML (left) and 2nd order MAML (right) with one inner training step. You can probably see why 2nd order MAML has much higher memory requirements!
然而,二阶 MAML 是一个比这更棘手的野兽。当我第一次写我的二阶 MAML 实现时,我认为我第一次尝试就奇迹般地完成了所有的工作。至少没有例外,对吗?只有在运行了全套 Omniglot 和 miniImageNet 实验后,我才开始怀疑我的工作——结果与一阶 MAML 太相似了。这是一种典型的无声 ML 错误,它不会导致异常,只会在模型的最终表现中显现出来。
因此,我决定全力以赴,编写一个单元测试,以确认我确实在执行二阶更新。声明:本着真正的测试驱动开发的精神,我应该在运行任何实验之前编写这个测试。事实证明我并不完美😛。
我决定进行的测试是在一个虚拟模型上运行 meta_gradient_step 函数,并手动解析自动签名的图,计算两次反向操作的次数。这样,我可以绝对肯定,我正在执行二阶更新时,需要的。相反,我能够测试我的一阶 MAML 实现只执行一阶更新,没有双重反向操作。
我最终找到了没有在内部训练循环中应用 create_graph 参数的错误(第 86 行)。然而,我保留了查询样本上的损失的签名图(第 97 行),但是这不足以执行二阶更新,因为展开的训练图没有被创建。
训练时间相当长(5 路 5 次拍摄的 miniImageNet 实验超过 24 小时),但最终我相当成功地再现了结果。
我希望你能从这次技术性的深潜中学到一些有用的东西。如果你有任何问题,请在评论中告诉我。
如果您想深入了解,请查看在【https://github.com/oscarknagg/few-shot】的完整实现
大(乱)数据中的冒险:通过客户同理心赢得机器学习工作的工具
Image from Pixabay
数据挑战
数据被比作石油,因为它是机器学习模型的“燃料”。就像发动机一样,算法依赖于燃料输送系统和大量经过适当提炼的燃料来工作。如果燃料没有经过适当的提炼,它就会分解(曾经意外地将柴油泵入无铅油箱吗?)或燃油管路是否损坏。类似地,机器学习模型需要一个适当的系统来传递经过适当清理和准备的数据。
内燃机并不是简单地一次燃烧掉油箱里的所有燃料,而是在每一个给定的时刻吸入运行机器所需的燃料,直到没有剩余的燃料。发动机的效率越高,用同样多的燃料就能做更多的事情。同样,我们应该尽最大努力创造尽可能高效的算法。通常,这意味着改进数据架构和数据本身要付出与模型所需一样多或更多的努力。
假设你是一家人工智能产品和/或服务公司。你有一个由数据科学家、工程师和架构师组成的精英团队来构建算法、数据管道和数据仓库。您甚至拥有主题专业知识来帮助告知产品的使用案例,从而让您的客户生活得更好和/或增加他们的销售额。你没有的是[可用]数据。
数据科学和人工智能领域的专家哀叹道,缺乏高质量的数据是这个领域面临的一个紧迫的挑战。为了训练和测试你的模型,你可以从(某些)网站搜集数据,寻找公共数据集,甚至创建一个合成数据集。但是这些选择可能会因为许多原因而失败:
- 公共数据集可能缺少解决问题所需的功能
- 在许多网站上,抓取数据经常受到限制
- 收集的数据可能无法组成一个完整的数据集
- 你的团队可能不知道如何产生合成数据
- 创造完全模拟现实的合成数据可能是不可能的
通常,客户拥有您正在寻找的数据。有时候也没那么糟糕。大多数时候,都很糟糕。几乎都是无标签的。它总是需要数据管理来为你的机器学习模型做准备。让您的工作更加复杂的是,客户可能会出于各种原因拒绝共享数据(即使有保密协议),其中最重要的是他们认为自己的数据很有价值。
这很有可能。但是还没有人真正知道。您和客户都需要回答的问题是,“我们如何知道数据的价值,以及解决方案的价值?”
如果数据就像石油,只有在土地被勘测后,钻探才有价值。如果你想钻探石油,你肯定会在安装钻机之前首先考虑当地的环境。同样,AI 公司应该了解一个客户的环境。技术和进步是公司愿景的一部分,还是对新流程和变革有相当大的阻力?目前存在什么样的依赖和架构?如果环境看起来适合人工智能,那么你就采集数据样本。
客户经常要求看看我们能用他们的一小部分数据做些什么。例如,他们可能会提供一个从客户关系管理(CRM)平台查询的几个月的表。这是一个很好的学习机会:
- 数据的状态
- 数据的特征*
- 客户对自己数据的理解
- 客户用来获取和访问其数据的过程
- 他们存储数据的位置和方式
- 您的客户如何为最终用户服务
如果您客户的数据看起来有足够的功能,并且在数据仓库中得到很好的维护,那么您将有可能继续讨论能够带来最大价值的人工智能用例(更多信息请参见“为客户带来效用和乐趣的工具”)。
俗话说“一知半解是件危险的事”。我在这里强调“小”,因为一个更大的整体的一部分可能是欺骗性的。当客户提供数据样本时,会出现一些挑战,例如:
- 客户不知道人工智能能做什么
- 客户不了解其“原样”数据的局限性
- *数据可能被错误地查询,给出了可用于分析的要素的不完整图像
- 他们必须使他们的过程现代化,否则人工智能将根本无法帮助他们
在我与中型企业合作的经验中,数据样本的分析常常需要回到最初的工作环境(特别是数据收集和存储方法)。
那么,你如何管理期望,同时让客户对机器学习的力量感到兴奋呢?
面向客户的数据科学家可以将这部分工作视为获取正确数据的“床边方式”。一个有用的方法是向他们展示哪些数据现在可能有用,以及你从这些数据中学到了什么。然后展示如果他们调整方法可以做些什么。你越能分解检修遗留系统的过程,就越好。
坏例子:“买贵的,训练大家用。”
更好的例子:“从你的数据中,我们发现这个部门可能有一种让事情变得缓慢的趋势。为了进一步调查,我们需要收集尽可能多的与这一趋势相关的数据。你有 XYZ 特征的数据吗?这就是它们如何帮助我们做出更好的预测。它们可能存储在另一个系统上。如果是这样的话,这就是整合它们所需要的,而且成本可能会很高。您是否考虑过更新您的存储和收集方法?要不要我帮你联系几个合作伙伴?”
为客户服务和取悦客户的工具(阅读:不仅仅是 UX 团队的工作!)
当谈到人工智能解决方案时,大多数客户希望在给出数据样本后立即看到一系列令人印象深刻的见解。因此,传达可以对数据(在其当前状态下)做什么,同时从您的客户那里了解应该做什么可能会特别困难。**
假设你还没有见到你的客户本人。给你的只是企业名称和一个小的数据集。你将很快被安排与他们谈论人工智能能为他们做什么。
对于任何声称以解决方案为导向的公司来说,一个潜在的危险是“金锤”,或者试图用同一种工具解决所有问题的倾向。最好是花时间评估情况,考虑解决问题的各种选择,即使我们大多数时候最终使用的是我们最熟悉的工具。
通过对公司业务和用户的深入了解,表现出为客户服务的真诚愿望。记住一般的想法,分析数据样本。在这第一步中,你的目标应该是利用你所拥有的数据找到尽可能多的用例。你拥有的数据越丰富,你可能发现的模式就越多,机会也就越多。就当是用数据头脑风暴吧。
呈现这种数据集思广益会议的一种方式是修改经典的“特性和优点”两栏表,这是一种基本的营销工具。单独来看,“特性和优点”很好地展示了您可以构建什么以及为什么要构建,但是它并没有说明如何构建。
改编显示了什么是可能的(特性),它提供了什么好处(好处),并添加了一个解释是什么需要使它发生(我们需要什么)。
客户将通过一系列“痛点”来讨论人工智能用例,然后面临的挑战是找出:(1)您的公司是否能够足够好地理解这些“痛点”来解决它们,以及(2)数据/架构是否足以支持解决方案。
如果您在对话中列出可以利用这些数据完成的事情,您就可以洞察哪些对客户来说是最有用的*,同时*告知他们可能没有意识到的其他用例。此外,通过展示“我们需要什么”,你向客户提供了关于需要什么来提炼他们的数据以推动每个人工智能解决方案的宝贵信息。
客户同理心不仅仅是推动机器学习模型,而是看什么真正有利于公司。以客户为中心的人工智能公司识别所有帮助客户变得更好的机会(包括那些人工智能公司可能不起作用的情况):
- 人工智能机会——您的人工智能公司在这方面表现出色。
- 数据机会—客户可能不会立即为您的解决方案做好准备,但这是向客户展示如何改善其数据状态的绝佳机会。如果他们工作得很快,你已经把他们变成了未来的一个可行的线索。(你认为他们会先给谁打电话?)
- 流程机会——如果你是一家人工智能产品/服务公司,你可能没有这方面的内部专业知识。准备好提供指导,告诉他们在这个过程中可以去哪里工作。顺利移交给合作伙伴的奖励积分。
人工智能团队必须表现出和 UX 团队一样的关注,提供具有最大效用和客户满意度的解决方案。它需要理解顾客的需求,创造性地仔细思考下一步的正确行动。像定制的“功能和优势”图表这样的工具,以及快速高效的数据样本分析系统,让你的人工智能解决方案感觉像是白手套体验,而不是争论一大堆数据。
针对强化学习代理的对抗性攻击
TWiML Talk 119
在这一集里,我和谷歌大脑的研究人员科学家伊恩·古德菲勒以及加州大学伯克利分校 EECS 系的博士生黄裕景一起讨论他们在《对神经网络政策的对抗性攻击》一文中的工作。
订阅:iTunes/SoundCloud/Google Play/Stitcher/RSS
如果你是这里的一名普通听众,你可能听说过敌对攻击,并见过基于深度学习的物体检测器的例子,例如,通过向图像中注入一些察觉不到的噪声,长颈鹿实际上是一辆校车。嗯,桑迪和伊恩的论文位于对抗性攻击和强化学习的交汇点,这是我们在播客中讨论了很多的另一个领域。在他们的论文中,他们描述了对抗性攻击如何在强化学习中有效地针对神经网络策略。Sandy 向我们概述了这篇论文,包括改变单个像素值如何影响训练来玩 Atari 游戏的模型的性能。我们还涵盖了许多有趣的主题,分别涉及对抗性攻击和学习力,以及一些相关领域,如等级奖励函数和迁移学习。这是一次很棒的谈话,我真的很高兴能带给你!
TWiML 在线会议更新
我想向本周早些时候参加 TWiML 在线聚会的每一个人大声欢呼。在我们的社区部分,我们就冷冻大脑(如果你错过了那家初创公司的公告,你可能不知道我在说什么)、医疗保健领域的 ML 和 AI 等问题进行了非常有趣和广泛的讨论。社区成员尼古拉斯·teague,在 twitter 上使用了 @NicT ,他也简要介绍了他的文章“一个蹒跚学步的孩子学会说话”,在这篇文章中,他探索了机器学习中不同模式之间的联系。最后,衷心感谢 Sean Devlin,他对深度强化学习和 Google DeepMind 在该领域的开创性论文进行了深入探讨。查看下个月在 twimlai.com/meetup聚会的视频记录和细节。
和我一起参加人工智能峰会
你是一名需要在企业中广泛的机器学习和人工智能机会上变得聪明的 IT、技术或业务领导者吗?或者,也许你组织中的某个人可以从这方面的提升中受益?(或者,也许你会从他们的升级中受益!)如果这听起来像你或你认识的人,你可能会对我即将举行的人工智能峰会感兴趣。
把这个活动想象成一个为期两天的机器学习和人工智能的技术 MBA。你会清楚地了解:
机器学习和深度学习如何工作(不需要数学知识) 如何在您的组织中识别机器学习和深度学习机会 如何理解和利用计算机视觉和自然语言处理等技术 如何管理和标记数据以利用 ML 和 AI 以及如何建立 AI 优先的文化,并在您的业务中实施 AI。
你将对整个人工智能和人工智能领域正在发生的事情有一个知情的观点,并将能够自信地与你的同事、客户和合作伙伴讨论机器学习和人工智能。我对这次活动和演讲者感到非常兴奋,你们将有机会向他们学习。欲了解更多信息,请访问twimlai.com/aisummit,如有疑问,请随时联系我。
关于伊恩
关于桑迪
采访中提到
- 论文——对神经网络策略的对抗性攻击
- 论文——探究可转移的示例
- VGGNet
- 纸— BADnet
- NPM 图书馆的故事
- 悬赏黑客
- 黑斑羚— DeepMind
- 论文—等级奖励—深度思维
- 论文—鲁棒对抗性强化学习
- 古德哈特定律
- 在这里报名参加人工智能大会!
- 查看@ShirinGlander 的伟大 TWiML 草图!
- TWiML 呈现:系列页面
- TWiML 事件页面
- TWiML Meetup
- TWiML 简讯
“稍后再谈”作者 Lee Rosevere 经 CC 4.0 授权
原载于 2018 年 3 月 15 日【twimlai.com。
深度学习中的对立例子
这篇文章将包含与我在上次深度学习会议上的演讲基本相同的信息。我觉得随着越来越多的领域开始在关键系统中使用深度学习,让人们意识到神经网络如何被愚弄以产生奇怪和潜在危险的行为是很重要的。这篇文章的目标不是尽可能精确和详尽,而是让你对对立的例子有一个基本的了解,并希望让你对现代深度学习的一个问题敏感起来。
这篇博文和更多关于机器学习安全的信息可以在以下地址获得:【mlsecurity.ai/blog。
在开始这篇文章之前,我还想提一下,我不是做这项工作的研究人员的一部分。我只是一个非常好奇的人,来自 fast.ai MOOC,对深度学习充满热情。
首先,什么是对立的例子?
一个相反的例子是输入数据的样本,该样本已经被非常轻微地修改,其修改方式旨在导致机器学习对其进行错误分类。
一个例子应该有助于巩固这个想法。
An image classified as “suit” by the VGG16 neural network (left), a perturbation created specifically using the image on the left (middle) and the resulting perturbed image classified as a wig (right).
在这个图中,我们可以看到扰动图像(最右边)的分类显然是荒谬的。我们还可以注意到,原始图像和修改后的图像之间的差异非常微小 。
有了像“加州终于为真正的无人驾驶汽车做好准备了”或“五角大楼的‘终结者难题’:会自己杀人的机器人”这样的文章,应用对抗性的例子并不难找到……
在这篇文章中,我将首先解释这些图像是如何被创造出来的,然后讨论已经发表的主要观点。更多细节和更严谨的信息,请参考参考的研究论文。
首先,快速提醒一下梯度下降。梯度下降是一种优化算法,用于寻找可微函数的局部最小值。
A curve and a tangent to this curve.
在左图中,你可以看到一条简单的曲线。假设我们想要找到一个局部最小值(一个 x 的值,其中 f(x) 是局部最小值)。
梯度下降包括以下步骤:首先为 x,选择一个初始值,然后根据 x 计算 f 的导数f’,并为我们的初始猜测进行评估。 f'(x) 是曲线在 x 处切线的斜率根据这个斜率的符号,我们就知道是要增加还是减少 x 才能使 f(x) 减少。在左边的例子中,斜率是负的,所以我们应该增加 x 的值,使 f(x) 减小。由于切线是曲线在微小邻域内的良好近似,应用于 x 的值变化非常小,以确保我们不会跳得太远。
现在,我们可以使用这种算法来训练机器学习模型。
A set of data points and a linear model initialized randomly.
假设我们有一组点,我们想找到一条线,它是这些值的合理近似值。
我们的机器学习模型将是直线 y = ax + b ,模型参数将是 a 和 b 。
现在使用梯度下降,我们要定义一个函数,我们要找到一个局部最小值。这是我们的损失函数。
这个损失取一个数据点 x ,它对应的值 y 和模型参数 a 和 b 。损失是真实值 y 和 *ax + b,*我们模型的预测的平方差。实际值和预测值之间的差异越大,损失函数值就越大。凭直觉,我们选择平方运算来惩罚真实值和预测值之间的大差异,而不是小差异。
现在我们根据模型 a 和 b 的参数计算我们的函数 L 的导数。
如前所述,我们可以用每个数据点 (x,y) 的 a 和 b 的当前值来评估该导数,这将给出损失函数切线的斜率,并使用这些斜率来更新 a 和 b ,以便最小化l
好的,这很酷,但这不是我们要如何产生对立的例子…
事实上,这正是我们要做的。假设现在模型是固定的(你不能改变 a 和 b ,你想增加损失的价值。唯一需要修改的是数据点 (x,y) 。由于修改 y s 实际上没有意义,我们将修改 xs。
我们可以用随机值代替 x,损失值会增加很多,但这并不微妙,特别是,对于绘制数据点的人来说,这是非常明显的。为了使我们的变化不被观察者明显察觉,我们将根据 x. 计算损失函数的导数
现在,就像以前一样,我们可以在我们的数据点上计算这个导数,获得切线的斜率,并相应地少量更新 x 值。损失将会增加,并且由于我们正在少量修改所有点,我们的扰动将很难被检测到。
嗯,这是一个非常简单的模型,我们刚刚弄乱了,深度学习要复杂得多…
你猜怎么着?不是的。我们刚刚做的一切在深度学习的世界里都有直接的对等物。当我们训练神经网络来分类图像时,损失函数通常是分类交叉熵,模型参数是网络的权重,输入是图像的像素值。
对抗样本生成的基本算法,称为快速梯度符号法(来自本文),正是我上面描述的。让我们解释一下,并在一个例子上运行它。
设 x 为原图像, y 为 x 的类, θ 为网络的权值, L(θ,x,y) 为用于训练网络的损失函数。
首先,我们根据输入像素计算损失函数的梯度。∇算子是一种简洁的数学方法,它根据函数的许多参数来计算函数的导数。你可以把它想象成一个形状矩阵*【宽度,高度,通道】*,包含切线的斜率。
和以前一样,我们只对斜率的符号感兴趣,以了解我们是想增加还是减少像素值。我们将这些符号乘以一个非常小的值 ε ,以确保我们不会在损失函数表面上走得太远,并且扰动是察觉不到的。这将是我们的摄动。
我们的最终图像就是我们添加了扰动 η的原始图像。
让我们在一个例子上运行它:
FGSM applied to an image. The original is classified as ‘king penguin’ with 100% confidence and the perturbed one is classified as ‘tripod’ with 71% confidence.
能够使用目标模型计算梯度的攻击系列被称为白盒攻击。
现在你可以告诉我,我刚才提出的攻击并不真实,因为你不太可能获得自动驾驶汽车上损失函数的梯度。研究人员想到了完全相同的事情,在的这篇论文中,他们找到了一种处理方法。
在更现实的情况下,您可能想要攻击只能访问其输出的系统。这样做的问题是,你将无法再应用 FGSM 算法,因为你将无法访问网络本身。
提出的解决方案是训练新的神经网络*M’来解决与目标模型 M 相同的分类任务。然后,当M’*被训练后,使用 FGSM 使用它来生成对立样本(我们现在可以这样做,因为它是我们自己的网络),并要求 M 对它们进行分类。
**他们发现 M 会经常错误分类使用*M’**生成的对立样本。此外,如果我们无法获得针对M’*的适当训练集,我们可以使用 M 预测作为真值来构建一个训练集。作者称之为合成输入。这是他们文章的节选,在文章中他们描述了他们对他们无法访问的 MetaMind 网络的攻击:
“在标记了 6400 个合成输入来训练我们的替代品(比 MetaMind 使用的训练集小一个数量级)后,我们发现他们的 DNN 对用我们的替代品制作的敌对例子的错误分类率为 84.24%”。
这种攻击被称为黑盒攻击,因为你把目标模型看成一个黑盒。
因此,即使攻击者没有访问模型内部的权限,他仍然可以产生对抗性的样本来欺骗它,但是这种攻击环境也是不现实的。在真实场景中,攻击者不被允许提供自己的图像文件,神经网络会将相机照片作为输入。这就是本文的作者试图解决的问题。
他们注意到,当你打印已经用足够高的 ε 生成的对立样本,然后对该打印进行拍照并分类时,神经网络仍然在相当大的时间里被愚弄。作者录制了一段视频来展示他们的成果:
Adversarial example in the physical world.
“我们使用手机摄像头拍摄的图像作为 Inception v3 图像分类神经网络的输入。我们表明,在这样的设置中,使用原始网络制作的敌对图像的很大一部分被错误分类为 ,即使当通过摄像机 输入分类器时也是如此。”
既然现实环境中的潜在攻击似乎是合理的,那么让我们回顾一些防御策略。
当试图为对立的例子辩护时,想到的第一个想法通常是生成大量的例子,并以这些图像和正确的类为目标在网络上运行更多的训练通道。这种策略被称为对抗性训练。
虽然这种策略提高了对 FGSM 攻击的鲁棒性,但它有多个缺点:
- 它无助于对抗更复杂的白盒攻击,如 RAND+FGSM ,正如文章中所解释的,我们不能用它来对抗训练网络。
- 它也无助于对抗黑盒攻击。
这最后一点很令人惊讶,但却是真实的,在许多情况下都观察到了。这种行为的原因在本文中探讨。正当我写这篇文章时,我们不知道如何完美地进行适当的白盒防御。正如作者指出的那样,经过对抗性训练的网络仍然容易受到黑盒攻击,这一事实在介绍新防御策略的文章中往往没有考虑到。
虽然白盒防御似乎是一个困难的问题,但攻击者可以访问模型权重的假设是很大的。在这篇论文中,研究人员试图创造出对黑盒攻击具有鲁棒性的网络。
由于经过对抗训练的网络仍然容易受到黑盒攻击,作者提出了集合对抗训练,这是一种策略,它包括使用来自其他模型集合(通常为 2 到 5 个)的修改样本来对抗训练一个模型。例如,他们训练一个模型,使用其他 5 个预训练模型制作的对立例子对 MNIST 数字进行分类。对于黑盒攻击,错误率从对抗训练模型的 15.5%到整体对抗训练模型的 3.9%。
这种算法是迄今为止黑盒防御中最好的。
作为对辩护部分的总结,我将引用 I. Goodfellow 和 N. Papernot 的一篇博文:
“到目前为止,大多数针对对抗性例子的防御措施都没有很好地发挥作用,但那些发挥作用的措施却没有适应性。这意味着这就像他们在玩打地鼠游戏:他们关闭一些漏洞,但让其他漏洞保持开放。”
我希望你喜欢阅读这篇博文。如果你注意到任何拼写或数学错误,不要犹豫留下评论。
敌对预测网络
作者:Lukasz Burzawa、Abhishek Chaurasia 和 Eugenio culrciello
我们想测试像 [CortexNet](engineering.purdue.edu/elab/Cortex…) 这样的预测性神经网络将从同时训练中受益的想法:
1-预测视频中的未来帧
2-使用对抗性训练来区分视频中的真实帧和网络生成的帧
我们称之为对抗性预测训练。这个想法是改进 CortexNet 的能力,在更多的未标记数据上进行预训练,然后只使用少量的标记数据。
我们以这种方式修改了我们的新型神经网络:
我们添加了一个分类器 C 来预测伪生成帧和真实生成帧。我们的网络鉴别器或编码器 D 类似于标准的多层神经网络,因此我们将分类器 C 放置在所有绿色层之后。蓝色生成层或解码器层对于重建未来的图像或表示是有用的。更详细的是这里。
为了进行培训,我们采用以下步骤:
1-我们训练网络来预测下一帧,就像在常规的 [CortexNet](engineering.purdue.edu/elab/Cortex…) 中一样
2-一旦网络可以生成合适的未来帧,我们训练分类器 C 来预测输入是真实的下一帧还是生成的下一帧
我们在每个训练步骤中按顺序运行步骤 1、2。
这些是 G 和 D 模块的详细信息:
D, G blocks in detail
我们在 conv 和 ReLU 之间使用批量标准化。
**结果:**使用 KTH 数据集,我们用上述对抗性预测方法对网络进行预训练,然后通过冻结生成器的网络,使用 10%的数据来训练分类器 C。
CASE 1
CASE 2
案例 1 :我们用 10%的数据训练整个网络。我们得到了 60.43%的最高测试准确率
案例 2 :我们对 100%的数据使用了对抗性预测训练(假/真,也预测下一帧),然后对 10%的数据进行了网络微调。我们得到了 53.33%的最高测试准确率
CASE 3
案例 3 :我们只对 100%的数据使用预测训练(预测下一帧,作为原始 CortexNet),然后对 10%的数据微调网络。我们得到了最高 71.98%的测试准确率
结论:如你所见,我们期望案例 2 比案例 3 更好。但这并没有发生: (53 对 71% —案例 2 对 3)。我们的结论是,对抗性预测训练在训练关于假/真分类的分类器和整个网络的预测能力之间产生冲突。
对 33%(62%对 79% —案例 2 对 3)和 50% (71%对 81% —案例 2 对 3)的数据进行预训练,而不是只对 10%的数据进行预训练,并没有改变这种情况,而且使用更多的数据无论如何都无法达到对未标记数据进行预训练的目的…
关于作者
我在硬件和软件方面都有将近 20 年的神经网络经验(一个罕见的组合)。在这里看关于我:媒介、网页、学者、 LinkedIn 等等…
捐款
如果你觉得这篇文章有用,请考虑捐赠来支持更多的教程和博客。任何贡献都能有所作为!
在数据科学领域找工作的建议:在就业市场学到的 10 个教训
这是我计划撰写的一系列帖子的第一篇,我希望这些帖子能够帮助其他人做出正确的决定,在数据科学领域找到一份工作。在任何领域就业都有许多因素,其中许多因素都是主观的,所以要努力从多种渠道获取意见。不可避免地会有人,其中一些会比我更有经验,会不同意我的一些观点。尽管如此,我还是希望我的建议对许多人有用,因为大部分建议都来自个人经验。
第一篇文章实际上来自我在 2017 年 1 月为一家名为 Pivigo 的公司写的一篇博文。它描述了我在 2016 年 9 月完成 Pivigo 的数据科学训练营“科学到数据科学”(S2DS)后,在找工作时学到的东西。我将在未来的帖子中写一篇关于我在 S2DS 上的时间的文章,但简而言之,我强烈推荐它,如果你想了解更多关于数据科学训练营计划的信息,请查看他们的网站:【www.s2ds.org】T2
总之,我说够了。以下是我去年一月的博客(最初贴在这里)。
原始帖子
参加 S2DS 研讨会的最大好处之一是增加了我的就业能力。我脑子里盘旋着许多问题:S2DS 毕业后的就业率是多少?找工作需要多长时间?这是得到数据科学工作的最好方法吗?……………….这样的例子不胜枚举。然而,不可避免的一个方面,我没有问太多细节,是实际的求职。
就业市场可能是一个令人望而生畏且无情的地方,尤其是当你第一次去那里的时候。对许多人来说,找工作是职业生涯中最糟糕的部分。但它可以塑造性格,教会你很多关于自己的事情,最重要的是,当你最终找到一份合适的工作时,它会给你带来难以置信的回报。是啊!当你找到合适的工作。
我对就业市场的尝试持续了 3 个月,在这段时间里,我有了许多与找工作相关的典型经历;拒绝、挫折、压力等。这不是一件容易的事情。看着别人在很棒的地方找到工作,我的自尊心也受到了一定程度的打击,因为我想“为什么不是我呢?我真的不够好吗?”
然而,并非一切都像看上去那么糟糕。我没有失业。我在牛津大学有一个博士后的职位,在我找到工作之前,我一直没有时间。通过我在 S2DS 建立的联系,我有一个很大的支持网络,我似乎总是有至少一个面试机会。在这种时候,关注积极的一面绝对是个好主意。总的来说,我意识到我其实很幸运。
考虑到这些,我想分享一些我在寻找合适的数据科学工作时学到的经验。我希望这能帮助那些正在寻找或将要开始寻找数据科学(或实际上任何)领域工作的人。我还必须加上一个强制性的“这份清单绝非详尽无遗”限定词。
我们开始吧:
1)网络!!!我知道人们说这很重要,但让我这么说吧:我申请的每家公司都拒绝了我,其中只有一家通知了我。然而,我收到的四份工作邀请中的三份,一份来自一位朋友的推荐,另外两份是在雇主找到我之后,因为他们看到我在一次聚会上做 S2DS 演示。这就是第一课的原因!
更新你的 LinkedIn 个人资料 雇主会看的。甚至在我上 S2DS 数据科学课程的时候,在我提出任何申请之前,在我认为我正式进入市场之前,雇主们就在寻找。因此,请确保您的在线个人资料/状态是最新且合适的。如果你没有名片,这是一个不错的选择。
3)了解你想要的角色类型 数据科学是一个非常宽泛的术语,用于涵盖多种角色。人们往往希望更适合业务分析师或软件工程师的工作规范被贴上“数据科学家”的标签。知道你想成为什么样的“数据科学家”将有助于你筛选出你不喜欢的工作规范,并让你在面试中提出更具体的问题。
准备你想问的问题招聘人员和雇主通常会在谈话或面试结束时问你是否有问题要问。准备好问题向面试官表明你感兴趣。相信我,当你只能说“对不起,我现在没有任何问题要问你”的时候,感觉很垃圾
脸皮厚一点在得到你想要的工作之前,你可能要花很多时间,而且在得到你想要的工作之前,你可能要经历很多拒绝。别往心里去。找出你可以改进的地方,然后继续前进。就业市场可能是无情的。
诚实在简历和面试中保持诚实会让生活变得容易得多。当你知道雇主对你的实际经验感兴趣时,你可以更放松地去参加面试。他们似乎也能接受自我意识,理解我的局限所在。
7)不要低估自己 从技术上来说,你很可能已经够资格成为一名数据科学家,因此你需要像数据科学家一样重视自己。我的第一份工作来自一家公司,该公司给我提供了一个职位,工资低于数据科学家的市场价值,他们将让我参加一个研究生计划,因为我被认为缺乏经验。两个月过去了,我得到了一个数据科学家的职位,这个职位的市场价值比我这个级别的数据科学家高。这也超过了任何招聘人员所说的我应该重视的程度。不要妄自菲薄!
做好坦率提问的准备他们来了。“你期望的薪水是多少?”,“你对我们公司有什么顾虑?”“是什么让你选择我们而不是其他公司?”第一个问题是每个给我工作机会的公司都会问我的。当我处于幸运(但有时令人沮丧)的情况下,其他公司知道我有多个工作机会时,其他人也问了这个问题。你应该准备好知道你对这些问题的答案,尤其是你想如何处理薪水的问题。
从你信任的中立人士那里获得建议 很多人在给你建议的时候都会有特定的目的(脑海中浮现出招聘者)或者偏见。我经历过这种情况,当我收到多份邀请,不同的人就最终担任哪个角色提出相互矛盾的建议。从几个我真正信任的人那里得到中立的建议真的很有帮助。
10)做出明智的决定 这非常重要。当我决定接受哪份工作时,情况尤其如此。在做出决定之前,我需要确保我已经和每家公司的相关人员谈过了(我几乎没有和一家公司谈过就做出了决定,但幸运的是被我信任的人说服了)。我还发现,在做出任何最终决定之前,与中立的人交谈会有所帮助。
现在,我可以说“我去过那里,做过那件事,穿过 t 恤衫”,并将在新的一年开始我作为数据科学家的新角色。随着新篇章的开始,不可避免地会有新的经历和更多的教训需要学习。放马过来。
找数据科学工作的建议:简历
一份出色的简历可能会让你获得面试机会。一份不好的简历会被扔掉!
这就是简历的重要性。通常这是雇主对你的第一印象,所以不要想让它变好,你的目标是让它变得出众。
现在,我远不是写简历的专家。如果我说我的求职成功率高于平均水平,那我是在撒谎。此外,网上已经有几篇文章对如何写简历给出了很好的指导和建议。事实上,我读过的对数据科学简历提出建议的最好的文章之一是由皇家邮政高级分析和数据科学主管本·迪亚斯写的,题为“招聘经理在数据科学家的简历中寻找什么?”
那么,我为什么要费心写一篇关于简历建议的帖子呢?
几个月前,我被要求浏览简历,并帮助筛选公司数据科学职位的面试候选人。这对我来说非常有见地。我看到了一些非常突出的东西,有正面的也有负面的。所以我想根据我从那次经历中学到的东西给你一些建议。
1.不要低估自己
记住,你是为了正确的理由而努力脱颖而出。当雇主看你的简历时,通常不是孤立的。他们看过很多简历,所以你会被拿来和其他人比较,有些人不怕夸大一点来让自己脱颖而出。雇主的任务是筛选出那些夸大事实的人。然而,如果要在一个简历夸大的候选人和一个简历低估自己的候选人之间做出选择,我可能会把赌注押在简历夸大的候选人身上。
让我们明确一点,我不是说你应该在简历上撒谎,但是不要使用让雇主有理由认为你没有实际上那么好的语言。
例如,假设你已经完成了一些在线数据科学课程,并且你已经用 Python 编程 6 个月了。你不太可能成为世界一流的 Python 程序员。但这并不意味着你应该在简历中注明你是“Python 初学者”。
Python 初学者是什么水平?是不知道如何编写 for 循环的人,还是对 Scikit-learn 中的机器学习知之甚少的人?我认为它们是不同程度的暴露。使用 Scikit-learn 的人可能可以浏览机器学习包生态系统,但 for-loop 初学者可能甚至没有见过终端/命令窗口。你永远不知道雇主会如何解释“初学者”。
所以请记住,你不必夸大你的技能,但是不要使用低于你的技能水平的语言。不要低估自己。
2.关注价值
作为一名数据科学家,很容易高估算法的重要性。关于如何实现各种 ML 模型和解决不同问题的新神经网络架构的教程不计其数,似乎每周都会出现。但事实是,模型只是造就优秀数据科学家的一小部分。最终,你必须表明你理解并关心商业价值。
我记得曾经看过一份候选人的简历,据说他有超过 10 年的数据科学经验。简历中充斥着数据科学术语。这位候选人使用了各种算法来完成工作项目,并获得了非常好的评估指标分数。太好了。但是在任何地方都没有提到商业附加值。这个项目产生了多少额外收入?对于 90%的分类准确率,效率提高了多少?我可以继续。
你简历上关于某个特定项目的分数应该是这样的:“我使用了 X 技术,获得了 Y 分数,并转化为 Z 值”。
如果你不能将模型性能的输出与附加的商业价值联系起来,那么你将失去巨大的印象分。
注意:如果你正在申请你的第一份工作,那么这不是一个很大的问题,但是如果你现在已经在工业界工作,那么你需要考虑你目前的项目如何提供商业价值,如何增加你的简历对未来雇主的吸引力。
记住关注价值。
3.展示自己
显然,简历应该是一个关于你和你的技能的光辉故事,但这是 2018 年的人!你可以超越你的简历。您可能有一个展示您的数据科学技能的博客,或者您可能有展示您进行精彩演示的视频。至少你应该在 GitHub 上有几个项目,以显示你有一个体面的技术能力的基础水平。你的简历中应该有所有这些东西的链接。不能保证雇主会看它,但是你给了他们选择权。谁知道呢,如果他们真的看了,你可能会给他们留下深刻印象。这就是我看过的一份简历的情况。
其中一个候选人链接了他们的博客,所以我决定去看看。我在那里看到了一些很棒的文章,其中一篇是关于我不熟悉的话题。我可以立即看出这位候选人有很好的技术知识和良好的书面沟通技巧,所以我建议这位候选人应该被选中参加面试(当然,简历的其他部分也必须很好)。
所以不要害怕,展示自己。
4。陈述你的相关技能…..早期
当你看一份工作说明书时,他们几乎总会有一部分是关于*【期望技能】*或其他类似的内容。这听起来可能很明显,但这些技能应该与你在简历中写的技能相匹配(你不必匹配所有的技能,在许多情况下,即使 50%也可以)。所以确保你在简历中陈述了这些技能。
我个人喜欢简历中的“技术技能”部分,因为它很容易查看和浏览列表,以了解候选人拥有什么技能,而无需试图挖掘大量的项目工作。虽然有些人不同意这一点。挺主观的。
但是无论你决定做什么,确保这些技能能在你简历的第一部分找到。
大约 6 个月前,我看了一个朋友的简历,他是一名博士后研究员。我已经知道他们具备初级数据科学家所需的基本技能,但是,他们的简历并没有说明这一点。我不得不翻到简历的第二页,才找到相关的技能。雇主不可能有那么大的耐心。那份简历很可能在任何人接触到相关部分之前就已经被许多公司扔掉了。
所以记得在早期陈述你的相关技能。
5.让很多人阅读你的简历
让我这么说吧:
如果你是唯一看过你简历的人,那么这是一份糟糕的简历!
也许这种说法有点苛刻,但我这样说是有充分理由的。简历不是为你设计的,而是为别人设计的——雇主。所以,即使你喜欢你的简历,你需要喜欢的人也可能不喜欢。
从几个信任的人那里获得反馈。不要害怕听到批评。它发生了。你的简历在初稿中不太可能是完美的。在寄出之前展示给别人看将会改善它,最重要的是,增加你获得面试的机会。
我自己的简历被我的三个朋友评论过,那是从我找到现在的工作开始的。有些人对应该如何写有非常不同的意见(一个人认为应该是 1 页,另一个人说如果我溢出到 3 页也没关系),所以我不得不管理我挑选的内容,但总的来说,反馈极大地改善了我的简历。
所以在你让很多人阅读你的简历之前,不要发出你的简历。
和往常一样,这并不是制作简历技巧的详尽清单,但这些是我在浏览候选人简历时注意到的。我希望这对你有所帮助。如果您有任何其他提示、意见或问题,请随时在下面留言。
感谢阅读。
ART + AI —使用(Tensorflow 和 TPUs)生成非洲面具
容易吗?需要多少数据?数据质量会影响结果吗?甘人学到了什么?
African Masks generated using a DCGAN model.
2018 年 8 月,我有机会参加了 2018 深度学习 Indaba ,在这里 Google 慷慨地向所有参与者提供了 TPUs (v2)的访问权限!我最终花了一些时间来熟悉在 TPUs 上运行 ML 实验,并开始训练 GAN 基于我一直在管理的自定义数据集生成图像——非洲掩模数据集。TPUs 提供了一些强大的计算能力(与高端 GPU不相上下),能够快速完成训练实验。访问 TPU 使我能够探索一些与训练 gan 相关的问题——例如,多少数据是足够的数据?图像大小如何影响生成的输出?数据质量有多重要(例如,整理数据集的努力?)生成的样本有多新颖?等等。在这篇文章中,我提供了我训练 GAN 的步骤、结果和有趣的观察。
想尝试使用生成的图像进行交互式演示,并探索它们与训练数据集中的图像的相似性吗?试玩在这里。有机会使用 TPU,并希望根据您的客户数据培训 GAN?本项目使用的代码在 GitHub 上,包括训练好的模型用于生成遮罩。
Web demo interface allows you view generated images and most similar from the dataset based on features extracted from a VGG network (block1_pool and block5_pool).
TPUs 上的张量流
要在 TPUs 上运行 TensorFlow 代码,最重要的部分是使用 TPU 版本的设计相当好的估算器 API。估计器封装了训练循环的以下方面:训练、评估、预测、服务输出。在很大程度上,使用该 API 编写的 Tensorflow 代码(顺便说一句,keras 模型可以很容易地转换为估算器 API)可以通过用 TPU 估算器替换常规估算器在 TPU 上运行。更好的是,tpuEstimator 将在 CPU 和 GPU 上工作(您应该设置 use_tpu 标志),允许在部署到 TPU 集群之前在本地机器上进行简单的测试。
TPUEstimator 处理在 TPU 设备上运行的许多细节,比如为每个内核复制输入和模型,以及定期返回主机运行钩子。
幸运的是,我不必从头开始实现 DCGANs,因为 Tensorflow 确实提供了一些样本代码。然而,该示例支持 32px 图像(cifar 数据集)的生成,我的主要任务是扩展该模型以支持大图像尺寸(64px,128px),类似于使用 artDCGAN 所做的工作。这主要是通过扩展(增加层)DCGAN 模型中的生成器和鉴别器来实现的。这里最棘手的部分是确保大小的一致性,即确保每一层或功能的输入/输出与预期的形状和大小相匹配。
生成对抗网络
GANs 是深度神经网络的一种形式,对于密度估计特别有用。gan 是生成性的,因为它们学习一个分布(训练图像数据集)并且能够生成位于该分布内的“新颖”样本。它们是对抗性的,因为它们被构造为一个游戏,其中两个神经网络(生成器 G 和鉴别器 D )竞争——G学习生成假图像(通过估计图像数据分布),而 D 学习区分真实和假图像(图像来自分布或来自的概率
随着游戏的进行, G 学会创造 D 无法从真实图像中分辨出来的“令人信服”的图像。期望 G 学习数据中的所有显著“模式”,并在生成新图像时涵盖所有这些模式。例如,在 Cifar10 数据集上训练的 GAN 应生成所有 10 个类别(汽车、卡车、飞机等)的图像。该研究领域的进展集中在为两个网络寻找良好的自我评估标准(损失函数)、解决几个已知问题的更好的架构(例如,一个网络压倒另一个网络、无法学习数据分布的所有“模式】)、生成逼真/高分辨率图像等。
对于这个项目,使用无条件 DCGAN[1]或深度卷积 GAN 架构,其架构选择使其在训练期间保持稳定。Tensorflow 提供了使用 TPUs 训练 DCGAN (CIFAR,MNIST)的示例代码,该代码针对本实验进行了扩展。
数据准备和培训
对于这个项目,我使用了非洲面具数据集——一组手动管理的描绘非洲面具的 ~9300 图像(我仍在管理这个数据集,但计划很快发布)。
这个数据集的目标是为探索人工智能和非洲艺术的交集提供额外的资源。
需要注意的一点是,该数据集包含不同“模式”的图像(即许多不同形状、纹理等的遮罩),而不是像 CelebA 这样定义良好的数据集,它只包含有限变化的人脸。看看 GAN 如何尝试从这个数据集学习模式以及它对这些模式的解释将会很有趣。我们的目标不是生成一个完美逼真的面具(这是最近 GAN 作品的一个共同目标),而是更多地观察编码在生成的 GAN 中的任何创造性或艺术性的元素。
TPU 培训
对于训练,第一步是调整、裁剪每张图像,然后转换为 TFrecords 。用于此的脚本在项目的 Github repo 中提供。虽然我们不关心无条件 gan 的标签,但是脚本使用目录名作为标签(类似于 torch visionimage folder)。
两个版本的 DCGAN 模型被训练以分别生成 64px 和 128px 图像。这包括更改输入函数以反映新的输入大小,然后扩展模型(向 D 和 G 添加层)以匹配 64px 和 128px 代。两个模型的其他参数基本相似——训练步数:15k,批量:1024,固定噪声维数:100,学习率:0.0002(对于 D 和 G)。
一些有趣的观察
64px 与 128px 一代
与 128 像素模式相比,在 64px 模式下生成的图像提供了更好的多样性。虽然 128px 图像的质量明显更高,但它们似乎存在部分模型崩溃的问题。这可能是由于数据集不足以训练如此大的模型(我也为 128px 模型试验了更长的训练时间,但这没有帮助)。
LEFT: 128px images generated using a DCGAN, fixed noise vector (dim=100), 15k steps, batch size 1024. Notice how several “modes” appear to emerge within the generated masks (highlighted with same color). While this may be as a result of the sample size. However this does not occur to the same degree when generating 64px images using similar training parameters. RIGHT: 64px images generated using a fixed noise vector (dim=100) 15k steps, batch size 1024. These results show more diversity compared to the 128px images.
多少数据才算足够的数据?
我发现在实践中,一个低至 2k -3k 图像的数据集会生成某种形式的“结果”。为了进一步探索数据集大小如何影响生成的结果,我提取了掩膜数据集(3k 图像,64px)的随机样本,并训练了一个模型。这里的主要观察结果是,局部“模式崩溃”(这个问题在这里有很好的解释)的发生率更高,并且生成的图像的多样性降低。下面的屏幕截图包含从使用相同参数训练的两个模型生成的图像,但是使用 3k 数据集和完整的 9k 数据集。其他研究项目(见这里)似乎训练 GANs 在 6k 和 9k 图像之间有不错的结果。到目前为止,我的直觉是,对于具有某种程度相关性的数据集,GAN 能够从大约 6k-9k 图像开始学习有趣的模式。随着我进行更多的实验,我将更新这一部分。
64px images generated with similar models but left uses a 3k dataset and right uses the full 9k images in the dataset. Images generated using the 3k image dataset shows lower diversity with several similar/repeated images (highlighted).
有噪声的数据集重要吗?
管理数据集可能很乏味。初始图像搜索结果可能包含不可用的数据(例如,图片的图片、草图、2D 图像、标记为遮罩的无关图像等)。这就提出了一些相关问题——噪声图像的存在如何影响 GAN 产生的图像质量。为了探索这一点,我使用 13k 图像(来自网络搜索的未整理结果)训练了一个模型,并将结果与我手动整理的 9k 图像进行了视觉比较。
64px images generated with similar models but left uses a 3k dataset and right uses the full 9k images in the dataset. Images generated using the 3k image dataset shows lower diversity with several similar/repeated images (highlighted).
在我的例子中,似乎有额外的图像(大约 3k,整个数据集的 20%)没有被策划,并没有完全阻止生成器探索数据中有趣的模式(左上图)。然而,有一些随机的图像(用红色突出显示)明显没有非洲面具的预期纹理或图案。为了进一步探索这个问题,我收集了 29k 张“茶杯”图片的数据集,并训练了一个模型。下图显示了结果(训练至 25k 步和 32k 步)。虽然有一些看起来特别有趣的图像,但仍然不清楚我们是否会通过管理数据集做得更好。
思考:如果你的目标不是“完美”地表示数据集中的模式,那么手工处理图像不会给你带来更多的价值。
Teacups generated from an “uncurated” dataset (29k) of teacups. LEFT: Trained to 25k steps. RIGHT: Trained to 32k steps.
甘人学到了什么?
这可能是这个实验中最有趣的方面。它聚焦于一个经过充分研究的问题“GAN 实际上学习什么?”,但更多的是从定性的角度。一种方法是观察生成的图像和数据集中的图像之间的相似性。在他们的论文中,Karras 等人[2]使用这些图像之间的像素的 L1 距离来计算这一点。这种方法被批评为过于简单(没有利用任何图像内容的知识)。为了计算相似性,使用预训练的 CNN ( [VGG16](http:// VGG16) ,Simonyan 和 Zisserman 2016)作为特征提取器。然后计算相似性,作为生成的图像和训练数据集中的图像之间的余弦距离的度量。
def compute_cosine_distance_matrix(feat, feat_matrix): cosine_dist_matrix = scipy.spatial.distance.cdist( feat_matrix, feat.reshape(1, -1), 'cosine').reshape(-1, 1) return 1 - cosine_dist_matrix
我尝试使用 VGG 的各种maxpool
图层提取特征进行相似性计算,发现早期和后期图层在识别视觉上看起来相似的图像方面表现最佳。我创建了一个演示,它根据 VGG 网络中两个层(早期层和后期层(block5_pool))的特征,显示了每个生成图像的数据集中前 24 个最相似的图像。
An interface that displays images similar to the generated images from the GAN. Similarity is computed as cosine distance of features extracted from layers of a pretrained CNN (VGG). Qualitative inspection suggests using an features from an early layer (block1_pool) finds images with similar low level features (color, pixels, texture), while later layers find images with similar high level features (shapes and and objects) etc. Check out the demo on this here — victordibia.github.io/cocoafrica/…
初步结果显示,GAN 生成的图像与数据集中它们最近的亲戚非常不同。没有明显的副本。这种解释是主观的,受限于生成图像的模糊性质,鼓励读者观看演示以形成更好的意见。
对生成图像的交互式检查还提供了查看数据集中一些有趣模式的机会。一些包括具有特定侧向取向的面具、具有毛发或毛发状突起的面具、长方形面具。相似性信息也可以是一种(弱监督的)技术,用于管理图像数据集,启用数据集的特定“模式”并发现异常值即坏图像。
Some of the images generated by the GAN are similar to some observable “modes” within the mask dataset. Some of these modes might reflect artistic style and origins of the masks themselves (yet to be explored).
摘要
- 与 TPU 一起工作比我最初想象的要容易。Estimator API 设计得非常好(封装了训练循环);已阅读并遵循现有评估程序 API 代码。对于已经熟悉估计器(或其他支持标准化训练 NN 训练循环的框架)的个人来说,完成工作将会很容易。
- 在这个项目中,一个麻烦的部分是对我的数据转换脚本(从原始图像到训练中摄取的 TFrecords)进行故障排除。我扩展了示例 DCGAN 代码,它碰巧期望一个形状为**【通道,高度,宽度】的图像张量,而不是我更习惯的【高度,宽度,通道】**。这并没有抛出任何错误——只是意味着我运行的前 30 个左右的实验产生了绝对嘈杂的废话。TFrecords 非常优秀有很多原因——然而,如果 Tensorflow 能够更好地标准化这一过程,它将会非常有用(不确定 TF 是否已经有了类似 torchvision imageFolder 的东西)。
提示:为了确保万无一失,要经常检查你的 TFrecords 中进出的东西。
- 组装一个干净的数据集是实际使用 GANs 进行有意义的艺术探索的一个非常重要的部分。这为支持数据集管理的工具提供了一个案例——可能以半监督的方式,我们标记一个小样本,在这个样本上训练一个模型,并使用它来“管理”其余的数据。
- 甘斯可以用于艺术探索。在这种情况下,虽然一些生成的图像不是完整的蒙版,但它们擅长捕捉非洲艺术的纹理或感觉。例如,我给一位同事看,他们提到生成的图像具有“部落感觉”。
- GANs 领域的许多现有工作集中于生成“真实”图像。虽然这非常有用(事实上,这是 GANs 等应用程序所希望的,因为超分辨率),但了解 有多少来自训练数据的 信息被合并, 它们如何被组合 以生成新图像,以及这些图像是否真的新颖也很重要。定性检验实验(真实世界数据集)可以提供这方面的见解。
- 预训练模型作为这些检查/相似性实验的特征提取器工作良好(与像素中的简单 L1 距离相反 Karras 等人 2017 年[2])。早期的图层允许我们根据线条和纹理等低级特征来检查相似性,而后期的图层则侧重于形状等高级特征。
后续步骤
在做这个项目的时候,我确实对 GANs 有所了解;非常感谢谷歌使 TPU 可用。一如既往,未来工作的机会数不胜数。我正在考虑的一些方法包括——扩展非洲面具数据集,用条件化的 GANs 做实验(学到的特征如何与艺术属性相对应?)和其他用于真实/更高分辨率图像生成的架构。
知道下一步该做什么吗?你可以随时联系 Twitter、T2、Github 或 T4 的 Linkedin。
参考
[1] A .拉德福德,l .梅斯,s .钦塔拉,“深度卷积生成对抗网络的无监督表示学习”,arxiv 1511.06434【cs】,第 1–16 页,2016。
[2] T. Karras、T. Aila、S. Laine 和 J. Lehtinen,“为提高质量、稳定性和变化性而逐步种植 gan”, CoRR ,第 abs/1710.1 卷,2017 年 10 月。
聚合和分组
GSoC:在 Pharo 中实现数据框架
这是 Pharo DataFrame
中聚合和分组的第一个实现。它仅涵盖基本功能,例如按相应大小的另一个系列的值对数据框或系列进行分组,然后将聚合函数应用于分组的数据结构。
在接下来的迭代中,该功能将根据目标用户场景进行扩展。实现也很有可能发展成更加优化的东西。
什么是 DataFrame?
数据框是一种类似电子表格的表格数据结构,它提供了一个用于切割、清理和分析数据的 API。在 Pharo 中实现数据帧是我今年谷歌代码之夏项目的一部分。您可以在这个库中找到代码:github.com/PolyMathOrg…,并使用下面的 Metacello 脚本将其加载到您的映像中:
Metacello new
baseline: 'DataFrame';
repository: 'github://PolyMathOrg/DataFrame';
load.
如果您想了解更多关于 DataFrame 项目的信息,请查阅文档并遵循您可以在资源库中找到的教程。文档仍在开发中,所以如果你找不到问题的答案,请随时给我写信:olk.zaytsev@gmail.com。
拆分-应用-合并
分割-应用-组合是一种策略,你把一个大问题分解成可管理的小块,独立地处理每一块,然后把所有的小块组合起来。
数据聚合和分组允许我们为显示或分析创建汇总,例如,在计算平均值或创建计数或总和表时。这是一个遵循分割-应用-组合策略的过程:
- 根据某些标准将数据分组
- 将该函数独立应用于每个组
- 将结果组合成一个数据结构
履行
在这一节中,我将解释聚合和分组功能目前是如何实现的。如果您对这些细节不感兴趣,可以跳过这一部分,跳到下一部分。
考虑以下发送到firstSeries
对象的消息:
firstSeries groupBy: secondSeries.
收到这个消息后,firstSeries
创建了一个对象DataSeriesGrouped
,它根据secondSeries
的值将firstSeries
分割成一系列子序列。然后,子系列的集合被存储为DataSeries
(名为groups
的实例变量)的对象,其键等于secondSeries
的唯一值,值存储firstSeries
的子系列,对应于这些唯一值中的每一个。
当一个groupBy:
消息的接收者是一个DataFrame
时,它创建一个DataFrameGrouped
的实例,该实例以类似于DataSeriesGroup
的方式分割数据,除了groups
系列的值是子数据帧,而不是子系列。换句话说,groups
是一个DataSeries
,其关键字对应于数据帧分组所依据的系列的唯一值(secondSeries
),并且groups
的每个值存储一个较小的数据帧,该数据帧具有由数字指定的行,其中secondSeries
的值等于groups
的对应关键字。如果数据框按其中一列进行分组,则在分组之前,该列将从数据框中排除。这样我们避免了数据重复,因为相同的值将作为groups
变量的关键字存储。
在DataSeriesGrouped
的情况下,每个子序列将被聚合成一个标量,所有这些标量将被组合成一个新的DataSeries
。至于DataFrameGrouped
,它会将块应用于每个子数据帧的每一列,并将结果标量矩阵作为新的DataFrame
返回。
聚合是通过apply:
消息完成的。它将一个块作为参数,并将其应用于 groups 系列的每个值,并将结果组合成一个新的数据结构。对于一些常用的聚合函数,如max
、min
、average
等。,DataGrouped
提供更短的消息。在这个迭代中,所有这些消息都只是方便的快捷方式
average
^ self apply: [ :each | each average ].
但是在将来,这些消息将包含相应聚合的优化实现,因为这些函数的时间和内存效率非常重要。
用法示例
在这一节中,我将提供一些简单的示例,例如按另一个系列的值对一个系列进行分组,按一个系列的值对一个数据框进行分组,最后我将展示如何将聚合函数应用于分组后的数据。
餐馆小费数据集
我将把我的例子建立在餐馆小费的数据集上。它最初出现在 Bryant & Smith 1995 年关于商业统计的文章中。您可以在这个 GitHub 资源库中获得一个带有 tipping 数据集的 CSV 文件:https://GitHub . com/wesm/pydata-book/blob/master/ch08/tips . CSV。
让我们使用fromCSV:
方法将数据读入DataFrame
tips := DataFrame fromCSV: '/path/to/tips.csv'.
快速了解存储在数据框中的数据集的最简单的方法是查看其标题-前 5 行(tips head
)
| total_bill tip sex smoker day time size
--+------------------------------------------------------
1 | 16.99 1.01 Female No Sun Dinner 2
2 | 10.34 1.66 Male No Sun Dinner 3
3 | 21.01 3.5 Male No Sun Dinner 3
4 | 23.68 3.31 Male No Sun Dinner 2
5 | 24.59 3.61 Female No Sun Dinner 4
我们可以看到,tipping 数据集有 2 个定量变量:total_bill
和tip
,5 个分类变量:sex
、smoker
、day
、time
和size
。在下面提供的例子中,我们将只根据分类变量对数据结构进行分组。从技术上来说,也可以通过数量变量进行分组,但在大多数情况下,这种分组不是很有用(更不用说它在教程中看起来不太好)。
分组系列
应用groupBy
操作符的最简单的例子是将一个系列的值按照另一个相同大小的值进行分组。
bill := tips column: #total_bill.
sex := tips column: #sex.bill groupBy: sex.
这个查询的结果将是一个对象DataSeriesGrouped
,它将bill
分成两个系列,映射到sex
系列的‘Male’
和‘Female’
值。
Female (16.99 24.59 35.26 14.83 ... 18.78)
Male (10.34 21.01 23.68 25.29 ... 17.82)
由于大多数情况下我们需要对属于单个数据框的两列序列进行分组,因此有一个方便的快捷方式:
tips group: #total_bill by: #sex.
分组数据框
除了上面演示的对其列进行分组的快捷方式之外,DataFrame
还提供了一种通过其中一列对自身进行分组的方法。
tips groupBy: #smoker
该查询的结果将是一个对象DataFrameGrouped
,存储两个独立的数据帧——一个针对所有吸烟者,一个针对非吸烟者。smoker
列将从这些数据框中排除,因为它的值将作为键存储在DataFrameGrouped
对象中,吸烟者和非吸烟者的单独分组将允许我们在需要时完全重建smoker
列。
聚集分组数据
聚合函数将一个序列作为输入,并返回一个汇总该序列值的标量值。这些是统计函数:min
、max
、average
、stdev
等。,像sum
、count
等很多功能。
一旦数据被分组,我们就可以对组成的组应用聚合函数,并接收汇总初始数据的组合数据结构
grouped := tips group: #total_bill by: #day.
grouped apply: [ :each | each average round: 2].
因为我们是按照另一列对DataFrame
的一列进行分组,所以结果将是一个DataSeries
的对象
a DataSeries
Sun 21.41
Sat 20.44
Thur 17.68
Fri 17.15
如前所述,DataGrouped
提供了一些常用聚合函数的快捷方式,如min
、max
、average
、sum
、count
等。目前它们只是快捷方式,但以后它们将实现应用速度更快的优化聚合(对于像 tipping 这样的小数据集,速度不是一个严重的问题)
grouped min.
grouped max.
grouped average.
一旦数据帧被分组到一个对象DataFrameGrouped
中,我们也可以对这个对象应用一个聚合函数。DataFrameGrouped 实现 apply:消息的方式是将函数应用于每个子数据帧的每一列,从而产生标量值。这些标量然后被组合成一个新的数据帧。
(tips groupBy: #sex) count.
此查询的结果将是一个数据框,其中包含每一列的非空单元格的数量,对应于“男性”和“女性”行
| total_bill tip smoker day time size
-------+-----------------------------------------
Female | 87 87 87 87 87 87
Male | 157 157 157 157 157 157
资源
- McKinney Wes,用于数据分析的 Python,O'Reilly Media,Inc .,2012 年
- 哈德利·威克姆(2011)。数据分析的分离-应用-组合策略。统计软件杂志,40(1),1–29。网址 www.jstatsoft.org/v40/i01/。
- pandas.pydata.org/pandas-docs…
- https://www . PostgreSQL . org/docs/9.5/static/tutorial-agg . html
- https://github . com/wesm/pydata-book/blob/master/ch08/tips . CSV
最佳敏捷:在金融机构中构建人工智能产品🏦
敏捷文化的核心在初创公司和小公司中非常流行,但由于传统的业务结构或企业文化,在大型组织中就不那么流行了。这是金融机构邀请咨询公司提供数字产品的几个原因之一。然而,随着人工智能(AI)的兴起,这种在金融领域流行的商业模式需要重新审视。趋势科技引入了不同性质的软件产品。
"*先进的分析解决方案可以模仿领域知识,做出决策,并消耗内部数据。*在当前的金融形势下,这类产品很难外包出去。这一点随着 AI 产品在金融的部署越来越明显。因此,经历过这种情况的企业正在发展自己的人工智能能力,以便在内部提供这种产品。”
…因此,让我们开始通过构建敏捷的人工智能产品来打破孤岛!
#金融机构如何引领这场变革?🦈
T 他的转变可以通过重新思考业务管理、数据战略和招聘流程来完成,以允许这种颠覆性解决方案的内部开发&部署。然后,敏捷文化可以通过构建一个又一个产品而有机地成长。此外,几乎每个人工智能产品开发都需要一个采用不同技术的项目。这很可能是由于人工智能领域突破性研究的快速发展造成的。这将使研究和工业应用之间的差距比通常情况下显得更大。
“人工智能产品开发需要组织内部的即时转型变化。这可以通过创建独特的运营模式来实现。这些模型将建立开发团队,并给予他们技术选择的自由。然后,团队可以通过每个敏捷项目解决当前组织的痛点。
…对于任何大型组织来说,这都是一项极具挑战性的任务
#如何创建构建 AI 产品的运营模式?🍹
最好的方法是将敏捷软件开发的基础知识(T21)和商业管理(T25)定制成开发团队的精益运营模式。这种定制应该努力允许团队在构建 AI 产品时灵活地驱动转型性的变化。这是一个为特定项目量身定制的迭代过程。它有选择地将开发团队放在一起,并设置他们的边界。
“引入合适的人,建立一个适合他们工作风格和人工智能产品的数字化工作环境。分 3 步做这件事;[1]通过“精明的”团队招募[2]组建“产品驱动的”团队,[3]能够在“轻量级”项目模型下执行任务。这可以通过专注于满足您的定制需求的特性来充分发挥敏捷和管理的优势。”
…请记住,只有当每个人齐心协力时,敏捷团队才能有效地交付产品&他们的界限被定义为使团队能够做出正确的决策,而不是限制团队的创新
[1]精明的团队招聘😜
T 为产品驱动型团队雇佣顶尖人才&技能从简化当前的招聘流程开始。这需要放弃任何冗长、低效、过度勤奋的流程,进行更明智的招聘。这也应该重视招聘经理的时间,这样他们可以更好地评估任何缺失的专业知识。最后,它是关于如何快速地使面试具体化,以防止领域专家流失到竞争中。
1 🏠内部招聘 - >寻找领域知识 专家和渴望改变的初级团队成员
…也可以浏览定量分析师和金融/研究分析师的人才库。有时可能会有其他人才,但不要试图寻找传统的管理工作(敏捷文化的对立面)。
2🏙外部招聘 - >寻找在人工智能、计算、科学和敏捷软件开发方面有原型开发&生产颠覆性解决方案经验的专家
🤓只进行 1 到 2 轮面试 - >只进行一次文化契合度面试&如有必要,再进行一次技术知识面试
🏋如果你真的需要测试候选人的知识,给他们布置一个任务,但是这个任务必须代表他们被雇佣的实际工作(这样他们就可以评估他们是否喜欢这个工作)
🤠在见候选人之前做好你的尽职调查,了解他们的技能(他们的工作信息通常可以在网上找到,因为他们是他们领域的专家)
🛋 面试时要放松 - >让应聘者谈论他们的工作&和他们讨论你目前面临的挑战,看看他们是否感兴趣,以及他们会如何处理这个问题
👐非常具体地说明你要招聘的工作 - >公开地与求职者交流他们未来的工作,明确你招聘的人是否具备目前所缺乏的技能,因为没有哪个领域的专家愿意在一个其他人无法胜任的地方工作(他们会发现面试官是否在假装理解工作)
🦊评估面试时要精明 - >在面试后召集团队,根据候选人对当前&未来团队目标的回答,客观地评判他们的技能,这将防止雇佣比现有技能更差的人
🏎利用试用期 - >给新员工一个机会在试用期证明他们的工作,如果需要不同的人,可以重新开始(找到一个替代者应该不难,因为这个精明的招聘已经到位了)
…没有必要让应聘者为难,因为面试永远无法模拟实际的工作环境或员工的决定。此外,任何面试官都不可能独自客观地判断应聘者的技能(应聘者是公认的领域专家)。因此,在现场面试中不要问一般性的问题或进行测试!这将会阻碍你的才华,暴露出你在展示你招聘的理想工作时的无能。
[2]产品驱动型团队🚀
一个开发团队可以遵循特定的组件(如下所列)来专注于交付人工智能产品。这样的产品通常是在短时间内和具有挑战性的环境中开发出来的,因此团队成员应该以敏捷的方式一起工作。这将消除任何无意义的工作,因为敏捷中的工作赋予每项任务以意义。尽管如此,重要的是所有成员都意识到敏捷文化可以积极地促进他们的职业道路,甚至是他们的工作快乐。例如,它可以让他们找到自己喜欢的工作,学习新技能,或者获得交付人工智能产品的出色经验。如果这样的团队已经成立,那么就要通过帮助他们找到最佳状态并给他们探索的自由来提高他们的表现。
1 🎳团队结构 - > 4 到 10 名通才,他们具备领域知识 e、计算科学、人工智能和敏捷 软件开发
…技能和团队成员数量的适当平衡取决于项目。但成员需要提供跨职能的专业知识,以保持团队的精干和协作。团队还需要拥有优秀领域知识的成员来实现特定领域的解决方案。否则,人工智能产品将永远无法在部署的地方发挥其商业价值。
2🧠团队心态 - >每个团队成员都必须具备一定的个人素质来交付敏捷产品
🏅不要成为一个追逐头衔的人 - >成为一个实际的贡献者&帮助其他成员发现和发展他们的潜力
🎭不要做戏剧女王 - >做一个透明的&问责成员
📓不要推动个人议程 - >要有团队愿景&产品目标
🔬不要微观管理 - >相信你的团队,把手拿开&看着
🌟不要满足于目前的技能组合 - >跟上研究和行业发展的步伐&跨领域发展其他技能,获得 T 型技能或更好的技能
…在组建团队时,很难找到满足上述个人素质的人,但这在团队互动中会出现。团队成员是那些在团队会议上透明地讨论他们的问题,而不是和他们喜欢的成员讨论的人(这会制造不必要的戏剧性事件)。此外,由于轻量级项目模型的工作透明性,不想做贡献的成员很容易被发现。
3📅团队会议 - >关于计划工作、已完成工作、障碍和其他问题的简短每日会议,最多 15 分钟
…高绩效团队召开涵盖上述 4 点的会议,并尽可能邀请业务利益相关方参加。它有助于工作的执行并带来友谊,从而使每个人都可以畅所欲言(这在只有传统的 1 对 1 时是不可能发生的)。
44🎬团队凝聚力 - >评估团队的检查点&如果一些成员不能适应敏捷文化,调整团队
…识别团队虐待者并采取行动。敏捷项目简短有趣,但同时也让人精疲力尽。成功的团队拥有无私的球员,他们能做出贡献并愿意学习。所以,在这个项目中,没有任何一个只想随大流的人(猪和鸡)的位置。
[3]轻量级项目模型⛵️
项目模型指导产品驱动团队如何在软件开发中执行他们的工作。它有一些核心部分(如下所列),应该总是在一定程度上得到解决。这取决于项目、团队、产品和环境产品开发&推出。此外,将模型做得尽可能轻便以对企业有不言自明的好处也是至关重要的。一旦就位,就需要每个团队成员带头讲述他们的工作成果。
1 🖥 技术 - >统一当前使用软件的视图&用开发特定产品所需的技术栈丰富它
2📖工作描述 - >使用叙述来描述整个项目中的任何类型的工作,例如,为每个工作任务编写一个简单的用户故事
3👀工作可访问性 - >让每个团队成员都可以使用工作,例如使用软件仓库来存储工作( GitHub , Bitbucket ,…)
4 🌱项目生命周期 - >跟踪&通过敏捷委员会展示产品开发的工作进度,并提供一个知识共享的场所,企业可以从任何设备访问,例如使用您选择的敏捷项目管理工具( Asana、GitLab、JIRA 、 Confluence、……)
5t34】🧬项目框架 - >选择&将适合项目需求的敏捷方法的特性结合到自己的项目框架中
…以前没有敏捷经验的团队可能会使用经典的 Scrum 作为大型项目的项目框架,并使用极限编程(XP)作为小型项目,例如解决方案原型/概念验证
#结论👩🏫
“在金融领域率先采用机器学习的时代已经过去了。街上的公牛正在敏捷文化上奔跑,并建立这样的人工智能能力。因此,引入的运营模式是金融机构建立自身人工智能能力的绝佳机会。他们甚至可以用它来参与进一步的研发活动。这最终应该会让人工智能研究更接近金融应用。”
我们已经为在金融机构建立产品驱动的人工智能团队的运营模式建立了标准。希望它能帮助读者在他们的工作场所为这种看似难以捉摸的技术的内部开发铺平道路。这可能会立即导致中断,但引入工作透明度、协作和绩效将带来长期的好处。总体而言,它调整了敏捷软件开发的商业模式,以在金融领域提供更多人工智能应用。
🍰这有助于金融机构更轻松地部署外部人工智能解决方案,金融机构将随时准备在这方面发挥带头作用
✌️ 它让金融机构减少了对外部人工智能解决方案的依赖,这迫使外部公司/咨询公司改进他们的产品
#进一步推荐阅读📚
敏捷数据科学——反思
重新审视数据科学团队内部的敏捷实践
Agile to Success within Data Science
如今,敏捷在软件开发中变得非常有名。数据科学是另一个趋势学科,越来越多的公司试图建立并从中受益。
Scrum as 方法论试图以小增量的方式帮助构建一个好的软件。将敏捷软件方法应用于数据科学的尝试很多,但结果大多不尽如人意。
基于我的经验、阅读和最近参加麦吉尔大学的 SCRUM 培训,我试图讨论:
- 为什么敏捷的 scrum 框架不适合数据科学项目
- 遵循数据科学原则的敏捷概念
- 来自框架的改编
- 数据产品环境中的最小可行产品
为什么敏捷过程(特别是 Scrum)不适用于数据科学?
敏捷软件的目标是交付生产软件,而数据科学则是提供可操作的见解。
为了提供可操作的见解,作为数据科学家,我们需要根据假设进行迭代实验,这是由上次实验产生的不确定性结果,而工程使用已知的科学和工程技术来构建线性时间表。
因此,在数据科学项目中,我们通常在发现上比在工程上花费更多的时间,并且由于科学/数据的性质,花费的时间总是不确定的。
敏捷概念仍然适用于数据科学项目
敏捷软件开发的好处:迭代/增量,可交付的产品,持续的重新评估(客户/开发)。
《敏捷数据科学 2.0》的作者 Russell Jurney 简短地说:
敏捷数据科学流程的目标是记录、促进和指导探索性数据分析,以发现并遵循通往引人注目的分析产品的关键路径。
在此,我尝试对数据科学学科的敏捷宣言做一个分析:
- 个人和互动流程和工具:分享是强制性的,因为团队是由不同的学科(DS、DE、Business)组成的,我们需要在团队内部以及与客户之间进行有效的沟通。
- 工作软件综合文档:全栈数据科学家应该能够同时创建并交付概念验证应用以发布见解并收集反馈。
- 客户协作合同谈判:作为数据科学团队,我们需要定期和频繁地沟通,在整个项目过程中与客户讨论发现,而不是交付一次就有好的结果。因此问题是
How can we make the intermediate discovery understandable by customers?
。 - 根据计划应对变化:这已经在数据科学中发生,随着我们进一步揭示数据本身,进一步分析的计划将在试错的基础上相应地改变。
在分析了敏捷宣言之后,事实上数据科学可以让敏捷的概念受益:
为了在不确定和动荡的环境中取得成功,创造和应对变化的能力。
打破规则并适应
数据科学项目有可能继承敏捷软件开发。我们需要勇敢地打破规则来解决第一部分的问题。
总的来说,我们应该牢记敏捷的概念(迭代、增量和持续),由于研究的不确定性,我们无法将这些直接转化为时间约束冲刺和基于点的任务。
但是,由于不确定性,数据准备是唯一的例外。因此,我们应该将数据准备部分从 SCRUM sprint 中分离出来,特别是我们知道我们非常依赖其他资源或者数据非常脏,并且预处理可能涉及团队外部的交互。
然后,Scrum 方法论应该作为管理数据科学项目的项目管理框架。实际上:
- Sprint:一个灵活的 2-4 周的时间盒,当我们应该重新排序时,根据最新的发现重新安排未来的优先次序。
- 冲刺规划:我们评估已知的数据发现,并在需要时对冲刺级规划进行适当的更改(例如切换方法、调整完成的预计时间、更改范围等)。
- 每日 Scrum(站立):我们应该分享团队基于数据的最新发现的知识,并利用这些时间对短期任务进行快速调整(如切换数据源、请求领域知识专家、更改算法等)。
- 冲刺评审:我们应该在与团队一起进行项目期间放弃评审,除非我们达到了某个里程碑。我们使用评估来展示业务/产品并与之同步,但仅限于领导层。
- 冲刺回顾:我们应该在项目期间放弃回顾,除了当我们完成项目的时候。
最小可行产品(MVP)
敏捷还有一个 MVP 的概念。那么什么是数据科学项目环境中的 MVP 呢?
看情况。在团队内部,MVP 可以作为第一次尝试的基线模型,或者在jupyter notebook
或rmarkdown notebook
中展示的见解。但是对于业务或工程,它应该是一个的中等性能模型,能够工作并提供可接受的结果(例如,推荐系统应该提供不会损害最终用户体验的推荐),或者显示在仪表板中的洞察力需要与业务保持一致。
原载于 2018 年 12 月 31 日https://Ricky king . github . io。
敏捷评估:错过的机会和错过的期限
为什么这些公司关心他们的开发项目何时完成?显然,为了更快地从项目中获益。这可能是销售或利润的增加,也可能是成本的降低。我们称之为错过的机会,它有美元的成本。
计算错过的机会比计算投资回报率更容易、更直接,更重要的是,误导性更小。想想看,软件项目的实际投资回报率比预计的要低多少倍?使用错过的机会计算也有助于您确定项目的优先级。
在这本笔记本中,我们将根据团队在一次迭代中可以完成的故事点数量,尝试估计单个项目错失机会的概率分布。正如在前面的故事中所讨论的,我们将使用对数正态分布来估计项目速度。
import numpy as np
from scipy.stats import lognorm
data=np.array([14, 12, 7, 14, 13])
shape, loc, scale = lognorm.fit(data, floc=0)
在这里,我们获取了关于团队过去迭代的信息(分别是 14、12、7、14、13 个故事点),并使其符合对数正态分布。我们感兴趣的问题是:给定数量的故事点(在这个例子中是 70 个)需要多少次迭代。同样,我们使用对数正态分布的奇妙性质,即逆也是对数正态的,具有相同的参数和逆参数
***num_points = 70
dist_iterations = lognorm(shape, loc, num_points/scale)
print(f'Mean: {dist_iterations.mean()}')
print(f'Median {dist_iterations.median()}')
print(f'Standard deviation {dist_iterations.std()}')Mean: 6.219638285087961
Median 6.011776848254893
Standard deviation 1.6496339740439272#We plot the distribution
%matplotlib inline
import matplotlib.pyplot as plt
def plot_dist(frozen, low=0, high=14):
fig, ax = plt.subplots(1, 1)
x = np.linspace(low, high, 100)
ax.plot(x, frozen.pdf(x), 'r-', lw=5, alpha=0.6, label='lognorm pdf')
plot_dist(dist_iterations);***
所以我们看到我们有很好的机会在 7 次迭代内完成它,但是也有可能需要 12 次迭代!让我们说,由于错过了机会,业务在每次迭代中损失了 10,000 美元。那么错过的机会分布如下:
***missed_opportunity_per_iteration = 10000
missed_opportunity = lognorm(shape, loc, num_points/scale*missed_opportunity_per_iteration)
print(f'Mean: {missed_opportunity.mean()}')
print(f'Median {missed_opportunity.median()}')
print(f'Standard deviation {missed_opportunity.std()}')
plot_dist(missed_opportunity, 0, 140000);Mean: 62196.382850879614
Median 60117.768482548934
Standard deviation 16496.33974043927***
正如我们所看到的,我们有各种动机来更快地完成项目,以使曲线向左移动。也许我们增加更多的开发人员来提高速度?我们可能还想缩小范围,以减少故事点的数量。
最后,不管一些敏捷理论家怎么说,企业设置最后期限是有原因的。当一个软件项目完成后,企业必须做 UAT,接触一些客户,请他们提供反馈,等等。企业也希望提前对此进行规划,因为关闭活动有固定成本,如果项目不能按时交付,这将增加项目成本。我们称之为延迟成本。
如果错过的机会成本为零,那么为了避免延迟成本,我们计划尽可能晚的结束活动。但是如果非零,那么两个成本之间就会有权衡。因此,如果 C 是结束成本, Co 是错过的机会成本, N 是实际迭代次数,是计划迭代次数,那么总成本将是:
我们需要在 M 上最小化这个成本 我们可以对 M 求导。注意,那个P*(N>M)就是所谓的生存函数,或者说1CDF**,其中 CDF 是累积密度函数。生存函数的导数是负概率密度函数。因此, M 的最佳值由下式定义:***
在这个例子中,我们猜测延迟成本是 95,000 美元
**#We solve the equation numerically:
from scipy.optimize import *
delay_cost = 95000
def to_optimize(m):
return missed_opportunity_per_iteration - delay_cost*dist_iterations.pdf(m)
roots = newton_krylov(to_optimize, 8.0)
float(roots)7.994986056462073**
这向我们表明,即使团队很可能在六个迭代中完成项目,但是由于延迟的高成本,最好在八个迭代之后安排关闭活动。
在实践中,迭代中充满了所谓的“松弛”,即低优先级的故事,当所有高优先级的故事都完成时,团队就会这样做。如果团队确实在六个迭代中完成了,那么它就可以处理松弛的故事或者解决技术债务。
你可以在这里找到这篇文章的笔记本。
敏捷评估:第二部分
在我的前一个笔记本中,我建议使用泊松分布来估计每次迭代的故事点数,即项目速度。这是一个相当简单的分布,它有一个突出的性质:泊松分布的随机变量之和的分布也遵循泊松分布,其中一个参数是各个参数之和。这意味着项目速度是单个开发人员速度的总和,就像你直觉上假设的那样!
但是,泊松分布存在问题。如果你看它的 PDF,
PMF of Poisson Distribution
你看,它只有一个参数 λ 。而且方差也是 λ ,等于均值。这就产生了一个问题,我如何区分好的估计量和差的估计量。例如,如果我使用随机数量的故事点来估计每个用户故事,最终我将得到与一个人相同的方差,这个人的估计是准确的。
另一个问题是泊松分布假设故事点的持续时间服从指数分布,其众数为 0。所以这意味着一个用户故事很可能需要 0 小时来完成?我相信项目经理听到这个会很高兴的。
但是,如果您从估计每个故事点的持续时间开始,您将不得不选择一个众数大于零的分布。我曾经使用正态分布来估计一个故事点的持续时间,但是我注意到,对于一些开发人员来说,方差是如此之高,以至于左边的尾巴将会进入负的区域(任务将会花费负的时间来完成!).所以我必须选择一个支持 x∈[0,∞]的分布。
我可以选择一个非常流行的伽马分布,但是更好的选择是对数正态分布。
PDF of log-normal distribution
这种分布的最佳特性是逆分布也是对数正态分布,具有相同的参数 σ 和反向参数μ。这意味着,如果故事持续时间是对数正态分布,那么项目速度也是对数正态分布!
我们将使用与上一个笔记本中相同的示例
**import** **numpy** **as** **np**
**from** **scipy.stats** **import** lognorm
data=np.array([14, 12, 7, 14, 13])
shape, loc, scale = lognorm.fit(data, floc=0)
fitted = lognorm(shape, loc, scale)
print(f'Mean: {fitted.mean()}')
print(f'Standard deviation {fitted.std()}')
print(f'95**% c**onfidence: {fitted.ppf(0.05)}')Mean: 12.046405137951629
Standard deviation 3.195066701596986
95% confidence: 7.582961342994959*#Let's plot it*
%**matplotlib** inline
**import** **matplotlib.pyplot** **as** **plt**
**def** plot_dist(frozen):
fig, ax = plt.subplots(1, 1)
x = np.linspace(5, 22, 100)
ax.plot(x, frozen.pdf(x), 'r-', lw=5, alpha=0.6, label='lognorm pdf')
plot_dist(fitted);
所以答案接近泊松分布给出的答案。让我们试着找另一个团队,他们可能有更低的速度,但是更可靠的估计:
data=np.array([10, 11, 12, 10, 11])
shape, loc, scale = lognorm.fit(data, floc=0)
fitted = lognorm(shape, loc, scale)
print(f'Mean: {fitted.mean()}')
print(f'Standard deviation {fitted.std()}')
print(f'95**% c**onfidence: {fitted.ppf(0.05)}')Mean: 10.799871930716652
Standard deviation 0.7427443647589952
95% confidence: 9.62328932436764plot_dist(fitted);
我们看到,即使这个团队的速度低于第一个团队,如果经理要求你有 95%的信心,你可以选择第二个团队,因为它可以在迭代中可靠地完成更多的故事点。
这里可以找到笔记本。
农业技术 2.0——机器的崛起
Case IH Magnum Autonomous Concept Tractor
最近媒体上有很多关于自动驾驶汽车和人工智能(AI)等新技术的谈论。这让人想起阿诺德·施瓦辛格在《终结者》中的形象,“天网”扮演反派,因为它变得有自我意识,并命令机器反抗人类。
幸运的是,这些新兴技术的现实实际上比好莱坞暗示的要光明得多。农业是一个人工智能和自主设备可以增加巨大的经济和环境价值的行业,以帮助养活世界上不断增长的人口。
农业行业涌现出越来越多的颠覆性公司,它们正在开发传感器、机器自动化和数据科学等新技术。例子包括土壤湿度传感器,如提高灌溉效率的 CropX。使用无人驾驶飞行器(UAV)监测作物健康和生长阶段的能力,如 AgEagle 。最近,我们已经看到自动驾驶拖拉机的出现,如 CNH Industrial 所展示的。
将所有这些颠覆性传感器和硬件技术结合在一起的粘合剂是数据科学。预测软件平台的一个全新的产品部分,如 AgDNA 现在已经上市,并且正在快速发展。总的来说,这种新一代农业技术被称为农业技术 2.0,它们将共同改变粮食种植的方式。
问题
耕作是艰难的。技术可以提供帮助。
大规模的商业农业就像经营一个大工厂——只是在户外!是的,这个作物生产“工厂”暴露在自然环境中,没有墙壁或屋顶,它有间歇性的电力供应(阳光、降雨),劳动力短缺(农村地区),收入波动(商品价格),并且假设作物一直存活到成熟,每年只支付一次工资。
正是天气、土壤类型、产量和收入的这种程度的可变性,使得农业具有难以置信的风险。事实上,没有两个季节是相同的,这意味着从一个季节到下一个季节的决策充满了不确定性。
今天的技术及其产生的基础数据将改变未来农场决策的方式。从一个季节到下一个季节,高分辨率数据和有关种植系统所有方面的信息的可用性意味着农民将有能力根据对历史结果的深入分析做出计算决策。
数据科学
在寒冷的气候下,世界上许多农民一年只能种植一种作物。因此,在他的职业生涯中,农民可能只有 40 次“做对”的机会。这给错误留下了很小的空间。
农业技术 2.0 将为种植者创造公平的竞争环境。田间传感器现在全天候向大数据算法传输数据,大数据算法不断处理信息,并提供实时见解,帮助种植者做出明智的决策。
展望未来,没有数据,这只是一种看法。
有几个关键因素将 AgTech 2.0 软件平台与传统的精准农业桌面工具区分开来。新一代软件平台包含以下属性,以便在 AgTech 2.0 级别上竞争:
-基于云的集中式数据
-与支持互联网的传感器实时连接
-与所有主要品牌设备的互操作性
-自动化大数据处理能力
-具有预测洞察力的算法
解决方案
AgTech 2.0 正在将农业从依赖人类生成的数据转移到自动化机器生成的连续数据流。也就是说,农业从来不缺数据。自 20 世纪 90 年代中期以来,联合收割机一直在记录产量。然而,直到现在,土壤、气候、植物健康、灌溉和管理实践等其他关键输入才以数字形式随时可用并实时传输。
AgTech 2.0 下一代平台使用实时真实数据为预测模型提供信息,这些预测模型可以根据从历史结果中得出的模式和结果生成预测和见解。种植者或农学家仍将决定需要做什么。但有了这种新型工具,它就成为一个高度明智的决策,降低生产风险和增加经济回报的可能性更大。
真实世界的例子
AgDNA 等公司的目标是在种植者知道该问什么问题之前提供答案。
目标是在小问题变成大问题之前解决它们。如前所述,农业中的误差幅度很小。这个季节早期的问题会限制植物的生长潜力,严重影响收获后的产量。
在 AgTech 2.0 硬件平台不断传输高分辨率数据的同时,其软件平台也在分析这种实时传输,以找到提高产量或降低运营成本的见解。
举个例子,一辆拖拉机穿过田野去种玉米。今天,这种拖拉机基本上是自动驾驶的,使用 GPS 定位在田间精确导航。
用于驾驶拖拉机的测量级 GPS 数据也可用于构建田地的 3d 高程模型。一旦知道了油田的地形,智能软件平台就可以识别出洼地。这些是田地中的低洼地区,在暴雨期间没有排水能力。
知道了这些低气压区的存在,软件就能计算出如果田地降雨量高于平均水平,某些疾病可能会发生的可能性。通过分析数十万英亩类似排水问题的历史结果,大数据软件可以确定整个田地或特定洼地中各种农艺问题的概率。
有了这些信息,系统可以向农民或农学家推荐一个处方进行评估。然后可以根据经济回报决定是否施用最佳量的杀真菌剂来防止疾病仅在低洼地区爆发还是在整个田地中爆发。
此外,当作物收获时,可以将所得的产量数据与 3d 高程图进行比较。如果排水不良和低产之间的关联概率很高,那么可以根据成本效益分析做出是否纠正问题的经济决策。这种级别的信息为种植者提供了商业案例和财务建议,因此他们可以确定是否愿意在未来的生长季节纠正排水问题,以增加利润。
这只是许多使用案例中的一个例子,在这些案例中,可以自动捕获和分析数据,以确定是否存在提高盈利能力和管理整个农业运营风险的经济机会。
农业科技 2.0 的未来
农业科技 2.0 运动将快速加速。大量资本投资正从私人投资者、风险资本家和主要原始设备制造商和投入物制造商流入该部门。短期的挑战不是技术,而是不同制造商之间缺乏数据标准和兼容性。
一些关键的颠覆性技术包括:
无人机
无人机目前面临的挑战包括发射所需的时间、有限的飞行时间和数据的自动化处理。随着时间的推移,这些问题将被克服,无人机将像一个超级本地卫星系统一样为每个农场提供高分辨率数据。
传感器
新的拖拉机、喷雾机和收割机已经包含数百个传感器,向云提供农艺和操作见解。未来,传感器将走出驾驶室,进入田间,提供针对每株植物的实时土壤和作物健康信息。
机器自动化
无人驾驶机械将成为常态。这并不是说每一项操作都将是自主的,而是像喷洒这样的低效率活动将是自动化的。此外,它们将由较小的电动车辆进行,这些车辆仅在杂草出现(或预测到)时喷洒,以确保最低的成本和最低的环境影响。
数据科学
与大多数行业一样,上述所有硬件解决方案都将商品化,价格是一个关键的购买因素。真正的价值在于从资本设备和最终数据中最大化经济价值的底层算法。
这是一个激动人心的农业时代。任何有前途的程序员、工程师或科学家都会被建议探索精准农业作为职业道路。对于我们这些已经在农业技术领域的人来说,我们有责任确保我们提供切实可行的解决方案,为种植者解决现实世界的问题。AgTech 2.0 是要遵循的路线图。
希望我们不会很快看到阿尼的天网战士占领农场。我们将看到新一代 AgTech 2.0 硬件和软件解决方案在农场中的应用,帮助种植者做出重要决策,并提高其运营的盈利能力和可持续性。