Tutorial ini menunjukkan cara menggunakan komponen TensorFlow Serving untuk membuat TensorFlow ModelServer standar yang secara dinamis menemukan dan menyajikan versi baru model TensorFlow terlatih. Jika Anda hanya ingin menggunakan server standar untuk menyajikan model Anda, lihat tutorial dasar Penyajian TensorFlow .
Tutorial ini menggunakan model Regresi Softmax sederhana yang diperkenalkan dalam tutorial TensorFlow untuk klasifikasi gambar tulisan tangan (data MNIST). Jika Anda belum mengetahui apa itu TensorFlow atau MNIST, lihat tutorial MNIST Untuk Pemula ML .
Kode untuk tutorial ini terdiri dari dua bagian:
File Python mnist_saved_model.py yang melatih dan mengekspor beberapa versi model.
File C++ main.cc yang merupakan TensorFlow ModelServer standar yang menemukan model baru yang diekspor dan menjalankan layanan gRPC untuk menyajikannya.
Tutorial ini langkah-langkah melalui tugas-tugas berikut:
- Latih dan ekspor model TensorFlow.
- Kelola pembuatan versi model dengan TensorFlow Serving
ServerCore
. - Konfigurasikan pengelompokan menggunakan
SavedModelBundleSourceAdapterConfig
. - Sajikan permintaan dengan TensorFlow Melayani
ServerCore
. - Jalankan dan uji layanan.
Sebelum memulai, instal dulu Docker
Latih dan ekspor Model TensorFlow
Pertama, jika Anda belum melakukannya, kloning repositori ini ke mesin lokal Anda:
git clone https://github.com/tensorflow/serving.git
cd serving
Hapus direktori ekspor jika sudah ada:
rm -rf /tmp/models
Latih (dengan 100 iterasi) dan ekspor model versi pertama:
tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
--training_iteration=100 --model_version=1 /tmp/mnist
Latih (dengan 2000 iterasi) dan ekspor model versi kedua:
tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
--training_iteration=2000 --model_version=2 /tmp/mnist
Seperti yang Anda lihat di mnist_saved_model.py
, pelatihan dan ekspor dilakukan dengan cara yang sama seperti di tutorial dasar Penyajian TensorFlow . Untuk tujuan demonstrasi, Anda dengan sengaja menurunkan iterasi pelatihan untuk proses pertama dan mengekspornya sebagai v1, sambil melatihnya secara normal untuk proses kedua dan mengekspornya sebagai v2 ke direktori induk yang sama -- seperti yang kami harapkan akan dicapai oleh yang terakhir akurasi klasifikasi yang lebih baik karena pelatihan yang lebih intensif. Anda akan melihat data pelatihan untuk setiap pelatihan yang dijalankan di direktori /tmp/mnist
Anda:
$ ls /tmp/mnist
1 2
ServerCore
Sekarang bayangkan model v1 dan v2 dihasilkan secara dinamis saat runtime, saat algoritme baru sedang diujicobakan, atau saat model dilatih dengan kumpulan data baru. Dalam lingkungan produksi, Anda mungkin ingin membangun server yang dapat mendukung peluncuran bertahap, di mana v2 dapat ditemukan, dimuat, diujicobakan, dipantau, atau dikembalikan saat menyajikan v1. Alternatifnya, Anda mungkin ingin menghapus v1 sebelum membuka v2. TensorFlow Serving mendukung kedua opsi tersebut -- meskipun opsi yang satu bagus untuk menjaga ketersediaan selama transisi, opsi lainnya bagus untuk meminimalkan penggunaan sumber daya (misalnya RAM).
TensorFlow Serving Manager
melakukan hal itu. Ini menangani siklus hidup penuh model TensorFlow termasuk memuat, menyajikan, dan membongkar model tersebut serta transisi versi. Dalam tutorial ini, Anda akan membangun server di atas TensorFlow Serving ServerCore
, yang secara internal membungkus AspiredVersionsManager
.
int main(int argc, char** argv) {
...
ServerCore::Options options;
options.model_server_config = model_server_config;
options.servable_state_monitor_creator = &CreateServableStateMonitor;
options.custom_model_config_loader = &LoadCustomModelConfig;
::google::protobuf::Any source_adapter_config;
SavedModelBundleSourceAdapterConfig
saved_model_bundle_source_adapter_config;
source_adapter_config.PackFrom(saved_model_bundle_source_adapter_config);
(*(*options.platform_config_map.mutable_platform_configs())
[kTensorFlowModelPlatform].mutable_source_adapter_config()) =
source_adapter_config;
std::unique_ptr<ServerCore> core;
TF_CHECK_OK(ServerCore::Create(options, &core));
RunServer(port, std::move(core));
return 0;
}
ServerCore::Create()
mengambil parameter ServerCore::Options. Berikut beberapa opsi yang umum digunakan:
-
ModelServerConfig
yang menentukan model yang akan dimuat. Model dideklarasikan melaluimodel_config_list
, yang mendeklarasikan daftar model statis, atau melaluicustom_model_config
, yang mendefinisikan cara khusus untuk mendeklarasikan daftar model yang mungkin diperbarui saat runtime. -
PlatformConfigMap
yang memetakan dari nama platform (sepertitensorflow
) kePlatformConfig
, yang digunakan untuk membuatSourceAdapter
.SourceAdapter
mengadaptasiStoragePath
(jalur tempat versi model ditemukan) ke modelLoader
(memuat versi model dari jalur penyimpanan dan menyediakan antarmuka transisi status keManager
). JikaPlatformConfig
berisiSavedModelBundleSourceAdapterConfig
,SavedModelBundleSourceAdapter
akan dibuat, yang akan kami jelaskan nanti.
SavedModelBundle
adalah komponen kunci dari TensorFlow Serving. Ini mewakili model TensorFlow yang dimuat dari jalur tertentu dan menyediakan antarmuka Session::Run
yang sama dengan TensorFlow untuk menjalankan inferensi. SavedModelBundleSourceAdapter
mengadaptasi jalur penyimpanan ke Loader<SavedModelBundle>
sehingga masa pakai model dapat dikelola oleh Manager
. Harap perhatikan bahwa SavedModelBundle
adalah penerus SessionBundle
yang tidak digunakan lagi. Pengguna dianjurkan untuk menggunakan SavedModelBundle
karena dukungan untuk SessionBundle
akan segera dihapus.
Dengan semua ini, ServerCore
secara internal melakukan hal berikut:
- Membuat instance
FileSystemStoragePathSource
yang memantau jalur ekspor model yang dideklarasikan dalammodel_config_list
. - Membuat instance
SourceAdapter
menggunakanPlatformConfigMap
dengan platform model yang dideklarasikan dalammodel_config_list
dan menghubungkanFileSystemStoragePathSource
ke platform tersebut. Dengan cara ini, setiap kali versi model baru ditemukan di jalur ekspor,SavedModelBundleSourceAdapter
menyesuaikannya denganLoader<SavedModelBundle>
. - Membuat instance implementasi spesifik
Manager
yang disebutAspiredVersionsManager
yang mengelola semua instanceLoader
yang dibuat olehSavedModelBundleSourceAdapter
.ServerCore
mengekspor antarmukaManager
dengan mendelegasikan panggilan keAspiredVersionsManager
.
Setiap kali versi baru tersedia, AspiredVersionsManager
ini memuat versi baru, dan berdasarkan perilaku defaultnya, membongkar versi lama. Jika Anda ingin mulai melakukan penyesuaian, Anda dianjurkan untuk memahami komponen yang dibuat secara internal, dan cara mengonfigurasinya.
Perlu disebutkan bahwa TensorFlow Serving dirancang dari awal agar sangat fleksibel dan dapat diperluas. Anda dapat membuat berbagai plugin untuk menyesuaikan perilaku sistem, sambil memanfaatkan komponen inti umum seperti ServerCore
dan AspiredVersionsManager
. Misalnya, Anda dapat membuat plugin sumber data yang memantau penyimpanan cloud, bukan penyimpanan lokal, atau Anda dapat membuat plugin kebijakan versi yang melakukan transisi versi dengan cara berbeda -- bahkan, Anda bahkan dapat membuat plugin model kustom yang berfungsi model non-TensorFlow. Topik-topik ini berada di luar cakupan tutorial ini. Namun, Anda dapat merujuk ke sumber kustom dan tutorial kustom yang dapat diservis untuk informasi lebih lanjut.
Pengelompokan
Fitur khas server lainnya yang kami inginkan dalam lingkungan produksi adalah batching. Akselerator perangkat keras modern (GPU, dll.) yang digunakan untuk melakukan inferensi pembelajaran mesin biasanya mencapai efisiensi komputasi terbaik ketika permintaan inferensi dijalankan dalam jumlah besar.
Batching dapat diaktifkan dengan menyediakan SessionBundleConfig
yang tepat saat membuat SavedModelBundleSourceAdapter
. Dalam hal ini kami menetapkan BatchingParameters
dengan nilai default yang cukup banyak. Batching dapat disempurnakan dengan mengatur nilai batas waktu khusus, ukuran_batch, dll. Untuk detailnya, silakan merujuk ke BatchingParameters
.
SessionBundleConfig session_bundle_config;
// Batching config
if (enable_batching) {
BatchingParameters* batching_parameters =
session_bundle_config.mutable_batching_parameters();
batching_parameters->mutable_thread_pool_name()->set_value(
"model_server_batch_threads");
}
*saved_model_bundle_source_adapter_config.mutable_legacy_config() =
session_bundle_config;
Setelah mencapai batch penuh, permintaan inferensi digabungkan secara internal menjadi satu permintaan besar (tensor), dan tensorflow::Session::Run()
dipanggil (dari situlah peningkatan efisiensi aktual pada GPU berasal).
Sajikan dengan Manajer
Seperti disebutkan di atas, TensorFlow Serving Manager
dirancang untuk menjadi komponen umum yang dapat menangani pemuatan, penyajian, pembongkaran, dan transisi versi model yang dihasilkan oleh sistem pembelajaran mesin arbitrer. API-nya dibangun berdasarkan konsep-konsep utama berikut:
Servable : Servable adalah objek buram apa pun yang dapat digunakan untuk melayani permintaan klien. Ukuran dan granularitas dari suatu yang dapat diservis bersifat fleksibel, sehingga satu yang dapat diservis dapat mencakup apa saja, mulai dari satu pecahan tabel pencarian, satu model yang dipelajari mesin, hingga serangkaian model. Server dapat berupa jenis dan antarmuka apa pun.
Versi yang Dapat Diservis : Servable memiliki versi dan TensorFlow Serving
Manager
dapat mengelola satu atau lebih versi dari sebuah servable. Pembuatan versi memungkinkan lebih dari satu versi server yang dapat dimuat secara bersamaan, mendukung peluncuran dan eksperimen bertahap.Aliran yang Dapat Diservis : Aliran yang dapat diservis adalah urutan versi dari sebuah yang dapat diservis, dengan nomor versi yang semakin bertambah.
Model : Model yang dipelajari mesin diwakili oleh satu atau lebih yang dapat diservis. Contoh yang dapat diservis adalah:
- Sesi TensorFlow atau pembungkus di sekitarnya, seperti
SavedModelBundle
. - Jenis model pembelajaran mesin lainnya.
- Tabel pencarian kosakata.
- Menyematkan tabel pencarian.
Model komposit dapat direpresentasikan sebagai beberapa server independen, atau sebagai satu server komposit. Suatu yang dapat diservis mungkin juga sesuai dengan sebagian kecil Model, misalnya dengan tabel pencarian besar yang dibagi ke dalam banyak instans
Manager
.- Sesi TensorFlow atau pembungkus di sekitarnya, seperti
Untuk memasukkan semua ini ke dalam konteks tutorial ini:
Model TensorFlow diwakili oleh satu jenis servable --
SavedModelBundle
.SavedModelBundle
secara internal terdiri daritensorflow:Session
yang dipasangkan dengan beberapa metadata tentang grafik apa yang dimuat ke dalam sesi dan cara menjalankannya untuk inferensi.Terdapat direktori sistem file yang berisi aliran ekspor TensorFlow, masing-masing dalam subdirektorinya sendiri yang namanya merupakan nomor versi. Direktori luar dapat dianggap sebagai representasi serial dari aliran yang dapat diservis untuk model TensorFlow yang disajikan. Setiap ekspor sesuai dengan server yang dapat dimuat.
AspiredVersionsManager
memantau aliran ekspor, dan mengelola siklus hidup semua servisSavedModelBundle
secara dinamis.
TensorflowPredictImpl::Predict
lalu:
- Meminta
SavedModelBundle
dari manajer (melalui ServerCore). - Menggunakan
generic signatures
untuk memetakan nama tensor logis diPredictRequest
ke nama tensor sebenarnya dan mengikat nilai ke tensor. - Menjalankan inferensi.
Uji dan jalankan server
Salin versi ekspor pertama ke folder yang dipantau:
mkdir /tmp/monitored
cp -r /tmp/mnist/1 /tmp/monitored
Kemudian mulai server:
docker run -p 8500:8500 \
--mount type=bind,source=/tmp/monitored,target=/models/mnist \
-t --entrypoint=tensorflow_model_server tensorflow/serving --enable_batching \
--port=8500 --model_name=mnist --model_base_path=/models/mnist &
Server akan mengeluarkan pesan log setiap satu detik yang mengatakan "Versi yang bercita-cita untuk dapat diservis ...", yang berarti server telah menemukan ekspor, dan melacak kelanjutan keberadaannya.
Mari kita jalankan klien dengan --concurrency=10
. Ini akan mengirimkan permintaan bersamaan ke server dan dengan demikian memicu logika batching Anda.
tools/run_in_docker.sh python tensorflow_serving/example/mnist_client.py \
--num_tests=1000 --server=127.0.0.1:8500 --concurrency=10
Yang menghasilkan output seperti:
...
Inference error rate: 13.1%
Kemudian kami menyalin versi kedua ekspor ke folder yang dipantau dan menjalankan kembali pengujian:
cp -r /tmp/mnist/2 /tmp/monitored
tools/run_in_docker.sh python tensorflow_serving/example/mnist_client.py \
--num_tests=1000 --server=127.0.0.1:8500 --concurrency=10
Yang menghasilkan output seperti:
...
Inference error rate: 9.5%
Ini mengonfirmasi bahwa server Anda secara otomatis menemukan versi baru dan menggunakannya untuk melayani!