巴萨你是信仰你是光 2024-03-01 11:09 采纳率: 0%
浏览 10
已结题

使用ACGAN网络生成调制信号星座图,效果不理想

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

img

img

img

img

我的代码如下

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网络生成星座图的例子,他们都有较好的结果

img

代码主要参考了以下博客
https://blog.csdn.net/weixin_44791964/article/details/103746380
https://blog.csdn.net/qq_40784418/article/details/105799289

希望有人能帮我看看代码哪里出了问题十分感谢!

  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2024-03-01 11:10
    关注

    巴萨你是信仰你是光 上午好☀️☀️☀️️
    本答案参考通义千问

    问题分析: 你的代码中ACGAN模型用于生成调制信号的星座图效果不佳,可能的原因有:

    1. 数据预处理和归一化:你提到将原本白底黑字的星座图转换为黑底白字并归一化,这可能导致生成的图像颜色反转,与训练数据不一致。
    2. 生成器和判别器的结构:你没有提供判别器和生成器的完整结构,这可能会影响它们学习到的特征表示。特别是,判别器的输出层可能需要调整以更好地适应分类任务。
    3. 损失函数和优化器:你使用的损失函数是二元交叉熵和多类别交叉熵,但没有明确说明如何结合这两个损失,这可能影响模型的训练过程。
    4. 噪声分布:噪声输入是否足够随机,影响生成的多样性。
    5. 学习率和迭代次数:训练轮数和学习率可能需要进一步调整以达到更好的收敛。

    解决方案:

    1. 数据处理

      • 确保输入数据是黑白图像,不需要转换颜色。如果原始数据是白底黑字,可以保持不变。
      • 检查归一化的范围:确保归一化后的数据在0-1范围内,而不是-1到1。
    2. 模型结构

      • 查看判别器的输出层:确保它有适当的输出维度和激活函数,例如对于分类任务,输出层可能是Softmax而不是Sigmoid。
      • 尝试不同的网络结构:比如增加更多的卷积层、批标准化层等,以提高模型性能。
    3. 损失函数

      • 结合损失函数:二元交叉熵用于判断真实样本和生成样本,多类别交叉熵用于分类标签,可以尝试组合权重,或者使用Wasserstein距离等其他更合适的损失。
    4. 噪声和标签输入

      • 噪声分布:确保噪声分布均匀,可以考虑使用正态分布或其他分布。
      • 标签输入:使用one-hot编码或独热编码来表示类别标签。
    5. 训练参数

      • 学习率:尝试调整Adam优化器的学习率,或者使用学习率衰减策略。
      • 迭代次数:增加训练轮数,观察模型是否在后期有所改进。

    代码修改建议:

    • generator_model中,确保最后的激活函数是sigmoid而不是tanh,因为输出应该是0-1之间的概率值。
    • discriminator_model中,输出层的validity部分使用sigmoid激活函数,label部分使用softmax激活函数。
    # 修改后的生成器模型
    def generator_model(self):
        ...
        x = layers.Conv2D(1, (2, 2), padding='same', activation='sigmoid')(x)  # 将tanh改为sigmoid
        img = x
        ...
    
    # 修改后的判别器模型
    def discriminator_model(self):
        ...
        validity = layers.Dense(1, activation='sigmoid')(x)  # 添加sigmoid激活函数
        label = layers.Dense(self.class_num, activation='softmax')(x)  # 确保label输出层是softmax
        ...
    

    完整的代码示例(仅供参考)

    ...
    # 修改后的损失函数计算
    d_loss_real = self.discriminator.train_on_batch(imgs, [real, label_cat], [True, label_cat])  # 为validity添加True标签
    d_loss_fake = self.discriminator.train_on_batch(gen_imgs, [fake, sampled_label_cat], [False, sampled_label_cat])  # 为validity添加False标签
    ...
    
    # 训练生成器
    g_loss = self.combined.train_on_batch([noise, sampled_label], [real, sampled_label_cat], [True, sampled_label_cat])  # 为validity添加True标签
    ...
    

    尝试以上修改并调整其他参数,如学习率、训练轮数等,观察模型性能是否有改善。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月12日
  • 创建了问题 3月1日