Skip to main content

Sentiment Analysis

Sentiment analysis detects the author's emotions expressed in the text. Was the author:

  • happy (I loved it.),
  • neutral (We went to London.),
  • unhappy (The lunch was not good at all.), or
  • ambivalent (The lunch was good, but expensive.)

about their experience?

You can analyze sentiment in reviews, feedback, or customer service messages. Document-level sentiment analysis of news articles often doesn't make much sense (except for opinion pieces), as the goal isn't to determine whether the news is "good" or "bad," but rather to detect the author's opinion about the subject matter.

Our sentiment analysis is driven by practical needs—not academic purity.

Textual Sentiment

Since sentiment often cannot be expressed as a single number, we return three values (all in the range [-1.0, 1.0]):

  • mean – the average sentiment
  • pos – the positive component (ignores negative parts)
  • neg – the negative component (ignores positive parts)
{
"language": { "detected": "en" },
"docSentiment": {
"mean": 0.6,
"label": "positive",
"positive": 0.8,
"negative": -0.2
},
"usedChars": 100
}

For clearly positive or negative texts, only the (mean) matters:

meanlabelposnegtext
+0.5positive+0.5+0.0Staff was nice.
+0.7very positive+0.7+0.0Staff was absolutely astounding.
-0.5negative+0.0-0.5Food was overpriced.
-0.7very negative+0.0-0.7Food was absolutely terrible.

In theses cases, the pos and neg values don't add any extra information—they are either zero or equal to the mean.

However, ambivalent reviews are common: the author likes some things but dislikes others. In such cases, the mean alone isn't enough—pos and neg provide critical nuance.

Consider the following examples. In both cases, the overall sentiment score is 0. However, the second text is more emotionally charged—both positively and negatively. This is reflected in the higher values of the positive and negative components.

meanlabelposnegtext
+0.0ambivalent+0.3-0.3Staff was nice. Food was overpriced.
+0.0ambivalent+0.4-0.4Staff was absolutely astounding. Food was absolutely terrible.

When calculating components, passages with opposite sentiment are treated as neutral. For example, both of the following texts result in the same negative component:

meanlabelposnegtext
+0.0ambivalent+0.4-0.4Staff was absolutely astounding. The food was absolutely terrible.
-0.4negative+0.0-0.4Today is Tuesday. The food was absolutely terrible.

Sentiment Labels

Sentiment labels are included for convenience. By default, they're defined as:

  • neutral: mean in interval [-0.1, 0.1]

  • ambivalent:

    • both pos and neg are non-zero
    • neither component is significant (i.e., mean is between [-0.5, 0.5])
    • {mean: 0.0, pos: 0.4, neg: -0.4}ambivalent {mean: -0.1, pos: 0.4, neg: -0.6}ambivalent
    • {mean: -0.6, pos: 0.2, neg: -1.0}negative (dominant negativity)

A typical text contains many neutral passages, which may "dilute" overall sentiment.

Item Sentiment

In addition to overall sentiment, we also provide item-level sentiment—i.e., sentiment linked to specific entities or relations.

Currently, item sentiment is derived from the sentiment of the sentence in which the items appears. This means that sentiment may not always precisely reflect the item's evaluation.

For example, in the sentence:

Even the talented actor could not make up for the absolutely disastrous script.

... the actor may be judged negatively because the sentence as a whole is negative—even though the phrase about the actor is positive.

Sample Call

Try sentiment analysis with the following examples:

curl -X POST https://api.geneea.com/v3/analysis \
-H 'Authorization: user_key <YOUR USER KEY>' \
-H 'Content-Type: application/json' \
-d '{
"id": "1",
"text": "The trip to London was amazing. Only the food was weird. Especially the pizza was terrible.",
"analyses": ["sentiment", "entities", "relations"],
"returnItemSentiment": "true",
"domain": "voc-hospitality"
}'

Sample Response

{
"id": "1",
"language": {"detected": "en"},
"entities": [
{"id": "E0", "gkbId": "HSP-1091", "stdForm": "pizza", "type": "food"}
],
"relations": [
{"id": "R0", "name": "amazing", "textRepr": "amazing(trip)", "type": "ATTR", "args": [{"type": "SUBJECT", "name": "trip"}], "feats": {"negated": "false", "modality": ""}},
{"id": "R1", "name": "weird", "textRepr": "weird(food)", "type": "ATTR", "args": [{"type": "SUBJECT", "name": "food"}], "feats": {"negated": "false", "modality": ""}},
{"id": "R2", "name": "terrible", "textRepr": "terrible(pizza)", "type": "ATTR", "args": [{"type": "SUBJECT", "name": "pizza", "entityId": "E0"}], "feats": {"negated": "false", "modality": ""}}
],
"docSentiment": {"mean": -0.1, "label": "negative", "positive": 0.2, "negative": -0.3},
"itemSentiments": {
"E0": {"mean": -0.5, "label": "negative", "positive": 0.0, "negative": -0.5},
"R0": {"mean": 0.5, "label": "positive", "positive": 0.5, "negative": 0.0},
"R1": {"mean": -0.4, "label": "negative", "positive": 0.0, "negative": -0.4},
"R2": {"mean": -0.5, "label": "negative", "positive": 0.0, "negative": -0.5}
},
"usedChars": 100
}

Interpretation

From the response:

  • The document as a whole is slighly negative → ("docSentiment": {"mean": -0.1, "label": "negative", ...}),
  • It contains positive sentiment ("docSentiment": { ... "positive": 0.2 ... }) → ("docSentiment": { ... "negative": -0.3})
  • ...and **negative sentiment → ("E0": {"mean": -0.5, "label": "negative", "positive": 0.0, "negative": -0.5})
  • Amazing trip is judged positively → ("R0": {"mean": 0.5, "label": "positive", "positive": 0.5, "negative": 0.0})
  • Weird food is judged negatively → ("R1": {"mean": -0.4, "label": "negative", "positive": 0.0, "negative": -0.4})
  • Terrible pizza is judged negatively → ("R2": {"mean": -0.5, "label": "negative", "positive": 0.0, "negative": -0.5})

Customization

We can tailor sentiment analysis to meet your specific needs.