Я обучил модель машинного обучения с помощью TensorFlow/Keras для классификации арабских символов, и она достигает точности около 91 % в наборе тестовых данных. Однако когда я подключаю эту модель к своему приложению с графическим интерфейсом Tkinter, она последовательно прогнозирует один и тот же класс для всех входных данных, независимо от предоставленного изображения.
Что я пробовал:
1- Предварительная обработка изображений: я убедился, что изображения предварительно обработаны так же, как и обучающие изображения (изменение размера и нормализация).
2- Оценка модели: я подтвердил, что модель хорошо работает на набор тестов вне графического интерфейса контекст.
3- Отладка: я распечатал прогнозы, чтобы увидеть необработанные выходные данные, прежде чем брать argmax, и кажется, что выходные данные смещены в сторону одного класса.
Так почему же моя модель может последовательно предсказывать один и тот же класс при использовании в графическом интерфейсе?
вот мой код:
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
import numpy as np
from keras.models import load_model
import tensorflow as tf
from tensorflow.keras.applications import ConvNeXtXLarge # Use the correct ConvNeXt model
import pyglet
from tkinter import font
import cv2
# Load the font using pyglet
pyglet.font.add_file("C:\\Users\\HP\\OneDrive\\سطح المكتب\\Project Grad\\Rakkas-Regular.ttf")
# Load the trained model (ensure path is correct)
model = load_model("C:\\Users\\HP\\Downloads\\my_Model_ConvNeXtBase.keras")
# Dictionary to label all Arabic character classes (update these with correct mappings)
classes = {
0: 'أ', 1: 'ب', 2: 'ت', 3: 'ث', 4: 'ج', 5: 'ح', 6: 'خ', 7: 'د',
8: 'ذ', 9: 'ر', 10: 'ز', 11: 'س', 12: 'ش', 13: 'ص', 14: 'ض', 15: 'ط',
16: 'ظ', 17: 'ع', 18: 'غ', 19: 'ف', 20: 'ق', 21: 'ك', 22: 'ل', 23: 'م',
24: 'ن', 25: 'هـ', 26: 'و', 27: 'ي', 28: 'ء'
}
font_name = "Rakkas" # Adjust this if necessary based on the available fonts
# Create the main window
root = tk.Tk()
root.title("Harf")
root.geometry("1600x900") # Set window size
# Store image references to prevent garbage collection
background_photo = None
new_background_photo = None
uploaded_image = None
thumbnail_photo = None
current_image_path = None # Initialize the variable to store image path
# Function to change pages (Page 1)
def show_page_1():
global background_photo
# Clear current content
for widget in root.winfo_children():
widget.destroy()
# Set background for page 1 (Main page)
background_image_path = 'C:\\Users\\HP\\Downloads\\Desktop - 5 (5).png' # Main page background
background_image = Image.open(background_image_path)
background_image = background_image.resize((1600, 900), Image.LANCZOS)
background_photo = ImageTk.PhotoImage(background_image)
background_label = tk.Label(root, image=background_photo)
background_label.place(relwidth=1, relheight=1)
font_style_mid = (font_name, 25) # Adjust font size to 25 for smaller buttons
# Add button to navigate to the second page
start_button = tk.Button(root, text="أبدا", font=font_style_mid, command=show_page_2)
start_button.place(relx=0.5, rely=0.5, anchor="center") # Center the button
# Function to show page 2 (Second page)
def show_page_2():
global new_background_photo, uploaded_image, thumbnail_photo, current_image_path
# Clear current content
for widget in root.winfo_children():
widget.destroy()
# Set background for page 2 (Second page)
new_background_image_path = 'C:\\Users\\HP\\Downloads\\Desktop - 4.png' # Second page background
new_background_image = Image.open(new_background_image_path)
new_background_image = new_background_image.resize((1600, 900), Image.LANCZOS)
new_background_photo = ImageTk.PhotoImage(new_background_image)
new_background_label = tk.Label(root, image=new_background_photo)
new_background_label.place(relwidth=1, relheight=1)
# Function to upload image
def upload_image():
global current_image_path # Declare the variable as global to update it in the global scope
try:
# Ask the user to select an image file
file_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.jpg;*.jpeg;*.png")])
if not file_path:
return # Exit if no file is selected
# Open and resize the image to 150x150 (you can display a larger image, but process it in 32x32)
img = Image.open(file_path)
img = img.resize((150, 150), Image.LANCZOS)
uploaded_image = ImageTk.PhotoImage(img)
# Update the thumbnail display
thumbnail_label.config(image=uploaded_image)
thumbnail_label.image = uploaded_image # Keep reference to prevent garbage collection
# Store the file path for future use in classification
current_image_path = file_path # Update the global variable
print(f"Image uploaded: {current_image_path}") # Debug print to ensure the path is correct
except Exception as e:
print(f"Error uploading image: {e}")
# Function to preprocess and predict the uploaded image
def preprocess_image(img, resize_dim=(32, 32)):
"""
Preprocess the input image for ConvNeXt model.
Resizes, normalizes, and adds batch dimension.
"""
# Ensure the image is in RGB mode
if isinstance(img, Image.Image):
img = img.convert("RGB") # Convert to RGB if not already
# Resize the image to the same size as used in training
img = img.resize(resize_dim) # Resize to (32, 32)
# Convert image to numpy array
img_array = np.array(img)
# If the image is grayscale, convert to RGB (3 channels)
if len(img_array.shape) == 2:
img_array = np.stack([img_array] * 3, axis=-1) # Convert grayscale to RGB (3 channels)
# Normalize pixel values using ConvNeXt's specific preprocessing
img_array = tf.keras.applications.ConvNeXtXLarge.preprocess_input(img_array)
# Add batch dimension (model expects (batch_size, height, width, channels))
img_array = np.expand_dims(img_array, axis=0) # Shape should be (1, 32, 32, 3)
return img_array
# Function to predict the uploaded image
def predict_image():
try:
# Ensure current_image_path is not None or empty
if not current_image_path:
prediction_label.config(text="No image uploaded!")
return
# Open the image for prediction
img = Image.open(current_image_path)
# Preprocess the image (resize, normalize, etc.)
preprocessed_img = preprocess_image(img)
# Predict using the model
prediction = model.predict(preprocessed_img)
# Find the predicted class
predicted_class = np.argmax(prediction, axis=1)[0] # Get the predicted class label
# Get the predicted label from the classes dictionary
predicted_label = classes[predicted_class]
# Update the label with the predicted class
prediction_label.config(text=f"Predicted Label: {predicted_label}")
print(f"Prediction made: {predicted_label}") # Debug print for model prediction
except Exception as e:
# Handle any errors that occur during prediction
prediction_label.config(text=f"Error predicting image: {str(e)}")
print(f"Error predicting image: {e}")
# Use a smaller font size for the buttons
font_style_small = (font_name, 18) # Adjust font size to 25 for smaller buttons
# Add Upload and Classify buttons side by side (in a row)
upload_button = tk.Button(root, text="أرفق الصورة", font=font_style_small, command=upload_image, padx=5, pady=5)
upload_button.configure(background='#364156', foreground='white', font=font_style_small) # Apply the smaller font
upload_button.place(relx=0.4, rely=0.7, anchor="center") # Positioned on the left side
classify_button = tk.Button(root, text="صنف", font=font_style_small, command=predict_image, padx=5, pady=5)
classify_button.configure(background='#364156', foreground='white', font=font_style_small) # Apply the smaller font
classify_button.place(relx=0.6, rely=0.7, anchor="center") # Positioned on the right side
# Add the thumbnail image display
thumbnail_label = tk.Label(root, font=(font_name, 20))
thumbnail_label.place(relx=0.5, rely=0.5, anchor="center") # Moved down by 50
# Add the label to display the predicted result
prediction_label = tk.Label(root, font=(font_name, 20))
prediction_label.place(relx=0.5, rely=0.8, anchor="center") # Moved down by 50
# Add a back button to return to page 1 (if desired)
back_button = tk.Button(root, text=" ⏎ ", font=(font_name, 70), command=show_page_1, background="#FDF7E5", borderwidth=0)
back_button.place(x=40, y=150) # Place the back button at the top-left corner
# Show the first page when the app starts
show_page_1()
# Start the main event loop
root.mainloop()
Подробнее здесь: https://stackoverflow.com/questions/791 ... ccuracy-91
Модель предсказывает тот же класс в графическом интерфейсе Tkinter, несмотря на высокую точность теста (91%) ⇐ Python
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Рассчитайте точность, полноту, точность и сбалансированную точность из матрицы путаницы.
Anonymous » » в форуме Python - 0 Ответы
- 37 Просмотры
-
Последнее сообщение Anonymous
-