simhash功能可靠吗?

时间:2015-10-16 12:54:07

标签: c# algorithm web-crawler simhash

我一直在使用simhash算法。我根据我对爬虫的理解实现了它。但是,当我做一些测试时,对我来说似乎不太可靠。

我计算了200,000个不同文本数据的指纹,看到一些不同的内容有相同的指纹。所以碰撞有很大的可能性。

我的实施代码如下。

我的问题是:如果我的实现是正确的,那么这个算法就会发生很大的冲突。谷歌怎么用这个算法?否则,我的算法有什么问题?

  public long  CalculateSimHash(string input)
        {
            var vector = GenerateVector(input);

            //5- Generate Fingerprint
            long fingerprint = 0;
            for (var i = 0; i < HashSize; i++)
            {
                if (vector[i] > 0)
                {
                    var zz = Convert.ToInt64(1 << i);
                    fingerprint += Math.Abs(zz);
                }
            }
            return fingerprint;
        }

 private int[] GenerateVector(string input)
        {
            //1- Tokenize input
            ITokeniser tokeniser = new OverlappingStringTokeniser(2, 1);
            var tokenizedValues = tokeniser.Tokenise(input);

            //2- Hash values
            var hashedValues = HashTokens(tokenizedValues);

            //3- Prepare vector
            var vector = new int[HashSize];
            for (var i = 0; i < HashSize; i++)
            {
                vector[i] = 0;
            }

            //4- Fill vector according to bitsetof hash
            foreach (var value in hashedValues)
            {
                for (var j = 0; j < HashSize; j++)
                {
                    if (IsBitSet(value, j))
                    {
                        vector[j] += 1;
                    }
                    else
                    {
                        vector[j] -= 1;
                    }
                }
            }
            return vector;

1 个答案:

答案 0 :(得分:1)

我可以看到几个问题。首先,您只获得32位散列,而不是64位散列,因为您使用了错误的类型。见https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/left-shift-operator 这里最好不要使用有符号整数类型,以避免混淆。所以:

// Generate Fingerprint
ulong fingerprint = 0;
for (int i = 0; i < HashSize; i++)
{
    if (vector[i] > 0)
    {
        fingerprint += 1UL << i;
    }
}

第二个问题是:我不知道你的OverlappingStringTokenizer是如何工作的 - 所以我只是猜测 - 但如果你的带状疱疹(重叠的ngrams)只有2个字符长,那么很多这些带状疱疹会被发现在很多文件中。有可能两个文档将共享许多这些功能,即使文档的目的和含义完全不同。

因为单词在处理文本时是最小的简单意义单位,所以我通常用单词而不是字符来计算我的标记。当然,2个字符对于有效的功能来说太小了。我喜欢用5个单词生成带状疱疹,忽略标点符号和空格。