ruby-svd 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/svd_matrix.rb +37 -8
- metadata +3 -3
data/lib/svd_matrix.rb
CHANGED
@@ -3,39 +3,68 @@ require 'svd'
|
|
3
3
|
|
4
4
|
class SVDMatrix < Matrix
|
5
5
|
public_class_method :new
|
6
|
+
|
7
|
+
# Create a new SVD Matrix with m rows, n columns
|
6
8
|
def initialize(m, n)
|
7
9
|
@rows = Array.new(m)
|
8
10
|
m.times {|i| @rows[i] = Array.new(n)}
|
9
11
|
end
|
10
12
|
|
13
|
+
# Set the value of the cell i, j
|
11
14
|
def []=(i, j, val)
|
12
15
|
@rows[i][j] = val
|
13
16
|
end
|
14
17
|
|
15
|
-
|
18
|
+
# Set the value of a row to an array
|
19
|
+
def set_row(i, row)
|
16
20
|
@rows[i] = row
|
17
21
|
end
|
18
22
|
|
23
|
+
# Nicely formatted inspect string for the matrix
|
19
24
|
def inspect
|
20
25
|
@rows.collect {|row| "#{row.inspect}\n"}
|
21
26
|
end
|
22
|
-
|
23
|
-
|
27
|
+
|
28
|
+
# Perform SVD and decompose the matrix into three matrices:
|
29
|
+
# U, W, and V. You can choose to reduce the dimensionality of
|
30
|
+
# the data by setting a number of diagonal cells to 0. For
|
31
|
+
# example, reduce_dimentions_to = 2 will set a 4x4 W
|
32
|
+
# matrix into:
|
33
|
+
# [NUM, 0, 0, 0]
|
34
|
+
# [0, NUM, 0, 0]
|
35
|
+
# [ 0, 0, 0, 0 ]
|
36
|
+
# [ 0, 0, 0, 0 ]
|
37
|
+
def decompose(reduce_dimensions_to = nil)
|
24
38
|
input_array = []
|
25
39
|
@rows.each {|row| input_array += row}
|
26
40
|
u_array, w_array, v_array = SVD.decompose(input_array, row_size, column_size)
|
27
41
|
|
42
|
+
# recompose U matrix
|
28
43
|
u = SVDMatrix.new(row_size, column_size)
|
29
|
-
row_size.times {|i| u
|
44
|
+
row_size.times {|i| u.set_row(i, u_array.slice!(0,column_size))}
|
30
45
|
|
46
|
+
# recompose V matric
|
31
47
|
v = SVDMatrix.new(column_size, column_size)
|
32
|
-
column_size.times {|i| v
|
48
|
+
column_size.times {|i| v.set_row(i, v_array.slice!(0,column_size))}
|
33
49
|
v = v.transpose
|
34
50
|
|
35
|
-
|
51
|
+
# diagonalise W array as a matrix
|
52
|
+
if reduce_dimensions_to
|
53
|
+
(reduce_dimensions_to...w_array.size).each {|index| w_array[index] = 0.0}
|
54
|
+
end
|
36
55
|
w = Matrix.diagonal(*w_array)
|
37
56
|
|
38
|
-
|
57
|
+
[u, w, v]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Reduce the number of dimensions of the data to dimensions.
|
61
|
+
# Returns a back a recombined matrix (conceptually the original
|
62
|
+
# matrix dimensionally reduced). For example Latent Semantic
|
63
|
+
# Analysis uses 2 dimensions, and commonly tf-idf cell data.
|
64
|
+
# The recombined matrix, and the 3 decomposed matrices are
|
65
|
+
# returned.
|
66
|
+
def reduce_dimensions(dimensions)
|
67
|
+
u, w, v = self.decompose(dimensions)
|
68
|
+
[(u * w * v), u, w, v]
|
39
69
|
end
|
40
70
|
end
|
41
|
-
|
metadata
CHANGED