进阶专题

词频与候选排序

权重与词频为何是两个维度、四种调频策略的取舍、首选保护的分级逻辑,以及各引擎的记账口径

v0.116.0

方案页里那几个调频选项——「调频策略」「补全词参与调频」「热度衰减半衰期」「保护前 N 项」——单看每一项都很短,但选错组合会让候选顺序变得难以预测。本页讲清楚它们背后的模型,方案页只列选项。

两个独立的维度

清风的候选排序由两个彼此独立的量决定:

  • 权重(weight) —— 候选自带的静态排序分,来自词库文件或语言模型。这是默认排序维度
  • 词频(frequency) —— 你实际使用候选的统计(用了多少次、最近何时用)

关键在于:词频不加到 weight 上。 排序时它作为独立维度与权重组合,全程绝不修改任何候选的 weight。

这一点有实际后果:删掉某条词频记录,该候选就精确回落到它的原始位置——不会留下任何「被调过」的残留。你在词库页的「词频」子标签里删除或清空,效果是干净可逆的。

排序是分层的,词频跨不出层

候选按来源分层:整句 → 精确码短语 → 精确全码 → 简码 → 前缀补全 → …

词频的提升只在同一层内发生。 前缀补全出来的词再怎么常用,也排不到精确全码的候选之前;整句候选与精确码短语恒占顶部,根本不参与提升。

这条硬约束保证了两件事:

  • 混输方案的「五笔优先」不会被调频破坏——码表层整体压在拼音字之前,是层间隔离干的事,词频动不了它
  • 打半个码时冒出来的长词,不会因为你选过一次就永久顶掉精确匹配的字

四种调频策略

设置页上码表与英文有「调频策略」下拉,拼音没有(它固定用位次渐进)。

策略语义有无衰减
置顶(top用过一次即排到「没用过的那批」之前,已用过的内部按最近使用时间排
步进(step同样是「用过优先」,已用过的内部按累计次数排
位次渐进(position0.114 新增每用一次目标位次前移一半,久不用按半衰期回落

「置顶」与「步进」本质是同一个

两者都是布尔的「用过优先」:只要用过一次,就整体跳到未用过的那批之前,策略只决定已用过的内部怎么排。

  • 好处:立竿见影。选一次就到位,符合直觉
  • 代价:一次误选就把词顶到很显眼的位置。而且码表侧的「用过」永不衰减——错了就一直错,只能手动去词频页删掉那条记录

这在候选以精确匹配为主的场景没问题(五笔全码位就是这样)。但对前缀匹配为主的方案过于粗暴:英文几乎所有候选都是前缀匹配(打 helhello / help / helper),选过一次就顶到最前,一次误选就很显眼。这正是英文方案出厂用「位次渐进」而不是「置顶」的原因。

「位次渐进」的模型

目标位次 = 原始位次 / 2^有效使用次数
有效使用次数 = 累计次数 × 时间衰减

第 8 位 → 4 → 2 → 1 → 0,四次到顶。没有「用过 / 没用过」那道台阶,误选一次只前移一档,用得多才爬得前。

四条要点:

  • 提升速度与权重无关。 位次天生是归一化的——第 2 位就是第 2 位,与它的绝对权重是 1500 万还是 2 万无关。所以不管候选之间差 486 倍还是 2 倍,第 2 位的候选都是用一次到首位
  • 只在层内提升(见上一节)
  • 同位次时用得多的在前
  • 累计有效使用不足半次的记录不提升——避免一年前用过一次、已衰减到几乎为零的记录仍把第 2 位顶上首位

热度衰减半衰期

「热度衰减到一半所需的小时数」。某个词最后一次使用过去越久,它累积的使用次数就越不算数。出厂 0 表示用内置的 72 小时(3 天)

  • 调大 —— 久不用的词也保持靠前,适合用词稳定的人
  • 调小 —— 更贴近「最近在写什么」

这意味着用过 50 次的词,一个月不用也会完全失效

墙钟衰减的固有行为——30 天约等于 10 个半衰期。不希望如此就把半衰期调大。

只在带衰减的策略下生效:码表与英文的「位次渐进」,以及拼音(它固定带衰减)。选了「置顶」或「步进」时这一项在设置页会置灰。

码表、拼音、英文各有一份同名设置,三者完全独立、各管各的

补全词参与调频 0.114 新增

控制前缀补全出来的候选是否参与位置提升。三档:

取值语义
不参与前缀补全的候选一律不提升
仅单字/单词只提升「单个语义单元」的候选:一个汉字,或一个西文单词
全部全部提升

判据是语义单元数而不是字符数:「东西」是 2 个单元,hello 是 1 个,thank you 是 2 个。用字符数判会把英文整个挡死(hello 有 5 个字符),语义单元让同一条规则在中英文下都成立。

三种引擎的出厂值不同,各有道理:

引擎出厂为什么
拼音仅单字/单词只打半个音(如 d)时所有候选都是补全。让「的 / 得」这类单字正常上浮,但不让「东西」这种词组跑到单字前面
码表全部码表的前缀补全已由档位隔离、跨不到精确档之前,无需再收窄
英文全部英文候选本来就几乎全是前缀补全,收窄到「仅单词」等于把调频关掉大半

码表侧只在「位次渐进」下生效

「置顶」/「步进」走布尔「用过优先」,根本不读这一项,故设置页把码表的「补全词参与调频」挂在策略为「位次渐进」时才可用。拼音侧没有策略选择,只要开了调频就生效。

首选保护 0.113 新增

仅码表方案(及混输的码表侧)有。 把基础排序原本的前 N 个候选按原序回填到最前——即使某候选词频极高,不在保护集内也进不了前 N 位。

本次输入的码长分成四档:

设置项出厂说明
一简位保护前 N 项1只打 1 个编码时
二简位保护前 N 项1打 2 个编码时
三简位保护前 N 项0打 3 个编码时
全码位保护前 N 项0打 4 个及以上编码时

为什么必须分档

失守的根源是词库与调频用了两条不同的轴

词库靠权重表达简码的钦定地位(生成时给一简 9999、二简 9950、三简 9000),而调频重排的比较链不看权重,只看「有没有被选过」。五笔一简的 25 个编码每个都是二选一(如 a → 工 9999 / 戈 9998),次选字被误选一次就永久翻转,且码表侧的「用过」不衰减。

0.112 及以前只有一个标量,对所有码长一视同仁,无论取什么值都有一头顾不上:

  • 1(旧出厂值):一简二简保住了,但全码位的首选也被永久锁死,调频只对第 2 位以后有效
  • 0:全码位调频正常,但一简二简当场失守

分档之后简码位保住词库钦定的首选,全码位仍可正常调频——那里才是调频该起作用的地方。

保护名额只在精确候选里取

名额从精确匹配(编码与输入完全相同)的候选里取,不足则少保护,该码位没有精确候选就不保护。这样名额多于精确候选时,不会把前缀补全出来的长词一并钉死在前面。

老配置不会自动迁移

本次不做配置迁移。已经手动开过码表调频的用户,其用户配置里冻结着旧的 protect_top_n = 1,全码位仍然锁死,需自行在设置页把「全码位保护前 N 项」改成 0。三个新增的分级键在老配置里缺省,会自动取新默认值,故简码保护对老用户自动生效

码表调频出厂关闭,没开过的用户不受影响。

英文没有这一组:它的判据是本次输入的码长,而英文没有简码位这回事——一个 a 后面跟的是几万个词而不是钦定首选。

记账口径:用哪个编码存这条记录

词频记录按「方案 + 编码 + 文本」存储。这个「编码」三类引擎取法不同,是刻意的。

引擎记什么后果
码表你实际敲的输入码d / de / def 是三个独立码位,各自的首选独立调整
拼音候选自身的编码d 选了「东西」之后,打 dongxi 也受益
英文可选,见下——

码表用输入码,是首选保护按码长分档成立的前提——不按输入码记,就无从谈「这次输入是一简位还是全码位」。

拼音用候选码,是因为拼音下不能用输入缓冲:双拼的 siyr 与候选码 siyuan、带分隔符的 xi'anxian 都对不上,用输入码会让同一个词分裂成一堆记录。

0.114 修正了一处混淆

0.113 及以前码表侧也走候选码,导致在 de 下选中「有」(它带的是全码 def)后,打 d 时它也跟着前移。0.114 已按候选来源分流修正。

英文的记账方式可选

英文方案有一项「调频记账方式」:

取值语义效果
按整词(默认)记成 (hello, hello)hel 选过 hello 后,打 he 也受益
按编码记成 (hel, hello)各前缀独立学习,与码表同口径

这一项按候选来源生效——混输方案里混进来的英文候选同样按它记账。

混输方案怎么记

混输方案自己不拥有词库,词频也按候选来源分流:

候选来源记到哪用哪套配置
码表候选主方案(如 wubi86)名下码表方案配置
拼音候选拼音方案(pinyin)名下拼音方案配置
英文候选码表侧,与码表候选同一个方案 id英文方案配置

所以在混输下调的频,切回纯五笔照样生效——本就是同一份数据。详见混输方案配置

候选调整不是词频

两者容易混淆,但机制完全不同:

词频候选调整
怎么产生你用一次就自动记一次你显式指定
效果参与排序计算,位置随时间衰减回落硬性置顶到指定位置 / 隐藏,不衰减
存储词频表shadow 规则表
怎么撤销删掉词频记录撤销该条规则

想让某个词稳定在首位,用候选调整而不是指望调频。尤其在拼音方案下——拼音候选权重是百万级,把用户词的 weight 调到几千也压不过常用词。

拼音自 0.115 起支持置顶(前移 / 后移仍不可用,理由见词库页)。置顶排在候选装配的最后一步,能翻过拼音的匹配层级闸门,是调频做不到的;代价是它不衰减、不会自动让位,只能手动撤销。不想上硬规则的话,给那个词一个不易碰撞的精确编码仍是可选项。

相关页面

本页目录