Baseline相关
Step1:导入库和数据转换
主要依赖库:
- numpy 用于矩阵运算
- pandas 用于表格处理
- pathlib 主要用于文件路径处理
- sklearn 用于机器学习算法,这里主要使用了线性回归LinearRegression
虽然平时见到过,但是从来没有系统整理过,这边给出的4个,我觉得1、2、4算是常见的,要记一下用途,要不学得云里雾里的
conda或pip安装第三方库
数据预处理
前面的数据都有出清价格
后面的就没有出清价格了,需要我们预测
①找出 clearing price (CNY/MWh) 列中有缺失值的行,electricity_price[...] 过滤出这些行,因为我们只需要预测缺失出清价格的那些行。drop(columns="demand") 从这些过滤出来的行中删除 'demand' 列,免除干扰,最后将结果保存为 sample_submit.csv 文件,并且文件不包含行索引(index=False)。
sample_submit = electricity_price[electricity_price["clearing price (CNY/MWh)"].isna()].drop(columns="demand")
sample_submit.to_csv(base_path / "sample_submit.csv", index=False)
②合并市场数据的日期和时间,变为时间戳,时间戳可以提取出丰富的时间特征,提高数据处理的灵活性和效率。
# 将day和time列合并成timestamp列,便于提取时间戳特征
electricity_price["timestamp"] = pd.to_datetime(
electricity_price["day"] + " " + electricity_price["time"].str.replace("24:00:00", "00:00"))
# 处理24:00:00的情况,即表示第二天的00:00:00
mask = electricity_price['timestamp'].dt.time == pd.Timestamp('00:00:00').time()
# 需要将这些行的日期部分加一天
electricity_price.loc[mask, 'timestamp'] += pd.Timedelta(days=1)
# 设置列的顺序,同时去除day和time列
electricity_price = electricity_price[["timestamp", "demand", "clearing price (CNY/MWh)"]]
经过处理的数据如下图所示。包含约55000个出清电价和电力负荷数据,市场每15分钟生成一次出清电价
- timestamp:时间戳
- demand:区域内电力总负荷(总需求),单位为MW
- clearing price (CNY/MWh):市场出清电价,单位为元/MW·h
机组数据包含549个不同的火电机组
- unit ID:每个机组唯一的ID
- Capacity(MW):机组的额定容量(额定功率),越高机组的发电能力越强
- utilization hour (h) :电厂的年平均运行小时数,需要注意多个机组可能共同属于一个电厂,有相同的utilization hour (h)
- coal consumption (g coal/KWh):每发一度电需要耗费多少煤炭,为成本参数
- power consumption rate:电厂单位时间内耗电量与发电量的百分比
Step2:使用ABM估计市场出清价格
ABM(代理模型)是一种模拟个体行为和相互作用的模型,它通过定义系统中的个体(称为“代理”)及其相互作用规则来进行建模。模拟ABM需要遵循3个规则,我结合捕食者-被捕食者模型理解:
- 捕食者和被捕食者都有初始的能量,移动会消耗能量,进食会增加能量
- 能量过低时死亡,能量足够高时繁育
- 如果移动后遇到食物,则吃下它(捕食者吃被捕食者,被捕食者吃草)
运用到电价预测有:
-
电力市场中的发电机组:每个发电机组有初始的资源(如燃料、资金)。运行和维护会消耗资源,而发电和出售电力则增加资源。
-
资源过低时:发电机组可能无法继续发电(类似于死亡)。
资源充足时:发电机组可以投入更多资源进行发电和设备维护,提升发电能力(类似于繁育)。
-
发电机组报价:当发电机组有足够资源时,它们会根据成本和市场需求进行报价。报价被市场接受后,发电机组将消耗资源(燃料)来生产电力。
当按累积容量排序的发电机组列表中,第一个累积容量大于或等于当前电力需求的发电机组就是“最后一个”发电机组。这个机组的报价或成本用于计算出清价格,因为它是满足该需求的边际机组。
# 按照一度电的耗煤量(近似为边际成本)降序排序
sorted_unit = unit.sort_values("coal consumption (g coal/KWh)")
# 预先计算 sorted_unit 的累积和
sorted_unit['cumulative_capacity'] = sorted_unit['Capacity(MW)'].cumsum()
prices = []
# 找到最后一个满足总需求的机组报价
for demand in electricity_price["demand"]:
price = sorted_unit[sorted_unit['cumulative_capacity'] >= demand]["coal consumption (g coal/KWh)"].iloc[0]
prices.append(price)
print(len(prices))
prices[:5]
Step3:转换耗煤量为机组报价
由于直接的报价数据可能不可用或复杂,因此使用线性回归来建立一种近似关系,来估计发电机组的实际报价(市场出清价格)和耗煤量之间的关系。
model = LinearRegression()
# 55392为训练集的长度
train_length = 55392
prices = np.array(prices).reshape(-1, 1)
X = prices[:train_length]
y = electricity_price["clearing price (CNY/MWh)"].iloc[:train_length].values.reshape(-1, 1)
model.fit(X, y)
model.coef_, model.intercept_
根据这个方程式,我们有:
- X对应耗煤量N
- Y对应市场出清价格P
- model.coef_表示线性回归模型中的系数(或斜率),代表耗煤量(N)对预测出的市场出清价格(P)的影响大小。根据方程式它的值为 11.26,表示耗煤量每增加一单位,估计的市场出清价格增加 11.26 单位
- model.intercept_表示线性回归模型中的截距,即当自变量为零时,预测的因变量的值。根据方程式它的值为 -2763.16,它表示即使耗煤量为零,模型预测的市场出清价格也会是 -2763.16(这是模型的初始估计值,可能不符合实际的物理意义,但对模型拟合有数学意义)
使用边际成本定价的机组报价为出清价格估计
y_pred = model.predict(prices[train_length:])
y_pred = y_pred.flatten() # 2维矩阵转为1维
y_pred[:5]