Tensorflow モデルを作成する
デバイスの制限により、Android プラットフォームではモデル自体をトレーニングできないため、既存のモデルを使用する必要があります。
この記事では、Tensorflow モデルを Android デバイスで使用できる tflite モデルに変換する方法を紹介します。
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")
Python で tensorflow モデルを適用してテストする
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
tflite_convert を使用して tensorflow モデルを tflite にエクスポートします
コンソールで実行します。
tflite_convert __saved_model_dir=forAndroid __output_file=model.tflite
実行中にエラーが発生しました。エラーは次のとおりです。
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'
エラー メッセージに従って Tensorflow を再構築します。Tensorflow
が提供する公式の解決策は、bazel を使用して tflite_convert をコンパイルすることです。
形式は次のとおりです:
bazel run tflite_convert Saved_model_dir=directory__output_file=target.tflite.
Windows 10 に bazel をインストールするコストは高すぎるため
、解決策のアイデアが調整されます。
ソリューション
そこで、より詳しい情報を得るために、コードを実行して変換を実装することにしました。
次のコードを編集します。
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)
発生する問題
変換プログラム実行時にエラーが発生しました。エラー内容は以下のとおりです。
プロンプトメッセージ エラーログ
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.
......
ログには大量のエラー情報が含まれています。次の内容を追加します。
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)
基本的な警告を無視すると、tflite ファイルが正常に生成されたことがわかります。