ruby - 在 tensorflow.rb 上运行保存的模型

标签 ruby tensorflow

我使用高级 Estimator API (DNNClassifier) 在 Python 中构建并保存了一个非常简单的模型。它需要 2 个 float 并输出两个类之一。我正在尝试使用 tensorflow.rb gem 在 Ruby 中加载它,并用它做出预测。这应该很相似to the CAPTCHA example provided by tensorflow.rb .

我使用 export_saved_model 保存了它。这是训练模型的 Python 代码。它可以正确地预测类别。

将 numpy 导入为 np 将 Pandas 导入为 pd 将 tensorflow 导入为 tf

dataframe = pd.read_csv("remediations_import.csv", sep=",")
dataframe = dataframe.reindex(
    np.random.permutation(dataframe.index))

STEPS = 5000
BATCH_SIZE = 10
SAVED_MODEL_FOLDER = 'saved_model'
FEATURE_1 = 'Float_input_1'
FEATURE_2 = 'Float_input_2'
LABEL = "Human_label"

my_feature_data = dataframe[[FEATURE_1, FEATURE_2]]
targets = dataframe[LABEL]

feature_columns = [tf.feature_column.numeric_column(FEATURE_1),
                   tf.feature_column.numeric_column(FEATURE_2)]

features = {key: np.array(value) for key, value in dict(my_feature_data).items()}
training_input_fn = tf.estimator.inputs.numpy_input_fn(x=features,
                                                       y=targets.as_matrix(),
                                                       batch_size=BATCH_SIZE,
                                                       shuffle=True)

classifier = tf.estimator.DNNClassifier(
    feature_columns=feature_columns,
    hidden_units=[10, 10],
    n_classes=2,
    model_dir=SAVED_MODEL_FOLDER)

classifier.train(
    input_fn=training_input_fn,
    steps=STEPS
)

print("Model training finished.")

# Save the model under pb format
features = {'Float_input_1': tf.placeholder(tf.float32, shape=[1]),
            'Float_input_2': tf.placeholder(tf.float32, shape=[1])}
serving_input_receiver_fn = tf.estimator.export.build_raw_serving_input_receiver_fn(features,
                                                                                    default_batch_size=None)
classifier.export_savedmodel(SAVED_MODEL_FOLDER + '_pb', serving_input_receiver_fn, strip_default_attrs=True)

# Predict
new_features = pd.DataFrame({FEATURE_1: [0.97, 0.03], FEATURE_2: [1.00, -1.00]})
# Convert pandas data into a dict of numpy arrays.
features = {key: np.array(value) for key, value in dict(new_features).items()}
prediction_input_fn = tf.estimator.inputs.numpy_input_fn(x=features,
                                                         num_epochs=1,
                                                         shuffle=False)

predictions_results = classifier.predict(input_fn=prediction_input_fn)
predictions = np.array([item['class_ids'][0] for item in predictions_results])
print(predictions)

使用 saved_model_cli 查看我保存的模型显示:

MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['predict']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['Float_input_1'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1)
        name: Placeholder:0
    inputs['Float_input_2'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1)
        name: Placeholder_1:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['class_ids'] tensor_info:
        dtype: DT_INT64
        shape: (-1, 1)
        name: dnn/head/predictions/ExpandDims:0
    outputs['classes'] tensor_info:
        dtype: DT_STRING
        shape: (-1, 1)
        name: dnn/head/predictions/str_classes:0
    outputs['logistic'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: dnn/head/predictions/logistic:0
    outputs['logits'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 1)
        name: dnn/logits/BiasAdd:0
    outputs['probabilities'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 2)
        name: dnn/head/predictions/probabilities:0
  Method name is: tensorflow/serving/predict

我的 tensorflow.rb 获取预测的 Ruby 代码:

saved_model = Tensorflow::Savedmodel.new
saved_model.LoadSavedModel('saved_model_pb', ['serve'], nil)

input = [0.97, 1.00]
feature1_output = saved_model.graph.operation('Placeholder').output(0)
feature2_output = 
saved_model.graph.operation('Placeholder_1').output(0)
classes = saved_model.graph.operation('dnn/head/predictions/str_classes').output(0)
# probabilities = saved_model.graph.operation('dnn/head/predictions/probabilities').output(0)

feature1_tensor = Tensorflow::Tensor.new(input[0])
feature2_tensor = Tensorflow::Tensor.new(input[1])
feeds_tensor_to_output_hash = {feature1_output => feature1_tensor,
                               feature2_output => feature2_tensor}
out_tensor = saved_model.session.run(feeds_tensor_to_output_hash, [classes], [])

puts out_tensor

这会失败并出现没有错误消息的 ArgumentError:

2018-05-22 17:07:08.443115: I tensorflow/cc/saved_model/loader.cc:242] Loading SavedModel with tags: { serve }; from: saved_model_pb/saved_model
2018-05-22 17:07:08.447053: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.2 AVX AVX2 FMA
2018-05-22 17:07:08.452575: I tensorflow/cc/saved_model/loader.cc:161] Restoring SavedModel bundle.
2018-05-22 17:07:08.453012: I tensorflow/cc/saved_model/loader.cc:171] The specified SavedModel has no variables; no checkpoints were restored.
2018-05-22 17:07:08.453024: I tensorflow/cc/saved_model/loader.cc:196] Running LegacyInitOp on SavedModel bundle.
2018-05-22 17:07:08.475575: I tensorflow/cc/saved_model/loader.cc:291] SavedModel load for tags { serve }; Status: success. Took 33095 microseconds.
rake aborted!
ArgumentError: 
.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/bundler/gems/tensorflow.rb-eb3f5bf4f0fd/lib/tensorflow/session.rb:57:in `Session_run'
.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/bundler/gems/tensorflow.rb-eb3f5bf4f0fd/lib/tensorflow/session.rb:57:in `run'
lib/tasks/ml.rake:380:in `block (2 levels) in <top (required)>'

知道我做错了什么吗? CAPTCHA 示例和模型工作正常。我的模型保存正确吗? Here is the saved model that I used.

最佳答案

原来是类型不匹配。我保存模型以接受 float32 变量。 tensorflow.rb created input tensors from Ruby's float type , 这是 float64。

改变这个:

# Save the model under pb format
features = {'Float_input_1': tf.placeholder(tf.float32, shape=[1]),
            'Float_input_2': tf.placeholder(tf.float32, shape=[1])}

对此:

# Save the model under pb format
features = {'Float_input_1': tf.placeholder(tf.float64, shape=[1]),
            'Float_input_2': tf.placeholder(tf.float64, shape=[1])}

解决了问题。

关于ruby - 在 tensorflow.rb 上运行保存的模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50478312/

相关文章:

ruby-on-rails - 在 ruby​​ on rails 上使用 time.now 制作 "if"语句时遇到问题

ruby - 使用 Rspec 断言 Ruby(Chef Recipe)中方法的返回值

c++ - 如何在 Windows 上调试 Tensorflow

python - ValueError : Layer sequential_20 expects 1 inputs, 但它收到 2 个输入张量

python - 加载 tfrecord 文件时出现 InvalidArgumentError

ruby - 为什么安装 ruby​​ 需要 GCC?

ruby capybara - 在运行时获取 xpath

ruby-on-rails - 捆绑exec rake db:迁移成功,但development.sqlite3为空

tensorflow - 卷积层输出大小

python - tensorflow 损失已经很低