Попытка извлечь y_val из набора данных выдает «все входные массивы должны иметь одинаковое количество измерений».

#python #numpy #tensorflow #machine-learning #keras

Вопрос:

Я очень новичок в машинном обучении и python в целом. Я работаю над проектом, требующим создания модели классификации изображений. Я прочитал данные с моего локального диска, используя tf.keras.preprocessing.image_dataset_from_directory , и теперь я пытаюсь извлечь x_val и y_val сгенерировать файл skilearn.metrics.classification_report .

Проблема в том, что всякий раз, когда я звоню:

 y_val = np.concatenate([y_val, np.argmax(y.numpy(), axis=-1)])`
 

Я получаю следующую ошибку, и я понятия не имею, почему и как ее исправить

y_val = np.объединение([y_val, np.argmax(y.numpy(), ось=-1)]) Файл «<внутренние функции array_function>», строка 5, в ошибке объединения значений: все входные массивы должны иметь одинаковое количество измерений, но массив с индексом 0 имеет 1 измерение(ы), а массив с индексом 1 имеет 0 измерений (ов)`


Вот мой код

 #data is split into train and validation folders with 6 folders in each representing a class, like this:
#data/train/hamburger/<haburger train images in here>
#data/train/pizza/<pizza train images in here>
#data/validation/hamburger/<haburger test images in here>
#data/validation/pizza/<pizza test images in here> 

#training_dir = ......
validation_dir = pathlib.Path('path to data dir on local disk')

#hyperparams

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
  training_dir,
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)

val_ds = tf.keras.preprocessing.image_dataset_from_directory(
  validation_dir,
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)

class_names = train_ds.class_names
print(class_names)
print(val_ds.class_names)

AUTOTUNE = tf.data.AUTOTUNE

train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

normalization_layer = layers.experimental.preprocessing.Rescaling(1./255)

resize_and_rescale = tf.keras.Sequential([
  layers.experimental.preprocessing.Resizing(img_height, img_width),
  layers.experimental.preprocessing.Rescaling(1./255)
])

#normalization, augmentation, model layers

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['accuracy'])

model.summary()

start_time = time.monotonic()

epochs = 1
history = model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=epochs
)

#plot

#testing random image
test_path = pathlib.Path('C:/Users/adi/Desktop/New folder/downloads/hamburger/images(91).jpg')

img = keras.preprocessing.image.load_img(
    test_path, target_size=(img_height, img_width)
)
img_array = keras.preprocessing.image.img_to_array(img)
img_array = tf.expand_dims(img_array, 0) # Create a batch

predictions = model.predict(img_array)
score = tf.nn.softmax(predictions[0])

print(
    "This image most likely belongs to {} with a {:.2f} percent confidence."
    .format(class_names[np.argmax(score)], 100 * np.max(score))
)


x_val = np.array([])
y_val = np.array([])
for x, y in val_ds:
  x_val = np.concatenate([x_val, np.argmax(model.predict(x), axis=-1)])
  y_val = np.concatenate([y_val, np.argmax(y.numpy(), axis=-1)])        #<----- crashes here

print(classification_report(y_val, x_val, target_names = ['doughnuts (Class 0)','french_fries (Class 1)', 'hamburger (Class 2)','hot_dog (Class 3)', 'ice_cream (Class 4)','pizza (Class 5)']))
 

Любые идеи, почему я получаю эту ошибку и как я могу ее исправить. Или, в качестве альтернативы, как я могу получить то, что мне нужно, чтобы classification_report работал. Спасибо.

Комментарии:

1. можете ли вы показать нам пару элементов из val_ds?

2. @sk877 хорошо. как мне это сделать? или вы имеете в виду изображения?

3. просто попробуйте напечатать(val_ds[0:3]) или что-то в этом роде и уменьшите 3, если массивы слишком длинные.

4. кроме того, не связанные, но хорошо приспосабливающиеся на ранней стадии… странно оценивать модель (с отчетом о классификации) между «x_val» и «y_val». вы оцениваете фактический y по сравнению с прогнозируемым y, поэтому, возможно, подумайте о переименовании ваших переменных в y_pred и y_act или что-то в этом роде, иначе люди будут плакать

5. @sk877ok. Я переименую. Спасибо. попытался распечатать. дай мне TypeError: 'PrefetchDataset' object is not subscriptable

Ответ №1:

Вам не нужна argmax операция при получении истинных классов.

Поскольку вы не указали class_mode в каталоге tf.keras.preprocessing.image_dataset_from_directory, метки разрежены, что означает, что они не закодированы одним горячим способом.

Если бы у вас были векторные метки с одним горячим кодом, приведенный выше код был бы правильным.

Другое дело, что переименование ваших массивов должно быть лучше таким образом, и при прогнозировании одного изображения за раз вы можете использовать model(x) то, что более эффективно. Правильный код должен быть:

 predicted_classes = np.array([])
labels = np.array([])

for x, y in val_ds:
  predicted_classes = np.concatenate([predicted_classes, np.argmax(model(x), axis=-1)])
  labels = np.concatenate([labels, y.numpy()])    
 

Комментарии:

1. Это работает. Большое вам спасибо, я потратил на это больше половины дня. Сейчас я ухожу, чтобы понять, что такое однократное кодирование.

2. Скажите, у вас есть ярлыки [0], [1], [2] —> 0 представлен в виде [1,0,0] // 1 —>> [0,1,0] … и так далее.