简体   繁体   English

与 python 中的相同脚本不同,深度学习模型在可执行文件程序中给出不准确的结果,从而打乱了预测

[英]Deep Learning Model gives inaccurate results in executable file program unlike the same script in python, messing up predictions

I made my first deep learning model for cancer detection using infrared image recognition through the Sequential DL model.我通过 Sequential DL 模型使用红外图像识别制作了我的第一个癌症检测深度学习模型。 I am able to run the following code through a GUI python script with the desired accuracy and results through the following code well enough when run in terminal/command.在终端/命令中运行时,我能够通过 GUI python 脚本以所需的准确性运行以下代码,并通过以下代码获得足够好的结果。

from tkinter import *          # Tkinter is the Python interface to the Tk GUI(Graphical User Interface) toolkit - all libraries imported
from tkinter import filedialog #File dialog module will help open, save files or directories
import tkinter as tk         #Assigning alias to tkinter
import numpy as np                    #Importing Numpy as np alias
import pydot                                               #importing pydot for Graphviz
import graphviz                                            #Importing graphviz for graphing
import matplotlib.pyplot as plt                            #Importing matplotlib - Python Plot for graphing
import h5py                                                #For Data processing 
import tensorflow as tf                                    #Importing tensorflow model as tf alias
from keras.models import Sequential                        #Importing the Sequential model to train algorithm
from keras.layers import Dense                             #Importing Dense layer 
from keras.layers import Dropout                           #Importing Dropout layer for reducing associations
from keras.layers import Flatten                           #Importing Flatten Layer to compress multidimensional data to 1-D
from keras.layers.convolutional import Conv2D              
from keras.layers.convolutional import MaxPooling2D        #Importing 2D Convolutional Layers for training of algorithm 
from keras.utils import np_utils                            #Import NumPy related-utilities from keras utils
from keras import backend as K                              #Impoting Keras Backend API 
from keras.models import load_model                         #load_model can load a model for use which is saved by model.save
from keras.utils.vis_utils import plot_model                #Converts keras model to dot format and saves to a file.
import cv2                                                  #OpenCV library to visualise and extract Image data
import os                                                   #OS Module - to interact with underlying Operating System
import sys
import glob, random
from random import randint
from sklearn.model_selection import train_test_split        #Split arrays or matrices into random train and test subsets.
K.image_data_format()                                       #Returns the default image data format convention. - how backend treats image information
sys.setrecursionlimit(10**6)
def resource_path(relative_path):                               #Installs relative path over hard-coded path for EXE file to work
    """ Get absolute path to resource, works for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

model=1
path=r'C:\Users\Nitin_Sethi-PC\Desktop\PS-I\FINAL\Images'

#Creating window of standard size and giving Name to window
window = tk.Tk()
window.title("Graphical Interface for Cancer Detection Model")  
wd = str(window.winfo_screenwidth()) + "x" + str(window.winfo_screenheight())
window.geometry(wd)

#Defining number of epochs, batchsize, folder path(to be made relative) and arrays for images and labels.
numepochs = 125
batchsize = 4
folder_path = r'C:\\Users\\Nitin_Sethi-PC\\Desktop\\PS-I\\FINAL\\Images'
images = []
labels = []
class_label = 0

#DEFINING FUNCTION FOR LOADING IMAGES FROM DATA/FOLDER - as done in earlier codes
def load_images_from_folder(folder,class_label):
    for filename in os.listdir(folder):                   #Until image is listed in folder
        img = cv2.imread(os.path.join(folder, filename))              #Read image using cv2.imread to read image from path
        if img is not None:
            img = cv2.resize(img,(140,92))                                 #Resizing img to specific size 140x92
            img = img.reshape(92,140,3)#Returns an array containing the same data with a new shape.
            #img = np.flip(img, axis=-1)                                    #Matplotlib and OpenCV load images inversely (RGB and BGR)
            #img_smt = cv2.fastNlMeansDenoisingColored(img,None,10,10,7,21) #NOISE REMOVAL INSTALLED - (image, ,FilterStrength,,templateWindowSize,searchWindowSize)        
            images.append(img)                                             #Resized image added to images array
            labels.append(class_label)                                     #Class_label appended to labels array
    class_label = class_label+1                                            #class_label value incremented for next image
    return class_label


# Defining FUNCTION For Larger(main) model, needed variables
def larger_model():
    # create model
    model = Sequential()  
    #1st Convolutional Layer(32 Filters) + MaxPooling2D
    model.add(Conv2D(32, (3, 3), padding="same",input_shape=(92,140,3), activation='relu'))  #(3,3) represents kernel size---> Always odd tuple
    #model.add(Conv2D(32, (3, 3), activation='relu',padding = 'same'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    #2nd Convolutional Layer(32 Filters) + MaxPooling2D
    model.add(Conv2D(32, (3, 3), activation='relu',padding = 'same'))
    #model.add(Conv2D(64, (3, 3), activation='relu',padding = 'same'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    #3rd Convolutional Layer(64 Filters) + MaxPooling2D
    model.add(Conv2D(64, (3, 3), activation='relu',padding = 'same'))
    #model.add(Conv2D(128, (3, 3), activation='relu',padding = 'same'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    #Dropping Associations and Flattening to 1 Dimesion
    model.add(Dropout(0.5))
    model.add(Flatten())
    model.add(Dropout(0.5))
    model.add(Dense(64, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(64, activation='relu'))
    model.add(Dropout(0.5))
    #model.add(Dense(50, activation='relu'))
    model.add(Dropout(0.5))
    
    #Output Layer   
    model.add(Dense(num_classes, activation='softmax'))                              
        
    # Compile model
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

#Creating Class Labels and Loading Images From Benign, Malignant and Normal Folders
class_label = load_images_from_folder(folder_path+'\\Benign',class_label)
class_label = load_images_from_folder(folder_path+'\\Malignant',class_label)
class_label = load_images_from_folder(folder_path+'\\Normal',class_label)

#Filling out Data and Labels array - asarray converts given input into array
Data = np.asarray(images)
Labels = np.asarray(labels)

#Creating variables for testing, training and splitting dataset as 20% to 80%
X_train,X_test,Y_train,Y_test=train_test_split(Data,Labels,test_size=0.2,random_state=2)

#X_train = tf.expand_dims(X_train, axis=-1) 

# Normalizing Pixel Inputs from 0-255 to 0-1
X_train = X_train / 255
X_test = X_test / 255
# one hot encode outputs - Converting Categorical data into variables for Deep Learning model
Y_train = np_utils.to_categorical(Y_train)    #to_categorical Converts a class vector (integers) to binary class matrix.
Y_test = np_utils.to_categorical(Y_test)
num_classes = Y_test.shape[1]                 #Finds number of classes in Y_tests

#Printing sizes of various training and testing variables 
tr="Training Data shape:"+"\n"
tr=tr+"Testing Data shape:"+"\n"
tr=tr+str(X_test.shape)+"\n"
tr=tr+"Training Label shape:"+"\n"
tr=tr+str(Y_train.shape)+"\n"
tr=tr+"Testing Label shape:"+"\n"
tr=tr+str(Y_test.shape)+"\n"


#FUNCTION FOR TRAINING THE MODEL MADE above
def training(X_train, Y_train,X_test, Y_test,tr):
    global hist                                      #Declaring Global Variable hist
    # Build the model
    model = larger_model()                           #Building model as larger_model made above
    # Fit the model - fit() => trains the model for a fixed number of epochs and set batchsize on X_train, Y_train and tests on X_test, Y_test
    hist  = model.fit(X_train, Y_train, validation_data = (X_test, Y_test), epochs = numepochs, batch_size = batchsize)
    #Giving Model Summary/Characteristics
    model.summary()
    # Ultimate Evaluation of the model - evaluate()- returns loss and metric value for the model in test mode. 
    scores = model.evaluate(X_test, Y_test, verbose=1,batch_size=batchsize)            #Verbose - allows us to see progress of each epoch
    model.save('BreastCancerDetector.h5')                                              #Saves the model made for use later
    print("Deep Neural Net Accuracy: %.2f%%" % (scores[1]*100)) 
    
    #Creating text field for printing Layer Architecture 
    greetings_disp = tk.Text(master = window, height=2, width=120, fg="midnight blue", font = ('Helvetica',14))  #Defining window, with height,width and foreground color
    greetings_disp.grid(column=0,row=3)                       #Positioning in Grid in the GUI Window
    greetings_disp2 = tk.Text(master = window, height=10, width=120, fg="midnight blue",font = ('Helvetica',14))  #Defining window, with height,width and foreground color
    greetings_disp2.grid(column=0,row=4)
    ly= ""                                                    #Layer ly string variable created - 
    
    #Printing Layer Architecture with training and accuracy results
    for layer in model.layers:
        ly=ly+str(layer.name)+"       "  + "                layer input: \n"+str(layer.input)+"\n\n"          #str(layer.inbound_nodes)+str(layer.outbound_nodes)      "            <<--inputs-->> \n\n" + tr+
    accuracy = ((scores[1]) *100)
    accuracyf = "{:.2f}".format(accuracy)
    greetings_disp.insert(tk.END ,"The Neural Network is trained with Accuracy  of: "+ accuracyf+ '%')
    greetings_disp2.insert(tk.END, "<<--DEEP LEARNING LAYER ARCHITECTURE-->> \n\n" +ly+"\n")
    return model

#Defining varibles for plotting and actually Plotting in Matplotlib 
def graphh():

    # Visualizing losses and accuracy with number of epochs
    train_loss = hist.history['loss']                           #Training Loss
    val_loss   = hist.history['val_loss']                       #Validation Losses
    train_acc  = hist.history['accuracy']                       #Training Accuracy
    val_acc    = hist.history['val_accuracy']                   #Validation Accuracy
    xc         = range(numepochs)                               #Visualises for entire range of numepochs
 
    #plt.figure(1) - Training Loss and Validation Loss Trends - Loss Vs. Number of Epochs
    plt.figure(1, figsize = (10,5))
    plt.subplot(121)
    plt.plot(xc,train_loss)
    plt.plot(xc,val_loss)
    plt.xlabel('Number of Epochs')
    plt.ylabel('Loss')
    plt.title('Training Vs. Validation Loss')
    plt.grid(True)
    plt.legend(['Training','Validation'])
    plt.style.use(['classic'])

    #Training Accuracy and Validation Accuracy Trends - Accuracy Vs. Number of Epochs
    #plt.figure(2,figsize=(7,5))
    plt.subplot(122)
    plt.plot(xc,train_acc)
    plt.plot(xc,val_acc)
    plt.xlabel('Number of Epochs')
    plt.ylabel('Accuracy')
    plt.title('Training Vs. Validation Accuracy')
    plt.grid(True)

    plt.legend(['Training','Validation'],loc=4)
    plt.style.use(['classic'])
    plt.show()

#Testing a sample test image from the dataset   
def test_test(model):
    test_image = X_test[0:1]
    pa = model.predict(test_image)        #Predicting output based on test_image through model = output captured by pa
    classes_x = np.argmax(pa,axis=1)    #Returns the indices of the maximum values along an axis=1 Columns(Categories) = Maximum of 3 taken
    if(classes_x ==[0]):
        accuracy_b = ((pa[0][0]*100))
        accuracy_bf = "{:.2f}".format(accuracy_b)
        s="BENIGN with Accuracy: " + accuracy_bf + "%\n"
    elif(classes_x == [1]):
        accuracy_m = ((pa[0][1]*100))
        accuracy_mf = "{:.2f}".format(accuracy_m)
        s="MALIGNANT with Accuracy: "+ accuracy_mf + "%\n"
    elif(classes_x ==[2]):
        accuracy_n = ((pa[0][2]*100))
        accuracy_nf = "{:.2f}".format(accuracy_n)
        s="NORMAL with Accuracy: "+ accuracy_nf + "%\n"
    return s

#Testing Image uploaded by user through OpenCV
def test_random(model,path): 
    test_image = cv2.imread(path)                    #Reading image using OpenCV through imread function on path defined
    test_image= cv2.resize(test_image,(140,92))      #Resizing to desired dimensions
    test_image = test_image.reshape(92,140,3)        #Reshaping the desired dimensions - changing array structure
    test_image = np.array(test_image)                #Converting test image to numpy array for model input
    test_image = test_image.astype('float32')        #Casting to float values
    test_image /= 255                                #Normalizing to 1 from 255
    test_image= np.expand_dims(test_image, axis=0)   
    pa=model.predict(test_image)             
    classes_x = np.argmax(pa,axis=1)
    if(classes_x ==[0]):
        accuracy_b = ((pa[0][0]*100))
        accuracy_bf = "{:.2f}".format(accuracy_b)
        s="BENIGN with Accuracy: " + accuracy_bf + "%\n"
    elif(classes_x == [1]):
        accuracy_m = ((pa[0][1]*100))
        accuracy_mf = "{:.2f}".format(accuracy_m)
        s="MALIGNANT with Accuracy: "+ accuracy_mf + "%\n"
    elif(classes_x ==[2]):
        accuracy_n = ((pa[0][2]*100))
        accuracy_nf = "{:.2f}".format(accuracy_n)
        s="NORMAL with Accuracy: "+ accuracy_nf + "%\n"
    return s

#Function to Test Image from test_test functions
def b_test_test():
    greetings = test_test(model)
    #create text field and alloting position below relavant button
    greetings_disp = tk.Text(master = window,height = 1,width = 45 ,fg = "midnight blue", font = ('Helvetica',14))
    greetings_disp.grid(column = 0,row = 6)
    greetings_disp.insert(tk.END , greetings)

#Function to Show Random Image as selected by User - to view Processed image indpendently
def b_random_test_show():
    global path1
    path  = filedialog.askopenfilename(filetypes=(("JPG", ".jpg"), ("All files", "*.*")))
    path1 = path
    img   = cv2.imread(path1)                             #Reading image using OpenCV from path1 = path
    img   = np.flip(img, axis=-1) 
    plt.imshow(img)
    plt.show()

#Function for calling Model to Test Random Image as provided by User
def b_random_test():
    path = filedialog.askopenfilename(filetypes=(("JPG", ".jpg"), ("All files", "*.*")))
    greetings=test_random(model,path)
    #create text field
    greetings_disp =tk.Text(master=window,height=1,width=45 ,fg="midnight blue", font = ('Helvetica',14))
    greetings_disp.grid(column=0,row=12)
    greetings_disp.insert(tk.END , greetings)      #Shows output of model through test_random(model,path) function
    img=cv2.imread(path)
    plt.imshow(img)
    plt.show()

#Function for Training model on Training and Testing Data
def b_training():
    global model
    model = training(X_train, Y_train,X_test, Y_test,tr)

#Creating Heading Text in GUI Window
labelfont=('Proxima Nova', 39, 'bold')
label1 = tk.Label(text="Cancer Detection by Image Recognition using Deep Learning", anchor='n', font=labelfont , fg="midnight blue" , bg="mint cream", borderwidth = 5)
label1.grid(column=0,row=0)

#Create Instructions
labelfont2 = ('Proxima Nova', 16,'bold')
label2 = tk.Label(text='Please click \'Initiate Training\' to begin. Wait for the training to complete, the window might become unresponsive.', anchor ='w', font=labelfont2,fg="midnight blue" , bg="powder blue", bd=1, justify='left')
label2.grid(column=0, row=1)

#Creating Buttons under GUI and alloting space using the Grid System
buttonfont = ('Proxima Nova','13','bold')

button1 = tk.Button(border=2, text = "Initiate Training", command = b_training, bg = "powder blue", padx=66.8,pady=10) #17
button1.grid(column=0,row=2)
button1['font'] = buttonfont

button2 = tk.Button(text = "Test an Image from Dataset", command = b_test_test , bg = "powder blue",padx=20.3,pady=10) #26
button2.grid(column=0,row=5)
button2['font'] = buttonfont

button3 = tk.Button(text = "Display an Image from Dataset", command = b_random_test_show , bg = "powder blue", padx=9,pady=10) #28
button3.grid(column=0,row=8)
button3['font'] = buttonfont

button4 = tk.Button(text = "Upload Image for Testing", command = b_random_test, bg = "powder blue", padx=30,pady=10) #24
button4.grid(column=0,row=10)
button4['font'] = buttonfont

button5 = tk.Button(text = "See Loss and Accuracy plots", command = graphh, bg = "powder blue", padx=14,pady=10) #27
button5.grid(column=0,row=15)
button5['font'] = buttonfont

window.mainloop()

The above code brings up a GUI window with 5 buttons for the functions as seen above.上面的代码为上面看到的功能打开了一个带有 5 个按钮的 GUI 窗口。 I converted the above python script to an executable file through PyInstaller in an Virtual Environment.我在虚拟环境中通过 PyInstaller 将上述 python 脚本转换为可执行文件。 After multiple recursion errors(Recursion observed in opening binary cv2 extensions), caused by OpenCV, I installed an older version 4.5.5.在由 OpenCV 引起的多个递归错误(打开二进制 cv2 扩展时观察到递归)后,我安装了旧版本 4.5.5。 which removed the recursion error and made the executable file as desired.它消除了递归错误并根据需要制作了可执行文件。

However, the functionality of classification of the cancer into benign, malignant and normal types was reduced considerably, as now the trained model classified almost all images as Benign with >99% accuracy.然而,将癌症分类为良性、恶性和正常类型的功能大大降低,因为现在经过训练的模型将几乎所有图像分类为良性,准确率 > 99%。 The same image from the two models is classified differently as shown here: By the EXE Model and By the GUIPython Script来自两个模型的相同图像的分类方式不同,如下所示:按 EXE 模型按 GUIPython 脚本

I think possible errors may be occurring due to the hard-coded paths for the Image folders in the codes.我认为由于代码中图像文件夹的硬编码路径,可能会发生错误。 While I have tried using resource_path function to find a relative path through '''sys._MEIPASS''' it might not be sufficient for making other paths relative as desired for optimum functioning of the .exe application.虽然我尝试使用 resource_path 函数通过 '''sys._MEIPASS''' 找到相对路径,但它可能不足以根据 .exe 应用程序的最佳功能使其他路径相对。

Another issue can be that on switching to an earlier version of OpenCV, the recursion limit remained the same and did not allow multiple images in the dataset to be read, leading to a reduction in accuracy.另一个问题可能是,在切换到早期版本的 OpenCV 时,递归限制保持不变,并且不允许读取数据集中的多个图像,从而导致准确性降低。

Please help as I am a novice to coding and deep learning, and am running into this issue without any clue on how to correct this.请帮助,因为我是编码和深度学习的新手,并且在没有任何关于如何纠正这个问题的线索的情况下遇到这个问题。

Solved the issue.解决了这个问题。 Apparently using an earlier version of OpenCV to remove the recursion error leads to issues in image reading and inputting for the deep learning model involved.显然,使用早期版本的 OpenCV 来消除递归错误会导致所涉及的深度学习模型的图像读取和输入出现问题。 Increasing the recursion limit by using the '''--add data''' in pyinstaller command for .exe conversion increases recursion limit to 5000 from 1000, allowing the OpenCV function to work as desired and produce the results as needed.通过在 pyinstaller 命令中使用 '''--add data''' 来增加递归限制以进行 .exe 转换将递归限制从 1000 增加到 5000,从而允许 OpenCV 函数按需要工作并根据需要生成结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 keras 模型上的迁移学习总是给出相同的预测 - Transfer learning on keras model always gives same predictions 由于输入层不兼容,深度学习模型没有给出预测 - Deep learning model not giving predictions as input layer is incompatible 提高机器学习的准确性 Python 中的 model 预测 - Improving accuracy of machine learning model predictions in Python 当我运行下面的程序时,在带有 ROCm 的 AMD GPU 上使用 Tensorflow 和 Keras 使用 Python 进行深度学习会出错 - Deep Learning with Python using Tensorflow and Keras on AMD GPU with ROCm gives errors when I run the program below 在 pytorch 中加速训练深度学习 model - Speed up training deep learning model in pytorch Keras 深度学习模型在使用完全相同的超参数重新运行时返回不一致的结果 - Keras deep learning model returning inconsistent results when rerun with exact same hyperparameters Python中的MXNet分类总是给出相同的预测 - MXNet classification in Python always gives the same predictions Theano的Python深度学习mnist的基本程序 - Python deep learning with theano the basic program of mnist 加载深度学习模型时的问题(Python) - problems when loading a deep learning model(python) 将模型保存为JSON后,使用Keras进行深度学习的模型无法给我正确的预测 - Deep learning model with Keras don't give me correct predictions after saving the model in JSON
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM