1. 赛题再解读
从赛事任务中我们可以得到任务流程,包括如下图所示的三个步骤:
1.1 商品识别
首先结合数据和代码来看第一个任务。
上面是随机从video_data中抽取的10条数据可以大概窥视数据的情况,首先看表头,有video_id,video_desc,video_tag和product_name几个。第一个任务的目的其实就是利用video_desc+video_tag然后去得到product_name,比较好理解。
baseline提供的代码也比较简单:
video_data["text"] = video_data["video_desc"].fillna("") + " " + video_data["video_tags"].fillna("")
首先是将video_desc和video_tags的内容拼接然后生成新的一列内容text,方便下一步处理
product_name_predictor = make_pipeline(
TfidfVectorizer(tokenizer=jieba.lcut, max_features=50), SGDClassifier()
)
product_name_predictor.fit(
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"])
然后就是先向量化然后用有标签的数据训练一个分类器,然后用这个分类器预测没有标签的video的product_name。
1.2 情感分析
一样的我们可以看原始提供数据,这里只有comment_text是提供的有效信息,后面的几列都是需要分类或聚类后去填充的。
其中,‘sentiment_category’,‘user_scenario’, ‘user_question’, 'user_suggestion’四列就是第二个任务需要关注的分类的目标。
我们再看看提供的代码
for col in ['sentiment_category',
'user_scenario', 'user_question', 'user_suggestion']:
predictor = make_pipeline(
TfidfVectorizer(tokenizer=jieba.lcut),LinearSVC()
)
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循环去生成了四个分类器分别去得到四列的分类结果。
1.3 评论聚类
评论聚类依然是这个图,最后的几列就是你需要去聚类的变量,包括
positive_cluster_theme string 按正面倾向聚类的类簇主题词
negative_cluster_theme string 按负面倾向聚类的类簇主题词
scenario_cluster_theme string 按用户场景聚类的类簇主题词
question_cluster_theme string 按用户疑问聚类的类簇主题词
suggestion_cluster_theme string 按用户建议聚类的类簇主题词
需要注意的是有以下关系存在:
positive_cluster_theme:基于训练集和测试集中正面倾向(sentiment_category=1 或 sentiment_category=3)的评论进行聚类并提炼主题词,聚类数范围为 5~8。
negative_cluster_theme:基于训练集和测试集中负面倾向(sentiment_category=2 或 sentiment_category=3)的评论进行聚类并提炼主题词,聚类数范围为 5~8。
scenario_cluster_theme:基于训练集和测试集中用户场景相关评论(user_scenario=1)进行聚类并提炼主题词,聚类数范围为 5~8。
question_cluster_theme:基于训练集和测试集中用户疑问相关评论(user_question=1)进行聚类并提炼主题词,聚类数范围为 5~8。
suggestion_cluster_theme:基于训练集和测试集中用户建议相关评论(user_suggestion=1)进行聚类并提炼主题词,聚类数范围为 5~8。
然后代码这块,是用同样的方法,向量化+k-mean聚类去分别处理这五个聚类问题。
另外要注意的是
从第三个问题的评估指标可以看出,前两个问题的结果的好坏对这个问题的影响很大,因为它这里使用轮廓系数,只计算商品识别和情感分析均正确的。
2. 两个简单的上分小技巧
2.1 提高商品识别的准确率
那么如何去提分呢?首先从赛题情况中我们可以知道这三个任务的表现的关联性很强,因此打好基础很重要,先来解决商品名的识别问题。先看一眼baseline的结果:分数详情:商品87.692308 + 情感86.762511 + 评论0.000000,第一个任务的准确率还挺高的,但是可以更高。
通过观察得知这个问题需要很强的语义理解能力,因此直接上大杀器,调用Spark MAX模型的api来进行语义理解,然后输出产品名。下面是我的参考的prompt:
def build_global_prompt(labeled_df):
prompt = "你是一个商品分类助手。请仅返回匹配的分类标签,禁止解释、禁止输出多余文本。\n\n"
prompt += "以下是一些示例:\n"
for _, row in labeled_df.iterrows():
prompt += f"文本:{row['text']}\n分类:{row['product_name']}\n\n"
prompt += "现在请你对以下文本进行分类,只输出分类名称:\n\n"
return prompt
在使用大模型通过理解然后分类后,结果如下:商品96.923077 + 情感86.782782 + 评论0.000000,提升非常多。
2.2 提高评论聚类效果
从上面的结果我们也可以看到提分最有效的方式应该是提高评论的分数,毕竟现在是0,估计还是比较好提升的,那就从这个角度来看看吧。
从baseline给的代码我们可以看到
kmeans_predictor = make_pipeline(
TfidfVectorizer(tokenizer=jieba.lcut), KMeans(n_clusters=2)
)
kmeans_predictor.fit(comments_data[comments_data["sentiment_category"].isin([2, 3])]["comment_text"])
kmeans_cluster_label = kmeans_predictor.predict(comments_data[comments_data["sentiment_category"].isin([2, 3])]["comment_text"])
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]
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([2, 3]), "negative_cluster_theme"] = [kmeans_top_word[x] for x in kmeans_cluster_label]
n_clusters只有2,那么很简单,题目要求是5-8之间,我们可以实施更多的聚类中心,我设置了6,然后得到如下结果:
分数详情:商品96.923077 + 情感86.778569 + 评论52.288344=235.98999
提分效果显著
3.结语
从上面的处理我们可以看任务一的准确率的重要性以及仍然可以看到有许多的提升空间,欢迎各位评论区讨论!