You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何加载自定义图片训练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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:15:59