Connect with us

Разработка

Начинаем работу с LiteRT (Tensorflow Lite)

Вот как можно переложить такую ментальную задачу на компьютер.

Опубликовано

/

     
     

Недавно Google переименовал TensorflowLite в LiteRT. И да, это был действительно гениальный ход. Потому что теперь впервые в жизни я действительно хочу попробовать TFLite… да, я имею в виду LiteRT.

В реальном мире вы в идеале должны думать как обычный ML-разработчик и начинать с поиска набора данных, который затем используется для обучения модели. А затем, в качестве следующего шага, вы бы придумали проблему, которую можно решить с помощью обученной модели.

Но в этом эксперименте мы не будем усложнять ситуацию и построим «Hello World» во вселенной машинного обучения с упражнением «Собаки против кошек».

Настройка

По случайному совпадению я нашел обученную модель из Flutter-проекта, которая может определить, кто изображен на данной фотографии — собака или кошка.

Отлично! Итак, следуя инструкциям в официальной документации по началу работы, нам нужно добавить tensorflowlite в качестве зависимости в наш проект.

use_frameworks!
# pod 'TensorFlowLiteSwift'
pod 'TensorFlowLiteSwift', '~> 0.0.1-nightly', :subspecs => ['CoreML', 'Metal']

Мы используем «ночную» сборку, а не стабильный релиз, потому что на сегодняшний день последний стабильный релиз TensorFlowLiteC не работает на симуляторе iOS. Но, судя по последнему комментарию к этому вопросу, похоже, что TensorFlowLiteC теперь также поставляется как xcframework, но только в ночных релизах.

А пока мы ждем окончания установки библиотеки, мы можем беззастенчиво поискать образцы изображений различных собак и кошек из курса «Введение в TensorFlow Lite» на Udacity в качестве тестового набора.

И все готово!

Создание приложения

Для пользовательского интерфейса нам нужно простое представление изображения, текстовая метка и кнопка. Кнопка, очевидно, будет показывать ответ, а затем случайным образом загружать следующее изображение.

Начинаем работу с LiteRT (Tensorflow Lite)

Теперь о самом интересном. Сначала нам нужен PetClassifier, который принимает изображение и возвращает текст.

class PetClassifier {

  init?(named: String, labels: [String]) {
    // ...
  }

  
  func labelForImage(_ image: UIImage) -> String? {
    // ...
  }
}

А затем в слое пользовательского интерфейса мы можем использовать наш PetClassifier для обновления метки при нажатии на кнопку «Evaluate».

class ViewController: UIViewController {

  var classifier: PetClassifier?
  @IBOutlet var answerLabel: UILabel!

  override func viewDidLoad() {
    super.viewDidLoad()
    classifier = PetClassifier(named: "dogvscat", labels: ["Cat", "Dog"])
  }

  @IBAction func handleTap() {
    answerLabel.text = classifier?.labelForImage(selectedImage) ?? "Potato"
  }
}

Наконец, загрузка модели довольно проста. Нам просто нужно инстанцировать Interpreter, указав путь к нашей tflite-модели.

class PetClassifier {
  let interpreter: Interpreter
  let labels: [String]
    
  init?(named: String, labels: [String]) {
    guard let modelPath = Bundle.main.path(forResource: named, ofType: "tflite") else {
      return nil
    }
    
    do {
      var options = Interpreter.Options()
      options.threadCount = Self.threadCount
      interpreter = try Interpreter(modelPath: modelPath, options: options)
      self.labels = labels
    } catch {
      print(error)
      return nil
    }
  }

  // ...
}

Вызов модели

Получение ответа от модели состоит из 4 шагов:

  1. Подготовить входные данные
  2. Отправить их
  3. Прочитать вывод
  4. Разобрать вывод
/*
 * 1. Prepare input
 */
// user provided image
let image: UIImage 
// image size used for training model
let inputWidth = 224
let inputHeight = 224

// convert image to pixel buffer for further manipulation
let pixelBuffer = ImageUtils.pixelBufferCreate(image: image)
// crop image to size used for training model
let scaledPixelBuffer = ImageUtils.pixelBufferCreateWith(
  pixelBuffer: pixelBuffer,
  resizedTo: CGSize(width: Self.inputWidth, height: Self.inputHeight)
)
// Remove the alpha component from the image buffer to get the RGB data.
let rgbData = ImageUtils.pixelBufferCreateRGBData(
    pixelBuffer: scaledPixelBuffer,
    byteCount: Self.inputWidth * Self.inputHeight * 3
)

/*
 * 2. Send input data 
 */
interpreter.allocateTensors()      
interpreter.copy(rgbData, toInputAt: 0)
interpreter.invoke()

/*
 * 3. Read output data
 */
let outputTensor = try interpreter.output(at: 0)
let results: [Float] = outputTensor.data.withUnsafeBytes {
  Array($0.bindMemory(to: Float.self))
}

/*
 * 4. Parse output
 */      
// Create a zipped array of tuples [(labelIndex: Int, confidence: Float)].
// Sort the zipped results by confidence value
let inferences = zip(labels.indices, results)
  .sorted { $0.1 > $1.1 }
  .map { (label: labels[$0.0], confidence: $0.1) }
      
let bestInference = inferences.first

Вот и все.

Вот как можно переложить такую ментальную задачу на компьютер.

Начинаем работу с LiteRT (Tensorflow Lite)

ImageUtils из этого эксперимента можно найти здесь. Но, вероятно, существуют и лучшие библиотеки для этих операций. Например, CoreMLHelpers или сам Core ML.

Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.

Наши партнеры:

LEGALBET

Мобильные приложения для ставок на спорт
Telegram

Популярное

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: