import torch
import numpy as np
初始化tensor
x=torch.rand(2,3)#rand -> 0-1均匀分布
x
tensor([[0.5223, 0.3861, 0.7927],
[0.0650, 0.2139, 0.5554]])
x=torch.rand(2,3,5,5)#两张图片,5*5,3个通道
x
tensor([[[[0.6514, 0.1037, 0.1890, 0.0705, 0.8500],
[0.0319, 0.7271, 0.7786, 0.9618, 0.4899],
[0.6720, 0.8095, 0.1165, 0.7330, 0.5179],
[0.6960, 0.8482, 0.7309, 0.8960, 0.5812],
[0.8186, 0.7967, 0.2190, 0.1376, 0.1547]],
[[0.1245, 0.0823, 0.4256, 0.6045, 0.3304],
[0.6117, 0.0188, 0.6216, 0.6096, 0.4485],
[0.7939, 0.0734, 0.3977, 0.6878, 0.4676],
[0.4374, 0.2487, 0.0258, 0.3575, 0.5550],
[0.4530, 0.7221, 0.0029, 0.5470, 0.3541]],
[[0.6341, 0.7226, 0.3016, 0.9484, 0.3385],
[0.2459, 0.3854, 0.3859, 0.1597, 0.2375],
[0.3053, 0.7966, 0.4069, 0.9130, 0.0453],
[0.3399, 0.6047, 0.5077, 0.5011, 0.6015],
[0.9481, 0.0935, 0.4068, 0.1542, 0.4614]]],
[[[0.6516, 0.9816, 0.9714, 0.6130, 0.5707],
[0.1513, 0.0896, 0.2221, 0.9066, 0.4582],
[0.5247, 0.5624, 0.9863, 0.4370, 0.2480],
[0.3368, 0.9663, 0.5783, 0.6623, 0.3842],
[0.9675, 0.0693, 0.8682, 0.1897, 0.3513]],
[[0.6280, 0.2984, 0.1723, 0.0217, 0.4816],
[0.6612, 0.4903, 0.8872, 0.6947, 0.8507],
[0.1511, 0.1027, 0.0563, 0.5026, 0.5621],
[0.2255, 0.3545, 0.3066, 0.5255, 0.6804],
[0.0921, 0.0520, 0.6802, 0.6108, 0.2427]],
[[0.1591, 0.4687, 0.5743, 0.0848, 0.1058],
[0.5135, 0.8735, 0.9415, 0.4116, 0.9736],
[0.4152, 0.9971, 0.2942, 0.2482, 0.0682],
[0.8459, 0.9607, 0.9089, 0.1150, 0.9878],
[0.4260, 0.7828, 0.8908, 0.5648, 0.8430]]]])
x=torch.randn(2,3)#正态分布
x
tensor([[-2.6275, -1.4752, 0.5001],
[-0.8584, 1.0908, 1.0742]])
x=torch.zeros(2,3)#全0矩阵,注意0是浮点类型
x
tensor([[0., 0., 0.],
[0., 0., 0.]])
x=torch.ones_like(x)#全1矩阵,注意1是浮点类型
x
tensor([[1., 1., 1.],
[1., 1., 1.]])
x.shape,x.size()
(torch.Size([2, 3]), torch.Size([2, 3]))
x.shape[0],x.size(0)#注意取出的方式不同
(2, 2)
创建tensor
x=torch.tensor([1,2,3])#注意这里的数字不是float类型
x
tensor([1, 2, 3])
type(x),x.dtype,x.type() #注意只有后两个才会显示tensor里面数字的类型
(torch.Tensor, torch.int64, 'torch.LongTensor')
x=torch.tensor([1,2,3],dtype=torch.int32)#规定数字类型
x
tensor([1, 2, 3], dtype=torch.int32)
#补充:大写Tensor会自动把数据类型设置为float32
x=torch.Tensor([1,2,3])
x.dtype
torch.float32
int16是shorttensor ;int32是intTensor;int64 是longtensor
float16–halftensor ; float32–float tensor ; float64-- double tensor
#转换数据类型,一定要赋值
x=x.type(torch.float32)
x
tensor([1., 2., 3.])
#转换成bool类型
x.bool()
tensor([[ True, False, False],
[False, True, False],
[False, False, True]])
#转换成short
x.short() #其余同理
tensor([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]], dtype=torch.int16)
从nparray -> tensor
a=np.random.randn(2,3)
a
array([[-0.27908411, -0.07223004, -0.0791617 ],
[ 0.51832475, -0.87109149, 0.08526975]])
type(a),a.dtype #注意没有a.type
(numpy.ndarray, dtype('float64'))
#np->tensor
x=torch.from_numpy(a)
x,a.dtype
(tensor([[ 0.4640, 0.3242, -0.5177],
[ 0.7884, 1.7696, 2.4990]]), dtype('float32'))
#在定义array时,还可以指定类型
a=np.random.randn(2,3).astype(np.float32)
a
array([[ 2.3492863 , 1.0640051 , 0.59622204],
[ 0.9716296 , -1.0521595 , -0.46624354]], dtype=float32)
#tensor->numpy
x=x.numpy()
x,x.dtype
(array([[ 0.46400413, 0.3242247 , -0.51766133],
[ 0.78837115, 1.7696291 , 2.4990394 ]], dtype=float32),
dtype('float32'))
设置设备
device = "cuda" if torch.cuda.is_available() else "cpu"
device
'cuda'
继续有关tensor的初始化
x=torch.tensor([[1,2,3]
,[4,5,6]],dtype=torch.float32,device=device,requires_grad=True)#requires_grad指可以求导
x
tensor([[1., 2., 3.],
[4., 5., 6.]], device='cuda:0', requires_grad=True)
x.dtype,x.type() #后者多了个cuda
(torch.float32, 'torch.cuda.FloatTensor')
x.device
device(type='cuda', index=0)
x.shape,x.size
(torch.Size([2, 3]), <function Tensor.size>)
#创建没有初始化的tensor
x=torch.empty(2,3)
x
tensor([[0., 0., 0.],
[0., 0., 0.]])
#创建正态分布初始化tensor
x=torch.empty(2,3).normal_(mean=0,std=1)
x
tensor([[-0.3193, -0.1803, 0.2486],
[ 0.4035, 0.7996, 0.4892]])
#创建序列
x=torch.arange(0,6,1)#(开始,结束,步长)
x
tensor([0, 1, 2, 3, 4, 5])
#同上
x=torch.linspace(0.1,1,10)#(开始,结束,步长)
x
tensor([0.1000, 0.2000, 0.3000, 0.4000, 0.5000, 0.6000, 0.7000, 0.8000, 0.9000,
1.0000])
#生成单位矩阵
x=torch.eye(5)
x
tensor([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]])
#生成对角阵
x=torch.diag(torch.tensor([1,2,3,4,5]))#括号里必须是tensor,不能是个列表
x
tensor([[1, 0, 0, 0, 0],
[0, 2, 0, 0, 0],
[0, 0, 3, 0, 0],
[0, 0, 0, 4, 0],
[0, 0, 0, 0, 5]])
#单位矩阵也是特殊的对角阵
x=torch.diag(torch.ones(3))#torch.ones(3)->[1,1,1]
x
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1oHpQchM-1614585694563)(attachment:image.png)]
求矩阵
A=torch.tensor([[0,-1,1],
[2,-3,0],
[0,0,0]],dtype=torch.float32)#一定要是float类型,int在进行矩阵运算时是不给算的
A
tensor([[ 0., -1., 1.],
[ 2., -3., 0.],
[ 0., 0., 0.]])
#求矩阵的99次方
A.matrix_power(99)
tensor([[ 6.3383e+29, -6.3383e+29, -3.1691e+29],
[ 1.2677e+30, -1.2677e+30, -6.3383e+29],
[ 0.0000e+00, 0.0000e+00, 0.0000e+00]])
张量相加
x=torch.tensor([1,2,3],dtype=torch.float32)
y=torch.tensor([11,22,33],dtype=torch.float32)
z1=torch.empty(3)
torch.add(x,y,out=z1)
z1
tensor([12., 24., 36.])
#也可以z1=x+y,但要注意类型要相同
z1=x+y
z1
tensor([12., 24., 36.])
张量除法
z=x/y
z
tensor([0.0909, 0.0909, 0.0909])
就地操作 (但是尽量少用,因为会在反向传播求导的时候出错,因为x+=y并没有改变x的存储地址,但是x=x+y改变了x的存储地址,而反向传播中经常要用到后者)
x=torch.ones(1)
y=torch.zeros(1)
x,y
(tensor([1.]), tensor([0.]))
x.add_(y) #相当于x+=y,即自带赋值操作
tensor([1.])
矩阵运算
x1=torch.rand(2,5)
x2=torch.rand(5,3)
x3=torch.mm(x1,x2)#mm是矩阵乘法 也就是2*3
x3
tensor([[0.9351, 1.6415, 0.8841],
[0.7019, 1.0061, 0.7000]])
张量乘法
x=torch.tensor([1,2,3])
y=torch.tensor([4,5,6])
#对应元素相乘
z=x*y
z
tensor([ 4, 10, 18])
#对应相乘再相加
z=torch.dot(x,y)
z
tensor(32)
#广播
x=torch.arange(1,7).reshape(2,3)
y=torch.arange(4,7)#y会被广播成2*3
z=x*y
z
tensor([[ 4, 10, 18],
[16, 25, 36]])
#含批次信息的矩阵相乘
batch_size=32
m=10
n=20
s=30
x1=torch.rand(batch_size,m,n)
x2=torch.rand(batch_size,n,s)
z=torch.bmm(x1,x2)#矩阵相乘时忽略batch_size
z.shape
torch.Size([32, 10, 30])
更高级的操作
x=torch.arange(1,7).reshape(2,3)
x
tensor([[1, 2, 3],
[4, 5, 6]])
torch.sum(x)
tensor(21)
torch.sum(x,dim=0)#竖着看
tensor([5, 7, 9])
torch.sum(x,dim=1)#横着看
tensor([ 6, 15])
#最大值&下标
torch.max(x,dim=0),torch.max(x,dim=1)
#竖着找 , 横着找
(torch.return_types.max(
values=tensor([4, 5, 6]),
indices=tensor([1, 1, 1])), torch.return_types.max(
values=tensor([3, 6]),
indices=tensor([2, 2])))
torch.argmax(x,dim=1)#最大下标
tensor([2, 2])
#求平均
x=torch.arange(1,7).reshape(2,3)
# x.mean() #会报错,因为x是int64,需要转化成float32
x=x.type(torch.float32) #一定要类型转化
torch.mean(x,dim=0)
tensor([2.5000, 3.5000, 4.5000])
#求绝对值
x=torch.randn(2,3)
# x.abs()# 对所有数据都求平均
x[0]=torch.abs(x[0])#仅仅对第一行求绝对值
x
tensor([[ 0.6137, 0.8074, 1.3660],
[ 0.3782, -0.8580, -0.0971]])
#排序 默认descending=False 也就是升序
val,index=torch.sort(x,dim=1)#竖着排,0代表横着排
val,index
(tensor([[ 0.6137, 0.8074, 1.3660],
[-0.8580, -0.0971, 0.3782]]), tensor([[0, 1, 2],
[1, 2, 0]]))
#限制tensor的大小
x=torch.arange(1,7).reshape(2,3)
x[1]=torch.randn(3)
z=torch.clamp(x,min=0,max=2) #大于2的变成2,小于0的变成0
z
tensor([[1, 2, 2],
[0, 0, 0]])
布尔运算
x=torch.tensor([1,0,1,1,1],dtype=torch.bool)
x
tensor([ True, False, True, True, True])
#any:有一个True就是True
torch.any(x)
tensor(True)
#all 所有都是true才行
torch.all(x)
tensor(False)
切片相关
batch_size = 10
features = 25
x=torch.rand((batch_size,features))
x.shape
torch.Size([10, 25])
x[0].shape,x[0,:].shape
(torch.Size([25]), torch.Size([25]))
取行列
x=torch.rand(3,5)
x
tensor([[0.1167, 0.9782, 0.8142, 0.0425, 0.7190],
[0.6441, 0.8283, 0.8873, 0.1442, 0.7565],
[0.8691, 0.4542, 0.1293, 0.8457, 0.6096]])
rows=torch.tensor([1,0])
cols=torch.tensor([4,0])
#取1行4列和0行0列
x[rows,cols],x[[1,0],[4,0]]#后面那个可以看成 矩阵x的[1,4]和[0,0]
(tensor([0.7565, 0.1167]), tensor([0.7565, 0.1167]))
取指定下标
x=torch.arange(10)
x
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
#取值满足条件的值
x[(x<2)|(x>8)]# 必须加小括号
tensor([0, 1, 9])
#对x取余
x.remainder(2)
tensor([0, 1, 0, 1, 0, 1, 0, 1, 0, 1])
#求偶数
x[x.remainder(2)==0]
tensor([0, 2, 4, 6, 8])
torch.where(x>5,x,x**2) #大于5的值->不变,小于5的值->平方
tensor([ 0, 1, 4, 9, 16, 25, 6, 7, 8, 9])
torch.where(x>5,torch.ones(1),torch.zeros(1))#大于5的值->变成1,小于5的值->归零
tensor([0., 0., 0., 0., 0., 0., 1., 1., 1., 1.])
#上面的where函数和np的where一样
a=np.arange(10)
np.where(a>5,1,0)
array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1])
去重
x=torch.tensor([0,0,1,1,2,2,3,4]).unique()#去掉重复元素
x
tensor([0, 1, 2, 3, 4])
维度
x=torch.rand(64,3,28,28)
x.ndimension()
4
x.dim()
4
统计
x=torch.arange(10).reshape(2,5)
x.numel()#统计元素个数
10
改变形状
x=torch.rand(2,3)
x
tensor([[0.2729, 0.8561, 0.7390],
[0.4517, 0.2049, 0.7372]])
#变成3*2
x.view(3,2)
tensor([[0.2729, 0.8561],
[0.7390, 0.4517],
[0.2049, 0.7372]])
#或者reshape
x.reshape(3,2)
tensor([[0.2729, 0.8561],
[0.7390, 0.4517],
[0.2049, 0.7372]])
#或者转置
x.T
tensor([[0.2729, 0.4517],
[0.8561, 0.2049],
[0.7390, 0.7372]])
总结:reshape比view强大,因为如果tensor不连续的话,view就无法使用,但reshape可以
拼接
x1=torch.randint(1,10,(2,5))
x2=torch.randint(100,110,(2,5))
x1,x2
(tensor([[3, 6, 5, 9, 6],
[9, 9, 1, 9, 9]]), tensor([[104, 106, 109, 105, 102],
[108, 108, 106, 101, 108]]))
torch.cat((x1,x2),dim=0)
tensor([[ 3, 6, 5, 9, 6],
[ 9, 9, 1, 9, 9],
[104, 106, 109, 105, 102],
[108, 108, 106, 101, 108]])
torch.cat((x1,x2),dim=1)
tensor([[ 3, 6, 5, 9, 6, 104, 106, 109, 105, 102],
[ 9, 9, 1, 9, 9, 108, 108, 106, 101, 108]])
分块
x=torch.randint(1,10,(5,6))
x
tensor([[4, 4, 3, 4, 2, 1],
[3, 9, 1, 7, 1, 3],
[1, 3, 5, 4, 7, 3],
[9, 4, 2, 5, 2, 2],
[7, 7, 6, 8, 5, 2]])
torch.chunk(x,chunks=2,dim=0)#上面三个列表是一块,下面两个是另一块
(tensor([[4, 4, 3, 4, 2, 1],
[3, 9, 1, 7, 1, 3],
[1, 3, 5, 4, 7, 3]]), tensor([[9, 4, 2, 5, 2, 2],
[7, 7, 6, 8, 5, 2]]))
维度变换
x=torch.rand(64,224,224,3) #b h w c -> b c h w 通道放前面
x.permute(0,3,1,2)
x.shape
torch.Size([64, 224, 224, 3])
添加维度: 因为输入的图片可能是(3,,28,28),但现在要在最前面加上batch_size的维度,所以要用膨胀,也就是unsqueeze函数
x=torch.rand(3,224,224)
x.shape
torch.Size([3, 224, 224])
x=x.unsqueeze(0)# 在第一个维度上添加一个维度
x.shape
torch.Size([1, 3, 224, 224])
行向量变列向量
x=torch.arange(10)
x,x.shape
(tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), torch.Size([10]))
#在第二个维度上加一维度
x=x.unsqueeze(1)
x,x.shape
(tensor([[0],
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]]), torch.Size([10, 1]))
#再变为行向量
x=x.squeeze(1)#去掉第二个维度
x,x.shape
(tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), torch.Size([10]))
对变量的梯度跟踪
x=torch.ones(2,2,requires_grad=True)
x,x.dtype
(tensor([[1., 1.],
[1., 1.]], requires_grad=True), torch.float32)
#取消梯度
x.detach().requires_grad
False
y=x+2
y
tensor([[3., 3.],
[3., 3.]], grad_fn=<AddBackward0>)
z=y**2+1
z
tensor([[10., 10.],
[10., 10.]], grad_fn=<AddBackward0>)
out=z.mean()
out
tensor(10., grad_fn=<MeanBackward0>)
out.backward()
x.grad
tensor([[1.5000, 1.5000],
[1.5000, 1.5000]])
应用 : 设f(x)=e^x*ln(x+1),求 f’(2)
x=torch.tensor([2.],requires_grad=True)
y=torch.exp(x)*torch.log(x+1)
y.backward()
x.grad
tensor([10.5807])