إنشاء نظام كامل لاقتراح الأفلام

1. قبل البدء

تُعدّ محرّكات الاقتراحات، المعروفة أيضًا باسم أدوات الاقتراحات، تطبيقًا مهمًا جدًا للتعلم الآلي، بدءًا من اقتراح الأفلام أو المطاعم، وصولاً إلى عرض فيديوهات مسلّية. تساعدك أنظمة التوصية في عرض محتوى جذّاب من مجموعة كبيرة من المحتوى المرشّح للمستخدمين. على سبيل المثال، يوفّر "متجر Google Play" الملايين من التطبيقات لتثبيتها، بينما يوفّر YouTube المليارات من الفيديوهات لمشاهدتها. وتتم إضافة المزيد من التطبيقات والفيديوهات كل يوم.

في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية إنشاء نظام توصية متكامل باستخدام:

  • ‫TensorFlow Recommenders لتدريب نموذج استرجاع ونموذج ترتيب لاقتراحات الأفلام
  • منصة TensorFlow للعرض لخدمة النماذج
  • ‫Flutter لإنشاء تطبيق من عدّة منصات لعرض الأفلام المقترَحة

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

  • معرفة أساسية بتطوير تطبيقات Flutter باستخدام Dart
  • معرفة أساسية بتعلُّم الآلة باستخدام TensorFlow، مثل التدريب مقابل النشر
  • معرفة أساسية بأنظمة التوصية
  • معرفة أساسية بلغة Python والأوامر الطرفية وDocker

أهداف الدورة التعليمية

  • كيفية تدريب نماذج الاسترجاع والترتيب باستخدام TensorFlow Recommenders
  • كيفية عرض نماذج الاقتراحات المدرَّبة باستخدام منصة TensorFlow للعرض
  • كيفية إنشاء تطبيق Flutter متوافق مع عدّة منصات لعرض المنتجات المقترَحة

المتطلبات

2. إعداد بيئة تطوير Flutter

لتطوير Flutter، تحتاج إلى برنامجَين لإكمال هذا الدرس التطبيقي حول الترميز، وهما حزمة تطوير البرامج (SDK) الخاصة بـ Flutter ومحرّر.

يمكنك تشغيل الواجهة الأمامية من الدرس العملي باستخدام أي من الأجهزة التالية:

  • محاكي iOS (يتطلّب تثبيت أدوات Xcode)
  • محاكي Android (يتطلّب الإعداد في "استوديو Android")
  • متصفّح (يجب استخدام Chrome لتصحيح الأخطاء).
  • كتطبيق سطح مكتب على Windows أو Linux أو macOS يجب أن يتم التطوير على النظام الأساسي الذي تخطّط للنشر عليه. لذا، إذا أردت تطوير تطبيق سطح مكتب لنظام التشغيل Windows، يجب أن يتم التطوير على Windows للوصول إلى سلسلة الإنشاء المناسبة. هناك متطلبات خاصة بنظام التشغيل يتم تناولها بالتفصيل على الرابط docs.flutter.dev/desktop.

بالنسبة إلى الخلفية، ستحتاج إلى ما يلي:

  • جهاز Linux أو جهاز Mac يستند إلى معالج Intel

3- طريقة الإعداد

لتنزيل الرمز البرمجي لهذا الدرس التطبيقي حول الترميز، اتّبِع الخطوات التالية:

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

2cd45599f51fb8a2.png

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

في هذا الدرس العملي، تحتاج فقط إلى الملفات الموجودة في الدليل الفرعي tfrs-flutter/ في المستودع، والذي يحتوي على مجلدات متعددة:

  • يحتوي المجلّدان step0 وstep5 على الرمز الأولي الذي ستستند إليه في كل خطوة من خطوات هذا الدرس البرمجي.
  • يحتوي المجلد finished على الرمز البرمجي المكتمل لنموذج التطبيق النهائي.
  • يحتوي كل مجلد على مجلد فرعي backend يتضمّن الرمز الخلفي لمحرك الاقتراحات، ومجلد فرعي frontend يتضمّن الرمز الأمامي لتطبيق Flutter.

4. تنزيل التبعيات للمشروع

الخلفية

سنستخدم Flask لإنشاء الخلفية. افتح الوحدة الطرفية ونفِّذ ما يلي:

pip install Flask flask-cors requests numpy

الواجهة الأمامية

  1. في VS Code، انقر على ملف > فتح مجلد، ثم اختَر المجلد step0 من رمز المصدر الذي نزّلته سابقًا.
  2. افتح ملف step0/frontend/lib/main.dart. إذا ظهر لك مربّع حوار VS Code يطلب منك تنزيل الحِزم المطلوبة لتطبيق البداية، انقر على الحصول على الحِزم (Get packages).
  3. إذا لم يظهر لك مربع الحوار هذا، افتح نافذة الأوامر ثم نفِّذ الأمر flutter pub get في المجلد step0/frontend.

7ada07c300f166a6.png

5- الخطوة 0: تشغيل تطبيق البداية

  1. افتح ملف step0/frontend/lib/main.dart في VS Code، وتأكَّد من إعداد "Android Emulator" أو "محاكي iOS" بشكل صحيح وظهورهما في شريط الحالة.

على سبيل المثال، إليك ما يظهر عند استخدام هاتف Pixel 5 مع "محاكي Android":

9767649231898791.png

في ما يلي ما يظهر عند استخدام iPhone 13 مع iOS Simulator:

95529e3a682268b2.png

  1. انقر على a19a0c68bc4046e6.png بدء تصحيح الأخطاء.

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

يجب تشغيل التطبيق على "محاكي Android" أو "محاكي iOS". واجهة المستخدم بسيطة جدًا. يتوفّر حقل نص يتيح للمستخدم كتابة النص كمعرّف للمستخدم. سيرسل تطبيق Flutter طلب البحث إلى الخلفية، التي ستشغّل نموذجين للاقتراحات وتعرض قائمة مرتّبة باقتراحات الأفلام. ستعرض الواجهة الأمامية النتيجة في واجهة المستخدم بعد تلقّي الردّ.

d21427db9587560f.png 73e8272a5ce8dfbc.png

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

6. الخطوة 1: إنشاء نماذج الاسترجاع والترتيب لمحرك التوصية

تتألف محركات التوصيات في العالم الحقيقي غالبًا من مراحل متعددة:

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

70dfc0d7e989164f.png

في هذا الدرس التطبيقي حول الترميز، ستدرّب نموذج استرجاع ونموذج ترتيب باستخدام مجموعة بيانات MovieLens الشائعة. يمكنك فتح رمز التدريب أدناه من خلال Colab واتّباع التعليمات:

7. الخطوة 2: إنشاء الخلفية لمحرك التوصية

بعد تدريب نماذج الاسترجاع والترتيب، يمكنك نشرها وإنشاء نظام خلفي.

بدء TensorFlow Serving

بما أنّك تحتاج إلى استخدام كلّ من نموذجَي الاسترجاع والترتيب لإنشاء قائمة الأفلام المقترَحة، يمكنك تفعيلهما معًا في الوقت نفسه باستخدام منصة TensorFlow للعرض.

  • في نافذة الوحدة الطرفية، انتقِل إلى المجلد step2/backend على جهاز الكمبيوتر وابدأ منصة TensorFlow للعرض باستخدام Docker:
docker run -t --rm -p 8501:8501 -p 8500:8500 -v "$(pwd)/:/models/" tensorflow/serving --model_config_file=/models/models.config

ينزّل Docker تلقائيًا صورة منصة TensorFlow للعرض أولاً، ويستغرق ذلك دقيقة واحدة. بعد ذلك، من المفترض أن تبدأ منصة TensorFlow للعرض. يجب أن يبدو السجلّ على النحو التالي: مقتطف الرمز هذا:

2022-04-24 09:32:06.461702: I tensorflow_serving/model_servers/server_core.cc:465] Adding/updating models.
2022-04-24 09:32:06.461843: I tensorflow_serving/model_servers/server_core.cc:591]  (Re-)adding model: retrieval
2022-04-24 09:32:06.461907: I tensorflow_serving/model_servers/server_core.cc:591]  (Re-)adding model: ranking
2022-04-24 09:32:06.576920: I tensorflow_serving/core/basic_manager.cc:740] Successfully reserved resources to load servable {name: retrieval version: 123}
2022-04-24 09:32:06.576993: I tensorflow_serving/core/loader_harness.cc:66] Approving load for servable version {name: retrieval version: 123}
2022-04-24 09:32:06.577011: I tensorflow_serving/core/loader_harness.cc:74] Loading servable version {name: retrieval version: 123}
2022-04-24 09:32:06.577848: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:38] Reading SavedModel from: /models/retrieval/exported-retrieval/123
2022-04-24 09:32:06.583809: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:90] Reading meta graph with tags { serve }
2022-04-24 09:32:06.583879: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:132] Reading SavedModel debug info (if present) from: /models/retrieval/exported-retrieval/123
2022-04-24 09:32:06.584970: I external/org_tensorflow/tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2022-04-24 09:32:06.629900: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle.
2022-04-24 09:32:06.634662: I external/org_tensorflow/tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 2800000000 Hz
2022-04-24 09:32:06.672534: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/retrieval/exported-retrieval/123
2022-04-24 09:32:06.673629: I tensorflow_serving/core/basic_manager.cc:740] Successfully reserved resources to load servable {name: ranking version: 123}
2022-04-24 09:32:06.673765: I tensorflow_serving/core/loader_harness.cc:66] Approving load for servable version {name: ranking version: 123}
2022-04-24 09:32:06.673786: I tensorflow_serving/core/loader_harness.cc:74] Loading servable version {name: ranking version: 123}
2022-04-24 09:32:06.674731: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:38] Reading SavedModel from: /models/ranking/exported-ranking/123
2022-04-24 09:32:06.683557: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:90] Reading meta graph with tags { serve }
2022-04-24 09:32:06.683601: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:132] Reading SavedModel debug info (if present) from: /models/ranking/exported-ranking/123
2022-04-24 09:32:06.688665: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 110815 microseconds.
2022-04-24 09:32:06.690019: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/retrieval/exported-retrieval/123/assets.extra/tf_serving_warmup_requests
2022-04-24 09:32:06.693025: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: retrieval version: 123}
2022-04-24 09:32:06.702594: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle.
2022-04-24 09:32:06.745361: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/ranking/exported-ranking/123
2022-04-24 09:32:06.772363: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 97633 microseconds.
2022-04-24 09:32:06.774853: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/ranking/exported-ranking/123/assets.extra/tf_serving_warmup_requests
2022-04-24 09:32:06.777706: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: ranking version: 123}
2022-04-24 09:32:06.778969: I tensorflow_serving/model_servers/server_core.cc:486] Finished adding/updating models
2022-04-24 09:32:06.779030: I tensorflow_serving/model_servers/server.cc:367] Profiler service is enabled
2022-04-24 09:32:06.784217: 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-04-24 09:32:06.785748: 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 ...

إنشاء نقطة نهاية جديدة

بما أنّ منصة TensorFlow للعرض لا تتيح "ربط" نماذج متعدّدة متسلسلة، عليك إنشاء خدمة جديدة تربط بين نماذج الاسترجاع والترتيب.

  • أضِف الرمز التالي إلى الدالة get_recommendations() في الملف step2/backend/recommendations.py:
user_id = request.get_json()["user_id"]
retrieval_request = json.dumps({"instances": [user_id]})
retrieval_response = requests.post(RETRIEVAL_URL, data=retrieval_request)
movie_candidates = retrieval_response.json()["predictions"][0]["output_2"]

ranking_queries = [
    {"user_id": u, "movie_title": m}
    for (u, m) in zip([user_id] * NUM_OF_CANDIDATES, movie_candidates)
]
ranking_request = json.dumps({"instances": ranking_queries})
ranking_response = requests.post(RANKING_URL, data=ranking_request)
movies_scores = list(np.squeeze(ranking_response.json()["predictions"]))
ranked_movies = [
    m[1] for m in sorted(list(zip(movies_scores, movie_candidates)), reverse=True)
]

return make_response(jsonify({"movies": ranked_movies}), 200)

بدء خدمة Flask

يمكنك الآن بدء خدمة Flask.

  • في الوحدة الطرفية، انتقِل إلى المجلد step2/backend/ وشغِّل ما يلي:
FLASK_APP=recommender.py FLASK_ENV=development flask run

سيُنشئ Flask نقطة نهاية جديدة في http://localhost:5000/recommend. من المفترض أن يظهر السجلّ كما يلي:

 * Serving Flask app 'recommender.py' (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 705-382-264
127.0.0.1 - - [25/Apr/2022 19:44:47] "POST /recommend HTTP/1.1" 200 -

يمكنك إرسال نموذج طلب إلى نقطة النهاية للتأكّد من أنّها تعمل على النحو المتوقّع:

curl -X POST -H "Content-Type: application/json" -d '{"user_id":"42"}' http://localhost:5000/recommend

ستعرض نقطة النهاية قائمة بالأفلام المقترَحة للمستخدم 42:

{
  "movies": [
    "While You Were Sleeping (1995)",
    "Preacher's Wife, The (1996)",
    "Michael (1996)",
    "Lion King, The (1994)",
    "Father of the Bride Part II (1995)",
    "Sleepless in Seattle (1993)",
    "101 Dalmatians (1996)",
    "Bridges of Madison County, The (1995)",
    "Rudy (1993)",
    "Jack (1996)"
  ]
}

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

8. الخطوة 3: إنشاء تطبيق Flutter لنظامَي التشغيل Android وiOS

الخادم الخلفي جاهز. يمكنك البدء بإرسال طلبات إليه للاستعلام عن اقتراحات الأفلام من تطبيق Flutter.

تطبيق الواجهة الأمامية بسيط إلى حدّ ما. يحتوي فقط على TextField الذي يتلقّى معرّف المستخدم ويرسل الطلب (في الدالة recommend()) إلى الخلفية التي أنشأتها للتو. بعد تلقّي الردّ، تعرض واجهة مستخدم التطبيق الأفلام المقترَحة في ListView.

  • أضِف الرمز التالي إلى الدالة recommend() في الملف step3/frontend/lib/main.dart:
final response = await http.post(
  Uri.parse('http://' + _server + ':5000/recommend'),
  headers: <String, String>{
    'Content-Type': 'application/json',
  },
  body: jsonEncode(<String, String>{
    'user_id': _userIDController.text,
  }),
);

بعد أن يتلقّى التطبيق الردّ من الخلفية، عليك تعديل واجهة المستخدم لعرض قائمة الأفلام المقترَحة للمستخدم المحدّد.

  • أضِف هذا الرمز مباشرةً أسفل الرمز أعلاه:
if (response.statusCode == 200) {
  return List<String>.from(jsonDecode(response.body)['movies']);
} else {
  throw Exception('Error response');
}

تشغيلها

  1. انقر على a19a0c68bc4046e6.png بدء تصحيح الأخطاء ثم انتظِر حتى يتم تحميل التطبيق.
  2. أدخِل معرّف مستخدم (مثل ‫42)، ثم انقر على اقتراح.

badb59d8b96959ae.png a0d2d4020aebfb0a.png

9- الخطوة 4: تشغيل تطبيق Flutter على منصات أجهزة الكمبيوتر

بالإضافة إلى Android وiOS، يتوافق Flutter أيضًا مع أنظمة التشغيل على أجهزة الكمبيوتر، بما في ذلك Linux وMac وWindows.

Linux

  1. تأكَّد من ضبط جهاز الاختبار على 86cba523de82b4f9.png في شريط الحالة في VSCode.
  2. انقر على a19a0c68bc4046e6.png بدء تصحيح الأخطاء ثم انتظِر حتى يتم تحميل التطبيق.
  3. أدخِل معرّف مستخدم (مثل ‫42)، ثم انقر على اقتراح.

2665514231033f1.png

Mac

  1. بالنسبة إلى أجهزة Mac، عليك إعداد الأذونات المناسبة لأنّ التطبيق سيرسل طلبات HTTP إلى الخلفية. يُرجى الرجوع إلى مقالة الأذونات وبيئة الاختبار المعزولة للتطبيق للحصول على مزيد من التفاصيل.

أضِف الرمز التالي إلى step4/frontend/macOS/Runner/DebugProfile.entitlements وstep4/frontend/macOS/Runner/Release.entitlements على التوالي:

<key>com.apple.security.network.client</key>
<true/>
  1. تأكَّد من ضبط جهاز الاختبار على eb4b0b5563824138.png في شريط الحالة في VSCode.
  2. انقر على a19a0c68bc4046e6.png بدء تصحيح الأخطاء ثم انتظِر حتى يتم تحميل التطبيق.
  3. أدخِل معرّف مستخدم (مثل ‫42)، ثم انقر على اقتراح.

860d523a7ac537e0.png

Windows

  1. تأكَّد من ضبط جهاز الاختبار على 9587be1bb375bc0f.png في شريط الحالة في VSCode.
  2. انقر على a19a0c68bc4046e6.png بدء تصحيح الأخطاء ثم انتظِر حتى يتم تحميل التطبيق.
  3. أدخِل معرّف مستخدم (مثل ‫42)، ثم انقر على اقتراح.

7d77c1e52a5927fc.png

10. الخطوة 5: تشغيل تطبيق Flutter على منصة الويب

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

  1. تأكَّد من ضبط جهاز الاختبار على 71db93efa928d15d.png في شريط الحالة في VSCode.
  2. انقر على a19a0c68bc4046e6.png بدء تصحيح الأخطاء، ثم انتظِر حتى يتم تحميل التطبيق في متصفّح Chrome.
  3. أدخِل معرّف مستخدم (مثل ‫42)، ثم انقر على اقتراح.

9376e1e432c18bef.png

11. تهانينا

لقد أنشأت تطبيقًا متكاملاً لاقتراح أفلام على المستخدمين.

على الرغم من أنّ التطبيق يقترح الأفلام فقط، تعرّفت على سير العمل العام لإنشاء محرك اقتراحات قوي وأتقنت مهارة استخدام الاقتراحات في تطبيق Flutter. يمكنك بسهولة تطبيق ما تعلّمته على سيناريوهات أخرى (مثل التجارة الإلكترونية والأطعمة والفيديوهات القصيرة).

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