torch的使用(二)

目录

一、张量的形状

1.reshape函数的用法

2.transpose和permute的使用

3.view和contigous函数的用法

4.squeeze 和unsqueeze

二、张量运算函数

三、自动微分

1.梯度基本计算

2.控制梯度计算

3.梯度计算注意


一、张量的形状

1.reshape函数的用法

reshape可以在保证张量数据不变的前提下改变数据的维度,将其转换成指定的形状,在神经网络中,会经常使用该函数来调节数据的形状的操作,以便能够更好处理网络各层之间的数据连接。

    torch.manual_seed(0)
    data = torch.randint(0,10,(4,5))

    print(data.size())
    # 转换之后的形状元素个数要等于原来张量的元素个数
    print(data.reshape(2,10))

    # 使用-1代替省略的形状
    new_data = data.reshape(5,-1)
    print(new_data.size()) 


torch.Size([4, 5])
tensor([[4, 9, 3, 0, 3, 9, 7, 3, 7, 3],
        [1, 6, 6, 9, 8, 6, 6, 8, 4, 3]])
torch.Size([5, 4])

2.transpose和permute的使用

transpose函数可以实现交换张量形状的指定维度,例如:一个张量的形状(2,3,4)可以通过transpose转换为(2,4,3)

permute可以一次转换更多的维度

    # transpose
    torch.manual_seed(0)
    data = torch.randint(0,10,(3,4,5))

    new_data = data.reshape(4,3,5) #重新计算
    print(new_data.shape)

    # 直接交换两个维度的值
    new_data = torch.transpose(data, 0,1)
    print(new_data.shape)
    # 缺点:一次只能交换两个维度


    #permute 一次交换多个维度
    new_data = torch.permute(data,[1,2,0])
    print(new_data.shape)


torch.Size([4, 3, 5])
torch.Size([4, 3, 5])
torch.Size([4, 5, 3])

3.view和contigous函数的用法

view函数也可以修改张量的形状,但是其用法比较局限,只能存储在整块内存中的张量。

    # view
    data = torch.tensor([[10,20,30],[40,50,60]])
    data = data.view(3,2)
    print(data.shape)
    # is_contiguous 函数判断张量是否是连续内存空间
    print(data.is_contiguous())
    data = torch.transpose(data,1,0)
    print(data.is_contiguous())
    data = data.contiguous().view(3,2)
    print(data)

torch.Size([3, 2])
True
False
tensor([[10, 30],
        [50, 20],
        [40, 60]])

4.squeeze 和unsqueeze

squeeze用于删除shape为1的维度,unsqueeze在每个维度添加1,以增加数据的形状

    data = torch.randint(0,10,(1,3,1,5))
    print(data.shape)

    #维度压缩 默认压缩所有为1的维度
    new_data = data.squeeze()
    print(new_data.shape)

    #指定去掉某个1的维度
    new_data = data.squeeze(0)
    print(new_data.shape)

    # unsqueeze 指定哪个维度 -1代表最后一个维度
    new_data = new_data.unsqueeze(-1)
    print(new_data.shape)


torch.Size([1, 3, 1, 5])
torch.Size([3, 5])
torch.Size([3, 1, 5])
torch.Size([3, 1, 5, 1])

二、张量运算函数

    #1 均值
    torch.manual_seed(0)
    data = torch.randint(0,10,[2,3]).double()
    # print(data.dtype)
    print(data)
    print(data.mean())
    # 按指定的维度计算均值
    print(data.mean(dim=0)) # 按列
    print('-'*10,'求和')
    print(data.sum())
    print(data.sum(dim=1))
    print('-'*10,'平方')
    print(data.pow(2))
    print('-'*10,'平方根')
    print(data.sqrt())
    print('-'*10,'e的n次方')
    print(data.exp())
    print('-'*10,'对数')
    print(data.log()) # 默认以e为底
    print(data.log2()) # 以2为底
    print(data.log10()) # 以10为底



tensor([[4., 9., 3.],
        [0., 3., 9.]], dtype=torch.float64)
tensor(4.6667, dtype=torch.float64)
tensor([2., 6., 6.], dtype=torch.float64)
---------- 求和
tensor(28., dtype=torch.float64)
tensor([16., 12.], dtype=torch.float64)
---------- 平方
tensor([[16., 81.,  9.],
        [ 0.,  9., 81.]], dtype=torch.float64)
---------- 平方根
tensor([[2.0000, 3.0000, 1.7321],
        [0.0000, 1.7321, 3.0000]], dtype=torch.float64)
---------- e的n次方
tensor([[5.4598e+01, 8.1031e+03, 2.0086e+01],
        [1.0000e+00, 2.0086e+01, 8.1031e+03]], dtype=torch.float64)
---------- 对数
tensor([[1.3863, 2.1972, 1.0986],
        [  -inf, 1.0986, 2.1972]], dtype=torch.float64)
tensor([[2.0000, 3.1699, 1.5850],
        [  -inf, 1.5850, 3.1699]], dtype=torch.float64)
tensor([[0.6021, 0.9542, 0.4771],
        [  -inf, 0.4771, 0.9542]], dtype=torch.float64)


三、自动微分

自动微分模块对张量做了进一步的封装,具有自动求导的功能。自动微分模块是构成神经网络的必要模块,在神经网络的反向传播过程中,Autigrad模块基于正向计算的结果对当前的参数进行微分计算,从而实现网络权重参数的更新。

1.梯度基本计算

# 标量的梯度计算
#y = x**2+20
def test01():
    #对于需要求导的张量需要设置 requires_grad=True
    x = torch.tensor(10,requires_grad=True,dtype=torch.float64)
    # 对x的中间计算
    f = x ** 2 +20  # 2x
    # 自动微分
    f.backward()
    # 访问梯度
    print(x.grad)

    # 2.向量的梯度计算
    x = torch.tensor([10,20,30,40],requires_grad=True,dtype=torch.float64)
    # 定义变量的计算过程
    y1 =  x ** 2 +20
    #注意:自动微分的时候,必须是一个标量
    y2 = y1.mean() # 1/4 * y1
    #自动微分
    y2.backward()

    # 打印梯度值
    print(x.grad)

    # 3.多标量梯度计算
    # y= x1 ** 2 + x2 ** 2 + x1*2
    x1 = torch.tensor(10,requires_grad=True,dtype=torch.float64)
    x2 = torch.tensor(20, requires_grad=True, dtype=torch.float64)

    y= x1 ** 2 + x2 ** 2 + x1*x2

    # 自动微分
    y.backward()

    #打印梯度值
    print(x1.grad)
    print(x2.grad)
    # 4.多向量梯度计算
    x1 = torch.tensor([10,20],requires_grad=True,dtype=torch.float64)
    x2 = torch.tensor([30,40], requires_grad=True, dtype=torch.float64)
    # 定义中间计算过程
    y= x1 ** 2 + x2 ** 2 + x1*x2

    #将输出结果变为标量
    y = y.sum()

    # 自动微分
    y.backward()

    #打印梯度值
    print(x1.grad)
    print(x2.grad)


tensor(20., dtype=torch.float64)
tensor([ 5., 10., 15., 20.], dtype=torch.float64)
tensor(40., dtype=torch.float64)
tensor(50., dtype=torch.float64)
tensor([50., 80.], dtype=torch.float64)
tensor([ 70., 100.], dtype=torch.float64)

2.控制梯度计算

# 1.控制梯度计算
def test01():
   # 控制梯度计算
   x = torch.tensor(10,requires_grad=True,dtype=torch.float64)
   print(x.requires_grad)

   #第一种方法
   with torch.no_grad():
    y = x**2  # 这个过程不参与梯度计算
   print(y.requires_grad)
   # 第二种方法
   @torch.no_grad()
   def my_func(x):
       return x**2

   y = my_func(x)
   print(y.requires_grad)
   # 第三种方法  全局的方式
   torch.set_grad_enabled(False)
   y = x ** 2
   print(y.requires_grad)

def test02():
   # 累计梯度和梯度清零
   x = torch.tensor([10, 20, 30, 40], requires_grad=True, dtype=torch.float64)
   # 当我们重复对x进行梯度计算的时候,时会将历史的梯度值累加到x.grad 属性中
   for _ in range(3):
       #对输入x的计算过程
       f1 = x**2 + 20
       # 将向量转换为标量
       f2 = f1.mean()
       # 梯度清零
       if x.grad is not None:
           x.grad.data.zero_()
       #自动微分
       f2.backward()
       # 打印梯度值
       print(x.grad)

# 梯度下降优化案例
def test03():

    # y = x** 2
    # 当x为什么值的情况下,y最小
    x = torch.tensor(10, requires_grad=True, dtype=torch.float64)

    for _ in range(5000):

        #正向计算
        y = x**2

        #梯度清零
        if x.grad is not None:
            x.grad.data.zero_()
        #自动微分
        y.backward()

        # 更新参数
        x.data = x.data - 0.001* x.grad

        # 打印x的值
        print('%.10f'%x.data)

3.梯度计算注意

当设置requires_grad=True的张量使用numnpy函数进行转换时,会报错。

RuntimeError: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.

需要使用detach函数将张量分离,在使用numpy函数。

注意:detach之后会产生一个新的张量,新的张量作为叶子节点,并且该张量和原来的张量共享数据,但是分离后的张量不需要计算梯度。

    x1 = torch.tensor([10,20],requires_grad=True,dtype=torch.float64)

    x2 = x1.detach()

    print(id(x1.data),id(x2.data))

    # 修改分离后的张量
    x2[0] = 100
    print(x1)
    print(x2)
    # x2张量不存在requires_grad=True
    # 表示x1的任何计算都会影响到 x1的梯度计算
    # 表示x2的任何计算都不会影响到x1的梯度计算

2316405416640 2316405416640
tensor([100.,  20.], dtype=torch.float64, requires_grad=True)
tensor([100.,  20.], dtype=torch.float64)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值