Skip to content

Commit 7b10973

Browse files
authored
Merge branch 'JuliaAI:dev' into dev
2 parents 00e752c + f721c3b commit 7b10973

File tree

6 files changed

+78
-67
lines changed

6 files changed

+78
-67
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# MLJ <> MultivariateStats.jl
2-
Repository implementing MLJ interface for
1+
# MLJMultivariateStatsInterface.jl
2+
Repository implementing [MLJ](https://alan-turing-institute.github.io/MLJ.jl/dev/) interface for
33
[MultivariateStats](https://github.com/JuliaStats/MultivariateStats.jl) models.
44

55

src/models/decomposition_models.jl

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ $PCA_DESCR
2222
@mlj_model mutable struct PCA <: MMI.Unsupervised
2323
maxoutdim::Int = 0::(_ ≥ 0)
2424
method::Symbol = :auto::(_ in (:auto, :cov, :svd))
25-
pratio::Float64 = 0.99::(0.0 < _ ≤ 1.0)
25+
variance_ratio::Float64 = 0.99::(0.0 < _ ≤ 1.0)
2626
mean::Union{Nothing, Real, Vector{Float64}} = nothing::(_check_typeof_mean(_))
2727
end
2828

@@ -37,14 +37,14 @@ function MMI.fit(model::PCA, verbosity::Int, X)
3737
fitresult = MS.fit(
3838
MS.PCA, Xarray';
3939
method=model.method,
40-
pratio=model.pratio,
40+
pratio=model.variance_ratio,
4141
maxoutdim=maxoutdim,
4242
mean=model.mean
4343
)
4444
cache = nothing
4545
report = (
46-
indim=MS.size(fitresult,1),
47-
outdim=MS.size(fitresult,2),
46+
indim=size(fitresult)[1],
47+
outdim=size(fitresult)[2],
4848
tprincipalvar=MS.tprincipalvar(fitresult),
4949
tresidualvar=MS.tresidualvar(fitresult),
5050
tvar=MS.var(fitresult),
@@ -112,8 +112,8 @@ function MMI.fit(model::KernelPCA, verbosity::Int, X)
112112
)
113113
cache = nothing
114114
report = (
115-
indim=MS.size(fitresult,1),
116-
outdim=MS.size(fitresult,2),
115+
indim=size(fitresult)[1],
116+
outdim=size(fitresult)[2],
117117
principalvars=copy(MS.eigvals(fitresult))
118118
)
119119
return fitresult, cache, report
@@ -155,7 +155,7 @@ $ICA_DESCR
155155
`Matrix{<:Real}` is used.
156156
"""
157157
@mlj_model mutable struct ICA <: MMI.Unsupervised
158-
k::Int = 0::(_ ≥ 0)
158+
outdim::Int = 0::(_ ≥ 0)
159159
alg::Symbol = :fastica::(_ in (:fastica,))
160160
fun::Symbol = :tanh::(_ in (:tanh, :gaus))
161161
do_whiten::Bool = true
@@ -174,7 +174,7 @@ function MMI.fit(model::ICA, verbosity::Int, X)
174174
Xarray = MMI.matrix(X)
175175
n, p = size(Xarray)
176176
m = min(n, p)
177-
k = ifelse(model.k m, model.k, m)
177+
k = ifelse(model.outdim m, model.outdim, m)
178178
fitresult = MS.fit(
179179
MS.ICA, Xarray', k;
180180
alg=model.alg,
@@ -187,8 +187,8 @@ function MMI.fit(model::ICA, verbosity::Int, X)
187187
)
188188
cache = nothing
189189
report = (
190-
indim=MS.size(fitresult,1),
191-
outdim=MS.size(fitresult,2),
190+
indim=size(fitresult)[1],
191+
outdim=size(fitresult)[2],
192192
mean=copy(MS.mean(fitresult))
193193
)
194194
return fitresult, cache, report
@@ -246,8 +246,8 @@ function MMI.fit(model::PPCA, verbosity::Int, X)
246246
)
247247
cache = nothing
248248
report = (
249-
indim=MS.size(fitresult,1),
250-
outdim=MS.size(fitresult,2),
249+
indim=size(fitresult)[1],
250+
outdim=size(fitresult)[2],
251251
tvar=MS.var(fitresult),
252252
mean=copy(MS.mean(fitresult)),
253253
loadings=MS.loadings(fitresult)
@@ -309,8 +309,8 @@ function MMI.fit(model::FactorAnalysis, verbosity::Int, X)
309309
)
310310
cache = nothing
311311
report = (
312-
indim=MS.size(fitresult,1),
313-
outdim=MS.size(fitresult,2),
312+
indim=size(fitresult)[1],
313+
outdim=size(fitresult)[2],
314314
variance=MS.var(fitresult),
315315
covariance_matrix=MS.cov(fitresult),
316316
mean=MS.mean(fitresult),
@@ -340,8 +340,13 @@ model_types = [
340340
]
341341

342342
for (M, MFitResultType) in model_types
343-
@eval function MMI.fitted_params(::$M, fr)
344-
return (projection=copy(MS.projection(fr)),)
343+
344+
if M !== ICA # special cased below
345+
quote
346+
function MMI.fitted_params(::$M, fr)
347+
return (projection=copy(MS.projection(fr)),)
348+
end
349+
end |> eval
345350
end
346351

347352
@eval function MMI.transform(::$M, fr::$MFitResultType, X)
@@ -360,3 +365,5 @@ for (M, MFitResultType) in model_types
360365
end
361366
end
362367
end
368+
369+
MMI.fitted_params(::ICA, fr) = (projection=copy(fr.W), mean = copy(MS.mean(fr)))

src/models/discriminant_analysis.jl

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -36,32 +36,32 @@ download?doi=10.1.1.89.7068&rep=rep1&type=pdf).
3636
method::Symbol = :gevd::(_ in (:gevd, :whiten))
3737
cov_w::CovarianceEstimator = MS.SimpleCovariance()
3838
cov_b::CovarianceEstimator = MS.SimpleCovariance()
39-
out_dim::Int = 0::(_ ≥ 0)
39+
outdim::Int = 0::(_ ≥ 0)
4040
regcoef::Float64 = 1e-6::(_ ≥ 0)
4141
dist::SemiMetric = SqEuclidean()
4242
end
4343

4444
function MMI.fit(model::LDA, ::Int, X, y)
45-
Xm_t, yplain, classes_seen, p, n, nc, nclasses, integers_seen, out_dim =
45+
Xm_t, yplain, classes_seen, p, n, nc, nclasses, integers_seen, outdim =
4646
_check_lda_data(model, X, y)
4747
core_res = MS.fit(
4848
MS.MulticlassLDA, nc, Xm_t, Int.(yplain);
4949
method=model.method,
50-
outdim=out_dim,
50+
outdim,
5151
regcoef=model.regcoef,
5252
covestimator_within=model.cov_w,
5353
covestimator_between=model.cov_b
5454
)
5555
cache = nothing
5656
report = (
5757
classes=classes_seen,
58-
out_dim=MS.size(core_res)[2],
59-
class_means=MS.classmeans(core_res),
58+
outdim=MS.size(core_res)[2],
59+
projected_class_means=MS.classmeans(core_res),
6060
mean=MS.mean(core_res),
6161
class_weights=MS.classweights(core_res),
6262
Sw=MS.withclass_scatter(core_res),
6363
Sb=MS.betweenclass_scatter(core_res),
64-
nc=nc
64+
nclasses=nc
6565
)
6666
fitresult = (core_res, classes_seen)
6767
return fitresult, cache, report
@@ -102,17 +102,17 @@ function _check_lda_data(model, X, y)
102102
# Check output dimension default is min(p, nc-1)
103103
def_outdim = min(p, nc - 1)
104104
# If unset (0) use the default; otherwise try to use the provided one
105-
out_dim = ifelse(model.out_dim == 0, def_outdim, model.out_dim)
105+
outdim = ifelse(model.outdim == 0, def_outdim, model.outdim)
106106
# Check if the given one is sensible
107-
if out_dim > p
107+
if outdim > p
108108
throw(
109109
ArgumentError(
110-
"`out_dim` must not be larger than `p`"*
110+
"`outdim` must not be larger than `p`"*
111111
"where `p` is the number of features in `X`"
112112
)
113113
)
114114
end
115-
return Xm_t, yplain, classes_seen, p, n, nc, nclasses, integers_seen, out_dim
115+
return Xm_t, yplain, classes_seen, p, n, nc, nclasses, integers_seen, outdim
116116
end
117117

118118
function MMI.fitted_params(::LDA, (core_res, classes_seen))
@@ -187,13 +187,13 @@ http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.89.7068&rep=rep1&type=p
187187
method::Symbol = :gevd::(_ in (:gevd, :whiten))
188188
cov_w::CovarianceEstimator=MS.SimpleCovariance()
189189
cov_b::CovarianceEstimator=MS.SimpleCovariance()
190-
out_dim::Int=0::(_ ≥ 0)
190+
outdim::Int=0::(_ ≥ 0)
191191
regcoef::Float64=1e-6::(_ ≥ 0)
192192
priors::Union{Nothing, Vector{Float64}}=nothing
193193
end
194194

195195
function MMI.fit(model::BayesianLDA, ::Int, X, y)
196-
Xm_t, yplain, classes_seen, p, n, nc, nclasses, integers_seen, out_dim =
196+
Xm_t, yplain, classes_seen, p, n, nc, nclasses, integers_seen, outdim =
197197
_check_lda_data(model, X, y)
198198
## If piors are specified check if they makes sense.
199199
## This was put here to through errors much earlier
@@ -204,7 +204,7 @@ function MMI.fit(model::BayesianLDA, ::Int, X, y)
204204
core_res = MS.fit(
205205
MS.MulticlassLDA, nc, Xm_t, Int.(yplain);
206206
method=model.method,
207-
outdim=out_dim,
207+
outdim,
208208
regcoef=model.regcoef,
209209
covestimator_within=model.cov_w,
210210
covestimator_between=model.cov_b
@@ -220,13 +220,13 @@ function MMI.fit(model::BayesianLDA, ::Int, X, y)
220220
cache = nothing
221221
report = (
222222
classes=classes_seen,
223-
out_dim=MS.size(core_res)[2],
224-
class_means=MS.classmeans(core_res),
223+
outdim=MS.size(core_res)[2],
224+
projected_class_means=MS.classmeans(core_res),
225225
mean=MS.mean(core_res),
226226
class_weights=MS.classweights(core_res),
227227
Sw=MS.withclass_scatter(core_res),
228228
Sb=MS.betweenclass_scatter(core_res),
229-
nc=nc
229+
nclasses=nc
230230
)
231231

232232
fitresult = (core_res, classes_seen, priors, n)
@@ -336,12 +336,12 @@ IEEE Trans. Patt. Anal. & Mach. Int., 26: 995-1006.
336336
"""
337337
@mlj_model mutable struct SubspaceLDA <: MMI.Probabilistic
338338
normalize::Bool = true
339-
out_dim::Int = 0::(_ ≥ 0)
339+
outdim::Int = 0::(_ ≥ 0)
340340
dist::SemiMetric = SqEuclidean()
341341
end
342342

343343
function MMI.fit(model::SubspaceLDA, ::Int, X, y)
344-
Xm_t, yplain, classes_seen, p, n, nc, nclasses, integers_seen, out_dim =
344+
Xm_t, yplain, classes_seen, p, n, nc, nclasses, integers_seen, outdim =
345345
_check_lda_data(model, X, y)
346346

347347
core_res = MS.fit(
@@ -356,23 +356,23 @@ function MMI.fit(model::SubspaceLDA, ::Int, X, y)
356356
report = (
357357
explained_variance_ratio=explained_variance_ratio,
358358
classes=classes_seen,
359-
class_means=MS.classmeans(core_res),
359+
projected_class_means=MS.classmeans(core_res),
360360
mean=MS.mean(core_res),
361361
class_weights=MS.classweights(core_res),
362-
nc=nc
362+
nclasses=nc,
363363
)
364-
fitresult = (core_res, out_dim, classes_seen)
364+
fitresult = (core_res, outdim, classes_seen)
365365
return fitresult, cache, report
366366
end
367367

368368
function MMI.fitted_params(::SubspaceLDA, (core_res, _))
369-
return (class_means=MS.classmeans(core_res), projection_matrix=MS.projection(core_res))
369+
return (projected_class_means=MS.classmeans(core_res), projection_matrix=MS.projection(core_res))
370370
end
371371

372-
function MMI.predict(m::SubspaceLDA, (core_res, out_dim, classes_seen), Xnew)
372+
function MMI.predict(m::SubspaceLDA, (core_res, outdim, classes_seen), Xnew)
373373
# projection of Xnew, XWt is nt x o where o = number of out dims
374374
# nt = number ot test samples
375-
proj = core_res.projw * view(core_res.projLDA, :, 1:out_dim) #proj is the projection_matrix
375+
proj = core_res.projw * view(core_res.projLDA, :, 1:outdim) #proj is the projection_matrix
376376
XWt = MMI.matrix(Xnew) * proj
377377
# centroids in the transformed space, nc x o
378378
centroids = transpose(core_res.cmeans) * proj
@@ -423,12 +423,12 @@ For more information about the algorithm, see the paper by Howland & Park (2006)
423423
"""
424424
@mlj_model mutable struct BayesianSubspaceLDA <: MMI.Probabilistic
425425
normalize::Bool=false
426-
out_dim::Int= 0::(_ ≥ 0)
426+
outdim::Int= 0::(_ ≥ 0)
427427
priors::Union{Nothing, Vector{Float64}}=nothing
428428
end
429429

430430
function MMI.fit(model::BayesianSubspaceLDA, ::Int, X, y)
431-
Xm_t, yplain, classes_seen, p, n, nc, nclasses, integers_seen, out_dim =
431+
Xm_t, yplain, classes_seen, p, n, nc, nclasses, integers_seen, outdim =
432432
_check_lda_data(model, X, y)
433433
## If piors are specified check if they makes sense.
434434
## This was put here to through errors much earlier
@@ -456,12 +456,12 @@ function MMI.fit(model::BayesianSubspaceLDA, ::Int, X, y)
456456
report = (
457457
explained_variance_ratio=explained_variance_ratio,
458458
classes=classes_seen,
459-
class_means=MS.classmeans(core_res),
459+
projected_class_means=MS.classmeans(core_res),
460460
mean=MS.mean(core_res),
461461
class_weights=MS.classweights(core_res),
462-
nc=nc
462+
nclasses=nc
463463
)
464-
fitresult = (core_res, out_dim, classes_seen, priors, n, mult)
464+
fitresult = (core_res, outdim, classes_seen, priors, n, mult)
465465
return fitresult, cache, report
466466
end
467467

@@ -479,13 +479,13 @@ end
479479

480480
function MMI.predict(
481481
m::BayesianSubspaceLDA,
482-
(core_res, out_dim, classes_seen, priors, n, mult),
482+
(core_res, outdim, classes_seen, priors, n, mult),
483483
Xnew
484484
)
485485
# projection of Xnew, XWt is nt x o where o = number of out dims
486486
# nt = number ot test samples
487487
#proj is the projection_matrix
488-
proj = core_res.projw * view(core_res.projLDA, :, 1:out_dim)
488+
proj = core_res.projw * view(core_res.projLDA, :, 1:outdim)
489489
XWt = MMI.matrix(Xnew) * proj
490490

491491
# centroids in the transformed space, nc x o
@@ -510,9 +510,9 @@ function MMI.predict(
510510
return MMI.UnivariateFinite(classes_seen, Pr)
511511
end
512512

513-
function MMI.transform(m::T, (core_res, out_dim, _), X) where T<:Union{SubspaceLDA, BayesianSubspaceLDA}
513+
function MMI.transform(m::T, (core_res, outdim, _), X) where T<:Union{SubspaceLDA, BayesianSubspaceLDA}
514514
# projection of X, XWt is nt x o where o = out dims
515-
proj = core_res.projw * view(core_res.projLDA, :, 1:out_dim)
515+
proj = core_res.projw * view(core_res.projLDA, :, 1:outdim)
516516
#proj is the projection_matrix
517517
XWt = MMI.matrix(X) * proj
518518
return MMI.table(XWt, prototype = X)

0 commit comments

Comments
 (0)