【Datawhale AI 夏令营】 用AI做带货视频评论分析(二)

5.预训练模型跑分

回顾赛题

回顾赛题任务

挑战与难点:

  • 标注数据少 ——> 半监督学习 or 数据增强

  • 聚类分析噪点影响严重

回顾Baseline

问题:

  • TF-IDF无法捕捉以下语义。
  • 聚类分析粗糙,未评估聚类质量。

提升方案:

  1. 分类任务(任务一和任务二)
    • 使用BERT模型
    • 数据增强(对于任务一)
    • 微调方式
  2. 聚类任务

预训练模型步骤

任务一:商品识别

  • 数据准备: 我们把文字标签(比如 “Xfaiyx Smart Translator”)映射成数字(0, 1),因为模型只能理解数字。
  • 模型和分词器: AutoTokenizer 负责把汉字句子切分成模型认识的“词元”(Token)。AutoModelForSequenceClassification 是一个专门用于分类任务的BERT模型结构。
  • 训练: TrainingArguments 用来设置训练的超参数(比如训练几轮、每批次用多少数据等)。Trainer 是一个高级封装,我们把模型、参数、数据都喂给它,它就会自动帮我们完成整个复杂的训练过程。
  • 预测: 训练好后,我们用 pipeline 这个便捷工具对所有视频的文本进行预测,得到商品名称。

任务二:情感分析

  • 这个过程和任务一非常类似,但是我们用一个 for 循环来为四个不同的情感维度分别独立地训练四个模型
  • 因为每个维度的分类任务都不同(比如sentiment_category是5分类,而user_scenario是2分类),所以为每个任务单独训练一个模型效果最好。
  • 注意,这里我们将 1,2,3,4,5 这样的原始标签也转换成了从 0 开始的 0,1,2,3,4,训练完再转换回去。这是Hugging Face模型的标准要求。

任务三:评论聚类

  • 句向量模型: 我们加载 SentenceTransformer 模型,它会把每个评论变成一个包含384或768个数字的向量,这个向量精准地捕捉了评论的语义。
  • 寻找最佳K: 这是关键的改进!代码会遍历 K 从 5 到 8,对每个 K 值都进行一次KMeans聚类,并计算轮廓系数。轮廓系数越高,代表聚类效果越好(类内越紧密,类间越疏远)。最后,代码会选用分数最高的那个 K 值。
  • 最终聚类: 使用找到的最佳 K,进行最后一次聚类,并把每个评论分到的簇标签(比如属于第0簇,第1簇…)记录下来。
  • 主题生成: 我们为每个簇生成了一个简单的名字,比如 positive_主题_1。这样做的好处是清晰明了,并且百分百符合提交格式。

步骤

前期准备

  1. 安装所需要的库
!pip install --upgrade transformers accelerate sentence-transformers -q
2. 导入
import pandas as pd
import numpy as np
import torch
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from transformers import (AutoTokenizer,AutoModelForSequenceClassification,TrainingArguments,Trainer,pipeline,
)
from sentence_transformers import SentenceTransformer
from datasets import Dataset
import os
import zipfile
  1. 全局设置(模型定义)和准备数据
# ---------------------------------
# 1. 全局设置和模型定义
# ---------------------------------
print("\n--> 1. 开始进行全局设置...")
CLASSIFICATION_MODEL = 'bert-base-multilingual-cased'
EMBEDDING_MODEL = 'sentence-transformers/paraphrase-multilingual-mpnet-base-v2'
DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'
print(f"将使用设备: {DEVICE}")# ---------------------------------
# 2. 加载和准备数据
# ---------------------------------
print("\n--> 2. 开始加载和准备数据...")
video_data = pd.read_csv("origin_videos_data.csv")
comments_data = pd.read_csv("origin_comments_data.csv")
video_data["text"] = video_data["video_desc"].fillna("") + " " + video_data["video_tags"].fillna("")

因为评论有多个国家的语言,所以分类模型选的bert-base-multilingual-cased,多语言句向量模型sentence-transformers/paraphrase-multilingual-mpnet-base-v2 (也可以尝试其它模型)

任务一:商品识别

  1. 数据准备:处理数据和标签
# 1. 筛选出有商品名的数据
train_video_df = video_data[~video_data["product_name"].isnull()].copy()# 2. 获取所有不重复的商品名,并排序
labels_list = sorted(train_video_df["product_name"].unique())# 3. 创建“商品名” -> “数字ID” 的映射 (字典)
label2id = {label: i for i, label in enumerate(labels_list)}# 4. 创建“数字ID” -> “商品名” 的映射 (反向字典,方便以后查看结果)
id2label = {i: label for i, label in enumerate(labels_list)}# 5. 在数据中创建新的一列 "label",存放转换后的数字ID
train_video_df["label"] = train_video_df["product_name"].map(label2id)
  1. 分词与编码
# 1. 加载一个预训练好的分词器
#    CLASSIFICATION_MODEL 是一个预训练模型的名字,比如 "bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(CLASSIFICATION_MODEL)# 2. 对所有文本进行分词和编码
#    - tolist(): 把一列文本转换成一个列表
#    - truncation=True: 如果句子太长,就截断
#    - padding=True: 如果句子太短,就用特殊数字填充,让所有句子一样长
#    - max_length=128: 指定句子的最大长度
train_encodings = tokenizer(train_video_df["text"].tolist(), truncation=True, padding=True, max_length=128)# 3. 把我们之前转换好的数字标签也放进这个编码结果里
train_encodings['label'] = train_video_df["label"].tolist()# 4. 将整个编码结果(包含文本编码和标签)封装成一个标准的数据集对象
train_dataset = Dataset.from_dict(train_encodings)
  1. 加载模型与配置训练
# 1. 加载预训练模型
model = AutoModelForSequenceClassification.from_pretrained(CLASSIFICATION_MODEL,          # 模型的名字,要和Tokenizer一致num_labels=len(labels_list),   # 告诉模型我们总共有多少个分类id2label=id2label,             # 把我们之前创建的ID->标签映射告诉模型label2id=label2id              # 也把标签->ID的映射告诉模型
).to(DEVICE) # 2. 设置训练参数
training_args = TrainingArguments(output_dir='./results',              # 训练结果存到哪里num_train_epochs=3,                  # 所有数据要学习3遍per_device_train_batch_size=8,       # 每次看8个样本logging_dir='./logs',                # 日志存到哪里logging_steps=10,                    # 每训练10步就打印一次日志report_to="none"                     # 不上报到第三方平台
)trainer = Trainer(model=model,args=training_args,train_dataset=train_dataset
)

4.训练与预测

# 1. 开始训练
trainer.train()# 2. 使用 pipeline(管道)
classifier = pipeline("text-classification",      # 任务类型是文本分类model=model,                # 用我们刚训练好的模型tokenizer=tokenizer,        # 用我们之前加载的分词器device=0                    # 0代表使用第一块GPU,-1代表使用CPU
)# 3. 把所有视频的文本都扔给它进行预测
predictions = classifier(video_data["text"].tolist())# 4. 从预测结果中提取出标签名字,并更新回原数据
video_data["product_name"] = [pred['label'] for pred in predictions]

pipeline 是 Hugging Face 提供的最高度封装的预测工具。它把“输入原始文本 -> 分词 -> 转换成ID -> 模型预测 -> 输出 logits -> Softmax -> 翻译回标签”这一整套繁琐的流程,压缩成了一步

classifier = pipeline("任务名称", model=训练好的模型, tokenizer=配套的分词器)

优化尝试

因为我用BERT微调之后,看了一下分数只有80左右,

数据太少: 生成伪标签 + 5折交叉验证

假设标签是“答案”,有标签的数据是“教材”,就是让5个专家做没有答案的练习册,如果5个专家的答案都一样,就把这道题收入到教材,这样教材的内容就更多了,最后再让学生学习这本“教材”

  1. 分离数据: 一部分有标签(答案)和一部分没标签
# 有答案的“教材”
train_video_df = video_data[~video_data["product_name"].isnull()].copy()
# 没答案的“练习题”
unlabeled_video_df = video_data[video_data["product_name"].isnull()].copy()# ... (标签数字化的部分和之前一样) ...
  1. 训练5个模型(专家),并让每个专家做一次“练习册”,收集“答案”
    1. 把教材(train_video_df)平均分成5份。
    2. 第1轮:用第1、2、3、4份当教材训练模型,第5份当模拟考(这里代码省略了验证,直接训练)。
    3. 第2轮:用第1、2、3、5份当教材训练模型,第4份当模拟考。
    4. …以此类推,一共训练5个模型。
    5. 每个模型都学习了80%的数据,而且学习的内容都不完全相同,这样就组成了我们的“专家委员会”。
# 引入分层K折交叉验证工具,它能保证每一折里各类别的比例都差不多
from sklearn.model_selection import StratifiedKFold# 设定交叉验证:分成5份,打乱顺序
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
unlabeled_preds = [] # 用来存放5个专家对“练习题”的答案# skf.split(...) 会自动循环5次,每次都生成不同的训练集索引(train_idx)
for fold, (train_idx, val_idx) in enumerate(skf.split(train_video_df['text'], train_video_df['label'])):print(f"\n===== 开始训练第 {fold+1} 位专家 =====")# 1. 准备当前这位专家的教材train_fold_df = train_video_df.iloc[train_idx]# (数据编码过程,和之前一样,只是数据源是 train_fold_df)train_dataset = ... # 2. 请来一位全新的专家(模型)model = AutoModelForSequenceClassification.from_pretrained(...)# 3. 对这位专家进行特训trainer = Trainer(model=model, args=training_args, train_dataset=train_dataset)trainer.train()# 4. 专家学成!让他去做“练习题”(unlabeled_video_df)unlabeled_dataset = ... # 把练习题也编码成模型能读懂的格式# trainer.predict 返回原始的、未经处理的预测分数(logits)raw_preds, _, _ = trainer.predict(unlabeled_dataset)# 5. 将该专家的答案(处理成0-1之间的概率后)存起来unlabeled_preds.append(F.softmax(torch.from_numpy(raw_preds), dim=-1).numpy())
  1. 生成“新教材”
# 1. 计算平均意见:对5位专家的预测概率取平均值
#    axis=0 表示在“专家”这个维度上求平均
avg_preds = np.mean(unlabeled_preds, axis=0)# 2. 确定最终投票结果:取平均概率最高的那个类别作为预测结果(第一题选A, 对应标签0)
pred_labels = np.argmax(avg_preds, axis=1) # 得到数字标签,如 0, 1, 2# 3. 取最高的那个平均概率作为置信度分数
pred_scores = np.max(avg_preds, axis=1) # 得到分数,如 0.98, 0.75, 0.91# 4. 只有信心超过90%的答案,我们才采纳
confidence_threshold = 0.90 
pseudo_df = pd.DataFrame({'text': unlabeled_video_df['text'], 'label': pred_labels, 'score': pred_scores})
high_confidence_pseudo_df = pseudo_df[pseudo_df['score'] > confidence_threshold].copy()# 5. 将“新教材”和“老教材”合并
if not high_confidence_pseudo_df.empty:print(f"成功筛选出 {len(high_confidence_pseudo_df)} 条新教材!")combined_train_df = pd.concat([train_video_df, high_confidence_pseudo_df], ignore_index=True)
else:# 如果没筛出来,就还用老教材combined_train_df = train_video_df

4.得到新的数据集,进行训练

# 1. 准备最全的教材
final_dataset = Dataset.from_pandas(combined_train_df)
final_dataset = final_dataset.map(...) # 编码# 2. 加载模型
final_model = AutoModelForSequenceClassification.from_pretrained(...)# 3. 用所有数据进行训练
final_trainer = Trainer(model=final_model, args=training_args, train_dataset=final_dataset)
final_trainer.train()print("\n--- 开始预测所有视频... ---")
final_classifier = pipeline("text-classification", model=final_model, ...)
final_predictions = final_classifier(video_data["text"].tolist())# 更新最终结果
video_data["product_name"] = [pred['label'] for pred in final_predictions]

任务二:情感分析

任务二与任务一类似,并且数据够多。用一个 for 循环来为四个不同的情感维度分别独立地训练四个模型

任务三:评论聚类

上期使用循环选择聚类个数得分50+, 本来打算使用UMAP降维试试,但是分数还是50+(暂时没有提高分数的头绪,等提高了再补充)

结果

在这里插入图片描述

心得

算是第一次参加这类大赛,通过Datawhale的教程,很轻松的入门,写的很详细。遇到不会的也可以在群里交流,对自己提升很多。

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

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

相关文章

SPSSPRO:数据分析市场SaaS挑战者的战略分析

目录 第一部分:执行摘要 第二部分:平台解构:产品、架构与用户体验 2.1 SaaS范式转移:架构与起源 2.2 功能能力:分析师的工具箱 2.3 “智能分析”的价值主张 第三部分:市场渗透与受众细分 3.1 目标用户…

低版本hive(1.2.1)UDF实现清除历史分区数据

目标&#xff1a;通过UDF实现对表历史数据清除 入参&#xff1a;表名、保留天数N 一、pom文件 <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.…

C++中顶层const与底层const

在C中&#xff0c;const关键字用于定义常量&#xff0c;但它在指针和引用上下文中会产生两种不同的常量性&#xff1a;顶层const&#xff08;top-level const&#xff09;和底层const&#xff08;low-level const&#xff09;。理解它们的区别是避免编译错误和提高代码质量的关…

“SRP模型+”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI指数生态质量评价

集成云端、桌面端等环境&#xff0c;结合遥感云计算、GIS空间分析&#xff0c;R语言统计分析的优势&#xff0c;以分析生态环境脆弱性的时空演变为主线。通过本课程的学习&#xff0c;您将掌握&#xff1a;第一&#xff0c;收集各类指标数据&#xff0c;构建的“生态压力度-生态…

算法学习笔记:17.蒙特卡洛算法 ——从原理到实战,涵盖 LeetCode 与考研 408 例题

在计算机科学和数学领域&#xff0c;蒙特卡洛算法&#xff08;Monte Carlo Algorithm&#xff09;以其独特的随机抽样思想&#xff0c;成为解决复杂问题的有力工具。从圆周率的计算到金融风险评估&#xff0c;从物理模拟到人工智能&#xff0c;蒙特卡洛算法都发挥着不可替代的作…

Tortoise 设置

如何关闭 Windows 下 TortoiseGit 任务栏里窗口标题的分支显示 一、引言 TortoiseGit 是一个专为团队协作设计的 Git 图形化客户端&#xff0c;旨在解决版本控制中常见的问题&#xff0c;如冲突、回滚、历史查看等。本文档是 TortoiseGit 的使用手册前言部分&#xff0c;旨在向…

[论文阅读] 人工智能 + 软件工程 | AI助力软件可解释性:从用户评论到自动生成需求与解释

AI助力软件可解释性&#xff1a;从用户评论到自动生成需求与解释 Automatic Generation of Explainability Requirements and Software Explanations From User ReviewsarXiv:2507.07344 Automatic Generation of Explainability Requirements and Software Explanations From …

C语言---自定义类型(上)(结构体类型)

结构体结构体的定义与声明结构体其实和数组一样&#xff0c;都是一些值的集合&#xff0c;只不过数组是一系类相同类型的值&#xff0c;而结构体里边的成员可以是不同的数据类型。关于它的声明&#xff0c;所用到的关键字是struct。声明的语法如下&#xff1a;struct 结构体名{…

Java观察者模式实现方式与测试方法

一、实现方式 自定义实现 通过手动定义Subject和Observer接口&#xff0c;实现一对多依赖关系&#xff1a; // 观察者接口 public interface Observer {void update(float temp, float humidity, float pressure); } // 主题接口 public interface Subject {void registerObser…

leetGPU解题笔记(1)

1.题面 题目要求 向量加法 实现一个程序&#xff0c;在GPU上对两个包含32位浮点数的向量执行逐元素加法。该程序应接受两个长度相等的输入向量&#xff0c;并生成一个包含它们和的输出向量。 实现要求 禁止使用外部库 solve函数签名必须保持不变 最终结果必须存储在向量C中 示例…

5. JVM 的方法区

1. JVM介绍和运行流程-CSDN博客 2. 什么是程序计数器-CSDN博客 3. java 堆和 JVM 内存结构-CSDN博客 4. 虚拟机栈-CSDN博客 5. JVM 的方法区-CSDN博客 6. JVM直接内存-CSDN博客 7. JVM类加载器与双亲委派模型-CSDN博客 8. JVM类装载的执行过程-CSDN博客 9. JVM垃圾回收…

网络安全的基本练习

一.docker搭建 1.安装dockerapt-get install docker.io docker-compose2.编写配置文件&#xff08;注意路径正确&#xff09;vim /etc/systemd/system/docker.service.d/http-proxy.conf[Service] Environment"HTTP_PROXYhttp://科学上网访问的ip:端口" Environment&…

380. O(1) 时间插入、删除和获取随机元素

实现RandomizedSet 类&#xff1a; RandomizedSet() 初始化 RandomizedSet 对象 bool insert(int val) 当元素 val 不存在时&#xff0c;向集合中插入该项&#xff0c;并返回 true &#xff1b;否则&#xff0c;返回 false 。 bool remove(int val) 当元素 val 存在时&#xff…

【LeetCode Hot100 | 每日刷题】字母异位词分组

题目链接&#xff1a;49. 字母异位词分组 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 示例 1: 输入: strs ["eat", "tea", "tan"…

docker 安装windows

目录 下载地址&#xff1a; 使用教程&#xff1a; docker compose 查看版本 测试启动 hello-world 报错1 The system cannot find the file specified&#xff1a; 检查 Docker Desktop 是否运行中 报错2HF_ENDPOINT 1. 临时解决方案&#xff08;当前终端会话有效&…

docker compose 和build

目录 docker compose 和build 的区别是什么&#xff1f; 核心差别&#xff1a; 1. docker build --platform linux/amd64 -f Dockerfile -t infiniflow/ragflow:nightly_lbg . 2. docker compose -f docker-compose-gpu.yml up -d 二者如何配合&#xff1f; 总结 docker …

裂变时刻:全球关税重构下的券商交易系统跃迁路线图(2025-2027)

——基于RWA清算、量子加密与实时非线性风控的下一代跨境基础设施核心事件锚定&#xff1a;特朗普于7月7日对14国启动分级关税制裁&#xff08;日韩25%、东南亚30%-40%、金砖关联国10%附加税&#xff09;&#xff0c;引发日元兑美元暴跌至144.47、铜价单日跳涨3.2%、散户单日交…

python爬虫初入门——基本库和写入方法

1.准备环境 python环境&#xff1a;3.10 2.常用库 1.请求库&#xff1a;实现 HTTP 请求操作 requests&#xff1a;基于 urllib 编写的&#xff0c;阻塞式 HTTP 请求库&#xff0c;发出一个请求&#xff0c;一直等待服务器响应后&#xff0c;程序才能进行下一步处理。seleni…

Sonar扫描C#代码配置

需要的工具 MSBuild、sonar-scanner-4.6.1.2450-windows、jdk1.8.0_181 下载地址&#xff1a;https://download.csdn.net/download/code12313/91315686 配置sonar的地址 一、环境变量配置 1.新建变量&#xff0c;nameSONAR_RUNNER_MSBUILD_HOME。valueD:\work\dev\dev_serve…

python 在运行时没有加载修改后的版本

陈旧的Python字节码 (.pyc 文件)&#xff1a;最常见的原因&#xff01;Python 会把你修改的 .py 文件编译成 .pyc 字节码来加速后续运行。有时&#xff0c;即使你修改了 .py 文件&#xff0c;系统可能仍然固执地加载旧的、未被删除的 .pyc 文件。1. 用“硬编码探针”强制验证# …