diff --git a/benchmarks/matbench_v0.1_DensGNN/hyper.py b/benchmarks/matbench_v0.1_DensGNN/hyper.py new file mode 100644 index 00000000..e197dca6 --- /dev/null +++ b/benchmarks/matbench_v0.1_DensGNN/hyper.py @@ -0,0 +1,934 @@ +hyper_1 = { + "model": { + "class_name": "make_model_asu", + "module_name": "kgcnn.literature.DenseGNN", + "config": { + "name": "DenseGNN", + "inputs": { + + "offset": {"shape": (None, 3), "name": "offset", "dtype": "float32", "ragged": True}, + # "voronoi_ridge_area": {"shape": (None, ), "name": "voronoi_ridge_area", "dtype": "float32", "ragged": True}, + "atomic_number": {"shape": (None,), "name": "atomic_number", "dtype": "int32", "ragged": True}, + # "AGNIFinger": {"shape": (None,61), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "AGNIFinger": {"shape": (None,24), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "edge_indices": {"shape": (None, 2), "name": "edge_indices", "dtype": "int64", "ragged": True}, + "charge": {'shape': [1], 'name': "charge", 'dtype': 'float32', 'ragged': False}, + + }, + + "input_block_cfg" : {'node_size': 128, + 'edge_size': 128, + 'edge_embedding_args': {'bins_distance': 32, + 'max_distance': 8.0, + 'distance_log_base': 1.0, + 'bins_voronoi_area': None, + 'max_voronoi_area': None}}, + + + "output_block_cfg" : {'edge_mlp': None, + 'node_mlp': None, + 'global_mlp': {'units': [1], + 'activation': ['linear']}, + 'aggregate_edges_local': 'sum', + 'aggregate_edges_global': 'mean', + 'aggregate_nodes': 'mean', + 'return_updated_edges': False, + 'return_updated_nodes': True, + 'return_updated_globals': True, + 'edge_attention_mlp_local': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'edge_attention_mlp_global': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'node_attention_mlp': {'units': [32, 1], 'activation': ['swish', 'swish']}, + 'edge_gate': None, + 'node_gate': None, + 'global_gate': None, + 'residual_node_update': False, + 'residual_edge_update': False, + 'residual_global_update': False, + 'update_edges_input': [True, True, True, True], + 'update_nodes_input': [True, True, True], + 'update_global_input': [True, True, True], + 'multiplicity_readout': True}, + + "input_embedding": {"node": {"input_dim": 96, "output_dim": 64}, + "graph": {"input_dim": 100, "output_dim": 64} + }, + "depth": 5, + "n_units":128, + "gin_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + "graph_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + + "gin_args": {"pooling_method":"sum", "g_pooling_method":"max", + "edge_mlp_args": {"units": [128]*3, "use_bias": True, "activation": ["swish"]*3}, + "concat_args": {"axis": -1}, + "node_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + "graph_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + }, + } + }, + "training": { + "fit": {"batch_size": 64, "epochs": 300, "validation_freq": 20, "verbose": 2, "callbacks": []}, + + "compile": { + + # "optimizer": {"class_name": "Adam", + # "config": {"lr": { + # "class_name": "ExponentialDecay", + # "config": {"initial_learning_rate": 0.001, + # "decay_steps": 5800, + # "decay_rate": 0.5, "staircase": False}, + # } + # } + # }, + + "optimizer": { + "class_name": "Adam", + "config": { + "learning_rate": { + "class_name": "kgcnn>KerasPolynomialDecaySchedule", + "config": { + "dataset_size": 509, "batch_size": 64, "epochs": 800, + "lr_start": 0.0001, "lr_stop": 1.0e-05 + } + } + } + }, + + + "loss": "mean_absolute_error" + }, + + "cross_validation": {"class_name": "KFold", + "config": {"n_splits": 5, "random_state": 42, "shuffle": True}}, + "scaler": {"class_name": "StandardScaler", "config": {"with_std": True, "with_mean": True, "copy": True}} + }, + + "data": { + "dataset": { + "config": {}, + "methods": [ + + {"set_representation": { + "pre_processor": { + + "class_name": "KNNUnitCell", + "module_name": "kgcnn.crystal.preprocessor", + "config": {"k": 24} + + # "class_name": "VoronoiUnitCell", + # "module_name": "kgcnn.crystal.preprocessor", + # "config": {"min_ridge_area": 0.1} + + }, + "reset_graphs": False}}, + + ] + }, + "data_unit": "" + }, + + + "info": { + "postfix": "", + "postfix_file": "", + "kgcnn_version": "3.0.2" + } +} + +hyper_2 = { + "model": { + "class_name": "make_model_asu", + "module_name": "kgcnn.literature.DenseGNN", + "config": { + "name": "DenseGNN", + "inputs": { + "offset": {"shape": (None, 3), "name": "offset", "dtype": "float32", "ragged": True}, + # "voronoi_ridge_area": {"shape": (None, ), "name": "voronoi_ridge_area", "dtype": "float32", "ragged": True}, + "atomic_number": {"shape": (None,), "name": "atomic_number", "dtype": "int32", "ragged": True}, + # "AGNIFinger": {"shape": (None,61), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "AGNIFinger": {"shape": (None,24), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "edge_indices": {"shape": (None, 2), "name": "edge_indices", "dtype": "int64", "ragged": True}, + "charge": {'shape': [1], 'name': "charge", 'dtype': 'float32', 'ragged': False}, + }, + + "input_block_cfg" : {'node_size': 128, + 'edge_size': 128, + 'edge_embedding_args': {'bins_distance': 32, + 'max_distance': 8.0, + 'distance_log_base': 1.0, + 'bins_voronoi_area': None, + 'max_voronoi_area': None}}, + + + "output_block_cfg" : {'edge_mlp': None, + 'node_mlp': None, + 'global_mlp': {'units': [1], + 'activation': ['linear']}, + 'aggregate_edges_local': 'sum', + 'aggregate_edges_global': 'mean', + 'aggregate_nodes': 'mean', + 'return_updated_edges': False, + 'return_updated_nodes': True, + 'return_updated_globals': True, + 'edge_attention_mlp_local': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'edge_attention_mlp_global': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'node_attention_mlp': {'units': [32, 1], 'activation': ['swish', 'swish']}, + 'edge_gate': None, + 'node_gate': None, + 'global_gate': None, + 'residual_node_update': False, + 'residual_edge_update': False, + 'residual_global_update': False, + 'update_edges_input': [True, True, True, True], + 'update_nodes_input': [True, True, True], + 'update_global_input': [True, True, True], + 'multiplicity_readout': True}, + + "input_embedding": {"node": {"input_dim": 96, "output_dim": 64}, + "graph": {"input_dim": 100, "output_dim": 64} + }, + "depth": 5, + "n_units":128, + "gin_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + "graph_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + + "gin_args": {"pooling_method":"max", "g_pooling_method":"max", + "edge_mlp_args": {"units": [128]*3, "use_bias": True, "activation": ["swish"]*3}, + "concat_args": {"axis": -1}, + "node_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + "graph_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + }, + } + }, + + "training": { + "fit": {"batch_size": 64, "epochs": 300, "validation_freq": 20, "verbose": 2, "callbacks": []}, + "compile": { + "optimizer": {"class_name": "Adam", + "config": {"lr": { + "class_name": "ExponentialDecay", + "config": {"initial_learning_rate": 0.001, + "decay_steps": 5800, + "decay_rate": 0.5, "staircase": False}, + } + } + }, + + # "optimizer": { + # "class_name": "Adam", + # "config": { + # "learning_rate": { + # "class_name": "kgcnn>KerasPolynomialDecaySchedule", + # "config": { + # "dataset_size": 1013, "batch_size": 64, "epochs": 800, + # "lr_start": 0.0001, "lr_stop": 1.0e-05 + # } + # } + # } + # }, + "loss": "mean_absolute_error" + }, + + "cross_validation": {"class_name": "KFold", + "config": {"n_splits": 5, "random_state": 42, "shuffle": True}}, + "scaler": {"class_name": "StandardScaler", "config": {"with_std": True, "with_mean": True, "copy": True}} + }, + + "data": { + "dataset": { + "config": {}, + "methods": [ + + {"set_representation": { + "pre_processor": { + + "class_name": "KNNUnitCell", + "module_name": "kgcnn.crystal.preprocessor", + "config": {"k": 12} + + # "class_name": "VoronoiUnitCell", + # "module_name": "kgcnn.crystal.preprocessor", + # "config": {"min_ridge_area": 0.1} + + }, + "reset_graphs": False}}, + + ] + }, + "data_unit": "" + }, + + + "info": { + "postfix": "", + "postfix_file": "", + "kgcnn_version": "3.0.2" + } +} + + +hyper_3 = { + "model": { + "class_name": "make_model_asu", + "module_name": "kgcnn.literature.DenseGNN", + "config": { + "name": "DenseGNN", + "inputs": { + "offset": {"shape": (None, 3), "name": "offset", "dtype": "float32", "ragged": True}, + "voronoi_ridge_area": {"shape": (None, ), "name": "voronoi_ridge_area", "dtype": "float32", "ragged": True}, + "atomic_number": {"shape": (None,), "name": "atomic_number", "dtype": "int32", "ragged": True}, + # "AGNIFinger": {"shape": (None,61), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "AGNIFinger": {"shape": (None,24), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "edge_indices": {"shape": (None, 2), "name": "edge_indices", "dtype": "int64", "ragged": True}, + "charge": {'shape': [1], 'name': "charge", 'dtype': 'float32', 'ragged': False}, + + }, + + "input_block_cfg" : {'node_size': 128, + 'edge_size': 128, + 'edge_embedding_args': {'bins_distance': 32, + 'max_distance': 8.0, + 'distance_log_base': 1.0, + 'bins_voronoi_area': 32, + 'max_voronoi_area': 32}}, + + "output_block_cfg" : {'edge_mlp': None, + 'node_mlp': None, + 'global_mlp': {'units': [1], + 'activation': ['linear']}, + 'aggregate_edges_local': 'sum', + 'aggregate_edges_global': 'mean', + 'aggregate_nodes': 'mean', + 'return_updated_edges': False, + 'return_updated_nodes': True, + 'return_updated_globals': True, + 'edge_attention_mlp_local': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'edge_attention_mlp_global': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'node_attention_mlp': {'units': [32, 1], 'activation': ['swish', 'swish']}, + 'edge_gate': None, + 'node_gate': None, + 'global_gate': None, + 'residual_node_update': False, + 'residual_edge_update': False, + 'residual_global_update': False, + 'update_edges_input': [True, True, True, True], + 'update_nodes_input': [True, True, True], + 'update_global_input': [True, True, True], + 'multiplicity_readout': True}, + "input_embedding": {"node": {"input_dim": 96, "output_dim": 64}, + "graph": {"input_dim": 100, "output_dim": 64} + }, + "depth": 5, + "n_units":128, + "gin_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + "graph_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + + "gin_args": {"pooling_method":"sum", "g_pooling_method":"max", + "edge_mlp_args": {"units": [128]*3, "use_bias": True, "activation": ["swish"]*3}, + "concat_args": {"axis": -1}, + "node_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + "graph_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + }, + } + }, + "training": { + "fit": {"batch_size": 128, "epochs": 300, "validation_freq": 20, "verbose": 2, "callbacks": []}, + + "compile": { + + "optimizer": {"class_name": "Adam", + "config": {"lr": { + "class_name": "ExponentialDecay", + "config": {"initial_learning_rate": 0.001, + "decay_steps": 5800, + "decay_rate": 0.5, "staircase": False}, + } + } + }, + "loss": "mean_absolute_error" + }, + + "cross_validation": {"class_name": "KFold", + "config": {"n_splits": 5, "random_state": 42, "shuffle": True}}, + "scaler": {"class_name": "StandardScaler", "config": {"with_std": True, "with_mean": True, "copy": True}} + }, + "data": { + "dataset": { + "config": {}, + "methods": [ + + {"set_representation": { + "pre_processor": { + # "class_name": "KNNUnitCell", + # "module_name": "kgcnn.crystal.preprocessor", + # "config": {"k": 12} + "class_name": "VoronoiUnitCell", + "module_name": "kgcnn.crystal.preprocessor", + "config": {"min_ridge_area": 0.1} + }, + "reset_graphs": False}}, + ] + }, + "data_unit": "" + }, + "info": { + "postfix": "", + "postfix_file": "", + "kgcnn_version": "3.0.2" + } +} + +hyper_4 = { + "model": { + "class_name": "make_model_asu", + "module_name": "kgcnn.literature.DenseGNN", + "config": { + "name": "DenseGNN", + "inputs": { + "offset": {"shape": (None, 3), "name": "offset", "dtype": "float32", "ragged": True}, + "voronoi_ridge_area": {"shape": (None, ), "name": "voronoi_ridge_area", "dtype": "float32", "ragged": True}, + "atomic_number": {"shape": (None,), "name": "atomic_number", "dtype": "int32", "ragged": True}, + # "AGNIFinger": {"shape": (None,61), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "AGNIFinger": {"shape": (None,24), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "edge_indices": {"shape": (None, 2), "name": "edge_indices", "dtype": "int64", "ragged": True}, + "charge": {'shape': [1], 'name': "charge", 'dtype': 'float32', 'ragged': False}, + }, + "input_block_cfg" : {'node_size': 128, + 'edge_size': 128, + 'edge_embedding_args': {'bins_distance': 32, + 'max_distance': 8.0, + 'distance_log_base': 1.0, + 'bins_voronoi_area': 32, + 'max_voronoi_area': 32}}, + + "output_block_cfg" : {'edge_mlp': None, + 'node_mlp': None, + 'global_mlp': {'units': [1], + 'activation': ['linear']}, + 'aggregate_edges_local': 'sum', + 'aggregate_edges_global': 'mean', + 'aggregate_nodes': 'mean', + 'return_updated_edges': False, + 'return_updated_nodes': True, + 'return_updated_globals': True, + 'edge_attention_mlp_local': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'edge_attention_mlp_global': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'node_attention_mlp': {'units': [32, 1], 'activation': ['swish', 'swish']}, + 'edge_gate': None, + 'node_gate': None, + 'global_gate': None, + 'residual_node_update': False, + 'residual_edge_update': False, + 'residual_global_update': False, + 'update_edges_input': [True, True, True, True], + 'update_nodes_input': [True, True, True], + 'update_global_input': [True, True, True], + 'multiplicity_readout': True}, + + "input_embedding": {"node": {"input_dim": 96, "output_dim": 64}, + "graph": {"input_dim": 100, "output_dim": 64} + }, + "depth": 5, + "n_units":128, + "gin_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + "graph_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + + "gin_args": {"pooling_method":"sum", "g_pooling_method":"max", + "edge_mlp_args": {"units": [128]*3, "use_bias": True, "activation": ["swish"]*3}, + "concat_args": {"axis": -1}, + "node_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + "graph_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + }, + } + }, + + "training": { + "fit": {"batch_size": 128, "epochs": 300, "validation_freq": 20, "verbose": 2, "callbacks": []}, + + "compile": { + + "optimizer": {"class_name": "Adam", + "config": {"lr": { + "class_name": "ExponentialDecay", + "config": {"initial_learning_rate": 0.001, + "decay_steps": 5800, + "decay_rate": 0.5, "staircase": False}, + } + } + }, + # "optimizer": { + # "class_name": "Adam", + # "config": { + # "learning_rate": { + # "class_name": "kgcnn>KerasPolynomialDecaySchedule", + # "config": { + # "dataset_size": 15142, "batch_size": 64, "epochs": 800, + # "lr_start": 0.0005, "lr_stop": 1.0e-05 + # } + # } + # } + # }, + "loss": "mean_absolute_error" + }, + + "cross_validation": {"class_name": "KFold", + "config": {"n_splits": 5, "random_state": 42, "shuffle": True}}, + "scaler": {"class_name": "StandardScaler", "config": {"with_std": True, "with_mean": True, "copy": True}} + }, + + "data": { + "dataset": { + + "config": {}, + "methods": [ + + {"set_representation": { + "pre_processor": { + + # "class_name": "KNNUnitCell", + # "module_name": "kgcnn.crystal.preprocessor", + # "config": {"k": 12} + + "class_name": "VoronoiUnitCell", + "module_name": "kgcnn.crystal.preprocessor", + "config": {"min_ridge_area": 0.1} + + }, + "reset_graphs": False}}, + + ] + }, + "data_unit": "" + }, + + + "info": { + "postfix": "", + "postfix_file": "", + "kgcnn_version": "3.0.2" + } +} + + +hyper_5 = { + "model": { + "class_name": "make_model_asu", + "module_name": "kgcnn.literature.DenseGNN", + "config": { + "name": "DenseGNN", + "inputs": { + + "offset": {"shape": (None, 3), "name": "offset", "dtype": "float32", "ragged": True}, + "voronoi_ridge_area": {"shape": (None, ), "name": "voronoi_ridge_area", "dtype": "float32", "ragged": True}, + "atomic_number": {"shape": (None,), "name": "atomic_number", "dtype": "int32", "ragged": True}, + # "AGNIFinger": {"shape": (None,61), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "AGNIFinger": {"shape": (None,24), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "edge_indices": {"shape": (None, 2), "name": "edge_indices", "dtype": "int64", "ragged": True}, + "charge": {'shape': [1], 'name': "charge", 'dtype': 'float32', 'ragged': False}, + + }, + "input_block_cfg" : {'node_size': 128, + 'edge_size': 128, + 'edge_embedding_args': {'bins_distance': 32, + 'max_distance': 8.0, + 'distance_log_base': 1.0, + 'bins_voronoi_area': 32, + 'max_voronoi_area': 32}}, + + + "output_block_cfg" : {'edge_mlp': None, + 'node_mlp': None, + 'global_mlp': {'units': [1], + 'activation': ['linear']}, + 'aggregate_edges_local': 'sum', + 'aggregate_edges_global': 'mean', + 'aggregate_nodes': 'mean', + 'return_updated_edges': False, + 'return_updated_nodes': True, + 'return_updated_globals': True, + 'edge_attention_mlp_local': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'edge_attention_mlp_global': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'node_attention_mlp': {'units': [32, 1], 'activation': ['swish', 'swish']}, + 'edge_gate': None, + 'node_gate': None, + 'global_gate': None, + 'residual_node_update': False, + 'residual_edge_update': False, + 'residual_global_update': False, + 'update_edges_input': [True, True, True, True], + 'update_nodes_input': [True, True, True], + 'update_global_input': [True, True, True], + 'multiplicity_readout': True}, + + "input_embedding": {"node": {"input_dim": 96, "output_dim": 64}, + "graph": {"input_dim": 100, "output_dim": 64} + }, + "depth": 5, + "n_units":128, + "gin_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + "graph_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + + "gin_args": {"pooling_method":"sum", "g_pooling_method":"max", + "edge_mlp_args": {"units": [128]*3, "use_bias": True, "activation": ["swish"]*3}, + "concat_args": {"axis": -1}, + "node_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + "graph_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + }, + } + }, + "training": { + "fit": {"batch_size": 128, "epochs": 300, "validation_freq": 20, "verbose": 2, "callbacks": []}, + "compile": { + "optimizer": {"class_name": "Adam", + "config": {"lr": { + "class_name": "ExponentialDecay", + "config": {"initial_learning_rate": 0.001, + "decay_steps": 5800, + "decay_rate": 0.5, "staircase": False}, + } + } + }, + # "optimizer": { + # "class_name": "Adam", + # "config": { + # "learning_rate": { + # "class_name": "kgcnn>KerasPolynomialDecaySchedule", + # "config": { + # "dataset_size": 8789, "batch_size": 64, "epochs": 800, + # "lr_start": 0.0001, "lr_stop": 1.0e-05 + # } + # } + # } + # }, + + "loss": "mean_absolute_error" + }, + + "cross_validation": {"class_name": "KFold", + "config": {"n_splits": 5, "random_state": 42, "shuffle": True}}, + "scaler": {"class_name": "StandardScaler", "config": {"with_std": True, "with_mean": True, "copy": True}} + }, + + "data": { + "dataset": { + "config": {}, + "methods": [ + {"set_representation": { + "pre_processor": { + + # "class_name": "KNNUnitCell", + # "module_name": "kgcnn.crystal.preprocessor", + # "config": {"k": 12} + + "class_name": "VoronoiUnitCell", + "module_name": "kgcnn.crystal.preprocessor", + "config": {"min_ridge_area": 0.1} + + }, + "reset_graphs": False}}, + + ] + }, + "data_unit": "" + }, + + + "info": { + "postfix": "", + "postfix_file": "", + "kgcnn_version": "3.0.2" + } +} + + +hyper_6 = { + "model": { + "class_name": "make_model_asu", + "module_name": "kgcnn.literature.DenseGNN", + "config": { + "name": "DenseGNN", + "inputs": { + "offset": {"shape": (None, 3), "name": "offset", "dtype": "float32", "ragged": True}, + "voronoi_ridge_area": {"shape": (None, ), "name": "voronoi_ridge_area", "dtype": "float32", "ragged": True}, + "atomic_number": {"shape": (None,), "name": "atomic_number", "dtype": "int32", "ragged": True}, + "AGNIFinger": {"shape": (None,61), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + # "AGNIFinger": {"shape": (None,24), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "edge_indices": {"shape": (None, 2), "name": "edge_indices", "dtype": "int64", "ragged": True}, + "charge": {'shape': [1], 'name': "charge", 'dtype': 'float32', 'ragged': False}, + }, + + "input_block_cfg" : {'node_size': 128, + 'edge_size': 128, + 'edge_embedding_args': {'bins_distance': 32, + 'max_distance': 8.0, + 'distance_log_base': 1.0, + 'bins_voronoi_area': 32, + 'max_voronoi_area': 32}}, + + "output_block_cfg" : {'edge_mlp': None, + 'node_mlp': None, + 'global_mlp': {'units': [1], + 'activation': ['linear']}, + 'aggregate_edges_local': 'sum', + 'aggregate_edges_global': 'mean', + 'aggregate_nodes': 'mean', + 'return_updated_edges': False, + 'return_updated_nodes': True, + 'return_updated_globals': True, + 'edge_attention_mlp_local': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'edge_attention_mlp_global': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'node_attention_mlp': {'units': [32, 1], 'activation': ['swish', 'swish']}, + 'edge_gate': None, + 'node_gate': None, + 'global_gate': None, + 'residual_node_update': False, + 'residual_edge_update': False, + 'residual_global_update': False, + 'update_edges_input': [True, True, True, True], + 'update_nodes_input': [True, True, True], + 'update_global_input': [True, True, True], + 'multiplicity_readout': True}, + + "input_embedding": {"node": {"input_dim": 96, "output_dim": 64}, + "graph": {"input_dim": 100, "output_dim": 64} + }, + "depth": 5, + "n_units":128, + "gin_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + "graph_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + + "gin_args": {"pooling_method":"sum", "g_pooling_method":"mean", + "edge_mlp_args": {"units": [128]*3, "use_bias": True, "activation": ["swish"]*3}, + "concat_args": {"axis": -1}, + "node_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + "graph_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + }, + } + }, + + "training": { + "fit": {"batch_size": 128, "epochs": 300, "validation_freq": 20, "verbose": 2, "callbacks": []}, + + "compile": { + + "optimizer": {"class_name": "Adam", + "config": {"lr": { + "class_name": "ExponentialDecay", + "config": {"initial_learning_rate": 0.001, + "decay_steps": 5800, + "decay_rate": 0.5, "staircase": False}, + } + } + }, + + # "optimizer": { + # "class_name": "Adam", + # "config": { + # "learning_rate": { + # "class_name": "kgcnn>KerasPolynomialDecaySchedule", + # "config": { + # "dataset_size": 8789, "batch_size": 64, "epochs": 800, + # "lr_start": 0.0001, "lr_stop": 1.0e-05 + # } + # } + # } + # }, + + "loss": "mean_absolute_error" + }, + + "cross_validation": {"class_name": "KFold", + "config": {"n_splits": 5, "random_state": 42, "shuffle": True}}, + "scaler": {"class_name": "StandardScaler", "config": {"with_std": True, "with_mean": True, "copy": True}} + }, + + "data": { + "dataset": { + "config": {}, + "methods": [ + {"set_representation": { + "pre_processor": { + + # "class_name": "KNNUnitCell", + # "module_name": "kgcnn.crystal.preprocessor", + # "config": {"k": 12} + + "class_name": "VoronoiUnitCell", + "module_name": "kgcnn.crystal.preprocessor", + "config": {"min_ridge_area": 0.1} + + }, + "reset_graphs": False}}, + + ] + }, + "data_unit": "" + }, + + + "info": { + "postfix": "", + "postfix_file": "", + "kgcnn_version": "3.0.2" + } +} + + +hyper_7 = { + "model": { + "class_name": "make_model_asu", + "module_name": "kgcnn.literature.DenseGNN", + "config": { + "name": "DenseGNN", + "inputs": { + + "offset": {"shape": (None, 3), "name": "offset", "dtype": "float32", "ragged": True}, + # "voronoi_ridge_area": {"shape": (None, ), "name": "voronoi_ridge_area", "dtype": "float32", "ragged": True}, + "atomic_number": {"shape": (None,), "name": "atomic_number", "dtype": "int32", "ragged": True}, + # "AGNIFinger": {"shape": (None,61), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "AGNIFinger": {"shape": (None,24), "name": "AGNIFinger", "dtype": "float32", "ragged": True}, + "edge_indices": {"shape": (None, 2), "name": "edge_indices", "dtype": "int64", "ragged": True}, + "charge": {'shape': [1], 'name': "charge", 'dtype': 'float32', 'ragged': False}, + + }, + + "input_block_cfg" : {'node_size': 128, + 'edge_size': 128, + 'edge_embedding_args': {'bins_distance': 32, + 'max_distance': 8.0, + 'distance_log_base': 1.0, + 'bins_voronoi_area': None, + 'max_voronoi_area': None}}, + + + "output_block_cfg" : {'edge_mlp': None, + 'node_mlp': None, + 'global_mlp': {'units': [1], + 'activation': ['linear']}, + 'aggregate_edges_local': 'sum', + 'aggregate_edges_global': 'mean', + 'aggregate_nodes': 'mean', + 'return_updated_edges': False, + 'return_updated_nodes': True, + 'return_updated_globals': True, + 'edge_attention_mlp_local': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'edge_attention_mlp_global': {'units': [32, 1], + 'activation': ['swish', 'swish']}, + 'node_attention_mlp': {'units': [32, 1], 'activation': ['swish', 'swish']}, + 'edge_gate': None, + 'node_gate': None, + 'global_gate': None, + 'residual_node_update': False, + 'residual_edge_update': False, + 'residual_global_update': False, + 'update_edges_input': [True, True, True, True], + 'update_nodes_input': [True, True, True], + 'update_global_input': [True, True, True], + 'multiplicity_readout': True}, + + "input_embedding": {"node": {"input_dim": 96, "output_dim": 64}, + "graph": {"input_dim": 100, "output_dim": 64} + }, + "depth": 5, + "n_units":128, + "gin_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + "graph_mlp": {"units": [128], "use_bias": True, "activation": ["swish"], + }, + + "gin_args": {"pooling_method":"sum", "g_pooling_method":"max", + "edge_mlp_args": {"units": [128]*3, "use_bias": True, "activation": ["swish"]*3}, + "concat_args": {"axis": -1}, + "node_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + "graph_mlp_args": {"units": [128], "use_bias": True, "activation": ["swish"]}, + }, + } + }, + + "training": { + "fit": {"batch_size": 64, "epochs": 300, "validation_freq": 20, "verbose": 2, "callbacks": []}, + "compile": { + + # "optimizer": {"class_name": "Adam", + # "config": {"lr": { + # "class_name": "ExponentialDecay", + # "config": {"initial_learning_rate": 0.001, + # "decay_steps": 5800, + # "decay_rate": 0.5, "staircase": False}, + # } + # } + # }, + + "optimizer": { + "class_name": "Adam", + "config": { + "learning_rate": { + "class_name": "kgcnn>KerasPolynomialDecaySchedule", + "config": { + "dataset_size": 3811, "batch_size": 64, "epochs": 800, + "lr_start": 0.0001, "lr_stop": 1.0e-05 + } + } + } + }, + + "loss": "mean_absolute_error" + }, + + "cross_validation": {"class_name": "KFold", + "config": {"n_splits": 5, "random_state": 42, "shuffle": True}}, + "scaler": {"class_name": "StandardScaler", "config": {"with_std": True, "with_mean": True, "copy": True}} + }, + + "data": { + "dataset": { + "config": {}, + "methods": [ + {"set_representation": { + "pre_processor": { + "class_name": "KNNUnitCell", + "module_name": "kgcnn.crystal.preprocessor", + "config": {"k": 12} + + # "class_name": "VoronoiUnitCell", + # "module_name": "kgcnn.crystal.preprocessor", + # "config": {"min_ridge_area": 0.1} + + }, + "reset_graphs": False}}, + ] + }, + "data_unit": "" + }, + + + "info": { + "postfix": "", + "postfix_file": "", + "kgcnn_version": "3.0.2" + } +} diff --git a/benchmarks/matbench_v0.1_DensGNN/info.json b/benchmarks/matbench_v0.1_DensGNN/info.json new file mode 100644 index 00000000..3b51eaea --- /dev/null +++ b/benchmarks/matbench_v0.1_DensGNN/info.json @@ -0,0 +1,33 @@ +{ + "authors": "Hongwei Du, Hong Wang (original code by Hongwei Du)", + "algorithm": "DenseGNN (kgcnn v3.0.2)", + "algorithm_long": "DenseGNN: universal and scalable deeper graph neural networks for high performance property prediction in crystals and molecules. Adapted implementation of `kgcnn`. Original code from https://github.com/dhw059/DenseGNN. Initially, features for nodes, edges, and global data are extracted. In each layer of the GNN, the GraphMLP layers transform the node and edge features, while the DenseGNN layer aggregates information from neighbors and global features. The outputs are concatenated and used to update the node features. Finally, the output block processes the updated edge and node features along with global features and edge indices to produce the final output.We used a larger input embedding vector [64] of atom species and added the charge as input graph attributes. The training configuration specifies a batch size of 64, 300 epochs, and validation every 20 batches. It uses the Adam optimizer with an exponential decay learning rate starting at 0.001, decaying every 5800 steps by a rate of 0.5. The loss function is mean absolute error. K-fold cross-validation with 5 splits is applied, and data is standardized using StandardScaler.Training was carried out on Nvidia-RTX4090 with 24 GB of memory.Hyperparameter were not optimized.", + "bibtex_refs": [ + "@article{UnderReview, author = {Hongwei Du, Hong Wang}, title = {DenseGNN: universal and scalable deeper graph neural networks for high-performance property prediction in crystals and molecules}, journal = {npj Computational Materials}, volume = {}, number = {}, pages = {}, year = {2024}, doi = {Under Review}, URL = {}, eprint = {}}" + ], + "notes": "", + "requirements": { + "python": [ + "numpy>=1.23.0", + "scikit-learn>=1.1.3", + "pandas>=1.5.2", + "scipy>=1.9.3", + "pyyaml>=6.0", + "matplotlib>=3.6.0", + "rdkit>=2022.9.2", + "pymatgen>=2022.11.7", + "tensorflow>=2.10.0", + "tensorflow-addons>=0.18.0", + "keras-tuner>=1.1.3", + "requests>=2.28.1", + "networkx>=2.8.8", + "sympy>=1.11.1", + "ase>=3.22.1", + "click>=7.1.2", + "visual_graph_datasets>=0.7.1", + "brotli>=1.0.9", + "pyxtal>=0.5.5", + "h5py>=3.9.0", + ] + } +} diff --git a/benchmarks/matbench_v0.1_DensGNN/results.json.gz b/benchmarks/matbench_v0.1_DensGNN/results.json.gz new file mode 100644 index 00000000..b5182cd4 Binary files /dev/null and b/benchmarks/matbench_v0.1_DensGNN/results.json.gz differ diff --git a/benchmarks/matbench_v0.1_DensGNN/run.py b/benchmarks/matbench_v0.1_DensGNN/run.py new file mode 100644 index 00000000..f7c5f91f --- /dev/null +++ b/benchmarks/matbench_v0.1_DensGNN/run.py @@ -0,0 +1,161 @@ +import os.path +import argparse +import pandas as pd +import tensorflow as tf +from matbench.bench import MatbenchBenchmark +from kgcnn.data.crystal import CrystalDataset +from kgcnn.literature.DenseGNN import make_model_asu + +from sklearn.preprocessing import StandardScaler +from kgcnn.training.schedule import LinearWarmupExponentialDecay +from kgcnn.training.scheduler import LinearLearningRateScheduler +import kgcnn.training.callbacks +from kgcnn.utils.devices import set_devices_gpu +import numpy as np +from copy import deepcopy +from hyper import * + +parser = argparse.ArgumentParser(description='Train DenseGNN.') +parser.add_argument("--gpu", required=False, help="GPU index used for training.", + default=None, nargs="+", type=int) +args = vars(parser.parse_args()) +print("Input of argparse:", args) +gpu_to_use = args["gpu"] +set_devices_gpu(gpu_to_use) + +subsets_compatible = ["matbench_jdft2d", "matbench_phonons", "matbench_mp_gap", + "matbench_perovskites", + "matbench_log_kvrh", "matbench_log_gvrh", "matbench_dielectric"] +mb = MatbenchBenchmark(subset=subsets_compatible, autoload=False) + +callbacks = { + "graph_labels": lambda st, ds: np.expand_dims(ds, axis=-1), + "node_coordinates": lambda st, ds: np.array(st.cart_coords, dtype="float"), + "node_frac_coordinates": lambda st, ds: np.array(st.frac_coords, dtype="float"), + "graph_lattice": lambda st, ds: np.ascontiguousarray(np.array(st.lattice.matrix), dtype="float"), + "abc": lambda st, ds: np.array(st.lattice.abc), + "charge": lambda st, ds: np.array([st.charge], dtype="float"), + "volume": lambda st, ds: np.array([st.lattice.volume], dtype="float"), + "node_number": lambda st, ds: np.array(st.atomic_numbers, dtype="int"), +} + +hyper_all = { + "matbench_jdft2d": hyper_1, + "matbench_phonons": hyper_2, + "matbench_mp_gap": hyper_3, + "matbench_perovskites": hyper_4, + "matbench_log_kvrh": hyper_5, + "matbench_log_gvrh": hyper_6, + "matbench_dielectric": hyper_7, +} + +restart_training = True +remove_invalid_graphs_on_predict = True + +for idx_task, task in enumerate(mb.tasks): + task.load() + for i, fold in enumerate(task.folds): + hyper = deepcopy(hyper_all[task.dataset_name]) + + # Define loss for either classification or regression + loss = { + "class_name": "BinaryCrossentropy", "config": {"from_logits": True} + } if task.metadata["task_type"] == "classification" else "mean_absolute_error" + hyper["training"]["compile"]["loss"] = loss + + if restart_training and os.path.exists( + "%s_predictions_%s_fold_%s.npy" % (task.dataset_name, hyper["model"]["config"]["name"], i)): + predictions = np.load( + "%s_predictions_%s_fold_%s.npy" % (task.dataset_name, hyper["model"]["config"]["name"], i) + ) + task.record(fold, predictions) + continue + + train_inputs, train_outputs = task.get_train_and_val_data(fold) + data_train = CrystalDataset() + + data_train._map_callbacks(train_inputs, pd.Series(train_outputs.values), callbacks) + print("Making graph... (this may take a while)") + data_train.set_methods(hyper["data"]["dataset"]["methods"]) + data_train.clean(hyper["model"]["config"]["inputs"]) + + y_train = np.array(data_train.get("graph_labels")) + x_train = data_train.tensor(hyper["model"]["config"]["inputs"]) + + if task.metadata["task_type"] == "classification": + scaler = None + else: + scaler = StandardScaler(**hyper["training"]["scaler"]["config"]) + y_train = scaler.fit_transform(y_train) + print(y_train.shape) + + # train and validate your model + model = make_model_asu(**hyper["model"]["config"]) + model.compile( + loss=tf.keras.losses.get(hyper["training"]["compile"]["loss"]), + optimizer=tf.keras.optimizers.get(hyper["training"]["compile"]["optimizer"]) + ) + hist = model.fit( + x_train, y_train, + batch_size=hyper["training"]["fit"]["batch_size"], + epochs=hyper["training"]["fit"]["epochs"], + verbose=hyper["training"]["fit"]["verbose"], + callbacks=[tf.keras.utils.deserialize_keras_object(x) for x in hyper["training"]["fit"]["callbacks"]] + ) + + # Get testing data + test_inputs = task.get_test_data(fold, include_target=False) + data_test = CrystalDataset() + data_test._map_callbacks(test_inputs, pd.Series(np.zeros(len(test_inputs))), callbacks) + print("Making graph... (this may take a while)") + data_test.set_methods(hyper["data"]["dataset"]["methods"]) + + if remove_invalid_graphs_on_predict: + removed = data_test.clean(hyper["model"]["config"]["inputs"]) + np.save( + "%s_predictions_invalid_%s_fold_%s.npy" % (task.dataset_name, hyper["model"]["config"]["name"], i), + removed + ) + else: + removed = None + + # Predict on the testing data + x_test = data_test.tensor(hyper["model"]["config"]["inputs"]) + predictions_model = model.predict(x_test) + + if remove_invalid_graphs_on_predict: + indices_test = [j for j in range(len(test_inputs))] + for j in removed: + indices_test.pop(j) + predictions = np.expand_dims(np.zeros(len(test_inputs), dtype="float"), axis=-1) + predictions[np.array(indices_test)] = predictions_model + else: + predictions = predictions_model + + if task.metadata["task_type"] == "classification": + def np_sigmoid(x): + return np.exp(-np.logaddexp(0, -x)) + predictions = np_sigmoid(predictions) + else: + predictions = scaler.inverse_transform(predictions) + + if predictions.shape[-1] == 1: + predictions = np.squeeze(predictions, axis=-1) + + np.save( + "%s_predictions_%s_fold_%s.npy" % (task.dataset_name, hyper["model"]["config"]["name"], i), + predictions + ) + + # Record data! + task.record(fold, predictions) + +# Save your results +mb.to_file("results_densegnn.json.gz") + +for key, values in mb.scores.items(): + factor = 1000.0 if key in ["matbench_jdft2d"] else 1.0 + if key not in ["matbench_mp_is_metal"]: + print(key, factor*values["mae"]["mean"], factor*values["mae"]["std"]) + else: + print(key, values["rocauc"]["mean"], values["rocauc"]["std"])