whatlang4cj三元组模型揭秘:语言检测的核心算法是如何工作的
【免费下载链接】whatlang4cj一个快捷高效的自然语言检测库项目地址: https://gitcode.com/Cangjie-SIG/whatlang4cj
whatlang4cj 是一个基于 Cangjie 语言实现的快捷高效的自然语言检测库,内置三元组(Trigram)模型,可对文本自动识别81 种语言和23 种文字体系,并输出置信度评分。本文带你一步步拆解它的核心算法:从"三元组是什么"到"置信度怎么算",看完你就能真正理解这段语言的"指纹"是如何被比对出来的 🔍
一、双层检测架构:先认文字,再辨语言
whatlang4cj 的语言检测并不是一步到位的,而是聪明的两步走:
- 第一层:文字体系检测(Script Detection)——先判断文本用的是哪套书写系统:拉丁文、西里尔文、汉字、日文假名……
- 第二层:语言检测(Language Detection)——在确定文字体系后,只在该体系下的候选语言中,用三元组模型进行精确匹配
这种分层设计的好处是"缩小包围圈":比如一段西里尔文字,候选语言只可能是俄语、乌克兰语、保加利亚语等,而不是全部 81 种,既快又准。整个流程的入口在 detectWithOptions 函数中清晰可见:先调detectScript,再按文字体系分流到不同的语言档案列表。
💡 各文字体系支持的候选语言清单,完整列在 SUPPORTED_LANGUAGES.md。
二、三元组模型基础:什么是"三元组"?
所谓三元组(Trigram),就是从文本中连续摘取的3 个字符。比如英文单词 "language" 可以拆成:lan、ang、ngu、uag、agu、gua、ua……
在真正统计之前,whatlang4cj 会先对文本做一轮"清洗"(见 toTrigramRune 函数):
- 特殊字符归一化:标点、数字、符号、空白全部替换为空格(判断逻辑在 utils.cj 的 isStopRune)
- 统一小写:避免 "The" 和 "the" 被当作不同片段
- 连续空格合并:防止 "Give - IT..." 里的 " - " 这类无意义空格串产生噪声三元组
清洗完成后,count 函数用滑动窗口遍历整段文本,把每个三元组出现几次都记录下来,形成一张"频率表"。这就是这段文本的语言指纹初稿。
三、从计数到排名:给三元组"排队"
光有计数还不够,whatlang4cj 会把频率表转成排名:出现次数越多的三元组,排名越靠前(次数相同时按字典序),排名值从倒数第一编号到第一。这一步由 getTrigramsWithPositions 函数完成。
为什么用排名而不是原始次数?
- 排名与文本长短无关——长文本和短文本可以在同一把"尺子"上比较
- 排名天然放大了"高频特征":真正决定语言身份的,恰恰是那些反复出现的头部三元组
与此同时,库为每一种候选语言预存了一份"语言档案"(Language Profile):一份按频率排名好的 Top-300 三元组列表,直接编译进代码,零配置、无需加载外部数据文件。例如拉丁文字档案就在 latinLangs 定义处,西语档案以de、os、la等开头,英语档案以th、the、an开头——这些正是各语言最高频的字符组合。全部 81 种语言的档案都集中在 lang.cj 中。
四、距离计算:让每种语言"对号入座"
核心比较逻辑在 calculateDistance 函数中,规则非常优雅:
对某语言的档案列表,从第 0 位到第 299 位逐个检查:
| 情况 | 距离取值 |
|---|---|
| 该三元组在文本中存在 | 文本中它的排名 与 档案中它的位次 之差的绝对值 |
| 该三元组在文本中缺失 | 记为最大距离 300(见 constants.cj) |
最后把 300 项距离累加得到该语言的总距离。
直观理解:如果一段文本是西班牙文,那么它在文本里的三元组排名就会和"西语档案"的位次高度吻合,总距离很小;而对英语档案,排名会大面积错位甚至缺失,总距离很大。总距离最小的那个语言,就是最终答案。
五、置信度评分:如何判断结果"有多可信"?
选出最佳语言后,whatlang4cj 还要回答"这个结果有多靠谱"。calculateConfidence 函数的打分思路值得玩味:
- 按总距离升序排序,取前两名语言,分别换算成得分(得分 = 90000 − 总距离,90000 即 maxTotalDistance 常量)
- 计算领先率rate = (得分1 − 得分2) / 得分2——冠军对亚军的领先幅度
- 用一条实验校准过的双曲线把领先率映射为 0~1 的置信度:
- 领先率超过阈值
12.0 / 三元组数量 + 0.05→ 直接满分 1.0 - 低于阈值 → 按比率折算
- 若亚军得分为 0(冠军一家独大)→ 用
得分1 / 500单独计算并封顶 1.0
其中除数 500、双曲线系数 12.0 和 0.05 都是实验与常识共同校准的产物(源码注释中明确写道)。
结果封装在 Info 类中。一个实用技巧:调用isReliable()方法,它基于 0.8 的可靠置信度阈值告诉你该结果是否值得直接采用;不够可靠时,可以考虑黑白名单(Options 类)缩小范围后重试。
六、特殊捷径:一文字一语言的体系
并非所有文字体系都需要跑三元组比对。detectLangBaseOnScript 函数中有一批"直接命中"的快捷通道:
- 纯汉字 → 中文(置信度 1.0)
- 谚文 → 韩语;泰文 → 泰语;格鲁吉亚文 → 格鲁吉亚语……
这些文字体系基本被单一语言垄断,无需比对。唯一有趣的边界情况是日语:日文混用汉字与假名,detectScript 函数专门处理——即使汉字占多数被判为 Han,只要检出平假名/片假名,就改判为 HiraganaKatakana,从而正确识别出日语 🇯🇵
七、实战建议:三元组模型的适用边界
- 文本别太短:三元组模型依赖频率统计,过短文本(几个词)样本量不足,准确率明显下降。官方建议检测文本保持一定长度
- 利用黑白名单:业务场景只涉及少数几种语言时,用白名单限定可显著提升准确率
- 关注置信度:低于 0.8 的结果建议结合业务上下文二次确认
完整接口说明可参考官方文档:doc/feature_api.md
关键源码文件导航
| 模块 | 文件 | 职责 |
|---|---|---|
| 检测主流程 | src/detect.cj | 双层检测、距离计算、置信度评分 |
| 三元组实现 | src/trigrams.cj | 清洗、计数、排名 |
| 语言档案 | src/lang.cj | 81 种语言定义与 Top-300 三元组档案 |
| 文字体系检测 | src/script.cj | 23 种文字体系识别 |
| 算法常量 | src/constants.cj | 最大距离、置信度阈值 |
| 单元测试 | src/test/trigrams_test.cj | 三元组行为验证 |
总结:whatlang4cj 用"清洗 → 计数 → 排名 → 距离匹配 → 置信度校准"五步流水线,把抽象的"这是什么语言"问题转化成了直观的排名比对问题。没有网络请求、没有外部模型文件,300 个三元组档案 × 81 种语言,全部编译进库中,这就是它"快捷高效、开箱即用"的秘密所在。
【免费下载链接】whatlang4cj一个快捷高效的自然语言检测库项目地址: https://gitcode.com/Cangjie-SIG/whatlang4cj
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考