Python 将CRF层添加到LSTM可使学习曲线变得平坦

Python 将CRF层添加到LSTM可使学习曲线变得平坦,python,keras,deep-learning,lstm,crf,Python,Keras,Deep Learning,Lstm,Crf,我使用tensorflow后端(tf版本1.13.1)在keras中实现了一个名为entity tagger的bi LSTM。给定一系列单词标记,网络的任务是用实体类型标签标记序列中的每个元素。随后,我在网络顶部添加了一个条件随机场(CRF)层;在最先进的命名实体标记器中,CRF通常用于通过对序列中的相邻元素施加邻接约束来改进bi LSTM的结果 这是网络代码。由于数据的性质,循环执行自定义小批量训练 from keras.models import Sequential from keras.

我使用tensorflow后端(tf版本1.13.1)在keras中实现了一个名为entity tagger的bi LSTM。给定一系列单词标记,网络的任务是用实体类型标签标记序列中的每个元素。随后,我在网络顶部添加了一个条件随机场(CRF)层;在最先进的命名实体标记器中,CRF通常用于通过对序列中的相邻元素施加邻接约束来改进bi LSTM的结果

这是网络代码。由于数据的性质,循环执行自定义小批量训练

from keras.models import Sequential
from keras.layers import LSTM, Dense, TimeDistributed, Bidirectional, Dropout
from keras import optimizers
from keras_contrib.layers import CRF

model = Sequential()
model.add(Bidirectional(LSTM(params['hidden_size'], return_sequences=True), input_shape=(params['max_seq_len'], params['emb_size'])))
model.add(Dropout(params['dropout']))
model.add(TimeDistributed(Dense(params['n_classes'], activation=params['activation'])))
model.add(CRF(params['n_classes'], sparse_target=True))

model.compile(loss=crf.loss_function, optimizer='sgd'), metrics=['mse']) 

for epoch in range(params['n_epochs']):

    for X,y in data:

        X = X.reshape(1, params['max_seq_len'], params['emb_size'])
        y = y.reshape(1, params['max_seq_len'], 1)

        history = model.fit(X, y, epochs=1, batch_size=params['batch_size'], verbose=1)
我期望增加CRF层来提高网络的性能;然而,它不仅没有改善结果,而且还完全平坦了学习曲线,如均方误差所测量的(如下面的均方误差底部面板图所示,每个历元的平均值)。这是令人费解的,特别是因为损失一直在减少(如下面损失的顶部面板图所示,同样在每个历元中平均)。此外,模型在测试集上的性能降至零

CRF的实施是否存在错误?或者是因为CRF损失函数不是通过均方误差测量的


问题中提供了可用于重现问题的模拟数据集(与此处的实现相同,但没有CRF层)。

您的网络看起来不错。
下面是我将尝试的一些更改和迭代-

  • 而不是使用
    mse
    使用
    crf\u边际精度
    并使用
    learn\u mode='marginal'
    初始化crf 这是因为您使用的是NER模型,而不是使用一个热编码器作为
    sparse\u target=True
  • 使用
    adam
    优化器,因为sgd在计算时不考虑整个数据集,但对于具有3个DIM以上的时间分布模型,sgd不会进行优化
  • 可能需要使用损失函数