tensorflow 的整体实现需要的变量:
首先我们需要记录所有层,已经所有的权重信息,需要两个优化器,添加层时当前层的神经元个数
class NaiveNN:
def __init__(self):
# 记录所有的layer
self._layers = []
# 记录所有的权值矩阵,偏置量
self._weights = []
self._bias = []
# 记录着所有权值矩阵的和偏置量的优化器
self._w_optimizer = self._b_optimizer = None
# 记录着当前最后一个Layer所含的神经元个数
self._current_dimension = 0
添加层的处理:
def add(self, layer):
if not self._layers:
# 如果是第一次加入layer、则初始化相应的属性
self._layers = [layer]
self._current_dimension = layer.shape[1]
# 调用初始化权值矩阵和偏置量的方法
self._add_params(layer.shape)
else:
_next = layer.shape[0]
layer.shape = (self._current_dimension, _next)
# 调用进一步处理Layer的方法
self._add_layer(layer, self._current_dimension, _next)
def _add_params(self, shape):
self._weights.append(np.random.randn(*shape))
self._bias.append(np.zeros((1, shape[1])))
def _add_layer(self, layer, *args):
_current, _next = args
self._add_params((_current, _next))
self._current_dimension = _next
self._layers.append(layer)
优化器的处理:
训练时需要初始化优化器,选择哪个优化器以及初始参数。
def _init_optimizers(self, optimizer, lr, epoch):
# 利用定义好的优化器工厂来初始化优化器
# 注意由于最后一层是CostLayer对应的占位符、所以无需把它输进优化器
_opt_fac = OptFactory()
self._w_optimizer = _opt_fac.get_optimizer_by_name(
optimizer, self._weights[:-1], lr, epoch)
self._b_optimizer = _opt_fac.get_optimizer_by_name(
optimizer, self._bias[:-1], lr, epoch)
前向传播的处理:
遍历每一层前向传播计算结果。
# 前向传播求各层的结果
def _get_activations(self, x):
_activations = [self._layers[0].activate(x, self._weights[0], self._bias[0])]
for i, layer in enumerate(self._layers[1:]):
_activations.append(layer.activate(_activations[-1], self._weights[i+1], self._bias[i+1]))
return _activations
更新权重:
根据梯度更新每一层的权重
# 求对应层优化后的权重矩阵
def _opt(self, i, _activation, _delta):
self._weights[i] += self._w_optimizer.run(i, _activation.T.dot(_delta))
self._bias[i] += self._b_optimizer.run(i, np.sum(_delta, axis=0, keepdims=True))
训练:
训练过程:准备好优化器,计算每一层前向传播结果,反向传播计算每一层梯度,根据梯度更新每一层权重,重复epoch。
# 训练
def fit(self, x, y, lr=0.001, optimizer="Adam", epoch=10):
# 初始化优化器
self._init_optimizers(optimizer, lr, epoch)
layer_width = len(self._layers)
for counter in range(epoch):
# 更新学习率
self._w_optimizer.update()
self._b_optimizer.update()
# 前向传播计算每一层的结果
_activations = self._get_activations(x)
# costlayer单独计算梯度,delta
_deltas = [self._layers[-1].bp_first(y, _activations[-1])]
# 计算其它层的梯度,delta
for i in range(-1, -len(_activations), -1):
_deltas.append(self._layers[i-1].bp(_activations[i-1], self._weights[i], _deltas[-1]))
# 根据梯度更新权重
for i in range(layer_width -1, 0, -1):
self._opt(i, _activations[i-1], _deltas[layer_width -i -1])
self._opt(0, x, _deltas[-1])
预测:
根据得到的权重直接预测结果
def predict(self, x, get_raw_results=False):
y_pred = self._get_prediction(np.atleast_2d(x))
if get_raw_results:
return y_pred
return np.argmax(y_pred, axis=1)
def _get_prediction(self, x):
# 直接取前向传导算法得到的最后一个激活值即可
return self._get_activations(x)[-1]