news 2026/2/22 15:59:35

开源NLP可视化库displaCy.js技术解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
开源NLP可视化库displaCy.js技术解析

displaCy.js:面向现代Web的开源NLP可视化工具

随着某中心、某机构等机构推出新服务,现在已有多种优秀的云端API可用于句法依赖分析。这些服务的一个关键部分是交互式演示,用户可以输入句子并查看标注结果。现在宣布发布displaCy.js,这是一个现代化的、独立于服务的可视化库。希望这能方便用户比较不同的服务,并探索自己的内部模型。

更新(2018年2月)
自spaCy v2.0起,displaCy可视化工具已集成到核心库中。它支持在浏览器中提供可视化、生成原始标记或在Jupyter笔记本中输出结果。更多细节,请参阅可视化工具文档。

displaCy的历史

于2015年将其作为NLP库spaCy的可视化工具推出,并于2016年8月开源了代码。

第一个版本依赖于一个旧的CSS技巧。新版本使用SVG来产生灵活且易于导出的输出。

这里有一个由新版基于SVG的displaCy渲染的句子示例。

在项目中使用displaCy.js

关于兼容性的说明
displaCy使用ECMAScript 6编写。为了获得完全的跨浏览器兼容性,请确保使用像Babel这样的编译器。更多信息,请参阅此兼容性表格。

只需包含displaCy.js,并初始化一个指定API和设置的新实例。parse(text, model, settings)方法将spaCy生成的解析结果在容器中渲染为SVG。默认情况下,它期望使用spaCy的服务(你可以免费下载和运行)。如果使用某中心的NLP API,请将format设置为'google'

// 你的APIconstapi='http://localhost:8000'// 初始化displaCyconstdisplacy=newdisplaCy(api,{container:'#displacy',format:'spacy',distance:300,offsetX:100,})// 解析句子displacy.parse('This is a sentence.','en',{collapsePunct:false,collapsePhrase:false,color:'#ffffff',bg:'#000000',})

displaCy的工作原理

一个依赖关系可视化包含三个主要组成部分:

  1. 单词及其对应的词性标签:按顺序水平显示。
  2. 弧线:不同长度的弧线连接两个单词,并带有显示其关系类型的相应标签。
  3. 箭头头部:位于每条弧线起点或终点的箭头头部,指示其方向。

关于SVG
可缩放矢量图形格式自21世纪初就已存在。与其他图像格式不同,SVG使用易于通过CSS或JavaScript操作的XML标记。SVG甚至提供了强大的颜色滤镜和动态裁剪功能,并且随着浏览器支持的改进,已在许多网站上取代了图标字体。

所有三个组件都可以使用SVG元素<path><text>来实现,其中<tspan>用于分隔文本片段,<textPath>用于将弧线标签沿着圆形的弧线路径包裹。让我们看一下第一个单词“Robots”以及连接它和“are”的箭头。这是displaCy生成的标记的一个简化示例:

示例SVG标记(节选)

<svgxmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink"><!-- 词元 --><texty="440"text-anchor="middle"><tspanx="150"fill="currentColor">Robots</tspan><tspanx="150"dy="2em"fill="currentColor">NNS</tspan></text><!-- 弧线 --><pathid="arrow-0"d="M150,400 C150,0 950,0 950,400"stroke-width="2px"stroke="currentColor"fill="none"></path><!-- 弧线标签 --><textdy="1em"><textPathxmlns:xlink="http://www.w3.org/1999/xlink"xlink:href="#arrow-0"startOffset="50%"text-anchor="middle"fill="currentColor">nsubj</textPath></text><!-- 箭头头部 --><pathd="M150,402 L144,392 156,392"fill="currentColor"></path></svg>

上面的标记是根据如下所示的JSON数据生成的:

来自API的示例JSON(节选)

{"arcs":[{"dir":"left","end":4,"label":"nsubj","start":0}],"words":[{"tag":"NNS","text":"Robots"}]}

为了将JSON格式转换为SVG标记,需要两个主要函数:一个用于绘制单词,一个用于绘制弧线。

绘制单词
渲染单词相当简单,因为它们独立于整个句子。每个单词需要两个坐标:x(距左侧的距离)和y(距顶部的距离)。从左侧的固定偏移量开始,第一个单词将放置在offsetX处,第二个单词在offsetX + distance处,第三个单词在offsetX + 2 * distance处,依此类推。这可以简化为一个简单的公式:offsetX + i * distance。暂时不要过于关注y坐标,因为它们对于所有组件几乎相同——对于单词,只是添加了一点间距,使它们不会太靠近箭头。

constoffsetX=150;// 距左侧的距离constdistance=300;// 单词间距// 遍历单词constmarkup=words.map(({text,tag},i)=>`<text y="${offsetY+wordSpacing}" text-anchor="middle"> <tspan x="${offsetX+i*distance}">${text}</tspan> <tspan x="${offsetX+i*distance}" dy="2em">${tag}</tspan> </text>`.trim()).join('');

绘制弧线
每条弧线都带有其起点和终点的索引,因此计算其长度变得很简单:end - start。这使得弧线的起点为offsetX + start * distance,终点为offsetX + (end - start) * distance。现在,如果将这些数字添加到我们的路径定义中,会得到一条连接两点的漂亮的直线:

<pathstroke="currentColor"d="M150,400 950,400"/>

曲线部分则有些棘手。对于每条曲线,需要在路径定义中添加四个额外的值:左右三次贝塞尔控制点的x和y坐标。为了展示其效果,从SitePoint复刻了这个很棒的演示。你可以移动控制点并观察它如何影响<path>标记。

曲线的高度需要适应弧线的长度。跨越三个单词的箭头需要比跨越两个单词的箭头更高——否则它们会重叠。

根据句子的语法结构,通常会有很多长度为1和2的弧线,连接单词与其下一个和第二个邻居,然后是一两条长度为3或4的弧线,可能还会有一条长度为10的大弧线。这种长依赖关系在关系从句、疑问句和标点符号中尤其常见,并且在像德语这样的语言中也很常见,动词和动词前缀经常放在从句的末尾。

错误修复说明
这个问题也是旧版displaCy中一个主要bug的原因。当时使用了一个技巧,如果句子有特别长的弧线,就按一定百分比减少整体弧线高度。然而,这有时会导致最小的弧线变得不可见。

如果仅使用弧线的长度来计算其曲线,在可视化复杂句子时会很快遇到问题:最大的箭头变得巨大并产生太多空白,使得可视化几乎无法使用。

最长的弧线与其他弧线相比非常巨大,并产生了太多空白。这里最大箭头的高度相对于其长度21来说是巨大的,即使相对于长度8的高度也足以使其比第二大箭头更高。可以通过生成所有出现长度的有序列表来解决这个问题。渲染弧线时,现在可以使用每个长度的索引(+1,从级别1开始)。

// 从集合创建数组以避免重复值并排序constlevels=[...newSet(arcs.map(({end,start})=>end-start).sort((a,b)=>a-b))];// [1, 2, 3, 4, 5, 6, 7, 21]// 获取弧线的级别constarc={dir:"right",end:28,label:"punct",start:7};constlevel=levels.indexOf(arc.end-arc.start)+1;// 8

同一句子得到了更好的结果——最大的弧线仍然是最大的。

现在可以相对于整体级别生成箭头及其曲线:

// 获取最高级别(最高长度值的索引 + 1)consthighestLevel=levels.indexOf(levels.slice(-1)[0])+1constoffsetX=150// 距左侧的距离constdistance=300// 单词间距conststartX=offsetX+start*distanceconststartY=(distance/2)*highestLevelconstendpoint=offsetX+(end-start)*distanceconstcurve=startY-((end-start)*distance)/2// 合并路径定义的值constd=`M${startX},${startY}C${startX},${curve}${endpoint},${curve}${endpoint},${startY}`// 生成路径标记constpath=`<path d="${d}" stroke-width="2px" fill="none" stroke="currentColor" ></path>`

箭头头部只是一个形成三角形的路径,放置在弧线的起点或终点。为了将标签沿着弧线路径的中间包裹,可以利用<textPath>元素并将其链接到弧线的id:

<pathid="arrow-0"d="..."></path><textPathxlink:href="#arrow-0"startOffset="50%"text-anchor="middle">Label</textPath>

使用CSS为可视化添加样式

为了允许自定义样式,SVG中包含的所有元素都带有标签和数据属性。默认情况下,使用元素的currentColor进行着色,这意味着你只需要在CSS中更改color属性。

例如,箭头具有类.displacy-arrow以及data-labeldata-dir属性。使用这些选择器的组合和一些基本的CSS逻辑,可以创建相当强大的模板来根据元素在解析中的角色和功能为其添加样式。

/* 使所有名词短语(以"NN"开头的标签)变为绿色 */.displacy-tag[data-tag^='NN']{color:green;}/* 隐藏所有不是基本形式("VB")的动词标签(以"VB"开头的标签) */.displacy-tag[data-tag^='VB']:not([data-tag='VB']){display:none;}

将displaCy与Harp或Node / Express一起使用

由于SVG图形由基本的XML组成,可以使用像Jade这样的模板引擎来动态生成标记。为此博客,编写了一个简单的mixin,可以为任何给定的解析JSON表示生成静态内联SVG。它甚至比displacy.js更紧凑(不到50行!),并且可在此处获得。它适用于基于Jade的静态网站生成器(如Harp),或使用原生支持Jade模板的Express的Node应用程序。

要使用此mixin,请将其包含在文件顶部,并使用完整的解析对象作为参数调用+displacy()

include _displacy +displacy({ arcs: [ ... ], words: [ ... ] })

要为单个弧线添加自定义类名,可以在相应的弧线对象中添加style: "classname"。已在此功能中使用了此功能,以在一张图形中说明正确的依赖关系与不正确的依赖关系。

下一步计划?

计划支持更多注释格式,如CoreNLP。同时,你可以添加自己的自定义转换器。

还推出了一个现代化且轻量级的命名实体可视化工具——敬请期待另一篇深入的博客文章!

更新(2018年2月)
自spaCy v2.0起,displaCy可视化工具已集成到核心库中。它支持在浏览器中提供可视化、生成原始标记或在Jupyter笔记本中输出结果。更多细节,请参阅可视化工具文档。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)或者 我的个人博客 https://blog.qife122.com/
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/17 3:17:00

效率对比:传统动画制作 vs Mixamo自动化流程

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个动画制作效率对比工具&#xff0c;能够记录并可视化两种工作流的时间消耗&#xff1a;1. 传统手动绑定和动画制作流程 2. 使用Mixamo的自动化流程。要求&#xff1a;1. 内…

作者头像 李华
网站建设 2026/2/22 4:22:57

1小时搭建Python异步服务原型:快马平台实践

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 我需要快速验证一个异步消息推送服务的可行性。请生成一个Python原型&#xff0c;包含&#xff1a;1) 使用websockets库的异步WebSocket服务器 2) 模拟多个客户端连接 3) 实现广播…

作者头像 李华
网站建设 2026/2/6 18:51:13

Jumpserver效率提升秘籍:5个技巧节省50%运维时间

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个Jumpserver效率工具包&#xff0c;包含&#xff1a;1. 批量用户导入/导出功能&#xff1b;2. 服务器配置模板系统&#xff1b;3. 常用操作快捷指令集&#xff1b;4. 自动化…

作者头像 李华
网站建设 2026/2/19 23:53:03

中文文本情感分析进阶:StructBERT模型调优技巧

中文文本情感分析进阶&#xff1a;StructBERT模型调优技巧 1. 引言&#xff1a;中文情感分析的挑战与机遇 随着社交媒体、电商平台和用户评论系统的普及&#xff0c;中文文本情感分析已成为自然语言处理&#xff08;NLP&#xff09;领域的重要应用方向。其核心任务是自动识别…

作者头像 李华
网站建设 2026/2/21 8:15:22

不安装TeX Live也能用:在线LaTeX环境体验

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个轻量级LaTeX环境原型&#xff0c;实现&#xff1a;1.基于Web的TeX Live核心功能 2.免安装即时使用 3.基础模板库 4.实时编译预览 5.导出PDF功能。要求能在浏览器中运行&am…

作者头像 李华
网站建设 2026/2/8 17:01:05

GitBash vs 其他终端工具:下载选择与效率对比

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个终端工具对比平台&#xff0c;专门比较GitBash与其他流行终端工具。功能包括&#xff1a;1) 下载安装步骤对比&#xff1b;2) 启动速度测试&#xff1b;3) 常用命令执行效…

作者头像 李华