Source code for neograd.nn.model
import dill
from itertools import chain as list_flattener
from .layers import Container, Layer
from ..autograd.utils import get_graph
[docs]class Model:
def __call__(self, inputs):
'''Abstracts the forward method
Args:
inputs (Tensor): Inputs to the model
Returns:
Tensor of the result
'''
return self.forward(inputs)
[docs] def eval(self, no_track=True):
'''Invokes EvalMode ContextManager
Args:
no_track (bool): If Tensors shouldn't be tracked, Defaults to False
Returns:
EvalMode ContextManager
'''
return EvalMode(self, no_track)
[docs] def get_layers(self):
'''Gathers all the layers in the Model
Accomplishes by going through all its attributes and if their values are
instances of Container/Layer it is taken as a layer
Returns:
Dict with attributes as key and their objects as value
'''
layers = {}
for attr, val in self.__dict__.items():
if isinstance(val, (Container, Layer)):
layers[attr] = val
return layers
[docs] def parameters(self, as_dict=False):
'''Gathers the params of the whole Model
Accomplishes this by iterating through all layers and getting their params
Args:
as_dict (bool): Whether to return the params as a dict. Defaults to False
'''
params = {}
for attr, layer in self.get_layers().items():
params[attr] = layer.parameters(as_dict)
return params if as_dict else list(list_flattener(*params.values()))
[docs] def set_eval(self, eval):
'''Sets eval
Sets the eval of its layers to eval argument
Args:
eval (bool): Whether in eval mode or not
'''
for layer in self.get_layers().values():
layer.set_eval(eval)
[docs] def save(self, fpath):
'''Saves the params of the model in the specified file path
Args:
fpath (str): File path
'''
params = self.parameters(as_dict=True)
with open(fpath, 'wb') as fp:
dill.dump(params, fp)
print(f"\nPARAMS SAVED at {fpath}\n")
[docs] def load(self, fpath):
'''Loads the params from the filepath onto the model
Args:
fpath (str): File path
'''
with open(fpath, 'rb') as fp:
params = dill.load(fp)
for attr, param in params.items():
layer = self.__getattribute__(attr)
layer.set_params(param)
print(f"\nPARAMS LOADED from {fpath}\n")
def __setattr__(self, attr, val):
'''Sets the attributes
Doesn't allow redefining an attribute that's been previously defined if the
value of the attribute is instance of Container/Layer
Args:
attr (str): Attribute to be set
val (object): Value to be set
'''
if isinstance(val, (Container, Layer)) and (attr in self.__dict__):
raise AttributeError(f"Attribute {attr} has already been defined, it cannot be defined again for a Container/Layer")
object.__setattr__(self, attr, val)
def __repr__(self):
return f'Model( {[str(layer) for layer in self.get_layers().values()]} )'
def __str__(self):
return f'Model( {[str(layer) for layer in self.get_layers().values()]} )'
[docs]class EvalMode:
'''ContextManager for handling eval
A ContextManager to run the model in eval mode, ie while testing the model.
Use of this is that some layers like Dropout need to be turned off while
testing
Args:
model (Model): Model to be put into eval
no_track (bool): If True, then the backward graph is not created and the tensors
aren't tracked
graph (Graph): Graph that's currently in use
'''
def __init__(self, model, no_track):
self.model = model
self.no_track = no_track
self.graph = get_graph()
def __enter__(self):
'''
If no_track, then sets graph track to False
Puts model in eval mode, by setting it to True
'''
if self.no_track:
self.graph.track = False
self.model.set_eval(True)
def __exit__(self, exc_type, exc_value, exc_traceback):
'''
If no_track, then sets back graph track to True
Puts model out of eval mode, by setting it to False
'''
if self.no_track:
self.graph.track = True
self.model.set_eval(False)