keras icon indicating copy to clipboard operation
keras copied to clipboard

TypeError: can't pickle _thread.RLock objects when using KerasClassifier with Keras and RandomizedSearchCV

Open leweex95 opened this issue 3 years ago • 3 comments

I created a simple neural network for binary spam/ham text classification using pretrained BERT transformer. Now I want to apply randomized search for tuning the hyperparameters. For now the only hyperparameter I would like to tune is the dropout regularization probability.

I set up a sklearn pipeline with scikeras's KerasClassifier that contains my custom build_sequential_nn() method. When merely fitting the pipeline, everything is fine; however, when I pass the pipeline into a sklearn RandomizedSearchCV, the following error message pops up:

TypeError: can't pickle _thread.RLock objects

Full error message will be detailed at the end of the post.

A full reproducible code is as follows, including sample data:

import numpy as np
import pandas as pd 

import sklearn 
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import Pipeline
from sklearn.model_selection import RandomizedSearchCV

from scikeras.wrappers import KerasClassifier

import tensorflow_hub as hub 
import tensorflow as tf 
import tensorflow_text
from tensorflow.keras.layers import Input, Dropout, Dense


class BertPreprocessor(TransformerMixin, BaseEstimator):
    def __init__(self, preprocessor_model):
        super().__init__()
        self.preprocessor_model = preprocessor_model
    def fit(self, X=None, y=None):
        return self 
    def transform(self, X, y=None):
        return self.preprocessor_model(X)

class BertEncoder(TransformerMixin, BaseEstimator):
    def __init__(self, encoder_model):
        super().__init__()
        self.encoder_model = encoder_model
    def fit(self, X=None, y=None):
        return self
    def transform(self, X, y=None):
        return pd.DataFrame(self.encoder_model(X)['pooled_output'])

def build_nn_sequential(dropout_prob=0.1, epochs=10): 
    model = Sequential()
    model.add(Input(shape=768, name='bert_pooled_output'))
    model.add(Dropout(dropout_prob, name='dropout'))
    model.add(Dense(1, activation='sigmoid', name='classification_output'))

    metrics_list = [
        tf.keras.metrics.AUC(name='auc'),
        tf.keras.metrics.BinaryAccuracy(name='accuracy')
    ]
    model.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = metrics_list)
    return model

# Automatically fetch BERT preprocessor and encoder
bert_encoder_url = "https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/4"
bert_preprocessor_url = "https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3"
bert_preprocessor_model = hub.KerasLayer(bert_preprocessor_url)
bert_encoder_model = hub.KerasLayer(bert_encoder_url)

# Get train data 
df = pd.read_json(...)   # see data also below

X_train_ = df['comment_text']
y_train_ = df['label']

pipe = Pipeline([
    ('preprocess', BertPreprocessor(bert_preprocessor_model)),
    ('encode', BertEncoder(bert_encoder_model)),
    ('model', KerasClassifier(build_fn=build_nn_sequential)),
])

# pipe.fit(X_train_, y_train_)    # This evaluates fine! 

search_spaces = ({
    'model__dropout_prob': np.logspace(np.log10(0.05), np.log10(0.67), 10),
    'model__epochs': [10, 20, 30],
})

search = RandomizedSearchCV(
    estimator=pipe,
    param_distributions=search_spaces, 
    scoring='roc_auc',
    cv=3, 
    verbose=0
).fit(X_train_, y_train_)   # <--- row where error pops up

Sample data:

df = pd.read_json('{"comment_text":{"0":"problem wanted say problem trying redirect event schedule pakistan NUMBERTAG NUMBERTAG pakistan mother fucker boy want married sister ohhhh love sister boob hmmmmm yummyy","1":"get life fucking loser question ask ask katie goulet picture","2":"cum drinker hey wat nigga thought u could ban took long cuz wa busy az hell recently ill keep cumming back take word cumdrinker","3":"liar liar pant fire seriously looked contribution tennis portal page tennis page ha descussion ever please lie NUMBERTAG NUMBERTAG NUMBERTAG NUMBERTAG","4":"stop writing p nothing discus given lack bsinc education diplomacy","5":"wa fucking page one edit page","6":"question mad gay","7":"warning page nerd please leave one stay girl though pleeeeeeeeeeeeeaaaaaaaaaaaaaaaaaaaaaassssssssssssssssseeeeeeeeeeeee NUMBERTAG oneoneoneoneoneoneoneoneoneoneoenone","8":"full shit","9":"go fuck conrad black cheated thousand people pension anyone defends hm asshole apologist evil","10":"list office bearer national union student australia wp userfy userfied page located","11":"talk history scottish national party claim spying hi sentence someone belief npov claim mean someone belief npov claim","12":"section meant vice review btw magazine website writer name attached also like richardwilson NUMBERTAG even know question ninjarobotpirate wa responding happy criticise answer \\u2026 \\u2026 btw NUMBERTAG far know none editor either albanian croatian maybe airplane vision quite good think take care","13":"next time subtweet","14":"physicsyo yo yo dog","15":"self censorship tv show might might notable tv pre empted breaking news notable happens time","16":"article contains information soursed huddersfield aa street street","17":"utc onto something centrifugal force experienced mass exhibiting inertia result tiny little bullet hitting side ride merry go round rueda puthoff haisch described zero point field electronic lorenz equation coupling inertial frame reference give mass inertial reluctance rather resistance enable describe change velocity direction compare ac v dc tesla v edison NUMBERTAG NUMBERTAG NUMBERTAG june NUMBERTAG","18":"meant wa meant state either unblock create new account rendering block useless simple","19":"NUMBERTAG utc hi NUMBERTAG must mistakenly thought ian wa original member b c always viewed band definitive axeman NUMBERTAG yeah almost bought akai headrush looper year ago notorious role cab one guitarist recording settled bos loop station instead rather headrush boomerang due two reliability price issue respectively check hovercraft southpacific auburn lull kind hallucinitory guitar looping thought cab new lineup wa incredible saw NUMBERTAG skipped classic lineup NUMBERTAG compare two performance wise best NUMBERTAG NUMBERTAG NUMBERTAG may"},"label":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0}}')

Full error message:

TypeError                                 Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_18240\1200168424.py in <module>
     63     cv=3,
     64     verbose=0
---> 65 ).fit(X_train_, y_train_)
     66 
     67 # print(f"Best model parameters: {search.best_params_}, best score {search.best_score_}.")

~\AppData\Local\Programs\Python\Python37\lib\site-packages\skopt\searchcv.py in fit(self, X, y, groups, callback, **fit_params)
    464             self.optimizer_kwargs_ = dict(self.optimizer_kwargs)
    465 
--> 466         super().fit(X=X, y=y, groups=groups, **fit_params)
    467 
    468         # BaseSearchCV never ranked train scores,

~\AppData\Local\Programs\Python\Python37\lib\site-packages\sklearn\model_selection\_search.py in fit(self, X, y, groups, **fit_params)
    803         n_splits = cv_orig.get_n_splits(X, y, groups)
    804 
--> 805         base_estimator = clone(self.estimator)
    806 
    807         parallel = Parallel(n_jobs=self.n_jobs, pre_dispatch=self.pre_dispatch)

~\AppData\Local\Programs\Python\Python37\lib\site-packages\sklearn\base.py in clone(estimator, safe)
     84     new_object_params = estimator.get_params(deep=False)
     85     for name, param in new_object_params.items():
---> 86         new_object_params[name] = clone(param, safe=False)
     87     new_object = klass(**new_object_params)
     88     params_set = new_object.get_params(deep=False)

~\AppData\Local\Programs\Python\Python37\lib\site-packages\sklearn\base.py in clone(estimator, safe)
     62     # XXX: not handling dictionaries
     63     if estimator_type in (list, tuple, set, frozenset):
---> 64         return estimator_type([clone(e, safe=safe) for e in estimator])
     65     elif not hasattr(estimator, "get_params") or isinstance(estimator, type):
     66         if not safe:

~\AppData\Local\Programs\Python\Python37\lib\site-packages\sklearn\base.py in <listcomp>(.0)
     62     # XXX: not handling dictionaries
     63     if estimator_type in (list, tuple, set, frozenset):
---> 64         return estimator_type([clone(e, safe=safe) for e in estimator])
     65     elif not hasattr(estimator, "get_params") or isinstance(estimator, type):
     66         if not safe:

~\AppData\Local\Programs\Python\Python37\lib\site-packages\sklearn\base.py in clone(estimator, safe)
     62     # XXX: not handling dictionaries
     63     if estimator_type in (list, tuple, set, frozenset):
---> 64         return estimator_type([clone(e, safe=safe) for e in estimator])
     65     elif not hasattr(estimator, "get_params") or isinstance(estimator, type):
     66         if not safe:

~\AppData\Local\Programs\Python\Python37\lib\site-packages\sklearn\base.py in <listcomp>(.0)
     62     # XXX: not handling dictionaries
     63     if estimator_type in (list, tuple, set, frozenset):
---> 64         return estimator_type([clone(e, safe=safe) for e in estimator])
     65     elif not hasattr(estimator, "get_params") or isinstance(estimator, type):
     66         if not safe:

~\AppData\Local\Programs\Python\Python37\lib\site-packages\sklearn\base.py in clone(estimator, safe)
     84     new_object_params = estimator.get_params(deep=False)
     85     for name, param in new_object_params.items():
---> 86         new_object_params[name] = clone(param, safe=False)
     87     new_object = klass(**new_object_params)
     88     params_set = new_object.get_params(deep=False)

~\AppData\Local\Programs\Python\Python37\lib\site-packages\sklearn\base.py in clone(estimator, safe)
     65     elif not hasattr(estimator, "get_params") or isinstance(estimator, type):
     66         if not safe:
---> 67             return copy.deepcopy(estimator)
     68         else:
     69             if isinstance(estimator, type):

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_tuple(x, memo, deepcopy)
    219 
    220 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):
--> 221     y = [deepcopy(a, memo) for a in x]
    222     # We're not going to put the tuple in the memo, but it's still important we
    223     # check for it, in case the tuple contains recursive mutable structures.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in <listcomp>(.0)
    219 
    220 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):
--> 221     y = [deepcopy(a, memo) for a in x]
    222     # We're not going to put the tuple in the memo, but it's still important we
    223     # check for it, in case the tuple contains recursive mutable structures.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_tuple(x, memo, deepcopy)
    219 
    220 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):
--> 221     y = [deepcopy(a, memo) for a in x]
    222     # We're not going to put the tuple in the memo, but it's still important we
    223     # check for it, in case the tuple contains recursive mutable structures.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in <listcomp>(.0)
    219 
    220 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):
--> 221     y = [deepcopy(a, memo) for a in x]
    222     # We're not going to put the tuple in the memo, but it's still important we
    223     # check for it, in case the tuple contains recursive mutable structures.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_list(x, memo, deepcopy)
    214     append = y.append
    215     for a in x:
--> 216         append(deepcopy(a, memo))
    217     return y
    218 d[list] = _deepcopy_list

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_tuple(x, memo, deepcopy)
    219 
    220 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):
--> 221     y = [deepcopy(a, memo) for a in x]
    222     # We're not going to put the tuple in the memo, but it's still important we
    223     # check for it, in case the tuple contains recursive mutable structures.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in <listcomp>(.0)
    219 
    220 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):
--> 221     y = [deepcopy(a, memo) for a in x]
    222     # We're not going to put the tuple in the memo, but it's still important we
    223     # check for it, in case the tuple contains recursive mutable structures.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_list(x, memo, deepcopy)
    214     append = y.append
    215     for a in x:
--> 216         append(deepcopy(a, memo))
    217     return y
    218 d[list] = _deepcopy_list

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_tuple(x, memo, deepcopy)
    219 
    220 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):
--> 221     y = [deepcopy(a, memo) for a in x]
    222     # We're not going to put the tuple in the memo, but it's still important we
    223     # check for it, in case the tuple contains recursive mutable structures.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in <listcomp>(.0)
    219 
    220 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):
--> 221     y = [deepcopy(a, memo) for a in x]
    222     # We're not going to put the tuple in the memo, but it's still important we
    223     # check for it, in case the tuple contains recursive mutable structures.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_tuple(x, memo, deepcopy)
    219 
    220 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):
--> 221     y = [deepcopy(a, memo) for a in x]
    222     # We're not going to put the tuple in the memo, but it's still important we
    223     # check for it, in case the tuple contains recursive mutable structures.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in <listcomp>(.0)
    219 
    220 def _deepcopy_tuple(x, memo, deepcopy=deepcopy):
--> 221     y = [deepcopy(a, memo) for a in x]
    222     # We're not going to put the tuple in the memo, but it's still important we
    223     # check for it, in case the tuple contains recursive mutable structures.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    305             for key, value in dictiter:
    306                 key = deepcopy(key, memo)
--> 307                 value = deepcopy(value, memo)
    308                 y[key] = value
    309         else:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279     if state is not None:
    280         if deep:
--> 281             state = deepcopy(state, memo)
    282         if hasattr(y, '__setstate__'):
    283             y.__setstate__(state)

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~\AppData\Local\Programs\Python\Python37\lib\copy.py in _deepcopy_dict(x, memo, deepcopy)
    239     memo[id(x)] = y
    240     for key, value in x.items():
--> 241         y[deepcopy(key, memo)] = deepcopy(value, memo)
    242     return y
    243 d[dict] = _deepcopy_dict

~\AppData\Local\Programs\Python\Python37\lib\copy.py in deepcopy(x, memo, _nil)
    167                     reductor = getattr(x, "__reduce_ex__", None)
    168                     if reductor:
--> 169                         rv = reductor(4)
    170                     else:
    171                         reductor = getattr(x, "__reduce__", None)

TypeError: can't pickle _thread.RLock objects

Versions:

numpy 1.21.5
pandas 1.3.5.
sklearn 1.0.2.
scikeras 0.6.1.
tensorflow 2.8.0.
tensorflow_text 2.8.1.
tensorflow_hub 0.12.0

Note:

  • A very similar issue was reported in 2020 where the issue was reproducible on TFv2.3 as mentioned in this comment in that thread. However there was no clear solution/workaround provided there, rather this link. Having compared the code snippets provided in that blog post with my code above, I don't see any obvious inconsistencies or mistakes in my solution. Note that the linked blog post is actually only about incorporating a KerasClassifier into a grid/randomized search logic, and not about incorporating an entire sklearn pipeline. This might be important.
  • Another time the same error message was reported here on github was this one. Yet, in this case the reason is seemingly unrelated.
  • In this thread on StackOverflow Marcin Możejko mentions that keras doesn't support parallelization via pickle which would be performed by default by grid/randomized search, and proposed explicitly setting n_jobs=1 to prevent multiprocessing. Makes total sense, I tried, yet I am still getting the same error message.
  • Another bug report from 2020 also mentioned the same issue. Just like before, this was unfortunately also closed without solution. Note however, that in this case too, a pure KerasClassifier model was used and not a sklearn pipeline. Might be relevant.

leweex95 avatar Mar 01 '22 09:03 leweex95

@sachinprasadhs Was able to reproduce this issue on colab using TF v2.8.0 ,please find the gist here.Thanks!

sushreebarsa avatar Mar 02 '22 17:03 sushreebarsa

Hi there, is there any update regarding this issue?

leweex95 avatar Mar 11 '22 18:03 leweex95

Facing same issue - It has sth to do with the keras.metrics.AUC() function because when I only use the tf.keras.metrics.BinaryAccuracy(name='accuracy') it runs fine

darinkist avatar Jun 24 '22 13:06 darinkist

We are no longer maintaining KerasClassifier. Can you please forward this issue to https://github.com/adriangb/scikeras. Thanks!!

gowthamkpr avatar Aug 13 '22 18:08 gowthamkpr

This issue has been automatically marked as stale because it has no recent activity. It will be closed if no further activity occurs. Thank you.

google-ml-butler[bot] avatar Aug 23 '22 18:08 google-ml-butler[bot]

Closing as stale. Please reopen if you'd like to work on this further.

google-ml-butler[bot] avatar Aug 30 '22 19:08 google-ml-butler[bot]

Are you satisfied with the resolution of your issue? Yes No

google-ml-butler[bot] avatar Aug 30 '22 19:08 google-ml-butler[bot]