aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGertjan van den Burg <gertjanvandenburg@gmail.com>2019-05-30 18:39:05 +0100
committerGertjan van den Burg <gertjanvandenburg@gmail.com>2019-05-30 18:39:05 +0100
commit47116a4682edb1f22d00da06802cc3eff40bf5bd (patch)
tree1f8bcbb1b86e112eefed5a6dd4fe0ea1541183d7
parentMerge branch 'master' of github.com:GjjvdBurg/PyGenSVM (diff)
downloadpygensvm-47116a4682edb1f22d00da06802cc3eff40bf5bd.tar.gz
pygensvm-47116a4682edb1f22d00da06802cc3eff40bf5bd.zip
Update documentation
-rw-r--r--Makefile4
-rw-r--r--docs/auto_functions.rst47
-rw-r--r--docs/cls_gensvm.rst33
-rw-r--r--docs/cls_gridsearch.rst28
-rw-r--r--docs/generate_autodocs.py92
-rw-r--r--poetry.lock250
-rw-r--r--pyproject.toml19
7 files changed, 419 insertions, 54 deletions
diff --git a/Makefile b/Makefile
index 134fcbe..7dc84b5 100644
--- a/Makefile
+++ b/Makefile
@@ -62,5 +62,5 @@ dist2: ## Make Python 2 source distribution
python2 setup.py sdist
docs: doc
-doc: install ## Build documentation with Sphinx
- $(MAKE) -C $(DOC_DIR) html
+doc: ## Build documentation with Sphinx
+ poetry run $(MAKE) -C $(DOC_DIR) html
diff --git a/docs/auto_functions.rst b/docs/auto_functions.rst
index 3ba1fff..2a6596f 100644
--- a/docs/auto_functions.rst
+++ b/docs/auto_functions.rst
@@ -1,9 +1,52 @@
-.. py:function:: load_default_grid()
+.. py:function:: load_grid_tiny()
:noindex:
:module: gensvm.gridsearch
- Load the default parameter grid for GenSVM
+ Load a tiny parameter grid for the GenSVM grid search
+
+ This function returns a parameter grid to use in the GenSVM grid search.
+ This grid was obtained by analyzing the experiments done for the GenSVM
+ paper and selecting the configurations that achieve accuracy within the
+ 95th percentile on over 90% of the datasets. It is a good start for a
+ parameter search with a reasonably high chance of achieving good
+ performance on most datasets.
+
+ Note that this grid is only tested to work well in combination with the
+ linear kernel.
+
+ :returns: **pg** -- List of 10 parameter configurations that are likely to perform
+ reasonably well.
+ :rtype: list
+
+
+.. py:function:: load_grid_small()
+ :noindex:
+ :module: gensvm.gridsearch
+
+ Load a small parameter grid for GenSVM
+
+ This function loads a default parameter grid to use for the #' GenSVM
+ gridsearch. It contains all possible combinations of the following #'
+ parameter sets::
+
+ pg = {
+ 'p': [1.0, 1.5, 2.0],
+ 'lmd': [1e-8, 1e-6, 1e-4, 1e-2, 1],
+ 'kappa': [-0.9, 0.5, 5.0],
+ 'weights': ['unit', 'group'],
+ }
+
+ :returns: **pg** -- Mapping from parameters to lists of values for those parameters. To be
+ used as input for the :class:`.GenSVMGridSearchCV` class.
+ :rtype: dict
+
+
+.. py:function:: load_grid_full()
+ :noindex:
+ :module: gensvm.gridsearch
+
+ Load the full parameter grid for GenSVM
This is the parameter grid used in the GenSVM paper to run the grid search
experiments. It uses a large grid for the ``lmd`` regularization parameter
diff --git a/docs/cls_gensvm.rst b/docs/cls_gensvm.rst
index fc19bf4..b4bc9a7 100644
--- a/docs/cls_gensvm.rst
+++ b/docs/cls_gensvm.rst
@@ -1,5 +1,5 @@
-.. py:class:: GenSVM(p=1.0, lmd=1e-05, kappa=0.0, epsilon=1e-06, weights='unit', kernel='linear', gamma='auto', coef=0.0, degree=2.0, kernel_eigen_cutoff=1e-08, verbose=0, random_state=None, max_iter=100000000.0)
+.. py:class:: GenSVM(p=1.0, lmd=1e-05, kappa=0.0, epsilon=1e-06, weights='unit', kernel='linear', gamma='auto', coef=1.0, degree=2.0, kernel_eigen_cutoff=1e-08, verbose=0, random_state=None, max_iter=100000000.0)
:noindex:
:module: gensvm.core
@@ -21,6 +21,10 @@
:type kappa: float, optional (default=0.0)
:param weights: Type of sample weights to use. Options are 'unit' for unit weights and
'group' for group size correction weights (equation 4 in the paper).
+
+ It is also possible to provide an explicit vector of sample weights
+ through the :func:`~GenSVM.fit` method. If so, it will override the
+ setting provided here.
:type weights: string, optional (default='unit')
:param kernel: Specify the kernel type to use in the classifier. It must be one of
'linear', 'poly', 'rbf', or 'sigmoid'.
@@ -31,7 +35,7 @@
:type gamma: float, optional (default='auto')
:param coef: Kernel parameter for the poly and sigmoid kernel. See `Kernels in
GenSVM <gensvm_kernels_>`_ for the exact implementation of the kernels.
- :type coef: float, optional (default=0.0)
+ :type coef: float, optional (default=1.0)
:param degree: Kernel parameter for the poly kernel. See `Kernels in GenSVM
<gensvm_kernels_>`_ for the exact implementation of the kernels.
:type degree: float, optional (default=2.0)
@@ -42,6 +46,10 @@
:type kernel_eigen_cutoff: float, optional (default=1e-8)
:param verbose: Enable verbose output
:type verbose: int, (default=0)
+ :param random_state: The seed for the random number generation used for initialization where
+ necessary. See the documentation of
+ ``sklearn.utils.check_random_state`` for more info.
+ :type random_state: None, int, instance of RandomState
:param max_iter: The maximum number of iterations to be run.
:type max_iter: int, (default=1e8)
@@ -65,6 +73,10 @@
*int* -- The number of support vectors that were found
+ .. attribute:: SVs_
+
+ *array, shape = [n_observations, ]* -- Index vector that marks the support vectors (1 = SV, 0 = no SV)
+
.. seealso::
:class:`.GenSVMGridSearchCV`
@@ -75,7 +87,7 @@
- .. py:method:: GenSVM.fit(X, y, seed_V=None)
+ .. py:method:: GenSVM.fit(X, y, sample_weight=None, seed_V=None)
:noindex:
:module: gensvm.core
@@ -88,6 +100,10 @@
:type X: array, shape = (n_observations, n_features)
:param y: The label vector, labels can be numbers or strings.
:type y: array, shape = (n_observations, )
+ :param sample_weight: Array of weights that are assigned to individual samples. If not
+ provided, then the weight specification in the constructor is used
+ ('unit' or 'group').
+ :type sample_weight: array, shape = (n_observations, )
:param seed_V: Seed coefficient array to use as a warm start for the optimization.
It can for instance be the :attr:`combined_coef_
<.GenSVM.combined_coef_>` attribute of a different GenSVM model.
@@ -106,15 +122,18 @@
:rtype: object
- .. py:method:: GenSVM.predict(X)
+ .. py:method:: GenSVM.predict(X, trainX=None)
:noindex:
:module: gensvm.core
Predict the class labels on the given data
- :param X:
- :type X: array, shape = [n_samples, n_features]
+ :param X: Data for which to predict the labels
+ :type X: array, shape = [n_test_samples, n_features]
+ :param trainX: Only for nonlinear prediction with kernels: the training data used
+ to train the model.
+ :type trainX: array, shape = [n_train_samples, n_features]
- :returns: **y_pred**
+ :returns: **y_pred** -- Predicted class labels of the data in X.
:rtype: array, shape = (n_samples, )
diff --git a/docs/cls_gridsearch.rst b/docs/cls_gridsearch.rst
index 8708123..6a2c05e 100644
--- a/docs/cls_gridsearch.rst
+++ b/docs/cls_gridsearch.rst
@@ -1,5 +1,5 @@
-.. py:class:: GenSVMGridSearchCV(param_grid, scoring=None, iid=True, cv=None, refit=True, verbose=0, return_train_score=True)
+.. py:class:: GenSVMGridSearchCV(param_grid='tiny', scoring=None, iid=True, cv=None, refit=True, verbose=0, return_train_score=True)
:noindex:
:module: gensvm.gridsearch
@@ -17,10 +17,15 @@
was needed to benefit from the fast low-level C implementation of grid
search in the GenSVM library.
- :param param_grid: Dictionary of parameter names (strings) as keys and lists of parameter
- settings to evaluate as values, or a list of such dicts. The GenSVM
- model will be evaluated at all combinations of the parameters.
- :type param_grid: dict or list of dicts
+ :param param_grid: If a string, it must be either 'tiny', 'small', or 'full' to load the
+ predefined parameter grids (see the functions :func:`load_grid_tiny`,
+ :func:`load_grid_small`, and :func:`load_grid_full`).
+
+ Otherwise, a dictionary of parameter names (strings) as keys and lists
+ of parameter settings to evaluate as values, or a list of such dicts.
+ The GenSVM model will be evaluated at all combinations of the
+ parameters.
+ :type param_grid: string, dict, or list of dicts
:param scoring: A single string (see :ref:`scoring_parameter`) or a callable (see
:ref:`scoring`) to evaluate the predictions on the test set.
@@ -40,7 +45,7 @@
:param cv: Determines the cross-validation splitting strategy. Possible inputs for
cv are:
- - None, to use the default 3-fold cross validation,
+ - None, to use the default 5-fold cross validation,
- integer, to specify the number of folds in a `(Stratified)KFold`,
- An object to be used as a cross-validation generator.
- An iterable yielding train, test splits.
@@ -51,6 +56,12 @@
Refer to the `scikit-learn User Guide on cross validation`_ for the
various strategies that can be used here.
+
+ NOTE: At the moment, the ShuffleSplit and StratifiedShuffleSplit are
+ not supported in this class. If you need these, you can use the GenSVM
+ classifier directly with the GridSearchCV object from scikit-learn.
+ (these methods require significant changes in the low-level library
+ before they can be supported).
:type cv: int, cross-validation generator or an iterable, optional
:param refit: Refit the GenSVM estimator with the best found parameters on the whole
dataset.
@@ -240,7 +251,7 @@
:rtype: object
- .. py:method:: GenSVMGridSearchCV.predict(X)
+ .. py:method:: GenSVMGridSearchCV.predict(X, trainX=None)
:noindex:
:module: gensvm.gridsearch
@@ -249,6 +260,9 @@
:param X: Test data, where n_samples is the number of observations and
n_features is the number of features.
:type X: array-like, shape = (n_samples, n_features)
+ :param trainX: Only for nonlinear prediction with kernels: the training data used
+ to train the model.
+ :type trainX: array, shape = [n_train_samples, n_features]
:returns: **y_pred** -- Predicted class labels of the data in X.
:rtype: array-like, shape = (n_samples, )
diff --git a/docs/generate_autodocs.py b/docs/generate_autodocs.py
index b2c9fb6..1aa8f7d 100644
--- a/docs/generate_autodocs.py
+++ b/docs/generate_autodocs.py
@@ -15,52 +15,64 @@ import os
from docutils.statemachine import StringList, ViewList
-from sphinx.ext.autodoc import (AutoDirective, ClassDocumenter, Options,
- FunctionDocumenter)
+from sphinx.ext.autodoc import (
+ AutoDirective,
+ ClassDocumenter,
+ Options,
+ FunctionDocumenter,
+)
from sphinx.application import Sphinx
from sphinx.environment import BuildEnvironment
-BASE_DIR = '/home/gertjan/Dropbox/phd/research/msvm/python/start_here/'
-DOCDIR = os.path.join(BASE_DIR, 'gensvm', 'docs')
+HERE_DIR = os.path.dirname(os.path.abspath(__file__))
+BASE_DIR = os.path.abspath(os.path.join(HERE_DIR, "..", ".."))
-CLASSES = [
- 'GenSVMGridSearchCV',
- 'GenSVM'
- ]
+DOCDIR = os.path.join(BASE_DIR, "gensvm", "docs")
-FUNCTIONS = [
- 'load_default_grid'
- ]
+CLASSES = ["GenSVMGridSearchCV", "GenSVM"]
+
+FUNCTIONS = ["load_grid_tiny", "load_grid_small", "load_grid_full"]
FULL_NAMES = {
- 'GenSVM': 'gensvm.core.GenSVM',
- 'GenSVMGridSearchCV': 'gensvm.gridsearch.GenSVMGridSearchCV',
- 'load_default_grid': 'gensvm.gridsearch.load_default_grid'
- }
+ "GenSVM": "gensvm.core.GenSVM",
+ "GenSVMGridSearchCV": "gensvm.gridsearch.GenSVMGridSearchCV",
+ "load_grid_tiny": "gensvm.gridsearch.load_grid_tiny",
+ "load_grid_small": "gensvm.gridsearch.load_grid_small",
+ "load_grid_full": "gensvm.gridsearch.load_grid_full",
+}
OUTPUT_FILES = {
- 'GenSVMGridSearchCV': os.path.join(DOCDIR, 'cls_gridsearch.rst'),
- 'GenSVM': os.path.join(DOCDIR, 'cls_gensvm.rst'),
- 'load_default_grid': os.path.join(DOCDIR, 'auto_functions.rst')
- }
+ "GenSVMGridSearchCV": os.path.join(DOCDIR, "cls_gridsearch.rst"),
+ "GenSVM": os.path.join(DOCDIR, "cls_gensvm.rst"),
+ "load_grid_tiny": os.path.join(DOCDIR, "auto_functions.rst"),
+ "load_grid_small": os.path.join(DOCDIR, "auto_functions.rst"),
+ "load_grid_full": os.path.join(DOCDIR, "auto_functions.rst"),
+}
def load_app():
srcdir = DOCDIR[:]
confdir = DOCDIR[:]
- outdir = os.path.join(BASE_DIR, 'gensvm_docs', 'html')
- doctreedir = os.path.join(BASE_DIR, 'gensvm_docs', 'doctrees')
- buildername = 'html'
+ outdir = os.path.join(BASE_DIR, "gensvm_docs", "html")
+ doctreedir = os.path.join(BASE_DIR, "gensvm_docs", "doctrees")
+ buildername = "html"
app = Sphinx(srcdir, confdir, outdir, doctreedir, buildername)
return app
def generate_class_autodoc(app, cls):
- ad = AutoDirective(name='autoclass', arguments=[FULL_NAMES[cls]],
- options={'noindex': True}, content=StringList([], items=[]),
- lineno=0, content_offset=1, block_text='', state=None,
- state_machine=None)
+ ad = AutoDirective(
+ name="autoclass",
+ arguments=[FULL_NAMES[cls]],
+ options={"noindex": True},
+ content=StringList([], items=[]),
+ lineno=0,
+ content_offset=1,
+ block_text="",
+ state=None,
+ state_machine=None,
+ )
ad.env = BuildEnvironment(app)
ad.genopt = Options(noindex=True)
@@ -70,16 +82,23 @@ def generate_class_autodoc(app, cls):
documenter = ClassDocumenter(ad, ad.arguments[0])
documenter.generate(all_members=True)
- with open(OUTPUT_FILES[cls], 'w') as fid:
+ with open(OUTPUT_FILES[cls], "w") as fid:
for line in ad.result:
- fid.write(line + '\n')
+ fid.write(line + "\n")
def generate_func_autodoc(app, func):
- ad = AutoDirective(name='autofunc', arguments=[FULL_NAMES[func]],
- options={'noindex': True}, content=StringList([], items=[]),
- lineno=0, content_offset=1, block_text='', state=None,
- state_machine=None)
+ ad = AutoDirective(
+ name="autofunc",
+ arguments=[FULL_NAMES[func]],
+ options={"noindex": True},
+ content=StringList([], items=[]),
+ lineno=0,
+ content_offset=1,
+ block_text="",
+ state=None,
+ state_machine=None,
+ )
ad.env = BuildEnvironment(app)
ad.genopt = Options(noindex=True)
@@ -89,15 +108,16 @@ def generate_func_autodoc(app, func):
documenter = FunctionDocumenter(ad, ad.arguments[0])
documenter.generate(all_members=True)
- with open(OUTPUT_FILES[func], 'a') as fid:
+ with open(OUTPUT_FILES[func], "a") as fid:
for line in ad.result:
- fid.write(line + '\n')
+ fid.write(line + "\n")
def main():
for of in OUTPUT_FILES:
fname = OUTPUT_FILES[of]
- os.unlink(fname)
+ if os.path.exists(fname):
+ os.unlink(fname)
app = load_app()
for cls in CLASSES:
generate_class_autodoc(app, cls)
@@ -105,5 +125,5 @@ def main():
generate_func_autodoc(app, func)
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/poetry.lock b/poetry.lock
new file mode 100644
index 0000000..91337ff
--- /dev/null
+++ b/poetry.lock
@@ -0,0 +1,250 @@
+[[package]]
+category = "dev"
+description = "A configurable sidebar-enabled Sphinx theme"
+name = "alabaster"
+optional = false
+python-versions = "*"
+version = "0.7.12"
+
+[[package]]
+category = "dev"
+description = "Internationalization utilities"
+name = "babel"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "2.7.0"
+
+[package.dependencies]
+pytz = ">=2015.7"
+
+[[package]]
+category = "dev"
+description = "Python package for providing Mozilla's CA Bundle."
+name = "certifi"
+optional = false
+python-versions = "*"
+version = "2019.3.9"
+
+[[package]]
+category = "dev"
+description = "Universal encoding detector for Python 2 and 3"
+name = "chardet"
+optional = false
+python-versions = "*"
+version = "3.0.4"
+
+[[package]]
+category = "dev"
+description = "Cross-platform colored terminal text."
+marker = "sys_platform == \"win32\""
+name = "colorama"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "0.4.1"
+
+[[package]]
+category = "dev"
+description = "Docutils -- Python Documentation Utilities"
+name = "docutils"
+optional = false
+python-versions = "*"
+version = "0.14"
+
+[[package]]
+category = "dev"
+description = "Internationalized Domain Names in Applications (IDNA)"
+name = "idna"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "2.8"
+
+[[package]]
+category = "dev"
+description = "Getting image size from png/jpeg/jpeg2000/gif file"
+name = "imagesize"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.1.0"
+
+[[package]]
+category = "dev"
+description = "A small but fast and easy to use stand-alone template engine written in pure python."
+name = "jinja2"
+optional = false
+python-versions = "*"
+version = "2.10.1"
+
+[package.dependencies]
+MarkupSafe = ">=0.23"
+
+[[package]]
+category = "main"
+description = "Lightweight pipelining: using Python functions as pipeline jobs."
+name = "joblib"
+optional = false
+python-versions = "*"
+version = "0.13.2"
+
+[[package]]
+category = "dev"
+description = "Safely add untrusted strings to HTML/XML markup."
+name = "markupsafe"
+optional = false
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
+version = "1.1.1"
+
+[[package]]
+category = "main"
+description = "NumPy is the fundamental package for array computing with Python."
+name = "numpy"
+optional = false
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
+version = "1.16.4"
+
+[[package]]
+category = "dev"
+description = "Pygments is a syntax highlighting package written in Python."
+name = "pygments"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "2.4.2"
+
+[[package]]
+category = "dev"
+description = "World timezone definitions, modern and historical"
+name = "pytz"
+optional = false
+python-versions = "*"
+version = "2019.1"
+
+[[package]]
+category = "dev"
+description = "Python HTTP for Humans."
+name = "requests"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "2.22.0"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+chardet = ">=3.0.2,<3.1.0"
+idna = ">=2.5,<2.9"
+urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26"
+
+[[package]]
+category = "main"
+description = "A set of python modules for machine learning and data mining"
+name = "scikit-learn"
+optional = false
+python-versions = ">=3.5"
+version = "0.21.2"
+
+[package.dependencies]
+joblib = ">=0.11"
+numpy = ">=1.11.0"
+scipy = ">=0.17.0"
+
+[[package]]
+category = "main"
+description = "SciPy: Scientific Library for Python"
+name = "scipy"
+optional = false
+python-versions = ">=3.5"
+version = "1.3.0"
+
+[package.dependencies]
+numpy = ">=1.13.3"
+
+[[package]]
+category = "dev"
+description = "Python 2 and 3 compatibility utilities"
+name = "six"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*"
+version = "1.12.0"
+
+[[package]]
+category = "dev"
+description = "This package provides 16 stemmer algorithms (15 + Poerter English stemmer) generated from Snowball algorithms."
+name = "snowballstemmer"
+optional = false
+python-versions = "*"
+version = "1.2.1"
+
+[[package]]
+category = "dev"
+description = "Python documentation generator"
+name = "sphinx"
+optional = false
+python-versions = "*"
+version = "1.6.5"
+
+[package.dependencies]
+Jinja2 = ">=2.3"
+Pygments = ">=2.0"
+alabaster = ">=0.7,<0.8"
+babel = ">=1.3,<2.0 || >2.0"
+colorama = ">=0.3.5"
+docutils = ">=0.11"
+imagesize = "*"
+requests = ">=2.0.0"
+setuptools = "*"
+six = ">=1.5"
+snowballstemmer = ">=1.1"
+sphinxcontrib-websupport = "*"
+
+[[package]]
+category = "dev"
+description = "Read the Docs theme for Sphinx"
+name = "sphinx-rtd-theme"
+optional = false
+python-versions = "*"
+version = "0.4.3"
+
+[package.dependencies]
+sphinx = "*"
+
+[[package]]
+category = "dev"
+description = "Sphinx API for Web Apps"
+name = "sphinxcontrib-websupport"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.1.2"
+
+[[package]]
+category = "dev"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+name = "urllib3"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4"
+version = "1.25.3"
+
+[metadata]
+content-hash = "28c38fca95c1a9663d1048eb9cffd5dcc8c73d85e4c79b0649aa7e550bdf0a09"
+python-versions = "^3.7"
+
+[metadata.hashes]
+alabaster = ["446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", "a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"]
+babel = ["af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab", "e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28"]
+certifi = ["59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", "b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"]
+chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
+colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"]
+docutils = ["02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", "51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", "7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"]
+idna = ["c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"]
+imagesize = ["3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8", "f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5"]
+jinja2 = ["065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", "14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"]
+joblib = ["21e0c34a69ad7fde4f2b1f3402290e9ec46f545f15f1541c582edfe05d87b63a", "315d6b19643ec4afd4c41c671f9f2d65ea9d787da093487a81ead7b0bac94524"]
+markupsafe = ["00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", "09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", "62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", "88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", "98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", "ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", "b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", "ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"]
+numpy = ["0778076e764e146d3078b17c24c4d89e0ecd4ac5401beff8e1c87879043a0633", "141c7102f20abe6cf0d54c4ced8d565b86df4d3077ba2343b61a6db996cefec7", "14270a1ee8917d11e7753fb54fc7ffd1934f4d529235beec0b275e2ccf00333b", "27e11c7a8ec9d5838bc59f809bfa86efc8a4fd02e58960fa9c49d998e14332d5", "2a04dda79606f3d2f760384c38ccd3d5b9bb79d4c8126b67aff5eb09a253763e", "3c26010c1b51e1224a3ca6b8df807de6e95128b0908c7e34f190e7775455b0ca", "52c40f1a4262c896420c6ea1c6fda62cf67070e3947e3307f5562bd783a90336", "6e4f8d9e8aa79321657079b9ac03f3cf3fd067bf31c1cca4f56d49543f4356a5", "7242be12a58fec245ee9734e625964b97cf7e3f2f7d016603f9e56660ce479c7", "7dc253b542bfd4b4eb88d9dbae4ca079e7bf2e2afd819ee18891a43db66c60c7", "94f5bd885f67bbb25c82d80184abbf7ce4f6c3c3a41fbaa4182f034bba803e69", "a89e188daa119ffa0d03ce5123dee3f8ffd5115c896c2a9d4f0dbb3d8b95bfa3", "ad3399da9b0ca36e2f24de72f67ab2854a62e623274607e37e0ce5f5d5fa9166", "b0348be89275fd1d4c44ffa39530c41a21062f52299b1e3ee7d1c61f060044b8", "b5554368e4ede1856121b0dfa35ce71768102e4aa55e526cb8de7f374ff78722", "cbddc56b2502d3f87fda4f98d948eb5b11f36ff3902e17cb6cc44727f2200525", "d79f18f41751725c56eceab2a886f021d70fd70a6188fd386e29a045945ffc10", "dc2ca26a19ab32dc475dbad9dfe723d3a64c835f4c23f625c2b6566ca32b9f29", "dd9bcd4f294eb0633bb33d1a74febdd2b9018b8b8ed325f861fffcd2c7660bb8", "e8baab1bc7c9152715844f1faca6744f2416929de10d7639ed49555a85549f52", "ec31fe12668af687b99acf1567399632a7c47b0e17cfb9ae47c098644ef36797", "f12b4f7e2d8f9da3141564e6737d79016fe5336cc92de6814eba579744f65b0a", "f58ac38d5ca045a377b3b377c84df8175ab992c970a53332fa8ac2373df44ff7"]
+pygments = ["71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", "881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297"]
+pytz = ["303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda", "d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"]
+requests = ["11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", "9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"]
+scikit-learn = ["051c53f9e900b0e9eccff2391f5317d1673d72e842bcbcd3e5d0b132459086ed", "0aafc312a55ebf58073151b9308761a5fcfa45b7f7730cea4b1f066f824c72db", "185d88ee4955cd68d7ff57356d1dd99cfc2de4b6aa5e5d679cafbc9df54716ff", "195465c39daded4f3ef8759291ffde81365486d4293e63dd9e32de0f569ecbbf", "4a6398500d035a4402476a2e3ae9f65a7a3f1b366ec6a7f6dd45c289f72dc954", "56f14e98632fb9237e7d005c6d8e346d01fa67f7b92f5f5d57a0bd06c741f9f6", "77092513dd780e12affde46a6394b52947db3fc00cf1d8c1c8eede52b37591d1", "7d2cdfe16b1ae6f9a1760b69be27c2004a84fc362984f930df135c847c47b765", "82c3450fc375f27e3529fa05fec627c9fc75915e05fcd55de43f193b3aa907af", "a5fba00d9037b62b0e0906f64efe9e4a754e556bc091cc12f84bc81655b4a414", "acba6bf5928e415b6296799a7aa069b66254c9440bce88ed2e5915865a317093", "b474f00d2533f18761fb17fb0950b27e72baf0796176247b5a7cf0ee369790ee", "ca45e0def97f73a828cee417174fafa0ab35a41f8bdca4424120a29c5589c548", "f09e544a6756afbd9d31e1d8ddfde5a2c9c17f6d4274104c988fceb611e2d5c5", "f979bb85cbfd9ed4d54709d86ab8893b316726abd1c9ab04abe7e6414b71b753", "fb4c7a2294447515fffec33c1f5eedbe942e9be56edb8c6619607e7882531d40"]
+scipy = ["03b1e0775edbe6a4c64effb05fff2ce1429b76d29d754aa5ee2d848b60033351", "09d008237baabf52a5d4f5a6fcf9b3c03408f3f61a69c404472a16861a73917e", "10325f0ffac2400b1ec09537b7e403419dcd25d9fee602a44e8a32119af9079e", "1db9f964ed9c52dc5bd6127f0dd90ac89791daa690a5665cc01eae185912e1ba", "409846be9d6bdcbd78b9e5afe2f64b2da5a923dd7c1cd0615ce589489533fdbb", "4907040f62b91c2e170359c3d36c000af783f0fa1516a83d6c1517cde0af5340", "6c0543f2fdd38dee631fb023c0f31c284a532d205590b393d72009c14847f5b1", "826b9f5fbb7f908a13aa1efd4b7321e36992f5868d5d8311c7b40cf9b11ca0e7", "a7695a378c2ce402405ea37b12c7a338a8755e081869bd6b95858893ceb617ae", "a84c31e8409b420c3ca57fd30c7589378d6fdc8d155d866a7f8e6e80dec6fd06", "adadeeae5500de0da2b9e8dd478520d0a9945b577b2198f2462555e68f58e7ef", "b283a76a83fe463c9587a2c88003f800e08c3929dfbeba833b78260f9c209785", "c19a7389ab3cd712058a8c3c9ffd8d27a57f3d84b9c91a931f542682bb3d269d", "c3bb4bd2aca82fb498247deeac12265921fe231502a6bc6edea3ee7fe6c40a7a", "c5ea60ece0c0c1c849025bfc541b60a6751b491b6f11dd9ef37ab5b8c9041921", "db61a640ca20f237317d27bc658c1fc54c7581ff7f6502d112922dc285bdabee"]
+six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"]
+snowballstemmer = ["919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128", "9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89"]
+sphinx = ["c6de5dbdbb7a0d7d2757f4389cc00e8f6eb3c49e1772378967a12cfcf2cfe098", "fdf77f4f30d84a314c797d67fe7d1b46665e6c48a25699d7bf0610e05a2221d4"]
+sphinx-rtd-theme = ["00cf895504a7895ee433807c62094cf1e95f065843bf3acd17037c3e9a2becd4", "728607e34d60456d736cc7991fd236afb828b21b82f956c5ea75f94c8414040a"]
+sphinxcontrib-websupport = ["1501befb0fdf1d1c29a800fdbf4ef5dc5369377300ddbdd16d2cd40e54c6eefc", "e02f717baf02d0b6c3dd62cf81232ffca4c9d5c331e03766982e3ff9f1d2bc3f"]
+urllib3 = ["b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", "dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"]
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..1668a61
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,19 @@
+[tool.poetry]
+name = "gensvm"
+version = "0.2.4"
+description = "Python package for the GenSVM classifier"
+authors = ["Gertjan van den Burg <gertjanvandenburg@gmail.com>"]
+license = "GPL-2.0+"
+
+[tool.poetry.dependencies]
+python = "^3.7"
+scikit-learn = "^0.21.2"
+numpy = "^1.16"
+
+[tool.poetry.dev-dependencies]
+Sphinx = "=1.6.5"
+sphinx_rtd_theme = "^0.4.3"
+
+[build-system]
+requires = ["poetry>=0.12"]
+build-backend = "poetry.masonry.api"