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.
436 lines
17 KiB
436 lines
17 KiB
# -*- coding: utf-8 -*-
|
|
"""
|
|
Created on Sun Feb 28 10:04:26 2016
|
|
PCA source code————最新更新————————————————————————————
|
|
@author: liudiwei
|
|
"""
|
|
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
from scipy.stats import norm
|
|
from scipy.stats.distributions import chi2
|
|
import json
|
|
import sys
|
|
import pymssql
|
|
import requests
|
|
import datetime
|
|
from scipy.stats import norm
|
|
from scipy.stats import f
|
|
from scipy.stats import chi2
|
|
import jenkspy
|
|
import xlrd
|
|
import gc
|
|
import time
|
|
import pyodbc
|
|
from recon import Lars, recon_fault_diagnosis_r, recon_fault_diagnosis_r_l, recon_fault_diagnosis_r_c
|
|
import config
|
|
|
|
|
|
"""
|
|
参数:
|
|
- XMat:传入的是一个numpy的矩阵格式,行表示样本数,列表示特征
|
|
- k:表示取前k个特征值对应的特征向量
|
|
返回值:
|
|
- finalData:参数一指的是返回的低维矩阵,对应于输入参数二
|
|
- reconData:参数二对应的是移动坐标轴后的矩阵
|
|
"""
|
|
|
|
|
|
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))
|
|
# A = []
|
|
# N_Co_added = 0
|
|
# i = 0
|
|
# mse = []
|
|
# limit_m=len(LockVariable)
|
|
# for k in range(m-limit_m):
|
|
# 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)
|
|
# addTndex = A_c[np.min(min_i)]
|
|
# 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
|
|
|
|
|
|
# import sklearn
|
|
# q=sklearn.linear_model.Lars
|
|
|
|
|
|
class MSSQL:
|
|
def __init__(self,host,user,pwd,database):
|
|
self.host = host
|
|
self.user = user
|
|
self.pwd = pwd
|
|
self.db = database
|
|
|
|
def __GetConnect(self):
|
|
"""
|
|
得到连接信息
|
|
返回: conn.cursor()
|
|
"""
|
|
if not self.db:
|
|
raise(NameError,"没有设置数据库信息")
|
|
self.conn = pymssql.connect(host=self.host,user=self.user,password=self.pwd,database=self.db,charset="utf8")
|
|
cur = self.conn.cursor()
|
|
if not cur:
|
|
raise(NameError,"连接数据库失败")
|
|
else:
|
|
return cur
|
|
|
|
def ExecQuery(self,sql):
|
|
"""
|
|
执行查询语句
|
|
返回的是一个包含tuple的list,list的元素是记录行,tuple的元素是每行记录的字段
|
|
"""
|
|
cur = self.__GetConnect()
|
|
cur.execute(sql)
|
|
resList = cur.fetchall()
|
|
|
|
#查询完毕后必须关闭连接
|
|
self.conn.close()
|
|
return resList
|
|
|
|
def ExecNonQuery(self,sql):
|
|
"""
|
|
执行非查询语句
|
|
|
|
调用示例:
|
|
cur = self.__GetConnect()
|
|
cur.execute(sql)
|
|
self.conn.commit()
|
|
self.conn.close()
|
|
"""
|
|
cur = self.__GetConnect()
|
|
cur.execute(sql)
|
|
self.conn.commit()
|
|
self.conn.close()
|
|
|
|
def get_model_by_ID(model_id):
|
|
ms = MSSQL(host=config._SQL_IP, user="sa", pwd="powerSIS#123", database="alert")
|
|
resList = ms.ExecQuery("SELECT Model_info FROM [alert].[dbo].[Model_CFG] where \"model_id\"="+str(model_id))
|
|
#return json.loads(resList[0][0])["para"]
|
|
return json.loads(resList[0][0])
|
|
|
|
|
|
def get_model_by_id(model_id):
|
|
try:
|
|
conn = pyodbc.connect(
|
|
r"DRIVER={ODBC Driver 17 for SQL Server};SERVER=%s;DATABASE=alert;UID=sa;PWD=powerSIS#123" % config._SQL_IP) # 连接数据库
|
|
except pyodbc.Error:
|
|
conn = pyodbc.connect(
|
|
r"DRIVER={SQL SERVER NATIVE CLIENT 10.0};SERVER=%s;DATABASE=alert;UID=sa;PWD=powerSIS#123" % config._SQL_IP) # 连接数据库
|
|
cursor = conn.cursor() # 获得操作的游标
|
|
cursor.execute(f"SELECT Model_info FROM [alert].[dbo].[Model_CFG] where model_id={model_id}")
|
|
res_list = cursor.fetchall() # 获取查询的结果
|
|
conn.commit() # 提交执行
|
|
cursor.close() # 关闭游标
|
|
conn.close() # 关闭数据库连接
|
|
return json.loads(res_list[0][0])
|
|
|
|
|
|
def get_model_by_id_and_version(model_id, version):
|
|
try:
|
|
conn = pyodbc.connect(
|
|
r"DRIVER={ODBC Driver 17 for SQL Server};SERVER=%s;DATABASE=alert;UID=sa;PWD=powerSIS#123" % config._SQL_IP) # 连接数据库
|
|
except pyodbc.Error:
|
|
conn = pyodbc.connect(
|
|
r"DRIVER={SQL SERVER NATIVE CLIENT 10.0};SERVER=%s;DATABASE=alert;UID=sa;PWD=powerSIS#123" % config._SQL_IP) # 连接数据库
|
|
cursor = conn.cursor() # 获得操作的游标
|
|
cursor.execute(f"SELECT Model_info FROM [alert].[dbo].[Model_Version] where model_id={model_id} and version='{version}'")
|
|
res_list = cursor.fetchall() # 获取查询的结果
|
|
conn.commit() # 提交执行
|
|
cursor.close() # 关闭游标
|
|
conn.close() # 关闭数据库连接
|
|
return json.loads(res_list[0][0])
|
|
|
|
|
|
# def recon_fault_diagnosis_r(x, m, limit_line, beta_value, model, spe_recon, m_spe, rbc=None):
|
|
#
|
|
# """基于重构的故障诊断,重构故障>3
|
|
# """
|
|
# k_p = int(model["K"])
|
|
# 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:
|
|
# 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 pca(model,LockVariable, Data_origin):
|
|
Data = (Data_origin - model["Train_X_mean"]) / model["Train_X_std"]
|
|
featValue = np.array(model["featValue"]) # 训练数据的特征值
|
|
featVec = np.array(model["featVec"]) # 训练数据的特征向量
|
|
k = (model["K"]) # 主元个数
|
|
# selectVec = np.array(model["selectVec"])
|
|
selectVec = featVec[:, 0:k]####自己选择的
|
|
# index = np.argsort(-np.array(featValue)) # 按照featValue进行从大到小排序
|
|
featValue_sort = featValue#[index] # 排序后的特征值
|
|
'''
|
|
featValue, featVec = np.linalg.eig(model["COV"]) # 求解协方差矩阵的特征值和特征向量
|
|
|
|
index = np.argsort(-featValue) # 按照featValue进行从大到小排序
|
|
featValue_sort =featValue[index]#排序后的特征值
|
|
selectVec = np.matrix(featVec[:,index[:int(model["K"])]]) # 所以这里需要进行转置P
|
|
'''
|
|
############----------*********-SPE-**************----------########################
|
|
numbel_variable = featValue.shape[0]
|
|
# LockVariable="3,5"
|
|
|
|
C_ = np.eye(numbel_variable) - np.dot(selectVec, selectVec.T)
|
|
X_SPE = C_.T
|
|
D_SPE = C_
|
|
DIAG_SPE = np.eye(numbel_variable)
|
|
|
|
'''
|
|
# ************************调用LARS*******************************
|
|
t = 50000
|
|
lamuta = 1
|
|
limit_line = model["QCUL_99"]
|
|
beta_path=[]
|
|
for i in range(Data.shape[0]):
|
|
Y=Data[i,:]
|
|
beta, mse=Lars(X_SPE, Y, D_SPE, DIAG_SPE, t, limit_line, lamuta)
|
|
beta_end=abs(beta[-1,:])
|
|
jenk=jenkspy.jenks_breaks(beta_end,5)
|
|
limt=(jenk[1]+jenk[2])/2
|
|
index=np.where(beta_end>limt)[0]
|
|
beta_path.append(beta[-1,:])
|
|
'''
|
|
############----------*********-T2-**************----------########################
|
|
DIAG_T2 = np.linalg.pinv(np.diag(featValue_sort[:int(model["K"])]))
|
|
D_T2 = selectVec.copy()
|
|
X_T2 = np.dot(D_T2, np.linalg.cholesky(DIAG_T2)).T
|
|
|
|
############----------*********-综合指标-**************----------########################
|
|
II = featValue_sort.copy()
|
|
II[:int(model["K"])] = II[:int(model["K"])] * model["T2CUL_99"]
|
|
II[int(model["K"]):] = model["QCUL_99"]
|
|
DIAG_Fai = np.linalg.pinv(np.diag(II))
|
|
D_Fai = featVec.copy()
|
|
X_Fai = np.dot(D_Fai, np.linalg.cholesky(DIAG_Fai)).T
|
|
# ************************调用LARS*******************************
|
|
t = 50000
|
|
lamuta = 1
|
|
#limit_line = model["Kesi_99"]/np.sqrt(numbel_variable)#修改
|
|
limit_line = model["Kesi_99"]
|
|
beta_path = []
|
|
SPE_list = []
|
|
FAI_list=[]
|
|
paraState = np.zeros([np.array(Data_origin).shape[0], np.array(Data_origin).shape[1]])
|
|
if Data.shape[1] >= 12:
|
|
para_length = 3
|
|
elif 12 > Data.shape[1] >= 7:
|
|
para_length = 2
|
|
else:
|
|
para_length = 1
|
|
Y = None
|
|
plots_matrix = [] # 贡献图法的矩阵
|
|
plots_index = [] # 贡献图法的index
|
|
for i in range(Data.shape[0]):
|
|
Y = Data[i, :] # 测试数据的每一行
|
|
#########*********************计算SPE******************************
|
|
SPE_line = np.dot(Y, C_).dot(Y.T)
|
|
SPE_list.append(SPE_line)
|
|
#########################计算综合指标##########
|
|
FAI_list.append(np.dot(Y.T, D_Fai).dot(DIAG_Fai).dot(D_Fai.T).dot(Y))
|
|
# **************计算LARS***************
|
|
beta, mse = Lars(X_Fai, Y, D_Fai, DIAG_Fai, t, limit_line,LockVariable)
|
|
beta_end = abs(beta[-1, :])
|
|
pi=len(beta_end)
|
|
if pi>7:
|
|
jenk = jenkspy.jenks_breaks(beta_end, 5)
|
|
else:
|
|
jenk = jenkspy.jenks_breaks(beta_end, 2)
|
|
limt = (jenk[1] + jenk[2]) / 2
|
|
index = np.where(beta_end > 0)[0]
|
|
if len(index) > para_length:
|
|
# res = recon_fault_diagnosis_r_c(Y, D_Fai @ DIAG_Fai @ D_Fai.T, limit_line, list(zip(index, beta_end[index])), model,
|
|
# True, X_SPE @ X_SPE.T, rbc=None)
|
|
res = recon_fault_diagnosis_r_c(Y, D_Fai @ DIAG_Fai @ D_Fai.T, limit_line,
|
|
list(zip(index, beta_end[index])), model,
|
|
True, X_SPE @ X_SPE.T, LockVariable, selectVec, rbc=None)
|
|
if not isinstance(res[0], list):
|
|
if res[1] == "plot":
|
|
# beta[-1, :] = res[0]
|
|
plots_matrix.append(res[0])
|
|
plots_index.append(i)
|
|
else:
|
|
beta[-1, :], index = res[0].T, res[1]
|
|
# beta[-1, :], index = res[0].T, res[1]
|
|
elif len(index) <= para_length and len(index) != 0:
|
|
res = recon_fault_diagnosis_r_l(Y, D_Fai @ DIAG_Fai @ D_Fai.T, index)
|
|
beta[-1, :], index = res[0].T, res[1]
|
|
paraState[i, index] = 1
|
|
beta_new=beta[-1, :]*paraState[i,:]
|
|
beta_path.append(beta_new)
|
|
del Y
|
|
gc.collect()
|
|
beta_path = np.array(beta_path)
|
|
################-------------------------------------------------------------###############
|
|
#finalData = np.dot(Data - beta_path, selectVec).dot(selectVec.T)
|
|
finalData=Data - beta_path
|
|
reconData = np.add(np.multiply(finalData, model["Train_X_std"]), model["Train_X_mean"]) # 重构值
|
|
if len(plots_matrix) != 0:
|
|
reconData[plots_index] = plots_matrix
|
|
errorData = Data_origin - reconData # 偏差值
|
|
# cos检验值
|
|
R = 0
|
|
for index in range(0, reconData.shape[1]):
|
|
vector1 = Data_origin[:, index]
|
|
vector2 = np.array(reconData)[:, index]
|
|
R += np.dot(vector1, vector2.T) / (np.sqrt(np.sum(vector1 ** 2)) * np.sqrt(np.sum(vector2 ** 2)))
|
|
R /= reconData.shape[1]
|
|
items = [('reconData', reconData.tolist())
|
|
, ('errorData', errorData.tolist()), ('R', R.tolist()), ('SPE', SPE_list),('FAI', FAI_list),
|
|
('paraState', paraState.tolist())]
|
|
result = json.dumps(dict(items)) # json.dumps(result)
|
|
return result
|
|
|
|
|
|
def get_history_value(points,time,interval):
|
|
#url="http://192.168.1.201:8080/openPlant/getMultiplePointHistorys"
|
|
url=f"http://{config._EXA_IP}:9000/exawebapi/exatime/GetSamplingValueArrayFloat"
|
|
headers = {"Content-Type": "application/json;charset=utf-8"}#,"token":get_token()
|
|
point_array = points.split(",")
|
|
time_span = time.split(";")
|
|
value_array = []
|
|
for item in point_array:
|
|
for time_piece in time_span:
|
|
st = time_piece.split(",")[0]
|
|
et = time_piece.split(",")[1]
|
|
para = {"ItemName": item, "StartingTime": st, "TerminalTime": et, "SamplingPeriod": interval}
|
|
response = requests.get(url, headers=headers, params=para)
|
|
value = eval(str(response.text).replace("\"","").replace("null","0"))
|
|
value_group = []
|
|
for row in value:
|
|
value_group.append(row[1])
|
|
value_array.append(value_group)
|
|
return np.transpose(np.array(value_array))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|