17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
# File 'lib/classifier-reborn/extensions/vector.rb', line 17
def SV_decomp(maxSweeps = 20)
q = if row_size >= column_size
trans * self
else
self * trans
end
qrot = q.dup
v = Matrix.identity(q.row_size)
mzrot = nil
cnt = 0
s_old = nil
loop do
cnt += 1
(0...qrot.row_size - 1).each do |row|
(1..qrot.row_size - 1).each do |col|
next if row == col
h = if (2.0 * qrot[row, col]) == (qrot[row, row] - qrot[col, col])
Math.atan(1) / 2.0
else
Math.atan((2.0 * qrot[row, col]) / (qrot[row, row] - qrot[col, col])) / 2.0
end
hcos = Math.cos(h)
hsin = Math.sin(h)
mzrot = Matrix.identity(qrot.row_size)
mzrot[row, row] = hcos
mzrot[row, col] = -hsin
mzrot[col, row] = hsin
mzrot[col, col] = hcos
qrot = mzrot.trans * qrot * mzrot
v *= mzrot
end
end
s_old = qrot.dup if cnt == 1
sum_qrot = 0.0
if cnt > 1
qrot.row_size.times do |r|
sum_qrot += (qrot[r, r] - s_old[r, r]).abs if (qrot[r, r] - s_old[r, r]).abs > 0.001
end
s_old = qrot.dup
end
break if (sum_qrot <= 0.001 && cnt > 1) || cnt >= maxSweeps
end s = []
qrot.row_size.times do |r|
s << Math.sqrt(qrot[r, r])
end
if row_size >= column_size
mu = self * v * Matrix.diagonal(*s).inverse
return [mu, v, s]
else
puts v.row_size
puts v.column_size
puts row_size
puts column_size
puts s.size
mu = (trans * v * Matrix.diagonal(*s).inverse)
return [mu, v, s]
end
end
|