示例#1
0
    # 构建数据集迭代器
    train_loader = torch.utils.data.DataLoader(train_dataset,
                                               batch_size=batch_size,
                                               shuffle=True)
    test_loader = torch.utils.data.DataLoader(test_dataset,
                                              batch_size=batch_size,
                                              shuffle=True)
    """初始化CNN网络"""
    Minionn_5 = Minionn_fivelayer(in_dim=1, n_class=10)
    print('Minionn_5: \n', Minionn_5)
    """构建优化器"""
    loss_fn = NLLLoss()
    lr = 1e-3  # Adam优化器的学习率
    beta1 = 0.5  # Adam优化器的参数(需要调整试试?)
    optimizer = Adam(Minionn_5.parameters(),
                     learning_rate=lr,
                     betas=(beta1, 0.999))  # 测试一下Adam优化器
    """加载预训练的模型"""

    pre_module_path = "./model_save/Minionn_5/Minionn_5_parameters-5.pkl"
    params = torch.load(pre_module_path)
    Minionn_5.load_state_dict(params['state_dict'])  # 加载模型
    n_epochs_pre = params['epoch']
    """迭代训练"""

    for epoch in range(n_epochs):
        # break
        running_loss = 0.0
        running_correct = 0
        print("Epoch {}/{}".format(epoch, n_epochs))
        print("-" * 10)
示例#2
0
def test_dcgan():
    start_time = time.time()
    # 设置transform
    cifar_transform = transforms.Compose([
        Data_loader.cifar_Resize((3,32,32))
    ])
    """加载CIFAR-10数据集"""
    root_dir = './data/cifar-10/cifar-10-python/cifar-10-batches-py'
    cifar_train_dataset = Data_loader.CifarDataset(root_dir, transform=cifar_transform, train=True)
    print('traindata_len: \n',len(cifar_train_dataset))
    # 构建数据集迭代器
    cifar_train_loader = torch.utils.data.DataLoader(cifar_train_dataset, batch_size=batch_size, shuffle=True)
    
    """初始化网络、参数"""
    netG = Generator()
    netG.apply(weights_init)
    print('netG: \n', netG)
    
    netD = Discriminator()
    netD.apply(weights_init)
    print('netD: \n', netD)


    """构建优化器"""
    # 二进制交叉熵损失函数
    loss = BECLoss()
    # 噪声从标准正态分布(均值为0,方差为 1,即高斯白噪声)中随机抽取一组数
    fixed_noise = np.random.normal(0.0, 1.2, size=(64,nz, 1,1)) # 用于G生成图像时固定的噪声初始化
    # 定义真假样本标签
    real_label = 1
    fake_label = 0
    # 定义Adam优化器
    optimizerD = Adam(netD.parameters(), learning_rate=lr, betas=(beta1, 0.999))
    optimizerG = Adam(netG.parameters(), learning_rate=lr, betas=(beta1, 0.999))

    """训练模型,生成数据"""
    # 存储生成的图像
    img_list = []
    # 记录G和D的损失
    G_losses = []
    D_losses = []
    iters = 0

    """加载预训练的模型"""
    '''
    pre_module_path = "./model_save/lenet_numpy_parameters-cifar-Adam-1.pkl"
    params = torch.load(pre_module_path)
    netD.load_state_dict(params['D_state_dict']) # 加载模型
    netG.load_state_dict(params['G_state_dict']) # 加载模型
    num_epochs_pre = params['epoch']
    '''
    
    print("----------start training loop----------")

    for epoch in range(num_epochs):
        # dataloader获取真实图像
        for t, (data, target) in enumerate(cifar_train_loader, 0):
            '''
                (1)先更新D Update D network: minimize -[ log(D(x)) + log(1 - D(G(z))) ]
                训练D的目标是让D更加有能力判断真假数据
            '''
            ## 使用真实数据X进行训练(计算log(D(x)))
            netD.zero_grad() # 训练更新前需要在每个batch中将梯度设置为0
            real_data = data.detach().numpy()
            # print('real_data: \n',real_data[0])
            # print('real_data shape: \n',real_data[0].shape)
            # break
            ## MNIST 数据需要先从1x28x28填充到1x32x32
            # if is_mnist:
            #     real_data = np.pad(real_data, ((0, 0), (0, 0), (2, 2), (2, 2)), 'constant', constant_values=0)
            b_size = real_data.shape[0]
            label = np.full((b_size,), real_label)
            # 计算D前向传播值
            output_d_real = netD.forward(real_data).reshape(-1)
            # 计算D真实数据交叉熵损失
            errD_real = loss.forward(output_d_real, label)
            # 计算D的梯度
            dy_errD_real = loss.gradient()
            netD.backward(dy_errD_real)
            
            ## 使用生成数据进行训练(计算log(1 - D(G(z))))
            noise = np.random.normal(0.0, 1.2, size=(b_size, nz, 1,1)) # 训练每次单独生成噪声
            # G生成假数据
            fake_data = netG.forward(noise)
            label.fill(fake_label)
            # D识别假数据
            output_d_fake = netD.forward(fake_data).reshape(-1)
            # 计算D假数据交叉熵损失
            errD_fake = loss.forward(output_d_fake, label)
            # 计算D的梯度
            dy_errD_fake = loss.gradient()
            netD.backward(dy_errD_fake)

            # 计算总损失
            errD = errD_real+errD_fake

            # 计算D(x),D(G(z))的均值
            D_x = np.mean(output_d_real)
            D_G_z1 = np.mean(output_d_fake)

            # 更新D参数
            optimizerD.step()

            '''
                (2)更新G Update G network: minimize -log(D(G(z)))
            '''
            netG.zero_grad()
            # 填充真实标签,使得交叉熵函数可以只计算log(D(G(z))部分
            label.fill(real_label)
            output_d_fake = netD.forward(fake_data).reshape(-1)
            errG = loss.forward(output_d_fake, label)
            # 计算G的梯度(梯度需要从D传向G)
            dy_errG = loss.gradient()
            dy_netD = netD.backward(dy_errG)
            netG.backward(dy_netD)
            # 计算D(G(z))的均值
            D_G_z2 = np.mean(output_d_fake)
            # 更新G参数(不会去计算D的梯度2333)
            optimizerG.step()

            """输出训练状态"""
            # Loss_D
            # Loss_G
            # D(x):训练中D对真实数据的平均预测输出
            # D(G(z)):训练中D对虚假数据的平均预测输出(为啥是除法??)
            if t % 10 == 0:
                end_time1 = time.time()
                print('[%d/%d][%d/%d]\t Loss_D: %.4f\t Loss_G: %.4f\t D(x): %.4f\t D(G(z)): %.4f / %.4f\t train time: %.4f min'
                  % (epoch, num_epochs, t, len(cifar_train_loader), errD, errG, D_x, D_G_z1, D_G_z2, (end_time1-start_time)/60))

            # 记录损失的历史,可以用作画图
            G_losses.append(errG)
            D_losses.append(errD)

            # 记录G生成的图像
            if (iters % 500 == 0) or ((epoch == num_epochs-1) and (t == len(cifar_train_loader)-1)):
                fake_img = netG.forward(fixed_noise)# 一次生成64张图
                fake_tensor = torch.tensor(fake_img)
                img_list.append(vutils.make_grid(fake_tensor, padding=2, normalize=True))
            
            iters += 1
        """绘图:记录损失"""
        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()
        # 保存图片
        time_stemp = time.strftime("%Y-%m-%d-%H-%M", time.localtime())
        plt.savefig('./experiment_img/gan_generate/Loss_fig-cifar-Adam-'+str(epoch+num_epochs_pre)+'('+time_stemp+').png')
        # plt.show()

        """绘图:记录G输出"""
        real_batch = next(iter(cifar_train_loader))
        # Plot the real images
        plt.figure(figsize=(15,15))
        plt.subplot(1,2,1)
        plt.axis("off")
        plt.title("Real Images")
        plt.imshow(np.transpose(vutils.make_grid(real_batch[0][:64], padding=5, normalize=True).cpu(),(1,2,0)))

        # Plot the fake images from the last epoch
        plt.subplot(1,2,2)
        plt.axis("off")
        plt.title("Fake Images")
        plt.imshow(np.transpose(img_list[-1],(1,2,0)))

        # 保存图片
        plt.savefig('./experiment_img/gan_generate/Real_Generate-cifar-Adam-'+str(epoch+num_epochs_pre)+'('+time_stemp+').png')
        # plt.show()
        end_time = time.time()
        print('training time: \n', (end_time-start_time)/60)

        '''存储模型'''
        checkpoint_path = "./model_save/DCGAN_numpy_parameters-cifar-Adam-"+str(epoch+num_epochs_pre)+".pkl"
        torch.save({'epoch':num_epochs+num_epochs_pre, 'D_state_dict':netD.state_dict(), 'G_state_dict':netG.state_dict(), 'G_losses':G_losses, 'D_losses':D_losses}, checkpoint_path)