Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/build/
/my_env/
/settree.egg-info/
*.jpg
**/__pycache__/
13 changes: 3 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ It contains two main components: `SetDataset` object, that receives `records` as

When configuring Set-Tree one should also configure:
- `operations` : list of the operations to be used
- `use_attention_set` : binary flag for activating the attention-sets mechanism
- `use_attention_set` : binary flag for activating the attention-sets mechanism
- `attention_set_limit` : the number of ancestors levels to derive attention-sets from
- `use_attention_set_comp` : binary flag for activating the attention-sets compatibility option

Expand Down Expand Up @@ -59,9 +59,9 @@ import numpy as np

set_data = settree.SetDataset(records=[np.random.randn(2,5) for _ in range(10)])
labels = np.random.randn(10) >= 0.5
gbest_model = settree.GradientBoostedSetTreeClassifier(learning_rate=0.1,
gbest_model = settree.GradientBoostedSetTreeClassifier(learning_rate=0.1,
n_estimators=10,
criterion='mse',
criterion='squared_error',
operations=settree.OPERATIONS,
use_attention_set=True,
use_attention_set_comp=True,
Expand Down Expand Up @@ -91,10 +91,3 @@ If you use Set-Tree in your work, please cite:

## License
Set-Tree is MIT licensed, as found in the [LICENSE](https://github.com/TAU-MLwell/Set-Tree/blob/main/LICENSE) file.







332 changes: 206 additions & 126 deletions example.ipynb

Large diffs are not rendered by default.

11 changes: 5 additions & 6 deletions exps/eval_utils/train_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ def train_and_predict_set_gbdt(params, ds_train, train_y, ds_test, test_y,
else:
gbdt = GradientBoostedSetTreeRegressor(**params)
eval_met = mse
eval_met_name = 'mse'
eval_met_name = 'squared_error'

timer = Timer()

Expand Down Expand Up @@ -373,7 +373,7 @@ def train_and_predict_set_tree(params, ds_train, train_y, ds_test, test_y,
eval_met_name = 'acc'
else:
eval_met = mse
eval_met_name = 'mse'
eval_met_name = 'squared_error'

timer = Timer()
tree.fit(ds_train, train_y)
Expand Down Expand Up @@ -435,7 +435,7 @@ def train_and_predict_xgboost(params,
else:
gbdt = xgb.XGBRegressor(**params)
eval_met = mse
eval_met_name = 'mse'
eval_met_name = 'squared_error'

if verbose:
logging.info('Params: {}'.format(params))
Expand Down Expand Up @@ -499,7 +499,7 @@ def train_and_predict_sklearn_gbtd(params,
else:
gbdt = GradientBoostingRegressor(**params)
eval_met = mse
eval_met_name = 'mse'
eval_met_name = 'squared_error'

if verbose:
logging.info('Params: {}'.format(params))
Expand Down Expand Up @@ -568,7 +568,7 @@ def train_and_predict_sklearn_dt(params,
else:
dt = DecisionTreeRegressor(**params)
eval_met = mse
eval_met_name = 'mse'
eval_met_name = 'squared_error'

if verbose:
logging.info('Params: {}'.format(params))
Expand Down Expand Up @@ -610,4 +610,3 @@ def train_and_predict_sklearn_dt(params,
return dt, train_met, test_met
else:
return dt

2 changes: 1 addition & 1 deletion exps/first_quadrant/first_quadrant_gbest.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
'verbose': 3}

xgboost_params = {'n_estimators': params['n_estimators'],
'criterion': 'mse',
'criterion': 'squared_error',
'learning_rate': params['learning_rate'],
'max_depth': params['max_depth'],
'max_features': params['max_features'],
Expand Down
5 changes: 2 additions & 3 deletions exps/jets/qg_jets_gbest.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
'max_depth': 5,
'max_features': None,
'subsample': 0.5,
'criterion': 'mse',
'criterion': 'squared_error',
'early_stopping_rounds': 5,
'random_state': args.seed}

Expand All @@ -85,7 +85,7 @@
'verbose': 3}

sklearn_params = {'n_estimators': shared_gbdt_params['n_estimators'],
'criterion': 'mse',
'criterion': 'squared_error',
'learning_rate': shared_gbdt_params['learning_rate'],
'max_depth': shared_gbdt_params['max_depth'],
'max_features': shared_gbdt_params['max_features'],
Expand Down Expand Up @@ -129,4 +129,3 @@
pkl_filename = os.path.join(log_dir, '{}_model.pkl'.format(args.exp_name))
with open(pkl_filename, 'wb') as file:
pickle.dump(set_gbtd, file)

4 changes: 2 additions & 2 deletions exps/jets/top_quark_gbdt.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def get_top_quark_datset(train=None, val=None, test=None):
'max_depth': 8,
'max_features': None,
'subsample': 0.5,
'criterion': 'mse',
'criterion': 'squared_error',
'early_stopping_rounds': 5,
'random_state': 42}

Expand All @@ -106,7 +106,7 @@ def get_top_quark_datset(train=None, val=None, test=None):
'verbose': 3}

sklearn_params = {'n_estimators': shared_gbdt_params['n_estimators'],
'criterion': 'mse',
'criterion': 'squared_error',
'learning_rate': shared_gbdt_params['learning_rate'],
'max_depth': shared_gbdt_params['max_depth'],
'max_features': shared_gbdt_params['max_features'],
Expand Down
2 changes: 1 addition & 1 deletion exps/mimic/mimic_gbest.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
'verbose': 3}

sklearn_params = {'n_estimators': shared_gbdt_params['n_estimators'],
'criterion': 'mse',
'criterion': 'squared_error',
'learning_rate': shared_gbdt_params['learning_rate'],
'max_depth': shared_gbdt_params['max_depth'],
'max_features': shared_gbdt_params['max_features'],
Expand Down
2 changes: 1 addition & 1 deletion exps/point_cloud/modelnet40_gbest.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
'verbose': 3}

sklearn_params = {'n_estimators': shared_gbdt_params['n_estimators'],
'criterion': 'mse',
'criterion': 'squared_error',
'learning_rate': shared_gbdt_params['learning_rate'],
'max_depth': shared_gbdt_params['max_depth'],
'max_features': shared_gbdt_params['max_features'],
Expand Down
2 changes: 1 addition & 1 deletion exps/redshift/redshift_gbest.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def eval_scatter(model, x, y):
'max_depth': 8,
'max_features': None,
'subsample': 0.5,
'criterion': 'mse',
'criterion': 'squared_error',
#'early_stopping_rounds': 5,
'random_state': 42}

Expand Down
51 changes: 18 additions & 33 deletions settree/gbest.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def __init__(self, *, loss, learning_rate, n_estimators, criterion, splitter='sk
max_depth, min_impurity_decrease, min_impurity_split,
init, subsample, max_features, ccp_alpha,
random_state, alpha=0.9, verbose=0, max_leaf_nodes=None,
warm_start=False, validation_fraction=0.1,
warm_start=False,
n_iter_no_change=None, tol=1e-4):

self.n_estimators = n_estimators
Expand Down Expand Up @@ -150,15 +150,13 @@ def __init__(self, *, loss, learning_rate, n_estimators, criterion, splitter='sk
self.verbose = verbose
self.max_leaf_nodes = max_leaf_nodes
self.warm_start = warm_start
self.validation_fraction = validation_fraction
self.n_iter_no_change = n_iter_no_change
self.tol = tol


def _fit_stage(self, i, X_set, y, raw_predictions, sample_weight, sample_mask, random_state):
"""Fit another stage of ``n_classes_`` trees to the boosting model. """

assert sample_mask.dtype == np.bool
assert sample_mask.dtype == bool
loss = self.loss_
original_y = y

Expand Down Expand Up @@ -295,15 +293,15 @@ def _check_params(self):

def _init_state(self):
"""Initialize model state and allocate model state data structures. """
#np.random.seed(self.random_state)
# np.random.seed(self.random_state)
self._rng = check_random_state(self.random_state)

self.init_ = self.init
if self.init_ is None:
self.init_ = self.loss_.init_estimator()

self.estimators_ = np.empty((self.n_estimators, self.loss_.K),
dtype=np.object)
dtype=object)
self.train_score_ = np.zeros((self.n_estimators,), dtype=np.float64)
# do oob?
if self.subsample < 1.0:
Expand All @@ -317,7 +315,7 @@ def _init_state(self):
def _clear_state(self):
"""Clear the state of the gradient boosting model. """
if hasattr(self, 'estimators_'):
self.estimators_ = np.empty((0, 0), dtype=np.object)
self.estimators_ = np.empty((0, 0), dtype=object)
if hasattr(self, 'train_score_'):
del self.train_score_
if hasattr(self, 'oob_improvement_'):
Expand Down Expand Up @@ -354,7 +352,7 @@ def _check_initialized(self):
"""Check that the estimator is initialized, raising an error if not."""
check_is_fitted(self)

def fit(self, X_set, y, sample_weight=None, monitor=None):
def fit(self, X_set, y, X_set_val = None, y_val = None, sample_weight=None, sample_weight_val=None, monitor=None):

y = check_array(y, dtype=DTYPE, ensure_2d=False)
n_samples, self.n_features_ = X_set.shape
Expand All @@ -366,20 +364,7 @@ def fit(self, X_set, y, sample_weight=None, monitor=None):
y = column_or_1d(y, warn=True)
y = self._validate_y(y, sample_weight)

if self.n_iter_no_change is not None:
stratify = y if is_classifier(self) else None
inds, inds_val = (train_test_split(range(len(X_set)),
random_state=self.random_state,
test_size=self.validation_fraction,
stratify=stratify))
X_set_val = X_set.get_subset(inds_val)
X_set = X_set.get_subset(inds)

y_val = y.take(inds_val)
y = y.take(inds)
sample_weight_val = sample_weight.take(inds_val)
sample_weight = sample_weight.take(inds)

if self.n_iter_no_change is not None and X_set_val is not None and y_val is not None:
if is_classifier(self):
if self.n_classes_ != np.unique(y).shape[0]:
# We choose to error here. The problem is that the init
Expand All @@ -393,6 +378,7 @@ def fit(self, X_set, y, sample_weight=None, monitor=None):
)
else:
X_set_val = y_val = sample_weight_val = None
self.n_iter_no_change = None

self._check_params()

Expand Down Expand Up @@ -442,7 +428,7 @@ def fit(self, X_set, y, sample_weight=None, monitor=None):
# The requirements of _decision_function (called in two lines
# below) are more constrained than fit. It accepts only CSR
# matrices.
#X = check_array(X, dtype=DTYPE, order="C", accept_sparse='csr')
# X = check_array(X, dtype=DTYPE, order="C", accept_sparse='csr')
raw_predictions = self._raw_predict(X_set)
self._resize_state()

Expand Down Expand Up @@ -473,7 +459,7 @@ def _fit_stages(self, X_set, y, raw_predictions, sample_weight,
n_samples = X_set.shape[0]

do_oob = self.subsample < 1.0
sample_mask = np.ones((n_samples,), dtype=np.bool)
sample_mask = np.ones((n_samples,), dtype=bool)
n_inbag = max(1, int(self.subsample * n_samples))
loss_ = self.loss_

Expand Down Expand Up @@ -554,7 +540,7 @@ def _make_estimator(self, append=True):
def _raw_predict_init(self, X_set):
"""Check input and compute raw predictions of the init estimator."""
self._check_initialized()
#X = self.estimators_[0, 0]._validate_X_predict(X_set, check_input=True)
# X = self.estimators_[0, 0]._validate_X_predict(X_set, check_input=True)
if X_set.shape[1] != self.n_features_:
raise ValueError("X.shape[1] should be {0:d}, not {1:d}.".format(
self.n_features_, X_set.shape[1]))
Expand Down Expand Up @@ -591,7 +577,7 @@ def _staged_raw_predict(self, X_set):
Regression and binary classification are special cases with
``k == 1``, otherwise ``k==n_classes``.
"""
#X = check_array(X, dtype=DTYPE, order="C", accept_sparse='csr')
# X = check_array(X, dtype=DTYPE, order="C", accept_sparse='csr')
raw_predictions = self._raw_predict_init(X_set)
for i in range(self.estimators_.shape[0]):
predict_stage(self.estimators_, i, X_set, self.learning_rate,
Expand Down Expand Up @@ -695,7 +681,7 @@ def apply(self, X_set):
"""

self._check_initialized()
#X = self.estimators_[0, 0]._validate_X_predict(X, check_input=True)
# X = self.estimators_[0, 0]._validate_X_predict(X, check_input=True)

# n_classes will be equal to 1 in the binary classification or the
# regression case.
Expand All @@ -715,15 +701,15 @@ class GradientBoostedSetTreeClassifier(ClassifierMixin, BaseGradientBoostedSetTr

@_deprecate_positional_args
def __init__(self, *, loss='deviance', learning_rate=0.1, n_estimators=100,
subsample=1.0, criterion='mse',
subsample=1.0, criterion='squared_error',
splitter='sklearn', operations=OPERATIONS, use_attention_set=True, use_attention_set_comp=True,
attention_set_limit=1, save_path=None,
min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.,
max_depth=3, min_impurity_decrease=0.,
min_impurity_split=None, init=None,
random_state=None, max_features=None, verbose=0,
max_leaf_nodes=None, warm_start=False,
validation_fraction=0.1, n_iter_no_change=None, tol=1e-4,
n_iter_no_change=None, tol=1e-4,
ccp_alpha=0.0):

super().__init__(
Expand All @@ -739,7 +725,7 @@ def __init__(self, *, loss='deviance', learning_rate=0.1, n_estimators=100,
max_leaf_nodes=max_leaf_nodes,
min_impurity_decrease=min_impurity_decrease,
min_impurity_split=min_impurity_split,
warm_start=warm_start, validation_fraction=validation_fraction,
warm_start=warm_start,
n_iter_no_change=n_iter_no_change, tol=tol, ccp_alpha=ccp_alpha)

def _validate_y(self, y, sample_weight):
Expand Down Expand Up @@ -914,14 +900,14 @@ class GradientBoostedSetTreeRegressor(RegressorMixin, BaseGradientBoostedSetTree

@_deprecate_positional_args
def __init__(self, *, loss='ls', learning_rate=0.1, n_estimators=100,
subsample=1.0, criterion='mse', splitter='sklearn',
subsample=1.0, criterion='squared_error', splitter='sklearn',
operations=OPERATIONS, use_attention_set=True, use_attention_set_comp=True,
attention_set_limit=1, save_path=None,
min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.,
max_depth=3, min_impurity_decrease=0.,
min_impurity_split=None, init=None, random_state=None,
max_features=None, alpha=0.9, verbose=0, max_leaf_nodes=None,
warm_start=False, validation_fraction=0.1,
warm_start=False,
n_iter_no_change=None, tol=1e-4, ccp_alpha=0.0):
super().__init__(
loss=loss, learning_rate=learning_rate, n_estimators=n_estimators, criterion=criterion, splitter=splitter,
Expand All @@ -936,7 +922,6 @@ def __init__(self, *, loss='ls', learning_rate=0.1, n_estimators=100,
min_impurity_split=min_impurity_split,
random_state=random_state, alpha=alpha, verbose=verbose,
max_leaf_nodes=max_leaf_nodes, warm_start=warm_start,
validation_fraction=validation_fraction,
n_iter_no_change=n_iter_no_change, tol=tol, ccp_alpha=ccp_alpha)

def predict(self, X_set):
Expand Down
Loading