یک وب سایت ساده ایجاد کنید که تصاویر را طبقه بندی می کند

1. قبل از شروع

در این کد لبه، شما یاد می گیرید که چگونه یک استنتاج طبقه بندی تصویر را از یک وب سایت با استفاده از سرویس TensorFlow با REST و gRPC اجرا کنید.

پیش نیازها

  • دانش اولیه توسعه وب، مانند HTML و JavaScript
  • دانش اولیه یادگیری ماشین با TensorFlow، مانند آموزش و استقرار
  • دانش اولیه ترمینال ها و داکر

چیزی که یاد خواهید گرفت

  • نحوه پیدا کردن مدل های طبقه بندی تصویر از پیش آموزش دیده در TensorFlow Hub.
  • چگونه یک وب سایت ساده بسازیم و با مدل طبقه بندی تصویر دانلود شده از طریق سرویس TensorFlow (REST و gRPC) پیش بینی کنیم.
  • نحوه نمایش نتیجه تشخیص در رابط کاربری

آنچه شما نیاز دارید

2. راه اندازی شوید

برای دانلود کد این کد لبه:

  1. به این مخزن GitHub بروید .
  2. روی Code > Download zip کلیک کنید تا همه کدهای این کد لبه را دانلود کنید.

a72f2bb4caa9a96.png

  1. فایل فشرده دانلود شده را از حالت فشرده خارج کنید تا بسته بندی پوشه ریشه codelabs با تمام منابع مورد نیاز شما باز شود.

برای این کد لبه، شما فقط به فایل های موجود در زیر شاخه TFServing/ImageClassificationWeb در مخزن نیاز دارید که شامل دو پوشه است:

  • پوشه starter حاوی کد شروعی است که برای این Codelab بر اساس آن ساخته اید.
  • پوشه finished شده حاوی کد تکمیل شده برای برنامه نمونه تمام شده است.

3. وابستگی ها را نصب کنید

برای نصب وابستگی ها:

  • در ترمینال خود، به پوشه starter بروید و سپس بسته های NPM مورد نیاز را نصب کنید:
npm install

4. وب سایت استارتر را اجرا کنید

از وب سرور برای Chrome برای بارگیری TFServing/ImageClassificationWeb/starter/dist/index.html استفاده کنید:

  1. Chrome://apps/ را در نوار آدرس Chrome وارد کنید و سپس Web Server for Chrome را در لیست برنامه ها پیدا کنید.
  2. وب سرور را برای Chrome راه اندازی کنید و سپس TFServing/ImageClassificationWeb/starter/dist/ را انتخاب کنید.
  3. برای فعال کردن گزینه Web Server کلیک کنید و سپس در مرورگر خود به http://localhost:8887/ بروید.

f7b43cd44ebf1f1b.png

وب سایت را اجرا و کاوش کنید

اکنون باید وب سایت را ببینید. رابط کاربری بسیار ساده است: یک تصویر گربه وجود دارد که می‌خواهید در آن طبقه‌بندی کنید و کاربر می‌تواند داده‌ها را با REST یا gRPC به باطن ارسال کند. Backend طبقه بندی تصویر را روی تصویر انجام می دهد و نتیجه طبقه بندی را به وب سایت برمی گرداند که نتیجه را نمایش می دهد.

837d97a27c59a0b3.png

اگر روی Classify کلیک کنید، هیچ اتفاقی نمی افتد زیرا هنوز نمی تواند با backend ارتباط برقرار کند.

5. یک مدل طبقه‌بندی تصویر را با سرویس TensorFlow اجرا کنید

طبقه بندی تصویر یک کار بسیار رایج ML است که یک تصویر را بر اساس محتوای اولیه تصویر به دسته های از پیش تعریف شده طبقه بندی می کند. در اینجا نمونه ای از طبقه بندی گل ها آورده شده است:

a6da16b4a7665db0.png

تعدادی مدل طبقه بندی تصویر از پیش آموزش دیده در TensorFlow Hub وجود دارد. شما از یک مدل محبوب Inception v3 برای این Codelab استفاده می کنید.

برای استقرار مدل طبقه‌بندی تصویر با سرویس TensorFlow:

  1. فایل مدل Inception v3 را دانلود کنید.
  2. فایل .tar.gz دانلود شده را با یک ابزار رفع فشرده سازی مانند 7-Zip از حالت فشرده خارج کنید.
  3. یک پوشه inception_v3 ایجاد کنید و سپس یک زیر پوشه 123 داخل آن ایجاد کنید.
  4. پوشه variables استخراج شده و فایل saved_model.pb را در زیر پوشه 123 قرار دهید.

می توانید به پوشه inception_v3 به عنوان پوشه SavedModel کنید. 123 یک نمونه نسخه شماره است. در صورت تمایل می توانید شماره دیگری را انتخاب کنید.

ساختار پوشه باید مانند تصویر زیر باشد:

21a8675ac8d31907.png

سرویس TensorFlow را شروع کنید

  • در ترمینال خود، سرویس TensorFlow را با Docker شروع کنید، اما PATH/TO/SAVEDMODEL را با مسیر مطلق پوشه inception_v3 در رایانه خود جایگزین کنید.
docker pull tensorflow/serving

docker run -it --rm -p 8500:8500 -p 8501:8501 -v "PATH/TO/SAVEDMODEL:/models/inception" -e MODEL_NAME=inception tensorflow/serving

Docker به طور خودکار ابتدا تصویر TensorFlow Serving را دانلود می کند که یک دقیقه طول می کشد. پس از آن، سرویس TensorFlow باید شروع شود. گزارش باید مانند این قطعه کد باشد:

2022-02-25 06:01:12.513231: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle.
2022-02-25 06:01:12.585012: I external/org_tensorflow/tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 3000000000 Hz
2022-02-25 06:01:13.395083: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/inception/123
2022-02-25 06:01:13.837562: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 1928700 microseconds.
2022-02-25 06:01:13.877848: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/inception/123/assets.extra/tf_serving_warmup_requests
2022-02-25 06:01:13.929844: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: inception version: 123}
2022-02-25 06:01:13.985848: I tensorflow_serving/model_servers/server_core.cc:486] Finished adding/updating models
2022-02-25 06:01:13.985987: I tensorflow_serving/model_servers/server.cc:367] Profiler service is enabled
2022-02-25 06:01:13.988994: I tensorflow_serving/model_servers/server.cc:393] Running gRPC ModelServer at 0.0.0.0:8500 ...
[warn] getaddrinfo: address family for nodename not supported
2022-02-25 06:01:14.033872: I tensorflow_serving/model_servers/server.cc:414] Exporting HTTP/REST API at:localhost:8501 ...
[evhttp_server.cc : 245] NET_LOG: Entering the event loop ...

6. پروکسی Envoy را راه اندازی کنید

در حال حاضر TensorFlow Serving هدر Access-Control-Allow-Origin را تنظیم نمی کند، بنابراین مرورگر درخواست را از JavaScript frontend به TensorFlow Serving به دلایل امنیتی مسدود می کند. برای حل این مشکل، باید از یک پروکسی مانند Envoy برای پراکسی کردن درخواست از جاوا اسکریپت به باطن TensorFlow Serving استفاده کنید.

فرستاده را شروع کنید

  • در ترمینال خود، تصویر Envoy را دانلود کنید و Envoy را با Docker شروع کنید، اما PATH/TO/ENVOY-CUSTOM.YAML را با مسیر مطلق فایل envoy-custom.yaml در پوشه starter جایگزین کنید.
docker pull envoyproxy/envoy-dev:fd3e8370ddb7a96634c192d1461516e6de1d1797

docker run --add-host host.docker.internal:host-gateway --rm -it -p 9901:9901 -p 8000:8000 -p 8080:8080 -v PATH/TO/ENVOY-CUSTOM.YAML:/envoy-custom.yaml envoyproxy/envoy-dev:fd3e8370ddb7a96634c192d1461516e6de1d1797 -c /envoy-custom.yaml

Docker به طور خودکار ابتدا تصویر Envoy را دانلود می کند. پس از آن، فرستاده باید شروع کند. گزارش باید مانند این قطعه کد باشد:

[2022-03-02 07:51:48.563][1][info][main] [source/server/server.cc:436]   response trailer map: 152 bytes: grpc-message,grpc-status
[2022-03-02 07:51:48.681][1][info][main] [source/server/server.cc:772] runtime: {}
[2022-03-02 07:51:48.682][1][info][admin] [source/server/admin/admin.cc:134] admin address: 0.0.0.0:9901
[2022-03-02 07:51:48.683][1][info][config] [source/server/configuration_impl.cc:127] loading tracing configuration
[2022-03-02 07:51:48.683][1][info][config] [source/server/configuration_impl.cc:87] loading 0 static secret(s)
[2022-03-02 07:51:48.683][1][info][config] [source/server/configuration_impl.cc:93] loading 2 cluster(s)
[2022-03-02 07:51:48.687][1][info][config] [source/server/configuration_impl.cc:97] loading 2 listener(s)
[2022-03-02 07:51:48.694][1][info][config] [source/server/configuration_impl.cc:109] loading stats configuration
[2022-03-02 07:51:48.696][1][info][main] [source/server/server.cc:868] starting main dispatch loop
[2022-03-02 07:51:48.881][1][info][runtime] [source/common/runtime/runtime_impl.cc:446] RTDS has finished initialization
[2022-03-02 07:51:48.881][1][info][upstream] [source/common/upstream/cluster_manager_impl.cc:207] cm init: all clusters initialized
[2022-03-02 07:51:48.881][1][info][main] [source/server/server.cc:849] all clusters initialized. initializing init manager
[2022-03-02 07:51:48.881][1][info][config] [source/server/listener_manager_impl.cc:784] all dependencies initialized. starting workers
[2022-03-02 07:51:48.902][1][warning][main] [source/server/server.cc:747] there is no configured limit to the number of allowed active connections. Set a limit via the runtime key overload.global_downstream_max_connections

7. وب سایت را با TensorFlow از طریق REST متصل کنید

پشتیبان اکنون آماده است، بنابراین می توانید درخواست های مشتری را برای طبقه بندی تصاویر به TensorFlow Serving ارسال کنید. دو راه برای ارسال درخواست به سرویس TensorFlow وجود دارد:

  • باقی مانده
  • gRPC

ارسال درخواست و دریافت پاسخ از طریق REST

سه مرحله ساده برای ارسال و دریافت درخواست از طریق REST وجود دارد:

  1. درخواست REST را ایجاد کنید.
  2. درخواست REST را به سرویس TensorFlow ارسال کنید.
  3. نتیجه پیش بینی شده را از پاسخ REST استخراج کنید و نتیجه را نمایش دهید.

این مراحل را در فایل src/index.js انجام می دهید.

درخواست REST را ایجاد کنید

در حال حاضر، تابع classify_img() درخواست REST را به سرویس TensorFlow ارسال نمی کند. برای ایجاد یک درخواست REST ابتدا باید این شاخه REST را پیاده سازی کنید:

if (radioButtons[0].checked) {
    console.log('Using REST');
    // TODO: Add code to send a REST request to TensorFlow Serving.

} 

سرویس TensorFlow انتظار یک درخواست POST را دارد که حاوی تانسور تصویر برای مدل Inception v3 است که استفاده می‌کنید، بنابراین باید مقادیر RGB را از هر پیکسل تصویر در یک آرایه استخراج کنید و سپس آرایه را در یک JSON بپیچید که همان بار است. از درخواست

  • این کد را به شاخه REST اضافه کنید:
//Create the REST request.
let imgTensor = new Array();
let pixelArray = new Array();
context.drawImage(img, 0, 0);
for(let i=0; i<inputImgHeight; i++) {
    pixelArray[i] = new Array();
    for (let j=0; j<inputImgWidth; j++) {
        pixelArray[i][j] = new Array();
        pixelArray[i][j].push(context.getImageData(i, j, 1, 1).data[0]/255); 
        pixelArray[i][j].push(context.getImageData(i, j, 1, 1).data[1]/255); 
        pixelArray[i][j].push(context.getImageData(i, j, 1, 1).data[2]/255); 
    }
}
imgTensor.push(pixelArray);

const RESTURL = 'http://localhost:8000/v1/models/inception:predict';        
let xhr = new XMLHttpRequest();
xhr.open('POST', RESTURL);
xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8;');
let data = JSON.stringify({
    instances: imgTensor
});    
xhr.onload = () => {

}
xhr.onerror = () => {
    console.log('REST request error');
}

درخواست REST را به سرویس TensorFlow ارسال کنید

اکنون می توانید درخواست را ارسال کنید.

  • این کد را درست بعد از کد بالا در شاخه REST اضافه کنید:
// Send the REST request.
xhr.send(data);

پاسخ REST را از سرویس TensorFlow پردازش کنید

مدل Inception v3 آرایه ای از احتمالات را برمی گرداند که تصویر به دسته های از پیش تعریف شده تعلق دارد. وقتی پیش‌بینی موفقیت‌آمیز بود، باید محتمل‌ترین دسته را در UI خروجی بگیرید.

شما شنونده onload() را برای مدیریت پاسخ پیاده سازی می کنید.

xhr.onload = () => {

}
  • این کد را به شنونده onload() اضافه کنید:
// Process the REST response.
const response = JSON.parse(xhr.responseText);
const maxIndex = argmax(response['predictions'][0])
document.getElementById('category').textContent = 'Predicted category: ' + maxIndex;

اکنون شنونده احتمالات پیش بینی شده را از پاسخ استخراج می کند، محتمل ترین دسته شی را شناسایی می کند و نتیجه را در UI نمایش می دهد.

آن را اجرا کنید

  1. در ترمینال خود، به پوشه starter بروید و از webpack استفاده کنید تا همه فایل های جاوا اسکریپت را در یک فایل واحد قرار دهید که می توانید آن را در فایل dist/index.html جاسازی کنید:
npm install -g npx
npm install --save-dev webpack
npx webpack
  1. http://localhost:8887/ را در مرورگر خود بازخوانی کنید و سپس روی REST > Classify کلیک کنید.

وب سایت 286 را به عنوان دسته پیش بینی شده نمایش می دهد که به برچسب Egyptian Cat در مجموعه داده ImageNet نگاشت می شود .

c865a93b9b58335d.png

8. وب سایت را با سرویس TensorFlow از طریق gRPC متصل کنید

علاوه بر REST، سرویس TensorFlow از gRPC نیز پشتیبانی می کند.

b6f4449c2c850b0e.png

gRPC یک چارچوب مدرن، متن باز و با کارایی بالا Remote Procedure Call (RPC) است که می تواند در هر محیطی اجرا شود. این می تواند به طور موثر خدمات را در مراکز داده و در سراسر آنها با پشتیبانی قابل اتصال برای تعادل بار، ردیابی، بررسی سلامت و احراز هویت متصل کند. مشاهده شده است که gRPC در عمل عملکرد بیشتری نسبت به REST دارد.

ارسال درخواست و دریافت پاسخ با gRPC

چهار مرحله ساده وجود دارد:

  1. اختیاری: کد خرد مشتری gRPC را ایجاد کنید.
  2. درخواست gRPC را ایجاد کنید.
  3. درخواست gRPC را به سرویس TensorFlow ارسال کنید.
  4. نتیجه پیش‌بینی‌شده را از پاسخ gRPC استخراج کرده و در UI نمایش دهید.

این مراحل را در فایل src/index.js انجام می دهید.

اختیاری: کد خرد مشتری gRPC را ایجاد کنید

برای استفاده از gRPC با سرویس TensorFlow، باید گردش کار gRPC را دنبال کنید. برای کسب اطلاعات بیشتر در مورد جزئیات، به مستندات gRPC مراجعه کنید.

a9d0e5cb543467b4.png

TensorFlow Serving و .proto فایل های .proto را برای شما تعریف می کنند. در مورد TensorFlow و TensorFlow Serving 2.8، این فایل‌های .proto موارد مورد نیاز هستند:

tensorflow/core/example/example.proto
tensorflow/core/example/feature.proto
tensorflow/core/protobuf/struct.proto
tensorflow/core/protobuf/saved_object_graph.proto
tensorflow/core/protobuf/saver.proto
tensorflow/core/protobuf/trackable_object_graph.proto
tensorflow/core/protobuf/meta_graph.proto
tensorflow/core/framework/node_def.proto
tensorflow/core/framework/attr_value.proto
tensorflow/core/framework/function.proto
tensorflow/core/framework/types.proto
tensorflow/core/framework/tensor_shape.proto
tensorflow/core/framework/full_type.proto
tensorflow/core/framework/versions.proto
tensorflow/core/framework/op_def.proto
tensorflow/core/framework/graph.proto
tensorflow/core/framework/tensor.proto
tensorflow/core/framework/resource_handle.proto
tensorflow/core/framework/variable.proto

tensorflow_serving/apis/inference.proto
tensorflow_serving/apis/classification.proto
tensorflow_serving/apis/predict.proto
tensorflow_serving/apis/regression.proto
tensorflow_serving/apis/get_model_metadata.proto
tensorflow_serving/apis/input.proto
tensorflow_serving/apis/prediction_service.proto
tensorflow_serving/apis/model.proto
  • در ترمینال خود، به پوشه starter/src/proto/ بروید و خرد را ایجاد کنید:
bash generate_grpc_stub_js.sh

درخواست gRPC را ایجاد کنید

مشابه درخواست REST، شما درخواست gRPC را در شاخه gRPC ایجاد می کنید .

if (connectionMode[picker.selectedRow(inComponent: 0)] == "REST") {

}
else {
    print("Using gRPC")
    // TODO: Add code to send a gRPC request to TensorFlow Serving.
    
}
  • این کد را به شاخه gRPC اضافه کنید:
// Create the gRPC request.
const PredictModule = require('./proto/generated/tensorflow_serving/apis/predict_pb.js');
const PredictionServiceClientModule = require('./proto/generated/tensorflow_serving/apis/prediction_service_grpc_web_pb.js');
const ModelModule = require('./proto/generated/tensorflow_serving/apis/model_pb.js');
const TensorModule = require('./proto/generated/tensorflow/core/framework/tensor_pb.js');

const GPRCURL = 'http://localhost:8080';
const stub = new PredictionServiceClientModule.PredictionServiceClient(GPRCURL);

const modelSpec = new ModelModule.ModelSpec();
modelSpec.setName('inception');

const tensorProto = new TensorModule.TensorProto();
const tensorShapeProto = new TensorModule.TensorShapeProto();

const batchDim = (new TensorModule.TensorShapeProto.Dim()).setSize(1);
const heightDim = (new TensorModule.TensorShapeProto.Dim()).setSize(inputImgHeight);
const widthDim = (new TensorModule.TensorShapeProto.Dim()).setSize(inputImgWidth);
const channelDim = (new TensorModule.TensorShapeProto.Dim()).setSize(3);

tensorShapeProto.setDimList([batchDim, heightDim, widthDim, channelDim]);

tensorProto.setDtype(proto.tensorflow.DataType.DT_FLOAT);
tensorProto.setTensorShape(tensorShapeProto);
context.drawImage(img, 0, 0);
for(let i=0; i<inputImgHeight; i++) {
    for (let j=0; j<inputImgWidth; j++) {
        tensorProto.addFloatVal(context.getImageData(i, j, 1, 1).data[0]/255); 
        tensorProto.addFloatVal(context.getImageData(i, j, 1, 1).data[1]/255); 
        tensorProto.addFloatVal(context.getImageData(i, j, 1, 1).data[2]/255); 
    }
}

const predictionServiceRequest = new PredictModule.PredictRequest();
predictionServiceRequest.setModelSpec(modelSpec);
predictionServiceRequest.getInputsMap().set('inputs', tensorProto);

درخواست gRPC را به سرویس TensorFlow ارسال کنید

اکنون می توانید درخواست را ارسال کنید.

  • این کد را بلافاصله بعد از کد موجود در شاخه gRPC در قطعه کد قبلی اضافه کنید:
// Send the gRPC request.
stub.predict(predictionServiceRequest, {}, function(err, response) {
    // TODO: Add code to process the response.
});

پاسخ gRPC از سرویس TensorFlow را پردازش کنید

در نهایت، تابع callback بالا را برای رسیدگی به پاسخ پیاده سازی می کنید.

  • این کد را به بدنه تابع در قطعه کد قبلی اضافه کنید:
// Process the gRPC response.
if (err) {
    console.log(err.code);
    console.log(err.message);
} 
else {
    const maxIndex = argmax(response.getOutputsMap().get('logits').getFloatValList());
    document.getElementById('category').textContent = 'Predicted category: ' + maxIndex;
}

اکنون شنونده احتمالات پیش بینی شده را از پاسخ استخراج می کند، محتمل ترین دسته شی را شناسایی می کند و نتیجه را در UI نمایش می دهد.

آن را اجرا کنید

  1. در ترمینال خود، از webpack استفاده کنید تا همه فایل های جاوا اسکریپت را در یک فایل واحد قرار دهید که می توانید آن را در فایل index.html جاسازی کنید:
npx webpack
  1. http://localhost:8887/ را در مرورگر خود بازخوانی کنید.
  2. روی gRPC > Classify کلیک کنید.

این وب سایت دسته پیش بینی شده 286 را نمایش می دهد که به برچسب Egyptian Cat در مجموعه داده ImageNet نگاشت می شود .

9. تبریک می گویم

شما از TensorFlow Serving برای افزودن قابلیت های طبقه بندی تصاویر به وب سایت خود استفاده کردید!

بیشتر بدانید