loss_cdq.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # time: 2023/5/8 13:15
  4. # file: loss.py.py
  5. # author: David
  6. # company: shenyang JY
  7. import tensorflow as tf
  8. tf.compat.v1.set_random_seed(1234)
  9. def rmse(y_true, y_pred):
  10. return tf.sqrt(tf.reduce_mean(tf.square(y_pred - y_true)))
  11. class SouthLoss(tf.keras.losses.Loss):
  12. def __init__(self, opt, name='south_loss'):
  13. """
  14. 南网新规则损失函数
  15. :param cap:装机容量
  16. """
  17. super(SouthLoss, self).__init__(name=name)
  18. self.cap = opt.cap*0.2 # 没有归一化cap,必须要先进行归一化
  19. self.opt = opt
  20. # self.cap01 = opt.cap*0.1
  21. def call(self, y_true, y_predict):
  22. """
  23. 自动调用
  24. :param y_true: 标签
  25. :param y_predict: 预测
  26. :return: 损失值
  27. """
  28. # 计算实际和预测的差值
  29. # y_true = y_true * self.opt.std['C_REAL_VALUE'] + self.opt.mean['C_REAL_VALUE']
  30. # y_predict = y_predict * self.opt.std['C_REAL_VALUE'] + self.opt.mean['C_REAL_VALUE']
  31. y_true = y_true[:, 15]
  32. y_predict = y_predict[:, 15]
  33. diff = y_true - y_predict
  34. logistic_values = tf.sigmoid(10000 * (y_true - self.cap))
  35. base = logistic_values * y_true + (1-logistic_values)*self.cap
  36. loss = K.square(diff/base)
  37. # loss = K.mean(loss, axis=-1)
  38. return loss
  39. def call2(self, y_true, y_predict):
  40. y_true = y_true * self.opt.std['C_REAL_VALUE'] + self.opt.mean['C_REAL_VALUE']
  41. y_predict = y_predict * self.opt.std['C_REAL_VALUE'] + self.opt.mean['C_REAL_VALUE']
  42. y_true = y_true[:, 15]
  43. y_predict = y_predict[:, 15]
  44. diff = y_true - y_predict
  45. logistic_values = tf.sigmoid(10000 * (y_true - self.cap))
  46. base = logistic_values * y_true + (1 - logistic_values) * self.cap
  47. loss = K.square(diff / base)
  48. mask_logical = tf.logical_and(tf.greater(y_true, self.cap01), tf.greater(y_predict, self.cap01))
  49. count = tf.reduce_sum(tf.cast(mask_logical, tf.float32), axis=-1)
  50. safe_count = tf.maximum(count, 1)
  51. # reduce_sum_loss = tf.reduce_sum(loss, axis=-1)
  52. mean_loss = loss / safe_count
  53. return mean_loss
  54. def call1(self, y_true, y_predict):
  55. y_true = y_true * self.opt.std['C_REAL_VALUE'] + self.opt.mean['C_REAL_VALUE']
  56. y_predict = y_predict * self.opt.std['C_REAL_VALUE'] + self.opt.mean['C_REAL_VALUE']
  57. base = tf.where(y_true > self.cap, y_true, tf.ones_like(y_true)*self.cap)
  58. loss = (y_true - y_predict) / base
  59. squared_loss = tf.square(loss)
  60. mean_squared_loss = tf.reduce_mean(squared_loss, axis=[1])
  61. return mean_squared_loss
  62. class NorthEastLoss(tf.keras.losses.Loss):
  63. def __init__(self, opt, name='northeast_loss'):
  64. """
  65. 东北新规则超短期损失函数
  66. """
  67. super(NorthEastLoss, self).__init__(name=name)
  68. self.opt = opt
  69. self.cap = round(opt.cap*0.1, 2)
  70. def call(self, y_true, y_predict):
  71. # 这里我们添加了一个小的 epsilon 值来避免除以 0
  72. # y_true = y_true * self.opt.std['C_REAL_VALUE'] + self.opt.mean['C_REAL_VALUE']
  73. # y_predict = y_predict * self.opt.std['C_REAL_VALUE'] + self.opt.mean['C_REAL_VALUE']
  74. mask_logical = tf.logical_and(tf.greater(y_true, self.cap), tf.greater(y_predict, self.cap))
  75. # mask = tf.cast(~mask_logical, tf.float32)
  76. # y_true = y_true * (1 - mask) + 0 * mask
  77. # y_predict = y_predict * (1 - mask) + 0 * mask
  78. epsilon = tf.keras.backend.epsilon()
  79. y_predict_safe = y_predict + epsilon
  80. # 计算 (y_true - y_predict) / y_predict_safe
  81. difference_over_predict = tf.abs(y_predict - y_true) / tf.abs(y_predict_safe)
  82. # 将结果中大于等于 1 的部分置为 1,剩下的保留原值
  83. masked_difference = tf.where(difference_over_predict >= 1, tf.ones_like(difference_over_predict)*1, difference_over_predict) #tf.where的操作是逐元素的,并且它不会改变张量中元素的数学性质(如可微性、可导性)。
  84. # 这里我们先沿着特征维度求和,但你也可以选择平均(使用 tf.reduce_mean 而不是 tf.reduce_sum)
  85. count = tf.reduce_sum(tf.cast(mask_logical, tf.float32), axis=-1)
  86. sum_diff = tf.reduce_sum(masked_difference, axis=-1)
  87. # mean_loss = tf.reduce_mean(masked_difference, axis=[1])
  88. safe_count = tf.maximum(count, 1)
  89. mean = sum_diff / safe_count
  90. mean1 = tf.reduce_sum(masked_difference, axis=-1)
  91. return mean
  92. class NorthWestLoss(tf.keras.losses.Loss):
  93. def __init__(self, name='northwest_loss'):
  94. """
  95. 东北新规则超短期损失函数
  96. """
  97. super(NorthWestLoss, self).__init__(name=name)
  98. def call(self, y_true, y_pred):
  99. # 保证预测值和真实值是浮点数
  100. y_pred = tf.cast(y_pred, tf.float32)
  101. y_true = tf.cast(y_true, tf.float32)
  102. # 避免除零错误
  103. epsilon = 1e-8
  104. y_pred_adjusted = y_pred + epsilon
  105. y_true_adjusted = y_true + epsilon
  106. # 计算 |Pr - Pn|
  107. abs_diff = tf.abs(y_pred - y_true)
  108. # 计算 |Pr - Pn| 的总和
  109. sum_abs_diff = tf.reduce_sum(abs_diff)
  110. # 计算每个差值的权重 |Pr - Pn| / sum(|Pr - Pn|)
  111. weights = abs_diff / (sum_abs_diff + epsilon) # 添加 epsilon 避免除零
  112. # 计算 |Pr/(Pr + Pn) - 0.5|
  113. ratios = tf.abs((y_pred_adjusted / (y_pred_adjusted + y_true_adjusted)) - 0.5)
  114. # 计算最终的损失值
  115. loss = 1.0 - 2.0 * tf.reduce_sum(ratios * weights)
  116. return loss