import math import random initial_rate = 0.005 fnpair = 0 if fnpair == 1: # ReLu def logi(x): if x > 0: return x return 0 def dlogi(x): if x > 0: return 1 return 0 elif fnpair == 2: # tanh def logi(x): y = math.exp(x) return (y - 1 / y) / (y + 1 / y) def dlogi(x): y = math.exp(x) s = 2 / (y + 1 / y) return s * s elif fnpair == 3: # softplus def logi(x): return math.log(1 + math.exp(x)) def dlogi(x): return 1 / (1 + math.exp(- x)) else: # logistic def logi(x): return 1 / (1 + math.exp(- x)) def dlogi(x): y = logi(x) return y * (1 - y) def test_logi(): for i in range(-10, -1): print(i, logi(i)) for i in range(-10, 10): print(i / 10, logi(i / 10)) for i in range(2, 11): print(i, logi(i)) class neuron: def __init__(self, numin): self.num = numin self.wts = [random.random() * 2 + 1 for i in range(0, numin)] self.bias = random.random() * 2 + 1 self.out = 0 self.first_wrong = -1 self.rate = initial_rate def compute(self, inps): self.inps = inps self.total = self.bias for i in range(0, self.num): self.total += self.wts[i] * self.inps[i] self.out = logi(self.total) def correct_towards(self, correct, verbose = False): change = self.rate * (correct - self.out) * dlogi(self.total) for i in range(0, self.num): self.wts[i] += change * self.inps[i] self.bias += change def torf(x): return 1 if x else 0 def fn1(xs): return torf(xs[0] + xs[1] > 0.7) def fn2(xs): return torf(xs[0] < 0.5 and xs[1] < 0.75) def fn3(xs): return torf(xs[0] - xs[1] > 0.5) def correct_answers(inps): return [fn1(inps), fn2(inps), fn3(inps)] def test_correct_answers(): for y in range(10, -1, -1): for x in range(0, 11): aa = correct_answers([x / 10, y / 10]) for i in range(0, len(aa)): print(i if aa[i] == 1 else " ", end = "") print(end = " ") print() def near(v, r): return v / r + random.random() / r - 1 / (2 * r) def test(): global net for n in net: n.wrong = 0 all = 0 wrong = 0 for y in range(10, -1, -1): for x in range(0, 11): ins = [near(x, 10), near(y, 10)] ca = correct_answers(ins) for i in range(0, len(net)): net[i].compute(ins) out = 1 if net[i].out > 0.5 else 0 if out == ca[i]: print("Y", end = "") else: print("-", end = "") wrong += 1 net[i].wrong += 1 all += 1 print(end = " ") print() for n in net: if n.first_wrong == -1: n.first_wrong = n.wrong #else: # n.rate = initial_rate * n.wrong / n.first_wrong print(wrong, "wrong out of", all) def random_inputs(): return [random.random(), random.random()] def start(): global net net = [neuron(2) for i in range(0, 3)] def step(n): global net, ins totaltotalerror = 0 for j in range(0, n): ins = random_inputs() corrects = correct_answers(ins) totalerror = 0 errors = [] for i in range(0, len(net)): net[i].compute(ins) error = net[i].out - corrects[i] errors.append(error) totalerror += error * error net[i].correct_towards(corrects[i]) totaltotalerror += totalerror print("mean error", totaltotalerror / n) test() start() step(1)