This commit is contained in:
Si11ium
2019-03-04 15:24:01 +01:00
parent 415c7e9d41
commit f33db614b0

View File

@@ -1,15 +1,18 @@
import math import math
import copy import copy
import os
import numpy as np import numpy as np
import tensorflow as tf
from keras.models import Sequential, Model from keras.models import Sequential
from keras.layers import SimpleRNN, Dense from keras.layers import SimpleRNN, Dense
from keras.layers import Input, TimeDistributed
from tqdm import tqdm from tqdm import tqdm
from experiment import FixpointExperiment, IdentLearningExperiment from experiment import FixpointExperiment, IdentLearningExperiment
# Supress warnings and info messages
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
def normalize_id(value, norm): def normalize_id(value, norm):
if norm > 1: if norm > 1:
@@ -19,9 +22,9 @@ def normalize_id(value, norm):
def are_weights_diverged(network_weights): def are_weights_diverged(network_weights):
for layer_id,layer in enumerate(network_weights): for layer_id, layer in enumerate(network_weights):
for cell_id,cell in enumerate(layer): for cell_id, cell in enumerate(layer):
for weight_id,weight in enumerate(cell): for weight_id, weight in enumerate(cell):
if math.isnan(weight): if math.isnan(weight):
return True return True
if math.isinf(weight): if math.isinf(weight):
@@ -30,10 +33,10 @@ def are_weights_diverged(network_weights):
def are_weights_within(network_weights, lower_bound, upper_bound): def are_weights_within(network_weights, lower_bound, upper_bound):
for layer_id,layer in enumerate(network_weights): for layer_id, layer in enumerate(network_weights):
for cell_id,cell in enumerate(layer): for cell_id, cell in enumerate(layer):
for weight_id,weight in enumerate(cell): for weight_id, weight in enumerate(cell):
if not (lower_bound <= weight and weight <= upper_bound): if not (lower_bound <= weight <= upper_bound):
return False return False
return True return True
@@ -43,10 +46,10 @@ class NeuralNetwork:
@staticmethod @staticmethod
def weights_to_string(weights): def weights_to_string(weights):
s = "" s = ""
for layer_id,layer in enumerate(weights): for layer_id, layer in enumerate(weights):
for cell_id,cell in enumerate(layer): for cell_id, cell in enumerate(layer):
s += "[ " s += "[ "
for weight_id,weight in enumerate(cell): for weight_id, weight in enumerate(cell):
s += str(weight) + " " s += str(weight) + " "
s += "]" s += "]"
s += "\n" s += "\n"
@@ -58,7 +61,6 @@ class NeuralNetwork:
self.params.update(params) self.params.update(params)
self.keras_params = dict(activation='linear', use_bias=False) self.keras_params = dict(activation='linear', use_bias=False)
self.silent = True self.silent = True
self.model = None
def silence(self): def silence(self):
self.silent = True self.silent = True
@@ -125,9 +127,9 @@ class NeuralNetwork:
self.unsilence() self.unsilence()
if are_weights_diverged(new_weights): if are_weights_diverged(new_weights):
return False return False
for layer_id,layer in enumerate(old_weights): for layer_id, layer in enumerate(old_weights):
for cell_id, cell in enumerate(layer): for cell_id, cell in enumerate(layer):
for weight_id,weight in enumerate(cell): for weight_id, weight in enumerate(cell):
new_weight = new_weights[layer_id][cell_id][weight_id] new_weight = new_weights[layer_id][cell_id][weight_id]
if abs(new_weight - weight) >= epsilon: if abs(new_weight - weight) >= epsilon:
return False return False
@@ -151,15 +153,15 @@ class WeightwiseNeuralNetwork(NeuralNetwork):
self.model.add(Dense(units=self.width, **self.keras_params)) self.model.add(Dense(units=self.width, **self.keras_params))
self.model.add(Dense(units=1, **self.keras_params)) self.model.add(Dense(units=1, **self.keras_params))
def apply(self, *input): def apply(self, *inputs):
stuff = np.transpose(np.array([[input[0]], [input[1]], [input[2]], [input[3]]])) stuff = np.transpose(np.array([[inputs[0]], [inputs[1]], [inputs[2]], [inputs[3]]]))
return self.model.predict(stuff)[0][0] return self.model.predict(stuff)[0][0]
def apply_to_weights(self, old_weights): def apply_to_weights(self, old_weights):
new_weights = copy.deepcopy(old_weights) new_weights = copy.deepcopy(old_weights)
max_layer_id = len(old_weights) - 1 max_layer_id = len(old_weights) - 1
for layer_id,layer in enumerate(old_weights): for layer_id, layer in enumerate(old_weights):
max_cell_id = len(layer) - 1 max_cell_id = len(layer) - 1
for cell_id, cell in enumerate(layer): for cell_id, cell in enumerate(layer):
@@ -174,7 +176,10 @@ class WeightwiseNeuralNetwork(NeuralNetwork):
new_weights[layer_id][cell_id][weight_id] = new_weight new_weights[layer_id][cell_id][weight_id] = new_weight
if self.params.get("print_all_weight_updates", False) and not self.silent: if self.params.get("print_all_weight_updates", False) and not self.silent:
print("updated old weight " + str(weight) + "\t @ (" + str(layer_id) + "," + str(cell_id) + "," + str(weight_id) + ") to new value " + str(new_weight) + "\t calling @ (" + str(normal_layer_id) + "," + str(normal_cell_id) + "," + str(normal_weight_id) + ")") print("updated old weight {weight}\t @ ({layer},{cell},{weight_id}) "
"to new value {new_weight}\t calling @ ({n_layer},{n_cell},{n_weight_id})").format(
weight=weight, layer=layer_id, cell=cell_id, weight_id=weight_id, new_weight=new_weight,
n_layer=normal_layer_id, n_cell=normal_cell_id, n_weight_id=normal_weight_id)
return new_weights return new_weights
@@ -231,14 +236,14 @@ class AggregatingNeuralNetwork(NeuralNetwork):
def get_amount_of_weights(self): def get_amount_of_weights(self):
total_weights = 0 total_weights = 0
for layer_id,layer in enumerate(self.get_weights()): for layer_id, layer in enumerate(self.get_weights()):
for cell_id,cell in enumerate(layer): for cell_id, cell in enumerate(layer):
for weight_id,weight in enumerate(cell): for weight_id, weight in enumerate(cell):
total_weights += 1 total_weights += 1
return total_weights return total_weights
def apply(self, *input): def apply(self, *inputs):
stuff = np.transpose(np.array([[input[i]] for i in range(self.aggregates)])) stuff = np.transpose(np.array([[inputs[i]] for i in range(self.aggregates)]))
return self.model.predict(stuff)[0] return self.model.predict(stuff)[0]
def apply_to_weights(self, old_weights): def apply_to_weights(self, old_weights):
@@ -247,9 +252,9 @@ class AggregatingNeuralNetwork(NeuralNetwork):
collections = [] collections = []
next_collection = [] next_collection = []
current_weight_id = 0 current_weight_id = 0
for layer_id,layer in enumerate(old_weights): for layer_id, layer in enumerate(old_weights):
for cell_id,cell in enumerate(layer): for cell_id, cell in enumerate(layer):
for weight_id,weight in enumerate(cell): for weight_id, weight in enumerate(cell):
next_collection += [weight] next_collection += [weight]
if (current_weight_id + 1) % collection_size == 0: if (current_weight_id + 1) % collection_size == 0:
collections += [next_collection] collections += [next_collection]
@@ -262,7 +267,7 @@ class AggregatingNeuralNetwork(NeuralNetwork):
new_aggregations = self.apply(*old_aggregations) new_aggregations = self.apply(*old_aggregations)
# generate list of new weights # generate list of new weights
new_weights_list = [] new_weights_list = []
for aggregation_id,aggregation in enumerate(new_aggregations): for aggregation_id, aggregation in enumerate(new_aggregations):
if aggregation_id == self.aggregates - 1: if aggregation_id == self.aggregates - 1:
new_weights_list += self.get_deaggregator()(aggregation, collection_size + leftovers) new_weights_list += self.get_deaggregator()(aggregation, collection_size + leftovers)
else: else:
@@ -271,9 +276,9 @@ class AggregatingNeuralNetwork(NeuralNetwork):
# write back new weights # write back new weights
new_weights = copy.deepcopy(old_weights) new_weights = copy.deepcopy(old_weights)
current_weight_id = 0 current_weight_id = 0
for layer_id,layer in enumerate(new_weights): for layer_id, layer in enumerate(new_weights):
for cell_id,cell in enumerate(layer): for cell_id, cell in enumerate(layer):
for weight_id,weight in enumerate(cell): for weight_id, weight in enumerate(cell):
new_weight = new_weights_list[current_weight_id] new_weight = new_weights_list[current_weight_id]
new_weights[layer_id][cell_id][weight_id] = new_weight new_weights[layer_id][cell_id][weight_id] = new_weight
current_weight_id += 1 current_weight_id += 1
@@ -298,25 +303,25 @@ class RecurrentNeuralNetwork(NeuralNetwork):
self.model.add(SimpleRNN(units=width, return_sequences=True, **self.keras_params)) self.model.add(SimpleRNN(units=width, return_sequences=True, **self.keras_params))
self.model.add(SimpleRNN(units=self.features, return_sequences=True, **self.keras_params)) self.model.add(SimpleRNN(units=self.features, return_sequences=True, **self.keras_params))
def apply(self, *input): def apply(self, *inputs):
stuff = np.transpose(np.array([[[input[i]] for i in range(len(input))]])) stuff = np.transpose(np.array([[[inputs[i]] for i in range(len(inputs))]]))
return self.model.predict(stuff)[0].flatten() return self.model.predict(stuff)[0].flatten()
def apply_to_weights(self, old_weights): def apply_to_weights(self, old_weights):
# build list from old weights # build list from old weights
new_weights = copy.deepcopy(old_weights) new_weights = copy.deepcopy(old_weights)
old_weights_list = [] old_weights_list = []
for layer_id,layer in enumerate(old_weights): for layer_id, layer in enumerate(old_weights):
for cell_id,cell in enumerate(layer): for cell_id, cell in enumerate(layer):
for weight_id,weight in enumerate(cell): for weight_id, weight in enumerate(cell):
old_weights_list += [weight] old_weights_list += [weight]
# call network # call network
new_weights_list = self.apply(*old_weights_list) new_weights_list = self.apply(*old_weights_list)
# write back new weights from list of rnn returns # write back new weights from list of rnn returns
current_weight_id = 0 current_weight_id = 0
for layer_id,layer in enumerate(new_weights): for layer_id, layer in enumerate(new_weights):
for cell_id,cell in enumerate(layer): for cell_id, cell in enumerate(layer):
for weight_id,weight in enumerate(cell): for weight_id, weight in enumerate(cell):
new_weight = new_weights_list[current_weight_id] new_weight = new_weights_list[current_weight_id]
new_weights[layer_id][cell_id][weight_id] = new_weight new_weights[layer_id][cell_id][weight_id] = new_weight
current_weight_id += 1 current_weight_id += 1
@@ -329,7 +334,7 @@ class LearningNeuralNetwork(NeuralNetwork):
def mean_reduction(weights, features): def mean_reduction(weights, features):
single_dim_weights = np.hstack([w.flatten() for w in weights]) single_dim_weights = np.hstack([w.flatten() for w in weights])
shaped_weights = np.reshape(single_dim_weights, (1, features, -1)) shaped_weights = np.reshape(single_dim_weights, (1, features, -1))
x = np.mean(shaped_weights, axis=1) x = np.mean(shaped_weights, axis=-1)
return x return x
@staticmethod @staticmethod
@@ -339,16 +344,15 @@ class LearningNeuralNetwork(NeuralNetwork):
return x return x
@staticmethod @staticmethod
def random_reduction(weights, features): def random_reduction(_, features):
x = np.random.rand(features)[None, ...] x = np.random.rand(features)[None, ...]
return x return x
def __init__(self, width, depth, features, reduction, **kwargs): def __init__(self, width, depth, features, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
self.width = width self.width = width
self.depth = depth self.depth = depth
self.features = features self.features = features
self.reduction = reduction
self.compile_params = dict(loss='mse', optimizer='sgd') self.compile_params = dict(loss='mse', optimizer='sgd')
self.model.add(Dense(units=self.width, input_dim=self.features, **self.keras_params)) self.model.add(Dense(units=self.width, input_dim=self.features, **self.keras_params))
for _ in range(self.depth-1): for _ in range(self.depth-1):
@@ -360,13 +364,13 @@ class LearningNeuralNetwork(NeuralNetwork):
self.compile_params.update(kwargs) self.compile_params.update(kwargs)
return self return self
def learn(self, epochs, batchsize=1): def learn(self, epochs, reduction, batchsize=1):
with tqdm(total=epochs, ascii=True, with tqdm(total=epochs, ascii=True,
desc='Type: {t} @ Epoch:'.format(t=self.__class__.__name__), desc='Type: {t} @ Epoch:'.format(t=self.__class__.__name__),
postfix=["Loss", dict(value=0)]) as bar: postfix=["Loss", dict(value=0)]) as bar:
for epoch in range(epochs): for epoch in range(epochs):
old_weights = self.get_weights() old_weights = self.get_weights()
x = self.reduction(old_weights) x = reduction(old_weights, self.features)
history = self.model.fit(x=x, y=x, verbose=0, batch_size=batchsize) history = self.model.fit(x=x, y=x, verbose=0, batch_size=batchsize)
bar.postfix[1]["value"] = history.history['loss'][-1] bar.postfix[1]["value"] = history.history['loss'][-1]
bar.update() bar.update()
@@ -377,8 +381,11 @@ if __name__ == '__main__':
with FixpointExperiment() as exp: with FixpointExperiment() as exp:
for run_id in tqdm(range(100)): for run_id in tqdm(range(100)):
# net = WeightwiseNeuralNetwork(width=2, depth=2).with_keras_params(activation='linear') # net = WeightwiseNeuralNetwork(width=2, depth=2).with_keras_params(activation='linear')
net = AggregatingNeuralNetwork(aggregates=4, width=2, depth=2).with_keras_params(activation='linear').with_params(shuffler=AggregatingNeuralNetwork.shuffle_random, print_all_weight_updates=False, use_bias=True) net = AggregatingNeuralNetwork(aggregates=4, width=2, depth=2).with_keras_params(activation='linear')\
# net = RecurrentNeuralNetwork(width=2, depth=2).with_keras_params(activation='linear').with_params(print_all_weight_updates=True) .with_params(shuffler=AggregatingNeuralNetwork.shuffle_random,
print_all_weight_updates=False, use_bias=True)
# net = RecurrentNeuralNetwork(width=2, depth=2).with_keras_params(activation='linear')\
# .with_params(print_all_weight_updates=True)
# net.print_weights() # net.print_weights()
exp.run_net(net, 100) exp.run_net(net, 100)
@@ -386,8 +393,7 @@ if __name__ == '__main__':
if True: if True:
with IdentLearningExperiment() as exp: with IdentLearningExperiment() as exp:
net = LearningNeuralNetwork(width=2, depth=2, features=2, reduction=LearningNeuralNetwork.random_reduction)\ net = LearningNeuralNetwork(width=2, depth=2, features=2, )\
.with_keras_params(activation='linear') \ .with_keras_params(activation='linear') \
.with_params(print_all_weight_updates=False) .with_params(print_all_weight_updates=False)
net.learn(1000) net.learn(1000, reduction=LearningNeuralNetwork.mean_reduction)