1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
| import numpy as np
def affine_forward(x, w, b): """ 计算神经网络当前层的前馈传播,该方法计算在全连接情况下的得分函数。 注:如果不理解affine仿射变换,简单的理解为在全连接情况下的得分函数即可。
输入数据x的形状为(N, d_1, ..., d_k),其中N表示数据量,(d_1, ..., d_k)表示 每一通道的数据维度,如果是图片数据就为(长,宽,色道)。数据的总维度为 D = d_1 * ... * d_k,因此我们需要将数据重塑成形状为(N,D)的数组再进行仿射变换。 Inputs: - x: 输入数据,其形状为(N, d_1, ..., d_k)的numpy数组。 - w: 权重矩阵,其形状为(D,M)的numpy数组,D表示输入数据维度,M表示输出数据维度 可以将D看成输入的神经元个数,M看成输出神经元个数。 - b: 偏置向量,其形状为(M,)的numpy数组。 Returns 元组: - out: 形状为(N, M)的输出结果。 - cache: 将输入进行缓存(x, w, b)。 """ out = None N = x.shape[0] x_new = x.reshape(N, -1) out = np.dot(x_new, w)+b cache = (x, w, b) return out, cache
def affine_backward(dout, cache): """ 计算仿射层的反向传播.
Inputs: - dout: 形状为(N, M)的上层梯度 - cache: 元组: - x: (N, d_1, ... d_k)的输入数据 - w: 形状为(D, M)的权重矩阵
Returns 元组: - dx: 输入数据x的梯度,其形状为(N, d1, ..., d_k) - dw: 权重矩阵w的梯度,其形状为(D,M) - db: 偏置项b的梯度,其形状为(M,) """ x, w, b = cache dx, dw, db = None, None, None db = np.sum(dout, axis=0) xx = x.reshape(x.shape[0], -1) dw = np.dot(xx.T, dout) dx = np.dot(dout, w.T) dx = np.reshape(dx, x.shape) return dx, dw, db
def relu_forward(x): """ 计算rectified linear units (ReLUs)激活函数的前向传播,并保存相应缓存
Input: - x: 输入数据
Returns 元组: - out: 和输入数据x形状相同 - cache: x """ out = None out = np.maximum(0, x) cache = x return out, cache
def relu_backward(dout, cache): """ 计算 rectified linear units (ReLUs)激活函数的反向传播.
Input: - dout: 上层误差梯度 - cache: 输入 x,其形状应该和dout相同
Returns: - dx: x的梯度 """ dx, x = None, cache dx = dout dx[x<=0] = 0 return dx
def affine_relu_forward(x, w, b): """ ReLU神经元前向传播
Inputs: - x: 输入到 affine层的数据 - w, b: affine层的权重矩阵和偏置向量
Returns 元组: - out: ReLU的输出结果 - cache: 前向传播的缓存 """ a, fc_cache = affine_forward(x, w, b) out, relu_cache = relu_forward(a) cache = (fc_cache, relu_cache) return out, cache
def affine_relu_backward(dout, cache): """ ReLU神经元的反向传播 Input: - dout: 上层误差梯度 - cache: affine缓存,以及relu缓存
Returns: - dx: 输入数据x的梯度 - dw: 权重矩阵w的梯度 - db: 偏置向量b的梯度 """ fc_cache, relu_cache = cache da = relu_backward(dout, relu_cache) dx, dw, db = affine_backward(da, fc_cache) return dx, dw, db
def softmax_loss(x, y): ''' 计算Softmax损失函数
Parameters ---------- x : numpy数组 表示训练数据. y : numpy数组 表示数据类标。
Returns ------- loss : TYPE 数据损失值 dx : TYPE 梯度
''' probs = np.exp(x - np.max(x, axis=1, keepdims=True)) probs /= np.sum(probs, axis=1, keepdims=True) N = x.shape[0] loss = -np.sum(np.log(probs[np.arange(N), y])) / N dx = probs.copy() dx[np.arange(N), y] -= 1 dx /= N
return loss, dx
|