【发布时间】:2015-08-13 10:46:13
【问题描述】:
我正在尝试实现小批量 Kmeans。似乎让我很难过的部分是将小批量指定为 theano 的输入。我有一个带有__init__(self, batch_size, data=None) 函数的KmeansMiniBatch 类,其中data 在这种情况下是小批量,batch_size 是批量的大小。我还有一个 fit_once 函数,它不接受任何参数,而是使用传递给 __init__ 的数据。
我的主要脚本包含以下内容:
X = T.matrix('X', dtype='float64')
mini_batch = T.matrix('X', dtype='float64')
kmeans = KmeansMiniBatch(
batch_size=10000,
data=X
)
func = theano.function(
inputs=[mini_batch],
outputs=kmeans.fit_once(),
givens={
kmeans.X: mini_batch,
}
)
data = load_data()
for i in xrange(30):
func(get_batch(data))
image = Image.fromarray(
tile_raster_images(X=np.transpose(kmeans.D.eval()),
img_shape=(12, 12), tile_shape=(10, 30),
tile_spacing=(1, 1)))
我打算用符号变量 X 初始化一个 KmeansMiniBatch 对象,在每次迭代时它都会被 mini_batch 替换。每个小批量由函数get_batch 生成,该函数基本上将整个数据集作为输入,使用numpy.random.choice 仅返回该数据集的一个子集,即numpy 数组。不幸的是,我似乎无法完成我想要实现的目标,因为上面的代码会导致以下错误消息:
theano.compile.function_module.UnusedInputError: theano.function 被要求创建一个函数来计算给定输入的输出,但索引 0 处提供的输入变量不是计算输出所需的计算图的一部分:X。 要将此错误变为警告,您可以将参数 on_unused_input='warn' 传递给 theano.function。要完全禁用它,请使用 on_unused_input='ignore'。
我不确定为什么会出现此错误,因为我确实将符号变量 X 替换为函数输入 mini_batch。此外,如果我确实设置了on_unused_input='ignore',我在评估kmeans.D.eval() 时会收到以下错误消息:
theano.gof.fg.MissingInputError: ("用于计算 Shape(X) 的图形输入未提供且未指定值。使用 Theano 标志 exception_verbosity='high',有关更多信息这个错误。”, X)
任何帮助将不胜感激!
编辑:
所以我终于让它工作了!我的fit_once 函数用于更新矩阵D,这是KmeanMiniBatch 类的一个属性,但没有返回它,这显然导致theano 抱怨,因为输入确实没有在输出中使用。我所做的是,我将fit_once修改为返回D,这基本上解决了问题。这是我修改后的main
X = T.matrix('X', dtype='float64')
mini_batch = T.matrix('mini_batch', dtype='float64')
kmeans = KmeansMiniBatch(
batch_size=1000,
data=X
)
func = theano.function(
inputs=[mini_batch],
outputs=kmeans.fit_once(),
givens={
X: mini_batch
},
)
data = load_data()
D= None
for i in xrange(30):
D = func(get_batch(data))
image = Image.fromarray(
tile_raster_images(X=np.transpose(D),
img_shape=(12, 12), tile_shape=(10, 30),
tile_spacing=(1, 1)))
image.save('repflds7.png')
显然theano 函数不能很好地与 void python 函数配合使用。
编辑 2:
只是为了进一步阐明我想解决的问题。因此,我正在实现的Kmeans 的版本也称为Vector Quantization,其中字典D 基本上将数据集X 压缩为S。最初,fit_once 与D 相关的部分如下:
self.D = T.dot(self.X, T.transpose(S))
self.D = self.D / T.sqrt(T.sum(T.sqr(self.D), axis=0))
所以基本上,在每次迭代中,字典 D 都会更新,因此返回 D 是没有意义的,我必须这样做才能阻止 theano 抱怨:
self.D = T.dot(self.X, T.transpose(S))
self.D = self.D / T.sqrt(T.sum(T.sqr(self.D), axis=0))
return self.D
D在__init__中初始化如下:
self.D = self.srng.normal(size=(self.dimensions, self.K))
self.D = self.D / T.sqrt(T.sum(T.sqr(self.D), axis=0))
我想要实现的是:
1. 不必返回D,而是更新和评估D,然后我可以通过kmeans.D检索
2. 我不是要选择将D 作为符号变量吗?也许共享变量会是更好的选择?
3. 最重要的是,在 30 次迭代中的每一次,我想用小批量将数据 X 替换为 KmeansMiniBatch 模型,因此我使用了给定参数。有没有更好的方法来实现这一目标?
【问题讨论】:
-
该代码中有很多奇怪的东西。您有两个名为“X”的 Theano 变量。您使用
mini_batch作为输入,但随后您也将它硬塞进givens(我很确定您在滥用givens)。你说fit_once更新D,但你的theano.function调用没有updates参数。您没有向我们展示fit_once的代码,但它之前返回了什么?如果它之前没有返回任何东西,那么将其指定为outputs是没有意义的。以此类推。 -
@cfh 我用详细信息更新了我的答案。我很确定在我的代码中我确实在某种意义上滥用了
theano,这就是我希望改进它的原因。如果您需要更多详细信息,请告诉我。我还编辑了重复变量错误。 -
您可能对 Theano 的工作方式有一些基本的疑虑。
fit_once必须返回一些东西,因为它只会执行一次,即当您构造function对象时,它返回的应该是一个符号计算图,它告诉 Theano 每当调用func时要计算什么。如果fit_once没有返回任何内容,则您的函数具有outputs=None,这意味着func实际上不会计算任何内容(因为它也没有updates=子句)。也许重温一些教程,看看这一切是如何结合在一起的。
标签: python numpy k-means theano