Joeの精進記録

旧:競プロ練習記録

卒論名言集

1年前の卒論関連のSlackを見返していたらわりと面白かったのでまとめます

ちなみに締切は2/1だったみたいです。

1/19

DDCCの装置実装部門の話で盛り上がっている

1/20

けんしん「またライブラリの闇と戦っていたら1日が終了しかけている」

1/21

f:id:xuzijian629:20200121162623p:plain

f:id:xuzijian629:20200121162615p:plain

f:id:xuzijian629:20200121162711p:plain

(ラボ内締切というか、校正が必要なので初稿を1/24までに出してくださいみたいな話だった気がします)

1/22

ぼくがこどふぉで黄色になってやっとDiv2 & えづほから開放される

1/23

f:id:xuzijian629:20200121162914p:plain

1/24

f:id:xuzijian629:20200121162937p:plain

けんしんがnumpyの仕様と一日中戦っていた

f:id:xuzijian629:20200121163049p:plain

1/25

f:id:xuzijian629:20200121163204p:plain

1/26

f:id:xuzijian629:20200121163241p:plain

1/27

けんしんがインフル新薬の耐性菌のせいで熱が続いていてまだ登校できない問題

f:id:xuzijian629:20200121163414p:plain

1/28

けんしんの熱が下がる

f:id:xuzijian629:20200121163446p:plain

やっと実験結果が出たらしい

じょえたぷにきあくん笑が初稿を提出する。30枚5800 words

1/29

熱は下がったけど登校できないけんしん

f:id:xuzijian629:20200121163610p:plain

1/30 締切前日

やっとけんしんが登校。ほぼ大学にいたのであんまりSlackで話したことがない

2/1 締切

必死すぎてSlackの投稿が皆無。たぶんけんしんは一晩で2000 wordsぐらい生成してそう

define-by-runじゃないと困る問題

Hanjun-Daiのgraphnnがdefine-by-runじゃないせいで困った

複数グラフの、頂点ごとの確率を推論して、CrossEntropyしたい状況

  • batchあたりのlossを定義するために入力は複数グラフ(ひとつずつやってlossを足すということはできない)
  • グラフごとにCrossEntropyを計算したい
  • グラフの最大ノード数を固定したくない
  • でもsoftmaxするときに最大ノード数でreshapeしたい
  • muriyarokonnnan

強化学習アルゴリズム整理

久しぶりにPolicy Gradientやろうとしたら全部忘れていた

DQN

アルゴリズム

  • とりあえずプレイアウトして (S, a, r)をreplay memoryに保存する
  •  (S, a, r)と、その nステップ後の (S', a', r')を取り出してきて、後者の価値を古いネットワークで推定し、そこからrewardを逆算した前者の価値に近づけるように、新しいネットワークを学習させる
  • iter学習したら古いネットワークを新しくする

いいところ

  • replay memoryに保存してまとめてとってくるので、まとめて推論できて、高速だしsample efficient

Policy Gradient

アルゴリズム

  • 期待報酬 J(\theta)を最大化するように学習する
  •  \pi(s | a; \theta)は確率的
  • この勾配はpolicy gradient theoremによって求まる

f:id:xuzijian629:20200103190739p:plain

sykwerくんの記事が優秀

sykwer.hatenablog.jp

いいところ

  • まあこれも Mエピソード分の推論は同時にできるしそんなにスピード悪くなさそう
  • DQNに比べて何がいいのかわからんな

MCTS

アルゴリズム

  • 未展開ノードについたらその評価を推論して、そこまでのノードの評価をupdateする
  • visit回数に応じて、より強いpolicyを構築し、それに合わせるように学習する
  • スコアは相対的なものにする

いいところ

  • 探索があるので、一般に普通の評価より強いと思う
  • DQNのやつと組み合わせたらさすがにDQNより強いはずでは

S2V-DQNコードリーディング

https://xuzijian629.hatenadiary.jp/entry/2019/07/27/154356

以前環境構築についてまとめた

今回は実装を読んでいく。

MVCについて読むが多分構造は他も一緒

構造

eps_start = 1.0
eps_end = 0.05
eps_step = 10000.0
for iter in range(int(opt['max_iter'])):
    if iter and iter % 5000 == 0:
        gen_new_graphs(opt)
    eps = eps_end + max(0., (eps_start - eps_end) * (eps_step - iter) / eps_step)
    if iter % 10 == 0:
        api.lib.PlayGame(10, ctypes.c_double(eps))

    if iter % 300 == 0:
        frac = 0.0
        for idx in range(n_valid):
            frac += api.lib.Test(idx)
        print 'iter', iter, 'eps', eps, 'average size of vc: ', frac / n_valid
        sys.stdout.flush()
        model_path = '%s/nrange_%d_%d_iter_%d.model' % (opt['save_dir'], int(opt['min_n']), int(opt['max_n']), iter)
        api.SaveModel(model_path)

    if iter % 1000 == 0:
        api.TakeSnapshot()

    api.lib.Fit()

流れはこんな感じ。もろもろの関数はmvc_lib.cppにある。

  • 5000 iterおきにグラフをgen_new_graphsをしている。内部的にはグラフのプールを更新している。プールには1000個グラフがある(main.py)
  • epsilon greedyのepsをだんだん小さくしているっぽい
  • 10 iterおきにPlayGameしている。10回最初からterminal stateまで実行して、結果の列をNStepReplayMemに格納する。毎回グラフをプールからサンプルするっぽい。
  • 1000 iterおきにSnapShotをとっている。これが実は本質っぽいんだけど、lossの計算ではこの記事の一番下に書いてあるように、Snapshotをとったold_modelと、新しいmodelでの2つの予測結果の二乗誤差を考えている
  • iterでFitしている。これは、batch_sizeサンプルしてきて、nn_api.cppのFitを呼んでいる。
net->SetupTrain(batch_idxes, g_list, covered, actions, target);
net->fg.FeedForward({net->loss}, net->inputs, Phase::TRAIN);
net->fg.BackPropagate({net->loss});
net->learner->Update();

loss += net->loss->AsScalar() * bsize;

みたいなことが行われている。誤差の計算のところはmvc_lib.cppにあって

PredictWithSnapshot(sample.g_list, sample.list_s_primes, list_pred);

からの

for (int i = 0; i < cfg::batch_size; ++i)
{
    double q_rhs = 0;
    if (!sample.list_term[i])
        q_rhs = max(sample.g_list[i]->num_nodes, list_pred[i]->data());
    q_rhs += sample.list_rt[i];
    list_target[i] = q_rhs;
}

が行われている。PredictWithSnapshotは古いモデルでの予測結果っぽい。

のところ。

On the complexity of the embedding problem for hypercube related graphs

www.sciencedirect.com

説 明 が ウ ン チ ー コ ン グ

writerやめろ

概要

「木 Tと、正整数 kが与えられたとき、 T k次元hypercubeに埋め込めるか」という判定問題はNP-Complete.

まあこれが成り立つので、 Tはより一般にグラフ Gに拡張できる。

証明がExact Cover by 3-sets (X3C)によるもので、これまたテクニカル

X3C

集合 Xの部分集合で、サイズ3のものをいくつか集めた集合 Cが与えられる(Cは集合の集合)。 Cの部分集合で、 Xのdisjointな分割になっているもの C'が存在するか(このとき C' Xをカバーしている)

これはNP-Completeらしい。 Xの要素数が3の倍数でない場合は明らかに不可能なので3の倍数個としてよい。

帰着

X3Cインスタンスが与えられたときに、木 T kをうまく構築して、「木が k次元hypercubeに埋め込める」ことと「X3Cインスタンスが解をもつ」ことを同値にしたい。

f:id:xuzijian629:20191225183835p:plain

まず、カバーすべき集合を Xとしたとき、集合 S = X \cup {z}を考える。また、 k = |S|とする。

 T k次元に埋め込めるかは、 Tのノードに、 Sの部分集合を割り当てたときに、

  1. 異なるノードについて異なる部分集合が割り当てられており
  2. 隣接するノードについて、部分集合のset differenceの大きさが1

であることと同値。

 Tとしては上図のように構成する。上図のノード数はみやすさのため少なくなっているが、 Xは実は x_1, \ldots, x_{3q}になっており、たとえば XX x_1x_1, \ldots, x_{3q}x_{3q}になっている。ポイントはノード数がたかだか 3q + 1 = |S|多項式のサイズなので、X3Cのインスタンスが与えられると多項式時間で構築できることである。

図で Rの説明がものすごく雑だけど、 R q要素で、それぞれ XXX型の部分集合が割り当てられている。 C_4ノードが XXX\backslash Cの型を持っているので、 XXX型は C_4 Rに限られる。もし、 Tのノードに割り当てられる集合がすべて異なるなら、 R \subset Cが成り立つ。

 R C_8の辺のつなぎ方も重要で、とりあえず R i番目のノードに割り当てる部分集合を x_{3i - 2}x_{3i-1}x_{3i}にしておく。これは本当はこうならないかも知れないけど、 x_kのネーミングはあとで適当にある順列によって差し替えることができるので、気にしなくていい。

とりあえずこれで構築は完了

X3Cインスタンスに解がある場合

 C' q要素からなるので、 R C_8を結ぶ辺は、 R j番目の要素とつながっている C_8の要素のラベルを、 C' j番目の集合にすればいい。このとき、明らかにノードのラベルは全ノードで異なっているので、 T k-cubeに埋め込むことができる。

X3Cインスタンスに解がない場合

つまりどう選んでも、 C'の各要素(集合)がdisjointにならない場合。  Rが要素数 q'tex: Cの役割を果たしているので、もし埋め込めるとしたら、そういう C'が見つかって矛盾。