(self, label_index, unlabel_index, batch_size=5, qp_solver='ECOS', **kwargs)
Select indexes from the unlabel_index for querying.

        Parameters
        ----------
        label_index: {list, np.ndarray, IndexCollection}
            The indexes of labeled samples.

        unlabel_index: {list, np.ndarray, IndexCollection}
            The indexes of unlabeled samples.

        batch_size: int, optional (default=1)
            Selection batch size.

        qp_solver: str, optional (default='ECOS')
            The solver in cvxpy to solve QP, must be one of
            ['ECOS', 'OSQP']
            ECOS: https://www.embotech.com/ECOS
            OSQP: https://osqp.org/

        Returns
        -------
        selected_idx: list
            The selected indexes which is a subset of unlabel_index.
Select indexes from the unlabel_index for querying.
Select indexes from the unlabel_index for querying .
def select(self, label_index, unlabel_index, batch_size=5, qp_solver='ECOS', **kwargs):
        """Select indexes from the unlabel_index for querying.

        Parameters
        ----------
        label_index: {list, np.ndarray, IndexCollection}
            The indexes of labeled samples.

        unlabel_index: {list, np.ndarray, IndexCollection}
            The indexes of unlabeled samples.

        batch_size: int, optional (default=1)
            Selection batch size.

        qp_solver: str, optional (default='ECOS')
            The solver in cvxpy to solve QP, must be one of
            ['ECOS', 'OSQP']
            ECOS: https://www.embotech.com/ECOS
            OSQP: https://osqp.org/

        Returns
        -------
        selected_idx: list
            The selected indexes which is a subset of unlabel_index.
        """
        cvxpy = self._cvxpy
        assert (batch_size > 0)
        assert (isinstance(unlabel_index, collections.Iterable))
        assert (isinstance(label_index, collections.Iterable))
        unlabel_index = np.asarray(unlabel_index)
        label_index = np.asarray(label_index)
        if len(unlabel_index) <= batch_size:
            return unlabel_index

        KLL = self._K[np.ix_(label_index, label_index)]
        KLU = self._K[np.ix_(label_index, unlabel_index)]
        KUU = self._K[np.ix_(unlabel_index, unlabel_index)]

        L_len = len(label_index)
        U_len = len(unlabel_index)
        N = L_len + U_len

        # precision of ADMM
        MAX_ITER = 1000
        ABSTOL = 1e-4
        RELTOL = 1e-2

        # train a linear model in kernel form for
        tau = np.linalg.inv(KLL + self._gamma * np.eye(L_len)).dot(self.y[label_index])

        # start optimization
        last_round_selected = []
        iter_round = 0
        while 1:
            iter_round += 1
            # solve QP
            P = 0.5 * self._beta * KUU
            pred_of_unlab = tau.dot(KLU)
            a = pred_of_unlab * pred_of_unlab + 2 * np.abs(pred_of_unlab)
            q = self._beta * (
                    (U_len - batch_size) / N * np.ones(L_len).dot(KLU) - (L_len + batch_size) / N * np.ones(U_len).dot(
                KUU)) + a

            # cvx
            x = cvxpy.Variable(U_len)
            objective = cvxpy.Minimize(0.5 * cvxpy.quad_form(x, P) + q.T @ x)
            constraints = [0 <= x, x <= 1, sum(x) == batch_size]
            prob = cvxpy.Problem(objective, constraints)
            # The optimal objective value is returned by `prob.solve()`.
            # print(prob.is_qp())
            try:
                result = prob.solve(solver=cvxpy.OSQP if qp_solver == 'OSQP' else cvxpy.ECOS)
            except cvxpy.error.DCPError:
                # cvx
                x = cvxpy.Variable(U_len)
                objective = cvxpy.Minimize(0.5 * cvxpy.quad_form(x, P) + q.T @ x)
                constraints = [0 <= x, x <= 1]
                prob = cvxpy.Problem(objective, constraints)
                # The optimal objective value is returned by `prob.solve()`.
                try:
                    result = prob.solve(solver=cvxpy.OSQP if qp_solver == 'OSQP' else cvxpy.ECOS)
                except cvxpy.error.DCPError:
                    result = prob.solve(solver=cvxpy.OSQP if qp_solver == 'OSQP' else cvxpy.ECOS, gp=True)

            # Sometimes the constraints can not be satisfied,
            # thus we relax the constraints to get an approximate solution.
            if not (type(result) == float and result != float('inf') and result != float('-inf')):
                # cvx
                x = cvxpy.Variable(U_len)
                objective = cvxpy.Minimize(0.5 * cvxpy.quad_form(x, P) + q.T @ x)
                constraints = [0 <= x, x <= 1]
                prob = cvxpy.Problem(objective, constraints)
                # The optimal objective value is returned by `prob.solve()`.
                try:
                    result = prob.solve(solver=cvxpy.OSQP if qp_solver == 'OSQP' else cvxpy.ECOS)
                except cvxpy.error.DCPError:
                    result = prob.solve(solver=cvxpy.OSQP if qp_solver == 'OSQP' else cvxpy.ECOS, gp=True)

            # The optimal value for x is stored in `x.value`.
            # print(x.value)
            dr_weight = np.array(x.value)
            if len(np.shape(dr_weight)) == 2:
                dr_weight = dr_weight.T[0]
            # end cvx

            # record selected indexes and judge convergence
            dr_largest = nlargestarg(dr_weight, batch_size)
            select_ind = np.asarray(unlabel_index)[dr_largest]
            if set(last_round_selected) == set(select_ind) or iter_round > 15:
                return select_ind
            else:
                last_round_selected = copy.copy(select_ind)
            # print(dr_weight[dr_largest])

            # ADMM optimization process
            delta = np.zeros(batch_size)  # dual variable in ADMM
            KLQ = self._K[np.ix_(label_index, select_ind)]
            z = tau.dot(KLQ)

            for solver_iter in range(MAX_ITER):
                # tau update
                A = KLL.dot(KLL) + self._rho / 2 * KLQ.dot(KLQ.T) + self._gamma * KLL
                r = self.y[label_index].dot(KLL) + 0.5 * delta.dot(KLQ.T) + self._rho / 2 * z.dot(KLQ.T)
                tau = np.linalg.pinv(A).dot(r)

                # z update
                zold = z
                v = (self._rho * tau.dot(KLQ) - delta) / (self._rho + 2)
                ita = 2 / (self._rho + 2)
                z_sign = np.sign(v)
                z_sign[z_sign == 0] = 1
                ztp = (np.abs(v) - ita * np.ones(len(v)))
                ztp[ztp < 0] = 0
                z = z_sign * ztp

                # delta update
                delta += self._rho * (z - tau.dot(KLQ))

                # judge convergence
                r_norm = np.linalg.norm((tau.dot(KLQ) - z))
                s_norm = np.linalg.norm(-self._rho * (z - zold))
                eps_pri = np.sqrt(batch_size) * ABSTOL + RELTOL * max(np.linalg.norm(z), np.linalg.norm(tau.dot(KLQ)))
                eps_dual = np.sqrt(batch_size) * ABSTOL + RELTOL * np.linalg.norm(delta)
                if r_norm < eps_pri and s_norm < eps_dual:
                    break
def select ( self , label_index , unlabel_index , batch_size = 5 , qp_solver = 'ECOS' , * * kwargs ) : cvxpy = self . _cvxpy assert ( batch_size > 0 ) assert ( isinstance ( unlabel_index , collections . Iterable ) ) assert ( isinstance ( label_index , collections . Iterable ) ) unlabel_index = np . asarray ( unlabel_index ) label_index = np . asarray ( label_index ) if len ( unlabel_index ) <= batch_size : return unlabel_index KLL = self . _K [ np . ix_ ( label_index , label_index ) ] KLU = self . _K [ np . ix_ ( label_index , unlabel_index ) ] KUU = self . _K [ np . ix_ ( unlabel_index , unlabel_index ) ] L_len = len ( label_index ) U_len = len ( unlabel_index ) N = L_len + U_len # precision of ADMM MAX_ITER = 1000 ABSTOL = 1e-4 RELTOL = 1e-2 # train a linear model in kernel form for tau = np . linalg . inv ( KLL + self . _gamma * np . eye ( L_len ) ) . dot ( self . y [ label_index ] ) # start optimization last_round_selected = [ ] iter_round = 0 while 1 : iter_round += 1 # solve QP P = 0.5 * self . _beta * KUU pred_of_unlab = tau . dot ( KLU ) a = pred_of_unlab * pred_of_unlab + 2 * np . abs ( pred_of_unlab ) q = self . _beta * ( ( U_len - batch_size ) / N * np . ones ( L_len ) . dot ( KLU ) - ( L_len + batch_size ) / N * np . ones ( U_len ) . dot ( KUU ) ) + a # cvx x = cvxpy . Variable ( U_len ) objective = cvxpy . Minimize ( 0.5 * cvxpy . quad_form ( x , P ) + q . T @ x ) constraints = [ 0 <= x , x <= 1 , sum ( x ) == batch_size ] prob = cvxpy . Problem ( objective , constraints ) # The optimal objective value is returned by `prob.solve()`. # print(prob.is_qp()) try : result = prob . solve ( solver = cvxpy . OSQP if qp_solver == 'OSQP' else cvxpy . ECOS ) except cvxpy . error . DCPError : # cvx x = cvxpy . Variable ( U_len ) objective = cvxpy . Minimize ( 0.5 * cvxpy . quad_form ( x , P ) + q . T @ x ) constraints = [ 0 <= x , x <= 1 ] prob = cvxpy . Problem ( objective , constraints ) # The optimal objective value is returned by `prob.solve()`. try : result = prob . solve ( solver = cvxpy . OSQP if qp_solver == 'OSQP' else cvxpy . ECOS ) except cvxpy . error . DCPError : result = prob . solve ( solver = cvxpy . OSQP if qp_solver == 'OSQP' else cvxpy . ECOS , gp = True ) # Sometimes the constraints can not be satisfied, # thus we relax the constraints to get an approximate solution. if not ( type ( result ) == float and result != float ( 'inf' ) and result != float ( '-inf' ) ) : # cvx x = cvxpy . Variable ( U_len ) objective = cvxpy . Minimize ( 0.5 * cvxpy . quad_form ( x , P ) + q . T @ x ) constraints = [ 0 <= x , x <= 1 ] prob = cvxpy . Problem ( objective , constraints ) # The optimal objective value is returned by `prob.solve()`. try : result = prob . solve ( solver = cvxpy . OSQP if qp_solver == 'OSQP' else cvxpy . ECOS ) except cvxpy . error . DCPError : result = prob . solve ( solver = cvxpy . OSQP if qp_solver == 'OSQP' else cvxpy . ECOS , gp = True ) # The optimal value for x is stored in `x.value`. # print(x.value) dr_weight = np . array ( x . value ) if len ( np . shape ( dr_weight ) ) == 2 : dr_weight = dr_weight . T [ 0 ] # end cvx # record selected indexes and judge convergence dr_largest = nlargestarg ( dr_weight , batch_size ) select_ind = np . asarray ( unlabel_index ) [ dr_largest ] if set ( last_round_selected ) == set ( select_ind ) or iter_round > 15 : return select_ind else : last_round_selected = copy . copy ( select_ind ) # print(dr_weight[dr_largest]) # ADMM optimization process delta = np . zeros ( batch_size ) # dual variable in ADMM KLQ = self . _K [ np . ix_ ( label_index , select_ind ) ] z = tau . dot ( KLQ ) for solver_iter in range ( MAX_ITER ) : # tau update A = KLL . dot ( KLL ) + self . _rho / 2 * KLQ . dot ( KLQ . T ) + self . _gamma * KLL r = self . y [ label_index ] . dot ( KLL ) + 0.5 * delta . dot ( KLQ . T ) + self . _rho / 2 * z . dot ( KLQ . T ) tau = np . linalg . pinv ( A ) . dot ( r ) # z update zold = z v = ( self . _rho * tau . dot ( KLQ ) - delta ) / ( self . _rho + 2 ) ita = 2 / ( self . _rho + 2 ) z_sign = np . sign ( v ) z_sign [ z_sign == 0 ] = 1 ztp = ( np . abs ( v ) - ita * np . ones ( len ( v ) ) ) ztp [ ztp < 0 ] = 0 z = z_sign * ztp # delta update delta += self . _rho * ( z - tau . dot ( KLQ ) ) # judge convergence r_norm = np . linalg . norm ( ( tau . dot ( KLQ ) - z ) ) s_norm = np . linalg . norm ( - self . _rho * ( z - zold ) ) eps_pri = np . sqrt ( batch_size ) * ABSTOL + RELTOL * max ( np . linalg . norm ( z ) , np . linalg . norm ( tau . dot ( KLQ ) ) ) eps_dual = np . sqrt ( batch_size ) * ABSTOL + RELTOL * np . linalg . norm ( delta ) if r_norm < eps_pri and s_norm < eps_dual : break