Skip to content

Commit

Permalink
KK,KKPのinverseの計算、間違ってたような気がするので修正した。(気がする)
Browse files Browse the repository at this point in the history
EvalLearningTools::KPPP半分ぐらい書いた。
  • Loading branch information
yaneurao committed Sep 1, 2017
1 parent b143751 commit 4badf2c
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 39 deletions.
13 changes: 2 additions & 11 deletions source/Makefile
Expand Up @@ -70,17 +70,8 @@ LDFLAGS += -Wl,-s

# OpenMPを使うときにCFLAGSとして指定するオプション
# ※ 学習部ではOpenMpを用いるので、学習用のビルドではこのオプションを指定する。
# あと、clangでは、gccのincludeフォルダにあるomp.hを
# pathの通っているところに配置しないといけないようだ。
# 例) ln -s /mingw64/lib/gcc/x86_64-w64-mingw32/7.2.0/include/omp.h omp.h
# → clangでコンパイルしたとき、OpenMPがプリプロセッサで有効になっていないようだ。[調査中]

ifeq ($(findstring g++,$(COMPILER)),g++)
OPENMP = -fopenmp
endif
ifeq ($(findstring clang++,$(COMPILER)),clang++)
OPENMP = -fopenmp=libgomp
endif
# clangでコンパイルする方法は調査中。
OPENMP = -fopenmp

CFLAGS += -DNO_EXCEPTIONS
LDFLAGS += -lpthread
Expand Down
22 changes: 12 additions & 10 deletions source/eval/evaluate_kpp_kkpt.cpp
@@ -1,6 +1,6 @@
#include "../shogi.h"

// KPP+KPPTの実験用コード
// KPP+KKPTの実験用コード
// ほとんどevaluate_kppt.cppと同じ。

#if defined (EVAL_KPP_KKPT)
Expand Down Expand Up @@ -192,8 +192,8 @@ namespace Eval
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cv;
cv.from_bytes(dir_name).c_str();

auto mapped_file_name = TEXT("YANEURAOU_KPP_PPT_MMF" ENGINE_VERSION) + cv.from_bytes(dir_name);
auto mutex_name = TEXT("YANEURAOU_KPP_PPT_MUTEX" ENGINE_VERSION) + cv.from_bytes(dir_name);
auto mapped_file_name = TEXT("YANEURAOU_KPP_KKPT_MMF" ENGINE_VERSION) + cv.from_bytes(dir_name);
auto mutex_name = TEXT("YANEURAOU_KPP_KKPT_MUTEX" ENGINE_VERSION) + cv.from_bytes(dir_name);

// プロセス間の排他用mutex
auto hMutex = CreateMutex(NULL, FALSE, mutex_name.c_str());
Expand Down Expand Up @@ -638,7 +638,8 @@ namespace Eval
}

for (; j < i; ++j) {
diff.p[1][0] += pkppw[list1[j]];
const int l1 = list1[j];
diff.p[1][0] += pkppw[l1];
}

// KKPのWK分。BKは移動していないから、BK側には影響ない。
Expand Down Expand Up @@ -730,7 +731,8 @@ namespace Eval
}

for (; j < i; ++j) {
diff.p[0][0] += pkppb[list0[j]];
const int l0 = list0[j];
diff.p[0][0] += pkppb[l0];
}

diff.p[2] += kkp[sq_bk][sq_wk][k0];
Expand Down Expand Up @@ -1072,11 +1074,11 @@ namespace Eval
l0 = list_fb[j];
l1 = list_fw[j];

sum.p[0][0] += pkppb[l0];
sum.p[1][0] += pkppw[l1];

cout << "BKPP : " << sq_bk << " " << k0 << " " << l0 << " = " << pkppb[l0] << endl;
cout << "WKPP : " << sq_wk << " " << k1 << " " << l1 << " = " << pkppw[l1] << endl;

sum.p[0][0] += pkppb[l0];
sum.p[1][0] += pkppw[l1];
}
sum.p[2] += kkp[sq_bk][sq_wk][k0];

Expand Down Expand Up @@ -1190,10 +1192,10 @@ namespace Eval
// パラメーターの分析などに用いる。
void foreach_eval_param(std::function<void(s32, s32)>f, int type)
{
// PP
// KK
if (type == -1 || type == 0)
{
for (u64 i = 0; i < (u64)fe_end * (u64)fe_end; ++i)
for (u64 i = 0; i < (u64)SQ_NB * (u64)SQ_NB; ++i)
{
auto v = ((ValueKk*)kk)[i];
f(v[0], v[1]);
Expand Down
6 changes: 5 additions & 1 deletion source/eval/evaluate_kppt.cpp
Expand Up @@ -273,7 +273,7 @@ namespace Eval
if (shared_eval_ptr == nullptr)
{
sync_cout << "info string can't allocate shared eval memory." << sync_endl;
exit(1);
my_exit();
}
else
{
Expand Down Expand Up @@ -393,6 +393,7 @@ namespace Eval
l0 = list_fb[j];
l1 = list_fw[j];

// KPP
#if defined(USE_SSE41)
// SSEによる実装

Expand All @@ -407,6 +408,8 @@ namespace Eval
sum.p[1] += pkppw[l1];
#endif
}

// KKP
sum.p[2] += kkp[sq_bk][sq_wk][k0];
}

Expand Down Expand Up @@ -477,6 +480,7 @@ namespace Eval
sum.p[0] = { 0, 0 };
sum.p[1] = { 0, 0 };
#endif
// KK
sum.p[2] = kkp[sq_bk][sq_wk][ebp.fb];

const auto* pkppb = kpp[sq_bk ][ebp.fb];
Expand Down
19 changes: 10 additions & 9 deletions source/learn/evaluate_learn_kpp_kkpt.cpp
Expand Up @@ -221,9 +221,10 @@ namespace Eval
// それに基いてvの更新を行い、そのvをlowerDimensionsそれぞれに書き出す。
// ids[0]==ids[1]==ids[2]==ids[3]みたいな可能性があるので、gは外部で合計する。
array<LearnFloatType, 2> g_sum = zero_t;
for (int i = 0; i <KK_LOWER_COUNT; ++i)
// inverseした次元下げに関しては符号が逆になる。
g_sum += (!a[i].is_inverse()) ? weights[ids[i]].get_grad() : -weights[ids[i]].get_grad();

// inverseした次元下げに関しては符号が逆になるのでadjust_grad()を経由して計算する。
for (int i = 0; i < KK_LOWER_COUNT; ++i)
g_sum += a[i].adjust_grad(weights[ids[i]].get_grad());

// 次元下げを考慮して、その勾配の合計が0であるなら、一切の更新をする必要はない。
if (is_zero(g_sum))
Expand All @@ -233,9 +234,9 @@ namespace Eval
weights[ids[0]].set_grad(g_sum);
weights[ids[0]].updateFV(v);

for (int i = 1; i< KK_LOWER_COUNT; ++i)
kk[a[i].king0()][a[i].king1()] = (!a[i].is_inverse()) ? v : -v;

for (int i = 1; i < KK_LOWER_COUNT; ++i)
kk[a[i].king0()][a[i].king1()] = a[i].adjust_grad(v);
// mirrorした場所が同じindexである可能性があるので、gのクリアはこのタイミングで行なう。
// この場合、毎回gを通常の2倍加算していることになるが、AdaGradは適応型なのでこれでもうまく学習できる。
for (auto id : ids)
Expand All @@ -257,7 +258,7 @@ namespace Eval

array<LearnFloatType, 2> g_sum = zero_t;
for (int i = 0; i <KKP_LOWER_COUNT; ++i)
g_sum += (!a[i].is_inverse()) ? weights[ids[i]].get_grad() : -weights[ids[i]].get_grad();
g_sum += a[i].adjust_grad(weights[ids[i]].get_grad());

if (is_zero(g_sum))
continue;
Expand All @@ -267,8 +268,8 @@ namespace Eval
weights[ids[0]].updateFV(v);

for (int i = 1; i < KKP_LOWER_COUNT; ++i)
kkp[a[i].king0()][a[i].king1()][a[i].piece()] = (!a[i].is_inverse()) ? v : -v;

kkp[a[i].king0()][a[i].king1()][a[i].piece()] = a[i].adjust_grad(v);
for (auto id : ids)
weights[id].set_grad(zero_t);

Expand Down
17 changes: 9 additions & 8 deletions source/learn/evaluate_learn_kppt.cpp
Expand Up @@ -213,9 +213,10 @@ namespace Eval
// それに基いてvの更新を行い、そのvをlowerDimensionsそれぞれに書き出す。
// ids[0]==ids[1]==ids[2]==ids[3]みたいな可能性があるので、gは外部で合計する。
array<LearnFloatType, 2> g_sum = zero_t;

// inverseした次元下げに関しては符号が逆になるのでadjust_grad()を経由して計算する。
for (int i = 0; i <KK_LOWER_COUNT; ++i)
// inverseした次元下げに関しては符号が逆になる。
g_sum += (!a[i].is_inverse()) ? weights[ids[i]].get_grad() : -weights[ids[i]].get_grad();
g_sum += a[i].adjust_grad(weights[ids[i]].get_grad());

// 次元下げを考慮して、その勾配の合計が0であるなら、一切の更新をする必要はない。
if (is_zero(g_sum))
Expand All @@ -226,8 +227,8 @@ namespace Eval
weights[ids[0]].updateFV(v);

for (int i = 1; i< KK_LOWER_COUNT; ++i)
kk[a[i].king0()][a[i].king1()] = (!a[i].is_inverse()) ? v : -v;

kk[a[i].king0()][a[i].king1()] = a[i].adjust_grad(v);
// mirrorした場所が同じindexである可能性があるので、gのクリアはこのタイミングで行なう。
// この場合、毎回gを通常の2倍加算していることになるが、AdaGradは適応型なのでこれでもうまく学習できる。
for (auto id : ids)
Expand All @@ -249,8 +250,8 @@ namespace Eval

array<LearnFloatType, 2> g_sum = zero_t;
for (int i = 0; i <KKP_LOWER_COUNT; ++i)
g_sum += (!a[i].is_inverse()) ? weights[ids[i]].get_grad() : -weights[ids[i]].get_grad();

g_sum += a[i].adjust_grad(weights[ids[i]].get_grad());
if (is_zero(g_sum))
continue;

Expand All @@ -259,8 +260,8 @@ namespace Eval
weights[ids[0]].updateFV(v);

for (int i = 1; i < KKP_LOWER_COUNT; ++i)
kkp[a[i].king0()][a[i].king1()][a[i].piece()] = (!a[i].is_inverse()) ? v : -v;

kkp[a[i].king0()][a[i].king1()][a[i].piece()] = a[i].adjust_grad(v);
for (auto id : ids)
weights[id].set_grad(zero_t);

Expand Down
4 changes: 4 additions & 0 deletions source/learn/learn.h
Expand Up @@ -159,6 +159,10 @@ typedef float LearnFloatType;
// KPPにはインバースはない。(先手側のKしかないので)
#define USE_KPP_MIRROR_WRITE

// KPPPに対してミラーを利用した次元下げを行なう。(これをオフにすると教師局面が倍ぐらい必要になる)
// KPPPにもインバースはない。(先手側のKしかないので)
#define USE_KPPP_MIRROR_WRITE


// ======================
// 教師局面生成時の設定
Expand Down
2 changes: 2 additions & 0 deletions source/learn/learner.cpp
Expand Up @@ -1443,6 +1443,8 @@ void LearnerThink::calc_loss(size_t thread_id, u64 done)
pos.set_hirate(th);
std::cout << "hirate eval = " << Eval::evaluate(pos);

//Eval::print_eval_stat(pos);

// ここ、並列化したほうが良いのだがslaveの前の探索が終わってなかったりしてちょっと面倒。
// taskを呼び出すための仕組みを作ったのでそれを用いる。

Expand Down

0 comments on commit 4badf2c

Please sign in to comment.