Toolkit del linguaggio naturale - Trasformazione degli alberi

Di seguito sono riportati i due motivi per trasformare gli alberi:

  • Per modificare l'albero di analisi profondo e
  • Per appiattire gli alberi di analisi profonda

Conversione di albero o sottostruttura in frase

La prima ricetta di cui parleremo qui è convertire un albero o un sottoalbero in una frase o in una stringa di blocchi. Questo è molto semplice, vediamo nel seguente esempio:

Esempio

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

Produzione

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

Appiattimento profondo dell'albero

Gli alberi profondi di frasi annidate non possono essere usati per addestrare un pezzo, quindi dobbiamo appiattirli prima dell'uso. Nell'esempio seguente, utilizzeremo la terza frase analizzata, che è un albero profondo di frasi annidate, daltreebank corpus.

Esempio

Per ottenere ciò, stiamo definendo una funzione denominata deeptree_flat()ciò richiederà un singolo albero e restituirà un nuovo albero che mantiene solo gli alberi di livello più basso. Per svolgere la maggior parte del lavoro, utilizza una funzione di supporto che abbiamo chiamatochildtree_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]))

Ora chiamiamo deeptree_flat() funzione sulla terza frase analizzata, che è un albero profondo di frasi annidate, dal file treebankcorpus. Abbiamo salvato queste funzioni in un file chiamato deeptree.py.

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

Produzione

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')]), ('.', '.')])

Albero poco profondo della costruzione

Nella sezione precedente, abbiamo appiattito un albero profondo di frasi nidificate mantenendo solo i sottoalberi di livello più basso. In questa sezione, manterremo solo i sottoalberi di livello più alto, ad esempio per costruire l'albero superficiale. Nell'esempio seguente useremo la terza frase analizzata, che è un albero profondo di frasi annidate, dal filetreebank corpus.

Esempio

Per ottenere ciò, stiamo definendo una funzione denominata tree_shallow() ciò eliminerà tutte le sottostrutture nidificate mantenendo solo le etichette delle sottostrutture superiori.

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)

Ora chiamiamo tree_shallow()funzione sulla terza frase analizzata, che è un albero profondo di frasi annidate, daltreebankcorpus. Abbiamo salvato queste funzioni in un file chiamato shallowtree.py.

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

Produzione

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')]), ('.', '.')])

Possiamo vedere la differenza con l'aiuto di ottenere l'altezza degli alberi -

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

Produzione

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

Produzione

9

Conversione delle etichette dell'albero

Negli alberi di analisi ci sono varietà di Treetipi di etichetta che non sono presenti negli alberi di blocchi. Ma mentre si utilizza l'albero di analisi per addestrare un chunker, vorremmo ridurre questa varietà convertendo alcune etichette di albero in tipi di etichetta più comuni. Ad esempio, abbiamo due sottoalberi NP alternativi, ovvero NP-SBL e NP-TMP. Possiamo convertirli entrambi in NP. Vediamo come farlo nel seguente esempio.

Esempio

Per ottenere ciò stiamo definendo una funzione denominata tree_convert() che richiede i seguenti due argomenti:

  • Albero da convertire
  • Una mappatura di conversione dell'etichetta

Questa funzione restituirà un nuovo albero con tutte le etichette corrispondenti sostituite in base ai valori nella mappatura.

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)

Ora chiamiamo tree_convert() funzione sulla terza frase analizzata, che è un albero profondo di frasi annidate, dal file treebankcorpus. Abbiamo salvato queste funzioni in un file denominatoconverttree.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)

Produzione

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('.', ['.'])])