Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I invert a matrix in tensorflow-js?

Simple question. Is there an operation for it, also, how do you create an identity matrix? I've checked the documentation but can't find a single operation.

like image 886
Edison Avatar asked Sep 07 '25 03:09

Edison


1 Answers

For now tensorflowJs does not have any direct operator that can return the inverse of a matrix M. You can consider using the module Math.js

Having said that, it is possible to invert a matrix using tensorflowJs operators.

The following calculates the inverse of a matrix using the adjoint method with tensorflowJs operators.

// calculate the determinant of a matrix m
function det(m) {
    return tf.tidy(() => {
        const [r, _] = m.shape
        if (r === 2) {
            const t = m.as1D()
            const a = t.slice([0], [1]).dataSync()[0]
            const b = t.slice([1], [1]).dataSync()[0]
            const c = t.slice([2], [1]).dataSync()[0]
            const d = t.slice([3], [1]).dataSync()[0]
            result = a * d - b * c
            return result

        } else {
            let s = 0;
            rows = [...Array(r).keys()]
            for (let i = 0; i < r; i++) {
                sub_m = m.gather(tf.tensor1d(rows.filter(e => e !== i), 'int32'))
                sli = sub_m.slice([0, 1], [r - 1, r - 1])
                s += Math.pow(-1, i) * det(sli)
            }
            return s
        }
    })
}

// the inverse of the matrix : matrix adjoint method
function invertMatrix(m) {
    return tf.tidy(() => {
        const d = det(m)
        if (d === 0) {
            return
        }
        [r, _] = m.shape
        rows = [...Array(r).keys()]
        dets = [];
        for (let i = 0; i < r; i++) {
            for (let j = 0; j < r; j++) {
                const sub_m = m.gather(tf.tensor1d(rows.filter(e => e !== i), 'int32'))
                let sli
                if (j === 0) {
                    sli = sub_m.slice([0, 1], [r - 1, r - 1])
                } else if (j === r - 1) {
                    sli = sub_m.slice([0, 0], [r - 1, r - 1])
                } else {
                    const [a, b, c] = tf.split(sub_m, [j, 1, r - (j + 1)], 1)
                    sli = tf.concat([a, c], 1)
                }
                dets.push(Math.pow(-1, (i + j)) * det(sli))
            }
        }
        com = tf.tensor2d(dets, [r, r])
        tr_com = com.transpose()
        inv_m = tr_com.div(tf.scalar(d))
        return inv_m
    })
}

const a = tf.tensor2d([1, 3, 3, 1, 4, 3, 1, 3, 4], [3, 3])
console.log("matrix a")
a.print()
const i = invertMatrix(a)
console.log("inverse i")
i.print()
const prod = i.dot(a)
console.log("a * i")
prod.print()
<html>
  <head>
    <!-- Load TensorFlow.js -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]"> </script>
  </head>

  <body>
  </body>
</html>

Using the Jordan-Gauss method, one can calculate the inverse of the matrix this way:

// calculate the determinant of a matrix m
function det(m) {
    return tf.tidy(() => {
        const [r, _] = m.shape
        if (r === 2) {
            const t = m.as1D()
            const a = t.slice([0], [1]).dataSync()[0]
            const b = t.slice([1], [1]).dataSync()[0]
            const c = t.slice([2], [1]).dataSync()[0]
            const d = t.slice([3], [1]).dataSync()[0]
            result = a * d - b * c
            return result

        } else {
            let s = 0;
            rows = [...Array(r).keys()]
            for (let i = 0; i < r; i++) {
                sub_m = m.gather(tf.tensor1d(rows.filter(e => e !== i), 'int32'))
                sli = sub_m.slice([0, 1], [r - 1, r - 1])
                s += Math.pow(-1, i) * det(sli)
            }
            return s
        }
    })
}

// the inverse of the matrix : jordan-gauss method
function invertM(m) {
    return tf.tidy(() => {
        if (det(m) === 0) {
            return
        }
        const [r, _] = m.shape
        let inv = m.concat(tf.eye(r), 1)
        rows = [...Array(r).keys()]
        for (let i = 0; i < r; i++) {
            inv = tf.tidy(() => {
                for (let j = i + 1; j < r; j++) {
                    const elt = inv.slice([j, i], [1, 1]).as1D().asScalar()
                    const pivot = inv.slice([i, i], [1, 1]).as1D().asScalar()
                    let newrow
                    if (elt.dataSync()[0] !== 0) {
                        newrow = inv.gather(tf.tensor1d([i], 'int32')).sub(inv.gather(tf.tensor1d([j], 'int32')).div(elt).mul(pivot)).as1D()
                        const sli = inv.gather(rows.filter(e => e !== j))
                        const arr = []
                        if (j === 0) {
                            arr.push(newrow)
                        }
                        sli.unstack().forEach((t, ind) => {
                            if (ind !== j) {
                                arr.push(t)
                            } else {
                                arr.push(newrow)
                                arr.push(t)
                            }
                        })
                        if (j === r - 1) {
                            arr.push(newrow)
                        }
                        inv = tf.stack(arr)
                    }
                }
                return inv
            })
        }
        const trian = tf.unstack(inv)
        len = trian.length
        trian[len - 1] = trian[len - 1].div(trian[len - 1].slice(trian[len - 1].shape[0] - 1, 1).asScalar())
        for (let i = r - 2; i > -1; i--) {
            for (j = r - 1; j > i; j--) {
                trian[i] = trian[i].sub(trian[j].mul(trian[i].slice(j, 1).asScalar()))
            }
            trian[i] = trian[i].div(trian[i].slice(i, 1).asScalar())
        }
        return tf.split(tf.stack(trian), 2, 1)[1]
    })
}

const a = tf.tensor2d([1, 3, 3, 1, 4, 3, 1, 3, 4], [3, 3])
console.log("matrix a")
a.print()
const i = invertM(a)
console.log("inverse i")
i.print()
const prod = i.dot(a)
console.log("a * i")
prod.print()
<html>
  <head>
    <!-- Load TensorFlow.js -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]"> </script>
  </head>

  <body>
  </body>
</html>
like image 187
edkeveked Avatar answered Sep 10 '25 17:09

edkeveked