深度学习自定义组件用法 - xuelang-group/suanpan-docs GitHub Wiki

深度学习自定义组件用法

使用自定义组件,您可以通过加载自定义的Python脚本,通过复用您现有的代码,完成更灵活的模型搭建和训练。

Keras自定义层

一些新型网络层还未被收录到Keras 深度学习库,我们以GroupNormalization为例,演示如何将其加入到模型中。

如果您想了解更多如何定义自定义层的信息,可以参考Keras官方文档,但需注意所有自定义代码中import keras时候请用import tensorflow.keras,因为所有Keras深度学习组件底层使用的是TensorFlow 版本的Keras库。

当您拖出一个Keras自定义层时候可以在其右面板“概览”中修改其名称。

然后在参数设置列配置其他信息,

customObject:GroupNormalization层的源码,即GroupNormalization class定义和相关的import,有关 Group Normalization 的源码可以参考这个GitHub 链接

layerConfig:GroupNormalization class初始化函数带的参数和实例化网络层的名称(name)。

classString:“GroupNormalization”即自定义层class的名称。

自定义层GroupNormalization

Keras自定义代码

自定义代码,对输入tensor操作,输出tensor。

以下我们以引用预训练的MobileNetV2为例演示如何使用自定义代码组件。

当您拖出一个Keras自定义代码时候可以在其右面板“概览”中修改其名称。

在 “customCode”中填写自定义代码,实例中人口函数名称为“custom_code”,与在functionString定义的名称对应。

人口函数的第一个参数“input_tensor”为必选参数,其他参数为用户自定义参数。

人口函数的自定义参数通过“functionArgs”传入。

根据输入端子连接数量不同,人口函数第一个参数“input_tensor”可以为单个tensor或一列tensors,在人口函数中将对这个变量做操作,并返回一个tensor作为节点输出。

Keras自定义代码

Keras自定义模型训练

Keras自定义模型训练中你可以向如下方式调用model.fit函数,利用输入的Numpy数据训练模型,你可以在训练前冻结/解冻部分网络层实现例如迁移学习/模型微调的高级操作。

Keras自定义模型训练

Keras模型自定义训练文件夹数据

类似Keras自定义模型训练,区别是输入的训练数据为文件,比如图片文件/或压缩的文件夹。

learnerCode中定义的代码可以使用下列3个变量。

• data [字符串] -- 数据集文件夹的路径,即dataFolder输入端子上传的数据。

• model_weights [字符串] -- 如果提供,则路径到预先训练的模型权重 HDF5 文件,即h5Model输入端子输入的文件,可以为空(None)。如果其不为空,您可以用代码model.load_weights(model_weights)方式加载。

• model [Keras模型] -- 输出模型。

Keras模型自定义训练文件夹数据

下列为完整的learnerCode内容案例,您可以适当修改以完成不同的操作。

# data {str} -- Path to the dataset folder.
# model_weights {str} -- Path to the pre-trained model weight HDF5 file if provided.
# model {Model} -- your output model

import zipfile
import os
import tempfile

print("data:", data)
folder_items = os.listdir(data)
print("model_weights: ", model_weights)

# Locate a zip file first.
zip_fnames = [
    item for item in folder_items if "zip" in os.path.splitext(item)[1].lower()
]
if len(zip_fnames) > 0:
    zip_file = os.path.join(data, zip_fnames[0])
    extract_dir = tempfile.mkdtemp()
    print("extracting zip.")
    with zipfile.ZipFile(zip_file, "r") as zip_ref:
        zip_ref.extractall(extract_dir)
        data = extract_dir

from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import optimizers

# Hyper parameters.
batch_size = 20
height = 224
width = 224
epochs = 2
lr = 2e-5
steps_per_epoch = 100
validation_steps = 50


def get_dirs(base_dir):
    """Get the train, test ,validation data folder paths.
    
    Arguments:
        base_dir {str} -- node input data folder path.
    
    Raises:
        ValueError: Expect one input folder.
    
    Returns:
        list -- a list of 3 elements, train, test ,
                validation data folder paths, or Nones
    """
    outputs = []
    folders = os.listdir(data)
    folders = [folder.replace("_$folder$", "") for folder in folders]
    folders = list(set(folders))
    if len(folders) != 1:
        raise ValueError("Expect one input folder, but got: {}".format(folders))
    else:
        data_dir = os.path.join(base_dir, folders[0])
        dir_names = ["train", "test", "validation"]
        for dir_name in dir_names:
            dir_path = os.path.join(data_dir, dir_name)
            if os.path.isdir(dir_path):
                outputs.append(dir_path)
            else:
                outputs.append(None)
        return outputs


train_dir, test_dir, validation_dir = get_dirs(data)
print("dataset split folders:", train_dir, test_dir, validation_dir)


train_datagen = ImageDataGenerator(
    rescale=1.0 / 255,
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    fill_mode="nearest",
)

# Note that the validation data should not be augmented!
test_datagen = ImageDataGenerator(rescale=1.0 / 255)

train_generator = train_datagen.flow_from_directory(
    # This is the target directory
    train_dir,
    # All images will be resized.
    target_size=(height, width),
    batch_size=batch_size,
    # Since we use binary_crossentropy loss, we need binary labels
    class_mode="categorical",
)

validation_generator = test_datagen.flow_from_directory(
    validation_dir,
    target_size=(height, width),
    batch_size=batch_size,
    class_mode="categorical",
)

model.compile(
    loss="categorical_crossentropy",
    optimizer=optimizers.RMSprop(lr=lr),
    metrics=["acc"],
)

history = model.fit_generator(
    train_generator,
    steps_per_epoch=steps_per_epoch,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=validation_steps,
    verbose=1,
)