ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

深度学习之神经网络(二)

2021-07-12 11:58:21  阅读:209  来源: 互联网

标签:loss ypred sigmoid h2 self 学习 神经网络 深度 out


深度学习之神经网络(一)

在前面文章中,我们已经系统了解了神经网络的部分概念,以及如何去搭建一个简单的神经网络模型。这篇文章我将主要讲解损失函数、反向传播等神经网络知识。


1. 损失函数

之前我们已经提到,损失函数就是用来计算我们的结果与真实值之间的误差,从而指导进一步的训练向正确的方向进行。

损失函数可以分为两大类:回归、分类。

1.1 回归损失

回归类的损失函数主要有MAE和MSE等。

1.1.1 MAE(Mean Absolute Error)

MAE为平均绝对误差,简单说就是计算输出值与真实值之间的误差绝对值大小的平均值。MAE是一种线性分数,所有个体差异在平均值上的权重都相等,比如,10和0之间的绝对误差是5和0之间绝对误差的两倍:

$$MAE(X,h)=\frac{1} {m}\sum_{i=1}^m | h(x_i)-y_i) |$$

  • 在高纬任务中表现比较好
  • 预测速度快
  • 对outliers(异常值)不敏感

1.1.2 MSE(Mean Square Error)

MSE为均方误差:

$$MSE(X,h)=\frac{1} {m}\sum_{i=1}^m (h(x_i)-y_i))^2$$

  • 比绝对误差函数得到的结果更精准
  • 对大的误差输出更敏感
  • 对outliers很敏感

1.2 分类损失

1.2.1 Cross-Entropy Loss

交叉熵损失,常在分类问题中使用,随着预测概率偏离实际标签,交叉熵会逐渐增加:

$$H(y,f)=-\sum_{i=1}^m y_i log(f(x_i))$$

  • 交叉熵能够衡量同一个随机变量中的两个不同概率分布的差异程度,在机器学习中就表示为真实概率分布与预测概率分布之间的差异。
  • 交叉熵经常搭配softmax使用,将输出的结果进行处理,使其多个分类的预测值和为1,再通过交叉熵来计算损失。


损失函数已经简单介绍完了,我们该如何训练神经网络,使得我们的损失最小呢?我们知道,梯度下降法是机器学习中一种用来“学习”参数的方法,神经网络中则可称为“反向传播”法。

2. 反向传播

前向传递输入信号直至输出产生误差,反向传播误差信息更新权重矩阵。

简单来说就是求偏导以及高数中的链式法则。(这里放个链接:反向传播,此文讲解的非常清楚)

假如我们有这样的一个数据集:

姓名身高体重性别
张三17062
陈四17565
王霞16045
李红16550

 为了方便处理,对其进行一定的处理:

 我们现在的目标就是训练一个神经网络,来预测性别:

代码示例:

import numpy as np


def sigmoid(x):
    # activation function
    return 1 / (1 + np.exp(-x))


def deriv_sigmoid(x):
    # derivative of sigmoid
    z = sigmoid(x)
    return z*(1 - z)


def mse_loss(y, yhat):
    # loss functionon
    return ((y - yhat) ** 2).mean()


class my_NN(object):
    # set all weights and biases
    def __init__(self):
        self.w1, self.w2, self.w3, self.w4, self.w5, self.w6 = np.random.randn(6)
        self.b1, self.b2, self.b3 = np.random.randn(3)

    def train(self, inputs, y_true):
        learn_rate = 0.1  # learning rate
        epochs = 1000  # number of times to loop through the entire dataset

        for epoch in range(epochs):
            # feedforward
            for x, y in zip(inputs, y_true):
                out_h1 = sigmoid(self.w1 * x[0] + self.w2 * x[1] + self.b1)
                out_h2 = sigmoid(self.w3 * x[0] + self.w4 * x[1] + self.b2)
                out_o1 = self.w5 * out_h1 + self.w6 * out_h2 + self.b3
                y_pred = sigmoid(out_o1)


                # - - - Naming: d_L_d_w1 represents "partial L / partial w1"
                # start calculating the backward error

                d_L_d_ypred = -2 * (y_true - y_pred)

                # the neuron in the output layer
                d_ypred_d_w5 = out_h1 * deriv_sigmoid(out_o1)
                d_ypred_d_w6 = out_h2 * deriv_sigmoid(out_o1)
                d_ypred_d_b3 = deriv_sigmoid(out_o1)

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

                # the one neuron in the hidden layer
                d_h1_d_w1 = x[0] * deriv_sigmoid(out_h1)
                d_h1_d_w2 = x[1] * deriv_sigmoid(out_h1)
                d_h1_d_b1 = deriv_sigmoid(out_h1)

                # another one
                d_h2_d_w3 = x[0] * deriv_sigmoid(out_h2)
                d_h2_d_w4 = x[0] * deriv_sigmoid(out_h2)
                d_h2_d_b2 = deriv_sigmoid(out_h2)

                # - - - update weights and biases
                # the neuron in the output layer
                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

                # the one neuron in the hidden layer
                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

                # another one
                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

            if (epoch+1)% 100 == 0:
                loss = mse_loss(y_true, y_pred)
                print("第%d次,loss为 %.5f" %(epoch+1, loss))


x = np.array([[15, 22],
             [20, 25],
             [5, 5],
             [10, 10],])

y = np.array([1,
              1,
              0,
              0,
              ])

mynn=my_NN()
mynn.train(x, y)

训练结果为:

第100次,loss为 0.00252
第200次,loss为 0.00119
第300次,loss为 0.00077
第400次,loss为 0.00057
第500次,loss为 0.00045
第600次,loss为 0.00038
第700次,loss为 0.00032
第800次,loss为 0.00028
第900次,loss为 0.00025
第1000次,loss为 0.00022

小结:梯度下降法是general的优化算法,反向传播法是其在神经网络上的具体实现方式。(开始以为它们两个都是相互独立的算法...)

标签:loss,ypred,sigmoid,h2,self,学习,神经网络,深度,out
来源: https://blog.csdn.net/weixin_48320163/article/details/118612870

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有