You need to enable JavaScript to run this app. Keras多类文本分类模型训练无报错但损失异常、准确率停滞求助
优惠活动
大模型
产品
解决方案
定价
更多

Keras多类文本分类模型训练无报错但损失异常、准确率停滞求助

多类文本分类训练失效问题排查

项目背景

  • 基于公开会议标题数据集开展多类文本分类练习
  • 为深入理解NLP底层原理,全程手动实现数据处理全流程,未依赖高层封装的预处理工具
  • 训练过程无代码运行报错,但指标长期停滞:loss: -3.8982e+01 - accuracy: 0.2058
  • 初步判断问题出在数据预处理逻辑环节,需要可落地的排查思路与优化方向

现有实现代码

import nltk 
nltk.download('punkt')
nltk.download('averaged_perception_tagger')
nltk.download('stopwords')
stopwords = nltk.corpus.stopwords.words('english')
from nltk.corpus import stopwords 

from sklearn.feature_extraction.text import CountVectorizer 
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np 
from sklearn.utils import shuffle
from keras.preprocessing import sequence 
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation 
from keras.layers import Embedding, LSTM, SpatialDropout1D
from keras.layers import Conv1D, Flatten, MaxPooling1D
from keras.preprocessing.sequence import pad_sequences 
from keras.utils.np_utils import to_categorical
from keras.preprocessing import text 
import tensorflow as tf
from nltk.tokenize import word_tokenize 

with open('/Multi Class Text Classification.txt') as f:
  data = f.read().splitlines()

conference_name = []
description = []
for row in data[1:]:
  conference_name.append(row.split()[-1].split(',')[1])
  description.append(row.split('.')[0])

import string 
stop_words = set(stopwords.words('english')) 
words = []
for row in description:
  for word in row.split():
    word = word.translate(str.maketrans('','',string.punctuation))
    if word not in stop_words and len(word) > 1:
      words.append(word.lower())

words_unique = sorted(list(set(words)))


count = 0 
word_idx = {}
for word in words_unique:
  count +=1
  if word not in word_idx:
    word_idx[word] = count

text_to_sequences = []
#Replace description with the index of each word
for row in description:
  empty = []
  for word in row.split():
    word = word.translate(str.maketrans('','',string.punctuation))
    word = word.lower()
    if word not in stop_words and len(word) > 1:
      empty.append(word_idx.get(word))
  text_to_sequences.append(empty)

def pad_sequences(text_sequences:list, length:int): #pad sequences
  padded_sequences = []
  max_len = length #choose an arbritrary number 
  for text_sequence in text_sequences:
    length = len(text_sequence)
    i = 0 
    while  length + i < max_len:
      text_sequence.insert(i,0)
      i += 1
    padded_sequences.append(text_sequence)
  return padded_sequences 

train_x = pad_sequences(text_to_sequences,20)
train_x = np.array(train_x)
print(train_x)

 #Create labels 
unique_labels = list(set(conference_name))
labels = []


for i in conference_name:
  if i in unique_labels:
    labels.append(unique_labels.index(i))
labels = np.array(labels)


#Creating the LSTM model 
import keras
from tensorflow.keras import layers 

model = keras.models.Sequential()
model.add(layers.Embedding(len(words),32,input_length = 10))
model.add(SpatialDropout1D(0.2))
model.add(layers.LSTM(196, dropout = 0.1, recurrent_dropout=0.1))

model.add(layers.Dense(1,activation = 'sigmoid'))

model.summary()

loss = keras.losses.BinaryCrossentropy(from_logits=False)
optim = keras.optimizers.Adam(lr = 0.0001)
metrics = ['accuracy']

model.compile(loss = loss , optimizer= optim, metrics = metrics)
model.fit(train_x,labels,epochs=35, verbose = 2)

核心问题定位

  • 任务类型与模型配置完全不适配
    本任务是4类文本分类,属于典型多分类场景,当前代码输出层为Dense(1, activation='sigmoid'),搭配二分类专用的BinaryCrossentropy损失,完全无法适配多分类的标签分布。二分类损失计算时要求标签值处于0-1的合法范围,当前传入的整数标签最大为3,超出合法取值范围,直接导致交叉熵计算出现异常负值;同时4类任务的随机猜中准确率为25%,当前训练准确率仅20%,本质是模型完全没有学到有效特征,处于随机预测状态。
  • Embedding层参数与实际输入不匹配
    手动补全后统一的序列长度为20,但Embedding层定义的input_length = 10,输入张量与层的期望维度不一致,会直接导致前向传播的特征映射错位;同时Embedding层传入的词表大小为总原始词数len(words),实际手动构建的词表最大索引为len(words_unique),存在索引映射范围不匹配的问题。
  • 数据解析逻辑存在截断误差
    数据集本身为CSV格式,当前代码通过手动字符串切分提取标题与标签,遇到标题内包含逗号、句号的样本时,会出现标题截断、标签错位的问题,训练样本的标注本身存在噪声。
  • 自定义padding函数存在逻辑缺陷
    函数循环过程中直接修改传入的原始序列对象,会导致后续复用序列时被重复补零;同时未设置序列截断逻辑,当原始序列长度大于设定的补全长度20时,输出序列长度不符合模型输入要求,会触发维度不匹配的隐性错误。
  • 标签编码方式不满足训练要求
    当前直接将标签的索引值作为整数输入模型,未根据损失函数要求做对应编码,会进一步加剧模型收敛失效的问题。

优化调整步骤

  • 修正模型适配配置:输出层改为Dense(类别总数, activation='softmax'),二分类损失替换为多分类对应损失——若保持整数标签形式可使用SparseCategoricalCrossentropy,若对标签做独热编码则使用CategoricalCrossentropy
  • 修正Embedding层参数:词表大小设为len(words_unique) + 1(预留0值对应padding位),input_length设置为与实际补全后的序列长度一致(当前为20)
  • 替换数据读取逻辑:使用pandas的CSV读取接口直接加载数据集,避免手动字符串切分带来的解析误差
  • 修正自定义padding函数:复制原始序列后再执行补零操作,避免修改原数据;增加序列截断逻辑,长度超过设定值的序列直接截取前N个元素,长度不足的序列在开头补零
  • 训练前按比例划分训练集、验证集,监控验证集指标,避免全量数据直接训练带来的指标计算偏差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.05 07:57:03