【发布时间】:2021-07-16 00:00:08
【问题描述】:
我目前正在尝试在 python 中使用 tensorflow.keras 构建用于人脸检测的 CNN。它应该拍摄两种类型的图像:人脸和非人脸。 我试图实现的模型来自表 [Cnn][1],但我不断收到错误,即使我修复了一个,我也会得到另一个,我陷入了错误的循环。 [1]:https://i.stack.imgur.com/WJCPb.png 请告诉我我可以尝试解决什么问题?
testRatio = 0.2
valRatio = 0.2
path="D:\ObjectsRecognition\data"
folder=["face","nonface"]
class_names = ["Face","Nonface"]
predictionList = []
def label(numpy):
npList=np.array([])
for i in range(len(numpy)):
if numpy[i]=="face":
npList=np.append(npList,[0])
else:
npList=np.append(npList,[1])
return npList
def file():
############################
images = [] # LIST CONTAINING ALL THE IMAGES
classNo = [] # LIST CONTAINING ALL THE CORRESPONDING CLASS ID OF IMAGES
myList = os.listdir(path)
print("Total Classes Detected:", len(myList))
noOfClasses = len(myList)
print("Importing Classes .......")
for x in folder:
myPicList = os.listdir(path + "/" + x)
for y in myPicList:
curImg = cv.imread(path + "/" + x + "/" + y)
curImg = cv.resize(curImg, (231, 231))
images.append(curImg)
classNo.append(x)
print(x, end=" ")
print(" ")
print("Total Images in Images List = ", len(images))
print("Total IDS in classNo List= ", len(classNo))
#######################
#### CONVERT TO NUMPY ARRAY
images = np.array(images)
classNo = np.array(classNo)
#### SPLITTING THE DATA
X_train, X_test, y_train, y_test = train_test_split(images, classNo, test_size=testRatio)
print(len(X_train) )
print(len(X_test) )
print(len(y_train) )
print(len(y_test) )
####################
(training_images, training_labels), (testing_images, testing_labels) = (X_train,label(y_train)), (X_test,label(y_test))
training_images, testing_images = training_images/255, testing_images/255
return (training_images, training_labels), (testing_images, testing_labels)
def defineTrainModel():
model = models.Sequential()
model.add(layers.Conv2D(96, (11, 11),strides=(4,4) ,activation='relu', input_shape=(231, 231, 3)))
model.add(layers.MaxPooling2D((2, 2),strides=(2,2)))
model.add(layers.Conv2D(256, (5, 5),strides=(1,1), activation='relu',input_shape=(24, 24, 3)))
model.add(layers.MaxPooling2D((2, 2),strides=(2,2)))
model.add(layers.Conv2D(512, (3, 3), strides=(1,1) ,activation='relu',input_shape=(12, 12, 3)))
model.add(layers.ZeroPadding2D(padding=(1,1)))
model.add(layers.Conv2D(1024, (3, 3), strides=(1, 1), activation='relu', input_shape=(12, 12, 3)))
model.add(layers.ZeroPadding2D(padding=(1,1)))
model.add(layers.Conv2D(1024, (3, 3), strides=(1, 1), activation='relu', input_shape=(24, 24, 3)))
model.add(layers.MaxPooling2D((2, 2), strides=(2, 2)))
model.add(layers.ZeroPadding2D(padding=(1,1)))
model.add(layers.Flatten())
model.add(layers.Dense(3072, activation='relu',input_shape=(6,6,3)))
model.add(layers.Dense(4096, activation='relu',input_shape=(1,1,3)))
model.add(layers.Dense(2, activation='softmax',input_shape=(1,1,3)))
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.summary()
model.fit(training_images, training_labels, epochs=30, validation_data=(testing_images, testing_labels))
loss, accuracy = model.evaluate(testing_images, testing_labels)
print(f"Loss: {loss}")
print(f"Accuracy: {accuracy}")
model.save("FancyGPUTrainedModel.h5")
(training_images, training_labels), (testing_images, testing_labels)= file() #Spliting the data
defineTrainModel()
这是我得到的错误,但如果我尝试修复它,我会得到另一个错误: ValueError: 层 zero_padding2d 的输入 0 与层不兼容:预期 ndim=4,发现 ndim=2。收到的完整形状:(无,51200)
这是模型摘要: 模型:“顺序”
图层(类型)输出形状参数#
conv2d (Conv2D) (无, 59, 59, 96) 34944
max_pooling2d (MaxPooling2D) (无, 29, 29, 96) 0
conv2d_1 (Conv2D)(无、25、25、256)614656
max_pooling2d_1 (MaxPooling2 (None, 12, 12, 256) 0
conv2d_2 (Conv2D) (无, 10, 10, 512) 1180160
zero_padding2d (ZeroPadding2 (None, 12, 12, 512) 0
conv2d_3 (Conv2D)(无、10、10、1024)4719616
zero_padding2d_1 (ZeroPaddin (None, 12, 12, 1024) 0
conv2d_4 (Conv2D) (无, 10, 10, 1024) 9438208
max_pooling2d_2 (MaxPooling2 (None, 5, 5, 1024) 0
zero_padding2d_2 (ZeroPaddin (None, 7, 7, 1024) 0
密集(密集)(无、7、7、3072)3148800
dense_1(密集)(无、7、7、4096)12587008
dense_2(密集)(无、7、7、2)8194
总参数:31,731,586 可训练参数:31,731,586 不可训练参数:0
并且 训练标签:形状(6607,)
测试标签:形状:(1652,)
训练图像:形状 (6607, 245, 245, 3)
测试图像:形状:(1652, 245, 245, 3)
【问题讨论】:
-
好吧,问题是在进行 Flatten 之后使用 ZeroPadding2D 没有任何意义,因为 ZeroPadding2D 期望图像作为输入(4 维),而 Flatten 将数据转换为 2 维。所以你得到一个错误。
-
@Dr.Snoopy 谢谢,这解决了一个问题。现在,当模型尝试训练时,我得到 tensorflow.python.framework.errors_impl.InvalidArgumentError: logits and labels must have the same first dimension, got logits shape [1568,2] and labels shape [32] [[node sparse_categorical_crossentropy/ SparseSoftmaxCrossEntropyWithLogits/SparseSoftmaxCrossEntropyWithLogits(定义在 /ObjectsRecognition/NewData/ObjectDetection.py: 127)]] [Op:__inference_train_function_1361]
-
根据错误,训练标签和预测的数量不匹配。你能打印 model.summary() 和训练标签的形状吗?
-
@Uchiha012 我打印了模型摘要以及用于训练和测试的标签和图像的形状
-
@DicsokGabriel 感谢更新。在最后一个零填充之后添加 layer.Flatten() 。目前你的输出是 (None, 7, 7, 2) 形状,它应该是 (None, 2) 因为最后你想要类的概率,在这种情况下是 2。
标签: python tensorflow keras conv-neural-network