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.