Pytorch Advanced(三) Neural Style Transfer

这篇具有很好参考价值的文章主要介绍了Pytorch Advanced(三) Neural Style Transfer。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

神经风格迁移在之前的博客中已经用keras实现过了,比较复杂,keras版本。

这里用pytorch重新实现一次,原理图如下:

Pytorch Advanced(三) Neural Style Transfer,deep learning,pytorch,人工智能,python


from __future__ import division
from torchvision import models
from torchvision import transforms
from PIL import Image
import argparse
import torch
import torchvision
import torch.nn as nn
import numpy as np

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

加载图像

def load_image(image_path, transform=None, max_size=None, shape=None):
    """Load an image and convert it to a torch tensor."""
    image = Image.open(image_path)
    
    if max_size:
        scale = max_size / max(image.size)
        size = np.array(image.size) * scale
        image = image.resize(size.astype(int), Image.ANTIALIAS)
    
    if shape:
        image = image.resize(shape, Image.LANCZOS)
    
    if transform:
        image = transform(image).unsqueeze(0)
    
    return image.to(device)

这里用的模型是 VGG-19,所要用的是网络中的5个卷积层

class VGGNet(nn.Module):
    def __init__(self):
        """Select conv1_1 ~ conv5_1 activation maps."""
        super(VGGNet, self).__init__()
        self.select = ['0', '5', '10', '19', '28'] 
        self.vgg = models.vgg19(pretrained=True).features
        
    def forward(self, x):
        """Extract multiple convolutional feature maps."""
        features = []
        for name, layer in self.vgg._modules.items():
            x = layer(x)
            if name in self.select:
                features.append(x)
        return features

 模型结构如下,可以看到使用序列模型来写的VGG-NET,所以标号即层号,我们要保存的是['0', '5', '10', '19', '28'] 的输出结果。

VGG(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (1): ReLU(inplace)
    (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (3): ReLU(inplace)
    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (6): ReLU(inplace)
    (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (8): ReLU(inplace)
    (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace)
    (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (13): ReLU(inplace)
    (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (15): ReLU(inplace)
    (16): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (17): ReLU(inplace)
    (18): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (19): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (20): ReLU(inplace)
    (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (22): ReLU(inplace)
    (23): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (24): ReLU(inplace)
    (25): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (26): ReLU(inplace)
    (27): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (29): ReLU(inplace)
    (30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (31): ReLU(inplace)
    (32): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (33): ReLU(inplace)
    (34): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (35): ReLU(inplace)
    (36): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
  (classifier): Sequential(
    (0): Linear(in_features=25088, out_features=4096, bias=True)
    (1): ReLU(inplace)
    (2): Dropout(p=0.5)
    (3): Linear(in_features=4096, out_features=4096, bias=True)
    (4): ReLU(inplace)
    (5): Dropout(p=0.5)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

 训练:

接下来对训练过程进行解释:

1、加载风格图像和内容图像,我们在之前的博客中使用的一幅加噪图进行训练,这里是用的内容图像的拷贝。

2、我们需要优化的就是作为目标的内容图像拷贝,可以看到target需要求导。

3、VGGnet参数是不需要优化的,所以设置为验证状态。

4、将3幅图像输入网络,得到总共15个输出(每个图像有5层的输出)

5、内容损失:这里是遍历5个层的输出来计算损失,而在keras版本中只用了第4层的输出计算损失

6、风格损失:同样计算格拉姆风格矩阵,将每一层的风格损失叠加,得到总的风格损失,计算公式同样和keras版本有所不一样

7、反向传播

def main(config):
    
    # Image preprocessing
    # VGGNet was trained on ImageNet where images are normalized by mean=[0.485, 0.456, 0.406] and std=[0.229, 0.224, 0.225].
    # We use the same normalization statistics here.
    transform = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize(mean=(0.485, 0.456, 0.406), 
                             std=(0.229, 0.224, 0.225))])
    
    # Load content and style images
    # Make the style image same size as the content image
    content = load_image(config.content, transform, max_size=config.max_size)
    style = load_image(config.style, transform, shape=[content.size(2), content.size(3)])
    
    # Initialize a target image with the content image
    target = content.clone().requires_grad_(True)
    
    optimizer = torch.optim.Adam([target], lr=config.lr, betas=[0.5, 0.999])
    vgg = VGGNet().to(device).eval()
    
    for step in range(config.total_step):
        
        # Extract multiple(5) conv feature vectors
        target_features = vgg(target)
        content_features = vgg(content)
        style_features = vgg(style)

        style_loss = 0
        content_loss = 0
        for f1, f2, f3 in zip(target_features, content_features, style_features):
            # Compute content loss with target and content images
            content_loss += torch.mean((f1 - f2)**2)

            # Reshape convolutional feature maps
            _, c, h, w = f1.size()
            f1 = f1.view(c, h * w)
            f3 = f3.view(c, h * w)

            # Compute gram matrix
            f1 = torch.mm(f1, f1.t())
            f3 = torch.mm(f3, f3.t())

            # Compute style loss with target and style images
            style_loss += torch.mean((f1 - f3)**2) / (c * h * w) 
        
        # Compute total loss, backprop and optimize
        loss = content_loss + config.style_weight * style_loss 
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if (step+1) % config.log_step == 0:
            print ('Step [{}/{}], Content Loss: {:.4f}, Style Loss: {:.4f}' 
                   .format(step+1, config.total_step, content_loss.item(), style_loss.item()))

        if (step+1) % config.sample_step == 0:
            # Save the generated image
            denorm = transforms.Normalize((-2.12, -2.04, -1.80), (4.37, 4.46, 4.44))
            img = target.clone().squeeze()
            img = denorm(img).clamp_(0, 1)
            torchvision.utils.save_image(img, 'output-{}.png'.format(step+1))

写在if __name__=="__main__"后面的语句只会在本脚本中才能被执行,被调用时是不会被执行的。 

python的命令行工具:argparse,很优雅的添加参数

但是由于jupyter不支持添加外部参数,所以使用了外部博客的方法来支持(记住更改读取图片的位置)文章来源地址https://www.toymoban.com/news/detail-707929.html

import sys
if __name__ == "__main__":
    
    #解决方案来自于博客
    if '-f' in sys.argv:
        sys.argv.remove('-f')
    
    parser = argparse.ArgumentParser()
    parser.add_argument('--content', type=str, default='png/content.png')
    parser.add_argument('--style', type=str, default='png/style.png')
    parser.add_argument('--max_size', type=int, default=400)
    parser.add_argument('--total_step', type=int, default=2000)
    parser.add_argument('--log_step', type=int, default=10)
    parser.add_argument('--sample_step', type=int, default=500)
    parser.add_argument('--style_weight', type=float, default=100)
    parser.add_argument('--lr', type=float, default=0.003)
    #config = parser.parse_args()
    config = parser.parse_known_args()[0]   #参考博客 https://blog.csdn.net/ken_for_learning/article/details/89675904
    print(config)
    main(config)

到了这里,关于Pytorch Advanced(三) Neural Style Transfer的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【论文精读】Deep Forest: Towards an Alternative to Deep Neural Networks

    本文详细阐述了 周志华教授及其学生冯霁 于 2017发表的一篇关于 深度森林 的学术论文。 注意 :本文不是对原论文的逐句翻译,而是提取论文中的关键信息,重点是是多粒度级联森林的原理部分。 同时也增加了自己的一些理解和感悟。 论文标题译为: 深度森林:深度神经

    2023年04月08日
    浏览(53)
  • 【论文合集】Awesome Transfer Learning

    目录 Papers (论文) 1.Introduction and Tutorials (简介与教程) 2.Transfer Learning Areas and Papers (研究领域与相关论文) 3.Theory and Survey (理论与综述) 4.Code (代码) 5.Transfer Learning Scholars (著名学者) 6.Transfer Learning Thesis (硕博士论文) 7.Datasets and Benchmarks (数据集与评测结果) 8.Transfer Learning Challen

    2024年02月06日
    浏览(82)
  • Neural Architecture Search for Deep Image Prior

    论文链接:https://arxiv.org/abs/2001.04776 项目链接:https://github.com/Pol22/NAS_DIP 在最近提出的深度图像先验算法(DIP)下,我们提出了一种神经结构搜索(NAS)技术来提高无监督图像去噪、修复和超分辨率的性能。我们发现,进化搜索可以自动优化DIP网络的编码器-解码器(E-D)结构和元参数

    2024年02月03日
    浏览(40)
  • 深度学习|9.7迁移学习transfer learning

    迁移学习是指将针对某项任务学习到的知识应用到其他任务的问题解决中去。 可以下载别人训练好的网络,保留网络中训练好的参数(参数分两种,一种是人为设置好的超参数,另外一种是在训练过程中学习/调整到的参数) 注意的是,原先训练好的网络可能会有多个输出结

    2024年01月20日
    浏览(42)
  • 【风格迁移-论文笔记12.20】Arbitrary style transfer based on Attention and Covariance-Matching

    任意风格迁移(Arbitrary style transfer)具有广阔的应用前景和重要的研究价值,是计算机视觉领域的研究热点。许多研究表明,任意风格迁移取得了显着的成功。 然而,现有的方法可能会产生伪影(artifacts),有时会导致内容结构的失真(distortion)。 为此,本文提出一种新颖

    2024年02月03日
    浏览(42)
  • Youtube DNN:Deep Neural Networks for YouTube Recommendations

    本文主要解决的三个挑战: 大规模的推荐场景,能够支持分布式训练和提供有效率的服务。 不断更新的新物料。 稀疏的用户行为,包含大量的噪声。 文章包含推荐系统的两阶段模型:召回和排序。 召回网络根据用户的历史行为从视频库中检索几百个候选视频,这些视频被

    2024年02月06日
    浏览(33)
  • 第八章 模型篇:transfer learning for computer vision

    参考教程: transfer-learning transfer-learning tutorial 很少会有人从头开始训练一个卷积神经网络,因为并不是所有人都有机会接触到大量的数据。常用的选择是在一个非常大的模型上预训练一个模型,然后用这个模型为基础,或者固定它的参数用作特征提取,来完成特定的任务。

    2024年02月11日
    浏览(39)
  • 【深度学习】风格迁移,转换,Stable Diffusion,FreeStyle : Free Lunch for Text-guided Style Transfer using Diffusion

    论文:https://arxiv.org/abs/2401.15636 代码:https://github.com/FreeStyleFreeLunch/FreeStyle 介绍 生成扩散模型的快速发展极大地推进了风格迁移领域的发展。然而,大多数当前基于扩散模型的风格转移方法通常涉及缓慢的迭代优化过程,例如模型微调和风格概念的文本反转。在本文中,我们

    2024年04月13日
    浏览(37)
  • 深度学习入门——深度卷积神经网络模型(Deep Convolution Neural Network,DCNN)概述

    机器学习是实现人工智能的方法和手段,其专门研究计算机如何模拟或实现人类的学习行为,以获取新的知识和技能,重新组织已有的知识结构使之不断改善自身性能的方法。计算机视觉技术作为人工智能的一个研究方向,其随着机器学习的发展而进步,尤其近10年来,以深

    2024年02月13日
    浏览(42)
  • 【论文阅读】ELA: Efficient Local Attention for Deep Convolutional Neural Networks

    论文链接 :ELA: Efficient Local Attention for Deep Convolutional Neural Networks (arxiv.org) 作者 :Wei Xu, Yi Wan 单位 :兰州大学信息科学与工程学院,青海省物联网重点实验室,青海师范大学 引用 :Xu W, Wan Y. ELA: Efficient Local Attention for Deep Convolutional Neural Networks[J]. arXiv preprint arXiv:2403.01123,

    2024年04月15日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包