Package: efg
Python bindings ofEasy Factor Graph.Easy Factor Graphis a general purpose library handling undirected graphical models.Markov Random Fieldsas well asConditional Random Fieldsfall under this cathegory.
Refer tothis documentationfor all the details.Isn't great that you can have the access to the whole power ofEasy Factor Graphinside python?? Leave a star in theoriginal repoplease ;).USAGEFACTORS CONSTRUCTIONfromefgimportVariable# define a couple of variables, with the same sizeA=Variable(3,"A")# size is 3B=Variable(3,"B")# size is 3Such variables can be referred by the factors correlating them. In order to build a simple correlating factor this is what you would do:fromefgimportFactor,Group# build a simply correlating factor connecting the 2 variablesfactor_AB=Factor.makeSimplyCorrelated(Group.make([A,B]))And this is what you would do to generate an exponential simple correlating factor:fromefgimportFactorExponential# build an exponential factor using as base `factor_AB`: values of the# images are assumed as exp(weight * images_factor_AB)factor_AB_exponential=FactorExponential(factor_AB,1.5)# 1.5 this will be the value assumed for the weightYou can also define custom factors, specifying the shape function that maps the values in their domain with their images. For example:factor_BC=Factor.makeSimplyCorrelated(Group.make([B,Variable(3,'C')]))# set some individual images of factor_BC# set for <0,1> -> 2factor_BC.set([0,1],2)# set for <2,0> -> 1.3ffactor_BC.set([2,0],1.3)MODELS CONSTRUCTIONFactor graphs can be built incrementally, passing one by one the factors that compose them. Without loss of generality suppose to start from an emptyrandom field:fromefgimportRandomField# start building an empty random fieldmodel=RandomField()then, you can build some factors and enrich the model with them:# define some variables, which will be later connectedA=Variable(4,"varA")B=Variable(4,"varB")C=Variable(4,"varC")# without loss of generality, add to the model some simply correlating factorsfactor_AB=Factor.makeSimplyCorrelated(Group.make([A,B]))model.addConstFactor(factor_AB)# the same factor_AB is added to the modelmodel.copyConstFactor(Factor.makeSimplyCorrelated(Group.make([A,C])))# a deep-copy of the factor is added into the modelThe previously added factor are kept constant in the model. In order to enrich the model with a tunable factor you can call a different method:# build some additional tunable exponential factors that will be too addedfactor_exp_BC=FactorExponential(Factor.makeSimplyCorrelated(Group.make([B,C])),1.0)model.addTunableFactor(factor_exp_BC)D=Variable(4,"varD")factor_exp_CD=FactorExponential(Factor.makeSimplyCorrelated(Group.make([C,D])),1.5)model.addTunableFactor(factor_exp_CD)You can also add a tunable factor, that must share its weigth with an already inserted factor of the model:# insert another tunable factor, this time specifying that it needs to# share the weight with already inserted exponential factor that connects B and Cmodel.addTunableFactorSharingWeight(FactorExponential(Factor.makeSimplyCorrelated(Group.make([C,D])),1.5# actually this value is irrelevant, as the weight of factor_exp_BC will be assumed from now on),[B,C]# this additional input is to specify that this exponential factor needs to share the weight with the one connecting B and C)You can also import the entire graph defined in an xml file (checkthese samplesfor the expected format):fromefgimportxmlasefg_xmlmodel=RandomField()efg_xml.from_file(model,'some/path/model.xml')Similarly, you can also import the structure defined in a jsonimportjsonfromefgimportjsonasefg_jsonmodel_json=json...model=RandomField()modelJson=efg_json.from_string(model,json.dumps(model_json))QUERY THE MODELA generated model can be queried in many ways. However, any query that you can do, is conditioned to the latest set of evidences.Setting the evidences can be easily done by calling:# set some evidencesmodel.setEvidenceByName("variable_1",0)# setting variable_1 = 0model.setEvidenceByName("variable_2",2)# setting variable_2 = 2You can get the conditioned marginal distribution of a variable by calling:# get the marginal conditioned distribution of an hidden variableconditioned_marginals=model.getMarginalDistributionByName("var_A")Or you might be interested in the maximum a posteriori estimation of the entire evidence set:# get maxiomum a posteriori estimation of the entire hidden setMAP_hidden_set=model.getHiddenSetMAP()As already mentioned, results are subjected to the latest evidences set (which can be also empty). Of course, you can update the evidences and get the updated marginals:# set some new evidencesmodel.removeAllEvidences()model.setEvidenceByName("evid_1",1)# compute new conditioned marginals: the should be different as the# evidences were changedconditioned_marginals=model.getMarginalDistributionByName("var_A")GIBBS SAMPLINGfromefgimportSamplesGenerationContext# some definitions to control the samples generation processctxt=SamplesGenerationContext()ctxt.setDeltaIterations(1000)# samples numberctxt.setSeed(0)# seed used by random enginesctxt.setTransient(500)# number of iterations to discard at the beginning (burn out)# get samples from the model using Gibbs samplersamples=# this will be a list of lists [[0,2,1], [0,1,1], etc... ]model.makeSamples(info,4# threads to use)