2014-03-31 93 views
3

我試圖運行使用樣本權重的陣列的簡單Sklearn嶺迴歸。 X_train是由100 2D numpy的陣列〜200K。我嘗試使用sample_weight選項時出現內存錯誤。沒有這個選項,它工作得很好。爲了簡單起見,我將特徵減少到2,並且sklearn仍然會引發內存錯誤。 任何想法?sklearn嶺和sample_weight給出內存錯誤

model=linear_model.Ridge() 

model.fit(X_train, y_train,sample_weight=w_tr) 

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/home/g/anaconda/lib/python2.7/site-packages/sklearn/linear_model/ridge.py", line 449, in fit 
    return super(Ridge, self).fit(X, y, sample_weight=sample_weight) 
    File "/home/g/anaconda/lib/python2.7/site-packages/sklearn/linear_model/ridge.py", line 338, in fit 
    solver=self.solver) 
    File "/home/g/anaconda/lib/python2.7/site-packages/sklearn/linear_model/ridge.py", line 286, in ridge_regression 
    K = safe_sparse_dot(X, X.T, dense_output=True) 
    File "/home/g/anaconda/lib/python2.7/site-packages/sklearn/utils/extmath.py", line 83, in safe_sparse_dot 
    return np.dot(a, b) 
MemoryError 

回答

8

設置樣本權重會導致sklearn linear_model Ridge對象處理您的數據的方式存在很大差異 - 尤其是在矩陣較高(n_samples> n_features)的情況下,您的情況更是如此。如果沒有樣本權重將利用以下事實:X.T.dot(X)是一個相對較小矩陣(100×100在您的情況),因此將反轉特徵空間的矩陣。對於給定的樣本權重,Ridge對象決定停留在樣本空間中(爲了能夠單獨對樣本進行加權,請參閱相關行herehere以分支到樣本空間中的_solve_dense_cholesky_kernel),因此需要將矩陣大小相同X.dot(XT)的(在你的情況是N_SAMPLES次X N_SAMPLES次= 200000 X 200000和將導致存儲器錯誤甚至創建之前)。這實際上是一個實施問題,請參閱下面的手動解決方法。

TL; DR:嶺對象是無法治療的特徵空間樣本的權重,並會生成一個矩陣N_SAMPLES次X N_SAMPLES次,這將導致你的內存錯誤

在等待可能的補救辦法中scikit學習,你可以嘗試明確解決在功能空間的問題,像這樣

import numpy as np 
alpha = 1. # You did not specify this in your Ridge object, but it is the default penalty for the Ridge object 
sample_weights = w_tr.ravel() # make sure this is 1D 
target = y.ravel() # make sure this is 1D as well 
n_samples, n_features = X.shape 
coef = np.linalg.inv((X.T * sample_weights).dot(X) + 
         alpha * np.eye(n_features)).dot(sample_weights * target) 

對於新樣本X_new,你的預測是

prediction = np.dot(X_new, coef) 

爲了確認這種方法的有效性,你可以從你的代碼,它適用於樣本數量較少時比較這些COEF到model.coef_(後你有適合的型號)(例如, 300),與Ridge對象一起使用時不會導致內存錯誤。

重要:只以上的代碼與sklearn實現,如果你的數據已經集中,即您的數據必須具有均值爲0實現一個完整的嶺迴歸的截距擬合這裏就等於一個貢獻scikit學習重合,所以最好發帖there。居中數據的方法如下:

X_mean = X.mean(axis=0) 
target_mean = target.mean() # Assuming target is 1d as forced above 

然後,您使用所提供的代碼上

X_centered = X - X_mean 
target_centered = target - target_mean 

有關新數據的預測,您需要

prediction = np.dot(X_new - X_mean, coef) + target_mean 

編輯:作爲2014年4月15日,scikit-learn嶺迴歸可以處理這個問題(出血邊緣代碼)。它將在0.15版本中提供。

+0

感謝@ogrisel爲我指出sklearn線性模型以數據爲中心這一事實 – eickenberg

+0

[此增強建議](https://github.com/scikit-learn/scikit-learn/pull/3034)實現瞭解釋的功能以上。 – eickenberg

+0

scikit學習的最新版本現在支持特徵空間中的樣本權重。 – eickenberg

1

你安裝了什麼NumPy版本?

看起來像最終的方法調用,它是numpy.dot(X, X.T),如果在你的情況下X.shape = (200000,2)會產生一個200k乘200k的矩陣。

嘗試將你的觀察到稀疏矩陣型或減少所使用的觀測次數(也有可能是使用在一個時間一些看法一批嶺迴歸的變體?)。