Spaces:
Sleeping
Sleeping
File size: 3,872 Bytes
ce4e7e0 e51a2fd ce4e7e0 e51a2fd 2a7f672 e51a2fd | 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 | import streamlit as st
import pickle
from collections import Counter
import re
from typing import Counter as TCounter, Tuple, List, Any
# --- 1. CONFIGURATION ---
# The n-gram range used during model training (e.g., (1, 4) for unigrams up to 4-grams)
N_GRAM_RANGE = (1, 4)
# Filenames saved in the previous step
MODEL_FILE = 'src/emotion.pkl'
VECTORIZER_FILE = 'src/vectorizer.pkl'
# --- 2. LOAD ARTIFACTS ---
@st.cache_resource
def load_artifacts():
"""Loads the saved classifier model and DictVectorizer."""
try:
# Load the Model
with open(MODEL_FILE, 'rb') as model_file:
loaded_model = pickle.load(model_file)
# Load the Vectorizer
with open(VECTORIZER_FILE, 'rb') as vec_file:
loaded_vectorizer = pickle.load(vec_file)
return loaded_model, loaded_vectorizer
except FileNotFoundError:
st.error(f"Error: Required files ({MODEL_FILE} or {VECTORIZER_FILE}) not found. Please ensure they are in the correct directory.")
return None, None
# --- 3. FEATURE EXTRACTION FUNCTION (CRITICAL!) ---
# This function MUST be identical to the one used during model training.
def create_feature(text: str, nrange: Tuple[int, int]) -> TCounter[str]:
"""Extracts n-gram and punctuation features from a text string."""
text_features: List[str] = []
lower_text = text.lower()
# Word N-Grams
text_alphanum = re.sub(r'[^a-z0-9#]', ' ', lower_text)
token = text_alphanum.split()
for n in range(nrange[0], nrange[1] + 1):
if n > 0 and n <= len(token):
ngrams = [' '.join(token[i-n:i]) for i in range(n, len(token) + 1)]
text_features.extend(ngrams)
# Punctuation Features
text_punc = re.sub(r'[a-z0-9]', ' ', lower_text)
text_features.extend(text_punc.split())
return Counter(text_features)
# --- 4. PREDICTION LOGIC ---
def predict_emotion(text: str, model: Any, vectorizer: Any) -> str:
"""Processes text and returns the predicted emotion label."""
if not text:
return "Please enter text for analysis."
# 1. Convert Text to Features (Counter object)
feature_counter = create_feature(text, N_GRAM_RANGE)
# 2. Vectorization (DictVectorizer expects a list of dictionaries/Counters)
# The saved vectorizer is used to ensure the features are ordered correctly.
X_processed = vectorizer.transform([feature_counter])
# 3. Make Prediction
prediction = model.predict(X_processed)
return prediction[0]
# --- 5. STREAMLIT UI ---
# Load the model artifacts
model, vectorizer = load_artifacts()
if model and vectorizer:
st.title("π¬ Text Emotion Detection App")
st.markdown("Enter a sentence or text below to see the predicted emotion.")
# User input area
user_input = st.text_area("Enter your text here:", "")
if st.button("Predict Emotion"):
if user_input:
# Perform prediction
result = predict_emotion(user_input, model, vectorizer)
# --- Result Display (Using visual cues) ---
st.subheader("Analysis Result")
# Simple color-coding based on common emotions
if result == 'joy':
st.success(f"Predicted Emotion: **{result.upper()}** π")
elif result in ['sadness', 'fear']:
st.warning(f"Predicted Emotion: **{result.upper()}** π")
elif result == 'anger':
st.error(f"Predicted Emotion: **{result.upper()}** π‘")
elif result == 'disgust':
st.markdown(f"Predicted Emotion: **{result.upper()}** π€’", unsafe_allow_html=True)
else:
st.info(f"Predicted Emotion: **{result.upper()}**")
else:
st.warning("Please enter some text to predict.") |