2015-12-08 72 views
6

我有一個非常大的矩陣我試圖通過glmnet在大量內存的服務器上運行。它工作正常,即使在非常大的數據集到一定點,在這之後我收到以下錯誤:R矢量大小限制:「長矢量(參數5)不支持.C」

Error in elnet(x, ...) : long vectors (argument 5) are not supported in .C 

如果我理解正確的話,這是由R中的限制,不能有任何長度矢量再引起比INT_MAX。那是對的嗎?有沒有可用的解決方案,不需要完全重寫glmnet?做任何其他R口譯員(Riposte等)解決這個限制?

謝謝!

+0

在您的代碼中,您是否執行矩陣的子集化?我可能是錯的,但如果矩陣有超過360億個元素,則不能執行矩陣子集。在這種情況下,你必須將矩陣子集看作是一個巨大的原子向量(事實上它是因爲矩陣只是一個具有dimesion屬性的vecotr)。 – SabDeM

+0

在整個我的代碼中,我使用一個支持bigmatrix的文件來避免這些問題,但是當我運行glmnet時,我必須將它作爲R矩陣傳遞,如下所示:'theMatrix [,]'。 – Danny

+2

嗨Danny。我的評論與問題沒有直接關係,但是它會有所幫助。看看Michael Kane的pirls包 - https://github.com/kaneplusplus/pirls。 Mb這個求解器適用於長載體。 –

回答

4

由於版本3 R支持長向量。長向量由double索引。只要每個維度足夠小以便可由integer索引,則長矩陣可以是矩陣或多於2維陣列的基礎。長向量不能通過.C.Fortran傳遞給本地代碼。您收到的錯誤消息是因爲一個長矢量正通過.C傳遞。

長向量可以通過.Call傳遞。所以,只要glmnet的本地代碼可以支持長向量(64位索引)或者可以修改/編譯以支持它,就只需修改R和glmnet的本地代碼之間的接口即可。您可以在C中手動執行此操作,並且此任務還有一個名爲dotCall64的新程序包。修改接口的一部分是決定何時複製參數 - .C/.Fortran預防性複製,但您不希望在大型數據結構中進行不必要的操作。

我認爲改變glmnet的本地代碼以支持64位索引的難度取決於實際的代碼(我只看過但從未使用過)。將Fortran代碼中的所有整數(或顯式或隱式32位整數)切換爲64位很容易。當一些整數必須保持32位時會出現問題,這會發生,例如,對於從/到R代碼傳遞的整數向量,因爲R使用32位整數(即使在長向量中也是如此)。在glmnet中有這樣的整數向量。修改的難度取決於原始Fortran代碼的乾淨程度(例如,如果它使用單獨的整數變量來索引和訪問整型數組的值等)。

R的子集的實驗性實現,如Riposte,將無濟於事。

+0

感謝您的信息,但是一些挖掘似乎表明,從.C切換到.Call需要對基礎Fortran代碼進行重大更改。這正是我想要避免的。聽起來好像根本沒有適合我需求的解決方案。 – Danny

+1

我已經更新了我的回覆。我認爲難度取決於實際代碼,因此使用該代碼的人可以給出最佳答案。我的猜測是:在編程一兩天之後,你要麼完成它,要麼有一個好的估計。當然,這不應該是一個完整的重寫。 –

+0

這似乎已經做到了!對我來說關鍵是dotCall64軟件包。直接使用.Call有點超出了我現在有時間和複雜性,但是使用dotCall64,我只需重新命名.Fortran調用併爲輸入變量添加一個數據類型列表。識別正確的數據類型需要一些時間,但不是太困難。記憶仍然存在一些問題,但我想我可以解決它們。非常感謝Tomas! – Danny

2

有在?"long vector"一張紙條,上面規定:

However, compiled code typically needs quite extensive changes. Note that the .C and .Fortran interfaces do not accept long vectors, so .Call (or similar) has to be used.

elnet使得.Fortran電話。您必須修改函數以使用.Call,可能通過調用FORTRAN代碼的C封裝器,並可能重寫和編譯相關的FORTRAN代碼來處理長向量。

+0

感謝您的信息,但是一些挖掘似乎表明,從.C切換到.Call需要對基礎Fortran代碼進行重大更改。這正是我想要避免的。聽起來好像根本沒有適合我需求的解決方案。 – Danny

+0

不,如果底層代碼被嵌入到32位向量中,恐怕你會被卡住。 – James