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
MLatom/MLtasks.py ADDED
@@ -0,0 +1,784 @@
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
+ mlatom_arg=addReplaceArg('MLmodelOut','MLmodelOut=%s'%args.MLmodelOut, mlatom_arg)
362
+
363
+ if args.XfileIn:
364
+ mlatom_arg=addReplaceArg('XfileIn','XfileIn=%s'% os.path.relpath(args.absXfileIn) ,mlatom_arg)
365
+ else:
366
+ mlatom_arg=addReplaceArg('xyzfile','xyzfile=%s'% os.path.relpath(args.absXYZfile) ,mlatom_arg)
367
+ if args.Yfile:
368
+ mlatom_arg=addReplaceArg('yfile','yfile=%s'% os.path.relpath(args.absYfile),mlatom_arg)
369
+ if args.YgradXYZfile:
370
+ mlatom_arg=addReplaceArg('ygradxyzfile','ygradxyzfile=%s'% os.path.relpath(args.absYgradXYZfile),mlatom_arg)
371
+
372
+ idx_dict={
373
+ 'train': args.itrainin,
374
+ 'subtrain': args.isubtrainin,
375
+ 'validate': args.ivalidatein,
376
+ 'test': args.itestin
377
+ }
378
+
379
+ with open(cls.index_prefix+idx_dict[setname],'r')as f:
380
+ ntrain=0
381
+ for line in f:
382
+ ntrain+=1
383
+ mlatom_arg=addReplaceArg('Ntrain','Ntrain=%s'% ntrain,mlatom_arg)
384
+ mlatom_arg=addReplaceArg('Ntest','',mlatom_arg)
385
+ mlatom_arg=addReplaceArg('Nvalidate','',mlatom_arg)
386
+ mlatom_arg=addReplaceArg('Nsubtrain','',mlatom_arg)
387
+ mlatom_arg=addReplaceArg('sampling','sampling=user-defined',mlatom_arg)
388
+ mlatom_arg=addReplaceArg('itrainin','itrainin='+cls.index_prefix+idx_dict[setname],mlatom_arg)
389
+ mlatom_arg=addReplaceArg('itestin','',mlatom_arg)
390
+ mlatom_arg=addReplaceArg('ivalidatein','',mlatom_arg)
391
+ mlatom_arg=addReplaceArg('isubtrainin','',mlatom_arg)
392
+ mlatom_arg=addReplaceArg('benchmark','benchmark',mlatom_arg)
393
+ os.system('rm '+ args.mlmodelout+' > /dev/null 2>&1 ')
394
+ print(' Training using MLatomF\n ............................................\n')
395
+ wallclock, _, _ = interface_MLatomF.ifMLatomCls.run(mlatom_arg,shutup=False)
396
+ print(' \n .............................................\n \n\n\tTraining Time: \t\t\t\t%f s\n' % wallclock)
397
+ else:
398
+ print(' Training started\n .............................................')
399
+ starttime = time.time()
400
+ if args.MLprog.lower() in cls.deepmd_alias:
401
+ wallclock = interface_DeePMDkit.DeePMDCls.createMLmodel(locargs, cls.subdatasets)
402
+ elif args.MLprog.lower() in cls.gap_alias:
403
+ wallclock = interface_GAP.GAPCls.createMLmodel(locargs, cls.subdatasets)
404
+ elif args.MLprog.lower() in cls.ani_alias:
405
+ wallclock = interface_TorchANI.ANICls.createMLmodel(locargs, cls.subdatasets)
406
+ elif args.MLprog.lower() in cls.physnet_alias:
407
+ wallclock = interface_PhysNet.PhysNetCls.createMLmodel(locargs, cls.subdatasets)
408
+ elif args.MLprog.lower() in cls.sgdml_alias:
409
+ wallclock = interface_sGDML.sGDMLCls.createMLmodel(locargs, cls.subdatasets)
410
+ endtime = time.time()
411
+ wallclock = endtime - starttime
412
+ print(' .............................................\n Training finished\n\n\tTraining Time: \t\t\t\t%f s\n' % wallclock)
413
+ sys.stdout.flush()
414
+ return wallclock
415
+
416
+
417
+
418
+ @classmethod
419
+ def optraining(cls, locargs, shutup=False):
420
+ #prepare args for optimization
421
+ optargs = addReplaceArg('setname', 'setname=subtrain', locargs)
422
+ optlines=args.optlines
423
+ optplaces = re.findall('hyperopt\..+?\(.+?\)',optlines) # find all places of hyperparas
424
+
425
+ # prepare spaces for each hyperparas
426
+ optspace = {}
427
+ for i, place in enumerate(optplaces):
428
+ optlines = optlines.replace(place, 'hypara'+str(i), 1) # mark position of hyperpara
429
+
430
+ spacetype = place.split('(')[0].split('.')[-1] # get type of space
431
+ lb = float(place.split('(')[1][:-1].split(',')[0]) # lower boundary
432
+ hb = float(place.split('(')[1][:-1].split(',')[1]) # higher boundary
433
+ # set space for each type
434
+ if spacetype == 'loguniform':
435
+ optspace['hypara'+str(i)] = hyperopt.hp.loguniform('hypara'+str(i), log(2)*lb, log(2)*hb)
436
+ elif spacetype == 'uniform':
437
+ optspace['hypara'+str(i)] = hyperopt.hp.uniform('hypara'+str(i), lb, hb)
438
+ elif spacetype == 'quniform':
439
+ q = int(place.split('(')[1][:-1].split(',')[1])
440
+ optspace['hypara'+str(i)] = hyperopt.hp.quniform('hypara'+str(i), int(lb), int(hb), q)
441
+ # see https://github.com/hyperopt/hyperopt/wiki/FMin#21-parameter-expressions
442
+
443
+ # replace hyperparas with marked position slots
444
+ for line in optlines.split():
445
+ optargs = addReplaceArg(line.split('=')[0], line, optargs)
446
+
447
+ bestsofar = inf # store best loss
448
+ bestreport = 'nothing happended yet' # store analyze report of best run so far
449
+
450
+ ##############################################################################################
451
+ def getloss(opt): # function that to plug in hyperopt.fmin later
452
+ nonlocal optargs, bestsofar, bestreport, optlines
453
+ optlines_tmp=copy.deepcopy(optlines)
454
+ # get values of hyperparas
455
+ for k, v in opt.items():
456
+ optlines_tmp = optlines_tmp.replace(k, str(v), 1)
457
+ # repalce slots with actual values
458
+ for line in optlines_tmp.split():
459
+ optargs = addReplaceArg(line.split('=')[0], line, optargs)
460
+
461
+ print(' ------------------------------------------------------------------------------\n with hyperparameter(s):\n\n%s\n' % optlines_tmp)
462
+ sys.stdout.flush()
463
+ # train with subtrain set, estimate & analyze with validate set
464
+
465
+ if args.MLprog.lower() == 'MLatomF'.lower():
466
+ optargs=addReplaceArg('yestfile','',optargs)
467
+ optargs=addReplaceArg('ygradXYZestfile','',optargs)
468
+ cls.training(optargs,'subtrain')
469
+ _, rmsedict, report = cls.estimate(optargs, 'validate', shutup=True)
470
+ rmses = list(rmsedict.values())
471
+ if len(rmses)>1:
472
+ if args.hyperopt.losstype.lower() == 'geomean': loss = np.sqrt(np.prod(rmses))
473
+ elif args.hyperopt.losstype.lower() == 'weighted': loss = rmses[0] + args.hyperopt.w_grad*rmses[1]
474
+ else:
475
+ print('invalid loss type, using geomean instead...')
476
+ loss = np.prod(rmses)
477
+ else: loss = rmses[0]
478
+
479
+ if args.MLprog.lower() == 'MLatomF'.lower():
480
+ optargs=addReplaceArg('yestfile','YestFile='+args.YestFile,optargs)
481
+ optargs=addReplaceArg('ygradXYZestfile','YgradXYZestFile='+args.YgradXYZestFile,optargs)
482
+ # check if this run performs best
483
+ if loss < bestsofar:
484
+ bestsofar = loss
485
+ bestreport = report
486
+ os.system('for file in `ls %s* `;do mv $file _optmp_${file}; done > /dev/null 2>&1' % args.mlmodelout)
487
+ os.system('for file in `ls *est.dat_validate`;do mv $file ${file}_optmp_; done > /dev/null 2>&1')# move mlmodel to tmp
488
+ print('\tLoss:\t\t\t\t\t%s\n\n' % loss)
489
+ return loss
490
+ ##############################################################################################
491
+ starttime = time.time()
492
+ print('\n optimizing hyperparameter(s)...\n')
493
+ # optimization process for different algorithm...
494
+ if args.hyperopt.algorithm.lower() == 'tpe':
495
+ bestpara=hyperopt.fmin(fn=getloss, space=optspace, algo=hyperopt.tpe.suggest, max_evals=args.hyperopt.max_evals)
496
+ # elif args.hyperopt.algorithm.lower() == 'random':
497
+ # bestpara=hyperopt.fmin(fn=getloss, space=optspace, algo=hyperopt.random.suggest, max_evals=args.hyperopt.max_evals)
498
+ else: print('under construction...')
499
+
500
+ endtime = time.time()
501
+ wallclock = endtime - starttime
502
+
503
+ # get and print optimized hyperparas
504
+ for k, v in bestpara.items():
505
+ optlines = optlines.replace(k, str(v), 1)
506
+ print('\n ==============================================================================\n optimizing finished\n\n Optimal hyperparameter(s):\n\n%s\n ==============================================================================\n' % optlines)
507
+ sys.stdout.flush()
508
+ # move best model back
509
+ os.system('for file in `ls *_optmp_*`; do mv $file `echo $file |sed "s/_optmp_//"`; done')
510
+
511
+ for line in optlines.split():
512
+ optargs = addReplaceArg(line.split('=')[0], line, optargs)
513
+ # if KM then train train set with optargs
514
+ if args.MLprog.lower() in cls.KMs:
515
+ print("Training whole training set with optimized hyperparameter(s)...")
516
+ optargs = addReplaceArg('setname', 'setname=train', optargs)
517
+ cls.training(optargs,'train')
518
+ # get optargs with optimized hyperparas
519
+ with open('hyperopt.inp','w') as f:
520
+ for i in optargs:
521
+ f.write(i+'\n')
522
+
523
+ return wallclock, optargs
524
+
525
+ @classmethod
526
+ def estimate(cls, locargs, setname, shutup=False):
527
+ if args.MLprog.lower() in cls.mlatom_alias and args.optlines:
528
+
529
+ setdict={
530
+ 'train':['train','train','train'],
531
+ 'subtrain':['subtrain','subtrain','subtrain'],
532
+ 'validate':['subtrain','validate','subtrain'],
533
+ 'test':['train','test','train']
534
+ }
535
+
536
+ idx_dict={
537
+ 'train': args.itrainin,
538
+ 'subtrain': args.isubtrainin,
539
+ 'validate': args.ivalidatein,
540
+ 'test': args.itestin
541
+ }
542
+
543
+ with open(cls.index_prefix+idx_dict[setdict[setname][0]],'r')as f:
544
+ ntrain=0
545
+ for line in f:
546
+ ntrain+=1
547
+ if setname=='train': ntrain=0
548
+ # MLatomF still check this number...
549
+ with open(cls.index_prefix+idx_dict[setname],'r')as f:
550
+ ntest=0
551
+ for line in f:
552
+ ntest+=1
553
+
554
+ useargs=addReplaceArg('createmlmodel','estaccmlmodel',locargs)
555
+ useargs=addReplaceArg('Ntrain','Ntrain=%s'% ntrain ,useargs)
556
+ useargs=addReplaceArg('Ntest','Ntest=%s'%ntest,useargs)
557
+ useargs=addReplaceArg('sampling','sampling=user-defined',useargs)
558
+ useargs=addReplaceArg('itrainin','itrainin='+cls.index_prefix+idx_dict[setdict[setname][2]],useargs)
559
+ useargs=addReplaceArg('itestin','itestin='+cls.index_prefix+idx_dict[setname],useargs)
560
+ useargs=addReplaceArg('mlmodelin','mlmodelin=%s'%args.mlmodelout,useargs)
561
+ useargs=addReplaceArg('yestfile','',useargs)
562
+ useargs=addReplaceArg('ygradXYZestfile','',useargs)
563
+ else:
564
+ useargs = addReplaceArg('setname', 'setname='+setname, locargs)
565
+ useargs = addReplaceArg('XYZFile', 'XYZFile='+cls.index_prefix+'xyz.dat_'+setname, useargs)
566
+ if args.Yfile or True: useargs = addReplaceArg('YestFile', 'YestFile=yest.dat_'+setname, useargs)
567
+ if args.YgradXYZfile or True: useargs = addReplaceArg('YgradXYZestFile', 'YgradXYZestFile=gradest.dat_'+setname, useargs)
568
+
569
+ print(' For %sing set:\n\t' % setname.rstrip('e'))
570
+ t_pred, rmsedict, report= cls.useMLmodel(useargs, shutup=shutup)
571
+ if args.MLprog.lower() != 'MLatomF'.lower():
572
+ rmsedict, report = cls.analyze(setname, shutup=shutup)
573
+ if not shutup: print(report)
574
+ else: print('\t'+'\n\t'.join([k+':\t\t\t\t\t'+str(v) for k, v in rmsedict.items()])+'\n')
575
+ return [t_pred, rmsedict, report]
576
+
577
+ @classmethod
578
+ def analyze(cls, setname, shutup=False):
579
+ analyzeargs = ['analyze']
580
+ if args.Yfile:
581
+ analyzeargs = addReplaceArg('Yfile', 'Yfile='+cls.index_prefix+'y.dat_'+setname, analyzeargs)
582
+ analyzeargs = addReplaceArg('YestFile', 'YestFile=yest.dat_'+setname, analyzeargs)
583
+ if args.YgradXYZfile:
584
+ analyzeargs = addReplaceArg('YgradXYZfile', 'YgradXYZfile='+cls.index_prefix+'grad.dat_'+setname, analyzeargs)
585
+ analyzeargs = addReplaceArg('YgradXYZestFile', 'YgradXYZestFile=gradest.dat_'+setname, analyzeargs)
586
+
587
+ analout = StringIO() # variable with disgusting name
588
+ with redirect_stdout(analout):
589
+ interface_MLatomF.ifMLatomCls.run(analyzeargs)
590
+ analresults = analout.getvalue()
591
+ rmses=[float(x.split()[2]) for x in re.findall('RMSE =.+',analresults)]
592
+ rmsedict = {}
593
+ if args.Yfile:
594
+ rmsedict['eRMSE'] = rmses[0]
595
+ if args.YgradXYZfile:
596
+ rmsedict['fRMSE'] = rmses[-1]
597
+ return [rmsedict, analresults]
598
+
599
+ @classmethod
600
+ def prepareData(cls, locargs):
601
+ if args.MLprog.lower() in cls.mlatom_alias:
602
+ cls.dataSplited = True
603
+ # cls.dataConverted = True
604
+ # store subtest needed
605
+ cls.subdatasets = ['Train']
606
+ if args.estAccMLmodel or args.learningCurve: cls.subdatasets.append('Test')
607
+ if args.MLprog in cls.model_needs_subvalid or args.optlines:
608
+ cls.subdatasets.append('Subtrain')
609
+ cls.subdatasets.append('Validate')
610
+ if args.useMLmodel: cls.subdatasets = []
611
+ if args.learningCurve: cls.subdatasets = ['Train','Subtrain','Validate','Test']
612
+ # check if sampling is needed
613
+
614
+ ldic={
615
+ 'Train':os.path.isfile(args.iTrainIn),
616
+ 'Subtrain':os.path.isfile(args.iSubtrainIn),
617
+ 'Validate':os.path.isfile(args.iValidateIn),
618
+ 'Test':os.path.isfile(args.iTestIn),
619
+ 'nosample': False
620
+ }
621
+ if cls.subdatasets: exec('nosample='+' and '.join([i for i in cls.subdatasets]),globals(),ldic)
622
+ nosample = ldic['nosample']
623
+ if not nosample and cls.subdatasets and not cls.dataSampled :
624
+ cls.sample(cls.subdatasets)
625
+ # modify args.iXxxIn
626
+ for i in cls.subdatasets:
627
+ exec('args.i'+i+'In="i'+i.lower()+'.dat"')
628
+ cls.dataSampled = True
629
+ # split datasets
630
+ if not cls.dataSplited:
631
+ if args.learningCurve:
632
+ for i in cls.subdatasets:
633
+ exec('args.i'+i+'In="i'+i.lower()+'.dat"')
634
+
635
+ if cls.subdatasets: print('\n Spliting data...\n')
636
+ sys.stdout.flush()
637
+ for i in cls.subdatasets:
638
+ exec("cls.splitDataset(0, cls.index_prefix+args.i"+i+"In, args.absXYZfile, cls.index_prefix+'xyz.dat_'+i.lower())")
639
+ if args.Yfile:
640
+ exec("cls.splitDataset(1, cls.index_prefix+args.i"+i+"In, args.absYfile, cls.index_prefix+'y.dat_'+i.lower())")
641
+ if args.YgradXYZfile:
642
+ exec("cls.splitDataset(0, cls.index_prefix+args.i"+i+"In, args.absYgradXYZfile, cls.index_prefix+'grad.dat_'+i.lower())")
643
+ cls.dataSplited = True
644
+
645
+ @classmethod
646
+ def splitDataset(cls, issizeone, indices, filein, fileout):
647
+ with open(indices,'r') as f:
648
+ idx = [int(line) for line in f]
649
+ with open(filein,'r') as fi, open(fileout,'w') as fo:
650
+ if issizeone:
651
+ for i, line in enumerate(fi):
652
+ if i+1 in idx:
653
+ fo.writelines(line)
654
+ else:
655
+ i = 0
656
+ for line in fi:
657
+ i = i+1
658
+ limit=int(line)
659
+ fi.readline()
660
+ if i in idx: fo.write(line+'\n')
661
+ for j in range(limit):
662
+ if i in idx: fo.write(fi.readline())
663
+ else: fi.readline()
664
+
665
+ @classmethod
666
+ def sample(cls, subdatasets):
667
+ print('\n Running sampling...\n')
668
+ sys.stdout.flush()
669
+ smplargs = ['sample']
670
+ smplargs = addReplaceArg('molDescriptor','molDescriptor=CM',smplargs)
671
+ pwd=os.getcwd()
672
+ if args.XfileIn:
673
+ smplargs = addReplaceArg('XfileIn', 'XfileIn=%s' % os.path.relpath(args.absXfileIn), smplargs)
674
+ else:
675
+ smplargs = addReplaceArg('XYZfile', 'XYZfile=%s' % os.path.relpath(args.absXYZfile), smplargs)
676
+ if args.sampling: smplargs = addReplaceArg('sampling', 'sampling=%s' % args.sampling, smplargs)
677
+ ldic={'smplargs':smplargs}
678
+ for i in subdatasets:
679
+ exec('if args.N'+i.lower()+': smplargs=addReplaceArg("N'+i.lower()+'","N'+i.lower()+'=%s" % args.N'+i.lower()+', smplargs)',globals(),ldic)
680
+ exec('smplargs = addReplaceArg("i'+i.lower()+'Out","i'+i.lower()+'Out='+cls.index_prefix+'i'+i.lower()+'.dat",smplargs)',globals(),ldic)
681
+ smplargs=ldic['smplargs']
682
+ interface_MLatomF.ifMLatomCls.run(smplargs, shutup=True)
683
+
684
+ def fnamewoExt(fullfname):
685
+ fname = os.path.basename(fullfname)
686
+ fname = os.path.splitext(fname)[0]
687
+ return fname
688
+
689
+ def argexist(argname, largs):
690
+ for iarg in range(len(largs)):
691
+ arg = largs[iarg]
692
+ if argname.lower() in arg.lower():
693
+ return True
694
+ else:
695
+ return False
696
+
697
+ def addReplaceArg(argname, newarg, originalargs):
698
+ finalargs = copy.deepcopy(originalargs)
699
+ for iarg in range(len(finalargs)):
700
+ arg = finalargs[iarg]
701
+ if argname.lower() == arg.split('=')[0].lower():
702
+ if newarg:
703
+ finalargs[iarg] = newarg
704
+ else:
705
+ del finalargs[iarg]
706
+ break
707
+ else:
708
+ finalargs.append(newarg)
709
+ return finalargs
710
+
711
+ class Args(ArgsBase):
712
+ def __init__(self):
713
+ super().__init__()
714
+ self.task_list = [
715
+ 'XYZ2X', 'analyze', 'sample', 'slicedata', 'sampleFromSlices', 'mergeSlices',
716
+ 'useMLmodel', 'createMLmodel', 'estAccMLmodel', 'learningCurve',
717
+ 'crossSection'
718
+ ]
719
+ self.add_default_dict_args(self.task_list, bool)
720
+ self.add_default_dict_args([
721
+ 'useMLmodel', 'createMLmodel', 'estAccMLmodel', 'learningCurve','deltaLearn','selfCorrect','MLmodelType'
722
+ ],
723
+ bool
724
+ )
725
+ self.add_default_dict_args([
726
+ 'MLprog'
727
+ ],
728
+ 'MLatomF'
729
+ )
730
+ self.add_default_dict_args([
731
+ 'Yb', 'Yt', 'YestT', 'YestFile','XYZfile', 'XfileIn', 'Yfile', 'YgradXYZfile', 'absXfileIn', 'absXYZfile', 'absYfile', 'absYgradXYZfile', 'YgradXYZestFile', 'Ntrain', 'Nsubtrain', 'Nvalidate', 'Ntest', 'iTrainIn', 'iTestIn', 'iSubtrainIn', 'iValidateIn', 'sampling', 'MLmodelIn', 'MLmodelOut',
732
+ 'molDescriptor', 'kernel'
733
+ ],
734
+ ""
735
+ )
736
+ self.add_dict_args({'MLmodelType': None, 'nthreads': None})
737
+ self.set_keyword_alias('crossSection', ['ML-NEA', 'ML_NEA', 'crossSection', 'cross-section', 'cross_section','MLNEA'])
738
+ self.args2pass = []
739
+ self.parse_input_content([
740
+ 'hyperopt.max_evals=8',
741
+ 'hyperopt.algorithm=tpe',
742
+ 'hyperopt.losstype=geomean',
743
+ 'hyperopt.w_grad=0.1'
744
+ ])
745
+ self.optlines=''
746
+
747
+ def parse(self, argsraw):
748
+ if len(argsraw) == 0:
749
+ Doc.printDoc({})
750
+ stopper.stopMLatom('At least one option should be provided')
751
+ elif len(argsraw) == 1:
752
+ if os.path.exists(argsraw[0]):
753
+ self.parse_input_file(argsraw[0])
754
+ else:
755
+ self.parse_input_content(argsraw[0])
756
+ self.args2pass = self.args_string_list(['', None])
757
+ elif len(argsraw) >= 2:
758
+ self.parse_input_content(argsraw)
759
+ self.args2pass = self.args_string_list(['', None])
760
+ self.argProcess()
761
+
762
+ def argProcess(self):
763
+ self.add_keyword_value_args(
764
+ ['absXfileIn','absXYZfile','absYfile','absYgradXYZfile'],
765
+ [os.path.abspath(self.XfileIn),os.path.abspath(self.XYZfile),os.path.abspath(self.Yfile),os.path.abspath(self.YgradXYZfile)]
766
+ )
767
+ for arg in self.args2pass:
768
+ if bool(re.search('hyperopt\..+?\(.+?\)',arg)):
769
+ import hyperopt
770
+ globals()['hyperopt']=hyperopt
771
+ self.optlines = self.optlines+arg+'\n'
772
+
773
+ if self.MLmodelType:
774
+ try: self.MLprog=MLtasksCls.default_MLprog[self.MLmodelType.lower()]
775
+ except: stopper.stopMLatom('Unkown MLmodelType')
776
+ if self.selfCorrect:
777
+ self.parse_input_content([
778
+ 'nlayers=4'])
779
+ if self.selfCorrect and (argexist('iTrainOut=', self.args2pass) or argexist('iTestOut=', self.args2pass) or argexist('iSubtrainOut=', self.args2pass) or argexist('iValidateOut=', self.args2pass)):
780
+ stopper.stopMLatom('Indices of subsets cannot be saved for self-correction')
781
+
782
+ if __name__ == '__main__':
783
+ print(__doc__)
784
+ MLtasks()