diff --git a/README.md b/README.md index 21c8d9a..a4552e4 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ | | [16-Pytorch神经网络基础](notes/16-Pytorch神经网络基础.md) | [讲义](https://zh-v2.d2l.ai/chapter_deep-learning-computation/model-construction.html) | [Jupyter 代码](code/16-Pytorch神经网络基础) | | | | [17-使用和购买GPU](notes/17-使用和购买GPU.md) | [讲义](https://zh-v2.d2l.ai/chapter_deep-learning-computation/use-gpu.html) | [Jupyter 代码](code/17-使用和购买GPU.ipynb) | | | | [18-预测房价竞赛总结](notes/18-预测房价竞赛总结.md) | [讲义](https://courses.d2l.ai/zh-v2/assets/pdfs/part-1_1.pdf) | | | -| | [19-卷积层] | [讲义1](https://courses.d2l.ai/zh-v2/assets/pdfs/part-1_2.pdf) [2](https://courses.d2l.ai/zh-v2/assets/pdfs/part-1_3.pdf) | | | +| | [19-卷积层](notes/19-卷积层.md) | [讲义1](https://courses.d2l.ai/zh-v2/assets/pdfs/part-1_2.pdf) [2](https://courses.d2l.ai/zh-v2/assets/pdfs/part-1_3.pdf) | [Jupyter 代码](code/19-卷积层.ipynb) | | | | [20-填充和步幅](notes/20-填充和步幅.md) | [讲义](https://courses.d2l.ai/zh-v2/assets/pdfs/part-1_4.pdf) | [Jupyter 代码](code/20-填充和步幅.ipynb) | | | | [21-多输入输出通道](notes/21-多输入输出通道.md) | [讲义](https://courses.d2l.ai/zh-v2/assets/pdfs/part-1_5.pdf) | [Jupyter 代码](code/21-多输入输出通道.ipynb) | | | | [22-池化层](notes/22-池化层.md) | [讲义](https://courses.d2l.ai/zh-v2/assets/pdfs/part-1_6.pdf) | [Jupyter 代码](code/22-池化层.ipynb) | | diff --git "a/code/19-\345\215\267\347\247\257\345\261\202.ipynb" "b/code/19-\345\215\267\347\247\257\345\261\202.ipynb" new file mode 100644 index 0000000..d926e9a --- /dev/null +++ "b/code/19-\345\215\267\347\247\257\345\261\202.ipynb" @@ -0,0 +1,233 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 20, + "id": "a673b451", + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "from torch import nn\n", + "\n", + "def corr2d(X,K): #X为输入,K为核矩阵\n", + " h,w=K.shape #h得到K的行数,w得到K的列数\n", + " Y=torch.zeros((X.shape[0]-h+1,X.shape[1]-w+1)) #用0初始化输出矩阵Y\n", + " for i in range(Y.shape[0]): #卷积运算\n", + " for j in range(Y.shape[1]):\n", + " Y[i,j]=(X[i:i+h,j:j+w]*K).sum()\n", + " return Y" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "85e0f332", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[19., 25.],\n", + " [37., 43.]])" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#样例点测试\n", + "X=torch.tensor([[0,1,2],[3,4,5],[6,7,8]])\n", + "K=torch.tensor([[0,1],[2,3]])\n", + "corr2d(X,K)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "3b9a8de1", + "metadata": {}, + "outputs": [], + "source": [ + "#实现二维卷积层\n", + "class Conv2d(nn.Module):\n", + " def _init_(self,kernel_size):\n", + " super()._init_()\n", + " self.weight=nn.Parameter(torch.rand(kerner_size))\n", + " self.bias=nn.Parameter(torch.zeros(1))\n", + " def forward(self,x):\n", + " return corr2d(x,self.weight)+self.bias " + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "555f2489", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[1., 1., 0., 0., 0., 0., 1., 1.],\n", + " [1., 1., 0., 0., 0., 0., 1., 1.],\n", + " [1., 1., 0., 0., 0., 0., 1., 1.],\n", + " [1., 1., 0., 0., 0., 0., 1., 1.],\n", + " [1., 1., 0., 0., 0., 0., 1., 1.],\n", + " [1., 1., 0., 0., 0., 0., 1., 1.]])" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "X=torch.ones((6,8))\n", + "X[:,2:6]=0\n", + "X" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "859d2935", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[ 0., -1., 0., 0., 0., 1., 0.],\n", + " [ 0., -1., 0., 0., 0., 1., 0.],\n", + " [ 0., -1., 0., 0., 0., 1., 0.],\n", + " [ 0., -1., 0., 0., 0., 1., 0.],\n", + " [ 0., -1., 0., 0., 0., 1., 0.],\n", + " [ 0., -1., 0., 0., 0., 1., 0.]])" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "K=torch.tensor([[-1,1]]) #这个K只能检测垂直边缘\n", + "Y=corr2d(X,K)\n", + "Y" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "926cb124", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.]])" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "corr2d(X.t(),K)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "2eb05498", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "batch 2, loss 3.852\n", + "batch 4, loss 1.126\n", + "batch 6, loss 0.386\n", + "batch 8, loss 0.145\n", + "batch 10, loss 0.057\n" + ] + } + ], + "source": [ + "conv2d = nn.Conv2d(1, 1, kernel_size=(1, 2), bias=False)\n", + "\n", + "X = X.reshape((1, 1, 6, 8))\n", + "Y = Y.reshape((1, 1, 6, 7))\n", + "\n", + "for i in range(10):\n", + " Y_hat = conv2d(X)\n", + " l = (Y_hat - Y)**2\n", + " conv2d.zero_grad()\n", + " l.sum().backward()\n", + " conv2d.weight.data[:] -= 3e-2 * conv2d.weight.grad\n", + " if (i + 1) % 2 == 0:\n", + " print(f'batch {i+1}, loss {l.sum():.3f}')" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "a626a495", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[-1.0173, 0.9685]])" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "conv2d.weight.data.reshape((1, 2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5722b641", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:py36torch040]", + "language": "python", + "name": "conda-env-py36torch040-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git "a/notes/19-\345\215\267\347\247\257\345\261\202.md" "b/notes/19-\345\215\267\347\247\257\345\261\202.md" new file mode 100644 index 0000000..ea22422 --- /dev/null +++ "b/notes/19-\345\215\267\347\247\257\345\261\202.md" @@ -0,0 +1,137 @@ +## 19-卷积层 + +#### 本讲文字介绍部分请参考沐神在线书籍~:https://zh-v2.d2l.ai/chapter_convolutional-neural-networks/why-conv.html + +#### 代码 +```python +import torch +from torch import nn + +def corr2d(X,K): #X为输入,K为核矩阵 + h,w=K.shape #h得到K的行数,w得到K的列数 + Y=torch.zeros((X.shape[0]-h+1,X.shape[1]-w+1)) #用0初始化输出矩阵Y + for i in range(Y.shape[0]): #卷积运算 + for j in range(Y.shape[1]): + Y[i,j]=(X[i:i+h,j:j+w]*K).sum() + return Y +``` + + +```python +#样例点测试 +X=torch.tensor([[0,1,2],[3,4,5],[6,7,8]]) +K=torch.tensor([[0,1],[2,3]]) +corr2d(X,K) +``` + + + + + >>> tensor([[19., 25.], + [37., 43.]]) + + + + +```python +#实现二维卷积层 +class Conv2d(nn.Module): + def _init_(self,kernel_size): + super()._init_() + self.weight=nn.Parameter(torch.rand(kerner_size)) + self.bias=nn.Parameter(torch.zeros(1)) + def forward(self,x): + return corr2d(x,self.weight)+self.bias +``` + + +```python +X=torch.ones((6,8)) +X[:,2:6]=0 +X +``` + + + + + >>> tensor([[1., 1., 0., 0., 0., 0., 1., 1.], + [1., 1., 0., 0., 0., 0., 1., 1.], + [1., 1., 0., 0., 0., 0., 1., 1.], + [1., 1., 0., 0., 0., 0., 1., 1.], + [1., 1., 0., 0., 0., 0., 1., 1.], + [1., 1., 0., 0., 0., 0., 1., 1.]]) + + + + +```python +K=torch.tensor([[-1,1]]) #这个K只能检测垂直边缘 +Y=corr2d(X,K) +Y +``` + + + + + >>> tensor([[ 0., -1., 0., 0., 0., 1., 0.], + [ 0., -1., 0., 0., 0., 1., 0.], + [ 0., -1., 0., 0., 0., 1., 0.], + [ 0., -1., 0., 0., 0., 1., 0.], + [ 0., -1., 0., 0., 0., 1., 0.], + [ 0., -1., 0., 0., 0., 1., 0.]]) + + + + +```python +corr2d(X.t(),K) +``` + + + + + >>> tensor([[0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0.]]) + + + + +```python +conv2d = nn.Conv2d(1, 1, kernel_size=(1, 2), bias=False) + +X = X.reshape((1, 1, 6, 8)) +Y = Y.reshape((1, 1, 6, 7)) + +for i in range(10): + Y_hat = conv2d(X) + l = (Y_hat - Y)**2 + conv2d.zero_grad() + l.sum().backward() + conv2d.weight.data[:] -= 3e-2 * conv2d.weight.grad + if (i + 1) % 2 == 0: + print(f'batch {i+1}, loss {l.sum():.3f}') +``` + + >>> batch 2, loss 3.852 + batch 4, loss 1.126 + batch 6, loss 0.386 + batch 8, loss 0.145 + batch 10, loss 0.057 + + + +```python +conv2d.weight.data.reshape((1, 2)) +``` + + + + + >>> tensor([[-1.0173, 0.9685]]) +