深度学习-张量相关

一. 张量的创建

张量简介

张量是pytorch的基本数据结构

张量,英文为Tensor,是机器学习的基本构建模块,是以数字方式表示数据的形式。

例如,图像可以表示为形状为 [3, 224, 224] 的张量,这意味着 [colour_channels, height, width] ,因为图像具有 3 颜色通道(红色、绿色、蓝色),高度为 224 像素,宽度为 224 像素。

在张量语言(用于描述张量的语言)中,张量将具有三个维度,一个维度表示 colour_channelsheightwidth

张量的基本创建

根据数据创建tensor

默认64

# 1. 使用torch.tensor根据数据创建张量
# 1.1. 创建标量
data = torch.tensor(10)
print(data)
​
# 1.2. 创建numpy数组
data = np.random.randn(3, 4)
data = torch.tensor(data)
print(data)
​
# 1.3. 创建张量
data = torch.tensor([[1, 2], [3, 4]])
print(data)

根据形状/数据创建Tensor

默认32

# 2.使用torch.Tensor根据形状/数据创建张量
# 2.1. 创建两行三列张量, 默认dtype为float32
data = torch.Tensor(2, 3)
print(data)
​
# 2.2. 如果传递列表, 则创建包含指定元素的张量
data = torch.Tensor([10])
print(data)
​
data = torch.Tensor([1, 4])
print(data)

指定类型张量

# 3. torch.IntTensor(), torch.FloatTensor(), torch.DoubleTensor()创建指定类型的张量
# 3.1. 创建2行3列, dtype 为 int32 的张量
data = torch.IntTensor(2, 3)
print(data)
​
# 3.2. 注意: 如果传递的元素类型不正确, 则会进行类型转换
data = torch.IntTensor([2.5, 3.3])
print(data)
​
# 3.3. 其他的类型
data = torch.ShortTensor()      # int16
print(data)
data = torch.LongTensor()       # int64
print(data)
data = torch.FloatTensor()      # float32
print(data)
data = torch.DoubleTensor()     # float64
print(data)

线性张量与随机张量

  1. torch.arange 和 torch.linspace 创建线性张量

  2. torch.random.init_seed 和 torch.random.manual_seed 随机种子设置

  3. torch.randn 创建随机张量

线性张量

torch.arange()
# 1.1 arange() 左闭右开
data = torch.arange(0, 11, 2)
print(data)
torch.linspace()
# 1.2 linspace() 左闭右闭
data = torch.linspace(0, 10, 5)
print(data)
区别

arange(start, end, step): 起始, 截至, 步长(每步走多少, 左闭右开)

linspace(start, end, steps): 起始, 截止, 步数(走几步, 左闭右闭)

随机张量

  1. torch.random.initial_seed()查看随机种子

  2. torch.random.manual_seed() 设置随机数种子

  3. torch.randn() 创建随机张量

创建随机张量

# 2.1 创建随机张量
data = torch.randn(2, 3)  # 2行3列
print(data)
​
# 2.2 查看随机种子
print(torch.random.initial_seed())      # 查看默认种子, 机器码
​
# 2.3 创建随机种子
torch.random.manual_seed(1)    # 设置随机种子
data = torch.randn(2, 3)    # 随机张量
print(data)
print(torch.random.initial_seed())

创建指定值张量

  1. torch.ones 和 torch.ones_like(像什么形状) 创建全1张量

  2. torch.zeros 和 torch.zeros_like 创建全0张量

  3. torch.full([行数, 列数], 指定值) 和 torch.full_like 创建指定值张量

创建全0张量

创建结果为浮点型, zeros_like(data) => 创建形状和data一样的张量

# 3.1 创建全0张量
data_zeros = torch.zeros(2, 3)
print('0张量', data_zeros)
​
data_zeros = torch.zeros_like(data_zeros)
print('0张量', data_zeros)

创建全1张量

# 3.2 创建全1张量
data_ons = torch.ones(2, 3)
print('1张量', data_ons)
​
data_ons = torch.tensor(data_ons)
print('1张量', data_ons)

创建全指定值张量

# 3.3 创建指定值张量
data_full = torch.full((2, 3), 5)
print('指定值张量', data_full)
​
data_full = torch.full_like(data_full, 10)
print('指定值张量', data_full)

张量元素类型转换

  1. data.type(torch.DoubleTensor)

  2. data.double(), data.float()......小写

  3. data.dtype: 查看数据类型

间接转换

data = torch.full([2, 3], 10)
print(data.dtype)
>>> torch.int64
​
# 将 data 元素类型转换为 float64 类型
data = data.type(torch.DoubleTensor)
print(data.dtype)
>>> torch.float64
​
# 转换为其他类型
# data = data.type(torch.ShortTensor)   # int16
# data = data.type(torch.IntTensor)    # int32
# data = data.type(torch.LongTensor)   # int64
# data = data.type(torch.FloatTensor)  # float32

直接转换

data = torch.full([2, 3], 10)
print(data.dtype)
>>> torch.int64
​
# 将 data 元素类型转换为 float64 类型
data = data.double()
print(data.dtype)
>>> torch.float64
​
# 转换为其他类型
# data = data.short()
# data = data.int()
# data = data.long()
# data = data.float()
​

张量创建总结

创建张量的方式

  • torch.tensor() 根据指定数据创建张量

  • torch.Tensor() 根据形状创建张量, 其也可用来创建指定数据的张量

  • torch.IntTensor()、torch.FloatTensor()、torch.DoubleTensor() 创建指定类型的张量

创建线性和随机张量

  • torch.arrange() 和 torch.linspace() 创建线性张量

  • torch.random.initial_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() 创建全为指定值张量

张量元素类型转换

  • data.type(torch.DoubleTensor)

  • data.double()

二. 张量相关操作

张量的类型转换

张量转Numpy数组

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

import torch
​
torch.manual_seed(21)
​
data = torch.randn(2, 3)
print(type(data))
​
data_numpy = data.numpy().copy()    # 设置不共享内存
print(type(data_numpy))
​
data[0][0] = 100
print(data)
print(data_numpy)

Numpy数组转张量

  1. from_numpy(data_numpy):默认共享内存, 可以使用data_numpy.copy()复制一份, 避免内存共享

  2. torch.tensor()/torch.Tensor ()此方法不共享内存

# numpy转张量
import numpy as np
​
data_numpy = np.random.randn(2, 3)
print(type(data_numpy))
print(data_numpy)
​
# data_tensor = torch.from_numpy(data_numpy)  # 此方法共享内存
# data_tensor = torch.from_numpy(data_numpy.copy())  # 此方法不共享内存
# data_tensor = torch.tensor(data_numpy)  # 此方法不共享内存
data_tensor = torch.Tensor(data_numpy)  # 此方法不共享内存
print(type(data_tensor))
print(data_tensor)
​
data_tensor[0][0] = 100
print(data_numpy)
print(data_tensor)

标量张量和数字转换

当只有一个元素的张量时, 可以使用data.item()函数将该值从张量中取出

# 标量张量和数字转换
​
data = torch.tensor(1)
print(data.item())
​
data = torch.tensor([1, 2])
print(data.item())      # 报错!

张量类型转换总结

张量转换为 numpy 数组
  • data_tensor.numpy()

  • data_tensor.numpy().copy()

numpy 转换为张量
  • torch.from_numpy(data_numpy)

  • torch.tensor(data_numpy)

标量张量和数字转换
  • data.item()

张量的数值计算

基本运算

1. 加减乘除取负号:
2. add+、sub-、mul*、div/、neg负号     不修改原数据
3. add_、sub_、mul_、div_、neg_        修改原数据
import torch
torch.manual_seed(21)
data1 = torch.randint(0, 10, [2, 3])
torch.manual_seed(22)
data2 = torch.randint(10, 20, [3, 4])
torch.manual_seed(23)
data3 = torch.randint(10, 20, [2, 3])
print(data1)
print(data2)
print(data3)
​
# 不修改原数据
print(data1.add(2))
print(data1.sub(2))
print(data1.mul(2))
print(data1.div(2))
print(data1.neg())
print(data1)
​
# # 修改原数据
print(data1.add_(2))
print(data1.sub_(2))
print(data1.mul_(2))
​
print(data1.neg_())
print(data1)

点乘运算

对应位置元素相乘

mul或者*

# 点乘
print(data1.mul(data3))
print(data1 * data3)

矩阵运算

点积

(n, m) * (m, p) = (n, p)

matmul或者@

# 点积
print(data1.matmul(data2))
print(data1 @ data2)

张量运算总结

张量基本运算函数
  • add、sub、mul、div、neg等函数

  • add、sub、mul、div、neg_等函数

张量的点乘运算
  • mul 和运算符 *

点积运算
  • 运算符@用于进行两个矩阵的点乘运算

  • torch.matmul 对进行点乘运算的两矩阵形状没有限定,对数输入的 shape 不同的张量, 对应的最后几个维度必须符合矩阵运算规则

张量函数运算

PyTorch 为每个张量封装很多实用的计算函数:

import torch
​
torch.manual_seed(21)
data = torch.randint(1, 10, (2, 3), dtype=torch.float64)
print(data)
​
# 均值
print(data.mean())
print(data.mean(dim=0))     # 按列求和
print(data.mean(dim=1))     # 按行求和
​
# 平方
print(torch.pow(data, 2))
​
# 平方根
print(data.sqrt())
​
# 求和
print(data.sum())
print(data.sum(dim=0))
print(data.sum(dim=1))
​
# 指数计算(以e为底的指数)
print(data.exp())
​
# 对数计算
print(data.log())   # 以e为底
print(data.log2())
print(data.log10())

张量索引操作

import torch
# 随机生成数据
data = torch.randint(0, 10, [4, 5])
print(data)
>>> tensor([[0, 7, 6, 5, 9],[6, 8, 3, 1, 0],[6, 3, 8, 7, 3],[4, 9, 5, 3, 1]])
​

简单行列索引

print(data[0])      # 第0行数据
>>> tensor([0, 7, 6, 5, 9])
​
print(data[:, 0])   # 所有行第0列数据
>>> tensor([0, 6, 6, 4])
​

列表索引

# 返回 (0, 2)、(1, 3) 两个位置的元素
print(data[[0, 1], [2, 3]])     # 第0行第2列和第1行第3列
>>> tensor([7, 3])
​
# 返回 0、1 行的 1、2 列共4个元素
print(data[[[0], [1]], [1, 2]])
>>> tensor([[7, 6],[8, 3]])
​

范围索引

# 前3行的前2列数据
print(data[:3, :2])
>>> tensor([[0, 7],[6, 8],[6, 3]])
​
# 第2行到最后的前2列数据
print(data[2:, :2])
>>> tensor([[6, 3],[4, 9]])
​
# 第0行、第2行的第0、1两列数据
print(data[0:3:2, :2])# data[行(start, end, step), 列(start, end, step)]
>>>tensor([[0, 7],[6, 3]])
​

布尔索引

# 第三列大于5的行数据
print(data[data[:, 2] > 5])
>>> tensor([[0, 7, 6, 5, 9],[6, 3, 8, 7, 3]])
​
# 第二行大于5的列数据
# 所有数据第1列数据大于5的所有行数据
print(data[:, data[1] > 5])     # data[行, 列] => 第2行大于5的列
>>> tensor([[0, 7],[6, 8],[6, 3],[4, 9]])
​
# 所有行中第4列小于10的行数据
print(data[data[:, 3] < 10])

多维索引

# 范围索引
torch.random.manual_seed(21)
data = torch.randint(0, 10, [3, 4, 5])  # 三通道、四行、五列
print(data)
>>>tensor([[[3, 3, 6, 8, 6],[4, 0, 9, 8, 8],[3, 7, 2, 2, 6],[7, 8, 5, 9, 9]],
​[[9, 4, 4, 4, 2],[2, 0, 8, 1, 2],[9, 8, 8, 3, 1],[4, 1, 6, 8, 8]],
​[[4, 8, 2, 6, 3],[5, 8, 2, 9, 4],[6, 9, 5, 8, 6],[8, 5, 2, 0, 8]]])
​
print(data[:, 1:3, 2])      # 所有通道的第1行和第2行,第2列的数据
>>>tensor([[0, 8],[4, 0],[0, 7]])
​
print(data[1, :, :])    # 第二通道的所有行,所有列的数据
>>>tensor([[9, 4, 4, 4, 2],[2, 0, 8, 1, 2],[9, 8, 8, 3, 1],[4, 1, 6, 8, 8]])

张量形状操作

有重塑、堆叠、挤压和解压:

方法单行描述
torch.reshape(input, shape)重塑 input 到 shape (如果兼容),也可以使用 torch.Tensor.reshape()。
tensor.view(shape)返回不同 shape 中的原始张量视图,但与原始张量共享相同的数据。
tensor.contiguous()将张量转换到整块内存上
torch.stack(tensors, dim=0)堆叠:沿着新的维度(dim)连接 tensors 的序列,所有 tensors 必须具有相同的大小。
torch.squeeze(input)降维:挤压 input 以移除值为 1 的所有尺寸。
torch.unsqueeze(input, dim)升维:返回在 dim 处添加了维度值 1 的 input。
torch.transpose(input,dim1,dim2)维度交换:实现交换张量形状的指定维度
torch.permute(input, dims)返回原始 input 的视图,其尺寸被置换(重新排列)为 dims。

深度学习模型(神经网络)都是以某种方式操纵张量。由于矩阵乘法的规则,如果形状不匹配,就会遇到错误。这些方法可帮助您确保张量的正确元素与其他张量的正确元素混合。

重塑维度形状

reshape

reshape 函数可以在保证张量数据不变的前提下改变数据的维度,将其转换成指定的形状。

使用 torch.reshape() 增加一个维度。

import torch
torch.random.manual_seed(21)
data = torch.randint(0, 10, [4, 5, 6])
print(data)
print(data.shape)
print(data.size())
​
# 1. reshape
# 1.1 降维
data1 = torch.reshape(data, [2, -1])    # -1表示自动计算  
​
print(data1.shape)  # torch.Size([2, 60])
​
# 1.2 改变形状
data2 = torch.reshape(data, [2, 5, -1])
print(data2.shape)  # torch.Size([2, 5, 12])

view/contiguous
  1. view 函数也可以用于修改张量的形状,只能用于存储在整块内存中的张量

  2. 在 PyTorch 中,有些张量是由不同的数据块组成的,它们并没有存储在整块的内存中,view 函数无法对这样的张量进行变形处理。例如: 一个张量经过了 transpose 或者 permute 函数的处理之后,就无法使用 view 函数进行形状操作。

  3. 此时需要先使用 contiguous 函数转换为整块内存的张量,再使用 view 函数。

# 2. view(): 存储在一块内存上才可以操作
# 查看data是否在一块内存上
print(data.is_contiguous())     # True
​
# 2.1 在一块内存上, 改变形状
data3 = data.view(3, 8, -1)
print(data3.shape)      # torch.Size([3, 8, 5])
​
# 2.2 不在一块内存上, 改变形状
# 2.2.1 交换数据维度, 使数据在不同的内存上
# data4 = data.permute(2, 0, 1)   # 一次交换多个维度
data4 = torch.transpose(data, 1, 2)  # 交换两个维度
print(data4.is_contiguous())    # False
​
# 2.2.2 转换为同一内存
print(data4.contiguous().is_contiguous())   # True
# 改变形状
data5 = data4.contiguous().view(3, 8, -1)
print(data5.shape)      # torch.Size([3, 8, 5])

stack

将新张量堆叠五次,使用 torch.stack() 来实现。

x = torch.arange(1, 9)
x_stack = torch.stack([x, x, x, x], dim=0)  # 按0维堆叠
print(x_stack)

升维降维

squeeze 函数删除形状为 1 的维度(降维),unsqueeze 函数添加形状为1的维度(升维)。

unsqueeze升维
# 4. unsqueeze(): 增加维度
data = torch.tensor([1, 2, 3, 4, 5])
print(data.shape)   # torch.Size([5])
​
data1 = data.unsqueeze(dim=0)
print(data1.shape)  # torch.Size([1, 5])
data2 = data.unsqueeze(dim=1)
print(data2.shape)  # torch.Size([5, 1])
data3 = data.unsqueeze(dim=-1)
print(data3.shape)  # torch.Size([5, 1])
squeeze降维

只可以将维度1的维度删除

# 5. squeeze(): 删除维度
data4 = data3.squeeze()
print(data4.shape)  # torch.Size([5])
data5 = data1.squeeze(dim=0)
print(data5.shape)  # torch.Size([5])

维度交换

transpose 函数可以实现交换张量形状的指定维度,

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

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

# 6. 交换维度
data = torch.randint(0, 10, [4, 5, 6])
print(data.shape)   # torch.Size([4, 5, 6])
​
# 交换1和2维度
data1 = torch.transpose(data, 1, 2)
print(data1.shape)  # torch.Size([4, 6, 5])
data2 = data.permute(0, 2, 1)
print(data2.shape)  # torch.Size([4, 6, 5])

张量形状总结

  1. reshape 函数可以在保证张量数据不变的前提下改变数据的维度

  2. squeeze 和 unsqueeze 函数可以用来增加或者减少维度

  3. transpose 函数可以实现交换张量形状的指定维度, permute 可以一次交换更多的维度

  4. view 函数也可以用于修改张量的形状, 但是它要求被转换的张量内存必须连续,所以一般配合 contiguous 函数使用

张量拼接

将多个张量按指定维度(根据维度索引)拼接成一个张量

torch.cat([data1, data2...], dim=维度索引)

import torch
​
data1 = torch.randint(1, 11, [1, 3, 4])
data2 = torch.randint(1, 11, [1, 3, 4])
# print(data1)
# print(data2)
​
# 按0维拼接
data3 = torch.cat([data1, data2], dim=0)
print(data3)
print(data3.shape)
​
# 按1维拼接
data4 = torch.cat([data1, data2], dim=1)
print(data4)
print(data4.shape)
​
# 按2维拼接
data5 = torch.cat([data1, data2], dim=2)
print(data5)
print(data5.shape)

自动微分模块

再反向传播中, 用于计算梯度

正向传播: 由x得到z

反向传播: 由损失更新权重参数

一维

多维

import torch
def test02():# 输入张量 2*5x = torch.ones(2,5)# 目标值是 2*3y = torch.zeros(2,3)# 设置要更新的权重和偏置的初始值w = torch.randn(5, 3,requires_grad=True)b = torch.randn(3, requires_grad=True)# 设置网络的输出值z = torch.matmul(x, w) + b  # 矩阵乘法# 设置损失函数,并进行损失的计算loss = torch.nn.MSELoss()loss = loss(z, y)# 自动微分loss.backward()# 打印 w,b 变量的梯度# backward 函数计算的梯度值会存储在张量的 grad 变量中print("W的梯度:", w.grad)print("b的梯度", b.grad)
​

案例-线性回归

pytorch模型构建流程:

  1. 准备训练集数据

    使用 PyTorch 的 data.DataLoader 代替自定义的数据加载器

    打乱数据顺序, 数据分批次

  2. 构建要使用的模型

    使用 PyTorch 的 nn.Linear 代替自定义的假设函数

  3. 设置损失函数和优化器

    使用 PyTorch 的 nn.MSELoss() 代替自定义的平方损失函数

    使用 PyTorch 的 optim.SGD 代替自定义的优化器

  4. 模型训练

225原则:

2: 2个初始化参数(损失函数, 优化器)

2: 2个遍历(epoch: 轮次, 数据: 批次大小)

5: 前向传播, 损失函数, 梯度清零, 反向传播, 参数更新

构建数据集

# 导入相关模块
import torch
from torch.utils.data import TensorDataset  # 构造数据集对象
from torch.utils.data import DataLoader  # 数据加载器
from torch import nn  # nn模块中有平方损失函数和假设函数
from torch import optim  # optim模块中有优化器函数
from sklearn.datasets import make_regression  # 创建线性回归模型数据集
import matplotlib.pyplot as plt
​
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
​
​
# 定义函数创建数据集: 线性回归: y = kx + b
def creat_datasets():x, y, coef = make_regression(n_samples=100,n_features=1,noise=10,coef=True,bias=1.5,random_state=21)x = torch.tensor(x)y = torch.tensor(y)
​return x, y, coef
​
​
if __name__ == '__main__':x, y, coef = creat_datasets()plt.scatter(x, y)x = torch.linspace(x.min(), x.max(), 1000)# y1 = torch.tensor([coef * i + 1.5 for i in x])    # 报错y1 = torch.tensor([i * coef + 1.5 for i in x])  # i为张量, 只可以张量 * 标量plt.plot(x, y1, label='predict')plt.legend()plt.grid()plt.xlabel('x')plt.ylabel('y')plt.show()

构建数据加载器和模型构建

# 构建数据加载器和模型
def data_loader(x, y):# 构造数据集对象dataset = TensorDataset(x, y)# 构造数据加载器# batch_size: 批次大小# batch: 批次数量# shuffle: 是否打乱顺序dataloader = DataLoader(dataset, batch_size=10, shuffle=True)# 构造模型model = nn.Linear(1, 1)return dataloader, model

训练参数设置

# 设置损失函数和优化器
def loss_optimizer(model):# 设置损失函数: 均方损失函数loss_fn = nn.MSELoss()# 设置优化器: 随机梯度下降, 学习率0.01optimizer = optim.SGD(model.parameters(), lr=0.01)return loss_fn, optimizer

模型训练

# 训练模型
def train_model(dataloader, model, loss_fn, optimizer):# 训练100轮epoch = 100# 存储每轮损失loss_epoch = []total_loss = 0train_sample = 0# 训练轮次for i in range(epoch):# 遍历批次for train_x, train_y in dataloader:# 预测值, 正向传播y_pred = model(train_x.type(torch.float32))# 计算损失loss = loss_fn(y_pred, train_y.reshape(-1, 1).type(torch.float32))# 累加损失total_loss += loss.item()# 累加样本数量train_sample += len(train_y)# 梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 优化器更新参数optimizer.step()# 存储批次损失loss_epoch.append(total_loss / train_sample)return loss_epoch, epoch

轮次损失可视化

if __name__ == '__main__':x, y, coef = creat_datasets()dataloader, model = data_loader(x, y)loss_fn, optimizer = loss_optimizer(model)loss_epoch, epochs = train_model(dataloader, model, loss_fn, optimizer)print(loss_epoch)# 绘制损失变化曲线plt.plot(range(epochs), loss_epoch)plt.title('损失变化曲线')plt.grid()plt.show()# 绘制拟合直线plt.scatter(x, y)x = torch.linspace(x.min(), x.max(), 1000)y1 = torch.tensor([v * model.weight + model.bias for v in x])y2 = torch.tensor([v * coef + 1.5 for v in x])plt.plot(x, y1, label='训练')plt.plot(x, y2, label='真实')plt.grid()plt.legend()plt.show()

案例总结

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

境内部署DIfy(上篇)

背景&#xff1a; 由于近2年大模型的火热催生出很多业务场景&#xff0c;这也迫使我们这些老一辈的程序搬运工去接触新事物&#xff0c;“工欲善其事必先利其器”&#xff0c;先从大模型应用开始摸索&#xff0c;网上大把工具&#xff0c;再三思考后决定先从Dify开始&#xff…

[CKS] 利用Trivy对image进行扫描

最近准备花一周的时间准备CKS考试&#xff0c;在准备考试中发现有一个题目关于Trivy镜像安全扫描的题目。 What’s Trivy Trivy的官方仓库https://github.com/aquasecurity/trivy&#xff0c;Trivy是一个开源的容器镜像漏洞扫描工具。它通过分析容器镜像中的操作系统包和应用…

vue3入门知识(一)

vue3简介 性能的提升 打包大小减少41%初次渲染快55%&#xff0c;更新渲染快133%内存减少54% 源码的升级 使用Proxy代替defineProperty实现响应式重写虚拟DOM的实现和Tree-Shaking 新的特性 1. Composition API&#xff08;组合API&#xff09; setupref与reactivecomput…

数据结构和算法入门

复杂度 大O记法 计算机怎么判断程序性能&#xff1f; 我们都知道编程基本上是在和数据打交道&#xff0c;大多数程序基本都在处理获取数据、查询数据、操作数据、返回数据相关的逻辑。 因此出现了数据结构和算法&#xff0c;这两者出现本质为了解决如何能够更快、更省进行数…

【Linux第八课-进程间通信】管道、共享内存、消息队列、信号量、信号、可重入函数、volatile

目录 进程间通信为什么&#xff1f;是什么&#xff1f;怎么办&#xff1f;一般规律具体做法 匿名管道原理代码 命名管道原理代码 system V共享内存消息队列信号量信号量的接口 信号概念为什么&#xff1f;怎么办&#xff1f;准备信号的产生信号的保存概念三张表匹配的操作和系统…

串的模式匹配

子串的定位操作通常称为串的模式匹配&#xff0c;它求的是子串(常称模式串)在主串中的位置。 子串——主串的一部分&#xff0c;一定存在 模式串——不一定能在主串中找到 朴素模式匹配 将主串中所有长度为m的子串&#xff08;共有n-m1个&#xff09;依次与模式串对比&…

继承的学习

1.继承 继承权限在类外&#xff0c;访问权限在类内部 1.1继承的概念 继承是面向对象程序设计使代码可以复用的重要手段&#xff08;解决类层次的复用问题&#xff09; 派生类&#xff1a;类特性的基础上进行扩展&#xff0c;增加方法&#xff08;成员函数&#xff09;和属性…

YOLOPv2论文翻译

YOLOPv2: Better, Faster, Stronger for Panoptic Driving Perception 摘要 在过去的十年中&#xff0c;多任务学习方法在解决全景驾驶感知问题方面取得了令人鼓舞的成果&#xff0c;既提供了高精度又具备高效能的性能。在设计用于实时实际自动驾驶系统的网络时&#xff0c;这…

跳表原理-课堂笔记

课程地址 跳表是一种基于随机化的有序数据结构&#xff0c;它提出是为了赋予有序单链表以 O(logn) 的快速查找和插入的能力 创建 首先在头部创建一个 sentinel 节点&#xff0c;然后在 L1 层采用“抛硬币”的方式来决定 L0 层的指针是否增长到 L1 层 例如上图中&#xff0c;L…

贪心day04(买卖股票的最佳时机)

1.买卖股票的最佳时机 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;我们其实只需遍历一篇就可以解决这个问题。首先我们定义一个min为无穷大值&#xff0c;再遍历只要有数字比min跟小我们就更改min的值就好&#xff0c;此时我们只需要找出…

【Python爬虫实战】深入解锁 DrissionPage:ChromiumPage 自动化网页操作指南

&#x1f308;个人主页&#xff1a;易辰君-CSDN博客 &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html ​ 目录 前言 一、ChromiumPage基础操作 &#xff08;一&#xff09;初始化Drission 和 ChromiumPage 对象 &#xff0…

VS Code 插件 MySQL Shell for VS Code

https://marketplace.visualstudio.com/items?itemNameOracle.mysql-shell-for-vs-code

稳压二极管详解

目录 1. 工作原理 2. 稳压二极管的伏安特性曲线 3. 正向特性&#xff1a; 4. 反向特性 5. 稳定电压&#xff08;Vz&#xff09; 6. 动态电阻&#xff08;rz&#xff09; 7.最大耗散功率&#xff08;PzM&#xff09; 8. 最大稳定工作电流&#xff08;IzMAX&#xff09;和…

Springboot 一个西餐主题网站-计算机设计毕业源码73020

目录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 2.2.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 系统总体设…

JS渗透(安全)

JS逆向 基本了解 作用域&#xff1a; 相关数据值 调用堆栈&#xff1a; 由下到上就是代码的执行顺序 常见分析调试流程&#xff1a; 1、代码全局搜索 2、文件流程断点 3、代码标签断点 4、XHR提交断点 某通js逆向结合burp插件jsEncrypter 申通快递会员中心-登录 查看登录包…

世界技能竞赛大数据应用开发环境1:1还原

关注我&#xff0c;私信我获得集群环境 集群情况 模块A搭建环境&#xff0c;在容器中搭建大数据平台 Hadoop HA环境 Pc机&#xff0c;安装安装比赛需要软件 模块B中使用idea快速开发完成数据处理 模块E包含了接口数据&#xff0c;使用vs code快速搭建vue数据可视化

【c++丨STL】vector模拟实现

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C、STL 目录 前言 一、vector底层刨析 二、模拟实现 1. 属性、迭代器以及函数声明 2. 功能实现 交换两个容器的内容 构造函数 拷贝构造 赋值重载 析构…

指针的运用

接下来我将会用的话&#xff0c;讲解我对指针运用仅有的印象 1.解引用 int a23; int*p&a; *p666; 而*p666&#xff1b;&#xff0c;便是解引用操作&#xff0c;跟简单地说*p便是解引用&#xff0c;它的意思是&#xff0c;对p中所储存的地址所在位置的内容进行操作&#xf…

三周精通FastAPI:38 针对不同的编程语言来生成客户端

官方文档&#xff1a;https://fastapi.tiangolo.com/zh/advanced/generate-clients/ 生成客户端 因为 FastAPI 是基于OpenAPI规范的&#xff0c;自然您可以使用许多相匹配的工具&#xff0c;包括自动生成API文档 (由 Swagger UI 提供)。 一个不太明显而又特别的优势是&#…

广告联盟有哪些

随着互联网的发展&#xff0c;越来越多的人开始投身于网站建设和运营。对于站长来说&#xff0c;如何在提供优质内容的同时获取收益是一个重要的问题。广告联盟作为一种常见的盈利模式&#xff0c;受到了广大站长的青睐。本文将介绍5个适合国内站长的广告联盟平台&#xff0c;帮…