Xây dựng mô hình TensorFlow tiêu chuẩn

Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.

Hướng dẫn này chỉ cho bạn cách sử dụng các thành phần Cung cấp TensorFlow để xây dựng Máy chủ TensorFlow ModelServer chuẩn tự động phát hiện và phục vụ các phiên bản mới của mô hình TensorFlow được đào tạo. Nếu bạn chỉ muốn sử dụng máy chủ tiêu chuẩn để phục vụ mô hình của bạn, xem TensorFlow Phục vụ hướng dẫn cơ bản .

Hướng dẫn này sử dụng mô hình hồi quy Softmax đơn giản được giới thiệu trong hướng dẫn TensorFlow để phân loại hình ảnh viết tay (dữ liệu MNIST). Nếu bạn không biết những gì TensorFlow hoặc MNIST là, xem MNIST Đối với người mới bắt đầu ML hướng dẫn.

Mã cho hướng dẫn này bao gồm hai phần:

  • Một Python tập tin mnist_saved_model.py rằng xe lửa và xuất khẩu nhiều phiên bản của mô hình.

  • Một C ++ tập tin main.cc đó là tiêu chuẩn TensorFlow ModelServer mà phát hiện ra mới xuất mô hình và chạy một gRPC dịch vụ để phục vụ họ.

Hướng dẫn này thực hiện các bước sau:

  1. Đào tạo và xuất mô hình TensorFlow.
  2. Quản lý mô hình versioning với TensorFlow Phục vụ ServerCore .
  3. Cấu hình trạm trộn sử dụng SavedModelBundleSourceAdapterConfig .
  4. Phục vụ yêu cầu với TensorFlow Phục vụ ServerCore .
  5. Chạy và thử nghiệm dịch vụ.

Trước khi bắt đầu, đầu tiên cài đặt Docker

Đào tạo và xuất Mô hình TensorFlow

Đầu tiên, nếu bạn chưa làm như vậy, hãy sao chép kho lưu trữ này vào máy cục bộ của bạn:

git clone https://github.com/tensorflow/serving.git
cd serving

Xóa thư mục xuất nếu nó đã tồn tại:

rm -rf /tmp/models

Huấn luyện (với 100 lần lặp) và xuất phiên bản đầu tiên của mô hình:

tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
  --training_iteration=100 --model_version=1 /tmp/mnist

Đào tạo (với 2000 lần lặp) và xuất phiên bản thứ hai của mô hình:

tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
  --training_iteration=2000 --model_version=2 /tmp/mnist

Như bạn có thể thấy trong mnist_saved_model.py , công tác đào tạo và xuất khẩu được thực hiện theo cùng một cách đó là trong TensorFlow Phục vụ hướng dẫn cơ bản . Với mục đích trình diễn, bạn đang cố tình quay số lặp lại đào tạo cho lần chạy đầu tiên và xuất nó dưới dạng v1, trong khi đào tạo nó bình thường cho lần chạy thứ hai và xuất nó dưới dạng v2 vào cùng một thư mục mẹ - như chúng tôi mong đợi sau này sẽ đạt được. độ chính xác phân loại tốt hơn do được đào tạo chuyên sâu hơn. Bạn sẽ thấy đào tạo dữ liệu cho mỗi lần chạy đào tạo của bạn /tmp/mnist thư mục:

$ ls /tmp/mnist
1  2

ServerCore

Bây giờ, hãy tưởng tượng v1 và v2 của mô hình được tạo động trong thời gian chạy, khi các thuật toán mới đang được thử nghiệm hoặc khi mô hình được đào tạo với tập dữ liệu mới. Trong môi trường sản xuất, bạn có thể muốn xây dựng một máy chủ có thể hỗ trợ triển khai dần dần, trong đó v2 có thể được khám phá, tải, thử nghiệm, giám sát hoặc hoàn nguyên trong khi cung cấp v1. Ngoài ra, bạn có thể muốn chia nhỏ v1 trước khi đưa lên v2. TensorFlow Serving hỗ trợ cả hai tùy chọn - trong khi một tùy chọn tốt để duy trì tính khả dụng trong quá trình chuyển đổi, tùy chọn còn lại tốt để giảm thiểu việc sử dụng tài nguyên (ví dụ: RAM).

TensorFlow Phục vụ Manager thực hiện chính xác đó. Nó xử lý toàn bộ vòng đời của các mô hình TensorFlow bao gồm tải, phục vụ và dỡ chúng cũng như chuyển đổi phiên bản. Trong hướng dẫn này, bạn sẽ xây dựng máy chủ của bạn trên đầu trang của một TensorFlow Phục vụ ServerCore , mà trong nội bộ kết thúc tốt đẹp một 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() mất một ServerCore :: Tùy chọn tham số. Dưới đây là một số tùy chọn thường được sử dụng:

  • ModelServerConfig đó quy định cụ thể mô hình được nạp. Mô hình được tuyên bố hoặc thông qua model_config_list , mà tuyên bố một danh sách tĩnh của mô hình, hoặc thông qua custom_model_config , trong đó xác định một cách tùy chỉnh để khai báo một danh sách các mô hình có thể được cập nhật trong thời gian chạy.
  • PlatformConfigMap mà các bản đồ từ tên của các nền tảng (như tensorflow ) đến PlatformConfig , được sử dụng để tạo ra các SourceAdapter . SourceAdapter thích nghi StoragePath (đường dẫn nơi một phiên bản mô hình được phát hiện) để mô hình Loader (tải phiên bản mô hình từ đường dẫn lưu trữ và cung cấp giao diện chuyển trạng thái sang Manager ). Nếu PlatformConfig chứa SavedModelBundleSourceAdapterConfig , một SavedModelBundleSourceAdapter sẽ được tạo ra, mà chúng tôi sẽ giải thích sau.

SavedModelBundle là một thành phần quan trọng của TensorFlow Phục vụ. Nó đại diện cho một mô hình TensorFlow nạp từ một con đường nhất định và cung cấp cùng Session::Run giao diện như TensorFlow để chạy suy luận. SavedModelBundleSourceAdapter thích nghi đường dẫn lưu trữ để Loader<SavedModelBundle> để mô hình đời có thể được quản lý bởi Manager . Xin lưu ý rằng SavedModelBundle là sự kế thừa của phản SessionBundle . Người dùng được khuyến khích sử dụng SavedModelBundle như sự hỗ trợ cho SessionBundle sẽ sớm được gỡ bỏ.

Với tất cả những, ServerCore nội bộ nào sau đây:

  • Instantiates một FileSystemStoragePathSource rằng con đường xuất khẩu mô hình giám sát khai báo trong model_config_list .
  • Instantiates một SourceAdapter sử dụng PlatformConfigMap với nền tảng mô hình khai báo trong model_config_list và kết nối FileSystemStoragePathSource với nó. Bằng cách này, bất cứ khi nào một phiên bản mô hình mới được phát hiện dưới con đường xuất khẩu, SavedModelBundleSourceAdapter thích nghi nó vào một Loader<SavedModelBundle> .
  • Instantiates một thực hiện cụ thể của Manager gọi AspiredVersionsManager quản lý tất cả các ví dụ Loader trường tạo ra bởi các SavedModelBundleSourceAdapter . ServerCore xuất khẩu các Manager giao diện bằng cách ủy quyền các cuộc gọi đến AspiredVersionsManager .

Bất cứ khi nào một phiên bản mới có sẵn, điều này AspiredVersionsManager tải phiên bản mới, và dưới unloads hành vi mặc định của nó một tuổi. Nếu bạn muốn bắt đầu tùy chỉnh, bạn nên hiểu các thành phần mà nó tạo ra bên trong và cách định cấu hình chúng.

Điều đáng nói là TensorFlow Serving được thiết kế từ đầu để rất linh hoạt và có thể mở rộng. Bạn có thể xây dựng các plugin khác nhau để tùy chỉnh hành vi hệ thống, trong khi lợi dụng thành phần cốt lõi chung chung như ServerCoreAspiredVersionsManager . Ví dụ: bạn có thể tạo một plugin nguồn dữ liệu giám sát lưu trữ đám mây thay vì lưu trữ cục bộ hoặc bạn có thể tạo một plugin chính sách phiên bản thực hiện chuyển đổi phiên bản theo một cách khác - trên thực tế, bạn thậm chí có thể tạo một plugin mô hình tùy chỉnh phục vụ các mô hình không phải TensorFlow. Các chủ đề này nằm ngoài phạm vi của hướng dẫn này. Tuy nhiên, bạn có thể tham khảo các nguồn tùy chỉnhtùy chỉnh thể phân phát các hướng dẫn để biết thêm thông tin.

Hàng loạt

Một tính năng máy chủ điển hình khác mà chúng tôi muốn trong môi trường sản xuất là theo lô. Các bộ tăng tốc phần cứng hiện đại (GPU, v.v.) được sử dụng để thực hiện suy luận học máy thường đạt được hiệu quả tính toán tốt nhất khi các yêu cầu suy luận được chạy theo lô lớn.

Trạm trộn có thể được bật bằng cách cung cấp thích hợp SessionBundleConfig khi tạo SavedModelBundleSourceAdapter . Trong trường hợp này chúng tôi đặt BatchingParameters với các giá trị mặc định khá nhiều. Bạn có thể tinh chỉnh lô bằng cách đặt các giá trị thời gian chờ, kích thước lô, v.v. tùy chỉnh. Để biết chi tiết, vui lòng tham khảo 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;

Sau khi đạt được toàn bộ lô hàng, yêu cầu suy luận được sáp nhập trong nội bộ thành một yêu cầu duy nhất lớn (tensor), và tensorflow::Session::Run() được gọi (đó là nơi tăng hiệu quả thực tế trên GPU xuất phát từ).

Phục vụ với Người quản lý

Như đã đề cập ở trên, TensorFlow Phục vụ Manager được thiết kế để trở thành một thành phần chung có thể xử lý tải, phục vụ, xếp dỡ và chuyển tiếp phiên bản của mô hình được tạo ra bởi hệ thống học máy tùy ý. Các API của nó được xây dựng dựa trên các khái niệm chính sau:

  • Thể phân phát: thể phân phát bất kỳ đối tượng đục có thể được sử dụng để phục vụ yêu cầu của khách hàng. Kích thước và mức độ chi tiết của một dịch vụ có thể linh hoạt, sao cho một dịch vụ duy nhất có thể bao gồm bất kỳ thứ gì từ một phân đoạn của bảng tra cứu đến một mô hình máy học cho đến một loạt các mô hình. Một dịch vụ có thể thuộc bất kỳ loại và giao diện nào.

  • Thể phân phát Version: Servables được phiên bản và cập TensorFlow Phục vụ Manager có thể quản lý một hoặc nhiều phiên bản của một thể phân phát. Việc tạo phiên bản cho phép tải đồng thời nhiều phiên bản của một dịch vụ, hỗ trợ triển khai và thử nghiệm dần dần.

  • Thể phân phát Suối: Một dòng thể phân phát là chuỗi các phiên bản của một thể phân phát, với sự gia tăng số phiên bản.

  • Mô hình: Một mô hình máy học được thể hiện bằng một hoặc nhiều servables. Ví dụ về các dịch vụ là:

    • TensorFlow phiên làm việc hoặc giấy gói xung quanh họ, chẳng hạn như SavedModelBundle .
    • Các loại mô hình máy học khác.
    • Các bảng tra từ vựng.
    • Nhúng bảng tra cứu.

    Một mô hình tổng hợp có thể được biểu diễn dưới dạng nhiều dịch vụ độc lập hoặc như một mô hình tổng hợp duy nhất có thể phục vụ. Một thể phân phát cũng có thể tương ứng với một phần nhỏ của một mô hình, ví dụ với một bảng tra cứu lớn sharded qua nhiều Manager trường hợp.

Để đặt tất cả những điều này vào ngữ cảnh của hướng dẫn này:

  • Mô hình TensorFlow được đại diện bởi một loại thể phân phát - SavedModelBundle . SavedModelBundle nội bộ bao gồm một tensorflow:Session kết hợp với một số siêu dữ liệu về những gì đồ thị được nạp vào phiên giao dịch và làm thế nào để chạy nó cho suy luận.

  • Có một thư mục hệ thống tệp chứa một luồng xuất TensorFlow, mỗi tệp nằm trong thư mục con riêng của nó có tên là số phiên bản. Thư mục bên ngoài có thể được coi là đại diện tuần tự của luồng có thể phục vụ cho mô hình TensorFlow đang được phục vụ. Mỗi lần xuất tương ứng với một dịch vụ có thể được tải.

  • AspiredVersionsManager giám sát dòng xuất khẩu, và quản lý vòng đời của tất cả SavedModelBundle servables động.

TensorflowPredictImpl::Predict sau đó chỉ cần:

  • Yêu cầu SavedModelBundle từ người quản lý (thông qua ServerCore).
  • Sử dụng generic signatures để lập bản đồ tên tensor logic trong PredictRequest để tên tensor thực tế và giá trị ràng buộc để tensors.
  • Chạy suy luận.

Kiểm tra và chạy máy chủ

Sao chép phiên bản xuất đầu tiên vào thư mục được giám sát:

mkdir /tmp/monitored
cp -r /tmp/mnist/1 /tmp/monitored

Sau đó khởi động máy chủ:

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 &

Máy chủ sẽ phát ra các thông báo nhật ký cứ sau một giây có nội dung "Phiên bản khao khát cho dịch vụ ...", có nghĩa là nó đã tìm thấy bản xuất và đang theo dõi sự tồn tại tiếp tục của nó.

Hãy chạy client với --concurrency=10 . Thao tác này sẽ gửi các yêu cầu đồng thời đến máy chủ và do đó kích hoạt logic phân lô của bạn.

tools/run_in_docker.sh python tensorflow_serving/example/mnist_client.py \
  --num_tests=1000 --server=127.0.0.1:8500 --concurrency=10

Kết quả đầu ra giống như sau:

...
Inference error rate: 13.1%

Sau đó, chúng tôi sao chép phiên bản thứ hai của quá trình xuất vào thư mục được giám sát và chạy lại kiểm tra:

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

Kết quả đầu ra giống như sau:

...
Inference error rate: 9.5%

Điều này xác nhận rằng máy chủ của bạn tự động phát hiện ra phiên bản mới và sử dụng nó để phục vụ!