使用LSTM进行韩文文本分类时验证准确率始终不变的问题排查
韩文LSTM文本分类:验证准确率固定问题的排查与解决
核心问题分析
- 输入数据结构完全错误:LSTM是序列模型,要求输入为三维序列数据(样本数×序列长度×特征数),但你用TF-IDF生成的是二维词袋向量(样本数×词汇表大小),这种结构丢失了文本语序信息,LSTM无法学习序列特征;同时Embedding层的输入必须是词的整数索引序列,而非TF-IDF的浮点数组,导致Embedding层完全无法正常工作。
- 输出层维度不匹配:
Dense(128, activation='softmax')中的128是固定值,但分类任务的输出单元数必须等于train_df.cat3的实际类别数量,否则模型输出与标签维度不匹配,训练逻辑混乱。 - 潜在类别不平衡:验证准确率固定为0.2125,大概率对应数据集中占比最高的类别比例,说明模型一直在预测这个大类,根本没学到有效特征。
解决方案
1. 替换TF-IDF为序列预处理流程
使用Tokenizer将文本转换为整数索引序列,再用pad_sequences统一长度,适配LSTM的输入要求。韩文建议先分词(如用KoNLPy的Okt工具),提升预处理效果。
from tensorflow.keras.preprocessing.text import Tokenizer from tensorflow.keras.preprocessing.sequence import pad_sequences # 可选韩文分词(需先安装konlpy) # from konlpy.tag import Okt # okt = Okt() # def tokenize_korean(text): # return ' '.join(okt.morphs(text)) # train_df['overview'] = train_df['overview'].apply(tokenize_korean) # test_df['overview'] = test_df['overview'].apply(tokenize_korean) # 基于训练集构建词汇表 tokenizer = Tokenizer(num_words=14256) # 沿用原TF-IDF的词汇表大小 tokenizer.fit_on_texts(train_df.overview) # 文本转整数序列 X_train_seq = tokenizer.texts_to_sequences(train_df.overview.tolist()) X_test_seq = tokenizer.texts_to_sequences(test_df.overview.tolist()) # 统一序列长度 max_seq_len = max([len(seq) for seq in X_train_seq]) X_train_pad = pad_sequences(X_train_seq, maxlen=max_seq_len, padding='post', truncating='post') X_test_pad = pad_sequences(X_test_seq, maxlen=max_seq_len, padding='post', truncating='post') # 此时输入形状为 (样本数, 序列长度),符合LSTM要求 print(X_train_pad.shape)
2. 修正模型结构
调整Embedding层参数适配序列输入,同时将输出层单元数设置为实际类别数量:
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Embedding, LSTM, Dense, Dropout # 获取实际类别数量 num_classes = train_df.cat3.nunique() model = Sequential() # Embedding层:输入维度=词汇表大小,输出维度=嵌入向量长度,输入长度=序列长度 model.add(Embedding(input_dim=14256, output_dim=120, input_length=max_seq_len)) model.add(LSTM(128)) model.add(Dropout(0.3)) # 可选:添加Dropout防止过拟合 # 输出层单元数=类别数,softmax激活适配多分类 model.add(Dense(num_classes, activation='softmax')) model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['acc']) es = EarlyStopping(monitor='val_loss', patience=30, verbose=1) history = model.fit( X_train_pad, train_df.cat3.values, validation_split=0.2, shuffle=True, batch_size=64, epochs=500, callbacks=[es] )
3. 额外优化建议
- 若存在类别不平衡,可在
model.compile中添加class_weight参数,或对数据集进行重采样。 - 尝试使用双向LSTM(
Bidirectional(LSTM(128)))捕捉双向序列特征。 - 调整嵌入维度、LSTM单元数等超参数,提升模型拟合能力。
内容的提问来源于stack exchange,提问作者bongbong
相关产品推荐
相关产品推荐

