|

【AI生程藝術之路】PaddlePaddle的3D點雲GAN模型(下)

   
作者:高煥堂

接續本文上集,我們複習一下GAN的兩個角色:生成器(G)和判別器(D)。

準備訓練數據:使用ShapeNet數據集

GAN(生成對抗網)是由蒙特利爾大學的Ian Goodfellow在2014年提出來的神經網路模型。GAN通常包含兩個角色,兩者互相較量(對抗),但又展現出教學相長,共同成長的美好機制和效果。這兩個角色就是:判別者(Discriminator)與生成者(Generator)。

其中的判別者(D)是老師角色,而生成者(G)則是學生角色。老師引導學生創作,兩者互相較量(對抗),但又展現出教學相長的效果。例如,在圖像渲染的應用上,它們的功能分別是:

  •  G(學生)負責生成圖片。它接收一個隨機噪音(z),或者其他條件(如黑白底圖或邊框),然後基于這個噪音或條件來生成新圖片。
  • D(老師)負責辨別一張圖片的真或假。它的輸入是一張圖片,進行辨別之後,輸出其判斷爲真品或假品的概率。如果輸出值愈接近于1,代表其爲真品的概率愈大;而當輸出值愈接0,代表其爲假品的概率愈大。

在GAN模型的訓練過程中,我們會拿真品來輸入給D,也會拿由G生成的假品來輸入給D。其目的是要訓練D,以便提升它判斷圖片真或假的能力。

如果D判斷正確,表示G(學生)生成的新作品(假品),被D識破了,這意味著G的作品不够逼真,此時G就會依據D的反饋而調整其參數,因而G就成長了。反之,如果D判斷錯誤,表示D的辨別能力不足,例如被G騙了(將假品誤判爲真品),于是D就會調整其參數,因而D也成長了。

這樣的訓練過程,持續重複下去,GAN裏的兩個角色,互相較量(對抗),展現出了教學相長的美好效果。最後,G大幅成長了,繪製出來非常逼真的作品(假品)了。

程式4:定義GAN的生成器,並進行訓練

定義並單獨訓練生成器(G);暫時不訓練判別器(D)。

由生成器(Generator)自己學習重建點雲3D圖像,訓練300回合。並且,把訓練過程的圖像(儲存)顯示出來。在訓練過程中,每60回合儲存一次。程式碼如下:

# paa_GAN_005.py

import numpy as np

import os

import torch

import paddle

import paddle.nn as nn

import paddle.optimizer as optim

from paddle.io import Dataset, DataLoader

import scipy.ndimage as nd

import scipy.io as sio

import matplotlib.gridspec as gridspec

import matplotlib.pyplot as plt

data_dir = 'c:/oopc/ShapeNet_data/chair/train/'

file_list = [os.path.join(data_dir, name)

for name in os.listdir(data_dir)

if name.endswith('.mat')]

print(len(file_list))

#-----------------------------------------------------

nchw =

# 讀取一個3D的*.mat檔案

def getVoxelFromMat(file_path):

voxels = sio.loadmat(file_path)

voxels = np.pad(voxels, (1, 1), 'constant', constant_values=(0, 0))

if nchw != 32:

ratio = nchw / 32.

voxels = nd.zoom(voxels, (ratio, ratio, ratio),

mode='constant', order=0)

return voxels

def SavePloat_Voxels(voxels, path, iteration):

voxels = voxels.__ge__(0.5)

fig = plt.figure(figsize=(32, 16))

gs = gridspec.GridSpec(2, 4)

gs.update(wspace=0.05, hspace=0.05)

for i, sample in enumerate(voxels):

x, y, z = sample.nonzero()

ax = plt.subplot(gs, projection='3d')

ax.scatter(x, y, z, zdir='z', c='red')

ax.set_xticklabels()

ax.set_yticklabels()

plt.savefig(path + '/{}.png'.format(str(iteration).zfill(3)), bbox_inches='tight')

plt.close()

#---------------------------------

class ShapeNetDataset(Dataset):

def __init__(self):

self.filenames = file_list

def __getitem__(self, index):

fna = self.filenames

volume = np.asarray(getVoxelFromMat(fna), dtype=np.float32)

return paddle.to_tensor(volume)

def __len__(self):

return len( self.filenames)

#---------------------------------------

batch_size = 1

d_thresh = 0.8

z_dim = 100

f_dim = 32

g_lr = 0.0025

d_lr = 0.0005

beta = (0.5, 0.999)

cube_len = 32

leak_value = 0.2

bias = False

def get_noise():

z = paddle.normal(shape=)

z = paddle.to_tensor(z)

return z

class Generator(nn.Layer):

def __init__(self):

super().__init__()

self.cube_len = cube_len

padd = (0, 0, 0)

if self.cube_len == 32:

padd = (1,1,1)

self.layer1 = nn.Sequential(

nn.Conv3DTranspose(z_dim, f_dim * 8,

kernel_size=4, stride=2,

padding=(1,1,1), bias_attr=False),

nn.BatchNorm3D(f_dim*8),

nn.ReLU()

)

self.layer2 = nn.Sequential(

nn.Conv3DTranspose(f_dim * 8, f_dim * 4,

kernel_size=4, stride=2,

padding=(1,1,1), bias_attr=False),

nn.BatchNorm3D(f_dim*4),

nn.ReLU()

)

self.layer3 = nn.Sequential(

nn.Conv3DTranspose(f_dim * 4, f_dim * 2,

kernel_size=4, stride=2,

padding=(1,1,1), bias_attr=False),

nn.BatchNorm3D(f_dim*2),

nn.ReLU()

)

self.layer4 = nn.Sequential(

nn.Conv3DTranspose(f_dim * 2, f_dim,

kernel_size=4, stride=2,

padding=(1,1,1), bias_attr=False),

nn.BatchNorm3D(f_dim),

)

self.layer5 = nn.Sequential(

nn.Conv3DTranspose(f_dim, 1,

kernel_size=4, stride=2,

padding=(1,1,1), bias_attr=False),

nn.Sigmoid()

)

def forward(self, x):

x = paddle.reshape(x, shape=)

x = self.layer1(x)

x = self.layer2(x)

x = self.layer3(x)

x = self.layer4(x)

x = self.layer5(x)

return x

#----------------------------------------------------

G = Generator()

optimizer_g = optim.Adam(learning_rate=g_lr, parameters=G.parameters())

L1_loss = nn.L1Loss()

#-------------------------------------------------

dataset = ShapeNetDataset()

real_vx = dataset

real_vx = real_vx.unsqueeze(0)

print('開始訓練 300回合...')

num_epochs = 300

for ep in range(num_epochs+1):

#print(ep)

G.train()

noise = get_noise()

gen_vx = G(noise)

loss_g = L1_loss(gen_vx, real_vx) * 100

loss_g.backward()

optimizer_g.step()

optimizer_g.clear_grad()

if(ep%60 == 0):

gen_vx = gen_vx.squeeze(0)

vx = gen_vx.numpy()

SavePloat_Voxels(vx, 'c:/oopc/ShapeNet_data/', ep)

#-------------------------------------

#END

在訓練生成器(G)共300回合的在訓練過程中,每60回合儲存一次寫入圖檔(儲存於/ShapeNet_data/裡),如下:

本文為會員限定文章

立即加入會員! 全站文章無限看~

                               

已經是會員? 按此登入

只需不到短短一分鐘...

輸入您的信箱與ID註冊即可享有一切福利!

會員福利
1

免費電子報

2

會員搶先看

3

主題訂閱

4

好文收藏

高煥堂

Author: 高煥堂

擁有40多年軟硬體整合設計經驗,專精Android終端平台、AI、Docker容器、VR、AI(人工智慧)、IC軟硬整合技術與大數據應用。 近5年來,從事於AI普及化教育工作,目前擔任銘傳大學AI課程、長庚智慧醫療研究所AI課程授課老師。也擔任永春國小、東園國小、立志中學、君毅中學、永春高中等學校的AI師資培育工作。

Share This Post On

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *