通过Python交互式控制台理解Conv1d
<p>以前在语音合成项目第一次接触PyTorch中的<code>Conv1d</code>函数时,作为一个初学者,我对它的参数和工作机制感到很困惑。<br>原本以为既然是1维卷积,那输入输出应该都是简单的1维张量。然而实际上,输入必须是一个3维张量,这让我颇感意外。<br>
后来因为工作缘故,我有一段时间没接触深度学习了。后来再次遇到<code>Conv1d</code>函数时,我又陷入了同样的困惑。<br>
因此,我决定写下自己的理解过程,帮助可能遇到类似情况的读者(包括未来的我自己)。</p>
<p>本文使用的工具版本是Python 3.13.3,PyTorch 2.7.1。</p>
<p>Python的版本号可用<code>python -V</code>命令确认。</p>
<pre><code>> python -V
Python 3.13.3
</code></pre>
<p>PyTorch的版本号可用<code>pip show torch</code>命令确认。</p>
<pre><code>> pip show torch
Name: torch
Version: 2.7.1
...
</code></pre>
<p>或者也可以像下面这样进入Python交互式控制台确认。</p>
<pre><code class="language-python">> python
Python 3.13.3 (tags/v3.13.3:6280bb5, Apr8 2025, 14:47:33) on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> torch.__version__
'2.7.1+cpu'
</code></pre>
<p>理解<code>Conv1d</code>输入输出形状的关键在于,我们必须考虑深度学习中的批次(batch)和通道(channel)概念。<br>
下面通过在Python交互式控制台里一步步执行代码来理解这一点。</p>
<h1 id="第一步创建conv1d实例">第一步:创建Conv1d实例</h1>
<p>使用<code>Conv1d</code>首先需要创建一个实例。实例化时需要指定三个主要参数:</p>
<ul>
<li><strong>in_channels</strong>:输入通道数。例如,1表示单声道音频,2表示立体声音频。</li>
<li><strong>out_channels</strong>:卷积后的输出通道数,代表卷积滤波器的数量。</li>
<li><strong>kernel_size</strong>:卷积滤波器的大小。</li>
</ul>
<p>创建一个具有2个输入通道、3个输出通道和滤波器大小为5的Conv1d实例:</p>
<pre><code class="language-python">>>> from torch import nn
>>> conv1d = nn.Conv1d(2, 3, 5)
</code></pre>
<h1 id="第二步查看权重和偏置">第二步:查看权重和偏置</h1>
<p>创建实例时,卷积操作使用的权重(weight)和偏置(bias)会自动初始化。<br>
在机器学习过程中,这些值会在训练过程中被逐步优化。</p>
<pre><code class="language-python">>>> conv1d.weight.shape
torch.Size()
>>> conv1d.weight
Parameter containing:
tensor([[[ 0.2076,0.1669, -0.0984,0.0040, -0.0094],
[-0.0277, -0.0257, -0.3107,0.2883,0.2560]],
[[ 0.0501, -0.2257,0.0464, -0.0605,0.1463],
[-0.1195,0.1820,0.0764,0.2922, -0.2718]],
[[ 0.2699, -0.2734,0.1698,0.2720, -0.2554],
[-0.0706, -0.2028, -0.2554, -0.1495,0.2460]]], requires_grad=True)
>>> conv1d.bias
Parameter containing:
tensor([-0.1664, -0.0393,0.2074], requires_grad=True)
</code></pre>
<ul>
<li><code>conv1d.weight</code>表示每个滤波器的权重,形状为<code>(输出通道数, 输入通道数, 滤波器大小)</code></li>
<li><code>conv1d.bias</code>表示每个滤波器的偏置,形状为<code>(输出通道数)</code></li>
</ul>
<h1 id="第三步准备输入数据">第三步:准备输入数据</h1>
<p><code>Conv1d</code>的输入数据必须是3维张量:</p>
<ul>
<li>第1维:批次大小(<code>batch_size</code>),表示一次处理的数据样本数量</li>
<li>第2维:输入通道数,必须与创建<code>Conv1d</code>实例时指定的<code>in_channels</code>一致</li>
<li>第3维:单个数据样本的长度。对于音频数据,通常是帧数</li>
</ul>
<pre><code class="language-python">>>> x = torch.rand(4, 2, 6)# 随机数据:批次大小4,2个输入通道,长度6
>>> x
tensor([[,
],
[,
],
[,
],
[,
]])
</code></pre>
<h1 id="第四步执行卷积操作">第四步:执行卷积操作</h1>
<p>将输入数据<code>x</code>传递给<code>conv1d</code>并查看结果:</p>
<pre><code class="language-python">>>> y = conv1d(x)
>>> y.shape
torch.Size()
>>> y
tensor([[[ 0.1683,0.1969],
[-0.2416,0.1589],
[ 0.3856, -0.0863]],
[[ 0.0034,0.1147],
[-0.0358, -0.2050],
[ 0.2556,0.0671]],
[[ 0.0630, -0.0035],
[ 0.0246,0.0918],
[-0.1203,0.1590]],
[[ 0.2665,0.0337],
[-0.1590,0.1789],
[ 0.0974,0.2275]]], grad_fn=<ConvolutionBackward0>)
</code></pre>
<p>输出<code>y</code>是一个3维张量,形状为<code>(批次大小, 输出通道数, 输出长度)</code>。</p>
<h1 id="第五步理解计算过程">第五步:理解计算过程</h1>
<p>卷积操作遵循以下原则:</p>
<ol>
<li>滤波器在输入数据上滑动</li>
<li>计算元素乘积的和</li>
<li>加上偏置</li>
</ol>
<p>每个输出元素的计算公式为:</p>
<pre><code class="language-python">y[批次索引, 输出通道索引, 数据位置] =
sum(x[批次索引, 输入通道0, (数据位置):(数据位置+滤波器大小)] @ conv1d.weight[输出通道索引, 输入通道0]) +
sum(x[批次索引, 输入通道1, (数据位置):(数据位置+滤波器大小)] @ conv1d.weight[输出通道索引, 输入通道1]) +
... +
conv1d.bias[输出通道索引]
</code></pre>
<p>其中<code>@</code>表示点积操作,<code>A @ B</code>等同于<code>A.dot(B)</code>。</p>
<p>输出长度可以通过以下公式计算:</p>
<pre><code class="language-python">输出长度 = (输入长度 - 滤波器大小 + 1)
</code></pre>
<p>例如,我们可以验证<code>y</code>的计算:</p>
<pre><code class="language-python">>>> y# 第0个数据样本,第0个输出通道,第0个输出数据位置
tensor(0.1683, grad_fn=<SelectBackward0>)
>>> x @ conv1d.weight + x @ conv1d.weight + conv1d.bias
tensor(0.1683, grad_fn=<AddBackward0>)
</code></pre>
<p>同样,我们可以计算<code>y</code>:</p>
<pre><code class="language-python">>>> y# 第0个数据样本,第0个输出通道,第1个输出数据位置
tensor(0.1969, grad_fn=<SelectBackward0>)
>>> x @ conv1d.weight + x @ conv1d.weight + conv1d.bias
tensor(0.1969, grad_fn=<AddBackward0>)
</code></pre>
<p>如上所示,<code>Conv1d</code>通过对输入数据<code>x</code>进行卷积操作生成新的特征量<code>y</code>。<br>
特征量<code>y</code>可用于音频识别、自然语言处理等各种1维(单通道或多通道)数据的处理任务。</p>
<h1 id="总结">总结</h1>
<ol>
<li>输入必须是3维张量:(批次大小, 输入通道数, 数据长度)</li>
<li>输出也是3维张量:(批次大小, 输出通道数, 输出长度)</li>
<li>输出长度由公式<code>输入长度 - 滤波器大小 + 1</code>决定</li>
<li>每个输出元素是输入数据与滤波器权重的点积加上偏置</li>
</ol><br><br>
来源:https://www.cnblogs.com/xiaozhu-zhixiang/p/19007927/250727-pytorch-conv1d
頁:
[1]