لمحة عن هذا الدرس التطبيقي حول الترميز
1. قبل البدء
في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية تشغيل استنتاج التراجع من تطبيق iOS باستخدام TensorFlow serving باستخدام REST وgRPC.
المتطلّبات الأساسية
- معرفة أساسية بالتطوير باستخدام نظام التشغيل iOS باستخدام Swift
- معرفة أساسية بتعلُّم الآلة مع TensorFlow، مثل التدريب والنشر
- المعرفة الأساسية بميزة Colaboratory
- معرفة أساسية بالأطراف الطرفية وPython وVault
ما ستتعرَّف عليه
- طريقة تدريب نموذج التراجع باستخدام TensorFlow
- كيفية إنشاء تطبيق iOS بسيط وتوقُّع التوقعات باستخدام النموذج المُدرَّب من خلال TensorFlow للعرض (REST وgRPC).
- كيفية عرض النتيجة في واجهة المستخدم.
الأشياء التي تحتاج إليها
- الوصول إلى Colab
- أحدث إصدار من Xcode
- بندق الكاكاو
- الدوكر
- البش
- المُجمِّع المؤقت للمخزون المؤقت للبروتوكول (مطلوب فقط إذا كنت تريد إعادة إنشاء مثيل gRPC بنفسك)
- المكوّن الإضافي الخاص بمنشئ رمز gRPC-swift (مطلوب فقط إذا كنت تريد إنشاء رمز بديل gRPC بنفسك)
2. الإعداد
لتنزيل الرمز في هذا الدرس التطبيقي حول الترميز:
- انتقِل إلى مستودع GitHub لهذا الدرس التطبيقي حول الترميز.
- انقر على رمز > تنزيل ملف zip لتنزيل كل رموز هذا الدرس التطبيقي حول الترميز.
- يمكنك فك ضغط ملف ZIP الذي تم تنزيله لفك ضغط مجلد الجذر
codelabs
الذي يحتوي على جميع الموارد التي تحتاجها.
بالنسبة إلى هذا الدرس التطبيقي حول الترميز، تحتاج فقط إلى الملفات في دليل TFServing/RegressioniOS
الفرعي في المستودع، الذي يحتوي على مجلدَين:
- يتضمّن المجلد
starter
رمز التفعيل الذي تستند إليه في هذا الدرس التطبيقي حول الترميز. - يحتوي مجلد
finished
على الرمز المكتمل لنموذج التطبيق المكتمل.
3. تنزيل تبعيات المشروع
تنزيل اللوحات المطلوبة
- في المجلد
starter/iOS
، شغِّل:
pod install
سيثبّت Cocoapods جميع المكتبات اللازمة وينشئ ملف regression.xcworkspace
جديدًا.
4. تشغيل تطبيق إجراء التفعيل
- انقر مرّتين على الملف
regression.xcworkspace
لفتح Xcode.
تشغيل التطبيق واستكشافه
- يمكنك تغيير استهداف الجهاز إلى أي هاتف iPhone، مثل iPhone 13.
- انقر على
"Run'، ثم انتظر حتى يجري Xcode تجميع المشروع وبدء تطبيق المبتدئين في المحاكي.
واجهة المستخدم سهلة جدًا. هناك مربع نص يمكنك كتابة رقم به، ويتم إرساله إلى خلفية TensorFlow serving باستخدام REST أو gRPC. تؤدي الخلفية إلى التراجع على قيمة الإدخال وعرض القيمة المتوقعة على تطبيق العميل، والتي تعرض النتيجة في واجهة المستخدم مرة أخرى.
وإذا أدخلت رقمًا ونقرت على استنتاج، لن يحدث شيء لأن التطبيق لا يمكنه التواصل مع الخلفية حتى الآن.
5. تدريب نموذج التراجع البسيط مع TensorFlow
تُعدّ ميزة التراجع أحد مهام ML الأكثر شيوعًا. ويكمن هدفها في توقّع كمية واحدة متواصلة استنادًا إلى البيانات التي يتم إدخالها. على سبيل المثال، استنادًا إلى حالة الطقس اليوم، من المتوقّع أن تصل درجة الحرارة القصوى غدًا.
تدريب نموذج التراجع
- افتح هذا الرابط في المتصفّح.
يحمّل Colab دفتر ملاحظات Python.
- في دفتر ملاحظات Python، يمكنك استيراد
TensorFlow
وNumPy
من المكتبات، ثم إنشاء ستة أزواج من بيانات التدريب باستخدامxs
كإدخال وys
كتصنيفات.
إذا رسمت نقاط البيانات هذه على رسم بياني، فإنها في الواقع في خط مستقيم لأنها يتم إنشاؤها من المعادلة y = 2x -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.
- تصدير النموذج:
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}
- ضغط النموذج المحفوظ في ملف
regression.zip
واحد:
!zip -r regression.zip ./regression
- انقر على تشغيل وقت > تشغيل الكل في قائمة التنقل لتشغيل دفتر الملاحظات ثم انتظار انتهاء الجري.
- انقر على
ملفات ثم نزِّل الملف
regression.zip
.
6. نشر نموذج لإجراء التراجع باستخدام TensorFlow
- لنشر النموذج من خلال TensorFlow Driving، يمكنك فك ضغط ملف
regression.zip
الذي تم تنزيله باستخدام أداة فك ضغط، مثل 7-Zip.
يجب أن تظهر بنية المجلد على النحو التالي:
يمكنك الإشارة إلى المجلد 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
هناك ثلاث خطوات بسيطة:
- إنشاء طلب REST.
- يُرجى إرسال طلب REST إلى TensorFlow serving.
- استخرِج النتيجة المتوقعة من استجابة REST واعرض واجهة المستخدم.
يمكنك تنفيذ هذه الخطوات في ملف iOS/regression/ViewController.swift
.
إنشاء طلب REST
- لا ترسل دالة
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، وهو حمولة الطلب.
- إضافة هذا الرمز إلى فرع 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])
}
والآن، تستخرج دالة ما بعد المعالجة القيم المتوقعة من الاستجابة وتعرض النتيجة في واجهة المستخدم.
التشغيل
- انقر على
"Run'، ثم انتظر حتى يتم إطلاق Xcode من خلال التطبيق "محاكي".
- أدخل رقمًا في مربع النص، ثم انقر على استنتاج.
ستظهر لك الآن قيمة متوقعة في واجهة المستخدم.
8. ربط تطبيق iOS بخدمة TensorFlow من خلال خدمة gRPC
بالإضافة إلى REST، تتوافق خدمة TensorFlow أيضًا مع gRPC.
gRPC هو إطار عمل حديث ومفتوح المصدر وعالي الأداء للإجراءات عن بُعد يمكن تشغيله في أي بيئة. وتستطيع هذه الخدمة توصيل الخدمات بكفاءة في مراكز البيانات وفي مناطق أخرى مع دعم قابل للتوصيل لموازنة الحِمل وتتبُّع الحالة الصحية والمصادقة. لقد لاحظنا أن gRPC هو أكثر أداءً من REST من الناحية العملية.
إرسال الطلبات وتلقّي الردود باستخدام gRPC
هناك أربع خطوات بسيطة:
- اختياري: أنشئ رمز كائن gRPC للعميل.
- إنشاء طلب gRPC.
- أرسِل طلب gRPC إلى TensorFlow العرض.
- استخرِج النتيجة المتوقعة من استجابة gRPC وعرض واجهة المستخدم.
يمكنك تنفيذ هذه الخطوات في ملف iOS/regression/ViewController.swift
.
اختياري: إنشاء رمز كائن gRPC للعميل
لاستخدام gRPC مع عرض TensorFlow، عليك اتّباع طريقة عمل gRPC. لمعرفة المزيد من التفاصيل، يُرجى الاطّلاع على وثائق gRPC.
يشكّل 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 للعميل:
- في الوحدة الطرفية، انتقِل إلى المجلد
starter/src/proto/
ثم أنشئ التنويه الموجز:
bash generate_grpc_stub_swift.sh
يتم إنشاء عدد من الملفات البالغ عددها .swift
في المجلد starter/src/proto/generated/import
.
- وإذا لم يتم نسخها إلى مشروعك بعد، اسحب جميع ملفات
.swift
التي تم إنشاؤها إلى مشروعك في Xcode.
إنشاء طلب 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)")
}
والآن، تستخرج دالة ما بعد المعالجة القيم المتوقعة من الاستجابة وتعرض النتيجة في واجهة المستخدم.
التشغيل
- انقر على
"Run' في قائمة التنقل، ثم انتظر حتى يتم إطلاق Xcode عن التطبيق في المحاكي.
- أدخل رقمًا في مربع النص، ثم انقر على استنتاج.
ستظهر لك الآن قيمة متوقعة في واجهة المستخدم.