如何用SMOTE或其他方法对不平衡情感分类评论文本数据集过采样?
解决文本数据不平衡的过采样方案
方案一:随机过采样(最简单直接,无需向量化)
直接对少数类(rating 1、2、3)的样本做随机重复采样,直到样本量和多数类(4、5)的3000条持平。这种方法不用处理文本向量化,直接操作原数据集的行,保证reviewtext和rating完全同步。
- 代码示例(基于pandas):
import pandas as pd from sklearn.utils import resample # 假设数据集为df df_majority_4 = df[df['rating'] == 4] df_majority_5 = df[df['rating'] == 5] # 对每个少数类执行过采样 df_minority_1 = resample(df[df['rating'] == 1], replace=True, # 允许重复采样 n_samples=3000, # 匹配多数类样本量 random_state=42) df_minority_2 = resample(df[df['rating'] == 2], replace=True, n_samples=3000, random_state=42) df_minority_3 = resample(df[df['rating'] == 3], replace=True, n_samples=3000, random_state=42) # 合并得到平衡数据集 df_balanced = pd.concat([df_majority_4, df_majority_5, df_minority_1, df_minority_2, df_minority_3]) # 验证平衡结果 print(df_balanced['rating'].value_counts())
- 优点:零额外成本,完全保留原文本语义,无合成样本噪声
- 缺点:重复样本可能导致模型过拟合
方案二:文本生成式过采样(生成全新文本,无需先向量化)
用文本生成模型为少数类合成语义相似的新评论,既平衡数据,又避免随机采样的过拟合问题。可以用Hugging Face的预训练模型快速实现。
- 代码示例(基于GPT2简化版):
from transformers import GPT2LMHeadModel, GPT2Tokenizer import torch # 加载预训练模型与分词器 tokenizer = GPT2Tokenizer.from_pretrained('gpt2') model = GPT2LMHeadModel.from_pretrained('gpt2') tokenizer.pad_token = tokenizer.eos_token # 定义文本生成函数 def generate_review(prompt, max_length=100): inputs = tokenizer(prompt, return_tensors='pt', padding=True) outputs = model.generate(**inputs, max_length=max_length, num_return_sequences=1, do_sample=True) return tokenizer.decode(outputs[0], skip_special_tokens=True) # 示例:从rating=1的样本中选一条作为prompt生成新评论 sample_prompt = df[df['rating'] == 1]['reviewtext'].iloc[0] new_review = generate_review(sample_prompt) # 将生成的评论与对应rating加入数据集 df = pd.concat([df, pd.DataFrame({'reviewtext': [new_review], 'rating': [1]})], ignore_index=True)
- 注意:需批量为每个少数类补够1000条样本,也可选用更贴合评论场景的预训练模型(如
distilgpt2) - 优点:生成全新样本,降低过拟合风险
- 缺点:需要一定计算资源,生成文本质量需人工校验
方案三:SMOTE结合文本向量化(正确处理稀疏矩阵)
你之前的误区是认为SMOTE需要“单条文本单独向量化”,实际上整个数据集向量化后的稀疏矩阵可直接用于SMOTE——矩阵每行对应一条文本的向量,和rating的顺序完全匹配。但要注意:SMOTE生成的是数值向量,无法还原为原始文本,仅适合无需保留合成文本的模型训练场景。
- 步骤与代码示例:
from sklearn.feature_extraction.text import TfidfVectorizer from imblearn.over_sampling import SMOTE # 文本向量化(用TF-IDF生成稀疏矩阵) vectorizer = TfidfVectorizer(max_features=5000) X = vectorizer.fit_transform(df['reviewtext']) y = df['rating'] # 应用SMOTE过采样(k_neighbors需小于少数类样本量) smote = SMOTE(random_state=42, k_neighbors=5) X_resampled, y_resampled = smote.fit_resample(X, y) # 平衡后的X_resampled与y_resampled可直接用于模型训练,但无法还原为文本
- 优点:生成特征空间的合成样本,避免随机采样的重复问题
- 缺点:无法得到对应的合成文本,仅能用于模型训练
单条文本向量化方法
若需单独处理单条文本,可直接用训练好的向量化器:
# 用之前训练的TF-IDF向量器处理单条评论 single_review = "This product is terrible" single_vector = vectorizer.transform([single_review]) # single_vector为该文本的稀疏矩阵形式,与之前的X格式一致
但此方法对过采样无帮助,因为SMOTE需要基于整个数据集的特征矩阵计算邻居,单条向量无法单独生成新样本。
内容的提问来源于stack exchange,提问作者Sughosh Indurkar
相关产品推荐
相关产品推荐

