本篇为《深度学习》系列博客的第八篇,该系列博客主要记录深度学习相关知识的学习过程和自己的理解,方便以后查阅。
上篇说道这篇那应该写PCA,但是……,也不知道忙啥了,就一直没写,再拖拖……,用到之后在写吧!!!
一维卷积
物理意义
这里主要参考b站《「珂学原理」No. 28「卷积为谁而生?」》,这里就直接放推导过程了。
说一下理解:视频里说的卷积,就是跟“傅里叶变换”
、“拉普拉斯变换”
一样的,都是对信号的或者说是函数的图像的分解,“傅里叶”是把信号分解成正弦信号
,“拉布拉斯”是在傅里叶的基础上增加了一个衰减
。
而这里说的卷积,是将信号分解成一个小段
或者说是分解成一个由冲激信号
组成的信号。
数学意义
还有一个视频《「珂学原理」No.90「卷积应该怎么卷」卷积描述了什么运算?》,这里主要讲的数学原理,下面贴几张图片:
在离散的信号里可以称之为“卷和”
二维卷积
以下参考文章《二维卷积的原理与手动编程实现》
二维卷积的实现
二维卷积实现可以分为两大步。
一是预处理:将卷积核翻转180°,将原始数据扩边;
二是滑动卷积计算。下面按这两个步骤分别说明:
预处理
对卷积核
翻转180°
就是"上下翻转+左右翻转";对原始数据的扩边其实就是为了"补0"好算
,扩边括多大呢?就看原始数据"左上角"那个点,卷积核是3x3,那么左顶点一周也就要扩成3x3(卷积核中心和左顶点对齐后可以做"点乘"),也就是上、下各括边"fix(3/2) = 1"。
滚动卷积运算
滑动卷积计算,其实就是对应的"两个小矩阵"
的"点乘并求和"
。"滑动"是指:卷积核沿着"扩边后的原始数据"从左到右,从上到下进行。
Matlab代码
clc; clear;
x = [-1 -2 -1;0 0 0;1 2 1]; % 卷积核——必须是方阵且为奇数行/列
data = [1 2 3 4 5;6 7 8 9 10;11 12 13 14 15;16 17 18 19 20;21 22 23 24 25]; % 原始数据
zidai = conv2(data,x,'same'); % matlab自带的二维卷积函数
x = rot90(rot90(x)); % 新的卷积核
% 核的尺寸
size_x = size(x);
row_x = size_x(1); % 核的行数
col_x = size_x(2); % 核的列数
% 数据的尺寸
size_data = size(data);
row_data = size_data(1); % 数据的行数
col_data = size_data(2); % 数据的列数
% 核的中心元素:
centerx_row = round(row_x/2); % round:四舍五入函数
centerx_col = round(col_x/2);
centerx = x(centerx_row,centerx_col);
% 对原始数据扩边:
data_tmp = zeros(row_data+row_x-1,col_data+row_x-1);
data_tmp(centerx_row:centerx_row+row_data-1,centerx_row:centerx_row+col_data-1) = data;
data_k = data_tmp;
% 扩边后新数据矩阵尺寸:
size_data_k = size(data_k);
row_data_k = size_data_k(1);
col_data_k = size_data_k(2);
% m = centerx_row:row_data+row_x-2
% 开始卷积计算: m n 是新数据矩阵的正常索引
result = zeros(row_data_k,col_data_k);
% m n一般卷积步长都是1
for m = centerx_row:centerx_row+row_data-1
for n = centerx_row:centerx_row+col_data-1
% tt是临时与卷积核大小相同的数据中的部分矩阵:
tt = data_k(m-(centerx_row-1):m+(centerx_row-1),n-(centerx_row-1):n+(centerx_row-1));
% juan是中间每一次卷积计算求和的中间量:
juan = sum(x.*tt);
result(m,n) = sum(juan(:));
end
end
% 去掉之前扩边的0:
result = result(centerx_row:centerx_row+row_data-1,centerx_row:centerx_row+col_data-1)
运行结果如下: