我正在处理一个需要同时进行词性(POS)标注和情感分析的问题。我使用Tensorflow,并且正在考虑使用Keras。
我有一个大的英语句子数据集,这些句子已经被标记了词性标签和情感(负面、中立、正面)。
是否可以训练一个循环神经网络(普通RNN、GRU或LSTM)来学习同时进行词性标注和情感分类?当然,在测试时,我希望输入一个句子,让RNN同时生成词性标签和情感的预测。
我在考虑以下RNN架构。我不确定它是否能用Tensorflow实现(我一直在使用)或Keras(我现在正在学习)。我之前实现的RNN都是单任务的,不是双任务的。
感谢任何帮助。
回答:
一个可能适用于词性标注的非常简单的Keras模型可能如下所示:
from keras.layers import Dense, LSTMfrom keras.models import Model, Sequentialmodel = Sequential()model.add( LSTM( hidden_layer_size, return_sequences=True, input_shape=(seq_length, nb_words), unroll=True ))model.add(Dense(nb_pos_types, activation="softmax"))model.compile(loss="categorical_crossentropy", optimizer="rmsprop")
其中我假设了各种参数:
hidden_layer_size
:内部循环层的维度。seq_length
:输入序列长度。nb_words
:词汇量,用于详细说明序列位置的单词的一热编码输入。nb_pos_types
:可能的词性标签数量(用于一热编码标签)。
目标是修改这样一个简单的网络,使其也能对情感进行预测(不清楚你的情感是分数还是类别标签,但我假设是类别标签),并且损失函数中包括对情感预测的惩罚项。
实现这一点的方法有很多,但一种常见的方法是“分叉”模型的一个早期层的新分支,让这个分支产生额外的预测(通常称为“多任务”或“联合任务”学习)。
为此,我们将从Sequential
开始,但将其重命名为base_model
,以明确它作为多任务分支前的基础层集。然后我们将使用Keras的功能语法来对每个分支进行所需的操作,然后将它们组合成final_model
的多个输出,我们可以在其中为每个输出表达整体损失函数的一部分。
我们可以这样修改上面的例子来实现它:
base_model = Sequential()base_model.add( LSTM( hidden_layer_size, return_sequences=True, input_shape=(seq_length, nb_words), unroll=True ))# 获取循环层的输出。rec_output = base_model.outputs[0]# 创建表示词性预测的层。pos_spoke = Dense(nb_pos_types, activation="softmax", name="pos")(rec_output)# 创建表示情感预测的层。# 我假设`nb_sentiments`是情感类别的数量。sentiment_spoke = Dense(nb_sentiments, activation="softmax", name="sentiment")(rec_output)# 重新统一成一个模型,该模型接受与`base_model`确定的相同输入,并提供一个包含2个输出的列表,# 每个分支一个(词性和情感)。final_model = Model(inputs=base_model.inputs, outputs=[pos_spoke, sentiment_spoke])# 最后,使用字典来指定每个输出的损失函数,并可选地为损失相加时提供单独的权重。 final_model.compile( optimizer='rmsprop', loss={'pos': 'categorical_crossentropy', 'sentiment': 'categorical_crossentropy'}, loss_weights={'pos': 1.0, 'sentiment': 1.0})
最后,当调用final_model.fit
时,你将提供一个标签列表,包含与每个输出相关的两个张量或数组标签。
你可以在Keras文档中关于多输入和多输出的模型部分阅读更多关于多输出损失和架构的信息,在Keras的多输入和多输出模型文档中。
最后,请注意,这是一个非常简单的模型(可能表现不会很好——仅供说明)。你可以使用我们创建的分支pos_spoke
和sentiment_spoke
来添加更多层,构建更复杂的网络拓扑,如果你有特定的词性或情感专用架构的话。
它们不一定要直接定义为Dense
,可以是额外的循环层,甚至是卷积层等,随后是最终的Dense
层,其变量名和层名将用于输出和损失的相应位置。
还要注意这里使用了return_sequences=True
。这允许在序列的每个步骤上进行词性和情感预测,尽管你可能只关心序列末尾的情感预测。一个可能的选项是修改sentiment_spoke
,使其仅在rec_output
的最后一个序列元素上操作,或者另一个不太可能的选项是为输入序列中的每个词重复句子的整体情感标签。