MNIST не выдает правильный прогноз – школьный проект ⇐ Python
MNIST не выдает правильный прогноз – школьный проект
Я создал простой скрипт Python, который открывает небольшое окно и позволяет пользователю нарисовать цифры от 1 до 9. Когда я тестирую его, он постоянно выдает неверные цифры, но говорит, что точность при обучении составляет 98%. Иногда он зависал и просто выводил одну и ту же цифру, независимо от того, что было нарисовано, поэтому я решил удалить старую модель и временный файл, но это не сработало. Вот код для обучения модели и графического интерфейса
Извиняюсь за мой уродливый код, я новичок в Python
model.py
импортировать тензорный поток как tf из keras.src.saving.saving_api импортируйте load_model из tensorflow.keras.models импортировать последовательный из tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D из tensorflow.keras.datasets импортировать mnist из tensorflow.keras.utils импорт в_categorical из изображения импорта PIL импортировать numpy как np импортировать ОС #удалить старое если os.path.exists("temp_canvas.ps"): # Удаляем файл os.remove("temp_canvas.ps") если os.path.exists("mnist_model.keras"): # Удаляем файл os.remove("mnist_model.keras") # Загрузите и предварительно обработайте набор данных MNIST (train_images, train_labels), (test_images, test_labels) = mnist.load_data() train_images = train_images.reshape((60000, 28, 28, 1)) train_images = train_images.astype('float32') / 255 test_images = test_images.reshape((10000, 28, 28, 1)) test_images = test_images.astype('float32') / 255 train_labels = to_categorical(train_labels) test_labels = to_categorical (test_labels) # Создаем модель модель = Последовательная([ Conv2D(32, (3, 3), активация='relu', input_shape=(28, 28, 1)), МаксPooling2D((2, 2)), Conv2D(64, (3, 3), активация='relu'), МаксPooling2D((2, 2)), Conv2D(64, (3, 3), активация='relu'), Сгладить(), Плотный(64, активация='relu'), Плотный (10, активация = 'softmax') ]) # Скомпилируем модель model.compile(optimizer='adam', потеря = 'categorical_crossentropy', метрики=['точность']) # Обучим модель model.fit(train_images, train_labels, epochs=5, Batch_size=64, validation_data=(test_images, test_labels)) # Сохраняем модель model.save('mnist_model.h5') защита preprocess_image (изображение): # Конвертируем изображение холста в правильный формат изображение = Image.fromarray(изображение) image = image.resize((28, 28)).convert('L') # Изменение размера и преобразование в оттенки серого image_for_display = np.array(image) # 2D-массив для отображения image_for_model = image_for_display.reshape(1, 28, 28, 1) # 4D-массив для модели image_for_model = image_for_model/255.0 # Нормализовать вернуть изображение_для_дисплея, изображение_для_модели Защиту предсказывающей_цифры (изображение): mnist_model = load_model('mnist_model.h5') image = image.reshape(1, 28, 28, 1) # 4D-массив для модели image = image / 255.0 # Нормализовать предсказание = mnist_model.predict(изображение) return np.argmax(prediction, axis=1)[0] # Возвращаем предсказанную цифру цифра-декодер.py
импортировать tkinter как tk из окна сообщения импорта tkinter из импорта модели Predict_digit импортировать numpy как np из PIL импортировать изображение, ImageTk время импорта импортировать ОС класс DigitDecoder: защита __init__(сам): self.root = tk.Tk() self.root.title("Нарисуйте букву") #окно настройки self.canvas = tk.Canvas(self.root, ширина=400, высота=400) self.canvas.pack() #добавить кнопку идентификации self.identify_button = tk.Button(self.root, text="Что я?", команда=self.identify_letter) self.identify_button.pack() #добавить кнопку сброса self.reset_button = tk.Button(self.root, text="Reset", команда=self.reset_canvas) self.reset_button.pack() self.old_x = Нет self.old_y = Нет self.setup() self.root.mainloop() настройка защиты (самостоятельная): self.canvas.bind('', self.paint) self.canvas.bind('', self.reset) Защиту show_popup(я, сообщение): messagebox.showinfo("Информация", сообщение) #нарисуй цифру Def Paint(сам, событие): если self.old_x и self.old_y: self.canvas.create_line(self.old_x, self.old_y, event.x, event.y, ширина=12, capstyle=tk.ROUND, сглаживание=tk.TRUE) self.old_x = event.x self.old_y = event.y #ОТЛАДКА Защиту display_preprocessed_image (я, изображение): # Убедитесь, что изображение 2D для оттенков серого если len(image.shape) > 2: image = image.squeeze() # При необходимости уменьшаем до 2D # Создаем новое окно image_window = tk.Toplevel(self.root) image_window.title("Предварительно обработанное изображение") # создаем окно рисования image_canvas = tk.Canvas(image_window, width=image.shape[1], height=image.shape[0]) image_canvas.pack() # нарисовать цифру для меня в диапазоне (image.shape[0]): для j в диапазоне (image.shape[1]): пиксельная интенсивность = изображение [i, j] цвет = f'#{pixel_intensity:02x}{pixel_intensity:02x}{pixel_intensity:02x}' image_canvas.create_rectangle(j, i, j+1, i+1, контур=цвет, заливка=цвет) #ОТЛАДКА Защиту preprocess_for_display (я, изображение): изображение = Image.fromarray(изображение) image = image.resize((28, 28)).convert('L') # уменьшение размера n преобразование в оттенки серого return np.array(image) # 2D-массив для отображения Защиту preprocess_for_model(я, изображение): изображение = Image.fromarray(изображение) image = image.resize((28, 28)).convert('L') # уменьшение размера n преобразование в оттенки серого изображение = np.array(изображение) image = image.reshape(1, 28, 28, 1) # Изменение формы модели изображение = изображение/255.0 вернуть изображение сброс защиты (я, событие): self.old_x = Нет self.old_y = Нет #берёт нарисованное изображение, пропускает его через mnist-модель и выводит то, что, по мнению модели, представляет собой буква. защита идентификации_буквы (сам): # Получить рисунок холста в виде изображения self.canvas.postscript(file='temp_canvas.ps', colormode='color') холст_изображение = Image.open('temp_canvas.ps') холст_изображение = холст_изображение.конвертировать('RGB') # конвертируем изображение в массив numpy холст_массив = np.array(canvas_image) image_for_display = self.preprocess_for_display(canvas_array) # отображаем предварительно обработанное изображение для отладки #DEBUGGING ТОЛЬКО ДЛЯ ИСПОЛЬЗОВАНИЯ self.display_preprocessed_image(image_for_display) # prreprocess изображение для модели image_for_model = self.preprocess_for_model(canvas_array) # Вызов функции прогнозирования из model.py цифра = предсказать_цифру (изображение_для_модели) # Распечатайте и покажите результат прогноза print(f"Прогнозируемая цифра: {цифра}") self.show_popup(f"Прогнозируемая цифра: {digit}") если os.path.exists('temp_canvas.ps'): os.remove('temp_canvas.ps') время.сон(1) self.root.destroy() #сброс области рисования защита reset_canvas (сам): self.canvas.delete("все") # Создаем экземпляр приложения приложение = ЦифровойДекодер()
Я создал простой скрипт Python, который открывает небольшое окно и позволяет пользователю нарисовать цифры от 1 до 9. Когда я тестирую его, он постоянно выдает неверные цифры, но говорит, что точность при обучении составляет 98%. Иногда он зависал и просто выводил одну и ту же цифру, независимо от того, что было нарисовано, поэтому я решил удалить старую модель и временный файл, но это не сработало. Вот код для обучения модели и графического интерфейса
Извиняюсь за мой уродливый код, я новичок в Python
model.py
импортировать тензорный поток как tf из keras.src.saving.saving_api импортируйте load_model из tensorflow.keras.models импортировать последовательный из tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D из tensorflow.keras.datasets импортировать mnist из tensorflow.keras.utils импорт в_categorical из изображения импорта PIL импортировать numpy как np импортировать ОС #удалить старое если os.path.exists("temp_canvas.ps"): # Удаляем файл os.remove("temp_canvas.ps") если os.path.exists("mnist_model.keras"): # Удаляем файл os.remove("mnist_model.keras") # Загрузите и предварительно обработайте набор данных MNIST (train_images, train_labels), (test_images, test_labels) = mnist.load_data() train_images = train_images.reshape((60000, 28, 28, 1)) train_images = train_images.astype('float32') / 255 test_images = test_images.reshape((10000, 28, 28, 1)) test_images = test_images.astype('float32') / 255 train_labels = to_categorical(train_labels) test_labels = to_categorical (test_labels) # Создаем модель модель = Последовательная([ Conv2D(32, (3, 3), активация='relu', input_shape=(28, 28, 1)), МаксPooling2D((2, 2)), Conv2D(64, (3, 3), активация='relu'), МаксPooling2D((2, 2)), Conv2D(64, (3, 3), активация='relu'), Сгладить(), Плотный(64, активация='relu'), Плотный (10, активация = 'softmax') ]) # Скомпилируем модель model.compile(optimizer='adam', потеря = 'categorical_crossentropy', метрики=['точность']) # Обучим модель model.fit(train_images, train_labels, epochs=5, Batch_size=64, validation_data=(test_images, test_labels)) # Сохраняем модель model.save('mnist_model.h5') защита preprocess_image (изображение): # Конвертируем изображение холста в правильный формат изображение = Image.fromarray(изображение) image = image.resize((28, 28)).convert('L') # Изменение размера и преобразование в оттенки серого image_for_display = np.array(image) # 2D-массив для отображения image_for_model = image_for_display.reshape(1, 28, 28, 1) # 4D-массив для модели image_for_model = image_for_model/255.0 # Нормализовать вернуть изображение_для_дисплея, изображение_для_модели Защиту предсказывающей_цифры (изображение): mnist_model = load_model('mnist_model.h5') image = image.reshape(1, 28, 28, 1) # 4D-массив для модели image = image / 255.0 # Нормализовать предсказание = mnist_model.predict(изображение) return np.argmax(prediction, axis=1)[0] # Возвращаем предсказанную цифру цифра-декодер.py
импортировать tkinter как tk из окна сообщения импорта tkinter из импорта модели Predict_digit импортировать numpy как np из PIL импортировать изображение, ImageTk время импорта импортировать ОС класс DigitDecoder: защита __init__(сам): self.root = tk.Tk() self.root.title("Нарисуйте букву") #окно настройки self.canvas = tk.Canvas(self.root, ширина=400, высота=400) self.canvas.pack() #добавить кнопку идентификации self.identify_button = tk.Button(self.root, text="Что я?", команда=self.identify_letter) self.identify_button.pack() #добавить кнопку сброса self.reset_button = tk.Button(self.root, text="Reset", команда=self.reset_canvas) self.reset_button.pack() self.old_x = Нет self.old_y = Нет self.setup() self.root.mainloop() настройка защиты (самостоятельная): self.canvas.bind('', self.paint) self.canvas.bind('', self.reset) Защиту show_popup(я, сообщение): messagebox.showinfo("Информация", сообщение) #нарисуй цифру Def Paint(сам, событие): если self.old_x и self.old_y: self.canvas.create_line(self.old_x, self.old_y, event.x, event.y, ширина=12, capstyle=tk.ROUND, сглаживание=tk.TRUE) self.old_x = event.x self.old_y = event.y #ОТЛАДКА Защиту display_preprocessed_image (я, изображение): # Убедитесь, что изображение 2D для оттенков серого если len(image.shape) > 2: image = image.squeeze() # При необходимости уменьшаем до 2D # Создаем новое окно image_window = tk.Toplevel(self.root) image_window.title("Предварительно обработанное изображение") # создаем окно рисования image_canvas = tk.Canvas(image_window, width=image.shape[1], height=image.shape[0]) image_canvas.pack() # нарисовать цифру для меня в диапазоне (image.shape[0]): для j в диапазоне (image.shape[1]): пиксельная интенсивность = изображение [i, j] цвет = f'#{pixel_intensity:02x}{pixel_intensity:02x}{pixel_intensity:02x}' image_canvas.create_rectangle(j, i, j+1, i+1, контур=цвет, заливка=цвет) #ОТЛАДКА Защиту preprocess_for_display (я, изображение): изображение = Image.fromarray(изображение) image = image.resize((28, 28)).convert('L') # уменьшение размера n преобразование в оттенки серого return np.array(image) # 2D-массив для отображения Защиту preprocess_for_model(я, изображение): изображение = Image.fromarray(изображение) image = image.resize((28, 28)).convert('L') # уменьшение размера n преобразование в оттенки серого изображение = np.array(изображение) image = image.reshape(1, 28, 28, 1) # Изменение формы модели изображение = изображение/255.0 вернуть изображение сброс защиты (я, событие): self.old_x = Нет self.old_y = Нет #берёт нарисованное изображение, пропускает его через mnist-модель и выводит то, что, по мнению модели, представляет собой буква. защита идентификации_буквы (сам): # Получить рисунок холста в виде изображения self.canvas.postscript(file='temp_canvas.ps', colormode='color') холст_изображение = Image.open('temp_canvas.ps') холст_изображение = холст_изображение.конвертировать('RGB') # конвертируем изображение в массив numpy холст_массив = np.array(canvas_image) image_for_display = self.preprocess_for_display(canvas_array) # отображаем предварительно обработанное изображение для отладки #DEBUGGING ТОЛЬКО ДЛЯ ИСПОЛЬЗОВАНИЯ self.display_preprocessed_image(image_for_display) # prreprocess изображение для модели image_for_model = self.preprocess_for_model(canvas_array) # Вызов функции прогнозирования из model.py цифра = предсказать_цифру (изображение_для_модели) # Распечатайте и покажите результат прогноза print(f"Прогнозируемая цифра: {цифра}") self.show_popup(f"Прогнозируемая цифра: {digit}") если os.path.exists('temp_canvas.ps'): os.remove('temp_canvas.ps') время.сон(1) self.root.destroy() #сброс области рисования защита reset_canvas (сам): self.canvas.delete("все") # Создаем экземпляр приложения приложение = ЦифровойДекодер()
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Я получаю Timeouterror: [Winerror 10060], когда я анализирую свой школьный сайт
Anonymous » » в форуме Python - 0 Ответы
- 4 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Я получаю Timeouterror: [Winerror 10060], когда я анализирую свой школьный сайт
Anonymous » » в форуме Python - 0 Ответы
- 2 Просмотры
-
Последнее сообщение Anonymous
-