当前位置: 首页 > 工具软件 > LingPipe > 使用案例 >

(7)使用Lucene、LingPipe做实体链接(Entity Linking)——根据用户输入进行entity recognition/linking

马国源
2023-12-01


应一些同学的要求,把最终的代码都贴出来了。。。。

一般不讲那么多东西,直接贴代码,想看原理直接找官网,文末有链接和参考文献。


public Map<String, String> EntityRecognition(String submitData) throws Exception
	{
		Map<String , String> returnDataMap = new TreeMap<String , String>(new LengthSort());
		String returnData="";
		int theFirstTime=0;
		HashMap<String, Integer> submitDataMAP = new HashMap<String, Integer>();
		
		Chunking chunking = entityDictionaryChunkerFF.chunk(submitData);
		for (Chunk chunk : chunking.chunkSet()) {
			int start = chunk.start();
			int end = chunk.end();
			String entity = submitData.substring(start,end); //find one entity
			System.out.println("start: "+start+" end: "+end+" entity: "+entity);
			//如果有些entity之前已经识别出来,就没必要在做检测了。
			//因为对于同一段用户输入,同样的entity,识别出的maxEntity一定一样。
			if(returnDataMap.containsKey(entity)) 
			{
				continue;
			}
			
			String ambiguationEntitysStr=FindAmbiguationEntity(entity); //judge if this entity is a ambiguation one
			if(ambiguationEntitysStr.equals("0")) //the entity is not a ambiguation one
			{			    	 
				returnData+=entity+"=>";
				System.out.println("returnData: "+returnData);
				returnDataMap.put(entity, entity);
			}
			else //消歧处理
			{
				if(theFirstTime==0)
				{
					//对submitData分词
					String tempWord="";
					@SuppressWarnings("resource")
					Analyzer analyzer = new StandardAnalyzer();					
					TokenStream ts=analyzer.tokenStream("", submitData); //注意,已经自动转成小写了
					CharTermAttribute cta = ts.addAttribute(CharTermAttribute.class);
					ts.reset();
					while(ts.incrementToken())
					{
						//System.out.println(cta.toString());
						tempWord=cta.toString();
						//if(tempWord.length()<4) //跟.py文件的预处理保持一致
						//{
						//	continue;
						//}
						if(submitDataMAP.containsKey(tempWord))
						{
							submitDataMAP.put(tempWord, submitDataMAP.get(tempWord)+1);
						}
						else
						{
							submitDataMAP.put(tempWord, 1);
						}
					}
					ts.close();
					theFirstTime++;
					System.out.println("submitDataMAP: "+submitDataMAP.toString());
				}
				
				String[] ambiguationEntitys=ambiguationEntitysStr.split("<=");
				int maxScore=-1,tempScore=-1;
				String maxEntity="",tempEntity="";
				for(int i=0;i<ambiguationEntitys.length;i++) //对所有可能的entity,使用abstract上下文选择最有可能的一个entity
				{
					tempEntity=ambiguationEntitys[i];
					tempScore=CaculateScoreForDisambiguation(tempEntity, submitDataMAP);					
					if(maxScore<tempScore)
					{
						maxScore=tempScore;
						maxEntity=tempEntity;
						System.out.println("tempEntity: "+tempEntity+"=>tempScore:"+tempScore);
					}
				}
				returnData+=entity+":"+maxEntity+"=>";//对于有ambiguation的entity,需要把原来的entity也返回,然后再index.jsp中用maxEntity替换原来的entity
				System.out.println("returnData: "+returnData);
				returnDataMap.put(entity, maxEntity);
			}
		}
		//return returnData;
		return returnDataMap;
	}
		
	//find if one entity is a ambiguation one
	//if yes, return all candidate ambiguation entitys
	public static String FindAmbiguationEntity(String entity) throws Exception
	{
		//Term是搜索的基本单位,一个 Term对象有两个 String类型的域组成。
		//生成一个 Term对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 
		//其中第一个参数代表了要在文档的哪一个 Field上进行查找,第二个参数代表了要查询的关键词。
		//注意,如果不是用QueryParser,则不对”queryWord”进行任何解析,这里正是采用了这个特质才替换了上面的搜索方式!!!
		Term term = new Term("entity", entity.toLowerCase()); //转换为小写
		//TermQuery 是抽象类 Query 的一个子类,它同时也是 Lucene支持的最为基本的一个查询类。
		//生成一个 TermQuery对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 
		//它的构造函数只接受一个参数,那就是一个 Term对象。
        TermQuery termQuery = new TermQuery(term);
        System.out.println("Searching for: " + termQuery.toString());
        
		TopDocs results=ambiguationEntitySearcher.search(termQuery, 1); //这边search有问题,一直search不上。。。。
		
		ScoreDoc[] hits=results.scoreDocs;
		//System.out.println("hits.length=>"+hits.length);
		if(hits.length==0) //the entity is not a ambiguation one
		{
			return "0";
		}
		else
		{
			Document doc=ambiguationEntitySearcher.doc(hits[0].doc);
			System.out.println("entity: " + doc.get("entity"));
			System.out.println("ambiguationEntitys: " + doc.get("ambiguationEntitys"));
			return doc.get("ambiguationEntitys");
		}
	}


关于函数“CaculateScoreForDisambiguation()”的代码就不贴了,每个人都有自己的办法,我的比较挫。。。

思路就是为每一个歧义实体   根据其所在的上下文   与   用户输入的上下文   之间的相似度去判断哪个歧义实体更有可能。。。



参考文献:

[1] Mendes, Pablo N, Jakob, Max, Garc&#, et al. DBpedia spotlight: Shedding light on the web of documents[C]// Proceedings of the 7th International Conference on Semantic Systems. ACM, 2011:1-8.

[2] Han X, Sun L. A Generative Entity-Mention Model for Linking Entities with Knowledge Base.[J]. Proceeding of Acl, 2011:945-954.

[3] http://lucene.apache.org/

[4] http://alias-i.com/lingpipe/demos/tutorial/ne/read-me.html

[5] http://wiki.dbpedia.org/Downloads2014

[6] http://www.oschina.net/p/jieba(结巴分词)


 类似资料: