Keras使用CategoryEncoding处理二分类特征报错及标签预处理问题
问题解答
1. 报错原因与token含义解释
报错的直接原因:CategoryEncoding层的one_hot输出模式只支持最高2维的输出,你输入的张量shape是(None, 50)(None是batch维度,50是特征数),如果对每个特征值单独做one-hot编码,输出shape会变成(None, 50, 2),属于3维张量,不符合要求因此报错。
该层语境下的token指分类特征所有可能取值的唯一编号,你的所有特征都是是/否二值,对应0和1两个编号,所以num_tokens应该设为2,你之前填100属于错误配置。
额外提示:你的50个输入特征本身已经是0/1的数值化二值特征,完全不需要额外做独热编码,直接输入后续网络即可,是性价比最高的方案。
2. 修正后的基础代码
注意原有代码还有一处逻辑错误:二分类单输出场景不能用softmax激活,softmax对单节点输出会固定返回1,需要替换为sigmoid。
model = Sequential([ tf.keras.Input(shape = (50,)), tf.keras.layers.LayerNormalization(), tf.keras.layers.Dense(1024, activation='relu'), tf.keras.layers.Dense(32, activation='relu'), tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(1, activation='sigmoid') ])
模型编译时使用二进制交叉熵损失即可:
model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(), metrics=['accuracy'])
3. 必须做独热编码的实现方案
如果业务要求必须对每个二值特征做独热编码,可以用tf.one_hot配合Flatten层处理维度问题:
model = Sequential([ tf.keras.Input(shape = (50,), dtype=tf.int32), # 每个0/1特征值转为长度2的独热向量,输出shape为(None, 50, 2) tf.keras.layers.Lambda(lambda x: tf.one_hot(x, depth=2)), # 压平为二维张量(None, 100),适配后续全连接层要求 tf.keras.layers.Flatten(), tf.keras.layers.LayerNormalization(), tf.keras.layers.Dense(1024, activation='relu'), tf.keras.layers.Dense(32, activation='relu'), tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(1, activation='sigmoid') ])
4. 标签预处理的TensorFlow原生实现
二分类是/否标签不需要用pd.get_dummies,TensorFlow有两种常用原生处理方案:
- 如果你用上述单输出
sigmoid配置,直接喂原始0/1标签即可,不需要额外处理 - 如果你要做多输出的独热标签,使用
tf.keras.utils.to_categorical(y, num_classes=2)即可直接转换,对应输出层改为Dense(2, activation='softmax'),损失函数用CategoricalCrossentropy()
内容的提问来源于stack exchange,提问作者zeromodz15
相关产品推荐
相关产品推荐

