atomistic-machine-learning/schnetpack

Question about config and model representation

Closed this issue · 15 comments

Hello, thanks a lot for the work! I have a question related to the config .yaml file. I have modified a bit the response.yaml file and tuned it to only predict the energy, forces and dipole moment. With the FieldSchNet representation, it is working well but when I want to change the representation to schnet or paiNN, it gives me the following error:

RuntimeError: One of the differentiated Tensors appears to not have been used in the graph. Set allow_unused=True if this is the desired behavior.

Can I not use representations other than the FieldSchNet for this config file?

Config file modification

# package _global_

defaults:
  - override /model: nnp
  - override /model/representation: field_schnet
  - override /data: custom

run:
  experiment: response

globals:
  cutoff: 5.0
  lr: 1e-4
  energy_key: energy
  forces_key: forces
  dipole_moment_key: dipole_moment
  response_properties:
    - forces
    - dipole_moment

Thanks in advance.
Nitik Bhatia

Hello, Could anyone please suggest me any solution for this?
Thanks!

Hi @nitbha007 ,

do you just want to predict dipole moments and forces? In that case you would need to use the output module DiploeMoment, Atomwise and Forces. Just have a look at the dipole_moment.yaml and at the md17.yaml comfigs. You cann just add the output modules for the dipole moment the configs of your force model.
In case you are working with external fields in your data, you will need to use FieldSchNet.

Does this help?

Best,
Stefaan

Hello,

I'm working on predicting energy, forces, and dipole moment, and I don't have any external fields in my input data. For clarification, I should integrate the "dipole_moment.yaml" section into the existing "md17.yaml" file, right? Will this integration enable me to use models that are different from FieldSchNet and obtained the requisite properties? Furthermore, I'm interested in knowing whether these models (Other than FieldSchNet) will yield the absolute dipole moment value or represent it as a vector.

I have modified the config file but its not working! Could you please check it out?
Thank you.
paiNN_yaml.txt

Hi,
yes this looks reasonable. Don't forget to also add the correct units in the propery_unit_dict for dipole moment.
This config file should allow you to use the SchNet or PaiNN representation. FieldSchNet requires a different structure, so with the new config it will not work anymore.
If you take a look at the DipoleMoment module, you can see the flag predict_magnitude. If True, you will obtain the absolute value and if False you will get the vector representation. What settings you want to use depends on you dataset. I.e. does it include scalar or vectorial labels for the dipole moment?

Hello,
Thanks a lot. It works well. I have specified the units as follows:
data:
distance_unit: Ang
property_units:
energy: eV
forces: eV/Ang
dipole_moment: e*Ang

Can you suggest, how to logically assign the loss_weight?
Thanks.

This looks reasonable, if these are the units of your dataset.
To find the right weights for your training is something you will need to test.
Usually I would check the magnitude of your properties. You could do some basic statistics on your data for that. Then use the weights to bring them to an equal level of magnitude. From that you will need to play around with it. It also depends on what you exactly want your model to do!

Hello,
A silly question. When I am creating my dataset in the schnetpack format:

new_dataset = ASEAtomsData.create(
    './combined_dataset.db',
    distance_unit='Ang',
    property_unit_dict={'energy': 'eV', 'forces': 'eV/Ang', 'dipole_moment':'eAng'}
)
new_dataset.add_systems(property_list, atoms_list)

I can specify the units of the dipole moment as 'eAng' but when I specified the same units for dipole_moment in my config file for training, ase does not accept it and raise an error. And If I dont specify any unit in the config file for dipole moment it works fine and prediction of dipole moment are also fine (in terms of magnitude). Any suggestions here?

Hi,
I am not 100% sure, but can you try e*Ang instead? For both, the dataset and the config.

Hello, It didn't work.

I have tried e*Ang but ase doesn’t recognize 'e'. Then digged in ase/units.py and find out that the symbol for charge is '_e' and it still does not work as it raised the error:

 self.conversions[prop] = spk.units.convert_units(
  File "/scratch/phys/t30424-euspeclab/SchnetPack/conda_env_spk/schnetpack/src/schnetpack/units.py", line 186, in convert_units
    return _parse_unit(src_unit) / _parse_unit(tgt_unit)
  File "/scratch/phys/t30424-euspeclab/SchnetPack/conda_env_spk/schnetpack/src/schnetpack/units.py", line 159, in _parse_unit
    p = conversion_factor(part)
  File "/scratch/phys/t30424-euspeclab/SchnetPack/conda_env_spk/schnetpack/src/schnetpack/units.py", line 138, in _conversion_factor_ase
    return getattr(aseunits, unit)
AttributeError: module 'ase.units' has no attribute '*'

Can you help me with it @Stefaanhess ? Thanks.

Hello @Stefaanhess,

Could you please suggest me something to solve this problem. Thanks!

Hi,
sorry for the late reply. I had to test some stuff myself.
The unit conversion is currently a bit complicated, which is also related to ase.
What I found out so far:

  1. * is not supported for the use in schnetpack units. Instead just use " ".
  2. ase.units does not know e, but e equals 1. This also holds for Ang, eV, ... So instead you could also write 1. as a unit or just leave out e. Unit conversion to e.g. Debye will still work well.

So instead of e*Ang you could either try Ang or just 1.. They are the same and should both work. I tested it:

>>> print(convert_units("Ang", "Debye"))
4.803204672997659
>>> print(convert_units(1., "Debye"))
4.803204672997659

Maybe this is not the cleanest solution, but we will need some time to find a good solution for this.
Let me know if this helps!

Hello,
Yes, it works as the logic of specifying it as 1. holds well.

Is there a possibility to use spkpredict command to know about the training, validation and test set loss on energy, forces and dipole moment? Sometimes, the training does not get completed within the assigned time and I'd like to have a quick check on the model performance (apart from checking the statistics in the logger) on the data it splits.

Thank you.

spkpredict will compute all model predictions for a full database. By using spkpredict on your database and afterwards splitting the predictions using your split file, you could achieve this.
However if you just want to monitor training, I suggest you look at the tensorboard logs of your validation set. Usually the training and validation set should have about the same performance. So I do not see why it would help to manually evaluate the test set...

Hello @Stefaanhess,
I wanted to ask about adding the single atom reference values while creating the dataset. "If you have more diverse data with systems of different composition and size, you might want to add single atom reference values to your dataset as metadata."

# calculate this at the same level of theory as your data
atomref = {
'energy': [0.0, 314.0,  ] # etc.
}

# the supplied list is ordered by atomic number, e.g.:
atomref_hydrogen= atomref['energy'][1]

# dataset = ASEAtomsData.create(
#     './new_dataset.db',
#     distance_unit='Ang',
#     property_unit_dict={'energy':'kcal/mol'},
#     atomref=atomref
# )

If my dataset consists of elements "H", "C", "N", "O", "Cu" then I need to calculate the energy of the mentioned elements and give it as a list in the increasing order of the atomic number. Correct?

Thank you!

Hi @nitbha007 ,
you have to provide the energies in a list where the index of an entry corresponds to the atomic number of the specific element. In your case, these are "H"=1, "C"=6, "N"=7, "O"=8. Therefore, the atomref would look like:

atomref = {
    "energy": [0.0, energy_H, 0.0, 0.0, 0.0, 0.0, energy_C, energy_N, energy_O]
}

Here energy_X is the energy you calculated for element "X".

Hope this helps!
Best regards,
Niklas