如何生成包含非零元素索引的张量?
how to produce a tensor containing the indices of nonzero elements?
我有一个像
这样的张量
[[0, 0, 0, 1, 0, 0],
[0, 3, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0],
[0, 0, 0, 0, 0, 0]]
如何生成仅包含前者非零索引的张量?
[[0,3],[1,1],[1,5],[4,3]]
我在 tfjs 上,所以它似乎没有 boolean_mask 或其他人似乎在索引中使用的其他一些有用的功能。如果不在阵列上使用 .data()
逃生舱口和 map/filtering 是否可能? (我只是将 tensorflow 用于其快速线性代数方法,所以这不会是最糟糕的,对吧?)
没错,目前没有可用于使用掩码定义分区的运算符。您可以将此 answer 视为解决方法。但是即使使用掩码,这里的问题也不能轻易解决,因为创建分区假设事先知道要检索的索引。
为了解决这个问题,可以使用logicalAnd between the input tensor and a tensor of the same shape with all the elements equal to 1. It is usefull because it will return a tensor of the same shape than the input shape with values 0 if the initial element was 0 and 1 if not.Using argMax,可以检索等于1的元素的索引
let t = tf.tensor2d([[0, 0, 0, 1, 0, 0], [0, 3, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 2, 0, 0], [0, 0, 0, 0, 0, 0]])
let a = t.as1D()
const b = tf.cast(a, 'bool')
let helper = b.logicalAnd(tf.cast(tf.ones([a.size]), 'bool'))
const n = helper.sum().dataSync()[0]
const noNull = []
for(let i = 0; i < n ; i++) {
let ind = tf.argMax(helper)
let s = ind.dataSync()[0]
noNull.push(tf.argMax(helper).dataSync()[0])
if (s === 0) {
const [x, y] = helper.split([1, helper.size - 1])
helper = tf.concat(tf.tensor1d([0]), y)
} else if (s === helper.size) {
const [x, y] = helper.split([helper.size -1, 1])
helper = tf.concat(x, tf.tensor1d([0]))
} else {
const [x, _, y] = helper.split([s, 1, helper.size - s - 1])
helper = tf.concat([x,tf.tensor1d([0]), y])
}
}
const indexToCoords = (index, shape) => {
const pseudoShape = shape.map((a, b, c) => c.slice(b + 1).reduce((a, b) => a * b, 1))
let coords = []
let ind = index
for (let i = 0; i < shape.length; i++) {
coords.push(Math.floor(ind / pseudoShape[i]))
ind = ind % pseudoShape[i]
}
return coords
}
const coords = noNull.map(e => indexToCoords(e, t.shape))
console.log(coords)
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.13.0"> </script>
</head>
<body>
</body>
</html>
在这个thread之后,有一个更简单的方法来实现同样的事情
(async function() {
const x = tf.tensor2d(
[[0, 0, 0, 1, 0, 0],
[0, 3, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0],
[0, 0, 0, 0, 0, 0]]);
const mask = x.greater([0]).asType('bool');
const coords = await tf.whereAsync(mask);
coords.print();
}());
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.13.0"> </script>
</head>
<body>
</body>
</html>
您可以使用 tf.whereAsync(condition)
到 return 索引。见 docs
示例:
(await tf.whereAsync(tf.tensor1d([0,1,2,0,1]).notEqual(0))).print();
==> Tensor
[[1],
[2],
[4]]
我有一个像
这样的张量 [[0, 0, 0, 1, 0, 0],
[0, 3, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0],
[0, 0, 0, 0, 0, 0]]
如何生成仅包含前者非零索引的张量?
[[0,3],[1,1],[1,5],[4,3]]
我在 tfjs 上,所以它似乎没有 boolean_mask 或其他人似乎在索引中使用的其他一些有用的功能。如果不在阵列上使用 .data()
逃生舱口和 map/filtering 是否可能? (我只是将 tensorflow 用于其快速线性代数方法,所以这不会是最糟糕的,对吧?)
没错,目前没有可用于使用掩码定义分区的运算符。您可以将此 answer 视为解决方法。但是即使使用掩码,这里的问题也不能轻易解决,因为创建分区假设事先知道要检索的索引。
为了解决这个问题,可以使用logicalAnd between the input tensor and a tensor of the same shape with all the elements equal to 1. It is usefull because it will return a tensor of the same shape than the input shape with values 0 if the initial element was 0 and 1 if not.Using argMax,可以检索等于1的元素的索引
let t = tf.tensor2d([[0, 0, 0, 1, 0, 0], [0, 3, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 2, 0, 0], [0, 0, 0, 0, 0, 0]])
let a = t.as1D()
const b = tf.cast(a, 'bool')
let helper = b.logicalAnd(tf.cast(tf.ones([a.size]), 'bool'))
const n = helper.sum().dataSync()[0]
const noNull = []
for(let i = 0; i < n ; i++) {
let ind = tf.argMax(helper)
let s = ind.dataSync()[0]
noNull.push(tf.argMax(helper).dataSync()[0])
if (s === 0) {
const [x, y] = helper.split([1, helper.size - 1])
helper = tf.concat(tf.tensor1d([0]), y)
} else if (s === helper.size) {
const [x, y] = helper.split([helper.size -1, 1])
helper = tf.concat(x, tf.tensor1d([0]))
} else {
const [x, _, y] = helper.split([s, 1, helper.size - s - 1])
helper = tf.concat([x,tf.tensor1d([0]), y])
}
}
const indexToCoords = (index, shape) => {
const pseudoShape = shape.map((a, b, c) => c.slice(b + 1).reduce((a, b) => a * b, 1))
let coords = []
let ind = index
for (let i = 0; i < shape.length; i++) {
coords.push(Math.floor(ind / pseudoShape[i]))
ind = ind % pseudoShape[i]
}
return coords
}
const coords = noNull.map(e => indexToCoords(e, t.shape))
console.log(coords)
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.13.0"> </script>
</head>
<body>
</body>
</html>
在这个thread之后,有一个更简单的方法来实现同样的事情
(async function() {
const x = tf.tensor2d(
[[0, 0, 0, 1, 0, 0],
[0, 3, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 0, 0],
[0, 0, 0, 0, 0, 0]]);
const mask = x.greater([0]).asType('bool');
const coords = await tf.whereAsync(mask);
coords.print();
}());
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.13.0"> </script>
</head>
<body>
</body>
</html>
您可以使用 tf.whereAsync(condition)
到 return 索引。见 docs
示例:
(await tf.whereAsync(tf.tensor1d([0,1,2,0,1]).notEqual(0))).print();
==> Tensor
[[1],
[2],
[4]]