Когато изпратя масив 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, във fit 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, 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 float, което води до изведен тип 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, за да поддържате един и същ тип 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.

  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
Много благодаря! Съгласен съм за себе си.b. Това реши предишния проблем. Разглеждам другите ви коментари, за да видя дали това решава проблема ми, че актуализациите наистина не се случват. - person swarb; 04.12.2015
comment
Добавих допълнително обяснение защо изглежда, че параметрите не се променят. - person Daniel Renshaw; 04.12.2015
comment
Благодаря много за всичките ви коментари относно кода! Да, след коригиране работи и разбирам какво се случва сега! Благодаря много. - person swarb; 04.12.2015

Добре, открих, че проблемът наистина е в себе си.b. След като го инициализирате с явен float, грешката в типа изчезва.

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