Keras中自定义保留两位小数的Sigmoid激活函数报错求助
解决Keras自定义激活函数的AttributeError问题
错误原因分析
你遇到的AttributeError: 'Tensor' object has no attribute 'rint'是因为混用了NumPy和Keras后端的张量操作:
K.sigmoid(x)返回的是Keras后端(比如TensorFlow)的Tensor对象,而非NumPy数组np.around()是NumPy专属函数,只能处理NumPy数组,无法识别Tensor对象的操作逻辑,因此触发了这个错误
正确的自定义激活函数实现
要处理Keras的张量,必须使用Keras后端(keras.backend)提供的函数来实现四舍五入逻辑。我们可以通过「乘以100 → 四舍五入 → 除以100」的方式实现保留两位小数的效果:
from keras import backend as K from keras.layers import Activation from keras.utils.generic_utils import get_custom_objects def mySigmoid(x): # 先计算标准sigmoid输出 sigmoid_output = K.sigmoid(x) # 用后端函数实现保留两位小数的四舍五入 return K.round(sigmoid_output * 100) / 100 # 注册自定义激活函数 get_custom_objects().update({'mySigmoid': Activation(mySigmoid)})
重要注意事项:梯度与训练稳定性
虽然上面的代码能解决报错问题,但必须提醒你:四舍五入是不可导操作,将其放在激活函数中会破坏反向传播的梯度连续性,可能导致模型训练时梯度消失,难以收敛。
针对你的门窗开启状态预测任务,更合理的做法是:
- 训练阶段保持最后一层使用普通
sigmoid激活,保证梯度正常传递 - 在模型预测完成后,再对输出结果做四舍五入处理
示例代码如下:
# 训练时的模型(最后一层用普通sigmoid) model = Sequential() model.add(Dense(40, input_shape=(13, ), kernel_initializer='random_normal', activation='tanh')) model.add(Dense(40, activation='tanh')) model.add(Dense(40, activation='tanh')) model.add(Dense(40, activation='tanh')) model.add(Dense(40, activation='relu')) model.add(Dense(10, activation='sigmoid')) # 用普通sigmoid保证训练稳定性 # 编译、训练模型(沿用你的原有配置) sgd = optimizers.SGD(lr=0.1, decay=1e-5, momentum=0.3, nesterov=True) model.compile(optimizer=sgd, loss='mean_squared_error', metrics=['mae', 'acc']) model.fit(Input_np, Output_Norm, validation_split=0.3, epochs=35, batch_size=100) # 预测后处理成两位小数 predictions = model.predict(Input_np) rounded_predictions = np.around(predictions, decimals=2)
这种方式既满足了输出保留两位小数的需求,又能保证模型训练的稳定性,是更推荐的方案。
内容的提问来源于stack exchange,提问作者fsofelipe
相关产品推荐
相关产品推荐

