Skip to content

Commit

Permalink
Remove append original (#29)
Browse files Browse the repository at this point in the history
* remove all traces of append_original

* remove all traces of append_original from UI

* add identity transformer

* update docs for removing append_original
  • Loading branch information
reiinakano authored Jun 7, 2017
1 parent 08d7908 commit 44577e7
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 48 deletions.
5 changes: 4 additions & 1 deletion docs/walkthrough.rst
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,10 @@ To set the hyperparameters of the secondary learner, enter the following into th

This should keep the Logistic Regression at its default values. If you'll notice, the format required for this code block is exactly the same as that required when creating a single base learner.

There's an additional checkbox you can tick to append the original features to the base learners' meta-features. Leave it unchecked for now, and go ahead and **Create new ensemble**.
.. admonition:: Appending original features to the meta-features

As of 0.4.0, Xcessiv no longer provides the checkbox option to append the original features to the meta-features. However, this functionality can be achieved by using the preset "Identity Transformer" and including this as a base learner in the ensemble. This approach reinforces the fact that a base learner is simply something that generates meta-features from features, and one that lets all features pass through unchanged fits this description.


After a short time, your ensemble should finish processing, and you'll be able to see its performance. Here we get an accuracy of 0.968, which is higher than any individual base learner.

Expand Down
16 changes: 5 additions & 11 deletions xcessiv/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,17 +367,15 @@ class StackedEnsemble(Base):
base_learner_origin = relationship('BaseLearnerOrigin', back_populates='stacked_ensembles')
secondary_learner_hyperparameters = Column(JsonEncodedDict)
individual_score = Column(JsonEncodedDict)
append_original = Column(Boolean)
job_status = Column(Text)
job_id = Column(Text)
description = Column(JsonEncodedDict)

def __init__(self, secondary_learner_hyperparameters, base_learners,
base_learner_origin, append_original, job_status):
base_learner_origin, job_status):
self.base_learner_origin = base_learner_origin
self.secondary_learner_hyperparameters = secondary_learner_hyperparameters
self.base_learners = base_learners
self.append_original = append_original
self.individual_score = dict()
self.job_status = job_status
self.job_id = None
Expand Down Expand Up @@ -461,12 +459,10 @@ def export_as_code(self, cv_source):
'(base_learners=base_learner_list_{},' \
' meta_feature_generators=meta_feature_generators_list_{},' \
' secondary_learner=secondary_learner_{},' \
' cv_function=return_splits_iterable,' \
' append_original={})\n'.format(
' cv_function=return_splits_iterable)\n'.format(
rand_value,
rand_value,
rand_value,
self.append_original
rand_value
)

return base_learner_code
Expand Down Expand Up @@ -571,8 +567,7 @@ def export_as_package(self, package_path, cv_source):
builder_source += '\nxcessiv_ensemble = XcessivStackedEnsemble(base_learners=base_learners,' \
' meta_feature_generators=meta_feature_generators,' \
' secondary_learner=metalearner.base_learner,' \
' cv_function=return_splits_iterable,' \
' append_original={})\n'.format(self.append_original)
' cv_function=return_splits_iterable)\n'

with open(os.path.join(package_path, 'builder.py'), 'wb') as f:
f.write(builder_source.encode('utf8'))
Expand All @@ -588,6 +583,5 @@ def serialize(self):
description=self.description,
base_learner_origin_id=self.base_learner_origin_id,
base_learner_ids=list(map(lambda x: x.id, self.base_learners)),
number_of_base_learners=len(self.base_learners),
append_original=self.append_original
number_of_base_learners=len(self.base_learners)
)
12 changes: 11 additions & 1 deletion xcessiv/presets/learnersetting.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
'sklearn_decision_tree_regressor',
'sklearn_linear_regression',
'sklearn_adaboost_regressor',
'xgboost_regressor'
'xgboost_regressor',

# Transformers
'identity_transformer'
]

# Classifiers
Expand Down Expand Up @@ -157,3 +160,10 @@
'source': learnersource.xgboost_regressor_source,
'meta_feature_generator': 'predict'
}


identity_transformer = {
'name': 'Identity Transformer',
'source': learnersource.identity_transformer_source,
'meta_feature_generator': 'transform'
}
11 changes: 10 additions & 1 deletion xcessiv/presets/learnersource.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
'sklearn_decision_tree_regressor_source',
'sklearn_linear_regression_source',
'sklearn_adaboost_regressor_source',
'xgboost_regressor_source'
'xgboost_regressor_source',

# Transformers
'identity_transformer_source'
]

sklearn_random_forest_classifier_source = \
Expand Down Expand Up @@ -154,3 +157,9 @@
base_learner = XGBRegressor(seed=8)
"""

identity_transformer_source = \
"""from sklearn.preprocessing import FunctionTransformer
base_learner = FunctionTransformer()
"""
3 changes: 0 additions & 3 deletions xcessiv/rqtasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,9 +437,6 @@ def evaluate_stacked_ensemble(path, ensemble_id):
indices = np.concatenate(indices_list)
X, y = X[indices], y[indices]

if stacked_ensemble.append_original:
secondary_features = np.concatenate((secondary_features, X), axis=1)

est = stacked_ensemble.return_secondary_learner()

return_splits_iterable_stacked_ensemble = functions.import_object_from_string_code(
Expand Down
14 changes: 1 addition & 13 deletions xcessiv/stacker.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@
class XcessivStackedEnsemble(_BasePipeline):
"""Contains the class for the Xcessiv stacked ensemble"""
def __init__(self, base_learners, meta_feature_generators,
secondary_learner, cv_function, append_original):
secondary_learner, cv_function):
super(XcessivStackedEnsemble, self).__init__()

self.base_learners = base_learners
self.meta_feature_generators = meta_feature_generators
self.secondary_learner = secondary_learner
self.cv_function = cv_function
self.append_original = append_original
self._named_learners = [('bl{}'.format(idx), base_learner) for idx, base_learner
in enumerate(base_learners)]
self._named_learners.append(('secondary-learner', secondary_learner))
Expand Down Expand Up @@ -67,12 +66,6 @@ def fit(self, X, y):

print('Fitting meta-learner')

if self.append_original:
all_learner_meta_features = np.concatenate(
(all_learner_meta_features, X[test_indices]),
axis=1
)

self.secondary_learner.fit(all_learner_meta_features, y[test_indices])

return self
Expand Down Expand Up @@ -100,11 +93,6 @@ def _process_using_meta_feature_generator(self, X, meta_feature_generator):
all_learner_meta_features.append(single_learner_meta_features)

all_learner_meta_features = np.concatenate(all_learner_meta_features, axis=1)
if self.append_original:
all_learner_meta_features = np.concatenate(
(all_learner_meta_features, X),
axis=1
)

out = getattr(self.secondary_learner, meta_feature_generator)(all_learner_meta_features)

Expand Down
14 changes: 3 additions & 11 deletions xcessiv/ui/src/Ensemble/EnsembleBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Select from 'react-select'
import CodeMirror from 'react-codemirror';
import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/python/python';
import { Checkbox, Button, Glyphicon } from 'react-bootstrap';
import { Button, Glyphicon } from 'react-bootstrap';


const defaultSourceParams = [
Expand All @@ -24,8 +24,7 @@ class EnsembleBuilder extends Component {
super(props);
this.state = {
selectedValue: null,
source: defaultSourceParams,
appendOriginal: false
source: defaultSourceParams
};
}

Expand Down Expand Up @@ -66,19 +65,12 @@ class EnsembleBuilder extends Component {
onChange={(src) => this.setState({source: src})}
options={options}
/>
<Checkbox
checked={this.state.appendOriginal}
onChange={() => this.setState((prevState) =>
({appendOriginal: !prevState.appendOriginal}))}
>
Append original features to secondary features
</Checkbox>
<Button
block
disabled={buttonDisabled}
bsStyle='primary'
onClick={() => this.props.createStackedEnsemble(
this.state.selectedValue.value, this.state.source, this.state.appendOriginal)}>
this.state.selectedValue.value, this.state.source)}>
<Glyphicon glyph="plus" />
{' Create new ensemble'}
</Button>
Expand Down
1 change: 0 additions & 1 deletion xcessiv/ui/src/Ensemble/ListEnsemble.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ class ListEnsemble extends Component {
const cols = [
{label: 'ID', value: 'id', width: 50},
{label: 'Secondary Learner ID', value: 'base_learner_origin_id', width: 100},
{label: 'Appended Original Features', value: 'append_original', width: 100},
{label: 'Number of Base Learners', value: 'number_of_base_learners', width: 100}
]
return cols.map((obj) => {
Expand Down
9 changes: 4 additions & 5 deletions xcessiv/ui/src/containers/ContainerBaseLearner.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,12 +530,11 @@ class ContainerBaseLearner extends Component {

// Create new stacked ensemble
createStackedEnsemble(base_learner_ids, base_learner_origin_id,
secondary_learner_hyperparameters_source, append_original) {
secondary_learner_hyperparameters_source) {
var payload = {
base_learner_ids,
base_learner_origin_id,
secondary_learner_hyperparameters_source,
append_original
secondary_learner_hyperparameters_source
};

fetch(
Expand Down Expand Up @@ -715,8 +714,8 @@ class ContainerBaseLearner extends Component {
optionsBaseLearnerOrigins={optionsBaseLearnerOrigins}
checkedOptions={checkedOptions}
setCheckedBaseLearners={(checkedArray) => this.setState({checkedBaseLearners: ImSet(checkedArray)})}
createStackedEnsemble={(bloId, hp, appendOriginal) =>
this.createStackedEnsemble(this.state.checkedBaseLearners, bloId, hp, appendOriginal)}
createStackedEnsemble={(bloId, hp) =>
this.createStackedEnsemble(this.state.checkedBaseLearners, bloId, hp)}
/>
<ListEnsemble
path={this.props.path}
Expand Down
1 change: 0 additions & 1 deletion xcessiv/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,6 @@ def create_new_stacked_ensemble():
secondary_learner_hyperparameters=hyperparameters,
base_learners=base_learners,
base_learner_origin=base_learner_origin,
append_original=req_body['append_original'],
job_status='queued'
)

Expand Down

0 comments on commit 44577e7

Please sign in to comment.