-
Notifications
You must be signed in to change notification settings - Fork 13
/
faces_utilities.jl
97 lines (95 loc) · 2.72 KB
/
faces_utilities.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# Utilities we need. unzip is being contributed to ZipFile,
# the more memory-efficient lda is being offered to MultivariateStats.
function unzip(inputfilename, outputpath=pwd())
r = ZipFile.Reader(inputfilename)
for f in r.files
outpath = joinpath(outputpath, f.name)
if isdirpath(outpath)
mkpath(outpath)
else
open(outpath, "w") do io
write(io, readall(f))
end
end
end
nothing
end
## Memory-efficient LDA
# These are large vectors, and storing the full covariance matrix is
# problematic. This algorithm works in terms of a projection onto a
# subspace spanning the means, which also serves to regularize. See
# Yu, Hua, and Jie Yang. "A direct LDA algorithm for
# high-dimensional data—with application to face recognition."
# Pattern recognition 34.10 (2001): 2067-2070.
function lda{T}(X::AbstractMatrix{T}, group::Vector{Int})
nd = size(X,1)
dmeans, dX = lda_prepare(X, group)
UB, SB, _ = svd(dmeans, thin=true)
ikeep = SB .>= sqrt(eps(T))*maximum(SB)
Y = UB[:,ikeep]
Z = scale(Y, 1./SB[ikeep])
projW = Z'*dX
UW, SW, _ = svd(projW, thin=true)
eigenval = 1./SW.^2
eigenvec = Z*scale(UW, 1./SW)
# Normalize
for j = 1:size(eigenvec,2)
evn = zero(T)
for i = 1:nd
evn += eigenvec[i,j]^2
end
evn = sqrt(evn)
for i = 1:nd
eigenvec[i,j] /= evn
end
end
# Start with largest eigenvalues first
return eigenvec[:,end:-1:1], eigenval[end:-1:1]
end
function lda_prepare{T}(X::AbstractMatrix{T}, group::Vector{Int})
nd = size(X,1)
npoints = size(X,2)
xbar = zeros(T,nd)
ngroups = maximum(group)
if ngroups > npoints
error("The group indices must be consecutive, starting at 1")
end
ngroups > 1 || error("Must have more than one group")
# Calculate the group means
means = zeros(T,nd,ngroups)
npergroup = zeros(Int,ngroups)
for j = 1:npoints
k = group[j]
for i = 1:nd
means[i,k] += X[i,j]
end
npergroup[k] += 1
end
keep = npergroup .> 0
if !all(keep)
npergroup = npergroup[keep]
means = means[:,keep]
end
gindex = cumsum(keep)
ngroups = length(npergroup)
for j = 1:ngroups
n = npergroup[j]
for i = 1:nd
xbar[i] += means[i,j]
means[i,j] /= n
end
end
for i = 1:nd
xbar[i] /= npoints
end
# Compute differences from the means
dX = Array(T, nd, npoints)
for j = 1:npoints
k = gindex[group[j]]
for i = 1:nd
dX[i,j] = X[i,j] - means[i,k]
end
end
dmeans = means .- xbar
dmeans, dX
end