对paddle上的案例进行少许调整得到如下,剩下的运行即可
# 库文件导入
# encoding=utf8
import re
import random
import requests
import numpy as np
import paddle
from paddle.nn import Embedding
import paddle.nn.functional as F
from paddle.nn import LSTM, Embedding, Dropout, Linear
import os
import jieba
import paddle.fluid
from build_dict import build_dict
from convert_corpus_to_id import convert_corpus_to_id
from data_preprocess import data_preprocess
from load_comment import load_comment
from __init__ import SentimentClassifier
from build_batch import build_batch
paddle.set_device('gpu')
# 这之后的PaddlePaddle计算将会在GPU上进行
paddle.seed(0)
random.seed(0)
np.random.seed(0)
train_corpus = load_comment(True)
test_corpus = load_comment(False)
train_corpus = data_preprocess(train_corpus)
test_corpus = data_preprocess(test_corpus)
word2id_freq, word2id_dict = build_dict(train_corpus)
train_corpus = convert_corpus_to_id(train_corpus, word2id_dict)
test_corpus = convert_corpus_to_id(test_corpus, word2id_dict)
# 定义训练参数
epoch_num = 5
batch_size = 128
learning_rate = 0.0001
dropout_rate = 0.2
num_layers = 2 # 这里改为2
hidden_size = 256
embedding_size = 256
max_seq_len = 128
vocab_size = len(word2id_freq)
# 实例化模型
sentiment_classifier = SentimentClassifier(hidden_size, vocab_size, embedding_size, num_steps=max_seq_len, num_layers=num_layers, dropout_rate=dropout_rate)
# 指定优化策略,更新模型参数
optimizer = paddle.optimizer.Adam(learning_rate=learning_rate, beta1=0.9, beta2=0.999, parameters= sentiment_classifier.parameters())
# 定义训练函数
# 记录训练过程中的损失变化情况,可用于后续画图查看训练情况
losses = []
steps = []
def train(model):
# 开启模型训练模式
model.train()
# 建立训练数据生成器,每次迭代生成一个batch,每个batch包含训练文本和文本对应的情感标签
train_loader = build_batch(word2id_dict, train_corpus, batch_size, epoch_num, max_seq_len)
for step, (sentences, labels) in enumerate(train_loader):
# 获取数据,并将张量转换为Tensor类型
sentences = paddle.to_tensor(sentences)
labels = paddle.to_tensor(labels)
# 前向计算,将数据feed进模型,并得到预测的情感标签和损失
logits = model(sentences)
# 计算损失
loss = F.cross_entropy(input=logits, label=labels, soft_label=False)
loss = paddle.mean(loss)
# 后向传播
loss.backward()
# 更新参数
optimizer.step()
# 清除梯度
optimizer.clear_grad()
if step % 100 == 0:
# 记录当前步骤的loss变化情况
losses.append(loss.numpy()[0])
steps.append(step)
# 打印当前loss数值
print("step %d, loss %.3f" % (step, loss.numpy()[0]))
#训练模型
train(sentiment_classifier)
# 保存模型,包含两部分:模型参数和优化器参数
model_name = "sentiment_classifier"
# 保存训练好的模型参数
paddle.save(sentiment_classifier.state_dict(), "{}.pdparams".format(model_name))
# 保存优化器参数,方便后续模型继续训练
paddle.save(optimizer.state_dict(), "{}.pdopt".format(model_name))
def evaluate(model):
# 开启模型测试模式,在该模式下,网络不会进行梯度更新
model.eval()
# 定义以上几个统计指标
tp, tn, fp, fn = 0, 0, 0, 0
# 构造测试数据生成器
test_loader = build_batch(word2id_dict, test_corpus, batch_size, 1, max_seq_len)
for sentences, labels in test_loader:
# 将张量转换为Tensor类型
sentences = paddle.to_tensor(sentences)
labels = paddle.to_tensor(labels)
# 获取模型对当前batch的输出结果
logits = model(sentences)
# 使用softmax进行归一化
probs = F.softmax(logits)
# 把输出结果转换为numpy array数组,比较预测结果和对应label之间的关系,并更新tp,tn,fp和fn
probs = probs.numpy()
for i in range(len(probs)):
# 当样本是的真实标签是正例
if labels[i][0] == 1:
# 模型预测是正例
if probs[i][1] > probs[i][0]:
tp += 1
# 模型预测是负例
else:
fn += 1
# 当样本的真实标签是负例
else:
# 模型预测是正例
if probs[i][1] > probs[i][0]:
fp += 1
# 模型预测是负例
else:
tn += 1
# 整体准确率
accuracy = (tp + tn) / (tp + tn + fp + fn)
# 输出最终评估的模型效果
print("TP: {}\nFP: {}\nTN: {}\nFN: {}\n".format(tp, fp, tn, fn))
print("Accuracy: %.4f" % accuracy)
# 加载训练好的模型进行预测,重新实例化一个模型,然后将训练好的模型参数加载到新模型里面
saved_state = paddle.load("./sentiment_classifier.pdparams")
sentiment_classifier = SentimentClassifier(hidden_size, vocab_size, embedding_size, num_steps=max_seq_len, num_layers=num_layers, dropout_rate=dropout_rate)
sentiment_classifier.load_dict(saved_state)
# 评估模型
evaluate(sentiment_classifier)