前言

        如果您是一个完全的新手,我建议你先阅读我同专栏下的关于大模型的笔记(这是远远不够的,还需要阅读其他人的博客以及更多的文献),对大模型的各种概念有一个简单的了解,再开始下面的任务。然后,在任务中遇到任何陌生的概念时(如不清楚什么是fasttext,什么是“文本分类任务”),请暂停你的脚步,在浏览器中搜索并阅读对应的概念。不需要完全理解,只需要有一个大概的印象即可,这些印象会随着你的学习慢慢串联起来,终有一天引起质变。

        本人认为将文本分类任务作为大模型的入门任务来说是不错的,因为这类任务的目的明确,数据获取较简单,模型回馈的结果明显,是很好的起点。

        而“情绪分类”则是文本分类任务中的经典,我们下面就基于python的fasttext库与jieba分词器来完成一个“情绪分类”的任务。

        这篇博客不会教您如何下载fasttext与jieba分词器,如果您仍未下载请先查阅其他博客下载。但我可以为你分享踩过的坑:在下载fasttext我直接pip安装发现怎么都不行,最后是直接下载whl文件,也就是fasttext_wheel-0.9.2-cp310-cp310-win_amd64,然后在本地pip安装的。然后jieba分词器在下载之后pycharm无法识别出来,还需要手动把他的文件夹移到python\Lib\site-packages下才行。

        训练一个大模型大致可以分为:数据收集,数据预处理,训练模型,模型评估,微调模型这几步,下面我将安装这几步来完成任务。

数据收集

        巧妇难为无米之炊,没有数据就没有模型。数据是一个模型的核心。我已经将这个任务需要用到的数据集上传了,是关于某一酒店评论的数据集。至于这个数据集的源头,我很抱歉因为时间久远我已经忘记了。但是,下面有一些收集了数据集的网站,希望以后可以帮你找到你想要的数据集:

开放数据集-飞桨AI Studio星河社区

魔搭社区

数据集 / HyperAI超神经 | HyperAI超神经

更多的网址可以自行查找

数据预处理

        在压缩文件中有pos与neg两个文件夹,分别表示好评(正面情绪)与差评(负面情绪)。里面各有2000个txt文件,表示2000条评论。而faxttext需要的格式是下面这样的

__label__消极	服务态度极差,前台超级没礼貌!
__label__消极	再也不来了,根本就是骗钱的地方,什么东西都贵的要死。
__label__积极    房间整洁,风景优美,五星好评!

所以我们需要对数据进行处理,将所有的评论全部整合到一个txt文件中去,并为他们添加标签。

from os import listdir

path = r"C:\Users\凡尘\PycharmProjects\pythonProject\课外\LLM\文本分类\fasttext\pos"  # 更改为你的路径哟
path2 = "neg.txt"  # 写入哪里?
files = listdir(path)
with open(path2, "w", encoding="utf-8") as f1:  # 打开文件夹读取所有文件
    for i in files:
        with open(rf"{path}\{i}", "r", encoding="utf-8") as f2:  # 写入
            str_in = ""
            for j in f2.readlines():
                str_in += j.strip()  # 吸收回车符
            str_in = "__label__积极\t" + str_in + "\n"  # 构造格式
            f1.write(str_in)

 处理完后我们就获得了合适格式的数据。(同理使用以上代码处理neg文件夹)

 接下来我们需要进行分词操作以提高模型的效率与训练速度。分词操作可以简单理解为为一个句子“断句”,将“广州大学是世界上最好的大学”断句为“广州  大学  是  世界上  最好  的  大学”,而且真正作用与详细原理这里限于篇幅就不展开讲了,希望你自行查阅其他资料。

在这里我选择的分词器是jieba分词器,修改一下下上面的代码来实现分词操作。:

from os import listdir

import jieba

path = r"C:\Users\陈瑞达\PycharmProjects\pythonProject\课外\LLM\文本分类\fasttext\pos"
path2 = "pos.txt"  # 写入哪里?
files = listdir(path)
with open(path2, "w", encoding="utf-8") as f1:  # 打开文件夹读取所有文件
    for i in files:
        with open(rf"{path}\{i}", "r", encoding="utf-8") as f2:  # 写入
            str_in = ""
            for j in f2.readlines():
                str_in += j.strip()  # 吸收回车符
                str_temp = ""
                for k in jieba.cut(str_in):
                    # print(k)  # 尝试保留这一行,看看输出的是什么?
                    str_temp += k + " "  # 使用空格来分割
            str_in = "__label__积极\t" + str_temp + "\n"  # 构造格式
            f1.write(str_in)

neg文件夹同理。在处理好之后我们还需要执行最后一步,对数据集进行划分,将其按一定比例划分为训练集与测试集(一般是8:2或7:3)。顾名思义训练集是用来训练你的模型的数据,而测试集是用来测试你模型的准确性的。

你需要将pos.txt与neg.txt的各1600条评论Ctrl+x出来贴到train.txt中去,剩下的400条也各自取出来贴到test.txt中去。

当然,如果您非常懒,我也为你准备好了脚本:

# 参数
train_txt_path = "train.txt"  # 无需手动创建,当python发现你没有这个文件的时候它会帮你创建
test_txt_path = "test.txt"
rate = 0.8  # 以80%的数据作为训练集
total = 2000  # 2000条数据/每文件

# txt读写
with open(train_txt_path, "w", encoding="utf-8") as f_train:
    with open(test_txt_path, "w", encoding="utf-8") as f_test:
        with open("pos.txt", "r", encoding="utf-8") as f_pos:
            for i, v in enumerate(f_pos.readlines()):
                        if i < total * rate:
                            f_train.write(v)
                        else:
                            f_test.write(v)
        with open("neg.txt", "r", encoding="utf-8") as f_neg:
            for i, v in enumerate(f_neg.readlines()):
                if i < total * rate:
                    f_train.write(v)
                else:
                    f_test.write(v)

这样我们就预处理好数据,可以开始进行模型的训练了。

为了避免你在上面的步骤中卡死而无法学习下面的关键内容,我已经将预处理好的train.txt与test.txt一并打包上传了。

模型训练

from fasttext import train_supervised

# 路径参数
train_data_path = 'train.txt'

# 模型训练
model = train_supervised(train_data_path)  # 以默认的模型进行,不进行任何参数调整。train_supervised()直接构建模型,炒鸡方便
# model = train_supervised(train_data_path, lr=1, epoch=15, wordNgrams=2, verbose=2, minCount=1, dim=100)  # 或者你想要我的参数?说实话不是特别好
model.save_model("model.bin")  # 保存模型。(你也不想训练了两天的模型只能用一次吧)

可以看到fasttext的训练代码非常少,非常清晰且萌新友好。

模型评估

from fasttext import load_model

# 路径参数
model_path = "model.bin"
test_data_path = 'test.txt'

# 加载模型
model = load_model(model_path)

# 数据读入
list_comment = []  # 用来存放评测集中评论的部分
list_emotion = []  # 存放情绪评价的部分,即label
with open(test_data_path, "r", encoding="utf-8") as f1:
    for i in f1.readlines():  # 切分情绪标签与评价内容二者
        list_comment.append(i.strip("__label__积极").strip("__label__消极").strip())
        list_emotion.append(i[9:11])

# 变量记录
list_correct_rate = []
correct_num = 0  # 正确匹配的数量
recall_num = 0  # 召回数量
list_record = []  # 记录预测的结果

# 开始评测
list_ans = model.predict(list_comment)
for i, v in enumerate(list_ans[0]):
    list_record.append(v[0].strip("__label__"))  # 记录每条内容评测的结果
    if v[0].strip("__label__") == list_emotion[i]:  # 如果预测结果与标签结果相同则视为预测正确
        correct_num += 1
        if list_emotion[i] == "积极":  # 用积极标签计算召回率(大概是这样吧?)
            recall_num += 1
correct_rate = correct_num / len(list_comment)
recalling_rate = recall_num / list_emotion.count("积极")
list_correct_rate.append(correct_rate)

print(f"\n预测为积极的数量为:{list_record.count('积极')},应为{list_emotion.count('积极')}.\n"
      f"预测为消极的数量为:{list_record.count('消极')},应为{list_emotion.count('消极')}.")
print(f"正确率为:{'%.4f' % correct_rate},召回率为:{'%.4f' % recalling_rate}")
print(f"由内置函数计算的精准正确率为:{model.test(test_data_path)[-1]}")

在我的电脑上跑出来的结果是这样的:

可以看到我们模型的准确率游八成左右,但是到这里你可能还是觉得没有一个清晰的概念,毕竟准确率是看不见摸不着的一个数字。那么我们就把模型对每一个评测集的判断结果输出出来看看吧。

(将以下代码加在模型评估代码的最后:)

for i, v in enumerate(list_record):
    if v=="积极":
        print(f"模型对于:\033[4;36m{list_comment[i]}的评估结果是\033[0m:\033[92m{v}\033[0m")
    else:
        print(f"模型对于:\033[4;36m{list_comment[i]}的评估结果是\033[0m:\033[31m{v}\033[0m")
    print()

输出结果: 

现在我们就能看到我们的模型对于每一条数据的评估结果了,你可以直观地感受到文本分类任务的作用了吗?

模型调整

        尝试调整模型训练时的参数,调整训练于测试集的比例来提高模型的准确率吧,相信你能做到。

最后

        希望本文对你学习人工智能和大模型有帮助。有任何问题可以向作者提出。

        (PS:才发现你们下载我上传的文件是要积分的,我还以为是免费的,等过几天我有空了传网盘上给大家。)

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐