特征向量相似度和距离计算方法

感谢作者:http://www.cppblog.com/unixfy/archive/2012/02/13/165487.html

/*
特征向量相似度和距离的计算

相似度:
·夹角余弦
·相关系数
·Dice
·Jaccard

距离
·明氏距离
·欧氏距离
·马氏距离
·Jffreys & Matusita 距离
·Mahalanobis 距离,未实现,协方差矩阵
·Camberra 距离(Lance 距离,Williams 距离)
*/

#include <iostream>
#include <vector>
#include <cassert>
#include <cmath>
using namespace std;

double dotProduct(const vector<double>& v1, const vector<double>& v2)
{
    assert(v1.size() == v2.size());
    double ret = 0.0;
    for (vector<double>::size_type i = 0; i != v1.size(); ++i)
    {
        ret += v1[i] * v2[i];
    }
    return ret;
}

double module(const vector<double>& v)
{
    double ret = 0.0;
    for (vector<double>::size_type i = 0; i != v.size(); ++i)
    {
        ret += v[i] * v[i];
    }
    return sqrt(ret);
}

// 夹角余弦
double cosine(const vector<double>& v1, const vector<double>& v2)
{
    assert(v1.size() == v2.size());
    return dotProduct(v1, v2) / (module(v1) * module(v2));
}

double mean(const vector<double>& v)
{
    assert(v.size() != 0);
    double ret = 0.0;
    for (vector<double>::size_type i = 0; i != v.size(); ++i)
    {
        ret += v[i];
    }
    return ret / v.size();
}

double cov(const vector<double>& v1, const vector<double>& v2)
{
    assert(v1.size() == v2.size() && v1.size() > 1);
    double ret = 0.0;
    double v1a = mean(v1), v2a = mean(v2);

    for (vector<double>::size_type i = 0; i != v1.size(); ++i)
    {
            ret += (v1[i] - v1a) * (v2[i] - v2a);
    }

    return ret / (v1.size() - 1);
}

// 相关系数
double coefficient(const vector<double>& v1, const vector<double>& v2)
{
    assert(v1.size() == v2.size());
    return cov(v1, v2) / sqrt(cov(v1, v1) * cov(v2, v2));
}

// Dice 系数
double dice(const vector<double>& v1, const vector<double>& v2)
{
    assert(v1.size() == v2.size());
    return 2.0 * dotProduct(v1, v2) / (dotProduct(v1, v1) + dotProduct(v2, v2));
}

// Jaccard 系数
double jaccard(const vector<double>& v1, const vector<double>& v2)
{
        assert(v1.size() == v2.size());
        return dotProduct(v1, v2) / (dotProduct(v1, v2) + dotProduct(v2, v2) - dotProduct(v1, v2));
}

// Minkowsky 距离
double minkowsky(const vector<double>& v1, const vector<double>& v2, double m)
{
    assert(v1.size() == v2.size());
    double ret = 0.0;
    for (vector<double>::size_type i = 0; i != v1.size(); ++i)
    {
            ret += pow(abs(v1[i] - v2[i]), m);
    }
    return pow(ret, 1.0 / m);
}

// Euclidean 距离
double euclidean(const vector<double>& v1, const vector<double>& v2)
{
    assert(v1.size() == v2.size());
    return minkowsky(v1, v2, 2.0);
}

// Manhattan 距离
double manhattan(const vector<double>& v1, const vector<double>& v2)
{
    assert(v1.size() == v2.size());
    return minkowsky(v1, v2, 1.0);
}

// Jffreys & Matusita 距离
double jffreysMatusita(const vector<double>& v1, const vector<double>& v2)
{
    assert(v1.size() == v2.size());
    double ret = 0.0;
    for (vector<double>::size_type i = 0; i != v1.size(); ++i)
    {
        ret += (sqrt(v1[i]) - sqrt(v2[i])) * (sqrt(v1[i]) - sqrt(v2[i]));
    }
    return sqrt(ret);
}

// Mahalanobis 距离
double mahalanobis(const vector<double>& v1, const vector<double>& v2)
{
    assert(v1.size() == v2.size());
    return 0.0;
}

// Camberra 距离(Lance 距离,Williams 距离)
double camberra(const vector<double>& v1, const vector<double>& v2)
{
    assert(v1.size() == v2.size());
    double ret = 0.0;
    for (vector<double>::size_type i = 0; i != v1.size(); ++i)
    {
        ret += abs(v1[i] - v2[i]) / abs(v1[i] + v2[i]);
    }
    return ret;
}

int main()
{
    double a[] = {1, 2, 3, 4, 5};
    double b[] = {5, 4, 3, 2, 1};
    vector<double> v1(a, a + sizeof (a) / sizeof (*a)), v2(b, b + sizeof (b) / sizeof (*b));

    cout << cosine(v1, v2) << endl;
    cout << coefficient(v1, v2) << endl;
    cout << dice(v1, v2) << endl;
    cout << jaccard(v1, v2) << endl;

    cout << minkowsky(v1, v2, 5.0) << endl;
    cout << euclidean(v1, v2) << endl;
    cout << manhattan(v1, v2) << endl;
    cout << jffreysMatusita(v1, v2) << endl;
    cout << mahalanobis(v1, v2) << endl;
    cout << camberra(v1, v2) << endl;

    return 0;
}

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值