近年来,随着陆上风电机组装机厂址的扩大,在天气渐变较多的地区安装的风力发电机组受到气候变化的影响愈发显著。在风况渐变时,因为控制系统的滞后性,容易导致机组出现载荷过大,以至是倒机的情况,造成重大经济损失。同时,现有超短期风功率预测的精确性较差,导致风功率预测系统对电网调度的参考价值不大,并且会导致业主产生大量的发电量计划考核。因为常见的激光雷达等风速丈量产品单价高昂、受天气影响较大,难以完成批量化的利用部署,且在大工夫空间尺度下仍难以具备可靠的前瞻性。因此,可靠的超短期风况预测迫在眉睫。
超短期风况预测是一个世界性难题,假如能通过大数据、人工智能技术预测出每台机组在未来短时间内的风速大风向数据,可能晋升风电机组的管制前瞻性、提高风电机组的载荷安全性;同时,现有超短期风功率预测能力的晋升,将带来显著的安全价值和经济效益。
本次比赛由深圳保安区人民政府与中国信息通信研究院联合主办,提供了来自工业生产中的实在数据与场景,心愿拆散工业与AI大数据,解决实际生产工作中面临的挑战。
数据分析
锤炼集说明
两个风场各两年的锤炼数据:
每个风场25台风电机组,提供各台机组的机舱风速、风向、温度、功率和对应的小时级气象数据;2. 风场1的风机编号为:x26-x50,锤炼集数据范畴为2018、2019年;3. 风场2的风机编号为:x25-x49,锤炼集数据范畴为2017、2018年;4. 各机组的数据文件按 /锤炼集/[风场]/[机组]/[日期].csv的形式存储;
气象数据存储在 /锤炼集/[风场] 文件夹下。
测试集说明
测试集分为两个文件夹:测试集初赛、测试集决赛,初赛和决赛的文件夹组织形式一致;
初赛和决赛文件夹各包含80个时段的数据,每个时段1小时数据(30S分辨率,工夫以秒数表白),春夏秋冬各20个时段,初赛编号1-20,决赛编号21-40;即初赛的时段编号为春_01-冬_20共80个;决赛的时段编号为春_21-冬_40共80个;
各机组的数据文件按照 /测试集_**/[风场]/[机组]/[时段].csv 的形式存储;
气象数据存储在 /测试集_**/[风场]/ 文件夹下,共80个时段风场所在地的风速风向数据,每个时段提供过来12小时和未来1小时的风速大风向数据。时段编码同上,工夫编码为-11~2,其中0~1这个小时正好对应的是机舱的1小时数据。
缺失值数据中的缺失值次要来自两个方面,一种是当天的数据记录存在缺失,另一种是某些时间段的数据存在缺失。多种缺失状况导致在填充数据时存在脱漏问题,仅应用一种形式填充缺失值会导致缺失值的填充呈现缺漏,因而较量中咱们同时应用了forward fill、backward fill与均值填充以保障填充覆盖率。这样解决可能会引入乐音,然而神经网络对于乐音有肯定的容忍度,因此最终的训练成果影响并不大。思考到训练数据、将来的测试数据中都可能存在缺失数据,而且它们的记录形式是雷同的,因而咱们没有去掉存在缺失值的数据,同时对它们应用了雷同的填充形式,防止因为预处理不同导致数据分布不统一问题的呈现。模型思路介绍模型构造较量中,咱们采纳了Encoder-Decoder 模式的模型,通过序列模型开掘输出序列中的信息,再通过Decoder进行预测。这里的Encoder、Decoder有多种抉择,例如常见的序列模型LSTM,或者近几年衰亡的Transformer。较量中咱们在Decoder侧重叠了多层LSTM,Encoder侧只应用了一层LSTM。模型中没有退出dropout进行正则化,这是思考到数据中自身就存在大量的高频乐音,再退出dropout会导致模型收敛迟缓,影响模型的训练效率。咱们应用飞桨框架搭建模型构造,起初发现飞桨官网的自然语言解决模型库
应用飞桨框架构建的最终模型构造的代码如下:class network(nn.Layer):
def __init__(self, name_scope='baseline'): super(network, self).__init__(name_scope) name_scope = self.full_name() self.lstm1 = paddle.nn.LSTM(128, 128, direction = 'bidirectional', dropout=0.0) self.lstm2 = paddle.nn.LSTM(25, 128, direction = 'bidirectional', dropout=0.0) self.embedding_layer1= paddle.nn.Embedding(100, 4) self.embedding_layer2 = paddle.nn.Embedding(100, 16) self.mlp1 = paddle.nn.Linear(29, 128) self.mlp_bn1 = paddle.nn.BatchNorm(120) self.bn2 = paddle.nn.BatchNorm(14) self.mlp2 = paddle.nn.Linear(1536, 256) self.mlp_bn2 = paddle.nn.BatchNorm(256) self.lstm_out1 = paddle.nn.LSTM(256, 256, direction = 'bidirectional', dropout=0.0) self.lstm_out2 = paddle.nn.LSTM(512, 128, direction = 'bidirectional', dropout=0.0) self.lstm_out3 = paddle.nn.LSTM(256, 64, direction = 'bidirectional', dropout=0.0) self.lstm_out4 = paddle.nn.LSTM(128, 64, direction = 'bidirectional', dropout=0.0) self.output = paddle.nn.Linear(128, 2, ) self.sigmoid = paddle.nn.Sigmoid()# 网络的前向计算函数def forward(self, input1, input2): embedded1 = self.embedding_layer1(paddle.cast(input1[:,:,0], dtype='int64')) embedded2 = self.embedding_layer2(paddle.cast(input1[:,:,1]+input1[:,:,0] # * 30 , dtype='int64')) x1 = paddle.concat([ embedded1, embedded2, input1[:,:,2:], input1[:,:,-2:-1] * paddle.sin(np.pi * 2 *input1[:,:,-1:]), input1[:,:,-2:-1] * paddle.cos(np.pi * 2 *input1[:,:,-1:]), paddle.sin(np.pi * 2 *input1[:,:,-1:]), paddle.cos(np.pi * 2 *input1[:,:,-1:]), ], axis=-1) # 4+16+5+2+2 = 29 x1 = self.mlp1(x1) x1 = self.mlp_bn1(x1) x1 = paddle.nn.ReLU()(x1) x2 = paddle.concat([ embedded1[:,:14], embedded2[:,:14], input2[:,:,:-1], input2[:,:,-2:-1] * paddle.sin(np.pi * 2 * input2[:,:,-1:]/360.), input2[:,:,-2:-1] * paddle.cos(np.pi * 2 * input2[:,:,-1:]/360.), paddle.sin(np.pi * 2 * input2[:,:,-1:]/360.), paddle.cos(np.pi * 2 * input2[:,:,-1:]/360.), ], axis=-1) # 4+16+1+2+2 = 25 x2 = self.bn2(x2) x1_lstm_out, (hidden, _) = self.lstm1(x1) x1 = paddle.concat([ hidden[-2, :, :], hidden[-1, :, :], paddle.max(x1_lstm_out, axis=1), paddle.mean(x1_lstm_out, axis=1) ], axis=-1) x2_lstm_out, (hidden, _) = self.lstm2(x2) x2 = paddle.concat([ hidden[-2, :, :], hidden[-1, :, :], paddle.max(x2_lstm_out, axis=1), paddle.mean(x2_lstm_out, axis=1) ], axis=-1) x = paddle.concat([x1, x2], axis=-1) x = self.mlp2(x) x = self.mlp_bn2(x) x = paddle.nn.ReLU()(x) # decoder x = paddle.stack([x]*20, axis=1) x = self.lstm_out1(x)[0] x = self.lstm_out2(x)[0] x = self.lstm_out3(x)[0] x = self.lstm_out4(x)[0] x = self.output(x) output = self.sigmoid(x)*2-1 output = paddle.cast(output, dtype='float32') return output复制代码飞桨框架在训练模型时有多种形式,能够像其余深度学习框架一样,通过梯度回传进行训练,也能够利用高度封装后的API进行训练。在应用高层API训练时,咱们须要筹备好数据的generator和模型构造。飞桨框架中generator的封装形式如下,应用效率很高:class TrainDataset(Dataset):
...