我将带头冲锋——典型相关分析


联系数计加油站获取论文和代码等资源。
邮箱:MathComputerSharing@outlook.com
微信公众号:数计加油站
致谢:清风数学建模


在这里插入图片描述

组与组的整体相关性

相关系数能衡量一对数据的线性关系。然而,我们常常会碰到这样的情况:有两组数据,每组各有几列数据,需要我们研究研究这两组数据之间有没有什么难以告人的关系。

一种做法是两两计算两组数据的每两列数据之间的相关系数,这样可以得出两组数据各列之间的关系。但我们想要得到的,往往并不是这种个体与个体之间的关系,而是两大组数据的整体相关性。比如,我们想要知道文科成绩和理科成绩的总体关系,而不仅仅只是语文和数学之间的关系、英语和物理之间的关系等等。

“代表大会制度”的引入

衡量整体相关性,很容易想到的一个方法,就是在每组之中分别找出一个代表,我们来研究这两个代表之间的关系就可以了。代表之间没有关系,那当然各组各选出一列数据,它们的关系也不会大到哪里去;代表之间纠葛很深,那当然各组各选出一列数据,它们的关系也不会那么的形同陌路。

代表之间的关系,表示着从整体上而言,两组数据之间的关系。

怎么挑选代表——尽量产生关系

代表当然不能简单地从已知数据列中挑选。我们可以采用线性组合的方式,以不同的权重,综合数据组中的各列已知数据。

还有一个原则:万事万物一定是有它们的内部联系存在的。我们挑选的两个代表,理应有着最大的关系,这样才有研究的意义。

如果代表之间的最大关系能够非常大,那么在特定代表的前提下,两组数据确实能产生一定联系。

如果代表之间的最大关系还是很小,那么这两组数据在很大程度上,关系很小。

一篇简短的小论文

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Matlab代码

clc,clear

%% 导入数据
data = readmatrix("data\健康指标.csv");
[m,n] = size(data);
X = data(:,1:3);
Y = data(:,4:6);
p = size(X,2);
q = size(Y,2);

%% 进行正态性检验
% Shapiro-wilk 检验
sw_H = ones([n,1]);
sw_P = ones([n,1]);
for i=1:n
    [sw_h,sw_p] = swtest(data(:,i),0.1);
    sw_H(i,1)=sw_h;
    sw_P(i,1)=sw_p;
end
disp("    是否通过      p")
disp([sw_H,sw_P]);

%% 未进行标准化的典型相关分析
[A,B,r,U,V,stats] = canoncorr(X,Y);
disp("r=")
disp(r);
disp("p=");
disp(stats.p);
disp("A=")
disp(A);
disp("B=")
disp(B);

%% 进行标准化的典型相关分析
R11 = corr(X,X);
R12 = corr(X,Y);
R21 = corr(Y,X);
R22 = corr(Y,Y);
M = R11\R12/(R22)*R21;
N = R22\R21/(R11)*R12;
[A_normalized,lambda1] = eig(M);
[B_normalized,lambda2] = eig(N);

lambda1 = sum(sqrt(lambda1));
[lambda1,I1] = sort(lambda1,"descend");
A_normalized = A_normalized(:,I1);
lambda2 = sum(sqrt(lambda2));
[lambda2,I2] = sort(lambda2,"descend");
B_normalized = B_normalized(:,I2);

for i=1:p
    d = A_normalized(:,i)' * R11 *A_normalized(:,i);
    A_normalized(:,i)=A_normalized(:,i)/(d^(1/2));
end

for i=1:q
    d = B_normalized(:,i)' * R22 *B_normalized(:,i);
    B_normalized(:,i)=B_normalized(:,i)/(d^(1/2));
end

disp("lambda_1=");
disp(lambda1);
disp("A_normalzed=");
disp(A_normalized);
disp("lambda_2=");
disp(lambda2);
disp("B_normalzed=");
disp(B_normalized);

%% 典型载荷分析
% 未标准化
RUX = corr(U,X);
RUY = corr(U,V);
RVX = corr(V,X);
RVY = corr(V,Y);
% 标准化
nRUX = A_normalized'*R11;
nRUY = A_normalized'*R12;
nRVX = B_normalized'*R21;
nRVY = B_normalized'*R22;

%% 典型冗余分析
RdU = sum(nRUX.^2,2)./p;
RdV = sum(nRVY.^2,2)./q;

clear d I1 I2 i   

Python代码

## 导库
import numpy as np
import pandas as pd
from scipy import stats

np.set_printoptions(suppress=True)

## 数据初始化
data = pd.read_csv("../data/健康指标.csv", header=None)
data.columns = ["体重", "腰围", "脉搏", "引体向上次数", "起坐次数", "跳跃次数"]
display(data)

m, n = data.shape
D = np.array(data)
X = np.array(data[["体重", "腰围", "脉搏"]])
Y = np.array(data[["引体向上次数", "起坐次数", "跳跃次数"]])
p = X.shape[1]
q = Y.shape[1]

## 正态性检验
swtest_result = []
for i in range(n):
    W, sw_p = stats.shapiro(D[:, i])
    swtest_result.append([W, sw_p])
swtest_result = pd.DataFrame(swtest_result, columns=["W值", "p值"], index=data.columns)
display(swtest_result)

def cov(X, Y,normalized=False):
"""计算两个矩阵的协方差矩阵"""
    p = X.shape[1]
    q = Y.shape[1]
    result = np.ones((p, q))
    for i in range(p):
        for j in range(q):
            if normalized:
                result[i, j] = np.corrcoef(X[:, i], Y[:, j])[0, 1]
            else:
                result[i,j] = np.cov(X[:, i], Y[:, j])[0, 1]
    return result

def sortVbyL(L,V):
"""按特征值大小排序特征向量"""
    vectors = V.T.tolist()
    tmp = zip(L,vectors)
    tmp = sorted(tmp,key=lambda x:x[0],reverse=True)
    L,V = zip(*tmp)
    L = np.array(L)
    V = np.array(V).T
    return L,V

def canoncorr(X, Y,normalized=False):
"""典型相关分析"""
    # 计算协方差矩阵
    S11 = cov(X, X,normalized)
    S12 = cov(X, Y,normalized)
    S21 = cov(Y, X,normalized)
    S22 = cov(Y, Y,normalized)
    # 求特征值和特征向量并排序
    M = np.linalg.inv(S11) @ S12 @ np.linalg.inv(S22) @ S21
    N = np.linalg.inv(S22) @ S21 @ np.linalg.inv(S11) @ S12

    lambda_1, A = np.linalg.eig(M)
    lambda_1 = np.sqrt(lambda_1)
    lambda_1, A = sortVbyL(lambda_1,A)

    lambda_2, B = np.linalg.eig(N)
    lambda_2 = np.sqrt(lambda_2)
    lambda_2, B = sortVbyL(lambda_2,B)

    if np.linalg.norm(lambda_1 - lambda_2) > 0.0001:
        return None
    r = lambda_1

    # 限制方差为1
    for i in range(p):
        d1 = A[:, i].T @ S11 @ A[:, i]
        A[:, i] = A[:, i] * (d1 ** (-1 / 2))
    for j in range(q):
        d2 = B[:, j].T @ S22 @ B[:, j]
        B[:, j] = B[:, j] * (d2 ** (-1 / 2))

    # 计算典型向量
    U = X @ A
    V = Y @ B

    # 假设检验
    P = []
    for k in range(r.shape[0]):
        Lambda_k = np.prod([1 - x ** 2 for x in r[k:]])
        m_k = (m - k - 1) - 1 / 2 * (p + q + 1) + np.sum([x ** (-2) for x in r[:k]])
        f_k = (p - k) * (q - k)
        P.append(stats.chi2.sf(-m_k * np.log(Lambda_k), f_k))

    return A, B, r, U, V, P

## 未进行标准化的典型相关分析
A, B, r, U, V, P = canoncorr(X, Y)
display(r, P, A, B)

## 进行标准化的典型相关分析
nA, nB, nr, nU, nV, nP = canoncorr(X, Y,normalized=True)
display(nr, nP, nA, nB)

## 典型载荷分析
# 未标准化
RUX = cov(U,X,normalized=True)
RUY = cov(U,V,normalized=True)
RVX = cov(V,X,normalized=True)
RVY = cov(V,Y,normalized=True)
# 标准化
nRUX = nA.T @ cov(X,X,normalized=True)
nRUY = nA.T @ cov(X,Y,normalized=True)
nRVX = nB.T @ cov(Y,X,normalized=True)
nRVY = nB.T @ cov(Y,Y,normalized=True)
display(RUX)
display(RVY)
display(nRUX)
display(nRVY)

## 典型冗余分析
RdU = np.sum(nRUX**2,1)/p
RdV = np.sum(nRVY**2,1)/q
display(RdU)
display(RdV)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值