إنشاء تطبيق iOS لتوقّع القيم

1. قبل البدء

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

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

  • معرفة أساسية بالتطوير باستخدام نظام التشغيل iOS باستخدام Swift
  • معرفة أساسية بتعلُّم الآلة مع TensorFlow، مثل التدريب والنشر
  • المعرفة الأساسية بميزة Colaboratory
  • معرفة أساسية بالأطراف الطرفية وPython وVault

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

  • طريقة تدريب نموذج التراجع باستخدام TensorFlow
  • كيفية إنشاء تطبيق iOS بسيط وتوقُّع التوقعات باستخدام النموذج المُدرَّب من خلال TensorFlow للعرض (REST وgRPC).
  • كيفية عرض النتيجة في واجهة المستخدم.

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

2. الإعداد

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

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

a72f2bb4caa9a96.png

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

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

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

3- تنزيل تبعيات المشروع

تنزيل اللوحات المطلوبة

  • في المجلد starter/iOS، شغِّل:
pod install

سيثبّت Cocoapods جميع المكتبات اللازمة وينشئ ملف regression.xcworkspace جديدًا.

4. تشغيل تطبيق إجراء التفعيل

  • انقر مرّتين على الملف regression.xcworkspace لفتح Xcode.

تشغيل التطبيق واستكشافه

  1. يمكنك تغيير استهداف الجهاز إلى أي هاتف iPhone، مثل iPhone 13.

a57198a4f21f970.png

  1. انقر على cacc15c5638260ed.png "Run'، ثم انتظر حتى يجري Xcode تجميع المشروع وبدء تطبيق المبتدئين في المحاكي.

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

d2976072474ce0b1.png

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

5. تدريب نموذج التراجع البسيط مع TensorFlow

تُعدّ ميزة التراجع أحد مهام ML الأكثر شيوعًا. ويكمن هدفها في توقّع كمية واحدة متواصلة استنادًا إلى البيانات التي يتم إدخالها. على سبيل المثال، استنادًا إلى حالة الطقس اليوم، من المتوقّع أن تصل درجة الحرارة القصوى غدًا.

تدريب نموذج التراجع

  1. افتح هذا الرابط في المتصفّح.

يحمّل Colab دفتر ملاحظات Python.

  1. في دفتر ملاحظات Python، يمكنك استيراد TensorFlow وNumPy من المكتبات، ثم إنشاء ستة أزواج من بيانات التدريب باستخدام xs كإدخال وys كتصنيفات.

إذا رسمت نقاط البيانات هذه على رسم بياني، فإنها في الواقع في خط مستقيم لأنها يتم إنشاؤها من المعادلة y = 2x -1.

56d05252cfc9df9d.png

  1. يمكنك استخدام Keras API لإنشاء شبكة عصبونية بسيطة من طبقتَين لتوقّع القيمة y استنادًا إلى إدخال x، ثم تجميع النموذج وملاءمةه.
xs = np.array([-1.0,  0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
ys = np.array([-3.0, -1.0, 1.0, 3.0, 5.0, 7.0], dtype=float)

model = tf.keras.Sequential([
   tf.keras.layers.Dense(units=10, input_shape=[1]),
   tf.keras.layers.Dense(units=1),
   ])

model.compile(optimizer='sgd',
             loss='mean_squared_error')

history = model.fit(xs, ys, epochs=500, verbose=0)

print("Finished training the model")

print(model.predict([10.0]))

يستغرق تدريب النموذج بضع ثوانٍ ويمكنك رؤية القيمة المتوقعة لإدخال 10 هي 18.999996، وهي توقع جيد إلى حد ما لأن الحقيقة الأساسية هي 2 * 10 -1 = 19.

  1. تصدير النموذج:
model_dir = './regression/'
version = 123
export_path = os.path.join(model_dir, str(version))
model.save(export_path, save_format="tf")
print('\nexport_path = {}'.format(export_path))
!ls -l {export_path}
  1. ضغط النموذج المحفوظ في ملف regression.zip واحد:
!zip -r regression.zip ./regression
  1. انقر على تشغيل وقت > تشغيل الكل في قائمة التنقل لتشغيل دفتر الملاحظات ثم انتظار انتهاء الجري.
  2. انقر على C55600d42359f901.png ملفات ثم نزِّل الملف regression.zip.

بَدِيَّة

6- نشر نموذج لإجراء التراجع باستخدام TensorFlow

  • لنشر النموذج من خلال TensorFlow Driving، يمكنك فك ضغط ملف regression.zip الذي تم تنزيله باستخدام أداة فك ضغط، مثل 7-Zip.

يجب أن تظهر بنية المجلد على النحو التالي:

7faeb4f03af39646.png

يمكنك الإشارة إلى المجلد regression باعتباره المجلد SavedModel. 123 هو مثال على رقم الإصدار. يمكنك اختيار رقم آخر، إذا أردت ذلك.

بدء عرض TensorFlow

  • في الوحدة الطرفية، ابدأ تشغيل TensorFlow للعرض باستخدام docker، ولكن استبدِل العنصر النائب PATH/TO/SAVEDMODEL بالمسار المطلق للمجلد regression على جهاز الكمبيوتر.
docker pull tensorflow/serving

docker run -it --rm -p 8500:8500 -p 8501:8501 -v "PATH/TO/SAVEDMODEL:/models/regression" -e MODEL_NAME=regression 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/ssd_mobilenet_v2_2/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/ssd_mobilenet_v2_2/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: regression 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 ...

7- ربط تطبيق iOS بخدمة TensorFlow العرض من خلال REST

أصبحت الخلفية جاهزة الآن، لذا يمكنك إرسال طلبات العميل إلى TensorFlow التنبؤ لتقديم توقعات. تتوفّر طريقتان لإرسال الطلبات إلى TensorFlow Driving:

  • استراحة
  • gRPC

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

هناك ثلاث خطوات بسيطة:

  1. إنشاء طلب REST.
  2. يُرجى إرسال طلب REST إلى TensorFlow serving.
  3. استخرِج النتيجة المتوقعة من استجابة REST واعرض واجهة المستخدم.

يمكنك تنفيذ هذه الخطوات في ملف iOS/regression/ViewController.swift.

إنشاء طلب REST

  1. لا ترسل دالة doInference() في الوقت الحالي طلب REST إلى TensorFlow العرض. عليك تنفيذ فرع REST هذا لإنشاء طلب REST:
if (connectionMode[picker.selectedRow(inComponent: 0)] == "REST") {
    print("Using REST")
    // TODO: Add code to send a REST request to TensorFlow Serving.
    
}

تتوقع منصة TensorFlow العرض طلب POST يحتوي على قيمة واحدة، لذا عليك تضمين قيمة الإدخال في JSON، وهو حمولة الطلب.

  1. إضافة هذا الرمز إلى فرع REST:
//Create the REST request.
let json: [String: Any] = ["signature_name" : "serving_default", "instances" : [[value]]]

let jsonData = try? JSONSerialization.data(withJSONObject: json)

let url = URL(string: "http://localhost:8501/v1/models/regression:predict")!
var request = URLRequest(url: url)
request.httpMethod = "POST"

// Insert JSON data into the request.
request.httpBody = jsonData

إرسال طلب REST إلى TensorFlow للعرض

  • أضف هذا الرمز مباشرةً بعد الرمز في فرع REST:
// Send the REST request.
let task = URLSession.shared.dataTask(with: request) { data, response, error in
    guard let data = data, error == nil else {
        print(error?.localizedDescription ?? "No data")
        return
    }
    
    // TODO: Add code to process the response.
}

task.resume()

معالجة استجابة REST من TensorFlow العرض

  • يمكنك إضافة هذا الرمز إلى مقتطف الرمز السابق بعد تعليق TODO: Add code to process the response. مباشرةً:
// Process the REST response.
let results: RESTResults = try! JSONDecoder().decode(RESTResults.self, from: data)
DispatchQueue.main.async{
    self.txtOutput.text = String(results.predictions[0][0])
}

والآن، تستخرج دالة ما بعد المعالجة القيم المتوقعة من الاستجابة وتعرض النتيجة في واجهة المستخدم.

التشغيل

  1. انقر على cacc15c5638260ed.png "Run'، ثم انتظر حتى يتم إطلاق Xcode من خلال التطبيق "محاكي".
  2. أدخل رقمًا في مربع النص، ثم انقر على استنتاج.

ستظهر لك الآن قيمة متوقعة في واجهة المستخدم.

df9bcb9aa21bb30e.png

8- ربط تطبيق iOS بخدمة TensorFlow من خلال خدمة gRPC

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

b6f4449c2c850b0e.png

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

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

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

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

يمكنك تنفيذ هذه الخطوات في ملف iOS/regression/ViewController.swift.

اختياري: إنشاء رمز كائن 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

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

  1. في الوحدة الطرفية، انتقِل إلى المجلد starter/src/proto/ ثم أنشئ التنويه الموجز:
bash generate_grpc_stub_swift.sh

يتم إنشاء عدد من الملفات البالغ عددها .swift في المجلد starter/src/proto/generated/import.

  1. وإذا لم يتم نسخها إلى مشروعك بعد، اسحب جميع ملفات .swift التي تم إنشاؤها إلى مشروعك في Xcode.

9e65705cf6be7aac.png

إنشاء طلب gRPC

على غرار طلب REST، يمكنك إنشاء طلب gRPC في فرع gRPC.

if (connectionMode[picker.selectedRow(inComponent: 0)] == "REST") {
    
}
else {
    print("Using gRPC")
    // TODO: add code to send a gRPC request to TF Serving
    
}
  • لإنشاء طلب gRPC، أضِف هذا الرمز إلى فرع gRPC:
//Create the gRPC request.
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
let channel = ClientConnection.insecure(group: group).connect(host: "localhost", port: 8500)
let stub = Tensorflow_Serving_PredictionServiceClient(channel: channel)

var modelSpec = Tensorflow_Serving_ModelSpec()
modelSpec.name = "regression"
modelSpec.signatureName = "serving_default"

// Prepare the input tensor.
var batchDim = Tensorflow_TensorShapeProto.Dim()
batchDim.size = 1
var inputDim = Tensorflow_TensorShapeProto.Dim()
inputDim.size = 1
var inputTensorShape = Tensorflow_TensorShapeProto()
inputTensorShape.dim = [batchDim, inputDim]
var inputTensor = Tensorflow_TensorProto()
inputTensor.dtype = Tensorflow_DataType.dtFloat
inputTensor.tensorShape = inputTensorShape
inputTensor.floatVal = [Float(value)]

var request = Tensorflow_Serving_PredictRequest()
request.modelSpec = modelSpec
request.inputs = ["dense_input" : inputTensor]

let callOptions = CallOptions(timeLimit: .timeout(.seconds(15)))

إرسال طلب gRPC إلى TensorFlow العرض

  • أضف هذا الرمز إلى فرع gRPC مباشرةً بعد الرمز في مقتطف الرمز السابق:
// Send the gRPC request.
let call = stub.predict(request, callOptions: callOptions)

معالجة استجابة gRPC من TensorFlow

  • أضف هذا الرمز مباشرةً بعد الرمز في مقتطف الرمز السابق:
// Process the response.
call.response.whenSuccess { response in
    let result = response.outputs["dense_1"]?.floatVal[0]
    DispatchQueue.main.async{
        self.txtOutput.text = String(describing: result!)
    }
}
call.response.whenFailure { error in
    print("Call failed with error\n\(error)")
}

والآن، تستخرج دالة ما بعد المعالجة القيم المتوقعة من الاستجابة وتعرض النتيجة في واجهة المستخدم.

التشغيل

  1. انقر على cacc15c5638260ed.png "Run' في قائمة التنقل، ثم انتظر حتى يتم إطلاق Xcode عن التطبيق في المحاكي.
  2. أدخل رقمًا في مربع النص، ثم انقر على استنتاج.

ستظهر لك الآن قيمة متوقعة في واجهة المستخدم.

9- تهانينا

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

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