# Sentiment Analysis

## Classifying

The OpenNLP Sentiment Analyzer can classify text into sentiment categories such as "positive" or "negative". It is based on the maximum entropy framework. For example, the text below could be classified as positive:

    I love this product it is absolutely wonderful and amazing

and the text below could be classified as negative:

    Terrible experience the worst customer service I have ever had

To be able to classify text, the sentiment analyzer needs a model. The sentiment categories are requirements-specific and defined by the training data. There are no pre-built models for sentiment analysis under the OpenNLP project.

### Sentiment Analysis Tool

The easiest way to try out the sentiment analyzer is the command line tool. The tool is only intended for demonstration and testing. The following command shows how to use the sentiment analysis tool:

    $ opennlp Sentiment model

The input is read from standard input and the predicted sentiment is written to standard output.

### Sentiment Analysis API

To perform sentiment classification you will need a model encapsulated in the `SentimentModel` class. First, load the model from an `InputStream`:

    InputStream is = ...
    SentimentModel model = new SentimentModel(is);

With the `SentimentModel` in hand, create a `SentimentME` instance and predict sentiments:

    SentimentME sentiment = new SentimentME(model);

    // Predict from a raw sentence string (tokenized internally)
    String result = sentiment.predict("I love this product");

    // Or predict from pre-tokenized input
    String[] tokens = new String[]{"I", "love", "this", "product"};
    String result2 = sentiment.predict(tokens);

    // Access the probability distribution over sentiment categories
    double[] probabilities = sentiment.probabilities(tokens);
    String bestSentiment = sentiment.getBestSentiment(probabilities);

## Training

The Sentiment Analyzer can be trained on annotated training material. The data format is one sample per line, containing the sentiment category followed by the text tokens, all separated by whitespace. The following sample shows the required format:

    positive I love this movie it is absolutely wonderful and amazing
    positive This product is great and I am very happy with it
    negative I hate this product it broke after one day of use
    negative Terrible experience the worst customer service I have ever had

### Training Tool

The following command will train the sentiment analyzer and write the model to `en-sentiment.bin`:

    $ opennlp SentimentTrainer -model en-sentiment.bin -lang en -data en-sentiment.train -encoding UTF-8

### Training API

To train a sentiment model programmatically, prepare an `ObjectStream` of `SentimentSample` objects and call the `SentimentME.train()` method:

    SentimentModel model;

    InputStreamFactory dataIn = new MarkableFileInputStreamFactory(
        new File("en-sentiment.train"));

    ObjectStream<String> lineStream =
        new PlainTextByLineStream(dataIn, StandardCharsets.UTF_8);
    ObjectStream<SentimentSample> sampleStream =
        new SentimentSampleStream(lineStream);

    model = SentimentME.train("eng", sampleStream,
        TrainingParameters.defaultParams(), new SentimentFactory());

Once trained, the model can be serialized for later use:

    try (OutputStream modelOut = new BufferedOutputStream(
        new FileOutputStream("en-sentiment.bin"))) {
      model.serialize(modelOut);
    }

## Evaluation

### Evaluation Tool

The sentiment analyzer can be evaluated against test data using the command line tool:

    $ opennlp SentimentEvaluator -model en-sentiment.bin -data en-sentiment.test -encoding UTF-8

This will output precision, recall, and F-measure statistics.

### Cross Validation

K-fold cross validation can be performed to evaluate the model without a separate test set:

    $ opennlp SentimentCrossValidator -lang en -data en-sentiment.train -encoding UTF-8 -folds 10

### Evaluation API

The evaluation API allows programmatic evaluation against a set of `SentimentSample` references:

    SentimentME sentiment = new SentimentME(model);
    SentimentEvaluator evaluator = new SentimentEvaluator(sentiment);
    evaluator.evaluate(testSampleStream);

    System.out.println(evaluator.getFMeasure());