новая форма и старая форма должны иметь одинаковое количество элементов - PullRequest
0 голосов
/ 10 октября 2018

В целях обучения я использую Tensorflow.js и у меня возникает ошибка при попытке использовать метод fit с набором пакетных данных (10 на 10) для изучения процесса пакетного обучения.

У меня есть несколько изображений 600x600x3, которые я хочу классифицировать (2 выхода, либо 1, либо 0)

Вот мой тренировочный цикл:

  const batches = await loadDataset()

  for (let i = 0; i < batches.length; i++) {
    const batch = batches[i]
    const xs = batch.xs.reshape([batch.size, 600, 600, 3])
    const ys = tf.oneHot(batch.ys, 2)

    console.log({
      xs: xs.shape,
      ys: ys.shape,
    })
    // { xs: [ 10, 600, 600, 3 ], ys: [ 10, 2 ] }

    const history = await model.fit(
      xs, ys,
      {
        batchSize: batch.size,
        epochs: 1
      }) // <----- The code throws here

    const loss = history.history.loss[0]
    const accuracy = history.history.acc[0]

    console.log({ loss, accuracy })
  }

Вот как я определяю набор данных

const chunks = chunk(examples, BATCH_SIZE)

const batches = chunks.map(
  batch => {
    const ys = tf.tensor1d(batch.map(e => e.y), 'int32')
    const xs = batch
      .map(e => imageToInput(e.x, 3))
      .reduce((p, c) => p ? p.concat(c) : c)
    return { size: batch.length, xs , ys }
  }
)

Вот модель:

const model = tf.sequential()
model.add(tf.layers.conv2d({
  inputShape: [600, 600, 3],
  kernelSize: 60,
  filters: 50,
  strides: 20,
  activation: 'relu',
  kernelInitializer: 'VarianceScaling'
}))
model.add(tf.layers.maxPooling2d({
  poolSize: [20, 20],
  strides: [20, 20]
}))
model.add(tf.layers.conv2d({
  kernelSize: 5,
  filters: 100,
  strides: 20,
  activation: 'relu',
  kernelInitializer: 'VarianceScaling'
}))

model.add(tf.layers.maxPooling2d({
  poolSize: [20, 20],
  strides: [20, 20]
}))
model.add(tf.layers.flatten())
model.add(tf.layers.dense({
  units: 2,
  kernelInitializer: 'VarianceScaling',
  activation: 'softmax'
}))

Я получаю ошибку во время первой итерации в цикле for из .fit, которая следующая:

Error: new shape and old shape must have the same number of elements.
    at Object.assert (/Users/person/nn/node_modules/@tensorflow/tfjs-core/dist/util.js:36:15)
    at reshape_ (/Users/person/nn/node_modules/@tensorflow/tfjs-core/dist/ops/array_ops.js:271:10)
    at Object.reshape (/Users/person/nn/node_modules/@tensorflow/tfjs-core/dist/ops/operation.js:23:29)
    at Tensor.reshape (/Users/person/nn/node_modules/@tensorflow/tfjs-core/dist/tensor.js:273:26)
    at Object.derB [as $b] (/Users/person/nn/node_modules/@tensorflow/tfjs-core/dist/ops/binary_ops.js:32:24)
    at _loop_1 (/Users/person/nn/node_modules/@tensorflow/tfjs-core/dist/tape.js:90:47)
    at Object.backpropagateGradients (/Users/person/nn/node_modules/@tensorflow/tfjs-core/dist/tape.js:108:9)
    at /Users/person/nn/node_modules/@tensorflow/tfjs-core/dist/engine.js:334:20
    at /Users/person/nn/node_modules/@tensorflow/tfjs-core/dist/engine.js:91:22
    at Engine.scopedRun (/Users/person/nn/node_modules/@tensorflow/tfjs-core/dist/engine.js:101:23)

Я не знаю, что из этого понять, и не нашел документации или помощи по этой конкретной ошибке, есть идеи?

1 Ответ

0 голосов
/ 11 октября 2018

Проблема модели заключается в том, как convolution применяется вместе с maxPooling

. Первый слой выполняет свертку ядра размера 60 с шагом [20, 20] и50 фильтров.Выходные данные этого слоя будут иметь приблизительную форму [600 / 20, 600 / 20, 50] = [30, 30, 50]

Максимальное объединение применяется с шагом [20, 20].Выходные данные этого слоя также будут иметь приблизительную форму [30 / 20, 30 / 20, 50] =[1, 1, 50 ]

На этом этапе модель больше не может выполнять свертку с размером ядра 5. Для формы ядра [5, 5] больше входной формы[1, 1] В результате выдается ошибка.Единственная свертка, которую может выполнить модель - это ядро, размер которого равен 1. Очевидно, что свертка будет выводить входные данные без какого-либо преобразования.

То же правило применяется к последнему maxPooling, чье poolingSize не можетотличаться от 1, в противном случае будет выдана ошибка.

Вот фрагмент:

const model = tf.sequential()
model.add(tf.layers.conv2d({
  inputShape: [600, 600, 3],
  kernelSize: 60,
  filters: 50,
  strides: 20,
  activation: 'relu',
  kernelInitializer: 'VarianceScaling'
}))
model.add(tf.layers.maxPooling2d({
  poolSize: [20, 20],
  strides: [20, 20]
}))
model.add(tf.layers.conv2d({
  kernelSize: 1,
  filters: 100,
  strides: 20,
  activation: 'relu',
  kernelInitializer: 'VarianceScaling'
}))

model.add(tf.layers.maxPooling2d({
  poolSize: 1,
  strides: [20, 20]
}))
model.add(tf.layers.flatten())
model.add(tf.layers.dense({
  units: 2,
  kernelInitializer: 'VarianceScaling',
  activation: 'softmax'
}))

model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});
model.fit(tf.ones([10, 600, 600, 3]), tf.ones([10, 2]), {batchSize: 4});

model.predict(tf.ones([1, 600, 600, 3])).print()
<html>
  <head>
    <!-- Load TensorFlow.js -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.13.0"> </script>
  </head>

  <body>
  </body>
</html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...