元理系院生の新入社員がPythonとJavaで色々頑張るブログ

プログラミングや機械学習について調べた事を書いていきます

Pythonでbatch型SOM

この記事に書かれていること

Pythonによるbatch型自己組織化マップの実装

Batch型SOMって何?

前回、Pythonによる逐次型自己組織化マップをPythonで実装しました。

Pythonで逐次型自己組織化マップ - 理系大学生がPythonで色々頑張るブログ

逐次型の自己組織化マップは、学習の際に与えられる入力ベクトルの順番によって、学習結果が大きく異る性質が有ります。

この性質は、研究対象としてとても有意義なものですが、クラスタリングやデータの可視化に用いる場合には再現性に疑問が残ります。


対し、Batch型の自己組織化マップは、重みベクトルの更新タイミングを全てのベクトルを処理した後にまとめて行う事で、入力ベクトルの順番の影響をなくしています。

PythonによるBatch型SOMの実装

__author__ = 'emoson'
import math
dist = lambda vec1, vec2: (sum([(vec[0]-vec[1])**2 for vec in list(zip(vec1, vec2))]))**0.5


def near(map_vector, input_vector):
    """
    input_vectorに対し、最近傍ユニットのラベルを返す
    :param map_vector:
    :param input_vector:
    :return:
    """
    dist_vector = [dist(input_vector, m) for m in map_vector]
    return dist_vector.index(min(dist_vector))


def batch_learning(input_vectors, map_width, map_height, vec_size, learning_count, area_size):
    """
    自己組織化マップの学習
    :param input_vectors:
    :param map_width:
    :param map_height:
    :param vec_size 入力ベクトルの次元数(色の場合はrgbの3次元):
    :param learning_count:
    :param area_size:
    :return map_vector:
    """
    import random
    map_vector = [[random.random() for v in range(vec_size)] for h in range(map_height) for w in range(map_width)]
    a_size = area_size
    for t in range(learning_count):
        w = [[[0 for v in range(vec_size)] for i in range(2)] for h in range(map_height) for w in range(map_width)]

        for input_vector in input_vectors:
            #近傍ユニットの探索
            bmu = near(map_vector=map_vector, input_vector=input_vector)

            #重みの加算
            for i in range(map_width * map_height):
                c = (a_size - dist([i // map_width, i % map_width], [bmu // map_width, bmu % map_width]))
                if c > 0:
                    w[i][0] = [w[i][0][j] + c*input_vector[j] for j in range(vec_size)]
                    w[i][1] = [w[i][1][j] + c for j in range(vec_size)]

        #学習の更新
        for i in range(map_width * map_height):
            map_vector[i] = [w[i][0][j]/w[i][1][j] if w[i][1][j] is not 0 else map_vector[i][j] for j in range(vec_size)]

        a_size = area_size * (learning_count - t) / learning_count
    return map_vector


前回と同様のパラメータで実行した際のマップは次のようになります。

比較の為に逐次型SOMの結果も載せておきます。

逐次型SOM

f:id:emoson:20150222163839g:plain

Batch型SOM

f:id:emoson:20150222163930g:plain