UPDATE - 2020/01/15 : การปฏิบัติที่ดีที่สุดในปัจจุบันสำหรับขนาดชุดเล็กควรจะเป็นปัจจัยการผลิตฟีดกับรูปแบบโดยตรง - คือpreds = model(x)
และถ้าชั้นทำงานแตกต่างกันที่รถไฟ / model(x, training=False)
การอนุมาน ตามการกระทำล่าสุดสิ่งนี้ได้รับการบันทึกไว้แล้ว
ฉันไม่ได้เปรียบเทียบสิ่งเหล่านี้ แต่ตามการอภิปรายของ Gitมันก็คุ้มค่าที่จะลองpredict_on_batch()
- โดยเฉพาะอย่างยิ่งกับการปรับปรุงใน TF 2.1
ULTIMATE ผู้ร้ายself._experimental_run_tf_function = True
: มันเป็นเรื่องการทดลอง แต่มันก็ไม่ได้เลวร้ายจริงๆ
เพื่อ TensorFlow ใด devs อ่าน: ทำความสะอาดรหัสของคุณ มันเป็นระเบียบ และมีการละเมิดการปฏิบัติการเข้ารหัสที่สำคัญเช่นฟังก์ชันหนึ่งไม่สิ่งหนึ่ง ; _process_inputs
ไม่ได้มากขึ้นกว่า "ปัจจัยการผลิตกระบวนการ" _standardize_user_data
เหมือนกันสำหรับ "ฉันไม่ได้รับเงินมากพอ" - แต่คุณต้องจ่ายเงินเพิ่มในการใช้เวลาทำความเข้าใจกับสิ่งของของคุณเองและในผู้ใช้ที่กรอกหน้าปัญหาของคุณด้วยข้อบกพร่องที่แก้ไขได้ง่ายขึ้นด้วยรหัสที่ชัดเจนขึ้น
สรุป : เป็นเพียงเล็ก ๆ น้อย ๆcompile()
ช้าลงด้วย
compile()
predict
ชุดธงชาติภายในที่กำหนดฟังก์ชั่นการคาดการณ์ที่แตกต่างกันไป ฟังก์ชั่นนี้สร้างกราฟใหม่ตามการโทรแต่ละครั้งทำให้ช้าลงเมื่อเทียบกับการไม่คอมไพล์ อย่างไรก็ตามความแตกต่างนั้นเด่นชัดก็ต่อเมื่อเวลารถไฟสั้นกว่าเวลาประมวลผลข้อมูลมากเท่านั้น ถ้าเราเพิ่มขนาดโมเดลเป็นอย่างน้อยขนาดกลางทั้งสองจะเท่ากัน ดูรหัสที่ด้านล่าง
เวลาในการประมวลผลข้อมูลที่เพิ่มขึ้นเล็กน้อยนี้เป็นมากกว่าการชดเชยด้วยความสามารถในการขยายกราฟ เนื่องจากมีประสิทธิภาพมากกว่าที่จะเก็บกราฟของโมเดลเพียงอันเดียวไว้ล่วงหน้าคอมไพล์หนึ่งรายการจะถูกยกเลิก อย่างไรก็ตาม : ถ้าแบบจำลองของคุณมีขนาดเล็กเมื่อเทียบกับข้อมูลคุณจะดีขึ้นโดยไม่มีcompile()
การอนุมานแบบ ดูคำตอบอื่น ๆ ของฉันสำหรับวิธีแก้ปัญหา
ฉันควรทำอย่างไรดี?
เปรียบเทียบประสิทธิภาพของรุ่นที่คอมไพล์แล้วเทียบกับคอมไพล์อย่างที่ฉันมีในโค้ดที่ด้านล่าง
- รวบรวมได้เร็วขึ้น : ทำงาน
predict
ในรูปแบบที่รวบรวม
- การคอมไพล์ช้ากว่า : รัน
predict
บนโมเดลที่ไม่ได้คอมไพล์
ใช่ทั้งสองเป็นไปได้และมันจะขึ้นอยู่กับขนาดข้อมูล (1); (2) ขนาดรูปแบบ; (3) ฮาร์ดแวร์ โค้ดที่ด้านล่างแสดงแบบจำลองที่คอมไพล์ได้เร็วขึ้น แต่การทำซ้ำ 10 ครั้งเป็นตัวอย่างขนาดเล็ก ดู "วิธีแก้ไขปัญหา" ในคำตอบอื่น ๆ ของฉันสำหรับ "วิธีการ"
รายละเอียด :
การแก้จุดบกพร่องใช้เวลาสักครู่ แต่ก็สนุก ด้านล่างฉันอธิบายถึงต้นเหตุสำคัญที่ฉันค้นพบอ้างอิงเอกสารที่เกี่ยวข้องและแสดงผลลัพธ์ของผู้สร้างโปรไฟล์ที่นำไปสู่ปัญหาคอขวดในที่สุด
( FLAG == self.experimental_run_tf_function
สำหรับความกะทัดรัด)
Model
FLAG=False
โดยเริ่มต้นด้วย instantiates ชุดมันไปcompile()
True
predict()
เกี่ยวข้องกับการรับฟังก์ชั่นการทำนาย func = self._select_training_loop(x)
- หากไม่มี kwargs พิเศษใด ๆ ที่ส่งผ่านไปยัง
predict
และcompile
แฟล็กอื่น ๆ ทั้งหมดจะเป็นเช่นนั้น:
- (A)
FLAG==True
->func = training_v2.Loop()
- (B)
FLAG==False
->func = training_arrays.ArrayLikeTrainingLoop()
- จากซอร์สโค้ด docstring , (A)เป็นกราฟที่พึ่งพาได้อย่างมากใช้กลยุทธ์การกระจายมากขึ้นและ ops มีแนวโน้มที่จะสร้างและทำลายองค์ประกอบกราฟซึ่ง "อาจ" (ทำ) ส่งผลกระทบต่อประสิทธิภาพ
ผู้กระทำผิดที่แท้จริง : _process_inputs()
คิดเป็น81% ของรันไทม์ เป็นองค์ประกอบหลักหรือไม่ _create_graph_function()
, 72% ของรันไทม์ วิธีการนี้ไม่ได้มีอยู่สำหรับ(B) โดยใช้แบบจำลองขนาดกลาง แต่_process_inputs
ประกอบด้วยน้อยกว่า 1% ของรันไทม์ โค้ดที่ด้านล่างและติดตามผลลัพธ์การทำโปรไฟล์
ตัวประมวลผลข้อมูล :
(A) : ใช้ในการ<class 'tensorflow.python.keras.engine.data_adapter.TensorLikeDataAdapter'>
ซอร์สโค้ดที่เกี่ยวข้อง_process_inputs()
(B) : กลับโดยnumpy.ndarray
ซอร์สโค้ดที่เกี่ยวข้องและที่นี่convert_eager_tensors_to_numpy
ฟังก์ชั่นการใช้งาน MODEL (เช่นทำนาย)
(A) : ฟังก์ชั่นการกระจายและที่นี่
(B) : ฟังก์ชั่นการกระจาย (แตกต่างกัน)และที่นี่
PROFILER : ผลลัพธ์สำหรับโค้ดในคำตอบอื่น ๆ ของฉัน "รุ่นจิ๋ว" และในคำตอบนี้ "โมเดลขนาดกลาง":
โมเดลจิ๋ว : 1,000 รอบcompile()
รุ่นจิ๋ว : 1,000 รอบซ้ำไม่ compile()
โมเดลขนาดกลาง : 10 ซ้ำ
เอกสาร (ทางอ้อม) เกี่ยวกับผลกระทบของcompile()
: แหล่งที่มา
ซึ่งแตกต่างจากการดำเนินงานของ TensorFlow อื่น ๆ เราไม่แปลงอินพุตตัวเลขหลามเป็นเมตริกซ์ ยิ่งไปกว่านั้นกราฟใหม่จะถูกสร้างขึ้นสำหรับค่าตัวเลขไพ ธ อนแต่ละตัวเช่นการโทรg(2)
และg(3)
จะสร้างกราฟใหม่สองกราฟ
function
instantiates กราฟแยกต่างหากสำหรับทุกชุดที่เป็นเอกลักษณ์ของรูปทรงเข้าและประเภทข้อมูล ตัวอย่างเช่นข้อมูลโค้ดต่อไปนี้จะส่งผลให้มีการติดตามกราฟที่แตกต่างกันสามกราฟเนื่องจากแต่ละอินพุตมีรูปร่างที่แตกต่างกัน
วัตถุ tf.function เดียวอาจจำเป็นต้องแมปไปยังกราฟการคำนวณหลายอันภายใต้ประทุน สิ่งนี้ควรปรากฏให้เห็นเฉพาะเมื่อมีประสิทธิภาพ (กราฟการติดตามมีค่าใช้จ่ายในการคำนวณและหน่วยความจำที่ไม่ใช่ศูนย์ ) แต่ไม่ควรส่งผลกระทบต่อความถูกต้องของโปรแกรม
COUNTEREXAMPLE :
from tensorflow.keras.layers import Input, Dense, LSTM, Bidirectional, Conv1D
from tensorflow.keras.layers import Flatten, Dropout
from tensorflow.keras.models import Model
import numpy as np
from time import time
def timeit(func, arg, iterations):
t0 = time()
for _ in range(iterations):
func(arg)
print("%.4f sec" % (time() - t0))
batch_size = 32
batch_shape = (batch_size, 400, 16)
ipt = Input(batch_shape=batch_shape)
x = Bidirectional(LSTM(512, activation='relu', return_sequences=True))(ipt)
x = LSTM(512, activation='relu', return_sequences=True)(ipt)
x = Conv1D(128, 400, 1, padding='same')(x)
x = Flatten()(x)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
x = Dense(128, activation='relu')(x)
x = Dense(64, activation='relu')(x)
out = Dense(1, activation='sigmoid')(x)
model = Model(ipt, out)
X = np.random.randn(*batch_shape)
timeit(model.predict, X, 10)
model.compile('adam', loss='binary_crossentropy')
timeit(model.predict, X, 10)
เอาท์พุท :
34.8542 sec
34.7435 sec