我们的在线课程(全部免费,没有广告):

我们的软件:fastai v1代表火炬

亲自参加我们的课程,2019年3月-4月,平方英尺:此处注册

manbetx登陆fast.ai新闻:


2019年编码员实践深度学习

今天启动,2019年版编码员的实用深度学习,课程的第三次迭代,是100%的新材料,包括以前从未被深度学习入门课程覆盖的应用程序(包括一些甚至尚未在学术论文中发表的技术)。有七个教训,每2小时左右,你应该计划每节课花大约10个小时做作业。manbetx官网手机登录谷歌云微软Azure已将课程所需的全部内容集成到其基于GPU的平台中,还有“一键式”平台,如新月形梯度.

本课程假设您至少有一年的编码经验(最好是在python中,虽然有经验的程序员将能够在他们前进的过程中学习Python;我们有一份清单python学习资源可用)高中数学(课程中会根据需要引入一些大学水平的数学)。许多完成课程的人告诉我们这需要很多工作,但这是他们所做的最有价值的事情之一;我们强烈建议你参加这门课程活跃的在线社区帮助你完成你的旅程。

在第一课之后,您将能够根据自己的数据培训最先进的图像分类模型。在完成这一课之后,一些学生从这门课程的亲自版本(在那里这些材料被记录)在不同的领域发表了新的最先进的结果!课程前半部分的重点是实用技术,只显示了理论需要在实践中实际使用这些技术。然后,在下半场,我们不断深入地研究这个理论,在最后一堂课之前,我们将从头开始构建和训练一个接近最先进精确度的“resnet”神经网络。

课程中的一些应用实例
课程中的一些应用实例

主要应用包括:

  • 计算机视觉(例如按品种分类宠物照片)
    • 图像分类
    • 图像定位(分割和激活图)
    • 图像关键点
  • NLP(例如电影评论情感分析)
    • 语言建模
    • 文档分类
  • 表格数据(例如销售预测)
    • 分类数据
    • 连续的数据
  • 协同过滤(例如电影推荐)

我们还将介绍这些应用程序的所有必要基础。

课程中覆盖的基础
课程中覆盖的基础

我们使用PyTorch图书馆,这是最现代化、最灵活、使用最广泛的图书馆,我们也会用fastai割炬包装,这样就可以更容易地访问用于培训深度学习模型的推荐最佳实践(同时也可以直接使用所有底层PyTorch功能)。我们认为法赛很棒,但我们有偏见,因为我们做到了……但这是pytorch.org上唯一一个通用的深度学习工具包,拥有超过10000颗Github星,并用于许多比赛的胜利,学术论文,以及顶尖的大学课程,所以不仅仅是我们这样!请注意,您所学的概念将同样适用于您想要使用Tensorflow/keras进行的任何工作,CNTKMXnet公司,或任何其他深度学习图书馆;重要的是概念。如果你能很好地理解新图书馆的概念,学习新图书馆只需要几天时间。

今年一个特别有用的补充是我们现在有一个超级充电视频播放器,的伟大工作扎克·卡塞雷斯.它允许你搜索课本,直接跳到你找到的视频部分。它还显示了与其他课程的链接,课程总结和资源,在可折叠的窗格中(但是它在移动设备上还不能很好地工作,所以如果你想在手机上观看,你可以使用此YouTube播放列表)还要特别感谢西尔文·古格,他在这门课程和fastai图书馆的发展中都发挥了重要作用——我们非常感谢亚马逊网络服务公司赞助Sylvain的工作。

manbetx登陆快速。人工智能的视频播放器和可搜索的时间线
manbetx登陆快速。人工智能的视频播放器和可搜索的时间线

如果你想尝试一下,点击这里去课程网站。现在让我们更详细地看一下每节课。

第一课:图像分类

第一课最重要的结果是,我们将训练一个图像分类器,它可以识别宠物品种在最先进的准确性。成功的关键在于转移学习,这将是本课程的一个基本平台。我们还将了解如何分析模型以了解其故障模式。在这种情况下,我们会发现模型出错的地方和育种专家出错的地方是一样的。

宠物品种分类器的训练与分析
宠物品种分类器的训练与分析

我们将讨论这门课的总体方法,有点不寻常自上而下而不是自下而上.所以与其从理论开始,以后才开始实际应用,我们从实际应用开始,然后逐渐深入挖掘,根据需要学习理论。这种方法需要教师付出更多的努力来发展,但它被证明对学生有很大帮助,例如在哈佛大学的教育研究大卫·帕金斯。

我们还讨论了如何设置最重要的hyper-parameter神经网络训练时:学习率,使用莱斯利·史密斯的精彩学习速率仪方法。最后,我们将讨论以下重要但很少讨论的主题:标记,并了解Fastai提manbetx官网手机登录供的一些功能,使您可以轻松地将标签添加到图像中。

请注意,随着课程的进行,您需要连接到安装了Fastai库的云GPU提供商(推荐;只需5分钟左右,成本低于0.50美元/小时)或者自己安装一台带有合适GPU的计算机(如果您不熟悉该过程,可能需要几天时间才能开始工作,所以我们以后才推荐。您还需要熟悉Jupyter笔记本我们用来进行深度学习实验的环境。有关这些内容的最新教程和建议可从课程网站.

教训2:数据清理和生产;SGD从头开始

我们从学习如何使用自己的数据建立自己的图像分类模型开始今天的课程,包括以下主题:

  • 图像采集
  • 并行下载
  • 创建验证集,和
  • 数据清理,使用模型来帮助我们发现数据问题。

在创建一个模型时,我将演示所有这些步骤,该模型可以承担区分泰迪熊和灰熊的重要任务。一旦我们把数据整理好了,然后我们将学习如何生产我们的泰迪探测器,并在网上提供。

将您的模型投入生产
将您的模型投入生产

自从这节课被记录下来后,我们有了一些很好的补充,所以一定要检查:

  • 这个生产配套在课程网站上,如这一个用于部署到Render.com
  • 课程笔记本中的新的交互式GUI,用于使用模型查找和修复贴错标签或收集错误的图像。

在本课的下半部分,我们将从头开始训练一个简单的模型,创造我们自己的梯度下降法循环。在这个过程中,我们会学到很多新的行话,所以要确保你有个好地方做笔记,因为我们会在整个课程中提到这个新术语(从现在开始每节课都会有更多的介绍)。

梯度下降作用
梯度下降作用

第3课:数据块;多标记分类;分割

今天要报道的内容很多!我们从第三课开始看一个有趣的数据集:行星的从太空了解亚马逊.为了使这些数据成为我们建模所需的形状,我们将使用fastai最强大(也最独特)的工具之一数据块的API.在接下来的课程中,我们将多次回到这个API,掌握它会让你成为一个真正的法赛超级明星!一旦你完成了这节课,如果您准备了解更多关于数据块API的信息,manbetx官网手机登录看看这篇伟大的文章:寻找数据块的天堂,Wayde Gilliam。

行星数据集的一个重要特征是多标记数据集。即:每个卫星图像可以包含倍数标签,而我们之前看到的数据集每个图像只有一个标签。我们将了解在使用多标签数据集时需要进行哪些更改。

我们的图像分割模型的结果
我们的图像分割模型的结果

下一步,我们来看看图像分割,这是用一个类别标记图像中的每个像素的过程,该类别显示该像素所描绘的对象的类型。我们将使用与早期图像分类模型相似的技术,稍作调整。Fastai使图像分割建模和解释与图像分类一样简单,所以不需要太多的调整。

我们将在本课的这一部分中使用流行的camvid数据集。在以后的课程中,我们还会回来,展示一些额外的技巧。我们最终的camvid模型的误差将大大低于我们在学术文献中所能找到的任何模型!

如果你的因变量是一个连续的值,而不是一个类别?接下来我们回答这个问题,看一看关键点数据集,建立了一个精确预测人脸关键点的模型。

第四课:NLP;表格数据;协同过滤;嵌入

我们将在第四课深入学习自然语言处理(NLP)使用IMDb电影评论数据集。在这个任务中,我们的目标是预测电影评论是正面的还是负面的;这叫做情绪分析.我们将使用ULMFiT算法,最初是在fast.ai 2018课程中开发的,manbetx登陆并在2018年成为了NLP革命的一部分这使得《纽约时报》宣布新系统开始破解自然语言的密码.ULMFiT是目前已知最准确的情绪分析算法。

概述ULMFiT
概述ULMFiT

基本步骤如下:

  1. 创建(或)优选的,下载一个pre-trained)语言模型在大型语料库(如维基百科)上进行训练(“语言模型”是学习预测句子下一个单词的任何模型)
  2. 使用您的目标语料库(在这种情况下,IMDB电影评论)
  3. 删除编码器在这个微调语言模型中,代入a分类器.然后为最终的分类任务(在本例中,情绪分析)。

在我们进入NLP之后,我们将通过覆盖表格数据(如电子表格和数据库表)来完成我们的实际应用程序,以便对编码人员进行实际的深入学习。和协同过滤(推荐系统)。

表格数据,我们看看怎么用绝对的连续的变量,以及如何使用板状的模块建立和训练一个模型。

然后我们将看到如何使用与表格数据类似的思想来构建协作过滤模型,但通过一些特殊的技巧来获得更高的准确性和更丰富的模型解释。

这就把我们带到了课程的中途,我们研究了如何在这些关键应用领域中构建和解释模型:

  • 计算机视觉
  • 自然语言处理
  • 表格
  • 协同过滤

在课程的后半段,我们将学习manbetx官网手机登录怎样这些模型确实有效,以及如何从头开始创造它们。对于本课,我们将把迄今为止所接触到的一些关键部分放在一起:

  • 激活
  • 参数
  • 层(仿射和非线性)
  • 损失函数。

在剩下的课程中,我们将详细介绍其中的每一个。我们还会学习一种对NLP很重要的层manbetx官网手机登录,协同过滤,和表格模型嵌入层.我们会发现,“嵌入”只是特定类型矩阵乘法的计算快捷方式(通过在一个炎热的编码矩阵)。

第5课:反向传播;加速SGD;从头开始的神经网络

在第5课中,我们把所有的训练内容放在一起,以准确地理解我们谈论的内容manbetx官网手机登录反向传播.我们将使用这些知识从头开始创建和训练一个简单的神经网络。

从头开始的神经网络
从头开始的神经网络

我们还将看到如何查看嵌入层的权重,找出我们的模型对分类变量的理解。manbetx官网手机登录这将让我们了解到哪些电影我们应该不惜一切代价避免……

解释电影评论的嵌入
解释电影评论的嵌入

尽管嵌入在单词embeddings for nlp的上下文中最广为人知,一般来说,它们至少对分类变量同样重要,如表格数据或协同过滤。它们甚至可以成功地用于非神经模型。

普通模型与不嵌入模型的性能比较
普通模型与不嵌入模型的性能比较

第6课:正规化;旋转;数据伦理学

今天,我们将讨论一些改进培训和避免过度装配的强大技术:

  • 辍学:在培训过程中随机删除激活,以规范模型
  • 数据扩充:在培训期间修改模型输入,以有效地增加数据大小
  • 批处理规范化:调整模型的参数化以使损失曲面更平滑。
单个图像的数据扩充示例
单个图像的数据扩充示例

接下来,我们会学到很多manbetx官网手机登录卷积,它可以被看作是矩阵乘法的一个变种,有着相等的权。是现代计算机视觉模型的核心操作(以及,越来越多地,还有其他类型的模型)。

我们将使用这些知识来创建a类激活映射,这是一幅热图,它显示了图像的哪些部分在预测中是最重要的。

卷积的工作原理
卷积的工作原理

最后,我们将讨论一个许多学生告诉我们的主题,这是课程中最有趣和最令人惊讶的部分:数据伦理。我们将了解一些模型出错的manbetx官网手机登录方法,特别关注反馈回路,为什么会产生问题,以及如何避免它们。我们还将研究数据偏差导致偏差算法的方法,讨论数据科学家能够也应该提出的问题,以帮助确保他们的工作不会导致意外的负面结果。

美国司法系统中算法偏见的例子
美国司法系统中算法偏见的例子

第7课:从头开始重新整理;U-net;生成(对抗)网络

在程序员实践深度学习的最后一课中,我们将学习现代架构中最重要的技术之一跳过连接.这是最著名的在雷尼特,这是我们在整个课程中用于图像分类的体系结构,并出现在许多前沿成果中。我们还要看看U-net建筑学,它使用不同类型的跳过连接来大大提高分段结果(也适用于输出结构与输入类似的类似任务)。

对Resnet跳接损耗面的影响
对Resnet跳接损耗面的影响

然后我们将使用U-NET架构来训练超分辨率模型。这是一个可以提高低质量图像分辨率的模型。我们的模型不仅可以提高分辨率,还可以删除jpeg工件和不需要的文本水印。

为了使我们的模型产生高质量的结果,我们将需要创建一个包含自定义损失函数的函数特征损失(也称为知觉损失)随着克损.这些技术可用于许多其他类型的图像生成任务,如图像着色。

超分辨率结果使用特征损失和克损失
超分辨率结果使用特征损失和克损失

我们将学习最近的损失函数manbetx官网手机登录生成对抗损失(用于生成对抗性网络,或甘斯)在某些情况下可以提高生成模型的质量,以速度为代价。

我们在本课中展示的技术包括一些未发表的研究:

  • 让我们比标准方法更快、更可靠地培训GANs,通过利用转移学习
  • 结合了以前从未以这种方式使用过的架构创新和损失功能方法。

结果是惊人的,而且只需几个小时的训练(与之前的几天的训练相比)。

复发性神经网络
复发性神经网络

最后,我们将学习如何从头开始创建循环神经网络(RNN)。这是我们在整个课程中一直使用的NLP模型的基础。事实证明,它们只是普通多层网络的简单重构。

谢谢你的阅读!如果你走了这么远,那么你应该去course.manbetx登陆fast.ai开始看第一个视频!

C++ 11,随机分布,和迅速

概述

从随机分布中生成数字实际上是一个有用的工具,任何编码人员都可能在某个时刻需要它。C++ 11增加了一组丰富的随机分布生成能力。这使得使用随机分布变得简单快捷,不仅仅是你在用c++ 11,但是如果你使用任何让你与C++交互的语言。

在本文中,我们将了解随机分布对什么有用,它们是如何产生的,以及如何在C++ 11中使用它们。我还将展示如何通过将c++ 11的类包装成Swift类来为Swift创建新的随机分发功能。虽然Swift不直接支持c++,我将展示如何通过为c++类创建纯C包装器来解决这个问题。

随机分布,为什么它们很重要

如果名字像负二项泊松只是对很久以前学过的东西的回忆的影子,请给我一点时间来说服你,随机分布的世界是值得你花时间和关注的。

编码人员已经意识到了随机数的概念。但对许多人来说,我们的工具箱仅限于统一的实数和整数随机数,也许偶尔也会抛出一些高斯(正态)随机数。产生随机数的方法还有很多!事实上,您甚至可能发现自己在不知情的情况下重新创建了标准的随机分布……

例如,假设你在写音乐播放器,您的用户已经对从一颗星到五颗星的各种歌曲进行了评级。你想要实现一个洗牌播放功能,随机选择歌曲,但选择高评价歌曲的频率更高。你将如何着手实施?manbetx官网手机登录答案是:随机分布!更具体地说,你想从a中得到随机数离散分布;也就是说,生成一个随机整数,使用一组权重,其中较高权重的数字按比例选择得更频繁。

或者,在向系统添加更多资源之后,您可能正在尝试模拟预测的队列长度。你模拟这个过程,因为您不仅想知道平均队列长度,但是有多少次它会大于某个大小,95%的大小,等等。你不确定系统的一些输入是什么,但是你知道可能值的范围,你对你认为最有可能发生的事情有一个猜测。在这种情况下,你想从a中得到随机数三角形分布;也就是说,生成随机浮点,这通常很接近你的猜测,距离越远,线性概率越小,在可能值范围之外的概率为零。(这种模拟形成了概率规划)。

还有很多其他随机分布,包括:

  • 经验分布:从历史数据中随机选取一个数字
  • 负二项分布:指定失败次数之前的成功次数
  • 泊松分布:可用于对固定时间段内发生的固定频率的独立事件数进行建模。

如何生成随机分布

一般来说,从随机分布中生成数字的步骤如下:

  1. 为你的发电机播种
  2. 使用生成器生成下一串随机比特
  3. 将这些随机位转换为所选的分布
  4. 如果你需要更多的随机数,返回(2)

我们通常所说的“随机数生成”实际上是步骤(2):使用伪随机信号发生器它确定地生成一系列尽可能“随机”的数字(即彼此不相关,很好地展开,等等)。伪随机发生器是具有这些性质的函数,如梅森缠绕机.首先,你需要一些种子;也就是说,传递给生成器的第一个数字。大多数操作系统都有某种生成随机种子的方法,如/dev/random在Linux和Mac上,它使用环境输入(如设备驱动程序的噪声)来获得一个应该是真正随机的数字。

然后,在步骤3中,我们将伪随机生成器创建的随机位转换成具有我们需要的分布。有一些普遍适用的方法,如逆变换抽样,把一个统一的随机数转换成任何给定的分布。还有一些针对某个发行版的更快的方法,如Box-Muller变换它从均匀生成器中创建高斯(正态)随机数。

要创建更多随机数,你不需要回到/dev/random,因为现在已经设置了一个伪随机生成器。相反,您只需从生成器中获取下一个数字(步骤(2)),并将其传递给分布生成转换(步骤(3))。

如何在C++中工作

c++ 11包括,在 标准库头,上述每个步骤的功能。步骤(1)通过简单地创建a来实现随机装置(我不包括性病:本文中的前缀;你可以打字std:: random_device或添加使用命名空间标准到您的c++文件的顶部)。然后将其传递给所提供的各种伪随机生成器之一的构造函数,如MT19937标准,即梅森捻线发电机;这是第(2)步。然后使用适当的类构造一个随机分布对象,如discrete_distribution,传入该发行版所需的任何参数(例如对于discrete_distribution输入每个可能值的权重列表)。最后,调用该对象(它支持()运营商,这是一个函子,被称为可调用的传入您创建的伪随机生成器。这是一个完整的例子来自优秀的cppreference.com。

CP+PROCENCENE.COM中C++离散分布()的实例
CP+PROCENCENE.COM中C++离散分布()的实例

如果您认为c++代码必须冗长和复杂,这个例子可能会让你重新思考你的假设!正如你所看到的,每个步骤都很好地映射到前面部分描述的随机分布过程的概述。(顺便说一句:如果你有兴趣学习现代c++,CpPraceNe.com有一个非常精心设计的例子,用于C++标准库的每一个部分;这也许是学习如何在实际操作中有效地使用语言的最佳场所。您甚至可以编辑示例并在线运行它们!

C++ 11提供的分布是:

  • 整数的一代:均匀分布,binomial_distribution,负二项分布,几何分布,poisson_distribution
  • 真实一代:uniform_real_distribution,指数分布,伽马分布,威布尔分布,normal_distribution,lognormal_distribution,chi_squared_distribution,cauchy_distribution,Fisher_f_分布,学生分配
  • 布尔代:bernoulli_distribution

这是如何在斯威夫特工作的

尽管Swift4现在提供了一些基本的随机数支持,它仍然没有提供任何不均匀的分布。因此,我已经把所有的C++ 11随机分布都提供给SWIFT,作为我的巴实抹图书馆。有关我创建这个库的原因和方法的更多信息,看到带swift的高性能数字编程.我将展示一下我是如何构建这个包装器的,但首先让我们看看如何使用它。这是我们在c++中看到的同一个函数,转换为swift+basemath:

 加勒比海盗 = Int.discrete_distribution([四十, 10, 10, 四十])一万]
 计数 = 加勒比海盗.减少进入之内: [ ]) { 0美元[1美元, 默认的:0] +=  _
计数.排序的通过:<).前额 { 打印\0美元)生成\1美元)“时代”) _

如你所见,在swift中生成随机数可以使用basemath分解为:内部离散分布([40,10日,10日,40])[10000].我们可以比c++ 11更简洁地做到这一点,因为我们没有提供太多的选项和细节。BaseMath只是假设你想使用标准的播种方法,并使用MT19937标准梅森素数捻线机发电机。

BaseMath中的分布名称与C++ 11完全相同。您只需在每个名称前面加上希望生成的类型(两者都可以)Int英特32对于整数分布,或双重的浮动对于实际分配)。每个分布都有一个初始化它与C++ 11分发构造函数的名称和类型匹配。这将返回一个带有许多方法的Swift对象。C++ 11对象,如前所述,提供()函子)运算符,但不幸的是,该操作符不能在Swift中重载。因此,我们借用斯威夫特的下标给我们等价行为的特殊方法。唯一的区别是我们必须使用[]而不是().如果只使用空下标[]然后basemath将返回一个随机数;如果使用Int,如[万]然后BaseMath将返回一个数组。(There are also methods to generate buffer pointers and aligned storage.) Using下标一开始可能会觉得有点奇怪,而不是函数。但这是绕过斯威夫特限制的完美方法。我要称之为quasi-functor;也就是说,像函子一样的东西,但被称为使用[…].

用Swift包C++

为了使Swift可以使用c++ 11随机发行版,我需要做两件事:

  1. 在C++ API中封装C++类,因为Swift不能直接与c++交互
  2. 用Swift类包装C API

我们将依次研究每一步:

在C中包装C++类

C包装器代码在里面cBasMaMat.CPP.这个MT19937标准mersenne twister generator将被包装在一个名为Swift的类中兰根,包装这个类的C函数都有RandGen_前缀。下面是C包装器的代码(注意包装器可以在内部使用c++特性,只要头文件中的接口是纯C):

结构体 RandGenC:MT19937标准 { }; 
类型定义 结构体 RandGenC RandGenC
RandGenC* RandGen_create() {
  返回 RandGenC*)() MT19937标准随机装置()());
_
无效 RandGen_destroyRandGenC* v) {
  删除v);
_

我们包装的每个类的模式将类似于此。我们至少会有:

  1. A结构体这是从C++类派生出来的结构Randgen)以及一个typedef来允许我们直接使用这个名称。使用结构而不是空洞*我们可以直接调用c++中的方法,但可以隐藏模板和其他c++内部从我们的纯C头文件
  2. A_create函数,该函数构造此类的对象并返回指向该对象的指针,转换为我们的结构类型
  3. A_destroy删除该对象的函数

在我们的头,我们会列出每个函数,以及typedef。任何导入这个C API的东西,包括我们的Swift代码,实际上不知道struct包含什么,manbetx官网手机登录因此我们不能直接使用类型(因为header中没有提供它的大小和布局)。相反,我们将在使用它的代码中使用不透明指针。

这是用于分发的包装器的代码;看起来几乎一样:

结构体 均匀分布:均匀分布<int> { };
类型定义 结构体 均匀分布 均匀分布
均匀分布* uniform_int_distribution_int_createint ,int ) {
  返回 均匀分布*)() 均匀分布<int>,));
_
无效 统一情报分发销毁均匀分布* v) {
  删除v);
_
int uniform_int_distribution_int_call均匀分布* p, RandGenC* g) {
  返回 *p)()*g);
_

主要区别在于调用,调用函数来允许我们实际调用该方法。也,因为类型是模板化的,我们必须为希望支持的每个模板类型创建一组单独的包装器;上面给出了一个例子 .注意,该类型需要包含在每个函数的名称中,因为C不支持重载。

当然,这些看起来都很冗长,我们不想为每一次发行都亲手写下这些。所以我们没有!相反,我们使用gyb为我们创建它们的模板,以及自动生成头文件。时间允许,我们以后会更详细地讨论这个问题。但是现在,您可以检查模板的源代码.

用Swift包装C API

现在我们有了C API,我们可以在Swift中轻松地重新创建原始c++类,例如。:

公众的  兰根 {
  公众的  ptr:无用指示器吗?
  公众的 初始化() { ptr=RandGen_create() _
  deinit { RandGen_destroyptr) _
_

如你所见,我们简单地称之为_create功能在初始化,和_destroy在里面deinit.如前一节所讨论的,我们的C API用户对我们的结构内部一无所知,manbetx官网手机登录所以斯威夫特给了我们一个无用指示器.

我们为每个分发创建类似的包装器(它还定义下标,它会调用我们的调用,调用函数)加上使用适当的静态包装器扩展数值类型,例如。:

延伸 英特32 {
  公众的 静止的 函数 均匀分布γ Gy:兰根, γ :英特32, γ :英特32)
      > 均匀分布 {
    返回 均匀分布Gy, ,)
  _
_

线程安全生成器

必须构造并传入a兰根对象不方便,特别是当我们必须处理线程安全的复杂性时。C++库不是,一般来说,线程安全;这包括c++ 11随机生成器。所以我们必须小心,不要在线程之间共享一个RandGen对象。如前所述带swift的高性能数字编程文章,我们可以通过使用线程本地存储.我添加了这个属性兰根:

静止的 var 存储:兰根 {
  如果  R = 螺纹.现在的.threadDictionary[“RandGen”] AS? 兰根 { 返回 R _
  返回 螺纹.setToTLS兰根(), “RandGen”)
_

这允许使用向每个分发类添加以下版本,这样用户就不必考虑创建或使用manbetx官网手机登录兰根班级。

公众的 方便 初始化γ :英特32, γ :英特32) { 
  自己.初始化兰根.存储, ,)
_ 

使用协议和BaseMath的扩展

以上步骤提供了一次生成单个随机数的功能。为了生成集合,我们可以添加一个分布每个发行版都遵守的协议,扩展如下:

公众的 协议 分布:Nullary {
  下标()>元素 {得到_
  下标N号:Int)>[元素] {得到_
_
延伸 分布 {
  公众的 下标N号:Int)>[元素] {
    返回 [元素].填满自己, N号)
  _
_

如你所见,我们利用了basemath方法填满,它调用一个函数或准函数N号时间和回报基站器(在这种情况下,安数组)和每次通话的结果。

你可能想知道协议manbetx官网手机登录Nullary上面提到过。也许你已经听说过一元(具有一个参数的函数或运算符)二元的(两个参数),和三元);鲜为人知,但同样有用,就是这个词零元,它只是一个没有参数的函数或运算符。如前所述,Swift不支持重载()运营商,所以我们添加了一个Nullary协议使用下标:

公众的 协议 Nullary {
  关联类型 元素:SignedNumeric
  下标()>元素 {得到_
_

试试看!

如果你是C++或快速程序员,尝试一些随机分布—也许您甚至可以尝试创建一些模拟并进入概率编程的世界!或者如果你是一个敏捷的程序员,想在c++库中使用函数,尝试用一个惯用的Swift API来包装它,并将其作为Swift包提供给任何人使用。

高性能快速数字编程:探索与思考

在过去的几周里,我一直在为构建一些数值编程库而工作斯威夫特.但是等一下,Swift不正是iOS程序员用来构建应用程序的吗?再也没有了!如今,Swift在Linux和Mac上运行,并且可以用于web应用程序,命令行工具,几乎任何你能想到的东西。

使用Swift进行数值编程,比如训练机器学习模型,这不是一个很多人正在努力的领域。关于这个话题的信息很少。但是经过几周的研究和实验,我成功地创建了几个库,它们可以达到与仔细优化的矢量化C代码相同的速度,同时简洁易用。在本文中,我将带您经历这段旅程,并向您展示我学到的关于如何有效地使用Swift进行数字编程的知识。manbetx官网手机登录我将主要包括来自我的巴实抹图书馆,它为浮动双重的,以及针对不同集合的优化版本。(在这个过程中,我有很多话要说,正的和负的,manbetx官网手机登录关于Swift和其他语言;如果你是一个和你最喜欢的编程语言有着深厚情感联系的人,你不希望看到任何对它的批评,你可能想跳过这篇文章!)

在以后的文章中,我还将展示如何通过与Intel的C性能库交互来获得额外的速度和功能。

背景

通常在新年前后,我会尝试使用一种新的语言或框架。对我来说特别有效的一种方法是看看那些创造了我最喜欢的语言的人,书,现在图书馆也在这么做。这种方法使我成为Delphi的早期用户,Typescript以及C(安德斯·海斯伯格,在我用了他的涡轮帕斯卡之后),波尔(拉里·沃尔,我用过以后)jquery(约翰·雷西格,读完之后现代Javascript)和更多。当我了解到这一点克里斯拉特纳(他编写了很棒的LLVM)正在创建一个新的深度学习框架,名为斯威夫特对Tensorflow(我将简称为S4TF从这里)我决定去看看。

注意,S4TF是只不过是TensorFlow的一个无聊的快速包装!这是第一次认真努力我已经看到合并可微程序设计深入到一种广泛使用的语言的中心。我希望S4TF能为我们提供一种语言和框架,第一次,将可微程序设计视为编程界的一流公民,并允许我们做以下事情:

  • 用swift编写自定义GPU内核
  • 提供编译时检查命名张量轴名称和大小匹配
  • 区分任何任意代码,同时还自动提供向量化和融合的实现。

这些东西在S4TF中不可用,至少到目前为止(事实上,对于这个项目来说,现在还处于非常早期的阶段,几乎没有一个深度学习功能能够工作)。但我完全期待它们最终会发生,当这种情况发生时,我相信在swift中使用可区别编程在swift中会比在任何其他语言中都有更好的体验。

我很幸运在最近的一次会议上遇到了克里斯,当我告诉他我对S4TF感兴趣时,manbetx官网手机登录他很好心,主动提出帮助我和斯威夫特开始交往。我一直都发现我的工作比我的工作效率和幸福更重要。什么我在工作,这是另一个花时间在这个项目上的很好的理由。克里斯帮了大忙,他也非常好,所以谢谢,克里斯!

manbetx官网手机登录关于迅速

Swift是一种通用工具,的多范式,编译的程序设计语言。它是由Chris Lattner在苹果时开始的,并支持Objective-C(苹果设备编程的主要语言)中的许多概念。Chris向我描述这种语言为“语法糖”LLVM”,因为它与编译器框架中的许多思想密切相关。

我已经编码30年了,在那段时间里,他们使用了几十种语言(甚至有过。导致了一些.我一直希望,当我开始寻找一种新的语言时,会有一些思想打开新的思路去发现,斯威夫特绝对不会让人失望。斯威夫特试图表达,灵活的,简洁,安全的,易于使用,而且速度快。大多数语言在这些领域中至少有一个领域会有明显的妥协。这是我个人对一些我使用过并喜欢的语言的看法,但所有这些都有局限性,我有时会感到沮丧:

  • Python:运行速度慢,不支持并行处理(但非常容易使用)
  • C,c++:难以使用(c++在编译时很慢),但快速和(C++)表达
  • javascript:不安全(除非使用typescript);有点慢(但是容易使用和灵活)
  • 朱莉娅:对通用编程的支持很差,但对于数字编程来说,速度和表现力都很快。(编辑:这对茱莉亚来说可能有点不公平;自从我上次看它以来,它已经有了很大的进步!)
  • Java:冗长(但越来越好)尤其是如果你使用Kotlin,灵活性较低(由于JVM问题)有点慢(但总的来说,这是一种有很多有用应用领域的语言)
  • C和F:可能对任何主要编程语言的影响最小,但仍然需要安装运行时,由于垃圾收集,灵活性有限,很难快速编写代码(除了在Windows上,你可以通过c++ /CLI接口)

我想说的是,斯威夫特实际上在避免任何重大妥协方面都做得很好(也可能是生锈;我没有认真使用过,所以不能发表有见地的评论)。这不是最好的在我提到的任何领域,但也不是太远。我不知道还有哪种语言可以做出这样的声明(但请注意,它也有其缺点,我将在本文的最后一节讨论这个问题)。我将依次简要介绍:

  • 简明:下面介绍如何创建新数组添加:let b=a.map {$0+2}.在这里,{ 0美元+2 }是一个匿名函数,与0美元作为第一个参数的自动名称(如果愿意,您可以选择添加名称和类型)。的类型自动推断。正如你所看到的,我们用少量代码做了很多工作!
  • 富有表现力:上面这行代码不仅适用于数组,但对于任何支持特定操作的对象(如序列在Swift标准库中)。您还可以添加对。的支持序列对于你的任何对象,甚至将其添加到现有的Swift类型或其他库中的类型中。一旦你这样做了,这些对象将免费获得此功能。
  • 灵活:斯威夫特没有什么做不了的。你可以将它用于移动应用程序,桌面应用程序,服务器代码,甚至是系统编程。它很适合并行计算,还可以处理(有些)小型存储设备。
  • 安全:斯威夫特有一个相当强大的类型系统,当你做了一些行不通的事情时,这能很好地提醒你。它对可选值有很好的支持,无需使代码冗长。但当你需要额外的速度或灵活性时,通常有办法绕过Swift的支票。
  • 快速:快速避免让语言变慢的事情;例如它不使用垃圾收集,允许您几乎在任何地方使用值类型,并且最小化了锁定的需要。它在后台使用LLVM,它对创建优化的机器代码有极好的支持。Swift还使编译器很容易知道什么时候事情是不可变的,避免了混叠,这也有助于编译器优化。正如你所看到的,您通常可以获得与仔细优化的C代码相同的性能。
  • 易于使用:这是一个领域,也许,有点妥协。编写基本的Swift程序非常简单,但可能会出现一些模糊的类型问题,神秘的错误信息离问题发生的真实站点很远,安装和分发应用程序和库可能具有挑战性。也,语言变化很大(为了更好!)因此,大多数在线信息都已过时,需要进行更改才能使其正常工作。说了这么多,它的远的比c++更容易使用。

面向协议的程序设计

让Swift避免妥协的主要技巧是它的使用面向协议的程序设计.基本的想法是我们尝试使用值类型尽可能多。在大多数易于使用的语言中,引用类型被广泛使用,因为它们允许使用垃圾收集,虚拟功能,超类行为,等等。面向协议的编程是Swift获得这些好处的方法,同时避免了引用类型的开销。此外,通过避免引用类型,当我们有两个变量指向同一事物时,我们可以避免所有引入的复杂错误。

值类型也非常适合编程的功能风格,因为它们允许更好地支持不可变性和相关的功能问题。许多程序员,尤其是在JavaScript世界中,最近对代码如何更简洁的理解,可以理解,正确,利用功能性风格。

如果你使用过C语言,你们应该已经熟悉了,用结构体给你一个值类型,和使用提供一个引用类型。这正是斯威夫特处理事情的方式。

在我们达成协议之前,让我们介绍一些其他的基本原理:自动引用计数(弧)和即写即拷.

自动参考计数(ARC)

Swift使用自动引用计数(ARC)来跟踪和管理应用程序的内存使用情况。在大多数情况下,这意味着在Swift中内存管理“只是工作”,你不需要自己考虑记忆管理。manbetx官网手机登录当不再需要类实例时,ARC会自动释放类实例使用的内存。“引用计数传统上被Perl和Python等动态语言使用。在现代编译语言中看到它是很不寻常的。然而,Swift的编译器努力地仔细跟踪引用,不引入的开销。

ARC对于处理swift的引用类型(有时我们仍然需要使用)都很重要,还可以处理值类型对象中的内存使用,这些对象与copy-on-write语义共享内存,或嵌入在引用类型中的。克里斯还向我提到了许多其他好处:它提供了确定性破坏,消除了GC终结器的常见问题,允许缩小到不需要/不需要GC的系统,消除不可预测/不可重复的停顿。

写上拷贝

在大多数语言中,值类型的一个主要问题是,如果有类似于大数组的东西,你不想把整个东西传递给函数,因为这需要大量缓慢的内存分配和复制。所以大多数语言在这种情况下使用指针或引用。迅速、然而,传递对原始内存的引用,但是如果引用改变了对象,只有这样它才会被复制(这是在后台自动完成的)。因此,我们得到了价值和参考类型组合的最佳性能特征!这被称为“写时复制”这在一些S4TF文档中被称为“奶牛”(是的,还有牛脸表情!)

Cow还帮助以功能性的方式进行编程,但是仍然允许在需要时进行修改——但是没有不必要的复制或冗长的手动引用的开销。

协议

值类型,我们不能使用继承层次结构来获得面向对象编程的好处(尽管如果使用引用类型,仍然可以使用这些好处,也有Swift的支持)。所以,迅速给我们协议.许多语言,如打字稿,C,和Java,有这样的想法接口元数据,描述对象可以包含哪些属性和方法。乍一看,协议看起来很像接口。例如,这是我的BaseMath库的定义ComposedStorage,它是一个协议,用于描述包装其他集合的集合。它定义了两个属性,数据终结索引,一种方法,下标(这是Swift中的一种特殊方法,并提供索引功能,像一个数组)。这个协议定义简单地说就是符合本协议必须提供这三件事的实现。

公众的 协议 ComposedStorage {
  关联类型 存储:可变集合 哪里 存储.指数=Int
  typealias 指数=Int

  var 数据: 存储 {得到 _
  var 终结索引: Int {得到_
  下标: Int)>存储.元素 {得到 _
_

这是一个通用的协议。通用协议不使用 类标记,而是使用关联类型关键字。在这种情况下,ComposedStorage是说数据属性包含称为的泛型类型存储哪个符合可变集合协议,这个类型又有一个关联类型被称为指数哪一种类型Int为了符合ComposedStorage.它还说下标方法返回存储元素 关联类型包含。正如你所看到的,协议提供了一个非常具有表现力的类型系统。

现在再看一看,你会看到别的东西……还有实现方式提供此协议!

公众的 延伸 ComposedStorage {
  下标: Int)>存储.元素 {
    得到 { 返回 数据[]     _
     { 数据[] = 新值 _
  _
  var 终结索引: Int {
    返回 数据.计数
  _
_

这就是事情变得有趣的地方。通过提供实现,我们会自动向任何符合这个协议的对象添加功能。例如,以下是basemath的完整定义AlignedStorage,类提供类似数组的功能,但在内部使用对齐内存,这通常需要快速向量化的代码:

公众的  AlignedStorage<T:支持基本路径>: 基站器, ComposedStorage {
  公众的 typealias 元素=T
  公众的 var 数据: 不可更改的缓冲指针<T>

  公众的 必修的 初始化γ 数据: 不可更改的缓冲指针<T>) {自己.数据=数据_
  公众的 必修的 方便 初始化γ 计数: Int)      { 自己.初始化不可更改的缓冲指针计数)) _
  公众的 必修的 方便 初始化γ 数组: 数组<T>) { 自己.初始化不可更改的缓冲指针数组)) _

  deinit { 不可更改的rawbufferpointer数据).释放() _

  公众的 var p: 穆特普特 {得到 {返回 数据.p}
  公众的 函数 复制()>自我 { 返回 .初始化数据.复制()) _
_

正如你所看到的,根本没有多少代码。但是这个类提供了协议的所有功能RandomAccessCollection,可变集合,可表示的YarrayLiteral,Equatable,和基站器(其中包括数百种方法,如地图,找到,dropLast,和距离)这是可能的,因为这个类所遵循的协议,基站器ComposedStorage,通过以下方式提供此功能:协议的扩展(直接或者按照他们所遵循的其他协议)。

顺便说一下,你们可能已经注意到我定义了AlignedStorage作为,不结构体,尽管我之前对值类型大肆宣传!manbetx官网手机登录重要的是要认识到在某些情况下仍然需要上课。苹果的文档提供了一些有益的指导关于这个主题。结构尚不支持的一件事是deinit;也就是说,在对象被破坏时运行一些代码的能力。在这种情况下,当我们处理完对象后,我们需要重新分配内存,所以我们需要戴尼特,这意味着我们需要上课。

您会发现真正需要使用协议的一种常见情况是您希望的行为抽象类.Swift根本不支持抽象类,但是你可以通过使用协议来达到同样的效果。在上述代码中ComposedStorage定义数据但是没有在协议扩展中实现它,因此,它就像一个抽象属性)。多重继承也是如此:Swift类不支持它,但是你可以遵守多种协议,每个都可以有扩展(有时称为as)混入在斯威夫特)。协议扩展与特征在铁锈和类型类在哈斯克尔

浮点数和双精度数上的泛型

对于数字编程,如果您正在创建一个库,那么您可能希望它至少透明地支持浮动双重的.然而,斯威夫特不容易做到这一点。有一个协议叫做二元浮点理论上支持这些类型,但不幸的是,Swift中只定义了三个数学函数(防抱死制动系统,马克斯,和最小-还有标准的数学运算符+-*/

你可以,当然,只需为每种类型提供单独的功能,但接下来你要处理的是创建两个版本的所有东西,您的用户也必须处理相同的问题。有趣的是,我在网上找不到关于这个问题的讨论,斯威夫特自己的图书馆在多个地方都面临着这个问题。正如下面所讨论的,Swift在数字编程中的应用并不多,这些都是我们必须解决的问题。顺便说一句,如果你在网上搜索数值编程代码,你会经常看到CG浮标类型(遭受了Objective-C的命名约定和限制,我们稍后会学到更多),manbetx官网手机登录但这只能提供支持浮点数或双精度数(取决于您所运行的系统)。这一事实CG浮标在swift的linux端口中存在是很奇怪的,因为它的创建只是出于苹果特定的兼容性原因;它几乎肯定不是你想要使用的东西。

解决这个问题其实很简单,这是一个如何使用协议的好例子。在BaseMath我创造了支持基本路径协议,提取如下:

公众的 协议 支持基本路径:二元浮点 {
  函数 登录2() > 自我
  函数 洛布() > 自我
  函数 近邻() > 自我
  函数 打印() > 自我
  函数 () > 自我
  ... 
_

然后我们告诉斯威夫特浮动符合本协议,我们也为这些方法提供实现

延伸 浮动 : 支持基本路径 {
  @可链接的 公众的 函数 登录2() > 浮动 {返回 基金会.登录2自己}
  @可链接的 公众的 函数 洛布() > 浮动 {返回 基金会.洛布自己}
  @可链接的 公众的 函数 近邻() > 浮动 {返回 基金会.近邻自己}
  @可链接的 公众的 函数 打印() > 浮动 {返回 基金会.打印自己}
  @可链接的 公众的 函数 () > 浮动 {返回 基金会.自己}
  ... 
_

现在在我们的库代码中,我们可以简单地使用支持基本路径作为对泛型类型的约束,我们可以直接调用所有常用的数学函数。(Swift已经以透明的方式为基础数学运算符提供了支持,所以我们不需要做任何事情就可以做到)

如果你认为写这些包装函数一定很痛苦,别担心,我使用了一个方便的技巧,这意味着电脑帮了我。诀窍是使用gyb使用python代码自动生成方法的模板,像这样:

% 对于 F 在里面 binfs:
  函数 ${F}(γ : 自我) > 自我
% 结束 # F

如果你看看Swift代码库本身,你会发现这种把戏被大量使用,例如,定义基本数学函数他们自己。希望在未来的版本中,我们可以在标准库中看到通用的数学函数。与此同时,只使用支持基本路径从巴实抹。

性能技巧和结果

Swift非常酷的一点是,上面这样的包装器没有运行时开销。manbetx官网手机登录如你所见,我已经用可链接的属性,它告诉LLVM用实际的函数体替换对该函数的调用是可以的。这种zero-overhead抽象是C++最重要的特性之一;看到它用如此简洁而富有表现力的语言如雨燕真是太不可思议了。

让我们做一些实验来看看这是如何工作的,通过运行一个简单的基准测试:添加2.0对1000000个数组中的每个元素进行快速浮动。假设我们已经分配了一个适当大小的数组,我们可以使用以下代码(注:基准是basemath中的一个简单函数,乘以一个代码块):

基准(标题:“swift add”){for i in 0..
         
          swift代码:0.963 ms
         

在一毫秒内添加100万个浮点数是非常令人印象深刻的!但是看看如果我们尝试一个小的调整会发生什么:

基准(标题:“Swift ptr add”)让(p1,p2)=(ar1.p,ar2.p)用于0中的i。
         
          swift ptr地址:.487 ms
         

几乎是相同的代码,但速度是原来的两倍-那到底发生了什么?巴加p财产数组,它返回一个指针阵列内存;上面的代码使用了一个指针,而不是数组对象本身。通常情况下,因为斯威夫特必须处理奶牛的复杂性,它不能完全优化这样的循环。但是通过使用指针,我们跳过那些支票,Swift可以全速运行代码。注意,由于写时复制,如果分配给数组,它可能会移动,它也可以移动,如果你做一些事情,如调整大小;因此,你应该只在你需要的时候抓住指针。

上面的代码仍然相当笨拙,但Swift使我们很容易提供一个优雅的、惯用的界面。我添加了一个新的地图方法数组,将结果放入一个预先分配的数组中,而不是创建一个新的数组。以下是对地图(它使用basemath中的一些类型别名使其更简洁):

@可链接的 公众的 函数 地图<T:基站器>γ F: UnaryF, γ : T) 哪里 自我.元素=T.元素 {
   pSrc = p  pde = .p  N号 = 计数
  对于  在里面 0N号 {pde[] = FpSrc[])}
_

正如你所看到的,这是普通的Swift代码。很酷的是,这让我们可以使用这个清晰简洁的代码,得到的结果和我们之前看到的一样

基准(标题:“地图添加”)ar1.map($0+2.0,ar2)>地图添加:.518 ms

我认为这是相当了不起的;我们已经能够创建一个简单的API,它和指针代码一样快,但是对于类用户来说,复杂性是完全隐藏起来的。当然,我们不真正地知道这有多快,因为我们还没有和C相比。我们接着做。

使用C

Swift的优点之一是,你可以很容易地添加C代码,manbetx官网手机登录或者使用外部C库。要使用我们自己的C代码,我们只是用Swift软件包经理SPM)流行音乐C文件在其来源目录,和一个h文件在其/来源包括目录。(哦,顺便说一句,在基础数学中h文件是完全自动生成的C文件使用GYB!)这一级别的C集成是极其稀有,其影响是巨大的。这意味着每一个C库,包括操作系统内置的所有功能,优化的数学库,Tensorflow的底层C API,等等都可以直接从Swift访问。如果你出于任何原因需要亲自去C,然后你就可以,无需任何手工接口代码或任何额外的构建步骤。

这是c中的和函数(这是浮动版本版本相似,这两个模板是由一个GYB模板生成的):

无效 斯马德里浮标康斯特 浮动* pSrc, 康斯特 浮动 瓦尔, 浮动* 血小板活化因子, 康斯特 int 伦恩) {
  对于 int =0 <伦恩 ++) { 血小板活化因子[] = pSrc[]+瓦尔 _
_

打这个电话,我们需要通过计数作为一个英特32;巴加C属性到数组以实现此目的(或者,您可以简单地使用numericCast (ar1.count).结果:

基准(标题:“c add”)smadd_float(ar1.p,2.0,AR2.Par1.c)>c添加:.488 ms

基本上和斯威夫特一样快。这是一个非常鼓舞人心的结果,因为它表明,我们可以得到与优化C相同的性能使用swift。而不是任何的斯威夫特,但惯用简洁,迅速,哪种方法(多亏了减少地图比大多数速度如此之快的语言更接近于数学方程式。

约简

现在我们来做一个不同的实验:取数组的和。以下是最地道的Swift代码:

benchmark(title:"reduce sum") {a1 = ar1.reduce(0.0,+)>减少和:1.308 ms

循环也是一样的:

基准(标题:“循环总和”)a1=0;我在0…
         
          循环和:1.331 ms
         

让我们看看我们之前的指针技巧是否有助于这次:

基准(标题:“指针和”)让p1=ar1.p a1=0;我在0…
         
          指针和:1.379 ms
         

这很奇怪。它不会更快,这表明它没有获得最佳的性能。让我们再次切换到C,看看它在这里的表现如何:

浮动 SMSUME浮标康斯特 浮动* pSrc, 康斯特 int 伦恩) {
  浮动 R = 0
  对于 int =0 <伦恩 ++) { R += pSrc[]; _
  返回 R
_

结果:

基准(标题:“c sum”)a1=smsum_float(ar1.p,ar1.c)>c总和:.230 ms

我将此性能与Intel的优化性能库版本总和并且发现这甚至比他们的手工优化汇编程序还要快!为了让它表现得比Swift更好,不过,我确实需要知道一些技巧(由LLVM的矢量化文档提供)。要用什么来编译-ffast-math国旗。对于这样的数值编程,我建议你总是至少使用这些标志(这是我在这些实验中使用的所有标志,尽管你也可以添加-三月=本地,改变优化级别O2对于Ofast):

-Xswiftc - uncheck -Xcc -ffast-math -Xcc -O2

我们为什么需要这面旗帜?因为严格来说,加法不是结合律,由于浮点数的特性。但这是,在实践中,不太可能是大多数人会关心的事情!manbetx官网手机登录默认情况下,叮当会使用“严格正确”的行为,这意味着它不能用SIMD对循环进行矢量化。但与-ffast-math我们告诉编译器我们不介意把加法看成是结合律,所以它将使循环向量化,速度提高了4倍。

为了在C代码中获得良好的性能,需要记住的另一件重要的事情是确保康斯特标记在所有不会改变的东西上,正如我在上面的代码中所做的。

不幸的是,目前似乎还没有一种方法能迅速使任何减量向量化。所以至少现在,我们必须使用C来获得良好的性能。这不是语言本身的限制,这只是Swift团队尚未着手实现的优化。

好消息是:basemath添加了总和方法数组,它使用了这个优化的C版本,如果你使用BaseMath,你会自动获得这个性能。所以测试1的结果是:失败。我们没能做到像C一样迅速的完成任务。但至少我们有一个很好的C版本,我们可以从Swift调用。让我们继续进行另一个测试,看看我们是否可以通过避免任何减少来获得更好的性能。

临时存储

如果我们想做一个函数约简,比如平方和?理想情况下,我们希望能够结合我们的地图风格上与总和,但不会因为Swift未优化的减少而造成性能损失。为了做到这一点,诀窍是使用临时存储。如果我们使用我们的地图上面的函数将结果存储在预分配的内存中,然后我们可以把它传递给C总和实施。我们需要一个静态变量来存储预先分配的内存,但是我们必须处理锁来处理线程之间的争用。为了避免这种情况,我们可以使用线程本地存储(TLS)。像大多数语言一样,Swift提供TLS功能;但是,它不是核心语言的一部分(比如,说,C)它提供了一个类,我们可以通过Thread.current.threadDictionary.BaseMath将预先分配的内存添加到此字典,并使其在内部可用暴风雪;这是一元函数约简的内部实现(也有二进制和三元版本可用):

@可链接的 公众的 函数 总和γ F: UnaryF)>元素 {
  自己.地图F, 暴风雪)
  返回 暴风雪.总和()
_

然后我们可以如下使用:

benchmark(title:"lib sum(sqr)") {a1 = ar1.sum(Float.sqr)}> lib sum(sqr): .786 ms

这提供了一个良好的加速比一般的Swift减少版本:

benchmark(title:"reduce sumsqr") {a1 = ar1.reduce(0.0,$0+float.sqr($1))>减少sumsqr:1.459 ms

这是C版:

浮动 SMSUME Sqrr-浮标康斯特 浮动* 限制 pSrc, 康斯特 int 伦恩) {
  浮动 R = 0
  pragma clang loop interleave_count(8)  对于 int =0 <伦恩 ++) { R += 正交频分复用pSrc[]); _
  返回 R
_

让我们试试看:

基准(标题:“c sumsqr”)a1=smsum_sqr_float(ar1.p,ar1.c)}> c sumsqr: .229 ms

C所有标准一元数学函数的求和实现都由basemath提供,因此,你可以调用上述实现,只需使用:

benchmark(title:"lib sumsqr") {a1 = ar1.sumsqr()}> c sumsqr: .219 ms

总之:虽然使用临时存储的Swift版本(并且只调用C来获得最终的金额)是使用的速度的两倍减少,使用C语言要快3倍或3倍以上。

的疣

正如你所看到的,关于Swift中的数字编程,有很多值得喜欢的manbetx官网手机登录地方。通过自动内存管理和优雅的语法,您可以同时获得优化C的性能。

我使用过的最简洁和灵活的语言是Python。我用得最快的是C(实际上是Fortran,但是,我们不要去那里。)那么,它是如何与这些高铁堆叠起来的呢?我们可以将一种语言与Python的灵活性和C的速度进行比较,这本身就是一个了不起的成就!

总体而言,我的观点是,一般来说,Swift代码要比Python代码多写一些我想写的东西,而且抽象公共代码的方法更少。例如,我在Python中经常使用装饰器,并使用它们为我编写大量的代码。我使用* args**夸格斯许多(新的)动态特性在Swift中可以提供一些功能,但不会太远)。我将多个变量同时压缩在一起(在Swift中,你必须为多个变量压缩成对的对,然后使用嵌套的参数对它们进行结构破坏)。然后还有一些代码,你必须编写这些代码来让你的类型排列得很好。

我也发现Swift的性能比C更难推理和优化。manbetx官网手机登录C在性能方面有自己的怪癖(例如需要使用康斯特有时甚至需要限制但它们通常有更好的文档记录,更好地理解,和更一致的。也,C编译器(如clang和gcc)使用OMP甚至可以自动并行化代码。

这么说之后,与我使用过的任何其他语言相比,Python的表现力和C的速度更快地结合在一起。

还有一些问题需要注意。需要考虑的一件事是,面向协议的编程需要一种非常不同的方式来处理您可能习惯的事情。从长远来看,这可能是件好事,因为学习新的编程风格可以帮助你成为一个更好的程序员;但这可能会在最初几周带来一些挫折。

这个问题特别具有挑战性,因为Swift的编译器通常不知道协议类型问题的真正来源是什么,它猜测类型的能力仍然相当薄弱。非常小的变化,比如改变类型的名称,或者更改类型约束的定义位置,可以改变一些过去有用的东西,它会弹出四个屏幕来显示错误消息。我的建议是尝试在独立的测试文件中创建类型结构的最小版本,先把事情做好。

请注意,然而,这种易用性通常需要妥协。巨蟒特别容易,因为朝自己的脚开枪对你来说是非常快乐的。斯威夫特至少能确保你首先知道如何解开鞋带。克里斯告诉我:首先,在构建Swift时,关键是要优化“端到端时间,以便正确实现您正在尝试做的任何事情”。这包括敲出代码的时间,调试时间到了,如果要对现有代码库进行更改,则需要重构/维护它。我还没有足够的经验,但我怀疑在这个标准上,斯威夫特会成为一个伟大的表演者。

斯威夫特的某些部分我不喜欢:苹果公司在客观-C的历史上做出的妥协,这是包装系统,是社区,缺乏c++的支持。或者更准确地说:它主要是斯威夫特的生态系统我不喜欢。语言本身很令人愉快。生态系统是可以修复的。但是,现在,这就是Swift程序员必须处理的情况,让我们依次看看这些问题。

目标-C

Objective-C是20世纪80年代开发的一种语言,旨在将Smalltalk的一些面向对象特性引入到C中。这是一个非常成功的项目,1988年被NeXT公司选为NeXT step编程的基础。随着NeXT被苹果收购,它成为苹果设备编码的主要语言。今天,它在显示它的年龄,它是C的一个严格超集。例如,Objective-C不支持真正的函数重载。相反,它使用了一种叫做选择器,它们只是必需的关键字参数。每个函数的全名是由函数名与所有选择器名的串联来定义的。这个思想也被AppleScript使用,它提供了类似于allow的名称打印在不同的环境中,意味着不同的事物:

打印第1页打印文档2打印第1页到第5页文档2

AppleScript又从HyperTalk继承了这个想法,1987年为苹果公司深受喜爱(和怀念)的产品创造的一种语言HyperCard程序。鉴于这段历史,今天,要求命名论点的想法是苹果公司的大多数人都非常喜欢的,这并不奇怪。也许更重要的是,它为Objective-C的设计者提供了一个有用的折中方案,因为他们能够避免向语言添加真正的函数重载,与C语言保持紧密的兼容性。

不幸的是,这种限制影响了今天的迅速发展,40多年后的情况导致了Objective-C的引入。斯威夫特提供真正的函数重载,这在数字编程中特别重要,你不需要为浮点数创建单独的函数,双打,复数(和四元数,等等)。但默认情况下,所有关键字名称仍然是必修的,这会导致代码冗长且视觉混乱。苹果的风格指南强烈提倡这种风格的编码;他们的目标——C和斯威夫特,风格引导彼此紧密地镜像,而不是让程序员真正利用Swift的独特功能。可以通过在参数名前面加上前缀来选择不需要命名参数γ,BaseMath在所有不需要可选参数的地方都使用它。

事情变得相当冗长的另一个领域是当涉及到工作的时候基金会,苹果的主类库,这也是Objective-C使用的。Swift的标准库缺少了许多您需要的功能,所以你经常需要求助于Foundation来完成工作。但你不会喜欢的。在享受了使用像Swift这样设计优雅的语言之后,使用它作为一个图书馆的笨拙的基础,有一些特别的悲哀。manbetx官网手机登录例如,Swift的标准库没有提供一种内置的方式来以固定的精度格式化浮动,所以我决定把这个功能添加到支持基本路径协议。这是代码:

延伸 支持基本路径 {
  公众的 函数 字符串γ 数字:Int) > 字符串 {
     FMT公司 = 数字格式化()
    FMT公司.最小分位数 = 数字
    FMT公司.最大分数位数 = 数字
    返回 FMT公司.字符串: 自己.NS编号) ?? \自己)
  _
_

我们可以添加这个功能的事实浮动双重的写这样的扩展真的很酷,和使用swift处理失败转换的能力一样??操作符。但是看看实际使用数字格式化从基础开始上课!它甚至不接受浮动双重的,但尴尬的数字对象Objective-C中的类型(由于Objective-C中缺少泛型,这本身就是一个笨拙的解决方案)。所以我必须添加一个NS编号财产支持基本路径做铸造。

Swift语言本身确实有助于支持更简洁的风格,如{f(0美元)}封口样式。简洁对于数字编程很重要,因为它可以让我们编写代码更紧密地反映我们正在实现的数学,并对整个方程一目了然。对于这一点(以及更多)的精彩阐述,看艾弗森的图灵奖演讲符号作为思考的工具.

Objective-C也没有命名空间,这意味着每个项目都会选择一些2或3个字母的前缀,并将其添加到所有符号中。大多数Foundation库仍然使用从Objective-C继承的名称,所以你会发现自己使用的类型CG浮标和功能等CFAbsoluteTimeGetCurrent.(每次我输入这些符号中的一个,我确信一头独角兽宝宝会痛苦地大叫……)

Swift团队做出了惊人的决定,在苹果设备上运行SWIFT时,使用基础和其他库的Objy-C实现,但要在Linux上使用本机Swift库。因此,有时,您会在每个平台上看到不同的行为。例如,Apple设备上的单元测试框架无法找到并运行作为协议扩展编写的测试,但是它们在Linux下工作得很好。

总体而言,我觉得Objective-C的约束和历史似乎过于频繁地被快速编程所取代,每次发生的时候,有一个真正的摩擦突然出现。随着时间的推移,然而,这些问题似乎在减少,我希望在未来,我们会看到越来越多的人从目标C的枷锁中迅速挣脱出来。例如,也许我们将看到为一些Objective-C类库创建惯用的swift替换程序的真正努力。

社区

在过去的几年里我一直在使用python,一直困扰我的一件事是,在Python社区中有太多的人只使用过一种语言(因为它是一种伟大的初学者语言,并且被广泛地教授给未毕业的学生)。因此,人们没有意识到不同的语言可以用不同的方式做事,每种选择都有自己的利弊。相反,在Python的世界里,人们有一种倾向,认为Python方法是唯一真正的方法。

我在斯威夫特身上看到了类似的东西,但在某些方面,情况更糟:大多数敏捷的程序员都是从Objective-C程序员开始的。所以,你在网上看到的很多讨论都来自于Objective-C程序员,他们以一种与Objective-C中的工作方式非常相似的方式编写Swift。几乎所有人都用xcode编程(这几乎肯定是我最不喜欢的IDE,除了它的美妙斯威夫特操场功能),所以你会在网上找到很多建议,告诉你如何通过让Xcode为你做事来解决快速问题,而不是自己编写代码。

大多数敏捷的程序员都在编写iOS应用程序,因此,您还可以找到许多关于如何布局移动图形用户界面的指导,但是几乎没有关于如何为Linux分发命令行程序的信息,manbetx官网手机登录或者如何编译静态库。一般来说,因为Linux对Swift的支持还很新,关于如何使用它的信息并不多,许多库和工具在Linux下不工作。

大多数时候,当我跟踪我的协议一致性的问题时,或者想知道如何优化一些代码,我能找到的唯一信息就是苹果公司Swift语言团队的邮件列表讨论。这些讨论往往集中在编译器和库的内部,而不是如何使用它们。因此,在讨论如何使用Xcode的应用程序开发人员和讨论如何修改编译器的Swift语言实现之间有一个巨大的中间地带。现在,在[https://forums.swift t.org/]的不和谐论坛周围正在形成一个良好的社区,希望随着时间的推移,这将成为快速程序员有用的知识库。

包装和安装

斯威夫特拥有官方批准的包裹系统,调用Swift包管理器(SPM)。不幸的是,这是我用过的最差的包装系统之一。我注意到几乎每一种语言,创建包管理器时,从零开始重新投资,并且未能充分利用以前尝试的所有成功和失败。斯威夫特遵循了这种不幸的模式。

有一些真正优秀的包装系统。最好的,也许,过去是,现在仍然是Perl的CPAN,其中包括一项国际自动化测试服务,该服务在各种系统上测试所有软件包,深深地集成文档,有很好的教程,等等。另一个伟大的(更现代的)系统是conda,它不仅处理特定于语言的库(重点是python),而且还处理自动安装兼容的系统库和二进制文件,并管理主目录中的所有操作,因此您甚至不需要根目录访问。它在Linux上很好地工作,Mac,和Windows。它可以处理两个编译模块的分发,或来源。

SPM,另一方面,没有这些系统的任何好处。即使Swift是一种编译语言,它不提供创建或分发已编译包的方法,这意味着包的用户必须安装构建它的所有先决条件。SPM不允许您描述如何构建包,因此(例如)如果您使用BaseMath,那么在构建使用它的对象时,您需要记住添加性能良好所需的标志。

处理依赖关系的方式非常笨拙。Git标记或分支用于依赖项,在本地开发版本和打包版本之间切换并不容易(比如,例如- e旗到皮普或者是康达发展命令)。相反,您必须修改包文件以更改依赖项的位置,在你提交之前记得把它换回来。

记录SPM的所有缺陷需要很长时间;相反,您可以假设,您从现在使用的任何包装系统中欣赏到的任何有用特性都可能不在SPM中。希望有人能为Swift建立一个基于conda的系统,我们都可以开始使用它。

也,安装斯威夫特是一团糟。在Linux上,例如,仅支持Ubuntu,不同的版本需要不同的安装程序。在MAC上,Swift版本以一种令人困惑和尴尬的方式绑定到Xcode版本,命令行和Xcode版本有些不同,但有些联系,让我的大脑受伤。再一次,conda似乎提供了避免这种情况的最佳选择,因为一个Conda包可以支持任何风格的Linux,Mac也可以以同样的方式得到支持。如果是为了迅速到达康达,那么就可以说Conda安装Swift在任何系统中,一切都会只是工作而已.这也将为版本控制提供一个解决方案,孤立的环境,以及复杂的依赖跟踪。

(如果你在Windows上,你是,现在,运气不好。有一个通往赛格温的非官方港口。Swift在Linux的Windows子系统上运行良好。但是还没有官方的本地窗口,遗憾的是。但这方面有一些好消息:一个名叫萨利姆·阿卜杜勒·拉苏尔的英雄大步为了完全自主地制造一个完全的本地端口,在过去的几天里,它已经达到了绝大多数Swift测试套件都能通过的程度。

C++

虽然苹果公司在其“C with Objects”解决方案中使用了Objective-C,世界其他地方都用C++进行了。最终,Objective-C的扩展也被添加到c++中,要创建“Objective-C++”,但并没有试图统一不同语言的概念,所以产生的语言是一个突变体许多重要的限制.然而,这门语言有一个很好的子集,它避开了C语言的一些最大限制;例如,您可以使用函数重载,并且可以访问一个丰富的标准库。

不幸的是,SWIFT根本无法与C++进行接口。即使是包含重载函数的头文件这样简单的东西也会导致Swift语言互操作失败。

这对数值程序员来说是个大问题,因为当今许多最有用的数字库都是用c++编写的。例如,这个阿托恩PyTorch的核心库是c++。数值程序员倾向于c++的原因有很多:它提供了解决数值编程问题的简洁和表达性解决方案所需的特性。例如,Julia程序员(有理由)为用他们的语言支持关键的广播功能是如此容易而自豪,他们记录了什么朱莉娅挑战赛.在c++中,这个挑战有一个优雅而快速的解决方案.你在纯C中找不到这样的东西,然而。

因此,这意味着对于快速程序员来说,大量且越来越多的最重要的数字编程构建块是不受限制的。这是一个严重的问题。(可以为C++类编写简单的C包装器,然后创建一个使用这些包装器的swift类,但这是一份非常大、非常枯燥的工作,我不确定有多少人会去做。

其他语言也显示出了解决这一问题的潜在方法。例如,c#在Windows上提供“它只是工作”(IJW)接口与c++ /CLI,一个C++的超集,支持.NET。更有趣的是,这个CPpsharp公司项目利用LLVM自动生成C++代码的包装器,不需要调用开销。

要迅速解决这个问题并不容易。但因为Swift使用LLVM,并且已经与C(和Objective-C)进行了接口,因此,比起几乎任何其他语言,提出一个伟大的解决方案可能是更好的选择。除了,也许,对于茱莉亚来说,因为他们已经已经做过.两次.

结论

斯威夫特是一种非常有趣的语言,可以支持快速,简洁,表达数字编程。Tensorflow项目的Swift可能是创建一种编程语言的最佳机会,在这种语言中,可微分编程是一等公民。Swift还允许我们轻松地与C代码和库进行交互。

然而,Linux上的Swift还不成熟,包装系统薄弱,安装很笨重,由于与Objective-C的历史渊源,图书馆也存在着一些问题。

那么它是如何累积起来的呢?在数据科学领域,我们主要使用r(这是我用过的最不愉快的语言,但是有了设计最精美的数据咀嚼和绘图库(到处都有)或Python(速度慢得令人痛苦,很难并行化,但它极具表现力,并拥有最好的深度学习库)。我们真的需要另一个选择。有点快,灵活的,并与现有库提供良好的互操作。

总体而言,快速的语言本身看起来正是我们所需要的,但是生态系统的大部分需要被替换,或者至少需要显著升级。没有数据科学生态系统可言,尽管S4TF项目似乎会创造一些重要的部分。如果你有兴趣成为一个有巨大潜力的事物的一部分,这真的是一个好地方。有一些真正伟大的人努力做到这一点,你也可以帮助消除疣子。

manbetx261

我2018年的目标是深入学习。2017年10月,我在阅读《纽约时报》的一篇文章后,偶然发现了一个名为famanbetx登陆st.a i的网站,文章描述了缺乏能够培养深度学习模式的人才。说它改变了我的生活听起来有点老套,但我很难想象,一年之后,我将在幕后帮助准备本课程的下一个版本。在这篇文章中,我会告诉你们一些关于我个人深入学习的经历,manbetx官网手机登录我将分享一些我认为在六个月前对我有用的建议。

使用神经网络将埃菲尔铁塔添加到绘画中的示例
使用神经网络将埃菲尔铁塔添加到绘画中的示例

我是谁?我从哪里来?

我的背景主要是数学。我有法国大学的硕士学位;我开始攻读博士学位,但六个月后就放弃了,因为我觉得这太令人沮丧了,在巴黎继续教本科生七年。我是一个自学的编码员,在我13岁的时候,我父亲就有了一个好主意,让我开始学习Basic语言。

我丈夫被搬到纽约,所以我三年半前搬到那里,成为了半个全职爸爸,半教科书作家,为法国一家出版社工作。当我第一次看fast的时候,manbetx登陆我对周围的炒作很好奇manbetx官网手机登录人工智能都是关于,manbetx官网手机登录我想知道我是否能理解只有少数天才才能理解的东西。

我不得不承认,我几乎没有开始这门课;对任何一个只有一年编码和高中数学经验的人来说,它可以解释他们的深入学习,我觉得这很可疑,我想知道这是不是都是假的(剧透提示:不是)。但我还是决定这么做;我已经完成了最新的一本书,每周花七个小时来学习这门课,而我的小儿子们似乎睡得并不多。

尽管我在数学方面有明显的优势,但我还是开始了第一个版本的mooc。我挣扎了很久令人讨厌的东西.我是一个Windows用户,以前从未启动过终端。这套设备花了我一个星期的时间才最终训练出我自己的狗和猫分类器。每次我必须在终端中运行一些命令时,都会感觉到某种形式的折磨(这一点还没有改变太多!)

如果你是这一领域的新手,正在为其中的一部分(或全部)而奋斗,还记得没有人能一帆风顺.总会有一些你不知道的事情,那将是一个挑战,但是如果你坚持下去,你会克服它的。随着时间的推移,会变得更容易,我的bash命令有一半还需要帮助,在第一节课上,两次破坏了文档和课程网站。幸运的是,每个人都忙着看杰里米,没有注意到。

你需要高等数学来进行深度学习吗?

简短的回答是不。答案是否定的,任何人告诉你相反的话,都只是想吓唬你。在深度学习的一些理论研究领域你可能需要高等数学,但桌上有供所有人使用的空间。

为了能够在实践中训练一个模型,你只需要三件事:了解导数是什么,了解错误函数的日志和exp,知道矩阵积是什么。你可以在很短的时间内学会所有这些,有多个在线资源。在这个过程中,杰里米建议可汗学院学习衍生品,manbetx官网手机登录日志,和EXP,和3蓝色1棕色为了学习矩阵乘积。manbetx官网手机登录

在我看来,你真正需要掌握的数学(或者至少是尽可能地熟悉)是广播.

做你自己的训练营,如果你是认真的manbetx官网手机登录

在我完成课程的第一部分后,我很清楚,我想在这个领域工作(因此有了很好的解决方案)。我考虑过各种训练营,它们承诺要把我变成一名数据科学家,以换取高额的学费。我在网上找到了足够多的推荐信,所以幸运的是,我很快就放弃了这个想法。

网上有足够的免费(或廉价)资源教你所需要的一切。,只要你有自律,你可以自己做训练营。最好的是课程从fast.aimanbetx登陆当然(但我现在在那里工作,所以有点偏颇)。

我以为我永远不会被选中参加第二部分课程的第二版的国际奖学金,所以当收到录取邮件时我有点措手不及。我订了一个同事的房间,让自己远离家里一个婴儿和一个小孩的疯狂。在我们找到一个保姆之前,我们匆忙雇了一队保姆,然后每天从9点工作到5点,加上晚上,在课程材料上。我以为我会跟着其他的情绪,但面对杰里米留下的所有挑战论坛,那里充满活力的社区,我从来没有时间去看别的地方。

尽管这门课的目的是让学生每周花7个小时做作业,绝对有足够让你忙更长的时间,尤其是在第二部分。如果你真的想把卡雷尔变成深度学习,manbetx官网手机登录你应该花七个星期在这门课上苦干。如果你能负担得起金钱/家庭方面的费用,飞到旧金山亲自去参加,每天去USF的学习小组。如果你不能,在你所在的城市找到其他人(或者组建自己的团队)。在任何情况下,活跃在论坛上,不仅仅是在你有缺陷的时候问问题,还可以帮助其他人编写代码。

展示你能做什么

我很害羞,我讨厌交际。那些亲自见过我的人知道我不能为上帝的爱而闲聊。幸运的是,在电脑安全的背后,有很多方法可以把你自己卖给潜在的雇主。这里有一些事情可以帮助你:

  1. 做你自己的项目来展示你学到了什么。在转移到另一个项目之前,一定要彻底完善一个项目。在我的例子中,它是再现超收敛莱斯利·史密斯的论文然后深度的绘画协调纸张。
  2. 写一篇博客解释你所学的。不一定是复杂的新研究文章,从模型的基础开始,即使您认为已经有上千篇这样的文章了。仅仅通过解释你认为你理解的事情,你就能学到很多。
  3. 参与一个与深度学习相关的开源项目(比如fastai图书馆
  4. 参加格格舞比赛(仍在我的待办事项列表中,也许这就是我2019年的决心;))。
  5. 建立一个Twitter账户,告诉人们以上所有的事情。manbetx官网手机登录

在课程结束前我得到了好几份工作机会,这让我很惊讶。然后,杰里米提到他要彻底重建图书馆,我主动提出帮忙。事情一件接一件,他设法得到AWS的赞助,让我成为fast.ai的研究科学家。manbetx登陆

在镜子后面

在我看来,学习总有三个阶段。首先你抽象地理解了一些东西,然后你可以解释,最终你真的做到了。这就是为什么看看你是否可以自己重做你在课程中看到的代码是如此重要。

就深度学习而言,学习这门课是我的第一阶段;写博客,第二阶段是记笔记或在论坛上回答问题;与杰里米一起从头开始重建图书馆是第三个。

在过去的几个月里,我学到的东西比我学习这些课程的时候还要多。其中一些在我丢弃的领域有点太快了……还有很多是在杰里米的指导下重构代码片段,直到我们得到今天你能看到的结果。构建一个完整的集成框架意味着你必须实现一切,所以你需要掌握这个过程的每一部分。

总而言之,这是我一生中学得最多的一年。我将永远感谢瑞秋和杰里米创造了这门神奇的课程,我很自豪能把我的小石头加进去。

m.7manbetx

在机器学习和深度学习中,没有数据我们什么都做不了。因此,为我们创建数据集以培训我们的模型的人是(通常不受重视的)英雄。一些最有用和最重要的数据集是那些成为重要“学术基线”的数据集;也就是说,研究人员广泛研究并用于比较算法变化的数据集。其中一些人成了家喻户晓的名字(至少,在训练模型的家庭中),如MNIST,CIVAR 10,和Imagenet.

我们都应该感谢那些为研究界提供数据集的人。太快了manbetx登陆。人工智能和AWS公共数据集程序我们已经联合起来试图回报一点:我们已经在一个地方提供了其中一些最重要的数据集,使用标准格式,可靠、快速的基础设施。有关完整列表和链接,请参见manbetx登陆fast.ai数据集页面.

manbetx登陆fast.ai在编码员的深度学习课程,因为它们提供了学生可能遇到的数据类型的很好例子,学术文献中有许多使用这些数据集的模型结果的例子,学生可以将他们的工作与这些数据集进行比较。如果你在研究中使用这些数据集,请引用原文来表达你的感激之情(我们在下面为每一篇文章提供了适当的引用链接),如果你把它们作为商业或教育项目的一部分,考虑添加一个感谢信和到数据集的链接。

数据集示例:法语/英语并行语料库

从fast.ai学生那里得到最多“哇”反馈的课程之一就是我们学习的时候manbetx登陆神经机器翻译.当我们可以教一个模型从法语翻译成英语,即使我们自己不会说两种语言!

但这不是魔法;关键是我们在本课中使用的出色的数据集:法语/英语平行文本语料库,于2009年由Chris Callison Burch教授宾夕法尼亚大学.这个数据集包含超过2000万个法语和英语句子对。他以一种非常聪明的方式构建了数据集:爬行数百万个加拿大web页面(通常是多语言的),然后使用一组简单的启发式方法将法语url转换为英语url。数据集对研究人员特别重要,因为它用于最重要的年度比赛用于基准机器翻译模型。

下面是一些我们的翻译模型可以学习的句子对的例子:

通常被认为是最古老的科学,它诞生于我们对天空的惊奇,我们需要质疑天文学是地球大气层之外的空间科学。 Souvent Consided_r_e comme la plus ancienne des sciences公司,它解耦了天文学和大气环境研究大学的天文学和大气环境研究大学的天文学的解耦和大气环境研究大学的天文学和大气环境研究的解耦。
这个名字来源于希腊词根astron,意思是恒星,和nomos的安排或法律。 我的儿子,也就是说,就是loi。
天文学研究的是天体和现象,比如恒星,行星,彗星和星系——以及宇宙的大尺度特性,也被称为“大局”。 Elle S'int_resse_des objets et des ph_nom_nes tels que les_oiles,Les计划,莱斯,星系和宇宙的所有者是一个大的阶梯。

那么Callison-Burch教授现在在做什么呢?当我们联系到他,为他的数据集检查一些细节时,他告诉我们他现在正在准备宾夕法尼亚大学新的人工智能课程;他的部分准备工作是:在course.manbetx登陆fast.ai!世界真的很小…

数据集集合

集合中当前包含以下类别:

数据集都存储在同一个TGZ格式,以及(在适当情况下)内容已转换为标准格式,适合导入大多数机器学习和深度学习软件。例如使用数据集建立实际的深度学习模型,注意manbetx登陆AI博客许多教程将很快发布。