Skip to content

Commit 0bbd9ba

Browse files
saswatacChoiByungWook
authored andcommitted
Add new hyper-parameters for linear learner and bump version to v1.1.3 (#112)
* add new hyper-parameters for linear learner adding hyper-parameters for early stopping and new loss types. * bump version to 1.1.3
1 parent 2c71fc9 commit 0bbd9ba

File tree

7 files changed

+97
-40
lines changed

7 files changed

+97
-40
lines changed

CHANGELOG.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
CHANGELOG
33
=========
44

5-
1.1.dev3
5+
1.1.3
66
========
77

88
* bug-fix: TensorFlow: Display updated data correctly for TensorBoard launched from ``run_tensorboard_locally=True``
99
* feature: Tests: create configurable ``sagemaker_session`` pytest fixture for all integration tests
1010
* bug-fix: AmazonEstimators: fix inaccurate hyper-parameters in kmeans, pca and linear learner
11+
* feature: Add new hyperparameters for linear learner.
1112

1213
1.1.2
1314
=====

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ You can install from source by cloning this repository and issuing a pip install
4747

4848
git clone https://github.com/aws/sagemaker-python-sdk.git
4949
python setup.py sdist
50-
pip install dist/sagemaker-1.1.2.tar.gz
50+
pip install dist/sagemaker-1.1.3.tar.gz
5151

5252
Supported Python versions
5353
~~~~~~~~~~~~~~~~~~~~~~~~~

doc/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def __getattr__(cls, name):
1818
'tensorflow.python.framework', 'tensorflow_serving', 'tensorflow_serving.apis']
1919
sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
2020

21-
version = '1.1.2'
21+
version = '1.1.3'
2222
project = u'sagemaker'
2323

2424
# Add any Sphinx extension module names here, as strings. They can be extensions

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def read(fname):
1111

1212

1313
setup(name="sagemaker",
14-
version="1.1.2",
14+
version="1.1.3",
1515
description="Open source library for training and deploying models on Amazon SageMaker.",
1616
packages=find_packages('src'),
1717
package_dir={'': 'src'},

src/sagemaker/amazon/linear_learner.py

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,13 @@
1313
from sagemaker.amazon.amazon_estimator import AmazonAlgorithmEstimatorBase, registry
1414
from sagemaker.amazon.common import numpy_to_record_serializer, record_deserializer
1515
from sagemaker.amazon.hyperparameter import Hyperparameter as hp # noqa
16-
from sagemaker.amazon.validation import isin, gt, lt
16+
from sagemaker.amazon.validation import isin, gt, lt, ge
1717
from sagemaker.predictor import RealTimePredictor
1818
from sagemaker.model import Model
1919
from sagemaker.session import Session
2020

2121

2222
class LinearLearner(AmazonAlgorithmEstimatorBase):
23-
2423
repo_name = 'linear-learner'
2524
repo_version = 1
2625

@@ -32,27 +31,30 @@ class LinearLearner(AmazonAlgorithmEstimatorBase):
3231
data_type=str)
3332
target_recall = hp('target_recall', (gt(0), lt(1)), "A float in (0,1)", float)
3433
target_precision = hp('target_precision', (gt(0), lt(1)), "A float in (0,1)", float)
34+
positive_example_weight_mult = hp('positive_example_weight_mult', (),
35+
"A float greater than 0 or 'auto' or 'balanced'", str)
3536
epochs = hp('epochs', gt(0), "An integer greater-than 0", int)
3637
predictor_type = hp('predictor_type', isin('binary_classifier', 'regressor'),
3738
'One of "binary_classifier" or "regressor"', str)
3839
use_bias = hp('use_bias', (), "Either True or False", bool)
3940
num_models = hp('num_models', gt(0), "An integer greater-than 0", int)
4041
num_calibration_samples = hp('num_calibration_samples', gt(0), "An integer greater-than 0", int)
4142
init_method = hp('init_method', isin('uniform', 'normal'), 'One of "uniform" or "normal"', str)
42-
init_scale = hp('init_scale', (gt(-1), lt(1)), 'A float in (-1, 1)', float)
43-
init_sigma = hp('init_sigma', (gt(0), lt(1)), 'A float in (0, 1)', float)
43+
init_scale = hp('init_scale', gt(0), 'A float greater-than 0', float)
44+
init_sigma = hp('init_sigma', gt(0), 'A float greater-than 0', float)
4445
init_bias = hp('init_bias', (), 'A number', float)
4546
optimizer = hp('optimizer', isin('sgd', 'adam', 'auto'), 'One of "sgd", "adam" or "auto', str)
4647
loss = hp('loss', isin('logistic', 'squared_loss', 'absolute_loss', 'auto'),
47-
'"logistic", "squared_loss", "absolute_loss" or"auto"', str)
48-
wd = hp('wd', (gt(0), lt(1)), 'A float in (0,1)', float)
49-
l1 = hp('l1', (gt(0), lt(1)), 'A float in (0,1)', float)
50-
momentum = hp('momentum', (gt(0), lt(1)), 'A float in (0,1)', float)
51-
learning_rate = hp('learning_rate', (gt(0), lt(1)), 'A float in (0,1)', float)
52-
beta_1 = hp('beta_1', (gt(0), lt(1)), 'A float in (0,1)', float)
53-
beta_2 = hp('beta_2', (gt(0), lt(1)), 'A float in (0,1)', float)
48+
'"logistic", "squared_loss", "absolute_loss", "hinge_loss", "eps_insensitive_squared_loss", '
49+
'"eps_insensitive_absolute_loss", "quantile_loss", "huber_loss" or "auto"', str)
50+
wd = hp('wd', ge(0), 'A float greater-than or equal to 0', float)
51+
l1 = hp('l1', ge(0), 'A float greater-than or equal to 0', float)
52+
momentum = hp('momentum', (ge(0), lt(1)), 'A float in [0,1)', float)
53+
learning_rate = hp('learning_rate', gt(0), 'A float greater-than or equal to 0', float)
54+
beta_1 = hp('beta_1', (ge(0), lt(1)), 'A float in [0,1)', float)
55+
beta_2 = hp('beta_2', (ge(0), lt(1)), 'A float in [0,1)', float)
5456
bias_lr_mult = hp('bias_lr_mult', gt(0), 'A float greater-than 0', float)
55-
bias_wd_mult = hp('bias_wd_mult', gt(0), 'A float greater-than 0', float)
57+
bias_wd_mult = hp('bias_wd_mult', ge(0), 'A float greater-than or equal to 0', float)
5658
use_lr_scheduler = hp('use_lr_scheduler', (), 'A boolean', bool)
5759
lr_scheduler_step = hp('lr_scheduler_step', gt(0), 'An integer greater-than 0', int)
5860
lr_scheduler_factor = hp('lr_scheduler_factor', (gt(0), lt(1)), 'A float in (0,1)', float)
@@ -62,15 +64,23 @@ class LinearLearner(AmazonAlgorithmEstimatorBase):
6264
unbias_data = hp('unbias_data', (), 'A boolean', bool)
6365
unbias_label = hp('unbias_label', (), 'A boolean', bool)
6466
num_point_for_scaler = hp('num_point_for_scaler', gt(0), 'An integer greater-than 0', int)
67+
margin = hp('margin', ge(0), 'A float greater-than or equal to 0', float)
68+
quantile = hp('quantile', (gt(0), lt(1)), 'A float in (0,1)', float)
69+
loss_insensitivity = hp('loss_insensitivity', gt(0), 'A float greater-than 0', float)
70+
huber_delta = hp('huber_delta', ge(0), 'A float greater-than or equal to 0', float)
71+
early_stopping_patience = hp('early_stopping_patience', gt(0), 'An integer greater-than 0', int)
72+
early_stopping_tolerance = hp('early_stopping_tolerance', gt(0), 'A float greater-than 0', float)
6573

6674
def __init__(self, role, train_instance_count, train_instance_type, predictor_type,
6775
binary_classifier_model_selection_criteria=None, target_recall=None, target_precision=None,
68-
epochs=None, use_bias=None, num_models=None,
76+
positive_example_weight_mult=None, epochs=None, use_bias=None, num_models=None,
6977
num_calibration_samples=None, init_method=None, init_scale=None, init_sigma=None, init_bias=None,
7078
optimizer=None, loss=None, wd=None, l1=None, momentum=None, learning_rate=None, beta_1=None,
7179
beta_2=None, bias_lr_mult=None, bias_wd_mult=None, use_lr_scheduler=None, lr_scheduler_step=None,
7280
lr_scheduler_factor=None, lr_scheduler_minimum_lr=None, normalize_data=None,
73-
normalize_label=None, unbias_data=None, unbias_label=None, num_point_for_scaler=None, **kwargs):
81+
normalize_label=None, unbias_data=None, unbias_label=None, num_point_for_scaler=None, margin=None,
82+
quantile=None, loss_insensitivity=None, huber_delta=None, early_stopping_patience=None,
83+
early_stopping_tolerance=None, **kwargs):
7484
"""An :class:`Estimator` for binary classification and regression.
7585
7686
Amazon SageMaker Linear Learner provides a solution for both classification and regression problems, allowing
@@ -113,6 +123,8 @@ def __init__(self, role, train_instance_count, train_instance_type, predictor_ty
113123
precision_at_target_recall.
114124
target_precision (float): Target precision. Only applicable if binary_classifier_model_selection_criteria
115125
is recall_at_target_precision.
126+
positive_example_weight_mult (float): The importance weight of positive examples is multiplied by this
127+
constant. Useful for skewed datasets. Only applies for classification tasks.
116128
epochs (int): The maximum number of passes to make over the training data.
117129
use_bias (bool): Whether to include a bias field
118130
num_models (int): Number of models to train in parallel. If not set, the number of parallel models to
@@ -125,7 +137,8 @@ def __init__(self, role, train_instance_count, train_instance_type, predictor_ty
125137
init_sigma (float): For "normal" init, the standard-deviation.
126138
init_bias (float): Initial weight for bias term
127139
optimizer (str): One of 'sgd', 'adam' or 'auto'
128-
loss (str): One of 'logistic', 'squared_loss', 'absolute_loss' or 'auto'
140+
loss (str): One of 'logistic', 'squared_loss', 'absolute_loss', 'hinge_loss',
141+
'eps_insensitive_squared_loss', 'eps_insensitive_absolute_loss', 'quantile_loss', 'huber_loss' or 'auto'
129142
wd (float): L2 regularization parameter i.e. the weight decay parameter. Use 0 for no L2 regularization.
130143
l1 (float): L1 regularization parameter. Use 0 for no L1 regularization.
131144
momentum (float): Momentum parameter of sgd optimizer.
@@ -150,13 +163,28 @@ def __init__(self, role, train_instance_count, train_instance_type, predictor_ty
150163
ubias_label (bool): If true, labels are modified to have mean 0.0.
151164
num_point_for_scaler (int): The number of data points to use for calculating the normalizing and
152165
unbiasing terms.
166+
margin (float): the margin for hinge_loss.
167+
quantile (float): Quantile for quantile loss. For quantile q, the model will attempt to produce
168+
predictions such that true_label < prediction with probability q.
169+
loss_insensitivity (float): Parameter for epsilon insensitive loss type. During training and metric
170+
evaluation, any error smaller than this is considered to be zero.
171+
huber_delta (float): Parameter for Huber loss. During training and metric evaluation, compute L2 loss for
172+
errors smaller than delta and L1 loss for errors larger than delta.
173+
early_stopping_patience (int): the number of epochs to wait before ending training if no improvement is
174+
made. The improvement is training loss if validation data is not provided, or else it is the validation
175+
loss or the binary classification model selection criteria like accuracy, f1-score etc. To disable early
176+
stopping, set early_stopping_patience to a value larger than epochs.
177+
early_stopping_tolerance (float): Relative tolerance to measure an improvement in loss. If the ratio of
178+
the improvement in loss divided by the previous best loss is smaller than this value, early stopping will
179+
consider the improvement to be zero.
153180
**kwargs: base class keyword argument values.
154181
"""
155182
super(LinearLearner, self).__init__(role, train_instance_count, train_instance_type, **kwargs)
156183
self.predictor_type = predictor_type
157184
self.binary_classifier_model_selection_criteria = binary_classifier_model_selection_criteria
158185
self.target_recall = target_recall
159186
self.target_precision = target_precision
187+
self.positive_example_weight_mult = positive_example_weight_mult
160188
self.epochs = epochs
161189
self.use_bias = use_bias
162190
self.num_models = num_models
@@ -184,6 +212,12 @@ def __init__(self, role, train_instance_count, train_instance_type, predictor_ty
184212
self.unbias_data = unbias_data
185213
self.unbias_label = unbias_label
186214
self.num_point_for_scaler = num_point_for_scaler
215+
self.margin = margin
216+
self.quantile = quantile
217+
self.loss_insensitivity = loss_insensitivity
218+
self.huber_delta = huber_delta
219+
self.early_stopping_patience = early_stopping_patience
220+
self.early_stopping_tolerance = early_stopping_tolerance
187221

188222
def create_model(self):
189223
"""Return a :class:`~sagemaker.amazon.kmeans.LinearLearnerModel` referencing the latest

tests/integ/test_linear_learner.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ def test_linear_learner(sagemaker_session):
4242
ll.binary_classifier_model_selection_criteria = 'accuracy'
4343
ll.target_recall = 0.5
4444
ll.target_precision = 0.5
45+
ll.positive_example_weight_mult = 0.1
4546
ll.epochs = 1
4647
ll.use_bias = True
4748
ll.num_models = 1
@@ -67,6 +68,12 @@ def test_linear_learner(sagemaker_session):
6768
ll.unbias_data = True
6869
ll.unbias_label = False
6970
ll.num_point_for_scaler = 10000
71+
ll.margin = 1.0
72+
ll.quantile = 0.5
73+
ll.loss_insensitivity = 0.1
74+
ll.huber_delta = 0.1
75+
ll.early_stopping_tolerance = 0.0001
76+
ll.early_stopping_patience = 3
7077
ll.fit(ll.record_set(train_set[0][:200], train_set[1][:200]))
7178

7279
endpoint_name = name_from_base('linear-learner')
@@ -102,6 +109,7 @@ def test_async_linear_learner(sagemaker_session):
102109
ll.binary_classifier_model_selection_criteria = 'accuracy'
103110
ll.target_recall = 0.5
104111
ll.target_precision = 0.5
112+
ll.positive_example_weight_mult = 0.1
105113
ll.epochs = 1
106114
ll.use_bias = True
107115
ll.num_models = 1
@@ -127,6 +135,12 @@ def test_async_linear_learner(sagemaker_session):
127135
ll.unbias_data = True
128136
ll.unbias_label = False
129137
ll.num_point_for_scaler = 10000
138+
ll.margin = 1.0
139+
ll.quantile = 0.5
140+
ll.loss_insensitivity = 0.1
141+
ll.huber_delta = 0.1
142+
ll.early_stopping_tolerance = 0.0001
143+
ll.early_stopping_patience = 3
130144
ll.fit(ll.record_set(train_set[0][:200], train_set[1][:200]), wait=False)
131145
training_job_name = ll.latest_training_job.name
132146

tests/unit/test_linear_learner.py

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,27 @@ def test_all_hyperparameters(sagemaker_session):
7070
lr = LinearLearner(sagemaker_session=sagemaker_session,
7171
binary_classifier_model_selection_criteria='accuracy',
7272
target_recall=0.5, target_precision=0.6,
73-
epochs=1, use_bias=True, num_models=5,
74-
num_calibration_samples=6, init_method='uniform', init_scale=-0.1, init_sigma=0.001,
73+
positive_example_weight_mult=0.1, epochs=1, use_bias=True, num_models=5,
74+
num_calibration_samples=6, init_method='uniform', init_scale=0.1, init_sigma=0.001,
7575
init_bias=0, optimizer='sgd', loss='logistic', wd=0.4, l1=0.04, momentum=0.1,
7676
learning_rate=0.001, beta_1=0.2, beta_2=0.03, bias_lr_mult=5.5, bias_wd_mult=6.6,
7777
use_lr_scheduler=False, lr_scheduler_step=2, lr_scheduler_factor=0.03,
7878
lr_scheduler_minimum_lr=0.001, normalize_data=False, normalize_label=True,
79-
unbias_data=True, unbias_label=False, num_point_for_scaler=3,
80-
**ALL_REQ_ARGS)
79+
unbias_data=True, unbias_label=False, num_point_for_scaler=3, margin=1.0,
80+
quantile=0.5, loss_insensitivity=0.1, huber_delta=0.1, early_stopping_patience=3,
81+
early_stopping_tolerance=0.001, **ALL_REQ_ARGS)
8182

8283
assert lr.hyperparameters() == dict(
8384
predictor_type='binary_classifier', binary_classifier_model_selection_criteria='accuracy',
84-
target_recall='0.5', target_precision='0.6', epochs='1',
85+
target_recall='0.5', target_precision='0.6', positive_example_weight_mult='0.1', epochs='1',
8586
use_bias='True', num_models='5', num_calibration_samples='6', init_method='uniform',
86-
init_scale='-0.1', init_sigma='0.001', init_bias='0.0', optimizer='sgd', loss='logistic',
87+
init_scale='0.1', init_sigma='0.001', init_bias='0.0', optimizer='sgd', loss='logistic',
8788
wd='0.4', l1='0.04', momentum='0.1', learning_rate='0.001', beta_1='0.2', beta_2='0.03',
8889
bias_lr_mult='5.5', bias_wd_mult='6.6', use_lr_scheduler='False', lr_scheduler_step='2',
8990
lr_scheduler_factor='0.03', lr_scheduler_minimum_lr='0.001', normalize_data='False',
90-
normalize_label='True', unbias_data='True', unbias_label='False', num_point_for_scaler='3',
91+
normalize_label='True', unbias_data='True', unbias_label='False', num_point_for_scaler='3', margin='1.0',
92+
quantile='0.5', loss_insensitivity='0.1', huber_delta='0.1', early_stopping_patience='3',
93+
early_stopping_tolerance='0.001',
9194
)
9295

9396

@@ -150,7 +153,13 @@ def test_iterable_hyper_parameters_type(sagemaker_session, iterable_hyper_parame
150153
('lr_scheduler_step', 'string'),
151154
('lr_scheduler_factor', 'string'),
152155
('lr_scheduler_minimum_lr', 'string'),
153-
('num_point_for_scaler', 'string')
156+
('num_point_for_scaler', 'string'),
157+
('margin', 'string'),
158+
('quantile', 'string'),
159+
('loss_insensitivity', 'string'),
160+
('huber_delta', 'string'),
161+
('early_stopping_patience', 'string'),
162+
('early_stopping_tolerance', 'string')
154163
])
155164
def test_optional_hyper_parameters_type(sagemaker_session, optional_hyper_parameters, value):
156165
with pytest.raises(ValueError):
@@ -169,31 +178,30 @@ def test_optional_hyper_parameters_type(sagemaker_session, optional_hyper_parame
169178
('num_models', 0),
170179
('num_calibration_samples', 0),
171180
('init_method', 'string'),
172-
('init_scale', -1),
173-
('init_scale', 1),
181+
('init_scale', 0),
174182
('init_sigma', 0),
175-
('init_sigma', 1),
176183
('optimizer', 'string'),
177184
('loss', 'string'),
178-
('wd', 0),
179-
('wd', 1),
180-
('l1', 0),
181-
('l1', 1),
182-
('momentum', 0),
185+
('wd', -1),
186+
('l1', -1),
183187
('momentum', 1),
184188
('learning_rate', 0),
185-
('learning_rate', 1),
186-
('beta_1', 0),
187189
('beta_1', 1),
188-
('beta_2', 0),
189190
('beta_2', 1),
190191
('bias_lr_mult', 0),
191-
('bias_wd_mult', 0),
192+
('bias_wd_mult', -1),
192193
('lr_scheduler_step', 0),
193194
('lr_scheduler_factor', 0),
194195
('lr_scheduler_factor', 1),
195196
('lr_scheduler_minimum_lr', 0),
196-
('num_point_for_scaler', 0)
197+
('num_point_for_scaler', 0),
198+
('margin', -1),
199+
('quantile', 0),
200+
('quantile', 1),
201+
('loss_insensitivity', 0),
202+
('huber_delta', -1),
203+
('early_stopping_patience', 0),
204+
('early_stopping_tolerance', 0)
197205
])
198206
def test_optional_hyper_parameters_value(sagemaker_session, optional_hyper_parameters, value):
199207
with pytest.raises(ValueError):

0 commit comments

Comments
 (0)