参考出自https://www.cs.princeton.edu/courses/archive/spring18/cos598B/public/projects/LiteratureReview/COS598B_spr2018_NeuralStyleTransfer.pdf
内容特征:图片输出入CNN某一层的激活值
风格特征:图片输入到CNN中的激活值的关联
分别将两张图输入model,分别得到在网络某一层的输出
和
,调整
越小,
content reconstructions 越到深层越差
style reconstruction 越到深层越接近风格
总结:风格深层,内容高层
内容损失函数的计算
代表第
个卷积层的卷积核的个数,大小为
输入图片到第
个卷积层 第
个卷积核 第
个位置的激活值
待生成图片到第
个卷积层 第
个卷积核第
个位置的激活值
# 输入图片的每层激活值
content_features=[vgg_for_content.conv1_1,
vgg_for_content.conv1_2,
#vgg_for_content.conv2_1,
#vgg_for_content.conv2_2
]
# 待生成图片的每层激活值
res_content_features=[vgg_for_res.conv1_1,
vgg_for_res.conv1_2,
# vgg_for_res.conv2_1,
# vgg_for_res.conv2_2
]
content_loss=tf.zeros(1,tf.float32)
# content_features [1,long,width,channel] , 需要在1,2,3维度上求平均
for c,c_ in zip(content_features,res_content_features):
content_loss+=tf.reduce_mean((c-c_)**2,[1,2,3])
风格损失
def gram_matrix(x):
# b一直是1
b,w,h,ch=x.get_shape().as_list()
features=tf.reshape(x,[b,h*w,ch])
# 计算 [h*w,ch] 两两列向量的相似度 ,所以矩阵乘以他的倒置
#[ch , h*w] * [h*w,ch] -> [ch,ch]
# adjoint_a=True 把第一个转置
# 为了得到的值防止过大 /tf.constant(ch*w*h,tf.float32)
gram=tf.matmul(features,features,adjoint_a=True)/tf.constant(ch*w*h,tf.float32)
return gram
# [1,width,height,channel]
style_features=[vgg_for_style.conv3_3,
vgg_for_style.conv4_3,
]
res_style_features=[vgg_for_res.conv3_3,
vgg_for_res.conv4_3,
]
style_gram=[gram_matrix(feature)
for feature in style_features]
res_style_gram=[gram_matrix(feature)
for feature in res_style_features]
style_loss=tf.zeros(1,tf.float32)
for s,s_ in zip(style_gram,res_style_gram):
style_loss +=tf.reduce_mean((s-s_)**2,[1,2])
最后得到既有风格图片的风格,内容图片的内容
运行慢,但可以逐步求导,产生很多效果图