课程一览表:
目录
一、.pytorch简介
二、环境配置
1.pycharm
2.annaconda
3.安装pytorch
三、张量简介与创建
1.张量的概念
2.Tensor——直接创建
3.Tensor——依据数值创建
4.Tensor——依据概率创建
四、张量操作与线性回归
1.张量操作(拼接、切分、索引和变换)
2.张量索引
3.张量变换
4.张量数学运算
5.线性回归
五、计算图与动态度机制
1.计算图
2.pytorch动态图机制
六、autograd与逻辑回归
1.autograd——自动求导系统
2.逻辑回归
pytorch优点
官网下载链接:Download PyCharm: Python IDE for Professional Developers by JetBrains
可以参考这篇博客:PyCharm2021安装教程_学习H的博客-CSDN博客_pycharm2021安装教程
annaconda的下载与安装:annaconda安装_Billie使劲学的博客-CSDN博客
annaconda环境管理:annaconda虚拟环境管理常用指令_Billie使劲学的博客-CSDN博客
pytorch的安装(以cuda11.0为例):cuda11.0+pytorch
(1)张量是什么?
(2)Tensor与Variable
Variable是torch.autograd中的数据类型,主要用于封装Tensor,进行求导。
Variable的五个属性:
data:被包装的Tensor
grad:data的梯度
grad_fn:创建Tensor的Function,是自动求导的关键
requires_grad:指示是否需要梯度
is_leaf:指示是否是叶子结点(张量)
(3)Tensor
PyTorch0.4.0版开始,Variable并入Tensor
张量的主要属性有八个:
其中五个属性在Variable中已经说到。
dtype:张量的数据类型,如,torch.FloatTensor,torch.cuda.FloatTensor
shape:张量的形状,如(1,3,512,512)->(batch_size,channel,height,width)
device:张量所在设备,GPU/CPU,是加速的关键
张量常用的数据类型:
(1)torch.tensor()
功能:从data创建tensor
data:数据,可以使list,numpy
dtype:数据类型,默认与data的一致
device:所在设备,cuda/cpu。device=‘cuda’
requires_grad:是否需要梯度
pin_memory:是否存于锁页内存,通常设为false
(2)torch.form_numpy(ndarray)
功能:从numpy创建tensor
注意事项:从torch.from_numpy创建的tensor与原ndarray共享内存,当修改其中一个的数据,另一个也将会被改动。
(1)torch.zeros()
功能:依size创建全0张量
size:张量的形状,如(3,3)、(3,224,224)
out:输出的张量(将输出的张量赋给out,该属性与输出张量的地址是一致的)
layout:内存中布局形式,有strided(默认),sparse_coo(稀疏张量时设置)等
device:所在设备,gpu/cpu
requires_grad:是否需要梯度
out_t = torch.tensor([1])
t = torch.zeros((3, 3), out=out_t)
print(t, '\n', out_t)
print(id(t), id(out_t), id(t) == id(out_t))
(2)torch.zeros_like()
功能:依input形状创建全0张量
input:创建与input同形状的全0张量
dtype:数据类型
layout:内存中布局形式
(3)torch.ones()
功能:创建全1张量
size:张量的形状,如(3,3)、(3,224,224)
(4)torch.ones_like()
功能:依input形状创建全1张量
dtype:数据类型
layout:内存中布局形式
device:所在设备,gpu/cpu
requires_grad:是否需要梯度
(5)torch.full()
功能:依input形状创建全 i 张量
size:张量的形状,如(3,3)
fill_value:张量的值 i
(6)torch.full_like()
(7)torch.arrange()
功能:创建等差的一维张量
注意事项:数值区间为[start,end)
start:数列起始值
end:数列“结束值”
step:数列公差,默认为1
(8)torch.linspace()
功能:创建均分的1维张量
注意事项:数值区间为[start,end)
start:数列起始值
end:数列结束值
steps:数列长度
[步长计算:(end-start)/steps - 1]
(9)torch.logspace()
功能:创建对数均分的1维张量
注意事项:长度为steps,底为base
start:数列起始值
end:数列结束值
steps:数列长度
base:对数函数的底,默认为10
(10)torch.eye()
功能:创建单位对角矩阵(2维张量)
注意事项:默认为方阵
n:矩阵行数(一般只设置行数,列数默认)
m:矩阵列数
(1)torch.normal()
功能:生成正态分布(高斯分布)
mean:均值
std:标准差
四种模式:
mean为标量,std为标量
mean为标量,std为张量
mean为张量,std为标量
mean为张量,std为张量
注意事项:当mean和std均为标量时, 应设定size来规定张量的长度
(2)torch.randn()
功能:生成标准正态分布
size:张量的形状
(3)torch.randn_like()
(4)torch.rand()
功能:在区间[0,1)上,生成均匀分布
(5)torch.rand_like()
(6)torch.randint()
功能:区间[low,high)生成证书均匀分布
size:张量的形状
(7)torch.randint_like()
(8)torch.randperm()
功能:生成从0到n-1的随机排列
n:张量的长度
(9)torch.bernoulli()
功能:以input为概率,生成伯努利分布(0-1分布,两点分布)
input:概率值
(1)torch.cat()
功能:将张量按维度dim进行拼接
tensors:张量序列
dim:要拼接的维度
(2)torch.stack()
功能:在新创建的维度dim上进行拼接
tensors:张量序列
dim:要拼接的维度
(3)torch.chunk()
功能:将张量按维度dim进行平均切分
返回值:张量列表
注意事项:若不能整除,最后一份张量小于其他张量
input:要切分的张量
chunks:要切分的份数
dim:要切分的维度(在哪个维度进行切分)
(4)torch.split()
功能:将张量按维度dim进行切分
返回值:张量列表
tensor:要切分的张量
split_size_or_sections:为int时,表示每一份的长度;为list时,按list元素切分(和为当前维度的长度,否则报错)
dim:要切分的维度
(1)torch.index_select()
功能:在维度dim上,按index索引数据
返回值:依index索引数据拼接的张量
input:要索引的张量
dim:要索引的维度
index:要索引数据的序号
注意事项:index的数据类型是long类型
[将索引的张量按在dim进行拼接]
t = torch.randint(0, 9, size=(3, 3))
idx = torch.tensor([0, 2], dtype=torch.long) # float
t_select = torch.index_select(t, dim=0, index=idx)
print("t:\n{}\nt_select:\n{}".format(t, t_select))
(2)torch.masked_select()
功能:按mask中的True进行索引,一般用来筛选数据
返回值:一维张量(因为不能确定张量中True的个数)
input:要索引的张量
mask:与input同形状的布尔类型张量
t = torch.randint(0, 9, size=(3, 3))
mask = t.le(5) # ge is mean greater than or equal/ gt: greater than le lt
t_select = torch.masked_select(t, mask)
print("t:\n{}\nmask:\n{}\nt_select:\n{} ".format(t, mask, t_select))
(1)torch.reshape()
功能: 变换张量形状
注意事项:当张量在内存中是连续时,新张量与input共享数据内存
input:要变换的张量
shape:新张量的形状
[新张量的大小与原张量要匹配,若维度为-1,则表示该维度不需要关心,它会根据其他维度的大小进行计算]
(2)torch.transpose()
功能:交换张量的两个维度
input:要变换的张量
dim0:要交换的维度
dim1:要交换的维度
(3)torch.t()
功能:2维张量转置,对矩阵而言,等价于torch.transpose(input,0,1)
(4)torch.squeeze()
功能:压缩长度为1的维度(轴)
dim:若为None,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除;
(5)torch.unsqueeze()
功能:依据dim扩展维度
dim:扩展的维度
(1)加减乘除
torch.add()
功能:逐元素计算input+alpha*other
input:第一个张量
alpha:乘项因子
other:第二个张量
(2)对数、指数、幂函数
(3)三角函数
线性回归是分析一个变量与另外一(多)个变量之间关系的方法
因变量:y 自变量:x 关系:线性
y=wx+b
分析:求解w,b
求解步骤:
(1)确定模型 model:y=wx+b
(3)求解梯度并更新w,b
w=w-LR*w.grad
b=b-LR*w.grad
import torch
import matplotlib.pyplot as plt
torch.manual_seed(10)
lr = 0.05 # 学习率
# 创建训练数据
x = torch.rand(20, 1) * 10 # x data (tensor), shape=(20, 1)
y = 2*x + (5 + torch.randn(20, 1)) # y data (tensor), shape=(20, 1)
# 构建线性回归参数
w = torch.randn((1), requires_grad=True)
b = torch.zeros((1), requires_grad=True)
for iteration in range(1000):
# 前向传播
wx = torch.mul(w, x)
y_pred = torch.add(wx, b)
# 计算 MSE loss
loss = (0.5 * (y - y_pred) ** 2).mean()
# 反向传播
loss.backward()
# 更新参数
b.data.sub_(lr * b.grad)
w.data.sub_(lr * w.grad)
# 清零张量的梯度
w.grad.zero_()
b.grad.zero_()
# 绘图
if iteration % 20 == 0:
plt.cla() # 防止社区版可视化时模型重叠
plt.scatter(x.data.numpy(), y.data.numpy())
plt.plot(x.data.numpy(), y_pred.data.numpy(), 'r-', lw=5)
plt.text(2, 20, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color': 'red'})
plt.xlim(1.5, 10)
plt.ylim(8, 28)
plt.title("Iteration: {}\nw: {} b: {}".format(iteration, w.data.numpy(), b.data.numpy()))
plt.pause(0.5)
if loss.data.numpy() < 1:
break
plt.show()
优点:运算简洁,梯度求导方便
计算图是用来描述运算的有向无环图
计算图有两个元素:结点(Node)和边(Edge)
结点表示数据,如向量,矩阵,张量
边表示运算,如加减乘除卷积等
例如:
用计算图表示:y=(x+w)*(w+1)
a=x+w b=w+1 y=a*b
叶子结点:用户创建的结点称为叶子结点,如X与W
is_leaf:指示张量是否为叶子结点
W和X就是叶子结点
叶子结点的作用:节省内存,梯度反向传播结束之后,非叶子结点的梯度会被释放掉。
若使用非叶子结点的梯度:a.retain_grad(),则会保留a的梯度
grad_fn:记录创建该张量时所用的方法(函数)(梯度反向传播的时候用到)
y是用乘法得到的,a和b是用加法得到的
import torch
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x) # retain_grad()
b = torch.add(w, 1)
y = torch.mul(a, b)
y.backward()
print(w.grad)
# 查看叶子结点
# print("is_leaf:\n", w.is_leaf, x.is_leaf, a.is_leaf, b.is_leaf, y.is_leaf)
# 查看梯度
# print("gradient:\n", w.grad, x.grad, a.grad, b.grad, y.grad)
# 查看 grad_fn
print("grad_fn:\n", w.grad_fn, x.grad_fn, a.grad_fn, b.grad_fn, y.grad_fn)
根据计算图搭建方式,可将计算图分为动态图和静态图
pytorch采用动态图机制,TensorFlow采用静态图机制
(1)torch.autograd.backward
功能:自动求取梯度
tensors:用于求导的张量,如loss
retain_graph:保存计算图
create_graph:创建导数计算图,用于高阶求导
grad_tensors:多梯度权重
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x)
b = torch.add(w, 1)
y = torch.mul(a, b)
#backward中自动调torch.autograd.backward
y.backward(retain_graph=True)
# print(w.grad)
#若要运行两次backward,需要设置retain_graph=True
y.backward()
tensors的作用是对y0和y1设置不同的权重
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x) # retain_grad()
b = torch.add(w, 1)
y0 = torch.mul(a, b) # y0 = (x+w) * (w+1)
y1 = torch.add(a, b) # y1 = (x+w) + (w+1) dy1/dw = 2
loss = torch.cat([y0, y1], dim=0) # [y0, y1]
grad_tensors = torch.tensor([1., 2.])
loss.backward(gradient=grad_tensors) # gradient 传入 torch.autograd.backward()中的grad_tensors
print(w.grad)
(2)torch.autograd.grad
功能:求取梯度
outputs:用于求导的张量,如loss
inputs:需要梯度的张量
create_graph:创建导数计算图,用于高阶求导
retain_graph:保存计算图
grad_outputs:多梯度权重
x = torch.tensor([3.], requires_grad=True)
y = torch.pow(x, 2) # y = x**2
#一阶求导
grad_1 = torch.autograd.grad(y, x, create_graph=True) # grad_1 = dy/dx = 2x = 2 * 3 = 6
print(grad_1)
#二阶求导
grad_2 = torch.autograd.grad(grad_1[0], x) # grad_2 = d(dy/dx)/dx = d(2x)/dx = 2
print(grad_2)
注意事项:
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
for i in range(4):
a = torch.add(w, x)
b = torch.add(w, 1)
y = torch.mul(a, b)
y.backward()
print(w.grad)
#梯度手动清零
w.grad.zero_()
#依赖于叶子结点的结点,requires_grad默认为True
print(a.requires_grad, b.requires_grad, y.requires_grad)
什么是原位操作?
a = torch.ones((1, ))
print(id(a), a)
#新建地址
# a = a + torch.ones((1, ))
# print(id(a), a)
#原位操作,在原地址上进行改变
a += torch.ones((1, ))
print(id(a), a)
逻辑回归是线性的二分类模型
模型表达式:
sigmoid函数可以吧y映射到0-1区间,故输出的y可用于做二分类
逻辑回归与线性回归的区别:
线性回归是分析自变量x与因变量y(标量)之间关系的方法
逻辑回归是分析自变量x与因变量y(概率)之间关系的方法
逻辑回归又称为对数几率回归,表示样本x为正样本的可能性
线性回归是wx+b拟合y
对数回归是wx+b拟合对数几率
逻辑回归:
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np
torch.manual_seed(10)
# ============================ step 1/5 生成数据 ============================
sample_nums = 100
mean_value = 1.7
bias = 1
n_data = torch.ones(sample_nums, 2)
x0 = torch.normal(mean_value * n_data, 1) + bias # 类别0 数据 shape=(100, 2)
y0 = torch.zeros(sample_nums) # 类别0 标签 shape=(100)
x1 = torch.normal(-mean_value * n_data, 1) + bias # 类别1 数据 shape=(100, 2)
y1 = torch.ones(sample_nums) # 类别1 标签 shape=(100)
train_x = torch.cat((x0, x1), 0)
train_y = torch.cat((y0, y1), 0)
# ============================ step 2/5 选择模型 ============================
class LR(nn.Module):
def __init__(self):
super(LR, self).__init__()
self.features = nn.Linear(2, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
x = self.features(x)
x = self.sigmoid(x)
return x
lr_net = LR() # 实例化逻辑回归模型
# ============================ step 3/5 选择损失函数 ============================
loss_fn = nn.BCELoss()
# ============================ step 4/5 选择优化器 ============================
lr = 0.01 # 学习率
optimizer = torch.optim.SGD(lr_net.parameters(), lr=lr, momentum=0.9)
# ============================ step 5/5 模型训练 ============================
for iteration in range(1000):
# 前向传播
y_pred = lr_net(train_x)
# 计算 loss
loss = loss_fn(y_pred.squeeze(), train_y)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 清空梯度
optimizer.zero_grad()
# 绘图
if iteration % 20 == 0:
mask = y_pred.ge(0.5).float().squeeze() # 以0.5为阈值进行分类
correct = (mask == train_y).sum() # 计算正确预测的样本个数
acc = correct.item() / train_y.size(0) # 计算分类准确率
plt.scatter(x0.data.numpy()[:, 0], x0.data.numpy()[:, 1], c='r', label='class 0')
plt.scatter(x1.data.numpy()[:, 0], x1.data.numpy()[:, 1], c='b', label='class 1')
w0, w1 = lr_net.features.weight[0]
w0, w1 = float(w0.item()), float(w1.item())
plot_b = float(lr_net.features.bias[0].item())
plot_x = np.arange(-6, 6, 0.1)
plot_y = (-w0 * plot_x - plot_b) / w1
plt.xlim(-5, 7)
plt.ylim(-7, 7)
plt.plot(plot_x, plot_y)
plt.text(-5, 5, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color': 'red'})
plt.title("Iteration: {}\nw0:{:.2f} w1:{:.2f} b: {:.2f} accuracy:{:.2%}".format(iteration, w0, w1, plot_b, acc))
plt.legend()
plt.show()
plt.pause(0.5)
if acc > 0.99:
break
=========================================================================
转载请注明出处
代码、数据联系作者QQ:1727177407