Crear un modelo de Tensorflow
Debido a las limitaciones del dispositivo, la plataforma Android no puede entrenar el modelo por sí misma, por lo que es necesario utilizar un modelo existente.
En este artículo, presentaremos cómo convertir el modelo Tensorflow en un modelo tflite, que puede ser utilizado por dispositivos Android.
import tensorflow as tf
import numpy as np
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras import Model
import matplotlib.pyplot as plt
# 读取训练用的输入特征和标签
fashion = tf.keras.datasets.fashion_mnist
(x_train, y_train), (x_test, y_test) = fashion.load_data()
x_train =x_train.reshape(x_train.shape[0],28,28,1).astype("float32")
x_test = x_test.reshape(x_test.shape[0],28,28,1).astype("float32")
# 输入特征归一化,减小计算量,将图片默认为0~255之间的数字,方便神经网络吸收
x_train, x_test = x_train/255.0, x_test/255.0
class_name = ["T恤","裤子","帽头衫","连衣裙","外套","凉鞋","衬衫","运动鞋","包","靴子"]
class FashionModel_CNN(tf.keras.Model):
"""
定义CNN网络结构
"""
def __init__(self):
super().__init__()
self.conv1 = tf.keras.layers.Conv2D(filters=32, kernel_size=[5,5], padding='valid',input_shape=(28,28,1),activation=tf.nn.relu)
self.pool1 = tf.keras.layers.MaxPool2D(pool_size=[2,2],strides = 2)
self.conv2 = tf.keras.layers.Conv2D(filters=64,kernel_size=[5,5],padding="same",activation = tf.nn.relu)
self.pool2 = tf.keras.layers.MaxPool2D(pool_size = [2,2],strides = 2)
self.flatten = Flatten() #tf.keras.layers.Reshape(target_shape=(28*28*64,))
self.dense1 = tf.keras.layers.Dense(units = 128,activation = tf.nn.relu)
self.dense2 = tf.keras.layers.Dense(units=10,activation = "softmax")
def call(self,inputs):
x = self.conv1(inputs)
x = self.pool1(x)
x = self.conv2(x)
x = self.pool2(x)
x = self.flatten(x)
x = self.dense1(x)
x = self.dense2(x)
output = tf.nn.softmax(x)
return output
def generate_nn(x_train,y_train,x_test,y_test):
# 声明神经网络对象
model = FashionModel_CNN()
# 配置训练方法(优化器,损失函数,评测指标)
model.compile(optimizer=tf.keras.optimizers.Adam(),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=[tf.keras.metrics.sparse_categorical_accuracy])
# 执行训练过程
model.fit(x_train, y_train,
batch_size=32, epochs=10,
validation_data=(x_test, y_test),
validation_freq=1)
# 打印网络结构和参数
model.summary()
return model
model = generate_nn(x_train,y_train,x_test,y_test)
tf.saved_model.save(model, "./forAndroid")
Aplique el modelo tensorflow en Python y pruébelo
import tensorflow as tf
import numpy as np
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras import Model
from tensorflow.python.keras.preprocessing.image import load_img
import matplotlib.pyplot as plt
#加载从指定的目录中加载模型
model = tf.saved_model.load("./forAndroid")
# 读取训练用的输入特征和标签
fashion = tf.keras.datasets.fashion_mnist
(x_train, y_train), (x_test, y_test) = fashion.load_data()
x_train = x_train.reshape(x_train.shape[0],28,28,1).astype("float32")
x_test = x_test.reshape(x_test.shape[0],28,28,1).astype("float32")
# 输入特征归一化,减小计算量,将图片默认为0~255之间的数字,方便神经网络吸收
x_train, x_test = x_train/255.0, x_test/255.0
class_name = ["T恤","裤子","帽头衫","连衣裙","外套","凉鞋","衬衫","运动鞋","包","靴子"]
#测试数据集的路径
path = "./test_data/exam_fashion/exam_fashion/"
images = ["%d.jpeg"%i for i in range(0,10)]
matrix = np.full(784,255.0).reshape(28,28)
images_data=[]
for imgfile in images:
img_name = "%s%s"%(path,imgfile)
print(img_name)
img = tf.keras.preprocessing.image.load_img(img_name,color_mode="grayscale",target_size=(28,28))
img_data = tf.keras.preprocessing.image.img_to_array(img)
img_data = matrix-img_data.reshape(28,28)
#将numpy数组的数据从float64转换成float32
images_data.append(img_data.astype('float32'))
#测试样本
images_data = np.array(images_data).reshape(10,28,28,1)
print(x_test.dtype,images_data.dtype)
y_pred = model(images_data)
index_list = np.argmax(y_pred,axis=1)
img_id = 0
index = 1
for i in index_list:
img_id +=1
print(index,i,class_name[i])
index = index+1
Utilice tflite_convert para exportar el modelo tensorflow a tflite
Ejecutar en consola:
tflite_convert __saved_model_dir=forAndroid __output_file=model.tflite
Se produjo un error durante la ejecución. El error es el siguiente:
2021-11-25 09:19:56.975579: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_UNKNOWN: unknown error
2021-11-25 09:19:56.979582: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:169] retrieving CUDA diagnostic information for host: DESKTOP-4CLUK38
2021-11-25 09:19:56.979752: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:176] hostname: DESKTOP-4CLUK38
2021-11-25 09:19:56.991993: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
Traceback (most recent call last):
File "d:\anaconda3\envs\tensorflow\lib\runpy.py", line 194, in _run_module_as_main
return _run_code(code, main_globals, None,
File "d:\anaconda3\envs\tensorflow\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "D:\anaconda3\envs\tensorflow\Scripts\tflite_convert.exe\__main__.py", line 7, in <module>
File "d:\anaconda3\envs\tensorflow\lib\site-packages\tensorflow\lite\python\tflite_convert.py", line 697, in main
app.run(main=run_main, argv=sys.argv[:1])
File "d:\anaconda3\envs\tensorflow\lib\site-packages\absl\app.py", line 303, in run
_run_main(main, args)
File "d:\anaconda3\envs\tensorflow\lib\site-packages\absl\app.py", line 251, in _run_main
sys.exit(main(argv))
File "d:\anaconda3\envs\tensorflow\lib\site-packages\tensorflow\lite\python\tflite_convert.py", line 680, in run_main
_convert_tf2_model(tflite_flags)
File "d:\anaconda3\envs\tensorflow\lib\site-packages\tensorflow\lite\python\tflite_convert.py", line 281, in _convert_tf2_model
converter = lite.TFLiteConverterV2.from_saved_model(
File "d:\anaconda3\envs\tensorflow\lib\site-packages\tensorflow\lite\python\lite.py", line 1348, in from_saved_model
saved_model = _load(saved_model_dir, tags)
File "d:\anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\saved_model\load.py", line 864, in load
result = load_internal(export_dir, tags, options)["root"]
File "d:\anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\saved_model\load.py", line 902, in load_internal
loader = loader_cls(object_graph_proto, saved_model_proto, export_dir,
File "d:\anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\saved_model\load.py", line 162, in __init__
self._load_all()
File "d:\anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\saved_model\load.py", line 259, in _load_all
self._load_nodes()
File "d:\anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\saved_model\load.py", line 448, in _load_nodes
slot_variable = optimizer_object.add_slot(
AttributeError: '_UserObject' object has no attribute 'add_slot'
Reconstruya Tensorflow de acuerdo con el mensaje de error.
La solución oficial proporcionada por Tensorflow es usar bazel para compilar tflite_convert.
El formulario es:
bazel run tflite_convert save_model_dir=directory__output_file=target.tflite.
Debido a que el costo de instalar bazel en Windows 10 es demasiado alto
, La idea de solución se ajusta.
la solución
Entonces recurrí a ejecutar código para implementar la conversión, con la esperanza de obtener más información.
Edite el siguiente código:
import tensorflow as tf
#指定保存模型的目录
saved_model_dir = "forAndroid"
# 转换模型
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
#转换模型
tflite_model = converter.convert()
# 将转换的模型保持到指定的文件model.tflite
with open('model.tflite', 'wb') as f:
f.write(tflite_model)
Problemas que surgen
Se produjo un error al ejecutar el programa de conversión. El contenido del error es el siguiente:
Registro de errores de mensajes rápidos
2021-11-25 09:28:46.532142: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_UNKNOWN: unknown error
2021-11-25 09:28:46.535042: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:169] retrieving CUDA diagnostic information for host: DESKTOP-4CLUK38
2021-11-25 09:28:46.535137: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:176] hostname: DESKTOP-4CLUK38
2021-11-25 09:28:46.535300: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX AVX2
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
......
El registro contiene una gran cantidad de información de error. Agregue el siguiente contenido:
import tensorflow as tf
import os
#指定日志的级别,设置为错误和警告信息
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
#指定保存模型的目录
saved_model_dir = "forAndroid"
# 转换模型
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
#转换模型
tflite_model = converter.convert()
# 将转换的模型保持到指定的文件model.tflite
with open('model.tflite', 'wb') as f:
f.write(tflite_model)
Ignore las advertencias básicas y descubra que el archivo tflite se ha generado correctamente.