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

《Day2-PyTorch Tensor 从入门到实践:核心操作与避坑指南》

一、Tensor的创建

在Torch中张量以 "类" 的形式封装起来,对张量的一些运算、处理的方法被封装在类中,官方文档:

torch — PyTorch 2.7 documentation

1. 基本创建方式

以下讲的创建tensor的函数中有两个有默认值的参数dtype和device, 分别代表数据类型和计算设备,可以通过属性dtype和device获取。

1.1 torch.tensor

注意这里的tensor是小写,该API是根据指定的数据创建张量。

import torch
import numpy as npdef test01():device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# tensor数据类型根据输入的数据类型自动判断# dtype:指定数据类型# device:指定计算设备t = torch.tensor([1, 2, 3], device=device, dtype=torch.float)print(t)print(t.dtype)print(t.device)# 通过numpy创建t1 = torch.tensor(np.array([1, 2, 3, 4]))print(t1)# 通过标量创建t2 = torch.tensor(5)print(t2)if __name__ == '__main__':test01()

注:如果出现如下错误:

UserWarning: Failed to initialize NumPy: _ARRAY_API not found

一般是因为numpy和pytorch版本不兼容,可以降低numpy版本,步骤如下:

1.anaconda prompt中切换虚拟环境:

        conda activate 虚拟环境名称

2.卸载numpy:

        pip uninstall numpy

3.安装低版本的numpy:

        pip install numpy==1.26.0

1.2 torch.Tensor

注意这里的Tensor是大写,该API根据形状创建张量,其也可用来创建指定数据的张量。

import torch
import numpy as npdef test01():device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# tensor数据类型根据输入的数据类型自动判断# dtype:指定数据类型# device:指定计算设备t = torch.tensor([1, 2, 3], device=device, dtype=torch.float)print(t)print(t.dtype)print(t.device)# 通过numpy创建t1 = torch.tensor(np.array([1, 2, 3, 4]))print(t1)# 通过标量创建t2 = torch.tensor(5)print(t2)def test02():# 不支持数据类型dtype属性# 不支持device属性# 指定形状创建t =torch.Tensor(2, 3)print(t)print(t.dtype)print(t.device)# 通过数组创建t1 = torch.Tensor([1, 2, 3])print(t1)# 3. 使用linspace创建等差序列张量# 创建从1到10(包含10)的10个等间隔元素组成的张量t2 = torch.linspace(1, 10, 10)print(t2)if __name__ == '__main__':# test01()test02()

torch.Tensor与torch.tensor区别

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

1.3 torch.IntTensor

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

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

import torch
​
def test003():# 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)
​
​
if __name__ == "__main__":test003()
 

2. 创建线性和随机张量

在 PyTorch 中,可以轻松创建线性张量和随机张量。

2.1 创建线性张量

使用torch.arange 和 torch.linspace 创建线性张量:

import torch
import numpy as np
​
# 不用科学计数法打印
torch.set_printoptions(sci_mode=False)
​
​
def test004():# 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)​
if __name__ == "__main__":test004()
 

2.2 随机张量

使用torch.randn 创建随机张量。

2.2.1 随机数种子

随机数种子(Random Seed)是一个用于初始化随机数生成器的数值。随机数生成器是一种算法,用于生成一个看似随机的数列,但如果使用相同的种子进行初始化,生成器将产生相同的数列。

2.2.2 随机张量

在 PyTorch 中,种子影响所有与随机性相关的操作,包括张量的随机初始化、数据的随机打乱、模型的参数初始化等。通过设置随机数种子,可以做到模型训练和实验结果在不同的运行中进行复现。

import torch
import numpy as npdef test03():# 随机数种子:每次运行生成随机数相同torch.manual_seed(0)# 随机生成符合标准正态分布的数,均值-0,方差-1t = torch.randn(2, 3)print(t)# 生成随机整数# start# end# sizet = torch.randint(0, 10, (2, 3))print(t)# shape和size():表示张量的形状print(t.shape)print(t.size())# 生成0-1之间的随机数# size:形状t = torch.rand(2, 3)print(t)
注:不设置随机种子时,每次打印的结果不一样。

五、Tensor常见属性

张量有device、dtype、shape等常见属性,知道这些属性对我们认识Tensor很有帮助。

1. 获取属性

掌握代码调试就是掌握了一切~import torch
​
​
def test001():data = torch.tensor([1, 2, 3])print(data.dtype, data.device, data.shape)
​
​
if __name__ == "__main__":test001()

2. 切换设备

import torchdef test04():# 设备切换方法演示:CPU与GPU之间的张量迁移# 1. 首先判断当前环境是否有可用的CUDA(GPU)#    若有则使用GPU设备,否则使用CPU设备device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# 方法1:创建张量时,通过device参数显式指定设备# 直接在创建张量时将其分配到指定设备(GPU优先,无则CPU)t = torch.tensor([1, 2, 3], device=device)print(t)  # 打印张量,可观察设备信息(如cuda:0或cpu)# 方法2:使用to()方法切换设备# 先创建一个默认在CPU上的张量t1 = torch.tensor([1, 2, 3])# 通过to(device)将张量迁移到目标设备(与上面的device一致)t1 = t1.to(device)print(t1)  # 此时t1已迁移到指定设备# 方法3:使用cuda()方法直接迁移到GPU(若可用)# 创建默认在CPU上的张量t2 = torch.tensor([1, 2, 3])# 使用cuda()方法将张量迁移到GPU(若GPU不可用会报错)t2 = t2.cuda()print(t2)  # 若有GPU,此时t2在GPU上# 方法3补充:使用cpu()方法迁移到CPU# 将GPU上的t2迁移回CPUt3 = t2.cpu()print(t3)  # 此时t3在CPU上

六、Tensor数据转换

import numpy as np
import torchdef test01():# 演示:PyTorch张量(tensor)转换为NumPy数组的两种方式(浅拷贝与深拷贝)# 创建一个PyTorch张量(1维张量,元素为[1,2,3])t = torch.tensor([1, 2, 3])print(t)  # 打印原始张量# 方法1:使用numpy()方法将张量转为NumPy数组# 注意:这是浅拷贝(共享内存),修改数组会同步影响原张量a = t.numpy()print(a)  # 打印转换后的NumPy数组# 修改NumPy数组的第一个元素a[0] = 100# 查看原张量是否被影响(由于浅拷贝,张量的值会同步改变)print(t)  # 输出 tensor([100,   2,   3])# 方法2:使用numpy().copy()进行深拷贝# 深拷贝会创建独立副本,修改副本不会影响原张量b = t.numpy().copy()# 修改深拷贝得到的数组b[0] = 200# 查看原张量是否被影响(深拷贝不会影响,张量保持之前的值)print(t)  # 输出 tensor([100,   2,   3])# 演示:NumPy数组转换为PyTorch张量的两种方式
def test02():# 创建一个NumPy数组(元素为[1,2,3])a = np.array([1, 2, 3])print(a)  # 打印原始NumPy数组# 方法1:使用torch.from_numpy(a)将NumPy数组转为张量# 注意:这是浅拷贝(共享内存),修改张量会同步影响原数组t = torch.from_numpy(a)print(t)  # 打印转换后的张量# 修改张量的第一个元素t[0] = 10# 查看原NumPy数组是否被影响(浅拷贝会同步改变)print(a)  # 输出 [10  2  3]# 方法2:使用torch.tensor(a)将NumPy数组转为张量# 这是深拷贝(创建独立副本),修改张量不会影响原数组t1 = torch.tensor(a)# 修改深拷贝得到的张量t1[0] = 100# 查看原NumPy数组是否被影响(深拷贝不会影响,数组保持之前的值)print(a)  # 输出 [10  2  3]if __name__ == '__main__':# 若取消注释则执行test01(张量转NumPy)# test01()# 执行test02(NumPy转张量)test02()

注释核心说明:

  1. 深浅拷贝区别:

    • 浅拷贝(tensor.numpy()torch.from_numpy()):共享内存,一方修改会同步影响另一方
    • 深拷贝(tensor.numpy().copy()torch.tensor(numpy数组)):创建独立副本,修改互不影响
  2. 转换方向:

    • 张量→NumPy:tensor.numpy()(浅)、tensor.numpy().copy()(深)
    • NumPy→张量:torch.from_numpy()(浅)、torch.tensor()(深)
  3. print作用:通过输出结果直观展示修改操作对原数据的影响,验证深浅拷贝特性

七、Tensor常见操作

在深度学习中,Tensor是一种多维数组,用于存储和操作数据,我们需要掌握张量各种运算。

import torchdef test01():# 演示item()方法:获取单个元素张量的值# 适用场景:无论张量维度如何,只要内部只有一个元素,均可使用item()提取其Python标量值# 创建0维张量(单个元素)t = torch.tensor(10)print(t.item())  # 输出:10(提取单个元素值)# 创建2维张量(形状为[1,1],仍只有一个元素)t1 = torch.tensor([[10]])print(t1.item())  # 输出:10(即使是高维单元素张量,也能提取值)def test02():# 演示PyTorch中运算方法的两种形式:# 1. 不带下划线的方法(如add):返回新张量,不修改原张量# 2. 带下划线的方法(如add_):原地修改原张量,返回修改后的自身# 创建初始张量t = torch.tensor(10)# 使用add():返回新张量(原张量t不变)t1 = t.add(1)  # 等价于 t + 1print(t1)  # 输出:tensor(11)(新张量)print(t)   # 输出:tensor(10)(原张量未修改)# 使用add_():原地修改原张量print(t.add_(2))  # 输出:tensor(12)(修改后的t)print(t)          # 输出:tensor(12)(原张量已被修改)def test03():# 演示阿达码积(元素-wise乘法)# 前提:两个张量必须形状相同# 运算规则:对应位置的元素直接相乘(C[i][j] = A[i][j] * B[i][j])# 可用运算符:mul()方法 或 * 符号# 创建两个形状相同的2D张量t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])t2 = torch.tensor([[1, 2, 3], [4, 5, 6]])# 计算阿达码积(两种等价方式)# t3 = t1.mul(t2)  # 使用mul()方法t3 = t1 * t2       # 使用*运算符print(t3)  # 输出:[[1, 4, 9], [16, 25, 36]](对应元素相乘结果)def test04():# 演示矩阵乘法(线性代数中的矩阵乘积)# 前提:第一个张量形状为(m×n),第二个为(n×p),即前一个的列数=后一个的行数# 运算规则:第一个张量的行与第二个张量的列对应元素相乘后求和,结果为(m×p)形状# 可用运算符:matmul()方法 或 @ 符号# 创建两个符合矩阵乘法维度要求的张量t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])  # 形状:2×3t2 = torch.tensor([[1, 1], [2, 2], [3, 3]])  # 形状:3×2# 计算矩阵乘法(两种等价方式)# t3 = t1 @ t2       # 使用@运算符t3 = t1.matmul(t2)  # 使用matmul()方法print(t3)  # 输出:[[14, 14], [32, 32]](矩阵乘积结果,形状2×2)def test05():# 演示view()方法:修改张量形状(重塑)# 前提:1. 张量在内存中必须是连续的(is_contiguous()返回True);2. 重塑前后总元素数必须相同# 连续性:数据在内存中按C顺序存储(通常新建张量都是连续的,转置等操作可能破坏连续性)# -1作为占位符:自动计算该维度的大小(需保证总元素数不变)# 创建2×3的连续张量t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])print(t1.is_contiguous())  # 输出:True(新建张量默认连续)# 交换维度(0和1维度交换,形状变为3×2)t2 = t1.transpose(1, 0)  # 等价于t1.T(转置)print(t2)  # 输出:[[1, 4], [2, 5], [3, 6]]print(t2.is_contiguous())  # 输出:False(转置后张量不连续)# 尝试用view()重塑不连续张量(可能报错,视PyTorch版本而定)# 注意:实际运行时可能因版本优化不报错,但不建议对不连续张量使用view()t3 = t2.view(2, 3)print(t3)  # 输出:[[1, 4, 2], [5, 3, 6]](内存顺序未变,重塑后值可能不符合预期)def test06():# 演示维度交换方法:# 1. transpose(dim1, dim2):一次只能交换两个维度# 2. permute(dims):可同时交换任意多个维度(需指定新的维度顺序)# 创建3×4×5的3D随机整数张量(值范围1-9)t1 = torch.randint(1, 10, (3, 4, 5))print(t1.size())  # 输出:torch.Size([3, 4, 5])(原维度:[0,1,2])# 使用transpose交换维度1和0(原维度[0,1,2] → [1,0,2])t2 = torch.transpose(t1, 1, 0)print(t2.size())  # 输出:torch.Size([4, 3, 5])(交换后维度)# 使用permute同时交换多个维度(原维度[0,1,2] → [1,2,0])t3 = torch.permute(t1, (1, 2, 0))print(t3.size())  # 输出:torch.Size([4, 5, 3])(新维度顺序)def test07():# 演示维度调整方法:# 1. squeeze(dim):删除尺寸为1的维度(默认删除所有尺寸为1的维度)# 2. unsqueeze(dim):在指定位置添加一个尺寸为1的维度# 创建形状为(1, 3, 1)的3D张量(含两个尺寸为1的维度)t1 = torch.randint(1, 10, (1, 3, 1))# 不指定dim:删除所有尺寸为1的维度(1×3×1 → 3)t2 = torch.squeeze(t1)print(t2.size())  # 输出:torch.Size([3])# 指定dim=0:仅删除第0维(尺寸为1)(1×3×1 → 3×1)t3 = torch.squeeze(t1, dim=0)print(t3.size())  # 输出:torch.Size([3, 1])# 指定dim=1:第1维尺寸为3(非1),不做操作(保持原形状)t4 = torch.squeeze(t1, dim=1)print(t4.size())  # 输出:torch.Size([1, 3, 1])# 在dim=0位置添加新维度(1×3×1 → 1×1×3×1)t5 = torch.unsqueeze(t1, dim=0)print(t5.size())  # 输出:torch.Size([1, 1, 3, 1])def test08():# 演示广播机制(Broadcasting):# 当两个张量形状不同时,PyTorch会自动扩展维度使它们兼容,以便进行元素-wise运算# 规则:从最后一个维度开始匹配,维度要么相同,要么其中一个为1,要么其中一个不存在# 创建1D张量(形状[3])和2D张量(形状[3,1])data1d = torch.tensor([1, 2, 3])data2d = torch.tensor([[4], [2], [3]])print(data1d.shape, data2d.shape)  # 输出:torch.Size([3]) torch.Size([3, 1])# 广播机制自动扩展:# data1d扩展为[3,3](复制行),data2d扩展为[3,3](复制列),再相加print(data1d + data2d)  # 输出:[[5,6,7], [3,4,5], [4,5,6]]def test09():# 演示高维张量的广播机制# 创建2D张量(形状[2,3])和3D张量(形状[2,1,3])a = torch.tensor([[1, 2, 3], [4, 5, 6]])  # 2×3b = torch.tensor([[[2, 3, 4]], [[5, 6, 7]]])  # 2×1×3print(a.shape, b.shape)  # 输出:torch.Size([2, 3]) torch.Size([2, 1, 3])# 广播机制:# a自动扩展为[2,1,3](添加中间维度),与b形状匹配后相加result = a + bprint(result, result.shape)  # 输出结果形状:torch.Size([2, 1, 3])if __name__ == '__main__':# 取消对应注释可运行不同测试函数# test01()  # 测试item()方法# test02()  # 测试原地/非原地运算# test03()  # 测试阿达码积# test04()  # 测试矩阵乘法# test05()  # 测试view()重塑# test06()  # 测试维度交换# test07()  # 测试维度调整(squeeze/unsqueeze)# test08()  # 测试广播机制(低维)test09()   # 测试广播机制(高维)

八、总结

一、核心知识点梳理:构建 Tensor 知识体系

1. Tensor 的创建:从基础到灵活运用

Tensor 的创建是入门第一步,需重点掌握不同方法的适用场景:

  • 基础创建方法

    • torch.tensor(data):推荐优先使用,支持自动推断数据类型(如整数默认 int64,浮点数默认 float32),可显式指定dtypedevice(CPU/GPU),输入为 NumPy 数组时默认深拷贝。
    • torch.Tensor(shape):大写开头,更适合按形状创建未初始化张量(值为内存随机值),默认数据类型为 float32,不支持直接指定device,灵活性低于torch.tensor
    • 类型专属创建:如torch.IntTensor(整数型)、torch.FloatTensor(浮点型)等,适合需要固定数据类型的场景,但需注意类型不匹配时的自动转换可能导致数据丢失。
  • 特殊张量创建

    • 线性张量:torch.arange(start, end, step)(按步长生成序列)、torch.linspace(start, end, num)(按元素个数生成等差序列),常用于生成索引或固定范围的测试数据。
    • 随机张量:torch.randn(shape)(标准正态分布)、torch.randint(low, high, shape)(整数随机数)、torch.rand(shape)(0-1 均匀分布),配合torch.manual_seed(seed)可固定随机数,保证实验可复现。

2. 张量属性:理解张量的 "身份信息"

张量的属性是操作的基础,需熟练掌握 3 个核心属性:

  • dtype:数据类型(如torch.float32torch.int64),决定计算精度和内存占用,需根据场景选择(如深度学习常用 float32,整数索引用 int64)。
  • device:计算设备(cpucuda:0),决定张量存储和计算的硬件,需通过torch.device('cuda' if torch.cuda.is_available() else 'cpu')自动适配环境。
  • shape/size():张量的维度信息(如(2,3)表示 2 行 3 列),是后续形状修改、运算的前提。

3. 设备切换:打通 CPU 与 GPU 的计算链路

深度学习中需频繁在 CPU 和 GPU 间迁移张量,3 种核心方法:

  • 创建时指定:torch.tensor(data, device=device),直接在目标设备初始化张量,避免后续迁移开销。
  • to(device):通用方法,支持动态切换到任意设备(如tensor.to('cuda')tensor.to(device)),推荐优先使用。
  • 快捷方法:tensor.cuda()(迁移到 GPU)、tensor.cpu()(迁移到 CPU),但需注意cuda()在无 GPU 环境下会报错,不如to()灵活。

4. 数据转换:Tensor 与 NumPy 的 "双向奔赴"

PyTorch 与 NumPy 的交互是数据预处理的高频操作,需区分深浅拷贝:

  • Tensor 转 NumPy
    • tensor.numpy():浅拷贝,共享内存(修改一方会同步影响另一方),适合临时转换且不修改数据的场景。
    • tensor.numpy().copy():深拷贝,创建独立副本,修改互不影响,适合需要独立操作的场景。
  • NumPy 转 Tensor
    • torch.from_numpy(numpy_arr):浅拷贝,共享内存,适合快速转换且需保持数据同步的场景。
    • torch.tensor(numpy_arr):深拷贝,创建独立副本,推荐用于需要独立操作张量的场景(如避免原始数据被意外修改)。

5. 核心操作:从基础运算到维度调整

张量的操作是构建计算逻辑的核心,需重点掌握以下几类:

  • 单元素提取tensor.item(),用于从单元素张量(无论维度)中提取 Python 标量(如损失值的提取)。
  • 运算类型
    • 元素 - wise 运算(阿达码积):*mul(),要求两张量形状相同,对应位置元素直接相乘。
    • 矩阵乘法:@matmul(),要求前张量列数 = 后张量行数,结果为线性代数中的矩阵乘积。
    • 原地 / 非原地运算:不带下划线的方法(如add())返回新张量,带下划线的方法(如add_())原地修改原张量(节省内存但会覆盖原始数据)。
  • 形状与维度操作
    • 形状修改:view(shape),要求张量连续(is_contiguous()为 True)且总元素数不变,-1可自动计算维度大小(如(2,3)(3,-1)得到(3,2))。
    • 维度交换:transpose(dim1, dim2)(交换两个维度)、permute(dims)(交换任意多个维度,如(3,4,5)(4,5,3)),常用于调整数据的维度顺序(如图像数据的(H,W,C)(C,H,W))。
    • 维度调整:squeeze(dim)(删除尺寸为 1 的维度)、unsqueeze(dim)(添加尺寸为 1 的维度),常用于匹配运算中的维度要求(如给标量添加批次维度)。
  • 广播机制:当两张量形状不同时,PyTorch 会自动扩展维度使其兼容(规则:从最后一维开始匹配,维度需相同、其中一个为 1 或不存在),简化不同形状张量的元素 - wise 运算(如(3,)(3,1)相加时自动扩展为(3,3))。

二、学习重点与避坑点:这些细节决定熟练度

  1. torch.tensor vs torch.Tensor:前者更灵活(支持devicedtype),后者默认 float32 且不支持设备指定,实际开发中优先用torch.tensor
  2. 深浅拷贝的影响:浅拷贝(numpy()/from_numpy())共享内存,修改时需谨慎(尤其在数据预处理 pipeline 中);深拷贝(copy()/torch.tensor())虽独立但内存开销更大,按需选择。
  3. 张量连续性:转置(transpose)等操作会导致张量不连续,此时使用view()可能报错或得到异常结果,可先用contiguous()转为连续张量(如tensor.transpose(0,1).contiguous().view(shape))。
  4. 随机种子的作用torch.manual_seed(seed)可固定随机数生成,是复现实验结果的关键(如模型初始化、数据打乱),务必在代码开头设置。
  5. 广播机制的边界:广播虽方便,但过度依赖可能导致维度匹配混乱,建议运算前先用shape确认张量维度,避免隐式扩展带来的错误。

三、实践建议:从 "看懂" 到 "会用"

  1. 边学边练,聚焦调试:Tensor 的很多细节(如设备、数据类型)需通过调试发现,推荐用print(tensor.dtype, tensor.device, tensor.shape)打印属性,结合 IDE 断点观察张量变化。
  2. 针对性练习
    • 基础操作:用不同方法创建相同形状的张量,对比数据类型和内存占用。
    • 设备迁移:在有 GPU 的环境下测试to()/cuda()/cpu()的效果,观察张量位置变化。
    • 运算练习:用相同数据分别做元素 - wise 乘法和矩阵乘法,对比结果差异。
  3. 结合实际场景:在数据预处理(如将图像 NumPy 数组转为 Tensor 并迁移到 GPU)、模型推理(如调整输入张量维度匹配模型要求)中强化应用,将知识点与实际任务绑定。

总结

Tensor 是 PyTorch 的 "基石",其操作的熟练度直接影响代码效率和正确性。学习时需从「创建 - 属性 - 转换 - 操作」逐步深入,重点关注细节(如数据类型、设备、拷贝方式),通过大量实践将 API 的使用内化为直觉。掌握 Tensor 后,无论是搭建模型还是调试训练过程,都会更加得心应手。

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

相关文章:

  • jmm 指令重排 缓存可见性 Volatile 内存屏障
  • 数据中心白牌服务器市场规模与发展趋势分析报告-路亿市场策略
  • 丝杆升降机的螺母磨损到什么程度需要更换?有无预警或检测方法?
  • Orange的运维学习日记--31.Linux防火墙深度详解
  • LVS-DR模式高性能负载均衡实战
  • PLC学习之路-定时器-(三)
  • Fabric.js从入门学习到实现labelImg矩形多边形标注工具【上】
  • 论文学习19:Multi-view Aggregation Network for Dichotomous Image Segmentation
  • STM32江科大学习笔记,全功能按键非阻塞式实现,按键点击,双击,长按
  • 思途AOP学习笔记 0806
  • 网安学习no.22
  • Zookeeper集群在Kubernetes上的高可用部署方案
  • 什么是VR全景图?VR全景图有什么优势?
  • vite项目中集成vditor文档编辑器
  • 金融风控实战:Spring Boot + LightGBM 贷款预测模型服务化(超详细版)
  • 多链钱包开发指南:MPC无助记词方案+60+公链支持
  • 问题定位排查手记1 | 从Windows端快速检查连接状态
  • STM32的PWR
  • 阿里云polardb-x 2.0迁移至华为云taurusdb
  • VSCode:基础使用 / 使用积累
  • react16 umi3 快速刷新配置
  • 从技术角度看React和Vue:性能、生态与开发体验对比
  • 猎板视角下的 PCB 翘曲:成因、检测、工艺优化及解决措施热点解析
  • C++ Primer Plus 14.4.10 模板别名
  • 下载 | Windows Server 2019最新原版ISO映像!(集成7月更新、标准版、数据中心版、17763.7558)
  • ref存储对象和reactive深度响应式递归地对对象的嵌套属性进行响应式处理
  • 纯血鸿蒙(HarmonyOS NEXT)应用开发完全指南
  • Baumer相机如何通过YoloV8深度学习模型实现农作物水稻病虫害的检测识别(C#代码UI界面版)
  • 机器学习----随机森林(Random Forest)详解
  • MonoFusion 与 Genie 3