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

CNN人脸分类训练报错:数组转标量及序列赋值异常排查

问题

我有总计1500张人脸数据集,每位人员对应500张人脸图像,计划用CNN做人脸预测,已经通过文件名(如mike.1.jpg)提取人员姓名。训练过程中出现only size-1 arrays can be converted to Python scalars和setting an array element with a sequence错误,不确定是数组格式问题还是CNN参数/网络层导致的,相关代码及报错信息如下:

数据集生成代码

# Generate dataset
def create_dataset():
    face_classifier = cv2.CascadeClassifier("/Users/germplus/PycharmProjects" 
                                            "/MAIDS-Thesis-Project/haarcascade_frontalface_default.xml")

    def image_cropped(image):
        #         convert image from RGB to gray scale to reduce complexity
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        # Scale images with scaling factor eg: 1.3 and minimum neighbour eg:)
        face = face_classifier.detectMultiScale(gray, 1.3, 5)

        if face is ():
            return None
        #         crop the faces
        for (x, y, w, h) in face:
            cropped_face = image[y:y + h, x:x + w]
        return cropped_face

    #     connect to web or external camera
    cam = cv2.VideoCapture(0)
    #     Participant id
    participant_image_name = participant
    #   image id
    image_id = 0

    while True:
        ret, frame = cam.read()
        if image_cropped(frame) is not None:
            image_id += 1
            # resize face
            face = cv2.resize(image_cropped(frame), (200, 200))
            face = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY)
            # save images to file
            file_path = "/Users/germplus/PycharmProjects/" \
                        "MAIDS-Thesis-Project/images/" \
                        + str(participant_image_name) + '.' + str(image_id) + '.jpg'
            cv2.imwrite(file_path, face)
            #  font scale = 1
            # thickness = 2
            cv2.putText(face, str(image_id), (50, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)

            cv2.imshow('Cropped face', face)
            # stop taking samples if you press enter or if image samples are up to 1000
            if cv2.waitKey(1) == 13 or int(image_id) == 500:
                break
    cam.release()
    cv2.destroyAllWindows()
    print("Sample images collection is completed.........")

标签与数据加载代码

def my_label(image_name):
    name = image_name.split('.')[-3]
    # names of participants in the research
    if name == 'Xavi':
        return np.array([1, 0, 0])
        # return np.array([1, 0, 0, 0, 0, 0, 0])
    elif name == 'mama_africa':
        return np.array([0, 1, 0])
        # return np.array([0, 1, 0, 0, 0, 0, 0])
    elif name == 'Isaac':
        return np.array([0, 0, 1])
        # return np.array([0, 0, 1, 0, 0, 0, 0])
    # elif name == Data_collection.participant:
    #     return np.array([0, 0, 0, 1, 0, 0, 0])
    # elif name == Data_collection.participant:
    #     return np.array([0, 0, 0, 0, 1, 0, 0])
    # elif name == Data_collection.participant:
    #     return np.array([0, 0, 0, 0, 0, 1, 0])
    # elif name == Data_collection.participant:
    #     return np.array([0, 0, 0, 0, 0, 0, 1])


def my_data():
    images = []
    for img in tqdm(os.listdir("/Users/germplus/PycharmProjects/MAIDS-Thesis-Project/images")):
        path = os.path.join("/Users/germplus/PycharmProjects/MAIDS-Thesis-Project/images", img)
        img_data = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
        img_data = cv2.resize(img_data, (50, 50))
        images.append([np.array(img_data), my_label(img)])
    shuffle(images)
    return images


data = my_data()

模型训练代码

# split data into train and testing
train = create_label.data[:1200]
test = create_label.data[1200:]

# x train in 0 index. -1 calculates the x-train number of train 50, 50 is the image shape.
# 1 is grayscale image
X_train = np.array([i[0] for i in train]).reshape(-1, 50, 50, 1)
print(f'X_train shape is {X_train.shape}')

# y train in 1 index -1 calculates the y-train number of train 50, 50 is the image shape
y_train = [i[1] for i in train]
X_test = np.array([i[0] for i in test]).reshape(-1, 50, 50, 1)
print(f'X_test shape is {X_test.shape}')
y_test = [i[1] for i in test]
print(X_train.ndim)
# DNN
# input_shape = input_data(shape=[50,50,1])

# model = tflearn.DNN

convnet = input_data(shape=[50,50,1])
convnet = conv_2d(convnet, 32, 5, activation='relu')
# 32 filters and stride=5 so that the filter will move 5 pixel or unit at a time
convnet = max_pool_2d(convnet, 5)
convnet = conv_2d(convnet, 64, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)
convnet = conv_2d(convnet, 128, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)
convnet = conv_2d(convnet, 64, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)
convnet = conv_2d(convnet, 32, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)

convnet = fully_connected(convnet, 1024, activation='relu')
convnet = dropout(convnet, 0.8)
convnet = fully_connected(convnet, 3, activation='softmax')
convnet = regression(convnet, optimizer='adam', learning_rate = 0.001, loss='categorical_crossentropy')
model = tflearn.DNN(convnet, tensorboard_verbose=1)
model.fit(X_train, y_train, n_epoch=12, validation_set=(X_test, y_test))

报错信息

Training samples: 1200
Validation samples: 300
--
2022-08-15 10:15:12.869457: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:112] Plugin optimizer for device_type GPU is enabled.
TypeError: only size-1 arrays can be converted to Python scalars

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/germplus/PycharmProjects/MAIDS-Thesis-Project/model_fit.py", line 86, in <module>
    model.fit(X_train, y_train, n_epoch=12, validation_set=(X_test, y_test) )
  File "/Users/germplus/miniforge3/envs/mlp/lib/python3.8/site-packages/tflearn/models/dnn.py", line 196, in fit
    self.trainer.fit(feed_dicts, val_feed_dicts=val_feed_dicts,
  File "/Users/germplus/miniforge3/envs/mlp/lib/python3.8/site-packages/tflearn/helpers/trainer.py", line 341, in fit
    snapshot = train_op._train(self.training_state.step,
  File "/Users/germplus/miniforge3/envs/mlp/lib/python3.8/site-packages/tflearn/helpers/trainer.py", line 827, in _train
    _, train_summ_str = self.session.run([self.train, self.summ_op],
  File "/Users/germplus/miniforge3/envs/mlp/lib/python3.8/site-packages/tensorflow/python/client/session.py", line 970, in run
    result = self._run(None, fetches, feed_dict, options_ptr,
  File "/Users/germplus/miniforge3/envs/mlp/lib/python3.8/site-packages/tensorflow/python/client/session.py", line 1163, in _run
    np_val = np.asarray(subfeed_val, dtype=subfeed_dtype)
ValueError: setting an array element with a sequence.

Process finished with exit code 1
解决方案

这两个错误的核心原因是标签数据格式不匹配,TFlearn的model.fit()要求标签是二维numpy数组,而你当前的y_train和y_test是numpy数组的列表,不是统一的二维数组。另外还有一处数据引用错误,具体修改步骤如下:

1. 修正数据引用错误

训练代码里的train = create_label.data[:1200]是错误的,你之前加载的数据存在data变量里,应该改成:

train = data[:1200]
test = data[1200:]

2. 转换标签为二维numpy数组

当前y_train和y_test是列表,每个元素是一个长度为3的numpy数组,需要把它们转换成形状为(样本数, 类别数)的二维numpy数组:

y_train = np.array([i[1] for i in train])
y_test = np.array([i[1] for i in test])

3. 可选:图像数据归一化

CNN训练时,将图像像素值归一化到0-1范围能提升训练稳定性,建议对X_train和X_test做归一化:

X_train = X_train / 255.0
X_test = X_test / 255.0

4. 修正后的完整训练代码片段

# split data into train and testing
train = data[:1200]
test = data[1200:]

# x train in 0 index. -1 calculates the x-train number of train 50, 50 is the image shape.
# 1 is grayscale image
X_train = np.array([i[0] for i in train]).reshape(-1, 50, 50, 1)
X_train = X_train / 255.0  # 归一化
print(f'X_train shape is {X_train.shape}')

# y train转换为二维numpy数组
y_train = np.array([i[1] for i in train])

X_test = np.array([i[0] for i in test]).reshape(-1, 50, 50, 1)
X_test = X_test / 255.0  # 归一化
print(f'X_test shape is {X_test.shape}')

y_test = np.array([i[1] for i in test])
print(X_train.ndim)

# 后续模型定义和训练代码不变
convnet = input_data(shape=[50,50,1])
convnet = conv_2d(convnet, 32, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)
convnet = conv_2d(convnet, 64, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)
convnet = conv_2d(convnet, 128, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)
convnet = conv_2d(convnet, 64, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)
convnet = conv_2d(convnet, 32, 5, activation='relu')
convnet = max_pool_2d(convnet, 5)

convnet = fully_connected(convnet, 1024, activation='relu')
convnet = dropout(convnet, 0.8)
convnet = fully_connected(convnet, 3, activation='softmax')
convnet = regression(convnet, optimizer='adam', learning_rate = 0.001, loss='categorical_crossentropy')
model = tflearn.DNN(convnet, tensorboard_verbose=1)
model.fit(X_train, y_train, n_epoch=12, validation_set=(X_test, y_test))

错误原因解释

  • setting an array element with a sequence:因为y_train是列表,每个元素是数组,TensorFlow无法将这种结构转换成统一的张量格式,必须转换成二维numpy数组。
  • only size-1 arrays can be converted to Python scalars:是列表转数组时的衍生错误,本质还是因为输入的数据结构不符合要求。

另外,检查my_label函数是否处理了所有可能的文件名,避免出现未匹配的情况导致返回None,如果有未匹配的样本,会导致标签数据出现异常,建议在函数末尾添加默认返回或者过滤掉这些异常样本。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 13:39:40