当前位置: 首页 > news >正文

2025.2.16机器学习笔记:TimeGan文献阅读

2025.2.9周报

  • 一、文献阅读
    • 题目信息
    • 摘要
    • Abstract
    • 创新点
    • 网络架构
      • 一、嵌入函数
      • 二、恢复函数
      • 三、序列生成器
      • 四、序列判别器
      • 损失函数
    • 实验
    • 结论
    • 后续展望

一、文献阅读

题目信息

  • 题目: Time-series Generative Adversarial Networks
  • 会议: Neural Information Processing Systems (NeurIPS)
  • 作者: Jinsung Yoon, Daniel Jarrett, Mihaela van der Schaar
  • 发表时间: 2019/12/01
  • 文章链接: https://papers.nips.cc/paper/2019/file/c9efe5f26cd17ba6216bbe2a7d26d490-Paper.pdf
  • 代码: https://github.com/jsyoon0823/TimeGAN

摘要

用生成模型生成时间序列数据是一件复杂的事,因为其要求生成模型既要捕捉各时间点特征分布,又要学习变量间的动态关系。在时序数据的生成中,自回归模型虽在序列预测中改进了时间动态性,并非真正的生成模型。此外,将生成对抗网络(GAN)框架直接应用于序列数据,但其未充分利用自回归的先验信息,仅靠标准GAN损失求和不能确保生成模型能有效捕捉训练数据中的多步依赖关系。为了解决以上问题,论文作者提出一种时间序列生成对抗网络(Time - GAN),该网络弥补了上述两种模型的缺陷,作者设计了一个包含嵌入函数、恢复函数、序列生成器和序列鉴别器的生成模型,通过有监督损失和无监督损失的学习嵌入空间对抗性和联合训练,让模型得以同时学习编码特征、生成表示和跨时间迭代。最后,作者通过多种实验证明该模型在生成现实时间序列数据方面相比现有基准模型有明显提升。

Abstract

Generating synthetic time-series data is a complex task, as it requires a generative model to capture both the distribution of features at each time point and the dynamic relationships between variables. Autoregressive models, although improved in terms of temporal dynamics for sequence prediction, are inherently deterministic and do not qualify as true generative models. On the other hand, directly applying the Generative Adversarial Network (GAN) framework to sequential data does not fully leverage the autoregressive prior, and relying solely on standard GAN loss summation is insufficient to ensure that the generative model can effectively capture the multi-step dependencies present in the training data.To address these issues, this paper proposes a Time Series Generative Adversarial Network (Time-GAN) that remedies the shortcomings of the aforementioned models. The proposed network is explicitly trained to preserve temporal dynamics through adversarial and joint training in a learned embedding space with both supervised and unsupervised losses. The authors demonstrate through various experiments that this model significantly outperforms existing benchmark models in generating realistic time-series data.

创新点

1、引入监督损失以更好捕捉时间动态。
2、采用嵌入网络提供低维对抗学习空间。
3、提出联合训练方案,使TimeGAN能同时编码、生成和迭代。

网络架构

作者提出时间序列生成对抗网络(Time-GAN)架构如下图所示:
其中包含嵌入函数和恢复函数、序列生成器和序列判别器四个网络部分
在这里插入图片描述

在分析之前,我们首先看看作者提出背景问题
在这里插入图片描述
作者认为时间序列数据由两部分组成,如下图所示:
在这里插入图片描述
作者还提到在生成时间序列数据的中,通常需要学习一个能够描述整个序列(包括静态特征和时间特征)的概率分布。然而,直接学习整个序列的联合概率分布是很难的,因为它可能遇到长序列、高维特征空间以及复杂的数据分布等情况。
因此作者采用了一种名为自回归分解(autoregressive decomposition)的方法,即将整个序列的联合概率分布分解为一系列条件概率分布的乘积。
公式如下图所示:
在这里插入图片描述
此外, X 1 : t − 1 X_{1:t-1} X1:t1表示表示从时间步 1 到时间步 t−1的所有时间序列数据。
这样就可以将学习整个序列的联合概率分布转化为学习每个时间点的条件概率分布,将复杂问题简单化。转化为条件概率分布可以让训练中模型更容易学习和优化。此外,时间序列数据通常具有自回归性(即当前时间点的值往往依赖于之前时间点的值),通过转化,模型可以更好地捕捉这种时间依赖性。

下面我们对网络架构进行分析:

一、嵌入函数

嵌入函数的目的是将括静态特征和时间序列特征映射到一个低维的潜在空间中。

  1. 因为在平时的数据集中数据都是高维的,高维空间中可能包含很多噪声或不重要的信息,这些信息可能会干扰模型的学习。因此,嵌入函数能够将数据映射到低维空间中,这个潜在空间的表示能够捕捉数据的关键信息的同时降低数据的维度,使得模型更容易学习和处理。
    e : S × ∏ t X → H S × ∏ t H X e:\mathcal{S} \times \prod_{t} \mathcal{X} \rightarrow \mathcal{H}_{\mathcal{S}} \times \prod_{t} \mathcal{H}_{\mathcal{X}} e:S×tXHS×tHX
    其中,S表示静态特征的空间; ∏ t X \prod_{t} \mathcal{X} tX表示时间序列特征在时间步 t 上的笛卡尔积 (使用笛卡尔积操作来表示时间序列数据的联合空间,能方便地映射到一个统一的潜在空间中) ; H S \mathcal{H} _S HS H X \mathcal{H} _X HX分别表示静态特征和时间序列特征的潜在空间。

  2. 嵌入函数 e e e s s s (静态特征)和 x 1 : T x _{1:T} x1:T(时间序列特征)映射到它们的潜在代码 h S \mathcal{h}_S hS h 1 : T \mathcal{h}_{1:T} h1:T 。公式表示如下:
    h S = e S ( s ) \mathbf{h}_{\mathcal{S}}=e_{\mathcal{S}}(\mathbf{s}) hS=eS(s)

     嵌入空间是特征空间到潜在空间的映射。在这个空间中,数据被表示为低维的潜在代码。例如,如果潜在空间是一个 2D 平面,那么潜在代码就是这个平面上的一个点 (x,y)。
    
  3. 时间序列特征的嵌入网络 e X \mathcal{e}_X eX​​ 是一个递归网络,它不仅依赖于当前的时间序列特征 x t x_t xt​,还依赖于前一个时间步的潜在代码 h t − 1 h_{t−1} ht1​ 和静态特征 h S \mathcal{h}_S hS​。公式表示如下:
    h t = e X ( h S , h t − 1 , x t ) \mathbf{h}_{t}=e_{\mathcal{X}}\left(\mathbf{h}_{\mathcal{S}}, \mathbf{h}_{t-1}, \mathbf{x}_{t}\right) ht=eX(hS,ht1,xt)

二、恢复函数

恢复函数的作用是将潜在空间中的代码再映射回原始数据的特征空间。

  1. r r r(恢复函数)将 h S \mathcal{h}_S hS(静态潜在代码)和 h 1 : T \mathcal{h}_{1:T} h1:T​ (时间序列潜在代码 )映射回 s s s (静态特征)和 x 1 : T x _{1:T} x1:T(时间序列特征)
    公式表示如下:
    r : H S × ∏ t H X → S × ∏ t X r: \mathcal{H}_{\mathcal{S}} \times \prod_{t} \mathcal{H}_{\mathcal{X}} \rightarrow \mathcal{S} \times \prod_{t} \mathcal{X} r:HS×tHXS×tX
    s ~ = r S ( h s ) , x ~ t = r X ( h t ) \tilde{\mathbf{s}}=r_{\mathcal{S}}\left(\mathbf{h}_{s}\right), \quad \tilde{\mathbf{x}}_{t}=r_{\mathcal{X}}\left(\mathbf{h}_{t}\right) s~=rS(hs),x~t=rX(ht)
    其中,静态特征的恢复网络 r S r_S rS​ 将静态潜在代码 h S h_S hS​ 映射回静态特征 s ~ \tilde{s} s~
    时间序列特征的恢复网络 r X {r}_{X} rX​ 将每个时间步的潜在代码 ht​ 映射回对应的时间序列特征 x ~ t \tilde{x}_t x~t​。

嵌入和恢复函数需要每一步的输出只能依赖于前面的信息,不能“看到”未来的信息。 这样确保模型能够正确地模拟时间序列数据的生成过程。
嵌入和恢复函数可以采用任何网络架构(如时间卷积网络、注意力解码器、循环神经网络等等)

三、序列生成器

序列生成器的用于生成合成的数据。它不是直接在特征空间生成数据,而是首先在嵌入空间生成数据。
生成器 g g g通过静态和时间序列的随机向量 z z z,生成合成的潜在代码 h h h
在这里插入图片描述
为什么生成的时间序列潜在表示 h ^ t \hat{\mathbf{h}}_{t} h^t的生成需要静态特征的潜在表示 h ^ S \hat{\mathbf{h}}_{S} h^S?
因为 h ^ t \hat{\mathbf{h}}_{t} h^t编码了静态特征的全局信息,这些信息对时间序列的生成有重要影响。 比如在生成一个人的身高序列时,个人的静态特征(如:年龄和性别)可能影响身高趋势的整体情况。

四、序列判别器

序列判别器的目的是区分真实数据和生成数据。
它也工作在嵌入空间中。判别器 d : H S × ∏ t H X → [ 0 , 1 ] × ∏ t [ 0 , 1 ] d: \mathcal{H}_{S} \times \prod_{t} \mathcal{H}_{\mathcal{X}} \rightarrow[0,1] \times \prod_{t}[0,1] d:HS×tHX[0,1]×t[0,1] 接受静态和时间序列的潜在代码,返回分类结果。这些分类结果表示数据是真实的还是合成的。

  1. 静态特征的判别网络 d S d_S dS​ 直接对静态潜在代码 h ~ S \tilde{h}_S h~S​ 进行分类
    y ~ S = d S ( h ~ S ) \tilde{y}_{\mathcal{S}}=d_{\mathcal{S}}\left(\tilde{\mathbf{h}}_{\mathcal{S}}\right) y~S=dS(h~S)
    其中 y ~ S \tilde{y}_{\mathcal{S}} y~S是一个值概率值范围是[0,1]。

  2. 时间序列特征的判别网络 d X d_X dX​ 使用一个双向递归网络来处理时间序列数据。
    它考虑了前向和后向的隐藏状态 u → t = c ⃗ X ( h ~ S , h ~ t , u → t − 1 ) \overrightarrow{\mathbf{u}}_{t}=\vec{c}_{\mathcal{X}}\left(\tilde{\mathbf{h}}_{\mathcal{S}}, \tilde{\mathbf{h}}_{t}, \overrightarrow{\mathbf{u}}_{t-1}\right) u t=c X(h~S,h~t,u t1)​​ 和 u ← t = c ← X ( h ~ S , h ~ t , u ← t + 1 ) \overleftarrow{\mathbf{u}}_{t}=\overleftarrow{c}_{\mathcal{X}}\left(\tilde{\mathbf{h}}_{\mathcal{S}}, \tilde{\mathbf{h}}_{t}, \overleftarrow{\mathbf{u}}_{t+1}\right) u t=c X(h~S,h~t,u t+1)(其中,​ c ← X \overleftarrow{c}_{\mathcal{X}} c X c → X \overrightarrow{c}_{\mathcal{X}} c X前向和后向的循环函数)
    y ~ t = d X ( u ← t , u → t ) \quad \tilde{y}_{t}=d_{\mathcal{X}}\left(\overleftarrow{\mathbf{u}}_{t}, \overrightarrow{\mathbf{u}}_{t}\right) y~t=dX(u t,u t)

生成器通过递归网络生成潜在表示,这些代码表示合成的时间序列数据。而判别器通过双向递归网络来区分真实数据和生成数据的潜在表示。

损失函数

1. 重建损失
嵌入和恢复函数能够准确地从潜在代码 h S ​ , h 1 : T h_S​,h_{1:T} hS,h1:T​ 重建原始数据 s , x 1 : T s,x_{1:T} s,x1:T​。
重建损失 L R \mathcal{L}_{R} LR 用于衡量重建数据与原始数据之间的差异。
公式如下:
L R = E s , x 1 : T ∼ p [ ∥ s − s ~ ∥ 2 + ∑ t ∥ x t − x ~ t ∥ 2 ] \mathcal{L}_{R}=\mathbb{E}_{s, x_{1: T} \sim p}\left[\|s-\tilde{s}\|_{2}+\sum_{t}\left\|x_{t}-\tilde{x}_{t}\right\|_{2}\right] LR=Es,x1:Tp[ss~2+txtx~t2]
其中, E s , x 1 : T ∼ p \mathbb{E}_{s, x_{1: T}\sim p} Es,x1:Tp表示对所有可能的静态特征 s s s和时间序列特征 x 1 : T x_{1:T} x1:T的期望值; ∥ s − s ~ ∥ 2 \|s-\tilde{s}\|_{2} ss~2表示原始静态特征 s 和重建的静态特征 s ~ \tilde{s} s~之间的欧几里得距离;同样的, ∑ t ∥ x t − x ~ t ∥ 2 \sum_{t}\left\|x_{t}-\tilde{x}_{t}\right\|_{2} txtx~t2表示原始时间序列特征 x t x_t xt 和重建的时间序列特征 x t ~ \tilde{x_{t}} xt~之间的欧几里得距离。
2. 无监督损失
生成器(自回归)通过合成嵌入 h S ​ , h 1 : t − 1 h_S​,h_{1:t−1} hS,h1:t1​生成下一个合成向量 h t ^ \hat{h_{t}} ht^。然后计算无监督损失的梯度,公式如下:
L U = E s , x 1 : T ∼ p [ log ⁡ y S + ∑ t log ⁡ y t ] + E s , x 1 : T ∼ p ^ [ log ⁡ ( 1 − y ^ S ) + ∑ t log ⁡ ( 1 − y ^ t ) ] \mathcal{L}_{U}=\mathbb{E}_{s, x_{1: T} \sim p}\left[\log y_{\mathcal{S}}+\sum_{t} \log y_{t}\right]+\mathbb{E}_{s, x_{1: T} \sim \hat{p}}\left[\log \left(1-\hat{y}_{\mathcal{S}}\right)+\sum_{t} \log \left(1-\hat{y}_{t}\right)\right] LU=Es,x1:Tp[logyS+tlogyt]+Es,x1:Tp^[log(1y^S)+tlog(1y^t)]
其实就是GAN的公式具体可以参考我之间关于GAN的博客,里面有公式的具体说明:https://blog.csdn.net/Zcymatics/article/details/145011685?spm=1001.2014.3001.5501
其中, y S ​ y_S​ yS y t y_t yt​ 是真实数据的分类结果, y S ^ \hat{y_S} yS^​ 和 y t ^ \hat{y_t} yt^是生成数据的分类结果。

3. 监督损失
作者认为仅依赖判别器的二元对抗不足以让生成器捕捉数据中的逐步条件分布。所以作者引入了额外的损失来进一步加强模型的捕捉特征能力。在交替的方式中,生成器还以循环迭代的模式训练即通过实际数据的嵌入序列 h 1 : t − 1 h_{1:t−1} h1:t1​以生成下一个潜在向量 h t h_t ht
作者在损失上计算梯度,该损失得到分布 p ( H t ∣ H S , H 1 : t − 1 ) p\left(H_{t} \mid H_{\mathcal{S}}, H_{1: t-1}\right) p(HtHS,H1:t1) p ^ ( H t ∣ H S , H 1 : t − 1 ) \hat{p}\left(H_{t} \mid H_{\mathcal{S}}, H_{1: t-1}\right) p^(HtHS,H1:t1)之间的差异。其应用最大似然得到监督损失,公式如下:
L S = E s , x 1 : T ∼ p [ ∑ t ∥ h t − g X ( h S , h t − 1 , z t ) ∥ 2 ] \mathcal{L}_{S}=\mathbb{E}_{s, x_{1: T} \sim p}\left[\sum_{t}\left\|h_{t}-g_{\mathcal{X}}\left(h_{\mathcal{S}}, h_{t-1}, z_{t}\right)\right\|_{2}\right] LS=Es,x1:Tp[thtgX(hS,ht1,zt)2]
优化过程:
下图展示了训练过程中的方法:

  1. θ e ​ , θ r ​ , θ g ​ , θ d θ_e​,θ_r​,θ_g​,θ_d θe,θr,θg,θd​ 分别表示嵌入、恢复、生成器和判别器网络的参数。
  2. 嵌入函数和恢复函数在重建损失和监督损失上进行训练,过程可以表达为: min ⁡ θ e , θ r ( λ L S + L R ) \min _{\theta_e, \theta_r}\left(\lambda \mathcal{L}_S+\mathcal{L}_R\right) minθe,θr(λLS+LR).其中,λ≥0 是一个超参数,用于平衡两个损失。
  3. 然后生成器和判别器网络以对抗方式进行训练(即在有监督和无监督损下失混合训练),过程可以表达为: min ⁡ θ g ( η L S + max ⁡ θ d L U ) \min _{\theta_g}\left(\eta \mathcal{L}_S+\max _{\theta_d} \mathcal{L}_U\right) minθg(ηLS+maxθdLU)。其中,η≥0 是另一个超参数,用于平衡两个损失。
    在这里插入图片描述

实验

作者通过在多个真实和合成数据集上进行实验。

  1. 采用定性方法,如t-SNE和PCA分析来可视化生成分布与原始分布的相似性;
  2. 采用定量方法,如训练后分类器区分真实和生成序列,以及应用在合成数据上训练,在真实数据上测试框架评估生成数据对原始预测特征的保留能力。对不同类型的时间序列数据进行实验,包括具有周期性、离散性、不同噪声水平、时间步长规律性以及时间和特征相关性的数据。

与其他基准模型对比实验结果
1.1 Discriminative Score(判别分数)
在自回归多元高斯数据实验中如表1所示:
TimeGAN在不同的时间相关性(φ)和特征相关性(σ)设置下,判别分数均优于RCGAN、C-RNN-GAN、T-Forcing、P-Forcing、WaveNet和WaveGAN等基准模型。例如,当φ = 0.8且σ = 0.8时,TimeGAN的判别分数为0.105±0.005,而其他模型的分数相对较高。
在这里插入图片描述
在正弦、股票、能源、事件数据集实验结果如表2所示:
TimeGAN的判别分数也始终优于其他基准模型。如在股票数据集上,TimeGAN生成样本的判别分数为0.102±0.021,比次优的RCGAN(0.196±0.027)低48%。
在这里插入图片描述
1.2 预测分数(Predictive Score)
在自回归多元高斯数据实验中,如表1所示:
TimeGAN在不同的时间相关性(φ)和特征相关性(σ)设置下,预测分数均优于其他基准模型。例如,当φ = 0.8且σ = 0.8时,TimeGAN的预测分数为0.251±0.002,低于其他模型。
在这里插入图片描述
在不同类型时间序列数据实验中,结果如表2所示:
TimeGAN的预测分数同样始终优于其他基准模型,并且TimeGAN的预测分数几乎与原始数据集一致。
在这里插入图片描述
4. t - SNE和PCA可视化结果
在正弦和股票数据集上进行t - SNE可视化如图3所示:
TimeGAN生成的合成数据集与原始数据的重叠度明显优于其他基准模型。
在这里插入图片描述
5. 增益来源分析结果
在对TimeGAN进行修改后的实验中,如表3所示:
作者分析了监督损失、嵌入网络和联合训练方案这三个元素对生成时间序列数据质量的贡献。结果表明这三个元素都对提高生成时间序列数据的质量有重要作用。例如,在股票数据集这种具有高时间相关性的数据中,监督损失的作用尤为重要;嵌入网络和与对抗网络的联合训练也能全面且持续地提高生成性能。
在这里插入图片描述
代码如下:

import tensorflow as tf 
import numpy as np  
from utils import extract_time, rnn_cell, random_generator, batch_generator  
def timegan(ori_data, parameters):"""TimeGAN 函数。使用原始数据作为训练集生成合成数据(时间序列)。参数:- ori_data: 原始时间序列数据- parameters: TimeGAN 网络参数返回:- generated_data: 生成的时间序列数据"""# 初始化 TensorFlow 计算图tf.reset_default_graph()# 获取原始数据的基本参数no, seq_len, dim = np.asarray(ori_data).shape  # no: 样本数, seq_len: 序列长度, dim: 特征维度# 提取时间信息并计算最大序列长度ori_time, max_seq_len = extract_time(ori_data)  # ori_time: 每个样本的时间长度, max_seq_len: 最大序列长度def MinMaxScaler(data):"""Min-Max 归一化器。参数:- data: 原始数据返回:- norm_data: 归一化后的数据- min_val: 最小值(用于反归一化)- max_val: 最大值(用于反归一化)"""min_val = np.min(np.min(data, axis=0), axis=0)  # 计算每个特征的最小值data = data - min_val  # 数据减去最小值max_val = np.max(np.max(data, axis=0), axis=0)  # 计算每个特征的最大值norm_data = data / (max_val + 1e-7)  # 归一化数据return norm_data, min_val, max_val# 对原始数据进行归一化ori_data, min_val, max_val = MinMaxScaler(ori_data)## 构建 RNN 网络# 网络参数hidden_dim = parameters['hidden_dim']  # 隐藏层维度num_layers = parameters['num_layer']  # RNN 层数iterations = parameters['iterations']  # 训练迭代次数batch_size = parameters['batch_size']  # 批量大小module_name = parameters['module']  # RNN 模块名称(如 LSTM 或 GRU)z_dim = dim  # 随机噪声的维度gamma = 1  # 超参数,用于调整损失函数# 输入占位符X = tf.placeholder(tf.float32, [None, max_seq_len, dim], name="myinput_x")  # 输入时间序列数据Z = tf.placeholder(tf.float32, [None, max_seq_len, z_dim], name="myinput_z")  # 输入随机噪声T = tf.placeholder(tf.int32, [None], name="myinput_t")  # 输入时间信息def embedder(X, T):"""嵌入网络:将原始特征空间映射到潜在空间。参数:- X: 输入时间序列特征- T: 输入时间信息返回:- H: 嵌入表示"""with tf.variable_scope("embedder", reuse=tf.AUTO_REUSE):e_cell = tf.nn.rnn_cell.MultiRNNCell([rnn_cell(module_name, hidden_dim) for _ in range(num_layers)])  # 创建多层 RNN 单元e_outputs, e_last_states = tf.nn.dynamic_rnn(e_cell, X, dtype=tf.float32, sequence_length=T)  # 动态 RNNH = tf.contrib.layers.fully_connected(e_outputs, hidden_dim, activation_fn=tf.nn.sigmoid)  # 全连接层return Hdef recovery(H, T):"""恢复网络:从潜在空间映射回原始空间。参数:- H: 潜在表示- T: 输入时间信息返回:- X_tilde: 恢复的数据"""with tf.variable_scope("recovery", reuse=tf.AUTO_REUSE):r_cell = tf.nn.rnn_cell.MultiRNNCell([rnn_cell(module_name, hidden_dim) for _ in range(num_layers)])  # 创建多层 RNN 单元r_outputs, r_last_states = tf.nn.dynamic_rnn(r_cell, H, dtype=tf.float32, sequence_length=T)  # 动态 RNNX_tilde = tf.contrib.layers.fully_connected(r_outputs, dim, activation_fn=tf.nn.sigmoid)  # 全连接层return X_tildedef generator(Z, T):"""生成器函数:在潜在空间中生成时间序列数据。参数:- Z: 随机噪声- T: 输入时间信息返回:- E: 生成的嵌入表示"""with tf.variable_scope("generator", reuse=tf.AUTO_REUSE):e_cell = tf.nn.rnn_cell.MultiRNNCell([rnn_cell(module_name, hidden_dim) for _ in range(num_layers)])  # 创建多层 RNN 单元e_outputs, e_last_states = tf.nn.dynamic_rnn(e_cell, Z, dtype=tf.float32, sequence_length=T)  # 动态 RNNE = tf.contrib.layers.fully_connected(e_outputs, hidden_dim, activation_fn=tf.nn.sigmoid)  # 全连接层return Edef supervisor(H, T):"""监督器函数:使用前一序列生成下一序列。参数:- H: 潜在表示- T: 输入时间信息- 返回:- S: 基于生成器生成的潜在表示生成的序列"""with tf.variable_scope("supervisor", reuse=tf.AUTO_REUSE):e_cell = tf.nn.rnn_cell.MultiRNNCell([rnn_cell(module_name, hidden_dim) for _ in range(num_layers - 1)])  # 创建多层 RNN 单元e_outputs, e_last_states = tf.nn.dynamic_rnn(e_cell, H, dtype=tf.float32, sequence_length=T)  # 动态 RNNS = tf.contrib.layers.fully_connected(e_outputs, hidden_dim, activation_fn=tf.nn.sigmoid)  # 全连接层return Sdef discriminator(H, T):"""判别器函数:区分原始和合成的时间序列数据。参数:- H: 潜在表示- T: 输入时间信息返回:- Y_hat: 原始和合成时间序列的分类结果"""with tf.variable_scope("discriminator", reuse=tf.AUTO_REUSE):d_cell = tf.nn.rnn_cell.MultiRNNCell([rnn_cell(module_name, hidden_dim) for _ in range(num_layers)])  # 创建多层 RNN 单元d_outputs, d_last_states = tf.nn.dynamic_rnn(d_cell, H, dtype=tf.float32, sequence_length=T)  # 动态 RNNY_hat = tf.contrib.layers.fully_connected(d_outputs, 1, activation_fn=None)  # 全连接层return Y_hat# 嵌入网络和恢复网络H = embedder(X, T)  # 嵌入表示X_tilde = recovery(H, T)  # 恢复的数据# 生成器E_hat = generator(Z, T)  # 生成的嵌入表示H_hat = supervisor(E_hat, T)  # 监督器生成的潜在表示H_hat_supervise = supervisor(H, T)  # 监督器生成的潜在表示(基于原始数据)# 合成数据X_hat = recovery(H_hat, T)  # 生成的合成数据# 判别器Y_fake = discriminator(H_hat, T)  # 判别器对合成数据的输出Y_real = discriminator(H, T)  # 判别器对原始数据的输出Y_fake_e = discriminator(E_hat, T)  # 判别器对生成器输出的嵌入表示的输出# 变量e_vars = [v for v in tf.trainable_variables() if v.name.startswith('embedder')]  # 嵌入网络变量r_vars = [v for v in tf.trainable_variables() if v.name.startswith('recovery')]  # 恢复网络变量g_vars = [v for v in tf.trainable_variables() if v.name.startswith('generator')]  # 生成器变量s_vars = [v for v in tf.trainable_variables() if v.name.startswith('supervisor')]  # 监督器变量d_vars = [v for v in tf.trainable_variables() if v.name.startswith('discriminator')]  # 判别器变量# 判别器损失D_loss_real = tf.losses.sigmoid_cross_entropy(tf.ones_like(Y_real), Y_real)  # 真实数据的损失D_loss_fake = tf.losses.sigmoid_cross_entropy(tf.zeros_like(Y_fake), Y_fake)  # 合成数据的损失D_loss_fake_e = tf.losses.sigmoid_cross_entropy(tf.zeros_like(Y_fake_e), Y_fake_e)  # 生成器嵌入表示的损失D_loss = D_loss_real + D_loss_fake + gamma * D_loss_fake_e  # 判别器总损失# 生成器损失# 1. 对抗损失G_loss_U = tf.losses.sigmoid_cross_entropy(tf.ones_like(Y_fake), Y_fake)  # 合成数据的对抗损失G_loss_U_e = tf.losses.sigmoid_cross_entropy(tf.ones_like(Y_fake_e), Y_fake_e)  # 生成器嵌入表示的对抗损失# 2. 监督损失G_loss_S = tf.losses.mean_squared_error(H[:, 1:, :], H_hat_supervise[:, :-1, :])  # 监督损失# 3. 二阶矩损失G_loss_V1 = tf.reduce_mean(tf.abs(tf.sqrt(tf.nn.moments(X_hat, [0])[1] + 1e-6) - tf.sqrt(tf.nn.moments(X, [0])[1] + 1e-6)))  # 方差损失G_loss_V2 = tf.reduce_mean(tf.abs((tf.nn.moments(X_hat, [0])[0]) - (tf.nn.moments(X, [0])[0])))  # 均值损失G_loss_V = G_loss_V1 + G_loss_V2  # 二阶矩总损失# 4. 总生成器损失G_loss = G_loss_U + gamma * G_loss_U_e + 100 * tf.sqrt(G_loss_S) + 100 * G_loss_V# 嵌入网络损失E_loss_T0 = tf.losses.mean_squared_error(X, X_tilde)  # 嵌入网络的恢复损失E_loss0 = 10 * tf.sqrt(E_loss_T0)  # 嵌入网络的总损失E_loss = E_loss0 + 0.1 * G_loss_S  # 嵌入网络的最终损失# 优化器E0_solver = tf.train.AdamOptimizer().minimize(E_loss0, var_list=e_vars + r_vars)  # 嵌入网络优化器E_solver = tf.train.AdamOptimizer().minimize(E_loss, var_list=e_vars + r_vars)  # 嵌入网络优化器D_solver = tf.train.AdamOptimizer().minimize(D_loss, var_list=d_vars)  # 判别器优化器G_solver = tf.train.AdamOptimizer().minimize(G_loss, var_list=g_vars + s_vars)  # 生成器优化器GS_solver = tf.train.AdamOptimizer().minimize(G_loss_S, var_list=g_vars + s_vars)  # 监督器优化器## TimeGAN 训练sess = tf.Session()  # 创建 TensorFlow 会话sess.run(tf.global_variables_initializer())  # 初始化所有变量# 1. 嵌入网络训练print('Start Embedding Network Training')for itt in range(iterations):# 生成小批量数据X_mb, T_mb = batch_generator(ori_data, ori_time, batch_size)# 训练嵌入网络_, step_e_loss = sess.run([E0_solver, E_loss_T0], feed_dict={X: X_mb, T: T_mb})# 打印训练进度if itt % 1000 == 0:print('step: ' + str(itt) + '/' + str(iterations) + ', e_loss: ' + str(np.round(np.sqrt(step_e_loss), 4)))print('Finish Embedding Network Training')# 2. 仅使用监督损失训练print('Start Training with Supervised Loss Only')for itt in range(iterations):# 生成小批量数据X_mb, T_mb = batch_generator(ori_data, ori_time, batch_size)# 生成随机噪声Z_mb = random_generator(batch_size, z_dim, T_mb, max_seq_len)# 训练生成器_, step_g_loss_s = sess.run([GS_solver, G_loss_S], feed_dict={Z: Z_mb, X: X_mb, T: T_mb})# 打印训练进度if itt % 1000 == 0:print('step: ' + str(itt) + '/' + str(iterations) + ', s_loss: ' + str(np.round(np.sqrt(step_g_loss_s), 4))print('Finish Training with Supervised Loss Only')# 3. 联合训练print('Start Joint Training')for itt in range(iterations):# 生成器训练(比判别器训练多一次)for kk in range(2):# 生成小批量数据X_mb, T_mb = batch_generator(ori_data, ori_time, batch_size)# 生成随机噪声Z_mb = random_generator(batch_size, z_dim, T_mb, max_seq_len)# 训练生成器_, step_g_loss_u, step_g_loss_s, step_g_loss_v = sess.run([G_solver, G_loss_U, G_loss_S, G_loss_V], feed_dict={Z: Z_mb, X: X_mb, T: T_mb})# 训练嵌入网络_, step_e_loss_t0 = sess.run([E_solver, E_loss_T0], feed_dict={Z: Z_mb, X: X_mb, T: T_mb})# 判别器训练# 生成小批量数据X_mb, T_mb = batch_generator(ori_data, ori_time, batch_size)# 生成随机噪声Z_mb = random_generator(batch_size, z_dim, T_mb, max_seq_len)# 检查判别器损失check_d_loss = sess.run(D_loss, feed_dict={X: X_mb, T: T_mb, Z: Z_mb})# 如果判别器损失较大,则训练判别器if check_d_loss > 0.15:_, step_d_loss = sess.run([D_solver, D_loss], feed_dict={X: X_mb, T: T_mb, Z: Z_mb})# 打印训练进度if itt % 1000 == 0:print('step: ' + str(itt) + '/' + str(iterations) +', d_loss: ' + str(np.round(step_d_loss, 4)) +', g_loss_u: ' + str(np.round(step_g_loss_u, 4)) +', g_loss_s: ' + str(np.round(np.sqrt(step_g_loss_s), 4)) +', g_loss_v: ' + str(np.round(step_g_loss_v, 4)) +', e_loss_t0: ' + str(np.round(np.sqrt(step_e_loss_t0), 4)))print('Finish Joint Training')## 合成数据生成Z_mb = random_generator(no, z_dim, ori_time, max_seq_len)  # 生成随机噪声generated_data_curr = sess.run(X_hat, feed_dict={Z: Z_mb, X: ori_data, T: ori_time})  # 生成合成数据generated_data = list()# 将生成的合成数据裁剪为原始时间长度for i in range(no):temp = generated_data_curr[i, :ori_time[i], :]generated_data.append(temp)# 反归一化generated_data = generated_data * max_valgenerated_data = generated_data + min_valreturn generated_data

结论

本篇论文提出TimeGAN这一新型时间序列生成框架,它结合无监督GAN方法的通用性和监督自回归模型对条件时间动态的控制。通过监督损失和联合训练嵌入网络,TimeGAN在生成现实时间序列数据方面较现有基准有显著改进。TimeGAN不仅依赖于二元对抗反馈进行学习,还通过采样从学习到的分布中生成数据,这对于合成数据生成非常重要。此外,TimeGAN能够处理不规则采样,并且通过嵌入网络识别数据的低维空间,从而学习数据的逐步分布和潜在动态。实验结果表明TimeGAN在多个数据集上的实验表明其能生成高质量数据,有助于提升数据可用性,对相关领域的时间序列数据的研究方面具有实际应用价值。

后续展望

未来可将差分隐私框架融入TimeGAN,以生成有差分隐私保证的高质量时间序列数据。此外,还可探索在更多类型数据或复杂场景下的应用,进一步优化模型结构或参数以提高性能等。

相关文章:

2025.2.16机器学习笔记:TimeGan文献阅读

2025.2.9周报 一、文献阅读题目信息摘要Abstract创新点网络架构一、嵌入函数二、恢复函数三、序列生成器四、序列判别器损失函数 实验结论后续展望 一、文献阅读 题目信息 题目: Time-series Generative Adversarial Networks会议: Neural Information…...

高通推出骁龙游戏超级分辨率™:充分释放移动游戏性能,带来更持久的续航

Snapdragon Elite Gaming 一直致力于为每位用户打造卓越游戏体验。骁龙支持众多端游级特性,包括144FPS游戏体验、True 10-bit HDR支持的最高视觉质量的超流畅图形,让玩家可以畅享超10亿色的游戏体验。骁龙将许多移动端首创特性引入备受玩家喜爱的游戏中&…...

golangAPI调用deepseek

目录 1.deepseek官方API调用文档1.访问格式2.curl组装 2.go代码1. config 配置2.模型相关3.错误处理4.deepseekAPI接口实现5. 调用使用 3.响应实例 1.deepseek官方API调用文档 1.访问格式 现在我们来解析这个curl 2.curl组装 // 这是请求头要加的参数-H "Content-Type:…...

SOC芯片前端设计对芯片电源完整性的影响

在进行芯片的电源完整性时,因为PI受影响的因素较多,出现问题debug也比较难,所以在进行芯片设计时,需要端到端从前到后进行考虑设计,本篇文章将从芯片前端设计的角度来看看哪些因素会影响到PI的设计。 芯片前端设计的主…...

【区块链】零知识证明基础概念详解

🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 ​💫个人格言: "如无必要,勿增实体" 文章目录 零知识证明基础概念详解引言1. 零知识证明的定义与特性1.1 基本定义1.2 三个核心…...

面基Spring Boot项目中实用注解一

在Spring Boot项目中,实用注解根据功能可以分为多个类别。以下是常见的注解分类、示例说明及对比分析: 1. 核心配置注解 SpringBootApplication 作用:标记主启动类,组合了Configuration、EnableAutoConfiguration和ComponentScan…...

最新智能优化算法: 中华穿山甲优化( Chinese Pangolin Optimizer ,CPO)算法求解23个经典函数测试集,MATLAB代码

中华穿山甲优化( Chinese Pangolin Optimizer ,CPO)算法由GUO Zhiqing 等人提出,该算法的灵感来自中华穿山甲独特的狩猎行为,包括引诱和捕食行为。 算法流程如下: 1. 开始 设置算法参数和最大迭代次数&a…...

shell脚本备份MySQL数据库和库下表

目录 注意: 一.脚本内容 二.执行效果 三.创建定时任务 注意: 以下为对MySQL5.7.42版本数据库备份shell脚本参考运行备份的机器请确认mysqldump版本>5.7,否则备份参数--set-gtid-purgedOFF无效,考虑到一般数据库节点和备份…...

Unity Shader Graph 2D - Procedural程序化图形之渐变的正弦波形

前言 正弦波形也是一种常用、常见的程序化图形,合理的使用正弦波形会创作出一些有趣、美观和丰富的效果,本文将使用Unity Shader Graph来实现一个正弦波形效果,帮助理解和实践Unity Shader Graph以及正弦函数。 创建一个名为SineWave的Shader…...

【算法与数据结构】并查集详解+题目

目录 一,什么是并查集 二,并查集的结构 三,并查集的代码实现 1,并查集的大致结构和初始化 2,find操作 3,Union操作 4,优化 小结: 四,并查集的应用场景 省份…...

国家队出手!DeepSeek上线国家超算互联网平台!

目前,国家超算互联网平台已推出 DeepSeek – R1 模型的 1.5B、7B、8B、14B 版本,后续还会在近期更新 32B、70B 等版本。 DeepSeek太火爆了!在这个春节档,直接成了全民热议的话题。 DeepSeek也毫无悬念地干到了全球增速最快的AI应用。这几天,国内的云计算厂家都在支持Dee…...

H5接入支付宝手机网站支付并实现

小程序文档 - 支付宝文档中心 1.登录 支付宝开放平台 创建 网页/移动应用 2.填写创建应用信息 3.配置开发设置 4.网页/移动应用:需要手动上线。提交审核后,预计 1 个工作日的审核时间。详细步骤可点击查看 上线应用 。应用上线后,还需要完成…...

Win10环境借助DockerDesktop部署大数据时序数据库Apache Druid

Win10环境借助DockerDesktop部署最新版大数据时序数据库Apache Druid32.0.0 前言 大数据分析中,有一种常见的场景,那就是时序数据,简言之,数据一旦产生绝对不会修改,随着时间流逝,每个时间点都会有个新的…...

(三)Axure制作转动的唱片

效果图 属性: 图标库:iconfont-阿里巴巴矢量图标库 方形图片转为圆角图片,裁剪,然后加圆角, 唱片和底图是两个图片,点击播放,唱片在旋转。 主要是播放按钮和停止按钮,两个动态面板…...

[JVM篇]分代垃圾回收

分代垃圾回收 分代收集法是目前大部分 JVM 所采用的方法,其核心思想是根据对象存活的不同生命周期将内存划分为不同的域,一般情况下将 GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young Generation)。老生代的特点是每次垃圾回收时只有少量对象…...

SpringBoot多数据源实践:基于场景的构建、实现和事务一体化研究

1. 多数据源应用场景剖析 1.1 业务驱动的多数据源需求 数据量与业务复杂度引发的分库分表:在现代企业级应用中,随着业务的不断拓展和用户量的持续增长,数据量呈爆炸式增长。例如,在大型电商平台中,用户数据、订单数据…...

鸿蒙应用开发者基础

目录 判断题 单选题 多选题 判断题 1、 在http模块中,多个请求可以使用同一个httpRequest对象,httpRequest对象可以复用。(错误) 2、订阅dataReceiverProgress响应事件是用来接收HTTP流式响应数据。(错误&#xff0…...

Java面试第二山!《计算机网络》!

在 Java 面试里,计算机网络知识是高频考点,今天就来盘点那些最容易被问到的计算机网络面试题,帮你轻松应对面试,也方便和朋友们一起探讨学习。 一、HTTP 和 HTTPS 的区别 1. 面试题呈现 HTTP 和 HTTPS 有什么区别?在…...

2025最新Java面试题大全(整理版)2000+ 面试题附答案详解

很多 Java 工程师的技术不错,但是一面试就头疼,10 次面试 9 次都是被刷,过的那次还是去了家不知名的小公司。 问题就在于:面试有技巧,而你不会把自己的能力表达给面试官。 应届生:你该如何准备简历&#…...

低空经济:开启未来空中生活的全新蓝海

引言 随着科技的进步,我们不再仅仅依赖地面交通和传统物流。你是否曾幻想过,未来的某一天,快递、外卖可以像魔法一样直接从空中送到你手中?或者,你能乘坐小型飞行器,快速穿梭于城市之间,告别拥堵…...

【机器学习】线性回归与一元线性回归

【机器学习系列】 KNN算法 KNN算法原理简介及要点 特征归一化的重要性及方式线性回归算法 线性回归与一元线性回归 线性回归模型的损失函数 多元线性回归 多项式线性回归 线性回归与一元线性回归 V1.1线性回归问题线性方程的最优解一元线性回归一元线性回归的方程一元线性回归…...

MongoDB 7 分片副本集升级方案详解(上)

#作者:任少近 文章目录 前言:Mongodb版本升级升级步骤环境1.1环境准备1.2standalone升级1.3分片、副本集升级 前言:Mongodb版本升级 在开始升级之前,请参阅 MongoDB下个版本中的兼容性变更文档,以确保您的应用程序和…...

Fiori APP配置中的Semantic object 小bug

在配置自开发程序的Fiori Tile时,需要填入Semantic Object。正常来说,是需要通过事务代码/N/UI2/SEMOBJ来提前新建的。 但是在S4 2022中,似乎存在一个bug,即无需新建也能输入自定义的Semantic Object。 如下,当我们任…...

坑多多之AC8257 i2c1 rtc-pcf8563

pcf85163 ordering information Ordering information Package Description Version Marking code PCF85163T/1 SO8 ① SOT96-1 PF85163 PCF85163TS/1 TSSOP8 ② SOT505-1 85163 ①plastic small outline package; 8 leads;body width 3.9 mm ②plastic thin…...

制作一个项目用于研究elementUI的源码

需求:修改el-tooltip的颜色,发现传递参数等方法都不太好用,也可以使用打断点的方式,但也有点麻烦,因此打算直接修改源码,把组件逻辑给修改了 第一步下载源码 源码地址 GitHub - ElemeFE/element: A Vue.j…...

Docker高级篇

1.Mysql主从复制Docker版本 mysql主从复制原理 binlog 1.新建主服务器容器实例 docker run -d -p 3307:3306 --privilegedtrue \ -v /opt/mysql8.4.3/log:/var/log/mysql \ -v /opt/mysql8.4.3/conf:/etc/mysql/conf.d \ -v /opt/mysql8.4.3/data:/var/lib/mysql \ -e MYSQL…...

OSI 参考模型和 TCP/IP 参考模型

数据通信是很复杂的,很难在一个协议中完成所有功能。因此在制定协议时经常采用的思路是将复杂的数据通信功能由若干协议分别完成,然后将这些协议按照一定的方式组织起来。最典型的是采用分层的方式来组织协议,每一层都有一套清晰明确的功能和…...

rocketmq-netty通信设计-request和response

1、NettyRemotingServer启动分析 org.apache.rocketmq.remoting.netty.NettyRemotingServer#start public void start() {this.defaultEventExecutorGroup new DefaultEventExecutorGroup(nettyServerConfig.getServerWorkerThreads(),new ThreadFactory() {private AtomicI…...

初识计算机网络

从此篇我将开始网络新篇章! 1. 网络发展史 最初的计算机之间相互独立存在,每个计算机只能持有自己的数据,数据无法共享。此时的计算机为独立模式 随着时代的发展,越来越需要计算机之间互相通信,共享软件和数据&#x…...

kamailio常见问题解答

常见问题解答 本页面接受贡献,你必须通过注册表单创建一个用户账户: https://www.kamailio.org/wiki/start?doregister 如果你有一个适合收录进常见问题解答的问题,并且你不知道答案,那就添加这个问题,并将答案设置…...

Flask框架入门完全指南

一、初识Flask:轻量级框架的魅力 1.1 Flask框架定位 Flask作为Python最受欢迎的轻量级Web框架,以"微核心可扩展"的设计哲学著称。其核心代码仅约2000行,却支持通过扩展实现完整Web开发功能。这种设计使得开发者可以: …...

用deepseek学大模型05逻辑回归

deepseek.com:逻辑回归的目标函数,损失函数,梯度下降 标量和矩阵形式的数学推导,pytorch真实能跑的代码案例以及模型,数据,预测结果的可视化展示, 模型应用场景和优缺点,及如何改进解决及改进方法数据推导。…...

为什么要选择3D机器视觉检测

选择3D机器视觉检测的原因主要包括以下几点: 高精度测量 复杂几何形状:能够精确测量复杂的三维几何形状。 微小细节:可捕捉微小细节,适用于高精度要求的行业。全面数据获取 深度信息:提供深度信息,弥补2D视…...

CentOS上安装WordPress

在CentOS上安装WordPress是一个相对直接的过程,可以通过多种方法完成,包括使用LAMP(Linux, Apache, MySQL, PHP)栈或使用更现代的LEMP(Linux, Nginx, MySQL, PHP)栈。 我选择的是(Linux, Nginx…...

webshell通信流量分析

环境安装 Apatche2 php sudo apt install apache2 -y sudo apt install php libapache2-mod-php php-mysql -y echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php sudo ufw allow Apache Full 如果成功访问info.php&#xff0c;则环境安…...

高效高并发调度架构

以下是从架构层面为你提供的适合多核CPU、多GPU环境下API客户端、服务端高级调度&#xff0c;以实现高效并发大规模与用户交互的技术栈&#xff1a; 通信协议 gRPC&#xff1a;基于HTTP/2协议&#xff0c;具有高性能、低延迟的特点&#xff0c;支持二进制序列化&#xff08;通…...

MYSQL下载安装及使用

MYSQL官网下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 也可以直接在服务器执行指令下载&#xff0c;但是下载速度比较慢。还是自己下载好拷贝过来比较快。 wget https://dev.mysql.com/get/Downloads/mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz 1…...

Python elasticsearch客户端连接常见问题整理

python 访问 elasticsearch 在python语言中&#xff0c;我们一般使用 pip install elasticsearch 软件包&#xff0c;来访问es服务器。 正确用法 本地安装elasticsearch时&#xff0c;应指定与服务端相同的大版本号&#xff1a; pip install elasticsearch7.17.0然后就可以…...

相得益彰,Mendix AI connector 秒连DeepSeek ,实现研发制造域场景

在当今快速发展的科技领域&#xff0c;低代码一体化平台已成为企业数字化转型的关键工具&#xff0c;同时&#xff0c;大型语言模型&#xff08;LLM&#xff09;如 DeepSeek 在自动生成代码和提供智能建议方面表现出色。 Mendix 于近期发布的 GenAI 万能连接器&#xff0c;目前…...

Python PyCharm DeepSeek接入

Python PyCharm DeepSeek接入 创建API key 首先进入DeepSeek官网&#xff0c;https://www.deepseek.com/ 点击左侧“API Keys”&#xff0c;创建API key&#xff0c;输出名称为“AI” 点击“创建"&#xff0c;将API key保存&#xff0c;复制在其它地方。 在PyCharm中下…...

pytest测试专题 - 2.1 一种推荐的测试目录结构

<< 返回目录 1 pytest测试专题 - 2.1 一种推荐的测试目录结构 2 pytest 项目目录结构及文件功能 以下是典型 pytest 项目中常见的文件和目录结构及其功能的概述&#xff1a; 2.1 文件/目录结构 文件/目录功能描述test_ 文件* 主测试文件&#xff0c;命名通常以 test_…...

Dify本地安装

目录 方式一docker安装&#xff1a; 方式二源码安装&#xff1a; Dify本地安装可以用docker方式&#xff0c;和源码编译方式。 先到云厂商平台申请一台Centos系统云主机&#xff0c;网络选择海外&#xff0c;需要公网IP&#xff0c;再按一下流程操作&#xff1a; 方式一doc…...

MySQL、MariaDB 和 TDSQL 的区别

MySQL、MariaDB 和 TDSQL 是三种不同的数据库管理系统&#xff0c;它们在设计理念、功能、性能和使用场景上有一些显著的区别。 以下是对这三者的详细比较和介绍。 1. MySQL 概述 类型&#xff1a;关系型数据库管理系统&#xff08;RDBMS&#xff09;。开发者&#xff1a;最…...

Java 设计模式之桥接模式

文章目录 Java 设计模式之桥接模式概述UML代码实现 Java 设计模式之桥接模式 概述 桥接模式(Bridge)&#xff1a;将抽象部分与它的实现部分分离&#xff0c;使它们都可以独立地变化。通过桥接模式&#xff0c;可以避免类爆炸问题&#xff0c;并提高系统的可扩展性。 UML 核心…...

【Linux】网络基础

目录 一、协议分层 &#xff08;一&#xff09;计算机网络 &#xff08;二&#xff09;协议分层 &#xff08;三&#xff09;OSI模型 &#xff08;四&#xff09;TCP/IP协议 二、网络传输过程 三、IP地址和MAC地址 &#xff08;一&#xff09;IP地址 &#xff08;二&a…...

[C++]多态详解

目录 一、多态的概念 二、静态的多态 三、动态的多态 3.1多态的定义 3.2虚函数 四、虚函数的重写&#xff08;覆盖&#xff09; 4.1虚函数 4.2三同 4.3两种特殊情况 &#xff08;1&#xff09;协变 &#xff08;2&#xff09;析构函数的重写 五、C11中的final和over…...

Python常见面试题的详解7

1. 内置的数据结构有哪几种 Python 中有多种内置的数据结构&#xff0c;主要分为以下几种&#xff1a; 1.1 数值类型 整数&#xff08;int&#xff09;&#xff1a;用于表示整数&#xff0c;没有大小限制。例如&#xff1a;1, -5, 100。浮点数&#xff08;float&#xff09;…...

C++ ——构造函数

1、作用&#xff1a;创建对象时&#xff0c;给对象的属性进行初始化 2、特点 &#xff08;1&#xff09;构造函数与类同名 &#xff08;2&#xff09;如果没有显式给出构造函数&#xff0c;编译器会给出默认的构造函数&#xff08;参数为空&#xff0c;并且函数体也为空&#…...

PostgreSQL如何关闭自动commit

PostgreSQL如何关闭自动commit 在 PostgreSQL 中&#xff0c;默认情况下&#xff0c;每个 SQL 语句都会自动提交&#xff08;即 AUTOCOMMIT 是开启的&#xff09;。如果希望关闭自动提交&#xff0c;以便手动控制事务的提交和回滚&#xff0c;可以通过以下方法实现。 1 使用 …...

HCIA项目实践--静态路由的总结和简单配置

七、静态路由 7.1 路由器获取未知网段的路由信息&#xff1a; &#xff08;1&#xff09;静态路由&#xff1a;网络管理员手工配置的路由条目&#xff0c;它不依赖网络拓扑的变化进行自动更新&#xff0c;而是根据管理员预先设定的路径来转发数据包。其优点是配置简单、占用系…...