Как адаптировать вывод модели keras: ValueError: размеры должны быть равныPython

Программы на Python
Anonymous
Как адаптировать вывод модели keras: ValueError: размеры должны быть равны

Сообщение Anonymous »

Я хочу создать детектор спелости фруктов.
Для этого я мог бы использовать API roboflow, но я хочу создать обученную модель локально.
Я скачал набор данных с этой страницы: https:/ /universe.roboflow.com/mixed-fruit-annotation/fruit-ripness-detector/dataset/2/download/tfrecord
Вот как я анализирую файл записи и обучаю модель кераса:
import tensorflow as tf
import os

# Parsing and preprocessing function
def parse_tfrecord_fn(example):
feature_description = {
'image/object/bbox/ymin': tf.io.VarLenFeature(tf.float32),
'image/width': tf.io.FixedLenFeature([], tf.int64),
'image/object/bbox/xmax': tf.io.VarLenFeature(tf.float32),
'image/encoded': tf.io.FixedLenFeature([], tf.string),
'image/height': tf.io.FixedLenFeature([], tf.int64),
'image/object/bbox/xmin': tf.io.VarLenFeature(tf.float32),
'image/filename': tf.io.FixedLenFeature([], tf.string),
'image/format': tf.io.FixedLenFeature([], tf.string),
'image/object/bbox/ymax': tf.io.VarLenFeature(tf.float32),
'image/object/class/label': tf.io.VarLenFeature(tf.int64),
'image/object/class/text': tf.io.VarLenFeature(tf.string),
}
example = tf.io.parse_single_example(example, feature_description)

# Decode and preprocess image
image = tf.io.decode_jpeg(example['image/encoded'], channels=3)
image = tf.image.resize(image, [224, 224])
image = tf.cast(image, tf.float32) / 255.0 # Normalize to [0, 1]

# Extract labels (assuming single label per image for simplicity)
label = tf.sparse.to_dense(example['image/object/class/label'])[0]

return image, label

# Input function for creating a dataset
def input_fn(file_path, batch_size=32):
dataset = tf.data.TFRecordDataset(file_path)
dataset = dataset.map(parse_tfrecord_fn, num_parallel_calls=tf.data.experimental.AUTOTUNE)
dataset = dataset.shuffle(buffer_size=1000)
dataset = dataset.batch(batch_size)
dataset = dataset.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
return dataset

# Model building function
def build_model(input_shape, num_classes):
model = tf.keras.Sequential([
tf.keras.layers.InputLayer(input_shape=input_shape),
tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(128, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(num_classes)
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
return model

def main():
train_file_path = '
'
valid_file_path = ''

# Determine the number of classes in your dataset
num_classes = 6

# Define input shape based on your data
input_shape = (224, 224, 3)

# Define model
model = build_model(input_shape, num_classes)

# Train model
train_dataset = input_fn(train_file_path)
valid_dataset = input_fn(valid_file_path)

model.fit(train_dataset,
epochs=10,
validation_data=valid_dataset)

# Save model
model.save('fruit_ripeness_detector_model.keras')

if __name__ == "__main__":
main()

В настоящее время я могу передать изображение в эту модель, которая предсказывает класс.
Я хочу расширить свой код, чтобы он также определял, где находится класс на изображении.
p>
Итак, результат, который мне нужен для изображения, должен быть следующим (не обязательно в формате json):
{
"predictions": [
{
"x": 3910,
"y": 2126.5,
"width": 710,
"height": 543,
"confidence": 0.962,
"class": "Good ButterFruitrotation",
"class_id": 4
},
{
"x": 2755.5,
"y": 1673,
"width": 755,
"height": 1576,
"confidence": 0.955,
"class": "Good Bananarotation",
"class_id": 3
},
{
"x": 765,
"y": 1091,
"width": 500,
"height": 698,
"confidence": 0.947,
"class": "Bad ButterFruitrotation",
"class_id": 1
},
{
"x": 3882.5,
"y": 1017,
"width": 461,
"height": 428,
"confidence": 0.946,
"class": "Good Orangerotation",
"class_id": 5
},
{
"x": 1658.5,
"y": 1643,
"width": 781,
"height": 1672,
"confidence": 0.944,
"class": "Bad Bananarotation",
"class_id": 0
},
{
"x": 866,
"y": 2193.5,
"width": 488,
"height": 411,
"confidence": 0.927,
"class": "Bad Orangerotation",
"class_id": 2
}
]
}

Как это реализовать?
Я пробовал разные вещи, например, возвращал bbox после анализа и вводил его в генерацию модели, но это выдавало кучу ошибок. >
Это адаптированный код:
import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense

# Define function to parse TFRecords
def parse_tfrecord_fn(example):
feature_description = {
'image/object/bbox/ymin': tf.io.VarLenFeature(tf.float32),
'image/width': tf.io.FixedLenFeature([], tf.int64),
'image/object/bbox/xmax': tf.io.VarLenFeature(tf.float32),
'image/encoded': tf.io.FixedLenFeature([], tf.string),
'image/height': tf.io.FixedLenFeature([], tf.int64),
'image/object/bbox/xmin': tf.io.VarLenFeature(tf.float32),
'image/filename': tf.io.FixedLenFeature([], tf.string),
'image/format': tf.io.FixedLenFeature([], tf.string),
'image/object/bbox/ymax': tf.io.VarLenFeature(tf.float32),
'image/object/class/label': tf.io.VarLenFeature(tf.int64),
'image/object/class/text': tf.io.VarLenFeature(tf.string),
}

example = tf.io.parse_single_example(example, feature_description)
image = tf.image.decode_jpeg(example['image/encoded'], channels=3)
image = tf.image.resize(image, (224, 224)) # Resize if necessary

# Normalize image pixel values to [0, 1]
image = tf.cast(image, tf.float32) / 255.0

# Convert sparse tensors to dense tensors for bbox coordinates
xmin = tf.sparse.to_dense(example['image/object/bbox/xmin'])
ymin = tf.sparse.to_dense(example['image/object/bbox/ymin'])
xmax = tf.sparse.to_dense(example['image/object/bbox/xmax'])
ymax = tf.sparse.to_dense(example['image/object/bbox/ymax'])

bbox = tf.stack([xmin, ymin, xmax, ymax], axis=-1)

label = tf.cast(tf.sparse.to_dense(example['image/object/class/label']), tf.int32)

return image, {'class_output': label, 'bbox_output': bbox}

# File paths
train_file = r'
'
valid_file = r''

# Create TFRecord datasets
train_dataset = tf.data.TFRecordDataset(train_file)
valid_dataset = tf.data.TFRecordDataset(valid_file)

# Map parsing function to datasets
train_dataset = train_dataset.map(parse_tfrecord_fn)
valid_dataset = valid_dataset.map(parse_tfrecord_fn)

# Optionally shuffle and batch the datasets
batch_size = 32
train_dataset = train_dataset.shuffle(buffer_size=1000).batch(batch_size)
valid_dataset = valid_dataset.batch(batch_size)

# Define model architecture
def create_model(input_shape=(224, 224, 3), num_classes=10):
inputs = Input(shape=input_shape)
x = Conv2D(16, (3, 3), activation='relu')(inputs)
x = MaxPooling2D((2, 2))(x)
x = Conv2D(32, (3, 3), activation='relu')(x)
x = MaxPooling2D((2, 2))(x)
x = Flatten()(x)
x = Dense(64, activation='relu')(x)

# Classification output
class_output = Dense(num_classes, activation='softmax', name='class_output')(x)

# Bounding box output (4 numbers for xmin, ymin, xmax, ymax)
bbox_output = Dense(4, name='bbox_output')(x) # Adjust output size as needed

# Combine into a Keras model
model = Model(inputs=inputs, outputs={'class_output': class_output, 'bbox_output': bbox_output})

return model

# Create an instance of the model
model = create_model()

# Print model summary
model.summary()

# Define custom loss function for bounding box coordinates (e.g., smooth L1 loss)
def smooth_l1_loss(y_true, y_pred):
return tf.reduce_mean(tf.abs(y_true - y_pred))

# Compile the model
model.compile(optimizer='adam',
loss={'class_output': 'sparse_categorical_crossentropy', 'bbox_output': smooth_l1_loss},
metrics={'class_output': 'accuracy'})

# Define steps per epoch and validation steps
steps_per_epoch = len(train_file) // batch_size
validation_steps = len(valid_file) // batch_size

# Train the model
model.fit(train_dataset, epochs=10, steps_per_epoch=steps_per_epoch,
validation_data=valid_dataset, validation_steps=validation_steps)

Вот какая ошибка:
C:\Users\Desktop\python>py main.py
2024-06-29 21:08:13.187140: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
2024-06-29 21:08:13.830194: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
2024-06-29 21:08:15.410930: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: AVX2 AVX512F AVX512_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
Model: "functional"
┌───────────────────────────────┬───────────────────────────┬─────────────────┬────────────────────────────┐
│ Layer (type) │ Output Shape │ Param # │ Connected to │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ input_layer (InputLayer) │ (None, 224, 224, 3) │ 0 │ - │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ conv2d (Conv2D) │ (None, 222, 222, 16) │ 448 │ input_layer[0][0] │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ max_pooling2d (MaxPooling2D) │ (None, 111, 111, 16) │ 0 │ conv2d[0][0] │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ conv2d_1 (Conv2D) │ (None, 109, 109, 32) │ 4,640 │ max_pooling2d[0][0] │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ max_pooling2d_1 │ (None, 54, 54, 32) │ 0 │ conv2d_1[0][0] │
│ (MaxPooling2D) │ │ │ │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ flatten (Flatten) │ (None, 93312) │ 0 │ max_pooling2d_1[0][0] │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ dense (Dense) │ (None, 64) │ 5,972,032 │ flatten[0][0] │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ bbox_output (Dense) │ (None, 4) │ 260 │ dense[0][0] │
├───────────────────────────────┼───────────────────────────┼─────────────────┼────────────────────────────┤
│ class_output (Dense) │ (None, 10) │ 650 │ dense[0][0] │
└───────────────────────────────┴───────────────────────────┴─────────────────┴────────────────────────────┘
Total params: 5,978,030 (22.80 MB)
Trainable params: 5,978,030 (22.80 MB)
Non-trainable params: 0 (0.00 B)
Epoch 1/10
Traceback (most recent call last):
File "C:\Users\Desktop\python\main.py", line 98, in
model.fit(train_dataset, epochs=10, steps_per_epoch=steps_per_epoch,
File "C:\Users\AppData\Local\Programs\Python\Python312\Lib\site-packages\keras\src\utils\traceback_utils.py", line 122, in error_handler
raise e.with_traceback(filtered_tb) from None
File "C:\Users\AppData\Local\Programs\Python\Python312\Lib\site-packages\keras\src\backend\tensorflow\nn.py", line 626, in sparse_categorical_crossentropy
raise ValueError(
ValueError: Argument `output` must have rank (ndim) `target.ndim - 1`. Received: target.shape=(None, None), output.shape=(None, 10)

Вот еще один подход:
import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Conv2D, Reshape, Concatenate
from tensorflow.keras.applications import MobileNetV2

# Function to parse TFRecord files
def parse_tfrecord_fn(example):
feature_description = {
'image/object/bbox/ymin': tf.io.VarLenFeature(tf.float32),
'image/width': tf.io.FixedLenFeature([], tf.int64),
'image/object/bbox/xmax': tf.io.VarLenFeature(tf.float32),
'image/encoded': tf.io.FixedLenFeature([], tf.string),
'image/height': tf.io.FixedLenFeature([], tf.int64),
'image/object/bbox/xmin': tf.io.VarLenFeature(tf.float32),
'image/filename': tf.io.FixedLenFeature([], tf.string),
'image/format': tf.io.FixedLenFeature([], tf.string),
'image/object/bbox/ymax': tf.io.VarLenFeature(tf.float32),
'image/object/class/label': tf.io.VarLenFeature(tf.int64),
'image/object/class/text': tf.io.VarLenFeature(tf.string),
}
example = tf.io.parse_single_example(example, feature_description)
image = tf.image.decode_jpeg(example['image/encoded'])
image = tf.image.resize(image, [224, 224])
image = image / 255.0

bbox = tf.stack([
example['image/object/bbox/ymin'].values,
example['image/object/bbox/xmin'].values,
example['image/object/bbox/ymax'].values,
example['image/object/bbox/xmax'].values,
], axis=-1)
label = example['image/object/class/label'].values
return image, (bbox, label)

# Function to load dataset from TFRecord files
def load_dataset(tfrecord_file, batch_size=32):
raw_dataset = tf.data.TFRecordDataset(tfrecord_file)
parsed_dataset = raw_dataset.map(parse_tfrecord_fn)
dataset = parsed_dataset.batch(batch_size).prefetch(tf.data.experimental.AUTOTUNE)
return dataset

# Function to create the object detection model
def create_model(num_classes):
input_layer = Input(shape=(224, 224, 3))
backbone = MobileNetV2(input_tensor=input_layer, include_top=False, weights='imagenet')
x = backbone.output
x = Conv2D(256, (3, 3), activation='relu')(x)

# Bounding box regression head
bbox_regression = Conv2D(4, (1, 1), name='bbox_regression')(x)
bbox_regression = Reshape((-1, 4))(bbox_regression)

# Classification head
class_head = Conv2D(num_classes, (1, 1), activation='softmax', name='class_head')(x)
class_head = Reshape((-1, num_classes))(class_head)

outputs = Concatenate(axis=-1)([bbox_regression, class_head])
model = Model(inputs=input_layer, outputs=outputs)
return model

# File paths
train_file = r'C:\Users\Desktop\python\Fruit_Ripness_Detector.v2i.tfrecord\train\Good-and-Bad-Fruits.tfrecord'
valid_file = r'C:\Users\Desktop\python\Fruit_Ripness_Detector.v2i.tfrecord\valid\Good-and-Bad-Fruits.tfrecord'

# Load datasets
train_dataset = load_dataset(train_file)
valid_dataset = load_dataset(valid_file)

# Create and compile the model
num_classes = 10 # Replace with the actual number of classes
model = create_model(num_classes)
model.compile(optimizer='adam', loss='mse') # Placeholder loss, customize as needed

# Train the model
model.fit(train_dataset, validation_data=valid_dataset, epochs=10)

Вот какая ошибка:
C:\Users\Desktop\python>py main.py
2024-06-29 23:15:57.686597: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
2024-06-29 23:15:58.493427: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
2024-06-29 23:16:00.635653: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: AVX2 AVX512F AVX512_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
C:\Users\Desktop\python\main.py:45: UserWarning: `input_shape` is undefined or non-square, or `rows` is not in [96, 128, 160, 192, 224]. Weights for input shape (224, 224) will be loaded as the default.
backbone = MobileNetV2(input_tensor=input_layer, include_top=False, weights='imagenet')
Downloading data from https://storage.googleapis.com/tensorfl ... _no_top.h5
←[1m9406464/9406464←[0m ←[32m━━━━━━━━━━━━━━━━━━━━←[0m←[37m←[0m ←[1m8s←[0m 1us/step
Epoch 1/10
Traceback (most recent call last):
File "C:\Users\Desktop\python\main.py", line 75, in
model.fit(train_dataset, validation_data=valid_dataset, epochs=10)
File "C:\Users\AppData\Local\Programs\Python\Python312\Lib\site-packages\keras\src\utils\traceback_utils.py", line 122, in error_handler
raise e.with_traceback(filtered_tb) from None
File "C:\Users\AppData\Local\Programs\Python\Python312\Lib\site-packages\keras\src\losses\losses.py", line 1286, in mean_squared_error
return ops.mean(ops.square(y_true - y_pred), axis=-1)
~~~~~~~^~~~~~~~
ValueError: Dimensions must be equal, but are 4 and 14 for '{{node compile_loss/mse/sub}} = Sub[T=DT_FLOAT](data_1, functional_1/concatenate_1/concat)' with input shapes: [?,?,4], [?,25,14].


Подробнее здесь: https://stackoverflow.com/questions/786 ... t-be-equal

Вернуться в «Python»