У меня были значительные проблемы с тем, чтобы моя модель TensorFlow действительно работала с моими собственными входными данными.
Я рисую изображения из помеченных каталогов. У меня есть два класса изображений, «хорошие» и «плохие», которые хранятся в их собственных каталогах.
Я читаю их, используя встроенный list_files(glob)
TensorFlow, и обрабатываю их строго с помощью TensorFlow. операции. Однако теперь, когда я пытаюсь запустить свою модель, она перестает работать в первую эпоху и выводит код ошибки: tensorflow/core/framework/op_kernel.cc:1730] OP_REQUIRES failed at cast_op.cc:123 : Unimplemented: Cast string to float is not supported
Мой код выглядит следующим образом:
import numpy as np
import matplotlib.pyplot as plt
import pathlib
import tensorflow as tf
from tensorflow.keras import layers, models
import random
import os
class E6Classifier:
image_size = 256
train_test_proportion = .8
current_working_directory = pathlib.Path.cwd()
data_directory = current_working_directory.parent / 'Jupyter Notebooks' / 'Tensorflow' / 'e6Classifier' / 'data'
categories = ['good', 'bad']
good_images = []
bad_images = []
batch_size = 32
total_dataset = None
train_dataset = None
test_dataset = None
def __init__(self):
self.read_images()
self.print_statistics()
#TensorFlow implementation
self.make_tensorflow_dataset()
self.train_test_split()
self.create_model()
self.train_model()
def read_images(self):
good_path = self.data_directory / self.categories[0]
bad_path = self.data_directory / self.categories[1]
filetypes = ('*.jpg', '*.png')
for filetype in filetypes:
self.good_images.extend(good_path.glob(filetype))
self.bad_images.extend(bad_path.glob(filetype))
def print_statistics(self):
self.num_good_images = len(self.good_images)
self.num_bad_images = len(self.bad_images)
self.total_images = self.num_good_images + self.num_bad_images
self.proportion_good = round(self.num_good_images / self.total_images * 100, 2)
print(str(self.total_images) + ' total images | ' + str(self.num_good_images) + ' good images, ' + str(self.num_bad_images) + ' bad images | ' + str(self.proportion_good) + ' percent good to bad')
def make_tensorflow_dataset(self):
directory_strings = []
for filetype in ['*.jpg', '*.png']:
directory_strings.append(str(self.data_directory / 'good' / filetype))
directory_strings.append(str(self.data_directory / 'bad' / filetype))
list_dataset = tf.data.Dataset.list_files(directory_strings)
labeled_dataset = list_dataset.map(self.process_tensor_path)
self.total_dataset = labeled_dataset
def process_tensor_path(self, filepath):
label = tf.strings.split(filepath, os.sep)[-2]
image = tf.io.read_file(filepath)
image = tf.image.decode_image(image, channels = 3)
image = tf.image.convert_image_dtype(image, tf.float32)
image = tf.image.resize_with_pad(image, target_width = self.image_size, target_height = self.image_size)
return image, label
def train_test_split(self):
num_training_images = int(round(self.total_images * self.train_test_proportion,0))
self.total_dataset.shuffle(buffer_size = self.total_images)
self.train_dataset = self.total_dataset.take(num_training_images)
self.test_dataset = self.total_dataset.skip(num_training_images)
def create_model(self):
#Batch datasets
self.train_dataset = self.train_dataset.batch(self.batch_size, drop_remainder = True)
self.test_dataset = self.test_dataset.batch(self.batch_size, drop_remainder = True)
self.total_dataset = self.total_dataset.batch(self.batch_size, drop_remainder = True)
#Create model
self.model = models.Sequential()
#Add a convolutional layer to detect features in the image
self.model.add(layers.Conv2D(32, (3, 3), activation = 'relu', input_shape = (self.image_size, self.image_size, 3)))
#Add a pooling layer to remove sensitivity to position in the image of the feature
self.model.add(layers.MaxPooling2D((2, 2)))
#Repeat ad nauseum
self.model.add(layers.Conv2D(64, (3, 3), activation = 'relu'))
self.model.add(layers.MaxPooling2D(2, 2))
self.model.add(layers.Conv2D(64, (3, 3), activation = 'relu'))
self.model.add(layers.MaxPooling2D(2, 2))
self.model.add(layers.Conv2D(64, (3, 3), activation = 'relu'))
self.model.add(layers.MaxPooling2D(2, 2))
self.model.add(layers.Conv2D(64, (3, 3), activation = 'relu'))
#Add dense layers
self.model.add(layers.Flatten())
self.model.add(layers.Dense(64, activation = 'relu'))
self.model.add(layers.Dense(2))
#Compile the model for training
self.model.compile(optimizer = 'adam', loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits = True), metrics = ['accuracy'])
def train_model(self):
#self.train_dataset.repeat()
#self.test_dataset.repeat()
self.model.fit(self.train_dataset, epochs = 1, validation_data = self.test_dataset, verbose = True)
def main():
E6Classifier()
if __name__ == '__main__':
main()
Я не понимаю, что вызывает эту ошибку, и, похоже, нет огромного количества информации о том, где на самом деле происходит сбой вызова. Я просмотрел типы данных моих наборов данных TensorFlow, и они указывают, что они являются кортежами Tensors с типами float32 и string соответственно.
Это проблема, связанная с наличием строк для названий категорий? Если да, то как мне go заменить названия категорий номерами?