что случилось с tensorflow.js Пример MNIST реализации nextbatch?

#javascript #tensorflow #mnist #tensorflow.js

#javascript #тензорный поток #mnist #tensorflow.js

Вопрос:

Черпая вдохновение из tensorflow.js Распознавание рукописных цифр с помощью руководства CNNs я наткнулся на следующую реализацию функции nextBatch в 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'
}));
  

Должен ли я быть прав, как мне исправить плотный слой и остальную часть реализации?
Если вместо этого предоставленная реализация верна, почему она работает?

Ответ №1:

Проблема связана с формой метки.

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

Метки создаются с самой правой осью, имеющей форму 1. Скорее оно должно быть равно количеству существующих классов (т. Е.: 0, 1 …, 9), которое, следовательно, должно быть 10.

Ошибка проста, указывая на то, что форма должна быть [, 10] .

  • создайте тензор с формой [batchSize, 10]

Очевидно, что если тензор создается с формой [BatchSize, 10], тогда batchLabelsArray как имеет длину batchSize , он выдаст ошибку формы. Он должен иметь длину batchSize * NUMBER_OF_CLASSES .

В codelab используется

 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);
      batchLabelsArray.set(label, i * NUM_CLASSES);
    }
  
  • Другой вариант — использовать tf.oneHot :
 const labels = tf.oneHot(batchLabelsArray, 10) // batchLabelsArray is an array of batchSize length 
  

Комментарии:

1. извините, я все еще немного в замешательстве. с тензором xs размера [batchSize, IMAGE_SIZE] и labels тензором размера [batchSize, 10] разве у вас не будет 10 меток для каждого изображения, где только первая верна?

2. Это способ создания тензора меток. Для каждого объекта (изображения) для значений NUMBER_CLASSES установлено значение 0, за исключением индекса правильного класса, для которого установлено значение class

3. понятно; поэтому не имеет значения, представляет ли остальная часть тензора случайные значения / 0s / несвязанные последующие метки. важен только первый элемент. Есть ли математическое объяснение этому или остальные метки (и / или результаты их взаимодействия) просто удаляются фреймворком?

4. Хорошо, наконец-то щелкнуло, когда я напечатал метки MNIST! Чего я не понял, так это того, что метка из набора данных MNIST пришла «уже» в горячем кодировании. Я одним горячим способом закодировал свои необработанные значения, и он, наконец, начал работать! Теперь все имеет смысл. Спасибо за помощь!