zoukankan      html  css  js  c++  java
  • Deep Learning Tutorial (翻译) 之使用逻辑回归分类手写数字MNIST

    英文原文请参考http://www.deeplearning.net/tutorial/logreg.html

    模型

    这里,我们将使用Theano实现最基本的分类器:逻辑回归,以及学习数学表达式如何映射成Theano图。

    逻辑回归是一个基于概率的线性分类器,W和b为参数。通过投射输入向量到一组超平面,每个对应一个类,输入到一个平面的距离反应它属于对应类的概率。

    那么输入向量x为i类的概率,数值表示如下:

     

    预测类别为概率最大的类,及:

    用Theano实现的代码如下:

     # initialize with 0 the weights W as a matrix of shape (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_out),
                    dtype=theano.config.floatX
                ),
                name='b',
                borrow=True
            )
            self.p_y_given_x = T.nnet.softmax(T.dot(input, self.W) + self.b)
            self.y_pred = T.argmax(self.p_y_given_x, axis=-1)

    模型的参数在训练中维持一个持久的状态,我们将W,b设为共享变量,也是Theano符号变量。

    目前定义的模型还没有做任何有用的事情,接下来将介绍如何学习最优参数。

    定义损失函数(Loss Function)

    对于多类回归,常见的是使用negative log-likelihood作为损失。

    在参数θ下,最大化数据集D的似然函数,让我们先定义似然函数和损失:

    这里使用随机梯度下降的方法求最小值。

    创建逻辑回归类

    代码请参考源网址:http://www.deeplearning.net/tutorial/logreg.html

    def negative_log_likelihood(self, y):
            '''
            :type y: theano.tensor.TensorType
            :param y: correct label
            :return:
            Note: 我们使用mean而不是sum是为了学习率更少地依赖于batch size
            p_y_given_x是vector类型
            '''
            # y.shape返回y的行数和列数,则y.shape[0]返回y的行数,即样本的总个数,因为一行是一个样本。
            # T.arange(n),则是产生一组包含[0,1,...,n-1]的向量。
            # T.log(x),则是对x求对数。记为LP
            # LP[T.arange(y.shape[0]),y]是一组向量,其元素是[ LP[0,y[0]], LP[1,y[1]],
            # LP[2,y[2]], ...,LP[n-1,y[n-1]] ]
            # T.mean(x),则是求向量x中元素的均值。
            return -T.mean(T.log(self.p_y_given_x)[T.arange(y.shape[0]), y])
        def errors(self, y):
            if y.ndim != self.y_pred.ndim:
                raise TypeError('y should have the same shape as self.y_pred',
                                ('y',y.type, 'y_pred', self.y_pred.type))
            if y.dtype.startwith('int'):
                # T.neq(y1, y2)是计算y1与y2对应元素是否相同,如果相同便是0,否则是1。
                # 举例:如果y1=[1,2,3,4,5,6,7,8,9,0] y2=[1,1,3,3,5,6,7,8,9,0]
                # 则,err = T.neq(y1,y2) = [0,1,0,1,0,0,0,0,0,0],其中有3个1,即3个元素不同
                # T.mean()的作用就是求均值。那么T.mean(err) = (0+1+0+1+0+0+0+0+0+0)/10 = 0.3,即误差率为30%
                return T.mean(T.neq(self.y_pred, y))
            else:
                raise NotImplementedError()
    

    训练模型

    若要在大多数的编程语言中实现梯度下降算法,需要手动的推导出梯度表达式,这是一个非常麻烦的推导,而且最终结果也很复杂,特别是考虑到数值稳定性的问题的时候。 

    然而,在Theano这个工具中,这个变得异常简单。因为它已经把求梯度这种运算给封装好了,不需要手动推导公式,只需要按照格式传入数据即可。

    g_W = T.grad(cost=cost, wrt=classifier.W)
    g_b = T.grad(cost=cost, wrt=classifier.b)
    
    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 * batch_size: (index + 1) * batch_size],
                y: train_set_y[index * batch_size: (index + 1) * batch_size]
            }
        )

    每一次调用train_model(index),都会计算并返回输入样本块的cost,然后执行一次MSGD,并更新Wb。整个学习算法的一次迭代这样循环调用train_model (总样本数/样本块数)次。假设总样本60000个,一个样本块600个,那么一次迭代就需要调用100次train_model。而模型的训练又需要进行多次迭代,直到达到迭代次数或者误差率达到要求。

    测试模型

    验证模型和测试模型的不同之处在于计算所用的数据不一样,验证模型用的是验证数据集。

     As you will see shortly, validate_model is key to our early-stopping implementation .

    test_model = thenao.function(
        inputs = [index],
        outputs = classifier.errors(y),
        givens = {
             x: test_set_x[index * batch_size: (index + 1) * batch_size],
             y: test_set_y[index * batch_size: (index + 1) * batch_size]
        }
    )
    validate_model = theano.function(
        inputs=[index],
        outputs=classifier.errors(y),
        givens={
            x: valid_set_x[index * batch_size: (index + 1) * batch_size],
            y: valid_set_y[index * batch_size: (index + 1) * batch_size]
        }
    )  
    

    完整代码

    略(请参考官方教程)

    参考目录

    1.深度学习(DL)与卷积神经网络(CNN)学习笔记随笔-03-基于Python的LeNet之LR

    2.官方教程

  • 相关阅读:
    mobx源码解读1
    表单元素之图形系
    koa2+koa-views示例
    avalon2的后端渲染实践
    向一个数组中插入元素
    一步步编写avalon组件02:分页组件
    avalon2学习教程15指令总结
    avalon2学习教程14动画使用
    WPF动态加载Menu菜单
    WPF自定义控件与样式 ---- 系列文章
  • 原文地址:https://www.cnblogs.com/liwei33/p/5578056.html
Copyright © 2011-2022 走看看