转载:https://blog.csdn.net/weixin_38145317/article/details/111270687
官方文档:
https://pytorch.org/docs/stable/generated/torch.nn.Linear.html?highlight=linear#torch.nn.Linear
CLASS torch.nn.Linear(in_features, out_features, bias=True, device=None, dtype=None)
Applies a linear transformation to the incoming data将线性转换应用于传入数据:
This module supports TensorFloat32.该模块支持TensorFloat32。
On certain ROCm devices, when using float16 inputs this module will use different precision for backward.在某些ROCM设备上,使用Float16输入时,该模块将使用不同的精度向后。
参数:
-
in_features (int) – size of each input sample 每个输入样本的大小
-
out_features (int) – size of each output sample 每个输出样本的大小
-
bias (bool) – If set to
False
, the layer will not learn an additive bias. Default:True如果设置为false,则该层将不会学习添加bias。 默认值:true
Input:(*, ) : *代表任何维度,包括none和
(输入的特征)
Output:(*, ) : 除最后一个维度以外的所有尺寸都与输入的相同,
(输出的特征)
例子:
import torch.nn as nn
import torch
m = nn.Linear(20, 30)
input = torch.randn(128, 20)
output = m(input)
print(output.size())
m = nn.Linear(20, 10)
input = torch.randn(112, 128, 20)
output = m(input)
print(output.size())
结果:
如上图所示,输出size的最后一维大小与nn.Linear设置的out_features保持一致,其余维度与输入的维度保持一致。
全连接层定义
全连接层(fully connected layers, FC)在整个卷积神经网络中起到”分类器“的作用。如果说卷积层,池化层和激活函数层和激活函数层等操作是将原始数据映射到隐层特征空间的话,全连接层则起到将学到的”分布式特征表示“映射到样本标记空间的作用。在实际使用中,全连接层可由卷积操作实现;
对前层是全连接的全连接层可以转化为卷积核为1*1的卷积,而前层是卷积层的全连接层可以转化为卷积核为h*w的全局卷积,h和w分别为前层卷积结果的高和宽。
全连接的核心操作就是矩阵向量乘积 y= Wx
本质就是由一个特征空间线性变换到另一个特征空间。目标空间中的任一维——也就是隐层的一个cell——都认为会受到源空间的每一维的影响。不考虑严谨,可以说,目标向量是源向量的加权和。
在CNN中,全连接常出现在最后几层,用于对于前面设计的特征做加权和,比如mnist,前面的卷积和池化相当于做特征工程,后面的全连接相当于做特征加权。(卷积相当于全连接的有意弱化,按照局部视野的启发,把局部之外的弱影响直接抹为0影响,还做了一点强制,不同的局部所使用的参数居然一致。弱化使参数变少,节省计算量,又专攻局部不贪多求全,强制进一步减少参数。在RNN中,全连接用来把embedding空间拉到隐层空间,把隐层空间转回label空间等。
在pytorch中的nn.Linear表示线性变换,官方文档给出的数学计算公式是
其中x是输入,A是权值,b是偏置,y是输出,卷积神经网络中的全连接层需要调用nn.Linear就可以实现,其源代码为
def __init__(self, in_features: int, out_features: int, bias: bool = True,
device=None, dtype=None) -> None:
factory_kwargs = {'device': device, 'dtype': dtype}
super().__init__()
self.in_features = in_features
self.out_features = out_features
self.weight = Parameter(torch.empty((out_features, in_features), **factory_kwargs))
if bias:
self.bias = Parameter(torch.empty(out_features, **factory_kwargs))
else:
self.register_parameter('bias', None)
self.reset_parameters()
分析:output.size()=矩阵size(128,20)*矩阵size(20,30)=(128,30)
线性变换不改变输入矩阵x的行数,仅改变列数
例子:假设输入x,权重矩阵A,偏置b分别为:
备注:这里需要注意下,偏置b的加法与普通的矩阵加法不太一样,这里只需要保持偏置b的列数与输出y的列数相同即可,对应位置元素相加,每一行都是加的同样的偏置