"""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