使用Keras的模型类将Tensorflow 1.x代码迁移到Tensorflow 2.x

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Keras的模型类将Tensorflow 1.x代码迁移到Tensorflow 2.x相关的知识,希望对你有一定的参考价值。

我刚刚开始使用Keras 2.3.1和Python 3.7.7学习Tensorflow 2.1.0。

我已经找到了这个“ Omniglot Character Set Classification Using Prototypical Network” github Jupyter Notebook,我认为它可以与Tensorflow 1.x一起使用。

我的问题是这段代码:

for epoch in range(num_epochs):

    for episode in range(num_episodes):

        # select 60 classes
        episodic_classes = np.random.permutation(no_of_classes)[:num_way]

        support = np.zeros([num_way, num_shot, img_height, img_width], dtype=np.float32)

        query = np.zeros([num_way, num_query, img_height, img_width], dtype=np.float32)


        for index, class_ in enumerate(episodic_classes):
            selected = np.random.permutation(num_examples)[:num_shot + num_query]
            support[index] = train_dataset[class_, selected[:num_shot]]

            # 5 querypoints per classs
            query[index] = train_dataset[class_, selected[num_shot:]]

        support = np.expand_dims(support, axis=-1)
        query = np.expand_dims(query, axis=-1)
        labels = np.tile(np.arange(num_way)[:, np.newaxis], (1, num_query)).astype(np.uint8)
        _, loss_, accuracy_ = sess.run([train, loss, accuracy], feed_dict=support_set: support, query_set: query, y:labels)

        if (episode+1) % 10 == 0:
            print('Epoch  : Episode  : Loss: , Accuracy: '.format(epoch+1, episode+1, loss_, accuracy_))

是否有任何教程,书籍或文章可以帮助我使用Keras的模型将此代码迁移到Tensorflow 2.x和Keras?

我想从链接中编写类似这样的代码:

import numpy as np 
import os
import skimage.io as io
import skimage.transform as trans
import numpy as np
from keras.models import *
from keras.layers import *
from keras.optimizers import *
from keras.callbacks import ModelCheckpoint, LearningRateScheduler
from keras import backend as keras

def unet(pretrained_weights = None,input_size = (256,256,1)):
    inputs = Input(input_size)
    conv1 = Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(inputs)
    conv1 = Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
    conv2 = Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(pool1)
    conv2 = Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv2)
    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
    conv3 = Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(pool2)
    conv3 = Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv3)
    pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)
    conv4 = Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(pool3)
    conv4 = Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv4)
    drop4 = Dropout(0.5)(conv4)
    pool4 = MaxPooling2D(pool_size=(2, 2))(drop4)

    conv5 = Conv2D(1024, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(pool4)
    conv5 = Conv2D(1024, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv5)
    drop5 = Dropout(0.5)(conv5)

    up6 = Conv2D(512, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(UpSampling2D(size = (2,2))(drop5))
    merge6 = concatenate([drop4,up6], axis = 3)
    conv6 = Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(merge6)
    conv6 = Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv6)

    up7 = Conv2D(256, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(UpSampling2D(size = (2,2))(conv6))
    merge7 = concatenate([conv3,up7], axis = 3)
    conv7 = Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(merge7)
    conv7 = Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv7)

    up8 = Conv2D(128, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(UpSampling2D(size = (2,2))(conv7))
    merge8 = concatenate([conv2,up8], axis = 3)
    conv8 = Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(merge8)
    conv8 = Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv8)

    up9 = Conv2D(64, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(UpSampling2D(size = (2,2))(conv8))
    merge9 = concatenate([conv1,up9], axis = 3)
    conv9 = Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(merge9)
    conv9 = Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv9)
    conv9 = Conv2D(2, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal')(conv9)
    conv10 = Conv2D(1, 1, activation = 'sigmoid')(conv9)

    model = Model(input = inputs, output = conv10)

    model.compile(optimizer = Adam(lr = 1e-4), loss = 'binary_crossentropy', metrics = ['accuracy'])

    #model.summary()

    if(pretrained_weights):
        model.load_weights(pretrained_weights)

    return model

以及train.py

model = unet(...)
model.compile(...)
model.fit(...)
答案

[来自Tensorflow陶氏的this tutorial汇总了所有内容。

最重要的是Sessions不再存在,应该使用tensorflow.keras.layers创建模型。

现在训练模型时,您有2个选择,可以使用Keras方式,也可以使用GradientTape(有点旧的方式。

这意味着您有两种选择,一种选择不会对您的代码产生太大的影响(GradientTape),一种选择使您只需更改几处(Keras)。

渐变色带

GradientTape用于您想要进行自己的循环并根据需要计算梯度,有点像Tensorflow 1.X。

  • 使用Keras API建立模型:
import tensorflow as tf

def unet(...):
    inputs = tf.keras.layers.Input(shape_images)
    ...
    model = Model(input = inputs, output = conv10)

    model.compile(...)

    return model

...

model = unet(...)
  • 定义损失
mse = tf.keras.losses.MeanSquaredError()
  • 定义优化器
optimizer = tf.keras.optimizer.Adam(lr=1e-4)

然后,您将按照通常的方式进行培训,只是用GradientTape替换了旧的Session机制:


for epoch in range(num_epochs):

    for episode in range(num_episodes):

        # select 60 classes
        episodic_classes = np.random.permutation(no_of_classes)[:num_way]

        support = np.zeros([num_way, num_shot, img_height, img_width], dtype=np.float32)

        query = np.zeros([num_way, num_query, img_height, img_width], dtype=np.float32)


        for index, class_ in enumerate(episodic_classes):
            selected = np.random.permutation(num_examples)[:num_shot + num_query]
            support[index] = train_dataset[class_, selected[:num_shot]]

            # 5 querypoints per classs
            query[index] = train_dataset[class_, selected[num_shot:]]

        support = np.expand_dims(support, axis=-1)
        query = np.expand_dims(query, axis=-1)
        labels = np.tile(np.arange(num_way)[:, np.newaxis], (1, num_query)).astype(np.uint8)

        # No session here but a Gradient computing

        with tf.GradientTape() as tape:
            prediction = model(support) # or whatever you need as input of model
            loss = mse(label, prediction)
        # apply gradient descent
        grads = tape.gradient(loss, model.trainable_weights)
        optimizer.apply_gradients(zip(grads, model.trainable_weights))

Keras

对于keras,您需要更改输入数据的方式,因为您使用fit,所以不会有for循环,而您需要实现Generator或可以迭代的任何数据结构。这意味着您基本上需要(X, y)的列表。 data_struct [0]将为您提供第一个X,Y对。

一旦有了此数据结构,就很容易。

  • 像GradientTape一样定义模型

  • 像GradientTape一样定义优化器

  • 编译模型


model.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=['accuracy']) # Or whatever you need as loss/metrics

  • 使用您的data_struct拟合模型
model.fit(data_struct, epochs=500) # Add validation_data if you want, callback ...

以上是关于使用Keras的模型类将Tensorflow 1.x代码迁移到Tensorflow 2.x的主要内容,如果未能解决你的问题,请参考以下文章

将 Keras 模型集成到 TensorFlow

如何为 keras 模型使用 tensorflow 自定义损失?

tensorflow的keras 与 原声keras几点比较

TensorFlow2.0教程-使用keras训练模型

TensorFlow/Keras 多线程模型拟合

如何使用 tensorflow 或 keras 重新训练具有新子集的线性回归模型?