最近主要调查了对序列数据进行数据增强的方法,以下是几种基于深度学习的生成对抗网络的数据增强方法

方法描述优缺点
T-CGAN使用一维卷积的CGAN,条件输入为时间戳,时间戳可以间隔不等可以针对时间间隔不规则的情况
WGAN适用于训练不稳定的传统GAN场景在某些情况下,WGAN可能仍然无法生成与真实数据完全一致的样本
TimeGAN适用于训练不稳定的传统GAN场景在某些情况下,WGAN可能仍然无法生成与真实数据完全一致的样本
C-RNN-GAN在生成音乐等连续数据方面表现出色能够处理并生成较长的连续序列,这在处理如自然语言、音频等复杂数据时尤为重要,但对离散数据处理能力有限
RGAN、RCGANRGAN采用相对判别器,将真假样本对作为输入,以其中一个样本作为基准,得判别器更稳健,生成对抗网络训练更稳定能够生成更高质量的数据样本,与真实数据难以区分,存在过拟合的风险,需要合理设置训练参数和策略
混合多个GAN用多个GAN,每一个生成特定标签的数据数据生成具有针对性,可用于严重不平衡的数据集

目前主要针对WGAN做了复现和研究

判别器:

class Discriminator(nn.Module):
    def __init__(self, input_dim):
        super(Discriminator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(input_dim, 128),
            nn.ReLU(),
            nn.Linear(128, 32),
            nn.ReLU(),
            nn.Linear(32, 1),
            nn.ReLU(),
        )
    def forward(self, x):
        return self.model(x)

判别器模型结构:
image.png

生成器:

class Generator(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(Generator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(input_dim, 32),
            nn.ReLU(),
            nn.Linear(32, output_dim),
            # nn.ReLU(),
        )

    def forward(self, z):
        return self.model(z)

生成器的结构:
image.png

对于该数据进行数据增强可有两种思路。
1.将生成器输入维度设置为5输出为6,创建维度为5的噪声,经由生成器输出维度为6的模拟数据,再经过dnn/mlp等模型预测其相对距离,最终得到维度为7的数据作为模拟数据
2.将生成器输入维度设置为6,创建维度为6的噪声,直接经由生成器输出维度为7的模拟数据

对于数据的选择也有两种思路:
1.选择混合后的五井数据作为原始数据进行数据增强
2.分别使用混合前的各井数据作为原始数据进行数据增强,增强后再进行混合

目前数据增强是按照思路1,数据选择按照也思路1
GAN模型训练:

def train_wgan(dnn, generator, discriminator, dataloader, num_epochs=3000, batch_size=8, n_critic=300):
    generator_losses = []  
    discriminator_losses = [] 
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    generator.to(device)
    discriminator.to(device)

    gen_optimizer = optim.SGD(generator.parameters(), lr=0.0002)
    disc_optimizer = optim.SGD(discriminator.parameters(), lr=0.0003) 
    dnn_optimizer = optim.SGD(dnn.parameters(), lr=0.0003)

    scaler = StandardScaler()
    columns = ['Column1', 'Column2', 'Column3', 'Column4', 'Column5', 'Column6', 'Column7']
    output_filepath = 'generated_data/generated_data2.csv'
    f = open(output_filepath,'w',encoding='utf-8')
    csv_writer = csv.writer(f)
    csv_writer.writerow(columns)
    loss_func = nn.MSELoss() # 均方根误差损失函数
    train_num = 0
    train_loss = 0
    for epoch in range(num_epochs):
        for _ in range(len(dataloader) // batch_size):
            real_data = next(iter(dataloader))
            real_data = torch.stack(real_data).to(device)

            X_real, y_real = np.split(real_data.squeeze(), [6], axis=1)
            dnn_optimizer.zero_grad()
            predict = dnn(X_real)
            # print(predict)
            loss = loss_func(predict, y_real)
            loss.backward()
            dnn_optimizer.step()
            for _ in range(n_critic):
                X_real = scaler.fit_transform(X_real.cpu().numpy())
                X_real = torch.FloatTensor(X_real).to(device)
                noise = torch.randn(batch_size, 5).to(device)
                fake_data = generator(noise)
                disc_real = discriminator(X_real)
                disc_fake = discriminator(fake_data.detach())
                disc_optimizer.zero_grad()
                disc_loss = -torch.mean(disc_real) + torch.mean(disc_fake)
                disc_optimizer.step()
                for param in discriminator.parameters():
                    param.data.clamp_(-0.1, 0.1)

            noise = torch.randn(batch_size, 5).to(device)
            fake_data = generator(noise)

            wasserstein_loss = discriminator(fake_data)
            gen_loss = -torch.mean(wasserstein_loss)
            gen_optimizer.zero_grad()
            gen_loss.requires_grad_(True)
            gen_loss.backward()
            gen_optimizer.step()
        generator_losses.append(gen_loss.item())  
        discriminator_losses.append(disc_loss.item())
        print(f"Epoch {epoch}/{num_epochs} [D loss: {disc_loss.item()}] [G loss: {gen_loss.item()}]")

流程图:
image.png

目前采取的评判生成器和判别器是否收敛的方法——绘制损失函数图像,查看是否稳定收敛
image.png

数据增强后的效果(扩充数据为800条原为160条)
image.png
但是将目前数据用于实际模型预测中得到的效果较差:
image.png

所以又尝试更换其他的预测效果更好的CNN模型来进行预测,模型如下

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = nn.Sequential(
            nn.Conv1d(in_channels=6, out_channels=8, kernel_size=3, stride=1, padding=1),
            nn.Tanh(),
            # nn.MaxPool1d(2),  # torch.Size([128, 16, 5])
            nn.Conv1d(in_channels=8, out_channels=16, kernel_size=3, stride=1, padding=1),
            nn.Tanh(),
            # nn.MaxPool1d(2),  # torch.Size([128, 32, 1])
            # nn.AdaptiveMaxPool1d(1),
            nn.Flatten(),  # torch.Size([128, 32])    (假如上一步的结果为[128, 32, 2], 那么铺平之后就是[128, 64])
        )
        self.model2 = nn.Sequential(
            # 如果要更改卷积核大小等,这里全连接层的输入特征数要改变
            # nn.Linear(in_features=96, out_features=100, bias=True),
            nn.Linear(in_features= 16, out_features=100, bias=True),
            # 第二个隐含层
            nn.Linear(100, 100),
            # 第三个隐含层
            nn.Linear(100, 50),
            # 回归预测层
            nn.Linear(50, 1)
        )

    def forward(self, input):
        x = input.reshape(-1,6,1)
        x = self.model1(x)
        x = self.model2(x)
        return x[:,0]

强化前:
image.png
强化后:
image.png
可以发现有了比较明显的提升,但是在很多次的强化结果中只有一次可以达到如上效果
后续尝试采用其他思路组合,并尝试优化生成器、判别器以及用于生成标签的模型选择。
根据定性生成数据与原真实数据对比来看,并不是适用于所有井,比如A1井和L3井对应的相对距离都在58米左右,但是猜测由于其在混合数据中数据占比少,导致数据增强所得数据中基本没有58米左右相对距离的数据.所以又尝试使用WGAN分别对单井数据进行数据增强,将各自的增强结果汇总。
初步通过汇总数据训练模型可得出如下效果:
并且此次数据增强全程采用WGAN进行标签的生成,标签生成的方面仍可继续进行优化。但与之前不同的是,此次生成的数据较为稳定,可以多次复现。
48e541da8feadf3762702f411434e07.png


李明
436 声望18 粉丝