验证精度远低于训练精度

Validation accuracy is much less than Training accuracy

我正在使用 MOSI 数据集进行多模态情感分析,目前我只为文本数据集训练模型。对于文本,我使用 300 维度的手套嵌入来处理文本。我的总词汇量是 2173,我的填充序列长度是 30。我的目标数组是 [0,0,0,0,0,0,1],其中最左边是高度 -ve,最右边是 +ve。

我正在这样拆分数据集

X_train, X_test, y_train, y_test = train_test_split(WDatasetX, y7, test_size=0.20, random_state=42)

我的标记化过程是

MAX_NB_WORDS = 3000
tokenizer = Tokenizer(num_words=MAX_NB_WORDS,oov_token = "OOV")
tokenizer.fit_on_texts(Text_X_Train)
tokenized_X_train = tokenizer.texts_to_sequences(Text_X_Train)
tokenized_X_test = tokenizer.texts_to_sequences(Text_X_Test)

我的嵌入矩阵:

vocab_size = len(tokenizer.word_index)+1
emb_mean=0
def embedding_matrix_filteration():
    all_embs = np.stack(list(embeddings_index.values()))
    print(all_embs.shape)
    emb_mean, emb_std = np.mean(all_embs), np.std(all_embs)
    print(emb_mean)
    embedding_matrix = np.random.normal(emb_mean, emb_std, (vocab_size, embed_dim)) gives the matrix of specified
                                                                    size filled with values from gauss distribution
    print(embedding_matrix.shape)
     print("length of word2id:",len(word2id))
    embeddedCount = 0
    not_found = []
    for word, idx in tokenizer.word_index.items():
        embedding_vector = embeddings_index.get(word.lower())
        if word == ' ':
            embedding_vector = np.zeros_like(emb_mean)
        if embedding_vector is not None: 
            embedding_matrix[idx] = embedding_vector
            embeddedCount += 1
        else:
            print(word)
            print("$$$")
    print('total embedded:',embeddedCount,'common words')# words common between glove vector and wordset
    print("length of word2id:",len(word2id))
    print(len(embedding_matrix))
    return embedding_matrix

emb = embedding_matrix_filteration()

模型架构:

嵌入层:

embedding_layer = Embedding(
    vocab_size,
    300,
    weights=[emb],
    trainable=False,
    input_length=sequence_length
)

我的模型:

from keras import regularizers,layers

model = Sequential()
model.add(embedding_layer)
model.add(Bidirectional(layers.LSTM(512,return_sequences=True)))
model.add(Bidirectional(layers.LSTM(512,return_sequences=True)))
model.add(Bidirectional(layers.LSTM(256,return_sequences=True)))
model.add(Bidirectional(layers.LSTM(256)))#kernel_regularizer=regularizers.l2(0.001)
model.add(Dense(128, activation='relu'))
# model.add(Dropout(0.2))
model.add(Dense(128, activation='relu'))
# model.add(Dropout(0.2))
model.add(Dense(7, activation='softmax'))

由于某种原因,当我的训练准确率达到 80% 时,val。准确性仍然很低。我尝试了不同的正则化技术、优化器、损失函数,但结果是一样的。不知道为什么。

请帮忙!!

编辑:总编号。代币数量为 2719,总数为句子(包括测试和训练数据集)为 2183.

Compiler: model.compile(optimizer='adam',         
loss='mean-squred-error',
metrics=['accuracy']
)

更新的统计数据:

我已将标签大小从 7 减小到 3,即 [0,1,0] -> +ve, neutral ,-ve.

model = Sequential()
model.add(embedding_layer)
model.add(Bidirectional(layers.LSTM(16,activation='relu'))) 
model.add(Dropout(0.2))
model.add(Dense(3, activation='softmax'))

编译:

model.compile( 
optimizer=keras.optimizers.Adam(learning_rate=0.00005),
              loss='categorical_crossentropy',
              metrics = ['accuracy'])

图表:

培训:

但损失仍然很高而且,我对数据集进行了分层。

训练和验证统计数据之间的巨大差异通常表示模型对训练数据过度拟合。

为了尽量减少这种情况,我做了一些事情

  1. 减小模型的大小。
  2. 在模型中添加一些 dropout 或类似层。我在使用这些层方面取得了很好的成功:layers.LeakyReLU(alpha=0.8),

在此处查看指南: https://www.tensorflow.org/tutorials/keras/overfit_and_underfit#strategies_to_prevent_overfitting

你的数据集有多长(多少句子),2179 个标记似乎并不多,在我看来你的模型对于任务来说太大了。我不会添加 4 层 LSTM,我会选择 1 层或 2 层。

from keras import regularizers,layers

model = Sequential()
model.add(embedding_layer)
model.add(Bidirectional(layers.LSTM(64,return_sequences=True)))
model.add(Bidirectional(layers.LSTM(32)))
model.add(Dense(16, activation='relu'))
# model.add(Dropout(0.2))
model.add(Dense(7, activation='softmax'))

至于训练,200 个纪元似乎很长,如果你的模型在 20 个纪元后似乎没有收敛,我会重置并尝试使用更简单的架构。

一些建议:

  1. categorical_crossentropy代替mean_squared_error,在做分类的时候可以给你很大的帮助(虽然后者也可以,但前者也更好)。
  2. 你们所有的标签都是互斥的吗?如果那么,使用 softmax + categorical_crossentropy,否则(例如标签显示为 [1,0,0,0,0,0,1] 使用 sigmoid + binary_crossentropy.
  3. 最初减小模型的大小,只有在过度拟合问题仍然存在时才使用 Dropout()。只使用一层 LSTM。
  4. 减少单位数量(即使您只有一个 LSTM 单元(64/128 可能就足够了)。
  5. 您可以使用双向 LSTM(我什至会选择双向 GRU,因为它们更简单,以查看性能表现如何)。
  6. 确保你做了一个stratified split(这样,一定的例子在训练集和验证集中肯定都出现了,而且比例也很好。
  7. 从较小的(呃)学习率开始 (0.0001/0.00005)。
  8. 建立一个objective/correct基线。如果你的数据很少,特别是在处理多模式数据集时(你只获取“文本”),你只处理文本,有 7 个不同的 类,那么你很可能达不到非常高的准确性。

请记住,为了在您的案例中获得合理的最终结果,您需要采用以数据为中心的方法,而不是以模型为中心的方法。不管可能的改进如何,如果数据稀少+不全面,你将无法取得很好的结果。