全连接层(线性连接层)-torch.nn.Linear-学习

全连接层(线性连接层)-torch.nn.Linear-学习

一、前言

虽然框架用起来爽是爽,但是探究一下其底层实现会更爽哈哈。有时知道怎么用,但是不知其所以然很恼火的。当然这并不是说我们要钻牛角尖,做理解底层实现这样的操作,前提不要耽搁我们的正常工作。

现在的社会真是快节奏,人变得浮躁,不愿再静下心去长时间学习,或自己愿意但身体不受控制学着学着搞别的去了。

学习最注重效率,效率的提升常伴随着方法的改进,时间的利用,资源的把握等方面。因此我们希望提高效率,尽快把手头工作做完,然后进一步学习自己求知的,深入的知识。不断充实自己,不断学习是我们的终极目标。

二、剖析

(一)、线性计算表达式

x先看一下官方对于该层的计算表达式定义:
y = x A T + b y=xA^T+b y=xAT+b

  • x x x的输入矩阵,形状为【batch_size,in_features】
  • A A A为权重矩阵,形状为【out_features,in_features】
  • b b b为偏置,形状为【out_features】

(二)、函数调用参数解析

首先我们看一下Linear类的构造函数的函数头部分,然后进一步分析

def __init__(self, in_features: int, out_features: int, bias: bool = True,device=None, dtype=None) -> None:
  • in_features

in_features是我们我们的输入的每个样本的特征数。这样好像不太好理解,我先说明一下,深度学习中,数据的输入往往是以批量的形式输入,那么一次会处理一个批次。

比如一次我要处理100个样本,前面说每个样本有in_features个特征,因此假设我们一个批次处理的数据量(样本个数)用batch_size表示,那么我们的输入矩阵(张量)的性状为[batch_size,in_features],表示这个矩阵有batch_size行,in_features列。

举个实际的例子吧,我现在要拟合一个3阶多项式,多项式形式为 y = a x 3 + b x 2 + c x + d y=ax^3+bx^2+cx+d y=ax3+bx2+cx+d。我将给出n个多项式和其多项式真实的值作为训练集的样本标签 [ a b c d ] \begin{bmatrix}a&b&c&d\end{bmatrix} [abcd]是我们的模型需要去学习的权重参数。我给出3个样本(batch_size=3)作为例子展示,矩阵如下:
[ 8 4 2 1 27 9 3 1 64 16 4 1 ] \begin{bmatrix} 8&4&2&1\\ 27&9&3&1\\ 64&16&4&1 \end{bmatrix} 827644916234111
上述矩阵每一行有4个元素 [ x 3 x 2 x 1 x 0 ] \begin{bmatrix}x^3&x^2&x^1&x^0\end{bmatrix} [x3x2x1x0]的值,对于不同的行(不同的多项式), x x x我分别取了 [ 2 3 4 ] T \begin{bmatrix}2&3&4\end{bmatrix}^T [234]T。每一行的4个元素,在深度学习中我们将其称为4个特征。基于上述分析,我们得到上面这个输入的形状为[3,4],表示输入了3个样本,每个样本有4个特征。

然后上述矩阵还原其实就是如下几个多项式:
y 1 = a ⋅ 2 3 + b ⋅ 2 2 + c ⋅ 2 + d ⋅ 1 y 2 = a ⋅ 3 3 + b ⋅ 3 2 + c ⋅ 3 + d ⋅ 1 y 3 = a ⋅ 4 3 + b ⋅ 4 2 + c ⋅ 4 + d ⋅ 1 \begin{aligned} y_1&=a\cdot 2^3+b\cdot 2^2+c\cdot 2+d\cdot1\\ y_2&=a\cdot 3^3+b\cdot 3^2+c\cdot 3+d\cdot1\\ y_3&=a\cdot 4^3+b\cdot 4^2+c\cdot 4+d\cdot1 \end{aligned} y1y2y3=a23+b22+c2+d1=a33+b32+c3+d1=a43+b42+c4+d1
假设真实权重矩阵 A r e a l = [ a b c d ] A_{real}=\begin{bmatrix}a&b&c&d\end{bmatrix} Areal=[abcd] [ 3 5 3.2 7 ] \begin{bmatrix}3&5&3.2&7\end{bmatrix} [353.27],那么我们将会得到上述输入样本的真实标签 [ y 1 y 2 y 3 ] \begin{bmatrix}y_1&y_2&y_3\end{bmatrix} [y1y2y3] [ 58.4000 143.6000 292.8000 ] T \begin{bmatrix}58.4000&143.6000&292.8000\end{bmatrix}^T [58.4000143.6000292.8000]T,上述标签由下面的程序计算得到:

import torch
from torch import nn

#创建一个全连接层
connected_layer = nn.Linear(in_features=4, out_features=1, bias=True)
#手动输入3个样本
input_data = torch.tensor(
    [
        [8, 4, 2, 1],
        [27, 9, 3, 1],
        [64, 16, 4, 1]
    ], dtype=torch.float32
)
#手动设置权重,即a,b,c,d的值
connected_layer.weight.data = torch.tensor(
    [
        [3, 5, 3.2, 7]
    ], dtype=torch.float32
)
#手动设置偏置b
connected_layer.bias.data = torch.tensor([1],dtype=torch.float32)
#获取输出结果
output = connected_layer(input_data)
print(output)
  • out_features

这个参数表示我们的数据通过全连接层计算,得到的结果会有几个特征。对于上面的例子,显然只会有1个特征,就是 y i y_i yi的最终值。

  • bias

这参数的汉译名为“偏置”,因此它就是我们计算表达式 y = x A T + b y=xA^T+b y=xAT+b中的b。

(三)、计算解析

上述例子真实标签是怎么得到的?我们按照如下步骤进行
y = x A T + b = [ 8 4 2 1 27 9 3 1 64 16 4 1 ] [ 3 5 3.2 7 ] + 1 = [ 58.4000 143.6000 292.8000 ] \begin{aligned} y&=xA^T+b\\ &=\begin{bmatrix}8&4&2&1\\27&9&3&1\\64&16&4&1\end{bmatrix}\begin{bmatrix}3\\5\\3.2\\7\end{bmatrix}+1\\ &=\begin{bmatrix}58.4000\\143.6000\\292.8000\end{bmatrix} \end{aligned} y=xAT+b= 827644916234111 353.27 +1= 58.4000143.6000292.8000
这就是全连接层的计算。

三、结语

我写这篇文章的原因是,我之前对权重矩阵的形状在Linear层的表示不是很理解。对于上面的例子,输入形状为【3x4】,在我的理解下,权重矩阵的形状应该为【4x1】因为这样刚好就可以直接进行矩阵乘积了,很方便。

我不明白之处在于为什么Linear的权重矩阵形状要设置为【1,4】,然后运算的时候先做一个转置变成【4x1】,再进行【3x4】【4x1】的矩阵乘积操作。

大家有想法的在评论区留言吧,我在网上暂时没找到解释得过去的答案!

  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值