1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- # @FileName :losses_cash.py
- # @Time :2025/6/11 15:31
- # @Author :David
- # @Company: shenyang JY
- import tensorflow as tf
- from tensorflow.keras.losses import Loss
- from typeguard import typechecked
- tf.compat.v1.set_random_seed(1234)
- """
- 两个细则结合现货交易损失函数
- 总体原则:
- 抑制负偏差,控制负偏差
- """
- class SouthLossCash(Loss):
- """南网新规则损失函数(支持完整序列化)"""
- @typechecked
- def __init__(self,
- cap: float,
- name: str = "south_cash_loss",
- penalty_coeff: float = 1.0, # 新增惩罚系数参数
- reduction: str = "sum_over_batch_size"):
- # if not 0 <= cap <= 1:
- # raise ValueError("cap 必须为归一化后的值且位于 [0,1] 区间")
- super().__init__(name=name, reduction=reduction)
- # 序列化相关参数
- self._raw_cap = cap
- self.penalty_coeff = penalty_coeff # 惩罚项系数
- # 实际计算值(注意:这里的0.2是原代码中的缩放逻辑,保持不动)
- self.cap = tf.constant(cap * 0.2, dtype=tf.float32)
- def get_config(self):
- config = super().get_config()
- config.update({
- "cap": self._raw_cap,
- "penalty_coeff": self.penalty_coeff, # 序列化新参数
- "name": self.name,
- "reduction": self.reduction
- })
- return config
- @classmethod
- def from_config(cls, config):
- return cls(
- cap=config["cap"],
- penalty_coeff=config.get("penalty_coeff", 1.0), # 带默认值以兼容旧配置
- name=config["name"],
- reduction=config["reduction"]
- )
- def call(self, y_true, y_pred):
- # 数值稳定化处理
- y_true = tf.cast(y_true, tf.float32)
- y_pred = tf.cast(y_pred, tf.float32)
- diff = y_true - y_pred # 负值表示预测偏高,正值表示预测偏低
- delta = y_true - self.cap
- # 基值计算逻辑(保持原样)
- logistic_input = tf.clip_by_value(10000.0 * delta, -50.0, 50.0)
- logistic_values = tf.sigmoid(logistic_input)
- base = logistic_values * y_true + (1 - logistic_values) * self.cap
- safe_base = tf.where(tf.equal(base, 0.0), 1e-7, base)
- # 原基础损失
- base_loss = tf.reduce_mean(tf.square(diff / safe_base), axis=-1)
- ############### 新增惩罚项部分 ###############
- # 计算负偏差惩罚(预测值低于真实值时进行惩罚)
- negative_bias = tf.maximum(diff, 0.0) # 获取负偏差部分的绝对值
- penalty = self.penalty_coeff * tf.reduce_mean(negative_bias, axis=-1)
- # 组合最终损失(可以尝试不同权重)
- total_loss = base_loss + penalty
- return total_loss
- if __name__ == "__main__":
- run_code = 0
|