深度学习softmax回归

softmax回归预测多分类问题,预测值的输出为每一个样本所属q个类别的概率,比如一个样本有三个类别,则输出可能为[0.1, 0.8, 0.1],表示该样本属于第二个类别。

花书中的softmax回归介绍相对简单,主要思想是使用softmax函数将预测值转化为值为正且和为1的概率

                                                               O = XW +b

                                                            \hat{y} = softmax(O)

如在上述公式中,若O的预测值为0.1,10,0.1,那么经过softmax函数,这三个预测输出大概变为0.01,0.98,0.1,这样输出中为类别2的概率最大,据此判断预测类别为2

同时,softmax使用交叉熵作为损失函数,因为交叉熵损失更偏重于概率大的那个值,而我们只需要将输出概率大的类别作为最终类别就行。

具体代码

这里书中的load_data_fashion_mnist(batch_size)函数是使用的d2l包中的函数,但是我们已经将FashionMNIST数据集下载到本地,不用重新下载,因此安前边代码,自己重写这个函数

import d2lzh as d2l
from mxnet import autograd,nd
import mxnet as mx
from mxnet.gluon import data as gdata
import sys

def load_data_fashion_mnist(batch_size):
    mnist_train = gdata.vision.FashionMNIST(root=r'C:/Users/Wu/AppData/Roaming/mxnet/datasets/fashion-mnist/',train=True)
    mnist_test = gdata.vision.FashionMNIST(root=r'C:/Users/Wu/AppData/Roaming/mxnet/datasets/fashion-mnist/',train=False)
    transformer = gdata.vision.transforms.ToTensor()
    if sys.platform.startswith('win'):
        num_workers = 0  # 表示不用额外进程来加速读取数据
    else:
        num_workers = 4

    train_iter = gdata.DataLoader(mnist_train.transform_first(transformer), batch_size, shuffle=True,num_workers=num_workers)
    test_iter = gdata.DataLoader(mnist_test.transform_first(transformer), batch_size, shuffle=False,num_workers=num_workers)
    return train_iter,test_iter

#小批量数据集
batch_size = 256
train_iter, test_iter = load_data_fashion_mnist((batch_size))


# print(len(train_iter))
#使用向量表示每个样本,所以将二维的变成一维的
num_inputs = 784 #28*28回归权重
num_outputs = 10 #10个类别,偏差参数

w = nd.random.normal(scale=0.01, shape=(num_inputs,num_outputs),ctx=mx.gpu())
b = nd.zeros(num_outputs,ctx=mx.gpu())

w.attach_grad()
b.attach_grad()

#定义softmax函数,只是把矩阵进行指数变换
#输入行为样本数,列为输出个数;输出每一行和为一,代表这个样本属于一个类别的概率
def softmax(x):
    x_exp = x.exp()
    partition = x_exp.sum(axis=1, keepdims=True)#1为行求和
    return x_exp / partition #广播机制

#定义模型
def net(x):
    return softmax(nd.dot(x.reshape((-1,num_inputs)),w) + b)

y_hat = nd.array([[0.1,0.3,0.6],[0.3,0.2,0.5]])
y = nd.array([0,2],dtype = 'int32')

#示例pick函数
print(nd.pick(y_hat,y))
#损失函数
def cross_entropy(y_hat,y):
    return -nd.pick(y_hat,y).log()

#分类准确率:正确预测数量与总预测数量之比
def accuracy(y_hat, y):
    #y_hat.argmax(axis=1)返回每行最大的元素的索引,mean取值为1的占总数的比
    return (y_hat.argmax(axis=1) == y.astype('float32')).mean().asscalar()#返回一个NDArray

#示例
print((y_hat.argmax(axis=1) == y.astype('float32')))
print(accuracy(y_hat,y))

#评价模型net在数据集上的精确度
def evaluate_accuracy(data_iter, net):
    #分布准确的数量除以总数
    acc_sum, n = 0.0, 0
    for x, y in data_iter:
        x = x.copyto(mx.gpu())
        y = y.copyto(mx.gpu())
        y = y.astype('float32')
        acc_sum += (net(x).argmax(axis=1) == y).sum().asscalar()
        n += y.size
    return acc_sum / n
#随机初始变量,所以此时精度应该接近0.1
print(evaluate_accuracy(test_iter,net))

num_epochs, lr = 5, 0.1

def train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params=None, lr=None, trainer=None):
    for epoch in range(num_epochs):
        # 总的损失# 总的准确率
        train_loss_sum , train_acc_sum, n = 0.0, 0.0, 0
        for X, y in train_iter:
            X = X.copyto(mx.gpu())
            y = y.copyto(mx.gpu())
            with autograd.record():
                y_hat = net(X)
                los = loss(y_hat, y).sum()
            # 求梯度
            los.backward()
            if trainer is None:
                # 小批量随机梯度下降
                d2l.sgd(params, lr, batch_size)
            else:
                trainer.step(batch_size)
            train_loss_sum += los.asscalar()
            train_acc_sum += accuracy(y_hat, y)
            n += y.size
        test_acc = evaluate_accuracy(test_iter,net)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f'
              % (epoch + 1, train_loss_sum / n, train_acc_sum / n,test_acc))

train_ch3(net,train_iter,test_iter,cross_entropy,num_epochs,batch_size,[w,b],lr)




 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值