import { simultaneous_poweriteration } from "../linear_algebra/index.js";
import { Matrix } from "../matrix/index.js";
import { DR } from "./DR.js";
/**
* @class
* @alias PCA
* @augments DR
*/
export class PCA extends DR {
/**
* @constructor
* @memberof module:dimensionality_reduction
* @alias PCA
* @param {Matrix|number[][]} X - the high-dimensional data.
* @param {object} parameters - Object containing parameterization of the DR method.
* @param {number} [parameters.d = 2] - the dimensionality of the projection.
* @param {number} [parameters.seed = 1212] - the seed for the random number generator.
* @param {object} [parameters.eig_args] - Parameters for the eigendecomposition algorithm.
* @returns {PCA}
*/
constructor(X, parameters) {
super(X, { d: 2, seed: 1212, eig_args: {} }, parameters);
if (!this._parameters.eig_args.hasOwnProperty("seed")) {
this._parameters.eig_args.seed = this._randomizer;
}
return this;
}
/**
* Transforms the inputdata {@link X} to dimensionality {@link d}. If parameter {@link A} is given, then project {@link A} with the principal components of {@link X}.
* @param {null|Matrix|number[][]} [A = null] - If given, the data to project.
* @returns {Matrix|number[][]} - The projected data.
*/
transform(A = null) {
const V = this.principal_components();
if (A == null) {
const X = this.X;
this.Y = X.dot(V);
return this.projection;
} else if (Array.isArray(A)) {
return Matrix.from(A).dot(V).asArray;
} else if (A instanceof Matrix) {
return A.dot(V);
} else {
throw new Error("No valid type for A!");
}
}
/**
* Computes the {@link d} principal components of Matrix {@link X}.
* @returns {Matrix}
*/
principal_components() {
if (this.V) {
return this.V;
}
const { d, eig_args } = this._parameters;
const X = this.X;
const X_cent = X.sub(X.meanCols);
const C = X_cent.transDot(X_cent);
const { eigenvectors: V } = simultaneous_poweriteration(C, d, eig_args);
this.V = Matrix.from(V).transpose();
return this.V;
}
static principal_components(X, parameters) {
const dr = new this(X, parameters);
return dr.principal_components();
}
}