Keras 不兼容的输入

Keras incompatible input

我正在使用 Keras 制作预测模型。但是当我尝试获得预测时,我得到一个 ValueError 指示输入不兼容。这是重现问题的最小代码:

import tensorflow as tf
from tensorflow.keras.callbacks import TensorBoard
import random
import time
import numpy as np
import pickle

#Bring data:
Name = "Predict-{}".format(int(time.time()))
tensorboard = TensorBoard(log_dir='logs/{}'.format(Name))


pickle_in = open("training_data.pickle","rb")
training_data = pickle.load(pickle_in)


random.shuffle(training_data)
X=[]
y=[]
for file_data, categ in training_data :
    X.append(file_data)
    y.append(categ)
  
X=np.array(X)
y=np.array(y)
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(172,activation=tf.nn.relu))
model.add(tf.keras.layers.Dense(2,activation=tf.nn.softmax))
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])

model.fit(X,y,epochs=10, batch_size=128,validation_split=0.25, callbacks=[tensorboard])

#New input Xnew, with len(Xnew)=172
Xnew = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]
ynew = model.predict(Xnew)

这是我得到的错误:

 ValueError: Input 0 of layer dense_107 is incompatible with the layer: expected axis -1 of input shape to have value 172 but received input with shape [None, 1]

模型总结:

Model: "sequential_53"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten_53 (Flatten)         (None, 172)               0         
_________________________________________________________________
dense_109 (Dense)            (None, 172)               29756     
_________________________________________________________________
dense_110 (Dense)            (None, 2)                 346       
=================================================================
Total params: 30,102
Trainable params: 30,102
Non-trainable params: 0
_________________________________________________________________

我也不明白为什么形状是 (None, 172) 而不是 172.

错误在于您为了预测而提供给网络的对象。它需要一个数组 (batch, data),你给的是 (,data).

你可以做的就是对网络说“我有一批”

Xnew = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0])
ynew = model.predict(np.expand_dims(Xnew, axis=0))

expand_dims 添加维度(在本例中为形状前面)

而对于最后一部分,你得到(None, 172) None意味着我们不知道摘要中的批次数(如果你愿意,你可以指定它),网络是期待 (X, 172),X 可以是一切 (32, 64 ...)

模型中不需要展平层,因为您的数据已经为密集层的正确形状。

所以你可以像这样重写模型,

model = tf.keras.models.Sequential()

model.add(tf.keras.layers.Dense(input_shape=(172,), units=172, activation=tf.nn.relu))
model.add(tf.keras.layers.Dense(2,activation=tf.nn.softmax))
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])

注意第一个 Dense 层中的 input_shape 参数。它告诉模型期望有多少维度。

模型摘要将如下所示,

Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_4 (Dense)              (None, 172)               29756     
_________________________________________________________________
dense_5 (Dense)              (None, 2)                 346       
=================================================================
Total params: 30,102
Trainable params: 30,102
Non-trainable params: 0
_________________________________________________________________

使用与您的数据形状相同的随机数据训练模型,

X = np.random.rand(*(602, 172))
y = np.random.rand(*(602, 2))

model.fit(X, y, epochs=100, batch_size=32)

Epoch 1/100
19/19 [==============================] - 0s 2ms/step - loss: 0.6006 - accuracy: 0.9934
Epoch 2/100
19/19 [==============================] - 0s 5ms/step - loss: 0.6006 - accuracy: 0.9900
Epoch 3/100
19/19 [==============================] - 0s 1ms/step - loss: 0.6006 - accuracy: 0.9983

关于输出形状中的None,None表示这个维度是可变的。

keras 模型中的第一个维度始终是批量大小。您不需要固定的批量大小,除非在非常特殊的情况下(例如,在使用有状态 = True LSTM 层时)。