class Framework(nn.Module):
    def __init__(self):
        super(Framework, self).__init__()
        self.fc1 = nn.Linear(input_shape, 512)
        self.fc21 = nn.Linear(512, 128)
        self.fc22 = nn.Linear(512, 128)
        self.fc3 = nn.Linear(128, 512)
        self.fc4 = nn.Linear(512, input_shape)
        for m in self.modules():
            if isinstance(m, nn.Linear):
                torch.nn.init.xavier_uniform_(m.weight)
                torch.nn.init.zeros_(m.bias)

    def encoder(self, x):
        h1 = F.relu(self.fc1(x)+self.fc1.bias)
        return self.fc21(h1)+self.fc21.bias, F.elu(self.fc22(h1)+self.fc22.bias)+1
        

    def sampling(self, mu, var):
        eps= torch.nn.init.uniform_(var, a=0.0, b=1.0)
        return mu + eps*var

    def decoder(self, z):
        h3 = F.relu(self.fc3(z)+self.fc3.bias)
        #print(self.fc3.bias)
        return torch.sigmoid(self.fc4(h3)+self.fc4.bias)

    def forward(self, x):
        mu, var = self.encoder(x.view(-1, input_shape))
        z = self.sampling(mu, var)
        return self.decoder(z), mu, var

model1 = Framework().to(device)
model2 = Framework().to(device)
model3 = Framework().to(device)

import itertools
#deine optimizers
f_params=model1.parameters()
s_params=model2.parameters()
t_params=model3.parameters()
dvne_params=itertools.chain(f_params,s_params,t_params)
optimizer = optim.RMSprop(dvne_params, lr=learning_rate)