连接图像和自然语言(翻译)一

摘要

人工智能领域的一个长期目标是开发可以感知和理解我们周围丰富的视觉世界的代理,并且可以用自然语言与我们沟通。由于计算基础设施,数据收集和算法的同步发展,在过去几年里,这个目标已经取得重大进展。视觉识别方面的进步尤为迅速,现在的计算机可以将图像分类为与人类相媲美的类别,甚至在某些情况下,例如对犬类进行分类,可以超越人类。然而,尽管取得了令人鼓舞的进展,但是视觉识别的大部分进展仍然是在为图像分配一个或几个离散标签(例如人,船,键盘等)的情况下进行的。

在本论文中,我们开发了模型和技术使我们能够连接视觉数据的领域和自然语言的领域,使两个领域的元素之间的翻译。具体来说,首先我们介绍一个将图像和句子嵌入到共同的多模态嵌入空间的模型。这个空间使我们能够识别描述任意句子描述的图像,相反,我们可以识别描述任何图像的句子。其次,我们开发了一个图像字幕模型,它可以直接生成一个图像,而不需要受限制的人工句子的有限集合来选择。最后,我们描述一个模型,可以把图像,本地化和描述所有,如果它的突出部分。我们证明,这个模型也可以反向使用任意描述(例如白色的网球鞋),并有效地将描述的概念定位在大量的图像中。我们认为,这些模型,他们利用内部的技术和它们之间的相互作用是人工智能的一个垫脚石,连接图像和自然语言为许多实际的好处和直接有价值的应用提供了支持。

从建模的角度来看,我们不是设计和分级显式算法来处理复杂处理流水线中的图像和句子,而是设计将视觉数据和自然语言话语与单一网络连接起来的混合卷积和递归神经网络架构。因此,图像的计算处理,句子,以及与之相关联的多模式嵌入的结构在图像及其字幕的训练数据集相对于网络参数的损失函数优化过程中自动出现。这种方法具有神经网络的许多优点,包括使用在硬件上易于并行化的简单,均匀的计算,以及由于端到端训练而产生的强大性能,从而将问题描述为单个优化问题,其中所有组件的模型共享相同的最终目标。我们展示了我们的模型在需要联合处理图像和自然语言的任务上推进了现有技术的发展水平,并且我们可以通过对网络预测进行可视化的可视化检查来设计架构。

目录

摘要iv
致谢vi
1引言1
1.1概述…………………………………… 1
1.2相关工作……………………………………… 4
1.3贡献和概述…………………………… 8
2深度学习背景10
2.1监督学习……………………………… 10
2.2优化…………………………………. 14
2.3反向传播……………………………….. 16
2.4 NeuralNetworks ………………………………… 19
2.4.1 VanillaNeuralNetworks ………………………… 19
2.4.2 ConvolutionalNeuralNetworks ……………………… 20
2.4.3经常性神经网络……………………… 23
2.5小结…………………………………… 26
3匹配图像和句子28
3.1相关工作…………………………………. 28
3.2模型…………………………………… 29
3.2.1代表图片………………………………………… 30
3.2.2代表经验………………………… 31
3.2.3对齐目标………………………….. 34
3.3优化………………………………… 37
3.4实验………………………………….. 37
3.4.1数据……………………………………… 37
3.4.2排名评估………………………… 38
3.4.3定性评估…………………………. 40
3.5结论…………………………………….. 42
4生成图像标题43
4.1相关工作………………………………… 44
4.2模型……………………………………….. 44
4.3优化…………………………………. 46
4.4实验………………………………….. 47
4.5结论……………………………………… 51
5密集图像字幕52
5.1相关工作………………………………… 54
5.2模型…………………………………… 54
5.2.1模型结构…………………………… 55
5.2.2损失功能……………………………… 59
5.2.3培训和优化……………………… 59
5.3实验………………………………….. 59
5.3.1密集调查……………………………. 60
5.3.2 ImageRetrievalusingRegionandCaptions。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 63
5.4结论………………………………… 66
6结论参考书目
67 71

引言

1.1概述

“我们可能希望机器最终将在所有纯知识领域与男人竞争。但是,哪一个是最好的开始呢?即使这是一个困难的决定。许多人认为像国际象棋这样非常抽象的活动是最好的。也可以这样说,最好是给机器提供最好的金钱可以购买的器官,然后教它理解和讲英语。这个过程可以遵循一个孩子的正常教学。事情会被指出和命名,等等。我不知道正确的答案是什么,但我认为这两种方法都应该尝试。“
- 艾伦·图灵(Alan Turing),计算机器与情报(1950)

在Alan Turing激励人心的愿景之后,人工智能领域的梦想之一就是让计算机能够看到和理解我们周围丰富的视觉世界,赋予他们以自然语言与我们沟通的能力。
人类发现很容易完成涉及复杂的视觉识别和场景理解的各种任务,涉及自然语言沟通的任务和结合两种模式之间的翻译的任务。例如,快速浏览一幅图像就足以让人指出并描述关于视觉场景的大量细节。使用图1.1中的例子,我们可以看图像,并立即指出并描述“橙色斑点猫”,“红色轮滑板”,“棕色硬木地板”,或者简单地说整个图像是一个“骑着滑板的猫”

这里写图片描述

挑战:由于这种能力对我们来说是如此的自然和无用,所以很容易忘记这个任务对于计算机来说是多么困难。在电脑中,这个图像被表示为一个大数字,表示任何位置的亮度。一个普通的图像可能有几百万像素,计算机必须将这些亮度值模式转换成高级语义概念,如“猫”。此外,在不同的照明条件下,以不同的照相角度,或以不同的姿势呈现的不同种类的猫可能仍然描绘“骑滑板的猫”,但亮度值的模式可以是完全不同的。相反,具有非常相似的低级统计数据(例如毛皮状高频模式)的模式可能会成为许多不同物体(地毯,大衣等)或动物(狗,熊,猴子等)的一部分。语言方面的挑战并不轻松。在计算机中,诸如“骑滑板的猫”之类的自然语言描述将被表示为表示词汇中每个词的索引的整数序列(例如,“骑滑板的猫”可能是[252,823,18,1742 ])。因此,指出和命名图像的不同部分的非常自然的任务实际上涉及识别具有几百万个亮度值的网格的显着子集并且用整数序列对其进行标注的复杂模式识别过程。此外,我们在本文中将使用的图像标题经常需要检测和描述复杂的高级概念,这些概念不仅是可视的,而且需要困难的推理。例如,一些图像可以被人类注释为“一群战斗的男人”,它需要检测多个人的能力,并分析他们的姿势,空间安排,甚至他们的面部特征。或者,有人可能被形容为“等待”某事,“玩”某种东西,或者“对某人玩笑话”。

鼓励进步。尽管这个任务很困难,但最近在视觉识别领域取得了突飞猛进的发展。具体而言,基于深度卷积神经网络的现有技术图像识别模型[58]已经能够在与人类相当的准确度上区分成千上万的视觉类别,甚至在一些细粒度的类别(例如狗的品种)中超越它们[84]。我们在分割和对象检测等相关任务方面的进展也同样显着[81,107]。这些进步一起使得许多真实世界的应用包括人脸检测和识别,个人照片搜索,机器人感知和自驾车等等。

未来的挑战:然而,这些应用程序中的主要方法是将视觉识别问题建模为将图像分类为若干固定和硬编码视觉类别的任务(图1.1,左图)。例如,ImageNet视觉识别挑战[84](一个流行的视觉识别基准)由一组1000个类别组成
(例如“热狗”,“螺丝刀”,“海蜇”,“笔记本”,“约克夏”等),也令人困惑地排除了许多常见的概念,如“人”,“脸”等)。同样,PASCAL VOC [24]物体检测基准使用一组20个手动选择的类别(例如“汽车”,“人”,“盆栽植物”等)。用于场景分类,动作分类或属性分类的其他数据集使用它们自己的一组类别。尽管视觉类别构成了一个方便的建模假设,但与人类可以为图像构成的描述的复杂性相比,这种方法却显得苍白(例如图1.1右)。

贡献纲要:在本文中,我们开发了使用自然语言作为计算机视觉任务的标签空间的模型和技术。例如,一个模型应该能够看到一个图像,并用自然语言描述其所有的视觉内容,而不是仅仅指定一个类别。相反,给定自然语言描述,模型应该能够识别描述该描述的视觉区域。换句话说,我们的目标是将视觉和自然语言两种模式联系起来,使计算机能够在两者之间进行转换。

长期的动机:这些抱负的动机既可以建立在智能机器的长期规模上,也可以在更短的时间范围内提供宝贵的实际应用。首先,这些技术是迈向未来的一个步骤,我们可以用自然语言与计算机进行交互,尤其是在这些交互可以在物理环境中正确使用的情况下。另外,人工智能代理人的工作将要求我们向计算机提供关于我们的世界如何工作的大量信息。具体而言,我们可以利用两个大量的知识来源:包含有关世界,场景,对象和交互(通过视觉传感器以最高带宽访问)的信息的物理域以及包含大量数据的互联网的数字域不能从物理领域单独推断的语义信息(例如,1760年发生的事情),主要以自然语言编码。

因此,愿景和语言是获取世界知识的主要渠道,而且我们开发的技术可以将信息跨越两个领域而不是独立处理,这一点至关重要。作为一个具体的短期例子,这可能使计算机可以在互联网上看到骆驼是“属于骆驼属的一种偶蹄有蹄类动物,在其背上带有被称为”驼背“的独特的脂肪沉积物,并认识到这样的概念在仅基于描述的视觉数据中。在较长远的将来,计算机可以读取有关程序(例如烹饪,修理被破坏的东西等)或关于过去展开的故事或事件,并了解它们在物理世界中的精确基础,从而可以解开关键的推论仅在文本中提到(例如,如果我“在头顶上举起一个沉重的球,放手”),将会发生什么。

短期动机。连接这两种模式的愿望也可以用更具体,短期和实际的论据来激发。首先,使用自然语言作为视觉识别的标签空间,引发了许多吸引人的实用性质。语言是一种丰富的编码,可以自然代表名词(物体,人物,场景),形容词(属性)动词(动作)和表示关系的嵌套结构。因此,预测自然语言话语会推广和继承许多其他视觉识别任务的挑战,这些视觉识别任务目前在计算机视觉中被视为独立的领域,包括对象识别,场景分类,属性分类,动作识别等。其次,最终用户我们的计算机视觉系统是人类,已经很流利的自然语言。因此,如果计算机使用语言作为标签空间,我们可以使计算机和人类之间的交互变得更容易和更自然,而不必求助于系统输入或输出的自然语言和固定类别之间的翻译。例如,用任意文本查询搜索个人照片集合,例如“与瀑布旁边的朋友一起游泳的照片”,不必经过“游泳”的调用动作分类器或“人”的对象分类器的中间阶段,或“瀑布”,但可以被模型直接拟合,并被视为一流的公民代表。相反地,计算机可以直接向视觉障碍者描述视觉场景,或者回答有关场景的查询。

这种方法的挑战:但是,这种方法也带来一些挑战。一个普遍的批评是,在这种情况下,评估变得更加困难。例如,在图像分类中,每个图像都由某个类别注释,因此计算和报告准确性是非常直接的-预测的一小部分是正确的。然而,如果一个模型用一个任意的句子来注释一个图像,那么评估这个句子的正确性就更加困难了。在一个标准的设置中,我们可能会有一些人类写的参考句子,我们可以比较每个预测,但这个比较可能很难明确地指定。在我们的工作中,我们使用最先进的自动评估方法,这种评估方法与人类判断的相关性最高,并期望未来可以进一步改进这些方法。另一个批评是,这种方法将视觉识别任务(即图像中的内容)与语言建模任务(即如何将概念串行化成流利的文本?)相结合;将这两项任务分离开来,将其孤立地研究,然后将它们组合起来,形成完整的系统,这可能是很自然的。另一方面,共同处理这些任务将使我们能够制定一个模型,在训练期间自动发现所有中间表示,而不必在处理图像以支持描述任务时明确指定应提取哪些特定特征。

1.2相关工作
图像和自然语言。本文的工作从渴望连接图像和语言形式的许多工作中得到灵感。一些最早的工作集中在基于统计模型的名词与图像区域特征关联的问题上[71,2,20,41],它们利用共现统计。

这些方法的一些扩展已经被开发来模拟不只是可以用来表示物体之间的关系的名词,而是介词和比较形容词[33]。最近人们已经开始处理更一般的语言结构和完整的句子。例如,Farhadi等人的早期工作 [26]提出了一个模型,将图像和句子映射到共同的意义空间,通过它们可以检索基于句子查询的图像,反之亦然。然而,他们的模型是基于一个限制性的处理,主要是从每个图像和句子中提取单个(对象,动作,场景)三元组。奥多涅斯等人[73]采用了类似的方法,但使用了更多的一般图像,更大的一组对象类别和场景,以及其他图像方面,包括东西,属性等。同样,Socher和Fei-Fei共同意义空间使用核化典型相关分析的特征表示在这两个领域。霍多什等人 [39]在完整的图像和句子上采用了类似的方法。由于这些排序方法被限制为从有限集合的句子中注释图像,因此已经提出了许多方法来克服这种限制并产生描述。姚等人的早期工作 [104]开发了一种方法处理图像与层次分析引擎,然后序列化到文本通过一个中间过程的语音生成规则,获取基于图像内容填写。不幸的是,他们的方法需要大量的关于生成过程的手工编码细节。古普塔等人早些时候使用了类似的方法[34]使用AND-OR图形来描述体育赛事视频。李等人的工作[60]是在图像中检测到的对象,并使用预训练的n-gram将它们组成一个句子,作为频繁出现的短片段短语的大型查找表。库兹涅佐娃等。 [53]通过检索然后选择性地组合人工句子来生成字幕。 Kulkarni等人[52]使用一种将对象,场景,修饰符或空间属性的检测插入到固定句子模板中的方法。最后,杨等人 [103]和米切尔等[70]基于对象检测类似地估计可能的单词,并通过生成具有生产规则的句法树来生成描述。

在本论文中,我们分享了这一工作的愿望,并解决了图像字幕和图像排序任务,而是在神经网络建模范例中开发了新颖的技术和算法,这些技术和算法具有优越的结果和多重吸引力的实用性质。此外,我们通过引入密集字幕任务来建立在这些愿望上,这要求计算机既能检测和描述图像的所有显着区域。不同于这个领域的早期工作[71,2,20],我们的描述包括任意的句子和名词短语,而不是有限的名词集合。

数据来源。这个领域的绝大多数建模方法都属于数据驱动技术的范畴,其中一个模型从人类注释数据中学习。因此重要的是突出可用的数据集并仔细研究其统计数据。

有几个数据集将视觉领域与自然语言领域联系起来。在本文中,我们使用包含一组图像(例如城市场景,客厅,公园餐厅,浴室等)的Flickr8K [39],Flickr30K [106]和MS COCO [62]数据集,Amazon Mechanical Turk写的描述。还应该指出标题和描述之间的区别。标题经常被理解为被设计为明确地提及不能单独从图像导出的场景的非显而易见的方面(例如确切的人物,位置或日期)的句子(即它们添加信息),而后者描述文字中的视觉内容。在图像句子数据集的情况下,要求人类注释者用句子描述图像的内容。因此,这些数据集主要包含图像描述,因为不熟悉照片的精确上下文的人很难适当地标注图像。在本论文中,我们将交替使用两个术语(描述,标题),但主要是指描述而不是标题。

经验地说,在这个数据收集任务中,人们经常描述图像中最突出的方面,并且倾向于描述人与他们的行为以及彼此或环境之间的相互作用。这些描述中的一些例子包括“在吃竹子时坐在阴凉树下的熊猫”,“在玻璃后面装满智能手机的陈列柜”,“两个孩子在睡觉时相互依偎”,“四名男子切入一个马来西亚写的蛋糕“,”一只狗把头放在船侧望着水面“。请注意,这个不受约束的设置引发了各种概念的混合:其中一些是可视的,更容易检测的(例如“狗”,“熊”,“蛋糕”),其中一些更加语义化,孩子睡觉“或”向外看“)。

此外,我们还将利用视觉基因组数据集[50],而每个图像包含多个描述,每个描述都附加地映射到图像中的某个边界框区域。在这种情况下,在数据收集期间,人们被要求识别图像中的多个矩形区域并描述其内容。有趣的是,这些描述不仅描述了最突出的概念,就像图像字幕数据集一样,而且还包含了诸如“银门把手”或“计算机监视器”等描述,否则这些描述不是很突出,通常不太可能在整个图像的描述中被提及。

建模方法:
目前所讨论的工作中的大多数建模方法使用的处理流水线首先包括特征提取,对象检测,场景或属性分类的步骤以从图像中提取高级概念,然后这些处理流水线与自然语言话语统计模型。这种方法的缺点是,该模型很快就会转化为复杂的多级流水线,包括预处理阶段,中间计算和表示,以及大量的超参数。对象,场景或属性检测器也经常在不同的数据集上进行训练,这些数据集有其自己的统计数据和偏差,并且转移到最终的感兴趣的领域是有限的。

最近,由于大规模数据集的可用性和更快的计算,我们目睹了使用深度卷积神经网络在视觉识别方面的快速进展[51,84]。这些模型基于20世纪40年代开发的一些技术。在“控制论”的名义下,McCulloch和Pitts [67],Rosenblatt [82]以及Widrow和Hoanna [100]开发人员早期模拟了具有可调突触强度和学习规则的神经元。在20世纪80年代,Rumelhart,Hinton和Williams以“连接主义”和“并行分布式处理”的名义推广使用反向传播训练神经元网络[83],这被用作当今极为有效的信用任务算法,该算法基于有效评估(通过递归应用链规则)损失函数相对于网络参数的梯度。尤其是,这些技术在视觉识别中的首次成功应用之一是LeCun等人的工作。 [57]数字识别,类似于福岛的Neocognitron [28]格子结构中的神经元和空间的本地连接。这是现代卷积神经网络的第一个描述,但是它在大规模视觉识别问题上的成功(比如ImageNet挑战[84])仅仅在几十年后才有可能实现,计算和训练数据更多[51]一个“深度学习”的新名称)。卷积网络描述了从输入空间(例如图像)到输出空间(例如,某些类别的概率)的函数,并且该函数的参数(所有神经元的连接的突触强度)使用大量的标记的图像(例如ImageNet数据集)。我们说,在这种方法中,模型是“端对端”的训练,这意味着从输入到输出的整个计算过程共享相同的最终目标(对图像进行正确分类),并进行联合优化。这个属性被广泛认为是使这些模型在实践中工作得很好的核心属性之一。这些模型的另一个实际优点是,一旦他们在一个数据集上训练,他们就可以用一个固定的特征提取器来处理图像,但更重要的是,他们可以通过初始化第一个任务的参数在不同的数据集上进行“微调”继续训练他们[17,87],这往往导致最终的表现有相当大的改善。在我们的工作中,我们使用卷积神经网络作为图像的核心处理模块,但将它们作为较大的神经网络架构的一部分进行微调,这些架构将图像与语言结构联系起来。

除了视觉识别方面的进展之外,我们在自然语言处理方面也见证了类似的成就。特别是与本文相关的,Mikolov等人[69]已经证明可以学习单词的分布表示[37],使得在类似的上下文中出现的单词在向量空间附近被发现。例如,“女人”和“女孩”这两个词可能(在训练了大量的句子之后)在彼此的附近发现,表明了类似的语义含义。类似于卷积网络,我们可以在其他应用程序中重新使用这些单词嵌入,并进一步“微调”新任务。最后,我们利用神经语言模型[4]的工作,制定表示概率分布在单词序列(即句子)上的神经网络结构。最近,递归神经网络[99,38]已经被证明在语言建模任务中特别有效[68,92,31]。在我们的工作中,我们使用大型体系结构中的语言模型和技术来表示给定图像的句子的条件分布。

综上所述,本文采用端到端的学习范式,设计了图像 - 句子匹配,图像字幕任务和图像区域标注任务的神经网络体系结构。因此,由于端到端的培训和从大规模相关数据集(如ImageNet)转移学习的好处,我们的模型在计算上更均匀,更简单并且产生更好的结果。

1.3贡献和纲要
在本论文中,我们开发了用自然语言连接图像的模型。具体而言,我们开发神经网络架构,有处理和对齐两种模式,并在图像字幕的数据集上端对端地训练其参数。

在第二章中,我们为监督学习,反向传播,优化,神经网络提供了相关的数学背景,并描述了处理图像和文本的常用体系结构设计模式,特别是卷积和递归神经网络。

在第3章中,我们开发了一个可以匹配图像和句子的模型。也就是说,给定一个有限的图像和句子集合,我们可以选择一个图像,并根据它们与图像的相容程度(他们描述内容的程度如何)来排列句子,相反,我们可以选择一个句子并排列图像基于他们与该句子的相容程度如何(他们描述的描述如何)。该模型将独立处理图像和句子,并将其嵌入到共同的多模式嵌入空间中,其中内部产品对应于多模式相似性。这些章节的内容主要基于Karpathy和Fei-Fei的排名模型部分[43],而在Karpathy等人的早期工作中则较少。 [45]和Socher等。 [90]。

在第四章中,我们具体地解决了对图像产生新颖描述的问题,放宽了排序模型的限制,假定有限的句子集合来选择形式。因此,该模型可以将图像作为输入,并生成可能不会逐字地出现在训练数据中的新颖描述。该体系结构基于用于处理图像的卷积网络和以图像信息为条件的递归神经网络语言的组合。本章的内容是基于Karpathy和Fei-Fei [43]的生成模型部分,对Karpathy,Johnson和Fei-Fei [44]的研究较少,Karpathy和Johnson是平等合着者。

在第五章中,我们删除了一个限制,即一个图像必须用一个句子来描述,并提出一个既可以检测又可以描述图像所有显着部分的模型。因此,这个模型可以选择描述整个图像,如前一章所述,而且还可以在空间上定位和描述图像的其他部分,如人物,背景,手机等。该模型的体系结构包括一个卷积神经网络,其次是由物体检测方法启发的区域提议模块和用于描述所有检测到的感兴趣区域的递归神经网络语言模型。本章的内容是基于Johnson,Karpathy和Fei-Fei [42]的作品,Johnson Karpathy是第一作者。

最后,在第6章中,我们确定了剩余的挑战,并讨论了前进的道路。

展开阅读全文

标准模板库简介(一)(翻译)

01-18

这篇文章翻译自SGI的网站,原文名为Introduction to Stand Template Library,链接为http://www.sgi.com/tech/stl/.我看后感觉对于理解一些相关概念和学习STL很有帮助就把它翻译过来了,是中英文对照的,因为我也不敢保证完全能表达原文意思,只是按自己的理解翻译出来了,希望对大家能有点帮助.rn 标准模板库简介rn标准模板库,或者STL,是一个包括容器类(container classes),算法(algorithms),和迭代器(iterator)的C++类库.它提供了许多计算机科学中的基本算法和数据结构.STL是一个泛型库,也就是说它的组件都是大量参数化了的(heavily parameterized):STL中的几乎每个组件都是一个模板.在开始使用STL之前,你应当确信你明白C++中的模板是如何运作的.rn容器和算法rn和许多类库一样,STL包括了容器类:它的目的是容纳其它对象.STL包含了vector,list,deque,set,multiset,map,multimap,hash_set,hash_multiset,hash_map和hash_multimap.这些类中的每一个都是一个模板.可以被实例化来容纳任何类型的对象.例如,你可以以与使用一个普通的C数组极其相似的方式来使用vector,,除了vector消除了手工管理动态内存分配之外.rnvector v(3); //声明一个有三个元素的vectorrnv[0] = 7;rnv[1] = v[0]+3;rnv[2] = v[0]+v[1]; //v[0]=7,v[1]=10,v[2]=17rnSTL也包含了大量的算法来操纵存储在容器中数据.例如,通过使用reverse算法,你可以反转一个vector中的元素顺序.rnreverse(v.begin(),v.end()); //v[0]=17,v[1]=10,v[2]=7rn对于reverse的这个调用有两点值得注意.首先,它是一个全局函数,而不是一个成员函数.第二,它接受两个参数而不是一个:它操作一系列元素,而不是一个容器.在这个例子中元素范围刚好是整个容器v.rn导致这两个事实的原因都是一样的:reverse,像其它STL算法一样,是与STL容器类分离的,也就是说,reverse不仅可以用来反转vector中的元素,而且可以反转list甚至C数组中的元素.下面的程序也是有效的:rndouble A[8] = 1.2,1.3,1.4,1.5,1.6,1.7;rnreverse(A,A+6);rnfor(int I = 0;i < 6;i++)rn cout << “A[“ << I << “]=” << A[i];rn这个例子使用了一个范围(range),就如反转一个vector的例子一样;reverse的第一个参数是一个指向该范围的开始指针,第二个参数指向该范围最后一个元素之后的位置.这个范围以[A,A+6]来标记;这个非对称的标记是用来提醒那两个端点是不同的,第一个是该范围的开始,第二个则是范围末尾之后的位置(也就是最后一个元素后面那个位置).rn迭代器(Iterators)rn在反转一个C数组的例子中,reverse的参数类型明显的是double*.但是如果反转一个vector或者一个list的话reverse的参数又是什么呢?即reverse所声明的参数究竟是什么,以及v.begin()和v.end()究竟返回的是什么?rnThe answer is that the arguments to reverse are iterators, which are a generalization of pointers. Pointers themselves are iterators, which is why it is possible to reverse the elements of a C array. Similarly, vector declares the nested types iterator and const_iterator. In the example above, the type returned by v.begin() and v.end() is vector::iterator. There are also some iterators, such as istream_iterator and ostream_iterator, that aren't associated with containers at all.rn答案就是reverse的参数为iterators,它是指针的一个泛化(generalization).指针自身就是是迭代器(iterator),所以才有可能反转一个C数组的元素.相似的,vector声明了内嵌类型(nested type)iterator和const_iterator.在上面的例子中,v.begin()和v.end()所返回的类型是vector::iterator.还有一些迭代器(iterators),例如istream_iterator和ostream_iterator与容器根本就没有关联.rnIterators are the mechanism that makes it possible to decouple algorithms from containers: algorithms are templates, and are parameterized by the type of iterator, so they are not restricted to a single type of container. Consider, for example, how to write an algorithm that performs linear search through a range. This is the STL's find algorithm. rn template rn InputIterator find(InputIterator first, InputIterator last, const T& value) rn while (first != last && *first != value) ++first;rn return first;rn rn迭代器(iterators)是一种使得将算法与容器进行分离成为可能的机制:算法是模板,用迭代器的类型进行参数化,所以它们并不限于单一类型的容器.例如,考虑怎样编写一个在一个范围内执行线性搜索的算法.这就是STL的find算法.rn Templatern InputIterator find(InputIterator first, InputIterator last, const T& value) rn While(first != last && *fist != value) ++first;rn Return first;rn rnFind takes three arguments: two iterators that define a range, and a value to search for in that range. It examines each iterator in the range [first, last), proceeding from the beginning to the end, and stops either when it finds an iterator that points to value or when it reaches the end of the range.rnFind接受三个参数:两个规定了一个范围的迭代器和在该范围内要搜寻的一个值value.它在[first,last]范围内检查每一个迭代器,从开始到最后,当它找到一个指向value的迭代器或者达到末尾时就停止了.rnFirst and last are declared to be of type InputIterator, and InputIterator is a template parameter. That is, there isn't actually any type called InputIterator: when you call find, the compiler substitutes the actual type of the arguments for the formal type parameters InputIterator and T. If the first two arguments to find are of type int* and the third is of type int, then it is as if you had called the following function.rn int* find(int* first, int* last, const int& value) rn while (first != last && *first != value) ++first;rn return first;rn rnfirst和last被声明为类型InputIterator,它是一个模板参数.即,事实上没有任何一个类型叫做InputIterator:当你调用find时,编译器用实际的参数类型来替换形式类型参数InputIterator和T.如果find的头两个参数类型为int*而第三个参数类型为int的话,那么就像你调用了下列函数一样:rn int* find(int* first, int* last, const int& value) rn while (first != last && *first != value) ++first;rn return first;rn rn 论坛

没有更多推荐了,返回首页