def invert(self, image, num_viz=0):
    'Inverts the given image to a latent code.\n\n    Basically, this function is based on gradient descent algorithm.\n\n    Args:\n      image: Target image to invert, which is assumed to have already been\n        preprocessed.\n      num_viz: Number of intermediate outputs to visualize. (default: 0)\n\n    Returns:\n      A two-element tuple. First one is the inverted code. Second one is a list\n        of intermediate results, where first image is the input image, second\n        one is the reconstructed result from the initial latent code, remainings\n        are from the optimization process every `self.iteration // num_viz`\n        steps.\n    '
    x = image[np.newaxis]
    x = self.G.to_tensor(x.astype(np.float32))
    x.requires_grad = False
    init_z = self.get_init_code(image)
    z = torch.Tensor(init_z).to(self.run_device)
    z.requires_grad = True
    optimizer = torch.optim.Adam([z], lr=self.learning_rate)
    viz_results = []
    viz_results.append(self.G.postprocess(_get_tensor_value(x))[0])
    x_init_inv = self.G.net.synthesis(z)
    viz_results.append(self.G.postprocess(_get_tensor_value(x_init_inv))[0])
    pbar = tqdm(range(1, (self.iteration + 1)), leave=True)
    for step in pbar:
        loss = 0.0
        x_rec = self.G.net.synthesis(z)
        loss_pix = torch.mean(((x - x_rec) ** 2))
        loss = (loss + (loss_pix * self.loss_pix_weight))
        log_message = f'loss_pix: {_get_tensor_value(loss_pix):.3f}'
        if self.loss_feat_weight:
            x_feat = self.F.net(x)
            x_rec_feat = self.F.net(x_rec)
            loss_feat = torch.mean(((x_feat - x_rec_feat) ** 2))
            loss = (loss + (loss_feat * self.loss_feat_weight))
            log_message += f', loss_feat: {_get_tensor_value(loss_feat):.3f}'
        if self.loss_reg_weight:
            z_rec = self.E.net(x_rec).view(1, *self.encode_dim)
            loss_reg = torch.mean(((z - z_rec) ** 2))
            loss = (loss + (loss_reg * self.loss_reg_weight))
            log_message += f', loss_reg: {_get_tensor_value(loss_reg):.3f}'
        log_message += f', loss: {_get_tensor_value(loss):.3f}'
        pbar.set_description_str(log_message)
        if self.logger:
            self.logger.debug(f'Step: {step:05d}, lr: {self.learning_rate:.2e}, {log_message}')
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if ((num_viz > 0) and ((step % (self.iteration // num_viz)) == 0)):
            viz_results.append(self.G.postprocess(_get_tensor_value(x_rec))[0])
    return (_get_tensor_value(z), viz_results)
Inverts the given image to a latent code.

Basically, this function is based on gradient descent algorithm.

Args:
  image: Target image to invert, which is assumed to have already been
    preprocessed.
  num_viz: Number of intermediate outputs to visualize. (default: 0)

Returns:
  A two-element tuple. First one is the inverted code. Second one is a list
    of intermediate results, where first image is the input image, second
    one is the reconstructed result from the initial latent code, remainings
    are from the optimization process every `self.iteration // num_viz`
    steps.
def invert(self, image, num_viz=0):
    'Inverts the given image to a latent code.\n\n    Basically, this function is based on gradient descent algorithm.\n\n    Args:\n      image: Target image to invert, which is assumed to have already been\n        preprocessed.\n      num_viz: Number of intermediate outputs to visualize. (default: 0)\n\n    Returns:\n      A two-element tuple. First one is the inverted code. Second one is a list\n        of intermediate results, where first image is the input image, second\n        one is the reconstructed result from the initial latent code, remainings\n        are from the optimization process every `self.iteration // num_viz`\n        steps.\n    '
    x = image[np.newaxis]
    x = self.G.to_tensor(x.astype(np.float32))
    x.requires_grad = False
    init_z = self.get_init_code(image)
    z = torch.Tensor(init_z).to(self.run_device)
    z.requires_grad = True
    optimizer = torch.optim.Adam([z], lr=self.learning_rate)
    viz_results = []
    viz_results.append(self.G.postprocess(_get_tensor_value(x))[0])
    x_init_inv = self.G.net.synthesis(z)
    viz_results.append(self.G.postprocess(_get_tensor_value(x_init_inv))[0])
    pbar = tqdm(range(1, (self.iteration + 1)), leave=True)
    for step in pbar:
        loss = 0.0
        x_rec = self.G.net.synthesis(z)
        loss_pix = torch.mean(((x - x_rec) ** 2))
        loss = (loss + (loss_pix * self.loss_pix_weight))
        log_message = f'loss_pix: {_get_tensor_value(loss_pix):.3f}'
        if self.loss_feat_weight:
            x_feat = self.F.net(x)
            x_rec_feat = self.F.net(x_rec)
            loss_feat = torch.mean(((x_feat - x_rec_feat) ** 2))
            loss = (loss + (loss_feat * self.loss_feat_weight))
            log_message += f', loss_feat: {_get_tensor_value(loss_feat):.3f}'
        if self.loss_reg_weight:
            z_rec = self.E.net(x_rec).view(1, *self.encode_dim)
            loss_reg = torch.mean(((z - z_rec) ** 2))
            loss = (loss + (loss_reg * self.loss_reg_weight))
            log_message += f', loss_reg: {_get_tensor_value(loss_reg):.3f}'
        log_message += f', loss: {_get_tensor_value(loss):.3f}'
        pbar.set_description_str(log_message)
        if self.logger:
            self.logger.debug(f'Step: {step:05d}, lr: {self.learning_rate:.2e}, {log_message}')
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if ((num_viz > 0) and ((step % (self.iteration // num_viz)) == 0)):
            viz_results.append(self.G.postprocess(_get_tensor_value(x_rec))[0])
    return (_get_tensor_value(z), viz_results)