Spaces:
Sleeping
Sleeping
from __future__ import division, print_function | |
from keras.models import Model | |
from keras.layers import Input, Conv1D, Dense, add, Flatten, Dropout,MaxPooling1D, Activation, BatchNormalization, Lambda | |
from keras import backend as K | |
from keras.optimizers import Adam | |
from keras.saving import register_keras_serializable | |
import tensorflow as tf | |
def zeropad(x): | |
""" | |
zeropad and zeropad_output_shapes are from | |
https://github.com/awni/ecg/blob/master/ecg/network.py | |
""" | |
y = tf.zeros_like(x) | |
return tf.concat([x, y], axis=2) | |
def zeropad_output_shape(input_shape): | |
shape = list(input_shape) | |
assert len(shape) == 3 | |
shape[2] *= 2 | |
return tuple(shape) | |
def ECG_model(config): | |
""" | |
implementation of the model in https://www.nature.com/articles/s41591-018-0268-3 | |
also have reference to codes at | |
https://github.com/awni/ecg/blob/master/ecg/network.py | |
and | |
https://github.com/fernandoandreotti/cinc-challenge2017/blob/master/deeplearn-approach/train_model.py | |
""" | |
def first_conv_block(inputs, config): | |
layer = Conv1D(filters=config.filter_length, | |
kernel_size=config.kernel_size, | |
padding='same', | |
strides=1, | |
kernel_initializer='he_normal')(inputs) | |
layer = BatchNormalization()(layer) | |
layer = Activation('relu')(layer) | |
shortcut = MaxPooling1D(pool_size=1, | |
strides=1)(layer) | |
layer = Conv1D(filters=config.filter_length, | |
kernel_size=config.kernel_size, | |
padding='same', | |
strides=1, | |
kernel_initializer='he_normal')(layer) | |
layer = BatchNormalization()(layer) | |
layer = Activation('relu')(layer) | |
layer = Dropout(config.drop_rate)(layer) | |
layer = Conv1D(filters=config.filter_length, | |
kernel_size=config.kernel_size, | |
padding='same', | |
strides=1, | |
kernel_initializer='he_normal')(layer) | |
return add([shortcut, layer]) | |
def main_loop_blocks(layer, config): | |
filter_length = config.filter_length | |
n_blocks = 15 | |
for block_index in range(n_blocks): | |
subsample_length = 2 if block_index % 2 == 0 else 1 | |
shortcut = MaxPooling1D(pool_size=subsample_length)(layer) | |
if block_index % 4 == 0 and block_index > 0 : | |
shortcut = Lambda(zeropad, output_shape=zeropad_output_shape)(shortcut) | |
filter_length *= 2 | |
layer = BatchNormalization()(layer) | |
layer = Activation('relu')(layer) | |
layer = Conv1D(filters= filter_length, | |
kernel_size=config.kernel_size, | |
padding='same', | |
strides=subsample_length, | |
kernel_initializer='he_normal')(layer) | |
layer = BatchNormalization()(layer) | |
layer = Activation('relu')(layer) | |
layer = Dropout(config.drop_rate)(layer) | |
layer = Conv1D(filters= filter_length, | |
kernel_size=config.kernel_size, | |
padding='same', | |
strides= 1, | |
kernel_initializer='he_normal')(layer) | |
layer = add([shortcut, layer]) | |
return layer | |
def output_block(layer, config): | |
layer = BatchNormalization()(layer) | |
layer = Activation('relu')(layer) | |
layer = Flatten()(layer) | |
outputs = Dense(len_classes, activation='softmax')(layer) | |
model = Model(inputs=inputs, outputs=outputs) | |
adam = Adam(learning_rate=0.1, beta_1=0.9, beta_2=0.999, epsilon=1e-7, amsgrad=False) | |
model.compile(optimizer= adam, | |
loss='categorical_crossentropy', | |
metrics=['accuracy']) | |
model.summary() | |
return model | |
classes = ['N','V','/','A','F','~'] | |
len_classes = len(classes) | |
inputs = Input(shape=(config.input_size, 1), name='input') | |
layer = first_conv_block(inputs, config) | |
layer = main_loop_blocks(layer, config) | |
return output_block(layer, config) | |