当我将一个 numpy 数组发送到 theano 函数中的一个 givens 参数时,为什么我会得到这个 Theano TypeError
When I send a numpy array to a givens parameter in a theano function, why do I get this Theano TypeError
我是 theano 的新手,一方面还在为 theano 的 "pseudo code" 风格和另一方面的严格类型检查而苦苦挣扎。我更像是一名 C 程序员和一名 python 程序员。有人可以指出我在这个示例代码中出错的地方吗,它使用预测的 y 点和 x 值的训练 y 点之间的均方误差,以获得线性拟合的最佳斜率和截距?
代码如下:
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)
错误是:
Traceback (most recent call last): File
"~/EclipseWorkspace/MemoryNetworkQA.Theano/linear_regression.py", line
70, in
lin.fit(x,y,learning_rate=0.01,num_iter=100) File "~/EclipseWorkspace/MemoryNetworkQA.Theano/linear_regression.py", line
54, in fit
self.x: trainset_x, File "/usr/local/lib/python2.7/dist-packages/theano/compile/function.py",
line 266, in function
profile=profile) File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line
489, in pfunc
no_default_updates=no_default_updates) File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line
217, in rebuild_collect_shared
raise TypeError(err_msg, err_sug)
TypeError: ('An update must have the same type as the original shared
variable (shared_var=b, shared_var.type=TensorType(int64, scalar),
update_val=Elemwise{sub,no_inplace}.0,
update_val.type=TensorType(float64, scalar)).', 'If the difference is
related to the broadcast pattern, you can call the
tensor.unbroadcast(var, axis_to_unbroadcast[, ...]) function to remove
broadcastable dimensions.')
在解决以下问题之前,此代码不会执行。
问题中报告的错误是由于 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
.
此外,
参数看起来没有更新,但这是错误的看法。由于上面的问题 4,迭代很快通过并且永不停止,并且学习率足够大以使模型收敛得非常快。尝试将学习率更改为更小的值,例如0.0001,只查看前 100 个时期的输出。
我建议避免使用 theano.tensor._shared
,除非你确实需要在 device=gpu
时强制在 CPU 上分配共享变量。首选方法是 theano.shared
.
n_train
变量未在任何地方使用。
您使用 givens
不一致。我建议将它用于 x
和 y
,或者两者都不用。查看 logistic regression tutorial 以获取更多关于此的指示。
每次调用 fit
时都会重新编译 Theano 函数,但最好只编译一次并在每次 fit
.[=58 时重新使用它=]
无需使用scan
即可实现此模型。通常,scan
通常仅在步骤的输出是先前步骤的输出的函数时才需要。 scan
通常也比替代方案慢得多,应尽可能避免使用。您可以使用 self.y = self.m * self.x + self.b
来删除 scan
。
如果您使用扫描,最好在 scan
调用中通过 strict=True
启用严格模式。
为所有共享变量显式提供类型是一种很好的做法。你这样做是为了 trainset_x
和 trainset_y
但不是为了 self.m
和 self.b
.
好吧,我发现问题真的出在self.b。用显式浮点数初始化后,类型错误消失。
但是斜率和截距(self.m 和 self.b)仍然是 theano 共享变量并且通过更新传入,并没有真正得到更新。如果有人能告诉我原因,那将是一个很大的帮助。谢谢
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)
我是 theano 的新手,一方面还在为 theano 的 "pseudo code" 风格和另一方面的严格类型检查而苦苦挣扎。我更像是一名 C 程序员和一名 python 程序员。有人可以指出我在这个示例代码中出错的地方吗,它使用预测的 y 点和 x 值的训练 y 点之间的均方误差,以获得线性拟合的最佳斜率和截距?
代码如下:
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)
错误是:
Traceback (most recent call last): File "~/EclipseWorkspace/MemoryNetworkQA.Theano/linear_regression.py", line 70, in lin.fit(x,y,learning_rate=0.01,num_iter=100) File "~/EclipseWorkspace/MemoryNetworkQA.Theano/linear_regression.py", line 54, in fit self.x: trainset_x, File "/usr/local/lib/python2.7/dist-packages/theano/compile/function.py", line 266, in function profile=profile) File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 489, in pfunc no_default_updates=no_default_updates) File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 217, in rebuild_collect_shared raise TypeError(err_msg, err_sug)
TypeError: ('An update must have the same type as the original shared variable (shared_var=b, shared_var.type=TensorType(int64, scalar), update_val=Elemwise{sub,no_inplace}.0, update_val.type=TensorType(float64, scalar)).', 'If the difference is related to the broadcast pattern, you can call the tensor.unbroadcast(var, axis_to_unbroadcast[, ...]) function to remove broadcastable dimensions.')
在解决以下问题之前,此代码不会执行。
问题中报告的错误是由于
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
.
此外,
参数看起来没有更新,但这是错误的看法。由于上面的问题 4,迭代很快通过并且永不停止,并且学习率足够大以使模型收敛得非常快。尝试将学习率更改为更小的值,例如0.0001,只查看前 100 个时期的输出。
我建议避免使用
theano.tensor._shared
,除非你确实需要在device=gpu
时强制在 CPU 上分配共享变量。首选方法是theano.shared
.n_train
变量未在任何地方使用。您使用
givens
不一致。我建议将它用于x
和y
,或者两者都不用。查看 logistic regression tutorial 以获取更多关于此的指示。每次调用
fit
时都会重新编译 Theano 函数,但最好只编译一次并在每次fit
.[=58 时重新使用它=]无需使用
scan
即可实现此模型。通常,scan
通常仅在步骤的输出是先前步骤的输出的函数时才需要。scan
通常也比替代方案慢得多,应尽可能避免使用。您可以使用self.y = self.m * self.x + self.b
来删除scan
。如果您使用扫描,最好在
scan
调用中通过strict=True
启用严格模式。为所有共享变量显式提供类型是一种很好的做法。你这样做是为了
trainset_x
和trainset_y
但不是为了self.m
和self.b
.
好吧,我发现问题真的出在self.b。用显式浮点数初始化后,类型错误消失。
但是斜率和截距(self.m 和 self.b)仍然是 theano 共享变量并且通过更新传入,并没有真正得到更新。如果有人能告诉我原因,那将是一个很大的帮助。谢谢
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)