无法将输出图层设置为分类

时间:2017-04-01 13:30:17

标签: python keras conv-neural-network

我目前正在尝试实施CNN,其目的是执行分类,但出于某种原因,我无法将输出维度定义为1.

以下是一个示例代码:

import keras
from keras.layers.merge import Concatenate
from keras.models import Model
from keras.layers import Input, Dense
from keras.layers import Dropout
from keras.layers.core import Dense, Activation, Lambda, Reshape,Flatten
from keras.layers import Conv2D, MaxPooling2D, Reshape, ZeroPadding2D
import numpy as np

train_data_1 = np.random.randint(100,size=(100,3,6,3))
train_data_2 = np.random.randint(100,size=(100,3,6,3))
test_data_1 = np.random.randint(100,size=(10,3,6,3))
test_data_2 = np.random.randint(100,size=(10,3,6,3))
labels_train_data =np.random.randint(145,size=100)
labels_test_data =np.random.randint(145,size=10)


input_img_1 = Input(shape=(3, 6, 3))
input_img_2 = Input(shape=(3, 6, 3))

conv2d_1_1 = Conv2D(filters = 32, kernel_size = (3,3) , padding = "same" , activation = 'relu' , name = "conv2d_1_1" )(input_img_1)
conv2d_2_1 = Conv2D(filters = 64, kernel_size = (3,3) , padding = "same" , activation = 'relu' )(conv2d_1_1)
conv2d_3_1 = Conv2D(filters = 64, kernel_size = (3,3) , padding = "same" , activation = 'relu' )(conv2d_2_1)
conv2d_4_1 = Conv2D(filters = 32, kernel_size = (1,1) , padding = "same" , activation = 'relu' )(conv2d_3_1)
conv2d_4_1_flatten = Flatten()(conv2d_4_1)

conv2d_1_2 = Conv2D(filters = 32, kernel_size = (3,3) , padding = "same" , activation = 'relu' , name = "conv2d_1_2")(input_img_2)
conv2d_2_2 = Conv2D(filters = 64, kernel_size = (3,3) , padding = "same" , activation = 'relu' )(conv2d_1_2)
conv2d_3_2 = Conv2D(filters = 64, kernel_size = (3,3) , padding = "same" , activation = 'relu' )(conv2d_2_2)
conv2d_4_2 = Conv2D(filters = 32, kernel_size = (1,1) , padding = "same" , activation = 'relu' )(conv2d_3_2)
conv2d_4_2_flatten = Flatten()(conv2d_4_2)


merge = keras.layers.concatenate([conv2d_4_1_flatten, conv2d_4_2_flatten])

dense1 = Dense(100, activation = 'relu')(merge)
dense2 = Dense(50,activation = 'relu')(dense1)
dense3 = Dense(1 ,activation = 'softmax')(dense2)


model = Model(inputs = [input_img_1, input_img_2] , outputs = dense3)
model.compile(loss="sparse_categorical_crossentropy", optimizer="adam")

print model.summary()

labels_train = keras.utils.to_categorical(labels_train_data, num_classes=145)
labels_test = keras.utils.to_categorical(labels_test_data, num_classes=145)

hist_current = model.fit(x = [train_data_1, train_data_2],
                    y = labels_train,
                    shuffle=False,
                    validation_data=([test_data_1 ,test_data_2], labels_test),
                    validation_split=0.1,
                    epochs=150000,
                    batch_size = 15,
                    verbose=1)

错误信息是:

Traceback (most recent call last):
  File "test_model.py", line 57, in <module>
    verbose=1)
  File "/usr/local/lib/python2.7/dist-packages/keras/engine/training.py", line 1405, in fit
    batch_size=batch_size)
  File "/usr/local/lib/python2.7/dist-packages/keras/engine/training.py", line 1299, in _standardize_user_data
    exception_prefix='model target')
  File "/usr/local/lib/python2.7/dist-packages/keras/engine/training.py", line 133, in _standardize_input_data
    str(array.shape))
ValueError: Error when checking model target: expected dense_3 to have shape (None, 1) but got array with shape (100, 145)

1 个答案:

答案 0 :(得分:2)

模型中存在一些不一致之处:

  1. dense3 = Dense(1 ,activation = 'softmax')(dense2):你不能单独在一个神经元上使用softmax。 softmax标准化层的输出,使其总和为1 ......在这种情况下,如果单独标准化一个值,它将始终输出1.但这不是您收到错误的原因
  2. 你有几节课?从您的网络,您输出一个值(最后一层是密集(1))所以我希望您想要预测2个类(输出1或0)。但是在这里我们看到你的输出是一个具有145种可能性的分类...你的label_train数组是100个长度为145的热矢量,所以我假设你想要将100个样本分类为145个不同的类别......这就是为什么keras抱怨,你的网络输出(100,1)和你的目标(标签)是(100,145)。你真的想做什么?
  3. 修改:

    在评论之后,由于您要预测图像属于145个类别之一,因此您必须输出145个值。因此,您必须更改网络的顶层,以便最后一层为Dense(145, activation='softmax')。所以我建议你替换

    dense1 = Dense(100, activation = 'relu')(merge)
    dense2 = Dense(50,activation = 'relu')(dense1)
    dense3 = Dense(1 ,activation = 'softmax')(dense2)
    

    dense1 = Dense(200, activation = 'relu')(merge)
    dense2 = Dense(150, activation = 'relu')(dense1)
    dense3 = Dense(145, activation = 'softmax')(dense2)
    

    如果你真的想拥有3个密集层,否则你可以删除中间层...这取决于你的用例,所以隐藏层的架构取决于你。我只是坚持你的最后一层应该是Dense(145, activation='softmax')

    有道理吗?

    编辑2:

    除此之外,您不应将目标(标签)编码为分类,当您使用sparse_categorical_crossentropy时,它会在引擎盖下自动完成。

    因此,您使用keras.utils.to_categorical

    在目标上使用loss=categorical_crossentropy

    或者您不会使用keras.utils.to_categorical转换目标并使用loss=sparse_categorical_crossentropy

    它在我的机器上运行。