我有一个数据集,试图用Keras进行训练,但每次都会遇到这个错误:“ValueError: Shapes (None, 1) 和 (None, 48, 48, 96) 不兼容”,我无法找出问题所在。我阅读了其他相关的问题,但无法理解我问题的核心是什么
DATASET_PATH = "/Users/user/Documents/ML Projects/Dataset"CLASSNAME_SIZE = 96IMG_SIZE = 48#Creating Dictionary of Classnamewith open(JSON_PATH) as classnameJSON: CLASSNAME = json.loads(classnameJSON.read())trainingData = []X = []Y = []#loading datadef loadTrainingData(): for instance in range(CLASSNAME_SIZE): joinedPath = os.path.join(DATASET_PATH, str(instance)) label = str(instance) for img in os.listdir(joinedPath): try: img_array = cv2.imread(os.path.join(joinedPath,img), cv2.COLOR_BGR2RGB) new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE)) trainingData.append([new_array, label]) except Exception as err: passloadTrainingData()print(len(trainingData))def distributeTrainingData(): for img, label in trainingData: X.append(img) Y.append(label)distributeTrainingData()print("distributing data")X = np.array(X, dtype='float32')Y = np.array(Y, dtype='float32')print(len(X))print(len(Y))def cnn_model(): model = Sequential() model.add(Dense(128, activation='relu')) model.add(Dense(128, activation='relu')) model.add(Dense(CLASSNAME_SIZE, activation='softmax')) return modelmodel = cnn_model()model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])model.fit(X, Y, batch_size=32, epochs=3)
回答:
你的代码中有两个问题。
首先,你需要决定是要对目标进行独热编码并使用categorical_crossentropy
损失函数,还是将它们作为一维张量传递并使用sparse_categorical_crossentropy
损失函数。
你目前是以一维张量的方式传递它们,但使用的是categorical_crossentropy
损失函数。这两者是不兼容的。你可以轻松地通过将损失函数改为sparse_categorical_crossentropy
来解决这个问题。
第二个问题是你将三维张量(图像)传递给了期望扁平输入的Dense层。如果你不想使用卷积层(即使你想用),你也需要在传递给Dense层之前对输入进行扁平化。你可以使用keras.layers.Flatten()
来实现这一点。
因此,将compile
方法改为
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
并在你的模型中添加Flatten
层。
def cnn_model(): model = Sequential() model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dense(128, activation='relu')) model.add(Dense(CLASSNAME_SIZE, activation='softmax')) return modelmodel = cnn_model()
如果你想在Dense层之前添加一些卷积(keras.layers.Conv2D
)层,那么Flatten
层将被添加在卷积基础和Dense顶层之间。
def cnn_model(): model = Sequential() model.add(Conv2D(...)) # ... more conv/pool layers model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dense(128, activation='relu')) model.add(Dense(CLASSNAME_SIZE, activation='softmax')) return model