mlatom 2.0.0__py3-none-any.whl

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 (38) hide show
  1. MLatom/ML_NEA.py +2697 -0
  2. MLatom/MLatom.py +151 -0
  3. MLatom/MLatomF +0 -0
  4. MLatom/MLtasks.py +767 -0
  5. MLatom/__init__.py +0 -0
  6. MLatom/args_class.py +396 -0
  7. MLatom/cs.so +0 -0
  8. MLatom/doc.py +620 -0
  9. MLatom/header.py +64 -0
  10. MLatom/interface_MLatomF.py +87 -0
  11. MLatom/interfaces/DeePMDkit/DP_inference.py +20 -0
  12. MLatom/interfaces/DeePMDkit/__init__.py +0 -0
  13. MLatom/interfaces/DeePMDkit/interface_DeePMDkit.py +327 -0
  14. MLatom/interfaces/DeePMDkit/template.json +70 -0
  15. MLatom/interfaces/GAP/__init__.py +0 -0
  16. MLatom/interfaces/GAP/interface_GAP.py +415 -0
  17. MLatom/interfaces/PhysNet/PhysNet_predict.py +180 -0
  18. MLatom/interfaces/PhysNet/PhysNet_train.py +425 -0
  19. MLatom/interfaces/PhysNet/__init__.py +0 -0
  20. MLatom/interfaces/PhysNet/interface_PhysNet.py +270 -0
  21. MLatom/interfaces/TorchANI/TorchANI_predict.py +82 -0
  22. MLatom/interfaces/TorchANI/TorchANI_train.py +217 -0
  23. MLatom/interfaces/TorchANI/__init__.py +0 -0
  24. MLatom/interfaces/TorchANI/interface_TorchANI.py +323 -0
  25. MLatom/interfaces/__init__.py +0 -0
  26. MLatom/interfaces/sGDML/__init__.py +0 -0
  27. MLatom/interfaces/sGDML/interface_sGDML.py +276 -0
  28. MLatom/interfaces/sGDML/sgdml_dataset_from_extxyz.py +199 -0
  29. MLatom/ref.json +23 -0
  30. MLatom/sliceData.py +334 -0
  31. MLatom/stopper.py +17 -0
  32. MLatom-2.0.0.data/scripts/MLatomF +12 -0
  33. MLatom-2.0.0.data/scripts/mlatom +12 -0
  34. MLatom-2.0.0.dist-info/LICENSE.txt +251 -0
  35. MLatom-2.0.0.dist-info/METADATA +149 -0
  36. MLatom-2.0.0.dist-info/RECORD +38 -0
  37. MLatom-2.0.0.dist-info/WHEEL +5 -0
  38. MLatom-2.0.0.dist-info/top_level.txt +1 -0
MLatom/MLtasks.py ADDED
@@ -0,0 +1,767 @@
1
+ #!/usr/bin/env python3
2
+ '''
3
+ !---------------------------------------------------------------------------!
4
+ ! MLtasks: Machine learning tasks of MLatom !
5
+ ! Implementations by: Pavlo O. Dral and Fuchun Ge !
6
+ !---------------------------------------------------------------------------!
7
+ '''
8
+
9
+ from ML_NEA import CrossSection_calc
10
+ import os, sys, subprocess, time, shutil, re, copy, json
11
+ import numpy as np
12
+ import stopper
13
+ import interface_MLatomF
14
+ import ML_NEA
15
+ from io import StringIO
16
+ from contextlib import redirect_stdout
17
+ from math import inf, log
18
+ from interfaces.sGDML import interface_sGDML
19
+ from interfaces.PhysNet import interface_PhysNet
20
+ from interfaces.GAP import interface_GAP
21
+ from interfaces.DeePMDkit import interface_DeePMDkit
22
+ from interfaces.TorchANI import interface_TorchANI
23
+
24
+ from args_class import ArgsBase
25
+
26
+ class MLtasksCls(object):
27
+ dataSampled = False
28
+ dataSplited = False
29
+ subdatasets = []
30
+ default_MLprog={
31
+ 'kreg': 'mlatomf',
32
+ 'gap-soap': 'gap',
33
+ 'sgdml': 'sgdml',
34
+ 'gdml':'sgdml',
35
+ 'dpmd': 'deepmd-kit',
36
+ 'deeppot-se': 'deepmd-kit',
37
+ 'physnet': 'physnet',
38
+ 'ani': 'torchani',
39
+ 'ani-aev':'torchani'
40
+ }
41
+ mlatom_alias=['mlatomf','mlatom']
42
+ gap_alias=[ 'gap', 'gap_fit', 'gapfit']
43
+ sgdml_alias=['sgdml']
44
+ deepmd_alias=['dp','deepmd','deepmd-kit']
45
+ physnet_alias=['physnet']
46
+ ani_alias=['torchani','ani']
47
+ KMs = mlatom_alias+gap_alias+sgdml_alias
48
+ model_needs_subvalid = deepmd_alias+ani_alias+physnet_alias+sgdml_alias
49
+ index_prefix = ''
50
+ def __init__(self, argsMLtasks = sys.argv[1:]):
51
+ global args
52
+ args = Args()
53
+ args.parse(argsMLtasks)
54
+
55
+ if args.deltaLearn:
56
+ self.deltaLearn()
57
+ elif args.selfCorrect:
58
+ self.selfCorrect()
59
+ elif args.learningCurve:
60
+ self.learningCurve()
61
+ elif args.crossSection:
62
+ CrossSection_args=copy.deepcopy(args.args2pass)
63
+ deadlist=[]
64
+ for arg in CrossSection_args:
65
+ flagmatch = re.search('(^nthreads)|(^hyperopt)|(^setname=)|(^learningcurve$)|(^lcntrains)|(^lcnrepeats)|(^mlmodeltype)|(^mlprog)|(^deltalearn)|(^yb=)|(^yt=)|(^yestt=)|(^nlayers=)|(^selfcorrect)', arg.lower(), flags=re.UNICODE | re.MULTILINE | re.DOTALL | re.IGNORECASE)
66
+ if flagmatch:
67
+ deadlist.append(arg)
68
+ for i in deadlist: CrossSection_args.remove(i)
69
+ print(CrossSection_args)
70
+ ML_NEA.parse_api(CrossSection_args)
71
+ else:
72
+ self.chooseMLop(args.args2pass)
73
+
74
+ @classmethod
75
+ def deltaLearn(cls):
76
+ locargs = args.args2pass
77
+ yb = [float(line) for line in open(args.Yb, 'r')]
78
+ if args.createMLmodel or args.estAccMLmodel:
79
+ ydatname = '%s-%s.dat' % (fnamewoExt(args.Yt), fnamewoExt(args.Yb))
80
+ locargs = addReplaceArg('Yfile', 'Yfile=%s' % ydatname, locargs)
81
+ yt = [float(line) for line in open(args.Yt, 'r')]
82
+ with open(ydatname, 'w') as fcorr:
83
+ for ii in range(len(yb)):
84
+ fcorr.writelines('%25.13f\n' % (yt[ii] - yb[ii]))
85
+ cls.chooseMLop(locargs)
86
+ elif args.useMLmodel:
87
+ cls.chooseMLop(locargs)
88
+
89
+ if argexist('YestFile=', locargs):
90
+ corr = [float(line) for line in open(args.YestFile, 'r')]
91
+ with open(args.YestT, 'w') as fyestt:
92
+ for ii in range(len(yb)):
93
+ fyestt.writelines('%25.13f\n' % (yb[ii] + corr[ii]))
94
+
95
+ @classmethod
96
+ def selfCorrect(cls):
97
+ locargs = args.args2pass
98
+ yfilename = ''
99
+ if args.createMLmodel or args.estAccMLmodel:
100
+ if args.createMLmodel:
101
+ MLtaskPos = [arg.lower() for arg in locargs].index('createmlmodel')
102
+ else:
103
+ MLtaskPos = [arg.lower() for arg in locargs].index('estaccmlmodel')
104
+ locargslower = [arg.lower() for arg in locargs]
105
+ if ('sampling=structure-based' in locargslower or
106
+ 'sampling=farthest-point' in locargslower or
107
+ 'sampling=random' in locargslower):
108
+ print('\n Running sampling\n')
109
+ sys.stdout.flush()
110
+ interface_MLatomF.ifMLatomCls.run(['sample',
111
+ 'iTrainOut=itrain.dat',
112
+ 'iTestOut=itest.dat',
113
+ 'iSubtrainOut=isubtrain.dat',
114
+ 'iValidateOut=ivalidate.dat']
115
+ + locargs[:MLtaskPos] + locargs[MLtaskPos+1:])
116
+ for arg in locargs:
117
+ if 'yfile=' in arg.lower():
118
+ locargs.remove(arg)
119
+ yfilename = arg[len('yfile='):]
120
+ for nlayer in range(1,args.nlayers+1):
121
+ print('\n Starting calculations for layer %d\n' % nlayer)
122
+ sys.stdout.flush()
123
+ if args.createMLmodel or args.estAccMLmodel:
124
+ if nlayer == 1:
125
+ ydatname = yfilename
126
+ else:
127
+ ydatname = 'deltaRef-%s_layer%d.dat' % (fnamewoExt(yfilename), (nlayer - 1))
128
+ yrefs = [float(line) for line in open(yfilename, 'r')]
129
+ ylayerm1 = [float(line) for line in open('ylayer%d.dat' % (nlayer - 1), 'r')]
130
+ with open(ydatname, 'w') as fydat:
131
+ for ii in range(len(ylayerm1)):
132
+ fydat.writelines('%25.13f\n' % (yrefs[ii] - ylayerm1[ii]))
133
+ for arg in locargs:
134
+ if ('sampling=structure-based' == arg.lower() or
135
+ 'sampling=farthest-point' == arg.lower() or
136
+ 'sampling=random' == arg.lower()):
137
+ locargs.remove(arg)
138
+ locargs += ['sampling=user-defined',
139
+ 'iTrainIn=itrain.dat',
140
+ 'iTestIn=itest.dat',
141
+ 'iSubtrainIn=isubtrain.dat',
142
+ 'iValidateIn=ivalidate.dat']
143
+ if args.createMLmodel:
144
+ locargs += ['MLmodelOut=mlmodlayer%d.unf' % nlayer]
145
+ locargs = addReplaceArg('Yfile', 'Yfile=%s' % ydatname, locargs)
146
+ cls.chooseMLop(['YestFile=yest%d.dat' % nlayer] + locargs)
147
+ elif args.useMLmodel:
148
+ if nlayer > 1:
149
+ ylayerm1 = [float(line) for line in open('ylayer%d.dat' % (nlayer - 1), 'r')]
150
+ cls.chooseMLop(['MLmodelIn=mlmodlayer%d.unf' % nlayer, 'YestFile=yest%d.dat' % nlayer] + locargs)
151
+
152
+ if nlayer == 1:
153
+ shutil.move('yest1.dat', 'ylayer1.dat')
154
+ else:
155
+ yestlayer = [float(line) for line in open('yest%d.dat' % nlayer, 'r')]
156
+ with open('ylayer%d.dat' % nlayer, 'w') as fylayer:
157
+ for ii in range(len(yestlayer)):
158
+ fylayer.writelines('%25.13f\n' % (ylayerm1[ii] + yestlayer[ii]))
159
+
160
+ @classmethod
161
+ def learningCurve(cls):
162
+ locargs=args.args2pass
163
+ try:
164
+ args.lcNtrains = [int(i) for i in str(args.lcNtrains).split(',')]
165
+ except:
166
+ stopper.stopMLatom('Please provide lcNtrains')
167
+ if args.lcNrepeats:
168
+ if type(args.lcNrepeats) == str:
169
+ args.lcNrepeats = [int(i) for i in args.lcNrepeats.split(',')]
170
+ else:
171
+ args.lcNrepeats = [args.lcNrepeats]*len(args.lcNtrains)
172
+ else:
173
+ args.lcNrepeats = [3]*len(args.lcNtrains)
174
+
175
+ surfix = ''
176
+
177
+ dirname = 'learningCurve'
178
+ if os.path.isdir(dirname): pass
179
+ else: os.mkdir(dirname)
180
+ os.chdir(dirname)
181
+ print('\n entered %s\n' % dirname)
182
+ cls.index_prefix = '../'
183
+
184
+ if os.path.isdir(args.MLprog+surfix): pass
185
+ else: os.mkdir(args.MLprog+surfix)
186
+ if os.path.isfile(args.MLprog+surfix+'/results.json'):
187
+ with open(args.MLprog+surfix+'/results.json','r') as f:
188
+ results = json.load(f)
189
+ print(results,'\nprevious results ')
190
+ else: results = {}
191
+
192
+ for i, ntrain in enumerate(args.lcNtrains):
193
+ if not os.path.isdir('Ntrain_'+str(ntrain)): os.mkdir('Ntrain_'+str(ntrain))
194
+
195
+ # enter Ntrain dir
196
+ os.chdir('Ntrain_'+str(ntrain))
197
+ print('\n\n testing for Ntrain = %d\n ==============================================================================' % ntrain)
198
+ sys.stdout.flush()
199
+ for j in range(args.lcNrepeats[i]):
200
+ if not os.path.isdir(str(j)): os.mkdir(str(j))
201
+
202
+ # enter repeat dir
203
+ os.chdir(str(j))
204
+
205
+ cls.dataSampled = True
206
+ for i in ['Train','Subtrain','Validate','Test']:
207
+ if not os.path.isfile('i'+i.lower()+'.dat'):
208
+ cls.dataSampled = False
209
+
210
+ cls.dataSplited = True
211
+ for i in ['Train','Subtrain','Validate','Test']:
212
+ if not os.path.isfile('xyz.dat_'+i.lower()):##
213
+ cls.dataSplited = False
214
+
215
+ if os.path.isdir(args.MLprog+surfix): pass
216
+ else: os.mkdir(args.MLprog+surfix)
217
+ # enter model dir
218
+ os.chdir(args.MLprog+surfix)
219
+ print('\n\n repeat %d for Ntrain_%d\n ------------------------------------------------------------------------------' % (j,ntrain))
220
+
221
+ sys.stdout.flush()
222
+ if os.path.isfile('result.json'):
223
+ print('this repeat is already done')
224
+
225
+ else:
226
+ # set args for learning curve
227
+ lcargs = addReplaceArg('Ntrain','Ntrain='+str(ntrain),locargs)
228
+ lcargs = addReplaceArg('estAccMLmodel','estAccMLmodel',lcargs)
229
+ args.Ntrain = ntrain
230
+ if args.XfileIn:
231
+ lcargs = addReplaceArg('XfileIn','XfileIn='+os.path.relpath(args.absXfileIn),lcargs)
232
+ else:
233
+ lcargs = addReplaceArg('XYZfile','XYZfile='+os.path.relpath(args.absXYZfile),lcargs)
234
+ if args.Yfile: lcargs = addReplaceArg('Yfile','Yfile='+os.path.relpath(args.absYfile),lcargs)
235
+ if args.YgradXYZfile: lcargs = addReplaceArg('YgradXYZfile','YgradXYZfile='+os.path.relpath(args.absYgradXYZfile),lcargs)
236
+ if args.MLprog.lower() in cls.mlatom_alias:
237
+ os.system('cp ../../../../eq.xyz .> /dev/null 2>&1')
238
+ lcargs = addReplaceArg('itrainin','itrainin=../itrain.dat',lcargs)
239
+ lcargs = addReplaceArg('itestin','itestin=../itest.dat',lcargs)
240
+ lcargs = addReplaceArg('isubtrainin','isubtrainin=../isubtrain.dat',lcargs)
241
+ lcargs = addReplaceArg('ivalidatein','ivalidatein=../ivalidate.dat',lcargs)
242
+ lcargs = addReplaceArg('benchmark','benchmark',lcargs)
243
+
244
+ # estAccMLmodel
245
+ cls.prepareData(lcargs)
246
+ result = cls.estAccMLmodel(lcargs, shutup=True)
247
+ if os.path.isfile('../../../'+args.MLprog+surfix+'/results.json'):
248
+ with open('../../../'+args.MLprog+surfix+'/results.json','r') as f:
249
+ results = json.load(f)
250
+ if str(ntrain) not in results.keys(): results[str(ntrain)] = {}
251
+ if j == 0:
252
+ for k, v in result.items():
253
+ results[str(ntrain)][k] = [v]
254
+ else:
255
+ for k, v in result.items():
256
+ results[str(ntrain)][k].append(v)
257
+ with open('../../../'+args.MLprog+surfix+'/results.json','w') as f:
258
+ json.dump(results, f, sort_keys=False, indent=4)
259
+ with open('result.json','w') as f:
260
+ json.dump(result, f, sort_keys=False, indent=4)
261
+
262
+ meanResults = {i:{j: np.mean(results[i][j]) for j in results[i]} for i in results}
263
+ stdevs = {i:{j: np.std(results[i][j],ddof=1) for j in results[i]} for i in results}
264
+
265
+ if args.Yfile:
266
+ with open('../../../'+args.MLprog+surfix+'/lcy.csv', 'w') as f:
267
+ f.write('Ntrain, meanRMSE, SD, Nrepeats, RMSEs\n')
268
+ for nTrain in results.keys():
269
+ f.write('%s, %f, %f, %d, "%s"\n' % (nTrain,meanResults[nTrain]['eRMSE'],stdevs[nTrain]['eRMSE'],len(results[nTrain]['eRMSE']),','.join([str(i) for i in results[nTrain]['eRMSE']])))
270
+ if args.YgradXYZfile:
271
+ with open('../../../'+args.MLprog+surfix+'/lcygradxyz.csv', 'w') as f:
272
+ f.write('Ntrain, meanRMSE, SD, Nrepeats, RMSEs\n')
273
+ for nTrain in results.keys():
274
+ f.write('%s, %f, %f, %d, "%s"\n' % (nTrain,meanResults[nTrain]['fRMSE'],stdevs[nTrain]['fRMSE'],len(results[nTrain]['fRMSE']),','.join([str(i) for i in results[nTrain]['fRMSE']])))
275
+ with open('../../../'+args.MLprog+surfix+'/lctimetrain.csv','w') as ft, open ('../../../'+args.MLprog+surfix+'/lctimepredict.csv','w') as fp:
276
+ ft.write('Ntrain, meanTime, SD, Nrepeats, times\n')
277
+ fp.write('Ntrain, meanTime, SD, Nrepeats, times\n')
278
+ for nTrain in results.keys():
279
+ ft.write('%s, %f, %f, %d, "%s"\n' % (nTrain,meanResults[nTrain]['t_train'],stdevs[nTrain]['t_train'],len(results[nTrain]['t_train']),','.join(["%.2f"%i for i in results[nTrain]['t_train']])))
280
+ fp.write('%s, %f, %f, %d, "%s"\n' % (nTrain,meanResults[nTrain]['t_pred'],stdevs[nTrain]['t_pred'],len(results[nTrain]['t_pred']),','.join(["%.2f"%i for i in results[nTrain]['t_pred']])))
281
+
282
+ os.chdir('../..')
283
+ os.chdir('..')
284
+ os.chdir('..')
285
+
286
+
287
+ @classmethod
288
+ def chooseMLop(cls, locargs):
289
+ if args.useMLmodel:
290
+ MLtasksCls.useMLmodel(locargs)
291
+ elif args.createMLmodel:
292
+ MLtasksCls.createMLmodel(locargs)
293
+ elif args.estAccMLmodel:
294
+ MLtasksCls.estAccMLmodel(locargs)
295
+
296
+ @classmethod
297
+ def createMLmodel(cls, locargs, shutup=False):
298
+ if args.MLprog.lower() in cls.mlatom_alias and not args.optlines:
299
+ interface_MLatomF.ifMLatomCls.run(locargs)
300
+ else:
301
+ cls.prepareData(locargs)
302
+
303
+ # training
304
+ if args.optlines:
305
+ t_train, locargs = cls.optraining(locargs,shutup=shutup)
306
+
307
+ else:
308
+ t_train = cls.training(locargs)
309
+
310
+ cls.estimate(locargs, 'train', shutup=shutup)
311
+
312
+ return [t_train, locargs]
313
+
314
+ @classmethod
315
+ def estAccMLmodel(cls, locargs, shutup=False):
316
+ if args.MLprog.lower() in cls.mlatom_alias and not args.optlines:
317
+ t_train, t_pred, results = interface_MLatomF.ifMLatomCls.run(locargs)
318
+ else:
319
+ cls.prepareData(locargs)
320
+
321
+ if args.mlmodelin:
322
+ t_train = None
323
+ print('Use existing model: '+args.mlmodelin)
324
+ else:
325
+ t_train, locargs = cls.createMLmodel(locargs, shutup=shutup)
326
+
327
+ t_pred, results, _ = cls.estimate(locargs, 'test', shutup=shutup)
328
+
329
+ results['t_train'] = t_train
330
+ results['t_pred'] = t_pred
331
+ return results
332
+
333
+ @classmethod
334
+ def useMLmodel(cls, locargs, shutup=False):
335
+ starttime = time.time()
336
+ rmsedict = {}
337
+ if args.MLprog.lower() in cls.mlatom_alias:
338
+ _, wallclock, rmsedict = interface_MLatomF.ifMLatomCls.run(locargs,shutup=shutup)
339
+ else:
340
+ cls.prepareData(locargs)
341
+ if args.MLprog.lower() in cls.deepmd_alias:
342
+ wallclock = interface_DeePMDkit.DeePMDCls.useMLmodel(locargs, cls.subdatasets)
343
+ elif args.MLprog.lower() in cls.gap_alias:
344
+ wallclock = interface_GAP.GAPCls.useMLmodel(locargs, cls.subdatasets)
345
+ elif args.MLprog.lower() in cls.ani_alias:
346
+ wallclock = interface_TorchANI.ANICls.useMLmodel(locargs, cls.subdatasets)
347
+ elif args.MLprog.lower() in cls.physnet_alias:
348
+ wallclock = interface_PhysNet.PhysNetCls.useMLmodel(locargs, cls.subdatasets)
349
+ elif args.MLprog.lower() in cls.sgdml_alias:
350
+ wallclock = interface_sGDML.sGDMLCls.useMLmodel(locargs, cls.subdatasets)
351
+ endtime = time.time()
352
+ wallclock = endtime - starttime
353
+ print('\tPrediction time: \t\t\t%f s\n' % wallclock)
354
+ sys.stdout.flush()
355
+ return [wallclock, rmsedict, '']
356
+
357
+ @classmethod
358
+ def training(cls, locargs, setname=''):
359
+ if args.MLprog.lower() in cls.mlatom_alias:
360
+ mlatom_arg=addReplaceArg('estaccmlmodel','createmlmodel',locargs)
361
+
362
+ if args.XfileIn:
363
+ mlatom_arg=addReplaceArg('XfileIn','XfileIn=%s'% os.path.relpath(args.absXfileIn) ,mlatom_arg)
364
+ else:
365
+ mlatom_arg=addReplaceArg('xyzfile','xyzfile=%s'% os.path.relpath(args.absXYZfile) ,mlatom_arg)
366
+ if args.Yfile:
367
+ mlatom_arg=addReplaceArg('yfile','yfile=%s'% os.path.relpath(args.absYfile),mlatom_arg)
368
+ if args.YgradXYZfile:
369
+ mlatom_arg=addReplaceArg('ygradxyzfile','ygradxyzfile=%s'% os.path.relpath(args.absYgradXYZfile),mlatom_arg)
370
+
371
+ with open('%si%s.dat'%(cls.index_prefix, setname),'r')as f:
372
+ ntrain=0
373
+ for line in f:
374
+ ntrain+=1
375
+ mlatom_arg=addReplaceArg('Ntrain','Ntrain=%s'% ntrain,mlatom_arg)
376
+ mlatom_arg=addReplaceArg('Ntest','',mlatom_arg)
377
+ mlatom_arg=addReplaceArg('Nvalidate','',mlatom_arg)
378
+ mlatom_arg=addReplaceArg('Nsubtrain','',mlatom_arg)
379
+ mlatom_arg=addReplaceArg('sampling','sampling=user-defined',mlatom_arg)
380
+ mlatom_arg=addReplaceArg('itrainin','itrainin=%si%s.dat'%(cls.index_prefix, setname),mlatom_arg)
381
+ mlatom_arg=addReplaceArg('itestin','',mlatom_arg)
382
+ mlatom_arg=addReplaceArg('ivalidatein','',mlatom_arg)
383
+ mlatom_arg=addReplaceArg('isubtrainin','',mlatom_arg)
384
+ mlatom_arg=addReplaceArg('benchmark','benchmark',mlatom_arg)
385
+ os.system('rm '+ args.mlmodelout+' > /dev/null 2>&1 ')
386
+ print(' Training using MLatomF\n ............................................\n')
387
+ wallclock, _, _ = interface_MLatomF.ifMLatomCls.run(mlatom_arg,shutup=False)
388
+ print(' \n .............................................\n \n\n\tTraining Time: \t\t\t\t%f s\n' % wallclock)
389
+ else:
390
+ print(' Training started\n .............................................')
391
+ starttime = time.time()
392
+ if args.MLprog.lower() in cls.deepmd_alias:
393
+ wallclock = interface_DeePMDkit.DeePMDCls.createMLmodel(locargs, cls.subdatasets)
394
+ elif args.MLprog.lower() in cls.gap_alias:
395
+ wallclock = interface_GAP.GAPCls.createMLmodel(locargs, cls.subdatasets)
396
+ elif args.MLprog.lower() in cls.ani_alias:
397
+ wallclock = interface_TorchANI.ANICls.createMLmodel(locargs, cls.subdatasets)
398
+ elif args.MLprog.lower() in cls.physnet_alias:
399
+ wallclock = interface_PhysNet.PhysNetCls.createMLmodel(locargs, cls.subdatasets)
400
+ elif args.MLprog.lower() in cls.sgdml_alias:
401
+ wallclock = interface_sGDML.sGDMLCls.createMLmodel(locargs, cls.subdatasets)
402
+ endtime = time.time()
403
+ wallclock = endtime - starttime
404
+ print(' .............................................\n Training finished\n\n\tTraining Time: \t\t\t\t%f s\n' % wallclock)
405
+ sys.stdout.flush()
406
+ return wallclock
407
+
408
+
409
+
410
+ @classmethod
411
+ def optraining(cls, locargs, shutup=False):
412
+ #prepare args for optimization
413
+ optargs = addReplaceArg('setname', 'setname=subtrain', locargs)
414
+ optlines=args.optlines
415
+ optplaces = re.findall('hyperopt\..+?\(.+?\)',optlines) # find all places of hyperparas
416
+
417
+ # prepare spaces for each hyperparas
418
+ optspace = {}
419
+ for i, place in enumerate(optplaces):
420
+ optlines = optlines.replace(place, 'hypara'+str(i), 1) # mark position of hyperpara
421
+
422
+ spacetype = place.split('(')[0].split('.')[-1] # get type of space
423
+ lb = float(place.split('(')[1][:-1].split(',')[0]) # lower boundary
424
+ hb = float(place.split('(')[1][:-1].split(',')[1]) # higher boundary
425
+ # set space for each type
426
+ if spacetype == 'loguniform':
427
+ optspace['hypara'+str(i)] = hyperopt.hp.loguniform('hypara'+str(i), log(2)*lb, log(2)*hb)
428
+ elif spacetype == 'uniform':
429
+ optspace['hypara'+str(i)] = hyperopt.hp.uniform('hypara'+str(i), lb, hb)
430
+ elif spacetype == 'quniform':
431
+ q = int(place.split('(')[1][:-1].split(',')[1])
432
+ optspace['hypara'+str(i)] = hyperopt.hp.quniform('hypara'+str(i), int(lb), int(hb), q)
433
+ # see https://github.com/hyperopt/hyperopt/wiki/FMin#21-parameter-expressions
434
+
435
+ # replace hyperparas with marked position slots
436
+ for line in optlines.split():
437
+ optargs = addReplaceArg(line.split('=')[0], line, optargs)
438
+
439
+ bestsofar = inf # store best loss
440
+ bestreport = 'nothing happended yet' # store analyze report of best run so far
441
+
442
+ ##############################################################################################
443
+ def getloss(opt): # function that to plug in hyperopt.fmin later
444
+ nonlocal optargs, bestsofar, bestreport, optlines
445
+ optlines_tmp=copy.deepcopy(optlines)
446
+ # get values of hyperparas
447
+ for k, v in opt.items():
448
+ optlines_tmp = optlines_tmp.replace(k, str(v), 1)
449
+ # repalce slots with actual values
450
+ for line in optlines_tmp.split():
451
+ optargs = addReplaceArg(line.split('=')[0], line, optargs)
452
+
453
+ print(' ------------------------------------------------------------------------------\n with hyperparameter(s):\n\n%s\n' % optlines_tmp)
454
+ sys.stdout.flush()
455
+ # train with subtrain set, estimate & analyze with validate set
456
+
457
+ if args.MLprog.lower() == 'MLatomF'.lower():
458
+ optargs=addReplaceArg('yestfile','',optargs)
459
+ optargs=addReplaceArg('ygradXYZestfile','',optargs)
460
+ cls.training(optargs,'subtrain')
461
+ _, rmsedict, report = cls.estimate(optargs, 'validate', shutup=True)
462
+ rmses = list(rmsedict.values())
463
+ if len(rmses)>1:
464
+ if args.hyperopt.losstype.lower() == 'geomean': loss = np.sqrt(np.prod(rmses))
465
+ elif args.hyperopt.losstype.lower() == 'weighted': loss = rmses[0] + args.hyperopt.w_grad*rmses[1]
466
+ else:
467
+ print('invalid loss type, using geomean instead...')
468
+ loss = np.prod(rmses)
469
+ else: loss = rmses[0]
470
+
471
+ if args.MLprog.lower() == 'MLatomF'.lower():
472
+ optargs=addReplaceArg('yestfile','YestFile='+args.YestFile,optargs)
473
+ optargs=addReplaceArg('ygradXYZestfile','YgradXYZestFile='+args.YgradXYZestFile,optargs)
474
+ # check if this run performs best
475
+ if loss < bestsofar:
476
+ bestsofar = loss
477
+ bestreport = report
478
+ os.system('for file in `ls %s* `;do mv $file _optmp_${file}; done > /dev/null 2>&1' % args.mlmodelout)
479
+ os.system('for file in `ls *est.dat_validate`;do mv $file ${file}_optmp_; done > /dev/null 2>&1')# move mlmodel to tmp
480
+ print('\tLoss:\t\t\t\t\t%s\n\n' % loss)
481
+ return loss
482
+ ##############################################################################################
483
+ starttime = time.time()
484
+ print('\n optimizing hyperparameter(s)...\n')
485
+ # optimization process for different algorithm...
486
+ if args.hyperopt.algorithm.lower() == 'tpe':
487
+ bestpara=hyperopt.fmin(fn=getloss, space=optspace, algo=hyperopt.tpe.suggest, max_evals=args.hyperopt.max_evals)
488
+ # elif args.hyperopt.algorithm.lower() == 'random':
489
+ # bestpara=hyperopt.fmin(fn=getloss, space=optspace, algo=hyperopt.random.suggest, max_evals=args.hyperopt.max_evals)
490
+ else: print('under construction...')
491
+
492
+ endtime = time.time()
493
+ wallclock = endtime - starttime
494
+
495
+ # get and print optimized hyperparas
496
+ for k, v in bestpara.items():
497
+ optlines = optlines.replace(k, str(v), 1)
498
+ print('\n ==============================================================================\n optimizing finished\n\n Optimal hyperparameter(s):\n\n%s\n ==============================================================================\n' % optlines)
499
+ sys.stdout.flush()
500
+ # move best model back
501
+ os.system('for file in `ls *_optmp_*`; do mv $file `echo $file |sed "s/_optmp_//"`; done')
502
+
503
+ for line in optlines.split():
504
+ optargs = addReplaceArg(line.split('=')[0], line, optargs)
505
+ # if KM then train train set with optargs
506
+ if args.MLprog.lower() in cls.KMs:
507
+ print("Training whole training set with optimized hyperparameter(s)...")
508
+ optargs = addReplaceArg('setname', 'setname=train', optargs)
509
+ cls.training(optargs,'train')
510
+ # get optargs with optimized hyperparas
511
+ with open('hyperopt.inp','w') as f:
512
+ for i in optargs:
513
+ f.write(i+'\n')
514
+
515
+ return wallclock, optargs
516
+
517
+ @classmethod
518
+ def estimate(cls, locargs, setname, shutup=False):
519
+ if args.MLprog.lower() in cls.mlatom_alias and args.optlines:
520
+
521
+ setdict={
522
+ 'train':['train','train','train'],
523
+ 'subtrain':['subtrain','subtrain','subtrain'],
524
+ 'validate':['subtrain','validate','subtrain'],
525
+ 'test':['train','test','train']
526
+ }
527
+ with open('%si%s.dat'%(cls.index_prefix, setdict[setname][0]),'r')as f:
528
+ ntrain=0
529
+ for line in f:
530
+ ntrain+=1
531
+ if setname=='train': ntrain=0
532
+ with open('%si%s.dat'%(cls.index_prefix, setname),'r')as f:
533
+ ntest=0
534
+ for line in f:
535
+ ntest+=1
536
+
537
+ useargs=addReplaceArg('createmlmodel','estaccmlmodel',locargs)
538
+ useargs=addReplaceArg('Ntrain','Ntrain=%s'% ntrain ,useargs)
539
+ useargs=addReplaceArg('Ntest','Ntest=%s'%ntest,useargs)
540
+ useargs=addReplaceArg('sampling','sampling=user-defined',useargs)
541
+ useargs=addReplaceArg('itrainin','itrainin=%si%s.dat'%(cls.index_prefix, setdict[setname][2]),useargs)
542
+ useargs=addReplaceArg('itestin','itestin=%si%s.dat'%(cls.index_prefix, setname),useargs)
543
+ useargs=addReplaceArg('mlmodelin','mlmodelin=%s'%args.mlmodelout,useargs)
544
+ useargs=addReplaceArg('yestfile','',useargs)
545
+ useargs=addReplaceArg('ygradXYZestfile','',useargs)
546
+ else:
547
+ useargs = addReplaceArg('setname', 'setname='+setname, locargs)
548
+ useargs = addReplaceArg('XYZFile', 'XYZFile='+cls.index_prefix+'xyz.dat_'+setname, useargs)
549
+ if args.Yfile or True: useargs = addReplaceArg('YestFile', 'YestFile=yest.dat_'+setname, useargs)
550
+ if args.YgradXYZfile or True: useargs = addReplaceArg('YgradXYZestFile', 'YgradXYZestFile=gradest.dat_'+setname, useargs)
551
+
552
+ print(' For %sing set:\n\t' % setname.rstrip('e'))
553
+ t_pred, rmsedict, report= cls.useMLmodel(useargs, shutup=shutup)
554
+ if args.MLprog.lower() != 'MLatomF'.lower():
555
+ rmsedict, report = cls.analyze(setname, shutup=shutup)
556
+ if not shutup: print(report)
557
+ else: print('\t'+'\n\t'.join([k+':\t\t\t\t\t'+str(v) for k, v in rmsedict.items()])+'\n')
558
+ return [t_pred, rmsedict, report]
559
+
560
+ @classmethod
561
+ def analyze(cls, setname, shutup=False):
562
+ analyzeargs = ['analyze']
563
+ if args.Yfile:
564
+ analyzeargs = addReplaceArg('Yfile', 'Yfile='+cls.index_prefix+'y.dat_'+setname, analyzeargs)
565
+ analyzeargs = addReplaceArg('YestFile', 'YestFile=yest.dat_'+setname, analyzeargs)
566
+ if args.YgradXYZfile:
567
+ analyzeargs = addReplaceArg('YgradXYZfile', 'YgradXYZfile='+cls.index_prefix+'grad.dat_'+setname, analyzeargs)
568
+ analyzeargs = addReplaceArg('YgradXYZestFile', 'YgradXYZestFile=gradest.dat_'+setname, analyzeargs)
569
+
570
+ analout = StringIO() # variable with disgusting name
571
+ with redirect_stdout(analout):
572
+ interface_MLatomF.ifMLatomCls.run(analyzeargs)
573
+ analresults = analout.getvalue()
574
+ rmses=[float(x.split()[2]) for x in re.findall('RMSE =.+',analresults)]
575
+ rmsedict = {}
576
+ if args.Yfile:
577
+ rmsedict['eRMSE'] = rmses[0]
578
+ if args.YgradXYZfile:
579
+ rmsedict['fRMSE'] = rmses[-1]
580
+ return [rmsedict, analresults]
581
+
582
+ @classmethod
583
+ def prepareData(cls, locargs):
584
+ if args.MLprog.lower() in cls.mlatom_alias:
585
+ cls.dataSplited = True
586
+ # cls.dataConverted = True
587
+ # store subtest needed
588
+ cls.subdatasets = ['Train']
589
+ if args.estAccMLmodel or args.learningCurve: cls.subdatasets.append('Test')
590
+ if args.MLprog in cls.model_needs_subvalid or args.optlines:
591
+ cls.subdatasets.append('Subtrain')
592
+ cls.subdatasets.append('Validate')
593
+ if args.useMLmodel: cls.subdatasets = []
594
+ if args.learningCurve: cls.subdatasets = ['Train','Subtrain','Validate','Test']
595
+ # check if sampling is needed
596
+
597
+ ldic={
598
+ 'Train':os.path.isfile(args.iTrainIn),
599
+ 'Subtrain':os.path.isfile(args.iSubtrainIn),
600
+ 'Validate':os.path.isfile(args.iValidateIn),
601
+ 'Test':os.path.isfile(args.iTestIn),
602
+ 'nosample': False
603
+ }
604
+ if cls.subdatasets: exec('nosample='+' and '.join([i for i in cls.subdatasets]),globals(),ldic)
605
+ nosample = ldic['nosample']
606
+ if not nosample and cls.subdatasets and not cls.dataSampled :
607
+ cls.sample(cls.subdatasets)
608
+ # modify args.iXxxIn
609
+ for i in cls.subdatasets:
610
+ exec('args.i'+i+'In="i'+i.lower()+'.dat"')
611
+ cls.dataSampled = True
612
+ # split datasets
613
+ if not cls.dataSplited:
614
+ if args.learningCurve:
615
+ for i in cls.subdatasets:
616
+ exec('args.i'+i+'In="i'+i.lower()+'.dat"')
617
+
618
+ if cls.subdatasets: print('\n Spliting data...\n')
619
+ sys.stdout.flush()
620
+ for i in cls.subdatasets:
621
+ exec("cls.splitDataset(0, cls.index_prefix+args.i"+i+"In, args.absXYZfile, cls.index_prefix+'xyz.dat_'+i.lower())")
622
+ if args.Yfile:
623
+ exec("cls.splitDataset(1, cls.index_prefix+args.i"+i+"In, args.absYfile, cls.index_prefix+'y.dat_'+i.lower())")
624
+ if args.YgradXYZfile:
625
+ exec("cls.splitDataset(0, cls.index_prefix+args.i"+i+"In, args.absYgradXYZfile, cls.index_prefix+'grad.dat_'+i.lower())")
626
+ cls.dataSplited = True
627
+
628
+ @classmethod
629
+ def splitDataset(cls, issizeone, indices, filein, fileout):
630
+ with open(indices,'r') as f:
631
+ idx = [int(line) for line in f]
632
+ with open(filein,'r') as fi, open(fileout,'w') as fo:
633
+ if issizeone:
634
+ for i, line in enumerate(fi):
635
+ if i+1 in idx:
636
+ fo.writelines(line)
637
+ else:
638
+ i = 0
639
+ for line in fi:
640
+ i = i+1
641
+ limit=int(line)
642
+ fi.readline()
643
+ if i in idx: fo.write(line+'\n')
644
+ for j in range(limit):
645
+ if i in idx: fo.write(fi.readline())
646
+ else: fi.readline()
647
+
648
+ @classmethod
649
+ def sample(cls, subdatasets):
650
+ print('\n Running sampling...\n')
651
+ sys.stdout.flush()
652
+ smplargs = ['sample']
653
+ smplargs = addReplaceArg('molDescriptor','molDescriptor=CM',smplargs)
654
+ pwd=os.getcwd()
655
+ if args.XfileIn:
656
+ smplargs = addReplaceArg('XfileIn', 'XfileIn=%s' % os.path.relpath(args.absXfileIn), smplargs)
657
+ else:
658
+ smplargs = addReplaceArg('XYZfile', 'XYZfile=%s' % os.path.relpath(args.absXYZfile), smplargs)
659
+ if args.sampling: smplargs = addReplaceArg('sampling', 'sampling=%s' % args.sampling, smplargs)
660
+ ldic={'smplargs':smplargs}
661
+ for i in subdatasets:
662
+ exec('if args.N'+i.lower()+': smplargs=addReplaceArg("N'+i.lower()+'","N'+i.lower()+'=%s" % args.N'+i.lower()+', smplargs)',globals(),ldic)
663
+ exec('smplargs = addReplaceArg("i'+i.lower()+'Out","i'+i.lower()+'Out='+cls.index_prefix+'i'+i.lower()+'.dat",smplargs)',globals(),ldic)
664
+ smplargs=ldic['smplargs']
665
+ interface_MLatomF.ifMLatomCls.run(smplargs, shutup=True)
666
+
667
+ def fnamewoExt(fullfname):
668
+ fname = os.path.basename(fullfname)
669
+ fname = os.path.splitext(fname)[0]
670
+ return fname
671
+
672
+ def argexist(argname, largs):
673
+ for iarg in range(len(largs)):
674
+ arg = largs[iarg]
675
+ if argname.lower() in arg.lower():
676
+ return True
677
+ else:
678
+ return False
679
+
680
+ def addReplaceArg(argname, newarg, originalargs):
681
+ finalargs = copy.deepcopy(originalargs)
682
+ for iarg in range(len(finalargs)):
683
+ arg = finalargs[iarg]
684
+ if argname.lower() == arg.split('=')[0].lower():
685
+ if newarg:
686
+ finalargs[iarg] = newarg
687
+ else:
688
+ del finalargs[iarg]
689
+ break
690
+ else:
691
+ finalargs.append(newarg)
692
+ return finalargs
693
+
694
+ class Args(ArgsBase):
695
+ def __init__(self):
696
+ super().__init__()
697
+ self.task_list = [
698
+ 'XYZ2X', 'analyze', 'sample', 'slicedata', 'sampleFromSlices', 'mergeSlices',
699
+ 'useMLmodel', 'createMLmodel', 'estAccMLmodel', 'learningCurve',
700
+ 'crossSection'
701
+ ]
702
+ self.add_default_dict_args(self.task_list, bool)
703
+ self.add_default_dict_args([
704
+ 'useMLmodel', 'createMLmodel', 'estAccMLmodel', 'learningCurve','deltaLearn','selfCorrect','MLmodelType'
705
+ ],
706
+ bool
707
+ )
708
+ self.add_default_dict_args([
709
+ 'MLprog'
710
+ ],
711
+ 'MLatomF'
712
+ )
713
+ self.add_default_dict_args([
714
+ 'Yb', 'Yt', 'YestT', 'YestFile','XYZfile', 'XfileIn', 'Yfile', 'YgradXYZfile', 'absXfileIn', 'absXYZfile', 'absYfile', 'absYgradXYZfile', 'YgradXYZestFile', 'Ntrain', 'Nsubtrain', 'Nvalidate', 'Ntest', 'iTrainIn', 'iTestIn', 'iSubtrainIn', 'iValidateIn', 'sampling', 'MLmodelIn', 'MLmodelOut',
715
+ 'molDescriptor', 'kernel'
716
+ ],
717
+ ""
718
+ )
719
+ self.add_dict_args({'MLmodelType': None, 'nthreads': None})
720
+ self.set_keyword_alias('crossSection', ['ML-NEA', 'ML_NEA', 'crossSection', 'cross-section', 'cross_section','MLNEA'])
721
+ self.args2pass = []
722
+ self.parse_input_content([
723
+ 'hyperopt.max_evals=8',
724
+ 'hyperopt.algorithm=tpe',
725
+ 'hyperopt.losstype=geomean',
726
+ 'hyperopt.w_grad=0.1'
727
+ ])
728
+ self.optlines=''
729
+
730
+ def parse(self, argsraw):
731
+ if len(argsraw) == 0:
732
+ Doc.printDoc({})
733
+ stopper.stopMLatom('At least one option should be provided')
734
+ elif len(argsraw) == 1:
735
+ if os.path.exists(argsraw[0]):
736
+ self.parse_input_file(argsraw[0])
737
+ else:
738
+ self.parse_input_content(argsraw[0])
739
+ self.args2pass = self.args_string_list(['', None])
740
+ elif len(argsraw) >= 2:
741
+ self.parse_input_content(argsraw)
742
+ self.args2pass = self.args_string_list(['', None])
743
+ self.argProcess()
744
+
745
+ def argProcess(self):
746
+ self.add_keyword_value_args(
747
+ ['absXfileIn','absXYZfile','absYfile','absYgradXYZfile'],
748
+ [os.path.abspath(self.XfileIn),os.path.abspath(self.XYZfile),os.path.abspath(self.Yfile),os.path.abspath(self.YgradXYZfile)]
749
+ )
750
+ for arg in self.args2pass:
751
+ if bool(re.search('hyperopt\..+?\(.+?\)',arg)):
752
+ import hyperopt
753
+ globals()['hyperopt']=hyperopt
754
+ self.optlines = self.optlines+arg+'\n'
755
+
756
+ if self.MLmodelType:
757
+ try: self.MLprog=MLtasksCls.default_MLprog[self.MLmodelType.lower()]
758
+ except: stopper.stopMLatom('Unkown MLmodelType')
759
+ if self.selfCorrect:
760
+ self.parse_input_content([
761
+ 'nlayers=4'])
762
+ if self.selfCorrect and (argexist('iTrainOut=', self.args2pass) or argexist('iTestOut=', self.args2pass) or argexist('iSubtrainOut=', self.args2pass) or argexist('iValidateOut=', self.args2pass)):
763
+ stopper.stopMLatom('Indices of subsets cannot be saved for self-correction')
764
+
765
+ if __name__ == '__main__':
766
+ print(__doc__)
767
+ MLtasks()