Neural Network in python only learning for 1 in-/output pair per dataset? -
i wrote code generating , training artifiacial neural networks in python (with backpropagation). works well, 1 problem bugs me days , can't seem find why:
the network generate decreases error on datasets if sets contain 1 in-/output pair. e.g. input [[1,1]] 2 input neurons , simplicity [[1,1]] output. works well, error decreases. if choose [[1,1],[0,0]] input, error alternates or somestimes goes against 2, no matter how long let work. here code:
import numpy np graphics import * import math class neuron(): def __init__(self,input=0,output=0,activation_func_key="logistic",bias=false,inp=false): self.b = bias self.input = input + self.b self.output = output self.key = activation_func_key self.inp = inp def add_to_input(self,input_=0): self.input += input_ def add_to_input(self,input_=0): self.input += float(input_) def get_output(self): if self.b: return 1 if self.inp: return self.input if self.key "relu": return np.maximum((self.input),0) if self.key "tanh": return np.tanh(self.input) if self.key "softplus": return np.log(1+np.e**(self.input)) if self.key "logistic": return 1/(1+np.e**-(self.input)) def reset(self): self.input = 0 self.ouput = 0 class network(): def __init__(self,weight_matrix,input_neuron_num,hidden_neuron_nums,ouput_neuron_num,activation_f="relu"): self.weight_matrix = weight_matrix self.neurons = [neuron(activation_func_key=activation_f) _ in range(weight_matrix[0].__len__())] back_layers = 0 val = input_neuron_num counter = 0 in range(weight_matrix[0].__len__()): bias = false inp = false if val: bias = true if counter < hidden_neuron_nums.__len__(): val += hidden_neuron_nums[counter]+1 counter += 1 if < input_neuron_num: inp = true self.neurons[i] = neuron(activation_func_key=activation_f,inp=inp,bias=bias) self.input_neuron_num = input_neuron_num self.hidden_neuron_nums = hidden_neuron_nums self.output_neuron_num = ouput_neuron_num def propagate_forward(self,inputv,output_len): in range(self.neurons.__len__()): if < self.input_neuron_num: self.neurons[i].add_to_input(inputv[i]) else: spalte = self.weight_matrix[:][i] j in range(spalte.__len__()): #if > j: #nur obere dreiecksmatrix self.neurons[i].add_to_input(self.weight_matrix[j][i] * self.neurons[j].get_output()) output = [] in range(output_len): output.append(self.neurons[self.weight_matrix[0].__len__()-i-1].get_output()) output.reverse() return output def reset(self): n in self.neurons: n.reset() def make_net(inp,hidden,out,activation_f="logistic"): hsum = 0 in range(hidden.__len__()): hsum += hidden[i]+1 sum = inp + 1 + hsum + out weights = [[0 _ in range(sum)] _ in range(sum)] neurons_till_this_layer = 0 in range(inp+1): j in range(hidden[0]): weights[i][inp+j+1] = np.random.uniform(-1,1) neurons_till_this_layer += inp+1 in range(hidden.__len__()-1): n in range(hidden[i]+1): m in range(hidden[i+1]): weights[n+neurons_till_this_layer][m+neurons_till_this_layer+hidden[i]+1] = np.random.uniform(-1,1) neurons_till_this_layer += hidden[i]+1 in range(hidden[hidden.__len__()-1]+1): j in range(out): weights[i+neurons_till_this_layer][j+neurons_till_this_layer+hidden[hidden.__len__()-1]+1] = np.random.uniform(-1,1) net = network(weights,inp,hidden,out,activation_f=activation_f) return net def backpropagation(net,inputs,outputs,learning_rate=0.001,epsilon=0.1,draw=false,win=0): if draw: win = 0 if win not 0: win = win else: win = draw_window(net) if inputs[0][:].__len__() not net.input_neuron_num: print("error: input length not match! no learning done!") return net if outputs[0][:].__len__() not net.output_neuron_num: print("error: output length not match! no learning done!") return net hsum = 0 in range(net.hidden_neuron_nums.__len__()): hsum += net.hidden_neuron_nums[i]+1 outer_delta_w_matrix = [[0 _ in range(net.input_neuron_num + 1 + hsum + net.output_neuron_num)] _ in range(net.input_neuron_num + 1 + hsum + net.output_neuron_num)] n in range(inputs.__len__()): net_output = net.propagate_forward(inputs[n],outputs[0].__len__()) delta_w_matrix = [[0 _ in range(net.input_neuron_num + 1 + hsum + net.output_neuron_num)] _ in range(net.input_neuron_num + 1 + hsum + net.output_neuron_num)] delta_j_list = [float(0) _ in range(net.input_neuron_num + 1 + hsum + net.output_neuron_num)] in range(net.input_neuron_num + 1 + hsum + net.output_neuron_num): j = net.input_neuron_num + 1 + hsum + net.output_neuron_num - - 1 derivate = "error" if net.neurons[j].key "relu": derivate = 0 if net.neurons[j].input <= 0 else 1 if net.neurons[j].key "tanh": derivate = (1 / (np.cosh(net.neurons[j].input) * np.cosh(net.neurons[j].input))) if net.neurons[j].key "softplus": derivate = 1 / (1 + np.e ** -net.neurons[j].input) if net.neurons[j].key "logistic": #print(" input: %f" % net.neurons[j].input) derivate = (np.exp(net.neurons[j].input)) / (((np.exp(net.neurons[j].input)) + 1) ** 2) #derivate = net.neurons[j].output * (1 - net.neurons[i].get_output()) if < net.output_neuron_num: delta_j_list[j] = derivate * (net.neurons[j].get_output() - float(outputs[n][net.output_neuron_num-i-1])) else: prev_delta_sum = 0 x in range(net.weight_matrix[j][:].__len__()): prev_delta_sum += (delta_j_list[j-x] * net.weight_matrix[j][x]) #print(net.neurons[j].input) delta_j_list[j] = derivate * prev_delta_sum in range(net.input_neuron_num + 1 + hsum + net.output_neuron_num): j in range(net.input_neuron_num + 1 + hsum + net.output_neuron_num): if net.weight_matrix[i][j]: delta_w_matrix[i][j] = -learning_rate * delta_j_list[j] * net.neurons[i].get_output() in range(net.input_neuron_num + 1 + hsum + net.output_neuron_num): j in range(net.input_neuron_num + 1 + hsum + net.output_neuron_num): outer_delta_w_matrix[i][j] += (delta_w_matrix[i][j] / (inputs.__len__())) #print_matrix(net.weight_matrix) #print() #print("completed cycle") net.reset() in range(net.input_neuron_num + hsum + net.output_neuron_num): j in range(net.input_neuron_num + hsum + net.output_neuron_num): if net.weight_matrix[i][j]: net.weight_matrix[i][j] = net.weight_matrix[i][j] + outer_delta_w_matrix[i][j] if draw: draw_net(net, win) return net def print_matrix(matrix): = matrix[0][:] b = matrix[:][0] in range(a.__len__()): print() j in range(b.__len__()): sys.stdout.write("% 1.7f " % matrix[i][j]) print() def get_dataset_binary(dataset_length=1000,max=4): rdm_nums = [np.random.randint(0,2**max) _ in range(dataset_length)] bin_nums = [0 _ in range(rdm_nums.__len__())] length = max in range(rdm_nums.__len__()): bin_nums[i] = "{0:b}".format(rdm_nums[i]) while bin_nums[i].__len__() < length: bin_nums[i] = "0" + bin_nums[i] r_value = [0 _ in range(dataset_length)] in range(dataset_length): r_value[i] = list(bin_nums[i]) return r_value def draw_window(net,autoflush=false): width = 0 in range(net.hidden_neuron_nums.__len__()): if net.hidden_neuron_nums[i] > width: width = net.hidden_neuron_nums[i] if net.input_neuron_num > width: width = net.input_neuron_num if net.output_neuron_num > width: width = net.output_neuron_num scale_factor = 0.7 counter = 0 r = 50*scale_factor v_buf = 100*scale_factor h_buf = 50*scale_factor d1 = 20*scale_factor d2 = 12*scale_factor return graphwin("netzwerk", (2*h_buf)+(width*2*r)+(width*h_buf)-h_buf, 2 * v_buf + 2*r+v_buf + net.hidden_neuron_nums.__len__()*2*r + net.hidden_neuron_nums.__len__()*v_buf-v_buf + 2*r+v_buf, autoflush=autoflush) def draw_net(net,win=0): width = 0 in range(net.hidden_neuron_nums.__len__()): if net.hidden_neuron_nums[i] > width: width = net.hidden_neuron_nums[i]+1 if net.input_neuron_num > width: width = net.input_neuron_num+1 if net.output_neuron_num > width: width = net.output_neuron_num scale_factor = 0.7 counter = 0 r = 50*scale_factor v_buf = 100*scale_factor h_buf = 50*scale_factor d1 = 20*scale_factor d2 = 12*scale_factor if win 0: win = graphwin("netzwerk", (2*h_buf)+(width*2*r)+(width*h_buf)-h_buf, 2 * v_buf + 2*r+v_buf + net.hidden_neuron_nums.__len__()*2*r + net.hidden_neuron_nums.__len__()*v_buf-v_buf + 2*r+v_buf) in range(net.weight_matrix.__len__()): j in range(net.weight_matrix.__len__()): if net.weight_matrix[i][j] not 0: from_pos = get_neuron_pos(net,i,r,v_buf,h_buf,width) to_pos = get_neuron_pos(net,j,r,v_buf,h_buf,width) thickness = np.abs(net.weight_matrix[i][j]) * 10 weight = polygon([point(from_pos.x-thickness,from_pos.y), point(from_pos.x+thickness,from_pos.y),point(to_pos.x+thickness,to_pos.y), point(to_pos.x-thickness,to_pos.y)]) if net.weight_matrix[i][j] > 0: weight.setfill("firebrick4") else: weight.setfill("lightskyblue") label = text(point((from_pos.x+to_pos.x)/2, (from_pos.y+to_pos.y)/2), "%0.5f" % net.weight_matrix[i][j]) label.setsize(np.maximum(int(10*scale_factor),5)) weight.draw(win) label.draw(win) hidden_neuron_num = 0 in range(net.hidden_neuron_nums.__len__()): hidden_neuron_num += net.hidden_neuron_nums[i]+1 in range(net.input_neuron_num+1): inp_neuron = circle(point( (win.width - ((net.input_neuron_num+1) * 2 * r + (net.input_neuron_num+1) * h_buf - h_buf))/2 + i*(2*r+h_buf) + r, v_buf+r),r) inp_neuron.setfill("springgreen3") if net.input_neuron_num: inp_neuron.setfill("snow") name = text(point((win.width - ((net.input_neuron_num+1) * 2 * r + (net.input_neuron_num+1) * h_buf - h_buf))/2 + i*(2*r+h_buf) + r, v_buf+r-d1), "%s" % ("neuron(in) " + str(counter+1))) if net.input_neuron_num: name.settext("%s" % ("neuron(bias) " + str(counter+1))) label = text(point((win.width - ((net.input_neuron_num+1) * 2 * r + (net.input_neuron_num+1) * h_buf - h_buf))/2 + i*(2*r+h_buf) + r, v_buf+r+d2), "output:\n%1.6f" % float(net.neurons[counter].get_output())) name.setsize(np.maximum(int(10*scale_factor),5)) label.setsize(np.maximum(int(10*scale_factor),5)) inp_neuron.draw(win) name.draw(win) label.draw(win) counter +=1 in range(net.hidden_neuron_nums.__len__()): j in range(net.hidden_neuron_nums[i]+1): hidden_neuron = circle(point((win.width-((net.hidden_neuron_nums[i]+1)*2*r+(net.hidden_neuron_nums[i]+1)*h_buf-h_buf))/2+j*(2*r+h_buf)+r,(3*r+2*v_buf)+i*(2*r+v_buf)),r) hidden_neuron.setfill("lavender") if j net.hidden_neuron_nums[i]: hidden_neuron.setfill("snow") name = text(point((win.width-((net.hidden_neuron_nums[i]+1)*2*r+(net.hidden_neuron_nums[i]+1)*h_buf-h_buf))/2+j*(2*r+h_buf)+r, (3*r+2*v_buf)+i*(2*r+v_buf)-d1), "%s" % ("neuron " + str(counter+1))) if j net.hidden_neuron_nums[i]: name.settext("%s" % ("neuron(bias) " + str(counter+1))) label = text(point((win.width-((net.hidden_neuron_nums[i]+1)*2*r+(net.hidden_neuron_nums[i]+1)*h_buf-h_buf))/2+j*(2*r+h_buf)+r, (3*r+2*v_buf)+i*(2*r+v_buf)+d2), "output:\n%1.6f" % net.neurons[counter].get_output()) name.setsize(np.maximum(int(10*scale_factor),5)) label.setsize(np.maximum(int(10*scale_factor),5)) hidden_neuron.draw(win) name.draw(win) label.draw(win) counter += 1 in range(net.output_neuron_num): out_neuron = circle(point((win.width-(net.output_neuron_num*2*r+net.output_neuron_num*h_buf-h_buf))/2+i*(2*r+h_buf)+r, net.hidden_neuron_nums.__len__()*2*r + 2*r + net.hidden_neuron_nums.__len__()*v_buf + 2* v_buf + r),r) out_neuron.setfill("darkgoldenrod3") name = text(point((win.width-(net.output_neuron_num*2*r+net.output_neuron_num*h_buf-h_buf))/2+i*(2*r+h_buf)+r, net.hidden_neuron_nums.__len__()*2*r + 2*r + net.hidden_neuron_nums.__len__()*v_buf + 2* v_buf + r - d1), "%s" % ("neuron(out) " + str(counter+1))) label = text(point((win.width-(net.output_neuron_num*2*r+net.output_neuron_num*h_buf-h_buf))/2+i*(2*r+h_buf)+r, net.hidden_neuron_nums.__len__()*2*r + 2*r + net.hidden_neuron_nums.__len__()*v_buf + 2* v_buf + r + d2), "output:\n%1.6f" % net.neurons[counter].get_output()) name.setsize(np.maximum(int(10*scale_factor),5)) label.setsize(np.maximum(int(10*scale_factor),5)) out_neuron.draw(win) name.draw(win) label.draw(win) counter += 1 win.update() win.wait_window() def get_neuron_pos(net, n, r, v_buf, h_buf, width): if n < net.input_neuron_num+1: return point(((2*h_buf)+(width*2*r)+(width*h_buf)-h_buf - ((net.input_neuron_num+1) * 2 * r + (net.input_neuron_num+1) * h_buf - h_buf)) / 2 + n * (2 * r + h_buf) + r, v_buf + r) current = net.input_neuron_num+1 h in range(net.hidden_neuron_nums.__len__()): current += (net.hidden_neuron_nums[h]+1) if n < current: return point(((2*h_buf)+(width*2*r)+(width*h_buf)-h_buf-((net.hidden_neuron_nums[h]+1)*2*r+(net.hidden_neuron_nums[h]+1)*h_buf-h_buf))/2+(n-(current-net.hidden_neuron_nums[h]-1))*(2*r+h_buf)+r,(3*r+2*v_buf)+h*(2*r+v_buf)) if n - current < net.output_neuron_num: return point(((2*h_buf)+(width*2*r)+(width*h_buf)-h_buf-((net.output_neuron_num)*2*r+(net.output_neuron_num)*h_buf-h_buf))/2+(n-current)*(2*r+h_buf)+r, net.hidden_neuron_nums.__len__()*2*r + 2*r + net.hidden_neuron_nums.__len__()*v_buf + 2* v_buf + r) return -1 def backpropagation_(net,inputs,outputs,learning_rate=0.01,epsilon=0.1): endlich_fertig = false while not endlich_fertig: net = backpropagation(net,inputs,outputs,learning_rate,epsilon) endlich_fertig = true error = 0 in range(inputs.__len__()): output = net.propagate_forward(inputs[i], outputs[0][:].__len__()) j in range(output.__len__()): error += np.abs(output[j] - float(outputs[i][j])) if error > epsilon: endlich_fertig = false print("error: %f" % error) return net net = make_net(2,[3,2],2) print_matrix(net.weight_matrix) inputs = [[1,1],[0,0]] outputs = inputs draw_net(net) trained_net = backpropagation_(net,inputs,outputs) draw_net(trained_net) edit: put in full code can reproduce behaviour locally
Comments
Post a Comment