deeplearning.net 0.1 document - Logistic Regression

Classifying MNIST digits using Logistic Regression

在本节我们会展示Theano是怎样实现一个最基本的逻辑斯特回归。我们快速过一下模型并且回顾一下符号和数学表达式。

在机器学习传统中,这个教程会解决MNIST手写识别这个令人振奋的问题。

The Model

逻辑斯特是一个概率,线性分类器,以权重矩阵W和偏置项b。分类器输入与一个类相关的一个超平面。输入超平面的距离映射到相关类的概率分布中。

数学上,输入向量x的概率是一个类i的概率。:

1

模型的预测 y~pred~是一个使概率最大的类,特别地:

2

Theano的代码实现 :

# 权值初始化0
self.W = theano.shared(
    value = numpy.zero(
        (n_in, n_out),
        dtype=theano.config.floatX,
        ),
    name = 'W',
    borrow = True
    )

# 初始化偏置项为0
self.b = theano.shared(
    value = numpy.zeros(
        (n_out,),
        dtype = theano.config.floatX,
        ),
    name = 'b',
    borrow = True
    )

# 符号表达式来计算类成员概率矩阵
# 其中:
# W是一个矩阵,第k列代表第k类的权值
# x是一个矩阵,第j行代表第j个样本输入
# b是一个向量,其中第k个代表第k个超平面的只有参数
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的符号变量同时初始化内容。点乘和softmax运算是用来计算P(Y|x,W,b)。结果p_y_given_x是一个向量类型的符号变量。

为了获得准确的预测模型,我们可以使用T.argmax运算,它会返回一个是p_y_given_x最大的下标。

当然这个刚定义的模型还没什么用,只要它是还是初始状态。所以下面我们来学习怎样学习最佳参数。

Defining a Loss Function

学习最佳模型参数设计最小化损失函数。在多类逻辑斯特回归中,最常用的是负对数似然。这等于最大化以theta为参数的D数据集的似然函数。让我们定义似然函数 L 和 损失 l

3

当整本书都在说最小化,梯度下降是最简单的最小化任意非线性函数。本教材会使用小批量随机梯度下降方法(MSGD)。

下面的Theano代码定义了给定小批量的符号化损失:

# y.shape[0]是y的行数目,例如,小批量里样本的数量。
# T.arange(y.shape[0])是一个向量,包括[0,1,2,...,n-1]
# T.log(self.p_y_given_x)是一个对数概率(LP)矩阵,每一行对应一个样本
# 和每一列对应一个类。 LP[T.arange(y.shape[0]), y)]是一个向量v,包括
# [LP[0, y[0]], LP[1, y[1]], LP[2, y[2]],...]和T.mean()是一个v的平均值
return -T.mean(T.log(self.p_y_given_x)[T.arange(y.shape[0]), y])

尽管损失函数是数据集的 sum。我们使用 mean,这样使学习率少依赖于小批量

Creating a LogisticRegression class

现在我们拥有所有LogisticRegression的部件。这跟我们之前的很像,而且加了注释。

class LogisticRegression(object) :
    """ 多类逻辑斯特分类

    逻辑斯特回归决定于一个权重矩阵:W 和偏置项向量:b。
    分类器是把数据点放在一系列超平面,到超平面的距离决定
    分类的概率
    """

    def __init__(self, input, n_in, n_out) :
        """ 初始化逻辑斯特回归的参数

        : type input : theano.tensor.TheanoType
        : param input : 一个小批量的符号变量输入

        : type n_int : int
        : param n_in : 输入单元的数量,数据点在空间的维数

        : type n_out : int
        : param n_out : 输出单元的数量,标签在空间的维数

        """
        # 开始 - 第一部分
        # 初始化(n_in, n_out)矩阵的权值为0
        self.W = theano.shared(
            value = numpy.zeros(
                (n_in, n_out),
                dtype = theano.config.floatX
                ),
            name = 'W',
            borrow = True
            )
        # 初始化偏置项b为0
        self.b = theano.shared(
            value = numpy.zeros(
                (n_out,),
                dtype = theano.config.floatX
                ),
            name = 'b',
            borrow = True
            )

        # 计算类成员概率的符号表达式
        # 其中:
        # W 的第k列代表第k类的超平面
        # x 的第k行代表第j个训练集
        # b 的第k个元素代表第k超平面的偏置项
        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)
        # 结束 - 第一部分

        # 模型的参数
        self.params = [self.W, self.b]

        # 保持模型的输入
        self.input - input

    def negetive_log_likelihood(self, y) :
        """ 返回预测值的负似然平均值

        : type y : theano.tensor.TensorType
        : param y : 每个样本对应的标签

        """

        return -T.mean(T.log(self.p_y_given_x)[T.arange(y.shape[0]), y])

    def error(self, y) :
        """ 返回一个浮点数代表每个小批量的误差;小批量的零一误差

        : type y :  theano.tensor.TensorType
        : param y : 对应标签

        """

        # 检查y和y_pred是否为相同维数
        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)
                )
        # 检查y是否为正确数据类型
        if y.dtype.startswith('int') :
            # T.neq返回一个0和1的向量,1代表预测错误
            return T.mean(T.neq(self.y_pred, y))
        else :
            raise NotImplementedError()

我们如下实例化类:

# 生成符号变量,输入x和y是一个小批量
x = T.matrix('x')
y = T.ivector('y')

# 构建逻辑斯特回归类
# 每个图片为 28*28
classifier = LogisticRegression(input=x, n_in=28*28, n_out=10)

我新建一个test_model函数和一个validate_model函数。validate_model是提早结束的关键。Theano函数获得一个小批量的下标并且计算,在小批量的样本里,数字被模型分类。唯一不同的就是test_model从测试集获取数据,validate_model从验证集获得数据。

# 编译Theano函数,计算小批量的误差
test_model = theano.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.error(y),
    givens = {
        x : test_set_x[index * batch_size : (index + 1) * batch_size],
        y : test_set_y[index * batch_size : (index + 1) * batch_size]
    }
)

Putting it All Together

代码见原网站

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值