pyTorch入门:numpy与Tensor

python 深度学习,基于pytorch 的学习笔记,,

numpy 复习

  1. 使用np.random 生成随机数组
    在这里插入图片描述
  • np.random.choice()
import numpy as np 
from numpy import random as nr 
a=np.arange(1,25,dtype=float) 
c1=nr.choice(a,size=(3,4)) #size指定输出数组形状 
c2=nr.choice(a,size=(3,4),replace=False) #replace缺省为True,即可重复抽取。 
#下式中参数p指定每个元素对应的抽取概率,不设置就是每个元素被抽取的概率相同。 
c3=nr.choice(a,size=(3,4),p=a / np.sum(a)) 
  1. 构建数组
    在这里插入图片描述
  • np.savetxt( X=data, fname=’./test1.txt’) 保持数据到文本
  • data = np.loadtxt(’./test.txt’)
  1. 改变数组形状

在这里插入图片描述

arr =np.arange(6).reshape(2, -1)
print(arr)
print("按照列优先,展平") 
print(arr.ravel('F'))   
print("按照行优先,展平") 
print(arr.ravel()) 
输出结果: 
[[0 1 2] 
[3 4 5]] 
按照列优先,展平 
[0 3 1 4 2 5] 
按照行优先,展平 
[0 1 2 3 4 5]

# flatten 将矩阵转为向量,通常在卷积网络与全连接层之间
a =np.floor(10*np.random.random((3,4)))
print(a.flatten())

[[4. 0. 8. 5.] 
[1. 0. 4. 8.] 
[8. 2. 3. 7.]] 

[4. 0. 8. 5. 1. 0. 4. 8. 8. 2. 3. 7.]

# squeeze降维的
arr =np.arange(3).reshape(3, 1) 
print(arr.shape) #(3,1) 
print(arr.squeeze().shape) #(3,) 
arr1 =np.arange(6).reshape(3,1,2,1) 
print(arr1.shape) #(3, 1, 2, 1) 
print(arr1.squeeze().shape) #(3, 2)

# transpose 轴转换,深度学习中可以用来吧图片从 RGB -> GBR
arr2 = np.arange(24).reshape(2,3,4) 
print(arr2.shape) #(2, 3, 4) 
print(arr2.transpose(1,2,0).shape) #(3, 4, 2)
  1. 数组合并
    在这里插入图片描述
  • append concatenate stack 都有一个 axis 参数,控制数组的合并方式是按行还是按列
  • 合并是注意两者的形状要匹配。
a =np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])

c = np.concatenate((a, b), axis=0)    # 跨行
print(c)
d = np.concatenate((a, b.T), axis=1)
print(d)

[[1 2]
 [3 4]
 [5 6]]
[[1 2 5]
 [3 4 6]]

a =np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
print(np.stack((a, b), axis=0))       # 这个是按指定轴堆叠数组或矩阵
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]   # 维数是不一样的
  1. 批量处理

随机梯度下降法嘛,,SGD。分批次处理

#生成10000个形状为2X3的矩阵
data_train = np.random.randn(10000,2,3)
#这是一个3维矩阵,第一个维度为样本数,后两个是数据形状
print(data_train.shape)
#(10000,2,3)
#打乱这10000条数据
np.random.shuffle(data_train)
#定义批量大小
batch_size=100
#进行批处理
for i in range(0,len(data_train),batch_size):
    x_batch_sum=np.sum(data_train[i:i+batch_size])        # 批处理数据集
    print("第{}批次,该批次的数据之和:{}".format(i,x_batch_sum))
  1. 通用函数
    在这里插入图片描述

  2. 广播机制

在这里插入图片描述

Tensor

与numpy 相似,可以是零维,多维数组,并共享内存,区别就是Tensor 可以放到GPU 中加速计算。

针对 Tensor 的操作,按照接口划分:

  • torch.function,比如 torch.sum torch.add(x,y) ( 等价于 x.add(y))
  • tensor.function 比如 tensor.view,tensor.add

针对修改方式:

  • 不修改自身数据:x.add(y) x不变,返回一个新的Tensor
  • 修改自身数据:x.add_(y) 修改x
x=torch.tensor([1,2])
y=torch.tensor([3,4])
z=x.add(y)
print(z)
print(x)
x.add_(y)
print(x)

tensor([4, 6])
tensor([1, 2])
tensor([4, 6])
  1. 创建:
函数功能
Tensor(*size)从参数中构造一个张量,支持List, Numpy数组
eye(row,column)创建指定行数,列数的二维单位Tensor
linspace(start, end, stepes)等差数列
logspace(start,end,steps)从 10^start 到 10^end ,分成steps份
rand/randn(*size)生成 [0,1) 均匀分布/标准正态分布数据
ones/zeros/ones_likes/zeros_like/arange(start,end,step)都懂。。
from_Numpy(ndarray)从ndarray 创建一个Tensor
torch.Tensor([1,2,3,4,5,6])
torch.Tensor(2,3)
t=torch.Tensor([[1,2,3],[4,5,6]])
t.size(),t.shape                # shape 与 size 等价
>>> (torch.Size([2, 3]), torch.Size([2, 3]))

torch.Tensor(t.size())       # 根据已有形状创建
>>> 
tensor([[0., 0., 0.],
        [0., 0., 0.]])


# torch.Tensor and  torch.tensor 的区别

t1 = torch.Tensor(1)
t2= torch.tensor(1)
print(t1,t1.type(),t2,t2.type())  # Tensor使用默认的dtype(FloatTensor) .tensor从数据中推断类型
>>> tensor([7.3447e-16]) torch.FloatTensor tensor(1) torch.LongTensor 
 # tensor(1)返回一个固定值1,而Tensor() 返回的是大小为 1 的随机张量
  1. 修改形状
函数说明
size()返回张量的 shape 值与函数,shape 等价
numel(input)计算Tensor 的元素个数
view(*shape)修改Tensor 的shape,与 Reshape类似,返回的对象与原Tensor 共享内存,修改一个都会修改。Reshape 就是生成一个新对象,而且不要求 原Tensor是连续的,View(-1) 展平数组
resize类似于view,但在 size 超出时重新分配内存。
item若Tensor是单元素,返回python 的标量
unsqueeze在指定维度加个1
squeeze在指定维度压缩一个1

x = torch.randn(2, 3)
x.size()   
>>> torch.Size([2, 3])

#查看x的维度
x.dim()    #结果为2
#把x变为3x2的矩阵
x.view(3,2)
#把x展平为1维向量
y=x.view(-1)  
y.shape   >>> torch.Size([6])
#添加一个维度
z=torch.unsqueeze(y,0)
#查看z的形状
z.size()   #结果为torch.Size([1, 6])
#计算Z的元素个数
z.numel()   #结果为6

torch.view and torch.reshape 的区别:

  • reshape()可以由,torch.reshape() or torch.Tensor.reshape() 调用。但 view() 只能由 torch.Tensor.view() 调用。
  • 对一个要被view 的 Tensor,新的size 必须与原来的 size与 stride 兼容,否则在之前调用contiguous 方法()
  • 只想重塑张量,使用torch.reshape ,如果还关注内存的使用并确保两个张量共享相同的数据,使用torch.view。
  1. 索引操作

索引操作与numpy类似,一般来说 索引结果与源数据共享内存。索引还可以通过一些函数

函数说明
index_select(input, dim, index)在指定维度上选择一些行或列
nonzero(input)获取非 0 元素的下标
masked_select(input, mask)使用二元值进行选择
gather( input, dim ,index)在指定维度上选择数据,输出的形状与 Index(LongTensor类型) 一致。
scatter_(input, dim, index, src)gather 的反操作,根据指定索引补充数据
torch.manual_seed(100)   # 一个随机种子
x = torch.randn(2,3)
x
>>> 
tensor([[ 0.3607, -0.2859, -0.3938],
        [ 0.2429, -1.3833, -2.3134]])


x[1,1:]  # >>> tensor([-1.3833, -2.3134])
x[:,-1] # >>> tensor([-0.3938, -2.3134])
mask=x>0      # 生成是否大于零的 Byter 张量
# tensor([[ True, False, False],   mask
#         [ True, False, False]])


torch.masked_select(x,mask)  # >>> tensor([0.3607, 0.2429]) 大于零的值
torch.nonzero(mask)  
# tensor([[0, 0],          # 非零下标,就是行,列的索引。
#         [1, 0]])

torch.index_select(x,1,torch.tensor([0,2]))     # 指定维度的跨行索引。。
>>>
tensor([[ 0.3607, -0.3938],
        [ 0.2429, -2.3134]])

#获取指定索引对应的值,输出根据以下规则得到
#out[i][j] = input[index[i][j]][j]  # if dim == 0  对行的操作
#out[i][j] = input[i][index[i][j]]  # if dim == 1  对列的操作,,啥玩意。。
index=torch.LongTensor([[0,1,1],[1,1,1]])
a=torch.gather(x,1,index)
a
>>>
tensor([[ 0.3607, -0.2859, -0.2859],
        [-1.3833, -1.3833, -1.3833]])

#把a的值返回到一个2x3的0矩阵中
z=torch.zeros(2,3)
torch.scatter(z,1,index,a)            # 顶层没有scratter_() 方法
z.scatter_(1,index,a)          
>>>
tensor([[ 0.3607, -0.2859,  0.0000],  # 对指定索引补充数据,,这又是啥。。
        [ 0.0000, -1.3833,  0.0000]])

torch.gather 脑补连接
语言处理中,给每个单词上一个标签,现在我们有四个句子(由单词标签构成的不同长度的句子):

input = [
[2, 3, 4, 5],
[1, 4, 3],
[4, 2, 2, 5, 7],
[1]
]
进行填充,padding

input = [
[2, 3, 4, 5, 0, 0],
[1, 4, 3, 0, 0, 0],
[4, 2, 2, 5, 7, 0],
[1, 0, 0, 0, 0, 0]
]
现在要从填充后的input 中选出最后一个单词的标签。

input = [
    [2, 3, 4, 5, 0, 0],
    [1, 4, 3, 0, 0, 0],
    [4, 2, 2, 5, 7, 0],
    [1, 0, 0, 0, 0, 0]
]
input = torch.tensor(input)  # 在指定维度上选择数据,输出的形状与 Index(LongTensor类型) 一致。
#注意index的类型 ,
# 将input的第i维的大小更改为y,且要满足y>=1(除了第i维之外的其他维度,大小要和input保持一致)
length = torch.LongTensor([[3],[2],[4],[0]])       # 学废了吗
out = torch.gather(input, 1, length)
out
tensor([[5],
        [3],
        [7],
        [1]])

length = torch.LongTensor([[3,0],[2,0],[4,0],[0,0]])
out = torch.gather(input, 1, length)
out
tensor([[5, 2],
        [3, 1],
        [7, 4],
        [1, 1]])

length = torch.LongTensor([[2,3]])   # 前两行的第三个,第四个元素
out = torch.gather(input, 0, length)
out
tensor([[4, 0]])

torch.scatter 脑部链接

就是把input数组中的数据进行重新分配。index中表示了要把原数组中的数据分配到output数组中的位置,如果未指定,则填充0。就是index 中的是index 中元素在 output 中的位置。

在这里插入图片描述
不一定所有的input数据都会分到output中,output也不是所有位置都有对应的input,当output中没有对应的input时,自动填充0。

一般scatter用于生成onehot向量,


index = torch.tensor([[1], [2], [0], [3]])
onehot = torch.zeros(4, 4)
onehot.scatter_(1, index, 1)
print(onehot)

tensor([[0., 1., 0., 0.],
[0., 0., 1., 0.],
[1., 0., 0., 0.],
[0., 0., 0., 1.]])

  1. 广播机制
A = np.arange(0, 40,10).reshape(4, 1)
B = np.arange(0, 3)
#把ndarray转换为Tensor
A1=torch.from_numpy(A)  #形状为4x1
B1=torch.from_numpy(B)  #形状为3
print(A1.shape,B1.size())
#Tensor自动实现广播
C=A1+B1     # torch.Size([4, 1]) torch.Size([3]) -> 4,3
print(C)

#我们可以根据广播机制,手工进行配置
#根据规则1,B1需要向A1看齐,把B变为(1,3)
B2=B1.unsqueeze(0)  #B2的形状为1x3
#使用expand函数重复数组,分别的4x3的矩阵
A2=A1.expand(4,3)
B3=B2.expand(4,3)
#然后进行相加,C1与C结果一致
C1=A2+B3
print(C1)

>>>
torch.Size([4, 1]) torch.Size([3])
tensor([[ 0,  1,  2],
        [10, 11, 12],
        [20, 21, 22],
        [30, 31, 32]], dtype=torch.int32)
tensor([[ 0,  1,  2],
        [10, 11, 12],
        [20, 21, 22],
        [30, 31, 32]], dtype=torch.int32)
  1. 逐元素操作

大多逐元素操作与numpy 类似,如果需要就地操作,可以在后面加个下划线 add_()

函数说明
abs/add绝对值,加法
addcdiv( t,v,t1, t2)t1 ,t2 按元素除后,乘 v 加 t 。
addcmul( t, v, t1, t2)t1,t2 按元素乘后,乘v 加 t
ceil /floor向上取整,向下取整
clamp(t, min, max)将张量元素限制在指定区间
exp/log/pow指数,对数,幂
mul or * /neg逐元素乘法/ 取反
sigmoid/tanh/softmax激活函数,,专业
sign/sqrt取符号,开根

感受到了np 之处。。

t = torch.randn(1, 3)
t1 = torch.randn(3, 1)
t2 = torch.randn(1, 3)
#t+0.1*(t1/t2)
torch.addcdiv(t, 0.1, t1, t2)
#计算sigmoid
torch.sigmoid(t)
#将t限制在[0,1]之间
torch.clamp(t,0,1)
#t+2进行就地运算
t.add_(2)
  1. 归并操作

对输入进行归并或合计等操作。。归并操作可以针对整个 Tensor or 针对某一个 axis

函数说明
cumprod(t, axis)累积
cumsum累加
dist(a,b,p=2)返回a,b 之间的 p 阶范数(二阶就是距离吧)
mean/median均值/中位数
std/var标准差/方差
norm(t,p=2)t 的 p 阶范数
prod(t)/sum(t)t 中所用元素的积/和

各种范数

在这里插入图片描述
归并操作一般有一个 dim 参数,指定在那个维度进行归并,keepdim 决定是否要保留维度1.默认不保留

a=torch.linspace(0,10,6)
a=a.view((2,3))
#沿y轴方向累加,即dim=0
b=a.sum(dim=0)   #b的形状为[3]  ,等于  a.sum(axis=0) 对列操作
>>> tensor([ 6., 10., 14.])
#沿y轴方向累加,即dim=0,并保留含1的维度
b=a.sum(dim=0,keepdim=True) #b的形状为[1,3]
>>>tensor([[ 6., 10., 14.]])
  1. 比较操作

一般是逐元素比较,有些是按指定方向比较

函数说明
eq比较Tensor 是否相等
equal比较两个Tensor s是否有相同的shape与值
ge/le/gt/lt大于/小于 / 大于等于/小于等于
max/min(t,axis)最值,指定axis 额外返回下标
topk(t,k,axis)指定axis 维上取最高的K 个值
x=torch.linspace(0,10,6).view(2,3)
#求所有元素的最大值
torch.max(x)   #结果为10
#求y轴方向的最大值
torch.max(x,dim=0)  #结果为[6,8,10]
>>>
torch.return_types.max(
values=tensor([ 6.,  8., 10.]),     # 专业
indices=tensor([1, 1, 1]))

#求最大的2个元素
torch.topk(x,2,dim=0)  
>>>
torch.return_types.topk(
values=tensor([[ 6.,  8., 10.],
               [ 0.,  2.,  4.]]),
indices=tensor([[1, 1, 1],
                [0, 0, 0]]))
  1. 矩阵操作
函数说明
dot(t1,t2)内积或点积
mm(mat1,mat2)/bmm(batch1,batch2)计算矩阵乘法/含batch 的3D 矩阵乘法
mv(t1,t2)计算矩阵与向量乘法
svd(t)计算t 的SVD 分解
t转置
  • Torch的 dot 是对两个 一维的点积运算,mm 才是2D 的矩阵的点积运算,bmm 3D点积。numpy中的dot 没有限制
a=torch.tensor([2, 3])
b=torch.tensor([3, 4])
torch.dot(a,b) 
tensor(18)

x=torch.randint(10,(2,3))
y=torch.randint(6,(3,4))
torch.mm(x,y)
tensor([[36, 77, 81, 41],
        [45, 63, 69, 42]])

x=torch.randint(10,(2,2,3))
y=torch.randint(6,(2,3,4))
torch.bmm(x,y)
(tensor([[[1, 8, 9],
          [0, 0, 6]],
 
         [[2, 4, 8],
          [0, 4, 3]]]),
 tensor([[[0, 2, 2, 0],
          [0, 1, 1, 5],
          [1, 5, 5, 0]],
 
         [[4, 2, 0, 1],
          [4, 5, 3, 3],
          [4, 0, 5, 1]]]))

tensor([[[ 9, 55, 55, 40],
         [ 6, 30, 30,  0]],     # 就是两个二维矩阵的点乘。。然后stack 堆叠起来

        [[56, 24, 52, 22],
         [28, 20, 27, 15]]])

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值