Package: crysnet
CrysNetGrysNet is a neural network package that allows researchers to train custom models for crystal modeling tasks. It aims to accelerate the research and application of material science. It provides user a series of state-of-the-art models and supports user's innovative researches.Table of ContentsHightlightsInstallationUsageFrameworkImplemented-modelsContributorsReferencesContactHightlightsEasy to installation.Three steps to fast testing.Flexible and adaptive to user's trainning task.InstallationCrysNet can be installed easily through anaconda! As follows:Create a new conda environment named "crysnet" by command, then activate environment "crysnet":condacreate-ncrysnetpython=3.8condaactivatecrysnetIt's necessary to create a new conda environment to aviod bugs causing by version conflict.Configure dependencies of crysnet:condainstall-cconda-forgetensorflow-gpu==2.6.0Install pymatgen:condainstall--channelconda-forgepymatgenInstall other dependencies:condainstall--channelconda-forgemendeleevcondainstall--channelconda-forgegraphvizcondainstall--channelconda-forgepydotcondainstall--channelconda-forgesklearnInstall crysnet:pipinstallcrysnetUsageQuick startCrysNet is very easy to use!Justthree stepscan finish a fast test using crysnet:download test dataGet test datas fromhttps://github.com/huzongxiang/CrystalNetwork/tree/main/datas/There are three json files in datas: dataset_classification.json, dataset_multiclassification.json and dataset_regression.json.prepare workdirDownload datas and put it in your trainning work directory, test.py file should also be put in the directoryrun commandrun command:pythontest.pyYou have finished your testing multi-classification trainning! The trainning results and model weight could be saved in /results and /models, respectively.Understanding trainning scriptYou can use crysnet by provided trainning scripts in user_easy_trainscript only, but understanding script will help you custom your trainning task!get datasGet current work directory of running trainning script, the script will read datas from 'workdir/datas/' , then saves results and models to 'workdir/results/' and 'workdir/models/'frompathlibimportPathModulePath=Path(__file__).parent.absolute()# workdirfed trainning datasModule Dataset will read data from 'ModulePath/datas/dataset.json', 'task_type' defines regression/classification/multi-classification, 'data_path' gets path of trainning datas.fromcrysnet.dataimportDatasetdataset=Dataset(task_type='multiclassfication',data_path=ModulePath)generatorModule GraphGenerator feds datas into model during trainning. The Module splits datas into train, valid, test sets, and transform structures data into labelled graphs and gets three generators.
BATCH_SIZE is batch size during trainning, DATA_SIZE defines number of datas your used in entire datas, CUTOFF is cutoff of graph edges in crystal.fromcrysnet.data.generatorimportGraphGeneratorBATCH_SIZE=128DATA_SIZE=NoneCUTOFF=2.5Generators=GraphGenerator(dataset,data_size=DATA_SIZE,batch_size=BATCH_SIZE,cutoff=CUTOFF)train_data=Generators.train_generatorvalid_data=Generators.valid_generatortest_data=Generators.test_generator#if task is multiclassfication, should define variable multiclassifictionmulticlassification=Generators.multiclassificationbuilding modelModule GNN defines a trainning framework that accepts a series of models. Crysnet provides a series of mainstream models as your need.fromcrysnet.modelsimportGNNfromcrysnet.models.gnnmodelimportMpnnBaseModel,TransformerBaseModel,CgcnnModel,GraphAttentionModelgnn=GNN(model=MpnnBaseModel,atom_dim=16bond_dim=64num_atom=118state_dim=16sp_dim=230units=32edge_steps=1message_steps=1transform_steps=1num_attention_heads=8dense_units=64output_dim=64readout_units=64dropout=0.0reg0=0.00reg1=0.00reg2=0.00reg3=0.00reg_rec=0.00batch_size=BATCH_SIZEspherical_harmonics=Trueregression=dataset.regressionoptimizer='Adam')trainningUsing trainning function of model to train. Common trainning parameters can be defined, workdir is current directory of trainning script, it saves results of model during trainning. If test_data exists, model will predict on test_data.gnn.train(train_data,valid_data,test_data,epochs=700,lr=3e-3,warm_up=True,load_weights=False,verbose=1,checkpoints=None,save_weights_only=True,workdir=ModulePath)predictionThe simplest method for predicting is using script predict.py in /user_easy_train_scripts.Using predict_data funciton to predict.gnn.predict_datas(test_data,workdir=ModulePath)# predict on test datas with labelsy_pred_keras=gnn.predict(datas)# predict on new datas without labelspreparing your custom datasIf you have your structures (and labels), the Dataset receives pymatgen.core.Structure type. So you should transform your POSCAR or cif to pymatgen.core.Structure type.importosfrompymatgen.core.structureimportStructurestructures=[]# your structure listforcifinos.listdir(cif_path):structures.append(Structure.from_file(cif))# for POSCAR too# construct your datasetfromcrysnet.dataimportDatasetdataset=Dataset(task_type='my_classification',data_path=ModulePath)# task_type could be my_regression, my_classification, my_multiclassificationdataset.prepare_x(structures)dataset.prepare_y(labels)# if you have labels used to trainning model, labels could be None in prediction on new datas without labels# alternatively, you can construct dataset as followdataset.structures=structuresdataset.labels=labels# save your structures and labels to dataset in dataset_my*.jsondataset.save_datasets(strurtures,labels)# for prediction on new datas without labels, Generators has not attribute multiclassification, should assign definite valueGenerators=GraphGenerator(dataset,data_size=DATA_SIZE,batch_size=BATCH_SIZE,cutoff=CUTOFF)# dataset.labels is NoneGenerators.multiclassification=5multiclassification=Generators.multiclassification# multiclassification = 5models provided by crysnetWe provide GraphModel, MpnnBaseModel, TransformerBaseModel, MpnnModel, TransformerModel, DirectionalMpnnModel, DirectionalTransformerModel and CGCNN model according to your demends. TransformerModel, GraphModel and MpnnModel are different models. TransformerModel is a graph transformer. MpnnModel is a massege passing neural network. GraphModel is a combination of TransformerModel and MpnnModel. MpnnBaseModel and TransformerBaseModel don't take directional informations of crystal into count so them run faster. MpnnBaseModel is the fastest model but accuracy is enough for most tasks. TransformerModel can achieve the hightest accuracy in most tasks. The CGCNN model is the crystal graph convolution neural network model. The GraphAttentionModel is the graph attention neural network.fromcrysnet.modelsimportGNNfromcrysnet.models.gnnmodelimportMpnnBaseModel,TransformerBaseModel,DirectionalMpnnModel,DirectionalTransformerModel,MpnnModel,TransformerModel,GraphModel,CgcnnModel,GraphAttentionModelcustom your model and trainningThe Module GNN provides a flexible trainning framework to accept tensorflow.keras.models.Model type customized by user. Yon can custom your model and train the model according to the following example.fromtensorflow.keras.modelsimportModelfromtensorflow.kerasimportlayersfromcrysnet.layersimportMessagePassingfromcrysnet.layersimportPartitionPaddingdefMyModel(bond_dim,atom_dim=16,num_atom=118,state_dim=16,sp_dim=230,units=32,message_steps=1,readout_units=64,batch_size=16,):atom_features=layers.Input((),dtype="int32",name="atom_features_input")atom_features_=layers.Embedding(num_atom,atom_dim,dtype="float32",name="atom_features")(atom_features)bond_features=layers.Input((bond_dim),dtype="float32",name="bond_features")local_env=layers.Input((6),dtype="float32",name="local_env")state_attrs=layers.Input((),dtype="int32",name="state_attrs_input")state_attrs_=layers.Embedding(sp_dim,state_dim,dtype="float32",name="state_attrs")(state_attrs)pair_indices=layers.Input((2),dtype="int32",name="pair_indices")atom_graph_indices=layers.Input((),dtype="int32",name="atom_graph_indices")bond_graph_indices=layers.Input((),dtype="int32",name="bond_graph_indices")pair_indices_per_graph=layers.Input((2),dtype="int32",name="pair_indices_per_graph")x=MessagePassing(message_steps)([atom_features_,edge_features,state_attrs_,pair_indices,atom_graph_indices,bond_graph_indices])x=PartitionPadding(batch_size)([x[0],atom_graph_indices])x=layers.BatchNormalization()(x)x=layers.GlobalAveragePooling1D()(x)x=layers.Dense(readout_units,activation="relu",name='readout0')(x)x=layers.Dense(1,activation="sigmoid",name='final')(x)model=Model(inputs=[atom_features,bond_features,local_env,state_attrs,pair_indices,atom_graph_indices,bond_graph_indices,pair_indices_per_graph],outputs=[x],)returnmodelfromcrysnet.modelsimportGNNgnn=GNN(model=MyModel,atom_dim=16,bond_dim=64,num_atom=118,state_dim=16,sp_dim=230,units=32,message_steps=1,readout_units=64,batch_size=16,optimizer='Adam',regression=False,multiclassification=None,)gnn.train(train_data,valid_data,test_data,epochs=700,lr=3e-3,warm_up=True,load_weights=False,verbose=1,checkpoints=None,save_weights_only=True,workdir=ModulePath)You can set edge as your model output.fromcrysnet.layersimportEdgeMessagePassingdefMyModel(bond_dim,atom_dim=16,num_atom=118,state_dim=16,sp_dim=230,units=32,message_steps=1,readout_units=64,batch_size=16,):atom_features=layers.Input((),dtype="int32",name="atom_features_input")atom_features_=layers.Embedding(num_atom,atom_dim,dtype="float32",name="atom_features")(atom_features)bond_features=layers.Input((bond_dim),dtype="float32",name="bond_features")local_env=layers.Input((6),dtype="float32",name="local_env")state_attrs=layers.Input((),dtype="int32",name="state_attrs_input")state_attrs_=layers.Embedding(sp_dim,state_dim,dtype="float32",name="state_attrs")(state_attrs)pair_indices=layers.Input((2),dtype="int32",name="pair_indices")atom_graph_indices=layers.Input((),dtype="int32",name="atom_graph_indices")bond_graph_indices=layers.Input((),dtype="int32",name="bond_graph_indices")pair_indices_per_graph=layers.Input((2),dtype="int32",name="pair_indices_per_graph")x=EdgeMessagePassing(units,edge_steps,kernel_regularizer=l2(reg0),sph=spherical_harmonics)([bond_features,local_env,pair_indices])x=PartitionPadding(batch_size)([x[1],bond_graph_indices])x=layers.BatchNormalization()(x)x=layers.GlobalAveragePooling1D()(x)x=layers.Dense(readout_units,activation="relu",name='readout0')(x)x=layers.Dense(readout_units//2,activation="relu",name='readout1')(x)x=layers.Dense(1,name='final')(x)model=Model(inputs=[atom_features,bond_features,local_env,state_attrs,pair_indices,atom_graph_indices,bond_graph_indices,pair_indices_per_graph],outputs=[x],)returnmodelThe Module GNN has some basic parameter necessary to be defined but not necessary to be used:classGNN:def__init__(self,model:Model,atom_dim=16,bond_dim=32,num_atom=118,state_dim=16,sp_dim=230,batch_size=16,regression=True,optimizer='Adam',multiclassification=None,**kwargs,):"""pass"""FrameworkCrysNetImplemented-modelsWe list currently supported GNN models:GCNfrom Kipf and Welling:Semi-Supervised Classification with Graph Convolutional Networks(ICLR 2017)GATfrom Veličkovićet al.:Graph Attention Networks(ICLR 2018)GNfrom Battagliaet al.:Relational inductive biases, deep learning, and graph networksTransformerfrom Vaswaniet al.:Attention Is All You Need(NIPS 2017)ContributorsZongxiang HuReferencesContactPlease contact me if you have any questions.Mail:huzongxiang@yahoo.comWechat: voodoozx2015