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
完成。