МІНІСТЕРСТВО ОСВІТИ ТА НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»
ЗВІТ ЛАБОРАТОРНОЇ РОБОТИ №4
З ПРЕДМЕТУ: «Теорія інтелектуальних систем»
ТЕМА: Дослідження методів та алгоритмів навчання з підкріпленням (Reinforcement Learning) в стаціонарному випадковому середовищі.
МЕТА: Дослідити роботу методів та алгоритмів навчання з підкріпленням, набути навички їх реалізації.
Хід роботи
1. Реалізувати обраний згідно варіанту метод навчання з підкріпленням у вигляді програми.
Приклади алгоритмів, що реалізують методи навчання з підкріпленням:
Розрахунок оціночної ваги дії
Згідно методу зваженої оцінки дій (action-value method) для кожної дії a визначається її оціночна вага
Qt(a) = st(a) / kt(a),
де
t – номер біжучого часового кроку,
kt(a) – кількість реалізацій дії a (скількі разів дія a була обрана та реалізована агентом на момент часу t),
st(a) – сумарний виграш, отриманий завдяки усім реалізаціям дії a.
e-жадібний метод навчання з підкріпленням (e-greedy RL)
2.0. Першу дію обрати рівновипадково.
2.1. Реалізувати обрану дію a.
2.2. Отримати відгук середовища (виграш/програш).
2.3. Перерахувати значення оціночної ваги Qt(a) дії a.
2.4. З ймовірністю (1-e) обрати наступну дію a',
для якої Qt(a') = max Qt(a), перейти до п.2.1.
2.5. З ймовірністю e обрати наступну дію a'
рівновипадково, перейти до п.2.1.
Номер варіанту:
e-greedy -> e-жадібний метод навчання з підкріпленням
N
Метод навчання з підкріпленням
Кількість доступних агенту дій
5
e-greedy
3
2. Фрагмент тексту програми обчислювального експерименту:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <tchar.h>
#include <math.h>
#define ENVTYPE 0
#define NACTIONS 3
#define NSTATES 2
#define NSTEPS 200
#define NREPLICAS 1000
#define REWARD 1//+1
#define PENALTY 0//-1
#define RLTYPE 3 //3 //4
#define RLEPSILON 0.1f
#define RLTAU 0.12f
int t; // current time step
int T = NSTEPS; // number of time steps = number of interactions between agent and environment
int n = NREPLICAS; // number of replicas
int nA = NACTIONS; // number of actions
int nS = NSTATES; // number of states
int env = ENVTYPE; // type of environment:
// env = 0 -> se (stationary environment)
float sePa[NACTIONS]; // se: probabilities of rewards for each action
int ceState; // ce: current state of commutative environment
float cePa[NSTATES][NACTIONS]; // ce: probabilities of reward for each action for each state of environment
float cePs[NSTATES][NSTATES]; // ce: probabilities of transition from one state to another
int agt;
int action=0; // current action = {0, ... ,(nA-1)}
int response; // current response of environment = {0;1}/{-1;+1}
int paction; // action of perfect agent
float e = RLEPSILON; // epsilon value (epsilon-greedy RL)
float tau = RLTAU; // tau value (softmax action selection)
int k[NACTIONS]; // number of realizations for each action
int r[NACTIONS]; // total reward for each action
float Q[NACTIONS]; // estimated action value Q[i]=r[i]/k[i] for each action;
float p[NACTIONS]; // selection probability for each action (softmax);
float sumR; // total reward over time sumR(t)
float avrR; // average reward over time avrR(t) = sumR(t)/t
float _sumR[NSTEPS][NREPLICAS];
float _avrR[NSTEPS][NREPLICAS];
float sumRm[NSTEPS]; // mean values of sumR(t)
float sumRv[NSTEPS]; // corresponding variances
float avrRm[NSTEPS]; // mean values of avrR(t)
float avrRv[NSTEPS]; // corresponding variances
char * par_file_name = "d:\\temp2\\lab3.parameters.dat";
FILE * par_file;
char * RA_res_file_name = "d:\\temp2\\lab3.RA.results.dat";
FILE * RA_res_file;
char * PA_res_file_name = "d:\\temp2\\lab3.PA.results.dat";
FILE * PA_res_file;
char * RL_res_file_name = "d:\\temp2\\lab3.RL.results.dat";
FILE * RL_res_file;
int uRand (int x)
{
int _rnum = (int) ((float)x * (float)rand() / (float)RAND_MAX);
return _rnum;
}
int dRand (float* _array, int size)
{
int _rnum = size-1;
float _left = 0;
float _right = _array[0];
float ftmp = (float)rand() / (float)RAND_MAX;
for (int i=0; i < size-1; i++)
{
if ((ftmp >= _left) && (ftmp < _right)) {_rnum = i; break;}
_left = _right;
_right += _array[i+1];
}
return _rnum;
}
void seInit (void)
{
for (int i=0; i < nA; i++)
sePa[i] = (float)rand() / (float)RAND_MAX;
int seResponse (void)
{
int _r;
float rnum = (float)rand() / (float)RAND_MAX;
if (rnum < sePa[action]) _r = REWARD;
else _r = PENALTY;
return _r;
}
void ceInit (void)
{
int i,j;
float _sum1, _sum2;
// probabilities of rewards
for (i=0; i < nS; i++)
for (j=0; j < nA; j++)
cePa[i][j] = (float)rand() / (float)RAND_MAX;
// probabilities of state transition
for (i=0; i < nS; i++)
{
_sum1 = 0;
_sum2 = 0;
for (j=0; j < nS; j++)
{
cePs[i][j] = (float)rand() / (float)RAND_MAX;
_sum1 += cePs[i][j];
}
for (j=0; j < nS-1; j++)
{
cePs[i][j] = cePs[i][j] / _sum1;
_sum2 += cePs[i][j];
}
cePs[i][nS-1] = 1.0f - _sum2;
}
// initial state
ceState = uRand(nS);
}
int ceResponse (void)
{
int _r;
// get response in current state
float rnum = (float)rand() / (float)RAND_MAX;
if (rnum < cePa[ceState][action]) _r = REWARD;
else _r = PENALTY;
// commutate states
ceState = dRand(cePs[ceState],nS);
return _r;
}
int environment (int _en)
{
int _r = 0;
switch (_en)
{
case 0: _r = seResponse(); break;
case 1: _r = ceResponse(); break;
default: printf("lab3 error: wrong env code specified\n");
}
return _r;
}
void saveParameters (void)
{
int i,j;
if ((par_file = fopen(par_file_name,"w")) == NULL) {
fprintf(stderr, "Cannot open file <%s> for parameters of experiment.\n", par_file_name);
}
fprintf(par_file,"T = %d\n", T);
fprintf(par_file,"n = %d\n", n);
fprintf(par_file,"env = %d\n", env);
fprintf(par_file,"nA = %d\n", nA);
if (env) fprintf(par_file,"nS = %d\n", nS);
fprintf(par_file,"RL-agent type = %d\n", RLTYPE);
if (agt==3) fprintf(par_file,"epsilon = %f\n", e);
if (agt==4) fprintf(par_file,"tau = %f\n", tau);
fprintf(par_file,"====================\n");
switch (env)
{
case 0: // se (stationary environment)
for (i=0; i < nA; i++)
fprintf(par_file,"p(a%d) = %f\n", i, sePa[i]);
break;
case 1: // ce (commutative environment)
// probabilities of rewards
for (i=0; i < nS; i++)
{
for (j=0; j < nA; j++)
fprintf(par_file,"p(s%d,a%d) = %f\n", i, j, cePa[i][j]);
if (i < nS-1) fprintf(par_file,"--------------------\n");
}
fprintf(par_file,"\n====================\n");
// probabilities of state transition
for (i=0; i < nS; i++)
{
for (j=0; j < nS; j++)
fprintf(par_file,"p(s%d,s%d) = %f\n", i, j, cePs[i][j]);
fprintf(par_file,"--------------------\n");
}
break;
default: printf("lab3 error: wrong env model code specified\n");
}
fclose(par_file);
}
void saveResultsRA (void)
{
int i;
if ((RA_res_file = fopen(RA_res_file_name,"w")) == NULL)
fprintf(stderr, "Cannot open file <%s> for experimental results.\n", RA_res_file_name);
for (i=0; i < T; i++)
fprintf(RA_res_file,"%f,%f,%f,%f\n", sumRm[i], sumRv[i], avrRm[i], avrRv[i]);
fclose(RA_res_file);
}
void saveResultsPA (void)
{
int i;
if ((PA_res_file = fopen(PA_res_file_name,"w")) == NULL)
fprintf(stderr, "Cannot open file <%s> for experimental results.\n", PA_res_file_name);
for (i=0; i < T; i++)
fprintf(PA_res_file,"%f,%f,%f,%f\n", sumRm[i], sumRv[i], avrRm[i], avrRv[i]);
fclose(PA_res_file);
}
void saveResultsRL (void)
{
int i;
if ((RL_res_file = fopen(RL_res_file_name,"w")) == NULL)
fprintf(stderr, "Cannot open file <%s> for experimental results.\n", RL_res_file_name);
for (i=0; i < T; i++)
fprintf(RL_res_file,"%f,%f,%f,%f\n", sumRm[i], sumRv[i], avrRm[i], avrRv[i]);
fclose(RL_res_file);
}
int argmax(float* _array, int size)
{
int _arg = uRand(size);
float _max = _array[_arg];
for (int i=0; i < size; i++)
if (_array[i] > _max) {_max = _array[i]; _arg = i;}
return _arg;
}
void initAgent (int _ag)
{
int i;
switch (_ag)
{
case 0: break;
case 1: break;
case 2: for(i=0;i<nA;i++){k[i]=0; r[i]=0; Q[i]=1.0f;}; action = uRand(nA); break;
case 3: for(i=0;i<nA;i++){k[i]=0; r[i]=0; Q[i]=1.0f;}; action = uRand(nA); break;
case 4: for(i=0;i<nA;i++){k[i]=0; r[i]=0; Q[i]=0.0f; p[i]=0.0f;}; action = uRand(nA); break;
default: printf("lab3 error: wrong agent code specified\n");
}
}
int randomAgent (void)
{
return uRand(nA);
}
int perfectAgent (void)
{
if (env) paction = argmax(cePa[ceState],nA);
else paction = argmax(sePa,nA);
return paction;
}
int greedy (void)
{
int _action = action;
// modify estimated action value
r[action] += response;
k[action]++;
Q[action] = (float)r[action] / (float)k[action];
// select next action
_action = argmax(Q,nA);
return _action;
}
int epsilonGreedy (void)
{
int _action = action;
// modify estimated action value
r[action] += response;
k[action]++;
Q[action] = (float)r[action] / (float)k[action];
// select next action
float rnum = (float)rand() / (float)RAND_MAX;
if (rnum < e) _action = uRand(nA);
else _action = argmax(Q,nA);
return _action;
}
int softmax (void)
{
int i;
int _action = action;
float tmp[NACTIONS], pSum = 0.0f;
// modify estimated action value
r[action] += response;
k[action]++;
Q[action] = (float)r[action] / (float)k[action];
// modify values of selection probabilities
for (i=0; i < nA; i++) {tmp[i] = expf(Q[i]/tau); pSum += tmp[i];}
for (i=0; i < nA; i++) {p[i] = tmp[i]/pSum;}
// select next action
_action = dRand(p,nA);
return _action;
}
int agent (int _ag)
{
int _a = 0;
switch (_ag)
{
case 0: _a = randomAgent(); break;
case 1: _a = perfectAgent(); break;
case 2: _a = greedy(); break;
case 3: _a = epsilonGreedy(); break;
case 4: _a = softmax(); break;
default: printf("lab3 error: wrong agent code specified\n");
}
return _a;
}
void simulation (int _i)
{
initAgent(agt);
sumR = 0.0f;
avrR = 0.0f;
for (t=0; t < T; t++) {
// get action of agent
action = agent(agt);
// get response of environment
response = environment(env);
// calculate cumulative results
sumR = sumR + (float)response;
avrR = sumR / ((float)t + 1);
// save results
_sumR[t][_i] = sumR;
_avrR[t][_i] = avrR;
}
}
void getMeanValues (void)
{
for (t=0; t < T; t++)
{
float tmps1 = 0.0f;
float tmps2 = 0.0f;
for (int i=0; i < n; i++)
{
tmps1 += _sumR[t][i];
tmps2 += _avrR[t][i];
}
sumRm[t] = (float)tmps1 / (float)n;
avrRm[t] = (float)tmps2 / (float)n;
}
}
void getVarianceValues (void)
{
for (t=0; t < T; t++)
{
float tmps1 = 0.0f;
float tmps2 = 0.0f;
for (int i=0; i < n; i++)
{
tmps1 += (sumRm[t] - _sumR[t][i]) * (sumRm[t] - _sumR[t][i]);
tmps2 += (avrRm[t] - _avrR[t][i]) * (avrRm[t] - _avrR[t][i]);
}
sumRv[t] = (float)tmps1 / (float)(n-1);
avrRv[t] = (float)tmps2 / (float)(n-1);
}
}
int main(int argc, char* argv[])
{
int i;
// init random-number generator
srand((unsigned)time(NULL));
// init environment
if (env == 0) seInit();
else ceInit();
// save parameters of experiment
saveParameters();
// run experiment for random agent
agt = 0;
for (i=0; i < n; i++) simulation(i);
getMeanValues();
getVarianceValues();
saveResultsRA();
// run experiment for perfect agent
agt = 1;
for (i=0; i < n; i++) simulation(i);
getMeanValues();
getVarianceValues();
saveResultsPA();
// run experiment for RL-agent
agt = RLTYPE;
for (i=0; i < n; i++) simulation(i);
getMeanValues();
getVarianceValues();
saveResultsRL();
return 0;
}
3. Результати виконання програми:
/
Рис.1. Параметри експерименту.
/
Рис.2. Порівняння
Висновок: виконавши дану лабораторну роботу, я змоделював та дослідив роботу методів та алгоритмів навчання з підкріпленням, набув навичок їх реалізації.