Sentiment analysis with VADER

NLTK · Practical · 10 min

VADER gives a solid, training-free sentiment baseline for reviews and social media in a few lines.

VADER (Valence Aware Dictionary and sEntiment Reasoner) is a rule-based sentiment model tuned for social media. It needs the vader_lexicon data package. Create SentimentIntensityAnalyzer() and call polarity_scores(text) to get a dict:

  • neg, neu, pos: the proportions of the text that fall in each class (they sum to about 1)
  • compound: a normalised overall score from -1 (most negative) to +1 (most positive)

The usual thresholds: compound >= 0.05 is positive, <= -0.05 negative, otherwise neutral.

VADER is more than a word list. Its rules handle:

  • negation: "not good" flips polarity
  • intensifiers: "very good" > "good"; "kind of good" < "good"
  • capitalisation and punctuation: "GOOD!!!" scores higher than "good"
  • "but": the clause after "but" weighs more
  • emoticons, common slang and emoji descriptions

Feed it raw text, not stemmed or lowercased tokens, because case, punctuation and stopwords like "not" carry signal.

Limitations: it doesn't understand sarcasm, domain-specific terms ("unpredictable" is good for a thriller, bad for a car) or long documents well. Score per sentence and aggregate for longer texts, and validate against labelled examples from your domain before trusting it; a trained classifier or transformer model usually beats it when labels exist.

Example

from nltk.sentiment import SentimentIntensityAnalyzer

sia = SentimentIntensityAnalyzer()

def label(text):
    c = sia.polarity_scores(text)["compound"]
    return "pos" if c >= 0.05 else "neg" if c <= -0.05 else "neu"

print(sia.polarity_scores("The food was good."))
# {'neg': 0.0, 'neu': 0.508, 'pos': 0.492, 'compound': 0.4404}

for t in ["The food was good.", "The food was not good.",
          "The food was VERY GOOD!!!", "The food was good, but the service was awful.",
          "The table is made of wood."]:
    print(f"{sia.polarity_scores(t)['compound']:+.3f} {label(t)}  {t}")
# +0.440 pos  The food was good.
# -0.341 neg  The food was not good.
# +0.760 pos  The food was VERY GOOD!!!
# -0.468 neg  The food was good, but the service was awful.
# +0.000 neu  The table is made of wood.

Remember

  • polarity_scores returns neg/neu/pos proportions and a compound score
  • compound >= 0.05 positive, <= -0.05 negative is the usual rule
  • Rules handle negation, intensifiers, caps, punctuation and 'but'
  • Give it raw text and validate on your own domain

Watch out for

  • Lowercasing and stripping punctuation before VADER, which throws away intensity cues.

Check yourself

  1. Which input will get the highest compound score from VADER?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: www.nltk.org/api/nltk.sentiment.vader.html

Builds on

Unlocks

Nothing builds on this yet.