一期0. AI认知课/pytorch框架

news/2025/10/26 19:22:14/文章来源:https://www.cnblogs.com/fuminer/p/19167231

1.1 人工智能发展史

人工智能发展史¶

学习目标¶

  • 了解人工智能发展历史
  • 了解目前AI的主流技术方向与就业方向
  • 人工智能 (Artificial Intelligence, 简称AI) 这个概念是在1956年提出的. 这一年, 约翰·麦卡锡 (John McCarthy) 和其他几位科学家在美国达特茅斯学院 (Dartmouth College) 组织了一场研讨会, 首次提出了"人工智能"一词, 标志着人工智能作为一门学科的正式诞生.
  • 人工智能这个概念从诞生到今天也只有不到70年的时间, 是一门很年轻的科学.
  • 深度学习所需要的神经网络技术起源于20世纪50年代, 叫做感知机. 当时也通常使用单层感知机, 尽管结构简单, 但是能够解决复杂的问题. 后来感知机被证明存在严重的问题, 因为只能学习线性可分函数, 连简单的异或 (XOR) 等线性不可分问题都无能为力.
  • 1969年Marvin Minsky写了一本叫做《Perceptrons》的书, 他提出了著名的两个观点:
  • 1: 单层感知机没用, 我们需要多层感知机来解决复杂问题.
  • 2: 没有有效的训练算法.
  • 20世纪80年代末期, 用于人工神经网络的反向传播算法 (Back Propagation算法, BP算法) 的发明, 给机器学习带来了希望, 掀起了基于统计模型的机器学习热潮, 这个热潮一直持续到今天. 人们发现, 利用BP算法可以让一个人工神经网络模型从大量训练样本中学习统计规律, 从而对未知事件做预测. 这种基于统计的机器学习方法比起过去基于人工规则的系统, 在很多方面显出优越性.
  • 这个时候的人工神经网络, 虽也被称作多层感知机 (Multi-layer Perceptron), 但实际是种只含有一层隐层节点的浅层模型.
  • 2012年, 在著名的ImageNet图像识别大赛中, 杰弗里·辛顿领导的小组采用深度学习模型AlexNet一举夺冠, AlexNet采用ReLU激活函数, 从根本上解决了梯度消失问题, 并采用GPU极大的提高了模型的运算速度.
  • 同年, 由斯坦福大学著名的吴恩达教授和世界顶尖计算机专家Jeff Dean共同主导的深度神经网络, DNN技术在图像识别领域取得了惊人的成绩, 在ImageNet评测中成功的把错误率从26%降低到了15%. 深度学习算法在世界大赛的脱颖而出, 也再一次吸引了学术界和工业界对于深度学习领域的关注.
  • 2016年, 随着谷歌公司基于深度学习开发的AlphaGo以4:1的比分战胜了国际顶尖围棋高手李世石, 深度学习的热度一时无两. 后来, AlphaGo又接连和众多世界级围棋高手过招, 均取得了完胜. 这也证明了在围棋界, 基于深度学习技术的机器人已经彻底超越了人类.
  • 2017年, 基于强化学习算法的AlphaGo升级版AlphaGo Zero横空出世. 其采用"从零开始", "无师自通"的学习模式, 以100:0的比分轻而易举打败了之前的AlphaGo. 除了围棋, 它还精通国际象棋等其它棋类游戏, 可以说是真正的棋类天才.
  • 2017年, 谷歌推出了划时代的作品Transformer, 对整个人工智能的发展影响深远. 此外在这一年, 深度学习的相关算法在医疗、金融、艺术、无人驾驶等多个领域均取得了显著的成果. 所以, 也有专家把2017年看作是深度学习甚至是人工智能发展最为突飞猛进的一年.
  • 2018年, 谷歌推出了BERT, 开启了预训练模型和迁移学习的时代.
  • 2019年, GPT2, T5, AlBERT, RoBERTa, XLNet, 一系列预训练模型的推出大大提升了AI的应用效果.
  • 2020年, 深度学习扩展到更多的应用场景, 比如积水识别, 路面塌陷等, 而且疫情期间, 在智能外呼系统, 人群测温系统, 口罩人脸识别等都有深度学习的应用.
  • 2021年, 巨量模型大量涌现, 参数规模从几百亿迅速增长到上万亿.
  • 2022年11月30日, ChatGPT横空出世, 开启了AI大模型的时代.
  • 2023年, 是全世界大模型的战国时代.
  • 2024年, 2月份Sora横空出世, 5月GPT-4o, DeepSeek-v2, 快手可灵, 都是最前沿的成果.

人工智能关键词¶

  • 人工智能 (Artificial Intelligence)
  • 机器学习 (Machine Learning) - 深度学习 (Deep Learning)
    • 大语言模型 (Large Language Model)

AI技术方向 & 就业方向¶

  • AI主流技术方向:
  • ASR: 语音
  • CV: 视觉
  • NLP: 语言
  • MM: 多模态
  • RS: 搜广推
  • RL: 强化学习
  • AI主流就业方向:
  • AI算法工程师
  • AI大模型工程师
  • AI研发工程师
  • AI应用开发工程师
  • AI产品经理
  • AI训练师
  • AI数据标注师

2.1 人工智能的奇点ChatGPT

人工智能的奇点ChatGPT¶

学习目标¶

  • 理解ChatGPT的发展脉络和重大意义.

ChatGPT时刻¶

  • 2017年6月Transformer横空出世!!!
  • 2018年6月GPT, 参数量1.1亿, 核心点是基于Transformer Decoder的masked multi-head self-attention
  • 2019年2月GPT2, 参数量15亿, 核心点是融合了prompt learning, 省去了微调.
  • 2020年5月GPT3, 参数量1750亿, 核心点是通过ICL(In-Context Learning)开启了prompt新范式.
  • 2021年7月Codex, 基于GPT3进行了大量的代码训练而产生的模型Codex, 使其具备了代码编写和代码推理能力.
  • 2021年10月OpenAI内部发展出了GPT3.5, 但未对外公开.
  • 2022年1月Google提出思维链技术CoT (Chain of Thought)
  • 2022年11月30日, OpenAI正式发布chatGPT, 核心点是基于GPT3.5, 融合了Codex + 强化学习的技术.
  • 2023年3月, OpenAI正式发布GPT4, 增加了多模态能力.
  • 2024年2月, OpenAI正式发布Sora, 首次完成60s稳定, 流畅, 一致性的视频生成模型.
  • https://www.bilibili.com/video/BV17u4m1P7yM/?spm_id_from=333.788&vd_source=df7ff49c7ff2ca7e998b84c4369f1a59
  • 2024年5月, OpenAI正式发布GPT-4o, 流浪地球2的电影场景第一次进入现实.
  • https://www.bilibili.com/video/BV1pt421M7CG/?vd_source=df7ff49c7ff2ca7e998b84c4369f1a59

3.1 AI前端界面

AI前端界面¶

学习目标¶

  • 了解一个具备AI能力的简单前端界面.
  • 理解未来的前端, 后端工程师要具备AI开发的能力.
  • 这里是AI课程, 不是前端课程, 只作为一个引子, 展示给同学们一个具备AI能力的前端界面.
  • # 老人与海经典原文 But a man is not made for defeat. A man can be destroyed but not defeated.
  • 输入一段圣经中的原文:
  • You are the salt of the earth,you are the light of the world,will shine before humanity.
  • streamlit run ./main_translate.py

4.1 大模型时代的风起云涌

大模型时代的风起云涌¶

学习目标¶

  • 了解当前主流语言大模型的进展.
  • 了解当前主流多模态大模型的进展.
  • 了解当前主流AI搜索大模型的进展.

语言大模型¶

  • ⭕️基础大模型底层 --->>> LLM中间层 --->>> AIGC软件层

百度: 文心大模型¶

  • https://yiyan.baidu.com/

阿里巴巴: 千问大模型¶

  • https://tongyi.aliyun.com/qianwen

腾讯: 混元大模型¶

  • https://lke.cloud.tencent.com/

字节跳动: 云雀大模型¶

  • https://www.doubao.com/chat/

科大讯飞: 星火大模型¶

  • https://xinghuo.xfyun.cn/spark

智谱清言: ChatGLM大模型¶

  • https://open.bigmodel.cn/

Minimax: ABAB大模型¶

  • https://www.minimaxi.com/

阶跃星辰: Step大模型¶

  • https://yuewen.cn/chats/

深度求索: DeepSeek大模型¶

  • https://chat.deepseek.com/

月之暗面: Kimi大模型¶

  • https://kimi.moonshot.cn/

多模态大模型¶

GPT4¶

快手: 可灵¶

  • https://klingai.kuaishou.com/

字节跳动: 即梦¶

  • https://jimeng.jianying.com/ai-tool/home

美图: Whee¶

  • https://www.whee.com/

AI搜索¶

秘塔¶

  • https://metaso.cn/

小节总结¶

  • 宏观上了解了当前学术圈和产业圈的AI大模型最新进展.

5.1 AI生存法则

技术人员的AI生存法则¶

学习目标¶

  • 了解AI时代的新变化.
  • 理解AI时代的变革原因.
  • 理解AI时代的模式和开发框架.

AI时代生存法则¶

  • 搜索关键字的变化!
  • 随着时代的发展, 技术模式也在不断迁移.
  • 算力增长和AI效能:
  • AI大模型时代的开发模式
  • AI大模型时代的技术栈

如何做一个职业程序员?¶

  • 1: 开发环境
  • ⭕️Linux优先!!! Linux优先!!! Linux优先!!!
  • 2: 开发IDE
  • vim
  • VSCode
  • PyCharm
  • Jupyter Notebook
  • 3: 软件版本
  • anaconda
  • Pytorch 1.6, 2.0, 2.1, 2.2
  • transformers 3.6, 4.30, 4.32
  • AutoDL: GPU
  • https://www.autodl.com/
  • 魔搭: GPU
  • https://modelscope.cn/
  • 趋动云: GPU
  • https://www.virtaicloud.com/
  • 青云:
  • https://www.qingcloud.com/
  • https://www.coreshub.cn/

  • 提醒📢: ⭕️整个课程期间基本上每周都会提交一次作业.
    • 助教邮箱📮: wanghao5276@163.com
    • 小朱老师邮箱📮: 348811083@qq.com
    • 提交作业的截止时间, 在布置作业的时候会通知, 具体时间也会写在每次课堂讲义最下面.
    • 每次作业评分A, B, C, D, 对同学们最后期末打分很重要, 加油🆙
  • 问题1: 单词Strawberry中有几个字母r ?
    • 如何理解大模型的"幻觉"问题?
      • 通俗的讲, 就是一本正经的胡说八道.
  • 问题2: 2025年春节:1月28日(农历除夕,周二)至2月4日(农历正月初七, 周二)放假调休, 共8天。1月26日(周日),2月8日(周六)上班。请你计算真的假期, 请注意, 双休日本来就是属于打工牛马的假期,请一步步思考。
  • 作业1: 回去查查什么叫感知机? (传统机器学习的领域, 深度学习中最最基础的一个小概念)
  • 问题3: Hinton大神认识吗?
    • 2019年图灵奖
    • 2024年诺贝尔物理奖
    • 全世界第一个同时拿图灵奖 + 诺贝尔奖的大神!!!
    • 🍊1989年的反向传播算法!!!
      • 2012年AlexNet勇拿竞赛冠军🏆, 才把这个算法发扬光大!!!
      • 大牛: 很多显而易见的事情, 是当所有人都知道它显而易见了, 它才显而易见.
  • 问题4: 到底啥是多模态? (不再犹豫)
    • 语音
    • 语言
    • 图片
    • 视频
    • 上面两个以上的模态放在一起就是多模态.
      • 文生图
      • 看图说话
      • 图生视频
  • 问题5: 当前学术圈 + 工业界, AI的最前沿的几个方向?
    • GPT-o1: 复杂推理
    • 具身智能
    • 多模态
  • 问题6: 关于大模型时代的算力需求?
    • 国内最大的算力池: 字节跳动的火山引擎 --- 保守估计10万块.
    • 3090, 4090: 5000元 ~ 10000元
    • T4, V100: 2 ~ 3万人民币
    • A100, A800: 10万人民币
      • 2023年训练GPT-4模型, 大概用了5万块A100. (花了50亿)
      • 2023年春天, 2月份, 美团联合创始人. (出资5000万, 6月份悄悄的跑了)
    • H100, H800: 25万人民币
      • 未来GPT-5模型需要10万块H100. (250亿)
    • B200: 60万人民币
  • 问题7: 关于开发 + 学习环境?
    • 强烈建议在Linux环境下.
    • ⭕️利用工具: anaconda 创建同学们自己的虚拟环境 (作业)
      • 创建虚拟环境命令: conda create -n deeplearning python=3.10
      • 激活环境: conda activate deeplearning
      • 安装包: pip install torch, pip install transformers
  • 问题8: 大模型领域哪些需求大? 偏饱和?
    • 整个大模型都属于蓝海.......
    • 1: NLP, 搜广推 ✅
    • 2: 语音, 多模态 ❎
    • 3: CV, 强化学习 ❌

1 框架介绍与安装¶

  • 本章节主要带领大家学习使用深度学习框架 PyTorch:

PyTorch 介绍¶

  • 在2017年1月, Facebook的人工智能研究院 (FAIR) 向世界推出了PyTorch. 这个基于Torch的框架, 以其Python语言作为前端, 同时为深度学习研究者和开发者提供了两大核心优势:
  • 一是强大的GPU加速张量计算能力, 其并行计算能力在当时与NumPy相媲美.
  • 二是内置的自动微分系统, 使得构建深度神经网络变得更加直观和高效.
  • 2018年10月, 在NeurIPS 2018会议上, Facebook宣布了PyTorch 1.0的发布. 这个版本的推出, 标志着PyTorch在商业化进程中取得了重要进展.
  • 在2019年前, Tensorflow一直作为深度学习系统中的领头存在, 而以2019年为分界线, Pytorch异军突起, 逐渐成为了开发者和研究人员最为喜爱的框架. 随着Pytorch的不断普及和完善, 其生态也越发蓬勃.
  • 在AI领域, huggingface社区的开源的transformers库使用pytorch实现了市面上绝大多数开源的预训练模型.
  • 微软的分布式训练框架deepspeed也支持Pytorch, 由于Pytorch备受研究人员的青睐, 近年来绝大多数开源神经网络架构都采用Pytorch实现.

PyTorch 安装¶

  • https://github.com/pytorch/pytorch
  • 安装:
  • pip install torch==2.1.0
  • 通过本章节的学习, 同学们将会了解Pytorch的发展历史, 并掌握 PyTorch 深度学习框架的安装.

1 张量的创建¶

学习目标¶

  • 掌握张量创建
    PyTorch 是一个 Python 深度学习框架,它将数据封装成张量(Tensor)来进行运算。PyTorch 中的张量就是元素为同一种数据类型的多维矩阵。在 PyTorch 中,张量以 "类" 的形式封装起来,对张量的一些运算、处理的方法被封装在类中。

1. 基本创建方式¶

  • torch.tensor 根据指定数据创建张量
  • torch.Tensor 根据形状创建张量, 其也可用来创建指定数据的张量
  • torch.IntTensor、torch.FloatTensor、torch.DoubleTensor 创建指定类型的张量
import torch
import numpy as np
import random# 1. 根据已有数据创建张量
def test01():# 1. 创建张量标量data = torch.tensor(10)print(data)# 2. numpy 数组, 由于 data 为 float64, 下面代码也使用该类型data = np.random.randn(2, 3)data = torch.tensor(data)print(data)# 3. 列表, 下面代码使用默认元素类型 float32data = [[10., 20., 30.], [40., 50., 60.]]data = torch.tensor(data)print(data)# 2. 创建指定形状的张量
def test02():# 1. 创建2行3列的张量, 默认 dtype 为 float32data = torch.Tensor(2, 3)print(data)# 2. 注意: 如果传递列表, 则创建包含指定元素的张量data = torch.Tensor([10])print(data)data = torch.Tensor([10, 20])print(data)# 3. 使用具体类型的张量
def test03():# 1. 创建2行3列, dtype 为 int32 的张量data = torch.IntTensor(2, 3)print(data)# 2. 注意: 如果传递的元素类型不正确, 则会进行类型转换data = torch.IntTensor([2.5, 3.3])print(data)# 3. 其他的类型data = torch.ShortTensor()  # int16data = torch.LongTensor()   # int64data = torch.FloatTensor()  # float32data = torch.DoubleTensor() # float64if __name__ == '__main__':test02()

程序输出结果:

tensor(10)
tensor([[ 0.1345,  0.1149,  0.2435],[ 0.8026, -0.6744, -1.0918]], dtype=torch.float64)
tensor([[10., 20., 30.],[40., 50., 60.]])
tensor([[0.0000e+00, 3.6893e+19, 2.2018e+05],[4.6577e-10, 2.4158e-12, 1.1625e+33]])
tensor([10.])
tensor([10., 20.])
tensor([[         0, 1610612736, 1213662609],[ 805308409,  156041223,          1]], dtype=torch.int32)
tensor([2, 3], dtype=torch.int32)

2. 创建线性和随机张量¶

  • torch.arange 和 torch.linspace 创建线性张量
  • torch.random.init_seed 和 torch.random.manual_seed 随机种子设置
  • torch.randn 创建随机张量
import torch# 1. 创建线性空间的张量
def test01():# 1. 在指定区间按照步长生成元素 [start, end, step)data = torch.arange(0, 10, 2)print(data)# 2. 在指定区间按照元素个数生成data = torch.linspace(0, 11, 10)print(data)# 2. 创建随机张量
def test02():# 1. 创建随机张量data = torch.randn(2, 3)  # 创建2行3列张量print(data)# 2. 随机数种子设置print('随机数种子:', torch.random.initial_seed())torch.random.manual_seed(100)print('随机数种子:', torch.random.initial_seed())if __name__ == '__main__':test02()

程序输出结果:

tensor([0, 2, 4, 6, 8])
tensor([ 0.0000,  1.2222,  2.4444,  3.6667,  4.8889,  6.1111,  7.3333,  8.5556,9.7778, 11.0000])
tensor([[-0.5209, -0.2439, -1.1780],[ 0.8133,  1.1442,  0.6790]])
随机数种子: 4508475192273306739
随机数种子: 100

3. 创建01张量¶

  • torch.ones 和 torch.ones_like 创建全1张量
  • torch.zeros 和 torch.zeros_like 创建全0张量
  • torch.full 和 torch.full_like 创建全为指定值张量
import torch# 1. 创建全0张量
def test01():# 1. 创建指定形状全0张量data = torch.zeros(2, 3)print(data)# 2. 根据张量形状创建全0张量data = torch.zeros_like(data)print(data)# 2. 创建全1张量
def test02():# 1. 创建指定形状全0张量data = torch.ones(2, 3)print(data)# 2. 根据张量形状创建全0张量data = torch.ones_like(data)print(data)# 3. 创建全为指定值的张量
def test03():# 1. 创建指定形状指定值的张量data = torch.full([2, 3], 10)print(data)# 2. 根据张量形状创建指定值的张量data = torch.full_like(data, 20)print(data)if __name__ == '__main__':test01()test02()test03()

程序输出结果:

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

4. 张量元素类型转换¶

  • tensor.type(torch.DoubleTensor)
  • torch.double()
import torchdef test():data = torch.full([2, 3], 10)print(data.dtype)# 将 data 元素类型转换为 float64 类型# 1. 第一种方法data = data.type(torch.DoubleTensor)print(data.dtype)# 转换为其他类型# data = data.type(torch.ShortTensor)# data = data.type(torch.IntTensor)# data = data.type(torch.LongTensor)# data = data.type(torch.FloatTensor)# 2. 第二种方法data = data.double()print(data.dtype)# 转换为其他类型# data = data.short()# data = data.int()# data = data.long()# data = data.float()if __name__ == '__main__':test()

程序输出结果:

torch.int64
torch.float64
torch.float64

5. 小节¶

在本小节中,我们主要学习了以下内容:
1. 创建张量的方式1. torch.tensor 根据指定数据创建张量2. torch.Tensor 根据形状创建张量, 其也可用来创建指定数据的张量3. torch.IntTensor、torch.FloatTensor、torch.DoubleTensor 创建指定类型的张量
  • 创建线性和随机张量 - torch.arange 和 torch.linspace 创建线性张量
    • torch.random.init_seed 和 torch.random.manual_seed 随机种子设置
    • torch.randn 创建随机张量
  • 创建01张量 - torch.ones 和 torch.ones_like 创建全1张量
    • torch.zeros 和 torch.zeros_like 创建全0张量
    • torch.full 和 torch.full_like 创建全为指定值张量
  • 张量元素类型转换 - tensor.type(torch.DoubleTensor)
    • torch.double()

2 张量数值计算¶

学习目标¶

  • 掌握张量基本运算
  • 掌握阿达玛积、点积运算
  • 掌握PyTorch指定运算设备
    PyTorch 计算的数据都是以张量形式存在, 我们需要掌握张量各种运算. 并且, 我们可以在 CPU 中运算, 也可以在 GPU 中运算.

1. 张量基本运算¶

基本运算中,包括 add、sub、mul、div、neg 等函数, 以及这些函数的带下划线的版本 add_、sub_、mul_、div_、neg_,其中带下划线的版本为修改原数据。

import numpy as np
import torchdef test():data = torch.randint(0, 10, [2, 3])print(data)print('-' * 50)# 1. 不修改原数据new_data = data.add(10)  # 等价 new_data = data + 10print(new_data)print('-' * 50)# 2. 直接修改原数据# 注意: 带下划线的函数为修改原数据本身data.add_(10)  # 等价 data += 10print(data)# 3. 其他函数print(data.sub(100))print(data.mul(100))print(data.div(100))print(data.neg())if __name__ == '__main__':test()

程序输出结果:

tensor([[3, 7, 4],[0, 0, 6]])
--------------------------------------------------
tensor([[13, 17, 14],[10, 10, 16]])
--------------------------------------------------
tensor([[13, 17, 14],[10, 10, 16]])
tensor([[-87, -83, -86],[-90, -90, -84]])
tensor([[1300, 1700, 1400],[1000, 1000, 1600]])
tensor([[0.1300, 0.1700, 0.1400],[0.1000, 0.1000, 0.1600]])
tensor([[-13, -17, -14],[-10, -10, -16]])

2. 阿达玛积¶

阿达玛积指的是矩阵对应位置的元素相乘.

import numpy as np
import torchdef test():data1 = torch.tensor([[1, 2], [3, 4]])data2 = torch.tensor([[5, 6], [7, 8]])# 第一种方式data = torch.mul(data1, data2)print(data)print('-' * 50)# 第二种方式data = data1 * data2print(data)print('-' * 50)if __name__ == '__main__':test()

程序输出结果:

tensor([[ 5, 12],[21, 32]])
--------------------------------------------------
tensor([[ 5, 12],[21, 32]])
--------------------------------------------------

3. 点积运算¶

点积运算要求第一个矩阵 shape: (n, m),第二个矩阵 shape: (m, p), 两个矩阵点积运算 shape 为: (n, p)。
  • 运算符 @ 用于进行两个矩阵的点乘运算
  • torch.mm 用于进行两个矩阵点乘运算, 要求输入的矩阵为2维
  • torch.bmm 用于批量进行矩阵点乘运算, 要求输入的矩阵为3维
  • torch.matmul 对进行点乘运算的两矩阵形状没有限定. - 对于输入都是二维的张量相当于 mm 运算.
    • 对于输入都是三维的张量相当于 bmm 运算
    • 对数输入的 shape 不同的张量, 对应的最后几个维度必须符合矩阵运算规则
import numpy as np
import torch# 1. 点积运算
def test01():data1 = torch.tensor([[1, 2], [3, 4], [5, 6]])data2 = torch.tensor([[5, 6], [7, 8]])# 第一种方式data = data1 @ data2print(data)print('-' * 50)# 第二种方式data = torch.mm(data1, data2)print(data)print('-' * 50)# 第三种方式data = torch.matmul(data1, data2)print(data)print('-' * 50)# 2. torch.mm 和 torch.matmull 的区别
def test02():# matmul 可以两个维度可以不同# 第一个张量: (3, 4, 5)# 第二个张量: (5, 4)# torch.mm 不可以相乘,而 matmul 则可以相乘print(torch.matmul(torch.randn(3, 4, 5), torch.randn(5, 4)).shape)print(torch.matmul(torch.randn(5, 4), torch.randn(3, 4, 5)).shape)# 3. torch.mm 函数的用法
def test03():# 批量点积运算# 第一个维度为 batch_size# 矩阵的二三维要满足矩阵乘法规则data1 = torch.randn(3, 4, 5)data2 = torch.randn(3, 5, 8)data = torch.bmm(data1, data2)print(data.shape)if __name__ == '__main__':test01()test02()test03()

程序输出结果:

tensor([[19, 22],[43, 50],[67, 78]])
--------------------------------------------------
tensor([[19, 22],[43, 50],[67, 78]])
--------------------------------------------------
tensor([[19, 22],[43, 50],[67, 78]])
--------------------------------------------------
torch.Size([3, 4, 4])
torch.Size([3, 5, 5])
torch.Size([3, 4, 8])

4. 指定运算设备¶

PyTorch 默认会将张量创建在 CPU 控制的内存中, 即: 默认的运算设备为 CPU。我们也可以将张量创建在 GPU 上, 能够利用对于矩阵计算的优势加快模型训练。将张量移动到 GPU 上有两种方法:

  1. 使用 cuda 方法
  2. 直接在 GPU 上创建张量
  3. 使用 to 方法指定设备
import torch# 1. 使用 cuda 方法
def test01():data = torch.tensor([10, 20 ,30])print('存储设备:', data.device)# 如果安装的不是 gpu 版本的 PyTorch# 或电脑本身没有 NVIDIA 卡的计算环境# 下面代码可能会报错data = data.cuda()print('存储设备:', data.device)# 使用 cpu 函数将张量移动到 cpu 上data = data.cpu()print('存储设备:', data.device)# 输出结果:# 存储设备: cpu# 存储设备: cuda:0# 存储设备: cpu# 2. 直接将张量创建在 GPU 上
def test02():data = torch.tensor([10, 20, 30], device='cuda:0')print('存储设备:', data.device)# 使用 cpu 函数将张量移动到 cpu 上data = data.cpu()print('存储设备:', data.device)# 输出结果:# 存储设备: cuda:0# 存储设备: cpu# 3. 使用 to 方法
def test03():data = torch.tensor([10, 20, 30])print('存储设备:', data.device)data = data.to('cuda:0')print('存储设备:', data.device)# 输出结果:# 存储设备: cpu# 存储设备: cuda:0# 4. 存储在不同设备的张量不能运算
def test04():data1 = torch.tensor([10, 20, 30], device='cuda:0')data2 = torch.tensor([10, 20, 30])print(data1.device, data2.device)# RuntimeError: Expected all tensors to be on the same device,# but found at least two devices, cuda:0 and cpu!data = data1 + data2print(data)if __name__ == '__main__':test04()

程序输出结果:

存储设备: cpu
存储设备: cuda:0
存储设备: cpu
存储设备: cuda:0
存储设备: cpu
存储设备: cpu
存储设备: cuda:0
cuda:0 cpu

5. 小节¶

在本小节中,我们主要学习的主要内容如下:

  • 张量基本运算函数 add、sub、mul、div、neg 等函数, add_、sub_、mul_、div_、neg_ 等 inplace 函数
  • 张量的阿达玛积运算 mul 和运算符 * 的用法
  • 点积运算: - 运算符 @ 用于进行两个矩阵的点乘运算
    • torch.mm 用于进行两个矩阵点乘运算, 要求输入的矩阵为2维
    • torch.bmm 用于批量进行矩阵点乘运算, 要求输入的矩阵为3维
    • torch.matmul 对进行点乘运算的两矩阵形状没有限定. - 对于输入都是二维的张量相当于 mm 运算.
      • 对于输入都是三维的张量相当于 bmm 运算
      • 对数输入的 shape 不同的张量, 对应的最后几个维度必须符合矩阵运算规则
  • 将变量移动到 GPU 设备的方法,例如: cuda 方法、直接在 GPU 上创建张量、使用 to 方法指定设备

3 张量类型转换¶

学习目标¶

  • 掌握张量类型转换方法
    张量的类型转换也是经常使用的一种操作,是必须掌握的知识点。在本小节,我们主要学习如何将 numpy 数组和 PyTorch Tensor 的转化方法.

1. 张量转换为 numpy 数组¶

使用 Tensor.numpy 函数可以将张量转换为 ndarray 数组,但是共享内存,可以使用 copy 函数避免共享。

# 1. 将张量转换为 numpy 数组
def test01():data_tensor = torch.tensor([2, 3, 4])# 使用张量对象中的 numpy 函数进行转换data_numpy = data_tensor.numpy()print(type(data_tensor))print(type(data_numpy))# 注意: data_tensor 和 data_numpy 共享内存# 修改其中的一个,另外一个也会发生改变# data_tensor[0] = 100data_numpy[0] = 100print(data_tensor)print(data_numpy)if __name__ == '__main__':test01()

2. numpy 转换为张量¶

  • 使用 from_numpy 可以将 ndarray 数组转换为 Tensor,默认共享内存,使用 copy 函数避免共享。
  • 使用 torch.tensor 可以将 ndarray 数组转换为 Tensor,默认不共享内存。
# 1. 使用 from_numpy 函数
def test01():data_numpy = np.array([2, 3, 4])# 将 numpy 数组转换为张量类型# 1. from_numpy# 2. torch.tensor(ndarray)# 浅拷贝data_tensor = torch.from_numpy(data_numpy)# nunpy 和 tensor 共享内存# data_numpy[0] = 100data_tensor[0] = 100print(data_tensor)print(data_numpy)# 2. 使用 torch.tensor 函数
def test02():data_numpy = np.array([2, 3, 4])data_tensor = torch.tensor(data_numpy)# nunpy 和 tensor 不共享内存# data_numpy[0] = 100data_tensor[0] = 100print(data_tensor)print(data_numpy)if __name__ == '__main__':test01()test02()

3. 标量张量和数字的转换¶

对于只有一个元素的张量,使用 item 方法将该值从张量中提取出来。

# 3. 标量张量和数字的转换
def test03():# 当张量只包含一个元素时, 可以通过 item 函数提取出该值data = torch.tensor([30,])print(data.item())data = torch.tensor(30)print(data.item())if __name__ == '__main__':test03()

程序输出结果:

30
30

小节¶

在本小节中, 我们主要学习了 numpy 和 tensor 互相转换的规则, 以及标量张量与数值之间的转换规则。


4 张量拼接操作¶

学习目标¶

  • 掌握torch.cat torch.stack使用
    张量的拼接操作在神经网络搭建过程中是非常常用的方法,例如: 在后面将要学习到的残差网络、注意力机制中都使用到了张量拼接。

1. torch.cat 函数的使用¶

torch.cat 函数可以将两个张量根据指定的维度拼接起来.
import torchdef test():data1 = torch.randint(0, 10, [3, 5, 4])data2 = torch.randint(0, 10, [3, 5, 4])print(data1)print(data2)print('-' * 50)# 1. 按0维度拼接new_data = torch.cat([data1, data2], dim=0)print(new_data.shape)print('-' * 50)# 2. 按1维度拼接new_data = torch.cat([data1, data2], dim=1)print(new_data.shape)print('-' * 50)# 3. 按2维度拼接new_data = torch.cat([data1, data2], dim=2)print(new_data.shape)if __name__ == '__main__':test()

程序输出结果:

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

2. torch.stack 函数的使用¶

torch.stack 函数可以将两个张量根据指定的维度叠加起来.
import torchdef test():data1= torch.randint(0, 10, [2, 3])data2= torch.randint(0, 10, [2, 3])print(data1)print(data2)new_data = torch.stack([data1, data2], dim=0)print(new_data.shape)new_data = torch.stack([data1, data2], dim=1)print(new_data.shape)new_data = torch.stack([data1, data2], dim=2)print(new_data.shape)if __name__ == '__main__':test()

程序输出结果:

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

3. 小节¶

张量的拼接操作也是在后面我们经常使用一种操作。cat 函数可以将张量按照指定的维度拼接起来,stack 函数可以将张量按照指定的维度叠加起来。


5 张量索引操作¶

学习目标¶

  • 掌握张量不同索引操作
    我们在操作张量时,经常需要去进行获取或者修改操作,掌握张量的花式索引操作是必须的一项能力。

1. 简单行、列索引¶

准备数据

import torchdata = torch.randint(0, 10, [4, 5])
print(data)
print('-' * 50)

程序输出结果:

tensor([[0, 7, 6, 5, 9],[6, 8, 3, 1, 0],[6, 3, 8, 7, 3],[4, 9, 5, 3, 1]])
--------------------------------------------------
# 1. 简单行、列索引
def test01():print(data[0])print(data[:, 0])print('-' * 50)if __name__ == '__main__':test01()

程序输出结果:

tensor([0, 7, 6, 5, 9])
tensor([0, 6, 6, 4])
--------------------------------------------------

2. 列表索引¶

# 2. 列表索引
def test02():# 返回 (0, 1)、(1, 2) 两个位置的元素print(data[[0, 1], [1, 2]])print('-' * 50)# 返回 0、1 行的 1、2 列共4个元素print(data[[[0], [1]], [1, 2]])
if __name__ == '__main__':test02()

程序输出结果:

tensor([7, 3])
--------------------------------------------------
tensor([[7, 6],[8, 3]])

3. 范围索引¶

# 3. 范围索引
def test03():# 前3行的前2列数据print(data[:3, :2])# 第2行到最后的前2列数据print(data[2:, :2])
if __name__ == '__main__':test03()

程序输出结果:

tensor([[0, 7],[6, 8],[6, 3]])
tensor([[6, 3],[4, 9]])

4. 布尔索引¶

# 布尔索引
def test():# 第2列大于5的行数据print(data[data[:, 2] > 5])# 第1行大于5的列数据print(data[:, data[1] > 5])
if __name__ == '__main__':test04()

程序输出结果:

tensor([[0, 7, 6, 5, 9],[6, 3, 8, 7, 3]])
tensor([[0, 7],[6, 8],[6, 3],[4, 9]])

5. 多维索引¶

# 多维索引
def test05():data = torch.randint(0, 10, [3, 4, 5])print(data)print('-' * 50)print(data[0, :, :])print(data[:, 0, :])print(data[:, :, 0])if __name__ == '__main__':test05()

程序输出结果:

tensor([[[2, 4, 1, 2, 3],[5, 5, 1, 5, 0],[1, 4, 5, 3, 8],[7, 1, 1, 9, 9]],[[9, 7, 5, 3, 1],[8, 8, 6, 0, 1],[6, 9, 0, 2, 1],[9, 7, 0, 4, 0]],[[0, 7, 3, 5, 6],[2, 4, 6, 4, 3],[2, 0, 3, 7, 9],[9, 6, 4, 4, 4]]])
--------------------------------------------------
tensor([[2, 4, 1, 2, 3],[5, 5, 1, 5, 0],[1, 4, 5, 3, 8],[7, 1, 1, 9, 9]])
tensor([[2, 4, 1, 2, 3],[9, 7, 5, 3, 1],[0, 7, 3, 5, 6]])
tensor([[2, 5, 1, 7],[9, 8, 6, 9],[0, 2, 2, 9]])

6 张量形状操作¶

学习目标¶

  • 掌握reshape, transpose, permute, view, contigous, squeeze, unsqueeze等函数使用
    在我们后面搭建网络模型时,数据都是基于张量形式的表示,网络层与层之间很多都是以不同的 shape 的方式进行表现和运算,我们需要掌握对张量形状的操作,以便能够更好处理网络各层之间的数据连接。

1. reshape 函数的用法¶

reshape 函数可以在保证张量数据不变的前提下改变数据的维度,将其转换成指定的形状,在后面的神经网络学习时,会经常使用该函数来调节数据的形状,以适配不同网络层之间的数据传递。

import torch
import numpy as npdef test():data = torch.tensor([[10, 20, 30], [40, 50, 60]])# 1. 使用 shape 属性或者 size 方法都可以获得张量的形状print(data.shape, data.shape[0], data.shape[1])print(data.size(), data.size(0), data.size(1))# 2. 使用 reshape 函数修改张量形状new_data = data.reshape(1, 6)print(new_data.shape)if __name__ == '__main__':test()

程序运行结果:

torch.Size([2, 3]) 2 3
torch.Size([2, 3]) 2 3
torch.Size([1, 6])

2. transpose 和 permute 函数的使用¶

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

permute 函数可以一次交换更多的维度。

import torch
import numpy as npdef test():data = torch.tensor(np.random.randint(0, 10, [3, 4, 5]))print('data shape:', data.size())# 1. 交换1和2维度new_data = torch.transpose(data, 1, 2)print('data shape:', new_data.size())# 2. 将 data 的形状修改为 (4, 5, 3)new_data = torch.transpose(data, 0, 1)new_data = torch.transpose(new_data, 1, 2)print('new_data shape:', new_data.size())# 3. 使用 permute 函数将形状修改为 (4, 5, 3)new_data = torch.permute(data, [1, 2, 0])print('new_data shape:', new_data.size())if __name__ == '__main__':test()

程序运行结果:

data shape: torch.Size([3, 4, 5])
data shape: torch.Size([3, 5, 4])
new_data shape: torch.Size([4, 5, 3])
new_data shape: torch.Size([4, 5, 3])

3. view 和 contigous 函数的用法¶

view 函数也可以用于修改张量的形状,但是其用法比较局限,只能用于存储在整块内存中的张量。在 PyTorch 中,有些张量是由不同的数据块组成的,它们并没有存储在整块的内存中,view 函数无法对这样的张量进行变形处理,例如: 一个张量经过了 transpose 或者 permute 函数的处理之后,就无法使用 view 函数进行形状操作。

import torch
import numpy as npdef test():data = torch.tensor([[10, 20, 30], [40, 50, 60]])print('data shape:', data.size())# 1. 使用 view 函数修改形状new_data = data.view(3, 2)print('new_data shape:', new_data.shape)# 2. 判断张量是否使用整块内存print('data:', data.is_contiguous())  # True# 3. 使用 transpose 函数修改形状new_data = torch.transpose(data, 0, 1)print('new_data:', new_data.is_contiguous())  # False# new_data = new_data.view(2, 3)  # RuntimeError# 需要先使用 contiguous 函数转换为整块内存的张量,再使用 view 函数print(new_data.contiguous().is_contiguous())new_data = new_data.contiguous().view(2, 3)print('new_data shape:', new_data.shape)if __name__ == '__main__':test()

程序运行结果:

data shape: torch.Size([2, 3])
new_data shape: torch.Size([3, 2])
data: True
new_data: False
True
new_data shape: torch.Size([2, 3])

4. squeeze 和 unsqueeze 函数的用法¶

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

import torch
import numpy as npdef test():data = torch.tensor(np.random.randint(0, 10, [1, 3, 1, 5]))print('data shape:', data.size())# 1. 去掉值为1的维度new_data = data.squeeze()print('new_data shape:', new_data.size())  # torch.Size([3, 5])# 2. 去掉指定位置为1的维度,注意: 如果指定位置不是1则不删除new_data = data.squeeze(2)print('new_data shape:', new_data.size())  # torch.Size([3, 5])# 3. 在2维度增加一个维度new_data = data.unsqueeze(-1)print('new_data shape:', new_data.size())  # torch.Size([3, 1, 5, 1])if __name__ == '__main__':test()

程序运行结果:

data shape: torch.Size([1, 3, 1, 5])
new_data shape: torch.Size([3, 5])
new_data shape: torch.Size([1, 3, 5])
new_data shape: torch.Size([1, 3, 1, 5, 1])

5. 小节¶

本小节带着同学们学习了经常使用的关于张量形状的操作,我们用到的主要函数有:

  • reshape 函数可以在保证张量数据不变的前提下改变数据的维度.
  • transpose 函数可以实现交换张量形状的指定维度, permute 可以一次交换更多的维度.
  • view 函数也可以用于修改张量的形状, 但是它要求被转换的张量内存必须连续,所以一般配合 contiguous 函数使用.
  • squeeze 和 unsqueeze 函数可以用来增加或者减少维度.

7 张量运算函数¶

学习目标¶

  • 掌握张量相关运算函数

1. 常见运算函数¶

PyTorch 为每个张量封装很多实用的计算函数,例如计算均值、平方根、求和等等

import torchdef test():data = torch.randint(0, 10, [2, 3], dtype=torch.float64)print(data)print('-' * 50)# 1. 计算均值# 注意: tensor 必须为 Float 或者 Double 类型print(data.mean())print(data.mean(dim=0))  # 按列计算均值print(data.mean(dim=1))  # 按行计算均值print('-' * 50)# 2. 计算总和print(data.sum())print(data.sum(dim=0))print(data.sum(dim=1))print('-' * 50)# 3. 计算平方print(data.pow(2))print('-' * 50)# 4. 计算平方根print(data.sqrt())print('-' * 50)# 5. 指数计算, e^n 次方print(data.exp())print('-' * 50)# 6. 对数计算print(data.log())  # 以 e 为底print(data.log2())print(data.log10())if __name__ == '__main__':test()

程序运行结果:

tensor([[4., 0., 7.],[6., 3., 5.]], dtype=torch.float64)
--------------------------------------------------
tensor(4.1667, dtype=torch.float64)
tensor([5.0000, 1.5000, 6.0000], dtype=torch.float64)
tensor([3.6667, 4.6667], dtype=torch.float64)
--------------------------------------------------
tensor(25., dtype=torch.float64)
tensor([10.,  3., 12.], dtype=torch.float64)
tensor([11., 14.], dtype=torch.float64)
--------------------------------------------------
tensor([[16.,  0., 49.],[36.,  9., 25.]], dtype=torch.float64)
--------------------------------------------------
tensor([[2.0000, 0.0000, 2.6458],[2.4495, 1.7321, 2.2361]], dtype=torch.float64)
--------------------------------------------------
tensor([[5.4598e+01, 1.0000e+00, 1.0966e+03],[4.0343e+02, 2.0086e+01, 1.4841e+02]], dtype=torch.float64)
--------------------------------------------------
tensor([[1.3863,   -inf, 1.9459],[1.7918, 1.0986, 1.6094]], dtype=torch.float64)
tensor([[2.0000,   -inf, 2.8074],[2.5850, 1.5850, 2.3219]], dtype=torch.float64)
tensor([[0.6021,   -inf, 0.8451],[0.7782, 0.4771, 0.6990]], dtype=torch.float64)

8 自动微分模块¶

学习目标¶

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

1. 梯度基本计算¶

我们使用 backward 方法、grad 属性来实现梯度的计算和访问.

import torch# 1. 单标量梯度的计算
# y = x**2 + 20
def test01():# 定义需要求导的张量# 张量的值类型必须是浮点类型x = torch.tensor(10, requires_grad=True, dtype=torch.float64)# 变量经过中间运算f = x ** 2 + 20# 自动微分f.backward()# 打印 x 变量的梯度# backward 函数计算的梯度值会存储在张量的 grad 变量中print(x.grad)# 2. 单向量梯度的计算
# y = x**2 + 20
def test02():# 定义需要求导张量x = torch.tensor([10, 20, 30, 40], requires_grad=True, dtype=torch.float64)# 变量经过中间计算f1 = x ** 2 + 20# 注意:# 由于求导的结果必须是标量# 而 f 的结果是: tensor([120., 420.])# 所以, 不能直接自动微分# 需要将结果计算为标量才能进行计算f2 = f1.mean()  # f2 = 1/2 * x# 自动微分f2.backward()# 打印 x 变量的梯度print(x.grad)if __name__ == '__main__':test01()

程序运行结果:

tensor(20., dtype=torch.float64)
tensor([ 5., 10., 15., 20.], dtype=torch.float64)

2. 控制梯度计算¶

我们可以通过一些方法使得在 requires_grad=True 的张量在某些时候计算不进行梯度计算。

import torch# 1. 控制不计算梯度
def test01():x = torch.tensor(10, requires_grad=True, dtype=torch.float64)print(x.requires_grad)# 第一种方式: 对代码进行装饰with torch.no_grad():y = x ** 2print(y.requires_grad)# 第二种方式: 对函数进行装饰@torch.no_grad()def my_func(x):return x ** 2print(my_func(x).requires_grad)# 第三种方式torch.set_grad_enabled(False)y = x ** 2print(y.requires_grad)# 2. 注意: 累计梯度
def test02():# 定义需要求导张量x = torch.tensor([10, 20, 30, 40], requires_grad=True, dtype=torch.float64)for _ in range(3):f1 = x ** 2 + 20f2 = f1.mean()# 默认张量的 grad 属性会累计历史梯度值# 所以, 需要我们每次手动清理上次的梯度# 注意: 一开始梯度不存在, 需要做判断if x.grad is not None:x.grad.data.zero_()f2.backward()print(x.grad)# 3. 梯度下降优化最优解
def test03():# y = x**2x = torch.tensor(10, requires_grad=True, dtype=torch.float64)for _ in range(5000):# 正向计算f = x ** 2# 梯度清零if x.grad is not None:x.grad.data.zero_()# 反向传播计算梯度f.backward()# 更新参数x.data = x.data - 0.001 * x.gradprint('%.10f' % x.data)if __name__ == '__main__':test01()print('--------------------')test02()print('--------------------')test03()

程序运行结果:

True
False
False
False
tensor([ 5., 10., 15., 20.], dtype=torch.float64)
tensor([ 5., 10., 15., 20.], dtype=torch.float64)
tensor([ 5., 10., 15., 20.], dtype=torch.float64)

3. 梯度计算注意¶

当对设置 requires_grad=True 的张量使用 numpy 函数进行转换时, 会出现如下报错:
Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.
此时, 需要先使用 detach 函数将张量进行分离, 再使用 numpy 函数.
注意: detach 之后会产生一个新的张量, 新的张量作为叶子结点,并且该张量和原来的张量共享数据, 但是分离后的张量不需要计算梯度。

import torch# 1. detach 函数用法
def test01():x = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)# Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.# print(x.numpy())  # 错误print(x.detach().numpy())  # 正确# 2. detach 前后张量共享内存
def test02():x1 = torch.tensor([10, 20], requires_grad=True, dtype=torch.float64)# x2 作为叶子结点x2 = x1.detach()# 两个张量的值一样: 140421811165776 140421811165776print(id(x1.data), id(x2.data))x2.data = torch.tensor([100, 200])print(x1)print(x2)# x2 不会自动计算梯度: Falseprint(x2.requires_grad)if __name__ == '__main__':test01()test02()

程序运行结果:

10. 20.]
140495634222288 140495634222288
tensor([10., 20.], dtype=torch.float64, requires_grad=True)
tensor([100, 200])
False

4. 小节¶

本小节主要讲解了 PyTorch 中非常重要的自动微分模块的使用和理解。我们对需要计算梯度的张量需要设置 requires_grad=True 属性,并且需要注意的是梯度是累计的,在每次计算梯度前需要先进行梯度清零。


10 模型的保存加载¶

学习目标¶

  • 掌握PyTorch保存模型的方法
  • 神经网络的训练有时需要几天, 几周, 甚至几个月, 为了在每次使用模型时避免高代价的重复训练, 我们就需要将模型序列化到磁盘中, 使用的时候反序列化到内存中.

1: 保存模型参数¶

import torch
import torch.nn as nn# 假设我们有一个模型
class SimpleModel(nn.Module):def __init__(self):super(SimpleModel, self).__init__()self.fc = nn.Linear(10, 1)def forward(self, x):return self.fc(x)model = SimpleModel()# 保存模型的参数
torch.save(model.state_dict(), 'model_weights.pth')

2: 保存全部模型¶

import torch
import torch.nn as nn# 假设我们有一个模型
class SimpleModel(nn.Module):def __init__(self):super(SimpleModel, self).__init__()self.fc = nn.Linear(10, 1)def forward(self, x):return self.fc(x)model = SimpleModel()# 保存全部模型
torch.save(model, 'model.pth')

3: 加载模型参数¶

# 创建一个与保存时相同结构的模型
model = SimpleModel()# 加载模型的参数
model.load_state_dict(torch.load('model_weights.pth'))
print(model)

4: 加载全部模型¶

model = torch.load('model.pth')
print(model)
  • 注意📢:
  • 模型结构: 如果你只保存了模型的参数, 那么在加载时需要确保你有与保存时相同的模型结构.
  • 设备兼容性: 如果你在一个设备上保存了模型(例如GPU), 而在另一个设备上加载(例如CPU), 你可能需要使用 map_location 参数来指定设备.
  • device = torch.device('cpu') model.load_state_dict(torch.load('model_weights.pth', map_location=device))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/946969.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

漏洞生命周期管理:从发现到防护的全流程方案 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

day02 pytorch介绍与安装

1 框架介绍与安装本章节主要带领大家学习使用深度学习框架 PyTorch:PyTorch 介绍在2017年1月, Facebook的人工智能研究院 (FAIR) 向世界推出了PyTorch. 这个基于Torch的框架, 以其Python语言作为前端, 同时为深度学习研…

Xshell7免费版下载及安装(详细教程)

Xshell7免费版下载及安装(详细教程)Xshell7免费版下载及安装(详细教程) https://www.xshell.com/zh/free-for-home-school/ xhsell免费版本下载地址

APT36组织利用Linux BOSS恶意软件通过.desktop文件攻击印度政府

网络安全研究人员发现APT36组织使用伪造成PDF文件的恶意Linux桌面文件,针对印度政府系统进行网络间谍活动。该攻击通过钓鱼邮件传播,利用BOSS Linux系统的漏洞窃取数据并维持持久访问权限。APT36组织利用Linux BOSS恶…

Sqlite EF CodeFirst For WPF

Sqlite EF在WPF 开发中使用Sqlite 数据库的EF框架 1.安装必要的插件install-package System.Data.Sqliteinstall-package System.Data.Sqlite.EF6install-package Sqlite.CodeFirst2.建立数据模型 using System; using…

大模型强化学习的熵控制:CE-GPPO、EPO与AsyPPO技术方案对比详解

LLM的强化学习训练最近进展很快,SOTA模型在各种推理benchmark上的表现确实亮眼。但更值得关注的其实是另一条信息——从Rutgers到Alibaba再到HKUST,这些研究团队正在攻克的是RL领域的一个老大难:怎么控制好熵,同时…

拼多多一面

1、你们是使用redis去记录一下是否同步成功,那么如果在这里面redis写挂了怎么办 答:如果只是因为网络波动导致一瞬间没有数据的话,可以使用重试机制,如果是因为redis的集群宕机的话,可以使用redis的哨兵机制,同时…

10.20-10.25 总结

10.20-10.25 总结 10.20 杂题 最近的 CF 和 AT 的题目,写了三道题目。主要的启发是对于一些最优化的 dp 要多发掘性质或者是最后答案的形态,还有一些题目可以分块或者是看成一块一块的观察。 10.21 比赛 不常规的四道…

就是 CCPC2025 重庆站游记

。懂不懂什么叫超长前摇。 10.26 终于过审核了,非常感谢重庆大学的李佳老师!!

25秋周总结6

总结 这周只考了两次,剩下时间都是自习。然后这两次考联考和 NOIP 模拟,我考得都很炸,大概总结就是这段时间有点飘、有点浮躁,看着题感觉简单于是就觉得随便考没问题的。但是两次都存在遇到简单题但是没注意到性质…

20232313 2025-2026-1 《网络与系统攻防技术》实验三实验报告 - 20232313

1.实验内容基本实验内容如下:学会使用msf编码器,veil-evasion,自己利用shellcode编程等免杀工具或技巧 正确使用msf编码器,使用msfvenom生成如jar之类的其他文件 veil,加壳工具 使用C + shellcode编程 通过组合应…

鸭子类型,反射

什么是鸭子类型鸭子模型(Duck Typing)是编程语言类型检查中的一种设计思想,核心原则是:“如果一个东西走路像鸭子,叫起来像鸭子,那么它就是鸭子”。(是一种编程语言风格,不是一个真实存在的约束关系,而是一种普…

Verilog学习-从FPGA的角度看Uart模块

想从零移植Uboot到FPGA上,但现有的小麻雀内核栈空间是使用FPGA内部的资源,它的内存十分有限,完全无法存放Uboot代码本体,故需要添加SDRAM控制器来调用其FPGA片内的SDRAM或者外部连接的SPI NorFlash,但是改动这些东…

朝花夕拾 -- AES(1)

初识AESAES(1) 零、 前言 ​ 朝花夕拾杯中酒。从CTF开始攻击CBC模式下的加密漏洞,再到第四学期的《密码学基础》课程,时至今日,《密码工程》课程的需要以及自己对于对称密码的兴趣驱使,下定决心写下这篇笔记…

【学习笔记】构造

本文记载了一些关于构造题的学习笔记。

特殊的背包问题

特殊的背包问题 设 \(n\) 为物品个数,\(m\) 为背包容量,\(k\) 为所有物品中重量最大值。 1. 最优化问题 当 \(m\) 较大时可以应用下面的解法。先贪心,然后扔掉一些,再补上一些。 1.1 完全背包 1 先找出性价比最高的…

2025 年 10 月承烧板厂家最新推荐,实力品牌深度解析采购无忧之选!

2025 年 10 月承烧板厂家最新推荐,实力品牌深度解析采购无忧之选!引言承烧板采购中,品牌实力是品质的核心保障,也是规避采购风险的关键。据中国耐火材料行业协会 2025 年 10 月发布的《承烧板采购风险报告》显示,…

【URP】Unity[视差贴图]模拟[冰面裂缝]实践

Unity URP 冰面裂缝视差效果实现方案 冰面裂缝效果优化的URP Shader实现。该方案通过‌视差遮挡贴图(POM)‌技术增强深度表现,结合‌高度图动态控制‌实现可调节的冰缝裂痕效果。 核心特【从UnityURP开始探索游戏渲染…

2025年热门的用地预审技术服务供应商、市面上用地预审技术服务公司、行业内用地预审技术服务品牌、市场用地预审技术服务方案、2025年用地预审技术服务单位深度解析

摘要 用地预审技术服务行业随着国家土地管理政策的收紧和基础设施建设加速而蓬勃发展,2025年预计市场规模将增长15%以上,驱动因素包括城镇化进程和生态保护需求。本排名基于市场调研、用户反馈和专家评估,为用地预审…

2025年热门的用地预审技术服务供应商、市面上用地预审技术服务公司、行业内用地预审技术服务品牌、市场用地预审技术服务方案、2025年用地预审技术服务单位综合排名与分析

文章摘要 用地预审技术服务行业在国土空间规划优化和基础设施建设加速的背景下快速发展,2025年预计市场规模将增长15%以上。本文基于行业数据和用户反馈,深度评测热门供应商,并提供权威排名榜单,其中陕西丰耘甲信息…