keras构建自定义模型

Keras提供Sequential API和Functional API来利用现有的layers和models构建模型,也可以构建自定义的layer和model。
以构建一个有三层隐藏层的MLP神经网络为例,hidden units为[64,32,16],使用mnist数据集,构建多分类模型,输出层unit为10。本文使用tensorflow框架。

一、Sequential API

Sequential API适合构造结构简单的神经网络,即每一层网络只有一个输入和一个输出。

import tensorflow as tf
from tensorflow.keras.layers import Layer, Dense
hidden_units = [64, 32, 16]

model = tf.keras.Sequential()
for unit in hidden_units:
    model.add(Dense(unit, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.build(input_shape=(None,784))

在这里插入图片描述
模型要built成功,需给定input_shape,除了上面使用的call build,还可以采用如下方法

model.add(tf.keras.Input(shape=(784,))) #加入Input层
model.add(Dense(64, activation='relu', input_shape=(784,))) # 构建第一层时指定input_shape
y = model(x_train) # call model on data

二、Functional API

Functional API可以构造网络拓扑结构复杂的模型,支持多输入和多输出。

inputs = tf.keras.Input(shape=(784,))
X = inputs
for unit in hidden_units:
    X = Dense(unit, activation='relu')(X)
outputs = Dense(10, activation='softmax')(X)
model = tf.keras.Model(inputs=inputs, outputs=outputs)

三、自定义模型

Keras-Making new layers and models via subclassing 支持建立自定义的layers and models。
以下构建一个HappyLayer类和一个HappyModel类:

import tensorflow as tf
from tensorflow.keras.layers import Layer

class HappyLayer(Layer):
    def __init__(self, units, num, initer="glorot_uniform", trainable=True):
        super(HappyLayer, self).__init__()
        self.units = units
        self.initer = initer
        self.num = num
        print('HappyLayer',self.num, ' init')
        
    def build(self, input_shape):
        print('HappyLayer',self.num, ' build')
        self.w = self.add_weight(shape=(input_shape[-1], self.units), initializer=self.initer, trainable=True)
        self.b = self.add_weight(shape=(self.units,), initializer=self.initer, trainable=True)
    
    def call(self, inputs):
        print('HappyLayer',self.num, ' call')
        return tf.nn.relu(tf.matmul(inputs, self.w) + self.b)
import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense
from HappyLayer import HappyLayer

class HappyModel(Model):
    def __init__(self, hidden_units, output_unit):
        super(HappyModel, self).__init__()
        print('HappyModel init start')
        self.n_layers = len(hidden_units)
        self.mylayers = []
        for i in range(self.n_layers):
            self.mylayers.append(HappyLayer(hidden_units[i],num=i+1))
        self.mylayers.append(Dense(output_unit, activation='softmax'))
        print('HappyModel init end')
        
    def call(self, X):
        print('HappyModel call')
        for i in range(self.n_layers):
            X = self.mylayers[i](X)
        Y = self.mylayers[-1](X)
        return Y
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype("float32") / 255
y_train = tf.one_hot(y_train, 10)
    
hidden_units = [64, 32, 16]
output_unit = 10
model = HappyModel(hidden_units, output_unit) 
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=3, batch_size=32, verbose=2)

代码输出结果如下:

HappyModel init start
HappyLayer 1  init
HappyLayer 2  init
HappyLayer 3  init
HappyModel init end
Epoch 1/3
HappyModel call
HappyLayer 1  build
HappyLayer 1  call
HappyLayer 2  build
HappyLayer 2  call
HappyLayer 3  build
HappyLayer 3  call
HappyModel call
HappyLayer 1  call
HappyLayer 2  call
HappyLayer 3  call
1875/1875 - 2s - loss: 0.3072 - accuracy: 0.9105 - 2s/epoch - 1ms/step
Epoch 2/3
1875/1875 - 2s - loss: 0.1321 - accuracy: 0.9619 - 2s/epoch - 1ms/step
Epoch 3/3
1875/1875 - 2s - loss: 0.0990 - accuracy: 0.9702 - 2s/epoch - 971us/step
  1. 在第一次调用call方法时,系统会自动调用build方法,我们通常在build里才创建参数,因为在init模型时,还不知道输入数据的大小,build方法中的input_shape来自调用call时的传入数据。
    若call有多个输入参数,会获得第一个参数的shape作为input_shape。
  2. Model class与Layer class的使用接口基本一样,区别就是Model提供如模型训练、模型预测、模型保存等方法。
  3. fit采用mini-batch=32,每个epoch内会调用模型的call方法1875次,可实际只输出print两次,原因在于tensorflow使用C++来加速训练,除了一次用来创建模型weights,一次开始训练并构建C++ object (graph),剩下的过程都在C++模式下进行,所以不会运行python print。
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值