65.9K
CodeProject 正在变化。 阅读更多。
Home

多类逻辑回归训练和测试

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2014年8月13日

CPOL

4分钟阅读

viewsIcon

17816

简介本文将介绍多类逻辑分类器的训练与测试。逻辑回归是一种概率性的线性分类器。它由权重矩阵 $W$ 和偏置向量 $b$ 参数化。分类是通过将数据点投影到一组超平面上来实现的,超平面到数据点的距离用于确定类成员概率。

引言

本文将介绍多类逻辑分类器的训练与测试。

  • 逻辑回归是一种概率性的线性分类器。它由权重矩阵 \(W\) 和偏置向量 \(b\) 参数化。分类是通过将数据点投影到一组超平面上来实现的,超平面到数据点的距离用于确定类成员概率。
  • 数学上可以表示为:
    \begin{eqnarray*} & P(Y=i|x, W,b) =\frac {e^{W_i x + b_i}}{\sum_j e^{W_j x + b_j}} \\ \end{eqnarray*}
  • 与每个类 \(y_i\) 对应,逻辑分类器由一组参数 \(W_i,b_i\) 参数化。
  • 这些参数用于计算类概率。
  • 给定一个未知向量 x,预测过程如下:
    \begin{eqnarray*} & y_{pred} = argmax_i P(Y=i|x,W,b) \\ & y_{pred} = argmax_i \frac {e^{W_i x + b_i}}{\sum_j e^{W_j x + b_j}} \end{eqnarray*}
  • 给定一组带标签的训练数据 \({X_i,Y_i}\),其中 \(i\)\({1,\ldots,N}\) 中,我们需要估计这些参数。

损失函数

  • 理想情况下,我们希望计算参数以最小化 \(0-1\) 损失:
    \begin{eqnarray*} & \ell_{0,1} = \sum_{i=0}^{|\mathcal{D}|} I_{f(x^{(i)}) \neq y^{(i)}} \\ & f(x)= argmax_k P(Y=y_k |x,\theta) \end{eqnarray*}
  • \(P(Y=y_k |x,\theta)\) 使用逻辑函数进行建模。
  • \(0-1\) 损失函数不可微分,因此对于大型模型进行优化在计算上是不可行的。
  • 相反,我们最大化分类器在给定训练数据 \(\mathcal{D}\) 时的对数似然。
  • 最大似然估计用于执行此操作。
  • 估计参数,使得模型参数下的训练数据 \(\mathcal{D} \) 的似然性最大化。
  • 假设数据样本是独立的,因此集合的概率是个别样本概率的乘积。
    \begin{eqnarray*} & L(\theta={W,b},\mathcal{D}) =argmax \prod_{i=1}^N P(Y=y_i | X=x_i,W,b) \\ & L(\theta,\mathcal{D}) = argmax \sum_{i=1}^N log P(Y=y_i | X=x_i,W,b) \\ & L(\theta,\mathcal{D}) = - argmin \sum_{i=1}^N log P(Y=y_i | X=x_i,W,b) \\ \end{eqnarray*}
  • 需要注意的是,正确类的似然性与正确预测的数量不同。
  • 对数似然函数可以看作是 \(0-1\) 损失函数的微分版本。
  • 在当前应用中,负对数似然用作损失函数。
  • 通过最小化损失函数来学习最优参数。
  • 在当前应用中,使用基于梯度的下降方法进行最小化。
  • 具体来说,使用随机梯度下降和共轭梯度下降来最小化损失函数。
  • 成本函数表示为:
    \begin{eqnarray*} & L(\theta,\mathcal{D}) = - \sum_{i=1}^N log P(Y=y_i | X=x_i,W,b) \\ & L(\theta,\mathcal{D}) = - \sum_{i=1}^N log \frac {e^{W_i x + b_i}}{\sum_j e^{W_j x + b_j}} \\ & L(\theta,\mathcal{D}) = - \sum_{i=1}^N log {e^{W_i x + b_i}}- log {\sum_j e^{W_j x + b_j}} \\ & L(\theta,\mathcal{D}) = - \sum_{i=1}^N {W_i x + b_i} + log \frac{1}{\sum_j e^{W_j x + b_j}} \\ \end{eqnarray*}
  • 求和的第一部分是仿射的,第二部分是对指数之和的对数,这是凸的。因此,损失函数是凸的。
  • 因此,我们可以使用梯度下降方法计算损失函数的全局最大值对应的参数。
  • 因此,我们计算损失函数 \(L(\theta,\mathcal{D})\) 相对于 \(\theta,\partial{\ell}/\partial{W}\)\(\partial{\ell}/\partial{b}\) 的导数。

Theano

  • Theano 是一个 Python 库,允许您高效地定义、优化和评估涉及多维数组的数学表达式。
  • 它是一个表达式编译器,可以在执行时评估符号表达式。通常,用 C/C++ 实现的程序可以用 Theano 简洁高效地编写。
  • 在大多数编程语言(C/C++、Matlab、Python)中计算梯度需要手动推导出损失函数相对于参数 \(\partial{\ell}\partial{W}\)\(\partial{\ell}/\partial{b}\) 的梯度表达式。
  • 这种方法不仅涉及手动编码,而且对于复杂的模型,导数可能难以计算。
  • 使用 Theano,由于它执行自动微分,这项工作大大简化了。

示例

  • 为了演示,我们将使用 MNIST 数据集。MNIST 数据集包含手写数字图像,分为 60,000 个训练样本和 10,000 个测试样本。官方的 60,000 个训练集被分为 50,000 个实际训练样本和 10,000 个验证样本。所有数字图像都经过尺寸归一化并居中在一个固定大小为 28 x 28 像素的图像中。在原始数据集中,图像的每个像素由 0 到 255 之间的值表示,其中 0 是黑色,255 是白色,两者之间的任何值都是不同深浅的灰色。
  • 数据集可在 http://deeplearning.net/data/mnist/mnist.pkl.gz 找到。
  • 数据集是 pickle 格式的,可以使用 Python 的 pickle 包加载。
  • 数据集包含训练集、验证集和测试集。
  • 数据集由长度为 \((28x28=784)\) 的特征向量组成,类别数为 10。



  • 定义了一个名为 Logistic Regression 的类,它封装了用于执行多类逻辑回归分类器训练和测试的方法。

Theano 代码

  • 训练和测试的 Python 代码可以在 git 仓库 https://github.com/pi19404/OpenVision 中的 ImgML/LogisticRegression.py 文件中找到。
  • ImgML/load_datasets.py 包含从 pickle 文件或 SVM 格式文件加载数据集的方法。
     
        """ symbolic expressions defining input and output vectors"""
        x=T.matrix('x');
        y=T.ivector('y');
        """ The mnist dataset in pickel format"""
        model_name1="/media/LENOVO_/repo/mnist.pkl.gz"
        
        """ creating object of class Logistic regression"""
        """ input is 28*28 dimension feature vector ,and
        output lables are digits from 0-9 """
        classifier = LogisticRegression(x,y,28*28,10);
        
        """ loading the datasets"""
        [train,test,validate]=load_datasets.load_pickle_data(model_name1);
        
        """ setting the dataset"""
        classifier.set_datasets(train,test,validate);
        #
        #classifier.init_classifier(model_name1);n_out
        """ Training the classifiers"""
        classifier.train_classifier(0.13,1000,30);
        
        """ Saving the model """
        
        classifier.save('1');
        #x=classifier.train[0].get_value(borrow=True)[0];
        #classifier.predict(x);
        
        """ Loading the model"""
        classifier.load('1')
        x=train[0].get_value(borrow=True);
        y=train[1].eval();
        print 'True class:'+`y`
        xx,yy=classifier.predict(x);
        print 'Predicted class:' + `yy`
        classifier.testing();
  • 还使用 Eigen/OpenCV 编写了 C/C++ 代码,并将其合并到 OpenVision 库中。可以在文件 https://github.com/pi19404/OpenVision 中的 ImgML/LogisticRegression.cppImgML/LogisticRegression.hpp 中找到。
© . All rights reserved.