定义全连接层,实现 a=g(x*W+b),前向传播输入x,返回a;反向传播输入
| 72 | |
| 73 | |
| 74 | class FullyConnected(LayerBase): |
| 75 | """ |
| 76 | 定义全连接层,实现 a=g(x*W+b),前向传播输入x,返回a;反向传播输入 |
| 77 | """ |
| 78 | |
| 79 | def __init__(self, n_out, acti_fn, init_w, optimizer=None): |
| 80 | """ |
| 81 | 参数说明: |
| 82 | acti_fn:激活函数, str型 |
| 83 | init_w:权重初始化方法, str型 |
| 84 | n_out:隐藏层输出维数 |
| 85 | optimizer:优化方法 |
| 86 | """ |
| 87 | super().__init__(optimizer) |
| 88 | |
| 89 | self.n_in = None # 隐藏层输入维数, int型 |
| 90 | self.n_out = n_out # 隐藏层输出维数, int型 |
| 91 | self.acti_fn = ActivationInitializer(acti_fn)() |
| 92 | self.init_w = init_w |
| 93 | self.init_weights = WeightInitializer(mode=init_w) |
| 94 | self.is_initialized = False # 是否初始化, bool型变量 |
| 95 | |
| 96 | def _init_params(self): |
| 97 | b = np.zeros((1, self.n_out)) |
| 98 | W = self.init_weights((self.n_in, self.n_out)) |
| 99 | self.params = {"W": W, "b": b} |
| 100 | self.gradients = {"W": np.zeros_like(W), "b": np.zeros_like(b)} |
| 101 | self.derived_variables = {"Z": []} |
| 102 | self.is_initialized = True |
| 103 | |
| 104 | def forward(self, X, retain_derived=True): |
| 105 | """ |
| 106 | 全连接网络的前向传播,原理见上文 反向传播算法 部分。 |
| 107 | |
| 108 | 参数说明: |
| 109 | X:输入数组,为(n_samples, n_in),float型 |
| 110 | retain_derived:是否保留中间变量,以便反向传播时再次使用,bool型 |
| 111 | """ |
| 112 | if not self.is_initialized: # 如果参数未初始化,先初始化参数 |
| 113 | self.n_in = X.shape[1] |
| 114 | self._init_params() |
| 115 | |
| 116 | W = self.params["W"] |
| 117 | b = self.params["b"] |
| 118 | z = X @ W + b |
| 119 | a = self.acti_fn.forward(z) |
| 120 | |
| 121 | if retain_derived: |
| 122 | self.X.append(X) |
| 123 | |
| 124 | return a |
| 125 | |
| 126 | def backward(self, dLda, retain_grads=True): |
| 127 | """ |
| 128 | 全连接网络的反向传播,原理见上文 反向传播算法 部分。 |
| 129 | |
| 130 | 参数说明: |
| 131 | dLda:关于损失的梯度,为(n_samples, n_out),float型 |
no outgoing calls
no test coverage detected