Pytorch实现基于CharRNN的文本分类与生成

Pytorch实现基于CharRNN的文本分类与生成

标签: deep-learning pytorch nlp


1 简介

本篇主要介绍使用pytorch实现基于CharRNN来进行文本分类与内容生成所需要的相关知识,并最终给出完整的实现代码。

2 相关API的说明

pytorch框架中每种网络模型都有构造函数,在构造函数中定义模型的静态参数,这些参数将对模型所包含weights参数的维度进行设置。在运行时,模型的实例将接收动态的tensor数据并调用forword,在得到模型输出之后便可以和真实的标签数据进行误差计算,并通过优化器进行反向传播以调整模型的参数。下面重点介绍NLP常用到的模型和相关方法。

2.1 nn.Embedding

词嵌入层是NLP应用中常见的模块。在word2vec出现之前,一种方法是使用每个token的one-hot向量进行运算。one-hot是一种稀疏编码,运算效果较差。word2vec用于生成每个token的Dense向量表示。目前的研究结果证明,word2vec可以有效提升模型的训练效果。
pytorch的模型提供了Embedding模型用于实现词嵌入过程Embedding层中的权重用于随机初始化词的向量,权重参数在后续的训练中会被不断调整,并被优化。

模型的创建方法为:embeding = nn.Embedding(vocab_size, embedding_dim)

  • vocab_size 表示字典的大小
  • embedding_dim 词嵌入的维度数量,通常设置远小于字典大小,60-300之间通常可满足需要

使用:embeded = embeding(input)

  • input 需要嵌入的句子,可为任意维度。单个句子表示为token的索引列表,如[283, 4092, 1, ]
  • output 数据的嵌入表示,shape=[*, embedding_dim],*为input的维度

示例代码:

import torch
from torch import nn

embedding = nn.Embedding(5, 4) # 假定语料只有5个词,词向量维度为3
sents = [[1, 2, 3], 
         [2, 3, 4]] # 两个句子,how:1 are:2 you:3, are:2 you:3 ok:4
embed = embedding(torch.LongTensor(sents))
print(embed) # shape=(2
'''
tensor([[[-0.6991, -0.3340, -0.7701, -0.6255],
         [ 0.2969,  0.4720, -0.9403,  0.2982],
         [ 0.8902, -1.0681,  0.4035,  0.1645]],
        [[ 0.2969,  0.4720, -0.9403,  0.2982],
         [ 0.8902, -1.0681,  0.4035,  0.1645],
         [-0.7944, -0.1766, -1.5941,  0.4544]]], grad_fn=<EmbeddingBackward>)
'''

2.2 nn.RNN

RNN是NLP的常用模型,普通的RNN单元结构如下图所示:RNN单元
RNN单元还有一些变体,主要是单元内部的激活函数不同或数据使用了不同计算。RNN每个单元存在输入x与上一时刻的隐层状态h,输出有y与当前时刻的隐层状态。

对RNN单元的改进有LSTM和GRU,这三种类型的模型的输入数据都需要3D的tensor,,,使用时设置b atch_first为true时,输入数据的shape为[batch,seq_length, input_dim],第一维为batch的数量不使用时设置为1,第二维序列的长度,第三维为输入的维度,通常为词嵌入的维度。

rnn = RNN(input_dim, hidden_dim, num_layers=1, batch_first, bidirectional)

  • input_dim 输入token的特征数量,使用embeding时为嵌入的维度
  • hidden_dim 隐层的单元数,决定RNN的输出长度
  • num_layers 层数
  • batch_frist 第一维为batch,反之第一堆为seq_len,默认为False
  • bidirectional 是否为双向RNN,默认为False

output, hidden = rnn(input, hidden)

  • input 一批输入数据,shape为[batch, seq_len, input_dim]
  • hidden 上一时刻的隐层状态,shape为[num_layers * num_directions, batch, hidden_dim]
  • output 当前时刻的输出,shape为[batch, seq_len, num_directions*hidden_dim]
import torch
from torch import nn

vocab_size = 5
embed_dim = 3
hidden_dim = 8

embedding = nn.Embedding(vocab_size, embed_dim)
rnn = nn.RNN(embed_dim, hidden_dim, batch_first=True)

sents = [[1, 2, 4], 
         [2, 3, 4]]
h0 = torch.zeros(1, embeded.size(0), 8) # shape=(num_layers*num_directions, batch, hidden_dim)

embeded = embedding(torch.LongTensor(sents))
out, hidden = rnn(embeded, h0) # out.shape=(2,3,8), hidden.shape=(1,2,8)

print(out, hidden)  

'''
tensor([[[-0.1556, -0.2721,  0.1485, -0.2081, -0.2231, -0.1459, -0.0319, 0.2617],
         [-0.0274,  0.1561, -0.0509, -0.1723, -0.2678, -0.2616,  0.0786, 0.4124],
         [ 0.2346,  0.4487, -0.1409, -0.0807, -0.0232, -0.4975,  0.4244, 0.8337]],
        [[ 0.0879,  0.1122,  0.1502, -0.3033, -0.2715, -0.1191,  0.1367, 0.5275],
         [ 0.2258,  0.4395, -0.1365,  0.0135, -0.0777, -0.5221,  0.4683, 0.8115],
         [ 0.0158,  0.3471,  0.0742, -0.0550, -0.0098, -0.5521,  0.5923,0.8782]]],              grad_fn=<TransposeBackward0>) 
tensor([[[ 0.2346,  0.4487, -0.1409, -0.0807, -0.0232, -0.4975,  0.4244, 0.8337],
         [ 0.0158,  0.3471,  0.0742, -0.0550, -0.0098, -0.5521,  0.5923, 0.8782]]],             grad_fn=<ViewBackward>)
'''

2.3 nn.LSTM

LSTM是RNN的一种模型,结构中增加了记忆单元,LSTM单元结构如下图所示:
LSTM单元结构
每个单元存在输入x与上一时刻的隐层状态h和上一次记忆c,输出有y与当前时刻的隐层状态及当前时刻的记忆c。其使用上和RNN类似。

lstm = LSTM(input_dim, hidden_dim, num_layers=1, batch_first=True, bidirectional)

  • input_dim 输入word的特征数量,使用embeding时为嵌入的维度
  • hidden_dim 隐层的单元数

output, (hidden, cell) = lstm(input, (hidden, cell))

  • input 一批输入数据,shape为[batch, seq_len, input_dim]
  • hidden 当前时刻的隐层状态,shape为[num_layers * num_directions, batch, hidden_dim]
  • cell 当前时刻的记忆状态,shape为[num_layers * num_directions, batch, hidden_dim]
  • output 当前时刻的输出,shape为[batch, seq_len, num_directions*hidden_dim]

2.4 nn.GRU

GRU也是一种RNN单元,但它比LSTM简化许多,普通的GRU单元结构如下图所示:
GRU单元
每个单元存在输入x与上一时刻的隐层状态h,输出有y与当前时刻的隐层状态。

rnn = GRU(input_dim, hidden_dim, num_layers=1, batch_first=True, bidirectional)

  • input_dim 输入word的特征数量,使用embeding时为嵌入的维度
  • hidden_dim 隐层的单元数

output, hidden = rnn(input, hidden)

  • input 一批输入数据,shape为[batch, seq_len, input_dim]
  • hidden 上一时刻的隐层状态,shape为[num_layers*num_directions, batch, hidden_dim]
  • output 当前时刻的输出,shape为[batch, seq_len, num_directions*hidden_size]

2.5 损失函数

MSELoss均方误差
l o s s ( x , y ) = 1 / n ∑ ( x i − y i ) 2 loss(x,y)=1/n\sum(x_i-y_i)^2 loss(x,y)=1/n(xiyi)2
输入x,y可以是任意的shape,但要保持相同的shape

CrossEntropyLoss 交叉熵误差
l o s s ( x , c l a s s ) = − log e x p ( x [ c l a s s ] ) ∑

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值