2017-06-22 126 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));