CNN训练自定义图像时SparseCategoricalCrossentropy类型错误
问题
用CNN训练自定义图像,已将class_mode设为sparse,选用SparseCategoricalCrossentropy损失函数,但训练时出现「无法将元素转换为张量」的TypeError,更换其他损失函数问题仍存在,怀疑数据格式有误,附上相关代码及报错栈。
数据生成器与网络代码
train_datagen = ImageDataGenerator( rescale=1./255, width_shift_range=.05, height_shift_range=.05, zoom_range=0.05, validation_split=0.3, horizontal_flip=True, vertical_flip=True, fill_mode="constant", cval=0) test_datagen = ImageDataGenerator( rescale=1./255) #data augmentation train_ds = train_datagen.flow_from_directory( train_data_dir, shuffle=True, target_size=(img_width, img_height), batch_size=batch_size, class_mode='sparse', subset='training'); cnn = Sequential() cnn.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(img_width,img_height,3))) cnn.add(BatchNormalization()) cnn.add(Conv2D(32, kernel_size=(3, 3), activation='relu')) cnn.add(BatchNormalization()) cnn.add(MaxPooling2D(pool_size=(2, 2))) cnn.add(Dropout(0.2)) cnn.add(Conv2D(64, kernel_size=(3, 3), activation='relu')) cnn.add(BatchNormalization()) cnn.add(Flatten()) cnn.add(Dense(64, activation='relu')) cnn.add(Dense(22, activation='softmax')) cnn.compile(loss=keras.losses.SparseCategoricalCrossentropy, optimizer="Adam", metrics=['accuracy'])
完整报错栈
-------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In [24], line 111 106 cnn.compile(loss=keras.losses.SparseCategoricalCrossentropy, 107 optimizer="Adam", 108 metrics=['accuracy']) 110 epochs=20 --> 111 history = cnn.fit( 112 train_ds, 113 validation_data=valid_ds, 114 steps_per_epoch=math.ceil(len(train_ds) / batch_size), 115 epochs=epochs) 117 plt.plot(history.history['loss'], label='train') 118 plt.plot(history.history['val_loss'], label='validation') File ~\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\utils\traceback_utils.py:70, in filter_traceback.<locals>.error_handler(*args, **kwargs) 67 filtered_tb = _process_traceback_frames(e.__traceback__) 68 # To get the full stack trace, call: 69 # `tf.debugging.disable_traceback_filtering()` ---> 70 raise e.with_traceback(filtered_tb) from None 71 finally: 72 del filtered_tb File ~\AppData\Local\Temp\__autograph_generated_fileswqeb6ya.py:15, in outer_factory.<locals>.inner_factory.<locals>.tf__train_function(iterator) 13 try: 14 do_return = True ---> 15 retval_ = ag__.converted_call(ag__.ld(step_function), (ag__.ld(self), ag__.ld(iterator)), None, fscope) 16 except: 17 do_return = False TypeError: in user code: File "C:\Users\maiaz\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\engine\training.py", line 1160, in train_function * return step_function(self, iterator) File "C:\Users\maiaz\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\engine\training.py", line 1146, in step_function ** outputs = model.distribute_strategy.run(run_step, args=(data,)) File "C:\Users\maiaz\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\engine\training.py", line 1135, in run_step ** outputs = model.train_step(data) File "C:\Users\maiaz\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\engine\training.py", line 994, in train_step loss = self.compute_loss(x, y, y_pred, sample_weight) File "C:\Users\maiaz\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\engine\training.py", line 1052, in compute_loss return self.compiled_loss( File "C:\Users\maiaz\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\engine\compile_utils.py", line 265, in __call__ loss_value = loss_obj(y_t, y_p, sample_weight=sw) File "C:\Users\maiaz\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\losses.py", line 158, in __call__ return losses_utils.compute_weighted_loss( File "C:\Users\maiaz\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\utils\losses_utils.py", line 328, in compute_weighted_loss losses = tf.convert_to_tensor(losses) TypeError: Failed to convert elements of <keras.losses.SparseCategoricalCrossentropy object at 0x0000017523557AC0> to Tensor. Consider casting elements to a supported type. See https://www.tensorflow.org/api_docs/python/tf/dtypes for supported TF dtypes.
解决方案
核心错误原因
你在compile方法中传入损失函数时,直接使用了keras.losses.SparseCategoricalCrossentropy(类本身),而非实例化后的对象。Keras要求接收损失函数的实例,而非类引用,这才是导致张量转换失败的根本原因,和数据格式无关。
修正代码
将损失函数改为实例化形式:
cnn.compile(loss=keras.losses.SparseCategoricalCrossentropy(), # 添加括号完成实例化 optimizer="Adam", metrics=['accuracy'])
或者使用更简洁的字符串形式(Keras会自动对应到损失函数实例):
cnn.compile(loss='sparse_categorical_crossentropy', optimizer="Adam", metrics=['accuracy'])
额外检查点
- 确认
valid_ds的创建参数和train_ds保持一致,同样设置class_mode='sparse',避免验证集标签格式不匹配 steps_per_epoch计算有误:len(train_ds)本身就是训练集的批次数量,无需再除以batch_size,直接使用steps_per_epoch=len(train_ds)即可,否则会导致每个epoch重复训练多轮
内容的提问来源于stack exchange,提问作者LargeMuscle2
相关产品推荐
相关产品推荐

