多分类任务损失函数选择及输出格式转换技术咨询
文本分类器损失函数相关问题
我在大学作业中需编写简单文本数据集分类器,共5个类别:['0', '1', '2', '3', '4']。参考网络代码后遇到两个问题:
- 使用
categorical_crossentropy时报错:Arguments 'target and 'output' must have the same rank (ndim). Received: target. shape=(None,), output.shape=(None,6) - 使用
sparse_categorical_crossentropy时,模型输出为二维数组。
我的代码如下:
x_train, x_test, y_train, y_test = train_test_split(X_scaled, y_encoded, test_size=0.2, random_state=42) x_train = x_train / 255 x_test = x_test / 255 def b_m(hp): model = Sequential() activation_choice = hp.Choice('activation', values=['relu', 'sigmoid', 'tanh', 'elu', 'selu']) model.add(Dense(units=hp.Int('units_input', min_value=512, max_value=1024, step=32), input_dim=2, activation=activation_choice)) model.add(Dense(units=hp.Int('units_hidden', min_value=128, max_value=600, step=32), activation=activation_choice)) model.add(Dense(5, activation='softmax')) model.compile( optimizer=hp.Choice('optimizer', values=['adam','rmsprop','SGD']), loss='sparse_categorical_crossentropy', #loss='categorical_crossentropy', metrics=['accuracy']) return model tuner = kt.Hyperband(b_m, objective='val_accuracy', max_epochs=10, factor=3, directory='test_dir') stop_early = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=5) tuner.search(x_train, y_train, epochs=50, validation_split=0.2, callbacks=[stop_early]) best_hps=tuner.get_best_hyperparameters(num_trials=1)[0] model = tuner.hypermodel.build(best_hps) history = model.fit(x_train, y_train, epochs=50, validation_split=0.2) val_acc_per_epoch = history.history['val_accuracy'] best_epoch = val_acc_per_epoch.index(max(val_acc_per_epoch)) + 1 hypermodel = tuner.hypermodel.build(best_hps) hypermodel.fit(x_train, y_train, epochs=best_epoch, validation_split=0.2) eval_result = hypermodel.evaluate(x_test, y_test) print("[loss, test]:", eval_result) y_pred = hypermodel.predict(x_test)
我有三个问题:
- 该场景下最适合使用哪种损失函数?
- 若选择
categorical_crossentropy,如何修复报错? - 若选择
sparse_categorical_crossentropy,如何将二维输出转为一维类别数组?
问题解答
1. 最适合的损失函数
两种损失函数都适用,选哪种看标签格式:
- 若标签是整数形式(比如
y_train形状为(None,),每个值是0-4的整数),优先用sparse_categorical_crossentropy,无需额外处理标签,还能节省内存。 - 若标签是one-hot编码形式(比如
y_train形状为(None,5),每个样本对应5维数组,仅对应类别位置为1),用categorical_crossentropy。
你的场景中y_encoded是整数形式(报错显示target.shape=(None,)),所以sparse_categorical_crossentropy更合适,代码改动最少。
2. 修复categorical_crossentropy的报错
报错根源是目标标签和模型输出维度不匹配:模型输出是(None,5)的二维数组(5类softmax输出),但标签是(None,)的一维整数数组。需要把标签转为one-hot编码:
在分割数据集后,对标签做如下处理:
from tensorflow.keras.utils import to_categorical # 假设y_encoded是0-4的整数数组 y_train_onehot = to_categorical(y_train, num_classes=5) y_test_onehot = to_categorical(y_test, num_classes=5)
然后修改模型编译和训练代码:
# 模型编译时启用categorical_crossentropy model.compile( optimizer=hp.Choice('optimizer', values=['adam','rmsprop','SGD']), loss='categorical_crossentropy', metrics=['accuracy']) # 训练时传入one-hot后的标签 tuner.search(x_train, y_train_onehot, epochs=50, validation_split=0.2, callbacks=[stop_early]) model.fit(x_train, y_train_onehot, epochs=50, validation_split=0.2) hypermodel.fit(x_train, y_train_onehot, epochs=best_epoch, validation_split=0.2) eval_result = hypermodel.evaluate(x_test, y_test_onehot)
3. 把sparse_categorical_crossentropy的二维输出转一维类别数组
模型softmax输出的是每个类别的概率(形状(样本数,5)),取每个样本概率最大的索引即可得到一维类别数组:
y_pred = hypermodel.predict(x_test) # 取每个样本概率最大的类别索引 y_pred_classes = y_pred.argmax(axis=1)
y_pred_classes形状为(样本数,),每个值对应0-4的类别编号,和y_test格式一致,可直接用于计算准确率、混淆矩阵等指标。
内容的提问来源于stack exchange,提问作者randomname
相关产品推荐
相关产品推荐

