def pooling_matrices(A_list, coarsening_levels, pool): """ Creates all the necessary matrices for decimation pooling and average pooling. :param A_list: a list of adjacency matrices :param coarsening_levels: a list of coarsening levels for pooling :param pool: pooling method to use (decim, graclus, nmf) :return: D_out: list of lists with decimation matrices for each graph A_out: list of Laplacians pyramids for each graph num_nodes_list: list with the number of nodes for each graph partition_list: list of lists, each list has N repeating integers where N is the size of each graph. Used as second argument for tf.segment_sum. """ A_out = [] D_out = [] if pool == 'decim': for a in A_list: L = convolution.normalized_laplacian(a) graphs, indices = reduction(L, levels=max(coarsening_levels) + 1, mode='kron') graphs = [convolution.rescale_laplacian(g, lmax=2) for g in graphs] dm, gl = decimation_matrices(levels=coarsening_levels, L=graphs, indices=indices) D_out.append(dm) A_out.append(gl) elif pool == 'graclus': perm_list = [] for a in A_list: a = sp.csr_matrix(a) # pooling.coarsen wants sparse matrices graphs, perm = coarsen(a, levels=max(coarsening_levels) + 1) graphs = [graphs[i] for i in coarsening_levels] # Keep only the right graphs graphs = [convolution.normalized_adjacency(g) for g in graphs] dm = graclus_pooling_matrices(graphs) D_out.append(dm) A_out.append(graphs) perm_list.append(perm) elif pool == 'nmf': for a in A_list: dm, gl = nmf_pooling(A=a, levels=coarsening_levels) gl = [convolution.normalized_adjacency(g) for g in gl] D_out.append(dm) A_out.append(gl) else: raise ValueError("pool must be 'decim', 'graclus' or 'nmf'") if pool == 'graclus': return A_out, D_out, perm_list else: return A_out, D_out
def test_graph_ops(): A = np.ones((N, N)) convert_to_sparse = [[True]] expected_output = convolution.normalized_adjacency(A) _check_op(ops.normalize_A, [A], expected_output, convert_to_sparse) expected_output = convolution.degree_matrix(A).sum(-1) _check_op(ops.degrees, [A], expected_output, convert_to_sparse) expected_output = convolution.degree_matrix(A) _check_op(ops.degree_matrix, [A], expected_output, convert_to_sparse)
def GNN(A, X): # 使用graph_hi构造图邻接矩阵A np.random.seed(0) # for reproducibility ITER = 10000 # Parameters P = OrderedDict([ ('es_patience', ITER), ('dataset', ['cora' ]), # 'cora', 'citeseer', 'pubmed', 'cloud', or 'synth' ('H_', [None]), ('n_channels', [16]), ('learning_rate', [5e-4]) ]) ############################################################################ # LOAD DATASET ############################################################################ A = np.maximum(A, A.T) A = sp.csr_matrix(A, dtype=np.float32) X = X.todense() n_feat = X.shape[-1] ############################################################################ # GNN MODEL ############################################################################ X_in = Input( tensor=tf.placeholder(tf.float32, shape=(None, n_feat), name='X_in')) A_in = Input(tensor=tf.sparse_placeholder(tf.float32, shape=(None, None)), name='A_in', sparse=True) # S_in = Input(tensor=tf.placeholder(tf.int32, shape=(None,), name='segment_ids_in')) A_norm = normalized_adjacency(A) X_1 = GCSConv(P['n_channels'], kernel_initializer='he_normal', activation='elu')([X_in, A_in]) pool1, adj1, C = MinCutPool(k=n_classes, h=P['H_'], activation='elu', return_mask=True)([X_1, A_in]) model = Model([X_in, A_in], [pool1, adj1, C]) model.compile('adam', None) ############################################################################ # TRAINING ############################################################################ # Setup sess = K.get_session() loss = model.total_loss opt = tf.train.AdamOptimizer(learning_rate=P['learning_rate']) train_step = opt.minimize(loss) # Initialize all variables init_op = tf.global_variables_initializer() sess.run(init_op) # Fit layer tr_feed_dict = {X_in: X, A_in: sp_matrix_to_sp_tensor_value(A_norm)} best_loss = np.inf patience = P['es_patience'] tol = 1e-5 for _ in tqdm(range(ITER)): outs = sess.run([train_step, model.losses[0], model.losses[1], C], feed_dict=tr_feed_dict) # c = np.argmax(outs[3], axis=-1) if outs[1] + outs[2] + tol < best_loss: best_loss = outs[1] + outs[2] patience = P['es_patience'] else: patience -= 1 if patience == 0: break ############################################################################ # RESULTS ############################################################################ C_ = sess.run([C], feed_dict=tr_feed_dict)[0] c = np.argmax(C_, axis=-1) K.clear_session() return c
_, S_pool = model(inputs, training=True) loss = sum(model.losses) gradients = tape.gradient(loss, model.trainable_variables) opt.apply_gradients(zip(gradients, model.trainable_variables)) return model.losses[0], model.losses[1], S_pool np.random.seed(1) epochs = 5000 # Training iterations lr = 5e-4 # Learning rate ################################################################################ # LOAD DATASET ################################################################################ A, X, y, _, _, _ = citation.load_data('cora') A_norm = normalized_adjacency(A) X = X.todense() F = X.shape[-1] y = np.argmax(y, axis=-1) n_clusters = y.max() + 1 ################################################################################ # MODEL ################################################################################ X_in = Input(shape=(F, ), name='X_in') A_in = Input(shape=(None, ), name='A_in', sparse=True) X_1 = GraphConvSkip(16, activation='elu')([X_in, A_in]) X_1, A_1, S = MinCutPool(n_clusters, return_mask=True)([X_1, A_in]) model = Model([X_in, A_in], [X_1, S])
"rb")) else: print('Computing coarsened Laplacians') A_train, X_train, D_train = preprocess( A_train, X_train, coarsening_levels=P['coarse_level'], pool=P['pool']) A_test, X_test, D_test = preprocess( A_test, X_test, coarsening_levels=P['coarse_level'], pool=P['pool']) L_train = [[normalized_adjacency(a_).astype(np.float32) for a_ in A] for A in A_train] L_test = [[normalized_adjacency(a_).astype(np.float32) for a_ in A] for A in A_test] # save f = open('data/' + P['dataset_ID'] + "_pool_" + P['pool'] + ".pkl", "wb") pickle.dump([ L_train, L_test, D_train, D_test, X_train, X_test, y_train, y_test ], f) f.close() else: L_train = [normalized_adjacency(A_) for A_ in A_train] L_test = [normalized_adjacency(A_) for A_ in A_test]
print('Downloading ' + dataset_name + ' from ' + data_url) req = requests.get(data_url + dataset_name) with open(dataset_name, 'wb') as out_file: out_file.write(req.content) # Load data loaded = np.load(dataset_name, allow_pickle=True) X_train, A_train, y_train = loaded['tr_feat'], list( loaded['tr_adj']), loaded['tr_class'] X_test, A_test, y_test = loaded['te_feat'], list( loaded['te_adj']), loaded['te_class'] X_val, A_val, y_val = loaded['val_feat'], list( loaded['val_adj']), loaded['val_class'] # Preprocessing adjacency matrices for convolution A_train = [normalized_adjacency(a) for a in A_train] A_val = [normalized_adjacency(a) for a in A_val] A_test = [normalized_adjacency(a) for a in A_test] # Parameters F = X_train[0].shape[-1] # Dimension of node features n_out = y_train[0].shape[-1] # Dimension of the target average_N = np.ceil(np.mean([a.shape[-1] for a in A_train ])) # Average number of nodes in dataset ################################################################################ # BUILD MODEL ################################################################################ X_in = Input(tensor=tf.placeholder(tf.float32, shape=(None, F), name='X_in')) A_in = Input(tensor=tf.sparse_placeholder(tf.float32, shape=(None, None)), sparse=True)
loss = sum(model.losses) gradients = tape.gradient(loss, model.trainable_variables) opt.apply_gradients(zip(gradients, model.trainable_variables)) return model.losses[0], model.losses[1], S_pool np.random.seed(1) epochs = 5000 # Training iterations lr = 5e-4 # Learning rate ################################################################################ # LOAD DATASET ################################################################################ dataset = Cora() adj, x, y = dataset[0].a, dataset[0].x, dataset[0].y a_norm = normalized_adjacency(adj) a_norm = sp_matrix_to_sp_tensor(a_norm) F = dataset.n_node_features y = np.argmax(y, axis=-1) n_clusters = y.max() + 1 ################################################################################ # MODEL ################################################################################ x_in = Input(shape=(F, ), name="X_in") a_in = Input(shape=(None, ), name="A_in", sparse=True) x_1 = GCSConv(16, activation="elu")([x_in, a_in]) x_1, a_1, s_1 = MinCutPool(n_clusters, return_selection=True)([x_1, a_in]) model = Model([x_in, a_in], [x_1, s_1])
X_test, A_test, y_test = loaded['te_feat'], list( loaded['te_adj']), loaded['te_class'] X_val, A_val, y_val = loaded['val_feat'], list( loaded['val_adj']), loaded['val_class'] else: raise ValueError # Parameters F = X_train[0].shape[-1] # Dimension of node features n_out = y_train[0].shape[-1] # Dimension of the target average_N = np.ceil(np.mean([a.shape[-1] for a in A_train ])) # Average number of nodes in dataset # Preprocessing adjacency matrices for convolution if P['GNN_type'] == 'GCS' or P['GNN_type'] == 'ARMA': A_train = [normalized_adjacency(a) for a in A_train] A_val = [normalized_adjacency(a) for a in A_val] A_test = [normalized_adjacency(a) for a in A_test] elif P['GNN_type'] == 'GCN': A_train = [ normalized_adjacency(a + sp.eye(a.shape[0])) for a in A_train ] A_val = [ normalized_adjacency(a + sp.eye(a.shape[0])) for a in A_val ] A_test = [ normalized_adjacency(a + sp.eye(a.shape[0])) for a in A_test ] else: raise ValueError('Unknown GNN type: {}'.format(P['GNN_type']))
X_val_A, y_val_A = load('val_ma.npy', allow_pickle=True), load('val_may.npy', allow_pickle=True) X_train_B, A_train_B, y_train_B = load('tr_feat.npy', allow_pickle=True), list( load('tr_adj.npy', allow_pickle=True)), load('tr_class.npy', allow_pickle=True) X_test_B, A_test_B, y_test_B = load('te_feat.npy', allow_pickle=True), list( load('te_adj.npy', allow_pickle=True)), load('te_class.npy', allow_pickle=True) X_val_B, A_val_B, y_val_B = load('val_feat.npy', allow_pickle=True), list( load('val_adj.npy', allow_pickle=True)), load('val_class.npy', allow_pickle=True) # Preprocessing adjacency matrices for convolution A_train_B = [normalized_adjacency(a) for a in A_train_B] A_val_B = [normalized_adjacency(a) for a in A_val_B] A_test_B = [normalized_adjacency(a) for a in A_test_B] # Load pre-trained models model_A = load_model('model_A.h5') model_B = load_model('model_B.h5', custom_objects={ 'GraphConvSkip': GraphConvSkip, 'MinCutPool': MinCutPool, 'GlobalAvgPool': GlobalAvgPool }) # Get the output before last layer of both models model_A = Model(inputs=model_A.inputs, outputs=model_A.layers[-2].output) model_B = Model(inputs=model_B.inputs, outputs=model_B.layers[-2].output)
from spektral.utils.convolution import normalized_adjacency np.random.seed(1) iterations = 5000 # Training iterations gnn_channels = 16 # Units in the GNN layer mlp_channels = None # Units in the MLP of MinCutPool Layer (if None, the MLP has no hidden layers) gnn_activ = 'elu' # Activation for the GNN layer mlp_activ = None # Activation for the hidden layers of MinCutPool lr = 5e-4 # Learning rate ################################################################################ # LOAD DATASET ################################################################################ A, X, y, _, _, _ = citation.load_data('cora') A_norm = normalized_adjacency(A) # Normalize adjacency matrix X = X.todense() n_feat = X.shape[-1] y = np.argmax(y, axis=-1) n_clust = y.max() + 1 ################################################################################ # MODEL ################################################################################ X_in = Input( tensor=tf.placeholder(tf.float32, shape=(None, n_feat), name='X_in')) A_in = Input(tensor=tf.sparse_placeholder(tf.float32, shape=(None, None)), name='A_in', sparse=True) X_1 = GraphConvSkip(gnn_channels,