Tutorial ini menunjukkan cara menggunakan komponen TensorFlow Serving untuk membangun TensorFlow ModelServer standar yang secara dinamis menemukan dan menyajikan versi baru model TensorFlow terlatih. Jika Anda hanya ingin menggunakan server standar untuk melayani model Anda, lihat TensorFlow Melayani tutorial dasar .
Tutorial ini menggunakan model Regresi Softmax sederhana yang diperkenalkan dalam tutorial TensorFlow untuk klasifikasi gambar tulisan tangan (data MNIST). Jika Anda tidak tahu apa TensorFlow atau MNIST adalah, melihat MNIST Untuk ML Pemula tutorial.
Kode untuk tutorial ini terdiri dari dua bagian:
Sebuah Python berkas mnist_saved_model.py bahwa kereta dan ekspor beberapa versi model.
Sebuah C ++ File main.cc yang merupakan standar TensorFlow ModelServer yang menemukan model baru diekspor dan menjalankan gRPC layanan untuk melayani mereka.
Langkah-langkah tutorial ini melalui tugas-tugas berikut:
- Latih dan ekspor model TensorFlow.
- Mengelola Model versioning dengan TensorFlow Melayani
ServerCore
. - Konfigurasi batching menggunakan
SavedModelBundleSourceAdapterConfig
. - Melayani permintaan dengan TensorFlow Melayani
ServerCore
. - Jalankan dan uji layanan.
Sebelum memulai, pertama install Docker
Latih dan ekspor Model TensorFlow
Pertama, jika Anda belum melakukannya, klon 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 mengekspor dilakukan dengan cara yang sama itu di TensorFlow Melayani tutorial dasar . Untuk tujuan demonstrasi, Anda 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 yang terakhir untuk dicapai akurasi klasifikasi yang lebih baik karena pelatihan yang lebih intensif. Anda harus melihat pelatihan data untuk setiap pelatihan berjalan di Anda /tmp/mnist
direktori:
$ ls /tmp/mnist
1 2
ServerCore
Sekarang bayangkan v1 dan v2 model dihasilkan secara dinamis saat runtime, saat algoritma baru sedang bereksperimen, atau saat model dilatih dengan kumpulan data baru. Di lingkungan produksi, Anda mungkin ingin membangun server yang dapat mendukung peluncuran bertahap, di mana v2 dapat ditemukan, dimuat, dicoba, dipantau, atau dikembalikan saat menayangkan v1. Atau, Anda mungkin ingin meruntuhkan v1 sebelum membuka v2. TensorFlow Serving mendukung kedua opsi -- sementara yang satu bagus untuk menjaga ketersediaan selama transisi, yang lain bagus untuk meminimalkan penggunaan sumber daya (mis. RAM).
TensorFlow Melayani Manager
tidak tepat. Ini menangani siklus hidup penuh model TensorFlow termasuk memuat, menyajikan, dan membongkarnya serta transisi versi. Dalam tutorial ini, Anda akan membangun server di atas TensorFlow Melayani ServerCore
, yang secara internal membungkus sebuah 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 ServerCore :: Pilihan parameter. Berikut adalah beberapa opsi yang umum digunakan:
-
ModelServerConfig
yang menentukan model yang akan dimuat. Model dinyatakan baik melaluimodel_config_list
, yang menyatakan daftar statis model, atau melaluicustom_model_config
, yang mendefinisikan cara kustom untuk menyatakan daftar model yang mungkin bisa diperbarui pada saat runtime. -
PlatformConfigMap
yang memetakan dari nama platform (sepertitensorflow
) kePlatformConfig
, yang digunakan untuk membuatSourceAdapter
.SourceAdapter
menyesuaikanStoragePath
(jalan di mana versi model yang ditemukan) untuk modelLoader
(beban versi model yang dari jalur penyimpanan dan menyediakan antarmuka transisi negara keManager
). JikaPlatformConfig
mengandungSavedModelBundleSourceAdapterConfig
, sebuahSavedModelBundleSourceAdapter
akan dibuat, yang akan kita jelaskan nanti.
SavedModelBundle
adalah komponen kunci dari TensorFlow Melayani. Ini merupakan model TensorFlow dimuat dari path yang diberikan dan memberikan yang sama Session::Run
antarmuka seperti TensorFlow untuk menjalankan inferensi. SavedModelBundleSourceAdapter
beradaptasi path penyimpanan untuk Loader<SavedModelBundle>
sehingga model seumur hidup dapat dikelola oleh Manager
. Harap dicatat bahwa SavedModelBundle
adalah penerus dari usang SessionBundle
. Pengguna dianjurkan untuk menggunakan SavedModelBundle
sebagai dukungan untuk SessionBundle
akan segera dihapus.
Dengan semua ini, ServerCore
internal melakukan berikut ini:
- Instantiates
FileSystemStoragePathSource
yang jalur ekspor monitor model yang dideklarasikan dimodel_config_list
. - Instantiates
SourceAdapter
menggunakanPlatformConfigMap
dengan model platform dideklarasikan dimodel_config_list
dan menghubungkanFileSystemStoragePathSource
untuk itu. Dengan cara ini, setiap kali versi model baru ditemukan di bawah jalur ekspor,SavedModelBundleSourceAdapter
beradaptasi ke sebuahLoader<SavedModelBundle>
. - Instantiates implementasi khusus dari
Manager
disebutAspiredVersionsManager
yang mengelola semua sepertiLoader
contoh diciptakan olehSavedModelBundleSourceAdapter
.ServerCore
eksporManager
antarmuka dengan mendelegasikan panggilan keAspiredVersionsManager
.
Setiap kali versi baru tersedia, ini AspiredVersionsManager
beban versi baru, dan di bawah perilaku unloads default yang lama. Jika Anda ingin mulai menyesuaikan, 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 membangun berbagai plugin untuk perilaku sistem menyesuaikan, saat mengambil keuntungan dari komponen inti generik seperti ServerCore
dan AspiredVersionsManager
. Misalnya, Anda dapat membuat plugin sumber data yang memantau penyimpanan cloud alih-alih penyimpanan lokal, atau Anda dapat membuat plugin kebijakan versi yang melakukan transisi versi dengan cara yang 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 pada sumber kustom dan kustom servable tutorial untuk informasi lebih lanjut.
Batching
Fitur server tipikal 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 saat permintaan inferensi dijalankan dalam batch besar.
Batching dapat diaktifkan dengan menyediakan tepat SessionBundleConfig
saat membuat SavedModelBundleSourceAdapter
. Dalam hal ini kita mengatur BatchingParameters
dengan cukup banyak nilai-nilai default. Batching dapat disesuaikan dengan mengatur batas waktu kustom, nilai batch_size, dll. Untuk detail, silakan lihat 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 yang penuh, permintaan inferensi digabungkan secara internal ke dalam satu permintaan besar (tensor), dan tensorflow::Session::Run()
dipanggil (yang mana keuntungan efisiensi yang sebenarnya pada GPU berasal dari).
Melayani dengan Manajer
Seperti disebutkan di atas, TensorFlow Melayani Manager
dirancang untuk menjadi komponen generik yang dapat menangani pemuatan, melayani, bongkar dan versi transisi dari model yang dihasilkan oleh sistem pembelajaran mesin yang sewenang-wenang. API-nya dibangun berdasarkan konsep utama berikut:
Servable: servable adalah setiap objek buram yang dapat digunakan untuk melayani permintaan klien. Ukuran dan granularitas dari sebuah servable fleksibel, sehingga servable tunggal dapat mencakup apa saja mulai dari pecahan tunggal tabel pencarian hingga model yang dipelajari mesin tunggal hingga tuple model. Servis dapat berupa jenis dan antarmuka apa pun.
Servable Versi: Servables diversi dan TensorFlow Melayani
Manager
dapat mengelola satu atau lebih versi servable a. Pembuatan versi memungkinkan lebih dari satu versi servable dimuat secara bersamaan, mendukung peluncuran dan eksperimen bertahap.Servable Stream: Sebuah aliran servable adalah urutan versi servable, dengan semakin banyak versi.
Model: Sebuah model mesin-belajar diwakili oleh satu atau lebih servables. Contoh servable adalah:
- Sesi TensorFlow atau pembungkus di sekitar mereka, seperti
SavedModelBundle
. - Jenis lain dari model yang dipelajari mesin.
- Tabel pencarian kosakata.
- Menanamkan tabel pencarian.
Model komposit dapat direpresentasikan sebagai beberapa servable independen, atau sebagai servable komposit tunggal. Sebuah servable juga dapat sesuai dengan sepersekian Model, misalnya dengan tabel besar sharded di banyak
Manager
kasus.- Sesi TensorFlow atau pembungkus di sekitar mereka, seperti
Untuk memasukkan semua ini ke dalam konteks tutorial ini:
Model TensorFlow diwakili oleh satu jenis servable -
SavedModelBundle
.SavedModelBundle
internal terdiri daritensorflow:Session
dipasangkan dengan beberapa metadata tentang apa grafik dimuat ke sesi dan bagaimana menjalankannya untuk inferensi.Ada direktori sistem file yang berisi aliran ekspor TensorFlow, masing-masing dalam subdirektori sendiri yang namanya adalah nomor versi. Direktori luar dapat dianggap sebagai representasi serial dari aliran yang dapat dilayani untuk model TensorFlow yang disajikan. Setiap ekspor sesuai dengan servable yang dapat dimuat.
AspiredVersionsManager
memonitor aliran ekspor, dan mengelola siklus hidup dari semuaSavedModelBundle
servables dinamis.
TensorflowPredictImpl::Predict
kemudian hanya:
- Permintaan
SavedModelBundle
dari manajer (melalui ServerCore). - Menggunakan
generic signatures
untuk memetakan nama tensor logis dalamPredictRequest
untuk nama tensor nyata dan nilai-nilai mengikat 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 mengirimkan pesan log setiap satu detik yang mengatakan "Versi yang diinginkan untuk dapat dilayani ...", yang berarti telah menemukan ekspor, dan melacak keberadaannya yang berkelanjutan.
Mari kita jalankan klien dengan --concurrency=10
. Ini akan mengirim 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 yang terlihat seperti:
...
Inference error rate: 13.1%
Kemudian kami menyalin versi kedua dari ekspor ke folder yang dipantau dan menjalankan kembali tes:
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 yang terlihat seperti:
...
Inference error rate: 9.5%
Ini mengonfirmasi bahwa server Anda secara otomatis menemukan versi baru dan menggunakannya untuk melayani!