NLP文本分类学习笔记2:基于MLP的文本分类
多层感知机MLP
MLP是最简单的深度学习模型,有输入层,多个隐藏层和输出层,可以采用任意激活函数。它是前馈神经网络,基于反向传播学习。简单的例子如下:
基于MLP的深度平均网络DAN
在论文Deep Unordered Composition Rivals Syntactic Methods for Text Classification中提出了基于MLP的深度平均网络DAN,其结构大致如下图,主要有四个过程:
1、将词输入嵌入层,得到词嵌入向量
2、计算所有词的嵌入向量的平均值(下图中绿色部分)
3、将平均嵌入向量输入MLP网络中
4、对最后一层的输出进行分类
另:作者提出了对网络的一种优化是,在计算平均值时,丢掉一些词的向量
主要思想
DAN采用文本中所有词向量的平均值代表一段文本,不考虑句子的语法语序,没有利用上下文信息,文中一些能代表本文“特点”的词也会因为平均而淹没。
pytorch实现DAN文本分类
模型结构参数如下,对于10分类的任务达到了72.42%的准确率。关于代码更详细的说明参考:NLP文本分类学习笔记0:数据预处理及训练说明
每一个训练批次输入的数据为【128,32】128为批次大小,32为句子填充截断后统一长度
经过词嵌入层后数据为【128,32,200】这里使用wordvec预训练的200维词向量
词向量经过平均运算后数据为【128,200】
最后输入MLP中
import json
import pickle
import numpy as np
import torch
from torch import nn
class Config(object):
"""配置参数"""
def __init__(self, embedding_pre):
self.embedding_path='data/embedding.npz' #预训练词向量
self.embedding_model_path="mymodel/word2vec.model" #词向量模型
self.train_path = 'data/train.df' # 训练集
self.dev_path = 'data/valid.df' # 验证集
self.test_path = 'data/test.df' # 测试集
self.class_path = 'data/class.json' # 类别名单
self.vocab_path = 'data/vocab.pkl' # 词表
self.save_path ='mymodel/mlp.pth' # 模型训练结果
self.embedding_pretrained = torch.tensor(np.load(self.embedding_path,allow_pickle=True)["embeddings"].astype('float32')) if embedding_pre ==True else None # 载入预训练词向量
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 设备
self.num_classes = len(json.load(open(self.class_path, encoding='utf-8'))) # 类别数
self.n_vocab = 0 # 词表大小,在运行时赋值
self.epochs = 20 # epoch数
self.batch_size = 128 # mini-batch大小
self.maxlen = 32 # 每句话处理成的长度(短填长切)
self.learning_rate = 1e-3 # 学习率
self.embed_size = self.embedding_pretrained.size(1) if self.embedding_pretrained is not None else 200 # 词向量维度
class MLP(nn.Module):
def __init__(self,config):
self.config=config
super(MLP,self).__init__()
#如果embedding_pre为True,则使用预训练好的词向量,否则使用随机向量
if config.embedding_pretrained is not None:
self.embedding = nn.Embedding.from_pretrained(config.embedding_pretrained, freeze=False)
else:
vocab = pickle.load(open(config.vocab_path, 'rb'))
config.n_vocab=len(vocab.dict)
self.embedding = nn.Embedding(config.n_vocab, config.embed_size, padding_idx=config.n_vocab - 1)
self.main=nn.Sequential(
nn.Linear(config.embed_size, 1000),
nn.ReLU(),
nn.Linear(1000,100),
nn.ReLU(),
nn.Linear(100,10),
nn.Softmax()
)
def forward(self,input):
"""
input维度【batch_size,maxle每则文本填充后长度】
x维度【batch_size,maxlen每则文本填充后长度,embed_size词向量维度】
x求取平均值后维度【batch_size,embed_size词向量维度】
"""
x=self.embedding(input)
x=torch.mean(x,1)
return self.main(x)