From a75340f0e1d8898975a511561b3325b9e8e7872e Mon Sep 17 00:00:00 2001 From: Rohaan Nadeem Date: Mon, 18 Dec 2023 22:48:49 -0500 Subject: [PATCH] designed gui to train the model --- README.md | 6 +- gui/gui.py | 188 ++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 159 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index f2b81f2e..2b5684fc 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ Which will run EXAMM with 9 threads or 9 processes, respectively. Note that EXAM The aviation data can be run similarly, however it the data should be normalized first (which can be done with the *--normalize* command line parameter), e.g.: ``` -./multithreaded/examm_mt --number_threads 9 --training_filenames ../datasets/2018_ngafid/flight_[0-7].csv --test_filenames ../datasets/2018_ngafid/flight_[8-9].csv --time_offset 1 --input_parameter_names "AltAGL" "E1 CHT1" "E1 CHT2" "E1 CHT3" "E1 CHT4" "E1 EGT1" "E1 EGT2" "E1 EGT3" "E1 EGT4" "E1 OilP" "E1 OilT" "E1 RPM" "FQtyL" "FQtyR" "GndSpd" "IAS" "LatAc" "NormAc" "OAT" "Pitch" "Roll" "TAS" "volt1" "volt2" "VSpd" "VSpdG" --output_parameter_names Pitch --number_islands 10 --population_size 10 --max_genomes 2000 --bp_iterations 10 --output_directory "./test_output" --possible_node_types simple UGRNN MGU GRU delta LSTM --normalize --std_message_level INFO --file_message_level INFO +./multithreaded/examm_mt --number_threads 9 --training_filenames ../datasets/2018_ngafid/flight_[0-7].csv --test_filenames ../datasets/2018_ngafid/flight_[8-9].csv --time_offset 1 --input_parameter_names "AltAGL" "E1 CHT1" "E1 CHT2" "E1 CHT3" "E1 CHT4" "E1 EGT1" "E1 EGT2" "E1 EGT3" "E1 EGT4" "E1 OilP" "E1 OilT" "E1 RPM" "FQtyL" "FQtyR" "GndSpd" "IAS" "LatAc" "NormAc" "OAT" "Pitch" "Roll" "TAS" "volt1" "volt2" "VSpd" "VSpdG" --output_parameter_names Pitch --number_islands 10 --population_size 10 --max_genomes 2000 --bp_iterations 10 --output_directory "./test_output" --possible_node_types simple UGRNN MGU GRU delta LSTM --normalize --std_message_level INFO --file_message_level INFO --island_size 10 ``` The *--time_offset* parameter specifies how many time steps in the future EXAMM should predict for the output parameter(s). The *--number_islands* is the number of islands of populations that EXAMM will use, and the *--population_size* parameter specifies how many individuals/genomes are in each island. The *--bp_iterations* specifies how many epochs/iterations backpropagation should be run for each generated RNN genome. @@ -157,14 +157,14 @@ So this will take 1000 images of each type from the training data and put them i You can then run EXACT in a similar manner to EXAMM, either using threads or MPI. For the threaded version: ``` -~/exact/build/ $ ./multithreaded/exact_mt --number_threads 9 --padding 2 --training_file ../datasets/mnist_train_50k.bin --validation_file ../datasets/mnist_validation_10k.bin --testing_file ../datasets/mnist_testing_data.bin --population_size 30 --max_epochs 5 --use_sfmp 1 --use_node_operations 1 --max_genomes 1000 --output_directory ./test_exact --search_name "test" --reset_edges 0 --images_resize 50000 +./multithreaded/examm_mt --number_threads 9 --training_filenames ../datasets/2018_ngafid/flight_[0-7].csv --test_filenames ../datasets/2018_ngafid/flight_[8-9].csv --time_offset 1 --input_parameter_names "AltAGL" "E1 CHT1" "E1 CHT2" "E1 CHT3" "E1 CHT4" "E1 EGT1" "E1 EGT2" "E1 EGT3" "E1 EGT4" "E1 OilP" "E1 OilT" "E1 RPM" "FQtyL" "FQtyR" "GndSpd" "IAS" "LatAc" "NormAc" "OAT" "Pitch" "Roll" "TAS" "volt1" "volt2" "VSpd" "VSpdG" --output_parameter_names Pitch --number_islands 10 --population_size 10 --max_genomes 2000 --bp_iterations 10 --output_directory "./test_output" --possible_node_types simple UGRNN MGU GRU delta LSTM --normalize --std_message_level INFO --file_message_level INFO --island_size 10 ``` And for the MPI version: ``` -~/exact/build/ $ mpirun -np 9 ./mpi/exact_mpi --padding 2 --training_file ../datasets/mnist_train_50k.bin --validation_file ../datasets/mnist_validation_10k.bin --testing_file ../datasets/mnist_testing_data.bin --population_size 30 --max_epochs 5 --use_sfmp 1 --use_node_operations 1 --max_genomes 1000 --output_directory ./test_exact --search_name "test" --reset_edges 0 --images_resize 50000 +~/exact/build/ $ mpirun -np 9 ./mpi/exact_mpi --padding 2 --training_file ../datasets/mnist_train_50k.bin --validation_file ../datasets/mnist_validation_10k.bin --testing_file ../datasets/mnist_testing_data.bin --population_size 30 --max_epochs 5 --use_sfmp 1 --use_node_operations 1 --max_genomes 1000 --output_directory ./test_exact --search_name "test" --reset_edges 0 --images_resize 50000 ``` Which will run EXACT with 9 threads or processes, respectively. The *--use_sfmp* argument turns on or off scaled fractional max pooling (which allows for pooling operations between feature maps of any size), the *--use_node_operations* argument turns on or off node level mutations (see the EXACT and EXAMM papers), the *--reset_edges* parameter turns on or off Lamarckian weight evolution (turning it on will evolve and train networks faster) and the *--images_resize* parameter allows EXACT to train CNNs on a subset of the training data to speed the evolution process (e.g., --images_resize 5000 would train each CNN on a different subset of 5k images from the training data, as opposed to the full 50k). diff --git a/gui/gui.py b/gui/gui.py index b943df56..f31ce0c2 100644 --- a/gui/gui.py +++ b/gui/gui.py @@ -1,6 +1,8 @@ import tkinter as tk from tkinter import filedialog, messagebox import pandas as pd +from tkinter import IntVar, Checkbutton + class CSVFileSelector(tk.Tk): def __init__(self): @@ -17,46 +19,144 @@ def __init__(self): self.train_label.grid(row=0, column=0, padx=10, pady=10) self.train_entry_var = tk.StringVar() - self.train_entry = tk.Entry(self, textvariable=self.train_entry_var, state="disabled", width=50) + self.train_entry = tk.Entry( + self, textvariable=self.train_entry_var, state="disabled", width=50 + ) self.train_entry.grid(row=0, column=1, padx=10, pady=10) - self.train_browse_button = tk.Button(self, text="Browse", command=self.browse_train_file) - self.train_browse_button.grid(row=0, column=2, padx=10, pady=10) + self.train_browse_button = tk.Button( + self, text="Browse", command=self.browse_train_file + ) + self.train_browse_button.grid(row=0, column=5, padx=10, pady=10) self.test_label = tk.Label(self, text="Select Test CSV:") self.test_label.grid(row=1, column=0, padx=10, pady=10) self.test_entry_var = tk.StringVar() - self.test_entry = tk.Entry(self, textvariable=self.test_entry_var, state="disabled", width=50) + self.test_entry = tk.Entry( + self, textvariable=self.test_entry_var, state="disabled", width=50 + ) self.test_entry.grid(row=1, column=1, padx=10, pady=10) - self.test_browse_button = tk.Button(self, text="Browse", command=self.browse_test_file) - self.test_browse_button.grid(row=1, column=2, padx=10, pady=10) - - self.column_listbox = tk.Listbox(self, selectmode=tk.MULTIPLE, exportselection=0, height=10) - + self.test_browse_button = tk.Button( + self, text="Browse", command=self.browse_test_file + ) + self.test_browse_button.grid(row=1, column=5, padx=10, pady=10) + + self.column_listbox = tk.Listbox( + self, selectmode=tk.MULTIPLE, exportselection=0, height=10 + ) + self.output_label = tk.Label(self, text="Select Output Directory:") self.output_label.grid(row=3, column=0, padx=10, pady=10) self.output_entry_var = tk.StringVar() - self.output_entry = tk.Entry(self, textvariable=self.output_entry_var, state="disabled", width=50) + self.output_entry = tk.Entry( + self, textvariable=self.output_entry_var, state="disabled", width=50 + ) self.output_entry.grid(row=3, column=1, padx=10, pady=10) - self.output_browse_button = tk.Button(self, text="Browse", command=self.browse_output_directory) - self.output_browse_button.grid(row=3, column=2, padx=10, pady=10) - - self.select_features_button = tk.Button(self, text="Select Features", command=self.select_features) - self.select_features_button.grid(row=4, column=0, columnspan=3, pady=10) + self.output_browse_button = tk.Button( + self, text="Browse", command=self.browse_output_directory + ) + self.output_browse_button.grid(row=3, column=5, padx=10, pady=10) + + self.number_threads_label = tk.Label(self, text="Number of Threads:") + self.number_threads_label.grid(row=4, column=0, padx=10, pady=5, sticky="e") + self.number_threads_var = tk.StringVar(value="9") + self.number_threads_entry = tk.Entry(self, textvariable=self.number_threads_var) + self.number_threads_entry.grid(row=4, column=1, padx=10, pady=5, sticky="w") + + self.node_types_label = tk.Label(self, text="Possible Node Types:") + self.node_types_label.grid(row=4, column=2, padx=10, pady=5) + self.node_types_options = ["simple", "UGRNN", "MGU", "GRU", "delta", "LSTM"] + self.node_type_vars = [tk.IntVar(value=1) for _ in self.node_types_options] + + for i, node_type in enumerate(self.node_types_options): + checkbox = tk.Checkbutton( + self, + text=node_type, + variable=self.node_type_vars[i], + onvalue=1, + offvalue=0, + ) + if i < 3: + checkbox.grid(row=4, column=i + 3, padx=5, pady=5) + else: + checkbox.grid(row=5, column=i, padx=5, pady=5) + + self.time_offset_label = tk.Label(self, text="Time Offset:") + self.time_offset_label.grid(row=5, column=0, padx=10, pady=5, sticky="e") + self.time_offset_var = tk.StringVar(value="1") + self.time_offset_entry = tk.Entry(self, textvariable=self.time_offset_var) + self.time_offset_entry.grid(row=5, column=1, padx=10, pady=5, sticky="w") + + self.number_islands_label = tk.Label(self, text="Number of Islands:") + self.number_islands_label.grid(row=6, column=0, padx=10, pady=5, sticky="e") + self.number_islands_var = tk.StringVar(value=10) + self.number_islands_entry = tk.Entry(self, textvariable=self.number_islands_var) + self.number_islands_entry.grid(row=6, column=1, padx=10, pady=5, sticky="w") + + self.std_message_level_label = tk.Label(self, text="Standard Message Level:") + self.std_message_level_label.grid(row=6, column=2, padx=10, pady=5) + + self.log_levels = ["NONE", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] + self.std_message_level_var = ( + tk.StringVar() + ) # Create StringVar without initial value + + std_message_level_menu = tk.OptionMenu( + self, self.std_message_level_var, *self.log_levels + ) + std_message_level_menu.grid(row=6, column=3, padx=5, pady=5) - self.initiate_run_button = tk.Button(self, text="Initiate Run", command=self.initiate_run, state="disabled") - self.initiate_run_button.grid(row=5, column=0, columnspan=3, pady=10) + # Set the default value after creating the OptionMenu + self.std_message_level_var.set("INFO") + + self.file_message_level_label = tk.Label(self, text="File Message Level:") + self.file_message_level_label.grid(row=7, column=2, padx=10, pady=5) + + self.file_message_level_var = tk.StringVar() + file_message_level_menu = tk.OptionMenu( + self, self.file_message_level_var, *self.log_levels + ) + file_message_level_menu.grid(row=7, column=3, padx=5, pady=5) + + self.file_message_level_var.set("NONE") + + self.size_islands_label = tk.Label(self, text="Island Size:") + self.size_islands_label.grid(row=7, column=0, padx=10, pady=5, sticky="e") + self.size_islands_var = tk.StringVar(value=10) + self.size_islands_entry = tk.Entry(self, textvariable=self.size_islands_var) + self.size_islands_entry.grid(row=7, column=1, padx=10, pady=5, sticky="w") + + self.max_genomes_label = tk.Label(self, text="Max Genomes:") + self.max_genomes_label.grid(row=8, column=0, padx=10, pady=5, sticky="e") + self.max_genomes_var = tk.StringVar(value=2000) + self.max_genomes_entry = tk.Entry(self, textvariable=self.max_genomes_var) + self.max_genomes_entry.grid(row=8, column=1, padx=10, pady=5, sticky="w") + + self.bp_iter_label = tk.Label(self, text="BP Iterations:") + self.bp_iter_label.grid(row=9, column=0, padx=10, pady=5, sticky="e") + self.bp_iter_var = tk.StringVar(value=10) + self.bp_iter_entry = tk.Entry(self, textvariable=self.bp_iter_var) + self.bp_iter_entry.grid(row=9, column=1, padx=10, pady=5, sticky="w") + + self.select_features_button = tk.Button( + self, text="Select Features", command=self.select_features + ) + self.select_features_button.grid(row=10, column=1, columnspan=3, pady=10) + + self.initiate_run_button = tk.Button( + self, text="Initiate Run", command=self.initiate_run, state="disabled" + ) + self.initiate_run_button.grid(row=11, column=1, columnspan=3, pady=10) def browse_train_file(self): file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")]) self.train_file_path = file_path self.train_entry_var.set(file_path) self.load_train_columns() - def browse_test_file(self): file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")]) @@ -72,17 +172,19 @@ def load_train_columns(self): for column in columns: self.column_listbox.insert(tk.END, column) except Exception as e: - messagebox.showerror("Error", f"Error loading columns: {e}") + messagebox.showerror("Error", f"Error loading columns: {e}") else: messagebox.showwarning("Warning", "Please select a training CSV file.") - def select_features(self): - self.features = [self.column_listbox.get(index) for index in range(self.column_listbox.size())] + self.features = [ + self.column_listbox.get(index) + for index in range(self.column_listbox.size()) + ] feature_selection_window = FeatureSelectionWindow(self, self.features) self.wait_window(feature_selection_window) - + def browse_output_directory(self): directory_path = filedialog.askdirectory() self.output_file_path = directory_path @@ -90,14 +192,25 @@ def browse_output_directory(self): def initiate_run(self): result_text = ( - f"Training File: {self.train_file_path}\n" - f"Test File: {self.test_file_path}\n" - f"Selected Features: {', '.join(self.features)}\n" - f"Target Variable: {self.target_variable}\n" - f"Output File: {self.output_file_path}" + f"./multithreaded/examm_mt " + f"--number_threads {self.number_threads_var.get()} \n" + f'--training_filenames "{self.train_file_path}" \n' + f'--test_filenames "{self.test_file_path}" \n' + f"--time_offset {self.time_offset_var.get()} \n" + f'--input_parameter_names {" ".join(self.features)} \n' + f"--output_parameter_names {self.target_variable} \n" + f"--number_islands {self.number_islands_var.get()} \n" + f"--island_size {self.size_islands_var.get()} \n" + f"--max_genomes {self.max_genomes_var.get()} \n" + f"--bp_iterations {self.bp_iter_var.get()} \n" + f'--output_directory "{self.output_file_path}" \n' + f'--possible_node_types {" ".join([node_type for node_type, var in zip(self.node_types_options, self.node_type_vars) if var.get()])} \n' + f"--std_message_level {self.std_message_level_var.get()} \n" + f"--file_message_level {self.file_message_level_var.get()} \n" ) messagebox.showinfo("Run Information", result_text) + class FeatureSelectionWindow(tk.Toplevel): def __init__(self, parent, features): super().__init__(parent) @@ -110,7 +223,9 @@ def __init__(self, parent, features): self.feature_label = tk.Label(self, text="Select Features:") self.feature_label.grid(row=0, column=0, padx=10, pady=10) - self.feature_listbox = tk.Listbox(self, selectmode=tk.MULTIPLE, exportselection=0, height=10) + self.feature_listbox = tk.Listbox( + self, selectmode=tk.MULTIPLE, exportselection=0, height=10 + ) for feature in self.features: self.feature_listbox.insert(tk.END, feature) self.feature_listbox.grid(row=0, column=1, padx=10, pady=10) @@ -118,12 +233,16 @@ def __init__(self, parent, features): self.target_label = tk.Label(self, text="Select Target Variable:") self.target_label.grid(row=1, column=0, padx=10, pady=10) - self.target_listbox = tk.Listbox(self, selectmode=tk.SINGLE, exportselection=0, height=5) + self.target_listbox = tk.Listbox( + self, selectmode=tk.SINGLE, exportselection=0, height=5 + ) for feature in self.features: self.target_listbox.insert(tk.END, feature) self.target_listbox.grid(row=1, column=1, padx=10, pady=10) - self.confirm_button = tk.Button(self, text="Confirm", command=self.confirm_selection) + self.confirm_button = tk.Button( + self, text="Confirm", command=self.confirm_selection + ) self.confirm_button.grid(row=2, column=0, columnspan=2, pady=10) def confirm_selection(self): @@ -133,12 +252,17 @@ def confirm_selection(self): messagebox.showwarning("Warning", "Please select the target variable.") return - self.parent.features = [self.feature_listbox.get(index) for index in selected_features] + self.parent.features = [ + self.feature_listbox.get(index) for index in selected_features + ] self.parent.target_variable = self.target_listbox.get(selected_target[0]) - self.parent.initiate_run_button["state"] = "active" # Enable Initiate Run button in the main window + self.parent.initiate_run_button[ + "state" + ] = "active" # Enable Initiate Run button in the main window self.destroy() + if __name__ == "__main__": app = CSVFileSelector() app.mainloop()