#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 пришла «уже» в горячем кодировании. Я одним горячим способом закодировал свои необработанные значения, и он, наконец, начал работать! Теперь все имеет смысл. Спасибо за помощь!