第九届泰迪杯上市公司财务造假全国一等奖,曾入围特等选拔7进3,并进行答辩。由于实习的原因不参加本次比赛,在此记录一下自己的一些想法与思考,希望可以为大家提供一些思路。此外,就多次参加比赛的经历中,笔者认为在模型构建以及论文撰写中,大家可以把某一个点作为论文的亮点,围绕这个点来展开,并对比这一个处理方法相较于其他的方法有多大的提升。通过图表的方式将多个模型结果进行可视化对比,提高摘要的质量,做到这几点,一般离拿奖就不远了。
B题:电力系统负荷预测分析
一、问题背景
电力系统负荷(电力需求量,即有功功率)预测是指充分考虑历史的系统负荷、经济状况、气象条件和社会事件等因素的影响,对未来一段时间的系统负荷做出预测。负荷预测是电力系统规划与调度的一项重要内容。短期(两周以内)预测是电网内部机组启停、调度和运营计划制定的基础;中期(未来数月)预测可为保障企业生产和社会生活用电,合理安排电网的运营与检修决策提供支持;长期(未来数年)预测可为电网改造、扩建等计划的制定提供参考,以提高电力系统的经济效益和社会效益。
复杂多变的气象条件和社会事件等不确定因素都会对电力系统负荷造成一定的影响,使得传统负荷预测模型的应用存在一定的局限性。同时,随着电力系统负荷结构的多元化,也使得模型应用的效果有所降低,因此电力系统负荷预测问题亟待进一步研究。
二、解决问题
1.地区负荷的中短期预测分析
根据附件中提供的某地区电网间隔15分钟的负荷数据,建立中短期负荷预测模型:
(1)给出该地区电网未来10天间隔15分钟的负荷预测结果,并分析其预测精度;
(2)给出该地区电网未来3个月日负荷的最大值和最小值预测结果,以及相应达到负荷最大值和最小值的时间,并分析其预测精度。
2.行业负荷的中期预测分析
对不同行业的用电负荷进行中期预测分析,能够为电网运营与调度决策提供重要依据。特别是在新冠疫情、国家“双碳”目标等背景下,通过对大工业、非普工业、普通工业和商业等行业的用电负荷进行预测,有助于掌握各行业的生产和经营状况、复工复产和后续发展走势,进而指导和辅助行业的发展决策。请根据附件中提供的各行业每天用电负荷相关数据,建立数学模型研究下面问题:
(1)挖掘分析各行业用电负荷突变的时间、量级和可能的原因。
(2)给出该地区各行业未来3个月日负荷最大值和最小值的预测结果,并对其预测精度做出分析。
(3)根据各行业的实际情况,研究国家“双碳”目标对各行业未来用电负荷可能产生的影响,并对相关行业提出有针对性的建议。
对于时间序列预测模型,一般采用arima,Facebook研发的prophet预测模型,还有对数据进行特征处理后采用lightGBM等机器学习模型进行预测。在回归中,预测精度一般采用RMSE,MAPE等评价指标进行预测精度判断。此外,对于后续数据增加,比较有亮点的地方是通过不同的调参方法进行参数调优。个人认为在本次比赛中,调参方法若是选择的好,参加比赛的小伙伴可以着重于这个点来撰写论文,获奖的可能性极大。
在01的基础上,大家可以参考数据预处理后的格式,并结合lightGBM构建其他的机器学习模型。在此基础上,增加较为前沿的调参方法。可以通过对比传统调参方法,网格搜索(GridSearchCV)和optuna,Hyperbot,openbox三者之间的运行速度,拟合优度等反向选择最好的调参方法进行预测。基于lightGBM,以GridSearchCV和Hyperbot为例:
from sklearn.model_selection import GridSearchCV
lgbm = lgb.LGBMRegressor()
parameters = {
'n_estimators': [10, 50, 100, 500, 1000], #树数
'learning_rate': [0.0001, 0.001, 0.01, 0.1, 1.0], #学习率
'max_depth': range(1, 5), #树深
'boosting_type': ['gbdt', 'dart', 'goss'] #增压型
}
cv = RepeatedKFold(n_splits = 10, n_repeats = 3, random_state = 1)
clf = GridSearchCV(lgbm, parameters, cv=cv)
clf.fit(train_x, train_y)
sorted(clf.cv_results_.keys())
clf.best_estimator_
params = {
'n_estimators': 1000,
'max_depth': 1,
'num_leaves': 2**4,
'learning_rate': 0.01,
'boosting_type': 'goss'
} #通过前面的clf.best_estimator_ 得到最优params
model = lgb.LGBMRegressor(first_metric_only = True, **params)
model.fit(train_x, train_y,
eval_metric = 'l1',
eval_set = [(test_x, test_y)],
#early_stopping_rounds = 10,
verbose = 0)
forecast = model.predict(test_x)
forecast
import datetime
import numpy as np
import pandas as pd
import lightgbm as lgb
from sklearn.metrics import mean_squared_error
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score,f1_score
import matplotlib.pyplot as plt
from hyperopt import fmin,hp,Trials,space_eval,rand,tpe,anneal
import warnings
warnings.filterwarnings('ignore')
def printlog(info):
nowtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print("\n"+"=========="*8 + "%s"%nowtime)
print(info+'...\n\n')
#================================================================================
# 一,读取数据
#================================================================================
printlog("step1: reading data...")
lgb_train = lgb.Dataset(train_x,train_y)
lgb_valid = lgb.Dataset(test_x, test_y,reference=lgb_train)
#================================================================================
# 二,搜索超参
#================================================================================
printlog("step2: searching parameters...")
boost_round = 1000
early_stop_rounds = 30
params = {
'learning_rate': 0.1,
'boosting_type': 'gbdt',#'dart','rf'
#'objective':'binary',
'metric': ['auc'],
'num_leaves': 31,
'max_depth': 6,
'min_data_in_leaf': 5,
'min_gain_to_split': 0,
'reg_alpha':0,
'reg_lambda':0,
'feature_fraction': 0.9,
'bagging_fraction': 0.8,
'bagging_freq': 5,
'feature_pre_filter':False,
'verbose': -1
}
# 1,定义目标函数
def loss(config):
params.update(config)
gbm = lgb.train(params,
lgb_train,
num_boost_round= boost_round,
valid_sets=(lgb_valid, lgb_train),
valid_names=('validate','train'),
early_stopping_rounds = early_stop_rounds,
verbose_eval = False)
y_pred_test = gbm.predict(test_x, num_iteration=gbm.best_iteration)
val_score = mean_squared_error(test_y,y_pred_test) ** 0.5
return val_score
# 2,定义超参空间
#可以根据需要,注释掉偏后的一些不太重要的超参
spaces = {"learning_rate":hp.choice("learning_rate",[0.0001, 0.001, 0.01, 0.1, 1.0]),
"boosting_type":hp.choice("boosting_type",['gbdt', 'dart']),
#"num_leaves":hp.choice("num_leaves",range(15,128)),
"n_estimators":hp.choice('n_estimators',[10, 50, 100, 500, 1000]),
"max_depth":hp.choice("max_depth",range(1,10))
#"min_data_in_leaf":hp.choice("min_data_in_leaf",range(1,50)),
}
# 3,执行超参搜索
# hyperopt支持如下搜索算法
#随机搜索(hyperopt.rand.suggest)
#模拟退火(hyperopt.anneal.suggest)
#TPE算法(hyperopt.tpe.suggest,算法全称为Tree-structured Parzen Estimator Approach)
trials = Trials()
best = fmin(fn=loss, space=spaces, algo= tpe.suggest, max_evals=100, trials=trials)
# 4,获取最优参数
best_params = space_eval(spaces,best)
print("best_params = ",best_params)
params = best_params
model = lgb.LGBMRegressor(first_metric_only = True, **params)
model.fit(train_x, train_y,
eval_metric = 'l1',
eval_set = [(test_x, test_y)],
early_stopping_rounds = 10,
verbose = 0)
forecast = model.predict(test_x)
forecast