训练图像分类CNN时遭遇数据基数模糊问题求助
解决CNN图像分类训练中的「数据基数模糊」报错
问题背景
训练性别分类CNN模型时触发「Ambiguous data cardinality」(数据基数模糊)报错,已确认图像数据集与标签集的样本数量匹配,但无法定位问题根源。相关代码如下:
import numpy as np import os, shutil import tensorflow as tf from PIL import Image import matplotlib.pyplot as plt import glob dataset_path = '/Users/myusername/Downloads/Male_and_Female_face_dataset' male_faces = os.path.join(dataset_path, 'Male_Faces') female_faces = os.path.join(dataset_path, 'Female_Faces') batch_size = 32 img_height = 180 img_width = 180 plt.figure(figsize=(10, 10)) image_files = os.listdir(male_faces) # Loop for displaying only the first 9 images for i in range(9): img_path = os.path.join(male_faces, image_files[i]) # Read the image using PIL and convert it to a NumPy array img_array = np.asarray(Image.open(img_path)) ax = plt.subplot(3, 3, i+1) plt.imshow(img_array.astype("uint8")) plt.title(f"Male {i+1}") # You can modify this title as needed plt.axis('off') plt.show() plt.figure(figsize=(10, 10)) image_files = os.listdir(female_faces) # Loop for displaying only the first 9 images for i in range(9): img_path = os.path.join(female_faces, image_files[i]) # Read the image using PIL and convert it to a NumPy array img_array = np.asarray(Image.open(img_path)) ax = plt.subplot(3, 3, i+1) plt.imshow(img_array.astype("uint8")) plt.title(f"female {i+1}") # You can modify this title as needed plt.axis('off') plt.show() male_file_types = set() female_file_types = set() for img in os.listdir(male_faces): img_path = os.path.join(male_faces, img) file_extension = os.path.splitext(img_path)[1] if file_extension not in male_file_types: male_file_types.add(file_extension) male_file_types for img in os.listdir(female_faces): img_path = os.path.join(female_faces, img) file_extension = os.path.splitext(img_path)[1] if file_extension not in female_file_types: female_file_types.add(file_extension) female_file_types male_file_types female_file_types male_images = [] female_images = [] labels = [] for file in os.listdir(male_faces): file_path = os.path.join(male_faces, file) file = np.asarray(Image.open(file_path)) male_images.append(file) labels.append('male') for file in os.listdir(female_faces): file_path = os.path.join(female_faces, file) file = np.asarray(Image.open(file_path)) female_images.append(file) labels.append('female') len(male_images) len(female_images) X = male_images + female_images y = labels len(X) len(y) from sklearn.model_selection import train_test_split print(y[0]) one_hot_labels = np.array([[1, 0] if label == 'female' else [0, 1] for label in y]) print(one_hot_labels) y = one_hot_labels for i in range(5): print(X[i].shape) import cv2 X_resized = [] for array in X: X_resize = cv2.resize(array, (200, 200), interpolation=cv2.INTER_AREA) X_resized.append(X_resize) X = X_resized X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.25, random_state=1) model = tf.keras.Sequential([ tf.keras.layers.InputLayer(input_shape=(200, 200, 3)), tf.keras.layers.Conv2D(32, kernel_size=(3, 3), activation='relu'), tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), tf.keras.layers.Flatten(), tf.keras.layers.Dense(64, activation='relu'), tf.keras.layers.Dense(2, activation='softmax') ]) # Compile the model model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) # Train the model history = model.fit(X_train, y_train, epochs=10, batch_size=32, validation_data=(X_val, y_val)) # Evaluate the model on the validation set loss, accuracy = model.evaluate(X_val, y_val) print(f'Validation accuracy: {accuracy}')
问题根源
你虽然调整了所有图像的尺寸为(200,200,3),但X_train、X_val始终是Python列表,而非NumPy数组。TensorFlow的model.fit需要输入具有明确形状的张量(NumPy数组或TensorFlow张量),列表无法让框架正确推断数据的整体维度和样本基数,即使每个列表元素的形状一致,列表本身没有统一的形状属性,最终触发基数模糊报错。
解决方案
在划分数据集后,将图像列表转换为NumPy数组,添加以下代码:
# 将训练、验证、测试集转换为NumPy数组 X_train = np.array(X_train) X_val = np.array(X_val) X_test = np.array(X_test)
转换后可以检查数组形状,确保符合模型输入要求:
print(X_train.shape) # 预期输出:(样本数, 200, 200, 3) print(y_train.shape) # 预期输出:(样本数, 2)
完成上述修改后,TensorFlow就能正确识别数据的基数和维度,正常启动训练。
内容的提问来源于stack exchange,提问作者gusifer98
相关产品推荐
相关产品推荐

