Skip to content

Commit

Permalink
Merge pull request #51 from h1st-ai/aht-graph-hello-world
Browse files Browse the repository at this point in the history
Add HelloWorld graph example
  • Loading branch information
aht authored Sep 25, 2020
2 parents de6556a + 771eff0 commit 77cedcb
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 21 deletions.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,22 @@ Human-First AI (`H1st` AI) solves three critical challenges in real-world data s
## Get started
`H1st` runs on Python 3.7 or above. Install with `pip3 install h1st`.

For a simple example to get started, take a look at the [forecasting example](examples/Forecasting). H1st Model API is designed to work well interactive in notebooks e.g. [examples/Forecasting/notebooks/forecast.ipynb](examples/Forecasting/notebooks/forecast.ipynb) as well as in structured project where models & components are importable e.g. [examples/Forecasting/models/forecast.py](examples/Forecasting//models/forecast.py).
See the [examples/HelloWorld folder](examples/HelloWorld) for simple "Hello world" examples of using
[H1st rule-based](examples/HelloWorld/rule_based_model.py) & [machine-learned models](examples/HelloWorld/ml_model.py) and using [H1st Graph](examples/HelloWorld/helloworld_graph.py).

To fully understand H1st philosophy and features, do check out the [H1st AI Tutorial](https://h1st.ai).
For a simple real-world data science example using H1st Model API, take a look at the [forecasting example](examples/Forecasting).

To fully understand H1st philosophy and power, check out the [H1st Automotive Cybersecurity Tutorial](https://h1st.ai).


## Read the Tutorials and API Documentation
Get started with [H1st Tutorial](https://h1st.ai) and API Documentation at [h1st.ai](https://docs.h1st.ai/).
## Read the Tutorials, Wiki, and API Documentation
We highly recommend following the [H1st Automotive Cybersecurity Tutorial](https://h1st.ai) as well as the quick-start examples in the [examples/HelloWorld folder](examples/HelloWorld).

See the wiki for design consideration e.g. [H1st.AI Model Explained](../../wiki/Human-First-AI-Graph-Explained), [H1st.AI Graph Explained](../../wiki/Human-First-AI-Graph-Explained).

Our full API Documentation is at [docs.h1st.ai](https://docs.h1st.ai/).

See our public [H1st.AI's roadmap](../../wiki/Human-First-AI-Roadmap).

## Join and Learn from Our Open-Source Community
We are collaborating with the open-source community. For Arimo-Panasonic, use cases include industrial applications such as Cybersecurity, Predictive Maintenance, Fault Prediction, Home Automation, Avionic & Automotive Experience Management, etc.
Expand Down
20 changes: 16 additions & 4 deletions examples/HelloWorld/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
Best way to quickly see this in action is to run the test suite:
This is a super quick guide to using H1st!

You can & should examine each file and run each example individually:

```
% nose2
python3 rule_based_model.py
python3 ml_model.py
python3 helloworld_graph.py
```

Some of the examples may require that you install various standard frameworks, e.g., `scikitlearn`
To quickly see everything in action at once, run the test suite:

```
% nose2
```

Some of the examples may require that you install various standard frameworks, e.g., `scikitlearn`.

```
% pip3 install -U scikit-learn
% pip3 install -U scikit-learn nose2
```

For a more complex example that demonstrate the power of H1st graph in a real-world use case,
see the [AutoCyber tutorial](../AutoCyber)
34 changes: 34 additions & 0 deletions examples/HelloWorld/helloworld_graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""
This is an example of a very simple graph which prints hello for each even number x in the input stream,
using a conditional RuleBasedModel node and a HelloPrinter h1.Action.
"""

import h1st as h1
from rule_based_model import RuleBasedModel

class HelloPrinter(h1.Action):
"""Print hello to the inputs value"""
def call(self, command, inputs):
# Note that H1st does the conditional/filtering orchestration already.
# All we need to do here is just to print.
for d in inputs["predictions"]:
print("Hello world {}!".format(d["value"]))


def create_graph():
"""Create a graph which prints hello for each even number x in the input stream,
using a conditional RuleBasedModel node and a HelloPrinter h1.Action."""
graph = h1.Graph()
graph.start()\
.add(h1.Decision(RuleBasedModel(), result_field="predictions"))\
.add(yes=HelloPrinter(), no=h1.NoOp())
graph.end()
return graph

if __name__ == "__main__":
graph = create_graph()
results = graph.predict({"values": range(6)})
# Should get:
# Hello world 0!
# Hello world 2!
# Hello world 4!
34 changes: 29 additions & 5 deletions examples/HelloWorld/ml_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

class MLModel(h1.MLModel):
def __init__(self):
self._native_model = svm.SVC(gamma=0.001, C=100.)
# This is the native SKLearn model
# H1st can automatically save/load this "self.model" property if it's a SKlearn or tf.keras.Model
self.model = svm.SVC(gamma=0.001, C=100.)

def get_data(self):
digits = datasets.load_digits()
Expand All @@ -33,15 +35,37 @@ def prep(self, data):
}

def train(self, prepared_data):
self._native_model.fit(prepared_data["train_x"], prepared_data["train_y"])
self.model.fit(prepared_data["train_x"], prepared_data["train_y"])

def evaluate(self, data):
pred_y = self.predict({"x": data["test_x"]})
metric = metrics.accuracy_score(data["test_y"], pred_y)
return metric
# self.metrics can also be persisted automatically by H1st
self.metrics = metrics.accuracy_score(data["test_y"], pred_y)
return self.metrics

def predict(self, input_data: dict) -> dict:
"""
We expect an array of input data rows in the "x" field of the input_data dict
"""
return self._native_model.predict(input_data["x"])
return self.model.predict(input_data["x"])

if __name__ == "__main__":
h1.init(MODEL_REPO_PATH=".models")

m = MLModel()
raw_data = m.get_data()
print(raw_data)

prepared_data = m.prep(raw_data)
print(prepared_data['train_x'].shape)
print(prepared_data['test_x'].shape)

m.train(prepared_data)
m.evaluate(prepared_data)
print("accuracy_score = %.4f" % m.metrics)

version_id = m.persist()
print("Persisted to version_id = %s" % version_id)
m = MLModel().load(version_id)
print(m.metrics)

11 changes: 9 additions & 2 deletions examples/HelloWorld/rule_based_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,12 @@ class RuleBasedModel(h1.Model):
Simple rule-based model that "predicts" if a given value is an even number
"""
def predict(self, input_data: dict) -> dict:
is_even = (input_data["value"] % 2 == 0)
return {"result": is_even}
predictions = [{'prediction': x % 2 == 0, 'value': x} for x in input_data["values"]]
return {"predictions": predictions}

if __name__ == "__main__":
m = RuleBasedModel()
xs = list(range(6))
results = m.predict({"values": xs})
predictions = results["predictions"]
print(f"RuleBasedModel's predictions for {xs} are {predictions}")
26 changes: 21 additions & 5 deletions examples/HelloWorld/tests/test_hello_world.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
import unittest
import h1st as h1

from HelloWorld.rule_based_model import RuleBasedModel
from HelloWorld.ml_model import MLModel
from HelloWorld.helloworld_graph import create_graph


class TestHellloWorld(unittest.TestCase):

def test_rule_based_model(self):
m = RuleBasedModel()
for value in range(6):
prediction = m.predict({"value": value})
print("Prediction for " + str(value) + " is " + str(m.predict({"value": value})))
self.assertTrue(prediction["result"] == (value % 2 == 0))

xs = list(range(6))
results = m.predict({"values": xs})
print(f"RuleBasedModel's predictions for {xs} is {results}")
self.assertTrue(results["predictions"] == [
{'prediction': True, 'value': 0}, {'prediction': False, 'value': 1}, {'prediction': True, 'value': 2}, {'prediction': False, 'value': 3}, {'prediction': True, 'value': 4}, {'prediction': False, 'value': 5}])

def test_ml_model(self):
h1.init(MODEL_REPO_PATH=".models")
m = MLModel()
raw_data = m.get_data()
prepared_data = m.prep(raw_data)

m.train(prepared_data)
metric = m.evaluate(prepared_data)
print("metric = ", str(metric))
self.assertGreaterEqual(metric, 0.9)

version_id = m.persist()
print("Persisted to version_id = %s" % version_id)
m = MLModel().load(version_id)
self.assertGreaterEqual(m.metrics, 0.9)

def test_graph(self):
graph = create_graph()
results = graph.predict({"values": range(6)})
print(results)
self.assertEqual(results, {'predictions': [{'prediction': True, 'value': 0}, {'prediction': False, 'value': 1}, {'prediction': True, 'value': 2}, {'prediction': False, 'value': 3}, {'prediction': True, 'value': 4}, {'prediction': False, 'value': 5}]})
2 changes: 1 addition & 1 deletion h1st/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from h1st.core.model import Model
from h1st.core.ml_model import MLModel
from h1st.core.rule_based_model import RuleBasedModel
from h1st.core.node import Action, Decision
from h1st.core.node import Action, Decision, NoOp
from h1st.core.exception import GraphException
from h1st.core.node_containable import NodeContainable
from h1st.core.trust.explainable import Explainable
Expand Down
6 changes: 6 additions & 0 deletions h1st/core/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@ def to_dot_node(self, visitor):
return visitor.render_dot_action_node(self)


class NoOp(Action):
"""A do-nothing action."""
def call(self, command, inputs):
pass


class Decision(Action):
"""
H1st conditional node
Expand Down

0 comments on commit 77cedcb

Please sign in to comment.