ml-trust-model

git clone git://git.codymlewis.com/ml-trust-model.git
Log | Files | Refs | README

commit 41d189bbeed25afa32cdd153b9bd4728f1bec7d4
parent aebd00db97d66ef18570aca2a639b760b5f0b181
Author: Cody Lewis <codymlewis@protonmail.com>
Date:   Tue, 16 Apr 2019 08:58:11 +1000

Got some predictions working

Diffstat:
AANN.h5 | 0
MBadMouther/__init__.py | 2+-
MFunctions.py | 4++--
MTrustManager/ANN.py | 21++++++++++++++++++---
MTrustManager/SVM.py | 15++++++++++++---
MTrustManager/__init__.py | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
MTrustModel.py | 76++++++++++++++++++++++++++++++++--------------------------------------------
Arecommendations.gv | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arecommendations.gv.pdf | 0
Mrequirements.txt | 1+
10 files changed, 288 insertions(+), 88 deletions(-)

diff --git a/ANN.h5 b/ANN.h5 Binary files differ. diff --git a/BadMouther/__init__.py b/BadMouther/__init__.py @@ -13,6 +13,6 @@ class BadMouther(Node.Node): A bad mouthing malicious node. ''' def take_note(self, proxy, service_target, capability_target): - if proxy.is_malicious(): # say that other bad mouthers are good + if proxy.is_malicious(): # say that other malicious nodes are good return 1 return -1 diff --git a/Functions.py b/Functions.py @@ -1,7 +1,7 @@ import numpy as np -def print_progress(current_epoch, total_epochs, progress_len=20): +def print_progress(current_epoch, total_epochs, progress_len=31): ''' Print a progress bar about how far a process has went through it's epochs. ''' @@ -15,7 +15,7 @@ def print_progress(current_epoch, total_epochs, progress_len=20): unprogressed = progress_len - 1 progress_bar = "[" progress_bar += "".join( - ["#" for _ in range(progress_bar_progress - 1)] + ["=" for _ in range(progress_bar_progress - 2)] + [">" if unprogressed > 0 else "="] ) progress_bar += "".join(["." for _ in range(unprogressed)]) progress_bar += "]" diff --git a/TrustManager/ANN.py b/TrustManager/ANN.py @@ -26,7 +26,22 @@ def create_and_train_ann(train_data, train_labels, test_data, test_labels): adam = keras.optimizers.Adam(lr=0.0001) model.compile(loss="mean_squared_error", optimizer=adam, metrics=['accuracy']) - model.summary() data = np.array(train_data + test_data) - labels = skp.label_binarize(np.array(train_labels + test_labels), [-1, 0, 1]) - model.fit(x=data, y=labels, epochs=5, validation_split=0.5) + labels = skp.label_binarize(np.array(train_labels + test_labels), ["-1", "0", "1"]) + model.fit(x=data, y=labels, epochs=300, validation_split=0.5) + + return model + + +def get_trusted_list(ann, client_id, service_target, capability_target, no_of_nodes): + trusted_list = dict() + + for i in range(no_of_nodes): + trusted_list[i] = unbinarize(ann.predict(np.array([[client_id, i, service_target, capability_target]]))[0]) + + return trusted_list + + +def unbinarize(arr): + value = list(arr) + return [-1, 0, 1][value.index(max(value))] diff --git a/TrustManager/SVM.py b/TrustManager/SVM.py @@ -31,11 +31,20 @@ def find_accuracy(svm, data, labels): return 100 * corrects / len(labels) +def get_trusted_list(svm, service_target, capability_target, no_of_nodes): + trusted_list = dict() + + for i in range(no_of_nodes): + trusted_list[i] = int(svm.predict([[i, service_target, capability_target]])[0]) + + return trusted_list + + def evolve(train_inputs, train_labels, test_inputs, test_labels): - genome, acc = hill_climb( + genome = hill_climb( train_inputs, train_labels, test_inputs, test_labels ) - return f"{genome[0]},{genome[1]}" + return create_and_fit_svm(train_inputs, train_labels, genome[0], genome[1]) def normalise_genome(genome): @@ -93,4 +102,4 @@ def hill_climb(train_inputs, train_labels, test_inputs, test_labels, acc_goal=99 genome = mutant_genome acc_champ = acc_mutant counter += 1 - return genome, acc_champ + return genome diff --git a/TrustManager/__init__.py b/TrustManager/__init__.py @@ -1,6 +1,9 @@ import csv import numpy as np +import joblib +import graphviz +from tensorflow import keras import Functions import Node @@ -17,10 +20,12 @@ class TrustManager: Create and control the network. ''' def __init__(self, no_of_nodes=50, constrained_nodes=0.5, malicious_nodes=0.1, malicious_reporters=0.1, - train_filename="reports-train.csv", test_filename="reports-test.csv"): + use_svm=True, train_filename="reports-train.csv", test_filename="reports-test.csv"): self.__network = [] self.__train_filename = train_filename self.__test_filename = test_filename + self.__use_svm = use_svm + self.__predicter = None # A real trust model would not be aware of these lists # these are for the training constrained_list = Functions.get_conditioned_ids( @@ -55,12 +60,27 @@ class TrustManager: self.__train_filename = train_filename self.__test_filename = test_filename + def set_use_svm_flag(self, use_svm): + self.__use_svm = use_svm + def get_network(self): return self.__network def get_reports(self): return self.__reports + def get_no_of_nodes(self): + return len(self.__network) + + def reset_predicter(self): + self.__predicter = None + + def save(self): + if self.__predicter: + del self.__predicter + + joblib.dump(self, "trust_manager.pkl") + def bootstrap(self, epochs=100, filewrite=True): ''' Go through the network and perform artificial transactions to develop @@ -106,60 +126,124 @@ class TrustManager: f"{reports_from_node_i[0]},{reports_on_node_j[0]},{reports_on_node_j[1].csv_output()}\n" ) - def train_svm(self): + def train(self): ''' - Fit a pair of SVMs to predict expected notes and observer class respectively. + Train the predicter. ''' - train_data, notes = read_data(self.__train_filename) - note_svm = SVM.create_and_fit_svm(train_data, notes, 5, 0.1) - - return note_svm + if self.__use_svm: + self.evolve_svm() + self.load_svms() + else: + self.train_ann() + self.load_ann() def evolve_svm(self): ''' Perform an evolutionary algorithm to find the optimal values of C and gamma for the respective SVMs. ''' - train_data, train_notes = read_data(self.__train_filename) - test_data, test_notes = read_data(self.__test_filename) + train_data, train_notes = read_data(self.__train_filename, dict_mode=True) + test_data, test_notes = read_data(self.__test_filename, dict_mode=True) - with open("svm_params.csv", "w") as param_file: - total_reporters = len(train_data.keys()) - progress = 0 + svms = dict() + total_reporters = len(train_data.keys()) + progress = 0 + + Functions.print_progress(progress, total_reporters) + for reporter_id in train_data.keys(): + svms[reporter_id] = SVM.evolve( + train_data[reporter_id], train_notes[reporter_id], test_data[reporter_id], test_notes[reporter_id] + ) + progress += 1 Functions.print_progress(progress, total_reporters) - for reporter_id in train_data.keys(): - svm_params = SVM.evolve( - train_data[reporter_id], - train_notes[reporter_id], - test_data[reporter_id], - test_notes[reporter_id] - ) - progress += 1 - Functions.print_progress(progress, total_reporters) - param_file.write(f"{reporter_id},{svm_params}\n") + + joblib.dump(svms, "SVMs.pkl") print() def train_ann(self): - train_data, train_notes = read_data(self.__train_filename, dict_mode=False) - test_data, test_notes = read_data(self.__test_filename, dict_mode=False) - ANN.create_and_train_ann(train_data, train_notes, test_data, test_notes) + train_data, train_notes = read_data(self.__train_filename) + test_data, test_notes = read_data(self.__test_filename) + ANN.create_and_train_ann(train_data, train_notes, test_data, test_notes).save("ANN.h5") - def load_classifiers(self): + def load_svms(self): ''' - Load the classifiers for each node in the network. + Load the kernel machine classifiers for each node in the network. ''' - svms = dict() - data, notes = read_data(self.__train_filename) + self.__predicter = joblib.load("SVMs.pkl") + + def load_ann(self): + ''' + Load the neural network classifier. + ''' + self.__predicter = keras.models.load_model("ANN.h5") + + def get_all_recommendations(self, service_target, capability_target): + trusted_lists = dict() + no_of_nodes = self.get_no_of_nodes() + + for client_id in range(no_of_nodes): + if self.__use_svm: + if not self.__predicter: + self.load_svms() + trusted_lists[client_id] = SVM.get_trusted_list( + self.__predicter[client_id], service_target, capability_target, no_of_nodes + ) + else: + if not self.__predicter: + self.load_ann() + trusted_lists[client_id] = ANN.get_trusted_list( + self.__predicter, client_id, service_target, capability_target, no_of_nodes + ) + + return trusted_lists + + def graph_recommendations(self, client_id, service_target, capability_target): + graph = graphviz.Digraph(comment="Recommendations DiGraph") + trusted_lists = self.get_all_recommendations(service_target, capability_target) + for node_id in range(self.get_no_of_nodes()): + graph.node( + f"{node_id}", + f"{node_id}", + color="red" if self.__network[node_id].is_malicious() else "blue", + style="filled", + fontcolor="white" + ) + for other_node_id, trust_val in trusted_lists[client_id].items(): + graph.edge( + f"{client_id}", + f"{other_node_id}", + color="red" if trust_val == -1 else "purple" if trust_val == 0 else "blue" + ) + graph.render("recommendations.gv", view=False) + + + def find_best_servers(self, client_id, service_target, capability_target): + if self.__use_svm: + if not self.__predicter: + self.load_svms() + trusted_list = SVM.get_trusted_list( + self.__predicter[client_id], service_target, capability_target, len(self.__network) + ) + else: + if not self.__predicter: + self.load_ann() + trusted_list = ANN.get_trusted_list( + self.__predicter, client_id, service_target, capability_target, len(self.__network) + ) + return trusted_list + + +def load(train_filename, test_filename, use_svm): + trust_manager = joblib.load("trust_manager.pkl") - with open("svm_params.csv") as param_file: - param_reader = csv.reader(param_file) - for row in param_reader: - svms[int(row[0])] = SVM.create_and_fit_svm(data, notes, int(row[1]), int(row[2])) + trust_manager.set_filenames(train_filename, test_filename) + trust_manager.set_use_svm_flag(use_svm) + trust_manager.reset_predicter() - return svms + return trust_manager -def read_data(filename, delimiter=",", dict_mode=True): +def read_data(filename, delimiter=",", dict_mode=False): ''' Read data from a csv of reports. ''' diff --git a/TrustModel.py b/TrustModel.py @@ -3,8 +3,6 @@ import sys import argparse -import joblib - import TrustManager import TrustManager.SVM @@ -17,33 +15,31 @@ Date: 2019-03-12 if __name__ == '__main__': - PARSER = argparse.ArgumentParser(description="Simulate a trust model") - PARSER.add_argument("--create-data", dest="is_creating", - action="store_const", const=True, default=False, + PARSER = argparse.ArgumentParser(description="Simulate a trust model which uses either a kernel machine or neural network for trust management.") + PARSER.add_argument("-c", "--create-data", dest="is_creating", action="store_const", const=True, default=False, help="Create data and place it in the csv file.") - PARSER.add_argument("-e", "--epochs", dest="epochs", - action="store", default="200", + PARSER.add_argument("-e", "--epochs", dest="epochs", type=int, action="store", default=200, help="The number of epochs to bootstrap for.") - PARSER.add_argument("-trf", "--train-file", dest="train_filename", - action="store", default="reports-train.csv", + PARSER.add_argument("-trf", "--train-file", dest="train_filename", action="store", default="reports-train.csv", help="Specify the training data file to read from or write to.") - PARSER.add_argument("-tef", "--test-file", dest="test_filename", - action="store", default="reports-test.csv", + PARSER.add_argument("-tef", "--test-file", dest="test_filename", action="store", default="reports-test.csv", help="Specify the test file to read from or write to.") - PARSER.add_argument("--fit-svm", dest="fit_svm", action="store_const", - const=True, default=False, - help="Train an SVM on previously generated data and test on a new network.") - PARSER.add_argument("--evolve-svm", dest="evolve_svm", action="store_const", - const=True, default=False, - help="Perform an evolutionary algorithm to find the optimal values for C and gamma") - PARSER.add_argument("--train-ann", dest="train_ann", action="store_const", - const=True, default=False, - help="Train an ANN on the previously generated data") + PARSER.add_argument("-s", "--svm", dest="use_svm", action="store_const", const=True, default=False, + help="Use a svm as the predicter") + PARSER.add_argument("-a", "--ann", dest="use_ann", action="store_const", const=True, default=False, + help="Use an ann as the predicter") + PARSER.add_argument("-t", "--train", dest="train", action="store_const", const=True, default=False, + help="Train the predicter on the previously generated data") + PARSER.add_argument("-tra", "--transact", dest="transact", action="store", nargs=3, type=int, + metavar=("ID", "SERVICE", "CAPABILITY"), + help="Simulate a single transaction for node ID for SERVICE at CAPABILITY and print out the trusted list.") ARGS = PARSER.parse_args() if len(sys.argv) == 1: PARSER.print_help() + TRUST_MANAGER = None + if ARGS.is_creating: # First blank out file with open(ARGS.train_filename, "w") as FILE: @@ -53,31 +49,23 @@ if __name__ == '__main__': # Then create trust manager and bootstrap TRUST_MANAGER = TrustManager.TrustManager( - train_filename=ARGS.train_filename, test_filename=ARGS.test_filename - ) - TRUST_MANAGER.bootstrap(int(ARGS.epochs)) - joblib.dump(TRUST_MANAGER, "trust_manager.pkl") - - if ARGS.evolve_svm: - print("Evolving...") - TRUST_MANAGER = joblib.load("trust_manager.pkl") - TRUST_MANAGER.set_filenames(ARGS.train_filename, ARGS.test_filename) - TRUST_MANAGER.evolve_svm() - print("Done. Parameters written to svm_params.csv") - - if ARGS.fit_svm: - TRUST_MANAGER = TrustManager.TrustManager( - train_filename=ARGS.train_filename, test_filename=ARGS.test_filename + train_filename=ARGS.train_filename, test_filename=ARGS.test_filename, use_svm=ARGS.use_svm ) - print("Fitting SVM...") - SVM = TRUST_MANAGER.train_svm() - print("SVM fitted") - joblib.dump(SVM, "svm.pkl") - print("Done. SVM saved as svm.pkl") + TRUST_MANAGER.bootstrap(ARGS.epochs) - if ARGS.train_ann: + if ARGS.train: print("Training...") - TRUST_MANAGER = joblib.load("trust_manager.pkl") - TRUST_MANAGER.set_filenames(ARGS.train_filename, ARGS.test_filename) - TRUST_MANAGER.train_ann() + TRUST_MANAGER = TrustManager.load(ARGS.train_filename, ARGS.test_filename, ARGS.use_svm) + TRUST_MANAGER.train() print("Done.") + + if ARGS.transact: + TRUST_MANAGER = TrustManager.load(ARGS.train_filename, ARGS.test_filename, ARGS.use_svm) + ID, SERVICE, CAP = ARGS.transact[0], ARGS.transact[1], ARGS.transact[2] + print(f"Trusted list for node {ID} requesting service {SERVICE} at capability {CAP}") + print() + print(TRUST_MANAGER.find_best_servers(ID, SERVICE, CAP)) + TRUST_MANAGER.graph_recommendations(ID, SERVICE, CAP) + + if TRUST_MANAGER: + TRUST_MANAGER.save() diff --git a/recommendations.gv b/recommendations.gv @@ -0,0 +1,103 @@ +// Recommendations DiGraph +digraph { + 0 [label=0 color=blue fontcolor=white style=filled] + 1 [label=1 color=blue fontcolor=white style=filled] + 2 [label=2 color=blue fontcolor=white style=filled] + 3 [label=3 color=blue fontcolor=white style=filled] + 4 [label=4 color=blue fontcolor=white style=filled] + 5 [label=5 color=blue fontcolor=white style=filled] + 6 [label=6 color=blue fontcolor=white style=filled] + 7 [label=7 color=red fontcolor=white style=filled] + 8 [label=8 color=blue fontcolor=white style=filled] + 9 [label=9 color=blue fontcolor=white style=filled] + 10 [label=10 color=blue fontcolor=white style=filled] + 11 [label=11 color=blue fontcolor=white style=filled] + 12 [label=12 color=blue fontcolor=white style=filled] + 13 [label=13 color=blue fontcolor=white style=filled] + 14 [label=14 color=blue fontcolor=white style=filled] + 15 [label=15 color=blue fontcolor=white style=filled] + 16 [label=16 color=blue fontcolor=white style=filled] + 17 [label=17 color=blue fontcolor=white style=filled] + 18 [label=18 color=red fontcolor=white style=filled] + 19 [label=19 color=blue fontcolor=white style=filled] + 20 [label=20 color=blue fontcolor=white style=filled] + 21 [label=21 color=red fontcolor=white style=filled] + 22 [label=22 color=red fontcolor=white style=filled] + 23 [label=23 color=blue fontcolor=white style=filled] + 24 [label=24 color=blue fontcolor=white style=filled] + 25 [label=25 color=blue fontcolor=white style=filled] + 26 [label=26 color=blue fontcolor=white style=filled] + 27 [label=27 color=blue fontcolor=white style=filled] + 28 [label=28 color=blue fontcolor=white style=filled] + 29 [label=29 color=blue fontcolor=white style=filled] + 30 [label=30 color=blue fontcolor=white style=filled] + 31 [label=31 color=blue fontcolor=white style=filled] + 32 [label=32 color=blue fontcolor=white style=filled] + 33 [label=33 color=blue fontcolor=white style=filled] + 34 [label=34 color=blue fontcolor=white style=filled] + 35 [label=35 color=blue fontcolor=white style=filled] + 36 [label=36 color=blue fontcolor=white style=filled] + 37 [label=37 color=blue fontcolor=white style=filled] + 38 [label=38 color=blue fontcolor=white style=filled] + 39 [label=39 color=blue fontcolor=white style=filled] + 40 [label=40 color=blue fontcolor=white style=filled] + 41 [label=41 color=blue fontcolor=white style=filled] + 42 [label=42 color=blue fontcolor=white style=filled] + 43 [label=43 color=blue fontcolor=white style=filled] + 44 [label=44 color=blue fontcolor=white style=filled] + 45 [label=45 color=blue fontcolor=white style=filled] + 46 [label=46 color=red fontcolor=white style=filled] + 47 [label=47 color=blue fontcolor=white style=filled] + 48 [label=48 color=blue fontcolor=white style=filled] + 49 [label=49 color=blue fontcolor=white style=filled] + 2 -> 0 [color=red] + 2 -> 1 [color=blue] + 2 -> 2 [color=blue] + 2 -> 3 [color=blue] + 2 -> 4 [color=blue] + 2 -> 5 [color=blue] + 2 -> 6 [color=blue] + 2 -> 7 [color=blue] + 2 -> 8 [color=red] + 2 -> 9 [color=purple] + 2 -> 10 [color=red] + 2 -> 11 [color=purple] + 2 -> 12 [color=blue] + 2 -> 13 [color=purple] + 2 -> 14 [color=blue] + 2 -> 15 [color=red] + 2 -> 16 [color=red] + 2 -> 17 [color=blue] + 2 -> 18 [color=purple] + 2 -> 19 [color=purple] + 2 -> 20 [color=blue] + 2 -> 21 [color=blue] + 2 -> 22 [color=red] + 2 -> 23 [color=blue] + 2 -> 24 [color=red] + 2 -> 25 [color=blue] + 2 -> 26 [color=red] + 2 -> 27 [color=blue] + 2 -> 28 [color=red] + 2 -> 29 [color=blue] + 2 -> 30 [color=blue] + 2 -> 31 [color=blue] + 2 -> 32 [color=red] + 2 -> 33 [color=red] + 2 -> 34 [color=blue] + 2 -> 35 [color=blue] + 2 -> 36 [color=red] + 2 -> 37 [color=red] + 2 -> 38 [color=purple] + 2 -> 39 [color=blue] + 2 -> 40 [color=purple] + 2 -> 41 [color=blue] + 2 -> 42 [color=blue] + 2 -> 43 [color=blue] + 2 -> 44 [color=blue] + 2 -> 45 [color=red] + 2 -> 46 [color=blue] + 2 -> 47 [color=purple] + 2 -> 48 [color=purple] + 2 -> 49 [color=blue] +} diff --git a/recommendations.gv.pdf b/recommendations.gv.pdf Binary files differ. diff --git a/requirements.txt b/requirements.txt @@ -2,3 +2,4 @@ numpy joblib scikit-learn tensorflow +graphviz