Я пытаюсь создать простой многослойный 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 для выбора выходного узла, который должен иметь самое высокое значение. После изменения размера вывода на два, код работает. И с достаточной подготовкой ошибки для всех случаев действительно становятся нулевыми.
Я настоятельно рекомендую вам очистить свой пост, так что это будет полезно для будущих читателей. – Amir