Lucene创建相似度矩阵 - 比较文档

时间:2018-03-27 09:06:27

标签: java lucene similarity information-retrieval

我有n个用户(目前只有1000个用户,将来应该超过100个&#39,000,所以它不应该效率太低)。

用户可视化为m(通常为1-10)文档。在我的第一次尝试中,我将文档串在一个字符串中。字符串包含所有不同的字母,数字和特殊字符(" /"," \ r \ n","&"," + ",...)一切皆有可能。

最后,我希望有一个nxn矩阵,其相似性得分可以将每个文档相互比较。 (对角线应该是最高分,因为它与自己最相似)

示例:

user/user| userA | userB | userC |
userA    | 1.00  | 0.94  | 0.33  |
userB    | 0.92  | 1.00  | 0.12  |
userC    | 0.35  | 0.22  | 1.00  |

这就是我想要实现的目标。我使用的是Lucene,但我认为当Lucene不能提供时,我也可以切换到另一个框架。

我做到了:

public class Similarity {

    public static void main(String[] args) throws IOException {
        UserFactory userFactory = UserFactory.getInstance();
        UserBase base = userFactory.getUserFromCsv("user.csv");
        Similarity sim = new Similarity();
        sim.indexing(base);
    }

    private StandardAnalyzer analyzer = null;
    private Directory index = null;
    private IndexWriterConfig config = null;
    private IndexWriter w = null;

    public Similarity() throws IOException {
        analyzer = new StandardAnalyzer();
        index = new RAMDirectory();
        config = new IndexWriterConfig(analyzer);
        w = new IndexWriter(index, config);
    }

    public void query(User user){
        // How??
    }


    public void indexing(UserBase base) throws IOException {
        for(User user : base.getUsers()){
                addDoc(w, user.getText(), user.getId());                
            }
        }
        w.close();
    }

    private void addDoc(IndexWriter w, String text, String id) throws IOException {
        Document doc = new Document();
        doc.add(new TextField("text", text, Field.Store.YES));
        doc.add(new StringField("id", id, Field.Store.YES));   
        w.addDocument(doc);
    }
}

User类非常简单,只有2个字段的text和id。我想比较每个用户的文字:user.getText()

我的第一次尝试是尝试普通的查询解析器:

public void query(User user){
    IndexReader reader = DirectoryReader.open(index);
    IndexSearcher searcher = new IndexSearcher(reader);
    Query q = new QueryParser("text",analyzer).parse(user.getText());
    TopDocs docs = searcher.search(q,10000);
    for(ScoreDoc hit : docs.scoreDocs){
        Document d = searcher.doc(hit.doc);
        System.out.println(d.getId() + " " + hit.score);
    }
}

此尝试的问题如下:

  1. 我必须更换所有特殊字符才能让它运行(替换" /" - 可能更多我只用一个文档测试它,我不知道将来哪个字符可能是个问题)
  2. 最相似的用户不是我用作查询的用户 - 更糟糕的是他甚至没有出现在列表中......
  3. 但是当我只使用一个子集(前20个字符)时,他找到了我用作查询的用户 - 奇怪吗?可能是我思考的一个缺陷...
  4. 但是,我不认为这是解决这个问题的最佳方法......

    我也尝试过MoreLikeThis(已经删除了代码抱歉......但它没有工作我甚至无法获得结果,即使我将所有内容与所有人进行比较,它也总是空的。)< / p>

    我是Lucene的初学者,所以我的想法可能是一些缺陷。

0 个答案:

没有答案