转载并整理自:
https://www.codenong.com/p12366364/
https://www.codenong.com/p12368419/
灰色关联度分析
# -*- coding: utf-8 -*-
from sklearn.preprocessing import StandardScaler
import pandas as pd
import numpy as np
import os
class GraModel():
'''灰色关联度分析模型'''
def __init__(self, inputData, p=0.5, standard=True):
'''
初始化参数
inputData:输入矩阵,纵轴为属性名,第一列为母序列
p:分辨系数,范围0~1,一般取0.5,越小,关联系数间差异越大,区分能力越强
standard:是否需要标准化
'''
self.inputData = np.array(inputData)
self.p = p
self.standard = standard
# 标准化
self.standarOpt()
# 建模
self.buildModel()
def standarOpt(self):
'''标准化输入数据'''
if not self.standard:
return None
self.scaler = StandardScaler().fit(self.inputData)
self.inputData = self.scaler.transform(self.inputData)
def buildModel(self):
# 第一列为母列,与其他列求绝对差
momCol = self.inputData[:, 0]
sonCol = self.inputData[:, 0:]
for col in range(sonCol.shape[1]):
sonCol[:, col] = abs(sonCol[:, col] - momCol)
# 求两级最小差和最大差
minMin = sonCol.min()
maxMax = sonCol.max()
# 计算关联系数矩阵
cors = (minMin + self.p * maxMax) / (sonCol + self.p * maxMax)
# 求平均综合关联度
meanCors = cors.mean(axis=0)
self.result = {'cors': {'value': cors, 'desc': '关联系数矩阵'}, 'meanCors': {'value': meanCors, 'desc': '平均综合关联系数'}}
if __name__ == "__main__":
# # 路径目录
# curDir = os.path.dirname(os.path.abspath(__file__)) # 当前目录
# baseDir = os.path.dirname(curDir) # 根目录
# staticDir = os.path.join(baseDir, 'Static') # 静态文件目录
# resultDir = os.path.join(baseDir, 'Result') # 结果文件目录
# 读数
data = [
[1, 1.1, 2, 2.25, 3, 4],
[1, 1.166, 1.834, 2, 2.314, 3],
[1, 1.125, 1.075, 1.375, 1.625, 1.75],
[1, 1, 0.7, 0.8, 0.9, 1.2]
]
data = np.array(data).T
# 建模
model = GraModel(data, standard=True)
print(model.result)
灰色预测
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
def GM11(x, n):
'''
灰色预测
x:序列,numpy对象
n:需要往后预测的个数
'''
x1 = x.cumsum() # 一次累加
z1 = (x1[:len(x1) - 1] + x1[1:]) / 2.0 # 紧邻均值
z1 = z1.reshape((len(z1), 1))
B = np.append(-z1, np.ones_like(z1), axis=1)
Y = x[1:].reshape((len(x) - 1, 1))
# a为发展系数 b为灰色作用量
[[a], [b]] = np.dot(np.dot(np.linalg.inv(np.dot(B.T, B)), B.T), Y) # 计算参数
result = (x[0] - b / a) * np.exp(-a * (n - 1)) - (x[0] - b / a) * np.exp(-a * (n - 2))
S1_2 = x.var() # 原序列方差
e = list() # 残差序列
for index in range(1, x.shape[0] + 1):
predict = (x[0] - b / a) * np.exp(-a * (index - 1)) - (x[0] - b / a) * np.exp(-a * (index - 2))
e.append(x[index - 1] - predict)
S2_2 = np.array(e).var() # 残差方差
C = S2_2 / S1_2 # 后验差比
if C <= 0.35:
assess = '后验差比<=0.35,模型精度等级为好'
elif C <= 0.5:
assess = '后验差比<=0.5,模型精度等级为合格'
elif C <= 0.65:
assess = '后验差比<=0.65,模型精度等级为勉强'
else:
assess = '后验差比>0.65,模型精度等级为不合格'
# 预测数据
predict = list()
for index in range(x.shape[0] + 1, x.shape[0] + n + 1):
predict.append((x[0] - b / a) * np.exp(-a * (index - 1)) - (x[0] - b / a) * np.exp(-a * (index - 2)))
predict = np.array(predict)
return {
'a': {'value': a, 'desc': '发展系数'},
'b': {'value': b, 'desc': '灰色作用量'},
'predict': {'value': result, 'desc': '第%d个预测值' % n},
'C': {'value': C, 'desc': assess},
'predict': {'value': predict, 'desc': '往后预测%d个的序列' % (n)},
}
if __name__ == "__main__":
data = np.array([1.2, 2.2, 3.1, 4.5, 5.6, 6.7, 7.1, 8.2, 9.6, 10.6, 11, 12.4, 13.5, 14.7, 15.2])
x = data[0:10] # 输入数据
y = data[10:] # 需要预测的数据
result = GM11(x, len(y))
predict = result['predict']['value']
predict = np.round(predict, 1)
print('真实值:', y)
print('预测值:', predict)
print(result)