我使用 opencv 创建了一些图像,并在其上运行深度神经网络分类器。 它给出了大约 97% 的准确度和 95% 的 val_accuracy,但当我测试它时,它给出了错误的预测。
这是我创建图像的代码。
import cv2
import numpy as np
import random
import os
size = 64
def circle(i,d):
img = np.zeros(shape=(size,size,3))
point = (random.randint(1,size),random.randint(1,size))
img = cv2.circle(img,point,random.randint(1,size),(255,255,0),thickness=2,lineType=8)
if not os.path.exists(d+"/circle"):
os.makedirs(d+"/circle")
cv2.imwrite(d+"/circle/"+str(i)+"circle.png",img)
#print("created circle"+str(i))
def rectangle(i,d):
img = np.zeros(shape=(size,size,3))
point = (random.randint(1,size),random.randint(1,size))
w = random.randint(1,size);
h = random.randint(1,size);
point2 = (point[0] + w,point[1]+h)
img = cv2.rectangle(img,point,point2,(255, 255, 0), 2)
if not os.path.exists(d+"/react"):
os.makedirs(d+"/react")
cv2.imwrite(d+"/react/"+str(i)+"react.png",img)
#print("created reactangle"+str(i))
def traingle(i,d):
img = np.zeros(shape=(size,size,3))
point1 = (random.randint(1,size),random.randint(1,size))
point2 = (random.randint(1,size),random.randint(1,size))
point3 = (random.randint(1,size),random.randint(1,size))
img = cv2.line(img,point1,point2,(255, 255, 0), 2)
img = cv2.line(img,point2,point3,(255, 255, 0), 2)
img = cv2.line(img,point3,point1,(255, 255, 0), 2)
if not os.path.exists(d+"/tra"):
os.makedirs(d+"/tra")
cv2.imwrite(d+"/tra/"+str(i)+"tra.png",img)
#print("created trangle"+str(i))
if not os.path.exists("data_train"):
os.makedirs('data_train')
for i in range(1,2000):
circle(i,"data_train")
rectangle(i,"data_train")
traingle(i,"data_train")
print("Created test data")
if not os.path.exists("data_test"):
os.makedirs('data_test')
for i in range(1,500):
circle(i,"data_test")
rectangle(i,"data_test")
traingle(i,"data_test")
这是我的分类代码。
# importing libraries
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import MaxPooling2D,Dropout, Convolution2D
from keras.layers import Flatten, Dense
from keras import backend as K
img_width, img_height = 64, 64
train_data_dir = 'data_train'
validation_data_dir = 'data_test'
nb_train_samples = 5997
nb_validation_samples = 1497
epochs = 3
batch_size = 15
if K.image_data_format() == 'channels_first':
input_shape = (3, img_width, img_height)
else:
input_shape = (img_width, img_height, 3)
model = Sequential()
model.add(Convolution2D(32, 3, 3, input_shape = input_shape,activation="relu"))
model.add(MaxPooling2D(pool_size =(2, 2)))
model.add(Convolution2D(32, 3, 3,activation="relu"))
model.add(MaxPooling2D(pool_size =(2, 2)))
model.add(Flatten())
model.add(Dropout(0.2))
model.add(Dense(output_dim=180,activation="relu"))
model.add(Dropout(0.2))
model.add(Dense(3,activation="softmax"))
model.compile(loss ='categorical_crossentropy',
optimizer ='adam',
metrics =['categorical_accuracy'])
train_datagen = ImageDataGenerator(
rescale = 1. / 255,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = False)
test_datagen = ImageDataGenerator(rescale = 1. / 255)
train_generator = train_datagen.flow_from_directory(train_data_dir,
target_size =(img_width, img_height),
batch_size = batch_size, class_mode ='categorical')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size =(img_width, img_height),
batch_size = batch_size, class_mode ='categorical')
model.fit_generator(train_generator,
steps_per_epoch = nb_train_samples,
epochs = epochs, validation_data = validation_generator,
validation_steps = nb_validation_samples)
我已经尝试过 1.改变隐藏层数 2. 在最后一层之前和第一层之后添加 dropout 层。 2.添加转换层。
请告诉我我做错了什么。
提前致谢。
此问题最可能的原因是您的测试集和训练集不是来自同一样本。这在分类问题中很常见。在训练之前,您应该比较训练集和测试集的类别分布和特征分布。如果它们彼此不接近,从训练集中学到的规则不会推广到测试集。
例如,训练集的类别分布为 70% 为 1 类,20% 为 2 类,10% 为 3 类。由于交叉验证来自训练集,因此该模型具有较高的训练和交叉性。 -验证准确性。但是,如果测试集类别分布类似于 10% 1 类、20% 2 类和 70% 3 类,则模型可能表现不佳。
此问题的另一个可能原因是过度拟合 因为您获得了很高的训练和验证准确性 常用的方法有:
交叉验证:查找样本外预测误差的标准方法是使用 5 折交叉验证。 早期停止:它的规则为我们提供了在学习器开始过度拟合之前可以运行多少次迭代的指导。 剪枝:剪枝在构建相关模型时被广泛使用。它只是删除了对当前问题几乎没有增加预测能力的节点。 正则化:它引入了一个成本项,用于通过目标函数引入更多特征。因此,它试图将许多变量的系数推至零,从而减少成本项。
此问题通常是由于推理过程中错误的归一化配置导致的。
在过度拟合的情况下,不太可能具有高验证准确性,除非验证集选择非常糟糕并且与训练集有过多的亲和力。