引言
以讯飞「基于带货视频评论的用户洞察挑战赛」的赛事项目为背景,将电商直播带货视频的碎片化用户评论 转化为可量化的商业洞察信息 。其实本质上在于利用自然语言处理、机器学习或者大模型技术,从海量的文本数据中提取有价值的商业洞察。
主要涉及以下几个关键领域的任务:
- 任务一(文本编码):基于视频内容识别对应的商品
- 任务二(文本分类):从非结构化评论中提取情感倾向
- 任务三(文本聚类):通过聚类总结用户的关键观点
1. 相关知识了解
文本编码
概念: 文本(文章句子、评论等)------> 机器可识别的向量(数字向量)
大模型文本编码关键步骤:
1. 分词: 将一句话拆解成更小的语言单元(通常是单词、子词、字符)
- 例子:
输入文本:"I love AI."
分词结果可能是:["I", "love", "AI", "."]
或["I", "lov", "e", "AI", "."]
(具体取决于分词器类型)
2. 词元映射为索引每个词元都会被映射到一个词汇表中的索引号
["I", "love", "AI", "."]
→[101, 456, 987, 102]
3.位置编码(Position Encoding):
因为 Transformer 结构本身没有序列顺序的概念,所以要显式加上位置信息
4. 生成词嵌入: 每个 token 索引会被映射为一个高维稠密向量
- 举例:
[101, 456, 987, 102]
→[[0.1, 0.2, ..., 0.9], [...], ..., [...]]
- 最终形成一个二维张量
[sequence_length, embedding_dim]
,比如[4, 768]
常用方法包括独热编码、词嵌入 (如Word2Vec、GloVe等静态词向量)以及基于预训练模型的上下文词嵌入(如BERT、GPT等动态词向量)。
编码方式 | 上下文相关 | 稠密向量 | 是否需要位置编码 | 模型是否训练词向量 | 适合场景 |
---|---|---|---|---|---|
独热编码 | 否 | ❌ 稀疏 | ❌ 否 | ❌ 否 | 教学演示、早期模型 |
Word2Vec/GloVe | 否 | ✅ 静态 | ❌ 否 | ✅ 是(预训练) | 传统NLP任务 |
BERT/GPT等 | ✅ 是 | ✅ 动态 | ✅ 是 | ✅ 是(上下文训练) | 现代NLP任务、SOTA模型 |
文本分类:根据文本内容将其自动归类到预定义类别。
- 本项目中的情感分析属于多维度文本分类任务,需要识别评论的情感倾向(正面/负面/中性等)以及是否涉及用户场景、疑问或建议等属性。
- 常用方法包括基于规则和词典的方法、传统机器学习方法(如朴素贝叶斯、支持向量机SVM等)以及深度学习方法(如循环神经网络RNN、卷积神经网络CNN、Transformer等) 。
文本聚类:根据文本内容的相似性自动将文本分组,无需预先定义类别。
- 本项目要求按商品对指定维度的评论进行聚类,并提炼每类的主题词。
- 常用聚类算法包括K-Means(需预设簇数K)、层次聚类、DBSCAN等
2.赛题及数据
赛题难点
- 数据量少,挑战模型泛化能力
- 比赛提供的数据量相对较少,包含 85 条脱敏后的带货视频数据和 6477 条评论文本数据。其中,带有 人工标注结果的训练集更是有限 。
- 多任务协同,要求全链路解决方案
- 本次比赛并非单一任务,而是要求参赛者完成" 商品识别-情感分析-评论聚类 "的完整链条,每个阶段环环相扣。
解题思路
商品识别是基础,如果这里出了错,后续的情感分析和聚类就没有意义。情感分析的结果又会影响聚类的样本选择。
- 商品识别 (高优先级): 必须尽可能准确。【文本分类】
- 情感分析 (高优先级): 这是数据最丰富的部分,也是后面聚类的关键输入。【多标签文本分类】
- 评论聚类 (次高优先级): 基于前两步的结果,需要考虑聚类的效果评估(轮廓系数)和主题词提炼的质量。【无监督学习 中的文本聚类 + 主题词提取】
3.baseline解读
1.设计思路: 分阶段处理 各个任务,并利用 TF-IDF / BGE向量化 和 线性分类器/KMeans 聚类 来完成商品识别、情感分析和评论聚类。
-
计算资源需求低: 相较于大型深度学习模型,TF-IDF 和 LinearSVC/KMeans 对计算资源的要求非常低。这意味着它可以在普通的个人电脑上快速运行,无需高性能GPU,也符合比赛中可能存在的资源限制(尤其是在不使用额外付费资源的情况下)。
-
TF-IDF 的局限性: TF-IDF 仅关注词语的频率和文档分布,无法捕捉词语的 上下文信息 、 语义相似性 或 多义词 。例如,"苹果"在"买苹果手机"和"吃苹果"中含义不同,TF-IDF 无法区分。
改进:可以尝试BERT
-
K-Means 的局限性: K-Means 是一种基于距离的聚类算法,它假设簇是凸形的且大小相近。它对初始质心敏感,且无法很好地处理不规则形状的簇。
2.代码整体流程
这个 baseline 代码严格按照比赛的三个任务顺序执行:
- 任务一: 训练一个模型来预测
product_name
。 - 任务二: 训练四个模型来分别预测四个情感相关的标签。
- 任务三: 对不同类别的评论进行聚类,并提取主题词。
分步详解
- 数据准备
python
video_data["text"] = video_data["video_desc"].fillna("") + " " + video_data["video_tags"].fillna("")
因为描述和标签都包含商品有关信息,合在一起,能给模型提供更全面信息
- 任务一:商品识别
python
product_name_predictor = make_pipeline( # 创建处理流水线
# 文本向量化+分类
TfidfVectorizer(tokenizer=jieba.lcut, max_features=50), SGDClassifier()
)
product_name_predictor.fit( # 训练模型,代码筛选出 product_name 这一列有标注的行,用这些数据来训练
video_data[~video_data["product_name"].isnull()]["text"],
video_data[~video_data["product_name"].isnull()]["product_name"],
)
video_data["product_name"] = product_name_predictor.predict(video_data["text"]) # 预测
3.任务二:情感分析
python
for col in ['sentiment_category',
'user_scenario', 'user_question', 'user_suggestion']:
predictor = make_pipeline(
TfidfVectorizer(tokenizer=jieba.lcut), SGDClassifier()
)
predictor.fit(
comments_data[~comments_data[col].isnull()]["comment_text"],
comments_data[~comments_data[col].isnull()][col],
)
comments_data[col] = predictor.predict(comments_data["comment_text"])
这里用一个 for
循环,对 sentiment_category
, user_scenario
等四个目标列,重复地做了和任务一几乎一样的事情:
- 创建一个
TF-IDF
+SGDClassifier
的流水线。 - 用已有标注的评论数据进行训练。
- 对所有评论进行预测,填上对应的标签。
4.任务三:评论聚类
python
# 1. 定义并训练聚类模型
kmeans_predictor = make_pipeline(
TfidfVectorizer(tokenizer=jieba.lcut), KMeans(n_clusters=2)
)
kmeans_predictor.fit(comments_data[comments_data["sentiment_category"].isin([1, 3])]["comment_text"])
# 2. 对评论进行聚类
kmeans_cluster_label = kmeans_predictor.predict(comments_data[comments_data["sentiment_category"].isin([1, 3])]["comment_text"])
# 3. 提取每个类簇的主题词
kmeans_top_word = []
tfidf_vectorizer = kmeans_predictor.named_steps['tfidfvectorizer']
kmeans_model = kmeans_predictor.named_steps['kmeans']
feature_names = tfidf_vectorizer.get_feature_names_out()
cluster_centers = kmeans_model.cluster_centers_
for i in range(kmeans_model.n_clusters): # 遍历每个聚类中心
top_feature_indices = cluster_centers[i].argsort()[::-1] # 按TF-IDF权重排序
top_word = ' '.join([feature_names[idx] for idx in top_feature_indices[:top_n_words]])
kmeans_top_word.append(top_word)
comments_data.loc[comments_data["sentiment_category"].isin([1, 3]), "positive_cluster_theme"] = [kmeans_top_word[x] for x in kmeans_cluster_label]
named_steps
:从 pipeline 中取出各步骤的具体对象
feature_names
:TF-IDF 中的所有词(按顺序)
cluster_centers_
:每个聚类中心的向量,表示这个簇中哪些词的平均 TF-IDF 值最大
步骤:
-
1、创建聚类流水线 :这次的流水线是
TF-IDF
+KMeans
。KMeans
是一种经典的聚类算法。 -
2、筛选数据并训练 :它先从所有评论中筛选出正面或包含正面的评论(
sentiment_category
为 1 或 3),然后用这些评论来训练KMeans
模型。 -
3、预测簇标签:模型会给每一条正面评论分配一个它所属的类别标签(比如第0类或第1类)。
-
4、提取主题词 :找出TF-IDF权重最高的几个词,然后把这几个词拼成一个字符串,作为这个类别的"总结词"。
-
5、结果 :最后,把每个评论所属类别的"总结词"填到
positive_cluster_theme
这一列。
其它几个评论文本类似。
4.优化思考
对于任务一
-
模型太简单 :
TF-IDF
+SGDClassifier
是非常基础的组合,它只能学到一些表面的词频信息,理解不了深层语义。 -
参数 :
max_features=50
这个参数限制了TfidfVectorizer
只会关注最重要的50个词。尝试改为100呢?
对于任务二
- 同样是TF-IDF局限性
对于任务三
- 模型
- 聚类数 :写一个循环,尝试
n_clusters
从5到8的所有可能 。对于每一个n_clusters
值,都计算一下聚类的轮廓系数 (Silhouette Coefficient) ,选择让轮廓系数最高的那个n_clusters
值作为你最终的聚类数量
python
# 动态确定最佳聚类数
from sklearn.metrics import silhouette_score
best_k = 0
best_score = -1for k in range(5,9):
kmeans = KMeans(n_clusters=k)
labels = kmeans.fit_predict(embeddings)
score = silhouette_score(embeddings, labels)
if score > best_score:
best_k = k
优化思路1: 修改max_features参数 和循环聚类数
分数从
提高到
其它优化思路:(预训练模型 和大模型)