小白的树莓派Tensorflow2.0 opencv 学习笔记(七)

在收集完图片后,要想构建自己的训练集最好现想要自己要怎么训练模型,训练哪种模型。

这就必须对TensorFlow的API有所了解。TensorFlow提供了Keras模块可以轻松地用几行代码调用已经封装好的模型,我们要做的只是把自己的数据塞进去,并且添加一些断点和保存权重的方法即可。

找了很多不同模型对比的文章,最后还是决定从YoloV3下手,虽然它训练可能有点困难,但是作为真正意义上第一个上手的模型,我还是想尝试一下。不过还是先从最基础的如何构造一个自定义网络层开始学习。

Keras API

Keras有两块

  1. Model :包含层连接和组织的函数和参数
  2. Layer :包含构成网络的函数和变量

Keras 基本操作

引入
import tensorflow as tf
网络容器

Keras 提供网络容器Sequential将多个网络封装成一个大网络模型

model = tf.keras.Sequential()
层的堆叠

通过add方式,选择Dense(全连接层)模式,激活函数为relu

model.add(tf.keras.layers.Dense(32,activation='relu'))
配置训练

利用compile方式,optimizer 为优化器,这里选择了Adam优化器,loss为损失函数,metrics为性能评估模块

model.compile(optimizer=tf.keras.optimizers.Adam(0.001),
              loss=tf.keras.losses.categorical_crossentropy,
              metrics=[tf.keras.metrics.categorical_accuracy])

利用容器配置模型

建立一个输入为756,输出10的5层全连接层模型(和MNIST手写图像训练集一样)

network = tf.keras.Sequential([tf.keras.layers.Dense(256,activation='relu'),
                               tf.keras.layers.Dense(128,activation='relu'),
                               tf.keras.layers.Dense(64,activation='relu'),
                               tf.keras.layers.Dense(32,activation='relu'),
                               tf.keras.layers.Dense(10)])
network.build(input_shape=(None,28*28))

自定义层

有时会需要自定义层以满足模型的需要,可以仿照自定义类模型来实现

class MyLayer(tf.keras.layers.Layer):
    def __init__(self,inp_dim,outp_dim):#inp_dim为输入个数,outp_dim为输出个数
        super().__init__()
        # 初始化代码
        # 例如创建可优化的权值张量
        self.kernel = self.add_weight('w', [inp_dim, outp_dim], trainable=True)

    def call(self, inputs):
        #处理输入
        return output

#调用并创建输入为4,输出为3的自定义层
net = MyLayer(4,3)

自定义类简单实现模型调用

上面的方法虽然能够调用模型,但是为了反复实例化,通过自定义类更加方便

class MyModel(tf.keras.Model):
    def __init__(self):
        super(MyModel,self).__init__()
        # 初始化代码(设定有几层和每层的参数)
        # 这里顺便利用之前定义的自定义层
        self.fc1 = MyLayer(28*28,256)
        self.fc2 = MyLayer(256,128)
        self.fc3 = MyLayer(128,64)
        self.fc4 = MyLayer(64,32)
        self.fc5 = MyLayer(32,10)

    def call(self, inputs):
        # 添加模型调用的代码(如何由输入得到输出)
        x = self.fc1(inputs)
        x = self.fc2(x)
        x = self.fc3(x)
        x = self.fc4(x)
        x = self.fc5(x)
        return x

        return output

模型训练

模型装配完成之后,可通过fit()函数送入训练数据和测试数据。

history = model.fit(train_db, epochs=5,validation_data=val_db,validation_freq=2)

train_db是tf.data.Dataset对象,也就是训练数据。
epochs是训练次数(每个训练数据都训练一遍,epochs的值为1)
validation_data是测试数据
validation_freq是测试的频率
可以利用history方法获得训练信息即(history.history)

模型测试

利用Model基类的predict方法即可完成模型的预测
out = model.predict(参数为测试数据)
如果只是简单的测试数据还可以调用evaluate方法
out = model.evaluate(参数为测试数据)

网络的保存和加载

将网络利用模型的方法保存和加载
利用Model.save(path)函数保存模型的结构和参数
利用keras.models.load_model(path)恢复网络的结构和参数

network.save("model.h5")
del network #删除网络对象
network = tf.keras.models.load_model("model.h5")

SavedModel方式

TensorFlow的SavedModel保存的模型具有平台无关性,可以迁移到其他平台
通过 tf.keras.experimental.export_saved_model(network, path) 即可将模型保存到path目录下的saved_model文件,文件的格式对于读取没有影响,读取时用函数 tf.keras.experimental.load_from_saved_model(path)

加载已经官方封装好的模型

利用keras.applications.模型名()模块可以调用TF库中利用ImageNet训练好的模型,这时只需要调整图片的输入大小即可,即可简单实现。

官方文档给出的可以调用的模型有
densenet 模块:用于Keras的DenseNet模型。
imagenet_utils 模块:用于ImageNet数据预处理和预测解码的实用程序。
inception_resnet_v2 模块:Keras的Inception-ResNet V2模型。
inception_v3 模块:Keras的Inception V3模型。
mobilenet 模块:Keras的MobileNet v1模型。
mobilenet_v2 模块:Keras的MobileNet v2模型。
nasnet 模块:适用于Keras的NASNet-A模型。
resnet 模块:Keras的ResNet模型。
resnet50 模块:tf.keras.applications.resnet50名称空间的公共API。
resnet_v2 模块:用于Keras的ResNet v2模型。
vgg16 模块:Keras的VGG16模型。
vgg19 模块:Keras的VGG19模型。
xception 模块:适用于Keras的Xception V1模型。

用之前需要下载,虽然keras模块能自动下载,但是速度比较慢,推荐先下载,然后放到C:\Users\你的用户名.keras\models目录下即可
下面是一段调用已经训练好的ResNet50模型预测图片里的物体的代码,不过它把马克思认成了手机…

import tensorflow as tf
import numpy as np

model = tf.keras.applications.ResNet50(weights='imagenet')

img_path = '2.jpg'
img = tf.keras.preprocessing.image.load_img(img_path, target_size=(224, 224))
x = tf.keras.preprocessing.image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = tf.keras.applications.resnet50.preprocess_input(x)

preds = model.predict(x)
print('Predicted:', tf.keras.applications.resnet50.decode_predictions(preds, top=3)[0])
发布了25 篇原创文章 · 获赞 2 · 访问量 2111

猜你喜欢

转载自blog.csdn.net/weixin_43874764/article/details/104192484