Что я делаю не так, пытаясь использовать TensorFlow для решения задач автогонок в гимназии? ⇐ Python
-
Гость
Что я делаю не так, пытаясь использовать TensorFlow для решения задач автогонок в гимназии?
Он определяет, как двигаться дальше, но не более того.
Я пробовал переключить CNN на сигмовидную активацию, уменьшив количество сверточных слоев, увеличив количество сверточных слоев и добавив плотные слои. Ничего не сработало. Вот мой код: импорт и запуск:
импортировать спортзал как спортзал импортировать numpy как np импортировать тензорный поток как tf импортировать коллекции статистика импорта импортировать tqdm импортировать matplotlib.pyplot как plt импортировать ОС импортировать cv2 импортировать atexit импортировать Shutil от ввода списка импорта, кортежа из изображения импорта PIL gpu = tf.config.experimental.list_physical_devices('GPU')[0] tf.config.experimental.set_memory_growth(GPU, True) env = Gym.make("CarRacing-v2", Continuous = False, render_mode="rgb_array") семя = 69 tf.random.set_seed(семя) np.random.seed(семя) # Небольшое значение эпсилон для стабилизации операций деления eps = np.finfo(np.float32).eps.item() num_hidden_units = 256 dir_name = "Автомобильные гонки" SAVE_PATH = f"C:/Users/potot/Desktop/code/Research/Gymnasium/Saved Models/{dir_name}/{num_hidden_units}/" Определение модели:
class ActorCritic(tf.keras.Model): """Объединенная актерско-критическая сеть.""" защита __init__( себя, число_действий: целое число, num_hidden_units: интервал, image_shape: Tuple[int,int]): """Инициализировать.""" супер().__init__() self.common = tf.keras.Sequential([ tf.keras.layers.Conv2D(32, (3, 3), активация = 'relu', input_shape = image_shape), tf.keras.layers.MaxPooling2D((2, 2)), tf.keras.layers.Conv2D(64, (3, 3), активация = 'relu'), tf.keras.layers.MaxPooling2D((2, 2)), tf.keras.layers.Conv2D(64, (3, 3), активация = 'relu'), tf.keras.layers.Flatten(), tf.keras.layers.Dropout(0,5), ]) self.actor = tf.keras.layers.Dense(num_actions,activation='softmax') self.critic = tf.keras.layers.Dense(1) # Добавьте сглаживающий слой к выходным данным критика, чтобы удалить пространственные измерения. self.flatten = tf.keras.layers.Flatten() def call(self, inputs: tf.Tensor) -> Tuple[tf.Tensor, tf.Tensor]: x = self.common(входные данные) актер_выход = self.actor(x) Critic_output = self.critic(x) вернуть актер_выход, критик_выход функция сохранения:
def save(модель: tf.keras.Model): dir_list = os.listdir(SAVE_PATH) num_saves = 8 если len(dir_list) >= num_saves: для папки в dir_list: путь к файлу = os.path.join(SAVE_PATH,папка) если ул(папка) == "1": Shutil.rmtree(os.path.join(SAVE_PATH, папка)) продолжать os.rename(filepath,f"{SAVE_PATH}{int(folder)-1}") новый_путь = os.path.join(SAVE_PATH,f"{num_saves}") os.madeirs(новый_путь) model.save_weights(new_path) еще: new_path = f"{SAVE_PATH}{len(dir_list)+1}" os.madeirs(новый_путь) model.save_weights(new_path+"/1") возвращаться Инициализирует модель:
num_actions = env.action_space.n image_shape = (21,24,1) если нет os.path.exists(SAVE_PATH): os.madeirs(SAVE_PATH) если len(os.listdir(SAVE_PATH)) > 0: модель = ActorCritic (num_actions, num_hidden_units, image_shape) модель (np.expand_dims (np.zeros (image_shape), ось = 0)) model.load_weights(f"{SAVE_PATH}{os.listdir(SAVE_PATH)[-1]}/1") print(f"Загрузка модели {os.listdir(SAVE_PATH)[-1]}...") еще: модель = ActorCritic (num_actions, num_hidden_units, image_shape) оптимизатор = tf.keras.optimizers.Adam (learning_rate=0,01) Группирует операции компьютерного зрения, выполняемые в состоянии наблюдения:
def cv_operations(state): # Image.fromarray(state).save("Гимназия/bruh.png") состояние = cv2.cvtColor(состояние, cv2.COLOR_RGB2GRAY) Т, состояние = cv2.threshold(state, 100, 255, cv2.THRESH_BINARY_INV) состояние = состояние[0:85,0:] состояние = cv2.resize(состояние, (24,21)) # Image.fromarray(state).save("Gymnasium/bruh2.png") состояние = состояние.reshape((21,24,1)) вернуть состояние Один шаг среды:
def env_step(action: np.ndarray) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: """Возвращает состояние, награду и флаг завершения действия.""" состояние, награда, выполнено, усечено, информация = env.step(действие) состояние = cv_operations (состояние) возврат (state.astype(np.float32), np.array(награда, np.int32), np.array(готово, np.int32)) защита tf_env_step (действие: tf.Tensor) -> Список[tf.Tensor]: вернуть tf.numpy_function(env_step, [действие], [tf.float32, tf.int32, tf.int32]) Запускает выпуск:
CAR_POINT_FAIL_THRESHOLD = 30 защита run_episode( начальное_состояние: tf.Tensor, модель: tf.keras.Model, max_steps: int) -> Tuple[tf.Tensor, tf.Tensor, tf.Tensor]: """Запускает один эпизод для сбора обучающих данных.""" action_probs = tf.TensorArray(dtype=tf.float32, size=0, Dynamic_size=True) значения = tf.TensorArray(dtype=tf.float32, size=0, Dynamic_size=True) награды = tf.TensorArray(dtype=tf.int32, size=0, Dynamic_size=True) начальное_состояние_форма = начальное_состояние[0].форма состояние = начальное_состояние вознаграждение_cache = Collections.deque(maxlen=CAR_POINT_FAIL_THRESHOLD) для t в tf.range(max_steps): # Преобразование состояния в пакетный тензор (размер пакета = 1) # состояние = tf.expand_dims(состояние, 0) # Запустите модель и получите вероятности действий и критическое значение action_logits_t, значение = модель (состояние) # Выборка следующего действия из распределения вероятности действия действие = tf.random.categorical(action_logits_t, 1)[0, 0] action_probs_t = tf.nn.softmax(action_logits_t) # Сохранение критических значений значения = значения.write(t, tf.squeeze(значение)) # Сохраняем вероятность выбранного действия action_probs = action_probs.write(t, action_probs_t[0, action]) # Примените действие к окружающей среде, чтобы получить следующее состояние и награду nstate, вознаграждение, выполнено = tf_env_step(действие) nstate.set_shape(initial_state_shape) # Добавляем состояние к пакету состояний состояние = tf.concat([state[1:],[nstate]], ось=0) # Награда магазина вознаграждения = вознаграждение.write(t, вознаграждение) вознаграждение_cache.append(int(награда)) если len(reward_cache) >= CAR_POINT_FAIL_THRESHOLD и статистика.mean(reward_cache) == 0: перерыв если tf.cast(сделано, tf.bool): перерыв action_probs = action_probs.stack() значения = значения.стек() награды = вознаграждения.стек() вернуть action_probs, значения, награды Рассчитать ожидаемую доходность за каждый временной шаг:
def get_expected_return( награды: tf.Tensor, гамма: плавающая, стандартизировать: bool = True) -> tf.Tensor: n = tf.shape(награды)[0] возвращает = tf.TensorArray(dtype=tf.float32, size=n) # Начните с конца «наград» и накапливайте суммы вознаграждений # в массив return вознаграждения = tf.cast(rewards[::-1], dtype=tf.float32) Discounted_sum = tf.constant(0,0) скидка_сумма_форма = скидка_сумма.форма для меня в tf.range(n): награда = награды[я] скидка_сумма = вознаграждение + гамма * скидка_сумма Discounted_sum.set_shape(discounted_sum_shape) return = return.write(i, Discounted_sum) возвращает = возвращает.стек()[::-1] если стандартизировать: возвращает = ((возвращает - tf.math.reduce_mean(возвращает)) / (tf.math.reduce_std(возвращает) + eps)) возврат возвращается вычисляет потери:
huber_loss = tf.keras.losses.Huber(reduction=tf.keras.losses.Reduction.SUM) Защиту Compute_loss( action_probs: tf.Tensor, значения: tf.Tensor, возвращает: tf.Tensor) -> tf.Tensor: """Вычисляет совокупные потери актера и критика.""" преимущество = прибыль - ценности action_log_probs = tf.math.log(action_probs) act_loss = -tf.math.reduce_sum (action_log_probs * преимущество) Critic_loss = Huber_loss(значения, возвраты) вернуть актер_лосс + критик_лосс Выполняет этап обучения модели:
@tf.function защита train_step( начальное_состояние: tf.Tensor, модель: tf.keras.Model, оптимизатор: tf.keras.optimizers.Optimizer, гамма: плавающая, max_steps_per_episode: int) -> tf.Тензор: с tf.GradientTape() в качестве ленты: # Запускаем модель для одного эпизода, чтобы собрать данные обучения action_probs, значения, награды = run_episode( начальное_состояние, модель, max_steps_per_episode) # Рассчитаем ожидаемую доходность return = get_expected_return(награды, гамма) # Преобразование обучающих данных в соответствующие формы тензоров TF action_probs, значения, возвращает = [ tf.expand_dims(x, 1) для x в [action_probs, значения, возвраты]] # Рассчитаем значения потерь для обновления нашей сети потеря = вычисление_потеря(action_probs, значения, возвраты) # Вычисляем градиенты потерь грады = лента.градиент(потеря, модель.trainable_variables) clipped_gradients, _ = tf.clip_by_global_norm(grads, clip_norm=1.0) # Примените градиенты к параметрам модели оптимизатор.apply_gradients(zip(обрезанные_градиенты, model.trainable_variables)) эпизод_reward = tf.math.reduce_sum(награды) вернуть эпизод_reward, проигрыш Функция визуализации окружающей среды:
def Visualize(max_steps: int): env2 = Gym.make("CarRacing-v2", Continuous = False, render_mode = "human") начальное_состояние, информация = env2.reset() начальное_состояние = cv_operations(начальное_состояние) начальное_состояние = [начальное_состояние, начальное_состояние, начальное_состояние, начальное_состояние] Initial_state = tf.constant(initial_state, dtype=tf.float32) начальное_состояние_форма = начальное_состояние[0].форма состояние = начальное_состояние вознаграждение_cache = Collections.deque(maxlen=CAR_POINT_FAIL_THRESHOLD) для t в диапазоне (max_steps): action_logits_t, значение = модель (состояние) действие = tf.random.categorical(action_logits_t, 1)[0, 0] nstate, вознаграждение, прекращено, усечено, информация = env2.step(action.numpy()) вознаграждение_cache.append(награда) nstate = cv_operations (nstate) nstate = tf.constant(nstate, dtype=tf.float32) nstate.set_shape(initial_state_shape) состояние = tf.concat([state[1:],[nstate]], ось=0) если len(reward_cache) >= CAR_POINT_FAIL_THRESHOLD и статистика.mean(reward_cache) == 0: перерыв если tf.cast(завершено, tf.bool): перерыв энв2.закрыть() возвращаться сохраняется при неожиданном выходе:
def exit_handler(): сохранить (модель) atexit.register(exit_handler) Модель запуска:
min_episodes_criterion = 100 max_episodes = 10000 max_steps_per_episode = 500 вознаграждение_порог = 475 работа_награда = 0 вознаграждение_arr = [] loss_arr = [] # Коэффициент скидки для будущих вознаграждений гамма = 0,99 # Сохраните награду за последние эпизоды Episodes_reward: Collections.deque = Collections.deque(maxlen=min_episodes_criterion) t = tqdm.trange(max_episodes) для меня в т: начальное_состояние, информация = env.reset() начальное_состояние = cv_operations(начальное_состояние) начальное_состояние = [начальное_состояние, начальное_состояние, начальное_состояние, начальное_состояние] Initial_state = tf.constant(initial_state, dtype=tf.float32) tf.config.run_functions_eagerly(False) эпизод_награда, потеря = поезд_шаг( начальное_состояние, модель, оптимизатор, гамма, max_steps_per_episode) Episode_reward = int(episode_reward) эпизоды_reward.append(episode_reward) вознаграждение_arr.append(episode_reward) loss_arr.append(loss.numpy()) работа_награда = статистика.среднее(эпизоды_награда) t.set_postfix( Episode_reward=episode_reward, Running_reward=running_reward) если я > 0 и я % 100 == 0: визуализировать (max_steps_per_episode) сохранить (модель) если Running_reward > вознаграждение_threshold и i >= min_episodes_criterion: сохранить (модель) перерыв print(f'\nРешено в эпизоде {i}: средняя награда: {running_reward:.2f}!') График потерь при обучении и визуализация:
plt.subplot(121) plt.plot(reward_arr, 'r-', label='score', linewidth=1) plt.xlabel('Эпизод') plt.legend() plt.subplot(122) plt.plot(loss_arr, 'b-', label='loss', linewidth=1) plt.xlabel('Эпизод') plt.legend() plt.show() визуализировать (max_steps_per_episode)
Он определяет, как двигаться дальше, но не более того.
Я пробовал переключить CNN на сигмовидную активацию, уменьшив количество сверточных слоев, увеличив количество сверточных слоев и добавив плотные слои. Ничего не сработало. Вот мой код: импорт и запуск:
импортировать спортзал как спортзал импортировать numpy как np импортировать тензорный поток как tf импортировать коллекции статистика импорта импортировать tqdm импортировать matplotlib.pyplot как plt импортировать ОС импортировать cv2 импортировать atexit импортировать Shutil от ввода списка импорта, кортежа из изображения импорта PIL gpu = tf.config.experimental.list_physical_devices('GPU')[0] tf.config.experimental.set_memory_growth(GPU, True) env = Gym.make("CarRacing-v2", Continuous = False, render_mode="rgb_array") семя = 69 tf.random.set_seed(семя) np.random.seed(семя) # Небольшое значение эпсилон для стабилизации операций деления eps = np.finfo(np.float32).eps.item() num_hidden_units = 256 dir_name = "Автомобильные гонки" SAVE_PATH = f"C:/Users/potot/Desktop/code/Research/Gymnasium/Saved Models/{dir_name}/{num_hidden_units}/" Определение модели:
class ActorCritic(tf.keras.Model): """Объединенная актерско-критическая сеть.""" защита __init__( себя, число_действий: целое число, num_hidden_units: интервал, image_shape: Tuple[int,int]): """Инициализировать.""" супер().__init__() self.common = tf.keras.Sequential([ tf.keras.layers.Conv2D(32, (3, 3), активация = 'relu', input_shape = image_shape), tf.keras.layers.MaxPooling2D((2, 2)), tf.keras.layers.Conv2D(64, (3, 3), активация = 'relu'), tf.keras.layers.MaxPooling2D((2, 2)), tf.keras.layers.Conv2D(64, (3, 3), активация = 'relu'), tf.keras.layers.Flatten(), tf.keras.layers.Dropout(0,5), ]) self.actor = tf.keras.layers.Dense(num_actions,activation='softmax') self.critic = tf.keras.layers.Dense(1) # Добавьте сглаживающий слой к выходным данным критика, чтобы удалить пространственные измерения. self.flatten = tf.keras.layers.Flatten() def call(self, inputs: tf.Tensor) -> Tuple[tf.Tensor, tf.Tensor]: x = self.common(входные данные) актер_выход = self.actor(x) Critic_output = self.critic(x) вернуть актер_выход, критик_выход функция сохранения:
def save(модель: tf.keras.Model): dir_list = os.listdir(SAVE_PATH) num_saves = 8 если len(dir_list) >= num_saves: для папки в dir_list: путь к файлу = os.path.join(SAVE_PATH,папка) если ул(папка) == "1": Shutil.rmtree(os.path.join(SAVE_PATH, папка)) продолжать os.rename(filepath,f"{SAVE_PATH}{int(folder)-1}") новый_путь = os.path.join(SAVE_PATH,f"{num_saves}") os.madeirs(новый_путь) model.save_weights(new_path) еще: new_path = f"{SAVE_PATH}{len(dir_list)+1}" os.madeirs(новый_путь) model.save_weights(new_path+"/1") возвращаться Инициализирует модель:
num_actions = env.action_space.n image_shape = (21,24,1) если нет os.path.exists(SAVE_PATH): os.madeirs(SAVE_PATH) если len(os.listdir(SAVE_PATH)) > 0: модель = ActorCritic (num_actions, num_hidden_units, image_shape) модель (np.expand_dims (np.zeros (image_shape), ось = 0)) model.load_weights(f"{SAVE_PATH}{os.listdir(SAVE_PATH)[-1]}/1") print(f"Загрузка модели {os.listdir(SAVE_PATH)[-1]}...") еще: модель = ActorCritic (num_actions, num_hidden_units, image_shape) оптимизатор = tf.keras.optimizers.Adam (learning_rate=0,01) Группирует операции компьютерного зрения, выполняемые в состоянии наблюдения:
def cv_operations(state): # Image.fromarray(state).save("Гимназия/bruh.png") состояние = cv2.cvtColor(состояние, cv2.COLOR_RGB2GRAY) Т, состояние = cv2.threshold(state, 100, 255, cv2.THRESH_BINARY_INV) состояние = состояние[0:85,0:] состояние = cv2.resize(состояние, (24,21)) # Image.fromarray(state).save("Gymnasium/bruh2.png") состояние = состояние.reshape((21,24,1)) вернуть состояние Один шаг среды:
def env_step(action: np.ndarray) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: """Возвращает состояние, награду и флаг завершения действия.""" состояние, награда, выполнено, усечено, информация = env.step(действие) состояние = cv_operations (состояние) возврат (state.astype(np.float32), np.array(награда, np.int32), np.array(готово, np.int32)) защита tf_env_step (действие: tf.Tensor) -> Список[tf.Tensor]: вернуть tf.numpy_function(env_step, [действие], [tf.float32, tf.int32, tf.int32]) Запускает выпуск:
CAR_POINT_FAIL_THRESHOLD = 30 защита run_episode( начальное_состояние: tf.Tensor, модель: tf.keras.Model, max_steps: int) -> Tuple[tf.Tensor, tf.Tensor, tf.Tensor]: """Запускает один эпизод для сбора обучающих данных.""" action_probs = tf.TensorArray(dtype=tf.float32, size=0, Dynamic_size=True) значения = tf.TensorArray(dtype=tf.float32, size=0, Dynamic_size=True) награды = tf.TensorArray(dtype=tf.int32, size=0, Dynamic_size=True) начальное_состояние_форма = начальное_состояние[0].форма состояние = начальное_состояние вознаграждение_cache = Collections.deque(maxlen=CAR_POINT_FAIL_THRESHOLD) для t в tf.range(max_steps): # Преобразование состояния в пакетный тензор (размер пакета = 1) # состояние = tf.expand_dims(состояние, 0) # Запустите модель и получите вероятности действий и критическое значение action_logits_t, значение = модель (состояние) # Выборка следующего действия из распределения вероятности действия действие = tf.random.categorical(action_logits_t, 1)[0, 0] action_probs_t = tf.nn.softmax(action_logits_t) # Сохранение критических значений значения = значения.write(t, tf.squeeze(значение)) # Сохраняем вероятность выбранного действия action_probs = action_probs.write(t, action_probs_t[0, action]) # Примените действие к окружающей среде, чтобы получить следующее состояние и награду nstate, вознаграждение, выполнено = tf_env_step(действие) nstate.set_shape(initial_state_shape) # Добавляем состояние к пакету состояний состояние = tf.concat([state[1:],[nstate]], ось=0) # Награда магазина вознаграждения = вознаграждение.write(t, вознаграждение) вознаграждение_cache.append(int(награда)) если len(reward_cache) >= CAR_POINT_FAIL_THRESHOLD и статистика.mean(reward_cache) == 0: перерыв если tf.cast(сделано, tf.bool): перерыв action_probs = action_probs.stack() значения = значения.стек() награды = вознаграждения.стек() вернуть action_probs, значения, награды Рассчитать ожидаемую доходность за каждый временной шаг:
def get_expected_return( награды: tf.Tensor, гамма: плавающая, стандартизировать: bool = True) -> tf.Tensor: n = tf.shape(награды)[0] возвращает = tf.TensorArray(dtype=tf.float32, size=n) # Начните с конца «наград» и накапливайте суммы вознаграждений # в массив return вознаграждения = tf.cast(rewards[::-1], dtype=tf.float32) Discounted_sum = tf.constant(0,0) скидка_сумма_форма = скидка_сумма.форма для меня в tf.range(n): награда = награды[я] скидка_сумма = вознаграждение + гамма * скидка_сумма Discounted_sum.set_shape(discounted_sum_shape) return = return.write(i, Discounted_sum) возвращает = возвращает.стек()[::-1] если стандартизировать: возвращает = ((возвращает - tf.math.reduce_mean(возвращает)) / (tf.math.reduce_std(возвращает) + eps)) возврат возвращается вычисляет потери:
huber_loss = tf.keras.losses.Huber(reduction=tf.keras.losses.Reduction.SUM) Защиту Compute_loss( action_probs: tf.Tensor, значения: tf.Tensor, возвращает: tf.Tensor) -> tf.Tensor: """Вычисляет совокупные потери актера и критика.""" преимущество = прибыль - ценности action_log_probs = tf.math.log(action_probs) act_loss = -tf.math.reduce_sum (action_log_probs * преимущество) Critic_loss = Huber_loss(значения, возвраты) вернуть актер_лосс + критик_лосс Выполняет этап обучения модели:
@tf.function защита train_step( начальное_состояние: tf.Tensor, модель: tf.keras.Model, оптимизатор: tf.keras.optimizers.Optimizer, гамма: плавающая, max_steps_per_episode: int) -> tf.Тензор: с tf.GradientTape() в качестве ленты: # Запускаем модель для одного эпизода, чтобы собрать данные обучения action_probs, значения, награды = run_episode( начальное_состояние, модель, max_steps_per_episode) # Рассчитаем ожидаемую доходность return = get_expected_return(награды, гамма) # Преобразование обучающих данных в соответствующие формы тензоров TF action_probs, значения, возвращает = [ tf.expand_dims(x, 1) для x в [action_probs, значения, возвраты]] # Рассчитаем значения потерь для обновления нашей сети потеря = вычисление_потеря(action_probs, значения, возвраты) # Вычисляем градиенты потерь грады = лента.градиент(потеря, модель.trainable_variables) clipped_gradients, _ = tf.clip_by_global_norm(grads, clip_norm=1.0) # Примените градиенты к параметрам модели оптимизатор.apply_gradients(zip(обрезанные_градиенты, model.trainable_variables)) эпизод_reward = tf.math.reduce_sum(награды) вернуть эпизод_reward, проигрыш Функция визуализации окружающей среды:
def Visualize(max_steps: int): env2 = Gym.make("CarRacing-v2", Continuous = False, render_mode = "human") начальное_состояние, информация = env2.reset() начальное_состояние = cv_operations(начальное_состояние) начальное_состояние = [начальное_состояние, начальное_состояние, начальное_состояние, начальное_состояние] Initial_state = tf.constant(initial_state, dtype=tf.float32) начальное_состояние_форма = начальное_состояние[0].форма состояние = начальное_состояние вознаграждение_cache = Collections.deque(maxlen=CAR_POINT_FAIL_THRESHOLD) для t в диапазоне (max_steps): action_logits_t, значение = модель (состояние) действие = tf.random.categorical(action_logits_t, 1)[0, 0] nstate, вознаграждение, прекращено, усечено, информация = env2.step(action.numpy()) вознаграждение_cache.append(награда) nstate = cv_operations (nstate) nstate = tf.constant(nstate, dtype=tf.float32) nstate.set_shape(initial_state_shape) состояние = tf.concat([state[1:],[nstate]], ось=0) если len(reward_cache) >= CAR_POINT_FAIL_THRESHOLD и статистика.mean(reward_cache) == 0: перерыв если tf.cast(завершено, tf.bool): перерыв энв2.закрыть() возвращаться сохраняется при неожиданном выходе:
def exit_handler(): сохранить (модель) atexit.register(exit_handler) Модель запуска:
min_episodes_criterion = 100 max_episodes = 10000 max_steps_per_episode = 500 вознаграждение_порог = 475 работа_награда = 0 вознаграждение_arr = [] loss_arr = [] # Коэффициент скидки для будущих вознаграждений гамма = 0,99 # Сохраните награду за последние эпизоды Episodes_reward: Collections.deque = Collections.deque(maxlen=min_episodes_criterion) t = tqdm.trange(max_episodes) для меня в т: начальное_состояние, информация = env.reset() начальное_состояние = cv_operations(начальное_состояние) начальное_состояние = [начальное_состояние, начальное_состояние, начальное_состояние, начальное_состояние] Initial_state = tf.constant(initial_state, dtype=tf.float32) tf.config.run_functions_eagerly(False) эпизод_награда, потеря = поезд_шаг( начальное_состояние, модель, оптимизатор, гамма, max_steps_per_episode) Episode_reward = int(episode_reward) эпизоды_reward.append(episode_reward) вознаграждение_arr.append(episode_reward) loss_arr.append(loss.numpy()) работа_награда = статистика.среднее(эпизоды_награда) t.set_postfix( Episode_reward=episode_reward, Running_reward=running_reward) если я > 0 и я % 100 == 0: визуализировать (max_steps_per_episode) сохранить (модель) если Running_reward > вознаграждение_threshold и i >= min_episodes_criterion: сохранить (модель) перерыв print(f'\nРешено в эпизоде {i}: средняя награда: {running_reward:.2f}!') График потерь при обучении и визуализация:
plt.subplot(121) plt.plot(reward_arr, 'r-', label='score', linewidth=1) plt.xlabel('Эпизод') plt.legend() plt.subplot(122) plt.plot(loss_arr, 'b-', label='loss', linewidth=1) plt.xlabel('Эпизод') plt.legend() plt.show() визуализировать (max_steps_per_episode)