Kit de ferramentas de linguagem natural - classificação de texto

O que é classificação de texto?

A classificação de texto, como o nome indica, é a maneira de categorizar pedaços de texto ou documentos. Mas aqui surge a pergunta: por que precisamos usar classificadores de texto? Depois de examinar o uso da palavra em um documento ou parte do texto, os classificadores serão capazes de decidir qual rótulo de classe deve ser atribuído a ele.

Classificador Binário

Como o nome indica, o classificador binário decidirá entre dois rótulos. Por exemplo, positivo ou negativo. Nesse caso, o trecho de texto ou documento pode ser uma etiqueta ou outra, mas não ambas.

Classificador Multi-rótulo

Oposto ao classificador binário, o classificador de vários rótulos pode atribuir um ou mais rótulos a um trecho de texto ou documento.

Conjunto de recursos rotulados x não rotulados

Um mapeamento de valor-chave de nomes de recursos para valores de recursos é chamado de conjunto de recursos. Conjuntos de recursos rotulados ou dados de treinamento são muito importantes para o treinamento de classificação para que ele possa posteriormente classificar conjuntos de recursos não rotulados.

Conjunto de recursos rotulados Conjunto de recursos não rotulados
É uma tupla semelhante a (feat, label). É uma façanha em si.
É uma instância com um rótulo de classe conhecido. Sem rótulo associado, podemos chamá-lo de instância.
Usado para treinar um algoritmo de classificação. Uma vez treinado, o algoritmo de classificação pode classificar um conjunto de recursos não rotulado.

Extração de recurso de texto

A extração de recursos de texto, como o nome indica, é o processo de transformar uma lista de palavras em um conjunto de recursos que pode ser usado por um classificador. Devemos ter que transformar nosso texto em‘dict’ conjuntos de recursos de estilo porque o Natural Language Tool Kit (NLTK) espera ‘dict’ conjuntos de recursos de estilo.

Modelo Saco de Palavras (BoW)

BoW, um dos modelos mais simples em PNL, é usado para extrair os recursos de um trecho de texto ou documento para que ele possa ser usado na modelagem, como em algoritmos de ML. Basicamente, ele constrói um conjunto de recursos de presença de palavras a partir de todas as palavras de uma instância. O conceito por trás desse método é que ele não se importa com quantas vezes uma palavra ocorre ou com a ordem das palavras, ele só se importa se a palavra está presente em uma lista de palavras ou não.

Exemplo

Para este exemplo, vamos definir uma função chamada bow () -

def bow(words):
   return dict([(word, True) for word in words])

Agora vamos ligar bow()função em palavras. Salvamos essas funções em um arquivo chamado bagwords.py.

from bagwords import bow
bow(['we', 'are', 'using', 'tutorialspoint'])

Resultado

{'we': True, 'are': True, 'using': True, 'tutorialspoint': True}

Classificadores de treinamento

Nas seções anteriores, aprendemos como extrair recursos do texto. Agora podemos treinar um classificador. O primeiro e mais fácil classificador éNaiveBayesClassifier classe.

Classificador Naïve Bayes

Para prever a probabilidade de que um determinado conjunto de características pertença a um rótulo específico, ele usa o teorema de Bayes. A fórmula do teorema de Bayes é a seguinte.

$$ P (A | B) = \ frac {P (B | A) P (A)} {P (B)} $$

Aqui,

P(A|B) - É também chamada de probabilidade posterior, ou seja, a probabilidade do primeiro evento, ou seja, A ocorrer, dado que o segundo evento, ou seja, B ocorreu.

P(B|A) - É a probabilidade do segundo evento, ou seja, B ocorrer após o primeiro evento, ou seja, A ocorrer.

P(A), P(B) - É também chamada de probabilidade anterior, ou seja, a probabilidade de ocorrer o primeiro evento, ou seja, A, ou o segundo evento, ou seja, B.

Para treinar o classificador Naïve Bayes, estaremos usando o movie_reviewscorpus de NLTK. Este corpus possui duas categorias de texto, a saber:pos e neg. Essas categorias fazem de um classificador treinado nelas um classificador binário. Cada arquivo no corpus é composto de dois, um é uma crítica positiva do filme e o outro é uma crítica negativa do filme. Em nosso exemplo, vamos usar cada arquivo como uma única instância para treinar e testar o classificador.

Exemplo

Para o classificador de treinamento, precisamos de uma lista de conjuntos de recursos rotulados, que estarão na forma [(featureset, label)]. Aqui ofeatureset variável é um dict e rótulo é o rótulo de classe conhecido para o featureset. Vamos criar uma função chamadalabel_corpus() que levará um corpus chamado movie_reviewse também uma função chamada feature_detector, cujo padrão é bag of words. Ele construirá e retornará um mapeamento do formulário, {rótulo: [conjunto de recursos]}. Depois disso, usaremos esse mapeamento para criar uma lista de instâncias de treinamento rotuladas e instâncias de teste.

import collections

def label_corpus(corp, feature_detector=bow):
   label_feats = collections.defaultdict(list)
   for label in corp.categories():
      for fileid in corp.fileids(categories=[label]):
         feats = feature_detector(corp.words(fileids=[fileid]))
         label_feats[label].append(feats)
   return label_feats

Com a ajuda da função acima, obteremos um mapeamento {label:fetaureset}. Agora vamos definir mais uma função chamadasplit isso levará um mapeamento retornado de label_corpus() função e divide cada lista de conjuntos de recursos em treinamento rotulado, bem como instâncias de teste.

def split(lfeats, split=0.75):
   train_feats = []
   test_feats = []
   for label, feats in lfeats.items():
      cutoff = int(len(feats) * split)
      train_feats.extend([(feat, label) for feat in feats[:cutoff]])
      test_feats.extend([(feat, label) for feat in feats[cutoff:]])
   return train_feats, test_feats

Agora, vamos usar essas funções em nosso corpus, ou seja, movie_reviews -

from nltk.corpus import movie_reviews
from featx import label_feats_from_corpus, split_label_feats
movie_reviews.categories()

Resultado

['neg', 'pos']

Exemplo

lfeats = label_feats_from_corpus(movie_reviews)
lfeats.keys()

Resultado

dict_keys(['neg', 'pos'])

Exemplo

train_feats, test_feats = split_label_feats(lfeats, split = 0.75)
len(train_feats)

Resultado

1500

Exemplo

len(test_feats)

Resultado

500

Nós vimos isso em movie_reviewscorpus, existem 1000 arquivos pos e 1000 arquivos neg. Também acabamos com 1500 instâncias de treinamento rotuladas e 500 instâncias de teste rotuladas.

Agora vamos treinar NaïveBayesClassifier usando seu train() método de classe -

from nltk.classify import NaiveBayesClassifier
NBC = NaiveBayesClassifier.train(train_feats)
NBC.labels()

Resultado

['neg', 'pos']

Classificador de árvore de decisão

Outro classificador importante é o classificador da árvore de decisão. Aqui para treiná-loDecisionTreeClassifierclasse criará uma estrutura em árvore. Nesta estrutura em árvore, cada nó corresponde a um nome de recurso e os ramos correspondem aos valores do recurso. E descendo pelos galhos chegaremos às folhas da árvore, ou seja, aos rótulos de classificação.

Para treinar o classificador da árvore de decisão, usaremos os mesmos recursos de treinamento e teste, ou seja, train_feats e test_feats, variáveis ​​que criamos a partir de movie_reviews corpus.

Exemplo

Para treinar este classificador, vamos chamar DecisionTreeClassifier.train() método de classe da seguinte forma -

from nltk.classify import DecisionTreeClassifier
decisiont_classifier = DecisionTreeClassifier.train(
   train_feats, binary = True, entropy_cutoff = 0.8, 
   depth_cutoff = 5, support_cutoff = 30
)
accuracy(decisiont_classifier, test_feats)

Resultado

0.725

Classificador de Entropia Máxima

Outro classificador importante é MaxentClassifier que também é conhecido como conditional exponential classifier ou logistic regression classifier. Aqui para treiná-lo, oMaxentClassifier classe converterá conjuntos de recursos rotulados em vetor usando codificação.

Para treinar o classificador da árvore de decisão, usaremos os mesmos recursos de treinamento e teste, ou seja, train_featse test_feats, variáveis ​​que criamos a partir de movie_reviews corpus.

Exemplo

Para treinar este classificador, vamos chamar MaxentClassifier.train() método de classe da seguinte forma -

from nltk.classify import MaxentClassifier
maxent_classifier = MaxentClassifier
.train(train_feats,algorithm = 'gis', trace = 0, max_iter = 10, min_lldelta = 0.5)
accuracy(maxent_classifier, test_feats)

Resultado

0.786

Classificador Scikit-learn

Uma das melhores bibliotecas de aprendizado de máquina (ML) é o Scikit-learn. Na verdade, ele contém todos os tipos de algoritmos de ML para vários fins, mas todos eles têm o mesmo padrão de design de ajuste da seguinte maneira -

  • Ajustando o modelo aos dados
  • E use esse modelo para fazer previsões

Em vez de acessar os modelos scikit-learn diretamente, aqui vamos usar o NLTK SklearnClassifierclasse. Esta classe é uma classe wrapper em torno de um modelo scikit-learn para torná-lo compatível com a interface Classifier do NLTK.

Seguiremos as etapas a seguir para treinar um SklearnClassifier classe -

Step 1 - Primeiro criaremos recursos de treinamento como fizemos nas receitas anteriores.

Step 2 - Agora, escolha e importe um algoritmo de aprendizagem Scikit.

Step 3 - Em seguida, precisamos construir um SklearnClassifier classe com o algoritmo escolhido.

Step 4 - Por último, vamos treinar SklearnClassifier aula com nossos recursos de treinamento.

Vamos implementar essas etapas na receita Python abaixo -

from nltk.classify.scikitlearn import SklearnClassifier
from sklearn.naive_bayes import MultinomialNB
sklearn_classifier = SklearnClassifier(MultinomialNB())
sklearn_classifier.train(train_feats)
<SklearnClassifier(MultinomialNB(alpha = 1.0,class_prior = None,fit_prior = True))>
accuracy(sk_classifier, test_feats)

Resultado

0.885

Medindo precisão e recall

Ao treinar vários classificadores, medimos sua precisão também. Mas, além da precisão, existem várias outras métricas que são usadas para avaliar os classificadores. Duas dessas métricas sãoprecision e recall.

Exemplo

Neste exemplo, vamos calcular a precisão e a recuperação da classe NaiveBayesClassifier que treinamos anteriormente. Para conseguir isso, criaremos uma função chamada metrics_PR () que terá dois argumentos, um é o classificador treinado e o outro são os recursos de teste rotulados. Ambos os argumentos são os mesmos que passamos ao calcular a precisão dos classificadores -

import collections
from nltk import metrics
def metrics_PR(classifier, testfeats):
   refsets = collections.defaultdict(set)
   testsets = collections.defaultdict(set)
   for i, (feats, label) in enumerate(testfeats):
      refsets[label].add(i)
      observed = classifier.classify(feats)
         testsets[observed].add(i)
   precisions = {}
   recalls = {}
   for label in classifier.labels():
   precisions[label] = metrics.precision(refsets[label],testsets[label])
   recalls[label] = metrics.recall(refsets[label], testsets[label])
   return precisions, recalls

Vamos chamar esta função para encontrar a precisão e rechamada -

from metrics_classification import metrics_PR
nb_precisions, nb_recalls = metrics_PR(nb_classifier,test_feats)
nb_precisions['pos']

Resultado

0.6713532466435213

Exemplo

nb_precisions['neg']

Resultado

0.9676271186440678

Exemplo

nb_recalls['pos']

Resultado

0.96

Exemplo

nb_recalls['neg']

Resultado

0.478

Combinação de classificador e votação

Combinar classificadores é uma das melhores maneiras de melhorar o desempenho da classificação. E votar é uma das melhores maneiras de combinar vários classificadores. Para votar, precisamos ter um número ímpar de classificadores. Na seguinte receita do Python, vamos combinar três classificadores, a saber, a classe NaiveBayesClassifier, a classe DecisionTreeClassifier e a classe MaxentClassifier.

Para conseguir isso, vamos definir uma função chamada vote_classifiers () como segue.

import itertools
from nltk.classify import ClassifierI
from nltk.probability import FreqDist
class Voting_classifiers(ClassifierI):
   def __init__(self, *classifiers):
      self._classifiers = classifiers
      self._labels = sorted(set(itertools.chain(*[c.labels() for c in classifiers])))
   def labels(self):
      return self._labels
   def classify(self, feats):
      counts = FreqDist()
      for classifier in self._classifiers:
         counts[classifier.classify(feats)] += 1
      return counts.max()

Vamos chamar esta função para combinar três classificadores e encontrar a precisão -

from vote_classification import Voting_classifiers
combined_classifier = Voting_classifiers(NBC, decisiont_classifier, maxent_classifier)
combined_classifier.labels()

Resultado

['neg', 'pos']

Exemplo

accuracy(combined_classifier, test_feats)

Resultado

0.948

A partir da saída acima, podemos ver que os classificadores combinados obtiveram a maior precisão do que os classificadores individuais.