← 研究ノート一覧へ
ベクトル(数学C)

キャラベクトル

〜「似ている」を測る〜

このノートで考えること

ゲームのキャラを「力・魔法・技」の3つの数字で表したとき,2人が どれくらい似ているか を,ひとつの数値で言い表せるでしょうか。

登場キャラクター

カードを押すと全身が見られます

ステータス画面はベクトルだった

戦士アルファのステータス画面から始めよう。

力 80魔法 −20技 20⟶a⃗=(80,  −20,  20)\text{力 } 80 \quad \text{魔法 } {-20} \quad \text{技 } 20 \qquad\longrightarrow\qquad \vec{a} = (80,\; -20,\; 20)

いくつかの数字をひとまとめにしたものがベクトルである。順番さえ決めておけば,3つの数の組でキャラ1人を表せる。

ステータス画面がベクトルになる

4人のキャラを並べる

4人のパーティを考える。

戦士アルファ
力 80
魔 −20
技 20
(80, −20, 20)(80,\ -20,\ 20)
騎士ベータ
力 75
魔 −15
技 20
(75, −15, 20)(75,\ -15,\ 20)
魔法使いガンマ
力 10
魔 65
技 25
(10, 65, 25)(10,\ 65,\ 25)
賢者デルタ
力 −70
魔 85
技 5
(−70, 85, 5)(-70,\ 85,\ 5)

戦士と騎士はパワータイプ,魔法使いと賢者は魔法特化で,とくに賢者は力がマイナスに振り切れている。

内積を計算してみる

2人の「似ている度」を測る第一歩が内積である。成分ごとに掛けて,足すだけ。

a⃗⋅b⃗=a1b1⏟力+a2b2⏟魔法+a3b3⏟技\vec{a}\cdot\vec{b} = \underbrace{a_1 b_1}_{\text{力}} + \underbrace{a_2 b_2}_{\text{魔法}} + \underbrace{a_3 b_3}_{\text{技}}

戦士と騎士なら

a⃗⋅b⃗=80⋅75+(−20)(−15)+20⋅20=6000+300+400=6700\vec{a}\cdot\vec{b} = 80\cdot 75 + (-20)(-15) + 20\cdot 20 = 6000 + 300 + 400 = 6700

どちらも力が高いので力の項が大きく伸び,どちらも魔法がマイナスなので魔法の項も(マイナス × マイナスで)プラスに効いている。

ところが,内積は「強さ」でも変わる

ここで立ち止まる。知りたいのはタイプの近さなのに,内積は強さにも反応してしまう。

向きがまったく同じで,強さだけ2倍のキャラを考えると,内積もちょうど2倍になる。タイプは同じはずなのに,「強い」というだけで値が大きくなってしまう。

向きは同じでも,長さが2倍なら内積も2倍
体験長さだけ変えて内積を見る
内積 a·b—
|b|—
cos θ—

内積は倍率にぴったり比例して増えるのに,
cos θ は 1 ミリも動きません。

キャラの向きを固定したまま長さだけを伸ばすと,内積がそれに比例して増えていきます。一方で「向きは変わっていない」ことも同時に表示されます。この食い違いが,次の一手の理由です。

大きさで割って cos⁡θ\cos\theta

そこで,内積を2人の大きさで割る。

cos⁡θ=a⃗⋅b⃗∣a⃗∣ ∣b⃗∣\cos\theta = \frac{\vec{a}\cdot\vec{b}}{|\vec{a}|\,|\vec{b}|}

大きさは三平方の定理と同じで,成分の2乗の和の平方根。4人ぶんを先に出しておく。

戦士アルファ ∣a⃗∣=7200≒84.9\lvert\vec{a}\rvert=\sqrt{7200}\fallingdotseq 84.9
騎士ベータ ∣b⃗∣=6250≒79.1\lvert\vec{b}\rvert=\sqrt{6250}\fallingdotseq 79.1
魔法使いガンマ ∣c⃗∣=4950≒70.4\lvert\vec{c}\rvert=\sqrt{4950}\fallingdotseq 70.4
賢者デルタ ∣d⃗∣=12150≒110.2\lvert\vec{d}\rvert=\sqrt{12150}\fallingdotseq 110.2
大きさで割って cosθ

これで長さの影響が消え,純粋に向きだけの指標になる。この値は必ず −1-1 から 11 の間に収まる。その根拠が次の不等式である。

もう少し詳しく

なぜ必ず −1-1 から 11 に収まるのか

コーシー・シュワルツの不等式:任意のベクトル a⃗,b⃗\vec{a}, \vec{b} について ∣a⃗⋅b⃗∣≤∣a⃗∣ ∣b⃗∣|\vec{a}\cdot\vec{b}| \le |\vec{a}|\,|\vec{b}|。等号は2本が平行なときに限る。

証明は3行で済む。実数 tt について ∣a⃗+tb⃗∣2≥0|\vec{a} + t\vec{b}|^2 \ge 0。展開すると

∣b⃗∣2t2+2(a⃗⋅b⃗) t+∣a⃗∣2≥0|\vec{b}|^2 t^2 + 2(\vec{a}\cdot\vec{b})\,t + |\vec{a}|^2 \ge 0

tt の2次式がつねに非負なので判別式が 00 以下:

4(a⃗⋅b⃗)2−4∣a⃗∣2∣b⃗∣2≤04(\vec{a}\cdot\vec{b})^2 - 4|\vec{a}|^2|\vec{b}|^2 \le 0

整理すれば主張を得る。両辺を ∣a⃗∣∣b⃗∣|\vec{a}||\vec{b}| で割れば ∣cos⁡θ∣≤1|\cos\theta| \le 1。cos⁡θ\cos\theta の値域は,この1行が保証している。

そして等号が成り立つのは2本が平行なとき,つまり b⃗=ka⃗\vec{b} = k\vec{a} と書けるときである。さきほど考えた「向きは同じで強さだけ2倍」のキャラは,まさにこの等号成立の場合だった。

cos⁡θ\cos\theta の3つの目印

値の意味を3つの位置で確認しておく。

なす角cos⁡θ\cos\theta意味
0∘0^\circ11同じ向き(配分がまったく同じ)
90∘90^\circ00直角(まったく別のタイプ)
180∘180^\circ−1-1逆向き(正反対のタイプ)
逆向き・直角・同じ向き
体験角度を回して cos⁡θ\cos\theta を見る
cos θ = 0.500

2本の矢印の間の角度をスライダーで 0∘0^\circ から 180∘180^\circ まで回すと,cos⁡θ\cos\theta の値が 1→0→−11 \to 0 \to -1 と連続的に変わります。どのあたりから「似ていない」と感じるか,自分の感覚と比べられます。

戦士から見た3人

戦士アルファを基準に,残りの3人との cos⁡θ\cos\theta を計算する。

戦士アルファ × 騎士ベータ 騎士ベータ ほぼ同じタイプ
a⃗⋅b⃗=80⋅75+(−20)(−15)+20⋅20=6700\vec{a}\cdot\vec{b}=80\cdot 75+(-20)(-15)+20\cdot 20=6700
∣a⃗∣=802+202+202=7200,∣b⃗∣=752+152+202=6250|\vec{a}|=\sqrt{80^2+20^2+20^2}=\sqrt{7200},\quad |\vec{b}|=\sqrt{75^2+15^2+20^2}=\sqrt{6250}
cos⁡θ=67007200 6250  ≒  0.99\displaystyle \cos\theta=\frac{6700}{\sqrt{7200}\,\sqrt{6250}}\;\fallingdotseq\;0.99
戦士アルファ × 魔法使いガンマ 魔法使いガンマ 直交=別タイプ
a⃗⋅c⃗=80⋅10+(−20)⋅65+20⋅25=800−1300+500=0\vec{a}\cdot\vec{c}=80\cdot 10+(-20)\cdot 65+20\cdot 25=800-1300+500=0
∣a⃗∣=7200,∣c⃗∣=102+652+252=4950|\vec{a}|=\sqrt{7200},\quad |\vec{c}|=\sqrt{10^2+65^2+25^2}=\sqrt{4950}
cos⁡θ=07200 4950=0\displaystyle \cos\theta=\frac{0}{\sqrt{7200}\,\sqrt{4950}}=0
戦士アルファ × 賢者デルタ 賢者デルタ ほぼ正反対
a⃗⋅d⃗=80(−70)+(−20)⋅85+20⋅5=−5600−1700+100=−7200\vec{a}\cdot\vec{d}=80(-70)+(-20)\cdot 85+20\cdot 5=-5600-1700+100=-7200
∣a⃗∣=7200,∣d⃗∣=702+852+52=12150|\vec{a}|=\sqrt{7200},\quad |\vec{d}|=\sqrt{70^2+85^2+5^2}=\sqrt{12150}
cos⁡θ=−72007200 12150  ≒  −0.77\displaystyle \cos\theta=\frac{-7200}{\sqrt{7200}\,\sqrt{12150}}\;\fallingdotseq\;-0.77
−101 ベータ 騎士ベータ cosθ=0.99 ガンマ 魔法使いガンマ cosθ=0 デルタ 賢者デルタ cosθ=-0.77

魔法使いとの内積がぴったり 00 になるのが面白い。力の項 +800+800 と技の項 +500+500 を,魔法の項 −1300-1300 がきれいに打ち消している。

シミュレーター2人のステータスを自由に決めて,似ている度を見る
キャラ 1
キャラ 2
内積 a·b—
大きさ |a|—
大きさ |b|—
cos θ—
なす角 θ—
—
ドラッグで視点を回転

片方を固定したまま,もう片方の長さだけを伸ばすとどうなるか。矢印は伸びても向きは変わらないので,内積は増えるのに cos⁡θ\cos\theta は動きません。逆に,長さをそのままに向きだけ回すと cos⁡θ\cos\theta が大きく動きます。cos⁡θ\cos\theta がちょうど 00 になる組み合わせ(直交する2人)は,探してみると意外といくらでも見つかります。

世の中ベクトルだらけ

楽曲・味覚・天気・映画など,世の中の多くのデータはベクトルで表せる。そして音楽や動画のレコメンド,検索エンジンのランキングは,まさにこの「似ている度」で動いている。

世の中のデータもベクトルで表せる
もう少し詳しく

平均を引くと,統計の相関係数になる

実データでは,各成分から平均を引いてから比べることがよくある。戦士 a⃗=(80,−20,20)\vec{a} = (80,-20,20) の平均は aˉ≒26.7\bar{a} \fallingdotseq 26.7 なので

a⃗′=(53.3,  −46.7,  −6.7)\vec{a}' = (53.3,\; -46.7,\; -6.7)

この中心化したベクトルどうしでコサイン類似度を取ると,それは統計でおなじみのピアソンの相関係数に一致する。

r=∑i(ai−aˉ)(bi−bˉ)∑i(ai−aˉ)2∑i(bi−bˉ)2=cos⁡(a⃗′,b⃗′)r = \frac{\sum_i (a_i-\bar{a})(b_i-\bar{b})} {\sqrt{\sum_i (a_i-\bar{a})^2}\sqrt{\sum_i (b_i-\bar{b})^2}} = \cos\bigl(\vec{a}',\vec{b}'\bigr)

つまり相関係数とは,平均を引いたあとのコサイン類似度だった。

平均を引く操作には意味がある。「全能力が高いキャラ」と「全能力が低いキャラ」は,そのままだと向きが近いので cos⁡θ\cos\theta が大きく出るが,平均を引くとどの能力に偏っているかだけが残る。何を「似ている」と呼びたいかで,引くか引かないかを選ぶ。

もっと先へ ── 成分を増やしていくと

ここまでは(力, 魔法, 技)の3成分だけを考えてきた。矢印として描けたのは,成分が3つだったからである。

では,キャラに素早さと運を足して5成分にしたらどうなるか。5次元の矢印は描けない。図がなくなった時点で,これまでの話は全部くずれてしまうのだろうか。

定義に「3」は一度も出てこない

内積の定義をもう一度見てみる。

a⃗⋅b⃗=a1b1+a2b2+a3b3\vec{a}\cdot\vec{b} = a_1b_1 + a_2b_2 + a_3b_3

やっていることは「成分ごとに掛けて,全部足す」だけだった。成分が5つでも100でも,まったく同じことができる。

a⃗⋅b⃗=∑i=1naibi∣a⃗∣=∑i=1nai 2cos⁡θ=a⃗⋅b⃗∣a⃗∣ ∣b⃗∣\vec{a}\cdot\vec{b} = \sum_{i=1}^{n} a_i b_i \qquad |\vec{a}| = \sqrt{\sum_{i=1}^{n} a_i^{\,2}} \qquad \cos\theta = \frac{\vec{a}\cdot\vec{b}}{|\vec{a}|\,|\vec{b}|}

どの式にも「33」という数字は出てこない。つまり図が描けるかどうかは,計算とは何の関係もなかったのである。

5成分でやってみる

戦士と騎士に素早さと運を足す。

a⃗=(80,  −20,  20,  30,  10),b⃗=(75,  −15,  20,  25,  40)\vec{a} = (80,\; -20,\; 20,\; 30,\; 10), \qquad \vec{b} = (75,\; -15,\; 20,\; 25,\; 40)

成分ごとに掛けて足すだけ。

a⃗⋅b⃗=6000+300+400+750+400=7850\vec{a}\cdot\vec{b} = 6000 + 300 + 400 + 750 + 400 = 7850∣a⃗∣=8200≒90.6,∣b⃗∣=8475≒92.1|\vec{a}| = \sqrt{8200} \fallingdotseq 90.6, \qquad |\vec{b}| = \sqrt{8475} \fallingdotseq 92.1cos⁡θ=785090.6×92.1≒0.94\cos\theta = \frac{7850}{90.6 \times 92.1} \fallingdotseq 0.94

3成分のときは 0.990.99 だった。素早さと運を加えると 0.940.94 に下がる。「運」で差がついたぶん,少しだけ似ていない,と読める。見るための軸を増やせば,判定も細かくなるわけである。

「直交」も,そのまま生き残る

内積が 00 なら直交,という言い方も次元によらず使える。たとえば4成分の

u⃗=(1, 1, 1, 1),v⃗=(1, 1, −1, −1)\vec{u} = (1,\,1,\,1,\,1), \qquad \vec{v} = (1,\,1,\,-1,\,-1)

は u⃗⋅v⃗=1+1−1−1=0\vec{u}\cdot\vec{v} = 1+1-1-1 = 0 で直交している。4次元の直角を目で見ることはできないが,「まったく別の方向を向いている」という意味はそのまま残る。

ここでいう「まったく別の方向」とは,つまり

その方向にどんなに進んでも,もう一方の方向にはいっさい進むことができない

ということである。平面で考えれば当たり前で,東へ何km歩いても北には1mmも進まない。東と北は直交しているからだ。u⃗\vec{u} の向きにいくら進んでも v⃗\vec{v} の側には1ミリも近づかない ── この関係が,図に描けない4次元でも,数千次元でもそのまま成り立つ。

戦士と魔法使いの内積がぴったり 00 だったのも同じで,戦士をどれだけ鍛え上げても,魔法使いの方向には一歩も近づけない。

実際には,もっと大きい

現実のデータの成分数は5どころではない。

データよくある成分数
文章(単語の出現回数)数万
楽曲の特徴量数十〜数百
画像(AIが扱う特徴ベクトル)数百〜数千

「向きの近さで似ているを測る」という考え方が,そのまま数千次元で動いている。図に描くことはもうできないが,やっていることは「成分ごとに掛けて,足す」だけである。