Когда я отправляю массив numpy в заданный параметр в функции theano, почему я получаю эту 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) File "/usr/local/lib/python2. 7/dist-packages/theano/compile/pfunc.py", строка 217, в reboot_collect_shared поднять TypeError(err_msg, err_sug)

TypeError: («Обновление должно иметь тот же тип, что и исходная общая переменная (shared_var=b, shared_var.type=TensorType(int64, scalar), update_val=Elemwise{sub,no_inplace}.0, update_val.type=TensorType(float64 , скаляр)).', 'Если разница связана с шаблоном трансляции, вы можете вызвать функцию tensor.unbroadcast(var, axis_to_unbroadcast[, ...]) для удаления широковещательных измерений.')


person swarb    schedule 04.12.2015    source источник


Ответы (2)


Этот код не будет выполняться, пока не будут устранены следующие проблемы.

  1. Ошибка, о которой сообщается в вопросе, связана с тем, что тип self.b не соответствует типу обновления для self.b. self.b не имеет указанного типа, поэтому он был выведен. Начальное значение — целое число Python, поэтому предполагаемый тип — int64. Обновление — floatX, потому что скорость обучения — floatX. Вы не можете обновить int64 с помощью floatX. Решение состоит в том, чтобы сделать начальное значение числом Python с плавающей запятой, что приведет к предполагаемому типу floatX. Замените self.b = theano.shared(value=1, name='b') на self.b = theano.shared(value=1., name='b') (обратите внимание на десятичную точку после 1).

  2. Следующая проблема заключается в том, что self.x определено как матрица, но значение, переданное в вызове функции в последней строке, является вектором. Решение состоит в том, чтобы преобразовать x в матрицу, например. изменить x = np.arange(10) на x = np.arange(10).reshape(1,10).

  3. Общие переменные набора поездов имеют тип float32, но это конфликтует с другими областями кода, которые работают с floatX. Если ваш floatX=float32, то проблем быть не должно, но было бы безопаснее просто использовать floatX для поддержания одного и того же типа с плавающей запятой. Измените 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.

  4. Количество эпох в настоящее время не имеет никакого значения, поскольку epoch не увеличивается. Замените while epoch < num_iter: на for epoch in xrange(num_iter): и удалите epoch = 0.

Кроме того,

  • Параметры выглядят так, как будто они не обновляются, но это ложное представление. Итерации проходят быстро и никогда не останавливаются из-за проблемы 4 выше, а скорость обучения достаточно велика, чтобы модель сходилась очень быстро. Попробуйте изменить скорость обучения на что-то намного меньшее, например. 0,0001, и посмотрите на вывод только для первых 100 эпох.

  • Я бы рекомендовал избегать использования theano.tensor._shared, если только вам действительно не нужно принудительно выделять общую переменную на ЦП, когда device=gpu. Предпочтительный метод — theano.shared.

  • Переменная n_train нигде не используется.

  • Вы используете givens непоследовательно. Я бы рекомендовал использовать его как для x, так и для y, или ни для одного из них. Взгляните на руководство по логистической регрессии, чтобы узнать больше об этом.

  • Функция Theano перекомпилируется при каждом вызове fit, но лучше скомпилировать ее только один раз и повторно использовать для каждого fit.

  • Эта модель может быть реализована без использования scan. В общем, scan часто требуется только тогда, когда результат шага является функцией результата предыдущего шага. scan также обычно намного медленнее, чем альтернативы, и его следует избегать, когда это возможно. Вы можете удалить scan, используя вместо него self.y = self.m * self.x + self.b.

  • Если вы используете сканирование, рекомендуется включить строгий режим через strict=True в вызове scan.

  • Хорошей практикой является явное указание типов для всех общих переменных. Вы делаете это для trainset_x и trainset_y, но не для self.m и self.b.

person Daniel Renshaw    schedule 04.12.2015
comment
Большое спасибо! Я согласен насчет self.b. Это решило предыдущую проблему. Я просматриваю ваши другие комментарии, чтобы увидеть, решает ли это мою проблему, что обновления на самом деле не происходят. - person swarb; 04.12.2015
comment
Я добавил дополнительное объяснение, почему параметры не меняются. - person Daniel Renshaw; 04.12.2015
comment
Большое спасибо за все ваши комментарии к коду! Да, после исправления, он работает, и я понимаю, что происходит сейчас! Большое спасибо. - person swarb; 04.12.2015

Хорошо, я обнаружил, что проблема действительно была в самом себе. После инициализации явным числом с плавающей запятой ошибка типа исчезает.

Но наклон и перехваты (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)
person swarb    schedule 04.12.2015
comment
См. мой обновленный ответ для получения информации о том, почему параметры выглядят так, как будто они не обновляются. - person Daniel Renshaw; 04.12.2015
comment
Да, после исправления я вижу его обновление и понимаю, что сейчас происходит! Большое спасибо - person swarb; 04.12.2015