举例说明神经网络运行机制(附用numpy从零实现神经网络)

举例说明神经网络运行机制(附用numpy从零实现神经网络)

1.数据,问题,目的

在这里插入图片描述
数据如上图所示,输入为身高体重,输出为性别(1:男,0:女)。
目的:搭建一个神经网络,通过四条数据训练模型参数使模型可以根据输入给出输出。
在这里插入图片描述
Input:输入
Output :输出
Weight:实体权重

2.前向传播

(1)将身高作为input1,体重作为input2。
(2)H1 =f [(input1 * weight1) +(input2 * weight3) + b1],f[x]:激活函数,激活函数存在的意义是:采用非线性激活函数使整个网络非线性化,具备更强的拟合能力;使方向传播变的可能。因为,这时候梯度和误差会被同时用来更新权重和偏移。没有可微分的线性函数,这就不可能了。

def sigmoid(x):
    '''
    激活函数 f(x) = 1 / (1 + e^(-x))
    '''
    return 1 / (1 + np.exp(-x))

(3)H2 =f [(input1* weight2) +(input2 * weight4) + b2]
(4)output = f[(H1 * weight5) + (H2 * weight6) + b3],此时就得到了模型的预测值,前向传播就完成了。

3.反向传播

根据上述的前向传播得到的预测值,显然是不可靠的,因为权重并不是最优的。因此评判模型被训练到了一个什么样的程度以及如何迭代更新权重(包括如何更新权重)就成了重要的问题。
(1)评判标准:loss = ∑(y(true)-y(pred))(y(true)-y(pred))/n,loss值就是对送入训练的所有样本的真实值减去预测值的平方进行求平均值。

def mse_loss(y_true, y_pred):
    '''
    计算模型对某一样本的预测值与真实值之间的差别
    '''
    return ((y_true - y_pred) ** 2).mean()

(2)显然,上述的loss值越接近于0,证明预测值越接近真实值。输入是相同的,激活函数是相同的,最终能改变预测结果的就是可变的参数,可变的参数为weight1,weight2,weight3,weight4,weight5,weight6,b1,b2,b3,那么我们就需要更改这些参数来试着减小loss。
这些参数如何更改才会使得loss变小呢?(不妨把loss看成以权重和偏置为自变量的函数)
我们可以用loss值对每个权重求偏导,如果某一个结果为正,表示增加这个权重loss值就会相应的增加。

在这里插入图片描述
相同的道理可以计算loss对每个权重和偏置的偏导数。
(3)之后我们根据(2)中得到的结果对权重和偏执进行更新,更新的公式如下:
weight = weight -lr * (偏导数值)
b = b -lr * (偏导数值)

                # 参数更新
                self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w1
                self.w2 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w2
                self.b1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_b1

                self.w3 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w3
                self.w4 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w4
                self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_b2

                self.w5 -= learn_rate * d_L_d_ypred * d_ypred_d_w5
                self.w6 -= learn_rate * d_L_d_ypred * d_ypred_d_w6
                self.b3 -= learn_rate * d_L_d_ypred * d_ypred_d_b3

(4)将更新完的参数再放回网络中,再进行前向传播,计算loss,求偏导,更新参数一系列的循环,知道loss值为0为止(理论上来讲,实际上loss降到0的情况很少)。

下放完整代码:

import numpy as np

def sigmoid(x):
    '''
    激活函数 f(x) = 1 / (1 + e^(-x))
    '''
    return 1 / (1 + np.exp(-x))

def deriv_sigmoid(x):
    '''
    对sigmoid激活函数求导f'(x) = f(x) * (1 - f(x))
    '''
    fx = sigmoid(x)
    return fx * (1 - fx)

def mse_loss(y_true, y_pred):
    '''
    计算模型对某一样本的预测值与真实值之间的差别
    '''
    return ((y_true - y_pred) ** 2).mean()

class NeuralNetwork:
    def __init__(self):
        # 随机设置权重
        self.w1 = np.random.normal()
        self.w2 = np.random.normal()
        self.w3 = np.random.normal()
        self.w4 = np.random.normal()
        self.w5 = np.random.normal()
        self.w6 = np.random.normal()

        # 随机设置偏置
        self.b1 = np.random.normal()
        self.b2 = np.random.normal()
        self.b3 = np.random.normal()

    def feedforward(self, x):
        # 前向传播,计算当前节点应得到的值,对前一层所有与先节点连接的节点×权重+偏置并且激活
        # x即是train里的data里的一条数据 x[0]:该条数据的第一个特征 x[1]:该条数据的第二个特征
        h1 = sigmoid(self.w1 * x[0] + self.w2 * x[1] + self.b1)
        h2 = sigmoid(self.w3 * x[0] + self.w4 * x[1] + self.b2)
        o1 = sigmoid(self.w5 * h1 + self.w6 * h2 + self.b3)
        return o1

    def train(self, data, all_y_trues):
        '''
        输入数据为(nx2)的numpy数组,n代表有多少条数据
        输入标签为(nx1)的numpy数组,n代表有多少条数据(输入标签与输入数据一一对应)
        '''
        learn_rate = 0.1     # 学习率
        epochs = 1000        # 训练的轮次
###########################训练,迭代更新参数##############################
        for epoch in range(epochs):
            for x, y_true in zip(data, all_y_trues):
                sum_h1 = self.w1 * x[0] + self.w2 * x[1] + self.b1
                h1 = sigmoid(sum_h1)

                sum_h2 = self.w3 * x[0] + self.w4 * x[1] + self.b2
                h2 = sigmoid(sum_h2)

                sum_o1 = self.w5 * h1 + self.w6 * h2 + self.b3
                o1 = sigmoid(sum_o1)
                y_pred = o1
                # loss对参数求偏导
                d_L_d_ypred = -2 * (y_true - y_pred)

                d_ypred_d_w5 = h1 * deriv_sigmoid(sum_o1)
                d_ypred_d_w6 = h2 * deriv_sigmoid(sum_o1)
                d_ypred_d_b3 = deriv_sigmoid(sum_o1)

                d_ypred_d_h1 = self.w5 * deriv_sigmoid(sum_o1)
                d_ypred_d_h2 = self.w6 * deriv_sigmoid(sum_o1)

                d_h1_d_w1 = x[0] * deriv_sigmoid(sum_h1)
                d_h1_d_w2 = x[1] * deriv_sigmoid(sum_h1)
                d_h1_d_b1 = deriv_sigmoid(sum_h1)

                d_h2_d_w3 = x[0] * deriv_sigmoid(sum_h2)
                d_h2_d_w4 = x[1] * deriv_sigmoid(sum_h2)
                d_h2_d_b2 = deriv_sigmoid(sum_h2)

                # 参数更新
                self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w1
                self.w2 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w2
                self.b1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_b1

                self.w3 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w3
                self.w4 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w4
                self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_b2

                self.w5 -= learn_rate * d_L_d_ypred * d_ypred_d_w5
                self.w6 -= learn_rate * d_L_d_ypred * d_ypred_d_w6
                self.b3 -= learn_rate * d_L_d_ypred * d_ypred_d_b3
#########################################################################################

            # --- Calculate total loss at the end of each epoch
            if epoch % 10 == 0:
                y_preds = np.apply_along_axis(self.feedforward, 1, data)
                loss = mse_loss(all_y_trues, y_preds)
                print("Epoch %d loss: %.3f" % (epoch, loss))
###########创建数据##############
data = np.array([
    [180, 80], 
    [175, 60],  
    [160, 50],   
    [155, 52], 
    ])
all_y_trues = np.array([
    1, 
    1, 
    0, 
    0, 
    ])
model = NeuralNetwork()
model.train(data, all_y_trues)
这里是一个简单的基于 Python 和 PyTorch 的 GGNN 交通流预测代码示例,供您参考: 首先,需要导入所需的库和模块: ```python import torch import torch.nn as nn import torch.optim as optim import numpy as np import random from sklearn.metrics import mean_squared_error, mean_absolute_error ``` 然后,定义 GGNN 模型: ```python class GGNN(nn.Module): def __init__(self, num_nodes, num_features, num_classes, num_steps, hidden_size): super(GGNN, self).__init__() self.num_nodes = num_nodes self.num_features = num_features self.num_classes = num_classes self.num_steps = num_steps self.hidden_size = hidden_size self.W = nn.Linear(num_features, hidden_size) self.U = nn.Linear(hidden_size, hidden_size, bias=False) self.V = nn.Linear(hidden_size, num_classes) self.tanh = nn.Tanh() self.softmax = nn.Softmax(dim=1) def forward(self, A, X): h = self.W(X) for i in range(self.num_steps): m = torch.matmul(A, h) n = self.U(h) h = self.tanh(m + n) out = self.V(h) out = self.softmax(out) return out ``` 在 GGNN 模型中,我们使用线性层来对节点特征进行编码,并使用门控机制来更新节点状态。最后,我们使用线性层和 softmax 函数对输出进行计算。 接下来,定义训练和测试函数: ```python def train(model, optimizer, criterion, A, X, Y): model.train() optimizer.zero_grad() out = model(A, X) loss = criterion(out, Y) loss.backward() optimizer.step() return loss.item() def test(model, A, X, Y): model.eval() with torch.no_grad(): out = model(A, X) pred = torch.argmax(out, dim=1) acc = np.mean((pred == Y).cpu().numpy()) mae = mean_absolute_error(Y.cpu().numpy(), pred.cpu().numpy()) mse = mean_squared_error(Y.cpu().numpy(), pred.cpu().numpy()) return acc, mae, mse ``` 在训练函数中,我们首先将模型设置为训练模式,并将优化器的梯度设置为。然后,我们计算输出和损失,并进行反向传播和优化。在测试函数中,我们首先将模型设置为评估模式,并计算预测结果和评估指标。 最后,加载数据和运行模型: ```python # Load data A = ... # Adjacency matrix X = ... # Node features Y = ... # Labels # Split data train_idx = ... test_idx = ... # Initialize model model = GGNN(num_nodes, num_features, num_classes, num_steps, hidden_size) # Initialize optimizer and criterion optimizer = optim.Adam(model.parameters(), lr=learning_rate) criterion = nn.CrossEntropyLoss() # Train and test for epoch in range(num_epochs): random.shuffle(train_idx) for i in range(0, len(train_idx), batch_size): batch_idx = train_idx[i:i+batch_size] loss = train(model, optimizer, criterion, A[batch_idx,:][:,batch_idx], X[batch_idx], Y[batch_idx]) acc, mae, mse = test(model, A[test_idx,:][:,test_idx], X[test_idx], Y[test_idx]) print("Epoch {}: Test acc: {:.4f}, Test MAE: {:.4f}, Test MSE: {:.4f}".format(epoch+1, acc, mae, mse)) ``` 在代码中,我们首先加载数据,然后使用随机梯度下降法训练模型,并在每个 epoch 中使用测试集进行测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值