You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于GAN生成ID-VG曲线样本:生成数据与真实样本不符问题

GAN生成ID-VG曲线样本无法拟合真实样本中数值低于-1的部分

我在实现GAN模型生成ID-VG曲线样本时,发现生成的Fake data与真实样本存在明显差异,尤其无法拟合真实样本中数值低于-1的部分。

实现说明

本示例通过generate_real_samples函数生成真实样本,用define_generator和define_discriminator分别定义生成器与判别器网络,再通过define_gan构建GAN模型。调用train函数在真实数据集上训练模型后评估性能,但生成的虚假数据始终无法拟合真实样本中低于-1的部分。

实现代码

# train a generative adversarial network on a one-dimensional function

from numpy import hstack
import numpy as np
from numpy import zeros
from numpy import ones
from numpy.random import rand
from numpy.random import randn
from keras.models import Sequential
from keras import Input
from keras.layers import Dense,LSTM
from matplotlib import pyplot
import matplotlib.pyplot as plt

LENGTH_INPUT=50 # gate length 
un=900
cox=5e-3
import numpy as np

# generate n real samples with class labels

def generate_real_samples(n):
    L = np.arange(0.012,300,0.08)
    W = np.arange(0.02,300,0.8)
    vt=0.3
    # freqs = np.linspace(1,2,1000)
    X2 = np.linspace(0.4,0.7,LENGTH_INPUT)
    X1 = []
    for x in range(n):
        noise = np.random.normal(size=len(X2))
        # id=un*cox*(W/L)*(i-vt)**2
        X1.append(np.log(un*cox*( np.random.choice(W)/ np.random.choice(L))*(X2-vt)**2)+0.1*noise)
    X1 = np.array(X1).reshape(n, LENGTH_INPUT)
    # generate class labels
    y = ones((n, 1))
    return X1, y
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Reshape, Flatten
from keras.layers import ELU, PReLU, LeakyReLU
from keras.optimizers import Adam

# Set the length input to 50

LENGTH_INPUT = 50

# Set the values for un and cox

un = 900
cox = 5e-3

# Define the generator model

def define_generator(latent_dim):
    model = Sequential()
    model.add(Dense(128, input_dim=latent_dim))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dense(256))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dense(LENGTH_INPUT, activation='tanh'))
    return model

# Define the discriminator model

def define_discriminator(input_shape):
    model = Sequential()
    model.add(Flatten(input_shape=input_shape))
    model.add(Dense(128))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dense(64))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dense(1, activation='sigmoid'))
    opt = Adam(lr=0.0002, beta_1=0.5)
    model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
    return model

# Define the GAN model

def define_gan(generator, discriminator):
    discriminator.trainable = False
    model = Sequential()
    model.add(generator)
    model.add(discriminator)
    opt = Adam(lr=0.0002, beta_1=0.5)
    model.compile(loss='binary_crossentropy', optimizer=opt)
    return model

# Generate n real samples with class labels

def generate_real_samples(n):
    L = np.arange(0.012, 300, 0.08)
    W = np.arange(0.02, 300, 0.8)
    vt = 0.3
    X2 = np.linspace(0.4, 0.7, LENGTH_INPUT)
    X1 = []
    for x in range(n):
        noise = np.random.normal(size=LENGTH_INPUT)
        X1.append(np.log(un * cox * (np.random.choice(W) / np.random.choice(L)) * (X2 - vt) ** 2) + 0 * noise)
    X1 = np.array(X1).reshape(n, LENGTH_INPUT)
    y = np.ones((n, 1))
    return X1, y

# Generate latent points

def generate_latent_points(latent_dim, n):
    x_input = np.random.randn(latent_dim * n)
    x_input = x_input.reshape(n, latent_dim)
    return x_input

# Use the generator to generate n fake samples with class labels

def generate_fake_samples(generator, latent_dim, n):
    x_input = generate_latent_points(latent_dim, n)
    X = generator.predict(x_input)
    y = np.zeros((n, 1))
    return X, y

# Train the generator and discriminator models

def train(g_model, d_model, gan_model, latent_dim, n_epochs, n_batch):
    half_batch = int(n_batch / 2)
    n_eval=50
    for i in range(n_epochs):
        # Train discriminator on real samples
        X_real, y_real = generate_real_samples(half_batch)
        d_loss_real, _ = d_model.train_on_batch(X_real, y_real)

        # Train discriminator on fake samples
        X_fake, y_fake = generate_fake_samples(g_model, latent_dim, half_batch)
        d_loss_fake, _ = d_model.train_on_batch(X_fake, y_fake)
    
        # Train generator via the GAN model
        x_gan = generate_latent_points(latent_dim, n_batch)
        y_gan = np.ones((n_batch, 1))
        g_loss = gan_model.train_on_batch(x_gan, y_gan)
    
        # Print progress
        print('Epoch %d/%d, Discriminator Loss: [Real: %.3f, Fake: %.3f], Generator Loss: %.3f' % (i+1, n_epochs, d_loss_real, d_loss_fake, g_loss))
        if (i+1) % n_eval == 0:
            plt.title('Number of epochs = %i'%(i+1))
            pred_data = generate_fake_samples(generator,latent_dim,latent_dim)[0]
            real_data  = generate_real_samples(latent_dim)[0]
            plt.plot(pred_data[0],'.',label='Random Fake Sample',color='firebrick')
            plt.plot(real_data[0],'.',label = 'Random Real Sample',color='navy')
            plt.legend(fontsize=10)
            plt.show()

# Define the size of the latent space

latent_dim = 100

# Create the generator, discriminator, and GAN models

generator = define_generator(latent_dim)
discriminator = define_discriminator((LENGTH_INPUT,))
gan_model = define_gan(generator, discriminator)

# Train the GAN model

n_epochs = 60000
n_batch = 128
train(generator, discriminator, gan_model, latent_dim, n_epochs, n_batch)

# 结果说明:虚假数据无法拟合真实样本中低于-1的部分

问题分析与解决建议

核心问题定位

  1. 生成器输出激活函数限制:生成器最后一层使用tanh激活,其输出范围固定为[-1,1],而真实样本中存在低于-1的数值,这直接导致生成器无法输出该区间的数据。
  2. 数据分布匹配缺失:真实样本的对数输出分布跨度较大,但当前生成器的网络结构和训练目标没有针对性覆盖低数值区间的特征。

具体优化方案

  • 替换生成器激活函数:将生成器最后一层的tanh替换为无边界限制的线性激活(即不设置激活函数),确保生成器可以输出任意范围的数值,完全匹配真实样本的分布。修改示例:
    def define_generator(latent_dim):
        model = Sequential()
        model.add(Dense(128, input_dim=latent_dim))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dense(256))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dense(LENGTH_INPUT))  # 移除tanh激活,使用默认线性输出
        return model
    
  • 数据归一化调整(备选):如果坚持使用有界激活函数,可先对真实样本做归一化处理(比如将所有数据映射到[-1,1]区间),训练完成后再反归一化还原数值范围。但这种方式可能损失部分精度,不如直接使用无界激活直接高效。
  • 增强判别器对低数值的敏感度:在判别器中添加针对低数值区间的特征提取分支,或者在训练时给低数值样本赋予更高权重,让判别器更关注该区间的差异,倒逼生成器学习该部分分布。
  • 切换GAN变体:尝试使用WGAN(Wasserstein GAN)替代传统GAN,WGAN对样本分布的覆盖能力更强,尤其是在样本分布不均匀时,能更好地生成覆盖全区间的样本。

内容的提问来源于stack exchange,提问作者Jaisingh Pal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:58:22