tensorflow.js MNIST 示例 nextbatch 实施情况如何?

what's up with tensorflow.js MNIST example nextbatch implementation?

从 tensorflow.js Handwritten digit recognition with CNNs tutorial, I stumbled upon the following implementation of the nextBatch function in mnist_data.js 中汲取灵感:

nextBatch(batchSize, data, index) {
  const batchImagesArray = new Float32Array(batchSize * IMAGE_SIZE);
  const batchLabelsArray = new Uint8Array(batchSize * NUM_CLASSES);

  for (let i = 0; i < batchSize; i++) {
    const idx = index();

    const image =
        data[0].slice(idx * IMAGE_SIZE, idx * IMAGE_SIZE + IMAGE_SIZE);
    batchImagesArray.set(image, i * IMAGE_SIZE);

    const label =
        data[1].slice(idx * NUM_CLASSES, idx * NUM_CLASSES + NUM_CLASSES); // weird part
    batchLabelsArray.set(label, i * NUM_CLASSES);
  }

  const xs = tf.tensor2d(batchImagesArray, [batchSize, IMAGE_SIZE]);
  const labels = tf.tensor2d(batchLabelsArray, [batchSize, NUM_CLASSES]);

  return {xs, labels};
}

我理解这个功能的重点是选择图像和相应的标签。
提供的实现的问题是正确选择了相应的标签,但也正确选择了其他 NUM_CLASSES-1(总共 10 个元素)随机标签,这些标签恰好在所选标签之后。

为什么没有像下面这样实现?

nextBatch(batchSize, data, index) {
  const batchImagesArray = new Float32Array(batchSize * IMAGE_SIZE);
  const batchLabelsArray = new Uint8Array(batchSize);

  for (let i = 0; i < batchSize; i++) {
    const idx = index();

    const image =
        data[0].slice(idx * IMAGE_SIZE, idx * IMAGE_SIZE + IMAGE_SIZE);
    batchImagesArray.set(image, i * IMAGE_SIZE);

    const label = new Uint8Array([data[1][idx]]); // weird part corrected
    batchLabelsArray.set(label, i);
  }

  const xs = tf.tensor2d(batchImagesArray, [batchSize, IMAGE_SIZE]);
  const labels = tf.tensor2d(batchLabelsArray, [batchSize, 1]);

  return {xs, labels};
}

我显然尝试 运行 它与上面的实现,但模型抛出以下内容:

Error when checking target: expected dense_Dense1 to have shape [,10], but got array with shape [1650,1].
    at new e (errors.ts:48)

作为 dense 步骤实施为

// Our last layer is a dense layer which has 10 output units, one for each
// output class (i.e. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9).
const NUM_OUTPUT_CLASSES = 10;
model.add(tf.layers.dense({
  units: NUM_OUTPUT_CLASSES,
  kernelInitializer: 'varianceScaling',
  activation: 'softmax'
}));

我应该是正确的,我应该如何修复密集层和其余实现?
相反,如果提供的实现是正确的,为什么它会起作用?

问题与标签的形状有关。

const labels = tf.tensor2d(batchLabelsArray, [batchSize, 1]);

标签是用形状为 1 的最右轴创建的。它应该等于 class 的数量(即:0、1 ...、9)应该因此是 10.

错误很简单,表示形状应该是[, 10]

  • 创建形状为 [batchSize, 10]
  • 的张量

显然,如果创建张量的形状为 [batchSize, 10],而 batchLabelsArray 的长度为 batchSize,则会抛出形状错误。它的长度应该是 batchSize * NUMBER_OF_CLASSES.

Codelab 使用

const batchLabelsArray = new Uint8Array(batchSize * NUM_CLASSES);

然后设置某个 batchSize 的 class 它使用以下内容:

for (let i = 0; i < batchSize; i++) {
      const idx = index();

      const image =
          data[0].slice(idx * IMAGE_SIZE, idx * IMAGE_SIZE + IMAGE_SIZE);
      batchImagesArray.set(image, i * IMAGE_SIZE);

      const label =
          data[1].slice(idx * NUM_CLASSES, idx * NUM_CLASSES + NUM_CLASSES);
      batchLabelsArray.set(label, i * NUM_CLASSES);
    }
  • 另一种选择是使用 tf.oneHot:
const labels = tf.oneHot(batchLabelsArray, 10) // batchLabelsArray is an array of batchSize length