为什么我的CNN keras模型的预测总是相同?

时间:2020-05-30 11:00:35

标签: python keras deep-learning classification conv-neural-network

我已经训练了CNN模型,将ECG信号分为4种不同的类别,然后将其保存。现在我加载了它,并试图用它预测一些事情,然后给了它32个ECG信号。因此,第一个预测总是给我4个不同的百分比,但接下来的31个彼此相同。有人知道为什么吗? 完整的代码可以在这里找到:https://github.com/awerdich/physionet

# Convolutional blocks
def conv2d_block(model, depth, layer_filters, filters_growth, 
                 strides_start, strides_end, input_shape, first_layer = False):

    ''' Convolutional block. 
    depth: number of convolutional layers in the block (4)
    filters: 2D kernel size (32)
    filters_growth: kernel size increase at the end of block (32)
    first_layer: provide input_shape for first layer'''

    # Fixed parameters for convolution
    conv_parms = {'kernel_size': (3, 3),
                  'padding': 'same',
                  'dilation_rate': (1, 1),
                  'activation': None,
                  'data_format': 'channels_last',
                  'kernel_initializer': 'glorot_normal'}

    for l in range(depth):

        if first_layer:

            # First layer needs an input_shape 
            model.add(layers.Conv2D(filters = layer_filters,
                                    strides = strides_start,
                                    input_shape = input_shape, **conv_parms))
            first_layer = False

        else:
            # All other layers will not need an input_shape parameter
            if l == depth - 1:
                # Last layer in each block is different: adding filters and using stride 2
                layer_filters += filters_growth
                model.add(layers.Conv2D(filters = layer_filters,
                                        strides = strides_end, **conv_parms))
            else:
                model.add(layers.Conv2D(filters = layer_filters,
                                        strides = strides_start, **conv_parms))

        # Continue with batch normalization and activation for all layers in the block
        model.add(layers.BatchNormalization(center = True, scale = True))
        model.add(layers.Activation('relu'))

    return model

def MeanOverTime():
    lam_layer = layers.Lambda(lambda x: K.mean(x, axis=1), output_shape=lambda s: (1, s[2]))
    return lam_layer

# Define the model
# Model parameters
filters_start = 32 # Number of convolutional filters
layer_filters = filters_start # Start with these filters
filters_growth = 32 # Filter increase after each convBlock
strides_start = (1, 1) # Strides at the beginning of each convBlock
strides_end = (2, 2) # Strides at the end of each convBlock
depth = 4 # Number of convolutional layers in each convBlock
n_blocks = 6 # Number of ConBlocks
n_channels = 1 # Number of color channgels
input_shape = (*dim, n_channels) # input shape for first layer


model = Sequential()

for block in range(n_blocks):

    # Provide input only for the first layer
    if block == 0:
        provide_input = True
    else:
        provide_input = False

    model = conv2d_block(model, depth,
                         layer_filters,
                         filters_growth,
                         strides_start, strides_end,
                         input_shape,
                         first_layer = provide_input)

    # Increase the number of filters after each block
    layer_filters += filters_growth



# Remove the frequency dimension, so that the output can feed into LSTM
# Reshape to (batch, time steps, filters)
model.add(layers.Reshape((-1, 224)))
model.add(layers.core.Masking(mask_value = 0.0))
model.add(MeanOverTime())

# Alternative: Replace averaging by LSTM

# Insert masking layer to ignore zeros
#model.add(layers.core.Masking(mask_value = 0.0))

# Add LSTM layer with 3 neurons
#model.add(layers.LSTM(200))
#model.add(layers.Flatten())

# And a fully connected layer for the output
model.add(layers.Dense(4, activation='sigmoid', kernel_regularizer = regularizers.l2(0.1)))


model.summary()

# Compile the model and run a batch through the network
model.compile(loss='categorical_crossentropy',
              optimizer=optimizers.Adam(lr=0.001),
              metrics=['acc'])

history = model.fit_generator(generator = train_generator,
                              steps_per_epoch = 50,
                              epochs = 10,
                              validation_data = val_generator,
                              validation_steps = 50)

model.save('PredictionTest.model')

为了进行预测,我稍微修改了批处理生成器:

def __data_generation(h5file, list_IDs, batch_size, dim, nperseg, noverlap, n_channels, sequence_length, n_classes, shuffle):
    'Generates data containing batch_size samples' # X : (n_samples, *dim, n_channels)
    # Initialization
    X = np.empty((batch_size, *dim, n_channels), dtype = float)
    y = np.empty((batch_size), dtype = int)
    # Generate data
    for i, ID in enumerate(list_IDs):
        data = extend_ts(h5file[ID]['ecgdata'][:, 0], sequence_length)
        data = np.reshape(data, (1, len(data)))

        # Generate spectrogram
        data_spectrogram = spectrogram(data, nperseg = nperseg, noverlap = noverlap)[2]   

        # Normalize
        data_norm = (data_spectrogram - np.mean(data_spectrogram))/np.std(data_spectrogram)

        X[i,] = np.expand_dims(data_norm, axis = 3)

        return X

我给它一些参数并将32个信号放入val_generator(我现在知道它不是发生器)

params = {'batch_size': batch_size,
          'dim': dim,
          'nperseg': spectrogram_nperseg,
          'noverlap': spectrogram_noverlap,
          'n_channels': 1,
          'sequence_length': sequence_length,
          'n_classes': n_classes,
          'shuffle': True}

val_generator = __data_generation(h5file, dataset_list, **params)

然后当我尝试预测时

from keras.models import load_model
model = load_model("Physionet17_ECG_CNN.model")
prediction = model.predict(val_generator)
print(prediction)

我得到了这些预测

[[1.9367344e-03 9.4601721e-01 6.0286120e-02 1.1672693e-03]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]
 [3.3482336e-04 6.3787904e-03 5.1438063e-02 9.9722642e-01]]

有人知道为什么会这样吗? 谢谢

如果有人想查看预测的整个代码

import tensorflow as tf
import numpy as np
import pandas as pd
import os
import h5py
import matplotlib
import scipy.io
import cv2
import numpy as np
from matplotlib import pyplot as plt

# Magic
%matplotlib inline
matplotlib.style.use('ggplot')

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder

# Keras5
import keras
from keras.models import Sequential
from keras import layers
from keras import optimizers
from keras import backend as K
from keras import regularizers

# Tensorflow -- the info from the devices used
import tensorflow as tf
from tensorflow.python.client import device_lib

# Custom imports
from physionet_processing import (fetch_h5data, spectrogram, 
                                  special_parameters, transformed_stats, extend_ts)

from physionet_generator_Copy1 import DataGeneratorAdib

### Open hdf5 file, load the labels and define training/validation splits ###

# Data folder and hdf5 dataset file
data_root = os.path.normpath('.')
hd_file = os.path.join(data_root, 'physioANDptb.h5')

# Open hdf5 file
h5file =  h5py.File(hd_file, 'r')
print(h5file)
# Get a list of dataset names -- keys()-gives the list of all attributes
dataset_list = list(h5file.keys())
#print(dataset_list)
# Encode labels to integer numbers
label_set = ['A', 'N', 'O', '~']
encoder = LabelEncoder().fit(label_set)
label_set_codings = [0, 1, 2, 3]

### Set up batch generators ###

# Parameters needed for the batch generator
# Maximum sequence length
max_length = 18286

# Output dimensions
sequence_length = max_length
spectrogram_nperseg = 64 # Spectrogram window
spectrogram_noverlap = 32 # Spectrogram overlap
n_classes = len(label_set)

batch_size = 32

# import ipdb; ipdb.set_trace() # debugging starts here

# calculate image dimensions
data = fetch_h5data(h5file, [0], sequence_length)# fetch some raw sequences from the hdf5 file
_, _, Sxx = spectrogram(data, nperseg = spectrogram_nperseg, noverlap = spectrogram_noverlap)
dim = Sxx[0].shape
print(data.shape)

# print(dataset_list)

def __data_generation(h5file, list_IDs, batch_size, dim, nperseg, noverlap, n_channels, sequence_length, n_classes, shuffle):
    'Generates data containing batch_size samples' # X : (n_samples, *dim, n_channels)
    # Initialization
    X = np.empty((batch_size, *dim, n_channels), dtype = float)
    y = np.empty((batch_size), dtype = int)
    # Generate data
    for i, ID in enumerate(list_IDs):
        data = extend_ts(h5file[ID]['ecgdata'][:, 0], sequence_length)
        data = np.reshape(data, (1, len(data)))

        # Generate spectrogram
        data_spectrogram = spectrogram(data, nperseg = nperseg, noverlap = noverlap)[2]   

        # Normalize
        data_norm = (data_spectrogram - np.mean(data_spectrogram))/np.std(data_spectrogram)

        X[i,] = np.expand_dims(data_norm, axis = 3)

        return X

params = {'batch_size': batch_size,
          'dim': dim,
          'nperseg': spectrogram_nperseg,
          'noverlap': spectrogram_noverlap,
          'n_channels': 1,
          'sequence_length': sequence_length,
          'n_classes': n_classes,
          'shuffle': True}


val_generator = __data_generation(h5file, dataset_list, **params)

for i, batch in enumerate(val_generator):
    if i == 1:
        break


from keras.models import load_model
model = load_model("Physionet17_ECG_CNN_E50_SPE200.model")

val_generator = np.arange(18810*3)
val_generator = val_generator.reshape(3, 570, 33, 1)
# bla1 = np.arange(18810)
# bla1 = bla1.reshape(1, 570, 33, 1)
# val_generator(2,)= bla1
val_generator.shape

val_generator = np.random.random((32, 570, 33, 1))


prediction = model.predict(val_generator)
print(prediction)

0 个答案:

没有答案