从杯子到意识(第三部分):用 SLAM 绘制你的家
SLAM 简介,深入了解 SLAM 前端和传感器套件
Our favourite animated robo-mascot treasure hunting for cups with his map. By instagram handle mizumitodepapu
在 MTank ,我们朝着两个目标努力:
(1)在 AI 内部建模和提炼知识。(2)朝着创造真正智能的机器前进。作为这些努力的一部分,MTank 团队发布了关于我们工作的片段,供人们欣赏和学习,完全免费。如果你喜欢我们的工作,那么请表明你的支持。提前感谢!
- 第一部分:杯子和智力有什么关系?
- 第二部分:从模拟到现实世界
- 第 3 部分:用 SLAM 绘制你的家
介绍
“你所需要的只是一个计划、一张路线图和朝着目的地前进的勇气”——厄尔·南丁格尔
在本系列的前一部分中,我们谈到了通往 AGI 之路是如何被分为感知和控制的。在控制范围内,导航和抓取是构建用于家务的通用机器人路线图的关键部分。但是正如柴郡猫在《爱丽丝梦游仙境》中对爱丽丝说的那样,
如果你不知道你想去哪里,你走哪条路真的重要吗?
这是两部分中的第一部分,我们将讨论我们的看似被绑架的机器人如何找到他们的方位。我们是什么意思?从他们的角度来看,每栋房子都是他们被扔进或突然醒来的神秘地方。正如人们可以猜测的那样,这一发现过程几乎完全属于感知领域,从逻辑上讲,这也是我们应该开始的地方。一个人必须先感知 ,然后才能相应地行动,包括了解你的周围,绘制你的环境,即了解哪里是什么,哪里是“被占领的”,哪里可以畅通无阻。
考虑一下制造能完成一般任务的机器人的第一步。忘记让机器人做单一的任务,例如,用 roomba 打扫地板,用 alexa 告诉你时间,还有一个烤面包机器人。为了执行一般任务,我们需要我们的机器人知道它的环境,即识别什么是障碍,以及东西在哪里,并使用这些信息来导航和完成任务。
似乎很简单。
模拟中的映射
在第一部分中,我们介绍了我们挑选杯子的哲学动机和愿望,并介绍了一组模拟的 3D 房屋环境。在第 2 部分中,我们介绍了 ai2 house 环境的包装器、一些强化学习(RL)实验和两个名为 PyBullet 和 Gazebo 的特定物理模拟,使我们能够将机器人向量放到月球上。
知道了映射是我们的下一个里程碑,我们自然开始在 PyBullet 模拟中实现初始映射。由于 PyBullet 包含深度和彩色 RGB 图像,以及相机的姿态(位置和方向),我们可以使用来自虚拟相机的深度信息来将每个 2D 像素转换为其在空间中的 3D 坐标,创建所谓的点云。
使用该点云,我们可以创建一个网格数据结构,定义机器人可以移动到哪里以及机器人周围的障碍物在哪里,即占用网格。这种深度图像,到点云,到占用网格管道是计算机视觉和机器人学中非常常见的操作。
扩展一个官方的 PyBullet 代码示例,从深度信息创建一个点云,我们能够在模拟的厨房中获取地板上和屋顶下的所有点。由此,我们创建一个占用网格,每个网格单元显示10 cm2区域的可能可通过性。这样,网格中的每个区域都被分配了一个被占用的概率。事实上,这是机器人导航最常见的格式和方法。
Note: Our own simulated PyBullet kitchen and living room with dynamic objects (e.g. beer bottle, bowl, cup, etc) and occupancy grid mapping with exact pose information. Within this GIF, we also present a semantic object occupancy grid map, mapping aggregation and a simulated robot with 2 wheels and a caster wheel moving around the living room with depth and segmented views displayed from the viewpoint of the robot. The semantic map describes which grid cells are occupied by specific objects. The aggregation combines the information from 3 viewpoints (local maps) into one merged map.
那么我们学到了什么?
这教会了我们很多关于占用网格、传感器模型以及将多个视点聚合到一个大的占用网格中的知识。但是上面提到的一切都是使用 PyBullet 提供的相机的精确姿势(位置和方向)找到的。我们知道接下来有必要找到一种方法在世界中定位代理的姿势,特别是在真实世界中。
正如我们在上一篇博客中提到的,我们决定从模拟转向首先让算法在真实机器人上工作。一个简单的原因是:与虚拟场景相比,真实摄像机会出现更多问题。
在未来,为了扩大我们的机器人可以处理的任务、杯子、水壶和环境的数量,我们肯定需要模拟。但是现在,真实的世界杯选拔赛每次都胜过黑客帝国风格。如你所见,通往 AGI 的道路漫长、曲折且充满危险。这一切都始于首先找到自己。
同步定位和绘图(SLAM)
“直到我们迷失了,我们才开始发现自己” —亨利·大卫·梭罗
使用已知的定位(映射问题)创建地图相对来说容易,在已知的地图内定位也相对来说容易(定位问题)。两者都有许多解决方案和变体,但是如果我们既没有机器人的姿态,也没有地图,会怎么样呢?也就是说,当我们不知道自己身在何处时,如何创建环境地图?
这个,相对来说,就没那么容易了。
回到我们被绑架的机器人,他刚刚被放在一个未知的房间里。一睁开眼睛,它怎么知道自己在哪里?大多数人会自然地使用他们周围的参考地标,即床、电视的角落、开着的门,来粗略地定位他们自己在环境中的位置。映射和本地化是密不可分的,它们相互需要,就像烤面包需要黄油一样,本质上是一个鸡和蛋的问题。
为了以极快的速度拿起杯子,并在机器人从未见过的家中操作,它应该能够在环境中定位自己,同时绘制地图,即找到世界各地的三维位置。这就是为什么在我们的旅程中,我们不可避免地到达了同步定位和绘图(SLAM) 领域。
SLAM 研究可以通过用于解决问题的传感器套件进行分类(稍后将详细介绍)。例如,您可以使用一台相机(或一组相机)通过在环境中检测到的地标来找到机器人的姿势。但是当灯关闭时,你可能不相信这些相机的弱点,或者视觉场景可能会令人困惑,在这种情况下,你可以使用雷达来代替。或者,就像大多数制造自动驾驶汽车的公司一样,如果你需要一个更可靠的传感器,可以发现距离你数百米远的物体的高细节,你可以使用昂贵的激光雷达。
**没有一种传感器可以解决我们所有的问题。**我们将需要将许多传感器结合在一起(即传感器融合),以寻求建造能够以我们能够理解的方式理解世界的机器人,同时保持低成本。为此,我们决定将精力集中在视觉算法上。即基于摄像机的 SLAM,或如文献中所命名的视觉 SLAM (V-SLAM)。
两年多前,我们在我们的计算机视觉报告中提到了 SLAM,现在我们很高兴有机会真正深入这项迷人的技术。如果您正在寻找一篇好的评论,或关于最新技术的详细信息,我们推荐:
典型 SLAM 系统的架构
一个典型的视觉 SLAM 算法有两个很容易并行的主要部分,这意味着即使两个部分互连,它们也可以独立运行。根据文献,我们将这些称为“前端”和“后端”。
前端
前端将传感器数据抽象成易于评估的模型。它负责预处理输入,以及检测和跟踪相关的标志,以估计我们观察它们的姿势序列。
在 VSLAM 的情况下,实现这一点的算法是视觉里程计(VO),它本质上是根据显著的视觉特征来计算两帧之间的相对姿态(变换)。
最常见的方法是从一帧中提取关键点(例如使用 SIFT、ORB ),然后在下一帧中匹配这些相同的关键点或者用光流跟踪它们。此外,在匹配/跟踪来自不同位置的那些观察到的关键点时,这些算法的性质可能导致错误数据关联的误差,因此通常在之后应用另一种算法来移除可能的离群值,这些离群值可能会将附加误差传播到我们的估计,例如随机样本一致性(RANSAC)。
另一个重要的考虑是,如果我们持续跟踪每张图像的每个显著点,我们将消耗大量的内存,包括大量的冗余信息。出于效率原因,通常仅观察到所有图像的子集,这些“关键帧”由选择算法选择,同时仅在关键帧之间匹配和跟踪观察到的特征。一个简单的关键帧选择算法是每第 5 或第 10 帧取一个,但其他方法只涉及如果图像与前一帧相比有足够大的变化就添加一个关键帧(例如,测量变化的视差或关键点移动的距离)。
Source: ORB-SLAM in the KITTI dataset (Sequence 00) YouTube link Note: The top view is from the KITTI dataset with ORB features overlayed from ORB-SLAM2. On the bottom we see top-down trajectory in green but only the blue frustums are keyframes. In red are the features which are tracked.
Note: By adapting a simple VO example in Python (from here) and by using every 10th frame as a keyframe we were able to get reasonably good results on a sequence in one of our houses. The top down trajectory is shown on the right on the black background as we go around a table 3 times with the camera attached to a chair. But this example was carefully cherry-picked; other sequences didn’t show as reliable results on the trajectory estimation. In general, the algorithm suffers from severe drift problems, e.g. by using only every 5th frame as a keyframe this caused caused the drift errors to accumulate much faster. This per keyframe error can be blamed on many factors e.g. calibration, initialisation or monocular scale issues.
此外,我们可以计算两个连续点云之间的转换(例如,使用迭代最近点(ICP)算法的点云配准)来定位代理的轨迹。
Note: Pointcloud registration is about finding the transformation from one pointcloud to the other so that they overlap and align together in a way that makes most sense. The GIF shows the resulting point cloud (yellow + blue) after the registration step is performed, i.e. one of the point clouds (yellow) is transformed to be aligned to the other one (blue: which is the reference to align to), optimising the transformation so that overlaying this transformed point cloud onto the reference represents a single scene as consistently as possible. This obviously implies some overlap and consistency between both pointclouds. This relative transformation between two frames/pointclouds can be the basis of RGB-D or LiDAR odometry. For reference, a famous algorithm for computing this registration is called Iterative Closest Point (ICP).
此外,我们可以使用在图像中发现的特征的较低维度的表示,而不是它们的完整描述,例如通过使用“视觉单词包”方法(DBoW ),其创建可能特征的字典,并将图像转换为由可能特征(或字典中的“单词”)的组合形成的向量,用于更压缩的表示。然后,这可以用于位置识别/重新定位和循环闭合。
Source: Bag of Visual Words in a Nutshell Note: First row are the images, the second row are the image patches from these images and the third row are the histograms “bag of visual words” in a simplified four word dictionary.
后端
后端通常是使用从前端提取的所有信息的组件,以便构建、扩展和进一步校正机器人的轨迹和地图。它包括几个算法,如束调整,其目标是通过在一对以上的帧上实施重投影一致性来纠正错误。它还扩展到使用估计的不同姿态生成和优化图形,以及比较由前端存储的视觉单词包,以完成重新定位和循环闭合。
闭环包括当机器人识别出先前看到的位置时对图形进行修正。利用这些信息,我们可以减轻在整个 SLAM 过程中可能遇到的累积“漂移”误差。
为了让您更清楚地了解这些不同部分如何相互作用,这里是我们最喜欢的 SLAM 系统之一的高级架构。
Source: RTAB-Map slides Note: Without the back-end, SLAM essentially reduces to odometry. RTAB-Map is an amazing SLAM algorithm that works out of the box and creates a dense pointcloud and an occupancy grid. It can be used with an IMU, stereo camera and an RGB-D camera (more on what these sensors do below)
传感器套件:单声道、立体声、RGB-D、IMU
不言而喻,不同的传感器配置可以使 SLAM 的任务更容易或更困难。通常,你的传感器提供的信息越多越好,但是对于额外的传感器,你还需要以一种巧妙而有原则的方式合并和融合它们的信息。从计算角度来说,这可能会变得非常昂贵。理想情况下,通过使用多个传感器,它们的优点和缺点相互抵消,系统变得异常稳定,但这种选择通常需要权衡。
单目 SLAM 涉及使用单个摄像机作为 SLAM 相应算法的输入。这受到比例问题的影响,即从单目 SLAM 系统的角度来看,如果相机相应地缩放,我们无法区分普通家庭和“玩偶之家”之间的大小差异。这个比例问题可以通过各种方式解决,例如良好的初始化程序或使用物体的已知长度或真实世界的距离。尽管处理这些缺陷在算法上可能更加繁琐。就机器人硬件和架构而言,拥有单个传感器是一个非常简单和优雅的解决方案。一些著名的例子是 MonoSLAM,ORB-SLAM 和 LSD-SLAM。
Note: Example of tracking points using a monocular camera.
从初始位置(从红色图像)的一组“n”个观察点(在这种情况下是房子上的 4 个),我们在场景中移动并捕捉第二个图像(以绿色突出显示)。使用匹配算法,我们可以在第二幅图像中找到第一幅图像上观察到的点,并使用该信息来计算相机的运动(里程计)和场景的结构(观察点的 3D 坐标)。来自运动的结构(SfM)是另一个著名的领域,与单目 SLAM 有许多相似之处。通过查看关键点在两帧之间移动了多少,我们可以计算第二帧中相机的外部变换。
我们发现我们的一台 RGB 摄像机的水平视场(FoV)非常小,为 69.4 度,如果移动太快,可能会导致跟踪失败。更大的 FoV 理论上允许即使在更长的位移之后也能跟踪相同的关键点。在未来,我们还将试验更宽 FoV 的相机,如鱼眼镜头相机,它在给定的时间内观察更大的区域,因此与较窄 FoV 的相机相比,在以更高的速度跟踪观察到的场景方面,可能会使我们的生活变得更容易。
Note: With a common laptop webcam we can barely capture the center of the living room (right), whereas the 200 degree wide angle camera (left) allows us to look at the entire living room, part of the kitchen on the left and also a small peek into the bedroom after the corridor to the right.
立体视觉涉及使用两个摄像头来寻找场景的结构。从不同的已知位置同时拍摄两幅图像具有显著的优点。例如,在单目 SLAM 中,匹配发生在不同时间的两幅图像之间,这意味着在这些时间之间,场景中的任何对象都可能移动,这将完全破坏视觉里程计计算,而在立体视觉中,匹配是在同时拍摄的图像之间进行的,即不需要移动。然而, stereo SLAM 实际上大多数 SLAM 仍然会有这个“动态对象问题”,因为它们仍然必须跟踪跨多个帧拍摄的相同特征。流行的立体声灌篮是 VINS 融合或软式灌篮。
此外,典型的匹配算法需要在计算上昂贵的匹配搜索,但是由于在这种情况下摄像机的相对位置是已知的,我们可以将两个图像投影到一个假想的平面,以便使搜索更容易并且防止匹配上的一些错误。这个过程称为立体纠正,如下图所示。
Note: The dotted rectangles represent the original unrectified images. The epipolar lines help on matching by constraining the search to the epipolar lines marked in solid red. The solid black rectangles represent the rectified images, in which the epipolar lines are all parallel to the horizon, allowing for a more efficient search of possible matches.
Note: Example of the left and right stereo infrared images (from the RealSense D435i camera we bought in the top and bottom left) with a calculated disparity image on the bottom right and colour image in top right. If you alternate closing your left eye and right eye, you should observe that objects closer to you appear to jump in position more compared to objects further away (see the pen in both infrared images being in different positions). This is essentially how stereo vision can calculate disparity/depth (bottom right). The pen is so close that it gives a blind spot to one camera from calculating disparity in certain parts of the disparity image. Calculating this disparity from two (preferably rectified) stereo images essentially computes the inverse depth map which can be visualised with a colour map going from white to yellow to red, in which white represents close distances and yellow is further away.
**被动对主动。**立体视觉不一定非要用被动式 RGB 相机计算视差图,也可以做主动式立体。主动立体将光束投射到世界上,通过使用变形模式,它可以帮助提高深度的准确性。更多关于整流和有源与无源立体声的信息在这里。
RGB-D SLAM 通常指 SLAM 系统的输入是彩色和深度图像时。深度可以通过使用商业深度相机来实现,商业深度相机通常包含立体相机,但是如何检索和优化的细节留给深度相机的内部。由于具有这些像素的深度信息,RGB-D SLAM 能够计算密集图,即包括所有可见像素的密集图。与上述稀疏特征(即少量关键点)相比,这代表了可以在密集地图中使用和显示的丰富信息。在下一篇博客中,我们将介绍 RTAB 地图(之前展示的架构),这是一个优秀的 RGB-D SLAM 系统,但其他著名的例子包括 KinectFusion 和kintinulous。
Note: We bought the RealSense D435i depth camera from Intel. Above is the RealSense viewer. In the color RGB image (bottom left) we can’t see as much in dark areas compared to the infrared images (top 2) which can see better in the dark. Also enabling and disabling the emitter will show or remove the white projected dots. The emitter improves depth accuracy (you can see as it turns off and on in the depth image in the bottom right) and is good for textured areas. One can disable the IR emitter and use the infrared cameras as a typical stereo pair but it is grayscale only.
Note: The depth accuracy is high and it works out of the box. Active stereo RGB-D cameras works better at low light as well as night time. The camera also contains an internal IMU and we can see the accelerometer and gyroscope display on the right. Half way through, we switch to the 3D point cloud viewer.
Note: An example of the RealSense rs-motion program which demonstrates how a Complementary Filter can be used to estimate orientation but not position on the D435i using the inbuilt IMU only.
惯性测量单元(IMU) 通常包含加速度计和陀螺仪(有时还包含磁力计)。在 D435i 包含的 IMU 中,第一个测量加速度,第二个测量角速度,两者都测量 3 个自由度(DoF ),从而在这个 6 DoF IMU 中形成 6 DoF。许多其他变体也是可能的,例如,内置的磁力计将使其为 9 DoF,更简单的 3 DoF IMUs 通常用于自动驾驶汽车。
然而,从这些中提取位置涉及双重积分(因为加速度的积分是速度,而速度的积分是位置),甚至现有技术的解决方案也涉及大量的定位偏差,这些偏差将随着时间的推移而显著累积。这就是所谓的漂移,也是为什么 IMU 定位系统通常需要结合视觉反馈来减少漂移。
IMU 的主要用途是根据原始数据以高频率计算机器人的方位。例如,在我们的 D435i 中,加速度计可以设置为 250Hz(每秒 250 次测量),陀螺仪可以设置为 200Hz,并且可以对原始数据使用滤波器(例如卡尔曼或互补滤波器)来计算 IMU 的方向。
当你在 VO 系统中增加一个 IMU,就叫做视觉惯性里程计(VIO) 。如果您选择并仔细调整正确的 VIO 系统,还有许多方法(松耦合和紧耦合)可以输出几乎“无漂移”的定位。我们推荐“ 用于飞行机器人 的单目视觉-惯性里程计算法的基准比较”论文,以了解使用 IMU 的顶级 VIO 或 SLAMs 的概况。在下一篇博客中,我们将谈论一些伟大的 VIO 系统,如 VINS-Mono 和 ROVIO。
所有 SLAM 狂热者可能都梦想最终的 SLAM 系统能够处理任何情况(弱光、低纹理、快速运动、循环闭合、遮挡、动态对象和场景),并且仍然非常健壮。我们称这种神秘的神话生物为**“跑酷满贯”**。
虽然这可能是纯粹的废话,只是一个荒谬的梦想,但适用于快速无人机的算法,如这些 VIO 系统,接近速度和灵活性的要求。因此,也许其中一个可能是我们正在寻找的跑酷大满贯,或者也许在未来的某一天,我们梦想中的大满贯将会到来。这个博客系列的第 4 部分将是我们试图找到这个街头顽童 SLAM 算法,用技术问题无情地测试它,并奖励一个 SLAMdog 百万富翁 100 万美元。
Source: ROVIO YouTube Note: Incredibly fast movements, could this be our ultimate champion SLAM, the Parkour SLAM?
基于功能与直接
Source: wavelab waterloo slides. Very good slides that are worth checking out to go deeper into many direct methods and compare them on a high level with feature-based SLAMs.
从自 2012 年以来一直主导计算机视觉的深度学习(DL)革命的角度来看,很容易被大多数 SLAMs 使用“经典”关键点或特征检测器(例如 SIFT,ORB,FAST,Harris corners)的事实所迷惑。考虑到围绕 DL 的大肆宣传和良好业绩,这是令人惊讶的。那么为什么没有深球呢?
首先,重要的是要提到,在“经典”分类管道中,关键点描述符被用作特征工程步骤,然后典型的分类器被用于输出类,例如支持向量机(SVM)。这个范例被 DL 完全破坏了,但是主要的收获是关键点和关键点描述符是不同的:关键点描述符是描述以关键点为中心的图像块的统计属性的值的向量,关键点指的是点本身,即它们的位置。
关键点在这里是非常常见且直观有用的,因为 SLAM 找到这些检测和跟踪的 2D 关键点所代表的 3D 点的几何关系和位置。事实上,这就是 VSLAM 所做的事情。
SLAM 可能会随着 DL 的使用而得到很大的改进——关键点检测、语义或者可能是“端到端 SLAM”。然而,经典的特征检测器目前做得很好。有关 DL 和 SLAM 如何相互帮助的更多信息,请查看 Tomasz Malisiewicz 关于实时 SLAM 和深度学习 vs SLAM 的精彩博客。
Note: This image highlights the difference between keypoints (2D pixel positions) or image descriptors of an image. In general, it’s important for feature detectors to repeatedly find re-identifiable parts of an image which can be found in successive frames e.g. corners, edges, points. Whereas the descriptor of each keypoint is a vector describing an image patch around the keypoint.
Note: Example of keypoints extracted using ORB features in ORB-SLAM2 algorithm running on a sequence from one of our houses. When referring to the word “features” it can mean a combination of the keypoint and its descriptor or just the keypoint. At the end of the GIF we see an example of loop closure fixing the accumulated drift. Keep an eye out for part 4 of this blog which covers the back-end and loop closure for greater depth on this.
SLAM 中还有另一个新兴的范例,它避免了稀疏关键点检测器的使用。这些所谓的“直接方法使用像素强度——来自图像的未经处理的 RGB 值——来直接估计相机的运动。这最小化了光度损失,而基于特征的方法通常最小化了几何损失。光度学本质上意味着我们正在计算如何使用直接来自两幅图像的像素值将第一幅图像投影扭曲成第二幅图像。通过最小化强度差异,我们对来自原始图像和经变换的合成生成图像的变换实施一致性。
Source: link Note: This highlights the projective transformation (T) between the first image to the second. Finding the correct T is the goal here.
直接方法中有许多变化。例如,我们可以使用 中的稀疏点直接稀疏里程表 (DSO) 。中的 DSO 论文很好地比较了密集+直接、密集+间接、稀疏+直接、稀疏+间接这四种组合。我们鼓励你去看看,特别是如果你像我们一样感到困惑的话。
另一篇著名论文 半密集视觉里程计 (SVO) 是基于特征和直接方法的混合。这意味着它仅跟踪来自边缘和角落的高梯度像素(使用直接光度误差),但是依赖于基于特征的方法来联合优化结构和运动。这些组合就是为什么它被认为只是“半直接”的原因。
Direct 有可能能够跟踪图像中纹理较少的部分,而基于特征的 SLAM 可能会发现这更加困难。许多著名的满贯狂热者相信直接满贯最终会战胜间接满贯。但是基于特征的 SLAM 的结果说明了一切。只有时间能证明一切。
结论
总之,我们讨论了一切,从映射背后的动机,模拟中的映射,到本地化和映射如何迫切需要彼此(SLAM);以及许多相关领域(例如视觉里程计、SfM)和不同 SLAM 算法之间的变化轴(例如它们的前端与后端、传感器套件等)。).不仅如此,还包括使用的具体方法,例如直接与基于特征、稀疏与密集地图/点云,以及这些系统是否具有全局优化和闭环。为了说明不同的 SLAM 是如何变化的,你可以在下表中找到许多著名 SLAM 之间的比较。
Source: Visual SLAM algorithms: a survey from 2010 to 2016 Note: This compares many different SLAMs across their varying dimensions. For example, the visual SLAM algorithms used with the raw image data could be feature-based (ORB-SLAM, MonoSLAM) vs direct (DTAM, LSD-SLAM) vs semi-direct (SVO) vs RGB-D (KinectFusion, SLAM++).
我们希望这个博客能够在很大程度上介绍和总结 SLAM 的前端组件。在某种意义上,这个组件主要负责计算相机的里程表。在我们看到的一些案例中,它可以在不需要任何后端组件的情况下产生高度精确的定位。
然而,机器人的轨迹越长,漂移就会积累得越多,即使每 10 公里仅平移 1 毫米或旋转 1/100 度,这种漂移也会增加。因此,在我们看来,需要一个后端系统和识别以前位置的能力。幸运的是,我们将这个组件的细节留到了本博客系列的下一部分,其中将包括束调整、姿势图创建和优化,以及循环闭合。
但是最激动人心的部分还在后面!在下一期的 C2C (#cuplife)中,我们将展示我们对 SLAM 中大量先进系统的选择和评估,包括我们测试过的一些算法以及我们认为该领域未来可能的发展方向。敬请期待!
从数据科学到 AI?
一个是人,另一个是机器…它指引着我们!
让我们玩个游戏,好吗?对于我给你的每个单词,你会告诉我在人工智能和数据科学之间首先想到的是什么?好吗?没有欺骗,没有宗教战争(如果你觉得有些奇怪,强迫自己朝着一个方向,问问自己为什么)。
准备好了吗?
走吧,一次一个,阅读并意识到你的联想——
数据科学还是 AI?
- 自治
- 统计数字
- 机器人
- 机器学习
- 终结者
- 光学字符识别
- 2001:太空漫游
- 形象化
完成了吗?好,我先来:
- 自主— AI
- 统计学— 数据科学
- 机器人— 人工智能
- 机器学习— 都有!
- 终结者— 艾
- OCR(光学字符识别)——数据科学
- 2001:太空漫游— 艾
- 可视化— 数据科学
这些和你的相配吗?如果他们这样做,原因可能是文化或时代精神。如果我们把时间拨回到 30 或 40 年前,一个自动识别你的糟糕书法的系统[抱歉,10%的人用摄像机拍下了不清晰的书法 T20,这仍然是人工智能。“会阅读的机器眼”!今天,OCR 可以在移动设备上完成,尽管它并不总是准确,但它太普遍了,以至于不再被视为人工智能。
为什么有些东西可以不被认为是人工智能?数据科学也会发生同样的情况吗?首先,人工智能是一个负载很重的术语,与科幻小说有很强的关联,也与人类思考和学习的能力有很强的关联。这些联系引发了我们的情感反应,或者与我们的年轻、我们的激情,或者甚至是我们对什么使我们成为人类的哲学思考有关。
现在…数据科学有没有让你思考是什么让你成为人类?如果不是,那是因为它是一个比人工智能更精确的术语,而且没有人工智能那么神秘。
但是还有更多。更具体的东西。
数据科学是人类——人工智能是机器
AI 是一台机器获取并应用知识和技能的能力,而数据科学是一个人对数据的系统学习和应用。人类可以利用数据科学来创建人工智能系统的组件。相反的情况只发生在科幻小说中,只有在遥远的星系中,人工智能系统才有能力进行数据科学。
在这之间呢?机器什么时候变得智能?
没有硬性门槛。人工智能需要 4 种基本能力:感知、知识保留、思考和适应。这些包括感知、过滤、解释、存储、抽象、推理、理解、学习和在环境中行动。这些功能越发达,系统就越智能。因此,即使是计算器也有一定程度的智能。类似于狗、海豚和任何人类的智力水平。如果一个人工智能系统胜过人类,那么它通常被称为拥有超级智能(除了非常具体的任务,截至 2019 年,我们离超级人工智能还非常远)。
那么,为什么 AI 也经常被描述为一个巨大的技术领域,包括机器学习、深度学习、统计学等等?一个关键的原因是人工智能的 4 种能力可以用这些方法来开发。如果是人类应用它们,那就是数据科学创造了人工智能;如果是机器,那就是 AI 创造 AI。例如,当机器学习系统被训练时,它是由机器完成的,因此它是一个解决某个任务的人工智能系统。数据科学是围绕培训的一切。这也意味着许多数据科学工具具有智能的某些能力,可以被定义为人工智能。如上所述,人们是否愿意称它们为人工智能,或者“超自动化”取决于文化因素。
数据科学可以产生人工智能
然而,数据科学并不是产生人工智能的唯一途径。有人认为进化、、量子力学以及其他尚待发现的方法也能产生人工智能元素。尽管如此,今天数据科学和人工智能之间有着强大的协同作用:虽然数据科学实际上让事情发生,但人工智能为我们提供了强大的工具和抱负,为我们指明了道路。
从开发到生产——让 Flask 应用程序在 AWS 上运行所需要知道的一切
获得正确的配置,确保它是安全的,确保通过端点访问资源,并有一个漂亮的渲染,…所有这些都是因为 AWS 而变得容易!
作为一名机器学习工程师,我从未真正面临过把我的算法发布出去的问题。嗯,直到最近,当我决定开始我的多重创业之旅…不幸的是,当你开始时,你没有 DevOps 或软件工程团队。这些人对客户使用这些服务的世界很有经验,他们知道如何跨越最后一步,让你的产品从零到一。
现在,我不得不花几个小时阅读教程和文档来学习基础知识,最后,将我自己的算法作为全球可用的独立容器化服务。出于可复制性的明显原因,我对这些步骤进行了模板化,我非常乐意与您分享这些模板!😃【模板托管这里。]
准备战场!
他的初始化步骤至关重要,取决于你的实践。在这里,我揭露了我做这件事的方式,但是你可以自由地创新。到目前为止,我唯一的假设是,你有一个适当的 AWS 帐户,并且你知道如何在服务之间导航!
- 安装并配置 AWS CLI: AWS 教程。
- 安装并配置 AWS Elastic Beanstalk CLI: AWS 教程。
- 下载模板:您目前有三种选择:您可以从文件夹模板中单独下载每个文件;您可以克隆 project Challenger 的整个存储库,这是我存放模板的地方;您可以使用 subversion 通过以下命令下载特定的文件夹:
sudo apt install subversion
svn checkout [https://github.com/Coricos/Challenger/trunk/templates/beanstalk](https://github.com/Coricos/Challenger/trunk/templates/beanstalk)
- 定义您的开发环境:
virtualenv -p python3 beanstalk
cd beanstalk
source bin/activate
pip install -r requirements.txt
- 在
application.py
中构建您的 flask 服务器!首先在您的本地机器上试一试,检查一下一切都运行正常,并确保将服务器启动封装在__main__
中。另外,这是 AWS 的特定要求,但是您的应用程序的名称应该明确为application
…
有用!现在怎么办?
B 因为我发现 AWS Elastic Beanstalk 是运行我的应用程序的最佳服务,我天生就愿意展示它。为什么?主要是因为在 beanstalk 实例上运行的内容可以在任何其他类似的服务和云提供商上产生。这给了您无限的灵活性(我甚至没有说使用 Docker 来获得更好的可部署性)。
该服务由一个运行在 EC2 实例上的基本容器组成,该容器链接到一个 S3 存储桶。在我们的例子中,应用程序本身不需要大量的计算能力(到目前为止我们没有谈到深度学习),所以我们将选择 t2.micro 实例(单个虚拟内核和 4gb RAM)。从那以后,它将只与配置有关,因为 AWS 使我们的生活更容易:您不必考虑子网、安全组、VPC、IP 网关、NAT 这是在您生成实例时自动创建和定义的。尽管如此,对于那些需要控制它们的人(在 VPC 工作或使用 RDS),你可以通过.ebextensions
文件夹中的security.config
来配置一切。关键配置以.elasticbeanstalk
文件夹中的config.yml
文件结束:
environment-defaults:
{flask-app}:
branch: null
repository: null
global:
application_name: {my-app}
default_ec2_keyname: {my-ec2-key}
default_region: {region}
profile: {my-profile}
workspace_type: Application
对于配置部分,没有太多事情要做:给应用程序和服务起一个好听的名字(~ environment);如果需要,定义它的 EC2 键名,否则使用缺省值;选择要在其中生成实例的区域;选择了您的用户配置文件;使用Application
负载平衡器(这是我的建议)。
从那里,您已经可以访问并可视化您的在线运行的应用程序,使用一个名称,例如 {flask-app}。{id}。{zone}.aws.com 。然而,这缺少了一些东西:信息传输过程中的加密。你可能不是我,但我真的不喜欢使用不使用 HTTPS 的网站或终端…
把公主带到城堡里!
不幸的是,没有 SSL 证书,您的实例无法使用 HTTPS。通常,人们会使用 OpenSSL,这非常简单,但是在我们的例子中,AWS 通过他们的证书管理器服务又一次让它变得简单。如果你想让它更有趣,可以通过 53 号路线服务购买一个域名。然后,您可以使用 AWS 为您的 beanstalk 创建自己的证书,或者与您新获得的域名相关(我向您保证,这样看起来更专业)。现在,必须配置两个对象来重定向请求:一个是Canonical Name
,比如 {cname}。将您的 EB 实例作为值的域名;一个Alias
,比如{ 别名 } 。您的 EB 实例的域名。有了这两张唱片,你就可以上路了!
请用 HTTPS!
您错过的是信使:HTTPS 请求到您的实例的特定重定向。这个信使被称为监听器,有一个简单的配置:将外部世界的 HTTPS 定向到实例上的 HTTP。(可在listener.config
买到!)
option_settings:
aws:elb:listener:443:
InstancePort: 80
ListenerEnabled: true
InstanceProtocol: HTTP
ListenerProtocol: HTTPS
SSLCertificateId: {certificate}
但这还不是全部!为了确保您的实例接受 HTTPS,您必须配置服务器:这就是https.config
为您做的!;)
部署部署部署。
一旦你弄清楚了你的 Flask 应用程序,如何填充所有缺失的配置设置,如何获得你的 SSL 证书,是时候部署了!(不需要初始化,我们已经为此构建了配置文件。)
eb create flask-app
想要更多吗?给你!
以下是我不想在之前的教程中介绍的一些内容,但对于接下来的步骤同样重要:
- 使用环境变量!当你在生产环境中工作时,记得要多疑;)我的做法通常是用我的变量填充一个
environment.json
文件,并用deploy-env.sh prod
将它们部署在弹性 Beanstalk 实例上。 - 如果您使用标题(例如
Flask-JWT
),请确保将headers.config
添加到您的.ebextensions
文件夹中。 - 如果你使用 websockets (例如
Flask-sockets
),你将不得不使用 Docker 镜像并使用websocket.config
。我可能要为那部分做另一个模板(如果那是你要找的,就同时 ping 我),因为我花了不止几个小时才弄明白…
Examples using such Configurations: project-element & project-aster
有兴趣保持联系吗?😄Twitter|LinkedIn|Github|Medium
从计量经济学到机器学习
为什么计量经济学应该成为你技能的一部分
作为一名拥有计量经济学硕士学位的数据科学家,我花了一些时间来理解让机器学习成为与计量经济学不同的学科的微妙之处。我想和你们谈谈这些乍一看并不明显的微妙之处,它们让我在整个旅程中都感到好奇。
首先…什么是机器学习?…什么是计量经济学?
计量经济学 是将统计方法应用于经济数据,以便赋予经济关系以实证内容。更准确地说,它是“基于理论和观察的并行发展,通过适当的推理方法对实际经济现象进行的定量分析”
机器学习*(ML)*是计算机系统用来执行特定任务的算法和统计模型的科学研究,不使用明确的指令,而是依靠模式和推理。它被视为人工智能的一个子集。机器学习算法基于样本数据(称为训练数据)构建数学模型,以便在没有明确编程执行任务的情况下做出预测或决策
很好,所以他们看起来都需要数据,都使用统计模型,都做出推论,所以根据他们的定义,机器学习似乎可以处理更广泛的问题,而不仅仅是经济。那么,计量经济学为什么还存在?!这是我在开始计量经济学研究的同时发现机器学习时问自己的问题。
作为一名未来优秀的经济学家,我需要完美地处理数字,拥有扎实的[Statistics](https://en.wikipedia.org/wiki/Statistics)
背景,成为[linear algreba](https://en.wikipedia.org/wiki/Linear_algebra)
和[Mathematical optimization](https://en.wikipedia.org/wiki/Mathematical_optimization)
的专家,最后拥有处理数据的计算机技能。这些技能将用于理解、演示应用我的回归、分类、聚类算法或时间序列预测。在这一年里,我将深入学习一些算法,如*[Linear Regression](https://en.wikipedia.org/wiki/Linear_regression)
[Logistic Regression](https://en.wikipedia.org/wiki/Logistic_regression)
[Kmeans](https://en.wikipedia.org/wiki/K-means_clustering)
[ARIMA](https://en.wikipedia.org/wiki/Autoregressive_integrated_moving_average)
[VAR](https://en.wikipedia.org/wiki/Vector_autoregression)
*……等等。等等?这些算法也用于机器学习!****
从理论效率到经验效率
机器学习和计量经济学的一个根本区别在于它们的理论基础。计量经济学有扎实的数理统计和概率论基础。算法在数学上是稳健的,具有可论证的和吸引人的性质,这些算法主要基于其基础的稳健性进行评估。
对于机器学习,数学当然不会缺席,但它的存在是为了解释算法的行为,而不是展示其可靠性和吸引人的属性。这些算法主要根据它们的经验有效性进行评估。一个非常有启发性的例子是 Xgboost 算法的成功,它的成功归功于它在几个机器学习竞赛中的统治地位,而不是它的数学证明。
从精确到近似
另一个区别是,计量经济学只有一个解决方案,给定一个指定的模型和数据集,参数回归的参数是使用代数公式计算的。系数的[best linear unbiased estimator](https://en.wikipedia.org/wiki/Gauss%E2%80%93Markov_theorem)
( 蓝色)由普通最小二乘 (OLS)估计器在某些假设得到尊重的情况下给出。这里的“最佳”是指与其他无偏的线性估计量相比,给出估计的最低方差。
而大多数机器学习算法过于复杂,无法用单一的数学公式来描述。他们的解决方案是通过称为训练阶段的迭代方法在算法上确定的,训练阶段的目标是找到最适合我们数据的解决方案,因此由机器学习算法确定的解决方案是近似的,并且只是最有可能是最优的。
从参数模型到非参数模型
计量经济学模型(即:大多数时候是参数模型)是基于经济理论的。然后使用传统的统计推断工具(如最大似然法)来估计参数模型 mθ中参数向量θ的值。渐近理论然后发挥了重要作用(泰勒的发展,大数定律和中心极限定理…等)。
另一方面,在机器学习中,通常构造非参数模型,几乎完全基于数据(没有进行底层分布假设)和所使用的元参数(树深度、惩罚参数等)。)通过交叉验证、网格搜索算法或任何超参数优化算法进行优化。
从理论到实证的验证
你会明白的,模式会和以前一样,计量经济学依靠稳健的数学测试来验证模型,我们通常说的是模型的[goodness of fit](https://en.wikipedia.org/wiki/Goodness_of_fit)
。它通过假设检验、残差的正态性评估、样本分布的比较来评估。我们还将讨论[R²](https://en.wikipedia.org/wiki/Coefficient_of_determination)
,它是从自变量中可预测的因变量方差的比例,以及[AIC|BIC](https://en.wikipedia.org/wiki/Akaike_information_criterion)
,它通过[p-value](https://en.wikipedia.org/wiki/P-value)
评估每个模型相对于其他每个模型或变量评估的质量。
机器学习模型的评估将取决于它的预测,其基本思想是,如果模型能够很好地预测,那么它已经成功地学习了数据中的隐藏模式。为了确保模型不会过度拟合,数据集将被分为训练集和测试集,然后使用[cross-validation](https://en.wikipedia.org/wiki/Cross-validation_(statistics))
砖块来验证模型的泛化能力,并确保数据分离没有偏差。最后,我们将使用 KPI 来衡量与现实的差距,如[RMSE](https://en.wikipedia.org/wiki/Root-mean-square_deviation), [MAE](https://en.wikipedia.org/wiki/Mean_absolute_error)
或[Accuracy](https://en.wikipedia.org/wiki/Accuracy_and_precision)
。
从理论趋同到目的分歧
计量经济学和机器学习都试图定义一个函数,该函数定义一组将对预测变量建模预测变量:
****
- ɛ是随机变量 i.i.d .,规律 N (0,σ2)的实现也称为残差,来自计量经济学,否则 y = f(x)属于机器学习。
理论上,这两者在现阶段似乎是一致的,但在方式和目标上,他们也会有分歧。机器学习的目的是 y 在大多数情况下,而计量经济学的目的是估计每个预测因子的β。
计量经济学的主要目的不是预测而是量化一种经济现象
从理论到实践!
如果我们在实践中观察这些差异,我们将从一个经典的计量经济学模型和一个最广泛使用的模型线性回归开始。为此,我们将通过主要服务于机器学习模型的[sklearn](https://scikit-learn.org/stable/index.html)
库的实现和更加面向计量经济学的[statsmodels](https://www.statsmodels.org/stable/index.html)
库的实现来观察我们建模的结果。
**#import library
import pandas as pd
import numpy as np
import seaborn as sns
import statsmodels.api as sm
from sklearn import linear_model#import data
iris = sns.load_dataset("iris")**
让我们比较一下这两种实现
**dummies = pd.get_dummies(iris["species"], drop_first=False)
iris = pd.concat([iris, dummies], axis=1)
iris.head()**
由于物种是一个分类变量,我们需要将它转换成计算机可以处理的格式,所以我们转向一次性编码格式。让我们从机器学习开始。
我们可以通过模型对象提取模型系数和斜率参数β0。让我们用 statsmodels 试一试。
与 sklearn 相比,Statsmodels 给了我们很多信息,我们得到了非常好的 R,我们之前讨论过的 AIC、BIC、每个变量的系数和警告。让我们试着预测一下:
我们得到了相同的 R 和非常好的 mae 和 Rmse …但是我们认为两个模型的系数不相等。Statsmodels 警告我们,我们的模型有可能是[Multicollinear](https://en.wikipedia.org/wiki/Multicollinearity)
!这是指一个多元回归模型中的两个或更多解释变量高度线性相关的情况,这意味着我们的数据集中有冗余信息。这些信息来自物种变量,我们必须放弃一个类别,因为很明显,如果鸢尾不是 setosa 或 verginica 它是杂色的。
这意味着,尽管我们的模型有很强的 R,因此有很强的预测能力,但这些系数是有偏差的,无法解释的。
sklearn 尚未将此信息传输给我们。让我们通过传递 drop_first = True 来更正它。
Statsmodel 删除了它的警告,我们现在有了无偏系数。此外,偏度接近 0,峰度也意味着我们的残差可能是正态的,Jarque-Bera 的概率证实了这是一个很好的模型。让我们重新运行我们的 sklearn 模型:
最后,我们得到了相同的,让我们做一些阅读。可以看出,在所有其他因素都相同的情况下,花瓣长度增加 1%会使花瓣宽度增加 0.24 厘米。在分类变量的情况下,我们总是指缺失类别。我们可以看到,在所有因素都相同的情况下,verginica 物种的花瓣比缺失物种 setosa 宽 1.04 厘米。所有的 p 值在 5%的阈值下是显著的,因此我们的系数被认为是稳健的和无偏的。我们已经看到了线性回归模型的分析,它也可以转置到分类。逻辑回归在模型分析中提供了一个非常有趣的读数,我会在以后的文章中讨论比值比的读数。
阅读模型分析,我会在以后的文章中讨论优势比的阅读。
最后
计量经济学的概率基础无疑是它的强项,它不仅具有模型的可解释性,还具有不确定性的量化。然而,机器学习模型的预测性能是有趣的,因为它们允许我们突出计量经济学模型的不良规范,并且其中一些算法更适合于非结构化数据。计量经济学旨在严谨,但成为一种非常相关的经济因素分析工具,如果你的经理要求你量化一种影响,它除了给你统计和数学上的合法性外,还可能是相关的。
从错误到自主
数字误差的艺术潜力。
到目前为止,计算自治的想法是有问题的,科学界还没有达成共识。自从 19 世纪开始计算和数据分析以来,阿达·洛芙莱斯已经构建了一种思想,使机器创造多样化的作品合法化,然而,洛夫莱斯认为,机器不可能“创造”没有预先编程的东西。(洛夫莱斯,1842 年)。计算自治的可能性在 XX 世纪被正式考虑,即由著名科学家艾伦·图灵,他反对洛夫莱斯的陈述。
艾伦·图灵认为,现在可重新编程的计算机可以模拟人类的智力,如果为此目的对它进行足够的编程的话。在这个意义上,数学家鼓励在计算机编程中包含伪随机算法(图灵,1950)。这些目前被定义为随机过程:允许做出看似随机的决定,但可以通过数学概率计算的算法集。一方面,这是整合计算艺术的基础之一,因为该设备开始被探索作为其随机结果的创造力的助手,这些随机结果似乎模拟了人类的创造力。另一方面,艺术家们的实验方法论暗示了计算艺术的一个重大问题:艺术家不再认识自己的输出。
Vilém Flusser 和 Edmond Couchot 都用黑盒类比的方式处理了艺术家与技术的关系:不知道产生图像的机制的功能。Couchot 认为任何由技术中介产生的图像都是模型过程的模拟,因为编码和解码过程模拟并介入了媒介的特性。与图像的代表性内容相关,在后来的研究中,Hito Steyerl 将的劣质图像概念化:在数字毁灭的美学中趋向于抽象的图像。这些图像往往会遭受意想不到的失败,并收集编码伪像、,即由内容的编码和解码过程引起的众所周知的失真。在 Steyerl 看来,它们就像图像中的瘀伤,来自数据的压缩和传输,这证明了它们的动态和运动。(斯特耶尔,2009 年)
在用于读取和解码图像的介质的过程中,有时会发生改变数字内容的数据故障。正是从这个事实出发,Steyerl 反映了人类希望变得像数字图像一样的愿望。她认为,这些图像作为事物独立存在,因为它们表现出自主性并参与我们现实的构建,这些事物积聚力量,但也退化(STEYERL,2010)。与此同时,丹尼尔·洛克在他的“数字自主性”文章中重新思考了计算误差,认为这是一种不太可能的数字重新定义,它是由推动进步的自身法则决定的。用作者的话来说,“作为事物的图像通过它所隐藏的小故障保持其自主性”,小故障是由错误导致的编码工件。(鲁尔克,2011 年)。
数字的转换会导致意外的和不可避免的错误,这些错误通常是由于对内容的操作及其持续的时空更新而发生的。在实践中,错误过程的起源在于数字信息的不断重新适应,这从其“明显”的故障中揭示了媒体的证据。通过以上,调查图像的编码文物使我探索它们在艺术领域的潜力。像罗莎·门克曼这样的艺术家试图保存和再现这个错误的时刻。从她的角度来看,失败可以鼓励对系统功能的新理解。它可以导致一个反身的时刻,反过来,可能会显示自己是进步的外骨骼,一个宣泄的时刻(MENKMAN,2011)。内容的条件容易受到不同解释的影响,这些解释可能不完全是负面的,因为它可以引导用户到临界维度或揭示计算系统的一些重要因素。
“错误是对规范的违反,事实上,这代表了新的创造性解决方案的巨大潜力。”
有趣的是,这是 2018 年 9 月举行的电子艺术节(Ars Electronica festival)的主题,当时就当前对错误的需求进行了辩论,以促进数字自主性的改善。例如,在神经网络的功能和预测分析的结构中。这些过程通过计算和测量误差以及随机变异程度来优化,以自我管理它们的行为并模拟更自治的系统。
在这一点上,我承认:反乌托邦式的技术完全能够超越人类能力的想法可能永远不会实现。然而,为模拟机器行为而输入的数据的日益增加的复杂性反映了其未来的能力。计算系统对故障的敏感性与其行为的形式特征有关,计算机被认为是一个封闭系统,只在确定性过程下起作用。从这个意义上说,由于法典编纂的有限性,对任何技术过程的操作的限制似乎是显而易见的,但在实践中,这些限制确实在不断扩大其可能性。因此,数字自主的可能性取决于计算的未来发展和插入数据的复杂性。
人工智能对计算创造的期望仍然很高,并且正在迅速发展。更多的智能物和智能体正在被关注,并且显然可以在无人监管的环境中(半)自主操作。可以预见的是,可能会产生一种机制,这种机制结合并适应他们的发现,以调整他们的自主行动,其目的不是取代人类,而是通过模拟我们的行为来帮助生产。假设这些艺术领域的自主能力,我想知道计算设备是否能够模拟艺术家的创造力?正如图灵会说的:如果他们“被教得足够多”;我想象那将成为一种与我们完全不同的创造力。然而,我承认,基于算法计算来定义某种创造能力是有风险的,因为这与人类的内在复杂性直接相关,而这是目前无法模拟的。
从 FaceApp 到 Deepfakes
关于挪用与人工智能的思考
考虑到我在摄影和性别研究方面的背景,我对森村泰正和 T2 辛迪·雪曼的作品感兴趣也就不足为奇了。两位艺术家都使用自画像来探索身份的表现,经常参考其他媒体。谢尔曼因她在《T4》系列电影《无题剧照》中扮演二流电影女演员而出名。森村以再现著名的历史艺术品而闻名,将自己作为主题插入其中。两人都投入了大量的工作来改造自己,模糊了神话和现实之间的界限。
My take on “American Gothic” with help from FaceApp.
现在,由于人工智能(AI)的发展,任何拥有智能手机的人都可以变形或将自己(或其他人)插入另一个场景。
当 FaceApp 在 2017 年火起来的时候,我花了一段时间才最终试图明白这到底是怎么回事。交换面孔,看看我几十年后可能的样子,对我来说没多大作用。但后来我顺便参观了格兰特·伍德的标志性画作美国哥特式。我无法告诉你看到那个农民冲我咧嘴笑时我有多开心。
My friend Travis and a stranger in the background, brought to life with Mug Life.
Mug Life 是另一款利用神经网络和深度学习的应用。它通过将静态图像转化为 3D 动画来提升游戏质量。这张照片让我开心多了,尽管我从未在自己的照片上用过它。
Me after Meitu. I look nothing like this in real life.
不过,在和某人讨论了我们作为动漫角色的样子后,我还是把自己的一些照片放到了美图应用程序中。这个应用程序以一种别人没有的方式让我反胃。该公司将自己宣传为“移动美容体验的先驱”,使用“获得专利的面部识别和机器学习算法来绘制每个用户独特的面部特征。”应用程序中的设置清楚地表明了美丽对美图的意义:更苗条的脸,更大的眼睛,没有雀斑或胎记的更亮的皮肤,以及化妆。
美图提出了几个问题。就个人而言,我担心认识我的人看到上面的照片后会一本正经地说:“你在那张照片里看起来真的很好!”但是也有关于数据隐私的问题。这是整个美白的问题。FaceApp 的“热”过滤器也做到了这一点,尽管这显然是一个缺陷,而不是一个功能。这位首席执行官为道歉,称“这是由训练集偏差引起的底层神经网络的不幸副作用,而不是有意的行为。”在像 FaceApp 这样的东西中复制偏见可能不会对整个世界产生太大影响。但这些同样的“不幸的副作用”也在人工智能的其他应用中发挥作用,包括贷款决策和预测性警务。
让我们在这里控制它。到目前为止,这些应用主要用于娱乐,人们为社交媒体制作迷因和自拍。这些图像与赞助广告、品牌大使和影响者一起填充提要。像机器人 Lil Miquela 这样的有影响力的人已经出演了广告活动,登上了杂志封面,在 Spotify 上发布了单曲,最近被聘为《Dazed》杂志的艺术编辑。
CGI influencer Lil Miquela with actress Tracee Ellis Ross.
像密凯拉这样的虚拟影响者的崛起带来了一些令人兴奋而另一些人害怕的可能性。公司可以雇佣容易驾驭的模特来推产品。Quantum Capture 首席执行官摩根杨预测名人可能会开始使用 CGI 替身:“围绕这一点建立了一个非常有趣的收入模式,其中你可能无法接触到人才本身,但你可能会接触到他们的数字化身,而实际的人将从使用他们的化身中赚钱。”
这些虚拟形象引发了许多其他问题,包括关于拨款和谁受益(经济上和其他方面)的问题。不管怎样,我们面对的未来是,人类和人工智能之间的界限只会越来越模糊。
用于驱动 Mug Life 等应用程序和创建头像的技术已经帮助创建了如此令人信服的复制品,以至于人们无法区分什么是真实的,什么是虚假的。显然,就连凯丽·费雪也认为她在《T2》和《星球大战外传:侠盗一号》中的出现是因为旧镜头,而不是 CGI 制作。
“We’re entering an era in which our enemies can make anyone say anything at any point in time.”
虽然对娱乐业来说很棒,但乔丹·皮尔在他的视频中强调了“深度假货”的潜在危险,美国前总统奥巴马似乎称唐纳德·川普为“完全彻底的笨蛋”这个视频可能会像病毒一样传播开来,因为许多人觉得它很有趣,但人们的担忧是真实的。
Deepfakes 已经被用来试图通过虚假的色情视频骚扰和羞辱女性。这个术语实际上来自于一个名为 Reddit 的用户的用户名,他通过使用 TensorFlow 建立生殖对抗网络(GANs)来创建这些视频。现在,情报官员正在谈论弗拉基米尔·普京利用假视频影响 2020 年总统选举的可能性。关于 deepfakes 作为对民主和国家安全的威胁以及如何检测它们的更多研究正在进行。
从个人层面来说,我觉得很纠结。我欣赏这些技术为表演和娱乐带来的可能性。我对算法和它们能产生什么一样感兴趣。但我也担心它们如何被使用,被谁使用,以及会产生什么(不)预期的后果。
感谢阅读!想法、问题和反馈总是很受欢迎。
从脸书到创业公司:数据科学正在成为一个工程问题
苹果 | 谷歌 | SPOTIFY | 其他 | 剪辑
塞尔坎·皮安蒂诺在 TDS 播客
编者按:这是迈向数据科学播客“攀登数据科学阶梯”系列的第七集,由 Jeremie Harris、Edouard Harris 和 Russell Pollari 主持。他们一起经营一家名为sharpes minds的数据科学导师创业公司。可以听下面的播客:
如果你关注了我们的播客,你会知道一个清晰的主题在一个接一个的采访中浮现。每当我们向我们的客人询问数据科学的发展方向时,我们都会得到两个答案之一:要么 1)数据科学正在成为产品/业务角色,数据科学家需要像精通数据的产品经理一样思考;或者 2)数据科学正在成为一个工程问题,数据科学家需要更像工程师一样思考。
在今天的播客中,我们采访了一位专注于考虑第二种可能性的人:数据科学正在成为工程师的游戏。Serkan Piantino 曾担任脸书人工智能研究所的工程总监,现在运营机器学习基础设施初创公司 Spell。他们的目标是为数据科学家开发开发工具,让在云上训练模型像在本地训练模型一样容易。这段经历,再加上他在脸书的经历,让他对数据科学家应该使用的工程最佳实践以及整个领域的未来有了独特的看法。
以下是我从聊天中得到的最大收获:
- 大多数人在工具上投资不足。任何时候你发现你在一遍又一遍地重复使用相同的代码,你应该认真考虑把它变成一个库。相关:你还需要留意新的工具,这些工具可以自动化或增强你的过程。正如 Serkan 指出的,最好的软件工程师花 80%的时间以这种方式优化流程——对于数据科学家来说,他认为这个数字应该更高。
- 构建使您更高效的工具具有您可能没有想到的优势。具体来说,提高效率的一个效果是,测试和深入理解您的模型需要更少的工作,这反过来使您更有可能发现模型中的错误、过度拟合或偏差。
- 机器学习逐渐成为软件工程工具带中的另一个工具。正如 devtools 在软件工程中至关重要一样,类似的工具在数据科学中将变得越来越重要。
- 尽管数据科学和工程似乎正在融合,Serkan 认为我们将永远需要数据科学家。他强调,仅仅因为不同的数据科学任务随着时间的推移被抽象出来(想想:
GridSearchCV
和BayesSearchCV
用于超参数调优,或者更一般的 AutoML ),并不意味着理解模型背后的数学或数据库管理背后的工作原理没有价值。 - 为您的模型运行健全性检查不是可选的。作为标准流程的一部分,除了使用所有标准模型评估策略(如 AUC 曲线、混淆矩阵等),您还应该始终使用精心选择的边缘案例测试您的模型。
- 如果你没有上过像斯坦福这样的华而不实的学校,但你想进入像脸书这样的顶级科技公司,你的最佳策略是打造一些能吸引公司内部人们注意力的酷东西。项目是王道,但最好的项目不是 Kaggle 竞赛:它们是有明确用例的应用程序,是你的面试官可以想象自己使用的东西。
- 要远离的一件事是:网上有很多肤浅的教学资源(例如,“在 5 分钟内学会如何构建 GAN!”).这些都是危险的,因为它们制造了理解的幻觉——当你不得不建立一些真实的东西时,这种幻觉很快就会瓦解。当你不明白某件事的时候,学会注意是一项至关重要的技能,可以帮助你避免这个陷阱。
TDS 播客—剪辑:
如果你在推特上,随时欢迎和我联系 @jeremiecharris !
从分形到吸引子
我一直喜欢分形艺术,但在写一篇关于分形的文章时,我偶然发现了一种叫做吸引子的东西。由吸引子创造的艺术非常迷人。我可以花几天时间去探索。在这里,我将尝试一下巨大的可能性。
什么是吸引子?更正式的定义如下。在动力系统的数学领域中,吸引子是一组数值,系统趋向于朝着这些数值进化。
吸引子是状态的集合(相空间中的点),相邻状态在动态演化过程中向其靠近。吸引子被定义为不能自身分解成两个或更多吸引子的最小单位。这个限制是必要的,因为一个动力系统可能有多个吸引子。
事实上,我今天在这里的目的不是教你关于吸引子的知识,而是向你展示当它们变成艺术时是多么令人惊叹。独特的形状和独特的配色方案将画布变成美丽的东西。而且,这都是用数学完成的。对于那些觉得我的数学令人沮丧或“难看”的人来说,我理解这是可能的,但这是一个需要更深入探索的美丽主题。所以,继续美丽吧!
我将在这里包含创建以下艺术的代码。您可以使用这些代码并尝试创建您自己的艺术。
定义
Here a, b, c, and d are variables. There can be more but we’ll focus on four and show the results of those.
数字可以输入数据帧并立即使用,而不必逐个输入。这将一个接一个地呈现多个图形。有如此多的吸引子和如此多的美丽艺术可以简单地从数学方程、数字和代码中呈现出来。可能性是无限的。
The equation here is different than the Clifford attractor’s
下面是我用额外的 python 代码创建的另外两个吸引器。
Code for Clifford Attractors
Code Continued for Clifford Attractors
Here there are fifty five strange attractors but there are so many more that can be created. Below you will find the code for one specific Lazaro Alonso example. See if it intrigues you. Play with the code and try to create your own artwork.
From all this code, what do you get? It’s amazing!!
You can use this code to change the color, the background, the gradients, etc. See what you can do as you change the code to make your own creation.
虽然我很想在这里嵌入一个交互式吸引子生成器,但完成它比我预期的更具挑战性。外面有更多的世界。我无法阻止自己回到对计算机和数字组合能产生什么的敬畏中来!这是数学和数据科学中令人惊奇的一部分,应该进一步探索。
在利益相关者的支持下,从脆弱到敏捷
项目成功的最重要因素是在过程中获得利益相关者的支持
Photo by Michael Payne on Unsplash.
很难把一个敏捷型的钉子放进一个商业型的洞里!
TMI 警告:在 2015 年 8 月一个阳光明媚的早晨,在我的预产期,我在我的分娩球上蹦蹦跳跳,不耐烦地等待我的宝宝出现,但没有任何杂音!我必须让自己有事可做,所以我决定参加基于计算机的 ScrumMaster 认证考试——我参加迈克·科恩的培训已经有几个月了,但是我忽略了考试,现在看起来是个好时机,因为我的手在接下来的 12 个月里会很忙!
获得资格是容易的部分;我一点也不知道,即使我学会了所有的理论,实践是一个完全不同的野兽…四年下来,我成功地交付了几个具有挑战性的项目,我逐渐意识到,项目成功的最重要因素是获得利益相关者的认可,所以这就是我在本文中要讨论的。
这里的主要困境是,通过采用 SCRUM,你依赖于外部团体(即不仅仅是开发团队),如果他们没有履行他们的角色和职责,整个项目可能会崩溃。
所以,让我们看看什么会出错…
“我没有足够的时间在每次迭代中与团队合作”
产品负责人的参与是敏捷团队成败的关键。敏捷方法的协作性质,即产品所有者是团队的一部分,在时间管理方面会给他们增加很多压力。传统上,他们的输入是在项目的开始和结束(签署软件符合规范)时被请求的,但是在敏捷项目中,他们被要求参加所有的仪式,保持待办事项列表整洁,区分优先级,并且每天与 Scrum 团队互动。
你需要向他们说明,他们有权做出与产品相关的决策,并利用他们的领域知识专注于功能,而不是管理本身。最重要的是,他们需要快速回答重要的问题,及时提供有价值的信息,并确保开发团队不受阻碍。你应该与产品负责人合作,支持他们需要的任何东西,并指导他们如何最好地为团队增加价值。
Courtesy: boost.co.nz
“我不需要每次冲刺复习都签到;给我发个报告就行了!”
利益相关者是忙碌的人。他们的日常工作要求很高,需要参加很多会议,做决策,管理多个项目。他们偶尔会对开发出来的软件不感兴趣,只要它能做到广告上说的那样。与产品负责人类似,他们习惯于参与项目的开始和结束,并不奇怪他们试图保护自己的时间,并取消任何他们似乎不必要的会议。
涉众不一定理解的是,Sprint 评审是为了团队的利益;不是让他们去发现团队在做什么,而是让团队去发现涉众真正想要什么。你需要让他们明白,在缺乏详细规格的情况下,这是检验产品并做出相应调整的机会。这是他们可以要求任何改变和增加的时候,所以如果他们不出现,他们就没有发言权**!**
这些评论经常会陷入一些陷阱:
它们太长:在两个小时的评审中,有 20 分钟的时间是有价值的,所以他们的时间被浪费了,
它们太技术性了:低级别的实现细节正在被讨论,
没有什么可看的:涉众只想评审完整的工作流,而不是每个 sprint 开发的增量部分。
调整 Sprint 评审的结构以关注产品是吸引利益相关者参与的关键。这使得每个人都更容易调整他们对项目的目标和愿景,并继续交付一个有凝聚力的产品。
“但是我已经知道我想要什么了!”
通常情况下,人们认为他们已经知道他们想要什么,他们对软件应该做什么有一个清晰的想法,所以他们认为如果他们能写下来,让你继续做,会更有效率。你不能真的对利益相关者或产品负责人说:“我不相信在我给你看之前你知道你想要什么”——你需要在这个问题上更加外交化,并强调在项目过程中持续的投入是无价的。边缘案例在项目开始时并不明显,需要在发生时处理。此外,利益相关者想要的和他们需要的可能是不同的,并且很可能会带来实质上不同的成本!
我喜欢用的一个比喻是“软件开发是蝴蝶效应的体现”:微小的变化可能会导致巨大的下游影响,所以除非利益相关者可以讨论和验证他们的需求,否则开发人员将不可避免地做出假设,这些假设在您获得的过程中变得越来越难以解开。
这部老掉牙但很好的轮胎摇摆卡通很好地总结了这一点:
Courtesy: businessballs.com
“我不能等待一个新特性的整个迭代”
敏捷宣言的第二个原则表明,即使在开发的后期,变化也是受欢迎的。利益相关者如何解释这一点:改变是要适应的 现在 !
固定迭代的想法是经过深思熟虑的,它试图控制需求的不断波动,并保护团队不要开始很多事情却没有完成。需要与产品所有者和其他利益相关者就最佳迭代长度达成一致:即,他们愿意等待新需求开始的可接受长度是多少,而开发团队需要足够长的周期来完成功能并满足他们的预期速度。
“这是一个监管项目,你能在截止日期前完成吗?”
是啊!!与流行的观点相反,敏捷方法确实可以在日期驱动的项目中发挥巨大作用。基于“铁三角”,有了固定的时间表,你必须变通其他两个目标中的一个,即要么增加更多的人员到项目中,要么缩小范围以实现这一目标。
Courtesy: Wikimedia
然而,你需要记住,如果更多的资源在项目的整个过程中保持不变,那么它们将是有益的——将更多的开发人员分配到一个已经运行较晚的项目中,将会使它运行得更晚(这在 Fred Brooks 的神话人月中有很好的记录)。关于范围,你确实依赖于产品所有者——他们必须优先考虑实现最小可行产品所需的特性。“从电影中学习”也是我推荐的一种方法:尽可能晚地对最终发布日期做出承诺。
要记住的一件重要事情是,在固定时间表的项目中,质量需要很高,这样错误和相关延迟的风险才能最小化。自动化测试和持续集成来拯救你,你应该把它们的附加值卖给管理层。此外,像 Atlassian Portfolio 或 ALM Works Structure 这样的工具可以可视化计划的组成部分(范围、人员和时间)来帮助你实时计划。
短迭代和使用工作软件作为主要的进度度量保证了当最后期限到来时,你保证交付一个具有正确特性的功能产品。即使你受困于不切实际的预算、进度和范围预期,你仍然应该以敏捷的方式运行项目,因为它提供了明确的证据,表明你将比在传统管理的项目中更早地失败,因此你有更多的选择…
计划就是一切,计划什么都不是——d·艾森豪威尔
准备好——准备好——Scrum!
以我的经验来看,从任何利益相关者那里获得认同的最好方法是让他们和你一起参加仪式,并参与日常的 Scrum 执行。有组织的演示和培训对于创造一种向敏捷过渡的最佳方式的感觉也是必不可少的。
另一方面,培养敏捷氛围并证明它不脆弱的需要,并没有给你全权去忽略那些不一定看到价值的涉众的反馈。相反,套用奈杰尔·尼科尔森在《哈佛商业评论》中的话:当有人反抗时,一个有效的领导者不会把他们视为需要解决的问题,而是需要理解的人!
感谢阅读!
我定期撰写关于领导力、技术和数据的文章——如果你想阅读我未来的帖子,请 在 Medium 上关注我 !
数据货币化的经验教训
谈论你的组织的隐藏价值的框架
Graph is illustrative of the journey not actual scale
2011 年 4 月。“Jumptap 是定向移动广告的领导者” Adam Towvim 指着他的 iPhone 4 告诉我。当他递给我的时候,那块闪亮的砖看起来像是被冰覆盖着。“用你的手指在屏幕上摩擦,”他示意道。霜神奇地消失了,露出了邓肯甜甜圈冰咖啡促销。
亚当给我看的广告很吸引人,但它不是由数据支持的。我们会面几周后,我加入了 Jumptap,领导团队最终将数据整合到公司的所有技术中。7 年后的今天,我回头看我们构建的客户喜爱的数据产品。这些产品让从广告商那里赚了数十亿美元,并推动了数十亿美元的收购。我思考着我们一路走来学到的教训。
当我们能够传达数据资产的价值和目的时,我们就取得了最大的成功。为了做到这一点,我们投入时间开发了一种通用的数据语言和工具来进行交流,我们与客户进行了深入的交流,并了解我们的数据如何解决他们的问题,当我们谈论数据时,我们要求数据和我们自己都保持完整性。在本文中,我描述了使成功成为可能的框架,以及可以使您的数据对话更有价值的工具。
学习语言
在一个充斥着数据点的世界里,令人痛苦的是缺乏关于数据的清晰交流。管理数据产品 20 年的经验告诉我,光是数据这个词就很危险。你需要上下文和定义来描述任何有价值的东西。无论是构建数据产品还是设定数据驱动的目标,管理者都必须花时间去学习、教授和使用一个比数据更好的词。
例如,如果你的公司存在于广告技术生态系统中,并希望将消费者行为数据货币化,你必须开始使用这些词的某些版本:
- **标识符:**与目标设备、用户、消费者或家庭相关联的字符串。
- 信号:可以与标识符相关联的唯一观察值。一组信号通常被称为特征。
- 段:所有共享共同信号或特征的 id 的集合。
为什么?这些词实际上对行业有一定的意义,并使团队能够围绕参与所需的技术和法律框架进行联合。Adtech,edtech,fintech,等。每个都有自己的基本数据字典。如果你不会说这种语言,你可能会有错误的对话。
在我的职业生涯中,我一直在接近尾声时加入注定要失败的数据货币化对话。一家数据提供商拥有一套令人满意的受众智能,但该团队尚未弄清楚如何将细分集成到应用程序中。几个月的业务发展审查质量和规模浪费了,因为没有办法连接这些点。差距可能是技术上的、法律上的、财务上的或者以上所有的。只需一次分歧就能扼杀一笔交易。
几乎有数百万博客提供如何更好地进行对话的建议,但我的经验证明,围绕复杂数据建立联系的唯一方式是建立一个简单的呼叫流程图,上面标有定义的数据元素(见下文)。你不需要成为一名工程师来组装这些。目标是开始一个实用的对话,而不是记录架构。
Call Flow for Weather Specific Ad Creative
当我们被要求设计一个根据当前天气动态更新的广告时,我们的团队需要集成一个天气数据服务。IP 地址是解析我们传递给气象服务的邮政编码所需的信号。他们回复了一个段,一个两位数的天气代码。创意团队将这些代码存储在天气广告中,并使用它们来动态更新广告创意,以反映当前的天气。这很简单,也很有效。
随着数据点之间跳跃次数的增加,这些图表的价值也会增加。大多数数据应用程序,如将移动运营商细分市场带给广告商,需要一个用户标识符,并且不像这个天气示例那样简单。如果这些点只是在罕见的情况下连接起来,那么一笔 10 亿美元的交易是不会有回报的。尽早将产品和工程引入对话至关重要。这里成功的关键是使用普遍接受的数据语言。你的行业已经有了一个——学习它。
如果你认为你发明了一种新的数据类型或数据的独特用途,花时间与你的团队和合作伙伴一起明确定义它是什么,不是什么。创建一个命名约定,坚持它,并推广它。与普遍的看法相反,利用数据赚钱并不容易。只有当一个组织花时间定义其数据资产,并学会如何在内部以及最终与客户讨论它们时,价值提取才是可能的。
知道问题
数据对话往往以关于数据数量的争论开始和结束。不要让规模立即打消你追求数据驱动产品的念头。市场将永远重视规模,但客户将帮助确定规模和精度之间的正确平衡。重要的是找到一个值得解决的问题。我们在 Jumptap 经历了这一点,并在此过程中学到了关于数据货币化的重要经验;了解问题,了解你的客户,然后确定合适的规模。
2011 年,针对移动设备的广告商没有消费者购买数据。为了触及受众群体,广告商必须信任出版商的上下文元数据,并抱最大希望。Jumptap 领导团队认识到了这一市场需求,我们开始设计一种将消费者行为数据引入移动广告的方法。
我们的第一次迭代专注于快速扩展。我们从 DataLogix (现归甲骨文所有)获得了消费者购买数据的许可。他们向我们证明,对于某些产品类型,某些邮政编码显示出高于平均水平的购买行为。我们已经可以针对预定义的邮政编码组,因此我们根据 DataLogix 购买数据创建了专门的位置目标,并开始向广告商出售这些基于位置的受众。初步成功后,客户开始质疑产品的精确度。他们期望购买行为和设备之间有一对一的匹配。我们的解决方案没有提供这一点,但我们已经向一组客户证明,我们正在向市场仍未提供的解决方案冲刺。
我们的第二次迭代重视精度胜过规模。数据提供商可以向我们发送任何有电子邮件地址的用户的受众分群。我们联系了我们的出版商合作伙伴,请他们收集他们用户的电子邮件,并在地址上添加模糊哈希后发送给我们。我们向出版商支付了数百万封链接到有效移动设备 id 的散列电子邮件,并继续从我们的数据合作伙伴那里下载数据。更精确的产品是相当成功的,但是这一次我们遇到了无法克服的困难。我们无法从合作伙伴那里获得足够的电子邮件地址。
The Complex Map of Consumer Purchase Data
我们回到客户那里,找到了平衡规模和精度的折中方案。我们想出了如何准确地将移动设备与具体家庭联系起来。然后,有针对性的广告被发送到我们能接触到的所有与家庭相关的设备上。这个伸缩性很好。我们的客户认识到,当整个家庭都收到类似的信息时,影响购买行为是非常有效的。
我们立即投入了广告预算,这些预算受到当时移动广告缺乏针对性的限制。然后,我们采用相同的技术堆栈,用它来驱动市场上最早的一些跨设备瞄准和测量解决方案。我们能够大规模交付产品,同时保持市场认可的精确度水平,这是 Jumptap 最终以超过 2 亿美元的价格出售给 Millennial Media 的关键因素。我们知道我们要解决的问题,我们倾听客户的意见,我们在规模和精度之间进行权衡。
进行对话
每个组织都将创建数据视为自然的业务过程。在某种程度上,他们得出结论,数据可能有一定的货币价值。多年来,我开发了一个框架来帮助推动围绕数据货币化的对话,以帮助团队确定是否值得追求以及如何让团队支持决策。
第一步在本文的开头部分已经介绍过了。组织必须定义正在考虑的数据集,确认组织拥有使用数据的合法权利,并估计当前规模。以我的经验来看,10 家公司中有 9 家在执行盈利计划之前必须回头重写一些数据使用或隐私语言。这需要时间,而且可能会引起争议。先这样做,或者以后付出代价。
下一步是通过评估数据提炼和外部化的潜力来探索货币化机会。想一想您的数据或您对数据的处理是如何与众不同的。下面的矩阵是推动对话的好工具。
所有数据都从左下方开始—原始的、内部的,不创造任何价值。矩阵迫使团队思考数据集如何移动到不同的盒子中。提炼时向上,分享或出售时向右。
- 我们对数据类型有唯一的访问权吗?
- 数据类似于原材料还是成品?
- 我们可以向其他公司提供我们的数据吗?
- 我们想投资改进我们的数据吗?
- 我们的数据已经有市场了吗?
- 我们对数据的处理有什么不同吗?
回答这些最初的问题,并将数据资产放入当前和期望的盒子中,有助于团队支持更广泛的数据战略。为了更好地说明这些选项,我根据公司当前的货币化对话状态,将公司名称放入下面的主要方框中。一个公司可以有多个盒子里的产品。
亚马逊进行了对话,并得出结论,他们的战略是围绕他们的数据资产创建一个堡垒,同时通过数据优化和内部数据服务进行创新。他们在数据民主化服务上投入了大量资金,以增强员工的能力。他们利用客户情报来发展业务,并取得了巨大的成功。他们现在是数据驱动型企业的典范。
寻求成为下一个亚马逊并不是一个糟糕的决定。然而,如果领导层决定关注内部,他们需要定期沟通并捍卫这一决定。具有创新精神和创业精神的员工会发现值得考虑的商业机会。不要害怕进行对话。如今,提供数据即服务(DaaS) 是一个巨大的机遇。在获取、交付或提炼数据方面具有竞争优势的公司,如 Datalogix (被甲骨文收购),以及气象公司(被 IBM 收购),有可能达到十亿美元的估值。
沿着这条路走下去是一个需要大量投资的重大战略决策。如果这是货币化对话的结果,那么下一步就需要达成一致并制定详细的计划。试着呆在一个盒子里,非常强调差异化。矩阵中的另一家 DaaS 公司 PlaceIQ 是位置数据生态系统的早期远见者之一,但他们在建立规模和差异化方面面临挑战。多年来,他们已经开发了几乎每一个盒子中的产品,然后通过其当前的平台为客户提供高度精确的位置洞察,取得了成功。
最后一栏,数据卖家,由于脸书(不是卖家)和其他行为者在消费者数据实践和政策上不够透明,这些天正在应对负面新闻。尽管如此,出售数据是一项可以正当进行的合法业务。早在互联网出现之前,原始数据供应商就开始出售精细数据集,如家庭人口统计数据、购买历史记录或其他用于各种目的的高价值列表。这些数据的老爷爷们还在卖收缩包装的软件。这不是数据业务的发展方向,但对于一些数据集来说,这仍然是一个值得考虑的有效商业模式。
一批新的数据卖家已经发现,各种原始和精炼数据类型都有数字市场。在美国,除了金融和医疗垂直行业,数据交换通常不受监管。这在未来可能会发生变化,但今天像甲骨文公司、T2 公司、洛塔梅公司和 T4 公司这样的公司提供了通用的方法来将定义的数据资产货币化。小众买家,如位置情报提供商 Cuebiq 、un cast和 Safegraph 从多个移动应用发行商购买并汇总原始位置信号,这些发行商提供服务以换取出售精确位置信号的权利。正如 matrix 所建议的那样,将这样的原始数据出售给数据生态系统是价值链上的一个低端。然而,如果您的公司正在考虑转向 DaaS 业务或成为数据顾问,从这里开始是测试数据价值的完美有效的方法。
我看到绝大多数专家反对出售数据,但我认为公司需要采取务实的态度。进行货币化对话。如果您的公司对数据资产拥有完全的权利,有限的风险暴露,并且没有建立数据业务的短期意图,那么应该考虑加入数据生态系统。使用多样化的收入流以其他方式建立企业价值,或者随着时间的推移向数据价值链的上游移动。
货币化对话既不是一劳永逸的练习,也不是你想永远做下去的跑步机。每个公司都需要找到正确的节奏。如果你的公司走上亚马逊的道路,你应该定期重新评估这个决定,但不是每个月。如果有机会出现,测试市场。如今,数据的保存期限如此之短,以至于一个测试项目可以在有限的暴露情况下提供大量的知识。最重要的是,在团队评估货币化机会时,花时间记录机会、厌恶和结果。记录对话有助于避免重复讨论同一个问题。它还可以帮助创新型员工发现领导层尚未考虑到的机会。
要求诚信
大规模利用数据赚钱并不容易。对于每一个估值达到 10 亿美元的 Datalogix,就有 100 家像 T2 rocket fuel 这样的公司找到了数据的独特应用,但却犯了严重的错误。要想取得成功,你需要一个非常正直、有能力沟通复杂事物的团队。我选择这两个特征是因为以今天的技术,假设你可以用数据做任何事情。这一事实很容易夸大能力,低估复杂性。团队需要清楚地传达价值,然后交付。结果(用数据表示)最终会揭开真相。不要冒险假装。
挑战在于,激烈的竞争将不断推动团队利用他们的数据做越来越多的事情。投资于安全、隐私和政策培训系统非常重要。所有这些都不能弥补在数据使用方面表现出完整性的领导力。像欧洲 GDPR 这样的法规是技术自大和多年不透明数据收集的结果。如果我们让这减缓我们的进步,那将是一场悲剧。解决办法很简单。团队需要接受数据透明、同意和控制的新规范。这是一种公平的平衡。随着公司从使用数据中获利,他们也需要为消费者提供对数据更大的访问和控制。如果一个组织希望保持数据驱动优势,管理层必须让这种新模式成为公司文化的一部分。
创新数据使用的例子在我们身边比比皆是。从把你带到这个页面的谷歌搜索,到因为当地政府众包坑洞位置而在你的汽车中平稳行驶,数据被用来让我们的生活变得更好。机会是无穷的,但是很容易被与构建这些产品相关的风险和复杂性所淹没。当工作感觉巨大或数据资产不可获得时,很容易发现异议。我的经验向我证明,企业数据蕴含着巨大的价值。关键是使用简单的语言将大问题分解成微小的数据点,进行货币化对话以使团队保持一致,然后在团队交付时以残酷的诚实进行沟通。遵循这一框架并确定您的公司在哪里有数据机会可能是增长和停滞的区别。这是最后一课。
从数学到数据科学
我拥有纯数学硕士学位(想想定理证明,而不是数字运算),最近决定开始过渡到数据科学,特别是机器学习/人工智能。我的背景教会了我严谨而精确地思考,但还没有让我做好除了教书以外的任何事情的准备,无论是在学院、大学还是高中当助教。我的目标是研究,而不是教学,尽管我心目中的博士和终身教职肯定会涉及一些教学。事实证明,我可能真的擅长教学,有几年我认为我可以做得很好,但尽管没有博士学位意味着我暂时被数学研究拒之门外,但研究新问题和新想法的冲动从未离开过我。
我最喜欢的两门数学课程是图论和数理逻辑,当我还打算攻读博士学位时,我向数理逻辑教授征求关于专攻该领域的建议。她告诉我,现在这已经过时了,专攻数理逻辑无异于自杀,但数理逻辑的现代应用是人工智能。图论在数据结构和算法方面也很突出,事实上我最喜欢的所有主题都在机器学习中发挥了作用。
Photo by Franki Chamaki on Unsplash
当时我并不相信,但在决定继续当五到六年的学生对我现在的职业轨迹来说并不是一个正确的决定后,我最终接受了她的建议。在sharpen Minds的联合创始人爱德华·哈里斯(Edouard Harris)的指导下,我开始学习 Python(从何塞·波尔蒂利亚的完整的 Python Bootcamp 开始,然后用杰克·范德普拉斯的Python 旋风之旅填补了我基础中的一些空白)。我决不会声称此时已经掌握了 Python,但是我已经掌握了足够的基础知识来进行下一步。
然后,对我来说,听从哈里斯和许多其他人的建议,不要遵循我在研究生院根深蒂固的学习模式,这是一个巨大的信念飞跃:在将所有组件组合在一起之前,彻底学习每个组件。相反,我采用自上而下的方法:通过使用工具来学习,而不是在使用之前。对我来说,这是一个巨大的思维转变,我不知道我需要多长时间来适应它。
Photo by Fabian Grohs on Unsplash
因此,我没有通过高级 Python 课程在 Python 方面继续前进,而是刚刚在 Coursera 上完成了吴恩达的深度学习专业,并且正在开始 fast.ai 的程序员实用深度学习(两者都使用 Python)。fast.ai 由雷切尔·托马斯和杰瑞米·霍华德共同创立,体现了自上而下的学习方法,并表现出令人印象深刻的能力,通过以做为中心而不是理论化来教授学生高度适用的技能。我也一直在使用模式分析 SQL 教程学习 SQL,在何塞·波尔蒂利亚的Python for Data Science boot camp中玩更多的 Python 库,并在 Khan Academy 中复习我的统计数据。本着边做边学的理念,我希望在一年内为数据科学的入门级职位做好准备,可能会在求职期间申请成为最敏锐思维的学员。
来自学术界的我,仍然在内心挣扎,觉得自学是“值得的”,尤其是在申请工作的时候,尤其是因为寻求数据科学家的工作描述往往会让新人有些气馁。但也许数据科学中思想和技术的内在快速迭代需要该领域的每个人都擅长自学,而我强大的数学背景——毕竟我拥有“定量领域的研究生学位”——加上自学新概念和新技能的技能,将对潜在雇主具有吸引力。
(2022 年 11 月更新)
在成为数据科学家的路上发生了一件有趣的事情:我成了一名技术作家!但是我经常从这篇文章的读者那里得到一些信息,通常是这两个问题中的一个:
我(读者)应该成为数据科学家吗?
恐怕我真的无法为任何不是我的人回答这个问题,但我可以说:职业会改变,因为人类会改变。如果你对这篇文章感兴趣,你已经知道了!所以,请继续前进,精通 Python,并开始学习在技术领域非常普遍的技能,例如:
- Git
-如何在命令行中工作
-如何使用像 Vim 或 Nano 这样的文本编辑器的绝对基础,即使你大多数时间更喜欢在 IDE 中工作
-一些 SQL(数据库到处都是*)
当你学习这些通用技能时,找到属于几个不同技术领域的人的社交媒体账户,即使你只是阅读。你会开始对不同的行业如何运作有一点感觉,如果你跟随那些人,你会对前景有一个更大的了解。
我(读者)怎样才能成为一名数据科学家?
我很难回答这个问题,因为我最终没有选择数据科学,但在我突然改变方向之前,我一直在积极寻找工作,经历了几次多轮面试,并在此过程中获得了宝贵的建议。以下是我的建议:公司仅仅根据学位雇佣数学毕业生的日子已经一去不复返了。无论你拥有什么样的学位,公司都希望你拥有:
-至少有一个数据科学项目的投资组合(不是来自课程或教程)
-能够编写生产级 Python
-精通 Scikit-Learn、NumPy 和 Pandas 等 Python DS 库
-精通 SQL(不仅仅是语法,而是真实世界的使用)
-精通 Git(也不仅仅是语法,而是真实世界的使用)
我列出了一个我最喜欢的学习这些技能的资源的清单。我希望这有所帮助!感谢阅读。😊
可以找到我的地方:
从熊猫到有考拉的派斯帕克
Photo by Ozgu Ozden on Unsplash
对于那些熟悉熊猫数据帧的人来说,切换到 PySpark 可能会相当混乱。API 是不一样的,当切换到分布式特性时,由于该特性所施加的限制,有些事情的处理方式会非常不同。
我最近在一个非常有趣的关于 Apache Spark 3.0、Delta Lake 和考拉的 Databricks 演示中偶然发现了考拉,我想探索一下会很不错。
考拉项目通过在 Apache Spark 上实现 pandas DataFrame API,使数据科学家在与大数据交互时更有效率。
pandas 是 Python 中事实上的标准(单节点)DataFrame 实现,而 Spark 是大数据处理的事实上的标准。使用此软件包,您可以:
-如果您已经熟悉熊猫,使用 Spark 可以立即提高工作效率,无需学习曲线。
-拥有一个既适用于 pandas(测试,较小的数据集)又适用于 Spark(分布式数据集)的单一代码库。
来源:https://koalas.readthedocs.io/en/latest/index.html
如何入门
考拉支持≥ Python 3.5 ,从我从文档中看到的来看, PySpark 2.4.x. 依赖项包括 pandas ≥ 0.23.0,pyarrow ≥ 0.10 用于使用柱状内存格式以获得更好的矢量操作性能,matplotlib ≥ 3.0.0 用于绘图。
装置
下面列出了安装考拉的不同方法:
[## 安装-考拉 0.20.0 文档
正式 Python 3.5 及以上。首先你需要安装 Conda。此后,我们应该创造一个新的环境
考拉. readthedocs.io](https://koalas.readthedocs.io/en/latest/getting_started/install.html)
但是让我们从简单的开始:
pip install koalas
和pip install pyspark
请记住上面提到的依赖性。
使用
给定以下数据:
**import** pandas **as** pd
**from** databricks **import** koalas **as** ks
**from** pyspark.sql **import** SparkSession
data = {**'a'**: [1, 2, 3, 4, 5, 6],
**'b'**: [100, 200, 300, 400, 500, 600],
**'c'**: [**"one"**, **"two"**, **"three"**, **"four"**, **"five"**, **"six"**]}
index = [10, 20, 30, 40, 50, 60]
你可以从熊猫的数据框架开始:
pdf = pd.DataFrame(data, index=index)*# from a pandas dataframe* kdf = ks.from_pandas(pdf)
来自考拉的数据框架:
*# start from raw data* kdf = ks.DataFrame(data, index=index)
或来自火花数据帧(单向):
# creating a spark dataframe from a pandas dataframe
sdf2 = spark_session.createDataFrame(pdf)# and then converting the spark dataframe to a koalas dataframe
kdf = sdf.to_koalas('index')
一个完整的简单输出示例:
A simple comparison of pandas, Koalas, pyspark Dataframe API
熊猫和考拉的 API 差不多。官方文档中的更多示例:
这是对考拉的简短介绍,主要面向新用户。本笔记本向您展示了一些关键的不同之处…
考拉. readthedocs.io](https://koalas.readthedocs.io/en/latest/getting_started/10min.html)
谨记在心
关于考拉项目的一些说明:
- 如果你是从零开始,没有任何关于熊猫的知识,那么直接进入 PySpark 可能是一个更好的学习方法。
- 一些功能可能丢失 —丢失的功能在这里记录
- 一些行为可能不同(例如,Null 与 NaN,NaN 用于考拉,更适合熊猫,Null 用于 Spark)
- 请记住,由于它是在幕后使用 Spark,s ome 操作是懒惰的,这意味着在有 Spark 动作之前,它们不会真正被评估和执行,比如打印出前 20 行。
- 我确实对一些操作的效率有些担心,例如
*.to_koalas()*
给出了一个*No Partition Defined for Window operation! Moving all data to a single partition, this can cause serious performance degradation.*
警告,这似乎是因为索引操作和**可能会有相当大的问题,这取决于您拥有的数据量。**请注意,当您在.to_koalas('index')
中指定索引列名称时,警告并不存在,这是合理的,因为 spark/koalas 知道使用哪一列作为索引,并且不需要将所有数据放入一个分区来计算全局排名/索引。更多细节请看这里:https://towards data science . com/adding-sequential-ids-to-a-spark-data frame-fa 0 df 5566 ff 6
结论
**免责声明:**我真的没有怎么使用它,因为当我开始学习 spark 时,这还不可用,但我真的认为了解可用的工具是很好的,并且它可能对那些来自熊猫环境的人有所帮助——我仍然记得我从熊猫数据帧切换到 Spark 数据帧时的困惑。
我希望这是有帮助的,并且知道考拉将会节省你一些时间和麻烦。任何想法,问题,更正和建议都非常欢迎:)
如果您想了解更多关于 Spark 的工作原理,请访问:
[## 用非技术性的方式解释技术性的东西——Apache Spark
什么是 Spark 和 PySpark,我可以用它做什么?
towardsdatascience.com](/explaining-technical-stuff-in-a-non-techincal-way-apache-spark-274d6c9f70e9)
关于在 Spark 中添加索引:
怎么做,这是个好主意吗?
towardsdatascience.com](/adding-sequential-ids-to-a-spark-dataframe-fa0df5566ff6)
一年从糕点师傅到数据分析师。
进入数据科学的秘诀是什么?
https://mycupcakeaddiction.com/en/recipes/laptop-computer-cupcakes
每天,像我这样有抱负的数据科学家都被关于数据科学如何酷以及它将如何在不久的将来改变一切的励志文章轰炸。这似乎是一个非常令人兴奋的学习和工作领域,如果你至少有一个 STEM 学位的话。
当你像我一样有不同的背景时,搜索那些转行从事数据工作的人并没有什么帮助。在很多情况下,你会发现那些从物理、天文或机械工程进入数据科学的人发生“大”变化的故事,这很酷,但厨师、银行出纳员和学校教师呢?这种感觉就像是一个陷阱,如果你以前从未接触过代码、统计或繁重的数学,就不可能真正处理数据。是的,从零开始学习任何东西都要困难得多,但是我在这里想告诉大家,尽管如此,这是可能的!
我学过烹饪学,它是烹饪艺术和酒店管理的混合体。大学毕业后,我做过糕点师和美食教师,后来,我还为一家银行工作。很多年来,我对 python、loops、z-scores 或者你可以用熊猫做的所有魔术一无所知。但是,我一直对 AI 和机器学习非常好奇,即使那时候那些概念对我来说更接近科幻。
在我休假一年后,当我意识到我想在生活中做一些新的事情时,一切都变了。然后,我开始研究什么是酷的,灵活的,有活力的,能让你在世界上任何地方工作。答案是技术,在所有的可能性中,数据科学是最酷的选择之一,所以我决定在 Dataquest 开设一门在线课程,看看我是否喜欢它,最初,我专注于学习 python 的基础知识。我也开始听播客,比如 Dataframed ,阅读大量文章,大部分是从到数据科学和 KD 掘金的文章,让自己熟悉那个世界的人物。
几个月后,我真的很喜欢我所学的东西,当时我搬到了爱尔兰的都柏林,在那里我找到了一个数据分析的高级文凭,这基本上是一个为期一年的密集课程,最终给你一个相当于学士学位的文凭。我当时全职工作,没有多少钱,但我决定给它一个机会,最终,一年的时间并不多。
记得我说过这是强化课程吗?这几乎占用了我一整年的所有空闲时间,有如此多的作业和考试,以至于我多次感到不知所措。但是,随着我在学习中的进步,我更高兴的是发现了这么多神奇的东西,如 Tableau、Kaggle 竞赛、学习如何清理数据(好吧,不是很酷,但真的很有必要)、t-test、ANOVA,还有很多。我非常确定我的方向是正确的,但是如何获得我的第一份工作机会呢?
我已经发出了 200 多份申请,已经修改了至少十几次简历,仍然一无所获。我照着菜谱做,创建了一个 github 文件夹和一个博客,同时我也试图在数据分析师需要的工具方面获得更多的实践知识。秘密是什么?很简单,耐心。
从零开始是很难的,坚韧不拔是我获得第一次面试的关键,也是我从第一次失败中吸取教训的关键。你需要了解人们期望你知道什么,以及你将如何展示这些。举个例子,我开始在我的面试中使用我的一个大学项目,一个交互式仪表盘(你可以点击这里)。谈论一些你深有体会的事情总是会在任何工作面试中给你加分,即使这个项目本身并不完美或不确定。
最后,我收到第一份工作邀请的面试来自当地的一次数据科学会议,我怎么强调都不为过的重要性是,尽可能参加所有可能的活动,与人交往,展示你的面孔,不要指望事情会轻易发生,做一个斗士!
总之,从我第一次在谷歌上输入“数据科学”到我签下第一份数据分析师的合同,整整花了我一年的时间,外加相当于一辆二手车的钱,但更重要的是,这需要我每天尽可能多地学习
。目前,我已经完成了我的课程,我现在有兴趣深入研究 NLP 和分类技术,可能明年开始攻读硕士学位。我刚刚开始烤我的数据科学蛋糕,但我可以告诉你,这将是一个美味的蛋糕!
从预训练的单词嵌入到预训练的语言模型——关注 BERT
从静态单词嵌入到动态(语境化)单词嵌入
*“在每个 NLP 实践者的工具箱中,**被 预训练语言模型 *所取代,这似乎只是时间问题”Sebastian Ruder
adsieg.github.io
静态单词嵌入
- Skip-Gram & CBOW(又名 Word2Vec
- 手套
- 快速文本
- 外来 : Lda2Vec,Node2Vec,字符嵌入,CNN 嵌入,…
- 庞加莱嵌入学习分层表示
上下文化(动态)单词嵌入(LM)
- CoVe ( 语境化嵌词 s)
- 无级变速器 ( 交叉训练)
- ELMO ( 来自语言模型的嵌入)
- ULMFiT ( 通用语言模型微调)
- 伯特 ( 来自变压器的双向编码器表示)
- GPT&GPT-2(创成式预训)
- 变压器 XL (意为超长)
- XLNet ( 广义自回归预训练)
- 恩里耶 (通过知识整合增强表现)
- (flai Embeddings(用于序列标记的上下文字符串嵌入))
还有很多其他的…
adsieg.github.io
什么是好的模式?
最佳模型将能够捕获 4 个组件:
- 词汇方法(关于一种语言的单词或词汇)**
- 句法方法(在一种语言中创造结构良好的句子的词语和短语的排列- >语法)**
- 语义方法(关于语言中的意义——>引申意义,理解歧义)**
- 语用方法(词语与文档的接近度)**
模特的主要家族有哪些?
语言建模是在单词序列上分配概率分布的任务,该概率分布与语言的分布相匹配。虽然听起来令人生畏,(即埃尔莫、伯特、GPT) 的语言建模本质上只是在一片空白中预测单词。更正式地说,给定一个上下文,语言模型预测一个单词在该上下文中出现的概率。**
这种方法为什么有效?因为这种方法迫使模型学习如何使用整句话中的信息来推断遗漏了什么单词。
0.静态与动态
- 静态单词嵌入未能捕获多义词*。它们为不同上下文中的同一个单词生成同一个嵌入。###语境化单词嵌入旨在捕获不同语境中的单词语义,以解决多义问题和单词依赖于语境的性质。***
- 静态单词嵌入只能利用来自下游任务的无监督模型的向量输出——而不是无监督模型本身。它们开始时大多是浅模型*,并且在训练后经常被丢弃(例如 word2vec、Glove)# # #上下文化(动态)单词嵌入训练的输出是被训练的模型和向量——而不仅仅是向量。***
- 传统的单词向量是浅层表示*(单层权重,称为嵌入)。他们只是在模型的第一层融入了之前的知识。对于新的目标任务,网络的其余部分仍然需要从头开始训练。他们未能捕捉到可能更有用的高层信息。单词嵌入只在捕捉单词的语义时有用,但我们还需要理解更高层次的概念,如回指、长期依赖、一致、否定等等。***
演变:
http://ruder.io/10-exciting-ideas-of-2018-in-nlp/
迁移学习——一种不是从头开始训练模型的技术,我们使用在大型数据集上预先训练的模型,然后针对特定的自然语言任务对它们进行微调。******
一些特殊性:
- ULMFiT →通过微调进行传送****
- ELMo →通过特征提取转移****
- 伯特 →转移注意力提取****
为什么使用迁移学习?
在 vision 中,它已经实践了一段时间,人们使用经过训练的模型从庞大的 ImageNet 数据集学习特征,然后针对不同的任务在较小的数据上进一步训练它。
- 用于文本分类(或任何其他受监督的 NLP 任务)的大多数数据集都相当小。这使得训练深度神经网络非常困难,因为它们会倾向于过度适应这些小的训练数据并且在实践中不能很好地概括。****
在计算机视觉领域,几年来,趋势是在巨大的 ImageNet 语料库上预先训练任何模型。这比随机初始化好得多,因为该模型学习一般的图像特征,并且该学习可以用于任何视觉任务(比如字幕或检测)。
在 NLP 中,我们在上训练一个通用语言建模(LM)任务,然后在文本分类(或其他任务)上微调。原则上,这将执行得很好,因为模型将能够使用从生成性预训练中获得的语言语义知识。
- 它能够捕捉语言中的长期依赖
- 它有效地合并了层级关系
- 它可以帮助模型学习情绪
- 对于 LM 来说,大数据语料库很容易获得
伯特
https://mostafadehghani.com/2019/05/05/universal-transformers/
改进?
- GPTvs埃尔莫vs伯特- > 所有预训练模型架构的区别。伯特使用双向转换器对对 GPT 使用从左到右转换器对对埃尔莫使用独立训练的从左到右和从右到左 LSTM 的串联来为下游任务生成特征。在所有层中,BERT 表示是由左右上下文共同决定的。换句话说,它是深度双向的,与 ELMo ( 浅层双向)和 OpenAI GPT ( 一个方向,从左到右)相反。****
- 变形金刚证明了递归和卷积对于构建高性能的自然语言模型并不重要
- 他们使用一种自我注意操作来实现最先进的机器翻译结果
- 由于其并行性和运行时的特性,注意力是一个高效操作
- 传统的语言模型采用前 n 个标记并预测下一个标记。相比之下,BERT 训练了一个语言模型,在预测时将上一个和下一个标记都考虑在内——实际上是双向的。
- 如果你简单地要求一个深度神经网络通过阅读所有维基百科来学习典型的英语句子是什么样子,那么它对英语语言学习了什么? 当计算机已经将句子中的每个单词表示为实值向量,而没有解析树的显式表示时,BERT 对类似人类的解析树进行编码,并在这些向量空间中找到树结构 。BERT 能够从 Penn 树库中重建解析树。
- 针对特定 NLP 任务 (如 POS、NER 等)对每层的重要性进行评分。),表示在网络中基本句法信息被更早的 (较低层)捕获,随后是较高层的语义信息。这反映在右图中。(这个观察结果也类似于在 ELMo 模型中看到的情况)。
- 此外,与句法任务相关的信息似乎更多地局限于几个层,其中用于语义任务 ( SPR and Relations)的信息通常遍布整个网络
- 检查输出单词向量显示,不仅单词的不同含义以不同的表示形式被捕获,它们还以细粒度的方式在空间上被分离。
https://arxiv.org/pdf/1906.02715.pdf
7.每个单词必须经过的距离:在一个简单的 RNN 中,单词“Echt”必须经过多个步骤。最后的红色层必须存储编码信息。在超过 50 个单词的大句子中,每个单词需要移动的距离线性增加。由于我们不断地改写那些编码信息,我们肯定会漏掉句子中出现较早的重要单词。在编码之后,它还必须经过传播才能到达解码的目的地。
有了注意力机制,我们不再试图将完整的源句子编码成固定长度的向量。相反,我们允许解码器在输出生成的每一步“关注”源句子的不同部分。
注意机制的显著成就是提高了对模型的空间理解。
工作?
1.→从单词到向量
- 记号化就是把它劈成碎片的任务,叫做记号,或许同时扔掉某些字符,比如标点符号。**
- 使用词块(如 playing - > play + ##ing)代替单词。这可以有效地减少词汇表的大小,并增加每个单词的可用数据量。
- 数字化旨在将每个标记映射到语料库词汇中的唯一整数。
- 令牌嵌入的任务是为序列中的每个单词获得嵌入(即一个实数向量)。该序列的每个单词被映射到模型将在训练期间学习的 emb_dim 维向量。你可以把它看作是对每个令牌的向量查找。这些向量的元素被视为模型参数,并像任何其他权重一样通过反向传播进行优化。
- 填充用于使批次中的输入序列具有相同的长度。也就是说,我们通过添加’ <填充符> ’ 记号来增加一些序列的长度。**
- 位置编码:
回想一下位置编码的设计是为了帮助模型学习序列的一些概念和记号的相对位置。这对于基于语言的任务至关重要,尤其是在这里,因为我们没有使用任何传统的循环单元,例如 RNN 、 GRU 或 LSTM
直观地说,我们的目标是能够根据特定单词的位置来修改该单词所代表的意思。我们不想改变单词的完整表示,但是我们想通过使用预定的(非学习的)正弦函数向令牌嵌入中添加 [-1,1] 之间的数,对进行一点修改,以编码其位置。对于编码器的其余部分,单词将根据单词在中的位置略有不同地表示(即使是同一个单词)。****
编码器必须能够利用这样一个事实,即一些字在给定位置,而在同一序列中,其他字在其他特定位置。也就是说,我们希望网络能够理解相对位置和**,而不仅仅是绝对位置**。****
https://www.mihaileric.com/posts/transformers-attention-in-disguise/
作者选择的正弦函数允许位置被表示为彼此的线性组合,从而允许网络学习记号位置之间的相对关系。
让我们考虑一个例子:
********
位置嵌入可以理解为序列中不同单词之间的距离。这里的直觉是将这些值添加到嵌入中提供了嵌入向量之间有意义的距离,一旦它们被投影到 Q/K/V 向量中,以及在点积注意力期间。****
https://mc.ai/seq2seq-pay-attention-to-self-attention-part-2/
2.→编码器模块
https://jalammar.github.io/illustrated-transformer/
总共 N 个编码器模块链接在一起,产生编码器的输出。
****注: 在 **伯特’s 实验中,块数 N(或者他们所说的 L)被选为 12 和 24。
- 编码块的输入和输出的尺寸相同。因此,使用一个编码器模块的输出作为下一个编码器模块的输入是有意义的。
- 一个特定的模块负责寻找输入表示之间的关系,并将它们编码到其输出中。**
- 这些块彼此不共享权重。
- 这种通过块的迭代过程将帮助神经网络捕获输入序列中单词之间更复杂的关系。
- 转换器使用 多头注意力 ,这意味着它用不同权重矩阵计算注意力 h 不同时间,然后将结果串联在一起。****
注意机制
让我们深入研究一下注意力机制。请注意,编码器模块和解码器模块之间的多头自我关注是不同的。
https://mc.ai/seq2seq-pay-attention-to-self-attention-part-2/
一个头自我关注
一个 RNN 保持一个隐藏状态,允许它将它已经处理过的先前单词/向量的表示与它正在处理的当前单词/向量的表示合并。自我关注是转换器用来将对其他相关单词的“理解”烘焙到我们当前正在处理的单词中的方法。
https://jalammar.github.io/illustrated-transformer/
这句话中的“ it 指的是什么?它指的是街道还是动物?
- 从每个编码器的输入向量的创建三个向量和
- 对于的每个单词,我们创建一个查询向量*,一个关键向量,以及**一个值向量*******
- 这些向量是通过将嵌入乘以三个矩阵创建的,这三个矩阵是我们在训练过程中训练的。****
注意这些新向量在尺寸上比嵌入向量小。它们的维度是 64* ,而嵌入和编码器输入/输出向量的维度是 512。*****
为什么维度是 64?正如我们必须拥有的:
****- >输出的维数是【输入序列长度】x【嵌入维数— 512】
->我们在多头自关注过程中使用 8 头。给定自我关注向量的输出大小为【输入序列长度】x【64】。因此所有多头自关注*过程产生的连接向量将是[输入序列长度]x([64]x[8])=[输入序列长度] x ([512])*******
How Self-Attention works?
****查询 q:查询向量 q 对左侧正在关注的单词/位置进行编码,即正在“查询”其他单词的那个。在上例中,突出显示了“the”(所选单词)的查询向量。
键 k: 键向量 k 对关注的右边的单词进行编码。如下所述,关键向量与查询向量一起确定各个单词之间的关注度得分。
q×k (逐元素):查询向量和一个关键向量的逐元素乘积。该乘积是在所选查询向量和每个关键向量之间计算的。这是点积(逐元素积的总和)的前身,包含它是为了可视化,因为它显示了查询中的单个元素和关键向量是如何贡献点积的。
q k :选择的查询向量和每个 keyvectors 的点积。这是未标准化的注意力得分。
Softmax :所有目标词的 q k / 8 的 Softmax。这将注意力分数归一化为正值,并且总和为 1。常数因子 8 是向量长度的平方根(64)。这个 softmax 分数决定了每个单词在这个位置的表达量。显然,在这个位置的单词将具有最高的 softmax 分数,但是有时关注与当前单词相关的另一个单词是有用的。
这三个向量怎么算?
我们为输入序列中的每个单词计算自我注意。
关注“分数”
【K 的 Q x 转置】是查询向量和关键向量的乘积标量。关键向量比查询向量越接近,由【Q x 转置】得到的分数越高。****
Softmax 将为我们提供一种概率分布,该概率分布保持增加与相应查询向量相似的关键向量的值,并因此保持减少远离查询向量的关键向量。
- d _ v设置为d _ k=d _ v=emb _ dim/h .
记住 Q 和 K 是令牌到一个 d_k (即 64)维空间的不同投影。因此,我们可以把 这些投影的点积看作是表征投影之间相似性的度量 。对于通过 Q 投影的每个向量,通过K投影的点积测量这些向量之间的相似性。如果我们分别通过 Q 和 K 将v _ I和 u_j 称为第 I 个令牌和第 j 个令牌的投影,它们的点积可以看做:********
这是衡量的方向有多相似 u_i 和v _ j和它们的长度有多大(方向越近,长度越大,点积越大)。******
考虑这个矩阵乘积的另一种方式是作为输入序列中每个记号之间的特定关系的编码(该关系由矩阵 K 、 Q 定义)。
https://lesdieuxducode.com/blog/2019/4/bert–le-transformer-model-qui-sentraine-et-qui-represente
我们看到""的查询向量和" store "(下一个单词)的关键向量的乘积在大多数神经元中都是强正的。对于除下一个令牌之外的令牌,键查询产品包含一些正值和负值的组合。结果是“The”和“store”之间的关注度得分较高。******
举例:考虑一下这个短语——“行动得到结果 ”。为了计算第一个单词“Action”的自我关注度,我们将计算短语中所有单词相对于“Action”的得分。当我们对输入序列中的某个单词进行编码时,该分数决定了其他单词的重要性。
https://www.analyticsvidhya.com/blog/2019/06/understanding-transformers-nlp-state-of-the-art-models/
https://www.analyticsvidhya.com/blog/2019/06/understanding-transformers-nlp-state-of-the-art-models/
让我们回到最初的例子:
********
总而言之,当谈到单头自我关注时
注意力背后的主要思想是查找表,一个有大量其他值的表你问它一个查询和它返回一个最接近它的。在这里使用的方法中,我们给它提供了三个值,键、值和查询。有大量的键,基本上是 n 维空间中的 1 维向量,其中每个键都有一些对应的值。
https://medium.com/datadriveninvestor/lets-build-attention-is-all-you-need-1-2-de377cebe22
注意功能可以描述为一个字典对象。
https://persagen.com/resources/biokdd-review-nlu.html
B —多头自我关注
这篇论文指出“附加注意”比上述自我注意表现得更好,尽管它要慢得多。加法注意力使用更复杂的兼容性函数,即前馈神经网络。
在 Transformer 的架构中,自我关注不是一次而是多次计算,并行且独立。因此称为多头关注。输出被连接并进行线性转换,如下图所示:
变压器使用八个注意力头,所以我们最终为每个编码器/解码器提供八套。每个集合用于将输入嵌入投影到不同的表示子空间。如果我们做同样的自我关注计算,我们会得到八个不同的 Z 矩阵。****
然而,前馈层并不期望八个矩阵。我们需要将它们连接起来,并通过将它们与附加权重矩阵 w0 相乘,将这八个压缩成一个矩阵
在多头注意力中如何将 8 个矩阵 Z1…Z8 返回成单个矩阵 Z?
在一个矩阵 W0 上串联一个排序,维数为 512 x 512([(nom bre de têtes)x(dimension reqête or cléou valeur,即 64)]x[dimension des embedding]),快速研究在一个排序空间上的结果。
https://lesdieuxducode.com/blog/2019/4/bert–le-transformer-model-qui-sentraine-et-qui-represente
总而言之…
https://jalammar.github.io/illustrated-transformer/
结果如下:
https://jalammar.github.io/illustrated-transformer/
辍学、新增和正常
https://web . Stanford . edu/class/archive/cs/cs 224n/cs 224n . 1184/lectures/lectures 12 . pdf
在这一层之前,总有一层输入和输出具有相同的尺寸(多头关注或前馈)。我们称该层为子层及其输入 x.****
在每个子层之后,以 10%的概率应用丢失。把这个结果叫做 Dropout(Sublayer(x)) 。这个结果被添加到子层的输入 x,,我们得到 x + Dropout(子层(x))。****
注意,在多头注意力层的上下文中,这意味着将令牌 x 的原始表示添加到基于与其他令牌的关系的表示中。这就像告诉令牌:**
“学习与其余令牌的关系,但不要忘记我们已经了解的关于你自己的内容!”
最后,用每一行的平均值和标准偏差计算标记方式/行方式的归一化。这提高了网络的稳定性。
https://jalammar.github.io/illustrated-transformer/
https://arxiv.org/pdf/1607.06450.pdf
我们计算用于归一化的平均值和方差,该平均值和方差来自单个训练案例中一层中神经元的所有总计输入。
位置式前馈网络
除了注意子层之外,我们的编码器和解码器中的每一层都包含一个完全连接的前馈网络,该网络分别且相同地应用于每个位置。这由两个线性转换组成,中间有一个 ReLU 激活。
https://mc.ai/seq2seq-pay-attention-to-self-attention-part-2/
虽然不同位置的线性变换是相同的,但是它们在层与层之间使用不同的参数。另一种描述方式是两个内核大小为 1 的卷积。输入和输出的维数是 dmodel=512,内层的维数是 dff=2048。
神经元的形式与一个激活的相关函数,形式类似于:
Ici W1 a pour dimensions[dimension des embedding]x[dimension d ’ entre d '渡厄·FFN-奥乔瓦]和 W2[dimension d ’ entre 渡厄·FFN-奥乔瓦]x[dimension des embedding]。来源ici*。*
3.→解码器模块
每个解码层由子层组成:
- 屏蔽多头注意(带前瞻屏蔽和填充屏蔽
- 多头注意(带垫口罩)。v(值)和 K(键)接收编码器输出作为输入。Q (query)接收来自屏蔽多头注意子层的输出。****
- 点式前馈网络
这些子图层中的每一个都有一个围绕它的残差连接,然后是图层规范化。每个子层的输出是LayerNorm(x + Sublayer(x))
。
变压器中有 N 个解码器层。
当 Q 接收来自解码器第一关注块的输出, K 接收编码器输出,关注权重代表基于编码器输出给予解码器输入的重要性。换句话说,解码器通过查看编码器输出并关注自身输出来预测下一个字。****
Decoder
包括:
- 输出嵌入
- 位置编码
- 解码器层
目标经过嵌入,该嵌入与位置编码相加。该求和的输出是解码器层的输入。解码器的输出是最终线性层的输入。
What are the inputs of Transformer?
我们同时输入和输出句子。输出最初可以用任何东西填充,模型忽略你填充的任何东西。它使用整个输入句子和输出句子一次性预测下一个单词。一旦我们预测了单词,我们在输出序列中替换它,模型只考虑到该点的输出,而忽略它前面的内容。我们继续这样做,直到我们有一个完整的句子。
多头掩蔽自我注意
在编码器中,自关注层过程输入查询来自上一层的输出的、键和值。编码器中的每个位置可以照顾到上一层编码器的所有位置。**
在解码器中,自关注层使每个位置能够关注解码器中所有以前的位置,包括当前位置。**
https://persagen.com/resources/biokdd-review-nlu.html
To prevent positions from attending to subsequent position (http://www.peterbloem.nl/blog/transformers)
****换句话说,自关注层仅被允许关注输出序列中前面的位置。掩蔽多头注意力是通过在自我注意力计算中的 softmax 步骤之前掩蔽未来位置(将它们设置为-∞)来完成的。该步骤确保位置 i 的预测仅依赖于小于 i 位置的已知输出。因为我们希望这些元素在 softmax 之后为零,所以我们将它们设置为。
http://www.peterbloem.nl/blog/transformers
对于 RNNs——不存在这样的问题,因为它们无法预测输入序列:输出 I 仅取决于输入 0 至 i 。使用 transformer,输出依赖于整个输入序列,因此预测下一个单词/字符变得非常容易,只需从输入中检索即可。
要使用自我关注作为自回归模型,我们需要确保它不能预测到结果 e。在应用 softmax 之前,我们通过对点积矩阵应用遮罩来做到这一点。该掩码禁用矩阵对角线上方的所有元素。
在我们像这样禁用了自我关注模块之后,模型在序列中不再向前看。
“解码器关注层的工作方式类似于多头自我关注,除了它从其下面的层创建其查询矩阵,并且从编码器堆栈的输出中获取键和值矩阵。****
********
解码器中的自关注层允许解码器中的每个位置关注解码器中的所有位置,直到并包括该位置。我们需要在解码器中防止向左的信息流,以保持的自回归特性。我们通过屏蔽(设置为∞)soft max 输入中与非法连接相对应的所有值,在比例点积注意中实现这一点。
4.→最终的线性和 Softmax 层
解码器堆栈输出一个浮点向量。我们如何把它变成一个单词?这是最后一个线性层的工作,接着是一个 Softmax 层。
线性层是一个简单的全连接神经网络,它将解码器堆栈产生的矢量投影到一个更大的矢量中,称为 logits 矢量。这个空间就是词汇量(所有单词)的大小。我们只是将权重矩阵(由解码器块提供)投影到“词汇空间”中。
从数学上讲,这意味着什么?
从代码的角度来看。关于矩阵 W1 的乘法。这是一个完整的连接,它是一个简单的在一个不可改变的尾巴空间里的一个故事。
在我们的词汇词典中,这是一个单词。elle aura donc pour dimensions[dimension des embedding,即d model]x[nom bre de mots dans notere]。**
让我们假设我们的模型知道 10,000 个独特的英语单词(我们模型的“输出词汇”),这些单词是从它的训练数据集学习来的。这将使 logits 向量有 10,000 个单元格宽 — 每个单元格对应一个唯一单词的分数。这就是我们如何解释线性层之后的模型输出。
然后 softmax 层再将这些分数转化为概率(都是正数,加起来都是 1.0)。选择概率最高的单元格,并产生与之相关的单词作为该时间步长的输出。Softmax 为我们提供了最有可能预测到的单词(我们采用给我们最高概率的列中的单词)。
https://jalammar.github.io/illustrated-transformer/
该图从底部开始,矢量作为解码器堆栈的输出产生。然后它被转换成一个输出字。
5.→剩余连接
一个残差连接基本上就是取输入,加到子网络的输出,让训练深度网络在计算机视觉领域变得更容易。层归一化是深度学习中的一种归一化方法,类似于批量归一化。在图层标准化中,统计数据是跨每个特征计算的,并且独立于其他示例。输入之间的独立性意味着每个输入都有不同的规范化操作。
7.→模型训练—如何训练 BERT?
A —屏蔽语言建模(MLM)
屏蔽语言模型从输入中随机屏蔽一些标记,目标是仅基于其上下文预测屏蔽单词的原始词汇 id。与从左到右语言模型预训练不同,MLM 目标允许表示融合左右上下文,这允许我们预训练一个深度双向转换器
谷歌人工智能研究人员随机屏蔽了每个序列中 15%的单词。任务?来预测这些蒙面文字。这里有一个警告—被屏蔽的单词并不总是被屏蔽的标记[MASK]替换,因为[MASK]标记在微调过程中永远不会出现。
因此,研究人员使用了以下技术:
- 80%的情况下,单词被替换为掩码标记[MASK]
- 10%的时候,这些单词被随机的单词替换
- 10%的时间单词保持不变
XLNet
B-下一句预测
通常,语言模型不能捕捉连续句子之间的关系。伯特也预先接受了这项任务的训练。
对于语言模型预训练,BERT 使用句子对作为其训练数据。每一对的选句都挺有意思的。我们试着借助一个例子来理解一下。
假设我们有一个包含 100,000 个句子的文本数据集,我们希望使用该数据集预先训练一个 BERT 语言模型。因此,将有 50,000 个训练示例或句子对作为训练数据。
- 对于 50%的配对,第二句实际上是第一句的下一句
- 对于剩余的 50%的对,第二个句子将是来自语料库的随机句子
- 第一种情况的标签是‘是下一个’,第二种情况的标签是*‘不是下一个’*******
应用程序?
A- Real 应用程序:预培训与微调
A review of BERT based models (https://towardsdatascience.com/a-review-of-bert-based-models-4ffdc0f15d58)
**在领域/应用特定语料库上预训练的模型是**预训练模型。在特定领域语料库上的训练已经表明,当在下游自然语言处理任务(如 NER 等)上对它们进行微调时,会产生更好的性能。对于那些领域,对比微调 BERT (在图书语料库和维基百科上训练过)。
- 比奥伯特 (生物医学文本)
- 塞伯特 (科学出版物)
- (临床笔记)
- G-BERT ( 医疗/诊断代码表示和建议)
- M-BERT 来自 104 种语言,用于零触发跨语言模型转移(一种语言中的任务特定注释用于微调模型,以便在另一种语言中进行评估)**
- 厄尼 (知识图)+ 厄尼 (2)将知识融入预训练但通过使用 KG 屏蔽实体和短语。
- trans Bert——无监督,跟随两个监督步骤,用于故事结局预测任务
- videoBERT ( 联合学习视频和语言表示学习的模型)通过将视频帧表示为特殊的描述符令牌,以及用于预训练的文本。这用于视频字幕。
微调型号。使用预训练模型针对特定任务进行微调的模型:
- 文档分类(文档分类)
- PatentBERT (专利分类)
b 案例研究
- 使用 BERT 进行更好的情感分析:通过在预训练的模型上应用一个新层和 softmax 进行微调+使用 Docker 和 Tensorflow + API
- 使用 BERT 和 TensorFlow 构建多标签文本分类器:在多标签分类中,不使用 softmax() ,而是使用 sigmoid() 来获取概率。Sigmoid 允许处理非独占标签(也称为多标签),而 softmax 处理独占类+计算一个 logit (也称为分数)
- 逻辑回归& BERT :使用 BERT 嵌入运行逻辑回归
- 使用 PyTorch 的 BERT 微调教程:
- 驯服 BERT——基线:微调 BERT 模型,而不是使用预先训练的权重+使用 BERT 层的混合,而不是只使用最后一层的输出+调整 MLP 模型的一些超参数
- BERT:Faire comprender le langage naturalàa machine,en pre-entrant des Transformers bi-directionals profonds:法国分类
奖金:
1.为什么要除以平方(dk)?
2.微调
来自https://yashuseth . blog/2019/06/12/Bert-explained-FAQs-understand-Bert-working/
- 序列分类任务的微调程序是什么?
- 句子对分类任务的微调程序是怎样的?
- 问答任务的微调程序是怎样的?
- 单句标注任务的微调程序是怎样的?
3.伯特即服务
输入记号的最终隐藏状态(变换器输出)可以被连接和/或汇集在一起,以获得句子的编码表示。bert-as-a-service是一个开源项目,提供针对生产优化的 BERT 语句嵌入。 使用 Tensorflow 和 ZeroMQ 在生产中服务 Google BERT。
4.库尔贝克·莱布勒散度
https://en.wikipedia.org/wiki/Kullback–Leibler_divergence
从“R 与 Python”到“R 与 Python”
在单个项目中充分利用 Python 和 R’的优点。
重点应该放在技能上,而不是工具上
如果你对数据科学感兴趣,可能会立即想到的两种编程语言是 R 和 Python 。然而,我们不是将它们视为两种选择,而是经常将它们进行比较。r 和 Python 本身都是优秀的工具,但经常被视为竞争对手。如果你在谷歌搜索栏中输入R vs Python
,你会立即得到大量关于一方优于另一方的话题的资源。
这种观点的原因之一是因为人们已经根据他们使用的编程语言的选择将数据科学领域分成了不同的阵营。有一个 R 阵营和一个 Python 阵营,历史是两个阵营无法和谐相处的见证。两个阵营的成员都坚信他们选择的语言优于对方。所以,在某种程度上,分歧不在于工具,而在于使用这些工具的人
为什么不两个都用?
数据科学社区中有人同时使用 Python 和 R,但他们的比例很小。另一方面,有许多人只致力于一种编程语言,但希望他们能够获得对手的一些能力。例如,R 用户有时渴望 Python 固有的面向对象能力,类似地,一些 Python 用户渴望 R 中可用的大范围统计分布。
上图为红和尚2018 年第三季度调查结果。这些结果基于语言在 Stack Overflow 和 Github 上的受欢迎程度,清楚地表明 R 和 Python 都被评为相当高。因此,我们没有内在的理由不能在同一个项目中与他们合作。我们的最终目标应该是做更好的分析,获得更好的洞察力,选择编程语言不应该成为实现这一目标的障碍。
R 和 Python 概述
让我们来看看这些语言的各个方面,以及它们的优点和缺点。
计算机编程语言
自 1991 年发布以来,Python 一直非常流行,并广泛应用于数据处理。它广受欢迎的一些原因是:
- 面向对象语言
- 通用
- 有很多扩展和令人难以置信的社区支持
- 简单易懂,易于学习
- 像 pandas、numpy 和 scikit-learn 这样的包使 Python 成为机器学习活动的绝佳选择。
然而,Python 没有专门的统计计算包,不像 r。
稀有
r 的第一个版本发布于 1995 年,从那时起,它已经成为业内最常用的数据科学工具之一。
- 包括几乎所有你能想到的统计应用的软件包。CRAN 目前托管超过 10k 个软件包。
- 配备了出色的可视化库,如 ggplot2。
- 能够独立分析
就性能而言,R 不是最快的语言,而且在处理大型数据集时,有时会占用大量内存。
利用两个世界的优点
我们能利用 R 的统计能力和 Python 的编程能力吗?那么,当我们可以轻松地将 SQL 代码嵌入到 R 或 Python 脚本中时,为什么不将 R 和 Python 融合在一起呢?
基本上有两种方法可以让我们在一个项目中同时使用 Python 和 R。
Python 中的 r
PypeR 提供了一种通过管道从 Python 访问 R 的简单方法。PypeR 也包含在 Python 的包索引中,这提供了一种更方便的安装方式。当 Python 和 R 之间不需要频繁的交互数据传输时,PypeR 特别有用。通过管道运行 R,Python 程序在子进程控制、内存控制和跨流行操作系统平台(包括 Windows、GNU Linux 和 Mac OS)的可移植性方面获得了灵活性
Conventions for conversion of Python objects to R objects
pyRserve 使用 Rserve 作为 RPC 连接网关。通过这样的连接,可以在 Python 的 R 中设置变量,也可以远程调用 R 函数。R 对象作为 Python 实现的类的实例公开,在许多情况下,R 函数作为这些对象的绑定方法。
rpy2 在 Python 进程中运行嵌入式 R。它创建了一个框架,可以将 Python 对象翻译成 R 对象,将它们传递给 R 函数,并将 R 输出转换回 Python 对象。rpy2 使用得更频繁,因为它是一种正在积极开发的产品。
在 Python 中使用 R 的一个好处是,我们可以在 Python 中轻松使用 R 的优秀包,如 ggplot2、tidyr、dplyr 等。作为一个例子,让我们看看如何在 Python 中轻松使用 ggplot2 进行映射。
- 基本情节
https://rpy2.github.io/doc/latest/html/graphics.html#plot
- 几何
https://rpy2.github.io/doc/latest/html/graphics.html#geometry
资源
为了更深入地了解 rpy2 ,您可能想看看以下资源:
R 内的 Python
我们可以使用下面的一种方法在 Python 中运行 R 脚本:
这个包通过 Jython 实现了 Python 的一个接口。它旨在让其他包能够嵌入 python 代码和 r。
rPython 又是一个允许 R 调用 Python 的包。它使得运行 Python 代码、进行函数调用、分配和检索变量等成为可能。从 r。
《耍蛇者》是 rPython 的现代改良版。它是“rPython”的一个分支,使用了“jsonlite ”,对 rPython 做了很多改进。
PythonInR 通过提供从 R 内部与 Python 交互的函数,使得从 R 内部访问 Python 变得非常容易。
reticulate 包为 Python 和 r 之间的互操作性提供了一套全面的工具。在上述所有选择中,这一个是使用最广泛的,因为它是由 Rstudio 积极开发的。Reticulate 在 R 会话中嵌入了一个 Python 会话,实现了无缝、高性能的互操作性。这个包使你能够将 Python 代码编织成 R 语言,创建一个将两种语言编织在一起的新型项目。
网状包提供以下设施:
- 以多种方式从 R 调用 Python,包括 R Markdown、获取 Python 脚本、导入 Python 模块以及在 R 会话中交互使用 Python。
- R 和 Python 对象之间的转换(例如,R 和 Pandas 数据框之间,或者 R 矩阵和 NumPy 数组之间)。
- 灵活绑定到不同版本的 Python,包括虚拟环境和 Conda 环境。
资源
关于使用 reticulate 包的一些重要资源有:
- 文档非常健壮,有很多例子和用例来帮助你开始。
- https://longhowlam . WordPress . com/2017/04/10/test-driving-python-integration-in-r-using-the-reticulate-package/
- 包装中的蛇:结合 PYTHON 和 R 与 RETICULATE
结论
R 和 Python 都是非常健壮的语言,它们中的任何一种实际上都足以执行数据分析任务。然而,他们两个肯定都有高低之分,如果我们能利用两者的优势,我们最终会做得更好。无论哪种方式,拥有这两方面的知识将使我们更加灵活,从而增加我们能够在多种环境中工作的机会。
参考
本文改编自 Andrew Collier 于 2018 年在 Pydata Berlin 发表的这篇 精彩演讲 。
http://blog . yhat . com/tutorials/RP y2-coming-the-power-of-r-and-python . html
从原始图像到深度学习的实时预测
使用 Keras、Flask 和 OpenCV 的人脸表情识别
Photo by Peter Lloyd on Unsplash
在我看来,人工智能最令人兴奋的领域之一是计算机视觉。我发现非常有趣的是,我们现在如何从复杂的原始数据结构(如图像)中自动提取知识。
本文的目标是探索一个计算机视觉应用的完整例子:构建一个具有深度学习的人脸表情识别系统。我们将了解如何:
- 设计一个卷积神经网络
- 通过输入一批图像来训练它
- 将其导出,以便与实时图像数据一起重新使用
工具
Keras 是一种高级神经网络 API,用 Python 编写,能够在 TensorFlow、CNTK 或 Theano 之上运行。我们将用它来建立、训练和输出神经网络。
Flask 是一个用 Python 编写的微型 web 框架,它允许我们将模型直接提供给 web 界面。
OpenCV 是一个计算机视觉库,有 C++、Python 和 Java 接口。我们将使用这个库来自动检测图像中的人脸。
数据源
数据来源于往届 Kaggle 竞赛《表征学习中的挑战:面部表情识别挑战》:
该数据由 48x48 像素的面部灰度图像组成。面部已经被自动注册,使得面部或多或少地居中,并且在每个图像中占据大约相同的空间。每张图片对应七种表情中的一种(0 =生气,1 =厌恶,2 =恐惧,3 =快乐,4 =悲伤,5 =惊讶,6 =中性)。数据集包含大约 36K 幅图像。
原始数据包含在数组中,每个像素有一个灰度值。我们将这些数据转换成原始图像,并将其拆分到多个文件夹中:
images/
train/
angry/
disgust/
fear/
happy/
neutral/
sad/
surprise/
validation/
angry/
disgust/
fear/
happy/
neutral/
sad/
surprise/
我们 80%的图像包含在 train 文件夹中,最后 20%在 validation 文件夹中。
快速数据可视化
首先让我们看看我们的图像是什么样子的:
Sample of the training images
你能猜出这些图像与哪些表情有关吗?
这项任务对人来说很容易,但对预测算法来说可能有点挑战,因为:
- 这些图像的分辨率很低
- 这些面不在同一位置
- 一些图像上写有文字
- 有些人用手遮住部分脸
然而,所有这些图像的多样性将有助于建立一个更通用的模型。
4103 fear images
436 disgust images
4982 neutral images
7164 happy images
3993 angry images
3205 surprise images
4938 sad images
除了“厌恶”类别,我们训练数据集中的面部表情相当平衡。
设置数据生成器
深度学习模型通过输入批量数据来训练。Keras 有一个非常有用的类可以自动从目录中获取数据:ImageDataGenerator。
Found 28821 images belonging to 7 classes.
Found 7066 images belonging to 7 classes.
它还可以在获取图像的同时执行数据扩充(随机旋转图像、缩放等。).当数据集很小时,这种方法通常被用作人工获取更多数据的方法。
函数 flow_from_directory()指定生成器应该如何导入图像(路径、图像大小、颜色等)。).
设置我们的卷积神经网络(CNN)
我们选择使用卷积神经网络来解决这个人脸识别问题。事实上,这种类型的神经网络(NN)对于提取图像的特征是很好的,并且被广泛用于图像分析主题,如图像分类。
快速提醒什么是 NN:
神经网络是由多层人工神经元(节点)组成的学习框架。每个节点获得加权的输入数据,将其传递给激活函数,并输出该函数的结果:
A node
神经网络由几层节点组成:
A classic NN architecture
- 将获取数据的输入图层。输入图层的大小取决于输入数据的形状。
- 一些隐藏层将允许神经网络学习数据中复杂的相互作用。具有许多隐藏层的神经网络被称为深度神经网络。
- 给出最终结果的输出层,例如类别预测。这一层的大小取决于我们想要产生的输出类型(例如,我们想要预测多少个类?)
经典神经网络通常由几个完全连接的层组成。这意味着一层的每个节点都连接到下一层的所有节点。
卷积神经网络也具有卷积层,该卷积层将滑动函数应用于彼此相邻的像素组。因此,这些结构对我们可以在图像中观察到的模式有更好的理解。我们将在后面对此进行更详细的解释。
现在让我们来定义 CNN 的架构:
我们用以下全球架构定义我们的 CNN:
- 4 个卷积层
- 2 个完全连接的层
卷积层将从图像中提取相关特征,完全连接的层将专注于使用这些特征来很好地分类我们的图像。这个建筑的灵感来自于以下关于这个主题的工作:【https://github.com/jrishabh96/Facial-Expression-Recognition
现在让我们来关注这些卷积层是如何工作的。其中每个都包含以下操作:
- 卷积运算符:使用滑动矩阵从输入图像中提取特征,以保持像素之间的空间关系。下图总结了它的工作原理:
A convolution operator
绿色矩阵对应于原始图像值。橙色滑动矩阵被称为“过滤器”或“内核”。此滤镜在图像上滑动,每步滑动一个像素。在每一步中,我们将滤波器与基础矩阵的相应元素相乘,并将结果相加。有不同类型的过滤器,每一种都能够检索不同的图像特征:
Different filter results
- 我们应用 ReLU 函数在 CNN 中引入非线性。也可以使用其他函数,如 tanh 或 sigmoid,但 ReLU 在大多数情况下表现更好。
- 池用于减少每个特征的维数,同时保留最重要的信息。像卷积步骤一样,我们对数据应用滑动函数。可以应用不同的函数:max、sum、mean…max 函数通常执行得更好。
Max pooling operation
我们还为每一层使用一些通用技术:
- 批量标准化:通过提供零均值和单位方差的输入,提高 NNs 的性能和稳定性。
- Dropout:通过随机不更新某些节点的权重来减少过度拟合。这有助于防止神经网络过分依赖层中的一个节点。
我们选择 softmax 作为最后的激活函数,因为它通常用于多标签分类。
现在我们的 CNN 已经定义好了,我们可以用更多的参数来编译它。我们选择 Adam 优化器,因为它是计算效率最高的优化器之一。我们选择分类交叉熵作为我们的损失函数,因为它与分类任务非常相关。我们的衡量标准将是准确性,这对于平衡数据集上的分类任务也非常有用。
在这里,我们从头开始定义和训练我们的 CNN,但您可能希望对需要更多计算资源的问题应用迁移学习方法。Keras 有几个预先训练好的模型可供使用:
Keras 应用程序是深度学习模型,可与预训练的权重一起使用。这些型号可以是…
keras.io](https://keras.io/applications/)
训练模型
一切都准备好了,现在开始训练我们的模型吧!
Epoch 1/50
225/225 [==============================] - 36s 161ms/step - loss: 2.0174 - acc: 0.2333 - val_loss: 1.7391 - val_acc: 0.2966
Epoch 00001: val_acc improved from -inf to 0.29659, saving model to model_weights.h5Epoch 2/50
225/225 [==============================] - 31s 138ms/step - loss: 1.8401 - acc: 0.2873 - val_loss: 1.7091 - val_acc: 0.3311
Epoch 00002: val_acc improved from 0.29659 to 0.33108, saving model to model_weights.h5...Epoch 50/50
225/225 [==============================] - 30s 132ms/step - loss: 0.6723 - acc: 0.7499 - val_loss: 1.1159 - val_acc: 0.6384
Epoch 00050: val_acc did not improve from 0.65221
我们的最佳模型设法获得了大约 65%的验证准确率,这已经很不错了,因为我们的目标类有 7 个可能的值!
在每个时期,Keras 检查我们的模型是否比前一时期的模型表现得更好。如果是这种情况,新的最佳模型权重被保存到文件中。这将允许我们直接加载模型的权重,而不必在其他情况下使用它时重新训练它。
我们还必须保存我们的 CNN 的结构(层等)。)到一个文件中:
分析结果
我们在训练阶段的每一步都有产出。所有这些输出都保存在“历史”变量中。我们可以使用它在训练和验证数据集上绘制损失和准确性的演变:
Evolution of loss and accuracy with the number of training epochs
在 50 个周期结束时,验证准确度开始稳定在 60%和 65%之间。
训练损失略高于第一个时期的验证损失,这可能令人惊讶。事实上,我们习惯于看到机器学习中验证损失比训练损失更高。在这里,这仅仅是由于辍学的存在,它只适用于培训阶段,而不是在验证阶段。
我们可以看到,在第 20 次迭代之后,训练损失变得比验证损失小得多。这意味着我们的模型在太多的时期后开始过度适应我们的训练数据集。这就是为什么验证损失在之后没有减少很多的原因。一种解决方案是提前停止模型的训练。
我们也可以使用一些不同的丢弃值并执行数据扩充。这些方法在这个数据集上进行了测试,但是尽管它们减少了过拟合效应,但是它们并没有显著增加验证的准确性。使用它们稍微增加了模型的训练持续时间。
最后,我们可以绘制混淆矩阵,以了解我们的模型如何对图像进行分类:
我们的模型非常适合预测快乐和惊讶的面孔。然而,它预测的是非常糟糕的恐惧面孔,因为它把它们和悲伤的面孔混淆了。
随着更多的研究和更多的资源,这个模型肯定会得到改善,但这项研究的目标主要是集中在获得一个相当好的模型相比,在这个领域已经做了什么。
现在是时候在真实情况下尝试我们的模型了!我们将使用 flask 来服务于我们的模型,以便通过网络摄像头输入来执行实时预测。
实时预测
对于这一部分,我重用了来自以下存储库的一些代码:
首先,让我们创建一个类,它将为我们提供之前训练的模型的预测:
接下来,我们实现一个 camera 类,它将执行以下操作:
- 从我们的网络摄像头获取图像流
- 使用 OpenCV 检测人脸并添加边界框
- 将人脸转换成灰度,重新缩放,然后发送给我们预先训练好的神经网络
- 从我们的神经网络中获取预测,并将标签添加到网络摄像头图像中
- 返回最终的图像流
最后,我们的主脚本将创建一个 Flask 应用程序,将我们的图像预测渲染到一个网页中。
这是结果!
Our face expression recognition app
有用!我们的应用程序能够检测面部位置并预测正确的表情。
然而,该模型似乎在恶劣的条件下工作不佳(低光,人没有面对相机,人移动…),但仍然是一个好的开始!
感谢阅读这篇文章,我希望你喜欢它!
你可以在这里找到完整的代码:
带有 Keras、Flask 和 OpenCV-jonathanoheix/实时面部表情识别的面部表情识别应用程序
github.com](https://github.com/jonathanoheix/Real-Time-Face-Expression-Recognition)
在 LinkedIn 上找到我:
[## Jonathan Oheix -数据科学家- Influans | LinkedIn
查看 Jonathan Oheix 在全球最大的职业社区 LinkedIn 上的个人资料。乔纳森列出了 8 份工作…
www.linkedin.com](https://www.linkedin.com/in/jonathanoheix/)
从 sci kit-学会火花 ML
从 Python 到 Scala 的机器学习项目
在之前的一篇文章中,我展示了如何获取房屋销售的原始数据集,并在 Python 中对熊猫应用特征工程技术。这使我们能够使用 scikit-learn 机器学习模型来产生和改进对房屋销售价格的预测。
但是,当你想把这种项目投入生产,而不是 10,000 个数据点,也许有几十或几百千兆字节的数据来训练时,会发生什么呢?在这种情况下,脱离 Python 和 scikit 是值得的——学习可以处理大数据的框架。
输入 Scala 和 Spark
Scala 是一种基于 Java 虚拟机(JVM)的编程语言,使用函数式编程技术。Scala 中有无数非常复杂的特性可以学习,但是开始使用基本的 Scala 并不比用 Java 甚至 Python 编写代码难多少。
另一方面,Spark 是一个基于 Hadoop 技术的框架,它提供了比传统 Hadoop 更多的灵活性和可用性。它可能是管理和分析大型数据集(也称为大数据)的最佳工具。Spark ML 框架允许开发人员在构建机器学习模型时使用 Spark 进行大规模数据处理。
为什么不首先在 Spark ML 中完成所有的数据探索和模型训练呢?当然可以,但事实是,Python 更容易进行开放式探索,尤其是当您在 Jupyter 笔记本上工作时。但是话虽如此,Scala 和 Spark 并不需要比 Python 复杂太多,因为 pandas 和 Spark 都使用数据帧结构进行数据存储和操作。我们的目标是展示这种简单性,而不是纠结于困难。
这篇文章不会深入探讨 Scala 的复杂性,它假设你对之前的项目有所了解。我们将重现 Python 示例的结果,但我们不会重复我们这样做的所有原因,因为它们在前面已经解释过了。
首先,我们将从加载数据集开始,与之前完全相同的 CSV 文件。
val data_key = “housing_data_raw.csv”val df = spark.read
.format(“csv”)
.option(“header”, “true”)
.option(“inferSchema”, “true”)
.load(s”./$data_key”)
接下来,我们将删除我们在上一篇文章中发现的异常值。
import org.apache.spark.sql.DataFrame
import org.apache.spark.sql.functions._def drop_outliers(data: DataFrame) = {
val drop = List(1618, 3405,10652, 954, 11136, 5103, 916, 10967, 7383, 1465, 8967, 8300, 4997)
data.filter(not($"_c0".isin(drop:_*)))
}val housing = drop_outliers(df)
现在,我们将lastsolddate
字段从文本转换为数值,回归模型可以对其进行训练。
val housing_dateint = housing.withColumn("lastsolddateint", unix_timestamp($"lastsolddate","MM/dd/yy"))
我们还想删除一些列,反正现在我们不想在这些列上进行训练。
def drop_geog(data: DataFrame, keep: List[String] = List()) = {
val removeList = List("info","address","z_address","longitude","latitude","neighborhood",
"lastsolddate","zipcode","zpid","usecode", "zestimate","zindexvalue")
.filter(!keep.contains(_))
data.drop(removeList: _*)
}val housing_dropgeo = drop_geog(housing_dateint)
我们通过一个函数来执行这个操作,以防我们以后想要再次运行相同的代码,我们将会这样做。还要注意,该函数有一个keep
参数,以防我们想要实际保留我们要删除的这些值中的一个。我们稍后会讲到。
注意,除了两个主要的例外,这个语法的大部分非常接近 Python。首先,Scala 是一种类型化语言。变量实际上不需要显式类型化,但是函数参数需要。第二,您将看到一行类似于:
data.drop(removeList: _*)
这意味着从数据 DataFrame 中删除removeList
中的所有内容。_*
是一个通配符类型定义,只是一些必要的语法,告诉 Scala 编译器如何完成工作。
在 Spark ML 中使用 VectorAssembler
现在,我们希望将数据分为训练集和测试集。
import org.apache.spark.ml.feature.VectorAssemblerdef train_test_split(data: DataFrame) = {
val assembler = new VectorAssembler().
setInputCols(data.drop("lastsoldprice").columns).
setOutputCol("features")
val Array(train, test) = data.randomSplit(Array(0.8, 0.2), seed = 30) (assembler.transform(train), assembler.transform(test))
}val (train, test) = train_test_split(housing_dropgeo)
这有点棘手,需要一些解释。
在 scitkit-learn 中,你可以获取整个熊猫数据帧,并将其发送给机器学习算法进行训练。Spark ML 也有一个数据帧结构,但模型训练总体上有点挑剔。您必须通过提取每行值并将它们打包到一个向量中,将您想要训练的每一列中的所有要素打包到一个列中。这意味着 Spark ML 只训练一列数据,而这恰好是一个实际包含多列数据的数据结构。一旦你有了代码(见上),设置起来并不复杂,但这是你必须意识到的一个额外的步骤。
使用 VectorAssembler 创建这些向量列之一。我们创建 VectorAssembler,表示我们想要使用所有的特征列(除了我们的标签/目标列,lastsoldprice
),然后给新的向量列命名,通常是features
。然后,我们使用这个新的组装器来转换两个数据帧,即测试和训练数据集,然后将每个转换后的数据帧作为一个元组返回。
现在,我们可以做一些机器学习。先说线性回归。
import org.apache.spark.ml.regression.LinearRegression
import org.apache.spark.ml.evaluation.RegressionEvaluatorval lr = new LinearRegression()
.setLabelCol("lastsoldprice")
.setFeaturesCol("features")val lrModel = lr.fit(train)
val predictions = lrModel.transform(test)val rmse = new RegressionEvaluator()
.setLabelCol("lastsoldprice")
.setPredictionCol("prediction")
.setMetricName("rmse")val r2 = new RegressionEvaluator()
.setLabelCol("lastsoldprice")
.setPredictionCol("prediction")
.setMetricName("r2")println("Root Mean Squared Error (RMSE) on test data = " + rmse.evaluate(predictions))
println("R^2 on test data = " + r2.evaluate(predictions))
我们的第一个预测
这应该是不言自明的。下面是上面代码的输出。
Root Mean Squared Error (RMSE) on test data = 857356.2890199891
R^2 on test data = 0.31933500943383086
这不太好,但这不是重点。这里真正的优势是我们现在有了一种格式的数据,我们可以使用 Spark ML,所以从这里开始尝试其他算法是很容易的一步。但是首先,我们将在一个函数中重新创建上述内容,我们可以使用不同的算法调用这个函数。在此过程中,我们将添加一个交叉验证选项,以便我们可以测试多个不同的超参数,并选择最佳结果模型。请注意,这一步并不是绝对必要的——前面的代码可以很容易地被重构以使用不同的算法——但这是一个更好的实践。
import org.apache.spark.ml.Predictor
import org.apache.spark.ml.PredictionModel
import org.apache.spark.ml.linalg.Vector
import org.apache.spark.ml.tuning.{CrossValidator, ParamGridBuilder}
import org.apache.spark.ml.param.ParamMapdef train_eval[R <: Predictor[Vector, R, M],
M <: PredictionModel[Vector, M]](
predictor: Predictor[Vector, R, M],
paramMap: Array[ParamMap],
train: DataFrame,
test: DataFrame) = {val cv = new CrossValidator()
.setEstimator( predictor
.setLabelCol("lastsoldprice")
.setFeaturesCol("features"))
.setEvaluator(new RegressionEvaluator()
.setLabelCol("lastsoldprice")
.setPredictionCol("prediction")
.setMetricName("rmse"))
.setEstimatorParamMaps(paramMap)
.setNumFolds(5)
.setParallelism(2) val cvModel = cv.fit(train)
val predictions = cvModel.transform(test)
println("Root Mean Squared Error (RMSE) on test data = " + rmse.evaluate(predictions))
println("R^2 on test data = " + r2.evaluate(predictions)) val bestModel = cvModel.bestModel
println(bestModel.extractParamMap)
bestModel
}
大部分内容应该是不言自明的— 除了函数定义,它实际上是难以理解的。这是这一部分:
def train_eval[R <: Predictor[Vector, R, M],
M <: PredictionModel[Vector, M]](
predictor: Predictor[Vector, R, M],
paramMap: Array[ParamMap],
train: DataFrame,
test: DataFrame) = {
不幸的是,Spark ML 似乎没有一个通用的“模型”类型,例如,我们可以传入一个 RegressionModel 对象,然后我们的函数可以接受这个“模型”对象并调用.fit
方法。这将使我们避免这种混乱。相反,我们必须提出这个复杂的定义,这样我们就可以创建一个接受通用“模型”类型的方法,因为该类型也依赖于输入格式和隐式赋值器类型。想出这种定义是相当棘手的——在环顾四周和反复试验之后,我发现直接从 Spark ML 源代码中提取它就可以了。
好消息是,一旦你写了这样的东西,呼叫者不需要真正了解或理解它(老实说,他们不太可能会了解)。相反,这种复杂类型定义允许调用者编写真正干净的代码,如下所示:
val lr = new LinearRegression()val lrParamMap = new ParamGridBuilder()
.addGrid(lr.regParam, Array(10, 1, 0.1, 0.01, 0.001))
.addGrid(lr.elasticNetParam, Array(0.0, 0.5, 1.0))
.addGrid(lr.maxIter, Array(10000, 250000))
.build()train_eval(lr, lrParamMap, train, test)
现在我们回到一些简单的东西:一个算法(线性回归)和一个交叉验证的参数网格。然后函数调用变得像我们在 Python 中看到的一样简单。这实际上是相同的代码。注意,我甚至为train_eval
和其他变量保留了嵌入式下划线语法。在 Scala 和 Java 中,我们通常会使用 camel case,即trainEval
,这也是我在编写产品代码时会做的事情,但是由于本教程最初是用 Python 编写的,所以为了比较,保持一些一致性是值得的。
我们现在来看看其他一些算法,看看它们是如何工作的。注意 Lasso 和 Ridge 没有显式类,因为elasticNetParam
分别设置为 1 和 0 时指定这两种算法。
决策树:
import org.apache.spark.ml.regression.DecisionTreeRegressorval decisionTree = new DecisionTreeRegressor()
val dtParamMap = new ParamGridBuilder().build()
train_eval(decisionTree, dtParamMap, train, test)
结果:
Root Mean Squared Error (RMSE) on test data = 759685.8395738212
R^2 on test data = 0.46558480196241925
随机森林:
import org.apache.spark.ml.regression.RandomForestRegressorval randomForest = new RandomForestRegressor()val rfParamMap = new ParamGridBuilder()
.addGrid(randomForest.maxBins, Array(4, 16, 32, 64))
.addGrid(randomForest.numTrees, Array(1, 10, 100))
.addGrid(randomForest.maxDepth, Array(2, 5, 10))
.build()train_eval(randomForest, rfParamMap, train, test)
结果:
Root Mean Squared Error (RMSE) on test data = 647133.830611256
R^2 on test data = 0.6122079099308858
梯度增强:
import org.apache.spark.ml.regression.GBTRegressorval gradientBoost = new GBTRegressor()val gbParamMap = new ParamGridBuilder()
.addGrid(randomForest.maxBins, Array(16, 32))
.addGrid(randomForest.numTrees, Array(5, 10, 100))
.addGrid(randomForest.maxDepth, Array(5, 10))
.addGrid(randomForest.minInfoGain, Array(0.0, 0.1, 0.5))
.build()train_eval(gradientBoost, gbParamMap, train, test)
结果:
Root Mean Squared Error (RMSE) on test data = 703037.6456894034
R^2 on test data = 0.5423137139558296
虽然确切的结果不同(特别是对于线性回归),但我们也看到了随机森林和梯度增强比更简单的算法工作得更好的类似趋势。同样,我们可以通过使用更好的数据来改进我们的结果。我们通过重新整合neighborhood
数据来做到这一点,但采用算法可以使用的数字格式。我们通过使用 one-hot 编码将像Mission
和South Beach
这样的类别更改为 1 和 0 的列来实现这一点。
一键编码
首先,我们用这些数据重建数据框架:
val housing_neighborhood = drop_geog(housing_dateint, List("neighborhood"))
然后,我们使用一个Pipeline
通过一键编码来转换数据:
import org.apache.spark.ml.Pipeline
import org.apache.spark.ml.feature.OneHotEncoderEstimator
import org.apache.spark.ml.feature.StringIndexerval indexer = new StringIndexer().setInputCol("neighborhood").setOutputCol("neighborhoodIndex")val encoder = new OneHotEncoderEstimator()
.setInputCols(Array(indexer.getOutputCol))
.setOutputCols(Array("neighborhoodVector"))val pipeline = new Pipeline().setStages(Array(indexer, encoder))val housingEncoded = pipeline.fit(housing_neighborhood).transform(housing_neighborhood)
.drop("neighborhoodIndex")
.drop("neighborhood")
首先,我们必须使用一个StringIndexer
,然后我们可以使用OneHotEncoderEstimator
得到我们想要的结果。因为这是两个步骤,我们可以使用阶段的Pipeline
将它们放在一起。管道可以用于许多多阶段的清理和修改操作,特别是当你需要一遍又一遍地做这些相同的阶段时,例如需要重新训练的不断发展的数据集。这在这里并不是真正必要的,但它值得展示,因为它非常有用。
更新数据后,我们可以像以前一样重新进行实验。我们只是传递我们的新数据(在创建训练和测试集之后):
val (train_neighborhood, test_neighborhood) = train_test_split(housingEncoded)
例如,对于线性回归,我们使用这些新变量调用完全相同的函数:
train_eval(lr, lrParamMap, train_neighborhood, test_neighborhood)
结果:
Root Mean Squared Error (RMSE) on test data = 754869.9632285038
R^2 on test data = 0.4723389619596349
这仍然不是很好,但比以前好多了。现在,让我们看看在传递转换后的数据帧后其他算法的结果。
决策树:
Root Mean Squared Error (RMSE) on test data = 722171.2606321493
R^2 on test data = 0.5170622654844328
随机森林:
Root Mean Squared Error (RMSE) on test data = 581188.983582857
R^2 on test data = 0.6872153115815951
梯度增强:
Root Mean Squared Error (RMSE) on test data = 636055.9695573623
R^2 on test data = 0.6253709908240936
在每种情况下,我们都看到了相当大的改进,现在我们有了一个模型和一个训练管道,可以用更大的数据集投入生产。
为 Connect4 从头开始实施 AlphaZero
一步一步的演示如何在游戏中使用 PyTorch 和标准 python 库实现 alpha zero
Demis Hassabis, the head of Google DeepMind. Credit: https://www.telegraph.co.uk/science/2017/12/06/entire-human-chess-knowledge-learned-surpassed-deepminds-alphazero
2016 年,谷歌 DeepMind 的计算机程序 AlphaGo 在一场有数百万人观看的比赛中以 4 比 1 击败了围棋世界冠军 Lee Sedol,这一壮举在此前一直由人类主导的超复杂围棋比赛中从未被任何计算机程序实现过。然而,在大约一年后的 2017 年由 DeepMind 出版的alpha go Zero,通过在没有任何人类数据输入的情况下实现类似的壮举,将边界向前推进了一大步。(AlphaGo 参考围棋特级大师游戏进行初始训练)同一组随后发布的一篇论文成功地将相同的强化学习+监督学习框架应用于国际象棋,仅经过 4 个小时的训练就超过了之前最好的国际象棋程序 Stockfish。
出于对这种强化学习模型的敬畏,我想了解它是如何获得一些见解的,没有什么比尝试从零开始构建自己的国际象棋人工智能程序更好的了,严格遵循上述论文中描述的方法。然而,事情很快变得过于昂贵,难以承受,因为即使程序已经启动并运行,训练它达到合理的技能水平很可能需要数百万的 GPU 和 TPU 成本。
由于无法与谷歌的雄厚财力相比,我决定尝试在 Connect4 上实现 AlphaZero,这是一种比国际象棋简单得多的游戏,对计算能力的要求也更低。这里的重点是证明 AlphaZero 算法最终可以很好地创建一个强大的 Connect4 AI 程序。这里描述的方法的实现脚本都可以在我的 Github repo 上找到。
连接 4 板
首先,我们需要用 Python 创建 Connect4 板供我们使用。我创建了一个名为“board”的类,有 4 个方法“init”、“drop_piece”、“check_winner”、“actions”。
Connect4 board in Python
- "init "构造函数将一个 6 行 7 列的空 Connect4 板初始化为 np.array,存储板的状态以及当前要玩的玩家
2)“drop _ piece”在每个玩家玩游戏时用“X”或“O”更新棋盘
3)“check _ winner”如果有人在当前棋盘状态中获胜,则返回 True
4)“动作”返回给定当前棋盘状态下可以下的所有可能的棋步,因此不会下非法的棋步
大局
AlphaZero 中有 3 个关键组件,稍后我将更详细地描述它们的实现。它们是:
1)深度卷积残差神经网络
输入:连接 4 板状态
输出:策略(可能移动的概率分布),值(O 胜:+1,X 胜:-1,平局:0)
2)蒙特卡罗树搜索(MCTS)
在迭代过程中,由来自神经网络的策略指导的自我游戏生成游戏数据集以训练神经网络
3)评估神经网络
玩家 vs 玩家,各自分别由当前网和先前网引导,保留赢得下一轮比赛的网
深度卷积残差神经网络
Neural network architecture of AlphaZero used here
我们使用具有类似于 AlphaZero 的上述架构的深度卷积残差神经网络(使用 PyTorch)来将输入 Connect4 板状态映射到其相关联的策略和值。策略本质上是玩家应该从当前棋盘状态(策略)移动的下一步棋的概率分布,值代表当前玩家从该棋盘状态中获胜的概率。**这个神经网络是 MCTS 的一个组成部分,它通过其策略和值输出来帮助指导树搜索,我们将在后面看到。**我们使用一个初始卷积块,接着是 19 个残差块,最后是一个输出块来构建这个神经网络(我称之为 ConnectNet ),如下所述。
卷积块
残留块
输出块
放在一起
在输入到神经网络之前,原始的 Connect4 板被编码成 6×7×3 的 1 和 0 的矩阵,其中 6×7 的板尺寸中的每一个的 3 个通道分别编码“X”、“O”(1 存在,0 为空)和要移动的玩家(0 为“O”,1 为“X”)。
Encoder to encode Connect4 board for neural net input
最后,为了正确地训练这个具有双头输出的神经网络,自定义损失函数(AlphaLoss)被定义为简单的均方误差值和交叉熵策略损失之和。
Neural Net loss function implemented via PyTorch
蒙特卡罗树搜索
一个游戏可以被描述为一棵树,树根是棋盘状态,树枝是所有可能的棋盘状态。在像围棋这样的游戏中,随着游戏的进行,分支的数量呈指数增长,简单地用蛮力评估所有分支实际上是不可能的。因此,蒙特卡罗树搜索(MCTS)算法被设计成以更智能和更有效的方式进行搜索。从本质上讲,人们希望优化探索-开发的权衡,人们希望进行足够彻底的搜索(探索)以发现可能的最佳回报(开发)。这在定义置信上限(UCB)的 MCTS 算法中的一个等式中被简洁地描述:
这里, Q 是平均行动值(平均报酬), cpuct 是确定探索水平的常数(设为 1),*P(s =状态,a =行动)*是神经网络的策略输出给出的选择行动 a 的先验概率, N(s,a) 是行动 a 所对应的分支被访问的次数。来自状态 s 的所有被探索分支(动作)的分子 sum 中的 N sum over b 本质上是 (s,a) 的父级被访问的次数。
MCTS 算法按以下步骤进行。
- 挑选
Select — AlphaGo Zero
Recursively selects the nodes based on highest UCB (best move) until leaf node or terminal node is reached. Adds node of best move if its not yet created.
从 s 开始,搜索选择具有最高 UCB 的下一个分支,直到到达叶节点(其分支都没有被探索的状态)或终端节点(结束游戏状态)。我们可以看到,如果奖励 Q 高,那么就更有可能选择那个分支。第二个探索项也起了很大的作用,其中我们看到如果动作 a 只被访问了几次,那么这个项将会很大,并且算法更有可能选择相关的分支。神经网络通过提供先验概率 P 来指导选择,当神经网络未被训练时,先验概率最初将是随机的。
2.展开并评估
Expand and Evaluate — AlphaGo Zero
Expand only nodes that result from legal moves, mask illegal moves and add Dirichlet noise to prior probabilities of root node.
这里,通过用神经网络评估与扩展节点相关联的状态来扩展叶节点,以获得并存储 P 。当然,非法移动不应该扩大,将被掩盖(通过设置先验概率为零)。如果该节点是根节点,我们还将在这里添加狄利克雷噪声,以向探索提供随机性,使得每个 MCTS 模拟都可能不同。
3.支持
Backup — AlphaGo Zero
Recursively update the visits counts and values of nodes once leaf node is evaluated.
现在,神经网络对叶节点进行评估,以确定其值 v 。这个值 v 然后被用于更新它上面的所有父节点的平均值 v 。更新应该是这样的,即 O 和 X 将发挥到最好(最小最大),例如,如果 O 赢了(对叶节点评估的 v = +1),则在该叶节点的直接父节点中,将轮到 O 出牌,并且我们将为该父节点更新 v = +1,然后为所有其他父节点更新 v = -1,其中 X 将出牌,以表示该动作对 X 不利。最后,在平局的情况下,更新 v = 0。
Code snippet for each simulation of Select, Expand and Evaluate, and Backup. num_reads here is the parameter controlling the number of simulations.
上述选择、扩展、评估和备份的过程代表了 MCTS 算法的每个根节点的一个搜索路径或模拟。在 AlphaGo Zero 中,进行了 1600 次这样的模拟。对于我们的 Connect4 实现,我们只运行 777,因为它是一个简单得多的游戏。在对该根节点运行 777 次模拟之后,我们将为根节点制定策略 p ,该策略被定义为与其直接子节点的访问次数成比例。这个策略 p 然后将被用于选择下一个移动到下一个棋盘状态,并且这个棋盘状态然后将被视为下一个 MCTS 模拟的根节点,以此类推,直到当有人赢或平局时游戏终止。对每个根节点运行 MCTS 模拟直到游戏结束的整个过程被称为 MCTS 自玩。
Function to execute MCTS self-play
在运行 MCTS 模拟的 MCTS 自玩游戏的每个步骤中,我们将有一个棋盘状态 s ,它的关联策略 p ,以及值 v ,因此当 MCTS 自玩游戏结束时,我们将有一组( s,p,v )值。然后,这组( s,p,v )值将用于训练神经网络,以改进其策略和值预测,然后,这个训练的神经网络将用于迭代地指导随后的 MCTS。通过这种方式,人们可以看到,最终在许多许多次迭代之后,神经网络和 MCTS 一起将非常善于生成最优移动。
评估神经网络
在一次迭代之后,其中使用 MCTS 自播放数据训练神经网络,然后再次使用由相应神经网络引导的 MCTS,将该训练的神经网络与其先前版本进行比较。表现更好的神经网络(例如赢得大多数游戏)将用于下一次迭代。这确保了网络总是在改进。
迭代流水线
总之,一个完整的迭代管道包括:
1.自我游戏使用 MCTS 生成游戏数据集( s 、 p 、 v ),神经网络通过提供选择动作的先验概率来指导搜索
2.用 MCTS 自弹自唱产生的( s 、 p 、 v )数据集训练神经网络
3.通过将经过训练的神经网络与来自前一次迭代的神经网络进行比较来评估经过训练的神经网络(在预定义的历元检查点),再次使用由相应神经网络引导的 MCTS,并且仅保留表现更好的神经网络。
4.冲洗并重复
结果
迭代 0:
alpha_net_0(用随机权重初始化)
151 游戏 MCTS 自玩生成
迭代 1:
alpha_net_1(从迭代 0 开始训练)
148 游戏 MCTS 自玩生成
迭代 2:
alpha_net_2(从迭代 1 开始训练)
310 游戏的 MCTS 自我发挥产生
评估 1:
阿尔法 _ 网络 _2 与阿尔法 _ 网络 _0 竞争
在 100 场比赛中,alpha_net_2 赢了 83 场,输了 17 场
迭代 3:
alpha_net_3(从迭代 2 开始训练)
584 游戏 MCTS 自玩生成
迭代 4:
alpha_net_4(从迭代 3 开始训练)
753 游戏 MCTS 自玩生成
迭代 5:
alpha_net_5(从迭代 4 开始训练)
1286 年 MCTS 自弹自唱游戏产生
迭代 6:
alpha_net_6(从迭代 5 开始训练)
1670 年 MCTS 自弹自唱游戏产生
评价 2:
阿尔法 _ 网络 _6 与阿尔法 _ 网络 _3 竞争
在 100 场比赛中,alpha_net_6 赢了 92 场,输了 8 场。
Typical Loss vs Epoch for neural net training at each iteration.
在 Google Colab 上几周的零星训练期间,总共生成了 4902 个 MCTS 自玩游戏的总共 6 次迭代。上面显示了每次迭代的神经网络训练的典型损失对时期,表明训练进行得相当好。从迭代中选定点处的评估 1 和 2 中,我们可以看到神经网络确实总是在改进,并且在生成获胜移动方面变得比其先前版本更强。
现在可能是展示一些真实游戏的时候了!下面的 gif 展示了 alpha_net_6(以 X 的身份玩)和 alpha_net_3(以 O 的身份玩)之间的一个示例游戏,其中 X 赢了。
此时此刻,我还在训练网/MCTS 自弹自唱。我希望能够达到一个阶段,使 MCTS +网络能够产生完美的移动(连接 4 是一个解决的游戏,这样首先移动的玩家总是可以迫使获胜),但谁知道这将需要多少次迭代…
反正都是乡亲们!希望你会觉得这篇文章有趣和有用。非常欢迎对实现和改进提出任何意见。要进一步阅读 AlphaZero 如何工作的更多细节,没有什么比阅读 DeepMind 的实际论文更好的了,我强烈推荐!
要了解最新的人工智能/数据科学趋势、论文和新闻,请查看我的@ follow AI _ bot(https://t.me/followai_bot),这是您的个性化人工智能/数据科学电报机器人。