ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

常用网络层:Linear、Conv、RNN、Embedding、Transformer

常用网络层:Linear、Conv、RNN、Embedding、Transformer 1. 网络层的本质把一种 变成另一种对于网络层而言, 全部都是nn.这样类别的。它们是存在参数的, 是拥有特定情况的, 是具备状态的, 并且还能够被以递归方式注册到模型里面。但从计算角度看层只有一句话输入 输出新的 。各自的区别是: 每一层对于“看数据”这件事, 所采用的方式存在差异。去看最后那一维度, Conv采用看局部窗口的方式, RNN/LSTM采用看时间顺序的方式, 进行查表运算, 开展做全局注意力的操作。2. 最朴素也最常用有这样一种层, 也就是全连接层, 它对于图片、文本以及时间并不予以关注, 它所关注的仅仅是最后那一维度。输入最后一维是 输出最后一维就是 。其它维度保持不变。layer nn.Linear(128, 64) y layer(x) # x: (..., 128) - y: (..., 64)的 层很薄。初始化时创建两个 和 bias。的形状是 x 。 时调用 F.。确切而言真正的重活它并不在类里面, 而是存在于和那更为底层的ATen算子里。# 源码主线简化 self.weight Parameter(torch.empty(out_features, in_features)) self.bias Parameter(torch.empty(out_features)) forward(x) - F.linear(x, weight, bias)抓取关键要点: 并非是“压平层” , 它仅仅对最后那一维度进行处理 , 是否如此呢 , 这取决于你自己去做出决定。3. 从整张图里抠局部模式图片有空间结构。相邻像素更相关。 就是利用这个特点。那种在H和W这两个方向滑动的卷积核, 就如同是一个能只看一块局部区域的小窗口, 并且它每次都有着上述这般的操作。一组卷积核产生一组输出通道。 越大提取的特征种类越多。conv nn.Conv2d(in_channels3, out_channels32, kernel_size3, padding1) y conv(x) # x: (N, 3, H, W) - y: (N, 32, H, W)从 继承而来, 在进行初始化操作的时候, 会将 , 以及 , 还有 , 再加上 , 统统转变为二维的 tuple。不直接计算卷积。它进入 再调用 F.。如果 不是 zeros会先 F.pad再 。# 源码主线简化. - _pair( / / )(x) - (x, , bias) - F.(...)将重点捕捉住: 其图像张量依照默认情况而言是 NCHW, 并非 NHWC。倘若形状出现错误, 那么卷积必然会产生报错现象。4. RNN / LSTM让模型记住前面发生了什么具有先后顺序的是序列数据, 今天的温度同昨天存在关联, 一个词与前面的词有着关系。RNN的思路径直得很: 于每个时间步, 都会去接收当下的输入x_t, 并且还会去接收上一步的state。相比于RNN, LSTM多了一个cell state, 并且其通过四个门来对记忆记录予以控制, 这四个门分别控制着记忆的写入, 支配着记忆的遗忘, 运行于记忆之输出环节。将 y 以及 (h, c) 通过长短期记忆网络LSTM作用于 x 得到, 这里的 x 是批次, 序列形式的。LSTM 继承自 。 负责参数管理、、、。LSTM每层的input-权重是4乘以, 由于它得同时为四个门提供服务, 所以是这样。会对输入维度展开检查, 着手准备 h0 和 c0, 随后把 flat 交付给底层的 RNN 算子, 在 GPU 上会尽可能选取 cuDNN 快路径运行。# 源码主线简化 RNNBase.__init__ - 创建每层每方向的门控权重 LSTM.forward - 检查 input/hx/cx - 底层 LSTM 算子注重关键要点: 等于真值, 仅仅去改变输入的批处理位置, 而不改变初始隐藏状态和初始细胞状态的形状准则。5. 把离散 ID 变成连续向量商品编号、用户编号、词编号, 其本质仅仅是编号而已。编号相互之间不存在天然之大小关联。做的事很简单维护一张可训练表。输入 ID取出对应行。参与训练之际, 反向传播会对这些向量予以更新, 使得相似对象于向量空间当中更为接近。emb nn.Embedding(num_embeddings50000, embedding_dim768) y emb(token_ids) # token_ids: (batch, seq) - y: (batch, seq, 768)内部保存一个 形状是 x 。进去到F., 输入所需要的必定是 又或者是 , 鉴于它属于索引这一范畴, 并非是连续特征, 是这样子的要求的。对应的行不参与梯度更新适合处理补齐 token。# 源码主线简化 self.weight Parameter(num_embeddings, embedding_dim) forward(input_ids) - F.embedding(input_ids, weight, padding_idx, ...)着重把握关键之处: 不具备对文字的理解能力。它仅仅是针对从ID到向量的映射进行学习。语义是源自训练目标的。6. 让序列里的每个位置互相看见RNN 是一步一步读。 是同时看全局。每一个 token 都会生成 Q、K、V, Q 是用于提问的, K 是用来进行匹配的, V 是那些被汇总起来的信息。多头机制使模型能从数个方位聚焦于序列, 接着运用其进行逐个位置的转变。block nn.TransformerEncoderLayer(d_model768, nhead12, batch_firstTrue) y block(x) # x: (batch, seq, 768)nn. 是参考实现。它会组装 和 。内部通常包含 、两个 、、。在可能时会使用的优化实现。# 源码主线简化 Transformer.__init__ - EncoderLayer / DecoderLayer EncoderLayer.forward - self_attn - Linear - Dropout - LayerNorm着重抓住重点之处: 对于新出现的项目所提出的建议, 需要明确地书写为等于真, 千万不要使得序列以及批次的位置仅仅依靠记忆来确定。7. 五类层怎么选选层不是追热点。先看输入数据结构。用向量, 用Conv表示图片, 先处理离散ID, 短序列能够应用LSTM, 长序列以及全局依赖需优先处理。8. 从 到底层算子一条源码主线上一章讲过 nn.。现在把它和具体层连起来。model(x) 会引发。 处置 hook、形态以及上下文, 接着步入。接下来 model(x) 会触动。 应对 hook、状况与语境, 随后踏入。再去进行API的调用, 之后API会朝着ATen、CUDA、cuDNN等后端实现的方向进入。读源码的顺序第一步看 保存了什么参数。第二步看 调了哪个 。第三步看 背后对应哪个底层算子。第四步, 接着去看设备后端, 其中包含CPU, 还有CUDA, 以及cuDNN, 还有MPS, 另外还有ROCm。9. 常见坑先查 shape再查源码绝大多数网络层报错第一原因都是 shape 不匹配。进行模型编写之际, 切勿凭借猜测。每当历经一个关键层级, 便开展一次形状打印。def hook(name): def fn(module, inputs, output): print(name, output.shape if hasattr(output, shape) else type(output)) return fn model.layer.register_forward_hook(hook(layer))工程习惯复杂模型不要一口气写完。先跑通一层再堆下一层。10. 总结这种说法是不正确的, LSTM不是五个孤立的API , 它并非是一套特征变换语言。它们各自所处理的究竟是什么样的结构, 它们各自会改变成何种形状, 源码最终会被调到什么地方, 这些才是你真正需要记住的。一句话带走改换维度, Conv 抓取局部, LSTM 记录历史, 查询向量, 建立全局关系。接着下一章展开: 激活函数, 归一化, 有一些层承担着表达的职责, 训练的稳定性要依靠它们来维持住。
返回列表