首页 > 其他分享 >softmax回归

softmax回归

时间:2023-07-25 10:07:44浏览次数:40  
标签:num hat 回归 torch train softmax data sum

前面我们学习了线性回归,线性回归主要用于对于问题的预测,输出一个结果值,但问题往往不止这一种,我们每天也在处理很多分类的问题,要的结果是哪一种。所以本节学习softmax回归模型

分类问题

对于分类问题,我们要的结果是输出一个类别

统计学家很早以前就发明了一种表示分类数据的简单方法:独热编码(one-hot encoding)。 独热编码是一个向量,它的分量和类别一样多。 类别对应的分量设置为1,其他所有分量设置为0。

例如(1,0,0,)(0,1,0)(0,0,1)这三个向量分别代表三个类别

为了估计所有可能类别的条件概率,我们需要一个有多个输出的模型,每个类别对应一个输出。 为了解决线性模型的分类问题,我们需要和输出一样多的仿射函数(affine function)。 每个输出对应于它自己的仿射函数。 在我们的例子中,由于我们有4个特征和3个可能的输出类别, 我们将需要12个标量来表示权重(带下标的w), 3个标量来表示偏置(带下标的b)。 下面我们为每个输入计算三个未规范化的预测(logit):o1、o2和o3。

$$
\begin{split}\begin{aligned} o_1 &= x_1 w_{11} + x_2 w_{12} + x_3 w_{13} + x_4 w_{14} + b_1,\\ o_2 &= x_1 w_{21} + x_2 w_{22} + x_3 w_{23} + x_4 w_{24} + b_2,\\ o_3 &= x_1 w_{31} + x_2 w_{32} + x_3 w_{33} + x_4 w_{34} + b_3. \end{aligned}\end{split}
$$


与线性回归一样,softmax回归也是一个单层神经网络。

运算

对于softmax的运算,我们要介绍的是softmax函数

$$
\hat{\mathbf{y}} = \mathrm{softmax}(\mathbf{o})\quad \text{其中}\quad \hat{y}_j = \frac{\exp(o_j)}{\sum_k \exp(o_k)}
$$


这个公式y_hat代表的是正确的概率分布,取幂的目的是为了让数保持非负数,为了确保最终输出的概率值总和为1,我们再让每个求幂后的结果除以它们的总和。

$$
\operatorname*{argmax}_j \hat y_j = \operatorname*{argmax}_j o_j.
$$


如上,我们进行求最大输出值,输出可能最大的概率。尽管softmax是一个非线性函数,但softmax回归的输出仍然由输入特征的仿射变换决定。 因此,softmax回归是一个线性模型(linear model)。

损失函数

损失函数的确定也十分重要,我们使用极大似然估计法,求对数似然来作为损失函数

$$
-\log P(\mathbf{Y} \mid \mathbf{X}) = \sum_{i=1}^n -\log P(\mathbf{y}^{(i)} \mid \mathbf{x}^{(i)}) = \sum_{i=1}^n l(\mathbf{y}^{(i)}, \hat{\mathbf{y}}^{(i)}),
$$


最后得出损失函数

$$
l(\mathbf{y}, \hat{\mathbf{y}}) = - \sum_{j=1}^q y_j \log \hat{y}_j.
$$


这个损失函数通常被称为交叉熵损失,能够表示出不确定性程度,比较直观的反应分类损失,使用交叉熵还因为它有一个特性是其他损失函数不容易替代的,就是交叉熵更强烈的惩罚错误的输出。如果有非常错误的输出,它的值就会变化很大,反馈很强,并且导数更大。

损失函数的导数

寻找损失函数的导数是一个很重要的问题

$$
\begin{split}\begin{aligned} l(\mathbf{y}, \hat{\mathbf{y}}) &= - \sum_{j=1}^q y_j \log \frac{\exp(o_j)}{\sum_{k=1}^q \exp(o_k)} \\ &= \sum_{j=1}^q y_j \log \sum_{k=1}^q \exp(o_k) - \sum_{j=1}^q y_j o_j\\ &= \log \sum_{k=1}^q \exp(o_k) - \sum_{j=1}^q y_j o_j. \end{aligned}\end{split}
$$


$$
\partial_{o_j} l(\mathbf{y}, \hat{\mathbf{y}}) = \frac{\exp(o_j)}{\sum_{k=1}^q \exp(o_k)} - y_j = \mathrm{softmax}(\mathbf{o})_j - y_j.
$$


由此得出该导数,以便于后续计算

由于softmax常用于分类,对于图片的分类需要采用图像数据集,在此插入图像分类数据集的相关知识

图像分类数据集

首先引入数据集所需要的准备工作(代码用课上的)
%matplotlib inline
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2l

d2l.use_svg_display()
接下来读取数据集
# 通过ToTensor实例将图像数据从PIL类型变换成32位浮点数格式,
# 并除以255使得所有像素的数值均在0~1之间
trans = transforms.ToTensor()
mnist_train = torchvision.datasets.FashionMNIST(
    root="../data", train=True, transform=trans, download=True)
mnist_test = torchvision.datasets.FashionMNIST(
    root="../data", train=False, transform=trans, download=True)
Fashion-MNIST中包含的10个类别,分别为t-shirt(T恤)、trouser(裤子)、pullover(套衫)、dress(连衣裙)、coat(外套)、sandal(凉鞋)、shirt(衬衫)、sneaker(运动鞋)、bag(包)和ankle boot(短靴)。 以下函数用于在数字标签索引及其文本名称之间进行转换。
创建函数可视化样本
def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5):  #@save
    """绘制图像列表"""
    figsize = (num_cols * scale, num_rows * scale)
    _, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)
    axes = axes.flatten()
    for i, (ax, img) in enumerate(zip(axes, imgs)):
        if torch.is_tensor(img):
            # 图片张量
            ax.imshow(img.numpy())
        else:
            # PIL图片
            ax.imshow(img)
        ax.axes.get_xaxis().set_visible(False)
        ax.axes.get_yaxis().set_visible(False)
        if titles:
            ax.set_title(titles[i])
    return axes
为了使我们在读取训练集和测试集时更容易,我们使用内置的数据迭代器,而不是从零开始创建。 回顾一下,在每次迭代中,数据加载器每次都会读取一小批量数据,大小为batch_size。 通过内置数据迭代器,我们可以随机打乱了所有样本,从而无偏见地读取小批量。
batch_size = 256

def get_dataloader_workers():  #@save
    """使用4个进程来读取数据"""
    return 4

train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True,
                             num_workers=get_dataloader_workers())
现在我们定义load_data_fashion_mnist函数,用于获取和读取Fashion-MNIST数据集。 这个函数返回训练集和验证集的数据迭代器。 此外,这个函数还接受一个可选参数resize,用来将图像大小调整为另一种形状。
def load_data_fashion_mnist(batch_size, resize=None):  #@save
    """下载Fashion-MNIST数据集,然后将其加载到内存中"""
    trans = [transforms.ToTensor()]
    if resize:
        trans.insert(0, transforms.Resize(resize))
    trans = transforms.Compose(trans)
    mnist_train = torchvision.datasets.FashionMNIST(
        root="../data", train=True, transform=trans, download=True)
    mnist_test = torchvision.datasets.FashionMNIST(
        root="../data", train=False, transform=trans, download=True)
    return (data.DataLoader(mnist_train, batch_size, shuffle=True,
                            num_workers=get_dataloader_workers()),
            data.DataLoader(mnist_test, batch_size, shuffle=False,
                            num_workers=get_dataloader_workers()))
下面,我们通过指定resize参数来测试load_data_fashion_mnist函数的图像大小调整功能。
train_iter, test_iter = load_data_fashion_mnist(32, resize=64)
for X, y in train_iter:
    print(X.shape, X.dtype, y.shape, y.dtype)
    break

softmax从零实现

准备工作
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

W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)
b = torch.zeros(num_outputs, requires_grad=True)

实现softmax由三个步骤组成:

  1. 对每个项求幂(使用exp);
  2. 对每一行求和(小批量中每个样本是一行),得到每个样本的规范化常数;
  3. 将每一行除以其规范化常数,确保结果的和为1。
softmax函数
def softmax(X):
    X_exp = torch.exp(X)
    partition = X_exp.sum(1, keepdim=True)
    return X_exp / partition  # 这里应用了广播机制
模型定义
def net(X):
    return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)
损失函数(一行代码实现交叉熵好牛)
def cross_entropy(y_hat, y):
    return - torch.log(y_hat[range(len(y_hat)), y])

cross_entropy(y_hat, y)
分类精度
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)
    cmp = y_hat.type(y.dtype) == y
    return float(cmp.type(y.dtype).sum())
累加类
class Accumulator:  #@save
    """在n个变量上累加"""
    def __init__(self, n):
        self.data = [0.0] * n

    def add(self, *args):
        self.data = [a + float(b) for a, b in zip(self.data, args)]

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

    def __getitem__(self, idx):
        return self.data[idx]

实现

def train_epoch_ch3(net, train_iter, loss, updater):  #@save
    """训练模型一个迭代周期(定义见第3章)"""
    # 将模型设置为训练模式
    if isinstance(net, torch.nn.Module):
        net.train()
    # 训练损失总和、训练准确度总和、样本数
    metric = Accumulator(3)
    for X, y in train_iter:
        # 计算梯度并更新参数
        y_hat = net(X)
        l = loss(y_hat, y)
        if isinstance(updater, torch.optim.Optimizer):
            # 使用PyTorch内置的优化器和损失函数
            updater.zero_grad()
            l.mean().backward()
            updater.step()
        else:
            # 使用定制的优化器和损失函数
            l.sum().backward()
            updater(X.shape[0])
        metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())
    # 返回训练损失和训练精度
    return metric[0] / metric[2], metric[1] / metric[2]
训练函数
def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater):  #@save
    """训练模型(定义见第3章)"""
    animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],
                        legend=['train loss', 'train acc', 'test acc'])
    for epoch in range(num_epochs):
        train_metrics = train_epoch_ch3(net, train_iter, loss, updater)
        test_acc = evaluate_accuracy(net, test_iter)
        animator.add(epoch + 1, train_metrics + (test_acc,))
    train_loss, train_acc = train_metrics
    assert train_loss < 0.5, train_loss
    assert train_acc <= 1 and train_acc > 0.7, train_acc
    assert test_acc <= 1 and test_acc > 0.7, test_acc
小批量随机梯度下降
lr = 0.1

def updater(batch_size):
    return d2l.sgd([W, b], lr, batch_size)

简洁实现

import torch
from torch import nn
from d2l import torch as d2l

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
初始化
# PyTorch不会隐式地调整输入的形状。因此,
# 我们在线性层前定义了展平层(flatten),来调整网络输入的形状
net = nn.Sequential(nn.Flatten(), nn.Linear(784, 10))

def init_weights(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, std=0.01)

net.apply(init_weights);
损失函数
loss = nn.CrossEntropyLoss(reduction='none')
优化算法
trainer = torch.optim.SGD(net.parameters(), lr=0.1)

onehot 独热

就像手写数字识别中的 0 1 0 0 0 0 0 0 0 0一样,只有正确值赋值1而其他赋值0的方式就是onehot表示

标签:num,hat,回归,torch,train,softmax,data,sum
From: https://blog.51cto.com/u_16196891/6842418

相关文章

  • 回归测试
    回归测试求助编辑百科名片回归测试是指修改了旧代码后,重新进行测试以确认修改没有引入新的错误或导致其他代码产生错误。自动回归测试将大幅降低系统测试、维护升级等阶段的成本。回归测试作为软件生命周期的一个组成部分,在整个软件测试过程中占有很大的工作量比重,软件开发的各......
  • 中文核心周刊复现(北大核心)-基于逻辑回归的金融风投评分卡模型实现
    最近有些学员有论文需求,让我提供一下逻辑回归,金融风控,评分卡相关参考论文,以供参考。我找了一篇描述评分卡模型原理的论文,题目是《基于逻辑回归的金融风投评分卡模型实现》,第一作者边玉宁。这篇论文发布于中文核心周刊,北大核心。核心周刊相对于普通周刊难度较大,查重率在5-10%,录取率......
  • 加入自定义块对fashion_mnist数据集进行softmax分类
    在之前,我们实现了使用torch自带的层对fashion_mnist数据集进行分类。这次,我们加入一个自己实现的block,实现一个四层的多层感知机进行softmax分类,作为对“自定义块”的代码实现的一个练习。我们设计的多层感知机是这样的:输入维度为784,在展平层过后,第一层为全连接层,输入输出维度分......
  • 回归分析
    回归的思想回归的分类回归分析:研究x和y之间相关性的分析这里有三个关键词:1、相关性2、X3、Y1、相关性!=因果性数据的分类横截面数据时间序列数据面板数据一元线性回归残差平方和在机器学习中被称为损失函数对于线性回归中线性的理解......
  • Matlab中的偏最小二乘法(PLS)回归模型,离群点检测和变量选择|附代码数据
    全文下载:http://tecdat.cn/?p=22319最近我们被客户要求撰写关于偏最小二乘法(PLS)回归的研究报告,包括一些图形和统计输出。本文建立偏最小二乘法(PLS)回归(PLSR)模型,以及预测性能评估。为了建立一个可靠的模型,我们还实现了一些常用的离群点检测和变量选择方法,可以去除潜在的离群点和只......
  • Python数学建模系列(九):回归
    文章目录前言往期文章1多元回归1.1选取数据1.2构建训练集与测试集,并构建模型1.3模型预测1.4模型评估2logistic回归2.1鸢尾花数据集2.2绘制散点图2.3逻辑回归分析结语前言Hello!小伙伴!非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ 自我介绍ଘ(੭ˊᵕˋ)੭......
  • java实现softmax
    Java实现Softmax在机器学习中,Softmax是一种常用的归一化函数,它将一组任意实数的输入转换为范围在0和1之间的实数,并且这些实数的总和为1。Softmax函数通常用于多分类问题中,用于将输出映射到概率分布。本文将介绍如何使用Java实现Softmax函数,并提供代码示例。Softmax函数的定义So......
  • Matlab马尔可夫区制转换动态回归模型估计GDP增长率|附代码数据
    原文链接:http://tecdat.cn/?p=19918最近我们被客户要求撰写关于马尔可夫区制转换动态回归的研究报告,包括一些图形和统计输出。本文估计实际GDP增长率的两状态Markov区制转换动态回归模型  ( 点击文末“阅读原文”获取完整代码数据******** )。创建模型进行估计通过指定转移......
  • R语言泊松Poisson回归模型分析案例|附代码数据
    原文链接:http://tecdat.cn/?p=2605最近我们被客户要求撰写关于泊松Poisson回归的研究报告,包括一些图形和统计输出。这个问题涉及马蹄蟹研究的数据。研究中的每只雌性马蹄蟹都有一只雄性螃蟹贴在她的巢穴中。这项研究调查了影响雌蟹是否有其他男性居住在她附近的因素。被认为影......
  • 白话机器学习笔记(一)学习回归
    最小二乘法定义模型表达式:\(f_\theta(x)=\theta_0+\theta_1x\)(常用\(\theta\)表示未知数、\(f_\theta(x)\)表示含有参数\(\theta\)并且和变量\(x\)相关的函数)目标函数假设有\(n\)个训练数据,那么它们的误差之和可以这样表示,这个表达式称为目标函数。\(E(\theta)=\frac12\sum......