各种卷积操作及其矩阵运算

article/2025/9/12 8:45:52

前言

简单来讲,卷积是一种函数和函数产生一个新函数的数学运算,该数学运算的自变量是两个函数f, g(连续或离散都可以,,定义域之外的部分记函数值填充为0),输出为一个函数h,满足在这里插入图片描述
,或者说,就是对每个自变量t, 的h(t)值,都是g与对应​f的函数值的加权和。

1. 一维离散卷积数学表达

在这里插入图片描述
在这里插入图片描述

2. 二维离散卷积定义

在这里插入图片描述

3. 图像卷积

卷积核套合在图像上,对应位置相乘求和赋值给中心像素,滑动卷积核(从左到右,从上到下),依次得到新的特征图上的值。

在这里插入图片描述

上图展示的是 stride=1 的情形,既每次移动一个像素的位置。并且,上图未进行padding,所以卷积之后的特征图会在四周各缩减(kernel_size-1)/2个像素。同时也可以在边缘填充0,使得卷积之后的特征图大小不变。

4. 深度学习中的卷积

在这里插入图片描述

5. 卷积计算的加速

5.1 原理示意图

在这里插入图片描述

卷积计算是将输入图像矩阵和卷积核矩阵变换为两个大的矩阵(im2col),然后进行矩阵相乘(GEMM)(利用GPU进行矩阵相乘的高效性)。

5.2 im2col in tensorflow

具体到tensorflow中,im2col操作可以用tf.extract_image_patches代替:

tf.image.extract_image_patches(images,ksizes=None,strides=None,rates=None,padding=None,name=None,sizes=None
)
# images:必须是shape为[batch, in_rows, in_cols, depth]的tensor;
# ksize:长度大于等于4的list,滑动窗的大小
# strides:每块patch区域之间中心点之间的距离,必须是: [1, stride_rows, stride_cols, 1].#具体点说就是用来计算每次选取patch的初始点位置
# rates: 在每次提取的patch中,对应dim像素点位置之间的差距,必须是[1, rate_rows, rate_cols, 1];「或者理解为 提取出来的每个框里面的像素不是都选择的 根据rate的不同 隔几个选一个 默认是1也就是的都选择 若为2 那么就是隔一个来选择」
# padding:有两个取值,“VALID”或者“SAME”,“VALID”表示所取的patch区域必须完全包含在原始图像中."SAME"表示可以取超出原始图像的部分,这一部分进行0填充。
# for example
import tensorflow as tf
import numpy as npimage = np.arange(5 * 5).reshape(5, 5)
# [[ 0,  1,  2,  3,  4],
#  [ 5,  6,  7,  8,  9],
#  [10, 11, 12, 13, 14],
#  [15, 16, 17, 18, 19],
#  [20, 21, 22, 23, 24]]image = image.reshape(1, 5, 5, 1) 
# image:(batch_size, img_row, img_col, input_filters)
images = tf.convert_to_tensor(image.astype(np.float32))image_patches = tf.extract_image_patches(images,[1, 3, 3, 1],[1, 1, 1, 1],[1, 1, 1, 1],padding='SAME')
# image_patches: (batch_size, img_row, img_col, kernel_row * kernel_col * input_filters)with tf.Session() as sess:print(sess.run(image_patches))
#  [[[[ 0.  0.  0.  0.  0.  1.  0.  5.  6.]
#     [ 0.  0.  0.  0.  1.  2.  5.  6.  7.]
#     [ 0.  0.  0.  1.  2.  3.  6.  7.  8.]
#     [ 0.  0.  0.  2.  3.  4.  7.  8.  9.]
#     [ 0.  0.  0.  3.  4.  0.  8.  9.  0.]]
#
#    [[ 0.  0.  1.  0.  5.  6.  0. 10. 11.]
#     [ 0.  1.  2.  5.  6.  7. 10. 11. 12.]
#     [ 1.  2.  3.  6.  7.  8. 11. 12. 13.]
#     [ 2.  3.  4.  7.  8.  9. 12. 13. 14.]
#     [ 3.  4.  0.  8.  9.  0. 13. 14.  0.]]
#
#    [[ 0.  5.  6.  0. 10. 11.  0. 15. 16.]
#     [ 5.  6.  7. 10. 11. 12. 15. 16. 17.]
#     [ 6.  7.  8. 11. 12. 13. 16. 17. 18.]
#     [ 7.  8.  9. 12. 13. 14. 17. 18. 19.]
#     [ 8.  9.  0. 13. 14.  0. 18. 19.  0.]]
#
#    [[ 0. 10. 11.  0. 15. 16.  0. 20. 21.]
#     [10. 11. 12. 15. 16. 17. 20. 21. 22.]
#     [11. 12. 13. 16. 17. 18. 21. 22. 23.]
#     [12. 13. 14. 17. 18. 19. 22. 23. 24.]
#     [13. 14.  0. 18. 19.  0. 23. 24.  0.]]
#
#    [[ 0. 15. 16.  0. 20. 21.  0.  0.  0.]
#     [15. 16. 17. 20. 21. 22.  0.  0.  0.]
#     [16. 17. 18. 21. 22. 23.  0.  0.  0.]
#     [17. 18. 19. 22. 23. 24.  0.  0.  0.]
#     [18. 19.  0. 23. 24.  0.  0.  0.  0.]]]]

5.3 对比自己写的卷积和tf原有的卷积

import tensorflow as tf
import numpy as np# 生成图像
image = np.arange(5 * 5 * 3).reshape(1, 5, 5, 3)
# image:(batch_size, img_row, img_col, input_filters)
images = tf.convert_to_tensor(image.astype(np.float32))image_patches = tf.extract_image_patches(images,[1, 3, 3, 1],[1, 1, 1, 1], [1, 1, 1, 1],padding='SAME')image_patches = tf.reshape(image_patches, [-1, 27])# 生成卷积核
kernel = np.arange(3 * 3 * 3 * 64).reshape(3, 3, 3, 64)
# kernel:(kernel_row, kernel_col, input_filters,output_filters)
kernel = tf.convert_to_tensor(kernel.astype(np.float32))
kernel_filter = tf.reshape(kernel, [27, 64])# 自定义的卷积
actual = tf.matmul(image_patches, kernel_filter)
actual = tf.reshape(actual, [-1, 5, 5, 64])
# filtered_image:(batch_size, img_row, img_col, output_filters)# tf定义的卷积
expected = tf.nn.conv2d(images, kernel, strides=[1, 1, 1, 1], padding='SAME')with tf.Session() as sess:print(sess.run(actual))print(sess.run(expected))print(sess.run(tf.reduce_sum(expected - actual)))# 0.0

6. local_connected conv

6.1 原理示意图

在这里插入图片描述

  • 正常卷积是参数共享的,也就是说,对于同一张图片的不同块,应用相同的卷积核;
  • 而局部连接卷积对于同一张图像的不同块应用不同的卷积核,其是非参数共享的。

6.2 自己写local_conv2d

import tensorflow as tf
import keras.backend as Kdef local_conv2d(inputs, kernel, kernel_size, strides, output_shape, data_format=None):# input: (batch_size, input_row, input_col, input_filter)# kernel: (output_row * output_col, kernel_row * kernel_col * input_filter, output_filters)# kernel_size: (kernel_row, kernel_col)# strides: (stride_row, stride_col)# output_shape: (output_row, output_col)# data_format=None: 'channels_first' or 'channels_last'data_format = normalize_data_format(data_format)stride_row, stride_col = stridesoutput_row, output_col = output_shapekernel_shape = int_shape(kernel)_, dim, filters = kernel_shapekernel_row, kernel_col = kernel_size[0], kernel_size[1]# result: (batch_size, output_row * output_col, kernel_row * kernel_col * input_filter)image_patches = tf.extract_image_patches(inputs,[1, kernel_row, kernel_col, 1],[1, stride_row, stride_col, 1],[1, 1, 1, 1],padding='VALID')image_patches = tf.reshape(image_patches, [-1, output_row * output_col, dim])image_patches = tf.transpose(image_patches, [1, 0, 2])output = K.batch_dot(image_patches, kernel)output = reshape(output,(output_row, output_col, -1, filters))if data_format == 'channels_first':output = tf.transpose(output, (2, 3, 0, 1))else:output = tf.transpose(output, (2, 0, 1, 3))return output

http://chatgpt.dhexx.cn/article/3GyRWcel.shtml

相关文章

矩阵卷积运算的具体过程

矩阵卷积运算的具体过程,很简单 最近在看图像处理,卷积运算这一块也查了很多,但是感觉都写的太复杂,我这里简单的写一下卷积到底是一个什么计算过程。 假设有一个卷积核h,就一般为3*3的矩阵: 有一个待处理…

矩阵卷积运算过程讲解

写了那么久的博客,始于Python爬虫,目前专于Java学习,终于有了属于自己的小窝,欢迎各位访问我的个人网站,未来我们一起交流进步。 在爬虫处理验证码的过程中接触到矩阵卷积运算,关于该类运算,记录…

矩阵的卷积以及使用python计算方法

1、离散⼆维卷积公式 其中A为被卷积矩阵,K为卷积核,B为卷积结果,该公式中,三个矩阵的排序均从0开始。 卷积核、滤波器通常为较小尺寸的矩阵,比如3333、5555等,数字图像是相对较大尺寸的2维(多…

矩阵卷积

1. 矩阵的卷积运算主要用在图像处理中,假设输入信号为x[m,n],激活响应为h[m,n],则其卷积定义为: 2.如果矩阵的中心在边缘就要将原矩阵进行扩展,例如补0 3.卷积的计算步骤: (1) 卷积核绕自己的核心…

隐马尔可夫模型(HMM)及Viterbi算法

HMM简介 对于算法爱好者来说,隐马尔可夫模型的大名那是如雷贯耳。那么,这个模型到底长什么样?具体的原理又是什么呢?有什么具体的应用场景呢?本文将会解答这些疑惑。   本文将通过具体形象的例子来引入该模型&#x…

viterbi算法实例及python实现

Python中hmmlearn给出了三种HMM模型:MultiomialHMM,GaussianHMM,GMMHMM。本文以MultiomialHMM为例,使用《从机器学习到深度学习》中第六章的活动/天气模型进行推算。 假设有这样一个问题,远在另一个城市上大学的儿子每天通过邮件向你汇报他今…

在HMM中实际应用Viterbi算法的例子

在HMM中实际应用Viterbi算法的例子 Viterbi概念动态规划使用HMM的Viterbi算法参考Viterbi概念 本质:动态规划算法 维特比算法是多步骤每步多选择模型的最优选择问题。 其在每一步的所有选择都保存了前续所有步骤到当前步骤当前选择的最小总代价(或者最大价值)以及当前代价…

HMM和viterbi算法初步实践-----中文分词

马尔科夫性质:当一个随机过程在给定现在状态及所有过去状态情况下,其未来状态的条件概率分布仅依赖于当前状态。换句话说,在给定现在状态时,它与过去状态(即该过程的历史路径)是条件独立的(也就是没有任何的…

HMM和Viterbi算法

一、隐马尔可夫模型(Hidden Markov Model) 1、简介 隐含马尔可夫模型并不是俄罗斯数学家马尔可夫发明的,而是美国数学家鲍姆提出的,隐含马尔可夫模型的训练方法(鲍姆-韦尔奇算法)也是以他名字命名的。隐含马…

基于Hmm模型和Viterbi算法的中文分词和词性标注

使用 python 实现基于Hmm模型和Viterbi算法的中文分词及词性标注;使用 最大概率算法 进行优化。最终效果:人民日报语料:分词(F1:96.189%);词性标注(F1:97.934%) 完整代码和数据,参见本实验的 github地址:h…

【生信算法】利用HMM纠正测序错误(Viterbi算法的python实现)

利用HMM纠正测序错误(Viterbi算法的python实现) 问题背景 对两个纯系个体M和Z的二倍体后代进行约~0.05x的低覆盖度测序,以期获得后代个体的基因型,即后代中哪些片段分别来源于M和Z。已知: 后代中基因型为MM、MZ&…

Viterbi算法实现中文分词和词性标注

Viterbi算法 目标过程词典分词统计分词词性标注 附录附录二附录三 源码地址 目标 实现基于词典的分词方法和统计分词方法对分词结果进行词性标注对分词及词性标注结果进行评价,包括4个指标:正确率、召回率、F1值和效率 过程 词典分词 基于词典的分词…

viterbi 算法与python实现

Viterbi算法 (部分内容转自知乎:《如何通俗地讲解 viterbi 算法?》) 1、问题描述 如下如所示,如何快速找到从 S 到 E 的最短路径? 一:遍历穷举法,可行,但速度太慢&am…

维特比算法(viterbi)原理以及简单实现

维特比算法 看一下维基百科的解释,维特比算法(Viterbi algorithm)是一种动态规划算法。它用于寻找最有可能产生观测事件序列的维特比路径——隐含状态序列,特别是在马尔可夫信息源上下文和隐马尔可夫模型中。 通俗易懂的解释知乎…

flask中jsonify遇到的坑

1.jsonify可以将字典转换成json对象传入前端 data {"movie": movie_list,"page": page,"dic_list": dic,"total_page": total_page}>>坑1 字典的值不能为range(x,x),上图dic就是像range(x,x),会报错 …

flask中的jsonify返回的是乱码

用flask返回json时遇到了返回字符串支持中文显示的问题,在web端显示的是utf-8的编码如图; 虽然不影响接口的读取,但是可读性太差,于是研究了一下怎么直接显示成中文。最后找到了解决方案如下,在配置中加入下面一行代码就OK了。 …

request jsonify

python的flask框架为用户提供了直接返回包含json格式数据响应的方法,即jsonify,在开发中会经常用到。如下一段简单的flask后端代码,服务端视图函数根据请求参数返回json格式的数据到客户端。 转载于:https://www.cnblogs.com/daqingzi/p/9018…

Flask使用json或jsonify返回响应的数据

前言 在做网站前后端数据交互的时候,我们经常需要使用Ajax等方法向后端发送请求来获取响应的数据,而我们经常需要的就是json格式的响应数据,它实际上就是一个字符串。要知道Flask如何返回json响应数据,首先就需要知道如何将字典di…

Flask 学习-8. jsonify返回中文没正常显示问题

前言 Flask 接口返回的json 格式数据有中文的时候,默认是以ASCII码 返回的,没正常显示中文。 jsonify 返回 json 数据 函数直接返回dict 数据 或返回jsonfy() 函数处理的数据,都是以json格式返回的 from flask import Flask, jsonify fro…

flask jsonify之序列化时的default函数、jsonify序列化自定义对象

目录 1.看源码 2、重写默认的default函数,实现自己的序列化机制 3、把对象转化成字典 3.1 __dict__的方式 3.2、定义keys和__getitem__的方式 4、最终的代码实现 5、关于default函数的其他知识 1.看源码 打开site-package,flask,json…