Exemple #1
0
    def backward(ctx, grad_indexC, grad_valueC):
        m, k = ctx.m, ctx.k
        n = ctx.n
        indexA, valueA, indexB, valueB, indexC = ctx.saved_tensors

        grad_valueA = grad_valueB = None

        if not grad_valueC.is_cuda:
            if ctx.needs_input_grad[1] or ctx.needs_input_grad[1]:
                grad_valueC = grad_valueC.clone()

            if ctx.needs_input_grad[1]:
                grad_valueA = torch_sparse.spspmm_cpu.spspmm_bw(
                    indexA, indexC.detach(), grad_valueC, indexB.detach(),
                    valueB, m, k)

            if ctx.needs_input_grad[3]:
                indexA, valueA = transpose(indexA, valueA, m, k)
                indexC, grad_valueC = transpose(indexC, grad_valueC, m, n)
                grad_valueB = torch_sparse.spspmm_cpu.spspmm_bw(
                    indexB, indexA.detach(), valueA, indexC.detach(),
                    grad_valueC, k, n)
        else:
            if ctx.needs_input_grad[1]:
                grad_valueA = torch_sparse.spspmm_cuda.spspmm_bw(
                    indexA, indexC.detach(), grad_valueC.clone(),
                    indexB.detach(), valueB, m, k)

            if ctx.needs_input_grad[3]:
                indexA_T, valueA_T = transpose(indexA, valueA, m, k)
                grad_indexB, grad_valueB = mm(indexA_T, valueA_T, indexC,
                                              grad_valueC, k, m, n)
                grad_valueB = lift(grad_indexB, grad_valueB, indexB, n)

        return None, grad_valueA, None, grad_valueB, None, None, None
Exemple #2
0
def is_undirected(edge_index, edge_attr=None, num_nodes=None):
    r"""Returns :obj:`True` if the graph given by :attr:`edge_index` is
    undirected.

    Args:
        edge_index (LongTensor): The edge indices.
        edge_attr (Tensor, optional): Edge weights or multi-dimensional
            edge features. (default: :obj:`None`)
        num_nodes (int, optional): The number of nodes, *i.e.*
            :obj:`max_val + 1` of :attr:`edge_index`. (default: :obj:`None`)

    :rtype: bool
    """
    num_nodes = maybe_num_nodes(edge_index, num_nodes)
    edge_index, edge_attr = coalesce(edge_index, edge_attr, num_nodes,
                                     num_nodes)

    if edge_attr is None:
        undirected_edge_index = to_undirected(edge_index, num_nodes=num_nodes)
        return edge_index.size(1) == undirected_edge_index.size(1)
    else:
        edge_index_t, edge_attr_t = transpose(edge_index,
                                              edge_attr,
                                              num_nodes,
                                              num_nodes,
                                              coalesced=True)
        index_symmetric = torch.all(edge_index == edge_index_t)
        attr_symmetric = torch.all(edge_attr == edge_attr_t)
        return index_symmetric and attr_symmetric
Exemple #3
0
    def loop_sparse_attention_centrality(self, attention, idx):
        # O(N) implementation

        batch, groups, npoints, neighbors = attention.size()
        idx_tag = torch.tensor([[i] * neighbors for i in range(npoints)],
                               device='cuda').flatten().unsqueeze(0)
        mtrx = torch.tensor([[1.] * npoints], device='cuda').T

        score = []

        for i in range(batch):
            idx_flatten = idx[i].flatten().unsqueeze(0)  # NK
            index = torch.cat([idx_tag, idx_flatten], dim=0)
            score_group = []
            for j in range(groups):
                attention_flatten = attention[i][j].flatten()
                index_s, value_s = coalesce(index, attention_flatten, npoints,
                                            npoints)
                index_t, value_t = transpose(index_s, value_s, npoints,
                                             npoints)
                out = spmm(index_t, value_t, npoints, npoints, mtrx)
                score_group.append(out)
                if j == groups - 1:
                    score.append(torch.cat(score_group, dim=1).unsqueeze(0))
            if i == batch - 1:
                final_score = torch.cat(score, dim=0)

        # fullnl instance

        final_score = final_score.unsqueeze(3).permute(0, 2, 3, 1)
        idx_value, idx_score = final_score.topk(
            k=neighbors, dim=3)  # B, G, 1, N -> B, G, 1, K'
        return idx_value, idx_score
Exemple #4
0
    def prepare_groups(self, features, mask):
        #tensor_mask = torch.from_numpy(mask)
        #self.groups = torch.clamp(self.groups[tensor_mask, :], 0, 1).transpose_(1, 0)
        #padding_a = features.shape[1] - self.groups.shape[0]
        #if padding_a > 0:
        #    padding_a = ConstantPad2d((0, 0, 0, padding_a), 0)
        #    self.groups = padding_a(self.groups)

        #if not self.sparse_groups.is_coalesced():
        #    self.sparse_groups = self.sparse_groups.coalesce()
        where_mask = torch.from_numpy(np.argwhere(mask).squeeze()).to(
            self.sparse_groups.device)
        value_mask = self.isin(self.sparse_groups._indices()[0, :], where_mask)

        values = self.sparse_groups._values()[value_mask]
        indicies = self.sparse_groups._indices()[:, value_mask]

        values = torch.clamp(values, 0, 1)

        new_cols = indicies[1, :]
        # Rescale row_idx to slice
        temp = indicies[0, :]
        d = {j: i for i, j in enumerate(temp.unique().cpu().numpy())}
        new_rows = temp.cpu().apply_(lambda x: d[x]).to(
            self.sparse_groups.device)

        indicies = torch.stack([new_rows, new_cols])

        from torch_sparse import transpose
        indicies, values = transpose(indicies, values,
                                     self.sparse_groups.shape[0],
                                     self.sparse_groups.shape[1])

        self.sparse_groups = torch.sparse.FloatTensor(
            indicies, values, (features.shape[1], mask.sum()))
def test_transpose():
    row = torch.tensor([1, 0, 1, 0, 2, 1])
    col = torch.tensor([0, 1, 1, 1, 0, 0])
    index = torch.stack([row, col], dim=0)
    value = torch.tensor([[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]])

    index, value = transpose(index, value, m=3, n=2)
    assert index.tolist() == [[0, 0, 1, 1], [1, 2, 0, 1]]
    assert value.tolist() == [[7, 9], [5, 6], [6, 8], [3, 4]]
def test_transpose_matrix(dtype, device):
    row = torch.tensor([1, 0, 1, 2], device=device)
    col = torch.tensor([0, 1, 1, 0], device=device)
    index = torch.stack([row, col], dim=0)
    value = tensor([1, 2, 3, 4], dtype, device)

    index, value = transpose(index, value, m=3, n=2)
    assert index.tolist() == [[0, 0, 1, 1], [1, 2, 0, 1]]
    assert value.tolist() == [1, 4, 2, 3]
    def transpose(self, transpose_mask=None):
        indices_out, values_out = torch_sparse.transpose(self.indices, self.values,
                                                         self.n, self.m, coalesced=True)
        
        if transpose_mask is not None:
            values_out = (transpose_mask.float() * values_out.T).T
        shape_out = (self.m, self.n, self.n_channels)

        return SparseMatrix(indices_out, values_out, shape_out, self.indices_diag, self.is_set)
Exemple #8
0
    def backward(ctx, grad_indexC, grad_valueC):
        m, k, n = ctx.m, ctx.k, ctx.n
        indexA, valueA, indexB, valueB, indexC = ctx.saved_tensors

        grad_valueA = grad_valueB = None

        if ctx.needs_input_grad[1]:
            indexB_T, valueB_T = transpose(indexB, valueB, k, n)
            grad_indexA, grad_valueA = mm(indexC, grad_valueC, indexB_T,
                                          valueB_T, m, n, k)
            grad_valueA = lift(grad_indexA, grad_valueA, indexA, k)

        if ctx.needs_input_grad[3]:
            indexA_T, valueA_T = transpose(indexA, valueA, m, k)
            grad_indexB, grad_valueB = mm(indexA_T, valueA_T, indexC,
                                          grad_valueC, k, m, n)
            grad_valueB = lift(grad_indexB, grad_valueB, indexB, n)

        return None, grad_valueA, None, grad_valueB, None, None, None
Exemple #9
0
def batched_transpose(adj, value, m=None, n=None):
    """
    Args:
        adj: Tensor or list of Tensor
        value: Tensor [num_edges, ]
        m: int
        n: int
    """
    if isinstance(adj, Tensor):
        m = maybe_num_nodes(adj[0], m)
        n = maybe_num_nodes(adj[1], n)
        return transpose(adj, value, m, n)
    else:  # adj is a list of Tensor
        adj_ = [None] * value.shape[1]
        vs = torch.zeros(value.shape)
        m = max([maybe_num_nodes(a_[0], m) for a_ in adj])
        n = max([maybe_num_nodes(a_[1], n) for a_ in adj])
        for j in range(len(adj)):
            adj_[j], vs[:, j] = transpose(adj[j], value[:, j], m, n)
        return adj_, vs
    def test_sparse(self):
        index = torch.tensor([[1, 0, 1, 0, 2, 1],
                              [0, 1, 1, 1, 0, 0]])
        value = torch.Tensor([[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]])

        index, value = torch_sparse.transpose(index, value, 3, 2)
        test_index = torch.LongTensor([[0, 0, 1, 1],
                                       [1, 2, 0, 1]])
        test_value = torch.Tensor([[7., 9.], [5., 6.], [6., 8.], [3., 4.]])
        self.assertTrue(torch.all(torch.eq(test_index, index)))
        self.assertTrue(torch.all(torch.eq(test_value, value)))
Exemple #11
0
def StAS(index_A, value_A, index_S, value_S, device, N, kN):
    r"""StAS: a function which returns new edge weights for the pooled graph using the formula S^{T}AS"""

    index_A, value_A = coalesce(index_A, value_A, m=N, n=N)
    index_S, value_S = coalesce(index_S, value_S, m=N, n=kN)
    index_B, value_B = spspmm(index_A, value_A, index_S, value_S, N, N, kN)

    index_St, value_St = transpose(index_S, value_S, N, kN)
    index_B, value_B = coalesce(index_B, value_B, m=N, n=kN)
    index_E, value_E = spspmm(index_St.cpu(), value_St.cpu(), index_B.cpu(), value_B.cpu(), kN, N, kN)

    return index_E.to(device), value_E.to(device)
Exemple #12
0
    def add_reverse_edge_index(self, edge_index_dict) -> None:
        reverse_edge_index_dict = {}
        for metapath in edge_index_dict:
            if is_negative(metapath) or edge_index_dict[metapath] == None:
                continue
            reverse_metapath = self.reverse_metapath_name(
                metapath, edge_index_dict)

            reverse_edge_index_dict[reverse_metapath] = transpose(
                index=edge_index_dict[metapath],
                value=None,
                m=self.num_nodes_dict[metapath[0]],
                n=self.num_nodes_dict[metapath[-1]])[0]
        edge_index_dict.update(reverse_edge_index_dict)
Exemple #13
0
    def rebuild_features_average(self, features, mask, target_edges):
        self.prepare_groups(features, mask)

        if not self.sparse_groups.is_coalesced():
            self.sparse_groups = self.sparse_groups.coalesce()
        idxs, values = transpose(self.sparse_groups._indices(),
                                 self.sparse_groups._values(),
                                 self.sparse_groups.shape[0],
                                 self.sparse_groups.shape[1])
        fe = spmm(idxs, values, self.sparse_groups.shape[1],
                  self.sparse_groups.shape[0],
                  features.squeeze(-1).T).T

        # fe = torch.matmul(features.squeeze(-1), self.groups)
        #occurrences = torch.sum(self.groups, 0).expand(fe.shape)
        occurrences = torch.sparse.sum(self.sparse_groups,
                                       0).to_dense().expand(fe.shape)
        fe = fe / occurrences
        padding_b = target_edges - fe.shape[1]
        if padding_b > 0:
            padding_b = ConstantPad2d((0, padding_b, 0, 0), 0)
            fe = padding_b(fe)
        return fe
Exemple #14
0
    else:
        pyg_dataset = PygNodePropPredDataset(name='ogbn-mag',
                                             root='../dataset')
        pyg_data = pyg_dataset[0]

        # ('author', 'affiliated_with', 'institution'),
        # ('author', 'writes', 'paper'),
        # ('paper', 'cites', 'paper'),
        # ('paper', 'has_topic', 'field_of_study')
        # reverse edges (relations) in the heterogeneous graph.
        pyg_data.edge_index_dict[(
            'institution', 'rev_affiliated_with',
            'author')] = transpose(pyg_data.edge_index_dict[('author',
                                                             'affiliated_with',
                                                             'institution')],
                                   None,
                                   m=pyg_data.num_nodes_dict['author'],
                                   n=pyg_data.num_nodes_dict['institution'])[0]

        pyg_data.edge_index_dict[('paper', 'rev_writes',
                                  'author')] = transpose(
                                      pyg_data.edge_index_dict[('author',
                                                                'writes',
                                                                'paper')],
                                      None,
                                      m=pyg_data.num_nodes_dict['author'],
                                      n=pyg_data.num_nodes_dict['paper'])[0]

        pyg_data.edge_index_dict[('paper', 'rev_cites', 'paper')] = transpose(
            pyg_data.edge_index_dict[('paper', 'cites', 'paper')],
            None,
Exemple #15
0
    def parallel_sparse_attention_centrality(self, attention, idx):
        # O(N) implementation

        cnt = 0

        #MEMCHK#
        tic = time.time()
        cnt, tic = memchk(cnt, string="AC Start", level=8, tic=tic)
        #MEMCHK#

        batch, groups, npoints, neighbors = attention.size()

        idx_arange = torch.tensor([[npoints * i] * npoints * neighbors
                                   for i in range(batch * groups)],
                                  device='cuda').flatten()  # NK -> 11NK

        idx_self = torch.tensor(
            [[i] * neighbors for i in range(npoints)],
            device='cuda').flatten().unsqueeze(0).unsqueeze(0)  # NK -> 11NK
        idx_self = idx_self.repeat(batch, groups, 1)  # BGNK
        mtrx = torch.tensor([[1.] * npoints * batch * groups], device='cuda').T

        idx_neighbor_flatten = idx.repeat(1, groups, 1, 1).flatten()  # BGNK
        idx_neighbor_flatten = (idx_arange + idx_neighbor_flatten).unsqueeze(
            0)  # 1, BGNK

        idx_self_flatten = idx_self.flatten()  # BGNK
        idx_self_flatten = (idx_arange + idx_self_flatten).unsqueeze(
            0)  # 1, BGNK

        index = torch.cat([idx_self_flatten, idx_neighbor_flatten],
                          dim=0)  # 2, BGNK

        attention_flatten = attention.flatten()  # BGNK

        #MEMCHK#
        cnt, tic = memchk(cnt, string="CoalesceStart", level=8, tic=tic)
        #MEMCHK#

        index_s, value_s = coalesce(index, attention_flatten,
                                    npoints * batch * groups,
                                    npoints * batch * groups)
        index_t, value_t = transpose(index_s, value_s,
                                     npoints * batch * groups,
                                     npoints * batch * groups)

        out = spmm(index_t, value_t, npoints * batch * groups,
                   npoints * batch * groups, mtrx)

        #MEMCHK#
        cnt, tic = memchk(cnt, string="CoalesceEnd", level=8, tic=tic)
        #MEMCHK#

        out = out.view(batch, groups, npoints, 1)
        score = out.permute(0, 1, 3, 2)
        idx_value, idx_score = score.topk(k=neighbors,
                                          dim=3)  # B, G, 1, N -> B, G, 1, K'

        #MEMCHK#
        cnt, tic = memchk(cnt, string="AC End", level=8, tic=tic)
        #MEMCHK#

        return idx_value, idx_score
Exemple #16
0
def mgpool(x, pos, edge_index, batch, mask=None):
    adj_values = torch.ones(edge_index.shape[1]).cuda()
    cluster = graclus(edge_index)
    cluster, perm = consecutive_cluster(cluster)

    index = torch.stack([cluster, torch.arange(0, x.shape[0]).cuda()], dim=0)
    values = torch.ones(cluster.shape[0], dtype=torch.float).cuda()
    uniq, inv, counts = torch.unique(cluster,
                                     return_inverse=True,
                                     return_counts=True)
    newsize = uniq.shape[0]

    origsize = x.shape[0]

    new_batch = pool_batch(perm, batch)
    # Compute random walk graph laplacian:
    laplacian_index, laplacian_weights = get_laplacian(edge_index,
                                                       normalization='rw')
    laplacian_index, laplacian_weights = torch_sparse.coalesce(
        laplacian_index, laplacian_weights, m=origsize, n=origsize)
    index, values = torch_sparse.coalesce(index, values, m=newsize,
                                          n=origsize)  # P^T matrix
    new_feat = torch_sparse.spmm(index,
                                 values,
                                 m=newsize,
                                 n=origsize,
                                 matrix=x)  # P^T X
    new_pos = torch_sparse.spmm(index,
                                values,
                                m=newsize,
                                n=origsize,
                                matrix=pos)  # P^T POS

    new_adj, new_adj_val = torch_sparse.spspmm(index,
                                               values,
                                               edge_index,
                                               adj_values,
                                               m=newsize,
                                               k=origsize,
                                               n=origsize,
                                               coalesced=True)  # P^T A
    index, values = torch_sparse.transpose(index,
                                           values,
                                           m=newsize,
                                           n=origsize,
                                           coalesced=True)  # P
    new_adj, new_adj_val = torch_sparse.spspmm(new_adj,
                                               new_adj_val,
                                               index,
                                               values,
                                               m=newsize,
                                               k=origsize,
                                               n=newsize,
                                               coalesced=True)  # (P^T A) P
    # Precompute QP :
    values = torch.ones(cluster.shape[0], dtype=torch.float).cuda()
    index, values = torch_sparse.spspmm(laplacian_index,
                                        laplacian_weights,
                                        index,
                                        values,
                                        m=origsize,
                                        k=origsize,
                                        n=newsize,
                                        coalesced=True)
    return new_adj, new_feat, new_pos, new_batch, index, values, origsize, newsize
Exemple #17
0
    def process(self):
        import pandas as pd

        data = HeteroData()

        # Get author labels.
        path = osp.join(self.raw_dir, 'id_author.txt')
        author = pd.read_csv(path,
                             sep='\t',
                             names=['idx', 'name'],
                             index_col=1)

        path = osp.join(self.raw_dir, 'label',
                        'googlescholar.8area.author.label.txt')
        df = pd.read_csv(path, sep=' ', names=['name', 'y'])
        df = df.join(author, on='name')

        data['author'].y = torch.from_numpy(df['y'].values) - 1
        data['author'].y_index = torch.from_numpy(df['idx'].values)

        # Get venue labels.
        path = osp.join(self.raw_dir, 'id_conf.txt')
        venue = pd.read_csv(path, sep='\t', names=['idx', 'name'], index_col=1)

        path = osp.join(self.raw_dir, 'label',
                        'googlescholar.8area.venue.label.txt')
        df = pd.read_csv(path, sep=' ', names=['name', 'y'])
        df = df.join(venue, on='name')

        data['venue'].y = torch.from_numpy(df['y'].values) - 1
        data['venue'].y_index = torch.from_numpy(df['idx'].values)

        # Get paper<->author connectivity.
        path = osp.join(self.raw_dir, 'paper_author.txt')
        paper_author = pd.read_csv(path, sep='\t', header=None)
        paper_author = torch.from_numpy(paper_author.values)
        paper_author = paper_author.t().contiguous()
        M, N = int(paper_author[0].max() + 1), int(paper_author[1].max() + 1)
        paper_author, _ = coalesce(paper_author, None, M, N)
        author_paper, _ = transpose(paper_author, None, M, N)
        data['paper'].num_nodes = M
        data['author'].num_nodes = N
        data['paper', 'written_by', 'author'].edge_index = paper_author
        data['author', 'writes', 'paper'].edge_index = author_paper

        # Get paper<->venue connectivity.
        path = osp.join(self.raw_dir, 'paper_conf.txt')
        paper_venue = pd.read_csv(path, sep='\t', header=None)
        paper_venue = torch.from_numpy(paper_venue.values)
        paper_venue = paper_venue.t().contiguous()
        M, N = int(paper_venue[0].max() + 1), int(paper_venue[1].max() + 1)
        paper_venue, _ = coalesce(paper_venue, None, M, N)
        venue_paper, _ = transpose(paper_venue, None, M, N)
        data['venue'].num_nodes = N
        data['paper', 'published_in', 'venue'].edge_index = paper_venue
        data['venue', 'publishes', 'paper'].edge_index = venue_paper

        if self.pre_transform is not None:
            data = self.pre_transform(data)

        torch.save(self.collate([data]), self.processed_paths[0])
Exemple #18
0
    def process(self):
        # Get author labels.
        path = osp.join(self.raw_dir, 'id_author.txt')
        author = pandas.read_csv(path,
                                 sep='\t',
                                 names=['idx', 'name'],
                                 index_col=1)

        path = osp.join(self.raw_dir, 'label',
                        'googlescholar.8area.author.label.txt')
        df = pandas.read_csv(path, sep=' ', names=['name', 'y'])
        df = df.join(author, on='name')

        author_y = torch.from_numpy(df['y'].values) - 1
        author_y_index = torch.from_numpy(df['idx'].values)

        # Get venue labels.
        path = osp.join(self.raw_dir, 'id_conf.txt')
        venue = pandas.read_csv(path,
                                sep='\t',
                                names=['idx', 'name'],
                                index_col=1)

        path = osp.join(self.raw_dir, 'label',
                        'googlescholar.8area.venue.label.txt')
        df = pandas.read_csv(path, sep=' ', names=['name', 'y'])
        df = df.join(venue, on='name')

        venue_y = torch.from_numpy(df['y'].values) - 1
        venue_y_index = torch.from_numpy(df['idx'].values)

        # Get paper<->author connectivity.
        path = osp.join(self.raw_dir, 'paper_author.txt')
        paper_author = pandas.read_csv(path, sep='\t', header=None)
        paper_author = torch.from_numpy(paper_author.values)
        paper_author = paper_author.t().contiguous()
        M, N = int(paper_author[0].max() + 1), int(paper_author[1].max() + 1)
        paper_author, _ = coalesce(paper_author, None, M, N)
        author_paper, _ = transpose(paper_author, None, M, N)

        # Get paper<->venue connectivity.
        path = osp.join(self.raw_dir, 'paper_conf.txt')
        paper_venue = pandas.read_csv(path, sep='\t', header=None)
        paper_venue = torch.from_numpy(paper_venue.values)
        paper_venue = paper_venue.t().contiguous()
        M, N = int(paper_venue[0].max() + 1), int(paper_venue[1].max() + 1)
        paper_venue, _ = coalesce(paper_venue, None, M, N)
        venue_paper, _ = transpose(paper_venue, None, M, N)

        data = Data(
            edge_index_dict={
                ('paper', 'written by', 'author'): paper_author,
                ('author', 'wrote', 'paper'): author_paper,
                ('paper', 'published in', 'venue'): paper_venue,
                ('venue', 'published', 'paper'): venue_paper,
            },
            y_dict={
                'author': author_y,
                'venue': venue_y,
            },
            y_index_dict={
                'author': author_y_index,
                'venue': venue_y_index,
            },
            num_nodes_dict={
                'paper': int(paper_author[0].max()) + 1,
                'author': author.shape[0],
                'venue': venue.shape[0],
            },
        )

        if self.pre_transform is not None:
            data = self.pre_transform(data)

        torch.save(self.collate([data]), self.processed_paths[0])
 def gather_transpose(self, mask):
     indices_out, values_out = torch_sparse.transpose(self.indices, self.values,
                                                      self.n, self.m, coalesced=True)
     return values_out[mask]
Exemple #20
0
def main():
    parser = argparse.ArgumentParser(description='OGBN-MAG (MetaPath2Vec)')
    parser.add_argument('--device', type=int, default=0)
    parser.add_argument('--embedding_dim', type=int, default=128)
    parser.add_argument('--walk_length', type=int, default=64)
    parser.add_argument('--context_size', type=int, default=7)
    parser.add_argument('--walks_per_node', type=int, default=5)
    parser.add_argument('--num_negative_samples', type=int, default=5)
    parser.add_argument('--batch_size', type=int, default=128)
    parser.add_argument('--lr', type=float, default=0.01)
    parser.add_argument('--epochs', type=int, default=5)
    parser.add_argument('--log_steps', type=int, default=100)
    args = parser.parse_args()

    device = f'cuda:{args.device}' if torch.cuda.is_available() else 'cpu'
    device = torch.device(device)

    dataset = PygNodePropPredDataset('ogbn-mag')
    data = dataset[0]

    # We need to add reverse edges to the heterogeneous graph.
    data.edge_index_dict[('institution', 'employs', 'author')] = transpose(
        data.edge_index_dict[('author', 'affiliated_with', 'institution')],
        None,
        m=data.num_nodes_dict['author'],
        n=data.num_nodes_dict['institution'])[0]
    data.edge_index_dict[('paper', 'written_by', 'author')] = transpose(
        data.edge_index_dict[('author', 'writes', 'paper')],
        None,
        m=data.num_nodes_dict['author'],
        n=data.num_nodes_dict['paper'])[0]
    data.edge_index_dict[('field_of_study', 'contains', 'paper')] = transpose(
        data.edge_index_dict[('paper', 'has_topic', 'field_of_study')],
        None,
        m=data.num_nodes_dict['paper'],
        n=data.num_nodes_dict['field_of_study'])[0]
    print(data)

    metapath = [
        ('author', 'writes', 'paper'),
        ('paper', 'has_topic', 'field_of_study'),
        ('field_of_study', 'contains', 'paper'),
        ('paper', 'written_by', 'author'),
        ('author', 'affiliated_with', 'institution'),
        ('institution', 'employs', 'author'),
        ('author', 'writes', 'paper'),
        ('paper', 'cites', 'paper'),
        ('paper', 'written_by', 'author'),
    ]

    model = MetaPath2Vec(data.edge_index_dict,
                         embedding_dim=128,
                         metapath=metapath,
                         walk_length=64,
                         context_size=7,
                         walks_per_node=5,
                         num_negative_samples=5,
                         sparse=True).to(device)

    loader = model.loader(batch_size=128, shuffle=True, num_workers=4)
    optimizer = torch.optim.SparseAdam(list(model.parameters()), lr=0.01)

    model.train()
    for epoch in range(1, args.epochs + 1):
        for i, (pos_rw, neg_rw) in enumerate(loader):
            optimizer.zero_grad()
            loss = model.loss(pos_rw.to(device), neg_rw.to(device))
            loss.backward()
            optimizer.step()

            if (i + 1) % args.log_steps == 0:
                print(f'Epoch: {epoch:02d}, Step: {i+1:03d}/{len(loader)}, '
                      f'Loss: {loss:.4f}')

            if (i + 1) % 1000 == 0:  # Save model every 1000 steps.
                save_embedding(model)
        save_embedding(model)
Exemple #21
0
 def transpose(self):
     (tidxs, tvals) = transpose(self.idxs, self.vals, self.shape[0], self.shape[1])
     return SpTensor(tidxs, tvals, (self.shape[1], self.shape[0]))
Exemple #22
0
def degrees(M):
    signal = torch.reshape(torch.ones(M.shape[0]), (-1, 1))
    index, values = torch_sparse.transpose(M.index, M.values, M.shape[0],
                                           M.shape[1])
    return torch.ravel(
        torch_sparse.spmm(index, values, M.shape[1], M.shape[0], signal))
Exemple #23
0
# 这里是按照行优先的顺序
# 按行排序索引并删除重复项。重复的条目使用 torch_scatter 的聚合函数计算
# 即存在空行或者空列的情况,合并稀疏矩阵重复位置处的数值
# 合并后只有4个位置处有数值
index = torch.tensor([[1, 0, 1, 0, 2, 1], [0, 1, 1, 1, 0, 0]])
value = torch.Tensor([[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]])

index, value = coalesce(index, value, m=3, n=2)
print(index, value, sep='\n')

# 聚合函数使用 平均值
index, value = coalesce(index, value, m=3, n=2, op='mean')
print(index, value, sep='\n')

# 转置,聚合函数默认为 add
index, value = transpose(index, value, 3, 2)
print(index, value, sep='\n')

# 稀疏矩阵 * 稠密矩阵
# index 表示稀疏矩阵的坐标,value表示对应的值
# 第一行是行坐标,第二行是列坐标
index = torch.tensor([[0, 0, 1, 2, 2], [0, 2, 1, 0, 1]])
value = torch.Tensor([1, 2, 4, 1, 3])
matrix = torch.Tensor([[1, 4], [2, 5], [3, 6]])

out = spmm(index, value, 3, matrix)
print(out)

# 稀疏矩阵 * 稀疏矩阵
indexA = torch.tensor([[0, 0, 1, 2, 2], [1, 2, 0, 0, 1]])
valueA = torch.Tensor([1, 2, 3, 4, 5])