ちょっとした用事のために、家にいないといけなかったので、リモートワークをした。 仕事は手につかなかった。 要件はものの15分で終わった。
洗面所の排水溝を掃除した。 いつも、どうせならお風呂に入る前に掃除したらいいのに、お風呂に入ってる間に掃除したくなる欲求が湧いてくるものだから、順序が逆になってしまう。 この家に引っ越してから洗面所を掃除するのは二度目だから、よっぽど掃除を避けている箇所である。 最も汚れている排水溝なのだ。 おそらく、歯磨き粉を流し、手洗い石鹸を流すからだろうと思う。それらが固まって、ヘドロになってしまっている。見るに堪えがたい。 歯磨き粉を使わずに歯を磨いても良いのであれば、使うのを辞めるのだが。
学習データやテストデータは十分多くてすでに真の分布を表すものだとしよう. だとすれば分類の結果の分布は真の分布に近くあってほしい. でないと真の分類をしているという感じがしない.
例えば, 正例と負例とが 9:1 な偏ったデータだとする. 偏ったデータをうまく学習するテクニックは色々あるがそれはおいておいて。 テストデータでもやはり 9:1 だけ混じっているのだから, それを分類してみた結果はやはり 9:1 あることが望ましい. もちろん accuracy だけを見ると下手に 9:1 であるように矯正すると下がり得るけど, こちらのほうが真の分類をしてる感じがある.
生成についても同様. MNIST はだいたい "0" から "9" までが同じ枚数だけがデータにあるようになっている. だから 1:1:...:1 が真の分布だと言える. 素のGAN で問題になるのはいわゆる mode collapse ですなわち, 生成しやすい一文字 (私の経験上それはだいたい "8" であることが多い) だけを生成するようになってしまう問題がある. 分類のときと同様にやはり 1:1:...:1 で生成されるのが真の生成という感じがする.
GAN のバリエーションを担保させるテクニックはいくらでもあって, バッチの単位で計算をするのだから, そのバッチの中のエントロピーやなんかを大きくさせるようなロスを追加するとか, Discriminator にエントロピーを渡してしまう(mode collapse に陥ったときのエントロピーは特徴的だから, 生成データであることが見抜きやすくなる)というのも聞いたことがある.
私も一つ思いついた. Discriminator とは別に(あるいは併用してもいいかもしれないが)Label Classifier を後ろにくっつける. Label Classifier は生成されたデータのラベルを推定し, それは \(p = (p_i)_{i=1,2,\ldots,10}\) という10次元実ベクトルの形をしている. これをバッチの中で各生成データについて推定すれば, バッチのサイズを \(B\) とすれば \(B\) 個の実ベクトル
\[p^1, p^2, \ldots, p^B\]が手に入る. これの平均を取る.
\[\frac{1}{B} \sum_i p^i\]先程言った真の分布に近いならこのベクトルは
\[(0.1, 0.1, \ldots, 0.1)\]であるはずだ. というわけでこのベクトルどうしの KL 距離をロスに加える. 生成をしてから分類して結果の平均を取るまでの操作は全て微分可能.
データにラベルがあるのなら話は楽だ。出力にも入力にも使えるから。 しかしながら、ラベルというのは目的に沿って人間が付与した単純な一つのクラスタに過ぎない。 それを超えた常識みたいなのを作ることが必要。
いつかの日記に、GANのmode callapse を防ぐのにラベルを使えばどうかなどと書いたが、 初めから入力にラベルを与えて conditional にすればいいだけだったことに今日気がついて、 やることを失くした。 それどころか、単にラベルの予測と Discriminator を兼ねさせるだけでも十分 mode collapse が抑えられることを自分も昔確認したのを思い出した。 cympfh/GAN-semisup-MNIST-Keras この予測器及び判別器は最終層手前までは共通で、最後だけ、10クラス分類とするか、真偽の判定とするかに分岐している。 今思えば、11クラス分類(10クラス + 偽クラス)としても良いかもしれない。
論理を作る。ニューラルネットで。 AND とか OR とか全てのゲートを用意して構成するのは当然出来るに決まっている。 もちろん XOR を作ることが出来るので、原理的に作ることもできる。 そんなことを考えなくても、例えば A IMPLIES B
を NOT A OR B
などと定めることをしなくても、個々のゲートを訓練すれば、 常識的な方法で常識的なものが出来るだろう。 もしかしたら、僅かな確率で A AND NOT A
が成り立ったり、三段論法が成り立たないことがあったり、人間的で面白く見えるものが出来上がるかもしれない。
でも所詮疑似科学だ。
個人的には最近はトポスに傾倒している。 細かいことを省けば、トポスというのは subobject classifier というものが備わっているもののことで、その機能があればイコールとか AND とかが作れる。 subobject classifier というのが何か。これまた不正確で雑な説明をすると、部分集合判定器である。 すなわち \(A \subseteq B\) という部分集合があったときに
\[\begin{align*} cl(b) = \begin{cases} \mathrm{true} & \text{ if } b \in A \\ \mathrm{false} \end{cases} \end{align*}\]という関数 cl が作れる。 トポスというのは任意の部分集合についてこのような関数が構成出来ることを言う。
すると例えば、集合 \(A\) の上のイコールは
\[\{ (a, b) \mid a,b \in A, a=b \} \subset A \times A\]の subobject classifier だし、AND は
\[\{ (\mathrm{true}, \mathrm{true}) \} \subset \Omega \times \Omega\]である。 ただしここで \(\Omega = \{ \mathrm{true}, \mathrm{false} \}\) 。
これが大してすごそうに思えないのは、部分集合というのが単純だからだ。単純というのは、属しているか、属していないかの二値だから。 これは cl の値域が true, false の二値であることに対応している。 ていうか集合論だと関係とか関数というのは結局 \(A \times A\) の部分集合で定義できるから、それはそうなんだよな。 上は「部分集合を定義すると、関係とか関数が定義できます」っていうのを丁寧に言っているだけ。
さてトポスは集合に上に成り立っているものではないので、一般に何にでも応用できる。 fuzzy logic とかみたいに曖昧なもの(それは例えば "true である確率" みたいに)をそのままのフレームワークで扱うことが出来る。 その場合の cl は上のように単純ではない。 \(\Omega\) も二値ではなくなるし、イコールも AND ももっと興味深いものになるかもしれない。
で、これをニューラルネットで実装するには? cl の部分を構成出来ればいい?
最近いつも眠たいので、自分の発言が夢の中での発言だったのか、それがあまりに他愛ないので誰かにした世間話だったのか、上手く思い出せない。
テーブルの斜め向かいの人が、アナログカメラがどういうと言っていて、デジタルカメラに対しての「アナログカメラ」のことだろうと推測し、 私が「フィルムカメラのことですか?」と言うと、思い出したように「あ、それそれ」と笑っていた。
夢の確率が7割、現実の確率が3割。
目覚まし時計の代わりに洗濯機を使うという話をした。 洗濯機が回る音だけでなく、干すという行為を半強制するのが目覚ましの役割を持たせるとかどういう話した。
こちらは現実の確率が8割強ある。 書いてて夢じゃなかった気がしてきた。
最近の趣味は Awk と sed。 どちらもその気になれば結局シェルスクリプトを呼び出せるというのが強い。 シェルスクリプトが呼び出せれば例えばRubyインタプリタを呼ぶことで Ruby も書けるということだ。 言語というのは案外他の言語を内に含めることが出来るので、表現能力はみな等しい。
形式言語と比較して自然言語のパースの難しさや意味解釈の曖昧さを思うにつけて、自然言語は残念に思う。 例えば日本語の中に名詞レベルでならば英語を含めることが出来る。 「昨日、うちで飼ってる dog がさ〜」なんて言っても、とりあえず会話が出来る。 形容詞まで行くと違和感が大きい。 「うちで飼ってる dog があまりに cute でさ〜」なんて言うとふざけてると思う。 それでも通じるのは単語レベルだからだ。 文単位で、英語を混ぜるのはさすがに無理がある(英文を引用している場合は意味が異なるので今は考えてない)。 仮に混ぜても問題ないと思っているのなら、「日本語を理解できる」ことは「英語を理解できる」ことを含んでなければいけない。 そのようなことを要請するのは無茶だろう。
何が言いたいのかと言えば、簡単に他の言語を混ぜることの出来るプログラミング言語はなんと表現能力豊かなのだろう、という話である。