2025.3.9机器学习笔记:文献阅读

2025.3.9周报

  • 一、文献阅读
    • 题目信息
    • 摘要
    • Abstract
    • 创新点
    • 网络架构
    • 实验
    • 结论
    • 不足以及展望

一、文献阅读

题目信息

  • 题目: Time-series generative adversarial networks for flood forecasting
  • 期刊: Journal of Hydrology
  • 作者: Peiyao Weng, Yu Tian, Yingfei Liu, Ying Zheng
  • 发表时间: 2023/5/20
  • 文章链接: https://www.sciencedirect.com/science/article/pii/S0022169423006443?via%3Dihub

摘要

洪水每年对全世界造成了巨大的损失,有效的洪水预警是重要防洪方式,但是现有洪水预测方法并不可靠,比如,传统的物理计算方法和数据驱动模型需大量水文和地貌数据,又因为极端洪水事件观测数据有限,这会导致模型的预测不准确。本论文基于时间序列GANs,探究其在洪水时间序列生成及预报中的作用,利用时间序列生成对抗网络进行洪水预测,应用TimeGAN和RTSGAN生成合成洪水时间序列。以中国西江流域为例,实验结果表明TimeGAN能准确高效模拟多站点洪水序列的时空相关性,RTSGAN在长序列时表现更优,且合成数据集可减少常规深度学习模型的预测误差。这种方法为解决洪水预报中数据稀缺问题提供了新思路,对提升洪水预报具有重要作用,有助于减少洪水造成的损失。

Abstract

Floods cause substantial losses worldwide each year, making effective flood warning systems a critical component of flood prevention. However, existing flood prediction methods are often unreliable. For instance, traditional physically-based computational approaches and data-driven models require extensive hydrological and geomorphological data. Moreover, the limited availability of observational data for extreme flood events often leads to inaccurate predictions. This paper investigates the application of time series Generative Adversarial Networks (GANs) in generating and forecasting flood time series. Specifically, we employ TimeGAN and RTSGAN to produce synthetic flood time series data. Using the Xijiang River Basin in China as a case study, experimental results demonstrate that TimeGAN can accurately and efficiently simulate the spatiotemporal correlations of multi-site flood sequences. RTSGAN, on the other hand, exhibits superior performance for longer sequences. Furthermore, the synthetic datasets generated by these models can reduce prediction errors in conventional deep learning approaches. This methodology offers a novel solution to the challenge of data scarcity in flood forecasting, significantly enhancing flood prediction accuracy and contributing to the mitigation of flood-related damages.

创新点

作者首次将时间序列GANs应用于洪水时间序列生成中,以提升洪水预报模型精度,其利用历史序列数据生成新数据,且无需预处理,生成的序列保留原始时间特征。

网络架构

在论文第3.1节“Flood generating model”中,提到在生成合成洪水数据之前,需要对原始洪水时间序列进行预处理。数据为洪水时间序列,包含多个洪水事件𝑘,特征维度 𝑛,时间步长𝑚,窗口大小𝑤,序列长度𝐿。将原始洪水时间序列通过滑动窗口的方式分割成三维数据,其表示为: [ ∑ i = 1 k ( L i − w + 1 ) , n , w ] [\sum_{i=1}^{k}\left(L_{i}-w+1\right), n, w] [i=1k(Liw+1),n,w]
窗口大小w决定每次处理的数据长度,论文中将小时尺度定为48小时每3小时一个时间步,则分为16个时间步;日尺度则为9天,则分为9个时间步;
论文中“the sliding step 𝑚 is set to 1”,将步长m设为1,表示窗口每次滑动1个时间步,生成重叠窗口。
举个例子:对于第𝑖个洪水事件,时间序列长度为 L i L_i Li,设 L i = 100 L_i = 100 Li=100(洪水持续了100个小事),窗口大小w=16,步长m=1,有三个特征,即n=3。
则第一个窗口时间步1到16;第二个窗口时间步2到17;最后一个窗口时间步85到100。​
总窗口数则为100−16+1=85,且一个窗口是一个二维矩阵[n,w]。
所以这个三维矩阵表达为: [ ∑ i = 1 k ( L i − w + 1 ) , n , w ] [\sum_{i=1}^{k}\left(L_{i}-w+1\right), n, w] [i=1k(Liw+1),n,w] = [85,3,16]
在这里插入图片描述
TimeGAN包含嵌入函数、恢复函数、序列生成器和序列鉴别器的生成模型,通过有监督损失和无监督损失的学习嵌入空间对抗性和联合训练,让模型得以同时学习编码特征、生成表示和跨时间迭代。有关于TimeGAN的知识点,我在之前的博客记录过,这里就不再赘述了,大家需要的话可以点击这个链接查看:https://blog.csdn.net/Zcymatics/article/details/145011621?spm=1001.2014.3001.5501
在这里插入图片描述
接下来我们详细分析一下作者提到的RTSGAN,其全称为“Recurrent Time-Series Generative Adversarial Network”,它是TimeGAN的改进版本,专门用于生成高质量时间序列数据。
其核心是通过结合WGAN 和自回归解码器,克服了传统TimeGAN在长序列生成中的不稳定性和长序列信息捕捉能力弱问题。
传统GAN使用的是JS散度或KL散度优化生成分布与真实分布的相似性。想要了解GAN可以去我这篇博客看一下原理:https://blog.csdn.net/Zcymatics/article/details/145011685?spm=1001.2014.3001.5501
而WGAN使用Wasserstein距离替代JS散度,减少模式崩塌,提高训练稳定性。

模型坍塌是指模型在训练过程中逐渐失去多样性和泛化能力,导致性能严重退化甚至无法继续优化。

在这里插入图片描述
其损失函数被定义为: L = E r ∼ P r [ D ( r ) ] − E r ^ ∼ P g [ D ( r ^ ) ] L=E_{r \sim P_{r}}[D(r)]-E_{\hat{r} \sim P_{g}}[D(\hat{r})] L=ErPr[D(r)]Er^Pg[D(r^)]
D是判别器 E r ∼ P r [ D ( r ) ] E_{r \sim P_{r}}[D(r)] ErPr[D(r)]是真实样本𝑟通过𝐷的期望输出; E r ^ ∼ P g [ D ( r ^ ) ] E_{\hat{r} \sim P_{g}}[D(\hat{r})] Er^Pg[D(r^)]合成样本 r ^ \hat{r} r^通过𝐷的期望输出。

说完了Wasserstein距离,下面来说一下RTSGAN的另一个改进点:
自回归编码器
TimeGAN中,使用的是嵌入函数和恢复函数完成。其嵌入函数是逐时间步生成潜在序列𝐻,每个时间步都有一个对应的潜在表示 h t h_t ht ;其恢复函数从整个潜在序列𝐻一次性生成重建序列 X ^ \hat X X^
RTSGAN中使用的则是自回归编码器和解码器。编码器同样负责将时间序列X映射到潜在空间,但其目标是生成一个固定维度的潜在表示𝑟,而不是逐时间步的潜在序列𝐻;其解码器从潜在表示逐步生成时间序列(不是一次性输出),采用自回归方式生成每个时间步的输出。
TimeGAN的一次性生成会导致长序列的时间相关性可能被削弱。RTSGAN中自回归解码器通过逐步生成的方式学习时间依赖性,每一步的生成依赖于前一步的输出,更加能够捕捉时间动态变化。
在这里插入图片描述
下图是论文工作的总体的流程图:
首先数据经过预处理后给TimeGAN和RTSGAN生成数据,然后真实的训练数据和生成数据进入滑动窗口。滑动窗口将真实和合成数据分割成两个部分,为监督学习提供数据,真实数据为covariates,如 x t − 2 1 , x t − 2 2 , x t − 2 3 x_{t-2}^1, x_{t-2}^2, x_{t-2}^3 xt21,xt22,xt23,绿色框为GAN生成数据y,如 y t y_t yt,每个实例包含输入和输出。这些数据对供GBRT和LSTM训练。最后两个预测模型输出预测值与真实值对比,得出评估指标。
在这里插入图片描述

实验

本文围绕时间序列生成对抗网络在洪水预测中的应用展开实验,
论文的评价指标如下图所示,其中比较陌生的有:
1、皮尔逊相关系数,其用于衡量预测值与观测值的线性相关性,值越大越好(最大值为1):
O C = ∑ i = 1 n ( F i − F ˉ ) ( O i − O ˉ ) ∑ i = 1 n ( F i − F ˉ ) 2 ∑ i = 1 n ( O i − O ˉ ) 2 O C=\frac{\sum_{i=1}^n\left(F_i-\bar{F}\right)\left(O_i-\bar{O}\right)}{\sqrt{\sum_{i=1}^n\left(F_i-\bar{F}\right)^2} \sqrt{\sum_{i=1}^n\left(O_i-\bar{O}\right)^2}} OC=i=1n(FiFˉ)2 i=1n(OiOˉ)2 i=1n(FiFˉ)(OiOˉ)
F i F_i Fi为预测值; O i O_i Oi为观测值; F ˉ \bar{F} Fˉ O ˉ \bar{O} Oˉ分别为预测和观测均值。
2、平均绝对相对误差,计算预测值与观测值的相对偏差,值越小越好(0为最小值):
A A R E = 1 n ∑ i = 1 n ∣ F i p − O i p O i p ∣ A A R E=\frac{1}{n} \sum_{i=1}^n\left|\frac{F_i^p-O_i^p}{O_i^p}\right| AARE=n1i=1n OipFipOip
𝑛为样本数; F i p F_i^p Fip为预测值; O i p O_i^p Oip为观测值。
3、预测区间覆盖概率,衡量观测值落入预测区间的比例,最佳值为1:
P I C P = 1 n ∑ i = 1 n ε i , ε i = 1 P I C P=\frac{1}{n} \sum_{i=1}^n \varepsilon_i, \quad \varepsilon_i=1 PICP=n1i=1nεi,εi=1 if O i ∈ [ L i , U i ] O_i \in\left[L_i, U_i\right] Oi[Li,Ui], else 0
L i L_i Li U i U_i Ui为预测区间的上下界。
4、预测区间归一化平均宽度,评估预测区间的宽度,最佳值为0:
P I N A W = 1 n R ∑ i = 1 n ( U i − L i ) , R = max ⁡ ( O i ) − min ⁡ ( O i ) PINAW =\frac{1}{n R} \sum_{i=1}^n\left(U_i-L_i\right), \quad R=\max \left(O_i\right)-\min \left(O_i\right) PINAW=nR1i=1n(UiLi),R=max(Oi)min(Oi)
R为观测值范围;
5、覆盖宽度综合准则,平衡覆盖率和区间宽度,PICP低于𝜇时施加指数惩罚,0为最佳值:
C W C = P I N A W ( 1 + γ e η ( μ − P I C P ) ) , γ ( P I C P ) = 1 C W C=P I N A W\left(1+\gamma e^{\eta(\mu-P I C P)}\right), \quad \gamma(P I C P)=1 CWC=PINAW(1+γeη(μPICP)),γ(PICP)=1 if P I C P < μ P I C P<\mu PICP<μ, else 0
μ为期望覆盖率;𝜂为惩罚系数;
在这里插入图片描述
结果如下:
论文通过二维t-SNE和PCA两种降维方法对原始洪水时间序列、TimeGAN生成的合成序列以及RTSGAN生成的合成序列进行了可视化分析。结果表明,RTSGAN生成的合成序列在分布上与原始数据集更为接近,表现为数据点簇的形状和密度更贴近原始数据,而TimeGAN生成的序列分布则稍显分散,偏离原始数据的特征。此外,RTSGAN生成的数据点不仅更集中,还展现出更高的多样性。
在这里插入图片描述
图6通过热图形式展示了原始数据集、TimeGAN和RTSGAN生成序列在不同时间滞后 𝜏 下的时间相关性对比。热图中,颜色深浅表示相关系数的大小,RTSGAN的热图模式与原始数据高度一致,尤其是在日尺度上,梧州站点的合成序列时间相关系数几乎完全重合原始数据。这表明RTSGAN能够精确再现洪水序列的时间依赖性,例如洪峰的到达时间和衰退过程。
在小时尺度上,由于时间步长更小,序列长度增加,对模型捕捉长期依赖性的要求更高。RTSGAN依然表现出色,其热图显示的空间相关性和时间相关性均优于TimeGAN。这可能是由于RTSGAN的自回归解码器设计,能够逐步生成序列并保留长期依赖。RTSGAN训练时间更短。
在这里插入图片描述
在多时间步预测任务中,论文比较了GBRT、LSTM、QRLSTM等模型的性能,图7展示了日尺度下各模型在T、T+1、T+2的评估指标箱线图,包括OC、AARE等。结果显示,LSTM在所有预测步长中的OC最高,AARE最低,且随着预测期从T到T+2增加,其优势逐渐扩大。例如,箱线图中LSTM的中位数OC值可能接近1,离群点较少,而其他模型的OC分布更分散,AARE更高。LSTM“三门”机制使LSTM能够有效捕捉洪水时间序列中的长期依赖关系。相比之下,GBRT基于窗口的特征提取更适合短期依赖,而QRLSTM在不确定性预测上虽有优势,但在点预测准确性上不如标准LSTM。
在这里插入图片描述
RTSGAN生成的合成数据集能显著提升基于窗口的GBRT模型性能,尤其在较长预测期。在24小时预测中,GBRT - RTSGAN在CC和NSE指标上分别比GBRT高2.08%和6.74%,RMSE降低,AARE减少56.52%。而TimeGAN对GBRT的改进效果有限且不稳定,其合成训练集甚至会导致误差范围增大。合成数据集对LSTM的有效性随预测期增加而急剧下降。
在这里插入图片描述
SHAP分析用于解释模型预测中各特征的重要性,通过SHAP分析发现,GBRT和GBRT - RTSGAN模型使用几乎相同的影响因素进行预测,且形状值模式趋势一致;而GBRT - TimeGAN从T + 5步开始与GBRT的形状值模式差异较大。
在这里插入图片描述
引入合成训练数据集可帮助QRLSTM模型获得更低的PINAW,但会降PICP,只有少数情况能在保持区间覆盖的同时减小区间宽度。图12结果显示,使用RTSGAN或TimeGAN的合成数据后,QRLSTM的PINAW降低,例如从0.15降至0.10,表明预测区间更窄、更精确。但是PICP从0.95降至0.85,说明部分观测值未被区间覆盖。这种权衡表明合成数据增强了模型的准确性,但牺牲了覆盖率。只有少数情况实现了PINAW降低的同时保持PICP接0.9。
随着合成数据集数量增加,PINAW和PICP降低,模型的CWC下降。RTSGAN对PINAW的影响更大,表明可通过调节假样本数量使预测区间更灵活、易调整。尽管合成训练集在QRLSTM中表现不佳,但在洪水峰值处较窄的预测区间是可取的。
在这里插入图片描述

代码如下:

import numpy as np  
import torch  
import torch.nn as nn  
import torch.optim as optim  # 导入PyTorch的优化器模块
from sklearn.ensemble import GradientBoostingRegressor  # 导入sklearn的GBRT模型
from sklearn.metrics import mean_squared_error  # 导入sklearn的均方误差计算函数
import matplotlib.pyplot as plt  # 设置随机种子,确保结果可重复
np.random.seed(42)
torch.manual_seed(42)# 定义数据参数
n_samples = 1755  # 样本数量,参考论文小时尺度数据
n_features = 3  # 特征数量(假设流量、降雨量等)
seq_len = 16  # 序列长度(窗口大小,48小时,每3小时一个时间步)# 生成模拟洪水时间序列数据,假设数据服从正弦波+噪声的形式
time_steps = np.arange(seq_len)  # 创建时间步数组
data = np.zeros((n_samples, seq_len, n_features))  # 初始化数据数组
for i in range(n_samples):for f in range(n_features):# 生成正弦波数据,模拟周期性洪水特征data[i, :, f] = np.sin(0.1 * time_steps + np.random.uniform(0, 2 * np.pi)) + np.random.normal(0, 0.1, seq_len)# 将数据转换为PyTorch张量
data = torch.FloatTensor(data)  # 转换为浮点张量,形状为[n_samples, seq_len, n_features]# 定义GRU网络类,作为TimeGAN的基础模块
class GRU(nn.Module):def __init__(self, input_dim, hidden_dim, num_layers):super(GRU, self).__init__()self.hidden_dim = hidden_dim  # 设置隐藏层维度self.num_layers = num_layers  # 设置GRU层数self.gru = nn.GRU(input_dim, hidden_dim, num_layers, batch_first=True)  # 定义GRU层def forward(self, x):# 初始化隐藏状态h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_dim).to(x.device)# 前向传播out, _ = self.gru(x, h0)return out# 定义TimeGAN模型
class TimeGAN(nn.Module):def __init__(self, input_dim, hidden_dim, num_layers):super(TimeGAN, self).__init__()self.hidden_dim = hidden_dim  # 设置隐藏层维度self.input_dim = input_dim  # 设置输入维度# 嵌入函数(Embedding Function)self.embedder = GRU(input_dim, hidden_dim, num_layers)  # 定义嵌入函数,使用GRU网络# 恢复函数(Recovery Function)self.recovery = nn.Sequential(nn.Linear(hidden_dim, input_dim),  # 线性层,将隐藏状态映射回输入维度nn.Sigmoid()  # Sigmoid激活,确保输出在[0, 1]范围内)# 生成器(Generator)self.generator = GRU(hidden_dim, hidden_dim, num_layers)  # 定义生成器,使用GRU网络self.gen_output = nn.Linear(hidden_dim, hidden_dim)  # 线性层,生成潜在表示# 判别器(Discriminator)self.discriminator = GRU(hidden_dim, hidden_dim, num_layers)  # 定义判别器,使用GRU网络self.dis_output = nn.Linear(hidden_dim, 1)  # 线性层,输出判别结果def forward(self, x):# 嵌入:将输入数据映射到潜在空间h = self.embedder(x)  # 通过嵌入函数生成潜在表示h# 恢复:从潜在空间重建输入数据x_tilde = self.recovery(h)  # 通过恢复函数重建数据return h, x_tildedef generate(self, z):# 生成器:从噪声生成潜在表示h_hat = self.generator(z)  # 通过生成器生成潜在表示h_hat = self.gen_output(h_hat)  # 映射到潜在空间# 恢复:从生成的潜在表示生成数据x_hat = self.recovery(h_hat)  # 通过恢复函数生成合成数据return x_hat# 设置模型参数
input_dim = n_features  # 输入维度(特征数)
hidden_dim = 24  # 隐藏层维度,参考论文中的设置
num_layers = 3  # GRU层数# 初始化TimeGAN模型
timegan = TimeGAN(input_dim, hidden_dim, num_layers)# 定义损失函数
mse_loss = nn.MSELoss()  # 均方误差损失,用于自编码和监督损失
bce_loss = nn.BCEWithLogitsLoss()  # 二元交叉熵损失,用于对抗损失# 定义优化器
optimizer_E = optim.Adam(list(timegan.embedder.parameters()) + list(timegan.recovery.parameters()), lr=0.001)  # 嵌入和恢复优化器
optimizer_G = optim.Adam(list(timegan.generator.parameters()) + list(timegan.gen_output.parameters()), lr=0.001)  # 生成器优化器
optimizer_D = optim.Adam(list(timegan.discriminator.parameters()) + list(timegan.dis_output.parameters()), lr=0.001)  # 判别器优化器# 训练TimeGAN
num_epochs = 100  # 训练轮数
batch_size = 128  # 批次大小
for epoch in range(num_epochs):for i in range(0, n_samples, batch_size):# 获取批次数据batch_data = data[i:i + batch_size].cuda() if torch.cuda.is_available() else data[i:i + batch_size]# 训练嵌入和恢复(自编码损失)optimizer_E.zero_grad()  # 清零梯度h, x_tilde = timegan(batch_data)  # 前向传播,得到潜在表示和重建数据recon_loss = mse_loss(x_tilde, batch_data)  # 计算自编码损失recon_loss.backward()  # 反向传播optimizer_E.step()  # 更新参数# 训练判别器optimizer_D.zero_grad()  # 清零梯度real_h = timegan.embedder(batch_data)  # 嵌入真实数据real_logit = timegan.dis_output(timegan.discriminator(real_h))  # 判别真实数据z = torch.randn(batch_size, seq_len, hidden_dim)  # 生成随机噪声fake_x = timegan.generate(z)  # 生成合成数据fake_h = timegan.embedder(fake_x)  # 嵌入合成数据fake_logit = timegan.dis_output(timegan.discriminator(fake_h))  # 判别合成数据d_loss = bce_loss(real_logit, torch.ones_like(real_logit)) + bce_loss(fake_logit, torch.zeros_like(fake_logit))  # 计算判别器损失d_loss.backward()  # 反向传播optimizer_D.step()  # 更新参数# 训练生成器optimizer_G.zero_grad()  # 清零梯度z = torch.randn(batch_size, seq_len, hidden_dim)  # 生成随机噪声fake_x = timegan.generate(z)  # 生成合成数据fake_h = timegan.embedder(fake_x)  # 嵌入合成数据fake_logit = timegan.dis_output(timegan.discriminator(fake_h))  # 判别合成数据g_loss = bce_loss(fake_logit, torch.ones_like(fake_logit))  # 计算生成器对抗损失# 计算监督损失(使用真实数据监督生成器)supervised_loss = mse_loss(fake_x[:, 1:, :], fake_x[:, :-1, :])  # 监督损失:预测下一步total_g_loss = g_loss + 0.1 * supervised_loss  # 总生成器损失(对抗损失+监督损失)total_g_loss.backward()  # 反向传播optimizer_G.step()  # 更新参数# 打印损失if (epoch + 1) % 10 == 0:print(f"Epoch {epoch+1}/{num_epochs}, Recon Loss: {recon_loss.item():.4f}, D Loss: {d_loss.item():.4f}, G Loss: {total_g_loss.item():.4f}")# 生成合成数据
with torch.no_grad():z = torch.randn(n_samples, seq_len, hidden_dim)  # 生成随机噪声synthetic_data_timegan = timegan.generate(z)  # 生成合成数据
synthetic_data_timegan = synthetic_data_timegan.cpu().numpy()  # 转换为numpy数组# 定义RTSGAN模型
class RTSGAN(nn.Module):def __init__(self, input_dim, hidden_dim, num_layers):super(RTSGAN, self).__init__()self.hidden_dim = hidden_dim  # 设置隐藏层维度self.input_dim = input_dim  # 设置输入维度# 自回归编码器(Autoregressive Encoder)self.encoder = GRU(input_dim, hidden_dim, num_layers)  # 定义编码器,使用GRU网络self.encoder_output = nn.Linear(hidden_dim * seq_len, hidden_dim)  # 线性层,压缩为固定维度潜在表示# 自回归解码器(Autoregressive Decoder)self.decoder = GRU(input_dim, hidden_dim, num_layers)  # 定义解码器,使用GRU网络self.decoder_output = nn.Linear(hidden_dim, input_dim)  # 线性层,生成输出数据# 判别器(Critic for WGAN)self.critic = GRU(hidden_dim, hidden_dim, num_layers)  # 定义判别器,使用GRU网络self.critic_output = nn.Linear(hidden_dim, 1)  # 线性层,输出Wasserstein距离def encode(self, x):# 编码:将输入序列压缩为固定维度潜在表示h = self.encoder(x)  # 通过编码器生成隐藏状态h = h.reshape(h.size(0), -1)  # 展平隐藏状态r = self.encoder_output(h)  # 压缩为固定维度潜在表示return rdef decode(self, r):# 解码:从潜在表示生成序列batch_size = r.size(0)  # 获取批次大小# 初始化解码器输入x_hat = torch.zeros(batch_size, seq_len, self.input_dim).to(r.device)  # 初始化生成序列h = r.unsqueeze(1).repeat(1, seq_len, 1)  # 将潜在表示扩展到序列长度# 自回归解码for t in range(seq_len):h_t = self.decoder(x_hat[:, :t+1, :])[:, -1, :]  # 获取当前时间步的隐藏状态x_hat[:, t, :] = self.decoder_output(h_t)  # 生成当前时间步的输出return x_hatdef forward(self, x):# 前向传播:编码+解码r = self.encode(x)  # 编码x_tilde = self.decode(r)  # 解码return r, x_tilde# 初始化RTSGAN模型
rtsgan = RTSGAN(input_dim, hidden_dim, num_layers)# 定义优化器
optimizer_E = optim.Adam(list(rtsgan.encoder.parameters()) + list(rtsgan.decoder.parameters()), lr=0.001)  # 编码器和解码器优化器
optimizer_G = optim.Adam(list(rtsgan.decoder.parameters()), lr=0.001)  # 生成器优化器
optimizer_C = optim.Adam(list(rtsgan.critic.parameters()) + list(rtsgan.critic_output.parameters()), lr=0.001)  # 判别器优化器# WGAN-GP的梯度惩罚
def gradient_penalty(critic, real, fake):alpha = torch.rand(real.size(0), 1, 1).to(real.device)  # 随机插值系数interpolates = alpha * real + (1 - alpha) * fake  # 插值数据interpolates.requires_grad_(True)  # 允许计算梯度critic_inter = critic(interpolates)  # 判别插值数据gradients = torch.autograd.grad(outputs=critic_inter, inputs=interpolates,grad_outputs=torch.ones_like(critic_inter),create_graph=True, retain_graph=True)[0]  # 计算梯度gradients = gradients.view(gradients.size(0), -1)  # 展平梯度gradient_norm = gradients.norm(2, dim=1)  # 计算梯度范数gp = ((gradient_norm - 1) ** 2).mean()  # 计算梯度惩罚return gp# 训练RTSGAN
lambda_gp = 10  # 梯度惩罚系数,参考论文
for epoch in range(num_epochs):for i in range(0, n_samples, batch_size):# 获取批次数据batch_data = data[i:i + batch_size].cuda() if torch.cuda.is_available() else data[i:i + batch_size]# 训练编码器和解码器(自编码损失)optimizer_E.zero_grad()  # 清零梯度r, x_tilde = rtsgan(batch_data)  # 前向传播,得到潜在表示和重建数据recon_loss = mse_loss(x_tilde, batch_data)  # 计算自编码损失recon_loss.backward()  # 反向传播optimizer_E.step()  # 更新参数# 训练判别器(WGAN-GP)optimizer_C.zero_grad()  # 清零梯度real_r = rtsgan.encode(batch_data)  # 编码真实数据real_h = rtsgan.critic(real_r.unsqueeze(1).repeat(1, seq_len, 1))  # 判别真实数据real_score = rtsgan.critic_output(real_h)  # 计算真实数据得分z = torch.randn(batch_size, hidden_dim)  # 生成随机噪声fake_x = rtsgan.decode(z)  # 生成合成数据fake_r = rtsgan.encode(fake_x)  # 编码合成数据fake_h = rtsgan.critic(fake_r.unsqueeze(1).repeat(1, seq_len, 1))  # 判别合成数据fake_score = rtsgan.critic_output(fake_h)  # 计算合成数据得分gp = gradient_penalty(rtsgan.critic, real_r.unsqueeze(1).repeat(1, seq_len, 1), fake_r.unsqueeze(1).repeat(1, seq_len, 1))  # 计算梯度惩罚c_loss = fake_score.mean() - real_score.mean() + lambda_gp * gp  # WGAN-GP损失c_loss.backward()  # 反向传播optimizer_C.step()  # 更新参数# 训练生成器optimizer_G.zero_grad()  # 清零梯度z = torch.randn(batch_size, hidden_dim)  # 生成随机噪声fake_x = rtsgan.decode(z)  # 生成合成数据fake_r = rtsgan.encode(fake_x)  # 编码合成数据fake_h = rtsgan.critic(fake_r.unsqueeze(1).repeat(1, seq_len, 1))  # 判别合成数据fake_score = rtsgan.critic_output(fake_h)  # 计算合成数据得分g_loss = -fake_score.mean()  # 生成器损失(WGAN)g_loss.backward()  # 反向传播optimizer_G.step()  # 更新参数# 打印损失if (epoch + 1) % 10 == 0:print(f"Epoch {epoch+1}/{num_epochs}, Recon Loss: {recon_loss.item():.4f}, C Loss: {c_loss.item():.4f}, G Loss: {g_loss.item():.4f}")# 生成合成数据
with torch.no_grad():z = torch.randn(n_samples, hidden_dim)  # 生成随机噪声synthetic_data_rtsgan = rtsgan.decode(z)  # 生成合成数据
synthetic_data_rtsgan = synthetic_data_rtsgan.cpu().numpy()  # 转换为numpy数组# 准备监督学习数据
def prepare_supervised_data(data, window_size):inputs, targets = [], []  # 初始化输入和目标列表data = data.reshape(data.shape[0], -1)  # 展平数据,形状为[n_samples, seq_len * n_features]for i in range(len(data) - window_size):inputs.append(data[i:i + window_size].flatten())  # 提取输入窗口targets.append(data[i + window_size, -1])  # 提取目标(最后一个特征)return np.array(inputs), np.array(targets)# 准备真实数据和合成数据
window_size = 3  # 窗口大小,参考图4
real_inputs, real_targets = prepare_supervised_data(data.numpy(), window_size)  # 准备真实数据
syn_inputs_timegan, syn_targets_timegan = prepare_supervised_data(synthetic_data_timegan, window_size)  # 准备TimeGAN合成数据
syn_inputs_rtsgan, syn_targets_rtsgan = prepare_supervised_data(synthetic_data_rtsgan, window_size)  # 准备RTSGAN合成数据# 混合真实和合成数据
mixed_inputs = np.concatenate([real_inputs, syn_inputs_rtsgan], axis=0)  # 混合真实和RTSGAN数据
mixed_targets = np.concatenate([real_targets, syn_targets_rtsgan], axis=0)  # 混合目标# 训练GBRT模型
gbrt = GradientBoostingRegressor(n_estimators=100, random_state=42)  # 初始化GBRT模型
gbrt.fit(mixed_inputs, mixed_targets)  # 训练GBRT模型
gbrt_pred = gbrt.predict(real_inputs)  # 使用真实数据预测
gbrt_mse = mean_squared_error(real_targets, gbrt_pred)  # 计算均方误差
print(f"GBRT MSE: {gbrt_mse:.4f}")  # 打印均方误差# 定义LSTM模型
class LSTM(nn.Module):def __init__(self, input_dim, hidden_dim, num_layers):super(LSTM, self).__init__()self.lstm = nn.LSTM(input_dim, hidden_dim, num_layers, batch_first=True)  # 定义LSTM层self.fc = nn.Linear(hidden_dim, 1)  # 定义全连接层def forward(self, x):h0 = torch.zeros(num_layers, x.size(0), hidden_dim).to(x.device)  # 初始化隐藏状态c0 = torch.zeros(num_layers, x.size(0), hidden_dim).to(x.device)  # 初始化单元状态out, _ = self.lstm(x, (h0, c0))  # 前向传播out = self.fc(out[:, -1, :])  # 取最后一个时间步输出return out# 初始化LSTM模型
lstm = LSTM(input_dim=n_features * (window_size - 1), hidden_dim=hidden_dim, num_layers=num_layers)# 定义优化器和损失函数
optimizer = optim.Adam(lstm.parameters(), lr=0.001)  # 定义优化器
criterion = nn.MSELoss()  # 定义损失函数# 准备LSTM输入数据
lstm_inputs = torch.FloatTensor(mixed_inputs.reshape(-1, window_size - 1, n_features))  # 重塑输入数据
lstm_targets = torch.FloatTensor(mixed_targets)  # 转换目标数据# 训练LSTM模型
for epoch in range(num_epochs):optimizer.zero_grad()  # 清零梯度outputs = lstm(lstm_inputs)  # 前向传播loss = criterion(outputs.squeeze(), lstm_targets)  # 计算损失loss.backward()  # 反向传播optimizer.step()  # 更新参数if (epoch + 1) % 10 == 0:print(f"LSTM Epoch {epoch+1}/{num_epochs}, Loss: {loss.item():.4f}")  # 打印损失# 使用LSTM预测
with torch.no_grad():lstm_pred = lstm(torch.FloatTensor(real_inputs.reshape(-1, window_size - 1, n_features)))  # 预测
lstm_pred = lstm_pred.numpy()  # 转换为numpy数组
lstm_mse = mean_squared_error(real_targets, lstm_pred)  # 计算均方误差
print(f"LSTM MSE: {lstm_mse:.4f}")  # 打印均方误差# 可视化预测结果
plt.figure(figsize=(10, 5))  # 设置画布大小
plt.plot(real_targets[:100], label="True")  # 绘制真实值
plt.plot(gbrt_pred[:100], label="GBRT Pred")  # 绘制GBRT预测值
plt.plot(lstm_pred[:100], label="LSTM Pred")  # 绘制LSTM预测值
plt.legend()  # 显示图例
plt.title("Flood Forecasting Results")  # 设置标题
plt.show()  # 显示图像

结论

机器学习对洪水预报有着重要的作用,但极端洪水事件稀少、现场数据不足导致模型的性能并没有充分发挥出来。TimeGAN生成的数据能够保留洪水场景的复杂时空相关性,引入合成数据集也有助于提升机器学习预测精度。不过对LSTM的改进有限,TimeGAN对Transformer等深度学习模型的有效性也有待进一步探究。

不足以及展望

作者提出了本论文中的不足,作者认为TimeGAN对如LSTM等深度学习模型的改进效果有限,没有发挥出实际的作用。未建立TimeGAN损失函数与下游预报性能的关联性,缺乏了对用户自定义参数敏感性分析。
关于对论文未来的展望,作者提出后续实验可建立TimeGAN损失函数与下游预报性能的直接联系。还需要考虑将天气信息作为洪水预报模型的重要输入变量,以提供长周期预报。此外,需要进一步探索生成的洪水场景在洪水风险管理中的各种应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/29150.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字IC后端实现教程| Clock Gating相关clock tree案例解析

今天小编给大家分享几个跟时钟树综合&#xff0c;clock tree相关的典型问题。 数字IC后端设计实现之分段长clock tree经典案例 Q1:星主好&#xff0c;下面的图是通过duplicate icg来解setup违例的示意图。我没看懂这个 duplicate操作在cts阶段是怎么实现的&#xff0c;用什么…

K8S学习之基础十一:k8s中容器钩子

容器钩子 容器钩子分为post-start和pre-stop post-start&#xff1a;容器启动后执行的命令 pre-stop&#xff1a;容器关闭前执行的命令&#xff0c;可用于优雅关闭 # 分别定义两个钩子&#xff0c;启动pod后更新index.html&#xff0c;关闭pod前正常关闭服务 vi post-pre.…

RabbitMQ知识点

1.为什么需要消息队列&#xff1f; RabbitMQ体系结构 操作001&#xff1a;RabbitMQ安装 二、安装 # 拉取镜像 docker pull rabbitmq:3.13-management ​ # -d 参数&#xff1a;后台运行 Docker 容器 # --name 参数&#xff1a;设置容器名称 # -p 参数&#xff1a;映射端口号&…

HTML + CSS 题目

1.说说你对盒子模型的理解? 一、是什么 对一个文档进行布局的时候&#xff0c;浏览器渲染引擎会根据标准之一的css基础盒模型&#xff0c;将所有元素表示为一个个矩形的盒子。 一个盒子由四个部分组成: content&#xff0c;padding&#xff0c;border&#xff0c;margin 下…

利用Postman和Apipost进行API测试的实践与优化-动态参数

在实际的开发和测试工作中&#xff0c;完成一个API后对其进行简单的测试是一项至关重要的任务。在测试过程中&#xff0c;确保API返回的数据符合预期&#xff0c;不仅可以提高开发效率&#xff0c;还能帮助我们快速发现可能存在的问题。对于简单的API测试&#xff0c;诸如验证响…

【银河麒麟高级服务器操作系统实际案例分享】数据库资源重启现象分析及处理全过程

更多银河麒麟操作系统产品及技术讨论&#xff0c;欢迎加入银河麒麟操作系统官方论坛 https://forum.kylinos.cn 了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer…

C++ Primer 拷贝、赋值与销毁

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

Java面经

Java 知识点总结 1. 封装&#xff0c;继承和多态 封装&#xff1a; “高内聚&#xff0c;低耦合”&#xff0c;隐藏内部实现细节&#xff0c;只通过接口开放部分使用权限给外部。继承&#xff1a; 主要是提高代码复用性&#xff0c;通过子类继承父类&#xff0c;来增加功能扩…

常见的限流算法有哪些?

好的&#xff0c;关于这个问题&#xff0c;我会从几个方面来回答。 首先&#xff0c;限流算法是一种系统保护策略&#xff0c;主要是避免在流量高峰导致系统被压垮&#xff0c;造成系统不可用的问题。 常见的限流算法有 5 种。 1. &#xff08;如图&#xff09;计数器限流&a…

GitHub获取token

获取token clone代码 git clone https://$tokengithub.com/*****/*****.git

公司网络安全组织结构

&#x1f345; 点击文末小卡片 &#xff0c;免费获取网络安全全套资料&#xff0c;资料在手&#xff0c;涨薪更快 第17章 网络安全应急响应技术原理与应用 17.1 网络安全应急响应概述 居安思危&#xff0c;思则有备&#xff0c;有备无患。网络安全应急响应是针对潜在发生的网络…

《深度学习进阶》第7集:深度实战 通过训练一个智能体玩游戏 来洞察 强化学习(RL)与决策系统

深度学习进阶 | 第7集&#xff1a;深度实战 通过训练一个智能体玩游戏 来洞察 强化学习&#xff08;RL&#xff09;与决策系统 在深度学习的广阔领域中&#xff0c;强化学习&#xff08;Reinforcement Learning, RL&#xff09;是一种独特的范式&#xff0c;它通过智能体与环境…

【web前端开发】CSS--CSS简介及其编写位置(上)

1、CSS简介 &#xff08;1&#xff09;CSS的全称为&#xff1a;层叠式样式表&#xff08;Cascading Style Sheets&#xff09; &#xff08;2&#xff09;CSS也是一种标记语言&#xff0c;用于给HTML结构设置样式&#xff0c;例如&#xff1a;文字大小、颜色、元素宽度等等…

计算机视觉|Swin Transformer:视觉 Transformer 的新方向

一、引言 在计算机视觉领域的发展历程中&#xff0c;卷积神经网络&#xff08;CNN&#xff09; 长期占据主导地位。从早期的 LeNet 到后来的 AlexNet、VGGNet、ResNet 等&#xff0c;CNN 在图像分类、目标检测、语义分割等任务中取得了显著成果。然而&#xff0c;CNN 在捕捉全…

UE4 组件 (对话组件)

制作一个可以生成对话气泡&#xff0c;显示对话台词的简单组件。这个组件要的变量&#xff1a;台词&#xff08;外部传入&#xff09;。功能&#xff1a;开始对话&#xff08;生成气泡UI&#xff09; &#xff0c;结束对话。 一、对话组件创建 二、开始对话事件 1、注意这里获…

WPF高级 | WPF 应用程序部署与发布:确保顺利交付到用户手中

WPF高级 | WPF 应用程序部署与发布&#xff1a;确保顺利交付到用户手中 一、前言二、部署与发布基础概念2.1 部署的定义与目的2.2 发布的方式与渠道2.3 部署与发布的关键要素 三、WPF 应用程序打包3.1 使用 Visual Studio 自带的打包工具3.2 使用第三方打包工具 四、发布到不同…

Vue3自定义hooks

Vue3自定义hooks 什么是自定义hooks 把一个功能的所有数据和方法写到同一个ts文件里。 命名规范&#xff1a;useXxx&#xff0c;小驼峰。 在每一个hooks中&#xff0c;都可以写onMounted、computed等属性&#xff0c;互不干扰。 体现出了组合式AI的优势&#xff0c;一个功能的…

Win7重装不翻车!ISO镜像安全下载渠道+BIOS设置避雷手册

一、写在前面&#xff1a;为什么你需要这份教程&#xff1f; 当电脑频繁蓝屏、系统崩溃甚至无法开机时&#xff0c;重装系统可能是最后的救命稻草。但市面上的教程往往存在三大痛点&#xff1a; ⚠️ 镜像来源不明导致系统被植入后门 ⚠️ 启动盘制作失败反复折腾 ⚠️ 操作失…

DeepSeek大模型 —— 全维度技术解析

DeepSeek大模型 —— 全维度技术解析 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff01;点我试试&#xff01;&#xff01; 文章目录 DeepSeek大模型 —— 全维度技术解析一、模型架构全景解析1.1…

AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型(LLM)应用开发平台

AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型&#xff08;LLM&#xff09;应用开发平台 目录 AGI 之 【Dify】 之 使用 Docker 在 Windows 端本地部署 Dify 大语言模型&#xff08;LLM&#xff09;应用开发平台 一、简单介绍 二、Docker 下载安…