Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

打出来的候选词顺序总是变来变去,我认为候选词的排序算法不合理 #377

Closed
fkxxyz opened this issue Jun 12, 2020 · 21 comments

Comments

@fkxxyz
Copy link

fkxxyz commented Jun 12, 2020

我发现我经常打的某些词,我以为每次都排在首位,但是时间长了之后,发现并不是排在首位了,而且也没有固定首位的功能,这会导致频繁输入错误的情况。在苦苦寻求答案,直到我看到了这篇文章 『技术贴』『改进版』小狼毫五笔自动造词、网盘同步

原来,排序并不是简单的按频率排序,而是结合最近使用该词的情况。

为什么不能就以输入频率这样简单的排序算法呢,这样很大避免输入错误进而提升输入速度。

我认为很多人需要这样的算法调整的,可能也有人不需要,我想,可不可以在配置文件中指定排序方式,来自定义如何排序,就完美地解决了这个问题。

@Ace-Who
Copy link
Contributor

Ace-Who commented Jun 13, 2020

五笔等形码的正确用法是固定词序。

@fkxxyz
Copy link
Author

fkxxyz commented Jun 13, 2020

我是简体全拼用户,希望部分词汇能够固定顺序,无论是否常用。

@lotem
Copy link
Member

lotem commented Jun 13, 2020

關閉用戶詞典可以禁用詞頻調整。
您可以在詞典文件中將字詞按完美的順序排列,並固定使用詞典中定義的順序。

@fkxxyz
Copy link
Author

fkxxyz commented Jun 13, 2020

感谢您的回复。

如果关闭用户词典的话,会失去造词功能,但对于拼音输入法来说造词功能也是至关重要。

而开启用户词典的话,候选词会按照最近使用的顺序优先排序,导致最近未使用但是最常用的词语不排在第一位了。

这是两难的选择,如果不修改源码或许无法完美解决。

目前大陆主流的简体拼音输入法,高频词都是排在第一位的而不是取决于最近使用,所以候选词序不会到处变,搜狗也支持固定首位。

我之所以很想解决这个问题,是因为作为用了十几年搜狗拼音的我,无法忍受它的大量广告和时常不稳定。而现有的 linux 端的拼音输入法也不是那么的符合自己的习惯,所以我最近在尝试基于 rime 制作一个完美接近于大陆主流习惯的简体拼音输入方案,帮助所有人摆脱和我类似的困扰。

于是我创建了这样一个项目 🍀️四叶草简体拼音输入方案

目前大多数问题大概都解决得差不多了,候选词词序的问题是现在最大的问题。

我对C++的开发也有大量的经验,所以我看了部分 librime 的源代码,定位了候选词排序的前因后果,在 dict/user_dictionary.cc的第484行 ,我将其修改成

double weight = (double)v.commits;

也就是将排序依据设为这个词语的 commit 的数量。

重新编译运行,发现达到了我想要的效果。

按照不同方案的需求,我觉得可以在配置文件中的 translator配置 添加一个配置项,名为候选词排序依据 candidate_sort_by ,仅对 script_translator 生效,可以自定义从多种排序方式里选择一种,如按词频排序、按最近使用排序等等,默认为按最近使用排序,让 rime 变得更有定制性。

这个功能涉及修改好几处代码,如果您觉得这个修改方案可行,我可以参与开发,提交 pull requests

@lotem
Copy link
Member

lotem commented Jun 16, 2020

既然改了,先用用看吧。
原先的算法可不是按最近使用排序的。從長期效果看也是高頻詞優先的,加了記憶力算法。
剛開始用時詞序變化較大,是因爲學習到的信息還不夠。
用上屏的絕對數量排序,上屏記錄較少時詞序也是不固定的,而用久了詞頻調整的效果逐漸不再顯著,基本不會調頻了。如果只是爲了固定首位,把調頻的算法搞得不太管用獲得一種近似的實現,還不如用前人研究過的多翻譯器的方法有效。

@fkxxyz
Copy link
Author

fkxxyz commented Jun 17, 2020

我确实没有好好研究原先的算法,公式有点复杂各种指数对数,是没怎么看懂。抽空好好研究研究。

不过如果在原来的算法基础上,加个固定首位的功能,也可行。我知道选中一候选词再按Ctrl+Del或Shift+Del可以删除一个词。那么用类似的方法加一个按键,来实现对一个词固定首位,你觉得怎样

@shewer
Copy link
Contributor

shewer commented Jul 19, 2020

我的作法是將 table_translator 字典 順序 固定後 權重由高往下排 最底的權重 大於八股文 約 80000
只用八股文的權重 和 用戶字典 一定被搞亂。
因為是 table_translator 重碼碼率低 且再把 一二簡碼 disable 用戶字典 。如果有三碼 特定碼再有限度加上

加上 二三碼 快鍵
常用詞組在有單字時在三 四順位即使開啟 造詞也不影響單字優先 ,目前用得還順手 太極圖的慣用語詞組也不影響單字
四碼以上單字其少 反而是詞組多

@X-hood
Copy link

X-hood commented Nov 4, 2020

五笔等形码的正确用法是固定词序。

试过固定词序,但是默认重码的排序效果并不理想。比如,对于单码,通常的五笔输入法都是首位「一级简码」,第二位「键名字根」,默认的不是这样,还有一些重码词语的,特别是一些词语和某些「罕用字」重码……这些字还排第一位,想手动的调整顺序也不知从何下手,难道只能去配置文件里一个个修改这些词的权重吗?最终还是妥协,开了调频,至少常用词能到前面来。虽然不能盲打了……折腾嘛,总要付出代价

@Ace-Who
Copy link
Contributor

Ace-Who commented Nov 25, 2020

@X-hood 可以找一份别人做好的码表。

@X-hood
Copy link

X-hood commented Nov 25, 2020

@X-hood 可以找一份别人做好的码表。

不知道谁的好,还是让它调频算了。设置一简不调,用着也还行。

@AllanZyne
Copy link

AllanZyne commented Dec 7, 2020

同样比较好奇 Rime 的候选词排序算法。
想请问一下排序算法有对这种情况优化吗?

比如我经常在输入完成(按回车)xxx 之后,然后又输入 yyy,那么,当我再次输入完成 xxx 之后,再输入 yyy 的选词是否比在输入完成 zzz 之后输入 yyy 的排序要靠前一些呢?

然后我也简单测试一下,好像没有达到我预期的效果。
测试如下:
你<确认>好<确认>你<确认>好<确认>你<确认>好<确认>你<确认>好<确认>你<确认>好<确认>
号<确认>号<确认>号<确认>号<确认>号<确认>号<确认>号<确认>号<确认>号<确认>号<确认>
你<确认>
此时 hao 的候选词是 “号” 不是 “好”

谢谢~

PS. 上面提到的排序优化好像其实是“输入预测”?请问有这样的预测功能吗?

@shiyanhui
Copy link

对于全拼来说, 这里提出一种算法.

  • 其输入行为是符合局部性原理的, 即上次选择的单词, 在这次输入中选择的概率很高.
  • 我们同样要考虑在一个拼音在一个窗口(比如最近N次选择结果)内的最终选择结果频率. 然后按照该频率从大到小排序.
    • 个人不建议使用LRU这种方式, 是因为LRU对于单次输入太敏感, 每次输入如果跟上次选择结果不一样, 就会排到第一位, 导致排序经常变动, 降低输入效率, 用户体验也比较差
    • 之所以选择一个窗口, 而不是该拼音所有的历史选择结果是因为, 每个人在不同的阶段输入偏好有可能是变化的, 统计最近使用窗口更能反映这种变动
  • 默认排序可以按照权重0, -1, -2, -3, -4, -5, .... 排序, 用户输入按最终选择结果次数来排序.

@lotem
Copy link
Member

lotem commented Feb 10, 2021

同样比较好奇 Rime 的候选词排序算法。
想请问一下排序算法有对这种情况优化吗?

比如我经常在输入完成(按回车)xxx 之后,然后又输入 yyy,那么,当我再次输入完成 xxx 之后,再输入 yyy 的选词是否比在输入完成 zzz 之后输入 yyy 的排序要靠前一些呢?

然后我也简单测试一下,好像没有达到我预期的效果。
测试如下:
你<确认>好<确认>你<确认>好<确认>你<确认>好<确认>你<确认>好<确认>你<确认>好<确认>
号<确认>号<确认>号<确认>号<确认>号<确认>号<确认>号<确认>号<确认>号<确认>号<确认>
你<确认>
此时 hao 的候选词是 “号” 不是 “好”

谢谢~

PS. 上面提到的排序优化好像其实是“输入预测”?请问有这样的预测功能吗?

​有。沒有你預期的那項功能。
目前使用靜態的語言模型做上下文調頻。用戶輸入習慣只反映在重碼候選詞的排序上。

@AllanZyne
Copy link

AllanZyne commented Feb 10, 2021

​有。沒有你預期的那項功能。
目前使用靜態的語言模型做上下文調頻。用戶輸入習慣只反映在重碼候選詞的排序上。

那么希望能作为一个功能建议吧 ( ̄∇ ̄)
个人觉得输入预测是一个能够显著改善输入体验的功能
不应该把每次输入看成相互独立的事件

@AllanZyne
Copy link

对于全拼来说, 这里提出一种算法.

  • 其输入行为是符合局部性原理的, 即上次选择的单词, 在这次输入中选择的概率很高.

  • 我们同样要考虑在一个拼音在一个窗口(比如最近N次选择结果)内的最终选择结果频率. 然后按照该频率从大到小排序.

    • 个人不建议使用LRU这种方式, 是因为LRU对于单次输入太敏感, 每次输入如果跟上次选择结果不一样, 就会排到第一位, 导致排序经常变动, 降低输入效率, 用户体验也比较差
    • 之所以选择一个窗口, 而不是该拼音所有的历史选择结果是因为, 每个人在不同的阶段输入偏好有可能是变化的, 统计最近使用窗口更能反映这种变动
  • 默认排序可以按照权重0, -1, -2, -3, -4, -5, .... 排序, 用户输入按最终选择结果次数来排序.

你这样设计也很好,很简洁的方法。
我不懂输入法算法的设计问题,只是觉得这件事很像贝叶斯模型,所有觉得如果这件事能够用贝叶斯方法解决可能比较完美。

@lotem
Copy link
Member

lotem commented Feb 10, 2021

​有。沒有你預期的那項功能。
目前使用靜態的語言模型做上下文調頻。用戶輸入習慣只反映在重碼候選詞的排序上。

那么希望能作为一个功能建议吧 ( ̄∇ ̄)
个人觉得输入预测是一个能够显著改善输入体验的功能
不应该把每次输入看成相互独立的事件

​有的。只是不會根據用戶輸入歷史來預測。

@lotem
Copy link
Member

lotem commented Feb 10, 2021

如果沒有其他事,就結案了。

是否合理,這裏談得較多是個別場景下的主觀感受。沒有一種算法能永遠符合​人的預期。而從理據上和實際用戶反饋中還沒有發現其他方案明顯優於現有的算法。

@lotem lotem closed this as completed Feb 10, 2021
@functoreality
Copy link

我这里在 custom_phrase 里就能够设置固定首位……

@AllanZyne
Copy link

如果沒有其他事,就結案了。

是否合理,這裏談得較多是個別場景下的主觀感受。沒有一種算法能永遠符合​人的預期。而從理據上和實際用戶反饋中還沒有發現其他方案明顯優於現有的算法。

抱歉,我对我的建议的看法太主观了。
这个也只是打字习惯的差异,如果习惯长句/短句输入的话或许就没有这种问题。
我想解释一下可能是我个人的习惯,之所以更习惯逐词输入是因为很不喜欢输入后再选词调整,我的习惯是在未打完之前如果看到预期的选词就直接确定输出。
其实对输入法还有的一个理想是对上下文感知,不过我想你们应该早有考虑,就不多言了。

@lotem
Copy link
Member

lotem commented Feb 23, 2021

談感受肯定是主觀的,​我想強調的重點是「個別」場景。就一種使用場景而談算法優劣,結論會有偏向性。
比方說,完全按詞頻排序就無法做到將某一個短期重複使用的同音字詞快速調整到首位,例如寫一篇文章、一本書反覆用到的專名,如果因爲詞典已有深厚的積累而要反覆多次手選,或是反之、該專名不再提及卻無法快速讓位於平時更常用的同音字詞,都會輕易地挫敗用戶對算法的信心。在設計算法時就考慮到:簡單按詞頻排序無法達成理想的效果,而將這個用例列爲一個成功算法必須要解決的問題之一。
這裏談了另一個個別場景。可知,只考慮特定的場景,沒有量化的數據,根本無法得到對算法效果的客觀評價。
至於說目前的實現,可以說是一個模擬人的記憶和遺忘過程的簡單模型。如果沒有對文句的理解等雖然舉足輕重但技術難以處理的因素,只簡單地憑記憶回答「這個音該是什麼字」的問題,則該模型可以很好地符合人的預期。理論上,完全按字頻排序是這一模型的特殊情況,即記憶強度和遺忘週期爲無窮大。但實現上不可以直接套用,代碼的邏輯依賴於權值能夠收斂。

@lotem
Copy link
Member

lotem commented Mar 17, 2024

挖墳呢?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants