我的模型具有较高的准确性和val_accuracy,但在测试数据上给出了错误的结果

时间:2019-06-21 04:36:34

标签: python opencv machine-learning keras

我已经使用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.在最后一层之前和第一层之后添加退出层。 2.添加转换层。

任何人都可以建议我我在做什么错。

谢谢。

2 个答案:

答案 0 :(得分:1)

此问题的最可能原因是您的测试集和训练集不是来自同一样本。这在分类问题中很常见。训练之前,您应该比较训练和测试集的类分布和特征分布。如果它们彼此之间距离不太近,则从训练集中学习到的规则不会推广到测试集中。

例如,训练集的班级分布是第一班的 70%,第二班的 20%和第三班的 10%。交叉验证来自训练集,该模型具有较高的训练和交叉验证精度。但是,如果测试集类别的分布类似于 10%类别1, 20%类别2和 70%类别,则该模型可能效果不佳3。

答案 1 :(得分:1)

此问题的另一个可能原因是过度拟合 因为您获得了很高的培训和验证准确性 常用的方法是:

交叉验证:查找样本外预测误差的标准方法是使用5倍交叉验证。 提前停止:它的规则为我们提供了指导,指导他们在学习者开始过度适应之前可以运行多少次迭代。 修剪:修剪在构建相关模型时被广泛使用。它只是删除了节点,这些节点对于手头的问题几乎没有增加预测能力。 正则化::它引入了一个成本项,目的是引入具有目标功能的更多功能。因此,它试图将许多变量的系数推为零,从而减少成本项。