[英]Custom Layer in Keras - Dimension Problem
我想要一个 CNN,它将原始信号作为输入,并作为第一步处理短时傅立叶变换。 因此我想用 Keras 创建一个自定义层。
我遵循了这里的解释,并将复杂性降低到以下代码:
class CreateSFTF(Layer):
def __init__(self, units=32,n_fft=1000,hop_length=0,log=True, **kwargs):
super(CreateSFTF, self).__init__(**kwargs)
self.units = units
self.n_fft = n_fft
self.hop_length = hop_length
self.log = log
def build(self, input_shape):
super(CreateSFTF, self).build(input_shape)
def call(self, inputs):
def _tf_log10(x):
numerator = tf.math.log(x)
denominator = tf.math.log(tf.constant(10, dtype=numerator.dtype))
return numerator / denominator
stfts = tf.signal.stft(
input,
frame_length=self.n_fft,
frame_step=self.hop_length,
window_fn=tf.signal.hann_window,
pad_end=False
)
mag_stfts = tf.abs(stfts)
return tf.expand_dims(mag_stfts, 3)
def get_config(self):
config = super(CreateSFTF, self).get_config()
config.update({'units': self.units})
return config
我在这里使用图层:
def DefineCNNWithFFTAtBeginning(length_signal):
input = Input(shape = (length_signal,1))
x = CreateSFTF(n_fft=1000,hop_length=100,log=True)(input)
x = BatchNormalization()(x) # recommended
x = layers.Conv2D(8, (3, 3), activation='relu',padding='valid')(x)
x = layers.Conv2D(8, (3, 3),activation='relu', padding='valid')(x)
x = layers.MaxPooling2D(pool_size=(4, 4))(x)
x = layers.Conv2D(16, (5, 5),activation='relu', padding='valid')(x)
x = layers.Conv2D(4, (5, 5),activation='relu', padding='valid')(x)
x = layers.MaxPooling2D(pool_size=(5, 5))(x)
x = Flatten()(x)
x = layers.Dropout(0.5)(x)
x = Dense(1,activation='sigmoid')(x)
model = Model(input, x)
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
model.summary()
return model
我在这里称之为:
model = DefineCNNWithFFTAtBeginning(76000)
history =model.fit(X_train.values, y_train,
validation_data=(X_test.values, y_test),
epochs=50, batch_size=32,
shuffle = True)
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 76000)] 0
_________________________________________________________________
create_sftf (CreateSFTF) (None, 751, 513, 1) 0
_________________________________________________________________
batch_normalization (BatchNo (None, 751, 513, 1) 4
_________________________________________________________________
conv2d (Conv2D) (None, 749, 511, 8) 80
_________________________________________________________________
conv2d_1 (Conv2D) (None, 747, 509, 8) 584
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 186, 127, 8) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 182, 123, 16) 3216
_________________________________________________________________
conv2d_3 (Conv2D) (None, 178, 119, 4) 1604
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 35, 23, 4) 0
_________________________________________________________________
flatten (Flatten) (None, 3220) 0
_________________________________________________________________
dropout (Dropout) (None, 3220) 0
_________________________________________________________________
dense (Dense) (None, 1) 3221
=================================================================
Total params: 8,709
Trainable params: 8,707
Non-trainable params: 2
_________________________________________________________________
Train on 987 samples, validate on 247 samples
Epoch 1/50
32/987 [..............................] - ETA: 29s
X_train 的形状是(xxxxx,76000)
旧的错误信息
检查输入时出错:预期 input_1 有 3 个维度,但得到形状为 (987, 1) 的数组 - 已解决
有人知道解决方案吗? 提前致谢。
更新
新的错误信息
急切执行函数的输入不能是 Keras 符号张量,但发现 tf.Tensor 'input_4:0' shape=(None, 76000) dtype=float32
试过
输入层为批量大小添加了一个维度:
输入形状
具有形状的 nD 张量:(batch_size, ..., input_dim)。 最常见的情况是具有形状 (batch_size, input_dim) 的 2D 输入。
因此,正如 keras 的文档所说(上面引用的),您指定的批次大小为length_signal
。
尝试类似(length_signal, )
, ( ,length_signal)
(或类似的)。
您的模型期望形状张量 (None, 76000, 1) 但您正在通过 (987,1)
您必须预处理您的数据以满足标准。
987 不是此模型的有效尺寸,您必须使用 76000 X 1。如果它不正确,您必须在您的模型中更正它。
如果您想一次添加额外的维度或对单个训练数据进行训练,您可以使用以下代码扩展维度
x = np.random.randn((76000,1)) # shape = (76000 X 1)
x = x[None] # shape = (1 X 76000 X 1)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.