فهرست منبع

Merge branch 'dev_david' of anweiguo/algorithm_platform into dev_awg

liudawei 2 هفته پیش
والد
کامیت
1f674cd1bd
3فایلهای تغییر یافته به همراه114 افزوده شده و 14 حذف شده
  1. 5 3
      models_processing/model_tf/losses.py
  2. 83 0
      models_processing/model_tf/losses_cash.py
  3. 26 11
      models_processing/model_tf/tf_lstm.py

+ 5 - 3
models_processing/model_tf/losses.py

@@ -6,6 +6,7 @@
 # company: shenyang JY
 import tensorflow as tf
 from tensorflow.keras.losses import Loss
+from models_processing.model_tf.losses_cash import *
 from typeguard import typechecked
 tf.compat.v1.set_random_seed(1234)
 
@@ -115,8 +116,8 @@ class SouthLoss(Loss):
                  name: str = "south_loss",
                  reduction: str = "sum_over_batch_size"):
         # 参数校验
-        if not 0 <= cap <= 1:
-            raise ValueError("cap 必须为归一化后的值且位于 [0,1] 区间")
+        # if not 0 <= cap <= 1:
+        #     raise ValueError("cap 必须为归一化后的值且位于 [0,1] 区间")
 
         super().__init__(name=name, reduction=reduction)
 
@@ -228,6 +229,7 @@ class NorthChina(Loss):
 region_loss_d = {
     'northeast': lambda region: RMSE(region),
     'south': lambda cap, region: SouthLoss(cap, region),
+    'south_cash': lambda cap, region: SouthLossCash(cap, region),
     'zone': lambda region: MSE_ZONE(region), # 分区建模损失:MSE + 分区总和一致性约束
     'northchina': lambda region: NorthChina(region) #华北损失函数
 }
@@ -239,7 +241,7 @@ def region_loss(opt):
     # 判断处理类型并执行
     if callable(handler):
         # 如果是lambda或函数,直接调用
-        if opt.region == "south":  # 需要额外参数的地区
+        if str(opt.region).startswith("south"):  # 需要额外参数的地区
             return handler(opt.cap, opt.region)
         else:
             return handler(opt.region)

+ 83 - 0
models_processing/model_tf/losses_cash.py

@@ -0,0 +1,83 @@
+#!/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

+ 26 - 11
models_processing/model_tf/tf_lstm.py

@@ -4,7 +4,15 @@
 # @Time      :2025/2/12 14:03
 # @Author    :David
 # @Company: shenyang JY
-
+# 固定NumPy随机种子
+import os
+os.environ['PYTHONHASHSEED'] = '42'
+import numpy as np
+np.random.seed(42)
+# 固定TensorFlow随机种子
+import tensorflow as tf
+tf.random.set_seed(42)
+from tensorflow.keras.initializers import glorot_uniform, orthogonal
 from tensorflow.keras.layers import Input, Dense, LSTM, concatenate, Conv1D, Conv2D, MaxPooling1D, Reshape, Flatten
 from tensorflow.keras.models import Model, load_model
 from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, TensorBoard, ReduceLROnPlateau
@@ -12,11 +20,10 @@ from tensorflow.keras import optimizers, regularizers
 from models_processing.model_tf.losses import region_loss
 import numpy as np
 from common.database_dml import *
-from models_processing.model_tf.settings import set_deterministic
 from threading import Lock
 import argparse
 model_lock = Lock()
-set_deterministic(42)
+
 
 class TSHandler(object):
     def __init__(self, logger, args):
@@ -43,13 +50,17 @@ class TSHandler(object):
         l2_reg = regularizers.l2(opt.Model['lambda_value_2'])
         nwp_input = Input(shape=(opt.Model['time_step']*time_series, opt.Model['input_size']), name='nwp')
 
-        con1 = Conv1D(filters=64, kernel_size=5, strides=1, padding='valid', activation='relu', kernel_regularizer=l2_reg)(nwp_input)
+        con1 = Conv1D(filters=64, kernel_size=5, strides=1, padding='valid', activation='relu', kernel_regularizer=l2_reg, kernel_initializer=glorot_uniform(seed=42))(nwp_input)
         con1_p = MaxPooling1D(pool_size=5, strides=1, padding='valid', data_format='channels_last')(con1)
-        nwp_lstm = LSTM(units=opt.Model['hidden_size'], return_sequences=False, kernel_regularizer=l2_reg)(con1_p)
+        nwp_lstm = LSTM(units=opt.Model['hidden_size'], return_sequences=False, kernel_regularizer=l2_reg, kernel_initializer=glorot_uniform(seed=43),
+        recurrent_initializer=orthogonal(seed=44),  # LSTM特有的初始化
+        bias_initializer='zeros')(con1_p)
         if lstm_type == 2:
-            output = Dense(opt.Model['time_step'], name='cdq_output')(nwp_lstm)
+            output = Dense(opt.Model['time_step'], name='cdq_output', kernel_initializer=glorot_uniform(seed=45),
+            bias_initializer='zeros')(nwp_lstm)
         else:
-            output = Dense(opt.Model['time_step']*time_series, name='cdq_output')(nwp_lstm)
+            output = Dense(opt.Model['time_step']*time_series, name='cdq_output', kernel_initializer=glorot_uniform(seed=45),
+            bias_initializer='zeros')(nwp_lstm)
 
         model = Model(nwp_input, output)
         adam = optimizers.Adam(learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-7, amsgrad=True)
@@ -64,13 +75,17 @@ class TSHandler(object):
         nwp_input = Input(shape=(opt.Model['time_step'] * time_series, opt.Model['input_size']), name='nwp')
 
         con1 = Conv1D(filters=64, kernel_size=1, strides=1, padding='valid', activation='relu',
-                      kernel_regularizer=l2_reg)(nwp_input)
+                      kernel_regularizer=l2_reg, kernel_initializer=glorot_uniform(seed=42))(nwp_input)
         con1_p = MaxPooling1D(pool_size=1, strides=1, padding='valid', data_format='channels_last')(con1)
-        nwp_lstm = LSTM(units=opt.Model['hidden_size'], return_sequences=False, kernel_regularizer=l2_reg)(con1_p)
+        nwp_lstm = LSTM(units=opt.Model['hidden_size'], return_sequences=False, kernel_regularizer=l2_reg, kernel_initializer=glorot_uniform(seed=43),
+        recurrent_initializer=orthogonal(seed=44),  # LSTM特有的初始化
+        bias_initializer='zeros')(con1_p)
         if lstm_type == 2:
-            output = Dense(opt.Model['time_step'], name='cdq_output')(nwp_lstm)
+            output = Dense(opt.Model['time_step'], name='cdq_output', kernel_initializer=glorot_uniform(seed=45),
+            bias_initializer='zeros')(nwp_lstm)
         else:
-            output = Dense(opt.Model['time_step'] * time_series, name='cdq_output')(nwp_lstm)
+            output = Dense(opt.Model['time_step'] * time_series, name='cdq_output', kernel_initializer=glorot_uniform(seed=45),
+            bias_initializer='zeros')(nwp_lstm)
 
         model = Model(nwp_input, output)
         adam = optimizers.Adam(learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-7, amsgrad=True)