前言
在深度学习日益成为解决复杂问题重要工具的今天,PyTorch凭借其灵活性和易用性,成为了众多研究者与开发者的首选框架。本系列博客
将对torch中的nn模块中186个函数进行介绍,以函数首字母从a到z的排序开展,包含函数原理、原型和示例。
本文对nn.AdaptiveAvgPool1d、nn.AdaptiveAvgPool2d、nn.AdaptiveAvgPool3d、nn.AdaptiveLogSoftmaxWithLoss、nn.AdaptiveMaxPool1d、nn.AdaptiveMaxPool2d、nn.AdaptiveMaxPool3d、nn.AlphaDropout、nn.AvgPool1d、nn.AvgPool2d、nn.AvgPool3d、nn.BCELoss、nn.BCEWithLogitsLoss、nn.BatchNorm1d、nn.BatchNorm2d、nn.BatchNorm3d、nn.Bilinear 17个函数进行详解。
- 前言
- 函数
- nn.AdaptiveAvgPool1d
- 原理
- 原型
- 示例
- nn.AdaptiveAvgPool2d
- 原理
- 原型
- 示例
- nn.AdaptiveAvgPool3d
- 原理
- 原型
- 示例
- nn.AdaptiveLogSoftmaxWithLoss
- 原理
- 原型
- 示例
- nn.AdaptiveMaxPool1、2、3d
- 原理
- 原型
- 示例
- nn.AlphaDropout
- 原理
- 函数原型
- 示例
- nn.AvgPool1、2、3d
- 原理
- 原型
- 示例
- nn.BCELoss
- 原理
- 原型
- 示例
- nn.BCEWithLogitsLoss
- 原理
- 原型
- 示例
- nn.BatchNorm1、2、3d
- 原理
- 原型
- 示例
- nn.Bilinear
- 原理
- 原型
- 示例
- 小结
函数
nn.AdaptiveAvgPool1d
原理
AdaptiveAvgPool1d执行一维自适应平均池化,它根据指定的输出尺寸自动调整池化窗口大小,对每个池化区域内的元素取平均值。
原型
torch.nn.AdaptiveAvgPool1d(output_size)
output_size:期望的输出尺寸,可以是单个整数或整数元组(对于AdaptiveAvgPool1d,通常是单个整数)。
示例
import torch
import torch.nn as nn
# 创建一个AdaptiveAvgPool1d层,输出尺寸为5
m = nn.AdaptiveAvgPool1d(5)
input = torch.randn(1, 64, 8) # (batch_size, channels, length)
output = m(input)
print(output.shape) # torch.Size([1, 64, 5])
nn.AdaptiveAvgPool2d
原理
AdaptiveAvgPool2d执行二维自适应平均池化,适用于图像等二维数据。它根据指定的输出尺寸自动调整池化窗口大小。
原型
torch.nn.AdaptiveAvgPool2d(output_size)
output_size:期望的输出尺寸,可以是单个整数(此时高度和宽度相同)或整数元组(H, W)。
示例
import torch
import torch.nn as nn
# 创建一个AdaptiveAvgPool2d层,输出尺寸为5x7
m = nn.AdaptiveAvgPool2d((5, 7))
input = torch.randn(1, 64, 8, 9) # (batch_size, channels, height, width)
output = m(input)
print(output.shape) # torch.Size([1, 64, 5, 7])
nn.AdaptiveAvgPool3d
原理
AdaptiveAvgPool3d执行三维自适应平均池化,适用于3D图像或视频帧等三维数据。
原型
torch.nn.AdaptiveAvgPool3d(output_size)
output_size:期望的输出尺寸,可以是单个整数(此时深度、高度和宽度相同)或整数元组(D, H, W)。
示例
import torch
import torch.nn as nn
m = nn.AdaptiveAvgPool3d((2, 2, 2))
input = torch.randn(1, 1, 4, 4, 4) # (batch_size, channels, depth, height, width)
output = m(input)
print(output.shape) # torch.Size([1, 1, 2, 2, 2])
nn.AdaptiveLogSoftmaxWithLoss
原理
nn.AdaptiveLogSoftmaxWithLoss 是 PyTorch 中的一个特殊损失函数,它结合了自适应的对数 Softmax 激活和负对数似然损失(NLLLoss),专门设计用于处理具有大量类别的分类问题。这种函数在处理大规模词汇量的自然语言处理(NLP)任务时特别有用,因为它能够显著减少内存消耗并加速计算。
nn.AdaptiveLogSoftmaxWithLoss 的核心思想是将类别分成多个块(partitions),并对每个块独立地应用 Softmax 和计算损失。这样,对于每个输入,它只需要计算一小部分类别(即当前输入所属的块中的类别)的 Softmax 值,而不是整个类别集合的 Softmax 值。这大大减少了计算量和内存使用。
具体来说,该函数接受一个整数列表 cutoffs 作为参数,该列表定义了不同块之间的边界。根据这些边界,输入类别的索引被分配到不同的块中。然后,对于每个块,都会应用一个独立的线性层(或称为“头”和“尾”),并将结果传递给 Softmax 激活函数和 NLLLoss。
原型
torch.nn.AdaptiveLogSoftmaxWithLoss(in_features, n_classes, cutoffs, div_value=4.0, head_bias=None)
参数说明:
in_features:输入特征的数量。
n_classes:类别总数。
cutoffs:一个整数列表,定义了类别分块的边界。
div_value:用于调整分块内类别数的对数比例,默认为 4.0。
head_bias:可选,用于初始化头部(即第一个分块)的偏置项。
示例
import torch
import torch.nn as nn
# 假设有1000个输入特征和200个类别
in_features = 1000
n_classes = 200
# 设置cutoffs,这里简单地将类别分为几个簇
cutoffs = [20, 100, 150]
# 初始化AdaptiveLogSoftmaxWithLoss
adaptive_softmax = nn.AdaptiveLogSoftmaxWithLoss(in_features, n_classes, cutoffs)
# 创建一个随机批次的输入数据
batch_size = 15
input = torch.randn(batch_size, in_features)
# 生成目标类别索引
target = torch.randint(n_classes, (batch_size,), dtype=torch.long)
# 计算损失
loss_output = adaptive_softmax(input, target)
loss = loss_output.loss # 获取损失值 Tensor
print("Loss:", loss.item())
nn.AdaptiveMaxPool1、2、3d
本部分为了更直观的对比 nn.AdaptiveMaxPool1d、 nn.AdaptiveMaxPooll2d和 nn.AdaptiveMaxPool3d三个函数,将其放在一起进行详解和示例。
原理
自适应最大池化(Adaptive Max Pooling)是一种池化方法,它可以根据输出尺寸自动调整池化窗口的大小,而不需要手动设置池化窗口的具体参数(如大小和步长)。这种方法使得网络能够处理不同大小的输入,同时保持输出尺寸的一致性。
**nn.AdaptiveMaxPool1d:**适用于一维数据,如音频波形。它将输入数据沿着单一维度(通常是长度维度)进行划分,并在每个划分的区域内取最大值,从而输出指定长度的特征向量。
**nn.AdaptiveMaxPool2d:**用于处理二维数据,如图像。它将输入特征图划分为多个固定大小的区域,并在每个区域内取最大值,从而输出指定尺寸的特征图。
**nn.AdaptiveMaxPool3d:**用于处理三维数据,如医学扫描图像。其原理与nn.AdaptiveMaxPool2d类似,但操作是在三维空间上进行的。
原型
nn.AdaptiveMaxPool1d:
torch.nn.AdaptiveMaxPool1d(output_size, return_indices=False)
参数说明:
output_size:输出特征图的长度。
return_indices:如果设置为True,则返回最大值的索引。
nn.AdaptiveMaxPool2d
nn.AdaptiveMaxPool2d:
torch.nn.AdaptiveMaxPool2d(output_size, return_indices=False)
参数说明:
output_size:输出特征图的高度和宽度,可以是一个整数(表示高度和宽度相同)或一个包含两个整数的元组(分别表示高度和宽度)。
return_indices:如果设置为True,则返回最大值的索引。
nn.AdaptiveMaxPool3d
nn.AdaptiveMaxPool3d:
torch.nn.AdaptiveMaxPool3d(output_size, return_indices=False)
参数说明:
output_size:输出特征图的深度、高度和宽度,可以是一个整数(表示所有维度相同)或一个包含三个整数的元组(分别表示深度、高度和宽度)。
return_indices:如果设置为True,则返回最大值的索引。
示例
import torch
import torch.nn as nn
# 假设输入数据形状为 [batch_size, channels, length]
input_1d = torch.randn(1, 3, 32)
# 创建一个AdaptiveMaxPool1d层,输出长度为16
pool_1d = nn.AdaptiveMaxPool1d(output_size=16)
# 应用池化层
output_1d = pool_1d(input_1d)
# 输出形状应为 [1, 3, 16]
print(f"nn.AdaptiveMaxPool1d函数示例结果{output_1d.shape}")
# 假设输入数据形状为 [batch_size, channels, height, width]
input_2d = torch.randn(1, 3, 24, 24)
# 创建一个AdaptiveMaxPool2d层,输出尺寸为(7, 7)
pool_2d = nn.AdaptiveMaxPool2d(output_size=(7, 7))
# 应用池化层
output_2d = pool_2d(input_2d)
# 输出形状应为 [1, 3, 7, 7]
print(f"nn.AdaptiveMaxPool2d函数示例结果{output_2d.shape}")
# 假设输入数据形状为 [batch_size, channels, depth, height, width]
input_3d = torch.randn(1, 3, 8, 24, 24)
# 创建一个AdaptiveMaxPool3d层,输出尺寸为(2, 7, 7)
pool_3d = nn.AdaptiveMaxPool3d(output_size=(2, 7, 7))
# 应用池化层
output_3d = pool_3d(input_3d)
print(f"nn.AdaptiveMaxPool3d函数示例结果{output_3d.shape}")
nn.AlphaDropout
原理
在深度学习中,过拟合是一个常见的问题,特别是在模型复杂度较高且训练数据相对较少的情况下。为了防止过拟合,研究者们提出了多种正则化技术,其中Dropout是一种非常有效的方法。而nn.AlphaDropout作为PyTorch框架中的一个特殊Dropout层,具有独特的自归一化属性,特别适用于与SELU激活函数一起使用的自归一化神经网络。
nn.AlphaDropout是一种保持输入数据自归一化属性的Dropout技术。对于具有0均值和单位标准差的输入,AlphaDropout能够确保输出数据的均值和标准差保持不变。这一特性使得AlphaDropout在训练过程中更加稳定,有助于加速模型的收敛。
在训练过程中,AlphaDropout会按照从伯努利分布中采样得到的概率p将输入张量中的部分元素置零。与普通的Dropout不同,AlphaDropout在置零后会对剩余的元素进行缩放和移位操作,以保持输出的均值和标准差不变。这一操作确保了即使在Dropout的情况下,数据的分布特性也能得到保持。
此外,AlphaDropout通常与SELU激活函数一起使用,因为SELU激活函数本身也具有自归一化的特性。两者结合使用,可以进一步增强模型的稳定性和泛化能力。
函数原型
torch.nn.AlphaDropout(p=0.5, inplace=False)
参数说明:
p:元素被置零的概率,默认值为0.5。
inplace:如果设置为True,则直接修改输入张量而不创建新的输出张量。默认值为False。
示例
import torch
import torch.nn as nn
# 自定义SELU激活函数
def selu(x, alpha=1.6732632423543772, scale=1.0507009873554805):
"""
SELU (Scaled Exponential Linear Unit) 激活函数
"""
return scale * torch.where(x >= 0, x, alpha * (torch.exp(x) - 1))
# 定义一个使用SELU激活函数的简单神经网络模型
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.fc1 = nn.Linear(10, 50) # 第一个全连接层
self.alpha_dropout = nn.AlphaDropout(p=0.5) # AlphaDropout层
self.fc2 = nn.Linear(50, 1) # 第二个全连接层
def forward(self, x):
x = self.fc1(x)
x = selu(x) # 应用SELU激活函数
x = self.alpha_dropout(x) # 应用AlphaDropout
x = self.fc2(x)
return x
# 创建一个模型实例
model = SimpleModel()
# 假设有一个输入张量
input_tensor = torch.randn(1, 10) # 形状为 [batch_size, features]
# 将模型设置为训练模式
model.train()
# 前向传播
output = model(input_tensor)
# 输出结果
print(output)
nn.AvgPool1、2、3d
本部分为了更直观的对比 nn.AvgPool1d、 nn.AvgPool2d和 nn.AvgPool3d三个函数,将其放在一起进行详解和示例。
原理
nn.AvgPool1d、nn.AvgPool2d和nn.AvgPool3d是PyTorch框架中提供的平均池化层,分别用于一维、二维和三维数据的池化操作。这些层通过计算输入数据在指定窗口(或称为核)内的平均值来降采样数据。平均池化层有助于减少数据的空间维度,减少计算量,并能够在一定程度上防止过拟合。
在平均池化过程中,输入数据被划分为不重叠的窗口,然后计算每个窗口内所有元素的平均值,并将该平均值作为该窗口的输出。窗口的大小(即核大小)和步长(stride)是可以设置的参数,它们决定了池化操作的行为。
原型
torch.nn.AvgPool1d(kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True, divisor_override=None)
参数说明:
kernel_size (int or tuple): 池化窗口的大小。对于一维池化,它应该是一个整数。
stride (int or tuple, 可选): 池化操作的步长。默认为kernel_size。
padding (int or tuple, 可选): 输入数据两侧添加的零填充的数量。
ceil_mode (bool, 可选): 是否使用ceil函数计算输出尺寸,而不是floor。默认为False。
count_include_pad (bool, 可选): 是否将零填充计入平均值的计算中。在PyTorch中,这个参数实际上叫做divisor_override,但通常在文档中看到的是count_include_pad的概念,用于说明是否包括填充值在平均数的计算中。在较新版本的PyTorch中,更常见的做法是使用divisor_override来直接指定除数,或者不使用它(默认为None)让PyTorch自动计算。
divisor_override (int, 可选): 指定用于平均值的除数。如果指定,它将覆盖由kernel_size、padding和是否包括填充确定的除数。
示例
import torch
import torch.nn as nn
# 创建一个输入张量,形状为 [batch_size, channels, length]
input_tensor_1d = torch.tensor([[[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]]], dtype=torch.float32)
# 创建一个一维平均池化层,指定池化窗口大小为3
avg_pool_1d = nn.AvgPool1d(kernel_size=3, stride=2)
# 应用池化层
output_tensor_1d = avg_pool_1d(input_tensor_1d)
print(f"nn.AvgPool1d函数示例结果{output_tensor_1d.shape}")
# 创建一个输入张量,形状为 [batch_size, channels, height, width]
input_tensor_2d = torch.tensor([[[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]]], dtype=torch.float32)
# 创建一个二维平均池化层,指定池化窗口大小为2x2
avg_pool_2d = nn.AvgPool2d(kernel_size=2, stride=2)
# 应用池化层
output_tensor_2d = avg_pool_2d(input_tensor_2d)
print(f"nn.AvgPool2d函数示例结果{output_tensor_2d.shape}")
# 创建一个输入张量,形状为 [batch_size, channels, depth, height, width]
input_tensor_3d = torch.randn(1, 1, 3, 3, 3)
# 创建一个三维平均池化层,指定池化窗口大小为2x2x2
avg_pool_3d = nn.AvgPool3d(kernel_size=2, stride=2)
# 应用池化层
output_tensor_3d = avg_pool_3d(input_tensor_3d)
# 输出结果
print(f"nn.AvgPool3d函数示例结果{output_tensor_3d.shape}")
nn.BCELoss
原理
nn.BCELoss(Binary Cross Entropy Loss)是PyTorch中用于计算二元交叉熵损失的函数。二元交叉熵损失是衡量两个概率分布之间差异的一种常用方法,特别适用于二分类问题。在二分类问题中,模型通常输出一个介于0和1之间的概率值,表示样本属于正类的概率。而nn.BCELoss函数则计算模型输出概率与真实标签(0或1)之间的二元交叉熵损失。
原型
torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean')
参数说明:
weight (Tensor, 可选): 给每个样本或每个类别的损失分配不同的权重。
size_average (bool, 可选): 是否对损失进行平均。注意,在PyTorch的较新版本中,这个参数已被弃用,取而代之的是reduction参数。
reduce (bool, 可选): 是否对损失进行汇总。同样,这个参数也被reduction参数所取代。
reduction (str, 可选): 指定损失的计算方式。可选值有'none'(不进行汇总,返回每个样本的损失)、'mean'(返回损失的平均值,默认值)和'sum'(返回损失的总和)。
示例
import torch
import torch.nn as nn
# 假设模型输出已经通过Sigmoid函数,输出值在(0, 1)之间
model_output = torch.sigmoid(torch.tensor([-1.2, 0.4, 1.3, -0.5])) # 假设的模型输出
true_labels = torch.tensor([0., 1., 1., 0.]) # 真实标签
# 创建BCELoss实例
criterion = nn.BCELoss()
# 计算损失
loss = criterion(model_output, true_labels)
print(f"nn.BCELoss函数示例结果: {loss.item()}")
nn.BCEWithLogitsLoss
原理
nn.BCEWithLogitsLoss是nn.BCELoss的一个变体,它自动集成了Sigmoid激活函数。这意味着你不需要在模型输出层后显式地添加Sigmoid函数,nn.BCEWithLogitsLoss会为你处理这一点。这样做的好处是可以提高数值稳定性,因为Sigmoid激活函数和交叉熵损失的组合可以直接通过更稳定的数学运算来优化。
原型
torch.nn.BCEWithLogitsLoss(weight=None, size_average=None, reduce=None, reduction='mean', pos_weight=None)
除了weight、size_average、reduce和reduction参数外,nn.BCEWithLogitsLoss还接受一个pos_weight参数,用于为正类样本分配更高的权重,这在处理类别不平衡问题时特别有用。
示例
import torch
import torch.nn as nn
# 假设模型直接输出未经Sigmoid处理的logits
logits = torch.tensor([-1.2, 0.4, 1.3, -0.5]) # 假设的模型输出logits
true_labels = torch.tensor([0., 1., 1., 0.]) # 真实标签
# 创建BCEWithLogitsLoss实例
criterion = nn.BCEWithLogitsLoss()
# 计算损失
loss = criterion(logits, true_labels)
print(f"BCEWithLogitsLoss函数示例结果: {loss.item()}")
nn.BatchNorm1、2、3d
本部分为了更直观的对比 nn.BatchNorm1d、 nn.BatchNorm2d和 nn.BatchNorm3d三个函数,将其放在一起进行详解和示例。
原理
在深度学习中,批归一化(Batch Normalization, BN)是一种用于加速深度网络训练的技术,它可以减少内部协变量偏移,提高网络的稳定性和收敛速度。PyTorch提供了几种不同维度的批归一化层,以适应不同形状的数据输入。
批归一化的核心思想是在每个小批量数据上,对每个特征进行归一化处理,使其均值为0,方差为1。然后,通过可学习的参数(缩放因子γ和偏移量β)对归一化后的数据进行缩放和平移,以恢复数据的原始分布。这样做有助于减轻模型训练过程中的梯度消失或爆炸问题,并加快训练速度。
nn.BatchNorm1d:适用于一维数据,如全连接层的输出。
nn.BatchNorm2d:适用于二维数据,如卷积层的输出(特征图)。
nn.BatchNorm3d:适用于三维数据,如3D卷积层的输出。
原型
nn.BatchNorm1d:
torch.nn.BatchNorm1d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None)
参数说明:
num_features:每个样本的特征数量。
eps:为了数值稳定性加在分母上的值。
momentum:用于运行平均的计算和更新,默认为0.1。
affine:是否使用可学习的仿射参数γ和β。
track_running_stats:是否跟踪运行时的均值和方差,默认为True。
nn.BatchNorm2d
torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None)
参数说明:
参数与nn.BatchNorm1d相同,但适用于二维数据。
nn.BatchNorm3d
torch.nn.BatchNorm3d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None)
参数说明:
参数与nn.BatchNorm1d相同,但适用于三维数据。
示例
import torch
import torch.nn as nn
# 假设有一个全连接层的输出,特征数量为10,小批量大小为3
input_1d = torch.randn(3, 10)
# 创建一个BatchNorm1d层
bn_1d = nn.BatchNorm1d(num_features=10)
# 通过BatchNorm1d层
output_1d = bn_1d(input_1d)
print(f"nn.BatchNorm1d函数示例结果: {output_1d}")
# 假设有一个卷积层的输出,特征数量为20,每个特征图的大小为(3, 3),小批量大小为3
input_2d = torch.randn(3, 20, 3, 3)
# 创建一个BatchNorm2d层
bn_2d = nn.BatchNorm2d(num_features=20)
# 通过BatchNorm2d层
output_2d = bn_2d(input_2d)
print(f"nn.BatchNorm2d函数示例结果: {output_2d}")
# 假设有一个3D卷积层的输出,特征数量为20,每个特征体的大小为(2, 2, 2),小批量大小为3
input_3d = torch.randn(3, 20, 2, 2, 2)
# 创建一个BatchNorm3d层
bn_3d = nn.BatchNorm3d(num_features=20)
# 通过BatchNorm3d层
output_3d = bn_3d(input_3d)
print(f"nn.BatchNorm3d函数示例结果: {output_3d}")
nn.Bilinear
nn.Bilinear 是 PyTorch 提供的一个非常有用的模块,它允许我们实现双线性变换,从而捕获两个输入之间的相互作用。通过调整权重矩阵和偏置项,我们可以学习输入特征之间的复杂关系,并将其映射到输出空间中。在处理需要两个不同输入源交互的任务时,双线性变换是一个值得考虑的选择。
原理
双线性变换是一种特殊的线性变换,它涉及两个输入向量(或矩阵、张量)x1 和 x2。与传统的线性变换不同,双线性变换不仅考虑每个输入与权重矩阵的乘积,还考虑了两个输入之间的相互作用。
双线性变换的核心在于它如何捕获两个输入之间的相互作用。通过权重矩阵 A,双线性变换允许我们学习两个输入特征之间的复杂关系,并将其映射到输出空间中。
原型
torch.nn.Bilinear(in1_features, in2_features, out_features, bias=True, device=None, dtype=None)
参数说明:
in1_features:第一个输入的特征数量。
in2_features:第二个输入的特征数量。
out_features:输出的特征数量。
bias:是否添加偏置项,默认为True。
device:指定张量所在的设备(CPU或GPU),默认为None(即与输入张量相同的设备)。
dtype:指定张量的数据类型,默认为None(即与输入张量相同的数据类型)。
示例
import torch
import torch.nn as nn
# 定义双线性变换层
bilinear_layer = nn.Bilinear(in1_features=5, in2_features=4, out_features=3, bias=True)
# 创建输入数据
# 注意:nn.Bilinear期望的输入形状是(batch_size, *, in1_features)和(batch_size, *, in2_features)
# 这里我们使用*来表示其他可能的维度(例如序列长度、高度、宽度等),但在本例中我们只考虑batch_size
input1 = torch.randn(2, 1, 5) # 形状为(batch_size, *, in1_features),这里*是1(表示没有额外的维度)
input2 = torch.randn(2, 1, 4) # 形状为(batch_size, *, in2_features),同样*是1
# 应用双线性变换
# 注意:nn.Bilinear的输出形状是(batch_size, *, out_features),其中*与输入中的*相同
output = bilinear_layer(input1, input2)
# 输出结果的形状应为(batch_size, *, out_features),即(2, 1, 3)
print(f" nn.Bilinear函数示例结果形状: {output.shape}")
# 验证输出
print(f" nn.Bilinear函数示例结果: {output}")
小结
本文对a、b开头的17个函数进行了详解,下一篇将对nn.CELU、nn.CTCLoss、nn.ChannelShuffle、nn.CircularPad1d、nn.CircularPad2d、nn.CircularPad3d、nn.ConstantPad1d、nn.ConstantPad2d、nn.ConstantPad3d、nn.Container、nn.Conv1d、nn.Conv2d、nn.Conv3d、nn.ConvTranspose1d、nn.ConvTranspose2d、nn.ConvTranspose3d、nn.CosineEmbeddingLoss、nn.CosineSimilarity、nn.CrossEntropyLoss、nn.CrossMapLRN2d 20个函数进行详解和示例。