【问题标题】:expected first layer to have x dimensions but got an array with shape y期望第一层具有 x 维,但得到一个形状为 y 的数组
【发布时间】:2019-07-09 03:31:38
【问题描述】:

(我只是在节点上启动 tensorflow.js)
我一直在网上搜索答案。
困惑
我有来自image1 = tf.fromPixels(img) 的图像数据,我尝试将它与其他图像数据一起输入到xs = tf.tensor([image1, image2])。令人困惑的是,无论我如何将一堆图像输入xsmodel.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']});

好吧,我尝试将其输入,尝试将它们转换为 typedarray 格式,尝试了很多东西。我很迷茫,无法为tf.fromPixels(canvas)model.fit(xs, ys, {epochs: 100, options....}); 转换为张量的多个图像提供适当的 xs 变量

代码:

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

【问题讨论】:

    标签: image tensorflow classification tensorflow.js


    【解决方案1】:

    查看您的代码,传入模型的数据与模型第一层 inputShape 的形状不同。

    如何解决问题?

    • 检查data.shape。
    console.log(xs.shape) // it will return (4,1)
    
    • 与输入形状比较

      数据形状应该比 inputShape 高一维(batchsize 多一维)

        // 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.reshapetf.slicetf.expandDims()、...

    • 重塑数据
    • 或者只是将 inputShape 更改为等于我们的数据形状


    在您的情况下,inputShape 和数据形状之间存在明显的不匹配。

    首先,您创建 xs 的方式是错误的。实际上,xs 的形状为 (4, 1),具有 NaN 值。就好像您创建了一个带有张量数组的tf.tensor。您可以这样创建 xs:

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

    但是不确定这是否能完全解决问题。您需要遍历上述步骤,即检查 xs 的形状,与 inputShape 进行比较等等...

    【讨论】:

    • 伟大的建设性答案!唯一的问题是无论我如何重塑它,形状都会是 [64, 16, 3]。我尝试制作它,以便批量处理 4 张图像,因此它将是 4d 张量形状:[4,16,16,3]。我尝试使用xs.reshape(4, 16, 16, 3) 对其进行整形,尝试使用xs.as4D(4, 16, 16, 3),但它不断转向[64、16、3]。错误:Error: Error when checking input: expected conv2d_Conv2D1_input to have 4 dimension(s). but got array with shape 64,16,3
    • @SimonCheng, tf 运算符不是就地运算符,这意味着它们不会更改应用它们的张量。如果您想改变xs 的形状,请考虑将运算结果重新分配给张量,如下所示:xs = xs.reshape(4, 16, 16, 3)
    • 感谢您的回复!我用xs = xs.reshape(4, 16, 16, 3); 修复了它,但现在它不是说but got array with shape 64,16,3 的错误,而是说Error when checking target: expected dense_Dense1 to have 4 dimension(s). but got array with shape 4,2,即使我记录了console.log(xs.shape);,它输出了[4, 16, 16, 3]。现在这里有什么问题?形状不错。
    • 我看到了问题,它是导致问题的原因。你有什么想法给ys放什么吗?它的标签对吗?
    • 由于这个问题与第一个问题没有直接关系,我建议为它开一个新线程。一个问题有一个线程很好:)
    猜你喜欢
    • 2020-06-18
    • 1970-01-01
    • 2021-10-06
    • 2020-05-21
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多