VC#2010で強化学習のプログラムを作ろうと考えているのですが、
実行すると「NullReferenceExceptionはハンドルされませんでした。
オブジェクト参照がオブジェクト インスタンスに設定されていません。」
というエラーが出てプログラムが動きません。
ソースは
static public Random rnd;
static void Main(string[] args)
{
double[][] Qtable; //Qtable
double Q_max = 0;//Q値の最大値
double reward = 0; //報酬
double alpha = 0.5;//学習係数
double gamma = 0.9;//減衰係数
int epsilon = 10;//行動を無作為に選ぶ確率[%]
int trial_max = 100;//試行回数
int num_a = 2;//行動の数
int num_s = 2;//状態の数
int a = 0;//行動
int s = 0;//状態
int sd = 0;//行動の実行によって遷移する状態
int i, j;
//メモリー空間の確保
Qtable = new double [num_s][];
for (i = 0; i < num_s; i++)
{
Qtable[i] = new double[num_a];
}
//Q値の初期化
for (i = 0; i < num_s; i++)
{
for (j = 0; j < num_a; j++)
{
Qtable[i][j] = 0;
Console.WriteLine("Q[{0}][{1}]={2}\n", i, j, Qtable[i][j]);
}
}
//試行開始
for (i = 0; i < trial_max; i++)
{
//行動の選択
a = epsilon_greedy(epsilon, s, num_a, Qtable);
a = 1;
//行動の実行
reward = vending_machine(s, a, sd);
//sdにおけるQ値の最大値を求める
Q_max = max_Qval(sd, num_a, Qtable);
//Q値の更新
Qtable[s][a] = (1 - alpha) * Qtable[s][a] + alpha * (reward + gamma * Q_max);
s = sd;
Console.WriteLine("i={0}\n", i);
if (reward > 0)
{
Console.WriteLine("成功\n", a);
}
if (reward == 0)
{
Console.WriteLine("失敗\n", a);
}
}
//Qtableの表示
for (i = 0; i < num_s; i++)
{
for (j = 0; j < num_a; j++)
{
Console.WriteLine("{0} ", Qtable[i][j]);
}
Console.Write("\n");
}
return;
}
static double vending_machine(int s, int a, int sd)
{
double reward;
if (a == 0)
{
if (s == 0)
sd = 1;
if (s == 1)
sd = 0;
reward = 0;
}
else
{
if (s == 1)
{
sd = s;
reward = 10;
}
else
{
sd = s;
reward = 0;
}
}
return reward;
}
static double max_Qval(int s, int num_a, double [][] Qtable)
{
double max;
int i = 0;
max = Qtable[s][0];
for (i = 1; i < num_a; i++)
{
if (Qtable[s][i] > max)
{
max = Qtable[s][i];
}
}
return max;
}
static int select_action(int s, int num_a, double [][] Qtable)
{
double max;
int i = 0;
int[] i_max;
i_max = new int[num_a];
int num_i_max = 1;
int a;
i_max[0] = 0;
max = Qtable[s][0];
for (i = 1; i < num_a; i++)
{
if (Qtable[s][i] > max)
{
max = Qtable[s][i];
num_i_max=1;
i_max[0]=i;
}
else if (Qtable[s][i] == max)
{
num_i_max++;
i_max[num_i_max - 1] = i;
}
}
int seed = Environment.TickCount;
rnd = new Random(seed++);
a = i_max[rnd.Next(num_i_max)];
return a;
}
static int epsilon_greedy(int epsilon, int s, int num_a, double [][] Qtable)
{
int a;
if (epsilon > rnd.Next(100))
{
//無作為に行動を選択
a = rnd.Next(num_a);
}
else
{
//最大のQ値を持つ行動を選択
a = select_action(s, num_a, Qtable);
}
return a;
}
のような感じです。
どなたか分かる方がいれば、教えていただけるとありがたいです。
よろしくお願いします。
お礼
回答ありがとうございました。 丁寧な解説をいただいたおかげで、無事に解決いたしました。