You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LinAlgError报错求助:矩阵含inf/NaN致正定化操作失败

问题描述

我下载了2022-09-01至2024-08-20的SPY日度数据,选取Close、High、Volume字段,计算sma_8、sma_13、rsi_14、ema12等指标后,计划进行协整检验(Cointegration Test)并用于VAR模型预测。因矩阵非正定,我尝试替换inf/-inf为NaN、删除缺失值、填充缺失值,并自定义正定化函数处理,但仍触发报错:LinAlgError: Array must not contain infs or NaNs,无法定位问题原因,寻求解决办法。

数据处理代码

data_n = yf.download("SPY",start="2022-09-01",end="2024-08-20",interval="1D")
data_n = data_n[["Close","High","Volume"]]

#data = np.exp(data)
#data.to_csv("DF.csv")

data = data_n.copy()

def calculate_rsi(data, window=14):
    delta = data['Close'].diff()
    gain = (delta.where(delta > 0, 0)).rolling(window=window).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window=window).mean()
    rs = gain / loss
    rsi = 100 - (100 / (1 + rs))
    return rsi

data["sma_8"]=data_n.Close.rolling(8).mean()
data["sma_13"]=data_n.Close.rolling(13).mean()
data['rsi_14'] = calculate_rsi(data)
data['ema12'] = data_n['Close'].ewm(span=4, adjust=False).mean()

data.index = pd.to_datetime(data.index)

正定化处理代码

import numpy as np
from sklearn.datasets import make_spd_matrix

from numpy import inf

data = data.replace([np.inf, -np.inf], np.nan)

data = data.dropna()

data = data.fillna(1e-10)

def make_positive_definite(matrix):
    sym_matrix = (matrix + matrix.T) / 2
    
    min_eig = np.min(np.real(np.linalg.eigvals(sym_matrix)))
    if min_eig < 0:
        sym_matrix -= 10 * min_eig * np.eye(*sym_matrix.shape)
    
    return sym_matrix

data_pos = make_positive_definite(data)
解决思路与方案

1. 排查隐藏的inf/NaN

即使执行了替换和删除操作,仍可能存在未被处理的异常值:

  • 执行以下代码确认数据状态:
    # 检查是否存在inf/NaN
    print(data.isin([np.inf, -np.inf, np.nan]).any())
    # 查看数据统计量,排查异常值
    print(data.describe())
    
  • 问题根源可能在RSI计算:当loss为0时,rs = gain / loss会生成inf,后续替换操作可能因顺序问题未覆盖这些inf。需调整RSI计算逻辑,避免除以0。

2. 修正RSI计算函数

修改calculate_rsi,处理loss为0的边界情况,避免生成inf:

def calculate_rsi(data, window=14):
    delta = data['Close'].diff()
    gain = (delta.where(delta > 0, 0)).rolling(window=window).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window=window).mean()
    
    # 替换loss为0的情况,避免除以0
    rs = gain / loss.replace(0, np.nan)
    rsi = 100 - (100 / (1 + rs))
    
    # 填充缺失值:仅loss为0时RSI=100;gain和loss都为0时RSI=50
    rsi = rsi.fillna(np.where(gain == 0, 50, 100))
    return rsi

3. 调整数据处理顺序

确保异常值处理覆盖所有指标生成后的结果:

  1. 计算所有技术指标
  2. 替换inf/-inf为NaN
  3. 删除含NaN的行(无需再填充,因为dropna()已移除所有缺失值)
    # 正确顺序
    data = data.replace([np.inf, -np.inf], np.nan)
    data = data.dropna()
    # 此时data已无NaN/inf,无需fillna
    

4. 正定化函数的正确使用

  • 传入正定化函数的应为numpy数组,而非DataFrame,避免索引/列名干扰:
    data_array = data.values
    data_pos = make_positive_definite(data_array)
    
  • 若矩阵仍非正定,可尝试更小的调整系数(如将10 * min_eig改为1.01 * min_eig),避免过度修正数据。

5. 重新审视模型前置要求

  • 协整检验不需要矩阵正定,VAR模型要求数据平稳性,而非协方差矩阵正定。若因多重共线性(如sma_8与sma_13高度相关)导致矩阵奇异,建议:
    • 删除高度相关的变量(用data.corr()查看相关性)
    • 对数据进行PCA降维,提取独立主成分后再建模

内容的提问来源于stack exchange,提问作者CuriousRybicka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:17:12