Python Keras分类模型
我正在尝试创建一个Keras深度学习算法,从假彩色正射影像中识别针叶树和树叶树。我提取了大约4500张被认为是正确的培训/验证图像,如和。现实世界中的像素大小是0.5米,所以这些不是真正的高分辨率图像。所有图像都是固定大小的31x31像素。以下模型是谷歌的产品,尤其是Keras自己的文档网站Python Keras分类模型,python,keras,Python,Keras,我正在尝试创建一个Keras深度学习算法,从假彩色正射影像中识别针叶树和树叶树。我提取了大约4500张被认为是正确的培训/验证图像,如和。现实世界中的像素大小是0.5米,所以这些不是真正的高分辨率图像。所有图像都是固定大小的31x31像素。以下模型是谷歌的产品,尤其是Keras自己的文档网站 from keras.preprocessing.image import ImageDataGenerator from keras.models import Sequential from 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')
从第二纪元开始,精度声称大于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进行此操作是否可行?我怀疑我的模型有点太合适了
如果有人有时间,请提前感谢 如果使用softmax,两个类的总和将为1。这意味着你永远不会得到“没有树”的结果 但是如果您将激活更改为“sigmoid”,那么您可以同时拥有两个零(以及两个1)。如果您的模型或数据不太好,您可能会以“赞成针叶树”和“赞成叶树”结束 您也可以尝试创建三个类,然后返回softmax。类别1=针叶林;类别2=叶状;类别3=无
关于你的模型
嗯,这是一门艺术。只有通过大量测试和阅读成功案例,你才能找到适合这项任务的最佳模式 如果使用softmax,两个类的总和将为1。这意味着你永远不会得到“没有树”的结果 但是如果您将激活更改为“sigmoid”,那么您可以同时拥有两个零(以及两个1)。如果您的模型或数据不太好,您可能会以“赞成针叶树”和“赞成叶树”结束 您也可以尝试创建三个类,然后返回softmax。类别1=针叶林;类别2=叶状;类别3=无
关于你的模型
嗯,这是一门艺术。只有通过大量测试和阅读成功案例,你才能找到适合这项任务的最佳模式 我假设您的数据集中只有两个类。因此,我想向您推荐一种有趣的技术,称为channel inhibited softmax,以便有一个额外的类别,您可以阅读。为了使用此类别,您需要将额外的第三个输出从网络添加到始终等于
0
的softmax
层。现在您有两个选择:
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)
这种方法的优点是,您不需要训练新模型,而是使用现有模型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))
现在,您可以使用附加的“不确定”类重新训练您的模型多亏了上述解决方案,您可以为模型添加不确定性,并检查给定图片是否可能不属于任何类别。我假设您的数据集中只有两个类别。因此,我想向您推荐一种有趣的技术,称为channel inhibited softmax,以便有一个额外的类别,您可以阅读。为了使用此类别,您需要将额外的第三个输出从网络添加到始终等于
0
的softmax
层。现在您有两个选择:
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)
这种方法的优点是,您不需要训练新模型,而是使用现有模型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))
现在,您可以使用附加的“不确定”类重新训练您的模型