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)
posted @ 2022-04-08 10:21  启林O_o  阅读(503)  评论(0编辑  收藏  举报