Kit de ferramentas de linguagem natural - árvores em transformação

A seguir estão as duas razões para transformar as árvores -

  • Para modificar a árvore de análise profunda e
  • Para achatar árvores de análise profunda

Convertendo Árvore ou Subárvore em Frase

A primeira receita que vamos discutir aqui é converter uma Árvore ou subárvore de volta em uma frase ou string de bloco. Isso é muito simples, vamos ver no exemplo a seguir -

Exemplo

from nltk.corpus import treebank_chunk
tree = treebank_chunk.chunked_sents()[2]
' '.join([w for w, t in tree.leaves()])

Resultado

'Rudolph Agnew , 55 years old and former chairman of Consolidated Gold Fields
PLC , was named a nonexecutive director of this British industrial
conglomerate .'

Achatamento profundo da árvore

Árvores profundas de frases aninhadas não podem ser usadas para treinar um pedaço, portanto, devemos achatá-las antes de usar. No exemplo a seguir, vamos usar a terceira frase analisada, que é uma árvore profunda de frases aninhadas, dotreebank corpus.

Exemplo

Para conseguir isso, estamos definindo uma função chamada deeptree_flat()isso pegará uma única árvore e retornará uma nova árvore que mantém apenas as árvores de nível mais baixo. Para fazer a maior parte do trabalho, ele usa uma função auxiliar que chamamos dechildtree_flat().

from nltk.tree import Tree
def childtree_flat(trees):
   children = []
   for t in trees:
      if t.height() < 3:
         children.extend(t.pos())
      elif t.height() == 3:
         children.append(Tree(t.label(), t.pos()))
      else:
         children.extend(flatten_childtrees([c for c in t]))
   return children
def deeptree_flat(tree):
   return Tree(tree.label(), flatten_childtrees([c for c in tree]))

Agora vamos ligar deeptree_flat() função na terceira frase analisada, que é uma árvore profunda de frases aninhadas, do treebankcorpus. Salvamos essas funções em um arquivo denominado deeptree.py.

from deeptree import deeptree_flat
from nltk.corpus import treebank
deeptree_flat(treebank.parsed_sents()[2])

Resultado

Tree('S', [Tree('NP', [('Rudolph', 'NNP'), ('Agnew', 'NNP')]),
(',', ','), Tree('NP', [('55', 'CD'), 
('years', 'NNS')]), ('old', 'JJ'), ('and', 'CC'),
Tree('NP', [('former', 'JJ'), 
('chairman', 'NN')]), ('of', 'IN'), Tree('NP', [('Consolidated', 'NNP'), 
('Gold', 'NNP'), ('Fields', 'NNP'), ('PLC', 
'NNP')]), (',', ','), ('was', 'VBD'), 
('named', 'VBN'), Tree('NP-SBJ', [('*-1', '-NONE-')]), 
Tree('NP', [('a', 'DT'), ('nonexecutive', 'JJ'), ('director', 'NN')]),
('of', 'IN'), Tree('NP', 
[('this', 'DT'), ('British', 'JJ'), 
('industrial', 'JJ'), ('conglomerate', 'NN')]), ('.', '.')])

Construção de árvore rasa

Na seção anterior, nivelamos uma árvore profunda de frases aninhadas, mantendo apenas as subárvores de nível mais baixo. Nesta seção, vamos manter apenas as subárvores de nível mais alto, ou seja, construir a árvore rasa. No exemplo a seguir, vamos usar a terceira frase analisada, que é uma árvore profunda de frases aninhadas, dotreebank corpus.

Exemplo

Para conseguir isso, estamos definindo uma função chamada tree_shallow() isso eliminará todas as subárvores aninhadas, mantendo apenas os rótulos das subárvores superiores.

from nltk.tree import Tree
def tree_shallow(tree):
   children = []
   for t in tree:
      if t.height() < 3:
         children.extend(t.pos())
      else:
         children.append(Tree(t.label(), t.pos()))
   return Tree(tree.label(), children)

Agora vamos ligar tree_shallow()função em 3 rd frase analisado, o que é profundo árvore de frases aninhadas, a partir dotreebankcorpus. Salvamos essas funções em um arquivo chamado shallowtree.py.

from shallowtree import shallow_tree
from nltk.corpus import treebank
tree_shallow(treebank.parsed_sents()[2])

Resultado

Tree('S', [Tree('NP-SBJ-1', [('Rudolph', 'NNP'), ('Agnew', 'NNP'), (',', ','), 
('55', 'CD'), ('years', 'NNS'), ('old', 'JJ'), ('and', 'CC'), 
('former', 'JJ'), ('chairman', 'NN'), ('of', 'IN'), ('Consolidated', 'NNP'), 
('Gold', 'NNP'), ('Fields', 'NNP'), ('PLC', 'NNP'), (',', ',')]), 
Tree('VP', [('was', 'VBD'), ('named', 'VBN'), ('*-1', '-NONE-'), ('a', 'DT'), 
('nonexecutive', 'JJ'), ('director', 'NN'), ('of', 'IN'), ('this', 'DT'), 
('British', 'JJ'), ('industrial', 'JJ'), ('conglomerate', 'NN')]), ('.', '.')])

Podemos ver a diferença com a ajuda de obter a altura das árvores -

from nltk.corpus import treebank
tree_shallow(treebank.parsed_sents()[2]).height()

Resultado

3
from nltk.corpus import treebank
treebank.parsed_sents()[2].height()

Resultado

9

Conversão de rótulos de árvore

Em árvores de análise, há uma variedade de Treetipos de rótulo que não estão presentes em árvores de bloco. Mas ao usar a árvore de análise para treinar um chunker, gostaríamos de reduzir essa variedade convertendo alguns dos rótulos da Árvore em tipos de rótulos mais comuns. Por exemplo, temos duas subárvores NP alternativas, nomeadamente NP-SBL e NP-TMP. Podemos converter ambos em NP. Vamos ver como fazer isso no exemplo a seguir.

Exemplo

Para conseguir isso, estamos definindo uma função chamada tree_convert() isso leva os seguintes dois argumentos -

  • Árvore para converter
  • Um mapeamento de conversão de rótulo

Esta função retornará uma nova árvore com todos os rótulos correspondentes substituídos com base nos valores no mapeamento.

from nltk.tree import Tree
def tree_convert(tree, mapping):
   children = []
   for t in tree:
      if isinstance(t, Tree):
         children.append(convert_tree_labels(t, mapping))
      else:
         children.append(t)
   label = mapping.get(tree.label(), tree.label())
   return Tree(label, children)

Agora vamos ligar tree_convert() função na terceira frase analisada, que é uma árvore profunda de frases aninhadas, do treebankcorpus. Salvamos essas funções em um arquivo chamadoconverttree.py.

from converttree import tree_convert
from nltk.corpus import treebank
mapping = {'NP-SBJ': 'NP', 'NP-TMP': 'NP'}
convert_tree_labels(treebank.parsed_sents()[2], mapping)

Resultado

Tree('S', [Tree('NP-SBJ-1', [Tree('NP', [Tree('NNP', ['Rudolph']), 
Tree('NNP', ['Agnew'])]), Tree(',', [',']), 
Tree('UCP', [Tree('ADJP', [Tree('NP', [Tree('CD', ['55']), 
Tree('NNS', ['years'])]), 
Tree('JJ', ['old'])]), Tree('CC', ['and']), 
Tree('NP', [Tree('NP', [Tree('JJ', ['former']), 
Tree('NN', ['chairman'])]), Tree('PP', [Tree('IN', ['of']), 
Tree('NP', [Tree('NNP', ['Consolidated']), 
Tree('NNP', ['Gold']), Tree('NNP', ['Fields']), 
Tree('NNP', ['PLC'])])])])]), Tree(',', [','])]), 
Tree('VP', [Tree('VBD', ['was']),Tree('VP', [Tree('VBN', ['named']), 
Tree('S', [Tree('NP', [Tree('-NONE-', ['*-1'])]), 
Tree('NP-PRD', [Tree('NP', [Tree('DT', ['a']), 
Tree('JJ', ['nonexecutive']), Tree('NN', ['director'])]), 
Tree('PP', [Tree('IN', ['of']), Tree('NP', 
[Tree('DT', ['this']), Tree('JJ', ['British']), Tree('JJ', ['industrial']), 
Tree('NN', ['conglomerate'])])])])])])]), Tree('.', ['.'])])