ожидаемый первый слой будет иметь размеры х, но получил массив с формой у - PullRequest
0 голосов
/ 15 февраля 2019

(я только запускаю tenorflow.js на узле)
Я искал ответ в интернете вверх и вниз.
Путаница
У меня есть данные изображения от image1 = tf.fromPixels(img), и я попытался ввести его вместе с другими данными изображения в xs = tf.tensor([image1, image2]).Неразбериха не имеет значения, как я ввожу кучу изображений в xs для model.fit, программа выводит ошибки, описанные ниже.

Что я уже пробовал
Когда я запускаюпрограмма, которую я получаю сообщение об ошибке Error: Error when checking input: expected conv2d_Conv2D1_input to have 4 dimension(s). but got array with shape 4,1
Я точно знаю, что неправильно ввел xs.Я прочитал несколько статей в Интернете, касающихся того, как вам нужно вводить массив таким образом, как tf.tensor([[0.2, 0.1], [0.2, 0.4]]);, и какой-то серии изображений.Я посмотрел статьи, показывающие, что для изображений вам нужен еще один набор слоев:

model.add(tf.layers.conv2d({
    inputShape: [scaleHeight, scaleWidth, 3],
    kernelSize: 5,
    filters: 8,
    strides: 1,
    activation: 'relu',
    kernelInitializer: 'VarianceScaling'
}));
model.add(tf.layers.maxPooling2d({
    poolSize: [2, 2],
    strides: [2, 2]
}));

model.add(tf.layers.conv2d({
    kernelSize: 5,
    filters: 16,
    strides: 1,
    activation: 'relu',
    kernelInitializer: 'VarianceScaling'
}));

model.add(tf.layers.maxPooling2d({
    poolSize: [2, 2],
    strides: [2, 2]
}));

model.add(tf.layers.dense({ // Output
    units: 2,
    kernelInitializer: 'VarianceScaling',
    activation: 'softmax'
}));
model.compile({loss: 'categoricalCrossentropy', optimizer: tf.train.sgd(0.1), metrics: ['accuracy']});

Ну, я попытался ввести это в, попытался преобразовать их в типизированный массив, попробовал много вещей.Я довольно растерялся, когда нашел правильную переменную xs для нескольких изображений, превращенных в тензоры на tf.fromPixels(canvas) для model.fit(xs, ys, {epochs: 100, options....});

Код:

var tf = require('@tensorflow/tfjs');
var cv = require('canvas');
var {Image, createCanvas, ImageData} = cv;
tf.disableDeprecationWarnings();

var scaleWidth = 16;
var scaleHeight = 16;

function getImage(path){
    var img = new Image();
    return new Promise(function(resolve, reject){
        img.onload = function(){
            var element = createCanvas(scaleWidth, scaleHeight);
            var ctx = element.getContext('2d');
            ctx.drawImage(img, 0, 0);
            ctx.scale(scaleWidth/img.width, scaleHeight/img.height);
            //resolve(Array.from(tf.fromPixels(element).flatten().dataSync()));

            resolve(tf.fromPixels(element));
        };
        img.src = path;
    });
}

var log = function(input){console.log(input)};

const model = tf.sequential();
model.add(tf.layers.conv2d({
    inputShape: [scaleHeight, scaleWidth, 3],
    kernelSize: 5,
    filters: 8,
    strides: 1,
    activation: 'relu',
    kernelInitializer: 'VarianceScaling'
}));
model.add(tf.layers.maxPooling2d({
    poolSize: [2, 2],
    strides: [2, 2]
}));

model.add(tf.layers.conv2d({
    kernelSize: 5,
    filters: 16,
    strides: 1,
    activation: 'relu',
    kernelInitializer: 'VarianceScaling'
}));

model.add(tf.layers.maxPooling2d({
    poolSize: [2, 2],
    strides: [2, 2]
}));

model.add(tf.layers.dense({ // Output
    units: 2,
    kernelInitializer: 'VarianceScaling',
    activation: 'softmax'
}));
model.compile({loss: 'categoricalCrossentropy', optimizer: tf.train.sgd(0.1), metrics: ['accuracy']});

(async function(){
    var cats = [], bland = [];

    cats[0] = await getImage('cats/0.jpeg');
    cats[1] = await getImage('cats/1.jpeg');
    bland[0] = await getImage('bland/0.png');
    bland[1] = await getImage('bland/1.png');

    var testCats = await getImage('c.jpeg');
    var testBland = await getImage('b.jpeg');

    var xs = tf.tensor([cats[0], cats[1], bland[0], bland[1]]); // confusion occurs here

    for(var c = 0; c < 10; c++){
        var result = await model.fit(xs, tf.tensor([[0, 1], [0, 1], [1, 0], [1, 0]]), {epochs: 100});
        console.log(result.history.loss[0]);
    }
})();

Ипосле того, как я его запустил, я ожидал как минимум записать потерю модели, но он выдал эту ошибку:
Error: Error when checking input: expected conv2d_Conv2D1_input to have 4 dimension(s). but got array with shape 4,1

1 Ответ

0 голосов
/ 15 февраля 2019

Глядя на ваш код, данные, передаваемые в вашу модель, не имеют такую ​​же форму, что и первый слой модели inputShape.

Как решить проблему?

  • Проверьте data.shape.
console.log(xs.shape) // it will return (4,1)
  • сравнить с inputShape

    Форма данных должна быть на одно измерение выше, чем inputShape (еще одно измерение для пакетного размера)

    // Does `xs.inputShape.slice(1) ===[Scaleheight, scaleWidth,3]` ? 

    shape1 = xs.inputShape.slice(1)
    shape2 = [Scaleheight, scaleWidth,3]
    const same = (shape1.length == shape2.length) && shape1.every(function(e, i) {
    return e === shape2[i]; 
});

Если они не равны, существует два способа решения проблемы

  • Изменение формы данных, если это возможно, с использованием tf.reshape, tf.slice, tf.expandDims(), ...

  • Или просто измените значение inputShape, чтобы оно соответствовало нашей форме данных


В вашемВ данном случае существует явное несоответствие между inputShape и формой данных.

Во-первых, во-первых, то, как вы создаете xs, неверно.На самом деле, xs имеет форму (4, 1) со значениями NaN.Это как если бы вы создали tf.tensor с массивом тензоров.Вы можете создать xs следующим образом:

xs = tf.concat([...cats, ...blands], 0)

Однако не уверен, что это полностью решит проблему.Вам нужно выполнить итерацию по шагу, описанному выше, то есть проверить форму xs, сравнить с inputShape и так далее ...

...