0

我正在尝试构建一个 CNN,它可以将 3D MRI 文件分类为两个类别之一,基本上有病或没有病。我做了很多谷歌搜索,似乎一致认为 2D CNN 是最好的,因为数据是黑白的,因此维度降低了。

在将所有内容传输到远程工作站以运行所有内容之前,我正在使用 Google Colab,并且我正在使用数据的子集在运行所有内容之前使其正常工作,但我有 20 个黑白文件 (189, 233 , 197)。以下是我到目前为止的代码:

import numpy as np
import glob
import os
import tensorflow as tf
import pandas as pd
import glob

pip install SimpleITK
import SimpleITK as sitk

from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from keras.preprocessing.image import ImageDataGenerator


from keras.utils import plot_model
from keras.utils import to_categorical
from keras.utils import np_utils

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout

from google.colab import drive
drive.mount('/content/gdrive')

datapath = ('/content/gdrive/My Drive/DirectoryTest/All Data/')
patients = os.listdir(datapath)
labels_df = pd.read_csv('/content/Data_Index.csv', index_col = 0 )

labelset = []

for i in patients:
  label = labels_df.loc[i, 'Group']
  if label is 'AD':
    np.char.replace(label, ['AD'], [0])
  if label is 'CN':
    np.char.replace(label, ['CN'], [1])
  labelset.append(label)

label_encoder = LabelEncoder()
labelset = label_encoder.fit_transform(labelset)

labelset = np_utils.to_categorical(labelset, num_classes= 2)


FullDataSet = []

for i in patients:
  a = sitk.ReadImage(datapath + i)
  b = sitk.GetArrayFromImage(a)
  #c = np.reshape(b, (197,233,189, 1))
  FullDataSet.append(b)

training_data, testing_data, training_labels, testing_labels = train_test_split(FullDataSet, labelset, train_size=0.70,test_size=0.30)

dataset_train = tf.data.Dataset.from_tensor_slices((training_data, training_labels))
dataset_test = tf.data.Dataset.from_tensor_slices((testing_data, testing_labels))

# 2D CNN

CNN_model = tf.keras.Sequential(
  [
      #tf.keras.layers.Input(shape=(189, 233, 197, 1), batch_size=2),
      #tf.keras.layers.Reshape((197, 233, 189, 1)),   
                              
      tf.keras.layers.Conv2D(kernel_size=(7, 7), data_format='channels_last', filters=64, activation='relu',
                             padding='same', strides=( 3, 3), input_shape=(189, 233, 197)),
      #tf.keras.layers.BatchNormalization(center=True, scale=False),
      tf.keras.layers.MaxPool2D(pool_size=(3, 3), padding='same'),
      tf.keras.layers.Dropout(0.20),
      
      tf.keras.layers.Conv2D(kernel_size=( 7, 7), filters=128, activation='relu', padding='same', strides=( 3, 3)),
      #tf.keras.layers.BatchNormalization(center=True, scale=False),
      tf.keras.layers.MaxPool2D(pool_size=(3, 3), padding='same'),
      tf.keras.layers.Dropout(0.20),      

      tf.keras.layers.Conv2D(kernel_size=( 7, 7), filters=256, activation='relu', padding='same', strides=( 3, 3)),
      #tf.keras.layers.BatchNormalization(center=True, scale=False),
      tf.keras.layers.MaxPool2D(pool_size=(3, 3), padding = 'same'),
      tf.keras.layers.Dropout(0.20), 

      # last activation could be either sigmoid or softmax, need to look into this more. Sig for binary output, Soft for multi output 
      tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(256, activation='relu'),   
      tf.keras.layers.Dense(64, activation='relu'),
      tf.keras.layers.Dropout(0.20),
      tf.keras.layers.Dense(2, activation='softmax')

  ])
# Compile the model
CNN_model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.00001), loss='categorical_crossentropy', metrics=['accuracy'])

# print model layers
CNN_model.summary()

CNN_history = CNN_model.fit(dataset_train, epochs=10, validation_data=dataset_test)

这会产生错误

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-89-a8b210ec2e72> in <module>()
      1 #running of the model
      2 #CNN_history = CNN_model.fit(dataset_train, epochs=100, validation_data =dataset_test, validation_steps=1)
----> 3 CNN_history = CNN_model.fit(dataset_train, epochs=10, validation_data=dataset_test)
      4 
      5 

10 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs)
    971           except Exception as e:  # pylint:disable=broad-except
    972             if hasattr(e, "ag_error_metadata"):
--> 973               raise e.ag_error_metadata.to_exception(e)
    974             else:
    975               raise

ValueError: in user code:

    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:806 train_function  *
        return step_function(self, iterator)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:796 step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:1211 run
        return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2585 call_for_each_replica
        return self._call_for_each_replica(fn, args, kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2945 _call_for_each_replica
        return fn(*args, **kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:789 run_step  **
        outputs = model.train_step(data)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:747 train_step
        y_pred = self(x, training=True)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py:976 __call__
        self.name)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/input_spec.py:196 assert_input_compatibility
        str(x.shape.as_list()))

    ValueError: Input 0 of layer sequential_24 is incompatible with the layer: : expected min_ndim=4, found ndim=3. Full shape received: [189, 233, 197]

所以我缺少一个维度,我认为是因为它不是 rgb 图像,所以缺少通道数据。所以我回到下面的代码行并使用 np.reshape 添加一个维度:

  a = sitk.ReadImage(datapath + i)
  b = sitk.GetArrayFromImage(a)
  c = np.reshape(b, (197,233,189, 1))
  FullDataSet.append(b)

当我通过所有内容运行时,我收到以下错误:

Epoch 1/10
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-a8b210ec2e72> in <module>()
      1 #running of the model
      2 #CNN_history = CNN_model.fit(dataset_train, epochs=100, validation_data =dataset_test, validation_steps=1)
----> 3 CNN_history = CNN_model.fit(dataset_train, epochs=10, validation_data=dataset_test)
      4 
      5 

10 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs)
    971           except Exception as e:  # pylint:disable=broad-except
    972             if hasattr(e, "ag_error_metadata"):
--> 973               raise e.ag_error_metadata.to_exception(e)
    974             else:
    975               raise

ValueError: in user code:

    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:806 train_function  *
        return step_function(self, iterator)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:796 step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:1211 run
        return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2585 call_for_each_replica
        return self._call_for_each_replica(fn, args, kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2945 _call_for_each_replica
        return fn(*args, **kwargs)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:789 run_step  **
        outputs = model.train_step(data)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:747 train_step
        y_pred = self(x, training=True)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/base_layer.py:976 __call__
        self.name)
    /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/input_spec.py:216 assert_input_compatibility
        ' but received input with shape ' + str(shape))

    ValueError: Input 0 of layer sequential_4 is incompatible with the layer: expected axis -1 of input shape to have value 197 but received input with shape [197, 233, 189, 1]

我已经在这几天了,任何帮助将不胜感激,谢谢!

4

1 回答 1

1

欢迎来到堆栈溢出。对于 2D 网络,您的输入应具有 形状(batch_size, height, width, channels)。您在数组末尾添加额外维度是正确的。那代表灰度颜色通道。

你得到错误

ValueError: Input 0 of layer sequential_4 is incompatible with the layer: expected axis -1 of input shape to have value 197 but received input with shape [197, 233, 189, 1]

因为您input_shape在网络的第一层定义错误。应该是input_shape=(height, width, 1),并且您需要选择正确的高度和宽度。请注意,我们在这里省略了批量维度。

这些特征需要重新塑造成一系列形状(n_slices, height, width, 1)。换句话说,您需要堆叠体积的 2D 切片。体积的尺寸可能具有轴向、冠状和矢状平面,因此您需要决定要在哪些视图上训练模型。此外,您可以堆叠所有视图,实际上是数据集大小的三倍。虽然要堆叠所有切片,但三个平面需要具有相同的形状。在您的情况下,飞机的形状不同。

这是堆叠数据切片的一种方法。

import numpy as np

volumes = []
for patient in patients:
    image = sitk.ReadImage(datapath + patient)
    volume = sitk.GetArrayFromImage(image)
    volumes.append(volume)

# Choose the plane you want by changing the `axis` parameter.
axis = 1
features = np.concatenate(volumes, axis=axis)

# Move the concatenation axis to the first position. We will take
# batches along this dimension, so each batch contains several slices.
features = np.moveaxis(slices, source=axis, destination=0)

# Add the grayscale channel dimension.
features = features[..., np.newaxis]

不要忘记沿批次维度打乱您的输入!

于 2020-08-12T21:11:28.007 回答