简介
记录在STM32平台移植神经网络的流程
模型搭建
上一篇提到神经网络搭建的三种方式为Sequential API、Functional API和Subclassing。这里对其简单叙述。
Sequential API
Sequential模式使用起来最简单,如果我们需要的网络结构是纯线性结构,优先考虑使用Sequential模式,一个简单的手写数字识别例子如下:
import tensorflow as tf
from tensorflow.keras import layers,models,optimizers,Sequential
from tensorflow.keras.layers import Dense,Flatten,Dropout
from tensorflow.keras.datasets import mnist
(train_x,train_y),(test_x,test_y) = mnist.load_data()
trian_x,test_x = train_x/255.0,test_x/255.0
model = Sequential([
Flatten(input_shape=(28,28)),
Dense(512,activation='relu'),
Dropout(0.2),
Dense(10,activation='softmax')
])
optimizer = optimizers.Adam(learning_rate=1e-3)
model.compile(loss = 'sparse_categorical_crossentropy',
optimizer = optimizer,
metrics=['accuracy'])
model.fit(train_x,train_y,batch_size=64,epochs=10)
该例子需要注意标签并没有进行onehot,模型输出和标签维度不一致,遇到这种情况在编译模型时loss函数一定要使用sparse_categorical_crossentropy
Functional API
Sequential方式就是简单,但对于一些较复杂的模型如ResNet、GoogleNet、Xception、SqueezeNet等就建议使用Functional API方式搭建,如下展示一个ResNet搭建方式
def block(x):
x_Conv_1 = Conv1D(filters=512, kernel_size=[3], strides=1, padding='same')(x)
x_Conv_1 = Activation(activation='relu')(x_Conv_1)
x_Conv_2 = Conv1D(filters=512, kernel_size=[3], strides=1, padding='same')(x_Conv_1)
x_Conv_2 = Add()([x, x_Conv_2])
x = Activation(activation='relu')(x_Conv_2)
return x
From keras.models import Model
inputs = tf.keras.Input(shape=(28,28))
block1 = block(inputs)
x = tf.keras.layers.Dense(4, activation=tf.nn.relu)(block1)
outputs = tf.keras.layers.Dense(5, activation=tf.nn.softmax)(x)
model = tf.keras.Model(inputs=inputs, outputs=outputs)
Subclassing
class LinearRegression(tf.keras.Model):
def __init__(self):
super().__init__()
self.dense = tf.keras.layers.Dense(units=1, activation=None)
def call(self, input):
output = self.dense(input)
return output
其实对于嵌入式场景来说,很多情况都并不复杂,使用好SequentialAPI其实就差不多了,毕竟学硬件就已经够心累的了,学这么多实在精力有限。