Softmax函数从零开始实现——2020.2.22

?????先导?本节实现所需的包或模块。

import torch
import torchvision
import numpy as np
import sys
sys.path.append("..") # 为了导?上层?录的d2lzh_pytorch
import d2lzh_pytorch as d2l

1.获取数据集

????使?Fashion-MNIST数据集,并设置批量??为256。

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

2.初始化模型参数

????跟线性回归中的例??样,我们将使?向量表示每个样本。已知每个样本输?是?和宽均为28像素的图像。模型的输?向量的?度是\(28 \times 28 =784\):该向量的每个元素对应图像中每个像素。由于图像有10个类别,单层神经?络输出层的输出个数为10,因此softmax回归的权重和偏差参数分别为\(784 \times 10\)和\(1 \times 10\)的矩阵。

num_inputs = 784
num_outputs = 10
W = torch.tensor(np.random.normal(0, 0.01, (num_inputs,
num_outputs)), dtype=torch.float)
b = torch.zeros(num_outputs, dtype=torch.float)

????需要模型参数梯度,进行跟踪。

W.requires_grad_(requires_grad=True)
b.requires_grad_(requires_grad=True)

3. 实现softmax运算

????对多维Tensor按维度操作:给定?个 Tensor 矩阵 X 。我们可以只对其中同?列( dim=0 )或同??( dim=1 )的元素求和,并在结果中保留?和列这两个维度( keepdim=True )。

X = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(X.sum(dim=0, keepdim=True))
print(X.sum(dim=1, keepdim=True))

输出结果:

tensor([[5, 7, 9]])
tensor([[ 6], [15]])

定义softmax运算
????矩阵 X 的?数是样本数,列数是输出个数。为了表达样本预测各个输出的概率,softmax运算会先通过 exp 函数对每个元素做指数运算,再对 exp 矩阵同?元素求和,最后令矩阵每?各元素与该?元素之和相除。这样?来,最终得到的矩阵每?元素和为1且?负。因此,该矩阵每?都是合法的概率分布。softmax运算的输出矩阵中的任意??元素代表了?个样本在各个输出类别上的预测概率。

def softmax(X):
 X_exp = X.exp()
 partition = X_exp.sum(dim=1, keepdim=True)
 return X_exp / partition # 这?应?了?播机制

????可以看到,对于随机输?,我们将每个元素变成了?负数,且每??和为1。

X = torch.rand((2, 5))
X_prob = softmax(X)
print(X_prob, X_prob.sum(dim=1))

输出结果:

tensor([[0.2206, 0.1520, 0.1446, 0.2690, 0.2138], [0.1540, 0.2290, 0.1387, 0.2019, 0.2765]]) tensor([1., 1.])

4. 定义模型

????定义上节描述的softmax回归模型了。这?通过 view 函数将每张原始图像改成?度为 num_inputs 的向量。

def net(X):
 return softmax(torch.mm(X.view((-1, num_inputs)), W) + b)

5. 定义损失函数

????为了得到标签的预测概率,我们可以使? gather 函数。在下?的例?中,变量 y_hat 是2个样本在3个类别的预测概率,变量 y 是这2个样本的标签类别。通过使? gather 函数,我们得到了2个样本的标签的预测概率。与softmax回归数学表述中标签类别离散值从1开始逐?递增不同,在代码中,标签类别的离散值是从0开始逐?递增的。

y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y = torch.LongTensor([0, 2])
y_hat.gather(1, y.view(-1, 1))

输出结果:

tensor([[0.1000], [0.5000]])

????实现softmax回归中的交叉熵损失函数:

def cross_entropy(y_hat, y):
 return - torch.log(y_hat.gather(1, y.view(-1, 1)))

6. 计算分类准确率

????给定?个类别的预测概率分布 y_hat ,我们把预测概率最?的类别作为输出类别。如果它与真实类别 y ?致,说明这次预测是正确的。分类准确率即正确预测数量与总预测数量之?。

为了演示准确率的计算,下?定义准确率 accuracy 函数。其中 y_hat.argmax(dim=1) 返回矩阵 y_hat 每 ? 中 最 ? 元 素 的 索 引 , 且 返 回 结 果 与 变 量 y 形 状 相 同 。 相 等 条 件 判 断式 (y_hat.argmax(dim=1) == y) 是?个类型为 ByteTensorTensor ,我们? float() 将其转换为值为0(相等为假)或1(相等为真)的浮点型 Tensor 。

def accuracy(y_hat, y):
 return (y_hat.argmax(dim=1) == y).float().mean().item()

????继续使?在演示 gather 函数时定义的变量 y_haty ,并将它们分别作为预测概率分布和标签。可以看到,第?个样本预测类别为2(该?最?元素0.6在本?的索引为2),与真实标签0不?致;第?个样本预测类别为2(该?最?元素0.5在本?的索引为2),与真实标签2?致。因此,这两个样本上的分类准确率为0.5。

print(accuracy(y_hat, y))

输出结果:

0.5

????评价模型 net 在数据集 data_iter 上的准确率。

# 本函数已保存在d2lzh_pytorch包中?便以后使?。该函数将被逐步改进:它的完整实现将在“图像增?”?节中描述
def evaluate_accuracy(data_iter, net):
    acc_sum, n = 0.0, 0
    for X, y in data_iter:
        acc_sum += (net(X).argmax(dim=1) == y).float().sum().item()
         n += y.shape[0]
    return acc_sum / n

????因为随机初始化了模型 net ,所以这个随机模型的准确率应该接近于类别个数10的倒数即0.1。

print(evaluate_accuracy(test_iter, net)

输出结果:

0.0568

7. 训练模型

num_epochs, lr = 5, 0.1
# 本函数已保存在d2lzh包中方便以后使用
def train_ch3(net, train_iter, test_iter, loss, num_epochs,
batch_size, params=None, lr=None, optimizer=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:
            y_hat = net(X)
            l = loss(y_hat, y).sum()

            # 梯度清零
            if optimizer is not None:
                optimizer.zero_grad()
            elif params is not None and params[0].grad is not None:
                for param in params:
                    param.grad.data.zero_()

            l.backward()
            if optimizer is None:
                d2l.sgd(params, lr, batch_size)
            else:
                optimizer.step() # “softmax回归的简洁实现”?节将?到

            train_l_sum += l.item()
            train_acc_sum += (y_hat.argmax(dim=1) == y).sum().item()
            n += y.shape[0]
        test_acc = evaluate_accuracy(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))

原文地址:https://www.cnblogs.com/somedayLi/p/12347277.html

时间: 2024-10-22 06:43:31

Softmax函数从零开始实现——2020.2.22的相关文章

softmax函数python实现

import numpy as np def softmax(x): """ 对输入x的每一行计算softmax. 该函数对于输入是向量(将向量视为单独的行)或者矩阵(M x N)均适用. 代码利用softmax函数的性质: softmax(x) = softmax(x + c) 参数: x -- 一个N维向量,或者M x N维numpy矩阵. 返回值: x -- 在函数内部处理后的x """ orig_shape = x.shape # 根据输

Softmax函数与交叉熵

在Logistic regression二分类问题中,我们可以使用sigmoid函数将输入Wx+b映射到(0,1)区间中,从而得到属于某个类别的概率.将这个问题进行泛化,推广到多分类问题中,我们可以使用softmax函数,对输出的值归一化为概率值 这里假设在进入softmax函数之前,已经有模型输出C值,其中C是要预测的类别数,模型可以是全连接网络的输出aa,其输出个数为C,即输出为: 所以对每个样本,它属于类别i的概率为: 通过上式可以保证 ,即属于各个类别的概率和为1 对softmax函数进

Sigmoid函数与Softmax函数的理解

1. Sigmod 函数 1.1 函数性质以及优点 其实logistic函数也就是经常说的sigmoid函数,它的几何形状也就是一条sigmoid曲线(S型曲线). 其中z是一个线性组合,比如z可以等于:b + w1*x1 + w2*x2.通过代入很大的正数或很小的负数到g(z)函数中可知,其结果趋近于0或1 A logistic function or logistic curve is a common “S” shape (sigmoid curve). 也就是说,sigmoid函数的功能

logistic函数和softmax函数

  简单总结一下机器学习最常见的两个函数,一个是logistic函数,另一个是softmax函数,若有不足之处,希望大家可以帮忙指正.本文首先分别介绍logistic函数和softmax函数的定义和应用,然后针对两者的联系和区别进行了总结. 1. logistic函数 1.1 logistic函数定义 引用wiki百科的定义: A logistic function or logistic curve is a common "S" shape (sigmoid curve). 其实逻

深入理解softmax函数

Softmax回归模型,该模型是logistic回归模型在多分类问题上的推广,在多分类问题中,类标签  可以取两个以上的值.Softmax模型可以用来给不同的对象分配概率.即使在之后,我们训练更加精细的模型时,最后一步也需要用softmax来分配概率.本质上其实是一种多种类型的线性分割,当类标签  取 2 时,就相当于是logistic回归模型. 在 softmax回归中,我们解决的是多分类问题(相对于 logistic 回归解决的二分类问题),类标  可以取  个不同的值(而不是 2 个).因

记账本开发记录——第五天(2020.1.22)

今天继续学习了javascript的相关内容,同时学习了关于表格标签的一些新标签. 首先,学习了如何使表格隔行换色.整体的思路不算复杂,用java里的思路就可以大致理解,以下是效果和代码: 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>表格隔行换色</title> 6 <script> 7 window.onl

记账本开发记录——第六天(2020.1.22)

在学习JQ之前,我上网百度了一下,看看是否有学习该部分的必要.根据网友所说,虽然JQ的使用率不比以前,但作为一个十分经典的框架,仍然值得学习.现在很多框架都依赖于JQ,这点也是不容忽略的.在JQ中的AJAX也是个很多公司需要的功能.总的来说对于初学者来说学习JQ还是很有必要的. 在学习了一部分JS的基础上,今天学习了jQuery的基本操作.jQuery其实就是js query(查询),从名字可以看到,jQuery是对JS代码的一个简单化的框架.运用JQ可以很简单的编写出用JS来说比较复杂的案例.

softmax函数

#include <vector> #include <cmath> //math.h std::vector<double> vsoftmax(std::vector<double> &v) { double sum=0; for(auto iter:v) { sum+=exp(iter); } std::vector<double> res; for(int i=0;i<v.size();i++) { res.push_back

思考题2020.1.22

很多同学博客里都说c语言不安全,不严谨,那么c语言哪里不安全,不严谨? 一.不严谨性: 1.C语言在数组下标越界的时候是不会提示错误的,这导致经常自己犯了数组越界的错误而不自知,只看到最后的运行结果是错误的,最后常常要经过好几次调试才能发现越界的错误(刚学数组的时候我经常干这事o(╥﹏╥)o) 2.对变量赋值的格式对应,要求不严格,在c语言中,我要是把一个浮点型数据赋给一个整型变量,在编译的时候只会给出警告,告诉你会丢失精度,但是是可以运行的,那这样子就导致在运行后发现有错,但是很难发现哪里出现