Java 使用 nlp-lang 包实现基于内存的搜索提示

最近有在研究希望能够实现一个搜索框的智能搜索提示,几经辗转找到了这个包。
在这里插入图片描述

<!-- https://mvnrepository.com/artifact/org.nlpcn/nlp-lang -->
<groupId>org.nlpcn</groupId>
<artifactId>nlp-lang</artifactId>
<version>1.7.9</version>

基于这个包可以帮助我们实现一个基于内存的关键字提示功能。

介绍

核心类为 org.nlpcn.commons.lang.index.MemoryIndex,通过这个类可以帮助我们实现一个简单的倒排索引。在不考虑性能的情况下,这个类可以帮助我们实现一个开箱即用的倒排索引。

这里我们主要是针对字符串实现智能提示,编写一个封装:

public class SearchTemplate {
	/**
	 * 索引
	*/
    private final MemoryIndex<String> index;
    public SearchTemplate() {
        index = new MemoryIndex<>();
    }
    /**
     * 获取提示
     * @param key
     * @return
     */
    public Collection<String> suggest(String key) {
    	// 智能提示,允许错别字
        return index.smartSuggest(key);
    }
    /**
     * 添加记录
     * @param record 记录
     */
    public void add(String record) {
    	// 获取记录的拼音,并为记录索引
        String pinyin = String.join("", Pinyin.pinyin(record));
        // 获取记录的首字母,并为记录索引
        String firstChar = String.join("", Pinyin.firstChar(record));
        index.addItem(record, record, pinyin, firstChar);
    }
}

然后在方法中添加记录,后调用方法suggest获取建议:

public static void main(String[] args) {
    List<String> list = Arrays.asList("中国", "中华人民共和国", "美国", "我爱中国", "我是中国人", "漂亮国", "中世纪的世界", "天堂");
    SearchTemplate searchTemplate = new SearchTemplate();
    // 将记录遍历并添加的倒排索引中
    list.forEach(searchTemplate::add);
    // 获取搜索结果
    System.out.println(searchTemplate.suggest("zhong")); //[中国, 我爱中国, 我是中国人, 中世纪的世界, 中华人民共和国]
    System.out.println(searchTemplate.suggest("国")); //[中国, 美国, 漂亮国, 我爱中国, 我是中国人, 中华人民共和国, 天堂, 中世纪的世界]
    System.out.println(searchTemplate.suggest("我")); //[我爱中国, 我是中国人]
    System.out.println(searchTemplate.suggest("wa")); //[我爱中国]
    System.out.println(searchTemplate.suggest("shijie")); //[中世纪的世界]
}

由于我在封装 MemoryIndex 的时候使用到了 smartSuggest 这个方法相较于 suggest会通过查询的关键字尽可能的去匹配记录,所以你会发现有的结果与你查询的关键字完全对不上。

比如当我以 “国” 为关键字进行搜索的时候,会出现 “天堂”,“中世纪的世界” 这样记录中完全不包含 “国” 的记录。而 MemoryIndex 背后的搜索逻辑为:

  1. 使用 “国” 进行搜索,获取搜索到的结果
  2. 如果结果数量少于配置的数量,
    则获取 “国” 的全拼 “guo” 并以此作为关键字获取相匹配的记录,
    添加到搜索结果中
  3. 如果结果数量任然小于配置的数量
    则获取 “国” 的拼音首字母 “g” 并以此作为关键字获取相匹配的记录
    添加到搜索结果中

最终得到的结果就是由于记录 “天堂” 的全拼 “taintang” 和 “中世纪的世界” 的全拼 “zhongshijideshijei” 中包含 “g”,因此他们也在搜索结果中。

这里实现的功能其实很简单,而基于内存的搜索提示其实相当占用内存,比如上述的逻辑,我只输入了 7 条记录,但是 MemoryIndex 处理后保存的记录数就已经达到了惊人的 743 条结果了,这是因为MemoryIndex 会将每一种输入可能都处理成为了一条记录并保存下来,因此这样的搜索提示我们实际上是不能把它放到线上去的,但这种实现原理也为我们的开发提供了一种参考。

关于 nlp-lang 包,它提供了相当多的工具,能够帮助我们很好的处理文本,有机会可以好好研究下。

与这个包相关的还有一个

<groupId>org.ansj</groupId>
<artifactId>ansj_seg</artifactId>
<version>5.1.1</version>

这是一个可以用于实现中文分词的工具,日后也可以好好研究下。

参考资料

java 汉字拼音搜索
NLPchina/ansj_seg
nlp 项目常用工具包

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个基于OpenNLP 2.1.1版本实现训练和使用MaxEntTrainer的示例代码: 1. 首先,需要准备好训练数据和测试数据。以命名实体识别为例,训练数据和测试数据应该是类似于以下格式的文件: ``` John Smith works for Microsoft Corporation in Seattle. ``` 其中,每个文本实例都是一行,由空格分隔的标记组成。 2. 接下来,使用OpenNLP提供的工具类创建一个训练器,并指定训练参数: ```java // 创建训练器 MaxentTrainer trainer = new GenericMaxentTrainer(); // 创建训练参数 TrainingParameters params = new TrainingParameters(); params.put(TrainingParameters.ALGORITHM_PARAM, "MAXENT"); params.put(TrainingParameters.TRAINER_TYPE_PARAM, "Event"); params.put(TrainingParameters.ITERATIONS_PARAM, 100); params.put(TrainingParameters.CUTOFF_PARAM, 5); ``` 其中,训练参数括训练算法、训练器类型、迭代次数和截断频率等。 3. 加载训练数据,并将其转换为OpenNLP需要的格式: ```java // 加载训练数据 ObjectStream<String> trainStream = new PlainTextByLineStream( () -> new FileInputStream("train.txt"), StandardCharsets.UTF_8); // 将训练数据转换为OpenNLP格式 ObjectStream<NameSample> nameSampleStream = new NameSampleDataStream(trainStream) ``` 4. 使用训练器和训练数据进行训练: ```java // 训练模型 AbstractModel model = trainer.train(nameSampleStream, params); ``` 5. 加载测试数据,并将其转换为OpenNLP需要的格式: ```java // 加载测试数据 ObjectStream<String> testStream = new PlainTextByLineStream( () -> new FileInputStream("test.txt"), StandardCharsets.UTF_8); // 将测试数据转换为OpenNLP格式 ObjectStream<NameSample> testSampleStream = new NameSampleDataStream(testStream); ``` 6. 使用训练好的模型进行测试: ```java // 创建评估器 TokenNameFinderEvaluator evaluator = new TokenNameFinderEvaluator( new NameFinderME(new TokenNameFinderModel(model)), new NameFinderEvaluationMonitor() { public void missclassified(NameSample reference, Span predicted) { // 处理错误标注 } public void correctlyClassified(NameSample reference, Span predicted) { // 处理正确标注 } public void missclassified(NameSample reference, String[] predicted) { // 处理错误标注 } public void correctlyClassified(NameSample reference, String[] predicted) { // 处理正确标注 } }); // 对测试数据进行评估 evaluator.evaluate(testSampleStream); ``` 其中,评估器会根据测试数据的真实标注和模型预测的标注计算出各种评估指标。 以上就是基于OpenNLP 2.1.1版本实现训练和使用MaxEntTrainer的示例代码,希望能对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值