simhash php实现
SimHash 的 PHP 实现
SimHash 是一种用于文本相似度计算的算法,适用于海量文本去重或相似内容检测。以下是基于 PHP 的实现方法:
实现步骤
分词与权重分配 对输入文本进行分词处理,并为每个词分配权重。权重可以基于词频或 TF-IDF 计算。例如:
function tokenize($text) {
$words = preg_split('/\s+/', strtolower($text));
return array_count_values($words); // 词频作为权重
}
哈希生成 对每个分词生成 64 位的哈希值(如使用 MD5 并截取):
function hashToken($token) {
return substr(md5($token), 0, 16); // 截取16字符作为64位哈希
}
加权哈希向量 将每个词的哈希值转换为二进制,并根据权重调整向量:
function weightedHash($token, $weight) {
$hash = hashToken($token);
$binary = '';
for ($i = 0; $i < strlen($hash); $i++) {
$bin = str_pad(decbin(hexdec($hash[$i])), 4, '0', STR_PAD_LEFT);
$binary .= $bin;
}
$vector = array();
for ($i = 0; $i < strlen($binary); $i++) {
$vector[$i] = ($binary[$i] == '1') ? $weight : -$weight;
}
return $vector;
}
向量叠加 合并所有分词的加权向量:
function mergeVectors($vectors) {
$result = array_fill(0, 64, 0);
foreach ($vectors as $vector) {
for ($i = 0; $i < 64; $i++) {
$result[$i] += $vector[$i];
}
}
return $result;
}
生成 SimHash 将叠加后的向量转换为 0/1 的二进制签名:
function simhash($text) {
$tokens = tokenize($text);
$vectors = array();
foreach ($tokens as $token => $weight) {
$vectors[] = weightedHash($token, $weight);
}
$merged = mergeVectors($vectors);
$hash = '';
foreach ($merged as $bit) {
$hash .= ($bit > 0) ? '1' : '0';
}
return $hash;
}
相似度计算
通过汉明距离比较两个 SimHash 的相似度:
function hammingDistance($hash1, $hash2) {
$distance = 0;
for ($i = 0; $i < strlen($hash1); $i++) {
if ($hash1[$i] != $hash2[$i]) $distance++;
}
return $distance;
}
使用示例
$text1 = "This is a sample text";
$text2 = "This is another example text";
$hash1 = simhash($text1);
$hash2 = simhash($text2);
$distance = hammingDistance($hash1, $hash2);
echo "Similarity distance: $distance";
性能优化建议
- 对于中文文本,需先使用分词工具(如 Jieba-PHP)。
- 大规模应用时可使用 Redis 存储哈希值,加速比对。
- 通过位运算优化汉明距离计算,例如使用
gmp_hamdist函数。







