0%

Pytorch学习第一周

Pytorch学习第一周

1.张量简介与创建

1.1Tensor概念

  1. 张量是什么?

    张量是一个多维数组,他是向量标量矩阵的高维扩展。

  2. Tensor 与Variable之间的关系?

    Variable(0.4版本之前)是torch.autograd中的数据类型,主要用于封装Tensor,进行自动求导

  3. Tensor的属性:
    • data:张量的数值
    • dtype:张量的数据类型
    • shape:张量的形状
    • device:张量所在的设备,GPU/CPU
    • requires_grad:是不是需要求导
    • grad:张量的导数
    • grad_fn: 张量的计算公式
    • is_leaf:是不是叶子节点,在计算图的时候会用到

1.2 张量的创建

  1. 直接创建
  • torch.tensor()
    1
    2
    3
    arr = np.ones((3,3))
    t = torch.tensor(arr,device='cuda')
    print(t)
  • torch.from_numpy(ndarray)

注意: tensor和ndarray共享内存,一个改变另一个也会改变

1
2
3
4
5
6
arr = np.array([[1,2,3],[4,5,6]])
t = torch.from_numpy(arr)
print('修改tensor:')
t[0,0]=10
print('numpy:',arr)
print('tensor:',t)
  1. 依据数值创建
  • torch.zeros()
    功能:依据size创建全0张量

注意:out参数用来存放torch.zeros()生成的张量

1
2
3
4
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))
  • torch.zeros_like()
    功能:依据形状创建全零张量
  • torch.ones()
  • torch.ones_like()
  • torch.full()
  • torch.full_like()
  • torch.arrange()
    功能:创建等差数列的张量

注意:是半开区间

1
t = torch.arrange(2,10,2)
  • torch.linspace()
    功能:创建一个等差数列
    注意:是闭合的区间
    1
    t = torch.linspace(1,10,5)
  • torch.logspace()
    功能:依对数创建张量,base:是指底数
  • torch.eye()
    功能:创建对角矩阵,默认为方阵
  1. 依据概率分布创建张量
  • torch.normal()
    功能:生成正态分布(高斯分布),mean:均值;std:标注差
    四种模式:
    1
    2
    # mean为标量,std为标量
    t_normal = torch.normal(0,1,size(4,))
    1
    2
    3
    # mean为标量,std为张量
    std = torch.arrange(1,5,dtype=torch.float)
    t_normal = torch.normal(1,std)
    1
    2
    3
    # mean为张量,std为标量
    mean = torch.arrange(1,5,dtype=torch.float)
    t_normal = torch.normal(mean,1)
    1
    2
    3
    4
    # mean为张量,std为张量
    mean = torch.arrange(1,5,dtype=torch.float)
    std = torch.arrange(1,5,dtype=torch.float)
    t_normal = torch.normal(mean,std)
  • torch.randn()
    功能:创建均值为0,标准差为1的正态分布
  • torch.randn_like()
  • torch.rand()
    功能:创建均匀分布的张量
  • torch.rand_like()
    功能:在区间[0,1)上,生成均匀分布
  • torch.randint()
  • torch.randint_like()
    功能:区间[low,high)生成整数均与分布
  • torch.randperm()
    功能:生成从0到n-1的随机排列
  • torch.bernoulli()
    功能:以input为概率,生成伯努利分布(0-1分布,两点分布)

    2. 张量操作与线性回归

    2.1 张量的操作:拼接、切分、索引和变换

  1. 张量拼接与切分
  • torch.cat()
    功能:将张量按维度dim进行拼接

    torch.cat(tensors,dim=0,out=None)

    • tensors: 张量序列
    • dim:要拼接的维度
    1
    2
    3
    t = torch.ones((2,3))
    t_0 = torch.cat([t,t],dim=0)
    t_1 = torch.cat([t,t]dim=1)
  • torch.stack()
    功能:在新创建的维度dim上进行拼接

    tensor.stack(tensors,dim=0,out=None)

    • tensors:张量序列
    • dim:要拼接的维度
    1
    2
    t = torch.ones((2,3))
    t_stack = torch.stack([t,t],dim=2)
  • torch.chunk()
    功能:将张量按维度dim进行平均切分
    返回值:张量列表
    注意事项:若不能整除,最后一份张量小于其他张量

    torch.chunk(input,chunks,dim=0)

    • inputs:要切分的张量
    • chunks:要切分的份数
    • dim:要切分的维度
    1
    2
    a = torch.ones((2,5))
    list_of_tensors = torch.chunk(a,chunks=3,dim=1)
  • torch.split()
    功能:将张量按维度dim进行切分
    返回值:张量列表

    torch.split(tensor,split_size_or_sections,dim=0)

    • tensor:要切分的张量
    • split_size_or_sections:为int时,表示每一份的长度;为list时,按list元素切分
    • dim:要切分的维度
    1
    2
    3
    a = torch.ones((2,5))
    list_of_tensors_1 = torch.split(a,3,dim=1)
    list_of_tensors_2 = torch.split(a,[1,2,2],dim=1)
  1. 张量的索引
  • torch.index_select()
    功能:在维度dim上,按index索引数据
    返回值:依据index索引数据拼接的张量

    • input: 要索引的张量
    • dim:要索引的维度
    • index:要索引的序列号
    1
    2
    3
    t = torch.randint(0,9,size=(3,3))
    idx =torch.tensor([0,2],dtype=torch.long)
    t_select = torch.index_select(t,dim=0,index=idx)
  • torch.masked_select()
    功能:按mask中的True进行索引
    返回值:一维张量

    torch.masked_select(input,mask,out=None)

    • input:要索引的张量
    • mask:与input同形状的不二类型张量
    1
    2
    3
    t = torch.randint(0,9,size=(3,3))
    mask = t.ge(5) # ge是大于等于的意思
    t_select = torch.masked_select(t,mask)
  1. 张量变换
  • torch.reshape()
    功能:变换张量形状
    注意事项:当张量在内存中是连续时,新张量与input共享数据存储内存

    torch.reshape(input,shape)

    • input:要变换的张量
    • shape:新张量的形状
    1
    2
    t = torch.randperm(8)
    t_reshape = torch.reshape(t,(-1,4))
  • torch.transpose()
    功能:交换张量的两个维度

    torch.transpose(input,dim0,dim1)

    • input:要交换的张量
    • dim0:要交换的维度
    • dim1:要交换的维度
    1
    2
    t = torch.rand((2,3,4))
    t_transpose = torch.transpose(t,dim0=1,dim1=2)
  • torch.t()
    功能:2维张量转置,对矩阵而言,等价于torch.transpose(input,0,1)

  • torch.squeeze()
    功能:压缩常速为1的维度(轴)

    torch.squeeze(input,dim=None,out=None)

    • dim:若为None,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除
  • torch.unsqueeze()
    功能:依据dim扩展维度

    torch.unsequeeze(input,dim,out=None)
    dim:扩展的维度

2.2 张量的数学运算

  1. 加减乘除
    • torch.add(input,alpha=1,other,out=None)
      功能:逐原素计算input+alpha * other
    • torch.addcdiv()
    • torch.sub()
    • torch.div()
    • torch.mul()
  2. 对数,指数,幂函数
    • torch.log(input,out =None)
    • torch.log10(input,out=None)
    • torch.log2(input,out=None)
    • torch.exp(input,out=None)
    • torch,pow()
  3. 三角函数
    • torch.abs(input,out=None)
    • torch.acos(input,out=None)
    • torch.cosh(input,out=None)
    • torch.cos(input,out=None)
    • torch.asin(input,out=None)
    • torch.atan(input,out=None)
    • torch.atan2(input,other,out=None)

2.3 线性回归

线性回归是分析一个变量与另外一(多)个变量之间关系的方法

线性回归求解步骤:

  1. 确定模型:Model:y = wx+b
  2. 选择损失函数: MSE: L1Loss,交叉熵损失
  3. 求解梯度并更新w,b w = w - LR* w.grad;b = b-LR*b.grad
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import torch
import matplotlib.pyplot as plt

lr = 0.001 # 设置学习率
# 创建训练数据
x = torch.rand(20,1) * 10
y = 2*x + (5 + torch.randn(20,1))
# 构建线性回归参数
w = torch.randn((1),requires_grad=True)
b = torch.randn((1),requires_grad=True)

for iteration in range(1000):
#前向传播
wx = torch.mul(w,x)
y_pred = torch.add(wx,b)

#计算loss
loss=(0.5*(y-y_pred)**2).mean()

#反向传播
loss.backward()

#更新参数
b.data.sub_(lr * b.grad)
w.data.sub_(lr * w.grad)

# 绘图
if iteration % 20 == 0:
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(3)

if loss.data.numpy() < 1:
break

3.计算图与动态图机制

3.1 计算图

计算图是用来描述运算的有向无环图
计算图有两个主要元素:节点(Node)和边(Edge)
好处:计算简洁,求导方便
叶子节点:用户创建的节点称为叶子节点,是整个计算图的根基
retain_grad()保存非叶子节点的梯度

3.2 动态图机制

根据计算图搭建方式,可将计算图分为动态图和静态图。
动态图:运算与搭建同时进行。pytorch、自由行;灵活、易调节
静态图:先搭建图,后运算。tensorflow、跟团旅行;高效、不灵活

4.autograd与逻辑回归

4.1 autograd-自动求导系统

  • torch.autograd.backward
    功能:自动求取梯度

    torch.autograd.backward(tensors,grad_tensors=None,retain_grad_None,create_graph=False)

    • tensors: 用于求导的张量,如loss
    • retain_graph: 保存计算图
    • create_graph: 创建导数计算图,用于高阶计算
    • grad_tensors:多梯度权重
  • torch.autograd.grad()
    功能:求取梯度

    torch.autograd.grad(outputs,inputs,grad_outputs=None,retain_grad=None,create_graph=False)

    • outputs:用于求导的张量,如loss
    • inputs:需要梯度的张量
    • retain_graph: 保存计算图
    • create_graph: 创建导数计算图,用于高阶计算
    • grad_tensors:多梯度权重

1. 梯度不会自动清零,记得手动清零2. 所有依赖叶子节点的节点,requires_grad都为True3. 叶子节点不能执行in_place操作

4.2 逻辑回归

逻辑回归(对数几率回归)是线性的二分类模型。
线性回归是分析自变量X与因变量Y(标量)之间关系的方法;
逻辑回归是分析自变量X与因变量Y(概率)之间关系的方法。

机器学习模型训练的步骤:

迭代训练:{
- 数据:数据采集,清洗,预处理
- 模型:根据任务复杂程度,选择不同的模型
- 损失函数:根据任务而定
- 优化器:求导,梯度优化
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import torch
import torch.nn as nn
import matplotlib.pyplot as plt

sample_nums = 100
mean_value = 1.7
bias =1
# 1.生成数据
n_data = torch.ones(sample_nums,2)
x0 = torch.normal(mean_value * n_data,1) + bias
y0 = torch.zeros(sample_nums)
x1 = torch.normal(-mean_value * n_data,1) + bias
y1 = torch.ones(sample_nums)
train_x = torch.cat((x0,x1),0)
train_y = torch.cat((y0,y1),0)

# 2. 选择模型
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()

# 3.选择损失函数
loss_fn = nn.BCELoss()

# 4.选择优化器
lr = 0.01
optimizer = torch.optim.SGD(lr_net.parameters(),lr=lr,momentum=0.9)

# 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()

# 绘图
if iteration % 20:
mask = y_pred.ge(0.5).float().squeeze()
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} accuracy:{:.2%}".format(iteration,w0,w1,plot_b,acc))
plt.legend()
plt.show()
plt.pause(0.5)

if acc > 0.99:
break
-------------本文结束感谢您的阅读-------------