Day28下 - 大模型微调:酒店评论情感分析

news2025/1/7 19:21:23

一、前置准备

1. 下载 LLaMA Factory

https://github.com/hiyouga/LLaMA-Factory.git

 搭建过程详见:https://blog.csdn.net/CSBLOG/article/details/144584581

2. 选择 预训练模型 和 prompt指令模型

预训练阶段在实际工作中,一般是用不上的,但我们可以学习了解。为了方便节省资源,我们可以先选个小点的模型试一试。

这里预训练模型选择 通义千问2.5-0.5B-预训练 ,指令模型选择 Qwen2.5-0.5B-Instruct

3. 下载 预训练模型 和 指令模型

下载预训练模型:

git clone https://www.modelscope.cn/Qwen/Qwen2.5-0.5B.git

下载指令模型:

git clone https://www.modelscope.cn/Qwen/Qwen2.5-0.5B-Instruct.git

4. 打开 LLaMA Factory 的webui,修改参数

(1)查看并确保 模型名称 和 模型路径 是否正确

 (2)选择推理引擎,实际工作中一般选择 vllm

 (3)按需决定是否还需要调整其他参数

5. 对话测试 

 二、数据处理

1. 数据集构建

通过查看 LLaMA-Factory/data/README_zh.md 文件可知,它需要什么样的数据。

 先找一小段文本尝试一下

import json

texts = """
1.流行性感冒:流行性感冒潜伏期多为1~7天,临床表现主要以发热(体温可达39~40℃)、头痛、肌痛和全身不适起病。除了全身症状,常有咽喉痛、干咳,可有鼻塞、流涕、胸骨后不适等。部分有呕吐、腹痛、腹泻等消化道症状。流感病原学检测阳性。
2.过敏性鼻炎:有过敏史,常年打喷嚏和流涕,鼻黏膜苍白伴有瘙痒感,鼻分泌物内嗜酸粒细胞增加等。
3.萎缩性鼻炎:大多是鼻腔通畅,鼻和鼻咽部干燥,鼻分泌物为块状、管筒状脓痂,伴有呼气恶臭、嗅觉减退等症状。
4.血管舒缩性鼻炎:无过敏史,常出现鼻黏膜间歇性血管充盈、打喷嚏和流清涕,吸入干燥空气后症状加重。
5.上呼吸道感染性疾病:如细菌性咽-扁桃体炎,疱疹性咽峡炎等均有其病变部位的特异性体征。前者有咽部充血,扁桃体肿大,表面有脓性分泌物等;后者软腭、咽和扁桃体表面有灰白色疱疹和浅表溃疡伴周围红晕。
"""

samples = []
for text in texts.split("\n"):
    if text:  # 检查行是否非空
        sample = dict(text=text)  # 创建一个字典,键为 'text',值为当前行的文本
        samples.append(sample)  # 将字典添加到 samples 列表中

运行结果:

 保存数据

with open(file="samples.json", mode="w", encoding="utf8") as f:
    json.dump(obj=samples, fp=f, ensure_ascii=False)

运行后,会在当前目录下生成 samples.json 文件。

想要在 LLaMA-Factory webui 的数据集中显示,还需要参照 README_zh.md 文件中的方式进行注册,因为它是通过dataset_info.json文件去找相关的数据。

 再回到 LLaMA Board,即可看到我们新增的数据集

按需添加数据集,然后就可以开始训练了

数据太少,训练没啥效果,接下来,我们用之前酒店评论情感分析的数据集作为示例

2. 数据切分

import pandas as pd

data = pd.read_csv(filepath_or_buffer="samples.tsv", sep="\t", encoding="utf8")

data = data.sample(frac=1)

data.reset_index(drop=True, inplace=True)

# 包含 stop [start, stop]
train = data.loc[1500:, :]
test = data.loc[:1499, :]


print(train.shape)
print(test.shape)

train.to_csv(path_or_buf="train.tsv", sep="\t", index=None)
test.to_csv(path_or_buf="test.tsv", sep="\t", index=None)

3. 数据格式转换

import pandas as pd
import json
from pprint import pp

data = pd.read_csv(filepath_or_buffer="train.tsv", sep="\t", encoding="utf8")

num_samples, num_features = data.shape

results = []
sys_prompt = """
你是一个情感识别专家!请对用户输入的酒店评论做情感分析!
如果是正面的评论,请输出:
{
    "sentiment": "正面"
},
如果是负面的评论,请输出:
{
    "sentiment": "负面"
}
"""
user_instruction = '{input}'

for idx in range(num_samples):
    comment, sentiment = data.loc[idx, :]
    # print(comment, sentiment)
    result = {
    "instruction": comment,
    "input": "",
    "output": '{"sentiment": "'  + sentiment + '"}',
    "system": sys_prompt}
    # pp(result)
    results.append(result)

print(results)
type()

print(results[1000]["system"])

print(results[1000]["instruction"])

print(results[1000]["input"])

print(results[1000]["output"])

with open(file="sentiments.json", mode="w", encoding="utf8") as f:
    json.dump(obj=results, fp=f, ensure_ascii=False)

运行成功后,会自动生成 sentiments.json 文件。

(1)将 sentiments.json 文件移动到 LLaMA-Factory/data目录下;

(2)在 LLaMA-Factory/data/dataset_info.json文件里进行注册;

三、微调

1. 修改模型的自我认知

修改 LLaMA-Factory/data/identity.json 文件,将 {{name}}  {{author}}分别替换成你需要的名字。

2. 回到 LLaMA Board 页面,选择数据集,微调时,一般选择三类数据。

(1)自我认知(每个项目是必改的,修改identity)

(2)私有数据(针对你的具体任务,需要设计指定格式,转换自己的数据)

(3)公开数据(框架自带)

所以这里的数据集可以选择 identity, sentiment , alpaca_zh_demo,alpaca_en_demo 。

3. 确保模型的路径正确。

4. 小模型,算力足,可以选择 full 全参。再调一下训练轮数、批处理大小、保存间隔可以调大一些, 日志可以改小一点,不需要打那么多日志,其他基本不怎么需要修改,即可开始炼丹啦。

 

四、多机多卡

1. 打开算力平台,选择多台机器

https://www.autodl.com/login

选了3台机器

 

2. 下载相关模型文件,操作步骤跟前面差不多。

(1)下载 LLaMA Factory 、下载Qwen模型。

(2)将前面修改好的 identity.json, sentiments.json, dataset_info.json 文件上传过来替换掉。

3. 监控显存

刚开始不要弄的太复杂。打开终端,切换到LLaMA Factory根目录下,输入以下命令:

# 监控显存
watch -n 1 'nvidia-smi'

 

可以看到目前3张卡都是空的。

4. 修改相关配置文件

参考 LLaMA Factory 说明文档

https://llamafactory.readthedocs.io/zh-cn/latest/advanced/distributed.html

FORCE_TORCHRUN=1,是True的意思,也就是直接用torch来启动。
train examples/train_full/llama3_full_sft_ds3.yaml 配置文件

(1)找到 LLaMA-Factory/examples/train_full 目录
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==编辑
(2)将该目录下的 llama3_full_sft.yaml 配置文件复制到 autodl 平台的 LLaMA-Factory 目录下,再重命名为: Qwen2.5_0.5B_Instruct_full_sft.yaml

(3)修改Qwen2.5_0.5B_Instruct_full_sft.yaml 文件内容

(4)autodl 平台终端,安装 deepspeed 

pip install deepspeed

(5)autodl 平台终端,切换到 LLaMA-Factory 根目录下,输入命令

# 并行训练
FORCE_TORCHRUN=1 llamafactory-cli train QWen2.5_0.5B_Instruct_full_sft.yaml

可以看到,3张卡开始使用了 。 

接下来,查看训练结果。

5. 模型微调

(1)启动 LLaMA-Factory(LLaMA Board 可视化微调),终端输入以下命令

llamafactory-cli webui

(2)在 LLaMA Board 可视化微调界面,将模型路径替换为刚才训练成果的路径。

(3)加载模型

 

(4)检验成果

先粗糙的试一下,看自我认知是否已经修改好;再进行公共知识和私有知识的提问,看回答问题的质量如何。

(5)考试,来测试训练后的模型效果

modelscope 和 antodl 两个平台的终端分别都切换到LLaMA-Factory的根目录下,输入以下命令:

# 模型测评
CUDA_VISIBLE_DEVICES=0 llamafactory-cli eval \
--model_name_or_path /root/autodl-tmp/outputs/Qwen2.5-0.5B-Instruct \
--template qwen \
--task cmmlu_test \
--lang zh \
--n_shot 5 \
--batch_size 4 \
--trust_remote_code True

其中,model_name_or_path 是之前训练后生成的模型路径

modelscope考试结果:

Average只有32,说明模型微调后,综合能力降低了。 

training loss :

autodl 平台考试情况:

 6. autodl 平台操作

(1)打开autodl 终端,输入以下命令,安装vllm

pip install vllm

(2)减配卡(训练的时候尽量多张卡,训练完成后可以只用一张卡)

(3)将之前写的情感识别任务的代码上传到autodl平台上,修改模型路径;

 

 (4)autodl 终端,进入LLaMA-Factory的根目录下,输入以下命令:

CUDA_VISIBLE_DEVICES=0 llamafactory-cli eval \
--model_name_or_path /root/autodl-tmp/outputs/Qwen2.5-0.5B-Instruct \
--template qwen \
--task cmmlu_test \
--lang zh \
--n_shot 5 \
--batch_size 4 \
--trust_remote_code True

运行第一轮:

运行第二轮:

7. 部署API服务

部署神器 vllm ,参考文档:

https://blog.vllm.ai/2023/06/20/vllm.html

# 模型部署
python -m vllm.entrypoints.openai.api_server \
--host 0.0.0.0 \
--port 6006 \
--model Qwen2.5-0.5B-Instruct \
--api-key abc123 \
--enable-auto-tool-choice \
--tool-call-parser hermes

五、大模型上层开发 

上层开发在本地操作即可,接下来使用本地 jupyter 操作。

上层开发有3件事:

  • prompt 开发
  • RAG 系统
  • Agent
from langchain_openai import ChatOpenAI

model = ChatOpenAI(base_url=base_url,
                  api_key=api_key,
                  model=model,
                  max_tokens=512,
                  temperature=0.1,
                  top_p=0.3)

1. 大模型调用方法

"""
    call
    invoke
"""
response = model.invoke(input="你是谁?")


# 文本内容
response.content

response.response_metadata["token_usage"]

response.response_metadata["finish_reason"]

2. stream

response = model.stream(input="你好")

for chunk in response:
    print(chunk.content)

3. 批量推理

queries = ["你好", "你吃饭了吗?", "一起去打球吧"]

responses = model.batch(inputs=queries)

len(responses)

responses

 4. 输入部分

# system
from langchain_core.messages import SystemMessage
# user
from langchain_core.messages import HumanMessage
# assistant
from langchain_core.messages import AIMessage

messages = [
    SystemMessage(content="""
    你是一个情感识别专家!请对用户输入的酒店评论做情感分析!
    如果是正面的评论,请输出:
    {
        "sentiment": "正面"
    },
    如果是负面的评论,请输出:
    {
        "sentiment": "负面"
    }
    """),
    HumanMessage(content="刚从无锡回来,住了该酒店二号楼328YUAN的,总体感觉如下;房间干净,配制齐全还有液镜电脑;饭菜可口且不是很贵;最值得称赞的是服务水准,老公粗心大意把手机掉了,工作人员捡后马上送回,赞了!饭店的员工几乎都是笑脸相迎,很难得,单从这点就间接提升了入住该饭店的理由!")
]


messages

response = model.invoke(input=messages)

response.content


import json
json.loads(s=response.content)

LangChain

  • 输入预处理
  • 大模型
  • 后处理
from langchain_core.prompts import SystemMessagePromptTemplate
from langchain_core.prompts import HumanMessagePromptTemplate
from langchain_core.prompts import ChatPromptTemplate

sys_prompt = SystemMessagePromptTemplate.from_template(template="""
你是一个情感识别专家!请对用户输入的酒店评论做情感分析!
如果是正面的评论,请输出:
{{
    "sentiment": "正面"
}},
如果是负面的评论,请输出:
{{
    "sentiment": "负面"
}}
""")

user_prompt = HumanMessagePromptTemplate.from_template(template="{text}")

prompt = ChatPromptTemplate.from_messages(messages=[sys_prompt, user_prompt])

prompt

model

from langchain_core.output_parsers import StrOutputParser
output_parser = StrOutputParser()

chain = prompt | model | output_parser

text = "刚从无锡回来,住了该酒店二号楼328YUAN的,总体感觉如下;房间干净,配制齐全还有液镜电脑;饭菜可口且不是很贵;最值得称赞的是服务水准,老公粗心大意把手机掉了,工作人员捡后马上送回,赞了!饭店的员工几乎都是笑脸相迎,很难得,单从这点就间接提升了入住该饭店的理由!"

chain.invoke(input={"text": text})

import pandas as pd

data = pd.read_csv(filepath_or_buffer="test.tsv", sep="\t", encoding="utf8")

num_samples, num_features = data.shape

from tqdm import tqdm

results = []
for idx in tqdm(range(num_samples)):
    comment, sentiment = data.loc[idx, :]
    result = chain.invoke(input={"text": comment})
    try:
        result = json.loads(s=result)
    except Exception as ex:
        print(result)
    results.append(result["sentiment"] == sentiment)


sum(results) / len(results)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【网络安全 | 漏洞挖掘】JS Review + GraphQL滥用实现管理面板访问

未经许可,不得转载。 正文 在映射目标范围后,我发现了一个用于管理的控制台界面,但没有注册功能。 于是我开始尝试: 1、模糊测试注册端点 -> 失败 2、在请求中将登录替换为注册 -> 再次失败 尝试均未奏效后,我决定冷静下来,重新思考方法并利用技术手段。 我观察…

数据库管理-第278期 开年综艺,第七届中国PG数据库生态大会有感(20250105)

数据库管理278期 20245-01-05 数据库管理-第278期 开年综艺,第七届中国PG数据库生态大会有感(20250105)1 走后门的可观测性2 社区VS商业3 从O来到PG去4 现场集锦5 IF CLUB社区总结 数据库管理-第278期 开年综艺,第七届中国PG数据库…

Docker 安装Elasticsearch搜索引擎 搜索优化 词库挂载 拼音分词 插件安装

介绍 允许用户快速索引和搜索大量的文本数据。通过使用倒排索引,它能够在海量数据中高效检索相关信息。提供灵活的查询语言,可以做全文搜索、模糊搜索、数据统计等,用来代替MYSQL的模糊搜索,MYSQL的模糊搜索不支持使用索引从而导…

NVR小程序接入平台EasyNVR使用FFmpeg取流时提示错误是什么原因呢?

在视频监控系统中,FFmpeg常用于从各种源(如摄像头、文件、网络流等)获取流媒体数据,这个过程通常称为“取流”。 在EasyNVR平台中,使用FFmpeg取流是一种常见的操作。FFmpeg作为一款强大的开源多媒体处理工具&#xff…

【电源专题】为什么测试电源的SW波形上冲振荡之前的0V电位要先来个小的下降

在同步电源的开关节点SW波形测试中,你可能会发现周期性的SW波形在上升前的一小段时间时间内会有一个小小的下跌,这个下跌会低于0V。那么这个下跌是怎么来的呢? 如下所示为某降压转换器的SW开关节点波形: 其展开后可以看到在上升之前有20ns左右的时间,SW电压是下跌…

基于EB和S32DS3.5建立基础工程

本文参考: https://blog.csdn.net/weixin_41660366/article/details/141949690 https://blog.csdn.net/zhoujingCSDN/article/details/142284796 0、简介 本文基于S32K312 介绍新建工程并引入EB,环境如下: MCU:NXP S32k312 RT…

如何申请LabVIEW软件著作权?

申请 软件著作权 时,若你的单位开发的应用是基于 LabVIEW 的图形化编程语言,你需要将 LabVIEW 程序中的图形化设计转换为源代码形式,以符合软件著作权申请的要求。由于LabVIEW本身是图形化编程语言,而不是传统的文本编程语言&…

C/C++中new/delete与malloc/free的区别及对象管理

C/C++中new/delete与malloc/free的区别及对象管理 在C/C++编程中,动态内存管理是一个核心且复杂的话题,其中new、delete、malloc和free是四个经常用于此目的的工具。尽管它们都涉及到内存的分配和释放,但它们在处理对象时的方式和效果却大相径庭。本文将通过示例来说明这些工…

GitHub 图像修复开源项目推荐【持续更新】

GFPGAN 介绍:GFPGAN(Generative Facial Prior-GAN)是由腾讯ARC(Applied Research Center)开发的一种实用的真实世界人脸修复算法。它专门设计用于人脸图像的生成和优化,尤其在低质量人脸图像的超分辨率恢复…

JWT认证实战

JWT(JSON Web Token)是一种轻量级的、基于 JSON 的开放标准(RFC 7519),用于在各方之间安全地传递信息。JWT 的特点是结构简单、轻量化和跨平台支持,适用于用户身份验证、信息加密以及无状态的 API 访问控制…

【无标题】优秀回答统计

在Class-Aware Pseudo-Labeling (CAP) 方法中,类感知阈值(Class-Aware Thresholds)的动态调整是通过以下步骤实现的: 初始化阈值: 在训练开始时,为每个类别设置初始阈值。这些阈值可以基于先验知识、数据分…

arcgis模版空库怎么用(一)

这里以某个项目的数据为例: 可以看到,属性表中全部只有列标题,无数据内容 可能有些人会认为空库是用来往里面加入信息的,其实不是,正确的用法如下: 一、下图是我演示用的数据,我们可以看到其中…

基于深度学习的视觉检测小项目(六) 项目的信号和变量的规划

• 关于前后端分离 当前流行的一种常见的前后端分离模式是vueflask,vueflask模式的前端和后端之间进行数据的传递通常是借助 API(应用程序编程接口)来完成的。vue通过调用后端提供的 API 来获取或提交数据。例如,前端可能通过发送…

edeg插件/扩展推荐:助力生活工作

WeTab 此插件在我看来有2个作用 1.改变edeg的主页布局和样式,使其更加精简,无广告 2.提供付费webtab Ai(底层是chatGpt) 沉浸式翻译 此插件可翻译网页的内容 假设我们浏览github 翻译前 翻译后 Better Ruler 可以对网页的距离进行测量 适合写前端的小伙伴 用法示例:

k8s基础(4)—Kubernetes-Service

Service概述 抽象层 ‌k8s的Service是一种抽象层,用于为一组具有相同功能的Pod提供一个统一的入口地址,并通过负载均衡将网络流量分发到这些Pod上。‌ Service解决了Pod动态变化的问题,例如Pod的IP地址和端口可能会发生变化,通过…

客户案例:基于慧集通(DataLinkX)集成平台的金蝶云星空公有云与WMS系统对接集成方案

本文档详细介绍了基于慧集通(DataLinkX)集成平台的金蝶云星空公有云与WMS系统对接集成方案。该方案旨在实现金蝶云星空与WMS系统之间的数据同步和流程对接,以提高企业供应链管理的效率和准确性。通过物料、供应商资料同步,采购、销…

jenkins入门4 --window执行execute shell

1、启动关闭jenkins 在Windows环境下,如果你需要关闭Jenkins服务,可以通过以下几种方式: 1、使用Windows服务管理器: 打开“运行”对话框(Win R),输入services.msc,然后回车。 在服…

ZYNQ初识7(zynq_7010)RAM_IP核

学习汇总正点原子bi站教学视频。但由于目前的学习板PL端缺乏时钟晶振,所以需要从PS端调用时钟供给PL端使用,也就造成顶层文件的设置出现一些问题,在IP核创建调用和例化过程中一些功能会受到限制,所以以下仅作汇总参考。 zynq_7000…

LeetCode:98.验证二叉搜索树

跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的! 代码随想录 LeetCode:98.验证二叉搜索树 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 …

Golang:使用minio替代文件系统实战教程

本文讨论项目开发中直接文件系统的限制或不足,接着介绍Minio对象存储的优势。同时给出Golang的实际示例代码,包括初始化客户端、读取minio对象以及设置过期策略等。 文件系统 vs Minio 在开发的早期阶段,常见的做法是使用文件系统来存储和检…