Kit de ferramentas de linguagem natural - análise

Análise e sua relevância na PNL

A palavra 'análise', cuja origem é da palavra latina ‘pars’ (que significa ‘part’), é usado para extrair significado exato ou significado de dicionário do texto. Também é chamada de análise sintática ou análise de sintaxe. Comparando as regras da gramática formal, a análise de sintaxe verifica se o texto é significativo. Uma frase como “Dê-me um sorvete quente”, por exemplo, seria rejeitada pelo analisador ou analisador sintático.

Nesse sentido, podemos definir análise sintática ou sintática ou análise sintática da seguinte forma -

Pode ser definido como o processo de análise das cadeias de símbolos na linguagem natural em conformidade com as regras da gramática formal.

Podemos entender a relevância da análise em PNL com a ajuda dos seguintes pontos -

  • Parser é usado para relatar qualquer erro de sintaxe.

  • Ajuda a se recuperar de erros comuns para que o processamento do restante do programa possa ser continuado.

  • A árvore de análise é criada com a ajuda de um analisador.

  • O analisador é usado para criar uma tabela de símbolos, que desempenha um papel importante na PNL.

  • Parser também é usado para produzir representações intermediárias (IR).

Análise Profunda Vs Rasa

Análise Profunda Análise superficial
Na análise profunda, a estratégia de pesquisa fornecerá uma estrutura sintática completa para uma frase. É a tarefa de analisar uma parte limitada das informações sintáticas da tarefa fornecida.
É adequado para aplicativos de PNL complexos. Ele pode ser usado para aplicativos NLP menos complexos.
Sistemas de diálogo e resumos são exemplos de aplicativos de PNL em que a análise profunda é usada. Extração de informações e mineração de texto são exemplos de aplicativos de PNL em que a análise profunda é usada.
Também é chamado de análise completa. Também é chamado de fragmentação.

Vários tipos de analisadores

Conforme discutido, um analisador é basicamente uma interpretação procedimental da gramática. Ele encontra uma árvore ótima para a frase dada depois de pesquisar no espaço de uma variedade de árvores. Vamos ver alguns dos analisadores disponíveis abaixo -

Analisador descendente recursivo

A análise descendente recursiva é uma das formas mais simples de análise. A seguir estão alguns pontos importantes sobre o analisador descendente recursivo -

  • Ele segue um processo de cima para baixo.

  • Ele tenta verificar se a sintaxe do fluxo de entrada está correta ou não.

  • Ele lê a frase de entrada da esquerda para a direita.

  • Uma operação necessária para o analisador descendente recursivo é ler os caracteres do fluxo de entrada e combiná-los com os terminais da gramática.

Analisador de redução de deslocamento

A seguir estão alguns pontos importantes sobre o analisador shift-reduce -

  • Ele segue um processo simples de baixo para cima.

  • Ele tenta encontrar uma sequência de palavras e frases que correspondam ao lado direito de uma produção gramatical e substitui-as pelo lado esquerdo da produção.

  • A tentativa acima de encontrar uma sequência de palavras continua até que toda a frase seja reduzida.

  • Em outras palavras simples, o analisador shift-reduce começa com o símbolo de entrada e tenta construir a árvore do analisador até o símbolo inicial.

Analisador de gráfico

A seguir estão alguns pontos importantes sobre o analisador de gráfico -

  • É principalmente útil ou adequado para gramáticas ambíguas, incluindo gramáticas de línguas naturais.

  • Ele aplica programação dinâmica aos problemas de análise.

  • Por causa da programação dinâmica, os resultados hipotéticos parciais são armazenados em uma estrutura chamada 'gráfico'.

  • O 'gráfico' também pode ser reutilizado.

Analisador regexp

A análise regexp é uma das técnicas de análise mais usadas. A seguir estão alguns pontos importantes sobre o analisador Regexp -

  • Como o nome indica, ele usa uma expressão regular definida na forma de gramática no topo de uma string marcada com POS.

  • Basicamente, ele usa essas expressões regulares para analisar as sentenças de entrada e gerar uma árvore de análise a partir disso.

Exemplo

A seguir está um exemplo funcional de Regexp Parser -

import nltk
sentence = [
   ("a", "DT"),
   ("clever", "JJ"),
   ("fox","NN"),
   ("was","VBP"),
   ("jumping","VBP"),
   ("over","IN"),
   ("the","DT"),
   ("wall","NN")
]
grammar = "NP:{<DT>?<JJ>*<NN>}" 
Reg_parser = nltk.RegexpParser(grammar)
Reg_parser.parse(sentence)
Output = Reg_parser.parse(sentence)
Output.draw()

Resultado

Análise de Dependência

Análise de dependência (DP), um mecanismo moderno de análise sintática, cujo conceito principal é que cada unidade linguística, ou seja, as palavras se relacionam entre si por uma ligação direta. Esses links diretos são na verdade‘dependencies’em linguística. Por exemplo, o diagrama a seguir mostra a gramática de dependência para a frase“John can hit the ball”.

Pacote NLTK

Seguimos as duas maneiras de fazer análise de dependência com NLTK -

Probabilístico, analisador de dependência projetiva

Esta é a primeira maneira de fazer análise de dependência com NLTK. Mas esse analisador tem a restrição de treinamento com um conjunto limitado de dados de treinamento.

Analisador de Stanford

Esta é outra maneira de fazer análise de dependência com NLTK. O analisador de Stanford é um analisador de dependência de última geração. O NLTK contém um invólucro. Para usá-lo, precisamos fazer o download de duas coisas -

O analisador Stanford CoreNLP .

Modelo de idioma para o idioma desejado. Por exemplo, modelo de idioma inglês.

Exemplo

Depois de fazer o download do modelo, podemos usá-lo por meio do NLTK da seguinte maneira -

from nltk.parse.stanford import StanfordDependencyParser
path_jar = 'path_to/stanford-parser-full-2014-08-27/stanford-parser.jar'
path_models_jar = 'path_to/stanford-parser-full-2014-08-27/stanford-parser-3.4.1-models.jar'
dep_parser = StanfordDependencyParser(
   path_to_jar = path_jar, path_to_models_jar = path_models_jar
)
result = dep_parser.raw_parse('I shot an elephant in my sleep')
depndency = result.next()
list(dependency.triples())

Resultado

[
   ((u'shot', u'VBD'), u'nsubj', (u'I', u'PRP')),
   ((u'shot', u'VBD'), u'dobj', (u'elephant', u'NN')),
   ((u'elephant', u'NN'), u'det', (u'an', u'DT')),
   ((u'shot', u'VBD'), u'prep', (u'in', u'IN')),
   ((u'in', u'IN'), u'pobj', (u'sleep', u'NN')),
   ((u'sleep', u'NN'), u'poss', (u'my', u'PRP$'))
]