【问题标题】:Validation accuracy is much less than Training accuracy验证准确率远低于训练准确率
【发布时间】:2023-12-12 00:55:02
【问题描述】:

我正在使用 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 枚,总数为 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'])

图表:

培训:

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

【问题讨论】:

  • 分享你的model.compile
  • 这是什么意思:My target array is [0,0,0,0,0,0,1]?这代表 7 个具有 0/1 二进制标签的训练实例,还是代表一个具有 7 个输出的训练实例?如果是后者,每个值的可能范围是多少?二进制 0/1 还是浮点数?
  • 我对输出进行了热编码,就像是情感分析一样,[1,0,0,0,0,0,0] 表示高度-ve,[0,0,0,1, 0,0,0] 表示中性,[0,0,0,0,1,0,0] 表示略微+ve。我已将整个数据集标签更改为这种形式,即大小为 (1,7) 的向量。 “我的目​​标数组是 [0,0,0,0,0,0,1]”我用这一行来讲述我的标签结构。因此,我的标签/输出是大小为(1,7)的向量的形式。
  • 你试过用基本的 DNN 代替 RNN 吗?
  • 不,我认为 RNN 比 DNN 更擅长 NLP 的任务。特别是双向更好。不是吗?

标签: python tensorflow machine-learning keras lstm


【解决方案1】:

几个建议:

  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. 建立客观/正确的基线。如果您的数据非常少,特别是在处理多模式数据集时(您只获取“文本”),您只处理具有 7 个不同类别的文本,那么您可能无法达到非常高的准确度。

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

【讨论】:

  • 是的!我应用了你的每一点。它奏效了。但是我达到了 0.64 的验证准确度,但损失为 0.91,并且在此之后并没有减少。那么,这是该模型的限制吗?如果不是,这 0.91 或 91% 有效。损失表示,我该怎么办。我已经在编辑部分更新了这个问题的统计数据。
  • 我还更新并添加了另一个建议。我真的很高兴看到您的模型的性能有所提高。
  • 同时,我认为现在取决于确切的验证拆分您将获得多少准确度,以及一些超参数调整。
【解决方案2】:

你的数据集有多长(多少个句子),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 epoch 似乎很长,如果您的模型在 20 之后似乎没有收敛,我会重置并尝试使用更简单的架构。

【讨论】:

  • 价值。在 6 个 epoch 后准确率在 30% 左右旋转,并且不会随着训练准确率在第 9 个 epoch 达到 50% 而增加
  • 我也尝试将倒数第二个密集层和 LSTM 神经元也移除到 16,但结果是一样的。
  • 你的数据集中有多少个句子?
  • 我很抱歉错误的信息,总数。令牌是 2719 和总数。句子(包括测试和训练数据集)是 2183。
  • 这对于训练循环神经网络来说太少了。我会使用更简单的方法,比如 tfidf-svc,或者微调已经在更大的语料库上针对该任务训练的深度学习模型。
【解决方案3】:

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

为了尽量减少这种情况,我做了几件事

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

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

【讨论】:

  • 我已经尝试了所有的过拟合预防技术,我也尝试了 2 个双向和一个密集层以及优化器和正则化器,但结果是一样的。
  • 您的数据集中有多少数据?是否没有足够的数据来掌握您要解决的问题的复杂性?
  • 分词器中有 2179 个唯一词。并且每个序列都用长度 30 填充
  • 你的model.compile 是什么?将其添加到问题中。
  • 优化器是亚当,损失是均方误差。我也尝试过 Binarycrossentropy