常用Tensor用法小结
- 生成 tensor
tensor(*size)
tensor(data)
arange(s,e,step) #s-e 步长为step
linspace(s,e,steps) #s-e 均匀steps份
rand/randn(size) #均匀/标准分布
normal(mean,std)/uniform(from,to)#正态/均匀分布
randperm(m) #随机排列 生成0- m-1 的随即排列
2. 常用操作
tensor.shape=tensor.size()
tensor.view(size) #自动调节tensor的形状 当某一维为-1的时候,会自动计算它的大小 公用内存
resize_(size) #它可以修改tensor的大小。如果新大小超过了原大小,会自动分配新的内存空间,而如果新大小小于原大小,则之前的数据依旧会被保存
squeeze unsqueeze 需要添加或减少某一维度
索引操作
a[0,2]= a[0][2]
a[:2]表示前两行 :表示遍历
a[:,0] 第0列
a[0:1, :2]和a[0, :2]最终生成的结果是不同的
None表示增加一个轴
常用选择函数
gather(input,dim,index) 根据index选取input上的数据
scatter是把取出的数据在放回去
tensor.item() #可以将tensor(只能有一个元素)转化为python float 类型
tensor的高级索引
import torch as t
t.randperm(6)
tensor([5, 3, 4, 2, 0, 1])
a=t.tensor([1,2])
b=t.Tensor(1,2)
a.shape,b.shape ##大小写区分还是不同的
(torch.Size([2]), torch.Size([1, 2]))
a = t.randn(3, 4)
a
print(a[0:1, :2]) # 第0行,前两列
print(a[0, :2]) # 注意两者的区别:形状不同
tensor([[ 0.2061, -0.6647]])
tensor([ 0.2061, -0.6647])
# None类似于np.newaxis, 为a新增了一个轴
# 等价于a.view(1, a.shape[0], a.shape[1])
a[None].shape
torch.Size([3, 1, 4])
a[:,None,:,None,None].shape
torch.Size([3, 1, 4, 1, 1])
a[a>1] # 等价于a.masked_select(a>1)
# 选择结果与原tensor不共享内存空间
tensor([1.0372, 1.1629])
a = t.arange(0, 16).view(4, 4)
a
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
index = t.LongTensor([[0,1,2,3]])
a.gather(0, index)
tensor([[ 0, 5, 10, 15]])
# 选取反对角线上的元素
index = t.LongTensor([[3,2,1,0]]).t()
a.gather(1, index)
tensor([[ 3],
[ 6],
[ 9],
[12]])
# 选取反对角线上的元素,注意与上面的不同
index = t.LongTensor([[3,2,1,0]])
a.gather(0, index)
tensor([[12, 9, 6, 3]])
a[0,0]
a[0,0].item() # python float# python float
0
3. tensor的类型
b=a.float() 转换a为float类型
还有long half 类型
CPU tensor 和GPU tensor类型
4. 逐元素操作
fmod log 取余
ceil/round/floor/trunc 上取整/四舍五入/下取整/只保留整数部分
clamp(input, min, max) #超过min和max部分截断 大于max 的取max 小于min的取min
5. 归并操作
6. 比较
7. 线性代数
矩阵的转置会导致存储空间不连续,需调用它的.contiguous方法将其转为连续。
a = t.arange(0, 6).view(2, 3).float()
# 取a中的每一个元素与3相比较大的一个 (小于3的截断成3)
print(a)
t.clamp(a, min=3)
tensor([[0., 1., 2.],
[3., 4., 5.]])
tensor([[3., 3., 3.],
[3., 4., 5.]])
b=a.t()
b.is_contiguous()
False
b.contiguous()
tensor([[0., 3.],
[1., 4.],
[2., 5.]])
8. tensor和numpy之间的转化
numpy和tensor 共享内存
import numpy as np
a = np.ones([2, 3],dtype=np.float32)
a
array([[1., 1., 1.],
[1., 1., 1.]], dtype=float32)
b = t.from_numpy(a)
b
tensor([[1., 1., 1.],
[1., 1., 1.]])
b = t.Tensor(a) # 也可以直接将numpy对象传入Tensor
b
#注意: 不论输入的类型是什么,
#t.tensor都会进行数据拷贝,不会共享内存
#t.Tensor和t.tensor注意区分
tensor([[1., 1., 1.],
[1., 1., 1.]])
a[0, 1]=100 #共享数据类型,除非是dtype不是同一类型的
b
tensor([[ 1., 100., 1.],
[ 1., 1., 1.]])
c=t.tensor(a)
print(c)
a[0,1]=0
c
tensor([[ 1., 100., 1.],
[ 1., 1., 1.]])
tensor([[ 1., 100., 1.],
[ 1., 1., 1.]])
线性回归的例子
import torch as t
%matplotlib inline
from matplotlib import pyplot as plt
from IPython import display
device = t.device('cpu')
t.manual_seed(1000)
def get_fake_data(batch_size):
x = t.rand(batch_size,1,device=device)*5
y = x*2+3+t.randn(batch_size,1,device=device)
return x,y
x,y = get_fake_data(batch_size=16)
plt.scatter(x.squeeze().cpu().numpy(),y.squeeze().cpu().numpy())
<matplotlib.collections.PathCollection at 0x1694053d748>
w = t.rand(1,1).to(device)
b = t.zeros(1,1).to(device)
lr = 0.01
for ii in range(500):
x,y = get_fake_data(batch_size=4)
y_pred = x.mm(w) + b.expand_as(y)
loss = 0.5*(y_pred - y)**2
loss=loss.mean()
dloss = 1
dy_pred = dloss*(y_pred - y)
dw = x.t().mm(dy_pred)
db = dy_pred.sum()
w.sub_(lr*dw)
b.sub_(lr*db)
if ii%50 == 0:
display.clear_output(wait=True)
x = t.arange(0,6).view(-1,1)
y = x.float().mm(w) +b.expand_as(x)
plt.plot(x.cpu().numpy(), y.cpu().numpy())
x2,y2 = get_fake_data(batch_size=32)
plt.scatter(x2.numpy(), y2.numpy())
plt.xlim(0,5)
plt.ylim(0,13)
plt.show()
plt.pause(0.5)
print('w:', w.item(),'b:',b.item())
w: 2.021925210952759 b: 2.943470001220703