zoukankan      html  css  js  c++  java
  • 使用C#把Tensorflow训练的.pb文件用在生产环境

    训练了很久的Tf模型,终于要到生产环境中去考研一番了。今天花费了一些时间去研究tf的模型如何在生产环境中去使用。大概整理了这些方法。

    继续使用分步骤保存了的ckpt文件

    这个貌似脱离不了tensorflow框架,而且生成的ckpt文件比较大,发布到生产环境的时候,还得把python的算法文件一起搞上去,如何和其他程序交互,可能还得自己去写服务。估计很少有人这么做,貌似性能也很一般。

    使用tensorflow Serving

    tf Serving貌似是大家都比较推崇的方法。需要编译tfServing,然后把模型导出来。直接执行tf Serving的进程,就可以对外提供服务了。具体调用的时候,还得自己写客户端,使用人gRPC去调用Serving,然后再对外提供服务,听上去比较麻烦。而且我今天没太多的时间去研究gRPC,网络上关于客户端很多都是用python写的,我感觉自己的python水平比较菜,没信心能写好。所以这个方式就先没研究。

    生产.pb文件,然后写程序去调用.pb文件

    生成了.pb文件以后,就可以被程序去直接调用,传入参数,然后就可以传出来参数,而且生成的.pb文件非常的小。而我又有比较丰富的.net开发经验。在想,是否可以用C#来解析.pb文件,然后做一个.net core的对外服务的API,这样貌似更加高效,关键是自己熟悉这款的开发,不用花费太多的时间去摸索。、

    具体的思路

    使用.net下面的TensorFlow框架tensorflowSharp(貌似还是没脱离了框架).去调用pb文件,然后做成.net core web API 对外提供服务。

    具体的实现

    直接上代码,非常简单,本身设计到tensorflowsharp的地方非常的少

                var graph = new TFGraph();
                //重点是下面的这句,把训练好的pb文件给读出来字节,然后导入
                var model = File.ReadAllBytes(model_file);
                graph.Import(model);
    
                    Console.WriteLine("请输入一个图片的地址");
                    var src = Console.ReadLine();
                    var tensor = ImageUtil.CreateTensorFromImageFile(src);
                    
                    using (var sess = new TFSession(graph))
                    {
                        var runner = sess.GetRunner();
                        runner.AddInput(graph["Cast_1"][0], tensor);
                        var r = runner.Run(graph.softmax(graph["softmax_linear/softmax_linear"][0]));
                        var v = (float[,])r.GetValue();
                        Console.WriteLine(v[0,0]);
                        Console.WriteLine(v[0, 1]);
                    }
    

    ImageUtil这个类库是tensorflowSharp官方的例子中一个把图片转成tensor的类库,我直接copy过来了,根据我的网络,修改了几个参数。

    public static class ImageUtil
        {
            public static TFTensor CreateTensorFromImageFile(byte[] contents, TFDataType destinationDataType = TFDataType.Float)
            {
                var tensor = TFTensor.CreateString(contents);
    
                TFOutput input, output;
    
                // Construct a graph to normalize the image
                using (var graph = ConstructGraphToNormalizeImage(out input, out output, destinationDataType))
                {
                    // Execute that graph to normalize this one image
                    using (var session = new TFSession(graph))
                    {
                        var normalized = session.Run(
                            inputs: new[] { input },
                            inputValues: new[] { tensor },
                            outputs: new[] { output });
    
                        return normalized[0];
                    }
                }
            }
            // Convert the image in filename to a Tensor suitable as input to the Inception model.
            public static TFTensor CreateTensorFromImageFile(string file, TFDataType destinationDataType = TFDataType.Float)
            {
                var contents = File.ReadAllBytes(file);
    
                // DecodeJpeg uses a scalar String-valued tensor as input.
                var tensor = TFTensor.CreateString(contents);
    
                TFOutput input, output;
    
                // Construct a graph to normalize the image
                using (var graph = ConstructGraphToNormalizeImage(out input, out output, destinationDataType))
                {
                    // Execute that graph to normalize this one image
                    using (var session = new TFSession(graph))
                    {
                        var normalized = session.Run(
                            inputs: new[] { input },
                            inputValues: new[] { tensor },
                            outputs: new[] { output });
    
                        return normalized[0];
                    }
                }
            }
    
            // The inception model takes as input the image described by a Tensor in a very
            // specific normalized format (a particular image size, shape of the input tensor,
            // normalized pixel values etc.).
            //
            // This function constructs a graph of TensorFlow operations which takes as
            // input a JPEG-encoded string and returns a tensor suitable as input to the
            // inception model.
            private static TFGraph ConstructGraphToNormalizeImage(out TFOutput input, out TFOutput output, TFDataType destinationDataType = TFDataType.Float)
            {
                // Some constants specific to the pre-trained model at:
                // https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip
                //
                // - The model was trained after with images scaled to 224x224 pixels.
                // - The colors, represented as R, G, B in 1-byte each were converted to
                //   float using (value - Mean)/Scale.
    
                const int W = 128;
                const int H = 128;
                const float Mean = 0;
                const float Scale = 1f;
    
                var graph = new TFGraph();
                input = graph.Placeholder(TFDataType.String);
    
                output = graph.Cast(
                    graph.Div(x: graph.Sub(x: graph.ResizeBilinear(images: graph.ExpandDims(input: graph.Cast(graph.DecodeJpeg(contents: input, channels: 3), DstT: TFDataType.Float),
                                dim: graph.Const(0, "make_batch")),
                            size: graph.Const(new int[] { W, H }, "size")),
                        y: graph.Const(Mean, "mean")),
                    y: graph.Const(Scale, "scale")), destinationDataType);
    
                return graph;
            }
        }
    

    搞定

  • 相关阅读:
    【流水账】2021-06-19 Day-09
    【流水账】2021-06-18 Day-08
    【流水账】2021-06-16 Day-06
    【流水账】2021-06-15 Day-05
    .Net调用Java的实现方法
    优先队列的实例题
    栈的相关程序题
    重载函数
    卡特兰数
    关于全排列的递归
  • 原文地址:https://www.cnblogs.com/bbird/p/9953749.html
Copyright © 2011-2022 走看看