commit 5bf8b03f0031b6371c5cee5bacbfc104bc83fbe9
parent 6f4dbf0ccd5f0b429c1a059c2616e12d560200cb
Author: Cody Lewis <codymlewis@protonmail.com>
Date: Thu, 11 Apr 2019 14:29:15 +1000
Started on evolutionary algorithm for SVM
Diffstat:
6 files changed, 182 insertions(+), 18 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -391,4 +391,5 @@ TSWLatexianTemp*
tags
tags.lock
Session.vim
-reports.csv
+*.csv
+*.pkl
diff --git a/Test.py b/Test.py
@@ -113,7 +113,7 @@ class TestTrustModel(unittest.TestCase):
no_of_transactions = 5
trust_manager.bootstrap(no_of_transactions)
- self.assertEqual(np.shape(trust_manager.get_reports()), (200, 200))
+ self.assertEqual(np.shape(trust_manager.get_reports()), (50, 50))
if __name__ == '__main__':
diff --git a/TrustManager/SVM.py b/TrustManager/SVM.py
@@ -1,3 +1,4 @@
+import numpy as np
from sklearn.svm import SVC
'''
@@ -28,3 +29,85 @@ def find_accuracy(svm, data, labels):
corrects += 1
return 100 * corrects / len(labels)
+
+
+def evolve(train_inputs, train_labels, test_inputs, test_labels):
+ genome, acc = hill_climb(
+ train_inputs, train_labels, test_inputs, test_labels
+ )
+ return f"C: {genome[0]}, gamma: {genome[1]}, accuracy: {acc}"
+
+
+def normalise_genome(genome):
+ for index_gene in enumerate(genome):
+ while genome[index_gene[0]] <= 0:
+ genome[index_gene[0]] = \
+ float(np.random.normal(10, 8, 1))
+
+
+def generate_genome():
+ '''
+ Generate a random starting genome.
+ '''
+ return [float(g) for g in list(np.random.normal(50, 20, 2))]
+
+
+def mutate_genome(genome):
+ '''
+ Take a genome and mutate it, return the mutant.
+ '''
+ step_size = 0.1 * np.random.normal(0, 5)
+ mutant_genome = genome.copy()
+
+ if np.random.normal() < 0:
+ return generate_genome() # Introduce annealing
+
+ for index_mutant_genome in enumerate(mutant_genome):
+ mutant_genome[index_mutant_genome[0]] += \
+ float(step_size * np.random.normal(0, 5))
+
+ return mutant_genome
+
+
+def crossover(genome_a, genome_b):
+ '''
+ Possibly crossover genome_b into genome_a and return the result.
+ '''
+ crossover_genome = []
+ crossed_over = False
+
+ for gene_pair in zip(genome_a, genome_b):
+ if not crossed_over and np.random.normal() < 0:
+ crossover_genome.append(gene_pair[1])
+ else:
+ crossover_genome.append(gene_pair[0])
+
+ return crossover_genome
+
+
+def hill_climb(train_inputs, train_labels, test_inputs, test_labels, acc_goal=99):
+ '''
+ Evolutionary algorithm to find the optimal number of neurons for the ANN.
+ '''
+ counter = 0
+ n_epochs = 100_000
+ genome = generate_genome()
+ svm_champ = create_and_fit_svm(
+ train_inputs, train_labels, genome[0], genome[1]
+ )
+ acc_champ = find_accuracy(svm_champ, test_inputs, test_labels)
+
+ while (acc_champ < acc_goal) and (counter < n_epochs):
+ mutant_genome = mutate_genome(genome)
+ mutant_genome = crossover(mutant_genome, genome)
+ print(f"Epoch: {counter}, Current mutant genome: {mutant_genome}, Current champion genome: {genome} at accuracy: {acc_champ}")
+ svm_mutant = create_and_fit_svm(
+ train_inputs, train_labels, mutant_genome[0], mutant_genome[1]
+ )
+ acc_mutant = find_accuracy(svm_mutant, test_inputs, test_labels)
+
+ if acc_mutant > acc_champ:
+ genome = mutant_genome
+ acc_champ = acc_mutant
+ counter += 1
+ return genome, acc_champ
diff --git a/TrustManager/__init__.py b/TrustManager/__init__.py
@@ -1,24 +1,32 @@
+import csv
+
import numpy as np
import Functions
import Node
import BadMouther
+import TrustManager.SVM as SVM
class TrustManager:
'''
Create and control the network.
'''
- def __init__(self, no_of_nodes=200, constrained_nodes=0.5,
- poor_witnesses=0.2, malicious_nodes=0.1):
+ def __init__(self, no_of_nodes=50, constrained_nodes=0.5,
+ poor_witnesses=0.2, malicious_nodes=0.1,
+ train_filename="reports-train.csv", test_filename="reports-test_csv"):
self.__network = []
+ self.__train_filename = train_filename
+ self.__test_filename = test_filename
+ # A real trust model would not be aware of these lists
+ # these are for the training
constrained_list = Functions.get_conditioned_ids(
no_of_nodes, constrained_nodes
)
- poor_witness_list = Functions.get_conditioned_ids(
+ self.poor_witness_list = Functions.get_conditioned_ids(
no_of_nodes, poor_witnesses
)
- malicious_list = Functions.get_conditioned_ids(
+ self.malicious_list = Functions.get_conditioned_ids(
no_of_nodes, malicious_nodes
)
@@ -29,8 +37,8 @@ class TrustManager:
else:
service = 100
capability = 100
- note_acc = np.random.rand() if i in poor_witness_list else 1.0
- if i in malicious_list:
+ note_acc = np.random.rand() if i in self.poor_witness_list else 1.0
+ if i in self.malicious_list:
self.__network.append(
BadMouther.BadMouther(service, capability, note_acc)
)
@@ -41,6 +49,10 @@ class TrustManager:
[None for _ in range(no_of_nodes)] for _ in range(no_of_nodes)
]
+ def set_filenames(self, train_filename, test_filename):
+ self.__train_filename = train_filename
+ self.__test_filename = test_filename
+
def get_network(self):
return self.__network
@@ -59,7 +71,7 @@ class TrustManager:
Functions.print_progress(i, epochs)
print("Done.")
- def __artificial_transactions(self, current_epoch):
+ def __artificial_transactions(self, current_epoch, report_filename=None):
'''
Perform some transactions through the entire network with random
targets.
@@ -75,9 +87,10 @@ class TrustManager:
capability_target,
current_epoch
)
- self.save_reports_csv()
+ if report_filename:
+ self.save_reports_csv(report_filename)
- def save_reports_csv(self, filename="reports.csv"):
+ def save_reports_csv(self, filename):
'''
Save a csv on the report data
'''
@@ -85,6 +98,39 @@ class TrustManager:
for reports_from_node_i in enumerate(self.__reports):
for reports_on_node_j in enumerate(reports_from_node_i[1]):
if reports_from_node_i[0] != reports_on_node_j[0]:
+ if reports_from_node_i[0] in self.malicious_list:
+ observer_class = 2
+ elif reports_from_node_i[0] in self.poor_witness_list:
+ observer_class = 1
+ else:
+ observer_class = 0
report_csv.write(
- f"{reports_from_node_i[0]},{reports_on_node_j[0]},{reports_on_node_j[1].csv_output()}\n"
+ f"{reports_from_node_i[0]},{reports_on_node_j[0]},{reports_on_node_j[1].csv_output()},{observer_class}\n"
)
+
+ def read_data(self, filename, delimiter=","):
+ train_data = []
+ notes = []
+ observer_class = []
+
+ with open(filename) as report_csv:
+ csv_reader = csv.reader(report_csv, delimiter=delimiter)
+ for row in csv_reader:
+ train_data.append(row[:4] + row[5:-1])
+ notes.append(row[4])
+ observer_class.append(row[-1])
+
+ return train_data, notes, observer_class
+
+ def train_svm(self):
+ print("Reading data...")
+ train_data, notes, observer_class = self.read_data()
+ print("Training SVMs...")
+ note_svm = SVM.create_and_fit_svm(train_data, notes, 5, 0.1)
+ # witness_svm = SVM.create_and_fit_svm(train_data, observer_class, 5, 0.1)
+
+ return note_svm # , witness_svm
+
+ def evolve_svm(self):
+ data, notes, observer_class = self.read_data()
+ return SVM.evolve(data, notes, data, notes)
diff --git a/TrustModel.py b/TrustModel.py
@@ -3,7 +3,10 @@
import sys
import argparse
+import joblib
+
import TrustManager
+import TrustManager.SVM
'''
A trust model simulation which uses machine learning techniques to find trust.
@@ -18,15 +21,43 @@ if __name__ == '__main__':
PARSER.add_argument("--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("-f", "--file", dest="filename",
- action="store", default="reports.csv",
- help="Specify the file to read from or write to.")
+ 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",
+ 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")
ARGS = PARSER.parse_args()
if len(sys.argv) == 1:
PARSER.print_help()
if ARGS.is_creating:
- TRUST_MANAGER = TrustManager.TrustManager()
- TRUST_MANAGER.bootstrap(500)
- TRUST_MANAGER.save_reports_csv(ARGS.filename)
+ # First blank out file
+ with open(ARGS.filename, "w") as FILE:
+ FILE.write("")
+
+ # Then create trust manager and bootstrap
+ TRUST_MANAGER = TrustManager.TrustManager(filename=ARGS.filename)
+ TRUST_MANAGER.bootstrap(1)
+ joblib.dump(TRUST_MANAGER, "trust_manager.pkl")
+
+ if ARGS.evolve_svm:
+ print("Evolving...")
+ TRUST_MANAGER = joblib.load("trust_manager.pkl")
+ TRUST_MANAGER.set_filename(ARGS.filename)
+ print(TRUST_MANAGER.evolve_svm())
+
+ if ARGS.fit_svm:
+ TRUST_MANAGER = TrustManager.TrustManager(filename=ARGS.filename)
+ print("Fitting SVM...")
+ SVM = TRUST_MANAGER.train_svm()
+ print("SVM fitted")
+ joblib.dump(SVM, "svm.pkl")
+ print("Done. SVM saved as svm.pkl")
diff --git a/requirements.txt b/requirements.txt
@@ -1 +1,4 @@
numpy
+joblib
+scikit-learn
+tensorflow