我正在尝试使用Singular Value Decomposition method(SVD)来计算3D线性回归LINE。
这很好用。现在,我想概括加权回归的方法。
如何使用SVD计算optimale beta?下面是我使用CSML package的C#代码。 LinearRegression()函数工作得很好。 WeightedLinearRegression()没有,我认为这是因为我不能简单地定义
weighted_mult_mat = M_tr * W * M;
CODE:
public static Vector3D WeightedLinearRegression(List<Point3D> pts, List<double> weights) {
// normalisation
double sum = weights.Sum();
if (sum != weights.Count) {
for (int i = 0; i < weights.Count; i++ ) {
weights[i] = weights[i] / sum;
}
}
Point3D avg = pts.average();
// populate Matrix M
CSML.Matrix M = new CSML.Matrix(pts.Count, 3); // init
// populate matrix M
for (int i = 1; i < pts.Count + 1; i++) {
M[i, 1] = new Complex(pts[i - 1].X - avg.X);
M[i, 2] = new Complex(pts[i - 1].Y - avg.Y);
M[i, 3] = new Complex(pts[i - 1].Z - avg.Z);
}
CSML.Matrix M_tr = M.Transpose();
// populate weights matrix
CSML.Matrix W = new CSML.Matrix(pts.Count, pts.Count); // init
for (int i = 1; i < pts.Count + 1; i++) {
W[i, i] = new Complex(weights[i-1]);
}
// compute matrix
CSML.Matrix weighted_mult_mat = new CSML.Matrix();
weighted_mult_mat = M_tr * W;
weighted_mult_mat = weighted_mult_mat * M;
var weighted_dense_mat = new DenseMatrix(3, 3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
weighted_dense_mat[i, j] = weighted_mult_mat[i + 1, j + 1].Re;
}
}
var weighted_svd = weighted_dense_mat.Svd(true);
var weighted_vt = weighted_svd.VT;
Vector3D weighted_dirVect = new Vector3D(weighted_vt[0, 0], weighted_vt[0, 1], weighted_vt[0, 2]);
weighted_dirVect.Normalize();
return weighted_dirVect;
}
public static Vector3D LinearRegression(List<Point3D> pts) {
Point3D avg = pts.average();
// populate Matrix M
CSML.Matrix M = new CSML.Matrix(pts.Count, 3); // init
// populate matrix M
for (int i = 1; i < pts.Count + 1; i++) {
M[i, 1] = new Complex(pts[i - 1].X - avg.X);
M[i, 2] = new Complex(pts[i - 1].Y - avg.Y);
M[i, 3] = new Complex(pts[i - 1].Z - avg.Z);
}
CSML.Matrix M_tr = M.Transpose();
CSML.Matrix mult_mat = new CSML.Matrix();
mult_mat = M_tr * M;
var dense_mat = new DenseMatrix(3, 3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
dense_mat[i, j] = mult_mat[i + 1, j + 1].Re ;
}
}
var svd = dense_mat.Svd(true);
var vt = svd.VT;
Vector3D dirVect = new Vector3D(vt[0, 0], vt[0, 1], vt[0, 2]);
dirVect.Normalize();
return dirVect;
}