用DeepSeek编程计算SEM(二)
之前用DeepSeek编程计算了较为简单的SEM,后来用DeepSeek编程计算较为复杂的SEM,但没找到问题。原来有错误的程序如第一部分,DeepSeek修改意见如第二部分,正确的代码如第三部分。new SimpleValueChecker(1e-5, 1e-5) // 收敛检查器。
之前用DeepSeek编程计算了较为简单的SEM,现在用DeepSeek编程计算较为复杂的SEM,如下:
import org.apache.commons.math3.linear.*;
import org.apache.commons.math3.optim.*;
import org.apache.commons.math3.optim.nonlinear.scalar.GoalType;
import org.apache.commons.math3.optim.nonlinear.scalar.ObjectiveFunction;
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.BOBYQAOptimizer;
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.CMAESOptimizer;
import org.apache.commons.math3.random.JDKRandomGenerator;
import java.util.Arrays;
public class SEMPathAnalysis {
private static final RealMatrix S = MatrixUtils.createRealMatrix(new double[][] {
{1, 0.2, 0.3, 0.1, 0.15, 0.2, 0.1, 0.12, 0.15},
{0.2, 1, 0.4, 0.12, 0.18, 0.22, 0.11, 0.13, 0.16},
{0.3, 0.4, 1, 0.15, 0.2, 0.25, 0.12, 0.14, 0.17},
{0.1, 0.12, 0.15, 1, 0.3, 0.4, 0.15, 0.18, 0.2},
{0.15, 0.18, 0.2, 0.3, 1, 0.5, 0.18, 0.2, 0.22},
{0.2, 0.22, 0.25, 0.4, 0.5, 1, 0.2, 0.22, 0.25},
{0.1, 0.11, 0.12, 0.15, 0.18, 0.2, 1, 0.3, 0.4},
{0.12, 0.13, 0.14, 0.18, 0.2, 0.22, 0.3, 1, 0.5},
{0.15, 0.16, 0.17, 0.2, 0.22, 0.25, 0.4, 0.5, 1}});
public static void main(String[] args) {
// 初始参数猜测
double[] initialParams = new double[15];
Arrays.fill(initialParams, 0.01);
initialParams[3] = 0.3; // psi_A
initialParams[4] = 0.3; // psi_B
initialParams[5] = 0.3; // phi_C
for (int i = 6; i < 15; i++) {
initialParams[i] = 0.1; // theta1-theta9
}
double[]lowerBounds={-5,-5,-5,0,0,0,0,0,0,0,0,0,0,0,0};//每个维度的下界
double[]upperBounds={5,5,5,5,5,5,5,5,5,5,5,5,5,5,5}; // 每个维度的上界
SimpleBounds bounds = new SimpleBounds(lowerBounds, upperBounds);
BOBYQAOptimizer bobyqa = new BOBYQAOptimizer(
15 + 2, // 插值点数
0.1, // 初始信任区域半径
0.001 // 停止半径
);
PointValuePair intermediateResult = bobyqa.optimize(
new MaxEval(5000),
new ObjectiveFunction(params -> computeML(params)),
GoalType.MINIMIZE,
new InitialGuess(initialParams),
new SimpleBounds(lowerBounds, upperBounds)
);
CMAESOptimizer optimizer = new CMAESOptimizer(
10000, 1e-8, true, 0, 0,
new JDKRandomGenerator(), false,
new SimpleValueChecker(1e-6, 1e-6)
);
PointValuePair result = optimizer.optimize(
new MaxEval(10000),
new ObjectiveFunction(params -> computeML(params)),
GoalType.MINIMIZE,
new CMAESOptimizer.Sigma(new double[]{0.05, 0.05, 0.05, 0.03, 0.03, 0.03, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01}),
new CMAESOptimizer.PopulationSize(15),
new InitialGuess(intermediateResult.getPoint()),
new SimpleBounds(lowerBounds, upperBounds)
);
double[] optimalParams = result.getPoint();
System.out.printf("gamma1: %.3f, gamma2: %.3f, beta: %.3f%n",
optimalParams[0], optimalParams[1], optimalParams[2]);
}
private static double computeML(double[] params) {
try {
double gamma1 = params[0];
double gamma2 = params[1];
double beta = params[2];
double psiA = params[3];
double psiB = params[4];
double phiC = params[5];
double[] theta = Arrays.copyOfRange(params, 6, 15);
// 计算潜变量协方差
double varB = gamma2 * gamma2 * phiC + psiB;
double covBC = gamma2 * phiC;
double varA = Math.pow(gamma1 + beta * gamma2, 2) * phiC + beta * beta * varB + 2 * beta * (gamma1 + beta * gamma2) * covBC + psiA;
double covAB = (gamma1 + beta * gamma2) * gamma2 * phiC + beta * varB;
double covAC = (gamma1 + beta * gamma2) * phiC;
// 构建隐含协方差矩阵
RealMatrix sigma = MatrixUtils.createRealMatrix(9, 9);
// 填充潜变量A的块
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
sigma.setEntry(i, j, i == j ? varA + theta[i] : varA);
}
}
// 填充潜变量B的块
for (int i = 3; i < 6; i++) {
for (int j = 3; j < 6; j++) {
sigma.setEntry(i, j, i == j ? varB + theta[i] : varB);
}
}
// 填充潜变量C的块
for (int i = 6; i < 9; i++) {
for (int j = 6; j < 9; j++) {
sigma.setEntry(i, j, i == j ? phiC + theta[i - 6] : phiC);
}
}
// 填充跨潜变量的协方差
for (int i = 0; i < 3; i++) {
for (int j = 3; j < 6; j++) {
sigma.setEntry(i, j, covAB);
sigma.setEntry(j, i, covAB);
}
for (int j = 6; j < 9; j++) {
sigma.setEntry(i, j, covAC);
sigma.setEntry(j, i, covAC);
}
}
for (int i = 3; i < 6; i++) {
for (int j = 6; j < 9; j++) {
sigma.setEntry(i, j, covBC);
sigma.setEntry(j, i, covBC);
}
}
SingularValueDecomposition svd = new SingularValueDecomposition(sigma);
double logDet = 0;
for (double s : svd.getSingularValues()) {
logDet += Math.log(s);
}
RealMatrix invSigma = svd.getSolver().getInverse();
RealMatrix product = S.multiply(invSigma);
double trace = 0;
for (int i = 0; i < 9; i++) trace += product.getEntry(i, i);
return logDet + trace;
} catch (Exception e) {
return Double.MAX_VALUE;
}
}
}
两次的运行结果为:
gamma1: 0.214, gamma2: 0.517, beta: 0.263
gamma1: 0.205, gamma2: 0.519, beta: 0.267
第二次相当于:
C -> A 路径系数: 0.205
C -> B 路径系数: 0.519
B -> A 路径系数: 0.267
下来后用lisrel计算了一下,结果为:
C -> A 路径系数: 0.17
C -> B 路径系数: 0.45
B -> A 路径系数: 0.40
看来还有很多改进的空间哦。
更多推荐



所有评论(0)