Datawhale AI 夏令营 Task1电价预测笔记

115 阅读5分钟

Baseline相关

Step1:导入库和数据转换

主要依赖库:

  1. numpy 用于矩阵运算
  2. pandas 用于表格处理
  3. pathlib 主要用于文件路径处理
  4. sklearn 用于机器学习算法,这里主要使用了线性回归LinearRegression

虽然平时见到过,但是从来没有系统整理过,这边给出的4个,我觉得1、2、4算是常见的,要记一下用途,要不学得云里雾里的

conda或pip安装第三方库

数据预处理

前面的数据都有出清价格 image.png

后面的就没有出清价格了,需要我们预测

image.png

①找出 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分钟生成一次出清电价

  1. timestamp:时间戳
  2. demand:区域内电力总负荷(总需求),单位为MW
  3. clearing price (CNY/MWh):市场出清电价,单位为元/MW·h

image.png

机组数据包含549个不同的火电机组

  1. unit ID:每个机组唯一的ID
  2. Capacity(MW):机组的额定容量(额定功率),越高机组的发电能力越强
  3. utilization hour (h) :电厂的年平均运行小时数,需要注意多个机组可能共同属于一个电厂,有相同的utilization hour (h)
  4. coal consumption (g coal/KWh):每发一度电需要耗费多少煤炭,为成本参数
  5. power consumption rate:电厂单位时间内耗电量与发电量的百分比

image.png

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_

image.png 根据这个方程式,我们有:

  • 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]