MXNET:分类模型

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

原文地址:https://www.cnblogs.com/houkai/p/9519866.html

时间: 2024-10-30 21:41:56

MXNET:分类模型的相关文章

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

Spark中常见的三种分类模型:线性模型.决策树和朴素贝叶斯模型. 线性模型,简单而且相对容易扩展到非常大的数据集:线性模型又可以分成:1.逻辑回归:2.线性支持向量机 决策树是一个强大的非线性技术,训练过程计算量大并且较难扩展(幸运的是,MLlib会替我们考虑扩展性的问题),但是在很多情况下性能很好: 朴素贝叶斯模型简单.易训练,并且具有高效和并行的优点(实际中,模型训练只需要遍历所有数据集一次).当采用合适的特征工程,这些模型在很多应用中都能达到不错的性能.而且,朴素贝叶斯模型可以作为一个很

分类模型评估

一直对于各种分类器评估的指标有点晕,今天决定琢磨下,并且写下来,方便以后回忆. 一.混淆矩阵 来源于信息论,根据上面的混淆矩阵,有3个指标需要搞清楚,我觉得记公式真的很容易搞混,建议大家都直接记文字加上自己理解就好了. 准确率=正确预测正负的个数/总个数(这个指标在python中的交叉验证时可以求准确率) 覆盖率(也叫作召回率)=正确预测正的个数/实际正的个数 (当然也可以是负覆盖率) 命中率=正确预测正的个数/预测正的个数 以上指标,在Python中提供混淆矩阵的报告 二.ROC 之所以又有R

分类模型评估与选择总结

1.评估分类器性能的度量 当建立好一个分类模型之后,就会考虑这个模型的性能或准确率如何,这里介绍几种分类器评估度量如下表: 假设在有标号的元组组成的训练集上使用分类器.P是正元组数,N是负元组数. 度量 公式 准确率.识别率 (TP+TN)/(P+N) 错误率.误分类率 (FP+FN)/(P+N) 敏感度.真正例率.召回率 TP/P 特效型.真负例率 TN/N 精度 TP/(TP+FP) F.F1.F分数 精度和召回率的调和均值 2*precision*recall/(precision+rec

spark机器学习笔记:(五)用Spark Python构建分类模型(下)

声明:版权所有,转载请联系作者并注明出处  http://blog.csdn.net/u013719780?viewmode=contents 博主简介:风雪夜归子(英文名:Allen),机器学习算法攻城狮,喜爱钻研Meachine Learning的黑科技,对Deep Learning和Artificial Intelligence充满兴趣,经常关注Kaggle数据挖掘竞赛平台,对数据.Machine Learning和Artificial Intelligence有兴趣的童鞋可以一起探讨哦,

sklearn特征选择和分类模型

数据格式: 这里.原始特征的输入文件的格式使用libsvm的格式,即每行是label index1:value1 index2:value2这样的稀疏矩阵的格式. sklearn中自带了非常多种特征选择的算法. 我们选用特征选择算法的根据是数据集和训练模型. 以下展示chi2的使用例.chi2,採用卡方校验的方法进行特征选择.比較适合0/1型特征和稀疏矩阵. from sklearn.externals.joblib import Memory from sklearn.datasets imp

机器学习二分类模型评价指标:准确率\召回率\特异度等

混淆矩阵是一种用于性能评估的方便工具,它是一个方阵,里面的列和行存放的是样本的实际类vs预测类的数量. P =阳性,N =阴性:指的是预测结果. T=真,F=假:表示 实际结果与预测结果是否一致,一致为真,不一致为假. TP=真阳性:预测结果为P,且实际与预测一致. FP=假阳性:预测结果为P,但与实际不一致. TN=真阴性:预测结果为N,且与实际一致. FN=假阴性:预测结果为N,但与实际不一致. 分类模型的经验误差可以通过计算1-准确率得到. 然而,如何选择一个适当的预测误差度量是高度依赖于

分类模型评估指标

对于分类模型的评价指标主要有错误率 .准确率.查准率.查全率.混淆矩阵.F1值.AUC和ROC. 1.1 错误率和准确率 错误率(Error rate):通常把分类错误的样本数占总样本总数的比例称为"错误率". 准确率(Accuracy):是指分类正确的样本数占样本总数的比例,即准确率=1-错误率. 1.2 查准率.查全率.混淆矩阵和F1值 查准率(Precision):又称精确率,预测为正例的样本中,真正为正例的比率. 查全率(Recall):又称召回率,预测为正例的真实正例(TP)

使用交叉验证对鸢尾花分类模型进行调参(超参数)

如何选择超参数: 交叉验证: 如图, 大训练集分块,使用不同的分块方法分成N对小训练集和验证集. 使用小训练集进行训练,使用验证集进行验证,得到准确率,求N个验证集上的平均正确率: 使用平均正确率最高的超参数,对整个大训练集进行训练,训练出参数. 在训练集上训练. 十折交叉验证 网格搜索 诸如你有多个可调节的超参数,那么选择超参数的方法通常是网格搜索,即固定一个参.变化其他参,像网格一样去搜索. # 人工智能数据源下载地址:https://video.mugglecode.com/data_ai

吴裕雄 python 机器学习——集成学习随机森林RandomForestClassifier分类模型

import numpy as np import matplotlib.pyplot as plt from sklearn import datasets,ensemble from sklearn.model_selection import train_test_split def load_data_classification(): ''' 加载用于分类问题的数据集 ''' # 使用 scikit-learn 自带的 digits 数据集 digits=datasets.load_d