2017-06-22 83 views
4

我正在研究一个使用nodeJs的小型机器学习理论算法。 我的目标是比较许多阵列模式,以一个源模式然后返回如何 相似,他们表示为百分比。对于一个示例,pattern1可能与源模式有80%的相似性。JavaScript模式比较

确定一个阵列与另一个阵列的百分比相似度的最佳方法是什么?

什么我迄今所做..

//source 
var soureSequence = [0.53,0.55,0.50,0.40,0.50,0.52,0.58,0.60] 

//patterns to compare 
var sequence1 = [0.53,0.54,0.49,0.40,0.50,0.52,0.58,0.60] 
var sequence2 = [0.53,0.55,0.50,0.42,0.50,0.53,0.57,0.62] 

既然我已经选择了一种基于%的结果,我想我应该从第一价值基础我的源图案关百分比变化第二数组中的值。

var percentChange = (firstVal, secondVal) => { 
     var pChange = ((parseFloat(secondVal) - firstVal)/
     Math.abs(firstVal)) * 100.00; 

     //To avoid NaN , Infinity , and Zero 

     if(!pChange || pChange == 0){ 
      return 0.00000001 
     } 
     return pChange; 
    } 

在这里,我会从我的源序列生成我的源模式

 var storePattern = function(sequence){ 
      var pattern = []; 
      for(var i = 0 ; i < sequence.length ; i++){ 
       let $change = percentChange(sequence[i] , sequence[i + 1]); 
       if(i != sequence.length && $change){ 
        pattern.push($change) 
       } 
      } 
    return pattern; 
    } 



    var sourcePattern = storePattern(soureSequence); 

现在,我将创造更多的模式进行比较

var testPattern1 = storePattern(sequence1); 
    var testPattern2 = storePattern(sequence2); 

下面是我的比较功能

var processPattern = function(source , target){ 
    var simularityArray = []; 

    for(var i = 0 ; i < target.length ; i++){ 
     //Compare percent change at indexof testPattern to sourcePattern of same index 
     let change = Math.abs(percentChange(target[i] , source[i])); 
     simularityArray.push(100.00 - change); 
    } 

    var rating = simularityArray.reduce((a,b) => { 
     return a + b 
    }); 

    //returns percent rating based of average of similarity pattern 

    rating = rating/parseFloat(source.length + ".00"); 
    return rating; 
} 

现在我可以尝试估计相似

var similarityOfTest1 = processPattern(sourcePattern , testPattern1) 

我的问题是同一范围内的值 ..内的序列这只适用于例如0.50,0.52 ..这些值的百分比变化将不会是相同的0.20,0.22但价值差异是相同的,即 - > 0.02

我想到价值差异模式,但在这一点上,我迷路了。

将考虑所有答案。谢谢您的帮助!

+0

所以你正在努力寻找两个阵列之间的差异整个生产的百分比?或者你的意思是各个数组值之间的差异? – Rick

+0

IMO两个数组“多么不同”的规则完全取决于为什么这种差异很重要,或者你正在使用它。本质上processPattern是一个[健身功能](https://en.wikipedia.org/wiki/Fitness_function),你应该相应地注意其设计的注意事项。 – James

+0

@Arrow我的理论是,单个数组值之间的差异最终将决定每个模式与源模式相似度的总体百分比。 – KpTheConstructor

回答

1

使用减少得到的差异比平均。

//patterns to compare 
 
var sequence1 = [0.53,0.54,0.49,0.40,0.50,0.52,0.58,0.60] 
 
var sequence2 = [0.53,0.55,0.50,0.42,0.50,0.53,0.57,0.62] 
 

 
function diff(sequence){ 
 
var soureSequence = [0.53,0.55,0.50,0.40,0.50,0.52,0.58,0.60] 
 
    var delta = soureSequence.reduce(function (r, a, i, aa) { 
 
     i && r.push(a - sequence[i]); 
 
     return r; 
 
    }, []), 
 
    average = delta.reduce(function (a, b) { return a + b; })/delta.length; 
 
    
 
    return {delta:delta, average:average} 
 
} 
 
console.log('sequence1',diff(sequence1)); 
 
console.log('sequence2',diff(sequence2));

1

在我的经验,两个向量(阵列)的相似性是使用点积ex测量。就像它在该链接中所说的那样,将数组中的每个对应元素相乘,将它们相加,然后除以每个数组的大小(每个组成部分的平方和的平方根)。罗塞塔代码有dot product in JavaScript的一个例子,在这里复制

// dotProduct :: [Int] -> [Int] -> Int 
const dotProduct = (xs, ys) => { 
    const sum = xs => xs ? xs.reduce((a, b) => a + b, 0) : undefined; 

    return xs.length === ys.length ? (
     sum(zipWith((a, b) => a * b, xs, ys)) 
    ) : undefined; 
} 

// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 
const zipWith = (f, xs, ys) => { 
    const ny = ys.length; 
    return (xs.length <= ny ? xs : xs.slice(0, ny)) 
     .map((x, i) => f(x, ys[i])); 
} 

所以,你会打电话

const score1 = dotProduct(sourceSequence, sequence1); 
const score2 = dotProduct(sourceSequence, sequence2); 

而且无论是大是sourceSequence越接近序列。

+1

我认为这与我正在努力实现的接近。使用这种方法可以说我有100个测试模式用于测试,我如何按顺序排列这些模式,排名规模是什么?例如,我的原始方法会产生一个百分比分数。 – KpTheConstructor

+0

点积乘以两个向量并返回一个介于0和1之间的数字。 1是最大相似度,0是最小相似度。因此,如果需要,您可以乘以100以获得百分比分数。 注意,1并不意味着它们是完全相同的向量。如果sequence2与sequ​​ence1类似,但每个元素乘以相同的常量,则它们的点积为1 –

1

我不确定你需要机器学习。你有一个源模式,你有一些输入,你基本上想要执行模式的差异。

机器学习可以用来找到模式,假设你有一些启发式的测量错误(如果你使用无监督学习技术),或者你有样本集来训练网络。

但是,如果您只是想测量一个模式和另一个模式之间的差异,那么只需执行diff操作。你需要做的是决定你的测量和如何规范化结果有什么不同。

1

我无法确定您想如何衡量相似度。我通过计算相应项目的差异并累积这些差异来查看源数组总和会产生多少偏差。你可以用你喜欢的方式玩这个计算。

function check([x,...xs],[y,...ys], state = {sumSource: 0, sumDiff: 0}){ 
 
    state.sumSource += x; 
 
    state.sumDiff += Math.abs(x-y); 
 
    return xs.length ? check(xs,ys,state) : (100 - 100 * state.sumDiff/state.sumSource).toFixed(4) + "% similarity"; 
 
} 
 

 
var soureSequence = [0.53,0.55,0.50,0.40,0.50,0.52,0.58,0.60], 
 
    sequence1  = [0.53,0.54,0.49,0.40,0.50,0.52,0.58,0.60], 
 
    sequence2  = [0.53,0.55,0.50,0.42,0.50,0.53,0.57,0.62]; 
 

 
console.log(check(soureSequence,sequence1)); 
 
console.log(check(soureSequence,sequence2));