特異値分解(SVD)の概要
データの開先手法の1つとして、特異値分解(SVD:Singular Value Decomposition)という手法があります。SVDでは、不要なデータを取り除くことができるため、画像やテキストデータの圧縮や解析に使われます[1][2]。以降では数式を用いてSVDについて概要を説明します。
特異値とは
そもそも特異値とは、ある行列とその行列の随伴行列(ある行列の共役かつ転置した行列)の積の固有値の非負な平方根のことです。
#直感的にわかる説明ができずすいません。そのレベルまでは理解できてないです。。
特異値分解(SVD)の数式表現
SVDは行列とベクトルを使った2種類の表し方があります。まず最初に行列を使って表現してみます。例として、AというI×J行列のSVDを行うと、
と分解できます。ここで、
- : I行K列のユニタリ行列
- : K行K列の対角行列(対角成分は特異値で、を満たす)
- : I行K列のユニタリ行列の随伴行列
とします。このとき、Kとは、行列のランクを指します(K I, J)。
次にベクトルを使って表現すると、
とできます。ここで、
- : 左特異ベクトル(上記のk行成分
- : 特異値
- : 右特異ベクトル(上記のk列成分
とします。
上記のように、SVDを使うことで対象となる行列を、行列のランクKまでサイズを縮小、つまりデータサイズを圧縮してデータを表現できます。
SVDによる擬似近似
特異値の値に閾値を設けることで、SVDでは擬似的にランクを落とすことが可能です。この操作により、サイズをK→K'(K K')に落とすことができます(計算式は[3]の1.4節を参照)。
参考文献
[1]潜在的意味インデキシング(LSI)徹底入門 - あらびき日記
[2]Topic model
[3]Greenacre1984.pdf
ROSでパラメータを登録する方法
ロボット業界でよく使われるフレームワークとして、ROS[1]というものがあります。ROSでは、生成するプロセス(ROS的にはノード)毎にパラメータを設定することが出来ます。先日そのパラメータを使う機会がありましたので、パラメータの設定方法を書きます。なおプログラミング言語を用いて説明する部分に関しては、Pythonを使って記述します。
パラメータとは
パラメータとは、ノードが外部に公開する変数のことです。外部からパラメータに値を設定することで、ノードの挙動を変更することが出来ます。例えば移動を司るノードが外部にパラメータとして速度を公開している時、外部からパラメータを操作することで速度を変更することができます。
パラメータの設定方法
パラメータを設定する方法には
1. ソース上で設定
2. ノード起動時に設定する
3. コマンドラインで設定する
の3パターンがあります。それぞれの設定方法により、同じプログラムを使っても生成されるノード毎に保有するパラメータが異なるので注意が必要になります。また上記3つの方法があることで、ROSではいつでもノードにパラメータを設定することができるとわかります。
ソース上で設定する
ソースコードで設定するには、set_param関数を使います。ソースコード上で設定することで、そのソースを元に作られたノードには必ずパラメータが設定された状態で生成されます。つまり、
rospy.set_param('foo', 0.1) # デフォルト値0.1
とすれば、ノードは起動時点で必ずデフォルトで0.1という値が入ったfooというパラメータを持つことになります。
ノード起動時に設定する
ノードを起動する時、パラメータを設定して起動することができます。方法としては、
./foo.py /foo/bar:=0.1
とすることで、ノードfooに0.1という値を持つ変数barを持たすことができます。
起動時にパラメータを設けることで、同じプログラムから生成するノードで別々のパラメータを設けることができます。また、プログラムを修正するせずにパラメータを設定することで、お試しでパラメータを使って、ノードの動きを検証してみるということができます。
area/district/region/zoneの使い分け
英単語の勉強をしていた時、"district"という単語が"地区"という意味を知りました。その時、「あれ?areaと似たような意味だけど、使い分けはどうすればいいのだろう?」と思いました。そのため、地区とか地域という意味の単語(area, district, region, zone)はどの様な使い分けがあるのかを英英辞典longmanで調べてみたので、纏めます。
英英辞典で調べてみた結果、各単語の使い分けをする時に意識するのは、範囲の大小ではなく区切り方でした。それぞれの単語の意味は
area | 特定の地域 |
district | 公的に定められた地域 |
region | 広大な地域(明確に定義できるかは関係なし) |
zone | 何か特徴を持った地域 |
ということが分かりました。
英英辞典で意味を調べてみた結果
英英辞典で単語の意味と例文を調べて見た結果、下記の表の通りになりました。
単語 | 意味 | 例 |
area | a particular part of a country, town etc | Crime rates are significantly higher in urban areas. |
district | an area of a country, city etc that has official borders | a house in a pleasant suburban district. |
region | a large area of a country or of the world, usually without exact limits | Flooding is likely in some coastal regions of the Northeast during the early part of the week. |
zone | a large area that is different from other areas around it in some way | San Francisco and Tokyo are both located in earthquake zones. |
habitとcustomの使い分け
学校で習う英単語の中に、「習慣」という意味で習う単語が"habit"と"custom"の2つあります。全く同じ意味という訳はないと感じつつ、今までその違いを調べたことはありませんでした。今回久々に気になったので、両者の違いを調べてみました。その結果、2つの単語は「習慣」という意味はあるものの、用途が全く異なる単語であることがわかりました。
英英辞典Longmanでそれぞれの単語の意味を調べてみたところ、"habit"は「習慣」で"custom"は「風習」と訳すのが正しいという結果です。下記にLongmanに記載されている意味と例文を記載します。
- habit
"something that you do regularly or usually, often without thinking about it because you have done it so many times before."
Ex. Regular exercise is a good habit for kids to develop.
- custom
"something that is done by people in a particular society because it is traditional."
Ex. It's the custom for the bride's father to pay for the wedding.
C/C++で配列の初期化に#includeを使う
データファイルを取り扱う時、そのデータを読んで配列に格納していくのは面倒ですよね。実は、配列の初期化には#includeプリプロセッサが使えます。今回は#includeを使って配列を初期化した時の挙動について書きます。
なお今回のテスト環境は、
- OS : Windows8.1
- IDE: Visual Studio 2013 Express for Windows Deskto
で、includeするファイルはソリューションファイルと同じディレクトリに存在するものとします。
使用コード・ファイル
今回の実験には、#includeで初期化した配列をprintfで各要素を表示するソースコードと、4つの数字","で区切られたデータファイルを使いました。それぞれの内容は下記の通りです。
ソースコード
#include "stdio.h" int sample[] = { #include "sample.txt" }; int main(void) { unsigned int i; unsigned int buf_size; buf_size = sizeof(sample) / sizeof(int); printf("Size of buffer(sample) is %d\n", buf_size); for (i = 0; i < buf_size; i++) { printf("element%2d: %d\n", i, sample[i]); } return 0; }
sample.txtの中身
1,2,3,4
実験1(上記ソースコードをただ実行する)
上記のソースコードを実行すると、#includeプリプロセッサがsample.txtの中身を読んで、配列を初期化してくれることが期待されます。実行してみた結果、実際にそうなりました。この時のコマンドプロンプトの表示を、Fig.1に示します。ファイルポインタを使わなくてよいことから、ファイルポインタ操作(fcloseとか)が不要になるのが便利ですね。
Fig.1 サンプルコード実行時のコマンドプロンプト表示結果
実験2(配列のサイズをsample.txtの要素より少なくしてみる)
#includeがsample.txtの中身を読んでいることから、例えばsample[3]とすると、コンパイルエラーが発生することが予想されます。実際に試してみた結果、Fig.2のようになりました。ファイルの中身を読んでいることがここから分かります。
Fig.2 サンプルコード中の配列サイズをsample.txtの中身より小さくした時のコンパイル結果
まとめ
C/C++では、配列の初期化に#includeプリプロセッサを使い、初期化時にファイルの中身を直接配列に保存することができます。これにより、ファイルポインタの解放忘れがなくなり、メモリ関係のトラブル要因を1つ消すことができます。また、実行環境でファイルを読まなくてよいので、秘密なデータを配列に保存したい時、セキュリティの面から有用だと思います。
また、配列サイズを指定する・しないをうまく使い分けることで、様々なメリットがあると考えます。自分の考えとしては、
-サイズを指定する →読み込むファイルの中身のサイズが固定
→読み込むファイルが想定したファイルか、フォーマットになっているかが確認できる
-サイズを指定しない→読み込むファイルのフォーマットが変わっても、柔軟に対応することができる
というメリットがあると思います。
ただし、#includeを使って配列を初期化すると、コンパイル時に配列サイズが決まってしまいます。つまり、ファイルの中身を変更しそれを配列に反映したい時、再コンパイルが必要になります。この点には注意が必要になります。
Discriminative ModelとGenerative Model
機械学習のモデルには、大別してGenerative ModelとDiscriminative Modelの2種類があります。今回はそれぞれの違いについて、簡単にまとめてみます。
両者の違いを端的に言うと、モデル化時に検討する要素の違いです。
・Generative Model : 注目変数だけでなく、全ての変数を考慮
・Discriminative Model: 注目変数のみ考慮
Generative Model(生成モデル)
生成モデルという名の通り、システムの全データの生成プロセスをモデル化します。そして、必要に応じてベイズ推定を行います。例えばGMMやLDAがこのモデルに属します。
Discriminative Model(識別モデル)
識別モデルという名の通り、入力データを単純に識別します。モデル化には条件付き確率が使われます。同時分布が必要ない時に活躍します。例えばSVMがこのモデルに属します。
force/compel/constrainの違い
「強制する」という日本語訳になる英単語がいくつかあります。以前からそれらの使い分けが気になっていました。今回は、それぞれの使い分けについて調べた結果を記載します。
今回、調査には英英辞典Longman(WEB版)を使いました。調べた結果は下記の通りです。
・force : "to make someone do something they do not want to do"
・compel : "to force someone to do something"
・constrain: "to stop someone from doing what they want to do"
上記から、forceとcompelは同等と思えば良さそうです。constrainについては、forceと違って「やらせる」ではなく「やらせない」という意味合いみたいです。