效率分析:图像数据集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
posted @ 2021-03-16 10:21  Js2Hou  阅读(700)  评论(0编辑  收藏  举报