def make_gan_phase_2_seen(GAN_in, G_set, D_set, loss, opt, loss_weights):
    output_set = []
    ATTR_NUM = len(G_set)
    for i in range(ATTR_NUM):
        G_out = []
        for j in range(ATTR_NUM):
            if i != j:
                set_trainability(G_set[j], False)
            else:
                set_trainability(G_set[j], True)
            x = G_set[j](GAN_in[j])
            G_out.append(x)
        x = add(G_out)
        set_trainability(D_set[i], True)
        output_i = D_set[i](x)
        output_set.append(output_i)
    GAN = Model(GAN_in, output_set)
    GAN.compile(loss=loss, optimizer=opt, loss_weights=loss_weights)
    return GAN, output_set
def make_gan(inputs, G, D, G_trainable, D_trainable):
    set_trainability(G, G_trainable)
    set_trainability(D, D_trainable)
    x = G(inputs)
    output = D(x)
    return output
def build_model(ATTR_NUM, CLASS_NUM, feature_dim, hidden_dim, input_shape,
                lambda_mat):

    model_input, inputs, _, shared_dim = input_model(hidden_dim, input_shape)

    G_set_phase_1 = []
    D_set_phase_1 = []
    for i in range(ATTR_NUM):
        G, _ = get_generative(input_dim=shared_dim, out_dim=feature_dim)
        G_set_phase_1.append(G)
        D_set_sub = []
        for j in range(ATTR_NUM):
            if i == j:
                activation = 'softmax'
            else:
                activation = 'softmax'
            D, _ = get_discriminative(input_dim=feature_dim,
                                      out_dim=CLASS_NUM[j],
                                      activation=activation)
            D_set_sub.append(D)
        D_set_phase_1.append(D_set_sub)

    opt_gan = Adam(lr=0.0002, beta_1=0.5, beta_2=0.999)
    opt = Adam(lr=1e-3)

    loss_weights = [1.]
    loss_weights.extend([0.1 for _ in range(ATTR_NUM - 1)])

    set_trainability(model_input, True)

    feats = model_input(inputs)
    loss = [K.categorical_crossentropy for _ in range(ATTR_NUM)]
    GAN_phase_1_task, _ = make_gan_phase_1_task(inputs, feats, G_set_phase_1,
                                                D_set_phase_1, loss, opt,
                                                loss_weights)

    for i in range(ATTR_NUM):
        loss_weights = [1.]
        loss_weights.extend([0.1 for _ in range(ATTR_NUM - 1)])
        for j in range(ATTR_NUM):
            if i != j:
                loss_weights[j] = loss_weights[j] * lambda_mat[j, i]
        if i == 0:
            loss_w = loss_weights
        else:
            loss_w.extend(loss_weights)
    loss_weights = loss_w

    set_trainability(model_input, False)
    feats = model_input(inputs)
    GAN_phase_1_domain_pos, _ = make_gan_phase_1_domain_pos(
        inputs, feats, G_set_phase_1, D_set_phase_1, 'mse', opt_gan,
        loss_weights)
    set_trainability(model_input, True)
    feats = model_input(inputs)
    GAN_phase_1_domain_neg, _ = make_gan_phase_1_domain_neg(
        inputs, feats, G_set_phase_1, D_set_phase_1, 'mse', opt_gan,
        loss_weights)

    Model_gen_hidden_feature, _ = make_gan_phase_1_gen_hidden_feature(
        inputs, feats, G_set_phase_1)

    return GAN_phase_1_task, GAN_phase_1_domain_pos, GAN_phase_1_domain_neg, Model_gen_hidden_feature