Keras分类模型

时间:2017-11-16 18:37:29

标签: python keras

我正在尝试创建一个Keras深度学习算法来识别假彩色正射影像中的针叶树和叶子树。我已经提取了大约4 500个被认为是正确的训练/验证图像,例如herehere。现实世界中的像素大小为0.5米,因此这些不是真正的高分辨率图像。所有图像均为31x31像素的固定尺寸。以下模型是谷歌搜索的产物,尤其是Keras自己的文档站点。

from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K

# dimensions of our images.
img_width, img_height = 30, 30

train_data_dir = 'treedata/train'
validation_data_dir = 'treedata/validation'
nb_train_samples = 4000
nb_validation_samples = 533
epochs = 50
batch_size = 16

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(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Dropout(0.5))

model.add(Activation('relu'))
model.add(Dense(2)) # number of classes
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy',
          optimizer='rmsprop',
          metrics=['accuracy'])

# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

# this is the augmentation configuration we will use for testing:
# only rescaling
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 // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=nb_validation_samples // batch_size)

model.save('treetypes.h5')

从第2纪元开始,准确度声称为> 0.99和损失< 0.02,我觉得很奇怪。在创建模型之后,我尝试通过正射影像并确定一个30x30像素的子图像是否包含给定类型的树。

import numpy as np
import cv2
from keras.models import load_model
from keras.preprocessing import image

model = load_model('treetypes.h5') 
roi = cv2.imread('roi.jpg')
sy, sx = img.shape[:2]
px_apart = 10 # start sub-images 10 px apart
s = 30 # sub-image size

for starty in range(1, sy-img_height, px_apart):

    for startx in range(1, sx-img_width, px_apart):

        subimg = img[starty:starty+s, startx:startx+s]
        x = image.img_to_array(subimg)
        x = np.expand_dims(x, axis=0)
        is_tree = model.predict(x, batch_size=1, verbose=0) # predict classes

这是我迷路的地方。首先,似乎没有选择子图像既不是针叶树也不是叶子树(所有子图像都被预测为is_tree = [[0,1]]或is_tree = [[1,0]] )。没有例如预测[[0.1,0.02]],这表明该子图像根本不是树。因此,有两个主要问题:

1)我是否正确理解模型应输出属于1类(针叶树)和2类(叶片)的概率?为什么它只给出“二进制”结果?我在某处读到softmax将概率的总和调整为1。

2)我的模型是否可以使用?或者,考虑到粗略的样本分辨率,使用NN是否可行?我怀疑我的模型有些过分......

如果有人有时间接受这个,请提前致谢!

2 个答案:

答案 0 :(得分:0)

如果你使用softmax,两个类的总和将是1.这意味着你永远不会得到一个"没有树"结果。

但是如果你将激活更改为" sigmoid",那么你可以同时拥有两个零(以及两者都是1)。如果您的模型或数据不是那么好,最终可能会针对针对性的#34;并且"是的叶子"。

您也可以尝试创建三个类的方法,然后返回softmax。 Class1 =针叶树; Class2 = leafed; Class3 =无。

关于您的模特。

嗯,这是一门艺术。只测试很多并阅读成功案例,您将找到最适合该任务的模型。

答案 1 :(得分:0)

我假设您的数据集中只有两个类。因此,我想向您推荐一种名为 channel inhibit softmax 的有趣技术,以便有一个额外的可能类别,您可以阅读here。要使用此类别,您需要将网络中的其他第3个输出添加到softmax图层,该图层始终等于0。现在你有两个选择:

  1. 您可以从模型中检索softmax的输入,并为其添加一个人工0

    logits_model = Model(model.input, model.layers[-2].output)
    data = logits_model.predict(x)
    final_probs = numpy.exp(x) / (numpy.sum(numpy.exp(x), axis = 1) + 1)
    

    这种方式的优点是您不需要训练新模型,而是使用现有模型。

  2. 你可以训练一个新模型:

    def channel_inhibited_softmax(x):
        e = K.exp(x - K.max(x, axis=1, keepdims=True))
        s = K.sum(e, axis=1, keepdims=True) + K.exp(-K.max(x), axis=1)
        return e / s
    
    model.add(Activation('relu'))
    model.add(Dense(2)) # number of classes
    model.add(Lambda(channel_inhibited_softmax))
    

    现在您可以使用其他不确定的课程重新训练您的模型。

  3. 感谢上述解决方案 - 您可以为模型添加不确定性,并检查给定图片是否可能不属于任何类别。