吴恩达深度学习_4_Week4特殊应用:神经风格转变

深度学习与艺术:神经风格迁移


1、问题描述
2、迁移学习
3、神经风格迁移
4、解决优化问题
5、使用自己图片测试


第四门课:卷积神经网络
第四周:特殊应用:人脸识别和神经风格转换

在这个任务中,你将学习神经风格迁移。这个算法是由Gatys等人在2015年创建的(https://arxiv.org/abs/1508.06576)。
在这个任务中,你将:
1、实现神经风格迁移算法
2、使用你的算法生成新颖的艺术图片
你所学习的大部分算法都是通过优化成本函数来获得一组参数值。在神经风格迁移中,你将通过优化成本函数来获得像素值!

import os
import sys
import scipy.io
import scipy.misc
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow
from PIL import Image
from nst_utils import *
import numpy as np
import tensorflow as tf

一、问题描述

神经风格迁移(NST)是深度学习中最有趣的技术之一。如下所示,它将两幅图像合并在一起,即一个“内容”图像(C)和一个“风格”图像(S),以创建一个“生成”图像(G)。生成的图像G将图像C的“内容”与图像S的“风格”相结合。
在这个例子中,你将生成一幅巴黎卢浮宫博物馆的图像(内容图像C),与印象派运动的领导者克洛德·莫奈的一幅画作(风格图像S)相结合。在这里插入图片描述

二、迁移学习

神经风格迁移(NST)使用之前训练过的卷积网络,并在此基础上进行构建。利用在不同任务上训练过的网络并将其应用到新任务上的思想被称为迁移学习。
根据原始的NST论文(https://arxiv.org/abs/1508.06576),我们将使用VGG网络。具体来说,我们将使用VGG-19,这是VGG网络的一个19层版本。该模型已经在非常大的ImageNet数据库上进行了训练,因此已经学会了识别各种低层次特征(在较早的层次上)和高层次特征(在深层次上)。
运行以下代码以加载VGG模型的参数。这可能需要几秒钟的时间。

model = load_vgg_model("pretrained-model/imagenet-vgg-verydeep-19.mat")
print(model)

该模型以Python字典的形式存储,其中每个变量名是键,相应的值是包含该变量值的张量。要通过该网络运行图像,只需将图像提供给模型即可。在TensorFlow中,你可以使用tf.assign函数来实现。具体来说,你将像这样使用assign函数:

model["input"].assign(image)

这将将图像分配为模型的输入。之后,如果你想要访问特定层的激活值,比如在该图像上运行网络时的第4_2层,你可以在正确的张量conv4_2上运行TensorFlow会话,如下所示:

sess.run(model["conv4_2"])

三、神经风格迁移

在这里插入图片描述

1、计算内容损失

在我们的运行示例中,内容图像C将是巴黎卢浮宫的图片。运行下面的代码来查看卢浮宫的图片。

content_image = scipy.misc.imread("images/louvre.jpg")
imshow(content_image)

内容图像(C)显示了卢浮宫博物馆的金字塔,周围是巴黎的古老建筑,在晴朗的天空和几朵云彩的映衬下。

如何确保生成的图像G与图像C的内容相匹配?

如我们在讲座中所见,ConvNet的较早(较浅)层往往会检测到较低级别的特征,如边缘和简单纹理,而较后(较深)的层往往会检测到更高级别的特征,如更复杂的纹理和物体类别。
我们希望“生成”的图像G与输入图像C具有相似的内容。假设你选择了某一层的激活值来表示图像的内容。在实践中,如果你选择了网络中间的一层,既不太浅也不太深,你将得到最令人愉悦的视觉效果。(完成此练习后,你可以随时回来尝试使用不同的层,看看结果如何变化。)
因此,假设你选择了一个特定的隐藏层来使用。现在,将图像C设置为预训练的VGG网络的输入,并进行前向传播。设𝑎(𝐶)为你选择的层中的隐藏层激活。这将是一个𝑛𝐻×𝑛𝑊×𝑛𝐶的张量。使用图像G重复此过程:将G设置为输入,并进行前向传播。设𝑎(𝐺)为相应的隐藏层激活。我们将定义内容损失函数如下:
在这里插入图片描述
这里,𝑛𝐻,𝑛𝑊和𝑛𝐶是你选择的隐藏层的高度、宽度和通道数,它们出现在损失的归一化项中。为了清晰起见,注意𝑎(𝐶)和𝑎(𝐺)是对应于隐藏层激活的体积。为了计算成本𝐽𝑐𝑜𝑛𝑡𝑒𝑛𝑡(𝐶,𝐺),将这些三维体积展开成二维矩阵可能更方便,如下所示。(从技术上讲,展开步骤对于计算𝐽𝑐𝑜𝑛𝑡𝑒𝑛𝑡并不是必需的,但对于后面计算样式损失𝐽𝑠𝑡𝑦𝑙𝑒时,这将是一个很好的实践。
在这里插入图片描述
Exercise: Compute the “content cost” using TensorFlow.
Instructions: The 3 steps to implement this function are:
1、Retrieve dimensions from a_G:
To retrieve dimensions from a tensor X, use: X.get_shape().as_list()
2、Unroll a_C and a_G as explained in the picture above
If you are stuck, take a look at Hint1 and Hint2.
3、Compute the content cost:
If you are stuck, take a look at Hint3, Hint4 and Hint5.

计算内容损失
参数:
a_C -- 维度为 (1, n_H, n_W, n_C) 的张量,表示图像 C 的内容的隐藏层激活
a_G -- 维度为 (1, n_H, n_W, n_C) 的张量,表示图像 G 的内容的隐藏层激活
返回值:J_content -- 根据上述方程 1 计算得出的标量值
# GRADED FUNCTION: compute_content_cost
def compute_content_cost(a_C, a_G):  
    # Retrieve dimensions from a_G (≈1 line)
    m, n_H, n_W, n_C = a_G.get_shape().as_list()

    # Reshape a_C and a_G (≈2 lines)
    a_C_unrolled = tf.reshape(a_C, [n_H*n_W, n_C])
    a_G_unrolled = tf.reshape(a_G, [n_H*n_W, n_C])

    # compute the cost with tensorflow (≈1 line)
    J_content = 1./(4 * n_H * n_W * n_C)*tf.reduce_sum(tf.square(tf.subtract(a_C_unrolled, a_G_unrolled)))
    
    return J_content

tf.reset_default_graph()
with tf.Session() as test:
    tf.set_random_seed(1)
    a_C = tf.random_normal([1, 4, 4, 3], mean=1, stddev=4)
    a_G = tf.random_normal([1, 4, 4, 3], mean=1, stddev=4)
    J_content = compute_content_cost(a_C, a_G)
    print("J_content = " + str(J_content.eval()))   

J_content=6.76559
记住:
1、内容损失采用神经网络的隐藏层激活,并测量𝑎(𝐶)和𝑎(𝐺)之间的差异。
2、当我们后面最小化内容损失时,这将有助于确保𝐺具有与𝐶相似的内容。

2、计算风格损失

在我们的运行示例中,我们将使用以下风格图像:

style_image = scipy.misc.imread("images/monet_800600.jpg")
imshow(style_image)

这幅画是以印象派风格绘制的。
现在让我们来看看如何定义“风格”损失函数𝐽𝑠𝑡𝑦𝑙𝑒(𝑆,𝐺)。

1)风格矩阵

风格矩阵也称为“格拉姆矩阵”。在线性代数中,一组向量(𝑣1,…,𝑣𝑛)的格拉姆矩阵𝐺是点积矩阵,其元素为𝐺𝑖𝑗=𝑣𝑇𝑖𝑣𝑗=𝑛𝑝.𝑑𝑜𝑡(𝑣𝑖,𝑣𝑗)。换句话说,𝐺𝑖𝑗比较了𝑣𝑖与𝑣𝑗的相似程度:如果它们非常相似,则预期它们具有较大的点积,因此𝐺𝑖𝑗将很大。
请注意,这里使用的变量名称存在不幸的冲突。我们遵循文献中常用的术语,但𝐺用于表示风格矩阵(或格拉姆矩阵)以及生成的图像𝐺。我们将尽量确保从上下文中明确指出我们所指的𝐺是哪一个。
在这里插入图片描述
结果是一个维度为(𝑛𝐶,𝑛𝐶)的矩阵,其中𝑛𝐶是滤波器的数量。值𝐺𝑖𝑗衡量滤波器𝑖的激活与滤波器𝑗的激活之间的相似程度。
格拉姆矩阵的一个重要部分是对角线元素,如𝐺𝑖𝑖也衡量了滤波器𝑖的活动程度。例如,假设滤波器𝑖在图像中检测垂直纹理。那么𝐺𝑖𝑖衡量了整个图像中垂直纹理的普遍程度:如果𝐺𝑖𝑖较大,这意味着图像中有很多垂直纹理。
通过捕捉不同类型特征的普遍性(𝐺𝑖𝑖),以及不同特征如何一起出现(𝐺𝑖𝑗),风格矩阵𝐺衡量了图像的风格。
练习:使用 TensorFlow 实现一个计算矩阵 A 的格拉姆矩阵的函数。公式为:矩阵 A 的格拉姆矩阵为𝐺𝐴=𝐴𝐴𝑇。如果你遇到困难,请参考提示 1提示 2

Argument:A -- matrix of shape (n_C, n_H*n_W)
Returns:GA -- Gram matrix of A, of shape (n_C, n_C)
# GRADED FUNCTION: gram_matrix
def gram_matrix(A):
    GA = tf.matmul(A, tf.transpose(A))
    return GA

tf.reset_default_graph()
with tf.Session() as test:
    tf.set_random_seed(1)
    A = tf.random_normal([3, 2*1], mean=1, stddev=4)
    GA = gram_matrix(A)
    
    print("GA = " + str(GA.eval())) 

GA [[ 6.42230511 -4.42912197 -2.09668207]
[ -4.42912197 19.46583748 19.56387138]
[ -2.09668207 19.56387138 20.6864624 ]]

2)风格损失

在生成风格矩阵(格拉姆矩阵)之后,你的目标是最小化“风格”图像 S 的格拉姆矩阵与“生成”图像 G 的格拉姆矩阵之间的距离。目前,我们仅使用一个隐藏层 𝑎[𝑙],对应的该层的风格损失定义如下:
在这里插入图片描述
其中 𝐺(𝑆) 和 𝐺(𝐺) 分别是“风格”图像和“生成”图像的格拉姆矩阵,用网络中特定隐藏层的隐藏层激活计算得。
练习:计算单层的风格损失。
指导:实现这个函数的三个步骤:
1、从隐藏层激活 a_G 中获取维度:
要从张量 X 中获取维度,使用:X.get_shape().as_list()
2、将隐藏层激活 a_S 和 a_G 展开成2D矩阵,如上图所示。
你可能会发现 Hint1Hint2 有用。
3、计算图像 S 和 G 的风格矩阵。(使用之前编写的函数。)
4、计算风格损失:
你可能会发现 Hint3Hint4Hint5 有用。

参数:
a_S -- 维度为 (1, n_H, n_W, n_C) 的张量,表示图像 S 的风格的隐藏层激活
a_G -- 维度为 (1, n_H, n_W, n_C) 的张量,表示图像 G 的风格的隐藏层激活
返回:J_style_layer -- 表示标量值的张量,由上述方程(2)定义的风格损失
# GRADED FUNCTION: compute_layer_style_cost
def compute_layer_style_cost(a_S, a_G):
    # Retrieve dimensions from a_G (≈1 line)
    m, n_H, n_W, n_C = a_G.get_shape().as_list()

    # Reshape the images to have them of shape (n_C, n_H*n_W) (≈2 lines)
    a_S = tf.transpose(tf.reshape(a_S, [n_H*n_W, n_C]))
    a_G = tf.transpose(tf.reshape(a_G, [n_H*n_W, n_C]))

    # Computing gram_matrices for both images S and G (≈2 lines)
    #矩阵转置的时候一定要注意方向
    GS = gram_matrix(a_S)
    GG = gram_matrix(a_G)
    
    # Computing the loss (≈1 line)
    J_style_layer = 1./(4 * n_C * n_C * n_H * n_W * n_H * n_W) * tf.reduce_sum(tf.square(tf.subtract(GS, GG)))
    
    return J_style_layer
    
tf.reset_default_graph()
with tf.Session() as test:
    tf.set_random_seed(1)
    a_S = tf.random_normal([1, 4, 4, 3], mean=1, stddev=4)
    a_G = tf.random_normal([1, 4, 4, 3], mean=1, stddev=4)
    J_style_layer = compute_layer_style_cost(a_S, a_G)
    
    print("J_style_layer = " + str(J_style_layer.eval()))

J_style_layer 9.19028

3)风格权重

到目前为止,你只从一个层捕捉到了风格。如果我们从几个不同的层合并风格损失,我们将获得更好的结果。在完成这个练习之后,随意返回并尝试不同的权重,看看它如何改变生成的图像 𝐺。但目前,以下是一个相当合理的默认设置:

STYLE_LAYERS = [
    ('conv1_1', 0.2),
    ('conv2_1', 0.2),
    ('conv3_1', 0.2),
    ('conv4_1', 0.2),
    ('conv5_1', 0.2)]

你可以按照以下方式组合不同层的风格损失:
在这里插入图片描述
其中 𝜆[𝑙] 的值在 STYLE_LAYERS 中给出。
我们已经实现了一个 compute_style_cost(…) 函数。它只是多次调用你的 compute_layer_style_cost(…) 函数,并使用 STYLE_LAYERS 中的值对它们的结果进行加权。仔细阅读它,确保你理解它在做什么。

计算从几个选择的层中的总体风格损失
参数:
model -- 我们的 TensorFlow 模型
STYLE_LAYERS -- 一个包含以下内容的 Python 列表:
- 我们希望从中提取风格的层的名称
- 每个层的系数
返回:J_style -- 表示标量值的张量,由上述方程(2)定义的风格损失
def compute_style_cost(model, STYLE_LAYERS):
    # initialize the overall style cost
    J_style = 0
    
    for layer_name, coeff in STYLE_LAYERS:
        # Select the output tensor of the currently selected layer
        out = model[layer_name]
        # Set a_S to be the hidden layer activation from the layer we have selected, by running the session on out
        a_S = sess.run(out)
        # Set a_G to be the hidden layer activation from same layer. Here, a_G references model[layer_name] 
        # and isn't evaluated yet. Later in the code, we'll assign the image G as the model input, so that
        # when we run the session, this will be the activations drawn from the appropriate layer, with G as input.
        a_G = out
        
        # Compute style_cost for the current layer
        J_style_layer = compute_layer_style_cost(a_S, a_G)

        # Add coeff * J_style_layer of this layer to overall style cost
        J_style += coeff * J_style_layer

    return J_style

注意:在上述的 for 循环的内部循环中,a_G 是一个张量,尚未被评估。在下面的 model_nn() 中运行 TensorFlow 图时,它将在每次迭代时被评估和更新。
记住:

  • 图像的风格可以用隐藏层激活的格拉姆矩阵来表示。然而,如果将多个不同层的表示组合起来,我们可以获得更好的结果。这与内容表示形成对比,通常只使用一个隐藏层就足够了
  • 最小化风格损失将使图像 G 遵循图像 S 的风格

3、定义总成本以进行优化

最后,让我们创建一个成本函数,同时最小化风格成本和内容成本。公式如下:
在这里插入图片描述
练习:实现包括内容损失和风格损失的总成本函数。

计算总成本函数
参数:
J_content -- 上面编码的内容成本
J_style -- 上面编码的风格成本
alpha -- 调整内容成本重要性的超参数
beta -- 调整风格成本重要性的超参数
返回:J -- 如上述公式定义的总成本
# GRADED FUNCTION: total_cost
def total_cost(J_content, J_style, alpha = 10, beta = 40):
    J = alpha * J_content + beta * J_style
    
    return J

tf.reset_default_graph()
with tf.Session() as test:
    np.random.seed(3)
    J_content = np.random.randn()    
    J_style = np.random.randn()
    J = total_cost(J_content, J_style)
    print("J = " + str(J))

J 35.34667875478276
记住:

  • 总成本是内容成本 J_content(C, G) 和风格成本 J_style(S, G) 的线性组合。
  • α 和 β 是控制内容和风格之间相对权重的超参数。

四、解决优化问题

最后,让我们将所有内容整合起来,实现神经风格迁移!
以下是程序需要完成的任务:

  1. 创建一个交互式会话
  2. 加载内容图像
  3. 加载风格图像
  4. 随机初始化待生成的图像
  5. 加载 VGG16 模型
  6. 构建 TensorFlow 图:
    通过 VGG16 模型运行内容图像,并计算内容成本
    通过 VGG16 模型运行风格图像,并计算风格成本
    计算总成本
  7. 定义优化器和学习率:初始化 TensorFlow 图,并在大量迭代中运行,每步更新生成的图像。
    让我们详细地逐个步骤进行。
    你之前已经实现了总成本 J(G)。现在,我们将设置 TensorFlow 来优化它相对于 G。为此,你的程序必须重置图并使用一个 “Interactive Session”。与常规会话不同,“Interactive Session” 会自动安装自身作为默认会话来构建图。这使得你可以在不需要不断引用会话对象的情况下运行变量,简化了代码。
    让我们开始交互式会话。
# Reset the graph
tf.reset_default_graph()

# Start interactive session
sess = tf.InteractiveSession()

# Let's load, reshape, and normalize our "content" image (the Louvre museum picture):
content_image = scipy.misc.imread("images/louvre_small.jpg")
content_image = reshape_and_normalize_image(content_image)

# Let's load, reshape and normalize our "style" image (Claude Monet's painting):
style_image = scipy.misc.imread("images/monet.jpg")
style_image = reshape_and_normalize_image(style_image)

现在,我们将"生成的"图像初始化为从内容图像创建的噪声图像。通过将生成图像的像素初始化为大部分噪声,但仍与内容图像略有相关性,这将有助于"生成的"图像的内容更快地与"内容"图像匹配。(可以随意查看 nst_utils.py 中 generate_noise_image(…) 的详细信息;要这样做,请在此 Jupyter 笔记本的左上角点击 “File–>Open…”)。

generated_image = generate_noise_image(content_image)
imshow(generated_image[0])

Next, as explained in part (2), let’s load the VGG16 model.

model = load_vgg_model("pretrained-model/imagenet-vgg-verydeep-19.mat")

为了让程序计算内容成本,我们现在将分配 a_C 和 a_G 作为适当的隐藏层激活。我们将使用层 conv4_2 来计算内容成本。下面的代码执行以下操作:
1、将内容图像分配为 VGG 模型的输入。
2、将 a_C 设置为给定层 “conv4_2” 的隐藏层激活的张量。
3、将 a_G 设置为给定层相同的隐藏层激活的张量。
4、使用 a_C 和 a_G 计算内容成本。

# Assign the content image to be the input of the VGG model.  
sess.run(model['input'].assign(content_image))

# Select the output tensor of layer conv4_2
out = model['conv4_2']

# Set a_C to be the hidden layer activation from the layer we have selected
a_C = sess.run(out)

# Set a_G to be the hidden layer activation from same layer. Here, a_G references model['conv4_2'] 
# and isn't evaluated yet. Later in the code, we'll assign the image G as the model input, so that
# when we run the session, this will be the activations drawn from the appropriate layer, with G as input.
a_G = out

# Compute the content cost
J_content = compute_content_cost(a_C, a_G)

注意:在此时,a_G 是一个张量,尚未被评估。当我们在下面的 model_nn() 中运行 TensorFlow 图时,它将在每次迭代时被评估和更新。

# Assign the input of the model to be the "style" image 
sess.run(model['input'].assign(style_image))

# Compute the style cost
J_style = compute_style_cost(model, STYLE_LAYERS)

练习:现在你已经有了 J_content 和 J_style,通过调用 total_cost() 计算总成本 J。使用 alpha = 10 和 beta = 40。

J = total_cost(J_content, J_style, 10, 40)

你之前学过如何在 TensorFlow 中设置 Adam 优化器。让我们在这里使用学习率为 2.0 来进行设置。参考资料

# 定义优化器
optimizer = tf.train.AdamOptimizer(2.0)

# 定义训练步骤
train_step = optimizer.minimize(J)

练习:实现 model_nn() 函数,该函数初始化 TensorFlow 图的变量,将输入图像(初始生成的图像)分配为 VGG16 模型的输入,并运行 train_step 多次迭代。

def model_nn(sess, input_image, num_iterations = 200):
    # Initialize global variables (you need to run the session on the initializer)
    sess.run(tf.global_variables_initializer())
    # Run the noisy input image (initial generated image) through the model. Use assign().
    sess.run(model["input"].assign(input_image))
    
    for i in range(num_iterations):
        # Run the session on the train_step to minimize the total cost
        sess.run(train_step)
        
        # Compute the generated image by running the session on the current model['input']
        generated_image =sess.run(model["input"])

        # Print every 20 iteration.
        if i%20 == 0:
            Jt, Jc, Js = sess.run([J, J_content, J_style])
            print("Iteration " + str(i) + " :")
            print("total cost = " + str(Jt))
            print("content cost = " + str(Jc))
            print("style cost = " + str(Js))
            
            # save current generated image in the "/output" directory
            save_image("output/" + str(i) + ".png", generated_image)
    
    # save last generated image
    save_image('output/generated_image.jpg', generated_image)
    
    return generated_image

运行以下单元格以生成艺术图像。对于每 20 次迭代,它大约需要 3 分钟在 CPU 上运行,但你在大约 140 次迭代后开始观察到吸引人的结果。神经风格迁移通常使用 GPU 进行训练。

model_nn(sess, generated_image)

在这里插入图片描述
完成了!在运行完之后,在笔记本的上方栏中点击 “文件”,然后点击 “打开”。进入 “/output” 目录以查看所有保存的图像。打开 “generated_image” 以查看生成的图像! 😃
你应该能在右侧看到下面呈现的图像:
在这里插入图片描述
我们不希望你等待太久才能看到初步结果,因此根据此设置了超参数。为了获得最好的结果,可以更长时间地运行优化算法(可能使用较小的学习率)。完成并提交此任务后,我们鼓励你回来继续玩弄这个笔记本,看看是否能生成更美观的图像。
以下是其他几个例子:
伊朗古城佩尔塞波利斯(Persepolis)的美丽废墟,以梵高(The Starry Night)的风格呈现

帕萨加代的大库鲁斯之墓,以伊斯法罕的陶瓷卡希(Ceramic Kashi)的风格呈现
在这里插入图片描述
以抽象的蓝色流体绘画的风格呈现的湍流流体的科学研究。
在这里插入图片描述

五、使用自己的图像进行测试

最后,您还可以在自己的图像上重新运行算法!
要这样做,请返回第4部分,并使用您自己的图片更改内容图像和风格图像。具体来说,您应该这样做:
1、点击笔记本上方的上方选项卡中的“文件->打开”
2、转到“/images”并上传您的图像(要求:(宽度=300,高度=225)),例如将它们重命名为“my_content.png”和“my_style.png”。
3、将第(3.4)部分中的代码更改为:
content_image = scipy.misc.imread(“images/louvre.jpg”)
style_image = scipy.misc.imread(“images/claude-monet.jpg”)
to:
content_image = scipy.misc.imread(“images/my_content.jpg”)
style_image = scipy.misc.imread(“images/my_style.jpg”)
4、重新运行单元格(您可能需要在笔记本上方的上方选项卡中重新启动内核)。
您还可以调整超参数:
哪些层负责表示风格?STYLE_LAYERS
您想运行算法多少次迭代?num_iterations
内容和风格之间的相对权重是多少?alpha/beta

六、总结

完成此任务的出色工作!您现在可以使用神经风格转移生成艺术图片。这也是您首次构建的模型,其中优化算法更新的是像素值,而不是神经网络的参数。深度学习有许多不同类型的模型,这只是其中之一!
您应该记住的是:

  • 神经风格转移是一种算法,它可以生成艺术图片,给定内容图像C和风格图像S-它使用基于预训练ConvNet的表示(隐藏层激活)
  • 内容成本函数使用一个隐藏层的激活来计算
  • 一个层的风格成本函数使用该层激活的格拉姆矩阵来计算。通过多个隐藏层获得整体的风格成本函数-优化总成本函数会合成新的图像。

参考文献:
神经风格转移算法是由Gatys等人(2015)提出的。Harish Narayanan和Github用户“log0”也有非常可读的文章,我们从中汲取了灵感。此实现中使用的预训练网络是VGG网络,由Simonyan和Zisserman(2015)提出。预训练权重来自MathConvNet团队的工作。
1、Leon A. Gatys,Alexander S. Ecker,Matthias Bethge,(2015)。《艺术风格的神经算法》(https://arxiv.org/abs/1508.06576
2、Harish Narayanan,《卷积神经网络用于艺术风格转移》。https://harishnarayanan.org/writing/artistic-style-transfer/
3、Log0,《“艺术风格的神经算法”的TensorFlow实现》。http://www.chioka.in/tensorflow-implementation-neural-algorithm-of-artistic-style
4、Karen Simonyan and Andrew Zisserman (2015). Very deep convolutional networks for large-scale image recognition (https://arxiv.org/pdf/1409.1556.pdf)
5、MatConvNet. http://www.vlfeat.org/matconvnet/pretrained/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值