nd-array 的快速padding
深度学习的batch training中经常遇到输入样本长度不一样的情况,例如时序序列,或者ffm中每个样本的维度不一样。我所知的解决方案有三种,第一种是对样本截断,第二种是对样本上采样或下采样,第三种是对样本补零。其中第三种被称为padding,具体做法是设定一个最大长度maxlen(它通常是各batch样本的最长长度,或者全体样本中的最长长度),然后在每个样本后面补零,使每一个样本的长度相等。
padding的两个方法
在这里找到了两个padding的实现,分别如下。实现一利用map,对lst中的每个样本进行映射,实现二则先定义一个宽度为目标长度的全0矩阵,然后把每个样本依次填入。
# 实现一
def pad_list(lst):
inner_max_len = max(map(len, lst))
map(lambda x: x.extend([0]*(inner_max_len-len(x))), lst)
return np.array(lst)
# 实现二
def apply_to_zeros(lst, dtype=np.int64):
inner_max_len = max(map(len, lst))
result = np.zeros([len(lst), inner_max_len], dtype)
for i, row in enumerate(lst):
for j, val in enumerate(row):
result[i][j] = val
return result
两种padding方法的速度
为了对比两种方法的处理速度快慢,随机生成若干个长度不一的序列,分别调用两个函数进行处理。
ns = range(5,10005,100)
np.random.seed(233)
time_consumption = []
for n in ns:
lens = np.random.randint(low=5,high=10,size=(n,))
sequences = [range(l) for l in lens]
start = time.time()
pad_list(sequences)
end = time.time()
# print "cost {0} sec".format(end-start)
time_consumption.append([end-start])
lens = np.random.randint(low=5,high=10,size=(n,))
sequences = [range(l) for l in lens]
start = time.time()
apply_to_zeros(sequences)
end = time.time()
# print "cost {0} sec".format(end-start)
time_consumption[-1].append(end-start)
if n% 100 == 0:
print n
time_consumption = np.array(time_consumption)
plt.plot(ns, time_consumption[:,0],label="pad_list")
plt.plot(ns, time_consumption[:,1],label="apply_to_zeros")
plt.xlabel("sample_size")
plt.ylabel("seconds")
plt.legend()
plt.show()
结果显示,第一种方法更快。