2016-11-09 88 views
0

是否可以設置火炬類的__index方法?我試圖實現一個簡單的dataset類作爲tutoral深學習與火炬概述:(ipynb here設置火炬類的__index

trainset = { 
    inputs = {0, 1, 1, 0}, 
    targets = {1, 1, 1, 0} 
} 

index = function(t, i) 
    return {t.inputs[i], t.targets[i]} 
end 

setmetatable(trainset, { 
    __index = index 
) 

,它允許你做trainset[1]]返回{0, 1}

但是,實現這個作爲火炬類不起作用。

local torch = require("torch") 

do 
    Dataset = torch.class("Dataset") 

    function Dataset:__init(i, t) 
     self.inputs = i 
     self.targets = t 
    end 

    function Dataset.__index(t, v) 
     print("inside index") 
     return { 
      rawget(t, inputs)[v], 
      rawget(t, targets)[v] 
     } 
    end 
end 

Dataset({0, 1, 1, 0}, {1, 1, 1, 0}) -- fails 

看來,在對象創建時,__index()被稱爲和失敗,因爲indextargets尚未創建。如果不使用rawget,則會導致堆棧溢出。

我對Lua的理解是有限的,但我很驚訝地看到__index()在對象創建過程中被調用:我認爲有些事情在後臺我不完全理解。

+1

使用'__index' metamethod只模擬數字鍵是有意義的。我想這將解決這個問題:'如果鍵入(v)=='數字'然後返回{t.inputs [v],t.targets [v]}結束' –

+0

謝謝,這很有用。儘管這不是全部,但還是有一些特定於火炬的問題(請參閱我的回答)。 – mgperry

回答

1

火炬班全部實施__index,它將在metatable中查找__index__,這是用於超載。

docs

如果想提供指數newindex在元類, 這些運營商必須遵循特定的方案:

指數必須要麼返回值和真或僅返回假。在第一種情況下,這意味着索引能夠處理給定的 參數(例如,類型是正確的)。第二種情況意味着它 無法執行任何操作,因此根metatable中的__index可以嘗試查看元類是否包含所需的值。

的例子這意味着,在__index__(不__index!)方法必須檢查是否type(v) == "number"如果沒有,返回false使__index可以尋找對象的metatable的值。

local torch = require("torch") 

do 
    Dataset = torch.class("Dataset") 

    function Dataset:__init(i, t) 
     self.inputs = i 
     self.targets = t 
    end 

function Dataset.__index__(t, v) 
    if type(v) == "number" then 
     local tbl = { 
      t.inputs[v], 
      t.targets[v] 
     } 
     return tbl, true 
    else 
     return false 
    end 
end 

local dset = Dataset({0, 1, 1, 0}, {1, 1, 1, 0}) 
dset[1] --> {0, 1}