Hi Kai!



 mkaic:

#Initialize a random image to refine into the final product
candidate = tensor(white_noise_image, requires_grad = True)

optimizer = torch.optim.Adam([candidate], lr = lr)

#Training Loop
for i in num_iterations:
    optimizer.zero_grad()

    #Determine the embedding and gender of the candidate
    candidate_gender = gender_classifier(candidate)
    candidate_embedding = face_embedder(candidate)

    #Determine how bad these values are compared to what I *want*, which is
    #a similar embedding, but opposite gender.
    gender_loss = binary_cross_entropy(candidate_gender, !ground_truth_gender)
    embedding_loss = mse_loss(candidate_embedding, ground_truth_embedding)
    
    loss = gender_loss * hyperparameter_weight + embedding_loss

    optimizer.step()



In short, you need to call loss.backward() before calling
optimizer.step().
There is no need for a tensor to be part of a model in order to
optimize it.
You need:


The tensor to have requires_grad = True, which you have.


The tensor to be included as an optimizer parameter, which
you have.


To calculate the gradient of the loss function with respect to
the tensor.  This is done by the autograd system when you call
loss.backward(), which you’re not doing.


To use the gradient to perform the optimization by calling
optimizer.step() (which you are doing, but the gradient
isn’t there).


Best.
K. Frank