首先,Gram矩阵可以看做是矩阵的向量与其转置的内积,即:给定一个实矩阵 A,矩阵 A T A {A^T}A ATA是A的列向量的格拉姆矩阵,而矩阵 A A T A{A^T} AAT是A的行向量的格拉姆矩阵。 作业要求是实现: G i j l = ∑ m , n F i , m , n l F j , m , n l G_{ij}^l = \sum\limits_{m,n} {F_{i,m,n}^l} F_{j,m,n}^l Gijl=m,n∑Fi,m,nlFj,m,nl 其中 F i , m , n l {F_{i,m,n}^l} Fi,m,nl代表着层l输出的第i个feature-map中位置(m,n)的像素点。
而实际在python+TensorFlow的操作中,采用这样的方式实现一个Gram矩阵函数:
shape = source_feature.get_shape().as_list() N = shape[3] M = shape[1] * shape[2] F_s = tf.reshape(source_feature, (-1, N)) Gram_s = (tf.matmul(tf.transpose(F_s), F_s) / (N * M))作业要求的feature-map是从vgg16中build出来的,为了对每个conv-layer都输出一个feature-map。在train.py里面使用
image_model.get_layer(layer)或者是,简单点的方法是可以使用getattr函数:
source_feature = getattr(source, layer)就避免了提取layer报错的情况。 至于M和N,N代表feature-map的个数,M代表feature-map的size。
基于Gram-Matrix,定义Gram-Loss: L o s s = ∑ l w l 1 4 N l 2 M l 2 ∑ i , j ( G i j l − G i j l ^ ) 2 Loss = \sum\limits_l {{w_l}\frac{1}{{4N_l^2M_l^2}}} {\sum\limits_{i,j} {\left( {G_{ij}^l - \widehat {G_{ij}^l}} \right)} ^2} Loss=l∑wl4Nl2Ml21i,j∑(Gijl−Gijl )2 在不考虑权重 w l {w_l} wl的情况下,应写为:
def get_l2_gram_loss_for_layer(noise, source, layer): source_feature = getattr(source, layer) noise_feature = getattr(noise, layer) shape = source_feature.get_shape().as_list() N = shape[3] M = shape[1] * shape[2] F_s = tf.reshape(source_feature, (-1, N)) Gram_s = (tf.matmul(tf.transpose(F_s), F_s) / (N * M)) F_n = tf.reshape(noise_feature, (-1, N)) Gram_n = tf.matmul(tf.transpose(F_n), F_n) / (N * M) loss = tf.nn.l2_loss((Gram_s-Gram_n))/2 return loss对于网络整体的Gram-Loss,所给的参考code中写的是:
def get_gram_loss(noise, source): with tf.name_scope('get_gram_loss'): gram_loss = [get_l2_gram_loss_for_layer(noise, source, layer) for layer in GRAM_LAYERS] return tf.reduce_mean(tf.convert_to_tensor(gram_loss))对图像1做纹理生成: 用以上Gram-loss得到的结果为: 将这部分代码进行修改:
def get_gram_loss(noise, source): with tf.name_scope('get_gram_loss'): loss_sum = 0. for layer in GRAM_LAYERS: loss_sum = tf.add(loss_sum,weight*get_l2_gram_loss_for_layer(noise, source, layer)) return loss_sum得到:
带上权重后:
def get_gram_loss(noise, source): with tf.name_scope('get_gram_loss'): loss_sum = 0. weight = 1. for layer in GRAM_LAYERS: weight = weight*10 loss_sum = tf.add(loss_sum,weight*get_l2_gram_loss_for_layer(noise, source, layer)) return loss_sum生成结果如下:
