如何修复:ValueError: 检查输入时出错:期望 conv2d_130_input 的形状为 (1, 512, 512),但得到的数组形状为 (79, 512, 512)

我是一个刚开始学习卷积神经网络的初学者。

因此,我正在构建一个二维卷积神经网络,用于预测脑肿瘤类型,并有一个关于NumPy数组的问题。我的模型的输入形状是 (1, 512, 512),即 (通道数, 图像高度, 图像宽度)。第四维是图像数量,似乎是由TensorFlow自动定义的。这只是一个简短的背景介绍。我有3064个扩展名为”.mat”的文件,包含脑肿瘤的MRI扫描。一切都已设置好。我将”.mat”文件转换为NumPy矩阵,并将整个矩阵列表附加到一个单一的NumPy数组中,作为CNN的输入。我还将相应的标签(在输入模型时与图像索引链接)作为NumPy数组。图像和标签中的所有数字都是浮点类型。

再次强调,我的输入形状是 (1, 512, 512)。然而,在拟合我的模型时,我得到了以下错误:

ValueError: 检查输入时出错:期望 conv2d_130_input 的形状为 (1, 512, 512),但得到的数组形状为 (79, 512, 512)

因此,我正在切片我的NumPy数组以创建 train_images, train_labels, test_images, test_labels。我已经验证了训练集和测试集的长度与它们的标签相匹配。它们也是数组,我检查了多次。这是一个值错误。那么,我该如何修复这个问题呢?

我甚至不知道输入形状何时变成了 (79,512,512)。我有一个循环来将 f”{n}.mat” 图像转换为矩阵。我使用100张图像进行测试,其中80张用于训练,20张用于测试。我认为错误出在这里,输入形状应该是 (通道数, 图像高度, 图像宽度),但训练用的图像数量却被放置在通道数的位置上。因此,输入被放置为 (图像数量, 图像高度, 图像宽度)。这是错误的,应该更改,但我不知道如何做。或者,我可能是错的,我所说的话可能没有意义。我提供了所有代码,在Colab上运行。如果你下载了代码并想运行它以帮助我,请确保更改图像路径。非常感谢!

数据集:https://figshare.com/articles/brain_tumor_dataset/1512427/5

#通过PIP将必要的库导入到虚拟环境中
try:
  !python -m pip install --upgrade pip #快速更新PIP到最新版本
  !python -m pip install pymatreader
  !python -m pip install pyswarm #一个用于测试目的的有趣库
  print("""以下库可用并已成功获取:
  >>> PyMatReader
  >>> Particle Swarm""")
except Exception:
  print("""以下库不可用且未能获取:
  >>> PyMatReader
  >>> Particle Swarm""")
  pass
#将必要的库导入到虚拟环境中
from __future__ import absolute_import, division, print_function, unicode_literals
import random as rnd
from random import shuffle
import numpy as np
import sys
import scipy as sp
from scipy.ndimage import gaussian_filter
import pymatreader as pym
import pandas as pd
import seaborn as sns
import matplotlib as mpl
import matplotlib.image as mplimg
import matplotlib.pyplot as plt
import PIL
from PIL import Image
import imageio
import sklearn as sk
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import image
import sklearn.metrics as skm
print("""以下库已成功导入:
  >>> Future
  >>> Random (带有shuffle)
  >>> NumPy
  >>> System
  >>> SciPy (带有gaussian filter)
  >>> PyMatReader
  >>> Pandas
  >>> Seaborn
  >>> Matplotlib (带有PyPlot & Image)
  >>> PIL (带有Image)
  >>> Imageio
  >>> Sci-Kit Learn (带有metrics & train_test_split)
  >>> Sci-kit Learn Feature Extraction (带有Image)""")
try:
  %tensorflow_version 2.x
  import keras
  import tensorflow as tf
  print("TensorFlow版本2.x可用并已成功导入。")
except Exception:
  %tensorflow_version 1.x
  import keras
  import tensorflow as tf
  print("TensorFlow版本2.x不可用。已改为导入TensorFlow版本1.x。")
  pass
from tensorflow.keras import datasets, layers, models
import keras.preprocessing
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D
from keras.optimizers import Adam
import pyswarm
from pyswarm import pso
autoTune = tf.data.experimental.AUTOTUNE
print("""以下深度学习优化器已成功导入:
  >>> Adam
  >>> Particle Swarm (带有pso)""")
print("所有库已成功导入。")
#使用Seaborn和Matplotlib理解图像数据
classNames = {1 : "脑膜瘤", 2 : "胶质瘤", 3 : "垂体瘤", 4 : "未知", 5 : "未知"}
outputSize = len(classNames)
chooseImgNum = 2978
example = pym.read_mat(f'/content/gdrive/My Drive/My Files/Neuroimaging/Neuroimaging Datasets/MATLAB Files/{chooseImgNum}.mat')
cjdata = example['cjdata']
pid = cjdata['PID']
img = cjdata['image']
label = cjdata['label']
tumorBorder = cjdata['tumorBorder']
tumorMask = cjdata['tumorMask']
print("肿瘤边界是:\n", tumorBorder, "\n")
print("肿瘤掩膜是:\n", tumorMask, "\n")
def printImage():
  plt.figure(figsize=(5, 5))
  plt.imshow(img, cmap=None)
def matrixConv(): #仅用于数据可视化
  matrix = np.asmatrix(tumorBorder)
  plt.figure(figsize=(5, 5))
  return matrix
def applyGrayscale():
  plt.figure(figsize=(5, 5))
  plt.imshow(img, cmap='gray')
print("""      以下是原始图像及其灰度应用:
____________________________________________________________________________""")
printImage()
applyGrayscale()
#从数据集中预处理脑图像
range1 = np.arange(0, 100)
imgMatrices = []
imgNum = 1
i = 1
while imgNum in range1:
  imgNum = pym.read_mat(f'/content/gdrive/My Drive/My Files/Neuroimaging/Neuroimaging Datasets/MATLAB Files/{imgNum}.mat')
  cjdata = imgNum['cjdata']
  imgMatrix = cjdata['image']
  # plt.figure(figsize=(5, 5))
  # plt.imshow(image_matrix, cmap='gray')
  imgMatrixNP = np.asmatrix(imgMatrix)
  imgArrayNP = np.asarray(imgMatrixNP)
  imgMatrices.append(imgArrayNP)
  imgNum = i
  i = i + 1
print("图像输入列表的长度为:", len(imgMatrices))
imgMatricesNP = np.asarray(imgMatrices)
print("转换后的图像输入数组的长度为:", len(imgMatricesNP), "\n")
print("图像输入数组:")
imgMatricesNP #打印原始数组
#监督学习:理解癌症类型标签
np.set_printoptions(threshold=3)
#np.set_printoptions(threshold=sys.maxsize) #检查整个数组的内容
rawMatData = pym.read_mat('/content/gdrive/My Drive/My Files/Neuroimaging/Neuroimaging Datasets/cvind.mat')
print("以“.mat”格式的标签文件转换为字典格式:", rawMatData)
matDataList = list(rawMatData.values())
print("标签转换为列表格式:", matDataList)
matDataArray = np.asarray(matDataList)
print("标签转换为数组格式:", matDataArray, "\n")
shapedMatDataArray = matDataArray.reshape(-1, 3064, 1)
print("重塑后的标签数组格式:\n", shapedMatDataArray, "\n")
matData = pd.DataFrame(matDataArray)
print("标签转换为Pandas DataFrame:")
matData #打印DataFrame
#根据图像编号查看标签
def imgLabelCheck(n):
  callback = matData.at[0, n-1]
  print(f"图像编号 {n} 的癌症类型为:{classNames[callback]}。")
  return
pickImg = 1 #选择一个图像编号以查看其癌症类型
imgLabelCheck(pickImg)
#准备数据集:循环训练集和测试集
print("___________________________________________________________________________________\n")
train_images = np.array([imgMatricesNP[0:79]])
print("训练图像范围是:\n", train_images, "\n")
uppTrBn = len(train_images)
loqTrRng = 0
uppTrRng = 79
train_labels = np.asarray(matData.loc[:, loqTrRng:uppTrRng], dtype=float, order='A')
print("训练标签范围是:", train_labels)
print("___________________________________________________________________________________\n")
test_images = np.array([imgMatricesNP[80:100]])
print("测试图像范围是:\n", test_images, "\n")
uppTsBn = len(test_images)
loqTsRng = 80
uppTsRng = 100
test_labels = np.asarray(matData.loc[:, loqTsRng:uppTsRng], dtype=float, order='A')
print("测试标签范围是:", test_labels)
print("___________________________________________________________________________________")
#train_labels #验证范围是否确实为NumPy数组
#test_labels
#定义卷积神经网络
model = models.Sequential()
model.add(layers.Conv2D(512, (3, 3), activation='relu', data_format="channels_first", input_shape=(1, 512, 512))) #输入层
#model.add(layers.Dropout(0.5, noise_shape=None, seed=None)) #可选的Dropout层
model.add(layers.MaxPooling2D((2, 2), padding='same')) #最大池化层1
model.add(layers.Conv2D(1024, (3, 3), activation='relu', padding='same')) #隐藏卷积层1
model.add(layers.Dropout(0.5, noise_shape=None, seed=None)) #可选的Dropout层
model.add(layers.MaxPooling2D((2, 2), padding='same')) #最大池化层2
model.add(layers.Conv2D(1024, (3, 3), activation='relu', padding='same')) #隐藏卷积层2
#model.add(layers.Dropout(0.5, noise_shape=None, seed=None)) #可选的Dropout层
model.add(layers.MaxPooling2D((2, 2), padding='same')) #最大池化层3
model.add(layers.Conv2D(1024, (3, 3), activation='relu', padding='same')) #隐藏卷积层3
model.add(layers.Dropout(0.5, noise_shape=None, seed=None)) #可选的Dropout层
model.add(layers.MaxPooling2D((2, 2), padding='same')) #最大池化层4
model.add(layers.Conv2D(1024, (3, 3), activation='relu', padding='same')) #隐藏卷积层4
#model.add(layers.Dropout(0.5, noise_shape=None, seed=None)) #可选的Dropout层
model.add(layers.MaxPooling2D((2, 2), padding='same')) #最大池化层5
model.add(layers.Conv2D(1024, (3, 3), activation='relu', padding='same')) #隐藏卷积层5
model.add(layers.Dropout(0.5, noise_shape=None, seed=None)) #可选的Dropout层
model.add(layers.MaxPooling2D((2, 2), padding='same')) #最大池化层6
model.add(layers.Conv2D(1024, (3, 3), activation='relu', padding='same')) #隐藏卷积层6
#model.add(layers.Dropout(0.5, noise_shape=None, seed=None)) #可选的Dropout层
model.add(layers.Flatten()) #平铺层
model.add(layers.Dense(512, activation='relu')) #密集层1
model.add(layers.Dense(256, activation='relu')) #密集层2
model.add(layers.Dense(128, activation='relu')) #密集层3
model.add(layers.Dense(64, activation='relu')) #密集层4
model.add(layers.Dense(32, activation='relu')) #密集层5
model.add(layers.Dense(16, activation='relu')) #密集层6
model.add(layers.Dense(outputSize, activation='softmax')) #输出层
model.summary()
#使用优化器编译卷积神经网络
#Adam优化器非常适合生物图像分类。
#优化器会自动执行前向和后向传播。
model.compile(
    optimizer='Adam',
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy'],
    loss_weights=None,
    sample_weight_mode=None,
    weighted_metrics=None,
    target_tensors=None
)
print("神经影像模型已成功编译。")
#训练卷积神经网络
history = model.fit(train_images, train_labels, epochs=10, batch_size=1, verbose=1,
                    validation_data=(test_images, test_labels))
print("\n神经影像模型已成功训练。")

此页面上的每个代码框代表Colab或Jupyter笔记本中的一个代码单元。再次感谢所有帮助和建议!(模型尚未完全构建,但添加了层以进行实验。)


回答:

在以下代码行之后添加一行:

train_images = np.reshape(train_images, (-1,1,512,512))

在你的代码中的以下行之后:

train_images = np.array([imgMatricesNP[0:79]])

以便获取单个图像的 input_shape=(1, 512, 512) 而不是 (79, 512, 512),因为模型期望的输入形状是 (1, 1, 512, 512)(根据维度 (batch_size, channels, height, width)),而你当前的代码提供的输入形状是 (1, 79, 512, 512)。如果你有足够的计算资源,可以将batch_size增加到 8(例如),这样你的总输入形状将是 (8, 1, 512, 512)

同样,对 test_images 执行类似的操作:

test_images = np.reshape(test_images, (-1,1,512,512))

在以下行之后:

test_images = np.array([imgMatricesNP[80:100]])

附注:看起来你的意图是从输入 imgMatricesNP 中切片前80张图像。然而,使用 imgMatricesNP[0:79],你只得到了前79张图像(因为Python中切片的最后一个索引是排除的)。所以,修正应该是:

train_images = np.array([imgMatricesNP[0:80]])

并将 uppTrRng 设为80。

希望这对你有帮助!:)

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注