《动手学深度学习》softmax回归的从零开始实现代码理解

softmax从零实现-逐行代码学习


代码来自B站的 跟着李沐学AI.,已学过吴恩达的深度学习,但是代码还是有很多看不懂,只好一步一步做记录了,分享的时候顺便学习,有不对的地方希望能替我指出来,或者说有更容易的理解方式也请帮帮忙。

import torch
from IPython import display
from d2l import torch as d2l

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

num_inputs = 784
num_outputs = 10
#返回一个从独立的正态分布中抽取的随机数的张量,正态分布的平均值为0,方差为0.01784*10的矩阵,开启梯度保存
W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)
b = torch.zeros(num_outputs, requires_grad=True)
def softmax(X):#定义一个softmax函数,有人说这个写的有溢出的可能,目前我还不懂
    X_exp = torch.exp(X) #对X中的每个值变成ex
    partition = X_exp.sum(1, keepdim=True) #按列取和,保持维度不变
    return X_exp / partition  # 这里应用了广播机制
-----------------------------------------------------------------------------------------
解释
X = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) #2*3矩阵 size[2,3]
X_exp = torch.exp(X)
X_exp                                                #2*3矩阵 size[2,3]
>>tensor([[1.3673, 1.0601, 1.9367, 5.2293, 1.1470],
        [1.2775, 1.2895, 1.2460, 0.5687, 0.4273]])
X_exp.sum(1, keepdim=True)                         #2*1矩阵,保证维度不变,size[2,1]并不会改变维度
>>tensor([[10.7405],
        [ 4.8090]])
X_exp / partition
>>tensor([[0.1273, 0.0987, 0.1803, 0.4869, 0.1068],
        [0.2656, 0.2681, 0.2591, 0.1183, 0.0888]])
def net(X):
    return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)
#定义了一个网络,z=x*w+b   ,a=softmax(z)return的a就是上面的 X_exp / partition
y = torch.tensor([0, 2]) #y是标签,假设有两个样本(图片0,图片1),有三个类别(猫,狗,鱼),图片0正确是猫,图片1正确是鱼
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])#y_hat是预测值张量,图片0的概率[=0.1,狗=0.3,鱼=0.6],图片1····
y_hat[[0, 1], y] #取出图片0对猫的预测,和图片1对鱼的预测值  tensor([0.1000, 0.5000])
>>测试一下 y_hat[[0, 1], [1, 1]]
>>tensor([0.3000, 0.2000])
def cross_entropy(y_hat, y): 
    return - torch.log(y_hat[range(len(y_hat)), y]) #返回损失函数值 损失函数的公式 -log(预测值)cross_entropy(y_hat, y) #输出的是样本0的损失,以及样本1的损失
def accuracy(y_hat, y):  #@save
    """计算预测正确的数量"""
    if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
        y_hat = y_hat.argmax(axis=1) #返回一个tensor,元素是每行中最大元素的索引
    cmp = y_hat.type(y.dtype) == y #把y_hat的数据类型转换成与y相同的数据类型 
    return float(cmp.type(y.dtype).sum()) #计算预测对的总数
def evaluate_accuracy(net, data_iter):  #@save
    """计算在指定数据集上模型的精度"""
    if isinstance(net, torch.nn.Module):#判断net是不是nn.Module
        net.eval()  # 将模型设置为评估模式,这是在测试集使用,训练集要关闭
#神经网络模块存在两种模式,train模式(net.train())和eval模式(net.eval())。一种训练用,一种测试使用
#参考https://www.jianshu.com/p/ef2a7a78aa83
    metric = Accumulator(2)  # 正确预测数、预测总数
    with torch.no_grad():    # 关闭梯度计算
        for X, y in data_iter:
            metric.add(accuracy(net(X), y), y.numel())#把预测对的个数,预测总数放入一个列表
    return metric[0] / metric[1]  #输出正确率

class Accumulator:  #@save  #具体用法参考这个博客https://blog.csdn.net/weixin_44556141/article/details/120116161
    """在n个变量上累加"""
    def __init__(self, n):
        self.data = [0.0] * n                       #[0.0]*2 ==>[0.0 , 0.0]

    def add(self, *args):         #*args的用法:当传入的参数个数未知,且不需要知道参数名称时。
        self.data = [a + float(b) for a, b in zip(self.data, args)] #a是data中的数,b是args中的数

    def reset(self):
        self.data = [0.0] * len(self.data)

    def __getitem__(self, idx):
        return self.data[idx]
evaluate_accuracy(net, test_iter)  #net参数是一个之前的网络函数,忘记python可以把函数作为参数传递了
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值