รูปแบบ SavedModel ของ TensorFlow 2 เป็นวิธีที่แนะนำในการแชร์โมเดลและชิ้นส่วนของโมเดลที่ได้รับการฝึกไว้ล่วงหน้าบน TensorFlow Hub โดยจะมาแทนที่ รูปแบบ TF1 Hub รุ่นเก่าและมาพร้อมกับ API ชุดใหม่
หน้านี้อธิบายวิธีนำ TF2 SavedModels มาใช้ซ้ำในโปรแกรม TensorFlow 2 ด้วย hub.load()
API ระดับต่ำและ wrapper hub.KerasLayer
(โดยทั่วไปแล้ว hub.KerasLayer
จะรวมกับ tf.keras.layers
อื่นๆ เพื่อสร้างโมเดล Keras หรือ model_fn
ของ TF2 Estimator) API เหล่านี้ยังสามารถโหลดโมเดลเดิมในรูปแบบ TF1 Hub ได้ภายในขีดจำกัด โปรดดู คู่มือความเข้ากัน ได้
ผู้ใช้ TensorFlow 1 สามารถอัปเดตเป็น TF 1.15 แล้วใช้ API เดียวกันได้ TF1 เวอร์ชันเก่าไม่ทำงาน
ใช้ SavedModels จาก TF Hub
การใช้ SavedModel ใน Keras
Keras เป็น API ระดับสูงของ TensorFlow สำหรับการสร้างแบบจำลองการเรียนรู้เชิงลึกโดยการเขียนวัตถุ Keras Layer ไลบรารี tensorflow_hub
จัดเตรียมคลาส hub.KerasLayer
ที่ได้รับการเริ่มต้นด้วย URL (หรือเส้นทางระบบไฟล์) ของ SavedModel จากนั้นจัดเตรียมการคำนวณจาก SavedModel รวมถึงน้ำหนักที่ได้รับการฝึกอบรมล่วงหน้า
นี่คือตัวอย่างการใช้การฝังข้อความที่ได้รับการฝึกล่วงหน้า:
import tensorflow as tf
import tensorflow_hub as hub
hub_url = "https://tfhub.dev/google/nnlm-en-dim128/2"
embed = hub.KerasLayer(hub_url)
embeddings = embed(["A long sentence.", "single-word", "http://example.com"])
print(embeddings.shape, embeddings.dtype)
จากนี้ คุณสามารถสร้างตัวแยกประเภทข้อความได้ด้วยวิธี Keras ตามปกติ:
model = tf.keras.Sequential([
embed,
tf.keras.layers.Dense(16, activation="relu"),
tf.keras.layers.Dense(1, activation="sigmoid"),
])
Colab การแยกประเภทข้อความ เป็นตัวอย่างที่สมบูรณ์ของวิธีฝึกและประเมินตัวแยกประเภทดังกล่าว
น้ำหนักของโมเดลใน hub.KerasLayer
ถูกตั้งค่าเป็นไม่สามารถฝึกได้ตามค่าเริ่มต้น ดูส่วนการปรับแต่งอย่างละเอียดด้านล่างเพื่อดูวิธีเปลี่ยนแปลง น้ำหนักจะถูกแชร์ระหว่างแอปพลิเคชันทั้งหมดของออบเจ็กต์เลเยอร์เดียวกัน ตามปกติใน Keras
การใช้ SavedModel ในเครื่องมือประมาณการ
ผู้ใช้ Estimator API ของ TensorFlow สำหรับการฝึกอบรมแบบกระจายสามารถใช้ SavedModels จาก TF Hub ได้โดยการเขียน model_fn
ในรูปของ hub.KerasLayer
ท่ามกลาง tf.keras.layers
อื่นๆ
เบื้องหลัง: การดาวน์โหลดและแคชของ SavedModel
การใช้ SavedModel จาก TensorFlow Hub (หรือเซิร์ฟเวอร์ HTTPS อื่นๆ ที่ใช้โปรโตคอล โฮสติ้ง ) จะดาวน์โหลดและขยายขนาดไปยังระบบไฟล์ในเครื่องหากยังไม่มี ตัวแปรสภาพแวดล้อม TFHUB_CACHE_DIR
สามารถตั้งค่าให้แทนที่ตำแหน่งชั่วคราวเริ่มต้นสำหรับการแคช SavedModels ที่ดาวน์โหลดและไม่บีบอัด สำหรับรายละเอียด โปรดดูที่ การแคช
การใช้ SavedModel ใน TensorFlow ระดับต่ำ
แฮนด์โมเดล
SavedModels สามารถโหลดได้จาก handle
ที่ระบุ โดยที่ handle
เป็นเส้นทางของระบบไฟล์ URL รุ่น TFhub.dev ที่ถูกต้อง (เช่น "https://tfhub.dev/...") URL ของโมเดล Kaggle สะท้อนการจัดการ TFhub.dev ตามข้อกำหนดของเราและใบอนุญาตที่เกี่ยวข้องกับเนื้อหาโมเดล เช่น "https://www.kaggle.com/..." แฮนเดิลจาก Kaggle Models เทียบเท่ากับแฮนเดิล TFhub.dev ที่สอดคล้องกัน
ฟังก์ชัน hub.load(handle)
ดาวน์โหลดและขยายขนาด SavedModel (เว้นแต่ว่า handle
เป็นเส้นทางของระบบไฟล์อยู่แล้ว) จากนั้นส่งคืนผลลัพธ์ของการโหลดด้วยฟังก์ชันในตัวของ TensorFlow tf.saved_model.load()
ดังนั้น hub.load()
สามารถจัดการ SavedModel ที่ถูกต้องได้ (ไม่เหมือนกับ hub.Module
รุ่นก่อนสำหรับ TF1)
หัวข้อขั้นสูง: สิ่งที่คาดหวังจาก SavedModel หลังจากโหลด
ขึ้นอยู่กับเนื้อหาของ SavedModel ผลลัพธ์ของ obj = hub.load(...)
สามารถเรียกใช้ได้หลายวิธี (ดังที่อธิบายในรายละเอียดที่มากขึ้นใน SavedModel Guide ของ TensorFlow :
ลายเซ็นการให้บริการของ SavedModel (ถ้ามี) แสดงเป็นพจนานุกรมของฟังก์ชันที่เป็นรูปธรรมและสามารถเรียกได้เช่น
tensors_out = obj.signatures["serving_default"](**tensors_in)
โดยมีพจนานุกรมของเทนเซอร์ที่คีย์โดยอินพุตและเอาต์พุตที่เกี่ยวข้อง ชื่อและขึ้นอยู่กับรูปร่างของลายเซ็นและข้อจำกัดประเภท dวิธีการ
@tf.function
- ตกแต่งของวัตถุที่บันทึกไว้ (ถ้ามี) จะถูกกู้คืนเป็นวัตถุ tf.function ที่สามารถเรียกได้โดยการรวมกันของอาร์กิวเมนต์ Tensor และไม่ใช่ Tensor ทั้งหมดซึ่งมี การติดตาม tf.function ก่อนที่จะบันทึก โดยเฉพาะอย่างยิ่ง หากมีเมธอดobj.__call__
ที่มีการติดตามที่เหมาะสม ตัวobj
ก็สามารถถูกเรียกได้เหมือนกับฟังก์ชัน Python ตัวอย่างง่ายๆ อาจมีลักษณะเช่นoutput_tensor = obj(input_tensor, training=False)
สิ่งนี้ทำให้มีอิสระอย่างมากในอินเทอร์เฟซที่ SavedModels สามารถใช้งานได้ อินเทอร์เฟซที่ใช้ซ้ำได้ SavedModels สำหรับ obj
กำหนดแบบแผนเพื่อให้โค้ดไคลเอ็นต์ รวมถึงอะแดปเตอร์ เช่น hub.KerasLayer
รู้วิธีใช้ SavedModel
SavedModel บางตัวอาจไม่เป็นไปตามแบบแผนดังกล่าว โดยเฉพาะอย่างยิ่งทั้งโมเดลที่ไม่ควรใช้ซ้ำในโมเดลขนาดใหญ่ และเพียงจัดเตรียมลายเซ็นต์ที่ให้บริการ
ตัวแปรที่ฝึกได้ใน SavedModel จะถูกโหลดซ้ำว่าสามารถฝึกได้ และ tf.GradientTape
จะดูตัวแปรเหล่านั้นตามค่าเริ่มต้น ดูหัวข้อการปรับแต่งอย่างละเอียดด้านล่างสำหรับคำเตือนบางประการ และลองหลีกเลี่ยงสิ่งนี้สำหรับผู้เริ่มต้น แม้ว่าคุณจะต้องการปรับแต่งอย่างละเอียด คุณอาจต้องการดูว่า obj.trainable_variables
แนะนำให้ฝึกใหม่เฉพาะชุดย่อยของตัวแปรที่ฝึกได้เดิมหรือไม่
การสร้าง SavedModels สำหรับ TF Hub
ภาพรวม
SavedModel คือรูปแบบการทำให้เป็นอนุกรมมาตรฐานของ TensorFlow สำหรับโมเดลที่ได้รับการฝึกหรือชิ้นส่วนของโมเดล โดยจะจัดเก็บตุ้มน้ำหนักที่ได้รับการฝึกของโมเดลพร้อมกับการดำเนินการ TensorFlow ที่แน่นอนเพื่อทำการคำนวณ สามารถใช้ได้อย่างอิสระจากโค้ดที่สร้างขึ้น โดยเฉพาะอย่างยิ่ง สามารถนำมาใช้ซ้ำกับ API การสร้างโมเดลระดับสูงต่างๆ เช่น Keras ได้ เนื่องจากการดำเนินการของ TensorFlow คือภาษาพื้นฐานทั่วไป
บันทึกจาก Keras
เริ่มต้นด้วย TensorFlow 2, tf.keras.Model.save()
และ tf.keras.models.save_model()
มีค่าเริ่มต้นเป็นรูปแบบ SavedModel (ไม่ใช่ HDF5) SavedModels ผลลัพธ์ที่สามารถใช้กับ hub.load()
, hub.KerasLayer
และอะแดปเตอร์ที่คล้ายกันสำหรับ API ระดับสูงอื่นๆ เมื่อพร้อมใช้งาน
หากต้องการแชร์โมเดล Keras ที่สมบูรณ์ เพียงบันทึกด้วย include_optimizer=False
หากต้องการแบ่งปันชิ้นส่วนของ Keras Model ให้สร้างชิ้นส่วนนั้นเป็น Model ในตัวมันเอง จากนั้นจึงบันทึกสิ่งนั้น คุณสามารถวางโค้ดแบบนั้นได้ตั้งแต่เริ่มต้น....
piece_to_share = tf.keras.Model(...)
full_model = tf.keras.Sequential([piece_to_share, ...])
full_model.fit(...)
piece_to_share.save(...)
...หรือตัดชิ้นส่วนออกเพื่อแบ่งปันภายหลัง (หากสอดคล้องกับเลเยอร์ของโมเดลเต็มของคุณ):
full_model = tf.keras.Model(...)
sharing_input = full_model.get_layer(...).get_output_at(0)
sharing_output = full_model.get_layer(...).get_output_at(0)
piece_to_share = tf.keras.Model(sharing_input, sharing_output)
piece_to_share.save(..., include_optimizer=False)
โมเดล TensorFlow บน GitHub ใช้วิธีการเดิมสำหรับ BERT (ดู nlp/tools/export_tfhub_lib.py สังเกตการแยกระหว่าง core_model
สำหรับการส่งออกและ pretrainer
สำหรับการกู้คืนจุดตรวจสอบ) และวิธีการหลังสำหรับ ResNet (ดู มรดก/image_classification/tfhub_export.py ).
บันทึกจาก TensorFlow ระดับต่ำ
สิ่งนี้ต้องอาศัยความคุ้นเคยเป็นอย่างดีกับ SavedModel Guide ของ TensorFlow
หากคุณต้องการให้มากกว่าแค่ลายเซ็นการให้บริการ คุณควรใช้ อินเทอร์เฟซ Reusable SavedModel ตามแนวคิดแล้วดูเหมือนว่านี้
class MyMulModel(tf.train.Checkpoint):
def __init__(self, v_init):
super().__init__()
self.v = tf.Variable(v_init)
self.variables = [self.v]
self.trainable_variables = [self.v]
self.regularization_losses = [
tf.function(input_signature=[])(lambda: 0.001 * self.v**2),
]
@tf.function(input_signature=[tf.TensorSpec(shape=None, dtype=tf.float32)])
def __call__(self, inputs):
return tf.multiply(inputs, self.v)
tf.saved_model.save(MyMulModel(2.0), "/tmp/my_mul")
layer = hub.KerasLayer("/tmp/my_mul")
print(layer([10., 20.])) # [20., 40.]
layer.trainable = True
print(layer.trainable_weights) # [2.]
print(layer.losses) # 0.004
การปรับแต่งแบบละเอียด
การฝึกตัวแปรที่ได้รับการฝึกแล้วของ SavedModel ที่นำเข้าร่วมกับโมเดลที่อยู่รอบๆ เรียกว่า การปรับแต่ง SavedModel อย่างละเอียด ซึ่งอาจส่งผลให้มีคุณภาพดีขึ้น แต่มักทำให้การฝึกอบรมมีความต้องการมากขึ้น (อาจใช้เวลามากขึ้น ขึ้นอยู่กับเครื่องมือเพิ่มประสิทธิภาพและไฮเปอร์พารามิเตอร์ของมันมากขึ้น เพิ่มความเสี่ยงในการติดตั้งมากเกินไป และต้องมีการเพิ่มชุดข้อมูล โดยเฉพาะสำหรับ CNN) เราแนะนำให้ผู้บริโภค SavedModel พิจารณาการปรับแต่งอย่างละเอียดหลังจากสร้างระบบการฝึกอบรมที่ดีแล้วเท่านั้น และเฉพาะเมื่อผู้เผยแพร่ SavedModel แนะนำเท่านั้น
การปรับแต่งอย่างละเอียดจะเปลี่ยนพารามิเตอร์โมเดล "ต่อเนื่อง" ที่ได้รับการฝึก จะไม่เปลี่ยนการแปลงแบบฮาร์ดโค้ด เช่น การป้อนข้อความเป็นโทเค็น และโทเค็นการแมปเป็นรายการที่สอดคล้องกันในเมทริกซ์ที่ฝัง
สำหรับผู้บริโภค SavedModel
การสร้าง hub.KerasLayer
เช่น KerasLayer
layer = hub.KerasLayer(..., trainable=True)
เปิดใช้งานการปรับแต่ง SavedModel ที่โหลดโดยเลเยอร์อย่างละเอียด โดยจะเพิ่มน้ำหนักที่สามารถฝึกได้และตัวกำหนดน้ำหนักที่ประกาศใน SavedModel ให้กับโมเดล Keras และรันการคำนวณของ SavedModel ในโหมดการฝึกอบรม (ลองนึกถึงการออกกลางคัน ฯลฯ )
colab การจัดหมวดหมู่รูปภาพ มีตัวอย่างตั้งแต่ต้นจนจบพร้อมการปรับแต่งแบบละเอียด (ไม่บังคับ)
ส่งออกผลลัพธ์การปรับแต่งอย่างละเอียดอีกครั้ง
ผู้ใช้ขั้นสูงอาจต้องการบันทึกผลลัพธ์ของการปรับแต่งกลับเข้าไปใน SavedModel ที่สามารถใช้แทนการโหลดครั้งแรก ซึ่งสามารถทำได้ด้วยโค้ดเช่น
loaded_obj = hub.load("https://tfhub.dev/...")
hub_layer = hub.KerasLayer(loaded_obj, trainable=True, ...)
model = keras.Sequential([..., hub_layer, ...])
model.compile(...)
model.fit(...)
export_module_dir = os.path.join(os.getcwd(), "finetuned_model_export")
tf.saved_model.save(loaded_obj, export_module_dir)
สำหรับผู้สร้าง SavedModel
เมื่อสร้าง SavedModel สำหรับการแชร์บน TensorFlow Hub ให้คิดล่วงหน้าว่าผู้บริโภคควรปรับแต่งหรือไม่ และอย่างไร และให้คำแนะนำในเอกสารประกอบ
การบันทึกจากโมเดล Keras ควรทำให้กลไกทั้งหมดของงานปรับแต่งอย่างละเอียด (บันทึกการสูญเสียการทำให้น้ำหนักเป็นมาตรฐาน การประกาศตัวแปรที่ฝึกได้ การติดตาม __call__
สำหรับทั้ง training=True
และ training=False
ฯลฯ )
เลือกอินเทอร์เฟซแบบจำลองที่ทำงานได้ดีกับโฟลว์การไล่ระดับสี เช่น การบันทึกเอาท์พุต แทนที่จะเป็นความน่าจะเป็นแบบ softmax หรือการทำนายแบบ top-k
หากโมเดลใช้การออกกลางคัน การทำให้เป็นมาตรฐานของแบทช์ หรือเทคนิคการฝึกอบรมที่คล้ายกันที่เกี่ยวข้องกับไฮเปอร์พารามิเตอร์ ให้ตั้งค่าเหล่านี้เป็นค่าที่เหมาะสมกับปัญหาเป้าหมายและขนาดแบทช์ที่คาดหวังไว้ (ในขณะที่เขียนบทความนี้ การประหยัดจาก Keras ไม่ได้ทำให้ผู้บริโภคปรับเปลี่ยนได้ง่าย)
ตัวปรับน้ำหนักในแต่ละเลเยอร์จะถูกบันทึกไว้ (ด้วยค่าสัมประสิทธิ์ความแข็งแกร่งของการทำให้เป็นมาตรฐาน) แต่การทำให้น้ำหนักเป็นมาตรฐานจากภายในตัวเพิ่มประสิทธิภาพ (เช่น tf.keras.optimizers.Ftrl.l1_regularization_strength=...)
) จะหายไป แนะนำผู้บริโภคของ SavedModel ของคุณตามลำดับ