Создайте модель Tf Lite, используя трансферное обучение на предварительно обученной модели Tensorflow, оптимизируйте ее и выполните выводы.

В этой статье вы научитесь использовать предварительно обученную модель, применять трансферное обучение, преобразовывать модель в TF Lite, применять оптимизацию и делать выводы из модели TFLite.

Предварительные требования:

Базовое введение в TensorFlow Lite

Набор данных собак и кошек

Tensorflow 2.0

Создайте набор данных

Я загрузил набор данных и разархивировал файл в соответствии со следующей структурой.

Код Python для извлечения данных и создания данных в соответствии со структурой ниже доступен здесь.

Импорт необходимых библиотек

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D
from tensorflow.keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img
from tensorflow.python.keras.applications import imagenet_utils
from tensorflow.python.keras.layers import Dense,GlobalAveragePooling2D
from tensorflow.keras.applications import   DenseNet121
from tensorflow.python.keras.applications.densenet import preprocess_input
from tensorflow.keras.models import Model

Установка основных параметров тренировки

BASE_PATH = 'Data\\dogs-vs-cats\\train\\'
TRAIN_PATH='Data\\dogs-vs-cats\\train_data\\'
VAL_PATH='Data\\dogs-vs-cats\\validation_data\\'
batch_size = 32 
epochs = 60
IMG_HEIGHT = 150
IMG_WIDTH = 150

Измените масштаб и примените различные улучшения к обучающему изображению

train_image_generator = ImageDataGenerator(                                                rescale=1./255,                                              rotation_range=45,                                                width_shift_range=.15,                                                height_shift_range=.15,                                                horizontal_flip=True,                                                zoom_range=0.3)

Изменить масштаб данных проверки

validation_image_generator = ImageDataGenerator(rescale=1./255)

Создание пакетов нормализованных данных для набора данных обучения и проверки

train_data_gen = train_image_generator.flow_from_directory(batch_size = batch_size,                                                     directory=TRAIN_PATH,                                                     shuffle=True,                                                     target_size=(IMG_HEIGHT, IMG_WIDTH),                                                     class_mode='categorical')
val_data_gen = validation_image_generator.flow_from_directory(batch_size = batch_size,                                                              directory=VAL_PATH,                                                              target_size=(IMG_HEIGHT, IMG_WIDTH),                                                              class_mode='categorical')

Применение трансферного обучения на предварительно обученной модели

Вы можете использовать любую из предварительно обученных моделей. Я использовал DenseNet121, который имеет 427 слоев.

# Create the base model from the pre-trained model MobileNet V2
base_model = tf.keras.applications.DenseNet121(
input_shape=(IMG_WIDTH, IMG_HEIGHT,3),                                               include_top=False,                                               weights='imagenet')

Замораживание всех весов базовой предварительно обученной модели и добавление нескольких слоев поверх предварительно обученной модели

base_model.trainable = False
x=base_model.output
x=Flatten()(x)
x=Dense(512,activation='relu')(x) 
output=Dense(2,activation='softmax')(x) 
model=Model(inputs=base_model.input,outputs=output)
model.summary()

Вы можете видеть, что веса предварительно обученной модели нельзя обучить, и можно обучить только веса добавленных слоев.

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

TRAINABLE_LAYERS= len(model.layers)-len(base_model.layers)+5
print(TRAINABLE_LAYERS)
for layer in model.layers[:-TRAINABLE_LAYERS]:
    layer.trainable=False
for layer in model.layers[-TRAINABLE_LAYERS:]:
    layer.trainable=True

вы можете увидеть, что количество обучаемых параметров увеличилось, и это также увеличит время обучения.

Скомпилируйте и обучите модель на пользовательском наборе данных

model.compile(loss='categorical_crossentropy', optimizer=tf.keras.optimizers.RMSprop(lr=2e-5), metrics=['acc'])
epochs=20
step_size_train=train_data_gen.n//train_data_gen.batch_size
history =model.fit_generator(generator=train_data_gen,
                   steps_per_epoch=step_size_train,
                   epochs=epochs)

После того, как модель скомпилирована и обучена, мы можем приступить к преобразованию модели в TF Lite, как показано ниже.

Преобразование предварительно обученной модели передачи обучения в TF Lite

После того, как вы обучили Модель, вам нужно будет сохранить Модель.

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

#save your model in the SavedModel format
export_dir = 'saved_model'
tf.saved_model.save(model, export_dir)

SavedModel содержит полную программу TensorFlow, включая веса и вычисления.

saved_model - это мета-график, сохраненный в export_dir,, который преобразуется в модель TFLite с помощью lite.TFLiteConverter.

# Converting a SavedModel to a TensorFlow Lite model.
converter = tf.lite.TFLiteConverter.from_saved_model(export_dir)
tflite_model = converter.convert()

Запись модели TFLIte с плоским буфером в двоичный файл, размер которого в настоящее время составляет 61 МБ.

open("model_tl.tflite", "wb").write(tflite_model)

Оптимизация модели

Модели в Edge должны быть легкими и иметь низкую задержку для выполнения выводов. Облегченная модель с низкой задержкой достигается за счет уменьшения объема вычислений, необходимых для прогнозирования, что достигается путем применения квантованной оптимизации к модели TF Lite.

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

Квантование применяется к весу и активациям.

optimize="Speed"
if optimize=='Speed':
    converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_LATENCY]
elif optimize=='Storage':
     converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
else:    
    converter.optimizations = [tf.lite.Optimize.DEFAULT]
#reduce the size of a floating point model by quantizing the weights to float16
converter.target_spec.supported_types = [tf.float16]
tflite_quant_model = converter.convert()
#save the quanitized model toa binary file
open("model_quant_tl.tflite", "wb").write(tflite_quant_model)

Здесь мы оптимизировали модель по скорости, а затем преобразовали 32-разрядные числа с плавающей запятой в 16-разрядные числа с плавающей запятой, чтобы уменьшить размер модели.

Модель TF Lite, которая составляла 61 МБ, теперь уменьшена до 30 МБ после применения оптимизации.

Оптимизированную модель можно развернуть на любом из пограничных устройств, где нам понадобится tflite_runtime.interpreter.

Выполнение выводов на краю

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

import tflite_runtime.interpreter as tflite
# Load TFLite model and allocate tensors.
interpreter = tf.lite.Interpreter(model_content=tflite_quant_model)
#allocate the tensors
interpreter.allocate_tensors()

Получите входные и выходные тензоры.

#get input and output tensors
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

Предварительная обработка входных данных

Входное изображение, для которого мы хотим сделать вывод, должно соответствовать входным данным для модели.

Считайте изображение, декодируйте в тензор и предварительно обработайте изображение до необходимого размера, преобразуйте его в float16 и добавьте размер пакета

import cv2
# Read the image and decode to a tensor
image_path='Data\\dogs-vs-cats\\test1\\151.jpg' 
img = cv2.imread(image_path)
img = cv2.resize(img,(IMG_WIDTH,IMG_HEIGHT))
#Preprocess the image to required size and cast
input_shape = input_details[0]['shape']
input_tensor= np.array(np.expand_dims(img,0), dtype=np.float16)

Ниже представлено изображение, которое мы пытаемся предсказать.

Выполните вывод

Направьте входные данные в 0-й массив для ввода тензора, задав тензор. Выполните вывод, вызвав интерпретатор

#set the tensor to point to the input data to be inferred
input_index = interpreter.get_input_details()[0]["index"]
interpreter.set_tensor(input_index, input_tensor)
#Run the inference
interpreter.invoke()
output_details = interpreter.get_output_details()

Интерпретация выходного тензора для нашей классификации изображений

output_data = interpreter.get_tensor(output_details[0]['index'])
results = np.squeeze(output_data)
top_k = results.argsort()
for label, idx in train_data_gen.class_indices.items():  
    if top_k[idx]==1:
        print("Prediction: " label)

На выходе получается собака.

Код Github для выводов TF Lite

Вывод:

Используйте настраиваемое, предварительно обученное или применяйте переносное обучение к предварительно обученной модели, сохраните модель, преобразуйте модель в файл с плоским буфером TFLite, оптимизируйте ее либо для задержки, либо для хранения, а затем сделайте выводы с помощью интерпретатора TF Lite.