Agreene5's picture
Update app.py
7a1892c verified
import pandas as pd
import numpy as np
import tensorflow as tf
import streamlit as st
import time
#-------------------------------------------------------------
# For outputting the final type but in color
type_to_color = {
'GRASS': "#33FF3F",
'FIRE': "#FF4533",
'WATER':"#339DFF",
'BUG': "#AFFF33",
'NORMAL': "#000000",
'DARK': "#10081A",
'POISON': "#E36DED",
'ELECTRIC': "#FCFF2A",
'GROUND': "#7F5131",
'ICE': "#B3FEFF",
'FAIRY': "#FFB3FE",
'STEEL': "#6E6E6E",
'FIGHTING': "#AB7148",
'PSYCHIC': "#A33EBF",
'ROCK': "#4A3727",
'GHOST': "#DDD2F4",
'DRAGON': "#DB8645",
'FLYING': "#98E6FF"
}
#---------------------------------------------------------------------
# Input your X values for prediction (a NumPy array)--------------------
options = ['Type', 'BST', 'HP', 'Attack', 'Defense', 'Sp. Attack', 'Sp. Defense', 'Speed']
# Create the multiselect
selected_options = st.multiselect('Select which stats you already have (Pick 2-7):', options)
input_feature_length = len(selected_options)
while input_feature_length not in range(2,8):
time.sleep(0.5)
loaded_model = tf.keras.models.load_model(f'Pokemon_Trained_Models/{input_feature_length}feature_model.HDF5')
# Initializing a numpy array to house input values
X_values = np.zeros((1,int(input_feature_length)+8))
options_to_positions = {
'Type': 0,
'BST': 1,
'HP': 2,
'Attack': 3,
'Defense': 4,
'Sp. Attack': 5,
'Sp. Defense': 6,
'Speed': 7,
}
# Reversing the options_to_positions dictionary so I can use it to label output stats
reversed_options_to_positions = {v: k for k, v in options_to_positions.items()}
# Ordering selected_options numerically based on options_to_positions dictionary
selected_options = sorted(selected_options, key=lambda x: options_to_positions[x])
# Adding the indicator vector based on selected stats
indicator_positions = [options_to_positions[i] for i in selected_options]
for i in indicator_positions:
X_values[0, i+input_feature_length] = 1
types_to_numbers = {
'GRASS': 0.056,
'FIRE': 0.112,
'WATER':0.168,
'BUG': 0.224,
'NORMAL': 0.28,
'DARK': 0.336,
'POISON': 0.392,
'ELECTRIC': 0.448,
'GROUND': 0.504,
'ICE': 0.56,
'FAIRY': 0.616,
'STEEL': 0.672,
'FIGHTING': 0.728,
'PSYCHIC': 0.784,
'ROCK': 0.84,
'GHOST': 0.896,
'DRAGON': 0.952,
'FLYING': 1.008
}
option_stat_ranges = {'BST': 'BST (175-1125)', 'HP': 'HP (1-255)', 'Attack': 'Attack (5-190)', 'Defense': 'Defense (5-250)', 'Sp. Attack': 'Sp. Attack (10-194)', 'Sp. Defense': 'Sp. Defense (20-250)', 'Speed': 'Speed (5-200)'}
pokemon_types = ['GRASS', 'FIRE', 'WATER', 'BUG', 'NORMAL', 'DARK', 'POISON', 'ELECTRIC', 'GROUND', 'ICE', 'FAIRY', 'STEEL', 'FIGHTING', 'PSYCHIC', 'ROCK', 'GHOST', 'DRAGON', 'FLYING']
counter = 0
for i in selected_options:
counter += 1
if 'Type' == i:
selected_type = st.selectbox('What type is the Pokemon:', pokemon_types)
X_values[0, counter-1] = types_to_numbers[selected_type]
else:
while True:
try:
X_values[0, counter-1] = st.text_input(f'What is the value for {option_stat_ranges[i]}?')
break
except Exception:
time.sleep(0.5)
# Changing 'Type' to 'Type 1' so it fits the name in the .csv file
selected_options = ['Type 1' if item == 'Type' else item for item in selected_options]
# Define the file path
file_path = "pokemon.csv"
df = pd.read_csv(file_path)
columns_to_delete = ['Dex No', 'Name', 'Base Name', 'Type 2']
df = df.drop(columns=columns_to_delete)
#Copy dataframe for future refernce:
old_df = df.copy()
#Selecting columns that will be scaled
values_to_scale = X_values[0, 0:input_feature_length]
#Scaling the columns with Min-Max Scaling
counter_2 = 0
for stat in selected_options:
counter_2 +=1
if stat != 'Type 1':
min_value = df[stat].min()
max_value = df[stat].max()
X_values[0, counter_2-1] = (X_values[0, counter_2-1] - min_value) / (max_value - min_value)
#-====================================================================================================================================
# Extract indices of '1' values-----------------------------------------
indices_of_ones = [index for index, value in enumerate(X_values[0]) if value == 1]
# Changing values so they fit their appropriate column
for i in range(len(indices_of_ones)):
indices_of_ones[i] -= input_feature_length-1
print("Indices of '1' values:", indices_of_ones)
# Use the '1' values to find what the export columns will be---
full_range = list(range(1, 9))
# Find the missing indices by taking the set difference
missing_indices = list(set(full_range) - set(indices_of_ones))
missing_indices.sort()
print(missing_indices)
# Use the model to make predictions-------------------------------------
Y_values = loaded_model.predict(X_values)
List_Y_values = Y_values[0].tolist()
print(f"Raw Output Values: {List_Y_values}")
# Initializing 'converted_Y_values' to be same length as 'Y_values'
converted_Y_values = [None] * (len(missing_indices))
#_------------ Making values readable (undoing min-max and other scaling)
if 1 in indices_of_ones:
converted_Y_values = [None] * (len(missing_indices))
#'len(missing_indices)' is the length of the 'missing_indices'
for i in range(len(missing_indices)):
# Defining Min-Max Values, using the indicies value to match elements
min_max_values = {
2: [old_df['BST'].min(), old_df['BST'].max()],
3: [old_df['HP'].min(), old_df['HP'].max()],
4: [old_df['Attack'].min(), old_df['Attack'].max()],
5: [old_df['Defense'].min(), old_df['Defense'].max()],
6: [old_df['Sp. Attack'].min(), old_df['Sp. Attack'].max()],
7: [old_df['Sp. Defense'].min(), old_df['Sp. Defense'].max()],
8: [old_df['Speed'].min(), old_df['Speed'].max()]
}
temp_min_max = min_max_values[missing_indices[i]]
# Undo the min-max scaling
converted_Y_values[i] = List_Y_values[i] * (temp_min_max[1] - temp_min_max[0]) + temp_min_max[0]
else:
converted_Y_values = [None] * (len(missing_indices) - 1)
# Converting 'Type 1' back to readable type
type_output_indicator = True
closest_type = None
min_difference = float('inf')
# Finding closest type for the value
for pokemon_type, value in types_to_numbers.items():
difference = abs(Y_values[0,0] - value)
if difference < min_difference:
min_difference = difference
closest_type = pokemon_type
# Delete the '1' from missing indices because it's dealt with above
del missing_indices[0]
del List_Y_values[0]
for i in range(len(missing_indices)):
# Defining Min-Max Values, using the indicies value to match elements
min_max_values = {
2: [old_df['BST'].min(), old_df['BST'].max()],
3: [old_df['HP'].min(), old_df['HP'].max()],
4: [old_df['Attack'].min(), old_df['Attack'].max()],
5: [old_df['Defense'].min(), old_df['Defense'].max()],
6: [old_df['Sp. Attack'].min(), old_df['Sp. Attack'].max()],
7: [old_df['Sp. Defense'].min(), old_df['Sp. Defense'].max()],
8: [old_df['Speed'].min(), old_df['Speed'].max()]
}
temp_min_max = min_max_values[missing_indices[i]]
# Undo the min-max scaling
converted_Y_values[i] = List_Y_values[i] * (temp_min_max[1] - temp_min_max[0]) + temp_min_max[0]
# For making the 'closest_type' text the color of the type
color = type_to_color[closest_type]
st.write("Output Stats:")
if 'closest_type' in vars():
st.write(f"<p style='color: {color};'>Type - {closest_type}</p>", unsafe_allow_html=True)
counter_3 = 0
for i in missing_indices:
st.write(f"{reversed_options_to_positions[i-1]} - {round(converted_Y_values[counter_3])}")
counter_3 +=1