1
0
Fork 0
Old engine for Continuous Time Bayesian Networks. Superseded by reCTBN. 🐍 https://github.com/madlabunimib/PyCTBN
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
Filippo Martini e358f53ce9 Merge pull 4 years ago
.github/workflows Update python-PyCTBN-package.yml 4 years ago
PyCTBN Modify plot graph method 4 years ago
docs Update documentation 4 years ago
docs-out Update documentation 4 years ago
.coverage Improved test coverage to 98% 4 years ago
.coveragerc Improved test coverage to 98% 4 years ago
.gitattributes Update .gitattributes 4 years ago
.gitignore Modify plot graph method 4 years ago
CTBN_Diagramma_Dominio.pdf Improved test coverage to 98% 4 years ago
README.rst Modify README 4 years ago
coverage.xml Improved test coverage to 98% 4 years ago
doc-requirements.txt Create doc-requirements.txt 4 years ago
requirements.txt Updated action CI 4 years ago
setup.py Modify plot graph method 4 years ago

README.rst

PyCTBN
======

A Continuous Time Bayesian Networks Library

Installation/Usage
*******************
Download the release in .tar.gz or .whl format and simply use pip install to install it::

$ pip install PyCTBN-1.0.tar.gz

Documentation
*************
Please refer to https://philipmartini.github.io/PyCTBN/ for the full project documentation.

Implementing your own data importer
***********************************
.. code-block:: python

"""This example demonstrates the implementation of a simple data importer the extends the class abstract importer to import data in csv format.
The net in exam has three ternary nodes and no prior net structure.
"""

from PyCTBN import AbstractImporter

class CSVImporter(AbstractImporter):

def __init__(self, file_path):
self._df_samples_list = None
super(CSVImporter, self).__init__(file_path)

def import_data(self):
self.read_csv_file()
self._sorter = self.build_sorter(self._df_samples_list[0])
self.import_variables()
self.compute_row_delta_in_all_samples_frames(self._df_samples_list)

def read_csv_file(self):
df = pd.read_csv(self._file_path)
df.drop(df.columns[[0]], axis=1, inplace=True)
self._df_samples_list = [df]

def import_variables(self):
values_list = [3 for var in self._sorter]
# initialize dict of lists
data = {'Name':self._sorter, 'Value':values_list}
# Create the pandas DataFrame
self._df_variables = pd.DataFrame(data)

def build_sorter(self, sample_frame: pd.DataFrame) -> typing.List:
return list(sample_frame.columns)[1:]

def dataset_id(self) -> object:
pass

Parameters Estimation Example
*****************************

.. code-block:: python

from PyCTBN import JsonImporter
from PyCTBN import SamplePath
from PyCTBN import NetworkGraph
from PyCTBN import ParametersEstimator


def main():
read_files = glob.glob(os.path.join('./data', "*.json")) #Take all json files in this dir
#import data
importer = JsonImporter(read_files[0], 'samples', 'dyn.str', 'variables', 'Time', 'Name')
importer.import_data(0)
#Create a SamplePath Obj passing an already filled AbstractImporter object
s1 = SamplePath(importer)
#Build The trajectries and the structural infos
s1.build_trajectories()
s1.build_structure()
print(s1.structure.edges)
print(s1.structure.nodes_values)
#From The Structure Object build the Graph
g = NetworkGraph(s1.structure)
#Select a node you want to estimate the parameters
node = g.nodes[2]
print("Node", node)
#Init the _graph specifically for THIS node
g.fast_init(node)
#Use SamplePath and Grpah to create a ParametersEstimator Object
p1 = ParametersEstimator(s1.trajectories, g)
#Init the peEst specifically for THIS node
p1.fast_init(node)
#Compute the parameters
sofc1 = p1.compute_parameters_for_node(node)
#The est CIMS are inside the resultant SetOfCIms Obj
print(sofc1.actual_cims)

Structure Estimation Examples
****************************
This example shows how to estimate the structure given a series of trajectories using a constraint based approach.
The first three instructions import all the necessary data (trajectories, nodes cardinalities, nodes labels),
and are contextual to the dataset that is been used, in the code comments are marked as optional <>.
If your data has a different structure or format you should implement your own importer (see Implementing your own importer example).
The other instructions are not optional and should follow the same order.
A SamplePath object is been created, passing an AbstractImporter object that contains the correct class members filled
with the data that are necessary to estimate the structure.
Next the build_trajectories and build_structure methods are called to instantiate the objects that will contain
the processed trajectories and all the net infos.
Then an estimator object is created, in this case a constraint based estimator, it necessary to pass a SamplePath object
where build_trajectories and build_structure methods have already been called.
If you have prior knowledge about the net structure pass it to the constructor with the known_edges parameter.
The other three parameters are contextual to the StructureConstraintBasedEstimator, see the documentation for more details.
To estimate the structure simply call the estimate_structure method.
You can obtain the estimated structure as a boolean adjacency matrix with the method adjacency_matrix, or save it as a json file
that contains all the nodes labels, and obviously the estimated edges.
You can also save a graphical model representation of the estimated structure with the save_plot_estimated_structure_graph.

.. code-block:: python

import glob
import os

from PyCTBN import JsonImporter
from PyCTBN import SamplePath
from PyCTBN import StructureConstraintBasedEstimator


def structure_constraint_based_estimation_example():
# <read the json files in ./data path>
read_files = glob.glob(os.path.join('./data', "*.json"))
# <initialize a JsonImporter object for the first file>
importer = JsonImporter(file_path=read_files[0], samples_label='samples',
structure_label='dyn.str', variables_label='variables',
time_key='Time', variables_key='Name')
# <import the data at index 0 of the outer json array>
importer.import_data(0)
# construct a SamplePath Object passing a filled AbstractImporter object
s1 = SamplePath(importer=importer)
# build the trajectories
s1.build_trajectories()
# build the information about the net
s1.build_structure()
# construct a StructureEstimator object passing a correctly build SamplePath object and the
# independence tests significance, if you have prior knowledge about the net structure create a list of tuples
# that contains them and pass it as known_edges parameter
se1 = StructureConstraintBasedEstimator(sample_path=s1, exp_test_alfa=0.1, chi_test_alfa=0.1,
known_edges=[], thumb_threshold=25)
# call the algorithm to estimate the structure
se1.estimate_structure()
# obtain the adjacency matrix of the estimated structure
print(se1.adjacency_matrix())
# save the estimated structure to a json file (remember to specify the path AND the .json extension)....
se1.save_results('./results0.json')
# ...or save it also in a graphical model fashion (remember to specify the path AND the .png extension)
se1.save_plot_estimated_structure_graph('./result0.png')