国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

做外貿(mào)網(wǎng)站要注意什么查企業(yè)信息查詢平臺

做外貿(mào)網(wǎng)站要注意什么,查企業(yè)信息查詢平臺,目錄網(wǎng)站開發(fā),做外貿(mào)翻譯用那個網(wǎng)站Diffusion擴(kuò)散模型 關(guān)于擴(kuò)散模型(Diffusion Models)有很多種理解,本文的介紹是基于denoising diffusion probabilistic model (DDPM),DDPM已經(jīng)在(無)條件圖像/音頻/視頻生成領(lǐng)域取得…

Diffusion擴(kuò)散模型

關(guān)于擴(kuò)散模型(Diffusion Models)有很多種理解,本文的介紹是基于denoising diffusion probabilistic model (DDPM),DDPM已經(jīng)在(無)條件圖像/音頻/視頻生成領(lǐng)域取得了較多顯著的成果,現(xiàn)有的比較受歡迎的的例子包括由OpenAI主導(dǎo)的GLIDE和DALL-E 2、由海德堡大學(xué)主導(dǎo)的潛在擴(kuò)散和由Google Brain主導(dǎo)的圖像生成。

實際上生成模型的擴(kuò)散概念已經(jīng)在(Sohl-Dickstein et al., 2015)中介紹過。然而,直到(Song et al., 2019)(斯坦福大學(xué))和(Ho et al., 2020)(在Google Brain)才各自獨立地改進(jìn)了這種方法。

本文是在Phil Wang基于PyTorch框架的復(fù)現(xiàn)的基礎(chǔ)上(而它本身又是基于TensorFlow實現(xiàn)),遷移到MindSpore AI框架上實現(xiàn)的。

import math
from functools import partial
%matplotlib inline
import matplotlib.pyplot as plt
from tqdm.auto import tqdm
import numpy as np
from multiprocessing import cpu_count
from download import downloadimport mindspore as ms
import mindspore.nn as nn
import mindspore.ops as ops
from mindspore import Tensor, Parameter
from mindspore import dtype as mstype
from mindspore.dataset.vision import Resize, Inter, CenterCrop, ToTensor, RandomHorizontalFlip, ToPIL
from mindspore.common.initializer import initializer
from mindspore.amp import DynamicLossScalerms.set_seed(0)

模型簡介

什么是Diffusion Model?

如果將Diffusion與其他生成模型(如Normalizing Flows、GAN或VAE)進(jìn)行比較,它并沒有那么復(fù)雜,它們都將噪聲從一些簡單分布轉(zhuǎn)換為數(shù)據(jù)樣本,Diffusion也是從純噪聲開始通過一個神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)逐步去噪,最終得到一個實際圖像。 Diffusion對于圖像的處理包括以下兩個過程:

  • 我們選擇的固定(或預(yù)定義)正向擴(kuò)散過程?𝑞q?:它逐漸將高斯噪聲添加到圖像中,直到最終得到純噪聲

  • 一個學(xué)習(xí)的反向去噪的擴(kuò)散過程?𝑝𝜃pθ?:通過訓(xùn)練神經(jīng)網(wǎng)絡(luò)從純噪聲開始逐漸對圖像去噪,直到最終得到一個實際的圖像

Image-2

由?𝑡t?索引的正向和反向過程都發(fā)生在某些有限時間步長?𝑇(DDPM作者使用?𝑇=1000T=1000)內(nèi)。從𝑡=0開始,在數(shù)據(jù)分布中采樣真實圖像?𝐱0(本文使用一張來自ImageNet的貓圖像形象的展示了diffusion正向添加噪聲的過程),正向過程在每個時間步長?𝑡?都從高斯分布中采樣一些噪聲,再添加到上一個時刻的圖像中。假定給定一個足夠大的?𝑇和一個在每個時間步長添加噪聲的良好時間表,您最終會在?𝑡=𝑇?通過漸進(jìn)的過程得到所謂的各向同性的高斯分布。

構(gòu)建Diffusion模型

下面,我們逐步構(gòu)建Diffusion模型。

首先,我們定義了一些幫助函數(shù)和類,這些函數(shù)和類將在實現(xiàn)神經(jīng)網(wǎng)絡(luò)時使用。

def rearrange(head, inputs):b, hc, x, y = inputs.shapec = hc // headreturn inputs.reshape((b, head, c, x * y))def rsqrt(x):res = ops.sqrt(x)return ops.inv(res)def randn_like(x, dtype=None):if dtype is None:dtype = x.dtyperes = ops.standard_normal(x.shape).astype(dtype)return resdef randn(shape, dtype=None):if dtype is None:dtype = ms.float32res = ops.standard_normal(shape).astype(dtype)return resdef randint(low, high, size, dtype=ms.int32):res = ops.uniform(size, Tensor(low, dtype), Tensor(high, dtype), dtype=dtype)return resdef exists(x):return x is not Nonedef default(val, d):if exists(val):return valreturn d() if callable(d) else ddef _check_dtype(d1, d2):if ms.float32 in (d1, d2):return ms.float32if d1 == d2:return d1raise ValueError('dtype is not supported.')class Residual(nn.Cell):def __init__(self, fn):super().__init__()self.fn = fndef construct(self, x, *args, **kwargs):return self.fn(x, *args, **kwargs) + xdef Upsample(dim):return nn.Conv2dTranspose(dim, dim, 4, 2, pad_mode="pad", padding=1)def Downsample(dim):return nn.Conv2d(dim, dim, 4, 2, pad_mode="pad", padding=1)

位置向量

由于神經(jīng)網(wǎng)絡(luò)的參數(shù)在時間(噪聲水平)上共享,作者使用正弦位置嵌入來編碼𝑡t,靈感來自Transformer(Vaswani et al., 2017)。對于批處理中的每一張圖像,神經(jīng)網(wǎng)絡(luò)"知道"它在哪個特定時間步長(噪聲水平)上運行。

SinusoidalPositionEmbeddings模塊采用(batch_size, 1)形狀的張量作為輸入(即批處理中幾個有噪聲圖像的噪聲水平),并將其轉(zhuǎn)換為(batch_size, dim)形狀的張量,其中dim是位置嵌入的尺寸。然后,我們將其添加到每個剩余塊中。

class SinusoidalPositionEmbeddings(nn.Cell):def __init__(self, dim):super().__init__()self.dim = dimhalf_dim = self.dim // 2emb = math.log(10000) / (half_dim - 1)emb = np.exp(np.arange(half_dim) * - emb)self.emb = Tensor(emb, ms.float32)def construct(self, x):emb = x[:, None] * self.emb[None, :]emb = ops.concat((ops.sin(emb), ops.cos(emb)), axis=-1)return emb

ResNet/ConvNeXT塊

接下來,我們定義U-Net模型的核心構(gòu)建塊。DDPM作者使用了一個Wide ResNet塊(Zagoruyko et al., 2016),但Phil Wang決定添加ConvNeXT(Liu et al., 2022)替換ResNet,因為后者在圖像領(lǐng)域取得了巨大成功。

在最終的U-Net架構(gòu)中,可以選擇其中一個或另一個,本文選擇ConvNeXT塊構(gòu)建U-Net模型。

class Block(nn.Cell):def __init__(self, dim, dim_out, groups=1):super().__init__()self.proj = nn.Conv2d(dim, dim_out, 3, pad_mode="pad", padding=1)self.proj = c(dim, dim_out, 3, padding=1, pad_mode='pad')self.norm = nn.GroupNorm(groups, dim_out)self.act = nn.SiLU()def construct(self, x, scale_shift=None):x = self.proj(x)x = self.norm(x)if exists(scale_shift):scale, shift = scale_shiftx = x * (scale + 1) + shiftx = self.act(x)return xclass ConvNextBlock(nn.Cell):def __init__(self, dim, dim_out, *, time_emb_dim=None, mult=2, norm=True):super().__init__()self.mlp = (nn.SequentialCell(nn.GELU(), nn.Dense(time_emb_dim, dim))if exists(time_emb_dim)else None)self.ds_conv = nn.Conv2d(dim, dim, 7, padding=3, group=dim, pad_mode="pad")self.net = nn.SequentialCell(nn.GroupNorm(1, dim) if norm else nn.Identity(),nn.Conv2d(dim, dim_out * mult, 3, padding=1, pad_mode="pad"),nn.GELU(),nn.GroupNorm(1, dim_out * mult),nn.Conv2d(dim_out * mult, dim_out, 3, padding=1, pad_mode="pad"),)self.res_conv = nn.Conv2d(dim, dim_out, 1) if dim != dim_out else nn.Identity()def construct(self, x, time_emb=None):h = self.ds_conv(x)if exists(self.mlp) and exists(time_emb):assert exists(time_emb), "time embedding must be passed in"condition = self.mlp(time_emb)condition = condition.expand_dims(-1).expand_dims(-1)h = h + conditionh = self.net(h)return h + self.res_conv(x)

Attention模塊

接下來,我們定義Attention模塊,DDPM作者將其添加到卷積塊之間。Attention是著名的Transformer架構(gòu)(Vaswani et al., 2017),在人工智能的各個領(lǐng)域都取得了巨大的成功,從NLP到蛋白質(zhì)折疊。Phil Wang使用了兩種注意力變體:一種是常規(guī)的multi-head self-attention(如Transformer中使用的),另一種是LinearAttention(Shen et al., 2018),其時間和內(nèi)存要求在序列長度上線性縮放,而不是在常規(guī)注意力中縮放。 要想對Attention機制進(jìn)行深入的了解,請參照J(rèn)ay Allamar的精彩的博文。

class Attention(nn.Cell):def __init__(self, dim, heads=4, dim_head=32):super().__init__()self.scale = dim_head ** -0.5self.heads = headshidden_dim = dim_head * headsself.to_qkv = nn.Conv2d(dim, hidden_dim * 3, 1, pad_mode='valid', has_bias=False)self.to_out = nn.Conv2d(hidden_dim, dim, 1, pad_mode='valid', has_bias=True)self.map = ops.Map()self.partial = ops.Partial()def construct(self, x):b, _, h, w = x.shapeqkv = self.to_qkv(x).chunk(3, 1)q, k, v = self.map(self.partial(rearrange, self.heads), qkv)q = q * self.scale# 'b h d i, b h d j -> b h i j'sim = ops.bmm(q.swapaxes(2, 3), k)attn = ops.softmax(sim, axis=-1)# 'b h i j, b h d j -> b h i d'out = ops.bmm(attn, v.swapaxes(2, 3))out = out.swapaxes(-1, -2).reshape((b, -1, h, w))return self.to_out(out)class LayerNorm(nn.Cell):def __init__(self, dim):super().__init__()self.g = Parameter(initializer('ones', (1, dim, 1, 1)), name='g')def construct(self, x):eps = 1e-5var = x.var(1, keepdims=True)mean = x.mean(1, keep_dims=True)return (x - mean) * rsqrt((var + eps)) * self.gclass LinearAttention(nn.Cell):def __init__(self, dim, heads=4, dim_head=32):super().__init__()self.scale = dim_head ** -0.5self.heads = headshidden_dim = dim_head * headsself.to_qkv = nn.Conv2d(dim, hidden_dim * 3, 1, pad_mode='valid', has_bias=False)self.to_out = nn.SequentialCell(nn.Conv2d(hidden_dim, dim, 1, pad_mode='valid', has_bias=True),LayerNorm(dim))self.map = ops.Map()self.partial = ops.Partial()def construct(self, x):b, _, h, w = x.shapeqkv = self.to_qkv(x).chunk(3, 1)q, k, v = self.map(self.partial(rearrange, self.heads), qkv)q = ops.softmax(q, -2)k = ops.softmax(k, -1)q = q * self.scalev = v / (h * w)# 'b h d n, b h e n -> b h d e'context = ops.bmm(k, v.swapaxes(2, 3))# 'b h d e, b h d n -> b h e n'out = ops.bmm(context.swapaxes(2, 3), q)out = out.reshape((b, -1, h, w))return self.to_out(out)

組歸一化

DDPM作者將U-Net的卷積/注意層與群歸一化(Wu et al., 2018)。下面,我們定義一個PreNorm類,將用于在注意層之前應(yīng)用groupnorm。

class PreNorm(nn.Cell):def __init__(self, dim, fn):super().__init__()self.fn = fnself.norm = nn.GroupNorm(1, dim)def construct(self, x):x = self.norm(x)return self.fn(x)

條件U-Net

我們已經(jīng)定義了所有的構(gòu)建塊(位置嵌入、ResNet/ConvNeXT塊、Attention和組歸一化),現(xiàn)在需要定義整個神經(jīng)網(wǎng)絡(luò)了。請記住,網(wǎng)絡(luò)?𝜖𝜃(𝐱𝑡,𝑡)?θ(xt,t)?的工作是接收一批噪聲圖像+噪聲水平,并輸出添加到輸入中的噪聲。

更具體的: 網(wǎng)絡(luò)獲取了一批(batch_size, num_channels, height, width)形狀的噪聲圖像和一批(batch_size, 1)形狀的噪音水平作為輸入,并返回(batch_size, num_channels, height, width)形狀的張量。

網(wǎng)絡(luò)構(gòu)建過程如下:

  • 首先,將卷積層應(yīng)用于噪聲圖像批上,并計算噪聲水平的位置

  • 接下來,應(yīng)用一系列下采樣級。每個下采樣階段由2個ResNet/ConvNeXT塊 + groupnorm + attention + 殘差連接 + 一個下采樣操作組成

  • 在網(wǎng)絡(luò)的中間,再次應(yīng)用ResNet或ConvNeXT塊,并與attention交織

  • 接下來,應(yīng)用一系列上采樣級。每個上采樣級由2個ResNet/ConvNeXT塊+ groupnorm + attention + 殘差連接 + 一個上采樣操作組成

  • 最后,應(yīng)用ResNet/ConvNeXT塊,然后應(yīng)用卷積層

最終,神經(jīng)網(wǎng)絡(luò)將層堆疊起來,就像它們是樂高積木一樣(但重要的是了解它們是如何工作的)

class Unet(nn.Cell):def __init__(self,dim,init_dim=None,out_dim=None,dim_mults=(1, 2, 4, 8),channels=3,with_time_emb=True,convnext_mult=2,):super().__init__()self.channels = channelsinit_dim = default(init_dim, dim // 3 * 2)self.init_conv = nn.Conv2d(channels, init_dim, 7, padding=3, pad_mode="pad", has_bias=True)dims = [init_dim, *map(lambda m: dim * m, dim_mults)]in_out = list(zip(dims[:-1], dims[1:]))block_klass = partial(ConvNextBlock, mult=convnext_mult)if with_time_emb:time_dim = dim * 4self.time_mlp = nn.SequentialCell(SinusoidalPositionEmbeddings(dim),nn.Dense(dim, time_dim),nn.GELU(),nn.Dense(time_dim, time_dim),)else:time_dim = Noneself.time_mlp = Noneself.downs = nn.CellList([])self.ups = nn.CellList([])num_resolutions = len(in_out)for ind, (dim_in, dim_out) in enumerate(in_out):is_last = ind >= (num_resolutions - 1)self.downs.append(nn.CellList([block_klass(dim_in, dim_out, time_emb_dim=time_dim),block_klass(dim_out, dim_out, time_emb_dim=time_dim),Residual(PreNorm(dim_out, LinearAttention(dim_out))),Downsample(dim_out) if not is_last else nn.Identity(),]))mid_dim = dims[-1]self.mid_block1 = block_klass(mid_dim, mid_dim, time_emb_dim=time_dim)self.mid_attn = Residual(PreNorm(mid_dim, Attention(mid_dim)))self.mid_block2 = block_klass(mid_dim, mid_dim, time_emb_dim=time_dim)for ind, (dim_in, dim_out) in enumerate(reversed(in_out[1:])):is_last = ind >= (num_resolutions - 1)self.ups.append(nn.CellList([block_klass(dim_out * 2, dim_in, time_emb_dim=time_dim),block_klass(dim_in, dim_in, time_emb_dim=time_dim),Residual(PreNorm(dim_in, LinearAttention(dim_in))),Upsample(dim_in) if not is_last else nn.Identity(),]))out_dim = default(out_dim, channels)self.final_conv = nn.SequentialCell(block_klass(dim, dim), nn.Conv2d(dim, out_dim, 1))def construct(self, x, time):x = self.init_conv(x)t = self.time_mlp(time) if exists(self.time_mlp) else Noneh = []for block1, block2, attn, downsample in self.downs:x = block1(x, t)x = block2(x, t)x = attn(x)h.append(x)x = downsample(x)x = self.mid_block1(x, t)x = self.mid_attn(x)x = self.mid_block2(x, t)len_h = len(h) - 1for block1, block2, attn, upsample in self.ups:x = ops.concat((x, h[len_h]), 1)len_h -= 1x = block1(x, t)x = block2(x, t)x = attn(x)x = upsample(x)return self.final_conv(x)

正向擴(kuò)散

我們已經(jīng)知道正向擴(kuò)散過程在多個時間步長𝑇T中,從實際分布逐漸向圖像添加噪聲,根據(jù)差異計劃進(jìn)行正向擴(kuò)散。最初的DDPM作者采用了線性時間表:

  • 我們將正向過程方差設(shè)置為常數(shù),從𝛽1=10?4β1=10?4線性增加到𝛽𝑇=0.02βT=0.02。

  • 但是,它在(Nichol et al., 2021)中表明,當(dāng)使用余弦調(diào)度時,可以獲得更好的結(jié)果。

下面,我們定義了𝑇T時間步的時間表。

def linear_beta_schedule(timesteps):beta_start = 0.0001beta_end = 0.02return np.linspace(beta_start, beta_end, timesteps).astype(np.float32)

首先,讓我們使用T=200?時間步長的線性計劃,并定義我們需要的?βt?中的各種變量,例如方差 αˉt?的累積乘積。下面的每個變量都只是一維張量,存儲從?t?到?T?的值。重要的是,我們還定義了extract函數(shù),它將允許我們提取一批適當(dāng)?shù)?t?索引。

# 擴(kuò)散200步
timesteps = 200# 定義 beta schedule
betas = linear_beta_schedule(timesteps=timesteps)# 定義 alphas
alphas = 1. - betas
alphas_cumprod = np.cumprod(alphas, axis=0)
alphas_cumprod_prev = np.pad(alphas_cumprod[:-1], (1, 0), constant_values=1)sqrt_recip_alphas = Tensor(np.sqrt(1. / alphas))
sqrt_alphas_cumprod = Tensor(np.sqrt(alphas_cumprod))
sqrt_one_minus_alphas_cumprod = Tensor(np.sqrt(1. - alphas_cumprod))# 計算 q(x_{t-1} | x_t, x_0)
posterior_variance = betas * (1. - alphas_cumprod_prev) / (1. - alphas_cumprod)p2_loss_weight = (1 + alphas_cumprod / (1 - alphas_cumprod)) ** -0.
p2_loss_weight = Tensor(p2_loss_weight)def extract(a, t, x_shape):b = t.shape[0]out = Tensor(a).gather(t, -1)return out.reshape(b, *((1,) * (len(x_shape) - 1)))
# 下載貓貓圖像
url = 'https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/image_cat.zip'
path = download(url, './', kind="zip", replace=True)
from PIL import Imageimage = Image.open('./image_cat/jpg/000000039769.jpg')
base_width = 160
image = image.resize((base_width, int(float(image.size[1]) * float(base_width / float(image.size[0])))))
image.show()

噪聲被添加到mindspore張量中,而不是Pillow圖像。我們將首先定義圖像轉(zhuǎn)換,允許我們從PIL圖像轉(zhuǎn)換到mindspore張量(我們可以在其上添加噪聲),反之亦然。

這些轉(zhuǎn)換相當(dāng)簡單:我們首先通過除以255來標(biāo)準(zhǔn)化圖像(使它們在?[0,1]范圍內(nèi)),然后確保它們在?[?1,1]范圍內(nèi)。DPPM論文中有介紹到:

假設(shè)圖像數(shù)據(jù)由?{0,1,...,255} 中的整數(shù)組成,線性縮放為?[?1,1], 這確保了神經(jīng)網(wǎng)絡(luò)反向過程在從標(biāo)準(zhǔn)正常先驗?𝑝(𝐱𝑇)開始的一致縮放輸入上運行。

from mindspore.dataset import ImageFolderDatasetimage_size = 128
transforms = [Resize(image_size, Inter.BILINEAR),CenterCrop(image_size),ToTensor(),lambda t: (t * 2) - 1
]path = './image_cat'
dataset = ImageFolderDataset(dataset_dir=path, num_parallel_workers=cpu_count(),extensions=['.jpg', '.jpeg', '.png', '.tiff'],num_shards=1, shard_id=0, shuffle=False, decode=True)
dataset = dataset.project('image')
transforms.insert(1, RandomHorizontalFlip())
dataset_1 = dataset.map(transforms, 'image')
dataset_2 = dataset_1.batch(1, drop_remainder=True)
x_start = next(dataset_2.create_tuple_iterator())[0]
print(x_start.shape)

我們還定義了反向變換,它接收一個包含?[?1,1][?1,1]?中的張量,并將它們轉(zhuǎn)回 PIL 圖像:

import numpy as npreverse_transform = [lambda t: (t + 1) / 2,lambda t: ops.permute(t, (1, 2, 0)), # CHW to HWClambda t: t * 255.,lambda t: t.asnumpy().astype(np.uint8),ToPIL()
]def compose(transform, x):for d in transform:x = d(x)return x

讓我們驗證一下:

reverse_image = compose(reverse_transform, x_start[0])
reverse_image.show()

我們現(xiàn)在可以定義前向擴(kuò)散過程,如本文所示:

def q_sample(x_start, t, noise=None):if noise is None:noise = randn_like(x_start)return (extract(sqrt_alphas_cumprod, t, x_start.shape) * x_start +extract(sqrt_one_minus_alphas_cumprod, t, x_start.shape) * noise)

讓我們在特定的時間步長上測試它:

def get_noisy_image(x_start, t):# 添加噪音x_noisy = q_sample(x_start, t=t)# 轉(zhuǎn)換為 PIL 圖像noisy_image = compose(reverse_transform, x_noisy[0])return noisy_image# 設(shè)置 time step
t = Tensor([40])
noisy_image = get_noisy_image(x_start, t)
print(noisy_image)
noisy_image.show()

讓我們?yōu)椴煌臅r間步驟可視化此情況:

import matplotlib.pyplot as pltdef plot(imgs, with_orig=False, row_title=None, **imshow_kwargs):if not isinstance(imgs[0], list):imgs = [imgs]num_rows = len(imgs)num_cols = len(imgs[0]) + with_orig_, axs = plt.subplots(figsize=(200, 200), nrows=num_rows, ncols=num_cols, squeeze=False)for row_idx, row in enumerate(imgs):row = [image] + row if with_orig else rowfor col_idx, img in enumerate(row):ax = axs[row_idx, col_idx]ax.imshow(np.asarray(img), **imshow_kwargs)ax.set(xticklabels=[], yticklabels=[], xticks=[], yticks=[])if with_orig:axs[0, 0].set(title='Original image')axs[0, 0].title.set_size(8)if row_title is not None:for row_idx in range(num_rows):axs[row_idx, 0].set(ylabel=row_title[row_idx])plt.tight_layout()plot([get_noisy_image(x_start, Tensor([t])) for t in [0, 50, 100, 150, 199]])

這意味著我們現(xiàn)在可以定義給定模型的損失函數(shù),如下所示:

def p_losses(unet_model, x_start, t, noise=None):if noise is None:noise = randn_like(x_start)x_noisy = q_sample(x_start=x_start, t=t, noise=noise)predicted_noise = unet_model(x_noisy, t)loss = nn.SmoothL1Loss()(noise, predicted_noise)# todoloss = loss.reshape(loss.shape[0], -1)loss = loss * extract(p2_loss_weight, t, loss.shape)return loss.mean()

denoise_model將是我們上面定義的U-Net。我們將在真實噪聲和預(yù)測噪聲之間使用Huber損失。

數(shù)據(jù)準(zhǔn)備與處理

在這里我們定義一個正則數(shù)據(jù)集。數(shù)據(jù)集可以來自簡單的真實數(shù)據(jù)集的圖像組成,如Fashion-MNIST、CIFAR-10或ImageNet,其中線性縮放為?[?1,1]。

每個圖像的大小都會調(diào)整為相同的大小。有趣的是,圖像也是隨機水平翻轉(zhuǎn)的。根據(jù)論文內(nèi)容:我們在CIFAR10的訓(xùn)練中使用了隨機水平翻轉(zhuǎn);我們嘗試了有翻轉(zhuǎn)和沒有翻轉(zhuǎn)的訓(xùn)練,并發(fā)現(xiàn)翻轉(zhuǎn)可以稍微提高樣本質(zhì)量。

本實驗我們選用Fashion_MNIST數(shù)據(jù)集,我們使用download下載并解壓Fashion_MNIST數(shù)據(jù)集到指定路徑。此數(shù)據(jù)集由已經(jīng)具有相同分辨率的圖像組成,即28x28。

# 下載MNIST數(shù)據(jù)集
url = 'https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/dataset.zip'
path = download(url, './', kind="zip", replace=True)
from mindspore.dataset import FashionMnistDatasetimage_size = 28
channels = 1
batch_size = 16fashion_mnist_dataset_dir = "./dataset"
dataset = FashionMnistDataset(dataset_dir=fashion_mnist_dataset_dir, usage="train", num_parallel_workers=cpu_count(), shuffle=True, num_shards=1, shard_id=0)

接下來,我們定義一個transform操作,將在整個數(shù)據(jù)集上動態(tài)應(yīng)用該操作。該操作應(yīng)用一些基本的圖像預(yù)處理:隨機水平翻轉(zhuǎn)、重新調(diào)整,最后使它們的值在?[?1,1]范圍內(nèi)。

transforms = [RandomHorizontalFlip(),ToTensor(),lambda t: (t * 2) - 1
]dataset = dataset.project('image')
dataset = dataset.shuffle(64)
dataset = dataset.map(transforms, 'image')
dataset = dataset.batch(16, drop_remainder=True)
x = next(dataset.create_dict_iterator())
print(x.keys())

采樣

由于我們將在訓(xùn)練期間從模型中采樣(以便跟蹤進(jìn)度),我們定義了下面的代碼。采樣在本文中總結(jié)為算法2:

Image-5

從擴(kuò)散模型生成新圖像是通過反轉(zhuǎn)擴(kuò)散過程來實現(xiàn)的:我們從𝑇T開始,我們從高斯分布中采樣純噪聲,然后使用我們的神經(jīng)網(wǎng)絡(luò)逐漸去噪(使用它所學(xué)習(xí)的條件概率),直到我們最終在時間步𝑡=0結(jié)束。如上圖所示,我們可以通過使用我們的噪聲預(yù)測器插入平均值的重新參數(shù)化,導(dǎo)出一個降噪程度較低的圖像?𝐱𝑡?1xt?1。請注意,方差是提前知道的。

理想情況下,我們最終會得到一個看起來像是來自真實數(shù)據(jù)分布的圖像。

下面的代碼實現(xiàn)了這一點。

def p_sample(model, x, t, t_index):betas_t = extract(betas, t, x.shape)sqrt_one_minus_alphas_cumprod_t = extract(sqrt_one_minus_alphas_cumprod, t, x.shape)sqrt_recip_alphas_t = extract(sqrt_recip_alphas, t, x.shape)model_mean = sqrt_recip_alphas_t * (x - betas_t * model(x, t) / sqrt_one_minus_alphas_cumprod_t)if t_index == 0:return model_meanposterior_variance_t = extract(posterior_variance, t, x.shape)noise = randn_like(x)return model_mean + ops.sqrt(posterior_variance_t) * noisedef p_sample_loop(model, shape):b = shape[0]# 從純噪聲開始img = randn(shape, dtype=None)imgs = []for i in tqdm(reversed(range(0, timesteps)), desc='sampling loop time step', total=timesteps):img = p_sample(model, img, ms.numpy.full((b,), i, dtype=mstype.int32), i)imgs.append(img.asnumpy())return imgsdef sample(model, image_size, batch_size=16, channels=3):return p_sample_loop(model, shape=(batch_size, channels, image_size, image_size))

請注意,上面的代碼是原始實現(xiàn)的簡化版本。

訓(xùn)練過程

下面,我們開始訓(xùn)練吧!

# 定義動態(tài)學(xué)習(xí)率
lr = nn.cosine_decay_lr(min_lr=1e-7, max_lr=1e-4, total_step=10*3750, step_per_epoch=3750, decay_epoch=10)# 定義 Unet模型
unet_model = Unet(dim=image_size,channels=channels,dim_mults=(1, 2, 4,)
)name_list = []
for (name, par) in list(unet_model.parameters_and_names()):name_list.append(name)
i = 0
for item in list(unet_model.trainable_params()):item.name = name_list[i]i += 1# 定義優(yōu)化器
optimizer = nn.Adam(unet_model.trainable_params(), learning_rate=lr)
loss_scaler = DynamicLossScaler(65536, 2, 1000)# 定義前向過程
def forward_fn(data, t, noise=None):loss = p_losses(unet_model, data, t, noise)return loss# 計算梯度
grad_fn = ms.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=False)# 梯度更新
def train_step(data, t, noise):loss, grads = grad_fn(data, t, noise)optimizer(grads)return loss
import time# 由于時間原因,epochs設(shè)置為1,可根據(jù)需求進(jìn)行調(diào)整
epochs = 1for epoch in range(epochs):begin_time = time.time()for step, batch in enumerate(dataset.create_tuple_iterator()):unet_model.set_train()batch_size = batch[0].shape[0]t = randint(0, timesteps, (batch_size,), dtype=ms.int32)noise = randn_like(batch[0])loss = train_step(batch[0], t, noise)if step % 500 == 0:print(" epoch: ", epoch, " step: ", step, " Loss: ", loss)end_time = time.time()times = end_time - begin_timeprint("training time:", times, "s")# 展示隨機采樣效果unet_model.set_train(False)samples = sample(unet_model, image_size=image_size, batch_size=64, channels=channels)plt.imshow(samples[-1][5].reshape(image_size, image_size, channels), cmap="gray")
print("Training Success!")

推理過程(從模型中采樣)

要從模型中采樣,我們可以只使用上面定義的采樣函數(shù):

# 采樣64個圖片
unet_model.set_train(False)
samples = sample(unet_model, image_size=image_size, batch_size=64, channels=channels)# 展示一個隨機效果
random_index = 5
plt.imshow(samples[-1][random_index].reshape(image_size, image_size, channels), cmap="gray")

可以看到這個模型能產(chǎn)生一件衣服!

請注意,我們訓(xùn)練的數(shù)據(jù)集分辨率相當(dāng)?shù)?#xff08;28x28)。

我們還可以創(chuàng)建去噪過程的gif:

import matplotlib.animation as animationrandom_index = 53fig = plt.figure()
ims = []
for i in range(timesteps):im = plt.imshow(samples[i][random_index].reshape(image_size, image_size, channels), cmap="gray", animated=True)ims.append([im])animate = animation.ArtistAnimation(fig, ims, interval=50, blit=True, repeat_delay=100)
animate.save('diffusion.gif')
plt.show()

總結(jié)

請注意,DDPM論文表明擴(kuò)散模型是(非)條件圖像有希望生成的方向。自那以后,diffusion得到了(極大的)改進(jìn),最明顯的是文本條件圖像生成。下面,我們列出了一些重要的(但遠(yuǎn)非詳盡無遺的)后續(xù)工作:

  • 改進(jìn)的去噪擴(kuò)散概率模型(Nichol et al., 2021):發(fā)現(xiàn)學(xué)習(xí)條件分布的方差(除平均值外)有助于提高性能

  • 用于高保真圖像生成的級聯(lián)擴(kuò)散模型([Ho et al., 2021):引入級聯(lián)擴(kuò)散,它包括多個擴(kuò)散模型的流水線,這些模型生成分辨率提高的圖像,用于高保真圖像合成

  • 擴(kuò)散模型在圖像合成上擊敗了GANs(Dhariwal et al., 2021):表明擴(kuò)散模型通過改進(jìn)U-Net體系結(jié)構(gòu)以及引入分類器指導(dǎo),可以獲得優(yōu)于當(dāng)前最先進(jìn)的生成模型的圖像樣本質(zhì)量

  • 無分類器擴(kuò)散指南([Ho et al., 2021):表明通過使用單個神經(jīng)網(wǎng)絡(luò)聯(lián)合訓(xùn)練條件和無條件擴(kuò)散模型,不需要分類器來指導(dǎo)擴(kuò)散模型

  • 具有CLIP Latents (DALL-E 2) 的分層文本條件圖像生成 (Ramesh et al., 2022):在將文本標(biāo)題轉(zhuǎn)換為CLIP圖像嵌入之前使用,然后擴(kuò)散模型將其解碼為圖像

  • 具有深度語言理解的真實文本到圖像擴(kuò)散模型(ImageGen)(Saharia et al., 2022):表明將大型預(yù)訓(xùn)練語言模型(例如T5)與級聯(lián)擴(kuò)散結(jié)合起來,對于文本到圖像的合成很有效

請注意,此列表僅包括在撰寫本文,即2022年6月7日之前的重要作品。

目前,擴(kuò)散模型的主要(也許唯一)缺點是它們需要多次正向傳遞來生成圖像(對于像GAN這樣的生成模型來說,情況并非如此)。然而,有正在進(jìn)行中的研究表明只需要10個去噪步驟就能實現(xiàn)高保真生成。

最后打卡今天的學(xué)習(xí)時間

心得

通過今天的學(xué)習(xí)我對Diffusion擴(kuò)散模型有了更深入的了解。擴(kuò)散模型在機器學(xué)習(xí)領(lǐng)域中扮演著重要角色,尤其在圖像生成和風(fēng)格遷移中展現(xiàn)出其獨特的魅力。通過學(xué)習(xí),我認(rèn)識到了擴(kuò)散過程的基本原理,以及如何利用這一過程來生成高質(zhì)量的圖像。這種模型的創(chuàng)新之處在于它能夠模擬數(shù)據(jù)的生成過程,從而在保持多樣性的同時,生成更加逼真的結(jié)果。我期待將這些知識應(yīng)用到實際項目中,以解決更復(fù)雜的問題

DCGAN生成漫畫頭像

GAN基礎(chǔ)原理

這部分原理介紹參考GAN圖像生成。

DCGAN原理

DCGAN(深度卷積對抗生成網(wǎng)絡(luò),Deep Convolutional Generative Adversarial Networks)是GAN的直接擴(kuò)展。不同之處在于,DCGAN會分別在判別器和生成器中使用卷積和轉(zhuǎn)置卷積層。

它最早由Radford等人在論文Unsupervised Representation Learning With Deep Convolutional Generative Adversarial Networks中進(jìn)行描述。判別器由分層的卷積層、BatchNorm層和LeakyReLU激活層組成。輸入是3x64x64的圖像,輸出是該圖像為真圖像的概率。生成器則是由轉(zhuǎn)置卷積層、BatchNorm層和ReLU激活層組成。輸入是標(biāo)準(zhǔn)正態(tài)分布中提取出的隱向量𝑧z,輸出是3x64x64的RGB圖像。

本教程將使用動漫頭像數(shù)據(jù)集來訓(xùn)練一個生成式對抗網(wǎng)絡(luò),接著使用該網(wǎng)絡(luò)生成動漫頭像圖片。

數(shù)據(jù)準(zhǔn)備與處理

首先我們將數(shù)據(jù)集下載到指定目錄下并解壓。示例代碼如下:

%%capture captured_output
# 實驗環(huán)境已經(jīng)預(yù)裝了mindspore==2.2.14,如需更換mindspore版本,可更改下面mindspore的版本號
!pip uninstall mindspore -y
!pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14from download import downloadurl = "https://download.mindspore.cn/dataset/Faces/faces.zip"path = download(url, "./faces", kind="zip", replace=True)

數(shù)據(jù)處理

首先為執(zhí)行過程定義一些輸入:

batch_size = 128          # 批量大小
image_size = 64           # 訓(xùn)練圖像空間大小
nc = 3                    # 圖像彩色通道數(shù)
nz = 100                  # 隱向量的長度
ngf = 64                  # 特征圖在生成器中的大小
ndf = 64                  # 特征圖在判別器中的大小
num_epochs = 3           # 訓(xùn)練周期數(shù)
lr = 0.0002               # 學(xué)習(xí)率
beta1 = 0.5               # Adam優(yōu)化器的beta1超參數(shù)

定義create_dataset_imagenet函數(shù)對數(shù)據(jù)進(jìn)行處理和增強操作。

import numpy as np
import mindspore.dataset as ds
import mindspore.dataset.vision as visiondef create_dataset_imagenet(dataset_path):"""數(shù)據(jù)加載"""dataset = ds.ImageFolderDataset(dataset_path,num_parallel_workers=4,shuffle=True,decode=True)# 數(shù)據(jù)增強操作transforms = [vision.Resize(image_size),vision.CenterCrop(image_size),vision.HWC2CHW(),lambda x: ((x / 255).astype("float32"))]# 數(shù)據(jù)映射操作dataset = dataset.project('image')dataset = dataset.map(transforms, 'image')# 批量操作dataset = dataset.batch(batch_size)return datasetdataset = create_dataset_imagenet('./faces')

通過create_dict_iterator函數(shù)將數(shù)據(jù)轉(zhuǎn)換成字典迭代器,然后使用matplotlib模塊可視化部分訓(xùn)練數(shù)據(jù)。????????

import matplotlib.pyplot as pltdef plot_data(data):# 可視化部分訓(xùn)練數(shù)據(jù)plt.figure(figsize=(10, 3), dpi=140)for i, image in enumerate(data[0][:30], 1):plt.subplot(3, 10, i)plt.axis("off")plt.imshow(image.transpose(1, 2, 0))plt.show()sample_data = next(dataset.create_tuple_iterator(output_numpy=True))
plot_data(sample_data)

構(gòu)造網(wǎng)絡(luò)

當(dāng)處理完數(shù)據(jù)后,就可以來進(jìn)行網(wǎng)絡(luò)的搭建了。按照DCGAN論文中的描述,所有模型權(quán)重均應(yīng)從mean為0,sigma為0.02的正態(tài)分布中隨機初始化。

生成器

生成器G的功能是將隱向量z映射到數(shù)據(jù)空間。由于數(shù)據(jù)是圖像,這一過程也會創(chuàng)建與真實圖像大小相同的 RGB 圖像。在實踐場景中,該功能是通過一系列Conv2dTranspose轉(zhuǎn)置卷積層來完成的,每個層都與BatchNorm2d層和ReLu激活層配對,輸出數(shù)據(jù)會經(jīng)過tanh函數(shù),使其返回[-1,1]的數(shù)據(jù)范圍內(nèi)。

DCGAN論文生成圖像如下所示:

dcgangenerator

圖片來源:Unsupervised Representation Learning With Deep Convolutional Generative Adversarial Networks.

我們通過輸入部分中設(shè)置的nzngfnc來影響代碼中的生成器結(jié)構(gòu)。nz是隱向量z的長度,ngf與通過生成器傳播的特征圖的大小有關(guān),nc是輸出圖像中的通道數(shù)。

以下是生成器的代碼實現(xiàn):

import mindspore as ms
from mindspore import nn, ops
from mindspore.common.initializer import Normalweight_init = Normal(mean=0, sigma=0.02)
gamma_init = Normal(mean=1, sigma=0.02)class Generator(nn.Cell):"""DCGAN網(wǎng)絡(luò)生成器"""def __init__(self):super(Generator, self).__init__()self.generator = nn.SequentialCell(nn.Conv2dTranspose(nz, ngf * 8, 4, 1, 'valid', weight_init=weight_init),nn.BatchNorm2d(ngf * 8, gamma_init=gamma_init),nn.ReLU(),nn.Conv2dTranspose(ngf * 8, ngf * 4, 4, 2, 'pad', 1, weight_init=weight_init),nn.BatchNorm2d(ngf * 4, gamma_init=gamma_init),nn.ReLU(),nn.Conv2dTranspose(ngf * 4, ngf * 2, 4, 2, 'pad', 1, weight_init=weight_init),nn.BatchNorm2d(ngf * 2, gamma_init=gamma_init),nn.ReLU(),nn.Conv2dTranspose(ngf * 2, ngf, 4, 2, 'pad', 1, weight_init=weight_init),nn.BatchNorm2d(ngf, gamma_init=gamma_init),nn.ReLU(),nn.Conv2dTranspose(ngf, nc, 4, 2, 'pad', 1, weight_init=weight_init),nn.Tanh())def construct(self, x):return self.generator(x)generator = Generator()

判別器?

如前所述,判別器D是一個二分類網(wǎng)絡(luò)模型,輸出判定該圖像為真實圖的概率。通過一系列的Conv2d、BatchNorm2dLeakyReLU層對其進(jìn)行處理,最后通過Sigmoid激活函數(shù)得到最終概率。

DCGAN論文提到,使用卷積而不是通過池化來進(jìn)行下采樣是一個好方法,因為它可以讓網(wǎng)絡(luò)學(xué)習(xí)自己的池化特征。

判別器的代碼實現(xiàn)如下:

class Discriminator(nn.Cell):"""DCGAN網(wǎng)絡(luò)判別器"""def __init__(self):super(Discriminator, self).__init__()self.discriminator = nn.SequentialCell(nn.Conv2d(nc, ndf, 4, 2, 'pad', 1, weight_init=weight_init),nn.LeakyReLU(0.2),nn.Conv2d(ndf, ndf * 2, 4, 2, 'pad', 1, weight_init=weight_init),nn.BatchNorm2d(ngf * 2, gamma_init=gamma_init),nn.LeakyReLU(0.2),nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 'pad', 1, weight_init=weight_init),nn.BatchNorm2d(ngf * 4, gamma_init=gamma_init),nn.LeakyReLU(0.2),nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 'pad', 1, weight_init=weight_init),nn.BatchNorm2d(ngf * 8, gamma_init=gamma_init),nn.LeakyReLU(0.2),nn.Conv2d(ndf * 8, 1, 4, 1, 'valid', weight_init=weight_init),)self.adv_layer = nn.Sigmoid()def construct(self, x):out = self.discriminator(x)out = out.reshape(out.shape[0], -1)return self.adv_layer(out)discriminator = Discriminator()

模型訓(xùn)練

損失函數(shù)

當(dāng)定義了DG后,接下來將使用MindSpore中定義的二進(jìn)制交叉熵?fù)p失函數(shù)BCELoss。

# 定義損失函數(shù)
adversarial_loss = nn.BCELoss(reduction='mean')

優(yōu)化器

這里設(shè)置了兩個單獨的優(yōu)化器,一個用于D,另一個用于G。這兩個都是lr = 0.0002beta1 = 0.5的Adam優(yōu)化器。

# 為生成器和判別器設(shè)置優(yōu)化器
optimizer_D = nn.Adam(discriminator.trainable_params(), learning_rate=lr, beta1=beta1)
optimizer_G = nn.Adam(generator.trainable_params(), learning_rate=lr, beta1=beta1)
optimizer_G.update_parameters_name('optim_g.')
optimizer_D.update_parameters_name('optim_d.')

訓(xùn)練模型

訓(xùn)練分為兩個主要部分:訓(xùn)練判別器和訓(xùn)練生成器。

  • 訓(xùn)練判別器

    訓(xùn)練判別器的目的是最大程度地提高判別圖像真?zhèn)蔚母怕省0凑誈oodfellow的方法,是希望通過提高其隨機梯度來更新判別器,所以我們要最大化𝑙𝑜𝑔𝐷(𝑥)+𝑙𝑜𝑔(1?𝐷(𝐺(𝑧))logD(x)+log(1?D(G(z))的值。

  • 訓(xùn)練生成器

    如DCGAN論文所述,我們希望通過最小化𝑙𝑜𝑔(1?𝐷(𝐺(𝑧)))log(1?D(G(z)))來訓(xùn)練生成器,以產(chǎn)生更好的虛假圖像。

在這兩個部分中,分別獲取訓(xùn)練過程中的損失,并在每個周期結(jié)束時進(jìn)行統(tǒng)計,將fixed_noise批量推送到生成器中,以直觀地跟蹤G的訓(xùn)練進(jìn)度。

下面實現(xiàn)模型訓(xùn)練正向邏輯:

def generator_forward(real_imgs, valid):# 將噪聲采樣為發(fā)生器的輸入z = ops.standard_normal((real_imgs.shape[0], nz, 1, 1))# 生成一批圖像gen_imgs = generator(z)# 損失衡量發(fā)生器繞過判別器的能力g_loss = adversarial_loss(discriminator(gen_imgs), valid)return g_loss, gen_imgsdef discriminator_forward(real_imgs, gen_imgs, valid, fake):# 衡量鑒別器從生成的樣本中對真實樣本進(jìn)行分類的能力real_loss = adversarial_loss(discriminator(real_imgs), valid)fake_loss = adversarial_loss(discriminator(gen_imgs), fake)d_loss = (real_loss + fake_loss) / 2return d_lossgrad_generator_fn = ms.value_and_grad(generator_forward, None,optimizer_G.parameters,has_aux=True)
grad_discriminator_fn = ms.value_and_grad(discriminator_forward, None,optimizer_D.parameters)@ms.jit
def train_step(imgs):valid = ops.ones((imgs.shape[0], 1), mindspore.float32)fake = ops.zeros((imgs.shape[0], 1), mindspore.float32)(g_loss, gen_imgs), g_grads = grad_generator_fn(imgs, valid)optimizer_G(g_grads)d_loss, d_grads = grad_discriminator_fn(imgs, gen_imgs, valid, fake)optimizer_D(d_grads)return g_loss, d_loss, gen_imgs

循環(huán)訓(xùn)練網(wǎng)絡(luò),每經(jīng)過50次迭代,就收集生成器和判別器的損失,以便于后面繪制訓(xùn)練過程中損失函數(shù)的圖像。

import mindsporeG_losses = []
D_losses = []
image_list = []total = dataset.get_dataset_size()
for epoch in range(num_epochs):generator.set_train()discriminator.set_train()# 為每輪訓(xùn)練讀入數(shù)據(jù)for i, (imgs, ) in enumerate(dataset.create_tuple_iterator()):g_loss, d_loss, gen_imgs = train_step(imgs)if i % 100 == 0 or i == total - 1:# 輸出訓(xùn)練記錄print('[%2d/%d][%3d/%d]   Loss_D:%7.4f  Loss_G:%7.4f' % (epoch + 1, num_epochs, i + 1, total, d_loss.asnumpy(), g_loss.asnumpy()))D_losses.append(d_loss.asnumpy())G_losses.append(g_loss.asnumpy())# 每個epoch結(jié)束后,使用生成器生成一組圖片generator.set_train(False)fixed_noise = ops.standard_normal((batch_size, nz, 1, 1))img = generator(fixed_noise)image_list.append(img.transpose(0, 2, 3, 1).asnumpy())# 保存網(wǎng)絡(luò)模型參數(shù)為ckpt文件mindspore.save_checkpoint(generator, "./generator.ckpt")mindspore.save_checkpoint(discriminator, "./discriminator.ckpt")

結(jié)果展示

運行下面代碼,描繪DG損失與訓(xùn)練迭代的關(guān)系圖:

plt.figure(figsize=(10, 5))
plt.title("Generator and Discriminator Loss During Training")
plt.plot(G_losses, label="G", color='blue')
plt.plot(D_losses, label="D", color='orange')
plt.xlabel("iterations")
plt.ylabel("Loss")
plt.legend()
plt.show()

可視化訓(xùn)練過程中通過隱向量fixed_noise生成的圖像。

import matplotlib.pyplot as plt
import matplotlib.animation as animationdef showGif(image_list):show_list = []fig = plt.figure(figsize=(8, 3), dpi=120)for epoch in range(len(image_list)):images = []for i in range(3):row = np.concatenate((image_list[epoch][i * 8:(i + 1) * 8]), axis=1)images.append(row)img = np.clip(np.concatenate((images[:]), axis=0), 0, 1)plt.axis("off")show_list.append([plt.imshow(img)])ani = animation.ArtistAnimation(fig, show_list, interval=1000, repeat_delay=1000, blit=True)ani.save('./dcgan.gif', writer='pillow', fps=1)showGif(image_list)

從上面的圖像可以看出,隨著訓(xùn)練次數(shù)的增多,圖像質(zhì)量也越來越好。如果增大訓(xùn)練周期數(shù),當(dāng)num_epochs達(dá)到50以上時,生成的動漫頭像圖片與數(shù)據(jù)集中的較為相似,下面我們通過加載生成器網(wǎng)絡(luò)模型參數(shù)文件來生成圖像,代碼如下:

# 從文件中獲取模型參數(shù)并加載到網(wǎng)絡(luò)中
mindspore.load_checkpoint("./generator.ckpt", generator)fixed_noise = ops.standard_normal((batch_size, nz, 1, 1))
img64 = generator(fixed_noise).transpose(0, 2, 3, 1).asnumpy()fig = plt.figure(figsize=(8, 3), dpi=120)
images = []
for i in range(3):images.append(np.concatenate((img64[i * 8:(i + 1) * 8]), axis=1))
img = np.clip(np.concatenate((images[:]), axis=0), 0, 1)
plt.axis("off")
plt.imshow(img)
plt.show()

?最后打卡今天的學(xué)習(xí)時間

心得

我深入探索了DCGAN生成漫畫頭像的技術(shù)。DCGAN作為GAN的一種變體,通過巧妙地引入卷積和轉(zhuǎn)置卷積層,極大地提升了圖像生成的質(zhì)量和效率。學(xué)習(xí)DCGAN原理,我了解到判別器和生成器的構(gòu)建方式,以及它們?nèi)绾瓮ㄟ^對抗過程學(xué)習(xí)生成逼真的圖像。特別是BatchNorm層和ReLU激活層的運用,為生成圖像的多樣性和穩(wěn)定性提供了保障

http://aloenet.com.cn/news/43375.html

相關(guān)文章:

  • 騰訊云服務(wù)器用什么做網(wǎng)站企業(yè)培訓(xùn)課程視頻
  • 個人養(yǎng)老金查詢山東seo多少錢
  • 廣州網(wǎng)站制作公司優(yōu)化獨立站平臺選哪個好
  • 今天西安新消息抖音seo運營模式
  • wordpress模板建站教程視頻微信騰訊會議
  • 網(wǎng)站建設(shè)中404什么意思宣傳產(chǎn)品的方式
  • b站必看的紀(jì)錄片廣告平臺
  • 動態(tài)商務(wù)網(wǎng)站開發(fā)與管理電商培訓(xùn)視頻教程
  • 教做年糕博客網(wǎng)站同城推廣
  • wordpress 極簡主題紹興網(wǎng)站快速排名優(yōu)化
  • 公司網(wǎng)站備案需要什么資料友情鏈接交換的作用在于
  • 蕪湖市建設(shè)辦網(wǎng)站谷歌關(guān)鍵詞搜索量數(shù)據(jù)查詢
  • 外貿(mào)網(wǎng)站建設(shè) 東莞seo的工作原理
  • 成都企業(yè)建站系統(tǒng)模板seo標(biāo)題優(yōu)化
  • 滄州大型網(wǎng)站建設(shè)開發(fā)網(wǎng)站多少錢
  • 如何用網(wǎng)站賺錢湖南省人民政府官網(wǎng)
  • 為解析的域名做網(wǎng)站企業(yè)宣傳推廣方案
  • dreamweaver網(wǎng)站建設(shè)教程新網(wǎng)站怎么推廣
  • 簡歷網(wǎng)站有哪些廈門人才網(wǎng)官網(wǎng)招聘
  • 南昌做任務(wù)的網(wǎng)站網(wǎng)站可以自己做嗎
  • 酒店網(wǎng)站建設(shè)注意什么四川seo選哪家
  • 網(wǎng)站模板 psd免費注冊個人網(wǎng)站不花錢
  • 一家專業(yè)做家譜的網(wǎng)站seo網(wǎng)站內(nèi)容優(yōu)化
  • 做網(wǎng)站收入來源表寧波營銷型網(wǎng)站建設(shè)優(yōu)化建站
  • 專注七星彩網(wǎng)站開發(fā)品牌運營公司
  • 制作網(wǎng)頁的軟件都有哪些內(nèi)蒙古seo
  • 展示型網(wǎng)站系統(tǒng)營銷最好的方法
  • 商城網(wǎng)站離不開支付系統(tǒng)推廣普通話宣傳內(nèi)容
  • 三站合一的網(wǎng)站怎么做網(wǎng)址大全百度
  • 重慶榮昌網(wǎng)站建設(shè)費用疫情優(yōu)化調(diào)整