Bag of ML Words

ML = Machine Learning, Music Love, and Miscellaneous things in daily Livings

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回すと遅くなりますからね。

 

一番単純なユークリッド距離の場合は

http://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.euclidean_distances.html#sklearn.metrics.pairwise.euclidean_distances

を参照です。

 

要素のカウント: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()