Skip to content

Commit

Permalink
Fix broken tensorflow based models due to deprecated Keras component (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jteijema committed Jul 17, 2023
1 parent 726d8ca commit 36a924b
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 193 deletions.
108 changes: 45 additions & 63 deletions asreview/models/classifiers/lstm_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Embedding
from tensorflow.keras.models import Sequential
from tensorflow.keras.wrappers.scikit_learn import KerasClassifier
except ImportError:
TF_AVAILABLE = False
else:
Expand All @@ -31,7 +30,8 @@
except AttributeError:
logging.getLogger("tensorflow").setLevel(logging.ERROR)

from scipy.sparse import isspmatrix
import numpy as np
import scipy

from asreview.models.classifiers.base import BaseTrainClassifier
from asreview.models.classifiers.utils import _set_class_weight
Expand Down Expand Up @@ -124,13 +124,13 @@ def fit(self, X, y):
# check is tensorflow is available
_check_tensorflow()

if isspmatrix(X):
if scipy.sparse.isspmatrix(X):
X = X.toarray()

sequence_length = X.shape[1]
if self._model is None or sequence_length != self.sequence_length:
self.sequence_length = sequence_length
keras_model = _create_lstm_base_model(
self._model = _create_lstm_base_model(
embedding_matrix=self.embedding_matrix,
backwards=self.backwards,
dropout=self.dropout,
Expand All @@ -141,8 +141,6 @@ def fit(self, X, y):
learn_rate=self.learn_rate,
verbose=self.verbose,
)
print(keras_model)
self._model = KerasClassifier(keras_model, verbose=self.verbose)

self._model.fit(
X,
Expand All @@ -155,24 +153,11 @@ def fit(self, X, y):
)

def predict_proba(self, X):
"""Get the inclusion probability for each sample.
Arguments
---------
X: numpy.ndarray
Feature matrix to predict.
Returns
-------
numpy.ndarray
Array with the probabilities for each class, with two
columns (class 0, and class 1) and the number of samples rows.
"""

if isspmatrix(X):
if scipy.sparse.issparse(X):
X = X.toarray()

return self._model.predict_proba(X)
pos_pred = self._model.predict(X, verbose=self.verbose)
neg_pred = 1 - pos_pred
return np.hstack([neg_pred, pos_pred])

def full_hyper_space(self):
from hyperopt import hp
Expand Down Expand Up @@ -216,55 +201,52 @@ def _create_lstm_base_model(
# check is tensorflow is available
_check_tensorflow()

def model_wrapper():
model = Sequential()

# add first embedding layer with pretrained wikipedia weights
model.add(
Embedding(
embedding_matrix.shape[0],
embedding_matrix.shape[1],
weights=[embedding_matrix],
input_length=max_sequence_length,
trainable=False,
)
)
model = Sequential()

# add LSTM layer
model.add(
LSTM(
lstm_out_width,
input_shape=(max_sequence_length,),
go_backwards=backwards,
dropout=dropout,
recurrent_dropout=dropout,
)
# add first embedding layer with pretrained wikipedia weights
model.add(
Embedding(
embedding_matrix.shape[0],
embedding_matrix.shape[1],
weights=[embedding_matrix],
input_length=max_sequence_length,
trainable=False,
)

# add Dense layer with relu activation
model.add(
Dense(
dense_width,
activation="relu",
)
)

# add LSTM layer
model.add(
LSTM(
lstm_out_width,
input_shape=(max_sequence_length,),
go_backwards=backwards,
dropout=dropout,
recurrent_dropout=dropout,
)
)

# add Dense layer
model.add(Dense(1, activation="sigmoid"))
# add Dense layer with relu activation
model.add(
Dense(
dense_width,
activation="relu",
)
)

optimizer_fn = _get_optimizer(optimizer, learn_rate)
# add Dense layer
model.add(Dense(1, activation="sigmoid"))

# Compile model
model.compile(
loss="binary_crossentropy", optimizer=optimizer_fn, metrics=["acc"]
)
optimizer_fn = _get_optimizer(optimizer, learn_rate)

if verbose >= 1:
model.summary(verbose=verbose)
# Compile model
model.compile(
loss="binary_crossentropy", optimizer=optimizer_fn, metrics=["acc"]
)

return model
if verbose >= 1:
model.summary(verbose=verbose)

return model_wrapper
return model


def _get_optimizer(optimizer, lr_mult=1.0):
Expand Down
110 changes: 47 additions & 63 deletions asreview/models/classifiers/lstm_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import MaxPooling1D
from tensorflow.keras.models import Sequential
from tensorflow.keras.wrappers.scikit_learn import KerasClassifier
except ImportError:
TF_AVAILABLE = False
else:
Expand All @@ -33,7 +32,8 @@
except AttributeError:
logging.getLogger("tensorflow").setLevel(logging.ERROR)

from scipy.sparse import isspmatrix
import numpy as np
import scipy

from asreview.models.classifiers.base import BaseTrainClassifier
from asreview.models.classifiers.lstm_base import _get_optimizer
Expand Down Expand Up @@ -128,13 +128,13 @@ def fit(self, X, y):
# check is tensorflow is available
_check_tensorflow()

if isspmatrix(X):
if scipy.sparse.isspmatrix(X):
X = X.toarray()

sequence_length = X.shape[1]
if self._model is None or sequence_length != self.sequence_length:
self.sequence_length = sequence_length
keras_model = _create_lstm_pool_model(
self._model = _create_lstm_pool_model(
embedding_matrix=self.embedding_matrix,
backwards=self.backwards,
dropout=self.dropout,
Expand All @@ -144,7 +144,7 @@ def fit(self, X, y):
learn_rate=self.learn_rate,
verbose=self.verbose,
)
self._model = KerasClassifier(keras_model, verbose=self.verbose)

self._model.fit(
X,
y,
Expand All @@ -156,24 +156,11 @@ def fit(self, X, y):
)

def predict_proba(self, X):
"""Get the inclusion probability for each sample.
Arguments
---------
X: numpy.ndarray
Feature matrix to predict.
Returns
-------
numpy.ndarray
Array with the probabilities for each class, with two
columns (class 0, and class 1) and the number of samples rows.
"""

if isspmatrix(X):
if scipy.sparse.isspmatrix(X):
X = X.toarray()

return self._model.predict_proba(X)
pos_pred = self._model.predict(X, verbose=self.verbose)
neg_pred = 1 - pos_pred
return np.hstack([neg_pred, pos_pred])

def full_hyper_space(self):
from hyperopt import hp
Expand Down Expand Up @@ -219,53 +206,50 @@ def _create_lstm_pool_model(

# The Sklearn API requires a callable as result.
# https://keras.io/scikit-learn-api/
def model_wrapper():
model = Sequential()

# add first embedding layer with pretrained wikipedia weights
model.add(
Embedding(
embedding_matrix.shape[0],
embedding_matrix.shape[1],
weights=[embedding_matrix],
input_length=max_sequence_length,
trainable=False,
)
model = Sequential()

# add first embedding layer with pretrained wikipedia weights
model.add(
Embedding(
embedding_matrix.shape[0],
embedding_matrix.shape[1],
weights=[embedding_matrix],
input_length=max_sequence_length,
trainable=False,
)

# add LSTM layer
model.add(
LSTM(
lstm_out_width,
input_shape=(max_sequence_length,),
go_backwards=backwards,
dropout=dropout,
recurrent_dropout=dropout,
return_sequences=True,
kernel_constraint=MaxNorm(),
)
)

# add LSTM layer
model.add(
LSTM(
lstm_out_width,
input_shape=(max_sequence_length,),
go_backwards=backwards,
dropout=dropout,
recurrent_dropout=dropout,
return_sequences=True,
kernel_constraint=MaxNorm(),
)
)

model.add(
MaxPooling1D(
pool_size=lstm_pool_size,
)
model.add(
MaxPooling1D(
pool_size=lstm_pool_size,
)
model.add(Flatten())
)
model.add(Flatten())

# Add output layer
model.add(Dense(1, activation="sigmoid"))
# Add output layer
model.add(Dense(1, activation="sigmoid"))

optimizer_fn = _get_optimizer(optimizer, learn_rate)

# Compile model
model.compile(
loss="binary_crossentropy", optimizer=optimizer_fn, metrics=["acc"]
)
optimizer_fn = _get_optimizer(optimizer, learn_rate)

if verbose >= 1:
model.summary()
# Compile model
model.compile(
loss="binary_crossentropy", optimizer=optimizer_fn, metrics=["acc"]
)

return model
if verbose >= 1:
model.summary()

return model_wrapper
return model

0 comments on commit 36a924b

Please sign in to comment.