使用自定义数据集构建神经网络时遭遇ValueError:无法将NumPy数组转换为Tensor(不支持的对象类型numpy.ndarray)
问题分析与修复方案
先帮你梳理代码里的几个关键问题,这些都是导致model.fit报错的核心原因:
1. 数据集路径错误
你定义white_people的时候,路径写成了和black_people一样的'black people',这意味着两个数据集加载的都是同一份图片,完全无法进行二分类训练:
# 错误代码 white_people = os.path.join(os.curdir, 'black people') # 应该改成对应的白人图片文件夹,比如: white_people = os.path.join(os.curdir, 'white people')
2. 数据集结构完全错误
你把图片数组和标签字符串混在了twod_array的同一个元素里,转成numpy数组后会变成dtype=object的混合数组,模型根本无法识别这种输入。正确的做法是把特征数据和标签数据分开存储:
- 特征数据:所有图片的归一化数组,形状应该是
(样本数, 32, 32, 通道数) - 标签数据:对应每个样本的数字标签(0代表White,1代表Black)
3. 模型结构与任务不匹配
你做的是二分类任务,但:
- 输入层
Flatten(input_shape=(32, 32))没有考虑图片的通道数(如果是RGB图,应该是(32,32,3)) - 输出层用了
Dense(10, activation='softmax'),这是给10分类任务用的,二分类应该用Dense(1, activation='sigmoid')配合binary_crossentropy损失,或者Dense(2, activation='softmax')配合sparse_categorical_crossentropy
4. 标签手动编写易出错
手动写class_label的列表很容易和样本数量不匹配,应该自动根据数据集长度生成标签。
修正后的完整代码
from PIL import Image import numpy as np import os import tensorflow as tf from tensorflow import keras import matplotlib.pyplot as plt # 1. 修复路径问题 black_people_dir = os.path.join(os.curdir, 'black people') white_people_dir = os.path.join(os.curdir, 'white people') def load_images_from_dir(dir_path): """加载指定文件夹下的所有png图片,归一化并返回numpy数组""" images = [] for root, _, files in os.walk(dir_path): for file in filter(lambda f: f.endswith(".png"), files): img_path = os.path.join(root, file) # 确保图片尺寸统一为32x32(根据你的模型输入调整) img = Image.open(img_path).resize((32, 32)) img_array = np.array(img) / 255.0 # 归一化到0-1 images.append(img_array) return np.array(images) # 加载两个数据集 black_images = load_images_from_dir(black_people_dir) white_images = load_images_from_dir(white_people_dir) # 2. 生成特征和标签数据 X = np.concatenate([white_images, black_images], axis=0) # 生成标签:白人样本标签为0,黑人样本标签为1 y = np.array([0]*len(white_images) + [1]*len(black_images)) # 检查数据形状:比如(样本数, 32, 32, 3)(如果是RGB图) print(f"特征数据形状: {X.shape}") print(f"标签数据形状: {y.shape}") # 3. 修正模型结构(二分类版本) model = keras.Sequential([ # 如果是灰度图,input_shape=(32,32,1);RGB图则是(32,32,3) keras.layers.Flatten(input_shape=(32, 32, 3)), keras.layers.Dense(128, activation='relu'), # 二分类用sigmoid激活,输出0-1的概率 keras.layers.Dense(1, activation='sigmoid') ]) # 4. 修正编译参数(对应二分类) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # 训练模型 model.fit(X, y, epochs=5)
额外注意事项
- 确保所有图片的尺寸一致:如果原始图片不是32x32,用
resize((32,32))统一尺寸,否则Flatten层会因为输入形状不一致报错 - 如果是灰度图片,记得把
input_shape改成(32,32,1),或者在加载时转成灰度图:img = Image.open(img_path).convert('L').resize((32,32)) - 可以加入数据集打乱:
from sklearn.utils import shuffle; X, y = shuffle(X, y),避免模型学习到顺序规律
内容的提问来源于stack exchange,提问作者snoopyballz901
相关产品推荐
相关产品推荐

