Как эффективно мутировать определенное количество значений в массиве? - PullRequest
0 голосов
/ 21 декабря 2018

Учитывая начальный двумерный массив:

initial = [
 [0.6711999773979187, 0.1949000060558319],
 [-0.09300000220537186, 0.310699999332428],
 [-0.03889999911189079, 0.2736999988555908],
 [-0.6984000205993652, 0.6407999992370605],
 [-0.43619999289512634, 0.5810999870300293],
 [0.2825999855995178, 0.21310000121593475],
 [0.5551999807357788, -0.18289999663829803],
 [0.3447999954223633, 0.2071000039577484],
 [-0.1995999962091446, -0.5139999985694885],
 [-0.24400000274181366, 0.3154999911785126]]

Цель состоит в том, чтобы умножить некоторые случайные значения внутри массива на случайный процент.Допустим, только 3 случайных числа заменяются случайным множителем, мы должны получить что-то вроде этого:

output = [
 [0.6711999773979187, 0.52],
 [-0.09300000220537186, 0.310699999332428],
 [-0.03889999911189079, 0.2736999988555908],
 [-0.6984000205993652, 0.6407999992370605],
 [-0.43619999289512634, 0.5810999870300293],
 [0.84, 0.21310000121593475],
 [0.5551999807357788, -0.18289999663829803],
 [0.3447999954223633, 0.2071000039577484],
 [-0.1995999962091446, 0.21],
 [-0.24400000274181366, 0.3154999911785126]]

Я пытался сделать это:

def mutate(array2d, num_changes):
    for _ in range(num_changes):
        row, col = initial.shape
        rand_row = np.random.randint(row)
        rand_col = np.random.randint(col)
        cell_value = array2d[rand_row][rand_col] 
        array2d[rand_row][rand_col] =  random.uniform(0, 1) * cell_value
    return array2d

И это работает для 2Dмассивы, но есть вероятность, что одно и то же значение будет видоизменено более одного раза = (

И я не думаю, что это эффективно, и оно работает только на 2D массиве.

Есть ли способсделать такую ​​«мутацию» для массива любой формы и более эффективно?

Нет ограничений в отношении того, какое значение может выбрать «мутация», но число «мутаций» должно быть строгоуказанный пользователем номер.

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

Использование shuffle вместо random_choice, это будет другое решение.Работает с массивом любой формы.

def mutate(arrayIn, num_changes):
    mult = np.zeros(arrayIn.ravel().shape[0])
    mult[:num_changes] = np.random.uniform(0,1,num_changes)
    np.random.shuffle(mult)
    mult = mult.reshape(arrayIn.shape)
    arrayIn = arrayIn + mult*arrayIn
    return arrayIn
0 голосов
/ 21 декабря 2018

Одним из довольно простых способов было бы работать с разбитым видом массива.Таким образом вы можете сгенерировать все свои номера одновременно и упростить гарантию того, что вы не будете обрабатывать один и тот же индекс дважды за один вызов:

def mutate(array_anyd, num_changes):
    raveled = array_anyd.reshape(-1)
    indices = np.random.choice(raveled.size, size=num_changes, replace=False)
    values = np.random.uniform(0, 1, size=num_changes)
    raveled[indices] *= values

Я использую array_anyd.reshape(-1) в пользу array_anyd.ravel() потому что, согласно документам , первый с меньшей вероятностью сделает непреднамеренную копию.

Конечно, такая возможность еще есть.Вы можете добавить дополнительную проверку, чтобы написать обратно, если вам нужно.Более эффективным способом было бы использовать np.unravel_index, чтобы избежать создания представления для начала:

def mutate(array_anyd, num_changes):
    indices = np.random.choice(array_anyd.size, size=num_changes, replace=False)
    indices = np.unravel_indices(indices, array_anyd.shape)
    values = np.random.uniform(0, 1, size=num_changes)
    raveled[indices] *= values

Нет необходимости возвращать что-либо, потому что модификация выполняется на месте,Условно такие функции ничего не возвращают.См. Например list.sort против sorted.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...