描述问题
在写实现生成mini-batches的时候,发现不能很好理解X[:,n]及X[:,m:n]的原理。下面具体围绕数组介绍切片原理展开讲述如何在不打乱数据集X与对应标签Y的对应关系的条件下,随机生成mini-batches的原理及过程。
解决方案
讲在前面。在具体实现中,X[a,b],a表示第 1 维(行)的第 a-1 个(行),b表示第 2 维(列)的第 b-1 个(列)。
注:下标均从0开始。
# 1-0.得到第1行第0列的元素
X = np.array([[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13], [14, 15], [16, 17], [18, 19]])
print(X[1, 0])
# 输出
# 2
1-1.数组切片 X[ :, n]原理
表示遍历所有行的第n-1列的元素。返回得到一个结构为(1,m)的数组
# 1-1.得到所有行的第0列
X = np.array([[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13], [14, 15], [16, 17], [18, 19]])
print(X[:, 0])
# 输出
# [ 0 2 4 6 8 10 12 14 16 18]
# 1-2.得到所有行的第1列数据
X = np.array([[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13], [14, 15], [16, 17], [18, 19]])
print(X[:, 1])
# 输出
# [ 1 3 5 7 9 11 13 15 17 19]
1-2.数组切片 X[ :, [1,0,2] ]的原理
原理 - 表示利用该列表[1,0,2]的元素作为下标进行重排。 首先提取所有行的第1列元素作为第0列;再提取所有行的第0列元素作为第1列;最后提取所有行的第2列元素作为第2列 。
效果 - 利用这种方法对所有样本进行重排,不会破坏每个样本内部的特征。
再利用同一个随机列表重排标签Y,达到样本和标签的对应关系不被破坏。
# 1-3.type(n)=list,且len(n)=n的效果。重排列,保持每列的对应关系。
X = np.array([[0, 1, 1], [2, 3, 1], [4, 5, 1], [6, 7, 1], [8, 9, 1], [10, 11, 1], [12, 13, 1], [14, 15, 1], [16, 17, 1],
[18, 19, 1]])
print(X[:, [1, 2, 0]])
# 输出
# [[ 1 1 0]
# [ 3 1 2]
# [ 5 1 4]
# [ 7 1 6]
# [ 9 1 8]
# [11 1 10]
# [13 1 12]
# [15 1 14]
# [17 1 16]
# [19 1 18]]
1-3.数组切片 X[ :, m:n]原理
取所有数据的第m到n-1列数据,含左不含右。
# 1-4.得到第1-2列的数据。含1不含3.
X = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14], [15, 16, 17], [18, 19, 20]])
print(X[:, 1:3])
# 输出
# [[ 1 2]
# [ 4 5]
# [ 7 8]
# [10 11]
# [13 14]
# [16 17]
2-1. 随机生成mini-batches的原理及过程
整个生成mini-batches 的过程分为2步:
第1步:随机化数据集X。利用数组切片 X[ :, [1,0,2] ]的原理打乱数组X的顺序。
具体实现:首先利用 np.random.permutation(m) 得到一个长度为m的元素取值为0-(m-1)的随机数组;此时不可直接使用permutation生成的数组,需要将数组转化为list列表待用;最后利用同一个随机列表对X、Y进行随机化。
permutation = list(np.random.permutation(m)) # 得到一个长度为m的随机列表,且里面的数是0-(m-1)
shuffled_X = X[:, permutation] # 将m个样本按照permutation列表里的数据进行排序
shuffled_Y = Y[:, permutation].reshape((1, m)) # 1.由于是二分类问题,所以每个样本的标签是(1,1),所以m个样本的结构是(1,m);2.reshape是确保格式不出错设定
第2步:分割为num_complete_minibatche个完整的mini-batch + 多余的样本。先得到mini-batches的个数;再遍历分割每个mini-batch的具体元素;每次分割后依次将mini-batch传入mini-batches的list中去。
注:样本个数m不一定是mini-batch-size的整数倍
num_complete_minibatches = math.floor(m / mini_batch_size) # 得到mini-batch的个数(向上取整)
for k in range(0, num_complete_minibatches):
mini_batches_X = shuffled_X[:, k * mini_batch_size:(k + 1) * mini_batch_size] # 分割数据集
mini_batches_Y = shuffled_Y[:, k * mini_batch_size:(k + 1) * mini_batch_size] # 分割标签
mini_batch = (mini_batches_X, mini_batches_Y)
mini_batches.append(mini_batch) # 存入list
附:若样本个数不是mini-batch-size的整数倍
if m % mini_batch_size != 0:
mini_batch_X = shuffled_X[:, mini_batch_size * num_complete_minibatches:] # copy余下的元素
mini_batch_Y = shuffled_Y[:, mini_batch_size * num_complete_minibatches:]
mini_batch = (mini_batch_X, mini_batch_Y)
mini_batches.append(mini_batch)
总结
1.X[:,n]及X[:,m:n]的原理
X[ :, n] - 表示遍历所有行的第n-1列的元素。返回得到一个结构为(1,m)的数组
X[ :, [1,0,2] ] - 原理 - 表示利用该列表[1,0,2]的元素作为下标进行重排。
效果 - 利用这种方法对所有样本进行重排,不会破坏每个样本内部的特征。
再利用同一个随机列表重排标签Y,达到样本和标签的对应关系不被破坏。
X[ :, m:n] - 取所有数据的第m到n-1列数据,含左不含右。
2.随机生成mini-batches的原理及过程
整个生成mini-batches 的过程分为2步:
第1步:利用同一个随机序列进行随机化数据集X和样本标签Y。
第2步:利用循环遍历分割为num_complete_minibatche个完整的mini-batch + 多余的样本。