Membangun Server Model TensorFlow Standar

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

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:

  1. Latih dan ekspor model TensorFlow.
  2. Mengelola Model versioning dengan TensorFlow Melayani ServerCore .
  3. Konfigurasi batching menggunakan SavedModelBundleSourceAdapterConfig .
  4. Melayani permintaan dengan TensorFlow Melayani ServerCore .
  5. 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 melalui model_config_list , yang menyatakan daftar statis model, atau melalui custom_model_config , yang mendefinisikan cara kustom untuk menyatakan daftar model yang mungkin bisa diperbarui pada saat runtime.
  • PlatformConfigMap yang memetakan dari nama platform (seperti tensorflow ) ke PlatformConfig , yang digunakan untuk membuat SourceAdapter . SourceAdapter menyesuaikan StoragePath (jalan di mana versi model yang ditemukan) untuk model Loader (beban versi model yang dari jalur penyimpanan dan menyediakan antarmuka transisi negara ke Manager ). Jika PlatformConfig mengandung SavedModelBundleSourceAdapterConfig , sebuah SavedModelBundleSourceAdapter 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 di model_config_list .
  • Instantiates SourceAdapter menggunakan PlatformConfigMap dengan model platform dideklarasikan di model_config_list dan menghubungkan FileSystemStoragePathSource untuk itu. Dengan cara ini, setiap kali versi model baru ditemukan di bawah jalur ekspor, SavedModelBundleSourceAdapter beradaptasi ke sebuah Loader<SavedModelBundle> .
  • Instantiates implementasi khusus dari Manager disebut AspiredVersionsManager yang mengelola semua seperti Loader contoh diciptakan oleh SavedModelBundleSourceAdapter . ServerCore ekspor Manager antarmuka dengan mendelegasikan panggilan ke AspiredVersionsManager .

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.

Untuk memasukkan semua ini ke dalam konteks tutorial ini:

  • Model TensorFlow diwakili oleh satu jenis servable - SavedModelBundle . SavedModelBundle internal terdiri dari tensorflow: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 semua SavedModelBundle servables dinamis.

TensorflowPredictImpl::Predict kemudian hanya:

  • Permintaan SavedModelBundle dari manajer (melalui ServerCore).
  • Menggunakan generic signatures untuk memetakan nama tensor logis dalam PredictRequest 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!