为什么要使用 2**N 值以及如何选择正确的值?
Why should I use a 2**N value and how do I choose the right one?
我正在学习 building a neural network 的课程,但我很困惑为什么示例代码中的 linear_relu_stack 使用 512:
class NeuralNetwork(nn.Module):
def __init__(self):
super(NeuralNetwork, self).__init__()
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512),
nn.ReLU(),
nn.Linear(512, 512),
nn.ReLU(),
nn.Linear(512, 10),
nn.ReLU()
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
我开始四处搜索并看到许多使用 2**N
的各种值的 torch.nn.Linear
函数的示例,但我不清楚他们为什么使用 2 的幂以及他们如何选择使用哪个值。
虽然有未经证实的说法称 2 的幂有助于优化神经网络各个部分的性能,但它是 selecting/testing/finding 正确数量级的便捷方法,可用于各种 parameters/hyperparameters.
原因是硬件如何制造过程。在深度学习中,矩阵运算是浮点运算(FLOPs)的主要计算和来源。
CPU 中的单指令多数据 (SIMD) 操作以批量大小进行,批量大小为 2 的幂。如果您有兴趣,请考虑看看:
https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37631.pdf
对于 GPU:
https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html
Memory allocated through the CUDA Runtime API, such as via
cudaMalloc(), is guaranteed to be aligned to at least 256 bytes.
Therefore, choosing sensible thread block sizes, such as multiples of
the warp size (i.e., 32 on current GPUs), facilitates memory accesses
by warps that are properly aligned. (Consider what would happen to the
memory addresses accessed by the second, third, and subsequent thread
blocks if the thread block size was not a multiple of warp size, for
example.)
这意味着 32 的任何倍数都会优化内存访问,从而在您使用 gpu 时优化处理速度。
关于正确的值,金字塔形通常效果更好,因为随着你深入,神经网络倾向于创建转换后数据的内部表示,以预期的层次结构,因此,金字塔形。所以一个很好的猜测是当你接近输出时在每一层使用减少数量的神经元,例如:
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512),
nn.ReLU(),
nn.Linear(512, 128),
nn.ReLU(),
nn.Linear(128, 10),
nn.ReLU()
)
但是没有通用规则,您可以找到有关如何为神经网络找到最佳超参数的整个研究领域(如神经架构搜索)。
您可以在这里查看一些更深入的信息:
我正在学习 building a neural network 的课程,但我很困惑为什么示例代码中的 linear_relu_stack 使用 512:
class NeuralNetwork(nn.Module):
def __init__(self):
super(NeuralNetwork, self).__init__()
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512),
nn.ReLU(),
nn.Linear(512, 512),
nn.ReLU(),
nn.Linear(512, 10),
nn.ReLU()
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
我开始四处搜索并看到许多使用 2**N
的各种值的 torch.nn.Linear
函数的示例,但我不清楚他们为什么使用 2 的幂以及他们如何选择使用哪个值。
虽然有未经证实的说法称 2 的幂有助于优化神经网络各个部分的性能,但它是 selecting/testing/finding 正确数量级的便捷方法,可用于各种 parameters/hyperparameters.
原因是硬件如何制造过程。在深度学习中,矩阵运算是浮点运算(FLOPs)的主要计算和来源。
CPU 中的单指令多数据 (SIMD) 操作以批量大小进行,批量大小为 2 的幂。如果您有兴趣,请考虑看看:
https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37631.pdf
对于 GPU:
https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html
Memory allocated through the CUDA Runtime API, such as via cudaMalloc(), is guaranteed to be aligned to at least 256 bytes. Therefore, choosing sensible thread block sizes, such as multiples of the warp size (i.e., 32 on current GPUs), facilitates memory accesses by warps that are properly aligned. (Consider what would happen to the memory addresses accessed by the second, third, and subsequent thread blocks if the thread block size was not a multiple of warp size, for example.)
这意味着 32 的任何倍数都会优化内存访问,从而在您使用 gpu 时优化处理速度。
关于正确的值,金字塔形通常效果更好,因为随着你深入,神经网络倾向于创建转换后数据的内部表示,以预期的层次结构,因此,金字塔形。所以一个很好的猜测是当你接近输出时在每一层使用减少数量的神经元,例如:
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512),
nn.ReLU(),
nn.Linear(512, 128),
nn.ReLU(),
nn.Linear(128, 10),
nn.ReLU()
)
但是没有通用规则,您可以找到有关如何为神经网络找到最佳超参数的整个研究领域(如神经架构搜索)。
您可以在这里查看一些更深入的信息: