python - Nolearn 在运行分类时会引发索引错误,但在回归时不会引发索引错误

标签 python machine-learning deep-learning lasagne nolearn

几天前我就被我要描述的问题困扰了。我正在关注 Daniel Nouri 关于深度学习的教程: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=1output_num_units=2我不太确定是否理解这一点,因为我正在处理二元分类问题,并且我认为这个多层感知器应该只有 1 个输出神经元,而不是 2 个……我错了吗?

我还尝试将成本函数更改为 ROC-AUC。我知道有一个参数叫 objective_loss_function定义为objective_loss_function=lasagne.objectives.categorical_crossentropy默认情况下,但是...我如何使用 ROC AUC 作为成本函数而不是分类交叉熵?

谢谢

最佳答案

在 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)

回答您的其他问题,Lasagne 似乎没有 ROC-AUC 目标,因此您需要实现它。请注意,例如,您不能使用 scikit-learn 的实现,因为 Lasagne 要求目标函数将 theano 张量作为参数,而不是列表或 ndarray。要了解目标函数是如何在 Lasagne 中实现的,您可以查看现有的目标函数 [2]。其中许多引用了theano内部的那些,你可以在[3]中看到它们的实现(它将自动滚动到binary_crossentropy,这是目标函数的一个很好的例子)。

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

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

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

关于python - Nolearn 在运行分类时会引发索引错误,但在回归时不会引发索引错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33843362/

相关文章:

python - Pandas - 将 AM/PM 格式更改为 24 小时制

python - 如何在 Python 中将列表初始化为某个值

python - Python-Django 的类似 cometd 的行为

python - PyTorch Autograd 自动微分功能

python - K.gradients(loss, input_img)[0] 返回 "None"。 (Keras CNN 可视化与 tensorflow 后端)

python - 在服务器上预处理图像

python - GridSearchCV 给出 ValueError : continuous is not supported for DecisionTreeRegressor

machine-learning - 从给定数据中学习并将其应用于新数据

machine-learning - 在 cifar-10 上的 Keras 中实现 AlexNet 的准确性较差

python - Keras提示错误: (Error when checking input: expected conv2d_4_input to have 4 dimensions)