深度残差网络+自适应参数化ReLU激活函数(调参记录1)

本文通过深度残差网络和自适应参数化ReLU激活函数在Cifar10数据集上进行实验,展示网络结构(9个残差模块,卷积核数量8-32)。实验发现,调整学习率如从0.01降至0.001,能显著降低loss。这一工作在故障诊断领域有应用,并发表于IEEE Transactions on Industrial Electronics。
摘要由CSDN通过智能技术生成

本文采用了深度残差网络和自适应参数化ReLU激活函数,构造了一个网络(有9个残差模块,卷积核的个数比较少,最少是8个,最多是32个),在Cifar10数据集上进行了初步的尝试。

其中,自适应参数化ReLU激活函数原本是应用在基于振动信号的故障诊断,是参数化ReLU的一种改进,其基本原理如下图所示。
在这里插入图片描述
具体的keras代码如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Apr 14 04:17:45 2020
Implemented using TensorFlow 1.10.0 and Keras 2.2.1

Minghang Zhao, Shisheng Zhong, Xuyun Fu, Baoping Tang, Shaojiang Dong, Michael Pecht,
Deep Residual Networks with Adaptively Parametric Rectifier Linear Units for Fault Diagnosis, 
IEEE Transactions on Industrial Electronics, 2020,  DOI: 10.1109/TIE.2020.2972458 

@author: Minghang Zhao
"""

from __future__ import print_function
import keras
import numpy as np
from keras.datasets import cifar10
from keras.layers import Dense, Conv2D, BatchNormalization, Activation, Minimum
from keras.layers import AveragePooling2D, Input, GlobalAveragePooling2D, Concatenate, Reshape
from keras.regularizers import l2
from keras import backend as K
from keras.models import Model
from keras import optimizers
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import LearningRateScheduler
K.set_learning_phase(1)

# The data, split between train and test sets
(x_train, y_train), (x_test, y_test) = cifar10.load_data()

# Noised data
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_test = x_test-np.mean(x_train)
x_train = x_train-np.mean(x_train)
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)

# Schedule the learning rate, multiply 0.1 every 400 epoches
def scheduler(epoch):
    if epoch % 400 == 0 and epoch != 0:
        lr = K.get_value(model.optimizer.lr)
        K.set_value(model.optimizer.lr, lr * 0.1)
        print("lr changed to {}".format(lr * 0.1))
    return K.get_value(model.optimizer.lr)

# An adaptively parametric rectifier linear unit (APReLU)
def aprelu(inputs):
    # get the number of channels
    channels = inputs.get_shape().as_list()[-1]
    # get a zero feature map
    zeros_input = keras.layers.subtract([inputs, inputs])
    # get a feature map with only positive features
    pos_input = Activation('relu')(inputs)
    # get a feature map with only negative features
    neg_input = Minimum()([inputs,zeros_input])
    # define a network to obtain the scaling coefficients
    scales_p = GlobalAveragePooling2D()(pos_input)
    scales_n = GlobalAveragePooling2D()(neg_input)
    scales = Concatenate()([scales_n, scales_p])
    scales = Dense(channels//4, activation='linear', kernel_initializer='he_normal', kernel_regularizer=l2(1e-4))(scales)
    scales = BatchNormalization()(scales)
    scales = Activation('relu')(scales)
    scales = Dense(channels, activation='linear', kernel_initializer='he_normal', kernel_regularizer=l2(1e-4))(scales)
    scales = BatchNormalization()(scales)
    scales = Activation('sigmoid')(scales)
    scales = Reshape((1,1,channels))(scales)
    # apply a paramtetric relu
    neg_part = keras.layers.multiply([scales, neg_input])
    return keras.layers.add([pos_input, neg_part])

# Residual Block
def residual_block(incoming, nb_blocks, out_channels, downsample=False,
                   downsample_strides=2):
    
    residual = incoming
    in_channels = incoming.get_shape().as_list()[-1]
    
    for i in range(nb_blocks):
        
        identity = residual
        
        if not downsample:
            downsample_strides = 1
        
        residual = BatchNormalization()(residual)
        residual = aprelu(residual)
        residual = Conv2D(out_channels, 3, strides=(downsample_strides, downsample_strides), 
                          padding='same', kernel_initializer='he_normal', 
                          kernel_regularizer=l2(1e-4))(residual)
        
        residual = BatchNormalization()(residual)
        residual = aprelu(residual)
        residual = Conv2D(out_channels, 3, padding='same', kernel_initializer='he_normal', 
                          kernel_regularizer=l2(1e-4))(residual)
        
        # Downsampling
        if downsample_strides > 1:
            identity = AveragePooling2D(pool_size=(1,1), strides=(2,2))(identity)
            
        # Zero_padding to match channels
        if in_channels != out_channels:
            zeros_identity = keras.layers.subtract([identity, identity])
            identity = keras.layers.concatenate([identity, zeros_identity])
            in_channels = out_channels
        
        residual = keras.layers.add([residual, identity])
    
    return residual


# define and train a model
inputs = Input(shape=(32, 32, 3))
net = Conv2D(8, 3, padding='same', kernel_initializer='he_normal', kernel_regularizer=l2(1e-4))(inputs)
net = residual_block(net, 3, 8, downsample=False)
net = residual_block(net, 1, 16, downsample=True)
net = residual_block(net, 2, 16, downsample=False)
net = residual_block(net, 1, 32, downsample=True)
net = residual_block(net, 2, 32, downsample=False)
net = BatchNormalization()(net)
net = aprelu(net)
net = GlobalAveragePooling2D()(net)
outputs = Dense(10, activation='softmax', kernel_initializer='he_normal', kernel_regularizer=l2(1e-4))(net)
model = Model(inputs=inputs, outputs=outputs)
sgd = optimizers.SGD(lr=0.1, decay=0., momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])

# data augmentation
datagen = ImageDataGenerator(
    # randomly rotate images in the range (deg 0 to 180)
    rotation_range=30,
    # randomly flip images
    horizontal_flip=True,
    # randomly shift images horizontally
    width_shift_range=0.125,
    # randomly shift images vertically
    height_shift_range=0.125)

reduce_lr = LearningRateScheduler(scheduler)
# fit the model on the batches generated by datagen.flow().
model.fit_generator(datagen.flow(x_train, y_train, batch_size=100),
                    validation_data=(x_test, y_test), epochs=1000, 
                    verbose=1, callbacks=[reduce_lr], workers=4)

# get results
K.set_learning_phase(0)
DRSN_train_score1 = model.evaluate(x_train, y_train, batch_size=100, verbose=0)
print('Train loss:', DRSN_train_score1[0])
print('Train accuracy:', DRSN_train_score1[1])
DRSN_test_score1 = model.evaluate(x_test, y_test, batch_size=100, verbose=0)
print('Test loss:', DRSN_test_score1[0])
print('Test accuracy:', DRSN_test_score1[1])

部分实验结果如下:

Epoch 755/1000
500/500 [==============================] - 19s 39ms/step - loss: 0.3548 - acc: 0.9084 - val_loss: 0.4584 - val_acc: 0.8794
Epoch 756/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3526 - acc: 0.9098 - val_loss: 0.4647 - val_acc: 0.8727
Epoch 757/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3516 - acc: 0.9083 - val_loss: 0.4516 - val_acc: 0.8815
Epoch 758/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3508 - acc: 0.9098 - val_loss: 0.4639 - val_acc: 0.8785
Epoch 759/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3565 - acc: 0.9078 - val_loss: 0.4542 - val_acc: 0.8751
Epoch 760/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3556 - acc: 0.9077 - val_loss: 0.4681 - val_acc: 0.8729
Epoch 761/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3519 - acc: 0.9089 - val_loss: 0.4459 - val_acc: 0.8824
Epoch 762/1000
500/500 [==============================] - 19s 39ms/step - loss: 0.3523 - acc: 0.9085 - val_loss: 0.4528 - val_acc: 0.8766
Epoch 763/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3565 - acc: 0.9071 - val_loss: 0.4621 - val_acc: 0.8773
Epoch 764/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3532 - acc: 0.9084 - val_loss: 0.4570 - val_acc: 0.8751
Epoch 765/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3561 - acc: 0.9068 - val_loss: 0.4551 - val_acc: 0.8780
Epoch 766/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3515 - acc: 0.9093 - val_loss: 0.4583 - val_acc: 0.8796
Epoch 767/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3532 - acc: 0.9083 - val_loss: 0.4591 - val_acc: 0.8805
Epoch 768/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3531 - acc: 0.9088 - val_loss: 0.4725 - val_acc: 0.8733
Epoch 769/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3556 - acc: 0.9082 - val_loss: 0.4599 - val_acc: 0.8796
Epoch 770/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3540 - acc: 0.9087 - val_loss: 0.4635 - val_acc: 0.8792
Epoch 771/1000
500/500 [==============================] - 19s 39ms/step - loss: 0.3549 - acc: 0.9068 - val_loss: 0.4534 - val_acc: 0.8769
Epoch 772/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3560 - acc: 0.9080 - val_loss: 0.4550 - val_acc: 0.8790
Epoch 773/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3569 - acc: 0.9066 - val_loss: 0.4524 - val_acc: 0.8788
Epoch 774/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3542 - acc: 0.9071 - val_loss: 0.4542 - val_acc: 0.8802
Epoch 775/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3532 - acc: 0.9085 - val_loss: 0.4764 - val_acc: 0.8734
Epoch 776/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3549 - acc: 0.9072 - val_loss: 0.4720 - val_acc: 0.8732
Epoch 777/1000
500/500 [==============================] - 19s 39ms/step - loss: 0.3537 - acc: 0.9078 - val_loss: 0.4567 - val_acc: 0.8778
Epoch 778/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3537 - acc: 0.9073 - val_loss: 0.4579 - val_acc: 0.8759
Epoch 779/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3538 - acc: 0.9090 - val_loss: 0.4735 - val_acc: 0.8716
Epoch 780/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3584 - acc: 0.9066 - val_loss: 0.4611 - val_acc: 0.8756
Epoch 781/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3558 - acc: 0.9077 - val_loss: 0.4480 - val_acc: 0.8815
Epoch 782/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3546 - acc: 0.9073 - val_loss: 0.4704 - val_acc: 0.8767
Epoch 783/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3547 - acc: 0.9082 - val_loss: 0.4604 - val_acc: 0.8808
Epoch 784/1000
500/500 [==============================] - 19s 38ms/step - loss: 0.3502 - acc: 0.9099 - val_loss: 0.4570 - val_acc: 0.8805
Epoch 785/1000
500/500 [==============================] - 19s 39ms/step - loss: 0.3517 - acc: 0.9109 - val_loss: 0.4589 - val_acc: 0.8781
Epoch 786/1000
500/500 [==============================] - 19s 38ms/step - loss
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值