本篇主要记录一下一些基础的pytorch知识,一些基本的数学操作

常用API

1.矩阵内元素的加减乘除

a = torch.rand(3, 4)
b = torch.rand(4)
# 这里能加是因为会做broadcast
a+b
torch.add(a, b)
'''
a = torch.rand(3, 4)
b = torch.rand(4)
a+b
Out[3]: 
tensor([[0.8518, 1.1405, 1.1919, 1.2886],
        [1.4325, 1.1519, 0.6564, 1.8520],
        [0.9096, 1.0659, 1.0295, 0.9981]])
torch.add(a, b)
Out[4]: 
tensor([[0.8518, 1.1405, 1.1919, 1.2886],
        [1.4325, 1.1519, 0.6564, 1.8520],
        [0.9096, 1.0659, 1.0295, 0.9981]])
'''
# pytorch里的+ - * / 和对应的add,sub,mul,div意义完全相同
torch.all(torch.eq(a-b, torch.sub(a, b)))
# 需要注意的是,这里的操作都是在元素之间的操作,不是矩阵意义上的
torch.all(torch.eq(a*b, torch.mul(a, b)))
torch.all(torch.eq(a/b, torch.div(a, b)))
'''
torch.all(torch.eq(a-b, torch.sub(a, b)))
Out[5]: tensor(True)
torch.all(torch.eq(a*b, torch.mul(a, b)))
Out[6]: tensor(True)
torch.all(torch.eq(a/b, torch.div(a, b)))
Out[7]: tensor(True)
'''

2.矩阵的乘法

# 2.矩阵的乘法
a = torch.tensor([[3., 3.],
                  [3., 3.]])
b = torch.ones(2, 2)
a,b
# torch.mm 仅限于二维的矩阵
torch.mm(a, b)
# torch.matmul() 可以更高维
# 但实际上是还是仅对最后两维作矩阵的乘法,前面的维度保持不变
# 如果前面几个维度的shape不一致,如果可以broadcast则会自动扩展,否则报错
torch.matmul(a, b)
# torch.matmul() 等同于 a@b
a@b
'''
a = torch.tensor([[3., 3.],
                  [3., 3.]])
b = torch.ones(2, 2)
a,b
Out[10]: 
(tensor([[3., 3.],
         [3., 3.]]),
 tensor([[1., 1.],
         [1., 1.]]))
torch.mm(a, b)
Out[11]: 
tensor([[6., 6.],
        [6., 6.]])
        torch.matmul(a, b)
Out[12]: 
tensor([[6., 6.],
        [6., 6.]])
a@b
Out[13]: 
tensor([[6., 6.],
        [6., 6.]])

'''

# 一个实际的例子
# 比如在神经网络的线性层经常会有降维的过程
# 比如[4, 784] => [4, 512]
x = torch.rand(4, 784)
# 在pytorch里,通常这种工具人的中间矩阵的格式是
# (channel_out, channel_in)
# 不过不是也无伤大雅,只是约定俗成
w = torch.rand(512, 784)
# 将w转置后和x相乘,高维的转置用transpose
(x@w.t()).shape
'''
x = torch.rand(4, 784)
w = torch.rand(512, 784)
(x@w.t()).shape
Out[15]: torch.Size([4, 512])
'''

3.矩阵的次方

# 3.矩阵的次方
a = torch.full([2, 2], 3)
a.pow(2)
a**2
aa = a**2
# square root, 即平方根
aa.sqrt()
# 1/3 次方
aa.rsqrt()
aa**(0.5)
'''
a
Out[17]: 
tensor([[3, 3],
        [3, 3]])
a.pow(2)
Out[18]: 
tensor([[9, 9],
        [9, 9]])
a**2
Out[19]: 
tensor([[9, 9],
        [9, 9]])
aa = a**2
aa.sqrt()
Out[20]: 
tensor([[3., 3.],
        [3., 3.]])
aa.rsqrt()
Out[21]: 
tensor([[0.3333, 0.3333],
        [0.3333, 0.3333]])
aa**(0.5)
Out[22]: 
tensor([[3., 3.],
        [3., 3.]])

'''

4.对数

# 4.对数
a = torch.exp(torch.ones(2, 2))
# 默认以e为底,即ln,也可是log10等
torch.log(a)
'''
a
Out[24]: 
tensor([[2.7183, 2.7183],
        [2.7183, 2.7183]])
torch.log(a)
Out[25]: 
tensor([[1., 1.],
        [1., 1.]])

'''

5.近似值

# 5.近似值
a = torch.tensor(3.14)
# 最后两个分别是裁剪为整数部分和小数部分
a.floor(), a.ceil(), a.trunc(), a.frac()
# 四舍五入
a = torch.tensor(3.499)
a.round()
a = torch.tensor(3.5)
a.round()
'''
a = torch.tensor(3.14)
a.floor(), a.ceil(), a.trunc(), a.frac()
Out[27]: (tensor(3.), tensor(4.), tensor(3.), tensor(0.1400))
a = torch.tensor(3.499)
a.round()
Out[28]: tensor(3.)
a = torch.tensor(3.5)
a.round()
Out[29]: tensor(4.)
'''

6.裁剪clamp (min) (min, max)

# 6.裁剪clamp (min) (min, max)
# 梯度裁剪 gradient clipping
grad = torch.rand(2, 3)*15
grad.max()
# Out[30]: tensor(12.9671)
grad.median()
# Out[31]: tensor(7.0764)
# 小于10的都变为10
grad.clamp(10)
'''
grad.clamp(10)
Out[32]: 
tensor([[10.3087, 12.9671, 10.0000],
        [10.0000, 10.0000, 10.0000]])
grad
Out[33]: 
tensor([[10.3087, 12.9671,  7.0764],
        [ 1.1382,  3.5013,  8.7587]])

'''
# 小于7的变为7,大于10的变为10
grad.clamp(7, 10)
'''
grad.clamp(7, 10)
Out[35]: 
tensor([[10.0000, 10.0000,  7.0764],
        [ 7.0000,  7.0000,  8.7587]])
'''