Package: genos
Instantiate objects and call functions using dictionary configs in Python using Genos.
This package was originally developed to help python developers in making configurable software components.WhileHydralets you instantiate objects and functions, it doesn't support recursive instantiation.
Plus, Hydra is mostly used for config management.
So, we decided to build Genos by referring to Hydra and added the functionality of recursive instantiation. E.g.,Install GenospipinstallgenosInstantiate a Python Class using Genosfromgenosimportrecursive_instantiatened={"cls":"genos.examples.King","params":{"name":"Eddard Stark","queen":"Catelyn Stark","allegiance":"Robert Baratheon"}}obj=recursive_instantiate(ned)print(obj)ContributorsInstallPippipinstallgenosPoetrypoetryaddgenosBasic UsageThe following examples will show how this library can make your life easier by letting you instantiate python objects from dictionaries.
First, let's consider a basic example where we simply instantiate a single class.Single Class InstantiationclassKing:def__init__(self,name:str,queen:str,allegiance:str):self.name=nameself.queen=queenself.allegiance=allegiancedef__repr__(self):returnf"Name:{self.name}\nQueen:{self.queen}\nAllegiance:{self.allegiance}"defprint_name(self):print(self.name)We need to pass 3 parameters to instantiate this class.
Note that these classes are located in thegenos.examples.*subpackage.
So, let's say we wish to instantiate aKingobject for Eddard Stark because, afterall,Winter is coming.fromgenosimportrecursive_instantiatened={"cls":"genos.examples.King","params":{"name":"Eddard Stark","queen":"Catelyn Stark","allegiance":"Robert Baratheon"}}obj=recursive_instantiate(ned)print(obj)# Name:Eddard Stark# Queen:Catelyn Stark# Allegiance:Robert BaratheonRecursive Class InstantiationWell, this seemed quite simple.
But rarely are things so simple in life.
Consider another class that takes an instance ofKingas a parameter.classHouse:def__init__(self,king:King,home:str,sigil:str):self.king=kingself.home=homeself.sigil=sigildef__repr__(self):returnf"King:{self.king.name}\nHome:{self.home}\nSigil:{self.sigil}"This is where recursive instantiation comes into action.
To initialize an object for this class, we can very easily create a nested dictionary and pass it to our magic method.
Of course, we'll be instantiating an object for House Stark.fromgenosimportrecursive_instantiatestark={"cls":"genos.examples.House","params":{"king":{"cls":"genos.examples.King","params":{"name":"Eddard Stark","queen":"Catelyn Stark","allegiance":"Robert Baratheon"}},"home":"Winterfell","sigil":"Direwolf"}}obj=recursive_instantiate(stark)print(obj)# output# King:Eddard Stark# Home:Winterfell# Sigil:DirewolfInstantiation Using Positional ArgumentsThe examples shown above always use keyword arguments to instantiate the classes. But we can also choose to simply pass in the positional arguments as shown below.fromgenosimportrecursive_instantiatestark={"cls":"genos.examples.House","args":[{"cls":"genos.examples.King","params":{"name":"Eddard Stark","queen":"Catelyn Stark","allegiance":"Robert Baratheon"}},"Winterfell","Direwolf"]}obj=recursive_instantiate(stark)print(obj)# output# King:Eddard Stark# Home:Winterfell# Sigil:DirewolfInstantiation Using Positional and Keyword ArgumentsThe following example makes use of both positional and keyword arguments together to instantiate theHouseclass. We do not pass the keyword for thekingparameter but we do so for the following parameters:homeandsigil.fromgenosimportrecursive_instantiatestark={"cls":"genos.examples.House","args":[{"cls":"genos.examples.King","params":{"name":"Eddard Stark","queen":"Catelyn Stark","allegiance":"Robert Baratheon"}}],"params":{"home":"Winterfell","sigil":"Direwolf"}}obj=recursive_instantiate(stark)print(obj)# output# King:Eddard Stark# Home:Winterfell# Sigil:DirewolfCall A FunctionJust like we classes, we can also instantiate functions by callingrecursive_instantiate. The following example shows how we can instantiate and call a simplemultiplyfunction usinggenos.fromgenosimportrecursive_instantiatefunction_call={"cls":"genos.examples.multiply","args":[12,1.3]}result=recursive_instantiate(function_call)print(result)# output# 15.600000000000001Advanced UsageDeep Learning Example using PyTorchFor running the following examples you will need to installPytorch.pipinstalltorchSuch workflows where we need to instantiate multiple classes recursively is more evident in Deep Learning and related fields.
NeuralSpace has been actively working in this space, building tools for Natural Language Processing (NLP). We have created this tool to make things easier for us.
The following example shows a scenario where you need different components/modules to create your own custom neural network for some specific task. The individual classes are merely wrappers aroundPyTorchfunctions. Let's get started.The following example classes can be found ingenos.examples.complex_examples.py.fromtorchimportnnclassActivationLayer(nn.Module):'''Gives two choices for activation function: ReLU or Tanh.Introduces non-linearity in neural-networks. Usually appliedafter an affine transformation.'''def__init__(self,activation:str):super().__init__()ifactivation=='relu':self.activation=nn.ReLU()else:self.activation=nn.Tanh()defforward(self,x):returnself.activation(x)classAffineLayer(nn.Module):'''Performs an affine transformation on the input tensor.For an input tensor "x", the output is W.x + b, where Wis a trainable weight matrix and b is the bias vector.'''def__init__(self,in_features:int,out_features:int,activation:ActivationLayer):super().__init__()self.transform=nn.Linear(in_features=in_features,out_features=out_features)self.activation=activationdefforward(self,x):returnself.activation(self.transform(x))classLSTMLayer(nn.Module):'''A wrapper over LSTM layer.'''def__init__(self,input_size,hidden_size,batch_first,dropout):super().__init__()self.lstm=nn.LSTM(input_size=input_size,hidden_size=hidden_size,batch_first=batch_first)self.dropout=nn.Dropout(dropout)defforward(self,x):output,_=self.lstm(x)returnself.dropout(output)The three classes above will now be used to create a custom neural network.
Note carefully that in order to instantiate anAffineLayer, we need to pass an object ofActivationLayer.
TheCustomModelwill comprise of two components:AffineLayerandLSTMLayer.classCustomModel(nn.Module):def__init__(self,affine_layer:AffineLayer,lstm_layer:LSTMLayer):super().__init__()self.affine_layer=affine_layerself.lstm_layer=lstm_layerdefforward(self,x):returnself.affine_layer(self.lstm_layer(x))The instantiation of this class using genos will be as follows.fromgenosimportrecursive_instantiatecustom_obj=\{"cls":"genos.examples.CustomModel","params":{"affine_layer":{{"cls":"examples.example.AffineLayer","params":{"in_features":256,"out_features":256,"activation":{"cls":"genos.examples.ActivationLayer","params":{"activation":"relu"}}}},{"cls":"genos.examples.LSTMLayer","params":{"input_size":256,"hidden_size":256,"batch_first":True,}}}}}model=recursive_instantiate(custom_obj)x=torch.randn(32,100,256)out=model(x)print(out.shape)# [32, 100, 256]Get Class Reference from Class PathIf you do not wish to usegenosfor instantiating your functions or classes, you can still use it to find and load different classes within your project structure. The following example shows the usage ofget_class()function fromgenosto locate theKingclass.fromgenosimportget_classclass_path="genos.examples.King"class_reference=get_class(class_path)eddard_stark=class_reference(name="Eddard Stark",queen="Catelyn Stark",allegiance="Robert Baratheon")print(eddard_stark)# Name:Eddard Stark# Queen:Catelyn Stark# Allegiance:Robert BaratheonGet Function Reference from Class PathSimilar to theget_class()method above, you can also useget_method()function fromgenosto find functions in your project structure and instantiate them normally.fromgenosimportget_methodmethod_path="genos.examples.multiply"method_reference=get_method(method_path)result=method_reference(2,3.5)print(result)# 7.0Dev SetupPrerequisitesPython >=3.7, <4Tested on Mac 10.15.6 Catalina, Ubuntu 18.04Install Bleeding Edge Version# clone the repo$gitclonehttps://github.com/Neural-Space/genos.git# Install system-level dependencies$makeinstall-system-deps# Install environment level dependencies$makeinstall-depsTesting and Code formatting# run the tests to make sure everything works$makeunit-test# check coverage of the code$maketest-coverageContribution guideRead the contribution guideline overhere.AttributionIcons made bySkyclickfromwww.flaticon.com