Source code for dltk.models.graphical.cgcnn

from __future__ import division
from __future__ import absolute_import
from __future__ import print_function

import tensorflow as tf
import numpy as np

from dltk.core.modules.base import AbstractModule
from dltk.core.modules.linear import Linear
from dltk.core.modules.graph_convolution import GraphConvolution


[docs]class CGCNN(AbstractModule): """Graph CNN This module builds a Graph Convolutional Network using the Chebyshev approximation (Defferrard et al. 2016). """ def __init__(self, L, filters, K, p, fc, bias='b1', pool='mpool', dropout=1, name='cgcnn'): """Builds a graph CNN for classification Parameters ---------- L: list list of Graph Laplacians, one per coarsening level filters : list number of filters per layer K : list list of polynomial orders, i.e. filter sizes or number of hopes p : list pooling size (should be 1 - no pooling or a power of 2 - reduction by 2 at each coarser level) fc: list number of features per sample, i.e. number of hidden neurons (the last layer is the softmax, i.e. M[-1] is the number of classes) bias: string type of bias to use, 'b1' for one bias per filter or 'b2' for one bias per vertex per filter pool: string pooling, 'mpool' for max pooling or 'apool' for average pooling dropout: float dropout for fc layers, probability to keep hidden neurons (no dropout with 1) name : string name of the network """ # Verify the consistency w.r.t. the number of layers assert len(L) >= len(filters) == len(K) == len(p) assert np.all(np.array(p) >= 1) p_log2 = np.where(np.array(p) > 1, np.log2(p), 0) assert np.all(np.mod(p_log2, 1) == 0) # Powers of 2. assert len(L) >= 1 + np.sum(p_log2) # Enough coarsening levels for pool sizes. # Keep the useful Laplacians only M_0 = L[0].shape[0] j = 0 self.L = [] for pp in p: self.L.append(L[j]) j += int(np.log2(pp)) if pp > 1 else 0 L = self.L # Store attributes self.L = L self.filters = filters self.K = K self.p = p self.fc = fc self.bias = bias self.pool = pool self.dropout = dropout super(CGCNN, self).__init__(name) def _build(self, inp, is_training=True): """Constructs a GraphCNN using the input tensor Parameters ---------- inp : tf.Tensor input tensor is_training : bool flag to specify whether this is training - used for dropout Returns ------- dict output dictionary containing: - `logits` - logits of the classification - `y_prob` - classification probabilities - `y_` - prediction of the classification """ outputs = {} x = inp pool_op = tf.nn.max_pool if self.pool == 'mpool' else tf.nn.avg_pool # Graph convolutional layers x = tf.expand_dims(x, 2) # N x M x F=1 for i in range(len(self.p)): with tf.variable_scope('conv_{}'.format(i + 1)): with tf.name_scope('filter'): x = GraphConvolution(self.filters[i], self.L[i], self.K[i], self.bias)(x) with tf.name_scope('relu'): x = tf.nn.relu(x) with tf.name_scope('pooling'): if self.p[i] > 1: x = tf.expand_dims(x, 3) # N x M x F x 1 x = pool_op(x, ksize=[1, self.p[i], 1, 1], strides=[1, self.p[i], 1, 1], padding='SAME') x = tf.squeeze(x, [3]) # N x M/p x F # Fully connected hidden layers N, M, F = x.get_shape() x = tf.reshape(x, [int(N), int(M * F)]) # N x M for i, M in enumerate(self.fc[:-1]): with tf.variable_scope('fc_{}'.format(i + 1)): x = Linear(M)(x) x = tf.nn.relu(x) if is_training: x = tf.nn.dropout(x, self.dropout) # Logits linear layer, i.e. softmax without normalization. with tf.variable_scope('logits'): x = Linear(self.fc[-1])(x) outputs['logits'] = x with tf.variable_scope('pred'): y_prob = tf.nn.softmax(x) outputs['y_prob'] = y_prob y_ = tf.argmax(x, axis=1) outputs['y_'] = y_ return outputs