Download app.py from kraghavendra99/TwitterSentimentAnalysis: direct link, hf CLI and curl.
- Browser
- Download file 10.3 kB
-
https://huggingface.co/spaces/kraghavendra99/TwitterSentimentAnalysis/resolve/main/app.py
- Command line
-
hf download hf://spaces/kraghavendra99/TwitterSentimentAnalysis/app.py
-
curl -L -o app.py https://huggingface.co/spaces/kraghavendra99/TwitterSentimentAnalysis/resolve/main/app.py
10.3 kB
| import gradio as gr | |
| import re | |
| import pickle | |
| import pandas as pd | |
| from sklearn.feature_extraction.text import TfidfVectorizer | |
| from sklearn.naive_bayes import MultinomialNB | |
| from sklearn.model_selection import train_test_split | |
| from sklearn.metrics import accuracy_score, classification_report | |
| import nltk | |
| from nltk.corpus import stopwords | |
| from nltk.stem import WordNetLemmatizer | |
| from nltk.tokenize import TweetTokenizer | |
| # Download required NLTK data | |
| try: | |
| nltk.data.find('tokenizers/punkt') | |
| except LookupError: | |
| nltk.download('punkt') | |
| try: | |
| nltk.data.find('corpora/stopwords') | |
| except LookupError: | |
| nltk.download('stopwords') | |
| try: | |
| nltk.data.find('corpora/wordnet') | |
| except LookupError: | |
| nltk.download('wordnet') | |
| # Initialize tokenizer and lemmatizer | |
| tokenizer = TweetTokenizer(preserve_case=False, strip_handles=True, reduce_len=True) | |
| lemmatizer = WordNetLemmatizer() | |
| stop_words = set(stopwords.words("english")) | |
| def preprocess_tweet(tweet): | |
| """ | |
| Preprocess a tweet by cleaning and normalizing the text. | |
| """ | |
| # Remove URLs | |
| tweet = re.sub(r"http\S+|www\S+|https\S+", "", tweet, flags=re.MULTILINE) | |
| # Remove punctuation and numbers | |
| tweet = re.sub(r"[^a-zA-Z]", " ", tweet) # Keep only letters | |
| # Tokenize | |
| tokens = tokenizer.tokenize(tweet) | |
| # Remove stopwords and lemmatize | |
| processed_tokens = [] | |
| for word in tokens: | |
| if word not in stop_words and len(word) > 2: # Also filter out very short words | |
| processed_tokens.append(lemmatizer.lemmatize(word)) | |
| return " ".join(processed_tokens) | |
| # Create a simple demo model (in a real scenario, you'd load a pre-trained model) | |
| class SentimentAnalyzer: | |
| def __init__(self): | |
| self.vectorizer = None | |
| self.model = None | |
| self.is_trained = False | |
| def create_demo_model(self): | |
| """ | |
| Create a simple demo model with sample data for demonstration purposes. | |
| In a real application, you would load your trained model here. | |
| """ | |
| # Sample training data for demo purposes | |
| sample_tweets = [ | |
| "I love this product! It's amazing!", | |
| "This is the worst thing ever.", | |
| "Great service and friendly staff!", | |
| "Terrible experience, would not recommend.", | |
| "Amazing quality and fast delivery!", | |
| "Poor customer service and bad quality.", | |
| "Excellent work, very satisfied!", | |
| "Disappointing results, not worth it.", | |
| "Outstanding performance, highly recommend!", | |
| "Awful experience, complete waste of money.", | |
| "Fantastic product, exceeded expectations!", | |
| "Horrible quality, broke immediately.", | |
| "Wonderful experience, will buy again!", | |
| "Terrible product, don't waste your money.", | |
| "Incredible service, very professional!", | |
| "Worst purchase ever made.", | |
| "Perfect solution for my needs!", | |
| "Completely useless and overpriced.", | |
| "Brilliant design and functionality!", | |
| "Absolutely terrible, avoid at all costs." | |
| ] | |
| sample_labels = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0] # 1 = positive, 0 = negative | |
| # Preprocess the sample tweets | |
| processed_tweets = [preprocess_tweet(tweet) for tweet in sample_tweets] | |
| # Create and train the model | |
| self.vectorizer = TfidfVectorizer(max_features=1000, min_df=1, max_df=0.8) | |
| X = self.vectorizer.fit_transform(processed_tweets) | |
| self.model = MultinomialNB() | |
| self.model.fit(X, sample_labels) | |
| self.is_trained = True | |
| def predict_sentiment(self, text): | |
| """ | |
| Predict the sentiment of a given text. | |
| """ | |
| if not self.is_trained: | |
| self.create_demo_model() | |
| # Preprocess the input text | |
| processed_text = preprocess_tweet(text) | |
| if not processed_text.strip(): | |
| return "Neutral", 0.5, "βͺ" | |
| # Transform the text using the fitted vectorizer | |
| text_features = self.vectorizer.transform([processed_text]) | |
| # Make prediction | |
| prediction = self.model.predict(text_features)[0] | |
| prediction_proba = self.model.predict_proba(text_features)[0] | |
| # Get confidence score | |
| confidence = max(prediction_proba) | |
| # Determine sentiment and emoji | |
| if prediction == 1: | |
| sentiment = "Positive" | |
| emoji = "π" | |
| else: | |
| sentiment = "Negative" | |
| emoji = "π" | |
| return sentiment, confidence, emoji | |
| # Initialize the sentiment analyzer | |
| analyzer = SentimentAnalyzer() | |
| def analyze_sentiment(text): | |
| """ | |
| Main function to analyze sentiment that will be called by Gradio. | |
| """ | |
| if not text.strip(): | |
| return "Please enter some text to analyze.", "", "" | |
| sentiment, confidence, emoji = analyzer.predict_sentiment(text) | |
| # Format the results | |
| result = f"{emoji} **{sentiment}**" | |
| confidence_text = f"Confidence: {confidence:.2%}" | |
| # Add interpretation | |
| if confidence > 0.8: | |
| interpretation = "High confidence prediction" | |
| elif confidence > 0.6: | |
| interpretation = "Moderate confidence prediction" | |
| else: | |
| interpretation = "Low confidence prediction" | |
| return result, confidence_text, interpretation | |
| # Example tweets for testing | |
| example_tweets = [ | |
| "I absolutely love this new phone! The camera quality is amazing and the battery lasts all day.", | |
| "This movie was terrible. Waste of time and money. Would not recommend to anyone.", | |
| "The weather is nice today.", | |
| "Just had the worst customer service experience ever. So frustrated right now!", | |
| "Thank you so much for your help! You made my day better.", | |
| "This restaurant has the best food in town! Highly recommend the pasta.", | |
| "I'm so disappointed with this purchase. It broke after just one day.", | |
| "Great job on the presentation! Very informative and well organized.", | |
| "Traffic is horrible today. Going to be late for my meeting.", | |
| "Excited to start my new job next week! Can't wait to meet the team." | |
| ] | |
| # Create the Gradio interface | |
| with gr.Blocks( | |
| theme=gr.themes.Soft(), | |
| title="Twitter Sentiment Analysis", | |
| css=""" | |
| .main-header { | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| } | |
| .result-box { | |
| padding: 1rem; | |
| border-radius: 8px; | |
| margin: 1rem 0; | |
| } | |
| .positive { | |
| background-color: #d4edda; | |
| border: 1px solid #c3e6cb; | |
| } | |
| .negative { | |
| background-color: #f8d7da; | |
| border: 1px solid #f5c6cb; | |
| } | |
| """ | |
| ) as demo: | |
| # Header | |
| gr.Markdown( | |
| """ | |
| # π¦ Twitter Sentiment Analysis | |
| ### Analyze the sentiment of tweets and text using machine learning | |
| This tool uses a Naive Bayes classifier trained on tweet data to determine whether text expresses positive or negative sentiment. | |
| Simply enter your text below and click "Analyze Sentiment" to get started! | |
| """, | |
| elem_classes=["main-header"] | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| # Input section | |
| text_input = gr.Textbox( | |
| label="Enter text to analyze", | |
| placeholder="Type your tweet or text here...", | |
| lines=4, | |
| max_lines=10 | |
| ) | |
| with gr.Row(): | |
| analyze_btn = gr.Button("π Analyze Sentiment", variant="primary", size="lg") | |
| clear_btn = gr.Button("ποΈ Clear", variant="secondary") | |
| with gr.Column(scale=1): | |
| # Output section | |
| sentiment_output = gr.Markdown(label="Sentiment", value="") | |
| confidence_output = gr.Markdown(label="Confidence", value="") | |
| interpretation_output = gr.Markdown(label="Interpretation", value="") | |
| # Examples section | |
| gr.Markdown("### π Try these examples:") | |
| with gr.Row(): | |
| example_buttons = [] | |
| for i in range(0, min(6, len(example_tweets)), 2): | |
| with gr.Column(): | |
| for j in range(2): | |
| if i + j < len(example_tweets): | |
| btn = gr.Button( | |
| example_tweets[i + j][:50] + "..." if len(example_tweets[i + j]) > 50 else example_tweets[i + j], | |
| size="sm" | |
| ) | |
| btn.click( | |
| lambda x=example_tweets[i + j]: x, | |
| outputs=text_input | |
| ) | |
| # Model information | |
| with gr.Accordion("βΉοΈ About this model", open=False): | |
| gr.Markdown( | |
| """ | |
| **Model Details:** | |
| - **Algorithm**: Multinomial Naive Bayes | |
| - **Features**: TF-IDF (Term Frequency-Inverse Document Frequency) | |
| - **Preprocessing**: Text cleaning, tokenization, stopword removal, lemmatization | |
| - **Classes**: Positive, Negative | |
| **Note**: This is a demonstration model trained on a small sample dataset. | |
| For production use, you would want to train on a larger, more diverse dataset like the Sentiment140 dataset. | |
| **Limitations**: | |
| - May not handle sarcasm or complex sentiment well | |
| - Performance depends on similarity to training data | |
| - Neutral sentiments may be classified as positive or negative | |
| """ | |
| ) | |
| # Event handlers | |
| analyze_btn.click( | |
| fn=analyze_sentiment, | |
| inputs=text_input, | |
| outputs=[sentiment_output, confidence_output, interpretation_output] | |
| ) | |
| clear_btn.click( | |
| lambda: ("", "", "", ""), | |
| outputs=[text_input, sentiment_output, confidence_output, interpretation_output] | |
| ) | |
| # Auto-analyze on text change (with debounce) | |
| text_input.change( | |
| fn=analyze_sentiment, | |
| inputs=text_input, | |
| outputs=[sentiment_output, confidence_output, interpretation_output] | |
| ) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| demo.launch() |