mirror of
https://github.com/HChaZZY/Stockfish.git
synced 2025-12-25 19:46:55 +08:00
Translation
Files in /eval, /extra, & /learn - comments translated from Japanese to English
This commit is contained in:
@@ -1,75 +1,75 @@
|
||||
#ifndef _EVALUATE_COMMON_H_
|
||||
#define _EVALUATE_COMMON_H_
|
||||
|
||||
// いまどきの手番つき評価関数(EVAL_KPPTとEVAL_KPP_KKPT)の共用header的なもの。
|
||||
// A common header-like function for modern evaluation functions (EVAL_KPPT and EVAL_KPP_KKPT).
|
||||
|
||||
#if defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
||||
#include <functional>
|
||||
|
||||
// KKファイル名
|
||||
// KK file name
|
||||
#define KK_BIN "KK_synthesized.bin"
|
||||
|
||||
// KKPファイル名
|
||||
// KKP file name
|
||||
#define KKP_BIN "KKP_synthesized.bin"
|
||||
|
||||
// KPPファイル名
|
||||
// KPP file name
|
||||
#define KPP_BIN "KPP_synthesized.bin"
|
||||
|
||||
namespace Eval
|
||||
{
|
||||
|
||||
#if defined(USE_EVAL_HASH)
|
||||
// prefetchする関数
|
||||
// prefetch function
|
||||
void prefetch_evalhash(const Key key);
|
||||
#endif
|
||||
|
||||
// 評価関数のそれぞれのパラメーターに対して関数fを適用してくれるoperator。
|
||||
// パラメーターの分析などに用いる。
|
||||
// typeは調査対象を表す。
|
||||
// type = -1 : KK,KKP,KPPすべて
|
||||
// type = 0 : KK のみ
|
||||
// type = 1 : KKPのみ
|
||||
// type = 2 : KPPのみ
|
||||
// An operator that applies the function f to each parameter of the evaluation function.
|
||||
// Used for parameter analysis etc.
|
||||
// type indicates the survey target.
|
||||
// type = -1 :KK,KKP,KPP all
|
||||
// type = 0: KK only
|
||||
// type = 1: KKP only
|
||||
// type = 2: KPP only
|
||||
void foreach_eval_param(std::function<void(int32_t, int32_t)>f, int type = -1);
|
||||
|
||||
// --------------------------
|
||||
// 学習用
|
||||
// for learning
|
||||
// --------------------------
|
||||
|
||||
#if defined(EVAL_LEARN)
|
||||
// 学習のときの勾配配列の初期化
|
||||
// 学習率を引数に渡しておく。0.0なら、defaultの値を採用する。
|
||||
// update_weights()のepochが、eta_epochまでetaから徐々にeta2に変化する。
|
||||
// eta2_epoch以降は、eta2から徐々にeta3に変化する。
|
||||
// Initialize the gradient array during learning
|
||||
// Pass the learning rate as an argument. If 0.0, the default value is used.
|
||||
// The epoch of update_weights() gradually changes from eta to eta2 until eta_epoch.
|
||||
// After eta2_epoch, gradually change from eta2 to eta3.
|
||||
void init_grad(double eta1, uint64_t eta_epoch, double eta2, uint64_t eta2_epoch, double eta3);
|
||||
|
||||
// 現在の局面で出現している特徴すべてに対して、勾配の差分値を勾配配列に加算する。
|
||||
// freeze[0] : kkは学習させないフラグ
|
||||
// freeze[1] : kkpは学習させないフラグ
|
||||
// freeze[2] : kppは学習させないフラグ
|
||||
// freeze[3] : kpppは学習させないフラグ
|
||||
// Add the gradient difference value to the gradient array for all features that appear in the current phase.
|
||||
// freeze[0]: Flag that kk does not learn
|
||||
// freeze[1]: Flag that kkp does not learn
|
||||
// freeze[2]: Flag that kpp does not learn
|
||||
// freeze[3]: Flag that kppp does not learn
|
||||
void add_grad(Position& pos, Color rootColor, double delt_grad, const std::array<bool, 4>& freeze);
|
||||
|
||||
// 現在の勾配をもとにSGDかAdaGradか何かする。
|
||||
// epoch : 世代カウンター(0から始まる)
|
||||
// freeze[0] : kkは学習させないフラグ
|
||||
// freeze[1] : kkpは学習させないフラグ
|
||||
// freeze[2] : kppは学習させないフラグ
|
||||
// freeze[3] : kpppは学習させないフラグ
|
||||
void update_weights(uint64_t epoch, const std::array<bool,4>& freeze);
|
||||
// Do SGD or AdaGrad or something based on the current gradient.
|
||||
// epoch: Generation counter (starting from 0)
|
||||
// freeze[0]: Flag that kk does not learn
|
||||
// freeze[1]: Flag that kkp does not learn
|
||||
// freeze[2]: Flag that kpp does not learn
|
||||
// freeze[3]: Flag that kppp does not learn
|
||||
void update_weights(uint64_t epoch, const std::array<bool, 4>& freeze);
|
||||
|
||||
// 評価関数パラメーターをファイルに保存する。
|
||||
// ファイルの末尾につける拡張子を指定できる。
|
||||
// Save the evaluation function parameters to a file.
|
||||
// You can specify the extension added to the end of the file.
|
||||
void save_eval(std::string suffix);
|
||||
|
||||
// 現在のetaを取得する。
|
||||
// Get the current eta.
|
||||
double get_eta();
|
||||
|
||||
// -- 学習に関連したコマンド
|
||||
// --learning related commands
|
||||
|
||||
// KKを正規化する関数。元の評価関数と完全に等価にはならないので注意。
|
||||
// kkp,kppの値をなるべくゼロに近づけることで、学習中に出現しなかった特徴因子の値(ゼロになっている)が
|
||||
// 妥当であることを保証しようという考え。
|
||||
// A function that normalizes KK. Note that it is not completely equivalent to the original evaluation function.
|
||||
// By making the values of kkp and kpp as close to zero as possible, the value of the feature factor (which is zero) that did not appear during learning
|
||||
// The idea of ensuring it is valid.
|
||||
void regularize_kk();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,35 +7,35 @@ namespace Eval
|
||||
|
||||
// --- tables
|
||||
|
||||
// あるBonaPieceを相手側から見たときの値
|
||||
// BONA_PIECE_INITが-1なので符号型で持つ必要がある。
|
||||
// KPPTを拡張しても当面、BonaPieceが2^15を超えることはないのでint16_tで良しとする。
|
||||
// Value when a certain BonaPiece is seen from the other side
|
||||
// BONA_PIECE_INIT is -1, so it must be a signed type.
|
||||
// Even if KPPT is expanded, BonaPiece will not exceed 2^15 for the time being, so int16_t is good.
|
||||
int16_t inv_piece_[Eval::fe_end];
|
||||
|
||||
// 盤面上のあるBonaPieceをミラーした位置にあるものを返す。
|
||||
// Returns the one at the position where a BonaPiece on the board is mirrored.
|
||||
int16_t mir_piece_[Eval::fe_end];
|
||||
|
||||
|
||||
// --- methods
|
||||
|
||||
// あるBonaPieceを相手側から見たときの値を返す
|
||||
// Returns the value when a certain BonaPiece is seen from the other side
|
||||
Eval::BonaPiece inv_piece(Eval::BonaPiece p) { return (Eval::BonaPiece)inv_piece_[p]; }
|
||||
|
||||
// 盤面上のあるBonaPieceをミラーした位置にあるものを返す。
|
||||
// Returns the one at the position where a BonaPiece on the board is mirrored.
|
||||
Eval::BonaPiece mir_piece(Eval::BonaPiece p) { return (Eval::BonaPiece)mir_piece_[p]; }
|
||||
|
||||
std::function<void()> mir_piece_init_function;
|
||||
|
||||
void init_mir_inv_tables()
|
||||
{
|
||||
// mirrorとinverseのテーブルの初期化。
|
||||
// Initialize the mirror and inverse tables.
|
||||
|
||||
// 初期化は1回に限る。
|
||||
// Initialization is limited to once.
|
||||
static bool first = true;
|
||||
if (!first) return;
|
||||
first = false;
|
||||
|
||||
// fとeとの交換
|
||||
// exchange f and e
|
||||
int t[] = {
|
||||
f_pawn , e_pawn ,
|
||||
f_knight , e_knight ,
|
||||
@@ -44,12 +44,12 @@ namespace Eval
|
||||
f_queen , e_queen ,
|
||||
};
|
||||
|
||||
// 未初期化の値を突っ込んでおく。
|
||||
// Insert uninitialized value.
|
||||
for (BonaPiece p = BONA_PIECE_ZERO; p < fe_end; ++p)
|
||||
{
|
||||
inv_piece_[p] = BONA_PIECE_NOT_INIT;
|
||||
|
||||
// mirrorは手駒に対しては機能しない。元の値を返すだけ。
|
||||
// mirror does not work for hand pieces. Just return the original value.
|
||||
mir_piece_[p] = (p < f_pawn) ? p : BONA_PIECE_NOT_INIT;
|
||||
}
|
||||
|
||||
@@ -61,26 +61,26 @@ namespace Eval
|
||||
{
|
||||
Square sq = (Square)(p - t[i]);
|
||||
|
||||
// 見つかった!!
|
||||
// found!!
|
||||
BonaPiece q = (p < fe_hand_end) ? BonaPiece(sq + t[i + 1]) : (BonaPiece)(Inv(sq) + t[i + 1]);
|
||||
inv_piece_[p] = q;
|
||||
inv_piece_[q] = p;
|
||||
|
||||
/*
|
||||
ちょっとトリッキーだが、pに関して盤上の駒は
|
||||
p >= fe_hand_end
|
||||
のとき。
|
||||
It's a bit tricky, but regarding p
|
||||
p >= fe_hand_end
|
||||
When.
|
||||
|
||||
このpに対して、nを整数として(上のコードのiは偶数しかとらない)、
|
||||
a) t[2n + 0] <= p < t[2n + 1] のときは先手の駒
|
||||
b) t[2n + 1] <= p < t[2n + 2] のときは後手の駒
|
||||
である。
|
||||
For this p, let n be an integer (i in the above code can only be an even number),
|
||||
a) When t[2n + 0] <= p <t[2n + 1], the first piece
|
||||
b) When t[2n + 1] <= p <t[2n + 2], the back piece
|
||||
Is.
|
||||
|
||||
ゆえに、a)の範囲にあるpをq = Inv(p-t[2n+0]) + t[2n+1] とすると180度回転させた升にある後手の駒となる。
|
||||
そこでpとqをswapさせてinv_piece[ ]を初期化してある。
|
||||
*/
|
||||
Therefore, if p in the range of a) is set to q = Inv(p-t[2n+0]) + t[2n+1], it becomes the back piece in the box rotated 180 degrees.
|
||||
So inv_piece[] is initialized by swapping p and q.
|
||||
*/
|
||||
|
||||
// 手駒に関してはmirrorなど存在しない。
|
||||
// There is no mirror for hand pieces.
|
||||
if (p < fe_hand_end)
|
||||
continue;
|
||||
|
||||
@@ -103,28 +103,28 @@ namespace Eval
|
||||
|
||||
for (BonaPiece p = BONA_PIECE_ZERO; p < fe_end; ++p)
|
||||
{
|
||||
// 未初期化のままになっている。上のテーブルの初期化コードがおかしい。
|
||||
// It remains uninitialized. The initialization code in the table above is incorrect.
|
||||
assert(mir_piece_[p] != BONA_PIECE_NOT_INIT && mir_piece_[p] < fe_end);
|
||||
assert(inv_piece_[p] != BONA_PIECE_NOT_INIT && inv_piece_[p] < fe_end);
|
||||
|
||||
// mirとinvは、2回適用したら元の座標に戻る。
|
||||
// mir and inv return to their original coordinates after being applied twice.
|
||||
assert(mir_piece_[mir_piece_[p]] == p);
|
||||
assert(inv_piece_[inv_piece_[p]] == p);
|
||||
|
||||
// mir->inv->mir->invは元の場所でなければならない。
|
||||
// mir->inv->mir->inv must be the original location.
|
||||
assert(p == inv_piece(mir_piece(inv_piece(mir_piece(p)))));
|
||||
|
||||
// inv->mir->inv->mirは元の場所でなければならない。
|
||||
// inv->mir->inv->mir must be the original location.
|
||||
assert(p == mir_piece(inv_piece(mir_piece(inv_piece(p)))));
|
||||
}
|
||||
|
||||
#if 0
|
||||
// 評価関数のミラーをしても大丈夫であるかの事前検証
|
||||
// 値を書き込んだときにassertionがあるので、ミラーしてダメである場合、
|
||||
// そのassertに引っかかるはず。
|
||||
// Pre-verification that it is okay to mirror the evaluation function
|
||||
// When writing a value, there is an assertion, so if you can't mirror it,
|
||||
// Should get caught in the assert.
|
||||
|
||||
// AperyのWCSC26の評価関数、kppのp1==0とかp1==20(後手の0枚目の歩)とかの
|
||||
// ところにゴミが入っていて、これを回避しないとassertに引っかかる。
|
||||
// Apery's WCSC26 evaluation function, kpp p1==0 or p1==20 (0th step on the back)
|
||||
// There is dust in it, and if you don't avoid it, it will get caught in the assert.
|
||||
|
||||
std::unordered_set<BonaPiece> s;
|
||||
vector<int> a = {
|
||||
@@ -139,24 +139,24 @@ namespace Eval
|
||||
for (auto b : a)
|
||||
s.insert((BonaPiece)b);
|
||||
|
||||
// さらに出現しない升の盤上の歩、香、桂も除外(Aperyはここにもゴミが入っている)
|
||||
// Excludes walks, incense, and katsura on the board that do not appear further (Apery also contains garbage here)
|
||||
for (Rank r = RANK_1; r <= RANK_2; ++r)
|
||||
for (File f = FILE_1; f <= FILE_9; ++f)
|
||||
{
|
||||
if (r == RANK_1)
|
||||
{
|
||||
// 1段目の歩
|
||||
// first step
|
||||
BonaPiece b1 = BonaPiece(f_pawn + (f | r));
|
||||
s.insert(b1);
|
||||
s.insert(inv_piece[b1]);
|
||||
|
||||
// 1段目の香
|
||||
// 1st stage incense
|
||||
BonaPiece b2 = BonaPiece(f_lance + (f | r));
|
||||
s.insert(b2);
|
||||
s.insert(inv_piece[b2]);
|
||||
}
|
||||
|
||||
// 1,2段目の桂
|
||||
// Katsura on the 1st and 2nd steps
|
||||
BonaPiece b = BonaPiece(f_knight + (f | r));
|
||||
s.insert(b);
|
||||
s.insert(inv_piece[b]);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#if defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
||||
|
||||
// BonaPieceのmirror(左右反転)やinverse(盤上の180度回転)させた駒を得るためのツール類。
|
||||
// BonaPiece's mirror (horizontal flip) and inverse (180° on the board) tools to get pieces.
|
||||
|
||||
#include "../types.h"
|
||||
#include "../evaluate.h"
|
||||
@@ -15,33 +15,33 @@ namespace Eval
|
||||
// tables
|
||||
// -------------------------------------------------
|
||||
|
||||
// --- BonaPieceに対してMirrorとInverseを提供する。
|
||||
// --- Provide Mirror and Inverse to BonaPiece.
|
||||
|
||||
// これらの配列は、init()かinit_mir_inv_tables();を呼び出すと初期化される。
|
||||
// このテーブルのみを評価関数のほうから使いたいときは、評価関数の初期化のときに
|
||||
// init_mir_inv_tables()を呼び出すと良い。
|
||||
// これらの配列は、以下のKK/KKP/KPPクラスから参照される。
|
||||
// These arrays are initialized by calling init() or init_mir_inv_tables();.
|
||||
// If you want to use only this table from the evaluation function,
|
||||
// Call init_mir_inv_tables().
|
||||
// These arrays are referenced from the KK/KKP/KPP classes below.
|
||||
|
||||
// あるBonaPieceを相手側から見たときの値を返す
|
||||
// Returns the value when a certain BonaPiece is seen from the other side
|
||||
extern Eval::BonaPiece inv_piece(Eval::BonaPiece p);
|
||||
|
||||
// 盤面上のあるBonaPieceをミラーした位置にあるものを返す。
|
||||
// Returns the one at the position where a BonaPiece on the board is mirrored.
|
||||
extern Eval::BonaPiece mir_piece(Eval::BonaPiece p);
|
||||
|
||||
|
||||
// mir_piece/inv_pieceの初期化のときに呼び出されるcallback
|
||||
// fe_endをユーザー側で拡張するときに用いる。
|
||||
// この初期化のときに必要なのでinv_piece_とinv_piece_を公開している。
|
||||
// mir_piece_init_functionが呼び出されたタイミングで、fe_old_endまでは
|
||||
// これらのテーブルの初期化が完了していることが保証されている。
|
||||
// callback called when initializing mir_piece/inv_piece
|
||||
// Used when extending fe_end on the user side.
|
||||
// Inv_piece_ and inv_piece_ are exposed because they are necessary for this initialization.
|
||||
// At the timing when mir_piece_init_function is called, until fe_old_end
|
||||
// It is guaranteed that these tables have been initialized.
|
||||
extern std::function<void()> mir_piece_init_function;
|
||||
extern int16_t mir_piece_[Eval::fe_end];
|
||||
extern int16_t inv_piece_[Eval::fe_end];
|
||||
|
||||
// この関数を明示的に呼び出すか、init()を呼び出すかしたときに、上のテーブルが初期化される。
|
||||
// The table above will be initialized when you call this function explicitly or call init().
|
||||
extern void init_mir_inv_tables();
|
||||
}
|
||||
|
||||
#endif // defined(EVAL_NNUE) || defined(EVAL_LEARN)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE<EFBFBD>]<5D><><EFBFBD><EFBFBD><D690>ŗp<C597><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͓<EFBFBD><CD93><EFBFBD><EFBFBD>ʂƃl<C683>b<EFBFBD>g<EFBFBD><67><EFBFBD>[<5B>N<EFBFBD>\<5C><><EFBFBD>̒<EFBFBD><CC92>`
|
||||
// Definition of input features and network structure used in NNUE evaluation function
|
||||
|
||||
#ifndef HALFKP_CR_EP_256X2_32_32_H
|
||||
#define HALFKP_CR_EP_256X2_32_32_H
|
||||
@@ -16,17 +16,17 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// <EFBFBD>]<5D><><EFBFBD><EFBFBD><D690>ŗp<C597><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͓<EFBFBD><CD93><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Input features used in evaluation function
|
||||
using RawFeatures = Features::FeatureSet<
|
||||
Features::HalfKP<Features::Side::kFriend>, Features::CastlingRight,
|
||||
Features::EnPassant>;
|
||||
|
||||
// <EFBFBD>ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̓<EFBFBD><EFBFBD>͓<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̎<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Number of input feature dimensions after conversion
|
||||
constexpr IndexType kTransformedFeatureDimensions = 256;
|
||||
|
||||
namespace Layers {
|
||||
|
||||
// <EFBFBD>l<EFBFBD>b<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>[<5B>N<EFBFBD>\<5C><><EFBFBD>̒<EFBFBD><CC92>`
|
||||
// define network structure
|
||||
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
|
||||
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
|
||||
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数で用いる入力特徴量とネットワーク構造の定義
|
||||
// Definition of input features and network structure used in NNUE evaluation function
|
||||
|
||||
#ifndef HALFKP_256X2_32_32_H
|
||||
#define HALFKP_256X2_32_32_H
|
||||
@@ -14,16 +14,16 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 評価関数で用いる入力特徴量
|
||||
// Input features used in evaluation function
|
||||
using RawFeatures = Features::FeatureSet<
|
||||
Features::HalfKP<Features::Side::kFriend>>;
|
||||
|
||||
// 変換後の入力特徴量の次元数
|
||||
// Number of input feature dimensions after conversion
|
||||
constexpr IndexType kTransformedFeatureDimensions = 256;
|
||||
|
||||
namespace Layers {
|
||||
|
||||
// ネットワーク構造の定義
|
||||
// define network structure
|
||||
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
|
||||
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
|
||||
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE<EFBFBD>]<5D><><EFBFBD><EFBFBD><D690>ŗp<C597><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͓<EFBFBD><CD93><EFBFBD><EFBFBD>ʂƃl<C683>b<EFBFBD>g<EFBFBD><67><EFBFBD>[<5B>N<EFBFBD>\<5C><><EFBFBD>̒<EFBFBD><CC92>`
|
||||
// Definition of input features and network structure used in NNUE evaluation function
|
||||
|
||||
#ifndef K_P_CR_EP_256X2_32_32_H
|
||||
#define K_P_CR_EP_256X2_32_32_H
|
||||
@@ -17,16 +17,16 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// <EFBFBD>]<5D><><EFBFBD><EFBFBD><D690>ŗp<C597><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͓<EFBFBD><CD93><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Input features used in evaluation function
|
||||
using RawFeatures = Features::FeatureSet<Features::K, Features::P,
|
||||
Features::CastlingRight, Features::EnPassant>;
|
||||
|
||||
// <EFBFBD>ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̓<EFBFBD><EFBFBD>͓<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̎<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Number of input feature dimensions after conversion
|
||||
constexpr IndexType kTransformedFeatureDimensions = 256;
|
||||
|
||||
namespace Layers {
|
||||
|
||||
// <EFBFBD>l<EFBFBD>b<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>[<5B>N<EFBFBD>\<5C><><EFBFBD>̒<EFBFBD><CC92>`
|
||||
// define network structure
|
||||
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
|
||||
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
|
||||
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE<EFBFBD>]<5D><><EFBFBD><EFBFBD><D690>ŗp<C597><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͓<EFBFBD><CD93><EFBFBD><EFBFBD>ʂƃl<C683>b<EFBFBD>g<EFBFBD><67><EFBFBD>[<5B>N<EFBFBD>\<5C><><EFBFBD>̒<EFBFBD><CC92>`
|
||||
// Definition of input features and network structure used in NNUE evaluation function
|
||||
|
||||
#ifndef K_P_CR_256X2_32_32_H
|
||||
#define K_P_CR_256X2_32_32_H
|
||||
@@ -16,16 +16,16 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// <EFBFBD>]<5D><><EFBFBD><EFBFBD><D690>ŗp<C597><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͓<EFBFBD><CD93><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Input features used in evaluation function
|
||||
using RawFeatures = Features::FeatureSet<Features::K, Features::P,
|
||||
Features::CastlingRight>;
|
||||
|
||||
// <EFBFBD>ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̓<EFBFBD><EFBFBD>͓<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̎<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Number of input feature dimensions after conversion
|
||||
constexpr IndexType kTransformedFeatureDimensions = 256;
|
||||
|
||||
namespace Layers {
|
||||
|
||||
// <EFBFBD>l<EFBFBD>b<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>[<5B>N<EFBFBD>\<5C><><EFBFBD>̒<EFBFBD><CC92>`
|
||||
// define network structure
|
||||
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
|
||||
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
|
||||
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数で用いる入力特徴量とネットワーク構造の定義
|
||||
// Definition of input features and network structure used in NNUE evaluation function
|
||||
#ifndef K_P_256X2_32_32_H
|
||||
#define K_P_256X2_32_32_H
|
||||
|
||||
@@ -14,15 +14,15 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 評価関数で用いる入力特徴量
|
||||
// Input features used in evaluation function
|
||||
using RawFeatures = Features::FeatureSet<Features::K, Features::P>;
|
||||
|
||||
// 変換後の入力特徴量の次元数
|
||||
// Number of input feature dimensions after conversion
|
||||
constexpr IndexType kTransformedFeatureDimensions = 256;
|
||||
|
||||
namespace Layers {
|
||||
|
||||
// ネットワーク構造の定義
|
||||
// define network structure
|
||||
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
|
||||
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
|
||||
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の計算に関するコード
|
||||
// Code for calculating NNUE evaluation function
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
|
||||
@@ -16,16 +16,16 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 入力特徴量変換器
|
||||
// Input feature converter
|
||||
AlignedPtr<FeatureTransformer> feature_transformer;
|
||||
|
||||
// 評価関数
|
||||
// Evaluation function
|
||||
AlignedPtr<Network> network;
|
||||
|
||||
// 評価関数ファイル名
|
||||
// Evaluation function file name
|
||||
const char* const kFileName = "nn.bin";
|
||||
|
||||
// 評価関数の構造を表す文字列を取得する
|
||||
// Get a string that represents the structure of the evaluation function
|
||||
std::string GetArchitectureString() {
|
||||
return "Features=" + FeatureTransformer::GetStructureString() +
|
||||
",Network=" + Network::GetStructureString();
|
||||
@@ -35,14 +35,14 @@ namespace {
|
||||
|
||||
namespace Detail {
|
||||
|
||||
// 評価関数パラメータを初期化する
|
||||
// Initialize the evaluation function parameters
|
||||
template <typename T>
|
||||
void Initialize(AlignedPtr<T>& pointer) {
|
||||
pointer.reset(reinterpret_cast<T*>(aligned_malloc(sizeof(T), alignof(T))));
|
||||
std::memset(pointer.get(), 0, sizeof(T));
|
||||
}
|
||||
|
||||
// 評価関数パラメータを読み込む
|
||||
// read evaluation function parameters
|
||||
template <typename T>
|
||||
bool ReadParameters(std::istream& stream, const AlignedPtr<T>& pointer) {
|
||||
std::uint32_t header;
|
||||
@@ -51,7 +51,7 @@ bool ReadParameters(std::istream& stream, const AlignedPtr<T>& pointer) {
|
||||
return pointer->ReadParameters(stream);
|
||||
}
|
||||
|
||||
// 評価関数パラメータを書き込む
|
||||
// write evaluation function parameters
|
||||
template <typename T>
|
||||
bool WriteParameters(std::ostream& stream, const AlignedPtr<T>& pointer) {
|
||||
constexpr std::uint32_t header = T::GetHashValue();
|
||||
@@ -61,7 +61,7 @@ bool WriteParameters(std::ostream& stream, const AlignedPtr<T>& pointer) {
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
// 評価関数パラメータを初期化する
|
||||
// Initialize the evaluation function parameters
|
||||
void Initialize() {
|
||||
Detail::Initialize(feature_transformer);
|
||||
Detail::Initialize(network);
|
||||
@@ -69,7 +69,7 @@ void Initialize() {
|
||||
|
||||
} // namespace
|
||||
|
||||
// ヘッダを読み込む
|
||||
// read the header
|
||||
bool ReadHeader(std::istream& stream,
|
||||
std::uint32_t* hash_value, std::string* architecture) {
|
||||
std::uint32_t version, size;
|
||||
@@ -82,7 +82,7 @@ bool ReadHeader(std::istream& stream,
|
||||
return !stream.fail();
|
||||
}
|
||||
|
||||
// ヘッダを書き込む
|
||||
// write the header
|
||||
bool WriteHeader(std::ostream& stream,
|
||||
std::uint32_t hash_value, const std::string& architecture) {
|
||||
stream.write(reinterpret_cast<const char*>(&kVersion), sizeof(kVersion));
|
||||
@@ -93,7 +93,7 @@ bool WriteHeader(std::ostream& stream,
|
||||
return !stream.fail();
|
||||
}
|
||||
|
||||
// 評価関数パラメータを読み込む
|
||||
// read evaluation function parameters
|
||||
bool ReadParameters(std::istream& stream) {
|
||||
std::uint32_t hash_value;
|
||||
std::string architecture;
|
||||
@@ -104,7 +104,7 @@ bool ReadParameters(std::istream& stream) {
|
||||
return stream && stream.peek() == std::ios::traits_type::eof();
|
||||
}
|
||||
|
||||
// 評価関数パラメータを書き込む
|
||||
// write evaluation function parameters
|
||||
bool WriteParameters(std::ostream& stream) {
|
||||
if (!WriteHeader(stream, kHashValue, GetArchitectureString())) return false;
|
||||
if (!Detail::WriteParameters(stream, feature_transformer)) return false;
|
||||
@@ -112,12 +112,12 @@ bool WriteParameters(std::ostream& stream) {
|
||||
return !stream.fail();
|
||||
}
|
||||
|
||||
// 差分計算ができるなら進める
|
||||
// proceed if you can calculate the difference
|
||||
static void UpdateAccumulatorIfPossible(const Position& pos) {
|
||||
feature_transformer->UpdateAccumulatorIfPossible(pos);
|
||||
}
|
||||
|
||||
// 評価値を計算する
|
||||
// Calculate the evaluation value
|
||||
static Value ComputeScore(const Position& pos, bool refresh = false) {
|
||||
auto& accumulator = pos.state()->accumulator;
|
||||
if (!refresh && accumulator.computed_score) {
|
||||
@@ -130,22 +130,22 @@ static Value ComputeScore(const Position& pos, bool refresh = false) {
|
||||
alignas(kCacheLineSize) char buffer[Network::kBufferSize];
|
||||
const auto output = network->Propagate(transformed_features, buffer);
|
||||
|
||||
// VALUE_MAX_EVALより大きな値が返ってくるとaspiration searchがfail highして
|
||||
// 探索が終わらなくなるのでVALUE_MAX_EVAL以下であることを保証すべき。
|
||||
// When a value larger than VALUE_MAX_EVAL is returned, aspiration search fails high
|
||||
// It should be guaranteed that it is less than VALUE_MAX_EVAL because the search will not end.
|
||||
|
||||
// この現象が起きても、対局時に秒固定などだとそこで探索が打ち切られるので、
|
||||
// 1つ前のiterationのときの最善手がbestmoveとして指されるので見かけ上、
|
||||
// 問題ない。このVALUE_MAX_EVALが返ってくるような状況は、ほぼ詰みの局面であり、
|
||||
// そのような詰みの局面が出現するのは終盤で形勢に大差がついていることが多いので
|
||||
// 勝敗にはあまり影響しない。
|
||||
// Even if this phenomenon occurs, if the seconds are fixed when playing, the search will be aborted there, so
|
||||
// The best move in the previous iteration is pointed to as bestmove, so apparently
|
||||
// no problem. The situation in which this VALUE_MAX_EVAL is returned is almost at a dead end,
|
||||
// Since such a jamming phase often appears at the end, there is a big difference in the situation
|
||||
// Doesn't really affect the outcome.
|
||||
|
||||
// しかし、教師生成時などdepth固定で探索するときに探索から戻ってこなくなるので
|
||||
// そのスレッドの計算時間を無駄にする。またdepth固定対局でtime-outするようになる。
|
||||
// However, when searching with a fixed depth such as when creating a teacher, it will not return from the search
|
||||
// Waste the computation time for that thread. Also, it will be timed out with fixed depth game.
|
||||
|
||||
auto score = static_cast<Value>(output[0] / FV_SCALE);
|
||||
|
||||
// 1) ここ、下手にclipすると学習時には影響があるような気もするが…。
|
||||
// 2) accumulator.scoreは、差分計算の時に用いないので書き換えて問題ない。
|
||||
// 1) I feel that if I clip too poorly, it will have an effect on my learning...
|
||||
// 2) Since accumulator.score is not used at the time of difference calculation, it can be rewritten without any problem.
|
||||
score = Math::clamp(score , -VALUE_MAX_EVAL , VALUE_MAX_EVAL);
|
||||
|
||||
accumulator.score = score;
|
||||
@@ -153,10 +153,10 @@ static Value ComputeScore(const Position& pos, bool refresh = false) {
|
||||
return accumulator.score;
|
||||
}
|
||||
|
||||
} // namespace NNUE
|
||||
} // namespace NNUE
|
||||
|
||||
#if defined(USE_EVAL_HASH)
|
||||
// HashTableに評価値を保存するために利用するクラス
|
||||
// Class used to store evaluation values in HashTable
|
||||
struct alignas(16) ScoreKeyValue {
|
||||
#if defined(USE_SSE2)
|
||||
ScoreKeyValue() = default;
|
||||
@@ -171,15 +171,15 @@ struct alignas(16) ScoreKeyValue {
|
||||
}
|
||||
#endif
|
||||
|
||||
// evaluate hashでatomicに操作できる必要があるのでそのための操作子
|
||||
// It is necessary to be able to operate atomically with evaluate hash, so the manipulator for that
|
||||
void encode() {
|
||||
#if defined(USE_SSE2)
|
||||
// ScoreKeyValue は atomic にコピーされるので key が合っていればデータも合っている。
|
||||
// ScoreKeyValue is copied to atomic, so if the key matches, the data matches.
|
||||
#else
|
||||
key ^= score;
|
||||
#endif
|
||||
}
|
||||
// decode()はencode()の逆変換だが、xorなので逆変換も同じ変換。
|
||||
// decode() is the reverse conversion of encode(), but since it is xor, the reverse conversion is the same.
|
||||
void decode() { encode(); }
|
||||
|
||||
union {
|
||||
@@ -193,45 +193,45 @@ struct alignas(16) ScoreKeyValue {
|
||||
};
|
||||
};
|
||||
|
||||
// シンプルなHashTableの実装。
|
||||
// Sizeは2のべき乗。
|
||||
// Simple HashTable implementation.
|
||||
// Size is a power of 2.
|
||||
template <typename T, size_t Size>
|
||||
struct HashTable {
|
||||
HashTable() { clear(); }
|
||||
T* operator [] (const Key k) { return entries_ + (static_cast<size_t>(k) & (Size - 1)); }
|
||||
void clear() { memset(entries_, 0, sizeof(T)*Size); }
|
||||
|
||||
// Size が 2のべき乗であることのチェック
|
||||
// Check that Size is a power of 2
|
||||
static_assert((Size & (Size - 1)) == 0, "");
|
||||
|
||||
private:
|
||||
T entries_[Size];
|
||||
};
|
||||
|
||||
// evaluateしたものを保存しておくHashTable(俗にいうehash)
|
||||
//HashTable to save the evaluated ones (following ehash)
|
||||
|
||||
#if !defined(USE_LARGE_EVAL_HASH)
|
||||
// 134MB(魔女のAVX2以外の時の設定)
|
||||
// 134MB (setting other than witch's AVX2)
|
||||
struct EvaluateHashTable : HashTable<ScoreKeyValue, 0x800000> {};
|
||||
#else
|
||||
// prefetch有りなら大きいほうが良いのでは…。
|
||||
// → あまり変わらないし、メモリもったいないのでデフォルトでは↑の設定で良いか…。
|
||||
// 1GB(魔女のAVX2の時の設定)
|
||||
// If you have prefetch, it's better to have a big one...
|
||||
// → It doesn't change much and the memory is wasteful, so is it okay to set ↑ by default?
|
||||
// 1GB (setting for witch's AVX2)
|
||||
struct EvaluateHashTable : HashTable<ScoreKeyValue, 0x4000000> {};
|
||||
#endif
|
||||
|
||||
EvaluateHashTable g_evalTable;
|
||||
|
||||
// prefetchする関数も用意しておく。
|
||||
// Prepare a function to prefetch.
|
||||
void prefetch_evalhash(const Key key) {
|
||||
constexpr auto mask = ~((uint64_t)0x1f);
|
||||
prefetch((void*)((uint64_t)g_evalTable[key] & mask));
|
||||
}
|
||||
#endif
|
||||
|
||||
// 評価関数ファイルを読み込む
|
||||
// benchコマンドなどでOptionsを保存して復元するのでこのときEvalDirが変更されたことになって、
|
||||
// 評価関数の再読込の必要があるというフラグを立てるため、この関数は2度呼び出されることがある。
|
||||
// read the evaluation function file
|
||||
// Save and restore Options with bench command etc., so EvalDir is changed at this time,
|
||||
// This function may be called twice to flag that the evaluation function needs to be reloaded.
|
||||
void load_eval() {
|
||||
NNUE::Initialize();
|
||||
|
||||
@@ -249,7 +249,7 @@ void load_eval() {
|
||||
// ASSERT(result);
|
||||
if (!result)
|
||||
{
|
||||
// 読み込みエラーのとき終了してくれないと困る。
|
||||
// It's a problem if it doesn't finish when there is a read error.
|
||||
std::cout << "Error! " << NNUE::kFileName << " not found or wrong format" << std::endl;
|
||||
//my_exit();
|
||||
}
|
||||
@@ -260,19 +260,19 @@ void load_eval() {
|
||||
std::cout << "info string NNUE " << NNUE::kFileName << " not loaded" << std::endl;
|
||||
}
|
||||
|
||||
// 初期化
|
||||
// Initialization
|
||||
void init() {
|
||||
}
|
||||
|
||||
// 評価関数。差分計算ではなく全計算する。
|
||||
// Position::set()で一度だけ呼び出される。(以降は差分計算)
|
||||
// 手番側から見た評価値を返すので注意。(他の評価関数とは設計がこの点において異なる)
|
||||
// なので、この関数の最適化は頑張らない。
|
||||
// Evaluation function. Perform full calculation instead of difference calculation.
|
||||
// Called only once with Position::set(). (The difference calculation after that)
|
||||
// Note that the evaluation value seen from the turn side is returned. (Design differs from other evaluation functions in this respect)
|
||||
// Since, we will not try to optimize this function.
|
||||
Value compute_eval(const Position& pos) {
|
||||
return NNUE::ComputeScore(pos, true);
|
||||
}
|
||||
|
||||
// 評価関数
|
||||
// Evaluation function
|
||||
Value evaluate(const Position& pos) {
|
||||
const auto& accumulator = pos.state()->accumulator;
|
||||
if (accumulator.computed_score) {
|
||||
@@ -280,8 +280,8 @@ Value evaluate(const Position& pos) {
|
||||
}
|
||||
|
||||
#if defined(USE_GLOBAL_OPTIONS)
|
||||
// GlobalOptionsでeval hashを用いない設定になっているなら
|
||||
// eval hashへの照会をskipする。
|
||||
// If Global Options is set not to use eval hash
|
||||
// Skip the query to the eval hash.
|
||||
if (!GlobalOptions.use_eval_hash) {
|
||||
ASSERT_LV5(pos.state()->materialValue == Eval::material(pos));
|
||||
return NNUE::ComputeScore(pos);
|
||||
@@ -289,19 +289,19 @@ Value evaluate(const Position& pos) {
|
||||
#endif
|
||||
|
||||
#if defined(USE_EVAL_HASH)
|
||||
// evaluate hash tableにはあるかも。
|
||||
// May be in the evaluate hash table.
|
||||
const Key key = pos.key();
|
||||
ScoreKeyValue entry = *g_evalTable[key];
|
||||
entry.decode();
|
||||
if (entry.key == key) {
|
||||
// あった!
|
||||
// there were!
|
||||
return Value(entry.score);
|
||||
}
|
||||
#endif
|
||||
|
||||
Value score = NNUE::ComputeScore(pos);
|
||||
#if defined(USE_EVAL_HASH)
|
||||
// せっかく計算したのでevaluate hash tableに保存しておく。
|
||||
// Since it was calculated carefully, save it in the evaluate hash table.
|
||||
entry.key = key;
|
||||
entry.score = score;
|
||||
entry.encode();
|
||||
@@ -311,12 +311,12 @@ Value evaluate(const Position& pos) {
|
||||
return score;
|
||||
}
|
||||
|
||||
// 差分計算ができるなら進める
|
||||
// proceed if you can calculate the difference
|
||||
void evaluate_with_no_return(const Position& pos) {
|
||||
NNUE::UpdateAccumulatorIfPossible(pos);
|
||||
}
|
||||
|
||||
// 現在の局面の評価値の内訳を表示する
|
||||
// display the breakdown of the evaluation value of the current phase
|
||||
void print_eval_stat(Position& /*pos*/) {
|
||||
std::cout << "--- EVAL STAT: not implemented" << std::endl;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数で用いるheader
|
||||
// header used in NNUE evaluation function
|
||||
|
||||
#ifndef _EVALUATE_NNUE_H_
|
||||
#define _EVALUATE_NNUE_H_
|
||||
@@ -14,11 +14,11 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 評価関数の構造のハッシュ値
|
||||
// hash value of evaluation function structure
|
||||
constexpr std::uint32_t kHashValue =
|
||||
FeatureTransformer::GetHashValue() ^ Network::GetHashValue();
|
||||
|
||||
// メモリ領域の解放を自動化するためのデリータ
|
||||
// Deleter for automating release of memory area
|
||||
template <typename T>
|
||||
struct AlignedDeleter {
|
||||
void operator()(T* ptr) const {
|
||||
@@ -29,30 +29,30 @@ struct AlignedDeleter {
|
||||
template <typename T>
|
||||
using AlignedPtr = std::unique_ptr<T, AlignedDeleter<T>>;
|
||||
|
||||
// 入力特徴量変換器
|
||||
// Input feature converter
|
||||
extern AlignedPtr<FeatureTransformer> feature_transformer;
|
||||
|
||||
// 評価関数
|
||||
// Evaluation function
|
||||
extern AlignedPtr<Network> network;
|
||||
|
||||
// 評価関数ファイル名
|
||||
// Evaluation function file name
|
||||
extern const char* const kFileName;
|
||||
|
||||
// 評価関数の構造を表す文字列を取得する
|
||||
// Get a string that represents the structure of the evaluation function
|
||||
std::string GetArchitectureString();
|
||||
|
||||
// ヘッダを読み込む
|
||||
// read the header
|
||||
bool ReadHeader(std::istream& stream,
|
||||
std::uint32_t* hash_value, std::string* architecture);
|
||||
|
||||
// ヘッダを書き込む
|
||||
// write the header
|
||||
bool WriteHeader(std::ostream& stream,
|
||||
std::uint32_t hash_value, const std::string& architecture);
|
||||
|
||||
// 評価関数パラメータを読み込む
|
||||
// read evaluation function parameters
|
||||
bool ReadParameters(std::istream& stream);
|
||||
|
||||
// 評価関数パラメータを書き込む
|
||||
// write evaluation function parameters
|
||||
bool WriteParameters(std::ostream& stream);
|
||||
|
||||
} // namespace NNUE
|
||||
@@ -61,4 +61,4 @@ bool WriteParameters(std::ostream& stream);
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の学習時用のコード
|
||||
// Code for learning NNUE evaluation function
|
||||
|
||||
#if defined(EVAL_LEARN) && defined(EVAL_NNUE)
|
||||
|
||||
@@ -31,30 +31,30 @@ namespace NNUE {
|
||||
|
||||
namespace {
|
||||
|
||||
// 学習データ
|
||||
// learning data
|
||||
std::vector<Example> examples;
|
||||
|
||||
// examplesの排他制御をするMutex
|
||||
// Mutex for exclusive control of examples
|
||||
std::mutex examples_mutex;
|
||||
|
||||
// ミニバッチのサンプル数
|
||||
// number of samples in mini-batch
|
||||
uint64_t batch_size;
|
||||
|
||||
// 乱数生成器
|
||||
// random number generator
|
||||
std::mt19937 rng;
|
||||
|
||||
// 学習器
|
||||
// learner
|
||||
std::shared_ptr<Trainer<Network>> trainer;
|
||||
|
||||
// 学習率のスケール
|
||||
// Learning rate scale
|
||||
double global_learning_rate_scale;
|
||||
|
||||
// 学習率のスケールを取得する
|
||||
// Get the learning rate scale
|
||||
double GetGlobalLearningRateScale() {
|
||||
return global_learning_rate_scale;
|
||||
}
|
||||
|
||||
// ハイパーパラメータなどのオプションを学習器に伝える
|
||||
// Tell the learner options such as hyperparameters
|
||||
void SendMessages(std::vector<Message> messages) {
|
||||
for (auto& message : messages) {
|
||||
trainer->SendMessage(&message);
|
||||
@@ -64,7 +64,7 @@ void SendMessages(std::vector<Message> messages) {
|
||||
|
||||
} // namespace
|
||||
|
||||
// 学習の初期化を行う
|
||||
// Initialize learning
|
||||
void InitializeTraining(double eta1, uint64_t eta1_epoch,
|
||||
double eta2, uint64_t eta2_epoch, double eta3) {
|
||||
std::cout << "Initializing NN training for "
|
||||
@@ -82,18 +82,18 @@ void InitializeTraining(double eta1, uint64_t eta1_epoch,
|
||||
EvalLearningTools::Weight::init_eta(eta1, eta2, eta3, eta1_epoch, eta2_epoch);
|
||||
}
|
||||
|
||||
// ミニバッチのサンプル数を設定する
|
||||
// set the number of samples in the mini-batch
|
||||
void SetBatchSize(uint64_t size) {
|
||||
assert(size > 0);
|
||||
batch_size = size;
|
||||
}
|
||||
|
||||
// 学習率のスケールを設定する
|
||||
// set the learning rate scale
|
||||
void SetGlobalLearningRateScale(double scale) {
|
||||
global_learning_rate_scale = scale;
|
||||
}
|
||||
|
||||
// ハイパーパラメータなどのオプションを設定する
|
||||
// Set options such as hyperparameters
|
||||
void SetOptions(const std::string& options) {
|
||||
std::vector<Message> messages;
|
||||
for (const auto& option : Split(options, ',')) {
|
||||
@@ -108,7 +108,7 @@ void SetOptions(const std::string& options) {
|
||||
SendMessages(std::move(messages));
|
||||
}
|
||||
|
||||
// 学習用評価関数パラメータをファイルから読み直す
|
||||
// Reread the evaluation function parameters for learning from the file
|
||||
void RestoreParameters(const std::string& dir_name) {
|
||||
const std::string file_name = Path::Combine(dir_name, NNUE::kFileName);
|
||||
std::ifstream stream(file_name, std::ios::binary);
|
||||
@@ -118,7 +118,7 @@ void RestoreParameters(const std::string& dir_name) {
|
||||
SendMessages({{"reset"}});
|
||||
}
|
||||
|
||||
// 学習データを1サンプル追加する
|
||||
// Add 1 sample of learning data
|
||||
void AddExample(Position& pos, Color rootColor,
|
||||
const Learner::PackedSfenValue& psv, double weight) {
|
||||
Example example;
|
||||
@@ -162,7 +162,7 @@ void AddExample(Position& pos, Color rootColor,
|
||||
examples.push_back(std::move(example));
|
||||
}
|
||||
|
||||
// 評価関数パラメーターを更新する
|
||||
// update the evaluation function parameters
|
||||
void UpdateParameters(uint64_t epoch) {
|
||||
assert(batch_size > 0);
|
||||
|
||||
@@ -192,21 +192,21 @@ void UpdateParameters(uint64_t epoch) {
|
||||
SendMessages({{"quantize_parameters"}});
|
||||
}
|
||||
|
||||
// 学習に問題が生じていないかチェックする
|
||||
// Check if there are any problems with learning
|
||||
void CheckHealth() {
|
||||
SendMessages({{"check_health"}});
|
||||
}
|
||||
|
||||
} // namespace NNUE
|
||||
|
||||
// 評価関数パラメーターをファイルに保存する
|
||||
// save merit function parameters to a file
|
||||
void save_eval(std::string dir_name) {
|
||||
auto eval_dir = Path::Combine(Options["EvalSaveDir"], dir_name);
|
||||
std::cout << "save_eval() start. folder = " << eval_dir << std::endl;
|
||||
|
||||
// すでにこのフォルダがあるならmkdir()に失敗するが、
|
||||
// 別にそれは構わない。なければ作って欲しいだけ。
|
||||
// また、EvalSaveDirまでのフォルダは掘ってあるものとする。
|
||||
// mkdir() will fail if this folder already exists, but
|
||||
// Apart from that. If not, I just want you to make it.
|
||||
// Also, assume that the folders up to EvalSaveDir have been dug.
|
||||
Dependency::mkdir(eval_dir);
|
||||
|
||||
if (Options["SkipLoadingEval"] && NNUE::trainer) {
|
||||
@@ -221,7 +221,7 @@ void save_eval(std::string dir_name) {
|
||||
std::cout << "save_eval() finished. folder = " << eval_dir << std::endl;
|
||||
}
|
||||
|
||||
// 現在のetaを取得する
|
||||
// get the current eta
|
||||
double get_eta() {
|
||||
return NNUE::GetGlobalLearningRateScale() * EvalLearningTools::Weight::eta;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の学習で用いるインターフェイス
|
||||
// Interface used for learning NNUE evaluation function
|
||||
|
||||
#ifndef _EVALUATE_NNUE_LEARNER_H_
|
||||
#define _EVALUATE_NNUE_LEARNER_H_
|
||||
@@ -11,30 +11,30 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 学習の初期化を行う
|
||||
// Initialize learning
|
||||
void InitializeTraining(double eta1, uint64_t eta1_epoch,
|
||||
double eta2, uint64_t eta2_epoch, double eta3);
|
||||
|
||||
// ミニバッチのサンプル数を設定する
|
||||
// set the number of samples in the mini-batch
|
||||
void SetBatchSize(uint64_t size);
|
||||
|
||||
// 学習率のスケールを設定する
|
||||
// set the learning rate scale
|
||||
void SetGlobalLearningRateScale(double scale);
|
||||
|
||||
// ハイパーパラメータなどのオプションを設定する
|
||||
// Set options such as hyperparameters
|
||||
void SetOptions(const std::string& options);
|
||||
|
||||
// 学習用評価関数パラメータをファイルから読み直す
|
||||
// Reread the evaluation function parameters for learning from the file
|
||||
void RestoreParameters(const std::string& dir_name);
|
||||
|
||||
// 学習データを1サンプル追加する
|
||||
// Add 1 sample of learning data
|
||||
void AddExample(Position& pos, Color rootColor,
|
||||
const Learner::PackedSfenValue& psv, double weight);
|
||||
|
||||
// 評価関数パラメータを更新する
|
||||
// update the evaluation function parameters
|
||||
void UpdateParameters(uint64_t epoch);
|
||||
|
||||
// 学習に問題が生じていないかチェックする
|
||||
// Check if there are any problems with learning
|
||||
void CheckHealth();
|
||||
|
||||
} // namespace NNUE
|
||||
@@ -43,4 +43,4 @@ void CheckHealth();
|
||||
|
||||
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量Kの定義
|
||||
//Definition of input feature quantity K of NNUE evaluation function
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
|
||||
@@ -11,10 +11,10 @@ namespace Eval {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
void CastlingRight::AppendActiveIndices(
|
||||
const Position& pos, Color perspective, IndexList* active) {
|
||||
// コンパイラの警告を回避するため、配列サイズが小さい場合は何もしない
|
||||
// do nothing if array size is small to avoid compiler warning
|
||||
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
|
||||
|
||||
int castling_rights = pos.state()->castlingRights;
|
||||
@@ -28,14 +28,14 @@ namespace Eval {
|
||||
& ((castling_rights >> 2) & 3);
|
||||
}
|
||||
|
||||
for (int i = 0; i < kDimensions; ++i) {
|
||||
for (int i = 0; i <kDimensions; ++i) {
|
||||
if (relative_castling_rights & (i << 1)) {
|
||||
active->push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
void CastlingRight::AppendChangedIndices(
|
||||
const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE<55>]<5D><><EFBFBD><EFBFBD><D690>̓<EFBFBD><CC93>͓<EFBFBD><CD93><EFBFBD><EFBFBD><EFBFBD>K<EFBFBD>̒<EFBFBD><CC92>`
|
||||
//Definition of input feature quantity K of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_FEATURES_CASTLING_RIGHT_H_
|
||||
#define _NNUE_FEATURES_CASTLING_RIGHT_H_
|
||||
@@ -14,25 +14,25 @@ namespace Eval {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>K<EFBFBD>F<EFBFBD>ʂ̈ʒu
|
||||
// Feature K: Ball position
|
||||
class CastlingRight {
|
||||
public:
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʖ<EFBFBD>
|
||||
// feature quantity name
|
||||
static constexpr const char* kName = "CastlingRight";
|
||||
// <EFBFBD>]<5D><><EFBFBD><EFBFBD><D690>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>ɖ<EFBFBD><C996>ߍ<EFBFBD><DF8D>ރn<DE83>b<EFBFBD>V<EFBFBD><56><EFBFBD>l
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t kHashValue = 0x913968AAu;
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̎<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// number of feature dimensions
|
||||
static constexpr IndexType kDimensions = 4;
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̂<EFBFBD><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɒl<EFBFBD><EFBFBD>1<EFBFBD>ƂȂ<EFBFBD><EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>b<EFBFBD>N<EFBFBD>X<EFBFBD>̐<EFBFBD><EFBFBD>̍ő<EFBFBD><EFBFBD>l
|
||||
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
|
||||
static constexpr IndexType kMaxActiveDimensions = 4;
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>v<EFBFBD>Z<EFBFBD>̑<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɑS<EFBFBD>v<EFBFBD>Z<EFBFBD><EFBFBD><EFBFBD>s<EFBFBD><EFBFBD><EFBFBD>^<5E>C<EFBFBD>~<7E><><EFBFBD>O
|
||||
// Timing of full calculation instead of difference calculation
|
||||
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone;
|
||||
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̂<EFBFBD><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD>l<EFBFBD><EFBFBD>1<EFBFBD>ł<EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>b<EFBFBD>N<EFBFBD>X<EFBFBD>̃<EFBFBD><EFBFBD>X<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>擾<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
static void AppendActiveIndices(const Position& pos, Color perspective,
|
||||
IndexList* active);
|
||||
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̂<EFBFBD><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>O<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>l<EFBFBD><EFBFBD><EFBFBD>ω<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>b<EFBFBD>N<EFBFBD>X<EFBFBD>̃<EFBFBD><EFBFBD>X<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>擾<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Get a list of indices whose values ??have changed from the previous one in the feature quantity
|
||||
static void AppendChangedIndices(const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added);
|
||||
};
|
||||
@@ -45,4 +45,4 @@ namespace Eval {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE<55>]<5D><><EFBFBD><EFBFBD><D690>̓<EFBFBD><CC93>͓<EFBFBD><CD93><EFBFBD><EFBFBD><EFBFBD>K<EFBFBD>̒<EFBFBD><CC92>`
|
||||
//Definition of input feature quantity K of NNUE evaluation function
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
|
||||
@@ -11,10 +11,10 @@ namespace Eval {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̂<EFBFBD><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD>l<EFBFBD><EFBFBD>1<EFBFBD>ł<EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>b<EFBFBD>N<EFBFBD>X<EFBFBD>̃<EFBFBD><EFBFBD>X<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>擾<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
void EnPassant::AppendActiveIndices(
|
||||
const Position& pos, Color perspective, IndexList* active) {
|
||||
// <EFBFBD>R<EFBFBD><EFBFBD><EFBFBD>p<EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>̌x<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>邽<EFBFBD>߁A<EFBFBD>z<EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C<EFBFBD>Y<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ꍇ<EFBFBD>͉<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD>
|
||||
// do nothing if array size is small to avoid compiler warning
|
||||
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
|
||||
|
||||
auto epSquare = pos.state()->epSquare;
|
||||
@@ -30,7 +30,7 @@ namespace Eval {
|
||||
active->push_back(file);
|
||||
}
|
||||
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̂<EFBFBD><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>O<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>l<EFBFBD><EFBFBD><EFBFBD>ω<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>b<EFBFBD>N<EFBFBD>X<EFBFBD>̃<EFBFBD><EFBFBD>X<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>擾<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Get a list of indices whose values ??have changed from the previous one in the feature quantity
|
||||
void EnPassant::AppendChangedIndices(
|
||||
const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE<55>]<5D><><EFBFBD><EFBFBD><D690>̓<EFBFBD><CC93>͓<EFBFBD><CD93><EFBFBD><EFBFBD><EFBFBD>K<EFBFBD>̒<EFBFBD><CC92>`
|
||||
//Definition of input feature quantity K of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_FEATURES_ENPASSANT_H_
|
||||
#define _NNUE_FEATURES_ENPASSANT_H_
|
||||
@@ -14,25 +14,25 @@ namespace Eval {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>K<EFBFBD>F<EFBFBD>ʂ̈ʒu
|
||||
// Feature K: Ball position
|
||||
class EnPassant {
|
||||
public:
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʖ<EFBFBD>
|
||||
// feature quantity name
|
||||
static constexpr const char* kName = "EnPassant";
|
||||
// <EFBFBD>]<5D><><EFBFBD><EFBFBD><D690>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>ɖ<EFBFBD><C996>ߍ<EFBFBD><DF8D>ރn<DE83>b<EFBFBD>V<EFBFBD><56><EFBFBD>l
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t kHashValue = 0x02924F91u;
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̎<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// number of feature dimensions
|
||||
static constexpr IndexType kDimensions = 8;
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̂<EFBFBD><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɒl<EFBFBD><EFBFBD>1<EFBFBD>ƂȂ<EFBFBD><EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>b<EFBFBD>N<EFBFBD>X<EFBFBD>̐<EFBFBD><EFBFBD>̍ő<EFBFBD><EFBFBD>l
|
||||
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
|
||||
static constexpr IndexType kMaxActiveDimensions = 1;
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>v<EFBFBD>Z<EFBFBD>̑<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɑS<EFBFBD>v<EFBFBD>Z<EFBFBD><EFBFBD><EFBFBD>s<EFBFBD><EFBFBD><EFBFBD>^<5E>C<EFBFBD>~<7E><><EFBFBD>O
|
||||
// Timing of full calculation instead of difference calculation
|
||||
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kAnyPieceMoved;
|
||||
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̂<EFBFBD><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD>l<EFBFBD><EFBFBD>1<EFBFBD>ł<EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>b<EFBFBD>N<EFBFBD>X<EFBFBD>̃<EFBFBD><EFBFBD>X<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>擾<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
static void AppendActiveIndices(const Position& pos, Color perspective,
|
||||
IndexList* active);
|
||||
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʂ̂<EFBFBD><EFBFBD><EFBFBD><EFBFBD>A<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>O<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>l<EFBFBD><EFBFBD><EFBFBD>ω<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><EFBFBD><EFBFBD>f<EFBFBD>b<EFBFBD>N<EFBFBD>X<EFBFBD>̃<EFBFBD><EFBFBD>X<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>擾<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// Get a list of indices whose values ??have changed from the previous one in the feature quantity
|
||||
static void AppendChangedIndices(const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added);
|
||||
};
|
||||
@@ -45,4 +45,4 @@ namespace Eval {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量セットを表すクラステンプレート
|
||||
// A class template that represents the input feature set of the NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_FEATURE_SET_H_
|
||||
#define _NNUE_FEATURE_SET_H_
|
||||
@@ -14,7 +14,7 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 値のリストを表すクラステンプレート
|
||||
// A class template that represents a list of values
|
||||
template <typename T, T... Values>
|
||||
struct CompileTimeList;
|
||||
template <typename T, T First, T... Remaining>
|
||||
@@ -36,7 +36,7 @@ struct CompileTimeList<T> {
|
||||
static constexpr std::array<T, 0> kValues = {{}};
|
||||
};
|
||||
|
||||
// リストの先頭への追加を行うクラステンプレート
|
||||
// Class template that adds to the beginning of the list
|
||||
template <typename T, typename ListType, T Value>
|
||||
struct AppendToList;
|
||||
template <typename T, T... Values, T AnotherValue>
|
||||
@@ -44,7 +44,7 @@ struct AppendToList<T, CompileTimeList<T, Values...>, AnotherValue> {
|
||||
using Result = CompileTimeList<T, AnotherValue, Values...>;
|
||||
};
|
||||
|
||||
// ソートされた重複のないリストへの追加を行うクラステンプレート
|
||||
// Class template for adding to a sorted, unique list
|
||||
template <typename T, typename ListType, T Value>
|
||||
struct InsertToSet;
|
||||
template <typename T, T First, T... Remaining, T AnotherValue>
|
||||
@@ -52,7 +52,7 @@ struct InsertToSet<T, CompileTimeList<T, First, Remaining...>, AnotherValue> {
|
||||
using Result = std::conditional_t<
|
||||
CompileTimeList<T, First, Remaining...>::Contains(AnotherValue),
|
||||
CompileTimeList<T, First, Remaining...>,
|
||||
std::conditional_t<(AnotherValue < First),
|
||||
std::conditional_t<(AnotherValue <First),
|
||||
CompileTimeList<T, AnotherValue, First, Remaining...>,
|
||||
typename AppendToList<T, typename InsertToSet<
|
||||
T, CompileTimeList<T, Remaining...>, AnotherValue>::Result,
|
||||
@@ -63,21 +63,21 @@ struct InsertToSet<T, CompileTimeList<T>, Value> {
|
||||
using Result = CompileTimeList<T, Value>;
|
||||
};
|
||||
|
||||
// 特徴量セットの基底クラス
|
||||
// Base class of feature set
|
||||
template <typename Derived>
|
||||
class FeatureSetBase {
|
||||
public:
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
template <typename IndexListType>
|
||||
static void AppendActiveIndices(
|
||||
const Position& pos, TriggerEvent trigger, IndexListType active[2]) {
|
||||
for (const auto perspective : Colors) {
|
||||
for (const auto perspective :Colors) {
|
||||
Derived::CollectActiveIndices(
|
||||
pos, trigger, perspective, &active[perspective]);
|
||||
}
|
||||
}
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
template <typename PositionType, typename IndexListType>
|
||||
static void AppendChangedIndices(
|
||||
const PositionType& pos, TriggerEvent trigger,
|
||||
@@ -85,7 +85,7 @@ class FeatureSetBase {
|
||||
const auto& dp = pos.state()->dirtyPiece;
|
||||
if (dp.dirty_num == 0) return;
|
||||
|
||||
for (const auto perspective : Colors) {
|
||||
for (const auto perspective :Colors) {
|
||||
reset[perspective] = false;
|
||||
switch (trigger) {
|
||||
case TriggerEvent::kNone:
|
||||
@@ -120,8 +120,8 @@ class FeatureSetBase {
|
||||
}
|
||||
};
|
||||
|
||||
// 特徴量セットを表すクラステンプレート
|
||||
// 実行時の計算量を線形にするために、内部の処理はテンプレート引数の逆順に行う
|
||||
// Class template that represents the feature set
|
||||
// do internal processing in reverse order of template arguments in order to linearize the amount of calculation at runtime
|
||||
template <typename FirstFeatureType, typename... RemainingFeatureTypes>
|
||||
class FeatureSet<FirstFeatureType, RemainingFeatureTypes...> :
|
||||
public FeatureSetBase<
|
||||
@@ -131,27 +131,27 @@ class FeatureSet<FirstFeatureType, RemainingFeatureTypes...> :
|
||||
using Tail = FeatureSet<RemainingFeatureTypes...>;
|
||||
|
||||
public:
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t kHashValue =
|
||||
Head::kHashValue ^ (Tail::kHashValue << 1) ^ (Tail::kHashValue >> 31);
|
||||
// 特徴量の次元数
|
||||
// number of feature dimensions
|
||||
static constexpr IndexType kDimensions =
|
||||
Head::kDimensions + Tail::kDimensions;
|
||||
// 特徴量のうち、同時に値が1となるインデックスの数の最大値
|
||||
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
|
||||
static constexpr IndexType kMaxActiveDimensions =
|
||||
Head::kMaxActiveDimensions + Tail::kMaxActiveDimensions;
|
||||
// 差分計算の代わりに全計算を行うタイミングのリスト
|
||||
// List of timings to perform all calculations instead of difference calculation
|
||||
using SortedTriggerSet = typename InsertToSet<TriggerEvent,
|
||||
typename Tail::SortedTriggerSet, Head::kRefreshTrigger>::Result;
|
||||
static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues;
|
||||
|
||||
// 特徴量名を取得する
|
||||
// Get the feature quantity name
|
||||
static std::string GetName() {
|
||||
return std::string(Head::kName) + "+" + Tail::GetName();
|
||||
}
|
||||
|
||||
private:
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
template <typename IndexListType>
|
||||
static void CollectActiveIndices(
|
||||
const Position& pos, const TriggerEvent trigger, const Color perspective,
|
||||
@@ -166,7 +166,7 @@ class FeatureSet<FirstFeatureType, RemainingFeatureTypes...> :
|
||||
}
|
||||
}
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
template <typename IndexListType>
|
||||
static void CollectChangedIndices(
|
||||
const Position& pos, const TriggerEvent trigger, const Color perspective,
|
||||
@@ -185,36 +185,36 @@ class FeatureSet<FirstFeatureType, RemainingFeatureTypes...> :
|
||||
}
|
||||
}
|
||||
|
||||
// 基底クラスと、自身を再帰的に利用するクラステンプレートをfriendにする
|
||||
// Make the base class and the class template that recursively uses itself a friend
|
||||
friend class FeatureSetBase<FeatureSet>;
|
||||
template <typename... FeatureTypes>
|
||||
friend class FeatureSet;
|
||||
};
|
||||
|
||||
// 特徴量セットを表すクラステンプレート
|
||||
// テンプレート引数が1つの場合の特殊化
|
||||
// Class template that represents the feature set
|
||||
// Specialization with one template argument
|
||||
template <typename FeatureType>
|
||||
class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
|
||||
public:
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t kHashValue = FeatureType::kHashValue;
|
||||
// 特徴量の次元数
|
||||
// number of feature dimensions
|
||||
static constexpr IndexType kDimensions = FeatureType::kDimensions;
|
||||
// 特徴量のうち、同時に値が1となるインデックスの数の最大値
|
||||
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
|
||||
static constexpr IndexType kMaxActiveDimensions =
|
||||
FeatureType::kMaxActiveDimensions;
|
||||
// 差分計算の代わりに全計算を行うタイミングのリスト
|
||||
// List of timings to perform all calculations instead of difference calculation
|
||||
using SortedTriggerSet =
|
||||
CompileTimeList<TriggerEvent, FeatureType::kRefreshTrigger>;
|
||||
static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues;
|
||||
|
||||
// 特徴量名を取得する
|
||||
// Get the feature quantity name
|
||||
static std::string GetName() {
|
||||
return FeatureType::kName;
|
||||
}
|
||||
|
||||
private:
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
static void CollectActiveIndices(
|
||||
const Position& pos, const TriggerEvent trigger, const Color perspective,
|
||||
IndexList* const active) {
|
||||
@@ -223,7 +223,7 @@ class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
|
||||
}
|
||||
}
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
static void CollectChangedIndices(
|
||||
const Position& pos, const TriggerEvent trigger, const Color perspective,
|
||||
IndexList* const removed, IndexList* const added) {
|
||||
@@ -232,7 +232,7 @@ class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
|
||||
}
|
||||
}
|
||||
|
||||
// 基底クラスと、自身を再帰的に利用するクラステンプレートをfriendにする
|
||||
// Make the base class and the class template that recursively uses itself a friend
|
||||
friend class FeatureSetBase<FeatureSet>;
|
||||
template <typename... FeatureTypes>
|
||||
friend class FeatureSet;
|
||||
@@ -246,4 +246,4 @@ class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量の共通ヘッダ
|
||||
//Common header of input features of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_FEATURES_COMMON_H_
|
||||
#define _NNUE_FEATURES_COMMON_H_
|
||||
@@ -14,26 +14,26 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// インデックスリストの型
|
||||
// Index list type
|
||||
class IndexList;
|
||||
|
||||
// 特徴量セットを表すクラステンプレート
|
||||
// Class template that represents the feature set
|
||||
template <typename... FeatureTypes>
|
||||
class FeatureSet;
|
||||
|
||||
// 差分計算の代わりに全計算を行うタイミングの種類
|
||||
// Type of timing to perform all calculations instead of difference calculation
|
||||
enum class TriggerEvent {
|
||||
kNone, // 可能な場合は常に差分計算する
|
||||
kFriendKingMoved, // 自玉が移動した場合に全計算する
|
||||
kEnemyKingMoved, // 敵玉が移動した場合に全計算する
|
||||
kAnyKingMoved, // どちらかの玉が移動した場合に全計算する
|
||||
kAnyPieceMoved, // 常に全計算する
|
||||
kNone, // Calculate the difference whenever possible
|
||||
kFriendKingMoved, // calculate all when own ball moves
|
||||
kEnemyKingMoved, // do all calculations when enemy balls move
|
||||
kAnyKingMoved, // do all calculations if either ball moves
|
||||
kAnyPieceMoved, // always do all calculations
|
||||
};
|
||||
|
||||
// 手番側or相手側
|
||||
// turn side or other side
|
||||
enum class Side {
|
||||
kFriend, // 手番側
|
||||
kEnemy, // 相手側
|
||||
kFriend, // turn side
|
||||
kEnemy, // opponent
|
||||
};
|
||||
|
||||
} // namespace Features
|
||||
@@ -44,4 +44,4 @@ enum class Side {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量HalfKPの定義
|
||||
//Definition of input features HalfKP of NNUE evaluation function
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
|
||||
@@ -11,13 +11,13 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 玉の位置とBonaPieceから特徴量のインデックスを求める
|
||||
// Find the index of the feature quantity from the ball position and BonaPiece
|
||||
template <Side AssociatedKing>
|
||||
inline IndexType HalfKP<AssociatedKing>::MakeIndex(Square sq_k, BonaPiece p) {
|
||||
return static_cast<IndexType>(fe_end) * static_cast<IndexType>(sq_k) + p;
|
||||
}
|
||||
|
||||
// 駒の情報を取得する
|
||||
// Get the piece information
|
||||
template <Side AssociatedKing>
|
||||
inline void HalfKP<AssociatedKing>::GetPieces(
|
||||
const Position& pos, Color perspective,
|
||||
@@ -31,7 +31,7 @@ inline void HalfKP<AssociatedKing>::GetPieces(
|
||||
*sq_target_k = static_cast<Square>(((*pieces)[target] - f_king) % SQUARE_NB);
|
||||
}
|
||||
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
template <Side AssociatedKing>
|
||||
void HalfKP<AssociatedKing>::AppendActiveIndices(
|
||||
const Position& pos, Color perspective, IndexList* active) {
|
||||
@@ -48,7 +48,7 @@ void HalfKP<AssociatedKing>::AppendActiveIndices(
|
||||
}
|
||||
}
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
template <Side AssociatedKing>
|
||||
void HalfKP<AssociatedKing>::AppendChangedIndices(
|
||||
const Position& pos, Color perspective,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量HalfKPの定義
|
||||
//Definition of input features HalfKP of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_FEATURES_HALF_KP_H_
|
||||
#define _NNUE_FEATURES_HALF_KP_H_
|
||||
@@ -14,39 +14,39 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 特徴量HalfKP:自玉または敵玉の位置と、玉以外の駒の位置の組み合わせ
|
||||
// Feature HalfKP: Combination of the position of own ball or enemy ball and the position of pieces other than balls
|
||||
template <Side AssociatedKing>
|
||||
class HalfKP {
|
||||
public:
|
||||
// 特徴量名
|
||||
// feature quantity name
|
||||
static constexpr const char* kName =
|
||||
(AssociatedKing == Side::kFriend) ? "HalfKP(Friend)" : "HalfKP(Enemy)";
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t kHashValue =
|
||||
0x5D69D5B9u ^ (AssociatedKing == Side::kFriend);
|
||||
// 特徴量の次元数
|
||||
// number of feature dimensions
|
||||
static constexpr IndexType kDimensions =
|
||||
static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(fe_end);
|
||||
// 特徴量のうち、同時に値が1となるインデックスの数の最大値
|
||||
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
|
||||
static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING;
|
||||
// 差分計算の代わりに全計算を行うタイミング
|
||||
// Timing of full calculation instead of difference calculation
|
||||
static constexpr TriggerEvent kRefreshTrigger =
|
||||
(AssociatedKing == Side::kFriend) ?
|
||||
TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved;
|
||||
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
static void AppendActiveIndices(const Position& pos, Color perspective,
|
||||
IndexList* active);
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
static void AppendChangedIndices(const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added);
|
||||
|
||||
// 玉の位置とBonaPieceから特徴量のインデックスを求める
|
||||
// Find the index of the feature quantity from the ball position and BonaPiece
|
||||
static IndexType MakeIndex(Square sq_k, BonaPiece p);
|
||||
|
||||
private:
|
||||
// 駒の情報を取得する
|
||||
// Get the piece information
|
||||
static void GetPieces(const Position& pos, Color perspective,
|
||||
BonaPiece** pieces, Square* sq_target_k);
|
||||
};
|
||||
@@ -59,4 +59,4 @@ class HalfKP {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量HalfRelativeKPの定義
|
||||
//Definition of input features HalfRelativeKP of NNUE evaluation function
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 玉の位置とBonaPieceから特徴量のインデックスを求める
|
||||
// Find the index of the feature quantity from the ball position and BonaPiece
|
||||
template <Side AssociatedKing>
|
||||
inline IndexType HalfRelativeKP<AssociatedKing>::MakeIndex(
|
||||
Square sq_k, BonaPiece p) {
|
||||
@@ -24,7 +24,7 @@ inline IndexType HalfRelativeKP<AssociatedKing>::MakeIndex(
|
||||
return H * W * piece_index + H * relative_file + relative_rank;
|
||||
}
|
||||
|
||||
// 駒の情報を取得する
|
||||
// Get the piece information
|
||||
template <Side AssociatedKing>
|
||||
inline void HalfRelativeKP<AssociatedKing>::GetPieces(
|
||||
const Position& pos, Color perspective,
|
||||
@@ -38,11 +38,11 @@ inline void HalfRelativeKP<AssociatedKing>::GetPieces(
|
||||
*sq_target_k = static_cast<Square>(((*pieces)[target] - f_king) % SQUARE_NB);
|
||||
}
|
||||
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
template <Side AssociatedKing>
|
||||
void HalfRelativeKP<AssociatedKing>::AppendActiveIndices(
|
||||
const Position& pos, Color perspective, IndexList* active) {
|
||||
// コンパイラの警告を回避するため、配列サイズが小さい場合は何もしない
|
||||
// do nothing if array size is small to avoid compiler warning
|
||||
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
|
||||
|
||||
BonaPiece* pieces;
|
||||
@@ -57,7 +57,7 @@ void HalfRelativeKP<AssociatedKing>::AppendActiveIndices(
|
||||
}
|
||||
}
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
template <Side AssociatedKing>
|
||||
void HalfRelativeKP<AssociatedKing>::AppendChangedIndices(
|
||||
const Position& pos, Color perspective,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量HalfRelativeKPの定義
|
||||
//Definition of input features HalfRelativeKP of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_FEATURES_HALF_RELATIVE_KP_H_
|
||||
#define _NNUE_FEATURES_HALF_RELATIVE_KP_H_
|
||||
@@ -14,45 +14,45 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 特徴量HalfRelativeKP:自玉または敵玉を基準とした、玉以外の各駒の相対位置
|
||||
// Feature HalfRelativeKP: Relative position of each piece other than the ball based on own ball or enemy ball
|
||||
template <Side AssociatedKing>
|
||||
class HalfRelativeKP {
|
||||
public:
|
||||
// 特徴量名
|
||||
// feature quantity name
|
||||
static constexpr const char* kName = (AssociatedKing == Side::kFriend) ?
|
||||
"HalfRelativeKP(Friend)" : "HalfRelativeKP(Enemy)";
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t kHashValue =
|
||||
0xF9180919u ^ (AssociatedKing == Side::kFriend);
|
||||
// 玉を除いた駒種
|
||||
// Piece type excluding balls
|
||||
static constexpr IndexType kNumPieceKinds = (fe_end - fe_hand_end) / SQUARE_NB;
|
||||
// 玉を中央に置いた仮想的な盤の幅
|
||||
// width of the virtual board with the ball in the center
|
||||
static constexpr IndexType kBoardWidth = FILE_NB * 2 - 1;
|
||||
// 玉を中央に置いた仮想的な盤の高さ
|
||||
// height of a virtual board with balls in the center
|
||||
static constexpr IndexType kBoardHeight = RANK_NB * 2 - 1;
|
||||
// 特徴量の次元数
|
||||
// number of feature dimensions
|
||||
static constexpr IndexType kDimensions =
|
||||
kNumPieceKinds * kBoardHeight * kBoardWidth;
|
||||
// 特徴量のうち、同時に値が1となるインデックスの数の最大値
|
||||
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
|
||||
static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING;
|
||||
// 差分計算の代わりに全計算を行うタイミング
|
||||
// Timing of full calculation instead of difference calculation
|
||||
static constexpr TriggerEvent kRefreshTrigger =
|
||||
(AssociatedKing == Side::kFriend) ?
|
||||
TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved;
|
||||
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
static void AppendActiveIndices(const Position& pos, Color perspective,
|
||||
IndexList* active);
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
static void AppendChangedIndices(const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added);
|
||||
|
||||
// 玉の位置とBonaPieceから特徴量のインデックスを求める
|
||||
// Find the index of the feature quantity from the ball position and BonaPiece
|
||||
static IndexType MakeIndex(Square sq_k, BonaPiece p);
|
||||
|
||||
private:
|
||||
// 駒の情報を取得する
|
||||
// Get the piece information
|
||||
static void GetPieces(const Position& pos, Color perspective,
|
||||
BonaPiece** pieces, Square* sq_target_k);
|
||||
};
|
||||
@@ -65,4 +65,4 @@ class HalfRelativeKP {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// 入力特徴量のインデックスリストの定義
|
||||
// Definition of index list of input features
|
||||
|
||||
#ifndef _NNUE_FEATURES_INDEX_LIST_H_
|
||||
#define _NNUE_FEATURES_INDEX_LIST_H_
|
||||
@@ -14,7 +14,7 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 特徴量のインデックスリストに使うクラステンプレート
|
||||
// Class template used for feature index list
|
||||
template <typename T, std::size_t MaxSize>
|
||||
class ValueList {
|
||||
public:
|
||||
@@ -39,7 +39,7 @@ class ValueList {
|
||||
std::size_t size_ = 0;
|
||||
};
|
||||
|
||||
// 特徴量のインデックスリストの型
|
||||
//Type of feature index list
|
||||
class IndexList
|
||||
: public ValueList<IndexType, RawFeatures::kMaxActiveDimensions> {
|
||||
};
|
||||
@@ -52,4 +52,4 @@ class IndexList
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量Kの定義
|
||||
//Definition of input feature quantity K of NNUE evaluation function
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
|
||||
@@ -11,10 +11,10 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
void K::AppendActiveIndices(
|
||||
const Position& pos, Color perspective, IndexList* active) {
|
||||
// コンパイラの警告を回避するため、配列サイズが小さい場合は何もしない
|
||||
// do nothing if array size is small to avoid compiler warning
|
||||
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
|
||||
|
||||
const BonaPiece* pieces = (perspective == BLACK) ?
|
||||
@@ -27,7 +27,7 @@ void K::AppendActiveIndices(
|
||||
}
|
||||
}
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
void K::AppendChangedIndices(
|
||||
const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量Kの定義
|
||||
//Definition of input feature quantity K of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_FEATURES_K_H_
|
||||
#define _NNUE_FEATURES_K_H_
|
||||
@@ -14,25 +14,25 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 特徴量K:玉の位置
|
||||
// Feature K: Ball position
|
||||
class K {
|
||||
public:
|
||||
// 特徴量名
|
||||
// feature quantity name
|
||||
static constexpr const char* kName = "K";
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t kHashValue = 0xD3CEE169u;
|
||||
// 特徴量の次元数
|
||||
// number of feature dimensions
|
||||
static constexpr IndexType kDimensions = SQUARE_NB * 2;
|
||||
// 特徴量のうち、同時に値が1となるインデックスの数の最大値
|
||||
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
|
||||
static constexpr IndexType kMaxActiveDimensions = 2;
|
||||
// 差分計算の代わりに全計算を行うタイミング
|
||||
// Timing of full calculation instead of difference calculation
|
||||
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone;
|
||||
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
static void AppendActiveIndices(const Position& pos, Color perspective,
|
||||
IndexList* active);
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
static void AppendChangedIndices(const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added);
|
||||
};
|
||||
@@ -45,4 +45,4 @@ class K {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量Pの定義
|
||||
//Definition of input feature P of NNUE evaluation function
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
|
||||
@@ -11,10 +11,10 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
void P::AppendActiveIndices(
|
||||
const Position& pos, Color perspective, IndexList* active) {
|
||||
// コンパイラの警告を回避するため、配列サイズが小さい場合は何もしない
|
||||
// do nothing if array size is small to avoid compiler warning
|
||||
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
|
||||
|
||||
const BonaPiece* pieces = (perspective == BLACK) ?
|
||||
@@ -27,7 +27,7 @@ void P::AppendActiveIndices(
|
||||
}
|
||||
}
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
void P::AppendChangedIndices(
|
||||
const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量Pの定義
|
||||
//Definition of input feature P of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_FEATURES_P_H_
|
||||
#define _NNUE_FEATURES_P_H_
|
||||
@@ -14,25 +14,25 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 特徴量P:玉以外の駒のBonaPiece
|
||||
// Feature P: BonaPiece of pieces other than balls
|
||||
class P {
|
||||
public:
|
||||
// 特徴量名
|
||||
// feature quantity name
|
||||
static constexpr const char* kName = "P";
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t kHashValue = 0x764CFB4Bu;
|
||||
// 特徴量の次元数
|
||||
// number of feature dimensions
|
||||
static constexpr IndexType kDimensions = fe_end;
|
||||
// 特徴量のうち、同時に値が1となるインデックスの数の最大値
|
||||
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
|
||||
static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING;
|
||||
// 差分計算の代わりに全計算を行うタイミング
|
||||
// Timing of full calculation instead of difference calculation
|
||||
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone;
|
||||
|
||||
// 特徴量のうち、値が1であるインデックスのリストを取得する
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
static void AppendActiveIndices(const Position& pos, Color perspective,
|
||||
IndexList* active);
|
||||
|
||||
// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
static void AppendChangedIndices(const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added);
|
||||
};
|
||||
@@ -45,4 +45,4 @@ class P {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の層AffineTransformの定義
|
||||
// Definition of layer AffineTransform of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_LAYERS_AFFINE_TRANSFORM_H_
|
||||
#define _NNUE_LAYERS_AFFINE_TRANSFORM_H_
|
||||
@@ -13,31 +13,31 @@ namespace NNUE {
|
||||
|
||||
namespace Layers {
|
||||
|
||||
// アフィン変換層
|
||||
// affine transformation layer
|
||||
template <typename PreviousLayer, IndexType OutputDimensions>
|
||||
class AffineTransform {
|
||||
public:
|
||||
// 入出力の型
|
||||
// Input/output type
|
||||
using InputType = typename PreviousLayer::OutputType;
|
||||
using OutputType = std::int32_t;
|
||||
static_assert(std::is_same<InputType, std::uint8_t>::value, "");
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kInputDimensions =
|
||||
PreviousLayer::kOutputDimensions;
|
||||
static constexpr IndexType kOutputDimensions = OutputDimensions;
|
||||
static constexpr IndexType kPaddedInputDimensions =
|
||||
CeilToMultiple<IndexType>(kInputDimensions, kMaxSimdWidth);
|
||||
|
||||
// この層で使用する順伝播用バッファのサイズ
|
||||
// Size of forward propagation buffer used in this layer
|
||||
static constexpr std::size_t kSelfBufferSize =
|
||||
CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize);
|
||||
|
||||
// 入力層からこの層までで使用する順伝播用バッファのサイズ
|
||||
// Size of the forward propagation buffer used from the input layer to this layer
|
||||
static constexpr std::size_t kBufferSize =
|
||||
PreviousLayer::kBufferSize + kSelfBufferSize;
|
||||
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t GetHashValue() {
|
||||
std::uint32_t hash_value = 0xCC03DAE4u;
|
||||
hash_value += kOutputDimensions;
|
||||
@@ -46,7 +46,7 @@ class AffineTransform {
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
// 入力層からこの層までの構造を表す文字列
|
||||
// A string that represents the structure from the input layer to this layer
|
||||
static std::string GetStructureString() {
|
||||
return "AffineTransform[" +
|
||||
std::to_string(kOutputDimensions) + "<-" +
|
||||
@@ -54,7 +54,7 @@ class AffineTransform {
|
||||
PreviousLayer::GetStructureString() + ")";
|
||||
}
|
||||
|
||||
// パラメータを読み込む
|
||||
// read parameters
|
||||
bool ReadParameters(std::istream& stream) {
|
||||
if (!previous_layer_.ReadParameters(stream)) return false;
|
||||
stream.read(reinterpret_cast<char*>(biases_),
|
||||
@@ -65,7 +65,7 @@ class AffineTransform {
|
||||
return !stream.fail();
|
||||
}
|
||||
|
||||
// パラメータを書き込む
|
||||
// write parameters
|
||||
bool WriteParameters(std::ostream& stream) const {
|
||||
if (!previous_layer_.WriteParameters(stream)) return false;
|
||||
stream.write(reinterpret_cast<const char*>(biases_),
|
||||
@@ -76,7 +76,7 @@ class AffineTransform {
|
||||
return !stream.fail();
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
const OutputType* Propagate(
|
||||
const TransformedFeatureType* transformed_features, char* buffer) const {
|
||||
const auto input = previous_layer_.Propagate(
|
||||
@@ -151,17 +151,17 @@ class AffineTransform {
|
||||
}
|
||||
|
||||
private:
|
||||
// パラメータの型
|
||||
// parameter type
|
||||
using BiasType = OutputType;
|
||||
using WeightType = std::int8_t;
|
||||
|
||||
// 学習用クラスをfriendにする
|
||||
// Make the learning class a friend
|
||||
friend class Trainer<AffineTransform>;
|
||||
|
||||
// この層の直前の層
|
||||
// the layer immediately before this layer
|
||||
PreviousLayer previous_layer_;
|
||||
|
||||
// パラメータ
|
||||
// parameter
|
||||
alignas(kCacheLineSize) BiasType biases_[kOutputDimensions];
|
||||
alignas(kCacheLineSize)
|
||||
WeightType weights_[kOutputDimensions * kPaddedInputDimensions];
|
||||
@@ -175,4 +175,4 @@ class AffineTransform {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の層ClippedReLUの定義
|
||||
// Definition of layer ClippedReLU of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_LAYERS_CLIPPED_RELU_H_
|
||||
#define _NNUE_LAYERS_CLIPPED_RELU_H_
|
||||
@@ -17,49 +17,49 @@ namespace Layers {
|
||||
template <typename PreviousLayer>
|
||||
class ClippedReLU {
|
||||
public:
|
||||
// 入出力の型
|
||||
// Input/output type
|
||||
using InputType = typename PreviousLayer::OutputType;
|
||||
using OutputType = std::uint8_t;
|
||||
static_assert(std::is_same<InputType, std::int32_t>::value, "");
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kInputDimensions =
|
||||
PreviousLayer::kOutputDimensions;
|
||||
static constexpr IndexType kOutputDimensions = kInputDimensions;
|
||||
|
||||
// この層で使用する順伝播用バッファのサイズ
|
||||
// Size of forward propagation buffer used in this layer
|
||||
static constexpr std::size_t kSelfBufferSize =
|
||||
CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize);
|
||||
|
||||
// 入力層からこの層までで使用する順伝播用バッファのサイズ
|
||||
// Size of the forward propagation buffer used from the input layer to this layer
|
||||
static constexpr std::size_t kBufferSize =
|
||||
PreviousLayer::kBufferSize + kSelfBufferSize;
|
||||
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t GetHashValue() {
|
||||
std::uint32_t hash_value = 0x538D24C7u;
|
||||
hash_value += PreviousLayer::GetHashValue();
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
// 入力層からこの層までの構造を表す文字列
|
||||
// A string that represents the structure from the input layer to this layer
|
||||
static std::string GetStructureString() {
|
||||
return "ClippedReLU[" +
|
||||
std::to_string(kOutputDimensions) + "](" +
|
||||
PreviousLayer::GetStructureString() + ")";
|
||||
}
|
||||
|
||||
// パラメータを読み込む
|
||||
// read parameters
|
||||
bool ReadParameters(std::istream& stream) {
|
||||
return previous_layer_.ReadParameters(stream);
|
||||
}
|
||||
|
||||
// パラメータを書き込む
|
||||
// write parameters
|
||||
bool WriteParameters(std::ostream& stream) const {
|
||||
return previous_layer_.WriteParameters(stream);
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
const OutputType* Propagate(
|
||||
const TransformedFeatureType* transformed_features, char* buffer) const {
|
||||
const auto input = previous_layer_.Propagate(
|
||||
@@ -150,10 +150,10 @@ class ClippedReLU {
|
||||
}
|
||||
|
||||
private:
|
||||
// 学習用クラスをfriendにする
|
||||
// Make the learning class a friend
|
||||
friend class Trainer<ClippedReLU>;
|
||||
|
||||
// この層の直前の層
|
||||
// the layer immediately before this layer
|
||||
PreviousLayer previous_layer_;
|
||||
};
|
||||
|
||||
@@ -165,4 +165,4 @@ class ClippedReLU {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の層InputSliceの定義
|
||||
// NNUE evaluation function layer InputSlice definition
|
||||
|
||||
#ifndef _NNUE_LAYERS_INPUT_SLICE_H_
|
||||
#define _NNUE_LAYERS_INPUT_SLICE_H_
|
||||
@@ -13,47 +13,47 @@ namespace NNUE {
|
||||
|
||||
namespace Layers {
|
||||
|
||||
// 入力層
|
||||
// input layer
|
||||
template <IndexType OutputDimensions, IndexType Offset = 0>
|
||||
class InputSlice {
|
||||
public:
|
||||
// アライメントを維持する必要がある
|
||||
// need to maintain alignment
|
||||
static_assert(Offset % kMaxSimdWidth == 0, "");
|
||||
|
||||
// 出力の型
|
||||
// output type
|
||||
using OutputType = TransformedFeatureType;
|
||||
|
||||
// 出力の次元数
|
||||
// output dimensionality
|
||||
static constexpr IndexType kOutputDimensions = OutputDimensions;
|
||||
|
||||
// 入力層からこの層までで使用する順伝播用バッファのサイズ
|
||||
// Size of the forward propagation buffer used from the input layer to this layer
|
||||
static constexpr std::size_t kBufferSize = 0;
|
||||
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t GetHashValue() {
|
||||
std::uint32_t hash_value = 0xEC42E90Du;
|
||||
hash_value ^= kOutputDimensions ^ (Offset << 10);
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
// 入力層からこの層までの構造を表す文字列
|
||||
// A string that represents the structure from the input layer to this layer
|
||||
static std::string GetStructureString() {
|
||||
return "InputSlice[" + std::to_string(kOutputDimensions) + "(" +
|
||||
std::to_string(Offset) + ":" +
|
||||
std::to_string(Offset + kOutputDimensions) + ")]";
|
||||
}
|
||||
|
||||
// パラメータを読み込む
|
||||
// read parameters
|
||||
bool ReadParameters(std::istream& /*stream*/) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// パラメータを書き込む
|
||||
// write parameters
|
||||
bool WriteParameters(std::ostream& /*stream*/) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
const OutputType* Propagate(
|
||||
const TransformedFeatureType* transformed_features,
|
||||
char* /*buffer*/) const {
|
||||
@@ -71,4 +71,4 @@ class InputSlice {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の層Sumの定義
|
||||
// Definition of layer Sum of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_LAYERS_SUM_H_
|
||||
#define _NNUE_LAYERS_SUM_H_
|
||||
@@ -13,7 +13,7 @@ namespace NNUE {
|
||||
|
||||
namespace Layers {
|
||||
|
||||
// 複数の層の出力の和を取る層
|
||||
// Layer that sums the output of multiple layers
|
||||
template <typename FirstPreviousLayer, typename... RemainingPreviousLayers>
|
||||
class Sum : public Sum<RemainingPreviousLayers...> {
|
||||
private:
|
||||
@@ -21,25 +21,25 @@ class Sum : public Sum<RemainingPreviousLayers...> {
|
||||
using Tail = Sum<RemainingPreviousLayers...>;
|
||||
|
||||
public:
|
||||
// 入出力の型
|
||||
// Input/output type
|
||||
using InputType = typename Head::OutputType;
|
||||
using OutputType = InputType;
|
||||
static_assert(std::is_same<InputType, typename Tail::InputType>::value, "");
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kInputDimensions = Head::kOutputDimensions;
|
||||
static constexpr IndexType kOutputDimensions = kInputDimensions;
|
||||
static_assert(kInputDimensions == Tail::kInputDimensions , "");
|
||||
static_assert(kInputDimensions == Tail::kInputDimensions ,"");
|
||||
|
||||
// この層で使用する順伝播用バッファのサイズ
|
||||
// Size of forward propagation buffer used in this layer
|
||||
static constexpr std::size_t kSelfBufferSize =
|
||||
CeilToMultiple(kOutputDimensions * sizeof(OutputType), kCacheLineSize);
|
||||
|
||||
// 入力層からこの層までで使用する順伝播用バッファのサイズ
|
||||
// Size of the forward propagation buffer used from the input layer to this layer
|
||||
static constexpr std::size_t kBufferSize =
|
||||
std::max(Head::kBufferSize + kSelfBufferSize, Tail::kBufferSize);
|
||||
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t GetHashValue() {
|
||||
std::uint32_t hash_value = 0xBCE400B4u;
|
||||
hash_value ^= Head::GetHashValue() >> 1;
|
||||
@@ -49,67 +49,67 @@ class Sum : public Sum<RemainingPreviousLayers...> {
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
// 入力層からこの層までの構造を表す文字列
|
||||
// A string that represents the structure from the input layer to this layer
|
||||
static std::string GetStructureString() {
|
||||
return "Sum[" +
|
||||
std::to_string(kOutputDimensions) + "](" + GetSummandsString() + ")";
|
||||
}
|
||||
|
||||
// パラメータを読み込む
|
||||
// read parameters
|
||||
bool ReadParameters(std::istream& stream) {
|
||||
if (!Tail::ReadParameters(stream)) return false;
|
||||
return previous_layer_.ReadParameters(stream);
|
||||
}
|
||||
|
||||
// パラメータを書き込む
|
||||
// write parameters
|
||||
bool WriteParameters(std::ostream& stream) const {
|
||||
if (!Tail::WriteParameters(stream)) return false;
|
||||
return previous_layer_.WriteParameters(stream);
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
const OutputType* Propagate(
|
||||
const TransformedFeatureType* transformed_features, char* buffer) const {
|
||||
Tail::Propagate(transformed_features, buffer);
|
||||
const auto head_output = previous_layer_.Propagate(
|
||||
transformed_features, buffer + kSelfBufferSize);
|
||||
const auto output = reinterpret_cast<OutputType*>(buffer);
|
||||
for (IndexType i = 0; i < kOutputDimensions; ++i) {
|
||||
for (IndexType i = 0; i <kOutputDimensions; ++i) {
|
||||
output[i] += head_output[i];
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
protected:
|
||||
// 和を取る対象となる層のリストを表す文字列
|
||||
// A string that represents the list of layers to be summed
|
||||
static std::string GetSummandsString() {
|
||||
return Head::GetStructureString() + "," + Tail::GetSummandsString();
|
||||
}
|
||||
|
||||
// 学習用クラスをfriendにする
|
||||
// Make the learning class a friend
|
||||
friend class Trainer<Sum>;
|
||||
|
||||
// この層の直前の層
|
||||
// the layer immediately before this layer
|
||||
FirstPreviousLayer previous_layer_;
|
||||
};
|
||||
|
||||
// 複数の層の出力の和を取る層(テンプレート引数が1つの場合)
|
||||
// Layer that sums the output of multiple layers (when there is one template argument)
|
||||
template <typename PreviousLayer>
|
||||
class Sum<PreviousLayer> {
|
||||
public:
|
||||
// 入出力の型
|
||||
// Input/output type
|
||||
using InputType = typename PreviousLayer::OutputType;
|
||||
using OutputType = InputType;
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kInputDimensions =
|
||||
PreviousLayer::kOutputDimensions;
|
||||
static constexpr IndexType kOutputDimensions = kInputDimensions;
|
||||
|
||||
// 入力層からこの層までで使用する順伝播用バッファのサイズ
|
||||
// Size of the forward propagation buffer used from the input layer to this layer
|
||||
static constexpr std::size_t kBufferSize = PreviousLayer::kBufferSize;
|
||||
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t GetHashValue() {
|
||||
std::uint32_t hash_value = 0xBCE400B4u;
|
||||
hash_value ^= PreviousLayer::GetHashValue() >> 1;
|
||||
@@ -117,38 +117,38 @@ class Sum<PreviousLayer> {
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
// 入力層からこの層までの構造を表す文字列
|
||||
// A string that represents the structure from the input layer to this layer
|
||||
static std::string GetStructureString() {
|
||||
return "Sum[" +
|
||||
std::to_string(kOutputDimensions) + "](" + GetSummandsString() + ")";
|
||||
}
|
||||
|
||||
// パラメータを読み込む
|
||||
// read parameters
|
||||
bool ReadParameters(std::istream& stream) {
|
||||
return previous_layer_.ReadParameters(stream);
|
||||
}
|
||||
|
||||
// パラメータを書き込む
|
||||
// write parameters
|
||||
bool WriteParameters(std::ostream& stream) const {
|
||||
return previous_layer_.WriteParameters(stream);
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
const OutputType* Propagate(
|
||||
const TransformedFeatureType* transformed_features, char* buffer) const {
|
||||
return previous_layer_.Propagate(transformed_features, buffer);
|
||||
}
|
||||
|
||||
protected:
|
||||
// 和を取る対象となる層のリストを表す文字列
|
||||
// A string that represents the list of layers to be summed
|
||||
static std::string GetSummandsString() {
|
||||
return PreviousLayer::GetStructureString();
|
||||
}
|
||||
|
||||
// 学習用クラスをfriendにする
|
||||
// Make the learning class a friend
|
||||
friend class Trainer<Sum>;
|
||||
|
||||
// この層の直前の層
|
||||
// the layer immediately before this layer
|
||||
PreviousLayer previous_layer_;
|
||||
};
|
||||
|
||||
@@ -160,4 +160,4 @@ class Sum<PreviousLayer> {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の差分計算用のクラス
|
||||
// Class for difference calculation of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_ACCUMULATOR_H_
|
||||
#define _NNUE_ACCUMULATOR_H_
|
||||
@@ -11,8 +11,8 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 入力特徴量をアフィン変換した結果を保持するクラス
|
||||
// 最終的な出力である評価値も一緒に持たせておく
|
||||
// Class that holds the result of affine transformation of input features
|
||||
// Keep the evaluation value that is the final output together
|
||||
struct alignas(32) Accumulator {
|
||||
std::int16_t
|
||||
accumulation[2][kRefreshTriggers.size()][kTransformedFeatureDimensions];
|
||||
@@ -27,4 +27,4 @@ struct alignas(32) Accumulator {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,11 +1,11 @@
|
||||
// NNUE評価関数で用いる入力特徴量とネットワーク構造
|
||||
// Input features and network structure used in NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_ARCHITECTURE_H_
|
||||
#define _NNUE_ARCHITECTURE_H_
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
|
||||
// 入力特徴量とネットワーク構造が定義されたヘッダをincludeする
|
||||
// include a header that defines the input features and network structure
|
||||
//#include "architectures/k-p_256x2-32-32.h"
|
||||
//#include "architectures/k-p-cr_256x2-32-32.h"
|
||||
//#include "architectures/k-p-cr-ep_256x2-32-32.h"
|
||||
@@ -20,7 +20,7 @@ static_assert(kTransformedFeatureDimensions % kMaxSimdWidth == 0, "");
|
||||
static_assert(Network::kOutputDimensions == 1, "");
|
||||
static_assert(std::is_same<Network::OutputType, std::int32_t>::value, "");
|
||||
|
||||
// 差分計算の代わりに全計算を行うタイミングのリスト
|
||||
// List of timings to perform all calculations instead of difference calculation
|
||||
constexpr auto kRefreshTriggers = RawFeatures::kRefreshTriggers;
|
||||
|
||||
} // namespace NNUE
|
||||
@@ -29,4 +29,4 @@ constexpr auto kRefreshTriggers = RawFeatures::kRefreshTriggers;
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数で用いる定数など
|
||||
// Constants used in NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_COMMON_H_
|
||||
#define _NNUE_COMMON_H_
|
||||
@@ -15,17 +15,17 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 評価関数ファイルのバージョンを表す定数
|
||||
// A constant that represents the version of the evaluation function file
|
||||
constexpr std::uint32_t kVersion = 0x7AF32F16u;
|
||||
|
||||
// 評価値の計算で利用する定数
|
||||
// Constant used in evaluation value calculation
|
||||
constexpr int FV_SCALE = 16;
|
||||
constexpr int kWeightScaleBits = 6;
|
||||
|
||||
// キャッシュラインのサイズ(バイト単位)
|
||||
// Size of cache line (in bytes)
|
||||
constexpr std::size_t kCacheLineSize = 64;
|
||||
|
||||
// SIMD幅(バイト単位)
|
||||
// SIMD width (in bytes)
|
||||
#if defined(USE_AVX2)
|
||||
constexpr std::size_t kSimdWidth = 32;
|
||||
#elif defined(USE_SSE2)
|
||||
@@ -35,17 +35,17 @@ constexpr std::size_t kSimdWidth = 16;
|
||||
#endif
|
||||
constexpr std::size_t kMaxSimdWidth = 32;
|
||||
|
||||
// 変換後の入力特徴量の型
|
||||
// Type of input feature after conversion
|
||||
using TransformedFeatureType = std::uint8_t;
|
||||
|
||||
// インデックスの型
|
||||
// index type
|
||||
using IndexType = std::uint32_t;
|
||||
|
||||
// 学習用クラステンプレートの前方宣言
|
||||
// Forward declaration of learning class template
|
||||
template <typename Layer>
|
||||
class Trainer;
|
||||
|
||||
// n以上で最小のbaseの倍数を求める
|
||||
// find the smallest multiple of n and above
|
||||
template <typename IntType>
|
||||
constexpr IntType CeilToMultiple(IntType n, IntType base) {
|
||||
return (n + base - 1) / base * base;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の入力特徴量の変換を行うクラス
|
||||
// A class that converts the input features of the NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_FEATURE_TRANSFORMER_H_
|
||||
#define _NNUE_FEATURE_TRANSFORMER_H_
|
||||
@@ -15,37 +15,37 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 入力特徴量変換器
|
||||
// Input feature converter
|
||||
class FeatureTransformer {
|
||||
private:
|
||||
// 片側分の出力の次元数
|
||||
// number of output dimensions for one side
|
||||
static constexpr IndexType kHalfDimensions = kTransformedFeatureDimensions;
|
||||
|
||||
public:
|
||||
// 出力の型
|
||||
// output type
|
||||
using OutputType = TransformedFeatureType;
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kInputDimensions = RawFeatures::kDimensions;
|
||||
static constexpr IndexType kOutputDimensions = kHalfDimensions * 2;
|
||||
|
||||
// 順伝播用バッファのサイズ
|
||||
// size of forward propagation buffer
|
||||
static constexpr std::size_t kBufferSize =
|
||||
kOutputDimensions * sizeof(OutputType);
|
||||
|
||||
// 評価関数ファイルに埋め込むハッシュ値
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t GetHashValue() {
|
||||
return RawFeatures::kHashValue ^ kOutputDimensions;
|
||||
}
|
||||
|
||||
// 構造を表す文字列
|
||||
// a string representing the structure
|
||||
static std::string GetStructureString() {
|
||||
return RawFeatures::GetName() + "[" +
|
||||
std::to_string(kInputDimensions) + "->" +
|
||||
std::to_string(kHalfDimensions) + "x2]";
|
||||
}
|
||||
|
||||
// パラメータを読み込む
|
||||
// read parameters
|
||||
bool ReadParameters(std::istream& stream) {
|
||||
stream.read(reinterpret_cast<char*>(biases_),
|
||||
kHalfDimensions * sizeof(BiasType));
|
||||
@@ -54,7 +54,7 @@ class FeatureTransformer {
|
||||
return !stream.fail();
|
||||
}
|
||||
|
||||
// パラメータを書き込む
|
||||
// write parameters
|
||||
bool WriteParameters(std::ostream& stream) const {
|
||||
stream.write(reinterpret_cast<const char*>(biases_),
|
||||
kHalfDimensions * sizeof(BiasType));
|
||||
@@ -63,7 +63,7 @@ class FeatureTransformer {
|
||||
return !stream.fail();
|
||||
}
|
||||
|
||||
// 可能なら差分計算を進める
|
||||
// proceed with the difference calculation if possible
|
||||
bool UpdateAccumulatorIfPossible(const Position& pos) const {
|
||||
const auto now = pos.state();
|
||||
if (now->accumulator.computed_accumulation) {
|
||||
@@ -77,7 +77,7 @@ class FeatureTransformer {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 入力特徴量を変換する
|
||||
// convert input features
|
||||
void Transform(const Position& pos, OutputType* output, bool refresh) const {
|
||||
if (refresh || !UpdateAccumulatorIfPossible(pos)) {
|
||||
RefreshAccumulator(pos);
|
||||
@@ -174,7 +174,7 @@ class FeatureTransformer {
|
||||
}
|
||||
|
||||
private:
|
||||
// 差分計算を用いずに累積値を計算する
|
||||
// Calculate cumulative value without using difference calculation
|
||||
void RefreshAccumulator(const Position& pos) const {
|
||||
auto& accumulator = pos.state()->accumulator;
|
||||
for (IndexType i = 0; i < kRefreshTriggers.size(); ++i) {
|
||||
@@ -232,7 +232,7 @@ class FeatureTransformer {
|
||||
accumulator.computed_score = false;
|
||||
}
|
||||
|
||||
// 差分計算を用いて累積値を計算する
|
||||
// Calculate cumulative value using difference calculation
|
||||
void UpdateAccumulator(const Position& pos) const {
|
||||
const auto prev_accumulator = pos.state()->previous->accumulator;
|
||||
auto& accumulator = pos.state()->accumulator;
|
||||
@@ -263,7 +263,7 @@ class FeatureTransformer {
|
||||
std::memset(accumulator.accumulation[perspective][i], 0,
|
||||
kHalfDimensions * sizeof(BiasType));
|
||||
}
|
||||
} else { // 1から0に変化した特徴量に関する差分計算
|
||||
} else {// Difference calculation for the feature amount changed from 1 to 0
|
||||
std::memcpy(accumulator.accumulation[perspective][i],
|
||||
prev_accumulator.accumulation[perspective][i],
|
||||
kHalfDimensions * sizeof(BiasType));
|
||||
@@ -292,7 +292,7 @@ class FeatureTransformer {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
{ // 0から1に変化した特徴量に関する差分計算
|
||||
{// Difference calculation for features that changed from 0 to 1
|
||||
for (const auto index : added_indices[perspective]) {
|
||||
const IndexType offset = kHalfDimensions * index;
|
||||
#if defined(USE_AVX2)
|
||||
@@ -325,14 +325,14 @@ class FeatureTransformer {
|
||||
accumulator.computed_score = false;
|
||||
}
|
||||
|
||||
// パラメータの型
|
||||
// parameter type
|
||||
using BiasType = std::int16_t;
|
||||
using WeightType = std::int16_t;
|
||||
|
||||
// 学習用クラスをfriendにする
|
||||
// Make the learning class a friend
|
||||
friend class Trainer<FeatureTransformer>;
|
||||
|
||||
// パラメータ
|
||||
// parameter
|
||||
alignas(kCacheLineSize) BiasType biases_[kHalfDimensions];
|
||||
alignas(kCacheLineSize)
|
||||
WeightType weights_[kHalfDimensions * kInputDimensions];
|
||||
@@ -344,4 +344,4 @@ class FeatureTransformer {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数に関するUSI拡張コマンド
|
||||
// USI extended command for NNUE evaluation function
|
||||
|
||||
#if defined(ENABLE_TEST_CMD) && defined(EVAL_NNUE)
|
||||
|
||||
@@ -19,15 +19,15 @@ namespace NNUE {
|
||||
|
||||
namespace {
|
||||
|
||||
// 主に差分計算に関するRawFeaturesのテスト
|
||||
// Testing RawFeatures mainly for difference calculation
|
||||
void TestFeatures(Position& pos) {
|
||||
const std::uint64_t num_games = 1000;
|
||||
StateInfo si;
|
||||
pos.set(StartFEN, false, &si, Threads.main());
|
||||
const int MAX_PLY = 256; // 256手までテスト
|
||||
const int MAX_PLY = 256; // test up to 256 hands
|
||||
|
||||
StateInfo state[MAX_PLY]; // StateInfoを最大手数分だけ
|
||||
int ply; // 初期局面からの手数
|
||||
StateInfo state[MAX_PLY]; // StateInfo only for the maximum number of steps
|
||||
int ply; // Trouble from the initial phase
|
||||
|
||||
PRNG prng(20171128);
|
||||
|
||||
@@ -96,13 +96,13 @@ void TestFeatures(Position& pos) {
|
||||
for (std::uint64_t i = 0; i < num_games; ++i) {
|
||||
auto index_sets = make_index_sets(pos);
|
||||
for (ply = 0; ply < MAX_PLY; ++ply) {
|
||||
MoveList<LEGAL> mg(pos); // 全合法手の生成
|
||||
MoveList<LEGAL> mg(pos); // Generate all legal hands
|
||||
|
||||
// 合法な指し手がなかった == 詰み
|
||||
// There was no legal move == Clog
|
||||
if (mg.size() == 0)
|
||||
break;
|
||||
|
||||
// 生成された指し手のなかからランダムに選び、その指し手で局面を進める。
|
||||
// Randomly choose from the generated moves and advance the phase with the moves.
|
||||
Move m = mg.begin()[prng.rand(mg.size())];
|
||||
pos.do_move(m, state[ply]);
|
||||
|
||||
@@ -113,7 +113,7 @@ void TestFeatures(Position& pos) {
|
||||
|
||||
pos.set(StartFEN, false, &si, Threads.main());
|
||||
|
||||
// 100回に1回ごとに'.'を出力(進んでいることがわかるように)
|
||||
// Output'.' every 100 times (so you can see that it's progressing)
|
||||
if ((i % 100) == 0)
|
||||
std::cout << "." << std::flush;
|
||||
}
|
||||
@@ -141,7 +141,7 @@ void TestFeatures(Position& pos) {
|
||||
<< ") features" << std::endl;
|
||||
}
|
||||
|
||||
// 評価関数の構造を表す文字列を出力する
|
||||
// Output a string that represents the structure of the evaluation function
|
||||
void PrintInfo(std::istream& stream) {
|
||||
std::cout << "network architecture: " << GetArchitectureString() << std::endl;
|
||||
|
||||
@@ -178,7 +178,7 @@ void PrintInfo(std::istream& stream) {
|
||||
|
||||
} // namespace
|
||||
|
||||
// NNUE評価関数に関するUSI拡張コマンド
|
||||
// USI extended command for NNUE evaluation function
|
||||
void TestCommand(Position& pos, std::istream& stream) {
|
||||
std::string sub_command;
|
||||
stream >> sub_command;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数に関するUSI拡張コマンドのインターフェイス
|
||||
// USI extended command interface for NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_TEST_COMMAND_H_
|
||||
#define _NNUE_TEST_COMMAND_H_
|
||||
@@ -9,7 +9,7 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// NNUE評価関数に関するUSI拡張コマンド
|
||||
// USI extended command for NNUE evaluation function
|
||||
void TestCommand(Position& pos, std::istream& stream);
|
||||
|
||||
} // namespace NNUE
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の特徴量変換クラステンプレート
|
||||
// NNUE evaluation function feature conversion class template
|
||||
|
||||
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_H_
|
||||
#define _NNUE_TRAINER_FEATURES_FACTORIZER_H_
|
||||
@@ -14,31 +14,31 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 入力特徴量を学習用特徴量に変換するクラステンプレート
|
||||
// デフォルトでは学習用特徴量は元の入力特徴量と同じとし、必要に応じて特殊化する
|
||||
// Class template that converts input features into learning features
|
||||
// By default, the learning feature is the same as the original input feature, and specialized as necessary
|
||||
template <typename FeatureType>
|
||||
class Factorizer {
|
||||
public:
|
||||
// 学習用特徴量の次元数を取得する
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return FeatureType::kDimensions;
|
||||
}
|
||||
|
||||
// 学習用特徴量のインデックスと学習率のスケールを取得する
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features) {
|
||||
assert(base_index < FeatureType::kDimensions);
|
||||
assert(base_index <FeatureType::kDimensions);
|
||||
training_features->emplace_back(base_index);
|
||||
}
|
||||
};
|
||||
|
||||
// 学習用特徴量の情報
|
||||
// Learning feature information
|
||||
struct FeatureProperties {
|
||||
bool active;
|
||||
IndexType dimensions;
|
||||
};
|
||||
|
||||
// 元の入力特徴量を学習用特徴量に追加する
|
||||
// Add the original input features to the learning features
|
||||
template <typename FeatureType>
|
||||
IndexType AppendBaseFeature(
|
||||
FeatureProperties properties, IndexType base_index,
|
||||
@@ -49,7 +49,7 @@ IndexType AppendBaseFeature(
|
||||
return properties.dimensions;
|
||||
}
|
||||
|
||||
// 学習率のスケールが0でなければ他の種類の学習用特徴量を引き継ぐ
|
||||
// If the learning rate scale is not 0, inherit other types of learning features
|
||||
template <typename FeatureType>
|
||||
IndexType InheritFeaturesIfRequired(
|
||||
IndexType index_offset, FeatureProperties properties, IndexType base_index,
|
||||
@@ -70,8 +70,8 @@ IndexType InheritFeaturesIfRequired(
|
||||
return properties.dimensions;
|
||||
}
|
||||
|
||||
// 学習用特徴量を追加せず、必要に応じてインデックスの差分を返す
|
||||
// 対応する特徴量がない場合にInheritFeaturesIfRequired()の代わりに呼ぶ
|
||||
// Return the index difference as needed, without adding learning features
|
||||
// Call instead of InheritFeaturesIfRequired() if there are no corresponding features
|
||||
IndexType SkipFeatures(FeatureProperties properties) {
|
||||
if (!properties.active) {
|
||||
return 0;
|
||||
@@ -79,7 +79,7 @@ IndexType SkipFeatures(FeatureProperties properties) {
|
||||
return properties.dimensions;
|
||||
}
|
||||
|
||||
// 学習用特徴量の次元数を取得する
|
||||
// Get the dimensionality of the learning feature
|
||||
template <std::size_t N>
|
||||
constexpr IndexType GetActiveDimensions(
|
||||
const FeatureProperties (&properties)[N]) {
|
||||
@@ -93,7 +93,7 @@ constexpr IndexType GetActiveDimensions(
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
// 配列の要素数を取得する
|
||||
// get the number of elements in the array
|
||||
template <typename T, std::size_t N>
|
||||
constexpr std::size_t GetArrayLength(const T (&/*array*/)[N]) {
|
||||
return N;
|
||||
@@ -107,4 +107,4 @@ constexpr std::size_t GetArrayLength(const T (&/*array*/)[N]) {
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の特徴量変換クラステンプレートのFeatureSet用特殊化
|
||||
// Specialization for feature set of feature conversion class template of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_FEATURE_SET_H_
|
||||
#define _NNUE_TRAINER_FEATURES_FACTORIZER_FEATURE_SET_H_
|
||||
@@ -14,8 +14,8 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 入力特徴量を学習用特徴量に変換するクラステンプレート
|
||||
// FeatureSet用特殊化
|
||||
// Class template that converts input features into learning features
|
||||
// Specialization for FeatureSet
|
||||
template <typename FirstFeatureType, typename... RemainingFeatureTypes>
|
||||
class Factorizer<FeatureSet<FirstFeatureType, RemainingFeatureTypes...>> {
|
||||
private:
|
||||
@@ -23,16 +23,16 @@ class Factorizer<FeatureSet<FirstFeatureType, RemainingFeatureTypes...>> {
|
||||
using Tail = Factorizer<FeatureSet<RemainingFeatureTypes...>>;
|
||||
|
||||
public:
|
||||
// 元の入力特徴量の次元数
|
||||
// number of dimensions of original input features
|
||||
static constexpr IndexType kBaseDimensions =
|
||||
FeatureSet<FirstFeatureType, RemainingFeatureTypes...>::kDimensions;
|
||||
|
||||
// 学習用特徴量の次元数を取得する
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return Head::GetDimensions() + Tail::GetDimensions();
|
||||
}
|
||||
|
||||
// 学習用特徴量のインデックスと学習率のスケールを取得する
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features,
|
||||
IndexType base_dimensions = kBaseDimensions) {
|
||||
@@ -62,20 +62,20 @@ class Factorizer<FeatureSet<FirstFeatureType, RemainingFeatureTypes...>> {
|
||||
}
|
||||
};
|
||||
|
||||
// 入力特徴量を学習用特徴量に変換するクラステンプレート
|
||||
// FeatureSetのテンプレート引数が1つの場合の特殊化
|
||||
// Class template that converts input features into learning features
|
||||
// Specialization when FeatureSet has one template argument
|
||||
template <typename FeatureType>
|
||||
class Factorizer<FeatureSet<FeatureType>> {
|
||||
public:
|
||||
// 元の入力特徴量の次元数
|
||||
// number of dimensions of original input features
|
||||
static constexpr IndexType kBaseDimensions = FeatureType::kDimensions;
|
||||
|
||||
// 学習用特徴量の次元数を取得する
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return Factorizer<FeatureType>::GetDimensions();
|
||||
}
|
||||
|
||||
// 学習用特徴量のインデックスと学習率のスケールを取得する
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features,
|
||||
IndexType base_dimensions = kBaseDimensions) {
|
||||
@@ -101,4 +101,4 @@ public:
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の特徴量変換クラステンプレートのHalfKP用特殊化
|
||||
// Specialization of NNUE evaluation function feature conversion class template for HalfKP
|
||||
|
||||
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KP_H_
|
||||
#define _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KP_H_
|
||||
@@ -16,18 +16,18 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// 入力特徴量を学習用特徴量に変換するクラステンプレート
|
||||
// HalfKP用特殊化
|
||||
// Class template that converts input features into learning features
|
||||
// Specialization for HalfKP
|
||||
template <Side AssociatedKing>
|
||||
class Factorizer<HalfKP<AssociatedKing>> {
|
||||
private:
|
||||
using FeatureType = HalfKP<AssociatedKing>;
|
||||
|
||||
// 特徴量のうち、同時に値が1となるインデックスの数の最大値
|
||||
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
|
||||
static constexpr IndexType kMaxActiveDimensions =
|
||||
FeatureType::kMaxActiveDimensions;
|
||||
|
||||
// 学習用特徴量の種類
|
||||
// Type of learning feature
|
||||
enum TrainingFeatureType {
|
||||
kFeaturesHalfKP,
|
||||
kFeaturesHalfK,
|
||||
@@ -36,7 +36,7 @@ class Factorizer<HalfKP<AssociatedKing>> {
|
||||
kNumTrainingFeatureTypes,
|
||||
};
|
||||
|
||||
// 学習用特徴量の情報
|
||||
// Learning feature information
|
||||
static constexpr FeatureProperties kProperties[] = {
|
||||
// kFeaturesHalfKP
|
||||
{true, FeatureType::kDimensions},
|
||||
@@ -50,12 +50,12 @@ class Factorizer<HalfKP<AssociatedKing>> {
|
||||
static_assert(GetArrayLength(kProperties) == kNumTrainingFeatureTypes, "");
|
||||
|
||||
public:
|
||||
// 学習用特徴量の次元数を取得する
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return GetActiveDimensions(kProperties);
|
||||
}
|
||||
|
||||
// 学習用特徴量のインデックスと学習率のスケールを取得する
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features) {
|
||||
// kFeaturesHalfKP
|
||||
@@ -100,4 +100,4 @@ constexpr FeatureProperties Factorizer<HalfKP<AssociatedKing>>::kProperties[];
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の学習用クラステンプレートの共通ヘッダ
|
||||
// Common header of class template for learning NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_TRAINER_H_
|
||||
#define _NNUE_TRAINER_H_
|
||||
@@ -18,10 +18,10 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 評価値と勝率の関係式で用いるPonanza定数
|
||||
// Ponanza constant used in the relation between evaluation value and winning percentage
|
||||
constexpr double kPonanzaConstant = 600.0;
|
||||
|
||||
// 学習用特徴量のインデックス1つを表すクラス
|
||||
// Class that represents one index of learning feature
|
||||
class TrainingFeature {
|
||||
using StorageType = std::uint32_t;
|
||||
static_assert(std::is_unsigned<StorageType>::value, "");
|
||||
@@ -60,7 +60,7 @@ class TrainingFeature {
|
||||
StorageType index_and_count_;
|
||||
};
|
||||
|
||||
// 学習データ1サンプルを表す構造体
|
||||
// Structure that represents one sample of training data
|
||||
struct Example {
|
||||
std::vector<TrainingFeature> training_features[2];
|
||||
Learner::PackedSfenValue psv;
|
||||
@@ -68,9 +68,9 @@ struct Example {
|
||||
double weight;
|
||||
};
|
||||
|
||||
// ハイパーパラメータの設定などに使用するメッセージ
|
||||
// Message used for setting hyperparameters
|
||||
struct Message {
|
||||
Message(const std::string& name, const std::string& value = "") :
|
||||
Message(const std::string& name, const std::string& value = ""):
|
||||
name(name), value(value), num_peekers(0), num_receivers(0) {}
|
||||
const std::string name;
|
||||
const std::string value;
|
||||
@@ -78,7 +78,7 @@ struct Message {
|
||||
std::uint32_t num_receivers;
|
||||
};
|
||||
|
||||
// メッセージを受理するかどうかを判定する
|
||||
// determine whether to accept the message
|
||||
bool ReceiveMessage(const std::string& name, Message* message) {
|
||||
const auto subscript = "[" + std::to_string(message->num_peekers) + "]";
|
||||
if (message->name.substr(0, name.size() + 1) == name + "[") {
|
||||
@@ -91,7 +91,7 @@ bool ReceiveMessage(const std::string& name, Message* message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 文字列を分割する
|
||||
// split the string
|
||||
std::vector<std::string> Split(const std::string& input, char delimiter) {
|
||||
std::istringstream stream(input);
|
||||
std::string field;
|
||||
@@ -102,13 +102,13 @@ std::vector<std::string> Split(const std::string& input, char delimiter) {
|
||||
return fields;
|
||||
}
|
||||
|
||||
// 浮動小数点数を整数に丸める
|
||||
// round a floating point number to an integer
|
||||
template <typename IntType>
|
||||
IntType Round(double value) {
|
||||
return static_cast<IntType>(std::floor(value + 0.5));
|
||||
}
|
||||
|
||||
// アライメント付きmake_shared
|
||||
// make_shared with alignment
|
||||
template <typename T, typename... ArgumentTypes>
|
||||
std::shared_ptr<T> MakeAlignedSharedPtr(ArgumentTypes&&... arguments) {
|
||||
const auto ptr = new(aligned_malloc(sizeof(T), alignof(T)))
|
||||
@@ -122,4 +122,4 @@ std::shared_ptr<T> MakeAlignedSharedPtr(ArgumentTypes&&... arguments) {
|
||||
|
||||
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の学習クラステンプレートのAffineTransform用特殊化
|
||||
// Specialization of NNUE evaluation function learning class template for AffineTransform
|
||||
|
||||
#ifndef _NNUE_TRAINER_AFFINE_TRANSFORM_H_
|
||||
#define _NNUE_TRAINER_AFFINE_TRANSFORM_H_
|
||||
@@ -15,22 +15,22 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 学習:アフィン変換層
|
||||
// Learning: Affine transformation layer
|
||||
template <typename PreviousLayer, IndexType OutputDimensions>
|
||||
class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
|
||||
private:
|
||||
// 学習対象の層の型
|
||||
// Type of layer to learn
|
||||
using LayerType = Layers::AffineTransform<PreviousLayer, OutputDimensions>;
|
||||
|
||||
public:
|
||||
// ファクトリ関数
|
||||
// factory function
|
||||
static std::shared_ptr<Trainer> Create(
|
||||
LayerType* target_layer, FeatureTransformer* feature_transformer) {
|
||||
return std::shared_ptr<Trainer>(
|
||||
new Trainer(target_layer, feature_transformer));
|
||||
}
|
||||
|
||||
// ハイパーパラメータなどのオプションを設定する
|
||||
// Set options such as hyperparameters
|
||||
void SendMessage(Message* message) {
|
||||
previous_layer_trainer_->SendMessage(message);
|
||||
if (ReceiveMessage("momentum", message)) {
|
||||
@@ -48,19 +48,19 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
|
||||
}
|
||||
}
|
||||
|
||||
// パラメータを乱数で初期化する
|
||||
// Initialize the parameters with random numbers
|
||||
template <typename RNG>
|
||||
void Initialize(RNG& rng) {
|
||||
previous_layer_trainer_->Initialize(rng);
|
||||
if (kIsOutputLayer) {
|
||||
// 出力層は0で初期化する
|
||||
// Initialize output layer with 0
|
||||
std::fill(std::begin(biases_), std::end(biases_),
|
||||
static_cast<LearnFloatType>(0.0));
|
||||
std::fill(std::begin(weights_), std::end(weights_),
|
||||
static_cast<LearnFloatType>(0.0));
|
||||
} else {
|
||||
// 入力の分布が各ユニット平均0.5、等分散であることを仮定し、
|
||||
// 出力の分布が各ユニット平均0.5、入力と同じ等分散になるように初期化する
|
||||
// Assuming that the input distribution is unit-mean 0.5, equal variance,
|
||||
// Initialize the output distribution so that each unit has a mean of 0.5 and the same variance as the input
|
||||
const double kSigma = 1.0 / std::sqrt(kInputDimensions);
|
||||
auto distribution = std::normal_distribution<double>(0.0, kSigma);
|
||||
for (IndexType i = 0; i < kOutputDimensions; ++i) {
|
||||
@@ -76,7 +76,7 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
|
||||
QuantizeParameters();
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
const LearnFloatType* Propagate(const std::vector<Example>& batch) {
|
||||
if (output_.size() < kOutputDimensions * batch.size()) {
|
||||
output_.resize(kOutputDimensions * batch.size());
|
||||
@@ -111,7 +111,7 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
|
||||
return output_.data();
|
||||
}
|
||||
|
||||
// 逆伝播
|
||||
// backpropagation
|
||||
void Backpropagate(const LearnFloatType* gradients,
|
||||
LearnFloatType learning_rate) {
|
||||
const LearnFloatType local_learning_rate =
|
||||
@@ -185,7 +185,7 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
|
||||
}
|
||||
|
||||
private:
|
||||
// コンストラクタ
|
||||
// constructor
|
||||
Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer) :
|
||||
batch_size_(0),
|
||||
batch_input_(nullptr),
|
||||
@@ -201,7 +201,7 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
|
||||
DequantizeParameters();
|
||||
}
|
||||
|
||||
// 重みの飽和とパラメータの整数化
|
||||
// Weight saturation and parameterization
|
||||
void QuantizeParameters() {
|
||||
for (IndexType i = 0; i < kOutputDimensions * kInputDimensions; ++i) {
|
||||
weights_[i] = std::max(-kMaxWeightMagnitude,
|
||||
@@ -222,7 +222,7 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
|
||||
}
|
||||
}
|
||||
|
||||
// 整数化されたパラメータの読み込み
|
||||
// read parameterized integer
|
||||
void DequantizeParameters() {
|
||||
for (IndexType i = 0; i < kOutputDimensions; ++i) {
|
||||
biases_[i] = static_cast<LearnFloatType>(
|
||||
@@ -242,14 +242,14 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
|
||||
static_cast<LearnFloatType>(0.0));
|
||||
}
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kInputDimensions = LayerType::kInputDimensions;
|
||||
static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions;
|
||||
|
||||
// 出力の次元数が1なら出力層
|
||||
// If the output dimensionality is 1, the output layer
|
||||
static constexpr bool kIsOutputLayer = kOutputDimensions == 1;
|
||||
|
||||
// パラメータの整数化で用いる係数
|
||||
// Coefficient used for parameterization
|
||||
static constexpr LearnFloatType kActivationScale =
|
||||
std::numeric_limits<std::int8_t>::max();
|
||||
static constexpr LearnFloatType kBiasScale = kIsOutputLayer ?
|
||||
@@ -257,37 +257,37 @@ class Trainer<Layers::AffineTransform<PreviousLayer, OutputDimensions>> {
|
||||
((1 << kWeightScaleBits) * kActivationScale);
|
||||
static constexpr LearnFloatType kWeightScale = kBiasScale / kActivationScale;
|
||||
|
||||
// パラメータの整数化でオーバーフローさせないために用いる重みの絶対値の上限
|
||||
// Upper limit of absolute value of weight used to prevent overflow when parameterizing integers
|
||||
static constexpr LearnFloatType kMaxWeightMagnitude =
|
||||
std::numeric_limits<typename LayerType::WeightType>::max() / kWeightScale;
|
||||
|
||||
// ミニバッチのサンプル数
|
||||
// number of samples in mini-batch
|
||||
IndexType batch_size_;
|
||||
|
||||
// ミニバッチの入力
|
||||
// Input mini batch
|
||||
const LearnFloatType* batch_input_;
|
||||
|
||||
// 直前の層のTrainer
|
||||
// Trainer of the previous layer
|
||||
const std::shared_ptr<Trainer<PreviousLayer>> previous_layer_trainer_;
|
||||
|
||||
// 学習対象の層
|
||||
// layer to learn
|
||||
LayerType* const target_layer_;
|
||||
|
||||
// パラメータ
|
||||
// parameter
|
||||
LearnFloatType biases_[kOutputDimensions];
|
||||
LearnFloatType weights_[kOutputDimensions * kInputDimensions];
|
||||
|
||||
// パラメータの更新で用いるバッファ
|
||||
// Buffer used for updating parameters
|
||||
LearnFloatType biases_diff_[kOutputDimensions];
|
||||
LearnFloatType weights_diff_[kOutputDimensions * kInputDimensions];
|
||||
|
||||
// 順伝播用バッファ
|
||||
// Forward propagation buffer
|
||||
std::vector<LearnFloatType> output_;
|
||||
|
||||
// 逆伝播用バッファ
|
||||
// buffer for back propagation
|
||||
std::vector<LearnFloatType> gradients_;
|
||||
|
||||
// ハイパーパラメータ
|
||||
// hyper parameter
|
||||
LearnFloatType momentum_;
|
||||
LearnFloatType learning_rate_scale_;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の学習クラステンプレートのClippedReLU用特殊化
|
||||
// Specialization of NNUE evaluation function learning class template for ClippedReLU
|
||||
|
||||
#ifndef _NNUE_TRAINER_CLIPPED_RELU_H_
|
||||
#define _NNUE_TRAINER_CLIPPED_RELU_H_
|
||||
@@ -13,22 +13,22 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 学習:アフィン変換層
|
||||
// Learning: Affine transformation layer
|
||||
template <typename PreviousLayer>
|
||||
class Trainer<Layers::ClippedReLU<PreviousLayer>> {
|
||||
private:
|
||||
// 学習対象の層の型
|
||||
// Type of layer to learn
|
||||
using LayerType = Layers::ClippedReLU<PreviousLayer>;
|
||||
|
||||
public:
|
||||
// ファクトリ関数
|
||||
// factory function
|
||||
static std::shared_ptr<Trainer> Create(
|
||||
LayerType* target_layer, FeatureTransformer* feature_transformer) {
|
||||
return std::shared_ptr<Trainer>(
|
||||
new Trainer(target_layer, feature_transformer));
|
||||
}
|
||||
|
||||
// ハイパーパラメータなどのオプションを設定する
|
||||
// Set options such as hyperparameters
|
||||
void SendMessage(Message* message) {
|
||||
previous_layer_trainer_->SendMessage(message);
|
||||
if (ReceiveMessage("check_health", message)) {
|
||||
@@ -36,13 +36,13 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
|
||||
}
|
||||
}
|
||||
|
||||
// パラメータを乱数で初期化する
|
||||
// Initialize the parameters with random numbers
|
||||
template <typename RNG>
|
||||
void Initialize(RNG& rng) {
|
||||
previous_layer_trainer_->Initialize(rng);
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
const LearnFloatType* Propagate(const std::vector<Example>& batch) {
|
||||
if (output_.size() < kOutputDimensions * batch.size()) {
|
||||
output_.resize(kOutputDimensions * batch.size());
|
||||
@@ -62,7 +62,7 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
|
||||
return output_.data();
|
||||
}
|
||||
|
||||
// 逆伝播
|
||||
// backpropagation
|
||||
void Backpropagate(const LearnFloatType* gradients,
|
||||
LearnFloatType learning_rate) {
|
||||
for (IndexType b = 0; b < batch_size_; ++b) {
|
||||
@@ -77,7 +77,7 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
|
||||
}
|
||||
|
||||
private:
|
||||
// コンストラクタ
|
||||
// constructor
|
||||
Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer) :
|
||||
batch_size_(0),
|
||||
previous_layer_trainer_(Trainer<PreviousLayer>::Create(
|
||||
@@ -89,7 +89,7 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
|
||||
std::numeric_limits<LearnFloatType>::lowest());
|
||||
}
|
||||
|
||||
// 学習に問題が生じていないかチェックする
|
||||
// Check if there are any problems with learning
|
||||
void CheckHealth() {
|
||||
const auto largest_min_activation = *std::max_element(
|
||||
std::begin(min_activations_), std::end(min_activations_));
|
||||
@@ -105,30 +105,30 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
|
||||
std::numeric_limits<LearnFloatType>::lowest());
|
||||
}
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kInputDimensions = LayerType::kOutputDimensions;
|
||||
static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions;
|
||||
|
||||
// LearnFloatTypeの定数
|
||||
// LearnFloatType constant
|
||||
static constexpr LearnFloatType kZero = static_cast<LearnFloatType>(0.0);
|
||||
static constexpr LearnFloatType kOne = static_cast<LearnFloatType>(1.0);
|
||||
|
||||
// ミニバッチのサンプル数
|
||||
// number of samples in mini-batch
|
||||
IndexType batch_size_;
|
||||
|
||||
// 直前の層のTrainer
|
||||
// Trainer of the previous layer
|
||||
const std::shared_ptr<Trainer<PreviousLayer>> previous_layer_trainer_;
|
||||
|
||||
// 学習対象の層
|
||||
// layer to learn
|
||||
LayerType* const target_layer_;
|
||||
|
||||
// 順伝播用バッファ
|
||||
// Forward propagation buffer
|
||||
std::vector<LearnFloatType> output_;
|
||||
|
||||
// 逆伝播用バッファ
|
||||
// buffer for back propagation
|
||||
std::vector<LearnFloatType> gradients_;
|
||||
|
||||
// ヘルスチェック用統計値
|
||||
// Health check statistics
|
||||
LearnFloatType min_activations_[kOutputDimensions];
|
||||
LearnFloatType max_activations_[kOutputDimensions];
|
||||
};
|
||||
@@ -139,4 +139,4 @@ class Trainer<Layers::ClippedReLU<PreviousLayer>> {
|
||||
|
||||
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の学習クラステンプレートのFeatureTransformer用特殊化
|
||||
// Specialization for feature transformer of learning class template of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_TRAINER_FEATURE_TRANSFORMER_H_
|
||||
#define _NNUE_TRAINER_FEATURE_TRANSFORMER_H_
|
||||
@@ -24,11 +24,11 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 学習:入力特徴量変換器
|
||||
// Learning: Input feature converter
|
||||
template <>
|
||||
class Trainer<FeatureTransformer> {
|
||||
private:
|
||||
// 学習対象の層の型
|
||||
// Type of layer to learn
|
||||
using LayerType = FeatureTransformer;
|
||||
|
||||
public:
|
||||
@@ -37,12 +37,12 @@ class Trainer<FeatureTransformer> {
|
||||
template <typename T, typename... ArgumentTypes>
|
||||
friend std::shared_ptr<T> MakeAlignedSharedPtr(ArgumentTypes&&... arguments);
|
||||
|
||||
// ファクトリ関数
|
||||
// factory function
|
||||
static std::shared_ptr<Trainer> Create(LayerType* target_layer) {
|
||||
return MakeAlignedSharedPtr<Trainer>(target_layer);
|
||||
}
|
||||
|
||||
// ハイパーパラメータなどのオプションを設定する
|
||||
// Set options such as hyperparameters
|
||||
void SendMessage(Message* message) {
|
||||
if (ReceiveMessage("momentum", message)) {
|
||||
momentum_ = static_cast<LearnFloatType>(std::stod(message->value));
|
||||
@@ -65,7 +65,7 @@ class Trainer<FeatureTransformer> {
|
||||
}
|
||||
}
|
||||
|
||||
// パラメータを乱数で初期化する
|
||||
// Initialize the parameters with random numbers
|
||||
template <typename RNG>
|
||||
void Initialize(RNG& rng) {
|
||||
std::fill(std::begin(weights_), std::end(weights_), +kZero);
|
||||
@@ -81,7 +81,7 @@ class Trainer<FeatureTransformer> {
|
||||
QuantizeParameters();
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
const LearnFloatType* Propagate(const std::vector<Example>& batch) {
|
||||
if (output_.size() < kOutputDimensions * batch.size()) {
|
||||
output_.resize(kOutputDimensions * batch.size());
|
||||
@@ -131,7 +131,7 @@ class Trainer<FeatureTransformer> {
|
||||
return output_.data();
|
||||
}
|
||||
|
||||
// 逆伝播
|
||||
// backpropagation
|
||||
void Backpropagate(const LearnFloatType* gradients,
|
||||
LearnFloatType learning_rate) {
|
||||
const LearnFloatType local_learning_rate =
|
||||
@@ -144,8 +144,8 @@ class Trainer<FeatureTransformer> {
|
||||
((output_[index] > kZero) * (output_[index] < kOne));
|
||||
}
|
||||
}
|
||||
// 重み行列は入力に出現した特徴量に対応する列のみを更新するため、
|
||||
// momentumを使用せず、学習率を補正してスケールを合わせる
|
||||
// Since the weight matrix updates only the columns corresponding to the features that appeared in the input,
|
||||
// Correct the learning rate and adjust the scale without using momentum
|
||||
const LearnFloatType effective_learning_rate =
|
||||
static_cast<LearnFloatType>(local_learning_rate / (1.0 - momentum_));
|
||||
#if defined(USE_BLAS)
|
||||
@@ -227,7 +227,7 @@ class Trainer<FeatureTransformer> {
|
||||
}
|
||||
|
||||
private:
|
||||
// コンストラクタ
|
||||
// constructor
|
||||
Trainer(LayerType* target_layer) :
|
||||
batch_(nullptr),
|
||||
target_layer_(target_layer),
|
||||
@@ -245,7 +245,7 @@ class Trainer<FeatureTransformer> {
|
||||
DequantizeParameters();
|
||||
}
|
||||
|
||||
// 重みの飽和とパラメータの整数化
|
||||
// Weight saturation and parameterization
|
||||
void QuantizeParameters() {
|
||||
for (IndexType i = 0; i < kHalfDimensions; ++i) {
|
||||
target_layer_->biases_[i] =
|
||||
@@ -268,7 +268,7 @@ class Trainer<FeatureTransformer> {
|
||||
}
|
||||
}
|
||||
|
||||
// 整数化されたパラメータの読み込み
|
||||
// read parameterized integer
|
||||
void DequantizeParameters() {
|
||||
for (IndexType i = 0; i < kHalfDimensions; ++i) {
|
||||
biases_[i] = static_cast<LearnFloatType>(
|
||||
@@ -282,7 +282,7 @@ class Trainer<FeatureTransformer> {
|
||||
std::fill(std::begin(biases_diff_), std::end(biases_diff_), +kZero);
|
||||
}
|
||||
|
||||
// 学習データに出現していない特徴量に対応する重みを0にする
|
||||
// Set the weight corresponding to the feature that does not appear in the learning data to 0
|
||||
void ClearUnobservedFeatureWeights() {
|
||||
for (IndexType i = 0; i < kInputDimensions; ++i) {
|
||||
if (!observed_features.test(i)) {
|
||||
@@ -293,7 +293,7 @@ class Trainer<FeatureTransformer> {
|
||||
QuantizeParameters();
|
||||
}
|
||||
|
||||
// 学習に問題が生じていないかチェックする
|
||||
// Check if there are any problems with learning
|
||||
void CheckHealth() {
|
||||
std::cout << "INFO: observed " << observed_features.count()
|
||||
<< " (out of " << kInputDimensions << ") features" << std::endl;
|
||||
@@ -320,48 +320,48 @@ class Trainer<FeatureTransformer> {
|
||||
std::numeric_limits<LearnFloatType>::lowest());
|
||||
}
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kInputDimensions =
|
||||
Features::Factorizer<RawFeatures>::GetDimensions();
|
||||
static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions;
|
||||
static constexpr IndexType kHalfDimensions = LayerType::kHalfDimensions;
|
||||
|
||||
// パラメータの整数化で用いる係数
|
||||
// Coefficient used for parameterization
|
||||
static constexpr LearnFloatType kActivationScale =
|
||||
std::numeric_limits<std::int8_t>::max();
|
||||
static constexpr LearnFloatType kBiasScale = kActivationScale;
|
||||
static constexpr LearnFloatType kWeightScale = kActivationScale;
|
||||
|
||||
// LearnFloatTypeの定数
|
||||
// LearnFloatType constant
|
||||
static constexpr LearnFloatType kZero = static_cast<LearnFloatType>(0.0);
|
||||
static constexpr LearnFloatType kOne = static_cast<LearnFloatType>(1.0);
|
||||
|
||||
// ミニバッチ
|
||||
// mini batch
|
||||
const std::vector<Example>* batch_;
|
||||
|
||||
// 学習対象の層
|
||||
// layer to learn
|
||||
LayerType* const target_layer_;
|
||||
|
||||
// パラメータ
|
||||
// parameter
|
||||
alignas(kCacheLineSize) LearnFloatType biases_[kHalfDimensions];
|
||||
alignas(kCacheLineSize)
|
||||
LearnFloatType weights_[kHalfDimensions * kInputDimensions];
|
||||
|
||||
// パラメータの更新で用いるバッファ
|
||||
// Buffer used for updating parameters
|
||||
LearnFloatType biases_diff_[kHalfDimensions];
|
||||
std::vector<LearnFloatType> gradients_;
|
||||
|
||||
// 順伝播用バッファ
|
||||
// Forward propagation buffer
|
||||
std::vector<LearnFloatType> output_;
|
||||
|
||||
// 学習データに出現した特徴量
|
||||
// Features that appeared in the training data
|
||||
std::bitset<kInputDimensions> observed_features;
|
||||
|
||||
// ハイパーパラメータ
|
||||
// hyper parameter
|
||||
LearnFloatType momentum_;
|
||||
LearnFloatType learning_rate_scale_;
|
||||
|
||||
// ヘルスチェック用統計値
|
||||
// Health check statistics
|
||||
LearnFloatType min_pre_activation_;
|
||||
LearnFloatType max_pre_activation_;
|
||||
LearnFloatType min_activations_[kHalfDimensions];
|
||||
@@ -374,4 +374,4 @@ class Trainer<FeatureTransformer> {
|
||||
|
||||
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の学習クラステンプレートのInputSlice用特殊化
|
||||
// Specialization of NNUE evaluation function learning class template for InputSlice
|
||||
|
||||
#ifndef _NNUE_TRAINER_INPUT_SLICE_H_
|
||||
#define _NNUE_TRAINER_INPUT_SLICE_H_
|
||||
@@ -13,10 +13,10 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 学習:入力層
|
||||
// Learning: Input layer
|
||||
class SharedInputTrainer {
|
||||
public:
|
||||
// ファクトリ関数
|
||||
// factory function
|
||||
static std::shared_ptr<SharedInputTrainer> Create(
|
||||
FeatureTransformer* feature_transformer) {
|
||||
static std::shared_ptr<SharedInputTrainer> instance;
|
||||
@@ -27,7 +27,7 @@ class SharedInputTrainer {
|
||||
return instance;
|
||||
}
|
||||
|
||||
// ハイパーパラメータなどのオプションを設定する
|
||||
// Set options such as hyperparameters
|
||||
void SendMessage(Message* message) {
|
||||
if (num_calls_ == 0) {
|
||||
current_operation_ = Operation::kSendMessage;
|
||||
@@ -40,7 +40,7 @@ class SharedInputTrainer {
|
||||
}
|
||||
}
|
||||
|
||||
// パラメータを乱数で初期化する
|
||||
// Initialize the parameters with random numbers
|
||||
template <typename RNG>
|
||||
void Initialize(RNG& rng) {
|
||||
if (num_calls_ == 0) {
|
||||
@@ -54,7 +54,7 @@ class SharedInputTrainer {
|
||||
}
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
const LearnFloatType* Propagate(const std::vector<Example>& batch) {
|
||||
if (gradients_.size() < kInputDimensions * batch.size()) {
|
||||
gradients_.resize(kInputDimensions * batch.size());
|
||||
@@ -72,7 +72,7 @@ class SharedInputTrainer {
|
||||
return output_;
|
||||
}
|
||||
|
||||
// 逆伝播
|
||||
// backpropagation
|
||||
void Backpropagate(const LearnFloatType* gradients,
|
||||
LearnFloatType learning_rate) {
|
||||
if (num_referrers_ == 1) {
|
||||
@@ -104,7 +104,7 @@ class SharedInputTrainer {
|
||||
}
|
||||
|
||||
private:
|
||||
// コンストラクタ
|
||||
// constructor
|
||||
SharedInputTrainer(FeatureTransformer* feature_transformer) :
|
||||
batch_size_(0),
|
||||
num_referrers_(0),
|
||||
@@ -115,11 +115,11 @@ class SharedInputTrainer {
|
||||
output_(nullptr) {
|
||||
}
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kInputDimensions =
|
||||
FeatureTransformer::kOutputDimensions;
|
||||
|
||||
// 処理の種類
|
||||
// type of processing
|
||||
enum class Operation {
|
||||
kNone,
|
||||
kSendMessage,
|
||||
@@ -128,55 +128,55 @@ class SharedInputTrainer {
|
||||
kBackPropagate,
|
||||
};
|
||||
|
||||
// ミニバッチのサンプル数
|
||||
// number of samples in mini-batch
|
||||
IndexType batch_size_;
|
||||
|
||||
// この層を入力として共有する層の数
|
||||
// number of layers sharing this layer as input
|
||||
std::uint32_t num_referrers_;
|
||||
|
||||
// 現在の処理が呼び出された回数
|
||||
// Number of times the current process has been called
|
||||
std::uint32_t num_calls_;
|
||||
|
||||
// 現在の処理の種類
|
||||
// current processing type
|
||||
Operation current_operation_;
|
||||
|
||||
// 入力特徴量変換器のTrainer
|
||||
// Trainer of input feature converter
|
||||
const std::shared_ptr<Trainer<FeatureTransformer>>
|
||||
feature_transformer_trainer_;
|
||||
|
||||
// 順伝播用に共有する出力のポインタ
|
||||
// pointer to output shared for forward propagation
|
||||
const LearnFloatType* output_;
|
||||
|
||||
// 逆伝播用バッファ
|
||||
// buffer for back propagation
|
||||
std::vector<LearnFloatType> gradients_;
|
||||
};
|
||||
|
||||
// 学習:入力層
|
||||
// Learning: Input layer
|
||||
template <IndexType OutputDimensions, IndexType Offset>
|
||||
class Trainer<Layers::InputSlice<OutputDimensions, Offset>> {
|
||||
private:
|
||||
// 学習対象の層の型
|
||||
// Type of layer to learn
|
||||
using LayerType = Layers::InputSlice<OutputDimensions, Offset>;
|
||||
|
||||
public:
|
||||
// ファクトリ関数
|
||||
// factory function
|
||||
static std::shared_ptr<Trainer> Create(
|
||||
LayerType* /*target_layer*/, FeatureTransformer* feature_transformer) {
|
||||
return std::shared_ptr<Trainer>(new Trainer(feature_transformer));
|
||||
}
|
||||
|
||||
// ハイパーパラメータなどのオプションを設定する
|
||||
// Set options such as hyperparameters
|
||||
void SendMessage(Message* message) {
|
||||
shared_input_trainer_->SendMessage(message);
|
||||
}
|
||||
|
||||
// パラメータを乱数で初期化する
|
||||
// Initialize the parameters with random numbers
|
||||
template <typename RNG>
|
||||
void Initialize(RNG& rng) {
|
||||
shared_input_trainer_->Initialize(rng);
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
const LearnFloatType* Propagate(const std::vector<Example>& batch) {
|
||||
if (output_.size() < kOutputDimensions * batch.size()) {
|
||||
output_.resize(kOutputDimensions * batch.size());
|
||||
@@ -199,7 +199,7 @@ class Trainer<Layers::InputSlice<OutputDimensions, Offset>> {
|
||||
return output_.data();
|
||||
}
|
||||
|
||||
// 逆伝播
|
||||
// backpropagation
|
||||
void Backpropagate(const LearnFloatType* gradients,
|
||||
LearnFloatType learning_rate) {
|
||||
for (IndexType b = 0; b < batch_size_; ++b) {
|
||||
@@ -217,28 +217,28 @@ class Trainer<Layers::InputSlice<OutputDimensions, Offset>> {
|
||||
}
|
||||
|
||||
private:
|
||||
// コンストラクタ
|
||||
Trainer(FeatureTransformer* feature_transformer) :
|
||||
// constructor
|
||||
Trainer(FeatureTransformer* feature_transformer):
|
||||
batch_size_(0),
|
||||
shared_input_trainer_(SharedInputTrainer::Create(feature_transformer)) {
|
||||
}
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kInputDimensions =
|
||||
FeatureTransformer::kOutputDimensions;
|
||||
static constexpr IndexType kOutputDimensions = OutputDimensions;
|
||||
static_assert(Offset + kOutputDimensions <= kInputDimensions, "");
|
||||
|
||||
// ミニバッチのサンプル数
|
||||
// number of samples in mini-batch
|
||||
IndexType batch_size_;
|
||||
|
||||
// 共有入力層のTrainer
|
||||
// Trainer of shared input layer
|
||||
const std::shared_ptr<SharedInputTrainer> shared_input_trainer_;
|
||||
|
||||
// 順伝播用バッファ
|
||||
// Forward propagation buffer
|
||||
std::vector<LearnFloatType> output_;
|
||||
|
||||
// 逆伝播用バッファ
|
||||
// buffer for back propagation
|
||||
std::vector<LearnFloatType> gradients_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// NNUE評価関数の学習クラステンプレートのSum用特殊化
|
||||
// Specialization of NNUE evaluation function learning class template for Sum
|
||||
|
||||
#ifndef _NNUE_TRAINER_SUM_H_
|
||||
#define _NNUE_TRAINER_SUM_H_
|
||||
@@ -13,40 +13,40 @@ namespace Eval {
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
// 学習:複数の層の出力の和を取る層
|
||||
// Learning: A layer that sums the outputs of multiple layers
|
||||
template <typename FirstPreviousLayer, typename... RemainingPreviousLayers>
|
||||
class Trainer<Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>> :
|
||||
Trainer<Layers::Sum<RemainingPreviousLayers...>> {
|
||||
private:
|
||||
// 学習対象の層の型
|
||||
// Type of layer to learn
|
||||
using LayerType = Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>;
|
||||
using Tail = Trainer<Layers::Sum<RemainingPreviousLayers...>>;
|
||||
|
||||
public:
|
||||
// ファクトリ関数
|
||||
// factory function
|
||||
static std::shared_ptr<Trainer> Create(
|
||||
LayerType* target_layer, FeatureTransformer* feature_transformer) {
|
||||
return std::shared_ptr<Trainer>(
|
||||
new Trainer(target_layer, feature_transformer));
|
||||
}
|
||||
|
||||
// ハイパーパラメータなどのオプションを設定する
|
||||
// Set options such as hyperparameters
|
||||
void SendMessage(Message* message) {
|
||||
// 他のメンバ関数の結果は処理の順番に依存しないため、
|
||||
// 実装をシンプルにすることを目的としてTailを先に処理するが、
|
||||
// SendMessageは添字の対応を分かりやすくするためにHeadを先に処理する
|
||||
// The results of other member functions do not depend on the processing order, so
|
||||
// Tail is processed first for the purpose of simplifying the implementation, but
|
||||
// SendMessage processes Head first to make it easier to understand subscript correspondence
|
||||
previous_layer_trainer_->SendMessage(message);
|
||||
Tail::SendMessage(message);
|
||||
}
|
||||
|
||||
// パラメータを乱数で初期化する
|
||||
// Initialize the parameters with random numbers
|
||||
template <typename RNG>
|
||||
void Initialize(RNG& rng) {
|
||||
Tail::Initialize(rng);
|
||||
previous_layer_trainer_->Initialize(rng);
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
/*const*/ LearnFloatType* Propagate(const std::vector<Example>& batch) {
|
||||
batch_size_ = static_cast<IndexType>(batch.size());
|
||||
auto output = Tail::Propagate(batch);
|
||||
@@ -65,7 +65,7 @@ class Trainer<Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>> :
|
||||
return output;
|
||||
}
|
||||
|
||||
// 逆伝播
|
||||
// backpropagation
|
||||
void Backpropagate(const LearnFloatType* gradients,
|
||||
LearnFloatType learning_rate) {
|
||||
Tail::Backpropagate(gradients, learning_rate);
|
||||
@@ -73,8 +73,8 @@ class Trainer<Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>> :
|
||||
}
|
||||
|
||||
private:
|
||||
// コンストラクタ
|
||||
Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer) :
|
||||
// constructor
|
||||
Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer):
|
||||
Tail(target_layer, feature_transformer),
|
||||
batch_size_(0),
|
||||
previous_layer_trainer_(Trainer<FirstPreviousLayer>::Create(
|
||||
@@ -82,51 +82,51 @@ class Trainer<Layers::Sum<FirstPreviousLayer, RemainingPreviousLayers...>> :
|
||||
target_layer_(target_layer) {
|
||||
}
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions;
|
||||
|
||||
// サブクラスをfriendにする
|
||||
// make subclass friend
|
||||
template <typename SumLayer>
|
||||
friend class Trainer;
|
||||
|
||||
// ミニバッチのサンプル数
|
||||
// number of samples in mini-batch
|
||||
IndexType batch_size_;
|
||||
|
||||
// 直前の層のTrainer
|
||||
// Trainer of the previous layer
|
||||
const std::shared_ptr<Trainer<FirstPreviousLayer>> previous_layer_trainer_;
|
||||
|
||||
// 学習対象の層
|
||||
// layer to learn
|
||||
LayerType* const target_layer_;
|
||||
};
|
||||
|
||||
|
||||
// 学習:複数の層の出力の和を取る層(テンプレート引数が1つの場合)
|
||||
// Learning: Layer that takes the sum of the outputs of multiple layers (when there is one template argument)
|
||||
template <typename PreviousLayer>
|
||||
class Trainer<Layers::Sum<PreviousLayer>> {
|
||||
private:
|
||||
// 学習対象の層の型
|
||||
// Type of layer to learn
|
||||
using LayerType = Layers::Sum<PreviousLayer>;
|
||||
|
||||
public:
|
||||
// ファクトリ関数
|
||||
// factory function
|
||||
static std::shared_ptr<Trainer> Create(
|
||||
LayerType* target_layer, FeatureTransformer* feature_transformer) {
|
||||
return std::shared_ptr<Trainer>(
|
||||
new Trainer(target_layer, feature_transformer));
|
||||
}
|
||||
|
||||
// ハイパーパラメータなどのオプションを設定する
|
||||
// Set options such as hyperparameters
|
||||
void SendMessage(Message* message) {
|
||||
previous_layer_trainer_->SendMessage(message);
|
||||
}
|
||||
|
||||
// パラメータを乱数で初期化する
|
||||
// Initialize the parameters with random numbers
|
||||
template <typename RNG>
|
||||
void Initialize(RNG& rng) {
|
||||
previous_layer_trainer_->Initialize(rng);
|
||||
}
|
||||
|
||||
// 順伝播
|
||||
// forward propagation
|
||||
/*const*/ LearnFloatType* Propagate(const std::vector<Example>& batch) {
|
||||
if (output_.size() < kOutputDimensions * batch.size()) {
|
||||
output_.resize(kOutputDimensions * batch.size());
|
||||
@@ -146,14 +146,14 @@ class Trainer<Layers::Sum<PreviousLayer>> {
|
||||
return output_.data();
|
||||
}
|
||||
|
||||
// 逆伝播
|
||||
// backpropagation
|
||||
void Backpropagate(const LearnFloatType* gradients,
|
||||
LearnFloatType learning_rate) {
|
||||
previous_layer_trainer_->Backpropagate(gradients, learning_rate);
|
||||
}
|
||||
|
||||
private:
|
||||
// コンストラクタ
|
||||
// constructor
|
||||
Trainer(LayerType* target_layer, FeatureTransformer* feature_transformer) :
|
||||
batch_size_(0),
|
||||
previous_layer_trainer_(Trainer<PreviousLayer>::Create(
|
||||
@@ -161,23 +161,23 @@ class Trainer<Layers::Sum<PreviousLayer>> {
|
||||
target_layer_(target_layer) {
|
||||
}
|
||||
|
||||
// 入出力の次元数
|
||||
// number of input/output dimensions
|
||||
static constexpr IndexType kOutputDimensions = LayerType::kOutputDimensions;
|
||||
|
||||
// サブクラスをfriendにする
|
||||
// make subclass friend
|
||||
template <typename SumLayer>
|
||||
friend class Trainer;
|
||||
|
||||
// ミニバッチのサンプル数
|
||||
// number of samples in mini-batch
|
||||
IndexType batch_size_;
|
||||
|
||||
// 直前の層のTrainer
|
||||
// Trainer of the previous layer
|
||||
const std::shared_ptr<Trainer<PreviousLayer>> previous_layer_trainer_;
|
||||
|
||||
// 学習対象の層
|
||||
// layer to learn
|
||||
LayerType* const target_layer_;
|
||||
|
||||
// 順伝播用バッファ
|
||||
// Forward propagation buffer
|
||||
std::vector<LearnFloatType> output_;
|
||||
};
|
||||
|
||||
@@ -187,4 +187,4 @@ class Trainer<Layers::Sum<PreviousLayer>> {
|
||||
|
||||
#endif // defined(EVAL_LEARN) && defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user