pytorch实现 wgan

在网上找了一个wgan的实现代码,在本地跑了以下,效果还可以,我把它封装成一个函数了,感兴趣的朋友可以用一下

不过这个gan生成的是一维数据,对于图片数据可能需要对代码进行一些改变

import numpy as np
import pandas as pd
import torch
import torch.autograd as autograd
import torch.nn as nn
import torch.optim as optim
from sklearn.model_selection import StratifiedKFold

torch.manual_seed(1)
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
import warnings
warnings.filterwarnings("ignore")
import os,sys

def train_model_save_gen(data, ITERS = 600, iter_ctrl=200, use_cuda = False, name_save='', file_name='./save_gen/'):

    if not os.path.exists(file_name):
        os.mkdir(file_name)
    if not os.path.exists('./model_file/'):
        os.mkdir('./model_file/')
    FIXED_GENERATOR = False
    LAMBDA = .1
    CRITIC_ITERS = 5
    CRITIC_ITERG = 1
    BATCH_SIZE = len(data)

    class Generator(nn.Module):

        def __init__(self, shape1):
            super(Generator, self).__init__()

            main = nn.Sequential(
                nn.Linear(shape1, 1024),
                nn.ReLU(True),
                nn.Linear(1024, 512),
                nn.ReLU(True),
                nn.Linear(512, 256),
                nn.ReLU(True),
                nn.Linear(256, 512),
                nn.ReLU(True),
                nn.Linear(512, 1024),
                nn.Tanh(),
                nn.Linear(1024, shape1),
            )
            self.main = main

        def forward(self, noise, real_data):
            if FIXED_GENERATOR:
                return noise + real_data
            else:
                output = self.main(noise)
                return output

    class Discriminator(nn.Module):

        def __init__(self, shape1):
            super(Discriminator, self).__init__()

            self.fc1 = nn.Linear(shape1, 512)
            self.relu1 = nn.LeakyReLU(0.2)
            self.fc2 = nn.Linear(512, 256)
            self.relu2 = nn.LeakyReLU(0.2)
            self.fc3 = nn.Linear(256, 256)
            self.relu3 = nn.LeakyReLU(0.2)
            self.fc4 = nn.Linear(256, 128)
            self.relu4 = nn.LeakyReLU(0.2)
            self.fc5 = nn.Linear(128, 1)

        def forward(self, inputs):
            out = self.fc1(inputs)
            out = self.relu1(out)
            out = self.fc2(out)
            out = self.relu2(out)
            out = self.fc3(out)
            out = self.relu3(out)
            out = self.fc4(out)
            out = self.relu4(out)
            out = self.fc5(out)
            return out.view(-1)

    def weights_init(m):
        classname = m.__class__.__name__
        if classname.find('Linear') != -1:
            m.weight.data.normal_(0.0, 0.02)
            m.bias.data.fill_(0)
        elif classname.find('BatchNorm') != -1:
            m.weight.data.normal_(1.0, 0.02)
            m.bias.data.fill_(0)

    def calc_gradient_penalty(netD, real_data, fake_data):
        alpha = torch.rand(BATCH_SIZE, 1)
        alpha = alpha.expand(real_data.size())
        alpha = alpha.cuda() if use_cuda else alpha
        interpolates = alpha * real_data + ((1 - alpha) * fake_data)
        if use_cuda:
            interpolates = interpolates.cuda()
        interpolates = autograd.Variable(interpolates, requires_grad=True)
        disc_interpolates = netD(interpolates)
        gradients = autograd.grad(outputs=disc_interpolates, inputs=interpolates,
                                  grad_outputs=torch.ones(disc_interpolates.size()).cuda() if use_cuda else torch.ones(
                                      disc_interpolates.size()), create_graph=True, retain_graph=True,
                                  only_inputs=True)[0]
        gradient_penalty = ((gradients.norm(2, dim=1) - 1) ** 2).mean() * LAMBDA
        return gradient_penalty

    netG = Generator(data.shape[1])
    netD = Discriminator(data.shape[1])
    netD.apply(weights_init)
    netG.apply(weights_init)
    if use_cuda:
        netD = netD.cuda()
        netG = netG.cuda()

    optimizerD = optim.Adam(netD.parameters(), lr=1e-4, betas=(0.5, 0.9))
    optimizerG = optim.Adam(netG.parameters(), lr=1e-4, betas=(0.5, 0.9))

    one = torch.tensor(1, dtype=torch.float)  ###torch.FloatTensor([1])
    mone = one * -1
    if use_cuda:
        one = one.cuda()
        mone = mone.cuda()

    ### ### ###
    one_list = np.ones((data.shape[0]))
    zero_list = np.zeros((data.shape[0]))
    opt_diff_accuracy_05 = 0.5
    best_item = 0
    opt_accuracy = 0
    all_result = []

    loss_list = {'D_loss':[], 'G_loss':[]}
    for iteration in range(ITERS):
        sys.stdout.write(f'\r进行:{iteration}/{ITERS}')  # \r 默认表示将输出的内容返回到第一个指针,这样的话,后面的内容会覆盖前面的内容。
        sys.stdout.flush()
        for p in netD.parameters():
            p.requires_grad = True
        # data = inf_train_gen('data_GAN')
        real_data = torch.FloatTensor(data)
        if use_cuda:
            real_data = real_data.cuda()
            false_data = false_data.cuda()
        real_data_v = autograd.Variable(real_data)
        # false_data_v = autograd.Variable(false_data)

        noise = torch.randn(BATCH_SIZE, data.shape[1])
        if use_cuda:
            noise = noise.cuda()

        noisev = autograd.Variable(noise, volatile=True)
        fake = autograd.Variable(netG(noisev, real_data_v).data)
        fake_output = fake.data.cpu().numpy()
        data = real_data.data.cpu().numpy()
        for iter_d in range(CRITIC_ITERS):
            netD.zero_grad()
            D_real = netD(real_data_v)
            D_real = D_real.mean()
            D_real.backward(mone)  ##############
            noise = torch.randn(BATCH_SIZE, data.shape[1])
            if use_cuda:
                noise = noise.cuda()
            noisev = autograd.Variable(noise, volatile=True)  # volatile=True相当于 requires_grad=False
            fake = autograd.Variable(netG(noisev, real_data_v).data)
            inputv = fake
            D_fake = netD(inputv)
            D_fake = D_fake.mean()
            D_fake.backward(one)  ################

            gradient_penalty = calc_gradient_penalty(netD, real_data_v.data, fake.data)
            gradient_penalty.backward()  ############
            D_cost = D_fake - D_real + gradient_penalty
            Wasserstein_D = D_real - D_fake
            loss_list['D_loss'].append(D_cost.item())
            optimizerD.step()

        if not FIXED_GENERATOR:
            for p in netD.parameters():
                p.requires_grad = False
            for iter_g in range(CRITIC_ITERG):
                netG.zero_grad()
                real_data = torch.Tensor(data)
                if use_cuda:
                    real_data = real_data.cuda()

                real_data_v = autograd.Variable(real_data)
                noise = torch.randn(BATCH_SIZE, data.shape[1])
                if use_cuda:
                    noise = noise.cuda()

                noisev = autograd.Variable(noise)
                fake = netG(noisev, real_data_v)
                G = netD(fake)
                G = G.mean()
                G.backward(mone)
                G_cost = -G
                loss_list['G_loss'].append(G_cost.item())
                optimizerG.step()

        ###save generated sample features every 200 iteration
        if iteration % iter_ctrl == 0:
            # if iteration % 10000 == 0:
            #     data = shuffle(data)
            # save_temp = pd.DataFrame(fake_output)
            # # fake_writer = open(file_name + "/Iteration_" + str(iteration) + ".txt", "w")
            # save_temp.to_csv(file_name + "/Iteration_" + str(iteration) + ".csv", index=None)

            print()
            print(f'循环{iteration}次..')

            x = np.concatenate((data, fake_output), axis=0)
            y = np.concatenate((one_list, zero_list), axis=0)
            kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
            real_label = np.zeros((x.shape[0]))
            pred_label = np.zeros((x.shape[0]))

            for train_index, test_index in kfold.split(x, y):
                x_train, x_test = x[train_index], x[test_index]
                y_train, y_test = y[train_index], y[test_index]
                knn = KNeighborsClassifier(n_neighbors=1).fit(x_train, y_train)
                predicted_y = knn.predict(x_test)
                pred_label[test_index] = predicted_y
                real_label[test_index] = y_test
            accuracy = accuracy_score(real_label, pred_label)
            all_result.append(str(iteration) + "," + str(accuracy))
            print(f'计算{iteration}的acc={accuracy}')

            diff_accuracy_05 = abs(accuracy - 0.5)
            if diff_accuracy_05 < opt_diff_accuracy_05:
                opt_diff_accuracy_05 = diff_accuracy_05
                best_item = iteration
                opt_accuracy = accuracy
                save_temp = pd.DataFrame(fake_output)
                # fake_writer = open(file_name + "/Iteration_" + str(iteration) + ".txt", "w")
                save_temp.to_csv(file_name + "/Iteration3_"+ str(name_save) +'_'+ str(iteration) + ".csv",index=None)

            torch.save(netG.state_dict(), './model_file/netG'+str(iteration)+'.dict')
            torch.save(netD.state_dict(), './model_file/netD'+str(iteration)+'.dict')

    save_loss = pd.DataFrame(loss_list['G_loss'])
    save_loss.to_csv(file_name + "/Gloss_" + str(iteration) + '.csv', index=None)
    save_loss = pd.DataFrame(loss_list['D_loss'])
    save_loss.to_csv(file_name + "/Dloss_" + str(iteration) + '.csv', index=None)

    return best_item,opt_diff_accuracy_05


if __name__ == '__main__':
    d = np.array(pd.read_csv('./data.txt', header=None))
    train_model_save_gen(d)


在本文件夹下新建data.txt,把下列数据粘贴进去(9行,4列):

1,1,1,2
1,1,1,2
1.1,1.1,1.1,2.1
1,1,1,2
1,1,1,2
1.1,1.1,1.1,2.1
1,1,1,2
1,1,1,2
1.1,1.1,1.1,2.1

调用上述函数即可

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
### 回答1: WGAN(Wasserstein生成对抗网络)是基于生成对抗网络(GAN)的一种改进算法。它旨在解决传统GAN训练中的一些困难,如模式崩溃和梯度消失等问题。 WGAN的核心思想是使用Wasserstein距离(Earth-Mover距离)来度量生成器和判别器之间的差异。传统GAN使用的JS散度或KL散度衡量了生成样本分布与真实样本分布之间的差异,但这些度量在训练过程中往往会出现不稳定的情况。Wasserstein距离则可以更稳定地度量生成样本和真实样本之间的差异。 在PyTorch实现WGAN,首先需要定义生成器和判别器的网络结构。生成器接收一个随机向量作为输入,并将其映射到生成样本空间。判别器则接收生成样本或真实样本,并输出一个标量,表示样本的真实性。 其次,需要定义损失函数。WGAN使用的是Wasserstein距离,因此可以将其作为损失函数来衡量生成样本和真实样本之间的差异。为了实现Wasserstein距离,需要定义一个判别器的Lipschitz连续性。可以通过剪裁判别器的权重来实现这一目标。 在训练过程中,首先更新判别器。通过对齐真实样本和生成样本之间的分布,来最小化差异。然后更新生成器,通过最大化判别器的输出来改善生成样本的质量。反复迭代这两个步骤,直到生成样本的质量达到预期。 综上所述,WGANPyTorch中的实现主要包括定义生成器和判别器的网络结构,定义Wasserstein距离作为损失函数,并使用剪裁技术来确保判别器的Lipschitz连续性。通过不断迭代训练生成器和判别器,可以得到高质量的生成样本。 ### 回答2: WGAN(Wasserstein生成对抗网络)是一种生成对抗网络的改进版本,它通过引入Wasserstein距离来解决原始GAN中训练不稳定和生成样本质量评估困难的问题。PyTorch是一种常用的深度学习框架,提供丰富的工具和函数来实现WGAN。 WGAN的核心思想是将生成器和判别器之间的距离解释为样本之间的差异度量,通过最小化生成器和判别器之间的Wasserstein距离来实现训练稳定性和生成质量的提高。 在PyTorch实现WGAN的过程一般包括以下几个步骤: 1. 定义生成器和判别器的网络结构:使用PyTorch的nn.Module类创建生成器和判别器的网络结构,可以使用卷积层、全连接层等组件来构建网络。 2. 定义损失函数:计算生成器和判别器之间的Wasserstein距离作为损失函数。可以使用PyTorch的nn.Module类中提供的损失函数计算生成器和判别器的损失。 3. 定义优化器:选择合适的优化器,例如Adam或RMSprop,并为生成器和判别器分别创建优化器对象。 4. 训练模型:使用训练数据集进行迭代的训练过程。每次迭代中,首先通过生成器生成一些样本,然后将生成的样本与真实样本一起输入给判别器进行判断,并计算生成器和判别器的损失。接下来,分别根据生成器和判别器的损失更新它们的参数。 5. 评估生成效果:在训练过程中,可以定期保存生成器的参数,并使用这些参数生成一些样本来评估生成效果。 总之,使用PyTorch可以方便地实现WGAN。通过定义网络结构、损失函数和优化器,迭代地训练模型并评估生成效果可以实现高质量的图像生成任务。 ### 回答3: WGAN(Wasserstein GAN)是一种生成对抗网络,它通过引入Wasserstein距离(Earth-Mover距离)来解决传统GAN中梯度不稳定和模式崩溃问题。下面将介绍WGANPyTorch中的实现。 首先,我们需要导入PyTorch和其他必要的库。然后定义生成器和判别器模型。生成器负责从随机噪声中生成假样本,判别器负责区分真实样本和假样本。 接着,我们定义损失函数和优化器。WGAN采用Wasserstein距离作为损失函数,并通过对判别器参数控制函数空间的Lipschitz连续性来进行训练。我们可以使用PyTorch自带的优化器来更新生成器和判别器的参数。 接下来,我们进入主要的训练过程。训练过程中,我们迭代若干次,每次迭代中进行以下步骤: 1. 从真实样本中随机抽样一批样本。 2. 从随机噪声中生成一批假样本。 3. 将真实样本和假样本传入判别器,获取真实样本和假样本的判别结果。 4. 计算Wasserstein距离作为损失函数。 5. 清空优化器的梯度。 6. 根据反向传播算法更新判别器的参数。 7. 对判别器的参数进行修剪,以满足Lipschitz连续性约束。 8. 如果达到一定迭代次数,再更新生成器的参数。 9. 输出损失函数的值和训练进度。 最后,我们输出训练完成后生成器生成的假样本,并与真实样本进行对比。 这就是WGANPyTorch中的实现过程,它通过引入Wasserstein距离解决了传统GAN中的一些问题,提高了生成器和判别器的稳定性和训练效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_刘文凯_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值