3

Я пытаюсь создать простой многослойный Perceptron (MLP) для «логического и» в Theano. Существует один слой между входом и выходом. Структура такова:Theano: Как передать данные обучения в нейронную сеть

2 входное значение -> умножают с весами, добавить смещение -> SoftMax -> 1 выходное значение

изменение размерности вызвано матрицы весов.

Реализация основана на данном руководстве: http://deeplearning.net/tutorial/logreg.html

Это мой класс для слоя:

class Layer(): 
""" 
this is a layer in the mlp 
it's not meant to predict the outcome hence it does not compute a loss. 
apply the functions for negative log likelihood = cost on the output of the last layer 
""" 

def __init__(self, input, n_in, n_out): 
    self.W = theano.shared(
      value=numpy.zeros(
        (n_in, n_out), 
        dtype=theano.config.floatX 
      ), 
      name="W", 
      borrow=True 
    ) 
    self.b = theano.shared(
      value=numpy.zeros((n_in 
           , n_out), 
           dtype=theano.config.floatX), 
      name="b", 
      borrow=True 
    ) 

    self.output = T.nnet.softmax(T.dot(input, self.W) + self.b) 
    self.params = (self.W, self.b) 
    self.input = input 

Класс предназначается, чтобы быть модульными. Вместо одного слоя я хочу иметь возможность добавлять несколько слоев. Поэтому функции для прогнозирования, стоимости и ошибки вне класса (в отличие от учебника):

def y_pred(output): 
    return T.argmax(output, axis=1) 


def negative_log_likelihood(output, y): 
    return -T.mean(T.log(output)[T.arange(y.shape[0]), y]) 


def errors(output, y): 
    # check if y has same dimension of y_pred 
    if y.ndim != y_pred(output).ndim: 
     raise TypeError(
       'y should have the same shape as self.y_pred', 
       ('y', y.type, 'y_pred', y_pred(output).type) 
     ) 
    # check if y is of the correct datatype 
    if y.dtype.startswith('int'): 
     # the T.neq operator returns a vector of 0s and 1s, where 1 
     # represents a mistake in prediction 
     return T.mean(T.neq(y_pred(output), y)) 
    else: 
     raise NotImplementedError() 

Логический и имеет 4 trainingcases:

  • [0,0] -> 0
  • [1,0] -> 0
  • [0,1] -> 0
  • [1,1] -> 1

Вот настройки классификатора и функции для обучения и оценки:

data_x = numpy.matrix([[0, 0], 
         [1, 0], 
         [0, 1], 
         [1, 1]]) 

data_y = numpy.array([0, 
         0, 
         0, 
         1]) 

train_set_x = theano.shared(numpy.asarray(data_x, 
         dtype=theano.config.floatX), 
         borrow=True) 

train_set_y = T.cast(theano.shared(numpy.asarray(data_y, 
         dtype=theano.config.floatX), 
         borrow=True),"int32") 

x = T.vector("x",theano.config.floatX) # data 
y = T.ivector("y") # labels 

classifier = Layer(input=x, n_in=2, n_out=1) 

cost = negative_log_likelihood(classifier.output, y) 

g_W = T.grad(cost=cost, wrt=classifier.W) 
g_b = T.grad(cost=cost, wrt=classifier.b) 
index = T.lscalar() 

learning_rate = 0.15 

updates = [ 
    (classifier.W, classifier.W - learning_rate * g_W), 
    (classifier.b, classifier.b - learning_rate * g_b) 
] 

train_model = theano.function(
     inputs=[index], 
     outputs=cost, 
     updates=updates, 
     givens={ 
      x: train_set_x[index], 
      y: train_set_y[index] 
     } 
) 
validate_model = theano.function(
     inputs=[index], 
     outputs=classifier.errors(y), 
     givens={ 
      x: train_set_x[index], 
      y: train_set_y[index] 
     } 
) 

Я пытался следовать конвенции. Каждая строка в матрице данных является образцом обучения. Каждому образцу обучения соответствует правильный результат. К сожалению, код не работает. Я не могу интерпретировать сообщение об ошибке. Что я сделал не так ? Ошибка:

TypeError: Cannot convert Type TensorType(int32, scalar) (of Variable Subtensor{int64}.0) into Type TensorType(int32, vector). You can try to manually convert Subtensor{int64}.0 into a TensorType(int32, vector).

Эта ошибка возникает глубоко в коде Theano. Конфликтная линия в моей программе является:

train_model = theano.function(
     inputs=[index], 
     outputs=cost, 
     updates=updates, 
     givens={ 
      x: train_set_x[index], 
      y: train_set_y[index]  # <---------------HERE 
     } 
) 

Видимо есть несоответствие между размерами и у тренировочных данных. Мой полный код на Pastebin: http://pastebin.com/U5jYitk2 полное сообщение об ошибке на Pastebin: http://pastebin.com/hUQJhfNM

Сжатый вопрос: Что такое правильный способ дать подготовки данных к MLP в Теано? Где моя ошибка?

Я скопировал большую часть кода учебника. Заметные изменения (возможные причины ошибки):

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

UPDATE: Я использовал код амира. Выглядит очень хорошо, спасибо.

Но это также создает ошибку. Последний цикл недоступный:

/usr/bin/python3.4 /home/lhk/programming/sk/mlp/mlp/Layer.py Traceback (most recent call last): File "/usr/local/lib/python3.4/dist-packages/theano/compile/function_module.py", line 595, in call outputs = self.fn() ValueError: y_i value out of bounds

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "/home/lhk/programming/sk/mlp/mlp/Layer.py", line 113, in train_model(i) File "/usr/local/lib/python3.4/dist-packages/theano/compile/function_module.py", line 606, in call storage_map=self.fn.storage_map) File "/usr/local/lib/python3.4/dist-packages/theano/gof/link.py", line 206, in raise_with_op raise exc_type(exc_value).with_traceback(exc_trace) File "/usr/local/lib/python3.4/dist-packages/theano/compile/function_module.py", line 595, in call outputs = self.fn() ValueError: y_i value out of bounds Apply node that caused the error: CrossentropySoftmaxArgmax1HotWithBias(Dot22.0, b, Elemwise{Cast{int32}}.0) Inputs types: [TensorType(float64, matrix), TensorType(float64, vector), TensorType(int32, vector)] Inputs shapes: [(1, 1), (1,), (1,)] Inputs strides: [(8, 8), (8,), (4,)] Inputs values: [array([[ 0.]]), array([ 0.]), array([1], dtype=int32)]

HINT: Re-running with most Theano optimization disabled could give you a back-trace of when this node was created. This can be done with by setting the Theano flag 'optimizer=fast_compile'. If that does not work, Theano optimizations can be disabled with 'optimizer=None'. HINT: Use the Theano flag 'exception_verbosity=high' for a debugprint and storage map footprint of this apply node.

Line 113 это одна:

#train the model 
for i in range(train_set_x.shape[0].eval()): 
    train_model(i)    # <-----------------HERE 

Я считаю, что это происходит потому, что индексация обучающих данных использует index и index+1. Почему это необходимо? Один ряд должен быть одним учебным образцом. И один ряд: train_set_x[index]

Редактировать: я отладил код. Без разрезания он возвращает 1d-массив, а срезание - 2d. 1d должно быть несовместимо с матрицей x.

Но в то время как я это сделал, я нашел еще одну странную проблему: Я добавил этот код, чтобы посмотреть на эффект обучения:

print("before") 
print(classifier.W.get_value()) 
print(classifier.b.get_value()) 

for i in range(3): 
    train_model(i) 

print("after") 
print(classifier.W.get_value()) 
print(classifier.b.get_value()) 

before 
[[ 0.] 
[ 0.]] 
[ 0.] 
after 
[[ 0.] 
[ 0.]] 
[ 0.] 

Это имеет смысл, так как первые три образца имеют 0, как правильно вывод. Если я изменил порядок и переместил образец обучения (1,1), 1 в начало, программа выйдет из строя.

before [[ 0.] [ 0.]] [ 0.] Traceback (most recent call last): File "/usr/local/lib/python3.4/dist-packages/theano/compile/function_module.py", line 595, in call outputs = self.fn() ValueError: y_i value out of bounds

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "/home/lhk/programming/sk/mlp/mlp/Layer.py", line 121, in train_model(i) File "/usr/local/lib/python3.4/dist-packages/theano/compile/function_module.py", line 606, in call storage_map=self.fn.storage_map) File "/usr/local/lib/python3.4/dist-packages/theano/gof/link.py", line 206, in raise_with_op raise exc_type(exc_value).with_traceback(exc_trace) File "/usr/local/lib/python3.4/dist-packages/theano/compile/function_module.py", line 595, in call outputs = self.fn() ValueError: y_i value out of bounds Apply node that caused the error: CrossentropySoftmaxArgmax1HotWithBias(Dot22.0, b, Elemwise{Cast{int32}}.0) Inputs types: [TensorType(float64, matrix), TensorType(float64, vector), TensorType(int32, vector)] Inputs shapes: [(1, 1), (1,), (1,)] Inputs strides: [(8, 8), (8,), (4,)] Inputs values: [array([[ 0.]]), array([ 0.]), array([1], dtype=int32)]

HINT: Re-running with most Theano optimization disabled could give you a back-trace of when this node was created. This can be done with by setting the Theano flag 'optimizer=fast_compile'. If that does not work, Theano optimizations can be disabled with 'optimizer=None'. HINT: Use the Theano flag 'exception_verbosity=high' for a debugprint and storage map footprint of this apply node.

UPDATE

Я установил python2.7 с Феано и попытался запустить код. Произошла та же ошибка. И я добавил подробные обработки исключений. Вот результат:

/usr/bin/python2.7 /home/lhk/programming/sk/mlp/mlp/Layer.py 
Traceback (most recent call last): 
    File "/home/lhk/programming/sk/mlp/mlp/Layer.py", line 113, in <module> 
    train_model(i) 
    File "/home/lhk/.local/lib/python2.7/site-packages/theano/compile/function_module.py", line 595, in __call__ 
    outputs = self.fn() 
    File "/home/lhk/.local/lib/python2.7/site-packages/theano/gof/link.py", line 485, in streamline_default_f 
    raise_with_op(node, thunk) 
    File "/home/lhk/.local/lib/python2.7/site-packages/theano/gof/link.py", line 481, in streamline_default_f 
    thunk() 
    File "/home/lhk/.local/lib/python2.7/site-packages/theano/gof/op.py", line 768, in rval 
    r = p(n, [x[0] for x in i], o) 
    File "/home/lhk/.local/lib/python2.7/site-packages/theano/tensor/nnet/nnet.py", line 896, in perform 
    nll[i] = -row[y_idx[i]] + m + numpy.log(sum_j) 
IndexError: index 1 is out of bounds for axis 0 with size 1 
Apply node that caused the error: CrossentropySoftmaxArgmax1HotWithBias(Dot22.0, b, Subtensor{int32:int32:}.0) 
Inputs types: [TensorType(float64, matrix), TensorType(float64, vector), TensorType(int32, vector)] 
Inputs shapes: [(1, 1), (1,), (1,)] 
Inputs strides: [(8, 8), (8,), (4,)] 
Inputs values: [array([[ 0.]]), array([ 0.]), array([1], dtype=int32)] 

Debugprint of the apply node: 
CrossentropySoftmaxArgmax1HotWithBias.0 [@A] <TensorType(float64, vector)> '' 
|Dot22 [@B] <TensorType(float64, matrix)> '' 
| |Subtensor{int32:int32:} [@C] <TensorType(float64, matrix)> '' 
| | |<TensorType(float64, matrix)> [@D] <TensorType(float64, matrix)> 
| | |ScalarFromTensor [@E] <int32> '' 
| | | |<TensorType(int32, scalar)> [@F] <TensorType(int32, scalar)> 
| | |ScalarFromTensor [@G] <int32> '' 
| | |Elemwise{add,no_inplace} [@H] <TensorType(int32, scalar)> '' 
| |  |<TensorType(int32, scalar)> [@F] <TensorType(int32, scalar)> 
| |  |TensorConstant{1} [@I] <TensorType(int8, scalar)> 
| |W [@J] <TensorType(float64, matrix)> 
|b [@K] <TensorType(float64, vector)> 
|Subtensor{int32:int32:} [@L] <TensorType(int32, vector)> '' 
    |Elemwise{Cast{int32}} [@M] <TensorType(int32, vector)> '' 
    | |<TensorType(float64, vector)> [@N] <TensorType(float64, vector)> 
    |ScalarFromTensor [@E] <int32> '' 
    |ScalarFromTensor [@G] <int32> '' 
CrossentropySoftmaxArgmax1HotWithBias.1 [@A] <TensorType(float64, matrix)> '' 
CrossentropySoftmaxArgmax1HotWithBias.2 [@A] <TensorType(int32, vector)> '' 

HINT: Re-running with most Theano optimization disabled could give you a back-trace of when this node was created. This can be done with by setting the Theano flag 'optimizer=fast_compile'. If that does not work, Theano optimizations can be disabled with 'optimizer=None'. 

Process finished with exit code 1 

UPDATE:

Я снова посмотрел на обучающих данных. Любой образец с меткой 1 будет вызывать указанную выше ошибку.

data_y = numpy.array([1, 
         1, 
         1, 
         1]) 

Вышеприведенные ярлыки образцов будут разбиты для каждого train_model (i) для i в (0,1,2,3). По-видимому, существует помеха между индексацией образцов и содержимым выборки.

ОБНОВЛЕНИЕ: Проблема заключается в том, что, как указывает контакт Амира, размер выходного слоя. У меня было заблуждение, что я мог бы обучить сеть кодировать вывод функции «логический» и «непосредственно в выходной нейрон». Хотя это, безусловно, возможно, этот подход к обучению использует индексирование значения y для выбора выходного узла, который должен иметь самое высокое значение. После изменения размера вывода на два, код работает. И с достаточной подготовкой ошибки для всех случаев действительно становятся нулевыми.

+0

Я настоятельно рекомендую вам очистить свой пост, так что это будет полезно для будущих читателей. – Amir

ответ

1

Это код ошибки для вашей проблемы. В вашем коде было довольно много ошибок. Тот, который вызвал ошибку, которую вы получали, был обусловлен определением b как матрицы n_in на n_out вместо простого определения его как вектора «n_out».Часть обновления была определена в скобках [], а не в скобках ().

Кроме того, индекс был определен как символический скаляр int32 (это не очень важно). Другим изменением импорта было определение функций с учетом правильной индексации. То, как вы использовали index для компиляции ваших функций, не позволяло компиляции функции по какой-либо причине. Вы также указали свой вход как вектор. Таким образом, вы не сможете обучать модель, используя мини-партии или полную партию. Поэтому можно объявить его как символическую матрицу. И для использования вектора вам нужно сохранить ваши входы как векторы вместо матрицы на общей переменной, чтобы запустить программу. Таким образом, такая головная боль будет объявлена ​​как вектор. В конце концов, вы использовали classifier.errors(y), чтобы скомпилировать вашу функцию проверки, хотя вы удалили функцию errors из класса Layer.

import theano 
import theano.tensor as T 
import numpy 


class Layer(object): 
    """ 
    this is a layer in the mlp 
    it's not meant to predict the outcome hence it does not compute a loss. 
    apply the functions for negative log likelihood = cost on the output of the last layer 
    """ 

    def __init__(self, input, n_in, n_out): 
     self.x = input 
     self.W = theano.shared(
       value=numpy.zeros(
         (n_in, n_out), 
         dtype=theano.config.floatX 
       ), 
       name="W", 
       borrow=True 
     ) 
     self.b = theano.shared(
       value=numpy.zeros(n_out, 
            dtype=theano.config.floatX), 
       name="b", 
       borrow=True 
     ) 

     self.output = T.nnet.softmax(T.dot(self.x, self.W) + self.b) 
     self.params = [self.W, self.b] 
     self.input = input 


def y_pred(output): 
    return T.argmax(output, axis=1) 


def negative_log_likelihood(output, y): 
    return -T.mean(T.log(output)[T.arange(y.shape[0]), y]) 


def errors(output, y): 
    # check if y has same dimension of y_pred 
    if y.ndim != y_pred(output).ndim: 
     raise TypeError(
       'y should have the same shape as self.y_pred', 
       ('y', y.type, 'y_pred', y_pred(output).type) 
     ) 
    # check if y is of the correct datatype 
    if y.dtype.startswith('int'): 
     # the T.neq operator returns a vector of 0s and 1s, where 1 
     # represents a mistake in prediction 
     return T.mean(T.neq(y_pred(output), y)) 
    else: 
     raise NotImplementedError() 

data_x = numpy.matrix([[0, 0], 
         [1, 0], 
         [0, 1], 
         [1, 1]]) 

data_y = numpy.array([0, 
         0, 
         0, 
         1]) 

train_set_x = theano.shared(numpy.asarray(data_x, 
         dtype=theano.config.floatX), 
         borrow=True) 

train_set_y = T.cast(theano.shared(numpy.asarray(data_y, 
         dtype=theano.config.floatX), 
         borrow=True),"int32") 

x = T.matrix("x") # data 
y = T.ivector("y") # labels 

classifier = Layer(input=x, n_in=2, n_out=1) 

cost = negative_log_likelihood(classifier.output, y) 

g_W = T.grad(cost=cost, wrt=classifier.W) 
g_b = T.grad(cost=cost, wrt=classifier.b) 
index = T.iscalar() 

learning_rate = 0.15 

updates = (
    (classifier.W, classifier.W - learning_rate * g_W), 
    (classifier.b, classifier.b - learning_rate * g_b) 
) 

train_model = theano.function(
     inputs=[index], 
     outputs=cost, 
     updates=updates, 
     givens={ 
      x: train_set_x[index:index + 1], 
      y: train_set_y[index:index + 1] 
     } 
) 
validate_model = theano.function(
     inputs=[index], 
     outputs=errors(classifier.output, y), 
     givens={ 
      x: train_set_x[index:index + 1], 
      y: train_set_y[index:index + 1] 
     } 
) 

#train the model 
for i in range(train_set_x.shape[0].eval()): 
    train_model(i) 

Вот обновленный код. Обратите внимание, что основное различие между приведенным выше кодом и приведенным ниже кодом состоит в том, что более поздняя версия подходит для двоичной проблемы, а другая работает, если у вас есть проблема с несколькими классами, что здесь не так. Причина, по которой я помещаю оба фрагмента кода, - это образовательные цели. Пожалуйста, прочитайте комментарии, чтобы понять проблему с приведенным выше кодом и как я решил ее решить.

import theano 
import theano.tensor as T 
import numpy 


class Layer(object): 
    """ 
    this is a layer in the mlp 
    it's not meant to predict the outcome hence it does not compute a loss. 
    apply the functions for negative log likelihood = cost on the output of the last layer 
    """ 

    def __init__(self, input, n_in, n_out): 
     self.x = input 
     self.W = theano.shared(
       value=numpy.zeros(
         (n_in, n_out), 
         dtype=theano.config.floatX 
       ), 
       name="W", 
       borrow=True 
     ) 
     self.b = theano.shared(
       value=numpy.zeros(n_out, 
            dtype=theano.config.floatX), 
       name="b", 
       borrow=True 
     ) 

     self.output = T.reshape(T.nnet.sigmoid(T.dot(self.x, self.W) + self.b), (input.shape[0],)) 
     self.params = [self.W, self.b] 
     self.input = input 


def y_pred(output): 
    return output 


def negative_log_likelihood(output, y): 
    return T.mean(T.nnet.binary_crossentropy(output,y)) 


def errors(output, y): 
    # check if y has same dimension of y_pred 
    if y.ndim != y_pred(output).ndim: 
     raise TypeError(
       'y should have the same shape as self.y_pred', 
       ('y', y.type, 'y_pred', y_pred(output).type) 
     ) 
    # check if y is of the correct datatype 
    if y.dtype.startswith('int'): 
     # the T.neq operator returns a vector of 0s and 1s, where 1 
     # represents a mistake in prediction 
     return T.mean(T.neq(y_pred(output), y)) 
    else: 
     raise NotImplementedError() 

data_x = numpy.matrix([[0, 0], 
         [1, 0], 
         [0, 1], 
         [1, 1]]) 

data_y = numpy.array([0, 
         0, 
         0, 
         1]) 

train_set_x = theano.shared(numpy.asarray(data_x, 
         dtype=theano.config.floatX), 
         borrow=True) 

train_set_y = T.cast(theano.shared(numpy.asarray(data_y, 
         dtype=theano.config.floatX), 
         borrow=True),"int32") 

x = T.matrix("x") # data 
y = T.ivector("y") # labels 

classifier = Layer(input=x, n_in=2, n_out=1) 

cost = negative_log_likelihood(classifier.output, y) 

g_W = T.grad(cost=cost, wrt=classifier.W) 
g_b = T.grad(cost=cost, wrt=classifier.b) 
index = T.iscalar() 

learning_rate = 0.15 

updates = (
    (classifier.W, classifier.W - learning_rate * g_W), 
    (classifier.b, classifier.b - learning_rate * g_b) 
) 

train_model = theano.function(
     inputs=[index], 
     outputs=cost, 
     updates=updates, 
     givens={ 
      x: train_set_x[index:index+1], 
      y: train_set_y[index:index+1] 
     } 
) 
validate_model = theano.function(
     inputs=[index], 
     outputs=errors(classifier.output, y), 
     givens={ 
      x: train_set_x[index:index + 1], 
      y: train_set_y[index:index + 1] 
     } 
) 

#train the model 
for i in range(train_set_x.shape[0].eval()): 
    train_model(i) 
+0

Комментарии не предназначены для расширенного обсуждения; этот разговор был [перемещен в чат] (http://chat.stackoverflow.com/rooms/99824/discussion-on-answer-by-amir-theano-how-to-give-training-data-to-a- нейронная-netwo). Если в комментариях есть что-то, что ваш ответ зависит, ** переместите его в ответ **. – meagar

0

Вы можете попробовать мой MLP класс:

лазаньи/на основе Theano многослойный персептрон MLP, который принимает и разреженных и плотных матриц входных и очень проста в использовании с scikit-апи узнать сходства.

У этого есть выпадающий конфигурируемый/разреженный вход/может быть изменен на логистическую регрессию, легко изменить функцию стоимости и l1/l2/elasticnet regularisations.

Код here

Смежные вопросы