softmax回归的实现

427 阅读1分钟

导包

import d2lzh as d2l
from mxnet import autograd,nd

读数据

batch_size = 256
train_iter,test_iter = d2l.load_data_fashion_mnist(batch_size)

初始化模型参数

num_inputs = 784
num_outputs =10
W =nd.random.normal(scale=0.01,shape=(num_inputs,num_outputs))
b = nd.zeros(num_outputs)

这不没有实际意义只是为W,b的梯度分配内存

W.attach_grad()
b.attach_grad()

实现softamax运算

def softmax(X):
    X_exp =X.exp()
    partition = X_exp.sum(axis=1,keepdims=True)
    return X_exp / partition

效果如下图,随机取值。每行的和为1

定义模型

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

调整输入的X的大小,然后进行点乘并加上偏差值

定义损失函数

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

交叉熵损失函数
补充下pick()函数
就是选择。。。没有花头的

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

就是说选择y_hat的1组0和2组2元素 也就是0,1和0.5

计算分类准确率

def accuracy(y_hat,y):
    return (y_hat.argmax(axis=1) == y.astype('float32')).mean().asscalar()

这时候一定会有人问asscalar()是什么
将向量X转换成标量,且向量X只能为一维含单个元素的向量

还有astype
就是转换数组的数据类型。

具一次来评价其准确性。
分析
acc_sum 和n 用来计数
重置y的类型 当X输入net后最大值与y相同则增加 y为输入的总量

def evaluate_accuraacy(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

输入数据
输出训练的结果

训练模型

输入各模块
输出最终预测得分

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)#预测
                l = loss(y_hat,y).sum()
            l.backward()#反馈
            if trainer is None:#默认训练器
                d2l.sgd(params,lr,batch_size)
            else:
                trainer.step(batch_size)
            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_accuraacy(test_iter,net)
        print('epoch %d ,loss %.4f,train acc %.3f,test acc %.3f'
             % (epoch+1,train_l_sum / n,train_acc_sum/n,test_acc))
num_epochs,lr =5,0.1
train_ch3(net,train_iter,test_iter,cross_entropy,num_epochs,batch_size,[W,b],lr)

输出样式