作者 | Thomas Wolf
编译 | 雁惊寒
情感情绪检测是自然语言理解的关键要素。最近,我们改造出了一个好用的情感理解集成系统,该系统前身是MIT媒体实验室的情感检测模型DeepMoji。
开源代码:https://github.com/huggingface/torchMoji
该模型最初的设计使用了TensorFlow、Theano和Keras,接着我们将其移植到了pyTorch上。与Keras相比,pyTorch能让我们更自由地开发和测试各种定制化的神经网络模块,并使用易于阅读的numpy风格来编写代码。在这篇文章中,我将详细说明在移植过程中出现的几个有趣的问题:
-
如何使用自定义激活功能定制pyTorch LSTM
-
PackedSequence对象的工作原理及其构建
-
如何将关注层从Keras转换成pyTorch
-
如何在pyTorch中加载数据:DataSet和Smart Batching
-
如何在pyTorch中实现Keras的权重初始化
首先,我们来看看torchMoji/DeepMoji的模型。它是一个相当标准而强大的人工语言处理神经网络,具有两个双LSTM层,其后是关注层和分类器:
torchMoji/DeepMoji模型
构建一个定制化的pyTorch LSTM模块
DeepMoji有一个很不错的特点:Bjarke Felbo及其协作者能够在一个拥有16亿条记录的海量数据集上训练该模型。因此,预先训练的模型在此训练集中具有非常丰富的情感和情绪表征,我们可以很方便地使用这个训练过的模型。
该模型是使用针对LSTM的回归内核的Theano/Keras默认激活函数hard sigmoid训练的,而pyTorch是基于NVIDIA的cuDNN库建模的,这样,可获得原生支持LSTM的GPU加速与标准的sigmoid回归激活函数:
Keras默认的LSTM和pyTorch默认的LSTM
因此,我写了一个具有hard sigmoid回归激活函数的自定义LSTM层:
def LSTMCell(input, hidden, w_ih, w_hh, b_ih=None, b_hh=None):
"""
A modified LSTM cell with hard sigmoid activation on the input, forget and output gates.
"""
hx, cx = hidden
gates = F.linear(input, w_ih, b_ih) + F.linear(hx, w_hh, b_hh)
ingate, forgetgate, cellgate, outgate = gates.chunk(4, 1)
ingate = hard_sigmoid(ingate)
forgetgate = hard_sigmoid(forgetgate)
cellgate = F.tanh(cellgate)
outgate = hard_sigmoid(outgate)
cy = (forgetgate * cx) + (ingate * cellgate)
hy = outgate * F.tanh(cy)
return hy, cy
def hard_sigmoid(x):
"""
Computes element-wise hard sigmoid of x.
See e.g. https://github.com/Theano/Theano/blob/master/theano/tensor/nnet/sigm.py#L279
"""
x = (0.2 * x) + 0.5
x = F.threshold(-x, -1, -1)
x = F.threshold(-x, 0, 0)
return x
这个LSTM单元必须集成在一个完整的模块中,这样才可以使用pyTorch所有的功能。这个集成相关的代码很长,建议直接引用到Github中的相关源代码。
Keras和pyTorch中的关注层
模型的关注层是一个有趣的模块,我们可以分别在Keras和pyTorch的代码中进行比较:
class Attention(Module):
"""
Computes a weighted average of channels across tim