В этом посте я расскажу о автокодировщиках сверточных вариаций графов.

В сверточных вариационных автокодировщиках Graph на выходе пытаются реконструировать матрицу смежности, используя в качестве входных данных функции смежности и узел.

Подобно ванильному VAE, граф сверточный VAE также состоит из двух частей: кодировщика и декодера. Кодировщик имеет определенную структуру, которая позволяет кодировщику изучать связи между узлами.

f(X,A) = Relu(ÂXW)

Где A — модифицированная версия матрицы смежности (я объясню это в следующем разделе), X — матрица признаков узла, а W — вес.

Что такое Â?

 рассчитывается следующим образом:

(Адаптировано с https://github.com/tkipf/gae/blob/master/gae/preprocessing.py)

import scipy.sparse as sp
import numpy as np
adj = np.matrix([
      [0, 1, 0, 0],
      [0, 0, 1, 1], 
      [0, 1, 0, 0],
      [1, 0, 1, 0]],
      dtype=float)
def preprocess_graph(adj):
    adj = sp.coo_matrix(adj)
    # adj matrix in sparse format
    [[0. 1. 0. 0.]
    [0. 0. 1. 1.]
    [0. 1. 0. 0.]
    [1. 0. 1. 0.]]  
  
    adj_ = adj + sp.eye(adj.shape[0])
    # creating the adj_ matrix  by adding the identity matrix I to the adj to create self connections
    [[1. 1. 0. 0.]
    [0. 1. 1. 1.]
    [0. 1. 1. 0.]
    [1. 0. 1. 1.]]
    rowsum = np.array(adj_.sum(1))
    # row sum of adj_ matrix
    [[2.]
    [3.]
    [2.]
    [3.]]
    degree_mat_inv_sqrt = sp.diags(np.power(rowsum, -0.5).flatten())
    # create a sparse diagonal matrix D ̃ −0.5
    [[0.70710678,0.,0.,0.]
    [0.,0.57735027 0.,0.]
    [0.,0.,0.70710678 0.]
    [0.,0.,0.,0.57735027]]
    adj_normalized = adj_.dot(degree_mat_inv_sqrt).transpose().dot(degree_mat_inv_sqrt).tocoo()
    #normalizing
    [[0.5, 0., 0., 0.40824829],
    [0.40824829, 0.33333333, 0.40824829, 0.],
    [0., 0.40824829, 0.5, 0.40824829],
    [0., 0.33333333, 0., 0.33333333]]
    return adj_normalized