Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'GATConv' object is not callable #438

Open
slhilyfe opened this issue Jul 18, 2023 · 0 comments
Open

'GATConv' object is not callable #438

slhilyfe opened this issue Jul 18, 2023 · 0 comments

Comments

@slhilyfe
Copy link

My spektral is version 1.3.0 and my tensorflow is version 2.10.0. I want to make a model of the integration of space and time. The use of convolution layer in the new version of spektral has changed a lot, but there are a few questions I would like to consult with experts.

  1. I think there is no way to call it using the GraphConv layer. I customized it, and I don't know if it is correct:
    class GraphConvLayer(Layer):
    def init(self, **kwargs):
    super(GraphConvLayer, self).init(**kwargs)
    def call(self, inputs, **kwargs):
    A, X = inputs
    return tf.einsum('bji,bjk->bik', A, X) # Change the positions of the adjacency matrix and the feature matrix
    def compute_output_shape(self, input_shape):
    return input_shape[1]
  2. The "# Create a GATConv layer gat_conv = GATConv (64, activation='relu') ([graph_conv_layer2, graph_input_layer]) " section of my code always shows" 'GATConv' object is not callable ". I've tried a lot of methods but haven't solved it. This is my code for defining the structure of the model:

Build adjacency matrix

sigma = 10.0 # This is a hyperparameter, you might need to tune it.
A = build_adjacency_matrix(stations_info, sigma)
A = A.squeeze() # Remove unnecessary dimensions

Normalize adjacency matrix

A = spektral.utils.normalized_adjacency(A, symmetric=True)
print(A.shape)

Convert the normalized adjacency matrix into a tensor

tensor_A = tf.convert_to_tensor(A, dtype=tf.float32)
print(tensor_A.shape)

copy the tensor_A to match the training set and test set, because each time step requires a tensor_A

tensor_A_train = np.repeat(tensor_A[np.newaxis, ...], X_train.shape[0], axis=0)
tensor_A_test = np.repeat(tensor_A[np.newaxis, ...], X_test.shape[0], axis=0)
print('X_train shape:', X_train.shape)
print('y_train shape:', y_train.shape)
print('tensor_A_train shape:', tensor_A_train.shape)

Define the model

input_layer = Input(shape=X_train.shape[1:])
graph_input_layer = Input(shape=tensor_A_train.shape[1:], name="graph_input")
print('graph_input_layer:', graph_input_layer.shape)

spatial information

graph_conv_layer = GraphConvLayer()([input_layer, graph_input_layer])
graph_conv_layer = tf.transpose(graph_conv_layer, perm=[0, 2, 1])
print('graph_conv_layer:', graph_conv_layer.shape)

Add a second graph convolution layer to try deeper spatial feature extraction

graph_conv_layer2 = GraphConvLayer()([graph_conv_layer, graph_input_layer])
graph_conv_layer2 = tf.transpose(graph_conv_layer2, perm=[0, 2, 1])
print('graph_conv_layer2:', graph_conv_layer2.shape)

Create a GATConv layer

gat_conv = GATConv(64, activation='relu')([graph_conv_layer2, graph_input_layer])
print(type(gat_conv))

temporal information

multihead_attn = MultiHeadAttention(num_heads=8, key_dim=64)
attn_output = multihead_attn(input_layer, input_layer)
attn_output = LayerNormalization(epsilon=1e-6)(attn_output)

add a second long attention layer to try deeper time feature extraction

multihead_attn2 = MultiHeadAttention(num_heads=8, key_dim=64)
attn_output2 = multihead_attn2(attn_output, attn_output)
attn_output2 = LayerNormalization(epsilon=1e-6)(attn_output2)
lstm = LSTM(64, return_sequences=False, input_shape=(num_timesteps, num_features + 2))(attn_output2)

lstm = Dense(64, activation='relu')(lstm) # New layer to adjust LSTM output shape

Combine spatial and temporal information

lstm_repeated = tf.keras.layers.RepeatVector(131)(lstm) # Shape: (None, 131, 64)
combined_features = Concatenate()([gat_conv, lstm_repeated]) # Shape: (None, 131, 128)

Decoding layer

dense = Dense(64, activation='relu')(combined_features)
output_layer = Dense(1, activation='linear')(dense)

Create and compile the model

model = Model(inputs=[input_layer, graph_input_layer], outputs=output_layer)
model.compile(optimizer=adam_v2.Adam(learning_rate=0.001), loss='mse')

early_stop = EarlyStopping(monitor='val_loss', patience=10)

train the model

model.fit([X_train, tensor_A_train], y_train, epochs=100, batch_size=32, validation_data=([X_test, tensor_A_test], y_test))

Thank you very much for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant