diff --git a/kgcnn/data/base.py b/kgcnn/data/base.py index 706ea920..2cd302bb 100644 --- a/kgcnn/data/base.py +++ b/kgcnn/data/base.py @@ -3,6 +3,7 @@ import pandas as pd import os from sklearn.model_selection import KFold +from kgcnn.io.loader import experimental_tf_disjoint_list_generator # import typing as t from typing import Union, List, Callable, Dict, Optional # from collections.abc import MutableSequence @@ -328,6 +329,10 @@ def rename_property_on_graphs(self, old_property_name: str, new_property_name: s set = assign_property get = obtain_property + def tf_disjoint_data_generator(self, inputs, outputs, **kwargs): + module_logger.info("Dataloader is experimental and not fully tested nor stable.") + return experimental_tf_disjoint_list_generator(self, inputs=inputs, outputs=outputs, **kwargs) + class MemoryGraphDataset(MemoryGraphList): r"""Dataset class for lists of graph tensor dictionaries stored on file and fit into memory. diff --git a/kgcnn/io/loader.py b/kgcnn/io/loader.py index e69de29b..c0c67f43 100644 --- a/kgcnn/io/loader.py +++ b/kgcnn/io/loader.py @@ -0,0 +1,92 @@ +import keras_core as ks +import numpy as np +import tensorflow as tf + + +def experimental_tf_disjoint_list_generator(graphs, + inputs, + outputs, + has_nodes=True, + has_edges=True, + has_graph_state=False, + batch_size=32, + shuffle=True): + def generator(): + dataset_size = len(graphs) + data_index = np.arange(dataset_size) + + if shuffle: + np.random.shuffle(data_index) + + for batch_index in range(0, dataset_size, batch_size): + idx = data_index[batch_index:batch_index + batch_size] + graphs_batch = [graphs[i] for i in idx] + + batch_id_node, batch_id_edge, node_id, edge_id, count_nodes, count_edges = [None for _ in range(6)] + out = [] + inputs_pos = 0 + for j in range(int(has_nodes)): + array_list = [x[inputs[inputs_pos]["name"]] for x in graphs_batch] + out.append(np.concatenate(array_list, axis=0)) + inputs_pos += 1 + if j == 0: + count_nodes = np.array([len(x) for x in array_list], dtype="int64") + batch_id_node = np.repeat(np.arange(len(array_list), dtype="int64"), repeats=count_nodes) + node_id = np.concatenate([np.arange(x, dtype="int64") for x in count_nodes], axis=0) + + for j in range(int(has_edges)): + array_list = [x[inputs[inputs_pos]["name"]] for x in graphs_batch] + out.append(np.concatenate(array_list, axis=0, dtype=inputs[inputs_pos]["dtype"])) + inputs_pos += 1 + + for j in range(int(has_graph_state)): + array_list = [x[inputs[inputs_pos]["name"]] for x in graphs_batch] + out.append(np.array(array_list, dtype=inputs[inputs_pos]["dtype"])) + inputs_pos += 1 + + # Indices + array_list = [x[inputs[inputs_pos]["name"]] for x in graphs_batch] + count_edges = np.array([len(x) for x in array_list], dtype="int64") + batch_id_edge = np.repeat(np.arange(len(array_list), dtype="int64"), repeats=count_edges) + edge_id = np.concatenate([np.arange(x, dtype="int64") for x in count_edges], axis=0) + edge_indices_flatten = np.concatenate(array_list, axis=0) + + node_splits = np.pad(np.cumsum(count_nodes), [[1, 0]]) + offset_edge_indices = np.expand_dims(np.repeat(node_splits[:-1], count_edges), axis=-1) + disjoint_indices = edge_indices_flatten + offset_edge_indices + disjoint_indices = np.transpose(disjoint_indices) + out.append(disjoint_indices) + + out = out + [batch_id_node, batch_id_edge, node_id, edge_id, count_nodes, count_edges] + + if isinstance(outputs, list): + out_y = [] + for k in range(len(outputs)): + array_list = [x[outputs[k]["name"]] for x in graphs_batch] + out_y.append(np.array(array_list, dtype=outputs[k]["dtype"])) + elif isinstance(outputs, dict): + out_y = np.array( + [x[outputs["name"]] for x in graphs_batch], dtype=outputs["dtype"]) + else: + raise ValueError() + + yield tuple(out), out_y + + input_spec = tuple([tf.TensorSpec(shape=tuple([None] + list(x["shape"])), dtype=x["dtype"]) for x in inputs]) + + if isinstance(outputs, list): + output_spec = tuple([tf.TensorSpec(shape=tuple([None] + list(x["shape"])), dtype=x["dtype"]) for x in outputs]) + elif isinstance(outputs, dict): + output_spec = tf.TensorSpec(shape=tuple([None] + list(outputs["shape"])), dtype=outputs["dtype"]) + else: + raise ValueError() + + data_loader = tf.data.Dataset.from_generator( + generator, + output_signature=( + input_spec, + output_spec + ) + ) + + return data_loader diff --git a/kgcnn/literature/GIN/_make.py b/kgcnn/literature/GIN/_make.py index 1fa32882..63fa9bb0 100644 --- a/kgcnn/literature/GIN/_make.py +++ b/kgcnn/literature/GIN/_make.py @@ -34,7 +34,7 @@ {"shape": (), "name": "total_edges", "dtype": "int64"} ], "input_tensor_type": "padded", - "cast_disjoint_kwargs": {"padded_disjoint": False}, + "cast_disjoint_kwargs": {}, "input_embedding": None, # deprecated "input_node_embedding": {"input_dim": 95, "output_dim": 64}, "gin_mlp": {"units": [64, 64], "use_bias": True, "activation": ["relu", "linear"], @@ -245,7 +245,8 @@ def make_model_edge(inputs: list = None, # Wrapping disjoint model. out = model_disjoint_edge( [n, ed, disjoint_indices, batch_id_node, count_nodes], - use_node_embedding=len(inputs[0]['shape']) < 2, use_edge_embedding=len(inputs[1]['shape']) < 2, + use_node_embedding="float" not in inputs[0]['dtype'], + use_edge_embedding="float" not in inputs[1]['dtype'], input_node_embedding=input_node_embedding, input_edge_embedding=input_edge_embedding, depth=depth, gin_args=gin_args, gin_mlp=gin_mlp, last_mlp=last_mlp, dropout=dropout, output_embedding=output_embedding, output_mlp=output_mlp diff --git a/kgcnn/models/casting.py b/kgcnn/models/casting.py index e3d80fc5..538aab9d 100644 --- a/kgcnn/models/casting.py +++ b/kgcnn/models/casting.py @@ -17,17 +17,28 @@ def template_cast_output(model_outputs, out = CastDisjointToBatchedGraphState(**cast_disjoint_kwargs)(out) elif output_embedding == 'node': if output_tensor_type in ["padded", "masked"]: - if input_tensor_type in ["padded", "masked"]: - if "static_batched_node_output_shape" in cast_disjoint_kwargs: - out_node_shape = cast_disjoint_kwargs["static_batched_node_output_shape"] - else: - out_node_shape = None - out = CastDisjointToBatchedAttributes(static_output_shape=out_node_shape, **cast_disjoint_kwargs)( - [out, batch_id_node, node_id, count_nodes]) + if "static_batched_node_output_shape" in cast_disjoint_kwargs: + out_node_shape = cast_disjoint_kwargs["static_batched_node_output_shape"] + else: + out_node_shape = None + out = CastDisjointToBatchedAttributes(static_output_shape=out_node_shape, **cast_disjoint_kwargs)( + [out, batch_id_node, node_id, count_nodes]) if output_tensor_type in ["ragged", "jagged"]: out = CastDisjointToRaggedAttributes()([out, batch_id_node, node_id, count_nodes]) else: out = CastDisjointToBatchedGraphState(**cast_disjoint_kwargs)(out) + elif output_embedding == 'edge': + if output_tensor_type in ["padded", "masked"]: + if "static_batched_edge_output_shape" in cast_disjoint_kwargs: + out_edge_shape = cast_disjoint_kwargs["static_batched_edge_output_shape"] + else: + out_edge_shape = None + out = CastDisjointToBatchedAttributes(static_output_shape=out_edge_shape, **cast_disjoint_kwargs)( + [out, batch_id_edge, edge_id, count_edges]) + if output_tensor_type in ["ragged", "jagged"]: + out = CastDisjointToRaggedAttributes()([out, batch_id_edge, edge_id, count_edges]) + else: + out = CastDisjointToBatchedGraphState(**cast_disjoint_kwargs)(out) else: raise NotImplementedError() diff --git a/notebooks/tutorial_model_loading_options.ipynb b/notebooks/tutorial_model_loading_options.ipynb index 9cc4467a..bb4337e4 100644 --- a/notebooks/tutorial_model_loading_options.ipynb +++ b/notebooks/tutorial_model_loading_options.ipynb @@ -13,7 +13,7 @@ { "cell_type": "code", "execution_count": 1, - "id": "3cf55e2e", + "id": "d2fa79c2-94ec-4322-b76d-1413d9e63655", "metadata": {}, "outputs": [ { @@ -24,9 +24,62 @@ ] } ], + "source": [ + "import keras_core as ks" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "3cf55e2e", + "metadata": {}, + "outputs": [], "source": [ "import numpy as np\n", - "from kgcnn.literature.GIN import make_model" + "from kgcnn.literature.GIN import make_model_edge as make_model\n", + "from kgcnn.utils.plots import plot_train_test_loss" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0b0805d7-d3ad-46ae-9f62-d6991eadda5d", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "ERROR:kgcnn.molecule.convert:Can not import `OpenBabel` package for conversion.\n", + "INFO:kgcnn.data.download:Checking and possibly downloading dataset with name FreeSolv\n", + "INFO:kgcnn.data.download:Dataset directory located at C:\\Users\\patri\\.kgcnn\\datasets\n", + "INFO:kgcnn.data.download:Dataset directory found. Done.\n", + "INFO:kgcnn.data.download:Dataset found. Done.\n", + "INFO:kgcnn.data.FreeSolv:Found SDF C:\\Users\\patri\\.kgcnn\\datasets\\FreeSolv\\SAMPL.sdf of pre-computed structures.\n", + "INFO:kgcnn.data.FreeSolv:Read molecules from mol-file.\n", + "INFO:kgcnn.data.FreeSolv: ... process molecules 0 from 642\n", + "INFO:kgcnn.molecule.encoder:OneHotEncoder Symbol found ['C', 'N', 'O', 'S', 'Cl', 'Br', 'P', 'F', 'I']\n", + "INFO:kgcnn.molecule.encoder:OneHotEncoder Hybridization found [rdkit.Chem.rdchem.HybridizationType.SP3, rdkit.Chem.rdchem.HybridizationType.SP2, rdkit.Chem.rdchem.HybridizationType.SP]\n", + "INFO:kgcnn.molecule.encoder:OneHotEncoder TotalDegree found [4, 3, 1, 2]\n", + "INFO:kgcnn.molecule.encoder:OneHotEncoder TotalNumHs found [3, 0, 1, 2, 4]\n", + "INFO:kgcnn.molecule.encoder:OneHotEncoder CIPCode found [None, 'S', 'R']\n", + "INFO:kgcnn.molecule.encoder:OneHotEncoder ChiralityPossible found [None, '1']\n", + "INFO:kgcnn.molecule.encoder:OneHotEncoder BondType found [rdkit.Chem.rdchem.BondType.SINGLE, rdkit.Chem.rdchem.BondType.DOUBLE, rdkit.Chem.rdchem.BondType.AROMATIC, rdkit.Chem.rdchem.BondType.TRIPLE]\n", + "INFO:kgcnn.molecule.encoder:OneHotEncoder Stereo found [rdkit.Chem.rdchem.BondStereo.STEREONONE, rdkit.Chem.rdchem.BondStereo.STEREOZ, rdkit.Chem.rdchem.BondStereo.STEREOE]\n" + ] + } + ], + "source": [ + "from kgcnn.data.datasets.FreeSolvDataset import FreeSolvDataset\n", + "dataset = FreeSolvDataset()" + ] + }, + { + "cell_type": "markdown", + "id": "cd215151-e850-4934-a6d4-83bd982700b4", + "metadata": {}, + "source": [ + "## 1. Padded tensor" ] }, { @@ -37,10 +90,11 @@ "outputs": [], "source": [ "inputs = [\n", - " {\"shape\": (None,), \"name\": \"node_number\", \"dtype\": \"int64\"},\n", + " {\"shape\": (None, 41), \"name\": \"node_attributes\", \"dtype\": \"float32\"},\n", + " {\"shape\": (None, 11), \"name\": \"edge_attributes\", \"dtype\": \"float32\"},\n", " {\"shape\": (None, 2), \"name\": \"edge_indices\", \"dtype\": \"int64\"},\n", - " {\"shape\": (), \"name\": \"total_nodes\", \"dtype\": \"int64\"},\n", - " {\"shape\": (), \"name\": \"total_edges\", \"dtype\": \"int64\"},\n", + " {\"shape\": (), \"name\": \"total_nodes\", \"dtype\": \"int64\"}, # Or mask\n", + " {\"shape\": (), \"name\": \"total_edges\", \"dtype\": \"int64\"}, # Or mask\n", "]\n", "outputs = {\"shape\": (1, ), \"name\": \"graph_labels\", \"dtype\": \"float32\"}" ] @@ -55,13 +109,14 @@ "name": "stderr", "output_type": "stream", "text": [ - "INFO:kgcnn.models.utils:Updated model kwargs: '{'name': 'GIN', 'inputs': [{'shape': (None,), 'name': 'node_number', 'dtype': 'int64'}, {'shape': (None, 2), 'name': 'edge_indices', 'dtype': 'int64'}, {'shape': (), 'name': 'total_nodes', 'dtype': 'int64'}, {'shape': (), 'name': 'total_edges', 'dtype': 'int64'}], 'cast_disjoint_kwargs': {'padded_disjoint': False}, 'input_node_embedding': {'input_dim': 95, 'output_dim': 64}, 'gin_mlp': {'units': [64, 64], 'use_bias': True, 'activation': ['relu', 'linear'], 'use_normalization': True, 'normalization_technique': 'graph_batch', 'padded_disjoint': False}, 'gin_args': {}, 'depth': 3, 'dropout': 0.0, 'verbose': 10, 'last_mlp': {'use_bias': [True, True, True], 'units': [64, 64, 64], 'activation': ['relu', 'relu', 'linear']}, 'output_embedding': 'graph', 'output_to_tensor': True, 'output_mlp': {'units': 1, 'activation': 'linear'}}'.\n" + "INFO:kgcnn.models.utils:Updated model kwargs: '{'name': 'GINE', 'inputs': [{'shape': (None, 41), 'name': 'node_attributes', 'dtype': 'float32'}, {'shape': (None, 11), 'name': 'edge_attributes', 'dtype': 'float32'}, {'shape': (None, 2), 'name': 'edge_indices', 'dtype': 'int64'}, {'shape': (), 'name': 'total_nodes', 'dtype': 'int64'}, {'shape': (), 'name': 'total_edges', 'dtype': 'int64'}], 'input_tensor_type': 'padded', 'cast_disjoint_kwargs': {}, 'input_embedding': None, 'input_node_embedding': {'input_dim': 95, 'output_dim': 64}, 'input_edge_embedding': {'input_dim': 5, 'output_dim': 64}, 'gin_mlp': {'units': [64, 64], 'use_bias': True, 'activation': ['relu', 'linear'], 'use_normalization': True, 'normalization_technique': 'graph_batch'}, 'gin_args': {'epsilon_learnable': False}, 'depth': 3, 'dropout': 0.0, 'verbose': 10, 'last_mlp': {'use_bias': [True, True, True], 'units': [64, 64, 64], 'activation': ['relu', 'relu', 'linear']}, 'output_embedding': 'graph', 'output_to_tensor': True, 'output_tensor_type': 'padded', 'output_mlp': {'units': 1, 'activation': 'linear'}}'.\n" ] } ], "source": [ "model = make_model(\n", " inputs=inputs,\n", + " input_tensor_type=\"padded\",\n", " output_mlp={\"units\": 1, \"activation\": \"linear\"}\n", ")\n", "model.compile(loss=\"mean_absolute_error\")" @@ -69,9 +124,256 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "f3238f5b-4d07-4ec5-aa0d-f4ff4494d32c", "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:kgcnn.data.FreeSolv:Property 'edge_attributes' is an empty list for graph '61'.\n", + "INFO:kgcnn.data.FreeSolv:Property 'edge_attributes' is an empty list for graph '195'.\n", + "INFO:kgcnn.data.FreeSolv:Property 'edge_attributes' is an empty list for graph '286'.\n", + "INFO:kgcnn.data.FreeSolv:Property 'edge_indices' is an empty list for graph '61'.\n", + "INFO:kgcnn.data.FreeSolv:Property 'edge_indices' is an empty list for graph '195'.\n", + "INFO:kgcnn.data.FreeSolv:Property 'edge_indices' is an empty list for graph '286'.\n", + "WARNING:kgcnn.data.FreeSolv:Found invalid graphs for properties. Removing graphs '[286 195 61]'.\n" + ] + } + ], + "source": [ + "dataset.map_list(method=\"count_nodes_and_edges\")\n", + "dataset.clean(inputs)\n", + "for i in range(len(dataset)):\n", + " dataset[i][\"graph_labels\"] = np.expand_dims(dataset[i][\"graph_labels\"], axis=-1)\n", + "x_train = dataset.tensor(inputs)\n", + "y_train = dataset.tensor(outputs)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "b28c133c-e66c-4c11-9c69-a9b51c7718e4", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAioAAAHHCAYAAACRAnNyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABO0klEQVR4nO3dd3hUVf4G8PdOTe+dVBJI6B0MqKCggIgiWFDUgO7aYIW1rdiFn4K666qrS1kRG4rgCiICLtIUpYQSOiGhJIE00uvUe35/hIzG9DZ3kryf58k+zJ07M9+5Knn3nO85VxJCCBARERE5IJXSBRARERHVh0GFiIiIHBaDChERETksBhUiIiJyWAwqRERE5LAYVIiIiMhhMagQERGRw2JQISIiIofFoEJEREQOi0GFqJObOXMmIiMjW/TaV155BZIktW1BXdhbb72F7t27Q61WY+DAgUqXQ9QhMKgQKSwzMxOvvPIKkpKSlC6F2tH//vc/PPPMMxg1ahRWrlyJ119/XemSiDoEiff6IVLWgQMHMGzYMKxcuRIzZ85s8/c3m82QZRl6vb7Zr7VYLLBYLHBycmrzurqaZ599Fm+99RYqKyuh0+mULoeow+CIClEHU1FR0azztVpti0IKAGg0mk4bUiwWC0wmk90+Lzc3F87Ozm0WUoQQqKysbJP3InJkDCpECtq5cyeGDRsGAJg1axYkSYIkSfj4448BAGPGjEHfvn1x8OBBXHvttXBxccFzzz0HAPj2228xadIkhISEQK/XIzo6GgsXLoTVaq3xGX/sUblw4QIkScLf//53LF++HNHR0dDr9Rg2bBgSExNrvLauHhVJkjBnzhysX78effv2hV6vR58+fbBly5Y6v9/QoUPh5OSE6OhoLFu2rFl9L/v27cNNN90Eb29vuLq6on///nj33Xdtz48ZMwZjxoyp9bqGvvM777xj+86HDx+GRqPBq6++Wus9kpOTIUkS3n//fduxoqIizJs3D2FhYdDr9YiJicEbb7wBWZYb/B6SJGHlypUoLy+v9c/YYrFg4cKFtpoiIyPx3HPPwWg01niPyMhI3Hzzzfjhhx8wdOhQODs7Y9myZU24ikQdm0bpAoi6sl69emHBggV46aWX8NBDD+Gaa64BAIwcOdJ2Tn5+PiZOnIjp06fj3nvvRWBgIADg448/hpubG5544gm4ublh+/bteOmll1BSUoK33nqr0c/+4osvUFpaiocffhiSJOHNN9/E1KlTce7cOWi12gZfu3v3bnzzzTd47LHH4O7ujvfeew/Tpk1Deno6fH19AQCHDx/GhAkTEBwcjFdffRVWqxULFiyAv79/k67N1q1bcfPNNyM4OBhz585FUFAQTp06hY0bN2Lu3LlNeo8/WrlyJQwGAx566CHo9XoEBwdj9OjRWLNmDV5++eUa53711VdQq9W44447AFSNZI0ePRqXLl3Cww8/jPDwcPz666+YP38+srKy8M4779T7uZ999hmWL1+O/fv348MPPwTw2z/jP/3pT/jkk09w++2348knn8S+ffuwaNEinDp1CuvWravxPsnJybj77rvx8MMP489//jNiY2NbdB2IOhRBRIpKTEwUAMTKlStrPTd69GgBQCxdurTWcxUVFbWOPfzww8LFxUUYDAbbsYSEBBEREWF7fP78eQFA+Pr6ioKCAtvxb7/9VgAQ3333ne3Yyy+/LP741wQAodPpRGpqqu3YkSNHBADxr3/9y3Zs8uTJwsXFRVy6dMl2LCUlRWg0mlrv+UcWi0VERUWJiIgIUVhYWOM5WZZtfx49erQYPXp0rdfX9509PDxEbm5ujXOXLVsmAIhjx47VON67d29x/fXX2x4vXLhQuLq6ijNnztQ479lnnxVqtVqkp6c3+J0SEhKEq6trjWNJSUkCgPjTn/5U4/hTTz0lAIjt27fbjkVERAgAYsuWLQ1+DlFnw6kfIgen1+sxa9asWsednZ1tfy4tLUVeXh6uueYaVFRU4PTp042+71133QVvb2/b4+rRnHPnzjX62nHjxiE6Otr2uH///vDw8LC91mq14scff8SUKVMQEhJiOy8mJgYTJ05s9P0PHz6M8+fPY968efDy8qrxXGuWS0+bNq3WiM7UqVOh0Wjw1Vdf2Y4dP34cJ0+exF133WU7tnbtWlxzzTXw9vZGXl6e7WfcuHGwWq346aefml3Ppk2bAABPPPFEjeNPPvkkAOD777+vcTwqKgrjx49v9ucQdWSc+iFycN26dauzAfPEiRN44YUXsH37dpSUlNR4rri4uNH3DQ8Pr/G4OrQUFhY2+7XVr69+bW5uLiorKxETE1PrvLqO/dHZs2cBAH379m303OaIioqqdczPzw9jx47FmjVrsHDhQgBV0z4ajQZTp061nZeSkoKj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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.45021405816078186\n" + ] + } + ], + "source": [ + "hist = model.fit(x_train, y_train, epochs=100, verbose=0)\n", + "plot_train_test_loss([hist]);\n", + "print(hist.history[\"loss\"][-1])" + ] + }, + { + "cell_type": "markdown", + "id": "27450862-dcaf-43fc-886d-9644dc748c48", + "metadata": {}, + "source": [ + "## 2. Ragged tensor" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "5d4cfe30-d9b1-437e-a8a1-763c70a359e7", + "metadata": {}, + "outputs": [], + "source": [ + "inputs = [\n", + " {\"shape\": (None, 41), \"name\": \"node_attributes\", \"dtype\": \"float32\", \"ragged\": True},\n", + " {\"shape\": (None, 11), \"name\": \"edge_attributes\", \"dtype\": \"float32\", \"ragged\": True},\n", + " {\"shape\": (None, 2), \"name\": \"edge_indices\", \"dtype\": \"int64\", \"ragged\": True},\n", + "]\n", + "outputs = {\"shape\": (1, ), \"name\": \"graph_labels\", \"dtype\": \"float32\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "054b5d5b-c31a-4156-8018-3a93d3ee7f72", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:kgcnn.models.utils:Updated model kwargs: '{'name': 'GINE', 'inputs': [{'shape': (None, 41), 'name': 'node_attributes', 'dtype': 'float32', 'ragged': True}, {'shape': (None, 11), 'name': 'edge_attributes', 'dtype': 'float32', 'ragged': True}, {'shape': (None, 2), 'name': 'edge_indices', 'dtype': 'int64', 'ragged': True}], 'input_tensor_type': 'ragged', 'cast_disjoint_kwargs': {}, 'input_embedding': None, 'input_node_embedding': {'input_dim': 95, 'output_dim': 64}, 'input_edge_embedding': {'input_dim': 5, 'output_dim': 64}, 'gin_mlp': {'units': [64, 64], 'use_bias': True, 'activation': ['relu', 'linear'], 'use_normalization': True, 'normalization_technique': 'graph_batch'}, 'gin_args': {'epsilon_learnable': False}, 'depth': 3, 'dropout': 0.0, 'verbose': 10, 'last_mlp': {'use_bias': [True, True, True], 'units': [64, 64, 64], 'activation': ['relu', 'relu', 'linear']}, 'output_embedding': 'graph', 'output_to_tensor': True, 'output_tensor_type': 'padded', 'output_mlp': {'units': 1, 'activation': 'linear'}}'.\n" + ] + } + ], + "source": [ + "model = make_model(\n", + " inputs=inputs,\n", + " input_tensor_type=\"ragged\",\n", + " output_mlp={\"units\": 1, \"activation\": \"linear\"}\n", + ")\n", + "model.compile(loss=\"mean_absolute_error\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "98814b19-8e09-448e-94f1-4e4b1408ea4a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "x_train = dataset.tensor(inputs)\n", + "print(type(x_train[0]))\n", + "y_train = dataset.tensor(outputs)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "9a959744-4e7a-4d06-ab99-70cbdc09fe63", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAioAAAHHCAYAAACRAnNyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABQEUlEQVR4nO3dd3hUZdoG8PtMzaT3BmkkgUAgSJcmKChdEWwsusBaEV1YdVWslFWwrOu67qKoC+qCCH6KqCCiCIjSS+gQIA2SkN6Taef9/hgyEtLbnEm4f9c11zJnzpx55izL3PtWSQghQEREROSEVEoXQERERFQXBhUiIiJyWgwqRERE5LQYVIiIiMhpMagQERGR02JQISIiIqfFoEJEREROi0GFiIiInBaDChERETktBhWiDm7mzJmIjIxs1nsXLFgASZJat6Br2BtvvIEuXbpArVbjuuuuU7oconaBQYVIYRkZGViwYAEOHz6sdCnUhn744Qc8/fTTGDp0KFasWIFXX31V6ZKI2gWJe/0QKWv//v0YMGAAVqxYgZkzZ7b69c1mM2RZhl6vb/J7LRYLLBYLXFxcWr2ua82zzz6LN954AxUVFdDpdEqXQ9RusEWFqJ0pLy9v0vlarbZZIQUANBpNhw0pFosFJpPJYZ+XnZ0Ng8HQaiFFCIGKiopWuRaRM2NQIVLQtm3bMGDAAADArFmzIEkSJEnCypUrAQAjR45Ez549ceDAAdxwww1wdXXFc889BwD4+uuvMWHCBISGhkKv1yM6OhqLFy+G1Wqt9hlXj1FJSUmBJEl48803sXz5ckRHR0Ov12PAgAHYt29ftffWNkZFkiQ89thjWL9+PXr27Am9Xo/4+Hh8//33tX6//v37w8XFBdHR0Xj//febNO5lz549GD9+PHx8fODm5oaEhAT885//tL8+cuRIjBw5ssb76vvOb7/9tv07Hzp0CBqNBgsXLqxxjdOnT0OSJLz77rv2Y4WFhZg3bx7CwsKg1+sRExOD1157DbIs1/s9JEnCihUrUFZWVuO/Y4vFgsWLF9trioyMxHPPPQej0VjtGpGRkZg4cSI2b96M/v37w2Aw4P3332/EXSRq3zRKF0B0LevevTsWLVqEl156CQ899BCGDx8OABgyZIj9nLy8PIwbNw733HMP7r33XgQFBQEAVq5cCXd3dzzxxBNwd3fH1q1b8dJLL6G4uBhvvPFGg5+9evVqlJSU4OGHH4YkSXj99dcxZcoUnD9/Hlqttt737ty5E19++SUeffRReHh44J133sHUqVORlpYGPz8/AMChQ4cwduxYhISEYOHChbBarVi0aBECAgIadW+2bNmCiRMnIiQkBHPnzkVwcDBOnjyJb7/9FnPnzm3UNa62YsUKVFZW4qGHHoJer0dISAhGjBiBtWvX4uWXX6527ueffw61Wo0777wTgK0la8SIEbh48SIefvhhhIeH47fffsP8+fORmZmJt99+u87P/fTTT7F8+XLs3bsXH374IYDf/zt+4IEH8PHHH+OOO+7Ak08+iT179mDJkiU4efIkvvrqq2rXOX36NKZNm4aHH34YDz74ILp169as+0DUrggiUtS+ffsEALFixYoar40YMUIAEO+9916N18rLy2sce/jhh4Wrq6uorKy0H5sxY4aIiIiwP09OThYAhJ+fn8jPz7cf//rrrwUA8c0339iPvfzyy+LqfyYACJ1OJ86ePWs/lpiYKACIf/3rX/ZjkyZNEq6uruLixYv2Y0lJSUKj0dS45tUsFouIiooSERERoqCgoNprsizb/zxixAgxYsSIGu+v6zt7enqK7Ozsaue+//77AoA4evRoteM9evQQN910k/354sWLhZubmzhz5ky185599lmhVqtFWlpavd9pxowZws3Nrdqxw4cPCwDigQceqHb8qaeeEgDE1q1b7cciIiIEAPH999/X+zlEHQ27foicnF6vx6xZs2ocNxgM9j+XlJQgNzcXw4cPR3l5OU6dOtXgde+++274+PjYn1e15pw/f77B944ePRrR0dH25wkJCfD09LS/12q14scff8TkyZMRGhpqPy8mJgbjxo1r8PqHDh1CcnIy5s2bB29v72qvtWS69NSpU2u06EyZMgUajQaff/65/dixY8dw4sQJ3H333fZj69atw/Dhw+Hj44Pc3Fz7Y/To0bBardixY0eT69m4cSMA4Iknnqh2/MknnwQAfPfdd9WOR0VFYcyYMU3+HKL2jF0/RE6uU6dOtQ7APH78OF544QVs3boVxcXF1V4rKipq8Lrh4eHVnleFloKCgia/t+r9Ve/Nzs5GRUUFYmJiapxX27GrnTt3DgDQs2fPBs9tiqioqBrH/P39MWrUKKxduxaLFy8GYOv20Wg0mDJliv28pKQkHDlypM6u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ubfBwcHIzs6u9rrFYkF+fn6L7z+DyhV0Oh369euHn376yX5MlmX89NNPGDx4sIKVtX9CCDz22GP46quvsHXrVkRFRVV7vV+/ftBqtdXu/enTp5GWlsZ730SjRo3C0aNHcfjwYfujf//+mD59uv3PvNetY+jQoTWm2Z85cwYREREAgKioKAQHB1e718XFxdizZw/vdROVl5dDpar+k6VWqyHLMgDe67bUmHs7ePBgFBYW4sCBA/Zztm7dClmWMWjQoJYV0KKhuB3QmjVrhF6vFytXrhQnTpwQDz30kPD29hZZWVlKl9auzZ49W3h5eYlt27aJzMxM+6O8vNx+ziOPPCLCw8PF1q1bxf79+8XgwYPF4MGDFay647hy1o8QvNetZe/evUKj0YhXXnlFJCUliVWrVglXV1fxv//9z37O0qVLhbe3t/j666/FkSNHxG233cYps80wY8YM0alTJ/v05C+//FL4+/uLp59+2n4O73XzlZSUiEOHDolDhw4JAOKtt94Shw4dEqmpqUKIxt3bsWPHij59+og9e/aInTt3itjYWE5Pbiv/+te/RHh4uNDpdGLgwIFi9+7dSpfU7gGo9bFixQr7ORUVFeLRRx8VPj4+wtXVVdx+++0iMzNTuaI7kKuDCu916/nmm29Ez549hV6vF3FxcWL58uXVXpdlWbz44osiKChI6PV6MWrUKHH69GmFqm2/iouLxdy5c0V4eLhwcXERXbp0Ec8//7wwGo32c3ivm+/nn3+u9d/oGTNmCCEad2/z8vLEtGnThLu7u/D09BSzZs0SJSUlLa5NEuKKZf2IiIiInAjHqBAREZHTYlAhIiIip8WgQkRERE6LQYWIiIicFoMKEREROS0GFSIiInJaDCpERETktBhUiKjdkyQJ69evV7oMImoDDCpE1CIzZ86EJEk1HmPHjlW6NCLqADRKF0BE7d/YsWOxYsWKasf0er1C1RBRR8IWFSJqMb1ej+Dg4GoPHx8fALZumWXLlmHcuHEwGAzo0qULvvjii2rvP3r0KG666SYYDAb4+fnhoYceQmlpabVz/vvf/yI+Ph56vR4hISF47LHHqr2em5uL22+/Ha6uroiNjcWGDRvsrxUUFGD69OkICAiAwWBAbGxsjWBFRM6JQYWI2tyLL76IqVOnIjExEdOnT8c999yDkydPAgDKysowZswY+Pj4YN++fVi3bh1+/PHHakFk2bJlmDNnDh566CEcPXoUGzZsQExMTLXPWLhwIe666y4cOXIE48ePx/Tp05Gfn2///BMnTmDTpk04efIkli1bBn9/f8fdACJqvhZva0hE17QZM2YItVot3Nzcqj1eeeUVIYRt5+xHHnmk2nsGDRokZs+eLYQQYvny5cLHx0eUlpbaX//uu++ESqUSWVlZQgghQkNDxfPPP19nDQDECy+8YH9eWloqAIhNmzYJIYSYNGmSmDVrVut8YSJyKI5RIaIWu/HGG7Fs2bJqx3x9fe1/Hjx4cLXXBg8ejMOHDwMATp48id69e8PNzc3++tChQyHLMk6fPg1JkpCRkYFRo0bVW0NCQoL9z25ubvD09ER2djYAYPbs2Zg6dSoOHjyIW265BZMnT8aQIUOa9V2JyLEYVIioxdzc3Gp0xbQWg8HQqPO0Wm2155IkQZZlAMC4ceOQmpqKjRs3YsuWLRg1ahTmzJmDN998s9XrJaLWxTEqRNTmdu/eXeN59+7dAQDdu3dHYmIiysrK7K//+uuvUKlU6NatGzw8PBAZGYmffvqpRTUEBARgxowZ+N///oe3334by5cvb9H1iMgx2KJCRC1mNBqRlZVV7ZhGo7EPWF23bh369++PYcOGYdWqVdi7dy8++ugjAMD06dPx8ssvY8aMGViwYAFycnLw+OOP47777kNQUBAAYMGCBXjkkUcQGBiIcePGoaSkBL/++isef/zxRtX30ksvoV+/foiPj4fRaMS3335rD0pE5NwYVIioxb7//nuEhIRUO9atWzecOnUKgG1Gzpo1a/Doo48iJCQEn332GXr06AEAcHV1xebNmzF37lwMGDAArq6umDp1Kt566y37tWbMmIHKykr84x//wFNPPQV/f3/ccccdja5Pp9Nh/vz5SElJgcFgwPDhw7FmzZpW+OZE1NYkIYRQuggi6rgkScJXX32FyZMnK10KEbVDHKNCRERETotBhYiIiJwWx6gQUZti7zIRtQRbVIiIiMhpMagQERGR02JQISIiIqfFoEJEREROi0GFiIiInBaDChERETktBhUiIiJyWgwqRERE5LQYVIiIiMhp/T9/+qwjndM10AAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.457836389541626\n" + ] + } + ], + "source": [ + "hist = model.fit(x_train, y_train, epochs=100, verbose=0)\n", + "plot_train_test_loss([hist]);\n", + "print(hist.history[\"loss\"][-1])" + ] + }, + { + "cell_type": "markdown", + "id": "ec4632f6-4c4a-4a10-9212-f9d272d6d167", + "metadata": {}, + "source": [ + "## 3. Disjoint input" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "0b930694-2e29-4b04-872a-464a4029fbad", + "metadata": {}, + "outputs": [], + "source": [ + "inputs = [\n", + " {\"shape\": (41, ), \"name\": \"node_attributes\", \"dtype\": \"float32\"},\n", + " {\"shape\": (11, ), \"name\": \"edge_attributes\", \"dtype\": \"float32\"},\n", + " {\"shape\": (None, ), \"name\": \"edge_indices\", \"dtype\": \"int64\"}, # shape is (2, None)\n", + " {\"shape\": (), \"name\": \"batch_id_node\", \"dtype\": \"int64\"},\n", + " {\"shape\": (), \"name\": \"batch_id_edge\", \"dtype\": \"int64\"},\n", + " {\"shape\": (), \"name\": \"node_id\", \"dtype\": \"int64\"},\n", + " {\"shape\": (), \"name\": \"edge_id\", \"dtype\": \"int64\"},\n", + " {\"shape\": (), \"name\": \"count_nodes\", \"dtype\": \"int64\"},\n", + " {\"shape\": (), \"name\": \"count_edges\", \"dtype\": \"int64\"},\n", + "]\n", + "outputs = {\"shape\": (1, ), \"name\": \"graph_labels\", \"dtype\": \"float32\"}" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "98c421bb-05c0-4484-b783-f31c913483d7", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:kgcnn.models.utils:Updated model kwargs: '{'name': 'GINE', 'inputs': [{'shape': (41,), 'name': 'node_attributes', 'dtype': 'float32'}, {'shape': (11,), 'name': 'edge_attributes', 'dtype': 'float32'}, {'shape': (None,), 'name': 'edge_indices', 'dtype': 'int64'}, {'shape': (), 'name': 'batch_id_node', 'dtype': 'int64'}, {'shape': (), 'name': 'batch_id_edge', 'dtype': 'int64'}, {'shape': (), 'name': 'node_id', 'dtype': 'int64'}, {'shape': (), 'name': 'edge_id', 'dtype': 'int64'}, {'shape': (), 'name': 'count_nodes', 'dtype': 'int64'}, {'shape': (), 'name': 'count_edges', 'dtype': 'int64'}], 'input_tensor_type': 'disjoint', 'cast_disjoint_kwargs': {}, 'input_embedding': None, 'input_node_embedding': {'input_dim': 95, 'output_dim': 64}, 'input_edge_embedding': {'input_dim': 5, 'output_dim': 64}, 'gin_mlp': {'units': [64, 64], 'use_bias': True, 'activation': ['relu', 'linear'], 'use_normalization': True, 'normalization_technique': 'graph_batch'}, 'gin_args': {'epsilon_learnable': False}, 'depth': 3, 'dropout': 0.0, 'verbose': 10, 'last_mlp': {'use_bias': [True, True, True], 'units': [64, 64, 64], 'activation': ['relu', 'relu', 'linear']}, 'output_embedding': 'graph', 'output_to_tensor': True, 'output_tensor_type': 'padded', 'output_mlp': {'units': 1, 'activation': 'linear'}}'.\n" + ] + } + ], + "source": [ + "model = make_model(\n", + " inputs=inputs,\n", + " input_tensor_type=\"disjoint\",\n", + " output_mlp={\"units\": 1, \"activation\": \"linear\"}\n", + ")\n", + "model.compile(loss=\"mean_absolute_error\")" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "20209ee9-41c8-4886-a8b5-d0baf8036e8a", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:kgcnn.data.base:Dataloader is experimental and not fully tested nor stable.\n", + "C:\\Users\\patri\\anaconda3\\envs\\gcnn_keras_test\\lib\\contextlib.py:153: UserWarning: Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least `steps_per_epoch * epochs` batches. You may need to use the `.repeat()` function when building your dataset.\n", + " self.gen.throw(typ, value, traceback)\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.43317434191703796\n" + ] + } + ], + "source": [ + "dataloader = dataset.tf_disjoint_data_generator(inputs=inputs, outputs=outputs, batch_size=31, has_edges=True)\n", + "hist = model.fit(dataloader, epochs=100, verbose=0)\n", + "plot_train_test_loss([hist]);\n", + "print(hist.history[\"loss\"][-1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa220355-da31-43d2-b66b-51e204d39f4f", + "metadata": {}, "outputs": [], "source": [] }