File size: 6,147 Bytes
e9e73c3 456e90c e9e73c3 cbe2c52 e9e73c3 cbe2c52 e9e73c3 456e90c e9e73c3 b413c92 e9e73c3 b413c92 e9e73c3 b413c92 e9e73c3 b413c92 e9e73c3 b413c92 e9e73c3 b413c92 |
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
import pickle
import streamlit as st
import numpy as np
import pandas as pd
import re
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
from nltk.corpus import stopwords
from sklearn.preprocessing import StandardScaler
import nltk
import time
# Download required NLTK data (for stopwords only)
nltk.download('stopwords')
# Load the trained model
model = load_model("./best_model.keras")
# Load the tokenizer
with open("./tokenizer.pkl", "rb") as f:
tokenizer = pickle.load(f)
# Ensure the tokenizer is valid
if not hasattr(tokenizer, 'texts_to_sequences'):
raise ValueError("Loaded tokenizer is not a valid Keras Tokenizer object.")
# Define constants
MAX_SEQUENCE_LENGTH = 100
# Simple tokenizer function
def simple_tokenizer(text):
text = text.lower()
text = re.sub(r'[^a-zA-Z\s]', '', text)
tokens = text.split() # Split by whitespace
return tokens
# Preprocessing function for input review
def preprocess_input_review(review_text):
tokens = simple_tokenizer(review_text)
stop_words = set(stopwords.words('english'))
tokens = [word for word in tokens if word not in stop_words]
processed_review = ' '.join(tokens)
return processed_review
# Convert simplified time strings (e.g., 2H30M or 15M) to minutes
def time_to_minutes(time_str):
if not time_str or pd.isna(time_str):
return 0
hours, minutes = 0, 0
if 'H' in time_str:
parts = time_str.split('H')
hours = int(parts[0]) if parts[0].isdigit() else 0
time_str = parts[1] if len(parts) > 1 else ''
if 'M' in time_str and time_str.split('M')[0].isdigit():
minutes = int(time_str.split('M')[0])
return hours * 60 + minutes
# Prediction function
def predict_menu_inclusion(food_name, review_text, cook_time, prep_time, total_time, protein, carbs, fat):
# Preprocess the review
processed_review = preprocess_input_review(review_text)
# Tokenize and pad the review
review_sequence = tokenizer.texts_to_sequences([processed_review])
padded_review = pad_sequences(review_sequence, maxlen=MAX_SEQUENCE_LENGTH)
# Prepare numerical features
numerical_features = np.array([[time_to_minutes(cook_time),
time_to_minutes(prep_time),
time_to_minutes(total_time),
protein, carbs, fat]])
# Normalize numerical features
scaler = StandardScaler()
numerical_features = scaler.fit_transform(numerical_features)
# Predict the rating
predicted_rating = model.predict([padded_review, numerical_features]).flatten()[0]
# Decide whether to include the item on the menu
include_on_menu = predicted_rating > 3.5 # Threshold for inclusion
return {
"FoodName": food_name,
"PredictedRating": round(predicted_rating, 2),
"IncludeOnMenu": include_on_menu
}
# Streamlit app with enhanced UI
st.set_page_config(page_title="Recipe Rating & Menu Optimization", layout="wide")
st.title("๐ฒ๐ Recipe Rating & Menu Optimization ๐")
st.markdown(
"""
Welcome to the **Recipe Rating & Menu Optimization** app! ๐
This tool uses cutting-edge **AI and machine learning** ๐ง to help chefs, restaurateurs, and food enthusiasts ๐ฝ๏ธ predict recipe ratings and decide if a dish deserves a place on the menu. ๐
Let's get started and create culinary magic! โจ
"""
)
st.sidebar.header("๐ Enter Recipe Details")
food_name = st.sidebar.text_input("๐ด Food Name", value="Paneer Butter Masala")
review_text = st.sidebar.text_area("๐ Review Text", value="This dish is delicious, rich in flavor, and a favorite among customers!")
cook_time = st.sidebar.text_input("โณ Cooking Time (e.g., 15M or 2H30M)", value="30M")
prep_time = st.sidebar.text_input("๐ Preparation Time (e.g., 15M or 1H15M)", value="15M")
total_time = st.sidebar.text_input("๐
Total Time (e.g., 45M or 1H45M)", value="45M")
protein = st.sidebar.number_input("๐ช Protein (grams)", min_value=0.0, step=1.0, value=20.0)
carbs = st.sidebar.number_input("๐ Carbohydrates (grams)", min_value=0.0, step=1.0, value=10.0)
fat = st.sidebar.number_input("๐ Fat (grams)", min_value=0.0, step=1.0, value=15.0)
if st.sidebar.button("๐ฎ Predict"):
result = predict_menu_inclusion(food_name, review_text, cook_time, prep_time, total_time, protein, carbs, fat)
predicted_rating = result["PredictedRating"]
include_on_menu = result["IncludeOnMenu"]
# Custom progress bar with color based on inclusion
bar_color = "green" if include_on_menu else "red"
progress_percentage = int(predicted_rating * 20) # Convert rating (0-5) to percentage (0-100)
# Display animated progress bar
st.markdown(
f"""
<div style="
width: 100%;
background-color: #ddd;
border-radius: 10px;
margin-bottom: 15px;
">
<div style="
width: {progress_percentage}%;
height: 25px;
background-color: {bar_color};
border-radius: 10px;
text-align: center;
color: white;
line-height: 25px;
font-weight: bold;
animation: growBar 2s;
">
{progress_percentage}%
</div>
</div>
<style>
@keyframes growBar {{
from {{ width: 0%; }}
to {{ width: {progress_percentage}%; }}
}}
</style>
""",
unsafe_allow_html=True,
)
# Display prediction results
st.subheader("Prediction Results")
st.markdown(f"**๐ด Food Name:** {result['FoodName']}")
st.markdown(f"**โญ Predicted Rating:** {result['PredictedRating']:.1f}")
st.markdown(
f"**๐ฝ๏ธ Include on Menu:** "
f"<span style='color: {'green' if include_on_menu else 'red'}; font-weight: bold;'>"
f"{'Yes' if include_on_menu else 'No'}</span>",
unsafe_allow_html=True,
)
|