我有一个 TensorFlow Keras 模型,看起来像这样。请注意,这个模型太大,无法在微控制器上运行,这是我的最终目标,但这是一个起点。最终目标是获得足够小的东西,以适合没有浮点单元的内存受限的微控制器。我使用的是 TensorFlow 版本 2.11.0
new_model = tf.keras.Sequential()
new_model.add(Conv2D(filters=128, kernel_size=[2, 2], activation='relu', input_shape=trainingData[0].shape))
new_model.add(Dropout(0.1))
new_model.add(Conv2D(filters=128, kernel_size=[2, 2], activation='relu'))
new_model.add(Dropout(0.2))
new_model.add(Flatten())
new_model.add(Dense(128, activation='relu'))
new_model.add(Dropout(0.5))
new_model.add(Dense(3, activation='softmax'))
new_model.compile(optimizer=Adam(learning_rate=0.001), loss='sparse_categorical_crossentropy', metrics=['accuracy'])
我没有在此处包含训练代码,因为它可以工作,并且我能够成功地对测试数据运行预测。如果有用我会添加它。该模型保存为 .h5 文件,并在转换为 TensorFlow Lite 时重新加载。
输入数据是 25 个 X、Y 和 Z 轴值,缩放范围为 -128...127。它们是从 .csv 文件加载的
data = pd.read_csv('../../TrainingData/training_raw.csv',
dtype={'X': np.int8, 'Z': np.int8, 'Y': np.int8, 'class': np.int8}, nrows=1000)
然后用这样的代码转换为框架
def convert_samples_to_frames(sensor_data, frame_size, hop_size):
frames = []
labels = []
data_length = len(sensor_data)
for i in range(0, data_length - frame_size, hop_size):
x = sensor_data['X'][i: i + frame_size]
y = sensor_data['Y'][i: i + frame_size]
z = sensor_data['Z'][i: i + frame_size]
label_statistics = stats.mode(sensor_data['class'][i: i + frame_size])
label = label_statistics[0][0]
frames.append([x, y, z])
labels.append(label)
frames = np.asarray(frames)
labels = np.asarray(labels)
return frames, labels
frames, labels = convert_samples_to_frames(data, 25, 10)
转换似乎有效,但此代码不是完整的整数
model = load_model('my_model.h5')
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS]
tflite_model = converter.convert()
当我尝试添加完整 8 位量化的代表性数据集时,问题就出现了。我尝试过一些事情。第一次尝试只是简单地给它样本数据中的帧。我尝试过这样的事情。请注意,这当然发生在我调用 converter.convert() 之前。
def representative_dataset_gen():
for i in range(100):
data = frames[i]
yield [data]
converter.representative_dataset = representative_dataset_gen
使用此代码我收到此错误
RuntimeError: tensorflow/lite/kernels/conv.cc:343 input->dims->size != 4 (2 != 4)Node number 0 (CONV_2D) failed to prepare.
我猜测这可能与 Conv2D 第一层有关,其中 kernel_size=[2, 2] 需要超过 1 帧。尽管回想起来,我不确定这是否有意义。无论如何,我尝试了一些类似的事情。
def representative_dataset_gen():
for i in range(100):
data = frames[i:i+2]
yield [data.reshape(1, 2, 3, 25)]
这导致它失败并出现不同的错误
Attempting to resize dimension 1 of tensor 0 with value 3 to 2. ResizeInputTensorStrict only allows mutating unknown dimensions identified by -1.
也尝试过这个
def representative_dataset_gen():
for i in range(100):
data = frames[i]
data = tf.expand_dims(data, 0)
yield [data]
这导致它失败了
RuntimeError: tensorflow/lite/kernels/conv.cc:343 input->dims->size != 4 (3 != 4)Node number 0 (CONV_2D) failed to prepare.
也尝试过
def representative_dataset_gen():
for i in range(100):
data = np.array(frames[i:i+2], dtype=np.float32).reshape(2, 1, 3, 25)
yield [data]
这给出了这个错误
RuntimeError: tensorflow/lite/core/subgraph.cc BytesRequired number of elements overflowed. Node number 1 (CONV_2D) failed to prepare.
请注意,最终我认为我需要添加一些类似的内容
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8
converter.inference_output_type = tf.int8
但为了弄清楚这一点,我正在采取一些小步骤,并忽略了这一点。
如果有人对如何正确设置我的代表性数据集有任何建议,或者对于在没有浮点单元的微控制器上进行此类推理的任何其他提示,我将非常感谢您的帮助。
我看到 2.4 中有一个问题,但看起来它已经解决了,因为我使用的是 2.11,我认为它不适合我。
我通过向模型添加输入层和重塑层以某种方式让它工作
new_model.add(tf.keras.layers.InputLayer(input_shape=(25, 3)))
new_model.add(tf.keras.layers.Reshape(target_shape=(25, 3, 1)))