2015-11-10 17 views
18

इंट्रा ट्यूटोरियल, जो अंतर्निहित ग्रेडियेंट वंश अनुकूलक का उपयोग करता है, बहुत समझ में आता है। हालांकि, के-साधन केवल कुछ नहीं है जो मैं ढाल वंश में प्लग कर सकता हूं। ऐसा लगता है कि मुझे अपना खुद का अनुकूलक लिखना होगा, लेकिन मुझे पूरा यकीन नहीं है कि टेंसरफ्लो प्राइमेटिव्स को यह कैसे करना है।मैं टेंसरफ्लो के साथ के-साधन कैसे कार्यान्वित करूं?

मुझे क्या दृष्टिकोण लेना चाहिए?

उत्तर

27

(ध्यान दें: अब आप a more polished version of this code as a gist on github प्राप्त कर सकते हैं।)

आप निश्चित रूप से यह कर सकते हैं, लेकिन आप (k-साधन के लिए अपने स्वयं के अनुकूलन मापदंड परिभाषित करने की जरूरत है, यह आम तौर पर एक अधिकतम पुनरावृत्ति संख्या और जब है असाइनमेंट स्थिर करता है)। यहां एक उदाहरण दिया गया है कि आप इसे कैसे कर सकते हैं (इसे लागू करने के लिए शायद अधिक इष्टतम तरीके हैं, और शुरुआती बिंदुओं का चयन करने के लिए निश्चित रूप से बेहतर तरीके हैं)। यह मूल रूप से है जैसे आप numpy में ऐसा चाहते हैं, तो आप iteratively अजगर में काम करने से दूर रहने की वास्तव में कड़ी मेहनत की कोशिश कर रहे थे:

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 

(ध्यान दें कि कोई वास्तविक कार्यान्वयन प्रारंभिक क्लस्टर चयन के बारे में अधिक सावधान रहने की जरूरत है, एक क्लस्टर, आदि पर जाने वाले सभी बिंदुओं के साथ समस्या के मामलों से परहेज करना। यह सिर्फ एक त्वरित डेमो है। मैंने इसे पहले से थोड़ा सा स्पष्ट और "उदाहरण-योग्य" बनाने के लिए अपना उत्तर अपडेट कर दिया है।)

+1

का उपयोग शायद मैं इसे थोड़ा बेहतर व्याख्या करनी चाहिए। यह एन अंक लेता है और उनकी प्रतियां बनाता है। यह के वर्तमान सेंट्रॉइड लेता है और उनमें से एन प्रतियां बनाता है। इसके बाद यह प्रत्येक बिंदु से प्रत्येक केंद्र से एन * के दूरी प्राप्त करने के लिए इन दो बड़े टेंसर को घटा देता है। यह उनसे वर्गों की दूरी की गणना करता है, और प्रत्येक बिंदु के लिए सबसे अच्छा खोजने के लिए 'argmin' का उपयोग करता है। फिर यह अपने क्लस्टर असाइनमेंट के आधार पर के विभिन्न टेंसर में बिंदुओं को समूहित करने के लिए गतिशील_ विभाजन का उपयोग करता है, उन समूहों में से प्रत्येक के माध्यम से साधन पाता है, और उस पर आधारित सेंट्रॉइड सेट करता है। – dga

3

अधिकांश उत्तर मैंने अभी तक 2 डी संस्करण पर ध्यान केंद्रित किया है (जब आपको 2 आयामों में अंक क्लस्टर करने की आवश्यकता है)। मनमाने ढंग से आयामों में क्लस्टरिंग का मेरा कार्यान्वयन यहां दिया गया है।


n में k-means algorithm की

बुनियादी विचार धुंधली हो जाती है:

  • असाइन:

    • यादृच्छिक कश्मीर शुरुआती बिंदु
    • ऐसा करने तक आप धैर्य या क्लस्टर काम नहीं बदलता है से अधिक उत्पन्न प्रत्येक बिंदु निकटतम प्रारंभ बिंदु
    • टी लेने के द्वारा प्रत्येक प्रारंभिक बिंदु का स्थान पुन: गणना करें वह इसे बीच औसत क्लस्टर

है किसी भी तरह के परिणाम मैं MNIST छवियों क्लस्टर करने का प्रयास करेंगे मान्य करने के लिए सक्षम होने के लिए।

import numpy as np 
import tensorflow as tf 
from random import randint 
from collections import Counter 
from tensorflow.examples.tutorials.mnist import input_data 

mnist = input_data.read_data_sets("MNIST_data/") 
X, y, k = mnist.test.images, mnist.test.labels, 10 

तो यहाँ एक्स क्लस्टर के लिए अपने डेटा (10000, 784), y वास्तविक संख्या है, और कश्मीर क्लस्टर की संख्या (जो अंक। की संख्या के रूप में ही है अब वास्तविक है एल्गोरिथ्म:।।

# select random points as a starting position. You can do better by randomly selecting k points. 
start_pos = tf.Variable(X[np.random.randint(X.shape[0], size=k),:], dtype=tf.float32) 
centroids = tf.Variable(start_pos.initialized_value(), 'S', dtype=tf.float32) 

# populate points 
points   = tf.Variable(X, 'X', dtype=tf.float32) 
ones_like  = tf.ones((points.get_shape()[0], 1)) 
prev_assignments = tf.Variable(tf.zeros((points.get_shape()[0],), dtype=tf.int64)) 

# find the distance between all points: http://stackoverflow.com/a/43839605/1090562 
p1 = tf.matmul(
    tf.expand_dims(tf.reduce_sum(tf.square(points), 1), 1), 
    tf.ones(shape=(1, k)) 
) 
p2 = tf.transpose(tf.matmul(
    tf.reshape(tf.reduce_sum(tf.square(centroids), 1), shape=[-1, 1]), 
    ones_like, 
    transpose_b=True 
)) 
distance = tf.sqrt(tf.add(p1, p2) - 2 * tf.matmul(points, centroids, transpose_b=True)) 

# assign each point to a closest centroid 
point_to_centroid_assignment = tf.argmin(distance, axis=1) 

# recalculate the centers 
total = tf.unsorted_segment_sum(points, point_to_centroid_assignment, k) 
count = tf.unsorted_segment_sum(ones_like, point_to_centroid_assignment, k) 
means = total/count 

# continue if there is any difference between the current and previous assignment 
is_continue = tf.reduce_any(tf.not_equal(point_to_centroid_assignment, prev_assignments)) 

with tf.control_dependencies([is_continue]): 
    loop = tf.group(centroids.assign(means), prev_assignments.assign(point_to_centroid_assignment)) 

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

# do many iterations. Hopefully you will stop because of has_changed is False 
has_changed, cnt = True, 0 
while has_changed and cnt < 300: 
    cnt += 1 
    has_changed, _ = sess.run([is_continue, loop]) 

# see how the data is assigned 
res = sess.run(point_to_centroid_assignment) 

अब यह समय की जांच कितना अच्छा हमारे समूहों हो रहा है इस हम समूह के सभी वास्तविक संख्या कि क्लस्टर में एक साथ दिखाई उसके बाद हम सबसे लोकप्रिय विकल्प है कि क्लस्टर में देखेंगे ऐसा करने के लिए। टी के मामले में वह सही क्लस्टरिंग हमारे पास प्रत्येक समूह में केवल एक मूल्य होगा। यादृच्छिक क्लस्टर के मामले में प्रत्येक मूल्य समूह में लगभग समान रूप से प्रतिनिधित्व किया जाएगा।

[(0, 738), (6, 18), (2, 11)] 
[(1, 641), (3, 53), (2, 51)] 
[(1, 488), (2, 115), (7, 56)] 
[(4, 550), (9, 533), (7, 280)] 
[(7, 634), (9, 400), (4, 302)] 
[(6, 649), (4, 27), (0, 14)] 
[(5, 269), (6, 244), (0, 161)] 
[(8, 646), (5, 164), (3, 125)] 
[(2, 698), (3, 34), (7, 14)] 
[(3, 712), (5, 290), (8, 110)] 

यह बहुत अच्छी है, क्योंकि मायने रखता है के बहुमत पहले समूह में है:

nums_in_clusters = [[] for i in xrange(10)] 
for cluster, real_num in zip(list(res), list(y)): 
    nums_in_clusters[cluster].append(real_num) 

for i in xrange(10): 
    print Counter(nums_in_clusters[i]).most_common(3) 

यह मैं कुछ इस तरह देता है। आप देखते हैं कि क्लस्टरिंग 7 और 9, 4 और 5 को भ्रमित करता है लेकिन 0 बहुत अच्छी तरह से क्लस्टर किया गया है।

कुछ दृष्टिकोण है कि यह कैसे सुधार करने के लिए:

  • एल्गोरिथ्म कई बार चलाने के लिए और जब कुछ भी एक को सौंपा गया है सबसे अच्छा एक
  • हैंडलिंग मामलों (समूहों के लिए दूरी के आधार पर) का चयन करें क्लस्टर। मेरे मामले में आपको means चर में नैन मिलेगा क्योंकि count 0.
  • यादृच्छिक बिंदु प्रारंभिकरण है।
1

सिर्फ tf.contrib.learn.KMeansClustering

संबंधित मुद्दे