使用numpy.hstack拼接数组报错ValueError:除拼接轴外维度需完全匹配
首先,咱们来拆解一下你遇到的报错原因:
np.hstack() 本质是沿着轴1(也就是第二个维度,索引从0开始)进行数组拼接,这个方法要求所有输入数组,除了拼接轴(轴1)之外的所有其他维度的大小必须完全一致。
看一下你的数组维度:
train_frames1:(2000, 1, 224, 224)train_frames2:(1000, 1, 224, 224)train_frames3:(2000, 1, 224, 224)train_frames4:(2000, 1, 224, 224)train_frames5:(2000, 1, 224, 224)train_frames6:(586, 1, 224, 224)
这里问题出在轴0(第一个维度,样本数量):有的数组是2000个样本,有的是1000,还有的是586,大小不统一,这就违反了hstack的要求,所以抛出了ValueError: all the input array dimensions except for the concatenation axis must match exactly。
接下来根据你的实际需求,给你两种解决方案:
方案1:按样本维度拼接(最可能是你想要的)
如果你是想把所有数组里的样本合并到一起,也就是沿着**轴0(样本轴)**拼接,那应该用np.vstack()或者更明确的np.concatenate(axis=0)。这时候只需要除了轴0之外的其他维度(1、2、3)一致就行,你的数组这些维度都是(1,224,224),完全符合要求。
代码示例:
import numpy as np # 用vstack train = np.vstack((train_frames1, train_frames2, train_frames3, train_frames4, train_frames5, train_frames6)) # 或者用concatenate,效果完全一样,更直观指定轴 train = np.concatenate( [train_frames1, train_frames2, train_frames3, train_frames4, train_frames5, train_frames6], axis=0 )
拼接后的数组维度会是 (2000+1000+2000+2000+2000+586, 1, 224, 224),也就是 (9586, 1, 224, 224)。
方案2:确实需要沿着轴1拼接(调整样本数统一)
如果你真的要沿着轴1拼接,那必须先把所有数组的轴0(样本数)调整成一样的。这里有两种常见的处理方式:
方式A:截断所有数组到最短样本数
把所有数组都截断成样本数最少的那个(也就是train_frames6的586个样本),这样所有数组的轴0都是586,就可以用hstack了:
import numpy as np # 找到最小样本数 min_sample_count = min( train_frames1.shape[0], train_frames2.shape[0], train_frames3.shape[0], train_frames4.shape[0], train_frames5.shape[0], train_frames6.shape[0] ) # 每个数组取前min_sample_count个样本,再拼接 train = np.hstack([arr[:min_sample_count] for arr in [ train_frames1, train_frames2, train_frames3, train_frames4, train_frames5, train_frames6 ]])
拼接后的维度是 (586, 6, 224, 224)(轴1从1变成了6,因为6个数组各贡献了1个维度)。
方式B:补全短数组到最长样本数
把样本数少的数组用0(或者其他值)填充到最长的样本数(2000),再进行拼接:
import numpy as np # 找到最大样本数 max_sample_count = max( train_frames1.shape[0], train_frames2.shape[0], train_frames3.shape[0], train_frames4.shape[0], train_frames5.shape[0], train_frames6.shape[0] ) # 定义一个补全函数,在轴0方向填充0 def pad_array(arr, target_length): pad_size = target_length - arr.shape[0] if pad_size <= 0: return arr # 填充参数:((轴0前填充, 轴0后填充), (轴1前, 轴1后), ...) return np.pad(arr, ((0, pad_size), (0, 0), (0, 0), (0, 0)), mode='constant') # 补全所有数组后拼接 padded_arrays = [pad_array(arr, max_sample_count) for arr in [ train_frames1, train_frames2, train_frames3, train_frames4, train_frames5, train_frames6 ]] train = np.hstack(padded_arrays)
拼接后的维度是 (2000, 6, 224, 224)。
内容的提问来源于stack exchange,提问作者Joseph

