You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

训练集准确率极高但测试集表现差的神经网络问题咨询

问题分析与优化建议

问题背景

我开发了一个用于情感多分类的简单神经网络,使用Kaggle上25k+带正面、中性、负面标签的推文数据集。模型在训练集上准确率达98-99%,但测试集准确率仅约60%。尝试过调整网络层数、层规模、批量大小、训练轮数及词表大小,测试性能仍无改善。想知道造成这种差异的原因,以及如何优化提升测试表现。

代码实现

df = pd.read_csv('Tweets.csv');

df = df.drop(columns=['textID', 'selected_text'])

data = df['text']
labels = df['sentiment']

labels = np.unique(labels, return_inverse=True)
lookup = labels[0]
labels = labels[1]

data = np.array(data).astype(str)
tokenizer = keras_preprocessing.text.Tokenizer(num_words=10000)
tokenizer.fit_on_texts(data)
sequences = tokenizer.texts_to_sequences(data)
one_hot_results = tokenizer.texts_to_matrix(data, mode='binary')

all_tweets = one_hot_results[:20000]
all_labels = labels[:20000]

train_data = all_tweets[:10000]
test_data = all_tweets[10000:]


train_labels = all_labels[:10000]
test_labels = all_labels[10000:]


model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000, )))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(3, activation='softmax'))
model.compile(optimizer='rmsprop', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

model.fit(train_data, train_labels, batch_size=512, epochs=20, validation_split=0.3)

test_loss, test_acc = model.evaluate(test_data, test_labels)
print("test_acc:", test_acc)

训练与测试输出

Epoch 19/20
14/14 [==============================] - 0s 14ms/step - loss: 0.0423 - accuracy: 0.9903 - val_loss: 1.9351 - val_accuracy: 0.6063
Epoch 20/20
14/14 [==============================] - 0s 14ms/step - loss: 0.0365 - accuracy: 0.9920 - val_loss: 2.0434 - val_accuracy: 0.6013
313/313 [==============================] - 1s 3ms/step - loss: 1.9856 - accuracy: 0.6086
test_acc: 0.6086000204086304

核心原因:严重过拟合+文本处理/模型适配不合理

从训练曲线和测试结果来看,模型完全记住了训练集的特征,但无法泛化到测试数据,具体诱因包括:

  • 文本特征无效:用binary模式的one-hot编码完全丢失了词序和语义关联,这种特征本身区分度极低,模型只能死记硬背训练集的词频组合,无法理解情感逻辑。
  • 数据集划分错误:直接按顺序切割数据,推文可能存在时间或主题的序列性,导致训练/测试集数据分布差异极大,模型学不到通用的情感判别模式。
  • 模型结构不适配:全连接Dense层擅长处理结构化数据,无法捕捉文本的上下文依赖关系,加上无正则化约束,很容易在简单特征上过度拟合。
  • 训练策略激进:20轮训练已经远超模型收敛所需,后期模型一直在学习训练集的噪声细节,验证集损失持续上升就是明确信号。

优化方案(按优先级排序)

1. 重构文本特征处理

  • 放弃one-hot编码,改用**词嵌入(Embedding)**层:将单词映射到低维语义空间,保留词之间的关联信息,可选择预训练GloVe/Word2Vec向量,或让模型在数据集上自行训练。
  • 保留序列结构:用pad_sequences将文本转为固定长度的序列,而非扁平的one-hot矩阵,为后续序列模型提供输入基础。

2. 修正数据集划分

  • 采用分层随机划分,用sklearn.model_selection.train_test_split并设置stratify=labels,确保训练/测试集的情感标签分布一致,避免数据偏移。

3. 调整模型结构与正则化

  • 替换全连接网络为文本专用模型:基础版用Embedding + LSTM/GRU捕捉上下文情感;进阶版用Transformer Encoder(如简化版BERT)提取复杂语义。
  • 添加正则化组件:
    • 在Dense层后加入Dropout(0.3-0.5),随机丢弃神经元打断噪声依赖;
    • 给Dense层添加kernel_regularizer=regularizers.l2(0.01),限制权重规模。

4. 优化训练策略

  • 启用早停(Early Stopping):监控验证集损失,当连续3轮无下降时停止训练并恢复最优权重,避免过度训练;
  • 调整批量大小:改用32/64这类较小批量,提升模型泛化能力;
  • 动态调整学习率:用ReduceLROnPlateau回调,当验证集损失停滞时降低学习率。

5. 文本预处理优化

  • 清洗推文:去除URL、@用户名、特殊符号/表情,转小写,过滤停用词,可选词干提取/词形还原,减少噪声干扰。

优化后代码示例

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from tensorflow import keras
from tensorflow.keras import layers, regularizers, callbacks

# 数据读取与预处理
df = pd.read_csv('Tweets.csv')
df = df.drop(columns=['textID', 'selected_text'])

data = df['text'].astype(str)
labels = df['sentiment']

# 标签编码
le = LabelEncoder()
labels = le.fit_transform(labels)

# 文本序列处理
tokenizer = keras.preprocessing.text.Tokenizer(num_words=10000)
tokenizer.fit_on_texts(data)
sequences = tokenizer.texts_to_sequences(data)
max_len = 50  # 设定每条推文的最大长度
padded_sequences = keras.preprocessing.sequence.pad_sequences(sequences, maxlen=max_len)

# 分层划分数据集
train_data, test_data, train_labels, test_labels = train_test_split(
    padded_sequences, labels, test_size=0.2, stratify=labels, random_state=42
)

# 构建模型
model = keras.Sequential([
    layers.Embedding(input_dim=10000, output_dim=128, input_length=max_len),
    layers.LSTM(64, return_sequences=False),
    layers.Dropout(0.3),
    layers.Dense(32, activation='relu', kernel_regularizer=regularizers.l2(0.01)),
    layers.Dense(3, activation='softmax')
])

model.compile(optimizer='rmsprop', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

# 早停回调
early_stop = callbacks.EarlyStopping(patience=3, restore_best_weights=True)

# 训练模型
history = model.fit(
    train_data, train_labels,
    batch_size=64,
    epochs=20,
    validation_split=0.3,
    callbacks=[early_stop]
)

# 测试
test_loss, test_acc = model.evaluate(test_data, test_labels)
print("test_acc:", test_acc)

内容的提问来源于stack exchange,提问作者mwdziak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 14:25:42