Tensorflow Keras 修改 Iris 示例时形状不兼容

Posted

技术标签:

【中文标题】Tensorflow Keras 修改 Iris 示例时形状不兼容【英文标题】:Tensorflow Keras Incompatible shapes when modifying Iris example 【发布时间】:2020-10-16 09:51:45 【问题描述】:

我正在尝试使用我自己的数据代替虹膜数据集来实现基于https://janakiev.com/notebooks/keras-iris/ 的神经网络。据我所知,唯一的区别是点数,我的数据有 13 个特征,而 iris 数据有 4 个,我的数据只有 2 个输出类,而 iris 数据有 3 个。但是,当我尝试拟合 NN 时,出现不兼容的形状错误。

import keras
from keras.models import Sequential
from keras.layers import Dense

batchSize = 10
epochs = 50
model = Sequential()

model.add(Dense(26, input_dim=13, activation='relu'))
model.add(Dense(26, input_dim=13, activation='relu'))
model.add(Dense(26, input_dim=13, activation='relu'))
model.add(Dense(2, activation='softmax')) #2 for number of classes, as far as I can tell
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

#All of xTrain, yTrain, xTest, yTest are defined elsewhere
modelTrain = model.fit(xTrain, yTrain, batch_size=batchSize,epochs=epochs,verbose=1,validation_data=(xTest, yTest))

错误:

ValueError: in user code:

/usr/local/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py:571 train_function  *
    outputs = self.distribute_strategy.run(
/usr/local/lib/python3.7/site-packages/tensorflow/python/distribute/distribute_lib.py:951 run  **
    return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
/usr/local/lib/python3.7/site-packages/tensorflow/python/distribute/distribute_lib.py:2290 call_for_each_replica
    return self._call_for_each_replica(fn, args, kwargs)
/usr/local/lib/python3.7/site-packages/tensorflow/python/distribute/distribute_lib.py:2649 _call_for_each_replica
    return fn(*args, **kwargs)
/usr/local/lib/python3.7/site-packages/tensorflow/python/keras/engine/training.py:533 train_step  **
    y, y_pred, sample_weight, regularization_losses=self.losses)
/usr/local/lib/python3.7/site-packages/tensorflow/python/keras/engine/compile_utils.py:205 __call__
    loss_value = loss_obj(y_t, y_p, sample_weight=sw)
/usr/local/lib/python3.7/site-packages/tensorflow/python/keras/losses.py:143 __call__
    losses = self.call(y_true, y_pred)
/usr/local/lib/python3.7/site-packages/tensorflow/python/keras/losses.py:246 call
    return self.fn(y_true, y_pred, **self._fn_kwargs)
/usr/local/lib/python3.7/site-packages/tensorflow/python/keras/losses.py:1527 categorical_crossentropy
    return K.categorical_crossentropy(y_true, y_pred, from_logits=from_logits)
/usr/local/lib/python3.7/site-packages/tensorflow/python/keras/backend.py:4561 categorical_crossentropy
    target.shape.assert_is_compatible_with(output.shape)
/usr/local/lib/python3.7/site-packages/tensorflow/python/framework/tensor_shape.py:1117 assert_is_compatible_with
    raise ValueError("Shapes %s and %s are incompatible" % (self, other))

ValueError: Shapes (None, 1) and (None, 2) are incompatible

如果我将最后一个 Dense 模型中的参数“2”更改为 1,那么一切都会运行,但我得到了一个平凡的模型。为什么我会收到这个不兼容的形状错误,可以做些什么来解决它?

【问题讨论】:

yTrain 的形状是 (n_sample,) 还是 (n_sample,1),对吗? yTrain 是否包含格式为 [0,1,0,0,1....] 的标签? @MarcoCerliani yTrain.shape 是 (n_sample,) 【参考方案1】:

如果您想使用 softmax 激活,您有两种可能性。请记住,对于 softmax,最后一个维度必须等于类的数量。

1 种可能性:如果你有一维整数编码的目标,你可以使用sparse_categorical_crossentropy 作为损失函数

# dummy data
xTrain = np.random.uniform(0,1, (100,13))
xTest = np.random.uniform(0,1, (50,13))
yTrain = np.random.randint(0,2, (100,))
yTest = np.random.randint(0,2, (50,))

batchSize = 10
epochs = 50
model = Sequential()

model.add(Dense(26, input_dim=13, activation='relu'))
model.add(Dense(26, activation='relu'))
model.add(Dense(26, activation='relu'))
model.add(Dense(2, activation='softmax'))
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

#All of xTrain, yTrain, xTest, yTest are defined elsewhere
modelTrain = model.fit(xTrain, yTrain, batch_size=batchSize, epochs=epochs, 
                       verbose=1, validation_data=(xTest, yTest))

2 种可能性:如果您对目标进行 one-hot 编码以获得 2D 形状(n_samples,n_class),您可以使用categorical_crossentropy

# dummy data
xTrain = np.random.uniform(0,1, (100,13))
xTest = np.random.uniform(0,1, (50,13))
yTrain = pd.get_dummies(np.random.randint(0,2, (100,)))
yTest = pd.get_dummies(np.random.randint(0,2, (50,)))

batchSize = 10
epochs = 50
model = Sequential()

model.add(Dense(26, input_dim=13, activation='relu'))
model.add(Dense(26, activation='relu'))
model.add(Dense(26, activation='relu'))
model.add(Dense(2, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

modelTrain = model.fit(xTrain, yTrain, batch_size=batchSize, epochs=epochs, 
                       verbose=1, validation_data=(xTest, yTest))

【讨论】:

这似乎让一切都运行起来了。谢谢

以上是关于Tensorflow Keras 修改 Iris 示例时形状不兼容的主要内容,如果未能解决你的问题,请参考以下文章

如何使 Keras 神经网络在 Iris 数据上的表现优于 Logistic 回归

Tensorflow.keras:AlreadyExistsError

如何强制 keras 使用 tensorflow GPU 后端

tensorflow 线性回归 iris

tensorflow 网站上的 iris 教程不好用

Tensorflow 数据集:有没有办法只修改一定比例的标签?