ruby-svd 0.1.0 → 0.2.0

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.
Files changed (2) hide show
  1. data/lib/svd_matrix.rb +37 -8
  2. 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
- def []=(i, row)
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
- def lsa
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[i] = u_array.slice!(0,column_size)}
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[i] = v_array.slice!(0,column_size)}
48
+ column_size.times {|i| v.set_row(i, v_array.slice!(0,column_size))}
33
49
  v = v.transpose
34
50
 
35
- w_array = w_array[0...2] + Array.new(w_array.size - 2).collect {|i| 0}
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
- r = (u * w * v)
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
@@ -4,12 +4,12 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
- - Will
12
+ - Will Cannings
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []