def __init__(self, trainset, opts=None):

        super(Factorizable_network, self).__init__(trainset, opts)
        self.mps_list = nn.ModuleList(
            [factor_updating_structure(opts) for i in range(self.MPS_iter)])
        # self.mps_list.apply(network.weight_init_fun_kaiming)
        network.weights_normal_init(self.mps_list, 0.01)
    def __init__(self, trainset, opts=None):

        super(Factorizable_network, self).__init__()
        # network settings
        self.n_classes_obj = trainset.num_object_classes
        self.n_classes_pred = trainset.num_predicate_classes
        self.MPS_iter = opts['MPS_iter']
        # loss weight
        ce_weights_obj = np.sqrt(trainset.inverse_weight_object)
        ce_weights_obj[0] = 1.
        ce_weights_pred = np.sqrt(trainset.inverse_weight_predicate)
        ce_weights_pred[0] = 1.
        self.object_loss_weight = ce_weights_obj if opts.get(
            'use_loss_weight', False) else None
        self.predicate_loss_weight = ce_weights_pred if opts.get(
            'use_loss_weight', False) else None
        self.opts = opts

        # loss
        self.loss_cls_obj = None
        self.loss_cls_rel = None
        self.loss_reg_obj = None

        with open(opts['rpn_opts'], 'r') as f:
            self.rpn_opts = yaml.load(f)
            assert len(trainset.opts['test']['SCALES']
                       ) == 1, "Currently only support single testing scale."
            self.rpn_opts['scale'] = trainset.opts['test']['SCALES'][0]

        self.rpn = RPN(self.rpn_opts)
        pool_size = self.opts.get('pool_size', 7)
        self.roi_pool_object = ROIAlign((pool_size, pool_size), 1.0 / 16, 0)
        self.roi_pool_region = ROIAlign((pool_size, pool_size), 1.0 / 16, 0)
        self.fc_obj = nn.Sequential(
            nn.Linear(512 * pool_size * pool_size, opts['dim_ho']),
            GroupDropout(p=opts['dropout'], inplace=True),
            nn.ReLU(inplace=True),
            nn.Linear(opts['dim_ho'], opts['dim_ho']),
            GroupDropout(p=opts['dropout'], inplace=True),
        )

        self.fc_region = nn.Sequential(
            nn.Conv2d(512, opts['dim_hr'], 3, stride=1, padding=1),
            GroupDropout(p=opts['dropout'], inplace=True),
            nn.ReLU(inplace=True),
            nn.Conv2d(opts['dim_hr'], opts['dim_hr'], 3, stride=1, padding=1),
            GroupDropout(p=opts['dropout'], inplace=True),
        )

        self.fc_obj.apply(network.weight_init_fun_kaiming)
        self.fc_region.apply(network.weight_init_fun_kaiming)
        # network.weights_normal_init(self.fc_obj, 0.01)
        # network.weights_normal_init(self.fc_region, 0.01)

        # the hierarchical message passing structure
        print('{} MPS modules are used.'.format(self.MPS_iter))
        self.mps_list = nn.ModuleList(
            [factor_updating_structure(opts) for i in range(self.MPS_iter)])
        # self.mps_list.apply(network.weight_init_fun_kaiming)
        network.weights_normal_init(self.mps_list, 0.01)

        self.phrase_inference = getattr(fusion_inference,
                                        self.opts['fusion'])(opts)
        # self.phrase_inference.apply(network.weight_init_fun_kaiming)
        network.weights_normal_init(self.phrase_inference, 0.01)

        self.score_obj = nn.Linear(opts['dim_ho'], self.n_classes_obj)
        self.bbox_obj = nn.Linear(opts['dim_ho'], self.n_classes_obj * 4)
        self.score_pred = nn.Linear(opts['dim_hp'], self.n_classes_pred)
        self.learnable_nms = self.opts.get('nms', 1.) > 0
        self.nms = Dumplicate_Removal(opts)

        network.weights_normal_init(self.score_obj, 0.01)
        network.weights_normal_init(self.bbox_obj, 0.005)
        network.weights_normal_init(self.score_pred, 0.01)

        self.engines = engines