模型的可视化指南 

174 阅读23分钟

Transformer 架构一直是大型语言模型 (LLMs。它已被用于当今使用的几乎所有 LLMs,从 Mistral 等开源模型到 ChatGPT 等闭源模型。

为了进一步改进 LLMs,开发了甚至可能优于 Transformer 架构的新架构。其中一种方法是 Mamba,一种_状态空间模型_。

[

](substackcdn.com/image/fetch…)

Mamba 是在论文 Mamba: Linear-Time Sequence Modeling with Selective State Spaces 中提出的。1 您可以在其存储库中找到其官方 implementation 和 model checkpoints

_
要查看目录 (ToC),请单击左侧的行堆栈。_

在这篇文章中,我将在语言建模的背景下介绍状态空间模型领域,并逐一探索概念,以形成对该领域的直觉。然后,我们将介绍 Mamba 如何挑战 Transformers 架构。

在本视觉指南中,有 50 多个自定义视觉对象可帮助您深入了解 Mamba 和 State Space 模型!

要查看与 LLMs效果并支持此新闻通讯,请查看我写的关于大型语言模型的书!

[

](substackcdn.com/image/fetch…)

该书的官方网站。您可以在亚马逊上订购这本书。所有代码都上传到 GitHub.

_
附言如果你读了这本书,**快速回顾**就会意味着全世界——它真的对我们作者有帮助!_

为了说明为什么 Mamba 是一个如此有趣的架构,让我们先对 transformer 做一个简短的回顾,并探讨它的缺点之一。

Transformer 将任何文本 input 视为 由_标记_组成的_序列_。

[

](substackcdn.com/image/fetch…)

Transformers 的一个主要好处是,无论它接收到什么 Importing,它都可以回溯查看序列中的任何早期 Token 以得出其表示。

[

](substackcdn.com/image/fetch…)

请记住,Transformer 由两个结构组成,一组用于表示文本的编码器块和一组用于生成文本的解码器块。这些结构一起可用于多项任务,包括翻译。

[

](substackcdn.com/image/fetch…)

我们可以采用这种结构,只使用解码器来创建生成模型。这个基于 Transformer 的模型 Generative Pre-trained Transformers (GPT) 使用解码器模块来完成一些输入文本。

[

](substackcdn.com/image/fetch…)

让我们来看看它是如何工作的!

单个解码器模块由两个主要组件组成,掩码自注意力和前馈神经网络。

[

](substackcdn.com/image/fetch…)

自我关注是这些模型如此有效的主要原因。它可以通过快速训练实现整个序列的未压缩视图。

那么它是如何工作的呢?

它创建一个矩阵,将每个标记与之前的每个标记进行比较。矩阵中的权重由标记对彼此之间的相关性决定。

[

](substackcdn.com/image/fetch…)

在训练期间,此矩阵是一次性创建的。在计算 “name” 和 “is” 之间的 attention 之前,不需要先计算 “my” 和 “name” 之间的关注度。

它支持并行化,从而极大地加快了训练速度!

然而,存在一个缺陷。在生成下一个 Token 时,我们需要重新计算_整个序列_的 attention ,即使我们已经生成了一些 token。

[

](substackcdn.com/image/fetch…)

为长度为 L 的序列生成标记 大约需要 计算,如果序列长度增加,这可能会很昂贵。

[

](substackcdn.com/image/fetch…)

这种重新计算整个序列的需求是 Transformer 架构的一个主要瓶颈。

让我们看看一种 “经典” 技术 Recurrent Neural Networks 如何解决这个缓慢推理的问题。

递归神经网络 (RNN) 是一种基于序列的网络。序列中的每个时间步都需要两个输入,即时间步 t 的输入和前一个时间步 t-1 的隐藏状态,以生成下一个隐藏状态并预测输出。

RNN 具有循环机制,允许它们将信息从上一步传递到下一步。我们可以 “展开” 这个可视化,使其更加明确。

[

](substackcdn.com/image/fetch…)

在生成 output 时,RNN 只需要考虑之前的 hidden state 和当前 input。它可以防止重新计算所有以前的隐藏状态,而 Transformer 就是这样做的。

换句话说,RNN 可以快速进行推理,因为它与序列长度呈线性关系缩放!理论上,它甚至可以具有_无限的上下文长度_。

为了说明这一点,让我们将 RNN 应用于我们之前使用的输入文本。

[

](substackcdn.com/image/fetch…)

每个隐藏状态都是所有先前隐藏状态的聚合,通常是一个压缩视图。

然而,有一个问题......

请注意,生成名称 “Maarten” 时的最后一个隐藏状态不再包含有关单词 “Hello” 的信息。随着时间的推移,RNN 往往会忘记信息,因为它们只考虑一个以前的状态。

尽管 RNN 对于训练和推理来说都很快,但它们缺乏 Transformer 模型所能提供的准确性。

相反,我们着眼于状态空间模型,以有效地使用 RNN(有时使用卷积)。

状态空间模型 (SSM) 与 Transformer 和 RNN 一样,处理信息序列,如文本和信号。在本节中,我们将介绍 SSM 的基础知识以及它们与文本数据的关系。

状态空间包含完全描述系统的最少数量的变量。这是一种通过定义系统的可能状态来数学表示问题的方法。

让我们稍微简化一下。想象一下,我们正在穿过一个迷宫。“状态空间” 是所有可能的位置(状态)的地图。每个点代表迷宫中的一个独特位置,具有特定的详细信息,例如您离出口有多远。

state space representation” 是此映射的简化描述。它显示你在哪里 (当前状态),你可以去哪里 (可能的未来状态),以及哪些变化会把你带到下一个状态 (向右或向左)。

[

](substackcdn.com/image/fetch…)

尽管状态空间模型使用方程和矩阵来跟踪此行为,但它只是一种跟踪您所在位置、可以到达何处以及如何到达那里的方法。

描述状态的变量,在我们的示例中是 X 和 Y 坐标,以及到出口的距离,可以表示为 “状态向量”。

[

](substackcdn.com/image/fetch…)

听起来很熟悉?这是因为语言模型中的嵌入或向量也经常用于描述输入序列的 “状态”。例如,您当前位置的 vector (state vector) 可能看起来有点像这样:

[

](substackcdn.com/image/fetch…)

就神经网络而言,系统的 “状态” 通常是其隐藏状态,在大型语言模型的上下文中,这是生成新令牌的最重要方面之一。

SSM 是用于描述这些状态表示的模型,并根据某些输入预测它们的下一个状态可能是什么。

传统上,在时间 t,SSM :

  • 映射输入序列 x(t) — (例如,在迷宫中向左和向下移动)

  • 到潜在状态表示 h(t) — (例如,到 Exit 的距离和 x/y 坐标)

  • 并推导出预测的输出序列 y(t) — (例如,再次向左移动以更快地到达出口)

但是,它不是使用_离散__序列_(如向左移动一次),而是将_连续__序列_作为输入并预测输出序列。

[

](substackcdn.com/image/fetch…)

SSM 假设动态系统(例如在 3D 空间中移动的物体)可以通过两个方程从其在时间 t 的状态中预测 。

[

](substackcdn.com/image/fetch…)

通过求解这些方程,我们假设我们可以揭示统计原理,根据观察到的数据(输入序列和先前状态)预测系统的状态。

它的目标是找到这个状态表示 _h(t),_这样我们就可以从 input 转到 output 序列。

[

](substackcdn.com/image/fetch…)

这两个方程是 State Space Model 的核心。

本指南中将引用这两个方程。为了使它们更直观,它们采用颜色编码,以便您可以快速引用它们。

状态方程根据输入对状态的影响(通过_矩阵 B_)描述状态如何变化(通过_矩阵 A_)。

[

](substackcdn.com/image/fetch…)

正如我们之前看到的,h(t) 指的是我们在任何给定时间 t 的潜伏状态表示,而 x(t) 指的是一些输入。

输出方程描述了状态如何转换为输出(通过_矩阵 C_)以及输入如何影响输出(通过_矩阵 D_)。

[

](substackcdn.com/image/fetch…)

注意:矩阵 ABCD 通常也被称为_参数_,因为它们是可学习的。

将这两个方程可视化,得到以下架构:

[

](substackcdn.com/image/fetch…)

让我们逐步了解通用技术,以了解这些矩阵如何影响学习过程。

假设我们有一些输入信号 _x(t),这个信号首先乘以_矩阵 B,它描述了输入如何影响系统。

[

](substackcdn.com/image/fetch…)

更新状态(类似于神经网络的隐藏状态)是一个包含环境核心“知识”的潜在空间。我们将状态与_矩阵 A_ 相乘,矩阵 A 描述了所有内部状态是如何连接的,因为它们代表了系统的基本动态。

[

](substackcdn.com/image/fetch…)

您可能已经注意到,矩阵 A 在创建状态表示之前应用,并在状态表示更新之后更新。

然后,我们使用_矩阵 C_ 来描述如何将状态转换为输出。

[

](substackcdn.com/image/fetch…)

最后,我们可以使用_矩阵 D_ 提供从输入到输出的直接信号。这通常也称为 skip-connection

[

](substackcdn.com/image/fetch…)

由于_矩阵 D_ 类似于 skip-connection,因此 SSM 通常被视为没有 skip-connection 的 following。

[

](substackcdn.com/image/fetch…)

回到我们的简化视角,我们现在可以关注矩阵 ABC 作为 SSM 的核心。

[

](substackcdn.com/image/fetch…)

我们可以像以前一样更新原始方程(并添加一些漂亮的颜色)来表示每个矩阵的用途。

[

](substackcdn.com/image/fetch…)

这两个方程总之旨在从观察到的数据中预测系统的状态。由于输入预期是连续的,因此 SSM 的主要表示形式是连续时间表示形式。

如果你有一个连续信号,找到状态表示 h(t) 在分析上是具有挑战性的。此外,由于我们通常有一个离散的输入(如文本序列),因此我们希望将模型离散化。

为此,我们使用 Zero-order hold 技术。 它的工作原理如下。首先,每次我们接收到一个离散信号时,我们都会保持它的值,直到我们接收到一个新的离散信号。此过程会创建一个 SSM 可以使用的连续信号:

[

](substackcdn.com/image/fetch…)

我们保持该值的时间由一个新的可学习参数表示,称为 step size。它表示输入的分辨率。

现在我们有一个 continuous 信号作为我们的输入,我们可以生成一个 continuous output,并且只根据 input 的时间步长对值进行采样。

[

](substackcdn.com/image/fetch…)

这些采样值就是我们的离散化输出!

在数学上,我们可以按如下方式应用 Zero-order hold:

[

](substackcdn.com/image/fetch…)

总之,它们使我们能够从一个连续的 SSM 变成一个离散的 SSM,该公式由一个公式表示,该公式不是_函数到函数_ x(t) → _y(t),而是一个_序列到序列 x kyk

[

](substackcdn.com/image/fetch…)

在这里,矩阵 AB 现在表示模型的离散化参数。

我们使用 k 而不是 t 来表示离散化的时间步长,并在我们提到连续 SSM 与离散 SSM 时更加清晰。

**注意:**在训练期间,我们仍然保存_矩阵 A_ 的连续形式,而不是离散化版本。在训练期间,连续表示是离散的。

现在我们有了离散表示的公式,让我们探索一下如何实际_计算_模型。

我们的离散 SSM 允许我们以特定的时间步长而不是连续信号来表述问题。正如我们之前看到的 RNN 一样,递归方法在这里非常有用。

如果我们考虑离散时间步长而不是连续信号,我们可以用时间步长重新表述问题:

[

](substackcdn.com/image/fetch…)

在每个时间步长,我们计算电流输入 (Bxk) 如何影响先前的状态 (Ahk₋₁),然后计算预测输出 (Chk)。

[

](substackcdn.com/image/fetch…)

这种表示形式可能看起来有点熟悉!我们可以像以前看到的一样处理 RNN。

[

](substackcdn.com/image/fetch…)

我们可以展开(或展开)如下:

[

](substackcdn.com/image/fetch…)

请注意我们如何使用 RNN 的底层方法来使用这个离散化版本。

我们可以用于 SSM 的另一种表示形式是卷积的表示形式。请记住,在经典的图像识别任务中,我们应用了过滤器(内核)来派生聚合特征:

[

](substackcdn.com/image/fetch…)

由于我们处理的是文本而不是图像,因此我们需要一维透视:

[

](substackcdn.com/image/fetch…)

我们用来表示此 “filter” 的内核源自 SSM 公式:

[

](substackcdn.com/image/fetch…)

让我们来探索一下这个内核在实践中是如何工作的。与卷积一样,我们可以使用 SSM 内核来检查每组 tokens 并计算输出:

[

](substackcdn.com/image/fetch…)

这也说明了 padding 可能对输出产生的影响。我更改了填充的顺序以改善可视化效果,但我们经常将其应用于句子末尾。

在下一步中,将 kernel 移动一次以执行计算的下一步:

[

](substackcdn.com/image/fetch…)

在最后一步中,我们可以看到 kernel 的全部效果:

[

](substackcdn.com/image/fetch…)

将 SSM 表示为卷积的一个主要好处是,它可以像卷积神经网络 (CNN) 一样进行并行训练。然而,由于内核大小固定,它们的推理不如 RNN 快速且不受限制。

这三种表示形式(_连续、_循环_和_卷积)都有不同的优点和缺点:

[

](substackcdn.com/image/fetch…)

有趣的是,我们现在可以使用递归 SSM 进行高效推理,并使用卷积 SSM 进行可并行化训练。

有了这些表示,我们可以使用一个巧妙的技巧,即根据任务选择一种表示。在训练过程中,我们使用可以并行化的卷积表示,在推理过程中,我们使用高效的递归表示:

[

](substackcdn.com/image/fetch…)

此模型称为线性状态空间层 (LSSL)。阿拉伯数字

这些表示都有一个重要的特性,即_线性时间不变_性 (LTI)。LTI 指出 SSM 参数 ABC 对于所有时间步长都是固定的。这意味着矩阵 ABC 对于 SSM 生成的每个标记都是相同的。

换句话说,无论您为 SSM 提供什么序列,ABC 的值都保持不变。我们有一个不感知内容的静态表示。

在我们探索 Mamba 如何解决这个问题之前,让我们先探索拼图的最后一块,矩阵 A

可以说,SSM 公式最重要的方面之一是_矩阵 A_。正如我们之前看到的 recurrent 表示,它捕获有关_先前_ state 的信息以构建_新_ state。

[

](substackcdn.com/image/fetch…)

实质上,矩阵__A 产生隐藏状态:

[

](substackcdn.com/image/fetch…)

因此,创建_矩阵 A_ 可能是只记住几个先前的标记和捕获我们目前看到的每个标记之间的区别。尤其是在 Recurrent 表示的上下文中,因为它只_回顾__之前的状态_。

那么我们如何 以保留大内存(上下文大小)的方式创建_矩阵 A_呢?

我们使用 Hungry Hungry Hippo!或 HiPPO3 for High-order Polynomial Projection Operators.HiPPO 尝试将迄今为止看到的所有输入信号压缩为系数向量。

[

](substackcdn.com/image/fetch…)

它使用_矩阵 A_ 构建一个状态表示形式,该表示形式可以很好地捕获最近的令牌并衰减较旧的令牌。其公式可以表示如下:

[

](substackcdn.com/image/fetch…)

假设我们有一个方阵 A,这得到:

[

](substackcdn.com/image/fetch…)

使用 HiPPO 构建_矩阵 A_ 比将其初始化为随机矩阵要好得多。因此,与_旧_信号 (初始标记) 相比,它更准确地重建_了较新的_信号 (最近的标记)。

HiPPO 矩阵背后的想法是,它会产生一个隐藏状态来记住其历史记录。

在数学上,它通过跟踪勒让德多项式的系数来实现这一点,这使得它能够近似所有以前的历史。4

然后将 HiPPO 应用于我们之前看到的递归和卷积表示,以处理长距离依赖性。结果是序列的结构化状态空间 (S4),这是一类可以有效处理长序列的 SSM。5

它由三个部分组成:

  • 状态空间模型

  • 用于处理长距离依赖的 HiPPO

  • 用于创建循环卷积表示的离散化

[

](substackcdn.com/image/fetch…)

此类 SSM 具有多种优势,具体取决于您选择的表示形式(递归与卷积)。它还可以通过构建 HiPPO 矩阵来处理长文本序列并有效地存储内存。

注意:如果您想深入了解有关如何计算 HiPPO 矩阵并自己构建 S4 模型的更多技术细节,我强烈建议您阅读带注释的 S4

我们终于涵盖了了解 Mamba 的特别之处所需的所有基础知识。状态空间模型 可以用来对文本序列进行建模,但仍然有一系列我们想要防止的缺点。

在本节中,我们将介绍 Maba 的两个主要贡献:

  1. 一种选择性扫描算法,允许模型过滤(非)相关信息

  2. 一种硬件感知算法,允许通过_并行扫描_、_内核融合_和_重新计算_来高效存储(中间)结果。

它们一起创建了_选择性的 SSM_ 或 S6 模型,这些模型可以像自我注意一样用于创建 Mamba 块

在探讨这两个主要贡献之前,让我们先探讨一下为什么它们是必要的。

状态空间模型,甚至 S4(结构化状态空间模型)在某些对语言建模和生成至关重要的任务上表现不佳,即_关注或忽略特定输入的能力_。

我们可以用两个合成任务来说明这一点,即选择性复制归纳头

选择性复制任务中,SSM 的目标是复制 input 的各个部分并按顺序输出它们:

[

](substackcdn.com/image/fetch…)

但是,(递归/卷积)SSM 在此任务中表现不佳,因为它是_线性时间不变_的。 正如我们之前看到的,SSM 生成的每个标记的矩阵 ABC 都是相同的。

因此,SSM 无法执行_内容感知推理_,因为它将每个标记视为固定 A、B 和 C 矩阵的结果。这是一个问题,因为我们希望 SSM 对输入 (提示) 进行推理。

SSM 执行不佳的第二个任务是归纳头,其目标是重现输入中的模式:

[

](substackcdn.com/image/fetch…)

在上面的例子中,我们基本上是在执行一次性提示,我们试图 “教” 模型在每个 “Q:” 之后提供 “A:” 响应。但是,由于 SSM 是时不变的,因此它无法从其历史记录中选择要调用哪些以前的标记。

让我们通过关注_矩阵 B_ 来说明这一点。无论输入 x 是什么,矩阵 B 都保持完全相同,因此独立于 x

[

](substackcdn.com/image/fetch…)

同样,无论输入如何,AC 也保持固定。这证明了 我们迄今为止看到的 SSM 的静态性质。

[

](substackcdn.com/image/fetch…)

相比之下,这些任务对 Transformer 来说相对容易,因为它们 会根据输入序列动态地改变注意力。他们可以有选择地 “查看” 或 “参与” 序列的不同部分。

SSM 在这些任务上的糟糕表现说明了时不变 SSM 的潜在问题,矩阵 ABC 的静态性质会导致_内容感知_问题。

SSM 的递归表示创建了一个非常有效的小状态,因为它压缩了整个历史记录。然而,与不压缩历史记录(通过注意力矩阵)的 Transformer 模型相比,它的功能要弱得多。

Mamba 的目标是两全其美。一个与 Transformer 的状态一样强大的小状态:

[

](substackcdn.com/image/fetch…)

如上所述,它通过选择性地将数据压缩到 state 中来实现这一点。当你有一个输入句子时,通常有一些信息(如停用词)没有太大意义。

为了有选择地压缩信息,我们需要参数依赖于输入。为此,我们首先在训练期间探索 SSM 中输入和输出的维度:

[

](substackcdn.com/image/fetch…)

在结构化状态空间模型 (S4) 中,矩阵 ABC 独立于输入,因为它们的维度 ND 是静态的,不会改变。

[

](substackcdn.com/image/fetch…)

相反,Mamba 通过合并输入的序列长度和批量大小,使矩阵 B 和 _C,甚至_步长 都取决于输入:

[

](substackcdn.com/image/fetch…)

这意味着对于每个输入令牌,我们现在都有不同的 BC 矩阵,这解决了内容感知的问题!

注意:矩阵 A 保持不变,因为我们希望状态本身保持静态,但它受到影响的方式(通过 BC)是动态的。

它们一起_有选择地_选择要保留在隐藏状态中的内容和要忽略的内容,因为它们现在依赖于 Input。

较小的_步长_会导致忽略特定的单词,而是更多地使用前面的上下文,而较大的_步长_更关注输入的单词而不是上下文:

[

](substackcdn.com/image/fetch…)

由于这些矩阵现在是_动态_的,因此无法使用卷积表示来计算它们,因为它假定一个_固定_的内核。我们只能使用递归表示,而失去了卷积提供的并行化。

为了实现并行化,我们来探索如何使用重新并发来计算输出:

[

](substackcdn.com/image/fetch…)

每个状态是前一个状态(乘以 A)加上当前输入(乘以 B)的总和。这称为 scan 操作,可以使用 for 循环轻松计算。

相比之下,并行化似乎是不可能的,因为只有当我们拥有前一个状态时,才能计算每个状态。但是,Mamba 通过_并行扫描_算法实现了这一点。

它假设我们执行操作的顺序与 associate 属性无关紧要。因此,我们可以分部分计算序列并迭代组合它们:

[

](substackcdn.com/image/fetch…)

动态矩阵 BC 以及并行扫描算法共同创建了_选择性扫描算法_,以表示使用递归表示的动态和快速性质。

最近 GPU 的一个缺点是它们在小型但高效的 SRAM 和大型但效率稍低的 DRAM 之间的传输 (IO) 速度有限。频繁地在 SRAM 和 DRAM 之间复制信息成为瓶颈。

[

](substackcdn.com/image/fetch…)

Mamba 和 Flash Attention 一样,试图限制我们需要从 DRAM 到 SRAM 的次数,反之亦然。它通过_内核融合_来实现这一点,这允许模型防止写入中间结果并持续执行计算,直到完成。

[

](substackcdn.com/image/fetch…)

我们可以通过可视化 Mamba 的基本架构来查看 DRAM 和 SRAM 分配的具体实例:

[

](substackcdn.com/image/fetch…)

在这里,以下内容融合到一个内核中:

  • 步长的离散化步骤

  • 选择性扫描算法

  • 使用 C 的乘法

硬件感知算法的最后一部分是 recomputation

中间状态不会保存,但对于向后传递计算梯度是必需的。相反,作者_在_向后传递期间重新计算这些中间状态。

虽然这看起来效率低下,但比从相对较慢的 DRAM 中读取所有这些中间状态的成本要低得多。

我们现在已经介绍了其架构的所有组件,使用其文章中的下图进行了描述:

[

](substackcdn.com/image/fetch…)

选择性 SSM。 取自:Gu, Albert 和 Tri Dao。“Mamba:具有选择性状态空间的线性时间序列建模。” arXiv 预印本 arXiv:2312.00752 (2023)。

这种架构通常被称为_选择性 SSM_ 或 S6 模型,因为它本质上是使用选择性扫描算法计算的 S4 模型。

到目前为止,我们探索的_选择性 SSM_ 可以实现为一个块,就像我们可以在解码器块中表示自我注意一样。

[

](substackcdn.com/image/fetch…)

与解码器一样,我们可以堆叠多个 Mamba 块,并将其输出用作下一个 Mamba 块的输入:

[

](substackcdn.com/image/fetch…)

它从线性投影开始,以扩展输入嵌入。然后,在 Selective SSM 之前应用卷积以防止独立标记计算。

选择性 SSM 具有以下属性:

  • 通过_离散化_创建的_递归 SSM_

  • 在矩阵 A 上进行 HiPPO 初始化以捕获_长距离依赖关系_

  • S_选择性扫描算法_,选择性压缩信息

  • _硬件感知算法_可加快计算速度

在查看代码实现时,我们可以进一步扩展此体系结构,并探索端到端示例的外观:

[

](substackcdn.com/image/fetch…)

请注意一些更改,例如包含规范化层和用于选择输出令牌的 softmax。

当我们把所有东西放在一起时,我们既可以得到快速推理和训练,也可以得到无限的上下文。使用这种架构,作者发现它与相同大小的 Transformer 模型的性能相当,有时甚至超过了它们!

我们的 State Space Models 之旅到此结束,并使用选择性 State Space Model 的令人难以置信的 Mamba 架构。希望这篇文章能让你更好地了解 State Space Models 的潜力,尤其是 Mamba。谁知道这是否会取代变形金刚,但就目前而言,看到如此不同的架构得到当之无愧的关注真是令人难以置信!

要查看与 LLMs并支持此新闻通讯,请查看我与 Jay Alammar 共同撰写的书。

[

](substackcdn.com/image/fetch…)

在官方网站上查看有关该书的更多信息。您可以在亚马逊上订购这本书。所有代码都上传到 Github.

希望这是对 Mamba 和 State Space 模型的通俗易懂的介绍。如果您想更深入地了解,我建议您使用以下资源:

订阅 探索语言模型Subscribe to Exploring Language Models

ML 工程师撰写有关 GenAI 的文章 |开源 (BERTopic, PolyFuzz, KeyBERT) |《Hands-On Large Language Models》的作者。ML Engineer writing about GenAI | Open Sourcerer (BERTopic, PolyFuzz, KeyBERT) | Author of "Hands-On Large Language Models".

本文使用 文章同步助手 同步