Системная информация
Всем привет! Это мой первый пост, так что простите меня, если я что-то упустил. Поэтому я пытаюсь использовать генетический алгоритм для обучения и оценки нескольких архитектур NN, поэтому мне нужно распараллелить их на многоядерном процессоре. Поэтому я использовал joblib, чтобы попытаться распараллелить это. Однако я застрял в коде tf.keras, потому что его нельзя было мариновать. После многих часов отладки я наконец понял, что модели tf.keras нельзя мариновать, а модели keras - нет.
Опишите текущее поведение
Приведенный ниже код работает, но если вы замените keras на tf.keras, возникнет ошибка:
Не удалось засолить задачу отправить в рабочие.
Опишите ожидаемое поведение
Двигаясь вперед, tf.keras должен заменить keras, и поэтому tf.keras также должны быть маринованными.
Код для воспроизведения проблемы
#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
Другие комментарии
Я предполагаю, что быстрое исправление было бы просто заменить весь существующий код с tf.keras на просто keras, но, поскольку поддержка keras будет прекращена и поглощена Tensorflow 2.0, я думаю, что это должно быть исправлено.
@ Edwin-Koh1
Не могли бы вы проверить ночную версию ( !pip install tf-nightly==2.1.0dev20191201
) и посмотреть, сохраняется ли ошибка. В последних ночных версиях значительно улучшена производительность. Благодаря!
Автоматически закрывается из-за отсутствия активности в последнее время. Обновите проблему, когда станет доступна новая информация, и мы повторно откроем ее. Благодаря!
@ravikyram Я все еще вижу эту проблему в 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()
приводит к
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
Я пробовал использовать colab с TF версии 2.1.0-rc2, 2.2.0-dev20200113 и смог воспроизвести проблему. Пожалуйста, найдите суть здесь . Благодаря!
@ravikyram , функциональные модели keras тоже должны быть травимыми или нет? Я бы предположил, что если последовательные модели являются, то функциональные модели тоже должны быть? Или функциональные модели обладают некоторыми свойствами, из-за которых их сложнее мариновать?
$ 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
Всем привет,
Я пытаюсь переключиться с автономного keras
на tensorflow.keras
в соответствии с рекомендацией на https://keras.io/.
Я попал в то же исключение, что и https://github.com/tensorflow/tensorflow/issues/34697#issuecomment -575705599 с joblib
(который использует pickle
под капотом).
Системная информация:
Скрипт для воспроизведения:
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')
Вывод:
TypeError: can't pickle _thread.RLock objects
Вот исправление, адаптированное из http://zachmoshe.com/2017/04/03/pickling-keras-models.html, предназначенное для решения той же проблемы, когда раньше модели Keras не поддавались маринованию.
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 Должен ли я вызывать этот код всякий раз, когда я собираюсь мариновать модель, или я могу просто вызвать его в начале моего приложения (перед созданием модели)?
@epetrovski Должен ли я вызывать этот код всякий раз, когда я собираюсь мариновать модель, или я могу просто вызвать его в начале моего приложения (перед созданием модели)?
Вы можете просто вызвать его один раз в начале вашего приложения после импорта tensorflow.keras.models.Model
. Выполнение функции добавляет два новых метода __getstate__()
и __setstate__()
к классу tensorflow.keras.models.Model
поэтому он должен работать каждый раз, когда вы хотите обработать член обновленного класса модели tf.keras - т.е. ваша собственная модель.
Вот альтернатива ответу @epetrovski , не требующая сохранения в файл:
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)
Источник: https://docs.python.org/3/library/pickle.html#object.__reduce__
Я чувствую, что это можно было бы добавить в Модель? Есть ли случаи, когда это не сработает?
Кажется, что есть два атрибута, которые нельзя выбрать в классе Sequential. Это исправление также сработало для меня:
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)
~
Я пробовал использовать colab с TF версии 2.2, ночные версии и смог воспроизвести проблему. Пожалуйста, найдите суть здесь. Спасибо!
Я пробовал использовать colab с TF версии 2.2, ночные версии и смог воспроизвести проблему. Пожалуйста, найдите суть здесь. Спасибо!
Модель keras выбирается, но tf.keras не выбирается, поэтому альтернативное решение для этого - см. приведенный ниже код: -
Я увидел вашу записную книжку Colab и внес необходимые изменения, просто скопируйте тот же код, что и ниже, и вы закончите с устранением ошибки
импортировать тензорный поток как 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_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)
если __name__ == '__main__':
главный()
@ Edwin-Koh1
Согласно предложению @lahsrahtidnap, я пробовал использовать colab и не вижу никаких проблем. Пожалуйста, найдите суть здесь. Спасибо!
Всем привет,
Я пытаюсь переключиться с автономногоkeras
наtensorflow.keras
в соответствии с рекомендацией на https://keras.io/.
Я попал в то же исключение, что и # 34697 (комментарий) сjoblib
(который используетpickle
под капотом).Системная информация:
- Debian 10 (прерыватель)
- Python 3.7.6
- joblib 0.14.1
- тензор потока 2.1.0
Скрипт для воспроизведения:
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')
Вывод:
TypeError: can't pickle _thread.RLock objects
Использование pickle или joblib не решит вашу проблему, поскольку tensorflow.keras этого не поддерживает.
Итак, альтернативное решение для этого: -
учитывая ваш код: -
замените эту строку: - joblib.dump (model, 'model.pkl')
с участием: -
для сохранения модели используйте: -
-----> model.save ('new_model.h5')
и если вы хотите загрузить эту модель, используйте: -
-----> новая_модель = tf.keras.models.load_model ('новая_модель.h5')
учитывая ваш код: -
замените эту строку: - joblib.dump (model, 'model.pkl')
с участием: -
для сохранения модели используйте: -
-----> model.save ('new_model.h5')
и если вы хотите загрузить эту модель, используйте: -
-----> новая_модель = tf.keras.models.load_model ('новая_модель.h5')
В некоторых случаях это работает, однако не помогает, когда модель обрабатывается как часть другой функции, в моем случае это происходит при использовании библиотеки python multiprocessing
.
@ Edwin-Koh1
Это все еще проблема?
Подтвердите, спасибо!
Можно ли сбросить последовательную модель Keras в контейнер 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
или во временном файле
tempfile.TemporaryFile().write(Keras_model)
или же
save_model(Keras_model, bytes_container)
# Error
TypeError: expected str, bytes or os.PathLike object, not _io.BytesIO
Это сработало отлично, ну, возможно, вам не понадобится base64, чтобы я мог хранить в базе данных, которую я сделал, все в памяти, без касания диска
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
Хорошее решение, спасибо. Только будьте осторожны, если планируете продолжить обучение этой модели, так как этот метод не сохраняет состояние оптимизатора.
@JohannesAck
Да, мы должны скомпилировать с оптимизатором, прежде чем соответствовать новым данным, это не должно занимать много времени,
С другой стороны, model.save очень сложно хранить в памяти.
Другой способ - мы можем выполнить get_config () и from_config () с инициализацией и компиляцией, после чего необходимо выполнить подгонку для новых данных.
@ Edwin-Koh1
Любые обновления по этому вопросу, пожалуйста. Спасибо!
Эта проблема была автоматически помечена как устаревшая, поскольку в последнее время не было активности. Он будет закрыт, если больше не будет активности. Спасибо.
учитывая ваш код: -
замените эту строку: - joblib.dump (model, 'model.pkl')
с участием: -
для сохранения модели используйте: -
-----> model.save ('new_model.h5')
и если вы хотите загрузить эту модель, используйте: -
-----> новая_модель = tf.keras.models.load_model ('новая_модель.h5')В некоторых случаях это работает, однако не помогает, когда модель обрабатывается как часть другой функции, в моем случае это происходит при использовании библиотеки python
multiprocessing
.
@JohannesAck , я думаю, у меня может быть похожая проблема. Я обучаю модель Keras на графическом процессоре, сохраняю ее в формате TensorFlow SavedModel с помощью Keras API, перезагружаю ее в новом сеансе и пытаюсь делать прогнозы параллельно на нескольких процессорах с помощью библиотеки multiprocessing
и starmap
функция. Если я загружаю модель перед распараллеливанием прогнозов, я получаю ошибку травления ( TypeError: can't pickle _thread.RLock objects
). Если я загружаю модель в свою функцию прогнозирования каждый раз и удаляю ее в конце каждого вызова функции, она зависает после нескольких прогнозов. Ты хоть представляешь, что здесь может происходить?
Закрытие как устаревшее. Пожалуйста, откройте снова, если вы хотите продолжить работу над этим.
Насколько я знаю, он не устарел.
Во вторник, 25 августа 2020 г., 5:26 tenorflow-butler [bot] <
[email protected]> написал:
Довольны ли вы решением вашей проблемы?
да
https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=Yes&entry.2137816233=https://githues.com/tens69/github.com/
Нет
https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=No&entry.2137816233=https://github.com/tens69/github.com/-
Вы получили это, потому что оставили комментарий.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/tensorflow/tensorflow/issues/34697#issuecomment-679941192 ,
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/AANMPP2EF3PRKBYRYHOHY3TSCOGTXANCNFSM4JSZ4QSA
.
Это WONTFIX после того, как проблема была закрыта?
В моем случае я не могу просто использовать model.save()
потому что травление выполняется из внешнего инструмента, для которого мой код просто предоставляет модель, совместимую с scikit-learn (мой класс предоставляет метод get_clf
). Я мог бы обойти проблему, поскольку мой код был (почти) Keras-совместимым (не tf.keras), а с Keras 2.3.1 (TF 1.15.0) травление работает без проблем.
@mimxrt, если вы хотите использовать модели Keras в среде scikit-learn, ознакомьтесь с SciKeras (полное раскрытие: я являюсь автором). Если вы просто ищете способ сделать объекты Keras доступными для выбора, проверьте https://github.com/tensorflow/tensorflow/pull/39609 и, в частности, https://github.com/tensorflow/tensorflow/pull/39609#issuecomment -683370566
Изменить: фиксированная ссылка
Мы не ведем активной работы над этим прямо сейчас, но возобновляем работу, так как это все еще проблема.
Закрытие как устаревшее. Пожалуйста, откройте снова, если вы хотите продолжить работу над этим.
Это снова остановится.
Эта проблема была автоматически помечена как устаревшая, поскольку в последнее время не было активности. Он будет закрыт, если больше не будет активности. Спасибо.
Самый полезный комментарий
Вот альтернатива ответу @epetrovski , не требующая сохранения в файл:
Источник: https://docs.python.org/3/library/pickle.html#object.__reduce__
Я чувствую, что это можно было бы добавить в Модель? Есть ли случаи, когда это не сработает?