文章目录
前言
本文使用pytorch,利用两种神经网络(lstm,cnn)实现中文的文本情感识别。代码都有详细的注释说明。使用的是谭松波酒店评价语料库,其中包含3000条负面评价,7000条正面评价。
一、数据处理与Word2vec词向量训练
原始的语料数据如下图

通过txt进行处理,将文本前的1与空格去除,得到结果如下图,将其作为程序的输入

将输入的文本进行预处理,利用jieba函数库进行分词
def del_stop_words(text): #分词
word_ls = jieba.lcut(text)
#word_ls = [i for i in word_ls if i not in stopwords]
return word_ls
with open("F:/python_data/practice/tansongbo/neg.txt", "r", encoding='UTF-8') as e: # 加载负面语料
neg_data1 = e.readlines()
with open("F:/python_data/practice/tansongbo/pos.txt", "r", encoding='UTF-8') as s: # 加载正面语料
pos_data1 = s.readlines()
neg_data = sorted(set(neg_data1), key=neg_data1.index) #列表去重 保持原来的顺序
pos_data = sorted(set(pos_data1), key=pos_data1.index)
neg_data = [del_stop_words(data.replace("\n", "")) for data in neg_data] # 处理负面语料
pos_data = [del_stop_words(data.replace("\n", "")) for data in pos_data]
all_sentences = neg_data + pos_data # 全部语料 用于训练word2vec
训练词向量,创建词向量词典
####训练过一次后可以不再训练词向量模型####
####用于训练词向量模型###
model = Word2Vec(all_sentences, # 上文处理过的全部语料
size=100, # 词向量维度 默认100维
min_count=1, # 词频阈值 词出现的频率 小于这个频率的词 将不予保存
window=5 # 窗口大小 表示当前词与预测词在一个句子中的最大距离是多少
)
model.save('f.model') # 保存模型
#加载模型,提取出词索引和词向量
def create_dictionaries(model):
gensim_dict = Dictionary() # 创建词语词典
gensim_dict.doc2bow(model.wv.vocab.keys(), allow_update=True)
w2indx = {
v: k + 1 for k, v in gensim_dict.items()} # 词语的索引,从1开始编号
w2vec = {
word: model[word] for word in w2indx.keys()} # 词语的词向量
return w2indx, w2vec
model = Word2Vec.load('F:/python_data/practice/tansongbo/f.model') # 加载模型
index_dict, word_vectors= create_dictionaries(model) # 索引字典、词向量字典
#使用pickle进行字典索引与词向量的存储
output = open('F:/python_data/practice/tansongbo/dict.txt' + ".pkl", 'wb')
pickle.dump(index_dict, output) # 索引字典
pickle.dump(word_vectors, output) # 词向量字典
output.close()
二、创建神经网络的输入batch
将文本句子转换为词向量的多维矩阵,并创建输入到神经网络中的batch#参数设置
vocab_dim = 100 # 向量维度
maxlen = 28 # 文本保留的最大长度
n_epoch = 10 # 迭代次数
batch_size = 64 #每次送入网络的句子数
#加载词向量数据,填充词向量矩阵
f = open("F:/python_data/practice/tansongbo/dict.txt.pkl", 'rb') # 预先训练好的
index_dict = pickle.load(f) # 索引字典,{单词: 索引数字}
word_vectors = pickle.load(f) # 词向量, {单词: 词向量(100维长的数组)}
n_symbols = len(index_dict) + 1 # 索引数字的个数,因为有的词语索引为0,所以+1
embedding_weights = np.zeros((n_symbols, vocab_dim)) # 创建一个n_symbols * 100的0矩阵
for w, index in index_dict.items(): # 从索引为1的词语开始,用词向量填充矩阵
embedding_weights[index, :] = word_vectors[w] # 词向量矩阵,第一行是0向量(没有索引为0的词语,未被填充)
#将文本数据映射成数字(是某个词的编号,不是词向量)
def text_to_index_array(p_new_dic, p_sen):
##文本或列表转换为索引数字
if type(p_sen) == list:
new_sentences = []
for sen in p_sen:
new_sen = []
for word in sen:
try:
new_sen.append(p_new_dic[word]) # 单词转索引数字
except:
new_sen.append(0) # 索引字典里没有的词转为数字0
new_sentences.append(new_sen)
return np.array(new_sentences) # 转numpy数组
else:
new_sentences = []
sentences = []
p_sen = p_sen.split(" ")
for word in p_sen:
try:
sentences.append(p_new_dic[word]) # 单词转索引数字
except:
sentences.append(0) # 索引字典里没有的词转为数字0
new_sentences.append(sentences)
return new_sentences
#将数据切割成一样的指定长度
def text_cut_to_same_long(sents):
data_num = len(sents)
new_sents = np.zeros((data_num,maxlen)) #构建一个矩阵来装修剪好的数据
se = []
for i in range(len(sents)):
new_sents[i,:] = sents[i,:maxlen]
new_sents = np.array(new_sents)
return new_sents
#将每个句子的序号矩阵替换成词向量矩阵
def creat_wordvec_tensor(embedding_weights,X_T):
X_tt = np.zeros((len(X_T),maxlen,vocab_dim))
num1 = 0
num2 = 0
for j in X_T:
for i in j:
X_tt[num1,num2,:] = embedding_weights[int(i),:]
num2 = num2+1
num1 = num1+1
num2 = 0
return X_tt
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print ('正在使用计算的是:%s'%device)
data = all_sentences #获取之前分好词的数据
# 读取语料类别标签
label_list = ([0] * len(neg_data) + [1] * len(pos_data))
# 划分训练集和测试集,此时都是list列表
X_train_l, X_test_l, y_train_l, y_test_l = train_test_split(data, label_list, test_size=0.2)
#print (X_train_l[0])
# 转为数字索引形式
# token = Tokenizer(num_words=3000) #字典数量
# token.fit_on_texts(train_text)
X_train = text_to_index_array(index_dict, X_train_l)
X_test = text_to_index_array(index_dict, X_test_l)
#print("训练集shape: ", X_train[0])
y_train = np.array(y_train_l) # 转numpy数组
y_test = np.array(y_test_l)
##将数据切割成一样的指定长度
from torch.nn.utils.rnn import pad_sequence
#将数据补长变成和最长的一样长
X_train = pad_sequence([torch.from_numpy(np.array(x)) for x in X_train],batch_first=True).float()
X_test = pad_sequence([torch.from_numpy(np.array(x)) for x in X_test],batch_first=True).float()
#将数据切割成需要的样子
X_train = text_cut_to_same_long(X_train)
X_test = text_cut_to_same_long(X_test)
#将词向量字典序号转换为词向量矩阵
X_train = creat_wordvec_tensor(embedding_weights,X_train)
X_test = creat_wordvec_tensor(embedding_weights,X_test)
#print("训练集shape: ", X_train.shape)
#print("测试集shape: ", X_test.shape)
####Datloader和创建batch####
from torch.utils.data import TensorDataset, DataLoader
# 创建Tensor datasets
train_data = TensorDataset(torch.from_numpy(X_train), torch.from_numpy(y_train))
test_data = TensorDataset(torch.from_numpy(X_test), torch.from_numpy(y_test))
# shuffle是打乱数据顺序
train_loader = DataLoader(train_data, shuffle=True, batch_size=batch_size)
test_loader = DataLoader(test_data, shuffle=True, batch_size=batch_size)
三、神经网络模型
1.LSTM
class lstm(nn.Module):
def __init__(self):
super(lstm, self)

本文介绍如何使用PyTorch和两种神经网络(LSTM与CNN)实现中文文本的情感识别任务。通过对谭松波酒店评价语料库进行数据预处理、词向量训练、神经网络模型搭建及训练等步骤,最终实现了文本情感的自动识别。
9286

被折叠的 条评论
为什么被折叠?



