NOTE本篇博客的大量图片来自3Blue1Brown,你可以点击这个链接找到他们的B站官方账号
谈及AI,我们现在大概率会直接想到大模型。诚然,大模型背后的庞大参数量和实现原理固然令人赞叹,但追本溯源我们会发现这些庞然大物的根基仍然是我们熟知的那个概念——神经网络。本篇作为“模型考古学”系列的第一篇,我会从神经网络的结构开始,一步步探寻大模型背后的奥秘。
机器学习的迷人之处在于,它赋予了机器“学习”的能力,而不再需要我们在代码中事无巨细地规定任务的执行步骤。这与 AI 发展初期的思路截然不同,那时,我们需要为每个特定任务编写明确的指令。如今,我们更倾向于构建一种通用的、具有可调参数的灵活架构,然后利用大量的样本数据(即输入与期望输出的对应关系)去训练这个架构。通过不断调整参数,模型逐渐学会模仿数据中蕴含的规律。以最简单的线性回归为例,我们输入房屋面积,期望得到预测的价格,这中间只需找到一条最佳拟合线——它由斜率和截距这两个关键参数定义。通过优化这些参数,我们就能让这条直线最大程度地贴合已知的房屋面积与价格数据,从而预测未来的房价。而这,仅仅是机器学习的冰山一角。
一个更容易理解的说法是:我们不直接告诉机器怎么做,而是搭建一个灵活的“大脑”——神经网络,然后给它看海量的“例子”,比如“这个面积的房子大概值多少钱”。机器“看”多了,自己就能琢磨出规律,慢慢地,它就能根据输入的面积,猜出个八九不离十的价格。这就像我们小时候学东西,不是靠死记硬背公式,而是通过不断的观察和练习,学会举一反三。从最简单的线性回归,到如今火爆的各种深度学习模型,背后的原理其实都一样:用数据训练模型,让模型自己找到最佳答案。
一、从神经网络结构开始说起
1.基本结构
顾名思义,神经网络之名来源自人的大脑结构,神经网络里的神经元(Neuron)也可以对应我们大脑中的神经。在大脑中,一个神经元通常有多个树突用于接收信号,一个轴突用于发送信号。神经元会通过突触与其他神经元进行连接,并根据接收信号的总和决定其激活状态,就像一个生物版本的逻辑门。神经元之间连接的强弱会在学习过程中不断发生改变,进而影响信息处理的方式,这便是我们学习和记忆的基础。
人工神经网络中的神经元模型 正是对生物神经元的简化模拟。一个典型的人工神经元模型,例如经典的 McCulloch-Pitts (M-P) 模型,也拥有类似的功能结构。它接收来自其他神经元或外部输入的信号,每个输入信号都乘以一个对应的 权重(weight) ,这些加权后的信号在神经元内部进行 求和(summation) ,然后将总和与一个 阈值(threshold) 进行比较。如果总和超过了阈值,神经元就会被激活,并通过 激活函数(activation function) 产生一个输出信号;否则,神经元则保持静默。
这个简单的数学模型,虽然看起来和我们生物体内的神经元相去甚远,却奠定了整个神经网络大厦的基石。我们可以将激活函数理解为对神经元是否“兴奋”的判定,不同的激活函数,例如阶跃函数、Sigmoid 函数、ReLU 函数等,都扮演着将神经元输入转化为输出的角色,同时也为神经网络引入了非线性,使其能够处理更复杂的任务。
从单个神经元到神经网络, 我们可以将多个神经元按照一定的层次结构连接起来,形成神经网络。最简单的结构便是 前馈神经网络(Feedforward Neural Network) ,其中神经元分层排列,信号只能从前一层单向传递到后一层,层内神经元之间没有连接。
在这种网络结构中,第一层被称为 输入层(Input Layer) ,负责接收外部输入的数据;最后一层被称为 输出层(Output Layer) ,负责输出网络的计算结果;中间的层被称为 隐藏层(Hidden Layer) ,隐藏层的层数和每层的神经元数量可以根据任务的复杂程度进行调整。
我们可以把神经元看做是一个函数(Function),它输入的是上一层所有神经元的输出,而它的输出是一个0到1之间的值。其实整个神经网络就是一个函数,在上图中是一个输入784个值(因为图片的像素是28*28),输出10个值(因为输出的是十个数字的概率)的函数。不过这个函数极其的复杂,它用了13002个权重参数偏置函数来识别特殊图案,当然这个函数要是不复杂的话我们又怎么能放心的用它来识别数字了呢()
那么,我们的神经网络是如何处理这项艰巨任务的,神经网络又是如何通过数据来获得合适的权重和偏置的?答案是 反向传播算法(Backpropagation)。
NOTE我们想要这么一种算法,你可以给这个网络看一大堆训练数据,其中包括一堆不同的手写数字图像,以及它们代表哪个数字的标记,算法会调整这13000个权重和偏置值,以提高网络对训练数据的表现。我们希望这种分层结构可以让它举一反三,识别训练数据之外的图像。训练好网络后,我们会给它更多以前从未见过的带标记的数据作为测试,你就可以看到这个模型对新图像进行分类的准确度。
2.反向传播算法
反向传播算法 可以说是神经网络的灵魂所在,它的核心思想可以概括为:计算损失,反向传播,更新权重 。
(1)、计算损失(Loss Calculation):
首先,我们需要一个衡量神经网络当前输出与期望输出之间差距的指标,这就是 损失函数(Loss Function) 。例如,在手写数字识别任务中,如果我们输入一张数字“2”的图片,期望的输出是“[0, 0, 1, 0, 0, 0, 0, 0, 0, 0]”,而神经网络实际输出的是“[0.1, 0.2, 0.5, 0.05, 0.02, 0.03, 0.01, 0.02, 0.05, 0.02]”,那么我们就需要一个损失函数来计算这两个向量之间的差异。常用的损失函数包括均方误差(Mean Squared Error, MSE)、交叉熵损失(Cross-Entropy Loss)等。损失函数的值越大,表示网络的输出与期望输出的差距越大,网络的性能越差。
(2)、反向传播(Backpropagation)
这一步是反向传播算法的精髓所在。它利用 链式法则(Chain Rule) ,从输出层开始,逐层计算每个权重对最终损失的 梯度(Gradient) 。可以把梯度理解为“权重对损失的影响程度”,它是一个向量,指明了损失函数在当前权重值下,沿着哪个方向变化最快,以及变化的速率。
让我们用一个简化的例子来说明:假设输出层的某个神经元 j 的输出值为 ,它与期望输出 之间的误差为 (假设使用 MSE 作为损失函数,则 )。神经元 j 的输出 是由上一层神经元 i 的输出 经过加权求和并经过激活函数得到的,即 ,其中 是神经元 i 到神经元 j 的权重, 是神经元 j 的偏置。
现在,我们想要知道权重 对误差 的影响,即 。根据链式法则,我们可以将这个偏导数分解为:
其中 。
- 表示误差对神经元 j 输出的变化率,可以直接根据损失函数的定义计算得出。
- 表示神经元 j 的输出对其加权输入和的变化率,这取决于激活函数的导数。
- 表示神经元 j 的加权输入和对权重 的变化率,这个值恰好等于 。
通过这种方式,我们可以计算出输出层每个权重对损失的梯度。然后,我们可以将误差信号继续向后传播,计算隐藏层每个权重对损失的梯度。这个过程一直持续到输入层,所有权重的梯度都被计算出来。
(3)、更新权重(Weight Update):
得到每个权重的梯度后,我们就需要根据梯度来更新权重。更新的原则是:**沿着梯度的反方向调整权重,因为梯度的反方向是损失函数下降最快的方向,**常用的权重更新方法是 梯度下降法(Gradient Descent)。
总结来说,反向传播算法通过计算损失函数对每个权重的梯度,并根据梯度来更新权重,从而使得网络的输出逐渐逼近期望输出。这个过程不断迭代进行,直到网络的损失降到足够小,或者达到预设的训练轮数。
通过反向传播算法,神经网络可以从大量的训练数据中学习到合适的权重和偏置,从而具备强大的模式识别和预测能力。而大模型,则是在此基础上,通过增加网络的深度和宽度,使用更复杂的网络结构和训练技巧,进一步提升了模型的性能和泛化能力。
2.梯度下降法
梯度下降法(Gradient Descent) 是一种广泛应用于机器学习,尤其是神经网络训练中的一阶迭代优化算法。其核心思想是,通过迭代地沿着损失函数梯度的反方向来更新模型参数(例如神经网络中的权重和偏置),从而逐步逼近损失函数的最小值,最终找到模型的最优参数。
(1)、梯度的含义回顾
在深入了解梯度下降法之前,让我们再次回顾一下梯度的概念。梯度是一个向量,它指向函数在某一点处变化最快的方向,并且其大小表示函数在该方向上的变化率。对于一个多元函数,其梯度由各个自变量的偏导数组成。在神经网络中,我们关注的是损失函数关于各个权重和偏置的梯度。
想象一下你站在一座山上,目标是走到山谷的最低点。你环顾四周,找到了最陡峭的下坡方向(梯度反方向),然后迈出了一小步。接着你再次观察周围环境,找到新的最陡峭下坡方向,然后又迈出了一小步。重复这个过程,你最终将到达山谷的最低点。这就是梯度下降法的直观体现。
(2)、数学描述
假设我们有一个损失函数 ,其中 是一个向量,表示模型的所有参数(权重和偏置)。梯度下降法的目标是找到一组 ,使得 最小化。
梯度下降法的更新规则如下:
其中:
- 表示第 次迭代时的参数值。
- 表示第 次迭代时的参数值。
- 是学习率(Learning Rate),一个正数,控制每次迭代的步长。
- 表示损失函数 在 处的梯度。
(3)、计算步骤
1.初始化参数: 随机初始化模型参数 。 2.计算梯度: 使用反向传播算法(或其他方法)计算损失函数 关于当前参数 的梯度 。 3.更新参数: 按照上述更新规则,使用梯度和学习率来更新参数 。 4. 重复步骤 2 和 3: 不断迭代,直到满足停止条件。常见的停止条件包括: - 达到预设的最大迭代次数。 - 损失函数的值变化小于某个阈值。 - 梯度的模长小于某个阈值。
(4)、学习率
学习率 η
是梯度下降法中一个至关重要的超参数。它决定了每次参数更新的步长。
- 学习率过大: 可能导致参数更新过猛,越过最小值,甚至导致损失函数发散,无法收敛。就像你在下山时步子迈得太大,可能会直接跳过山谷,甚至跑到另一座山上。
- 学习率过小: 会导致参数更新缓慢,训练过程耗时过长。就像你下山时步子迈得太小,可能需要很长时间才能到达山谷。
- 合适的学习率: 使得参数能够平稳地接近最小值,并在最小值附近震荡,最终收敛到最小值。
(5)、梯度下降法的变体
为了提高梯度下降法的效率和稳定性,研究者们提出了许多变体,常见的包括:
- 批量梯度下降法(Batch Gradient Descent, BGD): 每次迭代使用 所有 训练样本来计算梯度。优点是每次更新都朝着全局最优方向前进,缺点是计算量大,训练速度慢,尤其是对于大规模数据集。
- 随机梯度下降法(Stochastic Gradient Descent, SGD): 每次迭代 随机选择一个 训练样本来计算梯度。优点是计算速度快,尤其适合大规模数据集;缺点是由于每次只使用一个样本,更新方向可能不稳定,存在较大噪声,但从期望来看,它是沿着正确的方向的。
- 小批量梯度下降法(Mini-Batch Gradient Descent, MBGD): 每次迭代使用 一部分(一个 mini-batch) 训练样本来计算梯度。这是 BGD 和 SGD 的折中方案,既能加快训练速度,又能提高稳定性,是目前最常用的梯度下降法变体。
当然,梯度下降法也会有其局限性。例如其可能会陷入局部最小值,而无法达到全局最小值,尤其是对于非凸函数。就比如我们在下山时可能会到达一个小的山谷,但这个山谷并不是整座山的最低点。梯度下降法在鞍点处可能会停滞不前,因为鞍点处的梯度为零。鞍点是一个既不是局部最小值也不是局部最大值的点,就像马鞍的中心点一样。最后,学习率的选择对于训练结果的影响很大,需要按照实际经验来一点点调整。
二、大模型的架构解析
目前,绝大多数主流的大语言模型都基于 Transformer 架构。Transformer 架构最初是在 2017 年的论文 “Attention is All You Need” 中提出的,它彻底改变了自然语言处理领域。
为什么Transformer如此重要?
- 并行化处理:因为相较于之前的循环神经网络(RNN)和长短期记忆网络(LSTM),Transformer 能够并行处理输入序列中的所有词,大大提高了训练效率。
- 注意力机制: Transformer 的核心是注意力机制(Attention Mechanism),它允许模型关注输入序列中不同词之间的关系,并根据这些关系动态调整每个词的权重,从而更好地理解上下文信息。
- 长距离依赖:Transformer 能够有效地捕捉长距离依赖关系,这对于理解复杂的语言结构至关重要。
1.组成架构
(1)、嵌入层
在输入到 Transformer 之前,输入序列中的每个词都需要被转换成一个向量表示,这个过程称为 词嵌入 (Word Embedding)。嵌入层负责将每个词映射到一个固定维度的向量,这个向量能够表示该词的语义信息。
- 常用的词嵌入方法: Word2Vec, GloVe, FastText 等。
- 子词嵌入 (Subword Embedding): 为了解决未登录词 (Out-of-Vocabulary, OOV) 问题,现代 LLM 通常使用子词嵌入,例如 字节对编码 (Byte Pair Encoding, BPE) 或 WordPiece。这些方法将词分解成更小的子词单元,并为每个子词单元学习一个向量表示。
NOTE嵌入层之后就是我们的 Transformer 了,一个典型的 Transformer 模型由两个主要部分组成:编码器 (Encoder) 和 解码器 (Decoder)。
(2)、Encoder 编码器
编码器的作用是将输入序列(例如一句话)转换成一个包含丰富语义信息的向量表示,称为 上下文向量 (Context Vector) 或 隐藏状态 (Hidden State)。
我们的Encoder编码器通常由多个相同的编码器层(Encoder Layer)堆叠而成,而每个编码器层又包含两个主要子层:
- 自注意力层 (Self-Attention Layer): 这是 Transformer 的核心。自注意力机制允许模型关注输入序列中每个词与其他所有词之间的关系,并计算出一个权重矩阵,表示每个词对其他词的重要性。通过这种方式,模型可以理解每个词在句子中的上下文含义。
- 计算过程: 自注意力层会为输入序列中的每个词计算三个向量:查询向量 (Query)、键向量 (Key) 和 值向量 (Value)。然后,通过计算查询向量和键向量的点积来衡量每个词之间的相关性,并使用 Softmax 函数将这些相关性分数归一化为权重。最后,将这些权重与相应的值向量相乘并求和,得到每个词的上下文表示。
- 多头注意力 (Multi-Head Attention): 为了捕捉更丰富的语义信息,通常会使用多头注意力机制。它将输入序列映射到多个不同的表示空间,并在每个空间中独立地计算自注意力,最后将所有头的输出拼接起来。
- 前馈神经网络层 (Feed-Forward Network Layer): 这是一个简单的全连接神经网络,对自注意力层的输出进行进一步的非线性变换,增强模型的表达能力。
(3)、Decoder 解码器
解码器的作用是根据编码器输出的上下文向量生成目标序列(例如翻译后的句子)。
与编码器类似,解码器也由多个相同的 解码器层 (Decoder Layer) 堆叠而成。每个解码器层包含三个主要子层:
- 自注意力层 (Self-Attention Layer): 与编码器中的自注意力层类似,但解码器中的自注意力层只能关注到当前词和之前的词,这是为了防止模型在生成当前词时“偷看”到未来的信息,这被称为 掩码自注意力 (Masked Self-Attention)。
- 编码器-解码器注意力层 (Encoder-Decoder Attention Layer): 这个子层允许解码器关注编码器输出的上下文向量。解码器中的每个词都会计算一个查询向量,并与编码器输出的所有键向量和值向量进行交互,从而获取与当前生成任务相关的上下文信息。
- 前馈神经网络层 (Feed-Forward Network Layer): 与编码器中的前馈神经网络层类似,对注意力层的输出进行非线性变换。
(4)、Output Layer 输出层
解码器的最后一层输出一个向量,这个向量的维度与词汇表大小相同。然后,通过一个 Softmax 函数将这个向量转换成一个概率分布,表示每个词作为下一个词的概率。
2.为什么大模型如此之大?
在之前的讨论中,我们了解了神经网络的基础:反向传播和梯度下降,也领略了 Transformer 架构的精妙。现在,一个自然而然的问题浮现在我们脑海:为什么现在的大语言模型(LLM)都如此庞大?动辄数十亿、上千亿甚至上万亿的参数,究竟这些庞大的模型是如何炼成的,海量的训练数据又被模型“消化”到哪里去了呢?
(1)、大模型的“大”体现在哪里:
大模型的“大”,直观上体现在两个方面:
- 模型参数量巨大: 正如前面提到的,GPT-3 的参数量达到了 1750 亿,而后续的 PaLM、Gopher 等模型更是将参数量推向了新的高度。这些参数主要指的是模型中神经元之间的连接权重和偏置,每一个参数都是一个需要通过训练来确定的数值。
- 训练数据量庞大: 大模型的训练离不开海量的数据。GPT-3 使用了约 45TB 的压缩文本数据,而其他大模型使用的训练数据量也都在数百 GB 到数 TB 的级别。这些数据通常来源于互联网、书籍、论文等各种来源,涵盖了各种各样的主题和语言风格。
(2)、为什么要这么大?
简而言之,更大的模型和更多的数据通常意味着更强的能力和更好的泛化性能。 这背后的原因可以从以下几个方面来理解:
- 更强的模式识别能力: 大模型拥有更多的参数,这意味着它拥有更复杂的内部结构和更强大的非线性拟合能力。这使得它能够捕捉到训练数据中更细微、更复杂的模式和规律。如果把模型比作一个函数,那么更多的参数就意味着这个函数可以拥有更复杂的形态,从而更好地逼近真实世界中各种复杂的现象。
- 更好的泛化能力: 泛化能力是指模型在面对从未见过的数据时的表现。大模型通常拥有更好的泛化能力,因为它们在训练过程中见过了更多的数据,学习到了更普遍性的规律,而不是仅仅记住了训练数据中的特定例子。这就像一个学生,如果他只做了几道练习题,那么他可能只会做这几道题,但如果他做了大量的练习题,那么他就更有可能掌握解题的普遍方法,从而能够解决各种各样的新题目。
- 更丰富的知识表示: 大模型可以看作是一个巨大的知识库,它将海量的训练数据中蕴含的信息压缩并存储在其参数中。模型参数越多,这个知识库的容量就越大,能够存储的信息就越丰富。当模型遇到新的任务或问题时,它可以从这个知识库中检索相关的信息,并利用这些信息来生成答案或执行任务。
(3)、海量的训练数据都去哪了?
那么,如此庞大的训练数据,在训练完成后都去哪里了呢?它们并没有以原始的形式存储在模型中,而是被模型“消化吸收”,转化成了模型的参数(权重和偏置)。
我们可以将模型的训练过程类比为“读书学习”。当我们阅读一本书时,我们并不会把书中的每一个字都一字不差地记住,而是会理解书中的内容,并将这些内容提炼成我们自己的知识,存储在我们的记忆中。类似地,模型在训练过程中,会不断地调整自己的参数,使得模型的输出能够更好地匹配训练数据。这个过程实际上就是将训练数据中的信息压缩并编码到模型参数中的过程。
具体来说,训练数据通过以下方式影响模型的参数:
- 梯度下降: 在训练过程中,模型会计算损失函数关于每个参数的梯度,并根据梯度来更新参数。训练数据决定了损失函数的具体形式,从而影响了梯度的计算,最终影响了参数的更新方向和幅度。
- 参数的最终值: 经过大量的迭代训练后,模型的参数会收敛到一个特定的值,这些值就是模型从训练数据中学到的知识的体现。不同的训练数据会导致不同的参数值,从而使得模型表现出不同的行为和能力。
可以这样理解:训练数据塑造了模型的参数,而模型的参数则承载了模型从训练数据中学到的知识。
(4)、这些知识都是如何储存的?
需要注意的是,模型对知识的存储方式与人类的记忆机制有很大的不同。人类的记忆是显式的,我们可以清晰地回忆起具体的事件和知识。而模型的“知识”是隐式地分布在其所有的参数中,我们很难从某个具体的参数值中解读出模型学到了什么具体的知识。
这就像一个黑盒,我们知道输入(训练数据)和输出(模型预测),但我们很难理解中间的“知识”是如何被表示和存储的。 这也是目前深度学习领域的一个重要的研究方向:可解释性。
3.大语言模型(LLM)架构的发展历程
基于 Transformer 架构,目前主要有三种主流的 LLM 架构:
- 仅编码器模型 (Encoder-only Models): 例如 BERT、RoBERTa。这类模型只使用 Transformer 的编码器部分,擅长于理解语言,常用于文本分类、情感分析、命名实体识别等任务。它们通常通过 预训练 (Pre-training) 和 微调 (Fine-tuning) 的方式进行训练。
- 预训练: 在大规模无标注文本数据上进行预训练,学习通用的语言表示。常用的预训练任务包括 掩码语言模型 (Masked Language Modeling, MLM) 和 下一句预测 (Next Sentence Prediction, NSP)。
- 微调: 在特定任务的标注数据集上进行微调,将预训练学到的通用语言表示适配到具体任务。
- 仅解码器模型 (Decoder-only Models): 例如 GPT 系列 (GPT-1, GPT-2, GPT-3, GPT-4)。这类模型只使用 Transformer 的解码器部分,擅长于生成文本,常用于文本生成、对话系统、机器翻译等任务。它们通常通过 自回归 (Autoregressive) 的方式进行训练,即根据前面已生成的词来预测下一个词。
- 编码器-解码器模型 (Encoder-Decoder Models): 例如 BART、T5。这类模型同时使用 Transformer 的编码器和解码器部分,兼具理解和生成能力,常用于机器翻译、文本摘要等任务。
在大模型发展的早期阶段,encoder-only和encoder-decoder模型更受欢迎,但随着 2021 年 GPT-3 的横空出世,decoder-only 模型完成了一次漂亮的翻身仗。在 BERT 带来的最初爆炸性增长之后,encoder-only 模型逐渐开始失宠。
Encoder-Decoder or Encoder-only (BERT-style) | Decoder-only (GPT-style) | |
---|---|---|
训练方式 | Masked Language Models(遮盖某些单词) | Autoregressive Language Models(自回归) |
模型类型 | (Discriminative)判别式 | (Generative)生成式 |
预训练任务 | 预测遮掩掉的单词(完形填空) | 预测下一个单词 |
对应模型 | ELMo , BERT , RoBERTa , DistilBERT , BioBERT , XLM , Xlnet , ALBERT , ELECTRA , T5 , GLM , XLM-E , ST-MoE , AlexaTM | GPT 3/4 , OPT . PaLM , BLOOM , MT-NLG , GLaM ,Gopher , chinchilla , LaMDA , GPT-J , LLaMA , BloombergGPT |
(1)、BERT风格语言模型:encoder-decoder 或 encoder-only
因为自然语言数据在前大模型时代还是很容易获取的,为了更好的利用这些超级数据集,人们提出了很多无监督训练的方式。这其中一种很常见的方法就是在给定上下文的情况下,预测句子中掩盖(masked)掉的单词,这种训练范式被称为 Masked Language Model (MLM)。
典型模型包括
- BERT
- RoBERTa
- T5
这种模型在许多 NLP 任务(如情感分析和 named entity 识别)中取得了 state-of-the-art 的结果, 已经成为自然语言处理领域的重要工具。
(2)、GPT风格语言模型:decoder-only
尽管语言模型通常在架构上是任务无关的,但都需要在特定下游任务的数据集上进行微调。
研究人员发现,扩展语言模型的参数规模(scaling up) 能显著提高少样本(few-shot)甚至零样本(zero-shot)性能。 少样本和零样本最成功的模型是自回归语言模型(Autoregressive Language Models,ALM)。
- 这些模型的训练方式:给出前面的单词,生成这句话的下一个单词。
- 这些模型已被广泛用于文本生成和问题回答等 NLP 任务。
典型的自回归语言模型包括,
- GPT-3
- OPT
- PaLM
- BLOOM
这其中,GPT-3 是一个划时代的模型,它首次通过提示(prompting)和上下文学习(in-context learning) 展示了少样本/零样本也能取得不错的性能,展现了自回归语言模型的优越性。
还有一些模型针对特定任务进行了优化,如
- CodeX :代码生成
- BloombergGPT :金融领域
最近的突破是 ChatGPT,它专门针对对话任务优化了 GPT-3,从而在各种实际应用中 互动性、连贯性,以及更好的上下文理解能力。
参考文献
[1] Vaswani A. Attention is all you need[J]. Advances in Neural Information Processing Systems, 2017.
[2] Yang J, Jin H, Tang R, et al. Harnessing the power of llms in practice: A survey on chatgpt and beyond[J]. ACM Transactions on Knowledge Discovery from Data, 2024, 18(6): 1-32.