基于n-gram字符的相似性度量

时间:2014-09-25 11:21:45

标签: java

我使用代码从单词中提取了二维词:

Scanner a = new Scanner(file1);
PrintWriter pw1= new PrintWriter(file2);  
    while (a.hasNext()) {
       String gram=a.next();
       pw1.println(gram);
       int line;
       line = gram.length(); 
       for(int x=0;x<=line-2;x++){
         pw1.println(gram.substring(x, x+2));        
       }
    }
    pw1.close();
}
catch(FileNotFoundException e) {
  System.err.format("FileNotExist");`
}

例如,&#34;学生&#34;是&#34; st&#34;,&#34; tu&#34;,&#34; ud&#34;,&#34; de&#34;,&#34; en&#34;,&#34; NT&#34 ;.

但我需要找到相似度计算。

我必须计算这些分裂克数之间的相似性值。

1 个答案:

答案 0 :(得分:7)

嗯,你不是很好地解释你的问题,但是这是我对它的看法。

首先,你的代码到处都是,即使是这个小程序,任何人都很难阅读任何内容,我会编辑它以使其可读但我不确定我是否被允许。< / p>

无论如何,bigrams =成对的字母,单词或音节(根据谷歌)。你正在寻找它的相似性值吗?

我做了一些关于它的研究,似乎你需要的算法就是这个。

Formula for finding the similarity value of the bigrams of 2 words


现在,让我们开始充实这一点。 OP,如果我误解了你的问题,请纠正我。您正在寻找单词之间的相似性,将它们分解为双字母并找到各自的相似值,是吗?如果是这样,让我们​​在开始使用它之前分解这个公式,因为它肯定会是你需要的那个。

A specific example of the formula in action for the 2 words, FRANCE and FRENCH

现在,我们有2个单词,FRANCE和FRENCH。如果将它们分解为双字母组合,我们希望找到它们的相似值。

对于法国,我们有{FR,RA,AN,NC,CE}
对于FRENCH,我们有{FR,RE,EN,NC,CH}

法国和法国意味着代表第一个等式中的s1和s2。接下来,我们将在两个双桅杆中进行匹配。我的意思是,在两个单词中都可以找到哪些双字母或双字母?在这种情况下,答案是FR和NC。

由于我们找到了2对,因此公式表示,顶部的值变为4,2乘以匹配的双字母组的数量。所以我们有4个顶部,没有别的。

现在,通过将你要比较的每个单词中的双字母组合数加起来来解决下半部分,即法国5和法语5。所以分母是10

现在,我们有什么?我们有4/10,或.4。 THAT 是我们的相似度值,这是您制作程序时需要找到的值。


让我们尝试另一个例子,只是为了将这根植入我们的头脑中,让我们说吧

s1 =“GOLIATH”
s2 =“GOALIE”

所以,使用bigrams,我们想出了Strings数组......

{ “GO”, “OL”, “LI”, “IA”, “AT”, “TH”} { “GO”, “OA”, “AL”, “LI”, “IE”}

现在,匹配的数量。这2个单词中有多少匹配的双字母?答案 - 2,GO和LI

所以,分子会有

2 x {2匹配} = 4

现在,分母,我们为歌利亚队提供了6支双腿甲龙,为守门员提供了5支双谱系。请记住,我们必须按照原始公式添加这两个值,因此我们的分母将为11。

那么,这会让我们离开?

S(GOLIATH,GOALIE)= 4 / 11~ .364&lt; -----相似值


我在这个链接下找到了公式(基本上我刚刚学到的所有东西),这让我们很容易理解。

http://www.catalysoft.com/articles/StrikeAMatch.html

我会编辑此评论,因为我需要一段时间才能为您的课程提供方法,但只是为了快速回复,如果您正在寻找有关如何操作的更多帮助,则链接是好的起点。

EDIT ****

好的,刚为它构建了方法,就在这里。

public class BiGram
{

/*

here are your imports

import java.util.Scanner;
import java.io.File;
import java.io.PrintWriter;
import java.io.FileNotFoundException;

*/
//you'll have to forgive the lack of order or common sense, I threw it 
//together fast I could cuz it sounded like you were in a rush

   public String[][] bigramizedWords = new String[2][100];

   public String[] words = new String[2];

   public File file1 = new File("file1.txt");
   public File file2 = new File("file2.txt");

   public int tracker = 0;
   public double matches = 0;
   public double denominator = 0; //This will hold the sum of the bigrams of the 2 words

   public double results;

   public Scanner a;
   public PrintWriter pw1;


   public BiGram()
   {

      initialize();
      bigramize();

      results = matches/denominator;

      pw1.println("\n\nThe Bigram Similarity value between " + words[0] + " and " + words[1] + " is " + results  + ".");


      pw1.close();


   }

   public static void main(String[] args)
   {

      BiGram b = new BiGram();


   }

   public void initialize()
   {

      try
      {

         a = new Scanner(file1);
         pw1 = new PrintWriter(file2);

         while (a.hasNext()) 
         {

            //System.out.println("Enter 2 words delimited by a space to calculate their similarity values based off of bigrams.");
            //^^^ I was going to use the above line, but I see you are using File and PrintWriter, 
            //I assume you will have the files yourself with the words to be compared

            String gram  = a.next();

            //pw1.println(gram);    -----you had this originally, we don't need this
            int line = gram.length(); 

            for(int x=0;x<=line-2;x++)
            {

               bigramizedWords[tracker][x] = gram.substring(x, x+2);
               pw1.println(gram.substring(x, x+2) + "");

            }

            pw1.println("");

            words[tracker] = gram;

            tracker++;

         }


      }

      catch(FileNotFoundException e) 
      {
         System.err.format("FileNotExist");
      }
   }

   public void bigramize()
   {

      denominator = (words[0].length() - 1) + (words[1].length() - 1); 
      //^^ Let me explain this, basically, for every word you have, let's say BABY and BALL,
      //the denominator is gonna be the sum of number of bigrams. In this case, BABY has {BA,AB,BY} or 3
      //bigrams, same for BALL, {BA,AL,LL} or 3. And the length of the word BABY is 4 letters, same 
      //with Ball. So basically, just subtract their respective lengths by 1 and add them together, and 
      //you get the number of bigrams combined from both words, or 6


      for(int k = 0; k < bigramizedWords[0].length; k++)
      {

         if(bigramizedWords[0][k] != null)
         {


            for(int i = 0; i < bigramizedWords[1].length; i++)
            {

            ///////////////////////////////////////////

               if(bigramizedWords[1][i] != null)
               {

                  if(bigramizedWords[0][k].equals(bigramizedWords[1][i]))
                  {

                     matches++;

                  }

               }

            }

         }

      }

      matches*=2;




      }

}