我如何用TensorFlow实现k-means?

Rap*_*ith 18 k-means tensorflow

使用内置渐变下降优化器的介绍教程非常有意义.然而,k-means不仅仅是我可以插入梯度下降的东西.看起来我必须编写自己的优化器,但鉴于TensorFlow原语,我不太清楚如何做到这一点.

我应该采取什么方法?

dga*_*dga 27

(注意:您现在可以在github上获得这个代码的更精美版本.)

你绝对可以这样做,但你需要定义自己的优化标准(对于k-means,它通常是最大迭代次数和赋值稳定时).下面是一个如何实现它的示例(可能有更多的最佳实现方法,以及选择初始点的更好方法).它基本上就像你在numpy中做的那样,如果你真的很难在Python中迭代地做事情:

import tensorflow as tf
import numpy as np
import time

N=10000
K=4
MAX_ITERS = 1000

start = time.time()

points = tf.Variable(tf.random_uniform([N,2]))
cluster_assignments = tf.Variable(tf.zeros([N], dtype=tf.int64))

# Silly initialization:  Use the first two points as the starting                
# centroids.  In the real world, do this better.                                 
centroids = tf.Variable(tf.slice(points.initialized_value(), [0,0], [K,2]))

# Replicate to N copies of each centroid and K copies of each                    
# point, then subtract and compute the sum of squared distances.                 
rep_centroids = tf.reshape(tf.tile(centroids, [N, 1]), [N, K, 2])
rep_points = tf.reshape(tf.tile(points, [1, K]), [N, K, 2])
sum_squares = tf.reduce_sum(tf.square(rep_points - rep_centroids),
                            reduction_indices=2)

# Use argmin to select the lowest-distance point                                 
best_centroids = tf.argmin(sum_squares, 1)
did_assignments_change = tf.reduce_any(tf.not_equal(best_centroids,
                                                    cluster_assignments))

def bucket_mean(data, bucket_ids, num_buckets):
    total = tf.unsorted_segment_sum(data, bucket_ids, num_buckets)
    count = tf.unsorted_segment_sum(tf.ones_like(data), bucket_ids, num_buckets)
    return total / count

means = bucket_mean(points, best_centroids, K)

# Do not write to the assigned clusters variable until after                     
# computing whether the assignments have changed - hence with_dependencies
with tf.control_dependencies([did_assignments_change]):
    do_updates = tf.group(
        centroids.assign(means),
        cluster_assignments.assign(best_centroids))

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

changed = True
iters = 0

while changed and iters < MAX_ITERS:
    iters += 1
    [changed, _] = sess.run([did_assignments_change, do_updates])

[centers, assignments] = sess.run([centroids, cluster_assignments])
end = time.time()
print ("Found in %.2f seconds" % (end-start)), iters, "iterations"
print "Centroids:"
print centers
print "Cluster assignments:", assignments
Run Code Online (Sandbox Code Playgroud)

(请注意,真正的实现需要更加小心初始群集选择,避免所有点转到一个群集的问题情况等.这只是一个快速演示.我已经更新了我之前的答案,使其有点更加明确和"榜样值得".)