Python小练习:创建卷积层
作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/
使用Pytorch中的nn.Conv2d函数来创建卷积层,构建卷积神经网络(仅含卷积层与激活函数)。
1. cnn_test.py
1 # -*- coding: utf-8 -*- 2 # Author:凯鲁嘎吉 Coral Gajic 3 # https://www.cnblogs.com/kailugaji/ 4 # Python小练习:创建卷积层 5 import torch 6 import torch.nn as nn 7 import numpy as np 8 import os 9 import imageio 10 from PIL import Image 11 import torchvision.transforms as transforms 12 import matplotlib.pyplot as plt 13 from pylab import * 14 from warnings import simplefilter 15 simplefilter(action="ignore",category=UserWarning) 16 17 # 构建卷积神经网络(仅用到卷积层) 18 def build_CNN(input_size): 19 module_list = [] 20 last_h = input_size[2] 21 last_w = input_size[3] 22 cnn_kernels = [[input_size[1], 256, 4], 23 [256, 128, 3, 2, 1, 1], 24 [128, 64, 3, 2, 1, 1], 25 [64, 32, 3, 2, 1, 1], 26 [32, 3, 5, 2, 2, 1]] 27 # 除了输入层,后面有5层,5个激活函数 28 # 6个参数的含义: 29 # 1. in_channels (int) – 输入图像中的通道数 30 # 2. out_channels (int) – 卷积产生的通道数即输出图片的通道数 31 # 3. kernel_size (int or tuple) – 卷积核的大小(可以是个数,也可以是元组) 32 # 4. stride (int or tuple, optional) — 卷积的步幅。 默认值:1 33 # 5. padding (int, tuple or str, optional) – 填充添加到输入的所有四个边。 默认值:0 34 # 6. dilation (int or tuple, optional) – 内核元素之间的间距。 默认值:1。 35 act_func = [nn.LeakyReLU(), nn.Tanh(), nn.ReLU(), nn.ELU(), nn.CELU()] # 激活函数 36 default = [None, None, None, 1, 0] # in_c, out_c, kernel, stride, pad 37 for i, ck in enumerate(cnn_kernels): 38 # i: 0, 1, 2, 3, 4 ... 39 ck = ck + default[len(ck):] 40 last_h = int((last_h + 2 * ck[4] - ck[2]) / ck[3] + 1) #(h+2*pad-k)/stride+1 41 last_w = int((last_w + 2 * ck[4] - ck[2]) / ck[3] + 1) 42 module_list.append(nn.Conv2d(*ck)) 43 module_list.append(act_func[i]) 44 output_shape = (cnn_kernels[-1][1], last_h, last_w) 45 return nn.Sequential(*module_list), output_shape 46 47 # 使用方法 48 # 图像例子: 49 path = "./img" # 打开存放图像的文件夹 50 dirs = os.listdir(path) # ['1.jpg', '2.jpg', '3.jpg'] 51 len_dir = len(dirs) # len_dir张图片 52 outs = [] 53 count = 0 54 fig = plt.figure(figsize=(24, 6)) # 画布布局 55 for i in dirs: 56 image_pad = imageio.imread(os.path.join(path, i)) # i: 'xxx.jpg' 57 image_pad = Image.fromarray(image_pad).resize((600, 300)) # 重新调整图像尺寸 58 transf = transforms.ToTensor() # 将原始数据形式(图像)转换成tensor 59 outs.append(transf(image_pad)) # tensor数据格式是torch(C,H,W) 60 plt.subplot(2, len_dir, count+1) # 2行,len_dir列,第count+1个子图 61 plt.axis('off') 62 plt.imshow(image_pad) 63 count += 1 64 outs= torch.tensor([np.array(item) for item in outs]) # 将list转换为tensor 65 model, output_shape = build_CNN(outs.shape) 66 # N, C, H, W = outs.shape # 样本个数5, 通道数3, 高300, 宽600 67 print('网络结构:\n', model) 68 print('单个样本的输出维度:', output_shape) 69 print('输入数据维度:', outs.shape) 70 y = model(outs) # 实例化 71 print('实际输出维度:', y.shape) 72 for i in range(outs.shape[0]): # 展示结果 73 toPIL = transforms.ToPILImage() 74 pic = toPIL(y[i]) 75 plt.subplot(2, len_dir, int(i + 1 + outs.shape[0])) 76 plt.imshow(pic) 77 plt.axis('off') 78 plt.savefig('CNN_fig.png', bbox_inches='tight', pad_inches=0.0, dpi=500) 79 plt.show() 80 print('-------------------------------------------------') 81 # 随机数据例子: 82 input_size = [10, 3, 84, 84] 83 # 10张图片,3通道,每张图片长*宽为84*84 84 model, output_shape = build_CNN(input_size) 85 x = torch.randn(input_size) 86 print('输入数据维度:', x.shape) 87 y = model(x) 88 print('实际输出维度:', y.shape)
2. 结果
D:\ProgramData\Anaconda3\python.exe "D:/Python code/2023.3 exercise/Neural Network/cnn_test.py" 网络结构: Sequential( (0): Conv2d(3, 256, kernel_size=(4, 4), stride=(1, 1)) (1): LeakyReLU(negative_slope=0.01) (2): Conv2d(256, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1)) (3): Tanh() (4): Conv2d(128, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1)) (5): ReLU() (6): Conv2d(64, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1)) (7): ELU(alpha=1.0) (8): Conv2d(32, 3, kernel_size=(5, 5), stride=(2, 2), padding=(2, 2)) (9): CELU(alpha=1.0) ) 单个样本的输出维度: (3, 19, 38) 输入数据维度: torch.Size([5, 3, 300, 600]) 实际输出维度: torch.Size([5, 3, 19, 38]) ------------------------------------------------- 输入数据维度: torch.Size([10, 3, 84, 84]) 实际输出维度: torch.Size([10, 3, 6, 6]) Process finished with exit code 0
完成。