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. 调整数据处理顺序
确保异常值处理覆盖所有指标生成后的结果:
- 计算所有技术指标
- 替换inf/-inf为NaN
- 删除含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
相关产品推荐
相关产品推荐

