Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
bob.learn.em
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
bob
bob.learn.em
Commits
31ae6f70
Commit
31ae6f70
authored
2 years ago
by
Yannick DAYER
Browse files
Options
Downloads
Patches
Plain Diff
IVector test for machine with update_sigma
parent
d3c33d84
No related branches found
No related tags found
1 merge request
!60
Port of I-Vector to python
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
bob/learn/em/ivector.py
+31
-37
31 additions, 37 deletions
bob/learn/em/ivector.py
bob/learn/em/test/test_ivector.py
+113
-124
113 additions, 124 deletions
bob/learn/em/test/test_ivector.py
with
144 additions
and
161 deletions
bob/learn/em/ivector.py
+
31
−
37
View file @
31ae6f70
...
...
@@ -186,27 +186,6 @@ def compute_tt_sigma_inv_fnorm(
return
output
def
forward
(
ubm_means
:
np
.
ndarray
,
stats
:
GMMStats
,
T
:
np
.
ndarray
,
sigma
:
np
.
ndarray
):
# void bob::learn::em::IVectorMachine::forward_(const bob::learn::em::GMMStats& gs,
# blitz::Array<double,1>& ivector) const
# {
# // Computes \f$(Id + \sum_{c=1}^{C} N_{i,j,c} T^{T} \Sigma_{c}^{-1} T)\f$
# computeIdTtSigmaInvT(gs, m_tmp_tt);
# // Computes \f$T^{T} \Sigma^{-1} \sum_{c=1}^{C} (F_c - N_c ubmmean_{c})\f$
# computeTtSigmaInvFnorm(gs, m_tmp_t1);
# // Solves m_tmp_tt.ivector = m_tmp_t1
# bob::math::linsolve(m_tmp_tt, m_tmp_t1, ivector);
# }
return
np
.
linalg
.
solve
(
compute_id_tt_sigma_inv_t
(
stats
,
T
,
sigma
),
compute_tt_sigma_inv_fnorm
(
ubm_means
,
stats
,
T
,
sigma
),
)
class
IVectorMachine
(
BaseEstimator
):
"""
Trains and projects data using I-Vector.
...
...
@@ -397,26 +376,39 @@ class IVectorMachine(BaseEstimator):
logger
.
info
(
f
"
Did not converge after
{
step
+
1
}
steps.
"
)
return
self
def
project
(
self
,
stats
:
GMMStats
)
->
IVectorStats
:
if
not
isinstance
(
stats
,
GMMStats
):
return
[
self
.
project
(
s
)
for
s
in
stats
]
# TODO yes?
return
forward
(
self
.
ubm
.
means
,
stats
,
self
.
T
,
self
.
sigma
)
def
project
(
self
,
stats
:
GMMStats
)
->
np
.
ndarray
:
"""
Projects the GMMStats on the IVectorMachine.
This takes data already projected onto the UBM.
**Returns:**
The IVector of the input stats.
"""
return
np
.
linalg
.
solve
(
compute_id_tt_sigma_inv_t
(
stats
,
self
.
T
,
self
.
sigma
),
compute_tt_sigma_inv_fnorm
(
self
.
ubm
.
means
,
stats
,
self
.
T
,
self
.
sigma
),
)
def
transform
(
self
,
data
:
np
.
ndarray
)
->
List
[
IVectorStats
]:
def
transform
(
self
,
data
:
List
[
np
.
ndarray
]
)
->
List
[
np
.
ndarray
]:
"""
Transforms the data using the trained IVectorMachine.
Parameters
----------
data : np.ndarray
The data to transform.
This takes MFCC data, will project them onto the ubm, and compute the IVector
statistics.
Returns
-------
np.ndarray
The transformed data.
**Parameters:**
data
The data (MFCC features) to transform. Arrays of shape (n_samples, n_features).
**Returns:**
The IVector for each sample. Shape: (dim_t,)
"""
stats
=
self
.
project
(
self
.
ubm
.
acc_stats
(
data
))
return
stats
.
t
return
[
self
.
project
(
self
.
ubm
.
acc_stats
(
d
))
for
d
in
data
]
def
enroll
(
self
,
stats
:
List
[
GMMStats
])
->
IVectorStats
:
"""
Enrolls a new speaker.
...
...
@@ -433,7 +425,9 @@ class IVectorMachine(BaseEstimator):
"""
return
self
.
project
(
stats
)
def
score
(
self
,
model
:
IVectorStats
,
probes
:
List
[
GMMStats
])
->
List
[
float
]:
def
score
(
self
,
model
:
IVectorStats
,
probes
:
List
[
np
.
ndarray
]
)
->
List
[
float
]:
return
linear_scoring
(
model
,
ubm
=
self
.
ubm
,
...
...
This diff is collapsed.
Click to expand it.
bob/learn/em/test/test_ivector.py
+
113
−
124
View file @
31ae6f70
...
...
@@ -2,8 +2,9 @@
# @author: Yannick Dayer <yannick.dayer@idiap.ch>
# @date: Fri 06 May 2022 12:59:21 UTC+02
import
copy
import
numpy
as
np
import
pytest
from
bob.learn.em
import
GMMMachine
,
GMMStats
,
IVectorMachine
...
...
@@ -58,29 +59,24 @@ def test_ivector_machine_projection():
def
test_ivector_machine_transformer
():
dim_t
=
2
ubm
=
GMMMachine
(
n_gaussians
=
2
)
ubm
.
means
=
np
.
array
([[
1
,
7
,
4
],
[
4
,
5
,
3
]],
dtype
=
float
)
ubm
.
variances
=
np
.
array
([[
0.5
,
1.0
,
1.5
],
[
1.0
,
1.5
,
2.0
]],
dtype
=
float
)
machine
=
IVectorMachine
(
ubm
=
ubm
,
dim_t
=
2
)
machine
=
IVectorMachine
(
ubm
=
ubm
,
dim_t
=
dim_t
)
machine
.
T
=
np
.
array
(
[[[
1
,
2
],
[
4
,
1
],
[
0
,
3
]],
[[
5
,
8
],
[
7
,
10
],
[
11
,
1
]]],
dtype
=
float
)
assert
hasattr
(
machine
,
"
fit
"
)
assert
hasattr
(
machine
,
"
transform
"
)
assert
hasattr
(
machine
,
"
enroll
"
)
assert
hasattr
(
machine
,
"
score
"
)
transformed
=
machine
.
transform
([
np
.
ndarray
([
1
,
2
,
3
])])[
0
]
assert
isinstance
(
transformed
,
IVectorMachine
)
nij_sigma_wij2_ref
=
np
.
array
([[
0.5
,
1.0
,
1.5
],
[
1.0
,
1.5
,
2.0
]])
# TODO
nij_ref
=
np
.
array
([[
1
,
2
,
3
],
[
4
,
5
,
6
]])
fnorm_sigma_wij_ref
=
np
.
array
([[
0.5
,
1.0
,
1.5
],
[
1.0
,
1.5
,
2.0
]])
# TODO
snormij_ref
=
np
.
array
([[
1
,
2
,
3
],
[
4
,
5
,
6
]])
np
.
testing
.
assert_almost_equal
(
transformed
.
nij_sigma_wij2
,
nij_sigma_wij2_ref
)
np
.
testing
.
assert_almost_equal
(
transformed
.
nij
,
nij_ref
)
np
.
testing
.
assert_almost_equal
(
transformed
.
fnorm_sigma_wij
,
fnorm_sigma_wij_ref
transformed
=
machine
.
transform
([
np
.
array
([
1
,
2
,
3
])])[
0
]
assert
isinstance
(
transformed
,
np
.
ndarray
)
np
.
testing
.
assert_array_equal
(
transformed
,
np
.
array
([
-
0.04213415
,
0.21463343
])
)
np
.
testing
.
assert_almost_equal
(
transformed
.
snormij
,
snormij_ref
)
def
test_ivector_machine_training
():
...
...
@@ -324,6 +320,7 @@ def test_trainer_nosigma():
data
=
[
gs1
,
gs2
]
# Reference values TODO: load from hdf5 file
acc_Nij_Sigma_wij2_ref1
=
np
.
array
(
[
[[
0.03202305
,
-
0.02947769
],
[
-
0.02947769
,
0.0561132
]],
...
...
@@ -411,7 +408,7 @@ def test_trainer_nosigma():
assert
acc_Nij_Sigma_wij2_ref1
.
shape
==
(
2
,
2
,
2
)
assert
acc_Nij_Sigma_wij2_ref2
.
shape
==
(
2
,
2
,
2
)
#
Python
implementation
#
Reference
implementation
# Machine
m
=
IVectorMachine
(
ubm
,
dim_t
=
2
)
t
=
np
.
array
([[[
1.0
,
2
],
[
4
,
1
],
[
0
,
3
]],
[[
5
,
8
],
[
7
,
10
],
[
11
,
1
]]])
...
...
@@ -444,16 +441,15 @@ def test_trainer_nosigma():
# New implementation
# Machine
m
=
IVectorMachine
(
ubm
,
dim_t
=
2
)
m
=
IVectorMachine
(
ubm
,
dim_t
=
2
,
update_sigma
=
False
)
t
=
np
.
array
([[[
1.0
,
2
],
[
4
,
1
],
[
0
,
3
]],
[[
5
,
8
],
[
7
,
10
],
[
11
,
1
]]])
sigma
=
np
.
array
([[
1.0
,
2.0
,
1.0
],
[
3.0
,
2.0
,
4.0
]])
# Initialization
m
.
T
=
t
m
.
sigma
=
sigma
m
.
sigma
=
copy
.
deepcopy
(
sigma
)
stats
=
None
for
it
in
range
(
2
):
print
(
"
Iteration:
"
,
it
)
# E-Step
stats
=
m
.
e_step
(
data
)
np
.
testing
.
assert_almost_equal
(
...
...
@@ -470,10 +466,7 @@ def test_trainer_nosigma():
# M-Step
m
.
m_step
(
stats
)
np
.
testing
.
assert_almost_equal
(
t_ref
[
it
],
m
.
T
,
decimal
=
5
)
np
.
testing
.
assert_equal
(
sigma
,
m
.
sigma
)
# sigma is not updated
# testing exceptions
pytest
.
raises
(
RuntimeError
,
m
.
e_step
,
[
1
,
2
,
2
])
np
.
testing
.
assert_equal
(
sigma
,
m
.
sigma
)
# sigma should not be updated
def
test_trainer_update_sigma
():
...
...
@@ -512,90 +505,90 @@ def test_trainer_update_sigma():
data
=
[
gs1
,
gs2
]
# Reference values
acc_Nij_Sigma_wij2_ref1
=
{
0
:
np
.
array
([[
0.03202305
,
-
0.02947769
],
[
-
0.02947769
,
0.0561132
]]),
1
:
np
.
array
([[
0.07953279
,
-
0.07829414
],
[
-
0.07829414
,
0.13814242
]]),
}
acc_Fnorm_Sigma_wij_ref1
=
{
0
:
np
.
array
(
# Reference values TODO: load from hdf5 file
acc_Nij_Sigma_wij2_ref1
=
np
.
array
(
[
[[
0.03202305
,
-
0.02947769
],
[
-
0.02947769
,
0.0561132
]],
[[
0.07953279
,
-
0.07829414
],
[
-
0.07829414
,
0.13814242
]],
]
)
acc_Fnorm_Sigma_wij_ref1
=
np
.
array
(
[
[
[
-
0.29622691
,
0.61411796
],
[
0.09391764
,
-
0.27955961
],
[
-
0.39014455
,
0.89367757
],
]
),
1
:
np
.
array
(
],
[
[
0.04695882
,
-
0.13977981
],
[
-
0.05718673
,
0.24159665
],
[
-
0.17098161
,
0.47326585
],
]
),
}
acc_Snorm_ref1
=
np
.
array
([
16.6
,
22.4
,
16.6
,
61.4
,
55.0
,
97.4
])
]
,
]
)
acc_Snorm_ref1
=
np
.
array
([
[
16.6
,
22.4
,
16.6
]
,
[
61.4
,
55.0
,
97.4
]
]
)
N_ref1
=
np
.
array
([
0.6
,
1.4
])
t_ref1
=
np
.
array
(
[
[
1.59543739
,
11.78239235
],
[
-
3.20130371
,
-
6.66379081
],
[
4.79674111
,
18.44618316
],
[
-
0.91765407
,
-
1.5319461
],
[
2.26805901
,
3.03434944
],
[
2.76600031
,
4.9935962
],
[
[
1.59543739
,
11.78239235
],
[
-
3.20130371
,
-
6.66379081
],
[
4.79674111
,
18.44618316
],
],
[
[
-
0.91765407
,
-
1.5319461
],
[
2.26805901
,
3.03434944
],
[
2.76600031
,
4.9935962
],
],
]
)
sigma_ref1
=
np
.
array
(
[
16.39472121
,
34.72955353
,
3.3108037
,
43.73496916
,
38.85472445
,
68.22116903
,
[
16.39472121
,
34.72955353
,
3.3108037
],
[
43.73496916
,
38.85472445
,
68.22116903
],
]
)
acc_Nij_Sigma_wij2_ref2
=
{
0
:
np
.
array
([[
0.50807426
,
-
0.11907756
],
[
-
0.11907756
,
0.12336544
]]),
1
:
np
.
array
([[
1.18602399
,
-
0.2835859
],
[
-
0.2835859
,
0.39440498
]]),
}
acc_Fnorm_Sigma_wij_ref2
=
{
0
:
np
.
array
(
acc_Nij_Sigma_wij2_ref2
=
np
.
array
(
[
[[
0.50807426
,
-
0.11907756
],
[
-
0.11907756
,
0.12336544
]],
[[
1.18602399
,
-
0.2835859
],
[
-
0.2835859
,
0.39440498
]],
]
)
acc_Fnorm_Sigma_wij_ref2
=
np
.
array
(
[
[
[
0.07221453
,
1.1189786
],
[
-
0.08681275
,
-
0.35396112
],
[
0.15902728
,
1.47293972
],
]
),
1
:
np
.
array
(
],
[
[
-
0.04340637
,
-
0.17698056
],
[
0.10662127
,
0.21484933
],
[
0.13116645
,
0.64474271
],
]
),
}
acc_Snorm_ref2
=
np
.
array
([
16.6
,
22.4
,
16.6
,
61.4
,
55.0
,
97.4
])
]
,
]
)
acc_Snorm_ref2
=
np
.
array
([
[
16.6
,
22.4
,
16.6
]
,
[
61.4
,
55.0
,
97.4
]
]
)
N_ref2
=
np
.
array
([
0.6
,
1.4
])
t_ref2
=
np
.
array
(
[
[
2.93105054
,
11.89961223
],
[
-
1.08988119
,
-
3.92120757
],
[
4.02093173
,
15.82081981
],
[
-
0.17376634
,
-
0.57366984
],
[
0.26585634
,
0.73589952
],
[
0.60557877
,
2.07014704
],
[
[
2.93105054
,
11.89961223
],
[
-
1.08988119
,
-
3.92120757
],
[
4.02093173
,
15.82081981
],
],
[
[
-
0.17376634
,
-
0.57366984
],
[
0.26585634
,
0.73589952
],
[
0.60557877
,
2.07014704
],
],
]
)
sigma_ref2
=
np
.
array
(
[
5.12154025e00
,
3.48623823e01
,
1.00000000e-05
,
4.37792350e01
,
3.91525332e01
,
6.85613258e01
,
[
5.12154025e00
,
3.48623823e01
,
1.00000000e-05
],
[
4.37792350e01
,
3.91525332e01
,
6.85613258e01
],
]
)
...
...
@@ -609,70 +602,66 @@ def test_trainer_update_sigma():
t_ref
=
[
t_ref1
,
t_ref2
]
sigma_ref
=
[
sigma_ref1
,
sigma_ref2
]
#
Python
implementation
#
Reference
implementation
# Machine
m
=
IVectorMachine
(
ubm
,
2
)
t
=
np
.
array
([[[
1.0
,
2
],
[
4
,
1
],
[
0
,
3
]],
[[
5
,
8
],
[
7
,
10
],
[
11
,
1
]]])
sigma
=
np
.
array
([
1.0
,
2.0
,
1.0
,
3.0
,
2.0
,
4.0
])
sigma
=
np
.
array
([
[
1.0
,
2.0
,
1.0
]
,
[
3.0
,
2.0
,
4.0
]
]
)
# Initialization
trainer
=
IVectorTrainerPy
(
sigma_update
=
True
)
trainer
.
initialize
(
m
,
data
)
m
.
t
=
t
m
.
T
=
t
m
.
sigma
=
sigma
for
it
in
range
(
2
):
# E-Step
trainer
.
e_step
(
m
,
data
)
for
k
in
acc_Nij_Sigma_wij2_ref
[
it
]:
assert
np
.
allclose
(
acc_Nij_Sigma_wij2_ref
[
it
][
k
],
trainer
.
m_acc_Nij_Sigma_wij2
[
k
],
1e-5
,
)
for
k
in
acc_Fnorm_Sigma_wij_ref
[
it
]:
assert
np
.
allclose
(
acc_Fnorm_Sigma_wij_ref
[
it
][
k
],
trainer
.
m_acc_Fnorm_Sigma_wij
[
k
],
1e-5
,
)
assert
np
.
allclose
(
acc_Snorm_ref
[
it
],
trainer
.
m_acc_Snorm
,
1e-5
)
assert
np
.
allclose
(
N_ref
[
it
],
trainer
.
m_N
,
1e-5
)
np
.
testing
.
assert_almost_equal
(
acc_Nij_Sigma_wij2_ref
[
it
],
trainer
.
m_acc_Nij_Sigma_wij2
,
decimal
=
5
)
np
.
testing
.
assert_almost_equal
(
acc_Fnorm_Sigma_wij_ref
[
it
],
trainer
.
m_acc_Fnorm_Sigma_wij
,
decimal
=
5
,
)
np
.
testing
.
assert_almost_equal
(
acc_Snorm_ref
[
it
],
trainer
.
m_acc_Snorm
,
decimal
=
5
)
np
.
testing
.
assert_almost_equal
(
N_ref
[
it
],
trainer
.
m_N
,
decimal
=
5
)
# M-Step
trainer
.
m_step
(
m
,
data
)
assert
np
.
allclose
(
t_ref
[
it
],
m
.
t
,
1e-
5
)
assert
np
.
allclose
(
sigma_ref
[
it
],
m
.
sigma
,
1e-
5
)
trainer
.
m_step
(
m
)
np
.
testing
.
assert_almost_equal
(
t_ref
[
it
],
m
.
T
,
decimal
=
5
)
np
.
testing
.
assert_almost_equal
(
sigma_ref
[
it
],
m
.
sigma
,
decimal
=
5
)
#
C++
implementation
TODO
#
New
implementation
# Machine
m
=
IVectorMachine
(
ubm
,
2
)
m
.
variance_threshold
=
1e-5
m
=
IVectorMachine
(
ubm
,
dim_t
=
2
,
variance_floor
=
1e-5
)
# update_sigma is True by default
# Initialization
# trainer = IVectorTrainer(update_sigma=True)
# trainer.initialize(m)
# m.t = t
# m.sigma = sigma
# for it in range(2):
# # E-Step
# trainer.e_step(m, data)
# for k in acc_Nij_Sigma_wij2_ref[it]:
# assert np.allclose(
# acc_Nij_Sigma_wij2_ref[it][k], trainer.acc_nij_wij2[k], 1e-5
# )
# for k in acc_Fnorm_Sigma_wij_ref[it]:
# assert np.allclose(
# acc_Fnorm_Sigma_wij_ref[it][k], trainer.acc_fnormij_wij[k], 1e-5
# )
# assert np.allclose(
# acc_Snorm_ref[it].reshape(dim_c, dim_d), trainer.acc_snormij, 1e-5
# )
# assert np.allclose(N_ref[it], trainer.acc_nij, 1e-5)
# # M-Step
# trainer.m_step(m)
# assert np.allclose(t_ref[it], m.t, 1e-5)
# assert np.allclose(sigma_ref[it], m.sigma, 1e-5)
# Manual Initialization
m
.
T
=
t
m
.
sigma
=
sigma
for
it
in
range
(
2
):
# E-Step
stats
=
m
.
e_step
(
data
)
np
.
testing
.
assert_almost_equal
(
acc_Nij_Sigma_wij2_ref
[
it
],
stats
.
nij_sigma_wij2
,
decimal
=
5
)
np
.
testing
.
assert_almost_equal
(
acc_Fnorm_Sigma_wij_ref
[
it
],
stats
.
fnorm_sigma_wij
,
decimal
=
5
)
np
.
testing
.
assert_almost_equal
(
acc_Snorm_ref
[
it
],
stats
.
snormij
,
decimal
=
5
)
np
.
testing
.
assert_almost_equal
(
N_ref
[
it
],
stats
.
nij
,
decimal
=
5
)
# M-Step
m
.
m_step
(
stats
)
np
.
testing
.
assert_almost_equal
(
t_ref
[
it
],
m
.
T
,
decimal
=
5
)
np
.
testing
.
assert_almost_equal
(
sigma_ref
[
it
],
m
.
sigma
,
decimal
=
5
)
def
test_trainer_update_sigma_parallel
():
...
...
@@ -814,8 +803,8 @@ def test_trainer_update_sigma_parallel():
# C++ implementation TODO
# Machine
serial_m
=
IVectorMachine
(
ubm
,
2
)
serial_m
.
variance_threshold
=
1e-5
#
serial_m = IVectorMachine(ubm, 2)
#
serial_m.variance_threshold = 1e-5
# SERIAL TRAINER
# serial_trainer = IVectorTrainer(update_sigma=True)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment