Como reconhecer nomes e entidades em Java

Como reconhecer nomes e entidades em Java

Em uma aplicação de Processamento de Linguagem Natural é possível que o desenvolvedor queira extrair de um texto os nomes e entidades presentes. Para isto existe uma subtarefa específica da extração de informações que é capaz de identificar estas entidades.   

A implementação deste algoritmo é chamada de NER (named-entity recognition), seu objetivo é reconhecer categorias pré-definidas como nomes de pessoas, organizações, localizações, expressões de tempo, quantidades, valores monetários, porcentagens.   

Veja um exemplo simples na língua inglesa:  

  • Jim bought 300 shares of Acme Corp. in 2006.  
  • [Jim]Person bought 300 shares of [Acme Corp.]Organization in [2006]Time.  

A criação deste tipo de software é baseado em classificadores e modelos. O classificador é treinado com uma base de dados onde nela existem diversos exemplos de objetos classificados corretamente. O próximo passo é treinar o classificador possibilitando a geração de um modelo, a partir deste modelo novas entidades fornecidas pelo usuário podem ser classificadas de acordo com o modelo criado. Esta classificação é uma predição baseada nos exemplos anteriores. 


Um exemplo prático


A universidade de Stanford criou uma implementação deste algoritmo e os treinou para reconhecer 3 classes específicas: pessoas, organizações e localizações. A entrada pode ser feita com qualquer texto e o algoritmo tentará predizer na sentença quais palavras são pessoas, organizações ou localizações.   A universidade de Stanford mantém uma ótima documentação sobre seu produto inclusive um exemplo funcional.  

Lembrando que a utilização do Stanford parser é gratuita, porém necessita que o usuário faça download de todos seus modelos e o coreNPL.   Recomendamos ainda ao desenvolvedor que acesse o site do grupo de Processamento de Linguagem Natural.

Este grupo mantém não só o NER, mas também muitas outras ferramentas muito interessantes.    Veja um exemplo de código Java:    

import edu.stanford.nlp.ie.AbstractSequenceClassifier;
import edu.stanford.nlp.ie.crf.*;
import edu.stanford.nlp.io.IOUtils;
import edu.stanford.nlp.ling.CoreLabel;
import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.sequences.DocumentReaderAndWriter;
import edu.stanford.nlp.util.Triple;

import java.util.List;


public class NERDemo {

  public static void main(String[] args) throws Exception {

    String serializedClassifier = "classifiers/english.all.3class.distsim.crf.ser.gz";

    if (args.length > 0) {
      serializedClassifier = args[0];
    }

    AbstractSequenceClassifier<CoreLabel> classifier = CRFClassifier.getClassifier(serializedClassifier);


    if (args.length > 1) {

   

      String fileContents = IOUtils.slurpFile(args[1]);
      List<List<CoreLabel>> out = classifier.classify(fileContents);
      for (List<CoreLabel> sentence : out) {
        for (CoreLabel word : sentence) {
          System.out.print(word.word() + '/' + word.get(CoreAnnotations.AnswerAnnotation.class) + ' ');
        }
        System.out.println();
      }

      System.out.println("---");
      out = classifier.classifyFile(args[1]);
      for (List<CoreLabel> sentence : out) {
        for (CoreLabel word : sentence) {
          System.out.print(word.word() + '/' + word.get(CoreAnnotations.AnswerAnnotation.class) + ' ');
        }
        System.out.println();
      }

      System.out.println("---");
      List<Triple<String, Integer, Integer>> list = classifier.classifyToCharacterOffsets(fileContents);
      for (Triple<String, Integer, Integer> item : list) {
        System.out.println(item.first() + ": " + fileContents.substring(item.second(), item.third()));
      }
      System.out.println("---");
      System.out.println("Ten best entity labelings");
      DocumentReaderAndWriter<CoreLabel> readerAndWriter = classifier.makePlainTextReaderAndWriter();
      classifier.classifyAndWriteAnswersKBest(args[1], 10, readerAndWriter);

      System.out.println("---");
      System.out.println("Per-token marginalized probabilities");
      classifier.printProbs(args[1], readerAndWriter);

    } else {

    
      String[] example = {"Good afternoon Rajat Raina, how are you today?",
                          "I go to school at Stanford University, which is located in California." };
      for (String str : example) {
        System.out.println(classifier.classifyToString(str));
      }
      System.out.println("---");

      for (String str : example) {
        // This one puts in spaces and newlines between tokens, so just print not println.
        System.out.print(classifier.classifyToString(str, "slashTags", false));
      }
      System.out.println("---");

      for (String str : example) {
        // This one is best for dealing with the output as a TSV (tab-separated column) file.
        // The first column gives entities, the second their classes, and the third the remaining text in a document
        System.out.print(classifier.classifyToString(str, "tabbedEntities", false));
      }
      System.out.println("---");

      for (String str : example) {
        System.out.println(classifier.classifyWithInlineXML(str));
      }
      System.out.println("---");

      for (String str : example) {
        System.out.println(classifier.classifyToString(str, "xml", true));
      }
      System.out.println("---");

      for (String str : example) {
        System.out.print(classifier.classifyToString(str, "tsv", false));
      }
      System.out.println("---");

      // This gets out entities with character offsets
      int j = 0;
      for (String str : example) {
        j++;
        List<Triple<String,Integer,Integer>> triples = classifier.classifyToCharacterOffsets(str);
        for (Triple<String,Integer,Integer> trip : triples) {
          System.out.printf("%s over character offsets [%d, %d) in sentence %d.%n",
                  trip.first(), trip.second(), trip.third, j);
        }
      }
      System.out.println("---");

      // This prints out all the details of what is stored for each token
      int i=0;
      for (String str : example) {
        for (List<CoreLabel> lcl : classifier.classify(str)) {
          for (CoreLabel cl : lcl) {
            System.out.print(i++ + ": ");
            System.out.println(cl.toShorterString());
          }
        }
      }
      System.out.println("---");
    }
  }
}

Vinicius dos Santos

Apenas um apaixonado por Ciência da Computação e forma com que ela pode transformar vidas!

Deixe uma resposta