|
@@ -0,0 +1,570 @@
|
|
|
|
|
+{
|
|
|
|
|
+ "cells": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": null,
|
|
|
|
|
+ "id": "a11d642b",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "name": "stdout",
|
|
|
|
|
+ "output_type": "stream",
|
|
|
|
|
+ "text": [
|
|
|
|
|
+ "输入图片: torch.Size([1, 1, 32, 32])\n",
|
|
|
|
|
+ "卷积核权重: torch.Size([8, 1, 3, 3])\n",
|
|
|
|
|
+ "输出特征图: torch.Size([1, 8, 30, 30])\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "import torch.nn as nn\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 1 张 灰度图,每张大小 32x32。\n",
|
|
|
|
|
+ "# N C H W\n",
|
|
|
|
|
+ "images = torch.randn(1, 1, 32, 32)\n",
|
|
|
|
|
+ "# 8 个卷积核,每个卷积核看 1 个输入通道,常见的卷积核大小是 3x3 或 5x5。\n",
|
|
|
|
|
+ "#参数:(输入通道数, 输出通道数, 卷积核大小)\n",
|
|
|
|
|
+ "conv = nn.Conv2d(1, 8, kernel_size=3) #一层卷积\n",
|
|
|
|
|
+ "features = conv(images)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "print(\"输入图片:\", images.shape) #[1, 1, 32, 32]\n",
|
|
|
|
|
+ "print(\"卷积核权重:\", conv.weight.shape) # [8, 1, 3, 3] 3*3*8+8\n",
|
|
|
|
|
+ "print(\"输出特征图:\", features.shape) # [1, 8, 30, 30]"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": 2,
|
|
|
|
|
+ "id": "975e93b9",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "name": "stdout",
|
|
|
|
|
+ "output_type": "stream",
|
|
|
|
|
+ "text": [
|
|
|
|
|
+ "全连接参数量: 1200010\n",
|
|
|
|
|
+ "卷积层参数量: 28\n",
|
|
|
|
|
+ "结论: 卷积层靠局部连接和权重共享,把参数量明显压小。\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "from torch import nn\n",
|
|
|
|
|
+ "# 1. 超参数写死:只比较参数量,不做训练。\n",
|
|
|
|
|
+ "image_channels = 3\n",
|
|
|
|
|
+ "image_height = 200\n",
|
|
|
|
|
+ "image_width = 200\n",
|
|
|
|
|
+ "class_count = 10\n",
|
|
|
|
|
+ "# 2. 全连接层:需要把整张图片拍平成一个超长向量。\n",
|
|
|
|
|
+ "full_connection = nn.Linear(image_channels * image_height * image_width,\n",
|
|
|
|
|
+ "class_count)\n",
|
|
|
|
|
+ "full_connection_params = sum(param.numel() for param in\n",
|
|
|
|
|
+ "full_connection.parameters())\n",
|
|
|
|
|
+ "# 3. 卷积层:只看 3x3 局部窗口,参数量和图片宽高无关。\n",
|
|
|
|
|
+ "convolution = nn.Conv2d(in_channels=3, out_channels=1, kernel_size=3)\n",
|
|
|
|
|
+ "convolution_params = sum(param.numel() for param in convolution.parameters())\n",
|
|
|
|
|
+ "# 4. 打印对比结果。\n",
|
|
|
|
|
+ "print(\"全连接参数量:\", full_connection_params)\n",
|
|
|
|
|
+ "print(\"卷积层参数量:\", convolution_params)\n",
|
|
|
|
|
+ "print(\"结论: 卷积层靠局部连接和权重共享,把参数量明显压小。\")\n",
|
|
|
|
|
+ "\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": 3,
|
|
|
|
|
+ "id": "859b6fff",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "name": "stdout",
|
|
|
|
|
+ "output_type": "stream",
|
|
|
|
|
+ "text": [
|
|
|
|
|
+ "卷积参数:\n",
|
|
|
|
|
+ " weight 数量: 9\n",
|
|
|
|
|
+ " bias 数量: 1\n",
|
|
|
|
|
+ " 输出形状: torch.Size([1, 1, 2, 2])\n",
|
|
|
|
|
+ "全连接参数:\n",
|
|
|
|
|
+ " weight 数量: 64\n",
|
|
|
|
|
+ " bias 数量: 4\n",
|
|
|
|
|
+ " 输出形状: torch.Size([4])\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "from torch import nn\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 1. 模拟一张 1 通道 4x4 ‘假图片’。\n",
|
|
|
|
|
+ "image = torch.randn(1, 1, 4, 4)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 2. 卷积层:3x3 卷积核有 9 个权重,再加 1 个 bias。\n",
|
|
|
|
|
+ "conv = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3)\n",
|
|
|
|
|
+ "conv_out = conv(image)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "print(\"卷积参数:\")\n",
|
|
|
|
|
+ "print(\" weight 数量:\", conv.weight.numel())\n",
|
|
|
|
|
+ "print(\" bias 数量:\", conv.bias.numel())\n",
|
|
|
|
|
+ "print(\" 输出形状:\", conv_out.shape)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 3. 全连接层:把 4x4 图片拍平成 16 维,再输出 4 维。\n",
|
|
|
|
|
+ "flat_image = torch.flatten(image)\n",
|
|
|
|
|
+ "fc = nn.Linear(16, 4)\n",
|
|
|
|
|
+ "fc_out = fc(flat_image)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "print(\"全连接参数:\")\n",
|
|
|
|
|
+ "print(\" weight 数量:\", fc.weight.numel())\n",
|
|
|
|
|
+ "print(\" bias 数量:\", fc.bias.numel())\n",
|
|
|
|
|
+ "print(\" 输出形状:\", fc_out.shape)"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": null,
|
|
|
|
|
+ "id": "f90e3a5d",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "from torch import nn\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 1. 模拟一张 1 通道 4x4 ‘假图片’。\n",
|
|
|
|
|
+ "image = torch.randn(1, 1, 4, 4)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 2. 卷积层:5*5 卷积核。\n",
|
|
|
|
|
+ "conv = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=5)\n",
|
|
|
|
|
+ "conv_out = conv(image)\n",
|
|
|
|
|
+ "print(conv_out)"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": 6,
|
|
|
|
|
+ "id": "fa39666b",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "name": "stdout",
|
|
|
|
|
+ "output_type": "stream",
|
|
|
|
|
+ "text": [
|
|
|
|
|
+ "tensor([[[[-0.5894, -0.1350],\n",
|
|
|
|
|
+ " [ 0.4633, 0.5073]]]], grad_fn=<ConvolutionBackward0>)\n",
|
|
|
|
|
+ "torch.Size([1, 1, 2, 2])\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "from torch import nn\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 1. 模拟一张 1 通道 4x4 ‘假图片’。\n",
|
|
|
|
|
+ "image = torch.randn(1, 1, 4, 4)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 2. 卷积层:5*5 卷积核。\n",
|
|
|
|
|
+ "conv = nn.Conv2d(in_channels=1, \n",
|
|
|
|
|
+ " out_channels=1, \n",
|
|
|
|
|
+ " kernel_size=5,\n",
|
|
|
|
|
+ " padding=1)\n",
|
|
|
|
|
+ "conv_out = conv(image)\n",
|
|
|
|
|
+ "print(conv_out)\n",
|
|
|
|
|
+ "print(conv_out.shape)"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": 7,
|
|
|
|
|
+ "id": "c27d0b28",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "name": "stdout",
|
|
|
|
|
+ "output_type": "stream",
|
|
|
|
|
+ "text": [
|
|
|
|
|
+ "无填充输出: torch.Size([1, 1, 2, 2])\n",
|
|
|
|
|
+ "有填充输出: torch.Size([1, 1, 4, 4])\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 模拟一张 1 通道 4x4 ‘假图片’。\n",
|
|
|
|
|
+ "data = torch.randn(1, 1, 4, 4)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 对比有无 padding 的结果\n",
|
|
|
|
|
+ "# padding=0: 输出 2×2\n",
|
|
|
|
|
+ "conv_no_pad = torch.nn.Conv2d(in_channels=1, out_channels=1, \n",
|
|
|
|
|
+ " kernel_size=3,padding=0)\n",
|
|
|
|
|
+ "result_no_pad = conv_no_pad(data)\n",
|
|
|
|
|
+ "print(f\"无填充输出: {result_no_pad.shape}\") # [1, 1, 2, 2]\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# padding=1: 输出 4×4(补一圈零,尺寸不变)\n",
|
|
|
|
|
+ "conv_pad = torch.nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3,padding=1)\n",
|
|
|
|
|
+ "result_pad = conv_pad(data)\n",
|
|
|
|
|
+ "print(f\"有填充输出: {result_pad.shape}\") # [1, 1, 4, 4]"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": 8,
|
|
|
|
|
+ "id": "b7be42fd",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "name": "stdout",
|
|
|
|
|
+ "output_type": "stream",
|
|
|
|
|
+ "text": [
|
|
|
|
|
+ "输入形状: torch.Size([1, 3, 32, 32])\n",
|
|
|
|
|
+ "stride=1 输出: torch.Size([1, 8, 32, 32])\n",
|
|
|
|
|
+ "stride=2 输出: torch.Size([1, 8, 16, 16])\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "from torch import nn\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 1. 模拟一张 RGB 商品图。\n",
|
|
|
|
|
+ "image = torch.randn(1, 3, 32, 32)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 2. stride=1:卷积核移动更密,输出尺寸保持 32x32。\n",
|
|
|
|
|
+ "conv_stride_1 = nn.Conv2d(3, 8, kernel_size=3, stride=1, padding=1)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 3. stride=2:卷积核每次跳 2 格,输出尺寸减半。\n",
|
|
|
|
|
+ "conv_stride_2 = nn.Conv2d(3, 8, kernel_size=3, stride=2, padding=1)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 4. 打印输出形状,观察 stride 对空间尺寸的影响。\n",
|
|
|
|
|
+ "print(\"输入形状:\", image.shape) #1, 3, 32, 32\n",
|
|
|
|
|
+ "print(\"stride=1 输出:\", conv_stride_1(image).shape) #1, 8, 32, 32\n",
|
|
|
|
|
+ "print(\"stride=2 输出:\", conv_stride_2(image).shape) #1, 8, 16, 16"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": 9,
|
|
|
|
|
+ "id": "177a7758",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "name": "stdout",
|
|
|
|
|
+ "output_type": "stream",
|
|
|
|
|
+ "text": [
|
|
|
|
|
+ "输入图片形状: torch.Size([1, 3, 32, 32])\n",
|
|
|
|
|
+ "卷积权重形状: torch.Size([16, 3, 3, 3])\n",
|
|
|
|
|
+ "输出特征图形状: torch.Size([1, 16, 30, 30])\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "from torch import nn\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 1. 定义卷积层:输入 RGB 三通道,输出 16 组特征。\n",
|
|
|
|
|
+ "conv = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 2. 模拟 1 张 32x32 商品图。\n",
|
|
|
|
|
+ "images = torch.randn(1, 3, 32, 32)\n",
|
|
|
|
|
+ "features = conv(images)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 3. 重点看权重形状:[输出通道数, 输入通道数, 卷积核高, 卷积核宽]。\n",
|
|
|
|
|
+ "print(\"输入图片形状:\", images.shape) #1, 3, 32, 32\n",
|
|
|
|
|
+ "print(\"卷积权重形状:\", conv.weight.shape) #16, 3, 3, 3\n",
|
|
|
|
|
+ "print(\"输出特征图形状:\", features.shape) #1, 16, 30, 30"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": null,
|
|
|
|
|
+ "id": "cd5604e0",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "import torch.nn.functional as F\n",
|
|
|
|
|
+ "from torch import nn\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "class ResBlock(nn.Module):\n",
|
|
|
|
|
+ " def __init__(self,c):\n",
|
|
|
|
|
+ " super().__init__()\n",
|
|
|
|
|
+ " self.conv1 = torch.nn.Conv2d(c, c, 3, padding=1)\n",
|
|
|
|
|
+ " self.conv2 = torch.nn.Conv2d(c, c, 3, padding=1)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " def forward(self, x):\n",
|
|
|
|
|
+ " y = F.relu(self.conv1(x))\n",
|
|
|
|
|
+ " y = self.conv2(y)\n",
|
|
|
|
|
+ " return F.relu(y + x)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "if __name__ == '__main__':\n",
|
|
|
|
|
+ " x = torch.randn(1, 3, 32, 32)\n",
|
|
|
|
|
+ " net = ResBlock(3)\n",
|
|
|
|
|
+ " out = net(x)\n",
|
|
|
|
|
+ " print(out)\n",
|
|
|
|
|
+ " print(out.shape)"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": 11,
|
|
|
|
|
+ "id": "e0c98f24",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "name": "stdout",
|
|
|
|
|
+ "output_type": "stream",
|
|
|
|
|
+ "text": [
|
|
|
|
|
+ "tensor([[[[-0.0675, -0.2037, 0.0171, ..., 0.4069, 0.5789, 0.2718],\n",
|
|
|
|
|
+ " [ 0.2190, -0.2025, -0.0752, ..., 0.1766, 0.2935, 0.4443],\n",
|
|
|
|
|
+ " [ 0.2035, 0.2333, 0.1905, ..., -0.0450, 0.3506, 0.2333],\n",
|
|
|
|
|
+ " ...,\n",
|
|
|
|
|
+ " [-0.4011, 0.3804, -0.2089, ..., 0.1364, 0.1076, -0.1391],\n",
|
|
|
|
|
+ " [-0.1936, -0.0422, -0.0826, ..., 0.1392, 0.1757, 0.2660],\n",
|
|
|
|
|
+ " [ 0.1471, 0.1258, -0.1912, ..., -0.0734, 0.2551, 0.2739]],\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " [[ 0.7543, 0.2415, 0.0671, ..., 0.3817, 0.1778, 0.3153],\n",
|
|
|
|
|
+ " [-0.0306, 0.4632, 0.2696, ..., -0.2719, -0.1206, 0.2695],\n",
|
|
|
|
|
+ " [ 0.1162, 0.3065, 0.3385, ..., 0.0064, 0.2785, 0.5351],\n",
|
|
|
|
|
+ " ...,\n",
|
|
|
|
|
+ " [ 0.6120, 0.2779, -0.1715, ..., 0.2900, 0.4495, 0.5793],\n",
|
|
|
|
|
+ " [ 0.3929, 0.2231, 0.4754, ..., 0.0822, 0.7376, -0.0432],\n",
|
|
|
|
|
+ " [ 0.1821, 0.1866, 0.4352, ..., 0.1818, 0.3094, 0.5141]],\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " [[ 0.1182, -0.2091, -0.2565, ..., -0.1608, -0.2723, -0.0040],\n",
|
|
|
|
|
+ " [-0.4285, -0.1973, -0.2409, ..., -0.0442, -0.1848, -0.2102],\n",
|
|
|
|
|
+ " [-0.1080, -0.0223, -0.3410, ..., -0.4098, 0.0375, 0.1220],\n",
|
|
|
|
|
+ " ...,\n",
|
|
|
|
|
+ " [ 0.0412, -0.6477, 0.0764, ..., -0.4107, -0.2269, -0.0131],\n",
|
|
|
|
|
+ " [-0.0586, -0.2387, -0.0483, ..., -0.2497, -0.1536, -0.0121],\n",
|
|
|
|
|
+ " [ 0.0596, -0.2647, -0.2079, ..., -0.0137, -0.0346, 0.0276]],\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " ...,\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " [[-0.1513, -0.4924, -0.3291, ..., -0.0858, 0.3325, -0.1445],\n",
|
|
|
|
|
+ " [ 0.4556, 0.0310, -0.4014, ..., 0.3085, -0.1313, 0.0024],\n",
|
|
|
|
|
+ " [ 0.0458, -0.0948, -0.3584, ..., 0.5850, -0.1029, -0.0403],\n",
|
|
|
|
|
+ " ...,\n",
|
|
|
|
|
+ " [-0.2512, -1.0865, -0.0465, ..., 0.3306, 0.0660, 0.0341],\n",
|
|
|
|
|
+ " [-0.0380, -0.0944, -0.0224, ..., -0.0754, -0.3096, 0.2728],\n",
|
|
|
|
|
+ " [-0.0409, 0.1720, 0.1746, ..., 0.2054, 0.1020, 0.0853]],\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " [[ 0.2407, -0.1370, -0.2752, ..., 0.4636, 0.2640, 0.4261],\n",
|
|
|
|
|
+ " [ 0.4146, 0.1510, 0.1223, ..., 0.0529, 0.1967, 0.2584],\n",
|
|
|
|
|
+ " [ 0.1815, 0.6670, 0.3959, ..., 0.0048, 0.0204, 0.0871],\n",
|
|
|
|
|
+ " ...,\n",
|
|
|
|
|
+ " [ 0.0746, 0.2185, -0.3571, ..., 0.1158, -0.0269, -0.2000],\n",
|
|
|
|
|
+ " [ 0.0969, -0.2937, -0.2306, ..., 0.4424, 0.6800, 0.3173],\n",
|
|
|
|
|
+ " [ 0.3723, 0.2909, -0.0732, ..., 0.0284, 0.1223, 0.2113]],\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " [[-0.5429, -0.0432, -0.0599, ..., 0.0307, 0.1396, 0.0065],\n",
|
|
|
|
|
+ " [ 0.4744, 0.0020, 0.4407, ..., -0.2063, 0.0455, 0.2949],\n",
|
|
|
|
|
+ " [ 0.1040, 0.3706, 0.1427, ..., -0.4794, 0.0436, -0.2792],\n",
|
|
|
|
|
+ " ...,\n",
|
|
|
|
|
+ " [-0.1091, 0.1286, 0.0920, ..., -0.2311, -0.0640, -0.2771],\n",
|
|
|
|
|
+ " [-0.1871, -0.0525, -0.0609, ..., -0.0685, -0.1604, -0.0677],\n",
|
|
|
|
|
+ " [ 0.3317, -0.3073, -0.2099, ..., -0.1886, 0.0815, 0.1345]]]],\n",
|
|
|
|
|
+ " grad_fn=<ConvolutionBackward0>)\n",
|
|
|
|
|
+ "torch.Size([1, 128, 30, 30])\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "class Net(torch.nn.Module):\n",
|
|
|
|
|
+ " def __init__(self):\n",
|
|
|
|
|
+ " super(Net, self).__init__()\n",
|
|
|
|
|
+ " self.conv1 = torch.nn.Conv2d(3, 64, 3, 1)\n",
|
|
|
|
|
+ " self.resblock = ResBlock(64)\n",
|
|
|
|
|
+ " self.conv2 = torch.nn.Conv2d(64, 128, 1, 1)\n",
|
|
|
|
|
+ " def forward(self, x):\n",
|
|
|
|
|
+ " out = self.conv1(x)\n",
|
|
|
|
|
+ " x = self.resblock(out)\n",
|
|
|
|
|
+ " y = self.conv2(x)\n",
|
|
|
|
|
+ " return y\n",
|
|
|
|
|
+ "if __name__ == '__main__':\n",
|
|
|
|
|
+ " x = torch.randn(1, 3, 32, 32)\n",
|
|
|
|
|
+ " net = Net()\n",
|
|
|
|
|
+ " out = net(x)\n",
|
|
|
|
|
+ " print(out)\n",
|
|
|
|
|
+ " print(out.shape)"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": null,
|
|
|
|
|
+ "id": "77a94535",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "name": "stdout",
|
|
|
|
|
+ "output_type": "stream",
|
|
|
|
|
+ "text": [
|
|
|
|
|
+ "输入图片形状: torch.Size([5, 3, 32, 32])\n",
|
|
|
|
|
+ "卷积权重形状: torch.Size([16, 3, 3, 3])\n",
|
|
|
|
|
+ "输出特征图形状: torch.Size([5, 16, 30, 30])\n",
|
|
|
|
|
+ "weight 参数量: 432\n",
|
|
|
|
|
+ "bias 参数量: 16\n",
|
|
|
|
|
+ "总参数量: 448\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "from torch import nn\n",
|
|
|
|
|
+ "# 1. 定义卷积层:输入 RGB 三通道,输出 16 组特征。\n",
|
|
|
|
|
+ "conv = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3)\n",
|
|
|
|
|
+ "# 2. 模拟 10 张 32x32 商品图。\n",
|
|
|
|
|
+ "images = torch.randn(5, 3, 32, 32)\n",
|
|
|
|
|
+ "features = conv(images)\n",
|
|
|
|
|
+ "# 3. 重点看权重形状:[输出通道数, 输入通道数, 卷积核高, 卷积核宽]。\n",
|
|
|
|
|
+ "print(\"输入图片形状:\", images.shape)\n",
|
|
|
|
|
+ "print(\"卷积权重形状:\", conv.weight.shape)\n",
|
|
|
|
|
+ "print(\"输出特征图形状:\", features.shape)\n",
|
|
|
|
|
+ "# 4. 参数量计算:权重 16 * 3 * 3 * 3,再加 16 个 bias。\n",
|
|
|
|
|
+ "weight_count = conv.weight.numel()\n",
|
|
|
|
|
+ "bias_count = conv.bias.numel()\n",
|
|
|
|
|
+ "print(\"weight 参数量:\", weight_count)# 16 * 3 * 3 * 3 = 432\n",
|
|
|
|
|
+ "print(\"bias 参数量:\", bias_count) # 16\n",
|
|
|
|
|
+ "print(\"总参数量:\", weight_count + bias_count)"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": 3,
|
|
|
|
|
+ "id": "040eba4a",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "name": "stdout",
|
|
|
|
|
+ "output_type": "stream",
|
|
|
|
|
+ "text": [
|
|
|
|
|
+ "池化前: torch.Size([1, 3, 32, 32])\n",
|
|
|
|
|
+ "池化后: torch.Size([1, 3, 16, 16])\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "from torch import nn\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 1. 模拟 1 张图片经过卷积后得到的特征图。\n",
|
|
|
|
|
+ "features = torch.randn(1, 3, 32, 32)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 2. 最大池化:每个 2x2 小窗口取最大值,宽高减半。\n",
|
|
|
|
|
+ "max_pool = nn.MaxPool2d(kernel_size=2)\n",
|
|
|
|
|
+ "pooled_features = max_pool(features)\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 3. 池化不改变通道数,只压缩空间尺寸。\n",
|
|
|
|
|
+ "print(\"池化前:\", features.shape) #1, 3, 32, 32\n",
|
|
|
|
|
+ "print(\"池化后:\", pooled_features.shape) #1, 3, 16, 16"
|
|
|
|
|
+ ]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ "cell_type": "code",
|
|
|
|
|
+ "execution_count": null,
|
|
|
|
|
+ "id": "687a5f7c",
|
|
|
|
|
+ "metadata": {},
|
|
|
|
|
+ "outputs": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "name": "stdout",
|
|
|
|
|
+ "output_type": "stream",
|
|
|
|
|
+ "text": [
|
|
|
|
|
+ "tensor([[0.1005, 0.0953, 0.1032, 0.1047, 0.0979, 0.1016, 0.0990, 0.0962, 0.1005,\n",
|
|
|
|
|
+ " 0.1011]], grad_fn=<SoftmaxBackward0>)\n",
|
|
|
|
|
+ "输出形状: torch.Size([1, 10])\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "source": [
|
|
|
|
|
+ "import torch\n",
|
|
|
|
|
+ "import torch.nn as nn\n",
|
|
|
|
|
+ "import torch.nn.functional as F\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "class SimpleCNN(nn.Module):\n",
|
|
|
|
|
+ " def __init__(self, num_classes=10):\n",
|
|
|
|
|
+ " super(SimpleCNN, self).__init__()\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " #特征提取器 \n",
|
|
|
|
|
+ " #Conv → ReLU → Pool 重复堆叠\n",
|
|
|
|
|
+ " #卷积提取局部模式,ReLU 引入非线性,池化降低空间分辨率并扩大有效视野。\n",
|
|
|
|
|
+ " self.conv1 = nn.Sequential(\n",
|
|
|
|
|
+ " # 第一个卷积块\n",
|
|
|
|
|
+ " # 卷积核的大小 用奇数, 3*3 ,5*5\n",
|
|
|
|
|
+ " nn.Conv2d(3, 16, kernel_size=3, padding=1),\n",
|
|
|
|
|
+ " nn.ReLU(),\n",
|
|
|
|
|
+ " nn.MaxPool2d(kernel_size=2),\n",
|
|
|
|
|
+ " )\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " self.conv2 = nn.Sequential(\n",
|
|
|
|
|
+ " # 第二个卷积块\n",
|
|
|
|
|
+ " nn.Conv2d(16, 32, kernel_size=3, padding=1),\n",
|
|
|
|
|
+ " nn.ReLU(),\n",
|
|
|
|
|
+ " nn.MaxPool2d(kernel_size=2),\n",
|
|
|
|
|
+ " )\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " self.conv3 = nn.Sequential( \n",
|
|
|
|
|
+ " # 第三个卷积块\n",
|
|
|
|
|
+ " nn.Conv2d(32, 64, kernel_size=3),\n",
|
|
|
|
|
+ " nn.ReLU()\n",
|
|
|
|
|
+ " )\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " self.conv4 = nn.Sequential( \n",
|
|
|
|
|
+ " # 第三个卷积块\n",
|
|
|
|
|
+ " nn.Conv2d(64, 128, kernel_size=3),\n",
|
|
|
|
|
+ " nn.ReLU()\n",
|
|
|
|
|
+ " )\n",
|
|
|
|
|
+ " # 1 128 4 4\n",
|
|
|
|
|
+ " #N C H W -> N V\n",
|
|
|
|
|
+ " #分类器 处理卷积层提炼后的高层特征,最终输出类别得分\n",
|
|
|
|
|
+ " #Flatten 特征图拉成一维向量\n",
|
|
|
|
|
+ " #Linear映射到类别数维度\n",
|
|
|
|
|
+ " #Softmax:推理时转成概率分布\n",
|
|
|
|
|
+ " self.fc = nn.Sequential(\n",
|
|
|
|
|
+ " # 展平层\n",
|
|
|
|
|
+ " nn.Flatten(),\n",
|
|
|
|
|
+ " # 全连接层\n",
|
|
|
|
|
+ " nn.Linear(128 * 4 * 4, num_classes),\n",
|
|
|
|
|
+ " nn.Softmax(dim=1)\n",
|
|
|
|
|
+ " )\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ " def forward(self, x):\n",
|
|
|
|
|
+ " conv_out = self.conv1(x)\n",
|
|
|
|
|
+ " conv_out = self.conv2(conv_out)\n",
|
|
|
|
|
+ " conv_out = self.conv3(conv_out)\n",
|
|
|
|
|
+ " conv_out = self.conv4(conv_out)\n",
|
|
|
|
|
+ " out = self.fc(conv_out)\n",
|
|
|
|
|
+ " return out\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "\n",
|
|
|
|
|
+ "# 测试代码\n",
|
|
|
|
|
+ "if __name__ == \"__main__\":\n",
|
|
|
|
|
+ " data = torch.randn(1, 3, 32, 32)\n",
|
|
|
|
|
+ " model = SimpleCNN()\n",
|
|
|
|
|
+ " output = model(data)\n",
|
|
|
|
|
+ " print(output)\n",
|
|
|
|
|
+ " print(f\"输出形状: {output.shape}\")\n"
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ "metadata": {
|
|
|
|
|
+ "kernelspec": {
|
|
|
|
|
+ "display_name": "gitcode",
|
|
|
|
|
+ "language": "python",
|
|
|
|
|
+ "name": "python3"
|
|
|
|
|
+ },
|
|
|
|
|
+ "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.11.15"
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ "nbformat": 4,
|
|
|
|
|
+ "nbformat_minor": 5
|
|
|
|
|
+}
|