在Theano中模仿布尔蒙版

时间:2015-09-05 03:29:56

标签: numpy theano

我将一个numpy表达移植到theano。该表达式给出了每个类的真正正预测的数量,给定了基础真值类的一个热矩阵Y和预测类的一个热矩阵Y_hat。 numpy代码是:

import numpy as np

y = np.array([1, 0, 1, 2, 2])
y_hat = np.array([2, 0, 1, 1, 0])

Y = np.zeros(shape=(len(y), len(np.unique(y))))
Y_hat = np.zeros_like(Y)

rows = np.arange(len(y))

Y[rows, y] = 1
Y_hat[rows, y_hat] = 1

((Y_hat == Y) & (Y == 1)).sum(axis=0)

最后一个表达式产生array([1, 1, 0])。我尝试过使用theano'非零:

from theano import shared
Yt = shared(Y)
Yt_hat = shared(Y_hat)
Yt_hat[Yt.nonzero()].eval()

eval得到array([ 0., 1., 1., 0., 0.]),它是预测正确的Yt_hat行的0-1掩码。有关如何使这项工作的任何建议?对于不同的做法?感谢。

1 个答案:

答案 0 :(得分:1)

以下是三个变体,演示了如何在Theano中重新实现部分numpy代码。

请注意,Theano的Unique操作不支持在GPU上运行,也不支持渐变。结果版本3许多用处不大。版本2提供了一种解决方法:计算Theano外部的唯一值并将其传入。版本1仅是您的numpy代码最后一行的Theano实现。

解决您的具体问题:无需使用nonzero;在这种情况下,索引在Theano中工作就像它在numpy中工作一样。也许你在yY之间感到困惑? (常见的Python风格是坚持使用小写的所有变量和参数名称。)

import numpy as np
import theano
import theano.tensor as tt
import theano.tensor.extra_ops


def numpy_ver(y, y_hat):
    Y = np.zeros(shape=(len(y), len(np.unique(y))), dtype=np.int64)
    Y_hat = np.zeros_like(Y, dtype=np.int64)
    rows = np.arange(len(y), dtype=np.int64)
    Y[rows, y] = 1
    Y_hat[rows, y_hat] = 1
    return ((Y_hat == Y) & (Y == 1)).sum(axis=0), Y, Y_hat


def compile_theano_ver1():
    Y = tt.matrix(dtype='int64')
    Y_hat = tt.matrix(dtype='int64')
    z = (tt.eq(Y_hat, Y) & tt.eq(Y, 1)).sum(axis=0)
    return theano.function([Y, Y_hat], outputs=z)


def compile_theano_ver2():
    y = tt.vector(dtype='int64')
    y_hat = tt.vector(dtype='int64')
    y_uniq = tt.vector(dtype='int64')
    Y = tt.zeros(shape=(y.shape[0], y_uniq.shape[0]), dtype='int64')
    Y_hat = tt.zeros_like(Y, dtype='int64')
    rows = tt.arange(y.shape[0], dtype='int64')
    Y = tt.set_subtensor(Y[rows, y], 1)
    Y_hat = tt.set_subtensor(Y_hat[rows, y_hat], 1)
    z = (tt.eq(Y_hat, Y) & tt.eq(Y, 1)).sum(axis=0)
    return theano.function([y, y_hat, y_uniq], outputs=z)


def compile_theano_ver3():
    y = tt.vector(dtype='int64')
    y_hat = tt.vector(dtype='int64')
    y_uniq = tt.extra_ops.Unique()(y)
    Y = tt.zeros(shape=(y.shape[0], y_uniq.shape[0]), dtype='int64')
    Y_hat = tt.zeros_like(Y, dtype='int64')
    rows = tt.arange(y.shape[0], dtype='int64')
    Y = tt.set_subtensor(Y[rows, y], 1)
    Y_hat = tt.set_subtensor(Y_hat[rows, y_hat], 1)
    z = (tt.eq(Y_hat, Y) & tt.eq(Y, 1)).sum(axis=0)
    return theano.function([y, y_hat], outputs=z)


def main():
    y = np.array([1, 0, 1, 2, 2], dtype=np.int64)
    y_hat = np.array([2, 0, 1, 1, 0], dtype=np.int64)
    y_uniq = np.unique(y)
    result, Y, Y_hat = numpy_ver(y, y_hat)
    print result
    theano_ver1 = compile_theano_ver1()
    print theano_ver1(Y, Y_hat)
    theano_ver2 = compile_theano_ver2()
    print theano_ver2(y, y_hat, y_uniq)
    theano_ver3 = compile_theano_ver3()
    print theano_ver3(y, y_hat)


main()