[深度学习] pytorch学习笔记(2)(梯度、梯度下降、凸函数、鞍点、激活函数、Loss函数、交叉熵、Mnist分类实现、GPU)
一、梯度
- 导数是对某个自变量求导,得到一个标量。
- 偏微分是在多元函数中对某一个自变量求偏导(将其他自变量看成常数)。
- 梯度指对所有自变量分别求偏导,然后组合成一个向量,所以梯度是向量,有方向和大小。
上左图中,箭头的长度表示陡峭度,越陡峭的地方箭头越长,箭头指向的方向是y变大的方向,如果要使用梯度下降,则需要取负方向。
右图中,蓝色代表低点,红色代表高点,中间的箭头方向从蓝色指向红色,而且中间最陡峭的地方,箭头最长。
二、梯度下降
上图中分别使用梯度下降优化θ1和θ2的值,α表示学习率,即每次按梯度下降方向更新参数的一个乘数因子,可以控制参数调整的速度。
三、凸函数convex function、非凸函数non-convex function
上图为凸函数,即任意两个点 ( f(z1) + f(z2) ) / 2 > f( (z1 + z2) / 2 ) 。
上图为非凸函数,其中包含若干个局部最低和局部最高,还有一个全局最高和全局最低点。
四*、ResNet为什么效果好(直观)
ResNet利用残差块,相当于将Loss函数变得相对平滑,这样更利于深度网络找到最优解global minima(或相对比较好的局部最优解Local minima)。
五、鞍点saddle point
六、激活函数和梯度
sigmoid激活函数:
$$f(x)=\sigma(x)=\frac{1}{1+e^{-x}}$$
求导:
$$\begin{aligned} \frac{d}{d x} \sigma(x) &=\frac{d}{d x}\left(\frac{1}{1+e^{-x}}\right) \\ &=\frac{e^{-x}}{\left(1+e^{-x}\right)^{2}} \\ &=\frac{\left(1+e^{-x}\right)-1}{\left(1+e^{-x}\right)^{2}} \\ &=\frac{1+e^{-x}}{\left(1+e^{-x}\right)^{2}}-\left(\frac{1}{1+e^{-x}}\right)^{2} \\ &=\sigma(x)-\sigma(x)^{2} \\ \sigma^{\prime} &=\sigma(1-\sigma) \end{aligned}$$
tanh激活函数:
$$\begin{aligned} f(x) &=\tanh (x)=\frac{\left(e^{x}-e^{-x}\right)}{\left(e^{x}+e^{-x}\right)} \\ &=2 \operatorname{sigmoid}(2 x)-1 \end{aligned}$$
求导:
$$\begin{array}{l}{\frac{d}{d x} \tanh (x)=\frac{\left(e^{x}+e^{-x}\right)\left(e^{x}+e^{-x}\right)-\left(e^{x}-e^{-x}\right)\left(e^{x}-e^{-x}\right)}{\left(e^{x}+e^{-x}\right)^{2}}} \\ {=1-\frac{\left(e^{x}-e^{-x}\right)^{2}}{\left(e^{x}+e^{-x}\right)^{2}}=1-\tanh ^{2}(x)}\end{array}$$
import torch z = torch.linspace(-1, 1, 10)
a = torch.tanh(z)
print(a)
# tensor([-0.7616, -0.6514, -0.5047, -0.3215, -0.1107, 0.1107, 0.3215, 0.5047,
# 0.6514, 0.7616])
Relu激活函数(Rectified Linear Unit,整流线性单元)
$$f(x)=\left\{\begin{array}{ll}{0} & {\text { for } x<0} \\ {x} & {\text { for } x \geq 0}\end{array}\right.$$
求导:
$$f^{\prime}(x)=\left\{\begin{array}{ll}{0} & {\text { for } x<0} \\ {1} & {\text { for } x \geq 0}\end{array}\right.$$
import torch z = torch.linspace(-1,1,10)
a = torch.relu(z)
print(a)
# tensor([0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.1111, 0.3333, 0.5556, 0.7778,
# 1.0000])
七、Loss函数及梯度
均方差误差(MSE:Mean squared Error):
$$\text { loss }=\sum\left[y-f_{\theta}(x)\right]^{2}$$
求导:
$$\frac{\nabla \text{loss}}{\nabla \theta}=2 \sum\left[y-f_{\theta}(x)\right] * \frac{\nabla f_{\theta}(x)}{\nabla \theta}$$
# -*- coding:utf-8 -*-
__author__ = 'Leo.Z' import torch
import torch.nn.functional as F x = torch.ones(1)
w = torch.tensor([2.], requires_grad=True)
# w = torch.full([1], 2.)
# 如果在定义w的时候没有说明需要计算梯度,则使用下面语句指定
# w.requires_grad_() mse = F.mse_loss(torch.ones(1), x * w) # 梯度计算方法1,假设里面又N个w需要求导,则参数列表[w1,w2,w3,...,wn,b],返回的是[dw1,dw2,dw3,...,dwn,db]
# dw = torch.autograd.grad(mse, [w])
# print(dw) # 梯度计算方法2,计算出w的梯度会直接赋给w1.grad,w2.grad,...,wn.grad,b.grad
mse.backward()
print(w.grad)
Softmax误差:
# -*- coding:utf-8 -*-
__author__ = 'Leo.Z' import torch
import torch.nn.functional as F # L层计算结果z
z = torch.tensor([3., 2., 1.], requires_grad=True)
print(z)
# z经过softmax激活函数
y_hat = F.softmax(z, dim=0)
print(y_hat)
# 假设标签是y
y = torch.tensor([1., 0., 0.])
# 损失值loss为交叉熵函数结果
loss = -torch.sum(y * torch.log(y_hat))
print(loss) # 方法一
loss.backward()
print(z.grad)
# 方法二
# dz = torch.autograd.grad(loss, [z], retain_graph=True)
# print(dz) # tensor([-0.3348, 0.2447, 0.0900])
import torch
import torch.nn.functional as F z = torch.linspace(-100, 100, 10) # 新版api
a = torch.softmax(z, dim=0)
# 或 a = F.softmax(z,dim=0)
print(a)
# 输出tensor([0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 0.0000e+00, 2.4891e-39,
# 1.1144e-29, 4.9890e-20, 2.2336e-10, 1.0000e+00])
八、初步使用梯度下降优化参数
# -*- coding:utf-8 -*-
__author__ = 'Leo.Z' import torch # 该函数有4个局部最优解,但值是一样的,都是0
def func(x, y):
return (x ** 2 + y - 11) ** 2 + (x + y ** 2 - 7) ** 2 # 当初始化改变时,通过梯度下降找到的局部最优解也时不同的
# 初始化x=4,y=4时,局部最优x=3.0,y=2.0
# 初始化x=0,y=4时,局部最优x=-2.8051,y=3.1313
x = torch.tensor(0., requires_grad=True)
y = torch.tensor(4., requires_grad=True)
# 这里使用的优化方法是Adam
optimizer = torch.optim.Adam([x, y], lr=1e-3)
for step in range(20000):
optimizer.zero_grad() pred = func(x, y)
pred.backward()
optimizer.step()
if step % 2000 == 0:
print("step:", x, y)
上述代码中,我们优化的是函数z = func(),优化对象x和y。
如果用到深度学习中,我们优化的目标函数为loss函数,优化对象为w和b(如果使用BN等,则还要优化γβ等)。
九、使用cross_entropy实现多分类
# -*- coding:utf-8 -*-
__author__ = 'Leo.Z' import torch
import torch.nn.functional as F x = torch.randn(5, 784)
w = torch.randn(10, 784, requires_grad=True) # L层计算结果z
z = x @ w.t()
z.requires_grad_()
print(z.size()) # 注意,这里没有使用one-hot编码
y = torch.tensor([1, 4, 6, 2, 4]) # Adam优化器
optimizer = torch.optim.Adam([w], lr=1e-3) for step in range(100000):
# 每次更新w,重新计算z
z = x @ w.t()
optimizer.zero_grad()
# 使用cross_entropy,z为输入[B,C],B为batch_size,C为classes。y输入标签,但不是one-hot
loss = F.cross_entropy(z, y)
# 反向传播
loss.backward(retain_graph=True)
# 优化一次
optimizer.step()
if step % 2000 == 0:
print("step:", loss)
# 看看结果是否和标签一致
print(torch.softmax(z, dim=1))
可以用一下cross_entropy的分解步骤代替:
# -*- coding:utf-8 -*-
__author__ = 'Leo.Z' import torch
import torch.nn.functional as F x = torch.randn(5, 784)
w = torch.randn(10, 784, requires_grad=True) # L层计算结果z
z = x @ w.t()
z.requires_grad_()
print(z.size()) # 注意,这里没有使用one-hot编码
y = torch.tensor([1, 4, 6, 2, 4]) # Adam优化器
optimizer = torch.optim.Adam([w], lr=1e-3) for step in range(100000):
# 每次更新w,重新计算z
z = x @ w.t()
optimizer.zero_grad()
# 先计算softmax的log,即-ylog(y_hat)中的log(y_hat)
pred = torch.log_softmax(z, dim=1)
# 然后再计算整个-ylog(y_hat),并在各class上求和,然后batch平均
loss = F.nll_loss(pred, y)
loss.backward(retain_graph=True)
# 优化一次
optimizer.step()
if step % 2000 == 0:
print("step:", loss)
# 看看结果是否和标签一致
print(torch.softmax(z, dim=1))
十、Mnist数据分类
low-level api版
# -*- coding:utf-8 -*-
__author__ = 'Leo.Z' import torch
import torch.nn.functional as F
from torchvision import datasets, transforms
from torch.utils.data import DataLoader import time batch_size = 200
learning_rate = 0.001
epochs = 10 train_loader = DataLoader(
datasets.MNIST('../data', train=True, download=True,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=batch_size, shuffle=True)
test_loader = DataLoader(
datasets.MNIST('../data', train=False,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=batch_size, shuffle=True) w1, b1 = torch.randn(200, 784, requires_grad=True), torch.zeros(200, requires_grad=True)
w2, b2 = torch.randn(200, 200, requires_grad=True), torch.zeros(200, requires_grad=True)
w3, b3 = torch.randn(10, 200, requires_grad=True), torch.zeros(10, requires_grad=True) # 使用何凯明的参数初始化方法,初始化很重要
torch.nn.init.kaiming_normal_(w1)
torch.nn.init.kaiming_normal_(w2)
torch.nn.init.kaiming_normal_(w3) # 网络结构
def forward(x):
x = x @ w1.t() + b1
x = F.relu(x)
x = x @ w2.t() + b2
x = F.relu(x)
x = x @ w3.t() + b3
# 因为后面会用softmax激活函数,这里的relu可有可无,但一定不要是sigmoid和tanh
x = F.relu(x)
return x # 选择一个优化器,指定需要优化的参数,以及学习率
optimizer = torch.optim.SGD([w1, b1, w2, b2, w3, b3], lr=learning_rate) s_time = 0
for epoch in range(epochs): for batch_idx, (data, target) in enumerate(train_loader):
# data转换维度为[200,784],target的维度为[200]
data = data.view(-1, 28 * 28)
# 跑一次网络,得到z,维度为[200,10],200是batch_size,10是类别
z = forward(data)
# 使用cross_entropy计算损失值,参数为z和label(target)
loss = F.cross_entropy(z, target)
# 每次迭代前将梯度置0
optimizer.zero_grad()
# 反向传播,计算梯度
loss.backward()
# 相当于执行w = w - dw,也就是更新权值
optimizer.step()
if batch_idx % 100 == 0:
e_time = time.time()
if s_time != 0:
print("time:", e_time - s_time)
s_time = time.time()
print(loss)
high-level api版:
# -*- coding:utf-8 -*-
__author__ = 'Leo.Z' import torch
import torch.nn.functional as F
from torch.nn import Module, Sequential, Linear, LeakyReLU
from torchvision import datasets, transforms
from torch.utils.data import DataLoader import time batch_size = 200
learning_rate = 0.001
epochs = 10 train_loader = DataLoader(
datasets.MNIST('../data', train=True, download=True,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=batch_size, shuffle=True)
test_loader = DataLoader(
datasets.MNIST('../data', train=False,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=batch_size, shuffle=True) # 网络结构
class MLP(Module):
def __init__(self):
super(MLP, self).__init__() self.model = Sequential(
Linear(784, 200),
LeakyReLU(inplace=True),
Linear(200, 200),
LeakyReLU(inplace=True),
Linear(200, 10),
LeakyReLU(inplace=True)
) def forward(self, x):
x = self.model(x)
return x # 定义GPU设备
device = torch.device('cuda:0')
# model放到GPU
net = MLP().to(device) # 选择一个优化器,指定需要优化的参数,以及学习率
optimizer = torch.optim.SGD(net.parameters(), lr=learning_rate) for epoch in range(epochs): for batch_idx, (data, target) in enumerate(train_loader):
# data转换维度为[200,784],target的维度为[200]
data = data.view(-1, 28 * 28)
# 将data和target放到GPU
data, target = data.to(device), target.to(device)
# data为输入,net()直接执行forward
# 跑一次网络,得到z,维度为[200,10],200是batch_size,10是类别
# 由于net在GPU,data也在GPU,计算出的z就在GPU
# 调用net(data)的时候相当于调用Module类的__call__方法
z = net(data)
# 将loss放到GPU
loss = F.cross_entropy(z, target).to(device)
# 每次迭代前将梯度置0
optimizer.zero_grad()
# 反向传播,计算梯度
loss.backward()
# 相当于执行w = w - dw,也就是更新权值
optimizer.step()
if batch_idx % 100 == 0:
print(loss) # -*- coding:utf-8 -*-
十一、使用GPU
在上述代码中:
# 搬移一个model到GPU,net是对应更新的,也就是相当于剪切到GPU
net = MLP()
net2 = net.to(device)
print(net is net2) # 输出True # 搬移一个数据到GPU,相当于复制一份到GPU,两者是完全不同的
data2, target2 = data.to(device), target.to(device)
print(data is data2) # 输出False
[深度学习] pytorch学习笔记(2)(梯度、梯度下降、凸函数、鞍点、激活函数、Loss函数、交叉熵、Mnist分类实现、GPU)的更多相关文章
- [深度学习] Pytorch学习(一)—— torch tensor
[深度学习] Pytorch学习(一)-- torch tensor 学习笔记 . 记录 分享 . 学习的代码环境:python3.6 torch1.3 vscode+jupyter扩展 #%% im ...
- [深度学习] pytorch学习笔记(3)(visdom可视化、正则化、动量、学习率衰减、BN)
一.visdom可视化工具 安装:pip install visdom 启动:命令行直接运行visdom 打开WEB:在浏览器使用http://localhost:8097打开visdom界面 二.使 ...
- 【深度学习】softmax回归——原理、one-hot编码、结构和运算、交叉熵损失
1. softmax回归是分类问题 回归(Regression)是用于预测某个值为"多少"的问题,如房屋的价格.患者住院的天数等. 分类(Classification)不是问&qu ...
- [深度学习] pytorch学习笔记(4)(Module类、实现Flatten类、Module类作用、数据增强)
一.继承nn.Module类并自定义层 我们要利用pytorch提供的很多便利的方法,则需要将很多自定义操作封装成nn.Module类. 首先,简单实现一个Mylinear类: from torch ...
- [深度学习] pytorch学习笔记(1)(数据类型、基础使用、自动求导、矩阵操作、维度变换、广播、拼接拆分、基本运算、范数、argmax、矩阵比较、where、gather)
一.Pytorch安装 安装cuda和cudnn,例如cuda10,cudnn7.5 官网下载torch:https://pytorch.org/ 选择下载相应版本的torch 和torchvisio ...
- [深度学习] Pytorch学习(二)—— torch.nn 实践:训练分类器(含多GPU训练CPU加载预测的使用方法)
Learn From: Pytroch 官方Tutorials Pytorch 官方文档 环境:python3.6 CUDA10 pytorch1.3 vscode+jupyter扩展 #%% #%% ...
- loss函数学习笔记
一直对机器学习里的loss函数不太懂,这里做点笔记. 符号表示的含义,主要根据Andrew Ng的课程来的,\(m\)个样本,第\(i\)个样本为\(\vec x^{(i)}\),对应ground t ...
- 强化学习读书笔记 - 13 - 策略梯度方法(Policy Gradient Methods)
强化学习读书笔记 - 13 - 策略梯度方法(Policy Gradient Methods) 学习笔记: Reinforcement Learning: An Introduction, Richa ...
- 【PyTorch深度学习】学习笔记之PyTorch与深度学习
第1章 PyTorch与深度学习 深度学习的应用 接近人类水平的图像分类 接近人类水平的语音识别 机器翻译 自动驾驶汽车 Siri.Google语音和Alexa在最近几年更加准确 日本农民的黄瓜智能分 ...
随机推荐
- nginx配置反向代理支持session
Nginx反向代理tomcat,很是方便,但是也有些细节的问题需要注意:今天遇到了这样一个问题,tomcat中路径“host/web1”,nginx中直接“host/”代理,这时候session就无法 ...
- CDH的mysql主从准备
参考: https://www.cnblogs.com/yinzhengjie/p/10371899.html https://www.sysit.cn/blog/post/sysit/CDH6.2. ...
- Oracle块,区,段
数据块(Block) 数据块Block是Oracle存储数据信息的最小单位.注意,这里说的是Oracle环境下的最小单位.Oracle也就是通过数据块来屏蔽不同操作系统存储结构的差异.无论是Windo ...
- Chrome的cookie放在哪里了,Cookie/Session机制详解
Chrome的cookie放在哪里了,Cookie/Session机制详解:https://blog.csdn.net/u010002184/article/details/82082951
- 记java的那些编辑器的故事之凌嘉文+李晓彤-结对编程
[写在前面]这次是复用个人项目进行结对编程,其实主要复用的就是凌老板的出题部分和我的文件读写部分,其余部分都是新学的.在这次编程中也涨了很多知识,其中最最最让人哭笑不得的就是:两个人用了不一样的编辑器 ...
- Test:河北金力集团企业网集成
三.网站建设部分(40分) 河北金力集团公文流转系统 1.项目需求: 河北金力集团是我省机械加工的龙头企业,主要从事矿山机械制造及各种机械零部件加工.企业有3个厂区,主厂区位于省高新技术开发区,3个分 ...
- Sigma (化简)牛客多校第一场 -- Integration
思路: 可以裂项化简,类似找规律,可以两项.三项代进去试试看. #define IOS ios_base::sync_with_stdio(0); cin.tie(0); #include <c ...
- 02:linux常用命令
1.1 linux查看系统基本参数常用命令 1.查看磁盘 [root@linux-node1 ~]# df -hl Filesystem Size Used Avail Use% Mounted on ...
- 我爬的entityFramework的坑
老师使用的是mysql的数据库,但是我只有sqlserver的数据库,于是就照猫画虎,想连自己的sqlserver,结果一连跳了几个坑: 坑一:appsetting中的字符串连接是后面还有个s, 坑二 ...
- QuickSort(快排)的JAVA实现
QuickSort的JAVA实现 这是一篇算法课程的复习笔记 用JAVA对快排又实现了一遍. 先实现的是那个easy版的,每次选的排序轴都是数组的最后一个: package com.algorithm ...