mirror of https://gitee.com/godoos/godoos.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
79 lines
1.9 KiB
79 lines
1.9 KiB
package vector
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
)
|
|
|
|
const isNormalizedPrecisionTolerance = 1e-6
|
|
|
|
// cosineSimilarity 计算两个向量的余弦相似度。
|
|
// 向量在计算前会被归一化。
|
|
// 结果值表示相似度,值越高表示向量越相似。
|
|
func cosineSimilarity(a, b []float32) (float32, error) {
|
|
// 向量必须具有相同的长度
|
|
if len(a) != len(b) {
|
|
return 0, errors.New("向量必须具有相同的长度")
|
|
}
|
|
|
|
// 归一化向量
|
|
aNorm := normalizeVector(a)
|
|
bNorm := normalizeVector(b)
|
|
|
|
// 计算点积
|
|
dotProduct, err := dotProduct(aNorm, bNorm)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("无法计算点积: %w", err)
|
|
}
|
|
|
|
return dotProduct, nil
|
|
}
|
|
|
|
// dotProduct 计算两个向量的点积。
|
|
// 对于归一化的向量,点积等同于余弦相似度。
|
|
// 结果值表示相似度,值越高表示向量越相似。
|
|
func dotProduct(a, b []float32) (float32, error) {
|
|
// 向量必须具有相同的长度
|
|
if len(a) != len(b) {
|
|
return 0, errors.New("向量必须具有相同的长度")
|
|
}
|
|
|
|
var dotProduct float32
|
|
for i := range a {
|
|
dotProduct += a[i] * b[i]
|
|
}
|
|
|
|
return dotProduct, nil
|
|
}
|
|
|
|
// normalizeVector 归一化一个浮点数向量。
|
|
// 归一化是指将向量的每个分量除以向量的模(长度),使得归一化后的向量长度为 1。
|
|
func normalizeVector(v []float32) []float32 {
|
|
var norm float64
|
|
for _, val := range v {
|
|
norm += float64(val * val)
|
|
}
|
|
if norm == 0 {
|
|
return v // 避免除以零的情况
|
|
}
|
|
norm = math.Sqrt(norm)
|
|
|
|
res := make([]float32, len(v))
|
|
for i, val := range v {
|
|
res[i] = float32(float64(val) / norm)
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
// isNormalized 检查向量是否已经归一化。
|
|
// 如果向量的模接近 1,则认为它是归一化的。
|
|
func isNormalized(v []float32) bool {
|
|
var sqSum float64
|
|
for _, val := range v {
|
|
sqSum += float64(val) * float64(val)
|
|
}
|
|
magnitude := math.Sqrt(sqSum)
|
|
return math.Abs(magnitude-1) < isNormalizedPrecisionTolerance
|
|
}
|
|
|