当前位置:   article > 正文

基于pytorch的循环神经网络情感分析系统_pytorch情感分析模型

pytorch情感分析模型

任务目标

基于给定数据集,进行数据预处理,搭建以LSTM为基本单元的模型,以Adam优化器对模型进行训练,使用训练后的模型进行预测并计算预测分类的准确率。

数据简介

IMDB数据集是一个对电影评论标注为正向评论与负向评论的数据集,共有25000条文本数据作为训练集,25000条文本数据作为测试集。

已知数据集中数据格式如下

1、读取数据

在这里插入图片描述

2、数据预处理

首先,对于创建词汇表,记录每一个单词出现的频率,并由此将特征数据集转为特征向量。最后转化为tensor格式

在这里插入图片描述
由于数据量庞大,这里先用PCA将数据降维,这里选择降到20个维度

在这里插入图片描述
将特征数据集和标签进行匹配,并每两个数据作为一个批次,全部数据进行随机的打乱

在这里插入图片描述

模型构建

这里采用pytorch中的LSTM来得到LSTM层的状态
在这里插入图片描述
LSTM层总共设置4层,传入初始隐藏状态的细胞内容和输入内容。最后取得最后的时间步的输出

模型训练

损失函数选择均方误差函数,优化器选择了Adam优化,总共训练4个epoch

在这里插入图片描述

损失值变化图像

绘制出损失值的变化图像

在这里插入图片描述

模型评估

将测试集的内容导入并做和训练集一样的预处理,然后将测试集放入模型中,将均方误差作为评价标准,计算平均误差。

在这里插入图片描述
并绘制出误差图像

误差都在0.003到0.005之间,说明模型能够正确预测情感。

完整代码

 
import gzip
import pandas as pd
from io import StringIO
import torch
import torch.nn as nn
import torch.optim as optim
 
 
feat_file_path = 'labeledBow.feat'
 
with open(feat_file_path, 'r') as file:
    lines = file.readlines()  # 逐行读取文件内容
 
 
# 显示部分文件内容(可根据需要调整)
# for line in lines[990:1000]:  # 显示前10行内容
#     print(line)
 
 
# In[2]:
 
 
labels = []
features = []
 
for line in lines:
    parts = line.split(' ')
    labels.append(int(parts[0]))
    feats = {}
    for part in parts[1:]:
        index, value = part.split(':')
        feats[int(index)] = float(value)
    features.append(feats)
 
 
# In[3]:
 
 
# 1. 创建词汇表
vocab = {}
for feat_dict in features:
    vocab.update(feat_dict)
 
# 创建特征索引到新的连续索引的映射
feature_idx = {feat: idx for idx, feat in enumerate(sorted(vocab.keys()))}
 
# 2. 创建特征向量
max_features = len(vocab)
feature_vectors = []
for feat_dict in features:
    # 初始化特征向量
    vector = [0.0] * max_features
    
    # 填充特征向量
    for feat_idx, feat_value in feat_dict.items():
        vector[feature_idx[feat_idx]] = feat_value
    
    feature_vectors.append(vector)
 
# 3. 转换为张量
features_tensor = torch.tensor(feature_vectors, dtype=torch.float32)
 
# 检查张量形状
print(features_tensor.shape)
 
 
# In[4]:
 
 
from sklearn.decomposition import PCA
import torch
 
# features_tensor 是特征张量,大小为 torch.Size([25000, 89527])
# 这里将其转换为 NumPy 数组
features_np = features_tensor.numpy()
 
# 初始化PCA,选择需要降维的维度,这里假设降到100维
pca = PCA(n_components=20)
 
# 用PCA拟合数据
features_reduced = pca.fit_transform(features_np)
 
# 将降维后的数据转换回张量形式
features_reduced_tensor = torch.tensor(features_reduced)
 
# 打印降维后的数据大小
print(features_reduced_tensor.size())
 
 
# In[5]:
 
 
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
 
labels_tensor = torch.tensor(labels, dtype=torch.float32)
features_reduced = features_reduced_tensor.unsqueeze(1) 
labels_t = labels_tensor.unsqueeze(1) 
 
train_data = TensorDataset(features_reduced, labels_t)
train_loader = DataLoader(train_data, batch_size=2, shuffle=True)
 
class LSTMModel(nn.Module):
    def __init__(self, input_size, hidden_size, output_size, num_layers=4):
        super(LSTMModel, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)
 
    def forward(self, x):
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        out, _ = self.lstm(x, (h0, c0))
        out = self.fc(out[:, -1, :])  # 取最后一个时间步的输出
        return out
 
# 定义模型参数
input_size = 20
hidden_size = 128
num_layers = 4
output_size = 1
 
# 初始化模型、损失函数和优化器
model = LSTMModel(input_size, hidden_size, output_size, num_layers)
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.0001)
losses = []  # 存储损失值
# 训练模型
num_epochs = 5
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
 
for epoch in range(num_epochs):
    for i, (inputs, targets) in enumerate(train_loader):
        inputs, targets = inputs.to(device), targets.to(device)
        
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs.squeeze(), targets.squeeze())
 
        loss.backward()
        optimizer.step()
        losses.append(loss.item())  # 记录损失值
        if (i+1) % 2 == 0:
            print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item()}')
 
 
 
 
# In[6]:
 
 
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import matplotlib.pyplot as plt
# 绘制损失值变化图
plt.plot(losses, label='Training Loss')
plt.xlabel('Training Steps')
plt.ylabel('Loss')
plt.title('Training Loss over Steps')
plt.legend()
plt.show()
 
 
# In[7]:
 
 
feat_file_path = 'labeledBow_test.feat'
 
with open(feat_file_path, 'r') as file:
    lines = file.readlines()  # 逐行读取文件内容
 
labels_test = []
features_test = []
 
for line in lines:
    parts = line.split(' ')
    labels_test.append(int(parts[0]))
    feats = {}
    for part in parts[1:]:
        index, value = part.split(':')
        feats[int(index)] = float(value)
    features_test.append(feats)
 
 
# In[8]:
 
 
# 1. 创建词汇表
vocab = {}
for feat_dict in features_test:
    vocab.update(feat_dict)
 
# 创建特征索引到新的连续索引的映射
feature_idx = {feat: idx for idx, feat in enumerate(sorted(vocab.keys()))}
 
# 2. 创建特征向量
max_features = len(vocab)
feature_vectors = []
for feat_dict in features_test:
    # 初始化特征向量
    vector = [0.0] * max_features
    
    # 填充特征向量
    for feat_idx, feat_value in feat_dict.items():
        vector[feature_idx[feat_idx]] = feat_value
    
    feature_vectors.append(vector)
 
# 3. 转换为张量
features_tensor = torch.tensor(feature_vectors, dtype=torch.float32)
 
# 检查张量形状
print(features_tensor.shape)
 
 
# In[9]:
 
 
from sklearn.decomposition import PCA
import torch
 
# features_tensor 是特征张量,大小为 torch.Size([25000, 89527])
# 这里将其转换为 NumPy 数组
features_np = features_tensor.numpy()
 
# 初始化PCA,选择需要降维的维度,这里假设降到100维
pca = PCA(n_components=20)
 
# 用PCA拟合数据
features_reduced = pca.fit_transform(features_np)
 
# 将降维后的数据转换回张量形式
features_reduced_tensor = torch.tensor(features_reduced)
 
# 打印降维后的数据大小
print(features_reduced_tensor.size())
 
 
# In[14]:
 
 
from torch.utils.data import DataLoader, TensorDataset
 
labels_tensor = torch.tensor(labels_test, dtype=torch.float32)
features_reduced = features_reduced_tensor.unsqueeze(1) 
labels_t = labels_tensor.unsqueeze(1) 
 
train_data = TensorDataset(features_reduced, labels_t)
train_loader = DataLoader(train_data, batch_size=2, shuffle=True)
 
losses = []
 
for epoch in range(num_epochs):
    for i, (inputs, targets) in enumerate(train_loader):
        inputs, targets = inputs.to(device), targets.to(device)
        outputs = model(inputs)
        loss = criterion(outputs.squeeze(), targets.squeeze())
        losses.append(loss.item()/len(train_loader))
        if (i+1) % 2 == 0:
            print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {loss.item()/len(train_loader)}')
 
 
# In[15]:
 
 
plt.plot(losses, label='Training Loss')
plt.xlabel('Training Steps')
plt.ylabel('Loss')
plt.title('Training Loss over Steps')
plt.legend()
plt.show()
 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号