以np.concatenate为主题,谈谈numpy数组按维度合并的问题
1.引言
最近在做多模态融合的图像问题,其中最需要解决的就是不同模态的图像用什么方法进行融合,最简单也最直观的方法就是采用合并数组的方法,将不同模态的图像合并为多通道进行处理。在一些论文中,比如《Deep Learning-Based Image Segmentation on Multimodal Medical Imaging》中,如图1.1所示,论文中发现简单的concat 成多通道进行处理反而会比经过一部分网络提取特征后再融合效果更好。不过不同的情况需要具体分析,在《FusionNet: Incorporating Shape and Texture for Abnormality Detection in 3D Abdominal CT Scans》中,文章进行了多种组合的实验(不是模态融合,而是图片和mask的组合),结果发现某一种组合的效果最好。


图1.1 文章中提到的融合网络结构以及效果
不过总的来说,能够使用concat进行合并数组肯定是快速而有效的一种模态融合方法。
2.简要解析np.concatente官方文档
参见https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.concatenate.html
numpy.concatenate((a1, a2, ...), axis=0, out=None)
Join a sequence of arrays along an existing axis.
| Parameters: |
|
|---|---|
| Returns: |
|
concatenate中含有两个参数,第一个参数是一个元组,元组里填入你想合并的数组,第二个参数是axis轴,第一个参数没什么好说的,主要想谈第二个参数。
另外要提的是官方提示,这个对我来说没什么用。
注意:当要串联的一个或多个数组为MaskedArray时,此函数将返回MaskedArray对象而不是ndarray,但不会保留输入掩码。 如果需要使用MaskedArray作为输入,请改用MaskedArray模块中的ma.concatenate函数。
正常的数组例子
>>> a = np.array([[1, 2], [3, 4]])
>>> b = np.array([[5, 6]])
>>> np.concatenate((a, b), axis=0)
array([[1, 2],
[3, 4],
[5, 6]])
>>> np.concatenate((a, b.T), axis=1)
array([[1, 2, 5],
[3, 4, 6]])
>>> np.concatenate((a, b), axis=None)
array([1, 2, 3, 4, 5, 6])
数组是MaskedArray时的例子,此函数将不会保留MaskedArray输入的掩码,要保留的话要用ma那个函数。
>>> a = np.ma.arange(3)
>>> a[1] = np.ma.masked
>>> b = np.arange(2, 5)
>>> a
masked_array(data = [0 -- 2],
mask = [False True False],
fill_value = 999999)
>>> b
array([2, 3, 4])
>>> np.concatenate([a, b])
masked_array(data = [0 1 2 2 3 4],
mask = False,
fill_value = 999999)
>>> np.ma.concatenate([a, b])
masked_array(data = [0 -- 2 2 3 4],
mask = [False True False False False False],
fill_value = 999999)
3.axis的轴到底指的是什么
网上大多介绍的是一维数组和二维数组,但是很少提到高维数组的情况,
比如说当axis=0时,这时候就是np.concatenate指的是水平合并数组,当axi=1时,指的是垂直方向合并数组,举个例子:
定义两个数组:
a
array([0, 1, 2],
[3, 4, 5],
[6, 7, 8])
b = a*2
b
array([ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16])
下面进行合并:
np.hstack((a,b))
array([ 0, 1, 2, 0, 2, 4],
[ 3, 4, 5, 6, 8, 10],
[ 6, 7, 8, 12, 14, 16]) np.concatenate((a,b),axis=1)
array([ 0, 1, 2, 0, 2, 4],
[ 3, 4, 5, 6, 8, 10],
[ 6, 7, 8, 12, 14, 16])
np.vstack((a,b))
array([ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16]) np.concatenate((a,b),axis=0)
array([ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16])
两种方式分别和np中的hstack以及vstack的合并数组的结果相同,那么concatenate存在的意义到底是什么呢,就在于它可以进行更高维度的数组合并。
就对我的问题而言,我要对两种模态的3d切片数据进行合并,两个数据的shape均为(10,1,128,128),如果我使用axis=1,那么不是进行垂直合并,而是选择了第二维度进行合并,比如说下面这个例子,最终输出的结果就是一个(10,2,128,128)的数组。
#coding=utf-8
import numpy as np np.random.seed(0)
a = np.random.randint(0, 255, (10, 1, 128, 128))
b = np.random.randint(0, 255, (10, 1, 128,128))
ab = np.concatenate((a,b),axis = 1)
print('ab的维度为 = \n {}'.format(ab.shape)) ab的维度为 =
(10, 2, 128, 128)
这就一目了然了,原来np.concatenate并不仅仅是水平和垂直合并,而是多个维度的合并,axis轴的选择其实就是对某一个维度的选择。
那么进行数据融合的适合就方便多了,不过要解决先让数据进入网络后再提取特征进行fusion训练就是另一个问题了,我们下次再考虑。
以np.concatenate为主题,谈谈numpy数组按维度合并的问题的更多相关文章
- 1.2 NumPy数组基础
目录 第一章 numpy入门 1.2 numpy数组基础 1.2.1 数组的属性 1.2.2 数组的索引:获取单个元素 1.2.3 数组切片:获取子数组 1.2.4 数组的变形 1.2.5 数组的拼接 ...
- 操作 numpy 数组的常用函数
操作 numpy 数组的常用函数 where 使用 where 函数能将索引掩码转换成索引位置: indices = where(mask) indices => (array([11, 12, ...
- NumPy 超详细教程(1):NumPy 数组
系列文章地址 NumPy 最详细教程(1):NumPy 数组 NumPy 超详细教程(2):数据类型 NumPy 超详细教程(3):ndarray 的内部机理及高级迭代 文章目录 Numpy 数组:n ...
- 【NumPy学习指南】day5 改变数组的维度
我们已经学习了怎样使用reshape函数,现在来学习一下怎样将数组展平. (1) ravel 我们可以用ravel函数完成展平的操作: In: b Out: array([[[ 0, 1, 2, 3] ...
- numpy——>数组拼接np.concatenate
语法:np.concatenate((a1, a2, ...), axis=0) 1.默认是 axis = 0,也就是说对0轴(行方向)的数组对象,进行其垂直方向(axis=1)的拼接(即数据整行整行 ...
- python numpy 数组拼接
我就写一下我遇到的,更多具体的请看Python之Numpy数组拼接,组合,连接 >>> aarray([0, 1, 2], [3, 4, 5], [6, 7, ...
- Numpy 数组操作
Numpy 数组操作 Numpy 中包含了一些函数用于处理数组,大概可分为以下几类: 修改数组形状 翻转数组 修改数组维度 连接数组 分割数组 数组元素的添加与删除 修改数组形状 函数 描述 resh ...
- Python数据分析工具库-Numpy 数组支持库(二)
1 shape变化及转置 >>> a = np.floor(10*np.random.random((3,4))) >>> a array([[ 2., 8., 0 ...
- numpy数组 拼接
转载自:https://blog.csdn.net/zyl1042635242/article/details/43162031 数组拼接方法一 首先将数组转成列表,然后利用列表的拼接函数append ...
随机推荐
- Hadoop 之 Hadoop2.0
1.Hadoop2.0与1.0 答:Hadoop2.0之后的版本移除了原有的JobTracker和TaskTracker,改由Yarn平台的ResourceManager负责集群中所有资源的管理和分配 ...
- 从零开始用golang创建一条简单的区块链
区块链(Blockchain),是比特币的一个重要概念,它本质上是一个去中心化的数据库,同时作为比特币的底层技术,是一串使用密码学方法相关联产生的数据块,每一个数据块中包含了一批次比特币网络交易的信息 ...
- C++ 生成随机数 srand()和rand()
1. rand() rand(产生随机数)表头文件: #include<stdlib.h>定义函数 :int rand(void) 函数说明 :因为rand() 的内部实现是用线性同余法做 ...
- 夯实Java基础系列10:深入理解Java中的异常体系
目录 为什么要使用异常 异常基本定义 异常体系 初识异常 异常和错误 异常的处理方式 "不负责任"的throws 纠结的finally throw : JRE也使用的关键字 异常调 ...
- Google Test入门教程:从下载到运行
本文以VS2019为例,自己的工程使用Debug x64,多线程调试DLL(/MDd),用户可以根据自己需求更改配置,只要所有配置前后统一即可. 第一步:clone Google Test源码 打开h ...
- java实现图片验证码
一.验证码生成类 package hbi.tech.utils; import javax.imageio.ImageIO; import java.awt.*; import java.awt.im ...
- Java利用反射排序
前言 Java为我们提供了几种排序得方法,比如Arrays和Collections类,但是前提是数组或者集合中的元素都必须实现Comparable接口,基本的数据类型都已经实现了Comparable接 ...
- Stanford公开课《编译原理》学习笔记(2)递归下降法
目录 一. Parse阶段 CFG Recursive Descent(递归下降遍历) 二. 递归下降遍历 2.1 预备知识 2.2 多行语句的处理思路 2.3 简易的文法定义 2.4 文法产生式的代 ...
- 洛谷:P3950 部落冲突
原题地址:https://www.luogu.org/problemnew/show/P3950 题目简述 给定一棵树,每次给定一个操作,有如下两种: 将某条边染黑 2.询问给定的u,v两点间是否有边 ...
- 一个基于protobuf的极简RPC
前言 RPC采用客户机/服务器模式实现两个进程之间的相互通信,socket是RPC经常采用的通信手段之一.当然,除了socket,RPC还有其他的通信方法:http.管道...网络开源的RPC框架也比 ...