当前位置: 首页 > news >正文

[Pytorch]深度学习-part1

一、Pytorch的安装

 1.1打开cmd

1.2 输入nvidia-smi

可以查看到CUDA Version的版本是12.7

我们在安装的时候,需要注意,安装的cuda要小于等于我们电脑显示的CUDA版本

1.3 (可选)卸载之前版本Pytorch

通过上述方法,卸载之前安装的错误版本

1.4 正式安装

我这里选择安装12.4版本

>pip install torch==2.5.1 torchvision==0.20.1 torchaudio==2.5.1 --index-url https://download.pytorch.org/whl/cu124

1.5 检测是否安装成功

打开VS,使用安装了这个pytorch包的环境

这里可以看到成功安装:)

二、基本创建方式

2.1torch.tensor

    # 1. 用标量创建张量
tensor = torch.tensor(5)
print(tensor.shape)

    # 2. 使用numpy随机一个数组创建张量
tensor = torch.tensor(np.random.randn(3, 5))
print(tensor)
print(tensor.shape)

    # 3. 根据list创建tensor
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(tensor)
print(tensor.shape)
print(tensor.dtype)

1.2torch.Tensor

# 1. 根据形状创建张量
tensor1 = torch.Tensor(2, 3)
print(tensor1)
# 2. 也可以是具体的值
tensor2 = torch.Tensor([[1, 2, 3], [4, 5, 6]])
print(tensor2, tensor2.shape, tensor2.dtype)

    tensor3 = torch.Tensor([10])
print(tensor3, tensor3.shape, tensor3.dtype)

# 指定tensor数据类型
tensor1 = torch.Tensor([1,2,3]).short()
print(tensor1)

tensor1 = torch.Tensor([1,2,3]).int()
print(tensor1)

tensor1 = torch.Tensor([1,2,3]).float()
print(tensor1)

tensor1 = torch.Tensor([1,2,3]).double()
print(tensor1)

torch.Tensor与torch.tensor区别

特性torch.Tensor()torch.tensor()
数据类型推断强制转为 torch.float32根据输入数据自动推断(如整数→int64
显式指定 dtype不支持支持(如 dtype=torch.float64
设备指定不支持支持(如 device='cuda'
输入为张量时的行为创建新副本(不继承原属性)默认共享数据(除非 copy=True
推荐使用场景需要快速创建浮点张量需要精确控制数据类型或设备

1.3torch.IntTensor

用于创建指定类型的张量,还有诸如Torch.FloatTensor、 torch.DoubleTensor、 torch.LongTensor......等。

如果数据类型不匹配,那么在创建的过程中会进行类型转换,要尽可能避免,防止数据丢失。

 # 1. 创建指定形状的张量
tt1 = torch.IntTensor(2, 3)
print(tt1)

    tt2 = torch.FloatTensor(3, 3)
print(tt2, tt2.dtype)
tt3 = torch.DoubleTensor(3, 3)
print(tt3, tt3.dtype)
tt4 = torch.LongTensor(3, 3)
print(tt4, tt4.dtype)
tt5 = torch.ShortTensor(3, 3)
print(tt5, tt5.dtype)

三、创建线性和随机张量

3.1创建线性张量

# 1. 创建线性张量
r1 = torch.arange(0, 10, 2)
print(r1)
# 2. 在指定空间按照元素个数生成张量:等差
r2 = torch.linspace(3, 10, 10)
print(r2)

r2 = torch.linspace(3, 10000000, 10)
print(r2)

3.2随机张量

3.2.1随机数种子

使用随机数种子,生成器将在每次生成相同的数列

    # 设置随机数种子
torch.manual_seed(123)

    # 获取随机数种子
print(torch.initial_seed())

3.2.2随机张量

    # 1. 设置随机数种子
torch.manual_seed(123)

    # 2. 获取随机数种子,需要查看种子时调用
print(torch.initial_seed())

    # 3. 生成随机张量,均匀分布(范围 [0, 1))
# 创建2个样本,每个样本3个特征
print(torch.rand(2, 3))

    # 4. 生成随机张量:标准正态分布(均值 0,标准差 1)
print(torch.randn(2, 3))

    # 5. 原生服从正态分布:均值为2, 方差为3,形状为1*4的正态分布
print(torch.normal(mean=2, std=3, size=(1, 4)))

三、Tensor常见属性

张量常见属性:device,dtype,shape

3.1获取属性

    data = torch.tensor([1, 2, 3])
print(data.dtype, data.device, data.shape)

3.2切换设备

默认cpu上运行,可以切换到GPU上

    # 把数据切换到GPU进行运算
device = "cuda" if torch.cuda.is_available() else "cpu"
data = data.to(device)
print(data.device)

或者直接 data = data.cuda()或者data = data.to("cuda")

3.3类型转化

类型转化是张量的基本操作

 # 1. 使用type进行类型转换
data = data.type(torch.float32)
print(data.dtype)  # float32
data = data.type(torch.float16)
print(data.dtype)  # float16

    # 2. 使用类型方法
data = data.float()
print(data.dtype)  # float32
# 16 位浮点数,torch.float16,即半精度
data = data.half()
print(data.dtype)  # float16
data = data.double()
print(data.dtype)  # float64
data = data.long()
print(data.dtype)  # int64
data = data.int()
print(data.dtype)  # int32

四、Tensor数据转换

4.1张量转Numpy

4.1.1浅拷贝

调用numpy()方法可以把Tensor转化为Numpy,内存共享

    # 1. 张量转numpy
data_tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
data_numpy = data_tensor.numpy()
print(type(data_tensor), type(data_numpy))
# 2. 他们内存是共享的
data_numpy[0, 0] = 100
print(data_tensor, data_numpy)

4.1.2深拷贝

copy()避免内存共享

4.2Numpy转张量

4.2.1浅拷贝

from_numpy方法转Tensor默认是内存共享的

可以看出[0,0]都变成了100

4.2.2深拷贝

用tensor就不会共享内存

五、Tensor常见操作

5.1获取元素值

tips:和Tensor的维度没有关系,如果有多个元素就会报错,只能在CPU上的张量,如果在GPU上就要先移动

5.2元素值运算

带“_”的会改变原始值

5.3阿达玛积

俩形状相同的矩阵或张量对应的元素相乘,阿达玛积是逐元素操作

5.4Tensor相乘

假设有两个矩阵:

  • 矩阵 A的形状为 m×n(m行 n列)。

  • 矩阵 B的形状为 n×p(n行 p列)。

矩阵 A和 B的乘积 C=A×B是一个形状为 m×p的矩阵,其中 C的每个元素 Cij,计算 A的第 i行与 B的第 j列的点积。计算公式为:

就像是线性代数那样,俩矩阵相乘。

5.5形状操作

5.5.1 reshape

5.5.2 view

view进行形状变换的特征:

张量在内存中是连续的;

返回的是原始张量视图,不重新分配内存,效率更高;

如果张量在内存中不连续,view 将无法执行,并抛出错误。

5.5.2.1 内存连续性

对于多维张量,内存布局通常按照最后一个维度优先的顺序存储,即先存列,后存行。

.view() 要求张量在内存中是连续存储的,否则会报错

5.5.2.2 和reshape比较

view:高效,但需要张量在内存中是连续的;

reshape:更灵活,但涉及内存复制;

5.5.2.3 view变形操作

5.5.3 transpose

通过transpose这个方法,将data数据的(3,4,5)其中的0,1位上的数据位置进行转变成(4,3,5)

5.5.4 permute

它通过重新排列张量的维度来返回一个新的张量,不改变张量的数据,只改变维度的顺序。

permute(1, 2, 0) 就是把原来的 (3, 4, 5) 张量整体转置(4, 5, 3)不改变数据内容,只改变维度的排列顺序

5.5.5 升维和降维

unsqueeze:用于在指定位置插入一个大小为 1 的新维度。

squeeze:用于移除所有大小为 1 的维度,或者移除指定维度的大小为 1 的维度。

5.5.5.1 squeeze降维

torch.squeeze(input, dim=None)

  • input: 输入的张量。

  • dim (可选): 指定要移除的维度。如果指定了 dim,则只移除该维度(前提是该维度大小为 1);如果不指定,则移除所有大小为 1 的维度。

data.squeeze(0).squeeze(-1)表达第一维和最后一维,进行降维操作

5.5.5.2 unsqueeze升维

六、广播机制

6.1广播机制规则

张量维度至少为1

满足右对齐

6.2 广播案例

七、自动微分

7.1 基础概念

自动微分模块torch.autograd负责自动计算张量操作的梯度,具有自动求导功能。自动微分模块是构成神经网络训练的必要模块,可以实现网络权重参数的更新,使得反向传播算法的实现变得简单而高效。

7.1.1张量

Torch中一切皆为张量,属性requires_grad决定是否对其进行梯度计算。默认是 False,如需计算梯度则设置为True。

7.1.2 计算图

torch.autograd通过创建一个动态计算图来跟踪张量的操作,每个张量是计算图中的一个节点,节点之间的操作构成图的边。

在 PyTorch 中,当张量的 requires_grad=True 时,PyTorch 会自动跟踪与该张量相关的所有操作,并构建计算图。每个操作都会生成一个新的张量,并记录其依赖关系。当设置为 True 时,表示该张量在计算图中需要参与梯度计算,即在反向传播(Backpropagation)过程中会自动计算其梯度;当设置为 False 时,不会计算梯度。

在上述代码中,x 和 y 是输入张量,即叶子节点,z 是中间结果,loss 是最终输出。每一步操作都会记录依赖关系:

z = x * y:z 依赖于 x 和 y。

loss = z.sum():loss 依赖于 z。

  1. 叶子节点

    在 PyTorch 的自动微分机制中,叶子节点(leaf node) 是计算图中:

    • 由用户直接创建的张量,并且它的 requires_grad=True。

    • 这些张量是计算图的起始点,通常作为模型参数或输入变量。

    特征:

    • 没有由其他张量通过操作生成。

    • 如果参与了计算,其梯度会存储在 leaf_tensor.grad 中。

    • 默认情况下,叶子节点的梯度不会自动清零,需要显式调用 optimizer.zero_grad() 或 x.grad.zero_() 清除。

    如何判断一个张量是否是叶子节点?

    通过 tensor.is_leaf 属性,可以判断一个张量是否是叶子节点。

    x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)  # 叶子节点
    y = x ** 2  # 非叶子节点(通过计算生成)
    z = y.sum()
    ​
    print(x.is_leaf)  # True
    print(y.is_leaf)  # False
    print(z.is_leaf)  # False

    叶子节点与非叶子节点的区别

    特性叶子节点非叶子节点
    创建方式用户直接创建的张量通过其他张量的运算生成
    is_leaf 属性TrueFalse
    梯度存储梯度存储在 .grad 属性中梯度不会存储在 .grad,只能通过反向传播传递
    是否参与计算图是计算图的起点是计算图的中间或终点
    删除条件默认不会被删除在反向传播后,默认被释放(除非 retain_graph=True)

    detach():张量 x 从计算图中分离出来,返回一个新的张量,与 x 共享数据,但不包含计算图(即不会追踪梯度)。

    特点

    • 返回的张量是一个新的张量,与原始张量共享数据。

    • 对 x.detach() 的操作不会影响原始张量的梯度计算。

    • 推荐使用 detach(),因为它更安全,且在未来版本的 PyTorch 中可能会取代 data。

    x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
    y = x.detach()  # y 是一个新张量,不追踪梯度
    ​
    y += 1  # 修改 y 不会影响 x 的梯度计算
    print(x)  # tensor([1., 2., 3.], requires_grad=True)
    print(y)  # tensor([2., 3., 4.])
  2. 反向传播

    使用tensor.backward()方法执行反向传播,从而计算张量的梯度。这个过程会自动计算每个张量对损失函数的梯度。例如:调用 loss.backward() 从输出节点 loss 开始,沿着计算图反向传播,计算每个节点的梯度。

  3. 梯度

    计算得到的梯度通过tensor.grad访问,这些梯度用于优化模型参数,以最小化损失函数。

7.2 计算梯度

tensor.backward()方法执行反向传播,从而计算张量的梯度

7.2.1 标量梯度计算

7.2.2 向量梯度计算

7.2.3 多标量梯度计算

7.2.4 多向量梯度计算

7.3 梯度上下文控制

7.3.1 控制梯度计算

可以通过with torch.no_gard实现不计算y的梯度,还可以通过装饰器@torch.no_grad()实现不计算y的梯度。

7.3.2 累计梯度

7.3.3 梯度清零

7.3.4 求函数最小值

import torch
from matplotlib import pyplot as plt
import numpy as np


def test01():
x = np.linspace(-10, 10, 100)
y = x ** 2

    plt.plot(x, y)

    plt.show()


def test02():
# 初始化自变量X
x = torch.tensor([3.0], requires_grad=True, dtype=torch.float)
# 迭代轮次
epochs = 50
# 学习率
lr = 0.1

    list = []
for i in range(epochs):
# 计算函数表达式
y = x ** 2

        # 梯度清零
if x.grad is not None:
x.grad.zero_()
# 反向传播
y.backward()
# 梯度下降,不需要计算梯度,为什么?
with torch.no_grad():
x -= lr * x.grad

        print('epoch:', i, 'x:', x.item(), 'y:', y.item())
list.append((x.item(), y.item()))

    # 散点图,观察收敛效果
x_list = [l[0] for l in list]
y_list = [l[1] for l in list]

    plt.scatter(x=x_list, y=y_list)
plt.show()


if __name__ == "__main__":
test01()
test02()

用 PyTorch 的自动求导功能,手动实现对函数 y = x² 的最小值优化过程。

初始化变量

x = torch.tensor([3.0], requires_grad=True)  # 起点 x=3

设置超参数

epochs = 50      # 迭代50轮
lr = 0.1         # 学习率0.1

主循环

for i in range(epochs):y = x ** 2                    # 前向:计算 yx.grad.zero_()                # 清零梯度(防止累加)y.backward()                  # 反向传播:计算 dy/dxwith torch.no_grad():         # 禁止梯度计算(避免追踪)x -= lr * x.grad          # 更新 x:x = x - lr * dy/dx

7.3.5 函数参数求解

import torch

def test02():

    x = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float)

    y = torch.tensor([3, 5, 7, 9, 11], dtype=torch.float)

   

    a = torch.tensor([1.0], requires_grad=True)  # 简化初始化

    b = torch.tensor([1.0], requires_grad=True)

    lr = 0.01

    epochs = 100

    for epoch in range(epochs):

        # 每次迭代前清零梯度(无条件)

        if a.grad is not None:  # 确保梯度存在时清零

            a.grad.zero_()

        if b.grad is not None:

            b.grad.zero_()

       

        # 前向传播

        y_pred = a * x + b

        loss = ((y_pred - y) ** 2).mean()

       

        # 反向传播

        loss.backward()

       

        # 梯度下降(不追踪计算图)

        with torch.no_grad():

            a -= lr * a.grad

            b -= lr * b.grad

       

        if (epoch + 1) % 10 == 0:

            print(f'Epoch [{epoch + 1}/{epochs}], Loss: {loss.item():.4f}')

    print(f'Final parameters: a = {a.item():.4f}, b = {b.item():.4f}')

if __name__ == '__main__':

    test02()

输出结果接近期望的a=2 b=1的结果。

http://www.dtcms.com/a/279291.html

相关文章:

  • 策略模式及优化
  • LangChain面试内容整理-知识点16:OpenAI API接口集成
  • Linux操作系统之信号:信号的产生
  • 观察应用宝进程的自启动行为
  • Spring Boot启动原理:从main方法到内嵌Tomcat的全过程
  • vue vxe-tree 树组件加载大量节点数据,虚拟滚动的用法
  • 每日mysql
  • # 检测 COM 服务器在线状态
  • 在Linux下git的使用
  • 7.14练习案例总结
  • 渗透第一次总结
  • ThreadLocal内部结构深度解析(Ⅰ)
  • Olingo分析和实践——整体架构流程
  • idea下无法打开sceneBulider解决方法
  • JavaScript书写基础和基本数据类型
  • 关于僵尸进程
  • SwiftUI 全面介绍与使用指南
  • SSM框架学习——day1
  • 爬虫-爬取豆瓣top250
  • webrtc之子带分割下——SplittingFilter源码分析
  • vscode插件之markdown预览mermaid、markmap、markdown
  • 直播推流技术底层逻辑详解与私有化实现方案-以rmtp rtc hls为例-优雅草卓伊凡
  • 当 `conda list` 里出现两个 pip:一步步拆解并卸载冲突包
  • 2025年轨道交通与导航国际会议(ICRTN 2025)
  • 【数据同化案例1】ETKF求解参数-状态联合估计的同化系统(完整MATLAB实现)
  • C#结构体:值类型的设计艺术与实战指南
  • 2025年新能源与可持续发展国际会议(ICNESD 2025)
  • 非正常申请有这么多好处,为什么还要大力打击?
  • TreeSize Free - windows下硬盘空间管理工具
  • 一分钟K线实时数据数据接口,逐笔明细数据接口,分时成交量数据接口,实时五档委托单数据接口,历史逐笔明细数据接口,历史分时成交量数据接口