Advertisement
Guest User

Untitled

a guest
Jul 7th, 2015
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.65 KB | None | 0 0
  1. # A class to partition input points using the k-means algorithm
  2. #
  3. # Use it like this:
  4. #
  5. # points = [[0,0],[0,1],[0,100],[0,104]]
  6. # result = KMeans.calculate(points, 2))
  7. # # result is [[0,0.5],[0,102]]
  8. class KMeans
  9. def self.calculate(points, num_means)
  10. means = generate_initial_means(points, num_means)
  11. old_means = []
  12.  
  13. until means == old_means do
  14. old_means = means
  15. means = calculate_new_means(means, points)
  16. end
  17.  
  18. means
  19. end
  20.  
  21. def self.generate_initial_means(points, num_means)
  22. points.sample(num_means)
  23. end
  24.  
  25. def self.calculate_new_means(current_means, points)
  26. partitions = group_points_by_closest_mean(current_means, points)
  27.  
  28. new_means = partitions.map(&method(:calculate_center))
  29. new_means.sort
  30. end
  31.  
  32. def self.group_points_by_closest_mean(current_means, points)
  33. map = Hash.new{|h, k| h[k] = []}
  34. points.each do |point|
  35. closest = find_closest_mean(current_means, point)
  36. map[closest] << point
  37. end
  38. map.values
  39. end
  40.  
  41. def self.calculate_center(points)
  42. dimensions = points.transpose
  43.  
  44. averages = dimensions.collect do |dimension|
  45. sum = dimension.reduce(:+)
  46. sum.to_f / dimension.length
  47. end
  48.  
  49. averages
  50. end
  51.  
  52. def self.distance_squared(a, b)
  53. a.zip(b)
  54. .map{|ai, bi| (ai - bi)**2}
  55. .reduce(:+)
  56. end
  57.  
  58. def self.find_closest_mean(means, point)
  59. distances = means.map { |mean| distance_squared(mean, point) }
  60.  
  61. # if there are duplicate means, each_with_index.min will always
  62. # return the one with the lowest index. That's as good a solution
  63. # as any in case of duplication.
  64. _min, index = distances.each_with_index.min
  65. means[index]
  66. end
  67. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement