向量相似度算法,BM25,Jelinek-Mercer平滑

来源:互联网 发布:银行网络宣传总结报告 编辑:程序博客网 时间:2024/06/03 17:11

完整的来说,一下算法包括三个函数,分别是向量相似度基本算法,BM25,语言模型方法(Jelinek-Mercer平滑)或者叫线性插值LM
向量相似度基本算法公式为:


其中w表示权重,d表示文档。权重的计算公式为w= idf为逆文档频率

BM2公式为:

均长度。

其中,k1,b为调节因子,通常根据经验设置,一般k1=2,b=0.75

语言模型方法(Jelinek-Mercer平滑)公式为:


接下来就是具体的事例和代码:

Query:Obama health plan

Document1: Obama rejects allegations about his own bad health

Document2: The plan is to visit Obama

Document 3: Obama raisesconcerns with US health plan reforms


public class VSM {public static double sim(double d[],double w[][],int k)//计算相似度{//*d[]存的是idf同时也是每个单词在query的权重。//*k为文档iddouble simi = 0,fenzi=0,fmq,fmd=0,fenmu;int i;for(i=0;i<3;i++)fenzi=fenzi+d[i]*w[i][k];fmq=Math.sqrt(d[1]*d[1]+d[2]*d[2]);    fmd=Math.sqrt(w[0][k]*w[0][k]+w[1][k]*w[1][k]+w[2][k]*w[2][k]);fenmu=fmq*fmd;simi=fenzi/fenmu;return simi;}public static double bm25(double idf[],double w[][],int n){//*传入的n为文档id,w[][]为权重double rsv=0,b=0.25,k,leave;int k1=2,i,ld;if(n==1)ld=6;//文档2长度为6elseld=8;//文档1、3长度为8leave=(8+5+8)/3;//平均文档长度k=k1*(1-b+b*(ld/leave));        for(i=0;i<3;i++)//w[i][n]为单词i在文档n中权重        rsv=rsv+idf[i]*(((k1+1)*w[i][n])/(k+w[i][n]));//11.32公式return rsv;}public static void LM(int tf[][],int cf[],int t){//*传入的tf为每个单词出现在每个文档的概率//*传入的cf数组存储的是单词出现在文档集的次数//*传入的t为单词出现在文档集次数的总和double p1[]=new double [3];//用来存储p(t|mc)double p3[][]=new double [3][3];//用来存储p(t|md)double []pd={1,1,1};//初始化p(q|d)double []len={8,6,8};//文档1 2 3的内容长度double lmd=0.5;//随便取lanmuda为0.5int i,j;for(i=0;i<3;i++){p1[i]=cf[i]/(double)t;//公式//System.out.println(p1[i]);}for(i=0;i<3;i++){for(j=0;j<3;j++){p3[i][j]=tf[i][j]/len[j];//公式//System.out.print(p3[i][j]+" ");}//System.out.println();}for(i=0;i<3;i++){for(j=0;j<3;j++)pd[i]=pd[i]*(lmd*(p3[j][i]+p1[i]));//公式System.out.println("文档"+(i+1)+"的概率为:"+pd[i]);}}public static void main(String args[]){String q[]=new String [3];q[0]="Obama";q[1]="health";q[2]="plan";String d1[][]=new String[3][8];d1[0][0]="Obama";d1[0][1]="rejects";d1[0][2]="allegations";d1[0][3]="about";d1[0][4]="his";d1[0][5]="own";d1[0][6]="bad";d1[0][7]="health";d1[1][0]="The";d1[1][1]="plan";d1[1][2]="is";d1[1][3]="to";d1[1][4]="visit";d1[1][5]="Obama";d1[2][0]="Obama";d1[2][1]="raises";d1[2][2]="concerns ";d1[2][3]="with";d1[2][4]="US";d1[2][5]="health";d1[2][6]="plan";d1[2][7]="reforms";//*以上为初始化query和文档,下面开始进行运算int [][]tf =new int [3][3];//存单词在每个文档中出现的频率double [][]w=new double [3][3];//权重double []idf=new double [3];//逆文档频率int i,j,k,flag;for(i=0;i<3;i++)//取q中字符串for(k=0;k<3;k++)//取文档k{flag=0;for(j=0;j<8;j++)//取文档中的字符串if(q[i].equals(d1[k][j]))flag++;tf[i][k]=flag;}for(i=0;i<3;i++)//计算逆文档频率{flag=0;for(j=0;j<3;j++)if(tf[i][j]>0)//如果在这个文档出现过flag++;idf[i]=Math.log(3.0/(double) flag);}for(i=0;i<3;i++)//计算权重for(j=0;j<3;j++)w[i][j]=tf[i][j]*idf[i];//*0,1,2为文档号/*System.out.println("query和文档1的相似度为:"+sim(idf,w,0));System.out.println("query和文档2的相似度为:"+sim(idf,w,1));System.out.println("query和文档3的相似度为:"+sim(idf,w,2));*///*实验第二题的输出/*System.out.println("文档1:"+bm25(idf,w,0));System.out.println("文档2:"+bm25(idf,w,1));System.out.println("文档3:"+bm25(idf,w,2));*/////以下为第三小题int cf[]=new int [3];int t=0;for(i=0;i<3;i++){flag=0;for(j=0;j<3;j++)for(k=0;k<8;k++)if(q[i]==d1[j][k])flag++;cf[i]=flag;t=t+cf[i];//System.out.println(cf[i]+" "+t);}LM(tf,cf,t);}}




0 0
原创粉丝点击