首页 > 解决方案 > 层 conv1 的输入 0 与层不兼容:预期 ndim=4,发现 ndim=3。收到的完整形状:[None, 256, 3]

问题描述

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

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

标签: tensorflowkerasneural-network

解决方案


看起来问题是使用附加来创建 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

推荐阅读