一文读懂大语言模型

以ChatGPT为代表的大语言模型被很多人认为是新一轮科技革命的起点,本文旨在通过概念性介绍,让普通人能够尽可能理解人工智能以及大语言模型的基本概念,从而了解这些技术能做以及不能做什么。原文: A Very Gentle Introduction to Large Language Models without the Hype[1]

0. 简介

本文旨在让没有计算机科学背景的人对ChatGPT和类似的人工智能系统(GPT-3、GPT-4、Bing Chat、Bard等)的工作原理有一些了解。ChatGPT是一种基于大语言模型(Large Language Model) 的对话式AI聊天机器人。这些词汇当前还比较陌生,但我们将逐步拆解,讨论它们背后的核心概念。这篇文章不需要任何技术或数学背景,我们通过大量比喻来说明这些概念,讨论核心概念的工作方式,以及ChatGPT这样的大语言模型可以或不可以做什么。

这就是本文要做的,在没有任何术语的情况下慢慢讲解与大语言模型和ChatGPT相关的术语,对于必要术语,我将用常见词汇来拆解解释。我们从"什么是人工智能"开始,逐步深入。我会尽可能多的使用重复出现的比喻,从我们应该期望AI能做什么或不能做什么来谈论这些技术的含义。

出发!

1. 什么是人工智能(Artificial Intelligence)?

我们先从一些可能经常听到的基本术语开始。什么是人工智能(artificial intelligence)

  • 人工智能 : 如果一个实体的行为和人类类似,这个实体可能会被称之为智能。

"智能"的定义并没有达成一致,因此用"智能"这个词来定义人工智能有点问题,不过我觉得这仍然相当不错。基本上可以认为,如果看一些人工的东西,做一些吸引人的、有用的、让人惊叹的事情,就可以称之为智能。例如,我们经常将"AI"一词归因于电脑游戏中由电脑控制的角色,这些机器人大多是简单的if-then-else代码(例如: 例如,"如果玩家在射程内,那么射击,然后移动到……")。但如果工作会让我们保持投入和兴奋,而不是做那些明显的傻事,我们可能会认为这些工作更复杂。

我们一旦了解了某些东西是如何工作的,可能并不会留下太深刻的印象,而且会期望在幕后看到更复杂的东西,这完全取决于你对幕后发生事情了解多少。

重点是,人工智能不是魔法。因为不是魔法,所以可以解释。

让我们开始吧。

2. 什么是机器学习(Machine Learning)?

你经常听到的另一个与人工智能相关的术语是机器学习(machine learning)

  • 机器学习: 一种通过获取数据,形成模型,然后执行模型来创建行为的方法。

有时候,手动创建一堆if-then-else语句来捕捉复杂的现象(比如语言)非常困难。在这种情况下,我们试图找到一堆数据,并用可以在数据中找到的模式来建模的算法。

但什么是模型呢?模型是对一些复杂现象的简化。例如,模型汽车是一辆真正汽车的更小、更简单版本,它有许多属性,但并不意味着完全取代原来的汽车。一辆模型车可能看起来很真实,有时候很有用,但不能开它去购物。

DALL-E生成的桌子上的汽车模型图片。
DALL-E生成的桌子上的汽车模型图片。

就像我们能造出更小更简单的汽车一样,我们也能造出更小更简单的人类语言。我们用术语"大语言模型(large language models)",因为考虑到它们需要多少内存,这些模型非常大。生产中最大的模型,如ChatGPT、GPT-3和GPT-4,大到需要在数据中心服务器上运行大型超级计算机来创建和运行。

3. 什么是神经网络(Neural Network)?

有许多从数据中学习模型的方法,神经网络就是其中之一。该技术大致模仿人类大脑通过神经元相互连接的脑细胞网络而组成,这些神经元来回传递电信号,以某种方式使人类能够完成各种任务。20世纪40年代提出了神经网络的基本概念,但直到20世纪80年代才发明了训练神经网络的基本概念。神经网络效率非常低下,直到2017年左右,由于计算机硬件的发展,才让大规模使用神经网络成为可能。

不过,相对于大脑,我更喜欢用电路来比喻神经网络。即使你不是电气工程师,也应该知道电是通过电线流动的,而有种叫做电阻的东西,可以阻碍电流经过电路的某些部分。

假设你想做一辆能在高速公路上行驶的自动驾驶汽车,汽车的前部、后部和侧面都配备了距离传感器,当有什么东西非常接近时,传感器报告数值为1.0,而当附近没有任何东西时,报告数值为0.0。

你还调整了汽车的控制,使自动装置可以转动方向盘、踩刹车、踩油门。当加速器接收到值1.0时,表示用最大的加速度,0.0表示不加速。同样,发送给制动装置的值1.0表示猛踩刹车,0.0表示不刹车。发送给转向装置的值为-1.0到+1.0,负值表示向左转向,正值表示向右转向,0.0表示保持直线。

你还得记录驾驶数据。当前方道路畅通时,就加速。前面有车时,要减速。当一辆车从左边靠得太近时,就向右转,改变车道(除非右边也有一辆车)。这是一个复杂的过程,涉及基于不同传感器信息的不同动作组合(向左转向,向右转向,加速或减速,刹车)。

现在要把传感器和自动装置连接起来。该怎么做?目前还不清楚。所以你把每个传感器和每个自动装置驱动器连接起来。

作为电路连接传感器和执行器的神经网络。
作为电路连接传感器和执行器的神经网络。

就这样开车上路的话会发生什么?电流从所有传感器流向所有执行器,汽车同时向左、向右转向、加速和刹车,一团糟。

当传感器发送电流时,会流向所有执行器,汽车就会同时加速、刹车和转向。
当传感器发送电流时,会流向所有执行器,汽车就会同时加速、刹车和转向。

这可不行。所以我想在电路的不同部分放上电阻,这样电流就只能在某些传感器和某些执行器之间流动。例如,我希望电流只从前方距离传感器流向刹车,而不是流向方向盘。此外,我还放了一些叫做门的东西,可以阻止电流流动,直到电力积累到足够翻转开关(只有当前方距离传感器和后方距离传感器报告的数字比较高时才允许电流流动),或者只有在输入电流强度低时才流动(当前方距离传感器报告数值较低时向加速器发送更多电流)。

但把这些电阻和门放在哪里呢?不知道。一开始我把它们随意放在各个地方,然后再试一次。也许这次车开得更好了,它在数据显示应该刹车的时候刹车,应该转向的时候转向,等等。但并不是每件事都做对了,有些事情做得更糟(数据显示需要刹车的时候它却加速了),所以我一直随机尝试电阻和门的不同组合。最终,我偶然发现一种效果足够好的组合,成功了。也许看起来像这样:

经过训练的神经网络。较暗的线表示电路中电流可以自由流动的部分。中间的圆圈是门,在将电流发送到上面的执行器之前,可能会从下面的传感器积累大量电流,或者可能在几乎没有电流的情况下发送电流。
经过训练的神经网络。较暗的线表示电路中电流可以自由流动的部分。中间的圆圈是门,在将电流发送到上面的执行器之前,可能会从下面的传感器积累大量电流,或者可能在几乎没有电流的情况下发送电流。

(我们在现实中不能增加或减少门,它们总是存在的,但可以修改门,使它们以更少或更多的电流激活。纯粹的机器学习主义者可能会对这种描述感到恶心。不过从技术上说,这是通过调整门的偏置(bias) 来完成的,通常不会在图表中显示,但就电路比喻而言,可以将其视为直接插入电源的门的导线,然后可以像其他导线一样进行修改。)

让我们试驾一下吧!

alt

随机尝试是种很糟糕的方式,有一种被称为反向传播(back propagation) 的算法在猜测如何改变电路的配置方面相当出色。算法细节并不重要,只需要知道算法会对电路进行微小调整,让电路的行为更接近数据的建议,经过数百万次调整,最终使电路与数据一致。

我们把电阻和门称为参数,但实际上参数无所不在,反向传播算法会声明每个电阻的强弱,因此一旦知道了电路的布局和参数,就可以复制到其他汽车上。

4. 什么是深度学习(Deep Learning)?

深度学习可以让我们在电路中加入除了电阻和门之外的其他东西。例如,可以在电路中进行数学计算,在输出电流之前进行相加或相乘。深度学习仍然使用一样基本增量技术猜测参数。

5. 什么是语言模型(Language Model)?

在汽车的例子里,我们试图让神经网络的行为与数据一致,从而创造出一种能够操纵汽车机械装置的电路,模拟司机的行为。我们可以用同样的方式对待语言,看看人类写的文本,并尝试电路是否能产生与人类产生的单词序列非常相似的单词序列。现在,当传感器看到单词时就会启动,输出的也是单词。

我们要做什么?尝试创建一个电路,在给定一堆输入单词的情况下,猜测输出单词。例如:

"Once upon a ___"

看上去空格里填"time"比"armadillo"更合适。

我们倾向于从概率角度来讨论语言模型,上述例子的数学形式为:

alt

如果不熟悉这个符号,别担心,这只是一个数学术语,意思是"time"这个词在给定(|符号的意思表示给定)一堆单词"once"、"upon"和"a"条件下出现的概率(P)。我们期望好的语言模型输出"time"这个词的概率比"armadillo"这个词的概率高。

可以将其概括为:

alt

意思是计算序列中第n个单词在给定在它之前所有单词(从位置1到n-1的单词)的条件下出现的概率。

不过现在退一步,想想老式打字机,就是那种有撞针的打字机。

DALL-E2生成了这张照片,看看那些撞针!
DALL-E2生成了这张照片,看看那些撞针!

除了每个字母都有不同的撞针,我们给每个单词都装上一个撞针,如果英语有5万个单词,那么这会是一台巨大的打字机!

设想一个与汽车网络不同但类似的网络,电路顶部有5万个输出连接到撞针上,每个单词一个。相应的,有5万个传感器,每个传感器检测不同输入单词。最终选择一个能得到最高电流信号的撞针,对应的单词就会出现在空白纸上。

现在的情况是,如果想做一个简单的电路,输入一个单词并产生一个单词,就必须做一个有5万个传感器(每个单词一个)和5万个输出(每个撞针一个)的电路。只需将传感器连接到撞针上,总共50000 × 50000 = 25亿根电线。

底部的每个圆圈表示一个单词,需要5万个传感器来识别单词"once",电流通过网络随意传播,上面每个圆圈都连接到一个单词的撞针上,所有撞针都得到了一些电流,但其中某个会得到更多的电流。
底部的每个圆圈表示一个单词,需要5万个传感器来识别单词"once",电流通过网络随意传播,上面每个圆圈都连接到一个单词的撞针上,所有撞针都得到了一些电流,但其中某个会得到更多的电流。

这是个很大的网络!

更糟的是,如果我想以"Once upon a ___ "为例,需要感知三个输入位置都是哪个单词,将会需要50000 × 3 = 150,000个传感器,连接到5万个撞针,得到15万 × 5万 = 75亿个电线。截至2023年,大多数大型语言模型可以接收4000个单词,最大的可以接收3.2万个单词。我要哭了。

以三个单词作为输入的网络,每个单词需要50000个传感器。
以三个单词作为输入的网络,每个单词需要50000个传感器。

需要一些技巧来处理这种情况,我们将分阶段进行。

5.1 编码器(Encoders)

第一件事是把电路分成两个电路,一个叫编码器(encoder) ,一个叫解码器(decoder) 。由于许多单词的意思大致相同,比如以下短语:

The king sat on the ___

The queen sat on the ___

The princess sat on the ___

The regent sat on the ___

对于上面所有空格,一个合理的猜测是"throne"(或者"toilet")。也就是说,可能不需要在"king"和"throne"之间、"queen"和"throne"之间进行区分,相反,如果有一些近似意味着"royalty"的东西,每次看到"king"或"queen",就可以用这个东西来代替。然后就只需要关心哪些单词的意思大致相同,然后该怎么做(向"throne"发送大量电流)。

这就是我们要做的。设置一个电路,有5万个单词的传感器,并映射到一些较小的输出集合(比如256个而不是5万个)。同时不是只能触发一个撞针,而是可以一次触发一堆。每种可能的撞针组合都可以代表不同的概念(如"royalty"或"armored mammals")。这256个输出使我们能够表示 个概念,而在现实中甚至更多。就像在汽车的例子中,可以踩下部分刹车,这256个输出的每一个都处于1.0和0.0之间。也许更贴切的比喻是256只撞针都向下击打,但每只力度不同。

好吧,以前一个单词需要5万个传感器中的某一个来激活,现在我们把一个激活的传感器和49999个关闭的传感器浓缩成256个数字。所以"king"可能是[0.1, 0.0, 0.9, …, 0.4],"queen"可能是[0.1, 0.1, 0.9, …, 0.4],几乎一样。这些数字列表被称为encodings(由于历史原因也称为隐藏状态hidden state,但我不想解释这个,所以我们将坚持使用encoding)。把5万个传感器压缩成256个输出的电路被称为encoder,看上去是这样的:

encoder网络将监测单个单词所需的5万个传感器值压缩为256个数字编码(较浅和较深的蓝色用于表示较高或较低的值)。
encoder网络将监测单个单词所需的5万个传感器值压缩为256个数字编码(较浅和较深的蓝色用于表示较高或较低的值)。
5.2 解码器(Decoders)

但编码器不会告诉我们下一个单词应该是哪个,所以我们将编码器与解码器网络配对。解码器是另一个电路,采用256个数字构成编码,并激活原始的5万个撞针,每个单词一个,然后选择输出电量最高的单词,看起来是这样的:

解码器网络将编码中的256个值扩展为与每个可能的单词相关联的5万个撞针的激活值,数值最高的单词被激活。
解码器网络将编码中的256个值扩展为与每个可能的单词相关联的5万个撞针的激活值,数值最高的单词被激活。
5.3 编码器和解码器的组合

编码器和解码器一起工作,形成一个大神经网络:

编码器-解码器网络。
编码器-解码器网络。

顺便说一下,通过编码实现单个单词输入单个单词输出只需要(50000 × 256) × 2 = 2560万个参数,看起来好多了。

这个例子是一个单词输入并产生一个单词输出,所以如果想要读取n个单词,将有50000 × n个输入,编码后将有256 × n个输入。

为什么会这样?通过将5万个单词都压缩到一个小的数字集合中,我们迫使网络做出妥协,并将可能触发相同输出单词的输入单词分组在一起。这很像文件压缩,压缩文本文档时,我们会得到一个较小的不可读的文档。但可以解压缩文档并恢复原始可读文本。因为zip程序用符号替换了某些单词模式,解压缩时知道要将哪些文本替换符号。编码器和解码器电路学习了某种电阻和门的配置,可以用来压缩和解压缩单词。

5.4 自监督(Self-Supervision)

怎么才能知道每个单词的最佳编码方式?换句话说,怎么知道"king"的编码应该与"queen"的编码相似,而不是"armadillo"?

作为思想实验,考虑一个编码器-解码器网络,接收一个单词(5万个传感器)并产生完全相同的单词作为输出。这是件蠢事,但对接下来的事情很有启发意义。

编码器-解码器网络被训练输出与输入相同的单词。
编码器-解码器网络被训练输出与输入相同的单词。

输入"king",一个传感器通过编码器发送电信号,并在中间部分打开编码中的256个值。如果编码正确,那么解码器将向同一个单词"king"发送最高的电信号。容易对不对?先别下结论。很有可能会看到带有"armadillo"字样的撞针具有最高的电能,假设"king"的撞针得到0.051的电信号,"armadillo"的撞针得到0.23的电信号。而实际上我们根本不在乎"armadillo"的值是多少,可以只看"king"的输出能量,就知道它不是1.0。1.0和0.051之间的差异是误差(也称为损耗),可以用反向传播对解码器和编码器进行一些更改,以便下次看到单词"king"时的编码稍微不同。

我们对所有单词都这样做,而编码器将不得不妥协,因为256比50000小得多。也就是说,有些词必须使用相同的能量组合。因此选择时,会希望"king"和"queen"的编码几乎相同,而"armadillo"的编码则非常不同,这将使解码器通过查看256个编码值来更好的猜测单词。如果解码器看到256个值的特定组合,并猜测"king"为0.43,"queen"为0.42,只要"king"和"queen"得到最高的电信号,并且其余49998个撞针都得到较小的数字,就可以接受。另一种说法是,我们可能更容易接受网络混淆king和queen,而不是混淆king和armadillo。

我们说神经网络是自我监督(self-supervised) 的,因为与汽车的例子不同,不需要单独收集数据来测试输出,而只需要比较输出和输入(不需要为输入和输出单独提供数据)。

5.5 掩码语言模型(Masked Language Models)

上面的思维实验看起来很傻,但是所谓的掩码语言模型的基石,其思想是接收一个单词序列并生成一个单词序列,但掩盖输入和输出中的一个单词。

The [MASK] sat on the throne.

网络会猜测所有单词,我们只关心网络对掩蔽词的猜测。也就是说,对于输出的每个单词,有5万个撞针,我们来看看这5万个掩蔽词的撞针。

掩码序列。红线表示上下所有东西之间的很多很多连接。
掩码序列。红线表示上下所有东西之间的很多很多连接。

可以移动掩码,让网络在不同的地方猜测不同的单词。

一种特殊类型的掩码语言模型只在末尾有掩码,这被称为生成模型,因为猜测的掩码总是序列中的下一个单词,相当于生成下一个单词,看上去是这样的:

The [MASK]

The queen [MASK]

The queen sat [MASK]

The queen sat on [MASK]

The queen sat on the [MASK]

我们也称其为自回归(auto-regressive) 模型。回归(regressive) 这个词听起来不太好,但只是意味着试图理解事物之间的关系,比如已经输入的单词和应该输出的单词。Auto的意思是"自我",自回归模型是自我预测的,预测下一个单词,然后这个单词又被用来预测下一个单词,以此类推。其中有些有趣的含义,稍后会讲到。

6. 什么是转移模型(Transformer)?

我们听过很多关于GPT-3、GPT-4和ChatGPT的东西。GPT是OpenAI公司开发的一种大语言模型的特定品牌。GPT代表生成式预训练转移模型(Generative Pre-trained Transformer) 。我们来分析一下:

  • 生成式(Generative) 。该模型能够生成所提供输入的延续,也就是说,给定一些文本,模型试图猜测接下来出现的单词。
  • 预训练(Pre-trained) 。该模型是在一个非常大的通用文本语料库上进行训练的,只需训练一次,就可用于许多不同场景,而不需要从头开始训练。

该模型是在一个非常大的通用文本语料库上进行训练的,涵盖了大量可以想到的主题。这或多或少意味着"从互联网上抓取",而不是从一些专门的文本库中获取。通过对一般文本进行训练,语言模型相对基于非常特定类型的文本(如来自医疗文档的文本)上训练的语言模型更有能力响应广泛的输入。在通用语料库上训练的语言模型理论上可以合理响应互联网上文档中可能出现的任何内容,但可能对医学文本响应一般。只在医疗文档上训练的语言模型可能对与医疗上下文相关的输入响应得很好,但在响应闲聊或食谱等其他输入时就很差了。

要么模型在很多事情上都足够好,以至于人们不需要训练自己的模型,要么可以做一些所谓的微调(fine-tuning) ,即采用预先训练好的模型并对其进行一些更新,使其在特定任务(如医疗)上能更好的工作。

接下来是转移模型…

  • 转移模型(Transformer) 。一种特殊类型的自监督编码器-解码器深度学习模型,具有一些非常有趣的属性,使其擅长语言建模。

Transformer是一种特殊类型的深度学习模型,以一种特殊方式转换编码,使其更容易猜出空白的单词,最早是由Vaswani等人在2017年发表的一篇名为Attention is All You Need[2]的论文中介绍的。Transformer的核心是经典的编码器-解码器网络,编码器执行非常标准的编码过程,你会惊讶于它的普通,但它还增加了另一种叫做自关注(self-attention) 的东西。

6.1 自关注(Self-Attention)

这是自关注的概念: 序列中的某些单词与序列中的其他单词相关。想想这个句子:"The alien landed on earth because it needed to hide on a planet."如果我们掩盖第二个单词"alien",并让神经网络猜测,它会通过"landing"和"earth"这样的单词更容易的猜出来。同样的,如果我们把"it"遮住,让神经网络猜这个词,"alien"这个词的出现可能会让神经网络更倾向于选择"it",而不是"he"或"she"。

单词通过功能、指称同一事物或相互传达意义而相互联系。
单词通过功能、指称同一事物或相互传达意义而相互联系。

我们知道,一个序列中的单词会与其他单词相关联,因为它们之间有某种关系,这种关系并不一定为人所知。这种关系可以是解析代词,可以是动词和主语的关系,也可以是与同一个概念相关的两个单词("earth"和"planet")。不管是什么,知道单词之间存在某种联系对预测很有用。

下一节将讨论自关注的数学问题,要点是Transformer学习输入序列中哪些单词是相关的,然后为输入序列中的每个位置创建一个新的编码,该编码是所有相关单词的合集。可以把它想象成学习创造一个新词,这个新词是"alien"、"landing"和"earth"的混合体(aliandearth?)。每个单词都被编码为一个数字列表,如果alien = [0.1, 0.2, 0.3, …, 0.4],landing = [0.5, 0.6, 0.7, …, 0.8],earth = [0.9, 1.0, 1.1, …, 1.2],那么第二个单词位置可能被编码为所有这些编码的总和[1.5, 1.8, 2.1, …, 2.4],它本身不对应任何单词,但却捕获所有单词的片段。这样,当解码器最终看到这个单词在第二个位置的新编码时,就有了很多关于这个单词在序列中是如何使用的信息,从而更好的猜测掩码。(示例只是将编码加在一起,但实际上比这更复杂)。

6.2 自关注是如何起作用的?

自关注是对普通编码器-解码器网络的重大改进,如果想了解更多有关其工作原理的信息,请继续阅读,否则可以跳过本节。自关注是数学运算点积(dot product) 的一个博眼球的名字。

自关注分为三个阶段。

(1) 对输入序列的每个单词进行正常编码。将单词编码复制四份,其中一份称为residual,先保存起来。 (2) 在其他三份上运行第二轮编码(对编码的编码)。每一份都经历不同的编码过程,所以出来的结果不同,一个为查询(q),一个为键(k),一个为值(v)。

考虑有一大堆信息存储在哈希表(在python中也称为字典)中,每一行都有(唯一标识符)和(存储在该行中的数据)。要从哈希表中检索信息,可以执行查询,如果查询匹配到键,则提取对应的值。

可以用来查询教授在哪个大学工作的哈希表。
可以用来查询教授在哪个大学工作的哈希表。

自关注有点像一个模糊的哈希表,提供一个查询,但不是查找与键的精确匹配,而是根据查询和键之间的相似性查找近似匹配。如果没有完美匹配,就返回值的一部分。这只有在查询、键和值都是数值的情况下才有意义,类似这样:

部分匹配的哈希表。
部分匹配的哈希表。

这就是我们要做的。对于输入的每个单词位置,采用q编码和k编码并计算相似度,计算方式是点积,也叫余弦相似度。不过这不重要,关键是每个单词都是256个数字的列表(基于之前示例),可以计算数字列表的相似性并记录在矩阵中。我们称这个矩阵为自关注得分(self-attention scores) 。如果有三个单词的输入序列,注意力得分可能是这样:

每个单元格表示一个位置上的编码单词对另一个位置上的编码单词的关注程度。
每个单元格表示一个位置上的编码单词对另一个位置上的编码单词的关注程度。

网络将第一个单词视为查询,并与第二个关键字进行匹配(或者说第一个单词"关注"第二个单词)。如果第二个单词是查询,将与第三个键匹配。如果第三个单词是查询,将与第一个键匹配。在现实中永远不会有这样的1和0,而是会在0和1之间进行部分匹配,并且每个查询(行)会对多个键(列)进行部分匹配。

继续检索的比喻,把这个矩阵乘以v编码,有趣的事情发生了。假设v编码像这样:

每一行都是序列中一个单词的编码。
每一行都是序列中一个单词的编码。

也就是说,第一个单词被编码为数字列表0.10…0.19,第二个单词被编码为数字列表0.20…0.29,第三个单词被编码为数字列表0.30…0.39。这些数字是为了说明的目的而编出来的,实际上不会这么整齐。

将注意力与值相乘。
将注意力与值相乘。

第一个查询匹配第二个键,因此检索第二个编码单词。第二个查询与第三个键匹配,因此检索第三个编码单词。第三个查询匹配第一个键,因此检索第一个编码单词。实际上做的是行交换!

alt

实践中,分数不会是完美的1和0,而是将是每种编码混合在一起的(例如,单词1的97%加上1%或单词3加上单词2的2%),但这说明自关注是一种混合和交换。在这个极端版本中,第一个单词被替换为第二个单词,依此类推。所以也许"earth"这个词被换成了"planet"这个词。

怎么知道正确编码了q、k和v?如果整个网络猜测掩码最佳单词的能力提高了,那么就正确编码了q、k和v。如果没有,那就改一下参数,用稍微不同的方式编码。

(3) 第三件事是把所有数学运算的结果加到residual上。还记得我们搁置的原始编码的第一个副本吗?没错,现在要把混合交换的版本加进去。现在,"earth"不仅仅是"earth"的编码,而是某种虚构的词,是"earth"和"planet"的混搭……pearth?ealanet?都不是。无论如何,这是将被发送到解码器的最终转换编码。每个位置都有一个假单词,它实际上编码了两个或更多单词,这更有利于对基于位置的单个单词进行预测。

然后再这样做几次(多层)。

这里省略了很多关于编码器的最终编码如何进入解码器的细节(另一轮关注,称为源关注source-attention,其中编码器每个位置的编码被用作q和k,以应用于另一个不同版本的v),但现在你只需要知道个大概。最后,解码器接收编码器的编码,将能量发送给撞针,挑选出能量最强的单词。

7. 为什么大语言模型如此强大?

这一切意味着什么?包括ChatGPT、GPT-4等在内的大语言模型只做一件事: 接收一堆单词,并尝试猜测下一个单词应该是什么。如果这是"推理"或"思考",那也只是一种非常特殊的形式。

但即使是这种特殊的形式似乎也非常强大,因为ChatGPT和类似的东西似乎可以很好的完成很多事情: 写诗、回答有关科学和技术的问题、总结文档、起草电子邮件,甚至编写代码。为什么会如此有效?

秘诀有两个,第一个已经讨论过了: Transformer学习混合单词上下文的方式,从而非常善于猜测下一个单词。其次是如何训练系统。大语言模型根据从互联网上抓取的大量信息进行训练,包括书籍、博客、新闻网站、维基百科、reddit、社交媒体对话等。在训练过程中,从其中一个来源中输入一段文本,并要求它猜测下一个单词。如果猜错了,就稍微调整一下模型,直到猜对为止。想一下LLM被训练做什么,其实就是产生可以合理出现在互联网上的文本。它记不住整个互联网,所以用编码来做出妥协,也许会有点错,但希望不要错得太离谱。

重要的是不要低估互联网上文本的多样性。LLM学习了一切,看了几乎所有话题的数十亿次对话。因此,LLM可以生成看起来像是在与你对话的单词。它已经看了数十亿首诗歌和歌词,几乎可以想象,它可以产生看起来像诗歌的文本。它已经看了数十亿家庭作业及答案,所以可以对你的家庭作业做出合理的猜测。它看了数以十亿计的标准化考试问题及答案。而今年的SAT试题和去年也不会有什么不同。它看过人们谈论假期计划,所以可以猜出看起来像假期计划的单词。它已经看了数十亿代码示例,涵盖各种各样场景。程序员做的很多事情都是将非常典型和容易理解的代码片段组装成更大的代码块,因此LLM可以编写这些小而通用的代码片段。它已经在stackoverflow.com上看了数十亿个错误代码的例子和更正,这样它就能针对你的错误代码提出修复建议。已经有数十亿人在推特上说,由于摸了热炉子而烧伤了手指,所以LLM知道这些常识。它已经阅读了大量科学论文,所以可以猜测众所周知的科学事实,即使你还不知道。它已经看了数十亿关于如何总结要点的例子,知道如何使文本更符合语法,更简洁或更有说服力。

重点是,当你要求ChatGPT或其他大语言模型做某些事,并且发现它完成了,很有可能你只是在要求它做一些它已经见过数十亿个例子的事情。即使你想出了一些非常独特的东西,比如"告诉我闪电侠戈登吃了六个墨西哥卷饼后会做什么"(我甚至不知道这是不是独特的),而它已经看了关于闪电侠戈登的同人小说,看到人们谈论吃了太多的墨西哥卷饼,并且可以(由于自关注)混合和搭配零碎的东西来组合一个听上去合理的回应。

当我们与大语言模型交互时,第一直觉不应该是"哇,这东西一定非常聪明,或者非常有创造力,或者非常容易理解"。我们的第一反应应该是"我可能已经要求它做一些它以前见过的东西"。不过即使它不是"认真思考"或"做一些非常复杂的推理",仍然非常有用。

我们不需要拟人化的来理解它做了什么来给我们提供回应。

关于这个主题的最后一点说明: 由于大语言模型的工作方式和训练方式,它们倾向于提供某种程度上属于中间响应的答案。在询问关于闪电侠戈登的故事后,模型往往会给出平庸的回答,这对我来说似乎很奇怪。但在一个故事或一首诗的背景下,这些回应可以被认为是许多人(在互联网上写作)会想到的。以一个人独自思考的标准来看,这可能相当不错。但你自己写的故事和诗歌可能也很普通(但它们对你来说很特别)。对不起,事实如此。

8. 我应该注意什么?

Transformer的工作方式和训练方式会产生一些微妙的影响,以下是一些技术细节。

  1. 大语言模型是在互联网上训练的,这意味着也接受了人类阴暗面的训练。大语言模型可能会被输入种族主义、性别歧视言论、对各种类型的人的各种侮辱、对他人的刻板假设、阴谋论、政治错误信息等,因此语言模型选择生成的单词可能会反应这种语言。
  2. 大语言模型没有"核心信念"。他们是在玩填词游戏,试图预测如果同样的句子出现在互联网上,下一个单词会是什么。因此,可以要求大语言模型写一个支持或反对同一件事的句子,语言模型将遵循这两种方式。这并不意味着它相信这个或那个,或者改变信仰,或者一个比另一个更正确。如果训练数据中一个事物的例子比另一个事物多,那么大语言模型将倾向于一致的响应互联网上出现的更频繁的数据。记住: 该模型力求模仿最常见的反应。
  3. 大语言模型没有任何对与错的概念。有些事情我们认为是事实,比如地球是圆的,LLM也会这么说。但如果换个上下文,它也会说相反的话,因为互联网上确实有关于地球是平的文字。LLM不能保证提供真相,只是倾向于猜测我们认为正确的单词,这是最接近于LLM"知道"真相或对错的方式。
  4. 大语言模型可能会出错。训练数据可能有很多不一致的材料,当我们问问题时,自关注可能不会关注到我们想要关注的所有事情。作为填词游戏,它可能会做出错误的猜测。有时,训练数据看到一个词的次数太多,以至于更喜欢这个词,即使它对输入没有意义。以上导致了一种被称为" 幻觉(hallucination)"的现象,在这种现象中,一个词是猜测出来的,既不是来自输入,也不是"正确的"。LLM倾向于猜测较小的数字,因为较小的数字更常见。LLM并不擅长数学。LLM更喜欢数字"42",因为人类由于一本特别著名的书而喜欢这个数字。LLM更喜欢常用的名字,所以可能会虚构成作者的名字。
  5. 大语言模型是自回归的。因此,当它们猜到不正确的单词时,这些猜测的单词会被添加到它们自己的输入中,猜测下一个单词。也就是说,错误会累积。即使只有1%的几率出错,自关注也会关注到那个错误的选择,并使错误加倍。即使只犯了一个错误,之后发生的所有事情也可能与这个错误有关。然后,语言模型可能会在此基础上产生额外的错误。Transformer没有办法"改变主意"或再试一次或自我纠正,只能随波逐流。
  6. 应该始终验证大语言模型的输出。如果你要求它做一些你自己无法胜任的事情,那么应该考虑一下是否可以对所犯的错误采取行动。对于低风险任务(比如写一个短篇故事),这可能没问题。而对于高风险任务(比如决定投资哪些股票),这些错误可能会导致你做出非常昂贵的决定。
  7. 自关注意味着在输入提示中提供的信息越多,回答就会越专业,因为它会在猜测中混合更多输入的单词。响应的质量与输入提示的质量成正比,更好的提示产生更好的结果。尝试几种不同的提示,看看哪种最适合。不要假设语言模型"理解"你想要做的事情,并且能在第一次就给出最好的结果。
  8. 你并没有真正与大语言模型"进行对话"。大言模型不会"记住"交流中发生的事情。你只是输入并获得输出,LLM什么都不记得。也许你觉得初始输入、响应以及对响应的响应看起来像是在记忆,那也只是因为对话日志作为了新的输入。这是一个前端编程技巧,使大语言模型看起来像是在进行对话。由于这个技巧,它可能会围绕主题输出,但不能保证不会与之前的回应相矛盾。此外,可以输入多少单词是有限制的(目前ChatGPT允许大约4000个单词,而GPT-4允许大约32000个单词)。输入可以相当大,所以对话通常会在一段时间内保持连贯。最终,累积的日志变得越来越大,不得不把一开始的对话删掉,也就是说系统会"忘记"早期的内容。
  9. 大语言模型无法自己解决问题或制定计划,但可以要求他们制定计划并解决问题。这里需要详细解释一下, 解决问题(Problem-solving)计划(planning) 是人工智能研究社区中某些团体的保留术语,用于表示非常具体的东西。具体来说,意味着有一个目标(想在未来完成的事情)并通过在若干可以接近目标的备选方案中做出选择来努力实现目标。大语言模型没有目标,或者说他们只有一个目标,即在给定输入序列的情况下,选择最有可能出现在训练数据中的单词,也就是模式匹配。计划通常涉及到 前瞻性(look-ahead) ,人们做计划时,会想象行动结果,并根据目标分析未来。如果看起来离目标更近了一步,就是一个很好的行动。如果没有,可能会尝试想象另一种行为的结果。实际生活中还有更多东西,但关键是大语言模型没有目标,也没有前瞻性。Transformer只向后看,自关注只能应用于已经出现的输入词。现在,大语言模型可以生成看起来像计划的输出,只是因为在训练数据中看了很多计划,知道计划是什么样的,也知道关于某些主题的计划应该出现什么,因而对计划可以做出很好的猜测。它们做出计划可能会忽略特定细节,而倾向于最一般的计划。大语言模型当然没有"考虑各种选择",也没有尝试一件事,然后又退回去尝试另一件事。在Transformer内部,没有机制可以让它对未来进行这样的考虑。因此在要求它给出计划时,一定要验证其输出。

9. 是什么让ChatGPT如此特别?

"所以我听说RLHF是ChatGPT真正聪明的地方。"

"ChatGPT使用强化学习,所以它这么聪明。"

不一而足……

现在人们对RLHF(基于人类反馈的强化学习,Reinforcement Learning with Human Feedback)感到非常兴奋。业界在训练ChatGPT(以及其他越来越多的大语言模型)方面做了很多事情,这些并非是全新的技术,但是在ChatGPT发布时,这些技术的广泛引入产生了很好的效果。

ChatGPT是基于Transformer的大语言模型,因其非常擅长生成对输入提示的响应以及拒绝回答某些可能被认为是有害或固执己见的问题而赢得了声誉。它所做的与上面介绍的没有什么不同,事实上它很普通,但在训练过程中有点不一样。ChatGPT的训练方式和正常的一样,从互联网上抓取大量信息,提取文本片段,然后让系统预测下一个单词,这就产生了一个基本模型,已经是非常强大的单词预测器(相当于GPT-3),但还有两个额外的训练步骤: 指令调优(Instruction tuning)基于人类反馈的强化学习(reinforcement learning with human feedback)

9.1. 指令调优(Instruction Tuning)

大语言模型有个特别的问题: 它们只接受输入单词序列并生成后续单词。大多数时候,这正是人们想要的,但并非总是如此。考虑以下输入提示:

"写一篇关于亚历山大·汉密尔顿的文章。"

你认为回答应该是什么?可能会想到:"亚历山大·汉密尔顿于1757年出生在尼维斯。他是政治家、律师、陆军上校和美国第一任财政部长……"但实际上可能得到:

"你的文章应该至少有五页,双倍行距,并包括至少两次引用。"

发生了什么?嗯,语言模型可能已经看到了很多学生作业的例子,这些作业以"写一篇关于……的文章"开头,包括详细描述长度和格式的单词。当然,当你写"写一篇文章……"时,你认为是在给语言模型写指令,就好像它是一个能够理解意图的人。语言模型不理解你的意图或者它们自己的意图,它们只将输入与训练数据中看到的模式相匹配。

为了解决这个问题,可以做一些叫做指令调优的事情。想法相当简单,如果你得到了错误响应,写下正确的响应应该是什么,并将原始输入和新的、经过修正的输出作为训练数据通过神经网络发送。有了足够多的修正输出的例子,系统将学会改变其回路,使新的答案成为首选。

不需要做太花哨的事,只要让很多人与大语言模型交互,并要求它做很多事情,并在它行为不正确时纠正,然后收集所有出错的例子和新的、正确的输出,并进行更多的训练。

这使得大语言模型表现得好像能够理解输入提示的意图,并表现得好像它在遵循指令。除了试着猜下一个单词,它其实什么也没做。但新的训练数据让它能够更好的猜测对输入更匹配的单词。

9.2. 基于人类反馈的强化学习(Reinforcement Learning from Human Feedback)

下一步是从人类反馈中进行强化学习,这里需要一点解释。

强化学习(Reinforcement learning) 是一种AI技术,传统上用于机器人研究和虚拟游戏模拟(想想可以玩国际象棋、围棋或星际争霸的AI系统)。强化学习特别擅长弄清楚当它得到所谓的奖励时该怎么做。奖励只是一个数字,表明它做得有多好(做得非常好+100,做得很差-100)。在现实世界和游戏中,通常很少会有奖励。在游戏中,可能需要玩很久才能得分,甚至只会在游戏的最后一刻得分。在现实世界中,没有足够的人告诉你什么时候做得很好,除非你是一条狗。你唯一需要知道的是,强化学习系统试图预测它们将获得多少奖励,然后选择最有可能获得更多奖励的行为,这与人们用狗粮来训练狗的方式并没有什么不同。

好吧,先不想这些,考虑下面的提示:

"Mark是什么方面的专家?"

假设语言模型的输出为:

"Mark在人工智能、图形学和人机交互方面发表了许多著作。"

这只是部分正确,但我没有在图形学方面发表过论文,所以很想给它一个 alt ,或者-1分。但这里只有"图形学"是错的,如果告诉系统整个句子都是错的,语言模型可能会觉得所有这些单词都应该避免使用,但其实很多词并没什么问题。

这就是强化学习的用武之地。强化学习的工作原理是尝试不同选择,看看哪种选择能获得最大回报。假设我要求它对原始提示生成三个不同的响应。

"Mark在人工智能、图形学和人机交互方面发表了许多著作。"

"Mark曾从事人工智能、安全NLP系统和人机交互方面的工作。"

"Mark研究过人工智能、游戏AI和图形学。"

我可以给第一个相应-1,给第二个+1,给第三个-1。就像玩游戏一样,强化学习算法可以回顾并找出导致-1的一个共同因素是"图形学"这个词。现在,系统可以锁定这个单词,调整神经网络,使其不与特定的输入提示一起出现。

然后让一群人与大语言模型交互,这一次系统会给出三种(或更多)可能的回答。我们可以通过要求大语言模型提供多次响应并在响应的选择中引入一点随机性来做到(还没忘记吧?)我们有时可能会选择排第二或第三的响应,而不是选择激活可能性的响应。这就提供了不同的文本回复,人们可以选择最喜欢的回复,第二喜欢的回复,等等。现在有了选择,有了权重数字,就可以用强化学习来调整神经网络。

实际上,我们用"好"、"不好"的反馈来训练第二神经网络来预测人们的反应。如果这个神经网络能够很好的预测人们会喜欢什么,那么就可以用第二神经网络来猜测语言模型的反应会得到"好"还是"不好",然后用它来训练语言模型。

强化学习将文本生成视为游戏,每个动作都是一个单词。在序列最后,语言模型被告知是得分了还是丢分了。语言模型并没有像前一节中讨论的那样精确的进行预判,但是在某种意义上,它已经被训练来预测哪些单词会被点赞。大语言模型还是没有明确目标,但有一个"被点赞"的隐含目标(或者也可以说有一个"满足普通人"的隐含目标),并且已经学会将特定提示的特定反应与获得点赞联系起来。这具有许多计划的特性,但没有明确的前瞻性机制,更像是记住了在很多情况下都有效的获得奖励的策略。

那么RLHF有没有让ChatGPT更智能?它使ChatGPT更有可能产生我们希望看到的响应,因此看起来更智能,它的输出似乎传达了一种感觉,即能够理解我们输入的意图,并有自己的回应意图。其实这是一种错觉,因为它仍然只是对文字进行编码和解码。但话说回来,这不就是我们为啥要写这篇文章么😉。

指令调优和RLHF还使ChatGPT能够抵抗某些类型的滥用,例如产生种族主义、性别歧视或政治内容。还是有可能输出这些内容,而且旧版本的GPT-3总是能够被用来输出这些东西。然而作为免费的面向公众的服务,ChatGPT针对某些类型的滥用所做的工作传递了一种安全感,并且它还抵制将意见作为事实提供,这也消除了对用户的潜在伤害。

用强化学习来修改预训练的语言模型并不是什么新鲜事,至少可以追溯到2016年,并已被用于使大语言模型更安全。大多数基于强化学习的大语言模型调优都用第二模型来提供奖励,这也是用ChatGPT完成的。ChatGPT值得注意的是通过强化学习调整系统的规模,以及大规模的人类反馈收集工作。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。微信公众号:DeepNoMind

参考资料

[1]

A Very Gentle Introduction to Large Language Models without the Hype: https://mark-riedl.medium.com/a-very-gentle-introduction-to-large-language-models-without-the-hype-5f67941fa59e

[2]

Attention is All You Need: https://arxiv.org/abs/1706.03762

- END -

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/22492.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新手小白教程之 圈X-QuantumultX 某青极速版自动签到阅读

自动签到阅读功能 今天给大家带来QX的进阶玩法,实现阅读极速版的自动签到,自动阅读功能。我们今天的功能并不在重写或调试模块进行操作,直接在配置文件进行操作是最快最方便的。下面开始今天的教程。欢迎大家入群交流:868199154 …

0代码基础小白使用ChatGPT做出一款谷歌全屏截图插件的全过程

ChatGPT云炬学长 公众号:云炬网络 1 人赞同了该文章 开篇说明: 1、本次完全不懂代码,不知道什么Java、c,真正0基础开局; 2、以下是我按照时间顺序记录全过程,重点是记录使用ChatGPT的过程;…

看我用ChatGPT如何快速生成思维导图

这一节给大家分享下如何利用ChatGPT快速生成思维导图,先看效果图: 首先去ChatGPT提问题:如下图,生成MarkDown格式的内容。 把这些内容复制到支持MarkDown格式的编辑器,如果你没有这样的编辑器也没关系,你用…

用python画梵高星空-python画画梵高

广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 众多的第三方库; 解释执行,不需要编译; 跨平台,方便移植;..... 两个词总结起来就是:简单、方便。 2“不务正业”的python更可怕的是,某些实用主义者将py…

AI绘画人像promt分享

Promt Checkpoint为基础模型,常用chilloutmix和majicmixRealistic 在设置好checkpoint后,即可设置promt,按照经验来说, promtBase promtDescription promtlorapositive TextureStyle promt 其中的positive Texture和lora根据需求可以从c站…

教你从头到尾利用DL学梵高作画

教你从头到尾利用DL学梵高作画 作者:七月在线开发/市场团队三人,骁哲、李伟、July。本教程主要由骁哲撰写,李伟负责Linux命令部分。 配置:GTX 1070 cuda 8.0 Ubuntu 14.04 cudnn 5.1 tensorflow gpu 时间:二零一六年九…

【AI作画】当梵高遇上东方明珠——梵高画风迁移全纪录

【AI作画】当梵高遇上东方明珠——梵高画风迁移全纪录 视频: 【AI作画】当梵高遇上东方明珠——梵高画风迁移全纪录 梵高出生于1853年3月30日荷兰乡村津德尔特的一个新教牧师家庭,早年的他做过职员和商行经纪人,还当过矿区的传教士最后他投身…

手把手教你用AI画梵高的《星空》

导读:有人说,AI会导致失业;也有人说,AI创造大量工作机会,各行各业对AI人才的需求都将日益增加。 AI在模仿人类的学习方式,那么,人类又该怎样学习AI?本文就带你了解一本学习AI的神书。…

教你从头到尾利用DL学梵高作画:GTX 1070 cuda 8.0 tensorflow gpu版

教你从头到尾利用DL学梵高作画 作者:七月在线开发/市场团队中的三人,骁哲、李伟、July。本教程主要由骁哲撰写,李伟负责Linux命令部分。时间:二零一六年九月二十五日配置:GTX 1070 cuda 8.0 Ubuntu 14.04 cudnn 5.1 te…

没GPU也能玩梵高作画:Ubuntu tensorflow CPU版

没GPU也能玩梵高作画:Ubuntu tensorflow CPU版 作者:七月在线开发/市场团队骁哲、李伟、July时间:二零一六年九月二十七日交流:TensorFlow实战交流Q群 472899334,有问题可以加此群共同交流。另探究实验背后原理&#x…

基于vgg19的梵高图像风格迁移

前言 大家好,我是阿光。 本专栏整理了《PyTorch深度学习项目实战100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPy…

我给梵高当Tony:这三款AI绘图工具,就离谱

来源:果壳 本文约2500字,建议阅读5分钟 AI生成图像完成,并不代表创意就结束了。 很多人说今年是“AI 绘画元年”。先是 Disco Diffusion 火出了圈,从 Text-to-Image(用文字生成图像)开发社区和创意设计行业…

8. 黑马旅游网——旅游线路的详情展示

目录 13. 旅游线路的详情展示13.1 分析13.2 代码实现13.2.1 后台代码13.2.2 前台代码 分类-分页-查询-详情展示功能源码: 链接:https://pan.baidu.com/s/1xzvE0GqfV_uo0j7NCzWRhQ 提取码:mxpw 复制这段内容后打开百度网盘手机App,…

web马尔代夫旅游网

下载链接:https://download.csdn.net/download/weixin_57836618/85196322 图片展示: 前端开发是创建WEB页面或APP等前端界面呈现给用户的过程,通过HTML,CSS及JavaScript以及衍生出来的各种技术、框架、解决方案,来实现…

html旅游旅行游记攻略网页源码

html旅游旅行游记攻略网页源码 项目共包含8个html页面全部展示见录屏以下是部分展示 首页效果&#xff1a; 首页代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <title>旅人网</title> <meta charset"utf-8"…

黑马旅游网站全记录

一、 项目导入 点击侧边的maven&#xff08;如果没有可以在view–>tool window 中找到&#xff09;&#xff0c;点击加号&#xff0c;选择文件中的pom.xml文档即可导入 首先预览一下静态页面 启动方式1&#xff1a; 启动方式2&#xff1a;添加启动方式&#xff0c;点击…

亚丁游记(下)-云南篇

第八天&#xff1a;稻城&#xff0d;中甸 今天要离开四川去云南中甸。一大早&#xff0c;前一天联系好的司机开车过来&#xff0c;发现和我们昨天看的车不一样&#xff0c;车顶没有行李架。小小的面包车刚够坐下人&#xff0c;我们那么多的行李怎么放啊&#xff01;wolf急忙…

黑马旅游网站

第一次写CSDN所以不太会&#xff01; 我接下来会记录这一段时间&#xff0c;完成黑马旅游网站的代码&#xff01;我们使用的是maven框架&#xff0c;原因很简单&#xff0c;因为黑马提供了大部分的数据跟我们&#xff0c;里面有数据库表&#xff0c;数据库网页整体的容&#xf…

新加坡圣淘沙亲子游自助游景点购票攻略

新加坡圣淘沙岛有很多适合家庭亲子游的景点和游乐园&#xff0c;无论是想要感受肾上腺飙升的游乐设施&#xff0c;体验虚拟世界的惊险刺激&#xff0c;与众多名人约会&#xff0c;还是探索海洋世界&#xff0c;这里总有你想要的。 新加坡环球影城 新加坡环球影城分为七个主题景…

三亚旅游攻略-自由人实用指南

三亚&#xff0c;是个被大自然宠坏了的地方。大自然把最宜人的气候、最清新的空气、最和煦的阳光、最湛蓝的海水、最柔和的沙滩、最风情万种的少数民族、最美味的海鲜…都赐予了这座海南岛最南端的海滨旅游城市。 虽然三亚自古以来是贬官谪宦流放之地&#xff0c;可这段悲怆的历…