记录一下JS实现DTW算法

const maxVal =  Number.MAX_VALUE

/**
 * 返回一个mXn的矩阵
 * @param {number} m
 * @param {number} n
 * @param {number} val 初始值
 * @returns {number[][]} 
 */
function matrix(m, n, val = 0) {
    const arr = [[0]]
    arr.splice(0, 1)
    for(let i = 0; i < m; i++) {
        const child = []
        for (let j = 0; j < n; j++) {
            child.push[val]
        }
        arr.push(child)
    }
    return arr
}

/**
 *  寻找最近路径
 * @param {number[][]} dis 
 */
function findTrace(dis) {
    let m = dis.length
    let n = dis[0].length
    let i = m - 1
    let j = n - 1
    const W = []

    let left_down = maxVal
    let left = maxVal
    let down = maxVal

    while(i > 0 || j > 0) {
        W.push([i,j])
        console.log(i,j)
        if (i > 0 && j > 0) {
            left_down = dis[i-1][j-1]
        } else {
            left_down = maxVal
        }

        if (i > 0) {
            down = dis[i-1][j]
        } else {
            down = maxVal
        }

        if (j > 0) {
            left = dis[i][j-1]
        } else {
            left = maxVal
        }

        const min_dis = Math.min(left_down, down, left)

        if (min_dis === left_down) {
            i--
            j--
        } else if (min_dis === down) {
            i--
        } else {
            j--
        }
    }
    W.push([0, 0])
    W.reverse()
    return W
}

/**
 * C,Q数据格式需要一致
 * @param {number[]|number[][]} C
 * @param {number[]|number[][]} Q 
 */
function dtw(C, Q) {
    let m = C.length
    let n = Q.length
    let len2D = Array.isArray(C[0]) ? C[0].length : 0
    const point_dis = matrix(m,n)
    for (let i =0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            let val = 0
            if (len2D) {
                val = 0
                for (let k = 0; k < len2D; k++) {
                    val += Math.pow(C[i][k] - Q[j][k], 2)
                }
            } else {
                val = Math.pow(C[i] - Q[j], 2) 
            }
            point_dis[i][j] = Math.sqrt(val)
        }
    }

    const warping_dis = matrix(m,n, maxVal)

    for( let i = 0; i< m; i++) {
        for(let j = 0; j < n; j++) {
            if (i === 0 && j===0) {
                warping_dis[0][0] = point_dis[0][0]
                continue
            }
            let left_down = maxVal
            let down = maxVal
            let left = maxVal

            if (i > 0 && j > 0) {
                left_down = warping_dis[i-1][j-1]
            }

            if ( i > 0) {
                down = warping_dis[i - 1][j]
            }

            if ( j > 0) {
                left = warping_dis[i][ j - 1]
            }
            // console.log(i,j,left, left_down, down, point_dis[i][j]);
            warping_dis[i][j] = point_dis[i][j] + Math.min(left, left_down, down)
        }
    }
    // console.log(warping_dis)
    const dis = warping_dis[m-1][n-1]
    const W = findTrace(warping_dis)

    return {dis, W}

}

以下为测试代码:

let C = [[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7],[8,8],[9,9]]
let Q = [[1,5],[2,-2],[3,-1],[4,0],[5,1],[6,2],[7,3],[8,4],[9,5],[10,6],[11,7]]
    
const result = dtw(C, Q)
    
console.log(result)
C = [0,1,2,3,4,5]
Q = [1,2,3,4,5,6]
const {W, dis} = dtw(C, Q)
console.log(dis, W)

for(const item of W) {
   const [m, n] = item
   console.log(m,n, C[m], Q[n])
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值