Skip to content

Commit

Permalink
Merge pull request #288 from autonomio/dev
Browse files Browse the repository at this point in the history
v.0.5 to Master (ACTUAL)
  • Loading branch information
mikkokotila committed Apr 3, 2019
2 parents 4ccc4e0 + 1e9f96c commit 6a4fbfa
Show file tree
Hide file tree
Showing 41 changed files with 1,143 additions and 401 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -12,3 +12,4 @@ talos.egg-info
*.h5
*.json
*.npy
test.sh
4 changes: 2 additions & 2 deletions setup.py
Expand Up @@ -5,7 +5,7 @@
DESCRIPTION = "Talos Hyperparameter Tuning for Keras"
LONG_DESCRIPTION = """\
Talos radically changes the ordinary Keras workflow by
fullyautomating hyperparameter tuning and model evaluation.
fully automating hyperparameter tuning and model evaluation.
Talos exposes Keras functionality entirely and there is no new
syntax or templates to learn.
"""
Expand All @@ -16,7 +16,7 @@
URL = 'http://autonom.io'
LICENSE = 'MIT'
DOWNLOAD_URL = 'https://github.com/autonomio/talos/'
VERSION = '0.4.9'
VERSION = '0.5.0'

try:
from setuptools import setup
Expand Down
38 changes: 27 additions & 11 deletions talos/__init__.py
Expand Up @@ -6,20 +6,36 @@
from .commands.evaluate import Evaluate
from .commands.restore import Restore
from .commands.autom8 import Autom8
from .commands.params import Params
from .commands.kerasmodel import KerasModel
from . import utils
from . import examples as templates

# other internal imports
from .examples import datasets, params
# the purpose of everything below is to keep the namespace completely clean

# external append imports
import sklearn.metrics as performance
del_from_utils = ['best_model', 'connection_check', 'detector',
'exceptions', 'last_neuron', 'load_model', 'validation_split',
'pred_class', 'results', 'string_cols_to_numeric']

from .utils.connection_check import is_connected
for key in del_from_utils:
if key.startswith('__') is False:
delattr(utils, key)

if is_connected() is True:
import astetik as plots
else:
print("NO INTERNET CONNECTION: Reporting plots will not work.")
template_sub = [templates.datasets,
templates.models,
templates.params,
templates.pipelines]

from kerasplotlib import TrainingLog as live
keep_from_templates = ['iris', 'cervical_cancer', 'titanic', 'breast_cancer',
'icu_mortality']

__version__ = "0.4.9"
for sub in template_sub:
for key in list(sub.__dict__):
if key.startswith('__') is False:
if key not in keep_from_templates:
delattr(sub, key)

del commands, parameters, scan, reducers, model, metrics, key, del_from_utils
del examples, sub, keep_from_templates, template_sub

__version__ = "0.5.0"
1 change: 0 additions & 1 deletion talos/commands/__init__.py
@@ -1 +0,0 @@

26 changes: 20 additions & 6 deletions talos/commands/deploy.py
Expand Up @@ -5,19 +5,33 @@

from ..utils.best_model import best_model, activate_model

# NOTE: this has some overlap with code in evaluate.py
# and needs to be cleaned up.
# TODO: needs to also deploy the hyperparameter configuration
# and some kind of summary of the experiment and then finally
# pack everything into a zip file


class Deploy:

'''Functionality for deploying a model to a filename'''

def __init__(self, scan_object, model_name, metric='val_acc', asc=False):

'''Deploy a model to be used later or in a different system.
NOTE: for a metric that is to be minimized, set asc=True or otherwise
you will end up with the model that has the highest loss.
Deploy() takes in the object from Scan() and creates a package locally
that can be later activated with Restore().
scan_object : object
The object that is returned from Scan() upon completion.
model_name : str
Name for the .zip file to be created.
metric : str
The metric to be used for picking the best model.
asc: bool
Make this True for metrics that are to be minimized (e.g. loss) ,
and False when the metric is to be maximized (e.g. acc)
'''

self.scan_object = scan_object
os.mkdir(model_name)
self.path = model_name + '/' + model_name
Expand Down
16 changes: 10 additions & 6 deletions talos/commands/evaluate.py
Expand Up @@ -36,19 +36,21 @@ def evaluate(self, x, y,
y : array
The ground truth for x
model_id : int
It's possible to evaluate a specific model based on ID. Can be None.
It's possible to evaluate a specific model based on ID.
Can be None.
folds : int
Number of folds to use for cross-validation
sort_metric : string
A column name referring to the metric that was used in the scan_object
as a performance metric. This is used for sorting the results to pick
for evaluation.
A column name referring to the metric that was used in the
scan_object as a performance metric. This is used for sorting
the results to pick for evaluation.
shuffle : bool
Data is shuffled before evaluation.
mode : string
'binary', 'multi_class', 'multi_label', or 'regression'.
asc : bool
False if the metric is to be optimized upwards (e.g. accuracy or f1_score)
False if the metric is to be optimized upwards
(e.g. accuracy or f1_score)
print_out : bool
Print out the results.
Expand Down Expand Up @@ -78,7 +80,9 @@ def evaluate(self, x, y,

if mode == 'multi_label':
y_pred = model.predict(kx[i]).argmax(axis=1)
scores = f1_score(y_pred, ky[i].argmax(axis=1), average='macro')
scores = f1_score(y_pred,
ky[i].argmax(axis=1),
average='macro')

elif mode == 'regression':
y_pred = model.predict(kx[i])
Expand Down
92 changes: 92 additions & 0 deletions talos/commands/kerasmodel.py
@@ -0,0 +1,92 @@
import numpy as np

from talos.model.layers import hidden_layers
from talos.model.normalizers import lr_normalizer

from keras.models import Sequential
from keras.layers import Dropout, Flatten
from keras.layers import LSTM, Conv1D, SimpleRNN, Dense, Bidirectional

try:
from wrangle.reshape_to_conv1d import reshape_to_conv1d as array_reshape_conv1d
except ImportError:
from wrangle import array_reshape_conv1d


class KerasModel:

def __init__(self):

'''An input model for Scan(). Optimized for being used together with
Params(). For example:
Scan(x=x, y=y, params=Params().params, model=KerasModel().model)
NOTE: the grid from Params() is very large, so grid_downsample or
round_limit accordingly in Scan().
'''

self.model = self._create_input_model

def _create_input_model(self, x_train, y_train, x_val, y_val, params):

model = Sequential()

if params['network'] != 'dense':
x_train = array_reshape_conv1d(x_train)
x_val = array_reshape_conv1d(x_val)

if params['network'] == 'conv1d':
model.add(Conv1D(params['first_neuron'], x_train.shape[1]))
model.add(Flatten())

elif params['network'] == 'lstm':
model.add(LSTM(params['first_neuron']))

if params['network'] == 'bidirectional_lstm':
model.add(Bidirectional(LSTM(params['first_neuron'])))

elif params['network'] == 'simplernn':
model.add(SimpleRNN(params['first_neuron']))

elif params['network'] == 'dense':
model.add(Dense(params['first_neuron'],
input_dim=x_train.shape[1],
activation='relu'))

model.add(Dropout(params['dropout']))

# add hidden layers to the model
hidden_layers(model, params, 1)

# output layer (this is scetchy)
try:
last_neuron = y_train.shape[1]
except IndexError:
if len(np.unique(y_train)) == 2:
last_neuron = 1
else:
last_neuron = len(np.unique(y_train))

model.add(Dense(last_neuron,
activation=params['last_activation']))

# bundle the optimizer with learning rate changes
optimizer = params['optimizer'](lr=lr_normalizer(params['lr'],
params['optimizer']))

# compile the model
model.compile(optimizer=optimizer,
loss=params['losses'],
metrics=['acc'])

# fit the model
out = model.fit(x_train, y_train,
batch_size=params['batch_size'],
epochs=params['epochs'],
verbose=0,
validation_data=[x_val, y_val])

# pass the output to Talos
return out, model

0 comments on commit 6a4fbfa

Please sign in to comment.