<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Decay on Chang Luo</title>
		<link>https://www.luochang.ink/tags/decay/</link>
		<description>Recent content in Decay on Chang Luo</description>
		<generator>Hugo</generator>
		<language>zh-CN</language>
		
		
		
		
			<lastBuildDate>Sun, 07 Jul 2024 00:00:00 +0000</lastBuildDate>
		
			<atom:link href="https://www.luochang.ink/tags/decay/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>像搭积木一样搭神经网络</title>
				<link>https://www.luochang.ink/posts/dl_tricks/</link>
				<pubDate>Sun, 07 Jul 2024 00:00:00 +0000</pubDate>
				<guid>https://www.luochang.ink/posts/dl_tricks/</guid>
				<description>&lt;blockquote&gt;&#xA;&lt;p&gt;搭积木的时候，需要将不同类型的积木搭在一起：门框、窗子、走廊、屋顶。对每一种类型的积木，又有多种变体可供选择。比如，屋顶可以用文艺复兴风格，也可以用中式庭园风格。神经网络也是，学神经网络，本质上就是认识各种各样“积木”的过程。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;GitHub 项目地址：&lt;a href=&#34;https://github.com/luochang212/dl-tricks/blob/main/note.ipynb&#34; target=&#34;_blank&#34;&gt;dl-tricks/note.ipynb&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;一必要组件&#34;&gt;一、必要组件&lt;/h3&gt;&#xA;&lt;h4 id=&#34;11-从-mlp-说起&#34;&gt;1.1 从 MLP 说起&lt;/h4&gt;&#xA;&lt;p&gt;我们从最简单的深度神经网络 &lt;strong&gt;多层感知机&lt;/strong&gt; (MLP) 开始说起。麻雀虽小，五脏俱全。了解数据如何在 MLP 中流动，就能大致勾勒一个神经网络的 &lt;strong&gt;必要组件&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;下图是一个 4 层感知机，左边是特征，右边是标签。训练开始时，样本数据先从左到右做 &lt;strong&gt;正向传播&lt;/strong&gt;。待数据流到右侧，用 &lt;strong&gt;损失函数&lt;/strong&gt; 计算损失。此时损失是一个标量，而最后一层的节点权重 \( W \) 是一个矩阵，标量对矩阵的偏导是矩阵。&lt;strong&gt;优化器&lt;/strong&gt; 会用大小合适的梯度矩阵，沿负梯度方向逐层反向更新权重 \( W \)。这样下一 &lt;strong&gt;批量&lt;/strong&gt; (batch) 数据进入网络时，正好能用上一轮更新后的参数做正向传播。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://www.luochang.ink/img/mlp_network.png&#34; alt=&#34;image&#34;&gt;&lt;/p&gt;&#xA;&lt;h4 id=&#34;12-dataloader&#34;&gt;1.2 DataLoader&lt;/h4&gt;&#xA;&lt;p&gt;样本是有限的，为了让模型获得最强性能，必须榨干每个样本的价值。&lt;/p&gt;&#xA;&lt;p&gt;因此在训练中，一个样本往往要复用多次。&lt;code&gt;DataLoader&lt;/code&gt; 就在做这样一件事。它把数据编排成一个个批量，并构建一个迭代器。每次调用它，会返回一个从第一个批量开始遍历的迭代器。这个特性使得复用样本变得更加方便。&lt;/p&gt;&#xA;&lt;p&gt;原生的 PyTorch &lt;code&gt;DataLoader&lt;/code&gt; 很复杂，让我们来实现一个野生 &lt;code&gt;DataLoader&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;import math&#xA;import torch&#xA;&#xA;class DataLoader:&#xA;    def __init__(self, data: list, batch_size: int):&#xA;        self.i = 0&#xA;        self.batch_size = batch_size&#xA;        self.batch_num = math.ceil(len(data) / batch_size)&#xA;        self._data = self.gen_batch(data)&#xA;&#xA;    def gen_batch(self, data):&#xA;        lst = []&#xA;        s = self.batch_size&#xA;        for i in range(self.batch_num):&#xA;            start, end = s * i, s * (i + 1)&#xA;            X = torch.tensor([e[0] for e in data[start:end]])&#xA;            y = torch.tensor([e[1] for e in data[start:end]])&#xA;            lst.append((X, y))&#xA;&#xA;        return lst&#xA;&#xA;    def __iter__(self):&#xA;        self.i = 0&#xA;        return self&#xA;&#xA;    def __next__(self):&#xA;        if self.i &amp;lt; len(self._data):&#xA;            self.i += 1&#xA;            return self._data[self.i - 1]&#xA;        else:&#xA;            raise StopIteration&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;假设有 2560 个样本。计划分成 10 个批量，则每批量有 256 个样本。我们可以用上面的野生 &lt;code&gt;DataLoader&lt;/code&gt; 加载这些样本。&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
