从零训练MobileNet识别日文字符:验证集准确率为0的问题求助
首先,先解答你关于标签的两个疑问:
标签相关疑问
是否需要独热编码?
是的,因为你使用的是categorical_crossentropy作为损失函数,这种损失函数要求标签是独热编码格式(每个标签对应一个长度为类别数的向量,只有对应类别位置为1,其余为0)。你代码中已经使用tf.one_hot(label, num_classes)做了这个转换,这部分是正确的,但要注意:你的标签取值必须是0到955之间的整数(因为总共有956个类别),如果标签存在超出这个范围的数值,会导致独热编码失效,进而影响损失计算。是否可以使用全零标签?
绝对不可以!如果所有样本的标签都是0,模型只会学到“输出类别0就可以降低损失”,完全无法区分不同的日文字符类别,这会直接导致验证集准确率为0,训练集损失下降只是模型记住了这个无效的模式,没有任何泛化能力。请立即检查你的TFRecord文件中的标签是否有正常的类别分布,而不是全零或大部分为零。
代码中的核心问题排查
1. 输入图像尺寸不匹配MobileNet设计
MobileNet的默认输入尺寸是224x224x3,而你当前使用的是64x64的图像。小尺寸图像的特征信息量远不足以支撑956个类别的分类任务,会导致模型无法提取到足够的区分特征。
你代码中注释掉了图像resize的代码:
#image = tf.image.resize_images(image, (224, 224))
请取消注释这一行,将图像统一resize到224x224,这是MobileNet设计时优化的输入尺寸,能大幅提升特征提取能力。
2. 训练步数设置矛盾
你代码中设置了max_steps=500,但描述中说训练了约10万次迭代,这明显矛盾。如果是实际训练时修改了参数,那没问题;但如果是代码中的max_steps未更新,500步对于956类的任务来说远远不够,模型还没来得及学习到有效特征。
3. 数据正确性验证
建议先编写一个小脚本,读取你的TFRecord文件,解码几个样本的图像和标签,确认:
- 图像解码后是正确的日文字符图像(可以用PIL显示)
- 标签的取值范围在
0~955之间,且分布正常(不是全零或集中在少数类别)
示例验证代码片段:
import tensorflow as tf def check_tfrecord(filename): dataset = tf.data.TFRecordDataset(filename) for serialized in dataset.take(5): # 取前5个样本 features = { 'image/encoded': tf.FixedLenFeature([], tf.string), 'image/class/label': tf.FixedLenFeature([], tf.int64) } parsed_example = tf.parse_single_example(serialized, features) image = tf.image.decode_png(parsed_example['image/encoded'], 3) label = parsed_example['image/class/label'] print(f"Label: {label.numpy()}") # 显示图像 from PIL import Image img = Image.fromarray(image.numpy()) img.show() check_tfrecord('/home/myuser/data_set/dump_train_00000-of-00006.tfrecord')
4. 输入函数的潜在问题
检查_parse_function中image_shape的定义:
image_shape = tf.stack([parsed_example['image/width'], parsed_example['image/height'], 3])
如果你的TFRecord中存储的image/width和image/height都是64,那没问题;但如果存在不同尺寸的图像,tf.reshape会报错。而你后续如果resize到224x224,其实可以直接固定shape为(224,224,3),不需要从TFRecord中读取宽高,避免潜在的形状不匹配问题。修改为:
image = tf.image.resize_images(image, (224, 224)) image = tf.reshape(image, (224, 224, 3))
额外建议
- 尝试降低学习率:如果验证集损失先上升后稳定,可能是学习率过高导致模型震荡无法收敛。可以尝试将Adam的学习率设置为
1e-4,RMSProp设置为1e-3,观察效果。 - 增加正则化:956个类别属于多分类任务,容易过拟合,你已经设置了
dropout=0.001,可以尝试提高dropout率到0.2或添加L2正则化,增强模型泛化能力。 - 监控训练过程:在训练时查看Estimator的日志输出,确认训练集的准确率是否真的在上升,如果训练集准确率也很低,说明模型根本没学到东西,大概率是数据(图像或标签)有问题。
内容的提问来源于stack exchange,提问作者Seba

