Nolearn вызывает ошибку индекса при запуске классификации, но не с регрессией

Несколько дней назад я застрял с проблемой, которую собираюсь описать. Я следую учебнику Даниэля Нури о глубоком обучении: http://danielnouri.org/notes/category/deep-learning/ и я попытался адаптировать его пример к набору классификационных данных. Моя проблема здесь заключается в том, что если я рассматриваю набор данных как проблему регрессии, он работает правильно, но если я пытаюсь выполнить классификацию, он терпит неудачу. Я попытался написать 2 воспроизводимых примера.

1) Регрессия (работает хорошо)

import lasagne
from sklearn import datasets
import numpy as np
from lasagne import layers
from lasagne.updates import nesterov_momentum
from nolearn.lasagne import NeuralNet
from sklearn.preprocessing import StandardScaler

iris = datasets.load_iris()
X = iris.data[iris.target<2]  # we only take the first two features.
Y = iris.target[iris.target<2]
stdscaler = StandardScaler(copy=True, with_mean=True, with_std=True)
X = stdscaler.fit_transform(X).astype(np.float32)
y = np.asmatrix((Y-0.5)*2).T.astype(np.float32)

print X.shape, type(X)
print y.shape, type(y)

net1 = NeuralNet(
    layers=[  # three layers: one hidden layer
        ('input', layers.InputLayer),
        ('hidden', layers.DenseLayer),
        ('output', layers.DenseLayer),
        ],
    # layer parameters:
    input_shape=(None, 4),  # 96x96 input pixels per batch
    hidden_num_units=10,  # number of units in hidden layer
    output_nonlinearity=None,  # output layer uses identity function
    output_num_units=1,  # 1 target value

    # optimization method:
    update=nesterov_momentum,
    update_learning_rate=0.01,
    update_momentum=0.9,

    regression=True,  # flag to indicate we're dealing with regression problem
    max_epochs=400,  # we want to train this many epochs
    verbose=1,
    )

net1.fit(X, y)

2) Классификация (она вызывает ошибку размерности матрицы; я вставляю ее ниже)

import lasagne
from sklearn import datasets
import numpy as np
from lasagne import layers
from lasagne.nonlinearities import softmax
from lasagne.updates import nesterov_momentum
from nolearn.lasagne import NeuralNet
from sklearn.preprocessing import StandardScaler

iris = datasets.load_iris()
X = iris.data[iris.target<2]  # we only take the first two features.
Y = iris.target[iris.target<2]
stdscaler = StandardScaler(copy=True, with_mean=True, with_std=True)
X = stdscaler.fit_transform(X).astype(np.float32)
y = np.asmatrix((Y-0.5)*2).T.astype(np.int32)

print X.shape, type(X)
print y.shape, type(y)

net1 = NeuralNet(
    layers=[  # three layers: one hidden layer
        ('input', layers.InputLayer),
        ('hidden', layers.DenseLayer),
        ('output', layers.DenseLayer),
        ],
    # layer parameters:
    input_shape=(None, 4),  # 96x96 input pixels per batch
    hidden_num_units=10,  # number of units in hidden layer
    output_nonlinearity=softmax,  # output layer uses identity function
    output_num_units=1,  # 1 target value

    # optimization method:
    update=nesterov_momentum,
    update_learning_rate=0.01,
    update_momentum=0.9,

    regression=False,  # flag to indicate we're dealing with classification problem
    max_epochs=400,  # we want to train this many epochs
    verbose=1,
    )

net1.fit(X, y)

Неудачный вывод я получаю с кодом 2.

(100, 4) <type 'numpy.ndarray'>
(100, 1) <type 'numpy.ndarray'>
  input                 (None, 4)               produces       4 outputs
  hidden                (None, 10)              produces      10 outputs
  output                (None, 1)               produces       1 outputs
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-13-184a45e5abaa> in <module>()
     40     )
     41 
---> 42 net1.fit(X, y)

/Users/ivanvallesperez/anaconda/lib/python2.7/site-packages/nolearn/lasagne/base.pyc in fit(self, X, y)
    291 
    292         try:
--> 293             self.train_loop(X, y)
    294         except KeyboardInterrupt:
    295             pass

/Users/ivanvallesperez/anaconda/lib/python2.7/site-packages/nolearn/lasagne/base.pyc in train_loop(self, X, y)
    298     def train_loop(self, X, y):
    299         X_train, X_valid, y_train, y_valid = self.train_test_split(
--> 300             X, y, self.eval_size)
    301 
    302         on_epoch_finished = self.on_epoch_finished

/Users/ivanvallesperez/anaconda/lib/python2.7/site-packages/nolearn/lasagne/base.pyc in train_test_split(self, X, y, eval_size)
    399                 kf = KFold(y.shape[0], round(1. / eval_size))
    400             else:
--> 401                 kf = StratifiedKFold(y, round(1. / eval_size))
    402 
    403             train_indices, valid_indices = next(iter(kf))

/Users/ivanvallesperez/anaconda/lib/python2.7/site-packages/sklearn/cross_validation.pyc in __init__(self, y, n_folds, shuffle, random_state)
    531         for test_fold_idx, per_label_splits in enumerate(zip(*per_label_cvs)):
    532             for label, (_, test_split) in zip(unique_labels, per_label_splits):
--> 533                 label_test_folds = test_folds[y == label]
    534                 # the test split can be too big because we used
    535                 # KFold(max(c, self.n_folds), self.n_folds) instead of

IndexError: too many indices for array

Что здесь происходит? Я делаю что-то плохое? Я все перепробовал, но не могу понять, что происходит.

Обратите внимание, что я только что обновил свою лазанью и зависимости сегодня, используя команду: pip install -r https://raw.githubusercontent.com/dnouri/kfkd-tutorial/master/requirements.txt

заранее спасибо

редактировать

Я добился успеха, выполнив последующие изменения, но у меня все еще есть некоторые сомнения:

  • Я определил Y как одномерный вектор со значениями 0/1 как: y = Y.astype(np.int32) но у меня все еще есть некоторые сомнения

  • Я должен был изменить параметр output_num_units=1 в output_num_units=2 и я не совсем уверен, что понимаю это, потому что я работаю с проблемой двоичной классификации, и я думаю, что этот многослойный персептрон должен иметь только 1 выходной нейрон, а не 2 из них... Я ошибаюсь?

Я также попытался изменить функцию стоимости на ROC-AUC. Я знаю, что есть параметр под названием objective_loss_function который определяется как objective_loss_function=lasagne.objectives.categorical_crossentropy по умолчанию, но... как я могу использовать ROC AUC в качестве функции стоимости вместо категориальной кроссентропии?

Спасибо

1 ответ

В nolearn, если вы делаете классификацию, output_num_units сколько у вас классов Хотя можно реализовать классификацию двух классов только с одной выходной единицей, в nolearn это специально не рассматривается, как следует, например, из [1]:

    if not self.regression:
        predict = predict_proba.argmax(axis=1)

Обратите внимание, что прогноз всегда является аргументом argmax, независимо от того, сколько у вас классов (имеется в виду, что у классификации двух классов есть два выхода, а не один).

Итак, ваши изменения верны: output_num_units всегда должно быть количество классов, которые у вас есть, даже если у вас есть два, и Y должен иметь форму либо (num_samples) или же (num_samples, 1) содержит целочисленные значения, которые представляют категории, в отличие, например, от вектора с битом на категорию с формой (num_samples, num_categories),

Отвечая на другой ваш вопрос, Лазанье, похоже, не имеет ROC-AUC цель, так что вам нужно будет это реализовать. Обратите внимание, что вы не можете использовать реализацию из scikit-learn, например, потому что Lasagne требует, чтобы целевая функция принимала theano тензоры в качестве аргументов, а не списков или ndarrays. Чтобы увидеть, как в Lasagne реализована целевая функция, вы можете взглянуть на существующие целевые функции [2]. Многие из них ссылаются на те, что находятся внутри theano, их реализации можно увидеть в [3] (он автоматически прокрутится до binary_crossentropy, что является хорошим примером целевой функции).

[1] https://github.com/dnouri/nolearn/blob/master/nolearn/lasagne/base.py

[2] https://github.com/Lasagne/Lasagne/blob/master/lasagne/objectives.py

[3] https://github.com/Theano/Theano/blob/master/theano/tensor/nnet/nnet.py

Другие вопросы по тегам