You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by ms...@apache.org on 2020/02/13 05:06:02 UTC
[incubator-teaclave] branch develop updated: [worker] Add
gbdt_prediction function (#224)
This is an automated email from the ASF dual-hosted git repository.
mssun pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git
The following commit(s) were added to refs/heads/develop by this push:
new 048a31b [worker] Add gbdt_prediction function (#224)
048a31b is described below
commit 048a31b06a3b603f3a1f74c53b8e37e5a427c140
Author: Zhaofeng Chen <zf...@apache.org>
AuthorDate: Wed Feb 12 21:05:56 2020 -0800
[worker] Add gbdt_prediction function (#224)
---
.../test_cases/gbdt_prediction/expected_result.txt | 30 +++++
tests/test_cases/gbdt_prediction/model.txt | 1 +
tests/test_cases/gbdt_prediction/test_data.txt | 30 +++++
types/src/worker.rs | 2 +-
worker/src/function/gbdt_prediction.rs | 146 +++++++++++++++++++++
worker/src/function/mod.rs | 3 +
6 files changed, 211 insertions(+), 1 deletion(-)
diff --git a/tests/test_cases/gbdt_prediction/expected_result.txt b/tests/test_cases/gbdt_prediction/expected_result.txt
new file mode 100644
index 0000000..72e7124
--- /dev/null
+++ b/tests/test_cases/gbdt_prediction/expected_result.txt
@@ -0,0 +1,30 @@
+2.0000000000
+1.0000264645
+1.0000264645
+1.0000264645
+2.0000000000
+2.0000000000
+1.0000264645
+2.0000000000
+2.9999732971
+2.0000000000
+2.9999732971
+2.9999732971
+2.9999732971
+2.9999732971
+2.9999732971
+2.9999732971
+1.0000264645
+1.0000264645
+1.0000264645
+2.0000000000
+1.0000264645
+2.0000000000
+1.0000264645
+2.9999732971
+2.9999732971
+2.0000000000
+1.0000264645
+2.9999732971
+1.0000264645
+2.9999732971
diff --git a/tests/test_cases/gbdt_prediction/model.txt b/tests/test_cases/gbdt_prediction/model.txt
new file mode 100644
index 0000000..9b4bf0c
--- /dev/null
+++ b/tests/test_cases/gbdt_prediction/model.txt
@@ -0,0 +1 @@
+{"conf":{"feature_size":4,"max_depth":4,"iterations":100,"shrinkage":0.1,"feature_sample_ratio":1.0,"data_sample_ratio":1.0,"min_leaf_size":1,"loss":"LAD","debug":false,"initial_guess_enabled":false,"training_optimization_level":2},"trees":[{"tree":{"tree":[{"value":{"feature_index":2,"feature_value":2.45,"pred":0.0,"missing":0,"is_leaf":false},"index":0,"left":1,"right":2},{"value":{"feature_index":0,"feature_value":0.0,"pred":1.0,"missing":0,"is_leaf":true},"index":1,"left":0,"right":0 [...]
\ No newline at end of file
diff --git a/tests/test_cases/gbdt_prediction/test_data.txt b/tests/test_cases/gbdt_prediction/test_data.txt
new file mode 100644
index 0000000..74bb8dc
--- /dev/null
+++ b/tests/test_cases/gbdt_prediction/test_data.txt
@@ -0,0 +1,30 @@
+7.7,2.6,6.9,2.3
+6.1,2.9,4.7,1.4
+6.0,2.9,4.5,1.5
+5.8,2.6,4.0,1.2
+7.6,3.0,6.6,2.1
+5.6,2.8,4.9,2.0
+5.5,2.5,4.0,1.3
+7.1,3.0,5.9,2.1
+5.0,3.5,1.6,0.6
+6.7,3.0,5.2,2.3
+4.6,3.4,1.4,0.3
+5.1,3.5,1.4,0.2
+5.4,3.7,1.5,0.2
+5.0,3.4,1.6,0.4
+4.5,2.3,1.3,0.3
+4.9,3.6,1.4,0.1
+7.0,3.2,4.7,1.4
+6.0,2.2,4.0,1.0
+6.0,3.0,4.8,1.8
+6.7,3.1,5.6,2.4
+5.7,2.9,4.2,1.3
+6.1,3.0,4.9,1.8
+6.7,3.1,4.7,1.5
+5.4,3.9,1.3,0.4
+4.8,3.4,1.9,0.2
+6.4,3.2,5.3,2.3
+7.2,3.0,5.8,1.6
+5.0,3.5,1.3,0.3
+6.3,2.5,4.9,1.5
+5.0,3.4,1.5,0.2
diff --git a/types/src/worker.rs b/types/src/worker.rs
index 4051b41..6b21649 100644
--- a/types/src/worker.rs
+++ b/types/src/worker.rs
@@ -209,7 +209,7 @@ where
}
}
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Default)]
pub struct TeaclaveFunctionArguments {
pub args: HashMap<String, String>,
}
diff --git a/worker/src/function/gbdt_prediction.rs b/worker/src/function/gbdt_prediction.rs
new file mode 100644
index 0000000..a06fad1
--- /dev/null
+++ b/worker/src/function/gbdt_prediction.rs
@@ -0,0 +1,146 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#[cfg(feature = "mesalock_sgx")]
+use std::prelude::v1::*;
+
+use std::format;
+use std::io::{self, BufRead, BufReader, Write};
+
+use anyhow;
+use serde_json;
+
+use crate::function::TeaclaveFunction;
+use crate::runtime::TeaclaveRuntime;
+use teaclave_types::TeaclaveFunctionArguments;
+
+use gbdt::decision_tree::Data;
+use gbdt::gradient_boost::GBDT;
+
+#[derive(Default)]
+pub struct GbdtPrediction;
+
+static IN_MODEL: &str = "if_model";
+static IN_DATA: &str = "if_data";
+static OUT_RESULT: &str = "of_result";
+
+impl TeaclaveFunction for GbdtPrediction {
+ fn execute(
+ &self,
+ runtime: Box<dyn TeaclaveRuntime + Send + Sync>,
+ _args: TeaclaveFunctionArguments,
+ ) -> anyhow::Result<String> {
+ let mut json_model = String::new();
+ let mut f = runtime.open_input(IN_MODEL)?;
+ f.read_to_string(&mut json_model)?;
+
+ let model: GBDT = serde_json::from_str(&json_model)?;
+
+ let in_data = runtime.open_input(IN_DATA)?;
+ let test_data = parse_test_data(in_data)?;
+
+ let predict_set = model.predict(&test_data);
+
+ let mut of_result = runtime.create_output(OUT_RESULT)?;
+ for predict_value in predict_set.iter() {
+ writeln!(&mut of_result, "{:.10}", predict_value)?
+ }
+
+ let summary = format!("Predict result has {} lines of data.", predict_set.len());
+ Ok(summary)
+ }
+}
+
+fn parse_data_line(line: &str) -> anyhow::Result<Data> {
+ let trimed_line = line.trim();
+ anyhow::ensure!(!trimed_line.is_empty(), "Empty line");
+
+ let mut features: Vec<f32> = Vec::new();
+ for feature_str in trimed_line.split(',') {
+ let trimed_feature_str = feature_str.trim();
+ anyhow::ensure!(!trimed_feature_str.is_empty(), "Empty feature");
+
+ let feature: f32 = trimed_feature_str.parse()?;
+ features.push(feature);
+ }
+ Ok(Data::new_test_data(features, None))
+}
+
+fn parse_test_data(input: impl io::Read) -> anyhow::Result<Vec<Data>> {
+ let mut samples: Vec<Data> = Vec::new();
+
+ let reader = BufReader::new(input);
+ for line_result in reader.lines() {
+ let line = line_result?;
+ let data = parse_data_line(&line)?;
+ samples.push(data);
+ }
+
+ Ok(samples)
+}
+
+#[cfg(feature = "enclave_unit_test")]
+pub mod tests {
+ use super::*;
+ use teaclave_test_utils::*;
+
+ use std::untrusted::fs;
+
+ use teaclave_types::hashmap;
+ use teaclave_types::TeaclaveFileCryptoInfo;
+ use teaclave_types::TeaclaveFunctionArguments;
+ use teaclave_types::TeaclaveWorkerFileInfo;
+ use teaclave_types::TeaclaveWorkerFileRegistry;
+
+ use crate::function::TeaclaveFunction;
+ use crate::runtime::RawIoRuntime;
+
+ pub fn run_tests() -> bool {
+ run_tests!(test_gbdt_prediction)
+ }
+
+ fn test_gbdt_prediction() {
+ let func_args = TeaclaveFunctionArguments::default();
+
+ let plain_if_model = "test_cases/gbdt_prediction/model.txt";
+ let plain_if_data = "test_cases/gbdt_prediction/test_data.txt";
+ let plain_output = "test_cases/gbdt_prediction/result.txt.out";
+ let expected_output = "test_cases/gbdt_prediction/expected_result.txt";
+
+ let input_files = TeaclaveWorkerFileRegistry::new(hashmap!(
+ IN_MODEL.to_string() =>
+ TeaclaveWorkerFileInfo::new(plain_if_model, TeaclaveFileCryptoInfo::default()),
+ IN_DATA.to_string() =>
+ TeaclaveWorkerFileInfo::new(plain_if_data, TeaclaveFileCryptoInfo::default())
+ ));
+
+ let output_files = TeaclaveWorkerFileRegistry::new(hashmap!(
+ OUT_RESULT.to_string() =>
+ TeaclaveWorkerFileInfo::new(plain_output, TeaclaveFileCryptoInfo::default())
+ ));
+
+ let runtime = Box::new(RawIoRuntime::new(input_files, output_files));
+
+ let function = GbdtPrediction;
+ let summary = function.execute(runtime, func_args).unwrap();
+ assert_eq!(summary, "Predict result has 30 lines of data.");
+
+ let result = fs::read_to_string(&plain_output).unwrap();
+ let expected = fs::read_to_string(&expected_output).unwrap();
+ assert_eq!(&result[..], &expected[..]);
+ }
+}
diff --git a/worker/src/function/mod.rs b/worker/src/function/mod.rs
index 8430b2b..d3bdbf6 100644
--- a/worker/src/function/mod.rs
+++ b/worker/src/function/mod.rs
@@ -34,8 +34,10 @@ pub trait TeaclaveFunction {
// fn handle_event();
}
+mod gbdt_prediction;
mod gbdt_training;
mod mesapy;
+pub use gbdt_prediction::GbdtPrediction;
pub use gbdt_training::GbdtTraining;
pub use mesapy::Mesapy;
mod context;
@@ -48,6 +50,7 @@ pub mod tests {
pub fn run_tests() -> bool {
check_all_passed!(
gbdt_training::tests::run_tests(),
+ gbdt_prediction::tests::run_tests(),
mesapy::tests::run_tests(),
context::tests::run_tests(),
)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org