gpt4 book ai didi

python - 加载时找不到keras模型的输入层

转载 作者:行者123 更新时间:2023-12-02 11:24:29 25 4
gpt4 key购买 nike

我已经在 Python 中使用 Keras 在 TensorFlow 2.3.1 中训练了一个 Sequential 模型,生成了一个 saved_model.pb 文件,但是当我尝试在 Go 中使用该模型时,我没有看到输入或输出层我指定了,只有偏差和内核。

训练模型的Python代码:

import numpy as np
import pandas as pd

import tensorflow as tf

from tensorflow import feature_column
from tensorflow.keras import layers
from sklearn.model_selection import train_test_split
from sklearn.utils import shuffle
from sklearn import preprocessing
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense

# A utility method to create a tf.data dataset from a Pandas Dataframe
def dataframe_to_dataset(dataframe, shuffle=True, batch_size=32):
dataframe = dataframe.copy()
labels = dataframe.pop("URLType")
ds = tf.data.Dataset.from_tensor_slices((dict(dataframe), labels))
if shuffle:
ds = ds.shuffle(buffer_size=len(dataframe), seed=0)

ds = ds.batch(batch_size)

return ds, labels

# load full data list from csv file
csvList = pd.read_csv("./training-data.csv", sep='\t')

# split the list into training and test data lists
trainingList, _ = train_test_split(csvList, test_size=0.2, random_state=0)
# split the training data list into validation and test data lists
trainingList, validationList = train_test_split(
trainingList, test_size=0.2, random_state=0
)

# print the length of the individual lists
print("training: %d\nvalidation: %d" % (len(trainingList), len(validationList)))

# set up empty list for feature columns
feature_columns = []

# add numeric columns to feature columns
for header in ["ExcessLength", "PathTokens", "NumericPathTokens", "QueryTokens", "NumericQueryTokens", "LongestNumber"]:
feature_columns.append(feature_column.numeric_column(header))

# create datasets of the training and validation dataframes
batch_size = 32

trainDataset, _ = dataframe_to_dataset(
trainingList, shuffle=False, batch_size=batch_size
)

validationDataset, _ = dataframe_to_dataset(
validationList, shuffle=False, batch_size=batch_size
)

# set up the model layers
model = tf.keras.Sequential(
[
layers.DenseFeatures(feature_columns, name="layer_input"),
layers.Dense(128, activation="elu", name="layer_1"),
layers.Dense(128, activation="elu", name="layer_2"),
layers.Dense(128, activation="elu", name="layer_3"),
layers.Dense(1, name="layer_label"),
]
)

# compile the model
model.compile(
optimizer="adam",
loss=tf.keras.losses.Hinge(),
metrics=["accuracy"],
)

# callback to stop training early if the loss starts to increase
earlyStopCallback = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=3)

# train the model
model.fit(trainDataset, validation_data=validationDataset, epochs=5, shuffle=False, callbacks=[earlyStopCallback])

# save the model
model.save("./url_recognizer")
tf.keras.models.save_model(
model=model,
filepath='./url_recognizer',
overwrite=True,
include_optimizer=True,
save_format='tf')

然后当我在 Go 中加载模型并列出所有操作时,没有输入层的痕迹。


import (
"fmt"

tf "github.com/tensorflow/tensorflow/tensorflow/go"
)

func main() {

model, err := tf.LoadSavedModel("url_recognizer", []string{"serve"}, nil)

if err != nil {
fmt.Printf("Error loading saved model: %s\n", err.Error())
return
}

defer model.Session.Close()

ops := model.Graph.Operations()

for _, op := range ops {
fmt.Println(op.Name())
}
}

结果:

sequential/layer_1/kernel
sequential/layer_1/kernel/Read/ReadVariableOp
sequential/layer_1/bias
sequential/layer_1/bias/Read/ReadVariableOp
sequential/layer_2/kernel
sequential/layer_2/kernel/Read/ReadVariableOp
sequential/layer_2/bias
sequential/layer_2/bias/Read/ReadVariableOp
sequential/layer_3/kernel
sequential/layer_3/kernel/Read/ReadVariableOp
sequential/layer_3/bias
sequential/layer_3/bias/Read/ReadVariableOp
sequential/layer_label/kernel
sequential/layer_label/kernel/Read/ReadVariableOp
sequential/layer_label/bias
sequential/layer_label/bias/Read/ReadVariableOp
Adam/iter
Adam/iter/Read/ReadVariableOp
Adam/beta_1
Adam/beta_1/Read/ReadVariableOp
Adam/beta_2
Adam/beta_2/Read/ReadVariableOp
Adam/decay
Adam/decay/Read/ReadVariableOp
Adam/learning_rate
Adam/learning_rate/Read/ReadVariableOp
total
total/Read/ReadVariableOp
count
count/Read/ReadVariableOp
total_1
total_1/Read/ReadVariableOp
count_1
count_1/Read/ReadVariableOp
Adam/sequential/layer_1/kernel/m
Adam/sequential/layer_1/kernel/m/Read/ReadVariableOp
Adam/sequential/layer_1/bias/m
Adam/sequential/layer_1/bias/m/Read/ReadVariableOp
Adam/sequential/layer_2/kernel/m
Adam/sequential/layer_2/kernel/m/Read/ReadVariableOp
Adam/sequential/layer_2/bias/m
Adam/sequential/layer_2/bias/m/Read/ReadVariableOp
Adam/sequential/layer_3/kernel/m
Adam/sequential/layer_3/kernel/m/Read/ReadVariableOp
Adam/sequential/layer_3/bias/m
Adam/sequential/layer_3/bias/m/Read/ReadVariableOp
Adam/sequential/layer_label/kernel/m
Adam/sequential/layer_label/kernel/m/Read/ReadVariableOp
Adam/sequential/layer_label/bias/m
Adam/sequential/layer_label/bias/m/Read/ReadVariableOp
Adam/sequential/layer_1/kernel/v
Adam/sequential/layer_1/kernel/v/Read/ReadVariableOp
Adam/sequential/layer_1/bias/v
Adam/sequential/layer_1/bias/v/Read/ReadVariableOp
Adam/sequential/layer_2/kernel/v
Adam/sequential/layer_2/kernel/v/Read/ReadVariableOp
Adam/sequential/layer_2/bias/v
Adam/sequential/layer_2/bias/v/Read/ReadVariableOp
Adam/sequential/layer_3/kernel/v
Adam/sequential/layer_3/kernel/v/Read/ReadVariableOp
Adam/sequential/layer_3/bias/v
Adam/sequential/layer_3/bias/v/Read/ReadVariableOp
Adam/sequential/layer_label/kernel/v
Adam/sequential/layer_label/kernel/v/Read/ReadVariableOp
Adam/sequential/layer_label/bias/v
Adam/sequential/layer_label/bias/v/Read/ReadVariableOp
NoOp
Const
serving_default_Ending
serving_default_ExcessLength
serving_default_HasArticleToken
serving_default_HasDate
serving_default_IsFile
serving_default_LongestNumber
serving_default_NumericPathTokens
serving_default_NumericQueryTokens
serving_default_OriginalURL
serving_default_PathTokens
serving_default_QueryTokens
StatefulPartitionedCall
saver_filename
StatefulPartitionedCall_1
StatefulPartitionedCall_2

我在网上找到的所有示例代码都显示我应该能够看到名称为 layer_inputlayer_input_input 的操作,但我什么也没看到。

我怀疑问题可能出在 Python 方面,因为在 Go 中使用此方法加载其他预构建模型时,当我列出它们时,我在操作中看到了适当的输入层。

我正在使用以下版本的 Python 和库:

  • python 3.8.5
  • tensorflow 2.3.1
  • Pandas 1.1.2
  • numpy 1.18.5

最佳答案

找出输入签名

keras 的输入层与其他层有些不同。在你的情况下,你的 DenseFeatures层用于定义模型的默认服务签名,即您应该提供给它的输入。

如果我们查看您的 go 示例程序的输出,我们会看到这些行:

serving_default_Ending
serving_default_ExcessLength
serving_default_HasArticleToken
serving_default_HasDate
serving_default_IsFile
serving_default_LongestNumber
serving_default_NumericPathTokens
serving_default_NumericQueryTokens
serving_default_OriginalURL
serving_default_PathTokens
serving_default_QueryTokens

这些操作实际上是您模型的输入。使用 tf.keras.Model 时会自动推断出它们如 documentation 中所述:

Tools like TensorFlow Serving and saved_model_cli can interact with SavedModels. To help these tools determine which ConcreteFunctions to use, you need to specify serving signatures. tf.keras.Models automatically specify serving signatures, but you'll have to explicitly declare a serving signature for our custom modules.

保存模型时,模型的签名(为进行预测而必须提供的输入)是从 DenseFeatures 自动推断出来的.

找出输出签名

您还需要提供输出张量,以便能够通过图形获取操作。很难找到要运行的操作的名称。一个好的技巧是使用 saved_model_cli来自 tensorflow serving 的实用程序。

运行实用程序:

$ saved_model_cli show --dir ./url_recognizer --tag_set serve --signature_def serving_default
The given SavedModel SignatureDef contains the following input(s):
inputs['ExcessLength'] tensor_info:
dtype: DT_INT32
shape: (-1, 1)
name: serving_default_ExcessLength:0

[...]

The given SavedModel SignatureDef contains the following output(s):
outputs['output_1'] tensor_info:
dtype: DT_FLOAT
shape: (-1, 1)
name: StatefulPartitionedCall:0
Method name is: tensorflow/serving/predict

我们看到给出模型输出的 OP 的名称是 StatefulPartitionedCall .

运行预测

如果你想运行预测,你必须使用那些“serving_default”键提供输入,并使用输出键提供输出张量。然后调用 model.Session.Run()

因此我们设法收集了以下信息:

  • 输入被命名为serving_default_<Name of the feature column>
  • 输入具有批量大小(形状 (-1,1))。这意味着模型将期望每个输入都有一个数组。
  • 输出为StatefulPartitionedCall

有了这些,我们可以构建一个运行示例:(仅部分:我省略了其他输入以避免重复,但该模式很容易复制)。

// defining inputs
excessLength, err := tf.NewTensor([1]int32{0})
// otherInput, err := tf.NewTensor([1]int32{0})

// Calling session Run
output, err := model.Session.Run(
map[tf.Output]*tf.Tensor{
model.Graph.Operation("serving_default_ExcessLength").Output(0): excessLength,
// model.Graph.Operation("serving_default_<OtherInput>").Output(0): otherInput,
},
[]tf.Output{
model.Graph.Operation("StatefulPartitionedCall").Output(0),
},
nil)
if err != nil {
fmt.Printf("Error using the model: %s\n", err.Error())
return
}

// Getting the result of the run throigh the graph
val := output[0].Value()
fmt.Printf("Output : %f\n", val)


请注意,使用 Input 时的行为是相似的层代替。

 # set up the model layers
slp = tf.keras.Sequential(
[
# layers.DenseFeatures(feature_columns, name="layer_input"),
layers.Input(shape=(1), name='layer_input'),
layers.Dense(1, name="layer_label", activation='sigmoid'),
]
)

# compile the model
slp.compile(
optimizer="adam", loss='mse', metrics=["accuracy"],
)
slp.save('./url_recognizer')

你的 go 程序输出:

layer_label/kernel
layer_label/kernel/Read/ReadVariableOp
layer_label/bias
layer_label/bias/Read/ReadVariableOp
NoOp
Const
serving_default_layer_input
StatefulPartitionedCall
saver_filename
StatefulPartitionedCall_1

注意 serving_default_layer_input行。

关于python - 加载时找不到keras模型的输入层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64336549/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com