何通りかの値をとる整数を「その値のインデックスのみが1になっているベクトル」で表現するエンコード方法をone-hot encodingと呼ぶそうです。機械学習などでしばしば見られる手法です。
1 -> [1, 0, 0, 0]
2 -> [0, 1, 0, 0]
3 -> [0, 0, 1, 0]
4 -> [0, 0, 0, 1]
GNU Octaveでこの変換をきれいに書く方法を調べていたのですが、ブロードキャストという言語の機能を使うと簡潔な記述ができることを知ったので紹介します。
どうやるか
X == 1:max(X)
を使うと簡単です。ここでは1から最大値までとしましたが、例えば値が1〜10だと決まっているなら X == 1:10
とするかと思います。
octave:1> X = [1; 1; 2; 3; 5]
X =
1
1
2
3
5
octave:2> X == 1:max(X)
ans =
1 0 0 0 0
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 0 1
ちなみに不連続でも構いません。
octave:1> X = [1; 1; 2; 3; 5]
X =
1
1
2
3
5
octave:2> X == [1, 2, 4, 6, 8]
ans =
1 0 0 0 0
1 0 0 0 0
0 1 0 0 0
0 0 0 0 0
0 0 0 0 0
なぜこれで上手くいくのか
Octave 3.6.0からブロードキャスト(broadcasting)という機能が入ったらしいです。二項演算をする際に、次元が大きい方のベクトル・行列に合わせるように要素コピーをしてくれます。このとき小さい方の次元は1である必要があるようです。
先の例でいうと、 1:max(X)
は [1, 2, 3, 4, 5]
となり、 ==
演算は5×1ベクトルと1×5ベクトルに関して行われていました。
したがって、この場合はブロードキャストが発生し
X = [1, 1, 1, 1, 1;
1, 1, 1, 1, 1;
2, 2, 2, 2, 2;
3, 3, 3, 3, 3;
5, 5, 5, 5, 5]
X == [1, 2, 3, 4, 5;
1, 2, 3, 4, 5;
1, 2, 3, 4, 5;
1, 2, 3, 4, 5;
1, 2, 3, 4, 5]
このように評価されて一致していた箇所の値が1になったようです。簡潔でいいですね。