formula.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # @FileName :formula.py
  4. # @Time :2024/12/4 08:47
  5. # @Author :David
  6. # @Company: shenyang JY
  7. import numpy as np
  8. import pandas as pd
  9. '''
  10. 准确率formula.py模块使用手顺:
  11. ① Assessment: 考核类 Formular: 准确率计算类
  12. ② 初始化并传参:初始化考核类,传递opt命名空间 (包括cap装机容量)、logger日志对象(也可以用print代替)
  13. ③ 调用方法:按照考核类标注的方法和参数含义,进行传参和调用,获得日期平均准确率和考核分数
  14. ----------
  15. 注意:
  16. regulations > solar/wind []列表含义(按顺序):短期准确率考核线,超短期准确率考核线,短期考核系数,超短期考核系数
  17. 西北,东北地区短期采用考核积分电量和偏差带进行考核,这里不进行计算
  18. '''
  19. class Assessment(object):
  20. def __init__(self, opt, logger):
  21. self.logger = logger
  22. self.formula = Formulas(opt)
  23. self.regulations = {
  24. "south": {
  25. 'func': self.formula.calculate_acc_south,
  26. 'solar': [65, 70, 1*0.2, 1*0.2],
  27. 'wind': [60, 65, 0.2*2, 0.2*2],
  28. 'check': True
  29. },
  30. "east":{
  31. 'func': self.formula.calculate_acc,
  32. 'solar': ['', 97, '', 0.09*1],
  33. 'wind': ['', 96, '', 0.09*1],
  34. 'check': False
  35. },
  36. "northeast":{
  37. 'func': self.formula.calculate_acc_northeast,
  38. 'solar': ['', 85, '', 0.02*0.1],
  39. 'wind': ['', 80, '', 0.02*0.1]
  40. },
  41. "northwest":{
  42. 'func': self.formula.calculate_acc_northwest,
  43. 'solar': ['', 75, '', 0.015*0.1*0.5],
  44. 'wind': ['', 75, '', 0.015*0.1*0.5]
  45. }
  46. }
  47. def electricity_solar_cdq(self, df, province, predict, label='C_REAL_VALUE', output=True):
  48. df['C_TIME'] = pd.to_datetime(df['C_TIME'])
  49. df['C_TIME_DAY'] = df['C_TIME'].dt.strftime("%Y-%m-%d")
  50. dfs = df.groupby('C_TIME_DAY')
  51. limit = self.regulations[province]['solar'][1]
  52. alpha = self.regulations[province]['solar'][3]
  53. sum_score, sum_acc = 0, 0
  54. for dt, data in dfs:
  55. acc = self.regulations[province]['func'](data[predict].values, data[label].values)
  56. score = (limit - acc) * alpha if acc < limit else 0
  57. sum_acc += acc
  58. sum_score += score
  59. if output:
  60. self.logger.info("预测名称:{},日期:{},区域:{},超短期的准确率:{:.4f},考核分数:{:.4f}".format(predict, str(dt), province, acc, score))
  61. return round(sum_acc/len(dfs), 2), round(sum_score/len(dfs), 2)
  62. def electricity_wind_cdq(self, df, province, predict, label='C_REAL_VALUE'):
  63. df['C_TIME'] = pd.to_datetime(df['C_TIME'])
  64. df['C_TIME_DAY'] = df['C_TIME'].dt.strftime("%Y-%m-%d")
  65. dfs = df.groupby('C_TIME_DAY')
  66. limit = self.regulations[province]['solar'][1]
  67. alpha = self.regulations[province]['solar'][3]
  68. sum_score, sum_acc = 0, 0
  69. for dt, data in dfs:
  70. acc = self.regulations[province]['func'](data[predict].values, data[label].values)
  71. score = (limit - acc) * alpha if acc < limit else 0
  72. sum_acc += acc
  73. sum_score += score
  74. self.logger.info(
  75. "日期:{},区域:{},超短期的准确率:{:.4f},考核分数:{:.4f}".format(str(dt), province, acc, score))
  76. return round(sum_acc / len(dfs), 2), round(sum_score / len(dfs), 2)
  77. class Formulas(object):
  78. def __init__(self, opt):
  79. self.opt = opt
  80. def calculate_acc(self, label_data, predict_data):
  81. loss = np.sum((label_data - predict_data) ** 2) / len(label_data) # mse
  82. loss_sqrt = np.sqrt(loss) # rmse
  83. loss_acc = (1 - loss_sqrt / self.opt.cap) * 100
  84. return loss_acc
  85. def calculate_acc_south(self, label_data, predict_data):
  86. cap = 0.1 * self.opt.cap
  87. mask = (label_data < cap) & (predict_data < cap)
  88. label_data = label_data[~mask]
  89. predict_data = predict_data[~mask]
  90. diff = label_data - predict_data
  91. base = np.where(label_data < self.opt.cap * 0.2, self.opt.cap * 0.2, label_data)
  92. acc = np.sum((diff / base) ** 2) / len(diff)
  93. acc = (1 - np.sqrt(acc)) * 100
  94. return acc
  95. def calculate_acc_northwest(self, label_data, predict_data):
  96. cap = 0.03 * self.opt.cap
  97. mask = (label_data < cap) & (predict_data < cap)
  98. label_data = label_data[~mask]
  99. predict_data = predict_data[~mask]
  100. diff = np.abs(label_data - predict_data)
  101. base1 = label_data + predict_data + 1e-9
  102. base2 = np.sum(diff) + 1e-9
  103. acc = (1 - 2 * np.sum(np.abs(label_data / base1 - 0.5) * diff / base2)) * 100
  104. return acc
  105. def calculate_acc_northeast(self, label_data, predict_data):
  106. cap = 0.1 * self.opt.cap
  107. mask = (label_data < cap) & (predict_data < cap)
  108. label_data = label_data[~mask]
  109. predict_data = predict_data[~mask]
  110. diff = np.abs(predict_data - label_data)
  111. deviation = diff / np.abs(predict_data + 1e-9)
  112. acc = np.where(deviation >= 1, 1, deviation)
  113. acc = 1 - np.mean(acc)
  114. return acc
  115. if __name__ == '__main__':
  116. from config import myargparse
  117. args = myargparse(discription="场站端配置", add_help=False)
  118. opt = args.parse_args_and_yaml()
  119. formula = Formulas(opt)
  120. test = pd.read_csv('./data/测试集16.csv')
  121. test = test.iloc[:96, :]
  122. acc = formula.calculate_acc_northeast(test['C_REAL_VALUE'], test['C_FP_VALUE'])
  123. print(acc)