def eval_c_grad(layer, content): nonlocal loss feat = content.features[layer][:, start_[0]:end[0], start_[1]:end[1]] c_grad = self.data[layer] - feat loss += lw * content_weight[layer] * norm2(c_grad) axpy(lw * content_weight[layer], normalize(c_grad), self.diff[layer])
def eval_s_grad(layer, style): nonlocal loss current_gram = gram_matrix(self.data[layer]) n, mh, mw = self.data[layer].shape feat = self.data[layer].reshape((n, mh * mw)) gram_diff = current_gram - style.grams[layer] s_grad = self._arr_pool.array_like(feat) np.dot(gram_diff, feat, s_grad) s_grad = s_grad.reshape((n, mh, mw)) loss += lw * style_weight[layer] * norm2(gram_diff) / len( self.styles) / 2 axpy(lw * style_weight[layer] / len(self.styles), normalize(s_grad), self.diff[layer])
def eval_loss_and_grad(self, img, sc_grad_args): """Returns the summed loss and gradient.""" old_img = self.model.img self.model.img = img lw = self.layer_weights['data'] # Compute style+content gradient loss, grad = self.model.eval_sc_grad(*sc_grad_args) # Compute total variation gradient if ARGS.tv_weight: tv_loss, tv_grad = tv_norm(self.model.img / 127.5, beta=ARGS.tv_power) loss += lw * ARGS.tv_weight * tv_loss axpy(lw * ARGS.tv_weight, tv_grad, grad) # Compute SWT norm and gradient if ARGS.swt_weight: swt_loss, swt_grad = swt_norm(self.model.img / 127.5, ARGS.swt_wavelet, ARGS.swt_levels, p=ARGS.swt_power) loss += lw * ARGS.swt_weight * swt_loss axpy(lw * ARGS.swt_weight, swt_grad, grad) # Compute p-norm regularizer gradient (from jcjohnson/cnn-vis and [3]) if ARGS.p_weight: p_loss, p_grad = p_norm( (self.model.img + self.model.mean - 127.5) / 127.5, p=ARGS.p_power) loss += lw * ARGS.p_weight * p_loss axpy(lw * ARGS.p_weight, p_grad, grad) # Compute auxiliary image gradient if self.aux_image is not None: aux_grad = (self.model.img - self.aux_image) / 127.5 loss += lw * ARGS.aux_weight * norm2(aux_grad) axpy(lw * ARGS.aux_weight, aux_grad, grad) self.model.img = old_img return loss, grad
def eval_sc_grad_tile(self, img, start, layers, content_layers, style_layers, dd_layers, layer_weights, content_weight, style_weight, dd_weight): """Evaluates an individual style+content gradient tile.""" self.net.blobs['data'].reshape(1, 3, *img.shape[-2:]) self.data['data'] = img loss = 0 # Prepare gradient buffers and run the model forward for layer in layers: self.diff[layer] = 0 self.net.forward(end=layers[0]) self.data[layers[0]] = np.maximum(0, self.data[layers[0]]) for i, layer in enumerate(layers): lw = layer_weights[layer] scale, _ = self.layer_info(layer) start_ = start // scale end = start_ + np.array(self.data[layer].shape[-2:]) def eval_c_grad(layer, content): nonlocal loss feat = content.features[layer][:, start_[0]:end[0], start_[1]:end[1]] c_grad = self.data[layer] - feat loss += lw * content_weight[layer] * norm2(c_grad) axpy(lw * content_weight[layer], normalize(c_grad), self.diff[layer]) def eval_s_grad(layer, style): nonlocal loss current_gram = gram_matrix(self.data[layer]) n, mh, mw = self.data[layer].shape feat = self.data[layer].reshape((n, mh * mw)) gram_diff = current_gram - style.grams[layer] s_grad = self._arr_pool.array_like(feat) np.dot(gram_diff, feat, s_grad) s_grad = s_grad.reshape((n, mh, mw)) loss += lw * style_weight[layer] * norm2(gram_diff) / len( self.styles) / 2 axpy(lw * style_weight[layer] / len(self.styles), normalize(s_grad), self.diff[layer]) # Compute the content and style gradients if layer in content_layers: for content in self.contents: eval_c_grad(layer, content) if layer in style_layers: for style in self.styles: eval_s_grad(layer, style) if layer in dd_layers: loss -= lw * dd_weight[layer] * norm2(self.data[layer]) axpy(-lw * dd_weight[layer], normalize(self.data[layer]), self.diff[layer]) # Run the model backward if i + 1 == len(layers): self.net.backward(start=layer) else: self.net.backward(start=layer, end=layers[i + 1]) return loss, self.diff['data']