1. Trước khi bắt đầu
Trong lớp học lập trình này, bạn sẽ tìm hiểu cách chạy suy luận phân loại văn bản từ một ứng dụng Flutter bằng TensorFlow Serving thông qua REST và gRPC.
Điều kiện tiên quyết
- Kiến thức cơ bản về cách phát triển Flutter bằng Dart
- Kiến thức cơ bản về học máy bằng TensorFlow, chẳng hạn như huấn luyện so với triển khai
- Kiến thức cơ bản về thiết bị đầu cuối và Docker
- Huấn luyện mô hình phát hiện bình luận rác bằng lớp học lập trình Trình tạo mô hình TensorFlow Lite
Kiến thức bạn sẽ học được
- Cách tạo một ứng dụng Flutter đơn giản và phân loại văn bản thông qua TensorFlow Serving (REST và gRPC).
- Cách hiển thị kết quả trong giao diện người dùng.
Bạn cần có
- SDK Flutter
- Thiết lập Android hoặc iOS cho Flutter
- Thiết lập Visual Studio Code (VS Code) cho Flutter và Dart
- Docker
- Bash
- Trình biên dịch vùng đệm giao thức và trình bổ trợ gRPC Dart cho trình biên dịch giao thức (chỉ cần thiết nếu bạn muốn tự tạo lại phần giữ chỗ gRPC)
2. Thiết lập môi trường phát triển Flutter
Để phát triển Flutter, bạn cần có 2 phần mềm để hoàn thành bài thực hành này: Flutter SDK và một trình chỉnh sửa.
Bạn có thể chạy lớp học lập trình bằng bất kỳ thiết bị nào sau đây:
- Trình mô phỏng iOS (bạn cần cài đặt các công cụ Xcode).
- Trình mô phỏng Android (cần thiết lập trong Android Studio).
- Một trình duyệt (bạn cần có Chrome để gỡ lỗi).
- Là một ứng dụng máy tính cho Windows, Linux hoặc macOS. Bạn phải phát triển trên nền tảng mà bạn dự định triển khai. Vì vậy, nếu muốn phát triển một ứng dụng máy tính Windows, bạn phải phát triển trên Windows để truy cập vào chuỗi bản dựng thích hợp. Có những yêu cầu cụ thể theo hệ điều hành được đề cập chi tiết trên docs.flutter.dev/desktop.
3. Bắt đầu thiết lập
Cách tải mã xuống cho lớp học lập trình này:
- Chuyển đến kho lưu trữ GitHub cho lớp học lập trình này.
- Nhấp vào Code > Download zip (Mã > Tải xuống tệp ZIP) để tải tất cả mã cho lớp học lập trình này xuống.
- Giải nén tệp zip đã tải xuống để giải nén một thư mục gốc
codelabs-main
chứa tất cả tài nguyên bạn cần.
Đối với lớp học lập trình này, bạn chỉ cần các tệp trong thư mục con tfserving-flutter/codelab2
trong kho lưu trữ. Thư mục này chứa 2 thư mục:
- Thư mục
starter
chứa mã khởi đầu mà bạn sẽ dùng để xây dựng trong lớp học lập trình này. - Thư mục
finished
chứa mã hoàn chỉnh cho ứng dụng mẫu đã hoàn thành.
4. Tải các phần phụ thuộc cho dự án xuống
- Trong VS Code, hãy nhấp vào File > Open folder (Tệp > Mở thư mục), sau đó chọn thư mục
starter
trong mã nguồn mà bạn đã tải xuống trước đó. - Nếu bạn thấy một hộp thoại xuất hiện nhắc bạn tải các gói cần thiết cho ứng dụng khởi động, hãy nhấp vào Tải gói.
- Nếu bạn không thấy hộp thoại này, hãy mở thiết bị đầu cuối rồi chạy lệnh
flutter pub get
trong thư mụcstarter
.
5. Chạy ứng dụng khởi đầu
- Trong VS Code, hãy đảm bảo rằng Trình mô phỏng Android hoặc Trình mô phỏng iOS được thiết lập đúng cách và xuất hiện trên thanh trạng thái.
Ví dụ: sau đây là những gì bạn thấy khi sử dụng Pixel 5 với Trình mô phỏng Android:
Sau đây là những gì bạn thấy khi sử dụng iPhone 13 với Trình mô phỏng iOS:
- Nhấp vào
Bắt đầu gỡ lỗi.
Chạy và khám phá ứng dụng
Ứng dụng sẽ chạy trên Trình mô phỏng Android hoặc Trình mô phỏng iOS. Giao diện người dùng khá đơn giản. Có một trường văn bản cho phép người dùng nhập văn bản. Người dùng có thể chọn gửi dữ liệu đến phần phụ trợ bằng REST hoặc gRPC. Phần phụ trợ sử dụng một mô hình TensorFlow để thực hiện việc phân loại văn bản trên dữ liệu đầu vào đã xử lý trước và trả về kết quả phân loại cho ứng dụng khách, từ đó cập nhật giao diện người dùng.
Nếu bạn nhấp vào Phân loại, sẽ không có gì xảy ra vì ứng dụng chưa thể giao tiếp với phần phụ trợ.
6. Triển khai mô hình phân loại văn bản bằng TensorFlow Serving
Phân loại văn bản là một nhiệm vụ rất phổ biến trong học máy, giúp phân loại văn bản thành các danh mục được xác định trước. Trong lớp học lập trình này, bạn sẽ triển khai mô hình được huấn luyện trước từ Lớp học lập trình Huấn luyện mô hình phát hiện bình luận rác bằng TensorFlow Lite Model Maker bằng TensorFlow Serving và gọi phần phụ trợ từ giao diện người dùng Flutter để phân loại văn bản đầu vào là nội dung rác hay không phải nội dung rác.
Bắt đầu TensorFlow Serving
- Trong thiết bị đầu cuối, hãy bắt đầu TensorFlow Serving bằng Docker, nhưng thay thế phần giữ chỗ
PATH/TO/SAVEDMODEL
bằng đường dẫn tuyệt đối của thư mụcmm_spam_savedmodel
trên máy tính.
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
Trước tiên, Docker sẽ tự động tải hình ảnh TensorFlow Serving xuống. Quá trình này mất một phút. Sau đó, TensorFlow Serving sẽ bắt đầu. Nhật ký sẽ có dạng như đoạn mã sau:
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. Phân đoạn câu đầu vào
Phần phụ trợ hiện đã sẵn sàng, vì vậy, bạn gần như đã sẵn sàng gửi yêu cầu của ứng dụng đến TensorFlow Serving, nhưng trước tiên, bạn cần mã hoá câu đầu vào. Nếu kiểm tra tensor đầu vào của mô hình, bạn có thể thấy rằng mô hình này yêu cầu một danh sách gồm 20 số nguyên thay vì các chuỗi thô. Mã hoá là khi bạn liên kết các từ riêng lẻ mà bạn nhập trong ứng dụng với một danh sách các số nguyên dựa trên từ điển từ vựng trước khi bạn gửi chúng đến phần phụ trợ để phân loại. Ví dụ: nếu bạn nhập buy book online to learn more
, quy trình mã hoá sẽ ánh xạ mã này thành [32, 79, 183, 10, 224, 631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
. Các con số cụ thể có thể thay đổi tuỳ theo từ điển từ vựng.
- Trong tệp
lib/main.dart
, hãy thêm mã này vào phương thứcpredict()
để tạo từ điển từ vựng_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]);
}
}
}
- Ngay sau đoạn mã trước, hãy thêm mã này để triển khai quy trình mã hoá:
// 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;
}
}
Đoạn mã này chuyển chuỗi câu thành chữ thường, xoá các ký tự không phải chữ cái và liên kết các từ với 20 chỉ mục số nguyên dựa trên bảng từ vựng.
8. Kết nối ứng dụng Flutter với TensorFlow Serving thông qua REST
Có hai cách để gửi yêu cầu đến TensorFlow Serving:
- REST
- gRPC
Gửi yêu cầu và nhận phản hồi thông qua REST
Có 3 bước đơn giản để gửi yêu cầu và nhận phản hồi thông qua REST:
- Tạo yêu cầu REST.
- Gửi yêu cầu REST đến TensorFlow Serving.
- Trích xuất kết quả dự đoán từ phản hồi REST và hiển thị giao diện người dùng.
Bạn hoàn tất các bước này trong tệp main.dart
.
Tạo và gửi yêu cầu REST đến TensorFlow Serving
- Hiện tại, hàm
predict()
không gửi yêu cầu REST đến TensorFlow Serving. Bạn cần triển khai nhánh REST để tạo yêu cầu REST:
if (_connectionMode == ConnectionModeType.rest) {
// TODO: Create and send the REST request.
}
- Thêm mã này vào nhánh 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],
}),
);
Xử lý phản hồi REST từ TensorFlow Serving
- Thêm mã này ngay sau đoạn mã trước để xử lý phản hồi 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');
}
Đoạn mã xử lý hậu kỳ trích xuất xác suất câu đầu vào là thư rác từ phản hồi và hiển thị kết quả phân loại trong giao diện người dùng.
Chạy ứng dụng
- Nhấp vào
Start debugging (Bắt đầu gỡ lỗi) rồi đợi ứng dụng tải.
- Nhập một đoạn văn bản rồi chọn REST > Phân loại.
9. Kết nối ứng dụng Flutter với TensorFlow Serving thông qua gRPC
Ngoài REST, TensorFlow Serving còn hỗ trợ gRPC.
gRPC là một khung Lệnh gọi thủ tục từ xa (RPC) hiện đại, nguồn mở, hiệu suất cao, có thể chạy trong mọi môi trường. Nền tảng này có thể kết nối hiệu quả các dịch vụ trong và trên các trung tâm dữ liệu với khả năng hỗ trợ có thể cắm cho việc cân bằng tải, theo dõi, kiểm tra tình trạng và xác thực. Theo quan sát, gRPC hoạt động hiệu quả hơn REST trong thực tế.
Gửi yêu cầu và nhận phản hồi bằng gRPC
Có 4 bước đơn giản để gửi yêu cầu và nhận phản hồi bằng gRPC:
- Không bắt buộc: Tạo mã giả lập ứng dụng gRPC.
- Tạo yêu cầu gRPC.
- Gửi yêu cầu gRPC đến TensorFlow Serving.
- Trích xuất kết quả dự đoán từ phản hồi gRPC và hiển thị giao diện người dùng.
Bạn hoàn tất các bước này trong tệp main.dart
.
Không bắt buộc: Tạo mã giả lập ứng dụng gRPC
Để sử dụng gRPC với TensorFlow Serving, bạn cần làm theo quy trình gRPC. Để tìm hiểu thêm về thông tin chi tiết, hãy xem tài liệu về gRPC.
TensorFlow Serving và TensorFlow xác định các tệp .proto
cho bạn. Kể từ TensorFlow và TensorFlow Serving 2.8, đây là những tệp .proto
cần thiết:
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
- Trong thiết bị đầu cuối, hãy chuyển đến thư mục
starter/lib/proto/
rồi tạo phần giữ chỗ:
bash generate_grpc_stub_dart.sh
Tạo yêu cầu gRPC
Tương tự như yêu cầu REST, bạn tạo yêu cầu gRPC trong nhánh gRPC.
if (_connectionMode == ConnectionModeType.rest) {
} else {
// TODO: Create and send the gRPC request.
}
- Thêm mã này để tạo yêu cầu 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});
Lưu ý: Tên tensor đầu vào và đầu ra có thể khác nhau giữa các mô hình, ngay cả khi cấu trúc mô hình giống nhau. Hãy nhớ cập nhật các tham số này nếu bạn huấn luyện mô hình của riêng mình.
Gửi yêu cầu gRPC đến TensorFlow Serving
- Thêm mã này sau đoạn mã trước để gửi yêu cầu gRPC đến TensorFlow Serving:
// Send the gRPC request.
PredictResponse response = await _stub.predict(request);
Xử lý phản hồi gRPC từ TensorFlow Serving
- Thêm đoạn mã này sau đoạn mã trước để triển khai các hàm gọi lại nhằm xử lý phản hồi:
// 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');
}
Giờ đây, mã xử lý hậu kỳ sẽ trích xuất kết quả phân loại từ phản hồi và hiển thị kết quả đó trong giao diện người dùng.
Chạy ứng dụng
- Nhấp vào
Start debugging (Bắt đầu gỡ lỗi) rồi đợi ứng dụng tải.
- Nhập một số văn bản rồi chọn gRPC > Classify (gRPC > Phân loại).
10. Xin chúc mừng
Bạn đã sử dụng TensorFlow Serving để thêm các chức năng phân loại văn bản vào ứng dụng của mình!
Trong lớp học lập trình tiếp theo, bạn sẽ cải tiến mô hình để có thể phát hiện những tin nhắn rác cụ thể mà ứng dụng hiện tại không phát hiện được.