PyTorch深度学习——张量及其运算

深度学习框架的张量

张量的运算是深度学习的核心,如一张图片可以看作是四维的张量,一个迷你批次的文本可以看作是二维张量,基本上所有的深度学习模型都可以表示为张量的操作,梯度、反向传播算法也可以表示为张量和张量的运算

张量在内存中的排列方式是连续的,而且是从最后一个维度开始排列

张量的性质

  1. 在深度学习中,张量应该能够支持得到每一个维度的长度,也就是保存张量的形状
  2. 张量需要支持和其他相同类型的张量的加减乘除运算
  3. 张量还应该支持变形,也就是说,张量可以变换为总元素的数目相同,但是维度不同的另一个张量——可以将一个张量的某个维度分割为两个维度,或者将最后几个维度合并为一个维度。由于变形之前的两个张量的分量在内存中的排列形状一定是相同的,所以,这两个张量一般会在内存的底层哦女相同一个内存区域
  4. 张量应当支持线性变换(如在卷积层和全连接层中进行的运算)和对每个元素的激活函数进行操作,实现线性变换和激活函数的操作是为了能够方便地进行神经网络的前向运算

Pytorch的张量一共支持9种数据类型,每种数据类型都对应CPU和GPU的两种子类型——如果要获取一个张量的具体类型,可以直接访问张量的dtype属性,如果想要进一步获取张量的存储位置和数据类型,可以通过调用张量的type方法来同时获取存储位置和数据类型的值

现阶段Pytorch并不支持负数类型,如果有要用到的场合,需要使用张量的两个分量来分别模拟负数的实部和虚部,不同的类型之间,可以通过调用to方法进行转换,该方法传入的参数是转换目标类型

张量的创建方式

在Pytorch中创建张量的方式主要有四种方式:

torch.Tensor()、torch.tensor()、torch.as_tensor()、torch.from_numpy()

Pytorch创建张量的四种函数方法及其区别_python_脚本之家

pytorch中8种特殊张量创建方法_pytorch创建-CSDN博客

PyTorch : 了解Tensor(张量)依据数值和概率的创建方法 - 知乎

张量的存储设备

pytorch的张量可以在两种设备上创建:CPU和GPU

通过访问张量的device属性可以获取张量所在的设备,在没有指定设备的时候,pytorch会默认存储张量到CPU上面,如果要想转移到GPU上面,则需要指定张量转移到GPU设备:首先可以使用cpu方法把张量转移到CPU上,其次可以使用cuda方法把张量转移到GPU上,其中需要传入具体的GPU的设备编号;也可以使用to方法把张量从一个设备转移到另一个设备上面,该方法的参数是目标设备的名称(可以使字符串名称,也可以是torch.device实例)

PyTorch 将 PyTorch 代码从 CPU 移植到 GPU|极客笔记

需要注意的是——两个或多个张量之间的运算只有在相同的设备上才能运行(都在CPU或GPU上面),否则就会报错

和张量维度相关的方法

在深度学习中常会用到一些方法获取张量的维度数目,以及某一维度的具体大小,或者对张量的某些维度进行操作

tensor / numpy维度变换操作总结_np维度调换-CSDN博客

张量的运算

涉及单个张量的函数运算

深度学习中,常会用到对张量作四则运算、线性变换和激活等,这些方法可以由张量自带的方法实现,也可以由torch包中的一些函数实现

1、张量的四则运算

import torch  # 创建两个张量  
tensor1 = torch.tensor([1.0, 2.0, 3.0])  
tensor2 = torch.tensor([4.0, 5.0, 6.0])  # 加法  
addition = tensor1 + tensor2  
print("加法:", addition)  # 减法  
subtraction = tensor1 - tensor2  
print("减法:", subtraction)  # 乘法  
multiplication = tensor1 * tensor2  
print("乘法:", multiplication)  # 除法  
division = tensor1 / tensor2  
print("除法:", division)

2、线性变换

线性变换通常通过矩阵乘法实现。在PyTorch中,可以使用mm(针对二维张量)或matmul(针对任意维度的张量)进行矩阵乘法

# 创建一个二维张量(矩阵)  
matrix = torch.tensor([[1.0, 2.0], [3.0, 4.0]])  # 创建一个向量  
vector = torch.tensor([5.0, 6.0])  # 矩阵乘法  
linear_transformation = torch.matmul(matrix, vector.view(-1, 1))  
print("线性变换:", linear_transformation)

3、激活函数

激活函数是神经网络中非常重要的组成部分,它们为模型引入了非线性。PyTorch提供了许多内置的激活函数

# 创建一个张量  
input_tensor = torch.tensor([-2.0, 0.0, 2.0])  # 使用ReLU激活函数  
relu_output = torch.relu(input_tensor)  
print("ReLU激活:", relu_output)  # 使用Sigmoid激活函数  
sigmoid_output = torch.sigmoid(input_tensor)  
print("Sigmoid激活:", sigmoid_output)

在实际的深度学习模型中,这些操作会组合在一起,形成复杂的神经网络结构

涉及多个张量的函数方法

在深度学习中,经常需要对两个形状相同的张量进行逐个元素的四则运算。这些操作都是逐元素的,意味着张量中对应位置的元素会分别进行加法、减法、乘法或除法运算。在PyTorch中,这些操作可以通过简单的运算符重载实现

import torch  # 创建两个形状相同的张量  
tensor1 = torch.tensor([[1.0, 2.0], [3.0, 4.0]])  
tensor2 = torch.tensor([[5.0, 6.0], [7.0, 8.0]])  # 逐个元素的加法  
addition = tensor1 + tensor2  
print("加法:", addition)  # 逐个元素的减法  
subtraction = tensor1 - tensor2  
print("减法:", subtraction)  # 逐个元素的乘法  
multiplication = tensor1 * tensor2  
print("乘法:", multiplication)  # 逐个元素的除法  
# 注意:除法运算需要确保分母不为0,否则会导致错误或无穷大的结果  
division = tensor1 / tensor2  
print("除法:", division)  # 对于除法,如果担心分母为0,可以使用clamp函数确保分母不会太小  
tensor2_clamped = tensor2.clamp(min=1e-6)  # 设置一个小的正数作为分母的最小值  
safe_division = tensor1 / tensor2_clamped  
print("安全的除法:", safe_division)

还可以通过add、sub、mul、div方法来实现,同样也可以通过内置方法的原地操作版本实现

import torch  # 创建两个形状相同的张量  
tensor1 = torch.tensor([[1.0, 2.0], [3.0, 4.0]])  
tensor2 = torch.tensor([[5.0, 6.0], [7.0, 8.0]])  # 使用add方法实现加法  
addition = tensor1.add(tensor2)  
print("加法:", addition)  # 使用sub方法实现减法  
subtraction = tensor1.sub(tensor2)  
print("减法:", subtraction)  # 使用mul方法实现乘法  
multiplication = tensor1.mul(tensor2)  
print("乘法:", multiplication)  # 使用div方法实现除法  
# 注意:同样需要确保分母不为0  
division = tensor1.div(tensor2)  
print("除法:", division)  # 原地操作版本,直接在原张量上修改  
# 注意:原地操作不会返回新的张量,而是修改原张量  
result = tensor1.clone()  # 复制tensor1以便进行原地操作  
result.add_(tensor2)     # 原地加法  
print("原地加法结果:", result)  result = tensor1.clone()  # 再次复制tensor1  
result.sub_(tensor2)     # 原地减法  
print("原地减法结果:", result)  result = tensor1.clone()  
result.mul_(tensor2)     # 原地乘法  
print("原地乘法结果:", result)  result = tensor1.clone()  
result.div_(tensor2)     # 原地除法  
print("原地除法结果:", result)
张量的极值和排序

深度学习中,我们常需要获取张量的最大值和最小值,以及这些值所在的位置,如果只需要最大值和最小值,可以使用argmax和argmin,通过传入具体要沿着那个维度求最大值和最小值的位置,返回沿着该维度最大和最小值对应的序号是多少,如果既要求获取最大值和最小值,又要求获得具体的值,就需要使用max和min,通过传入具体的维度,同时返回沿着该维度最大和最小值的位置,以及对应的最大值和最小值组成的元组

最后一个和大小有关的函数是排序函数sort(默认是从小到大,如果需要从大到小排序,则需要设置参数 descending=True),同样是传入具体需要进行排序的维度,返回的是排序完的张量,记忆对应排序后的元素在原始张量上的位置,如果要知道原始张量还是那的元素沿着某个维度排第几位,只需要对应排序后的元素在原始张量上的位置进行再次排序,得到新位置的值即为原始张量沿着搞方向进行大小排序后的序号,和前面一样,关于排序和极值的函数,既可以是Pytorch的函数,也可以是张量的内置方法,两种方法的调用方法等价

import torch  # 创建一个张量  
tensor = torch.tensor([[4.0, 2.0, 9.0], [6.0, 5.0, 3.0], [8.0, 1.0, 7.0]])  # 使用argmax获取最大值的位置  
max_indices = tensor.argmax(dim=1)  # 沿着维度1(列)查找最大值的位置  
print("最大值的位置:", max_indices)  # 使用argmin获取最小值的位置  
min_indices = tensor.argmin(dim=1)  # 沿着维度1(列)查找最小值的位置  
print("最小值的位置:", min_indices)  # 使用max获取最大值及其位置  
max_values, max_positions = tensor.max(dim=1)  # 沿着维度1(列)查找最大值及其位置  
print("最大值和它们的位置:", max_values, max_positions)  # 使用min获取最小值及其位置  
min_values, min_positions = tensor.min(dim=1)  # 沿着维度1(列)查找最小值及其位置  
print("最小值和它们的位置:", min_values, min_positions)  # 使用sort对张量进行排序  
sorted_tensor, sorted_indices = tensor.sort(dim=1, descending=False)  # 从小到大排序,并获取原始位置的索引  
print("排序后的张量:", sorted_tensor)  
print("排序后的元素在原始张量上的位置:", sorted_indices)  # 如果要知道原始张量中的元素沿着某个维度排第几位,需要对排序后的索引进行排序  
original_indices = torch.arange(sorted_indices.size(0)).to(sorted_indices.device)  # 创建原始索引  
sorted_original_indices = sorted_indices.argsort(dim=1)  # 对排序后的索引进行排序  
print("原始张量元素排序后的序号:", sorted_original_indices)
矩阵的乘法和张量的缩并

除上述的运算之外,由两个张量作为参数的操作还有矩阵乘法(线性变换),可以使用torch.mm函数或者张量内置的mm方法进行矩阵乘法,还可以使用@运算符实现

需要注意的是,如果你的张量不是二维的(例如,它们包含额外的维度,如批次维度),你可能需要使用torch.matmul函数或matmul方法,或者使用@运算符(在PyTorch中,@运算符在内部实际上是调用torch.matmul)。torch.matmul可以处理任意维度的张量,只要它们的维度是兼容的以进行矩阵乘法

import torch  # 创建两个二维张量(矩阵)  
matrix1 = torch.tensor([[1.0, 2.0], [3.0, 4.0]])  
matrix2 = torch.tensor([[5.0, 6.0], [7.0, 8.0]])  # 使用torch.mm函数进行矩阵乘法  
result_mm = torch.mm(matrix1, matrix2)  
print("使用torch.mm的结果:", result_mm)  # 使用张量内置的mm方法进行矩阵乘法  
result_method = matrix1.mm(matrix2)  
print("使用张量mm方法的结果:", result_method)  # 使用@运算符进行矩阵乘法  
result_at = matrix1 @ matrix2  
print("使用@运算符的结果:", result_at)

另一个特殊的矩阵乘法的函数是bmm函数,在深度学习中,实际经常用到的数据是迷你批次的数据,一般来说,第一个维度是迷你批次的大小,因此,数据的矩阵实际上是一个迷你批次的矩阵,即一个三维的张量(可以看作是一个迷你批次数量和矩阵叠加在一起)

此时如果两个张量做矩阵乘法,一般情况下是沿着迷你批次的方向分别对每个矩阵对做乘法,最后把结果整合在一起,如果是一个 b×m×k 的张量和 b×k×n 的张量相乘,那么结果应该是 b×m×n 的张量,torch.einsum 函数的使用如下

torch.einsum 是一个极其强大的函数,它用于在 PyTorch 中执行爱因斯坦求和约定(Einstein summation convention)。爱因斯坦求和约定提供了一种紧凑的方式来表示多维数组(如张量)之间的复杂操作,包括但不限于点积、外积、转置、矩阵乘法、批量矩阵乘法等。

torch.einsum 的基本语法是:

torch.einsum(equation, *operands)

其中 equation 是一个描述操作的字符串,而 *operands 是参与操作的张量列表。

Einstein Summation Convention 的基本思想

爱因斯坦求和约定使用特定的标记来表示张量的维度,并通过省略号来指定对这些维度进行求和。

  • 字母(如 i, j, k, ...)表示张量的维度。
  • 每个字母在每个张量中最多出现两次:一次在输入位置,一次在输出位置。
  • 如果一个字母在输出位置没有出现,则意味着对该维度进行求和。
  • 省略号 ... 用于表示多个维度。

示例

1. 向量点积

import torch a = torch.tensor([1.0, 2.0, 3.0]) 
b = torch.tensor([4.0, 5.0, 6.0]) result = torch.einsum('i,i->', a, b) # 点积:1*4 + 2*5 + 3*6 
print(result) # 输出:32.0

2. 矩阵乘法

A = torch.tensor([[1.0, 2.0], [3.0, 4.0]]) 
B = torch.tensor([[5.0, 6.0], [7.0, 8.0]]) result = torch.einsum('ij,jk->ik', A, B) # 矩阵乘法 
print(result)

3. 批量矩阵乘法

A = torch.randn(3, 2, 5) # 3个2x5矩阵 
B = torch.randn(3, 5, 4) # 3个5x4矩阵 result = torch.einsum('bij,bjk->bik', A, B) # 批量矩阵乘法,输出为3个2x4矩阵 
print(result.shape) # 输出:torch.Size([3, 2, 4])

4. 转置

M = torch.randn(2, 3) # 转置矩阵,从 'ij' 变为 'ji' 
transposed = torch.einsum('ij->ji', M) 
print(transposed)

5. 外积

a = torch.tensor([1.0, 2.0]) 
b = torch.tensor([3.0, 4.0]) # 外积,输出是一个2x2的矩阵 
outer_product = torch.einsum('i,j->ij', a, b) 
print(outer_product)

torch.einsum 的强大之处在于它可以以非常简洁的方式表达复杂的张量操作,而不需要编写冗长的循环或显式的维度操作代码。这使得它在处理高维数据和复杂的神经网络结构时特别有用

张量的拼接和分割

在PyTorch中,你可以使用torch.cat来拼接张量,使用torch.chunk、torch.split或torch.narrow等函数来分割张量。下面是一些代码示例:

张量的拼接

假设我们有两个形状相同的张量,我们想要将它们沿某个维度拼接起来

import torch # 创建两个形状相同的张量 
tensor1 = torch.tensor([[1, 2], [3, 4]]) 
tensor2 = torch.tensor([[5, 6], [7, 8]]) # 沿着第一个维度(行)拼接 
concatenated_row = torch.cat((tensor1, tensor2), dim=0) 
print("沿着行拼接:") 
print(concatenated_row) # 沿着第二个维度(列)拼接 
concatenated_col = torch.cat((tensor1, tensor2), dim=1) 
print("沿着列拼接:") 
print(concatenated_col)

张量的分割

分割张量通常涉及到将一个大张量分成若干个小张量。

使用torch.chunk分割张量

torch.chunk函数将张量分割成指定数量的块

# 创建一个张量 
tensor = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) # 沿着第一个维度(行)分割成2块 
chunks_row = torch.chunk(tensor, chunks=2, dim=0) 
for chunk in chunks_row: 
print(chunk) # 沿着第二个维度(列)分割成2块 
chunks_col = torch.chunk(tensor, chunks=2, dim=1) 
for chunk in chunks_col: 
print(chunk)

使用torch.split分割张量

torch.split函数允许你按照更灵活的规则分割张量,可以指定每个块的大小

# 创建一个张量 
tensor = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) # 沿着第二个维度(列)分割,指定每个块的大小 
split_col = torch.split(tensor, split_size_or_sections=[2, 1, 1], dim=1) 
for part in split_col: 
print(part)

使用torch.narrow选择张量的狭窄切片

torch.narrow不是用来分割张量的,但它可以用来选择张量沿着某一维度的一个狭窄切片

# 创建一个张量 
tensor = torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) # 选择第二行 
narrow_tensor = tensor.narrow(0, 1, 1) 
print(narrow_tensor) # 选择第一列到第三列 
narrow_tensor_col = tensor.narrow(1, 0, 3) 
print(narrow_tensor_col)

注意:上述代码中torch.cat函数的括号使用有误,正确的应该是去掉内层的括号。修正后的代码应该如下所示:

# 沿着第一个维度(行)拼接 
concatenated_row = torch.cat((tensor1, tensor2), dim=0) # 错误用法 
concatenated_row = torch.cat((tensor1, tensor2), dim=0) # 正确用法,但内层括号是多余的 
concatenated_row = torch.cat([tensor1, tensor2], dim=0) # 更常见的正确用法 # 沿着第二个维度(列)拼接 
concatenated_col = torch.cat((tensor1, tensor2), dim=1) # 错误用法 
concatenated_col = torch.cat([tensor1, tensor2], dim=1) # 正确用法

在实际使用中,通常更推荐使用列表[]来传递要拼接的张量,而不是元组(),尽管在某些情况下元组也是可行的

张量维度的扩增和压缩

在PyTorch中,张量维度的扩增(也称为扩展或广播)和压缩是常见的操作。这通常通过torch.unsqueeze和torch.squeeze函数实现。此外,torch.shape、torch.view和torch.flatten等函数也常用于改变张量的形状

张量维度的扩增(Unsqueeze)

torch.unsqueeze函数用于在张量的指定位置增加一个新的维度,大小为1

import torch # 创建一个形状为 [2, 3] 的张量 
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]]) 
print("原始张量:") 
print(tensor) 
print("形状:", tensor.shape) # 在第一个维度前增加一个新维度 
tensor_unsqueezed_dim0 = torch.unsqueeze(tensor, dim=0) 
print("在第一个维度前增加维度后的张量:") 
print(tensor_unsqueezed_dim0) 
print("形状:", tensor_unsqueezed_dim0.shape) # 在第二个维度后增加一个新维度 
tensor_unsqueezed_dim1 = torch.unsqueeze(tensor, dim=1) 
print("在第二个维度后增加维度后的张量:") 
print(tensor_unsqueezed_dim1) 
print("形状:", tensor_unsqueezed_dim1.shape)

张量维度的压缩(Squeeze)

torch.squeeze函数用于移除张量中所有大小为1的维度

# 使用上面的 tensor_unsqueezed_dim1 张量,它有一个大小为1的维度在第二个位置 
print("带有一个大小为1的维度的张量:") 
print(tensor_unsqueezed_dim1) 
print("形状:", tensor_unsqueezed_dim1.shape) # 压缩大小为1的维度 
tensor_squeezed = torch.squeeze(tensor_unsqueezed_dim1) 
print("压缩维度后的张量:") 
print(tensor_squeezed) 
print("形状:", tensor_squeezed.shape)

重塑张量形状(Reshape/View)

torch.resape和torch.view函数用于改变张量的形状,但不改变数据

# 使用原始的 [2, 3] 张量 
print("原始张量:") 
print(tensor) 
print("形状:", tensor.shape) # 使用reshape改变形状为 [3, 2] 
tensor_reshaped = tensor.reshape(3, 2) 
print("重塑后的张量:") 
print(tensor_reshaped) 
print("形状:", tensor_reshaped.shape) # 使用view改变形状为 [6] 
tensor_view = tensor.view(6) 
print("view后的张量:") 
print(tensor_view) 
print("形状:", tensor_view.shape)

请注意,reshape和view要求新形状与原始张量的元素总数相同。如果尝试将张量重塑为不兼容的形状,将会引发错误

张量展平(Flatten)

展平张量意味着将其所有维度合并成一个维度,通常用于将多维张量转换为一维张量

# 使用原始的 [2, 3] 张量 
print("原始张量:") 
print(tensor) 
print("形状:", tensor.shape) # 使用flatten展平张量 
tensor_flattened = tensor.flatten() 
print("展平后的张量:") 
print(tensor_flattened) 
print("形状:", tensor_flattened.shape)

torch.flatten函数还允许你指定从哪一维度开始展平以及是否保持批处理维度。这对于处理具有批处理维度的张量(如在神经网络中)特别有用

张量的广播

在PyTorch中,广播(broadcasting)是一种强大的机制,它允许PyTorch在元素级操作中对不同形状的张量进行自动扩展。这允许你在不显式重塑张量的情况下执行诸如加法、乘法等操作。广播规则基于NumPy的广播规则

import torch  # 创建两个形状不同的张量  
tensor1 = torch.tensor([[1, 2, 3]])  # 形状: [1, 3]  
tensor2 = torch.tensor([[4], [5], [6]])  # 形状: [3, 1]  # 由于广播规则,我们可以直接对这两个张量进行加法操作  
# tensor1 会沿着第0维(行)复制以匹配tensor2的形状  
# tensor2 会沿着第1维(列)复制以匹配tensor1的形状  
# 结果形状为 [3, 3]  
result = tensor1 + tensor2  print("tensor1:")  
print(tensor1)  
print("形状:", tensor1.shape)  print("tensor2:")  
print(tensor2)  
print("形状:", tensor2.shape)  print("广播后的结果:")  
print(result)  
print("形状:", result.shape)

在上面的例子中,tensor1 的形状是 [1, 3],而 tensor2 的形状是 [3, 1]。当我们将这两个张量相加时,PyTorch会根据广播规则自动扩展它们以匹配对方的形状。具体来说,tensor1 会在第0维(行)上复制以匹配 tensor2 的3行,而 tensor2 会在第1维(列)上复制以匹配 tensor1 的3列。因此,结果张量的形状是 [3, 3]

广播规则要求,从右到左比较每个维度的大小:

  1. 如果两个维度的大小相等,或者其中一个维度的大小为1,则它们兼容,因此可以进行广播。
  2. 如果两个维度的大小都不为1且不相等,则它们不兼容,无法广播。

在上述例子中,tensor1 的第1维(列)大小为3,而 tensor2 的第0维(行)大小为3,因此它们是兼容的。同时,tensor1 的第0维(行)大小为1,而 tensor2 的第1维(列)大小为1,因此它们也是兼容的。因此,这两个张量可以广播

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

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

相关文章

scoped原理及使用

一、什么是scoped,为什么要用 在vue文件中的style标签上,有一个特殊的属性:scoped。 当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,通过该属性,可以使得组件之间的样式不互相污染。…

LLM大模型可视化-以nano-gpt为例

内容整理自:LLM 可视化 --- LLM Visualization (bbycroft.net)https://bbycroft.net/llm Introduction 介绍 Welcome to the walkthrough of the GPT large language model! Here well explore the model nano-gpt, with a mere 85,000 parameters. 欢迎来到 GPT 大…

深入浅出 -- 系统架构之分布式CAP理论和BASE理论

科技进步离不开理论支撑,而当下大行其道的分布式架构,透过繁荣昌盛表象,底层同样离不开诸多分布式理论撑持。当然,相信诸位在学习分布式相关技术时,必然学到过两个分布式领域中的基础理论,即:CA…

9.set容器的使用

文章目录 set容器1.构造和赋值代码工程运行结果 2.大小和交换代码工程运行结果 4.插入和删除代码工程运行结果 5.查找和统计工程代码运行结果 6.multset代码工程运行结果 7.指定排序规则代码工程运行结果 8.自定义数据类型排序代码工程运行结果 set容器 所有元素都会在插入时&a…

理解Three.js的相机

大家都知道我们生活中的相机,可以留下美好瞬间。那Three.js的相机是什么呢?Three.js创建的场景是三维的,而我们使用的显示器显然是二维的,相机就是抽象的定义了三维空间到二维显示器的投影方式。Three.js常见的相机有两类&#xf…

Stable diffusion 加载扩展列表报错解决方法

项目场景: 在使用Stable diffusion webui时,使用扩展列表出现错误 问题描述 点击loadfrom后,出现加载扩展列表报错 原因分析: 下载的扩展的时候,都是github 的url,需要科学上网,如果不能科学…

C语言动态内存空间分配

1. 前言 在讲内存分配前,咱来聊一下为什么会有内存分配这个概念呢,大家都知道C语言当中是有着许多的数据类型,使用这些数据类型就会在内存上开辟其相对应的空间,那既然会开辟相应的空间,为什么还会有内存分配呢&#x…

如何利用FLUENT计算流体力学方法解决大气与环境领域流动问题

ANSYS FLUENT是目前全球领先的商用CFD 软件,市场占有率达70%左右,是工程师和研究者不可多得的有力工具。由于采用了多种求解方法和多重网格加速收敛技术,因而FLUENT能达到最佳的收敛速度和求解精度。灵活的非结构化网格和基于解的自适应网格技…

Pycharm安装request的时候出现警告“由于目标计算机积极拒绝,无法连接”,然后出现报错无法安装

Pycharm安装request的时候出现警告“由于目标计算机积极拒绝,无法连接”,然后出现报错无法安装 一、报错二、解决办法 一、报错 二、解决办法 1、点击WinR 2、输入 regedit、进入注册表 3、在搜索框处输入:HKEY_CURRENT_USER\Software\Mic…

HTML基础知识详解(上)(如何想知道html的全部基础知识点,那么只看这一篇就足够了!)

前言:在学习前端基础时,必不可少的就是三大件(html、css、javascript ),而HTML(超文本标记语言——HyperText Markup Language)是构成 Web 世界的一砖一瓦,它定义了网页内容的含义和…

57 npm run build 和 npm run serve 的差异

前言 npm run serve 和 npm run build 的差异 这里主要是从 vue-cli 的流程 来看一下 我们经常用到的这两个命令, 他到传递给 webpack 打包的时候, 的一个具体的差异, 大致是配置了那些东西? 经过了那些流程 ? vue-cli 的 vue-plugin 的加载 内置的 plugin 列表如下, 依次…

Python云计算技术库之libcloud使用详解

概要 随着云计算技术的发展,越来越多的应用和服务迁移到了云端。然而,不同云服务商的API和接口千差万别,给开发者带来了不小的挑战。Python的libcloud库应运而生,它提供了一个统一的接口,让开发者可以轻松地管理不同云服务商的资源。本文将深入探讨libcloud库的特性、安装…

keycloak - 鉴权VUE

目录 一、前言 1、背景 2、实验版本 二、开始干活 1、keycloak配置 a、创建领域(realms) b、创建客户端 c、创建用户、角色 2、vue代码 a、依赖 b、main.js 三、未解决的问题 目录 一、前言 1、背景 2、实验版本 二、开始干活 1、keycloak配置 a、创建领域(r…

51单片机入门:认识开发板

认识开发板 板载资源: 数码管模块 说明: 2个四位一体共阴数码管 详细: 2个四位一体:两个独立的四位数码管,每个四位数码管都是“一体”的设计,也就是说,每个数码管内部集成了四个独立的七段LE…

【学习】成为优秀的软件测试工程师需要学哪些知识

成为软件测试工程师,需要学习的内容非常的多,但是无非是这几大类,今天就和小编一起来看看这些知识,你是否都已经掌握。 01、测试环境的搭建 本部分主要是学习从操作系统开始,有关的计算机基础知识、软件和硬件知识、…

golang设计模式图解——模板方法模式

设计模式 GoF提出的设计模式有23个,包括: (1)创建型(Creational)模式:如何创建对象; (2)结构型(Structural )模式:如何实现类或对象的组合; (3&a…

LeNet卷积神经网络

文章目录 简介conv2d网络层的结构 简介 它是最早发布的卷积神经网络之一 conv2d 这个卷积成的参数先进行介绍一下: self.conv1 nn.Conv2d(in_channels3, out_channels10, kernel_size3, stride1, padding1)先看一下in_channels 输入的通道数,out_cha…

初识MySQL(中篇)

使用语言 MySQL 使用工具 Navicat Premium 16 代码能力快速提升小方法,看完代码自己敲一遍,十分有用 目录 1.SQL语言 1.1 SQL语言组成部分 2.MySQL数据类型 2.1 数值类型 2.2 字符串类型 2.3 日期类型 3.创建数据表 3.1 创建数据表方法1 …

scala实现通过Spark统计人均登录次数最终写入MySQL

谨以此博客作为记录 小编这里用的版本是&#xff1a; <hadoop.version>2.7.7</hadoop.version> <spark.version>2.4.5</spark.version> <scala.version>2.12.10</scala.version> 如果没用到Hadoop可以忽略 步骤 准备数据&#xff0c;知道…

Python网络爬虫(四):b站评论

首先来看一下采集的数据格式: 本文不对数据采集的过程做探讨,直接上代码。首先要在程序入口处bvids列表内替换成自己想要采集的视频bvid号,然后将self.cookies替换成自己的(需要字典格式),代码可以同时爬取多个视频的评论,且爬取的评论较为完整,亲测有效: im…