中小学校园网站开发技术,怎么让别人访问自己做的的网站,app网站软件,什么叫静态网站本主要是利用RNN做多分类任务#xff0c;在熟悉RNN训练的过程中#xff0c;我们可以理解 1#xff09;超参数 batch_size和pad_size对训练过程的影响。 2#xff09;文本处理过程中是如何将文本的文字表示转化为向量表示 3#xff09;RNN梯度消失和序列长度的关系 4#…本主要是利用RNN做多分类任务在熟悉RNN训练的过程中我们可以理解 1超参数 batch_size和pad_size对训练过程的影响。 2文本处理过程中是如何将文本的文字表示转化为向量表示 3RNN梯度消失和序列长度的关系 4利用pytorch如何训练一个网络模型以及保存和加载 5理解多分类任务中的混淆矩阵
数据集HUCNews中抽取了20万条新闻标题文本长度在20到30之间。一共10个类别每类2万条。 类别财经、房产、股票、教育、科技、社会、时政、体育、游戏、娱乐。
数据集划分
数据集数据量训练集18万验证集1万测试集1万
重要参数如下
self.dropout 0.3 # 随机失活
self.num_epochs 7 # epoch数
self.batch_size 256 # batch size
self.pad_size 7 # 每句话处理成的长度(短填长切)
self.learning_rate 1e-3 # 学习率
self.hidden_size 128 # rnn隐藏层
self.num_layers 2 # rnn层数注意RNN中的层数必须大于1dropout才会生效RNN.py 模型文件主要是配置文件和RNN网络模型定义。
# coding: UTF-8
import torch
import torch.nn as nn
import numpy as npclass Config(object):配置参数def __init__(self, dataset, embedding):self.model_name RNNself.train_path dataset /data/train.txt # 训练集self.dev_path dataset /data/dev.txt # 验证集self.test_path dataset /data/test.txt # 测试集self.class_list [x.strip() for x in open(dataset /data/class.txt, encodingutf-8).readlines()] # 类别名单self.vocab_path dataset /data/vocab.pkl # 词表self.save_path dataset /saved_dict/ self.model_name ckpt # 模型训练结果self.log_path dataset /log/ self.model_nameself.embedding_pretrained torch.tensor(np.load(dataset /data/ embedding)[embeddings].astype(float32)) \if embedding ! random else None # 预训练词向量self.device torch.device(cuda if torch.cuda.is_available() else cpu) # 设备self.dropout 0.3 # 随机失活self.require_improvement 10000 # 若超过10000batch效果还没提升则提前结束训练self.num_classes len(self.class_list) # 类别数self.n_vocab 0 # 词表大小在运行时赋值self.num_epochs 7 # epoch数self.batch_size 256 # batch sizeself.pad_size 7 # 每句话处理成的长度(短填长切)self.learning_rate 1e-3 # 学习率self.embed self.embedding_pretrained.size(1) \if self.embedding_pretrained is not None else 300 # 字向量维度 若使用了预训练词向量则维度统一self.hidden_size 128 # rnn隐藏层self.num_layers 2 # rnn层数注意RNN中的层数必须大于1dropout才会生效class Model(nn.Module):def __init__(self, config):super(Model, self).__init__()if config.embedding_pretrained is not None:self.embedding nn.Embedding.from_pretrained(config.embedding_pretrained, freezeFalse)else:self.embedding nn.Embedding(config.n_vocab, config.embed, padding_idxconfig.n_vocab - 1)self.rnn nn.RNN(config.embed, config.hidden_size, config.num_layers,batch_firstTrue, dropoutconfig.dropout)self.fc nn.Linear(config.hidden_size, config.num_classes)def forward(self, x):# 将原始数据转化成密集向量表示 [batch_size, seq_len, embedding]out self.embedding(x[0])out, hidden_ self.rnn(out)# out[:, -1, :] seq_len最后时刻的输出等价 hidden_out self.fc(out[:, -1, :])return outrun_rnn.py文件主程序入口指定运行参数以及文本加载过程最后调用train_eval.py的train函数进行模型训练。
import time
import torch
import numpy as np
from train_eval import train, init_network
from importlib import import_module
import argparse
from utils import build_dataset, build_iterator, get_time_difparser argparse.ArgumentParser(descriptionChinese Text Classification)
parser.add_argument(--model, defaultRNN, typestr, requiredTrue)
parser.add_argument(--embedding, defaultpre_trained, typestr, helprandom or pre_trained)
parser.add_argument(--word, defaultFalse, typebool, helpTrue for word, False for char)
args parser.parse_args()if __name__ __main__:dataset THUCNews # 数据集# 搜狗新闻:embedding_SougouNews.npz, 腾讯:embedding_Tencent.npz, 随机初始化:randomembedding embedding_SougouNews.npzif args.embedding random:embedding randommodel_name args.modelx import_module(models. model_name)config x.Config(dataset, embedding)np.random.seed(1)torch.manual_seed(1)torch.cuda.manual_seed_all(1)torch.backends.cudnn.deterministic Truestart_time time.time()print(Loading data...)# args.word 分词方式, True是词级别,默认是Falsevocab, train_data, dev_data, test_data build_dataset(config, args.word)# build_iterator返回格式 [([词/字在词典中的位置] ,label, len(word)), ...]train_iter build_iterator(train_data, config)dev_iter build_iterator(dev_data, config)test_iter build_iterator(test_data, config)time_dif get_time_dif(start_time)print(Time usage:, time_dif)# len(vocab)PAD, len(vocab) -1 UNKconfig.n_vocab len(vocab)model x.Model(config).to(config.device)init_network(model)print(model.parameters)train(config, model, train_iter, dev_iter, test_iter)train_eval.py 文件主要对模型参数进行初始化函数train主要是从自定义迭代器中加载数据进行训练。test函数是在模型训练完后对测试数据集进行测试。evaluate函数主要是在训练过程中对验证集数据进行验证。
# coding: UTF-8
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from sklearn import metrics
import time
from utils import get_time_dif
from tensorboardX import SummaryWriter
import matplotlib.pyplot as plt# 权重初始化默认xavier
def init_network(model, methodxavier, excludeembedding, seed123):for name, w in model.named_parameters():if exclude not in name:if weight in name:if method xavier:nn.init.xavier_normal_(w)elif method kaiming:nn.init.kaiming_normal_(w)else:nn.init.normal_(w)elif bias in name:nn.init.constant_(w, 0)else:passdef train(config, model, train_iter, dev_iter, test_iter):loss_list []start_time time.time()model.train()optimizer torch.optim.Adam(model.parameters(), lrconfig.learning_rate)total_batch 0 # 记录进行到多少batchdev_best_loss float(inf)last_improve 0 # 记录上次验证集loss下降的batch数flag False # 记录是否很久没有效果提升writer SummaryWriter(log_dirconfig.log_path / time.strftime(%m-%d_%H.%M, time.localtime()))# dev_acc_list []# dev_loss_list []for epoch in range(config.num_epochs):print(Epoch [{}/{}].format(epoch 1, config.num_epochs))for i, (trains, labels) in enumerate(train_iter):outputs model(trains)# 打印tensor的所有数据# torch.set_printoptions(thresholdfloat(inf))model.zero_grad()loss F.cross_entropy(outputs, labels)loss_list.append(loss.detach().numpy())loss.backward()optimizer.step()if total_batch % 100 0:true labels.data.cpu()# 取出每一行最大的那个概率的索引值predic torch.max(outputs.data, 1)[1].cpu()train_acc metrics.accuracy_score(true, predic)dev_acc, dev_loss evaluate(config, model, dev_iter)# dev_acc_list.append(dev_acc)# dev_loss_list.append(dev_loss)if dev_loss dev_best_loss:dev_best_loss dev_losstorch.save(model.state_dict(), config.save_path)improve *last_improve total_batchelse:improve time_dif get_time_dif(start_time)msg Iter: {0:6}, Train Loss: {1:5.2}, Train Acc: {2:6.2%}, Val Loss: {3:5.2}, Val Acc: {4:6.2%}, Time: {5} {6}print(msg.format(total_batch, loss.item(), train_acc, dev_loss, dev_acc, time_dif, improve))writer.add_scalar(loss/train, loss.item(), total_batch)writer.add_scalar(loss/dev, dev_loss, total_batch)writer.add_scalar(acc/train, train_acc, total_batch)writer.add_scalar(acc/dev, dev_acc, total_batch)model.train()total_batch 1if total_batch - last_improve config.require_improvement:# 验证集loss超过10000batch没下降结束训练print(No optimization for a long time, auto-stopping...)flag Truebreakif flag:breakwriter.close()size len(loss_list)x_axis [i for i in range(0, size)]plt.plot(x_axis, loss_list, colorred)plt.show()test(config, model, test_iter)def test(config, model, test_iter):model.load_state_dict(torch.load(config.save_path))model.eval()start_time time.time()test_acc, test_loss, test_report, test_confusion evaluate(config, model, test_iter, testTrue)msg Test Loss: {0:5.2}, Test Acc: {1:6.2%}print(msg.format(test_loss, test_acc))print(Precision, Recall and F1-Score...)print(test_report)print(Confusion Matrix...)print(test_confusion)time_dif get_time_dif(start_time)print(Time usage:, time_dif)def evaluate(config, model, data_iter, testFalse):model.eval()loss_total 0predict_all np.array([], dtypeint)labels_all np.array([], dtypeint)# 模型评估的时候无梯度模式with torch.no_grad():for texts, labels in data_iter:outputs model(texts)loss F.cross_entropy(outputs, labels)loss_total losslabels labels.data.cpu().numpy()predict torch.max(outputs.data, 1)[1].cpu().numpy()labels_all np.append(labels_all, labels)predict_all np.append(predict_all, predict)acc metrics.accuracy_score(labels_all, predict_all)if test:report metrics.classification_report(labels_all, predict_all, target_namesconfig.class_list, digits4)confusion metrics.confusion_matrix(labels_all, predict_all)return acc, loss_total / len(data_iter), report, confusion# 用于训练过程中的验证return acc, loss_total / len(data_iter)
model_test.py 是单个文本的推理文件。
utils.py定义了加载数据集函数load_dataset自定义迭代器将数据转化为tensor格式便于输入到模型。
完整代码github地址
项目结构清晰以后我们主要要记录一下RNN训练过程中遇到的一些问题尽管现在已经不怎么使用RNN网络模型了不过这不影响RNN在时序网络中的地位LSTM 长短时记忆网络、GRU门控循环单元都是RNN的优化我们还是有必要好好认识一下RNN的训练过程以及超参数对损失值的影响。
我们主要参数设置如下我们只对batch_size和pad_size进行修改看一下模型的损失下降曲线。
self.dropout 0.3 # 随机失活
self.require_improvement 10000 # 若超过10000batch效果还没提升则提前结束训练
self.num_classes len(self.class_list) # 类别数
self.n_vocab 0 # 词表大小在运行时赋值
self.num_epochs 7 # epoch数
self.batch_size 64 # batch size
self.pad_size 32 # 每句话处理成的长度(短填长切)
self.learning_rate 1e-3 # 学习率
self.embed self.embedding_pretrained.size(1) \
if self.embedding_pretrained is not None else 300 # 字向量维度
self.hidden_size 128 # rnn隐藏层
self.num_layers 2 # rnn层数注意RNN中的层数必须大于1dropout才会生效batch_size 64 pad_size 32 learning_rate 1e-3
训练过程
损失函数结果图可以看出根本就不收敛pad_size值过大可能出现出现梯度消失导致模型参数根本就不更新。 batch_size 64 pad_size 16 learning_rate 1e-3
训练过程 从这里足以感性的理解为什么很多人说RNN携带的时序信息走不远当我们将时序长度pad_size设置16时其他参数不变可以看到验证数据集的准确度和损失都还不错的比pad_size32要好很多至少可以知道模型的参数是在更新且损失值也有下降的趋势。 混淆矩阵也还可以。 混淆矩阵参考 以上是文本序列长度pad_size对RNN训练的影响。现在我们来看下batch_size大小对RNN训练的影响。为了让模型收敛pad_szie统一取16
batch_size 128 pad_size 16 learning_rate 1e-3
训练过程
batch_size变大为128更新次数少每一次迭代考虑的样本更多。每次迭代考虑的样本大了以后梯度优化的波动变小下降更平滑。相比batch_size64损失图像下下降确实更平滑。混淆矩阵无太大差异。 batch_size 256 pad_size 16 learning_rate 1e-3
训练过程 batch_size256损失值下降更平滑收敛速度更快batch_size64时训练时长在18min左右而此参数下训练时长仅要5min左右。 batch_size 1024 pad_size 16 learning_rate 1e-3
训练过程 batch_size1024时收敛速度更快而此参数下训练时长仅要2min左右。
混淆矩阵可以看出在显存足够大的情况下适当增大batch_size可以达到两点效果1加快训练的收敛的速度 2梯度优化的波动减小收敛过程更加平滑。 至此我们已经完成了RNN训练中两个比较重要的超参数batch_size和pad_size对训练过程的影响。还有很多其他的超参数这里就不实验了。
pad_size由32变成16时候显然只用到了一半的数据信息无论怎么进行超参数的优化都不可能达到最好的结果。如果使用32又会出现梯度消失从而模型不收敛。LSTM模型就有效的改进了这个缺陷。下一篇文章我们使用同样的超参数和数据集构造一个LSTM模型实验这个改进有多大。
参考 https://github.com/649453932/Chinese-Text-Classification-Pytorch