Python: Bo(V)Wで遭遇した二つの例。距離比較と数え上げ
たとえば、Bag-of-Visual Words形式を考えましょう。
元の画像特徴量を、適当なベクトル量子化かけて、
1画像(単位)内のword数を数えるという話。
このとき、
既にcodebook(量子化コード、代表点。D-dim特徴ベクトル)は既に
K個持っていたとして、
新規画像のBoVWを計算したいとします。
すると、まずは元画像から特徴量を抽出します。
特徴量は通常局所特徴量といって、画像の1部分から計算されるので、
1画像からはたくさん出てきます。
それらをK個のcodebookにアサインして、
それぞれの個数を数える
ことになります。
pairwise距離の数え上げ: scikit-learnのmetrics.pairwise
アサインする部分ですが愚直には各局所特徴量を
K個のcodebookのベクトルと比較して距離を測ります。
で、一番近いcodebookにアサインすれば良いです。
それを華麗に処理してくれうのが
scikit-learnパッケージのmetrics.pairwiseモジュールです。
scikit-learn(http://scikit-learn.org/stable/index.html)はPythonによる
各種統計計算・機械学習ライブラリで、関わっているメンバーは
実際にその第一線の研究者を含んでいます。
今回はその中で上記のモジュールを使います。
今の話は、二つの要素ごと(pairwise)に距離を計算するのをforで繰り返すのを、
多分内部的に最適化してくれているのでしょう。
for回すと遅くなりますからね。
一番単純なユークリッド距離の場合は
を参照です。
要素のカウント:collections.Counter
で、Bag-of-Wordsの場合、
N個の局所特徴量がどこにアサインされたか、
K個のcodebookごとに総数が必要になります。
ここには、collections.Counterモジュールが使えるようです。
http://docs.python.jp/2/library/collections.html
most_count()を呼べば、とりあえず降順で並べてくれるので、
0個になった時点で止めればBoWカウントの出来上がりですね。
Qiitaが初めて役に立ちました(笑)
http://qiita.com/hatchinee/items/a904c1f8d732a4686c9d
まとめると、以下みたいな形?一応動きました
# read the codebook file
codefile = open(codebook_filename, 'r')
codebook =
for line in codefile.readlines():
line_splited = split(strip(line), ' ')
codebook.append(line_splited)
# end line-for
# changed into numpy-array
codebook_array = np.array(codebook)
# read the data to encode
infile = open(target_filename, 'r')
input =
for line in infile.readlines():
# read the input file
line_splited = split(strip(line), ' ')
input.append(line_splited)
# end line-for
infile.close()
# make it numpy array
input_array = np.array(input)
# assignment to the codebook
dist_mat = euclidean_distances(codebook_array, input_array)
assignment = np.argmin(dist_mat, axis = 0)
# accumulate as histogram, output
cnt = Counter(assignment)
intotal = 0
outfile = open(out_filename, 'w')
for code, code_cnt in cnt.most_common():
if(code_cnt == 0):
break
# end code_cnt-if
intotal = intotal + code_cnt
outfile.write(str(code) + ":" + str(code_cnt) + " ")
# end most_common-for
outfile.write('\n')
outfile.close()