线性回归模型适用于输出为连续值的情景,例如输出为房价。在其他情景中,模型输出还可以是一个离散值,例如图片类别。对于这样的分类问题,我们可以使用分类模型,例如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. Linux系统之常用文件搜索命令

    (一)常用文件搜索命令 (1)which命令 (2)find命令 (3)locate (4)updatedb (5)grep (6)man (7)whatis (一)常用文件搜索命令 (1)which ...

  2. Ubuntu18.10&Ubuntu18.04安装Python虚拟环境

    Ubuntu18.04版本里面自带了最新的Python3.6.5版本,在安装Python虚拟环境时需注意: 1.首先是安装两个包 pip3 install virtualenv # python虚拟环 ...

  3. Angularjs 根据数据结构创建动态菜单无限嵌套循环--指令版

    目标:根据数据生成动态菜单,希望可以根据判断是否有子集无限循环下去. 菜单希望的样子是这样的: 菜单数据是这样的: $scope.expanders = [{ title: 'title1', lin ...

  4. 服务端、实时、大数据、AI计算

    服务端.实时.大数据.AI计算,各种各样的计算,计算机本质是什么,计算机的本质是 利用compute的计算速度为人提供更优的计算结果. 所以实时也好,准实时.离线.AI本质上是两个维度,实时准实时强调 ...

  5. BZOJ.3510.首都(LCT 启发式合并 树的重心)

    题目链接 BZOJ 洛谷 详见这. 求所有点到某个点距离和最短,即求树的重心.考虑如何动态维护. 两棵子树合并后的重心一定在两棵树的重心之间那条链上,所以在合并的时候用启发式合并,每合并一个点检查sz ...

  6. 2553 ACM N皇后 回溯递归

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2553 中文题目,题意很简单. 思路:听说这是学习递归的经典题目,就来试试,发现自己一点想法都没有,一遇到递 ...

  7. Codechef October Challenge 2018 游记

    Codechef October Challenge 2018 游记 CHSERVE - Chef and Serves 题目大意: 乒乓球比赛中,双方每累计得两分就会交换一次发球权. 不过,大厨和小 ...

  8. JTAG 引脚自动识别 JTAG Finder, JTAG Pinout Tool, JTAG Pin Finder, JTAG pinout detector, JTAGULATOR, Easy-JTAG, JTAG Enumeration

    JTAG Finder Figuring out the JTAG Pinouts on a Device is usually the most time-consuming and frustra ...

  9. hdu 4339 Query(两种思路求解)

    Query Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Su ...

  10. CSS网页布局垂直居中整理

    一.使用CSS3处理垂直居中方式 1.使用Flex布局处理(推荐),简单好用 body,html{ width:100%; height:100%; } .out { width: 20%; heig ...