Unverified Commit f9b074ce authored by Gao, Xiang's avatar Gao, Xiang Committed by GitHub
Browse files

Reduce test latency (#319)

* Move unittest check to GitHub Actions

Tests are parallelized

* Delete tests.yml

* Update setup.py

* Create test_requirements.txt

* Update unittest.yml

* Update unittest.yml

* Update README.md

* Delete install_dependencies.sh

* Delete install_dependencies_python2.sh

* Update unittest.yml

* split

* split

* fix

* fix

* -v

* more

* more

* fix

* fix

* flake8

* transform

* reduce testBenzeneMD

* version

* reduce number of epoches

* further reduce time

* Update docs.yml
parent 48846357
...@@ -308,7 +308,7 @@ tensorboard = torch.utils.tensorboard.SummaryWriter() ...@@ -308,7 +308,7 @@ tensorboard = torch.utils.tensorboard.SummaryWriter()
mse = torch.nn.MSELoss(reduction='none') mse = torch.nn.MSELoss(reduction='none')
print("training starting from epoch", AdamW_scheduler.last_epoch + 1) print("training starting from epoch", AdamW_scheduler.last_epoch + 1)
max_epochs = 200 max_epochs = 10
early_stopping_learning_rate = 1.0E-5 early_stopping_learning_rate = 1.0E-5
best_model_checkpoint = 'best.pt' best_model_checkpoint = 'best.pt'
......
...@@ -248,7 +248,9 @@ tensorboard = torch.utils.tensorboard.SummaryWriter() ...@@ -248,7 +248,9 @@ tensorboard = torch.utils.tensorboard.SummaryWriter()
mse = torch.nn.MSELoss(reduction='none') mse = torch.nn.MSELoss(reduction='none')
print("training starting from epoch", AdamW_scheduler.last_epoch + 1) print("training starting from epoch", AdamW_scheduler.last_epoch + 1)
max_epochs = 20 # We only train 3 epoches here in able to generate the docs quickly.
# Real training should take much more than 3 epoches.
max_epochs = 3
early_stopping_learning_rate = 1.0E-5 early_stopping_learning_rate = 1.0E-5
force_coefficient = 0.1 # controls the importance of energy loss vs force loss force_coefficient = 0.1 # controls the importance of energy loss vs force loss
best_model_checkpoint = 'force-training-best.pt' best_model_checkpoint = 'force-training-best.pt'
......
import random
import unittest
import torch
import torchani
tolerance = 1e-5
class _TestAEVBase(unittest.TestCase):
def setUp(self):
ani1x = torchani.models.ANI1x()
self.aev_computer = ani1x.aev_computer
self.radial_length = self.aev_computer.radial_length
self.debug = False
def transform(self, x):
return x
def random_skip(self, prob=0):
return random.random() < prob
def assertAEVEqual(self, expected_radial, expected_angular, aev, tolerance=tolerance):
radial = aev[..., :self.radial_length]
angular = aev[..., self.radial_length:]
radial_diff = expected_radial - radial
if self.debug:
aid = 1
print(torch.stack([expected_radial[0, aid, :], radial[0, aid, :], radial_diff.abs()[0, aid, :]], dim=1))
radial_max_error = torch.max(torch.abs(radial_diff)).item()
angular_diff = expected_angular - angular
angular_max_error = torch.max(torch.abs(angular_diff)).item()
self.assertLess(radial_max_error, tolerance)
self.assertLess(angular_max_error, tolerance)
...@@ -3,18 +3,17 @@ import torchani ...@@ -3,18 +3,17 @@ import torchani
import unittest import unittest
import os import os
import pickle import pickle
import random
import copy import copy
import itertools import itertools
import ase import ase
import ase.io import ase.io
import math import math
import traceback import traceback
from common_aev_test import _TestAEVBase
path = os.path.dirname(os.path.realpath(__file__)) path = os.path.dirname(os.path.realpath(__file__))
N = 97 N = 97
tolerance = 1e-5
class TestIsolated(unittest.TestCase): class TestIsolated(unittest.TestCase):
...@@ -85,32 +84,7 @@ class TestIsolated(unittest.TestCase): ...@@ -85,32 +84,7 @@ class TestIsolated(unittest.TestCase):
self.fail(f'\n\n{error}\nFailure on lone atom\n') self.fail(f'\n\n{error}\nFailure on lone atom\n')
class TestAEV(unittest.TestCase): class TestAEV(_TestAEVBase):
def setUp(self):
ani1x = torchani.models.ANI1x()
self.aev_computer = ani1x.aev_computer
self.radial_length = self.aev_computer.radial_length
self.debug = False
def random_skip(self, prob=0):
return random.random() < prob
def transform(self, x):
return x
def assertAEVEqual(self, expected_radial, expected_angular, aev, tolerance=tolerance):
radial = aev[..., :self.radial_length]
angular = aev[..., self.radial_length:]
radial_diff = expected_radial - radial
if self.debug:
aid = 1
print(torch.stack([expected_radial[0, aid, :], radial[0, aid, :], radial_diff.abs()[0, aid, :]], dim=1))
radial_max_error = torch.max(torch.abs(radial_diff)).item()
angular_diff = expected_angular - angular
angular_max_error = torch.max(torch.abs(angular_diff)).item()
self.assertLess(radial_max_error, tolerance)
self.assertLess(angular_max_error, tolerance)
def testIsomers(self): def testIsomers(self):
for i in range(N): for i in range(N):
...@@ -129,44 +103,6 @@ class TestAEV(unittest.TestCase): ...@@ -129,44 +103,6 @@ class TestAEV(unittest.TestCase):
_, aev = self.aev_computer((species, coordinates)) _, aev = self.aev_computer((species, coordinates))
self.assertAEVEqual(expected_radial, expected_angular, aev) self.assertAEVEqual(expected_radial, expected_angular, aev)
def testBenzeneMD(self):
for i in range(10):
datafile = os.path.join(path, 'test_data/benzene-md/{}.dat'.format(i))
with open(datafile, 'rb') as f:
coordinates, species, expected_radial, expected_angular, _, _, cell, pbc \
= pickle.load(f)
coordinates = torch.from_numpy(coordinates).float().unsqueeze(0)
species = torch.from_numpy(species).unsqueeze(0)
expected_radial = torch.from_numpy(expected_radial).float().unsqueeze(0)
expected_angular = torch.from_numpy(expected_angular).float().unsqueeze(0)
cell = torch.from_numpy(cell).float()
pbc = torch.from_numpy(pbc)
coordinates = torchani.utils.map2central(cell, coordinates, pbc)
coordinates = self.transform(coordinates)
species = self.transform(species)
expected_radial = self.transform(expected_radial)
expected_angular = self.transform(expected_angular)
_, aev = self.aev_computer((species, coordinates), cell=cell, pbc=pbc)
self.assertAEVEqual(expected_radial, expected_angular, aev, 5e-5)
def testTripeptideMD(self):
tol = 5e-6
for i in range(100):
datafile = os.path.join(path, 'test_data/tripeptide-md/{}.dat'.format(i))
with open(datafile, 'rb') as f:
coordinates, species, expected_radial, expected_angular, _, _, _, _ \
= pickle.load(f)
coordinates = torch.from_numpy(coordinates).float().unsqueeze(0)
species = torch.from_numpy(species).unsqueeze(0)
expected_radial = torch.from_numpy(expected_radial).float().unsqueeze(0)
expected_angular = torch.from_numpy(expected_angular).float().unsqueeze(0)
coordinates = self.transform(coordinates)
species = self.transform(species)
expected_radial = self.transform(expected_radial)
expected_angular = self.transform(expected_angular)
_, aev = self.aev_computer((species, coordinates))
self.assertAEVEqual(expected_radial, expected_angular, aev, tol)
def testPadding(self): def testPadding(self):
species_coordinates = [] species_coordinates = []
radial_angular = [] radial_angular = []
...@@ -195,20 +131,6 @@ class TestAEV(unittest.TestCase): ...@@ -195,20 +131,6 @@ class TestAEV(unittest.TestCase):
start += conformations start += conformations
self.assertAEVEqual(expected_radial, expected_angular, aev_) self.assertAEVEqual(expected_radial, expected_angular, aev_)
def testNIST(self):
datafile = os.path.join(path, 'test_data/NIST/all')
with open(datafile, 'rb') as f:
data = pickle.load(f)
for coordinates, species, radial, angular, _, _ in data:
if self.random_skip():
continue
coordinates = torch.from_numpy(coordinates).to(torch.float)
species = torch.from_numpy(species)
radial = torch.from_numpy(radial).to(torch.float)
angular = torch.from_numpy(angular).to(torch.float)
_, aev = self.aev_computer((species, coordinates))
self.assertAEVEqual(radial, angular, aev)
@unittest.skipIf(not torch.cuda.is_available(), "Too slow on CPU") @unittest.skipIf(not torch.cuda.is_available(), "Too slow on CPU")
def testGradient(self): def testGradient(self):
"""Test validity of autodiff by comparing analytical and numerical """Test validity of autodiff by comparing analytical and numerical
......
import os
import torch
import pickle
import torchani
import unittest
from common_aev_test import _TestAEVBase
path = os.path.dirname(os.path.realpath(__file__))
class TestAEVBenzeneMD(_TestAEVBase):
def testBenzeneMD(self):
for i in [2, 8]:
datafile = os.path.join(path, 'test_data/benzene-md/{}.dat'.format(i))
with open(datafile, 'rb') as f:
coordinates, species, expected_radial, expected_angular, _, _, cell, pbc \
= pickle.load(f)
coordinates = torch.from_numpy(coordinates).float().unsqueeze(0)
species = torch.from_numpy(species).unsqueeze(0)
expected_radial = torch.from_numpy(expected_radial).float().unsqueeze(0)
expected_angular = torch.from_numpy(expected_angular).float().unsqueeze(0)
cell = torch.from_numpy(cell).float()
pbc = torch.from_numpy(pbc)
coordinates = torchani.utils.map2central(cell, coordinates, pbc)
coordinates = self.transform(coordinates)
species = self.transform(species)
expected_radial = self.transform(expected_radial)
expected_angular = self.transform(expected_angular)
_, aev = self.aev_computer((species, coordinates), cell=cell, pbc=pbc)
self.assertAEVEqual(expected_radial, expected_angular, aev, 5e-5)
if __name__ == '__main__':
unittest.main()
import os
import torch
import pickle
import unittest
from common_aev_test import _TestAEVBase
path = os.path.dirname(os.path.realpath(__file__))
class TestAEVNIST(_TestAEVBase):
def testNIST(self):
datafile = os.path.join(path, 'test_data/NIST/all')
with open(datafile, 'rb') as f:
data = pickle.load(f)
for coordinates, species, radial, angular, _, _ in data:
if self.random_skip():
continue
coordinates = torch.from_numpy(coordinates).to(torch.float)
species = torch.from_numpy(species)
radial = torch.from_numpy(radial).to(torch.float)
angular = torch.from_numpy(angular).to(torch.float)
_, aev = self.aev_computer((species, coordinates))
self.assertAEVEqual(radial, angular, aev)
if __name__ == '__main__':
unittest.main()
import os
import torch
import pickle
import unittest
from common_aev_test import _TestAEVBase
path = os.path.dirname(os.path.realpath(__file__))
class TestAEVTripeptideMD(_TestAEVBase):
def testTripeptideMD(self):
tol = 5e-6
for i in range(100):
datafile = os.path.join(path, 'test_data/tripeptide-md/{}.dat'.format(i))
with open(datafile, 'rb') as f:
coordinates, species, expected_radial, expected_angular, _, _, _, _ \
= pickle.load(f)
coordinates = torch.from_numpy(coordinates).float().unsqueeze(0)
species = torch.from_numpy(species).unsqueeze(0)
expected_radial = torch.from_numpy(expected_radial).float().unsqueeze(0)
expected_angular = torch.from_numpy(expected_angular).float().unsqueeze(0)
coordinates = self.transform(coordinates)
species = self.transform(species)
expected_radial = self.transform(expected_radial)
expected_angular = self.transform(expected_angular)
_, aev = self.aev_computer((species, coordinates))
self.assertAEVEqual(expected_radial, expected_angular, aev, tol)
if __name__ == '__main__':
unittest.main()
...@@ -3,7 +3,6 @@ import torchani ...@@ -3,7 +3,6 @@ import torchani
import unittest import unittest
import os import os
import pickle import pickle
import math
path = os.path.dirname(os.path.realpath(__file__)) path = os.path.dirname(os.path.realpath(__file__))
...@@ -42,42 +41,6 @@ class TestEnergies(unittest.TestCase): ...@@ -42,42 +41,6 @@ class TestEnergies(unittest.TestCase):
max_diff = (energies - energies_).abs().max().item() max_diff = (energies - energies_).abs().max().item()
self.assertLess(max_diff, self.tolerance) self.assertLess(max_diff, self.tolerance)
def testBenzeneMD(self):
tolerance = 1e-5
for i in range(10):
datafile = os.path.join(path, 'test_data/benzene-md/{}.dat'.format(i))
with open(datafile, 'rb') as f:
coordinates, species, _, _, energies, _, cell, pbc \
= pickle.load(f)
coordinates = torch.from_numpy(coordinates).float().unsqueeze(0)
species = torch.from_numpy(species).unsqueeze(0)
cell = torch.from_numpy(cell).float()
pbc = torch.from_numpy(pbc)
coordinates = torchani.utils.map2central(cell, coordinates, pbc)
coordinates = self.transform(coordinates)
species = self.transform(species)
energies = self.transform(energies)
_, aev = self.aev_computer((species, coordinates), cell=cell, pbc=pbc)
_, energies_ = self.nn((species, aev))
max_diff = (energies - energies_).abs().max().item()
self.assertLess(max_diff, tolerance)
def testTripeptideMD(self):
tolerance = 2e-4
for i in range(100):
datafile = os.path.join(path, 'test_data/tripeptide-md/{}.dat'.format(i))
with open(datafile, 'rb') as f:
coordinates, species, _, _, energies, _, _, _ \
= pickle.load(f)
coordinates = torch.from_numpy(coordinates).float().unsqueeze(0)
species = torch.from_numpy(species).unsqueeze(0)
coordinates = self.transform(coordinates)
species = self.transform(species)
energies = self.transform(energies)
_, energies_ = self.model((species, coordinates))
max_diff = (energies - energies_).abs().max().item()
self.assertLess(max_diff, tolerance)
def testPadding(self): def testPadding(self):
species_coordinates = [] species_coordinates = []
energies = [] energies = []
...@@ -100,21 +63,6 @@ class TestEnergies(unittest.TestCase): ...@@ -100,21 +63,6 @@ class TestEnergies(unittest.TestCase):
max_diff = (energies - energies_).abs().max().item() max_diff = (energies - energies_).abs().max().item()
self.assertLess(max_diff, self.tolerance) self.assertLess(max_diff, self.tolerance)
def testNIST(self):
datafile = os.path.join(path, 'test_data/NIST/all')
with open(datafile, 'rb') as f:
data = pickle.load(f)
for coordinates, species, _, _, e, _ in data:
if self.random_skip():
continue
coordinates = torch.from_numpy(coordinates).to(torch.float)
species = torch.from_numpy(species)
energies = torch.from_numpy(e).to(torch.float)
_, energies_ = self.model((species, coordinates))
natoms = coordinates.shape[1]
max_diff = (energies - energies_).abs().max().item()
self.assertLess(max_diff / math.sqrt(natoms), self.tolerance)
class TestEnergiesEnergyShifterJIT(TestEnergies): class TestEnergiesEnergyShifterJIT(TestEnergies):
def setUp(self): def setUp(self):
......
...@@ -66,65 +66,6 @@ class TestForce(unittest.TestCase): ...@@ -66,65 +66,6 @@ class TestForce(unittest.TestCase):
max_diff = (forces + derivative).abs().max().item() max_diff = (forces + derivative).abs().max().item()
self.assertLess(max_diff, self.tolerance) self.assertLess(max_diff, self.tolerance)
def testBenzeneMD(self):
tolerance = 1e-5
for i in range(10):
datafile = os.path.join(path, 'test_data/benzene-md/{}.dat'.format(i))
with open(datafile, 'rb') as f:
coordinates, species, _, _, _, forces, cell, pbc \
= pickle.load(f)
coordinates = torch.from_numpy(coordinates).float().unsqueeze(0).requires_grad_(True)
species = torch.from_numpy(species).unsqueeze(0)
cell = torch.from_numpy(cell).float()
pbc = torch.from_numpy(pbc)
forces = torch.from_numpy(forces)
coordinates = torchani.utils.map2central(cell, coordinates, pbc)
coordinates = self.transform(coordinates)
species = self.transform(species)
forces = self.transform(forces)
_, aev = self.aev_computer((species, coordinates), cell=cell, pbc=pbc)
_, energies_ = self.nnp((species, aev))
derivative = torch.autograd.grad(energies_.sum(),
coordinates)[0]
max_diff = (forces + derivative).abs().max().item()
self.assertLess(max_diff, tolerance)
def testTripeptideMD(self):
tolerance = 2e-6
for i in range(100):
datafile = os.path.join(path, 'test_data/tripeptide-md/{}.dat'.format(i))
with open(datafile, 'rb') as f:
coordinates, species, _, _, _, forces, _, _ \
= pickle.load(f)
coordinates = torch.from_numpy(coordinates).float().unsqueeze(0).requires_grad_(True)
species = torch.from_numpy(species).unsqueeze(0)
forces = torch.from_numpy(forces)
coordinates = self.transform(coordinates)
species = self.transform(species)
forces = self.transform(forces)
_, energies_ = self.model((species, coordinates))
derivative = torch.autograd.grad(energies_.sum(),
coordinates)[0]
max_diff = (forces + derivative).abs().max().item()
self.assertLess(max_diff, tolerance)
def testNIST(self):
datafile = os.path.join(path, 'test_data/NIST/all')
with open(datafile, 'rb') as f:
data = pickle.load(f)
for coordinates, species, _, _, _, forces in data:
if self.random_skip():
continue
coordinates = torch.from_numpy(coordinates).to(torch.float) \
.requires_grad_(True)
species = torch.from_numpy(species)
forces = torch.from_numpy(forces).to(torch.float)
_, energies = self.model((species, coordinates))
derivative = torch.autograd.grad(energies.sum(),
coordinates)[0]
max_diff = (forces + derivative).abs().max().item()
self.assertLess(max_diff, self.tolerance)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment