我目前正在尝试实现一个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)
最佳答案
模型中的几个不一致之处:dense3 = Dense(1 ,activation = 'softmax')(dense2)
:您不能仅对一个神经元使用softmax。 softmax对层的输出进行归一化,使其总和为1 ...在这种情况下,如果仅对一个值进行归一化,它将始终输出1。但这不是为什么会出现错误的原因
你有几节课?从您的网络中,您输出一个值(最后一层是Dense(1)),因此我希望您希望预测2个类(输出1或0)。但是在这里,我们看到您的输出是145种可能性的分类...您的label_train
数组是100个长度为145的热向量,所以我假设您要将100个样本分类为145个不同的类别...这是为什么keras抱怨,您的网络输出(100,1)和目标(标签)为(100,145)。你到底想干什么?
编辑:
注释之后,由于您要预测图像是否属于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
。它正在我的机器上运行。
关于python - 无法将输出层设置为分类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43157511/