如何为softmax分类指定onehot标签数组的形状?

时间:2019-03-02 03:33:18

标签: python tensorflow machine-learning keras

我正在做一个简单的图像分类,我希望将图像分为16类之一。我的标签是16长的一键式ndarray。

当我调用fit()时,很明显该模型期望16个样本,而不是一个由一个大小为16的数组组成的标签。我不知所措,无法理解我需要什么魔术告诉Keras我在喂它什么。

代码和提示如下。尝试忽略传递给Dense()的无关大小,这只是一个玩具项目。我有意一次分批传递一个样本。

def main():
FLAGS, unparsed = ut.parseArgs()
print(FLAGS)
# TEST_DATA_PATH      = FLAGS.test_data_path
SAMPLE_FILE = FLAGS.train_data_path + FLAGS.sample
IMG_SHAPE   = ut.get_image_shape(filename=SAMPLE_FILE, scale=FLAGS.scale, show=FLAGS.show)
img = ut.read_image(filename=SAMPLE_FILE, show=False)
img = np.array(img)
IMG_SHAPE=img.shape
(x_train, y_train), (x_test, y_test)=load_data(numclasses=FLAGS.numclasses, train_path=FLAGS.train_data_path, sample_file=SAMPLE_FILE, onehot=True)


model = tf.keras.models.Sequential()


print(f'IMG_SHAPE:{IMG_SHAPE},  y_train shape:{y_train[0].shape}')

model.add(tf.keras.layers.Dense(256,activation='relu',input_shape=IMG_SHAPE, name='d1'))
model.add(tf.keras.layers.Dense(64, activation='sigmoid', name='d2'))
model.add(tf.keras.layers.Flatten(data_format='channels_last'))
model.add(tf.keras.layers.Dense(32, activation='softmax', name='d3'))

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.summary()
for nx in range(len(x_train)):
    file = x_train[nx]
    img = ut.read_image(filename=FLAGS.train_data_path+file, show=False)
    img=np.array(img)
    img = np.expand_dims(img, axis=0)
    model.fit(x=img, y=y_train[nx],verbose=2)

这是恶作剧:

  

“ C:\ Users \ WascallyWabbit \ AppData \ Local \ Programs \ Python \ Python36 \ python.exe”   “ C:/用户/WascallyWabbit/PycharmProjects/sentdex_keras/sentdex_keras.py”   命名空间(batch_size = 4,epochs = 1,learning_rate = 0.01,numclasses = 16,   sample ='0cdf5b5d0ce1_01.jpg',scale = 1.0,show = False,target ='mnist',   tb_dir ='/用户/ WascallyWabbit / tensorlog /',   test_data_path ='/用户/ WascallyWabbit /下载/ carvana / test /',   train_data_path ='/用户/ WascallyWabbit /下载/ carvana / train /')   IMG_SHAPE:(1280,1918,2),y_train shape:(16,)   _________________________________________________________________图层(类型)输出形状参数#
  ================================================== ============== d1(密集)(无,1280、1918、256)768
  _________________________________________________________________ d2(密集)(无,1280、1918、64)16448
  _________________________________________________________________展平(展平)(无,157122560)0
  _________________________________________________________________ d3(密集)(无,32岁)732954656   ================================================== ===============总参数:732,971,872可训练参数:732,971,872不训练   参数:0   _________________________________________________________________追溯(最近一次通话结束):文件   “ C:/用户/WascallyWabbit/PycharmProjects/sentdex_keras/sentdex_keras.py”,   第113行,在       main()文件“ C:/Users/WascallyWabbit/PycharmProjects/sentdex_keras/sentdex_keras.py”,   主线74        model.fit(x = img,y = y_train [nx],verbose = 2) 文件“ C:\ Users \ WascallyWabbit \ AppData \ Roaming \ Python \ Python36 \ site-packages \ tensorflow \ python \ keras \ engine \ training.py“,   1536行,适合       validate_split = validation_split)文件“ C:\ Users \ WascallyWabbit \ AppData \ Roaming \ Python \ Python36 \ site-packages \ tensorflow \ python \ keras \ engine \ training.py”,   _standardize_user_data中的第992行       class_weight,batch_size)文件“ C:\ Users \ WascallyWabbit \ AppData \ Roaming \ Python \ Python36 \ site-packages \ tensorflow \ python \ keras \ engine \ training.py”,   第1169行,在_standardize_weights中       training_utils.check_array_lengths(x,y,sample_weights)文件“ C:\ Users \ WascallyWabbit \ AppData \ Roaming \ Python \ Python36 \ site-packages \ tensorflow \ python \ keras \ engine \ training_utils.py”,   第426行,在check_array_lengths中       '和'+ str(list(set_y)[0])+'目标样本。')ValueError:输入数组的样本数量应与目标数组相同。    找到了1个输入样本和16个目标样本

     

以退出代码1完成的过程

仍然卡住,对不起。

我已经把问题简化了:

import tensorflow as tf
import numpy as np
in_shape=(128,128,3)
a=np.zeros(shape=in_shape,dtype='float32')
np.fill_diagonal(a[:,:,0],1.)
np.fill_diagonal(a[:,:,1],1.)
np.fill_diagonal(a[:,:,2],1.)

model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(64, input_shape=in_shape, activation=tf.nn.relu, batch_size=1,name='d0'),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(16, activation=tf.nn.softmax,name='d1')
])

model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])

Y=np.empty(16)
Y.fill(1.)
#forgot to make one of them 'hot' , does not matter now

#this line barfs
model.fit(x=np.expand_dims(a, axis=0), y=np.expand_dims(Y, axis=0),steps_per_epoch=1)

输出为:

  

“ C:\ Users \ WascallyWabbit \ AppData \ Local \ Programs \ Python \ Python36 \ python.exe”   “ C:/用户/WascallyWabbit/.PyCharmCE2018.2/config/scratches/scratch_39.py”   追溯(最近一次通话):文件   “ C:/用户/WascallyWabbit/.PyCharmCE2018.2/config/scratches/scratch_39.py”,   第28行,在       model.fit(x = np.expand_dims(a,axis = 0),y = np.expand_dims(Y,axis = 0),steps_per_epoch = 1)文件   “ C:\ Users \ WascallyWabbit \ AppData \ Roaming \ Python \ Python36 \ site-packages \ tensorflow \ python \ keras \ engine \ training.py”,   1536行,适合       validate_split = validation_split)文件“ C:\ Users \ WascallyWabbit \ AppData \ Roaming \ Python \ Python36 \ site-packages \ tensorflow \ python \ keras \ engine \ training.py”,   _standardize_user_data中的第992行       class_weight,batch_size)文件“ C:\ Users \ WascallyWabbit \ AppData \ Roaming \ Python \ Python36 \ site-packages \ tensorflow \ python \ keras \ engine \ training.py”,   第1154行,在_standardize_weights中       exception_prefix ='target')文件“ C:\ Users \ WascallyWabbit \ AppData \ Roaming \ Python \ Python36 \ site-packages \ tensorflow \ python \ keras \ engine \ training_utils.py”,   第332行,位于standardize_input_data中       ',但数组的形状为'+ str(data_shape))ValueError:检查 target 时出错:预期d1具有形状(1,)但数组   形状为(16,)

我希望针对16个元素的标签数组将一个16个元素的概率数组“ softmax”。随便使用np.expand_dims(...,axis =)并没有带来喜悦。

我看不到什么?

1 个答案:

答案 0 :(得分:0)

如果使用sparse_categorical_crossentropy,则y值应提供为整数,因此会观察到预期的错误形状(1,)。当损失函数为categorical_crossentropy时,以一热编码的形式提供y。

此链接有一个很好的插图。 https://jovianlin.io/cat-crossentropy-vs-sparse-cat-crossentropy/

因此,解决方法是

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

也可以使用np.expand_dims或y_train [nx] [None]创建批次尺寸。

model.fit(x = img,y = np.expand_dims(y_train [nx],0),详细= 2)