You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
8.8 KiB

"""PCA的重构算法"""
import math
import numpy as np
def min_pos(X):
X[X <= 0] = np.max(X)
m = np.min(X)
re = np.where(X == m)
min_i = re[0]
min_j = re[1]
if m < 0:
m = 0
return m, min_i, min_j
def Lars(X, Y, D, DIAG, t, limit_line, LockVariable):
n, m = X.shape
beta = np.zeros((1, m))
beta_temp = np.zeros((m, 1))
A = []
N_Co_added = 0
i = 0
mse = []
limit_m = len(LockVariable)
for k in range(m - limit_m - 1):
i += 1
ero = np.array(Y - beta[-1, :].T)
# c=np.dot(P,DIAG,P.T,ero)
c = np.dot(D, DIAG).dot(D.T).dot(ero) # 计算相关性
c[LockVariable] = 0
C = np.max(np.abs(c))
mse.append(np.dot(ero.T, D).dot(DIAG).dot(D.T).dot(ero))
if mse[k] < limit_line:
break
elif k == 0:
addTndex = np.where(abs(c) == C)[-1][0]
A.append(addTndex) # 活动集
# 更新正在添加的相应协方差索引的数量
N_Co_added = N_Co_added + 1
A_c = list(set(range(0, m)).difference(set(A))) # 非活动集
s_A = np.diag(np.sign(c[A]))
num_Zero_Coeff = len(A_c)
## 计算 X_A, A_A , u_A ,the inner product vecto
X_A = np.dot(X[:, A], s_A).reshape(n, -1)
G_A = np.dot(X_A.T, X_A)
One_A = np.ones((len(A), 1))
s = One_A.copy()
if G_A.shape == ():
inv_GA = 1 / G_A
else:
inv_GA = np.linalg.pinv(G_A)
# G_a_inv_red_cols = np.sum(inv_GA, 1)
A_A = 1 / np.sqrt(np.dot(s.T, inv_GA).dot(s))
w_A = (A_A * inv_GA).dot(s) # w_A: (less then 90%)构成等角的单位向量
u_A = np.dot(X_A, w_A) # .reshape(n)
a = X.T.dot(u_A) # inner product vector
gamma_Test = np.zeros((num_Zero_Coeff, 2))
# gamma=[]
# if k == m - 1 - limit_m:
if N_Co_added == m - 1:
gamma = C / A_A
else:
for j in range(num_Zero_Coeff):
j_p = A_c[j]
first_term = (C - c[j_p]) / (A_A - a[j_p])
second_term = (C + c[j_p]) / (A_A + a[j_p])
gamma_Test[j, :] = np.array([first_term, second_term]).reshape(1, -1)
gamma, min_i, min_j = min_pos(gamma_Test)
# gamma.append(m_s)
try:
addTndex = A_c[np.min(min_i)]
except:
print(123)
beta_temp = np.zeros((m, 1))
beta_temp[A] = beta[k, A].reshape(-1, 1) + np.dot(s_A, gamma * w_A)
beta = np.vstack((beta, beta_temp.transpose())) # 更新的系数即故障f
return beta, mse
def recon_fault_diagnosis_r(x, m, limit_line, beta_value, model, spe_recon, m_spe, rbc=None):
"""基于重构的故障诊断,重构故障>3
"""
k_p = int(model["K"])
count = 0
dimension = x.shape[0]
if rbc is None:
fault_para = sorted(beta_value, key=lambda item: item[1], reverse=True)
else:
fault_para = sorted(rbc, key=lambda item: item[1], reverse=True)
fault_para_index_temp = [item[0] for item in fault_para]
fault_para_index = [fault_para_index_temp[: i] for i in range(1, len(beta_value) + 1)][::-1]
fault_matrix, fault_index_recon = [], []
for item in fault_para_index:
ke_si_matrix = np.zeros(shape=(dimension, dimension))
k_matrix = np.zeros(shape=(dimension, 1))
for i in range(dimension):
ke_si = np.zeros(shape=(dimension, 1))
ke_si_i = np.zeros(shape=(dimension, 1)) # 每一行的fai对应的ke_si
if i in item:
ke_si_i[i] = 1 # 计算每一行的ke_si
fai = m @ ke_si_i @ np.linalg.pinv(ke_si_i.T @ m @ ke_si_i) # 计算每一行的fai
for j in range(dimension):
ke_si_j = ke_si.copy() # 每一行每一列的ke_si
if i == j:
ke_si_matrix[i, j] = 1 # ke_si矩阵对角线元素全为1
else:
if j in item:
ke_si_j[j] = 1
ke_si_matrix[i, j] = ke_si_j.T @ fai # 计算矩阵其他元素
k_matrix[i] = x.T @ fai # 计算k 矩阵
if np.linalg.det(ke_si_matrix) > 1e-15 and len(item) <= ke_si_matrix.shape[0] - k_p:
f_matrix = np.linalg.pinv(ke_si_matrix) @ k_matrix # 计算f 矩阵
else:
continue
f_matrix_1 = np.zeros(shape=(dimension, 1))
for k in item:
f_matrix_1[k] = f_matrix[k]
if ((x - f_matrix_1.T) @ m @ (x - f_matrix_1.T).T)[0][0] < limit_line:
count += 1
fault_matrix = f_matrix_1
fault_index_recon = item
else:
return fault_matrix, np.array(fault_index_recon)
return fault_matrix, np.array(fault_index_recon) # 没有找到故障
def recon_fault_diagnosis_r_l(x, m, fault_index: "list"):
"""基于重构的故障诊断,重构故障<=3,或者是直接用于fai后的spe重构
"""
dimension = x.shape[0]
item = fault_index.copy()
ke_si_matrix = np.zeros(shape=(dimension, dimension))
k_matrix = np.zeros(shape=(dimension, 1))
for i in range(dimension):
ke_si = np.zeros(shape=(dimension, 1))
ke_si_i = np.zeros(shape=(dimension, 1)) # 每一行的fai对应的ke si
if i in item:
ke_si_i[i] = 1 # 计算每一行的ke_si
fai = m @ ke_si_i @ np.linalg.pinv(ke_si_i.T @ m @ ke_si_i) # 计算每一行的fai
for j in range(dimension):
ke_si_j = ke_si.copy() # 每一行每一列的ke si
if i == j:
ke_si_matrix[i, j] = 1 # ke_si矩阵对角线元素全为1
else:
if j in item:
ke_si_j[j] = 1
ke_si_matrix[i, j] = ke_si_j.T @ fai # 计算矩阵其他元素
k_matrix[i] = x.T @ fai # 计算k 矩阵
f_matrix = np.linalg.pinv(ke_si_matrix) @ k_matrix # 计算f 矩阵
f_matrix_1 = np.zeros(shape=(dimension, 1))
for k in fault_index:
f_matrix_1[k] = f_matrix[k]
fault_matrix = f_matrix_1
return fault_matrix, np.array(fault_index) # 没有找到故障
def recon_fault_diagnosis_r_c(x, m, limit_line, beta_value, model, spe_recon, m_spe, lock_variable,
selectVec, rbc=None):
"""基于重构的故障诊断,重构故障>3
"""
k_p = int(model["K"])
count = 0
dimension = x.shape[0]
if rbc is None:
fault_para = sorted(beta_value, key=lambda item: item[1], reverse=True)
else:
fault_para = sorted(rbc, key=lambda item: item[1], reverse=True)
fault_para_index_temp = [item[0] for item in fault_para]
fault_para_index = [fault_para_index_temp[: i] for i in range(1, len(beta_value) + 1)][::-1]
fault_matrix, fault_index_recon = [], []
for item in fault_para_index:
ke_si_matrix = np.zeros(shape=(dimension, dimension))
k_matrix = np.zeros(shape=(dimension, 1))
for i in range(dimension):
ke_si = np.zeros(shape=(dimension, 1))
ke_si_i = np.zeros(shape=(dimension, 1)) # 每一行的fai对应的ke_si
if i in item:
ke_si_i[i] = 1 # 计算每一行的ke_si
fai = m @ ke_si_i @ np.linalg.pinv(ke_si_i.T @ m @ ke_si_i) # 计算每一行的fai
for j in range(dimension):
ke_si_j = ke_si.copy() # 每一行每一列的ke_si
if i == j:
ke_si_matrix[i, j] = 1 # ke_si矩阵对角线元素全为1
else:
if j in item:
ke_si_j[j] = 1
ke_si_matrix[i, j] = ke_si_j.T @ fai # 计算矩阵其他元素
k_matrix[i] = x.T @ fai # 计算k 矩阵
if np.linalg.det(ke_si_matrix) > 1e-15 and len(item) <= ke_si_matrix.shape[0] - k_p:
f_matrix = np.linalg.pinv(ke_si_matrix) @ k_matrix # 计算f 矩阵
else:
# 如果矩阵不可逆则使用贡献图法进行重构
res = contribution_plot(x, model, lock_variable, selectVec)
return res, "plot" # 返回故障幅值和故障参数
f_matrix_1 = np.zeros(shape=(dimension, 1))
for k in item:
f_matrix_1[k] = f_matrix[k]
if ((x - f_matrix_1.T) @ m @ (x - f_matrix_1.T).T)[0][0] < limit_line:
count += 1
fault_matrix = f_matrix_1
fault_index_recon = item
else:
return fault_matrix, np.array(fault_index_recon)
return fault_matrix, np.array(fault_index_recon) # 没有找到故障
def contribution_plot(x, model, lock_variable, select_vec):
"""贡献图法直接计算重构值"""
final_data = np.dot(x, select_vec).dot(select_vec.T)
final_data[lock_variable] = x[lock_variable]
recon_data = np.add(np.multiply(final_data, model["Train_X_std"]), model["Train_X_mean"]) # 重构值
return recon_data