python - 使用自定义 Keras 数据生成器和损失函数时地面实况标签的形状(无,无)
问题描述
我正在尝试实现自己的检测模型,该模型试图通过其坐标在灰度图像中查找对象,为此我创建了一个自定义数据集,由自定义数据生成器定义:
class DataGenerator(tf.compat.v2.keras.utils.Sequence):
def __init__(self, X_data , y_data, batch_size, shuffle = True):
self.batch_size = batch_size
self.X_data = X_data
self.labels = y_data
self.y_data = y_data
self.shuffle = shuffle
self.n = 0
self.dim = (480, 848)
self.list_IDs = np.arange(len(self.X_data))
self.on_epoch_end()
def __next__(self):
# Get one batch of data
data = self.__getitem__(self.n)
# Batch index
self.n += 1
# If we have processed the entire dataset then
if self.n >= self.__len__():
self.on_epoch_end
self.n = 0
return data
def __len__(self):
# Return the number of batches of the dataset
return math.ceil(len(self.indexes)/self.batch_size)
def __getitem__(self, index):
# Generate indexes of the batch
indexes = self.indexes[index*self.batch_size:
(index+1)*self.batch_size]
# Find list of IDs
list_IDs_temp = [self.list_IDs[k] for k in indexes]
X = self._generate_x(list_IDs_temp)
y = self._generate_y(list_IDs_temp)
return X, y
def on_epoch_end(self):
self.indexes = np.arange(len(self.X_data))
if self.shuffle:
np.random.shuffle(self.indexes)
def _generate_x(self, list_IDs_temp):
X = np.empty((self.batch_size, *self.dim))
for i, ID in enumerate(list_IDs_temp):
X[i,] = cv2.imread(self.X_data[ID],0)
X = (X/255).astype('float32') # Normalize data
return X[:,:,:, np.newaxis]
def _generate_y(self, list_IDs_temp):
y = np.empty((self.batch_size, 2))
for i, ID in enumerate(list_IDs_temp):
y[i] = self.y_data[ID]
return y
当被调用时,它会给出以下输出:
val_generator = DataGenerator(x_test, y_test, batch_size=4, shuffle=False)
images, labels = next(val_generator)
print(labels.shape)
>>>> (4, 2)
这是您期望批量大小为 4 且 x 和 y 作为图像中的坐标的情况。
该模型如下所示:
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
activation='relu',
batch_input_shape=(4, 480, 848, 1)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(15, activation="relu"))
model.compile(loss=simple_loss, optimizer=keras.optimizers.Adam(lr=0.001))
调用模型:
steps_per_epoch = len(train_generator)
validation_steps = len(val_generator)
model.fit(train_generator,
steps_per_epoch=steps_per_epoch,
epochs=10,
validation_data=val_generator,
validation_steps=validation_steps)
我用于测试模型是否正在运行的自定义但简单的损失函数给出了一些错误:
def simple_loss(yTrue, yPred):
probs_logs, coords = yPred[:,:5], yPred[:,5:]
coords_2d = tf.reshape(coords, [4, 10]) # 4 batch size and 10 coords flatten out
_abs = tf.math.abs(yTrue, coords_2d )
return tf.sqrt(_abs)
我首先认为yPred
包含错误,但这产生了以下张量: Tensor("simple_loss/Reshape:0", shape=(4, 10), dtype=float32)
然后我看了看,yTrue
发现形状是 (None, None): Tensor("IteratorGetNext:1", shape=(None, None), dtype=float32)
所以我想我的发电机有问题,我不知道是什么,所以我想知道你们中的任何人是否可以帮助我?
谢谢
解决方案
基本事实的形状应该是 None,因为在代码首次运行时它们还没有被评估。此外,“yTrue”和“yPred”是纯粹的张量,所以一定要对它们的每一个操作都使用张量流函数。
我遇到了同样的错误,因为我使用 tensor.shape 推断了张量的长度,这给了我浮动而不是张量。修复了使用 tf.size() 函数的问题。这将张量的长度作为张量对象返回。
推荐阅读
- java - 我完全迷失在这个刽子手游戏中
- javascript - 使用 contentType 发送的 Java 字节数组:application/octetstream 丢失负字节值
- python - Matplotlib 底图:离线地图
- nativescript - Nativescript 环境值获取布尔值或未定义值。
- vb.net - 不能在文本框中输入超过 9 个数字或删除所有输入的数字
- sql-server - 参数化 SQL 存储过程 Excel Get&Transform
- php - RewriteCond 查询字符串以清除 URL
- php - 旧 mysql 函数的 PDO 等价物,如 fetch assoc
- python - 前向选择策略 - 使用 np.arrays() 进行回归
- woocommerce - Woocommerce 添加复选框并链接到产品单页