Información del sistema
¡Hola todos! Esta es mi primera publicación, así que perdóname si me he perdido algo. Así que estoy tratando de usar un algoritmo genético para entrenar y evaluar múltiples arquitecturas NN, así que necesito paralelizarlas en una CPU de múltiples núcleos. Por lo tanto, he usado joblib para intentar paralelizar esto. Sin embargo, estaba atascado en mi código tf.keras porque no era apto para encurtidos. Después de muchas horas de depuración, finalmente me di cuenta de que los modelos tf.keras no se pueden encurtir mientras que los modelos keras sí.
Describe el comportamiento actual
El siguiente código funciona, pero si reemplazó keras con tf.keras, habrá un error:
No se pudo seleccionar la tarea para enviarla a los trabajadores.
Describe el comportamiento esperado
En el futuro, tf.keras debería reemplazar a keras y, por lo tanto, tf.keras también debería ser encurtido.
Código para reproducir el problema
#The following is a simple code to illustrate the problem:
from joblib import Parallel, delayed
import keras
import tensorflow as tf
def test():
model = keras.models.Sequential()
return
Parallel(n_jobs=8)(delayed(test)(i) for i in range(10)) #this works as intended
def test_tf():
model = tf.keras.models.Sequential()
return
Parallel(n_jobs=8)(delayed(test_tf)(i) for i in range(10)) #this will spit out the error above
Otros comentarios
Supongo que una solución rápida sería reemplazar todo el código existente con tf.keras por solo keras, pero dado que el soporte de keras será descontinuado y absorbido por Tensorflow 2.0, creo que esto debería arreglarse.
@ Edwin-Koh1
¿Puede verificar con la versión nocturna ( !pip install tf-nightly==2.1.0dev20191201
) y ver si el error persiste? Hay muchas mejoras de rendimiento en las últimas versiones nocturnas. ¡Gracias!
Cierre automático por falta de actividad reciente. Actualice el problema cuando haya nueva información disponible y volveremos a abrir el problema. ¡Gracias!
@ravikyram sigo viendo este problema en tensorflow == 2.1.0:
import pickle
import tensorflow as tf
def main():
model_1 = tf.keras.Sequential((
tf.keras.layers.Dense(16, activation='relu'),
tf.keras.layers.Dense(1, activation='linear'),
))
_ = model_1(tf.random.uniform((15, 3)))
model_2 = pickle.loads(pickle.dumps(model_1))
for w1, w2 in zip(model_1.get_weights(), model_2.get_weights()):
tf.debugging.assert_equal(w1, w2)
if __name__ == '__main__':
main()
resultados en
Traceback (most recent call last):
File "/Users/hartikainen/conda/envs/softlearning-3/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/Users/hartikainen/conda/envs/softlearning-3/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/Users/hartikainen/github/rail-berkeley/softlearning-3/tests/test_pickle_keras_model.py", line 25, in <module>
main()
File "/Users/hartikainen/github/rail-berkeley/softlearning-3/tests/test_pickle_keras_model.py", line 18, in main
model_2 = pickle.loads(pickle.dumps(model_1))
TypeError: can't pickle weakref objects
$ pip freeze | grep "tf\|tensor"
tensorboard==2.1.0
tensorflow==2.1.0
tensorflow-estimator==2.1.0
tensorflow-probability==0.9.0
$ python --version
Python 3.7.5
Probé colab con TF versión 2.1.0-rc2, 2.2.0-dev20200113 y pude reproducir el problema. Por favor, encuentre la esencia aquí . ¡Gracias!
@ravikyram , ¿deberían los modelos funcionales de keras ser decapables también o no? ¿Asumiría que si los modelos secuenciales son, los modelos funcionales también deberían serlo? ¿O los modelos funcionales tienen algunas propiedades que los hacen más difíciles de encurtir?
$ python -m tests.test_pickle_keras_functional_model
2020-01-17 16:47:08.567598: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2020-01-17 16:47:08.581327: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x7fa0a55aa6c0 initialized for platform Host (this does not guarantee that XLA will be used). Devices:
2020-01-17 16:47:08.581362: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Host, Default Version
Traceback (most recent call last):
File "/Users/hartikainen/conda/envs/softlearning-3/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/Users/hartikainen/conda/envs/softlearning-3/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/Users/hartikainen/github/rail-berkeley/softlearning-3/tests/test_pickle_keras_functional_model.py", line 20, in <module>
main()
File "/Users/hartikainen/github/rail-berkeley/softlearning-3/tests/test_pickle_keras_functional_model.py", line 13, in main
model_2 = pickle.loads(pickle.dumps(model_1))
TypeError: can't pickle _thread.RLock objects
Hola a todos,
Estoy tratando de cambiar de keras
independiente a tensorflow.keras
según la recomendación en https://keras.io/.
Tengo la misma excepción que https://github.com/tensorflow/tensorflow/issues/34697#issuecomment -575705599 con joblib
(que usa pickle
debajo del capó).
Información del sistema:
Guión para reproducir:
import joblib
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
model = Sequential()
model.add(Dense(1, input_dim=42, activation='sigmoid'))
model.compile(optimizer='Nadam', loss='binary_crossentropy', metrics=['accuracy'])
joblib.dump(model, 'model.pkl')
Salida:
TypeError: can't pickle _thread.RLock objects
Aquí hay una solución adaptada de http://zachmoshe.com/2017/04/03/pickling-keras-models.html destinada a resolver el mismo problema cuando los modelos de Keras solían no ser encurtidos.
import pickle
import tempfile
from tensorflow.keras.models import Sequential, load_model, save_model, Model
from tensorflow.keras.layers import Dense
# Hotfix function
def make_keras_picklable():
def __getstate__(self):
model_str = ""
with tempfile.NamedTemporaryFile(suffix='.hdf5', delete=True) as fd:
save_model(self, fd.name, overwrite=True)
model_str = fd.read()
d = {'model_str': model_str}
return d
def __setstate__(self, state):
with tempfile.NamedTemporaryFile(suffix='.hdf5', delete=True) as fd:
fd.write(state['model_str'])
fd.flush()
model = load_model(fd.name)
self.__dict__ = model.__dict__
cls = Model
cls.__getstate__ = __getstate__
cls.__setstate__ = __setstate__
# Run the function
make_keras_picklable()
# Create the model
model = Sequential()
model.add(Dense(1, input_dim=42, activation='sigmoid'))
model.compile(optimizer='Nadam', loss='binary_crossentropy', metrics=['accuracy'])
# Save
with open('model.pkl', 'wb') as f:
pickle.dump(model, f)
@epetrovski ¿Debo llamar a este código cada vez que estoy a punto de seleccionar un modelo o puedo llamarlo al principio de mi aplicación (antes de crear el modelo)?
@epetrovski ¿Debo llamar a este código cada vez que estoy a punto de seleccionar un modelo o puedo llamarlo al principio de mi aplicación (antes de crear el modelo)?
Definitivamente puede llamarlo una vez al comienzo de su aplicación después de importar tensorflow.keras.models.Model
. La ejecución de la función agrega dos métodos nuevos __getstate__()
y __setstate__()
a la clase tensorflow.keras.models.Model
, por lo que debería funcionar cada vez que desee seleccionar un miembro de la clase de modelo tf.keras actualizada - es decir. tu propio modelo.
Aquí hay una alternativa a la respuesta de @epetrovski que no requiere guardar en un archivo:
import pickle
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense
from tensorflow.python.keras.layers import deserialize, serialize
from tensorflow.python.keras.saving import saving_utils
def unpack(model, training_config, weights):
restored_model = deserialize(model)
if training_config is not None:
restored_model.compile(
**saving_utils.compile_args_from_training_config(
training_config
)
)
restored_model.set_weights(weights)
return restored_model
# Hotfix function
def make_keras_picklable():
def __reduce__(self):
model_metadata = saving_utils.model_metadata(self)
training_config = model_metadata.get("training_config", None)
model = serialize(self)
weights = self.get_weights()
return (unpack, (model, training_config, weights))
cls = Model
cls.__reduce__ = __reduce__
# Run the function
make_keras_picklable()
# Create the model
model = Sequential()
model.add(Dense(1, input_dim=42, activation='sigmoid'))
model.compile(optimizer='Nadam', loss='binary_crossentropy', metrics=['accuracy'])
# Save
with open('model.pkl', 'wb') as f:
pickle.dump(model, f)
Fuente: https://docs.python.org/3/library/pickle.html#object.__reduce__
Siento que tal vez esto podría agregarse al modelo. ¿Hay casos en los que esto no funcionaría?
Parece que hay dos atributos que no se pueden seleccionar en la clase Sequential. Esta solución también funcionó para mí:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
class PickableSequential(Sequential):
def __getstate__(self):
state = super().__getstate__()
state.pop("_trackable_saver")
state.pop("_compiled_trainable_state")
return state
model = PickableSequential(Dense(10))
import pickle
pickle.dumps(model)
~
Lo intenté en Colab con TF versión 2.2, versiones nocturnas y pude reproducir el problema. Por favor, encuentre la esencia aquí . ¡Gracias!
Lo intenté en Colab con TF versión 2.2, versiones nocturnas y pude reproducir el problema. Por favor, encuentre la esencia aquí . ¡Gracias!
El modelo de keras se puede seleccionar pero tf.keras no se puede seleccionar, por lo que la solución alternativa para esto es consultar el siguiente código:
Vi su cuaderno de colab e hice los cambios requeridos, solo copie el mismo código que se muestra a continuación y habrá terminado de resolver el error
importar tensorflow como tf
def main ():
modelo_1 = tf.keras.Sequential ((
tf.keras.layers.Dense (16, activación = 'relu'),
tf.keras.layers.Dense (1, activación = 'lineal'),
))
_ = model_1(tf.random.uniform((15, 3)))
model_1.save('model_2.h5')
model_2 = tf.keras.models.load_model('model_2.h5')
for w1, w2 in zip(model_1.get_weights(), model_2.get_weights()):
tf.debugging.assert_equal(w1, w2)
si __name__ == '__main__':
principal()
@ Edwin-Koh1
Según la sugerencia de @lahsrahtidnap, probé en colab y no veo ningún problema. Por favor, encuentre la esencia aquí . ¡Gracias!
Hola a todos,
Estoy tratando de cambiar dekeras
independiente atensorflow.keras
según la recomendación en https://keras.io/.
Estoy haciendo la misma excepción quejoblib
(que usapickle
debajo del capó).Información del sistema:
- Debian 10 (destructor)
- Python 3.7.6
- joblib 0.14.1
- tensorflow 2.1.0
Guión para reproducir:
import joblib from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense model = Sequential() model.add(Dense(1, input_dim=42, activation='sigmoid')) model.compile(optimizer='Nadam', loss='binary_crossentropy', metrics=['accuracy']) joblib.dump(model, 'model.pkl')
Salida:
TypeError: can't pickle _thread.RLock objects
El uso de pickle o joblib no resolverá su problema, ya que tensorflow.keras no admite esto.
Entonces, la solución alternativa para esto es: -
considerando su código: -
reemplace esta línea: - joblib.dump (modelo, 'modelo.pkl')
con: -
para guardar el modelo use: -
-----> model.save ('nuevo_modelo.h5')
y si desea cargar este modelo use: -
-----> nuevo_modelo = tf.keras.models.load_model ('nuevo_modelo.h5')
considerando su código: -
reemplace esta línea: - joblib.dump (modelo, 'modelo.pkl')
con: -
para guardar el modelo use: -
-----> model.save ('nuevo_modelo.h5')
y si desea cargar este modelo use: -
-----> nuevo_modelo = tf.keras.models.load_model ('nuevo_modelo.h5')
Esto funciona en algunos casos, sin embargo, no ayuda cuando un modelo es decapado como parte de otra función, en mi caso esto sucede cuando se usa la biblioteca python multiprocessing
.
@ Edwin-Koh1
¿Sigue siendo un problema?
Por favor, confirma ¡Gracias!
¿Es posible volcar el modelo secuencial de Keras en el contenedor byteIO?
bytes_container = BytesIO()
joblib.dump(Keras_model, bytes_container, protocol=4)
# Error
TypeError: can't pickle _thread.RLock objects
pickle.dump(Keras_model, bytes_container, protocol=4)
# Error
TypeError: can't pickle _thread.RLock objects
dill.dump(Keras_model, bytes_container, protocol=4)
# Error
TypeError: can't pickle tensorflow.python._tf_stack.StackSummary objects
o en un archivo temporal
tempfile.TemporaryFile().write(Keras_model)
o
save_model(Keras_model, bytes_container)
# Error
TypeError: expected str, bytes or os.PathLike object, not _io.BytesIO
Esto funcionó perfectamente, bueno, es posible que no necesite base64, para que lo almacene en la base de datos que hice, todo en la memoria, sin tocar el disco
from io import BytesIO
import dill,base64,tempfile
#Saving Model as base64
model_json = Keras_model.to_json()
def Base64Converter(ObjectFile):
bytes_container = BytesIO()
dill.dump(ObjectFile, bytes_container)
bytes_container.seek(0)
bytes_file = bytes_container.read()
base64File = base64.b64encode(bytes_file)
return base64File
base64KModelJson = Base64Converter(model_json)
base64KModelJsonWeights = Base64Converter(Keras_model.get_weights())
#Loading Back
from joblib import load
from keras.models import model_from_json
def ObjectConverter(base64_File):
loaded_binary = base64.b64decode(base64_File)
loaded_object = tempfile.TemporaryFile()
loaded_object.write(loaded_binary)
loaded_object.seek(0)
ObjectFile = load(loaded_object)
loaded_object.close()
return ObjectFile
modeljson = ObjectConverter(base64KModelJson)
modelweights = ObjectConverter(base64KModelJsonWeights)
loaded_model = model_from_json(modeljson)
loaded_model.set_weights(modelweights)
@hanzigs
Esta es una buena solución, gracias. Solo tenga cuidado si planea continuar entrenando este modelo, ya que este método no conserva el estado del optimizador.
@JohannesAck
Sí, tenemos que compilar con el optimizador antes de ajustar con nuevos datos, eso no debería llevar mucho tiempo.
La otra forma model.save es muy difícil de almacenar en la memoria.
Otra forma es que podemos hacer get_config () y from_config () con inicialización y compilación, luego se debe ajustar para nuevos datos.
@ Edwin-Koh1
Cualquier actualización sobre este tema por favor ¡Gracias!
Este problema se ha marcado automáticamente como obsoleto porque no ha tenido actividad reciente. Se cerrará si no se produce más actividad. Gracias.
considerando su código: -
reemplace esta línea: - joblib.dump (modelo, 'modelo.pkl')
con: -
para guardar el modelo use: -
-----> model.save ('nuevo_modelo.h5')
y si desea cargar este modelo use: -
-----> nuevo_modelo = tf.keras.models.load_model ('nuevo_modelo.h5')Esto funciona en algunos casos, sin embargo, no ayuda cuando un modelo es decapado como parte de otra función, en mi caso esto sucede cuando se usa la biblioteca python
multiprocessing
.
@JohannesAck , creo que podría tener un problema similar. Entreno un modelo de Keras en GPU, lo guardo usando el formato TensorFlow SavedModel usando la API de Keras, lo recargo en una nueva sesión y trato de hacer predicciones en paralelo en múltiples CPU usando la biblioteca multiprocessing
y la biblioteca starmap
función. Si cargo el modelo antes de paralelizar las predicciones, obtengo un error de decapado ( TypeError: can't pickle _thread.RLock objects
). Si cargo el modelo dentro de mi función de predicción cada vez y lo elimino al final de cada llamada de función, se cuelga después de un par de predicciones. ¿Tienes idea de lo que podría estar pasando aquí?
Cerrando como rancio. Vuelva a abrir si desea seguir trabajando en esto.
Esto no es rancio que yo sepa.
El martes, 25 de agosto de 2020 a las 5:26 a. M., Tensorflow-butler [bot] <
[email protected]> escribió:
¿Está satisfecho con la resolución de su problema?
si
https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=Sí&entry.2137816233=https://github349sorflujo
No
https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=No&entry.2137816233=https://github69/tensorflowues-
Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/tensorflow/tensorflow/issues/34697#issuecomment-679941192 ,
o darse de baja
https://github.com/notifications/unsubscribe-auth/AANMPP2EF3PRKBYRYHOHY3TSCOGTXANCNFSM4JSZ4QSA
.
¿Es esto un WONTFIX después de que el problema se haya cerrado ahora?
En mi caso, no puedo simplemente usar model.save()
porque el decapado se realiza desde una herramienta externa a la que mi código simplemente proporciona un modelo compatible con scikit-learn (mi clase proporciona un método get_clf
). Pude solucionar el problema ya que mi código era (casi) compatible con Keras (no tf.keras), y con Keras 2.3.1 (TF 1.15.0) el decapado funciona sin problemas.
@mimxrt si está buscando usar modelos Keras dentro de un entorno scikit-learn, consulte SciKeras (divulgación completa: soy el autor). Si solo está buscando una forma de hacer que los objetos de Keras se puedan seleccionar, consulte https://github.com/tensorflow/tensorflow/pull/39609 y, en particular, https://github.com/tensorflow/tensorflow/pull/39609#issuecomment -683370566
Editar: enlace fijo
No estamos trabajando activamente en esto en este momento, pero reabrimos ya que todavía es un problema.
Cerrando como rancio. Vuelva a abrir si desea seguir trabajando en esto.
Esto se estancará de nuevo.
Este problema se ha marcado automáticamente como obsoleto porque no ha tenido actividad reciente. Se cerrará si no se produce más actividad. Gracias.
Comentario más útil
Aquí hay una alternativa a la respuesta de @epetrovski que no requiere guardar en un archivo:
Fuente: https://docs.python.org/3/library/pickle.html#object.__reduce__
Siento que tal vez esto podría agregarse al modelo. ¿Hay casos en los que esto no funcionaría?