暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

[译文] Nebula Graph:我是如何使用知识图谱破解中文单词的

原创 Wey Gu 2022-04-24
691

Wordle 这些天在社交媒体上风靡一时。Josh Wardle制作游戏允许玩家尝试六次猜测五个字母的单词,每次猜测都会以彩色瓷砖的形式给出反馈,指示字母何时匹配或占据正确位置。

我们已经看到许多使用拉丁文字的语言的 Wordle 变体,例如西班牙语 Wordle法语 Wordle德语 Wordle然而,对于像中文这样的非字母语言,简单地改编英语 Wordle 的规则是行不通的。

在大多数人更熟悉汉字或汉字的中国,Wordle 的粉丝们发明了一个本地化版本的 Wordle,名字非常巧妙:Handle。(你猜对了,它是汉字和 Wordle 的组合。)

与 Wordle 一样,Handle 允许玩家尝试 10 次来猜一个四字成语,即成语虽然英文 Wordle 使用字母及其位置来表示玩家是否猜对了,但 Handle 使用中国大陆的简体中文拼音系统来给玩家反馈。

在 Handle 中每次猜测后,每个汉字及其拼音都被标记为青色、橙色或灰色:青色表示汉字拼音部分(声母或韵母)正确且位置正确,橙色表示正确在答案中但不在正确的位置,而灰色表示它根本不在答案中。当然,每个游戏都会给出一个提示来指示角色的拼音汉字之一(取决于您希望游戏有多难)。

下面是一个如何成功播放 Handle 的示例。

处理游戏

把手助手:你的第二个大脑

在所有用于解决 Wordle 的魔法中,让我印象最深刻的是 Grant Sanderson(或 YouTube 上的 3Blue1Brown),他提供了一种使用信息论解决 Wordle的优雅而令人愉快的方法。

今天,我想写一下我是如何使用另一种方法——知识图谱来解决Handle(中文Wordle)的。该解决方案背后的想法是,我相信知识图谱是模仿我们在 Wordle 和 Handle 等游戏中如何在脑海中搜索最终答案的最佳方式。

想象一个由五个字母的单词和字母组成的知识图谱,这些单词和字母使用表示它们的关系(包含或组成)的边连接起来,游戏中的每次尝试都会给你一些线索(希望如此!)关于如何接近隐藏答案单词和字母的网络。

同样的理论也适用于 Handle。我们还可以创建成语(四字成语)和汉字的知识图谱,边连接来表示它们之间的关系。

在我们深入研究如何使用知识图解决 Handle 之前,我想先了解一下如何在没有计算机帮助的情况下玩 Handle。

我已经提到,Handle 使用拼音汉字来给玩家反馈。但是拼音很复杂,它由声母(声母;shēngmǔ)、韵母(韵母;yùnmǔ)和四分之一声组成。例如,汉字声”(sheng1)的拼音声母“ sh”和韵母“ eng”组成,其声调为首声(声1)。

对于每次猜测,每个字符可能有正确的声母,但错误的韵母。有时,如果您猜对了声母和韵母,则语气可能是错误的。例如,拼音“ sheng1”可能是“声”(声音),而拼音“ sheng4”可能是“圣” (神圣)。

让我们看看玩Handle是什么感觉:

  • 玩家有 10 次猜测正确的 4 字成语
  • 字符是要考虑的最基本的元素:
    • 例如,在下面屏幕截图的第一行中,位置 2 中的绿色字符“门”是正确的汉字并且在正确的位置。
    • 在第二行中,橙色的“仓”字是正确的汉字,但位置不正确。
  • 汉字的拼音提供了进一步的信息。但是,我们也应该知道,有时多个字符可能共享一个确切的拼音
    • 在图片的第三行中,绿色的拼音“qiao”表示成语的第一个字符发音为“ qiao”,但声调不应该是猜想的第三声。
    • 在第三行中,最后一个橙色的“ uo”表示该成语中至少有一个拼音中有最后一个“ ou”字符,但该字符不在第 2 位。

Pinyin

处理知识图谱

我不会创建一个完全自动化的 Handle 求解器。那只会扼杀游戏的乐趣。相反,我将制作一个 Handle 助手,我称之为第二个大脑,它将帮助人们了解隐藏的四字成语。

在玩英文 Wordle 时,人们可以根据已有的线索搜索五个字母的单词。例如,他们可以搜索元音最多的五个字母单词、以“sau”开头的五个字母单词或以“e”结尾的五个字母单词

在Handle(中文)中,几乎不可能根据搜索引擎中的声调和拼音首字母等提示进行搜索,因为大多数中文网页只是由汉字组成,而不是由拼音或声调组成。

正如我所提到的,这个助手的关键思想是它应该作为第二大脑,帮助人们在成语的海洋中找到答案,估计有20,000个那么问题是:我们的大脑在处理 Handle 的知识时是如何工作的(是的,双关语)?

因此,为什么不以图/神经网络的方式来做呢?在这里,让我们创建一个中国成语的知识图谱,看看它如何与 Handle 游戏配合使用。

什么是知识图谱?

简而言之,知识图谱是实体之间连接关系的网络。它最初由谷歌提出,用于回答只能通过基于知识的推理来回答的搜索查询,而不是网页的倒排索引。例如:“休斯顿火箭队赢得了多少个冠军?” 和“谁嫁给了猫王?”

如何为 Handle 构建知识图谱?

知识图谱由实体(顶点)和关系(边)组成,图数据库管理系统可以方便地对知识图谱进行索引、查询和探索。

在本文中,我将使用开源图数据库Nebula Graph来构建解决 Handle 的知识图谱。让我们从使用 Nebula Graph 对 Handle 知识图谱进行建模开始。

设置句柄知识图

为知识图建模

Handle 知识图谱的建模实际上非常简单:我只需要将游戏中的实体索引为顶点,并使用它们的关系将它们连接起来。

通常,在玩完知识图之后,您必须回来优化模式。但主要原则是不要过度设计它:只需以直观的方式进行即可。

对于我的实践,Handle 知识图谱有以下几种类型的顶点:

  • 成语(四字汉字)
  • 特点
  • pinyin
    • 音调(1、2、3、4)
  • 拼音部分
    • 类型(初始和最终)

有三种类型的边缘:

  • with_char
  • with_pinyin
  • with_pinyin_part

当然,每种类型的顶点和边都会有自己的属性。例如,顶点“成语”会有一个VID,它是Nebula Graph中的唯一标识符;它的拼音由声母、韵母和声调数字表示(如上面提到的拼音“sheng4”)。

下面的草图是 Handle 知识图谱的模式的粗略表示。 

知识图谱架构

建模之后,我们需要做的就是对数据进行收集、清理和索引。

我从游戏的GitHub 存储库中提取了 Handle 中使用的通用习语集我使用PyPinyin,一个开源 Python 库,将成语转换成他们的拼音PyPinyin 也可用于将拼音实体拆分为声母和韵母。

这是该项目的 Github 存储库:https ://github.com/wey-gu/chinese-graph

部署星云图

您可以使用Nebula-UP仅使用一行代码部署 Nebula Graph。


git clone https://github.com/wey-gu/chinese-graph.git && cd chinese-graph


加载数据

# Get the code from the Github repo and load generate the data
 
git clone https://github.com/wey-gu/chinese-graph.git && cd chinese-graph
 
python3 graph_data_generator.py # generate the Handle knowledge graph data
 
# load data into Nebula Graph with Nebula-Importer
docker run --rm -ti \
    --network=nebula-docker-compose_nebula-net \
    -v ${PWD}/importer_conf.yaml:/root/importer_conf.yaml \
    -v ${PWD}/output:/root \
    vesoft/nebula-importer:v3.0.0 \
    --config /root/importer_conf.yaml



用知识图玩句柄

准备好所有设置后,让我们开始用我们的第二个大脑玩游戏。

现在让我们访问Handle游戏。假设我们使用成语“爱憎分明”作为我们的第一个猜测。输入成语后,我们得到第一批提示:

处理提示

不错,现在我们有一些信息提示:

  • 4声有一个字尾“ ai”,但不在1位,也不是“爱”
  • 声调 1 中有一个字符,但位置 2 中没有。
  • 有一个字符带有最后的“ ing”,但该字符不在位置 4。
  • 第 4 个字符在声调 2 中。

让我们将这些提示翻译成 Nebula Graph 的nGQL查询语言


# There is one character with the final of *"ai"* in tone 4, but it is not in position 1 (starting from 0 in the query)  and it is not *"爱"*.
(char0:character)<-[with_char_0:with_character]-(x:idiom)-[with_pinyin_0:with_pinyin]->(pinyin_0:character_pinyin)-[:with_pinyin_part]->(final_part_0:pinyin_part{part_type: "final"})
WHERE id(final_part_0) == "ai" AND pinyin_0.character_pinyin.tone == 4 AND with_pinyin_0.position != 0 AND with_char_0.position != 0 AND id(char0) != "爱"
 
# There is one character in tone 1 but it is not in position 2.
MATCH (x:idiom) -[with_pinyin_1:with_pinyin]->(pinyin_1:character_pinyin)
WHERE pinyin_1.character_pinyin.tone == 1 AND with_pinyin_1.position != 1
 
#There is one character with the final “ing”, but the character is not in position 4.
MATCH (x:idiom) -[with_pinyin_2:with_pinyin]->(:character_pinyin)-[:with_pinyin_part]->(final_part_2:pinyin_part{part_type: "final"})
WHERE id(final_part_2) == "ing" AND with_pinyin_2.position != 3
 
# The 4th character is in tone 2.
MATCH (x:idiom) -[with_pinyin_3:with_pinyin]->(pinyin_3:character_pinyin)
WHERE pinyin_3.character_pinyin.tone == 2 AND with_pinyin_3.position == 3
 
RETURN x, count(x) as c ORDER BY c DESC


在将这些查询输入到运行我们的 Handle 知识图谱的 Nebula Graph 实例中之后,现在我们有七个可以在第二次猜测中使用的替代习语!

("惊愚骇俗" :idiom{pinyin: "['jing1', 'yu2', 'hai4', 'su2']"})
("惊世骇俗" :idiom{pinyin: "['jing1', 'shi4', 'hai4', 'su2']"})
("惊见骇闻" :idiom{pinyin: "['jing1', 'jian4', 'hai4', 'wen2']"})
("沽名卖直" :idiom{pinyin: "['gu1', 'ming2', 'mai4', 'zhi2']"})
("惊心骇神" :idiom{pinyin: "['jing1', 'xin1', 'hai4', 'shen2']"})
("荆棘载途" :idiom{pinyin: "['jing1', 'ji2', 'zai4', 'tu2']"})
("出卖灵魂" :idiom{pinyin: "['chu1', 'mai4', 'ling2', 'hun2']"})

Let’s give the idiom "惊世骇俗" a try.

处理尝试 1

And here we go, we got the final answer. It is "惊世骇俗".

让我们用另一天的 Handle(3 月 1 日)再试一次。

My first guess was "一言为定". And we got the following feedback:

处理反馈

这可以翻译成以下 nGQL 语句:


# There is one character that is not in the first position whose pinyin final is "i" in the first tone, but its pinyin is not "yi"
MATCH (x:idiom) -[with_pinyin_0:with_pinyin]->(char_pinyin_0:character_pinyin)-[:with_pinyin_part]->(final_part_0:pinyin_part{part_type: "final"})
WHERE id(final_part_0) == "i" AND char_pinyin_0.character_pinyin.tone == 1 AND with_pinyin_0.position != 0 AND id(char_pinyin_0) != "yi1"

# There is one character whose pinyin initial is "d," but the character is not in the 4th position
MATCH (x:idiom) -[with_pinyin_1:with_pinyin]->(:character_pinyin)-[:with_pinyin_part]->(initial_part_1:pinyin_part{part_type: "initial"})
WHERE id(initial_part_1) == "d" AND with_pinyin_1.position != 3

# The third character is in tone 2, but its pinyin is not "wei"
MATCH (x:idiom) -[with_pinyin_2:with_pinyin]->(char_pinyin_2:character_pinyin)
WHERE char_pinyin_2.character_pinyin.tone == 2 AND id(char_pinyin_2) != "wei2" AND with_pinyin_2.position == 2
 
RETURN x



这是我们得到的:

("堆积如山" :idiom{pinyin: "['dui1', 'ji1', 'ru2', 'shan1']"})
("丹漆随梦" :idiom{pinyin: "['dan1', 'qi1', 'sui2', 'meng4']"})
("植党营私" :idiom{pinyin: "['zhi2', 'dang3', 'ying2', 'si1']"})
("结党营私" :idiom{pinyin: "['jie2', 'dang3', 'ying2', 'si1']"})
("堆案盈几" :idiom{pinyin: "['dui1', 'an4', 'ying2', 'ji1']"})
("涓滴成河" :idiom{pinyin: "['juan1', 'di1', 'cheng2', 'he2']"})
("当之无愧" :idiom{pinyin: "['dang1', 'zhi1', 'wu2', 'kui4']"})
("荡析离居" :idiom{pinyin: "['dang4', 'xi1', 'li2', 'ju1']"})
("路断人稀" :idiom{pinyin: "['lu4', 'duan4', 'ren2', 'xi1']"})
("地广人稀" :idiom{pinyin: "['di4', 'guang3', 'ren2', 'xi1']"})
("地广人希" :idiom{pinyin: "['di4', 'guang3', 'ren2', 'xi1']"})
("地旷人稀" :idiom{pinyin: "['di4', 'kuang4', 'ren2', 'xi1']"})
("大失人望" :idiom{pinyin: "['da4', 'shi1', 'ren2', 'wang4']"})
("得不酬失" :idiom{pinyin: "['de2', 'bu4', 'chou2', 'shi1']"})
("得失荣枯" :idiom{pinyin: "['de2', 'shi1', 'rong2', 'ku1']"})
("独木难支" :idiom{pinyin: "['du2', 'mu4', 'nan2', 'zhi1']"})
("不得而知" :idiom{pinyin: "['bu4', 'de2', 'er2', 'zhi1']"})
("班师得胜" :idiom{pinyin: "['ban1', 'shi1', 'de2', 'sheng4']"})
("是非得失" :idiom{pinyin: "['shi4', 'fei1', 'de2', 'shi1']"})
("鸡虫得失" :idiom{pinyin: "['ji1', 'chong2', 'de2', 'shi1']"})
("锋镝余生" :idiom{pinyin: "['feng1', 'di1', 'yu2', 'sheng1']"})
("心到神知" :idiom{pinyin: "['xin1', 'dao4', 'shen2', 'zhi1']"})
("小大由之" :idiom{pinyin: "['xiao3', 'da4', 'you2', 'zhi1']"})
("水滴石穿" :idiom{pinyin: "['shui3', 'di1', 'shi2', 'chuan1']"})
("天打雷劈" :idiom{pinyin: "['tian1', 'da3', 'lei2', 'pi1']"})

Let’s try the idiom "首当其冲" this time.

处理尝试 2

同样,让我们尝试将线索翻译成 nGQL:


# There is one character whose pinyin initial is "ch"
MATCH (x:idiom) -[:with_pinyin]->(:character_pinyin)-[:with_pinyin_part]->(initial_part_0:pinyin_part{part_type: "initial"})
WHERE id(initial_part_0) == "ch"
 
# There is one character whose pinyin initial is "d"
MATCH (x:idiom) -[:with_pinyin]->(:character_pinyin)-[:with_pinyin_part]->(initial_part_1:pinyin_part{part_type: "initial"})
WHERE id(initial_part_1) == "d"
 
# There is one character whose *pinyin* initial is "sh"
MATCH (x:idiom) -[:with_pinyin]->(:character_pinyin)-[:with_pinyin_part]->(initial_part_2:pinyin_part{part_type: "initial"})
WHERE id(initial_part_2) == "sh"
 
# The third character is in tone 2
MATCH (x:idiom) -[with_pinyin3:with_pinyin]->(char_pinyin3:character_pinyin)
WHERE char_pinyin3.character_pinyin.tone == 2 AND with_pinyin3.position == 2
 
# The fourth character is in tone 1
MATCH (x:idiom) -[with_pinyin4:with_pinyin]->(char_pinyin4:character_pinyin)
WHERE char_pinyin4.character_pinyin.tone == 1 AND with_pinyin4.position == 3
 
# There is one character whose Pinyin final is "ang"
MATCH (x:idiom) -[:with_pinyin]->(:character_pinyin)-[:with_pinyin_part]->(final_part_5:pinyin_part{part_type: "final"})
WHERE id(final_part_5) == "ang"
 
RETURN x


我们得到了三个可能的结果:

("适当其冲" :idiom{pinyin: "['shi4', 'dang1', 'qi2', 'chong1']"})
("得不偿失" :idiom{pinyin: "['de2', 'bu4', 'chang2', 'shi1']"})
("首当其冲" :idiom{pinyin: "['shou3', 'dang1', 'qi2', 'chong1']"})

Let’s try the idiom "首当其冲".

还有宾果游戏!我们明白了。

处理尝试 3

下一步是什么?

如果你碰巧对图数据库感兴趣,可以查看 Github 上的Nebula Graph项目。

Nebula Graph 将很快推出 Visual Builder,使用户能够在拖放界面中生成 nGQL 查询。如果您还不熟悉 nGQL 等图形查询语言,则可以使用无代码工具更轻松地探索 Handle 知识图谱。如果您对新功能感兴趣,请加入我们的Slack 频道,以便在它准备就绪时收到提醒。

星云图可视化生成器


我也会在后续文章中分享更多可视化的Handle玩法,敬请期待。


文章来源:

https://dzone.com/articles/how-i-cracked-chinese-wordle-using-knowledge-graph

最后修改时间:2022-04-24 11:25:59
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论