【风况预测评分规则-python实现】第五届全国工业互联网数据创新应用大赛-机组数据驱动的风电场短期风况预测
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【1】【验证集制作】
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【2】【验证集使用】
第五届全国工业互联网数据创新应用大赛 机组数据驱动的风电场短期风况预测 【3】【计算最终得分】
上传答案返回成绩的机会每周只有3次,机会非常宝贵,为了能够随时验证自己的模型,于是这个博客应运而生。
验证集格式及数据来源(具体实现请看代码注释)- 验证集和测试集的文件夹组织形式完全一致
- 文件名和测试集的文件名对应
- 验证集_初赛 <- 测试集_初赛
- 验证集_决赛 <- 测试集_决赛
- 验证数据完全遵从测试集说明
- 验证样本区间:Y年M月D 日 的 00:00:30 -> Y年M月D日 的 01:00:00,共 120 行数据(30S分辨率,单位:秒)
- 答案数据区间:Y年M月D 日 的 01:00:30 -> Y年M月D日 的 01:10:00,共 20 行数据(30S分辨率,单位:秒)
- 气象数据区间:Y年M月D-1日 的 13:00:00 -> Y年M月D日 的 02:00:00,共 14 行数据(1H分辨率,单位:时)
- 验证集的答案和答案样本说明一致
-
若测试集含有部分时段缺失的情况,对于缺失值,一律用 0 填充
- 部分变量名来源(采用谷歌翻译,省略“风”)
- 风场: field
- 风机: machine
- 时段: period
- 时刻: time
- 风速: speed
- 风向: direction
import glob
import os
import threading
from tqdm import tqdm
import warnings
warnings.filterwarnings('ignore')
import numpy as np
import pandas as pd
train_dir, test_dir, val_dir = 'train', '测试集_初赛', '验证集_初赛'
field_1, field_2 = '风场1', '风场2'
machine_1 = [f'x{i}' for i in list(range(26, 50+1))]
machine_2 = [f'x{i}' for i in list(range(25, 49+1))]
period = [f'{s}_{str(i).zfill(2)}' for s in ['春', '夏', '秋', '冬'] for i in range(1, 20+1)]
field_1_weather_val = pd.Dataframe(
data = {
'时段': np.array(period * 14).reshape(14, 80).T.flatten(),
'时刻': np.array(list(range(-11, 3)) * 80),
'风速': None,
'风向': None
}
)
field_2_weather_val = pd.Dataframe(
data = {
'时段': np.array(period * 14).reshape(14, 80).T.flatten(),
'时刻': np.array(list(range(-11, 3)) * 80),
'风速': None,
'风向': None
}
)
2.2. 读取训练集气象数据
field_1_weather_train = pd.read_csv(os.path.join(train_dir, field_1, 'weather.csv'), encoding='utf-8') field_2_weather_train = pd.read_csv(os.path.join(train_dir, field_2, 'weather.csv'), encoding='utf-8')
# 添加一个索引,方便后面制作验证集的气象数据
field_1_weather_train.insert(0, 'date', np.array([s.split(' ')[0].replace('/', '-') for s in field_1_weather_train['time'].values]))
field_2_weather_train.insert(0, 'date', np.array([s.split(' ')[0].replace('/', '-') for s in field_2_weather_train['time'].values]))
3. 答案相关准备
3.1. 准备容器存储答案数据
field_len = 2
machine_len = 25
period_len = 80
field = [field_1, field_2]
machine = [machine_1, machine_2]
time = [i * 30 for i in range(1, 20+1)]
time_len = len(time)
answer_val = pd.Dataframe(
data={
'风场': np.array(field * machine_len * period_len * time_len).reshape(-1, field_len).T.reshape(-1),
'风机': np.array(machine * period_len * time_len).reshape(-1, field_len * machine_len).T.reshape(-1),
'时段': np.array(np.array(period * time_len).reshape(-1, period_len).T.reshape(-1).tolist() * field_len * machine_len),
'时刻': np.array(time * field_len * machine_len * period_len),
'风速': None,
'风向': None
}
)
4. 验证数据相关准备
4.1. 生成与测试集对应的空文件夹
df.to_csv() 要求保存路径存在,不然会报错
FileNotFoundError: [Errno 2] No such file or directory
os.makedirs(val_dir, exist_ok=True) os.makedirs(os.path.join(val_dir, field_1), exist_ok=True) os.makedirs(os.path.join(val_dir, field_2), exist_ok=True) [os.makedirs(os.path.join(val_dir, field_1, machine), exist_ok=True) for machine in machine_1]; [os.makedirs(os.path.join(val_dir, field_2, machine), exist_ok=True) for machine in machine_2];4.2. 读取所有测试数据路径
path_list = glob.glob(os.path.join(test_dir, '*', 'x*', '*'))5. 季节判定
- 同一季节时间范围
- 春 02-05 ~ 05-06
- 夏 05-07 ~ 08-07
- 秋 08-08 ~ 11-07
- 冬 11-08 ~ 02-04
def check_file(train_file_path, target_season):
"""
季节是否对应
数据是否含缺失值
"""
month, day = train_file_path.split(os.sep)[-1].split('.')[0].split('-')[1:]
month, day = int(month), int(day)
if (month == 2 and day >= 5) or month == 3 or month == 4 or (month == 5 and day <= 6):
season = '春'
if (month == 5 and day >= 7) or month == 6 or month == 7 or (month == 8 and day <= 7):
season = '夏'
if (month == 8 and day >= 8) or month == 9 or month == 10 or (month == 11 and day <= 7):
season = '秋'
if (month == 11 and day >= 8) or month == 12 or month == 1 or (month == 2 and day <= 4):
season = '冬'
if season == target_season:
if len(pd.read_csv(train_file_path)[1:141].dropna()) == 140:
return True
return False
6. 开始制作验证集和验证集的答案
# path_list 存放了所有测试数据路径,根据这些路径一一制作与之对应的验证集
for test_file_path in tqdm(path_list):
# 验证数据保存位置,与测试集相对应
val_file_path = test_file_path.replace('测试', '验证')
# 当前测试数据路径的信息(风场,风机,时段)
_, field_test, machine_test, period_test = test_file_path.split(os.sep)
# 验证数据从训练集中来(train),又要与测试集对应(风场对应,风机对应)
machine_train = os.path.join(train_dir, field_test, machine_test)
# 当前测试集对应的验证集制作成功就会保存到相应位置,未成功的话就一直循环到成功为止
while not os.path.exists(val_file_path):
# 从当前指定的训练集风机文件夹中抽取 1 个历史数据文件
# 为防止BUG,采样时不包含现有历史数据的头一天,因为头一天没有前一天
target_file_path = os.path.join(machine_train, np.random.choice(os.listdir(machine_train)[1:], 1)[0])
# 检查文件是否符合标准,不符合标准就重新采样
if check_file(target_file_path, period_test.split('_')[0]): # period_test.split('_')[0] 将 '冬_01.csv' 变成 '冬'
train_data = pd.read_csv(target_file_path)
# -------------------- 制作时段数据 --------------------
val_data = train_data[1:121] # [1:121] 代表 00:00:30 -> 01:00:00
val_data['time'] = np.arange(1, 121) * 30
val_data.to_csv(val_file_path, float_format='%.7f', index=False, encoding='utf-8')
# -------------------- 制作气象数据 --------------------
date = target_file_path.split(os.sep)[-1].split('.')[0] # 目标数据的日期。例如 2018-10-01
date_list = eval(f'field_{field_test[-1]}_weather_train')['date'] # 前面添加的索引现在派上用场了
# 目标气象数据在历史气象数据中的第一个数据的索引
weather_data_index = np.where(date == date_list)[0][0]
# 目标气象数据
weather_data = eval(f'field_{field_test[-1]}_weather_train')[weather_data_index-11: weather_data_index+3][['wind_spd', 'wind_dir']].values
eval(f'field_{field_test[-1]}_weather_val').loc[eval(f'field_{field_test[-1]}_weather_val')['时段'] == period_test.split('.')[0], ['风速', '风向']] = weather_data
# -------------------- 制作答案数据 --------------------
answer_data = train_data[121:141][['风速', '风向']].values # [121:141] 代表 01:00:30 -> 01:10:00
answer_val.loc[((answer_val['风场'] == field_test) * (answer_val['风机'] == machine_test) * (answer_val['时段'] == period_test.split('.')[0])), ['风速', '风向']] = answer_data
field_1_weather_val.to_csv(os.path.join(val_dir, field_1, 'weather.csv'), index=False, encoding='utf-8')
field_2_weather_val.to_csv(os.path.join(val_dir, field_2, 'weather.csv'), index=False, encoding='utf-8')
answer_val.fillna(0).to_csv('answer_val.csv', index=False, encoding='utf-8')
一些问题
- 验证集时间过于集中。我们需要的是能够预测任意时间的模型,不是只预测 01:00:30 -> 01:10:00 这一小段时间。
- 这个问题过段时间就改进,难点还是在缺失值,毕竟是时序问题。
- 验证数据浮点精度问题。官方提供的测试集浮点精度在16位左右,而本代码所制作的验证集浮点精度只有7位。
- 无法改进,因为验证集数据来源于训练集,训练集本来就是这样的,后面几位小数训练集不存在我也不能变出来对吧。
你可以参考(【风况预测评分规则-python实现】第五届全国工业互联网数据创新应用大赛-机组数据驱动的风电场短期风况预测)
也可以等我的下一期博客



