ValueError: Error when checking target: expected activation_6 to have shape(None,2) but got array with shape (5760,1)
ValueError: Error when checking target: expected activation_6 to have shape(None,2) but got array with shape (5760,1)
我正在尝试为具有 8 类 的卷积神经网络(在 Keras 中)调整 Python 代码以在 2 类 上工作。我的问题是收到以下错误消息:
ValueError: Error when checking target: expected activation_6 to have
shape(None,2) but got array with shape (5760,1).
我的模型如下(没有缩进问题):
class MiniVGGNet:
@staticmethod
def build(width, height, depth, classes):
# initialize the model along with the input shape to be
# "channels last" and the channels dimension itself
model = Sequential()
inputShape = (height, width, depth)
chanDim = -1
# if we are using "channels first", update the input shape
# and channels dimension
if K.image_data_format() == "channels_first":
inputShape = (depth, height, width)
chanDim = 1
# first CONV => RELU => CONV => RELU => POOL layer set
model.add(Conv2D(32, (3, 3), padding="same",
input_shape=inputShape))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(32, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
# second CONV => RELU => CONV => RELU => POOL layer set
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
# first (and only) set of FC => RELU layers
model.add(Flatten())
model.add(Dense(512))
model.add(Activation("relu"))
model.add(BatchNormalization())
model.add(Dropout(0.5))
# softmax classifier
model.add(Dense(classes))
model.add(Activation("softmax"))
# return the constructed network architecture
return model
其中 类 = 2,并且 inputShape=(32,32,3).
我知道我的错误与我的 binary_crossentropy 的 classes/use 有关,并且出现在下面的 model.fit 行中,但一直无法弄清楚为什么会这样有问题,或者如何解决它。
通过将上面的 model.add(Dense(类)) 更改为 model.add(Dense(类-1)) 我可以训练模型,但是然后我的标签大小和 target_names 不匹配,我只有一个类别,所有内容都归类为。
# import the necessary packages
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from pyimagesearch.nn.conv import MiniVGGNet
from pyimagesearch.preprocessing import ImageToArrayPreprocessor
from pyimagesearch.preprocessing import SimplePreprocessor
from pyimagesearch.datasets import SimpleDatasetLoader
from keras.optimizers import SGD
#from keras.datasets import cifar10
from imutils import paths
import matplotlib.pyplot as plt
import numpy as np
import argparse
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True,
help="path to input dataset")
ap.add_argument("-o", "--output", required=True,
help="path to the output loss/accuracy plot")
args = vars(ap.parse_args())
# grab the list of images that we'll be describing
print("[INFO] loading images...")
imagePaths = list(paths.list_images(args["dataset"]))
# initialize the image preprocessors
sp = SimplePreprocessor(32, 32)
iap = ImageToArrayPreprocessor()
# load the dataset from disk then scale the raw pixel intensities
# to the range [0, 1]
sdl = SimpleDatasetLoader(preprocessors=[sp, iap])
(data, labels) = sdl.load(imagePaths, verbose=500)
data = data.astype("float") / 255.0
# partition the data into training and testing splits using 75% of
# the data for training and the remaining 25% for testing
(trainX, testX, trainY, testY) = train_test_split(data, labels,
test_size=0.25, random_state=42)
# convert the labels from integers to vectors
trainY = LabelBinarizer().fit_transform(trainY)
testY = LabelBinarizer().fit_transform(testY)
# initialize the label names for the items dataset
labelNames = ["mint", "used"]
# initialize the optimizer and model
print("[INFO] compiling model...")
opt = SGD(lr=0.01, decay=0.01 / 10, momentum=0.9, nesterov=True)
model = MiniVGGNet.build(width=32, height=32, depth=3, classes=2)
model.compile(loss="binary_crossentropy", optimizer=opt,
metrics=["accuracy"])
# train the network
print("[INFO] training network...")
H = model.fit(trainX, trainY, validation_data=(testX, testY),
batch_size=64, epochs=10, verbose=1)
print ("Made it past training")
# evaluate the network
print("[INFO] evaluating network...")
predictions = model.predict(testX, batch_size=64)
print(classification_report(testY.argmax(axis=1),
predictions.argmax(axis=1), target_names=labelNames))
# plot the training loss and accuracy
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0, 10), H.history["loss"], label="train_loss")
plt.plot(np.arange(0, 10), H.history["val_loss"], label="val_loss")
plt.plot(np.arange(0, 10), H.history["acc"], label="train_acc")
plt.plot(np.arange(0, 10), H.history["val_acc"], label="val_acc")
plt.title("Training Loss and Accuracy on items dataset")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend()
plt.savefig(args["output"])
我已经看过这些问题了,但是无法根据回答解决这个问题。
任何建议或帮助将不胜感激,因为我在过去的几天里一直在做这件事。
我认为问题出在 LabelBinarizer
的使用上。
来自这个例子:
>>> lb = preprocessing.LabelBinarizer()
>>> lb.fit_transform(['yes', 'no', 'no', 'yes'])
array([[1],
[0],
[0],
[1]])
我了解到您的转换输出具有相同的格式,即。 e.单个 1
或 0
编码 "is new" 或 "is used".
如果您的问题只需要在这两个 class 之间进行 class 化,则该格式更可取,因为它包含所有信息并且使用的 space 比替代格式少,我. e. [1,0], [0,1], [0,1], [1,0]
.
因此,使用 classes = 1
是正确的,输出应该是一个浮点数,表示网络对第一个样本的置信度 class。由于这些值总和必须为 1,因此可以通过从 1 中减去 class 轻松推断出它在第二个中的概率。
您需要将 softmax
替换为任何其他激活,因为单个值上的 softmax 总是 returns 1. 我不完全确定 binary_crossentropy
的行为single-valued 结果,你可能想尝试 mean_squared_error
作为损失。
如果您希望扩展模型以涵盖两个以上的 class,您可能希望将目标向量转换为 One-hot 编码。我相信 LabelBinarizer
中的 inverse_transform
会这样做,尽管这似乎是一种迂回的方式。我看到 sklearn 也有 OneHotEncoder
这可能是更合适的替代品。
注意:您可以更轻松地指定任何层的激活函数,例如:
Dense(36, activation='relu')
这可能有助于将您的代码保持在可管理的大小。
Matt 的评论是绝对正确的,因为问题出在使用 LabelBinarizer 上,这个提示使我找到了一个解决方案,不需要我放弃使用 softmax,或将最后一层更改为 类 = 1. 对于后代和其他人,这是我更改的代码部分以及我如何避免使用 LabelBinarizer:
from keras.utils import np_utils
from sklearn.preprocessing import LabelEncoder
# load the dataset from disk then scale the raw pixel intensities
# to the range [0,1]
sp = SimplePreprocessor (32, 32)
iap = ImageToArrayPreprocessor()
# encode the labels, converting them from strings to integers
le=LabelEncoder()
labels = le.fit_transform(labels)
data = data.astype("float") / 255.0
labels = np_utils.to_categorical(labels,2)
# partition the data into training and testing splits using 75% of
# the data for training and the remaining 25% for testing
....
我正在尝试为具有 8 类 的卷积神经网络(在 Keras 中)调整 Python 代码以在 2 类 上工作。我的问题是收到以下错误消息:
ValueError: Error when checking target: expected activation_6 to have shape(None,2) but got array with shape (5760,1).
我的模型如下(没有缩进问题):
class MiniVGGNet:
@staticmethod
def build(width, height, depth, classes):
# initialize the model along with the input shape to be
# "channels last" and the channels dimension itself
model = Sequential()
inputShape = (height, width, depth)
chanDim = -1
# if we are using "channels first", update the input shape
# and channels dimension
if K.image_data_format() == "channels_first":
inputShape = (depth, height, width)
chanDim = 1
# first CONV => RELU => CONV => RELU => POOL layer set
model.add(Conv2D(32, (3, 3), padding="same",
input_shape=inputShape))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(32, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
# second CONV => RELU => CONV => RELU => POOL layer set
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
# first (and only) set of FC => RELU layers
model.add(Flatten())
model.add(Dense(512))
model.add(Activation("relu"))
model.add(BatchNormalization())
model.add(Dropout(0.5))
# softmax classifier
model.add(Dense(classes))
model.add(Activation("softmax"))
# return the constructed network architecture
return model
其中 类 = 2,并且 inputShape=(32,32,3).
我知道我的错误与我的 binary_crossentropy 的 classes/use 有关,并且出现在下面的 model.fit 行中,但一直无法弄清楚为什么会这样有问题,或者如何解决它。
通过将上面的 model.add(Dense(类)) 更改为 model.add(Dense(类-1)) 我可以训练模型,但是然后我的标签大小和 target_names 不匹配,我只有一个类别,所有内容都归类为。
# import the necessary packages
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from pyimagesearch.nn.conv import MiniVGGNet
from pyimagesearch.preprocessing import ImageToArrayPreprocessor
from pyimagesearch.preprocessing import SimplePreprocessor
from pyimagesearch.datasets import SimpleDatasetLoader
from keras.optimizers import SGD
#from keras.datasets import cifar10
from imutils import paths
import matplotlib.pyplot as plt
import numpy as np
import argparse
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True,
help="path to input dataset")
ap.add_argument("-o", "--output", required=True,
help="path to the output loss/accuracy plot")
args = vars(ap.parse_args())
# grab the list of images that we'll be describing
print("[INFO] loading images...")
imagePaths = list(paths.list_images(args["dataset"]))
# initialize the image preprocessors
sp = SimplePreprocessor(32, 32)
iap = ImageToArrayPreprocessor()
# load the dataset from disk then scale the raw pixel intensities
# to the range [0, 1]
sdl = SimpleDatasetLoader(preprocessors=[sp, iap])
(data, labels) = sdl.load(imagePaths, verbose=500)
data = data.astype("float") / 255.0
# partition the data into training and testing splits using 75% of
# the data for training and the remaining 25% for testing
(trainX, testX, trainY, testY) = train_test_split(data, labels,
test_size=0.25, random_state=42)
# convert the labels from integers to vectors
trainY = LabelBinarizer().fit_transform(trainY)
testY = LabelBinarizer().fit_transform(testY)
# initialize the label names for the items dataset
labelNames = ["mint", "used"]
# initialize the optimizer and model
print("[INFO] compiling model...")
opt = SGD(lr=0.01, decay=0.01 / 10, momentum=0.9, nesterov=True)
model = MiniVGGNet.build(width=32, height=32, depth=3, classes=2)
model.compile(loss="binary_crossentropy", optimizer=opt,
metrics=["accuracy"])
# train the network
print("[INFO] training network...")
H = model.fit(trainX, trainY, validation_data=(testX, testY),
batch_size=64, epochs=10, verbose=1)
print ("Made it past training")
# evaluate the network
print("[INFO] evaluating network...")
predictions = model.predict(testX, batch_size=64)
print(classification_report(testY.argmax(axis=1),
predictions.argmax(axis=1), target_names=labelNames))
# plot the training loss and accuracy
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0, 10), H.history["loss"], label="train_loss")
plt.plot(np.arange(0, 10), H.history["val_loss"], label="val_loss")
plt.plot(np.arange(0, 10), H.history["acc"], label="train_acc")
plt.plot(np.arange(0, 10), H.history["val_acc"], label="val_acc")
plt.title("Training Loss and Accuracy on items dataset")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend()
plt.savefig(args["output"])
我已经看过这些问题了,但是无法根据回答解决这个问题。
任何建议或帮助将不胜感激,因为我在过去的几天里一直在做这件事。
我认为问题出在 LabelBinarizer
的使用上。
来自这个例子:
>>> lb = preprocessing.LabelBinarizer()
>>> lb.fit_transform(['yes', 'no', 'no', 'yes'])
array([[1],
[0],
[0],
[1]])
我了解到您的转换输出具有相同的格式,即。 e.单个 1
或 0
编码 "is new" 或 "is used".
如果您的问题只需要在这两个 class 之间进行 class 化,则该格式更可取,因为它包含所有信息并且使用的 space 比替代格式少,我. e. [1,0], [0,1], [0,1], [1,0]
.
因此,使用 classes = 1
是正确的,输出应该是一个浮点数,表示网络对第一个样本的置信度 class。由于这些值总和必须为 1,因此可以通过从 1 中减去 class 轻松推断出它在第二个中的概率。
您需要将 softmax
替换为任何其他激活,因为单个值上的 softmax 总是 returns 1. 我不完全确定 binary_crossentropy
的行为single-valued 结果,你可能想尝试 mean_squared_error
作为损失。
如果您希望扩展模型以涵盖两个以上的 class,您可能希望将目标向量转换为 One-hot 编码。我相信 LabelBinarizer
中的 inverse_transform
会这样做,尽管这似乎是一种迂回的方式。我看到 sklearn 也有 OneHotEncoder
这可能是更合适的替代品。
注意:您可以更轻松地指定任何层的激活函数,例如:
Dense(36, activation='relu')
这可能有助于将您的代码保持在可管理的大小。
Matt 的评论是绝对正确的,因为问题出在使用 LabelBinarizer 上,这个提示使我找到了一个解决方案,不需要我放弃使用 softmax,或将最后一层更改为 类 = 1. 对于后代和其他人,这是我更改的代码部分以及我如何避免使用 LabelBinarizer:
from keras.utils import np_utils
from sklearn.preprocessing import LabelEncoder
# load the dataset from disk then scale the raw pixel intensities
# to the range [0,1]
sp = SimplePreprocessor (32, 32)
iap = ImageToArrayPreprocessor()
# encode the labels, converting them from strings to integers
le=LabelEncoder()
labels = le.fit_transform(labels)
data = data.astype("float") / 255.0
labels = np_utils.to_categorical(labels,2)
# partition the data into training and testing splits using 75% of
# the data for training and the remaining 25% for testing
....