מידע על Codelab זה
1. לפני שמתחילים
בשיעור ה-Lab הזה תלמדו איך להריץ מסקנות לסיווג טקסט באמצעות אפליקציה של Fluter עם הצגת TensorFlow דרך REST ו-gRPC.
דרישות מוקדמות
- היכרות בסיסית עם פיתוח פלוטר עם חצים
- ידע בסיסי בלמידה חישובית עם TensorFlow, כמו אימון לעומת פריסה
- ידע בסיסי על מסופים ותחנות עגינה
- לימוד מודל לזיהוי תגובות ספאם באמצעות TensorFlow Lite Maker Codelab
מה תלמדו
- איך לבנות אפליקציה פשוטה של Flutter ולסווג טקסטים באמצעות TensorFlow הגשה (REST ו-gRPC).
- איך להציג את התוצאות בממשק המשתמש.
מה תצטרך להכין
- SDK לפלאש
- הגדרת Android או iOS ל-Fluter
- הגדרת קוד Visual Studio (קוד VS) עבור Flutter ו-Dart
- אביזר עגינה
- שיט
- מהדר מאגר של מאגר protocol ופלאגין gRPC Dat עבור מהדר פרוטוקול (נדרש רק אם רוצים ליצור מחדש את סשן ה-gRPC בעצמכם)
2. הגדרת סביבת הפיתוח של Flutter
כדי לפתח את Fluter, תצטרכו שתי תוכנות כדי להשלים את שיעור ה-Lab הזה - Fluter SDK ו-Editor.
ניתן להריץ את קוד Lab באמצעות אחד מהמכשירים הבאים:
- הסימולטור של iOS (נדרש התקנה של כלי Xcode).
- האמולטור של Android (נדרש הגדרה ב-Android Studio).
- דפדפן (כדי לנפות באגים צריך להשתמש ב-Chrome).
- כאפליקציה של Windows , Linux או macOS. עליכם לפתח בפלטפורמה שבה אתם מתכננים לפרוס. לכן, אם ברצונך לפתח אפליקציה ל-Windows Desktop, עליך לפתח ב-Windows כדי לגשת לשרשרת הבנייה המתאימה. הדרישות הספציפיות למערכת הפעלה מפורטות במאמר docs.flutter.dev/desktop.
3. להגדרה
כדי להוריד את הקוד של Lab Lab זה:
- עוברים אל מאגר GitHub עבור מעבדת קוד זו.
- לוחצים על Code > הורדת zip כדי להוריד את כל הקוד של מעבדת הקוד הזו.
- יש לבטל את הדחיסה של קובץ ה-ZIP שהורדת כדי לפתוח את תיקיית הבסיס של
codelabs-main
עם כל המשאבים הדרושים.
ב-codelab זה נדרשים רק הקבצים בספריית המשנה tfserving-flutter/codelab2
במאגר, המכיל שתי תיקיות:
- התיקייה
starter
מכילה את הקוד למתחילים שעליו כדאי לבנות את מעבדת הקוד הזו. - התיקייה
finished
מכילה את הקוד המלא לאפליקציה לדוגמה שהושלמה.
4. להוריד את התלות של הפרויקט
- בקוד VS, לוחצים על קובץ > פתיחת תיקייה ולאחר מכן בוחרים את התיקייה
starter
בקוד המקור שהורדתם בעבר. - אם מופיעה תיבת דו-שיח שבה מתבקשים להוריד את החבילות הדרושות לאפליקציה למתחילים, לוחצים על קבלת חבילות.
- אם תיבת הדו-שיח לא מופיעה, יש לפתוח את המסוף ואז להריץ את הפקודה
flutter pub get
בתיקייהstarter
.
5. הפעלת האפליקציה למתחילים
- בקוד VS, מוודאים שהאמולטור של Android או הסימולטור של iOS מוגדר כראוי ומופיע בשורת הסטטוס.
לדוגמה, מה שמוצג כשמשתמשים ב-Pixel 5 עם אמולטור Android:
זה מה שמוצג בעת שימוש ב-iPhone 13 עם סימולטור iOS:
- לוחצים על
התחלת ניפוי באגים.
הרצה ועיון באפליקציה
יש להפעיל את האפליקציה באמולטור Android או בסימולטור iOS. ממשק המשתמש פשוט למדי. יש שדה טקסט שמאפשר למשתמש להקליד את הטקסט. המשתמשים יכולים לבחור אם לשלוח את הנתונים לקצה העורפי באמצעות REST או gRPC. הקצה העורפי משתמש במודל TensorFlow כדי לבצע סיווג של טקסט בקלט מעובד מראש ומחזיר את תוצאת הסיווג לאפליקציית הלקוח, שמעדכנת את ממשק המשתמש.
אם לוחצים על סיווג, לא יקרה דבר כי עדיין לא ניתן לתקשר עם הקצה העורפי.
6. פריסת מודל של סיווג טקסט באמצעות TensorFlow serving
סיווג טקסט הוא משימה נפוצה מאוד בתחום הלמידה החישובית. הסיווג הזה מסווג את הטקסטים בקטגוריות מוגדרות מראש. ב-codelab הזה, אתם פורסים את המודל המיומן מראש מאימון מודל לזיהוי ספאם באמצעות תגובות עם הקוד של TensorFlow Lite Maker Maker, באמצעות קריאה ל-TenororFlow וקורא את הקצה העורפי של Flutter של ממשק הקצה, כדי לסווג את הטקסט שהזנת כספאם או כלא ספאם.
התחלת הצגה של TensorFlow
- במסוף, מפעילים את TensorFlow serving עם Docker, אבל מחליפים את ה-placeholder
PATH/TO/SAVEDMODEL
בנתיב המוחלט של תיקייתmm_spam_savedmodel
במחשב.
docker pull tensorflow/serving docker run -it --rm -p 8500:8500 -p 8501:8501 -v "PATH/TO/SAVEDMODEL:/models/spam-detection" -e MODEL_NAME=spam-detection tensorflow/serving
אביזר העגינה מוריד תחילה באופן אוטומטי את התמונה של TensorFlow serving. לאחר מכן, ההצגה של 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: spam-detection 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. יצירת אסימון קלט למשפט
הקצה העורפי מוכן עכשיו, כך שאתם כמעט מוכנים לשלוח בקשות של לקוחות ל-TensorFlow serving, אבל קודם צריך לתת אסימון למשפט הקלט. אם תבדקו את טנור הקלט של המודל, תוכלו לראות שהוא מצפה לרשימה של 20 מספרים שלמים ולא למחרוזות גולמיות. אסימון הוא שיטה שבה ממפים את המילים הספציפיות שמקלידים באפליקציה לרשימה של מספרים שלמים על סמך מילון אוצר מילים לפני ששולחים אותן לקצה העורפי לצורך סיווג. לדוגמה, אם מקלידים buy book online to learn more
, תהליך יצירת האסימון ממפה אותו אל [32, 79, 183, 10, 224, 631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
. המספרים הספציפיים עשויים להשתנות בהתאם למילון המונחים.
- בקובץ
lib/main.dart
, יש להוסיף את הקוד לשיטהpredict()
כדי ליצור את מילון המונחים_vocabMap
.
// Build _vocabMap if empty.
if (_vocabMap.isEmpty) {
final vocabFileString = await rootBundle.loadString(vocabFile);
final lines = vocabFileString.split('\n');
for (final l in lines) {
if (l != "") {
var wordAndIndex = l.split(' ');
(_vocabMap)[wordAndIndex[0]] = int.parse(wordAndIndex[1]);
}
}
}
- מיד אחרי קטע הקוד הקודם צריך להוסיף את הקוד הזה כדי להטמיע את האסימון:
// Tokenize the input sentence.
final inputWords = _inputSentenceController.text
.toLowerCase()
.replaceAll(RegExp('[^a-z ]'), '')
.split(' ');
// Initialize with padding token.
_tokenIndices = List.filled(maxSentenceLength, 0);
var i = 0;
for (final w in inputWords) {
if ((_vocabMap).containsKey(w)) {
_tokenIndices[i] = (_vocabMap)[w]!;
i++;
}
// Truncate the string if longer than maxSentenceLength.
if (i >= maxSentenceLength - 1) {
break;
}
}
הקוד הזה מקטין את מחרוזת המשפט, מסיר תווים שאינם אלפביתיים וממפה את המילים ל-20 אינדקסים של מספרים שלמים על סמך טבלת אוצר המילים.
8. חיבור של האפליקציה Flutter עם TensorFlow serving דרך REST
יש שתי דרכים לשלוח בקשות ל-TensorFlow serving:
- REST
- gRPC
שליחת בקשות וקבלת תשובות דרך REST
יש שלושה שלבים פשוטים לשליחת בקשות ולקבלת תשובות דרך REST:
- יוצרים את הבקשה ל-REST.
- שליחת בקשת REST להגשה של TensorFlow.
- מחלצים את התוצאה החזויה מתגובת ה-REST ומעבדים את ממשק המשתמש.
יש להשלים את השלבים האלה בקובץ main.dart
.
יצירה ושליחה של בקשת REST ל-TensorFlow serving
- נכון לעכשיו, הפונקציה
predict()
לא שולחת את הבקשה ל-REST להצגת TensorFlow. כדי ליצור בקשת REST, צריך להטמיע את הסניף של REST:
if (_connectionMode == ConnectionModeType.rest) {
// TODO: Create and send the REST request.
}
- מוסיפים את הקוד הזה לסניף של REST:
//Create the REST request.
final response = await http.post(
Uri.parse('http://' +
_server +
':' +
restPort.toString() +
'/v1/models/' +
modelName +
':predict'),
body: jsonEncode(<String, List<List<int>>>{
'instances': [_tokenIndices],
}),
);
עיבוד התגובה ל-REST מ-TensorFlow serving
- מוסיפים את הקוד הזה מייד אחרי קטע הקוד הקודם כדי לטפל בתגובה ל-REST:
// Process the REST response.
if (response.statusCode == 200) {
Map<String, dynamic> result = jsonDecode(response.body);
if (result['predictions']![0][1] >= classificationThreshold) {
return 'This sentence is spam. Spam score is ' +
result['predictions']![0][1].toString();
}
return 'This sentence is not spam. Spam score is ' +
result['predictions']![0][1].toString();
} else {
throw Exception('Error response');
}
הקוד שמופיע לאחר העיבוד עובד ומחליק את ההסתברות שמשפט הקלט הוא הודעת ספאם מהתגובה, ומציג את תוצאת הסיווג בממשק המשתמש.
הפעלה
- לוחצים על
התחלת ניפוי באגים וממתינים לטעינה של האפליקציה.
- מזינים טקסט ובוחרים באפשרות REST > Classification.
9. חיבור של אפליקציית Flutter עם TensorFlow serving דרך gRPC
בנוסף ל-REST, שירות TensorFlow תומך גם ב-gRPC.
gRPC היא מסגרת מודרנית ומודרנית של ביצועים טובים (RTT) שניתן להפעיל בכל סביבה. הוא יכול לחבר שירותים ביעילות למרכזי נתונים, ובהם בתמיכה, לאיזון עומסים, למעקב אחר נתונים, לבדיקת תקינות ולאימות. התגלה ש-gRPC מניב ביצועים טובים יותר בהשוואה ל-REST בפועל.
שליחה של בקשות וקבלת תשובות באמצעות gRPC
יש ארבעה שלבים פשוטים לשליחת בקשות ולקבלת תשובות באמצעות gRPC:
- אופציונלי: יצירת קוד stub של לקוח gRPC.
- יוצרים את בקשת ה-gRPC.
- שליחת בקשת gRPC לשירות TensorFlow.
- מחלצים את התוצאה החזויה מתגובת ה-gRPC ומעבדים את ממשק המשתמש.
יש להשלים את השלבים האלה בקובץ main.dart
.
אופציונלי: יצירת קוד stub של לקוח gRPC
כדי להשתמש ב-gRPC עם TensorFlow serving, יש לפעול לפי תהליך העבודה של 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
google/protobuf/any.proto
google/protobuf/wrappers.proto
- במסוף שלך, עליך להיכנס לתיקייה
starter/lib/proto/
וליצור את הסימן הבא:
bash generate_grpc_stub_dart.sh
יצירת בקשת gRPC
בדומה לבקשת ה-REST, יוצרים את בקשת gRPC בסניף gRPC.
if (_connectionMode == ConnectionModeType.rest) {
} else {
// TODO: Create and send the gRPC request.
}
- יש להוסיף את הקוד הזה כדי ליצור את בקשת ה-gRPC:
//Create the gRPC request.
final channel = ClientChannel(_server,
port: grpcPort,
options:
const ChannelOptions(credentials: ChannelCredentials.insecure()));
_stub = PredictionServiceClient(channel,
options: CallOptions(timeout: const Duration(seconds: 10)));
ModelSpec modelSpec = ModelSpec(
name: 'spam-detection',
signatureName: 'serving_default',
);
TensorShapeProto_Dim batchDim = TensorShapeProto_Dim(size: Int64(1));
TensorShapeProto_Dim inputDim =
TensorShapeProto_Dim(size: Int64(maxSentenceLength));
TensorShapeProto inputTensorShape =
TensorShapeProto(dim: [batchDim, inputDim]);
TensorProto inputTensor = TensorProto(
dtype: DataType.DT_INT32,
tensorShape: inputTensorShape,
intVal: _tokenIndices);
// If you train your own model, update the input and output tensor names.
const inputTensorName = 'input_3';
const outputTensorName = 'dense_5';
PredictRequest request = PredictRequest(
modelSpec: modelSpec, inputs: {inputTensorName: inputTensor});
הערה: שמות האמצעים לקלט ולפלט יכולים להיות שונים מהמודל, גם אם ארכיטקטורת המודלים זהה. הקפידו לעדכן אותם אם אתם מאמנים את המודל שלכם.
שליחת בקשת gRPC לשירות TensorFlow
- צריך להוסיף את הקוד הזה אחרי קטע הקוד הקודם כדי לשלוח את בקשת ה-gRPC להצגת יכולות TensorFlow:
// Send the gRPC request.
PredictResponse response = await _stub.predict(request);
מעבד את תגובת ה-gRPC מ-TensorFlow serving
- צריך להוסיף את הקוד הזה אחרי קטע הקוד הקודם כדי להטמיע את הפונקציות של הקריאה החוזרת לטיפול בתגובה:
// Process the response.
if (response.outputs.containsKey(outputTensorName)) {
if (response.outputs[outputTensorName]!.floatVal[1] >
classificationThreshold) {
return 'This sentence is spam. Spam score is ' +
response.outputs[outputTensorName]!.floatVal[1].toString();
} else {
return 'This sentence is not spam. Spam score is ' +
response.outputs[outputTensorName]!.floatVal[1].toString();
}
} else {
throw Exception('Error response');
}
עכשיו הקוד אחרי העיבוד מחלץ את תוצאת הסיווג מהתגובה ומציג אותה בממשק המשתמש.
הפעלה
- לוחצים על
התחלת ניפוי באגים וממתינים לטעינה של האפליקציה.
- מזינים טקסט ובוחרים באפשרות gRPC > Classification.
10. מזל טוב
השתמשת ב-TensorFlow serving כדי להוסיף לאפליקציה יכולות של סיווג טקסט!
באתגר הקוד הבא, תשפרו את המודל כך שתוכלו לזהות הודעות ספאם ספציפיות שהאפליקציה הנוכחית לא יכולה לזהות.