Skip to content

Commit 267fc1c

Browse files
committed
simplified sampling without constructing block matrices
1 parent f162e69 commit 267fc1c

10 files changed

Lines changed: 418 additions & 224 deletions

src/HVIApproximation.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ abstract type AbstractMeanHVIApproximation <: AbstractHVIApproximation end
1010

1111
struct MeanHVIApproximation <: AbstractMeanHVIApproximation end
1212
struct MeanHVIApproximationMat <: AbstractMeanHVIApproximation end
13+
struct MeanHVIApproximationDev <: AbstractMeanHVIApproximation end
1314

1415

src/HybridVariationalInference.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ include("cholesky.jl")
112112
export neg_elbo_gtf, sample_posterior, predict_hvi, zero_penalty_loss
113113
include("elbo.jl")
114114
include("elbo2.jl")
115+
include("elbo_dev.jl")
115116

116117
export init_hybrid_params, init_hybrid_ϕunc
117118
include("init_hybrid_params.jl")

src/cholesky.jl

Lines changed: 50 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ function transformU_cholesky1(v::AbstractVector;
158158
U = _transformU_cholesky1_getU(v; n, create_empty)
159159
# ? UpperTriangular has problems with AD (which tries to set elements in lower)
160160
#return U
161-
return (UpperTriangular(U))
161+
_maybe_UpperTriangular(U)
162162
end
163163

164164
function _transformU_cholesky1_getU(v::AbstractVector;
@@ -173,13 +173,9 @@ function _transformU_cholesky1_getU(v::AbstractVector;
173173
U = U_scaled ./ sqrt.(sum(abs2, U_scaled, dims=1))
174174
end
175175

176-
function transformU_cholesky1(v::GPUArraysCore.AbstractGPUVector;
177-
n=invsumn(length(v)) + 1, create_empty = false)
178-
U = _transformU_cholesky1_getU(v; n, create_empty)
179-
# do not convert to UpperTrinangular on GPU, but full matrix
180-
#return (UpperTriangular(U))
181-
return U
182-
end
176+
# convert to UpperTriangular, but not on GPU
177+
_maybe_UpperTriangular(U::AbstractMatrix) = UpperTriangular(U)
178+
_maybe_UpperTriangular(U::GPUArraysCore.AbstractGPUMatrix) = U
183179

184180
# function transformU_block_cholesky1(v::CA.ComponentVector;
185181
# ns=(invsumn(length(v[k])) + 1 for k in keys(v)) # may pass for efficiency
@@ -219,10 +215,11 @@ front(itr, n=1) = Iterators.take(itr, length(itr) - n)
219215
220216
Return a Vector with ending positions of components in vc.
221217
Useful for providing information on correlactions among subranges in a vector.
218+
For an empty vector Int[0] is returned.
222219
"""
223220
function get_ca_ends(vc::CA.ComponentVector)
224221
#(cumsum(length(vc[k]) for k in keys(vc))...,)
225-
length(keys(vc)) == 0 ? Int[] : cumsum(length(vc[k])::Int for k in keys(vc))
222+
length(keys(vc)) == 0 ? Int[0] : cumsum(length(vc[k])::Int for k in keys(vc))
226223
end
227224

228225

@@ -254,7 +251,7 @@ end
254251
transformU_block_cholesky1(v::AbstractVector, cor_ends)
255252
256253
Transform a parameterization, `v`, of a blockdiagonal of upper triangular matrices
257-
into the this matrix.
254+
into a vector with a matrix for each block.
258255
`cor_ends` is an AbstractVector of Integers specifying the last column of each block.
259256
E.g. For a matrix with a 3x3, a 2x2, and another single-entry block,
260257
the blocks start at columns (3,5,6). It defaults to a single entire block.
@@ -263,43 +260,54 @@ An correlation parameterization can parameterize a block of a single parameter,
263260
or an empty parameter block. To indicate the empty block, provide `cor_ends == [0]`.
264261
"""
265262
function transformU_blocks_cholesky1(
266-
v::AbstractVector{T}, cor_ends::AbstractVector{TI}=Int[]) where {T,TI<:Integer}
267-
if length(cor_ends) <= 1 # if there is only one block, return it
268-
# (cor_ends == [0]) no parameters at all (and also no correclation)
269-
# (cor_ends == [1]) a single parameter (and also no correclation)
270-
create_empty = (cor_ends == [0])
271-
return [transformU_cholesky1(v; create_empty)], 1:0
263+
v::AbstractVector{T}, cor_ends::AbstractVector{TI}=1:length(v)) where {T,TI<:Integer}
264+
if isempty(cor_ends) # 1:0
265+
# assume a single parameter -> no correclation -> One() matrix and empty range
266+
# 1-1-matrix with value 1 with the same type as v
267+
v1 = v[1]
268+
v1m = ChainRulesCore.@ignore_derivatives reshape(v[1:1] .* zero(v1) .+ one(v1), 1,1)
269+
[_maybe_UpperTriangular(v1m)], (1:1 for i in 1:1)
270+
elseif (cor_ends == [0])
271+
#no parameters at all (and also no correclation) -> empty matrix and empty range
272+
[_maybe_UpperTriangular(reshape(v[1:0],0,0))], (1:0 for i in 1:1)
273+
else
274+
cor_counts = get_cor_counts(cor_ends) # number of correlation parameters
275+
ranges = ChainRulesCore.@ignore_derivatives (
276+
begin
277+
cor_start = (i == 1 ? one(TI) : cor_counts[i-1] + one(TI))
278+
cor_start:cor_counts[i]
279+
end for i in 1:length(cor_counts)
280+
)
281+
ranges_z = ChainRulesCore.@ignore_derivatives (
282+
begin
283+
284+
cor_start = (i == 1 ? one(TI) : cor_ends[i-1] + one(TI))
285+
cor_start:cor_ends[i]
286+
end for i in 1:length(cor_counts)
287+
)
288+
[transformU_cholesky1(v[r]) for r in ranges], ranges_z
272289
end
273-
cor_counts = get_cor_counts(cor_ends) # number of correlation parameters
274-
#@show cor_counts
275-
ranges = ChainRulesCore.@ignore_derivatives (
276-
begin
277-
cor_start = (i == 1 ? one(TI) : cor_counts[i-1] + one(TI))
278-
cor_start:cor_counts[i]
279-
end for i in 1:length(cor_counts)
280-
)
281-
#@show collect(ranges)
282-
[transformU_cholesky1(v[r]) for r in ranges], ranges
283290
end
284291

285292
function transformU_block_cholesky1(
286293
v::AbstractVector{T}, cor_ends::AbstractVector{TI}=Int[]) where {T,TI<:Integer}
287-
# (cor_ends == [0]) no parameters at all (and also no correclation)
288-
if length(cor_ends) <= 1 # if there is only one block, return it
289-
# for type stability create a BlockDiagonal of a single block
290-
create_empty = (cor_ends == [0])
291-
return _create_blockdiag(v, [transformU_cholesky1(v; create_empty)])
292-
end
293-
cor_counts = get_cor_counts(cor_ends) # number of correlation parameters
294-
#@show cor_counts
295-
ranges = ChainRulesCore.@ignore_derivatives (
296-
begin
297-
cor_start = (i == 1 ? one(TI) : cor_counts[i-1] + one(TI))
298-
cor_start:cor_counts[i]
299-
end for i in 1:length(cor_counts)
300-
)
301-
#@show collect(ranges)
302-
blocks = [transformU_cholesky1(v[r]) for r in ranges]
294+
blocks, _ = transformU_blocks_cholesky1(v, cor_ends)
295+
# # (cor_ends == [0]) no parameters at all (and also no correclation)
296+
# if length(cor_ends) <= 1 # if there is only one block, return it
297+
# # for type stability create a BlockDiagonal of a single block
298+
# create_empty = (cor_ends == [0])
299+
# return _create_blockdiag(v, [transformU_cholesky1(v; create_empty)])
300+
# end
301+
# cor_counts = get_cor_counts(cor_ends) # number of correlation parameters
302+
# #@show cor_counts
303+
# ranges = ChainRulesCore.@ignore_derivatives (
304+
# begin
305+
# cor_start = (i == 1 ? one(TI) : cor_counts[i-1] + one(TI))
306+
# cor_start:cor_counts[i]
307+
# end for i in 1:length(cor_counts)
308+
# )
309+
# #@show collect(ranges)
310+
# blocks = [transformU_cholesky1(v[r]) for r in ranges]
303311
U = _create_blockdiag(v, blocks) # v only for dispatch: plain matrix for gpu
304312
return (U)
305313
end

src/elbo.jl

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -578,14 +578,16 @@ function sample_ζresid_norm(approx::AbstractHVIApproximation, rng::Random.Abstr
578578
# P = (n_MC, n_θP), Ms = (n_MC, n_θM, n_site_batch)))
579579
# end
580580
#urandn = _create_randn(rng, CA.getdata(ζP), n_MC, n_θP + n_θMs)
581-
urandn = _create_randn(rng, CA.getdata(ζP), n_θP + n_θMs, n_MC)
582-
sample_ζresid_norm(approx, urandn, CA.getdata(ζP), CA.getdata(ζMs), args...;
581+
z = _create_randn(rng, CA.getdata(ζP), n_MC, n_θP + n_θMs)
582+
zP = @view z[:, 1:n_θP]
583+
zMs = @view z[:, (n_θP+1):end]
584+
sample_ζresid_norm(approx, zP, zMs, CA.getdata(ζP), CA.getdata(ζMs), args...;
583585
cor_ends,
584586
int_ϕq=get_concrete(int_ϕq)
585587
)
586588
end
587589

588-
function sample_ζresid_norm(approx::MeanHVIApproximationMat, urandn::AbstractMatrix,
590+
function sample_ζresid_norm(approx::MeanHVIApproximationMat, zP::AbstractMatrix, zMs::AbstractMatrix,
589591
ζP::TP, ζMs::TM, ϕq::AbstractVector;
590592
int_ϕq=get_concrete(ComponentArrayInterpreter(ϕq)),
591593
cor_ends
@@ -609,9 +611,11 @@ function sample_ζresid_norm(approx::MeanHVIApproximationMat, urandn::AbstractMa
609611
# need to construct full matrix for CUDA
610612
Uσ, diagUσ = _compute_choleskyfactor(UP, UM, σP, σMs, n_batch) # inferred only BlockDiagonal
611613
#diagUσ = diag(Uσ)::typeof(σP) # elements of the diagonal: standard deviations
612-
n_MC = size(urandn, 2) # TODO transform urandn
614+
n_MC = size(zP, 1)
613615
# is this multiplication efficient if Uσ is not concrete but only sumtype BlockDiagonal?
614-
ζ_resids_parfirst = (Uσ' * urandn) #::typeof(urandn) # n_par x n_MC
616+
urandn = hcat(zP, zMs)
617+
ζ_resids_parfirst = (Uσ' * urandn') #::typeof(urandn) # n_par x n_MC
618+
#ζ_resids_parfirst = (urandn * Uσ)' #::typeof(urandn) # n_par x n_MC
615619
#ζ_resids_parfirst = urandn' * Uσ # n_MC x n_par
616620
# need to handle empty(ζP) explicitly, otherwise Zygote tries to take gradient
617621
ζP_resids = isempty(ζP) ? ζ_resids_parfirst[1:0, :] : ζ_resids_parfirst[1:n_θP, :]
@@ -682,8 +686,10 @@ function _compute_choleskyfactor(UP::AbstractMatrix{T}, UM, σP, σMs, n_batch)
682686
#diagUσM = reduce(vcat, [diag(UM) .* σMs[:, i] for i in 1:n_batch]; init = σMs[1:0])
683687
empty_arr = ChainRulesCore.@ignore_derivatives eltype(σMs)[]
684688
#diagUσM = reduce(vcat, [diag(UM) .* σMs[:, i] for i in 1:n_batch]; init=empty_arr)
685-
diagUσM = vcat([diag(UM) .* σMs[:, i] for i in 1:n_batch]...)::Vector{T}
686-
diagUσ = vcat(diag(UP) .* σP, diagUσM)
689+
#diag U = ones -> diag Uσ = σ
690+
# diagUσM = vcat([diag(UM) .* σMs[:, i] for i in 1:n_batch]...)::Vector{T}
691+
# diagUσ = vcat(diag(UP) .* σP, diagUσM)
692+
diagUσ = vcat(σP, vec(σMs))
687693
# diagUσ == diag(Uσ)
688694
Uσ, diagUσ
689695
end

src/elbo2.jl

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,86 @@
1-
function sample_ζresid_norm(app::MeanHVIApproximation, z::AbstractMatrix, ζP::TP, ζMs::TM,
1+
function sample_ζresid_norm(app::MeanHVIApproximation,
2+
zP::AbstractMatrix, zMs::AbstractMatrix, ζP::TP, ζMs::TM,
23
ϕq::AbstractVector;
34
int_ϕq=get_concrete(ComponentArrayInterpreter(ϕq)),
45
cor_ends
56
) where {T,TP<:AbstractVector{T},TM<:AbstractMatrix{T}}
67
ϕuncc = int_ϕq(CA.getdata(ϕq))
7-
n_θP, n_θMs, (n_θM, n_batch) = length(ζP), length(ζMs), size(ζMs)
8+
n_θP, n_θMs, (n_θM, n_batch), n_MC = length(ζP), length(ζMs), size(ζMs), size(zP,1)
89
# do not create a UpperTriangular Matrix of an AbstractGÜUArray in transformU_cholesky1
910
ρsP = isempty(ϕuncc[Val(:ρsP)]) ? similar(ϕuncc[Val(:ρsP)]) : ϕuncc[Val(:ρsP)] # required by zygote
1011
UPs, rangesP = transformU_blocks_cholesky1(ρsP, cor_ends.P)
11-
UP = transformU_block_cholesky1(ρsP, cor_ends.P)
12-
ρsM, rangesM = isempty(ϕuncc[Val(:ρsM)]) ? similar(ϕuncc[Val(:ρsM)]) : ϕuncc[Val(:ρsM)] # required by zygote
12+
ρsM = isempty(ϕuncc[Val(:ρsM)]) ? similar(ϕuncc[Val(:ρsM)]) : ϕuncc[Val(:ρsM)] # required by zygote
1313
# cholesky factor of the correlation: diag(UM' * UM) .== 1
1414
# coefficients ρsM can be larger than 1, still yielding correlations <1 in UM' * UM
15-
UMs = transformU_block_cholesky1(ρsM, cor_ends.M)
15+
UMs, rangesM = transformU_blocks_cholesky1(ρsM, cor_ends.M)
1616
cf = ϕuncc[Val(:coef_logσ2_ζMs)]
1717
logσ2_logMs = vec(cf[1, :] .+ cf[2, :] .* ζMs)
1818
logσ2_ζP = vec(CA.getdata(ϕuncc[Val(:logσ2_ζP)]))
1919
# CUDA cannot multiply BlockDiagonal * Diagonal, construct already those blocks
2020
σMs = reshape(exp.(logσ2_logMs ./ 2), n_θM, :)
2121
σP = exp.(logσ2_ζP ./ 2)
22-
# create random numbers from U diag(σ) z = (σ .* z)
23-
24-
25-
# # BlockDiagonal does work with CUDA, but not with combination of Zygote and CUDA
26-
# # need to construct full matrix for CUDA
27-
# Uσ, diagUσ = _compute_choleskyfactor(UP, UM, σP, σMs, n_batch) # inferred only BlockDiagonal
28-
# #diagUσ = diag(Uσ)::typeof(σP) # elements of the diagonal: standard deviations
29-
# n_MC = size(urandn, 2) # TODO transform urandn
30-
# # is this multiplication efficient if Uσ is not concrete but only sumtype BlockDiagonal?
31-
# ζ_resids_parfirst = (Uσ' * urandn) #::typeof(urandn) # n_par x n_MC
32-
# #ζ_resids_parfirst = urandn' * Uσ # n_MC x n_par
33-
# # need to handle empty(ζP) explicitly, otherwise Zygote tries to take gradient
34-
# ζP_resids = isempty(ζP) ? ζ_resids_parfirst[1:0, :] : ζ_resids_parfirst[1:n_θP, :]
35-
# ζMs_parfirst_resids = reshape(ζ_resids_parfirst[(n_θP+1):end, :], n_θM, n_batch, n_MC)
36-
22+
# create random numbers from U diag(σ) z = U (σ .* z)
23+
# for each block separately
24+
#σzMs = σMs .* reshape(zMs, (n_θM, n_batch, n_MC))
25+
#Ui, ri = first(zip(UMs, rangesM))
26+
zMs_subjects = reshape(zMs, (n_MC, n_θM, n_batch))
27+
#σM, zM = first(zip(eachcol(σMs), eachslice(zMs_subjects; dims=3)))
28+
cat3 = (x,y) -> cat(x,y,dims=3)
29+
# map across subjects (n_batch)
30+
#ζMs_vec = map(eachcol(σMs), eachslice(zMs_subjects; dims=3)) do σM, zM
31+
fBlock = let UMs = UMs, rangesM = collect(rangesM) # without collect, type unstable
32+
function fBlock_inner(σM, zM)
33+
mapreduce(vcat, UMs, rangesM) do Ui, ri # n_θM, n_MC
34+
ri::UnitRange{Int}
35+
#(zM[:,ri]' * Ui * diagm(σM[ri]))'
36+
diagm(σM[ri]) * Ui' * zM[:, ri]'
37+
end
38+
end
39+
end
40+
ζMs1 = ChainRulesCore.@ignore_derivatives fBlock(σMs[:,1], zMs_subjects[:,:,1])
41+
#TB = Base.infer_return_type(fBlock, (typeof(σMs[:,1]), typeof(zMs_subjects[:,:,1])))
42+
#ζMs_vec = map(fBlock, eachcol(σMs[:,2:end]), eachslice(zMs_subjects[:,:,2:end]; dims=3), init = ζMs1)
43+
ζMs_vec = map((σM, zM) -> fBlock(σM, zM)::typeof(ζMs1), eachcol(σMs), eachslice(zMs_subjects; dims=3))
44+
#zM = zMs_subjects[:,:,1]
45+
#ζMs_vec = [fBlock(σMs[:,i], zM) for i in axes(σMs, 2)]
46+
#ζMs_vec = [fBlock(σMs[:,1], zM)]
47+
#ζMs_vec = [fBlock(σMs[:,1], zM) for i in 1:n_batch]
48+
#ζMs_vec = [fBlock(σMs[:,1], zM) for i in axes(σMs, 2)]
49+
#ζMs_vec = [fBlock(σM, zM) for (σM, zM) in zip(eachcol(σMs), eachslice(zMs_subjects; dims=3))]
50+
# concatenate so that n_MC is last dimension
51+
local ζMs_parfirst_resids = stack(ζMs_vec; dims = 2 ) # n_θM, n_batch, n_MC
52+
#size(ζMs_parfirst_resids)
3753

54+
# std(ζMs_parfirst_resids[1,1,:])
55+
# std(ζMs_parfirst_resids[1,end,:])
56+
# σzMs_stacked = reshape(σzMs, (n_θM, n_batch * n_MC))
57+
# ζMs_resids_stacked = mapreduce(vcat, UMs, rangesM) do Ui, ri
58+
# #Ui * σzMs_stacked[ri, :]
59+
# Uσ = Ui * σMs[ri,:]
60+
# Uσ' * zMs[:,ri]'
61+
# diagm(σMs[ri,:]) * Ui' * zMs[:,ri]'
62+
# end
63+
# ζMs_parfirst_resids = reshape(ζMs_resids_stacked, n_θM, n_batch, n_MC)
64+
#
65+
#σzP = σP .* reshape(zP, (n_θP, n_MC))
66+
#Ui, ri = first(zip(UPs, rangesP))
67+
local ζP_resids = if isempty(ζP)
68+
# provide init of correct empty matrix type
69+
# single branch with init to mapreduce has Problems with Zygote
70+
ChainRulesCore.@ignore_derivatives ζMs_parfirst_resids[1:0,1,1:n_MC]
71+
else
72+
mapreduce(vcat, UPs, rangesP) do Ui, ri
73+
diagm(σP[ri]) * Ui' * zP[:,ri]'
74+
end
75+
end
76+
#
77+
() -> begin
78+
tmp = tmp1 = (σzP[ri,:]' * Ui)'
79+
tmp = tmp2 = (zP * (Ui * diagm(σP)))'
80+
tmp = tmp3 = (zP * Ui * diagm(σP))' # σ on wrong side of U
81+
tmp = tmp4 = diagm(σP) * Ui' * zP' # σ on wrong side of U
82+
std(tmp[2,:])
83+
end
84+
diagUσ = vcat(σP, vec(σMs))
3885
ζP_resids, ζMs_parfirst_resids, diagUσ
39-
# #map(std, eachcol(ζ_resids_parfirst[:, 3:8]))
40-
# ζ_resid = transpose_mPMs_sitefirst(ζ_resids_parfirst; intm_PMs_parfirst)
41-
# #map(std, eachcol(ζ_resid[:, 3:8])) # all ~ 0.1 in sample_ζresid_norm cpu
42-
# #map(std, eachcol(ζ_resid[:, 2 + n_batch .+ (-1:5)])) # all ~ 100, except first two
43-
# # returns AbstractGPUuArrays to either continue on GPU or need to transfer to CPU
44-
# ζ_resid, diagUσ
4586
end

src/elbo_dev.jl

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
function sample_ζresid_norm(app::MeanHVIApproximationDev,
2+
zP::AbstractMatrix, zMs::AbstractMatrix, ζP::TP, ζMs::TM,
3+
ϕq::AbstractVector;
4+
int_ϕq=get_concrete(ComponentArrayInterpreter(ϕq)),
5+
cor_ends
6+
) where {T,TP<:AbstractVector{T},TM<:AbstractMatrix{T}}
7+
ϕuncc = int_ϕq(CA.getdata(ϕq))
8+
n_θP, n_θMs, (n_θM, n_batch), n_MC = length(ζP), length(ζMs), size(ζMs), size(zP,1)
9+
# do not create a UpperTriangular Matrix of an AbstractGÜUArray in transformU_cholesky1
10+
ρsP = isempty(ϕuncc[Val(:ρsP)]) ? similar(ϕuncc[Val(:ρsP)]) : ϕuncc[Val(:ρsP)] # required by zygote
11+
UPs, rangesP = transformU_blocks_cholesky1(ρsP, cor_ends.P)
12+
ρsM = isempty(ϕuncc[Val(:ρsM)]) ? similar(ϕuncc[Val(:ρsM)]) : ϕuncc[Val(:ρsM)] # required by zygote
13+
# cholesky factor of the correlation: diag(UM' * UM) .== 1
14+
# coefficients ρsM can be larger than 1, still yielding correlations <1 in UM' * UM
15+
UMs, rangesM = transformU_blocks_cholesky1(ρsM, cor_ends.M)
16+
cf = ϕuncc[Val(:coef_logσ2_ζMs)]
17+
logσ2_logMs = vec(cf[1, :] .+ cf[2, :] .* ζMs)
18+
logσ2_ζP = vec(CA.getdata(ϕuncc[Val(:logσ2_ζP)]))
19+
# CUDA cannot multiply BlockDiagonal * Diagonal, construct already those blocks
20+
σMs = reshape(exp.(logσ2_logMs ./ 2), n_θM, :)
21+
σP = exp.(logσ2_ζP ./ 2)
22+
# create random numbers from U diag(σ) z = U (σ .* z)
23+
# for each block separately
24+
#σzMs = σMs .* reshape(zMs, (n_θM, n_batch, n_MC))
25+
#Ui, ri = first(zip(UMs, rangesM))
26+
zMs_subjects = reshape(zMs, (n_MC, n_θM, n_batch))
27+
#σM, zM = first(zip(eachcol(σMs), eachslice(zMs_subjects; dims=3)))
28+
cat3 = (x,y) -> cat(x,y,dims=3)
29+
# map across subjects (n_batch)
30+
#ζMs_vec = map(eachcol(σMs), eachslice(zMs_subjects; dims=3)) do σM, zM
31+
fBlock = let UMs = UMs, rangesM = collect(rangesM) # without collect, type unstable
32+
function fBlock_inner(σM, zM)
33+
mapreduce(vcat, UMs, rangesM) do Ui, ri # n_θM, n_MC
34+
ri::UnitRange{Int}
35+
#(zM[:,ri]' * Ui * diagm(σM[ri]))'
36+
diagm(σM[ri]) * Ui' * zM[:, ri]'
37+
end
38+
end
39+
end
40+
ζMs1 = ChainRulesCore.@ignore_derivatives fBlock(σMs[:,1], zMs_subjects[:,:,1])
41+
#TB = Base.infer_return_type(fBlock, (typeof(σMs[:,1]), typeof(zMs_subjects[:,:,1])))
42+
#ζMs_vec = map(fBlock, eachcol(σMs[:,2:end]), eachslice(zMs_subjects[:,:,2:end]; dims=3), init = ζMs1)
43+
ζMs_vec = map((σM, zM) -> fBlock(σM, zM)::typeof(ζMs1), eachcol(σMs), eachslice(zMs_subjects; dims=3))
44+
#zM = zMs_subjects[:,:,1]
45+
#ζMs_vec = [fBlock(σMs[:,i], zM) for i in axes(σMs, 2)]
46+
#ζMs_vec = [fBlock(σMs[:,1], zM)]
47+
#ζMs_vec = [fBlock(σMs[:,1], zM) for i in 1:n_batch]
48+
#ζMs_vec = [fBlock(σMs[:,1], zM) for i in axes(σMs, 2)]
49+
#ζMs_vec = [fBlock(σM, zM) for (σM, zM) in zip(eachcol(σMs), eachslice(zMs_subjects; dims=3))]
50+
# concatenate so that n_MC is last dimension
51+
local ζMs_parfirst_resids = stack(ζMs_vec; dims = 2 ) # n_θM, n_batch, n_MC
52+
#size(ζMs_parfirst_resids)
53+
54+
# std(ζMs_parfirst_resids[1,1,:])
55+
# std(ζMs_parfirst_resids[1,end,:])
56+
# σzMs_stacked = reshape(σzMs, (n_θM, n_batch * n_MC))
57+
# ζMs_resids_stacked = mapreduce(vcat, UMs, rangesM) do Ui, ri
58+
# #Ui * σzMs_stacked[ri, :]
59+
# Uσ = Ui * σMs[ri,:]
60+
# Uσ' * zMs[:,ri]'
61+
# diagm(σMs[ri,:]) * Ui' * zMs[:,ri]'
62+
# end
63+
# ζMs_parfirst_resids = reshape(ζMs_resids_stacked, n_θM, n_batch, n_MC)
64+
#
65+
#σzP = σP .* reshape(zP, (n_θP, n_MC))
66+
#Ui, ri = first(zip(UPs, rangesP))
67+
local ζP_resids = if isempty(ζP)
68+
# provide init of correct empty matrix type
69+
# single branch with init to mapreduce has Problems with Zygote
70+
ChainRulesCore.@ignore_derivatives ζMs_parfirst_resids[1:0,1,1:n_MC]
71+
else
72+
mapreduce(vcat, UPs, rangesP) do Ui, ri
73+
diagm(σP[ri]) * Ui' * zP[:,ri]'
74+
end
75+
end
76+
#
77+
() -> begin
78+
tmp = tmp1 = (σzP[ri,:]' * Ui)'
79+
tmp = tmp2 = (zP * (Ui * diagm(σP)))'
80+
tmp = tmp3 = (zP * Ui * diagm(σP))' # σ on wrong side of U
81+
tmp = tmp4 = diagm(σP) * Ui' * zP' # σ on wrong side of U
82+
std(tmp[2,:])
83+
end
84+
diagUσ = vcat(σP, vec(σMs))
85+
ζP_resids, ζMs_parfirst_resids, diagUσ
86+
end

0 commit comments

Comments
 (0)