IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

111 satır
3.8KB

  1. #
  2. # Copyright (C) Stanislaw Adaszewski, 2020
  3. # License: GPLv3
  4. #
  5. import numpy as np
  6. import scipy.sparse as sp
  7. import torch
  8. def add_eye_sparse(adj_mat: torch.Tensor) -> torch.Tensor:
  9. if not isinstance(adj_mat, torch.Tensor):
  10. raise ValueError('adj_mat must be a torch.Tensor')
  11. if not adj_mat.is_sparse:
  12. raise ValueError('adj_mat must be sparse')
  13. if len(adj_mat.shape) != 2 or \
  14. adj_mat.shape[0] != adj_mat.shape[1]:
  15. raise ValueError('adj_mat must be a square matrix')
  16. adj_mat = adj_mat.coalesce()
  17. indices = adj_mat.indices()
  18. values = adj_mat.values()
  19. eye_indices = torch.arange(adj_mat.shape[0], dtype=indices.dtype).view(1, -1)
  20. eye_indices = torch.cat((eye_indices, eye_indices), 0)
  21. eye_values = torch.ones(adj_mat.shape[0], dtype=values.dtype)
  22. indices = torch.cat((indices, eye_indices), 1)
  23. values = torch.cat((values, eye_values), 0)
  24. adj_mat = torch.sparse_coo_tensor(indices=indices, values=values, size=adj_mat.shape)
  25. return adj_mat
  26. def norm_adj_mat_one_node_type_sparse(adj_mat):
  27. if len(adj_mat.shape) != 2 or \
  28. adj_mat.shape[0] != adj_mat.shape[1]:
  29. raise ValueError('adj_mat must be a square matrix')
  30. adj_mat = add_eye_sparse(adj_mat)
  31. adj_mat = adj_mat.coalesce()
  32. indices = adj_mat.indices()
  33. values = adj_mat.values()
  34. degrees_row = torch.zeros(adj_mat.shape[0])
  35. degrees_row = degrees_row.index_add(0, indices[0], values.to(degrees_row.dtype))
  36. degrees_col = torch.zeros(adj_mat.shape[1])
  37. degrees_col = degrees_col.index_add(0, indices[1], values.to(degrees_col.dtype))
  38. # degrees_row = torch.sqrt(degrees_row)
  39. # degrees_col = torch.sqrt(degrees_col)
  40. # print('degrees:', degrees)
  41. # print('values:', values)
  42. values = values.to(degrees_row.dtype) / torch.sqrt(degrees_row[indices[0]] * degrees_col[indices[1]])
  43. adj_mat = torch.sparse_coo_tensor(indices=indices, values=values, size=adj_mat.shape)
  44. return adj_mat
  45. def norm_adj_mat_one_node_type_dense(adj_mat):
  46. if not isinstance(adj_mat, torch.Tensor):
  47. raise ValueError('adj_mat must be a torch.Tensor')
  48. if adj_mat.is_sparse:
  49. raise ValueError('adj_mat must be dense')
  50. if len(adj_mat.shape) != 2 or \
  51. adj_mat.shape[0] != adj_mat.shape[1]:
  52. raise ValueError('adj_mat must be a square matrix')
  53. adj_mat = adj_mat + torch.eye(adj_mat.shape[0], dtype=adj_mat.dtype)
  54. degrees_row = adj_mat.sum(1).view(-1, 1).to(torch.float32)
  55. degrees_col = adj_mat.sum(0).view(1, -1).to(torch.float32)
  56. degrees_row = torch.sqrt(degrees_row)
  57. degrees_col = torch.sqrt(degrees_col)
  58. adj_mat = adj_mat.to(degrees_row.dtype) / degrees_row
  59. adj_mat = adj_mat / degrees_col
  60. return adj_mat
  61. def norm_adj_mat_one_node_type(adj_mat):
  62. if adj_mat.is_sparse:
  63. return norm_adj_mat_one_node_type_sparse(adj_mat)
  64. else:
  65. return norm_adj_mat_one_node_type_dense(adj_mat)
  66. # def norm_adj_mat_one_node_type(adj):
  67. # adj = sp.coo_matrix(adj)
  68. # assert adj.shape[0] == adj.shape[1]
  69. # adj_ = adj + sp.eye(adj.shape[0])
  70. # rowsum = np.array(adj_.sum(1))
  71. # degree_mat_inv_sqrt = np.power(rowsum, -0.5).flatten()
  72. # degree_mat_inv_sqrt = sp.diags(degree_mat_inv_sqrt)
  73. # adj_normalized = adj_.dot(degree_mat_inv_sqrt).transpose().dot(degree_mat_inv_sqrt)
  74. # return adj_normalized
  75. def norm_adj_mat_two_node_types(adj):
  76. adj = sp.coo_matrix(adj)
  77. rowsum = np.array(adj.sum(1))
  78. colsum = np.array(adj.sum(0))
  79. rowdegree_mat_inv = sp.diags(np.nan_to_num(np.power(rowsum, -0.5)).flatten())
  80. coldegree_mat_inv = sp.diags(np.nan_to_num(np.power(colsum, -0.5)).flatten())
  81. adj_normalized = rowdegree_mat_inv.dot(adj).dot(coldegree_mat_inv).tocoo()
  82. return adj_normalized