0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

PyTorch教程-14.12. 神经风格迁移

jf_pJlTbmA9 来源:PyTorch 作者:PyTorch 2023-06-05 15:44 次阅读

如果你是摄影爱好者,你可能对滤镜并不陌生。它可以改变照片的色彩风格,使风景照片变得更清晰或肖像照片皮肤变白。但是,一个滤镜通常只会改变照片的一个方面。要为照片应用理想的风格,您可能需要尝试多种不同的滤镜组合。这个过程与调整模型的超参数一样复杂。

在本节中,我们将利用 CNN 的分层表示将一幅图像的风格自动应用到另一幅图像,即 风格迁移 (Gatys等人,2016 年)。此任务需要两张输入图像:一张是内容图像,另一张是风格图像。我们将使用神经网络修改内容图像,使其在风格上接近风格图像。例如 图14.12.1中的内容图片是我们在西雅图郊区雷尼尔山国家公园拍摄的风景照,而风格图是一幅以秋天的橡树为主题的油画。在输出的合成图像中,应用了样式图像的油画笔触,使颜色更加鲜艳,同时保留了内容图像中对象的主要形状。

poYBAGR9PAyAD4TXACzLlevRbk4394.svg

图 14.12.1给定内容和风格图像,风格迁移输出合成图像。

14.12.1。方法

图 14.12.2用一个简化的例子说明了基于 CNN 的风格迁移方法。首先,我们将合成图像初始化为内容图像。这张合成图像是风格迁移过程中唯一需要更新的变量,即训练期间要更新的模型参数。然后我们选择一个预训练的 CNN 来提取图像特征并在训练期间冻结其模型参数。这种深度 CNN 使用多层来提取图像的层次特征。我们可以选择其中一些层的输出作为内容特征或样式特征。如图14.12.2举个例子。这里的预训练神经网络有 3 个卷积层,其中第二层输出内容特征,第一层和第三层输出风格特征。

pYYBAGR9PBGAHsKTAAxCCRcH-98436.svg

图 14.12.2基于 CNN 的风格迁移过程。实线表示正向传播方向,虚线表示反向传播。

接下来,我们通过正向传播(实线箭头方向)计算风格迁移的损失函数,并通过反向传播(虚线箭头方向)更新模型参数(输出的合成图像)。风格迁移中常用的损失函数由三部分组成:(i)内容损失使合成图像和内容图像在内容特征上接近;(ii)风格损失使得合成图像和风格图像在风格特征上接近;(iii) 总变差损失有助于减少合成图像中的噪声。最后,当模型训练结束后,我们输出风格迁移的模型参数,生成最终的合成图像。

下面,我们将通过一个具体的实验来解释风格迁移的技术细节。

14.12.2。阅读内容和样式图像

首先,我们阅读内容和样式图像。从它们打印的坐标轴,我们可以看出这些图像具有不同的尺寸。

%matplotlib inline
import torch
import torchvision
from torch import nn
from d2l import torch as d2l

d2l.set_figsize()
content_img = d2l.Image.open('../img/rainier.jpg')
d2l.plt.imshow(content_img);

poYBAGR9PBSAQji4AAJilAS7Cj4664.svg

style_img = d2l.Image.open('../img/autumn-oak.jpg')
d2l.plt.imshow(style_img);

pYYBAGR9PBmAZ-kLAAMLjwnT-xs129.svg

%matplotlib inline
from mxnet import autograd, gluon, image, init, np, npx
from mxnet.gluon import nn
from d2l import mxnet as d2l

npx.set_np()

d2l.set_figsize()
content_img = image.imread('../img/rainier.jpg')
d2l.plt.imshow(content_img.asnumpy());

poYBAGR9PBSAQji4AAJilAS7Cj4664.svg

style_img = image.imread('../img/autumn-oak.jpg')
d2l.plt.imshow(style_img.asnumpy());

pYYBAGR9PBmAZ-kLAAMLjwnT-xs129.svg

14.12.3。预处理和后处理

下面,我们定义了两个用于预处理和后处理图像的函数。该preprocess函数对输入图像的三个 RGB 通道中的每一个进行标准化,并将结果转换为 CNN 输入格式。该postprocess函数将输出图像中的像素值恢复为标准化前的原始值。由于图像打印功能要求每个像素都有一个从0到1的浮点值,我们将任何小于0或大于1的值分别替换为0或1。

rgb_mean = torch.tensor([0.485, 0.456, 0.406])
rgb_std = torch.tensor([0.229, 0.224, 0.225])

def preprocess(img, image_shape):
  transforms = torchvision.transforms.Compose([
    torchvision.transforms.Resize(image_shape),
    torchvision.transforms.ToTensor(),
    torchvision.transforms.Normalize(mean=rgb_mean, std=rgb_std)])
  return transforms(img).unsqueeze(0)

def postprocess(img):
  img = img[0].to(rgb_std.device)
  img = torch.clamp(img.permute(1, 2, 0) * rgb_std + rgb_mean, 0, 1)
  return torchvision.transforms.ToPILImage()(img.permute(2, 0, 1))

rgb_mean = np.array([0.485, 0.456, 0.406])
rgb_std = np.array([0.229, 0.224, 0.225])

def preprocess(img, image_shape):
  img = image.imresize(img, *image_shape)
  img = (img.astype('float32') / 255 - rgb_mean) / rgb_std
  return np.expand_dims(img.transpose(2, 0, 1), axis=0)

def postprocess(img):
  img = img[0].as_in_ctx(rgb_std.ctx)
  return (img.transpose(1, 2, 0) * rgb_std + rgb_mean).clip(0, 1)

14.12.4。提取特征

我们使用在 ImageNet 数据集上预训练的 VGG-19 模型来提取图像特征( Gatys et al. , 2016 )。

pretrained_net = torchvision.models.vgg19(pretrained=True)

pretrained_net = gluon.model_zoo.vision.vgg19(pretrained=True)

为了提取图像的内容特征和风格特征,我们可以选择VGG网络中某些层的输出。一般来说,越靠近输入层越容易提取图像的细节,反之越容易提取图像的全局信息。为了避免在合成图像中过度保留内容图像的细节,我们选择了一个更接近输出的VGG层作为内容层来输出图像的内容特征。我们还选择不同 VGG 层的输出来提取局部和全局风格特征。这些图层也称为样式图层。如第 8.2 节所述,VGG 网络使用 5 个卷积块。在实验中,我们选择第四个卷积块的最后一个卷积层作为内容层,每个卷积块的第一个卷积层作为样式层。这些层的索引可以通过打印pretrained_net实例来获得。

style_layers, content_layers = [0, 5, 10, 19, 28], [25]

style_layers, content_layers = [0, 5, 10, 19, 28], [25]

当使用 VGG 层提取特征时,我们只需要使用从输入层到最接近输出层的内容层或样式层的所有那些。让我们构建一个新的网络实例net,它只保留所有用于特征提取的 VGG 层。

net = nn.Sequential(*[pretrained_net.features[i] for i in
           range(max(content_layers + style_layers) + 1)])

net = nn.Sequential()
for i in range(max(content_layers + style_layers) + 1):
  net.add(pretrained_net.features[i])

给定输入X,如果我们简单地调用前向传播 net(X),我们只能得到最后一层的输出。由于我们还需要中间层的输出,因此我们需要逐层计算并保留内容层和样式层的输出。

def extract_features(X, content_layers, style_layers):
  contents = []
  styles = []
  for i in range(len(net)):
    X = net[i](X)
    if i in style_layers:
      styles.append(X)
    if i in content_layers:
      contents.append(X)
  return contents, styles

def extract_features(X, content_layers, style_layers):
  contents = []
  styles = []
  for i in range(len(net)):
    X = net[i](X)
    if i in style_layers:
      styles.append(X)
    if i in content_layers:
      contents.append(X)
  return contents, styles

下面定义了两个函数:get_contents函数从内容图像中提取内容特征,函数get_styles从风格图像中提取风格特征。由于在训练期间不需要更新预训练 VGG 的模型参数,我们甚至可以在训练开始之前提取内容和风格特征。由于合成图像是一组需要更新的模型参数以进行风格迁移,因此我们只能extract_features 在训练时通过调用函数来提取合成图像的内容和风格特征。

def get_contents(image_shape, device):
  content_X = preprocess(content_img, image_shape).to(device)
  contents_Y, _ = extract_features(content_X, content_layers, style_layers)
  return content_X, contents_Y

def get_styles(image_shape, device):
  style_X = preprocess(style_img, image_shape).to(device)
  _, styles_Y = extract_features(style_X, content_layers, style_layers)
  return style_X, styles_Y

def get_contents(image_shape, device):
  content_X = preprocess(content_img, image_shape).copyto(device)
  contents_Y, _ = extract_features(content_X, content_layers, style_layers)
  return content_X, contents_Y

def get_styles(image_shape, device):
  style_X = preprocess(style_img, image_shape).copyto(device)
  _, styles_Y = extract_features(style_X, content_layers, style_layers)
  return style_X, styles_Y

14.12.5。定义损失函数

现在我们将描述风格迁移的损失函数。损失函数包括内容损失、风格损失和全变损失。

14.12.5.1。内容丢失

类似于线性回归中的损失函数,内容损失通过平方损失函数衡量合成图像和内容图像之间内容特征的差异。平方损失函数的两个输入都是该extract_features函数计算的内容层的输出。

def content_loss(Y_hat, Y):
  # We detach the target content from the tree used to dynamically compute
  # the gradient: this is a stated value, not a variable. Otherwise the loss
  # will throw an error.
  return torch.square(Y_hat - Y.detach()).mean()

def content_loss(Y_hat, Y):
  return np.square(Y_hat - Y).mean()

14.12.5.2。风格损失

风格损失与内容损失类似,也是使用平方损失函数来衡量合成图像与风格图像之间的风格差异。为了表达任何样式层的样式输出,我们首先使用函数extract_features来计算样式层输出。假设输出有 1 个示例,c渠道,高度 h, 和宽度w,我们可以将此输出转换为矩阵 X和c行和hw列。这个矩阵可以被认为是串联c载体 x1,…,xc, 其中每一个的长度为hw. 在这里,矢量xi表示频道的风格特征i.

在这些向量的 Gram 矩阵中XX⊤∈Rc×c, 元素 xij在排队i和专栏j是向量的点积xi和xj. 表示渠道风格特征的相关性i和 j. 我们使用这个 Gram 矩阵来表示任何样式层的样式输出。请注意,当值hw越大,它可能会导致 Gram 矩阵中的值越大。还要注意,Gram矩阵的高和宽都是通道数c. 为了让风格损失不受这些值的影响,gram 下面的函数将 Gram 矩阵除以其元素的数量,即chw.

def gram(X):
  num_channels, n = X.shape[1], X.numel() // X.shape[1]
  X = X.reshape((num_channels, n))
  return torch.matmul(X, X.T) / (num_channels * n)

def gram(X):
  num_channels, n = X.shape[1], d2l.size(X) // X.shape[1]
  X = X.reshape((num_channels, n))
  return np.dot(X, X.T) / (num_channels * n)

显然,风格损失的平方损失函数的两个格拉姆矩阵输入是基于合成图像和风格图像的风格层输出。这里假设 gram_Y基于风格图像的 Gram 矩阵已经预先计算好了。

def style_loss(Y_hat, gram_Y):
  return torch.square(gram(Y_hat) - gram_Y.detach()).mean()

def style_loss(Y_hat, gram_Y):
  return np.square(gram(Y_hat) - gram_Y).mean()

14.12.5.3。总变异损失

有时,学习到的合成图像有很多高频噪声,即特别亮或特别暗的像素。一种常见的降噪方法是全变差去噪。表示为 xi,j坐标处的像素值(i,j). 减少总变异损失

(14.12.1)∑i,j|xi,j−xi+1,j|+|xi,j−xi,j+1|

使合成图像上相邻像素的值更接近。

def tv_loss(Y_hat):
  return 0.5 * (torch.abs(Y_hat[:, :, 1:, :] - Y_hat[:, :, :-1, :]).mean() +
         torch.abs(Y_hat[:, :, :, 1:] - Y_hat[:, :, :, :-1]).mean())

def tv_loss(Y_hat):
  return 0.5 * (np.abs(Y_hat[:, :, 1:, :] - Y_hat[:, :, :-1, :]).mean() +
         np.abs(Y_hat[:, :, :, 1:] - Y_hat[:, :, :, :-1]).mean())

14.12.5.4。损失函数

风格迁移的损失函数是内容损失、风格损失和总变异损失的加权和。通过调整这些权重超参数,我们可以在合成图像的内容保留、风格迁移和降噪之间取得平衡。

content_weight, style_weight, tv_weight = 1, 1e4, 10

def compute_loss(X, contents_Y_hat, styles_Y_hat, contents_Y, styles_Y_gram):
  # Calculate the content, style, and total variance losses respectively
  contents_l = [content_loss(Y_hat, Y) * content_weight for Y_hat, Y in zip(
    contents_Y_hat, contents_Y)]
  styles_l = [style_loss(Y_hat, Y) * style_weight for Y_hat, Y in zip(
    styles_Y_hat, styles_Y_gram)]
  tv_l = tv_loss(X) * tv_weight
  # Add up all the losses
  l = sum(styles_l + contents_l + [tv_l])
  return contents_l, styles_l, tv_l, l

content_weight, style_weight, tv_weight = 1, 1e4, 10

def compute_loss(X, contents_Y_hat, styles_Y_hat, contents_Y, styles_Y_gram):
  # Calculate the content, style, and total variance losses respectively
  contents_l = [content_loss(Y_hat, Y) * content_weight for Y_hat, Y in zip(
    contents_Y_hat, contents_Y)]
  styles_l = [style_loss(Y_hat, Y) * style_weight for Y_hat, Y in zip(
    styles_Y_hat, styles_Y_gram)]
  tv_l = tv_loss(X) * tv_weight
  # Add up all the losses
  l = sum(styles_l + contents_l + [tv_l])
  return contents_l, styles_l, tv_l, l

14.12.6. 初始化合成图像

在风格迁移中,合成图像是训练期间唯一需要更新的变量。因此,我们可以定义一个简单的模型, SynthesizedImage并将合成图像作为模型参数。在这个模型中,前向传播只返回模型参数。

class SynthesizedImage(nn.Module):
  def __init__(self, img_shape, **kwargs):
    super(SynthesizedImage, self).__init__(**kwargs)
    self.weight = nn.Parameter(torch.rand(*img_shape))

  def forward(self):
    return self.weight

class SynthesizedImage(nn.Block):
  def __init__(self, img_shape, **kwargs):
    super(SynthesizedImage, self).__init__(**kwargs)
    self.weight = self.params.get('weight', shape=img_shape)

  def forward(self):
    return self.weight.data()

接下来,我们定义get_inits函数。此函数创建一个合成图像模型实例并将其初始化为 image X。styles_Y_gram在训练之前计算各种样式层的样式图像的 Gram 矩阵 。

def get_inits(X, device, lr, styles_Y):
  gen_img = SynthesizedImage(X.shape).to(device)
  gen_img.weight.data.copy_(X.data)
  trainer = torch.optim.Adam(gen_img.parameters(), lr=lr)
  styles_Y_gram = [gram(Y) for Y in styles_Y]
  return gen_img(), styles_Y_gram, trainer

def get_inits(X, device, lr, styles_Y):
  gen_img = SynthesizedImage(X.shape)
  gen_img.initialize(init.Constant(X), ctx=device, force_reinit=True)
  trainer = gluon.Trainer(gen_img.collect_params(), 'adam',
              {'learning_rate': lr})
  styles_Y_gram = [gram(Y) for Y in styles_Y]
  return gen_img(), styles_Y_gram, trainer

14.12.7. 训练

在训练风格迁移模型时,我们不断提取合成图像的内容特征和风格特征,并计算损失函数。下面定义了训练循环。

def train(X, contents_Y, styles_Y, device, lr, num_epochs, lr_decay_epoch):
  X, styles_Y_gram, trainer = get_inits(X, device, lr, styles_Y)
  scheduler = torch.optim.lr_scheduler.StepLR(trainer, lr_decay_epoch, 0.8)
  animator = d2l.Animator(xlabel='epoch', ylabel='loss',
              xlim=[10, num_epochs],
              legend=['content', 'style', 'TV'],
              ncols=2, figsize=(7, 2.5))
  for epoch in range(num_epochs):
    trainer.zero_grad()
    contents_Y_hat, styles_Y_hat = extract_features(
      X, content_layers, style_layers)
    contents_l, styles_l, tv_l, l = compute_loss(
      X, contents_Y_hat, styles_Y_hat, contents_Y, styles_Y_gram)
    l.backward()
    trainer.step()
    scheduler.step()
    if (epoch + 1) % 10 == 0:
      animator.axes[1].imshow(postprocess(X))
      animator.add(epoch + 1, [float(sum(contents_l)),
                   float(sum(styles_l)), float(tv_l)])
  return X

def train(X, contents_Y, styles_Y, device, lr, num_epochs, lr_decay_epoch):
  X, styles_Y_gram, trainer = get_inits(X, device, lr, styles_Y)
  animator = d2l.Animator(xlabel='epoch', ylabel='loss',
              xlim=[10, num_epochs], ylim=[0, 20],
              legend=['content', 'style', 'TV'],
              ncols=2, figsize=(7, 2.5))
  for epoch in range(num_epochs):
    with autograd.record():
      contents_Y_hat, styles_Y_hat = extract_features(
        X, content_layers, style_layers)
      contents_l, styles_l, tv_l, l = compute_loss(
        X, contents_Y_hat, styles_Y_hat, contents_Y, styles_Y_gram)
    l.backward()
    trainer.step(1)
    if (epoch + 1) % lr_decay_epoch == 0:
      trainer.set_learning_rate(trainer.learning_rate * 0.8)
    if (epoch + 1) % 10 == 0:
      animator.axes[1].imshow(postprocess(X).asnumpy())
      animator.add(epoch + 1, [float(sum(contents_l)),
                   float(sum(styles_l)), float(tv_l)])
  return X

现在我们开始训练模型。我们将内容和样式图像的高度和宽度重新调整为 300 x 450 像素。我们使用内容图像来初始化合成图像。

device, image_shape = d2l.try_gpu(), (300, 450) # PIL Image (h, w)
net = net.to(device)
content_X, contents_Y = get_contents(image_shape, device)
_, styles_Y = get_styles(image_shape, device)
output = train(content_X, contents_Y, styles_Y, device, 0.3, 500, 50)

pYYBAGR9PCOAVzxPAALdi2cLvzA330.svg

device, image_shape = d2l.try_gpu(), (450, 300)
net.collect_params().reset_ctx(device)
content_X, contents_Y = get_contents(image_shape, device)
_, styles_Y = get_styles(image_shape, device)
output = train(content_X, contents_Y, styles_Y, device, 0.9, 500, 50)

poYBAGR9PCeAFdwbAANZAkSHWx4949.svg

我们可以看到,合成图保留了内容图的景物和物体,同时传递了风格图的颜色。例如,合成图像具有风格图像中的颜色块。其中一些块甚至具有笔触的微妙纹理。

14.12.8。概括

风格迁移中常用的损失函数由三部分组成:(i)内容损失使合成图像和内容图像在内容特征上接近;(ii) 风格损失使得合成图像和风格图像在风格特征上接近;(iii) 总变差损失有助于减少合成图像中的噪声。

我们可以使用预训练的 CNN 提取图像特征并最小化损失函数,以在训练期间不断更新合成图像作为模型参数。

我们使用 Gram 矩阵来表示样式层的样式输出。

14.12.9。练习

当您选择不同的内容和样式层时,输出如何变化?

调整损失函数中的权重超参数。输出是保留更多内容还是噪音更少?

使用不同的内容和样式图像。你能创造出更有趣的合成图像吗?

我们可以对文本应用样式转换吗?提示:您可以参考Hu等人的调查论文。( 2022 )。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cnn
    cnn
    +关注

    关注

    3

    文章

    327

    浏览量

    21304
  • pytorch
    +关注

    关注

    2

    文章

    764

    浏览量

    12836
收藏 人收藏

    评论

    相关推荐

    教你如何用OpenCV、Python和深度学习技术对图像和实时视频进行神经风格迁移

    虽然Gatys等人的方法能生成不错的神经风格迁移结果,但是它的速度非常慢。2016年,Johnson等人在Gatys的基础上提出的全新算法速度快了三倍,但同时也存在着缺点,即用户不能随机选择想要应用的
    的头像 发表于 08-31 09:47 7418次阅读

    【洞幺邦】基于深度学习的GAN应用风格迁移

    博弈以学习产生好的输出。”当然这么说略显抽象,我们不如来看一个有趣的例子:当爱德华·蒙克碰撞上现实生活中骑车的行人,会产生怎样的火花呢?​(该图片来自大名鼎鼎的风格迁移开创论文:Image Style
    发表于 07-01 10:53

    迁移学习

    经典机器学习算法介绍章节目标:机器学习是人工智能的重要技术之一,详细了解机器学习的原理、机制和方法,为学习深度学习与迁移学习打下坚实的基础。二、深度学习简介与经典网络结构介绍 神经网络简介神经网络组件简介
    发表于 04-21 15:15

    机器学习简介与经典机器学习算法人才培养

    经典机器学习算法介绍章节目标:机器学习是人工智能的重要技术之一,详细了解机器学习的原理、机制和方法,为学习深度学习与迁移学习打下坚实的基础。二、深度学习简介与经典网络结构介绍神经网络简介神经网络组件简介
    发表于 04-28 18:56

    Facebook致力AI 开源PyTorch1.0 AI框架

    ,将于近期开源PyTorch 1.0 AI框架,据悉,该框架是PyTorch与Caffe 2的结合,可以让开发者无需迁移就从研究转为生产。 据悉,Facebook2017年与微软公司合作开源了开放
    的头像 发表于 06-18 10:30 2941次阅读

    ​多模态风格迁移——生成更加美丽动人的风格图像

    基于卷积的图像风格迁移主要利用两种方法来对特征进行表示,一种假设全局具有相同分布并用全局特征来表风格,另一种则基于图像片提取风格。当风格图像
    的头像 发表于 05-01 14:11 4435次阅读

    基于PyTorch的深度学习入门教程之PyTorch的自动梯度计算

    计算 Part3:使用PyTorch构建一个神经网络 Part4:训练一个神经网络分类器 Part5:数据并行化 本文是关于Part2的内容。 Part2:PyTorch的自动梯度计算
    的头像 发表于 02-16 15:26 1755次阅读

    基于PyTorch的深度学习入门教程之使用PyTorch构建一个神经网络

    PyTorch的自动梯度计算 Part3:使用PyTorch构建一个神经网络 Part4:训练一个神经网络分类器 Part5:数据并行化 本文是关于Part3的内容。 Part3:使
    的头像 发表于 02-15 09:40 1886次阅读

    PyTorch教程之循环神经网络

    电子发烧友网站提供《PyTorch教程之循环神经网络.pdf》资料免费下载
    发表于 06-05 09:52 0次下载
    <b class='flag-5'>PyTorch</b>教程之循环<b class='flag-5'>神经</b>网络

    PyTorch教程10.3之深度递归神经网络

    电子发烧友网站提供《PyTorch教程10.3之深度递归神经网络.pdf》资料免费下载
    发表于 06-05 15:12 0次下载
    <b class='flag-5'>PyTorch</b>教程10.3之深度递归<b class='flag-5'>神经</b>网络

    PyTorch教程10.4之双向递归神经网络

    电子发烧友网站提供《PyTorch教程10.4之双向递归神经网络.pdf》资料免费下载
    发表于 06-05 15:13 0次下载
    <b class='flag-5'>PyTorch</b>教程10.4之双向递归<b class='flag-5'>神经</b>网络

    PyTorch教程14.12神经风格迁移

    电子发烧友网站提供《PyTorch教程14.12神经风格迁移.pdf》资料免费下载
    发表于 06-05 11:21 0次下载
    <b class='flag-5'>PyTorch</b>教程<b class='flag-5'>14.12</b>之<b class='flag-5'>神经</b><b class='flag-5'>风格</b><b class='flag-5'>迁移</b>

    PyTorch教程16.2之情感分析:使用递归神经网络

    电子发烧友网站提供《PyTorch教程16.2之情感分析:使用递归神经网络.pdf》资料免费下载
    发表于 06-05 10:55 0次下载
    <b class='flag-5'>PyTorch</b>教程16.2之情感分析:使用递归<b class='flag-5'>神经</b>网络

    PyTorch教程21.6之用于个性化排名的神经协同过滤

    电子发烧友网站提供《PyTorch教程21.6之用于个性化排名的神经协同过滤.pdf》资料免费下载
    发表于 06-06 09:30 0次下载
    <b class='flag-5'>PyTorch</b>教程21.6之用于个性化排名的<b class='flag-5'>神经</b>协同过滤

    基于OpenCV的DNN图像风格迁移

    /deep-photo-styletransfer 项目,需要安装 CUDA、pytorch、cudnn等等,配置能花一天的时间。 不过最近我发现一个非常好的开源应用项目,那就是基于OpenCV的DNN图像风格迁移。你只需要安装
    的头像 发表于 10-30 10:03 250次阅读