ดูบน TensorFlow.org | ทำงานใน Google Colab | ดูแหล่งที่มาบน GitHub | ดาวน์โหลดโน๊ตบุ๊ค |
import tensorflow as tf
TensorFlow 2.x รวมถึงการเปลี่ยนแปลงที่สำคัญในการ tf.summary
API ที่ใช้ในการเขียนข้อมูลสรุปสำหรับการแสดงใน TensorBoard
สิ่งที่เปลี่ยนไป
มันมีประโยชน์ที่จะคิดว่าของ tf.summary
API เป็นย่อยสอง APIs:
- ชุดปฏิบัติการสำหรับการบันทึกสรุปของแต่ละบุคคล -
summary.scalar()
,summary.histogram()
,summary.image()
,summary.audio()
และsummary.text()
- ซึ่งจะเรียกว่าอินไลน์จากโค้ดรูปแบบของคุณ - ตรรกะการเขียนที่รวบรวมบทสรุปแต่ละรายการเหล่านี้และเขียนลงในล็อกไฟล์ที่มีรูปแบบพิเศษ (ซึ่ง TensorBoard จะอ่านเพื่อสร้างการแสดงข้อมูล)
ใน TF 1.x
ทั้งสองส่วนได้ที่จะสายด้วยตนเองร่วมกัน - โดยการเรียกผลสรุป op ผ่าน Session.run()
และเรียก FileWriter.add_summary(output, step)
v1.summary.merge_all()
op ทำนี้ได้ง่ายขึ้นโดยใช้คอลเลกชันกราฟเพื่อรวมทุกผลสรุป op แต่วิธีการนี้ยังคงทำงานได้ไม่ดีสำหรับการดำเนินการความกระตือรือร้นและการควบคุมการไหลทำให้มันโดยเฉพาะอย่างยิ่งไม่เหมาะสำหรับ TF 2.x.
ใน TF 2.X
ทั้งสองส่วนมีการบูรณาการอย่างแน่นหนาและตอนนี้แต่ละ tf.summary
Ops เขียนข้อมูลของพวกเขาทันทีเมื่อดำเนินการ การใช้ API จากโค้ดโมเดลของคุณน่าจะยังดูคุ้นเคย แต่ตอนนี้มันเป็นมิตรกับการดำเนินการที่กระตือรือร้นในขณะที่ยังคงเข้ากันได้กับโหมดกราฟ การบูรณาการทั้งสองของ API หมายถึง summary.FileWriter
ตอนนี้เป็นส่วนหนึ่งของการดำเนินการบริบท TensorFlow และได้รับการเข้าถึงได้โดยตรงโดย tf.summary
Ops ดังนั้นนักเขียนกำหนดค่าเป็นส่วนหลักที่ลักษณะแตกต่างกัน
ตัวอย่างการใช้งานด้วยการดำเนินการอย่างกระตือรือร้น ค่าเริ่มต้นใน TF 2.x:
writer = tf.summary.create_file_writer("/tmp/mylogs/eager")
with writer.as_default():
for step in range(100):
# other model code would go here
tf.summary.scalar("my_metric", 0.5, step=step)
writer.flush()
ls /tmp/mylogs/eager
events.out.tfevents.1633086727.kokoro-gcp-ubuntu-prod-1386032077.31590.0.v2
ตัวอย่างการใช้งานด้วยการดำเนินการกราฟ tf.function:
writer = tf.summary.create_file_writer("/tmp/mylogs/tf_function")
@tf.function
def my_func(step):
with writer.as_default():
# other model code would go here
tf.summary.scalar("my_metric", 0.5, step=step)
for step in tf.range(100, dtype=tf.int64):
my_func(step)
writer.flush()
ls /tmp/mylogs/tf_function
events.out.tfevents.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.1.v2
ตัวอย่างการใช้งานกับการประมวลผลกราฟ TF 1.x แบบเดิม:
g = tf.compat.v1.Graph()
with g.as_default():
step = tf.Variable(0, dtype=tf.int64)
step_update = step.assign_add(1)
writer = tf.summary.create_file_writer("/tmp/mylogs/session")
with writer.as_default():
tf.summary.scalar("my_metric", 0.5, step=step)
all_summary_ops = tf.compat.v1.summary.all_v2_summary_ops()
writer_flush = writer.flush()
with tf.compat.v1.Session(graph=g) as sess:
sess.run([writer.init(), step.initializer])
for i in range(100):
sess.run(all_summary_ops)
sess.run(step_update)
sess.run(writer_flush)
ls /tmp/mylogs/session
events.out.tfevents.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.2.v2
กำลังแปลงรหัสของคุณ
แปลงที่มีอยู่ tf.summary
การใช้งานกับ TF 2.x API ไม่สามารถเชื่อถือได้โดยอัตโนมัติดังนั้น tf_upgrade_v2
สคริปต์ เพียงแค่ปรับเปลี่ยนทุกอย่างให้ tf.compat.v1.summary
ในการย้ายไปยัง TF 2.x คุณจะต้องปรับโค้ดของคุณดังนี้:
ชุดเริ่มต้นเขียนผ่าน
.as_default()
จะต้องนำเสนอที่จะใช้ปฏิบัติการสรุป- ซึ่งหมายความว่าดำเนินการ ops อย่างกระตือรือร้นหรือใช้ ops ในการสร้างกราฟ
- หากไม่มีตัวเขียนเริ่มต้น การดำเนินการสรุปจะกลายเป็นแบบไม่ต้องดำเนินการใดๆ
- นักเขียนเริ่มต้นทำไม่ได้ (ยัง) การเผยแพร่ทั่ว
@tf.function
ขอบเขตการดำเนินการ - พวกเขามีการตรวจพบก็ต่อเมื่อมีฟังก์ชั่นที่มีการตรวจสอบ - ดังนั้นวิธีที่ดีที่สุดคือการเรียกwriter.as_default()
ภายในร่างกายทำงานและเพื่อให้แน่ใจว่าวัตถุนักเขียน ยังคงมีอยู่ตราบใดที่@tf.function
จะถูกใช้
"ขั้นตอน" ค่าจะต้องผ่านเข้าไปในแต่ละ op ผ่านที่
step
การโต้แย้ง- TensorBoard ต้องการค่าขั้นตอนเพื่อแสดงข้อมูลเป็นอนุกรมเวลา
- การส่งผ่านที่ชัดเจนเป็นสิ่งจำเป็นเนื่องจากขั้นตอนสากลจาก TF 1.x ถูกลบออก ดังนั้น op แต่ละคนจะต้องทราบตัวแปรขั้นตอนที่ต้องการในการอ่าน
- เพื่อลดสำเร็จรูป, สนับสนุนการทดลองสำหรับการลงทะเบียนเป็นค่าเริ่มต้นขั้นตอนที่สามารถใช้ได้เป็น
tf.summary.experimental.set_step()
แต่นี่คือการทำงานชั่วคราวที่อาจจะมีการเปลี่ยนแปลงโดยไม่ต้องแจ้งให้ทราบล่วงหน้า
ลายเซ็นฟังก์ชันของการดำเนินการสรุปแต่ละรายการมีการเปลี่ยนแปลง
- ค่าที่ส่งคืนตอนนี้เป็นบูลีน (แสดงว่ามีการเขียนสรุปจริงหรือไม่)
- ชื่อพารามิเตอร์ที่สอง (ถ้าใช้) มีการเปลี่ยนแปลงจาก
tensor
ไปยังdata
-
collections
พารามิเตอร์ได้ถูกลบออก; คอลเลกชันเป็น TF 1.x เท่านั้น -
family
พารามิเตอร์ได้ถูกลบออก; เพียงแค่ใช้tf.name_scope()
[สำหรับผู้ใช้โหมดกราฟเดิม / การดำเนินการเซสชันเท่านั้น]
แรกเริ่มต้นเขียนด้วย
v1.Session.run(writer.init())
ใช้
v1.summary.all_v2_summary_ops()
จะได้รับทั้งหมด Ops TF 2.x สรุปรูปแบบของกราฟในปัจจุบันเช่นการดำเนินการพวกเขาผ่านทางSession.run()
ล้างนักเขียนที่มี
v1.Session.run(writer.flush())
และเช่นเดียวกันสำหรับclose()
ถ้ารหัส 1.x TF ของคุณแทนการใช้ tf.contrib.summary
API ก็มากขึ้นคล้ายกับ TF 2.x API เพื่อ tf_upgrade_v2
สคริปต์จะอัตโนมัติมากที่สุดของขั้นตอนการย้ายถิ่น (และเปล่งคำเตือนหรือข้อผิดพลาดสำหรับการใช้งานใด ๆ ที่ไม่สามารถ อพยพได้อย่างเต็มที่) ส่วนใหญ่มันเป็นเพียงแค่ปรับเปลี่ยนสาย API เพื่อ tf.compat.v2.summary
; ถ้าคุณต้องการเพียงเข้ากันได้กับ TF 2.x คุณสามารถวาง compat.v2
และอ้างอิงเพียงว่ามันเป็น tf.summary
เคล็ดลับเพิ่มเติม
นอกจากประเด็นสำคัญข้างต้นแล้ว ยังมีการเปลี่ยนแปลงด้านเสริมบางประการด้วย:
การบันทึกแบบมีเงื่อนไข (เช่น "บันทึกทุกๆ 100 ขั้นตอน") มีรูปลักษณ์ใหม่
- การปฏิบัติการควบคุมและรหัสที่เกี่ยวข้องห่อไว้ในปกติถ้ามีคำสั่ง (ซึ่งทำงานในโหมดความกระตือรือร้นและ
@tf.function
ผ่านลายเซ็น ) หรือtf.cond
- ในการควบคุมเพียงสรุปใช้ใหม่
tf.summary.record_if()
ผู้จัดการบริบทและผ่านมันสภาพบูลที่คุณเลือก สิ่งเหล่านี้แทนที่รูปแบบ TF 1.x:
if condition: writer.add_summary()
- การปฏิบัติการควบคุมและรหัสที่เกี่ยวข้องห่อไว้ในปกติถ้ามีคำสั่ง (ซึ่งทำงานในโหมดความกระตือรือร้นและ
ไม่มีการเขียนโดยตรงของ
tf.compat.v1.Graph
- แทนฟังก์ชั่นการใช้งานการติดตาม- การดำเนินการในการใช้กราฟ TF 2.x
@tf.function
แทนอย่างชัดเจนกราฟ - ใน TF 2.x, ใช้ API ใหม่การติดตามสไตล์
tf.summary.trace_on()
และtf.summary.trace_export()
เพื่อบันทึกดำเนินกราฟฟังก์ชั่น
- การดำเนินการในการใช้กราฟ TF 2.x
ไม่มีแคชนักเขียนระดับโลกมากขึ้นต่อ logdir กับ
tf.summary.FileWriterCache
- ผู้ใช้ก็ควรจะใช้แคชของตัวเอง / ใช้งานร่วมกันของวัตถุที่นักเขียนหรือเพียงแค่ใช้นักเขียนแยกต่างหาก (สนับสนุน TensorBoard สำหรับหลังคือ ในความคืบหน้า )
การแสดงไบนารีของไฟล์เหตุการณ์เปลี่ยนไป
- TensorBoard 1.x รองรับรูปแบบใหม่แล้ว ความแตกต่างนี้มีผลกับผู้ใช้ที่แยกวิเคราะห์ข้อมูลสรุปจากไฟล์เหตุการณ์ด้วยตนเองเท่านั้น
- ข้อมูลสรุปถูกจัดเก็บเป็นเทนเซอร์ไบต์ คุณสามารถใช้
tf.make_ndarray(event.summary.value[0].tensor)
เพื่อแปลงเป็น numpy