Hey Thomas,
thank you for your answer.
in the following, I will post a snippet of my code.
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
dtype = torch.float32

X = torch.tensor([[1, 2, 3, 4, 5, 6]], dtype=dtype)
Y = torch.tensor([[1, 4, 9, 16, 25, 36]], dtype=dtype)


class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.base_l1 = torch.nn.Linear(6, 6, bias=True)
        self.base_l2 = torch.nn.Linear(6, 6, bias=True)
        self.l3 = torch.nn.Linear(6, 6, bias=True)
        self.l4 = torch.nn.Linear(6, 6, bias=True)

    def forward(self, x):
        x1 = self.base_l1(x)
        x1 = F.relu(x1)
        x1 = self.base_l2(x1)
        x2 = x1
        x2 = F.relu(x2)
        self.l3.weight.data = x1.repeat(6, 1)
        x2 = self.l3(x2)
        x2 = F.relu(x2)
        x2 = self.l4(x2)
        return x2, x1


model = Model()
my_list = ['base']
base_params = list(filter(lambda kv: my_list[0] in kv[0], model.named_parameters()))
params = list(filter(lambda kv: my_list[0] not in kv[0], model.named_parameters()))
prms = []
base_prms = []
for i in params:
    prms.append(i[1])
for i in base_params:
    base_prms.append(i[1])

optimizer1 = optim.SGD(base_prms, lr=.05, momentum=0.9)
optimizer2 = optim.SGD(prms, lr=.05, momentum=0.9)

Loss = nn.MSELoss()
l1 = []
l2 = []
n_iters = 100
for epoch in range(n_iters):
    print(epoch)
    optimizer1.zero_grad()
    optimizer2.zero_grad()
    y_pred2, y_pred1 = model(X)
    loss2 = Loss(y_pred2, Y)
    l2.append(loss2)
    loss2.backward()
    optimizer2.step()
    y_pred1.data = model.l3.weight[0, :].data.unsqueeze(0) # reinject the newly updated parameters to 
     #y_pred1
    loss1 = Loss(y_pred1, Y)
    l1.append(loss1)
    loss1.backward()
    optimizer1.step()

I want that my model final output x2 and the intermediate output x1 gets both optimized to the target Y
however,  X1 is penalized by how much l3.weights are far from Y which means I have to update the layer l3 with loss2.backward(retain_graph=True) first. then collect it new value and assign it to X1 and then execute loss1.backward()
can you see another way to achieve this without assigning True to retain_graph?
thank you