mlatom 2.0.1__py3.7.egg

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. EGG-INFO/PKG-INFO +145 -0
  2. EGG-INFO/SOURCES.txt +40 -0
  3. EGG-INFO/dependency_links.txt +1 -0
  4. EGG-INFO/native_libs.txt +1 -0
  5. EGG-INFO/not-zip-safe +1 -0
  6. EGG-INFO/requires.txt +2 -0
  7. EGG-INFO/scripts/MLatomF +12 -0
  8. EGG-INFO/scripts/mlatom +12 -0
  9. EGG-INFO/top_level.txt +1 -0
  10. MLatom/ML_NEA.py +2697 -0
  11. MLatom/MLatom.py +151 -0
  12. MLatom/MLatomF +0 -0
  13. MLatom/MLtasks.py +784 -0
  14. MLatom/__init__.py +0 -0
  15. MLatom/__pycache__/ML_NEA.cpython-37.pyc +0 -0
  16. MLatom/__pycache__/MLatom.cpython-37.pyc +0 -0
  17. MLatom/__pycache__/MLtasks.cpython-37.pyc +0 -0
  18. MLatom/__pycache__/__init__.cpython-37.pyc +0 -0
  19. MLatom/__pycache__/args_class.cpython-37.pyc +0 -0
  20. MLatom/__pycache__/doc.cpython-37.pyc +0 -0
  21. MLatom/__pycache__/header.cpython-37.pyc +0 -0
  22. MLatom/__pycache__/interface_MLatomF.cpython-37.pyc +0 -0
  23. MLatom/__pycache__/sliceData.cpython-37.pyc +0 -0
  24. MLatom/__pycache__/stopper.cpython-37.pyc +0 -0
  25. MLatom/args_class.py +396 -0
  26. MLatom/cs.so +0 -0
  27. MLatom/doc.py +620 -0
  28. MLatom/header.py +64 -0
  29. MLatom/interface_MLatomF.py +87 -0
  30. MLatom/interfaces/DeePMDkit/DP_inference.py +20 -0
  31. MLatom/interfaces/DeePMDkit/__init__.py +0 -0
  32. MLatom/interfaces/DeePMDkit/__pycache__/DP_inference.cpython-37.pyc +0 -0
  33. MLatom/interfaces/DeePMDkit/__pycache__/__init__.cpython-37.pyc +0 -0
  34. MLatom/interfaces/DeePMDkit/__pycache__/interface_DeePMDkit.cpython-37.pyc +0 -0
  35. MLatom/interfaces/DeePMDkit/interface_DeePMDkit.py +327 -0
  36. MLatom/interfaces/DeePMDkit/template.json +70 -0
  37. MLatom/interfaces/GAP/__init__.py +0 -0
  38. MLatom/interfaces/GAP/__pycache__/__init__.cpython-37.pyc +0 -0
  39. MLatom/interfaces/GAP/__pycache__/interface_GAP.cpython-37.pyc +0 -0
  40. MLatom/interfaces/GAP/interface_GAP.py +415 -0
  41. MLatom/interfaces/PhysNet/PhysNet_predict.py +180 -0
  42. MLatom/interfaces/PhysNet/PhysNet_train.py +425 -0
  43. MLatom/interfaces/PhysNet/__init__.py +0 -0
  44. MLatom/interfaces/PhysNet/__pycache__/PhysNet_predict.cpython-37.pyc +0 -0
  45. MLatom/interfaces/PhysNet/__pycache__/PhysNet_train.cpython-37.pyc +0 -0
  46. MLatom/interfaces/PhysNet/__pycache__/__init__.cpython-37.pyc +0 -0
  47. MLatom/interfaces/PhysNet/__pycache__/interface_PhysNet.cpython-37.pyc +0 -0
  48. MLatom/interfaces/PhysNet/interface_PhysNet.py +270 -0
  49. MLatom/interfaces/TorchANI/TorchANI_predict.py +82 -0
  50. MLatom/interfaces/TorchANI/TorchANI_train.py +217 -0
  51. MLatom/interfaces/TorchANI/__init__.py +0 -0
  52. MLatom/interfaces/TorchANI/__pycache__/TorchANI_predict.cpython-37.pyc +0 -0
  53. MLatom/interfaces/TorchANI/__pycache__/TorchANI_train.cpython-37.pyc +0 -0
  54. MLatom/interfaces/TorchANI/__pycache__/__init__.cpython-37.pyc +0 -0
  55. MLatom/interfaces/TorchANI/__pycache__/interface_TorchANI.cpython-37.pyc +0 -0
  56. MLatom/interfaces/TorchANI/interface_TorchANI.py +323 -0
  57. MLatom/interfaces/__init__.py +0 -0
  58. MLatom/interfaces/__pycache__/__init__.cpython-37.pyc +0 -0
  59. MLatom/interfaces/sGDML/__init__.py +0 -0
  60. MLatom/interfaces/sGDML/__pycache__/__init__.cpython-37.pyc +0 -0
  61. MLatom/interfaces/sGDML/__pycache__/interface_sGDML.cpython-37.pyc +0 -0
  62. MLatom/interfaces/sGDML/__pycache__/sgdml_dataset_from_extxyz.cpython-37.pyc +0 -0
  63. MLatom/interfaces/sGDML/interface_sGDML.py +276 -0
  64. MLatom/interfaces/sGDML/sgdml_dataset_from_extxyz.py +199 -0
  65. MLatom/ref.json +23 -0
  66. MLatom/sliceData.py +334 -0
  67. MLatom/stopper.py +17 -0
@@ -0,0 +1,270 @@
1
+ #!/usr/bin/python3
2
+ '''
3
+ !---------------------------------------------------------------------------!
4
+ ! Interface_PhysNet: Interface between PhysNet and MLatom !
5
+ ! Implementations by: Fuchun Ge and Max Pinheiro Jr !
6
+ !---------------------------------------------------------------------------!
7
+ '''
8
+ import numpy as np
9
+ import os, sys, subprocess, time, shutil, re, math, random
10
+ import stopper
11
+ from args_class import ArgsBase
12
+
13
+ filedir = os.path.dirname(__file__)
14
+
15
+ class Args(ArgsBase):
16
+ def __init__(self):
17
+ super().__init__()
18
+ self.add_default_dict_args([
19
+ 'learningCurve'
20
+ ],
21
+ bool
22
+ )
23
+ self.add_default_dict_args([
24
+ 'xyzfile', 'yfile', 'ygradxyzfile','itrainin','itestin','isubtrainin','ivalidatein','mlmodelin','setname'
25
+ ],
26
+ ""
27
+ )
28
+ self.add_dict_args({
29
+ 'mlmodeltype': 'PhysNet',
30
+ 'mlmodelout': "PhysNet",
31
+ 'sampling': "random",
32
+ 'yestfile': "enest.dat",
33
+ 'ygradxyzestfile': "gradest.dat",
34
+ 'lcNtrains': [],
35
+ 'natom': 0,
36
+ 'atype': []
37
+ })
38
+ self.parse_input_content([
39
+ 'physnet.batch_sizes=0',
40
+ 'physnet.restart=0',
41
+ 'physnet.num_features=128',
42
+ 'physnet.num_basis=64',
43
+ 'physnet.num_blocks=5',
44
+ 'physnet.num_residual_atomic=2',
45
+ 'physnet.num_residual_interaction=3',
46
+ 'physnet.num_residual_output=1',
47
+ 'physnet.cutoff=10.0',
48
+ 'physnet.use_electrostatic=0',
49
+ 'physnet.use_dispersion=0',
50
+ 'physnet.grimme_s6=0.5',
51
+ 'physnet.grimme_s8=0.2130',
52
+ 'physnet.grimme_a1=0.0',
53
+ 'physnet.grimme_a2=6.0519',
54
+ 'physnet.num_train=8',
55
+ 'physnet.num_valid=2',
56
+ 'physnet.seed=42',
57
+ 'physnet.max_steps=10000000',
58
+ 'physnet.learning_rate=0.0008',
59
+ 'physnet.max_norm=1000.0',
60
+ 'physnet.ema_decay=0.999',
61
+ 'physnet.keep_prob=1.0',
62
+ 'physnet.l2lambda=0.0',
63
+ 'physnet.nhlambda=0.01',
64
+ 'physnet.decay_steps=10000000',
65
+ 'physnet.decay_rate=0.1',
66
+ 'physnet.batch_size=12',
67
+ 'physnet.valid_batch_size=2',
68
+ 'physnet.force_weight=52.91772105638412',
69
+ 'physnet.charge_weight=0',
70
+ 'physnet.dipole_weight=0',
71
+ 'physnet.summary_interval=5',
72
+ 'physnet.validation_interval=5',
73
+ 'physnet.save_interval=10',
74
+ 'physnet.record_run_metadata=0'
75
+ ])
76
+ def parse(self, argsraw):
77
+ self.parse_input_content(argsraw)
78
+ self.argProcess()
79
+
80
+ def argProcess(self):
81
+ with open(self.xyzfile,'r') as f:
82
+ self.natom = int(f.readline())
83
+ exec('f.readline()')
84
+ self.atype = [f.readline().split()[0] for i in range(self.natom)]
85
+ if not self.mlmodelin:
86
+ self.mlmodelin = self.mlmodelout
87
+ if not self.ygradxyzfile:
88
+ self.physnet.force_weight=0
89
+
90
+ if self.learningcurve:
91
+ self.lcNtrains = [int(i) for i in str(self.lcNtrains).split(',')]
92
+ if self.physnet.batch_sizes:
93
+ self.physnet.batch_sizes = [int(i) for i in self.lcNtrains.split(',')]
94
+ self.physnet.batch_size = self.physnet.batch_sizes[self.lcNtrains.index(self.ntrain)]
95
+
96
+ class PhysNetCls(object):
97
+ dataConverted = False
98
+
99
+ @classmethod
100
+ def load(cls):
101
+ loaded=False
102
+ if not loaded:
103
+
104
+ sp_z = {'X': 0, 'H': 1, 'He': 2, 'Li': 3, 'Be': 4, 'B': 5, 'C': 6, 'N': 7, 'O': 8, 'F': 9, 'Ne': 10, 'Na': 11, 'Mg': 12, 'Al': 13, 'Si': 14, 'P': 15, 'S': 16, 'Cl': 17, 'Ar': 18, 'K': 19, 'Ca': 20, 'Sc': 21, 'Ti': 22, 'V': 23, 'Cr': 24, 'Mn': 25, 'Fe': 26, 'Co': 27, 'Ni': 28, 'Cu': 29, 'Zn': 30, 'Ga': 31, 'Ge': 32, 'As': 33, 'Se': 34, 'Br': 35, 'Kr': 36, 'Rb': 37, 'Sr': 38, 'Y': 39, 'Zr': 40, 'Nb': 41, 'Mo': 42, 'Tc': 43, 'Ru': 44, 'Rh': 45, 'Pd': 46, 'Ag': 47, 'Cd': 48, 'In': 49, 'Sn': 50, 'Sb': 51, 'Te': 52, 'I': 53, 'Xe': 54, 'Cs': 55, 'Ba': 56, 'La': 57, 'Ce': 58, 'Pr': 59, 'Nd': 60, 'Pm': 61, 'Sm': 62, 'Eu': 63, 'Gd': 64, 'Tb': 65, 'Dy': 66, 'Ho': 67, 'Er': 68, 'Tm': 69, 'Yb': 70, 'Lu': 71, 'Hf': 72, 'Ta': 73, 'W': 74, 'Re': 75, 'Os': 76, 'Ir': 77, 'Pt': 78, 'Au': 79, 'Hg': 80, 'Tl': 81, 'Pb': 82, 'Bi': 83, 'Po': 84, 'At': 85, 'Rn': 86, 'Fr': 87, 'Ra': 88, 'Ac': 89, 'Th': 90, 'Pa': 91, 'U': 92, 'Np': 93, 'Pu': 94, 'Am': 95, 'Cm': 96, 'Bk': 97, 'Cf': 98, 'Es': 99, 'Fm': 100, 'Md': 101, 'No': 102, 'Lr': 103, 'Rf': 104, 'Db': 105, 'Sg': 106, 'Bh': 107, 'Hs': 108, 'Mt': 109, 'Ds': 110, 'Rg': 111, 'Cn': 112, 'Uut': 113, 'Fl': 114, 'Uup': 115, 'Lv': 116, 'Uus': 117, 'Uuo': 118}
105
+
106
+ z_sp = {v:k for k,v in sp_z.items()}
107
+ try:
108
+ from . import PhysNet_train
109
+ from . import PhysNet_predict
110
+ except:
111
+ stopper.stopMLatom('Please specify PhysNet installation dir in $PhysNet')
112
+
113
+ globals()['z_sp'] = z_sp
114
+ globals()['sp_z'] = sp_z
115
+ globals()['PhysNet_train'] = PhysNet_train
116
+ globals()['PhysNet_predict'] = PhysNet_predict
117
+ loaded=True
118
+
119
+
120
+ def __init__(self, argsPhysNet = sys.argv[1:]):
121
+ print(' ___________________________________________________________\n\n%s' % __doc__)
122
+
123
+ @classmethod
124
+ def convertdata(cls, argsPhysNet, subdatasets):
125
+ cls.load()
126
+ def convert(fileout, setname, yorgrad=False):
127
+ # convert data to .h5 format
128
+ prefix = ''
129
+ if args.learningcurve: prefix = '../'
130
+ if setname:
131
+ coordfile = prefix+'xyz.dat_'+setname
132
+ yfile = prefix+'y.dat_'+setname
133
+ gradfile = prefix+'grad.dat_'+setname
134
+ else:
135
+ coordfile = args.xyzfile
136
+ if args.yfile and yorgrad: yfile = args.yfile
137
+ if args.ygradxyzfile and yorgrad: gradfile = args.ygradxyzfile
138
+ with open(coordfile ,'r') as fxyz:
139
+ natom = int(fxyz.readline())
140
+ fxyz.seek(0)
141
+ data={}
142
+ data['R'] = np.array([])
143
+ data['Z'] = np.array([])
144
+ data['N'] = np.array([])
145
+ if args.yfile and yorgrad:
146
+ fy = open(yfile,'r')
147
+ data['E'] = np.array([])
148
+ if args.ygradxyzfile and yorgrad:
149
+ fgrad = open(gradfile,'r')
150
+ data['F'] = np.array([])
151
+ for line in fxyz:
152
+ # 1st line
153
+ data['N'] = np.append(data['N'], int(line)).astype('int')
154
+ if args.ygradxyzfile and yorgrad: fgrad.readline()
155
+ if args.yfile and yorgrad: data['E'] =np.append(data['E'], float(fy.readline()))
156
+ # 2nd line
157
+ fxyz.readline()
158
+ if args.ygradxyzfile and yorgrad: fgrad.readline()
159
+ # rest lines
160
+ for i in range(natom):
161
+ ln = fxyz.readline()
162
+ data['Z'] = np.append(data['Z'], sp_z[ln.split()[0].capitalize()])
163
+ data['R'] = np.append(data['R'], [float(i) for i in ln.split()[-3:]])
164
+ if args.ygradxyzfile and yorgrad: data['F'] = np.append(data['F'], [-1*float(i) for i in fgrad.readline().split()[-3:]])
165
+
166
+ if args.yfile and yorgrad: fy.close()
167
+ if args.ygradxyzfile and yorgrad: fgrad.close()
168
+ data['R'] = data['R'].reshape(-1,natom,3)
169
+ data['Z'] = data['Z'].reshape(-1,natom).astype('int')
170
+ if args.ygradxyzfile and yorgrad: data['F'] = data['F'].reshape(-1,natom,3)
171
+
172
+ np.savez(fileout, **data)
173
+
174
+
175
+ args = Args()
176
+ args.parse(argsPhysNet)
177
+ print('\n Converting data...\n\n')
178
+ if subdatasets:
179
+ if 'Subtrain' in subdatasets:
180
+ for i in subdatasets:
181
+ if i in ['Subtrain', 'Validate']: convert('PhysNet_'+i.lower()+'.npz', i.lower(),True)
182
+ else: convert('PhysNet_'+i.lower()+'.npz', i.lower())
183
+ else:
184
+ for i in subdatasets:
185
+ if i == 'Train': convert('PhysNet_'+i.lower()+'.npz', i.lower(),True)
186
+ else: convert('PhysNet_'+i.lower()+'.npz', i.lower())
187
+ else: convert('PhysNet.npz', '')
188
+
189
+ @classmethod
190
+ def createMLmodel(cls, argsPhysNet, subdatasets):
191
+ cls.load()
192
+ PNargs = Args()
193
+ PNargs.parse(argsPhysNet)
194
+
195
+ if not cls.dataConverted or PNargs.learningcurve:
196
+ cls.convertdata(argsPhysNet, subdatasets)
197
+ cls.dataConverted = True
198
+
199
+ starttime = time.time()
200
+
201
+ PhysNet_train.train(PNargs)
202
+
203
+ endtime = time.time()
204
+ wallclock = endtime - starttime
205
+ return wallclock
206
+
207
+ @classmethod
208
+ def useMLmodel(cls, argsPhysNet, subdatasets):
209
+ cls.load()
210
+ PNargs = Args()
211
+ PNargs.parse(argsPhysNet)
212
+
213
+ if not cls.dataConverted:
214
+ cls.convertdata(argsPhysNet, subdatasets)
215
+ cls.dataConverted = True
216
+
217
+ starttime = time.time()
218
+ PhysNet_predict.predict(PNargs)
219
+ endtime = time.time()
220
+ wallclock = endtime - starttime
221
+ return wallclock
222
+
223
+ def printHelp():
224
+ helpText = __doc__ + '''
225
+ To use Interface_PhysNet, please define $PhysNet to where PhysNet is located
226
+
227
+ Arguments with their default values:
228
+ MLprog=PhysNet enables this interface
229
+ MLmodelType=PhysNet requests PhysNet model
230
+
231
+ physnet.num_features=128 number of input features
232
+ physnet.num_basis=64 number of radial basis functions
233
+ physnet.num_blocks=5 number of stacked modular building blocks
234
+
235
+ physnet.num_residual_atomic=2
236
+ number of residual blocks for
237
+ atom-wise refinements
238
+ physnet.num_residual_interaction=3
239
+ number of residual blocks for
240
+ refinements of proto-message
241
+ physnet.num_residual_output=1
242
+ number of residual blocks in
243
+ output blocks
244
+ physnet.cutoff=10.0 cutoff radius for interactions
245
+ in the neural network
246
+ physnet.seed=42 random seed
247
+ physnet.max_steps=32 max steps to perform in training
248
+ physnet.learning_rate=0.0008
249
+ starting learning rate
250
+ physnet.decay_steps=10000000
251
+ decay steps
252
+ physnet.decay_rate=0.1 decay rate for learning rate
253
+ physnet.batch_size=12 training batch size
254
+ physnet.valid_batch_size=2 validation batch size
255
+ physnet.force_weight=52.91772105638412
256
+ weight for force
257
+ physnet.charge_weight=0 weight for charge
258
+ physnet.dipole_weight=0 weight for dipole
259
+ physnet.summary_interval=5 interval for summary
260
+ physnet.validation_interval=5
261
+ interval for validation
262
+ physnet.save_interval=10 interval for model saving
263
+
264
+ Cite PhysNet:
265
+ O. T. Unke, M. Meuwly, J. Chem. Theory Comput. 2019, 15, 3678
266
+ '''
267
+ print(helpText)
268
+
269
+ if __name__ == '__main__':
270
+ PhysNetCls()
@@ -0,0 +1,82 @@
1
+ import torch
2
+ import torchani
3
+ import os
4
+ import math
5
+ import torch.utils.tensorboard
6
+ import tqdm
7
+ import numpy as np
8
+ import h5py
9
+
10
+ def predict(args):
11
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
12
+
13
+ species_order = sorted(set(args.atype), key=lambda x: args.atype.index(x))
14
+ energyOffset = 0
15
+
16
+ # if args.mlmodeltype.lower() == 'ani1x':
17
+ # model = torchani.models.ANI1x(periodic_table_index=True).to(device)
18
+ # elif args.mlmodeltype.lower() == 'ani1ccx':
19
+ # model = torchani.models.ANI1ccx(periodic_table_index=True).to(device)
20
+ # elif args.mlmodeltype.lower() == 'ani2x':
21
+ # model = torchani.models.ANI2x(periodic_table_index=True).to(device)
22
+ if False:
23
+ pass
24
+ else:
25
+ best_model = torch.load(args.mlmodelin)
26
+
27
+ Rcr = best_model['args']['Rcr']
28
+ Rca = best_model['args']['Rca']
29
+ EtaR = best_model['args']['EtaR'].to(device)
30
+ ShfR = best_model['args']['ShfR'].to(device)
31
+ Zeta = best_model['args']['Zeta'].to(device)
32
+ ShfZ = best_model['args']['ShfZ'].to(device)
33
+ EtaA = best_model['args']['EtaA'].to(device)
34
+ ShfA = best_model['args']['ShfA'].to(device)
35
+
36
+
37
+ num_species = len(species_order)
38
+
39
+ self_energies=best_model['args']['self_energies']
40
+ energyOffset=best_model['args']['energyOffset']
41
+
42
+ aev_computer = torchani.AEVComputer(Rcr, Rca, EtaR, ShfR, EtaA, Zeta, ShfA, ShfZ, num_species)
43
+ aev_dim = aev_computer.aev_length
44
+ networkdic = best_model['network']
45
+
46
+ nn = torchani.ANIModel([networkdic[specie] for specie in species_order])
47
+ nn.load_state_dict(best_model['nn'])
48
+
49
+ model = torchani.nn.Sequential(aev_computer, nn).to(device)
50
+ model.eval()
51
+
52
+ batch_size = args.ani.batch_size
53
+
54
+ if args.setname: args.setname='_'+args.setname
55
+ testfile=h5py.File('ANI'+args.setname+'.h5','r')
56
+ test=testfile.get('dataset').get('molecule')
57
+ all_coordinates=torch.tensor(test.get('coordinates')[()]).to(device).float()
58
+
59
+ with open(args.yestfile,'wb') as fy, open(args.ygradxyzestfile,'wb') as fgrad:
60
+ for i in range(math.ceil(len(all_coordinates)/batch_size)):
61
+ coordinates=all_coordinates[batch_size*i:min(batch_size*(i+1),len(all_coordinates))].requires_grad_(True)
62
+
63
+ species=test.get('species')[()]
64
+ species=torch.tensor([[species_order.index(i.decode('ascii')) for i in species] for j in range(len(coordinates))]).to(device)
65
+
66
+ _, predicted_energies = model((species, coordinates))
67
+ predicted_forces = -torch.autograd.grad(predicted_energies.sum(), coordinates, create_graph=True, retain_graph=True)[0]
68
+ if args.ygradxyzfile:
69
+ predicted_energies = np.array(predicted_energies.cpu().detach().numpy()).reshape(-1,1)+energyOffset
70
+ predicted_forces = np.array(predicted_forces.cpu().detach().numpy()).reshape(-1, args.natom, 3)
71
+ else:
72
+ predicted_energies = np.array(predicted_energies.cpu().detach().numpy()).reshape(-1,1)+energyOffset
73
+ predicted_forces = np.array(predicted_forces.cpu().detach().numpy()).reshape(-1, args.natom, 3)
74
+
75
+ np.savetxt(fy, predicted_energies, fmt='%20.12f', delimiter=" ")
76
+ line="%d\n\n" % args.natom
77
+ for force in predicted_forces:
78
+ fgrad.write(line.encode('utf-8'))
79
+ np.savetxt(fgrad, -1*force, fmt='%20.12f', delimiter=" ")
80
+
81
+ import time
82
+ time.sleep(0.0000001) # Sometimes program hangs without no reason, adding short sleep time helps to exit this module without a problem / P.O.D., 2021-02-17
@@ -0,0 +1,217 @@
1
+ import torch
2
+ import torchani
3
+ import os
4
+ import sys
5
+ import math
6
+ import torch.utils.tensorboard
7
+ import tqdm
8
+ import numpy as np
9
+
10
+ def train(args):
11
+
12
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
13
+ print('Training with %s'% device)
14
+
15
+ Rcr = args.ani.Rcr
16
+ Rca = args.ani.Rca
17
+ EtaR = args.ani.EtaR.to(device)
18
+ ShfR = args.ani.ShfR.to(device)
19
+ Zeta = args.ani.Zeta.to(device)
20
+ ShfZ = args.ani.ShfZ.to(device)
21
+ EtaA = args.ani.EtaA.to(device)
22
+ ShfA = args.ani.ShfA.to(device)
23
+
24
+
25
+
26
+ max_epochs = args.ani.max_epochs
27
+ early_stopping_learning_rate = args.ani.early_stopping_learning_rate
28
+ if args.ygradxyzfile:
29
+ force_coefficient = args.ani.force_coefficient
30
+ best_model_checkpoint = args.mlmodelout
31
+
32
+
33
+ species_order = sorted(set(args.atype), key=lambda x: args.atype.index(x))
34
+ num_species = len(species_order)
35
+ energy_shifter = torchani.utils.EnergyShifter(None)
36
+
37
+
38
+ trainfile = 'ANI_subtrain.h5'
39
+ validaefile = 'ANI_validate.h5'
40
+
41
+ batch_size = args.ani.batch_size
42
+ if args.ygradxyzfile:
43
+ training = torchani.data.load(trainfile, additional_properties=('forces',)).subtract_self_energies(energy_shifter, species_order).species_to_indices(species_order).shuffle()
44
+ energyOffset=sum([np.array(energy_shifter.self_energies)[species_order.index(i)] for i in args.atype])
45
+ validation= torchani.data.load(validaefile, additional_properties=('forces',)).subtract_self_energies(energy_shifter, species_order).species_to_indices(species_order).shuffle()
46
+ else:
47
+ training = torchani.data.load(trainfile).subtract_self_energies(energy_shifter, species_order).species_to_indices(species_order).shuffle()
48
+ energyOffset=sum([np.array(energy_shifter.self_energies)[species_order.index(i)] for i in args.atype])
49
+ validation = torchani.data.load(validaefile).subtract_self_energies(energy_shifter, species_order).species_to_indices(species_order).shuffle()
50
+
51
+ training = training.collate(batch_size).cache()
52
+ validation = validation.collate(batch_size).cache()
53
+
54
+ # print('Self atomic energies: ', energy_shifter.self_energies)
55
+
56
+ energyOffset1=sum([np.array(energy_shifter.self_energies)[species_order.index(i)] for i in args.atype])
57
+
58
+ deltaOffset=energyOffset-energyOffset1
59
+
60
+ argdic = {'Rcr': Rcr, 'Rca': Rca, 'EtaR': EtaR, 'ShfR': ShfR, 'Zeta': Zeta, 'ShfZ': ShfZ, 'EtaA': EtaA, 'ShfA': ShfA, 'self_energies': np.array(energy_shifter.self_energies),'energyOffset':energyOffset}
61
+
62
+
63
+ aev_computer = torchani.AEVComputer(Rcr, Rca, EtaR, ShfR, EtaA, Zeta, ShfA, ShfZ, num_species)
64
+ aev_dim = aev_computer.aev_length
65
+ networkdic ={}
66
+ for i, specie in enumerate(species_order):
67
+ networkdic[specie] = torch.nn.Sequential(
68
+ torch.nn.Linear(aev_dim, int(args.ani.Neuron_l1[i])),
69
+ torch.nn.CELU(0.1),
70
+ torch.nn.Linear(int(args.ani.Neuron_l1[i]), int(args.ani.Neuron_l2[i])),
71
+ torch.nn.CELU(0.1),
72
+ torch.nn.Linear(int(args.ani.Neuron_l2[i]), int(args.ani.Neuron_l3[i])),
73
+ torch.nn.CELU(0.1),
74
+ torch.nn.Linear(int(args.ani.Neuron_l3[i]), 1)
75
+ )
76
+ nn = torchani.ANIModel([networkdic[specie] for specie in species_order])
77
+
78
+ def init_params(m):
79
+ if isinstance(m, torch.nn.Linear):
80
+ torch.nn.init.kaiming_normal_(m.weight, a=1.0)
81
+ torch.nn.init.zeros_(m.bias)
82
+
83
+ nn.apply(init_params)
84
+
85
+ print('batch_size: %s' % batch_size)
86
+
87
+ print('Neural Network Structure:\n', nn)
88
+
89
+
90
+ model = torchani.nn.Sequential(aev_computer, nn).to(device)
91
+
92
+ wlist2d = [
93
+ [
94
+ {'params': [networkdic[specie][0].weight]},
95
+ {'params': [networkdic[specie][2].weight], 'weight_decay': 0.00001},
96
+ {'params': [networkdic[specie][4].weight], 'weight_decay': 0.000001},
97
+ {'params': [networkdic[specie][6].weight]},
98
+ ]
99
+ for specie in species_order
100
+ ]
101
+
102
+ AdamW = torch.optim.AdamW([i for j in wlist2d for i in j])
103
+
104
+ blist2d = [
105
+ [
106
+ {'params': [networkdic[specie][0].bias]},
107
+ {'params': [networkdic[specie][2].bias]},
108
+ {'params': [networkdic[specie][4].bias]},
109
+ {'params': [networkdic[specie][6].bias]},
110
+ ]
111
+ for specie in species_order
112
+ ]
113
+
114
+ SGD = torch.optim.SGD([i for j in blist2d for i in j], lr=1e-3)
115
+
116
+ AdamW_scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(AdamW, factor=args.ani.lrfactor, patience=args.ani.patience, threshold=0)
117
+ SGD_scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(SGD, factor=args.ani.lrfactor, patience=args.ani.patience, threshold=0)
118
+
119
+ latest_checkpoint = 'latest.pt'
120
+
121
+ if os.path.isfile(latest_checkpoint):
122
+ checkpoint = torch.load(latest_checkpoint)
123
+ nn.load_state_dict(checkpoint['nn'])
124
+ AdamW.load_state_dict(checkpoint['AdamW'])
125
+ SGD.load_state_dict(checkpoint['SGD'])
126
+ AdamW_scheduler.load_state_dict(checkpoint['AdamW_scheduler'])
127
+ SGD_scheduler.load_state_dict(checkpoint['SGD_scheduler'])
128
+
129
+ def validate():
130
+ # run validation
131
+ mse_sum = torch.nn.MSELoss(reduction='sum')
132
+ total_mse = 0.0
133
+ count = 0
134
+ for properties in validation:
135
+ species = properties['species'].to(device)
136
+ coordinates = properties['coordinates'].to(device).float()
137
+ true_energies = properties['energies'].to(device).float()
138
+ _, predicted_energies = model((species, coordinates))
139
+ # print(true_energies-deltaOffset,'\n\n',predicted_energies)
140
+ total_mse += mse_sum(predicted_energies, true_energies-deltaOffset).item()
141
+ count += predicted_energies.shape[0]
142
+ return math.sqrt(total_mse / count)
143
+
144
+ tensorboard = torch.utils.tensorboard.SummaryWriter()
145
+
146
+ mse = torch.nn.MSELoss(reduction='none')
147
+
148
+ print("training starting from epoch", AdamW_scheduler.last_epoch + 1)
149
+
150
+ for _ in range(AdamW_scheduler.last_epoch + 1, max_epochs):
151
+ rmse = validate()
152
+ print('RMSE:', rmse, 'at epoch', AdamW_scheduler.last_epoch + 1)
153
+ sys.stdout.flush()
154
+
155
+ learning_rate = AdamW.param_groups[0]['lr']
156
+ print('learning_rate:',learning_rate)
157
+
158
+ if learning_rate < early_stopping_learning_rate:
159
+ break
160
+
161
+ if AdamW_scheduler.is_better(rmse, AdamW_scheduler.best):
162
+ torch.save(
163
+ {
164
+ 'network': networkdic,
165
+ 'args': argdic,
166
+ 'nn': nn.state_dict()
167
+ }
168
+ , best_model_checkpoint
169
+ )
170
+ print('best model saved')
171
+ AdamW_scheduler.step(rmse)
172
+ SGD_scheduler.step(rmse)
173
+
174
+ tensorboard.add_scalar('validation_rmse', rmse, AdamW_scheduler.last_epoch)
175
+ tensorboard.add_scalar('best_validation_rmse', AdamW_scheduler.best, AdamW_scheduler.last_epoch)
176
+ tensorboard.add_scalar('learning_rate', learning_rate, AdamW_scheduler.last_epoch)
177
+ for i, properties in tqdm.tqdm(
178
+ enumerate(training),
179
+ total=len(training),
180
+ desc="epoch {}".format(AdamW_scheduler.last_epoch)
181
+ ):
182
+ species = properties['species'].to(device)
183
+
184
+ if args.ygradxyzfile:
185
+ coordinates = properties['coordinates'].to(device).float().requires_grad_(True)
186
+ true_energies = properties['energies'].to(device).float()
187
+ true_forces = properties['forces'].to(device).float()
188
+ num_atoms = (species >= 0).sum(dim=1, dtype=true_energies.dtype)
189
+ _, predicted_energies = model((species, coordinates))
190
+ forces = -torch.autograd.grad(predicted_energies.sum(), coordinates, create_graph=True, retain_graph=True)[0]
191
+ energy_loss = (mse(predicted_energies, true_energies) / num_atoms.sqrt()).mean()
192
+ force_loss = (mse(true_forces, forces).sum(dim=(1, 2)) / num_atoms).mean()
193
+ loss = energy_loss + force_coefficient * force_loss
194
+ # print('\n\n',true_energies+energyOffset,'\n\n',predicted_energies+energyOffset)
195
+ else:
196
+ coordinates = properties['coordinates'].to(device).float()
197
+ true_energies = properties['energies'].to(device).float()
198
+ num_atoms = (species >= 0).sum(dim=1, dtype=true_energies.dtype)
199
+ _, predicted_energies = model((species, coordinates))
200
+ loss = (mse(predicted_energies, true_energies) / num_atoms.sqrt()).mean()
201
+
202
+ AdamW.zero_grad()
203
+ SGD.zero_grad()
204
+ loss.backward()
205
+ AdamW.step()
206
+ SGD.step()
207
+
208
+ tensorboard.add_scalar('batch_loss', loss, AdamW_scheduler.last_epoch * len(training) + i)
209
+
210
+ torch.save({
211
+ 'nn': nn.state_dict(),
212
+ 'AdamW': AdamW.state_dict(),
213
+ 'SGD': SGD.state_dict(),
214
+ 'AdamW_scheduler': AdamW_scheduler.state_dict(),
215
+ 'SGD_scheduler': SGD_scheduler.state_dict(),
216
+ }, latest_checkpoint)
217
+
File without changes