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!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
9.9KB

  1. import decagon_pytorch.convolve
  2. import decagon.deep.layers
  3. import torch
  4. import tensorflow as tf
  5. import numpy as np
  6. def prepare_data():
  7. np.random.seed(0)
  8. latent = np.random.random((5, 10)).astype(np.float32)
  9. latent[latent < .5] = 0
  10. latent = np.ceil(latent)
  11. adjacency_matrices = []
  12. for _ in range(5):
  13. adj_mat = np.random.random((len(latent),) * 2).astype(np.float32)
  14. adj_mat[adj_mat < .5] = 0
  15. adj_mat = np.ceil(adj_mat)
  16. adjacency_matrices.append(adj_mat)
  17. print('latent:', latent)
  18. print('adjacency_matrices[0]:', adjacency_matrices[0])
  19. return latent, adjacency_matrices
  20. def dense_to_sparse_tf(x):
  21. a, b = np.where(x)
  22. indices = np.array([a, b]).T
  23. values = x[a, b]
  24. return tf.sparse.SparseTensor(indices, values, x.shape)
  25. def dropout_sparse_tf(x, keep_prob, num_nonzero_elems):
  26. """Dropout for sparse tensors. Currently fails for very large sparse tensors (>1M elements)
  27. """
  28. noise_shape = [num_nonzero_elems]
  29. random_tensor = keep_prob
  30. random_tensor += tf.convert_to_tensor(torch.rand(noise_shape).detach().numpy())
  31. # tf.convert_to_tensor(np.random.random(noise_shape))
  32. # tf.random_uniform(noise_shape)
  33. dropout_mask = tf.cast(tf.floor(random_tensor), dtype=tf.bool)
  34. pre_out = tf.sparse_retain(x, dropout_mask)
  35. return pre_out * (1./keep_prob)
  36. def dense_graph_conv_torch():
  37. torch.random.manual_seed(0)
  38. latent, adjacency_matrices = prepare_data()
  39. latent = torch.tensor(latent)
  40. adj_mat = adjacency_matrices[0]
  41. adj_mat = torch.tensor(adj_mat)
  42. conv = decagon_pytorch.convolve.DenseGraphConv(10, 10,
  43. adj_mat)
  44. latent = conv(latent)
  45. return latent
  46. def dense_dropout_graph_conv_activation_torch(keep_prob=1.):
  47. torch.random.manual_seed(0)
  48. latent, adjacency_matrices = prepare_data()
  49. latent = torch.tensor(latent)
  50. adj_mat = adjacency_matrices[0]
  51. adj_mat = torch.tensor(adj_mat)
  52. conv = decagon_pytorch.convolve.DenseDropoutGraphConvActivation(10, 10,
  53. adj_mat, keep_prob=keep_prob)
  54. latent = conv(latent)
  55. return latent
  56. def sparse_graph_conv_torch():
  57. torch.random.manual_seed(0)
  58. latent, adjacency_matrices = prepare_data()
  59. print('latent.dtype:', latent.dtype)
  60. latent = torch.tensor(latent).to_sparse()
  61. adj_mat = adjacency_matrices[0]
  62. adj_mat = torch.tensor(adj_mat).to_sparse()
  63. print('adj_mat.dtype:', adj_mat.dtype,
  64. 'latent.dtype:', latent.dtype)
  65. conv = decagon_pytorch.convolve.SparseGraphConv(10, 10,
  66. adj_mat)
  67. latent = conv(latent)
  68. return latent
  69. def sparse_graph_conv_tf():
  70. torch.random.manual_seed(0)
  71. latent, adjacency_matrices = prepare_data()
  72. conv_torch = decagon_pytorch.convolve.SparseGraphConv(10, 10,
  73. torch.tensor(adjacency_matrices[0]).to_sparse())
  74. weight = tf.constant(conv_torch.weight.detach().numpy())
  75. latent = dense_to_sparse_tf(latent)
  76. adj_mat = dense_to_sparse_tf(adjacency_matrices[0])
  77. latent = tf.sparse_tensor_dense_matmul(latent, weight)
  78. latent = tf.sparse_tensor_dense_matmul(adj_mat, latent)
  79. return latent
  80. def sparse_dropout_graph_conv_activation_torch(keep_prob=1.):
  81. torch.random.manual_seed(0)
  82. latent, adjacency_matrices = prepare_data()
  83. latent = torch.tensor(latent).to_sparse()
  84. adj_mat = adjacency_matrices[0]
  85. adj_mat = torch.tensor(adj_mat).to_sparse()
  86. conv = decagon_pytorch.convolve.SparseDropoutGraphConvActivation(10, 10,
  87. adj_mat, keep_prob=keep_prob)
  88. latent = conv(latent)
  89. return latent
  90. def sparse_dropout_graph_conv_activation_tf(keep_prob=1.):
  91. torch.random.manual_seed(0)
  92. latent, adjacency_matrices = prepare_data()
  93. conv_torch = decagon_pytorch.convolve.SparseGraphConv(10, 10,
  94. torch.tensor(adjacency_matrices[0]).to_sparse())
  95. weight = tf.constant(conv_torch.weight.detach().numpy())
  96. nonzero_feat = np.sum(latent > 0)
  97. latent = dense_to_sparse_tf(latent)
  98. latent = dropout_sparse_tf(latent, keep_prob,
  99. nonzero_feat)
  100. adj_mat = dense_to_sparse_tf(adjacency_matrices[0])
  101. latent = tf.sparse_tensor_dense_matmul(latent, weight)
  102. latent = tf.sparse_tensor_dense_matmul(adj_mat, latent)
  103. latent = tf.nn.relu(latent)
  104. return latent
  105. def test_sparse_graph_conv():
  106. latent_torch = sparse_graph_conv_torch()
  107. latent_tf = sparse_graph_conv_tf()
  108. assert np.all(latent_torch.detach().numpy() == latent_tf.eval(session = tf.Session()))
  109. def test_sparse_dropout_graph_conv_activation():
  110. for i in range(11):
  111. keep_prob = i/10. + np.finfo(np.float32).eps
  112. latent_torch = sparse_dropout_graph_conv_activation_torch(keep_prob)
  113. latent_tf = sparse_dropout_graph_conv_activation_tf(keep_prob)
  114. latent_torch = latent_torch.detach().numpy()
  115. latent_tf = latent_tf.eval(session = tf.Session())
  116. print('latent_torch:', latent_torch)
  117. print('latent_tf:', latent_tf)
  118. assert np.all(latent_torch - latent_tf < .000001)
  119. def test_sparse_multi_dgca():
  120. latent_torch = None
  121. latent_tf = []
  122. for i in range(11):
  123. keep_prob = i/10. + np.finfo(np.float32).eps
  124. latent_torch = sparse_dropout_graph_conv_activation_torch(keep_prob) \
  125. if latent_torch is None \
  126. else latent_torch + sparse_dropout_graph_conv_activation_torch(keep_prob)
  127. latent_tf.append(sparse_dropout_graph_conv_activation_tf(keep_prob))
  128. latent_torch = torch.nn.functional.normalize(latent_torch, p=2, dim=1)
  129. latent_tf = tf.add_n(latent_tf)
  130. latent_tf = tf.nn.l2_normalize(latent_tf, dim=1)
  131. latent_torch = latent_torch.detach().numpy()
  132. latent_tf = latent_tf.eval(session = tf.Session())
  133. assert np.all(latent_torch - latent_tf < .000001)
  134. def test_graph_conv():
  135. latent_dense = dense_graph_conv_torch()
  136. latent_sparse = sparse_graph_conv_torch()
  137. assert np.all(latent_dense.detach().numpy() == latent_sparse.detach().numpy())
  138. def setup_function(fun):
  139. if fun == test_dropout_graph_conv_activation or \
  140. fun == test_multi_dgca:
  141. print('Disabling dropout for testing...')
  142. setup_function.old_dropout = decagon_pytorch.convolve.dropout, \
  143. decagon_pytorch.convolve.dropout_sparse
  144. decagon_pytorch.convolve.dropout = lambda x, keep_prob: x
  145. decagon_pytorch.convolve.dropout_sparse = lambda x, keep_prob: x
  146. def teardown_function(fun):
  147. print('Re-enabling dropout...')
  148. if fun == test_dropout_graph_conv_activation or \
  149. fun == test_multi_dgca:
  150. decagon_pytorch.convolve.dropout, \
  151. decagon_pytorch.convolve.dropout_sparse = \
  152. setup_function.old_dropout
  153. def flexible_dropout_graph_conv_activation_torch(keep_prob=1.):
  154. torch.random.manual_seed(0)
  155. latent, adjacency_matrices = prepare_data()
  156. latent = torch.tensor(latent).to_sparse()
  157. adj_mat = adjacency_matrices[0]
  158. adj_mat = torch.tensor(adj_mat).to_sparse()
  159. conv = decagon_pytorch.convolve.DropoutGraphConvActivation(10, 10,
  160. adj_mat, keep_prob=keep_prob)
  161. latent = conv(latent)
  162. return latent
  163. def test_dropout_graph_conv_activation():
  164. for i in range(11):
  165. keep_prob = i/10.
  166. if keep_prob == 0:
  167. keep_prob += np.finfo(np.float32).eps
  168. print('keep_prob:', keep_prob)
  169. latent_dense = dense_dropout_graph_conv_activation_torch(keep_prob)
  170. latent_dense = latent_dense.detach().numpy()
  171. print('latent_dense:', latent_dense)
  172. latent_sparse = sparse_dropout_graph_conv_activation_torch(keep_prob)
  173. latent_sparse = latent_sparse.detach().numpy()
  174. print('latent_sparse:', latent_sparse)
  175. latent_flex = flexible_dropout_graph_conv_activation_torch(keep_prob)
  176. latent_flex = latent_flex.detach().numpy()
  177. print('latent_flex:', latent_flex)
  178. nonzero = (latent_dense != 0) & (latent_sparse != 0)
  179. assert np.all(latent_dense[nonzero] == latent_sparse[nonzero])
  180. nonzero = (latent_dense != 0) & (latent_flex != 0)
  181. assert np.all(latent_dense[nonzero] == latent_flex[nonzero])
  182. nonzero = (latent_sparse != 0) & (latent_flex != 0)
  183. assert np.all(latent_sparse[nonzero] == latent_flex[nonzero])
  184. def test_multi_dgca():
  185. keep_prob = .5
  186. torch.random.manual_seed(0)
  187. latent, adjacency_matrices = prepare_data()
  188. latent_sparse = torch.tensor(latent).to_sparse()
  189. latent = torch.tensor(latent)
  190. assert np.all(latent_sparse.to_dense().numpy() == latent.numpy())
  191. adjacency_matrices_sparse = [ torch.tensor(a).to_sparse() for a in adjacency_matrices ]
  192. adjacency_matrices = [ torch.tensor(a) for a in adjacency_matrices ]
  193. for i in range(len(adjacency_matrices)):
  194. assert np.all(adjacency_matrices[i].numpy() == adjacency_matrices_sparse[i].to_dense().numpy())
  195. torch.random.manual_seed(0)
  196. multi_sparse = decagon_pytorch.convolve.SparseMultiDGCA([10,] * len(adjacency_matrices), 10, adjacency_matrices_sparse, keep_prob=keep_prob)
  197. torch.random.manual_seed(0)
  198. multi = decagon_pytorch.convolve.DenseMultiDGCA([10,] * len(adjacency_matrices), 10, adjacency_matrices, keep_prob=keep_prob)
  199. print('len(adjacency_matrices):', len(adjacency_matrices))
  200. print('len(multi_sparse.sparse_dgca):', len(multi_sparse.sparse_dgca))
  201. print('len(multi.dgca):', len(multi.dgca))
  202. for i in range(len(adjacency_matrices)):
  203. assert np.all(multi_sparse.sparse_dgca[i].sparse_graph_conv.weight.detach().numpy() == multi.dgca[i].graph_conv.weight.detach().numpy())
  204. # torch.random.manual_seed(0)
  205. latent_sparse = multi_sparse([latent_sparse,] * len(adjacency_matrices))
  206. # torch.random.manual_seed(0)
  207. latent = multi([latent,] * len(adjacency_matrices))
  208. assert np.all(latent_sparse.detach().numpy() == latent.detach().numpy())