【问题标题】:How to normalize image in tensorflow.js?如何标准化 tensorflow.js 中的图像?
【发布时间】:2021-02-25 15:38:30
【问题描述】:

我在 pytorch 的训练阶段应用了转换,然后我将模型转换为在 tensorflow.js 中运行。它工作正常,但由于我没有应用相同的转换而得到错误的预测。

test_transform = torchvision.transforms.Compose([
    torchvision.transforms.Resize(size=(224, 224)),
    torchvision.transforms.ToTensor(),
    torchvision.transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

我可以调整图像大小但无法正常化。我该怎么做?

更新:-

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js" type="text/javascript"></script>
    <script>
        {% load static %}
       async function load_model(){
            const model = await tf.loadGraphModel("{% static 'disease_detection/tfjs_model_2/model.json' %}");
            console.log(model);
            return model;
        }

        function loadImage(src){
            return new Promise((resolve, reject) => {
                const img = new Image();
                img.src = src;
                img.onload = () => resolve(tf.browser.fromPixels(img, 3));
                img.onerror = (err) => reject(err);
            });
        }

        

        function resizeImage(image) {

            return tf.image.resizeBilinear(image, [224, 224]).sub([0.485, 0.456, 0.406]).div([0.229, 0.224, 0.225]);

        }

        function batchImage(image) {
            
            const batchedImage = image.expandDims(0);  
            //const batchedImage = image; 
            return batchedImage.toFloat();
        }

        function loadAndProcessImage(image) {
            //const croppedImage = cropImage(image);
            const resizedImage = resizeImage(image);
            const batchedImage = batchImage(resizedImage);
            return batchedImage;
        }


        let model =  load_model();
       model.then(function (model_param){
            loadImage('{% static 'disease_detection/COVID-19 (97).png' %}').then(img=>{
             let imge = loadAndProcessImage(img);
             const t4d = tf.tensor4d(Array.from(imge.dataSync()),[1,3,224,224])
                console.log(t4d.dataSync());
             let prediction = model_param.predict(t4d);
             let v = prediction.argMax().dataSync()[0]
             console.log(v)
        })
       })

我尝试了这段代码,但它没有正确规范化图像。

【问题讨论】:

    标签: javascript tensorflow deep-learning tensorflow.js


    【解决方案1】:
    • torchvision.transforms.ToTensor() 将 0 到 255 范围内的 PIL Image 或 numpy 数组转换为 0.0 到 1.0 范围内的浮点张量 os 形状(通道 x 高度 x 宽度)。要在 0.0 到 1.0 的范围内进行转换,它会将张量的每个元素除以 255。因此,在 tensorflowJS 中执行相同的操作,如下所示 -
    img = tf.image.resizeBilinear(img, [224, 224]).div(tf.scalar(255))
    img = tf.cast(img, dtype = 'float32');
    
    • torchvision.transforms.Normalize() 用均值和标准差对张量图像进行归一化。给定 n 个通道的均值: (mean[1],...,mean[n]) 和 std: (std[1],..,std[n]) ,此变换将对输入张量的每个通道进行归一化,即,输出[通道] = (输入[通道] - 平均[通道]) / 标准[通道]。我在 tensorflowJS 中没有找到任何这样的功能。所以,我分别对每个通道进行归一化并再次组合它们。

    完整功能如下-

    function imgTransform(img){
                img = tf.image.resizeBilinear(img, [224, 224]).div(tf.scalar(255))
                img = tf.cast(img, dtype = 'float32');
    
                /*mean of natural image*/
               let meanRgb = {  red : 0.485,  green: 0.456,  blue: 0.406 }
    
               /* standard deviation of natural image*/
               let stdRgb = { red: 0.229,  green: 0.224,  blue: 0.225 }
    
                let indices = [
                            tf.tensor1d([0], "int32"),
                            tf.tensor1d([1], "int32"),
                            tf.tensor1d([2], "int32")
                ];
    
               /* sperating tensor channelwise and applyin normalization to each chanel seperately */
               let centeredRgb = {
                   red: tf.gather(img,indices[0],2)
                            .sub(tf.scalar(meanRgb.red))
                            .div(tf.scalar(stdRgb.red))
                            .reshape([224,224]),
                   
                   green: tf.gather(img,indices[1],2)
                            .sub(tf.scalar(meanRgb.green))
                            .div(tf.scalar(stdRgb.green))
                            .reshape([224,224]),
                   
                   blue: tf.gather(img,indices[2],2)
                            .sub(tf.scalar(meanRgb.blue))
                            .div(tf.scalar(stdRgb.blue))
                            .reshape([224,224]),
               }
              
    
                /* combining seperate normalized channels*/
                let processedImg = tf.stack([
                    centeredRgb.red, centeredRgb.green, centeredRgb.blue
                ]).expandDims();
               return processedImg;
            }
    

    【讨论】:

      【解决方案2】:

      尽管我对 pytorch 文档不太熟悉,但快速浏览一下就会发现Normalize 的第一个参数是数据集的平均值,第二个参数是标准差。

      要在 tensorflow.js 中使用这两个参数进行归一化,可以使用以下方法

      tensor.sub([0.485, 0.456, 0.406]).div([0.229, 0.224, 0.225])
      

      但是张量值应该在 0 到 1 的范围内,在调整大小操作后将其除为 255。整个 compose 操作如下所示

      tf.image.resizeBilinear(image, [224, 224]).div(255)
        .sub([0.485, 0.456, 0.406])
        .div([0.229, 0.224, 0.225]);
      

      【讨论】:

      • 我试过了,但仍然没有得到正确的预测。
      • pytorchNormalize做了哪些操作?
      • 和你说的操作是一样的。 (x[channel] - mean[channel]) / std[channel].
      • 我只是通过在控制台中打印来检查值,所以它并没有标准化所有像素。总共有 224 x 224 x 3 = 150,528 个值,但其中只有 1343 个值被标准化。
      • 广播应用于所有张量值。我不明白为什么它只适用于张量的一个子集。在调整大小后,您缺少将结果张量除以 255
      猜你喜欢
      • 1970-01-01
      • 2020-10-09
      • 2017-07-05
      • 2021-05-12
      • 1970-01-01
      • 2012-11-29
      • 2013-05-17
      • 2022-01-12
      • 1970-01-01
      相关资源
      最近更新 更多