Thêm siêu dữ liệu vào các mô hình LiteRT

Siêu dữ liệu LiteRT cung cấp một tiêu chuẩn cho nội dung mô tả mô hình. Chiến lược phát hành đĩa đơn siêu dữ liệu là một nguồn kiến thức quan trọng về chức năng của mô hình và thông tin đầu vào / đầu ra. Siêu dữ liệu bao gồm cả hai

Tất cả mẫu hình ảnh được xuất bản trên Kaggle Hệ thống đã điền sẵn mô hình siêu dữ liệu.

Mô hình có định dạng siêu dữ liệu

model_with_metadata
Hình 1. Mô hình TFLite với siêu dữ liệu và tệp liên kết.

Siêu dữ liệu của mô hình được xác định trong metadata_schema.fbs, một FlatBuffer . Như được minh hoạ trong Hình 1, dữ liệu này được lưu trữ trong siêu dữ liệu trường của mô hình TFLite giản đồ, dưới tên, "TFLITE_METADATA". Một số mô hình có thể có tệp liên kết, chẳng hạn như nhãn phân loại tệp. Các tệp này được nối vào cuối tệp mô hình ban đầu dưới dạng tệp ZIP bằng cách sử dụng "nối" của ZipFile chế độ (chế độ 'a'). TFLite Chế độ phiên dịch có thể sử dụng định dạng tệp mới này theo cách tương tự như trước đây. Xem Gói các tệp liên quan để biết thêm thông tin.

Hãy xem hướng dẫn dưới đây về cách điền sẵn, trực quan hoá và đọc siêu dữ liệu.

Thiết lập công cụ siêu dữ liệu

Trước khi thêm siêu dữ liệu vào mô hình, bạn cần lập trình Python thiết lập môi trường để chạy TensorFlow. Có hướng dẫn chi tiết về cách hãy thiết lập điều này tại đây.

Sau khi thiết lập môi trường lập trình Python, bạn sẽ cần cài đặt công cụ bổ sung:

pip install tflite-support

Công cụ siêu dữ liệu LiteRT hỗ trợ Python 3.

Thêm siêu dữ liệu bằng API Flatbuffers Python

Có ba phần siêu dữ liệu của mô hình trong giản đồ:

  1. Thông tin về mẫu thiết bị – Mô tả tổng thể về mô hình cũng như các mặt hàng chẳng hạn như các điều khoản cấp phép. Xem ModelMetadata.
    1. Thông tin đầu vào – Nội dung mô tả về dữ liệu đầu vào và quá trình xử lý trước chẳng hạn như chuẩn hoá. Xem SubGraphMetadata.input_tensor_metadata.
      1. Thông tin đầu ra – Nội dung mô tả về đầu ra và hậu xử lý bắt buộc, chẳng hạn như ánh xạ đến nhãn. Xem SubGraphMetadata.output_tensor_metadata.

Vì LiteRT chỉ hỗ trợ một đồ thị con tại thời điểm này, nên phương thức Trình tạo mã LiteRTLiên kết máy học Android Studio tính năng sẽ sử dụng ModelMetadata.nameModelMetadata.description, thay vì SubGraphMetadata.nameSubGraphMetadata.description, khi hiển thị siêu dữ liệu và tạo mã.

Các loại đầu vào / đầu ra được hỗ trợ

Siêu dữ liệu LiteRT cho đầu vào và đầu ra không được thiết kế với loại mô hình đầu vào và đầu ra. Không quan trọng mô hình hoạt động về chức năng, miễn là loại đầu vào và đầu ra bao gồm ký tự sau hoặc kết hợp các thuộc tính sau đây, nó được TensorFlow hỗ trợ Siêu dữ liệu phiên bản rút gọn:

  • Tính năng – Số là số nguyên không dấu hoặc float32.
  • Hình ảnh – Siêu dữ liệu hiện hỗ trợ hình ảnh RGB và thang màu xám.
  • Hộp giới hạn – Hộp giới hạn hình chữ nhật. Giản đồ này hỗ trợ a nhiều cách đánh số .

Đóng gói các tệp liên quan

Các mô hình LiteRT có thể đi kèm với nhiều tệp liên kết. Ví dụ: mô hình ngôn ngữ tự nhiên thường có tệp từ vựng liên kết các phần từ với từ Giấy tờ tuỳ thân; mô hình phân loại có thể có tệp nhãn cho biết các danh mục đối tượng. Nếu không có các tệp liên kết (nếu có), mô hình sẽ không hoạt động tốt.

Giờ đây, bạn có thể nhóm các tệp đã liên kết cùng với mô hình thông qua siêu dữ liệu Thư viện Python. Mô hình LiteRT mới sẽ trở thành tệp zip chứa cả mô hình và các tệp được liên kết. Tệp này có thể được giải nén bằng mã zip thông thường và các công cụ lập mô hình tuỳ chỉnh. Định dạng tệp mới này tiếp tục sử dụng cùng một đuôi tệp là .tflite. Nó tương thích với khung TFLite và Trình thông dịch hiện có. Xem phần Siêu dữ liệu của gói và tệp được liên kết vào mô hình để biết thêm chi tiết.

Thông tin về tệp liên kết có thể được ghi lại trong siêu dữ liệu. Tuỳ thuộc vào loại tệp và nơi tệp được đính kèm (ví dụ: ModelMetadata, SubGraphMetadataTensorMetadata), mã LiteRT Android công cụ tạo có thể áp dụng trước/sau tương ứng tự động xử lý cho đối tượng. Hãy xem phần <Codegen Usage> phần của từng tệp liên kết loại thiết bị trong giản đồ để biết thêm chi tiết.

Tham số chuẩn hoá và lượng tử hoá

Chuẩn hoá là một kỹ thuật tiền xử lý dữ liệu phổ biến trong công nghệ học máy. Chiến lược phát hành đĩa đơn mục tiêu của quá trình chuẩn hoá là thay đổi các giá trị về một thang đo chung mà không làm biến dạng sự khác biệt trong phạm vi giá trị.

Lượng tử hoá mô hình là một kỹ thuật cho phép giảm độ chính xác của trọng số và không bắt buộc cho cả việc lưu trữ và tính toán.

Về mặt tiền xử lý và hậu xử lý, chuẩn hoá và lượng tử hoá là hai bước độc lập. Dưới đây là các chi tiết.

Chuẩn hoá Lượng tử hoá

Ví dụ về các giá trị thông số của thuộc tính nhập hình ảnh vào MobileNet cho độ chính xác đơn và mô hình lượng tử, tương ứng.
Mô hình số thực:
- trung bình: 127,5
- tiêu chuẩn: 127,5
Mô hình lượng:
- trung bình: 127,5
- std: 127,5
Mô hình số thực:
- zeroPoint: 0
- tỷ lệ: 1,0
Mô hình lượng:
– zeroPoint: 128,0
- tỷ lệ:0.0078125f




Khi nào nên gọi?


Đầu vào: Nếu đầu vào được chuẩn hoá theo huấn luyện, đầu vào dữ liệu của nhu cầu suy luận để được chuẩn hoá cho phù hợp.
Kết quả: đầu ra sẽ không được được chuẩn hoá nói chung.
Mô hình nổi có thể không cần lượng tử hoá.
Mô hình lượng tử có thể hoặc có thể không cần lượng tử hoá trong giai đoạn trước và sau khi triển khai đang xử lý. Tuỳ trường hợp dựa trên loại dữ liệu của tensor đầu vào/đầu ra.
– tensor số thực: không lượng tử hoá trong giai đoạn trước và sau khi triển khai cần xử lý. Quant hoạt động vận hành và gián tiếp đưa vào mô hình biểu đồ.
- tensor int8/uint8: cần định lượng trong xử lý trước/sau.


Công thức


đầu_ vào_chuẩn = (đầu vào – trung bình) / std
Định lượng dữ liệu đầu vào:
q = f / tỷ lệ + zeroPoint
Loại bỏ lượng tử trong kết quả:
f = (q - zeroPoint) * quy mô

Vị trí tham số
Điền bởi người tạo mô hình và được lưu trữ trong mô hình siêu dữ liệu, như NormalizationOptions Được tự động điền bởi Công cụ chuyển đổi TFLite và được lưu trữ trong mô hình tflite .
Cách tải tham số không? Thông qua API MetadataExtractor [2] Thông qua TFLite Tensor API [1] hoặc thông qua API MetadataExtractor [2]
Độ chính xác đơn và số tử các mô hình có cùng giá trị? Có, số thực và số lượng các mô hình có cùng Chuẩn hoá tham số Không, mô hình số thực không cần lượng tử hoá.
Có mã TFLite trình tạo hoặc Android Liên kết công nghệ học máy trong Studio tự động tạo trong quá trình xử lý dữ liệu?

[1] LiteRT Java APILiteRT C++ .
[2] Thư viện trình trích xuất siêu dữ liệu

Khi xử lý dữ liệu hình ảnh cho mô hình uint8, việc chuẩn hoá và lượng tử hoá đôi khi bị bỏ qua. Bạn có thể làm như vậy khi giá trị pixel nằm trong khoảng [0, 255]. Nhưng nhìn chung, bạn nên luôn xử lý dữ liệu theo các tham số chuẩn hoá và lượng tử hoá khi có thể.

Ví dụ

Bạn có thể xem các ví dụ về cách điền siêu dữ liệu cho các các loại mô hình ở đây:

Phân loại hình ảnh

Tải tập lệnh xuống tại đây , giúp điền siêu dữ liệu để mobilenet_v1_0.75_160_quantized.tflite. Chạy tập lệnh như sau:

python ./metadata_writer_for_image_classifier.py \
    --model_file=./model_without_metadata/mobilenet_v1_0.75_160_quantized.tflite \
    --label_file=./model_without_metadata/labels.txt \
    --export_directory=model_with_metadata

Để điền siêu dữ liệu cho các mô hình phân loại hình ảnh khác, hãy thêm thông số kỹ thuật của mô hình lượt thích thế này vào tập lệnh. Phần còn lại của hướng dẫn này sẽ nêu bật một số phần chính trong ví dụ phân loại hình ảnh để minh hoạ các yếu tố chính.

Tìm hiểu sâu ví dụ về cách phân loại hình ảnh

Thông tin mẫu

Siêu dữ liệu bắt đầu bằng cách tạo một thông tin mô hình mới:

from tflite_support import flatbuffers
from tflite_support import metadata as _metadata
from tflite_support import metadata_schema_py_generated as _metadata_fb

""" ... """
"""Creates the metadata for an image classifier."""

# Creates model info.
model_meta = _metadata_fb.ModelMetadataT()
model_meta.name = "MobileNetV1 image classifier"
model_meta.description = ("Identify the most prominent object in the "
                          "image from a set of 1,001 categories such as "
                          "trees, animals, food, vehicles, person etc.")
model_meta.version = "v1"
model_meta.author = "TensorFlow"
model_meta.license = ("Apache License. Version 2.0 "
                      "http://www.apache.org/licenses/LICENSE-2.0.")

Thông tin đầu vào / đầu ra

Phần này cho bạn biết cách mô tả chữ ký đầu vào và đầu ra của mô hình. Trình tạo mã tự động có thể sử dụng siêu dữ liệu này để tạo mã xử lý. Cách tạo thông tin đầu vào hoặc đầu ra về một tensor:

# Creates input info.
input_meta = _metadata_fb.TensorMetadataT()

# Creates output info.
output_meta = _metadata_fb.TensorMetadataT()

Nhập hình ảnh

Hình ảnh là một loại dữ liệu đầu vào phổ biến cho công nghệ học máy. Siêu dữ liệu LiteRT hỗ trợ các thông tin như hệ màu và thông tin xử lý trước như chuẩn hoá dữ liệu. Kích thước của hình ảnh không yêu cầu thông số kỹ thuật thủ công vì nó đã được cung cấp bởi hình dạng của tensor đầu vào và có thể được được tự động suy luận.

input_meta.name = "image"
input_meta.description = (
    "Input image to be classified. The expected image is {0} x {1}, with "
    "three channels (red, blue, and green) per pixel. Each value in the "
    "tensor is a single byte between 0 and 255.".format(160, 160))
input_meta.content = _metadata_fb.ContentT()
input_meta.content.contentProperties = _metadata_fb.ImagePropertiesT()
input_meta.content.contentProperties.colorSpace = (
    _metadata_fb.ColorSpaceType.RGB)
input_meta.content.contentPropertiesType = (
    _metadata_fb.ContentProperties.ImageProperties)
input_normalization = _metadata_fb.ProcessUnitT()
input_normalization.optionsType = (
    _metadata_fb.ProcessUnitOptions.NormalizationOptions)
input_normalization.options = _metadata_fb.NormalizationOptionsT()
input_normalization.options.mean = [127.5]
input_normalization.options.std = [127.5]
input_meta.processUnits = [input_normalization]
input_stats = _metadata_fb.StatsT()
input_stats.max = [255]
input_stats.min = [0]
input_meta.stats = input_stats

Đầu ra của nhãn

Có thể ánh xạ nhãn tới một tensor đầu ra thông qua một tệp liên kết bằng cách sử dụng TENSOR_AXIS_LABELS.

# Creates output info.
output_meta = _metadata_fb.TensorMetadataT()
output_meta.name = "probability"
output_meta.description = "Probabilities of the 1001 labels respectively."
output_meta.content = _metadata_fb.ContentT()
output_meta.content.content_properties = _metadata_fb.FeaturePropertiesT()
output_meta.content.contentPropertiesType = (
    _metadata_fb.ContentProperties.FeatureProperties)
output_stats = _metadata_fb.StatsT()
output_stats.max = [1.0]
output_stats.min = [0.0]
output_meta.stats = output_stats
label_file = _metadata_fb.AssociatedFileT()
label_file.name = os.path.basename("your_path_to_label_file")
label_file.description = "Labels for objects that the model can recognize."
label_file.type = _metadata_fb.AssociatedFileType.TENSOR_AXIS_LABELS
output_meta.associatedFiles = [label_file]

Tạo Vùng đệm phẳng siêu dữ liệu

Đoạn mã sau đây kết hợp thông tin về mô hình với dữ liệu đầu vào và đầu ra của bạn:

# Creates subgraph info.
subgraph = _metadata_fb.SubGraphMetadataT()
subgraph.inputTensorMetadata = [input_meta]
subgraph.outputTensorMetadata = [output_meta]
model_meta.subgraphMetadata = [subgraph]

b = flatbuffers.Builder(0)
b.Finish(
    model_meta.Pack(b),
    _metadata.MetadataPopulator.METADATA_FILE_IDENTIFIER)
metadata_buf = b.Output()

Đóng gói siêu dữ liệu và các tệp liên kết vào mô hình

Sau khi siêu dữ liệu Flatbuffers được tạo, siêu dữ liệu và tệp nhãn sẽ được ghi vào tệp TFLite thông qua phương thức populate:

populator = _metadata.MetadataPopulator.with_model_file(model_file)
populator.load_metadata_buffer(metadata_buf)
populator.load_associated_files(["your_path_to_label_file"])
populator.populate()

Bạn có thể đóng gói bao nhiêu tệp liên kết tuỳ thích vào mô hình thông qua load_associated_files. Tuy nhiên, bạn cần phải đóng gói ít nhất các tệp đó được ghi lại trong siêu dữ liệu. Trong ví dụ này, việc đóng gói tệp nhãn sẽ bắt buộc.

Trực quan hoá siêu dữ liệu

Bạn có thể sử dụng Netron để trực quan hoá siêu dữ liệu hoặc bạn có thể đọc siêu dữ liệu từ mô hình LiteRT thành tệp json bằng cách sử dụng MetadataDisplayer:

displayer = _metadata.MetadataDisplayer.with_model_file(export_model_path)
export_json_file = os.path.join(FLAGS.export_directory,
                                os.path.splitext(model_basename)[0] + ".json")
json_file = displayer.get_metadata_json()
# Optional: write out the metadata as a json file
with open(export_json_file, "w") as f:
  f.write(json_file)

Android Studio cũng hỗ trợ hiển thị siêu dữ liệu thông qua Học máy Android Studio Ràng buộc .

Tạo phiên bản siêu dữ liệu

Siêu dữ liệu giản đồ được tạo phiên bản theo cả số phiên bản ngữ nghĩa, giúp theo dõi các thay đổi của tệp giản đồ và bằng cách nhận dạng tệp Flatbuffers, mã này cho biết khả năng tương thích thực sự với phiên bản.

Số phiên bản ngữ nghĩa

Giản đồ siêu dữ liệu được tạo phiên bản theo Phiên bản ngữ nghĩa số, chẳng hạn như MAJOR.MINOR.PATCH. Theo dõi các thay đổi của giản đồ theo quy tắc tại đây. Xem lịch sử của trường được thêm sau phiên bản 1.0.0.

Nhận dạng tệp Flatbuffers

Việc tạo phiên bản ngữ nghĩa đảm bảo tính tương thích nếu bạn tuân thủ các quy tắc, nhưng không ngụ ý sự không tương thích thực sự. Khi tăng số MAJOR, không nhất thiết có nghĩa là khả năng tương thích ngược bị hỏng. Do đó, chúng tôi hãy dùng tệp Flatbuffers nhận dạng, file_identifier, để biểu thị khả năng tương thích thực sự của giản đồ siêu dữ liệu. Giá trị nhận dạng tệp là dài chính xác 4 ký tự. Nó được cố định theo một giản đồ siêu dữ liệu nhất định và không có thể thay đổi bởi người dùng. Nếu giản đồ siêu dữ liệu có khả năng tương thích ngược bị hỏng vì lý do nào đó, file_identifier sẽ tăng lên, ví dụ: từ "M001" đến "M002". File_identifier có thể sẽ ít thay đổi hơn thường xuyên hơn phiên bản siêu dữ liệu.

Phiên bản tối thiểu cần thiết của trình phân tích cú pháp siêu dữ liệu

Trình phân tích cú pháp siêu dữ liệu cần thiết tối thiểu phiên bản là phiên bản tối thiểu của trình phân tích cú pháp siêu dữ liệu (mã được tạo bằng Flatbuffers) có thể đọc toàn bộ siêu dữ liệu Flatbuffers. Phiên bản này là số phiên bản lớn nhất trong số các phiên bản của tất cả các trường được điền sẵn và phiên bản tương thích nhỏ nhất được biểu thị bằng mã nhận dạng tệp. Giá trị tối thiểu phiên bản trình phân tích cú pháp siêu dữ liệu cần thiết được điền tự động bằng MetadataPopulator khi siêu dữ liệu được điền vào mô hình TFLite. Xem công cụ trích xuất siêu dữ liệu để biết thêm thông tin về cách bạn cần sử dụng phiên bản tối thiểu cần thiết của trình phân tích cú pháp siêu dữ liệu.

Đọc siêu dữ liệu của mô hình

Thư viện Trình trích xuất siêu dữ liệu là một công cụ thuận tiện để đọc siêu dữ liệu và tệp được liên kết từ mô hình trên các nền tảng khác nhau (xem Hướng dẫn phiên bảnC++ phiên bản). Bạn có thể xây dựng công cụ trích xuất siêu dữ liệu của riêng mình bằng các ngôn ngữ khác bằng cách sử dụng Thư viện Flatbuffers.

Đọc siêu dữ liệu trong Java

Để sử dụng thư viện Trình trích xuất siêu dữ liệu trong ứng dụng Android, bạn nên sử dụng AAR siêu dữ liệu LiteRT được lưu trữ tại MavenCentral. Tệp này chứa lớp MetadataExtractor, cũng như Java FlatBuffers các liên kết cho siêu dữ liệu giản đồmô hình giản đồ.

Bạn có thể chỉ định mã này trong các phần phụ thuộc build.gradle như sau:

dependencies {
    implementation 'org.tensorflow:tensorflow-lite-metadata:0.1.0'
}

Để sử dụng ảnh chụp nhanh hàng đêm, hãy đảm bảo bạn đã thêm ảnh chụp nhanh Sonatype kho lưu trữ.

Bạn có thể khởi tạo đối tượng MetadataExtractor bằng ByteBuffer trỏ đến cho mô hình:

public MetadataExtractor(ByteBuffer buffer);

ByteBuffer không được thay đổi trong toàn bộ thời gian hoạt động của Đối tượng MetadataExtractor. Quá trình khởi chạy có thể không thành công nếu tệp Flatbuffers giá trị nhận dạng của siêu dữ liệu mô hình không khớp với giá trị nhận dạng của trình phân tích cú pháp siêu dữ liệu. Xem tạo phiên bản siêu dữ liệu để biết thêm thông tin.

Khi có giá trị nhận dạng tệp trùng khớp, trình trích xuất siêu dữ liệu sẽ đọc thành công siêu dữ liệu được tạo từ tất cả giản đồ trước đây và trong tương lai do Flatbuffers tương thích tiến và tương thích ngược. Tuy nhiên, các trường trong tương lai các công cụ trích xuất siêu dữ liệu cũ không thể trích xuất giản đồ. Số tiền tối thiểu cần thiết phiên bản trình phân tích cú pháp của siêu dữ liệu cho biết phiên bản tối thiểu của trình phân tích cú pháp siêu dữ liệu có thể đọc siêu dữ liệu Hết vùng đệm phẳng. Bạn có thể sử dụng phương pháp sau đây để xác minh xem giá trị Điều kiện phiên bản trình phân tích cú pháp cần thiết được đáp ứng:

public final boolean isMinimumParserVersionSatisfied();

Bạn có thể truyền dữ liệu vào mô hình không có siêu dữ liệu. Tuy nhiên, việc gọi các phương thức đọc từ siêu dữ liệu sẽ gây ra lỗi thời gian chạy. Bạn có thể kiểm tra xem một mô hình siêu dữ liệu bằng cách gọi phương thức hasMetadata:

public boolean hasMetadata();

MetadataExtractor cung cấp các hàm thuận tiện để bạn có thể lấy tensor đầu vào/đầu ra siêu dữ liệu. Ví dụ:

public int getInputTensorCount();
public TensorMetadata getInputTensorMetadata(int inputIndex);
public QuantizationParams getInputTensorQuantizationParams(int inputIndex);
public int[] getInputTensorShape(int inputIndex);
public int getoutputTensorCount();
public TensorMetadata getoutputTensorMetadata(int inputIndex);
public QuantizationParams getoutputTensorQuantizationParams(int inputIndex);
public int[] getoutputTensorShape(int inputIndex);

Mặc dù mô hình LiteRT giản đồ hỗ trợ nhiều đồ thị con, nên Trình thông dịch TFLite hiện chỉ hỗ trợ đồ thị con đơn. Do đó, MetadataExtractor bỏ qua chỉ mục đồ thị con làm dữ liệu đầu vào đối số trong phương thức của nó.

Đọc các tệp được liên kết từ mô hình

Mô hình LiteRT với siêu dữ liệu và các tệp được liên kết về cơ bản là tệp zip có thể được giải nén bằng các công cụ zip phổ biến để lấy các tệp liên quan. Ví dụ: bạn có thể giải nén mobilenet_v1_0.75_160_quantized và trích xuất tệp nhãn trong mô hình như sau:

$ unzip mobilenet_v1_0.75_160_quantized_1_metadata_1.tflite
Archive:  mobilenet_v1_0.75_160_quantized_1_metadata_1.tflite
 extracting: labels.txt

Bạn cũng có thể đọc các tệp liên quan thông qua thư viện Trình trích xuất siêu dữ liệu.

Trong Java, hãy chuyển tên tệp vào MetadataExtractor.getAssociatedFile phương thức:

public InputStream getAssociatedFile(String fileName);

Tương tự, trong C++, bạn có thể thực hiện việc này bằng phương thức, ModelMetadataExtractor::GetAssociatedFile:

tflite::support::StatusOr<absl::string_view> GetAssociatedFile(
      const std::string& filename) const;