- 系列博客不会出现任何真实数据
- 比赛期间将拒绝一切私信,有问题请发评论
系列文章目录
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【0】【风况预测评分规则-最终得分R的计算】【已弃用】
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【1】【验证集制作】【已弃用】
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【2】【验证集使用】【已弃用】
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【3】【计算最终得分】
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【4】【数据管理】
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【5】【数据可视化】【测试集_初赛】
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【6】【数据可视化】【训练集】
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【7】【数据管理】【验证集本地化】
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【8】【数据可视化】【验证集】
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【9】【数据可视化】【气象数据】
文章目录
- 声明
- 系列文章目录
- 更新说明
- 前言
- 一、评分规则
- 二、评分规则计算思路
- 三、编程实现计算过程
- 1. 模仿答案样本生成“预测值”和“真实值”
- 2. 计算预测误差
- 2.1 mj
- 2.2 nj
- 3 计算平均预测误差
- 4. 计算最终得分R
- 四、 封装
更新说明
无
前言
了解比赛的评分规则,可谓是比赛过程中非常重要的一环,从评分规则中可以得到很多信息,比如出题者在关注什么,损失函数的设计思路等。接下来就让我们来研究一下评分规则,然后把它代码化。
一、评分规则
评分规则的图片来源于大赛官网
二、评分规则计算思路开始之前我觉得有必要先介绍一下数据集
- 一共有2个风场,每个风场25台风机
- 关于时段,每个时段的时间是1小时(3600秒),时间分辨率为30秒,也就是说一个时段有120行数据
- 训练集每台风机一共两年(2 * 365 * 24 = 17520 个时段)
- 测试集每台风机一共160个时段(初赛80段,春夏秋冬各20段,编号01~20;决赛80段,春夏秋冬各20段,编号21~40)
- 预测目标:某时段的未来10分钟,时间分辨率为30秒,也就是说需要预测20行数据
要求 R R R ,就要先求各个风场各个时段的平均预测误差
要求 E ⋅ i E_{cdot i} E⋅i,就要先求各个风机预测误差,然后求平均值
要求 m j m_j mj 和 n j n_j nj,就要先有风速和风向的预测值与真实值
接着只需要一步一步计算回去就好了,但是怎样计算最高效呢?
观察一下答案样本,位置基本上都是特定的,比如第1 ~ 20行是风场1风机x26时段春_01的10分钟风速风向数据,第21 ~ 40行是风场1风机x26时段春_02的10分钟风速风向数据,最后20行是风场2风机x49时段冬_20的10分钟风速风向数据,然后风场、风机、时段、时刻的排列是有顺序的。位置固定,顺序已知,就是待会我们实现高效计算的基础。
由于现阶段还没有预测值,也没有真实值,所以拿随机数来代替一下先
先看一下答案样本
1. 模仿答案样本生成“预测值”和“真实值”import itertools import numpy as np import pandas as pd
field = np.array([
'风场1',
'风场2'
])
field_len = field.shape[0]
machine = np.array([
[f'x{i}' for i in range(26, 50+1)],
[f'x{i}' for i in range(25, 49+1)]
])
machine_len = machine[0].shape[0]
season = np.array(['春', '夏', '秋', '冬'])
season_len = season.shape[0]
period = np.array([f'{s}_{str(i).zfill(2)}' for s in season for i in range(1, 20+1)])
period_len = period.shape[0]
df = pd.Dataframe(
data = np.array([
[*x0, x1, x2, x3, x4] for x0, x1, x2, x3, x4 in
itertools.product(
np.vstack([list(itertools.product([field[f]], machine[f])) for f in range(field_len)]).tolist(), # '风场', '风机'
period, # '时段'
np.arange(1, 20+1) * 30, # '时刻'
[None], # '风速'
[None] # '风向'
)
]),
columns = ['风场', '风机', '时段', '时刻', '风速', '风向']
)
df
睁大你的眼睛看好了,这数据是np.random.random(size=(2 * 25 * 80 * 20, 2)),不是真实数据哈
val_true = df.copy() val_true.loc[:, ['风速', '风向']] = np.random.random(size=(2 * 25 * 80 * 20, 2)) val_true
睁大你的眼睛看好了,这数据是np.random.random(size=(2 * 25 * 80 * 20, 2)),不是真实数据哈
val_pred = df.copy() val_pred.loc[:, ['风速', '风向']] = np.random.random(size=(2 * 25 * 80 * 20, 2)) val_pred2. 计算预测误差
记住,位置固定,顺序已知。2个风场,每个风场25个风机,每个风机80个时段,每个时段20个时刻
预测值和真实值都有了,现在还差这个 w
w = np.arange(2 * 25 * 80 * 20, dtype=float) % 20 print(w[:20], w[20:40], w[40:60], sep='n') w[w < 10] = 0.06 w[w >= 10] = 0.04 print(w[:20], w[20:40], w[40:60], sep='n')
这样,就为每个风场每个风机每个时段每个时刻都生成对应的 w 值了
接下来计算公式3
记住,位置固定,顺序已知。2个风场,每个风场25个风机,每个风机80个时段,每个时段20个时刻
m = (w * np.abs(val_pred['风速'] - val_true['风速']).values).reshape(2 * 25 * 80, 20).sum(-1) m.shape
公式中的求和体现在.reshape(2 * 25 * 80, 20).sum(-1)
2.2 nj记住,位置固定,顺序已知。2个风场,每个风场25个风机,每个风机80个时段,每个时段20个时刻
alpha 本质上就是部分权重为0的 w ,为什么变 0,是因为风速小所以风向不稳定。这个判断的阈值两个风场不一样。
记住,位置固定,顺序已知。2个风场,每个风场25个风机,每个风机80个时段,每个时段20个时刻
前面一半是风场1,后面一半是风场2,直接根据这个生成阈值
threshold = np.repeat([0.15, 0.086], 25 * 80 * 20) threshold
当风速小这个阈值时,w 置 0
a = w * (val_true['风速'].values > threshold) a
注:符合条件为True,不符合条件为False,True 默认为 1, False 默认为 0。
直接按公式计算就可以了
e = np.minimum(np.mod((val_pred['风向'] - val_true['风向']).values, 1), np.mod((val_true['风向'] - val_pred['风向']).values, 1))
记住,位置固定,顺序已知。2个风场,每个风场25个风机,每个风机80个时段,每个时段20个时刻
n = (a * e).reshape(2 * 25 * 80, 20).sum(-1) n.shape
公式中的求和体现在.reshape(2 * 25 * 80, 20).sum(-1)
3 计算平均预测误差记住,位置固定,顺序已知。2个风场,每个风场25个风机,每个风机80个时段,每个时段20个时刻
E1, E2 = (0.7 * m + 0.3 * n).reshape(2, 25, 80).mean(1) E1.shape, E2.shape4. 计算最终得分R
R = 100 / (1 + E1.sum() + E2.sum()) R
根据公式以及极限的知识可知,最高分无限接近于100分,最低分无限接近于0分。
随机数都能得2分,能得0分某种程度上也是挺厉害的。。
假设你存放真实数据的文件名为val_true.csv
假设你存放预测数据的文件名为val_pred.csv
问:这俩东西在哪搞?
答:【7】【数据管理】【验证集本地化】
import itertools
import numpy as np
import pandas as pd
field = np.array([
'风场1',
'风场2'
])
field_len = field.shape[0]
machine = np.array([
[f'x{i}' for i in range(26, 50+1)],
[f'x{i}' for i in range(25, 49+1)]
])
machine_len = machine[0].shape[0]
season = np.array(['春', '夏', '秋', '冬'])
season_len = season.shape[0]
period = np.array([f'{s}_{str(i).zfill(2)}' for s in season for i in range(1, 20+1)])
period_len = period.shape[0]
def standardize(val_df):
"""
记住,位置固定,顺序已知。
不管你是有缺失值还是顺序不对,这段代码都帮你解决。
"""
df = pd.Dataframe(
data = np.array([
[*x0, x1, x2, x3, x4] for x0, x1, x2, x3, x4 in
itertools.product(
np.vstack([list(itertools.product([field[f]], machine[f])) for f in range(field_len)]).tolist(), # '风场', '风机'
period, # '时段'
np.arange(1, 20+1) * 30, # '时刻'
[None], # '风速'
[None] # '风向'
)
]),
columns = ['风场', '风机', '时段', '时刻', '风速', '风向']
)
return pd.merge(
left = df[['风场', '风机', '时段', '时刻']].copy(),
right = val_df,
how = 'left',
on = ['风场', '风机', '时段', '时刻']
).fillna(0)
def cal_R():
val_true = standardize(pd.read_csv('val_true.csv', encoding='utf-8'))
val_pred = standardize(pd.read_csv('val_pred.csv', encoding='utf-8'))
# 公式 6
w = np.arange(2 * 25 * 80 * 20, dtype=float) % 20
w[w < 10] = 0.06
w[w >= 10] = 0.04
# 公式 3
m = (w * np.abs(val_pred['风速'] - val_true['风速']).values).reshape(2 * 25 * 80, 20).sum(-1)
# 公式 7
threshold = np.repeat([0.15, 0.086], 25 * 80 * 20)
a = w * (val_true['风速'].values > threshold)
# 公式 5
e = np.minimum(np.mod((val_pred['风向'] - val_true['风向']).values, 1), np.mod((val_true['风向'] - val_pred['风向']).values, 1))
# 公式 4
n = (a * e).reshape(2 * 25 * 80, 20).sum(-1)
# 公式 2
# 2个风场,每个风场25个风机,每个风机80个时段
E1, E2 = (0.7 * m + 0.3 * n).reshape(2, 25, 80).mean(1)
# 公式 1
R = 100 / (1 + E1.sum() + E2.sum())
print(f'R: {R:.3f}')
cal_R()



