Module 6 · Lesson 125 minBeginner

Project 19: Sentiment Analysis

What you'll build
Score any text as positive, negative, or neutral with NLP — no API keys needed.

Introduction

In this project you will build a Sentiment Analysis web app using Python and Streamlit. The app uses TextBlob to determine whether a piece of text is positive, negative, or neutral — and shows you a polarity score from -1 to +1. For generative AI instead of analysis, the Mistral chatbot tutorial is the natural next step.

Prerequisites

  • Python 3.8+python.org
  • Libraries:
  • code
    pip install streamlit textblob
    python -m textblob.download_corpora

    Step 1: Create the Script

    Create sentiment_app.py and paste the following:

    code
    import streamlit as st
    from textblob import TextBlob
    
    st.set_page_config(page_title="Sentiment Analysis", page_icon="😊")
    st.title("😊 Sentiment Analysis App")
    st.write("Enter any text to find out if it is positive, negative, or neutral.")
    
    user_input = st.text_area("Enter your text:", height=150,
                               placeholder="Type or paste text here...")
    
    if st.button("Analyse Sentiment") and user_input:
        blob = TextBlob(user_input)
        polarity = blob.sentiment.polarity
        subjectivity = blob.sentiment.subjectivity
    
        if polarity > 0.1:
            label, color = "😊 Positive", "success"
        elif polarity < -0.1:
            label, color = "😞 Negative", "error"
        else:
            label, color = "😐 Neutral", "info"
    
        col1, col2, col3 = st.columns(3)
        col1.metric("Sentiment", label)
        col2.metric("Polarity", f"{polarity:.2f}")
        col3.metric("Subjectivity", f"{subjectivity:.2f}")
    
        if color == "success":
            st.success(f"This text has a **positive** sentiment (polarity: {polarity:.2f}).")
        elif color == "error":
            st.error(f"This text has a **negative** sentiment (polarity: {polarity:.2f}).")
        else:
            st.info(f"This text has a **neutral** sentiment (polarity: {polarity:.2f}).")
    
    st.caption("Polarity: -1 (very negative) → 0 (neutral) → +1 (very positive)")

    Step 2: Run the App

    code
    streamlit run sentiment_app.py

    Step 3: Use the App

    Type or paste any text in the input area and click Analyse Sentiment. The app returns a labelled result plus polarity and subjectivity scores.

    How It Works

    The app uses VADER (Valence Aware Dictionary and sEntiment Reasoner) from NLTK. VADER scores text against a lexicon of words rated from -4 to +4, with special handling for intensifiers ("very good"), negation ("not good"), and punctuation ("good!!!"). It returns four numbers: positive, neutral, negative proportions, and a compound score from -1 (most negative) to +1 (most positive).

    The compound score drives the verdict: typically ≥ 0.05 is positive, ≤ -0.05 negative, and anything between is neutral. Rendering the three proportions with st.progress() bars makes the result instantly readable.

    VADER is *lexicon-based*, not learned — it needs no training data and runs instantly, which is why it is the right first NLP tool. Its weakness is context and sarcasm; for conversational text, an LLM approach like the SANGAM AI toolkit handles nuance better.

    Key Concepts

  • `TextBlob(text)` — Creates a TextBlob object that analyses the provided text.
  • `blob.sentiment.polarity` — Float from -1.0 (very negative) to +1.0 (very positive).
  • `blob.sentiment.subjectivity` — Float from 0.0 (objective) to 1.0 (very subjective).
  • `st.metric()` — Displays each score in a clean highlighted card.
  • Understanding the Scores

    Polarity RangeSentiment
    0.1 to 1.0Positive 😊
    -0.1 to 0.1Neutral 😐
    -1.0 to -0.1Negative 😞

    What to Try Next

  • Analyse sentiment sentence by sentence and display results for each.
  • Generate a word cloud of the most frequent words using wordcloud.
  • Swap TextBlob for VADER for better accuracy on social-media-style text.
  • Common Errors & Fixes

  • LookupError: resource vader_lexicon not found — the NLTK data download did not complete. Run nltk.download('vader_lexicon') once in a plain Python shell, not inside the Streamlit rerun.
  • Every sentence scores neutral — you are analyzing the raw SentimentIntensityAnalyzer() object instead of calling polarity_scores(text).
  • Slow on first load — VADER's lexicon loads once per process; cache the analyzer with @st.cache_resource.
  • Emoji/ slang scored wrong — expected for a lexicon model. Preprocess with the emoji package or accept the limitation.
  • `nltk` data downloads on every visitor's first load — pre-download the lexicon into the repo or a persistent folder and point NLTK_DATA at it, so deploys don't re-fetch.
  • FAQ

    How accurate is VADER?

    On social-media-style English it benchmarks around 0.88 F1 on standard test sets. On formal or domain-specific text, accuracy drops — test against your own labeled samples.

    Can it handle Hindi or other languages?

    Not natively — VADER is English-only. Translate first (see the translator app) or use a multilingual model.

    Why compound instead of the three percentages?

    Compound is a single normalized score that accounts for the whole sentence, making thresholds and comparisons simple.

    Can I analyze whole reviews or documents?

    Yes — score per sentence and average the compound scores, which tracks mixed sentiment better than scoring the whole block at once.

    Adapted from: Sentiment Analysis App using Python and Streamlit

    Checkpoint
    Typing a sentence shows its sentiment with visual score bars.
    What you learned
    • VADER and compound scores
    • Caching loaded models
    • Progress bars as data viz