栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python 灰色关联度 & 灰色预测模型

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python 灰色关联度 & 灰色预测模型

灰色关联度

灰色关联度常用于分析影响因子与被影响因子的关联,是水论文的好东西

import numpy as np


def gray_correlation(refer, data, rho=0.5):
    ''' refer: 参照数列 (列向量)
        data: 比较数列 (以列为单位)
        rho: 分辨率
        return: 灰色关联度'''
    # 确保参照数列为列向量
    refer = refer.reshape(-1, 1)
    # 数列间的绝对距离
    distance = np.abs(data - refer)
    dis_min = distance.min()
    dis_max = rho * distance.max()
    # 关联系数: 比较数列中每个值与参照数列的关联性
    cor_param = (dis_min + dis_max) / (distance + dis_max)
    # 关联度: 关联系数按列求平均
    degree = cor_param.mean(axis=0)
    return degree

求解示例:

x0 = np.array([9, 9, 9, 9, 9, 9, 9])
xk = np.array([[8, 9, 8, 7, 5, 2, 9],
               [7, 8, 7, 5, 7, 3, 8],
               [9, 7, 9, 6, 6, 4, 7],
               [6, 8, 8, 8, 4, 3, 6],
               [8, 6, 6, 9, 8, 3, 8]])

# 比较数列 xk 应以列为单位, 故转置
degree = gray_correlation(x0, xk.T)
print(degree)

# OUTPUT: [0.71313131 0.61424774 0.68020215 0.5986346  0.68266821]

灰色预测模型
import logging
import warnings

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

warnings.filterwarnings('ignore')
logging.basicConfig(format='%(message)s', level=logging.INFO)
LOGGER = logging.getLogger(__name__)

三种灰色数列的计算

# 灰积分: 累加数列
integrade = np.cumsum(seq)

# 灰微分: 差分数列
diff = np.diff(seq)

def gray_poly(seq, alpha=0.5):
    ''' return: 灰多项式 (加权邻值生成数列)'''
    part_1 = alpha * seq[1:]
    part_2 = (1 - alpha) * seq[:-1]
    return part_1 + part_2

模型建立步骤:

  1. 记时间序列 x 的长度为 n,计算级比序列:
  2. 可容覆盖区间:,若  均在该区间内,则级比检验成功
  3. 灰导数 diff:时间序列 -> 累加数列 -> 差分数列
  4. 白化背景值 white:时间序列 -> 累加数列 -> 灰多项式
  5. 求解灰微分方程:diff + a · white = b,得到 a 和 b
  6. 白化模型预测函数:
  7. 相对残差:,均小于 0.1 则认为达到较高要求,均小于 0.2 则认为达到一般要求
  8. 级比偏差:,均小于 0.1 则认为达到较高要求,均小于 0.2 则认为达到一般要求

灰色预测模型一步到位代码如下:

def gray_model(seq, alpha=0.5, decimals=4, show=False):
    ''' 灰色预测模型建立
        seq: 原始序列
        alpha: 灰多项式权值
        decimals: 数值精度
        show: 绘制真实值和预测值的对比图
        return: 灰色预测模型, 模型信息'''
    seq = seq.reshape(-1)
    length = len(seq)
    index = np.arange(1, length + 1, 1)
    # 创建数据存储表单
    model_info = pd.DataFrame(index=index, columns=['真实值', '模型值', '相对误差', '级比偏差'])
    model_info['真实值'] = seq
    # 级比: x(k-1) / x(k)
    mag_ratio = seq[:-1] / seq[1:]
    mr_right = round(mag_ratio.max(), decimals)
    mr_left = round(mag_ratio.min(), decimals)
    # 级比检验的区间边界
    left = round(np.exp(- 2 / (length + 1)), decimals)
    right = round(np.exp(2 / (length + 1)), decimals)
    # 级比检验: 检验数列级比是否都落在可容覆盖区间
    LOGGER.info('n'.join(['级比检验:', f'MR ∈ [{mr_left}, {mr_right}]',
                           f'Border ∈ [{left}, {right}]', '']))
    assert mr_left >= left and mr_right <= right, '序列未通过级比检验, 可通过平移变换改善'
    # 灰积分: 累加数列
    integrade = np.cumsum(seq)
    # 灰微分: 差分数列
    diff = np.diff(integrade)
    # 灰多项式: 加权邻值生成数列
    white = alpha * integrade[1:] + (1 - alpha) * integrade[:-1]
    # 求解灰微分方程: diff + a * white = b
    hidden = np.stack([-white, np.ones(white.shape)], axis=0)
    # shape: [2, n] × [n, 2] × [2, n] × [n, ] -> [2, ]
    a, b = (np.linalg.inv(hidden @ hidden.T) @ hidden @ diff)
    LOGGER.info('n'.join([f'发展灰度: {a}', f'内生控制灰度: {b}']))
    model_info['模型值'][1] = seq[0]
    c2 = b / a
    c1 = seq[0] - c2

    def inte_pred(time):
        ''' 白化模型预测函数
            time: 序列首个值对应的时间为 1'''
        return c1 * (np.exp(- a * (time - 1)) - np.exp(- a * (time - 2)))

    LOGGER.info(
        f'预测方程: x(t) = {round(c1, decimals)}·[e^({-round(a, decimals)}(t-1)) - e^({-round(a, decimals)}(t-2))]n')
    # 得到白化模型预测值
    origin = seq[1:]
    prediction = inte_pred(index[1:])
    model_info['模型值'][1:] = np.round(prediction, decimals)

    def check(error, label):
        model_info[label][1:] = error
        # 相对残差 / 级比偏差: < 0.1 达到较高要求, < 0.2 达到一般要求
        if np.all(error < 0.1):
            model_info[label][1] = 'Excelent'
        elif np.all(error < 0.2):
            model_info[label][1] = 'Common'
        else:
            model_info[label][1] = False

    # 计算得到误差信息
    rela_error = np.round(np.abs((origin - prediction) / origin), decimals)
    check(rela_error, '相对误差')
    radio_error = np.round(np.abs(1 - (1 - 0.5 * a) / (1 + 0.5 * a) * mag_ratio), decimals)
    check(radio_error, '级比偏差')
    LOGGER.info(model_info)
    if show:
        # 绘制真实值和预测值的对比图
        plt.plot(index, model_info['真实值'], c='deepskyblue', label='true')
        plt.scatter(index, model_info['模型值'], c='orange', label='pred', marker='p')
        plt.legend()
        plt.show()
    return inte_pred, model_info

求解示例:

data = np.array([71.1, 72.4, 72.4, 72.1, 71.4, 72.0, 71.6])
# 只给模型提供前 5 个值, 利用后 2 个值验证模型精度
pred, model = gray_model(data[:5], decimals=4, alpha=0.5, show=True)
print(f'真实值: {data[-2]}, 模型值: {pred(6)}')
print(f'真实值: {data[-1]}, 模型值: {pred(7)}')

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/849068.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号