【自然语言处理】微博评论情感分析——从数据预处理到词向量实战
微博评论情感分析:从数据预处理到词向量构建
- 简介
- 一、项目介绍
- 1. 项目任务
- 2. 数据处理策略
- 1)核心目标
- 2)输入词向量格式
- 3)固定输入长度
- 4)超长评论处理
- 5)不足长度填充
- 6)词表压缩
- 7)未登录词处理
- 二、代码实现
- 1. 构建词表(vocab_create.py)
- 词表构建逻辑说明
- 2. 数据加载与预处理(load_dataset.py)
- 数据格式说明
- 3. 数据迭代器(DatasetIterator)
- DatasetIterator 核心功能
- 三、总结
- 项目核心流程回顾
- 关键技术要点
简介
在当今信息爆炸的时代,海量的文本数据如社交媒体评论、产品评价、新闻留言等不断涌现,这些文本中蕴含着人们丰富的情感态度——无论是对商品的喜爱、对政策的支持,还是对服务的不满。自然语言处理(NLP)领域中的情感分析技术,正是挖掘这些情感信息的关键工具。
情感分析,也常被称为意见挖掘,它通过计算机技术对文本数据进行处理、分析和理解,自动识别和提取文本中所包含的情感倾向,如积极、消极、中性,甚至还能进一步细分为喜悦、愤怒、悲伤、惊讶等具体的情感类别,为企业决策、公共舆情监测、个人服务等诸多领域提供有力的支持。
一、项目介绍
1. 项目任务
本项目旨在对微博评论信息进行情感分析,建立模型自动识别评论所表达的情绪状态(如积极、消极、中性等)。
2. 数据处理策略
在深度学习的 NLP 任务中,文本数据无法直接输入模型,需要先将其转换为数值形式。以下是本项目中的核心处理策略:
1)核心目标
将每条评论内容转换为词向量形式,作为模型的输入。
2)输入词向量格式
每个词/字转换为200 维的词向量。本项目采用腾讯训练好的词向量模型(原始维度为 4960 维),如需该模型文件可私信获取。
3)固定输入长度
每次传入模型的词/字个数需要固定。例如设定输入长度为 32,则每条评论传入的数据格式为32 × 200的矩阵,表示该批次 32 个词的向量表示。
4)超长评论处理
如果一条评论超过 32 个词/字,直接截断,删除后面的内容。
5)不足长度填充
如果一条评论不足 32 个词/字,使用特殊标记<PAD>进行填充,补齐到固定长度。
6)词表压缩
语料库中的词/字数量庞大,部分低频词难以训练出有效特征。因此项目中选择出现频率最高的4760 个词构建词表。
7)未登录词处理
被压缩掉的低频词以及词表中不存在的词,统一使用特殊标记<UNK>替代。
二、代码实现
1. 构建词表(vocab_create.py)
本模块负责读取原始数据,统计字符频率,构建固定大小的词表并保存。
fromtqdmimporttqdmimportpickleaspkl MAX_VOCAB_SIZE=4760UNK,PAD='<UNK>','<PAD>'defbuild_vocab(file_path,max_size,min_freq):""" 基于文本内容构建词表 参数: file_path: 数据文件路径 max_size: 词表最大容量 min_freq: 最小词频阈值 返回: vocab_dic: 词表字典 {字符: 索引} """tokenizer=lambdax:[yforyinx]# 分字函数vocab_dic={}withopen(file_path,'r',encoding='UTF-8')asf:i=0forlineintqdm(f):# 跳过表头ifi==0:i+=1continue# 提取评论内容(跳过标签和逗号)content=line[2:].strip()ifnotcontent:continue# 统计每个字符的出现频率forwordintokenizer(content):vocab_dic[word]=vocab_dic.get(word,0)+1# 按词频降序排列,取前 max_size 个vocab_list=sorted([itemforiteminvocab_dic.items()ifitem[1]>min_freq],key=lambdax:x[1],reverse=True)[:max_size]# 构建词表字典vocab_dic={word:idxforidx,(word,_)inenumerate(vocab_list)}vocab_dic.update({UNK:len(vocab_dic),PAD:len(vocab_dic)+1})# 保存词表pkl.dump(vocab_dic,open('simplifyweibo_4_moods.pkl','wb'))print(f'词表大小:{len(vocab_dic)}')returnvocab_dicif__name__=='__main__':vocab=build_vocab('simplifyweibo_4_moods.csv',MAX_VOCAB_SIZE,1)print('词表构建完成')词表构建逻辑说明
| 步骤 | 说明 |
|---|---|
| 1 | 从 CSV 文件中读取中文评论文本 |
| 2 | 统计每个字符在语料中出现的次数 |
| 3 | 按词频降序排列,保留前 4760 个高频字符 |
| 4 | 为每个字符分配唯一索引(0~4759) |
| 5 | 添加<UNK>(索引 4760)和<PAD>(索引 4761) |
| 6 | 将词表序列化保存为 .pkl 文件 |
2. 数据加载与预处理(load_dataset.py)
本模块负责读取数据、进行填充/截断、划分数据集。
fromtqdmimporttqdmimportpickleaspklimportrandomimporttorch UNK,PAD='<UNK>','<PAD>'defload_dataset(path,pad_size=70):""" 加载数据集并进行预处理 参数: path: 数据文件路径 pad_size: 固定序列长度 返回: vocab: 词表字典 train_data: 训练集 dev_data: 验证集 test_data: 测试集 """contents=[]vocab=pkl.load(open('simplifyweibo_4_moods.pkl','rb'))tokenizer=lambdax:[yforyinx]withopen(path,'r',encoding='utf8')asf:i=0forlineintqdm(f):# 跳过表头ifi==0:i+=1continueifnotline:continue# 提取标签和评论内容label=int(line[0])content=line[2:].strip('\n')# 分字token=tokenizer(content)seq_len=len(token)# 填充或截断到 pad_sizeifpad_size:iflen(token)<pad_size:token.extend([PAD]*(pad_size-len(token)))else:token=token[:pad_size]seq_len=pad_size# 字符转索引words_line=[vocab.get(word,vocab.get(UNK))forwordintoken]contents.append((words_line,label,seq_len))# 随机打乱random.shuffle(contents)# 按 8:1:1 划分训练集、验证集、测试集total=len(contents)train_data=contents[:int(total*0.8)]dev_data=contents[int(total*0.8):int(total*0.9)]test_data=contents[int(total*0.9):]returnvocab,train_data,dev_data,test_dataif__name__=='__main__':vocab,train_data,dev_data,test_data=load_dataset('simplifyweibo_4_moods.csv')print(f'训练集:{len(train_data)}条')print(f'验证集:{len(dev_data)}条')print(f'测试集:{len(test_data)}条')数据格式说明
处理后的每条数据是一个三元组:
| 字段 | 类型 | 说明 |
|---|---|---|
| words_line | list[int] | 字符索引列表(长度为 pad_size) |
| label | int | 情感标签(0/1/2等) |
| seq_len | int | 填充前的实际长度 |
3. 数据迭代器(DatasetIterator)
本模块负责将数据按批次打包,转换为 PyTorch Tensor,并支持迭代访问。
classDatasetIterator:"""数据集迭代器:批次化处理 + Tensor 转换"""def__init__(self,batches,batch_size,device):self.batch_size=batch_size self.batches=batches self.n_batches=len(batches)//batch_size self.residue=len(batches)%batch_size!=0self.index=0self.device=devicedef_to_tensor(self,datas):"""将批次数据转换为 Tensor"""x=torch.LongTensor([_[0]for_indatas]).to(self.device)y=torch.LongTensor([_[1]for_indatas]).to(self.device)seq_len=torch.LongTensor([_[2]for_indatas]).to(self.device)return(x,seq_len),ydef__next__(self):"""迭代下一批次"""# 处理剩余样本ifself.residueandself.index==self.n_batches:batches=self.batches[self.index*self.batch_size:len(self.batches)]self.index+=1returnself._to_tensor(batches)# 迭代结束ifself.index>self.n_batches:self.index=0raiseStopIteration# 正常批次start=self.index*self.batch_size end=(self.index+1)*self.batch_size batches=self.batches[start:end]self.index+=1returnself._to_tensor(batches)def__iter__(self):returnselfdef__len__(self):returnself.n_batches+(1ifself.residueelse0)DatasetIterator 核心功能
| 功能 | 说明 |
|---|---|
| 批次化处理 | 将数据分批加载,避免内存溢出 |
| 自动转换 Tensor | 将 Python 数据转为 PyTorch Tensor |
| 设备兼容 | 自动将数据分配到 CPU 或 GPU |
| 标准迭代接口 | 支持 for 循环和 len() 操作 |
三、总结
项目核心流程回顾
词表构建:统计语料字符频率 → 筛选高频词 → 分配索引 → 保存词表
数据预处理:读取文本 → 分字 → 填充/截断 → 转索引 → 划分数据集
批次迭代:按批次加载数据 → 转 Tensor → 供模型训练使用
关键技术要点
固定输入长度是 NLP 模型训练的基本要求
用于填充不足部分, 用于处理未登录词
词表压缩可减少模型参数量,提升训练效率
数据集迭代器是连接预处理和模型训练的关键桥梁