How do I invert a matrix in tensorflow-js?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



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.




2 Answers
2



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/tfjs@0.12.0"> </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/tfjs@0.12.0"> </script>
</head>

<body>
</body>
</html>





Thank you for verifying that for me. I'm trying to solve an unconstrained nonlinear minimization problem and the Levenberg-Marquardt algorithm requires the inverse operation. I've implemented it in Math.js but it is too slow so I was hoping an ml library would have some quick matrix manipulation capabilities. So far numeric has been the swiftest. Do you think it's feasible to use the built-in minimization functions of tf to solve these sorts of problems?
– Edison
Aug 12 at 21:59





It is feasible to built your own implementation of a function that inverts a matrix using tfjs operators. Consider the edit to my answer
– edkeveked
Aug 12 at 23:11





Thank you for this detailed answer, it's very helpful. The code seems to be very slow when applied to moderately sized matrices. Do you know why that is? The inverse operation is implemented in regular TensorFlow and it doesn't suffer from that issue. I may look into how that is done.
– Edison
Aug 13 at 16:08





The adjoint method is a very poor algorithm in practice because of it's complexity due to the calculation of each determinant. The jordan-Gauss method is preferred for big matrixes
– edkeveked
Aug 13 at 21:06



For the identity matrix you can use tf.eye() and I am not sure what you mean by inverting a matrix but it could either be tf.reciprocal() which performs 1/x element-wise or you want to transpose it, which would be done using tf.transpose().


tf.eye()


tf.reciprocal()


1/x


tf.transpose()





Thanks for the response. I mean a matrix where given matrix A the inverse is defined as the matrix B where AB = I, and I is the identity matrix.
– Edison
Aug 12 at 21:56






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard