Datawhale AI 夏令营 - 市场博弈和价格预测

基于第二届世界科学智能大赛社会科学赛道:市场博弈和价格预测

数据加载与预处理

base_path = Path("data")  # 确保数据都放在同级的data目录下

# 读取市场数据
electricity_price = pd.read_csv(base_path / "electricity price.csv")
# 读取市场主体(各发电机组)数据
unit = pd.read_csv(base_path / "unit.csv")

解析:

  • base_path = Path("data"): 定义了一个路径变量base_path指向"data"目录,确保所有的数据文件都位于这个目录下。
  • pd.read_csv(base_path / "electricity price.csv"): 使用pandasread_csv函数读取名为"electricity price.csv"的CSV文件,并将数据存储在名为electricity_price的DataFrame对象中。
  • pd.read_csv(base_path / "unit.csv"): 类似地,读取名为"unit.csv"的CSV文件,并将数据存储在名为unit的DataFrame对象中。

知识点:

  • 路径操作: 使用pathlib.Path来处理文件路径,这提供了更现代和跨平台的方式来处理文件路径。
  • 数据加载: pandas库中的read_csv函数用于加载CSV文件中的数据,并将其转换为DataFrame对象,便于后续的数据处理和分析。

创建示例提交文件

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)

解析:

  • electricity_price["clearing price (CNY/MWh)"].isna(): 选择electricity_priceDataFrame中"clearing price (CNY/MWh)"列中值为NaN(缺失值)的行。
  • .drop(columns="demand"): 删除这些行中的"demand"列。
  • sample_submit.to_csv(base_path / "sample_submit.csv", index=False): 将处理后的DataFrame保存为CSV文件,文件名为"sample_submit.csv",并且不包含索引列。

知识点:

  • 缺失值处理: 使用isna()函数来选择缺失值,这对于电力市场的预测任务很重要,因为我们需要预测缺失的出清价格。
  • 数据子集: 通过.drop(columns="demand")选择DataFrame的子集,删除不需要的列。
  • CSV文件保存: 使用to_csv函数保存DataFrame为CSV文件,这是一个常见的数据输出方式。

时间特征处理

electricity_price["timestamp"] = pd.to_datetime(
    electricity_price["day"] + " " + electricity_price["time"].str.replace("24: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)
electricity_price = electricity_price[["timestamp", "demand", "clearing price (CNY/MWh)"]]

解析:

  • pd.to_datetime(electricity_price["day"] + " " + electricity_price["time"].str.replace("24:00:00", "00:00")): 将"day"和"time"列合并成一个时间戳格式的列,同时将"24:00:00"替换为"00:00",以确保时间戳的正确性。
  • mask = electricity_price['timestamp'].dt.time == pd.Timestamp('00:00:00').time(): 创建一个布尔掩码,用于标识那些时间戳为"00:00:00"的行。
  • electricity_price.loc[mask, 'timestamp'] += pd.Timedelta(days=1): 对于所有时间戳为"00:00:00"的行,将时间戳增加一天。
  • electricity_price = electricity_price[["timestamp", "demand", "clearing price (CNY/MWh)"]]: 重新组织DataFrame,只保留"timestamp"、"demand"和"clearing price (CNY/MWh)"这三列。

知识点:

  • 时间戳转换: 使用pd.to_datetime函数将日期和时间字符串转换为时间戳格式,这对于时间序列分析至关重要。
  • 时间处理: 使用pd.Timestamppd.Timedelta处理特殊时间点(如"24:00:00"),确保时间连续性。
  • DataFrame列选择: 使用DataFrame的列名选择特定的列,这是数据清洗和预处理中的常见操作。

特征构造与排序

sorted_unit = unit.sort_values("coal consumption (g coal/KWh)")
sorted_unit['cumulative_capacity'] = sorted_unit['Capacity(MW)'].cumsum()

解析:

  • unit.sort_values("coal consumption (g coal/KWh)"): 按照"coal consumption (g coal/KWh)"列的值对unitDataFrame进行升序排序。
  • sorted_unit['cumulative_capacity'] = sorted_unit['Capacity(MW)'].cumsum(): 计算累积容量,即将"Capacity(MW)"列的值进行累加,得到每个发电机组累计的容量。

知识点:

  • 排序: 使用sort_values函数对DataFrame进行排序,这对于电力市场的分析非常重要,因为出清价格通常与发电成本有关。
  • 累积和: 使用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)

解析:

  • 循环遍历electricity_priceDataFrame中的"demand"`列:
    • sorted_unit[sorted_unit['cumulative_capacity'] >= demand]: 对于每个需求值,找到能够满足该需求的最小累积容量的发电机组。
    • ["coal consumption (g coal/KWh)"].iloc[0]: 获取第一个满足条件的发电机组的耗煤量,作为该需求水平下的价格。
    • prices.append(price): 将计算出的价格添加到prices列表中。

知识点:

  • 需求匹配: 通过遍历电力需求,找到能够满足该需求的最小耗煤量发电机组,将其耗煤量作为价格。这一步骤利用了电力市场的基本原理之一:边际成本定价。
  • 循环: 使用Python的for循环来迭代DataFrame中的行,这是一种常见的数据处理技术。

模型训练与预测

from sklearn.ensemble import GradientBoostingRegressor

model = GradientBoostingRegressor(
    n_estimators=100, learning_rate=0.1, random_state=42)

model.fit(X, y)

解析:

  • from sklearn.ensemble import GradientBoostingRegressor: 导入GradientBoostingRegressor类,这是Scikit-Learn库中的一个梯度提升回归器模型,比原版的线性回归更有效。
  • 初始化模型:
    • n_estimators=100: 指定模型中决策树的数量为100。
    • learning_rate=0.1: 指定模型的学习率为0.1,这影响了每次迭代时模型更新的程度。
    • random_state=42: 设置随机种子为42,以确保结果的可重复性。
  • model.fit(X, y): 使用X(特征矩阵)和y(目标向量)来训练模型。

知识点:

  • 梯度提升回归算法: 一种机器学习模型,可以捕捉复杂的关系,并且不需要复杂的特征工程。它通过构建多个弱学习器(通常是决策树)并结合它们的结果来提高整体预测性能。
    梯度提升回归树(Gradient Boosting Regression Trees,简称GBRT或GBR)是一种迭代的回归算法,属于集成学习方法,主要用于解决回归问题。它通过构建一系列的弱学习器(通常是决策树),然后将这些弱学习器组合起来形成一个强学习器。GBRT的工作原理是基于梯度下降的概念,它通过最小化损失函数的梯度来构建每棵树,以逐渐减小预测误差。-

  • 算法流程如下:

    假设我们有一个损失函数 L ( y , F ( x ) ) L(y, F(x)) L(y,F(x)),其中 y y y是真实值, F ( x ) F(x) F(x)是模型的预测值。GBRT的目标是最小化损失函数的期望值。

在第(m)轮迭代中,我们已经有了一组弱学习器 { T 1 ( x ) , T 2 ( x ) , … , T m − 1 ( x ) } \{T_1(x), T_2(x), \ldots, T_{m-1}(x)\} {T1(x),T2(x),,Tm1(x)},并构建了预测函数 F ( m − 1 ) ( x ) = ∑ k = 1 m − 1 γ k T k ( x ) F^{(m-1)}(x) = \sum_{k=1}^{m-1} \gamma_k T_k(x) F(m1)(x)=k=1m1γkTk(x),其中 γ k \gamma_k γk是每个弱学习器的权重。

在第(m)轮,我们想要找到一个新的弱学习器 T m ( x ) T_m(x) Tm(x)和权重 γ m \gamma_m γm,使得损失函数 L ( y , F ( m ) ( x ) ) L(y, F^{(m)}(x)) L(y,F(m)(x))最小化,其中 F ( m ) ( x ) = F ( m − 1 ) ( x ) + γ m T m ( x ) F^{(m)}(x) = F^{(m-1)}(x) + \gamma_m T_m(x) F(m)(x)=F(m1)(x)+γmTm(x)

为了找到 T m ( x ) T_m(x) Tm(x) γ m \gamma_m γm,我们使用梯度下降的思想。具体来说,我们找到一个函数 h m ( x ) h_m(x) hm(x)来近似损失函数关于 F ( m − 1 ) ( x ) F^{(m-1)}(x) F(m1)(x)的负梯度:

h m ( x ) ≈ − [ ∂ L ( y i , F ( x i ) ) ∂ F ( x i ) ] F ( x ) = F ( m − 1 ) ( x ) h_m(x) \approx -\left[\frac{\partial L(y_i, F(x_i))}{\partial F(x_i)}\right]_{F(x)=F^{(m-1)}(x)} hm(x)[F(xi)L(yi,F(xi))]F(x)=F(m1)(x)
然后,我们将 h m ( x ) h_m(x) hm(x)作为目标来构建决策树 T m ( x ) T_m(x) Tm(x)。一旦 T m ( x ) T_m(x) Tm(x)构建完成,我们可以通过线性搜索找到最佳的 γ m \gamma_m γm,使得 L ( y , F ( m ) ( x ) ) L(y, F^{(m)}(x)) L(y,F(m)(x))最小化。

最终的预测函数为:

F ( x ) = F ( 0 ) ( x ) + ∑ m = 1 M γ m T m ( x ) F(x) = F^{(0)}(x) + \sum_{m=1}^M \gamma_m T_m(x) F(x)=F(0)(x)+m=1MγmTm(x)

其中 F ( 0 ) ( x ) F^{(0)}(x) F(0)(x)是初始预测值, M M M是弱学习器的总数。

  • 模型参数: n_estimatorslearning_raterandom_state是梯度提升回归器的重要参数,它们决定了模型的复杂性和随机性。
  • 模型训练: 使用fit方法来训练模型,这是机器学习中常见的步骤。

预测与结果输出

y_pred = model.predict(prices[train_length:])
y_pred = y_pred.flatten()
sample_submit["clearing price (CNY/MWh)"] = y_pred
sample_submit.head()
sample_submit.to_csv("submit.csv", index=False)

解析:

  • model.predict(prices[train_length:]): 使用训练好的模型对测试集中的数据进行预测。
  • y_pred.flatten(): 将预测结果转换为一维数组。
  • sample_submit["clearing price (CNY/MWh)"] = y_pred: 将预测的价格添加到samples_submit数据框中。
  • sample_submit.head(): 显示samples_submit数据框的前几行。
  • sample_submit.to_csv("submit.csv", index=False): 将samples_submit数据框保存为CSV文件,文件名为"submit.csv",并且不包含索引列。

知识点:

  • 模型预测: 使用训练好的模型对新的数据进行预测,这是机器学习的核心应用之一。
  • 结果输出: 使用to_csv函数将预测结果保存为CSV文件,以便提交给比赛平台。
  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值