В этом примере показано, как изучить оптимальную политику планирования насосов для системы распределения воды с использованием обучения армированию (RL).
На следующем рисунке показана система распределения воды.

Здесь:
- количество воды, подаваемой в резервуар для воды из резервуара.
- это количество воды, вытекающей из резервуара для удовлетворения потребностей в использовании.
Целью средства обучения армированию является планирование количества работающих насосов для минимизации потребления энергии системой и удовлетворения потребности в использовании (0). Дибамики танковой системы регулируются следующим уравнением.
QDemand (t)
Здесь м2 = 7m. Потребность в течение 24-часового периода является функцией времени, указанного как
+ (t)
где ) является ожидаемой потребностью, t) представляет неопределенность потребности, которая выбирается из равномерного случайного распределения.
Подача определяется количеством работающих насосов в a∈{0,1,2,3}according со следующим отображением.
2344a = 3 cmh
Для упрощения проблемы энергопотребление определяется как количество работающих насосов, .
Следующая функция является наградой для этой среды. Во избежание переполнения или опорожнения резервуара добавляются дополнительные расходы, если высота воды близка к максимальному или минимальному уровню воды, hmaxor , соответственно.
h≤0.1) -a
Чтобы создать и профиль потребности в воде на основе количества рассмотренных дней, используйте generateWaterDemand функция, определенная в конце этого примера.
num_days = 4; % Number of days
[WaterDemand,T_max] = generateWaterDemand(num_days);Просмотр профиля спроса.
plot(WaterDemand)

Откройте распределительную систему Simulink model.
mdl = "watertankscheduling";
open_system(mdl)
В дополнение к агенту обучения усилению в блоке функции MATLAB закона управления определен простой контроллер базовой линии. Этот контроллер включает определенное количество насосов в зависимости от уровня воды.
Укажите начальную высоту воды.
h0 = 3; % mУкажите параметры модели.
SampleTime = 0.2; H_max = 7; % Max tank height (m) A_tank = 40; % Area of tank (m^2)
Чтобы создать интерфейс среды для модели Simulink, сначала определите спецификации действий и наблюдений, actInfo и obsInfoсоответственно. Действием агента является выбранное количество насосов. Наблюдением агента является высота воды, которая поглощается как сигнал непрерывного времени.
actInfo = rlFiniteSetSpec([0,1,2,3]); obsInfo = rlNumericSpec([1,1]);
Создайте интерфейс среды.
env = rlSimulinkEnv(mdl,mdl+"/RL Agent",obsInfo,actInfo);Укажите пользовательскую функцию сброса, определенную в конце этого примера, которая случайным образом определяет начальную высоту воды и потребность в воде. Это позволяет обучать агента различным начальным уровням воды и функциям потребности в воде для каждого эпизода.
env.ResetFcn = @(in)localResetFcn(in);
Агент DQN аппроксимирует долгосрочное вознаграждение, учитывая наблюдения и действия, используя представление функции Q-значения критика. Чтобы создать критика, сначала создайте глубокую нейронную сеть. Дополнительные сведения о создании глубокого представления функции значений нейронной сети см. в разделе Создание представлений политик и функций значений.
% Fix the random generator seed for reproducibility.
rng(0);Создать глубокую нейронную сеть для критика. Для этого примера используйте непериодическую нейронную сеть. Для использования рекуррентной нейронной сети, набор useLSTM кому true.
useLSTM = false; if useLSTM layers = [ sequenceInputLayer(obsInfo.Dimension(1),"Name","state","Normalization","none") fullyConnectedLayer(32,"Name","fc_1") reluLayer("Name","relu_body1") lstmLayer(32,"Name","lstm") fullyConnectedLayer(32,"Name","fc_3") reluLayer("Name","relu_body3") fullyConnectedLayer(numel(actInfo.Elements),"Name","output")]; else layers = [ featureInputLayer(obsInfo.Dimension(1),"Name","state","Normalization","none") fullyConnectedLayer(32,"Name","fc_1") reluLayer("Name","relu_body1") fullyConnectedLayer(32,"Name","fc_2") reluLayer("Name","relu_body2") fullyConnectedLayer(32,"Name","fc_3") reluLayer("Name","relu_body3") fullyConnectedLayer(numel(actInfo.Elements),"Name","output")]; end
Укажите параметры для создания критического представления.
criticOpts = rlRepresentationOptions('LearnRate',0.001,'GradientThreshold',1);
Создайте критическое представление с помощью определенной глубокой нейронной сети и опций.
critic = rlQValueRepresentation(layerGraph(layers),obsInfo,actInfo,... 'Observation',{'state'},criticOpts);
Чтобы создать агента, сначала укажите его параметры. При использовании сети LSTM установите длину последовательности на 20.
opt = rlDQNAgentOptions('SampleTime',SampleTime); if useLSTM opt.SequenceLength = 20; else opt.SequenceLength = 1; end opt.DiscountFactor = 0.995; opt.ExperienceBufferLength = 1e6; opt.EpsilonGreedyExploration.EpsilonDecay = 1e-5; opt.EpsilonGreedyExploration.EpsilonMin = .02;
Создайте агент, используя определенные опции и критическое представление.
agent = rlDQNAgent(critic,opt);
Для обучения агента сначала укажите варианты обучения. В этом примере используются следующие опции.
Запустить обучение для 1000 серий, с каждым эпизодом длительностью в ceil(T_max/Ts) временные шаги.
Отображение хода обучения в диалоговом окне «Менеджер эпизодов» (установите Plots опция)
Укажите параметры обучения с помощью rlTrainingOptions объект.
trainOpts = rlTrainingOptions(... 'MaxEpisodes',1000, ... 'MaxStepsPerEpisode',ceil(T_max/SampleTime), ... 'Verbose',false, ... 'Plots','training-progress',... 'StopTrainingCriteria','EpisodeCount',... 'StopTrainingValue',1000,... 'ScoreAveragingWindowLength',100);
Хотя вы не делаете этого для этого примера, вы можете сохранить агентов во время процесса обучения. Например, следующие параметры позволяют сохранить каждого агента со значением вознаграждения, большим или равным -42.
Save agents using SaveAgentCriteria if necessary trainOpts.SaveAgentCriteria = 'EpisodeReward'; trainOpts.SaveAgentValue = -42;
Обучение агента с помощью train функция. Обучение этого агента - интенсивный вычислительный процесс, который занимает несколько часов. Чтобы сэкономить время при выполнении этого примера, загрузите предварительно подготовленный агент путем установки doTraining кому false. Чтобы обучить агента самостоятельно, установите doTraining кому true.
doTraining = false; if doTraining % Train the agent. trainingStats = train(agent,env,trainOpts); else % Load the pretrained agent for the example. load('SimulinkWaterDistributionDQN.mat','agent') end
На следующем рисунке показан ход обучения.

Для проверки работоспособности обучаемого агента смоделируйте его в среде водоемов. Дополнительные сведения о моделировании агентов см. в разделе rlSimulationOptions и sim.
Для моделирования производительности агента подключите блок агента RL путем переключения блока ручного переключения.
set_param(mdl+"/Manual Switch",'sw','0');
Установите максимальное количество шагов для каждого моделирования и количество моделирований. В этом примере выполните 30 моделирований. Функция сброса среды устанавливает различную начальную высоту воды, и потребность в воде различна в каждом моделировании.
NumSimulations = 30; simOptions = rlSimulationOptions('MaxSteps',T_max/SampleTime,... 'NumSimulations', NumSimulations);
Для сравнения агента с контроллером базовой линии при тех же условиях сбросьте начальное случайное начальное число, используемое в функции сброса среды.
env.ResetFcn("Reset seed");Смоделировать агент против окружающей среды.
experienceDQN = sim(env,agent,simOptions);
Для сравнения агента DQN с контроллером базовой линии необходимо смоделировать контроллер базовой линии, используя те же опции моделирования и начальное случайное начальное значение для функции сброса.
Включите базовый контроллер.
set_param(mdl+"/Manual Switch",'sw','1');
Для сравнения агента с контроллером базовой линии при тех же условиях сбросьте случайное начальное значение, используемое в функции сброса среды.
env.ResetFcn("Reset seed");Смоделировать базовый контроллер в зависимости от среды.
experienceBaseline = sim(env,agent,simOptions);
Инициализируйте векторы совокупного результата вознаграждения как для агента, так и для базового контроллера.
resultVectorDQN = zeros(NumSimulations, 1); resultVectorBaseline = zeros(NumSimulations,1);
Расчет совокупных вознаграждений как для агента, так и для базового контроллера.
for ct = 1:NumSimulations resultVectorDQN(ct) = sum(experienceDQN(ct).Reward); resultVectorBaseline(ct) = sum(experienceBaseline(ct).Reward); end
Постройте график совокупных вознаграждений.
plot([resultVectorDQN resultVectorBaseline],'o') set(gca,'xtick',1:NumSimulations) xlabel("Simulation number") ylabel('Cumulative Reward') legend('DQN','Baseline','Location','NorthEastOutside')

Совокупное вознаграждение, полученное агентом, постоянно составляет около -40. Это значение намного больше среднего вознаграждения, полученного контроллером базовой линии. Поэтому агент DQN последовательно превосходит базовый контроллер с точки зрения экономии энергии.
Функция спроса на воду
function [WaterDemand,T_max] = generateWaterDemand(num_days) t = 0:(num_days*24)-1; % hr T_max = t(end); Demand_mean = [28, 28, 28, 45, 55, 110, 280, 450, 310, 170, 160, 145, 130, ... 150, 165, 155, 170, 265, 360, 240, 120, 83, 45, 28]'; % m^3/hr Demand = repmat(Demand_mean,1,num_days); Demand = Demand(:); % Add noise to demand a = -25; % m^3/hr b = 25; % m^3/hr Demand_noise = a + (b-a).*rand(numel(Demand),1); WaterDemand = timeseries(Demand + Demand_noise,t); WaterDemand.Name = "Water Demand"; end
Функция сброса
function in = localResetFcn(in) % Use a persistent random seed value to evaluate the agent and the baseline % controller under the same conditions. persistent randomSeed if isempty(randomSeed) randomSeed = 0; end if strcmp(in,"Reset seed") randomSeed = 0; return end randomSeed = randomSeed + 1; rng(randomSeed) % Randomize water demand. num_days = 4; H_max = 7; [WaterDemand,~] = generateWaterDemand(num_days); assignin('base','WaterDemand',WaterDemand) % Randomize initial height. h0 = 3*randn; while h0 <= 0 || h0 >= H_max h0 = 3*randn; end blk = 'watertankscheduling/Water Tank System/Initial Water Height'; in = setBlockParameter(in,blk,'Value',num2str(h0)); end