简体   繁体   中英

Problem: Export python tensorflow model and load it in ML.Net

I'm trying to play a little bit with ML.Net and keras but i have some questions and problems, maybe i can find the answers:

What i want to achieve: Create a simple NN in Keras, with a hidden layer, 7 inputs and 10 outputs. Export that model, import it in ML.Net and make a prediction there. Part 1: Python code:

features_train = ///an array of 3000x7(values between 0 - 1)
labels_train = //an array(vector) of 3000x1 (with the values between 0-9)

model = tf.keras.models.Sequential([
    tf.keras.layers.InputLayer(input_shape=(7,), dtype=float, name='Features'),
    tf.keras.layers.Dense(50, activation='relu'),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(10, activation='softmax',name='Prediction/Softmax'),
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy']
)

model.fit(features_train, labels_train, epochs=100)
model.save(path_to_save_file, save_format='tf')

If I save it in h5 and open it with netron, i get the following graph(which looks ok) 在此处输入图片说明

The first question: If i set the name of the input layer = "Features", why it's not saved in the model as "Features", but as "input"? The output layer is correctly named.

The second question: If i save it as "tf" format, the whole graph get messed in the netron, the names are changed, you can't understand much thing from it(reported also here ) Why?

Part 2: I import the model(pb file and variables) in VS, and i put the following code:

class House
{
    public float Bathrooms { get; set; }
    public float SqftLiving { get; set; }
    public float SqftLot { get; set; }
    public float Floors { get; set; }
    public float YearBuild { get; set; }
    public float YearRenovated { get; set; }
    public float Price { get; set; }

}

class Prediction
{
    [VectorType(10)]
    public float[] Scores { get; set; }
}


 class Program
    {
        static void Main(string[] args)
        {
            var mlContext = new MLContext();
            var tensorFlowModel = mlContext.Model.LoadTensorFlowModel("....pathToModel"); 

            var pipeline = mlContext.Transforms.Concatenate("Features",
                    new[] { "Bathrooms", "SqftLiving", "SqftLot", "Floors", "YearBuild", "YearRenovated", "Price" })
                .Append(tensorFlowModel.ScoreTensorFlowModel("Prediction/Softmax", "Features"))
                .Append(mlContext.Transforms.CopyColumns("Scores", "Prediction/Softmax"));

            var dataView = mlContext.Data.LoadFromEnumerable(Enumerable.Empty<House>(), tensorFlowModel.GetModelSchema());
            var transformer = pipeline.Fit(dataView);

            var engine = mlContext.Model.CreatePredictionEngine<House, Prediction>(transformer);

        }

    }

When i create the pipeline I get this error: Tensorflow.ValueError: 'Could not find operation "Features" inside graph "grap-key-1/".'

The only way i made it was to not use save_model with tf format anymore, but save it as h5 file, then convert it to onnx via keras2onnx and use the onnx file in .net via ApplyOnnxModel.

Using the tf, the input schema looks like this:

在此处输入图片说明

As you can see, the input is meesed up, the name of the input layer is "serving_default_Features" instead of Features, and you cannot see how the output layer is called.

Do you know why using the pb file generated in python throws that error?

Thanks ^_^

Ok, i found the answer to the .net problem. ML.Net.Tensorflow wants a frozen model. So, if anybody encounters these problems in future: i could freeze the model generate by keras using this https://hellobird.tistory.com/399 (after few adaptations to work with Tf2) and used that generated pb(without pbtxt) file to open it in VS(you have to provide the full path(including the file name) to mlContext.Model.LoadTensorflowModel(in the sentiment analysis sample from ML.Net is just the folder) or it would throw an exception).

Also, i had to inspect the model with Netron to see the actual input/output layer's names in the pb file so i could adapt the pipeline in c#(input layer was named Features_8 for example). and after these changes to the c# code, it worked.

Reference: https://github.com/dotnet/machinelearning/issues/5487

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM