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

如何让Keras数据生成器适配图像numpy数组?报错求助

云识别模型开发中Keras数据处理报错排查与解决

开发云识别模型时,使用Keras从CSV读取图片ID和标签、加载指定目录图像,调用ImageDataGenerator.flow()时触发错误:

ValueError: ('Input data in NumpyArrayIterator should have rank 4. You passed an array with shape', (0,))

尝试修改图像numpy数组生成逻辑但未解决,附上完整代码与报错信息,请求排查解决。

原代码

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import cv2 
import pandas as pd
import tensorflow.python.keras
import keras
import os
from PIL import Image
from numpy import asarray

adam = Adam(learning_rate=0.0001)

train_data_map = pd.read_csv('C:/Users/owenc/Desktop/WeatherIdentify/input/cloud-type-classification2/train.csv')
img_path = 'C:/Users/owenc/Desktop/WeatherIdentify/input/cloud-type-classification2/images/train'
sub_class = os.listdir(img_path)
checkpoint_path = "C:\\Users\\owenc\\Desktop\\WeatherIdentify\\codes\\cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)

# Create a callback that saves the model's weights
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
                                                 save_weights_only=True,
                                                 verbose=1)

#class_names = ['cirriform clouds', 'high cumuliform clouds', 'stratocumulus clouds', 'cumulus clouds', 'cumulonimbus clouds', 'stratiform clouds', 'clear sky']

cases_count = train_data_map['label'].value_counts()
num_class = 7
epochs = 100
batch_size = 100

train_data_arr = []
train_data_label_arr = []
train_datagen = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True,
    validation_split=0.2)
for idx in range(len(train_data_arr)):
    train_data_label_arr.append(train_data_map.iloc[idx]['label'])
    train_data_arr.append(train_data_map.iloc[idx]['id'])

train_data_label_np = np.array(train_data_label_arr)
train_data = np.array([np.array(cv2.resize(cv2.imread(fname),244,244)) for fname in train_data_arr])
'''
for fname in train_data_arr:
    Img = Image.open(os.path.join(img_path, str(fname)))
    Img.resize((244,244))
    np.append(train_data, np.array(Img))
'''
model = Sequential()

model.add(Conv2D(filters = 32, kernel_size = (5,5),padding = 'Same', 
                 activation ='relu', input_shape = (224,224,3)))
model.add(Conv2D(filters = 32, kernel_size = (5,5),padding = 'Same', 
                 activation ='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.25))


model.add(Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', 
                 activation ='relu'))
model.add(Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', 
                 activation ='relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))
model.add(Dropout(0.25))


model.add(Flatten())
model.add(Dense(256, activation = "relu"))
model.add(Dropout(0.5))
model.add(Dense(num_class, activation = "softmax"))
model.build()
model.summary()
model.compile(loss='categorical_crossentropy', metrics=['acc'], optimizer=adam)
#TODO test

train_gen = train_datagen.flow(train_data, train_data_label_np, batch_size=batch_size)
print(train_gen)
history = model.fit(train_gen,
                epochs = epochs,
                steps_per_epoch=100 // batch_size,callbacks=[cp_callback])
model.save('supermod100.h5','C:\\Users\\owenc\\Desktop\\WeatherIdentify\\models')

报错信息

Traceback (most recent call last):
  File "c:\Users\owenc\Desktop\WeatherIdentify\codes\main.py", line 88, in <module>
    train_gen = train_datagen.flow(train_data, train_data_label_np, batch_size=batch_size)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\owenc\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\keras\src\preprocessing\image.py", line 1545, in flow
    return NumpyArrayIterator(
           ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\owenc\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\keras\src\preprocessing\image.py", line 758, in __init__
    raise ValueError(
ValueError: ('Input data in `NumpyArrayIterator` should have rank 4. You passed an array with shape', (0,))
PS C:\Users\owenc\Desktop\WeatherIdentify> 

问题排查与修复方案

核心错误点解析

  1. 训练数据为空
    初始化train_data_arr = []后,循环条件用了range(len(train_data_arr)),此时数组长度为0,循环完全没执行,导致train_data_arr和标签数组都是空的,最终train_data形状为(0,),触发rank不匹配的错误。

  2. 图像路径错误
    读取图像时直接使用fname(图片ID)作为路径,没有拼接图像目录img_path,会导致找不到图片,即使循环正常也加载失败。

  3. 图像尺寸不匹配
    模型输入形状是(224,224,3),但代码中resize设置为244,尺寸不一致会导致后续输入不兼容。

  4. 标签格式错误
    模型使用categorical_crossentropy损失,要求标签是独热编码格式,但当前直接将原始标签转为numpy数组,不符合要求。

  5. 其他细节问题

    • 缺少Adam、Sequential等类的导入语句,代码无法运行;
    • steps_per_epoch计算错误,100//100=1,训练步数严重不足;
    • model.save()参数格式错误,第二个参数不是路径,应直接传入完整保存路径。

修正后的完整代码

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import cv2 
import pandas as pd
import os
from PIL import Image
# 补充必要的导入
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.preprocessing.image import ImageDataGenerator

adam = Adam(learning_rate=0.0001)

train_data_map = pd.read_csv('C:/Users/owenc/Desktop/WeatherIdentify/input/cloud-type-classification2/train.csv')
img_path = 'C:/Users/owenc/Desktop/WeatherIdentify/input/cloud-type-classification2/images/train'
checkpoint_path = "C:\\Users\\owenc\\Desktop\\WeatherIdentify\\codes\\cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)

# 保存权重的回调
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
                                                 save_weights_only=True,
                                                 verbose=1)

num_class = 7
epochs = 100
batch_size = 100

train_data_arr = []
train_data_label_arr = []
train_datagen = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True,
    validation_split=0.2)

# 修正循环逻辑:遍历train_data_map的索引
for idx in range(len(train_data_map)):
    train_data_label_arr.append(train_data_map.iloc[idx]['label'])
    # 拼接完整图像路径
    img_full_path = os.path.join(img_path, str(train_data_map.iloc[idx]['id']))
    train_data_arr.append(img_full_path)

# 加载并预处理图像:修正尺寸为224,匹配模型输入
train_data = []
for fname in train_data_arr:
    # 读取图像,确保路径正确
    img = cv2.imread(fname)
    if img is not None:
        # resize参数应为(宽度,高度),cv2.resize的第二个参数是dsize=(w,h)
        img_resized = cv2.resize(img, (224, 224))
        train_data.append(img_resized)
train_data = np.array(train_data)

# 标签转为独热编码
train_data_label_np = to_categorical(train_data_label_arr, num_classes=num_class)

# 构建模型
model = Sequential()

model.add(Conv2D(filters=32, kernel_size=(5,5), padding='Same', 
                 activation='relu', input_shape=(224,224,3)))
model.add(Conv2D(filters=32, kernel_size=(5,5), padding='Same', 
                 activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.25))

model.add(Conv2D(filters=64, kernel_size=(3,3), padding='Same', 
                 activation='relu'))
model.add(Conv2D(filters=64, kernel_size=(3,3), padding='Same', 
                 activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(256, activation="relu"))
model.add(Dropout(0.5))
model.add(Dense(num_class, activation="softmax"))

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

# 生成数据生成器
train_gen = train_datagen.flow(train_data, train_data_label_np, batch_size=batch_size)

# 修正steps_per_epoch:用训练样本总数除以batch_size
steps_per_epoch = len(train_data) // batch_size
history = model.fit(train_gen,
                    epochs=epochs,
                    steps_per_epoch=steps_per_epoch,
                    callbacks=[cp_callback])

# 修正模型保存路径
model.save('C:\\Users\\owenc\\Desktop\\WeatherIdentify\\models\\supermod100.h5')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 15:14:59