示例#1
0
def multi_hg_weighting_trans_infer(hg_list, y, lbd, mu, max_iter, log=True):
    """ multi-hypergraph weighting from the "3-D Object Retrieval and
    Recognition With Hypergraph Analysis"
    :param hg_list: list, list of HyperG instance
    :param y: numpy array, shape = (n_nodes,)
    :param lbd: float, the positive tradeoff parameter of empirical loss
    :param mu: float, the positive tradeoff parameter of the l2 norm on hypergraph weights
    :param max_iter: int, maximum iteration times of alternative optimization.
    :param log: bool
    :return: numpy array, shape = (n_test, ), predicted labels of test instances
    """
    assert max_iter > 0

    loss = []
    prev_F = None
    Y = init_label_matrix(y)
    n_hg = len(hg_list)
    n_nodes = len(y)
    omega = np.zeros(n_hg)
    hg_weights = np.ones(n_hg)/n_hg

    for i_iter in range(max_iter):
        print_log("hypergraph weights: {}".format(str(hg_weights)))

        # update F
        THETA = None
        for idx in range(len(hg_list)):
            if THETA is None:
                THETA = hg_weights[idx] * hg_list[idx].theta_matrix()
            else:
                THETA += hg_weights[idx] * hg_list[idx].theta_matrix()

        L2 = sparse.eye(n_nodes) - (1 / (1 + lbd)) * THETA
        F = ((lbd + 1) / lbd) * inv(L2.toarray()).dot(Y)

        # update hg_weight
        for idx in range(n_hg):
            omega[idx] = np.trace(F.T.dot(np.eye(n_nodes) + hg_list[idx].theta_matrix()).dot(F)) # TODO
        for idx in range(n_hg):
            hg_weights[idx] = 1. / n_hg + np.sum(omega) / (2 * mu * n_hg) - omega[idx] / (2 * mu)

        # loss
        i_loss = np.sum(omega * hg_weights) + lbd * np.linalg.norm(F - Y)
        loss.append(i_loss)

        if log:
            print_log("Iter: {}; loss:{:.5f}".format(i_iter, i_loss))

        if i_iter > 0 and (i_loss - loss[-2]) > 0.:
            print_log("Iteration stops after {} round.".format(i_iter))
            F = prev_F
            break
        prev_F = F

    predict_y = F.argmax(axis=1).reshape(-1)[y == -1]
    return predict_y
def main():
    print_log("loading data")
    X_train, X_test, y_train, y_test = load_modelnet(selected_mod=(0, 1))

    X = [np.vstack((X_train[imod], X_test[imod])) for imod in range(len(X_train))]
    y = np.concatenate((y_train, -1 * np.ones_like(y_test)))

    print_log("generating hypergraph")
    hg_list = [
        gen_knn_hg(X[imod], n_neighbors=10)
        for imod in range(len(X_train))
    ]

    print_log("learning on hypergraph")
    y_predict = multi_hg_trans_infer(hg_list, y, lbd=100)

    print_log("accuracy: {}".format(accuracy_score(y_test, y_predict)))
def main():
    print_log("loading data")
    X_train, X_test, y_train, y_test = load_myocardium([3])
    X = np.concatenate([X_train, X_test], axis=0)
    y = np.concatenate(
        [y_train.reshape(-1), -1 * np.ones_like(y_test).reshape(-1)])

    print_log("generating hypergraph")
    # grid hg
    grid_hg_s = [gen_grid_neigh_hg(X[i].shape) for i in range(X.shape[0])]
    grid_hg = fuse_mutli_sub_hg(grid_hg_s)
    # knn hg
    X_patch_ft = np.stack([
        gather_patch_ft(X[i][:, :, np.newaxis], (5, 5))
        for i in range(X.shape[0])
    ])
    knn_hg = gen_knn_hg(X_patch_ft.reshape(-1, X_patch_ft.shape[-1]),
                        n_neighbors=7)
    # concatfeat hg
    concat_hg = concat_multi_hg([grid_hg, knn_hg])

    print_log("learning on hypergraph")
    y_predict = trans_infer(concat_hg, y, 100)
    print_log("iou: {}".format(iou_socre(y_predict, y_test.reshape(-1))))

    print_log("postprocessing")
    y_postpro = postprocess(y_predict.reshape(y_test.shape))
    print_log("iou(postprocess): {}".format(
        iou_socre(y_postpro.reshape(-1), y_test.reshape(-1))))

    # visualize
    print_log("visualizing")
    fig = plt.figure()
    ax1 = fig.add_subplot(2, 2, 1)
    ax1.imshow(X_test.squeeze())
    ax1.title.set_text('X_test')
    ax1.axis('off')

    ax2 = fig.add_subplot(2, 2, 2)
    ax2.imshow(y_test.squeeze())
    ax2.title.set_text('y_test')
    ax2.axis('off')

    ax3 = fig.add_subplot(2, 2, 3)
    ax3.imshow(y_predict.reshape(y_test.squeeze().shape))
    ax3.title.set_text('y_predict')
    ax3.axis('off')

    ax4 = fig.add_subplot(2, 2, 4)
    ax4.imshow(y_postpro.reshape(y_test.squeeze().shape))
    ax4.title.set_text('y_postpro')
    ax4.axis('off')

    plt.show()
示例#4
0
def hyedge_weighting_trans_infer(hg, y, lbd, mu, max_iter=15, log=True):
    """ hyperedge weighting from the "Visual-Textual Joint Relevance
    Learning for Tag-Based Social Image Search" paper

    :param hg: instance of HyperG
    :param y: numpy array, shape = (n_nodes,)
    :param lbd: float, the positive tradeoff parameter of empirical loss
    :param mu: float, the positive tradeoff parameter of hyperedge weights
    :param max_iter: int, maximum iteration times of alternative optimization
    :param log: bool
    :return: numpy array, shape = (n_test, ), predicted labels of test instances
    """
    assert max_iter > 0

    loss = []
    prev_F = None
    Y = init_label_matrix(y)

    for i_iter in range(max_iter):

        # update F
        if i_iter > 0:
            prev_F = F
        F = _transductive_one_step(hg, Y, lbd)

        # update w
        n_edges = hg.num_edges()
        H = hg.incident_matrix()
        DV = hg.node_degrees()
        DV2 = hg.inv_square_node_degrees()
        invde = hg.inv_edge_degrees().data.reshape(-1)
        dv = DV.data.reshape(-1)

        Tau = DV2.dot(H).toarray()
        C = np.zeros((n_edges, 1))
        for i in range(n_edges):
            C[i, 0] = -invde[i] * np.trace(
                np.sum(np.power(F.T.dot(Tau[:, i].reshape(-1, 1)), 2.), axis=0, keepdims=True)
            )
        # update w --- optimization
        Dense_H = H.toarray()
        w = cp.Variable(n_edges, nonneg=True)
        objective = cp.Minimize((1 / 2) * cp.quad_form(w, 2 * mu * np.eye(n_edges)) + C.T @ w)
        constraints = [Dense_H @ w == dv, w >= np.zeros(n_edges)]
        prob = cp.Problem(objective, constraints)
        prob.solve()

        hg.update_hyedge_weights(w.value)

        # loss
        hg_reg_loss = np.trace(F.T.dot(hg.laplacian().dot(F)))
        emp_loss = np.linalg.norm(F - Y)
        w_loss = np.sum(np.power(w.value, 2.))
        i_loss = hg_reg_loss + lbd * emp_loss + w_loss
        loss.append(i_loss)

        # log
        if log:
            print_log("Iter: {}; loss:{:.5f}".format(i_iter, i_loss))

        if i_iter > 0 and (i_loss - loss[-2]) > 0.:
            print_log("Iteration stops after {} round.".format(i_iter))
            F = prev_F
            break

    predict_y = F.argmax(axis=1).reshape(-1)[y == -1]
    return predict_y
示例#5
0
def tensor_hg_trans_infer(X, y, lbd, alpha, mu, stepsize, max_iter=50, hsl_iter=10, log=True, stop=True):
    """ tensor-based (dynamic) hypergraph learning
    :param X: numpy array, shape = (n_nodes, n_features)
    :param y: numpy array, shape = (n_nodes,) -1 for the unlabeled data, 0,1,2.. for the labeled data
    :param lbd: float, the positive tradeoff parameter of empirical loss
    :param alpha: float,
    :param mu: float,
    :param stepsize: float
    :param max_iter: int, maximum iteration times of alternative optimization
    :param hsl_iter: int, the number of iterations in the process of updating hypergraph tensor
    :param log: bool
    :param stop: boolean,
    :return: numpy array, shape = (n_test, ), predicted labels of test instances
    """
    if log:
        print_log("parameters: lambda:{}\talpha:{}\tmu:{}\tstepsize:{}".format(lbd, alpha, mu, stepsize))

    n_nodes = X.shape[0]

    # init Y
    Y = init_label_matrix(y)

    ceil_logn = np.ceil(np.log(n_nodes)).astype('int')

    # init tensor hypergraph
    T = np.ones((1, n_nodes * ceil_logn))

    mED = pairwise_distances(X)

    neighbors = np.asarray(np.argsort(mED, axis=1, kind='stable'))
    neighbors = neighbors[:, 1:(ceil_logn + 1)]

    # calculate S
    S = np.zeros((n_nodes, n_nodes))
    delta_omega = np.arange(2, ceil_logn + 2)
    delta_omega = np.tile(delta_omega, (n_nodes, 1))
    delta_omega = delta_omega.reshape((1, -1), order='F')

    t_iter = 0
    for i in range(ceil_logn):
        for j in range(n_nodes):
            if T[0, t_iter] == 0:
                continue

            clique = [j] + neighbors[j, 0:i + 1].tolist()
            indexs = np.array(list(combinations(clique, 2)))
            S[indexs[:, 0], indexs[:, 1]] = S[indexs[:, 0], indexs[:, 1]] + T[0, t_iter] / delta_omega[0, t_iter]

            t_iter = t_iter + 1

    S = S + S.T
    c = 1 / (1 + alpha)

    F = np.linalg.inv(np.eye(n_nodes) + (2 * c / lbd) * (np.diag(np.sum(S, axis=0)) - S)) @ Y

    T0 = T
    fH_value = []

    loss = []
    prev_F = None

    for i_iter in range(max_iter):
        FED = pairwise_distances(F)
        f = np.zeros((1, T.shape[1]))
        f_iter = 0
        for i in range(ceil_logn):
            for j in range(n_nodes):
                clique = [j] + neighbors[j, 0:i + 1].tolist()
                indexs = np.array(list(combinations(clique, 2)))
                tmp1 = np.sum(FED[indexs[:, 0], indexs[:, 1]], axis=0)
                tmp2 = np.sum(mED[indexs[:, 0], indexs[:, 1]], axis=0)
                f[0, f_iter] = (tmp1 + alpha * tmp2) / ((1 + alpha) * delta_omega[0, f_iter])
                f_iter = f_iter + 1

        for iter2 in range(hsl_iter):
            dfT = f + 2 * mu * (T - T0)
            T = T - stepsize * dfT
            T[T < 0] = 0
            T[T > 1] = 1

        fH_value.append(
            (f @ T.T).reshape(-1)[0] + lbd * np.power(np.linalg.norm(F - Y, ord='fro'), 2.) + mu * np.power(
                np.linalg.norm(T - T0, ord='fro'), 2))

        S = np.zeros((n_nodes, n_nodes))
        t_iter = 0
        for i in range(ceil_logn):
            for j in range(n_nodes):
                if T[0, t_iter] != 0:
                    clique = [j] + neighbors[j, 0:i + 1].tolist()
                    indexs = np.array(list(combinations(clique, 2)))
                    S[indexs[:, 0], indexs[:, 1]] = S[indexs[:, 0], indexs[:, 1]] + T[0, t_iter] / delta_omega[0, t_iter]

                t_iter = t_iter + 1
        S = S + S.T
        c = 1 / (1 + alpha)
        F = np.linalg.inv(np.eye(n_nodes) + (2 * c / lbd) * (np.diag(np.sum(S, 0)) - S)) @ Y

        fh = (f @ T.T).reshape(-1)[0] + lbd * np.power(np.linalg.norm(F - Y, ord='fro'), 2.) + mu * np.power(
            np.linalg.norm(T - T0, ord='fro'), 2)
        if log:
            loss.append(fh)
            print_log("Iter: {}; loss:{:.5f}".format(i_iter, fh))

        fH_value.append(fh)

        if stop:
            if len(loss) >= 2 and loss[-1] > loss[-2]:
                print_log("Stop at iteration :{}".format(i_iter))
                F = prev_F
                break
            prev_F = F

    predict_y = np.argmax(F, axis=1).reshape(-1)[y == -1]
    return predict_y
示例#6
0
def dyna_hg_trans_infer(hg, y, lbd, stepsize, beta, max_iter, hsl_iter, log=True):
    """dynamic hypergraph structure learning from the "Dynamic Hypergraph
    Structure Learning" paper.
    :param hg: instance of HyperG
    :param y: numpy array, shape = (n_nodes,)
    :param lbd: float, the positive tradeoff parameter of empirical loss
    :param stepsize: float
    :param beta: float, the positive tradeoff parameter of regularizer on H in the feature space loss
    :param max_iter: int, maximum iteration times of alternative optimization.
    :param hsl_iter: int, the number of iterations in the process of updating hypergraph incident matrix
    :param log: bool
    :return: numpy array, shape = (n_test, ), predicted labels of test instances
    """
    if log:
        print_log("alpha:{}\tbeta:{}".format(stepsize, beta))

    n_nodes = hg.num_nodes()

    Y = init_label_matrix(y)

    a = np.ones(n_nodes)
    a[y != -1] = 1e-4
    A = sparse.diags(a)
    X = hg.node_features()

    assert X is not None, "hg instance should be constructed with the parameter of 'with_feature=True'"

    F = _dhsl_update_f(hg, Y, A, lbd)

    for i_iter in range(max_iter):
        # update H
        C = (1 - beta) * F.dot(F.T) + beta * X.dot(X.T)

        for i_hsl in range(hsl_iter):
            # sparse
            DV2 = hg.inv_square_node_degrees()
            INVDE = hg.inv_edge_degrees()
            W = sparse.diags(hg.hyperedge_weights())

            # dense
            H = hg.incident_matrix()
            WDHD = W.dot(INVDE).dot(H.T).dot(DV2).todense()
            H = H.todense()
            DCD = sparse.dia_matrix.dot(DV2.dot(C), DV2)

            term3 = 2 * sparse.coo_matrix.dot(DCD.dot(H), W.dot(INVDE))
            tmp = np.diag(H.T.dot(DCD).dot(H)).reshape(1, -1)
            term2 = - np.tile(sparse.csr_matrix.dot(tmp, W.dot(INVDE).dot(INVDE)), (n_nodes, 1))
            term1 = - DV2.dot(DV2).dot(DV2).dot(np.diag(H.dot(WDHD).dot(C)).reshape(-1, 1)).dot(
                hg.hyperedge_weights().reshape(1, -1)
            )

            dfH = term1 + term2 + term3
            H = H + stepsize * dfH
            H[H < 0] = 0
            H[H > 1] = 1
            H = sparse.coo_matrix(H)
            hg.update_incident_matrix(H)

        # update F
        F = _dhsl_update_f(hg, Y, A, lbd)

        if log:
            print_log("Iter: {}".format(i_iter))

    predict_y = F.argmax(axis=1).reshape(-1)[y == -1]
    return predict_y
示例#7
0
def inductive_fit(hg, y, lbd, mu, eta, max_iter, log=True):
    """ inductive multi-hypergraph learning from the "Inductive
    Multi-Hypergraph Learning and Its Application on View-Based
    3D Object Classification"
    (you should call the inductive_fit first and then
    call the inductive_predict to predict unlabeled instances)
    :param hg: instance of HyperG or list
    :param y: numpy array, shape = (n_nodes,)
    :param lbd: float, the positive tradeoff parameter of empirical loss.
    :param mu: float, the positive tradeoff parameter of the regularizer on projection matrix.
    :param eta: float, the positive tradeoff parameter of the l2 norm on hypergraph weights
    :param max_iter: int, maximum iteration times of alternative optimization.
    :param log: bool
    :return: instance of IMHL
    """
    assert isinstance(hg, (HyperG, list))
    assert isinstance(y, (np.ndarray, list))

    if isinstance(hg, HyperG):
        hg_list = [hg]
    else:
        hg_list = hg

    n_hg = len(hg_list)

    Y = init_label_matrix(y)

    M = [None for _ in range(n_hg)]
    omega = np.zeros(n_hg)
    loss = np.zeros(n_hg)

    for hg_idx in range(n_hg):
        if log:
            print_log("processing I_HG :{}".format(hg_idx))

        X = hg_list[hg_idx].node_features()
        L = hg_list[hg_idx].laplacian()

        _, n_features = X.shape
        INVU = np.eye(n_features)

        for i_iter in range(max_iter):
            # fix U, update M
            A = sparse.csr_matrix.dot(X.T, L).dot(X) + lbd * X.T.dot(X)
            TMP = np.linalg.inv(A.dot(INVU) + mu * np.eye(n_features))
            M[hg_idx] = lbd * INVU.dot(TMP).dot(X.T).dot(Y)

            # fix M, update U
            invu = np.sqrt(np.sum(np.power(M[hg_idx], 2.), axis=1)).reshape(-1)
            INVU = 2 * np.diag(invu)

        g_reg_term = np.trace(M[hg_idx].T.dot(X.T).dot(
            L.dot(X).dot(M[hg_idx])))
        emp_loss_term = np.power(np.linalg.norm(X.dot(M[hg_idx]) - Y), 2)
        m_reg_term = np.sum(
            [np.linalg.norm(M[hg_idx][i, :]) for i in range(n_features)])
        i_loss = g_reg_term + lbd * emp_loss_term + mu * m_reg_term

        if log:
            print_log("I_HG: {}; loss:{:.5f}".format(hg_idx, i_loss))

        loss[hg_idx] = i_loss

    for hg_idx in range(n_hg):
        omega[hg_idx] = 1. / n_hg + np.sum(loss) / (
            2 * n_hg * eta) - loss[hg_idx] / (2 * eta)

    if log:
        print("hypergraph weights:{}".format(omega))

    return IMHL(M, omega)
示例#8
0
def gen_l1_hg(X, gamma, n_neighbors, log=False, with_feature=False):
    """
    :param X: numpy array, shape = (n_samples, n_features)
    :param gamma: float, the tradeoff parameter of the l1 norm on representation coefficients
    :param n_neighbors: int,
    :param log: bool
    :param with_feature: bool, optional(default=False)
    :return: instance of HyperG
    """

    assert n_neighbors >= 1.
    assert isinstance(X, np.ndarray)
    assert X.ndim == 2

    n_nodes = X.shape[0]
    n_edges = n_nodes

    m_dist = pairwise_distances(X)
    m_neighbors = np.argsort(m_dist)[:, 0:n_neighbors + 1]

    edge_idx = np.tile(
        np.arange(n_edges).reshape(-1, 1), (1, n_neighbors + 1)).reshape(-1)
    node_idx = []
    values = []

    for i_edge in range(n_edges):
        if log:
            print_log("processing edge {} ".format(i_edge))

        neighbors = m_neighbors[i_edge].tolist()
        if i_edge in neighbors:
            neighbors.remove(i_edge)
        else:
            neighbors = neighbors[:-1]

        P = X[neighbors, :]
        v = X[i_edge, :]

        # cvxpy
        x = cp.Variable(P.shape[0], nonneg=True)
        objective = cp.Minimize(
            cp.norm((P.T @ x).T - v, 2) + gamma * cp.norm(x, 1))
        # objective = cp.Minimize(cp.norm(x@P-v, 2) + gamma * cp.norm(x, 1))
        prob = cp.Problem(objective)
        try:
            prob.solve()
        except SolverError:
            prob.solve(solver='SCS', verbose=False)

        node_idx.extend([i_edge] + neighbors)
        values.extend([1.] + x.value.tolist())

    node_idx = np.array(node_idx)
    values = np.array(values)

    H = sparse.coo_matrix((values, (node_idx, edge_idx)),
                          shape=(n_nodes, n_edges))

    if with_feature:
        return HyperG(H, X=X)

    return HyperG(H)