군집화 (clustering)

[텐서플로 첫걸음] 3.3 K-평균 알고리즘

K-평균 알고리즘은 군집화 문제를 풀기 위해 적합한 알고리즘으로 주어진 데이터를 군집 개수(K)로 그룹화하는 것이 특징입니다. 당연한 이야기지만 군집되어 있는 데이터끼리는 같은 성질을 가지며 다른 그룹과는 구별됩니다. 한 개 그룹에 포함된 데이터는 다른 그룹에 군집 될 수 없습니다.

책의 예제를 순서대로 진행합니다.

샘플 데이터 생성 (2D 좌표계에 2,000개의 랜덤한 점)

import numpy as np

num_points = 2000
vectors_set = []

for i in xrange(num_points):
    if np.random.random() > 0.5:
        vectors_set.append([np.random.normal(0.0, 0.9),
                            np.random.normal(0.0, 0.9)])
    else:
        vectors_set.append([np.random.normal(3.0, 0.5),
                            np.random.normal(1.0, 0.5)])

데이터를 그림으로 표현

try:
    import matplotlib.pyplot as plt
    import pandas as pd #  needs "pip install pandas"
    import seaborn as sns # needs "pip install seaborn"

    df = pd.DataFrame({"x": [v[0] for v in vectors_set],
                   "y": [v[1] for v in vectors_set]})
    sns.lmplot("x", "y", data=df, fit_reg=False, size=6)
    plt.show()
except ImportError:
    print("Please install pandas, seaborn to visualize embeddings.")

위의 데이터를 TensorFlow로 4개의 군집으로 그룹화

import tensorflow as tf

# 위에서 무작위로 생성한 데이터를 가지고 상수 텐서를 만듭니다.
vectors = tf.constant(vectors_set)

# 0단계 : K개 중심의 초기 집합을 결정
# tf.slice : 텐서의 일부분을 삭제합니다.
# tf.random_shuffle : 첫 번째 차원을 기준으로 텐서의 원소를 섞습니다.
k = 4
centroides = tf.Variable(tf.slice(tf.random_shuffle(vectors), [0,0],[k,-1]))

# 아래 tf.sub를 계산하기 위해 차원을 추가하는 과정입니다.
# tf.expand_dims : 텐서에 차원을 추가
expanded_vectors = tf.expand_dims(vectors, 0)
expanded_centroides = tf.expand_dims(centroides, 1)

# 1단계 : 각 데이터를 가장 가까운 군집에 할당
assignments = tf.argmin(tf.reduce_sum(tf.square(tf.sub(expanded_vectors, expanded_centroides)), 2), 0)

# 2단계 : 각 그룹에 대해 새로운 중심을 계산
# tf.reshape : 텐서의 원소는 그대로 유지하면서 텐서의 구조를 바꿉니다.
means = tf.concat(0, [tf.reduce_mean(tf.gather(vectors,
        tf.reshape(tf.where(tf.equal(assignments, c)), [1,-1])),
        reduction_indices=[1]) for c in xrange(k)])

update_centroides = tf.assign(centroides, means)

init_op = tf.initialize_all_variables()

sess = tf.Session()
sess.run(init_op)

for step in xrange(100):
    _, centroid_values, assignment_values = sess.run([update_centroides, centroides, assignments])

데이터를 그림으로 표현

data = {"x": [], "y": [], "cluster": []}

for i in xrange(len(assignment_values)):
    data["x"].append(vectors_set[i][0])
    data["y"].append(vectors_set[i][1])
    data["cluster"].append(assignment_values[i])

df = pd.DataFrame(data)
sns.lmplot("x", "y", data=df, fit_reg=False, size=6, hue="cluster", legend=False)

plt.show()

results matching ""

    No results matching ""