мл-агенты проектная практика (1)

обучение с подкреплением

Эта статья была впервые опубликована на:Уокер ИИ

Обучение с подкреплением — это проблема в машинном обучении и искусственном интеллекте, которая изучает, как достичь конкретной цели с помощью ряда последовательных решений. Это тип алгоритма, который позволяет компьютеру ничего не осознавать с самого начала, без какой-либо идеи в голове, путем непрерывных проб и ошибок, обучения на ошибках и, наконец, нахождения закона и изучения метода достижения цели. Это полный процесс обучения с подкреплением. Здесь мы можем обратиться к рисунку ниже для более интуитивного объяснения.

Агент — это агент, то есть наш алгоритм, который выступает в виде игрока в игре. С помощью ряда стратегий агент выводит действие (Action) для воздействия на среду (Environment), а среда возвращает значение состояния после действия, то есть наблюдение (Observation) и значение вознаграждения (Reward) в фигура. Когда среда возвращает значение вознаграждения агенту, оно обновляет свое состояние, и агент получает новое наблюдение.

1. ml-agents

1.1 Введение

В настоящее время большинство игр Unity в игре имеют большое количество игр, движок совершенен, а тренировочную среду легко построить. Поскольку Unity может быть кроссплатформенным, его можно обучить на платформах Windows и Linux, а затем преобразовать в WebGL и опубликовать в Интернете. А mlgents — это подключаемый модуль с открытым исходным кодом для Unity, который позволяет разработчикам обучаться в среде Unity даже без написания кода на стороне Python или без глубокого понимания таких алгоритмов, как PPO и SAC. Пока разработчики настраивают параметры, они могут легко использовать алгоритм обучения с подкреплением для обучения своих собственных моделей.

Если вас интересует алгоритм, пожалуйста, нажмите здесь, чтобы узнать алгоритмPPO,SAC.

Нажмите сюда, для получения дополнительной информации

1.2 Установка Anaconda, tensorflow и tensorboard

Мл-агенты, представленные в этой статье, должны общаться с Tensorflow через Python.Во время обучения наблюдение, действие, вознаграждение, выполнено и другая информация получаются со стороны Unity мл-агентов и отправляются в Tensorflow для обучения, а затем решение модели передается в Unity. Поэтому перед установкой мл-агентов необходимо установить tensorflow по следующей ссылке.

Tensorboard облегчает визуализацию данных и анализ того, соответствует ли модель ожиданиям.

Для получения подробной информации об установке нажмите здесь

1.3 шага установки ml-агентов

(1) Перейдите на github, чтобы загрузить мл-агенты (в этом примере используется версия Release6)

гитхаб можно скачать

(2) Разархивируйте сжатый пакет и поместитеcom.unity.ml-agents,com.unity.ml-agents.extensionsПоместите его в каталог пакетов Unity (если у вас его нет, создайте его), поместитеmanifest.jsonДобавьте эти два каталога в файл .

(3) После завершения установки импортируйте его в проект, создайте новый сценарий и введите следующую ссылку, чтобы проверить успешную установку.

using Unity.MLAgents;
using Unity.MLAgents.Sensors;
using Unity.MLAgents.Policies;

public class MyAgent : Agent

{

}

2. Пример обучения мл-агентов

2.1 Схема и проект

Среда обычно описывается марковским процессом, агент генерирует действие, принимая определенную политику, взаимодействует со средой и генерирует вознаграждение. Затем агент корректирует и оптимизирует текущую политику в соответствии с Наградой.

Фактический проект этого примера относится к правилам Xiaoxiaole, и вы можете получить три цвета одним и тем же цветом.В этом примере дополнительные награды в виде четырех последовательных цветов и нескольких последовательных цветов удалены (для облегчения дизайна среды).

Скачать пример проектаНажмите, чтобы перейти

Раздел экспорта проекта Unity можно найти на официальном сайте.Нажмите, чтобы перейти.

Далее будет представлен метод проектной практики с четырех точек зрения: извлечение интерфейса, выбор алгоритма, среда проектирования и настройка параметров.

2.2 Извлечение интерфейса ИИ игрового фреймворка

Извлеките из игры интерфейсы, необходимые для Наблюдения и Действия проекта. Используется для перехода в текущее состояние игры и выполнения игровых действий.

static List<ML_Unit> states = new List<ML_Unit>();

public class ML_Unit
{
	public int color = (int)CodeColor.ColorType.MaxNum;
	public int widthIndex = -1;
	public int heightIndex = -1;
}
//从当前画面中,拿到所有方块的信息,包含所在位置x(长度),位置y(高度),颜色(坐标轴零点在左上)
public static List<ML_Unit> GetStates()
{
	states.Clear();
	var xx = GameMgr.Instance.GetGameStates();
	for(int i = 0; i < num_widthMax;i++)
	{
		for(int j = 0; j < num_heightMax; j++)
		{
			ML_Unit tempUnit = new ML_Unit();
			try
			{
				tempUnit.color = (int)xx[i, j].getColorComponent.getColor;
			}
			catch
			{
				Debug.LogError($"GetStates i:{i} j:{j}");
			}
			tempUnit.widthIndex = xx[i, j].X;
			tempUnit.heightIndex = xx[i, j].Y;
			states.Add(tempUnit);
		}
	}
	return states;
}

public enum MoveDir
{
	up,
	right,
	down,
	left,
}

public static bool CheckMoveValid(int widthIndex, int heigtIndex, int dir)
{
	var valid = true;
	if (widthIndex == 0 && dir == (int)MoveDir.left)
	{
		valid = false;
	}
	if (widthIndex == num_widthMax - 1 && dir == (int)MoveDir.right)
	{
		valid = false;
	}

	if (heigtIndex == 0 && dir == (int)MoveDir.up)
	{
		valid = false;
	}

	if (heigtIndex == num_heightMax - 1 && dir == (int)MoveDir.down)
	{
		valid = false;
	}
	return valid;
}

//执行动作的接口,根据位置信息和移动方向,调用游戏逻辑移动方块。widthIndex 0-13,heigtIndex 0-6,dir 0-3 0上 1右 2下 3左
public static void SetAction(int widthIndex,int heigtIndex,int dir,bool immediately)
{
	if (CheckMoveValid(widthIndex, heigtIndex, dir))
	{
		GameMgr.Instance.ExcuteAction(widthIndex, heigtIndex, dir, immediately);
	}
}

2.3 Выбор игрового алгоритма искусственного интеллекта

Входя в первую тему проекта обучения с подкреплением, перед лицом множества алгоритмов выбор подходящего алгоритма может получить вдвое больший результат при вдвое меньших усилиях. Если вы не знакомы с характеристиками алгоритма, вы можете напрямую использовать PPO и SAC, которые поставляются с мл-агентами.

В этом примере алгоритм PPO, который автор использовал в начале, перепробовал множество настроек, и для правильного выполнения одного шага требуется в среднем 9 шагов, а эффект относительно плохой.

Позже я тщательно проанализировал игровую среду.Из-за игры в жанре «три в ряд» этого проекта среда каждый раз совершенно разная.Результат каждого шага мало влияет на следующий шаг, а спрос на цепи Маркова невелик. . . . Поскольку PPO представляет собой основанный на политике алгоритм OnPolicy, обновление политики каждого обновления происходит очень осторожно, что затрудняет сходимость результата (автор пробовал XX ткань, но она все равно не сходится).

По сравнению с DQN, который является базовым алгоритмом OffPolicy, он может собирать большое количество параметров среды для построения Qtable и постепенно находить максимальное значение соответствующей среды.

Проще говоря, PPO — это онлайн-обучение.Каждый раз, когда вы выполняете несколько сотен шагов, вы возвращаетесь назад и узнаете, что вы сделали правильно, а что — нет.Затем, обновив обучение, выполните еще несколько сотен шагов и так далее. Таким образом, эффективность обучения низка, и сложно найти глобально оптимальное решение.

DQN — это обучение в автономном режиме, оно может выполнять сотни миллионов шагов, а затем возвращаться и изучать все места, где оно выполнялось, и тогда легко найти глобально оптимальную точку.

(В этом примере в качестве демонстрации используется PPO, а затем используется внешний алгоритм в мл-агентах с использованием внешнего инструмента stable_baselines3 и алгоритма DQN для обучения)

2.4 Среда разработки игрового ИИ

После того, как мы определим структуру алгоритма, то, как спроектировать наблюдение, действие и вознаграждение, станет решающим фактором для определения эффекта обучения. В этой игре окружение в основном имеет две переменные: одна — положение блока, а другая — цвет блока.

--Наблюдение:

Для изображения выше наш пример состоит из 14 длинных, 7 широких и 6 цветов.

В качестве функции активации используется взмах, используемый мл-агентами, который может использовать не слишком большие числа с плавающей запятой (-10f ~10f), но для того, чтобы агенты получили более чистую среду и лучший эффект обучения, мы все же необходимо кодировать среду.

В этом примере автор использует метод Onehot для кодирования среды и размещает нулевую точку координаты в верхнем левом углу. Таким образом, код среды голубого квадрата в верхнем левом углу может быть выражен как [0,0,0,0,0,0,0,0,0,0,0,0,0,1] ,

Высокий [0,0,0,0,0,0,1], цвет обрабатывается фиксированным перечислением (желтый, зеленый, фиолетовый, розовый, синий, красный) цвет [0,0,0,0,1,0 ] .

Окружение содержит всего (14+7+6)14 * 7 = 2646

Пример кода:

public class MyAgent : Agent
{
	static List<ML_Unit> states = new List<ML_Unit>();
	public class ML_Unit
	{
		public int color = (int)CodeColor.ColorType.MaxNum;
		public int widthIndex = -1;
		public int heightIndex = -1;
	}

	public static List<ML_Unit> GetStates()
	{
		states.Clear();
		var xx = GameMgr.Instance.GetGameStates();
		for(int i = 0; i < num_widthMax;i++)
		{
			for(int j = 0; j < num_heightMax; j++)
			{
				ML_Unit tempUnit = new ML_Unit();
				try
				{
					tempUnit.color = (int)xx[i, j].getColorComponent.getColor;
				}
				catch
				{
					Debug.LogError($"GetStates i:{i} j:{j}");
				}
				tempUnit.widthIndex = xx[i, j].X;
				tempUnit.heightIndex = xx[i, j].Y;
				states.Add(tempUnit);
			}
		}
		return states;
	}

	List<ML_Unit> curStates = new List<ML_Unit>();
	public override void CollectObservations(VectorSensor sensor)
	{
		//需要判断是否方块移动结束,以及方块结算结束
		var receiveReward = GameMgr.Instance.CanGetState();
		var codeMoveOver = GameMgr.Instance.IsCodeMoveOver();
		if (!codeMoveOver || !receiveReward)
		{
			return;
		}

		//获得环境的状态信息
		curStates = MlagentsMgr.GetStates();
		for (int i = 0; i < curStates.Count; i++)
		{
			sensor.AddOneHotObservation(curStates[i].widthIndex, MlagentsMgr.num_widthMax);
			sensor.AddOneHotObservation(curStates[i].heightIndex, MlagentsMgr.num_heightMax);
			sensor.AddOneHotObservation(curStates[i].color, (int)CodeColor.ColorType.MaxNum);
		}
	}
}

--Действие:

Каждый блок может двигаться вверх, вниз, влево и вправо.Минимальная информация, которую нам нужно записать, включает 14*7 блоков, и каждый блок может двигаться в 4 направлениях.В этом примере направления пронумерованы (вверх, вправо, вниз, левый).

Верхний левый — это нулевая точка, голубой квадрат в верхнем левом углу занимает первые четыре действия Действия, а именно (голубой квадрат в верхнем левом углу движется вверх, голубой квадрат в верхнем левом углу движется вправо, и голубой квадрат в верхнем левом углу сдвинется вниз,

голубой квадрат в верхнем левом углу сдвинется влево).

Тогда действие содержит всего 14 * 7 * 4 = 392.

Внимательные читатели могут обнаружить, что голубой квадратик в левом верхнем углу не может двигаться вверх и влево, а в это время нам нужно установить Actionmask, чтобы блокировать эти действия, запрещенные правилами.

Пример кода:

public class MyAgent : Agent
{
	public enum MoveDir
	{
		up,
		right,
		down,
		left,
	}


	public void DecomposeAction(int actionId,out int width,out int height,out int dir)
	{
		width = actionId / (num_heightMax * num_dirMax);
		height = actionId % (num_heightMax * num_dirMax) / num_dirMax;
		dir = actionId % (num_heightMax * num_dirMax) % num_dirMax;
	}

	//执行动作,并获得该动作的奖励
	public override void OnActionReceived(float[] vectorAction)
	{
		//需要判断是否方块移动结束,以及方块结算结束
		var receiveReward = GameMgr.Instance.CanGetState();
		var codeMoveOver = GameMgr.Instance.IsCodeMoveOver();
		if (!codeMoveOver || !receiveReward)
		{
			Debug.LogError($"OnActionReceived CanGetState = {GameMgr.Instance.CanGetState()}");
			return;
		}

		if (invalidNums.Contains((int)vectorAction[0]))
		{
			//方块结算的调用,这里可以获得奖励(这里是惩罚,因为这是在屏蔽动作内,训练的时候会调用所有的动作,在非训练的时候则不会进此逻辑)
			GameMgr.Instance.OnGirdChangeOver?.Invoke(true, -5, false, false);
		}
		DecomposeAction((int)vectorAction[0], out int widthIndex, out int heightIndex, out int dirIndex);
		//这里回去执行动作,移动对应的方块,朝对应的方向。执行完毕后会获得奖励,并根据情况重置场景
		MlagentsMgr.SetAction(widthIndex, heightIndex, dirIndex, false);
	}

	//MlagentsMgr.SetAction调用后,执行完动作,会进入这个函数
	public void RewardShape(int score)
	{
		//计算获得的奖励
		var reward = (float)score * rewardScaler;
		AddReward(reward);
		//将数据加入tensorboard进行统计分析
		Mlstatistics.AddCumulativeReward(StatisticsType.action, reward);
		//每一步包含惩罚的动作,可以提升探索的效率
		var punish = -1f / MaxStep * punishScaler;
		AddReward(punish);
		//将数据加入tensorboard进行统计分析
		Mlstatistics.AddCumulativeReward( StatisticsType.punishment, punish);
	}

	//设置屏蔽动作actionmask
	public override void CollectDiscreteActionMasks(DiscreteActionMasker actionMasker)
	{
		// Mask the necessary actions if selected by the user.
		checkinfo.Clear();
		invalidNums.Clear();
		int invalidNumber = -1;
		for (int i = 0; i < MlagentsMgr.num_widthMax;i++)
		{
			for (int j = 0; j < MlagentsMgr.num_heightMax; j++)
			{
				if (i == 0)
				{
					invalidNumber = i * (num_widthMax + num_heightMax) + j * num_heightMax + (int)MoveDir.left;
					actionMasker.SetMask(0, new[] { invalidNumber });
				}
				if (i == num_widthMax - 1)
				{
					invalidNumber = i * (num_widthMax + num_heightMax) + j * num_heightMax + (int)MoveDir.right;
					actionMasker.SetMask(0, new[] { invalidNumber });
				}

				if (j == 0)
				{
					invalidNumber = i * (num_widthMax + num_heightMax) + j * num_heightMax + (int)MoveDir.up;
					actionMasker.SetMask(0, new[] { invalidNumber });
				}

				if (j == num_heightMax - 1)
				{
					invalidNumber = i * (num_widthMax + num_heightMax) + j * num_heightMax + (int)MoveDir.down;
					actionMasker.SetMask(0, new[] { invalidNumber });
				}
			}
		}
	}
}

В исходном проекте использовалось большое количество сопрограмм в процессе исключения, что имеет высокую задержку, нам нужно выжать время задержки при переобучении.

Чтобы не влиять на основную логику игры, в нормальных условиях измените fillTime в yield return new WaitForSeconds(fillTime) в сопрограмме на 0.001f, чтобы модель могла выбрать Action без большого количества изменений в логике игры. , Получите награду сейчас.

public class MyAgent : Agent
{
	private void FixedUpdate()
	{
		var codeMoveOver = GameMgr.Instance.IsCodeMoveOver();
		var receiveReward = GameMgr.Instance.CanGetState();
		if (!codeMoveOver || !receiveReward /*||!MlagentsMgr.b_isTrain*/)
		{		
			return;
		}
		//因为有协程需要等待时间,需要等待产生Reward后才去请求决策。所以不能使用ml-agents自带的DecisionRequester
		RequestDecision();
	}
}

2.5 Настройка параметров

После разработки модели давайте запустим предварительную версию, чтобы увидеть, насколько результаты отличаются от наших ожиданий.

Сначала настройте файл yaml для инициализации параметров сети:

behaviors:
SanXiaoAgent:
trainer_type: ppo
hyperparameters:
batch_size: 128
buffer_size: 2048
learning_rate: 0.0005
beta: 0.005
epsilon: 0.2
lambd: 0.9
num_epoch: 3
learning_rate_schedule: linear
network_settings:
normalize: false
hidden_units: 512
num_layers: 2
vis_encode_type: simple
memory: null
reward_signals:
extrinsic:
gamma: 0.99
strength: 1.0
init_path: null
keep_checkpoints: 25
checkpoint_interval: 100000
max_steps: 1000000
time_horizon: 128
summary_freq: 1000
threaded: true
self_play: null
behavioral_cloning: null
framework: tensorflow

Код обучения см. в официальном интерфейсе. В этом примере используется версия 6. Команды следующие:

mlagents-learn config/ppo/sanxiao.yaml --env=G:\mylab\ml-agent-buildprojects\sanxiao\windows\display\121001display\fangkuaixiaoxiaole --run-id=121001xxl --train --width 800 --height 600 --num-envs 2 --force --initialize-from=121001

После завершения обучения откройте Anaconda, введите tensorboard --logdir=results --port=6006 в основную директорию проекта ml-agents, скопируйтеhttp://PS20190711FUOV:6006/ Зайдите в браузер и откройте его, чтобы увидеть результаты тренировки.

(mlagents) PS G:\mylab\ml-agents-release_6> tensorboard --logdir=results --port=6006
TensorBoard 1.14.0 at http://PS20190711FUOV:6006/ (Press CTRL+C to quit)

Схема тренировочного эффекта выглядит следующим образом:

количество ходов - это среднее количество шагов, которые необходимо сделать, чтобы устранить блок, требуется около 9 тряпок, чтобы сделать правильный шаг. В случае использования Actionmask блокировку можно снять один раз примерно за 6 шагов.

-Награда:

Посмотрите на среднее значение дизайна вознаграждения в соответствии с вознаграждением в таблице выше. Мне нравится контролировать между 0,5 и 2. НаградаScaler может быть скорректирована, если она слишком велика или слишком мала.

//MlagentsMgr.SetAction调用后,执行完动作,会进入这个函数
public void RewardShape(int score)
{
	//计算获得的奖励
	var reward = (float)score * rewardScaler;
	AddReward(reward);
	//将数据加入tensorboard进行统计分析
	Mlstatistics.AddCumulativeReward(StatisticsType.action, reward);
	//每一步包含惩罚的动作,可以提升探索的效率
	var punish = -1f / MaxStep * punishScaler;
	AddReward(punish);
	//将数据加入tensorboard进行统计分析
	Mlstatistics.AddCumulativeReward( StatisticsType.punishment, punish);
}

3. Резюме и разные разговоры

В настоящее время официальная практика мл-агентов использует имитационное обучение и использует экспертные данные для обучения сети.

В этом примере автор попробовал PPO, и это дало определенный эффект. Однако в настоящее время PPO сложно обучить для match-3, трудно сходиться и сложно найти глобальный оптимум.

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

Текущий алгоритм обучения с подкреплением повторяется относительно быстро, если в приведенном выше есть какие-либо ошибки, пожалуйста, поправьте меня и двигайтесь вперед вместе.

Из-за ограниченного места код всего проекта не может быть опубликован.Если вы заинтересованы в исследовании, вы можете оставить сообщение ниже, и я могу отправить вам полный проект по электронной почте.

В дальнейшем я поделюсь внешним алгоритмом мл-агентов, использую внешний инструмент stable_baselines3, а для обучения использую алгоритм DQN.


PS: Для получения дополнительной технической галантереи, пожалуйста, обратите внимание на [Публичный аккаунт | xingzhe_ai] и обсудите с ходоками!