Я реализую проблему бандита, используя различные алгоритмы. Проблема, с которой я сталкиваюсь, заключается в том, что эпсилон-жадный работает лучше, чем UCB, для 5 армов и горизонта 2000 года для значения эпсилона 0,95.
Я осознаю тот факт, что эпсилон-жадный действительно лучше работает, когда горизонт сопоставим с количеством оружия.
Но так как мои руки значительно меньше горизонта, UCB должен работать лучше. Есть идеи, почему это происходит?
Я прилагаю свою реализацию UCB.
else if(algorithm.compare("UCB") == 0){
if(pulls == 0){
armpullfrequency = new int[numArms];
armRewards = new float[numArms];
armmean = new double[numArms];
UCB = new double[numArms];
for(int i=0; i<numArms; i++){
armpullfrequency[i] = 0;
armRewards[i] = 0.0;
armmean[i] = (double)0;
UCB[i] = (double)0;
}
}
else{
armpullfrequency[pulled_arm] = armpullfrequency[pulled_arm] + 1;
armRewards[pulled_arm] = armRewards[pulled_arm] + reward;
}
int selected_arm = 0;
//int randint = (rand() % 100);
if(pulls<=6){
for(int i=0;i<numArms;i++){
if(armpullfrequency[i]==0){
selected_arm = i;
return selected_arm;
}
}
}
for(int i=0;i<numArms;i++){
int freq = armpullfrequency[i];
float prize = armRewards[i];
double mean = eval_mean(freq, prize);
armmean[i] = mean;
}
for(int i=0; i<numArms;i++){
int freq = armpullfrequency[i];
double mean = armmean[i];
double UCBval = UCBUpdate(mean, freq, pulls);
UCB[i] = UCBval;
}
selected_arm = LargestElementIndex(UCB, numArms);
return(selected_arm);
Моя функция UCB и LargestElementIndex: —
int LargestElementIndex(double arr[], int size){
int max = 0;
for(int i=0;i<size; i++){
if(arr[i]>max){
max = arr[i];
}
}
return max;
}
int UCBUpdate(double mean, int freq, int pulls){
double result = mean + sqrt((double)2.0 *(log(pulls))/(double)freq);
return result;
}
Результаты в случае UCB это: —
maxMean 0.5805 numTotalPulls 2000 cumulativeReward 716.308
Сожаление = 444,692
Результаты в случае с Epsilon Greedy:
макс означает 0,5805 numTotalPulls 2000 кумулятивное вознаграждение 823,948
Сожаление = 337,052
Я подозреваю, что ошибка в следующем коде:
int LargestElementIndex(double arr[], int size){
int max = 0;
for(int i=0;i<size; i++){
if(arr[i]>max){
max = arr[i];
}
}
return max;
}
Это не возвращает индекс руки с наибольшим значением UCB (что, вероятно, то, что вы хотели). Этот код просто возвращает наибольшее значение UCB в самом массиве, после приведения его к int
, Вероятно, это можно исправить следующим образом:
int LargestElementIndex(double arr[], int size){
double max_val = -1000.0;
int max_idx = -1;
for(int i=0;i<size; i++){
if(arr[i]>max_val){
max_val = arr[i];
max_idx = i;
}
}
return max_idx;
}
Других решений пока нет …