ValueError: Can not squeeze dim[1], expected a dimension of 1 for '{{node binary_crossentropy/weighted_loss/Squeeze}}

ValueError: Can not squeeze dim[1], expected a dimension of 1 for '{{node binary_crossentropy/weighted_loss/Squeeze}}

我正在尝试使用前面的掩蔽层将 LSTM 模型拟合到我的数据中,但出现此错误:

ValueError: Can not squeeze dim[1], expected a dimension of 1, got 4 for '{{node binary_crossentropy/weighted_loss/Squeeze}} = Squeeze[T=DT_FLOAT, squeeze_dims=[-1]](Cast)' with input shapes: [128,4].

这是我的代码:

from tensorflow.keras.layers import LSTM, Dense, BatchNormalization, Masking
from tensorflow.keras.losses import BinaryCrossentropy
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Nadam
import numpy as np

if __name__ == '__main__':
    
    # define stub data
    samples, timesteps, features = 128, 4, 99
    X = np.random.rand(samples, timesteps, features)
    Y = np.random.randint(0, 2, size=(samples))
    
    # create model
    model = Sequential()
    model.add(Masking(mask_value=0., input_shape=(None, 99)))
    model.add(LSTM(100, return_sequences=True))
    model.add(BatchNormalization())
    model.add(Dense(1, activation='sigmoid'))
    optimizer = Nadam(learning_rate=0.0001)
    loss = BinaryCrossentropy(from_logits=False)
    model.compile(loss=loss, optimizer=optimizer)

    # train model
    model.fit(
        X,
        Y,
        batch_size=128)

我从 了解到,我不能使用单热编码标签,但我的标签不是单热编码的。 另外,当我移除遮蔽层时,训练有效。

据我了解,这里的一个样本包含 4 个时间步长和 99 个特征。因此 X 的形状是 (128,4,99) 因此,我只需为每个样本提供一个标签,因此 Y 的形状为 (128,)

但似乎 X 和/或 Y 的尺寸不正确,因为 tensorflow 想要更改其尺寸? 我尝试为每个样本的每个时间步提供一个标签(Y = np.random.randint(0, 2, size=(samples, timesteps)),结果相同。

为什么添加遮罩层会引入此错误?以及如何保留遮蔽层而不出现错误?

系统信息:

我认为问题不在 Masking 层。由于您在 LSTM 层中将参数 return_sequences 设置为 True,因此您将获得一个时间步长与输入相同且输出 space 为 100 的序列对于每个时间步,因此形状为 (128, 4, 100),其中 128 是批量大小。之后,应用 BatchNormalization 层,最后应用 Dense 层,形成 (128, 4, 1) 形状。问题是您的标签具有 2D 形状 (128, 1),而由于 return_sequences 参数,您的模型具有 3D 输出。因此,只需将此参数设置为 False 即可解决您的问题。另见 .

这是一个工作示例:

from tensorflow.keras.layers import LSTM, Dense, BatchNormalization, Masking
from tensorflow.keras.losses import BinaryCrossentropy
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Nadam
import numpy as np

if __name__ == '__main__':
    
    # define stub data
    samples, timesteps, features = 128, 4, 99
    X = np.random.rand(samples, timesteps, features)
    Y = np.random.randint(0, 2, size=(samples))
    
    # create model
    model = Sequential()
    model.add(Masking(mask_value=0., input_shape=(None, 99)))
    model.add(LSTM(100, return_sequences=False))
    model.add(BatchNormalization())
    model.add(Dense(1, activation='sigmoid'))
    optimizer = Nadam(learning_rate=0.0001)
    loss = BinaryCrossentropy(from_logits=False)
    model.compile(loss=loss, optimizer=optimizer)

    # train model
    model.fit(
        X,
        Y,
        batch_size=128)