本文采用了深度残差网络和自适应参数化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