如何加载自定义图片训练MNIST手写数字识别模型?
自定义手写数字图片融入MNIST训练流程的实现方案
我已经看过Stack Overflow上《MNIST trained network tested with my own samples》的讨论,但没找到把自定义图片加入MNIST训练流程的方法。我打算用自定义手写数字图片(比如所有标注为5的图片)来训练MNIST模型,但多数教程都没讲这块。现在用原生MNIST数据集训练的Keras脚本准确率只有约10%,想把本地的自定义图片整理成训练需要的图像数组和标签数组,传入model.fit训练。现有脚本已经能加载单张自定义图片预测,但不知道怎么批量加载来完成训练。
现有训练脚本如下:
import keras from keras.datasets import mnist import matplotlib.pyplot as plt import PIL from PIL import Image (train_images,train_labels),(test_images,test_labels) = mnist.load_data() train_images.shape len(train_labels) train_labels test_images.shape len(test_labels) test_labels from keras import models from keras import layers network = models.Sequential() network.add(layers.Dense(512,activation='relu',input_shape=(28*28,))) network.add(layers.Dense(10,activation='softmax')) network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) train_images = train_images.reshape((60000,28*28)) train_images = train_images.astype('float32')/255 test_images = test_images.reshape((10000,28*28)) test_images = test_images.astype('float32')/255 from keras.utils import to_categorical train_labels = to_categorical(train_labels) test_labels = to_categorical(test_labels) network.fit(train_images,train_labels,epochs= 3 ,batch_size=128) test_loss , test_acc = network.evaluate(test_images,test_labels) print('test_acc:',test_acc) network.save('m_lenet.h5') ######### import numpy as np from keras.models import load_model import matplotlib.pyplot as plt from PIL import Image model = load_model('/content/m_lenet.h5') picPath = '/content/02_a.png' img = Image.open(picPath) reIm = img.resize((28,28),Image.ANTIALIAS) plt.imshow(reIm) plt.savefig('/content/result.png') im1 = np.array(reIm.convert("L")) im1 = im1.reshape((1,28*28)) im1 = im1.astype('float32')/255 # predict = model.predict_classes(im1) predict_x=model.predict(im1) classes_x=np.argmax(predict_x,axis=1) print ("---------------------------------") print ('predict as:') print (predict_x) print ("") print ("") print ('predict number as:') print (classes_x) print ("---------------------------------") print ("Original img : ")
一、批量加载自定义图片生成训练数组
1. 整理自定义图片目录结构
建议按数字分类存放,方便批量读取:
custom_data/ ├── 0/ │ ├── img0.png │ ├── img1.png │ └── ... ├── 1/ │ ├── img0.png │ └── ... ... └── 9/ └── ...
如果只想加入某一类(比如数字5),单独建立5/目录即可。
2. 批量加载并预处理图片的代码实现
用PIL和numpy批量读取图片,转换成符合MNIST格式的数组:
import os import numpy as np from PIL import Image def load_custom_images(data_dir, target_size=(28,28)): images = [] labels = [] # 遍历每个数字目录 for digit in os.listdir(data_dir): digit_dir = os.path.join(data_dir, digit) if not os.path.isdir(digit_dir): continue # 遍历目录下的所有图片 for img_name in os.listdir(digit_dir): img_path = os.path.join(digit_dir, img_name) try: # 打开图片并转为灰度图 img = Image.open(img_path).convert('L') # 调整尺寸(适配新版PIL) img = img.resize(target_size, Image.Resampling.LANCZOS) # 反转颜色(MNIST是黑底白字,若你的图片是白底黑字必须执行) img_array = 255 - np.array(img) # 归一化到0-1区间 img_array = img_array.astype('float32') / 255 # 展平成(784,)的一维数组 img_array = img_array.flatten() images.append(img_array) # 添加对应数字标签 labels.append(int(digit)) except Exception as e: print(f"加载图片{img_path}失败: {e}") # 转换为numpy数组 images = np.array(images) labels = np.array(labels) return images, labels
3. 合并自定义数据与原生MNIST数据
加载完自定义数据后,和原生MNIST的训练数组合并:
# 加载自定义数据,替换为你的本地目录路径 custom_train_images, custom_train_labels = load_custom_images("path/to/your/custom_data") # 加载原生MNIST数据 (train_images, train_labels), (test_images, test_labels) = mnist.load_data() # 预处理原生数据 train_images = train_images.reshape((60000, 28*28)).astype('float32')/255 test_images = test_images.reshape((10000, 28*28)).astype('float32')/255 # 合并训练数据 combined_train_images = np.concatenate([train_images, custom_train_images], axis=0) combined_train_labels = np.concatenate([train_labels, custom_train_labels], axis=0) # 转换标签为one-hot编码 from keras.utils import to_categorical combined_train_labels = to_categorical(combined_train_labels) test_labels = to_categorical(test_labels)
二、用合并后的数据训练模型
直接把合并后的数组传入model.fit即可:
# 初始化模型(和原代码一致) network = models.Sequential() network.add(layers.Dense(512,activation='relu',input_shape=(28*28,))) network.add(layers.Dense(10,activation='softmax')) network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) # 用合并数据训练,可适当增加epochs提升准确率 network.fit(combined_train_images, combined_train_labels, epochs=5, batch_size=128) # 评估模型 test_loss , test_acc = network.evaluate(test_images,test_labels) print('test_acc:',test_acc) # 保存更新后的模型 network.save('m_lenet_with_custom.h5')
三、关键注意事项
- 颜色反转:MNIST数据集是黑底白字,如果你的自定义图片是白底黑字,必须执行
img_array = 255 - np.array(img),否则模型识别逻辑会完全错误。 - 格式匹配:所有图片必须调整为28x28的灰度图,和MNIST数据格式保持一致。
- 数据归一化:所有图片都要除以255缩放到0-1之间,保证输入数据分布统一。
- 原脚本准确率低:原代码准确率仅10%大概率是训练轮次太少(仅3轮),合并自定义数据后可增加到5-10轮,提升模型拟合效果。
内容的提问来源于stack exchange,提问作者user20167627
相关产品推荐
相关产品推荐

