Python ScikitLearn回归:设计矩阵X对于回归来说太大了。我该怎么办?
我有一个矩阵Python ScikitLearn回归:设计矩阵X对于回归来说太大了。我该怎么办?,python,numpy,matrix,scikit-learn,regression,Python,Numpy,Matrix,Scikit Learn,Regression,我有一个矩阵X,大约有7000列和38000行。因此,它是一个numpy数组,形状(380007000) 我实例化了模型 model = RidgeCV(alphas = (0.001,0.01, 0.1, 1) 然后装上它 model.fit(X, y) 其中,y是响应向量,它是一个形状为(38000,)的numpy数组 通过运行此命令,我得到一个内存错误 我怎样才能解决这个问题 我的想法 我的第一个想法是“水平”分割矩阵X。我的意思是,我把X分成两个矩阵,两个矩阵的列数相同(因此保留了所
X
,大约有7000列和38000行。因此,它是一个numpy数组
,形状(380007000)
我实例化了模型
model = RidgeCV(alphas = (0.001,0.01, 0.1, 1)
然后装上它
model.fit(X, y)
其中,y
是响应向量,它是一个形状为(38000,)
的numpy数组
通过运行此命令,我得到一个内存错误
我怎样才能解决这个问题
我的想法
我的第一个想法是“水平”分割矩阵X。我的意思是,我把X分成两个矩阵,两个矩阵的列数相同(因此保留了所有特征),但行数较少。那么我每次都要为每个子矩阵拟合模型?但恐怕这并不等于拟合整个矩阵
有什么想法吗?这是一个众所周知的问题,可以通过核心外学习来解决。通过谷歌搜索这个词,你会发现解决这个问题的几种方法 对于您的特定问题,首先必须创建一个生成器,生成矩阵的一行(或多行),然后使用算法的
partial\u fit
方法
scikit learn的标准算法实际上使用了解的精确计算,如sklearn.linear\u model.LinearRegression
或sklearn.linear\u model.LinearRegression.RidgeCV
。其他方法基于批量学习,并具有部分拟合
方法,如sklearn.linear\u model.SGDRegressor
,只允许拟合小批量。这就是你要找的
过程是:使用生成器生成一个小批量,应用partial_fit
方法,从内存中删除该小批量并获取一个新的
但是,由于此方法是随机的,并且取决于数据的顺序和权重的初始化,因此与标准回归方法给出的解决方案相反,标准回归方法可以拟合内存中的所有数据。我将不详细介绍,但看看梯度下降优化,了解它是如何工作的()在我看来,这并不是非常大规模,您可能不需要在这里使用核心外学习(尽管我不知道您有多少内存) 在不需要时使用核心外的方法,您将付出代价(如果不进行大量调优,则不健壮)强> 了解您的特征是稀疏的还是密集的也很有趣,这会产生巨大的差异(因为大多数解算器都可以利用稀疏数据!) 这里有几句话要说:
- 使用一些问题调整的交叉验证方法,可能因为这个原因,没有用于控制底层解算器的参数
- 当有效的热启动有助于过程(性能)时,使用问题调整CV方法并不少见
- 手动执行CV时,sklearn中提供了所有工具,您可以选择不同的工具
- 这些在方法和特点上都有很大的不同
稀疏cg
或者可能lsqr
与手动CV一起使用。如果这样做有效(对我来说非常好),我希望,这种方法更加稳定/稳健(与使用SGD的核心外方法相比),并且您不需要对其参数进行太多调整,这是一个巨大的优势
当然,人们总是可以使用sag
和sgd
,但收敛理论是基于一些关于参数调整的强大假设。在非常大规模的环境中,这两个都是可行的候选人(因为其他人不起作用),但在这里我看不到多少merrit(同样:我不确定你有多少内存)。如果上述方法不起作用,请在sgd之前尝试saga,并遵守规则(标准化+参数调整)。(edit:sag对我的测试数据来说非常糟糕!)
例如:
from sklearn.datasets import make_regression
from sklearn.linear_model import Ridge
from time import perf_counter
X, y, = make_regression(n_samples=38000, n_features=7000, n_informative=500,
bias=-2.0, noise=0.1, random_state=0)
print(type(X)) # dense!!! if your data is sparse; use that fact!
clf = Ridge(alpha=1.0, solver="lsqr")
start = perf_counter()
clf.fit(X, y)
end = perf_counter()
print('LSQR: used secs: ', end-start)
输出:
LSQR: used secs: 8.489622474064486
LSQR: used secs: 0.08252486090450709
train-score: 0.999999907282
sparse_cg: used secs: 0.13668818702548152
train-score: 0.999999181151
SGD: used secs: 0.04154542095705427
train-score: 0.743448766459
SGD: used secs: 0.05300238587407993
train-score: 0.774611911034
SGD: used secs: 0.038653031605587
train-score: 0.733585661919
SGD: used secs: 0.46313909066321507
train-score: 0.776444474871
因此,即使在高密度的情况下,优化也不难(并且使用了约6-8GB的内存)
虽然我会小心地暗示Ridge模型和以下基于SGD的Ridge模型之间的等价性(小心哪个变量是正则化的一部分;太懒了以至于无法检查),但这里只是一个演示如何调整SGD。把这个和一粒盐一起吃(和
LSQR: used secs: 0.08252486090450709
train-score: 0.999999907282
sparse_cg: used secs: 0.13668818702548152
train-score: 0.999999181151
SGD: used secs: 0.04154542095705427
train-score: 0.743448766459
SGD: used secs: 0.05300238587407993
train-score: 0.774611911034
SGD: used secs: 0.038653031605587
train-score: 0.733585661919
SGD: used secs: 0.46313909066321507
train-score: 0.776444474871