Skip to content

Commit

Permalink
Created pypi package
Browse files Browse the repository at this point in the history
  • Loading branch information
makgyver committed Mar 1, 2019
1 parent b14b7e3 commit 279fbaf
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 117 deletions.
18 changes: 9 additions & 9 deletions PRL/prl.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import math
import numpy as np

from genF import *
from genP import *
from .genF import *
from .genP import *

import logging

Expand Down Expand Up @@ -124,7 +124,7 @@ def fit(self, iterations=1000, verbose=False):
logging.info("Starting training of %s" %self)
logging.info("Matrix game initialization...")

for j in xrange(self.n_cols):
for j in range(self.n_cols):
(p, f), rp = self._get_new_col()
self.feat_list.append((p, f))
self.feat_set.add((p, f))
Expand All @@ -133,12 +133,12 @@ def fit(self, iterations=1000, verbose=False):
self.M[:,j] = x

#iterative updates
for t in xrange(iterations):
for t in range(iterations):
if verbose: logging.info("PRL iteration %d/%d" %(t+1, iterations))
(P, Q, V) = self.solver.solve(self.M, self.n_rows, self.n_cols)
if verbose: logging.info("Value of the game (current margin): %.6f" %V)
if (t+1 < iterations):
for j in xrange(self.n_cols):
for j in range(self.n_cols):
if Q[j] <= 0:
(p, f), rp = self._get_new_col()
self.feat_set.remove(self.feat_list[j])
Expand Down Expand Up @@ -178,7 +178,7 @@ def fit(self, iterations=1000, verbose=False):
logging.info("Starting training of %s" %self)
logging.info("Matrix game initialization...")

for j in xrange(self.n_cols):
for j in range(self.n_cols):
(p, f), rp = self._get_new_col()
self.feat_list.append((p, f))
self.feat_set.add((p, f))
Expand All @@ -187,12 +187,12 @@ def fit(self, iterations=1000, verbose=False):
self.M[:,j] = x

#iterative updates
for t in xrange(iterations):
for t in range(iterations):
if verbose: logging.info("PRL_ext iteration %d/%d" %(t+1, iterations))
(P, Q, V) = self.solver.solve(self.M, self.n_rows, self.M.shape[1])
if verbose: logging.info("Value of the game (current margin): %.6f" %V)
if (t+1 < iterations):
for j in xrange(self.M.shape[1]):
for j in range(self.M.shape[1]):
if Q[j] <= 0:
(p, f), rp = self._get_new_col()
self.feat_set.remove(self.feat_list[j])
Expand All @@ -205,7 +205,7 @@ def fit(self, iterations=1000, verbose=False):
n_zeros = np.sum(Q <= 0)
if n_zeros < self.n_cols:
M_r = np.zeros((self.n_rows, self.n_cols-n_zeros))
for j in xrange(self.n_cols-n_zeros):
for j in range(self.n_cols-n_zeros):
(p, f), rp = self._get_new_col()
self.feat_list.append((p, f))
self.feat_set.add((p, f))
Expand Down
105 changes: 0 additions & 105 deletions PRL/run_prl.py

This file was deleted.

4 changes: 2 additions & 2 deletions PRL/solvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def solve(self, M, n_rows, n_cols):

Sq = M[i_min,:].copy()

for t in xrange(self.iterations):
for t in range(self.iterations):
j_max = np.argmax(Sq / (t+1))
Q[j_max] += 1.
Sp += M[:,j_max]
Expand Down Expand Up @@ -137,7 +137,7 @@ def solve(self, M, n_rows, n_cols):
Q = np.zeros(n_cols)
V = 0.0

for t in xrange(self.iterations):
for t in range(self.iterations):
PP += P
q_eval = np.zeros(ncols)
for j in range(n_cols):
Expand Down
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ PRL has been presented @ AAAI 2019; the reference paper is:
M. Polato and F. Aiolli, "[Interpretable preference learning: a game theoretic framework for large margin on-line feature and rule learning]", AAAI 2019.


## Install PRL with Pypi (Python 3)
PRL is available in the PyPi repository and it can be installed with
```sh
pip3 install prl
```

and then it can be imported in python with

```python
import prl
```

## How to use the PRL module
It is possible to run PRL using the provided python script `run_prl.py`.

Expand Down Expand Up @@ -72,7 +84,7 @@ which runs PRL using 80% of the dataset as training set and the rest as test set
The evaluation is computed in terms of *accuracy*, *balanced accuracy* and it also shows the *confusion matrix*.

### Version
1.0b
0.94b

### Requirements
PRL requires the following python modules:
Expand Down
7 changes: 7 additions & 0 deletions prl/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .genP import *
from .genF import *
from .evaluation import *
from .prl import *
from .solvers import *

__all__ = ["prl", "genF", "genP", "evaluation", "solvers"]
106 changes: 106 additions & 0 deletions run_prl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import sys
import json
import numpy as np
from optparse import OptionParser

from sklearn.datasets import load_svmlight_file
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler

from prl.prl import *
from prl.genF import *
from prl.genP import *
from prl.evaluation import *
from prl.solvers import *

#LOGGER SETUP
import logging
logging.basicConfig(level=logging.INFO,
format="[%(asctime)s] %(filename)s - %(message)s",
datefmt='%H:%M:%S-%d%m%y')

def manage_options():
"""Manages the options of the command line.
:returns: a dictionary containg the options and their associated values
:rtype: dictionary
"""
parser = OptionParser(usage="usage: %prog [options] dataset_file", version="%prog 1.0")

parser.add_option("-s", "--seed", dest="seed", default=42, help="Pseudo-random seed for replicability", type="int")
parser.add_option("-t", "--test_size", dest="test_size", default=.3, help="Test set size in percentage [0,1]")
parser.add_option("-c", "--config_file", dest="config_file", default="../config/config.json", help="Configuration file")
parser.add_option("-v", "--verbose", dest="verbose", default=False, help="Verbose output", action="store_true")

(options, args) = parser.parse_args()
if len(args) == 0:
parser.error("Wrong arguments")

out_dict = vars(options)
out_dict["dataset"] = args[0]
return out_dict


#INPUT
options = manage_options()
logging.info("Options: %s" %options)
#

#LOADING DATA
X, y = load_svmlight_file(options["dataset"])
X, y = X.toarray(), y.astype(int)

# maps labels into the range 0,..,m-1
unique_y = np.unique(y)
dim = len(unique_y)
map_y = dict(zip(unique_y, range(len(unique_y))))
y = np.array([map_y[i] for i in y])

#TRAINING-TEST SET SPLIT
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=options["test_size"], random_state=options["seed"])

scaler = MinMaxScaler()
scaler.fit(Xtr)
Xtr = scaler.transform(Xtr)
Xte = scaler.transform(Xte)
#

#LOAD CONFIGURATION FILE
with open(options['config_file'], "r") as f:
data = json.load(f)
logging.info("Configuration: %s" %data)

genf_class = getattr(__import__("prl.genF"), data['feat_gen'])
gen_feat = genf_class(Xtr, *data['feat_gen_params'])

if data["pref_generator"] == "micro":
gen_pref_training = GenMicroP(Xtr, ytr)
gen_pref_test = GenMicroP(Xte, yte)
else: #if not micro
gen_pref_training = GenMacroP(Xtr, ytr)
gen_pref_test = GenMacroP(Xte, yte)

budget = data["columns_budget"]
iterations = data["iterations"]

solver_class = getattr(__import__("prl.solvers"), data['solver'])
solver = solver_class(*data['solver_params'])

prl_alg = getattr(__import__("prl.prl"), data['algorithm'])
#

#TRAINING PRL
prl = prl_alg(gen_pref_training, gen_feat, dim, budget, solver)
prl.fit(iterations, options["verbose"])
#

#EVALUATION
acc, conf = accuracy(prl, gen_pref_test)
bacc, _ = balanced_accuracy(prl, gen_pref_test, conf)

logging.info("Accuracy: %.2f" %acc)
logging.info("Balanced accuracy: %.2f" %bacc)
logging.info("Confusion matrix:\n%s" %conf)
#

logging.shutdown()
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[metadata]
description-file = README.md
27 changes: 27 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from setuptools import setup, find_packages
#from distutils.core import setup

setup(
name = 'prl',
packages = find_packages(exclude=['build', '_docs', 'templates']),
version = '0.94b',
install_requires=[
"numpy",
"scipy",
"cvxopt",
"sklearn"
],
license = "MIT",
description = '[P]reference and [R]ule [L]earning algorithm implementation',
author = 'Mirko Polato',
author_email = '[email protected]',
url = 'https://github.com/makgyver/PRL',
download_url = 'https://github.com/makgyver/PRL',
keywords = ['preference-learning', 'game-theory', 'machine-learning', 'algorithm'],
classifiers = [
'Development Status :: 4 - Beta',
'Programming Language :: Python :: 3.6',
'Topic :: Scientific/Engineering :: Artificial Intelligence',
'License :: OSI Approved :: MIT License',
]
)

0 comments on commit 279fbaf

Please sign in to comment.