线性回归模型适用于输出为连续值的情景,例如输出为房价。在其他情景中,模型输出还可以是一个离散值,例如图片类别。对于这样的分类问题,我们可以使用分类模型,例如softmax回归。

为了便于讨论,让我们假设输入图片的尺寸为2×2,并设图片的四个特征值,即像素值分别为\(x_1,x_2,x_3,x_4\)。假设训练数据集中图片的真实标签为狗、猫或鸡,这些标签分别对应离散值\(y_1,y_2,y_3\)。

单样本分类的矢量计算表达式

针对上面的问题,假设分类模型的权重和偏差参数分别为:

\[W=\begin{bmatrix}
w_11 & w_12 & w_13 \\
w_21 & w_22 & w_23 \\
w_31 & w_32 & w_33 \\
w_41 & w_42 & w_43
\end{bmatrix}, b=\begin{bmatrix}
b_1 & b_2 & b_3
\end{bmatrix}
\]

设某样本为:\(x^{(i)}=[x_1^{(i)}, x_2^{(i)}, x_3^{(i)}, x_4^{(i)}]\),输出层为\(o^{(i)}=[o_1^{(i)}, o_2^{(i)}, o_3^{(i)}]\),预测为狗、猫或鸡的概率为\(y^{(i)}=[y_1^{(i)}, y_2^{(i)}, y_3^{(i)}]\)。

小批量样本的适量计算表达式

如果每个批次有n个样本,假设输入特征数为x,输出类别数为y,则:X的size为nx,W的维度为xy,b的维度为1*y。

\[O=XW+b, \hat(Y)=softmax(O)
\]

这里的加法运算使用了广播机制。

交叉熵损失函数

Softmax回归使用了交叉熵损失函数(cross-entropy

loss)。给定分类问题的类别个数m。当样本i的标签类别为\(y_j\)时 (\(1 \leq j \leq m\)),设\(q_j^{(i)}=1\)且当\(k \neq j, 1 \leq k \leq m\)时\(q_k^{(i)}=0\)。

设模型对样本i在类别\(y_j\)上的预测概率为\(p_j^{(i)}\)(\(1 \leq j \leq m\))。假设训练数据集的样本数为n,交叉熵损失函数定义为

\[\ell(\boldsymbol{\Theta}) = -\frac{1}{n} \sum_{i=1}^n \sum_{j=1}^m q_j^{(i)} \log p_j^{(i)},
\]

其中\(\boldsymbol{\Theta}\)代表模型参数。在训练softmax回归时,我们将使用优化算法来迭代模型参数并不断降低损失函数的值。

不妨从另一个角度来理解交叉熵损失函数。在训练模型时,对于训练数据集上每个样本,总体上我们希望模型对这些样本真实的标签类别的预测概率尽可能大,也就是希望模型尽可能容易输出真实的标签类别。

设\(p_{\text{label}_i}\)是模型对样本i的标签类别的预测概率,并设训练数据集的样本数为n。由于对数函数单调递增,最大化训练数据集所有标签类别的联合预测概率\(\prod_{i=1}^n p_{\text{label}_i}\)等价于最大化<\(\sum_{i=1}^n \log p_{\text{label}_i}\),即最小化\(-\sum_{i=1}^n \log p_{\text{label}_i}\),因此也等价于最小化以上定义的交叉熵损失函数。

softmax回归

获取Fashion-MNIST数据集

我们使用一个类别为数字的数据集MNIST。该数据集中,图片尺寸为:math:28 times 28,一共包括了10个类别。

from mxnet.gluon import data as gdata

def transform(feature, label):
return feature.astype('float32') / 255, label.astype('float32') mnist_train = gdata.vision.MNIST(train=True, transform=transform)
mnist_test = gdata.vision.MNIST(train=False, transform=transform) feature, label = mnist_train[0]
print 'feature shape: ', feature.shape, 'label: ', label

读取数据

batch_size = 256
train_iter = gdata.DataLoader(mnist_train, batch_size, shuffle=True)
test_iter = gdata.DataLoader(mnist_test, batch_size, shuffle=False)

初始化模型参数

模型的输入向量的长度是28×28=784:该向量的每个元素对应图片中每个像素。由于图片有10个类别,单层神经网络输出层的输出个数为10。由上一节可知,Softmax回归的权重和偏差参数分别为784×10和1×10的矩阵。

num_inputs = 784
num_outputs = 10 W = nd.random_normal(scale=0.01, shape=(num_inputs, num_outputs))
b = nd.zeros(num_outputs)
params = [W, b]
for param in params:
param.attach_grad()

定义softmax函数

#在结果中保留行和列这两个维度(keepdims=True)
def softmax(X):
exp = X.exp()
partition = exp.sum(axis=1, keepdims=True)
return exp / partition # 这里应用了广播机制。

定义模型

通过reshape函数将每张原始图片改成长度为num_inputs的向量。

def net(X):
return softmax(nd.dot(X.reshape((-1, num_inputs)), W) + b)

定义损失函数

通过使用pick函数,我们得到了2个样本的标签的被预测概率。

y_hat = nd.array([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y = nd.array([0, 2])
nd.pick(y_hat, y)
# output
[ 0.1 0.5]
<NDArray 2 @cpu(0)>

交叉熵损失函数翻译成代码:

def cross_entropy(y_hat, y):
return -nd.pick(y_hat.log(), y)

模型的评测-计算分类精度

分类准确率即正确预测数量与总预测数量的比。

def accuracy(y_hat, y):
return (nd.argmax(y_hat, axis=1) == y).asnumpy().mean() def evaluate_accuracy(data_iter, net):
acc = 0
for X, y in data_iter:
acc += accuracy(net(X), y)
return acc / len(data_iter)

因为我们随机初始化了模型net,所以这个模型的准确率应该接近于1 / num_outputs = 0.1。

evaluate_accuracy(test_iter, net)
# output
0.0947265625

训练模型

在训练模型时,迭代周期数num_epochs和学习率lr都是可以调的超参数。改变它们的值可能会得到分类更准确的模型。

def sgd(params, lr, batch_size):
for param in params:
param[:] = param - lr * param.grad / batch_size num_epochs = 5
lr = 0.1
loss = cross_entropy def train_cpu(net, train_iter, test_iter, loss, num_epochs, batch_size, params=None, lr=None, trainer=None):
for epoch in range(1, num_epochs + 1):
train_l_sum = 0
train_acc_sum = 0
for X, y in train_iter:
with autograd.record():
y_hat = net(X)
l = loss(y_hat, y)
l.backward()
if trainer is None:
sgd(params, lr, batch_size)
else:
trainer.step(batch_size)
train_l_sum += nd.mean(l).asscalar()
train_acc_sum += accuracy(y_hat, y)
test_acc = evaluate_accuracy(test_iter, net)
print("epoch %d, loss %.4f, train acc %.3f, test acc %.3f"% (epoch, train_l_sum / len(train_iter), train_acc_sum / len(train_iter), test_acc)) train_cpu(net, train_iter, test_iter, loss, num_epochs, batch_size, params, lr)
# output
epoch 1, loss 0.7105, train acc 0.842, test acc 0.884
epoch 2, loss 0.4296, train acc 0.887, test acc 0.899
epoch 3, loss 0.3840, train acc 0.896, test acc 0.905
epoch 4, loss 0.3607, train acc 0.901, test acc 0.909
epoch 5, loss 0.3461, train acc 0.905, test acc 0.911

预测

data, label = mnist_test[0:9]
predicted_labels = net(data).argmax(axis=1)

Softmax回归——使用Gluon

Softmax和交叉熵损失函数

分开定义Softmax运算和交叉熵损失函数可能会造成数值不稳定。因此,Gluon提供了一个包括Softmax运算和交叉熵损失计算的函数。它的数值稳定性更好。

程序实现

# -*- coding: utf-8 -*-
from mxnet import init #定义数据源
import gb
batch_size = 256
train_iter, test_iter = gb.load_data_fashion_mnist(batch_size) #定义网络
from mxnet.gluon import nn
net = nn.Sequential()
net.add(nn.Flatten())
net.add(nn.Dense(10))
net.initialize(init.Normal(sigma=0.01)) #损失函数
from mxnet.gluon import loss as gloss
loss = gloss.SoftmaxCrossEntropyLoss() #优化算法
from mxnet.gluon import Trainer
trainer = Trainer(net.collect_params(), 'sgd', {'learning_rate': 0.1}) #训练模型
num_epochs = 5
gb.train_cpu(net, train_iter, test_iter, loss, num_epochs, batch_size, None,
None, trainer)

基础函数包 gb.py

from mxnet.gluon import data as gdata
from mxnet import autograd
from mxnet import ndarray as nd def transform(feature, label):
return feature.astype('float32') / 255, label.astype('float32') mnist_train = gdata.vision.MNIST(train=True, transform=transform)
mnist_test = gdata.vision.MNIST(train=False, transform=transform) def load_data_fashion_mnist(batch_size):
train_iter = gdata.DataLoader(mnist_train, batch_size, shuffle=True)
test_iter = gdata.DataLoader(mnist_test, batch_size, shuffle=False)
return train_iter, test_iter def accuracy(y_hat, y):
return (nd.argmax(y_hat, axis=1) == y).asnumpy().mean() def evaluate_accuracy(data_iter, net):
acc = 0
for X, y in data_iter:
acc += accuracy(net(X), y)
return acc / len(data_iter) def sgd(params, lr, batch_size):
for param in params:
param[:] = param - lr * param.grad / batch_size def train_cpu(net, train_iter, test_iter, loss, num_epochs, batch_size, params=None, lr=None, trainer=None):
for epoch in range(1, num_epochs + 1):
train_l_sum = 0
train_acc_sum = 0
for X, y in train_iter:
with autograd.record():
y_hat = net(X)
l = loss(y_hat, y)
l.backward()
if trainer is None:
sgd(params, lr, batch_size)
else:
trainer.step(batch_size)
train_l_sum += nd.mean(l).asscalar()
train_acc_sum += accuracy(y_hat, y)
test_acc = evaluate_accuracy(test_iter, net)
print("epoch %d, loss %.4f, train acc %.3f, test acc %.3f" % (
epoch, train_l_sum / len(train_iter), train_acc_sum / len(train_iter), test_acc))

MXNET:分类模型的更多相关文章

  1. 笔记︱风控分类模型种类(决策、排序)比较与模型评估体系(ROC/gini/KS/lift)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 本笔记源于CDA-DSC课程,由常国珍老师主讲 ...

  2. Spark学习笔记——构建分类模型

    Spark中常见的三种分类模型:线性模型.决策树和朴素贝叶斯模型. 线性模型,简单而且相对容易扩展到非常大的数据集:线性模型又可以分成:1.逻辑回归:2.线性支持向量机 决策树是一个强大的非线性技术, ...

  3. 利用libsvm-mat建立分类模型model参数解密[zz from faruto]

    本帖子主要就是讲解利用libsvm-mat工具箱建立分类(回归模型)后,得到的模型model里面参数的意义都是神马?以及如果通过model得到相应模型的表达式,这里主要以分类问题为例子. 测试数据使用 ...

  4. 【AUC】二分类模型的评价指标ROC Curve

    AUC是指:从一堆样本中随机抽一个,抽到正样本的概率比抽到负样本的概率大的可能性! AUC是一个模型评价指标,只能用于二分类模型的评价,对于二分类模型,还有很多其他评价指标,比如logloss,acc ...

  5. Spark机器学习4·分类模型(spark-shell)

    线性模型 逻辑回归--逻辑损失(logistic loss) 线性支持向量机(Support Vector Machine, SVM)--合页损失(hinge loss) 朴素贝叶斯(Naive Ba ...

  6. sklearn特征选择和分类模型

    sklearn特征选择和分类模型 数据格式: 这里.原始特征的输入文件的格式使用libsvm的格式,即每行是label index1:value1 index2:value2这样的稀疏矩阵的格式. s ...

  7. Windows下mnist数据集caffemodel分类模型训练及测试

    1. MNIST数据集介绍 MNIST是一个手写数字数据库,样本收集的是美国中学生手写样本,比较符合实际情况,大体上样本是这样的: MNIST数据库有以下特性: 包含了60000个训练样本集和1000 ...

  8. Edgeboard试用 — 基于CIFAR10分类模型的移植

    前言 在上一次的测试中,我们按照官方给的流程,使用EasyDL快速实现了一个具有性别检测功能的人脸识别系统,那么今天,我们将要试一下通过Paddlepaddle从零开始,训练一个自己的多分类模型,并进 ...

  9. python实现感知机线性分类模型

    前言 感知器是分类的线性分类模型,其中输入为实例的特征向量,输出为实例的类别,取+1或-1的值作为正类或负类.感知器对应于输入空间中对输入特征进行分类的超平面,属于判别模型. 通过梯度下降使误分类的损 ...

随机推荐

  1. 李宏毅机器学习笔记1:Regression、Error

    李宏毅老师的机器学习课程和吴恩达老师的机器学习课程都是都是ML和DL非常好的入门资料,在YouTube.网易云课堂.B站都能观看到相应的课程视频,接下来这一系列的博客我都将记录老师上课的笔记以及自己对 ...

  2. Java—集合框架详解

    一.描述Java集合框架 集合,在Java语言中,将一系类的对象看成一个整体. 首先查看jdk中的Collection类的源码后会发现Collection是一个接口类,其继承了java迭代接口Iter ...

  3. sql注入总结(二)--2018自我整理

    0x00前言: 继上篇的内容,这章总结下二次注入,python脚本,bypass 上篇sql注入总结(一)--2018自我整理 0x01二次注入: 二次注入的原理是在把非法代码添加进数据库里面存储了, ...

  4. 利用FutureTask进行超时设置方法

    public class Test {   public static void main(String[] args) { ExecutorService executor = Executors. ...

  5. Android-LruCache与DiskLruCache

    Android LruCache与DiskLruCache 学习自 Android开发艺术探索 https://blog.csdn.net/guolin_blog/article/details/28 ...

  6. NOIP 2000 乘积最大

    分析: 这一题虽然是加强版的,但也就是数据范围比原题大了点儿,思路都一样,在原题的基础上加一个高精度乘法就OK了,下面说一下算法:看到题首先想到的就是动态规划,你会发现这一题极像一道经典题目---添加 ...

  7. php中14中排序方式的实现

    <?php if (PHP_SAPI == 'cli') {         define('EOL', PHP_EOL);         define('T', "\t" ...

  8. 安装 Keepalived

    安装环境 [root@node1 ~]# cat /etc/redhat-release CentOS Linux release (Core) [root@node1 ~]# cat /proc/v ...

  9. http://blog.csdn.net/wzzvictory/article/details/16994913

      原文地址:http://blog.csdn.net/wzzvictory/article/details/16994913   一.什么是instancetype instancetype是cla ...

  10. MySQL查看数据库表容量大小

    本文介绍MySQL查看数据库表容量大小的命令语句,提供完整查询语句及实例,方便大家学习使用. 1.查看所有数据库容量大小 select table_schema as '数据库', sum(table ...