إنشاء موقع إلكتروني بسيط لتصنيف الصور

1. قبل البدء

في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية تنفيذ استنتاج تصنيف الصور من موقع إلكتروني باستخدام TensorFlow Signing مع REST وgRPC.

المتطلّبات الأساسية

  • معرفة أساسية بتطوير برامج الويب، مثل HTML وJavaScript
  • معرفة أساسية بتعلُّم الآلة مع TensorFlow، مثل التدريب والنشر
  • معرفة أساسية حول محطات الدفع وقاعدة الإرساء

ما ستتعرَّف عليه

  • كيفية العثور على نماذج مصنّفة مسبقًا لتصنيف الصور على TensorFlow Hub
  • كيفية إنشاء موقع إلكتروني بسيط وتوقّع التوقعات باستخدام نموذج تصنيف الصور الذي تم تنزيله من خلال TensorFlow Driving (REST وgRPC).
  • كيفية عرض نتيجة الاكتشاف في واجهة المستخدم.

الأشياء التي تحتاج إليها

2. الإعداد

لتنزيل الرمز في هذا الدرس التطبيقي حول الترميز:

  1. انتقِل إلى مستودع GitHub.
  2. انقر على رمز > تنزيل ملف zip لتنزيل كل رموز هذا الدرس التطبيقي حول الترميز.

a72f2bb4caa9a96.png

  1. يمكنك فك ضغط ملف ZIP الذي تم تنزيله لفك ضغط مجلد الجذر الذي يتضمّن codelabs مع جميع الموارد التي تحتاجها.

بالنسبة إلى هذا الدرس التطبيقي حول الترميز، تحتاج فقط إلى الملفات في دليل TFServing/ImageClassificationWeb الفرعي في المستودع، الذي يحتوي على مجلدَين:

  • يتضمّن المجلد starter رمز التفعيل الذي تستند إليه في هذا الدرس التطبيقي حول الترميز.
  • يحتوي مجلد finished على الرمز المكتمل لنموذج التطبيق المكتمل.

3- تثبيت التبعيات

لتثبيت التبعيات:

  • في الوحدة الطرفية، انتقِل إلى المجلد starter ثم ثبِّت حِزم NPM المطلوبة:
npm install

4. تشغيل الموقع الإلكتروني للمبتدئين

استخدِم Web Server for Chrome لتحميل ملف TFServing/ImageClassificationWeb/starter/dist/index.html:

  1. أدخِل Chrome://apps/ في شريط العناوين في Chrome، ثم ابحث عن Web Server for Chrome في قائمة التطبيقات.
  2. افتح خادم الويب لمتصفِّح Chrome، ثم اختَر مجلد TFServing/ImageClassificationWeb/starter/dist/.
  3. انقر على مفتاح تبديل خادم الويب لتفعيله ثم انتقِل إلى http://localhost:8887/ في المتصفّح.

f7b43cd44ebf1f1b.png

إدارة الموقع الإلكتروني واستكشافه

من المفترض أن يظهر لك الموقع الإلكتروني الآن. واجهة المستخدم سهلة الاستخدام، فهي توفّر صورة للقطط تريد تصنيفها، ويمكن للمستخدم إرسال البيانات إلى الخلفية باستخدام REST أو gRPC. تؤدي الخلفية إلى تصنيف الصورة على أنها تعرض نتيجة التصنيف لموقع الويب الذي يعرض النتيجة.

837d97a27c59a0b3.png

إذا نقرت على التصنيف، لن يحدث شيء لأنه لا يمكن التواصل مع الخلفية بعد.

5. نشر نموذج تصنيف الصور باستخدام TensorFlow

يُعدّ تصنيف الصور مهمة شائعة جدًا تتعلّق بتعلّم الآلة وتصنيف الصورة إلى فئات محدّدة مسبقًا استنادًا إلى المحتوى الأساسي للصورة. في ما يلي مثال على تصنيف الزهور:

a6da16b4a7665db0.png

هناك عدد من نماذج تصنيف الصور المدرَّبة مسبقًا في TensorFlow Hub. أنت تستخدم نموذجًا شهيرًا من Incetion v3 لهذا الدرس التطبيقي حول الترميز.

لنشر نموذج تصنيف الصور مع TensorFlow:

  1. نزِّل ملف النموذج Incetion 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 أولاً، الأمر الذي يستغرق دقيقة واحدة. بعد ذلك، من المفترض أن يبدأ عرض 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 للعرض عنوان Access-Control-Allow-Origin، وبالتالي يحظر المتصفّح الطلب من JavaScript من الواجهة الأمامية إلى TensorFlow العرض لأسباب أمنية. ولحل هذا الأمر، يجب استخدام خادم وكيل، مثل Envoy، لربط الطلب من JavaScript بواجهة TensorFlow العرضية.

بدء Envoy

  • في الوحدة الطرفية، نزِّل صورة 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 العرض لتصنيف الصور. تتوفّر طريقتان لإرسال الطلبات إلى TensorFlow Driving:

  • استراحة
  • gRPC

إرسال طلبات وتلقّي ردود من خلال REST

هناك ثلاث خطوات بسيطة لإرسال الطلبات واستلامها من خلال خدمة REST:

  1. إنشاء طلب REST.
  2. يُرجى إرسال طلب REST إلى TensorFlow serving.
  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 يحتوي على موتّر الصورة لنموذج Incetion 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 مجموعة من الاحتمالات التي تنتمي إليها الصورة في فئات محدّدة مسبقًا. عند نجاح التوقّع، يجب إخراج أكثر فئة احتمالية في واجهة المستخدم.

ويمكنك تنفيذ أداة معالجة 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;

والآن، يستخلص المستمع الاحتمالات المتوقعة من الاستجابة، ويحدّد الفئة الأكثر احتمالاً للعنصر، ويعرض النتيجة في واجهة المستخدم.

التشغيل

  1. في المحطّة الطرفية، انتقِل إلى المجلد starter واستخدِم Webpack لتجميع كل ملفات JavaScript في ملف واحد، يمكنك تضمينه في ملف dist/index.html:
npm install -g npx
npm install --save-dev webpack
npx webpack
  1. حدّث http://localhost:8887/ في المتصفح وانقر على REST > Classify.

يعرض الموقع الإلكتروني 286 على أنه الفئة المتوقعة التي يتم ربطها بتصنيف Egyptian Cat في مجموعة بيانات الصور على NetNet.

c865a93b9b58335d.png

8- ربط الموقع الإلكتروني بخدمة TensorFlow من خلال gRPC

بالإضافة إلى REST، تتوافق خدمة TensorFlow أيضًا مع gRPC.

b6f4449c2c850b0e.png

gRPC هو إطار عمل حديث ومفتوح المصدر وعالي الأداء للإجراءات عن بُعد يمكن تشغيله في أي بيئة. وتستطيع هذه الخدمة توصيل الخدمات بكفاءة في مراكز البيانات وفي مناطق أخرى مع دعم قابل للتوصيل لموازنة الحِمل وتتبُّع الحالة الصحية والمصادقة. لقد لاحظنا أن gRPC هو أكثر أداءً من REST من الناحية العملية.

إرسال الطلبات وتلقّي الردود باستخدام gRPC

هناك أربع خطوات بسيطة:

  1. اختياري: أنشئ رمز كائن gRPC للعميل.
  2. إنشاء طلب gRPC.
  3. أرسِل طلب gRPC إلى TensorFlow العرض.
  4. استخرِج النتيجة المتوقعة من استجابة gRPC وعرضها في واجهة المستخدم.

يمكنك إكمال هذه الخطوات في ملف src/index.js.

اختياري: إنشاء رمز كائن gRPC للعميل

لاستخدام gRPC مع عرض TensorFlow، عليك اتّباع طريقة عمل gRPC. لمعرفة المزيد من التفاصيل، يُرجى الاطّلاع على وثائق gRPC.

a9d0e5cb543467b4.png

يشكّل TensorFlow للعرض وTensorFlow ملفات .proto بالنيابة عنك. اعتبارًا من TensorFlow وTensorFlow العرض 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

وأخيرًا، نفّذ دالة رد الاتصال أعلاه للتعامل مع الاستجابة.

  • أضف هذا الرمز إلى نص الدالة في مقتطف الرمز السابق:
// 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;
}

والآن، يستخلص المستمع الاحتمالات المتوقعة من الاستجابة، ويحدّد الفئة الأكثر احتمالاً للعنصر، ويعرض النتيجة في واجهة المستخدم.

التشغيل

  1. في المحطّة الطرفية، استخدِم حزمة الويب لتجميع جميع ملفات JavaScript في ملف واحد يمكنك تضمينه في ملف index.html:
npx webpack
  1. حدّث http://localhost:8887/ في متصفحك.
  2. انقر على gRPC > Classification.

ويعرض الموقع الإلكتروني الفئة المتوقّعة التي تبلغ 286، والتي يتم ربطها بتصنيف Egyptian Cat في مجموعة بيانات ImageNet.

9- تهانينا

استخدمت منصة TensorFlow لعرض إمكانيات تصنيف الصور على موقعك الإلكتروني.

مزيد من المعلومات