C# 如何序列化dnnclassifier(服务输入接收器)所需的张量输入

C# 如何序列化dnnclassifier(服务输入接收器)所需的张量输入,c#,python,tensorflow,tensorflowsharp,C#,Python,Tensorflow,Tensorflowsharp,我希望能够在使用tensorflowsharp的IIS上使用dnnclassifier(估计器)。该模型以前已经用python进行过训练。到目前为止,我已经能够生成PB文件,知道正确的输入/输出,但是我仍然使用字符串输入来处理tensorflowsharp 我可以创建iris数据集的有效.pb文件。它使用以下功能规格: {'SepalLength': FixedLenFeature(shape=(1,), dtype=tf.float32, default_value=None), 'Sepal

我希望能够在使用tensorflowsharp的IIS上使用dnnclassifier(估计器)。该模型以前已经用python进行过训练。到目前为止,我已经能够生成PB文件,知道正确的输入/输出,但是我仍然使用字符串输入来处理tensorflowsharp

我可以创建iris数据集的有效.pb文件。它使用以下功能规格:

{'SepalLength': FixedLenFeature(shape=(1,), dtype=tf.float32, default_value=None), 'SepalWidth': FixedLenFeature(shape=(1,), dtype=tf.float32, default_value=None), 'PetalLength': FixedLenFeature(shape=(1,), dtype=tf.float32, default_value=None), 'PetalWidth': FixedLenFeature(shape=(1,), dtype=tf.float32, default_value=None)}
我已经创建了一个简单的c#控制台来尝试将其旋转起来。输入应为“输入\示例\张量”,输出位于“dnn/head/预测/概率”中。在alex_zu使用保存的_model_cli命令提供帮助后,我发现了这个问题

据我所知,所有tensorflow估计器API都是这样工作的

问题来了:输入\示例\张量应该是字符串格式,将由ParseExample函数在内部解析。现在我被卡住了。我找到了TFTensor.CreateString,但这并不能解决问题

using System;
using TensorFlow;

namespace repository
{
    class Program
    {
        static void Main(string[] args)
        {
            using (TFGraph tfGraph = new TFGraph()){
                using (var tmpSess = new TFSession(tfGraph)){
                    using (var tfSessionOptions = new TFSessionOptions()){
                        using (var metaGraphUnused = new TFBuffer()){

                            //generating a new session based on the pb folder location with the tag serve
                            TFSession tfSession = tmpSess.FromSavedModel(
                                tfSessionOptions,
                                null,
                                @"path/to/model/pb", 
                                new[] { "serve" }, 
                                tfGraph, 
                                metaGraphUnused
                            );

                            //generating a new runner, which will fetch the tensorflow results later
                            var runner = tfSession.GetRunner();

                            //this is in the actual tensorflow documentation, how to implement this???
                            string fromTensorflowPythonExample = "{'SepalLength': [5.1, 5.9, 6.9],'SepalWidth': [3.3, 3.0, 3.1],'PetalLength': [1.7, 4.2, 5.4],'PetalWidth': [0.5, 1.5, 2.1],}";

                            //this is the problem, it's not working...
                            TFTensor rawInput = new TFTensor(new float[4]{5.1f,3.3f,1.7f,0.5f});
                            byte[] serializedTensor = System.Text.Encoding.ASCII.GetBytes(rawInput.ToString());
                            TFTensor inputTensor = TensorFlow.TFTensor.CreateString (serializedTensor);

                            runner.AddInput(tfGraph["input_example_tensor"][0], inputTensor);
                            runner.Fetch("dnn/head/predictions/probabilities", 0);

                            //start the run and get the results of the iris example
                            var output = runner.Run();
                            TFTensor result = output[0];

                            //printing response to the client
                            Console.WriteLine(result.ToString());
                            Console.ReadLine();
                        } 
                    }
                }
            }
        }
    }
}
此示例将给出以下错误:

An unhandled exception of type 'TensorFlow.TFException' occurred in TensorFlowSharp.dll: 'Expected serialized to be a vector, got shape: []
 [[Node: ParseExample/ParseExample = ParseExample[Ndense=4, Nsparse=0, Tdense=[DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT], dense_shapes=[[1], [1], [1], [1]], sparse_types=[], _device="/job:localhost/replica:0/task:0/device:CPU:0"](_arg_input_example_tensor_0_0, ParseExample/ParseExample/names, ParseExample/ParseExample/dense_keys_0, ParseExample/ParseExample/dense_keys_1, ParseExample/ParseExample/dense_keys_2, ParseExample/ParseExample/dense_keys_3, ParseExample/Const, ParseExample/Const, ParseExample/Const, ParseExample/Const)]]'
如何以正确使用pb文件的方式序列化张量

我还发布了这个问题,在这里您可以找到iris示例python文件、pb文件和控制台应用程序。在我看来,解决这个问题会创造一个
为所有tensorflow用户提供了一个简洁的解决方案,这些用户拥有古老的生产环境(如我)。

预期序列化为矢量的
已成形:[]
错误可以通过使用
TFTensor.CreateString
函数的重载来修复:而不是直接获取字符串,该模型显然需要一个包含单个字符串的向量:

TFTensor inputTensor = TFTensor.CreateString(new byte[][] { bytes }, new TFShape(1));
您案例中的
input\u example\u tensor
现在需要一条序列化的
example
protobuf消息(另请参见和文件)

使用protobuf编译器,我生成了一个C#文件,其中包含
示例
类。您可以从此处下载:。具体来说,我将其与
csharpproto
一起使用,并替换了
import“tensorflow/core/example/feature.proto”中定义的消息的行

将文件添加到项目中后,需要对
Google.Protobuf
的包引用。然后,您可以像这样将序列化示例传递给模型:

Func makeFeature=(float x)=>{
var floatList=new Tensorflow.floatList();
floatList.Value.Add(x);
返回新的Tensorflow.Feature{FloatList=FloatList};
};
var example=new Tensorflow.example{Features=new Tensorflow.Features()};
示例.Features.Feature.Add(“separalength”,makeFeature(5.1f));
示例.Features.Feature.Add(“separawidth”,makeFeature(3.3f));
示例.Features.Feature.Add(“PetalLength”,makeFeature(1.7f));
示例.Features.Feature.Add(“PetalWidth”,makeFeature(0.5f));
TFTensor InputSensor=TFTensor.CreateString(
新的[]{example.ToByteArray()},新的TFShape(1));
runner.AddInput(tfGraph[“input\u example\u tensor”][0],InputSensor);
runner.Fetch(“dnn/head/predictions/probabilities”,0);
//开始运行并获得iris示例的结果
var output=runner.Run();
t传感器结果=输出[0];

@Klass你解决过这个问题吗?目前,我正在尝试加载使用
simple\u save
(python)生成的
pb
文件,并且遇到了类似的问题。