I would like to take a list of unknown size, containing ndarrays, where each ndarray could have any dimension and size independent from the the others, and replace values at random spots in this entire data structure.
I can create an index for a random spot by doing this:
for w in weights:
number_of_weights = w.size()
The problem is how I would go about inserting without having to recursively check that I am at the last dimension while adding to a counter until it is greater than the index and decrementing another counter to know where in the last dimension I am inserting.
CodePudding user response:
I am already using Tensorflow, so I came up with a solution that uses it.
The idea was to reshape the multidimensional ndarray that would get the replacement into a flat array after finding what index in the list it was, and then reshaping it back to the original shape after the replacement, and replacing it's old copy in the list.
Please note that this is not as efficient as it could be due to multiple iterations of index keeping and replacements. If it becomes an issue, the indices could be pre-computed, and the ndarrays replaced a max of once instead of every iteration of the loop below.
def mutate(weights, n_mutations):
number_of_weights = 0
a = 0
b = 0
for i in weights:
number_of_weights = i.size
a = min(a, i.min())
b = max(b, i.min())
n_mutations = min(number_of_weights, n_mutations)
row = 0
count = weights[row].size - 1
for i in range(n_mutations):
index = random.randrange(0, number_of_weights)
index_const = index
while count < index_const:
index -= (weights[row].size 1)
row = 1
count = weights[row].size
new_weight = random.uniform(a, b - 1)
shape = weights[row].shape
flat_row = tf.reshape(weights[row], [-1]).numpy()
flat_row[index] = new_weight
new_row = tf.reshape(flat_row, shape).numpy()
weights[row] = new_row
row = 0
count = 0
return weights
CodePudding user response:
I found out about a solution that uses the ravel() function.
def get_row_and_index(weights, index):
index_const = index
row = 0
count = weights[row].size - 1
while count < index_const:
index -= weights[row].size
row = 1
count = weights[row].size
return row, index
def mutate_weights(weights, n_mutations):
new_weights = copy.deepcopy(weights)
number_of_weights = 0
a = 0
b = 0
for i in new_weights:
number_of_weights = i.size
a = min(a, i.min())
b = max(b, i.max())
n_mutations = min(number_of_weights, n_mutations)
for i in range(n_mutations):
index = random.randrange(0, number_of_weights)
row, index = get_row_and_index(new_weights, index)
new_weight = random.uniform(a, b)
flat_row = new_weights[row].ravel()
flat_row[index] = new_weight