まずは、二値分類のプログラムを書こうと思います。
そのために、ランダムに超平面を作ります。しかし、超平面をランダムに作ろうとすれば、法線ベクトルをランダムに作る必要があります。すなわち、これは超球面上にランダムに点を打つことになります。
最も簡単な方法は、xi ∊ [-1, 1]を生成し、超球面上に原点方向へ射影することです。しかし、これはダメです。二次元で考えても、x軸方向より(1, 1)方向からに射影される点のほうが多いです。
正確で簡単な方法は、同様に超立方体上に点を打ち、それがその超立方体に入る超球内なら超球面上に射影する方法です。しかし、これは次元が高くなると非現実的になります。
これによると、n次元で超立法体に占める超球の割合は、
小さな次元で割合を具体的に計算すると、
2 3 4 5 6 7 8 9 0.079 0.524 0.308 0.164 0.081 0.037 0.016 0.006
このように、次元が高くなると急速に小さくなります。
検索してみると、次のような方法が知られていることがわかりました。
各座標成分を正規分布でランダムに出して、それを球面上に射影すればよいと。なるほど。
正規分布に従う乱数にはBox-Mullerを使う。
これで、1000次元でも高速に超球面上にランダムに点を打つことができますね。
from math import sqrt, log, cos, pi import random def Box_Muller(): r1 = random.random() r2 = random.random() return sqrt(-2.0 * log(r1)) * cos(2.0 * pi * r2) def random_hyper_sphere(D): xs = [ Box_Muller() for _ in range(D) ] r = sqrt(sum(x * x for x in xs)) return [ x / r for x in xs ] D = 6 N = 20 format = "%10.6f" * D for k in range(N): xs = random_hyper_sphere(D) print format % tuple(xs)