PyTorch多分类模型训练无进展,损失持续震荡求助
多分类模型训练不收敛问题排查
问题概况
使用PyTorch搭建MLP多分类模型,以TIME OCC(案发时间)、**AREA(区域)为输入特征,对Crm Cd(犯罪类型)**进行分类,共138个类别。完成数据读取、特征提取、标签映射、归一化、数据集加载等步骤后,训练时损失始终在4.908~4.708区间震荡,无法收敛,模型无学习效果,怀疑数据集格式存在问题。
已执行的数据处理步骤
读取数据集
# main data df = pd.read_csv('abstract_data.csv',delimiter=',')
数据集包含TIME OCC、AREA、Crm Cd等字段,样本量893672条。
提取输入特征
# extracting the 2 inputs from the dataset inputs_list=['TIME OCC','AREA'] inputs=df[inputs_list].to_numpy() inputs.shape # of shape (893672, 2)
标签处理
提取原始标签:
# extraction the labels y=df['Crm Cd']
原始标签样例:
0 510 1 330 2 480 3 343 4 354 ... 893667 740 893668 230 893669 625 893670 745 893671 210 Name: Crm Cd, Length: 893672, dtype: int64
将原始3位数字标签映射为0-137的连续类别ID:
# unique classes unq=y.unique() # mapping origonal classes numbers into the new classes ids y2=[] for i in y: #print(f'i: {i}') for index, element in enumerate(unq): if i == element: y2.append(index) break output=np.array(y2)
模型训练配置
- 模型结构:MLP
- 损失函数:CrossEntropyLoss
- 优化器:SGD、Adam(均尝试)
- 调整过的参数:学习率、MLP层数/神经元数
排查方向
1. 标签映射效率与正确性
当前标签映射采用嵌套循环,效率极低且易出错。建议用pandas.factorize替代,同时验证映射后的类别分布是否正确:
# 更高效的标签映射方式 output, unq = pd.factorize(df['Crm Cd']) # 验证类别数量是否为138 assert len(unq) == 138, "类别数量不符"
检查映射后的标签是否覆盖所有138个类别,无遗漏或重复。
2. 输入特征的预处理合理性
- TIME OCC:若为原始时间格式(如HHMM),需转为周期性特征(如sin/cos编码小时、分钟),而非直接归一化。直接归一化会破坏时间的周期性(如23:59和00:01归一化后差距大,但实际时间接近)。
- AREA:若为类别型特征(如区域编号),需进行独热编码或嵌入(Embedding)处理,而非当作数值特征归一化。区域编号本身无数值大小意义,直接归一化会引入错误的数值关联。
3. 数据集划分与类别平衡
- 检查训练集/验证集的类别分布是否与整体一致,避免出现严重的类别不平衡。138个类别中若存在大量稀有类别,会导致模型倾向于预测高频类别,损失震荡。
- 计算每个类别的样本占比,若某类别样本占比极低,可考虑合并相似类别或采用加权CrossEntropyLoss。
4. 模型结构与初始化
- 仅2个输入特征的情况下,MLP的第一层神经元数量不宜过多,避免过拟合或梯度消失。建议从64/128神经元开始尝试。
- 检查模型初始化方式,确保权重初始化合理(如Xavier/Kaiming初始化),避免初始权重导致梯度异常。
5. 训练流程验证
- 检查DataLoader是否正确加载数据,输入与标签的维度是否匹配(输入应为[N,2],标签应为[N])。
- 验证CrossEntropyLoss的输入格式:模型输出应为[N,138](每个样本对应138个类别的logit),标签应为类别的索引(0-137),无需独热编码。
- 查看训练时的梯度值,若梯度接近0或过大,需调整学习率或模型结构。
内容的提问来源于stack exchange,提问作者Amir Alasady
相关产品推荐
相关产品推荐

