学习和应用图像风格迁移的 PyTorch 入门指南
从图片文件中加载训练数据
引入相关包
首先导入所有需要的软件包,软件包中大部分都是熟悉面孔。在本次实验中依然使用 torchvision 中的大型神经网络模型做迁移网络,使用 transforms 进行图片的转换等操作。需要提一下的是 PIL 包。这个包中包含了大量处理图片数据的工具,是一个经典的图像处理工具包。并且 PIL 包存在一个复刻版本,叫做 pillow,大家可以自行了解。
# 下载实验所需数据并解压
!wget http://labfile.oss.aliyuncs.com/courses/1073/images.zip
!unzip images.zip
#导入必要的包
from __future__ import print_function
import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.optim as optim
from PIL import Image
import matplotlib.pyplot as plt
import torchvision.transforms as transforms
import torchvision.models as models
import copy
判断 GPU 环境
如果想让自己的程序能够自动识别 GPU 计算环境,并且在 GPU 不具备的情况下也能自动使用 CPU 正常运行,那么应该:
# 是否用GPU计算,如果检测到有安装好的GPU,则利用它来计算
use_cuda = torch.cuda.is_available()
dtype = torch.cuda.FloatTensor if use_cuda else torch.FloatTensor
准备输入文件
进行图像风格迁移需要准备两张同样大小的文件,一张作为风格,一张作为内容。因为图片数据本身在后面要参加梯度计算,所以在这里首先将图像转化为张量,方便后面计算时转化为 Variable。
#风格图像的路径,自行设定
style = 'images/escher.jpg'
#内容图像的路径,自行设定
content = 'images/portrait1.jpg'
#风格损失所占比重
style_weight=1000
#内容损失所占比重
content_weight=1
#希望得到的图片大小(越大越清晰,计算越慢)
imsize = 128
loader = transforms.Compose([
transforms.Resize(imsize), # 将加载的图像转变为指定的大小
transforms.ToTensor()]) # 将图像转化为tensor
图像的加载与显示
首先定义图片加载函数,加载风格图像和内容图像,检测图像的尺寸。
#图片加载函数
def image_loader(image_name):
image = Image.open(image_name)
image = Variable(loader(image))
# 为了适应卷积网络的需要,虚拟一个batch的维度
image = image.unsqueeze(0)
return image
#载入图片并检查尺寸
style_img = image_loader(style).type(dtype)
content_img = image_loader(content).type(dtype)
assert style_img.size() == content_img.size(), \
"我们需要输入相同尺寸的风格和内容图像"
同样的,定义图片显示函数,可以将 Tensor 中包含的图片数据显示出来。
# 绘制图像的函数
def imshow(tensor, title=None):
image = tensor.clone().cpu() # 克隆Tensor防止改变
image = image.view(3, imsize, imsize) # 删除添加的batch层
image = unloader(image)
plt.imshow(image)
if title is not None:
plt.title(title)
plt.pause(0.001) # 停一会以便更新视图
#绘制图片并查看
unloader = transforms.ToPILImage() # 将其转化为PIL图像(Python Imaging Library)
plt.ion()
plt.figure()
imshow(style_img.data, title='Style Image')
plt.figure()
imshow(content_img.data, title='Content Image')
风格迁移网络的实现
值得注意的是,风格迁移的实现并没有训练一个神经网络,而是将已训练好的卷积神经网络权值直接迁移过来.网络的学习过程并不体现为对神经网络权重的训练,而是训练一张输入的图像,让它尽可能地靠近内容图像的内容和风格图像的风格。
为了实现风格迁移,需要在迁移网络的基础上再构建一个计算图,这样可以加速计算。构建计算图分为两步:
1、加载一个训练好的CNN
2、在原网络的基础上添加计算风格损失和内容损失的新计算层
加载已训练好的大型网络 VGG
首先,利用 PyTorch 自带的计算机视觉包 torchvision 中加载 VGG 19 网络,只需要一句代码就能自动加载。
torch.utils.model_zoo.load_url('http://labfile.oss.aliyuncs.com/courses/1073/vgg19-dcbb9e9d.pth')
cnn = models.vgg19(pretrained=True).features
# 如果可能就用GPU计算:
if use_cuda:
cnn = cnn.cuda()
重新定义新的计算模块
接下来,定义如何计算内容损失,风格损失,以及 Gram 矩阵的函数如下:
首先定义内容损失模块:
#内容损失模块
class ContentLoss(nn.Module):
def __init__(self, target, weight):
super(ContentLoss, self).__init__()
# 由于网络的权重都是从target上迁移过来,所以在计算梯度的时候,需要把它和原始计算图分离
self.target = target.detach() * weight
self.weight = weight
self.criterion = nn.MSELoss()
def forward(self, input):
# 输入input为一个特征图
# 它的功能就是计算误差,误差就是当前计算的内容与target之间的均方误差
self.loss = self.criterion(input * self.weight, self.target)
self.output = input
return self.output
def backward(self, retain_graph=True):
# 开始进行反向传播算法
self.loss.backward(retain_graph=retain_graph)
return self.loss
紧接着是定义风格损失:
class StyleLoss(nn.Module):
# 计算风格损失的神经模块
def __init__(self, target, weight):
super(StyleLoss, self).__init__()
self.target = target.detach() * weight
self.weight = weight
#self.gram = GramMatrix()
self.criterion = nn.MSELoss()
def forward(self, input):
# 输入input就是一个特征图
self.output = input.clone()
# 计算本图像的gram矩阵,并将它与target对比
input = input.cuda() if use_cuda else input
self_G = Gram(input)
self_G.mul_(self.weight)
# 计算损失函数,即输入特征图的gram矩阵与目标特征图的gram矩阵之间的差异
self.loss = self.criterion(self_G, self.target)
return self.output
def backward(self, retain_graph=True):
# 反向传播算法
self.loss.backward(retain_graph=retain_graph)
return self.loss
最后是 Gram 矩阵。
#定义Gram矩阵
def Gram(input):
# 输入一个特征图,计算gram矩阵
a, b, c, d = input.size() # a=batch size(=1)
# b=特征图的数量
# (c,d)=特征图的图像尺寸 (N=c*d)
features = input.view(a * b, c * d) # 将特征图图像扁平化为一个向量
G = torch.mm(features, features.t()) # 计算任意两个向量之间的乘积
# 我们通过除以特征图中的像素数量来归一化特征图
return G.div(a * b * c * d)
注意,在这段代码中使用了 target.detach(),它的作用是将 target 与当前的动态计算图解耦,也就是设置它的 grad_fn 为空。这样,后续的操作将重新构造一个独立的动态计算图,而与以前的计算图无关。最后,将需要计算风格损失的层,以及内容损失的层实现定义好。可以通过这些层的名称在 VGG 网络中找到相应的模块。
# 希望计算的内容或者风格层 :
content_layers = ['conv_4'] #只考虑第四个卷积层的内容
style_layers = ['conv_1', 'conv_2', 'conv_3', 'conv_4', 'conv_5']
# 考虑第1、2、3、4、5层的风格损失
动态建立计算图
在所有的基本部件都准备完毕之后,就可以完成整个图像的优化过程了。我们希望利用 PyTorch 的动态计算图,以及强大的 backward 函数来自动完成对生成图像的优化。于是,下面要做的就是在原有的 VGG 网络基础上,重新定义一个新的动态计算图。在这个新的计算图中,除了原有 VGG 网络的一层接一层的计算步骤以外,还包括了内容损失和风格损失的计算步骤。
下面通过一层层地遍历 VGG 网络,将每一层的神经模块(nn.Module)同时添加到新的计算图中, 然后在相应的卷积层之后添加内容损失以及风格损失的计算模块来构建新的计算图的。之后,只需要在这个新的动态计算图上执行反向传播算法,就可以对生图像进行优化了。
下面的代码展示了整个过程:
#获取第一个图像batch和标签
# 定义列表存储每一个周期的计算损失
content_losses = []
style_losses = []
model = nn.Sequential() # 一个新的序贯网络模型
# 如果有GPU就把这些计算挪到GPU上:
if use_cuda:
model = model.cuda()
# 接下来要做的操作是:循环vgg的每一层,同时构造一个全新的神经网络model
# 这个新网络与vgg基本一样,只是多了一些新的层来计算风格损失和内容损失。
# 将每层卷积核的数据都加载到新的网络模型model上来
i = 1
for layer in list(cnn):
if isinstance(layer, nn.Conv2d):
name = "conv_" + str(i)
#将已加载的模块放到model这个新的神经模块中
model.add_module(name, layer)
if name in content_layers:
# 如果当前层模型在定义好的要计算内容的层:
target = model(content_img).clone() #将内容图像当前层的feature信息拷贝到target中
content_loss = ContentLoss(target, content_weight) #定义content_loss的目标函数
content_loss = content_loss if use_cuda else content_loss
model.add_module("content_loss_" + str(i), content_loss) #在新网络上加content_loss层
content_losses.append(content_loss)
if name in style_layers:
# 如果当前层在指定的风格层中,进行风格层损失的计算
target_feature = model(style_img).clone()
target_feature = target_feature.cuda() if use_cuda else target_feature
target_feature_gram = Gram(target_feature)
style_loss = StyleLoss(target_feature_gram, style_weight)
style_loss = style_loss.cuda() if use_cuda else style_loss
model.add_module("style_loss_" + str(i), style_loss)
style_losses.append(style_loss)
if isinstance(layer, nn.ReLU):
#如果不是卷积层,则做同样处理
name = "relu_" + str(i)
model.add_module(name, layer)
i += 1
if isinstance(layer, nn.MaxPool2d):
name = "pool_" + str(i)
model.add_module(name, layer)
风格迁移的训练
原始输入
首先,我们需要现准备一张原始的图像,可以是一张噪音图或者就是内容图。在这里随机生成一张原始的生成图像(噪音图),并将生成图像转换为自动微分变量(因为要对它进行调解)。
# 如果想从调整一张噪声图像开始,请用下面一行的代码
input_img = Variable(torch.randn(content_img.data.size())).type(dtype)
# 或者你可以尝试从调整内容图开始,那么请用下面这行代码
# input_img = content_img
if use_cuda:
input_img = input_img.cuda()
content_img = content_img.cuda()
style_img = style_img.cuda()
# 将选中的待调整图打印出来:
plt.figure()
imshow(input_img.data, title='Input Image')
优化输入的图像(训练过程)
接下来一步步迭代整个计算图,从而对图像进行优化。
# 首先,需要先讲输入图像变成神经网络的参数,这样我们就可以用反向传播算法来调节这个输入图像了
input_param = nn.Parameter(input_img.data)
#定义个优化器,采用LBFGS优化算法来优化(试验效果很好,它的特点是可以计算大规模数据的梯度下降)
optimizer = optim.LBFGS([input_param])
# 迭代步数
num_steps=300
"""运行风格迁移的主算法过程."""
print('正在构造风格迁移模型..')
print('开始优化..')
for i in range(num_steps):
#每一个训练周期
# 限制输入图像的色彩取值范围在0-1间
input_param.data.clamp_(0, 1)
# 清空梯度
optimizer.zero_grad()
# 将图像输入构造的神经网络中
model(input_param)
style_score = 0
content_score = 0
# 每个损失函数层都开始反向传播算法
for sl in style_losses:
style_score += sl.backward()
for cl in content_losses:
content_score += cl.backward()
# 每隔50个周期打印一次训练数据
if i % 50 == 0:
print("运行 {}轮:".format(i))
print('风格损失 : {:4f} 内容损失: {:4f}'.format(
style_score.data, content_score.data))
print()
def closure():
return style_score + content_score
#一步优化
optimizer.step(closure)
# 做一些修正,防止数据超界...
output = input_param.data.clamp_(0, 1)
# 打印结果图
plt.figure()
imshow(output, title='Output Image')
plt.ioff()
plt.show()
由于在线环境资源有限,此步骤的代码执行需要较长的时间,需要大家耐心等待。
推荐阅读
-
学习和应用图像风格迁移的 PyTorch 入门指南
-
吴恩达的深度学习,第四课(4)特殊应用:人脸识别和神经风格迁移
-
41 个下载免费 3D 模型的最佳网站-使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 17. Clara.io Clara.io 是一个创建 3D 内容的全球平台,也是一个培养新 3D 艺术家的社区。Clara.io 提供+100,000个免费的3D模型,包括OBJ,Blend,STL,FBX,DAE,Babylon.JS,Three.JS格式,用于 Clara.io,Unity 3D,Blender,Sketchup,Cinema 4D,3DS Max和Maya。 使用说明:免费,标准和专业帐户仅供个人使用,如果您需要将 clara.io 用于商业用途,请与销售团队联系。 18. 3DExport 3DExport是一个市场,您可以在其中购买和销售用于CG项目的3D模型,3D打印模型和纹理。它提供15 +不同的3D格式供下载,如3DS MAX(.max),Cinema4D(.c4d),Maya(.mb,.ma),Lightwave(.lwo),Softimage(.xsi),Wavefront OBJ(.obj),Autodesk FBX(.fbx)等。它还提供15种不同的语言! 使用说明:免费下载仅供个人和非商业用途。 19. 3D Warehouse 3D Warehouse是一个开放的库,允许用户共享和下载SketchUp 3D模型,用于建筑,设计,施工和娱乐!任何人都可以免费制作,修改和重新上传内容到3D仓库,您可以找到任何您能想到的东西,如家具,电子产品,室内产品等。 使用说明:3D Warehouse中的所有模型都是免费的,因此任何人都可以下载文件以用于SketchUp甚至其他软件,如AutoCAD,Revit和ArchiCAD。 20. CadNav.com CadNav是CGI平面设计师和CAD / CAM / CAE工程师的在线3D模型库,我们提供超过50000 +免费3D模型和CAD模型下载。在CadNav网站上,您可以下载高质量的多边形网格3D模型,3D CAD实体对象,纹理,Vray材料,3D作品,CAD图纸等。 使用说明:免费下载仅供个人和非商业用途。 21. All3dfree.net 就像网站名称一样,它提供免费的3D模型,还包括Vray材料,CAD块,2d和3d纹理集合,无需注册即可免费下载。它是不断更新的,因此您可以查找或请求3DS,MAX,C4D,skp,OBJ,FBX,MTL等格式的模型。 使用说明:所有资源均不允许用于商业用途,否则您将承担责任。 22. Hum3D 自2005年以来,Hum3D帮助来自3多个国家的80D艺术家节省3D建模时间,并制作逼真的3D模型,用于电影,视频游戏,AR应用程序和可视化。所有模型均由首席3D艺术家进行验证,他们检查其是否符合专业要求和最新的3D建模标准。 使用说明:免费下载仅供个人和非商业用途。 23. Artist-3D.com 艺术家-3D 库存的免费 3D 模型下载按通用类别排序。它为人体解剖学、汽车、家具、火箭、卫星等模型提供 AutoDesk 3DS Max 格式。您还可以在浏览他们的网站时找到教程和类似类型的建模。 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 24. Free the models 就像本网站的标题一样,它为3d应用程序和3d游戏引擎提供免费的内容模型。您可以为您的任何项目找到许多有趣且有用的模型!它提供3ds,wavefront,bryce,poser,lightwave,md2和unity3d格式的模型。还有一个很棒的纹理集合,可以在您最喜欢的建模和渲染程序中使用。 使用说明:您从这里下载的所有内容都可以免费使用,除非它不能包含在另一个免费的网络或CD收藏中,也不能单独出售。否则,您可以在商业游戏,3D应用程序或渲染作品中使用它。您不必提供信用,但如果您这样做,那就太好了。 25. Resources.blogscopia 本网站由一家名为Scopia的公司创建。他们制作3D图像和视频,您可以找到许多为CGI工作的信息架构设计的模型,所有这些都可以在现实生活中使用。您可以免费下载它们,但是,如果您想一次下载它们,您可以支付 3 到 9 欧元。 使用说明:您可以免费下载模型部分的所有文件。每个压缩文件都包含您也可以在此处找到的许可证。基本上,您可以对文件执行任何操作。唯一的限制是不归属于Scopia的重新分发。 26.ambientCG 1000+公共领域PBR材料适合所有人!环境CG是使用许多不同的方法和资产类型创建的,例如照片纹理(PBR),贴花(PBR),图集(PBR),照片纹理(普通),物质存档(SBSAR),雕刻画笔,3D模型和地形。您可以在所有项目中*使用它们! 使用说明:在 ambientCG 上提供下载的所有 PBR 材料、画笔、照片和 3D 模型均根据知识共享 CC0 1.0 通用许可提供。您可以复制、修改、分发和执行作品,即使是出于商业目的,也无需征得许可。信用将不胜感激。 不要满足于平庸的大理石纹理 - 立即使用我们的免费PBR大理石纹理升级您的3D设计。 27.Pixar One Twenty Eight 这是一个提供官方动画行业经典纹理的网站:皮克斯,创建于 1993 年,该纹理库包括 128 个重复纹理,现在免费提供。 它包含您来到的纹理,包括砖块和动物毛皮。肯定会有一些你可以使用的东西。 使用说明:皮克斯动画工作室的《Pixar One Twenty Eight》根据知识共享署名4.0国际许可协议进行许可。即使出于商业目的,您也可以重新混合、调整和构建您的作品,只要您以相同的条款对新创作进行信用和许可。 访问数以千计的免费纹理并提升您的设计游戏 - 立即开始下载! 28. 3DXO 即使有近 620 个免费贴纸可供下载,3DXO 也不是最大的资源,但它的内容非常有用,不需要注册。无论是简单的墙壁或地板,还是一些奇怪的小东西,您都需要的纹理都可以在此网站上看到。 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 29. 3DModelsCC0 3DModelsCC0 与其他产品的不同之处在于它包含超过 250+ 个高质量 3D 模型,并且本网站上的所有内容都是免费的,完全是公共领域!使用我们的模型时无需信用或归属! 使用说明:为每个人提供完全免费的公共领域内容。 30.Sketch up texture club Sketchup Texture Club是一个非营利性的教育和信息门户网站,由3D社区的图像促进协会管理,特别强调面向学生和建筑和室内设计专业人士的可视化和渲染技术,以及所有正在学习3D可视化的人。 使用说明:您无需支付版税或使用费。纹理可以免费下载和使用。不允许将纹理作为竞争产品出售或重新分发,即使图像被修改也是如此。 31. FlippedNormals FlippedNormal 是一个提供计算机图形和 3D 资产的市场,您可以找到许多用于雕刻、建模、纹理、概念艺术、3D 模型、游戏资产或课程的高级资产! 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 32. NASA 3D NASA 3D网站是一个在线门户,提供与太空和各种NASA任务相关的大量三维模型和模拟。该网站是用户友好的,并提供有关每个型号的详细信息。该网站允许用户探索和下载几种不同格式的模型,包括 OBJ、STL 和 FBX,只需单击下载按钮即可。 使用说明: 要下载模型,只需单击模型页面上的下载按钮并选择所需的格式。 33. 3DAGOGO (Astroprint) 3DAGOGO 是一个提供广泛 3D 模型的网站,包括角色、车辆和建筑物。3DAGOGO 的独特功能之一是它专注于适合 3D 打印的模型,使其成为希望创建物理原型或模型的设计师的绝佳资源。要使用 3DAGOGO,设计师只需在网站上搜索他们正在寻找的模型类型,然后下载 STL 格式的文件。 使用说明: 要使用 3DAGOGO,只需搜索所需的 3D 模型类型并下载 STL 格式的文件。根据需要自定义模型,并确保在将其用于商业目的之前检查使用权限。 34. FreeCAD FreeCAD是一款了不起的3D建模软件,可让您在计算机上创建令人难以置信的3D设计。该软件可免费下载和使用,它提供了广泛的工具和功能,可用于创建用于各种目的的3D模型。 该网站易于浏览,您可以找到开始使用FreeCAD的所有必要信息。此外,该网站还提供一系列教程和指南,可帮助您了解 3D 建模的来龙去脉。 使用说明: 要下载模型,请访问网站并从库中选择所需的模型。该网站还提供了一系列使用该软件的教程和指南。 35. Pinshape Pinshape是一个提供一系列3D打印模型的网站。网站上提供的型号质量很高,因此您可以确保您的最终印刷产品看起来很棒。该网站提供了广泛的模型,包括从家居用品到小雕像和珠宝的所有物品。 但这还不是Pinshape所能提供的全部!该网站还允许用户上传和共享自己的3D模型。这意味着您不仅可以下载出色的模型,还可以通过分享自己的设计为社区做出贡献。此外,Pinshape 提供了一系列自定义选项,因此您可以调整和调整模型以满足您的特定需求。 使用说明: 要下载模型,请在网站上创建一个帐户,搜索所需的模型,然后单击下载按钮。该网站还为每种型号提供了一系列定制选项。 36.Yeggi Yeggi 提供了大量免费的 3D 模型,您可以下载各种格式的模型,例如 STL、OBJ 和 FBX。该网站易于使用,您可以按关键字、类别或特定网站搜索模型。 Yeggi 对于任何寻找 3D 模型的人来说都是一个很好的资源。它提供了大量的模型集合,从日常物品到复杂的机械,以及介于两者之间的一切。该网站的收藏量在不断增长,每天都有新的型号增加。 使用说明: 要下载模型,请在网站上搜索所需的模型,然后单击下载按钮。该网站还提供指向托管模型的原始网站的链接。 37. Open3DModel 来自开放3D模型的图像 Open3DModel具有各种类别的模型,包括建筑,车辆和角色。无论您需要建筑物,汽车还是人的3D模型,都可以在此网站上找到。 该网站易于浏览,您可以按类别或关键字搜索模型。每个模型都附带预览图像和详细信息,例如文件格式、大小和多边形数量。此信息可以帮助您选择适合您需求的模型。 使用说明: 要下载模型,请访问网站,从库中选择所需的模型,然后单击下载按钮。 使用最好的 3D 资产管理工具简化您的 3D 制作流程。立即试用它们,将您的 3D 项目提升到一个新的水平! 38. 3DExport 对于那些为其 3D 设计项目寻找 3D 模型、纹理和其他资源的人来说,该平台是一个很好的资源。该网站有大量模型可供选择,包括 3D 打印对象、游戏资产等。用户可以按类别、文件格式或价格范围浏览,以找到适合其项目的完美资源。此外,3DExport 还提供一系列教程和其他 3D 资源,以帮助用户提高技能并创建更令人印象深刻的设计。 使用说明: 要使用 3DExport,只需创建一个帐户并浏览可用型号。您可以按类别、格式和价格进行搜索,以找到所需的型号。找到喜欢的模型后,只需下载它并开始在您的项目中使用它。 39.Blend Swap Blend Swap是一个社区驱动的市场,提供与Blender软件兼容的各种免费3D模型。该平台允许用户共享和下载模型、纹理和其他资产,以便在他们的项目中使用。 使用说明: 创建免费帐户后,您可以浏览社区上传的大量3D模型。当您找到要使用的一个时,只需下载它并将其导入您选择的 3D 软件即可。 40. 3DShook 3DShook 是一个高级 3D 模型市场,提供一系列用于建筑、游戏等各个行业的高质量模型。该平台提供基于订阅的模型,具有不同的定价计划,允许用户访问一系列模型。 使用说明: 注册免费帐户后,只需浏览3D模型库,选择您喜欢的模型,然后以您需要的格式下载它们。 41. Smithsonian X 3D 史密森尼 X 3D 对于正在寻找历史文物和文物的高质量 3D 模型的设计师来说,这是一个独特的资源。该平台提供了大量3D模型,这些模型是根据史密森尼博物馆和研究中心中的真实物体扫描创建的。 使用说明:
-
深度学习中的不确定性量化:2020年实用技术与应用大解析 - 61页精华解读" 这份报告深入剖析了近年来深度学习领域中不确定性量化(UQ)技术的最新发展,包括其在强化学习(RL)中的运用实例。探讨了贝叶斯近似和集成学习等主流UQ方法在各个具体场景中的广泛应用,比如自动驾驶、目标识别、图像修复、医疗影像分析(如分类和分割)、文本理解(如文本分类和风险评估)、以及生物信息学等多个领域。 报告进一步梳理了UQ方法在深度学习领域的关键应用案例,并针对当前面临的挑战及未来研究方向进行了概览和展望,为这一领域的研究人员和实践者提供了有价值的参考指南。