| 21 | * for particular labels. This object will concat them into two large xs and ys. |
| 22 | */ |
| 23 | export class ControllerDataset { |
| 24 | constructor(numClasses) { |
| 25 | this.numClasses = numClasses; |
| 26 | } |
| 27 | |
| 28 | /** |
| 29 | * Adds an example to the controller dataset. |
| 30 | * @param {Tensor} example A tensor representing the example. It can be an image, |
| 31 | * an activation, or any other type of Tensor. |
| 32 | * @param {number} label The label of the example. Should be a number. |
| 33 | */ |
| 34 | addExample(example, label) { |
| 35 | // One-hot encode the label. |
| 36 | const y = tf.tidy( |
| 37 | () => tf.oneHot(tf.tensor1d([label]).toInt(), this.numClasses)); |
| 38 | |
| 39 | if (this.xs == null) { |
| 40 | // For the first example that gets added, keep example and y so that the |
| 41 | // ControllerDataset owns the memory of the inputs. This makes sure that |
| 42 | // if addExample() is called in a tf.tidy(), these Tensors will not get |
| 43 | // disposed. |
| 44 | this.xs = tf.keep(example); |
| 45 | this.ys = tf.keep(y); |
| 46 | } else { |
| 47 | const oldX = this.xs; |
| 48 | this.xs = tf.keep(oldX.concat(example, 0)); |
| 49 | |
| 50 | const oldY = this.ys; |
| 51 | this.ys = tf.keep(oldY.concat(y, 0)); |
| 52 | |
| 53 | oldX.dispose(); |
| 54 | oldY.dispose(); |
| 55 | y.dispose(); |
| 56 | } |
| 57 | } |
| 58 | } |
nothing calls this directly
no outgoing calls
no test coverage detected