互相关运算,卷积核生成,填充,步幅,多输入多输出通道(深度学习—复现)
深度学习复现——互相关运算,填充,步幅,多输入多输出
·
6.2图像卷积
6.2.1互相关运算
#二维互相关运算输出
import numpy
import torch
def corr2d(X,K):
h,w=K.shape
Y=torch.zeros((X.shape[0]-h+1,X.shape[1]-w+1))
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
X=numpy.array([[0.0,1.0,2.0],
[3.0,4.0,5.0],
[6.0,7.0,8.0]])
K=numpy.array([[0.0,1.0],
[2.0,3.0]])
print(corr2d(X,K))
#实现卷积层
import torch.nn as nn
class Conv2D(nn.Module):
def __init__(self,kernel_size,**kwargs):
super().__init__(**kwargs)
self.weight=nn.Parameter(torch.rand(kernel_size))
self.bias=nn.Parameter(torch.zeros(1))
def forward(self,x):
return corr2d(x,self.weight.data())+self.bias.data()
#图像中目标的边缘检测,找到像素变化的位置,来检测图像中不同颜色的边缘(寻找黑白边缘)
#6×8像素的黑白图像,中间四列为黑色,其余像素为白色
X=torch.ones([6,8]).float()
X[:,2:6]=0
print(X)
#卷积核:1×2,互相关运算,水平相邻两元素相同,则输出为0,否则输出为非0
K=numpy.array([[1.0,-1.0]])
#互相关运算,输出Y中的1代表从白色到黑色的边缘,-1代表从黑色到白色的边缘,其他情况的输出为0
Y=corr2d(X,K)
print(Y)
#输入的二维图像转置,再进行互相关运算。垂直边缘消失(这个卷积核K只可以检测垂直边缘,无法检测水平边缘)
#A=corr2d(torch.transpose(torch.tensor(X),dim0=0,dim1=1),K)#转换数据类型tensor,
#print(A)
#6.2.4学习卷积核
'''
更复杂数值的卷积核+连续的卷积层:由’输入-输出‘对来学习由X生成Y的卷积核
构造一个卷积层,并将其卷积核初始化为随机张量,接下来,在每次的迭代中,我们比较Y与卷积层输出的平方误差,然后计算梯度来更新卷积核。
'''
#构造一个二维卷积层,具有1个输出通道和形状为(1,2)的卷积核
conv2d=nn.Conv2d(1,kernel_size=(1,2),bias=False,out_channels=1)#使用内置的二维卷积层,忽略偏置
#二维卷积层使用四维输入和输出格式(批量大小,通道,高度,宽度)
X=X.reshape(1,1,6,8)
Y=Y.reshape(1,1,6,7)
lr=3e-2#学习率
for i in range(10):
Y_hat=conv2d(X)
l = (Y_hat - Y) ** 2
conv2d.zero_grad()
l.sum().backward()
#迭代卷积核
conv2d.weight.data[:] -= lr * conv2d.weight.grad
if (i + 1) % 2 == 0:
print(f'epoch{i + 1},loss {float(l.sum()):3f}')
#l.requires_grad=True#RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
#l.backward(torch.ones_like(l))#RuntimeError: grad can be implicitly created only for scalar outputs
#卷积核的权重张量(卷积核权重接近之前定义的卷积核)
print(conv2d.weight.data.reshape(1,2))#TypeError: 'Tensor' object is not callable,解决办法:去掉()
6.3填充和步幅
#错误:TypeError: can only concatenate tuple (not "builtin_function_or_method") tuple,解决办法:将形状大小shape()函数改为view()
#填充
import torch
import torch.nn as nn
def comp_conv2d(conv2d,X):
#view()调整size,相当于reshape,resize
#(1,1)批量大下和通道数
X=X.view((1,1)+X.shape)#view()是把原先tensor中的数据进行排列,排成一行,然后根据所给的view()中的参数从一行中按顺序选择组成最终的tensor。
Y=conv2d(X)
return Y.view(Y.shape[2:])
#每边都填充了1行1列,相当于总共添加了2行或2列
conv2d=nn.Conv2d(1,kernel_size=3,padding=1,out_channels=1)
X=torch.rand(8,8)
print(comp_conv2d(conv2d,X).shape)#torch.Size([8, 8])
#卷积核的高度和宽度不同,填充不同的高度和宽度,使输出和输入具有相同的高度和宽度
conv2d=nn.Conv2d(1,kernel_size=(5,3),padding=(2,1),out_channels=1)
print(comp_conv2d(conv2d,X).shape)#torch.Size([8, 8])
#步幅2
conv2d=nn.Conv2d(1,kernel_size=3,padding=1,stride=2,out_channels=1)
print(comp_conv2d(conv2d,X).shape)#torch.Size([4, 4])
#步幅,垂直步幅3,水平步幅4
conv2d=nn.Conv2d(1,kernel_size=(3,5),padding=(0,1),stride=(3,4),out_channels=1)
print(comp_conv2d(conv2d,X).shape)#torch.Size([2, 2])
6.4多输入多输出通道
#多输入通道互相关运算
import torch
import torch.nn as nn
def corr2d_multi_in(X,K):
return sum(corr2d(x,k)for x,k in zip(X,K))
X=numpy.array([[[0.0,1.0,2.0],
[3.0,4.0,5.0],
[6.0,7.0,8.0]],
[[1.0,2.0,3.0],
[4.0,5.0,6.0],
[7.0,8.0,9.0]]])
K=numpy.array([[[0.0,1.0],
[2.0,3.0]],
[[1.0,2.0],
[3.0,4.0]]])
print(corr2d_multi_in(X,K))
#多通道输出的互相关函数
def corr2d_multi_in_out(X,K):
#迭代K的第0个维度,每次都对输入X执行互相关运算,最后将所有结果都叠加在一起
return numpy.stack([corr2d_multi_in(X,k)for k in K],0)
K=numpy.stack((K,K+1,K+2),0)#开辟一个新的维度,原始的维度在新的维度上拼接起来
print(K.shape)#(3, 2, 2, 2)
print(corr2d_multi_in_out(X,K))#输出包含3个通道
更多推荐



所有评论(0)