term vectors

Leveraging term vectors
所谓term vector, 就是对于documents的某一field,如title,body这种文本类型的, 建立词频的多维向量空间.每一个词就是一维, 这维的值就是这个词在这个field中的频率.

如果你要使用term vectors, 就要在indexing的时候对该field打开term vectors的选项:

Field options for term vectors
TermVector.YES – record the unique terms that occurred, and their counts, in each document, but do not store any positions or offsets information.
TermVector.WITH_POSITIONS – record the unique terms and their counts, and also the positions of each occurrence of every term, but no offsets.
TermVector.WITH_OFFSETS – record the unique terms and their counts, with the offsets (start & end character position) of each occurrence of every term, but no positions.
TermVector.WITH_POSITIONS_OFFSETS – store unique terms and their counts, along with positions and offsets.
TermVector.NO – do not store any term vector information.
If Index.NO is specified for a field, then you must also specify TermVector.NO.

这样在index完后, 给定这个document id和field名称, 我们就可以从IndexReader读出这个term vector(前提是你在indexing时创建了terms vector):
TermFreqVector termFreqVector = reader.getTermFreqVector(id, "subject");
你可以遍历这个TermFreqVector去取出每个词和词频, 如果你在index时选择存下offsets和positions信息的话, 你在这边也可以取到.

有了这个term vector我们可以做一些有趣的应用:
1) Books like this
比较两本书是否相似,把书抽象成一个document文件, 具有author, subject fields. 那么现在就通过这两个field来比较两本书的相似度.
author这个field是multiple fields, 就是说可以有多个author, 那么第一步就是比author是否相同,
String[] authors = doc.getValues("author");
BooleanQuery authorQuery = new BooleanQuery(); // #3
for (int i = 0; i < authors.length; i++) { // #3
    String author = authors[i]; // #3
    authorQuery.add(new TermQuery(new Term("author", author)), BooleanClause.Occur.SHOULD); // #3
}
authorQuery.setBoost(2.0f);
最后还可以把这个查询的boost值设高, 表示这个条件很重要, 权重较高, 如果作者相同, 那么就很相似了.
第二步就用到term vector了, 这里用的很简单, 单纯的看subject field的term vector中的term是否相同,
TermFreqVector vector = // #4
reader.getTermFreqVector(id, "subject"); // #4
BooleanQuery subjectQuery = new BooleanQuery(); // #4
for (int j = 0; j < vector.size(); j++) { // #4
    TermQuery tq = new TermQuery(new Term("subject", vector.getTerms()[j]));
    subjectQuery.add(tq, BooleanClause.Occur.SHOULD); // #4
}

2) What category?
这个比上个例子高级一点, 怎么分类了,还是对于document的subject, 我们有了term vector.
所以对于两个document, 我们可以比较这两个文章的term vector在向量空间中的夹角, 夹角越小说明这个两个document越相似.
那么既然是分类就有个训练的过程, 我们必须建立每个类的term vector作为个标准, 来给其它document比较.
这里用map来实现这个term vector, (term, frequency), 用n个这样的map来表示n维. 我们就要为每个category来生成一个term vector, category和term vector也可以用一个map来连接.创建这个category的term vector, 这样做:
遍历这个类中的每个document, 取document的term vector, 把它加到category的term vector上.
private void addTermFreqToMap(Map vectorMap, TermFreqVector termFreqVector) {
    String[] terms = termFreqVector.getTerms();
    int[] freqs = termFreqVector.getTermFrequencies();
    for (int i = 0; i < terms.length; i++) {
        String term = terms[i];
        if (vectorMap.containsKey(term)) {
            Integer value = (Integer) vectorMap.get(term);
            vectorMap.put(term, new Integer(value.intValue() + freqs[i]));
        } else {
            vectorMap.put(term, new Integer(freqs[i]));
        }
   }
}
首先从document的term vector中取出term和frequency的list, 然后从category的term vector中取每一个term, 把document的term frequency加上去.OK了

有了这个每个类的category, 我们就要开始计算document和这个类的向量夹角了
cos = A*B/|A||B|
A*B就是点积, 就是两个向量每一维相乘, 然后全加起来.
这里为了简便计算, 假设document中term frequency只有两种情况, 0或1.就表示出现或不出现
private double computeAngle(String[] words, String category) {
    // assume words are unique and only occur once
    Map vectorMap = (Map) categoryMap.get(category);
    int dotProduct = 0;
    int sumOfSquares = 0;
    for (int i = 0; i < words.length; i++) {
        String word = words[i];
        int categoryWordFreq = 0;
        if (vectorMap.containsKey(word)) {
            categoryWordFreq = ((Integer) vectorMap.get(word)).intValue();
        }
        dotProduct += categoryWordFreq; // optimized because we assume frequency in words is 1
        sumOfSquares += categoryWordFreq * categoryWordFreq;
    }
    double denominator;
    if (sumOfSquares == words.length) {
        // avoid precision issues for special case
        denominator = sumOfSquares; // sqrt x * sqrt x = x
    } else {
        denominator = Math.sqrt(sumOfSquares) *
        Math.sqrt(words.length);
    }
    double ratio = dotProduct / denominator;
    return Math.acos(ratio);
}
这个函数就是实现了上面那个公式还是比较简单的.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Term Vector是一个存储着文档中的术语及其位置、频率等信息的数据结构,主要用于全文搜索和文档聚类等操作。在Java中,我们可以使用Lucene或者Elasticsearch等开源搜索引擎库来实现Term Vector分词。具体实现方法如下: Lucene使用Term Vector分词 Lucene是一款Java开源搜索引擎库,它提供了丰富的API来实现Term Vector分词。我们可以使用IndexWriter类将文档索引化,并使用IndexSearcher类进行高效的全文搜索。在Lucene中,我们可以通过以下代码实现Term Vector分词: 1. 创建IndexWriterConfig对象 IndexWriterConfig config = new IndexWriterConfig(analyzer); 其中analyzer是指定的分词器,可以选择StandardAnalyzer、CJKAnalyzer等。 2. 设置Term Vector 在IndexWriterConfig中设置Term Vector: config.setTermVectors(true); config.setTermVectorPositions(true); config.setTermVectorOffsets(true); config.setTermVectorPayloads(true); 其中setTermVectors表示将Term Vector存储在文档中,setTermVectorPositions表示存储每个词项在文档中的位置,setTermVectorOffsets表示存储每个词项在文档中的偏移量,setTermVectorPayloads表示存储每个词项的负载信息。 3. 索引化文档 使用IndexWriter将文档索引化: IndexWriter writer = new IndexWriter(directory, config); writer.addDocument(doc); 其中directory是指定的索引目录,doc是待索引的文档。 4. 搜索 使用IndexSearcher进行全文搜索: IndexSearcher searcher = new IndexSearcher(reader); TermVectors termVectors = searcher.reader().getTermVectors(docID); TermVectorMapper mapper = new MyMapper(); termVectorsMapper.forEach(mapper); 其中docID是待搜索的文档ID,TermVectors是Term Vector对象,MyMapper是自定义的处理器。 Elasticsearch使用Term Vector分词 Elasticsearch是一种流行的分布式搜索和分析引擎,它基于Lucene库实现。在Elasticsearch中,我们可以使用Term Vector API实现Term Vector分词: 1. 创建Index 创建索引并指定分词器: PUT /my_index { "settings": { "analysis": { "analyzer": { "my_analyzer": { "type": "standard" } } } }, "mappings": { "properties": { "my_field": { "type": "text", "term_vector": "with_positions_offsets_payloads", "analyzer": "my_analyzer" } } } } 其中term_vector字段指定了需要存储的Term Vector属性类型,可以选择with_positions、with_offsets、with_payloads或者它们的组合。 2. 搜索 使用Term Vector API进行搜索: GET /my_index/_termvectors/1?fields=my_field&offsets=true&positions=true&payloads=true 其中1是文档ID,fields是要搜索的字段名,offsets、positions、payloads是需要的Term Vector属性类型。 总结 Term Vector分词是一种常用的全文搜索和文档聚类技术,它可以提高搜索效率、减少索引大小、提高查询精度等。在Java中,我们可以使用Lucene或者Elasticsearch等开源搜索引擎库来实现Term Vector分词。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值