如何使用TensorFlow子类化方法完成二分类任务并解决预测异常问题
异常原因与解决方案
核心原因
- 你当前模型输出维度和预期不符:最后一层定义为
layers.Dense(2, activation = 'sigmoid'),调用predict得到的prediction是形状为(样本数, 2)的二维数组,每一行对应样本属于类别0、类别1的两个概率值,你直接将二维数组传入仅定义了1列的DataFrame,自然无法得到预期结果。 - 额外存在训练逻辑不匹配的问题:你的标签
Y_train_nur是0/1格式的稀疏整数标签,但你编译时使用的损失函数CategoricalCrossentropy要求输入独热编码格式的标签,训练时损失计算本身就存在错误。
修复方案
方案1:保留当前2输出神经元的写法
- 先修正损失函数配置,将编译时的损失替换为适配稀疏整数标签的
SparseCategoricalCrossentropy:
ChurnClassifier.compile(optimizer = 'adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(), metrics = ['accuracy'])
- 预测后取概率最大的下标作为类别标签,再转换为DataFrame:
# 取每行概率最高的下标作为预测类别 pred_class = np.argmax(prediction, axis=1) pred_y = pd.DataFrame(pred_class, columns=['pred_y'])
方案2:切换为更适配二分类的写法
二分类任务更推荐使用单神经元输出,可简化后续处理逻辑:
- 修改模型最后一层、损失函数配置:
class ChurnClassifier(Model): def __init__(self): super(ChurnClassifier, self).__init__() self.layer1 = layers.Dense(20, input_dim = 20, activation = 'relu') self.layer2 = layers.Dense(41, activation = 'relu') self.layer3 = layers.Dense(83, activation = 'relu') # 改为单神经元输出,用sigmoid激活输出0-1之间的概率 self.layer4 = layers.Dense(1, activation = 'sigmoid') def call(self, inputs): x = self.layer1(inputs) x = self.layer2(x) x = self.layer3(x) return self.layer4(x) ChurnClassifier = ChurnClassifier() # 损失换为二分类交叉熵 ChurnClassifier.compile(optimizer = 'adam', loss=tf.keras.losses.BinaryCrossentropy(), metrics = ['accuracy'])
- 预测后按阈值(通常取0.5)转换为0/1类别,再生成DataFrame:
prediction = ChurnClassifier.predict(X_val_nur) # 概率大于0.5判定为类别1,否则为类别0 pred_class = (prediction > 0.5).astype(int) pred_y = pd.DataFrame(pred_class, columns=['pred_y'])
内容的提问来源于stack exchange,提问作者Sourodip Kundu
相关产品推荐
相关产品推荐

