![](/img/trans.png)
[英]Why do I get a Theano TypeError when trying to update a shared variable?
[英]When I send a numpy array to a givens parameter in a theano function, why do I get this Theano TypeError
我是theano的新手,一方面仍在努力解決theano的“偽代碼”風格,另一方面仍在進行嚴格的類型檢查。 我更多是C程序員和python程序員。 有人可以指出在此示例代碼中哪里出了問題,該示例代碼使用預測的y點與訓練y點之間的均方誤差作為x值,以獲得線性擬合的最佳斜率和截距?
代碼如下:
import numpy as np
import theano
import theano.tensor as T
from collections import OrderedDict
class LinearModel:
def __init__(self,num_points):
self.m = theano.shared(value=0.1,name='m')
self.b = theano.shared(value=1, name='b')
self.params = [self.m, self.b]
def step(x_t):
y_t = self.m * x_t + self.b
return y_t
self.x = T.matrix('x',dtype=theano.config.floatX)
self.y, _ = theano.scan(
fn=step,
sequences=self.x,
)
self.loss = lambda y_train: self.mse(y_train)
def mse(self, y_train):
return T.mean((self.y - y_train) ** 2)
def fit(self,x, y, learning_rate=0.01, num_iter=100):
trainset_x = theano.tensor._shared(x.astype(np.dtype(np.float32)),borrow=True)
trainset_y = theano.tensor._shared(y.astype(np.dtype(np.float32)),borrow=True)
n_train = trainset_x.get_value(borrow=True).shape[0]
cost = self.loss(trainset_y)
gparams = T.grad(cost,self.params)
l_r = T.scalar('l_r', dtype=theano.config.floatX)
updates = OrderedDict()
for param,gparam in zip(self.params,gparams):
updates[param] = param - l_r * gparam
self.train_model = theano.function( inputs=[l_r],
outputs=[cost,self.y],
updates=updates,
givens={
self.x: trainset_x,
}
)
epoch = 0
while epoch < num_iter:
cost, _ = self.train_model(learning_rate)
m = self.m.get_value()
b = self.b.get_value()
print "epoch: ",epoch," cost: ",cost," m: ",m," b: ",b
if __name__ == '__main__':
lin = LinearModel(10)
x = np.arange(10)
y = np.random.rand(10)
lin.fit(x,y,learning_rate=0.01,num_iter=100)
錯誤是:
追溯(最近一次通話):文件“〜/ EclipseWorkspace / MemoryNetworkQA.Theano / linear_regression.py”,第70行,位於lin.fit(x,y,learning_rate = 0.01,num_iter = 100)文件“〜/ EclipseWorkspace / MemoryNetworkQA .theano / linear_regression.py”,第54行,適合self.x:trainset_x,文件“ /usr/local/lib/python2.7/dist-packages/theano/compile/function.py”,第266行,在函數中profile = profile)文件“ /usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py”,行489,在pfunc中no_default_updates = no_default_updates)文件“ / usr / local / lib / python2。 7 / dist-packages / theano / compile / pfunc.py“,第217行,位於rebuild_collect_shared中,引發TypeError(err_msg,err_sug)
TypeError :('更新必須與原始共享變量具有相同的類型(shared_var = b,shared_var.type = TensorType(int64,標量),update_val = Elemwise {sub,no_inplace} .0,update_val.type = TensorType(float64 ,標量))。','如果差異與廣播模式有關,則可以調用tensor.unbroadcast(var,axis_to_unbroadcast [,...])函數刪除可廣播的尺寸。')
在解決以下問題之前,該代碼將不會執行。
在問題報告的錯誤是由於類型self.b
不匹配的更新類型self.b
。 self.b
沒有指定類型,因此可以推斷出一個。 初始值為Python整數,因此推斷的類型為int64
。 由於學習率是floatX
所以更新為floatX
。 您不能使用floatX
更新int64
。 解決方案是將初始值設為Python浮點數,從而得出推斷的floatX
類型。 將self.b = theano.shared(value=1, name='b')
更改為self.b = theano.shared(value=1., name='b')
(注意1
后面的小數點)。
下一個問題是self.x
被定義為矩陣,但是在最后一行的函數調用中傳遞的值是向量。 一種解決方案是將x
重塑為矩陣,例如將x = np.arange(10)
更改為x = np.arange(10).reshape(1,10)
。
訓練集共享變量的類型為float32
但這與使用floatX
的代碼的其他區域沖突。 如果您的floatX=float32
則應該沒有問題,但是更簡單地使用floatX
來始終保持相同的float類型會更安全。 將trainset_x = theano.tensor._shared(x.astype(np.dtype(np.float32)),borrow=True)
更改trainset_x = theano.tensor._shared(x.astype(theano.config.floatX),borrow=True)
,同樣適用於trainset_y
。
當前的時期數沒有任何效果,因為沒有增加epoch
。 while epoch < num_iter:
更改for epoch in xrange(num_iter):
中的epoch = 0
並刪除epoch = 0
。
此外,
參數看起來好像沒有更新,但這是一個錯誤的視圖。 由於上面的問題4,迭代很快通過並且永不停止,並且學習率足夠大,可以使模型非常快速地收斂。 嘗試將學習率更改為較小的值,例如0.0001,然后僅查看前100個時期的輸出。
我建議避免使用theano.tensor._shared
除非您確實需要在device=gpu
時強制將共享變量分配到CPU上。 首選方法是theano.shared
。
n_train
變量沒有在任何地方使用。
您正在使用givens
不一致。 我建議將其同時用於x
和y
,或者都不使用。 看看Logistic回歸教程,以獲取更多有關此方面的指導。
Theano函數在每次fit
調用時都會重新編譯,但最好只編譯一次,並在每次fit
重新使用。
無需使用scan
即可實現此模型。 通常,通常僅在步驟的輸出是先前步驟的輸出的函數時才需要scan
。 scan
通常也比其他方法慢得多,應盡可能避免。 您可以self.y = self.m * self.x + self.b
使用self.y = self.m * self.x + self.b
刪除scan
。
如果您確實使用掃描,則最好通過在scan
調用中使用strict=True
啟用嚴格模式。
最好為所有共享變量提供類型。 你做到這一點的trainset_x
和trainset_y
但不self.m
和self.b
。
好的,我發現問題確實出在自我上。b。 用顯式float對其進行初始化后,類型錯誤消失了。
但是仍然是theano共享變量並通過更新傳遞的斜率和截距(self.m和self.b)並沒有真正得到更新。 如果有人能告訴我原因,那將是很大的幫助。 謝謝。
import numpy as np
import theano
import theano.tensor as T
from collections import OrderedDict
class LinearModel:
def __init__(self,num_points):
self.m = theano.shared(value=0.1,name='m')
self.b = theano.shared(value=1.0, name='b')
self.params = [self.m, self.b]
def step(x_t):
y_t = self.m * x_t + self.b
return y_t
#self.x = T.matrix('x',dtype=theano.config.floatX)
#self.x = T.dmatrix('x')
self.x = T.vector('x',dtype=theano.config.floatX)
self.y, _ = theano.scan(
fn=step,
sequences=self.x,
)
self.loss = lambda y_train: self.mse(y_train)
def mse(self, y_train):
return T.mean((self.y - y_train) ** 2)
def fit(self,x, y, learning_rate=0.01, num_iter=100):
trainset_x = theano.tensor._shared(x.astype(np.dtype(np.float32)),borrow=True)
trainset_y = theano.tensor._shared(y.astype(np.dtype(np.float32)),borrow=True)
n_train = trainset_x.get_value(borrow=True).shape[0]
cost = self.loss(trainset_y)
gparams = T.grad(cost,self.params)
l_r = T.scalar('l_r', dtype=theano.config.floatX)
updates = OrderedDict()
for param,gparam in zip(self.params,gparams):
updates[param] = param - l_r * gparam
self.train_model = theano.function( inputs=[l_r],
outputs=[cost,self.y],
updates=updates,
givens={
self.x: trainset_x,
}
)
epoch = 0
while epoch < num_iter:
cost, _ = self.train_model(learning_rate)
m = self.m.get_value()
b = self.b.get_value()
print "epoch: ",epoch," cost: ",cost," m: ",m," b: ",b
epoch += 1
if __name__ == '__main__':
lin = LinearModel(10)
x = np.array([1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0])
y = np.random.rand(10)
lin.fit(x,y,learning_rate=0.01,num_iter=100)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.