回顾MNIST的前向传播,输入虽然是一个形状为(10000,784)的数据集,但是每次计算都是一张一张图地计算
X | W1 | W2 | W3 | -> | Y输出 | |
形状 | 784 | 784*50 | 50*100 | 100*10 | 10 |
批处理
使用批处理来打包100张图片将其作为一个批次,需要将X的形状改为100*784,再将100张图像打包在一起作为输入数据,如下图
X | W1 | W2 | W3 | -> | Y输出 | |
形状 | 100*784 | 784*50 | 50*100 | 100*10 | 100*10 |
则代码需要修改,其中之一就是Softmax做一个修改,之前的Softmax只支持向量,修改过后也支持矩阵。修改后代码如下:
def _softmax(x):
if x.ndim ==2:
#因为x为二维函数,所以shape为(ndim,row,column)
#axis=1:求各column的最大值
#axis=2:求各row的最大值
D = np.max(x, axis=1)
# 由于是求各列的最大值,所以需要对x进行转置
x = x.T -D #溢出对策
# np.sum(a, axis=0) 表示的是将二维数组中的各个元素对应相加
# axis =1 时, 表示的是二维数组中的各自维的列相加
# axis =2 时, 表示的是二维数组中的各自维的行相加
y = np.exp(x) / np.sum(np.exp(x), axis=0)
return y.T
D = np.max(x)
exp_x = np.exp(x-D)
return exp_x / np.sum(exp_x)
另一个需要修改的地方如下代码所示:
accuracy_cnt = 0
batch_size = 100
# 要参与运算所以要使矩阵大小相同
x = test_dataset.test_data.numpy().reshape(-1, 28 * 28)
# 不需要参与运算,只需使Tensor 转换成numpy
labels = test_dataset.test_labels.numpy()
for i in range(0,len(x),batch_size):
x_batch = x[i:i+batch_size]
y_batch = forward(network, x_batch)
# 取最大值的索引,为了输出概率最大的预测值
# 在一维数组中argmax有一个参数axis,默认是0,表示每一列的最大值的索引 axis=1表示每一行的最大值的索引
# 而在二维数组中默认是求矩阵中的最大值的索引,axis=1表示求每列的最大值的索引,axis=2,表示求每行的最大值索引
p = np.argmax(y_batch,axis=1)
if p == labels[i:i+batch_size]:
accuracy_cnt += 1
print("Accuracy:" + str(float(accuracy_cnt) / len(x) * 100) + "%")
广播原则
广播原则是指如果两个数组的后缘维度(即从末尾开始算起的维度)的轴长度相符,或者其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。
下面举两个例子,代码如下:
import numpy as np
arr1 =np.array([[0,0,0],[1,1,1],[2,2,2],[3,3,3]])
arr2 = np.array([1,2,3])
arr_sum= arr1 + arr2
print(arr1.shape)
print(arr2.shape)
print(arr_sum)
运行结果:
可以看到,虽然他们维度不同,但是他们的后缘维度相等,arr1的第二个为3,其余arr2的维度相同,因此可以通过广播的原则进行相加 (列方向拉伸)。
下面再看第二个例子,代码如下:
import numpy as np
arr1 =np.array([[0,0,0],[1,1,1],[2,2,2],[3,3,3]])
arr2 = np.array([[1],[2],[3],[4]])
arr_sum= arr1 + arr2
print(arr1.shape)
print(arr2.shape)
print(arr_sum)
运行结果 如下:
arr1的shape为(4,3),arr2的shape为(4,1),它们都是二维的,但是arr2在1轴上的长度为1,因此可以通过广播的原则进行相加 (行方向拉伸)