Разработка
Начинаем работу с 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 в качестве тестового набора.
И все готово!
Создание приложения
Для пользовательского интерфейса нам нужно простое представление изображения, текстовая метка и кнопка. Кнопка, очевидно, будет показывать ответ, а затем случайным образом загружать следующее изображение.
Теперь о самом интересном. Сначала нам нужен PetClassifier
, который принимает изображение и возвращает текст.
xxxxxxxxxx
class PetClassifier {
init?(named: String, labels: [String]) {
// ...
}
func labelForImage(_ image: UIImage) -> String? {
// ...
}
}
А затем в слое пользовательского интерфейса мы можем использовать наш PetClassifier
для обновления метки при нажатии на кнопку «Evaluate».
xxxxxxxxxx
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-модели.
xxxxxxxxxx
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 шагов:
- Подготовить входные данные
- Отправить их
- Прочитать вывод
- Разобрать вывод
xxxxxxxxxx
/*
* 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
Вот и все.
Вот как можно переложить такую ментальную задачу на компьютер.
ImageUtils
из этого эксперимента можно найти здесь. Но, вероятно, существуют и лучшие библиотеки для этих операций. Например, CoreMLHelpers или сам Core ML.
-
Программирование3 недели назад
Конец программирования в том виде, в котором мы его знаем
-
Магазины приложений3 недели назад
Магазин игр Aptoide запустился на iOS в Европе
-
Видео и подкасты для разработчиков5 дней назад
Как устроена мобильная архитектура. Интервью с тех. лидером юнита «Mobile Architecture» из AvitoTech
-
Новости3 недели назад
Видео и подкасты о мобильной разработке 2025.8