Я пытаюсь создать функцию, которая применяет случайные значения к диапазону параметров, которые используются в другой функции, где случайная последовательность не повторяется.
Причина: используется для случайной настройки гиперпараметров и сокращения обработки за счет отсутствия повторения последовательности.
Пример кода:
num_evals = 2500
parameters = {
'n_parameter_1': range(2,100),
'n_parameter_2': range(1,20),
'n_parameter_3': range(2,150),
}
for i in range(num_evals):
n_parameter_1 = random.choice(parameters['n_parameter_1'])
n_parameter_2 = random.choice(parameters['n_parameter_2'])
n_parameter_3 = random.choice(parameters['n_parameter_3'])
Затем результаты заносятся в файл со случайными параметрами, используемыми для генерации.
Мне нужна помощь со вторым битом.
Поскольку эта функция работает с течением времени, вы начинаете получать последовательности, которые выглядят следующим образом:
n_parameter_1 = 54, n_parameter_2 = 15, n_parameter_3 = 120
n_parameter_1 = 10, n_parameter_2 = 12, n_parameter_3 = 89
n_parameter_1 = 54, n_parameter_2 = 15, n_parameter_3 = 120
Я хочу избежать последней последовательности, либо захватив последовательности в списке, либо в фрейме данных и т. д. (уже сохраняя последовательности), которые проверяет функция, а затем генерирует новую/другую последовательность, если в списке есть повторяющаяся последовательность.
Спасибо за помощь в продвижении.
В чем ваша настоящая проблема? У вас есть первая часть: «создайте функцию, которая применяет случайные значения к диапазону параметров», и мне непонятно, что вы подразумеваете под «где случайная последовательность не повторяется».
Извините, поправил, чтобы было понятнее
Вы пробовали random.shuffle вместо random.choice ?
random.shuffle и random.sample предоставляют набор неповторяющихся чисел из исходного образца. См. документацию для деталей и некоторых примеров. Таким образом, сначала создайте список для каждого случайного параметра, а затем выполните итерацию по этим спискам. Не пытайтесь выбирать случайный параметр каждый раз внутри цикла; подготовьте это перед циклом.
Считали ли вы, что случайная выборка может быть не лучшим подходом? При соответствующем планировании экспериментов вы, возможно, могли бы подобрать модель поверхности отклика, которая могла бы рассказать вам о влиянии каждого параметра, как по отдельности, так и совместно через условия взаимодействия, чтобы облегчить ваши усилия по «настройке». Хороший дизайн, скорее всего, даст вам больше информации с меньшим количеством выборок. См. en.wikipedia.org/wiki/Data_farming и en.wikipedia.org/wiki/Response_surface_methodology.






Вы можете сохранить последовательности в наборе, а затем проверить, есть ли уже последовательность в наборе.
num_evals = 2500
i = 0
parameters = {
'n_parameter_1': range(2,100),
'n_parameter_2': range(1,20),
'n_parameter_3': range(2,150),
}
sequences = set()
while i < num_evals:
n_parameter_1 = random.choice(parameters['n_parameter_1'])
n_parameter_2 = random.choice(parameters['n_parameter_2'])
n_parameter_3 = random.choice(parameters['n_parameter_3'])
sequence = (n_parameter_1, n_parameter_2, n_parameter_3)
if sequence not in sequences:
sequences.add(sequence)
i += 1
Цикл for был заменен циклом while, чтобы обеспечить условное приращение.
Спасибо, это было достаточно легко понять, я мог адаптировать это, чтобы вписаться в мои процессы, и обновить его.
Вы можете использовать random.sample, чтобы получить неповторяющийся набор значений из списка всех возможностей. Но для вашего сценария генерация списка возможностей может быть непомерно высокой (только в вашем примере будет 275576 записей в этом списке).
random.sample может эффективно работать с диапазонами, поэтому, если вы напишите функцию для преобразования номера индекса в соответствующую комбинацию параметров, вы можете построить список индексов комбинаций, используя random.sample(range(275576),num_evals), а затем преобразовать эти индексы в фактические значения параметров:
def paramRange(params): # index range of all combinations
count = 1
for r in params.values():
count *= len(r)
return range(count)
def getParams(params,index): # parameter value combination at index
result = []
for r in reversed([*params.values()]):
index,pIndex = divmod(index,len(r))
result.append(r[pIndex])
return dict(zip(params,reversed(result)))
выход:
num_evals = 10 #2500
parameters = {
'n_parameter_1': range(2,100),
'n_parameter_2': range(1,20),
'n_parameter_3': range(2,150),
}
import random
comboIndexes = random.sample(paramRange(parameters),num_evals)
for index in comboIndexes:
print(getParams(parameters,index))
{'n_parameter_1': 31, 'n_parameter_2': 12, 'n_parameter_3': 14}
{'n_parameter_1': 18, 'n_parameter_2': 12, 'n_parameter_3': 15}
{'n_parameter_1': 11, 'n_parameter_2': 15, 'n_parameter_3': 74}
{'n_parameter_1': 21, 'n_parameter_2': 19, 'n_parameter_3': 78}
{'n_parameter_1': 25, 'n_parameter_2': 12, 'n_parameter_3': 94}
{'n_parameter_1': 52, 'n_parameter_2': 6, 'n_parameter_3': 40}
{'n_parameter_1': 57, 'n_parameter_2': 8, 'n_parameter_3': 53}
{'n_parameter_1': 85, 'n_parameter_2': 12, 'n_parameter_3': 133}
{'n_parameter_1': 66, 'n_parameter_2': 1, 'n_parameter_3': 60}
{'n_parameter_1': 19, 'n_parameter_2': 13, 'n_parameter_3': 80}
С помощью этого метода вы не ограничены диапазонами для словаря parameters, у вас могут быть списки конкретных значений с разными типами данных.
Спасибо, это отличный ответ, это действительно помогло/вдохновило меня на другую проблему.
Какой вопрос? Как избежать повторения?