日記

日記です

0512

大学

 10時過ぎに研究室着。遅くなってしまった。さらに午前中はモチベーションが上がらずボーっとしていることが多かった。研究室のパソコンで学習を回してしまうと作業ができなくて困る。ノートパソコンだとどうもねぇ。これ結構深刻なのでどうしよう。もう一つパソコンが欲しいとか言って買ってもらえるのかなぁ。

 仕方がないからいくらか論文を漁るくらいしかしていなかった。しかし読んだ論文の良いまとめ方がわからないなぁ。いろいろなパソコンを使いうるので上手くクラウド的に管理したいところだけど、どうすればいいのかわからない。PDF保存までいくと大変だから出典とか置くくらいか。しかしダウンロードするたび大学がお金払っているんだっけ。うーん。

 テキスト形式でまとめているとやはり見栄えが悪そうだから、まとめスライド1枚作るとか実践的なのかなぁ。パラパラ見返してくのは便利そうか。あとは検索性の問題があるわけだけど。

 一覧性は欲しいがそこから詳細へも飛びたいとなるとハイパーリンクが欲しくて、結局ブログにまとめてしまうのが良いのではとかちょっと思ったり。さすがに公開はしたくないので非公開ブログを作るとかはありかなぁ。

将棋

 叡王戦第3局は千日手になった。これが本当にもうすごくて、金井六段が最後頭抱えながら千日手を選んだところで僕はもう感極まってしまったんですね。これは普通に負けるより辛いのでは。この局面で、自分は勝てないと自分で判決を下すわけなのだから。僕は何かと自分の意志で何か重大な選択をするというシーンに弱い。

 ふと思い出したのは虐殺器官だった。人を殺すことに抵抗はないのに、母の死を決定したことは引きずり続ける主人公の内省が続く小説である。自分の行動の中でも自由意志を感じる重みは平等でない。重さが、この千日手の決定にはあったのではないか。

 負けは相手という抗えない力によって引き起こされる事態と見ることもできる。しかしこの千日手は……。

 最後の千日手を決めた1分間。金井六段の頭の中には何が駆け巡っていたのだろう。

 僕の中でエモさが爆発してきてしまった。

 指し直し局で金井六段は破れました。辛いとか、そんなレベルではないのだろうな。

0511

大学

 9:51に研究室着。

 最近、表現が得られている後の回帰をすることと(たとえばkkp_kpptを用いて学習)と、表現自体を学習しなければならないDeepLearningの断絶を強く感じる。

 あとは「こんなことやってみました~」って研究はやっぱりちょっと変だなって気もして、ちゃんと仮説と分析を重ねたものであってほしいなぁという気持ちがある。自分がそういうことをできるかというと全く自信はないわけだけど。

 やることが迫ってきて精神が無になってきた。

将棋ソフト開発

 データの容量に問題が多い。そもそもとして今は各要素を2byteで取っていて、要素の数はkkp {81 * 81 * 1534 = 10064574}, kpptが  { 81 * 1534 * 1534 * 2 = 381211272}なので全部で782.551692 メガバイトだそうです(Googleに計算式をぶちこんだ)

 けれど出力されるパラメータのバイナリファイルは764,211 KBと表示されていて、あれーという感じ。ひょっとしてkkpの分が上手く保存されてない……? しかしkpptの分だけだと762.422544 メガバイトのはずで、これもちょっと違う。なにもわからない。

 しかし適当に確保したパラメータを書き出し,読み込みしてみても多分変わってない。データが吹っ飛んでいるとかならわかるんだけどなぁ。ちゃんと保存できてるなら良いかなとは思いつつ、しかしこれは気持ち悪いなぁ。

 パラメータを0初期化する関数はバグっていた。memsetの使い方よくわからなくて怖いので全要素をなめて0を代入するしょうもない実装でいきます。ちょっと速度で損しているんだろうけど、0初期化するタイミングなんてそうそうないし。

 学習させるとメモリをバカ食いする問題もある。学習用パラメータとしてfloat,勾配としてfloat,対戦相手用としてint16_t,の3種類を新たに用意するので上の6倍メモリを使うことになるはずで、4.69531015 ギガバイトのはず。しかしタスクマネージャーで確認するとそれより多くのメモリを確保している。探索部でhistoryとか確保するからこれよりは多くなるとは思うんだけど、それほどか?

 scoreは先手のとき

kkp_score_ + kpp_score_[BLACK] - kpp_score_[WHITE] + turn_bonus

となり,後手の時は

-kkp_score_ - kpp_score_[BLACK] + kpp_score_[WHITE] + turn_bonus

となるので勾配としてもこの符号でいいはず? それでやってみよう。

 やねうら王とか読み太とか読んでいるとなんかルート局面の手番を持っている気がする。下は読み太のeval_pptp.cpp

    // 現在の局面で出現している特徴すべてに対して、勾配値を勾配配列に加算する。
    void addGrad(Board& b, Turn root_turn, double delta_grad)
    {
        // 手番を考慮しない値と手番を考慮する値
        auto f = (root_turn ==    BLACK) ? LearnFloatType(delta_grad) : -LearnFloatType(delta_grad);
        auto g = (root_turn == b.turn()) ? LearnFloatType(delta_grad) : -LearnFloatType(delta_grad);
        auto list = b.evalList()->pieceListFb();

#ifdef USE_AVX
        WeightValue w;

        for (int i = 0; i < M_CNT; i++)
            w.m[i] = _mm256_setzero_p();
#else
        WeightValue w = { 0 };
#endif
        double progress = Progress::evaluate(b);
        int pro = int(progress * 6.0);
        pro = (pro < 0 ? 0 : pro > 5 ? 5 : pro);
        
        w.p[0] = f;
        w.p[1] = g;
        w.p[2 + pro] = f;

        for (int i = 0; i < PIECE_NO_NB; ++i)
            for (int j = 0; j < i; ++j)
                ((Weight*)pptp_w_)[getPpIndex(list[i], list[j])].addGrad(w);
    }

 わからない。現局面でのスコアは現局面でのスコアなんだからルート局面の手番とか関係なくない? なんでそれによって値を反転させたりしているんだ……。winnerの見方とかが違うだけという気がする。そうじゃないかなぁ。

 メモリバカ食い問題はなんか直っていた。4.5GBくらいで想定よりちょっと少ない。これはWindowsのファイルとして表示されている量の6倍に近いけどぴったり一致するわけでもなく、むしろ小さいってちょっと負担になりませすね。メモリを管理するの大変だなぁ。

 あとはX手で引き分けというのと、千日手のスコアをUSIオプションとして指定できるようにしたい。学習の時も有用か?千日手、理念的には評価値0かなとも思うけど、先後入れ替えて指しなおしというルールなら先手番の初期値を反転した値がふさわしいはずですかね。

 コンピュータ将棋、モチベーションが全てだという感じがあるし、ただ時間があるだけではなく何も他にやるべきことが存在していない状況が必要。つまりそろそろダメになってきます。大学……。大学……!

その他

 今日は何度もお茶をこぼした。悲しい。

0510

大学

 10時ごろに研究室へ。ちょっと朝が遅いなぁ。もうちょっと早く始動できるようになりたい。

 午前中はSIMD演算を書く。ちょっと複雑なプログラムだと書き始める前にグッと気合いを入れる儀式が必要になる。自分にも書けるはずだと思い込まねばならない。

 やるべきことを多少思い出して憂鬱になる。コンピュータ将棋をやるにあたって大学邪魔だなぁと思うことも多いけど、kumaさんという前例が発生したので「休学すれば?」で論破されてしまう。さすがに4年生で休学って現実的ではないのでは、とか思ってしまうけど、しかし現実とは。コンピュータ将棋こそ現実なのではないか? まぁ休学よりは退学の方がありそう。いや絶対しないけどね。

将棋ソフト開発

 差分計算を書き直した。頭が悪いので今までPositionクラスがkpp_score_を変数として1個だけ持っていたので差分計算で符号が先手玉についてと後手玉についてでぐちゃぐちゃして大変だったんだけど、これをkpp_score_[2]という配列にして先手玉についてと後手玉についてそれぞれ持つようにしたら多少簡単になった。実際に点数を返すタイミングでkpp_score_[BLACK] - kpp_score_[WHITE]とすればいいんですね。なるほど。知能がなかった。こういう細かい実装部分がなぁ。

 しかしSIMDを使うと計算が合わない。うーん、なんでだろう。

 そういえば昨日速度がどうこうって言っていたのは見間違えでした。初期局面を検討モードでしばらく開いた時のを目視で確認しただけだけど、自分のノートパソコンでYaneuraOu4.79(elmo評価関数)が

1Thread : 921kNPS
4Thread : 1682kNPS

 くらいで、海底が

1Thread : 400kNPS

 くらいなので半分くらいですか? まぁこれランダムに初期化した評価関数での速度なので実際に学習させたらどうなのかは知らないけど。

 というか4ThreadにするとかなりNPSも伸びるんですね。hashのヒットをやねうら王も数えているんだっけ? 探索ノード数の数え方が合っているのか自信がない。2倍くらいしか差がないって本当か? 感覚的にはもっとありそうな気もするんだけど……。

 SIMDを導入成功した。

初期局面で60秒探索したNPS

SIMD無し : 443428
SIMD有り : 518124

 1.17倍速いっぽい。だいたい野田さんが言っていたのと同じくらいか。他の部分が遅くてあんまり効果ないかもとか思ってたけどそんなこともなかった。

 なんか時間が経過するとNPSどんどん上がっていくんだけど、合っているのか? まぁハッシュとかにヒットすることが増えるとなるとそうなのかな。

 しかしまだまだ遅いなぁ。無駄に情報を保持、更新していたりするので、そのへんをなんとかやっていければいいんじゃないかと。それでも2倍以上速くなる気はなかなかしないが。

 とりあえず学習回してみるところまで行ったけど全然ダメだった。ちゃんと微分しなきゃ……。精神が落ち着かなくて計算ができない。

動画

 久しぶりにVTuber、というかにじさんじの動画をちょっと見た。

 鈴鹿詩子さん、普通のオタクでは。いや普通ではないけども。

 樋口楓さん、つい興味を惹かれてしまうような不安定さがすごくてこれは狙ってやっているとしたらすごいキャラクターだなぁ。

 剣持刀也さん、結構面白いのでは。

その他

 何もしていないのに時間が過ぎていく。なんで???

 何もしたくない……。

0509

大学

 10時頃に研究室へ。なんか学習が途中で止まっていてassertに引っかかっているしこれはバグっぽいなぁ。原因がわからず。

 ほぼずっとコンピュータ将棋やっていた。

 サーベイミーティングを経て、19時ごろに帰宅。なんか僕にも発表の順番が回ってくるらしい。コンピュータ将棋に集中したいのに……。輪講のもあるし、なんだかなぁ。

将棋ソフト開発

 gitの使い方がよくわからない。ブランチ作ったはずなのにmasterにも同じ更新が反映されてしまっているぞ。

 相変わらず多次元配列が確保できない。「配列サイズの合計は 0x7fffffff バイトを超えることはできません」って、動的に確保するものなんだからclass定義では許してほしいんだけどなぁ。

 読み太のソースコードを読んでみるがどうやっているのかわからない。どうでもいいけどeval_kppt.cppの113行目みたいなコメント好き。

        // せめてkk, kkpだけでも先に解放してやる。

 囚われていた子供を助け出すシーンみたいじゃないですか?

 なんか普通に配列として確保すればdouble型(64bit必要な型)を使わなければコンパイル通るし実行も可能になった。floatでも学習は大丈夫と信じればこれで良いことになる。

 そして点数計算について考えてみるが、やはりKKPとかKPPTとかの根本的なところをちゃんと理解できていないということが明らかになってくる。なんでKKPは反転したものを考えなくていいのかとか、KPPTの手番の足し方とか、実装しようとすると全然わからない。KPPTの符号を間違えずに実装できる気がしない。頭が爆発する。

 とりあえず差分計算は書けた気がする。テストが甘いので気がするだけ。しかし30万NPSとかしか出ませんねぇ。同じ環境で強いソフトは1500万とか出るし、わかりやすく64倍の差があるとすると、2倍でレート150とか言われている気がするから速度差だけでレート900差ですか。まぁでも逆に言えばそれだけとも言える。同じKKP_KPPTを使っているソフトでレート4000とかあるなら、ここから高速化なしで3000くらいは行けておかしくないってわけですか。全く行ける自信はありませんなぁ。

あとで気づいたけどこれ一個桁間違えてるので全部嘘ですね。明日の記事で修正します。

 実際のところは学習の速度にも影響するから高速化はできるだけ早く手を付けるべきだろう。とりあえずSIMDは頑張って導入したい。でもこれタダのパクりなんですよね。結構苦労はしているけど苦労自慢には意味がないし、やっていくしかない。

 探索ノード数あたりの強さもひどいんだろう。探索ダメダメなので無駄な手をいっぱい読んでいるに違いない。

 並列化もしていないし、やることは多い。この半年間サボっていたので当然ですね。それらを全部やったとして、どのくらいのところまで伸びるんだろうなぁ。

 どうせ今みたいな高いモチベーションは2週間くらいしか続かないので、2週間のうちにガガっと強くできなければ終わりです。そういうことに最近気づいた。

Twitter

 煽られている……。実際Squirrelは2駒で強くできたっぽいのに僕はさっさと3駒の方に移行しようとしているの、逃げているという感じはある。でもSIMD計算の部分を何回も書きたくはないという気持ちがあり、やるならさっさと最先端の評価項目を使ってしまおうと。むしろこれで強くできなかったらより言い訳が気かないという面もある。しかし世の中的にはもう3駒関係なんで時代遅れだよねーっていう感じなのかもしれない。時代に遅れる人間だ。

デレステ

 コンピュータ将棋ばっかりやってるわけではないことの証明としてデレステの話をします。

 いつの間にか投票期間が終わっていた。だいぶサボっていたので36票でした。期間とかに余裕があれば(SSRがうちに来たばかりの)大石泉さんとかにも投げようと思っていたんだけど、まぁ、ね。

 北条加蓮さん、SSR3週目来ないんだろうか。300連分はずっとキープしているんだけど。ラブデスの衣装が来ていたのもあって早くガシャ回すタイミングが欲しいなー。

 最近ちょっと音ゲー部分も再開しだして、とりあえず普通の方のnewは消した。スマートの方は……ちょっと面倒くさいなぁ。

将棋

 名人戦はあまりまともに見られなかったけど、角換わりのなんか比較的じっくりした将棋で、いつの間にやら竜王の方が良くなっていたという感じ(知らんけど)。

その他

 競技プログラミングも毎日ACは止めて、Twitterも毎日ツイート縛りを止めて、日課はこのブログだけになった。

 おそらく一年後の自分が読むんだろうし、そういう意識でもって書くとシャンとしてくる部分がある。いや、あまりない。

 僕は僕のセンスが好き(自明)なので、適当に思ったことを書いていればいいだろう。

 WCSC28の振り返り記事みたいなの、要るかぁ? 出遅れた感がある。

 まぁいいだろう。何もなかった。何もね。

0508

大学

 10時ごろに研究室へ。とりあえずずっと将棋ソフトを書く。5限に講義に出る。舟をこぎながらなんとか耐える。またコンピュータ将棋をやる。20時頃帰る。

将棋ソフト開発

 高速化したとしてたかが10%なんだよなぁと思ってとりあえず今日は気合でkkp_kpptを書こうとした。手番の部分をどう扱えばいいのかさっぱりわからなくてぎゃーぎゃー言いながらなんとか分かった気がするけどメモリが全然上手く扱えない。動的に多次元配列を確保できない雑魚プログラマ。しかしクラスの内部に配列を取ろうとしているのが間違っているのか……? 動的配列にするとメモリ上でちゃんと連続性が満たされるのかもわからない。とりあえずグローバルに置けば大丈夫っぽいことはわかったけど学習の時は結局動的確保が必要だからそれで妥協するわけにもいかない。すべてをstd::vectorに任せたくなってしまう。それはダメそう。どうすればいいのかよくわからないなぁ。

その他

 Twitterのプロフィールにはこっちじゃない方のブログを載せることにした。それが正しい。こっちは相当来訪者減るだろうな。インターネットの中にあり、誰にでも見られ得るが実際には誰にも見られないという場所。そういうところになってきた。

 つらいことは多い。しかしこれは自分の能力、人格からすれば必然的なものであって、いま特別運が悪いということではないのだ。それがさらにいっそう強いつらさを呼び起こす。これが普通の状態、そうなのだ。あと何年これが続きますか……? 何年という話ではない。

0507

大学

 9時過ぎに研究室へ。論文をちょっと読んだりしたけどほとんどコンピュータ将棋をやっていた。

 5限も講義があったけど教室には行ってその場でコンピュータ将棋をやる。話を聞いていなかったので講義終了時にやるクイズがさっぱりわからなかった。

 このように邪悪に染まっています。

将棋ソフト開発

 進捗

 pure2駒の高速化なんてやってどうするんだという気もするんですが、できればちゃんと検証したい。いやそういうのはもっと余裕がある人がやるべきなのか……。

その他

 22時ごろにベッドに倒れ込んだらそのまま寝てしまっていたようだ。こんなことあまりないんだけど。やっぱり疲れているのかなぁ。

0506

将棋ソフト開発

 Apreyのソースコードを読み始めた。さっそくcommon.hppの120行目あたりの意味が分からない。

// Binary表記
// Binary<11110>::value とすれば、30 となる。
// 符号なし64bitなので19桁まで表記可能。
template <u64 n> struct Binary {
    static const u64 value = n % 10 + (Binary<n / 10>::value << 1);
};
// template 特殊化
template <> struct Binary<0> {
    static const u64 value = 0;
};

 なんでstructで再帰みたいなことができているのか? いやできるものなのか……。というかこれって普通に書けないのかな? わからない。Unrollerも同様。

// N 回ループを展開させる。t は lambda で書くと良い。
// こんな感じ書くと、lambda がテンプレート引数の数値の分だけ繰り返し生成される。
// Unroller<5>()([&](const int i){std::cout << i << std::endl;});
template <int N> struct Unroller {
    template <typename T> FORCE_INLINE void operator() (T t) {
        Unroller<N - 1>()(t);
        t(N - 1);
    }
};

 ねね将棋も公開されていた。どう読んでいくのがいいものか。

 あとは手番を評価関数に導入することについて考えていた。つまりKPPTとかのこと。なんとなくわかる気はするんだけど、具体的に学習をどうやればいいのか、どんな情報を持てばうまく勾配が求まるかということがわかってこない。じっと心を落ち着けて手計算で微分してみるのが一番速い気がする。こういう時に頭の悪さを強く感じる。

 ちゃんといろんなタイプの評価関数を比較してみたい気もするが、そういうのは計算資源富豪に任せたほうが良いのかな。デスクトップ1台しかないし、KPPTとかちゃんと学習させられる気がしないんだけど、どうしましょう。

 つらいことは多い。なんとかやっていかなければ。

その他

 無を感じた。

 無限の時間が欲しい。

 カープは負けました。