/fiece_em

Feasible-Infeasible Evolutionary Create & Eliminate Algorithm for Expectation Maximization.

Primary LanguagePythonMIT LicenseMIT

FIECE-EM

FIECE-EM stands for Feasible-Infeasible Evolutionary Create & Eliminate Algorithm for Expectation Maximization.

If you find this code useful in your research, please consider citing:

@inproceedings{covoes2018classification,
  author    = {Cov{\~o}es, Thiago F and Hruschka, Eduardo R},
  title     = {Classification with Multi-Modal Classes Using Evolutionary Algorithms and Constrained Clustering},
  booktitle = {IEEE Congress on Evolutionary Computation (CEC)},
  year      = {2018},
  pages     = {1-8},
  doi       = {10.1109/CEC.2018.8477858},
}

@inproceedings{fernandes2019active,
    title={Active Learning for Evolutionary Constrained Clustering},
  author={Matheus Campos Fernandes and Thiago Ferreira Cov{\~o}es and André Luiz Vizine Pereira},
  booktitle={2019 Brazilian Conference on Intelligent Systems},
  year={2019},
  organization={IEEE}
} 

How to use

First, make you sure you have Python 3.x installed, with Numpy, Scipy, Pandas and Scikit-Learn.

Then, clone or download this repository and place the fiece_em directory in your working directory.

You can then use FIECE-EM by doing:

from fiece_em import FieceEm, Constraints

X, y = read_my_dataset()

# extract 3 random objects from each class and generate corresponding constraints
constraints = Constraints.from_classes(3, y)
# create a FIECE-EM instance with a maximum of 20 clusters in a single individual
clf = FieceEm(constraints, 20)
# runs FIECE-EM
clf.fit(X)

Active Learning

We also provide Active Learning strategies for FIECE-EM.

They are avaiable in the submodule fiece_em.active_learning.strategies.

Example:

import fiece_em.active_learning as al

# get 5 objects
objects_to_label = al.strategies.best_feasible_classification_uncertainty(clf, constraints, X, 5)
# transform them into pairwise queries
pairwise_queries = al.to_pairwise(clf, constraints, X, objects_to_label)

# create a perfect oracle, which knows every object's label
oracle = al.oracles.make_oracle_from_labels(y)
# perform queries to the perfect oracle
new_constraints, number_of_questions = al.ask_oracle(constraints, pairwise_queries, oracle)

# OR perform queries to a human oracle in the python console
# new_constraints, number_of_questions = al.ask_oracle(constraints, pairwise_queries, al.oracles.simple_human_oracle)

# updates FIECE-EM to take into account new constraints
clf.update_constraints(new_constraints, X)
# fits it again
clf.fit(X)

For convenience, we provide the method ask_with_strategy, as follows:

# create a perfect oracle, which knows every object's label
oracle = al.oracles.make_oracle_from_labels(y)

# performs queries about 5 objects
new_constraints, number_of_questions = al.ask_with_strategy(clf, constraints, X, oracle, al.strategies.best_feasible_classification_uncertainty, 5)

# updates FIECE-EM to take into account new constraints
clf.update_constraints(new_constraints, X)
# fits it again
clf.fit(X)

Observation about LUC

When using LUC, the answer to each query influences which object will be the next one queried. Therefore, a different function should be used:

oracle = al.oracles.make_oracle_from_labels(y)
# labels 5 objects with LUC
new_constraints, number_of_questions = al.luc_custom_ask(clf, constraints, X, oracle, 5)

# updates FIECE-EM to take into account new constraints
clf.update_constraints(new_constraints, X)
# fits it again
clf.fit(X)

Documentation