def _convert_to_sparse_tensor(x):
    if x.ndim == 2:
        return sp_matrix_to_sp_tensor(x)
    elif x.ndim == 3:
        s1_, s2_, s3_ = x.shape
        return ops.reshape(sp_matrix_to_sp_tensor(x.reshape(s1_ * s2_, s3_)),
                           (s1_, s2_, s3_))
def test_modes_ops():
    ns = [10, 5, 8]
    x_list = [np.random.randn(n, 3) for n in ns]
    a_list = [sp.csr_matrix(np.ones((n, n))) for n in ns]

    x, a, i = to_disjoint(x_list, a_list)
    a = sp_matrix_to_sp_tensor(a)

    expected_x = np.zeros((len(ns), max(ns), 3))
    for i_, n in enumerate(ns):
        expected_x[i_, :n] = x_list[i_]

    expected_a = np.zeros((len(ns), max(ns), max(ns)))
    for i_, n in enumerate(ns):
        expected_a[i_, :n, :n] = a_list[i_].A

    # Disjoint signal to batch
    result = ops.disjoint_signal_to_batch(x, i).numpy()

    assert expected_x.shape == result.shape
    assert np.allclose(expected_x, result, atol=tol)

    # Disjoint adjacency to batch
    result = ops.disjoint_adjacency_to_batch(a, i).numpy()

    assert expected_a.shape == result.shape
    assert np.allclose(expected_a, result, atol=tol)
Exemple #3
0
def test_modes_ops():
    X = np.array([[1, 0], [0, 1], [1, 1], [0, 0], [1, 2]])
    I = np.array([0, 0, 0, 1, 1])

    A_data = [1, 1, 1, 1, 1]
    A_row = [0, 1, 2, 3, 4]
    A_col = [1, 0, 1, 4, 3]
    A_sparse = sp.csr_matrix((A_data, (A_row, A_col)), shape=(5, 5))
    A_sparse_tensor = sp_matrix_to_sp_tensor(A_sparse)

    # Disjoint signal to batch
    expected_result = np.array([[[1.0, 0.0], [0.0, 1.0], [1.0, 1.0]],
                                [[0.0, 0.0], [1.0, 2.0], [0.0, 0.0]]])
    result = ops.disjoint_signal_to_batch(X, I).numpy()

    assert expected_result.shape == result.shape
    assert np.allclose(expected_result, result, atol=tol)

    # Disjoint adjacency to batch
    expected_result = np.array([
        [[0.0, 1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]],
        [[0.0, 1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]],
    ])

    result = ops.disjoint_adjacency_to_batch(A_sparse_tensor, I).numpy()

    assert expected_result.shape == result.shape
    assert np.allclose(expected_result, result, atol=tol)
Exemple #4
0
def _get_input_from_dtypes(dtypes, sparse=False):
    assert len(dtypes) >= 2
    x = np.ones((3, 1), dtype=dtypes[0])
    a = np.ones((3, 3), dtype=dtypes[1])
    if sparse:
        a = sp_matrix_to_sp_tensor(a)
    output = [x, a]
    if len(dtypes) > 2:
        e = np.ones((3 * 3, 1), dtype=dtypes[2])
        output.append(e)
    return output
def test_sparse_model_sizes():
    """
    This is a sanity check to make sure we have the same number of operations that we intend to have
    """
    N = 5
    F = 4
    S = 3
    X_in = Input(shape=(F, ), name="X_in")
    A_in = Input(shape=(None, ), name="A_in", sparse=True)
    E_in = Input(shape=(S, ), name="E_in")

    x = np.ones(shape=(N, F))
    a = np.ones(shape=(N, N))
    a = sp_matrix_to_sp_tensor(a)
    e = np.ones(shape=(N * N, S))

    def assert_n_params(inp, out, expected_size):
        model = Model(inputs=inp, outputs=out)
        model.compile(optimizer="adam", loss="mean_squared_error")
        print(model.count_params())
        assert model.count_params() == expected_size
        # for test coverage:
        model([x, a, e])

    X, E = XENetConv([5], 10, 20, False)([X_in, A_in, E_in])
    assert_n_params([X_in, A_in, E_in], [X, E], 350)
    # int vs list: 5 vs [5]
    X, E = XENetConv(5, 10, 20, False)([X_in, A_in, E_in])
    assert_n_params([X_in, A_in, E_in], [X, E], 350)
    # t = (4+4+3+3+1)*5 =  75    # Stack Conv
    # x = (4+5+5+1)*10  = 150    # Node reduce
    # e = (5+1)*20      = 120    # Edge reduce
    # p                 =   5    # Prelu
    # total = t+x+e+p   = 350

    X, E = XENetConv(5, 10, 20, True)([X_in, A_in, E_in])
    assert_n_params([X_in, A_in, E_in], [X, E], 362)
    # t = (4+4+3+3+1)*5 =  75
    # a = (5+1)*1   *2  =  12    # Attention
    # x = (4+5+5+1)*10  = 150
    # e = (5+1)*20      = 120
    # p                 =   5    # Prelu
    # total = t+x+e+p   = 362

    X, E = XENetConv([50, 5], 10, 20, True)([X_in, A_in, E_in])
    assert_n_params([X_in, A_in, E_in], [X, E], 1292)
Exemple #6
0
def _test_disjoint_mode(layer, sparse=False, **kwargs):
    A = sp.block_diag(
        [np.ones((N1, N1)), np.ones((N2, N2)), np.ones((N3, N3))]
    ).todense()
    X = np.random.normal(size=(N, F))
    I = np.array([0] * N1 + [1] * N2 + [2] * N3).astype(int)

    A_in = Input(shape=(None,), sparse=sparse)
    X_in = Input(shape=(F,))
    I_in = Input(shape=(), dtype=tf.int32)
    inputs = [X_in, A_in, I_in]

    if sparse:
        input_data = [X, sp_matrix_to_sp_tensor(A), I]
    else:
        input_data = [X, A, I]

    layer_instance = layer(**kwargs)
    output = layer_instance(inputs)
    model = Model(inputs, output)

    output = model(input_data)

    X_pool, A_pool, I_pool, s = output

    if "ratio" in kwargs.keys():
        N_pool_expected = int(
            np.ceil(kwargs["ratio"] * N1)
            + np.ceil(kwargs["ratio"] * N2)
            + np.ceil(kwargs["ratio"] * N3)
        )
    elif "k" in kwargs.keys():
        N_pool_expected = int(kwargs["k"])
    else:
        N_pool_expected = None
    N_pool_true = A_pool.shape[0]

    if N_pool_expected is not None:
        _check_number_of_nodes(N_pool_expected, N_pool_true)

        assert X_pool.shape == (N_pool_expected, F)
        assert A_pool.shape == (N_pool_expected, N_pool_expected)
        assert I_pool.shape == (N_pool_expected,)

    output_shape = [o.shape for o in output]
    _check_output_and_model_output_shapes(output_shape, model.output_shape)
Exemple #7
0
def _test_single_mode(layer, sparse=False, edges=False, **kwargs):
    A_in = Input(shape=(None, ), sparse=sparse)
    X_in = Input(shape=(F, ))
    inputs = [X_in, A_in]

    if sparse:
        input_data = [X, sp_matrix_to_sp_tensor(A)]
    else:
        input_data = [X, A]

    if edges:
        E_in = Input(shape=(S, ))
        inputs.append(E_in)
        input_data.append(E_single)

    layer_instance = layer(**kwargs)
    output = layer_instance(inputs)
    model = Model(inputs, output)

    output = model(input_data)

    assert output.shape == (N, kwargs["channels"])
def k_hop_sparse_subgraph(a, node_idx, k, transformer=None):
    """
    Computes the subgraph containing all the neighbors of `node_idx` up to the k-th order.
    If `a` is not the binary adjacency matrix a  `transformer` should be passed.
    **Arguments**
    - `a`: sparse `(n_nodes, n_nodes)` graph tensor;
    - `node_idx`: center node;
    - `k`: order of neighbor;
    - `transformer`: one of the functions from the `spektral.transforms` module,
       needed to convert the binary adjacency matrix into the correct format for the model;
    """
    if a.dtype != tf.float32:
        a = tf.cast(a, tf.float32)

    if transformer:
        a = binary_adj_converter(a)

    power_a = tf.sparse.eye(a.shape[0])
    k_neighs = np.zeros(a.shape[0]).astype("float32").reshape(1, -1)
    k_neighs[0, node_idx] = 1

    for _ in range(k - 1):
        power_a = dot(power_a, a)
        temp = tf.sparse.slice(power_a,
                               start=[node_idx, 0],
                               size=[1, power_a.shape[0]])
        k_neighs += tf.sparse.to_dense(temp)

    comp_graph = tf.sparse.add(a * tf.reshape(k_neighs, (-1, 1)), a * k_neighs)
    is_nonzero = tf.not_equal(comp_graph.values, 0)
    comp_graph = tf.sparse.retain(comp_graph, is_nonzero)
    comp_graph = tf.sign(comp_graph)

    if transformer:
        comp_graph = sp_tensor_to_sp_matrix(comp_graph)
        comp_graph = transformer(comp_graph)
        return sp_matrix_to_sp_tensor(comp_graph)
    else:
        return comp_graph
Exemple #9
0
def _test_single_mode(layer, sparse=False, **kwargs):
    A = np.ones((N, N))
    X = np.random.normal(size=(N, F))

    A_in = Input(shape=(None,), sparse=sparse)
    X_in = Input(shape=(F,))
    inputs = [X_in, A_in]

    if sparse:
        input_data = [X, sp_matrix_to_sp_tensor(A)]
    else:
        input_data = [X, A]

    layer_instance = layer(**kwargs)
    output = layer_instance(inputs)
    model = Model(inputs, output)

    output = model(input_data)

    X_pool, A_pool, mask = output
    if "ratio" in kwargs.keys():
        N_exp = kwargs["ratio"] * N
        N_pool_expected = int(np.ceil(N_exp))
    elif "k" in kwargs.keys():
        N_pool_expected = int(kwargs["k"])
    else:
        N_pool_expected = None

    N_pool_true = A_pool.shape[-1]
    assert N_pool_true > 0

    if N_pool_expected is not None:
        _check_number_of_nodes(N_pool_expected, N_pool_true)

        assert X_pool.shape == (N_pool_expected, F)
        assert A_pool.shape == (N_pool_expected, N_pool_expected)

    output_shape = [o.shape for o in output]
    _check_output_and_model_output_shapes(output_shape, model.output_shape)
Exemple #10
0
def test_disjoint_2_batch():
    X = np.array([[1, 0], [0, 1], [1, 1], [0, 0], [1, 2]])
    I = np.array([0, 0, 0, 1, 1])
    A_data = [1, 1, 1, 1, 1]
    A_row = [0, 1, 2, 3, 4]
    A_col = [1, 0, 1, 4, 3]
    A = sp_matrix_to_sp_tensor(sp.csr_matrix((A_data, (A_row, A_col)), shape=(5, 5)))

    expected_X = np.array(
        [[[1.0, 0.0], [0.0, 1.0], [1.0, 1.0]], [[0.0, 0.0], [1.0, 2.0], [0.0, 0.0]]]
    )
    expected_A = np.array(
        [
            [[0.0, 1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]],
            [[0.0, 1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]],
        ]
    )

    result_X, result_A = layers.Disjoint2Batch()((X, A, I))
    assert np.allclose(result_A, expected_A, atol=tol)
    assert np.allclose(result_X, expected_X, atol=tol)

    _test_get_config(layers.Disjoint2Batch)
Exemple #11
0
def _test_mixed_mode(layer, sparse=False, edges=False, **kwargs):
    X_batch = np.stack([X] * batch_size)
    A_in = Input(shape=(N, ), sparse=sparse)
    X_in = Input(shape=(N, F))
    inputs = [X_in, A_in]

    if sparse:
        input_data = [X_batch, sp_matrix_to_sp_tensor(A)]
    else:
        input_data = [X_batch, A]

    if edges:
        E_in = Input(shape=(N * N, S))
        inputs.append(E_in)
        E_batch = np.stack([E_single] * batch_size)
        input_data.append(E_batch)

    layer_instance = layer(**kwargs)
    output = layer_instance(inputs)
    model = Model(inputs, output)

    output = model(input_data)

    assert output.shape == (batch_size, N, kwargs["channels"])
Exemple #12
0
    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])
Exemple #13
0
from spektral.layers import GCNConv, GlobalSumPool
from spektral.utils.sparse import sp_matrix_to_sp_tensor

# Parameters
batch_size = 32  # Batch size
epochs = 1000  # Number of training epochs
patience = 10  # Patience for early stopping
l2_reg = 5e-4  # Regularization rate for l2

# Load data
data = MNIST()

# The adjacency matrix is stored as an attribute of the dataset.
# Create filter for GCN and convert to sparse tensor.
data.a = GCNConv.preprocess(data.a)
data.a = sp_matrix_to_sp_tensor(data.a)

# Train/valid/test split
data_tr, data_te = data[:-10000], data[-10000:]
np.random.shuffle(data_tr)
data_tr, data_va = data_tr[:-10000], data_tr[-10000:]

# We use a MixedLoader since the dataset is in mixed mode
loader_tr = MixedLoader(data_tr, batch_size=batch_size, epochs=epochs)
loader_va = MixedLoader(data_va, batch_size=batch_size)
loader_te = MixedLoader(data_te, batch_size=batch_size)


# Build model
class Net(Model):
    def __init__(self, **kwargs):
Exemple #14
0
def sp_matrices_to_sp_tensors(inputs):
    inputs = list(inputs)
    for i in range(len(inputs)):
        if sp.issparse(inputs[i]):
            inputs[i] = sp_matrix_to_sp_tensor(inputs[i])
    return tuple(inputs)
    def __call__(self, graph):
        if graph.a is not None:
            graph.a = sp_matrix_to_sp_tensor(graph.a)

        return graph