C# 利用tensorflowsharp調用Tesnorflow模型預測
有時我們會用到C#來部署tensorflow或者keras的訓練模型,,其中會就涉及到模型的加載和調用,。C#已經開發(fā)了相關支持包TensorFlowSharp。該插件可以在NuGet中獲取并安裝,。當前使用的VS2015, Python 3.6,Pycharm2018.1 ,tensorflow2.0
訓練模型的生成
利用python訓練模型,,這里不再詳細介紹如何訓練模型。后續(xù)會專門來做一章節(jié)來介紹這一塊內容,。當前應用是用以簡單的貫序模型做圖片的二分類,。由于用keras生成的模型是.h5的文件,需要轉換成可以用tensorflow調用的.pb文件,。轉換的相關代碼如下,。
from keras import layers, models
from keras.preprocessing.image import ImageDataGenerator
import numpy as np
import tensorflow.compat.v1 as tf1
import tensorflow as tf
def seq_model(X_train, X_val, Y_train, Y_val, img_width, img_height, batch_size):
nb_train_samples = len(X_train)
nb_validation_samples = len(X_val)
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), input_shape=(img_width, img_height, 3)))
model.add(layers.Activation('relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Conv2D(32, (3, 3)))
model.add(layers.Activation('relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Conv2D(64, (3, 3)))
model.add(layers.Activation('relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(64))
model.add(layers.Activation('relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1))
model.add(layers.Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
model.summary()
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
val_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
train_generator = train_datagen.flow(np.array(X_train), Y_train, batch_size=batch_size)
validation_generator = val_datagen.flow(np.array(X_val), Y_val, batch_size=batch_size)
history = model.fit_generator(
train_generator,
steps_per_epoch=nb_train_samples // batch_size,
epochs=100,
validation_data=validation_generator,
validation_steps=nb_validation_samples // batch_size
)
model.save_weights('model_wieghts.h5')
model.save('model_keras.h5')
print('input is :', model.input.name)
print('output is:', model.output.name)
tf1.reset_default_graph()
tf1.keras.backend.set_learning_phase(0) # 調用模型前一定要執(zhí)行該命令
tf1.disable_v2_behavior() # 禁止tensorflow2.0的行為
network = tf.keras.models.load_model('model_keras.h5')
frozen_graph = freeze_session(tf1.keras.backend.get_session(),
output_names=[out.op.name for out in network.outputs])
tf1.train.write_graph(frozen_graph, "D:\AI Vision\AICore", "saved2pb.pb", as_text=False)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
在訓練完之后,請一定要記下他的輸入層和輸出層名稱,,在C#中調用時需要用作配置參數,。
C#中部署.pb訓練模型
注意事項
在C#中如果需要調用tesorflow加載訓練模型。
- .net版本在4.6以上,,本版本使用4.7.2
2.使用64位系統(tǒng),,去掉勾選Prefer 32-bit。.引用命名空間
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing.Imaging;
using System.IO;
using TensorFlow;
using LT.ST;
using System.Drawing;
using LT.ST.Element;
讀取模型
//modelFile為.pb訓練文件路徑
private TFGraph LoadModel(string modelFile)
{
var g = new TFGraph();
var model = File.ReadAllBytes(modelFile);
g.Import(model, "");
return g;
}
獲取輸入圖形張量
//inputFileName 輸入圖片的路徑
public unsafe TFTensor CreateTensorFromImageFileAlt(string inputFileName, TFDataType destinationDataType = TFDataType.Float)
{
Bitmap bitmap = new Bitmap(inputFileName);
//需要將圖片處理成訓練樣本的相同大小
int w = dataDirectorLocal.CurrProject.fWidth;//訓練時圖片寬度
int h = dataDirectorLocal.CurrProject.fHeighth;//訓練時圖片高度
Bitmap resizedBmp = new Bitmap(w, h);
Graphics g = Graphics.FromImage(resizedBmp);
//設置高質量插值法
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
//設置高質量,低速度呈現平滑程度
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
//消除鋸齒
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.DrawImage(bitmap, new Rectangle(0, 0, w, h), new Rectangle(0, 0, bitmap.Width, bitmap.Height), GraphicsUnit.Pixel);
BitmapData data = resizedBmp.LockBits(new Rectangle(0, 0, resizedBmp.Width, resizedBmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
var matrix = new float[1, resizedBmp.Width, resizedBmp.Height, 3];
byte* scan0 = (byte*)data.Scan0.ToPointer();
for (int i = 0; i < data.Height; i++)
{
for (int j = 0; j < data.Width; j++)
{
byte* pixelData = scan0 + i * data.Stride + j * 3;
matrix[0, i, j, 0] = pixelData[2];
matrix[0, i, j, 1] = pixelData[1];
matrix[0, i, j, 2] = pixelData[0];
}
}
resizedBmp.UnlockBits(data);
TFTensor tensor = matrix;
g.Dispose();
resizedBmp.Dispose();
bitmap.Dispose();
return tensor;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
開始測試和預測
public bool TensorAnalysisFromFile(string modelFile, string[] labelsFiles)
{
// 創(chuàng)建圖
try
{
var g = new TFGraph();
g = LoadModel(modelFile);
dataDirectorLocal.Images.Clear();
foreach (var labelsFile in labelsFiles)
{
// 定義常量
using (var session = new TFSession(g))
{
var tensor = CreateTensorFromImageFileAlt(labelsFile);
var runner = session.GetRunner();
//訓練時的輸入和輸出名稱
runner.AddInput(g["conv2d_1_input"][0], tensor);
runner.Fetch(g["activation_5/Sigmoid"][0]);
var output = runner.Run();
var result = output[0];
var rshape = result.Shape;
if (result.NumDims != 2 || rshape[0] != 1)
{
var shape = "";
foreach (var d in rshape)
{
shape += $"3squ974rb ";
}
shape = shape.Trim();
Console.WriteLine($"Error: expected to produce a [1 N] shaped tensor where N is the number of labels, instead it produced one with shape [{shape}]");
Environment.Exit(1);
}
bool jagged = true;
var bestIdx = 0;
float p = 0, best = 0;
var probabilities = ((float[][])result.GetValue(jagged: true))[0];
ImageStruct img = new ImageStruct();
img.strSource = labelsFile;
img.Factor = (float)probabilities[0];
img.Name = img.Factor < 0.5 ? dataDirectorLocal.LabelCatetorys[1].Name : dataDirectorLocal.LabelCatetorys[2].Name;
img.backgroud2 = img.Factor < 0.5 ? dataDirectorLocal.LabelCatetorys[1].Color : dataDirectorLocal.LabelCatetorys[2].Color;
img.iTested = img.Factor < 0.5 ? dataDirectorLocal.LabelCatetorys[1].Key : dataDirectorLocal.LabelCatetorys[2].Key;
dataDirectorLocal.Images.Add(img);
}
}
}
catch (Exception e)
{
return false;
}
return true;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
程序測試成功如下
|