SciSharp / SciSharp-Stack-Examples

Practical examples written in SciSharp's machine learning libraries
http://scisharpstack.org
Apache License 2.0
319 stars 103 forks source link

Tensorflow.InvalidArgumentError: 'Can not squeeze dim[1], expected a dimension of 1, got 3 [[{{node InceptionV1/Logits/SpatialSqueeze}}]]' #52

Open dorodorodororo opened 3 years ago

dorodorodororo commented 3 years ago

Hi, I'm currently trying to run a 'ImageRecognitionInception' example with my pre-trained model (which is .pb file)

and here comes a problem :

Tensorflow.InvalidArgumentError: 'Can not squeeze dim[1], expected a dimension of 1, got 3 [[{{node InceptionV1/Logits/SpatialSqueeze}}]]'

and here is the code

using NumSharp;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using Tensorflow;
using Tensorflow.Keras.Utils;
using static Tensorflow.Binding;
using Console = Colorful.Console;

namespace TensorFlowNET.Examples
{
     /// Inception v3 is a widely-used image recognition model 
    /// that has been shown to attain greater than 78.1% accuracy on the ImageNet dataset. 
    /// The model is the culmination of many ideas developed by multiple researchers over the years.

    public class ImageRecognitionInception : SciSharpExample, IExample
    {
        string dir = "ImageRecognitionInception";
        string pbFile = "tensorflow_inception_graph.pb";
        string labelFile = "imagenet_comp_graph_label_strings.txt";
        List<NDArray> file_ndarrays = new List<NDArray>();
        public ExampleConfig InitConfig()
            => Config = new ExampleConfig
            {
                Name = "Image Recognition Inception",
                Enabled = true,
                IsImportingGraph = false
            };

        public bool Run()
        {
            tf.compat.v1.disable_eager_execution();

            PrepareData(); 

            var graph = new Graph();
            //import GraphDef from pb file
            graph.Import(Path.Join(dir, pbFile));

            var input_name = "input";
            var output_name = "InceptionV1/Logits/Predictions/Softmax";

            var input_operation = graph.OperationByName(input_name);
            var output_operation = graph.OperationByName(output_name);

            var labels = File.ReadAllLines(Path.Join(dir, labelFile)); 
            var result_labels = new List<string>(); 
            var sw = new Stopwatch(); 

            using (var sess = tf.Session(graph)) 
            {
                foreach (var nd in file_ndarrays)
                {
                    sw.Restart();

                    var results = sess.run(output_operation.outputs[0], (input_operation.outputs[0], nd));  // the error happens here
                    results = np.squeeze(results); 
                    int idx = np.argmax(results); 

                    Console.WriteLine($"{labels[idx]} {results[idx]} in {sw.ElapsedMilliseconds}ms", Color.Tan); 
                    result_labels.Add(labels[idx]); 
                }
            }

            return result_labels.Contains("Blues"); 
        }

        private NDArray ReadTensorFromImageFile(string file_name, 
                                int input_height = 288,
                                int input_width = 432,
                                int input_mean = 0,
                                int input_std = 255)
        {
            var graph = tf.Graph().as_default();

            var file_reader = tf.io.read_file(file_name, "file_reader");
            var decodeJpeg = tf.image.decode_jpeg(file_reader, channels: 3, name: "DecodeJpeg");
            var cast = tf.cast(decodeJpeg, tf.float32);
            var dims_expander = tf.expand_dims(cast, 0);
            var resize = tf.constant(new int[] { input_height, input_width });
            var bilinear = tf.image.resize_bilinear(dims_expander, resize);
            var sub = tf.subtract(bilinear, new float[] { input_mean });
            var normalized = tf.divide(sub, new float[] { input_std });

            using (var sess = tf.Session(graph))
                return sess.run(normalized);
        }

        public override void PrepareData()
        {
            //DirectoryInfo di = new DirectoryInfo(dir);
            //di.Delete(true);
            Directory.CreateDirectory(dir);

            // get model file
            string url = "https://github.com/dorodorodororo/trainedmodel/raw/main/trainedmodel.zip"; //my own trained model

            Web.Download(url, dir, "trainedmodel.zip");

            Compress.UnZip(Path.Join(dir, "trainedmodel.zip"), dir);

            // download sample picture
            Directory.CreateDirectory(Path.Join(dir, "img"));

            url = $"https://raw.githubusercontent.com/dorodorodororo/Csharp/main/blues00081.jpg";
            Web.Download(url, Path.Join(dir, "img"), "blues00081.jpg");

            // load image file
            var files = Directory.GetFiles(Path.Join(dir, "img"));
            for (int i = 0; i < files.Length; i++)
            {
                var nd = ReadTensorFromImageFile(files[i]);
                file_ndarrays.Add(nd);
            }
        }
    }
}

It says it expected a dimension of 1, but mine is 3.

So I brought it on Netron and got this flowchart. (It's too large so I just got the output node.)

image

I don't know how to fix this problem.

Can fix this problem by using a V3 model in training instead of V1? (I made this .pb file using V1 model and I think you used model using V3)

I'd appreciate it if you could give me any suggestions or comments.

Thank you Have a nice day!