ดูบน TensorFlow.org | ทำงานใน Google Colab | ดูแหล่งที่มาบน GitHub | ดาวน์โหลดโน๊ตบุ๊ค |
ในการทำแมชชีนเลิร์นนิงใน TensorFlow คุณมักจะต้องกำหนด บันทึก และกู้คืนโมเดล
โมเดลเป็นนามธรรม:
- ฟังก์ชันที่คำนวณบางอย่างบนเทนเซอร์ ( forward pass )
- ตัวแปรบางตัวที่สามารถอัพเดตตามการฝึกได้
ในคู่มือนี้ คุณจะไปที่ด้านล่างพื้นผิวของ Keras เพื่อดูว่าโมเดล TensorFlow ถูกกำหนดอย่างไร นี่คือวิธีที่ TensorFlow รวบรวมตัวแปรและแบบจำลอง ตลอดจนวิธีการบันทึกและกู้คืน
ติดตั้ง
import tensorflow as tf
from datetime import datetime
%load_ext tensorboard
การกำหนดโมเดลและเลเยอร์ใน TensorFlow
โมเดลส่วนใหญ่ทำจากเลเยอร์ เลเยอร์เป็นฟังก์ชันที่มีโครงสร้างทางคณิตศาสตร์ที่รู้จักซึ่งสามารถนำมาใช้ซ้ำได้และมีตัวแปรที่ฝึกได้ ใน TensorFlow การใช้งานเลเยอร์และโมเดลระดับสูงส่วนใหญ่ เช่น Keras หรือ Sonnet สร้างขึ้นบนคลาสพื้นฐานเดียวกัน: tf.Module
ต่อไปนี้คือตัวอย่าง tf.Module
แบบง่ายๆ ที่ทำงานบนเมตริกซ์สเกลาร์:
class SimpleModule(tf.Module):
def __init__(self, name=None):
super().__init__(name=name)
self.a_variable = tf.Variable(5.0, name="train_me")
self.non_trainable_variable = tf.Variable(5.0, trainable=False, name="do_not_train_me")
def __call__(self, x):
return self.a_variable * x + self.non_trainable_variable
simple_module = SimpleModule(name="simple")
simple_module(tf.constant(5.0))
<tf.Tensor: shape=(), dtype=float32, numpy=30.0>
โมดูลและโดยการขยาย เลเยอร์เป็นคำศัพท์ที่เรียนรู้อย่างลึกซึ้งสำหรับ "วัตถุ": พวกมันมีสถานะภายในและวิธีการที่ใช้สถานะนั้น
ไม่มีอะไรพิเศษเกี่ยวกับ __call__
ยกเว้นการทำตัวเหมือน Python callable ; คุณสามารถเรียกใช้โมเดลของคุณด้วยฟังก์ชันใดก็ได้ที่คุณต้องการ
คุณสามารถตั้งค่าเปิดและปิดความสามารถในการฝึกของตัวแปรได้ไม่ว่าจะด้วยเหตุผลใดก็ตาม รวมถึงการแช่แข็งเลเยอร์และตัวแปรระหว่างการปรับแต่งอย่างละเอียด
โดยการแบ่งคลาสย่อย tf.Module
อินสแตนซ์ tf.Module
หรือ tf.Variable
ใดๆ ที่กำหนดให้กับคุณสมบัติของอ็อบเจ็กต์นี้จะถูกรวบรวมโดยอัตโนมัติ สิ่งนี้ทำให้คุณสามารถบันทึกและโหลดตัวแปร และสร้างคอลเล็กชันของ tf.Module
s
# All trainable variables
print("trainable variables:", simple_module.trainable_variables)
# Every variable
print("all variables:", simple_module.variables)
trainable variables: (<tf.Variable 'train_me:0' shape=() dtype=float32, numpy=5.0>,) all variables: (<tf.Variable 'train_me:0' shape=() dtype=float32, numpy=5.0>, <tf.Variable 'do_not_train_me:0' shape=() dtype=float32, numpy=5.0>) 2021-10-26 01:29:45.284549: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
นี่คือตัวอย่างโมเดลเลเยอร์เชิงเส้นแบบสองชั้นที่สร้างจากโมดูล
ขั้นแรกให้เลเยอร์หนาแน่น (เชิงเส้น):
class Dense(tf.Module):
def __init__(self, in_features, out_features, name=None):
super().__init__(name=name)
self.w = tf.Variable(
tf.random.normal([in_features, out_features]), name='w')
self.b = tf.Variable(tf.zeros([out_features]), name='b')
def __call__(self, x):
y = tf.matmul(x, self.w) + self.b
return tf.nn.relu(y)
จากนั้นโมเดลที่สมบูรณ์ ซึ่งสร้างอินสแตนซ์สองชั้นและนำไปใช้:
class SequentialModule(tf.Module):
def __init__(self, name=None):
super().__init__(name=name)
self.dense_1 = Dense(in_features=3, out_features=3)
self.dense_2 = Dense(in_features=3, out_features=2)
def __call__(self, x):
x = self.dense_1(x)
return self.dense_2(x)
# You have made a model!
my_model = SequentialModule(name="the_model")
# Call it, with random results
print("Model results:", my_model(tf.constant([[2.0, 2.0, 2.0]])))
Model results: tf.Tensor([[7.706234 3.0919805]], shape=(1, 2), dtype=float32)
อินสแตนซ์ tf.Module
จะรวบรวมอินสแตนซ์ tf.Variable
หรือ tf.Module
แบบเรียกซ้ำ แบบเรียกซ้ำโดยอัตโนมัติ สิ่งนี้ทำให้คุณสามารถจัดการคอลเลกชั่นของ tf.Module
ด้วยอินสแตนซ์โมเดลเดียว และบันทึกและโหลดทั้งโมเดล
print("Submodules:", my_model.submodules)
Submodules: (<__main__.Dense object at 0x7f7ab2391290>, <__main__.Dense object at 0x7f7b6869ea10>)
for var in my_model.variables:
print(var, "\n")
<tf.Variable 'b:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)> <tf.Variable 'w:0' shape=(3, 3) dtype=float32, numpy= array([[ 0.05711935, 0.22440144, 0.6370985 ], [ 0.3136791 , -1.7006774 , 0.7256515 ], [ 0.16120772, -0.8412193 , 0.5250952 ]], dtype=float32)> <tf.Variable 'b:0' shape=(2,) dtype=float32, numpy=array([0., 0.], dtype=float32)> <tf.Variable 'w:0' shape=(3, 2) dtype=float32, numpy= array([[-0.5353216 , 1.2815404 ], [ 0.62764466, 0.47087234], [ 2.19187 , 0.45777202]], dtype=float32)>
รอสร้างตัวแปร
คุณอาจสังเกตเห็นที่นี่ว่าคุณต้องกำหนดทั้งขนาดอินพุตและเอาต์พุตให้กับเลเยอร์ นี่คือตัวแปร w
มีรูปร่างที่รู้จักและสามารถจัดสรรได้
เมื่อเลื่อนการสร้างตัวแปรไปในครั้งแรกที่มีการเรียกโมดูลด้วยรูปร่างอินพุตเฉพาะ คุณไม่จำเป็นต้องระบุขนาดอินพุตไว้ล่วงหน้า
class FlexibleDenseModule(tf.Module):
# Note: No need for `in_features`
def __init__(self, out_features, name=None):
super().__init__(name=name)
self.is_built = False
self.out_features = out_features
def __call__(self, x):
# Create variables on first call.
if not self.is_built:
self.w = tf.Variable(
tf.random.normal([x.shape[-1], self.out_features]), name='w')
self.b = tf.Variable(tf.zeros([self.out_features]), name='b')
self.is_built = True
y = tf.matmul(x, self.w) + self.b
return tf.nn.relu(y)
# Used in a module
class MySequentialModule(tf.Module):
def __init__(self, name=None):
super().__init__(name=name)
self.dense_1 = FlexibleDenseModule(out_features=3)
self.dense_2 = FlexibleDenseModule(out_features=2)
def __call__(self, x):
x = self.dense_1(x)
return self.dense_2(x)
my_model = MySequentialModule(name="the_model")
print("Model results:", my_model(tf.constant([[2.0, 2.0, 2.0]])))
Model results: tf.Tensor([[4.0598335 0. ]], shape=(1, 2), dtype=float32)
ความยืดหยุ่นนี้เป็นสาเหตุที่เลเยอร์ TensorFlow มักจะต้องระบุรูปร่างของเอาต์พุตเท่านั้น เช่น ใน tf.keras.layers.Dense
แทนที่จะเป็นทั้งขนาดอินพุตและเอาต์พุต
ออมน้ำหนัก
คุณสามารถบันทึก tf.Module
เป็นทั้ง จุดตรวจสอบ และ SavedModel
จุดตรวจเป็นเพียงค่าน้ำหนัก (นั่นคือ ค่าของชุดของตัวแปรภายในโมดูลและโมดูลย่อย):
chkp_path = "my_checkpoint"
checkpoint = tf.train.Checkpoint(model=my_model)
checkpoint.write(chkp_path)
'my_checkpoint'
จุดตรวจประกอบด้วยไฟล์สองประเภท: ตัวข้อมูลและไฟล์ดัชนีสำหรับข้อมูลเมตา ไฟล์ดัชนีติดตามสิ่งที่ถูกบันทึกไว้จริง ๆ และการกำหนดหมายเลขของจุดตรวจ ในขณะที่ข้อมูลจุดตรวจสอบมีค่าตัวแปรและเส้นทางการค้นหาแอตทริบิวต์
ls my_checkpoint*
my_checkpoint.data-00000-of-00001 my_checkpoint.index
คุณสามารถดูภายในจุดตรวจเพื่อให้แน่ใจว่าได้บันทึกคอลเลกชันของตัวแปรทั้งหมดแล้ว โดยจัดเรียงตามวัตถุ Python ที่มีอยู่
tf.train.list_variables(chkp_path)
[('_CHECKPOINTABLE_OBJECT_GRAPH', []), ('model/dense_1/b/.ATTRIBUTES/VARIABLE_VALUE', [3]), ('model/dense_1/w/.ATTRIBUTES/VARIABLE_VALUE', [3, 3]), ('model/dense_2/b/.ATTRIBUTES/VARIABLE_VALUE', [2]), ('model/dense_2/w/.ATTRIBUTES/VARIABLE_VALUE', [3, 2])]
ในระหว่างการฝึกอบรมแบบกระจาย (หลายเครื่อง) พวกเขาสามารถแบ่งส่วนข้อมูลได้ ซึ่งเป็นสาเหตุว่าทำไมจึงมีการกำหนดหมายเลขไว้ (เช่น '00000-of-00001') ในกรณีนี้ มีเพียงเศษเสี้ยวเดียวเท่านั้น
เมื่อคุณโหลดโมเดลกลับเข้าไป คุณจะเขียนทับค่าในอ็อบเจกต์ Python ของคุณ
new_model = MySequentialModule()
new_checkpoint = tf.train.Checkpoint(model=new_model)
new_checkpoint.restore("my_checkpoint")
# Should be the same result as above
new_model(tf.constant([[2.0, 2.0, 2.0]]))
<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[4.0598335, 0. ]], dtype=float32)>ตัวยึดตำแหน่ง23
ฟังก์ชั่นการบันทึก
TensorFlow สามารถเรียกใช้โมเดลโดยไม่มีอ็อบเจ็กต์ Python ดั้งเดิม ดังที่แสดงโดย TensorFlow Serving และ TensorFlow Lite แม้ว่าคุณจะดาวน์โหลดโมเดลที่ผ่านการฝึกอบรมจาก TensorFlow Hub
TensorFlow จำเป็นต้องรู้วิธีคำนวณตามที่อธิบายไว้ใน Python แต่ ไม่มีโค้ดต้นฉบับ ในการดำเนินการนี้ คุณสามารถสร้าง กราฟ ซึ่งมีคำอธิบายอยู่ในคู่มือ แนะนำกราฟและฟังก์ชัน
กราฟนี้มีการดำเนินการ หรือ ops ที่นำฟังก์ชันไปใช้
คุณสามารถกำหนดกราฟในแบบจำลองด้านบนโดยเพิ่ม @tf.function
decorator เพื่อระบุว่าโค้ดนี้ควรทำงานเป็นกราฟ
class MySequentialModule(tf.Module):
def __init__(self, name=None):
super().__init__(name=name)
self.dense_1 = Dense(in_features=3, out_features=3)
self.dense_2 = Dense(in_features=3, out_features=2)
@tf.function
def __call__(self, x):
x = self.dense_1(x)
return self.dense_2(x)
# You have made a model with a graph!
my_model = MySequentialModule(name="the_model")
โมดูลที่คุณสร้างขึ้นนั้นทำงานเหมือนเดิมทุกประการ ลายเซ็นที่ไม่ซ้ำกันแต่ละอันที่ส่งผ่านไปยังฟังก์ชันจะสร้างกราฟแยกกัน ตรวจสอบคำ แนะนำเกี่ยวกับกราฟและฟังก์ชัน สำหรับรายละเอียด
print(my_model([[2.0, 2.0, 2.0]]))
print(my_model([[[2.0, 2.0, 2.0], [2.0, 2.0, 2.0]]]))
tf.Tensor([[0.62891716 0. ]], shape=(1, 2), dtype=float32) tf.Tensor( [[[0.62891716 0. ] [0.62891716 0. ]]], shape=(1, 2, 2), dtype=float32)
คุณสามารถดูกราฟได้โดยการติดตามภายในสรุป TensorBoard
# Set up logging.
stamp = datetime.now().strftime("%Y%m%d-%H%M%S")
logdir = "logs/func/%s" % stamp
writer = tf.summary.create_file_writer(logdir)
# Create a new model to get a fresh trace
# Otherwise the summary will not see the graph.
new_model = MySequentialModule()
# Bracket the function call with
# tf.summary.trace_on() and tf.summary.trace_export().
tf.summary.trace_on(graph=True)
tf.profiler.experimental.start(logdir)
# Call only one tf.function when tracing.
z = print(new_model(tf.constant([[2.0, 2.0, 2.0]])))
with writer.as_default():
tf.summary.trace_export(
name="my_func_trace",
step=0,
profiler_outdir=logdir)
tf.Tensor([[0. 0.01750386]], shape=(1, 2), dtype=float32)
เรียกใช้ TensorBoard เพื่อดูการติดตามผลลัพธ์:
#docs_infra: no_execute
%tensorboard --logdir logs/func
การสร้าง SavedModel
วิธีที่แนะนำในการแชร์โมเดลที่ได้รับการฝึกอบรมอย่างสมบูรณ์คือการใช้ SavedModel
SavedModel
มีทั้งชุดของฟังก์ชันและชุดของตุ้มน้ำหนัก
คุณสามารถบันทึกโมเดลที่คุณเพิ่งฝึกได้ดังนี้:
tf.saved_model.save(my_model, "the_saved_model")
INFO:tensorflow:Assets written to: the_saved_model/assets
# Inspect the SavedModel in the directory
ls -l the_saved_model
total 24 drwxr-sr-x 2 kbuilder kokoro 4096 Oct 26 01:29 assets -rw-rw-r-- 1 kbuilder kokoro 14702 Oct 26 01:29 saved_model.pb drwxr-sr-x 2 kbuilder kokoro 4096 Oct 26 01:29 variablesตัวยึดตำแหน่ง
# The variables/ directory contains a checkpoint of the variables
ls -l the_saved_model/variables
total 8 -rw-rw-r-- 1 kbuilder kokoro 408 Oct 26 01:29 variables.data-00000-of-00001 -rw-rw-r-- 1 kbuilder kokoro 356 Oct 26 01:29 variables.index
ไฟล์ saved_model.pb
เป็น บัฟเฟอร์โปรโตคอล ที่อธิบายการทำงาน tf.Graph
โมเดลและเลเยอร์สามารถโหลดได้จากการแสดงนี้ โดยไม่ต้องสร้างอินสแตนซ์ของคลาสที่สร้างมันขึ้นมาจริงๆ สิ่งนี้เป็นที่ต้องการในสถานการณ์ที่คุณไม่มี (หรือต้องการ) ล่าม Python เช่นการให้บริการในขนาดหรือบนอุปกรณ์ Edge หรือในสถานการณ์ที่ไม่มีรหัส Python ดั้งเดิมหรือใช้งานได้จริง
คุณสามารถโหลดโมเดลเป็นวัตถุใหม่ได้:
new_model = tf.saved_model.load("the_saved_model")
new_model
สร้างขึ้นจากการโหลดโมเดลที่บันทึกไว้ เป็นอ็อบเจ็กต์ผู้ใช้ TensorFlow ภายในที่ไม่มีความรู้ในคลาสใดๆ ไม่ใช่ประเภท SequentialModule
isinstance(new_model, SequentialModule)
False
โมเดลใหม่นี้ใช้งานได้กับลายเซ็นอินพุตที่กำหนดไว้แล้ว คุณไม่สามารถเพิ่มลายเซ็นเพิ่มเติมให้กับโมเดลที่กู้คืนเช่นนี้
print(my_model([[2.0, 2.0, 2.0]]))
print(my_model([[[2.0, 2.0, 2.0], [2.0, 2.0, 2.0]]]))
tf.Tensor([[0.62891716 0. ]], shape=(1, 2), dtype=float32) tf.Tensor( [[[0.62891716 0. ] [0.62891716 0. ]]], shape=(1, 2, 2), dtype=float32)
ดังนั้น เมื่อใช้ SavedModel
คุณจะสามารถบันทึกน้ำหนักและกราฟของ TensorFlow โดยใช้ tf.Module
แล้วโหลดอีกครั้ง
Keras รุ่นและชั้น
โปรดทราบว่าจนถึงจุดนี้ ไม่มีการกล่าวถึง Keras คุณสามารถสร้าง API ระดับสูงของคุณเองบน tf.Module
และผู้คนมี
ในส่วนนี้ คุณจะพิจารณาว่า Keras ใช้ tf.Module
อย่างไร คู่มือผู้ใช้ฉบับสมบูรณ์สำหรับรุ่น Keras มีอยู่ใน คู่มือ Keras
ชั้น Keras
tf.keras.layers.Layer
เป็นคลาสพื้นฐานของเลเยอร์ Keras ทั้งหมด และสืบทอดมาจาก tf.Module
คุณสามารถแปลงโมดูลเป็นเลเยอร์ Keras เพียงแค่สลับพาเรนต์แล้วเปลี่ยน __call__
เป็น call
:
class MyDense(tf.keras.layers.Layer):
# Adding **kwargs to support base Keras layer arguments
def __init__(self, in_features, out_features, **kwargs):
super().__init__(**kwargs)
# This will soon move to the build step; see below
self.w = tf.Variable(
tf.random.normal([in_features, out_features]), name='w')
self.b = tf.Variable(tf.zeros([out_features]), name='b')
def call(self, x):
y = tf.matmul(x, self.w) + self.b
return tf.nn.relu(y)
simple_layer = MyDense(name="simple", in_features=3, out_features=3)
เลเยอร์ Keras มี __call__
ของตัวเองที่ทำบัญชีที่อธิบายไว้ในส่วนถัดไปแล้วเรียก call()
คุณควรสังเกตว่าไม่มีการเปลี่ยนแปลงในการทำงาน
simple_layer([[2.0, 2.0, 2.0]])
<tf.Tensor: shape=(1, 3), dtype=float32, numpy=array([[0. , 0.179402, 0. ]], dtype=float32)>ตัวยึดตำแหน่ง43
ขั้นตอนการ build
ดังที่ระบุไว้ ในหลาย ๆ กรณีจะสะดวกที่จะรอเพื่อสร้างตัวแปรจนกว่าคุณจะแน่ใจในรูปร่างอินพุต
เลเยอร์ Keras มาพร้อมกับขั้นตอนวงจรชีวิตเพิ่มเติมที่ช่วยให้คุณมีความยืดหยุ่นมากขึ้นในการกำหนดเลเยอร์ของคุณ สิ่งนี้ถูกกำหนดไว้ในฟังก์ชัน build
ด์
บิลด์ถูกเรียกเพียงครั้งเดียว และถูกเรียกด้วย build
ของอินพุต มักใช้ในการสร้างตัวแปร (น้ำหนัก)
คุณสามารถเขียนเลเยอร์ MyDense
ด้านบนใหม่เพื่อให้มีความยืดหยุ่นตามขนาดของอินพุต:
class FlexibleDense(tf.keras.layers.Layer):
# Note the added `**kwargs`, as Keras supports many arguments
def __init__(self, out_features, **kwargs):
super().__init__(**kwargs)
self.out_features = out_features
def build(self, input_shape): # Create the state of the layer (weights)
self.w = tf.Variable(
tf.random.normal([input_shape[-1], self.out_features]), name='w')
self.b = tf.Variable(tf.zeros([self.out_features]), name='b')
def call(self, inputs): # Defines the computation from inputs to outputs
return tf.matmul(inputs, self.w) + self.b
# Create the instance of the layer
flexible_dense = FlexibleDense(out_features=3)
ณ จุดนี้ โมเดลยังไม่ถูกสร้างขึ้น ดังนั้นจึงไม่มีตัวแปร:
flexible_dense.variables
[]ตัวยึดตำแหน่ง46
การเรียกใช้ฟังก์ชันจะจัดสรรตัวแปรที่มีขนาดเหมาะสม:
# Call it, with predictably random results
print("Model results:", flexible_dense(tf.constant([[2.0, 2.0, 2.0], [3.0, 3.0, 3.0]])))
Model results: tf.Tensor( [[-1.6998017 1.6444504 -1.3103955] [-2.5497022 2.4666753 -1.9655929]], shape=(2, 3), dtype=float32)
flexible_dense.variables
[<tf.Variable 'flexible_dense/w:0' shape=(3, 3) dtype=float32, numpy= array([[ 1.277462 , 0.5399406 , -0.301957 ], [-1.6277349 , 0.7374014 , -1.7651852 ], [-0.49962795, -0.45511687, 1.4119445 ]], dtype=float32)>, <tf.Variable 'flexible_dense/b:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>]
เนื่องจากมีการเรียกบิลด์เพียงครั้งเดียว อินพุตจะถูกปฏิเสธหาก build
อินพุตไม่เข้ากันกับตัวแปรของเลเยอร์:
try:
print("Model results:", flexible_dense(tf.constant([[2.0, 2.0, 2.0, 2.0]])))
except tf.errors.InvalidArgumentError as e:
print("Failed:", e)
Failed: In[0] mismatch In[1] shape: 4 vs. 3: [1,4] [3,3] 0 0 [Op:MatMul]ตัวยึดตำแหน่ง52
เลเยอร์ Keras มีคุณสมบัติพิเศษมากมายรวมถึง:
- การสูญเสียทางเลือก
- รองรับเมตริก
- การสนับสนุนในตัวสำหรับอาร์กิวเมนต์
training
ที่เป็นตัวเลือกเพื่อแยกความแตกต่างระหว่างการใช้การฝึกอบรมและการอนุมาน -
get_config
และfrom_config
ที่ให้คุณจัดเก็บการกำหนดค่าได้อย่างแม่นยำเพื่ออนุญาตการโคลนโมเดลใน Python
อ่านเกี่ยวกับสิ่งเหล่านี้ใน คู่มือฉบับเต็มสำหรับ เลเยอร์และโมเดลที่กำหนดเอง
รุ่น Keras
คุณสามารถกำหนดโมเดลของคุณเป็นเลเยอร์ Keras ที่ซ้อนกันได้
อย่างไรก็ตาม Keras ยังมีคลาสโมเดลที่มีคุณสมบัติครบถ้วนที่เรียกว่า tf.keras.Model
มันสืบทอดมาจาก tf.keras.layers.Layer
ดังนั้นโมเดล Keras สามารถใช้ ซ้อน และบันทึกได้ในลักษณะเดียวกับเลเยอร์ Keras รุ่น Keras มาพร้อมกับฟังก์ชันพิเศษที่ทำให้ง่ายต่อการฝึก ประเมิน โหลด บันทึก และแม้แต่ฝึกบนเครื่องหลายเครื่อง
คุณสามารถกำหนด SequentialModule
จากด้านบนด้วยโค้ดที่เกือบเหมือนกัน แปลง __call__
เป็น call()
อีกครั้ง และเปลี่ยนพาเรนต์:
class MySequentialModel(tf.keras.Model):
def __init__(self, name=None, **kwargs):
super().__init__(**kwargs)
self.dense_1 = FlexibleDense(out_features=3)
self.dense_2 = FlexibleDense(out_features=2)
def call(self, x):
x = self.dense_1(x)
return self.dense_2(x)
# You have made a Keras model!
my_sequential_model = MySequentialModel(name="the_model")
# Call it on a tensor, with random results
print("Model results:", my_sequential_model(tf.constant([[2.0, 2.0, 2.0]])))
Model results: tf.Tensor([[5.5604653 3.3511646]], shape=(1, 2), dtype=float32)
มีคุณลักษณะเดียวกันทั้งหมด รวมถึงตัวแปรการติดตามและโมดูลย่อย
my_sequential_model.variables
[<tf.Variable 'my_sequential_model/flexible_dense_1/w:0' shape=(3, 3) dtype=float32, numpy= array([[ 0.05627853, -0.9386015 , -0.77410126], [ 0.63149 , 1.0802224 , -0.37785745], [-0.24788402, -1.1076807 , -0.5956209 ]], dtype=float32)>, <tf.Variable 'my_sequential_model/flexible_dense_1/b:0' shape=(3,) dtype=float32, numpy=array([0., 0., 0.], dtype=float32)>, <tf.Variable 'my_sequential_model/flexible_dense_2/w:0' shape=(3, 2) dtype=float32, numpy= array([[-0.93912166, 0.77979285], [ 1.4049559 , -1.9380962 ], [-2.6039495 , 0.30885765]], dtype=float32)>, <tf.Variable 'my_sequential_model/flexible_dense_2/b:0' shape=(2,) dtype=float32, numpy=array([0., 0.], dtype=float32)>]
my_sequential_model.submodules
(<__main__.FlexibleDense at 0x7f7b48525550>, <__main__.FlexibleDense at 0x7f7b48508d10>)
การแทนที่ tf.keras.Model
เป็นแนวทาง Pythonic ในการสร้างแบบจำลอง TensorFlow หากคุณกำลังโยกย้ายโมเดลจากเฟรมเวิร์กอื่น สิ่งนี้สามารถทำได้ตรงไปตรงมามาก
หากคุณกำลังสร้างโมเดลที่เป็นการรวมเลเยอร์และอินพุตที่มีอยู่อย่างง่าย คุณสามารถประหยัดเวลาและพื้นที่โดยใช้ API การทำงาน ซึ่งมาพร้อมกับคุณสมบัติเพิ่มเติมเกี่ยวกับการสร้างโมเดลใหม่และสถาปัตยกรรม
นี่เป็นรุ่นเดียวกันกับ API ที่ใช้งานได้:
inputs = tf.keras.Input(shape=[3,])
x = FlexibleDense(3)(inputs)
x = FlexibleDense(2)(x)
my_functional_model = tf.keras.Model(inputs=inputs, outputs=x)
my_functional_model.summary()
Model: "model" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) [(None, 3)] 0 _________________________________________________________________ flexible_dense_3 (FlexibleDe (None, 3) 12 _________________________________________________________________ flexible_dense_4 (FlexibleDe (None, 2) 8 ================================================================= Total params: 20 Trainable params: 20 Non-trainable params: 0 _________________________________________________________________
my_functional_model(tf.constant([[2.0, 2.0, 2.0]]))
<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[8.219393, 4.511119]], dtype=float32)>
ความแตกต่างที่สำคัญในที่นี้คือ รูปร่างของอินพุตถูกระบุไว้ด้านหน้าซึ่งเป็นส่วนหนึ่งของกระบวนการสร้างฟังก์ชันการทำงาน อาร์กิวเมนต์ input_shape
ในกรณีนี้ไม่จำเป็นต้องระบุอย่างสมบูรณ์ คุณสามารถปล่อยให้บางมิติเป็น None
การบันทึกโมเดล Keras
โมเดล Keras สามารถถูกตรวจสอบได้ และจะมีลักษณะเหมือนกับ tf.Module
โมเดล Keras สามารถบันทึกได้ด้วย tf.saved_model.save()
เนื่องจากเป็นโมดูล อย่างไรก็ตาม รุ่น Keras มีวิธีอำนวยความสะดวกและฟังก์ชันอื่น ๆ :
my_sequential_model.save("exname_of_file")
INFO:tensorflow:Assets written to: exname_of_file/assets
สามารถโหลดกลับเข้าไปได้อย่างง่ายดายเช่นเดียวกัน:
reconstructed_model = tf.keras.models.load_model("exname_of_file")
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.
Keras SavedModels
ยังบันทึกสถานะการวัด การสูญเสีย และเครื่องมือเพิ่มประสิทธิภาพอีกด้วย
โมเดลที่สร้างใหม่นี้สามารถใช้ได้และจะให้ผลลัพธ์เดียวกันเมื่อเรียกใช้ข้อมูลเดียวกัน:
reconstructed_model(tf.constant([[2.0, 2.0, 2.0]]))
<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[5.5604653, 3.3511646]], dtype=float32)>
มีข้อมูลเพิ่มเติมเกี่ยวกับการบันทึกและการทำให้เป็นอนุกรมของโมเดล Keras รวมถึงการจัดเตรียมวิธีการกำหนดค่าสำหรับเลเยอร์ที่กำหนดเองสำหรับการสนับสนุนคุณลักษณะ ดู คำแนะนำในการบันทึกและซีเรีย ลไลซ์เซชัน
อะไรต่อไป
หากคุณต้องการทราบรายละเอียดเพิ่มเติมเกี่ยวกับ Keras คุณสามารถทำตามคำแนะนำของ Keras ได้ ที่นี่
อีกตัวอย่างหนึ่งของ API ระดับสูงที่สร้างบน tf.module
คือ Sonnet จาก DeepMind ซึ่งครอบคลุมใน เว็บไซต์ของตน