Skip to content

Commit

Permalink
Replaced hand-chosen regressors with completely arbitrary ones
Browse files Browse the repository at this point in the history
Instead of having the `--regressor` option take one of a few hand-chosen
values, it now takes the name of _any arbitrary regressor object_, such
as the default, `--regressor sklearn.linear_model.LassoLarsIC`. This
requires a little more user-knowledge, but opens a world of
possibilities.

This is accomplished through the new `plotypus.utils.import_name`
function, which imports an object from its full name and returns it,
without affecting the enclosing namespace.
  • Loading branch information
dwysocki committed Jan 21, 2016
1 parent 332a6e8 commit 3fbbc78
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 21 deletions.
32 changes: 11 additions & 21 deletions src/plotypus/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
import dill
from argparse import ArgumentError, ArgumentParser, SUPPRESS
from pandas import read_table
from sklearn.linear_model import (LassoCV, LassoLarsCV, LassoLarsIC,
LinearRegression, RidgeCV, ElasticNetCV)
import sklearn.linear_model
from sklearn.grid_search import GridSearchCV
from matplotlib import rc_params_from_file
from collections import ChainMap
Expand All @@ -20,8 +19,9 @@
plot_periodogram)
import plotypus
from plotypus.preprocessing import Fourier
from plotypus.utils import (colvec, mad, make_sure_path_exists, pmap,
strlist_to_dict, valid_basename, verbose_print)
from plotypus.utils import (colvec, import_name, mad, make_sure_path_exists,
pmap, strlist_to_dict, valid_basename,
verbose_print)
from plotypus.resources import matplotlibrc

import pkg_resources # part of setuptools
Expand Down Expand Up @@ -277,12 +277,12 @@ def get_args():
default=(2, 20), metavar=('MIN', 'MAX'),
help='range of degrees of fourier fits to use '
'(default = 2 20)')
fourier_group.add_argument('-r', '--regressor',
choices=['LassoCV', 'LassoLarsCV', 'LassoLarsIC', 'OLS', 'RidgeCV',
'ElasticNetCV'],
default='LassoLarsIC',
help='type of regressor to use '
'(default = "Lasso")')
fourier_group.add_argument('-r', '--regressor', type=import_name,
default=sklearn.linear_model.LassoLarsIC,
help='type of regressor to use, loads any Python object named like '
'*module.submodule.etc.object_name*, though it must behave like a '
'scikit-learn regressor '
'(default = "sklearn.linear_model.LassoLarsIC")')
fourier_group.add_argument('--selector',
choices=['Baart', 'GridSearch'],
default='GridSearch',
Expand Down Expand Up @@ -333,16 +333,6 @@ def get_args():
# parse regressor (TODO: and selector) options into a dict
regressor_options = strlist_to_dict(args.regressor_options)

regressor_choices = {
"LassoCV" : LassoCV,
"LassoLarsCV" : LassoLarsCV,
"LassoLarsIC" : LassoLarsIC,
"OLS" : LinearRegression,
"RidgeCV" : RidgeCV,
"ElasticNetCV" : ElasticNetCV
}


selector_choices = {
"Baart" : None,
"GridSearch" : GridSearchCV
Expand All @@ -363,7 +353,7 @@ def get_args():
}
args.scoring = scoring_choices[args.scoring]

args.regressor = regressor_choices[args.regressor](**regressor_options)
args.regressor = args.regressor(**regressor_options)
Selector = selector_choices[args.selector] or GridSearchCV
args.periodogram = periodogram_choices[args.periodogram]
args.sigma_clipping = sigma_clipping_choices[args.sigma_clipping]
Expand Down
46 changes: 46 additions & 0 deletions src/plotypus/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

__all__ = [
'verbose_print',
'import_name',
'literal_eval_str',
'strlist_to_dict',
'pmap',
Expand Down Expand Up @@ -47,6 +48,51 @@ def verbose_print(message, *, operation, verbosity):
print(message, file=stderr)


def import_name(dotted_name):
"""import_name(dotted_name)
Import an object from a module, and return the object. Does not affect the
encapsulating namespace.
**Parameters**
dotted_name : str
The fully-qualified name of the object to import, in the form
*module.submodule.etc.object_name*. Will error if *dotted_name* is
a top-level module (e.g. *module* and not *module.something*) or if
the object does not exist.
**Returns**
obj : object
The object specified by *dotted_name*.
"""
# Separate `module.submodule.object` into `[module, submodule]` and `object`
*module_path_components, object_name = dotted_name.split(".")

# Ensure `object_name` is contained within a module, and is not a
# standalone module.
# In other words, make sure `dotted_name` is a module containing an object
# like `foo.bar.baz` and not just a module like `baz`
if len(module_path_components) == 0:
raise ValueError("must name object within a module, not just a module")

# Reinsert the dots into the module name, e.g. turn
# `[module, submodule]` back into `module.submodule`
module_name = ".".join(module_path_components)

# import the module
from importlib import import_module
module = import_module(module_name)

# return the desired object
try:
return getattr(module, object_name)
except AttributeError:
raise ImportError("module '{module}' has no object '{object_name}'"
.format(module=module_name, object_name=object_name))


def literal_eval_str(string):
"""literal_eval_str(string)
Expand Down

0 comments on commit 3fbbc78

Please sign in to comment.