深度学习笔记(四)

目录

本文将介绍以下内容

  • softmax回归从零开始实现
  • softmax回归的简洁实现
  • 小结



softmax回归从零开始实现


读取数据集

batch_size = 256
#Gluon的DataLoader中允许使用多进程加速数据读取(linux系统)
#在上一章的基础上,我们需要小批量的读取数据样本的函数
train_iter,test_iter = d2l.load_data_fashion_mnist(batch_size)

# 一共60000+10000组,每次取256组,大概235次,因此,train_iter表示一次性读取的数据
#对于一个train_iter,是一个256*1*28*28的矩阵,表示256张图片,跟batch_size有关
print(len(train_iter))  #235
print(len(test_iter))   #40

初始化参数模型

# 初始化模型参数
#图像 10个类别,单层输出个数10,权重784*10和偏差参数为10
num_inputs = 784
num_outputs = 10
W = nd.random.normal(scale=0.01,shape=(num_inputs,num_outputs))
b = nd.zeros(num_outputs)
W.attach_grad()
b.attach_grad()

实现softmax运算

# 实现softmax运算
def softmax(X):
    X_exp = X.exp()
    partition = X_exp.sum(axis=1,keepdims=True)
    return X_exp/partition  #运用广播机制

定义模型

#定义模型
def net(X):
    return softmax(nd.dot(X.reshape((-1,num_inputs)),W)+b)
#	假设传入的X是data_iter中的一个元素,也就是256*1*28*28
#	调用reshape把形状变成一维,也就是256个 1*784的矩阵
#	与权重参数W作矩阵乘法,256*[1*784*784*10] = 256个 1*10的矩阵
#   softmax运算,可以看公式就好理解了。比如1*10矩阵,首先,矩阵每个元素做指数运算,
#	axis=1,表示行相加,keepdims=Ture表示结果显示行和列
#	partition = 所有元素指数和
#	X_exp = 1 *10,/partition,广播机制,相当于每个元素都除以partition
#	返回一个概率矩阵	256*1*10

定义损失函数

def cross_entropy(y_hat,y):
    return -nd.pick(y_hat,y).log()
# pick函数,源矩阵 y_hat,大小是返回y矩阵的大小
# 作用,返回源矩阵中,y矩阵下标对应的位置
# 比如y_hat = [[1,2,3],[4,5,6]]
# y = [0,2]
# 返回y_hat[y[0]] = y_hat[0] = 1
# y_hat[y[1]] = y_hat[2] = 6
# 概率跟输出的值做交叉熵
# y是真实的标签
# y_hat是预测概率矩阵
# 交叉熵只关心对正确类别的预测概率,要么元素为0,其余全为1.

计算分类准确率

# 计算分类准确率
#给定一个类别的预测概率y_hat,概率最大类别作为输出类别。
# argmax是返回每行(每列,看axis)最大元素的索引,且返回结果与变量y的形状相同
# astype类型转换成float32,mean求均值,asscalar转换成标量
def accuracy(y_hat,y):
    return (y_hat.argmax(axis=1)==y.astype('float32')).mean().asscalar()
# 不使用astype转float32是否可行?

# 评价模型net在数据集data_iter上的准确率
def evaluate_accuracy(data_iter,net):
    acc_sum,n = 0.0,0
    for X,y in data_iter:
        y = y.astype('float32')
        acc_sum +=(net(X).argmax(axis=1)==y).sum().asscalar()
        n +=y.size
    return acc_sum/n
# y.size是batch_size大小,为256一次
# 首先把y(标签)转换成float32类型
# acc_sum 是准确率,调用net(X)进行softmax运算,然后将结果与y比较,求和,转标量

训练模型

# 训练模型

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_l_sum,train_acc_sum,n = 0.0,0.0,0
        for X,y in train_iter:
            with autograd.record():
                y_hat = net(X)	#进行softmax运算,转换成测试概率
                l = loss(y_hat,y).sum()	#损失函数的值求和
            l.backward()	#自动求梯度
            if trainer is None:
                d2l.sgd(params,lr,batch_size)	#调用随机梯度下降
            else:
                trainer.step(batch_size)	#否则调用Gluon中step求批量中样本梯度求平均
            y = y.astype('float32')			#转换
            train_l_sum +=l.asscalar()		#标量
            train_acc_sum +=(y_hat.argmax(axis=1)==y).sum().asscalar()	
            n +=y.size	
        test_acc = evaluate_accuracy(test_iter,net)	#一轮结束,求test准确率
        print('epoch %d,loss %.4f,train acc %.3f,test acc %.3f' %(epoch+1,train_l_sum/n,train_acc_sum/n,test_acc))

for X,y in test_iter:
    #调用函数
    #net 函数名
    #train_iter	训练数据
    #test_iter	测试数据
    #cross_entropy 交叉熵损失函数
    #num_epochs 轮数
    #batch_size	样本大小
    #[W,b] 权重和偏差
    # lr 学习率
    train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, batch_size, [W, b], lr)
 	#将索引转换成标签值
    true_labels = d2l.get_fashion_mnist_labels(y.asnumpy())
    #将索引转换成标签值
    pred_labels = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1).asnumpy())
    #显示的标题
    titles = [true + '\n' + pred for true, pred in zip(true_labels, pred_labels)]
    d2l.show_fashion_mnist(X[0:9], titles[0:9])
    #画图
    d2l.plt.show()
    break

运行结果

  • batch_size = 256
  • num_epochs= 3

在这里插入图片描述

  • batch_size = 256
  • num_epochs= 8

在这里插入图片描述

  • batch_size = 512
  • num_epochs= 8

在这里插入图片描述

  • batch_size = 128
  • num_epochs= 8
    在这里插入图片描述

分析,增加训练的轮数,能够明显增加数据测试的准确率,但增加一次性喂给神经网络的个数,有时候却不能增加数据测试的准确率。一次性样本数据太大,却不能及时进行梯度下降,导致测试准确率不高,相反减少样本数大小,能够提高测试准确率,由于模型的比较简单,因此,无法得到更好的效果。

在这里插入图片描述




softmax回归的简洁实现

import matplotlib
from mxnet import autograd,nd
from mxnet.gluon import nn
from utils import corr2d
from mxnet.gluon import data as gdata
from mxnet.gluon import nn
from mxnet import init
from mxnet.gluon import loss as gloss
from mxnet import gluon
import sys
import time
import d2lzh as d2l
from IPython import display
# 通过Gluon的data包下载数据集


batch_size = 256
#Gluon的DataLoader中允许使用多进程加速数据读取(linux系统)
#在上一章的基础上,我们需要小批量的读取数据样本的函数
train_iter,test_iter = d2l.load_data_fashion_mnist(batch_size)

# 定义和初始化模型

net = nn.Sequential()
net.add(nn.Dense(10))   #输出个数是10
net.initialize(init.Normal(sigma=0.01))

# 包括softmax运算和交叉熵损失计算的函数,数值稳定性更好
loss = gloss.SoftmaxCrossEntropyLoss()

# 定义优化算法

trainer = gluon.Trainer(net.collect_params(),'sgd',{'learning_rate':0.1})

# 训练模型

num_epochs = 5
test = d2l.train_ch3(net,train_iter,test_iter,loss,num_epochs,batch_size,None,None,trainer)
print(test)

运行结果

在这里插入图片描述




小结

  • Gluon提供函数更具有好的数值稳定性
  • 可以使用Gluon更简洁实现softmax回归
  • 可以使用softmax回归做多类别分类。


猜你喜欢

转载自blog.csdn.net/qq_40318498/article/details/100572280