You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jupyter Notebook中一次性展示所有NLTK句法分析树?

批量展示NLTK句法分析树(Jupyter Notebook)

问题描述

使用上下文无关文法(CFG)进行句法分析得到多棵分析树,当前代码通过tree.draw()逐个弹出窗口展示,必须手动关闭窗口程序才会继续运行。希望能将所有分析树生成到一张图片中,在Jupyter Notebook一次性展示。

当前使用的代码:

grammar = nltk.CFG.fromstring("""
  S   -> VP NP PUN | NP VP PUN | NP PUN | VP PUN
  NP  -> ADP NP | NOUN | ADJ NP | ADV ADJ NP |ADJ | CONJ NP | NOUN NP | DET NP |ADV
  VP  -> VERB | ADV VP | ADV | VERB VP | VERB NP
  
  ADP -> 'as' | 'in' | 'along' | 'with' | 'of' | 'a'
  NOUN ->  'three' | 'parts' | 'milk' | 'oak' | 'body' | 'center' | 'stage' | 'notes' | 'date' | 'rice' | 'structure' | 'a' | 'hint' | 'blossom' | 'candy' | 'chocolate' | 'lemon' | 'thyme' | 'espresso' | 'cacao' | 'tart' | 'honeysuckle' | 'citrus' | 'apricot' | 'finish' | 'paste' | 'grapefruit' | 'cherry' | 'mouthfeel' | 'spice' | 'cup' | 'vanilla' | 'narcissus' | 'savory-tart' | 'aroma' | 'leads' | 'zest' | 'herb' | 'florals' | 'tones' | 'peppercorn' | 'intimations' | 'nib'
  PUN -> '.' | ',' | ';' | '(' | ')'
  DET -> 'the' | 'all' | 'a'
  ADV -> 'as' | 'deeply' | 'long' | 'all' | 'gently' | 'crisply' | 'richly' | 'delicately' | 'sweetly' 
  VERB -> 'evaluated' | 'take' | 'notes' | 'follow' | 'roasted' | 'dried' | 'fruit' | 'finish' | 'drying' | 'leads' | 'intensify'
  X -> 'a'
  CONJ -> 'and'
  PRT -> 'in'
  ADJ -> 'rich' | 'dark' | 'black' | 'short' | 'small' | 'sweet' | 'white' | 'floral' | 'silky' | 'pink' | 'thyme-like' | 'syrupy' | 'roasted' | 'dried' | 'floral-toned' | 'chocolaty' | 'sweet-toned' | 'cocoa-toned' | 'plush' | 'floral-driven' | 'herb-toned' | 'delicate' | 'resonant' | 'flavor-saturated'
  """)

statement = nltk.word_tokenize("Crisply sweet cocoa-toned Lemon blossom roasted cacao nib date rice candy white peppercorn in aroma and cup.")
statement = [i.lower().strip() for i in statement]

rd_parser = nltk.RecursiveDescentParser(grammar)
for pos, tree in enumerate(rd_parser.parse(statement)):
    tree.draw() 

解决方案

利用matplotlib将所有分析树绘制到同一张画布的子图中,无需逐个关闭窗口。

步骤1:安装依赖

如果未安装matplotlib,执行以下命令:

pip install matplotlib

步骤2:修改后的代码

import nltk
import matplotlib.pyplot as plt

# 原CFG文法定义(保持不变)
grammar = nltk.CFG.fromstring("""
  S   -> VP NP PUN | NP VP PUN | NP PUN | VP PUN
  NP  -> ADP NP | NOUN | ADJ NP | ADV ADJ NP |ADJ | CONJ NP | NOUN NP | DET NP |ADV
  VP  -> VERB | ADV VP | ADV | VERB VP | VERB NP
  
  ADP -> 'as' | 'in' | 'along' | 'with' | 'of' | 'a'
  NOUN ->  'three' | 'parts' | 'milk' | 'oak' | 'body' | 'center' | 'stage' | 'notes' | 'date' | 'rice' | 'structure' | 'a' | 'hint' | 'blossom' | 'candy' | 'chocolate' | 'lemon' | 'thyme' | 'espresso' | 'cacao' | 'tart' | 'honeysuckle' | 'citrus' | 'apricot' | 'finish' | 'paste' | 'grapefruit' | 'cherry' | 'mouthfeel' | 'spice' | 'cup' | 'vanilla' | 'narcissus' | 'savory-tart' | 'aroma' | 'leads' | 'zest' | 'herb' | 'florals' | 'tones' | 'peppercorn' | 'intimations' | 'nib'
  PUN -> '.' | ',' | ';' | '(' | ')'
  DET -> 'the' | 'all' | 'a'
  ADV -> 'as' | 'deeply' | 'long' | 'all' | 'gently' | 'crisply' | 'richly' | 'delicately' | 'sweetly' 
  VERB -> 'evaluated' | 'take' | 'notes' | 'follow' | 'roasted' | 'dried' | 'fruit' | 'finish' | 'drying' | 'leads' | 'intensify'
  X -> 'a'
  CONJ -> 'and'
  PRT -> 'in'
  ADJ -> 'rich' | 'dark' | 'black' | 'short' | 'small' | 'sweet' | 'white' | 'floral' | 'silky' | 'pink' | 'thyme-like' | 'syrupy' | 'roasted' | 'dried' | 'floral-toned' | 'chocolaty' | 'sweet-toned' | 'cocoa-toned' | 'plush' | 'floral-driven' | 'herb-toned' | 'delicate' | 'resonant' | 'flavor-saturated'
  """)

statement = nltk.word_tokenize("Crisply sweet cocoa-toned Lemon blossom roasted cacao nib date rice candy white peppercorn in aroma and cup.")
statement = [i.lower().strip() for i in statement]

rd_parser = nltk.RecursiveDescentParser(grammar)
# 一次性收集所有分析树,避免逐棵处理的阻塞
trees = list(rd_parser.parse(statement))
num_trees = len(trees)

# 设置子图布局:2列,行数自动计算(向上取整)
cols = 2
rows = (num_trees + cols - 1) // cols

# 创建画布,调整尺寸适配树的数量
fig, axes = plt.subplots(rows, cols, figsize=(15, 8 * rows))
axes = axes.flatten()  # 将二维子图数组转为一维,方便遍历

# 遍历每棵树,绘制到对应子图
for idx, tree in enumerate(trees):
    ax = axes[idx]
    tree.plot(ax=ax)
    ax.set_title(f"分析树 {idx+1}")

# 隐藏多余的空白子图(如果树的数量不是列数的整数倍)
for idx in range(num_trees, len(axes)):
    axes[idx].axis('off')

# 调整子图间距,避免重叠
plt.tight_layout()
# 在Jupyter Notebook中直接展示
plt.show()

关键说明

  • 先将所有分析树收集到列表trees中,避免tree.draw()的阻塞问题
  • 使用matplotlib创建网格子图,根据树的数量自动分配布局
  • 调用tree.plot(ax=ax)替代tree.draw(),将树绘制到指定子图,无需弹出独立窗口
  • 最后通过plt.show()一次性展示所有分析树

内容的提问来源于stack exchange,提问作者DumbCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 14:30:04