使用sigmoid函数,进行数据训练【进行了优化+出现梯度爆炸】

一、预期目标

在这里插入图片描述

二、实现的步骤

  1. 标签数据设置(即函数的x和y)
    在这里插入图片描述

注意:对于y的值中的x要用wx+b的方式表示出来(方便后面学习时候,w和b就是要学习的参数)

  1. 设置w,b的值(随机设置点)
    在这里插入图片描述
  2. 定义激活函数
    在这里插入图片描述

激活函数的作用:就是用来激活所要 求的函数
question:为什么循环2次?
answer:
内层循环:每一组_x都要生成学习后的y,以及计算每一个_y的损失
外层循环:改变w,b的值100次,去拟合目标图像

  1. 将激活函数的值即wx+b的值赋给sigmoid函数(要求的函数)在这里插入图片描述

这里和步骤1里面的y值设置是对应的,x的格式是wx+b

  1. 写出损失函数

在这里插入图片描述

为什么前面有个1/2?
损失函数求导之后,其系数直接就为1了

  1. 计算w 和 b的梯度(即对w和b进行求导)
    在这里插入图片描述

如何进行求导呢?
在这里插入图片描述

  1. 将w和b的值进行更新
    在这里插入图片描述

一定设置梯度逐渐的减小,即要乘以0.5

  1. 先进行梯度。在画出标签的图像
    在这里插入图片描述

因为使用的是_x,_y,所以直接将目标图像画出

  1. 计算出学习的y的值即v
    在这里插入图片描述

这里为什么使用循环?
一对w 和b的值将和初始给的_x值全部遍历一遍生成一组v,然后才能将每个点连接起来,绘制成一副该w和b下的图像
在这里插入图片描述

10.画出学习后的图像 (该组w和b生成的点连接起来画出的线)
在这里插入图片描述

学习的过程就是,是学习的w和b逐渐趋向于最开始赋值的便签值中的w和b
在这里插入图片描述

三、完整的代码

import numpy as np
import random
import math
import matplotlib.pyplot as plt


def sig():
    w = random.random()
    b = random.random()
    plt.ion()

    def sigmod(x):
        return 1 / (1 + math.e ** (-x))

    _x = np.arange(-10, 10, 0.1)
    _y = [sigmod(3 * i + 4) for i in _x]  # 标签值

    for i in range(100):
        for x,y in zip(_x,_y):
            net = w*x+b#前向
            out=sigmod(net)
            loss = 1/2*(out-y)**2
            dw =-(out-y)*(out-out**2)*x
            db =-(out-y)*(out-out**2)*1
            w = w+0.5*dw#后向
            b = b+0.5*db#后向
            print("w={},b={},loss={}".format(w,b,loss))
            plt.clf()#清空梯度
            plt.plot(_x,_y,".")
            v = [1/(1+math.e**(-(w*i+b))) for i in _x]
            plt.plot(_x,v,"b")
            plt.pause(0.01)
    plt.ioff()
    plt.show()

if __name__ == '__main__':#相当于一扇门
    sig()

四、优化:大大减小训练的速度

  1. 优化的地方一
  • 在设置标签值的时候,将x,y设置成一个数组,里面存放线性的值
    在这里插入图片描述
  1. 优化地方二

计算梯度和损失的时候,一次性对标签所有值全部进行计算并求和(不在一个点一个点的进行拟合)
在这里插入图片描述
3. 优化三

不进行一个点一个点的拟合,即不需要对每个标签点进行遍历,只需要当损失满足需要时,就停止拟合
在这里插入图片描述
4. 完整的代码如下

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-1,1,51)          #在-1到1中产生51个线性的数
print(type(x))
m = len(x)
y = (2*x+1)**3

w = np.random.rand()              #随机产生w,b
b = np.random.rand()
print(w,b)
plt.ion()

if __name__ == '__main__':
    i = 0
    loss = 1
    I = []
    Loss = []
    while loss>0.01:
        # i = i + 1
        y1 = (w*x+b)**3
        loss = sum(1/2*(y1-y)**2)
        dw = sum((y1-y)*3*(w*x+b)**2*x)
        db = sum((y1-y)*3*(w*x+b)**2*1)
        w = w - 0.00027 * dw
        b = b - 0.00014 * db
        print("w={},b={},loss={}".format(w, b, loss))
        plt.figure('拟合函数图')
        plt.clf()
        plt.plot(x, y, ".", c='r')
        v = (w * x + b)**3
        plt.plot(x, v, c='k')
        plt.pause(0.1)
        # I.append(i)
        # Loss.append(loss)
    # plt.figure('loss梯度下降图')
    # plt.plot(I, Loss)
    # print(i)
    plt.ioff()
    plt.show()

五、梯度爆炸产生的原因:

  • 学习率过高,即出现了梯度震荡,超过了需要的点,来回的进行震荡在这里插入图片描述
    在这里插入图片描述
  • 解决的办法就是降低学习率,如果出现拟合很慢的情况,那就不断调整学习率,直到合适为止

猜你喜欢

转载自blog.csdn.net/qq_43586192/article/details/109163112