dcekit 2.15.1__tar.gz → 2.17.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {dcekit-2.15.1/dcekit.egg-info → dcekit-2.17.1}/PKG-INFO +1 -1
  2. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/generative_model/__init__.py +2 -0
  3. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/generative_model/gmr.py +109 -4
  4. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/generative_model/gtm.py +8 -7
  5. dcekit-2.17.1/dcekit/generative_model/ssgmr_xgmm.py +696 -0
  6. dcekit-2.17.1/dcekit/generative_model/ssgmr_xgmm_xma.py +65 -0
  7. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/generative_model/vbgmr.py +2 -2
  8. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/variable_selection/basic_variable_selection.py +1 -1
  9. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/variable_selection/variable_importance.py +12 -3
  10. {dcekit-2.15.1 → dcekit-2.17.1/dcekit.egg-info}/PKG-INFO +1 -1
  11. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit.egg-info/SOURCES.txt +2 -0
  12. {dcekit-2.15.1 → dcekit-2.17.1}/setup.py +1 -1
  13. {dcekit-2.15.1 → dcekit-2.17.1}/LICENSE +0 -0
  14. {dcekit-2.15.1 → dcekit-2.17.1}/LICENSE.txt +0 -0
  15. {dcekit-2.15.1 → dcekit-2.17.1}/MANIFEST.in +0 -0
  16. {dcekit-2.15.1 → dcekit-2.17.1}/README.md +0 -0
  17. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/__init__.py +0 -0
  18. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/design_of_exmeriments/__init__.py +0 -0
  19. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/design_of_exmeriments/bayesian_optimization.py +0 -0
  20. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/just_in_time/__init__.py +0 -0
  21. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/just_in_time/jitpls.py +0 -0
  22. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/just_in_time/lwpls.py +0 -0
  23. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/learning/__init__.py +0 -0
  24. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/learning/ensemble_learning.py +0 -0
  25. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/learning/semi_supervised_learning.py +0 -0
  26. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/learning/transfer_learning.py +0 -0
  27. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/optimization/__init__.py +0 -0
  28. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/optimization/fast_opt_svr_hyperparams.py +0 -0
  29. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/optimization/iot.py +0 -0
  30. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/optimization/opt_dnn_hyperparams.py +0 -0
  31. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/optimization/opt_dnn_hyperparams_class.py +0 -0
  32. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/sampling/__init__.py +0 -0
  33. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/sampling/kennard_stone.py +0 -0
  34. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/validation/__init__.py +0 -0
  35. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/validation/applicability_domain.py +0 -0
  36. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/validation/metrics.py +0 -0
  37. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/validation/validation.py +0 -0
  38. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/variable_selection/__init__.py +0 -0
  39. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit/variable_selection/local_interpretation.py +0 -0
  40. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit.egg-info/dependency_links.txt +0 -0
  41. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit.egg-info/requires.txt +0 -0
  42. {dcekit-2.15.1 → dcekit-2.17.1}/dcekit.egg-info/top_level.txt +0 -0
  43. {dcekit-2.15.1 → dcekit-2.17.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dcekit
3
- Version: 2.15.1
3
+ Version: 2.17.1
4
4
  Summary: Data Chemical Engineering toolkit
5
5
  Home-page: https://github.com/hkaneko1985/dcekit/
6
6
  Author: Hiromasa Kaneko
@@ -7,3 +7,5 @@
7
7
  from .gmr import GMR
8
8
  from .gtm import GTM
9
9
  from .vbgmr import VBGMR
10
+ from .ssgmr_xgmm import SSGMRXGMM
11
+ from .ssgmr_xgmm_xma import SSGMRXGMMXMA
@@ -24,8 +24,10 @@ warnings.simplefilter('ignore')
24
24
  class GMR(GaussianMixture):
25
25
 
26
26
  def __init__(self, n_components=1, covariance_type='full', rep='mean',
27
+ weights_init=None, means_init=None, precisions_init=None,
27
28
  max_iter=100, random_state=None, display_flag=False):
28
29
  super(self.__class__, self).__init__(n_components=n_components, covariance_type=covariance_type,
30
+ weights_init=weights_init, means_init=means_init, precisions_init=precisions_init,
29
31
  max_iter=max_iter, random_state=random_state)
30
32
 
31
33
  self.rep = rep
@@ -123,9 +125,9 @@ class GMR(GaussianMixture):
123
125
  """
124
126
 
125
127
  mode_of_estimated_mean, weighted_estimated_mean, _, _ = self.predict(dataset, numbers_of_input_variables, numbers_of_output_variables)
126
- if self.rep == 'mean':
128
+ if self.rep == 'mode':
127
129
  values = mode_of_estimated_mean.copy()
128
- elif self.rep == 'mode':
130
+ elif self.rep == 'mean':
129
131
  values = weighted_estimated_mean.copy()
130
132
  return values
131
133
 
@@ -301,7 +303,6 @@ class GMR(GaussianMixture):
301
303
  Parameters
302
304
  ----------
303
305
  gmm_model: mixture.gaussian_mixture.GaussianMixture
304
- GMM model constructed using scikit-learn
305
306
  dataset: numpy.array or pandas.DataFrame
306
307
  (autoscaled) m x n matrix of dataset of training data or test data,
307
308
  m is the number of sammples and
@@ -363,6 +364,104 @@ class GMR(GaussianMixture):
363
364
  l x m matrix of weights,
364
365
  """
365
366
 
367
+ dataset = np.array(dataset)
368
+ if dataset.ndim == 0:
369
+ dataset = np.reshape(dataset, (1, 1))
370
+ elif dataset.ndim == 1:
371
+ dataset = np.reshape(dataset, (1, dataset.shape[0]))
372
+
373
+ input_means = self.means_[:, numbers_of_input_variables]
374
+ output_means = self.means_[:, numbers_of_output_variables]
375
+
376
+ if self.covariance_type == 'full':
377
+ all_covariances = self.covariances_
378
+ elif self.covariance_type == 'diag':
379
+ all_covariances = np.empty(
380
+ [self.n_components, self.covariances_.shape[1], self.covariances_.shape[1]])
381
+ for component_number in range(self.n_components):
382
+ all_covariances[component_number, :, :] = np.diag(self.covariances_[component_number, :])
383
+ elif self.covariance_type == 'tied':
384
+ all_covariances = np.tile(self.covariances_, (self.n_components, 1, 1))
385
+ elif self.covariance_type == 'spherical':
386
+ all_covariances = np.empty([self.n_components, self.means_.shape[1], self.means_.shape[1]])
387
+ for component_number in range(self.n_components):
388
+ all_covariances[component_number, :, :] = np.diag(
389
+ self.covariances_[component_number] * np.ones(self.means_.shape[1]))
390
+
391
+ estimated_means = np.zeros([self.n_components, dataset.shape[0], len(numbers_of_output_variables)])
392
+ estimated_covariances = np.zeros([self.n_components, len(numbers_of_output_variables), len(numbers_of_output_variables)])
393
+ weights = np.zeros([self.n_components, dataset.shape[0]])
394
+ # print(all_covariances.shape[2], len(numbers_of_input_variables), len(numbers_of_output_variables))
395
+ if all_covariances.shape[2] == len(numbers_of_input_variables) + len(numbers_of_output_variables):
396
+ input_output_covariances = all_covariances[:, numbers_of_input_variables, :]
397
+ input_covariances = input_output_covariances[:, :, numbers_of_input_variables]
398
+ input_output_covariances = input_output_covariances[:, :, numbers_of_output_variables]
399
+ output_input_covariances = all_covariances[:, numbers_of_output_variables, :]
400
+ output_covariances = output_input_covariances[:, :, numbers_of_output_variables]
401
+ output_input_covariances = output_input_covariances[:, :, numbers_of_input_variables]
402
+
403
+ # estimated means and weights for all components
404
+ for component_number in range(self.n_components):
405
+ estimated_means[component_number, :, :] = output_means[component_number, :] + (
406
+ dataset - input_means[component_number, :]).dot(
407
+ np.linalg.inv(input_covariances[component_number, :, :])).dot(
408
+ input_output_covariances[component_number, :, :])
409
+ estimated_covariances[component_number, :, :] = output_covariances[component_number, :, :] - output_input_covariances[component_number, :, :].dot(
410
+ np.linalg.inv(input_covariances[component_number, :, :])).dot(input_output_covariances[component_number, :, :])
411
+ try:
412
+ weights[component_number, :] = self.weights_[component_number] * \
413
+ multivariate_normal.pdf(dataset,
414
+ input_means[component_number, :],
415
+ input_covariances[component_number, :, :])
416
+ except:
417
+ print('assignment of weights is failed, and zero is assigned')
418
+
419
+ if len(np.where(weights.sum(axis=0)==0)[0]) > 0:
420
+ weights = np.ones(weights.shape)
421
+ if np.isnan(weights.sum(axis=0)).any():
422
+ weights = np.ones(weights.shape)
423
+ if np.isinf(weights.sum(axis=0)).any():
424
+ weights = np.ones(weights.shape)
425
+ weights = weights / weights.sum(axis=0)
426
+
427
+ return estimated_means, estimated_covariances, weights
428
+
429
+ def predict_mog_pdf(self, dataset, numbers_of_input_variables, numbers_of_output_variables):
430
+ """
431
+ Gaussian Mixture Regression (GMR) based on Gaussian Mixture Model (GMM)
432
+
433
+ Predict values of variables for forward analysis (regression) and inverse analysis. Predition results are given as mixture of Gaussians
434
+
435
+ Parameters
436
+ ----------
437
+ gmm_model: mixture.gaussian_mixture.GaussianMixture
438
+ GMM model constructed using scikit-learn
439
+ dataset: numpy.array or pandas.DataFrame
440
+ (autoscaled) m x n matrix of dataset of training data or test data,
441
+ m is the number of sammples and
442
+ n is the number of input variables
443
+ When this is X-variables, it is forward analysis (regression) and
444
+ when this is Y-variables, it is inverse analysis
445
+ numbers_of_input_variables: list
446
+ vector of numbers of input variables
447
+ When this is numbers of X-variables, it is forward analysis (regression) and
448
+ when this is numbers of Y-variables, it is inverse analysis
449
+ numbers_of_output_variables: list
450
+ vector of numbers of output variables
451
+ When this is numbers of Y-variables, it is forward analysis (regression) and
452
+ when this is numbers of X-variables, it is inverse analysis
453
+
454
+ Returns
455
+ -------
456
+ estimated_means : numpy.array
457
+ (autoscaled) l x m x k matrix of output variables estimated for all components,
458
+ k is the number of output variables
459
+ estimated_covariances : numpy.array
460
+ (autoscaled) l x k x k variance-covariance matrix of output variables estimated for all components,
461
+ weights : numpy.array
462
+ l x m matrix of weights,
463
+ """
464
+
366
465
  dataset = np.array(dataset)
367
466
  if dataset.ndim == 0:
368
467
  dataset = np.reshape(dataset, (1, 1))
@@ -390,6 +489,9 @@ class GMR(GaussianMixture):
390
489
  estimated_means = np.zeros([self.n_components, dataset.shape[0], len(numbers_of_output_variables)])
391
490
  estimated_covariances = np.zeros([self.n_components, len(numbers_of_output_variables), len(numbers_of_output_variables)])
392
491
  weights = np.zeros([self.n_components, dataset.shape[0]])
492
+ pdfs = np.zeros([self.n_components, dataset.shape[0]])
493
+ logpdfs = np.zeros([self.n_components, dataset.shape[0]])
494
+
393
495
  # print(all_covariances.shape[2], len(numbers_of_input_variables), len(numbers_of_output_variables))
394
496
  if all_covariances.shape[2] == len(numbers_of_input_variables) + len(numbers_of_output_variables):
395
497
  input_output_covariances = all_covariances[:, numbers_of_input_variables, :]
@@ -412,6 +514,8 @@ class GMR(GaussianMixture):
412
514
  multivariate_normal.pdf(dataset,
413
515
  input_means[component_number, :],
414
516
  input_covariances[component_number, :, :])
517
+ pdfs[component_number, :] = multivariate_normal.pdf(dataset, input_means[component_number, :], input_covariances[component_number, :, :])
518
+ logpdfs[component_number, :] = multivariate_normal.logpdf(dataset, input_means[component_number, :], input_covariances[component_number, :, :])
415
519
  except:
416
520
  print('assignment of weights is failed, and zero is assigned')
417
521
 
@@ -422,8 +526,9 @@ class GMR(GaussianMixture):
422
526
  if np.isinf(weights.sum(axis=0)).any():
423
527
  weights = np.ones(weights.shape)
424
528
  weights = weights / weights.sum(axis=0)
529
+ ioe = -logsumexp(logpdfs, axis=0, b=weights)
425
530
 
426
- return estimated_means, estimated_covariances, weights
531
+ return estimated_means, estimated_covariances, weights, pdfs, logpdfs, ioe
427
532
 
428
533
  def cv_opt(self, dataset, numbers_of_input_variables, numbers_of_output_variables, covariance_types,
429
534
  numbers_of_components, fold_number):
@@ -627,7 +627,7 @@ class GTM:
627
627
  if bo_iter == 0: # 最初の試行ではD最適基準を計算
628
628
  # D最適基準の計算
629
629
  param_std = params_df.std(axis=0, ddof=1)
630
- param_std[np.where(param_std == 0)[0]] = 1
630
+ param_std.iloc[np.where(param_std == 0)[0]] = 1
631
631
  autoscaled_params_df = (params_df - params_df.mean(axis=0)) / param_std # 計算のために標準化
632
632
 
633
633
  all_indexes = list(range(autoscaled_params_df.shape[0])) # indexを取得
@@ -748,7 +748,7 @@ class GTM:
748
748
  for bo_sample_number in range(bo_number_of_selecting_samples):
749
749
  # オートスケーリング
750
750
  x_std = bo_x_data.std(axis=0, ddof=1)
751
- x_std[np.where(x_std == 0)[0]] = 1
751
+ x_std.iloc[np.where(x_std == 0)[0]] = 1
752
752
  autoscaled_bo_y_data = (bo_y_data - bo_y_data.mean()) / bo_y_data.std()
753
753
  autoscaled_bo_x_data = (bo_x_data - bo_x_data.mean()) / x_std
754
754
  autoscaled_bo_x_prediction = (bo_x_prediction - bo_x_data.mean()) / x_std
@@ -937,7 +937,7 @@ class GTM:
937
937
  if bo_iter == 0: # 最初の試行ではD最適基準を計算
938
938
  # D最適基準の計算
939
939
  param_std = params_df.std(axis=0, ddof=1)
940
- param_std[np.where(param_std == 0)[0]] = 1
940
+ param_std.iloc[np.where(param_std == 0)[0]] = 1
941
941
  autoscaled_params_df = (params_df - params_df.mean(axis=0)) / param_std # 計算のために標準化
942
942
 
943
943
  all_indexes = list(range(autoscaled_params_df.shape[0])) # indexを取得
@@ -1004,8 +1004,8 @@ class GTM:
1004
1004
  else:
1005
1005
  # k3nerror_of_gtm = 10 ** 100
1006
1006
  k3nerror_of_gtm = (np.random.rand()/10 + 1) * 50
1007
-
1008
- params_with_score_df['k3nerror score'].loc[selected_params_idx] = k3nerror_of_gtm # データの保存
1007
+
1008
+ params_with_score_df.loc[selected_params_idx, 'k3nerror score'] = k3nerror_of_gtm # データの保存
1009
1009
 
1010
1010
  if bo_display_flag:
1011
1011
  print('Best k3n-error :', params_with_score_df['k3nerror score'].min())
@@ -1016,7 +1016,7 @@ class GTM:
1016
1016
  break
1017
1017
 
1018
1018
  # Bayesian optimization
1019
- bo_x_data = bo_params_df.copy() # GP学習用データはGMRの結果があるサンプル
1019
+ bo_x_data = bo_params_df.copy() # GP学習用データはGTMの結果があるサンプル
1020
1020
  bo_x_prediction = remaining_params_df.copy() # predictionは選択されていない(GMRの結果がない)サンプル
1021
1021
  bo_y_data = params_with_score_df.loc[bo_params_df.index, 'k3nerror score'] # yはGMRのr2cv
1022
1022
 
@@ -1039,7 +1039,7 @@ class GTM:
1039
1039
  for bo_sample_number in range(bo_number_of_selecting_samples):
1040
1040
  # オートスケーリング
1041
1041
  x_std = bo_x_data.std(axis=0, ddof=1)
1042
- x_std[np.where(x_std == 0)[0]] = 1
1042
+ x_std.iloc[np.where(x_std == 0)[0]] = 1
1043
1043
  autoscaled_bo_y_data = (bo_y_data - bo_y_data.mean()) / bo_y_data.std()
1044
1044
  autoscaled_bo_x_data = (bo_x_data - bo_x_data.mean()) / x_std
1045
1045
  autoscaled_bo_x_prediction = (bo_x_prediction - bo_x_data.mean()) / x_std
@@ -1125,6 +1125,7 @@ class GTM:
1125
1125
  self.shape_of_rbf_centers = [shape_of_rbf_centers, shape_of_rbf_centers]
1126
1126
  self.variance_of_rbfs = variance_of_rbfs
1127
1127
  self.lambda_in_em_algorithm = lambda_in_em
1128
+ self.rep = 'mean'
1128
1129
  self.k3nerror = params_with_score_df_best['k3nerror score']
1129
1130
  if bo_display_flag:
1130
1131
  self.display_flag = True
@@ -0,0 +1,696 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ @author: Hiromasa Kaneko
4
+ """
5
+
6
+ # Semi-supervised Gaussian Mixture Regression with x-only GMM pretraining
7
+ # (ssGMR-xGMM)
8
+
9
+ import numpy as np
10
+ from sklearn.mixture import GaussianMixture
11
+
12
+ from .gmr import GMR
13
+
14
+
15
+ _VALID_COVARIANCE_TYPES = ('full', 'diag', 'tied', 'spherical')
16
+
17
+
18
+ def _as_2d_float_array(values, name, allow_one_dimensional=False):
19
+ """Convert input data to a finite two-dimensional float array."""
20
+ array = np.asarray(values, dtype=float)
21
+ if array.ndim == 1 and allow_one_dimensional:
22
+ array = array.reshape(-1, 1)
23
+ if array.ndim != 2:
24
+ raise ValueError('{0} must be a two-dimensional array.'.format(name))
25
+ if array.shape[0] == 0 or array.shape[1] == 0:
26
+ raise ValueError('{0} must not be empty.'.format(name))
27
+ if not np.all(np.isfinite(array)):
28
+ raise ValueError('{0} contains NaN or infinite values.'.format(name))
29
+ return array
30
+
31
+
32
+ def _validate_variable_numbers(numbers, number_of_variables, name):
33
+ """Validate variable-number lists used by DCEKit GMR."""
34
+ values = np.asarray(numbers, dtype=int).reshape(-1)
35
+ if values.size == 0:
36
+ raise ValueError('{0} must contain at least one variable number.'.format(name))
37
+ if np.unique(values).size != values.size:
38
+ raise ValueError('{0} contains duplicated variable numbers.'.format(name))
39
+ if np.any(values < 0) or np.any(values >= number_of_variables):
40
+ raise ValueError(
41
+ '{0} contains a variable number outside [0, {1}].'.format(
42
+ name, number_of_variables - 1
43
+ )
44
+ )
45
+ return values
46
+
47
+
48
+ def _make_symmetric_positive_definite(matrix, minimum_eigenvalue):
49
+ """Symmetrize a matrix and clip its eigenvalues to a positive floor."""
50
+ matrix = np.asarray(matrix, dtype=float)
51
+ matrix = 0.5 * (matrix + matrix.T)
52
+ eigenvalues, eigenvectors = np.linalg.eigh(matrix)
53
+ eigenvalues = np.maximum(eigenvalues, minimum_eigenvalue)
54
+ matrix = (eigenvectors * eigenvalues).dot(eigenvectors.T)
55
+ return 0.5 * (matrix + matrix.T)
56
+
57
+
58
+ def _stabilize_joint_covariance(
59
+ covariance_x, covariance_xy, covariance_y, minimum_eigenvalue):
60
+ """
61
+ Construct a positive-definite block covariance while preserving the x and
62
+ y marginal covariance matrices. The cross-covariance is shrunk only when
63
+ required by the positive-definite constraint.
64
+ """
65
+ covariance_x = _make_symmetric_positive_definite(
66
+ covariance_x, minimum_eigenvalue
67
+ )
68
+ covariance_y = _make_symmetric_positive_definite(
69
+ covariance_y, minimum_eigenvalue
70
+ )
71
+ covariance_xy = np.asarray(covariance_xy, dtype=float)
72
+
73
+ cholesky_x = np.linalg.cholesky(covariance_x)
74
+ cholesky_y = np.linalg.cholesky(covariance_y)
75
+
76
+ # The block matrix is positive definite if all singular values of
77
+ # Lx^-1 Sxy Ly^-T are smaller than one.
78
+ normalized_cross_covariance = np.linalg.solve(
79
+ cholesky_x, covariance_xy
80
+ )
81
+ normalized_cross_covariance = np.linalg.solve(
82
+ cholesky_y, normalized_cross_covariance.T
83
+ ).T
84
+ singular_values = np.linalg.svd(
85
+ normalized_cross_covariance, compute_uv=False
86
+ )
87
+ largest_singular_value = (
88
+ singular_values[0] if singular_values.size else 0.0
89
+ )
90
+
91
+ cross_covariance_scaling = 1.0
92
+ maximum_allowed_singular_value = 1.0 - 1e-8
93
+ if largest_singular_value >= maximum_allowed_singular_value:
94
+ cross_covariance_scaling = (
95
+ maximum_allowed_singular_value / largest_singular_value
96
+ )
97
+ covariance_xy = covariance_xy * cross_covariance_scaling
98
+
99
+ number_of_x_variables = covariance_x.shape[0]
100
+ number_of_y_variables = covariance_y.shape[0]
101
+ covariance = np.zeros(
102
+ (number_of_x_variables + number_of_y_variables,
103
+ number_of_x_variables + number_of_y_variables),
104
+ dtype=float,
105
+ )
106
+ covariance[:number_of_x_variables, :number_of_x_variables] = covariance_x
107
+ covariance[:number_of_x_variables, number_of_x_variables:] = covariance_xy
108
+ covariance[number_of_x_variables:, :number_of_x_variables] = covariance_xy.T
109
+ covariance[number_of_x_variables:, number_of_x_variables:] = covariance_y
110
+ covariance = 0.5 * (covariance + covariance.T)
111
+ return covariance, cross_covariance_scaling
112
+
113
+
114
+ def _covariances_to_precisions(covariances, covariance_type):
115
+ """Convert covariance parameters to the precisions_init representation."""
116
+ if covariance_type == 'full':
117
+ number_of_components, number_of_variables, _ = covariances.shape
118
+ identity = np.eye(number_of_variables)
119
+ precisions = np.empty_like(covariances)
120
+ for component_number in range(number_of_components):
121
+ precision = np.linalg.solve(
122
+ covariances[component_number], identity
123
+ )
124
+ precisions[component_number] = 0.5 * (
125
+ precision + precision.T
126
+ )
127
+ return precisions
128
+ if covariance_type == 'tied':
129
+ identity = np.eye(covariances.shape[0])
130
+ precision = np.linalg.solve(covariances, identity)
131
+ return 0.5 * (precision + precision.T)
132
+ if covariance_type in ('diag', 'spherical'):
133
+ return 1.0 / covariances
134
+ raise ValueError('Invalid covariance_type: {0}'.format(covariance_type))
135
+
136
+
137
+ def _estimate_covariances_given_means(
138
+ dataset, responsibilities, effective_sample_sizes, means,
139
+ reg_covar, covariance_type):
140
+ """
141
+ Estimate covariance parameters with means supplied externally.
142
+
143
+ This helper is also used by ssGMR-xGMM-xMA after replacing the x-side
144
+ means with their anchors.
145
+ """
146
+ dataset = np.asarray(dataset, dtype=float)
147
+ responsibilities = np.asarray(responsibilities, dtype=float)
148
+ means = np.asarray(means, dtype=float)
149
+ number_of_samples, number_of_variables = dataset.shape
150
+ number_of_components = responsibilities.shape[1]
151
+
152
+ if covariance_type == 'full':
153
+ covariances = np.empty(
154
+ (number_of_components, number_of_variables, number_of_variables),
155
+ dtype=float,
156
+ )
157
+ for component_number in range(number_of_components):
158
+ centered_dataset = dataset - means[component_number]
159
+ covariance = (
160
+ centered_dataset.T * responsibilities[:, component_number]
161
+ ).dot(centered_dataset) / effective_sample_sizes[component_number]
162
+ covariance = 0.5 * (covariance + covariance.T)
163
+ covariance.flat[::number_of_variables + 1] += reg_covar
164
+ covariances[component_number] = covariance
165
+ return covariances
166
+
167
+ if covariance_type == 'tied':
168
+ covariance = np.zeros(
169
+ (number_of_variables, number_of_variables), dtype=float
170
+ )
171
+ for component_number in range(number_of_components):
172
+ centered_dataset = dataset - means[component_number]
173
+ covariance += (
174
+ centered_dataset.T * responsibilities[:, component_number]
175
+ ).dot(centered_dataset)
176
+ covariance /= responsibilities.sum()
177
+ covariance = 0.5 * (covariance + covariance.T)
178
+ covariance.flat[::number_of_variables + 1] += reg_covar
179
+ return covariance
180
+
181
+ if covariance_type == 'diag':
182
+ covariances = np.empty(
183
+ (number_of_components, number_of_variables), dtype=float
184
+ )
185
+ for component_number in range(number_of_components):
186
+ centered_dataset = dataset - means[component_number]
187
+ covariances[component_number] = (
188
+ responsibilities[:, component_number, np.newaxis]
189
+ * centered_dataset ** 2
190
+ ).sum(axis=0) / effective_sample_sizes[component_number]
191
+ covariances += reg_covar
192
+ return covariances
193
+
194
+ if covariance_type == 'spherical':
195
+ covariances = np.empty(number_of_components, dtype=float)
196
+ for component_number in range(number_of_components):
197
+ centered_dataset = dataset - means[component_number]
198
+ covariances[component_number] = (
199
+ responsibilities[:, component_number]
200
+ * np.sum(centered_dataset ** 2, axis=1)
201
+ ).sum() / (
202
+ effective_sample_sizes[component_number] * number_of_variables
203
+ )
204
+ covariances += reg_covar
205
+ return covariances
206
+
207
+ raise ValueError('Invalid covariance_type: {0}'.format(covariance_type))
208
+
209
+
210
+ def _compute_precision_cholesky(covariances, covariance_type):
211
+ """
212
+ Compute precision Cholesky factors using scikit-learn's convention.
213
+
214
+ For full and tied covariances, the returned matrix is inv(L).T where
215
+ covariance = L L.T.
216
+ """
217
+ if covariance_type == 'full':
218
+ number_of_components, number_of_variables, _ = covariances.shape
219
+ identity = np.eye(number_of_variables)
220
+ precision_cholesky = np.empty_like(covariances)
221
+ for component_number in range(number_of_components):
222
+ cholesky = np.linalg.cholesky(covariances[component_number])
223
+ precision_cholesky[component_number] = np.linalg.solve(
224
+ cholesky, identity
225
+ ).T
226
+ return precision_cholesky
227
+
228
+ if covariance_type == 'tied':
229
+ number_of_variables = covariances.shape[0]
230
+ cholesky = np.linalg.cholesky(covariances)
231
+ return np.linalg.solve(cholesky, np.eye(number_of_variables)).T
232
+
233
+ if covariance_type in ('diag', 'spherical'):
234
+ if np.any(covariances <= 0):
235
+ raise ValueError('Covariances must be positive.')
236
+ return 1.0 / np.sqrt(covariances)
237
+
238
+ raise ValueError('Invalid covariance_type: {0}'.format(covariance_type))
239
+
240
+
241
+ class SSGMRXGMM(GMR):
242
+ """
243
+ Semi-supervised GMR with x-only GMM pretraining (ssGMR-xGMM).
244
+
245
+ A GMM is first fitted to x data that do not require corresponding y
246
+ measurements. Its weights, x-side means, and x-side covariance structure
247
+ are then used to initialize a joint GMM fitted to the labeled [x, y]
248
+ samples. After fitting, all prediction methods inherited from ``GMR`` can
249
+ be used for forward prediction and direct inverse analysis.
250
+
251
+ Parameters
252
+ ----------
253
+ n_components : int, default=1
254
+ Number of Gaussian components.
255
+ covariance_type : {'full', 'diag', 'tied', 'spherical'}, default='full'
256
+ Covariance representation used in both the x-only and joint GMMs.
257
+ rep : {'mean', 'mode'}, default='mean'
258
+ Representative value returned by ``predict_rep``. ``'mode'`` selects
259
+ the conditional mean of the component with the largest responsibility;
260
+ ``'mean'`` returns the responsibility-weighted conditional mean.
261
+ tol : float, default=1e-3
262
+ EM convergence tolerance.
263
+ reg_covar : float, default=1e-6
264
+ Non-negative regularization added to covariance diagonals.
265
+ max_iter : int, default=100
266
+ Maximum number of EM iterations for both GMM stages.
267
+ x_gmm_n_init : int, default=1
268
+ Number of initializations for the x-only GMM.
269
+ init_params : {'kmeans', 'k-means++', 'random', 'random_from_data'},
270
+ default='kmeans'
271
+ Initialization method for the x-only GMM.
272
+ random_state : int, RandomState or None, default=None
273
+ Random seed.
274
+ display_flag : bool, default=False
275
+ DCEKit-compatible display flag used by inherited utility methods.
276
+ responsibility_floor : float, default=1e-12
277
+ Small floor applied to x-only responsibilities before calculating
278
+ y-side initial values.
279
+ verbose : int, default=0
280
+ Verbosity passed to scikit-learn's GMM implementation.
281
+ verbose_interval : int, default=10
282
+ Interval between verbose messages.
283
+
284
+ Notes
285
+ -----
286
+ ``labeled_dataset`` and ``x_for_pretraining`` must be expressed in exactly
287
+ the same x-variable scale and column order. The class intentionally does
288
+ not autoscale data, matching DCEKit's ``GMR`` behavior.
289
+ """
290
+
291
+ def __init__(
292
+ self, n_components=1, covariance_type='full', rep='mean',
293
+ tol=1e-3, reg_covar=1e-6, max_iter=100, x_gmm_n_init=1,
294
+ init_params='kmeans', random_state=None, display_flag=False,
295
+ responsibility_floor=1e-12, verbose=0, verbose_interval=10):
296
+ # GMR.__init__ currently uses super(self.__class__, self), which is not
297
+ # subclass-safe. Initialize GaussianMixture directly and inherit only
298
+ # GMR's regression/prediction methods.
299
+ GaussianMixture.__init__(
300
+ self,
301
+ n_components=n_components,
302
+ covariance_type=covariance_type,
303
+ tol=tol,
304
+ reg_covar=reg_covar,
305
+ max_iter=max_iter,
306
+ n_init=1,
307
+ init_params=init_params,
308
+ weights_init=None,
309
+ means_init=None,
310
+ precisions_init=None,
311
+ random_state=random_state,
312
+ warm_start=False,
313
+ verbose=verbose,
314
+ verbose_interval=verbose_interval,
315
+ )
316
+ self.rep = rep
317
+ self.x_gmm_n_init = x_gmm_n_init
318
+ self.display_flag = display_flag
319
+ self.responsibility_floor = responsibility_floor
320
+
321
+ def _check_method_parameters(self):
322
+ if self.covariance_type not in _VALID_COVARIANCE_TYPES:
323
+ raise ValueError(
324
+ 'covariance_type must be one of {0}.'.format(
325
+ _VALID_COVARIANCE_TYPES
326
+ )
327
+ )
328
+ if self.rep not in ('mean', 'mode'):
329
+ raise ValueError("rep must be either 'mean' or 'mode'.")
330
+ if not isinstance(self.x_gmm_n_init, (int, np.integer)) \
331
+ or self.x_gmm_n_init < 1:
332
+ raise ValueError('x_gmm_n_init must be a positive integer.')
333
+ if self.responsibility_floor < 0:
334
+ raise ValueError('responsibility_floor must be non-negative.')
335
+ if self.reg_covar < 0:
336
+ raise ValueError('reg_covar must be non-negative.')
337
+
338
+ def _prepare_joint_fit(self):
339
+ """Hook used by ssGMR-xGMM-xMA before joint EM starts."""
340
+ return None
341
+
342
+ def _build_initial_parameters(
343
+ self, labeled_dataset, x_labeled, y_labeled,
344
+ numbers_of_x, numbers_of_y):
345
+ number_of_components = self.n_components
346
+ number_of_variables = labeled_dataset.shape[1]
347
+ number_of_x_variables = len(numbers_of_x)
348
+ number_of_y_variables = len(numbers_of_y)
349
+ responsibilities = self.x_gmm_.predict_proba(x_labeled)
350
+ if self.responsibility_floor > 0:
351
+ responsibilities = np.maximum(
352
+ responsibilities, self.responsibility_floor
353
+ )
354
+ responsibilities /= responsibilities.sum(axis=1, keepdims=True)
355
+ effective_sample_sizes = responsibilities.sum(axis=0)
356
+ minimum_effective_sample_size = np.finfo(float).eps * 100
357
+ effective_sample_sizes = np.maximum(
358
+ effective_sample_sizes, minimum_effective_sample_size
359
+ )
360
+
361
+ initial_weights = np.asarray(self.x_gmm_.weights_, dtype=float).copy()
362
+ initial_weights /= initial_weights.sum()
363
+
364
+ initial_means = np.zeros(
365
+ (number_of_components, number_of_variables), dtype=float
366
+ )
367
+ initial_means[:, numbers_of_x] = self.x_gmm_.means_
368
+ initial_y_means = responsibilities.T.dot(y_labeled) \
369
+ / effective_sample_sizes[:, np.newaxis]
370
+ initial_means[:, numbers_of_y] = initial_y_means
371
+
372
+ minimum_eigenvalue = max(
373
+ float(self.reg_covar), np.finfo(float).eps * 100
374
+ )
375
+ cross_covariance_scaling = np.ones(
376
+ number_of_components, dtype=float
377
+ )
378
+
379
+ if self.covariance_type == 'full':
380
+ initial_covariances = np.zeros(
381
+ (number_of_components, number_of_variables,
382
+ number_of_variables),
383
+ dtype=float,
384
+ )
385
+ for component_number in range(number_of_components):
386
+ sample_weights = responsibilities[:, component_number]
387
+ centered_x = (
388
+ x_labeled - self.x_gmm_.means_[component_number]
389
+ )
390
+ centered_y = (
391
+ y_labeled - initial_y_means[component_number]
392
+ )
393
+ covariance_y = (
394
+ centered_y.T * sample_weights
395
+ ).dot(centered_y) / effective_sample_sizes[component_number]
396
+ covariance_y = _make_symmetric_positive_definite(
397
+ covariance_y, minimum_eigenvalue
398
+ )
399
+ covariance_xy = (
400
+ centered_x.T * sample_weights
401
+ ).dot(centered_y) / effective_sample_sizes[component_number]
402
+ covariance, scaling = _stabilize_joint_covariance(
403
+ self.x_gmm_.covariances_[component_number],
404
+ covariance_xy,
405
+ covariance_y,
406
+ minimum_eigenvalue,
407
+ )
408
+ cross_covariance_scaling[component_number] = scaling
409
+ initial_covariances[component_number][
410
+ np.ix_(numbers_of_x, numbers_of_x)
411
+ ] = covariance[
412
+ :number_of_x_variables, :number_of_x_variables
413
+ ]
414
+ initial_covariances[component_number][
415
+ np.ix_(numbers_of_x, numbers_of_y)
416
+ ] = covariance[
417
+ :number_of_x_variables, number_of_x_variables:
418
+ ]
419
+ initial_covariances[component_number][
420
+ np.ix_(numbers_of_y, numbers_of_x)
421
+ ] = covariance[
422
+ number_of_x_variables:, :number_of_x_variables
423
+ ]
424
+ initial_covariances[component_number][
425
+ np.ix_(numbers_of_y, numbers_of_y)
426
+ ] = covariance[
427
+ number_of_x_variables:, number_of_x_variables:
428
+ ]
429
+
430
+ elif self.covariance_type == 'diag':
431
+ initial_covariances = np.zeros(
432
+ (number_of_components, number_of_variables), dtype=float
433
+ )
434
+ initial_covariances[:, numbers_of_x] = self.x_gmm_.covariances_
435
+ for component_number in range(number_of_components):
436
+ centered_y = (
437
+ y_labeled - initial_y_means[component_number]
438
+ )
439
+ y_variances = (
440
+ responsibilities[:, component_number, np.newaxis]
441
+ * centered_y ** 2
442
+ ).sum(axis=0) / effective_sample_sizes[component_number]
443
+ initial_covariances[
444
+ component_number, numbers_of_y
445
+ ] = np.maximum(y_variances, minimum_eigenvalue)
446
+ initial_covariances = np.maximum(
447
+ initial_covariances, minimum_eigenvalue
448
+ )
449
+
450
+ elif self.covariance_type == 'tied':
451
+ covariance_xy_all = np.zeros(
452
+ (number_of_components, number_of_x_variables,
453
+ number_of_y_variables),
454
+ dtype=float,
455
+ )
456
+ covariance_y_all = np.zeros(
457
+ (number_of_components, number_of_y_variables,
458
+ number_of_y_variables),
459
+ dtype=float,
460
+ )
461
+ for component_number in range(number_of_components):
462
+ sample_weights = responsibilities[:, component_number]
463
+ centered_x = (
464
+ x_labeled - self.x_gmm_.means_[component_number]
465
+ )
466
+ centered_y = (
467
+ y_labeled - initial_y_means[component_number]
468
+ )
469
+ covariance_xy_all[component_number] = (
470
+ centered_x.T * sample_weights
471
+ ).dot(centered_y) / effective_sample_sizes[component_number]
472
+ covariance_y_all[component_number] = (
473
+ centered_y.T * sample_weights
474
+ ).dot(centered_y) / effective_sample_sizes[component_number]
475
+
476
+ component_weights = effective_sample_sizes \
477
+ / effective_sample_sizes.sum()
478
+ covariance_xy = np.tensordot(
479
+ component_weights, covariance_xy_all, axes=(0, 0)
480
+ )
481
+ covariance_y = np.tensordot(
482
+ component_weights, covariance_y_all, axes=(0, 0)
483
+ )
484
+ covariance, scaling = _stabilize_joint_covariance(
485
+ self.x_gmm_.covariances_, covariance_xy, covariance_y,
486
+ minimum_eigenvalue,
487
+ )
488
+ cross_covariance_scaling[:] = scaling
489
+ initial_covariances = np.zeros(
490
+ (number_of_variables, number_of_variables), dtype=float
491
+ )
492
+ initial_covariances[np.ix_(numbers_of_x, numbers_of_x)] = \
493
+ covariance[:number_of_x_variables, :number_of_x_variables]
494
+ initial_covariances[np.ix_(numbers_of_x, numbers_of_y)] = \
495
+ covariance[:number_of_x_variables, number_of_x_variables:]
496
+ initial_covariances[np.ix_(numbers_of_y, numbers_of_x)] = \
497
+ covariance[number_of_x_variables:, :number_of_x_variables]
498
+ initial_covariances[np.ix_(numbers_of_y, numbers_of_y)] = \
499
+ covariance[number_of_x_variables:, number_of_x_variables:]
500
+
501
+ else: # spherical
502
+ initial_covariances = np.zeros(number_of_components, dtype=float)
503
+ for component_number in range(number_of_components):
504
+ centered_y = (
505
+ y_labeled - initial_y_means[component_number]
506
+ )
507
+ y_variances = (
508
+ responsibilities[:, component_number, np.newaxis]
509
+ * centered_y ** 2
510
+ ).sum(axis=0) / effective_sample_sizes[component_number]
511
+ initial_covariances[component_number] = (
512
+ number_of_x_variables
513
+ * self.x_gmm_.covariances_[component_number]
514
+ + np.sum(y_variances)
515
+ ) / number_of_variables
516
+ initial_covariances = np.maximum(
517
+ initial_covariances, minimum_eigenvalue
518
+ )
519
+
520
+ initial_precisions = _covariances_to_precisions(
521
+ initial_covariances, self.covariance_type
522
+ )
523
+ return (
524
+ initial_weights,
525
+ initial_means,
526
+ initial_covariances,
527
+ initial_precisions,
528
+ responsibilities,
529
+ effective_sample_sizes,
530
+ cross_covariance_scaling,
531
+ )
532
+
533
+ def fit(
534
+ self, labeled_dataset, x_for_pretraining=None,
535
+ numbers_of_x=None, numbers_of_y=None):
536
+ """
537
+ Fit ssGMR-xGMM.
538
+
539
+ Parameters
540
+ ----------
541
+ labeled_dataset : array-like of shape (n_labeled, n_x + n_y)
542
+ Paired, consistently scaled [x, y] samples used for the joint GMM.
543
+ x_for_pretraining : array-like of shape (n_pretraining, n_x), optional
544
+ x samples used by the x-only GMM. They may include the labeled x
545
+ samples, additional unlabeled x samples, and, in a transductive
546
+ protocol, target-domain test x samples. If omitted, the labeled x
547
+ samples are used.
548
+ numbers_of_x : array-like of int
549
+ Column numbers of x in ``labeled_dataset``.
550
+ numbers_of_y : array-like of int
551
+ Column numbers of y in ``labeled_dataset``.
552
+
553
+ Returns
554
+ -------
555
+ self : SSGMRXGMM
556
+ Fitted model.
557
+ """
558
+ self._check_method_parameters()
559
+ labeled_dataset = _as_2d_float_array(
560
+ labeled_dataset, 'labeled_dataset'
561
+ )
562
+ number_of_variables = labeled_dataset.shape[1]
563
+ if numbers_of_x is None or numbers_of_y is None:
564
+ raise ValueError(
565
+ 'numbers_of_x and numbers_of_y must both be specified.'
566
+ )
567
+ numbers_of_x = _validate_variable_numbers(
568
+ numbers_of_x, number_of_variables, 'numbers_of_x'
569
+ )
570
+ numbers_of_y = _validate_variable_numbers(
571
+ numbers_of_y, number_of_variables, 'numbers_of_y'
572
+ )
573
+ if np.intersect1d(numbers_of_x, numbers_of_y).size:
574
+ raise ValueError('numbers_of_x and numbers_of_y must not overlap.')
575
+ if not np.array_equal(
576
+ np.sort(np.r_[numbers_of_x, numbers_of_y]),
577
+ np.arange(number_of_variables)):
578
+ raise ValueError(
579
+ 'numbers_of_x and numbers_of_y must jointly cover every '
580
+ 'column of labeled_dataset.'
581
+ )
582
+
583
+ x_labeled = labeled_dataset[:, numbers_of_x]
584
+ y_labeled = labeled_dataset[:, numbers_of_y]
585
+ if x_for_pretraining is None:
586
+ x_for_pretraining = x_labeled
587
+ else:
588
+ x_for_pretraining = np.asarray(
589
+ x_for_pretraining, dtype=float
590
+ )
591
+ if x_for_pretraining.ndim == 1 and len(numbers_of_x) == 1:
592
+ x_for_pretraining = x_for_pretraining.reshape(-1, 1)
593
+ if x_for_pretraining.ndim != 2:
594
+ raise ValueError(
595
+ 'x_for_pretraining must be a two-dimensional array.'
596
+ )
597
+ if x_for_pretraining.shape[1] == number_of_variables:
598
+ # Select x before the finite-value check so that a joint-style
599
+ # array may contain missing y values.
600
+ x_for_pretraining = x_for_pretraining[:, numbers_of_x]
601
+ elif x_for_pretraining.shape[1] != len(numbers_of_x):
602
+ raise ValueError(
603
+ 'x_for_pretraining must have either {0} x columns or {1} '
604
+ 'joint-data columns.'.format(
605
+ len(numbers_of_x), number_of_variables
606
+ )
607
+ )
608
+ x_for_pretraining = _as_2d_float_array(
609
+ x_for_pretraining, 'x_for_pretraining'
610
+ )
611
+
612
+ if labeled_dataset.shape[0] < self.n_components:
613
+ raise ValueError(
614
+ 'The number of labeled samples must be at least '
615
+ 'n_components.'
616
+ )
617
+ if x_for_pretraining.shape[0] < self.n_components:
618
+ raise ValueError(
619
+ 'The number of x pretraining samples must be at least '
620
+ 'n_components.'
621
+ )
622
+
623
+ self.numbers_of_x_ = numbers_of_x.copy()
624
+ self.numbers_of_y_ = numbers_of_y.copy()
625
+ self.number_of_x_variables_ = len(numbers_of_x)
626
+ self.number_of_y_variables_ = len(numbers_of_y)
627
+
628
+ self.x_gmm_ = GaussianMixture(
629
+ n_components=self.n_components,
630
+ covariance_type=self.covariance_type,
631
+ tol=self.tol,
632
+ reg_covar=self.reg_covar,
633
+ max_iter=self.max_iter,
634
+ n_init=self.x_gmm_n_init,
635
+ init_params=self.init_params,
636
+ random_state=self.random_state,
637
+ warm_start=False,
638
+ verbose=self.verbose,
639
+ verbose_interval=self.verbose_interval,
640
+ )
641
+ self.x_gmm_.fit(x_for_pretraining)
642
+
643
+ (
644
+ self.initial_weights_,
645
+ self.initial_means_,
646
+ self.initial_covariances_,
647
+ self.initial_precisions_,
648
+ self.x_responsibilities_for_labeled_samples_,
649
+ self.x_effective_sample_sizes_,
650
+ self.cross_covariance_scaling_,
651
+ ) = self._build_initial_parameters(
652
+ labeled_dataset,
653
+ x_labeled,
654
+ y_labeled,
655
+ numbers_of_x,
656
+ numbers_of_y,
657
+ )
658
+
659
+ # GaussianMixture consumes these public initialization attributes.
660
+ self.weights_init = self.initial_weights_.copy()
661
+ self.means_init = self.initial_means_.copy()
662
+ self.precisions_init = np.array(
663
+ self.initial_precisions_, copy=True
664
+ )
665
+ self._prepare_joint_fit()
666
+
667
+ # Call GaussianMixture.fit directly to retain GMR's prediction methods
668
+ # while avoiding GMR.__init__'s subclassing issue.
669
+ GaussianMixture.fit(self, labeled_dataset)
670
+ return self
671
+
672
+ def fit_from_xy(self, x_labeled, y_labeled, x_for_pretraining=None):
673
+ """
674
+ Convenience interface when x and y are supplied as separate arrays.
675
+ """
676
+ x_labeled = _as_2d_float_array(
677
+ x_labeled, 'x_labeled', allow_one_dimensional=True
678
+ )
679
+ y_labeled = _as_2d_float_array(
680
+ y_labeled, 'y_labeled', allow_one_dimensional=True
681
+ )
682
+ if x_labeled.shape[0] != y_labeled.shape[0]:
683
+ raise ValueError(
684
+ 'x_labeled and y_labeled must have the same number of samples.'
685
+ )
686
+ labeled_dataset = np.c_[x_labeled, y_labeled]
687
+ numbers_of_x = np.arange(x_labeled.shape[1])
688
+ numbers_of_y = np.arange(
689
+ x_labeled.shape[1], labeled_dataset.shape[1]
690
+ )
691
+ return self.fit(
692
+ labeled_dataset,
693
+ x_for_pretraining=x_for_pretraining,
694
+ numbers_of_x=numbers_of_x,
695
+ numbers_of_y=numbers_of_y,
696
+ )
@@ -0,0 +1,65 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ @author: Hiromasa Kaneko
4
+ """
5
+
6
+ # Semi-supervised Gaussian Mixture Regression with x-only GMM pretraining
7
+ # and x-mean anchoring (ssGMR-xGMM-xMA)
8
+
9
+ import numpy as np
10
+
11
+ from .ssgmr_xgmm import (
12
+ SSGMRXGMM,
13
+ _compute_precision_cholesky,
14
+ _estimate_covariances_given_means,
15
+ )
16
+
17
+
18
+ class SSGMRXGMMXMA(SSGMRXGMM):
19
+ """
20
+ Semi-supervised GMR with x-only GMM pretraining and x-mean anchoring.
21
+
22
+ Initialization is identical to :class:`SSGMRXGMM`. During every M-step of
23
+ the joint-GMM EM algorithm, the x-side means are replaced by the x-only GMM
24
+ means. Mixture weights, y-side means, and all covariance parameters remain
25
+ trainable. The covariance update is calculated around the anchored means,
26
+ as specified by ssGMR-xGMM-xMA.
27
+
28
+ The constructor and ``fit`` interface are the same as ``SSGMRXGMM``.
29
+ After fitting, all prediction methods inherited from DCEKit's ``GMR`` can
30
+ be used for forward prediction and direct inverse analysis.
31
+ """
32
+
33
+ def _prepare_joint_fit(self):
34
+ self.x_mean_anchors_ = self.initial_means_[
35
+ :, self.numbers_of_x_
36
+ ].copy()
37
+
38
+ def _m_step(self, dataset, log_responsibilities, xp=None):
39
+ """M-step with hard anchoring of the x-side component means."""
40
+ dataset = np.asarray(dataset, dtype=float)
41
+ log_responsibilities = np.asarray(
42
+ log_responsibilities, dtype=float
43
+ )
44
+ responsibilities = np.exp(log_responsibilities)
45
+ effective_sample_sizes = responsibilities.sum(axis=0)
46
+ effective_sample_sizes += 10 * np.finfo(float).eps
47
+
48
+ self.weights_ = effective_sample_sizes \
49
+ / effective_sample_sizes.sum()
50
+ means = responsibilities.T.dot(dataset) \
51
+ / effective_sample_sizes[:, np.newaxis]
52
+ means[:, self.numbers_of_x_] = self.x_mean_anchors_
53
+ self.means_ = means
54
+
55
+ self.covariances_ = _estimate_covariances_given_means(
56
+ dataset,
57
+ responsibilities,
58
+ effective_sample_sizes,
59
+ self.means_,
60
+ self.reg_covar,
61
+ self.covariance_type,
62
+ )
63
+ self.precisions_cholesky_ = _compute_precision_cholesky(
64
+ self.covariances_, self.covariance_type
65
+ )
@@ -132,9 +132,9 @@ class VBGMR(BayesianGaussianMixture):
132
132
  """
133
133
 
134
134
  mode_of_estimated_mean, weighted_estimated_mean, _, _ = self.predict(dataset, numbers_of_input_variables, numbers_of_output_variables)
135
- if self.rep == 'mean':
135
+ if self.rep == 'mode':
136
136
  values = mode_of_estimated_mean.copy()
137
- elif self.rep == 'mode':
137
+ elif self.rep == 'mean':
138
138
  values = weighted_estimated_mean.copy()
139
139
  return values
140
140
 
@@ -103,7 +103,7 @@ def clustering_based_on_correlation_coefficients(x, threshold_of_r):
103
103
  distance_in_x = 1 / r_in_x
104
104
 
105
105
  # clustering
106
- clustering = AgglomerativeClustering(n_clusters=None, affinity='precomputed', compute_full_tree='True',
106
+ clustering = AgglomerativeClustering(n_clusters=None, metric='precomputed', compute_full_tree='auto',
107
107
  distance_threshold=1 / threshold_of_r, linkage='complete')
108
108
  clustering.fit(distance_in_x)
109
109
  cluster_numbers = clustering.labels_
@@ -88,7 +88,11 @@ def cvpfi(
88
88
  corr_variable_all = X[:, corr_variable_number].copy()
89
89
  for sample_number in range(x_test.shape[0]):
90
90
  if np.random.rand(1)[0] < target_x_corr[corr_variable_number]:
91
- x_test_shuffled[sample_number, corr_variable_number] = np.random.choice(corr_variable_all, 1, replace=replace)
91
+ tmp = np.random.choice(corr_variable_all, 1, replace=replace)
92
+ if len(tmp)== 1:
93
+ x_test_shuffled[sample_number, corr_variable_number] = tmp[0]
94
+ else:
95
+ x_test_shuffled[sample_number, corr_variable_number] = tmp
92
96
 
93
97
  estimated_y_test_shuffled = estimator_copy.predict(x_test_shuffled)
94
98
  if y.ndim == 1:
@@ -115,11 +119,12 @@ def cvpfi(
115
119
  accuracy_cv = accuracy_score(y, estimated_y_in_cv)
116
120
  else:
117
121
  accuracy_cv = accuracy_score(np.ravel(y), np.ravel(estimated_y_in_cv))
118
- # print(accuracy_score)
122
+ print(accuracy_cv)
119
123
  for variable_number in range(X.shape[1]):
120
124
  for n_repeat in range(n_repeats):
121
125
  # print(accuracy_score(y, estimated_y_in_cv_shuffled[:, n_repeat, variable_number]))
122
126
  if y.ndim == 1:
127
+ print(accuracy_score(y, estimated_y_in_cv_shuffled[:, n_repeat, variable_number]))
123
128
  importances[variable_number, n_repeat] = accuracy_cv - accuracy_score(y, estimated_y_in_cv_shuffled[:, n_repeat, variable_number])
124
129
  else:
125
130
  importances[variable_number, n_repeat] = accuracy_cv - accuracy_score(np.ravel(y), np.ravel(estimated_y_in_cv_shuffled[:, :, n_repeat, variable_number]))
@@ -202,7 +207,11 @@ def cvpfi_gmr(
202
207
  corr_variable_all = X[:, corr_variable_number].copy()
203
208
  for sample_number in range(x_test.shape[0]):
204
209
  if np.random.rand(1)[0] < target_x_corr[corr_variable_number]:
205
- x_test_shuffled[sample_number, corr_variable_number] = np.random.choice(corr_variable_all, 1, replace=replace)
210
+ tmp = np.random.choice(corr_variable_all, 1, replace=replace)
211
+ if len(tmp)== 1:
212
+ x_test_shuffled[sample_number, corr_variable_number] = tmp[0]
213
+ else:
214
+ x_test_shuffled[sample_number, corr_variable_number] = tmp
206
215
  estimated_y_in_cv_shuffled[fold_index==fold_number_in_outer_cv, :, n_repeat, variable_number] = estimator_copy.predict_rep(x_test_shuffled, numbers_of_x, numbers_of_y)
207
216
 
208
217
  importances = np.zeros([X.shape[1], n_repeats])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dcekit
3
- Version: 2.15.1
3
+ Version: 2.17.1
4
4
  Summary: Data Chemical Engineering toolkit
5
5
  Home-page: https://github.com/hkaneko1985/dcekit/
6
6
  Author: Hiromasa Kaneko
@@ -14,6 +14,8 @@ dcekit/design_of_exmeriments/bayesian_optimization.py
14
14
  dcekit/generative_model/__init__.py
15
15
  dcekit/generative_model/gmr.py
16
16
  dcekit/generative_model/gtm.py
17
+ dcekit/generative_model/ssgmr_xgmm.py
18
+ dcekit/generative_model/ssgmr_xgmm_xma.py
17
19
  dcekit/generative_model/vbgmr.py
18
20
  dcekit/just_in_time/__init__.py
19
21
  dcekit/just_in_time/jitpls.py
@@ -13,7 +13,7 @@ with open('LICENSE.txt') as f:
13
13
 
14
14
  setup(
15
15
  name='dcekit',
16
- version='2.15.1',
16
+ version='2.17.1',
17
17
  description='Data Chemical Engineering toolkit',
18
18
  long_description=readme,
19
19
  author='Hiromasa Kaneko',
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes