Tensorflow: نموذج Keras قادر على المخلل ولكن طراز tf.keras غير قابل للمخلل

تم إنشاؤها على ٢٩ نوفمبر ٢٠١٩  ·  34تعليقات  ·  مصدر: tensorflow/tensorflow

معلومات النظام

  • نظام التشغيل Windows 10
  • Tensorflow 2.0 (وحدة المعالجة المركزية)
  • جوبليب 0.14.0
  • بايثون 3.7.5
  • Keras 2.3.1

مرحبا جميعا! هذه أول مشاركة لي لذا أرجوك سامحني إذا فاتني شيء. لذلك أحاول استخدام خوارزمية جينية لتدريب وتقييم بنى NN متعددة لذا أحتاج إلى موازنتها على وحدة معالجة مركزية متعددة النواة. لذلك استخدمت كتاب العمل لمحاولة موازاة ذلك. ومع ذلك ، كنت عالقًا في كود 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 ، أعتقد أنه يجب إصلاح ذلك.

TF 2.2 keras awaiting tensorflower bug

التعليق الأكثر فائدة

إليك بديل لإجابة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__

أشعر أنه ربما يمكن إضافة هذا إلى النموذج؟ هل هناك حالات لا يعمل فيها هذا؟

ال 34 كومينتر

@ 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 تحت الغطاء).

معلومات النظام:

  • Debian 10 (باستر)
  • بايثون 3.7.6
  • جوبليب 0.14.1
  • Tensorflow 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

إليك إصلاح مقتبس من 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__

أشعر أنه ربما يمكن إضافة هذا إلى النموذج؟ هل هناك حالات لا يعمل فيها هذا؟

يبدو أن هناك سمتين لا يمكن اختيارهما في فئة متسلسلة. نجح هذا الإصلاح أيضًا بالنسبة لي:

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 الخاص بك وقمت بإجراء التغييرات المطلوبة ، فقط قم بنسخ نفس الرمز على النحو التالي ، وقد انتهيت من حل الخطأ

استيراد tensorflow مثل tf

def main ():
model_1 = tf.keras.Sequential ((
tf.keras.layers.Dense (16 ، تنشيط = 'relu') ،
tf.keras.layers.Dense (1 ، التنشيط = "خطي") ،
))

_ = 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__ == '__الرئيسية__':
الأساسية()

@ Edwin-Koh1

وفقًا لاقتراح lahsrahtidnap ، لقد جربت في colab ولا أرى أي مشكلة ، من فضلك ، اعثر على الجوهر هنا ، شكرًا!

مرحبا بالجميع ،
أحاول التبديل من قائمة keras إلى tensorflow.keras وفقًا للتوصية الموجودة على https://keras.io/.
أصاب نفس الاستثناء مثل # 34697 (تعليق) مع joblib (والذي يستخدم pickle تحت الغطاء).

معلومات النظام:

  • Debian 10 (باستر)
  • بايثون 3.7.6
  • جوبليب 0.14.1
  • Tensorflow 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

استخدام المخلل أو Joblib لن يحل مشكلتك لأن Tensorflow.keras لا يدعم ذلك.
لذا فإن الحل البديل لذلك هو: -

بالنظر إلى الكود الخاص بك: -
استبدل هذا السطر: - joblib.dump (model، 'model.pkl')
مع: -
لحفظ استخدام النموذج: -
-----> model.save ('new_model.h5')
وإذا كنت تريد تحميل هذا النموذج فاستخدم: -
-----> new_model = tf.keras.models.load_model ('new_model.h5')

بالنظر إلى الكود الخاص بك: -
استبدل هذا السطر: - joblib.dump (model، 'model.pkl')
مع: -
لحفظ استخدام النموذج: -
-----> model.save ('new_model.h5')
وإذا كنت تريد تحميل هذا النموذج فاستخدم: -
-----> new_model = tf.keras.models.load_model ('new_model.h5')

يعمل هذا في بعض الحالات ، ومع ذلك ، فإنه لا يساعد عندما يتم مخلل نموذج كجزء من وظيفة أخرى ، في حالتي يحدث هذا عند استخدام مكتبة python multiprocessing .

@ Edwin-Koh1

لا تزال هذه القضية؟
من فضلك تأكيد شكرا!

هل من الممكن تفريغ نموذج Keras المتسلسل في حاوية بايت

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)

تضمين التغريدة
هذا حل جميل ، شكرا. كن حذرًا فقط إذا كنت تخطط لمواصلة تدريب هذا النموذج ، لأن هذه الطريقة لا تحافظ على حالة المحسن.

تضمين التغريدة
نعم ، يتعين علينا التجميع باستخدام المُحسِّن قبل التوافق مع البيانات الجديدة ، ولا ينبغي أن يستغرق ذلك وقتًا طويلاً ،

من الصعب جدًا تخزين model.save بالطريقة الأخرى في الذاكرة.

هناك طريقة أخرى وهي أننا نستطيع الحصول على get_config () و from_config () مع التهيئة والترجمة ، ثم يجب إجراء الملاءمة للبيانات الجديدة.

@ Edwin-Koh1

أي تحديث في هذا الموضوع من فضلك. شكرا!

تم وضع علامة على هذه المشكلة تلقائيًا على أنها قديمة نظرًا لعدم وجود نشاط حديث لها. سيتم إغلاقه إذا لم يحدث أي نشاط آخر. شكرا لك.

بالنظر إلى الكود الخاص بك: -
استبدل هذا السطر: - joblib.dump (model، 'model.pkl')
مع: -
لحفظ استخدام النموذج: -
-----> model.save ('new_model.h5')
وإذا كنت تريد تحميل هذا النموذج فاستخدم: -
-----> new_model = tf.keras.models.load_model ('new_model.h5')

يعمل هذا في بعض الحالات ، ومع ذلك ، فإنه لا يساعد عندما يتم مخلل نموذج كجزء من وظيفة أخرى ، في حالتي يحدث هذا عند استخدام مكتبة python multiprocessing .

JohannesAck ، أعتقد أنه قد يكون لدي مشكلة مماثلة. أقوم بتدريب نموذج Keras على GPU ، وحفظه باستخدام تنسيق TensorFlow SavedModel باستخدام Keras API ، وإعادة تحميله في جلسة جديدة ومحاولة عمل تنبؤات بالتوازي على وحدات المعالجة المركزية المتعددة باستخدام مكتبة multiprocessing و starmap وظيفة. إذا قمت بتحميل النموذج قبل موازاة التوقعات ، فسأحصل على خطأ تخليل ( TypeError: can't pickle _thread.RLock objects ). إذا قمت بتحميل النموذج ضمن وظيفة التنبؤ الخاصة بي في كل مرة وقمت بحذفه في نهاية كل وظيفة ، فسيتم تعليقه بعد بضعة تنبؤات. هل لديك أي فكرة عما يمكن أن يحدث هنا؟

إغلاق كما لا معنى له. الرجاء إعادة الفتح إذا كنت ترغب في مزيد من العمل على هذا.

هل أنت راضٍ عن حل مشكلتك؟
نعم
لا

هذا ليس بالية بقدر ما أعرف.

في الثلاثاء ، 25 آب (أغسطس) 2020 ، 5:26 ص tensorflow-butler [بوت] <
[email protected]> كتب:

هل أنت راضٍ عن حل مشكلتك؟
نعم
https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform؟entry.85265664=Yes&entry.2137816233=https://github.com/tensor/tensor
لا
https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform؟entry.85265664=No&entry.2137816233=https://github.com/tensorflow/

-
أنت تتلقى هذا لأنك علقت.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على 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

تحرير: ارتباط ثابت

نحن لا نعمل بنشاط على هذا في الوقت الحالي ، لكننا نعيد فتحه لأنه لا يزال يمثل مشكلة.

إغلاق كما لا معنى له. الرجاء إعادة الفتح إذا كنت ترغب في مزيد من العمل على هذا.

هل أنت راضٍ عن حل مشكلتك؟
نعم
لا

هذا سوف يتعطل مرة أخرى.

تم وضع علامة على هذه المشكلة تلقائيًا على أنها قديمة نظرًا لعدم وجود نشاط حديث لها. سيتم إغلاقه إذا لم يحدث أي نشاط آخر. شكرا لك.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات