1. 自定义神经网络卷积核权重

神经网络被深度学习者深深喜爱,究其原因之一是神经网络的便利性,使用者只需要根据自己的需求像搭积木一样搭建神经网络框架即可,搭建过程中我们只需要考虑卷积核的尺寸,输入输出通道数,卷积方式等等。

我们使用惯了自带的参数后,当我们要自定义卷积核参数时,突然有种无从下手的感觉,哈哈哈哈哈哈哈哈~~,请允许我开心下,嘿嘿!因为笔者在初入神经网络时也遇到了同样的问题,当时踩了太多坑了,宝宝想哭(灬ꈍ ꈍ灬)!让我悲伤的是,找遍了各个资源区,也没有找到大家的分享。因此,我想把我的方法写出来,希望能帮助到各位宝宝,开心(*^▽^*)。

  话不多说,正文开始......

2. 定义卷积核权重

  我这里是自定义的dtt系数卷积核权重,直接上权重代码:

2.1 dtt系数权重Code

  def dtt_matrix(n): 这个函数是n*n的DTT系数矩阵,笔者的是8*8的系数矩阵。

def dtt_kernel(out_channels, in_channels, kernel_size): 这个方法是设定权重,权重需要包括4个参数(输出通道数,输入通道数,卷积核高,卷积核宽),这里有很多细节要注意,宝宝们要亲自躺下坑,才能映像深刻也,我就不深究了哈,(#^.^#)。

import numpy as np
import torch
import torch.nn as nn # ================================
# DTT coefficient matrix of n * n
# ================================
def dtt_matrix(n):
dtt_coe = np.zeros([n, n], dtype='float32')
for i in range(0, n):
dtt_coe[0, i] = 1/np.sqrt(n)
dtt_coe[1, i] = (2*i + 1 - n)*np.sqrt(3/(n*(np.power(n, 2) - 1)))
for i in range(1, n-1):
dtt_coe[i+1, 0] = -np.sqrt((n-i-1)/(n+i+1)) * np.sqrt((2*(i+1)+1)/(2*(i+1)-1)) * dtt_coe[i, 0]
dtt_coe[i+1, 1] = (1 + (i+1)*(i+2)/(1-n)) * dtt_coe[i+1, 0]
dtt_coe[i+1, n-1] = np.power(-1, i+1) * dtt_coe[i+1, 0]
dtt_coe[i+1, n-2] = np.power(-1, i+1) * dtt_coe[i+1, 1]
for j in range(2, int(n/2)):
t1 = (-(i+1) * (i+2) - (2*j-1) * (j-n-1) - j)/(j*(n-j))
t2 = ((j-1) * (j-n-1))/(j * (n-j))
dtt_coe[i+1, j] = t1 * dtt_coe[i+1, j-1] + t2 * dtt_coe[i+1, j-2]
dtt_coe[i+1, n-j-1] = np.power(-1, i-1) * dtt_coe[i+1, j]
return dtt_coe # ===============================================================
# DTT coefficient matrix of (out_channels * in_channels * n * n)
# ===============================================================
def dtt_kernel(out_channels, in_channels, kernel_size):
dtt_coe = dtt_matrix(kernel_size)
dtt_coe = np.array(dtt_coe) dtt_weight = np.zeros([out_channels, in_channels, kernel_size, kernel_size], dtype='float32')
temp = np.zeros([out_channels, in_channels, kernel_size, kernel_size], dtype='float32') order = 0
for i in range(0, kernel_size):
for j in range(0, kernel_size):
dtt_row = dtt_coe[i, :]
dtt_col = dtt_coe[:, j]
dtt_row = dtt_row.reshape(len(dtt_row), 1)
dtt_col = dtt_col.reshape(1, len(dtt_col))
# print("dtt_row: ", dtt_row)
# print("dtt_col: ", dtt_col)
# print("i:", i, "j: ", j)
temp[order, 0, :, :] = np.dot(dtt_row, dtt_col)
order = order + 1
for i in range(0, in_channels):
for j in range(0, out_channels):
# dtt_weight[j, i, :, :] = flip_180(temp[j, 0, :, :])
dtt_weight[j, i, :, :] = temp[j, 0, :, :]
return torch.tensor(dtt_weight)

2.2 'same'方式卷积

  如果宝宝需要保持卷积前后的数据尺寸保持不变,即'same'方式卷积,那么你直接使用我这个卷积核(提一下哟,这个我也是借自某位前辈的,我当时没备注哇,先在这里感谢那位前辈,前辈如果路过,还请留言小生哈,(#^.^#))。

import torch.utils.data
from torch.nn import functional as F
import math
import torch
from torch.nn.parameter import Parameter
from torch.nn.functional import pad
from torch.nn.modules import Module
from torch.nn.modules.utils import _single, _pair, _triple class _ConvNd(Module):
def __init__(self, in_channels, out_channels, kernel_size, stride,
padding, dilation, transposed, output_padding, groups, bias):
super(_ConvNd, self).__init__()
if in_channels % groups != 0:
raise ValueError('in_channels must be divisible by groups')
if out_channels % groups != 0:
raise ValueError('out_channels must be divisible by groups')
self.in_channels = in_channels
self.out_channels = out_channels
self.kernel_size = kernel_size
self.stride = stride
self.padding = padding
self.dilation = dilation
self.transposed = transposed
self.output_padding = output_padding
self.groups = groups
if transposed:
self.weight = Parameter(torch.Tensor(
in_channels, out_channels // groups, *kernel_size))
else:
self.weight = Parameter(torch.Tensor(
out_channels, in_channels // groups, *kernel_size))
if bias:
self.bias = Parameter(torch.Tensor(out_channels))
else:
self.register_parameter('bias', None)
self.reset_parameters() def reset_parameters(self):
n = self.in_channels
for k in self.kernel_size:
n *= k
stdv = 1. / math.sqrt(n)
self.weight.data.uniform_(-stdv, stdv)
if self.bias is not None:
self.bias.data.uniform_(-stdv, stdv) def __repr__(self):
s = ('{name}({in_channels}, {out_channels}, kernel_size={kernel_size}'
', stride={stride}')
if self.padding != (0,) * len(self.padding):
s += ', padding={padding}'
if self.dilation != (1,) * len(self.dilation):
s += ', dilation={dilation}'
if self.output_padding != (0,) * len(self.output_padding):
s += ', output_padding={output_padding}'
if self.groups != 1:
s += ', groups={groups}'
if self.bias is None:
s += ', bias=False'
s += ')'
return s.format(name=self.__class__.__name__, **self.__dict__) class Conv2d(_ConvNd):
def __init__(self, in_channels, out_channels, kernel_size, stride=1,
padding=0, dilation=1, groups=1, bias=True):
kernel_size = _pair(kernel_size)
stride = _pair(stride)
padding = _pair(padding)
dilation = _pair(dilation)
super(Conv2d, self).__init__(
in_channels, out_channels, kernel_size, stride, padding, dilation,
False, _pair(0), groups, bias)
def forward(self, input):
return conv2d_same_padding(input, self.weight, self.bias, self.stride,
self.padding, self.dilation, self.groups) # custom con2d, because pytorch don't have "padding='same'" option. def conv2d_same_padding(input, weight, bias=None, stride=1, padding=1, dilation=1, groups=1):
input_rows = input.size(2)
filter_rows = weight.size(2)
effective_filter_size_rows = (filter_rows - 1) * dilation[0] + 1
out_rows = (input_rows + stride[0] - 1) // stride[0] input_cols = input.size(3)
filter_cols = weight.size(3)
effective_filter_size_cols = (filter_cols - 1) * dilation[1] + 1
out_cols = (input_cols + stride[1] - 1) // stride[1] padding_needed = max(0, (out_rows - 1) * stride[0] + effective_filter_size_rows -input_rows)
padding_rows = max(0, (out_rows - 1) * stride[0] +
(filter_rows - 1) * dilation[0] + 1 - input_rows)
rows_odd = (padding_rows % 2 != 0)
padding_cols = max(0, (out_cols - 1) * stride[1] +
(filter_cols - 1) * dilation[1] + 1 - input_cols)
cols_odd = (padding_cols % 2 != 0)
if rows_odd or cols_odd:
input = pad(input, [0, int(cols_odd), 0, int(rows_odd)])
return F.conv2d(input, weight, bias, stride,
padding=(padding_rows // 2, padding_cols // 2),
dilation=dilation, groups=groups)

2.3 将权重赋给卷积核

  此处才是宝宝们最关心的吧,不慌,这就来了哈,开心(*^▽^*),进入正文了(#^.^#)。

  这里给了一个简单的网络模型(一个固定卷积+3个全连接,全连接是1*1的Conv2d),代码里我给了注释,宝宝们应该能秒懂滴,(*^▽^*)!

import torch
import torchvision
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
import dtt_kernel
import util
import paddingSame # 定义权重
dtt_weight1 = dtt_kernel.dtt_kernel(64, 2, 8) class DttNet(nn.Module):
def __init__(self):
super(DttNet, self).__init__()
self.conv1 = paddingSame.Conv2d(2, 64, 8)
     # 将权重赋给卷积核
self.conv1.weight = nn.Parameter(dtt_weight1, requires_grad=False) self.fc1 = util.fc(64, 512, 1)
self.fc2 = util.fc(512, 128, 1)
self.fc3 = util.fc(128, 2, 1, last=True) def forward(self, x):
x = self.conv1(x)
x = self.fc1(x)
x = self.fc2(x)
x = self.fc3(x)
return x

2.4 补充我的util类

import torch.nn as nn

def conv(in_channels, out_channels, kernel_size, stride=1, dilation=1, batch_norm=True):
if batch_norm:
return nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size, stride=stride, padding=(kernel_size // 2)),
nn.BatchNorm2d(out_channels),
nn.ReLU()
)
else:
return nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size, stride=stride, padding=(kernel_size // 2)),
nn.ReLU()
) def fc(in_channels, out_channels, kernel_size, stride=1, bias=True, last=False):
if last:
return nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size, stride=stride, padding=(kernel_size // 2)),
)
else:
return nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size, stride=stride, padding=(kernel_size // 2)),
nn.BatchNorm2d(out_channels),
nn.ReLU()
)

3. 总结

  哇哦,写完了耶,不晓得宝宝们有没得收获呢,o((⊙﹏⊙))o,o((⊙﹏⊙))o。大家不懂的可以再下面留言哟,我会时常关注我家的园子呢。若有不足之处,宝宝们也在留言区吱我一下哟,我们下次再见,┏(^0^)┛┏(^0^)┛。

Pytorch中自定义神经网络卷积核权重的更多相关文章

  1. pytorch中网络特征图(feture map)、卷积核权重、卷积核最匹配样本、类别激活图(Class Activation Map/CAM)、网络结构的可视化方法

    目录 0,可视化的重要性: 1,特征图(feture map) 2,卷积核权重 3,卷积核最匹配样本 4,类别激活图(Class Activation Map/CAM) 5,网络结构的可视化 0,可视 ...

  2. 详解Pytorch中的网络构造,模型save和load,.pth权重文件解析

    转载:https://zhuanlan.zhihu.com/p/53927068 https://blog.csdn.net/wangdongwei0/article/details/88956527 ...

  3. 转pytorch中训练深度神经网络模型的关键知识点

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_42279044/articl ...

  4. 第五章——Pytorch中常用的工具

    2018年07月07日 17:30:40 __矮油不错哟 阅读数:221   1. 数据处理 数据加载 ImageFolder DataLoader加载数据 sampler:采样模块 1. 数据处理 ...

  5. (原)CNN中的卷积、1x1卷积及在pytorch中的验证

    转载请注明处处: http://www.cnblogs.com/darkknightzh/p/9017854.html 参考网址: https://pytorch.org/docs/stable/nn ...

  6. [Pytorch]PyTorch Dataloader自定义数据读取

    整理一下看到的自定义数据读取的方法,较好的有一下三篇文章, 其实自定义的方法就是把现有数据集的train和test分别用 含有图像路径与label的list返回就好了,所以需要根据数据集随机应变. 所 ...

  7. pytorch中如何使用预训练词向量

    不涉及具体代码,只是记录一下自己的疑惑. 我们知道对于在pytorch中,我们通过构建一个词向量矩阵对象.这个时候对象矩阵是随机初始化的,然后我们的输入是单词的数值表达,也就是一些索引.那么我们会根据 ...

  8. PyTorch中使用深度学习(CNN和LSTM)的自动图像标题

    介绍 深度学习现在是一个非常猖獗的领域 - 有如此多的应用程序日复一日地出现.深入了解深度学习的最佳方法是亲自动手.尽可能多地参与项目,并尝试自己完成.这将帮助您更深入地掌握主题,并帮助您成为更好的深 ...

  9. pytorch中的激励函数(详细版)

          初学神经网络和pytorch,这里参考大佬资料来总结一下有哪些激活函数和损失函数(pytorch表示)      首先pytorch初始化:   import torch import t ...

随机推荐

  1. STL(六)——map、multimap

    STL--map.multimap 文章目录 STL--map.multimap 关联容器与map的介绍 map与set的异同 map与multimap的异同 map类对象的构造 map添加元素 ma ...

  2. 【JavaScript】js01

    一,javascript 历史. netscape -> 浏览器. -> livescript 微软 -> jscript netscape -> ecma 组织 -> ...

  3. kali2016&2019的安装使用

    先解释一下,为什么要说2016&2019哪,这是因为有一些测试靶机环境在2016以上的系统安装不通过,所以有时候会特意找2016的镜像来用. 一.下载镜像 1.下载镜像当然要到官方去下载了: ...

  4. 对EL自己以及对于param、header、cookie的相关应用的相关知识点的复习

    EL表达式语言是一种可以计算和输出的java对象的简单语言. 列入请求语句为下面的方式:request.setAttribute("username","zhangsan ...

  5. matplotlib IdentityTransform(原地变换)

    2020-04-12 23:33:56 -- Edit by yangrayIdentityTransform继承于Affine2DBase类,它是一个高效实现原地变换的类.(不知道有什么用,变换前后 ...

  6. xargs与exec区别

    平时使用find命令查找出文件的时候有时候后面有时候用-exec有时候用管道加xargs,这2个到底有什么不同?下面就这2个的不同做简单介绍. 零.实验环境 [root@osker /]# find ...

  7. Linux C++ 网络编程学习系列(2)——多路IO之select实现

    select实现多路IO 源码地址:https://github.com/whuwzp/linuxc/tree/master/select 源码说明: server.cpp: 监听127.1:6666 ...

  8. 事务的传播属性及隔离级别 Spring

    事务的传播属性(Propagation) REQUIRED ,这个是默认的属性 Support a current transaction, create a new one if none exis ...

  9. Java 基础增强

    jdk与jre 要想深入了解Java必须对JDK的组成, 本文对JDK6里的目录做了基本的介绍,主要还是讲解 了下JDK里的各种可执行程序或工具的用途 Java(TM) 有两个平台 JRE 运行平台, ...

  10. day28作业

    import os import uuid import pickle from conf import settings class School: def __init__(self,name,a ...