如何在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
相关产品推荐
相关产品推荐

