bilstm+attention机制对京东评论数据进行数据处理加情感分类(能跑通)

article/2025/10/13 15:37:07

数据集

#此数据为京东评论数据分为两列一列为text,一列为target分数需要数据集私信
#1.处理数据
#导入数据处理的基础包
import numpy as np
import pandas as pd
#导入用于计数的包
from collections import Counter
import os
import requests#这里label的评分有1-5有5类
#目的是将label的数值 -1 缩放到[0,4]之间
def get_label(label):label = label - 1return label
data["target"] = data['target'].apply(get_label)#按评论进行去重,对于重复项,保留第一次出现的值
data = data.drop_duplicates('text',keep='first')
#会将标签重新从零开始顺序排序,使用参数设置drop=True删除旧的索引序列
data = data.reset_index(drop=True)import re
def clear_character(sentence):pattern1='[a-zA-Z0-9]'pattern2 = re.compile(u'[^\s1234567890::' + '\u4e00-\u9fa5]+')pattern3='[’!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~]+'line1=re.sub(pattern1,'',sentence)   #去除英文字母和数字line2=re.sub(pattern2,'',line1)   #去除表情和其他字符line3=re.sub(pattern3,'',line2)   #去除去掉残留的冒号及其它符号new_sentence=''.join(line3.split()) #去除空白return new_sentence#在["评论"]这一列使用定义的"clear_character"函数
data["text"]=data['text'].apply(clear_character)
data.head()# 导入中文分词包jieba, 并用jieba对原始文本做分词
import jieba
from tqdm import tqdm
def comment_cut(content):# TODO: 使用结巴完成对每一个comment的分词seg = list(jieba.cut(content.strip()))return seg
# 输出进度条
tqdm.pandas(desc='apply')
data['text'] = data['text'].progress_apply(comment_cut)
# 观察新的数据的格式
data.head()# 停用词可以去网上搜下载的停用词表改为json格式,读取下载的停用词表,并保存在列表中
with open("D:\\shujuji\\1\\stopwords.json","r",encoding='utf-8') as f:stopWords = f.read().split("\n")  # 去除停用词
def rm_stop_word(wordList):filtered_words = [word for word in wordList if word not in stopWords]return filtered_words#return " ".join(filtered_words)
#这行代码中.progress_apply()函数的作用等同于.apply()函数的作用,只是写成.progress_apply()函数才能被tqdm包监控从而输出进度条。
data['text'] = data['text'].progress_apply(rm_stop_word)
# 观察新的数据的格式
data.head()# 去除低频词, 去掉词频小于10的单词,并把结果存放在data['comment_processed']里
from collections import Counter
list_set = []
for i in range(len(data)):for j in data.iloc[i]['text']: list_set.extend(j)words_count = Counter(list_set)min_threshold=10
my_dict = {k: v for k, v in words_count.items() if v < min_threshold}
filteredA = Counter(my_dict)# 去除低频词
def rm_low_frequence_word(wordList):# your code, remove stop words# TODOoutstr = ''for word in wordList:if word not in filteredA:if word != '\t':outstr += wordoutstr += " "#filtered_words = [word for word in wordList if word not in filteredA]return outstr#这行代码中.progress_apply()函数的作用等同于.apply()函数的作用,只是写成.progress_apply()函数才能被tqdm包监控从而输出进度条。
data['text'] = data['text'].progress_apply(rm_low_frequence_word)
data.head()

数据样式

#进行模型处理过程
import collections
import os
import random
import  time
from tqdm import tqdm
import numpy as np
import torch
from torch import nn
import torchtext.vocab as Vocab
import torch.utils.data as Data
import torch.nn.functional as F
import matplotlib.pyplot as plt
import seaborn as sns
#os.environ["CUDA_VISIBLE_DEVICES"] = "6"
#使用GPU运算
device=torch.device("cuda:6" if torch.cuda.is_available() else "cpu")#首先将comment_processed中的每一条评论转换为列表
word_list=[str(s).split() for s in data["text"]]
print(word_list)#生成word2vec模型
from gensim.models.word2vec import Word2Vec
import time
start = time.time()
#窗口大小设置为3,词的最小出现次数为1
model_w2v = Word2Vec(word_list, window = 3, iter = 5,size=256,min_count=1)
print('完成')
end = time.time()
print('花费时间:', end - start)
print(model_w2v)#数据集做划分
from sklearn.model_selection import train_test_split
Temp_trin, valid_data = train_test_split(data,test_size=0.2, random_state=42) #默认split_ratio=0.7
train_data,test_data = train_test_split(Temp_trin,test_size=0.2, random_state=42)
train_data.to_csv("D:/shujuji/1/2/train_data.csv",index=False,header=True,encoding="utf-8")
valid_data.to_csv("D:/shujuji/1/2/valid_data.csv",index=False,header=True,encoding="utf-8")
test_data.to_csv("D:/shujuji/1/2/test_data.csv",index=False,header=True,encoding="utf-8")#torchtext处理数据过程
import torch
import torchtext 
from torchtext.legacy import data
from torchtext.legacy.data import Field
from torchtext.legacy.data import TabularDataset
torch.backends.cudnn.deterministic = True
tokenize = lambda x:x.split()
TEXT = data.Field(sequential=True,tokenize=tokenize)
LABEL = data.Field(sequential=False, dtype=torch.long, use_vocab=False)
fields = [('text',TEXT), ('label',LABEL)]#定理类划分数据集
class DataFrameDataset(data.Dataset):def __init__(self, df, fields, is_test=False, **kwargs):examples = []for i, row in df.iterrows():label = row.target if not is_test else Nonetext = row.textexamples.append(data.Example.fromlist([text, label], fields))super().__init__(examples, fields, **kwargs)@staticmethoddef sort_key(ex):return len(ex.text)@classmethoddef splits(cls, fields, train_df, val_df=None, test_df=None, **kwargs):train_data, val_data, test_data = (None, None, None)data_field = fieldsif train_df is not None:train_data = cls(train_df.copy(), data_field, **kwargs)if val_df is not None:val_data = cls(val_df.copy(), data_field, **kwargs)if test_df is not None:test_data = cls(test_df.copy(), data_field, True, **kwargs)return tuple(d for d in (train_data, val_data, test_data) if d is not None)print(f'Number of training examples: {len(train_data)}')
print(f'Number of validation examples: {len(valid_data)}')
print(f'Number of testing examples: {len(test_data)}')
train_df,val_df,test_df = DataFrameDataset.splits(fields, train_df=train_data, val_df=valid_data, test_df = test_data)# 构建词表
TEXT.build_vocab(train_df)
# print(train[0].__dict__.keys())
print(vars(train_df.examples[0]))
print(vars(test_df.examples[0]))
#语料库单词频率越高,索引越靠前。前两个默认为unk和pad。
print(TEXT.vocab.stoi)
#查看训练数据集中最常见的单词。
print(TEXT.vocab.freqs.most_common(40))
print(TEXT.vocab.itos[:10]) #查看TEXT单词表#生成词嵌入矩阵
import numpy as np
embedding_dic = dict(zip(model_w2v.wv.index2word, model_w2v.wv.syn0))
embedding_matrix = np.zeros((len(TEXT.vocab), 256))
for w, i in TEXT.vocab.stoi.items():embedding_vec = embedding_dic.get(w)if embedding_vec is not None:embedding_matrix[i] = embedding_vec
print(embedding_matrix.shape)#划分batch
from torchtext.legacy.data import Iterator, BucketIterator
train_batch_size = 64
val_batch_size = 64
test_batch_size = 64#相当于把样本划分batch,只是多做了一步,把相等长度的单词尽可能的划分到一个batch,不够长的就用padding。
# 同时对训练集和验证集进行迭代器构建
train_iterator, valid_iterator = BucketIterator.splits((train_df, val_df),batch_sizes=(train_batch_size, val_batch_size),device=device,sort_key=lambda x: len(x.text),sort_within_batch=False,repeat=False)# 对测试集进行迭代器构建
test_iterator = Iterator(test_df,batch_size=test_batch_size,device=device, sort=False,sort_within_batch=False,repeat=False)#定义bilstm+attention模型
import torch.nn as nn
import torch.nn.functional as Fclass LSTMmodel(nn.Module):def __init__(self,embedding_size,hidden_size,output_size):super(LSTMmodel,self).__init__()self.embedding=nn.Embedding(len(TEXT.vocab),256)self.lstm=nn.LSTM(embedding_size,hidden_size,num_layers=2,bidirectional=True,dropout=0.5)self.fc=nn.Linear(hidden_size*2,output_size)self.dropout = nn.Dropout(0.5)#向前传播def attention_net(self, x, query, mask=None): d_k = query.size(-1)     # d_k为query的维度# query:[batch, seq_len, hidden_dim*2], x.t:[batch, hidden_dim*2, seq_len]
#         print("query: ", query.shape, x.transpose(1, 2).shape)  # torch.Size([128, 38, 128]) torch.Size([128, 128, 38])# 打分机制 scores: [batch, seq_len, seq_len]scores = torch.matmul(query, x.transpose(1, 2)) / math.sqrt(d_k)  
#         print("score: ", scores.shape)  # torch.Size([128, 38, 38])# 对最后一个维度 归一化得分alpha_n = F.softmax(scores, dim=-1) 
#         print("alpha_n: ", alpha_n.shape)    # torch.Size([128, 38, 38])# 对权重化的x求和# [batch, seq_len, seq_len]·[batch,seq_len, hidden_dim*2] = [batch,seq_len,hidden_dim*2] -> [batch, hidden_dim*2]context = torch.matmul(alpha_n, x).sum(1)return context, alpha_ndef forward(self,text):embedded=self.embedding(text)output,(hidden,c)=self.lstm(embedded)#hidden的维度是(num_layers * num_directions, batch, hidden_size)取最后一层的前向和后向输出,[4,64,hidden_size]h = torch.cat((hidden[-1, :, :], hidden[-2, :, :]), dim=1)output = output.permute(1, 0, 2)  # [batch, seq_len, hidden_dim*2]query = self.dropout(output)# 加入attention机制attn_output, alpha_n = self.attention_net(output, query)output = self.fc(attn_output) #print("h",h)#print(h.shape)
#         output=self.fc(h)return output def train(model, iterator, optimizer, criterion):epoch_loss = 0epoch_acc = 0total_len = 0count = 0model.train() #model.train()代表了训练模式#这步一定要加,是为了区分model训练和测试的模式的。#有时候训练时会用到dropout、归一化等方法,但是测试的时候不能用dropout等方法。for batch in iterator: #iterator为train_iteratoroptimizer.zero_grad() #加这步防止梯度叠加predictions = model(batch.text)#print("predictions",predictions)#batch.comment_processed comment_processedloss = criterion(predictions, batch.label)epoch_loss += loss.item()loss.backward() #反向传播optimizer.step() #梯度下降epoch_acc += ((predictions.argmax(axis = 1)) == batch.label).sum().item()#(acc.item():一个batch的正确率) *batch数 = 正确数#train_iterator所有batch的正确数累加。total_len += len(batch.label)#计算train_iterator所有样本的数量count += 1print(f'训练了{count}个batch')return epoch_loss / total_len, epoch_acc / total_len#epoch_loss / total_len :train_iterator所有batch的损失#epoch_acc / total_len :train_iterator所有batch的正确率def evaluate(model, iterator, criterion):epoch_loss = 0epoch_acc = 0total_len = 0count = 0model.eval()#转换成测试模式,冻结dropout层或其他层。with torch.no_grad():for batch in iterator: #iterator为valid_iterator#没有反向传播和梯度下降predictions = model(batch.text)loss = criterion(predictions, batch.label)epoch_loss += loss.item()epoch_acc += ((predictions.argmax(axis = 1)) == batch.label).sum().item()total_len += len(batch.label)count += 1model.train() #调回训练模式   print(f'验证了{count}个batch')return epoch_loss / total_len, epoch_acc / total_len#设置参数
#设置超参数
EMBEDDING_SIZE = 256
HIDDEN_SIZE = 128
OUTPUT_SIZE = 5#实例化模型
model = LSTMmodel(embedding_size = EMBEDDING_SIZE,hidden_size = HIDDEN_SIZE,output_size = OUTPUT_SIZE,).to(device)#模型词向量初始化成预训练的词向量
#from_munpy ndarray和tensor转换
#将生成的词向量-id矩阵嵌入到我们的网络模型中
model.embedding.weight.data.copy_(torch.from_numpy(embedding_matrix))[2:10]def count_parameters(model): #统计模型参数return sum(p.numel() for p in model.parameters() if p.requires_grad)print(f'The model has {count_parameters(model):,} trainable parameters')import torch.optim as optim
optimizer = optim.Adam(model.parameters()) #定义优化器
criterion = nn.CrossEntropyLoss()  #定义损失函数,交叉熵损失函数
model = model.to(device) #送到gpu上去
criterion = criterion.to(device) #送到gpu上去import time 
def epoch_time(start_time, end_time):  #查看每个epoch的时间elapsed_time = end_time - start_timeelapsed_mins = int(elapsed_time / 60)elapsed_secs = int(elapsed_time - (elapsed_mins * 60))return elapsed_mins, elapsed_secs#最后训练
import math
N_EPOCHS = 10
best_valid_loss = float('inf') #无穷大
for epoch in tqdm(range (N_EPOCHS),desc='Processing'):start_time = time.time()train_loss, train_acc = train(model, train_iterator, optimizer, criterion)valid_loss, valid_acc = evaluate(model, valid_iterator, criterion)end_time = time.time()epoch_mins, epoch_secs = epoch_time(start_time, end_time)if valid_loss < best_valid_loss: #只要模型效果变好,就存模型best_valid_loss = valid_losstorch.save(model.state_dict(), 'Best-Checkpoint.pt')print(f'Epoch: {epoch+1:02} | Epoch Time: {epoch_mins}m {epoch_secs}s')print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%')print(f'\t Val. Loss: {valid_loss:.3f} |  Val. Acc: {valid_acc*100:.2f}%')

在这里插入图片描述


http://chatgpt.dhexx.cn/article/cVliNrU9.shtml

相关文章

爬取京东一万条评论-python

要求&#xff1a; 1 万条以上的京东手机评论爬取&#xff08;爬取内容为评论 score&#xff09; 浏览器部分 为了一次爬取评论更多的手机所以在选取url的时候优先筛选相应品牌评论更多的款&#xff0c;以我爬取的vivo品牌为例&#xff1a; 1.筛选评论 2.选择一款商品后点击对应…

用户评论观点抽取

1.目的&#xff1a;从用户的订单评论里&#xff0c;抽取观点&#xff0c;进行标签化&#xff0c;此标签可以用来作一些辅助决策或者填充到用户画像体系里。 其实评论挖掘的主要有两个部分&#xff0c;观点抽取和情感判断&#xff0c;主要的作用还是间接或直接引导用户购买意向…

京东API分享:获取京东商品评论接口

接口名称&#xff1a;item_review-获得JD商品评论 接口背景介绍&#xff1a; 京东是一家中国知名的综合性电商平台&#xff0c;成立于1998年。作为中国最大的B2C在线零售商之一&#xff0c;京东提供了包括电子产品、家居用品、服装配饰、食品饮料等在内的广泛商品选择。为了…

京东用户行为分析

京东用户行为分析 项目背景 京东作为传统电商巨头&#xff0c;京东商城与京东物流的发展相得益彰&#xff0c;然而各种新兴的电商模式&#xff0c;带来了千人千面的购物方式和电商平台更加激烈的竞争&#xff0c;电商平台发展初期的粗放式经营也转向了利用大数据和算法&#…

京东商城评论爬虫

一、前言 基于评论信息做情感分析模型第一步&#xff0c;收集数据。这里准备抓取京东商城的物品评论&#xff0c;大致可以分为两步。 1、获取商品id 2、获取商品评论 二、实战 接下来的代码都基于scrapy框架编写&#xff0c;请确保已经了解scrapy基础知识。 1、获取商品i…

京东商品及评论 数据采集

好吧&#xff0c;下面的爬虫是同步的&#xff0c;其实可以用协程来写&#xff0c;效率会增加很多&#xff01; 对京东的商品基本信息&#xff0c;产品参数&#xff0c;商品评论进行采集 使用BeautifulSoup解析 注意&#xff1a;由于每个产品的评论只能采集100页&#xff0c;为…

爬虫京东评论+可视化

前期工作 选取一个网站&#xff0c;最好是教育网站&#xff0c;因为教育网站很少有反爬虫机制。 在网站内打开开发者工具&#xff0c;不同的浏览器开发者工具也不同&#xff0c;但都大同小异(这里使用的是谷歌)。 在开发者工具中确定你要爬虫的部分&#xff0c;找到我们爬取数…

京东手机评论的爬取

开篇 做论文的时候&#xff0c;最多接触的就是标准的数据集&#xff0c;几乎不需要太多的结构化处理&#xff0c;下载下来就是可以直接加载使用的数据&#xff0c;课题是有关评论分析的&#xff0c;但是论文针对的都是英文数据&#xff0c;而国内电商平台其实积累了大量的评论…

京东也做社交电商了

不知道大家有没有注意到&#xff0c;这两天朋友圈好像被京东商品给刷屏了&#xff0c; 身边不少大佬朋友都通过【芬香】在朋友圈带货。 我作为一个IT技术男&#xff0c;对于新出现的事物&#xff0c;自然也去研究了一番。下面就把我了解的信息分享给大家。 1、什么是「芬香」&a…

主存与内存

计算器内存条采用的是DRAM(动态随机存储器)&#xff0c;即计算机的主存。我们通常所说的内存容量即指内存条DRAM的大小。 但是&#xff0c;严格地说&#xff0c;内存是包括主存与高速缓存(Cache&#xff0c;基于SRAM)的。可能是由于Cache相较内存条容量很小&#xff0c;毕竟内…

CPU/内存分析

一、概念理解 程序运作原理&#xff1a;一个请求发送到服务器&#xff0c;首先经过网卡&#xff0c;然后通知cpu有待处理任务&#xff0c;CPU去运行操作系统指令&#xff0c;根据请求的端口号&#xff0c;找到对应的应用程序代码&#xff0c;安排线程去处理&#xff1b;由于程…

linux服务器查看cpu和内存

一、服务器CPU情况 1 查看物理CPU个数 cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l 2 查看服务器CPU内核个数 cat /proc/cpuinfo | grep "cpu cores" | uniq 3 查看虚拟机查看核数 grep processor /proc/cpuinfo|wc -l 4 查看cpu内核频…

计算机中CPU是如何与内存交互的

这篇文章主要整理了一下计算机中的内存结构&#xff0c;以及 CPU 是如何读写内存中的数据的&#xff0c;如何维护 CPU 缓存中的数据一致性。什么是虚拟内存&#xff0c;以及它存在的必要性。如有不对请多多指教。 概述 目前在计算机中&#xff0c;主要有两大存储器 SRAM 和 D…

CPU访问内存

首先我们需要一个引子&#xff0c;引子如下&#xff1a; 作为一个计算机领域的工程师&#xff0c;这里有一个问题&#xff1a;有一个10米深的水池需要测量其水深&#xff0c;并在计算机&#xff08;或者微机&#xff09;上显示测量结果&#xff0c;保留小数点后一位。请概要的设…

计算机cpu、寄存器、内存区别

1、寄存器是中央处理器内的组成部分。它跟CPU有关。寄存器是有限存贮容量的高速存贮部件&#xff0c;它们可用来暂存指令、数据和位址。在中央处理器的控制部件中&#xff0c;包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中&#xff0c;包含的…

CPU、内存、磁盘性能监控

CPU监控 网络由设备、服务器、路由器、交换机和其他网络组件组成。CPU 是网络中所有硬件设备的组成部分。它负责设备的稳定性和性能。企业严重依赖网络&#xff0c;企业硬件的处理能力决定了网络的容量。随着 CPU 功能和硬件的快速发展&#xff0c;组织必须规划其容量并监控其…

内存、CPU、硬盘

目录 内存虚拟内存 硬盘扩充内存和硬盘CPUCPU 频率CPU 高速缓存CPU三级缓存缓存行 CPU-内存的工作原理 内存 内存是外存与CPU进⾏沟通的桥梁&#xff0c;计算机中所有程序的运⾏都在内存中进行。 内存(Memory)也称内存储器和主存储器&#xff0c;它用于暂时存放CPU中的运算数据…

内存、CPU、显存、GPU

底盘中经常会出现资源、算力等词语&#xff0c;对于里面的CPU、内存、GPU、显存&#xff0c;究竟是什么&#xff0c;这里主要对此进行一个基础认识。 一、内存 内存(Memory)也被称为内存储器&#xff0c;主要用来暂时存放CPU中的运算数据及与硬盘等外部存储器交换的数据。只要…

CPU 与 内存

CPU 与 内存 CPU控制器控制单元指令译码器指令寄存器 运算器ALU算数运算器逻辑运算器 寄存器L1&#xff0c;L2数据寄存器&#xff0c;程序计数器&#xff0c;段寄存器&#xff0c;通用寄存器&#xff0c;标志寄存器 内存 CPU 控制器 控制单元 时序控制&#xff0c;指令控制 …

cpu与内存的工作原理

计算机最核心的俩大部分&#xff1a;cpu和内存。哪它们之间有什么联系呢&#xff1f; 程序是在内存里运行的&#xff0c;程序要运行语句需要cpu发出指令给程序&#xff0c;程序收到指令后就会找到main方法&#xff0c;把执行语句的指令和需要的数据分别给cpu里的pc和registers…