Secara teori, prediksi harus konstan karena bobot memiliki ukuran tetap. Bagaimana saya mendapatkan kembali kecepatan saya setelah dikompilasi (tanpa perlu menghapus optimizer)?
Lihat eksperimen terkait: https://nbviewer.jupyter.org/github/off99555/TensorFlowExperiments/blob/master/test-prediction-speed-after-compile.ipynb?flush_cache=true
python
performance
tensorflow
keras
jupyter-notebook
off99555
sumber
sumber
fit
tanpacompile
; Pengoptimal bahkan tidak ada untuk memperbarui bobot.predict
dapat digunakan tanpafit
ataucompile
seperti yang dijelaskan dalam jawaban saya, tetapi perbedaan kinerja seharusnya tidak sedramatis ini - karena itu masalahnya.Jawaban:
UPDATE - 1/15/2020 : praktik terbaik saat ini untuk ukuran batch kecil adalah untuk memberi makan input ke model secara langsung - yaitu
preds = model(x)
, dan jika lapisan berperilaku berbeda di kereta / inferensimodel(x, training=False)
,. Per komit terbaru, ini sekarang didokumentasikan .Saya belum membuat tolok ukur ini, tetapi per diskusi Git , ini juga layak untuk dicoba
predict_on_batch()
- terutama dengan peningkatan pada TF 2.1.ULTIMATE PENYEBAB :
self._experimental_run_tf_function = True
. Itu eksperimental . Tapi itu sebenarnya tidak buruk.Untuk membaca pengembang TensorFlow: bersihkan kode Anda . Ini berantakan. Dan itu melanggar praktik pengkodean penting, seperti satu fungsi melakukan satu hal ;
_process_inputs
melakukan banyak lebih dari "input proses", sama untuk_standardize_user_data
. "Saya tidak dibayar cukup" - tetapi Anda lakukan membayar, di waktu tambahan menghabiskan memahami barang-barang Anda sendiri, dan pada pengguna mengisi halaman Masalah Anda dengan bug lebih mudah diselesaikan dengan kode yang lebih jelas.RINGKASAN : Hanya sedikit lebih lambat
compile()
.compile()
menetapkan bendera internal yang menetapkan fungsi prediksi berbedapredict
. Fungsi ini membangun grafik baru pada setiap panggilan, memperlambatnya relatif terhadap yang tidak dikompilasi. Namun, perbedaannya hanya diucapkan ketika waktu kereta jauh lebih pendek dari waktu pemrosesan data . Jika kita meningkatkan ukuran model menjadi setidaknya menengah, keduanya menjadi sama. Lihat kode di bagian bawah.Sedikit peningkatan dalam waktu pemrosesan data ini lebih dari dikompensasi oleh kemampuan grafik yang diperkuat. Karena lebih efisien jika hanya menyimpan satu grafik model, satu pra-kompilasi dibuang. Meskipun demikian : jika model Anda relatif kecil terhadap data, Anda lebih baik tanpa
compile()
inferensi model. Lihat jawaban saya yang lain untuk solusinya.APA YANG HARUS SAYA LAKUKAN?
Bandingkan kinerja model yang dikompilasi vs yang tidak dikompilasi seperti yang saya miliki dalam kode di bagian bawah.
predict
pada model yang dikompilasi.predict
pada model yang tidak dikompilasi.Ya, keduanya mungkin, dan itu akan tergantung pada (1) ukuran data; (2) ukuran model; (3) perangkat keras. Kode di bagian bawah sebenarnya menunjukkan model yang dikompilasi menjadi lebih cepat, tetapi 10 iterasi adalah sampel kecil. Lihat "pemecahan masalah" di jawaban saya yang lain untuk "bagaimana caranya".
RINCIAN :
Butuh beberapa saat untuk debug, tetapi menyenangkan. Di bawah ini saya menggambarkan penyebab utama yang saya temukan, mengutip beberapa dokumentasi yang relevan, dan menunjukkan hasil profiler yang mengarah pada hambatan utama.
(
FLAG == self.experimental_run_tf_function
, untuk singkatnya)Model
secara instantiate default denganFLAG=False
.compile()
set keTrue
.predict()
melibatkan perolehan fungsi prediksi,func = self._select_training_loop(x)
predict
dancompile
, semua bendera lainnya sedemikian rupa sehingga:FLAG==True
->func = training_v2.Loop()
FLAG==False
->func = training_arrays.ArrayLikeTrainingLoop()
Benar pelakunya :
_process_inputs()
, akuntansi untuk 81% dari runtime . Komponen utamanya?_create_graph_function()
, 72% dari runtime . Metode ini bahkan tidak ada untuk (B) . Menggunakan model menengah, bagaimanapun,_process_inputs
terdiri dari kurang dari 1% dari runtime . Kode di bawah, dan hasil profiling mengikuti.PROSESOR DATA :
(A) :,
<class 'tensorflow.python.keras.engine.data_adapter.TensorLikeDataAdapter'>
digunakan dalam_process_inputs()
. Kode sumber yang relevan(B) :
numpy.ndarray
, dikembalikan olehconvert_eager_tensors_to_numpy
. Kode sumber yang relevan , dan di siniFUNGSI PELAKSANAAN MODEL (mis. Prediksi)
(A) : fungsi distribusi , dan di sini
(B) : fungsi distribusi (berbeda) , dan di sini
PROFILER : hasil untuk kode di jawaban saya yang lain, "model kecil", dan dalam jawaban ini, "model sedang":
Model kecil : 1000 iterasi,
compile()
Model kecil : 1000 iterasi, no
compile()
Model medium : 10 iterasi
DOKUMENTASI (tidak langsung) pada efek dari
compile()
: sumberCONTOH COUNTER :
Output :
sumber
compile()
?PEMBARUAN : lihat jawaban aktual yang diposting sebagai jawaban terpisah; posting ini mengandung info tambahan
.compile()
mengatur sebagian besar grafik TF / Keras, termasuk kerugian, metrik, gradien, dan sebagian pengoptimal dan bobotnya - yang menjamin perlambatan yang mencolok.Yang tidak terduga adalah tingkat perlambatan - 10 kali lipat pada percobaan saya sendiri, dan untuk
predict()
, yang tidak memperbarui bobot. Melihat ke kode sumber TF2, elemen grafik tampak saling terkait erat, dengan sumber daya tidak selalu dialokasikan "secara adil".Kemungkinan diabaikan oleh pengembang tentang
predict
kinerja untuk model yang tidak dikompilasi, karena model biasanya digunakan dikompilasi - tetapi dalam praktiknya , ini adalah perbedaan yang tidak dapat diterima. Mungkin juga itu adalah "kejahatan yang perlu", karena ada solusi sederhana (lihat di bawah).Ini bukan jawaban yang lengkap, dan saya harap seseorang dapat menyediakannya di sini - jika tidak, saya sarankan membuka masalah Github di TensorFlow. (OP memiliki; di sini )
Penanganan masalah : latih model, simpan bobotnya , bangun kembali model tanpa kompilasi, muat bobot. Jangan tidak menyimpan seluruh model (misalnya
model.save()
), karena akan beban yang disusun - bukan menggunakanmodel.save_weights()
danmodel.load_weights()
.Solusi 2 : di atas, tetapi gunakan
load_model(path, compile=False)
; kredit saran: D. MöllerUPDATE : untuk memperjelas, optimizer yang tidak sepenuhnya dipakai dengan
compile
, termasuk yangweights
danupdates
tensor - ini dilakukan ketika panggilan pertama ke fungsi pas dibuat (fit
,train_on_batch
, dll), melaluimodel._make_train_function()
.Perilaku yang diamati dengan demikian bahkan lebih aneh. Lebih buruk lagi, membangun optimizer tidak menimbulkan perlambatan lebih lanjut (lihat di bawah) - menunjukkan "ukuran grafik" bukan penjelasan utama di sini.
EDIT : pada beberapa model, penurunan 30x . TensorFlow, apa yang sudah kamu lakukan. Contoh di bawah ini:
Output :
sumber
model.fit()
versus loop dinamis dengan eksekusi bersemangat untuk melihat apakah kehilangan kinerja terlalu besar ...load_model(name, compile=False)
, ini lebih sederhana daripada menyimpan / memuat bobot dan membuat ulang model.