Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
amaiya committed Jun 10, 2020
2 parents ef8c5bf + 9e2b371 commit 3228f33
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 24 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ Most recent releases are shown at the top. Each release shows:
- **Fixed**: Bug fixes that don't change documented behaviour


## 0.16.3 (2020-06-10)

### New:
- added `metrics` parameter to `text.text_classifier` and `text.text_regression_model` functions
- added `metrics` parameter to `Transformer.get_classifier` and `Transformer.get_regrssion_model` methods

### Changed
- `metric` parameter in `vision.image_classifier` and `vision.image_regression_model` functions changed to `metrics`

### Fixed:
- N/A


## 0.16.2 (2020-06-07)

### New:
Expand Down
17 changes: 10 additions & 7 deletions ktrain/text/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def calc_r(y_i, x, y):
return np.log(calc_pr(y_i, x, y, True) / calc_pr(y_i, x, y, False))


def _text_model(name, train_data, preproc=None, multilabel=None, classification=True, verbose=1):
def _text_model(name, train_data, preproc=None, multilabel=None, classification=True, metrics=['accuracy'], verbose=1):
"""
Build and return a text classification or text regression model.
Expand All @@ -73,6 +73,7 @@ def _text_model(name, train_data, preproc=None, multilabel=None, classification=
If None, multilabel will be inferred from data.
classification(bool): If True, will build a text classificaton model.
Otherwise, a text regression model will be returned.
metrics(list): list of metrics to use
verbose (boolean): verbosity of output
Return:
model (Model): A Keras Model instance
Expand Down Expand Up @@ -103,7 +104,7 @@ def _text_model(name, train_data, preproc=None, multilabel=None, classification=
raise ValueError('you preprocessed for %s but want to build a %s model' % (preproc.name, name))

if not classification: # regression
metrics=['mae']
if metrics is None or metrics==['accuracy']: metrics=['mae']
num_classes = 1
multilabel = False
loss_func = 'mse'
Expand All @@ -113,7 +114,7 @@ def _text_model(name, train_data, preproc=None, multilabel=None, classification=
maxlen = U.shape_from_data(train_data)[1]
U.vprint('maxlen is %s' % (maxlen), verbose=verbose)
else: # classification
metrics = ['accuracy']
if metrics is None: metrics = ['accuracy']
# set number of classes and multilabel flag
num_classes = U.nclasses_from_data(train_data)

Expand Down Expand Up @@ -436,7 +437,7 @@ def _build_bigru(num_classes,



def text_classifier(name, train_data, preproc=None, multilabel=None, verbose=1):
def text_classifier(name, train_data, preproc=None, multilabel=None, metrics=['accuracy'], verbose=1):
"""
Build and return a text classification model.
Expand All @@ -456,6 +457,7 @@ def text_classifier(name, train_data, preproc=None, multilabel=None, verbose=1):
multilabel (bool): If True, multilabel model will be returned.
If false, binary/multiclass model will be returned.
If None, multilabel will be inferred from data.
metrics(list): metrics to use
verbose (boolean): verbosity of output
Return:
model (Model): A Keras Model instance
Expand All @@ -465,10 +467,10 @@ def text_classifier(name, train_data, preproc=None, multilabel=None, verbose=1):
if preproc is not None and not preproc.get_classes():
raise ValueError('preproc.get_classes() is empty, but required for text classification')
return _text_model(name, train_data, preproc=preproc,
multilabel=multilabel, classification=True, verbose=verbose)
multilabel=multilabel, classification=True, metrics=metrics, verbose=verbose)


def text_regression_model(name, train_data, preproc=None, verbose=1):
def text_regression_model(name, train_data, preproc=None, metrics=['mae'], verbose=1):
"""
Build and return a text regression model.
Expand All @@ -484,6 +486,7 @@ def text_regression_model(name, train_data, preproc=None, verbose=1):
train_data (tuple): a tuple of numpy.ndarrays: (x_train, y_train)
preproc: a ktrain.text.TextPreprocessor instance.
As of v0.8.0, this is required.
metrics(list): metrics to use
verbose (boolean): verbosity of output
Return:
model (Model): A Keras Model instance
Expand All @@ -493,4 +496,4 @@ def text_regression_model(name, train_data, preproc=None, verbose=1):
if preproc is not None and preproc.get_classes():
raise ValueError('preproc.get_classes() is supposed to be empty for text regression tasks')
return _text_model(name, train_data, preproc=preproc,
multilabel=False, classification=False, verbose=verbose)
multilabel=False, classification=False, metrics=metrics, verbose=verbose)
17 changes: 12 additions & 5 deletions ktrain/text/preprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -919,15 +919,16 @@ def _load_pretrained(self, mname, num_labels):



def get_classifier(self, fpath=None, multilabel=None):
def get_classifier(self, fpath=None, multilabel=None, metrics=['accuracy']):
"""
creates a model for classification
creates a model for text classification
Args:
fpath(str): optional path to saved pretrained model. Typically left as None.
multilabel(bool): If None, multilabel status is discovered from data [recommended].
If True, model will be forcibly configured for multilabel task.
If False, model will be forcibly configured for non-multilabel task.
It is recommended to leave this as None.
metrics(list): metrics to use
"""
self.check_trained()
if not self.get_classes():
Expand All @@ -953,11 +954,17 @@ def get_classifier(self, fpath=None, multilabel=None):
loss_fn = keras.losses.CategoricalCrossentropy(from_logits=True)
model.compile(loss=loss_fn,
optimizer=U.DEFAULT_OPT,
metrics=['accuracy'])
metrics=metrics)
return model


def get_regression_model(self, fpath=None):
def get_regression_model(self, fpath=None, metrics=['mae']):
"""
creates a model for text regression
Args:
fpath(str): optional path to saved pretrained model. Typically left as None.
metrics(list): metrics to use
"""
self.check_trained()
if self.get_classes():
warnings.warn('class labels were provided - treating as classification problem')
Expand All @@ -968,7 +975,7 @@ def get_regression_model(self, fpath=None):
loss_fn = 'mse'
model.compile(loss=loss_fn,
optimizer=U.DEFAULT_OPT,
metrics=['mae'])
metrics=metrics)
return model


Expand Down
2 changes: 1 addition & 1 deletion ktrain/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__all__ = ['__version__']
__version__ = '0.16.2'
__version__ = '0.16.3'
22 changes: 11 additions & 11 deletions ktrain/vision/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def image_classifier(name,
train_data,
val_data=None,
freeze_layers=None,
metric='accuracy',
metrics=['accuracy'],
optimizer_name = U.DEFAULT_OPT,
multilabel=None,
multigpu_number=None,
Expand All @@ -95,7 +95,7 @@ def image_classifier(name,
freeze_layers (int): number of beginning layers to make untrainable
If None, then all layers except new Dense layers
will be frozen/untrainable.
metric (string): metric to use
metrics (list): metrics to use
optimizer_name(str): name of Keras optimizer (e.g., 'adam', 'sgd')
multilabel(bool): If True, model will be build to support
multilabel classificaiton (labels are not mutually exclusive).
Expand All @@ -118,7 +118,7 @@ def image_classifier(name,
"""
return image_model(name, train_data, val_data=val_data, freeze_layers=freeze_layers,
metric=metric, optimizer_name=optimizer_name, multilabel=multilabel,
metrics=metrics, optimizer_name=optimizer_name, multilabel=multilabel,
multigpu_number=multigpu_number,
pt_fc=pt_fc, pt_ps=pt_ps, verbose=verbose)

Expand All @@ -129,7 +129,7 @@ def image_regression_model(name,
train_data,
val_data=None,
freeze_layers=None,
metric='mae',
metrics=['mae'],
optimizer_name = U.DEFAULT_OPT,
multigpu_number=None,
pt_fc = [],
Expand All @@ -149,7 +149,7 @@ def image_regression_model(name,
freeze_layers (int): number of beginning layers to make untrainable
If None, then all layers except new Dense layers
will be frozen/untrainable.
metric (string): metric to use
metrics (list): metrics to use
optimizer_name(str): name of Keras optimizer (e.g., 'adam', 'sgd')
multilabel(bool): If True, model will be build to support
multilabel classificaiton (labels are not mutually exclusive).
Expand All @@ -174,7 +174,7 @@ def image_regression_model(name,


return image_model(name, train_data, val_data=val_data, freeze_layers=freeze_layers,
metric=metric, optimizer_name=optimizer_name, multilabel=False,
metrics=metrics, optimizer_name=optimizer_name, multilabel=False,
multigpu_number=multigpu_number,
pt_fc=pt_fc, pt_ps=pt_ps, verbose=verbose)

Expand All @@ -184,7 +184,7 @@ def image_model( name,
train_data,
val_data=None,
freeze_layers=None,
metric='accuracy',
metrics=['accuracy'],
optimizer_name = U.DEFAULT_OPT,
multilabel=None,
multigpu_number=None,
Expand All @@ -205,7 +205,7 @@ def image_model( name,
freeze_layers (int): number of beginning layers to make untrainable
If None, then all layers except new Dense layers
will be frozen/untrainable.
metric (string): metric to use
metrics (list): metrics to use
optimizer_name(str): name of Keras optimizer (e.g., 'adam', 'sgd')
multilabel(bool): If True, model will be build to support
multilabel classificaiton (labels are not mutually exclusive).
Expand Down Expand Up @@ -278,7 +278,7 @@ def image_model( name,
elif is_regression:
loss_func = 'mse'
activation = None
if metric == 'accuracy': metric = 'mae'
if metrics == ['accuracy']: metrics = ['mae']

U.vprint("Is Multi-Label? %s" % (multilabel), verbose=verbose)
U.vprint("Is Regression? %s" % (is_regression), verbose=verbose)
Expand Down Expand Up @@ -306,7 +306,7 @@ def image_model( name,
pt_ps = pt_ps)
parallel_model = multi_gpu_model(model, gpus=multigpu_number)
parallel_model.compile(optimizer=optimizer_name,
loss='categorical_crossentropy', metrics=[metric])
loss='categorical_crossentropy', metrics=metrics)
return parallel_model
else:
model = build_visionmodel(name,
Expand All @@ -316,7 +316,7 @@ def image_model( name,
activation=activation,
pt_fc = pt_fc,
pt_ps = pt_ps)
model.compile(optimizer=optimizer_name, loss=loss_func, metrics=[metric])
model.compile(optimizer=optimizer_name, loss=loss_func, metrics=metrics)
return model


Expand Down

0 comments on commit 3228f33

Please sign in to comment.