Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import joblib | |
| import pandas as pd | |
| import numpy as np | |
| import re | |
| import nltk | |
| import pickle | |
| import tensorflow as tf | |
| from nltk.corpus import stopwords | |
| from tensorflow.keras.models import load_model | |
| from tensorflow.keras.preprocessing.sequence import pad_sequences | |
| # --- Setup & Preprocessing --- | |
| nltk.download('stopwords') | |
| stop_words = set(stopwords.words('english')) | |
| def preprocess(text): | |
| text = str(text).lower() | |
| text = re.sub(r'[^a-zA-Z\s]', '', text) | |
| tokens = text.split() | |
| return " ".join([w for w in tokens if w not in stop_words]) | |
| # --- Load Artifacts --- | |
| print("Loading models...") | |
| # 1. Load Scikit-Learn Models & Vectorizer | |
| try: | |
| lr_model = joblib.load('model_lr.joblib') | |
| nb_model = joblib.load('model_nb.joblib') | |
| tfidf = joblib.load('tfidf_vectorizer.joblib') | |
| except Exception as e: | |
| print(f"Error loading Sklearn models: {e}") | |
| # 2. Load Keras Models & Tokenizer | |
| try: | |
| ffnn_model = load_model('model_ffnn.h5') | |
| embed_model = load_model('model_embed.h5') | |
| with open('tokenizer.pickle', 'rb') as handle: | |
| tokenizer = pickle.load(handle) | |
| except Exception as e: | |
| print(f"Error loading Keras models/tokenizer: {e}") | |
| # Constants | |
| MAX_LEN = 100 # Must match the training length | |
| LABELS = {-1: "Negative", 0: "Neutral", 1: "Positive"} | |
| # Map Keras output indices (0, 1, 2) to Sentiment Labels (-1, 0, 1) | |
| INDEX_TO_LABEL = {0: -1, 1: 0, 2: 1} | |
| # --- Prediction Logic --- | |
| def predict_single(text, model_name): | |
| if not text: return "Please enter text." | |
| clean_text = preprocess(text) | |
| # A. Scikit-Learn Models | |
| if model_name in ["Logistic Regression", "Naive Bayes"]: | |
| model = lr_model if model_name == "Logistic Regression" else nb_model | |
| vectorized = tfidf.transform([clean_text]) | |
| pred = model.predict(vectorized)[0] | |
| return LABELS.get(int(pred), "Unknown") | |
| # B. Feedforward NN (TF-IDF based) | |
| elif model_name == "Feedforward Neural Network": | |
| vectorized = tfidf.transform([clean_text]).toarray() # NN needs dense array | |
| pred_probs = ffnn_model.predict(vectorized) | |
| pred_idx = np.argmax(pred_probs, axis=1)[0] | |
| return LABELS.get(INDEX_TO_LABEL[pred_idx], "Unknown") | |
| # C. Embedding NN (Sequence based) | |
| elif model_name == "Embedding Neural Network": | |
| seq = tokenizer.texts_to_sequences([clean_text]) | |
| padded = pad_sequences(seq, maxlen=MAX_LEN, padding='post', truncating='post') | |
| pred_probs = embed_model.predict(padded) | |
| pred_idx = np.argmax(pred_probs, axis=1)[0] | |
| return LABELS.get(INDEX_TO_LABEL[pred_idx], "Unknown") | |
| def predict_file(file_obj, model_name): | |
| if file_obj is None: return None | |
| df = pd.read_csv(file_obj.name) | |
| if 'clean_text' not in df.columns: | |
| return "Error: CSV must have a column named 'clean_text'" | |
| # Preprocess all rows | |
| processed_texts = df['clean_text'].apply(preprocess) | |
| # A. Scikit-Learn Batch | |
| if model_name in ["Logistic Regression", "Naive Bayes"]: | |
| model = lr_model if model_name == "Logistic Regression" else nb_model | |
| vectors = tfidf.transform(processed_texts) | |
| preds = model.predict(vectors) | |
| df['Predicted_Sentiment'] = [LABELS.get(int(p), "Unknown") for p in preds] | |
| # B. Feedforward NN Batch | |
| elif model_name == "Feedforward Neural Network": | |
| # Note: Large datasets might need batching here to avoid memory issues with .toarray() | |
| vectors = tfidf.transform(processed_texts).toarray() | |
| pred_probs = ffnn_model.predict(vectors) | |
| pred_indices = np.argmax(pred_probs, axis=1) | |
| df['Predicted_Sentiment'] = [LABELS.get(INDEX_TO_LABEL[i], "Unknown") for i in pred_indices] | |
| # C. Embedding NN Batch | |
| elif model_name == "Embedding Neural Network": | |
| seqs = tokenizer.texts_to_sequences(processed_texts) | |
| padded = pad_sequences(seqs, maxlen=MAX_LEN, padding='post', truncating='post') | |
| pred_probs = embed_model.predict(padded) | |
| pred_indices = np.argmax(pred_probs, axis=1) | |
| df['Predicted_Sentiment'] = [LABELS.get(INDEX_TO_LABEL[i], "Unknown") for i in pred_indices] | |
| output_file = "predictions.csv" | |
| df.to_csv(output_file, index=False) | |
| return output_file | |
| # --- Interface --- | |
| model_choices = [ | |
| "Logistic Regression", | |
| "Naive Bayes", | |
| "Feedforward Neural Network", | |
| "Embedding Neural Network" | |
| ] | |
| with gr.Blocks(title="Twitter Sentiment Analysis") as demo: | |
| gr.Markdown("# Twitter Sentiment Analysis Hub") | |
| with gr.Tabs(): | |
| # Tab 1: Single Tweet | |
| with gr.TabItem("Analyze Tweet"): | |
| with gr.Row(): | |
| txt_input = gr.Textbox(lines=2, placeholder="Enter tweet...", label="Input Text") | |
| model_drop = gr.Dropdown(model_choices, value="Logistic Regression", label="Select Model") | |
| btn_predict = gr.Button("Predict") | |
| lbl_output = gr.Label(label="Sentiment") | |
| btn_predict.click(predict_single, inputs=[txt_input, model_drop], outputs=lbl_output) | |
| # Tab 2: Batch Analysis | |
| with gr.TabItem("Batch Analysis (Upload CSV)"): | |
| gr.Markdown("Upload a CSV file with a `clean_text` column.") | |
| with gr.Row(): | |
| file_input = gr.File(label="Upload CSV") | |
| model_drop_batch = gr.Dropdown(model_choices, value="Logistic Regression", label="Select Model") | |
| btn_process = gr.Button("Run Analysis") | |
| file_output = gr.File(label="Download Predictions") | |
| btn_process.click(predict_file, inputs=[file_input, model_drop_batch], outputs=file_output) | |
| if __name__ == "__main__": | |
| demo.launch() |