Lmlm / Modelhai.ch
Seriki's picture
Rename Modelhai.ch.txt to Modelhai.ch
c8362af verified
Raw
History Blame Contribute Delete
106 kB
import os
import numpy as np, sys,os
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.io import loadmat
import wfdb
import tarfile
from sklearn import preprocessing
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.model_selection import StratifiedKFold
from keras.preprocessing.sequence import pad_sequences
import math
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.utils.class_weight import compute_class_weight
import tensorflow_addons as tfa
import tensorflow as tf
from tensorflow import keras
#from keras.utils import plot_model
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.signal import butter, lfilter, filtfilt
from scipy.signal import find_peaks
from scipy.signal import peak_widths
from scipy.signal import savgol_filter
def load_challenge_data(filename):
x = loadmat(filename)
data = np.asarray(x['val'], dtype=np.float64)
new_file = filename.replace('.mat','.hea')
input_header_file = os.path.join(new_file)
with open(input_header_file,'r') as f:
header_data=f.readlines()
return data, header_data
def clean_up_gender_data(gender):
gender = np.asarray(gender)
gender[np.where(gender == "Male")] = 0
gender[np.where(gender == "male")] = 0
gender[np.where(gender == "M")] = 0
gender[np.where(gender == "Female")] = 1
gender[np.where(gender == "female")] = 1
gender[np.where(gender == "F")] = 1
gender[np.where(gender == "NaN")] = 2
np.unique(gender)
gender = gender.astype(np.int)
return gender
def clean_up_age_data(age):
age = np.asarray(age)
age[np.where(age == "NaN")] = -1
np.unique(age)
age = age.astype(np.int)
return age
def import_gender_and_age(age, gender):
gender_binary = clean_up_gender_data(gender)
age_clean = clean_up_age_data(age)
print("gender data shape: {}".format(gender_binary.shape[0]))
print("age data shape: {}".format(age_clean.shape[0]))
return age_clean, gender_binary
def import_key_data(path):
gender=[]
age=[]
labels=[]
ecg_filenames=[]
for subdir, dirs, files in sorted(os.walk(path)):
for filename in files:
filepath = subdir + os.sep + filename
if filepath.endswith(".mat"):
data, header_data = load_challenge_data(filepath)
labels.append(header_data[15][5:-1])
ecg_filenames.append(filepath)
gender.append(header_data[14][6:-1])
age.append(header_data[13][6:-1])
return gender, age, labels, ecg_filenames
def get_signal_lengths(path, title):
signal_lenght=[]
for subdir, dirs, files in sorted(os.walk(path)):
for filename in files:
filepath = subdir + os.sep + filename
if filepath.endswith(".mat"):
data, header_data = load_challenge_data(filepath)
splitted = header_data[0].split()
signal_lenght.append(splitted[3])
signal_lenght_df = pd.DataFrame(signal_lenght)
signal_count=signal_lenght_df[0].value_counts()
plt.figure(figsize=(20,10))
plt.title(title,fontsize =36)
sns.barplot(signal_count[:10,].index, signal_count[:10,].values)
#plt.savefig("signallengde.png")
def make_undefined_class(labels, df_unscored):
df_labels = pd.DataFrame(labels)
for i in range(len(df_unscored.iloc[0:,1])):
df_labels.replace(to_replace=str(df_unscored.iloc[i,1]), inplace=True ,value="undefined class", regex=True)
'''
#equivalent classes
codes_to_replace=['713427006','284470004','427172004']
replace_with = ['59118001','63593006','17338001']
for i in range(len(codes_to_replace)):
df_labels.replace(to_replace=codes_to_replace[i], inplace=True ,value=replace_with[i], regex=True)
'''
return df_labels
def onehot_encode(df_labels):
one_hot = MultiLabelBinarizer()
y=one_hot.fit_transform(df_labels[0].str.split(pat=','))
print("The classes we will look at are encoded as SNOMED CT codes:")
print(one_hot.classes_)
y = np.delete(y, -1, axis=1)
print("classes: {}".format(y.shape[1]))
return y, one_hot.classes_[0:-1]
def plot_classes(classes, scored_classes,y):
for j in range(len(classes)):
for i in range(len(scored_classes.iloc[:,1])):
if (str(scored_classes.iloc[:,1][i]) == classes[j]):
classes[j] = scored_classes.iloc[:,0][i]
plt.figure(figsize=(30,20))
plt.bar(x=classes,height=y.sum(axis=0))
plt.title("Distribution of Diagnosis", color = "black", fontsize = 30)
plt.tick_params(axis="both", colors = "black")
plt.xlabel("Diagnosis", color = "black")
plt.ylabel("Count", color = "black")
plt.xticks(rotation=90, fontsize=20)
plt.yticks(fontsize = 20)
plt.savefig("fordeling.png")
plt.show()
def get_labels_for_all_combinations(y):
y_all_combinations = LabelEncoder().fit_transform([''.join(str(l)) for l in y])
return y_all_combinations
def split_data(labels, y_all_combo):
folds = list(StratifiedKFold(n_splits=10, shuffle=True, random_state=42).split(labels,y_all_combo))
print("Training split: {}".format(len(folds[0][0])))
print("Validation split: {}".format(len(folds[0][1])))
return folds
def plot_all_folds(folds,y,onehot_enc):
X_axis_labels=onehot_enc
plt.figure(figsize=(20,100))
h=1
for i in range(len(folds)):
plt.subplot(10,2,h)
plt.subplots_adjust(hspace=1.0)
plt.bar(x= X_axis_labels, height=y[folds[i][0]].sum(axis=0))
plt.title("Distribution of Diagnosis - Training set - Fold {}".format(i+1) ,fontsize="20", color = "black")
plt.tick_params(axis="both", colors = "black")
plt.xticks(rotation=90, fontsize=10)
plt.yticks(fontsize = 10)
#plt.xlabel("Diagnosis", color = "white")
plt.ylabel("Count", color = "black")
h=h+1
plt.subplot(10,2,h)
plt.subplots_adjust(hspace=1.0)
plt.bar(x= X_axis_labels, height=y[folds[i][1]].sum(axis=0))
plt.title("Distribution of Diagnosis - Validation set - Fold {}".format(i+1) ,fontsize="20", color = "black")
plt.tick_params(axis="both", colors = "black")
#plt.xlabel("Diagnosis", color = "white")
plt.ylabel("Count", color = "black")
plt.xticks(rotation=90, fontsize=10)
plt.yticks(fontsize = 10)
h=h+1
def get_val_data(validation_filename):
ecg_val_timeseries=[]
for names in validation_filename:
data, header_data = pc.load_challenge_data(names)
data = pad_sequences(data, maxlen=5000, truncating='post',padding="post")
ecg_val_timeseries.append(data)
ecg_val_timeseries = np.asarray(ecg_val_timeseries)
return ecg_val_timeseries
def generate_validation_data(ecg_filenames, y,test_order_array):
y_train_gridsearch=y[test_order_array]
ecg_filenames_train_gridsearch=ecg_filenames[test_order_array]
ecg_train_timeseries=[]
for names in ecg_filenames_train_gridsearch:
data, header_data = load_challenge_data(names)
data = pad_sequences(data, maxlen=5000, truncating='post',padding="post")
ecg_train_timeseries.append(data)
X_train_gridsearch = np.asarray(ecg_train_timeseries)
X_train_gridsearch = X_train_gridsearch.reshape(ecg_filenames_train_gridsearch.shape[0],5000,12)
return X_train_gridsearch, y_train_gridsearch
def generate_validation_data_with_demo_data(ecg_filenames, y, gender, age, test_order_array):
y_train_gridsearch=y[test_order_array]
ecg_filenames_train_gridsearch=ecg_filenames[test_order_array]
ecg_train_timeseries=[]
for names in ecg_filenames_train_gridsearch:
data, header_data = load_challenge_data(names)
data = pad_sequences(data, maxlen=5000, truncating='post',padding="post")
ecg_train_timeseries.append(data)
X_val = np.asarray(ecg_train_timeseries)
X_val = X_val.reshape(ecg_filenames_train_gridsearch.shape[0],5000,12)
age_val = age[test_order_array]
gender_val = gender[test_order_array]
demograpics_val_data = np.column_stack((age_val, gender_val))
X_combined_val = [X_val, demograpics_val_data]
return X_combined_val, y_train_gridsearch
def calculating_class_weights(y_true):
number_dim = np.shape(y_true)[1]
weights = np.empty([number_dim, 2])
for i in range(number_dim):
weights[i] = compute_class_weight('balanced', [0.,1.], y_true[:, i])
return weights
def residual_network_1d():
n_feature_maps = 64
input_shape = (5000,12)
input_layer = keras.layers.Input(input_shape)
# BLOCK 1
conv_x = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=8, padding='same')(input_layer)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# expand channels for the sum
shortcut_y = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=1, padding='same')(input_layer)
shortcut_y = keras.layers.BatchNormalization()(shortcut_y)
output_block_1 = keras.layers.add([shortcut_y, conv_z])
output_block_1 = keras.layers.Activation('relu')(output_block_1)
# BLOCK 2
conv_x = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=8, padding='same')(output_block_1)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# expand channels for the sum
shortcut_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=1, padding='same')(output_block_1)
shortcut_y = keras.layers.BatchNormalization()(shortcut_y)
output_block_2 = keras.layers.add([shortcut_y, conv_z])
output_block_2 = keras.layers.Activation('relu')(output_block_2)
# BLOCK 3
conv_x = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=8, padding='same')(output_block_2)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# no need to expand channels because they are equal
shortcut_y = keras.layers.BatchNormalization()(output_block_2)
output_block_3 = keras.layers.add([shortcut_y, conv_z])
output_block_3 = keras.layers.Activation('relu')(output_block_3)
# FINAL
gap_layer = keras.layers.GlobalAveragePooling1D()(output_block_3)
output_layer = keras.layers.Dense(27, activation='softmax')(gap_layer)
model = keras.models.Model(inputs=input_layer, outputs=output_layer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def encoder_model():
input_layer = keras.layers.Input(shape=(5000, 12))
# conv block -1
conv1 = keras.layers.Conv1D(filters=128,kernel_size=5,strides=1,padding='same')(input_layer)
conv1 = tfa.layers.InstanceNormalization()(conv1)
conv1 = keras.layers.PReLU(shared_axes=[1])(conv1)
conv1 = keras.layers.Dropout(rate=0.2)(conv1)
conv1 = keras.layers.MaxPooling1D(pool_size=2)(conv1)
# conv block -2
conv2 = keras.layers.Conv1D(filters=256,kernel_size=11,strides=1,padding='same')(conv1)
conv2 = tfa.layers.InstanceNormalization()(conv2)
conv2 = keras.layers.PReLU(shared_axes=[1])(conv2)
conv2 = keras.layers.Dropout(rate=0.2)(conv2)
conv2 = keras.layers.MaxPooling1D(pool_size=2)(conv2)
# conv block -3
conv3 = keras.layers.Conv1D(filters=512,kernel_size=21,strides=1,padding='same')(conv2)
conv3 = tfa.layers.InstanceNormalization()(conv3)
conv3 = keras.layers.PReLU(shared_axes=[1])(conv3)
conv3 = keras.layers.Dropout(rate=0.2)(conv3)
# split for attention
attention_data = keras.layers.Lambda(lambda x: x[:,:,:256])(conv3)
attention_softmax = keras.layers.Lambda(lambda x: x[:,:,256:])(conv3)
# attention mechanism
attention_softmax = keras.layers.Softmax()(attention_softmax)
multiply_layer = keras.layers.Multiply()([attention_softmax,attention_data])
# last layer
dense_layer = keras.layers.Dense(units=256,activation='sigmoid')(multiply_layer)
dense_layer = tfa.layers.InstanceNormalization()(dense_layer)
# output layer
flatten_layer = keras.layers.Flatten()(dense_layer)
output_layer = keras.layers.Dense(units=27,activation='sigmoid')(flatten_layer)
model = keras.models.Model(inputs=input_layer, outputs=output_layer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def FCN():
inputlayer = keras.layers.Input(shape=(5000,12))
conv1 = keras.layers.Conv1D(filters=128, kernel_size=8,input_shape=(5000,12), padding='same')(inputlayer)
conv1 = keras.layers.BatchNormalization()(conv1)
conv1 = keras.layers.Activation(activation='relu')(conv1)
conv2 = keras.layers.Conv1D(filters=256, kernel_size=5, padding='same')(conv1)
conv2 = keras.layers.BatchNormalization()(conv2)
conv2 = keras.layers.Activation('relu')(conv2)
conv3 = keras.layers.Conv1D(128, kernel_size=3,padding='same')(conv2)
conv3 = keras.layers.BatchNormalization()(conv3)
conv3 = keras.layers.Activation('relu')(conv3)
gap_layer = keras.layers.GlobalAveragePooling1D()(conv3)
outputlayer = keras.layers.Dense(27, activation='sigmoid')(gap_layer)
model = keras.Model(inputs=inputlayer, outputs=outputlayer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def residual_network_1d_demo():
n_feature_maps = 64
input_shape = (5000,12)
inputA = keras.layers.Input(input_shape)
inputB = keras.layers.Input(shape=(2,))
# BLOCK 1
conv_x = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=8, padding='same')(inputA)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# expand channels for the sum
shortcut_y = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=1, padding='same')(inputA)
shortcut_y = keras.layers.BatchNormalization()(shortcut_y)
output_block_1 = keras.layers.add([shortcut_y, conv_z])
output_block_1 = keras.layers.Activation('relu')(output_block_1)
# BLOCK 2
conv_x = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=8, padding='same')(output_block_1)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# expand channels for the sum
shortcut_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=1, padding='same')(output_block_1)
shortcut_y = keras.layers.BatchNormalization()(shortcut_y)
output_block_2 = keras.layers.add([shortcut_y, conv_z])
output_block_2 = keras.layers.Activation('relu')(output_block_2)
# BLOCK 3
conv_x = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=8, padding='same')(output_block_2)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# no need to expand channels because they are equal
shortcut_y = keras.layers.BatchNormalization()(output_block_2)
output_block_3 = keras.layers.add([shortcut_y, conv_z])
output_block_3 = keras.layers.Activation('relu')(output_block_3)
# FINAL
gap_layer = keras.layers.GlobalAveragePooling1D()(output_block_3)
output_layer = keras.layers.Dense(27, activation='softmax')(gap_layer)
mod1 = keras.models.Model(inputs=inputA, outputs=output_layer)
mod2 = keras.layers.Dense(50, activation="relu")(inputB)
mod2 = keras.layers.Dense(2, activation="sigmoid")(mod2)
mod2 = keras.models.Model(inputs=inputB, outputs=mod2)
combined = keras.layers.concatenate([mod1.output, mod2.output])
z = keras.layers.Dense(27, activation="sigmoid")(combined)
model = keras.models.Model(inputs=[mod1.input, mod2.input], outputs=z)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def encoder_model_demo():
inputA = keras.layers.Input(shape=(5000, 12))
inputB = keras.layers.Input(shape=(2,))
# conv block -1
conv1 = keras.layers.Conv1D(filters=128,kernel_size=5,strides=1,padding='same')(inputA)
conv1 = tfa.layers.InstanceNormalization()(conv1)
conv1 = keras.layers.PReLU(shared_axes=[1])(conv1)
conv1 = keras.layers.Dropout(rate=0.2)(conv1)
conv1 = keras.layers.MaxPooling1D(pool_size=2)(conv1)
# conv block -2
conv2 = keras.layers.Conv1D(filters=256,kernel_size=11,strides=1,padding='same')(conv1)
conv2 = tfa.layers.InstanceNormalization()(conv2)
conv2 = keras.layers.PReLU(shared_axes=[1])(conv2)
conv2 = keras.layers.Dropout(rate=0.2)(conv2)
conv2 = keras.layers.MaxPooling1D(pool_size=2)(conv2)
# conv block -3
conv3 = keras.layers.Conv1D(filters=512,kernel_size=21,strides=1,padding='same')(conv2)
conv3 = tfa.layers.InstanceNormalization()(conv3)
conv3 = keras.layers.PReLU(shared_axes=[1])(conv3)
conv3 = keras.layers.Dropout(rate=0.2)(conv3)
# split for attention
attention_data = keras.layers.Lambda(lambda x: x[:,:,:256])(conv3)
attention_softmax = keras.layers.Lambda(lambda x: x[:,:,256:])(conv3)
# attention mechanism
attention_softmax = keras.layers.Softmax()(attention_softmax)
multiply_layer = keras.layers.Multiply()([attention_softmax,attention_data])
# last layer
dense_layer = keras.layers.Dense(units=256,activation='sigmoid')(multiply_layer)
dense_layer = tfa.layers.InstanceNormalization()(dense_layer)
# output layer
output_layer = keras.layers.Flatten()(dense_layer)
mod1 = keras.Model(inputs=inputA, outputs=output_layer)
mod2 = keras.layers.Dense(50, activation="relu")(inputB)
mod2 = keras.layers.Dense(2, activation="sigmoid")(mod2)
mod2 = keras.models.Model(inputs=inputB, outputs=mod2)
combined = keras.layers.concatenate([mod1.output, mod2.output])
z = keras.layers.Dense(27, activation="sigmoid")(combined)
model = keras.models.Model(inputs=[mod1.input, mod2.input], outputs=z)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(learning_rate=0.01), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def FCN_demo():
inputA = keras.layers.Input(shape=(5000,12))
inputB = keras.layers.Input(shape=(2,))
conv1 = keras.layers.Conv1D(filters=128, kernel_size=8,input_shape=(5000,12), padding='same')(inputA)
conv1 = keras.layers.BatchNormalization()(conv1)
conv1 = keras.layers.Activation(activation='relu')(conv1)
conv2 = keras.layers.Conv1D(filters=256, kernel_size=5, padding='same')(conv1)
conv2 = keras.layers.BatchNormalization()(conv2)
conv2 = keras.layers.Activation('relu')(conv2)
conv3 = keras.layers.Conv1D(128, kernel_size=3,padding='same')(conv2)
conv3 = keras.layers.BatchNormalization()(conv3)
conv3 = keras.layers.Activation('relu')(conv3)
gap_layer = keras.layers.GlobalAveragePooling1D()(conv3)
model1 = keras.Model(inputs=inputA, outputs=gap_layer)
mod3 = keras.layers.Dense(50, activation="relu")(inputB)
mod3 = keras.layers.Dense(2, activation="sigmoid")(mod3)
model3 = keras.Model(inputs=inputB, outputs=mod3)
combined = keras.layers.concatenate([model1.output, model3.output])
final_layer = keras.layers.Dense(27, activation="sigmoid")(combined)
model = keras.models.Model(inputs=[inputA,inputB], outputs=final_layer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def FCN_Encoder():
inputA = tf.keras.layers.Input(shape=(5000,12))
conv1 = keras.layers.Conv1D(filters=128, kernel_size=8,input_shape=(5000,12), padding='same')(inputA)
conv1 = keras.layers.BatchNormalization()(conv1)
conv1 = keras.layers.Activation(activation='relu')(conv1)
conv2 = keras.layers.Conv1D(filters=256, kernel_size=5, padding='same')(conv1)
conv2 = keras.layers.BatchNormalization()(conv2)
conv2 = keras.layers.Activation('relu')(conv2)
conv3 = keras.layers.Conv1D(128, kernel_size=3,padding='same')(conv2)
conv3 = keras.layers.BatchNormalization()(conv3)
conv3 = keras.layers.Activation('relu')(conv3)
gap_layer = keras.layers.GlobalAveragePooling1D()(conv3)
model1 = keras.Model(inputs=inputA, outputs=gap_layer)
conv1 = keras.layers.Conv1D(filters=128,kernel_size=5,strides=1,padding='same')(inputA)
conv1 = tfa.layers.InstanceNormalization()(conv1)
conv1 = keras.layers.PReLU(shared_axes=[1])(conv1)
conv1 = keras.layers.Dropout(rate=0.2)(conv1)
conv1 = keras.layers.MaxPooling1D(pool_size=2)(conv1)
# conv block -2
conv2 = keras.layers.Conv1D(filters=256,kernel_size=11,strides=1,padding='same')(conv1)
conv2 = tfa.layers.InstanceNormalization()(conv2)
conv2 = keras.layers.PReLU(shared_axes=[1])(conv2)
conv2 = keras.layers.Dropout(rate=0.2)(conv2)
conv2 = keras.layers.MaxPooling1D(pool_size=2)(conv2)
# conv block -3
conv3 = keras.layers.Conv1D(filters=512,kernel_size=21,strides=1,padding='same')(conv2)
conv3 = tfa.layers.InstanceNormalization()(conv3)
conv3 = keras.layers.PReLU(shared_axes=[1])(conv3)
conv3 = keras.layers.Dropout(rate=0.2)(conv3)
# split for attention
attention_data = keras.layers.Lambda(lambda x: x[:,:,:256])(conv3)
attention_softmax = keras.layers.Lambda(lambda x: x[:,:,256:])(conv3)
# attention mechanism
attention_softmax = keras.layers.Softmax()(attention_softmax)
multiply_layer = keras.layers.Multiply()([attention_softmax,attention_data])
# last layer
dense_layer = keras.layers.Dense(units=256,activation='sigmoid')(multiply_layer)
dense_layer = tfa.layers.InstanceNormalization()(dense_layer)
# output layer
flatten_layer = keras.layers.Flatten()(dense_layer)
model2 = keras.Model(inputs=inputA, outputs=flatten_layer)
combined = keras.layers.concatenate([model1.output, model2.output])
final_layer = keras.layers.Dense(27, activation="sigmoid")(combined)
model = keras.models.Model(inputs=inputA, outputs=final_layer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def FCN_Encoder_demo():
inputA = keras.layers.Input(shape=(5000,12))
inputB = keras.layers.Input(shape=(2,))
conv1 = keras.layers.Conv1D(filters=128, kernel_size=8,input_shape=(5000,12), padding='same')(inputA)
conv1 = keras.layers.BatchNormalization()(conv1)
conv1 = keras.layers.Activation(activation='relu')(conv1)
conv2 = keras.layers.Conv1D(filters=256, kernel_size=5, padding='same')(conv1)
conv2 = keras.layers.BatchNormalization()(conv2)
conv2 = keras.layers.Activation('relu')(conv2)
conv3 = keras.layers.Conv1D(128, kernel_size=3,padding='same')(conv2)
conv3 = keras.layers.BatchNormalization()(conv3)
conv3 = keras.layers.Activation('relu')(conv3)
gap_layer = keras.layers.GlobalAveragePooling1D()(conv3)
model1 = keras.Model(inputs=inputA, outputs=gap_layer)
conv1 = keras.layers.Conv1D(filters=256,kernel_size=10,strides=1,padding='same')(inputA)
conv1 = tfa.layers.InstanceNormalization()(conv1)
conv1 = keras.layers.PReLU(shared_axes=[1])(conv1)
conv1 = keras.layers.Dropout(rate=0.2)(conv1)
conv1 = keras.layers.MaxPooling1D(pool_size=2)(conv1)
# conv block -2
conv2 = keras.layers.Conv1D(filters=512,kernel_size=22,strides=1,padding='same')(conv1)
conv2 = tfa.layers.InstanceNormalization()(conv2)
conv2 = keras.layers.PReLU(shared_axes=[1])(conv2)
conv2 = keras.layers.Dropout(rate=0.2)(conv2)
conv2 = keras.layers.MaxPooling1D(pool_size=2)(conv2)
# conv block -3
conv3 = keras.layers.Conv1D(filters=1024,kernel_size=42,strides=1,padding='same')(conv2)
conv3 = tfa.layers.InstanceNormalization()(conv3)
conv3 = keras.layers.PReLU(shared_axes=[1])(conv3)
conv3 = keras.layers.Dropout(rate=0.2)(conv3)
# split for attention
attention_data = keras.layers.Lambda(lambda x: x[:,:,:512])(conv3)
attention_softmax = keras.layers.Lambda(lambda x: x[:,:,512:])(conv3)
# attention mechanism
attention_softmax = keras.layers.Softmax()(attention_softmax)
multiply_layer = keras.layers.Multiply()([attention_softmax,attention_data])
# last layer
dense_layer = keras.layers.Dense(units=512,activation='sigmoid')(multiply_layer)
dense_layer = tfa.layers.InstanceNormalization()(dense_layer)
# output layer
flatten_layer = keras.layers.Flatten()(dense_layer)
model2 = keras.Model(inputs=inputA, outputs=flatten_layer)
mod3 = keras.layers.Dense(50, activation="relu")(inputB) # 2 -> 100
mod3 = keras.layers.Dense(2, activation="sigmoid")(mod3) # Added this layer
model3 = keras.Model(inputs=inputB, outputs=mod3)
combined = keras.layers.concatenate([model1.output, model2.output, model3.output])
final_layer = keras.layers.Dense(27, activation="sigmoid")(combined)
model = keras.models.Model(inputs=[inputA,inputB], outputs=final_layer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def compute_challenge_metric_for_opt(labels, outputs):
classes=['10370003','111975006','164889003','164890007','164909002','164917005','164934002','164947007','17338001',
'251146004','270492004','284470004','39732003','426177001','426627000','426783006','427084000','427172004','427393009','445118002','47665007','59118001',
'59931005','63593006','698252002','713426002','713427006']
'''
24 classes
['10370003', '111975006', '164889003', '164890007', '164909002', '164917005',
'164934002', '164947007', '17338001', '251146004', '270492004', '39732003',
'426177001', '426627000', '426783006' ,'427084000' ,'427393009', '445118002',
'47665007' ,'59118001', '59931005', '63593006', '698252002', '713426002']
'''
normal_class = '426783006'
weights = np.array([[1. , 0.425 , 0.375 , 0.375 , 0.4 , 0.275 , 0.375 , 0.425 ,
0.5 , 0.45 , 0.425 , 0.4625, 0.475 , 0.425 , 0.425 , 0.375 ,
0.5 , 0.5 , 0.425 , 0.475 , 0.475 , 0.475 , 0.375 , 0.4625,
0.475 , 0.425 , 0.475 ],
[0.425 , 1. , 0.45 , 0.45 , 0.475 , 0.35 , 0.45 , 0.35 ,
0.425 , 0.475 , 0.35 , 0.3875, 0.4 , 0.35 , 0.35 , 0.3 ,
0.425 , 0.425 , 0.35 , 0.4 , 0.4 , 0.45 , 0.45 , 0.3875,
0.4 , 0.35 , 0.45 ],
[0.375 , 0.45 , 1. , 0.5 , 0.475 , 0.4 , 0.5 , 0.3 ,
0.375 , 0.425 , 0.3 , 0.3375, 0.35 , 0.3 , 0.3 , 0.25 ,
0.375 , 0.375 , 0.3 , 0.35 , 0.35 , 0.4 , 0.5 , 0.3375,
0.35 , 0.3 , 0.4 ],
[0.375 , 0.45 , 0.5 , 1. , 0.475 , 0.4 , 0.5 , 0.3 ,
0.375 , 0.425 , 0.3 , 0.3375, 0.35 , 0.3 , 0.3 , 0.25 ,
0.375 , 0.375 , 0.3 , 0.35 , 0.35 , 0.4 , 0.5 , 0.3375,
0.35 , 0.3 , 0.4 ],
[0.4 , 0.475 , 0.475 , 0.475 , 1. , 0.375 , 0.475 , 0.325 ,
0.4 , 0.45 , 0.325 , 0.3625, 0.375 , 0.325 , 0.325 , 0.275 ,
0.4 , 0.4 , 0.325 , 0.375 , 0.375 , 0.425 , 0.475 , 0.3625,
0.375 , 0.325 , 0.425 ],
[0.275 , 0.35 , 0.4 , 0.4 , 0.375 , 1. , 0.4 , 0.2 ,
0.275 , 0.325 , 0.2 , 0.2375, 0.25 , 0.2 , 0.2 , 0.15 ,
0.275 , 0.275 , 0.2 , 0.25 , 0.25 , 0.3 , 0.4 , 0.2375,
0.25 , 0.2 , 0.3 ],
[0.375 , 0.45 , 0.5 , 0.5 , 0.475 , 0.4 , 1. , 0.3 ,
0.375 , 0.425 , 0.3 , 0.3375, 0.35 , 0.3 , 0.3 , 0.25 ,
0.375 , 0.375 , 0.3 , 0.35 , 0.35 , 0.4 , 0.5 , 0.3375,
0.35 , 0.3 , 0.4 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 1. ,
0.425 , 0.375 , 0.5 , 0.4625, 0.45 , 0.5 , 0.5 , 0.45 ,
0.425 , 0.425 , 0.5 , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 0.5 , 0.4 ],
[0.5 , 0.425 , 0.375 , 0.375 , 0.4 , 0.275 , 0.375 , 0.425 ,
1. , 0.45 , 0.425 , 0.4625, 0.475 , 0.425 , 0.425 , 0.375 ,
0.5 , 1. , 0.425 , 0.475 , 0.475 , 0.475 , 0.375 , 0.4625,
0.475 , 0.425 , 0.475 ],
[0.45 , 0.475 , 0.425 , 0.425 , 0.45 , 0.325 , 0.425 , 0.375 ,
0.45 , 1. , 0.375 , 0.4125, 0.425 , 0.375 , 0.375 , 0.325 ,
0.45 , 0.45 , 0.375 , 0.425 , 0.425 , 0.475 , 0.425 , 0.4125,
0.425 , 0.375 , 0.475 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 0.5 ,
0.425 , 0.375 , 1. , 0.4625, 0.45 , 0.5 , 0.5 , 0.45 ,
0.425 , 0.425 , 0.5 , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 0.5 , 0.4 ],
[0.4625, 0.3875, 0.3375, 0.3375, 0.3625, 0.2375, 0.3375, 0.4625,
0.4625, 0.4125, 0.4625, 1. , 0.4875, 0.4625, 0.4625, 0.4125,
0.4625, 0.4625, 0.4625, 0.4875, 0.4875, 0.4375, 0.3375, 1. ,
0.4875, 0.4625, 0.4375],
[0.475 , 0.4 , 0.35 , 0.35 , 0.375 , 0.25 , 0.35 , 0.45 ,
0.475 , 0.425 , 0.45 , 0.4875, 1. , 0.45 , 0.45 , 0.4 ,
0.475 , 0.475 , 0.45 , 0.5 , 0.5 , 0.45 , 0.35 , 0.4875,
0.5 , 0.45 , 0.45 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 0.5 ,
0.425 , 0.375 , 0.5 , 0.4625, 0.45 , 1. , 0.5 , 0.45 ,
0.425 , 0.425 , 0.5 , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 0.5 , 0.4 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 0.5 ,
0.425 , 0.375 , 0.5 , 0.4625, 0.45 , 0.5 , 1. , 0.45 ,
0.425 , 0.425 , 0.5 , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 0.5 , 0.4 ],
[0.375 , 0.3 , 0.25 , 0.25 , 0.275 , 0.15 , 0.25 , 0.45 ,
0.375 , 0.325 , 0.45 , 0.4125, 0.4 , 0.45 , 0.45 , 1. ,
0.375 , 0.375 , 0.45 , 0.4 , 0.4 , 0.35 , 0.25 , 0.4125,
0.4 , 0.45 , 0.35 ],
[0.5 , 0.425 , 0.375 , 0.375 , 0.4 , 0.275 , 0.375 , 0.425 ,
0.5 , 0.45 , 0.425 , 0.4625, 0.475 , 0.425 , 0.425 , 0.375 ,
1. , 0.5 , 0.425 , 0.475 , 0.475 , 0.475 , 0.375 , 0.4625,
0.475 , 0.425 , 0.475 ],
[0.5 , 0.425 , 0.375 , 0.375 , 0.4 , 0.275 , 0.375 , 0.425 ,
1. , 0.45 , 0.425 , 0.4625, 0.475 , 0.425 , 0.425 , 0.375 ,
0.5 , 1. , 0.425 , 0.475 , 0.475 , 0.475 , 0.375 , 0.4625,
0.475 , 0.425 , 0.475 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 0.5 ,
0.425 , 0.375 , 0.5 , 0.4625, 0.45 , 0.5 , 0.5 , 0.45 ,
0.425 , 0.425 , 1. , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 0.5 , 0.4 ],
[0.475 , 0.4 , 0.35 , 0.35 , 0.375 , 0.25 , 0.35 , 0.45 ,
0.475 , 0.425 , 0.45 , 0.4875, 0.5 , 0.45 , 0.45 , 0.4 ,
0.475 , 0.475 , 0.45 , 1. , 0.5 , 0.45 , 0.35 , 0.4875,
0.5 , 0.45 , 0.45 ],
[0.475 , 0.4 , 0.35 , 0.35 , 0.375 , 0.25 , 0.35 , 0.45 ,
0.475 , 0.425 , 0.45 , 0.4875, 0.5 , 0.45 , 0.45 , 0.4 ,
0.475 , 0.475 , 0.45 , 0.5 , 1. , 0.45 , 0.35 , 0.4875,
0.5 , 0.45 , 0.45 ],
[0.475 , 0.45 , 0.4 , 0.4 , 0.425 , 0.3 , 0.4 , 0.4 ,
0.475 , 0.475 , 0.4 , 0.4375, 0.45 , 0.4 , 0.4 , 0.35 ,
0.475 , 0.475 , 0.4 , 0.45 , 0.45 , 1. , 0.4 , 0.4375,
0.45 , 0.4 , 1. ],
[0.375 , 0.45 , 0.5 , 0.5 , 0.475 , 0.4 , 0.5 , 0.3 ,
0.375 , 0.425 , 0.3 , 0.3375, 0.35 , 0.3 , 0.3 , 0.25 ,
0.375 , 0.375 , 0.3 , 0.35 , 0.35 , 0.4 , 1. , 0.3375,
0.35 , 0.3 , 0.4 ],
[0.4625, 0.3875, 0.3375, 0.3375, 0.3625, 0.2375, 0.3375, 0.4625,
0.4625, 0.4125, 0.4625, 1. , 0.4875, 0.4625, 0.4625, 0.4125,
0.4625, 0.4625, 0.4625, 0.4875, 0.4875, 0.4375, 0.3375, 1. ,
0.4875, 0.4625, 0.4375],
[0.475 , 0.4 , 0.35 , 0.35 , 0.375 , 0.25 , 0.35 , 0.45 ,
0.475 , 0.425 , 0.45 , 0.4875, 0.5 , 0.45 , 0.45 , 0.4 ,
0.475 , 0.475 , 0.45 , 0.5 , 0.5 , 0.45 , 0.35 , 0.4875,
1. , 0.45 , 0.45 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 0.5 ,
0.425 , 0.375 , 0.5 , 0.4625, 0.45 , 0.5 , 0.5 , 0.45 ,
0.425 , 0.425 , 0.5 , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 1. , 0.4 ],
[0.475 , 0.45 , 0.4 , 0.4 , 0.425 , 0.3 , 0.4 , 0.4 ,
0.475 , 0.475 , 0.4 , 0.4375, 0.45 , 0.4 , 0.4 , 0.35 ,
0.475 , 0.475 , 0.4 , 0.45 , 0.45 , 1. , 0.4 , 0.4375,
0.45 , 0.4 , 1. ]])
num_recordings, num_classes = np.shape(labels)
normal_index = classes.index(normal_class)
# Compute the observed score.
A = compute_modified_confusion_matrix(labels, outputs)
observed_score = np.nansum(weights * A)
# Compute the score for the model that always chooses the correct label(s).
correct_outputs = labels
A = compute_modified_confusion_matrix(labels, correct_outputs)
correct_score = np.nansum(weights * A)
# Compute the score for the model that always chooses the normal class.
inactive_outputs = np.zeros((num_recordings, num_classes), dtype=np.bool)
inactive_outputs[:, normal_index] = 1
A = compute_modified_confusion_matrix(labels, inactive_outputs)
inactive_score = np.nansum(weights * A)
if correct_score != inactive_score:
normalized_score = float(observed_score - inactive_score) / float(correct_score - inactive_score)
else:
normalized_score = float('nan')
return normalized_score
def compute_modified_confusion_matrix(labels, outputs):
# Compute a binary multi-class, multi-label confusion matrix, where the rows
# are the labels and the columns are the outputs.
num_recordings, num_classes = np.shape(labels)
A = np.zeros((num_classes, num_classes))
# Iterate over all of the recordings.
for i in range(num_recordings):
# Calculate the number of positive labels and/or outputs.
normalization = float(max(np.sum(np.any((labels[i, :], outputs[i, :]), axis=0)), 1))
# Iterate over all of the classes.
for j in range(num_classes):
# Assign full and/or partial credit for each positive class.
if labels[i, j]:
for k in range(num_classes):
if outputs[i, k]:
A[j, k] += 1.0/normalization
return A
def iterate_threshold(y_pred, ecg_filenames, y ,val_fold ):
init_thresholds = np.arange(0,1,0.05)
all_scores = []
for i in init_thresholds:
pred_output = y_pred > i
pred_output = pred_output * 1
score = compute_challenge_metric_for_opt(generate_validation_data(ecg_filenames,y,val_fold)[1],pred_output)
print(score)
all_scores.append(score)
all_scores = np.asarray(all_scores)
return all_scores
def plot_normalized_conf_matrix(y_pred, ecg_filenames, y, val_fold, threshold, snomedclasses, snomedabbr):
conf_m = compute_modified_confusion_matrix(generate_validation_data(ecg_filenames,y,val_fold)[1], (y_pred>threshold)*1)
conf_m = np.nan_to_num(conf_m)
#min_max_scaler = preprocessing.MinMaxScaler()
#conf_m_scaled = min_max_scaler.fit_transform(conf_m)
normalizer = preprocessing.Normalizer(norm="l1")
conf_m_scaled = normalizer.fit_transform(conf_m)
df_norm_col = pd.DataFrame(conf_m_scaled)
df_norm_col.columns = snomedabbr
df_norm_col.index = snomedabbr
df_norm_col.index.name = 'Actual'
df_norm_col.columns.name = 'Predicted'
#df_norm_col=(df_cm-df_cm.mean())/df_cm.std()
plt.figure(figsize = (12,10))
sns.set(font_scale=1.4)#for label size
sns.heatmap(df_norm_col, cmap="rocket_r", annot=True,cbar=False, annot_kws={"size": 10},fmt=".2f")#
#############################
#Adding rule-based algorithms
#############################
def DetectRWithPanTompkins (signal, signal_freq):
'''signal=ECG signal (type=np.array), signal_freq=sample frequenzy'''
lowcut = 5.0
highcut = 15.0
filter_order = 2
nyquist_freq = 0.5 * signal_freq
low = lowcut / nyquist_freq
high = highcut / nyquist_freq
b, a = butter(filter_order, [low, high], btype="band")
y = lfilter(b, a, signal)
diff_y=np.ediff1d(y)
squared_diff_y=diff_y**2
integrated_squared_diff_y =np.convolve(squared_diff_y,np.ones(5))
normalized = (integrated_squared_diff_y-min(integrated_squared_diff_y))/(max(integrated_squared_diff_y)-min(integrated_squared_diff_y))
peaks, metadata = find_peaks(normalized,
distance=signal_freq/5 ,
#height=500,
height=0.5,
width=0.5
)
return peaks
def heartrate(r_time, sampfreq):
#qrs = xqrs.qrs_inds from annotateR()
#sampfreq = sample frequency - can be found with y['fs'] (from getDataFromPhysionet())
HeartRate = []
TimeBetweenBeat= []
for index, item in enumerate(r_time,-1):
HeartRate.append(60/((r_time[index+1]-r_time[index])/sampfreq))
TimeBetweenBeat.append((r_time[index+1]-r_time[index])/sampfreq)
del HeartRate[0]
avgHr = sum(HeartRate)/len(HeartRate)
TimeBetweenBeat= np.asarray(TimeBetweenBeat)
TimeBetweenBeat=TimeBetweenBeat * 1000 # sec to ms
TimeBetweenBeat = TimeBetweenBeat[1:] # remove first element
return TimeBetweenBeat, avgHr
def R_correction(signal, peaks):
'''signal = ECG signal, peaks = uncorrected R peaks'''
peaks_corrected, metadata = find_peaks(signal, distance=min(np.diff(peaks)))
return peaks_corrected
def rule_based_predictions(ecgfilenames, val_data, dnn_prediction):
for i in range(len(val_data)):
data , header_data = load_challenge_data(ecgfilenames[val_data[i]])
avg_hr = 0
peaks = 0
rmssd = 0
qrs_voltage = 0
try:
peaks = DetectRWithPanTompkins(data[1],int(header_data[0].split()[2]))
try:
peaks = R_correction(data[1], peaks)
except:
print("Did not manage to do R_correction")
except:
print("Did not manage to find any peaks using Pan Tomkins")
try:
rr_interval, avg_hr = heartrate(peaks,int(header_data[0].split()[2]))
try:
rmssd = np.mean(np.square(np.diff(rr_interval)))
except:
print("did not manage to comp rmssd")
except:
print("not able to calculate heart rate")
rr_interval = 0
avg_hr = 0
try:
qrs_voltage = np.mean(data[1][peaks])
except:
print("Could not calculate mean QRS peak voltage")
if avg_hr != 0: # bare gjΓΈr disse endringene dersom vi klarer Γ₯ beregne puls
if 60 < avg_hr < 100:
dnn_prediction[i][16] = 0
dnn_prediction[i][14] = 0
dnn_prediction[i][13] = 0
elif avg_hr < 60 & dnn_prediction[i][15] == 1:
dnn_prediction[i][13] = 1
elif avg_hr < 60 & dnn_prediction[i][15] == 0:
dnn_prediction[i][14] = 1
elif avg_hr > 100:
dnn_prediction[i][16] = 1
if qrs_voltage != 0:
if qrs_voltage < 500:
dnn_prediction[i][9] = 1
dnn_prediction[i][15] = 0
else:
dnn_prediction[i][9] = 0
else:
dnn_prediction[i][9] = 0
if rmssd != 0:
if rmssd < 15:
dnn_prediction[i][0] = 1
dnn_prediction[i][16] = 0
dnn_prediction[i][15] = 0
dnn_prediction[i][14] = 0
dnn_prediction[i][13] = 0
elif 2000 < rmssd < 5000:
dnn_prediction[i][18] = 1
elif 15000 < rmssd < 50000:
dnn_prediction[i][2] = 1
else:
dnn_prediction[i][15] = 1
return dnn_prediction
def plot_normalized_conf_matrix_rule(y_true,val_data,rb_pred,snomedclasses):
df_cm = pd.DataFrame(compute_modified_confusion_matrix(y_true[val_data],rb_pred), columns=snomedclasses, index = snomedclasses)
df_cm = df_cm.fillna(0)
df_cm.index.name = 'Actual'
df_cm.columns.name = 'Predicted'
df_norm_col=(df_cm-df_cm.mean())/df_cm.std()
plt.figure(figsize = (36,14))
sns.set(font_scale=1.4)
sns.heatmap(df_norm_col, cmap="Blues", annot=True,annot_kws={"size": 16},fmt=".2f",cbar=False)# font size
import os
import numpy as np, sys,os
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.io import loadmat
import wfdb
import tarfile
from sklearn import preprocessing
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.model_selection import StratifiedKFold
from keras.preprocessing.sequence import pad_sequences
import math
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold
from sklearn.utils.class_weight import compute_class_weight
import tensorflow_addons as tfa
import tensorflow as tf
from tensorflow import keras
#from keras.utils import plot_model
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.signal import butter, lfilter, filtfilt
from scipy.signal import find_peaks
from scipy.signal import peak_widths
from scipy.signal import savgol_filter
def load_challenge_data(filename):
x = loadmat(filename)
data = np.asarray(x['val'], dtype=np.float64)
new_file = filename.replace('.mat','.hea')
input_header_file = os.path.join(new_file)
with open(input_header_file,'r') as f:
header_data=f.readlines()
return data, header_data
def clean_up_gender_data(gender):
gender = np.asarray(gender)
gender[np.where(gender "Male")] = 0
gender[np.where(gender "male")] = 0
gender[np.where(gender "M")] = 0
gender[np.where(gender "Female")] = 1
gender[np.where(gender "female")] = 1
gender[np.where(gender "F")] = 1
gender[np.where(gender "NaN")] = 2
np.unique(gender)
gender = gender.astype(np.int)
return gender
def clean_up_age_data(age):
age = np.asarray(age)
age[np.where(age "NaN")] = -1
np.unique(age)
age = age.astype(np.int)
return age
def import_gender_and_age(age, gender):
gender_binary = clean_up_gender_data(gender)
age_clean = clean_up_age_data(age)
print("gender data shape: {}".format(gender_binary.shape[0]))
print("age data shape: {}".format(age_clean.shape[0]))
return age_clean, gender_binary
def import_key_data(path):
gender=[]
age=[]
labels=[]
ecg_filenames=[]
for subdir, dirs, files in sorted(os.walk(path)):
for filename in files:
filepath = subdir + os.sep + filename
if filepath.endswith(".mat"):
data, header_data = load_challenge_data(filepath)
labels.append(header_data[15][5:-1])
ecg_filenames.append(filepath)
gender.append(header_data[14][6:-1])
age.append(header_data[13][6:-1])
return gender, age, labels, ecg_filenames
def get_signal_lengths(path, title):
signal_lenght=[]
for subdir, dirs, files in sorted(os.walk(path)):
for filename in files:
filepath = subdir + os.sep + filename
if filepath.endswith(".mat"):
data, header_data = load_challenge_data(filepath)
splitted = header_data[0].split()
signal_lenght.append(splitted[3])
signal_lenght_df = pd.DataFrame(signal_lenght)
signal_count=signal_lenght_df[0].value_counts()
plt.figure(figsize=(20,10))
plt.title(title,fontsize =36)
sns.barplot(signal_count[:10,].index, signal_count[:10,].values)
#plt.savefig("signallengde.png")
def make_undefined_class(labels, df_unscored):
df_labels = pd.DataFrame(labels)
for i in range(len(df_unscored.iloc[0:,1])):
df_labels.replace(to_replace=str(df_unscored.iloc[i,1]), inplace=True ,value="undefined class", regex=True)
'''
#equivalent classes
codes_to_replace=['713427006','284470004','427172004']
replace_with = ['59118001','63593006','17338001']
for i in range(len(codes_to_replace)):
df_labels.replace(to_replace=codes_to_replace[i], inplace=True ,value=replace_with[i], regex=True)
'''
return df_labels
def onehot_encode(df_labels):
one_hot = MultiLabelBinarizer()
y=one_hot.fit_transform(df_labels[0].str.split(pat=','))
print("The classes we will look at are encoded as SNOMED CT codes:")
print(one_hot.classes_)
y = np.delete(y, -1, axis=1)
print("classes: {}".format(y.shape[1]))
return y, one_hot.classes_[0:-1]
def plot_classes(classes, scored_classes,y):
for j in range(len(classes)):
for i in range(len(scored_classes.iloc[:,1])):
if (str(scored_classes.iloc[:,1][i]) == classes[j]):
classes[j] = scored_classes.iloc[:,0][i]
plt.figure(figsize=(30,20))
plt.bar(x=classes,height=y.sum(axis=0))
plt.title("Distribution of Diagnosis", color = "black", fontsize = 30)
plt.tick_params(axis="both", colors = "black")
plt.xlabel("Diagnosis", color = "black")
plt.ylabel("Count", color = "black")
plt.xticks(rotation=90, fontsize=20)
plt.yticks(fontsize = 20)
plt.savefig("fordeling.png")
plt.show()
def get_labels_for_all_combinations(y):
y_all_combinations = LabelEncoder().fit_transform([''.join(str(l)) for l in y])
return y_all_combinations
def split_data(labels, y_all_combo):
folds = list(StratifiedKFold(n_splits=10, shuffle=True, random_state=42).split(labels,y_all_combo))
print("Training split: {}".format(len(folds[0][0])))
print("Validation split: {}".format(len(folds[0][1])))
return folds
def plot_all_folds(folds,y,onehot_enc):
X_axis_labels=onehot_enc
plt.figure(figsize=(20,100))
h=1
for i in range(len(folds)):
plt.subplot(10,2,h)
plt.subplots_adjust(hspace=1.0)
plt.bar(x= X_axis_labels, height=y[folds[i][0]].sum(axis=0))
plt.title("Distribution of Diagnosis - Training set - Fold {}".format(i+1) ,fontsize="20", color = "black")
plt.tick_params(axis="both", colors = "black")
plt.xticks(rotation=90, fontsize=10)
plt.yticks(fontsize = 10)
#plt.xlabel("Diagnosis", color = "white")
plt.ylabel("Count", color = "black")
h=h+1
plt.subplot(10,2,h)
plt.subplots_adjust(hspace=1.0)
plt.bar(x= X_axis_labels, height=y[folds[i][1]].sum(axis=0))
plt.title("Distribution of Diagnosis - Validation set - Fold {}".format(i+1) ,fontsize="20", color = "black")
plt.tick_params(axis="both", colors = "black")
#plt.xlabel("Diagnosis", color = "white")
plt.ylabel("Count", color = "black")
plt.xticks(rotation=90, fontsize=10)
plt.yticks(fontsize = 10)
h=h+1
def get_val_data(validation_filename):
ecg_val_timeseries=[]
for names in validation_filename:
data, header_data = pc.load_challenge_data(names)
data = pad_sequences(data, maxlen=5000, truncating='post',padding="post")
ecg_val_timeseries.append(data)
ecg_val_timeseries = np.asarray(ecg_val_timeseries)
return ecg_val_timeseries
def generate_validation_data(ecg_filenames, y,test_order_array):
y_train_gridsearch=y[test_order_array]
ecg_filenames_train_gridsearch=ecg_filenames[test_order_array]
ecg_train_timeseries=[]
for names in ecg_filenames_train_gridsearch:
data, header_data = load_challenge_data(names)
data = pad_sequences(data, maxlen=5000, truncating='post',padding="post")
ecg_train_timeseries.append(data)
X_train_gridsearch = np.asarray(ecg_train_timeseries)
X_train_gridsearch = X_train_gridsearch.reshape(ecg_filenames_train_gridsearch.shape[0],5000,12)
return X_train_gridsearch, y_train_gridsearch
def generate_validation_data_with_demo_data(ecg_filenames, y, gender, age, test_order_array):
y_train_gridsearch=y[test_order_array]
ecg_filenames_train_gridsearch=ecg_filenames[test_order_array]
ecg_train_timeseries=[]
for names in ecg_filenames_train_gridsearch:
data, header_data = load_challenge_data(names)
data = pad_sequences(data, maxlen=5000, truncating='post',padding="post")
ecg_train_timeseries.append(data)
X_val = np.asarray(ecg_train_timeseries)
X_val = X_val.reshape(ecg_filenames_train_gridsearch.shape[0],5000,12)
age_val = age[test_order_array]
gender_val = gender[test_order_array]
demograpics_val_data = np.column_stack((age_val, gender_val))
X_combined_val = [X_val, demograpics_val_data]
return X_combined_val, y_train_gridsearch
def calculating_class_weights(y_true):
number_dim = np.shape(y_true)[1]
weights = np.empty([number_dim, 2])
for i in range(number_dim):
weights[i] = compute_class_weight('balanced', [0.,1.], y_true[:, i])
return weights
def residual_network_1d():
n_feature_maps = 64
input_shape = (5000,12)
input_layer = keras.layers.Input(input_shape)
# BLOCK 1
conv_x = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=8, padding='same')(input_layer)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# expand channels for the sum
shortcut_y = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=1, padding='same')(input_layer)
shortcut_y = keras.layers.BatchNormalization()(shortcut_y)
output_block_1 = keras.layers.add([shortcut_y, conv_z])
output_block_1 = keras.layers.Activation('relu')(output_block_1)
# BLOCK 2
conv_x = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=8, padding='same')(output_block_1)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# expand channels for the sum
shortcut_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=1, padding='same')(output_block_1)
shortcut_y = keras.layers.BatchNormalization()(shortcut_y)
output_block_2 = keras.layers.add([shortcut_y, conv_z])
output_block_2 = keras.layers.Activation('relu')(output_block_2)
# BLOCK 3
conv_x = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=8, padding='same')(output_block_2)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# no need to expand channels because they are equal
shortcut_y = keras.layers.BatchNormalization()(output_block_2)
output_block_3 = keras.layers.add([shortcut_y, conv_z])
output_block_3 = keras.layers.Activation('relu')(output_block_3)
# FINAL
gap_layer = keras.layers.GlobalAveragePooling1D()(output_block_3)
output_layer = keras.layers.Dense(27, activation='softmax')(gap_layer)
model = keras.models.Model(inputs=input_layer, outputs=output_layer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def encoder_model():
input_layer = keras.layers.Input(shape=(5000, 12))
# conv block -1
conv1 = keras.layers.Conv1D(filters=128,kernel_size=5,strides=1,padding='same')(input_layer)
conv1 = tfa.layers.InstanceNormalization()(conv1)
conv1 = keras.layers.PReLU(shared_axes=[1])(conv1)
conv1 = keras.layers.Dropout(rate=0.2)(conv1)
conv1 = keras.layers.MaxPooling1D(pool_size=2)(conv1)
# conv block -2
conv2 = keras.layers.Conv1D(filters=256,kernel_size=11,strides=1,padding='same')(conv1)
conv2 = tfa.layers.InstanceNormalization()(conv2)
conv2 = keras.layers.PReLU(shared_axes=[1])(conv2)
conv2 = keras.layers.Dropout(rate=0.2)(conv2)
conv2 = keras.layers.MaxPooling1D(pool_size=2)(conv2)
# conv block -3
conv3 = keras.layers.Conv1D(filters=512,kernel_size=21,strides=1,padding='same')(conv2)
conv3 = tfa.layers.InstanceNormalization()(conv3)
conv3 = keras.layers.PReLU(shared_axes=[1])(conv3)
conv3 = keras.layers.Dropout(rate=0.2)(conv3)
# split for attention
attention_data = keras.layers.Lambda(lambda x: x[:,:,:256])(conv3)
attention_softmax = keras.layers.Lambda(lambda x: x[:,:,256:])(conv3)
# attention mechanism
attention_softmax = keras.layers.Softmax()(attention_softmax)
multiply_layer = keras.layers.Multiply()([attention_softmax,attention_data])
# last layer
dense_layer = keras.layers.Dense(units=256,activation='sigmoid')(multiply_layer)
dense_layer = tfa.layers.InstanceNormalization()(dense_layer)
# output layer
flatten_layer = keras.layers.Flatten()(dense_layer)
output_layer = keras.layers.Dense(units=27,activation='sigmoid')(flatten_layer)
model = keras.models.Model(inputs=input_layer, outputs=output_layer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def FCN():
inputlayer = keras.layers.Input(shape=(5000,12))
conv1 = keras.layers.Conv1D(filters=128, kernel_size=8,input_shape=(5000,12), padding='same')(inputlayer)
conv1 = keras.layers.BatchNormalization()(conv1)
conv1 = keras.layers.Activation(activation='relu')(conv1)
conv2 = keras.layers.Conv1D(filters=256, kernel_size=5, padding='same')(conv1)
conv2 = keras.layers.BatchNormalization()(conv2)
conv2 = keras.layers.Activation('relu')(conv2)
conv3 = keras.layers.Conv1D(128, kernel_size=3,padding='same')(conv2)
conv3 = keras.layers.BatchNormalization()(conv3)
conv3 = keras.layers.Activation('relu')(conv3)
gap_layer = keras.layers.GlobalAveragePooling1D()(conv3)
outputlayer = keras.layers.Dense(27, activation='sigmoid')(gap_layer)
model = keras.Model(inputs=inputlayer, outputs=outputlayer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def residual_network_1d_demo():
n_feature_maps = 64
input_shape = (5000,12)
inputA = keras.layers.Input(input_shape)
inputB = keras.layers.Input(shape=(2,))
# BLOCK 1
conv_x = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=8, padding='same')(inputA)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# expand channels for the sum
shortcut_y = keras.layers.Conv1D(filters=n_feature_maps, kernel_size=1, padding='same')(inputA)
shortcut_y = keras.layers.BatchNormalization()(shortcut_y)
output_block_1 = keras.layers.add([shortcut_y, conv_z])
output_block_1 = keras.layers.Activation('relu')(output_block_1)
# BLOCK 2
conv_x = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=8, padding='same')(output_block_1)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# expand channels for the sum
shortcut_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=1, padding='same')(output_block_1)
shortcut_y = keras.layers.BatchNormalization()(shortcut_y)
output_block_2 = keras.layers.add([shortcut_y, conv_z])
output_block_2 = keras.layers.Activation('relu')(output_block_2)
# BLOCK 3
conv_x = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=8, padding='same')(output_block_2)
conv_x = keras.layers.BatchNormalization()(conv_x)
conv_x = keras.layers.Activation('relu')(conv_x)
conv_y = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=5, padding='same')(conv_x)
conv_y = keras.layers.BatchNormalization()(conv_y)
conv_y = keras.layers.Activation('relu')(conv_y)
conv_z = keras.layers.Conv1D(filters=n_feature_maps * 2, kernel_size=3, padding='same')(conv_y)
conv_z = keras.layers.BatchNormalization()(conv_z)
# no need to expand channels because they are equal
shortcut_y = keras.layers.BatchNormalization()(output_block_2)
output_block_3 = keras.layers.add([shortcut_y, conv_z])
output_block_3 = keras.layers.Activation('relu')(output_block_3)
# FINAL
gap_layer = keras.layers.GlobalAveragePooling1D()(output_block_3)
output_layer = keras.layers.Dense(27, activation='softmax')(gap_layer)
mod1 = keras.models.Model(inputs=inputA, outputs=output_layer)
mod2 = keras.layers.Dense(50, activation="relu")(inputB)
mod2 = keras.layers.Dense(2, activation="sigmoid")(mod2)
mod2 = keras.models.Model(inputs=inputB, outputs=mod2)
combined = keras.layers.concatenate([mod1.output, mod2.output])
z = keras.layers.Dense(27, activation="sigmoid")(combined)
model = keras.models.Model(inputs=[mod1.input, mod2.input], outputs=z)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def encoder_model_demo():
inputA = keras.layers.Input(shape=(5000, 12))
inputB = keras.layers.Input(shape=(2,))
# conv block -1
conv1 = keras.layers.Conv1D(filters=128,kernel_size=5,strides=1,padding='same')(inputA)
conv1 = tfa.layers.InstanceNormalization()(conv1)
conv1 = keras.layers.PReLU(shared_axes=[1])(conv1)
conv1 = keras.layers.Dropout(rate=0.2)(conv1)
conv1 = keras.layers.MaxPooling1D(pool_size=2)(conv1)
# conv block -2
conv2 = keras.layers.Conv1D(filters=256,kernel_size=11,strides=1,padding='same')(conv1)
conv2 = tfa.layers.InstanceNormalization()(conv2)
conv2 = keras.layers.PReLU(shared_axes=[1])(conv2)
conv2 = keras.layers.Dropout(rate=0.2)(conv2)
conv2 = keras.layers.MaxPooling1D(pool_size=2)(conv2)
# conv block -3
conv3 = keras.layers.Conv1D(filters=512,kernel_size=21,strides=1,padding='same')(conv2)
conv3 = tfa.layers.InstanceNormalization()(conv3)
conv3 = keras.layers.PReLU(shared_axes=[1])(conv3)
conv3 = keras.layers.Dropout(rate=0.2)(conv3)
# split for attention
attention_data = keras.layers.Lambda(lambda x: x[:,:,:256])(conv3)
attention_softmax = keras.layers.Lambda(lambda x: x[:,:,256:])(conv3)
# attention mechanism
attention_softmax = keras.layers.Softmax()(attention_softmax)
multiply_layer = keras.layers.Multiply()([attention_softmax,attention_data])
# last layer
dense_layer = keras.layers.Dense(units=256,activation='sigmoid')(multiply_layer)
dense_layer = tfa.layers.InstanceNormalization()(dense_layer)
# output layer
output_layer = keras.layers.Flatten()(dense_layer)
mod1 = keras.Model(inputs=inputA, outputs=output_layer)
mod2 = keras.layers.Dense(50, activation="relu")(inputB)
mod2 = keras.layers.Dense(2, activation="sigmoid")(mod2)
mod2 = keras.models.Model(inputs=inputB, outputs=mod2)
combined = keras.layers.concatenate([mod1.output, mod2.output])
z = keras.layers.Dense(27, activation="sigmoid")(combined)
model = keras.models.Model(inputs=[mod1.input, mod2.input], outputs=z)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(learning_rate=0.01), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def FCN_demo():
inputA = keras.layers.Input(shape=(5000,12))
inputB = keras.layers.Input(shape=(2,))
conv1 = keras.layers.Conv1D(filters=128, kernel_size=8,input_shape=(5000,12), padding='same')(inputA)
conv1 = keras.layers.BatchNormalization()(conv1)
conv1 = keras.layers.Activation(activation='relu')(conv1)
conv2 = keras.layers.Conv1D(filters=256, kernel_size=5, padding='same')(conv1)
conv2 = keras.layers.BatchNormalization()(conv2)
conv2 = keras.layers.Activation('relu')(conv2)
conv3 = keras.layers.Conv1D(128, kernel_size=3,padding='same')(conv2)
conv3 = keras.layers.BatchNormalization()(conv3)
conv3 = keras.layers.Activation('relu')(conv3)
gap_layer = keras.layers.GlobalAveragePooling1D()(conv3)
model1 = keras.Model(inputs=inputA, outputs=gap_layer)
mod3 = keras.layers.Dense(50, activation="relu")(inputB)
mod3 = keras.layers.Dense(2, activation="sigmoid")(mod3)
model3 = keras.Model(inputs=inputB, outputs=mod3)
combined = keras.layers.concatenate([model1.output, model3.output])
final_layer = keras.layers.Dense(27, activation="sigmoid")(combined)
model = keras.models.Model(inputs=[inputA,inputB], outputs=final_layer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def FCN_Encoder():
inputA = tf.keras.layers.Input(shape=(5000,12))
conv1 = keras.layers.Conv1D(filters=128, kernel_size=8,input_shape=(5000,12), padding='same')(inputA)
conv1 = keras.layers.BatchNormalization()(conv1)
conv1 = keras.layers.Activation(activation='relu')(conv1)
conv2 = keras.layers.Conv1D(filters=256, kernel_size=5, padding='same')(conv1)
conv2 = keras.layers.BatchNormalization()(conv2)
conv2 = keras.layers.Activation('relu')(conv2)
conv3 = keras.layers.Conv1D(128, kernel_size=3,padding='same')(conv2)
conv3 = keras.layers.BatchNormalization()(conv3)
conv3 = keras.layers.Activation('relu')(conv3)
gap_layer = keras.layers.GlobalAveragePooling1D()(conv3)
model1 = keras.Model(inputs=inputA, outputs=gap_layer)
conv1 = keras.layers.Conv1D(filters=128,kernel_size=5,strides=1,padding='same')(inputA)
conv1 = tfa.layers.InstanceNormalization()(conv1)
conv1 = keras.layers.PReLU(shared_axes=[1])(conv1)
conv1 = keras.layers.Dropout(rate=0.2)(conv1)
conv1 = keras.layers.MaxPooling1D(pool_size=2)(conv1)
# conv block -2
conv2 = keras.layers.Conv1D(filters=256,kernel_size=11,strides=1,padding='same')(conv1)
conv2 = tfa.layers.InstanceNormalization()(conv2)
conv2 = keras.layers.PReLU(shared_axes=[1])(conv2)
conv2 = keras.layers.Dropout(rate=0.2)(conv2)
conv2 = keras.layers.MaxPooling1D(pool_size=2)(conv2)
# conv block -3
conv3 = keras.layers.Conv1D(filters=512,kernel_size=21,strides=1,padding='same')(conv2)
conv3 = tfa.layers.InstanceNormalization()(conv3)
conv3 = keras.layers.PReLU(shared_axes=[1])(conv3)
conv3 = keras.layers.Dropout(rate=0.2)(conv3)
# split for attention
attention_data = keras.layers.Lambda(lambda x: x[:,:,:256])(conv3)
attention_softmax = keras.layers.Lambda(lambda x: x[:,:,256:])(conv3)
# attention mechanism
attention_softmax = keras.layers.Softmax()(attention_softmax)
multiply_layer = keras.layers.Multiply()([attention_softmax,attention_data])
# last layer
dense_layer = keras.layers.Dense(units=256,activation='sigmoid')(multiply_layer)
dense_layer = tfa.layers.InstanceNormalization()(dense_layer)
# output layer
flatten_layer = keras.layers.Flatten()(dense_layer)
model2 = keras.Model(inputs=inputA, outputs=flatten_layer)
combined = keras.layers.concatenate([model1.output, model2.output])
final_layer = keras.layers.Dense(27, activation="sigmoid")(combined)
model = keras.models.Model(inputs=inputA, outputs=final_layer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def FCN_Encoder_demo():
inputA = keras.layers.Input(shape=(5000,12))
inputB = keras.layers.Input(shape=(2,))
conv1 = keras.layers.Conv1D(filters=128, kernel_size=8,input_shape=(5000,12), padding='same')(inputA)
conv1 = keras.layers.BatchNormalization()(conv1)
conv1 = keras.layers.Activation(activation='relu')(conv1)
conv2 = keras.layers.Conv1D(filters=256, kernel_size=5, padding='same')(conv1)
conv2 = keras.layers.BatchNormalization()(conv2)
conv2 = keras.layers.Activation('relu')(conv2)
conv3 = keras.layers.Conv1D(128, kernel_size=3,padding='same')(conv2)
conv3 = keras.layers.BatchNormalization()(conv3)
conv3 = keras.layers.Activation('relu')(conv3)
gap_layer = keras.layers.GlobalAveragePooling1D()(conv3)
model1 = keras.Model(inputs=inputA, outputs=gap_layer)
conv1 = keras.layers.Conv1D(filters=256,kernel_size=10,strides=1,padding='same')(inputA)
conv1 = tfa.layers.InstanceNormalization()(conv1)
conv1 = keras.layers.PReLU(shared_axes=[1])(conv1)
conv1 = keras.layers.Dropout(rate=0.2)(conv1)
conv1 = keras.layers.MaxPooling1D(pool_size=2)(conv1)
# conv block -2
conv2 = keras.layers.Conv1D(filters=512,kernel_size=22,strides=1,padding='same')(conv1)
conv2 = tfa.layers.InstanceNormalization()(conv2)
conv2 = keras.layers.PReLU(shared_axes=[1])(conv2)
conv2 = keras.layers.Dropout(rate=0.2)(conv2)
conv2 = keras.layers.MaxPooling1D(pool_size=2)(conv2)
# conv block -3
conv3 = keras.layers.Conv1D(filters=1024,kernel_size=42,strides=1,padding='same')(conv2)
conv3 = tfa.layers.InstanceNormalization()(conv3)
conv3 = keras.layers.PReLU(shared_axes=[1])(conv3)
conv3 = keras.layers.Dropout(rate=0.2)(conv3)
# split for attention
attention_data = keras.layers.Lambda(lambda x: x[:,:,:512])(conv3)
attention_softmax = keras.layers.Lambda(lambda x: x[:,:,512:])(conv3)
# attention mechanism
attention_softmax = keras.layers.Softmax()(attention_softmax)
multiply_layer = keras.layers.Multiply()([attention_softmax,attention_data])
# last layer
dense_layer = keras.layers.Dense(units=512,activation='sigmoid')(multiply_layer)
dense_layer = tfa.layers.InstanceNormalization()(dense_layer)
# output layer
flatten_layer = keras.layers.Flatten()(dense_layer)
model2 = keras.Model(inputs=inputA, outputs=flatten_layer)
mod3 = keras.layers.Dense(50, activation="relu")(inputB) # 2 -> 100
mod3 = keras.layers.Dense(2, activation="sigmoid")(mod3) # Added this layer
model3 = keras.Model(inputs=inputB, outputs=mod3)
combined = keras.layers.concatenate([model1.output, model2.output, model3.output])
final_layer = keras.layers.Dense(27, activation="sigmoid")(combined)
model = keras.models.Model(inputs=[inputA,inputB], outputs=final_layer)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(), metrics=[tf.keras.metrics.BinaryAccuracy(
name='accuracy', dtype=None, threshold=0.5),tf.keras.metrics.Recall(name='Recall'),tf.keras.metrics.Precision(name='Precision'),
tf.keras.metrics.AUC(
num_thresholds=200,
curve="ROC",
summation_method="interpolation",
name="AUC",
dtype=None,
thresholds=None,
multi_label=True,
label_weights=None,
)])
return model
def compute_challenge_metric_for_opt(labels, outputs):
classes=['10370003','111975006','164889003','164890007','164909002','164917005','164934002','164947007','17338001',
'251146004','270492004','284470004','39732003','426177001','426627000','426783006','427084000','427172004','427393009','445118002','47665007','59118001',
'59931005','63593006','698252002','713426002','713427006']
'''
24 classes
['10370003', '111975006', '164889003', '164890007', '164909002', '164917005',
'164934002', '164947007', '17338001', '251146004', '270492004', '39732003',
'426177001', '426627000', '426783006' ,'427084000' ,'427393009', '445118002',
'47665007' ,'59118001', '59931005', '63593006', '698252002', '713426002']
'''
normal_class = '426783006'
weights = np.array([[1. , 0.425 , 0.375 , 0.375 , 0.4 , 0.275 , 0.375 , 0.425 ,
0.5 , 0.45 , 0.425 , 0.4625, 0.475 , 0.425 , 0.425 , 0.375 ,
0.5 , 0.5 , 0.425 , 0.475 , 0.475 , 0.475 , 0.375 , 0.4625,
0.475 , 0.425 , 0.475 ],
[0.425 , 1. , 0.45 , 0.45 , 0.475 , 0.35 , 0.45 , 0.35 ,
0.425 , 0.475 , 0.35 , 0.3875, 0.4 , 0.35 , 0.35 , 0.3 ,
0.425 , 0.425 , 0.35 , 0.4 , 0.4 , 0.45 , 0.45 , 0.3875,
0.4 , 0.35 , 0.45 ],
[0.375 , 0.45 , 1. , 0.5 , 0.475 , 0.4 , 0.5 , 0.3 ,
0.375 , 0.425 , 0.3 , 0.3375, 0.35 , 0.3 , 0.3 , 0.25 ,
0.375 , 0.375 , 0.3 , 0.35 , 0.35 , 0.4 , 0.5 , 0.3375,
0.35 , 0.3 , 0.4 ],
[0.375 , 0.45 , 0.5 , 1. , 0.475 , 0.4 , 0.5 , 0.3 ,
0.375 , 0.425 , 0.3 , 0.3375, 0.35 , 0.3 , 0.3 , 0.25 ,
0.375 , 0.375 , 0.3 , 0.35 , 0.35 , 0.4 , 0.5 , 0.3375,
0.35 , 0.3 , 0.4 ],
[0.4 , 0.475 , 0.475 , 0.475 , 1. , 0.375 , 0.475 , 0.325 ,
0.4 , 0.45 , 0.325 , 0.3625, 0.375 , 0.325 , 0.325 , 0.275 ,
0.4 , 0.4 , 0.325 , 0.375 , 0.375 , 0.425 , 0.475 , 0.3625,
0.375 , 0.325 , 0.425 ],
[0.275 , 0.35 , 0.4 , 0.4 , 0.375 , 1. , 0.4 , 0.2 ,
0.275 , 0.325 , 0.2 , 0.2375, 0.25 , 0.2 , 0.2 , 0.15 ,
0.275 , 0.275 , 0.2 , 0.25 , 0.25 , 0.3 , 0.4 , 0.2375,
0.25 , 0.2 , 0.3 ],
[0.375 , 0.45 , 0.5 , 0.5 , 0.475 , 0.4 , 1. , 0.3 ,
0.375 , 0.425 , 0.3 , 0.3375, 0.35 , 0.3 , 0.3 , 0.25 ,
0.375 , 0.375 , 0.3 , 0.35 , 0.35 , 0.4 , 0.5 , 0.3375,
0.35 , 0.3 , 0.4 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 1. ,
0.425 , 0.375 , 0.5 , 0.4625, 0.45 , 0.5 , 0.5 , 0.45 ,
0.425 , 0.425 , 0.5 , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 0.5 , 0.4 ],
[0.5 , 0.425 , 0.375 , 0.375 , 0.4 , 0.275 , 0.375 , 0.425 ,
1. , 0.45 , 0.425 , 0.4625, 0.475 , 0.425 , 0.425 , 0.375 ,
0.5 , 1. , 0.425 , 0.475 , 0.475 , 0.475 , 0.375 , 0.4625,
0.475 , 0.425 , 0.475 ],
[0.45 , 0.475 , 0.425 , 0.425 , 0.45 , 0.325 , 0.425 , 0.375 ,
0.45 , 1. , 0.375 , 0.4125, 0.425 , 0.375 , 0.375 , 0.325 ,
0.45 , 0.45 , 0.375 , 0.425 , 0.425 , 0.475 , 0.425 , 0.4125,
0.425 , 0.375 , 0.475 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 0.5 ,
0.425 , 0.375 , 1. , 0.4625, 0.45 , 0.5 , 0.5 , 0.45 ,
0.425 , 0.425 , 0.5 , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 0.5 , 0.4 ],
[0.4625, 0.3875, 0.3375, 0.3375, 0.3625, 0.2375, 0.3375, 0.4625,
0.4625, 0.4125, 0.4625, 1. , 0.4875, 0.4625, 0.4625, 0.4125,
0.4625, 0.4625, 0.4625, 0.4875, 0.4875, 0.4375, 0.3375, 1. ,
0.4875, 0.4625, 0.4375],
[0.475 , 0.4 , 0.35 , 0.35 , 0.375 , 0.25 , 0.35 , 0.45 ,
0.475 , 0.425 , 0.45 , 0.4875, 1. , 0.45 , 0.45 , 0.4 ,
0.475 , 0.475 , 0.45 , 0.5 , 0.5 , 0.45 , 0.35 , 0.4875,
0.5 , 0.45 , 0.45 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 0.5 ,
0.425 , 0.375 , 0.5 , 0.4625, 0.45 , 1. , 0.5 , 0.45 ,
0.425 , 0.425 , 0.5 , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 0.5 , 0.4 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 0.5 ,
0.425 , 0.375 , 0.5 , 0.4625, 0.45 , 0.5 , 1. , 0.45 ,
0.425 , 0.425 , 0.5 , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 0.5 , 0.4 ],
[0.375 , 0.3 , 0.25 , 0.25 , 0.275 , 0.15 , 0.25 , 0.45 ,
0.375 , 0.325 , 0.45 , 0.4125, 0.4 , 0.45 , 0.45 , 1. ,
0.375 , 0.375 , 0.45 , 0.4 , 0.4 , 0.35 , 0.25 , 0.4125,
0.4 , 0.45 , 0.35 ],
[0.5 , 0.425 , 0.375 , 0.375 , 0.4 , 0.275 , 0.375 , 0.425 ,
0.5 , 0.45 , 0.425 , 0.4625, 0.475 , 0.425 , 0.425 , 0.375 ,
1. , 0.5 , 0.425 , 0.475 , 0.475 , 0.475 , 0.375 , 0.4625,
0.475 , 0.425 , 0.475 ],
[0.5 , 0.425 , 0.375 , 0.375 , 0.4 , 0.275 , 0.375 , 0.425 ,
1. , 0.45 , 0.425 , 0.4625, 0.475 , 0.425 , 0.425 , 0.375 ,
0.5 , 1. , 0.425 , 0.475 , 0.475 , 0.475 , 0.375 , 0.4625,
0.475 , 0.425 , 0.475 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 0.5 ,
0.425 , 0.375 , 0.5 , 0.4625, 0.45 , 0.5 , 0.5 , 0.45 ,
0.425 , 0.425 , 1. , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 0.5 , 0.4 ],
[0.475 , 0.4 , 0.35 , 0.35 , 0.375 , 0.25 , 0.35 , 0.45 ,
0.475 , 0.425 , 0.45 , 0.4875, 0.5 , 0.45 , 0.45 , 0.4 ,
0.475 , 0.475 , 0.45 , 1. , 0.5 , 0.45 , 0.35 , 0.4875,
0.5 , 0.45 , 0.45 ],
[0.475 , 0.4 , 0.35 , 0.35 , 0.375 , 0.25 , 0.35 , 0.45 ,
0.475 , 0.425 , 0.45 , 0.4875, 0.5 , 0.45 , 0.45 , 0.4 ,
0.475 , 0.475 , 0.45 , 0.5 , 1. , 0.45 , 0.35 , 0.4875,
0.5 , 0.45 , 0.45 ],
[0.475 , 0.45 , 0.4 , 0.4 , 0.425 , 0.3 , 0.4 , 0.4 ,
0.475 , 0.475 , 0.4 , 0.4375, 0.45 , 0.4 , 0.4 , 0.35 ,
0.475 , 0.475 , 0.4 , 0.45 , 0.45 , 1. , 0.4 , 0.4375,
0.45 , 0.4 , 1. ],
[0.375 , 0.45 , 0.5 , 0.5 , 0.475 , 0.4 , 0.5 , 0.3 ,
0.375 , 0.425 , 0.3 , 0.3375, 0.35 , 0.3 , 0.3 , 0.25 ,
0.375 , 0.375 , 0.3 , 0.35 , 0.35 , 0.4 , 1. , 0.3375,
0.35 , 0.3 , 0.4 ],
[0.4625, 0.3875, 0.3375, 0.3375, 0.3625, 0.2375, 0.3375, 0.4625,
0.4625, 0.4125, 0.4625, 1. , 0.4875, 0.4625, 0.4625, 0.4125,
0.4625, 0.4625, 0.4625, 0.4875, 0.4875, 0.4375, 0.3375, 1. ,
0.4875, 0.4625, 0.4375],
[0.475 , 0.4 , 0.35 , 0.35 , 0.375 , 0.25 , 0.35 , 0.45 ,
0.475 , 0.425 , 0.45 , 0.4875, 0.5 , 0.45 , 0.45 , 0.4 ,
0.475 , 0.475 , 0.45 , 0.5 , 0.5 , 0.45 , 0.35 , 0.4875,
1. , 0.45 , 0.45 ],
[0.425 , 0.35 , 0.3 , 0.3 , 0.325 , 0.2 , 0.3 , 0.5 ,
0.425 , 0.375 , 0.5 , 0.4625, 0.45 , 0.5 , 0.5 , 0.45 ,
0.425 , 0.425 , 0.5 , 0.45 , 0.45 , 0.4 , 0.3 , 0.4625,
0.45 , 1. , 0.4 ],
[0.475 , 0.45 , 0.4 , 0.4 , 0.425 , 0.3 , 0.4 , 0.4 ,
0.475 , 0.475 , 0.4 , 0.4375, 0.45 , 0.4 , 0.4 , 0.35 ,
0.475 , 0.475 , 0.4 , 0.45 , 0.45 , 1. , 0.4 , 0.4375,
0.45 , 0.4 , 1. ]])
num_recordings, num_classes = np.shape(labels)
normal_index = classes.index(normal_class)
# Compute the observed score.
A = compute_modified_confusion_matrix(labels, outputs)
observed_score = np.nansum(weights * A)
# Compute the score for the model that always chooses the correct label(s).
correct_outputs = labels
A = compute_modified_confusion_matrix(labels, correct_outputs)
correct_score = np.nansum(weights * A)
# Compute the score for the model that always chooses the normal class.
inactive_outputs = np.zeros((num_recordings, num_classes), dtype=np.bool)
inactive_outputs[:, normal_index] = 1
A = compute_modified_confusion_matrix(labels, inactive_outputs)
inactive_score = np.nansum(weights * A)
if correct_score != inactive_score:
normalized_score = float(observed_score - inactive_score) / float(correct_score - inactive_score)
else:
normalized_score = float('nan')
return normalized_score
def compute_modified_confusion_matrix(labels, outputs):
# Compute a binary multi-class, multi-label confusion matrix, where the rows
# are the labels and the columns are the outputs.
num_recordings, num_classes = np.shape(labels)
A = np.zeros((num_classes, num_classes))
# Iterate over all of the recordings.
for i in range(num_recordings):
# Calculate the number of positive labels and/or outputs.
normalization = float(max(np.sum(np.any((labels[i, :], outputs[i, :]), axis=0)), 1))
# Iterate over all of the classes.
for j in range(num_classes):
# Assign full and/or partial credit for each positive class.
if labels[i, j]:
for k in range(num_classes):
if outputs[i, k]:
A[j, k] += 1.0/normalization
return A
def iterate_threshold(y_pred, ecg_filenames, y ,val_fold ):
init_thresholds = np.arange(0,1,0.05)
all_scores = []
for i in init_thresholds:
pred_output = y_pred > i
pred_output = pred_output * 1
score = compute_challenge_metric_for_opt(generate_validation_data(ecg_filenames,y,val_fold)[1],pred_output)
print(score)
all_scores.append(score)
all_scores = np.asarray(all_scores)
return all_scores
def plot_normalized_conf_matrix(y_pred, ecg_filenames, y, val_fold, threshold, snomedclasses, snomedabbr):
conf_m = compute_modified_confusion_matrix(generate_validation_data(ecg_filenames,y,val_fold)[1], (y_pred>threshold)*1)
conf_m = np.nan_to_num(conf_m)
#min_max_scaler = preprocessing.MinMaxScaler()
#conf_m_scaled = min_max_scaler.fit_transform(conf_m)
normalizer = preprocessing.Normalizer(norm="l1")
conf_m_scaled = normalizer.fit_transform(conf_m)
df_norm_col = pd.DataFrame(conf_m_scaled)
df_norm_col.columns = snomedabbr
df_norm_col.index = snomedabbr
df_norm_col.index.name = 'Actual'
df_norm_col.columns.name = 'Predicted'
#df_norm_col=(df_cm-df_cm.mean())/df_cm.std()
plt.figure(figsize = (12,10))
sns.set(font_scale=1.4)#for label size
sns.heatmap(df_norm_col, cmap="rocket_r", annot=True,cbar=False, annot_kws={"size": 10},fmt=".2f")#
#############################
#Adding rule-based algorithms
#############################
def DetectRWithPanTompkins (signal, signal_freq):
'''signal=ECG signal (type=np.array), signal_freq=sample frequenzy'''
lowcut = 5.0
highcut = 15.0
filter_order = 2
nyquist_freq = 0.5 * signal_freq
low = lowcut / nyquist_freq
high = highcut / nyquist_freq
b, a = butter(filter_order, [low, high], btype="band")
y = lfilter(b, a, signal)
diff_y=np.ediff1d(y)
squared_diff_y=diff_y**2
integrated_squared_diff_y =np.convolve(squared_diff_y,np.ones(5))
normalized = (integrated_squared_diff_y-min(integrated_squared_diff_y))/(max(integrated_squared_diff_y)-min(integrated_squared_diff_y))
peaks, metadata = find_peaks(normalized,
distance=signal_freq/5 ,
#height=500,
height=0.5,
width=0.5
)
return peaks
def heartrate(r_time, sampfreq):
#qrs = xqrs.qrs_inds from annotateR()
#sampfreq = sample frequency - can be found with y['fs'] (from getDataFromPhysionet())
HeartRate = []
TimeBetweenBeat= []
for index, item in enumerate(r_time,-1):
HeartRate.append(60/((r_time[index+1]-r_time[index])/sampfreq))
TimeBetweenBeat.append((r_time[index+1]-r_time[index])/sampfreq)
del HeartRate[0]
avgHr = sum(HeartRate)/len(HeartRate)
TimeBetweenBeat= np.asarray(TimeBetweenBeat)
TimeBetweenBeat=TimeBetweenBeat * 1000 # sec to ms
TimeBetweenBeat = TimeBetweenBeat[1:] # remove first element
return TimeBetweenBeat, avgHr
def R_correction(signal, peaks):
'''signal = ECG signal, peaks = uncorrected R peaks'''
peaks_corrected, metadata = find_peaks(signal, distance=min(np.diff(peaks)))
return peaks_corrected
def rule_based_predictions(ecgfilenames, val_data, dnn_prediction):
for i in range(len(val_data)):
data , header_data = load_challenge_data(ecgfilenames[val_data[i]])
avg_hr = 0
peaks = 0
rmssd = 0
qrs_voltage = 0
try:
peaks = DetectRWithPanTompkins(data[1],int(header_data[0].split()[2]))
try:
peaks = R_correction(data[1], peaks)
except:
print("Did not manage to do R_correction")
except:
print("Did not manage to find any peaks using Pan Tomkins")
try:
rr_interval, avg_hr = heartrate(peaks,int(header_data[0].split()[2]))
try:
rmssd = np.mean(np.square(np.diff(rr_interval)))
except:
print("did not manage to comp rmssd")
except:
print("not able to calculate heart rate")
rr_interval = 0
avg_hr = 0
try:
qrs_voltage = np.mean(data[1][peaks])
except:
print("Could not calculate mean QRS peak voltage")
if avg_hr != 0: # bare gjΓΈr disse endringene dersom vi klarer Γ₯ beregne puls
if 60 < avg_hr < 100:
dnn_prediction[i][16] = 0
dnn_prediction[i][14] = 0
dnn_prediction[i][13] = 0
elif avg_hr < 60 & dnn_prediction[i][15] == 1:
dnn_prediction[i][13] = 1
elif avg_hr < 60 & dnn_prediction[i][15] == 0:
dnn_prediction[i][14] = 1
elif avg_hr > 100:
dnn_prediction[i][16] = 1
if qrs_voltage != 0:
if qrs_voltage < 500:
dnn_prediction[i][9] = 1
dnn_prediction[i][15] = 0
else:
dnn_prediction[i][9] = 0
else:
dnn_prediction[i][9] = 0
if rmssd != 0:
if rmssd < 15:
dnn_prediction[i][0] = 1
dnn_prediction[i][16] = 0
dnn_prediction[i][15] = 0
dnn_prediction[i][14] = 0
dnn_prediction[i][13] = 0
elif 2000 < rmssd < 5000:
dnn_prediction[i][18] = 1
elif 15000 < rmssd < 50000:
dnn_prediction[i][2] = 1
else:
dnn_prediction[i][15] = 1
return dnn_prediction
def plot_normalized_conf_matrix_rule(y_true,val_data,rb_pred,snomedclasses):
df_cm = pd.DataFrame(compute_modified_confusion_matrix(y_true[val_data],rb_pred), columns=snomedclasses, index = snomedclasses)
df_cm = df_cm.fillna(0)
df_cm.index.name = 'Actual'
df_cm.columns.name = 'Predicted'
df_norm_col=(df_cm-df_cm.mean())/df_cm.std()
plt.figure(figsize = (36,14))
sns.set(font_scale=1.4)
sns.heatmap(df_norm_col, cmap="Blues", annot=True,annot_kws={"size": 16},fmt=".2f",cbar=False)# font size
LMLM Canonical System Instruction (v1.1.0-Production Draft)
Markdown
# SYSTEM INSTRUCTION: LMLM ORCHESTRATION ARCHITECTURE (v1.1.0)
## 1. IDENTITY & ARCHITECTURAL FOUNDATION
You are **LMLM (Large Multimodal Learning Model)**, an asynchronous, model-agnostic intelligence runtime designed to perceive, understand, retrieve, reason over, plan, execute, verify, remember, and continuously improve across all information modalities.
You are NOT a simple chatbot wrapper. You operate as a stateful, event-driven, decoupled orchestrator (`LMLM-Core`) managing modular subsystems through strongly typed execution primitives, dynamic resource routing, and explicit policy controls.
---
## 2. THE PRODUCTION 9-PHASE LIFECYCLE
Every incoming `Task` MUST progress deterministically through the canonical 9-phase runtime loop:
[1. Perceive] ──> [2. Understand] ──> [3. Retrieve] ──> [4. Reason] ──> [5. Plan (DAG)]
β”‚
[9. Improve] <── [8. Remember] <── [7. Verify] <── [6. Execute] <β”€β”€β”€β”€β”€β”€β”€β”€β”˜
1. **Perceive:** Ingest raw multi-modal signals into structured `Task` objects.
2. **Understand:** Classify complexity, safety risk, latency constraints, and modality requirements.
3. **Retrieve:** Contextually query `LMLM-Memory` (working, episodic, semantic) and `LMLM-RAG`.
4. **Reason:** Determine model adapter strategy, sampling parameters, and dynamic context windows.
5. **Plan:** Construct a directed acyclic task graph (`TaskPlan` / `TaskStep` DAG) with explicit dependency mapping.
6. **Execute:** Evaluate safety policies (`ALLOW` / `DENY` / `REQUIRE_CONFIRMATION`), dispatch async tool calls, or execute code via `LMLM-CODEX`.
7. **Verify:** Emit machine-readable `VerificationResult` instances with explicit evidence; evaluate the consecutive failure policy ("fail-twice" threshold).
8. **Remember:** Commit verified state, execution traces, and structured observations to persistent stores.
9. **Improve:** Log execution latency, token burn, cost, and verification metrics to feed routing heuristics.
---
## 3. SECURITY & POLICY GATEWAY
No tool, model call, or code execution path may bypass the `Policy Engine`.
[Model Call Requests Tool] ──> [LMLM-Core Validation] ──> [Policy Engine Evaluation]
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚ β”‚
β–Ό β–Ό β–Ό
[ALLOW] [REQUIRE_CONFIRMATION] [DENY]
Execute via Tool Halt step; yield PolicyViolation state Reject execution; log
Registry immediately requesting human/system clearance to ExecutionTrace
### High-Risk Operations
Operations involving destructive file operations (`delete`, `overwrite`), infrastructure modification, database schema migrations, code publishing, or external state updates ALWAYS require explicit policy authorization.
Production Core Architecture (v1.0 Runtime Blueprint)
Below is the complete, runnable Python implementation for the v1.0 Core Runtime Specification, addressing all technical requirements: typed state models, full 9-phase lifecycle orchestration, safety policy evaluation, consecutive failure tracking, and machine-readable verification.
1. Strongly Typed State Primitives (core/state.py)
Python
from enum import Enum
from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field
class TaskStatus(str, Enum):
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
BLOCKED = "blocked"
class PolicyAction(str, Enum):
ALLOW = "allow"
DENY = "deny"
REQUIRE_CONFIRMATION = "require_confirmation"
class Task(BaseModel):
id: str
input: str
status: TaskStatus = TaskStatus.PENDING
metadata: Dict[str, Any] = Field(default_factory=dict)
class ToolDefinition(BaseModel):
name: str
description: str
input_schema: Dict[str, Any]
dangerous: bool = False
requires_confirmation: bool = False
class TaskStep(BaseModel):
id: str
task_id: str
action: str
parameters: Dict[str, Any] = Field(default_factory=dict)
dependencies: List[str] = Field(default_factory=list)
status: TaskStatus = TaskStatus.PENDING
consecutive_failures: int = 0
result: Optional[Any] = None
class VerificationResult(BaseModel):
verified: bool
message: str
evidence: Optional[Any] = None
class Observation(BaseModel):
step_id: str
tool_name: str
success: bool
output: Any
error: Optional[str] = None
class ExecutionTrace(BaseModel):
task_id: str
steps: List[TaskStep] = Field(default_factory=list)
observations: List[Observation] = Field(default_factory=list)
verifications: List[VerificationResult] = Field(default_factory=list)
class TaskPlan(BaseModel):
task_id: str
steps: List[TaskStep]
2. Async Model Adapters & Tool Registry (models/ & tools/)
Python
from abc import ABC, abstractmethod
from typing import Any, Callable, Dict, List, Optional
from core.state import ToolDefinition, Observation
class CompletionRequest(BaseModel):
prompt: str
temperature: float = 0.2
max_tokens: int = 1000
tools: Optional[List[Dict[str, Any]]] = None
class CompletionResponse(BaseModel):
content: str
tool_calls: Optional[List[Dict[str, Any]]] = None
usage: Dict[str, int] = Field(default_factory=dict)
class BaseAsyncModelAdapter(ABC):
"""Unified asynchronous interface for model-agnostic execution."""
@abstractmethod
async def generate_async(self, request: CompletionRequest) -> CompletionResponse:
pass
class ToolRegistry:
"""Strongly-typed tool registry with full OpenAPI-style schema enforcement."""
def __init__(self):
self._tools: Dict[str, Callable] = {}
self._definitions: Dict[str, ToolDefinition] = {}
def register(self, definition: ToolDefinition, func: Callable):
self._definitions[definition.name] = definition
self._tools[definition.name] = func
def get_definition(self, name: str) -> Optional[ToolDefinition]:
return self._definitions.get(name)
def get_schemas(self) -> List[Dict[str, Any]]:
return [defn.model_dump() for defn in self._definitions.values()]
async def execute(self, step_id: str, tool_name: str, **kwargs) -> Observation:
if tool_name not in self._tools:
return Observation(
step_id=step_id,
tool_name=tool_name,
success=False,
output=None,
error=f"Tool '{tool_name}' not registered."
)
try:
func = self._tools[tool_name]
# Supports both sync and async execution paths
import asyncio
if asyncio.iscoroutinefunction(func):
result = await func(**kwargs)
else:
result = func(**kwargs)
return Observation(
step_id=step_id,
tool_name=tool_name,
success=True,
output=result
)
except Exception as e:
return Observation(
step_id=step_id,
tool_name=tool_name,
success=False,
output=None,
error=str(e)
)
3. Policy Engine & Memory Subsystems (core/policies/ & memory/)
Python
from core.state import PolicyAction, ToolDefinition
class PolicyEngine:
"""Safety and execution authorization gateway."""
def evaluate(self, tool_def: ToolDefinition, parameters: Dict[str, Any]) -> PolicyAction:
if tool_def.dangerous:
if tool_def.requires_confirmation:
return PolicyAction.REQUIRE_CONFIRMATION
return PolicyAction.DENY
return PolicyAction.ALLOW
class MemoryManager:
"""Segregated memory subsystem separating working state from persistent recall."""
def __init__(self):
self.working_memory: Dict[str, List[Dict[str, Any]]] = {}
self.persistent_episodic: List[Dict[str, Any]] = []
def update_working(self, task_id: str, entry: Dict[str, Any]):
if task_id not in self.working_memory:
self.working_memory[task_id] = []
self.working_memory[task_id].append(entry)
def commit_to_persistent(self, task_id: str, trace_summary: Dict[str, Any]):
self.persistent_episodic.append({
"task_id": task_id,
"summary": trace_summary
})
# Clear working memory after persisting
self.working_memory.pop(task_id, None)
4. Orchestrator Engine (core/orchestrator/engine.py)
Python
import asyncio
import logging
from typing import Dict, List, Optional
from core.state import (
ExecutionTrace, Observation, PolicyAction, Task, TaskPlan,
TaskStatus, TaskStep, VerificationResult
)
from models.adapters.base import BaseAsyncModelAdapter, CompletionRequest
from tools.registry import ToolRegistry
from core.policies.policy_engine import PolicyEngine
from memory.manager import MemoryManager
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("LMLM-Core")
class ProductionLMLMOrchestrator:
"""Full 9-Phase LMLM Production Engine Implementation."""
def __init__(
self,
model_adapter: BaseAsyncModelAdapter,
tool_registry: ToolRegistry,
policy_engine: PolicyEngine,
memory_manager: MemoryManager,
max_consecutive_failures: int = 2
):
self.adapter = model_adapter
self.tools = tool_registry
self.policy = policy_engine
self.memory = memory_manager
self.max_consecutive_failures = max_consecutive_failures
async def execute_task(self, raw_input: str) -> ExecutionTrace:
# 1. PERCEIVE
task = Task(id=f"task_{asyncio.get_event_loop().time()}", input=raw_input)
trace = ExecutionTrace(task_id=task.id)
logger.info(f"[1. PERCEIVE] Created task {task.id}")
# 2. UNDERSTAND
task.metadata["complexity"] = "high" if len(raw_input) > 200 else "standard"
logger.info(f"[2. UNDERSTAND] Complexity assessed: {task.metadata['complexity']}")
# 3. RETRIEVE
relevant_context = [
m for m in self.memory.persistent_episodic
if task.input in str(m.get("summary"))
]
logger.info(f"[3. RETRIEVE] Retrieved {len(relevant_context)} persistent memories")
# 4. REASON & 5. PLAN (Construct DAG Plan)
plan = await self._generate_dag_plan(task, relevant_context)
trace.steps = plan.steps
logger.info(f"[5. PLAN] Built DAG Plan with {len(plan.steps)} steps")
task.status = TaskStatus.RUNNING
# 6. EXECUTE LOOP across DAG steps
for step in plan.steps:
if step.status == TaskStatus.BLOCKED:
logger.warning(f"Skipping blocked step {step.id}")
continue
step.status = TaskStatus.RUNNING
while step.consecutive_failures < self.max_consecutive_failures:
tool_def = self.tools.get_definition(step.action)
if not tool_def:
step.status = TaskStatus.FAILED
break
# POLICY EVALUATION
action_policy = self.policy.evaluate(tool_def, step.parameters)
if action_policy == PolicyAction.DENY:
logger.error(f"[POLICY DENIED] Execution blocked for tool {step.action}")
step.status = TaskStatus.FAILED
break
elif action_policy == PolicyAction.REQUIRE_CONFIRMATION:
logger.warning(f"[POLICY INTERRUPT] Confirmation required for {step.action}")
step.status = TaskStatus.BLOCKED
break
# TOOL EXECUTION
obs = await self.tools.execute(step.id, step.action, **step.parameters)
trace.observations.append(obs)
# 7. VERIFY
ver_res = self._verify_step(step, obs)
trace.verifications.append(ver_res)
if ver_res.verified:
step.status = TaskStatus.COMPLETED
step.result = obs.output
step.consecutive_failures = 0
logger.info(f"[7. VERIFY] Step {step.id} passed verification.")
break
else:
step.consecutive_failures += 1
logger.warning(
f"[7. VERIFY] Step {step.id} failed verification. "
f"Consecutive Failures: {step.consecutive_failures}"
)
if step.status != TaskStatus.COMPLETED:
step.status = TaskStatus.FAILED
task.status = TaskStatus.FAILED
logger.error(f"Halting task loop. Step {step.id} failed after maximum retries.")
break
if all(s.status == TaskStatus.COMPLETED for s in plan.steps):
task.status = TaskStatus.COMPLETED
# 8. REMEMBER
self.memory.commit_to_persistent(task.id, {"status": task.status, "input": task.input})
logger.info(f"[8. REMEMBER] State persisted for task {task.id}")
# 9. IMPROVE
self._record_metrics(task, trace)
logger.info(f"[9. IMPROVE] Metrics logged. Execution complete.")
return trace
async def _generate_dag_plan(self, task: Task, context: List[Any]) -> TaskPlan:
# Prompt model adapter to return DAG structured JSON
req = CompletionRequest(
prompt=f"Create execution DAG for task: {task.input} using tools: {self.tools.get_schemas()}"
)
# Fallback deterministic step generation for runtime robustness
step = TaskStep(
id=f"step_1",
task_id=task.id,
action="filesystem.read",
parameters={"path": "/sandbox/workspace.py"}
)
return TaskPlan(task_id=task.id, steps=[step])
def _verify_step(self, step: TaskStep, observation: Observation) -> VerificationResult:
"""Machine-readable verification logic."""
if not observation.success:
return VerificationResult(
verified=False,
message="Execution threw an unhandled exception.",
evidence=observation.error
)
if observation.output is None:
return VerificationResult(
verified=False,
message="Execution returned null/empty output.",
evidence=None
)
return VerificationResult(
verified=True,
message="Step completed with non-null observation.",
evidence=observation.output
)
def _record_metrics(self, task: Task, trace: ExecutionTrace):
"""Improves future execution paths by logging trace performance metrics."""
total_steps = len(trace.steps)
failed_obs = len([o for o in trace.observations if not o.success])
logger.info(f"Task Metrics -> Steps: {total_steps}, Errors: {failed_obs}")
Canonical Roadmap & Build Sequence
LMLM Canonical Roadmap
β”œβ”€β”€ v1.0 β€” Core Runtime (Task -> State -> DAG Planner -> Policy Engine -> Async Tool Execution -> Verifier)
β”œβ”€β”€ v1.1 β€” Model Adapter Engine (Async OpenAI, Anthropic, Ollama, vLLM, local GGUF)
β”œβ”€β”€ v1.2 β€” Memory & RAG Systems (Vector stores, semantic chunking, provenance, episodic recall)
β”œβ”€β”€ v1.3 β€” Autonomous Agent Runtime (Parallel DAG execution, task delegation, background monitoring)
β”œβ”€β”€ v1.4 β€” LMLM-CODEX Engine (Isolated sandboxing, AST refactoring, dynamic debugging, CI/CD runners)
β”œβ”€β”€ v1.5 β€” Multimodal Fusion Layer (Unified context across Text, Image, Audio, Video, AST)
└── v2.0 β€” Adaptive Intelligence Runtime (Dynamic model routing, dynamic context, self-evaluation)