纯Numpy实现多层神经网络

纯Numpy实现多层神经网络

本文分为以下几个内容

1.实现层的逻辑结构
2.实现各种激活函数
3.实现Dense层
4.实现前向传播
5.实现反向传播
6.示例

实现网络层的逻辑:

首先实现一个简单的网络层,该网络层什么也不做,就是前向传播,来什么,就前向传播什么。

# 定义一个layer
class Layer:
    def __init__(self):
        pass
    def forward(self, input):
        return input
    def backward(self, input, grad_output):
        pass

实现基本的神经网络激活函数:

# 定义Relu层
class ReLU(Layer):
    def __init__(self):
        pass
    def forward(self,input):
        return np.maximum(0,input) # relu函数为max(0,x)
    def backward(self,input,grad_output):
        relu_grad = input>0        #relu函数导数为1 if x>0 else 0
        return grad_output*relu_grad

实现Sigmoid层

class Sigmoid(Layer):
    def __init__(self):
        pass
    
    def _sigmoid(self,x):
        return 1.0/(1+np.exp(-x))
    
    def forward(self,input):
        return self._sigmoid(input)
    
    def backward(self,input,grad_output):
        sigmoid_grad = self._sigmoid(input)*(1-self._sigmoid(input))
        return grad_output*sigmoid_grad

实现Tanh层

class Tanh(Layer):
    def __init__(self):
        pass
    def _tanh(self,x):
        return np.tanh(x)
    def forward(self,input):
        return self._tanh(input)
    def backward(self, input, grad_output):
        grad_tanh = 1-(self._tanh(input))**2
        return grad_output*grad_tanh

还有各种各样的激活函数,只要继承了Layer类即可。

实现Dense

一个Dense包括层,权重以及偏置,同时也包括前向传播,反向传播,反向传播,公式如下

前向传播

[公式]在这里插入图片描述

反向传播

[公式]

在这里插入图片描述

那么这样就很明显了,我们实现前向传播以及反向传播:

class Dense(Layer):
    def __init__(self, input_units, output_units, learning_rate=0.01):
        self.learning_rate = learning_rate
        self.weights = np.random.randn(input_units, output_units)*0.01
        self.biases = np.zeros(output_units)
    def forward(self,input):
        return np.dot(input,self.weights)+self.biases
    def backward(self,input,grad_output):
        grad_input = np.dot(grad_output, self.weights.T)
        grad_weights = np.dot(input.T,grad_output)/input.shape[0]
        grad_biases = grad_output.mean(axis=0)
        self.weights = self.weights - self.learning_rate*grad_weights
        self.biases = self.biases - self.learning_rate*grad_biases
        return grad_input

通过上面的工作,如果我们需要构建一个神经网络,我们可以这样:

network = []
network.append(Dense(1,50))
network.append(Tanh())
network.append(Dense(50,1))

这样,就构建了一个只含有一个隐藏层的神经网络:

前向传播

def forward(network,X):
    activations = []
    input = X
    for layer in network:
        activations.append(layer.forward(input))
        input = activations[-1]
                
    assert len(activations) == len(network)
    return activations

预测:

def predict(network,X):
    logits = forward(network,X)[-1]
    return logits

训练:
训练的时候需要损失函数,这里我只定义了一个mse损失函数

def train(network,X,y):    
    layer_activations = forward(network,X)
    layer_inputs = [X]+layer_activations  
    logits = layer_activations[-1]
    
    # 这里的损失函数需要自己定义
    loss = np.square(logits - y).sum()
    loss_grad = 2.0*(logits-y)
    
    for layer_i in range(len(network))[::-1]:
        layer = network[layer_i]
        loss_grad = layer.backward(layer_inputs[layer_i],loss_grad) #grad w.r.t. input, also weight updates
        
    return np.mean(loss)

这样,整个神经网络就搭建起来。

我们使用该神经网络拟合 [公式]:y=sinx

首先构建训练集和测试集:

x_train = np.linspace(-np.pi,0.7 * np.pi,140).reshape(140,-1)
y_train = np.sin(x_train)
x_test = np.linspace(np.pi*0.7,np.pi,60).reshape(60,-1)
y_test = np.sin(x_test)

使用刚刚我们定义的神经网络:

losses = []
for h in range(3,100):
    network = []
    network.append(Dense(1,h))
    network.append(Tanh())
    network.append(Dense(h,1))
    ll = []
    for e in range(100000):
        loss = train(network,x_train,y_train)
        ll.append(loss)
    print(np.mean(ll[-1000:]))
    losses.append(np.mean(ll[-1000:]))

通过对含有一个隐藏层的神经元个数分析

可以发现
在这里插入图片描述
当隐藏层神经元为94的时候,该loss是最小的,于是,我们将神经元个数设置为94

进行训练:

在这里插入图片描述
看起来效果不错,我们将图画出来:

在这里插入图片描述
看起来神经网络对历史的拟合是非常完美的,但是对未来的预测还是有点差强人意。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值