NDKMeans 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Rakefile +8 -0
- data/bin/TestMultiDimension +10 -0
- data/lib/MultiDimensional KMeans.rb +190 -0
- metadata +46 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: d4c4f0b227178a699448686ead2882ff579ecf74
|
|
4
|
+
data.tar.gz: 9438ccf1c1bbda0cf556671e779189cae0907150
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 1bdf489a238cf029f9fc2c674ae819486789b5e9b9b91403ced30d16b4758703f6c8570a0508392a153ea8a15ee5745d5b83b56c1854571c19d2066fd610807f
|
|
7
|
+
data.tar.gz: 9ce04af21cc3d7ff910ace41b1f57e00b2222170288b1d0ff253a3fca7067fc49cc6502b3f7eb586229777cd081194c77f46dc772ba8e018ba0dfa061f561b9f
|
data/Rakefile
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#! /bin/ruby
|
|
2
|
+
require 'MultiDimensional KMeans'
|
|
3
|
+
|
|
4
|
+
test = MultiDimensionalKMeans.new 3, 4
|
|
5
|
+
points = [[0,0,0,0], [1,1,1,1], [2,2,2,2], [3,3,3,3], [4,4,4,4], [1,2,3,4], [4,3,2,1]]
|
|
6
|
+
centroids, clusters = test.build points
|
|
7
|
+
for i in 0...centroids.size
|
|
8
|
+
puts "CENTROID: " + centroids[i].to_s
|
|
9
|
+
puts "Cluster: " + clusters[i].to_s
|
|
10
|
+
end
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
|
|
2
|
+
require "gnuplot"
|
|
3
|
+
require "rubygems"
|
|
4
|
+
require 'csv'
|
|
5
|
+
require 'pp'
|
|
6
|
+
|
|
7
|
+
class Point
|
|
8
|
+
attr_accessor :values
|
|
9
|
+
def initialize(values)
|
|
10
|
+
@values = values
|
|
11
|
+
end
|
|
12
|
+
def to_s
|
|
13
|
+
return @values.to_s
|
|
14
|
+
end
|
|
15
|
+
def distance(p)
|
|
16
|
+
dis = 0
|
|
17
|
+
for i in 0...@values.length
|
|
18
|
+
dis = dis + (p.values[i] - @values[i])**2
|
|
19
|
+
end
|
|
20
|
+
ret = Math.sqrt(dis)
|
|
21
|
+
end
|
|
22
|
+
def equals(p)
|
|
23
|
+
eq = true
|
|
24
|
+
for i in 0...@values.size
|
|
25
|
+
if p.values[i] != @values[i]
|
|
26
|
+
eq = false
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
return eq
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class MultiDimensionalKMeans
|
|
34
|
+
attr_accessor :centroids, :old_centroids, :clusters, :dimension
|
|
35
|
+
def initialize(inputs, dimen)
|
|
36
|
+
@dimension = dimen
|
|
37
|
+
@centroids = Array.new
|
|
38
|
+
for i in 0...inputs
|
|
39
|
+
@centroids[i] = Point.new zeros()
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def zeros()
|
|
44
|
+
arr = Array.new
|
|
45
|
+
for i in 0...@dimension
|
|
46
|
+
arr[i] = 0
|
|
47
|
+
end
|
|
48
|
+
return arr
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def generateKmeansPoints(points)
|
|
52
|
+
retArr = Array.new points[0].size
|
|
53
|
+
for i in 0...retArr.size
|
|
54
|
+
retArr[i] = Array.new
|
|
55
|
+
end
|
|
56
|
+
for i in 0...points[0].size
|
|
57
|
+
for j in 0...points.size
|
|
58
|
+
retArr[i][j] = points[j][i]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
return retArr
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def build(points)
|
|
65
|
+
# Calcular centroides aleatorios
|
|
66
|
+
kmeansPoints = generateKmeansPoints(points)
|
|
67
|
+
# Modificar función initialize_random_centroids
|
|
68
|
+
@old_centroids = Array.new @centroids
|
|
69
|
+
initialize_random_centroids kmeansPoints
|
|
70
|
+
while stop_condition
|
|
71
|
+
@clusters = Array.new @centroids.length
|
|
72
|
+
for i in 0...@clusters.length
|
|
73
|
+
clusters[i] = Array.new
|
|
74
|
+
end
|
|
75
|
+
# Meter cada punto a su cluster mas cercano
|
|
76
|
+
for i in 0...points.length
|
|
77
|
+
clusters[eval(points[i])].push Point.new(points[i])
|
|
78
|
+
# clusters[eval(x[i], y[i], z[i])].push Point.new x[i], y[i], z[i]
|
|
79
|
+
end
|
|
80
|
+
@old_centroids = Array.new @centroids
|
|
81
|
+
update_centroids kmeansPoints
|
|
82
|
+
end
|
|
83
|
+
cen, clus = @centroids, @clusters
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def randomizeSubarray(arr)
|
|
87
|
+
random = rand(arr.max - arr.min) + arr.min
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def randomizeCentroid(points)
|
|
91
|
+
centroidArray = Array.new points.size
|
|
92
|
+
for i in 0...points.size
|
|
93
|
+
centroidArray[i] = randomizeSubarray points[i]
|
|
94
|
+
end
|
|
95
|
+
return centroidArray
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def initialize_random_centroids(points)
|
|
99
|
+
@old_centroids = Array.new @centroids
|
|
100
|
+
for i in 0...@centroids.length
|
|
101
|
+
arr = randomizeCentroid(points)
|
|
102
|
+
@centroids[i] = Point.new arr
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def eval(point)
|
|
107
|
+
p = Point.new point
|
|
108
|
+
distancias = Array.new @centroids.length
|
|
109
|
+
for i in 0...distancias.length
|
|
110
|
+
distancias[i] = p.distance @centroids[i]
|
|
111
|
+
end
|
|
112
|
+
min_dis = distancias.min
|
|
113
|
+
min_idx = distancias.find_index min_dis
|
|
114
|
+
ret = min_idx
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Modificando
|
|
118
|
+
def update_centroids(points)
|
|
119
|
+
@old_centroids = Array.new @centroids
|
|
120
|
+
reinitialize = false
|
|
121
|
+
for i in 0...@clusters.length
|
|
122
|
+
puts "Cluster " + (i+1).to_s + " tiene " + @clusters[i].length.to_s
|
|
123
|
+
if @clusters[i].length < 2
|
|
124
|
+
reinitialize = true
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
if reinitialize
|
|
128
|
+
initialize_random_centroids points
|
|
129
|
+
else
|
|
130
|
+
minimus = Array.new points.size
|
|
131
|
+
maximus = Array.new points.size
|
|
132
|
+
for i in 0...@centroids.length
|
|
133
|
+
for j in 0...minimus.size
|
|
134
|
+
minimus[j] = Float::INFINITY
|
|
135
|
+
maximus[j] = 0
|
|
136
|
+
end
|
|
137
|
+
# min_x = Float::INFINITY
|
|
138
|
+
# min_y = Float::INFINITY
|
|
139
|
+
# min_z = Float::INFINITY
|
|
140
|
+
# max_x = 0
|
|
141
|
+
# max_y = 0
|
|
142
|
+
# max_z = 0
|
|
143
|
+
for j in 0...@clusters[i].length
|
|
144
|
+
# Verificar cada cluster para actualizar minimos y maximos
|
|
145
|
+
for k in 0...minimus.size
|
|
146
|
+
if @clusters[i][j].values[k] < minimus[k]
|
|
147
|
+
minimus[k] = @clusters[i][j].values[k]
|
|
148
|
+
elsif @clusters[i][j].values[k] > maximus[k]
|
|
149
|
+
maximus[k] = @clusters[i][j].values[k]
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
# if clusters[i][j].x < min_x
|
|
153
|
+
# min_x = clusters[i][j].x
|
|
154
|
+
# elsif clusters[i][j].x > max_x
|
|
155
|
+
# max_x = clusters[i][j].x
|
|
156
|
+
# end
|
|
157
|
+
# if clusters[i][j].y < min_y
|
|
158
|
+
# min_y = clusters[i][j].y
|
|
159
|
+
# elsif clusters[i][j].y > max_y
|
|
160
|
+
# max_y = clusters[i][j].y
|
|
161
|
+
# end
|
|
162
|
+
# if clusters[i][j].z < min_z
|
|
163
|
+
# min_z = clusters[i][j].z
|
|
164
|
+
# elsif clusters[i][j].z > max_z
|
|
165
|
+
# max_z = clusters[i][j].z
|
|
166
|
+
# end
|
|
167
|
+
end
|
|
168
|
+
newPoint = Array.new minimus.size
|
|
169
|
+
for x in 0...newPoint.size
|
|
170
|
+
newPoint[x] = (maximus[x]-minimus[x])/2 + minimus[x]
|
|
171
|
+
end
|
|
172
|
+
@centroids[i] = Point.new newPoint
|
|
173
|
+
# @centroids[i] = Point.new (max_x-min_x)/2+min_x, (max_y-min_y)/2+min_y, (max_z-min_z)/2+min_z
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def stop_condition
|
|
179
|
+
ending = false
|
|
180
|
+
for i in 0...@centroids.size
|
|
181
|
+
fin = false
|
|
182
|
+
if !@centroids[i].equals @old_centroids[i]
|
|
183
|
+
ending = true
|
|
184
|
+
break
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
ret = ending
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: NDKMeans
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Salvador Guerra Delgado
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2018-10-12 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Multi dimensional K-Means clustering algorithm
|
|
14
|
+
email: salvador.guerra.delgado2@gmail.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- Rakefile
|
|
20
|
+
- bin/TestMultiDimension
|
|
21
|
+
- lib/MultiDimensional KMeans.rb
|
|
22
|
+
homepage: http://rubygems.org/gems/SEATC
|
|
23
|
+
licenses:
|
|
24
|
+
- MIT
|
|
25
|
+
metadata: {}
|
|
26
|
+
post_install_message:
|
|
27
|
+
rdoc_options: []
|
|
28
|
+
require_paths:
|
|
29
|
+
- lib
|
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
31
|
+
requirements:
|
|
32
|
+
- - ">="
|
|
33
|
+
- !ruby/object:Gem::Version
|
|
34
|
+
version: '0'
|
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
requirements: []
|
|
41
|
+
rubyforge_project:
|
|
42
|
+
rubygems_version: 2.5.2.1
|
|
43
|
+
signing_key:
|
|
44
|
+
specification_version: 3
|
|
45
|
+
summary: SEATC
|
|
46
|
+
test_files: []
|