惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
A
About on SuperTechFans
IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Blog — PlanetScale
Blog — PlanetScale
aimingoo的专栏
aimingoo的专栏
云风的 BLOG
云风的 BLOG
The GitHub Blog
The GitHub Blog
Vercel News
Vercel News
G
Google Developers Blog
J
Java Code Geeks
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
Cloudbric
Cloudbric
L
LINUX DO - 最新话题
MyScale Blog
MyScale Blog
H
Heimdal Security Blog
PCI Perspectives
PCI Perspectives
Attack and Defense Labs
Attack and Defense Labs
S
Security @ Cisco Blogs
Latest news
Latest news
I
Intezer
L
Lohrmann on Cybersecurity
C
CXSECURITY Database RSS Feed - CXSecurity.com
月光博客
月光博客
T
Threatpost
博客园 - 【当耐特】
S
Schneier on Security
P
Privacy International News Feed
G
GRAHAM CLULEY
T
Tenable Blog
AWS News Blog
AWS News Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
博客园 - Franky
Engineering at Meta
Engineering at Meta
美团技术团队
S
Secure Thoughts
T
Troy Hunt's Blog
Microsoft Security Blog
Microsoft Security Blog
SecWiki News
SecWiki News
V
Visual Studio Blog
人人都是产品经理
人人都是产品经理
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cisco Talos Blog
Cisco Talos Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Martin Fowler
Martin Fowler
Webroot Blog
Webroot Blog
Google DeepMind News
Google DeepMind News
H
Hackread – Cybersecurity News, Data Breaches, AI and More

HibisciDai

Python科学绘图 | HibisciDai AVIZO自动化 | HibisciDai AVIZO曲率计算 | HibisciDai AVIZO二值化数据导出 | HibisciDai 内网穿透 | HibisciDai PyTorch-26H-7 | HibisciDai PyTorch-26H-6 | HibisciDai PyTorch-26H-5 | HibisciDai PyTorch-26H-4 | HibisciDai PyTorch-26H-3 | HibisciDai PyTorch-26H-2 | HibisciDai PyTorch-26H-1 | HibisciDai Linux登录提示语 | HibisciDai drd-Digital_Rocks_Data | HibisciDai WebDAV-使用指南 | HibisciDai Cesium-使用指南 | HibisciDai 小丑在殿堂 | HibisciDai PyCharm挂载Linux服务器 | HibisciDai 核磁共振测井 | HibisciDai
CGAN-TensorFlow | HibisciDai
HibisciDai · 2024-07-10 · via HibisciDai

CGAN-TensorFlow

[TOC]

原文链接:Conditional Generative Adversarial Nets in TensorFlow

We have seen the Generative Adversarial Nets (GAN) model in the previous post. We have also seen the arch nemesis of GAN, the VAE and its conditional variation: Conditional VAE (CVAE). Hence, it is only proper for us to study conditional variation of GAN, called Conditional GAN or CGAN for short.
我们在上一篇文章中看到了生成对抗网络(GAN)模型。我们还看到了 GAN 的死对头,VAE 及其条件变体:条件 VAE(CVAE)。因此,我们研究 GAN 的条件变体(称为条件 GAN 或简称 CGAN)是再合适不过的了。

CGAN: Formulation and Architecture

Recall, in GAN, we have two neural nets: the generator and the discriminator .
Now, as we want to condition those networks with some vector , the easiest way to do it is to feed into both networks. Hence, our generator and discriminator are now and respectively.
回想一下,在 GAN 中,我们有两个神经网络:生成器 和鉴别器 。
现在,由于我们想用某个向量 来调节这些网络,最简单的方法是将 输入两个网络。因此,我们的生成器和鉴别器现在分别是 和 。

We can see it with a probabilistic point of view. is modeling the distribution of our data, given and , that is, our data is generated with this scheme .
我们可以用概率的角度来看待它。给定和,正在对我们的数据分布进行建模,也就是说,我们的数据是用这个方案生成的。

Likewise for the discriminator, now it tries to find discriminating label for and , that are modeled with .
同样对于鉴别器来说,现在它试图为 和 找到鉴别标签,用 建模。

Hence, we could see that both and is jointly conditioned to two variables or and .
因此,我们可以看到 和 都与两个变量 或 和 联合相关。

Now, the objective function is given by:
现在,目标函数如下:

If we compare the above loss to GAN loss, the difference only lies in the additional parameter in both and .
如果我们将上述损失与 GAN 损失进行比较,差异仅在于 和 中的附加参数 。

The architecture of CGAN is now as follows (taken from [1]):
CGAN 的架构如下(取自[1]):

In contrast with the architecture of GAN, we now has an additional input layer in both discriminator net and generator net.
与 GAN 的架构相比,我们现在在鉴别器网络和生成器网络中都增加了一个输入层。

CGAN: Implementation in TensorFlow

I’d like to direct the reader to the previous post about GAN, particularly for the implementation in TensorFlow. Implementing CGAN is so simple that we just need to add a handful of lines to the original GAN implementation. So, here we will only look at those modifications.
我想引导读者阅读上一篇关于 GAN 的文章,特别是关于在 TensorFlow 中的实现。实现 CGAN 非常简单,我们只需要在原始 GAN 实现中添加几行代码即可。因此,我们在这里只讨论这些修改。

Generative Adversarial Nets in TensorFlow

The first additional code for CGAN is here:
CGAN 的第一个附加代码在这里:

1
y = tf.placeholder(tf.float32, shape=[None, y_dim])

We are adding new input to hold our variable we are conditioning our CGAN to.
我们正在添加新输入来保存我们用来调节 CGAN 的变量。

Next, we add it to both our generator net and discriminator net:
接下来,我们将其添加到我们的生成器网络和鉴别器网络中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def generator(z, y):

inputs = tf.concat(concat_dim=1, values=[z, y])

G_h1 = tf.nn.relu(tf.matmul(inputs, G_W1) + G_b1)
G_log_prob = tf.matmul(G_h1, G_W2) + G_b2
G_prob = tf.nn.sigmoid(G_log_prob)

return G_prob


def discriminator(x, y):

inputs = tf.concat(concat_dim=1, values=[x, y])

D_h1 = tf.nn.relu(tf.matmul(inputs, D_W1) + D_b1)
D_logit = tf.matmul(D_h1, D_W2) + D_b2
D_prob = tf.nn.sigmoid(D_logit)

return D_prob, D_logit

The problem we have here is how to incorporate the new variable into and . As we are trying to model the joint conditional, the simplest way to do it is to just concatenate both variables. Hence, in , we are concatenating and before we feed it into the networks. The same procedure is applied to .
我们这里的问题是如何将新变量 合并到 和 中。由于我们试图对联合条件进行建模,最简单的方法就是将两个变量连接起来。因此,在 中,我们在将其输入网络之前将 和 连接起来。同样的程序也适用于 。

Of course, as our inputs for and is now different than the original GAN, we need to modify our weights:
当然,由于我们对 和 的输入现在与原始 GAN 不同,我们需要修改我们的权重:

1
2
3
4
5
6
7


D_W1 = tf.Variable(shape=[X_dim + y_dim, h_dim]))



G_W1 = tf.Variable(shape=[Z_dim + y_dim, h_dim]))

That is, we just adjust the dimensionality of our weights.
也就是说,我们只是调整权重的维数。

Next, we just use our new networks:
接下来,我们只需使用我们的新网络:

1
2
3
4
5


G_sample = generator(Z, y)
D_real, D_logit_real = discriminator(X, y)
D_fake, D_logit_fake = discriminator(G_sample, y)

And finally, when training, we also feed the value of into the networks:
最后,在训练时,我们还将 的值输入网络:

1
2
3
4
5
X_mb, y_mb = mnist.train.next_batch(mb_size)

Z_sample = sample_Z(mb_size, Z_dim)
_, D_loss_curr = sess.run([D_solver, D_loss], feed_dict={X: X_mb, Z: Z_sample, y:y_mb})
_, G_loss_curr = sess.run([G_solver, G_loss], feed_dict={Z: Z_sample, y:y_mb})

As an example above, we are training our GAN with MNIST data, and the conditional variable is the labels.
如上例,我们使用 MNIST 数据训练我们的 GAN,条件变量 是标签。

CGAN: Results

At test time, we want to generate new data samples with certain label. For example, we set the label to be 5, i.e. we want to generate digit “5”:
在测试时,我们希望生成具有特定标签的新数据样本。例如,我们将标签设置为 5,即我们希望生成数字“5”:

1
2
3
4
5
6
7
8
9
n_sample = 16
Z_sample = sample_Z(n_sample, Z_dim)



y_sample = np.zeros(shape=[n_sample, y_dim])
y_sample[:, 5] = 1

samples = sess.run(G_sample, feed_dict={Z: Z_sample, y:y_sample})

Above, we just sample , and then construct the conditional variables. In our example case, the conditional variables is a collection of one-hot vectors with value 1 in the 5th index. The last thing we need to is to run the network with those variables as inputs.
上面,我们只是对 进行采样,然后构造条件变量。在我们的示例中,条件变量是第 5 个索引中值为 1 的独热向量集合。我们需要做的最后一件事是使用这些变量作为输入来运行网络。

Here is the results:
结果如下:

Looks pretty much like digit 5, right?
看起来很像数字 5,对吧?

If we set our one-hot vectors to have value of 1 in the 7th index:
如果我们将独热向量设置为第 7 个索引中的值为 1:

Those results confirmed that have successfully trained our CGAN.
这些结果证实了我们的 CGAN 训练成功。

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

import torch
import torch.nn.functional as nn
import torch.autograd as autograd
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import os
from torch.autograd import Variable
from tensorflow.examples.tutorials.mnist import input_data


mnist = input_data.read_data_sets('../../MNIST_data', one_hot=True)
mb_size = 64
Z_dim = 100
X_dim = mnist.train.images.shape[1]
y_dim = mnist.train.labels.shape[1]
h_dim = 128
cnt = 0
lr = 1e-3


def xavier_init(size):
in_dim = size[0]
xavier_stddev = 1. / np.sqrt(in_dim / 2.)
return Variable(torch.randn(*size) * xavier_stddev, requires_grad=True)


""" ==================== GENERATOR ======================== """

Wzh = xavier_init(size=[Z_dim + y_dim, h_dim])
bzh = Variable(torch.zeros(h_dim), requires_grad=True)

Whx = xavier_init(size=[h_dim, X_dim])
bhx = Variable(torch.zeros(X_dim), requires_grad=True)


def G(z, c):
inputs = torch.cat([z, c], 1)
h = nn.relu(inputs @ Wzh + bzh.repeat(inputs.size(0), 1))
X = nn.sigmoid(h @ Whx + bhx.repeat(h.size(0), 1))
return X


""" ==================== DISCRIMINATOR ======================== """

Wxh = xavier_init(size=[X_dim + y_dim, h_dim])
bxh = Variable(torch.zeros(h_dim), requires_grad=True)

Why = xavier_init(size=[h_dim, 1])
bhy = Variable(torch.zeros(1), requires_grad=True)


def D(X, c):
inputs = torch.cat([X, c], 1)
h = nn.relu(inputs @ Wxh + bxh.repeat(inputs.size(0), 1))
y = nn.sigmoid(h @ Why + bhy.repeat(h.size(0), 1))
return y


G_params = [Wzh, bzh, Whx, bhx]
D_params = [Wxh, bxh, Why, bhy]
params = G_params + D_params


""" ===================== TRAINING ======================== """


def reset_grad():
for p in params:
if p.grad is not None:
data = p.grad.data
p.grad = Variable(data.new().resize_as_(data).zero_())


G_solver = optim.Adam(G_params, lr=1e-3)
D_solver = optim.Adam(D_params, lr=1e-3)

ones_label = Variable(torch.ones(mb_size, 1))
zeros_label = Variable(torch.zeros(mb_size, 1))


for it in range(100000):

z = Variable(torch.randn(mb_size, Z_dim))
X, c = mnist.train.next_batch(mb_size)
X = Variable(torch.from_numpy(X))
c = Variable(torch.from_numpy(c.astype('float32')))


G_sample = G(z, c)
D_real = D(X, c)
D_fake = D(G_sample, c)

D_loss_real = nn.binary_cross_entropy(D_real, ones_label)
D_loss_fake = nn.binary_cross_entropy(D_fake, zeros_label)
D_loss = D_loss_real + D_loss_fake

D_loss.backward()
D_solver.step()


reset_grad()


z = Variable(torch.randn(mb_size, Z_dim))
G_sample = G(z, c)
D_fake = D(G_sample, c)

G_loss = nn.binary_cross_entropy(D_fake, ones_label)

G_loss.backward()
G_solver.step()


reset_grad()


if it % 1000 == 0:
print('Iter-{}; D_loss: {}; G_loss: {}'.format(it, D_loss.data.numpy(), G_loss.data.numpy()))

c = np.zeros(shape=[mb_size, y_dim], dtype='float32')
c[:, np.random.randint(0, 10)] = 1.
c = Variable(torch.from_numpy(c))
samples = G(z, c).data.numpy()[:16]

fig = plt.figure(figsize=(4, 4))
gs = gridspec.GridSpec(4, 4)
gs.update(wspace=0.05, hspace=0.05)

for i, sample in enumerate(samples):
ax = plt.subplot(gs[i])
plt.axis('off')
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.set_aspect('equal')
plt.imshow(sample.reshape(28, 28), cmap='Greys_r')

if not os.path.exists('out/'):
os.makedirs('out/')

plt.savefig('out/{}.png'.format(str(cnt).zfill(3)), bbox_inches='tight')
cnt += 1
plt.close(fig)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import os


mnist = input_data.read_data_sets('../../MNIST_data', one_hot=True)
mb_size = 64
Z_dim = 100
X_dim = mnist.train.images.shape[1]
y_dim = mnist.train.labels.shape[1]
h_dim = 128


def xavier_init(size):
in_dim = size[0]
xavier_stddev = 1. / tf.sqrt(in_dim / 2.)
return tf.random_normal(shape=size, stddev=xavier_stddev)


""" Discriminator Net model """
X = tf.placeholder(tf.float32, shape=[None, 784])
y = tf.placeholder(tf.float32, shape=[None, y_dim])

D_W1 = tf.Variable(xavier_init([X_dim + y_dim, h_dim]))
D_b1 = tf.Variable(tf.zeros(shape=[h_dim]))

D_W2 = tf.Variable(xavier_init([h_dim, 1]))
D_b2 = tf.Variable(tf.zeros(shape=[1]))

theta_D = [D_W1, D_W2, D_b1, D_b2]


def discriminator(x, y):
inputs = tf.concat(axis=1, values=[x, y])
D_h1 = tf.nn.relu(tf.matmul(inputs, D_W1) + D_b1)
D_logit = tf.matmul(D_h1, D_W2) + D_b2
D_prob = tf.nn.sigmoid(D_logit)

return D_prob, D_logit


""" Generator Net model """
Z = tf.placeholder(tf.float32, shape=[None, Z_dim])

G_W1 = tf.Variable(xavier_init([Z_dim + y_dim, h_dim]))
G_b1 = tf.Variable(tf.zeros(shape=[h_dim]))

G_W2 = tf.Variable(xavier_init([h_dim, X_dim]))
G_b2 = tf.Variable(tf.zeros(shape=[X_dim]))

theta_G = [G_W1, G_W2, G_b1, G_b2]


def generator(z, y):
inputs = tf.concat(axis=1, values=[z, y])
G_h1 = tf.nn.relu(tf.matmul(inputs, G_W1) + G_b1)
G_log_prob = tf.matmul(G_h1, G_W2) + G_b2
G_prob = tf.nn.sigmoid(G_log_prob)

return G_prob


def sample_Z(m, n):
return np.random.uniform(-1., 1., size=[m, n])


def plot(samples):
fig = plt.figure(figsize=(4, 4))
gs = gridspec.GridSpec(4, 4)
gs.update(wspace=0.05, hspace=0.05)

for i, sample in enumerate(samples):
ax = plt.subplot(gs[i])
plt.axis('off')
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.set_aspect('equal')
plt.imshow(sample.reshape(28, 28), cmap='Greys_r')

return fig


G_sample = generator(Z, y)
D_real, D_logit_real = discriminator(X, y)
D_fake, D_logit_fake = discriminator(G_sample, y)

D_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logit_real, labels=tf.ones_like(D_logit_real)))
D_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logit_fake, labels=tf.zeros_like(D_logit_fake)))
D_loss = D_loss_real + D_loss_fake
G_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logit_fake, labels=tf.ones_like(D_logit_fake)))

D_solver = tf.train.AdamOptimizer().minimize(D_loss, var_list=theta_D)
G_solver = tf.train.AdamOptimizer().minimize(G_loss, var_list=theta_G)


sess = tf.Session()
sess.run(tf.global_variables_initializer())

if not os.path.exists('out/'):
os.makedirs('out/')

i = 0

for it in range(1000000):
if it % 1000 == 0:
n_sample = 16

Z_sample = sample_Z(n_sample, Z_dim)
y_sample = np.zeros(shape=[n_sample, y_dim])
y_sample[:, 7] = 1

samples = sess.run(G_sample, feed_dict={Z: Z_sample, y:y_sample})

fig = plot(samples)
plt.savefig('out/{}.png'.format(str(i).zfill(3)), bbox_inches='tight')
i += 1
plt.close(fig)

X_mb, y_mb = mnist.train.next_batch(mb_size)

Z_sample = sample_Z(mb_size, Z_dim)
_, D_loss_curr = sess.run([D_solver, D_loss], feed_dict={X: X_mb, Z: Z_sample, y:y_mb})
_, G_loss_curr = sess.run([G_solver, G_loss], feed_dict={Z: Z_sample, y:y_mb})

if it % 1000 == 0:
print('Iter: {}'.format(it))
print('D loss: {:.4}'. format(D_loss_curr))
print('G_loss: {:.4}'.format(G_loss_curr))
print()

修改后代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252


import torch
import torch.nn.functional as nn
import torch.autograd as autograd
import torch.optim as optim

import numpy as np

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

import os
from torch.autograd import Variable

import tensorflow as tf

import csv

mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()


x_train = x_train.reshape(x_train.shape[0], 784).astype('float32') / 255.
x_test = x_test.reshape(x_test.shape[0], 784).astype('float32') / 255.


y_train = tf.keras.utils.to_categorical(y_train, 10)
y_test = tf.keras.utils.to_categorical(y_test, 10)


def next_batch(num, data, labels):
idx = np.arange(0 , len(data))
np.random.shuffle(idx)
idx = idx[:num]
data_shuffle = [data[i] for i in idx]
labels_shuffle = [labels[i] for i in idx]
return np.asarray(data_shuffle), np.asarray(labels_shuffle)



mb_size = 64
Z_dim = 100
X_dim = x_train.shape[1]
y_dim = y_train.shape[1]


h_dim = 128
c = 0
lr = 1e-3



def xavier_init(size):
in_dim = size[0]
xavier_stddev = 1. / np.sqrt(in_dim / 2.)
return Variable(torch.randn(*size) * xavier_stddev, requires_grad=True)


""" ==================== GENERATOR ======================== """

Wzh = xavier_init(size=[Z_dim, h_dim])
bzh = Variable(torch.zeros(h_dim), requires_grad=True)

Whx = xavier_init(size=[h_dim, X_dim])
bhx = Variable(torch.zeros(X_dim), requires_grad=True)


def G(z):
h = nn.relu(z @ Wzh + bzh.repeat(z.size(0), 1))
X = nn.sigmoid(h @ Whx + bhx.repeat(h.size(0), 1))
return X


""" ==================== DISCRIMINATOR ======================== """

Wxh = xavier_init(size=[X_dim, h_dim])
bxh = Variable(torch.zeros(h_dim), requires_grad=True)

Why = xavier_init(size=[h_dim, 1])
bhy = Variable(torch.zeros(1), requires_grad=True)


def D(X):
h = nn.relu(X @ Wxh + bxh.repeat(X.size(0), 1))
y = nn.sigmoid(h @ Why + bhy.repeat(h.size(0), 1))
return y


G_params = [Wzh, bzh, Whx, bhx]
D_params = [Wxh, bxh, Why, bhy]
params = G_params + D_params


""" ===================== TRAINING ======================== """


def reset_grad():
for p in params:
if p.grad is not None:
data = p.grad.data
p.grad = Variable(data.new().resize_as_(data).zero_())


G_solver = optim.Adam(G_params, lr=1e-3)
D_solver = optim.Adam(D_params, lr=1e-3)


ones_label = Variable(torch.ones(mb_size, 1))
zeros_label = Variable(torch.zeros(mb_size, 1))


D_losses = []
G_losses = []


def moving_average(data, window_size):
cumsum = np.cumsum(np.insert(data, 0, 0))
return (cumsum[window_size:] - cumsum[:-window_size]) / window_size


if not os.path.exists('out_gan_pytorch_1/'):
os.makedirs('out_gan_pytorch_1/')
csv_file = open('out_gan_pytorch_1/loss_data.csv', 'w', newline='')
csv_writer = csv.writer(csv_file)
csv_writer.writerow(['Iteration', 'D_loss', 'G_loss'])


for it in range(100000):

z = Variable(torch.randn(mb_size, Z_dim))

X, _ = next_batch(mb_size, x_train, y_train)
X = Variable(torch.from_numpy(X))

""" ===================== 判别器训练 ======================== """

G_sample = G(z)
D_real = D(X)
D_fake = D(G_sample)


D_loss_real = nn.binary_cross_entropy(D_real, ones_label)
D_loss_fake = nn.binary_cross_entropy(D_fake, zeros_label)
D_loss = D_loss_real + D_loss_fake


D_loss.backward()
D_solver.step()



reset_grad()

""" ===================== 生成器训练 ======================== """


z = Variable(torch.randn(mb_size, Z_dim))
G_sample = G(z)
D_fake = D(G_sample)


G_loss = nn.binary_cross_entropy(D_fake, ones_label)


G_loss.backward()
G_solver.step()



reset_grad()


D_losses.append(D_loss.item())
G_losses.append(G_loss.item())



if it % 1000 == 0:
print('Iter-{}; D_loss: {}; G_loss: {}'.format(it, D_loss.data.numpy(), G_loss.data.numpy()))

samples = G(z).data.numpy()[:16]

fig = plt.figure(figsize=(4, 4))
gs = gridspec.GridSpec(4, 4)
gs.update(wspace=0.05, hspace=0.05)

for i, sample in enumerate(samples):
ax = plt.subplot(gs[i])
plt.axis('off')
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.set_aspect('equal')
plt.imshow(sample.reshape(28, 28), cmap='Greys_r')

if not os.path.exists('out_gan_pytorch_1/'):
os.makedirs('out_gan_pytorch_1/')

plt.savefig('out_gan_pytorch_1/{}.png'.format(str(c).zfill(3)), bbox_inches='tight')
c += 1
plt.close(fig)


with open('out_gan_pytorch_1/loss_data_ongoing.csv', 'a', newline='') as file:
writer = csv.writer(file)
if it == 0:
writer.writerow(["Iteration", "G_loss", "D_loss"])
writer.writerow([it, G_loss.item(), D_loss.item()])

print(f"Loss data at iteration {it} has been appended to 'out_gan_pytorch_1/loss_data_ongoing.csv'")


window_size = 1000
G_losses_avg = moving_average(G_losses, window_size)
D_losses_avg = moving_average(D_losses, window_size)


plt.figure(figsize=(10, 5))
plt.title("Generator and Discriminator Loss During Training")
plt.plot(G_losses, label="G")
plt.plot(D_losses, label="D")
plt.xlabel("iterations")
plt.ylabel("Loss")
plt.legend()
plt.savefig('out_gan_pytorch_1/loss_curve.png')
plt.close()


with open('out_gan_pytorch_1/loss_data.csv', 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(["Iteration", "G_loss", "D_loss"])
for i, (g_loss, d_loss) in enumerate(zip(G_losses, D_losses)):
writer.writerow([i, g_loss, d_loss])

print("Loss data has been saved to 'out_gan_pytorch_1/loss_data.csv'")


window_size = 1000
G_losses_avg = moving_average(G_losses, window_size)
D_losses_avg = moving_average(D_losses, window_size)


with open('out_gan_pytorch_1/loss_data_avg.csv', 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(["Iteration", "G_loss_avg", "D_loss_avg"])
for i, (g_loss, d_loss) in enumerate(zip(G_losses_avg, D_losses_avg)):
writer.writerow([i+window_size, g_loss, d_loss])

print("Averaged loss data has been saved to 'out_gan_pytorch_1/loss_data_avg.csv'")