设置环境

虽然现在可以在 CPU 上运行许多 LLM,但如果没有 GPU,对它们进行微调仍然是不可行的。因此,本教程需要具有超过 40GB 视频内存的 GPU。我建议使用提供安装了 CUDA 和 cuDNN 的虚拟机的云计算服务。否则,您应该首先确保您的机器上安装了适当版本的 CUDA 和 cuDNN。有关安装过程的更多信息,请参见此处。

一切准备就绪后,我们可以开始创建新环境并安装必要的库。

conda -n mbti- =3.12.4

conda mbti-

接下来,我们需要安装以下库:

pip numpy-learn-加载数据集

为了保存模型,我们需要在 Face 网站上创建一个账户并获取一个访问密钥。我们可以将访问密钥保存在项目根目录中的 .env 文件中。

登录(令牌=操作系统(“”))

然后,您可以使用库加载数据集。以下代码将从 Face 下载数据集或从缓存中加载数据集。

=(“/mbti”,拆分='训练')

为了确保良好的训练-验证分割,我们将使用分层抽样。因此,我们需要先对列进行编码。

=.(“mbti”)

=.(“EI”)

=.(“NS”)

=.(“FT”)

=.(“JP”)

由于训练集包含约 230 万行数据,训练所有数据可能会很慢。因此,我们将仅使用 10% 的数据进行训练,使用 20% 的数据进行验证。

=.(=0.1,“mbti”,种子=0)

=["test"] # 丢弃 90% 的数据

=.(=0.2, ="mbti", seed=1) 定义模型

与使用较旧的 BERT 模型的 Face 教程不同,我将使用微软于 2024 年发布的 Phi-3 模型。

型号=“/Phi-3-mini-4k-”

=“Phi-3-mini-4k--mbti”

然后我们可以定义我们的模型和标记器。

=.(模型)

开启(数据):

(数据[“body”],=True)

=.map(,=True)

# 节省内存

为了简化,我将仅对 MBTI 的 JP 侧进行分类。在此数据集中,JP 侧的比例为 60-40,这有些不平衡,但并不严重倾斜。因此,我将删除所有其他列。

=.(['', 'mbti', 'FT', "EI", 'NS'])

=.('JP', “标签”)

为了通过动态填充令牌来简化数据批处理并提高效率,我们将使用

=ing(=)

为了评估我们的模型,该软件包提供了许多开箱即用的指标。

# 使用 3 种不同的指标来评估模型

=.负载(“”)

f1 = .load("f1")

=.负载(“”)

安息香

():

,=

=np.(,轴=1)

=pute(=,=)

=pute(=,=)

=pute(=,=)

{**,**,**}

我们还需要标签和 ID 之间的映射,以便模型在训练期间进行损失计算。错误的映射会导致损失计算中出现 NaN,从而使模型无法学习。

={0:“J”,1:“P”}

={“J”:0,“P”:1}

现在我们可以使用以下方法定义模型

包含 300 万行的数据库设置环境教程:需超 40GB 显存 GPU 及安装 CUDA 和 cuDNN,,

模型 = .(

型号, =2, =, =

)微调法学硕士

包含 300 万行的数据库设置环境教程:需超 40GB 显存 GPU 及安装 CUDA 和 cuDNN  第1张

为了使用提供的类,我们需要定义训练参数。

火炬..cuda.. =真

火炬..cudnn.=真

=(

=,

=2e-5,

=4,#根据显存调整

=4,#根据显存调整

=1,

=0.01,

=“steps”,#根据数据大小调整

=“steps”,#根据数据大小调整

=1000,#根据数据大小调整

=1000,#根据数据大小调整

=1000,#根据数据大小调整

nd=真,

=正确,

优化="",

eps=2, # 根据显存调整

=2,#根据显存调整

tf32=真,

在这些训练参数中,使用了几种方法来加速训练过程并减少内存使用。

从这张图片中可以看出,使用 tf32 会牺牲准确率来换取更小的内存占用。TF32 使用 19 位而不是 32 位来表示每个浮点数,从而将内存占用减少了 40%。根据研究,使用 tf32 训练的模型与使用 fp32 训练的模型表现非常相似。

可以注意到我们没有使用 bf16 来微调模型。根据模型配置,Phi3 模型实际上是使用 bf16 进行训练的。但是,由于某种未知原因,如果在微调期间使用 bf16,则损失变为 NaN。

现在,我们可以定义训练器并开始训练模型。

():

(自我,模型,,=False):

=.获取(“”)

# 前向传递

=模型(**)

=.获取('')

# 计算自定义损失

=nn.(=torch.([0.6, 0.4]).to('cuda'))

损失 =(.view(-1,self.model..),.view(-1))

(损失, )

=(

模型=模型,

参数=,

=[“火车”],

=[“测试”],

=,

=,

=,

在这里,我们编写了一个具有特殊损失函数的自定义训练器。如前所述,我们的数据是不平衡的,大约 60-40。因此,我们使用了权重平衡方法来防止模型成为主导分类器。

最后,我们终于可以开始训练模型了。

。火车

.()

这些代码将训练模型并将训练好的模型推送到你的Face存储库。

结果

如果你将上述内容放入,你将看到类似下图的结果。

随着训练损失和验证损失的稳步下降,准确率也在提高。在此示例中,我们的模型在验证集上的准确率约为 0.65。这不是一个特别好的结果,但考虑到我们仅使用了 10% 的数据和较小的模型,这是一个不错的结果。如果您想要更好的结果,可以尝试使用更大的模型、更多的数据和更多的训练时间。

总结一下:文本分类是自然语言处理 (NLP) 中的常见任务。它是根据文本内容为文本分配标签的过程。例如,将电影评论分类为正面或负面,或将新闻文章分类为体育、政治或娱乐。在大型语言模型 (LLM) 出现之前,文本分类是通过传统的机器学习方法进行的,需要大量的特征工程。使用诸如、GloVe 和之类的词嵌入将文本转换为数值向量。然后将这些向量输入到诸如逻辑回归、支持向量机或随机森林之类的机器学习模型中进行分类。这个过程可能很慢,并且需要大量的手动工作才能获得良好的结果。大型模型,尤其是像 Phi-3 这样可以自行调整的模型,无疑是实现这种能力非常有用的工具。