Keras 不兼容输入

问题描述

我正在使用 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,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,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 模型中的第一个维度始终是批量大小。您不需要固定批量大小,除非在非常特殊的情况下(例如,使用 stateful=True LSTM 层时)。