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

Python中图像数组归一化时内存耗尽,求解决方法

解决猫狗分类图像归一化内存耗尽问题

核心问题原因

你当前的代码会一次性将所有训练/测试图像加载到内存中的Numpy数组,加上归一化操作会创建新的数组副本,直接耗尽内存。哪怕减少图像数量,当单张图像分辨率较高时,内存占用依然会超过上限。

最优解决方案:使用TensorFlow tf.data 流式加载+实时归一化

这种方式不需要一次性加载所有图像到内存,而是按需加载单批图像、实时完成归一化,内存占用仅为单批图像的大小,彻底解决内存溢出问题。

步骤1:获取所有图像文件路径

import glob
import tensorflow as tf

train_paths = glob.glob('/content/drive/MyDrive/Colab Notebooks/Cats_Dogs/training_set/*.jpg')
test_paths = glob.glob('/content/drive/MyDrive/Colab Notebooks/Cats_Dogs/test_set/*.jpg')

步骤2:定义加载+预处理函数(内置归一化)

函数会读取单张图像、直接归一化到0-1区间,同时生成对应标签(和你原代码的独热编码格式一致):

def load_and_preprocess(img_path):
    # 读取图像文件
    img_raw = tf.io.read_file(img_path)
    # 解码JPEG图像,保留3通道
    img = tf.image.decode_jpeg(img_raw, channels=3)
    # 归一化到0-1范围(直接替代原代码的除以255操作)
    img = tf.cast(img, tf.float32) / 255.0
    
    # 生成标签:从文件名提取首字符,转成独热编码
    filename = tf.path.basename(img_path)
    label_char = tf.strings.substr(filename, 0, 1)
    # 狗(d)标记为1,猫(c)标记为0,再转独热编码
    label = tf.cast(tf.equal(label_char, 'd'), tf.int32)
    label = tf.one_hot(label, depth=2)
    
    return img, label

步骤3:构建流式数据集

设置批次大小,让数据集自动完成洗牌、分批、预加载,训练时直接传入模型即可:

batch_size = 32  # 可根据内存调整,比如16/64

# 构建训练数据集
train_ds = tf.data.Dataset.from_tensor_slices(train_paths)
train_ds = train_ds.map(load_and_preprocess, num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.shuffle(len(train_paths)).batch(batch_size).prefetch(tf.data.AUTOTUNE)

# 构建测试数据集
test_ds = tf.data.Dataset.from_tensor_slices(test_paths)
test_ds = test_ds.map(load_and_preprocess, num_parallel_calls=tf.data.AUTOTUNE)
test_ds = test_ds.batch(batch_size).prefetch(tf.data.AUTOTUNE)

步骤4:训练模型

直接将流式数据集传入model.fit即可:

# 你的模型定义(和原代码一致,需替换input_shape为你的图像尺寸)
model = Sequential([
    Conv2D(32, (3,3), activation='relu', input_shape=(224, 224, 3)),
    MaxPooling2D((2,2)),
    Conv2D(64, (3,3), activation='relu'),
    MaxPooling2D((2,2)),
    Conv2D(128, (3,3), activation='relu'),
    MaxPooling2D((2,2)),
    Flatten(),
    Dense(512, activation='relu'),
    Dropout(0.5),
    Dense(2, activation='softmax')
])

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

# 训练
model.fit(train_ds, validation_data=test_ds, epochs=10)

备选方案:分批加载并归一化(适合坚持用Numpy的场景)

如果不想用TensorFlow的数据集API,可以分批加载图像,处理一批就存一批,避免一次性占满内存:

import cv2
import numpy as np
import glob

batch_size = 100
train_paths = glob.glob('/content/drive/MyDrive/Colab Notebooks/Cats_Dogs/training_set/*.jpg')
total_batches = len(train_paths) // batch_size + 1

# 分批处理并保存到磁盘(或直接分批训练)
for batch_idx in range(total_batches):
    start = batch_idx * batch_size
    end = min((batch_idx+1)*batch_size, len(train_paths))
    batch_paths = train_paths[start:end]
    
    # 加载当前批次图像并归一化
    batch_imgs = []
    for path in batch_paths:
        img = cv2.imread(path)
        img = img / 255.0
        batch_imgs.append(img)
    batch_imgs = np.array(batch_imgs)
    
    # 这里可以直接用batch_imgs训练,或者保存到.npy文件后续加载
    # np.save(f'train_batch_{batch_idx}.npy', batch_imgs)

你之前尝试的逐个归一化代码问题

你写的img_train = np.array([])是空数组,循环中用img_train[x]赋值是错误的——x是图像数组而非索引,正确的方式应该是用列表逐个append归一化后的图像,但这种方式最终还是会把所有图像加载到内存,无法解决根本问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 07:40:21