图形套索数值问题(不是 SPD 矩阵结果)

机器算法验证 回归 套索 图形模型 scikit-学习
2022-04-08 21:15:33

我正在尝试应用glasso一个由 60 多个特征和 30k 多个观察组成的非常简单且稀疏的数据集。如果您有兴趣重现该问题,您可以在此处以 csv 格式找到它。

通过为正则化系数尝试不同的值来使用很少的代码行的sklearn 实现α

for alpha in [0.00000001, 0.0000001, 0.000001, 0.00001, 0.0001]:
    glasso_model = GraphLasso(alpha=alpha, mode='lars', max_iter=2000)
    glasso_model.fit(scaled_train)

我遇到的是该模型无法拟合协方差估计,因为它在引发异常抱怨问题的非 PSD 性质后停止:

/usr/local/lib/python3.4/dist-packages/sklearn/covariance/graph_lasso_.py in graph_lasso(emp_cov, alpha, cov_init, mode, tol, max_iter, verbose, return_costs, eps, return_n_iter)
    245         e.args = (e.args[0]
    246                   + '. The system is too ill-conditioned for this solver',)
--> 247         raise e
    248 
    249     if return_costs:

/usr/local/lib/python3.4/dist-packages/sklearn/covariance/graph_lasso_.py in graph_lasso(emp_cov, alpha, cov_init, mode, tol, max_iter, verbose, return_costs, eps, return_n_iter)
    236                 break
    237             if not np.isfinite(cost) and i > 0:
--> 238                 raise FloatingPointError('Non SPD result: the system is '
    239                                          'too ill-conditioned for this solver')
    240         else:

FloatingPointError: Non SPD result: the system is too ill-conditioned for this solver. The system is too ill-conditioned for this solver

如果我尝试用 sklearn 的另一个函数(顺便说一句,与该graph_lasso过程使用的函数相同)对协方差进行 mle,则该矩阵确实是 PSD。所以,我怀疑问题出在代码计算的某个地方。

现在我在应用该方法之前对数据进行规范化或标准化(零均值,1.0 var),但问题仍然存在。

有什么想法吗?我是否错过了应用玻璃的一些关键点。是否有可能用另一个工具包做一些有意义的事情?

1个回答

我在研究中使用的一些数据遇到了同样的问题——虽然我不太明白是什么在数学/计算上导致了这种情况,但希望我的回答和下面的代码有所帮助:

关于您的问题的两条评论:

  • 原始 CSV 文件包括尚未被贬低或缩放的数据字段。规范化数据是一个有用的步骤,对于某些类型的处理很重要。这可以通过 sklearn StandardScaler() 类来完成。

  • 当经验协方差矩阵具有广泛的特征值范围时,l1 正则化协方差实现似乎对不稳定性很敏感。您的初始数据具有 [0, 3e6] 范围内的特征值。

  • 在对输入数据进行归一化后,经验协方差矩阵的特征值仍然跨越一个相对较大的范围,约为 [0-8]。使用 sklearn.covariance.shrunk_covariance() 函数将其缩小可以使其进入计算上更可接受的范围(根据我的阅读,[0,1] 是理想的,但似乎更大的范围也可以工作)。

如果有人知道导致此错误的数学/计算上发生了什么,以及在输出解释方面缩小协方差矩阵的注意事项是什么,我很想听听您的评论和改进。但是,下面的代码似乎既适用于@rano 提出的问题,也适用于我在研究中遇到的错误(能源市场中大约 10k 的数据样本)。

import numpy as np
import pandas as pd
from sklearn import covariance, preprocessing

myData  = pd.read_csv('Data/weight_comp_simple_prop.df.train.csv')
X = myData.values.astype('float64')
myScaler = preprocessing.StandardScaler()
X = myScaler.fit_transform(X)
emp_cov = covariance.empirical_covariance(X)
shrunk_cov = covariance.shrunk_covariance(emp_cov, shrinkage=0.8) # Set shrinkage closer to 1 for poorly-conditioned data

alphaRange = 10.0 ** np.arange(-8,0) # 1e-7 to 1e-1 by order of magnitude
for alpha in alphaRange:
    try: 
        graphCov = covariance.graph_lasso(shrunk_cov, alpha)
        print("Calculated graph-lasso covariance matrix for alpha=%s"%alpha)
    except FloatingPointError:
        print("Failed at alpha=%s"%alpha)