我正在使用ACGAN网络来生成一些调制信号的星座图,在借鉴了大部分网上的方法后依然得不到较好的结果,生成的星座图只有混乱的黑白斑块。
用于训练的部分星座图如图所示




我的代码如下
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
from scipy.io import loadmat
class ACGAN():
def __init__(self):
self.img_row = 100
self.img_col = 100
self.channel = 1
self.img_shape = (self.img_row, self.img_col, self.channel)
self.class_num = 6
self.latent_dim = 100
losses = ['binary_crossentropy', 'categorical_crossentropy']
self.discriminator = self.discriminator_model()
self.discriminator.compile(loss=losses,
metrics=['accuracy'],
optimizer=tf.keras.optimizers.Adam(learning_rate=0.002))
self.generator = self.generator_model()
noise = layers.Input(shape=(self.latent_dim,))
label = layers.Input(shape=(1,))
img = self.generator([noise, label])
self.discriminator.trainable = False
valid, target_label = self.discriminator(img)
self.combined = keras.Model([noise, label], [valid, target_label])
self.combined.compile(loss=losses,
optimizer=tf.keras.optimizers.Adam(learning_rate=0.002))
def generator_model(self):
# 定义生成器
noise=layers.Input(shape=(self.latent_dim,))
modulation=layers.Input(shape=(1,))
modulation_embedding=layers.Flatten()(layers.Embedding(self.class_num, self.latent_dim)(modulation))
generator_input=layers.multiply([noise,modulation_embedding])
x = layers.Dense(5 * 5 * 32, activation='relu')(generator_input)
x = layers.Reshape((5, 5, 32))(x)
x = layers.Conv2D(16, (2, 2), padding='same')(x)
x = layers.BatchNormalization(momentum=0.8)(x)
x = layers.Activation('relu')(x)
x = layers.UpSampling2D(size=(2,2))(x)
x = layers.Conv2D(32, (2, 2), padding='same')(x)
x = layers.BatchNormalization(momentum=0.8)(x)
x = layers.Activation('relu')(x)
x = layers.UpSampling2D(size=(2,2))(x)
x = layers.Conv2D(64, (2, 2), padding='same')(x)
x = layers.BatchNormalization(momentum=0.8)(x)
x = layers.Activation('relu')(x)
x = layers.UpSampling2D(size=(5, 5))(x)
x = layers.Conv2D(128, (2, 2), padding='same')(x)
x = layers.BatchNormalization(momentum=0.8)(x)
x = layers.Activation('relu')(x)
img = layers.Conv2D(1, (2, 2), padding='same', activation='tanh')(x)
model = keras.Model(inputs=[noise, modulation], outputs=img, name='generator')
return model
def discriminator_model(self):
# 定义鉴别器
img = layers.Input(shape=self.img_shape)
x = layers.Conv2D(16, (2, 2), strides=2, padding='same', activation='relu')(img)
x = layers.Dropout(0.25)(x)
x = layers.Conv2D(32, (2, 2), strides=2, padding='same', activation='relu')(x)
x = layers.Dropout(0.25)(x)
x = layers.Conv2D(64, (2, 2), strides=1, padding='same', activation='relu')(x)
x = layers.Dropout(0.25)(x)
x = layers.Conv2D(128, (2, 2), strides=1, padding='same', activation='relu')(x)
x = layers.Dropout(0.25)(x)
x = layers.GlobalAveragePooling2D()(x)
validity = layers.Dense(1, activation='sigmoid')(x)
label = layers.Dense(self.class_num, activation='softmax')(x)
model = keras.Model(inputs=img, outputs=[validity, label], name='discriminator')
return model
def train(self, epochs, batch_size):
# 数据加载
BPSK=loadmat('....../subsetBPSK.mat')
BPSK=np.array(BPSK['subsetBPSK'])
#OQPSK, GMSK, QAM128, PSK32, QPSK,同理
X_train=np.concatenate((OQPSK, GMSK, QAM128, PSK32, QPSK, BPSK), axis=0)
Y_train=np.concatenate((np.zeros((100, 1), dtype=int), np.ones((100, 1), dtype=int),
np.ones((100, 1), dtype=int)*2, np.ones((100, 1), dtype=int)*3,
np.ones((100, 1), dtype=int)*4, np.ones((100, 1), dtype=int)*5), axis=0)
# 归一化
X_train = (255 - X_train.astype(np.float32))/255.0 #这里我将原本白底黑字的星座图转换为黑底白字,并归一化
X_train = np.expand_dims(X_train, axis=3)
real=np.ones((batch_size,1))
fake=np.zeros((batch_size,1))
for epoch in range(epochs):
# 数据调用
index=np.random.randint(0, X_train.shape[0], batch_size)
imgs=X_train[index]
label=Y_train[index].reshape(-1,1)
# 训练鉴别器
noise=np.random.normal(0,1, size=(batch_size, self.latent_dim))
sampled_label=np.random.randint(0, self.class_num, (batch_size, 1))
gen_imgs=self.generator.predict([noise, sampled_label])
label_cat=tf.keras.utils.to_categorical(label, num_classes=self.class_num)
sampled_label_cat=tf.keras.utils.to_categorical(sampled_label, num_classes=self.class_num)
d_loss_real=self.discriminator.train_on_batch(imgs, [real, label_cat])
d_loss_fake=self.discriminator.train_on_batch(gen_imgs, [fake, sampled_label_cat])
d_loss=0.5*np.add(d_loss_real, d_loss_fake)
# 训练生成器
noise=np.random.normal(0,1, size=(batch_size, self.latent_dim))
sampled_label=np.random.randint(0, self.class_num, (batch_size, 1))
sampled_label_cat=tf.keras.utils.to_categorical(sampled_label, num_classes=self.class_num)
g_loss=self.combined.train_on_batch([noise, sampled_label], [real, sampled_label_cat])
if epoch % 50 == 0:
print('epochs:', epoch)
print('Discriminator loss:', d_loss[0], 100*d_loss[3], 100*d_loss[4])
print('Generator loss:', g_loss[0])
if epoch % 100 == 0: #每100轮保存一次图片
noise=np.random.normal(0,1, size=(6, 100))
sampled_labels=np.arange(0,6).reshape(-1, 1)
gen_img=self.generator.predict([noise, sampled_labels])
# gen_img = 0.5 * gen_img + 0.5 这行代码一直没搞明白用法
fig, axs = plt.subplots(2,3)
cnt=0
for i in range(2):
for j in range(3):
axs[i,j].imshow(gen_img[cnt,:,:,0],cmap='gray')
axs[i,j].set_title("%d" % sampled_labels[cnt])
axs[i,j].axis('off')
cnt+=1
fig.savefig('gen/%d.png' % epoch)
plt.close()
self.generator.save('generator.h5')
if __name__ == '__main__':
acgan=ACGAN()
acgan.train(epochs=20000, batch_size=32)
生成器输入的训练样本为(12000 100 100 1)共120000个100X100像素的灰度图,输出为100X100。生成效果很差,这里没做过多展示。
我在查阅文献时,找到了使用GAN网络生成星座图的例子,他们都有较好的结果

代码主要参考了以下博客
https://blog.csdn.net/weixin_44791964/article/details/103746380
https://blog.csdn.net/qq_40784418/article/details/105799289
希望有人能帮我看看代码哪里出了问题十分感谢!