softmax

简单的分类问题

一个简单的图像分类问题,输入图像的高和宽均为2像素,色彩为灰度。图像中的4像素分别记为x1,x2,x3,x4x_1,x_2,x_3,x_4x1​,x2​,x3​,x4​。真实标签为狗、猫或者鸡,这些标签对应的离散值为y1,y2,y3y_1,y_2,y_3y1​,y2​,y3​。我们通常使用离散的数值来表示类别。例如y1=1,y2=2,y3=3y_1=1,y_2=2,y_3=3y1​=1,y2​=2,y3​=3.。

神经网络图

下图用神经网络图描绘了上面的计算。softmax回归同线性回归一样,也是一个单层神经网络。由于每个输出的o1,o2,o3o_1,o_2,o_3o1​,o2​,o3​计算都要依赖于所有的输入x1,x2,x3,x4x_1,x_2,x_3,x_4x1​,x2​,x3​,x4​,softmax回归的输出层也是一个全连接层。

权重矢量

o1=x1w11+x2w21+x3w31+x4w41+b1o_1=x_1w_{11} +x_2w_{21} + x_3w_{31}+x_4w_{41} + b_1o1​=x1​w11​+x2​w21​+x3​w31​+x4​w41​+b1​
o2=x1w12+x2w22+x3w32+x4w42+b2o_2=x_1w_{12} +x_2w_{22} + x_3w_{32}+x_4w_{42} + b_2o2​=x1​w12​+x2​w22​+x3​w32​+x4​w42​+b2​
o3=x1w13+x2w23+x3w33+x4w43+b3o_3=x_1w_{13} +x_2w_{23} + x_3w_{33}+x_4w_{43} + b_3o3​=x1​w13​+x2​w23​+x3​w33​+x4​w43​+b3​

既然分类问题需要得到离散的预测输出,一个简单的办法是将输出值oio_ioi​当作预测类别是iii的置信度,并将值最大的输出所对应的类作为预测输出,即输出argmaxoiargmaxo_iargmaxoi​ 。例如o1,o2,o3o_1,o_2,o_3o1​,o2​,o3​,如果分别为0.1,10,0.10.1,10,0.10.1,10,0.1,由于o2o_2o2​最大,那么预测类别为2,其代表猫。
softmax运算符(softmax operator)通过下式将输出值变换成值为正且和为1的概率分布
y1predict,y2predict,y3predict=softmax(o1,o2,o3,o4)y_1^{predict},y_2^{predict},y_3^{predict} = softmax(o_1,o_2,o_3,o4)y1predict​,y2predict​,y3predict​=softmax(o1​,o2​,o3​,o4)
其中
y1predicty_1^{predict}y1predict​=exp(o1)∑i=13exp(oi)=\frac{exp(o_1)}{\sum_{i=1}^{3} exp(o_i)}=∑i=13​exp(oi​)exp(o1​)​,
y2predicty_2^{predict}y2predict​=exp(o2)∑i=13exp(oi)=\frac{exp(o_2)}{\sum_{i=1}^{3} exp(o_i)}=∑i=13​exp(oi​)exp(o2​)​,
y3predicty_3^{predict}y3predict​=exp(o3)∑i=13exp(oi)=\frac{exp(o_3)}{\sum_{i=1}^{3} exp(o_i)}=∑i=13​exp(oi​)exp(o3​)​,
因此softmax运算不改变预测类别输出。

单样本矢量计算表达式

为了提高计算效率,我们可以将单样本分类通过矢量计算来表达。在上面的图像分类问题中,假设softmax回归的权重和偏差参数分别为

设高和宽分别为2个像素的图像样本的特征为

输出层的输出为

预测为狗、猫或鸡的概率分布为

softmax回归对样本iii分类的矢量计算表达式为

小批量矢量计算表达式

为了进一步提升计算效率,我们通常对小批量数据做矢量计算。广义上讲,给定一个小批量样本,其批量大小为nnn,输入个数(特征数)为ddd,输出个数(类别数)为qqq。softmax回归的矢量计算表达式为

交叉熵损失函数

模型训练和预测

在训练好softmax回归模型后,给定任一样本特征,就可以预测每个输出类别的概率。通常,我们把预测概率最大的类别作为输出类别。如果它与真实类别(标签)一致,说明这次预测是正确的。在3.6节的实验中,我们将使用准确率(accuracy)来评价模型的表现。它等于正确预测数量与总预测数量之比。

获取Fashion-MNIST训练集和读取数据

在介绍softmax回归的实现前我们先引入一个多类图像分类数据集。它将在后面的章节中被多次使用,以方便我们观察比较算法之间在模型精度和计算效率上的区别。图像分类数据集中最常用的是手写数字识别数据集MNIST[1]。但大部分模型在MNIST上的分类精度都超过了95%。为了更直观地观察算法之间的差异,我们将使用一个图像内容更加复杂的数据集Fashion-MNIST[2]。

我这里我们会使用torchvision包,它是服务于PyTorch深度学习框架的,主要用来构建计算机视觉模型。torchvision主要由以下几部分构成:
torchvision.datasets: 一些加载数据的函数及常用的数据集接口;
torchvision.models: 包含常用的模型结构(含预训练模型),例如AlexNet、VGG、ResNet等;
torchvision.transforms: 常用的图片变换,例如裁剪、旋转等;
torchvision.utils: 其他的一些有用的方法。

get dataset

mnist_train = torchvision.datasets.FashionMNIST(root='/home/FashionMNIST2065', train=True, download=True, transform=transforms.ToTensor())
mnist_test = torchvision.datasets.FashionMNIST(root='/home/FashionMNIST2065', train=False, download=True, transform=transforms.ToTensor())

root(string)– 数据集的根目录,其中存放processed/training.pt和processed/test.pt文件。
train(bool, 可选)– 如果设置为True,从training.pt创建数据集,否则从test.pt创建。
download(bool, 可选)– 如果设置为True,从互联网下载数据并放到root文件夹下。如果root目录下已经存在数据,不会再次下载。
transform(可被调用 , 可选)– 一种函数或变换,输入PIL图片,返回变换之后的数据。如:transforms.RandomCrop。
target_transform(可被调用 , 可选)– 一种函数或变换,输入目标,进行变换。

def get_fashion_mnist_labels(labels):text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat','sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']return [text_labels[int(i)] for i in labels]def show_fashion_mnist(images, labels):d2l.use_svg_display()# 这里的_表示我们忽略(不使用)的变量_, figs = plt.subplots(1, len(images), figsize=(12, 12))for f, img, lbl in zip(figs, images, labels):f.imshow(img.view((28, 28)).numpy())f.set_title(lbl)f.axes.get_xaxis().set_visible(False)f.axes.get_yaxis().set_visible(False)plt.show()X, y = [], []
for i in range(10):X.append(mnist_train[i][0]) # 将第i个feature加到X中y.append(mnist_train[i][1]) # 将第i个label加到y中
show_fashion_mnist(X, get_fashion_mnist_labels(y))

读取数据

batch_size = 256
num_workers = 4
train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=num_workers)
test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_worke)start = time.time()
for X, y in train_iter:continue
print('%.2f sec' % (time.time() - start))

softmax从零开始实现

import torch
import torchvision
import numpy as np
import sys
sys.path.append("/home/")
import d2lzh1981 as d2lprint(torch.__version__)
print(torchvision.__version__)#获取训练集数据和测试集数据
batch_size = 256
mnist_train = torchvision.datasets.FashionMNIST(root='/home/FashionMNIST2065', train=True, download=True, transform=transforms.ToTensor())
mnist_test = torchvision.datasets.FashionMNIST(root='/home/FashionMNIST2065', train=False, download=True, transform=transforms.ToTensor())
#模型参数初始化
num_inputs = 784
num_outputs = 10W = 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)
#定义softmax操作
def softmax(X):X_exp = X.exp()partition = X_exp.sum(dim=1, keepdim=True)# print("X size is ", X_exp.size())# print("partition size is ", partition, partition.size())return X_exp / partition  # 这里应用了广播机制def net(X):return softmax(torch.mm(X.view((-1, num_inputs)), W) + b)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))def cross_entropy(y_hat, y):return - torch.log(y_hat.gather(1, y.view(-1, 1)))def accuracy(y_hat, y):return (y_hat.argmax(dim=1) == y).float().mean().item()``def evaluate_accuracy(data_iter, net):acc_sum, n = 0.0, 0for X, y in data_iter:acc_sum += (net(X).argmax(dim=1) == y).float().sum().item()n += y.shape[0]return acc_sum / nnum_epochs, lr = 5, 0.1
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, 0for 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() 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)) train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, batch_size, [W, b], lr)
#模型预测
X, y = iter(test_iter).next()true_labels = d2l.get_fashion_mnist_labels(y.numpy())
pred_labels = d2l.get_fashion_mnist_labels(net(X).argmax(dim=1).numpy())
titles = [true + '\n' + pred for true, pred in zip(true_labels, pred_labels)]d2l.show_fashion_mnist(X[0:9], titles[0:9])

softmax的pytorch实现

# 加载各种包或者模块
import torch
from torch import nn
from torch.nn import initimport numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2lprint(torch.__version__)batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, root='/home/FashionMNIST2065')#定义网络模型
num_inputs = 784
num_outputs = 10class LinearNet(nn.Module):def __init__(self, num_inputs, num_outputs):super(LinearNet, self).__init__()self.linear = nn.Linear(num_inputs, num_outputs)def forward(self, x): # x 的形状: (batch, 1, 28, 28)y = self.linear(x.view(x.shape[0], -1))return y# net = LinearNet(num_inputs, num_outputs)class FlattenLayer(nn.Module):def __init__(self):super(FlattenLayer, self).__init__()def forward(self, x): # x 的形状: (batch, *, *, ...)return x.view(x.shape[0], -1)#from collections import OrderedDict
net = nn.Sequential(# FlattenLayer(),# LinearNet(num_inputs, num_outputs) OrderedDict([('flatten', FlattenLayer()),('linear', nn.Linear(num_inputs, num_outputs))]) # 或者写成我们自己定义的 LinearNet(num_inputs, num_outputs) 也可以)
#初始化模型参数
init.normal_(net.linear.weight, mean=0, std=0.01)
init.constant_(net.linear.bias, val=0)#定义损失函数
loss = nn.CrossEntropyLoss() # 下面是他的函数原型
# class torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')
#定义优化函数
optimizer = torch.optim.SGD(net.parameters(), lr=0.1) # 下面是函数原型
# class torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)
#训练
num_epochs = 5
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, None, None, optimizer)

多层感知机

深度学习主要关注多层模型。在这里,我们将以多层感知机(multilayer perceptron,MLP)为例,下图展示了一个多层感知机的神经网络图,它含有一个隐藏层,该层中有5个隐藏单元。。


H=XWh+bhH=XW_h + b_hH=XWh​+bh​,
O=HWo+boO=HWo + b_oO=HWo+bo​,
也就是将隐藏层的输出直接作为输出层的输入。如果将以上两个式子联立起来,可以得到
O=(XWh+bh)Wo+bo=XWhWo+bhWo+boO=(XW_h + b_h)W_o + b_o = XW_hW_o + b_hW_o + b_oO=(XWh​+bh​)Wo​+bo​=XWh​Wo​+bh​Wo​+bo​
从联立后的式子可以看出,虽然神经网络引入了隐藏层,却依然等价于一个单层神经网络,即便再添加更多的隐藏层,以上设计依然只能与仅含输出层的单层神经网络等价。

激活函数

上述问题的根源在于全连接层只是对数据做仿射变换(affine transformation),而多个仿射变换的叠加仍然是一个仿射变换。解决问题的一个方法是引入非线性变换,例如对隐藏变量使用按元素运算的非线性函数进行变换,然后再作为下一个全连接层的输入。这个非线性函数被称为激活函数(activation function)。

下面我们介绍几个常用的激活函数:
ReLU函数
ReLU(rectified linear unit)函数提供了一个很简单的非线性变换。给定元素,该函数定义为
RELU(x)=max(x,0)RELU(x)=max(x,0)RELU(x)=max(x,0)

%matplotlib inline
import torch
import numpy as np
import matplotlib.pyplot as plt
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l
print(torch.__version__)def xyplot(x_vals, y_vals, name):# d2l.set_figsize(figsize=(5, 2.5))plt.plot(x_vals.detach().numpy(), y_vals.detach().numpy())plt.xlabel('x')plt.ylabel(name + '(x)')



sigmoid函数
sigmoid函数可以将元素的值变换到0和1之间:
sigmoid(x)sigmoid(x)sigmoid(x)=11+exp(−x)=\frac{1}{1+exp(-x)}=1+exp(−x)1​


tanh函数
tanh(双曲正切)函数可以将元素的值变换到-1和1之间:
tanh(x)tanh(x)tanh(x)=1−exp(−2x)1+exp(−2x)=\frac{1-exp(-2x)}{1+exp(-2x)}=1+exp(−2x)1−exp(−2x)​


关于激活函数的选择
ReLu函数是一个通用的激活函数,目前在大多数情况下使用。但是,ReLU函数只能在隐藏层中使用。

用于分类器时,sigmoid函数及其组合通常效果更好。由于梯度消失问题,有时要避免使用sigmoid和tanh函数。

在神经网络层数较多的时候,最好使用ReLu函数,ReLu函数比较简单计算量少,而sigmoid和tanh函数计算量大很多。

在选择激活函数的时候可以先选用ReLu函数如果效果不理想可以尝试其他激活函数。

多层感知机
多层感知机就是含有至少一个隐藏层的由全连接层组成的神经网络,且每个隐藏层的输出通过激活函数进行变换。多层感知机的层数和各隐藏层中隐藏单元个数都是超参数。以单隐藏层为例并沿用本节之前定义的符号,多层感知机按以下方式计算输出:

其中表示激活函数。

多层感知机从零开始实现

import torch
import numpy as np
import sys
sys.path.append("/home/")
import d2lzh1981 as d2l
print(torch.__version__)#获取训练集
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,root='/home/FashionMNIST2065')#定义模型参数
num_inputs, num_outputs, num_hiddens = 784, 10, 256W1 = torch.tensor(np.random.normal(0, 0.01, (num_inputs, num_hiddens)), dtype=torch.float)
b1 = torch.zeros(num_hiddens, dtype=torch.float)
W2 = torch.tensor(np.random.normal(0, 0.01, (num_hiddens, num_outputs)), dtype=torch.float)
b2 = torch.zeros(num_outputs, dtype=torch.float)params = [W1, b1, W2, b2]
for param in params:param.requires_grad_(requires_grad=True)#定义激活函数
def relu(X):return torch.max(input=X, other=torch.tensor(0.0))
#定义网络
def net(X):X = X.view((-1, num_inputs))H = relu(torch.matmul(X, W1) + b1)return torch.matmul(H, W2) + b2
#定义损失函数
loss = torch.nn.CrossEntropyLoss()
#训练
num_epochs, lr = 5, 100.0
# 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))d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params, lr)

多层感知机pytorch实现

import torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2lprint(torch.__version__)
#初始化模型和各个参数
num_inputs, num_outputs, num_hiddens = 784, 10, 256net = nn.Sequential(d2l.FlattenLayer(),nn.Linear(num_inputs, num_hiddens),nn.ReLU(),nn.Linear(num_hiddens, num_outputs), )for params in net.parameters():init.normal_(params, mean=0, std=0.01)
#训练
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,root='/home/kesci/input/FashionMNIST2065')
loss = torch.nn.CrossEntropyLoss()optimizer = torch.optim.SGD(net.parameters(), lr=0.5)num_epochs = 5
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, None, None, optimizer)

深度学习softmax与多层感知机分类模型相关推荐

  1. 深度学习入门之多层感知机

    深度学习入门之多层感知机 参考书籍:深度学习入门--基于pyhthon的理论与实现 文章目录 深度学习入门之多层感知机 前言 一.单层感知机局限性 1.感知机?异或门 2.小结 二.多层感知机 1.问 ...

  2. 深度学习入门:多层感知机实现异或门

    文章目录 前言 感知机 2层感知机实现异或门 总结 参考文献: 前言 最近又开始看深度学习的内容了,好久不用忘得差不多了,先从最简单的感知机入手了,这里记录下用2层感知机实现异或门. 感知机 什么是感 ...

  3. 动手学习深度学习 04:多层感知机

    文章目录 01 多层感知机 1.感知机 总结 2.多层感知机 2.1.隐藏层 2.1.1 线性模型可能会出错 2.1.2 在网络中加入隐藏层 2.1.3 从线性到非线性 2.1.4 通用近似定理 3. ...

  4. 【tensorflow 深度学习】8.训练图片分类模型

    1.训练图片分类模型的三种方法 (1).从无到有,先确定好算法框架,准备好需要训练的数据集,从头开始训练,参数一开始也是初始化的随机值,一个批次一个批次地进行训练. (2).准备好已经训练好的模型,权 ...

  5. 花书+吴恩达深度学习(四)多分类 softmax

    目录 0. 前言 1. 二分类 sigmoid 2. 多分类 softmax 3. 多分类 softmax 梯度下降推导 如果这篇文章对你有一点小小的帮助,请给个关注,点个赞喔~我会非常开心的~ 花书 ...

  6. 深度学习 第3章线性分类 实验四 pytorch实现 Softmax回归 鸢尾花分类任务 下篇

    目录: 第3章 线性分类 3.3 实践:基于Softmax回归完成鸢尾花分类任务 3.3.1 数据处理 3.3.1.1 数据集介绍 3.3.1.2 数据清洗 1. 缺失值分析 2. 异常值处理 3.3 ...

  7. 上手!深度学习最常见的26个模型练习项目汇总

    作者:沧笙踏歌 转载自AI部落联盟(id:AI_Tribe) 今天更新关于常见深度学习模型适合练手的项目.这些项目大部分是我之前整理的,基本上都看过,大概俩特点:代码不长,一般50-200行代码,建议 ...

  8. 一文看懂深度学习发展史和常见26个模型

    参加 2019 Python开发者日,请扫码咨询 ↑↑↑ 来源 | AI部落联盟(ID:AI_Tribe) 作者简介:沧笙踏歌,硕士毕业于北京大学,目前计算机科学与技术博士在读,主要研究自然语言处理和 ...

  9. 深度学习利器:TensorFlow与NLP模型

    深度学习利器:TensorFlow与NLP模型 享到:微博微信FacebookTwitter有道云笔记邮件分享 稍后阅读 我的阅读清单 前言 自然语言处理(简称NLP),是研究计算机处理人类语言的一门 ...

最新文章

  1. JsonObject json字符串转换成JSonObject对象
  2. 10.图的深度优先遍历序列是否唯一?为什么?
  3. 批量正则替换某文件夹中代码(div id=XXXX替换为div id=XXXX)
  4. CodeIgniter 2.X 于 PHP5.6 兼容错误
  5. Java简单内存解析
  6. 【开发者成长】“机器学习还是很难用!”
  7. Java中Xml文件的解析
  8. 现代控制理论(4)——李雅普诺夫稳定性理论
  9. VS2015安装教程详细步骤及配置Opencv4.1.1(亲测)
  10. HTML链接和锚点学习---第四天
  11. 了解计算机的配置及价格行情,最新电脑配置清单及价格的详细介绍
  12. 抽空写了个小游戏(未完待续)
  13. yutons_sug搜索框提示插件||输入框提示插件
  14. 重邮计算机专业取得奖项,重邮邹宇航:保研北大,囊括国内外40余个重量级奖项的科创达人...
  15. 联想u盘启动linux,联想thinkpad e335台式机bios设置u盘启动的方法
  16. 缓冲区、通道、Files、NIO2
  17. 有一个很棒的想法,如何向老板证明你是对的
  18. [数据结构] UVa1471 Defense Lines 防线
  19. 2021年度总结 | 葡萄城软件开发技术回顾(下)
  20. MobaXterm 忘记主密码 密码重置

热门文章

  1. 1、orbslam2 安装与运行
  2. 虚拟世界进入探索区,元宇宙新星META WORLD为何值得关注?
  3. golang:线程安全的map----sync.Map
  4. iphone之间同步所有_在iPhone上请勿打扰和静音之间有什么区别?
  5. HashMap 遍历hashMap的7种方法和删除数据两种方式
  6. php冷饮料奶茶店在线点单系统 java小程序python
  7. 中国炸鸡粉市场现状研究分析与发展前景预测报告(2022)
  8. SpringBoot -- request输入流重复可读
  9. 第十三届蓝桥杯Web应用开发(大学组)
  10. 小米10s和小米11参数配置对比哪个好 哪个更值得入手