简单的例子学会在pytorch中实现更新Kernel——卷积核的操作

卷积神经网络

从传统的滤波器角度来看,其实卷积操作可以狭隘地理解为对图像进行锐化,模糊,寻找边缘等修图的操作,但是其核心是什么呢,是如何实现这些操作的呢?
图片模糊操作

1. 认识卷积操作

如果熟悉图像的构成(这里主要说明灰度图像),灰度图像的像素变化为0-255,其中0为黑色,255为白色。如下图所示,左边的input为一个55的二维矩阵(可以看成一个像素为55的正方形图片),中间的矩阵即为大小为33的卷积核,最右边的矩阵则为输出矩阵(图像)。如果想要自己动笔计算,可以回顾线性代数中学习的知识,矩阵的乘法,卷积核的移动(从左到右,从上到下)与原始矩阵相乘,便可以计算得出最终的33矩阵。接下来将在Pytorch中实现。
卷积操作

"""实现2维卷积函数"""
import torch
from torch import nn

# 输入
x = torch.tensor([[2, 1, 0, 2, 3],
                  [9, 5, 4, 2, 0],
                  [2, 3, 4, 5, 6],
                  [1, 2, 3, 1, 0],
                  [0, 4, 4, 2, 8]])
# 卷积核
k = torch.tensor([[0, 1],
                  [2, 3]])

# 创建卷积核移动过程的计算函数
def conv2d(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

# 输出
y = conv2d(x, k)
print(y)

2. 创建卷积核-并初始化

有的初学者在学习CNN的过程中,搞不明白卷积核是怎么选取数值的,接下来,将用一个小实例进行讲解,也是我在学习过程中的一个总结。最终结果对比给出的边界检测卷积核和梯度下降计算出来的卷积核。

"""
首先,创建要给Conv2D的类(class),继承nn.Moudule;
其次,人为设定一个图像,用于边界检测;
再次,选用一个边界检测卷积核,用于计算图像的边界;
最终,通过梯度下降,求解初始化的Conv2D类中卷积核的参数如何根据输入输出学习出正确的边界检测卷积核。
"""
import torch
from torch import nn


# 创建卷积核移动过程的计算函数
def conv2d(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


class Conv2D(nn.Module):
    def __init__(self, kernel_size):
        super(Conv2D, self).__init__()
        self.weight = nn.Parameter(torch.randn(kernel_size))
        self.bias = nn.Parameter(torch.randn(1))

    def forward(self, x):
        return conv2d(x, self.weight) + self.bias

# 创建图像x,其中人为设定边界区域
x = torch.ones(6, 8)
x[:, 3:7] = 0
# 创建卷积核
k = torch.tensor([[1, -1]])
# 通过卷积操作得到输出——边界检测结果
y = conv2d(x, k)
print(y)
# 构造一个卷积核为(2,1)的二维矩阵,自动初始化,输出权重
kernal = Conv2D(kernel_size=(1, 2))
print(kernal.weight, kernal.bias)
# 设置迭代次数
step = 40
# 学习率
lr = 0.01
for i in range(step):
    y_hat = kernal(x)
    l = ((y_hat - y) ** 2).sum()
    l.backward()
	# 梯度下降
    kernal.weight.data -= lr * kernal.weight.grad
    kernal.bias.data -= lr * kernal.bias.grad
	# 梯度清零
    kernal.weight.grad.fill_(0)
    kernal.bias.grad.fill_(0)
    if (i + 1) & 5 == 0:
        print('Step %d, loss %.3f' % (i + 1, l.item()))
   
# 输出训练(梯度下降)学习到的卷积核以及真实的卷积核对比
print("weight: ", kernal.weight.data)
print("bias: ", kernal.bias.data)
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值