مساعدة في حماية الحاجز المرجاني العظيم مع TensorFlow على Kaggle تاريخ التحدي

RESTful API

بالإضافة إلى gRPC واجهات برمجة التطبيقات TensorFlow ModelServer كما يدعم واجهات برمجة التطبيقات مريحة. توضح هذه الصفحة هذه النهاية API ونهاية إلى نهاية مثال على الاستخدام.

الطلب والاستجابة عبارة عن كائن JSON. يعتمد تكوين هذا الكائن على نوع الطلب أو الفعل. راجع أقسام API المحددة أدناه للحصول على التفاصيل.

في حالة الخطأ، وجميع واجهات برمجة التطبيقات بإرجاع كائن JSON في الجسم استجابة مع error كمفتاح ورسالة خطأ على أنها القيمة:

{
  "error": <error message string>
}

نموذج حالة API

هذا API تتابع عن كثب ModelService.GetModelStatus API gRPC. تقوم بإرجاع حالة النموذج في ModelServer.

URL

GET http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]

بما في ذلك /versions/${VERSION} أو /labels/${LABEL} اختيارية. إذا تم حذف حالة جميع الإصدارات يتم إرجاعها في الاستجابة.

تنسيق الاستجابة

في حال نجاحها، بإرجاع تمثيل JSON من GetModelStatusResponse protobuf.

نموذج Metadata API

هذا API تتابع عن كثب PredictionService.GetModelMetadata API gRPC. تقوم بإرجاع البيانات الوصفية لنموذج في ModelServer.

URL

GET http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]/metadata

بما في ذلك /versions/${VERSION} أو /labels/${LABEL} اختيارية. إذا تم حذف بيانات تعريف النموذج لأحدث إصدار ، يتم إرجاعها في الاستجابة.

تنسيق الاستجابة

في حال نجاحها، بإرجاع تمثيل JSON من GetModelMetadataResponse protobuf.

تصنيف وتراجع API

هذا API تتابع عن كثب Classify و Regress طرق PredictionService gRPC API.

URL

POST http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]:(classify|regress)

بما في ذلك /versions/${VERSION} أو /labels/${LABEL} اختيارية. في حالة حذفه ، يتم استخدام أحدث إصدار.

تنسيق الطلب

نص طلب ل classify و regress يجب أن تكون واجهات برمجة التطبيقات كائن JSON تنسيق على النحو التالي:

{
  // Optional: serving signature to use.
  // If unspecifed default serving signature is used.
  "signature_name": <string>,

  // Optional: Common context shared by all examples.
  // Features that appear here MUST NOT appear in examples (below).
  "context": {
    "<feature_name3>": <value>|<list>
    "<feature_name4>": <value>|<list>
  },

  // List of Example objects
  "examples": [
    {
      // Example 1
      "<feature_name1>": <value>|<list>,
      "<feature_name2>": <value>|<list>,
      ...
    },
    {
      // Example 2
      "<feature_name1>": <value>|<list>,
      "<feature_name2>": <value>|<list>,
      ...
    }
    ...
  ]
}

<value> هو رقم JSON (كليا أو عشري)، سلسلة JSON، أو كائن JSON التي تمثل البيانات الثنائية (انظر القيم ثنائي ترميز أدناه للحصول على مزيد من التفاصيل). <list> هي قائمة من هذه القيم. هذا الشكل يشبه gRPC في ClassificationRequest و RegressionRequest بروتوس. كلا الإصدارين تقبل قائمة Example الكائنات.

تنسيق الاستجابة

A classify طلب بإرجاع كائن JSON في الجسم ردا على ذلك، منسقة على النحو التالي:

{
  "result": [
    // List of class label/score pairs for first Example (in request)
    [ [<label1>, <score1>], [<label2>, <score2>], ... ],

    // List of class label/score pairs for next Example (in request)
    [ [<label1>, <score1>], [<label2>, <score2>], ... ],
    ...
  ]
}

<label> هو سلسلة (التي يمكن أن تكون سلسلة فارغة "" إذا لم يكن لديك نموذج تسمية المرتبطة النتيجة). <score> هو (نقطة عائمة) عدد عشري.

و regress طلب بإرجاع كائن JSON في الجسم ردا على ذلك، منسقة على النحو التالي:

{
  // One regression value for each example in the request in the same order.
  "result": [ <value1>, <value2>, <value3>, ...]
}

<value> هو رقم عشري.

وسيكون للمستخدمين من gRPC API يلاحظ تشابه هذا الشكل مع ClassificationResponse و RegressionResponse بروتوس.

توقع API

هذا API تتابع عن كثب PredictionService.Predict API gRPC.

URL

POST http://host:port/v1/models/${MODEL_NAME}[/versions/${VERSION}|/labels/${LABEL}]:predict

بما في ذلك /versions/${VERSION} أو /labels/${LABEL} اختيارية. في حالة حذفه ، يتم استخدام أحدث إصدار.

تنسيق الطلب

نص طلب لل predict API يجب أن يكون الكائن JSON تنسيق على النحو التالي:

{
  // (Optional) Serving signature to use.
  // If unspecifed default serving signature is used.
  "signature_name": <string>,

  // Input Tensors in row ("instances") or columnar ("inputs") format.
  // A request can have either of them but NOT both.
  "instances": <value>|<(nested)list>|<list-of-objects>
  "inputs": <value>|<(nested)list>|<object>
}

تحديد موتر الإدخال بتنسيق الصف.

هذا الشكل يشبه PredictRequest بروتو من gRPC API و CMLE التنبؤ API . استخدام هذا الشكل إذا كانت كل التنسورات إدخال اسمه نفس 0-عشر بعدا. إذا لم يفعلوا ذلك ، فاستخدم التنسيق العمودي الموضح لاحقًا أدناه.

في شكل صف واحد، ومرتبطا المدخلات إلى مفتاح الحالات في طلب JSON.

عندما يكون هناك واحد فقط اسمه المدخلات، وتحديد قيمة من الحالات الرئيسية أن تكون قيمة المدخلات:

{
  // List of 3 scalar tensors.
  "instances": [ "foo", "bar", "baz" ]
}

{
  // List of 2 tensors each of [1, 2] shape
  "instances": [ [[1, 2]], [[3, 4]] ]
}

يتم التعبير عن الموترات بشكل طبيعي في تدوين متداخل حيث لا توجد حاجة لتسوية القائمة يدويًا.

بالنسبة للمدخلات المتعددة المسماة ، من المتوقع أن يكون كل عنصر كائنًا يحتوي على اسم الإدخال / زوج قيمة الموتر ، واحد لكل إدخال مسمى. على سبيل المثال ، ما يلي هو طلب من مثيلين ، كل منهما به مجموعة من ثلاث موترات إدخال مسماة:

{
 "instances": [
   {
     "tag": "foo",
     "signal": [1, 2, 3, 4, 5],
     "sensor": [[1, 2], [3, 4]]
   },
   {
     "tag": "bar",
     "signal": [3, 4, 1, 2, 5]],
     "sensor": [[4, 5], [6, 8]]
   }
 ]
}

ملاحظة، كل المدخلات اسمه ( "العلامة"، "إشارة"، "الاستشعار") يفترض ضمنيا لها نفس 0 عشر، بعد (اثنان في المثال أعلاه، كما أن هناك نوعان من الكائنات في قائمة الحالات). إذا قمت بتسمية المدخلات التي لها بُعد مختلف من 0 ، فاستخدم التنسيق العمودي الموضح أدناه.

تحديد موترات الإدخال بتنسيق العمود.

استخدم هذا التنسيق لتحديد موتر الإدخال الخاص بك ، إذا لم يكن للمدخلات الفردية المسماة نفس البعد 0-th أو كنت تريد تمثيلاً أكثر إحكاما. هذا شكل مشابه ل inputs مجال gRPC Predict الطلب.

في شكل عمودي، ومرتبطا المدخلات إلى مفتاح المدخلات في طلب JSON.

قيمة مفتاح المدخلات يمكن إما موتر مدخل واحد أو خريطة اسم الإدخال إلى التنسورات (المدرجة في المداخلات الطبيعي بهم). يمكن أن يكون لكل إدخال شكل تعسفي ولا يحتاج إلى مشاركة / نفس البعد 0-th (المعروف أيضًا باسم حجم الدُفعة) كما هو مطلوب بواسطة تنسيق الصف الموضح أعلاه.

التمثيل العمودي للمثال السابق كما يلي:

{
 "inputs": {
   "tag": ["foo", "bar"],
   "signal": [[1, 2, 3, 4, 5], [3, 4, 1, 2, 5]],
   "sensor": [[[1, 2], [3, 4]], [[4, 5], [6, 8]]]
 }
}

ملاحظة، والمدخلات هي كائن JSON وليس قائمة مثل حالات (المستخدمة في تمثيل صف). أيضًا ، يتم تحديد جميع المدخلات المسماة معًا ، بدلاً من فتحها في صفوف فردية يتم إجراؤها بتنسيق الصف الموضح سابقًا. هذا يجعل التمثيل مضغوطًا (ولكن ربما أقل قابلية للقراءة).

تنسيق الاستجابة

و predict طلب بإرجاع كائن JSON في الجسم استجابة.

طلب في شكل صف واحد واستجابة منسقة على النحو التالي:

{
  "predictions": <value>|<(nested)list>|<list-of-objects>
}

إذا إخراج نموذج يحتوي على واحد فقط اسمه موتر، ونحن حذف اسم و predictions مفتاح الخرائط إلى قائمة العددية أو قائمة القيم. إذا كان النموذج ينتج موترات متعددة مسماة ، فإننا نخرج قائمة كائنات بدلاً من ذلك ، على غرار الطلب بتنسيق الصف المذكور أعلاه.

طلب في شكل عمودي واستجابة منسقة على النحو التالي:

{
  "outputs": <value>|<(nested)list>|<object>
}

إذا إخراج نموذج يحتوي على واحد فقط اسمه موتر، ونحن حذف اسم و outputs خرائط المفتاح إلى قائمة العددية أو قائمة القيم. إذا كان النموذج ينتج موترات متعددة مسماة ، فإننا نخرج كائنًا بدلاً من ذلك. يتوافق كل مفتاح لهذا الكائن مع موتر إخراج مسمى. التنسيق مشابه للطلب في تنسيق العمود المذكور أعلاه.

إخراج القيم الثنائية

لا يميز TensorFlow بين السلاسل غير الثنائية والسلاسل الثنائية. كلها DT_STRING نوع. التنسورات اسمه أن يكون _bytes تعتبر لاحقة باسمهم أن يكون ثنائي القيم. يتم ترميز هذه القيم بشكل مختلف كما هو موضح في ترميز القيم الثنائية أدناه.

تعيين JSON

تدعم واجهات برمجة التطبيقات RESTful التشفير المتعارف عليه في JSON ، مما يسهل مشاركة البيانات بين الأنظمة. بالنسبة للأنواع المدعومة ، يتم وصف الترميزات على أساس نوع بنوع في الجدول أدناه. الأنواع غير المدرجة أدناه تعتبر غير مدعومة.

نوع بيانات TF قيمة JSON مثال على JSON ملحوظات
DT_BOOL خطأ صحيح خطأ صحيح
DT_STRING سلسلة "مرحبا بالعالم!" إذا DT_STRING يمثل بايت الثنائية (مثل تسلسل بايت صورة أو protobuf)، ترميز هذه في باستخدام Base64. انظر ترميز القيم الثنائية لمزيد من المعلومات.
DT_INT8 ، DT_UINT8 ، DT_INT16 ، DT_INT32 ، DT_UINT32 ، DT_INT64 ، DT_UINT64 عدد 1 ، -10 ، 0 ستكون قيمة JSON رقمًا عشريًا.
DT_FLOAT ، DT_DOUBLE عدد 1.1 -10.0، 0، NaN ، Infinity ستكون قيمة JSON رقم أو إحدى القيم رمزية خاصة - NaN ، Infinity ، و -Infinity . انظر JSON المطابقة للمزيد من المعلومات. كما يتم قبول تدوين الأس.

دقة النقطة العائمة

يحتوي JSON على نوع بيانات رقم واحد. وبالتالي ، من الممكن توفير قيمة لمدخل ينتج عنه فقدان الدقة. على سبيل المثال، إذا كان إدخال x هو float نوع البيانات، وإدخال {"x": 1435774380} يتم إرسالها إلى نموذج يعمل على الأجهزة القائمة على IEEE 754 عائمة مستوى نقطة (مثل Intel أو AMD)، ثم سوف قيمة يتم تحويل بصمت من قبل الأجهزة underyling إلى 1435774336 منذ 1435774380 لا يمكن تمثيل بالضبط في عدد النقطة العائمة 32 بت. عادة ، يجب أن تكون مدخلات الخدمة هي نفس توزيع التدريب ، لذلك لن يكون هذا بشكل عام مشكلة لأن نفس التحويلات حدثت في وقت التدريب. ومع ذلك ، في حالة الحاجة إلى الدقة الكاملة ، تأكد من استخدام نوع بيانات أساسي في نموذجك يمكنه التعامل مع الدقة المطلوبة و / أو التفكير في التحقق من جانب العميل.

ترميز القيم الثنائية

يستخدم JSON ترميز UTF-8. إذا كان لديك المدخلات ميزة أو موتر القيم التي تحتاج إلى أن يكون ثنائي (مثل بايت الصورة)، يجب عليك باستخدام Base64 ترميز البيانات وتغلف في كائن JSON وجود b64 كمفتاح على النحو التالي:

{ "b64": <base64 encoded string> }

يمكنك تحديد هذا الكائن كقيمة لميزة إدخال أو موتر. يتم استخدام نفس التنسيق لتشفير استجابة الإخراج أيضًا.

طلب تصنيف مع image (البيانات الثنائية) و caption هو مبين أدناه الميزات:

{
  "signature_name": "classify_objects",
  "examples": [
    {
      "image": { "b64": "aW1hZ2UgYnl0ZXM=" },
      "caption": "seaside"
    },
    {
      "image": { "b64": "YXdlc29tZSBpbWFnZSBieXRlcw==" },
      "caption": "mountains"
    }
  ]
}

مطابقة JSON

العديد من قيم المعالم أو الموتر هي أرقام فاصلة عائمة. وبصرف النظر عن قيمتها محدودة (مثلا 3.14، 1.0 الخ) وهذه يمكن أن يكون NaN وغير محدود ( Infinity و -Infinity ) القيم. للأسف مواصفات JSON ( RFC 7159 ) لا تعترف بتلك القيم (على الرغم من أن مواصفات جافا سكريبت يفعل).

تسمح واجهة برمجة تطبيقات REST الموضحة في هذه الصفحة بامتلاك مثل هذه القيم لكائنات JSON للطلب / الاستجابة. هذا يعني أن الطلبات مثل الطلبات التالية صالحة:

{
  "example": [
    {
      "sensor_readings": [ 1.0, -3.14, Nan, Infinity ]
    }
  ]
}

وهناك معايير (صارمة) JSON متوافقة محلل رفض هذا مع خطأ تحليل (بسبب NaN و Infinity ورموز مختلطة مع الأرقام الفعلية). للتعامل مع الطلبات / الردود بشكل صحيح في التعليمات البرمجية الخاصة بك ، استخدم محلل JSON الذي يدعم هذه الرموز المميزة.

NaN ، Infinity ، -Infinity يتم التعرف على الرموز التي proto3 ، بيثون JSON وحدة ولغة جافا سكريبت.

مثال

يمكننا استخدام لعبة half_plus_three نموذج لرؤية واجهات برمجة التطبيقات REST في العمل.

ابدأ ModelServer بنقطة نهاية REST API

تحميل half_plus_three نموذج من بوابة مستودع :

$ mkdir -p /tmp/tfserving
$ cd /tmp/tfserving
$ git clone --depth=1 https://github.com/tensorflow/serving

سوف نستخدم Docker لتشغيل ModelServer. إذا كنت ترغب في تثبيت ModelServer أصلا على النظام الخاص بك، اتبع تعليمات الإعداد لتثبيت بدلا من ذلك، وبدء ModelServer مع --rest_api_port الخيار لنقطة النهاية تصدير REST API (وهذا ليست هناك حاجة عند استخدام عامل الميناء).

$ cd /tmp/tfserving
$ docker pull tensorflow/serving:latest
$ docker run --rm -p 8501:8501 \
    --mount type=bind,source=$(pwd),target=$(pwd) \
    -e MODEL_BASE_PATH=$(pwd)/serving/tensorflow_serving/servables/tensorflow/testdata \
    -e MODEL_NAME=saved_model_half_plus_three -t tensorflow/serving:latest
...
.... Exporting HTTP/REST API at:localhost:8501 ...

قم بإجراء مكالمات REST API إلى ModelServer

في محطة مختلفة، استخدم curl أداة لإجراء مكالمات API REST.

احصل على حالة النموذج على النحو التالي:

$ curl http://localhost:8501/v1/models/saved_model_half_plus_three
{
 "model_version_status": [
  {
   "version": "123",
   "state": "AVAILABLE",
   "status": {
    "error_code": "OK",
    "error_message": ""
   }
  }
 ]
}

و predict أن الدعوة تبدو على النحو التالي:

$ curl -d '{"instances": [1.0,2.0,5.0]}' -X POST http://localhost:8501/v1/models/saved_model_half_plus_three:predict
{
    "predictions": [3.5, 4.0, 5.5]
}

و regress تبدو الدعوة على النحو التالي:

$ curl -d '{"signature_name": "tensorflow/serving/regress", "examples": [{"x": 1.0}, {"x": 2.0}]}' \
  -X POST http://localhost:8501/v1/models/saved_model_half_plus_three:regress
{
    "results": [3.5, 4.0]
}

ملاحظة، regress متاح في اسم توقيع غير الافتراضي ويجب تحديد صراحة. يؤدي عنوان URL أو النص الأساسي لطلب غير صحيح إلى حالة خطأ HTTP.

$ curl -i -d '{"instances": [1.0,5.0]}' -X POST http://localhost:8501/v1/models/half:predict
HTTP/1.1 404 Not Found
Content-Type: application/json
Date: Wed, 06 Jun 2018 23:20:12 GMT
Content-Length: 65

{ "error": "Servable not found for request: Latest(half)" }
$