我使用GTSRB训练了一个神经网络,并尝试使用保存的模型(.h5),但在使用model.predict
时遇到了以下错误:
ValueError: Input 0 of layer sequential is incompatible with the layer: : expected min_ndim=4, found ndim=3. Full shape received: (None, 30, 3)
训练代码如下:
import cv2import numpy as npimport osimport sysimport tensorflow as tffrom sklearn.model_selection import train_test_splitEPOCHS = 10IMG_WIDTH = 30IMG_HEIGHT = 30NUM_CATEGORIES = 43TEST_SIZE = 0.4def main(): # 检查命令行参数 if len(sys.argv) not in [2, 3]: sys.exit("Usage: python traffic.py data_directory [model.h5]") # 获取所有图像文件的图像数组和标签 images, labels = load_data(sys.argv[1]) # 将数据分割成训练集和测试集 labels = tf.keras.utils.to_categorical(labels) x_train, x_test, y_train, y_test = train_test_split( np.array(images), np.array(labels), test_size=TEST_SIZE ) # 获取已编译的神经网络 model = get_model() # 在训练数据上拟合模型 model.fit(x_train, y_train, epochs=EPOCHS) # 评估神经网络性能 model.evaluate(x_test, y_test, verbose=2) # 将模型保存到文件中 if len(sys.argv) == 3: filename = sys.argv[2] model.save(filename) print(f"Model saved to {filename}.")def load_data(data_dir): """ 从目录`data_dir`加载图像数据。 假设`data_dir`有一个按每个类别命名的目录,编号从0到NUM_CATEGORIES - 1。每个类别目录中将有一些图像文件。 返回元组`(images, labels)`。`images`应该是数据目录中所有图像的列表,每个图像格式化为具有维度IMG_WIDTH x IMG_HEIGHT x 3的numpy ndarray。`labels`应该是整数标签的列表,表示每个对应`images`的类别。 """ images = list() labels = list() for folder in os.listdir(data_dir): folder_path = os.path.join(data_dir, folder) if os.path.isdir(folder_path): for photo in os.listdir(folder_path): img = cv2.imread(os.path.join(folder_path, photo)) img = cv2.resize(img, (IMG_WIDTH, IMG_HEIGHT)) images.append(img) labels.append(int(folder)) return images, labelsdef get_model(): """ 返回已编译的卷积神经网络模型。假设第一层的`input_shape`为`(IMG_WIDTH, IMG_HEIGHT, 3)`。 输出层应具有`NUM_CATEGORIES`个单元,每个类别一个。 """ # 创建一个卷积神经网络 model = tf.keras.models.Sequential([ # 卷积层。使用3x3的内核学习32个滤波器 tf.keras.layers.Conv2D( 32, (3, 3), activation="relu", input_shape=(IMG_WIDTH, IMG_HEIGHT, 3) ), # 最大池化层,使用2x2的池化大小 tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), tf.keras.layers.Conv2D( 32, (3, 3), activation="relu", input_shape=(IMG_WIDTH, IMG_HEIGHT, 3) ), # 展平单元 tf.keras.layers.Flatten(), # 添加一个带有丢弃的隐藏层 tf.keras.layers.Dense(NUM_CATEGORIES * 16, activation="relu"), tf.keras.layers.Dropout(0.3), # 添加一个具有所有10个数字输出单元的输出层 tf.keras.layers.Dense(NUM_CATEGORIES, activation="softmax") ]) # 训练神经网络 model.compile( optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"] ) return modelif __name__ == "__main__": main()
使用保存的模型对照片进行分类的代码
from tensorflow.keras.models import load_modelfrom tensorflow.keras.preprocessing import imageimport numpyimport cv2PHOTO_PATH = r'C:\Users\m\ai50\projects\2020\x\traffic\gtsrb\x.ppm'MODEL_PATH = r'C:\Users\m\ai50\projects\2020\x\traffic\model.h5'model = load_model(MODEL_PATH, compile=True)img = cv2.imread(PHOTO_PATH)img = cv2.resize(img, (30, 30))img = numpy.array(img)print(img.shape)result = model.predict(img)print(result)
回答:
给你的图像数组增加一个维度。.predict()
方法期望输入具有四个维度:(batch, height, width, channels)
。增加一个维度实际上使其成为一个包含一张图像的批次。
result = model.predict(img[numpy.newaxis])