Skip to content
This repository was archived by the owner on Aug 24, 2022. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.DS_Store
.idea/
111 changes: 111 additions & 0 deletions ml_examples/01_smart_contract_model/model.etch
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//------------------------------------------------------------------------------
//
// Copyright 2019 Fetch.AI Limited
//
// Licensed 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.
//
//------------------------------------------------------------------------------

persistent model_state : Model;
persistent data_state : Tensor;
persistent label_state : Tensor;

// initial set up creates the model and persistent data
@init
function setup(owner : Address)
use model_state;
use data_state;
use label_state;

// set up the initial model
var model = model_state.get(Model("sequential"));
model.add("dense", 13u64, 10u64, "relu");
model.add("dense", 10u64, 10u64, "relu");
model.add("dense", 10u64, 1u64);
model.compile("mse", "adam");
model_state.set(model);

// define the initial input data
var data_shape = Array<UInt64>(2);
data_shape[0] = 13u64; // boston feature size is 13
data_shape[1] = 1u64; // batch size == 1
var data = data_state.get(Tensor(data_shape));
data_state.set(data);

// define the initial label
var label_shape = Array<UInt64>(2);
label_shape[0] = 1u64; // house price output size is 1
label_shape[1] = 1u64; // batch size == 1
var label = label_state.get(Tensor(label_shape));
label_state.set(label);

endfunction

// get the data state
@query
function getData() : String
use data_state;
var data = data_state.get();
return data.toString();
endfunction

// get the label state
@query
function getLabel() : String
use label_state;
var label = label_state.get();
return label.toString();
endfunction

// get the current training loss of the model
@query
function evaluate() : String
use model_state;
var model = model_state.get();
var loss = model.evaluate();
var str_loss = toString(loss[0]);
return str_loss;
endfunction

// pass in some data, train the model with it, save the updated model to state
@action
function train(data_string: String, label_string: String)
use model_state;
var model = model_state.get();

use data_state;
var data = data_state.get();
data.fromString(data_string);

use label_state;
var label = label_state.get();
label.fromString(label_string);

var batch_size = 10u64;
model.fit(data, label, batch_size);
model_state.set(model);
endfunction

// make a prediction with the model based on input data passed to function
@query
function predict(data_string: String) : String
use model_state;
var model = model_state.get();

use data_state;
var data = data_state.get();
data.fromString(data_string);

var prediction = model.predict(data);
return prediction.toString();
endfunction
67 changes: 67 additions & 0 deletions ml_examples/01_smart_contract_model/submit_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from fetchai.ledger.api import LedgerApi
from fetchai.ledger.contract import Contract
from fetchai.ledger.crypto import Entity, Address
import sys
import time

DATA_FILE = "/Users/khan/fetch/corpora/boston/boston_data.csv"
LABEL_FILE = "/Users/khan/fetch/corpora/boston/boston_label.csv"

def read_one_line_data_csv_as_string(fname):

f = open(fname, 'r')
return f.readline()


def main(source, train_data, train_labels, test_data, test_labels):

# Create keypair for the contract owner
entity = Entity()
address = Address(entity)

# Setting API up
api = LedgerApi('127.0.0.1', 8000)

# Need funds to deploy contract
api.sync(api.tokens.wealth(entity, 10000000000000))

# Create contract
contract = Contract(source, entity)

# Deploy contract
# api.sync(api.contracts.create(entity, contract, 1000000000))
api.sync(contract.create(api, entity, 1000000000))

# grab the data and label tensor - just to demonstrate usage
data_string = contract.query(api, 'getData')
label_string = contract.query(api, 'getLabel')

# grab boston data set data
data_string = read_one_line_data_csv_as_string(DATA_FILE)
label_string = read_one_line_data_csv_as_string(LABEL_FILE)

print("initial data: " + data_string)
print("initial label: " + label_string)

# train on some input data
fet_tx_fee = 16000000
api.sync(contract.action(api, 'train', fet_tx_fee, [entity], data_string, label_string))

# evaluate the initial loss
initial_loss = contract.query(api, 'evaluate')

# predict loss after training
prediction = contract.query(api, 'predict', data_string=data_string)
print("model prediction: " + prediction)

if __name__ == '__main__':

# Loading contract
if len(sys.argv) != 6:
print("Usage: ", sys.argv[0], "[filename] train_data.csv train_labels.csv test_data.csv test_labels.csv")
exit(-1)

with open(sys.argv[1], "r") as fb:
source = fb.read()

main(source, sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5])
141 changes: 141 additions & 0 deletions ml_examples/02_synergetic_contract_model/model.etch
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
//------------------------------------------------------------------------------
//
// Copyright 2019 Fetch.AI Limited
//
// Licensed 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.
//
//------------------------------------------------------------------------------

persistent model_state : Model;
persistent data_state : Tensor;
persistent label_state : Tensor;
persistent loss_state : Fixed64;

// TODO : createProblem must return the problem - this should wrap up model and data somehow
// TODO : doWork must take in the problem & nonce, and return the solution - solution must be the new model
// TODO : evaluateWork must take in the solution, and return a value
// TODO : applyWork will save the new model to a state, for querying

@init
function setup()
use model_state;
use data_state;
use label_state;

// set up the initial model
var model = model_state.get(Model("sequential"));
model.add("dense", 13u64, 10u64, "relu");
model.add("dense", 10u64, 10u64, "relu");
model.add("dense", 10u64, 1u64);
model.compile("mse", "adam");
model_state.set(model);

// define the initial input data
var data_shape = Array<UInt64>(2);
data_shape[0] = 13u64; // boston feature size is 13
data_shape[1] = 1u64; // batch size == 1
var data = data_state.get(Tensor(data_shape));
data_state.set(data);

// define the initial label
var label_shape = Array<UInt64>(2);
label_shape[0] = 1u64; // house price output size is 1
label_shape[1] = 1u64; // batch size == 1
var label = label_state.get(Tensor(label_shape));
label_state.set(label);

endfunction

// set up a problem around training a machine learning model
@problem
function createProblem(model: Model, data: Tensor, label: Tensor)

return {model, data, label}

endfunction

// get the data state
@query
function getData() : String
use data_state;
var data = data_state.get();
return data.toString();
endfunction

// get the label state
@query
function getLabel() : String
use label_state;
var label = label_state.get();
return label.toString();
endfunction

// evaluates performance as the loss function of the model after training
@objective
function evaluateWork(in_model: String)
use model_state;
var model = model_state.get();
model.fromString(in_model);
return model.evaluate();
endfunction

// the work of training the model
@objective
function doWork(problem : String, nonce : UInt256) : String
use model_state;
use data_state;
use label_state;

var model = model_state.get();
model.fromString(in_model);

// update the learning rate of the local model
var lr = nonce.toFloat64() % 1.0fp64;
model.setLearningRate(lr);

// train the model
var batch_size = 10u64;
var data = data_state.get();
var label = label_state.get();
model.fit(data, label, batch_size);

// return the serialised model
return model.toString();
endfunction

// set the new model to be the specified winner
@clear
function applyWork(in_model: String)
use model_state;
var model = model_state.get();
model.fromString(in_model);
model_state.set(model);
endfunction

// make a prediction with the model based on input data passed to function
@query
function predict(data: Tensor) : Tensor
use model_state;
var model = model_state.get();
var prediction = model.predict(data);
return prediction;
endfunction

// query the current model performance
@query
function evaluate() : Tensor
use model_state;
var model = model_state.get();
return model.evaluate();
endfunction

72 changes: 72 additions & 0 deletions ml_examples/02_synergetic_contract_model/submit_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from fetchai.ledger.api import LedgerApi
from fetchai.ledger.contract import Contract
from fetchai.ledger.crypto import Entity, Address
import sys
import time


def main(source, train_data, train_labels, test_data, test_labels):


# Create keypair for the contract owner
entity = Entity()
address = Address(entity)

# Setting API up
api = LedgerApi('127.0.0.1', 8000)

# Need funds to deploy contract
api.sync(api.tokens.wealth(entity, 10000000000000))

# Create contract
contract = Contract(source, entity)

# Deploy contract
api.sync(contract.create(api, entity, 1000000000))

# Run the synergetic contract

# combine the data and label into one string for passing into the createProblem function
data_string = contract.query(api, 'getData')
label_string = contract.query(api, 'getLabel')
print("initial data: " + data_string)
print("initial label: " + label_string)

# TODO : combine data and label

# pass the combined input data
api.sync(api.contracts.submit_data(entity, contract.digest, contract.address, value = (data_string + label_string)))
api.wait_for_blocks(10)
result = contract.query(api, 'query_result')



# evaluate the initial loss
initial_loss = contract.query(api, 'evaluate')
print("initial loss: " + initial_loss)

# grab the data and label tensor
data_string = contract.query(api, 'getData')
label_string = contract.query(api, 'getLabel')
print("initial data: " + data_string)
print("initial label: " + label_string)

# train on some input data
fet_tx_fee = 16000000
api.sync(contract.action(api, 'train', fet_tx_fee, [entity], data_string, label_string))

# predict loss after training
prediction = contract.query(api, 'predict', data_string=data_string)
print("model prediction: " + prediction)

if __name__ == '__main__':

# Loading contract
if len(sys.argv) != 6:
print("Usage: ", sys.argv[0], "[filename] train_data.csv train_labels.csv test_data.csv test_labels.csv")
exit(-1)

with open(sys.argv[1], "r") as fb:
source = fb.read()

main(source, sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5])