TensorFlow Lite 모델에 메타데이터 추가

TensorFlow Lite 메타데이터는 모델 설명에 대한 표준을 제공합니다. 메타데이터는 모델이 하는 일과 해당 입력/출력 정보에 대한 중요한 지식 소스입니다. 메타데이터는 두 가지 모두로 구성됩니다.

TensorFlow Hub 에 게시된 모든 이미지 모델은 메타데이터로 채워졌습니다.

메타데이터 형식의 모델

model_with_metadata
그림 1. 메타데이터 및 관련 파일이 있는 TFLite 모델.

모델 메타데이터는 FlatBuffer 파일인 metadata_schema.fbs 에 정의되어 있습니다. 그림 1과 같이 TFLite 모델 스키마메타데이터 필드에 "TFLITE_METADATA" 라는 이름으로 저장됩니다. 일부 모델은 분류 레이블 파일 과 같은 관련 파일과 함께 제공될 수 있습니다. 이러한 파일은 ZipFile "추가" 모드 ( 'a' 모드)를 사용하여 ZIP으로 원본 모델 파일의 끝에 연결됩니다. TFLite Interpreter는 이전과 같은 방식으로 새 파일 형식을 사용할 수 있습니다. 자세한 내용 은 관련 파일 압축 을 참조하십시오.

메타데이터를 채우고 시각화하고 읽는 방법은 아래 지침을 참조하세요.

메타데이터 도구 설정

모델에 메타데이터를 추가하기 전에 TensorFlow를 실행하기 위한 Python 프로그래밍 환경 설정이 필요합니다. 여기 에 설정 방법 에 대한 자세한 가이드 가 있습니다 .

Python 프로그래밍 환경을 설정한 후 추가 도구를 설치해야 합니다.

pip install tflite-support

TensorFlow Lite 메타데이터 도구는 Python 3을 지원합니다.

Flatbuffers Python API를 사용하여 메타데이터 추가

스키마 의 모델 메타데이터에는 세 부분이 있습니다.

  1. 모델 정보 - 모델에 대한 전반적인 설명과 라이선스 조건과 같은 항목입니다. ModelMetadata 를 참조하십시오.
  2. 입력 정보 - 정규화와 같이 필요한 입력 및 전처리에 대한 설명입니다. SubGraphMetadata.input_tensor_metadata 를 참조하십시오.
  3. 출력 정보 - 레이블에 대한 매핑과 같이 필요한 출력 및 후처리에 대한 설명입니다. SubGraphMetadata.output_tensor_metadata 를 참조하십시오.

TensorFlow Lite는 이 시점에서 단일 하위 그래프만 지원하므로 TensorFlow Lite 코드 생성기Android Studio ML 바인딩 기능 은 메타데이터를 표시하고 코드를 생성할 때 ModelMetadata.nameModelMetadata.description 대신 SubGraphMetadata.nameSubGraphMetadata.description 을 사용합니다.

지원되는 입력/출력 유형

입력 및 출력을 위한 TensorFlow Lite 메타데이터는 특정 모델 유형을 염두에 둔 것이 아니라 입력 및 출력 유형을 염두에 두고 설계되었습니다. 입력 및 출력 유형이 다음 또는 다음 조합으로 구성되는 한 모델이 기능적으로 수행하는 작업은 중요하지 않습니다. TensorFlow Lite 메타데이터에서 지원됩니다.

  • 기능 - 부호 없는 정수 또는 float32인 숫자입니다.
  • 이미지 - 메타데이터는 현재 RGB 및 회색조 이미지를 지원합니다.
  • 경계 상자 - 직사각형 모양의 경계 상자입니다. 스키마는 다양한 번호 매기기 체계를 지원합니다.

관련 파일 압축

TensorFlow Lite 모델은 다른 관련 파일과 함께 제공될 수 있습니다. 예를 들어, 자연어 모델에는 일반적으로 단어 조각을 단어 ID에 매핑하는 어휘 파일이 있습니다. 분류 모델에는 개체 범주를 나타내는 레이블 파일이 있을 수 있습니다. 연결된 파일(있는 경우)이 없으면 모델이 제대로 작동하지 않습니다.

관련 파일은 이제 메타데이터 Python 라이브러리를 통해 모델과 함께 번들로 제공될 수 있습니다. 새로운 TensorFlow Lite 모델은 모델과 관련 파일을 모두 포함하는 zip 파일이 됩니다. 일반적인 zip 도구로 압축을 풀 수 있습니다. 이 새로운 모델 형식은 동일한 파일 확장자 .tflite 를 계속 사용합니다. 기존 TFLite 프레임워크 및 인터프리터와 호환됩니다. 자세한 내용 은 모델에 메타데이터 및 관련 파일 압축을 참조하세요.

관련 파일 정보는 메타데이터에 기록될 수 있습니다. 파일 유형 및 파일이 첨부된 위치(예: ModelMetadata , SubGraphMetadataTensorMetadata )에 따라 TensorFlow Lite Android 코드 생성기 는 해당 사전/사후 처리를 객체에 자동으로 적용할 수 있습니다. 자세한 내용은 스키마에서 각 연관 파일 유형의 <Codegen 사용법> 섹션 을 참조하십시오.

정규화 및 양자화 매개변수

정규화는 기계 학습에서 일반적인 데이터 전처리 기술입니다. 정규화의 목표는 값 범위의 차이를 왜곡하지 않고 값을 공통 척도로 변경하는 것입니다.

모델 양자화 는 가중치의 감소된 정밀도 표현과 선택적으로 저장 및 계산 모두에 대한 활성화를 허용하는 기술입니다.

전처리 및 후처리 측면에서 정규화와 양자화는 두 개의 독립적인 단계입니다. 자세한 내용은 다음과 같습니다.

표준화 양자화

float 및 quant 모델 각각에 대한 MobileNet의 입력 이미지 매개변수 값의 예입니다.
플로트 모델 :
- 평균: 127.5
- 표준: 127.5
퀀트 모델 :
- 평균: 127.5
- 표준: 127.5
플로트 모델 :
- 영점: 0
- 규모: 1.0
퀀트 모델 :
- 영점: 128.0
- 스케일: 0.0078125f




언제 호출합니까?


입력 : 훈련에서 입력 데이터가 정규화되면 추론의 입력 데이터는 그에 따라 정규화되어야 합니다.
출력 : 출력 데이터는 일반적으로 정규화되지 않습니다.
Float 모델 은 양자화가 필요하지 않습니다.
양자화된 모델 은 전/후 처리에서 양자화가 필요할 수도 있고 필요하지 않을 수도 있습니다. 입력/출력 텐서의 데이터 유형에 따라 다릅니다.
- float 텐서: 전/후 처리에서 양자화가 필요하지 않습니다. Quant op 및 dequant op는 모델 그래프에 구워집니다.
- int8/uint8 텐서: 전/후 처리에서 양자화가 필요합니다.


공식


normalized_input = (입력 - 평균) / 표준
입력을 위한 양자화 :
q = f / 스케일 + 영점
출력을 위한 역양자화 :
f = (q - 영점) * 스케일

매개변수는 어디에 있습니까
모델 작성자가 NormalizationOptions 로 모델 메타데이터에 저장 TFLite 변환기에 의해 자동으로 채워지고 tflite 모델 파일에 저장됩니다.
매개변수를 얻는 방법? MetadataExtractor API를 통해 [2] TFLite Tensor API[1] 또는 MetadataExtractor API[2]를 통해
float 및 quant 모델은 동일한 값을 공유합니까? 예, float 및 quant 모델에는 동일한 정규화 매개변수가 있습니다. 아니요, float 모델은 양자화가 필요하지 않습니다.
TFLite 코드 생성기 또는 Android Studio ML 바인딩은 데이터 처리에서 자동으로 생성합니까?

[1] TensorFlow Lite Java APITensorFlow Lite C++ API .
[2] 메타데이터 추출기 라이브러리

uint8 모델의 이미지 데이터를 처리할 때 정규화 및 양자화를 건너뛰는 경우가 있습니다. 픽셀 값이 [0, 255] 범위에 있을 때 그렇게 하는 것이 좋습니다. 그러나 일반적으로 적용 가능한 경우 항상 정규화 및 양자화 매개변수에 따라 데이터를 처리해야 합니다.

TensorFlow Lite 작업 라이브러리 는 메타데이터에서 NormalizationOptions 를 설정한 경우 정규화를 처리할 수 있습니다. 양자화 및 역양자화 처리는 항상 캡슐화됩니다.

여기에서 다양한 유형의 모델에 대해 메타데이터를 채우는 방법에 대한 예를 찾을 수 있습니다.

이미지 분류

mobilenet_v1_0.75_160_quantized.tflite 에 메타데이터를 채우는 스크립트 를 여기 에서 다운로드하십시오. 다음과 같이 스크립트를 실행합니다.

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

다른 이미지 분류 모델에 대한 메타데이터를 채우려면 이와 같은 모델 사양을 스크립트에 추가합니다. 이 가이드의 나머지 부분에서는 핵심 요소를 설명하기 위해 이미지 분류 예제의 주요 섹션 중 일부를 강조 표시합니다.

이미지 분류 예제 자세히 알아보기

모델 정보

메타데이터는 새 모델 정보를 생성하여 시작합니다.

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.")

입/출력 정보

이 섹션에서는 모델의 입력 및 출력 서명을 설명하는 방법을 보여줍니다. 이 메타데이터는 자동 코드 생성기가 사전 및 사후 처리 코드를 생성하는 데 사용할 수 있습니다. 텐서에 대한 입력 또는 출력 정보를 생성하려면:

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

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

이미지 입력

이미지는 기계 학습을 위한 일반적인 입력 유형입니다. TensorFlow Lite 메타데이터는 색상 공간과 같은 정보 및 정규화와 같은 전처리 정보를 지원합니다. 이미지의 차원은 이미 입력 텐서의 모양에 의해 제공되고 자동으로 유추될 수 있으므로 수동 지정이 필요하지 않습니다.

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

라벨 출력

레이블은 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]

메타데이터 플랫 버퍼 생성

다음 코드는 모델 정보를 입력 및 출력 정보와 결합합니다.

# 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()

메타데이터 및 관련 파일을 모델로 압축

메타데이터 Flatbuffers가 생성되면 메타데이터와 레이블 파일이 populate 메서드를 통해 TFLite 파일에 기록됩니다.

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()

load_associated_files 를 통해 모델에 관련 파일을 원하는 만큼 압축할 수 있습니다. 그러나 최소한 메타데이터에 문서화된 파일을 압축해야 합니다. 이 예에서 레이블 파일을 패킹하는 것은 필수입니다.

메타데이터 시각화

Netron 을 사용하여 메타데이터를 시각화하거나 MetadataDisplayer 를 사용하여 TensorFlow Lite 모델의 메타데이터를 json 형식으로 읽을 수 있습니다.

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는 또한 Android Studio ML 바인딩 기능 을 통해 메타데이터 표시를 지원합니다.

메타데이터 버전 관리

메타데이터 스키마 는 스키마 파일의 변경 사항을 추적하는 시맨틱 버전 번호와 실제 버전 호환성을 나타내는 플랫 버퍼 파일 ID로 버전이 지정됩니다.

시맨틱 버전 번호

메타데이터 스키마는 MAJOR.MINOR.PATCH와 같은 시맨틱 버전 번호 로 버전이 지정됩니다. 여기 에 있는 규칙 에 따라 스키마 변경 사항 을 추적 합니다 . 버전 1.0.0 이후에 추가된 필드 내역을 확인하세요.

플랫 버퍼 파일 식별

시맨틱 버전 관리는 규칙을 따르는 경우 호환성을 보장하지만 진정한 비호환성을 의미하지는 않습니다. MAJOR 번호를 올릴 때 반드시 이전 버전과의 호환성이 깨진 것은 아닙니다. 따라서 플랫 버퍼 파일 식별file_identifier 를 사용하여 메타데이터 스키마의 진정한 호환성을 나타냅니다. 파일 식별자는 정확히 4자입니다. 특정 메타데이터 스키마에 고정되어 사용자가 변경할 수 없습니다. 어떤 이유로 메타데이터 스키마의 이전 버전과의 호환성이 중단되어야 하는 경우 file_identifier는 예를 들어 "M001"에서 "M002"로 증가합니다. File_identifier는 metadata_version보다 훨씬 덜 자주 변경될 것으로 예상됩니다.

필요한 최소 메타데이터 파서 버전

필요한 최소 메타데이터 파서 버전 은 메타데이터 Flatbuffers 전체를 읽을 수 있는 메타데이터 파서(Flatbuffers 생성 코드)의 최소 버전입니다. 버전은 채워진 모든 필드의 버전 중에서 사실상 가장 큰 버전 번호이며 파일 식별자로 표시된 가장 작은 호환 버전입니다. 필요한 최소 메타데이터 파서 버전은 메타데이터가 TFLite 모델에 채워질 때 MetadataPopulator 에 의해 자동으로 채워집니다. 필요한 최소 메타데이터 파서 버전이 사용되는 방법에 대한 자세한 내용은 메타데이터 추출기 를 참조하세요.

모델에서 메타데이터 읽기

Metadata Extractor 라이브러리는 다양한 플랫폼의 모델에서 메타데이터 및 관련 파일을 읽는 편리한 도구입니다( Java 버전C++ 버전 참조). Flatbuffers 라이브러리를 사용하여 다른 언어로 고유한 메타데이터 추출 도구를 구축할 수 있습니다.

Java에서 메타데이터 읽기

Android 앱에서 Metadata Extractor 라이브러리를 사용하려면 MavenCentral에서 호스팅되는 TensorFlow Lite Metadata AAR 을 사용하는 것이 좋습니다. 여기에는 MetadataExtractor 클래스와 메타데이터 스키마모델 스키마 에 대한 FlatBuffers Java 바인딩이 포함됩니다.

다음과 같이 build.gradle 종속성에서 이를 지정할 수 있습니다.

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

야간 스냅샷을 사용하려면 Sonatype 스냅샷 저장소 를 추가했는지 확인하십시오.

모델을 가리키는 ByteBuffer 를 사용하여 MetadataExtractor 개체를 초기화할 수 있습니다.

public MetadataExtractor(ByteBuffer buffer);

ByteBufferMetadataExtractor 개체의 전체 수명 동안 변경되지 않은 상태로 유지되어야 합니다. 모델 메타데이터의 플랫 버퍼 파일 식별자가 메타데이터 파서의 식별자와 일치하지 않으면 초기화가 실패할 수 있습니다. 자세한 내용은 메타데이터 버전 관리 를 참조하세요.

일치하는 파일 식별자를 사용하여 메타데이터 추출기는 플랫 버퍼의 이전 버전 및 이전 버전과의 호환성 메커니즘으로 인해 모든 과거 및 미래 스키마에서 생성된 메타데이터를 성공적으로 읽습니다. 그러나 미래 스키마의 필드는 이전 메타데이터 추출기로 추출할 수 없습니다. 메타데이터의 최소 필수 파서 버전 은 메타데이터 Flatbuffers를 완전히 읽을 수 있는 메타데이터 파서의 최소 버전을 나타냅니다. 다음 방법을 사용하여 필요한 최소 파서 버전 조건이 충족되는지 확인할 수 있습니다.

public final boolean isMinimumParserVersionSatisfied();

메타데이터 없이 모델을 전달할 수 있습니다. 그러나 메타데이터에서 읽는 메서드를 호출하면 런타임 오류가 발생합니다. hasMetadata 메서드를 호출하여 모델에 메타데이터가 있는지 확인할 수 있습니다.

public boolean hasMetadata();

MetadataExtractor 는 입력/출력 텐서의 메타데이터를 가져올 수 있는 편리한 기능을 제공합니다. 예를 들어,

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);

TensorFlow Lite 모델 스키마 는 여러 하위 그래프를 지원하지만 TFLite 인터프리터는 현재 단일 하위 그래프만 지원합니다. 따라서 MetadataExtractor 는 메서드의 입력 인수로 하위 그래프 인덱스를 생략합니다.

모델에서 관련 파일 읽기

메타데이터 및 관련 파일이 있는 TensorFlow Lite 모델은 기본적으로 일반적인 zip 도구로 압축을 풀어 관련 파일을 가져올 수 있는 zip 파일입니다. 예를 들어, mobilenet_v1_0.75_160_quantized 의 압축을 풀고 다음과 같이 모델의 레이블 파일을 추출할 수 있습니다.

$ 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

Metadata Extractor 라이브러리를 통해 관련 파일을 읽을 수도 있습니다.

Java에서 파일 이름을 MetadataExtractor.getAssociatedFile 메서드에 전달합니다.

public InputStream getAssociatedFile(String fileName);

마찬가지로 C++에서는 ModelMetadataExtractor::GetAssociatedFile 메서드를 사용하여 이 작업을 수행할 수 있습니다.

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