@@ -579,6 +579,10 @@ def __init__(
579
579
self .p_lambda_mats = np .empty ([self .c_num_classes ,self .c_degree ,self .c_degree ])
580
580
self .p_lambda_mats_inv = np .empty ([self .c_num_classes ,self .c_degree ,self .c_degree ])
581
581
582
+ # for Viterbi
583
+ self .omega_vecs = None
584
+ self .phi_vecs = None
585
+
582
586
self .set_h0_params (
583
587
h0_eta_vec ,
584
588
h0_zeta_vecs ,
@@ -1012,6 +1016,7 @@ def update_posterior(
1012
1016
Parameters
1013
1017
----------
1014
1018
x : numpy.ndarray
1019
+ (sample_length,c_degree)-dimensional ndarray.
1015
1020
All the elements must be real number.
1016
1021
max_itr : int, optional
1017
1022
maximum number of iterations, by default 100
@@ -1395,38 +1400,138 @@ def pred_and_update(
1395
1400
)
1396
1401
return prediction
1397
1402
1398
- def estimate_latent_vars (self ,x ,loss = '' ):
1403
+ def estimate_latent_vars (self ,x ,loss = '0-1' , viterbi = True ):
1399
1404
"""Estimate latent variables under the given criterion.
1400
1405
1401
- Note that the criterion is independently applied to each data point.
1406
+ If the ``viterbi`` option is ``True``, this function estimates
1407
+ the latent variables maximizing the joint distribution.
1408
+ If ``False``, this function independently estimates the latent
1409
+ variables at each time point.
1402
1410
1403
1411
Parameters
1404
1412
----------
1413
+ x : numpy.ndarray
1414
+ (sample_length,c_degree)-dimensional ndarray.
1415
+ All the elements must be real number.
1405
1416
loss : str, optional
1406
- Loss function underlying the Bayes risk function, by default \" xxx\" .
1407
- This function supports \" xxx\" , \" xxx\" , and \" xxx\" .
1417
+ Loss function underlying the Bayes risk function, by default \" 0-1\" .
1418
+ If the ``viterbi`` option is ``True``, this function supports only \" 0-1\" .
1419
+ Otherwise, \" 0-1\" , \" squared\" , and \" KL\" are supported.
1420
+ viterbi : bool, optional
1421
+ If ``True``, this function estimates the latent variables as a sequence.
1408
1422
1409
1423
Returns
1410
1424
-------
1411
1425
estimates : numpy.ndarray
1412
1426
The estimated values under the given loss function.
1413
- If the loss function is \" xxx\" , the posterior distribution will be returned
1414
- as a numpy.ndarray whose elements consist of occurence probabilities.
1427
+ If the ``viterbi`` option is ``False`` and loss function is \" KL\" ,
1428
+ a marginalized posterior distribution will be returned as
1429
+ a numpy.ndarray whose elements consist of occurence
1430
+ probabilities for each latent variabl.
1415
1431
"""
1416
- pass
1432
+ _check .float_vecs (x ,'x' ,DataFormatError )
1433
+ if x .shape [- 1 ] != self .c_degree :
1434
+ raise (DataFormatError (
1435
+ "x.shape[-1] must be self.c_degree: "
1436
+ + f"x.shape[-1]={ x .shape [- 1 ]} , self.c_degree={ self .c_degree } " ))
1437
+ x = x .reshape (- 1 ,self .c_degree )
1438
+ self ._length = x .shape [0 ]
1439
+ z_hat = np .zeros ([self ._length ,self .c_num_classes ],dtype = int )
1440
+ self ._ln_rho = np .zeros ([self ._length ,self .c_num_classes ])
1441
+ self ._rho = np .ones ([self ._length ,self .c_num_classes ])
1417
1442
1418
- def estimate_latent_vars_and_update (self ):
1443
+ if viterbi :
1444
+ if loss == '0-1' :
1445
+ self .omega_vecs = np .zeros ([self ._length ,self .c_num_classes ])
1446
+ self .phi_vecs = np .zeros ([self ._length ,self .c_num_classes ],dtype = int )
1447
+ self ._calc_rho (x )
1448
+
1449
+ self .omega_vecs [0 ] = self ._ln_rho [0 ] + self ._ln_pi_tilde_vec
1450
+ for i in range (1 ,self ._length ):
1451
+ self .omega_vecs [i ] = self ._ln_rho [i ] + np .max (self ._ln_a_tilde_mat + self .omega_vecs [i - 1 ,:,np .newaxis ],axis = 0 )
1452
+ self .phi_vecs [i ] = np .argmax (self ._ln_a_tilde_mat + self .omega_vecs [i - 1 ,:,np .newaxis ],axis = 0 )
1453
+
1454
+ tmp_k = np .argmax (self .omega_vecs [- 1 ])
1455
+ z_hat [- 1 ,tmp_k ] = 1
1456
+ for i in range (self ._length - 2 ,- 1 ,- 1 ):
1457
+ tmp_k = self .phi_vecs [i + 1 ,tmp_k ]
1458
+ z_hat [i ,tmp_k ] = 1
1459
+ return z_hat
1460
+ else :
1461
+ raise (CriteriaError (f"loss=\" { loss } \" is unsupported. "
1462
+ + "When viterbi == True, this function supports only \" 0-1\" ." ))
1463
+
1464
+ else :
1465
+ self .alpha_vecs = np .ones ([self ._length ,self .c_num_classes ])/ self .c_num_classes
1466
+ self .beta_vecs = np .ones ([self ._length ,self .c_num_classes ])
1467
+ self .gamma_vecs = np .ones ([self ._length ,self .c_num_classes ])/ self .c_num_classes
1468
+ self .xi_mats = np .zeros ([self ._length ,self .c_num_classes ,self .c_num_classes ])/ (self .c_num_classes ** 2 )
1469
+ self ._cs = np .ones ([self ._length ])
1470
+ self ._update_q_z (x )
1471
+ if loss == "squared" or loss == "KL" :
1472
+ return self .gamma_vecs
1473
+ elif loss == "0-1" :
1474
+ return np .identity (self .c_num_classes ,dtype = int )[np .argmax (self .gamma_vecs ,axis = 1 )]
1475
+ else :
1476
+ raise (CriteriaError (f"loss=\" { loss } \" is unsupported. "
1477
+ + "When viterbi == False, This function supports \" squared\" , \" 0-1\" , and \" KL\" ." ))
1478
+
1479
+ def estimate_latent_vars_and_update (
1480
+ self ,
1481
+ x ,
1482
+ loss = "0-1" ,
1483
+ viterbi = True ,
1484
+ max_itr = 100 ,
1485
+ num_init = 10 ,
1486
+ tolerance = 1.0E-8 ,
1487
+ init_type = 'subsampling'
1488
+ ):
1419
1489
"""Estimate latent variables and update the posterior sequentially.
1420
1490
1421
1491
h0_params will be overwritten by current hn_params
1422
1492
before updating hn_params by x
1423
1493
1424
1494
Parameters
1425
1495
----------
1496
+ x : numpy.ndarray
1497
+ It must be a `c_degree`-dimensional vector
1498
+ loss : str, optional
1499
+ Loss function underlying the Bayes risk function, by default \" 0-1\" .
1500
+ If the ``viterbi`` option is ``True``, this function supports only \" 0-1\" .
1501
+ Otherwise, \" 0-1\" , \" squared\" , and \" KL\" are supported.
1502
+ viterbi : bool, optional
1503
+ If ``True``, this function estimates the latent variables as a sequence.
1504
+ max_itr : int, optional
1505
+ maximum number of iterations, by default 100
1506
+ num_init : int, optional
1507
+ number of initializations, by default 10
1508
+ tolerance : float, optional
1509
+ convergence croterion of variational lower bound, by default 1.0E-8
1510
+ init_type : str, optional
1511
+ type of initialization, by default 'random_responsibility'
1512
+ * 'random_responsibility': randomly assign responsibility to r_vecs
1513
+ * 'subsampling': for each latent class, extract a subsample whose size is int(np.sqrt(x.shape[0])).
1514
+ and use its mean and covariance matrix as an initial values of hn_m_vecs and hn_lambda_mats.
1426
1515
1427
1516
Returns
1428
1517
-------
1429
- predicted_value : numpy.ndarray
1518
+ estimates : numpy.ndarray
1430
1519
The estimated values under the given loss function.
1520
+ If the ``viterbi`` option is ``False`` and loss function is \" KL\" ,
1521
+ a marginalized posterior distribution will be returned as
1522
+ a numpy.ndarray whose elements consist of occurence
1523
+ probabilities for each latent variabl.
1431
1524
"""
1432
- pass
1525
+ _check .float_vec (x ,'x' ,DataFormatError )
1526
+ if x .shape != (self .c_degree ,):
1527
+ raise (DataFormatError (f"x must be a 1-dimensional float array whose size is c_degree: { self .c_degree } ." ))
1528
+ z_hat = self .estimate_latent_vars (x ,loss = loss ,viterbi = viterbi )
1529
+ self .overwrite_h0_params ()
1530
+ self .update_posterior (
1531
+ x ,
1532
+ max_itr = max_itr ,
1533
+ num_init = num_init ,
1534
+ tolerance = tolerance ,
1535
+ init_type = init_type
1536
+ )
1537
+ return z_hat
0 commit comments