【问题标题】:Input 0 of layer conv1 is incompatible with the layer: expected ndim=4, found ndim=3. Full shape received: [None, 256, 3]层 conv1 的输入 0 与层不兼容:预期 ndim=4,发现 ndim=3。收到的完整形状:[None, 256, 3]
【发布时间】:2020-11-15 20:52:00
【问题描述】:

首先,我知道 NN 正在处理一个数组。这个好像没有关系。

我拥有的是一个 U-Net,一个相当标准的 U-Net。在代码(如下)中,我尝试了生成器并将数据作为数组传递。两种方法都抱怨数据形状错误(见帖子标题)。但我正在传递一个 (None, 256, 256, 3) 数组! 如果您指出错误在哪里,我将不胜感激。很可能是一些愚蠢而简单的事情:) 该代码是一个 Colab 笔记本,它应该从上到下执行,最后一行(“test”函数)产生错误,真正的问题在 Keras:fit()

代码: 我在源和标签文件夹中有图像(目前相同)。

from google.colab import drive
drive.mount("/content/drive/", force_remount=True)

#!pip install -q efficientnet 
#import efficientnet.tfkeras as efn

#!pip install livelossplot
#from livelossplot.tf_keras import PlotLossesCallback

import numpy as np
#from sklearn.utils import shuffle

from glob import glob
from pathlib import Path
from shutil import copyfile

import pandas as pd

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

#from tensorflow.keras.utils import Sequence

import sys
import random
#import math
#import numpy as np
#
#import skimage.io
#from skimage.util import img_as_ubyte
#from skimage.util import random_noise
#from skimage.transform import rescale
#from skimage.color import rgb2gray
#from skimage.transform import rotate
#import skimage.filters
#from scipy import ndimage
#
#import matplotlib
import matplotlib.pyplot as plt
#import matplotlib.patheffects as PathEffects
#
import os
from os import listdir
from os.path import isfile, join
#
#import json
#import datetime
##import skimage.draw
#
#import pickle
#
#from copy import copy, deepcopy
#
#import tensorflow as tf
#import tensorflow.keras.layers as Layers
from tensorflow.keras import regularizers
#
from tensorflow.keras.optimizers import Adamax
#
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.preprocessing.image import array_to_img, img_to_array
#
from tensorflow.keras import backend as K
#
from tensorflow.keras.applications.vgg16 import VGG16,preprocess_input
from tensorflow.keras.applications import InceptionResNetV2, Xception, NASNetLarge
#
from mpl_toolkits.mplot3d import Axes3D
from sklearn.manifold import TSNE
#
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Dense, Activation, Dropout, Flatten, Lambda, concatenate, BatchNormalization, GlobalAveragePooling2D, UpSampling2D
#from tensorflow.keras.layers import LeakyReLU
from tensorflow.keras.callbacks import LambdaCallback
#from tensorflow.keras.callbacks import ReduceLROnPlateau, LearningRateScheduler
from tensorflow.keras.callbacks import ModelCheckpoint
#
from tensorflow.keras.models import Model
from tensorflow.keras.models import Sequential
#from sklearn.neighbors import NearestNeighbors
#
#import pylab as pl
import seaborn as sns
#
import cv2
#
##import warnings
##warnings.simplefilter("ignore", category=DeprecationWarning)
##warnings.filterwarnings("ignore")
##os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

#from tensorflow.keras.utils import Sequence
from tensorflow.python.keras.utils.data_utils import Sequence

#%tensorflow_version 1.5

# Is GPU Working?
import tensorflow as tf
print(tf.__version__)
tf.test.gpu_device_name()   

working_path = "/content/drive/My Drive/03_unet_selector/"

best_weights_filepath = working_path + "models/03_unet_selector_best.h5"
last_weights_filepath = working_path + "models/03_unet_selector_last.h5"

IMAGE_SIZE = 256
input_shape=(IMAGE_SIZE, IMAGE_SIZE, 3)

BATCH_SIZE = 8
EPOCHS = 20

u_model = 0

TRAINING_IMAGES_PERCENT = 0.6
VALIDATION_IMAGES_PERCENT = 0.2

nL2 = 0.2
opt = tf.keras.optimizers.Adam(0.0001)

def loadImage(path):
    img=cv2.imread(str(path)) #, cv2.IMREAD_GRAYSCALE)
    img = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE))
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = img.astype(np.float32)/255.
    img = img.reshape(input_shape)
    
    return img

arrLabeledData = []
arrExtensions = ['.jpg','.jpeg','.png', '.gif']
nCount = 0

for strExtension in arrExtensions:
  for strImagePath in Path(working_path + "images/inputs/").glob("**/*" + strExtension):
      # Get the input image
      strImageName = os.path.basename(strImagePath)

      # Get corresponding output image (label)
      strLabelPath = working_path + "images/labels/" + strImageName
      
      # --- 
      img_src = loadImage(strImagePath)
      img_lbl = loadImage(strLabelPath)

      arrLabeledData.append(
          {
              "src" : strImageName,
              "X" : img_src,
              "Y" : img_lbl
          }
      )
      
      # ---
      
      if(nCount % 10 == 0):
        print(nCount)
      nCount = nCount + 1

nImageIdx = random.randint(0, len(arrLabeledData) - 1)

img_src = loadImage(join(working_path, "images/inputs/", arrLabeledData[nImageIdx]['src']))
img_lbl = loadImage(join(working_path, "images/labels/", arrLabeledData[nImageIdx]['src']))
#img = img.reshape((IMAGE_SIZE, IMAGE_SIZE))
print(arrLabeledData[nImageIdx]['src'])
plt.imshow(img_src) #, cmap='gray')
plt.show()
plt.imshow(img_lbl)
plt.show()

datagen = ImageDataGenerator(
  samplewise_center=True,
  rotation_range=0,
  width_shift_range=0,
  height_shift_range=0,
  zoom_range=0
)

def deleteSavedNet(best_weights_filepath):
    if(os.path.isfile(best_weights_filepath)):
        os.remove(best_weights_filepath)
        print("deleteSavedNet():File removed")
    else:
        print("deleteSavedNet():No file to remove")  

def plotHistory(history, strParam1, strParam2):
    plt.plot(history.history[strParam1], label=strParam1)
    plt.plot(history.history[strParam2], label=strParam2)
    #plt.title('strParam1')
    #plt.ylabel('Y')
    #plt.xlabel('Epoch')
    plt.legend(loc="best")
    plt.show()
    
def plotFullHistory(history):
    arrHistory = []
    for i,his in enumerate(history.history):
        arrHistory.append(his)
    plotHistory(history, arrHistory[0], arrHistory[2])    
    plotHistory(history, arrHistory[1], arrHistory[3])  

def createModel(nL2=0.2, optimizer="adam"):
  inputs = keras.Input(shape=(IMAGE_SIZE, IMAGE_SIZE, 3))

  conv1 = layers.Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv1")(inputs)
  conv1 = layers.Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv1a")(conv1)
  pool1 = layers.MaxPooling2D(pool_size=(2, 2), name="pool1")(conv1)
  conv2 = layers.Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv2")(pool1)
  conv2 = layers.Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv2a")(conv2)
  pool2 = layers.MaxPooling2D(pool_size=(2, 2), name="pool2")(conv2)
  conv3 = layers.Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv3")(pool2)
  conv3 = layers.Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv3a")(conv3)
  pool3 = layers.MaxPooling2D(pool_size=(2, 2), name="pool3")(conv3)
  conv4 = layers.Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv4")(pool3)
  conv4 = layers.Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv4a")(conv4)
  drop4 = layers.Dropout(0.5, name="drop4")(conv4)
  pool4 = layers.MaxPooling2D(pool_size=(2, 2), name="pool4")(drop4)

  conv5 = layers.Conv2D(1024, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv5")(pool4)
  conv5 = layers.Conv2D(1024, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv5a")(conv5)
  drop5 = layers.Dropout(0.5, name="drop5")(conv5)

  up6 = layers.Conv2D(512, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="up6")(UpSampling2D(size = (2,2))(drop5))
  merge6 = layers.concatenate([drop4,up6], axis = 3)
  conv6 = layers.Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv6")(merge6)
  conv6 = layers.Conv2D(512, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv6a")(conv6)

  up7 = layers.Conv2D(256, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="up7")(UpSampling2D(size = (2,2), name="up7a")(conv6))
  merge7 = layers.concatenate([conv3,up7], axis = 3)
  conv7 = layers.Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv7")(merge7)
  conv7 = layers.Conv2D(256, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv7a")(conv7)

  up8 = layers.Conv2D(128, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="up8")(UpSampling2D(size = (2,2), name="up8a")(conv7))
  merge8 = layers.concatenate([conv2,up8], axis = 3)
  conv8 = layers.Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv8")(merge8)
  conv8 = layers.Conv2D(128, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv8a")(conv8)

  up9 = layers.Conv2D(64, 2, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="up9")(UpSampling2D(size = (2,2), name="up9a")(conv8))
  merge9 = layers.concatenate([conv1,up9], axis = 3)
  conv9 = layers.Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv9")(merge9)
  conv9 = layers.Conv2D(64, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv9a")(conv9)
  conv9 = layers.Conv2D(3, 3, activation = 'relu', padding = 'same', kernel_initializer = 'he_normal', name="conv10")(conv9)
  conv10 = layers.Conv2D(1, 1, activation = 'sigmoid')(conv9)

  model = keras.Model(inputs=inputs, outputs=conv10)

  model.compile(optimizer = optimizer, loss = keras.losses.BinaryCrossentropy(), metrics = ['accuracy'])
    
  #model.summary()

  return model

def gen(bIsTrain):
  while True:
    arrBatchImages = []
    arrBatchLabels = []

    for i in range(BATCH_SIZE):
      transform_parameters = {
        'theta': random.randint(0, 180),
        'flip_horizontal': random.randint(0, 1),
        'flip_vertical': random.randint(0, 1)
      }

      if(bIsTrain):
        nStart = 0
        nEnd = int(len(arrLabeledData) * TRAINING_IMAGES_PERCENT - 1)
      else:
        nStart = int(len(arrLabeledData) * TRAINING_IMAGES_PERCENT)
        nEnd = nStart + int((TRAINING_IMAGES_PERCENT + VALIDATION_IMAGES_PERCENT) - 1)

      nImageIdx = random.randint(nStart, nEnd)
      img_src = arrLabeledData[nImageIdx]['X']
      arrImgSrc = img_to_array(img_src)
      arrImgSrc = datagen.apply_transform(arrImgSrc, transform_parameters) #/ 255.
      arrImgSrc = np.array(arrImgSrc, dtype="float32")

      img_lbl = arrLabeledData[nImageIdx]['Y']
      arrImgLbl = img_to_array(img_lbl)
      arrImgLbl = datagen.apply_transform(arrImgLbl, transform_parameters) #/ 255.
      arrImgLbl = np.array(arrImgLbl, dtype="float32")

      arrBatchImages.append(arrImgSrc)
      arrBatchLabels.append(arrImgLbl)

    yield arrBatchImages, arrBatchLabels

arrNext = next(gen(True))
#print(np.array(arrNext[0]).shape, np.array(arrNext[1]).shape)
plt.imshow(arrNext[0][0])
plt.show()

gen_train = gen(True)
gen_valid = gen(False)

def getCallbacks(monitor, mode):
    checkpoint = ModelCheckpoint(best_weights_filepath, monitor=monitor, save_best_only=True, save_weights_only=True, mode=mode, verbose=1)
    save_model_at_epoch_end_callback = LambdaCallback(on_epoch_end=lambda epoch, logs: u_model.save_weights(last_weights_filepath))  
    callbacks_list = [checkpoint, save_model_at_epoch_end_callback]  # , early]

    return callbacks_list

def loadModel(bBest):
  global u_model

  if(bBest):
    path = best_weights_filepath
    strMessage = "load best model"
  else:
    path = last_weights_filepath
    strMessage = "load last model"

  if(os.path.isfile(path)):
    u_model.load_weights(path)
    print(strMessage, ": File loaded")
  else:
    print(strMessage, ": No file to load")

  return u_model

def trainNetwork(EPOCHS, nL2, optimizer, bCumulativeLearning = False):
  global u_model
  global history

  if(bCumulativeLearning == False):
    deleteSavedNet(best_weights_filepath)

  random.seed(7)
  
  u_model = createModel(nL2, optimizer)
  print("Model created")
  
  callbacks_list = getCallbacks("val_accuracy", 'max')  
      
  if(bCumulativeLearning == True):
    loadModel(u_model, False)

  nNumOfTrainSamples = int(len(arrLabeledData) * TRAINING_IMAGES_PERCENT - 1)

  STEP_SIZE_TRAIN = nNumOfTrainSamples // BATCH_SIZE
  #if(STEP_SIZE_TRAIN < 100):
  #  STEP_SIZE_TRAIN = 100

  nNumOfValidSamples = int(nNumOfTrainSamples * VALIDATION_IMAGES_PERCENT / TRAINING_IMAGES_PERCENT)
  STEP_SIZE_VALID = nNumOfValidSamples // BATCH_SIZE
  #if(STEP_SIZE_VALID < 100):
  #  STEP_SIZE_VALID = 100

  print(STEP_SIZE_TRAIN, STEP_SIZE_VALID)
  print("Available metrics: ", u_model.metrics_names)

#  history = u_model.fit(gen_train, 
#    validation_data=gen_valid, verbose=0,
#    epochs=EPOCHS, steps_per_epoch=STEP_SIZE_TRAIN, 
#    validation_steps=STEP_SIZE_VALID, callbacks=callbacks_list)
#    #workers=4, 
#    #use_multiprocessing=True)

  X_train = []
  Y_train = []
  for nIdx in range(int(len(arrLabeledData) * (TRAINING_IMAGES_PERCENT + VALIDATION_IMAGES_PERCENT))):
    X_train.append(arrLabeledData[nIdx]['X'])
    Y_train.append(arrLabeledData[nIdx]['Y'])

  #np.array(Y_train[0]).shape

  u_model.fit(X_train, Y_train, validation_split=STEP_SIZE_VALID / STEP_SIZE_TRAIN, batch_size=BATCH_SIZE, epochs=EPOCHS, callbacks=callbacks_list)

  print(nL2)
  plotFullHistory(history)
  
  # TBD: here, return best model, not last one
  return u_model

def plotAllTestImages():
  for nIdx in range(10): #int(len(arrLabeledData) * (TRAINING_IMAGES_PERCENT + VALIDATION_IMAGES_PERCENT)), len(arrLabeledData)): 
    img_src = arrLabeledData[nIdx]['X']
    img_lbl = arrLabeledData[nIdx]['Y']

    arrImgSrc = img_src.reshape(1, IMAGE_SIZE, IMAGE_SIZE, 3)

    predicts = u_model.predict(arrImgSrc)
      
    img_pred = predicts.reshape(IMAGE_SIZE, IMAGE_SIZE, 3)
      
    f, axarr = plt.subplots(1,2)
    axarr[0,0].imshow(img_src)
    axarr[0,1].imshow(img_pred)
    plt.show()

def test(EPOCHS = EPOCHS, nL2 = nL2, optimizer = optimizer, bCumulativeLearning = False):
  global u_model
  
  u_model = trainNetwork(EPOCHS, nL2, optimizer, bCumulativeLearning)
  print("loading best model")
  u_model = loadModel(u_model, True)

  plotAllTestImages()

  print(">>> done <<<")

np.random.seed(7)
test(EPOCHS, nL2, opt, False) # **Error is displayed here**

【问题讨论】:

    标签: tensorflow keras neural-network


    【解决方案1】:

    看起来问题在于使用 append 创建 X_train 和 Y_train。

    我会检查它们的形状并尝试使用堆栈来代替,这将在开头添加一个维度来表示样本数量。这是一个简化的示例:

    a=np.array([[0,1,2],[3,4,5]])
    b=np.array([[6,7,8],[9,10,11]])
    c=np.stack((a,b))   #shape (2,2,3) with the first 2 representing the number of samples
    

    【讨论】:

    • 当我增加 X 和 Y 数组的大小时,无法弄清楚如何堆叠数据。使用 append 的部分应该做哪些改动?
    • 结果(使用追加时)数组的形状与预期一致:(126, 256, 256, 3),126 是 num。图片
    • 奇怪 - 如果 arrLabeledData[nIdx]['X'] 是一个数组,似乎 X_train 将是一个数组列表而不是单个数组。如果是这种情况,您可以执行 np.stack(X_train) 将 3D 数组列表转换为 4D 数组。如果不是,我不确定问题出在哪里。
    • 致珍妮的评论:我认为这不是问题所在。我传递给“fit”的数组的维度是 (126, 256, 256, 3),126 是 num。的图像。 AFAIK,这是我们应该通过的 - fitt 是 num。项目,然后是图像尺寸的 3 个数字。我仍在寻找建议:请帮助。
    • 附加信息。当通过 Sequence 实现数据馈送时,一切正常。
    猜你喜欢
    • 2020-08-13
    • 2020-08-11
    • 2020-09-01
    • 2021-01-14
    • 2021-04-09
    • 2021-11-13
    • 2021-03-22
    • 2020-03-20
    • 1970-01-01
    相关资源
    最近更新 更多