LiteRT 지원 라이브러리로 입력 및 출력 데이터 처리

모바일 애플리케이션 개발자는 일반적으로 다음과 같은 유형이 지정된 객체와 상호작용합니다. 비트맵 또는 프리미티브(예: 정수) 하지만 LiteRT 인터프리터는 온디바이스 머신러닝 모델을 실행하는 API는 다음과 같은 형식으로 텐서를 사용합니다. ByteBuffer: 디버그 및 조작하기 어려울 수 있습니다. 이 LiteRT Android 지원 라이브러리 LiteRT 모델의 입력과 출력을 처리하도록 설계되어 있습니다. LiteRT 인터프리터를 더 쉽게 사용할 수 있습니다.

시작하기

Gradle 종속 항목 및 기타 설정 가져오기

.tflite 모델 파일을 Android 모듈의 assets 디렉터리에 복사합니다. 지정할 수도 있습니다 파일을 압축하지 않도록 지정합니다. LiteRT 라이브러리를 모듈의 build.gradle 파일에 추가합니다.

android {
    // Other settings

    // Specify tflite file should not be compressed for the app apk
    aaptOptions {
        noCompress "tflite"
    }

}

dependencies {
    // Other dependencies

    // Import tflite dependencies
    implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly-SNAPSHOT'
    // The GPU delegate library is optional. Depend on it as needed.
    implementation 'com.google.ai.edge.litert:litert-gpu:0.0.0-nightly-SNAPSHOT'
    implementation 'com.google.ai.edge.litert:litert-support:0.0.0-nightly-SNAPSHOT'
}

이제 MavenCentral에서 호스팅되는 LiteRT 지원 라이브러리 AAR 서로 다른 버전의 지원 라이브러리에 대해 자세히 알아볼 수 있습니다.

기본적인 이미지 조작 및 변환

LiteRT 지원 라이브러리에는 기본적인 이미지 조작 묶음이 있습니다. 사용할 수 있습니다. 사용하려면 ImagePreprocessor를 만들고 필요한 작업을 추가합니다. 이미지를 텐서 형식으로 변환하기 필요한 경우 사용할 TensorImage를 만듭니다. 다음과 같이 입력합니다.

import org.tensorflow.lite.DataType;
import org.tensorflow.lite.support.image.ImageProcessor;
import org.tensorflow.lite.support.image.TensorImage;
import org.tensorflow.lite.support.image.ops.ResizeOp;

// Initialization code
// Create an ImageProcessor with all ops required. For more ops, please
// refer to the ImageProcessor Architecture section in this README.
ImageProcessor imageProcessor =
    new ImageProcessor.Builder()
        .add(new ResizeOp(224, 224, ResizeOp.ResizeMethod.BILINEAR))
        .build();

// Create a TensorImage object. This creates the tensor of the corresponding
// tensor type (uint8 in this case) that the LiteRT interpreter needs.
TensorImage tensorImage = new TensorImage(DataType.UINT8);

// Analysis code for every frame
// Preprocess the image
tensorImage.load(bitmap);
tensorImage = imageProcessor.process(tensorImage);

텐서의 DataType메타데이터 추출기 라이브러리 다른 모델 정보를 확인할 수 있습니다

기본 오디오 데이터 처리

LiteRT 지원 라이브러리는 TensorAudio 클래스 래핑도 정의합니다. 몇 가지 기본적인 오디오 데이터 처리 방법을 다룹니다. 주로 함께 사용됩니다. AudioRecord 링 버퍼에서 오디오 샘플을 캡처합니다.

import android.media.AudioRecord;
import org.tensorflow.lite.support.audio.TensorAudio;

// Create an `AudioRecord` instance.
AudioRecord record = AudioRecord(...)

// Create a `TensorAudio` object from Android AudioFormat.
TensorAudio tensorAudio = new TensorAudio(record.getFormat(), size)

// Load all audio samples available in the AudioRecord without blocking.
tensorAudio.load(record)

// Get the `TensorBuffer` for inference.
TensorBuffer buffer = tensorAudio.getTensorBuffer()

출력 객체 만들기 및 모델 실행

모델을 실행하기 전에 작업을 수행할 컨테이너 객체를 다음과 같이 결과를 저장합니다.

import org.tensorflow.lite.DataType;
import org.tensorflow.lite.support.tensorbuffer.TensorBuffer;

// Create a container for the result and specify that this is a quantized model.
// Hence, the 'DataType' is defined as UINT8 (8-bit unsigned integer)
TensorBuffer probabilityBuffer =
    TensorBuffer.createFixedSize(new int[]{1, 1001}, DataType.UINT8);

모델 로드 및 추론 실행:

import java.nio.MappedByteBuffer;
import org.tensorflow.lite.InterpreterFactory;
import org.tensorflow.lite.InterpreterApi;

// Initialise the model
try{
    MappedByteBuffer tfliteModel
        = FileUtil.loadMappedFile(activity,
            "mobilenet_v1_1.0_224_quant.tflite");
    InterpreterApi tflite = new InterpreterFactory().create(
        tfliteModel, new InterpreterApi.Options());
} catch (IOException e){
    Log.e("tfliteSupport", "Error reading model", e);
}

// Running inference
if(null != tflite) {
    tflite.run(tImage.getBuffer(), probabilityBuffer.getBuffer());
}

결과 액세스

개발자는 Cloud Build API를 통해 probabilityBuffer.getFloatArray() 모델이 양자화된 출력을 생성하는 경우 결과를 변환해야 합니다 MobileNet 양자화 모델의 경우 개발자는 각 출력값을 255로 나누어 각 카테고리에 대해 0 (가능성이 가장 낮음)부터 1 (가장 높음) 사이로 표시합니다.

선택사항: 결과에 결과 매핑

개발자는 선택적으로 결과를 라벨에 매핑할 수도 있습니다. 먼저, 텍스트를 복사합니다 라벨이 포함된 파일을 모듈의 assets 디렉터리에 복사합니다. 다음으로 라벨을 로드합니다. 파일을 업로드할 수 있습니다.

import org.tensorflow.lite.support.common.FileUtil;

final String ASSOCIATED_AXIS_LABELS = "labels.txt";
List<String> associatedAxisLabels = null;

try {
    associatedAxisLabels = FileUtil.loadLabels(this, ASSOCIATED_AXIS_LABELS);
} catch (IOException e) {
    Log.e("tfliteSupport", "Error reading label file", e);
}

다음 스니펫은 확률을 카테고리 라벨:

import java.util.Map;
import org.tensorflow.lite.support.common.TensorProcessor;
import org.tensorflow.lite.support.common.ops.NormalizeOp;
import org.tensorflow.lite.support.label.TensorLabel;

// Post-processor which dequantize the result
TensorProcessor probabilityProcessor =
    new TensorProcessor.Builder().add(new NormalizeOp(0, 255)).build();

if (null != associatedAxisLabels) {
    // Map of labels and their corresponding probability
    TensorLabel labels = new TensorLabel(associatedAxisLabels,
        probabilityProcessor.process(probabilityBuffer));

    // Create a map to access the result based on label
    Map<String, Float> floatMap = labels.getMapWithFloatValue();
}

현재 사용 사례 범위

현재 버전의 LiteRT 지원 라이브러리는 다음을 포함합니다.

  • 일반적인 데이터 유형 (float, uint8, images, 오디오 및 이러한 객체의 배열) tflite 모델의 입력 및 출력으로 사용할 수 있습니다.
  • 기본 이미지 작업 (이미지 자르기, 크기 조절 및 회전)을 제공합니다.
  • 정규화와 양자화
  • 파일 유틸리티

향후 버전에서는 텍스트 관련 애플리케이션에 대한 지원이 개선될 예정입니다.

ImageProcessor 아키텍처

ImageProcessor의 설계 덕분에 이미지 조작 작업은 미리 정의하고 빌드 프로세스 중에 최적화할 수 있습니다 ImageProcessor 는 현재 세 가지 기본 전처리 작업을 지원합니다. 세 개의 주석이 있습니다.

import org.tensorflow.lite.support.common.ops.NormalizeOp;
import org.tensorflow.lite.support.common.ops.QuantizeOp;
import org.tensorflow.lite.support.image.ops.ResizeOp;
import org.tensorflow.lite.support.image.ops.ResizeWithCropOrPadOp;
import org.tensorflow.lite.support.image.ops.Rot90Op;

int width = bitmap.getWidth();
int height = bitmap.getHeight();

int size = height > width ? width : height;

ImageProcessor imageProcessor =
    new ImageProcessor.Builder()
        // Center crop the image to the largest square possible
        .add(new ResizeWithCropOrPadOp(size, size))
        // Resize using Bilinear or Nearest neighbour
        .add(new ResizeOp(224, 224, ResizeOp.ResizeMethod.BILINEAR));
        // Rotation counter-clockwise in 90 degree increments
        .add(new Rot90Op(rotateDegrees / 90))
        .add(new NormalizeOp(127.5, 127.5))
        .add(new QuantizeOp(128.0, 1/128.0))
        .build();

세부정보 더보기 자세한 내용은 여기를 정규화와 양자화의 두 가지 개념입니다.

지원 라이브러리의 최종 목표는 tf.image 드림 사용할 수 있습니다 즉, 변환은 TensorFlow와 동일하며 구현은 운영 체제와 독립적입니다.

개발자는 커스텀 프로세서를 만들 수도 있습니다. 인코더-디코더 아키텍처를 이 사례를 교육 프로세스에 맞게 조정해야 합니다. 즉, 학습과 추론에 모두 전처리를 적용하여 복제할 수 있습니다

양자화

입력 또는 출력 객체(예: TensorImage 또는 TensorBuffer)를 시작할 때 유형을 DataType.UINT8 또는 DataType.FLOAT32로 지정해야 합니다.

TensorImage tensorImage = new TensorImage(DataType.UINT8);
TensorBuffer probabilityBuffer =
    TensorBuffer.createFixedSize(new int[]{1, 1001}, DataType.UINT8);

TensorProcessor는 입력 텐서를 양자화하거나 출력을 비양자화하는 데 사용할 수 있음 텐서 등이 포함됩니다 예를 들어 양자화 출력 TensorBuffer를 처리할 때 개발자는 DequantizeOp를 사용하여 결과를 부동 소수점으로 비양자화할 수 있음 0과 1 사이의 확률입니다.

import org.tensorflow.lite.support.common.TensorProcessor;

// Post-processor which dequantize the result
TensorProcessor probabilityProcessor =
    new TensorProcessor.Builder().add(new DequantizeOp(0, 1/255.0)).build();
TensorBuffer dequantizedBuffer = probabilityProcessor.process(probabilityBuffer);

텐서의 양자화 매개변수는 메타데이터 추출기 라이브러리를 사용하여 BigQuery에서 직접 데이터를 가져올 수 있습니다.