效率分析:图像数据集reshape处理
问题
考虑这么一个场景:有一份人脸数据集 \(X\in R^{p\times a\times b}\),该数据集包括b个人,每个人有a张图片,每张图片含p个像素。我们用这份数据集进行人脸识别模型的训练,而模型输入为训练样本 \(X_{train}\in R^{p\times n}\) 训练标签 \(Y_{train}\in R^{n\times 1}\),怎么处理呢?
import numpy as np
from scipy.io import loadmat
data = loadmat('data.mat')['DAT']
print(data.shape)
# output: (8064, 7, 38)
# 表示数据集中包括38个人,每人7张图片,图片含8064个像素
解决方法
这里提供两种方法:
-
一是直接reshape。由于python中矩阵存储采用c风格(行排列),在矩阵reshape的时候先变化“后方的”维度,所以直接reshape即可满足要求;
# method 1 def method1(data): X_train = data.reshape(p, a * b).transpose(1, 0) Y_train = np.tile(np.arange(b), a) return X_train, Y_train
-
二是依次遍历所有照片,取出来后拼接到一块。具体有两种顺序,
- 遍历所有人的第一张照片,所有人的第二张照片...
- 遍历第一个人的所有照片,第二个人的所有照片...
我们只演示第一种方式
# method 2
def method2(data):
X_train = np.vstack([data[:, i, j] for i in range(a) for j in range(b)])
Y_train = np.tile(np.arange(b), a)
return X_train, Y_train
效率对比
先给出结论:直接reshape效率会更低一些!
import time
# 函数计时器
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
func_return = func(*args, **kwargs)
end = time.time()
print(f'{func.__name__}() execute time: {end - start}s')
return func_return
return wrapper
@timer
def test_method1():
for i in range(500):
_, _ = method1(data)
pass
@timer
def test_method2():
for i in range(500):
_, _ = method2(data)
pass
if __name__ == '__main__':
method1()
method2()
# output
# method1() execute time: 4.76141357421875s
# method2() execute time: 3.401926040649414s