根据欧式距离和余弦相似度来计算tensor之间的相似度的代码实现

本文介绍了如何通过余弦相似度和欧式距离计算量化模型推理过程中tensor的相似度,讨论了在处理tensor数据时遇到的问题,如维度不匹配,以及解决方法。还提及了曼哈顿距离和切比雪夫距离作为替代的相似度衡量标准,并展示了计算这些距离的代码示例。
摘要由CSDN通过智能技术生成

通常情况下,在端侧的模型推理过程中,使用的是量化后的数据来参与各层计算的,而并非原始的float数据类型,通常的量化数据类型有UINT8/INT8/INT16等等,由于数据表示范围的差异,在量化过程中,必然涉及到精度损失,这种同一个模型相同层之间使用量化推理计算得到的数据经过反量化之后和原始goden版的float数据的差异,我们用相似度表示,用图形化描述如下:

通常相似度的比较可以用余弦距离和空间欧式距离表示,根据线性空间理论,当两个向量相似时,他们的内积较大,我们可以认为内积大小表示两个向量的相似性,cos的结果表示余弦相似度。

\\ \vec{a}\cdot \vec{b} = \left | a \right |\left | b \right |cos(\theta) \\ cos(\theta) = \frac{\vec{a}\cdot \vec{b} }{\left | a \right |\left | b \right |}

用矩阵向量表示就是:

高维空间难以理解,在二维空间就好理解多了,用到的就是中学学的余弦定理。图形化表示如下图所示,可以看到,当向量i和向量u方向大致相同时(夹角为锐角),红色的投影长度比较大,而当两向量垂直时,投影为零,并且当向量夹角为钝角的时候,投影为负的向量,代表差异最大。

下面以两笔同一个模型的不同过程产生的tensor为例,介绍两类统计信息的C语言实现过程。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <math.h>
#include <sys/ioctl.h>
 
#define DBG(fmt, ...)   do { printf("%s line %d, "fmt"\n", __func__, __LINE__, ##__VA_ARGS__); } while (0)
 
static void dump_memory(uint8_t *buf, int32_t len)
{
    int i;
 
    printf("\n\rdump file memory:");
    for (i = 0; i < len; i ++)
    {
        if ((i % 16) == 0)
        {
            printf("\n\r%p: ", buf + i);
        }
        printf("0x%02x ", buf[i]);
    }
    printf("\n\r");
    return;
}

int get_tensor_from_txt_file(char *file_path, float **buf)
{
    int len = 0;
    static float *memory = NULL;
    static int max_len = 10 * 1024 * 1024;
    FILE *fp = NULL;

    if(memory == NULL)
    {
        memory = (float*) malloc(max_len * sizeof(float));
    }
    
    if((fp = fopen(file_path, "r")) == NULL)
    {
        DBG("open tensor error.");
        exit(-1);
    }

    while(!feof(fp))
    {
        fscanf(fp, "%f", &memory[len ++]);
    }

    *buf = (float*)malloc(len * sizeof(float));
    if(len == 0 || *buf == NULL)
    {
        DBG("read tensor error, len %d, *buf %p", len, *buf);
        exit(-1);
    }
    memcpy(*buf, memory, len * sizeof(float));

    fclose(fp);

    return len;
}

float calculate_ojilide(int tensor_len, float *data0, float *data1)
{
	int i;
    float sum = 0.00;

	for(i = 0; i < tensor_len; i ++)
	{
		float square = (data0[i]-data1[i]) * (data0[i]-data1[i]);
		sum += square;
	}

	return sqrt(sum);
}

float yuxianxiangsidu(int tensor_len, float *data0, float *data1)
{
	int i;
    float fenzi = 0.00;
	float fenmu = 0.00;
	float len_vec0 = 0.00;
	float len_vec1 = 0.00;

	for(i = 0; i < tensor_l
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

papaofdoudou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值