formula.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # time: 2024/9/23 15:27
  4. # file: formula.py
  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. "south129":{
  25. 'func': self.formula.calculate_acc,
  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. "south": {
  31. 'func': self.formula.calculate_acc_south,
  32. 'solar': [65, 70, 1*0.2, 1*0.2],
  33. 'wind': [60, 65, 0.2*2, 0.2*2],
  34. 'check': True
  35. },
  36. "east":{
  37. 'func': self.formula.calculate_acc,
  38. 'solar': ['', 97, '', 0.09*1],
  39. 'wind': ['', 96, '', 0.09*1],
  40. 'check': False
  41. },
  42. "northeast":{
  43. 'func': self.formula.calculate_acc_northeast,
  44. 'solar': ['', 85, '', 0.02*0.1],
  45. 'wind': ['', 80, '', 0.02*0.1]
  46. },
  47. "northwest":{
  48. 'func': self.formula.calculate_acc_northwest,
  49. 'solar': ['', 75, '', 0.015*0.1*0.5],
  50. 'wind': ['', 75, '', 0.015*0.1*0.5]
  51. }
  52. }
  53. def electricity_solar_cdq(self, df, province, predict, label='C_REAL_VALUE', output=True):
  54. df['C_TIME'] = pd.to_datetime(df['C_TIME'])
  55. df['C_TIME_DAY'] = df['C_TIME'].dt.strftime("%Y-%m-%d")
  56. dfs = df.groupby('C_TIME_DAY')
  57. limit = self.regulations[province]['solar'][1]
  58. alpha = self.regulations[province]['solar'][3]
  59. sum_score, sum_acc = 0, 0
  60. for dt, data in dfs:
  61. acc = self.regulations[province]['func'](data[label].values, data[predict].values)
  62. score = (limit - acc) * alpha if acc < limit else 0
  63. sum_acc += acc
  64. sum_score += score
  65. if output:
  66. self.logger.info("预测名称:{},日期:{},区域:{},超短期的准确率:{:.4f},考核分数:{:.4f}".format(predict, str(dt), province, acc, score))
  67. return round(sum_acc/len(dfs), 5), round(sum_score/len(dfs), 5)
  68. def electricity_wind_cdq(self, df, province, predict, label='C_REAL_VALUE', output=True):
  69. df['C_TIME'] = pd.to_datetime(df['C_TIME'])
  70. df['C_TIME_DAY'] = df['C_TIME'].dt.strftime("%Y-%m-%d")
  71. dfs = df.groupby('C_TIME_DAY')
  72. limit = self.regulations[province]['solar'][1]
  73. alpha = self.regulations[province]['solar'][3]
  74. sum_score, sum_acc = 0, 0
  75. for dt, data in dfs:
  76. acc = self.regulations[province]['func'](data[label].values, data[predict].values)
  77. score = (limit - acc) * alpha if acc < limit else 0
  78. sum_acc += acc
  79. sum_score += score
  80. if output:
  81. self.logger.info("预测名称:{},日期:{},区域:{},超短期的准确率:{:.4f},考核分数:{:.4f}".format(predict, str(dt), province, acc, score))
  82. return round(sum_acc / len(dfs), 2), round(sum_score / len(dfs), 2)
  83. class Formulas(object):
  84. def __init__(self, opt):
  85. self.opt = opt
  86. def calculate_acc(self, label_data, predict_data):
  87. loss = np.sum((label_data - predict_data) ** 2) / len(label_data) # mse
  88. loss_sqrt = np.sqrt(loss) # rmse
  89. loss_acc = (1 - loss_sqrt / self.opt.cap) * 100
  90. return loss_acc
  91. def calculate_acc_south(self, label_data, predict_data):
  92. cap = 0.1 * self.opt.cap
  93. mask = (label_data < cap) & (predict_data < cap)
  94. label_data = label_data[~mask]
  95. predict_data = predict_data[~mask]
  96. if len(predict_data) == 0:
  97. return 0
  98. diff = label_data - predict_data
  99. base = np.where(label_data < self.opt.cap * 0.2, self.opt.cap * 0.2, label_data)
  100. acc = np.sum((diff / base) ** 2) / len(diff)
  101. acc = (1 - np.sqrt(acc)) * 100
  102. return acc
  103. def calculate_acc_northwest(self, label_data, predict_data):
  104. cap = 0.03 * self.opt.cap
  105. mask = (label_data < cap) & (predict_data < cap)
  106. label_data = label_data[~mask]
  107. predict_data = predict_data[~mask]
  108. if len(predict_data) == 0:
  109. return 0
  110. diff = np.abs(label_data - predict_data)
  111. base1 = label_data + predict_data + 1e-9
  112. base2 = np.sum(diff) + 1e-9
  113. acc = (1 - 2 * np.sum(np.abs(label_data / base1 - 0.5) * diff / base2)) * 100
  114. return acc
  115. def calculate_acc_northeast(self, label_data, predict_data):
  116. cap = 0.1 * self.opt.cap
  117. mask = (label_data < cap) & (predict_data < cap)
  118. label_data = label_data[~mask]
  119. predict_data = predict_data[~mask]
  120. if len(predict_data) == 0:
  121. return 0
  122. diff = np.abs(predict_data - label_data)
  123. deviation = diff / np.abs(predict_data + 1e-9)
  124. acc = np.where(deviation >= 1, 1, deviation)
  125. acc = 1 - np.mean(acc)
  126. return acc
  127. if __name__ == '__main__':
  128. from config import myargparse
  129. args = myargparse(discription="场站端配置", add_help=False)
  130. opt = args.parse_args_and_yaml()
  131. formula = Formulas(opt)
  132. test = pd.read_csv('./data/测试集16.csv')
  133. test = test.iloc[:96, :]
  134. acc = formula.calculate_acc_northeast(test['C_REAL_VALUE'], test['C_FP_VALUE'])
  135. print(acc)