Pytorch深度学习指南 卷I --编程基础(A Beginner‘s Guide) 第1章 一个简单的回归
本章正式开始使用pytorch的接口来实现对应的numpy的学习的过程,来学习模型的实现,我们会介绍numpy是如何学习的,以及我们如何一步步的通过torch的接口来实现简单化的过程,优雅的展示我们的代码,已经我们的代码完成的事情
numpy的线性回归
在此之前,先看看现在的numpy实现的学习的过程是什么样的
#引入计算模块
import numpy as np
from sklearn.linear_model import LinearRegressionimport torch
import torch.optim as optim
import torch.nn as nn
from torchviz import make_dot用真实的数据来生成对应的分布点的数据
true_b = 1
true_w = 2
N = 100# Data Generation
np.random.seed(42)
x = np.random.rand(N, 1)
epsilon = (.1 * np.random.randn(N, 1))
y = true_b + true_w * x + epsilon
np.rand# Shuffles the indices
idx = np.arange(N)
np.random.shuffle(idx)# Uses first 80 random indices for train
train_idx = idx[:int(N*.8)]
# Uses the remaining indices for validation
val_idx = idx[int(N*.8):]# Generates train and validation sets
x_train, y_train = x[train_idx], y[train_idx]
x_val, y_val = x[val_idx], y[val_idx]np.random.seed(42)
b = np.random.randn(1)
w = np.random.randn(1)for _ in range(1000):# Step 1 - Computes our model's predicted output - forward passyhat = b + w * x_train# Step 2 - Computing the loss# We are using ALL data points, so this is BATCH gradient# descent. How wrong is our model? That's the error!error = (yhat - y_train)# It is a regression, so it computes mean squared error (MSE)loss = (error ** 2).mean()# Step 3 - Computes gradients for both "b" and "w" parametersb_grad = 2 * error.mean()w_grad = 2 * (x_train * error).mean()# Sets learning rate - this is "eta" ~ the "n" like Greek letterlr = 0.1# Step 4 - Updates parameters using gradients and # the learning rateb = b - lr * b_gradw = w - lr * w_grad#验证,通过线性的模型直接学习
linr = LinearRegression()
linr.fit(x_train, y_train)
如上一章所说,我们的5个步骤,就是准备数据,前向传递,计算损失,计算梯度,更新参数,循环往复
pytorch的取代
张量(通常指3维)但是这里除了标量全部都是张量,为了简化。
#如下是创建张量的例子
scalar = torch.tensor(3.14159) #张量
vector = torch.tensor([1, 2, 3]) #一维
matrix = torch.ones((2, 3), dtype=torch.float) #二维
tensor = torch.randn((2, 3, 4), dtype=torch.float) #三维
获取到张量的shape
shape将会是我们以后将会长期用到的东西
print(tensor.size(), tensor.shape)
torch.Size([2, 3, 4]) torch.Size([2, 3, 4])
view
我们可以使用view的接口来改变一个张量的shape,注意view并不会创建新的张量。
# We get a tensor with a different shape but it still is the SAME tensor
same_matrix = matrix.view(1, 6)
# If we change one of its elements...
same_matrix[0, 1] = 2.
创建新的tensor
使用这个可以使用new_tensor和clone
# We can use "new_tensor" method to REALLY copy it into a new one
different_matrix = matrix.new_tensor(matrix.view(1, 6))
# Now, if we change one of its elements...
different_matrix[0, 1] = 3.
使用clone.detach,为什么要用detach(涉及到后面的数据存放和计算的内容)
another_matrix = matrix.view(1, 6).clone().detach()
加载数据、设备、CUDA
我们需要从numpy的数据转成tensor张量
x_train_tensor = torch.as_tensor(x_train)
x_train.dtype, x_train_tensor.dtype
注意,这里变成了torch的张量,但是这里是还是共享的原始的内存,换句话说,改了还是会一起改
(dtype('float64'), torch.float64)
cuda的数据
cuda就是要使用GPU来存储和运算的数据,我们需要手动的将其放到GPU的内存中,用于加速计算的过程
#判断是否有GPU的数据可以使用的接口,如果存在那么设置device为GPU,否则CPU
device = 'cuda' if torch.cuda.is_available() else 'cpu'
#可以获取GPU的数量
n_cudas = torch.cudsa.device_count()
for i in range(n_cuda):print(torch.cuda.get_device_naem(i))
我的机器上的输出的结果
NVIDIA GeForce RTX 2060
将数据发送到GPU上
gpu_tensor = torch.as_tensor(x_train).to(device)
gpu_tensor[0]
输出
torch.cuda.FloatTensor
如果发送到了GPU上的数据,需要重新变成numpy的数组,需要使用CPU的变量
back_to_numpy = x_train_tensor.cpu().numpy()
创建参数,并且需要梯度计算
为什么要使用torch,很多的时候在于可以自行进行梯度计算,也可以使用到很多pytorch的使用的接口和用法
# 创建一个随机1以内的参数,并且需要梯度,类型是float
b = torch.randn(1, requires_grad=True, dtype=torch.float)
w = torch.randn(1, requires_grad=True, dtype=torch.float)
print(b, w)
创建数据并且发送到GPU,但是需要注意的是,这样会丢失梯度,因为这个是CPU的数据需要梯度,发送到GPU后又是新的数据,
b = torch.randn(1, requires_grad=True, dtype=torch.float).to(device)
w = torch.randn(1, requires_grad=True, dtype=torch.float).to(device)
好的方法是直接在GPU上创建变量
b = torch.randn(1, requires_grad=True, dtype=torch.float,device = device)
w = torch.randn(1, requires_grad=True, dtype=torch.float),device = device)
Autograd
自动求解梯度
backward
我们可以通过backward直接计算和进行backward的实现,注意b,w是我们创建的参数(需要梯度的那种)
# Step 1 - Computes our model's predicted output - forward pass
yhat = b + w * x_train_tensor# Step 2 - Computes the loss
# We are using ALL data points, so this is BATCH gradient descent
# How wrong is our model? That's the error!
error = (yhat - y_train_tensor)
# It is a regression, so it computes mean squared error (MSE)
loss = (error ** 2).mean()# Step 3 - Computes gradients for both "b" and "w" parameters
# No more manual computation of gradients!
# b_grad = 2 * error.mean()
# w_grad = 2 * (x_tensor * error).mean()
loss.backward()
需要说明的是,所有的参与到b,w的计算的都是需要梯度的参数,例如这里面的yhat,error,loss,都是通过w,b的计算得来的,我们都认为是传递了梯度的计算特性
需要特别注意的是,这里的梯度是累计的,因为为了后续的小批量的情况,所以每次更新完毕以后需要手动设置gard_zero_()函数
b.grad.zero_(), w.grad.zero_()
还需要特别注意的是,我们更新参数的时候,是不能直接更新的,需要使用
with torch.no_grad():b -= lr * b.gradw -= lr * w.grad
这在停一下,除了前面的变量的配置不一样的地方,我们这里已经在改造我们的numpy代码了
# 原来的numpy的梯度的计算需要手动计算# Step 3 - Computes gradients for both "b" and "w" parametersb_grad = 2 * error.mean()w_grad = 2 * (x_train * error).mean()#但是这里已经可以使用自动计算的方法loss.backward()#可以直接读取当前的梯度的值b.gradw.grad
动态计算图
可以使用动态计算图,直接看到当前的所有的梯度的变量的相互之间的关系,这里大家可以自己看,我就不放出来了
优化器
我们之前都要手动的执行backward,然后获取b,w的grad,然后手动的进行更新使用了learning rate,最后还需要zero_grad。我们可以通过优化器的方式将变量一开始就加入到优化器中
optimizer = optim.SGD([b,w],lr = lr)# ....执行学习的步骤loss.backward()optimizer.step()#一次性更新所有的参数的变量optimizer.zero_grad()#一次性zero所有的变量的值
损失函数
实际上,我们的损失函数也有torch的封装,可以直接使用已经配置好的损失函数
loss_fn = nn.MSELoss(reduction = ‘mean’)
损失函数直接得到我们的yhat的结果和y_lable之间的损失的值
#原文中的损失函数的部分error = (yhat - y_train_tensor)loss = (error**2).mean()#取代后loss_fn = nn.MSELoss(reduction='mean')loss = loss_fn(y_hat,y_train_tensor)此时的loss计算出来的结果和之前的是一模一样的
需要注意的是,如果此时需要回归的numpy,需要执行detach()操作,表示Loss函数不再参与grad的计算
模型
我们已经有了优化器(用于更新参数),损失函数(用于生成损失值),我们还可以定义自己的module模型(显然吗,我们还需要构建很多的我们自己的东西)
我们使用model函数来用现有的模型针对输入得到我们的输出函数,model函数对比forward函数,还会 前向和反向的钩子函数
我们声明一个继承与Module的自己的类
class ManualLinearRegression(nn.Module):def __init__(self):super().__init__()# To make "b" and "w" real parameters of the model,# we need to wrap them with nn.Parameterself.b = nn.Parameter(torch.randn(1,requires_grad=True, dtype=torch.float))self.w = nn.Parameter(torch.randn(1, requires_grad=True,dtype=torch.float))def forward(self, x):# Computes the outputs / predictionsreturn self.b + self.w * x
通过parameters的函数,我们可以得到一个module类的目前包含的参数
dummpy = ManualLinearRegression()
list(dummy.parameters)
[Parameter containing:tensor([0.3367], requires_grad=True), Parameter containing:tensor([0.1288], requires_grad=True)]
也可以state_dict来获取所有的参数的当前值,和parameters的区别在于state_dict通常用于加载和保存模型,而前面的通常用于展示优化器的包含的变量
注意,数据和模型需要在同一个设备
dummy = ManualLinearRegression().to(device)
阶段代码
经过我们的使用自己的类以后的代码可以优化如下
# Greek letter
lr = 0.1# Step 0 - Initializes parameters "b" and "w" randomly
torch.manual_seed(42)
# Now we can create a model and send it at once to the device
model = ManualLinearRegression().to(device)# Defines a SGD optimizer to update the parameters
# (now retrieved directly from the model)
optimizer = optim.SGD(model.parameters(), lr=lr)# Defines a MSE loss function
loss_fn = nn.MSELoss(reduction='mean')# Defines number of epochs
n_epochs = 1000for epoch in range(n_epochs):model.train() # What is this?!?# Step 1 - Computes model's predicted output - forward pass# No more manual prediction,直接使yhat = model(x_train_tensor)# 一定注意这里使用的是model而不是forward# Step 2 - Computes the lossloss = loss_fn(yhat, y_train_tensor)# Step 3 - Computes gradients for both "b" and "w" parametersloss.backward()# Step 4 - Updates parameters using gradients and# the learning rateoptimizer.step()optimizer.zero_grad()# We can also inspect its parameters using its state_dict
print(model.state_dict())
model.train()
这个是配置了训练模式,训练模式可以有很多内容,例如我们常见的dropout的优化模式来减少过拟合的问题
嵌套模型
我们可以使用了已经有的模型来作为嵌套的模型
首先我们使用nn自带的Linear来取代我们手写的线性的Module,如下是一个具有一个权重w,和一个bias的线性模型,我们完全可以用这个来取代我们之前的手写的类
linear = nn.Linear(1,1)
当然我们可以嵌套这个到我们自己的类,这个和之前的基本上是完全等价的
class MyLinearRegression(nn.Module):def __init__(self):super().__init__()# Instead of our custom parameters, we use a Linear model# with single input and single outputself.linear = nn.Linear(1, 1)def forward(self, x):# Now it only takes a callself.linear(x)
序列模型
一个好的深度学习的模型,显然不只有一层,通常都会有很多隐藏层,将所有的封装子在一起,我们可以认为是一个序列模型
# Building the model from the figure above
model = nn.Sequential(nn.Linear(3, 5), nn.Linear(5, 1)).to(device)model.state_dict()
注意这里创建了一个序列类,序列类里面有两层,第一层是一个35的输出,第二层是一个51的模型,或者我们可以通过添加层的方式来增加带名字的层
# Building the model from the figure above
model = nn.Sequential()
model.add_module('layer1', nn.Linear(3, 5))
model.add_module('layer2', nn.Linear(5, 1))
model.to(device)
这里其实已经涉及到了深度学习的部分,pytorch的层只是很多例如
卷积层、池化层、填充层、非线性激活层、归一化层、循环层、transformer层、线性层、丢弃层、稀疏层、视觉层、数据平移(多GPU),展平层
相关文章:
Pytorch深度学习指南 卷I --编程基础(A Beginner‘s Guide) 第1章 一个简单的回归
本章正式开始使用pytorch的接口来实现对应的numpy的学习的过程,来学习模型的实现,我们会介绍numpy是如何学习的,以及我们如何一步步的通过torch的接口来实现简单化的过程,优雅的展示我们的代码,已经我们的代码完成的事…...
【EXCEL_VBA_实战】多工作薄合并深入理解
工作背景:多个工作薄存在冲突的名称,需快速合并 困难点:工作表移动复制时,若有冲突的名称,会不断弹出对话框待人工确认 思路:利用代码确认弹出的对话框 关键代码:Application.DisplayAlerts …...
mysql之表的外键约束
MySQL表的外键约束详细介绍及代码示例 外键约束是数据库中用于维护数据完整性和一致性的重要机制。它确保一个表中的数据与另一个表中的数据相关联,防止无效的数据引用。本文将详细介绍了外键约束的各个方面,并通过具体的代码示例进行演示。 1. 外键约束…...

Tuning the Go HTTP Client Settings
记录一次Go HTTP Client TIME_WAIT的优化 业务流程 分析 通过容器监控发现服务到事件总线的负载均衡之间有大量的短链接,回看一下代码 发送请求的代码 func SendToKEvent(ev *KEvent) error {data, err : json.Marshal(ev.Data)if err ! nil {return err}log.Pri…...
第二十四课 Vue中子组件调用父组件数据
Vue中子组件调用父组件数据 Vue是不建议在不同的组件直接传递值的,我们需要使用props方法来进行组件间的值传递 子组件调用父组件数据 父模板的数据,子组件是无法直接调用的 无法直接调用 1)组件调用顶级对象中的data <div class&quo…...
Jenkins-pipeline语法说明
一. 简述: Jenkins Pipeline 是一种持续集成和持续交付(CI/CD)工具,它允许用户通过代码定义构建、测试和部署流程。 二. 关于jenkinsfile: 1. Sections部分: Pipeline里的Sections通常包含一个或多个Direc…...

小米Vela操作系统开源:AIoT时代的全新引擎
小米近日正式开源了其物联网嵌入式软件平台——Vela操作系统,并将其命名为OpenVela。这一举动在AIoT(人工智能物联网)领域掀起了不小的波澜,也为开发者们提供了一个强大的AI代码生成器和开发平台。OpenVela项目源代码已托管至GitH…...
NodeJs如何做API接口单元测试? --【elpis全栈项目】
NodeJs API接口单元测试 api单元测试需要用到的 assert:断言库 (还要一些断言库比如:Chai)supertest: 模拟http请求 简单的例子: const express require(express); const supertest require(supertest); const assert require(assert);…...
bundletool来特定设备规范的json安装aab包
1、获取自己设备的设备规范json java -jar ./bundletool.jar get-device-spec --outputj:/device-spec.json 2、根据设备规范生成apks包 java -jar ./bundletool.jar build-apks --device-specj:/device-spec.json --bundleapp-dev-release.aab --output随便的文件名.apks -…...

2024年第十五届蓝桥杯青少组国赛(c++)真题—快速分解质因数
快速分解质因数 完整题目和在线测评可点击下方链接前往: 快速分解质因数_C_少儿编程题库学习中心-嗨信奥https://www.hixinao.com/tiku/cpp/show-3781.htmlhttps://www.hixinao.com/tiku/cpp/show-3781.html 若如其他赛事真题可自行前往题库中心查找,题…...

.Net Core微服务入门全纪录(四)——Ocelot-API网关(上)
系列文章目录 1、.Net Core微服务入门系列(一)——项目搭建 2、.Net Core微服务入门全纪录(二)——Consul-服务注册与发现(上) 3、.Net Core微服务入门全纪录(三)——Consul-服务注…...

chrome游览器JSON Formatter插件无效问题排查,FastJsonHttpMessageConverter导致Content-Type返回不正确
问题描述 chrome游览器又一款JSON插件叫JSON Formatter,游览器GET请求调用接口时,如果返回的数据是json格式,则会自动格式化展示,类似这样: 但是今天突然发现怎么也格式化不了,打开一个json文件倒是可以格…...

[Qt]系统相关-网络编程-TCP、UDP、HTTP协议
目录 前言 一、UDP网络编程 1.Qt项目文件 2.UDP类 QUdpSocket QNetworkDatagram 3.UDP回显服务器案例 细节 服务器设计 客户端设计 二、TCP网络编程 1.TCP类 QTcpServer QTcpSocket 2.TCP回显服务器案例 细节 服务器设计 客户端设计 三、HTTP客户端 1.HTTP…...

docker 安装 nginx 详解
在平常的开发工作中,我们经常会用到 nginx,那么在 docker 中 如何安装 nginx呢?又有哪些需要注意的事项呢?简单来说,第一步:拉取 nginx 镜像;第二步:创建 挂载目录并设置 nginx.conf…...

2025年大模型气象预测架构与商业化影响
随着人工智能技术,尤其是大模型(如深度学习、大规模神经网络)的飞速发展,气象预测的传统方法正在经历深刻变革。2025年,气象预测将借助大模型技术进入一个新的阶段。本文将从架构角度详细探讨2025年大模型在气象预测中的应用,并分析其对商业化的潜在影响。 一、2025年大模…...

基于51单片机和ESP8266(01S)、八位数码管、独立按键的WiFi定时器时钟
目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、延时函数2、定时器03、串口4、数码管扫描5、独立按键扫描 四、主函数总结 系列文章目录 前言 有三个版本: ①普中开发板版本1:28800bps11.0592MHz,12T ②普中开发板版本2&am…...
Androidstudio 中,project下的.gitignore和module下的.gitignore有什么区别,生效优先级是什么
在 Android Studio 项目中,project 根目录下的 .gitignore 文件和 module 目录下的 .gitignore 文件作用和生效优先级是不同的,理解它们之间的区别非常重要,可以避免不必要的提交和冲突。 1. project 根目录下的 .gitignore: 作…...

python学习笔记3-字符串常用的方法
一、判断(9个): 二、查找和替换(8个) 三、⼤⼩写转换(5个) 四、⽂本对⻬(3个) 五、去除空⽩字符(3个) 六、拆分和连接 (6个࿰…...

提示词工程(Prompt Engineering)
1. Prompt 是什么? Prompt:提示词,是描述 AI 需要执行的任务的自然语言文本。 如上图所示,Prompt就是用户的提问。其实我们大家都用过Prompt,比如我们使用的ChatGPT、文心一言、豆包等AI产品时的提问就是Prompt&…...

后端开发Web
Maven Maven是apache旗下的一个开源项目,是一款用于管理和构建java项目的工具 Maven的作用 依赖管理 方便快捷的管理项目依赖的资源(jar包),避免版本冲突问题 统一项目结构 提供标准、统一的项目结构 项目构建 标准跨平台(…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...