1. לפני שמתחילים
החל מהמלצה על סרטים או מסעדות ועד הדגשת סרטונים מבדרים, מנועי המלצות (שנקראים גם המלצות) הם יישום חשוב מאוד של למידת מכונה. שירות ההמלצות עוזר לך להציג למשתמשים תוכן מעניין מתוך מאגר גדול של מועמדים. לדוגמה, חנות Google Play מציעה מיליוני אפליקציות להתקנה, ואילו YouTube מספק מיליארדי סרטונים לצפייה. וכל יום נוספים עוד אפליקציות וסרטונים.
ב-Codelab הזה תלמדו איך לבנות שירות המלצות מסוג fullstack באמצעות:
- שירות TensorFlow הממליץ לאמן אחזור ומודל דירוג להמלצות על סרטים
- TensorFlow הגשה להגשה של המודלים
- Flutter ליצירת אפליקציה בפלטפורמות שונות להצגת סרטים מומלצים
דרישות מוקדמות
- ידע בסיסי על התפתחות Flutter עם Drt
- ידע בסיסי בלמידת מכונה עם TensorFlow, למשל אימון לעומת פריסה
- היכרות בסיסית עם מערכות של המלצות
- ידע בסיסי ב-Python, טרמינלים ו-Docker
מה תלמדו
- איך לאמן מודלים של אחזור ודירוג באמצעות שירות ההמלצות של TensorFlow
- איך להציג את המודלים של ההמלצות שעברו אימון באמצעות TensorFlow Delivery
- איך ליצור אפליקציה של Flutter בפלטפורמות שונות כדי להציג את הפריטים המומלצים
למה תזדקק?
- Flutter SDK
- הגדרת Android ו-iOS עבור Flutter
- הגדרה של Flutter במחשב
- הגדרת אינטרנט של Flutter
- הגדרה של Visual Studio Code (VS Code) ב-Flutter וב-Dart
- Docker
- באש
- Python 3.7 ואילך
- גישה ל-Colab
2. הגדרת סביבת הפיתוח של Flutter
לפיתוח של Flutter, נדרשות שתי קטעי תוכנה כדי להשלים את ה-Codelab הזה – Flutter SDK ועורך.
אפשר להריץ את החזית של Codelab באמצעות כל אחד מהמכשירים הבאים:
- הסימולטור של iOS (צריך להתקין כלים של Xcode).
- האמולטור של Android (נדרשת הגדרה ב-Android Studio).
- דפדפן (Chrome נדרש לניפוי באגים).
- בתור אפליקציית Windows , Linux או macOS למחשב. צריך לפתח בפלטפורמה שבה אתם מתכננים לפרוס. לכן, כדי לפתח אפליקציה למחשב של Windows, צריך לפתח את האפליקציה ב-Windows כדי לגשת לשרשרת ה-build המתאימה. יש דרישות ספציפיות למערכת ההפעלה שמפורטות בהרחבה בכתובת docs.flutter.dev/desktop.
בשביל הקצה העורפי צריך:
- מחשב Linux או Mac מבוסס Intel.
3. להגדרה
כדי להוריד את הקוד ל-Codelab הזה:
- עוברים אל מאגר ה-GitHub של ה-Codelab הזה.
- לוחצים על קוד > כדי להוריד את כל הקוד ל-Codelab הזה, צריך להוריד את ה-ZIP.
- מחלצים את קובץ ה-ZIP שהורדתם כדי לפתוח תיקיית בסיס מסוג
codelabs-main
עם כל המשאבים הנחוצים.
ב-Codelab הזה, צריך רק את הקבצים בספריית המשנה tfrs-flutter/
במאגר, שמכיל כמה תיקיות:
- התיקיות
step0
עדstep5
מכילות את קוד הסימן לתחילת פעולה שעליו יוצרים בכל שלב ב-Codelab הזה. - התיקייה
finished
מכילה את הקוד שהושלם עבור האפליקציה לדוגמה הסופית. - כל תיקייה מכילה תיקיית משנה
backend
, שכוללת את הקוד לקצה העורפי של מנוע ההמלצות, וגם תיקיית משנהfrontend
, שכוללת את הקוד בקצה הקדמי של Flutter
4. הורדת יחסי התלות של הפרויקט
קצה עורפי
נשתמש ב-Flask כדי ליצור את הקצה העורפי שלנו. פותחים את הטרמינל ומריצים את הפקודה הבאה:
pip install Flask flask-cors requests numpy
קצה קדמי
- ב-VS Code, לוחצים על File > (קובץ >) פותחים את התיקייה ובוחרים בתיקייה
step0
מקוד המקור שהורדתם קודם. - פתיחת הקובץ
step0/frontend/lib/main.dart
. אם מופיעה תיבת דו-שיח של VS Code, עם בקשה להוריד את החבילות הנדרשות לאפליקציה למתחילים, לוחצים על קבלת חבילות. - אם תיבת הדו-שיח הזו לא מופיעה, פותחים את הטרמינל ואז מריצים את הפקודה
flutter pub get
בתיקייהstep0/frontend
.
5. שלב 0: מפעילים את האפליקציה לתחילת הפעולה
- פותחים את הקובץ
step0/frontend/lib/main.dart
ב-VS Code, מוודאים שהאמולטור של Android או הסימולטור של iOS מוגדרים כראוי ומופיעים בשורת הסטטוס.
לדוגמה, זה מה שרואים כשמשתמשים ב-Pixel 5 עם האמולטור Android:
כשמשתמשים ב-iPhone 13 עם הסימולטור של iOS, רואים את הפרטים הבאים:
- לוחצים על התחלת ניפוי באגים.
הפעלה וגילוי של האפליקציה
האפליקציה צריכה להיות מופעלת באמולטור Android או בסימולטור של iOS. ממשק המשתמש הוא די פשוט. יש שדה טקסט שמאפשר למשתמש להקליד את הטקסט בתור מזהה המשתמש. אפליקציית Flutter תשלח את בקשת השאילתה לקצה העורפי, שמפעיל שני מודלים של המלצות ומחזיר רשימה מדורגת של המלצות לסרטים. הקצה הקדמי יציג את התוצאה בממשק המשתמש לאחר קבלת התגובה.
אם תלחצו על ההמלצה, לא יקרה כלום כי האפליקציה עדיין לא יכולה לתקשר עם הקצה העורפי.
6. שלב 1: יצירת מודלים לאחזור ודירוג של מנוע ההמלצות
בדרך כלל, מנועי ההמלצות בעולם האמיתי מורכבים מכמה שלבים:
- בשלב השליפה אחראיים לבחירת קבוצה ראשונית של מאות מועמדים מתוך כל המועמדים האפשריים. המטרה העיקרית של המודל הזה היא לסנן ביעילות את כל המועמדים שהמשתמשים לא מעוניינים בהם. מכיוון שמודל האחזור מטפל במיליוני מועמדים, הוא חייב להיות יעיל מבחינה חישובית.
- שלב הדירוג לוקח את הפלטים של מודל האחזור ומכוונן אותם כדי לבחור את ההמלצות הטובות ביותר. המשימה שלה היא לצמצם את קבוצת הפריטים שהמשתמש עשוי להתעניין בהם, לרשימה קצרה של מועמדים אפשריים, לפי סדר של מאות.
- השלב שאחרי הדירוג עוזר להבטיח מגוון, עדכניות והוגנות ומארגנת מחדש את הפריטים המועמדים בסדרת המלצות שימושיות לפי סדר של עשרות.
בשביל ה-codelab הזה, תאמנו מודל אחזור ומודל דירוג באמצעות מערך הנתונים הפופולרי MovieLens. אפשר לפתוח את קוד האימון שלמטה דרך Colab ולפעול לפי ההוראות:
7. שלב 2: יצירת הקצה העורפי של מנוע ההמלצות
עכשיו, אחרי שתרגלתם את המודלים לאחזור והדירוג, אתם יכולים לפרוס אותם וליצור קצה עורפי.
התחלת ההצגה של TensorFlow
בגלל שצריך להשתמש גם במודלים לאחזור וגם במודלים של דירוג כדי ליצור את רשימת הסרטים המומלצים, אתם צריכים לפרוס את שניהם בו-זמנית באמצעות שירות 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 -
אתם יכולים לשלוח בקשה לדוגמה לנקודת הקצה (endpoint) כדי לוודא שהיא פועלת כצפוי:
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'); }
הפעלה
- לוחצים על התחלת ניפוי באגים ומחכים עד שהאפליקציה תיטען.
- צריך להזין מזהה משתמש (כלומר 42) ואז בוחרים באפשרות מומלץ.
9. שלב 4: מפעילים את אפליקציית Flutter בפלטפורמות למחשבים
בנוסף ל-Android ול-iOS, אפליקציית Flutter תומכת גם בפלטפורמות למחשב, כולל Linux, Mac ו-Windows.
Linux
- צריך לוודא שמכשיר היעד מוגדר לערך בשורת הסטטוס של VSCode.
- לוחצים על התחלת ניפוי באגים ומחכים עד שהאפליקציה תיטען.
- צריך להזין מזהה משתמש (כלומר 42) ואז בוחרים באפשרות מומלץ.
Mac
- ב-Mac צריך להגדיר את ההרשאות המתאימות כי האפליקציה תשלח בקשות HTTP לקצה העורפי. לפרטים נוספים, ניתן לעיין בהרשאות וארגז החול של האפליקציות.
מוסיפים את הקוד הזה אל step4/frontend/macOS/Runner/DebugProfile.entitlements
ואל step4/frontend/macOS/Runner/Release.entitlements
בהתאמה:
<key>com.apple.security.network.client</key>
<true/>
- צריך לוודא שמכשיר היעד מוגדר לערך בשורת הסטטוס של VSCode.
- לוחצים על התחלת ניפוי באגים ומחכים עד שהאפליקציה תיטען.
- צריך להזין מזהה משתמש (כלומר 42) ואז בוחרים באפשרות מומלץ.
Windows
- צריך לוודא שמכשיר היעד מוגדר לערך בשורת הסטטוס של VSCode.
- לוחצים על התחלת ניפוי באגים ומחכים עד שהאפליקציה תיטען.
- צריך להזין מזהה משתמש (כלומר 42) ואז בוחרים באפשרות מומלץ.
10. שלב 5: מפעילים את אפליקציית Flutter בפלטפורמת האינטרנט
דבר נוסף שניתן לעשות הוא להוסיף תמיכה באינטרנט לאפליקציית Flutter. כברירת מחדל, פלטפורמת האינטרנט מופעלת באופן אוטומטי עבור אפליקציות Flutter, כך שכל מה שצריך לעשות הוא להפעיל אותה.
- צריך לוודא שמכשיר היעד מוגדר לערך בשורת הסטטוס של VSCode.
- לוחצים על התחלת ניפוי באגים ומחכים עד שהאפליקציה תיטען בדפדפן Chrome.
- צריך להזין מזהה משתמש (כלומר 42) ואז בוחרים באפשרות מומלץ.
11. מזל טוב
יצרת אפליקציית fullstack כדי להמליץ על סרטים למשתמשים שלך!
למרות שהאפליקציה ממליצה רק על סרטים, למדתם את תהליך העבודה הכולל של פיתוח מנוע המלצות מתקדם ושאתם שולטים במיומנות לקבל את ההמלצות באפליקציית Flutter. אתם יכולים ליישם בקלות את מה שלמדתם בתרחישים אחרים (למשל, מסחר אלקטרוני, אוכל וסרטונים קצרים).