最近在做文本匹配,想到了特征值的算法,自己写了一个文本计算算法。求批判。
2010-09-05 18:35
459 查看
之前有个需求,就是比较2个文本是否相近。
最牛逼的方法就是用语义去分析,然后比较结果。可是这个性能是在不敢恭维,于是想起了以前做过的人脸识别,使用特征值去操作。
人脸识别当是时把图片转变为一维向量,然后计算特征值。最终发现,如果是文本计算特征值,把文本的字符串输入后,简单的简化为每个char自相乘,再相加 = 向量的模的平方。
例如:
HI = (char 72)(char 73).
eigenValue = 72*72+73*73.
这样,IH的结果和HI就是一样了。 而且另外一个问题就是char的取值范围是0~255。如果对文本检测,那么很快就会超过了double的长度了。针对这些问题,我自己想到了一个算法。
代码 public static double GetStringEigenValue(string value)
{
if (string.IsNullOrEmpty(value))
return 0;
double length = value.Length;
double eigenvalue = 0;
int index = 1;
foreach (char str in value)
{
double strnum = (double)str;
eigenvalue += (strnum * strnum) / 100000 * index++;
}
//计算由于每个位置添加了权重,导致最终值增加的值
double weightfactor = (length - 1) * 255 * 255 / 100000 + (length - 1) * (length - 2) * 255 * 255 / 2 / 100000;
if (weightfactor == 0)
weightfactor = 1;
weightfactor = Math.Ceiling(Math.Log10(weightfactor));
if (weightfactor == 0)
weightfactor = 1;
eigenvalue /= weightfactor;
eigenvalue /= length;
return length + eigenvalue;
}
这里简单说下原理,还是很简单白痴的。
1. char的取值范围是0~255.那么 char相乘的最大值= 255*255 = 65025. 我为了每次都让特征值保持在小数,于是除以了10000.
eigenvalue += (strnum * strnum) / 100000* index++
2. 考虑到字符串位置的问题,我每个字符串都乘以了位置权重 index,这样不同顺序的字符串结果就一定不同了。
eigenvalue += (strnum * strnum) / 100000 * index++
3. 可是由于每个字符运算的时候都添加了权重,导致了结果比没有添加权重的大了很多。大了多少?我就按照 65025这个等差数列去运算:
N* 65025 + N(N-1)* 65025 /2, N = length -1
double weightfactor = (length - 1) * 255 * 255 / 100000 + (length - 1) * (length - 2) * 255 * 255 / 2 / 100000;
4. 最后,我计算这个增加的额外值到底是10的多少次方(需要再缩小多少)。得到:
weightfactor = Math.Ceiling(Math.Log10(weightfactor));
5. 然后根据权重放大的倍数,就是特征值再缩小回小数部分:
eigenvalue /= weightfactor;
6. 由于特征值结果是每个位置的char相乘再相加,因此相加导致放大的倍数 = 255*255/100000*length的倍数。因此就是length。最终需要缩小到小数:
eigenvalue /= length;
7. 为了保证不同长度的字符串可能计算出来的结果会一样,最终结果会再加上了字符串的长度。
return length + eigenvalue;
最后这个值,就是代表了这个文本的特征值了。整数部分是长度,小数部分是相似度。
最后,请各位大牛们拍拍砖。。。。小弟数学不才,在此献丑了。
最牛逼的方法就是用语义去分析,然后比较结果。可是这个性能是在不敢恭维,于是想起了以前做过的人脸识别,使用特征值去操作。
人脸识别当是时把图片转变为一维向量,然后计算特征值。最终发现,如果是文本计算特征值,把文本的字符串输入后,简单的简化为每个char自相乘,再相加 = 向量的模的平方。
例如:
HI = (char 72)(char 73).
eigenValue = 72*72+73*73.
这样,IH的结果和HI就是一样了。 而且另外一个问题就是char的取值范围是0~255。如果对文本检测,那么很快就会超过了double的长度了。针对这些问题,我自己想到了一个算法。
代码 public static double GetStringEigenValue(string value)
{
if (string.IsNullOrEmpty(value))
return 0;
double length = value.Length;
double eigenvalue = 0;
int index = 1;
foreach (char str in value)
{
double strnum = (double)str;
eigenvalue += (strnum * strnum) / 100000 * index++;
}
//计算由于每个位置添加了权重,导致最终值增加的值
double weightfactor = (length - 1) * 255 * 255 / 100000 + (length - 1) * (length - 2) * 255 * 255 / 2 / 100000;
if (weightfactor == 0)
weightfactor = 1;
weightfactor = Math.Ceiling(Math.Log10(weightfactor));
if (weightfactor == 0)
weightfactor = 1;
eigenvalue /= weightfactor;
eigenvalue /= length;
return length + eigenvalue;
}
这里简单说下原理,还是很简单白痴的。
1. char的取值范围是0~255.那么 char相乘的最大值= 255*255 = 65025. 我为了每次都让特征值保持在小数,于是除以了10000.
eigenvalue += (strnum * strnum) / 100000* index++
2. 考虑到字符串位置的问题,我每个字符串都乘以了位置权重 index,这样不同顺序的字符串结果就一定不同了。
eigenvalue += (strnum * strnum) / 100000 * index++
3. 可是由于每个字符运算的时候都添加了权重,导致了结果比没有添加权重的大了很多。大了多少?我就按照 65025这个等差数列去运算:
N* 65025 + N(N-1)* 65025 /2, N = length -1
double weightfactor = (length - 1) * 255 * 255 / 100000 + (length - 1) * (length - 2) * 255 * 255 / 2 / 100000;
4. 最后,我计算这个增加的额外值到底是10的多少次方(需要再缩小多少)。得到:
weightfactor = Math.Ceiling(Math.Log10(weightfactor));
5. 然后根据权重放大的倍数,就是特征值再缩小回小数部分:
eigenvalue /= weightfactor;
6. 由于特征值结果是每个位置的char相乘再相加,因此相加导致放大的倍数 = 255*255/100000*length的倍数。因此就是length。最终需要缩小到小数:
eigenvalue /= length;
7. 为了保证不同长度的字符串可能计算出来的结果会一样,最终结果会再加上了字符串的长度。
return length + eigenvalue;
最后这个值,就是代表了这个文本的特征值了。整数部分是长度,小数部分是相似度。
最后,请各位大牛们拍拍砖。。。。小弟数学不才,在此献丑了。
相关文章推荐
- git是一种分布式代码管理工具,git通过树的形式记录文件的更改历史,比如: base'<--base<--A<--A' ^ | --- B<--B' 小米工程师常常需要寻找两个分支最近的分割点,即base.假设git 树是多叉树,请实现一个算法,计算git树上任意两点的最近分割点。 (假设git树节点数为n,用邻接矩阵的形式表示git树:字符串数组matrix包含n个字符串,每个字符串由字符'0
- <仅是自己做笔记。。。系列15>实现一个挺高级的字符匹配算法: 给一串很长字符串,要求找到符合要求的字符串,例如目的串:123 1******3***2 ,12*****3这些都要找出来
- 3月24日 想到了一个字符串匹配的新算法 程序 时间复杂度自己不会算
- 刚想到一个计算地图计算距离的算法,自我感觉是最牛的算法,没有之一
- 教材上关于模式匹配中的求next数组的算法不易理解,本人自己编写了一个具有相同功能的子函数
- 刚想到一个计算地图计算距离的算法,自我感觉是最牛的算法,没有之一
- 自己实现的一个Cache 使用最近常使用算法
- [Weka]在自己的算法中调用Weka实现文本分类的一个例子
- 我就给一个PHP逆波兰表达式的算法吧---工资计算专用
- 自己写的一个将指定目录下的文本文件集合成单独的一个大文本文件工具
- 最近学习webwork+spring+hibernate,自己学习过程中的一个例子
- 我就给一个PHP逆波兰表达式的算法吧---工资计算专用
- 自己实现文本相似度算法(余弦定理)
- 文本去重之MinHash算法——就是多个hash函数对items计算特征值,然后取最小的计算相似度
- 请设计一个算法,计算n的阶乘有多少个尾随零。 给定一个int n,请返回n的阶乘的尾零个数。保证n为正整数
- 文本中关键字匹配算法
- 自己写的括号匹配算法
- 最近常用的一个算法(生成不重复的随机数组)
- 计算电磁学数值模式匹配算法实现