The use of torchani.nn.Sequential is highly discouraged due to being error-prone and verbose. Instead, use factory functions in torchani.arch or the torchani.arch.Assembler class to build models ready for training.
Option 1: Simple Factory Functions
Use torchani.arch.simple_ani for a quick setup with random weights.
Option 2: Using Assembler for Customization
Use torchani.arch.Assembler to fine-tune components like radial/angular terms, strategies (e.g., cuAEV), and ground state atomic energies (GSAEs).
Option 3: Custom torch.nn.Module
For maximum flexibility, inherit from torch.nn.Module and manually compose the components.
# Option 1: Simple factory
from torchani.arch import simple_ani
model = simple_ani(("H", "C", "N", "O", "S"), lot="wb97x-631gd")
# Option 2: Assembler
import torchani
asm = torchani.arch.Assembler()
asm.set_symbols(("H", "C", "N", "O"))
asm.set_aev_computer(radial="ani2x", angular="ani2x", strategy="cuaev")
asm.set_atomic_networks(ctor="ani2x")
asm.set_gsaes_as_self_energies("wb97x-631gd")
model = asm.assemble()
# Option 3: Custom Module
import torchani
from torch.nn import Module
class Model(Module):
def __init__(self):
super().__init__()
self.converter = torchani.nn.SpeciesConverter("...")
self.neighborlist = torchani.neighbors.AllPairs("...")
self.aevc = torchani.aev.AEVComputer("...")
self.nn = torchani.nn.ANINetworks("...")
self.shifter = torchani.sae.SelfEnergy("...")
def forward(self, atomic_nums, coords, cell, pbc):
idxs = self.converter(atomic_nums)
cutoff = self.aevc.radial.cutoff
neighbors = self.neighborlist(cutoff, idxs, coords, cell, pbc)
aevs = self.aevc.compute_from_neighbors(idxs, neighbors)
return self.nn(idxs, aevs) + self.shifter(idxs)
model = Model()