一、预期目标
二、实现的步骤
- 标签数据设置(即函数的x和y)
注意:对于y的值中的x要用wx+b的方式表示出来(方便后面学习时候,w和b就是要学习的参数)
- 设置w,b的值(随机设置点)
- 定义激活函数
激活函数的作用:就是用来激活所要 求的函数
question:为什么循环2次?
answer:
内层循环:每一组_x都要生成学习后的y,以及计算每一个_y的损失
外层循环:改变w,b的值100次,去拟合目标图像
- 将激活函数的值即wx+b的值赋给sigmoid函数(要求的函数)
这里和步骤1里面的y值设置是对应的,x的格式是wx+b
- 写出损失函数
为什么前面有个1/2?
损失函数求导之后,其系数直接就为1了
- 计算w 和 b的梯度(即对w和b进行求导)
如何进行求导呢?
- 将w和b的值进行更新
一定设置梯度逐渐的减小,即要乘以0.5
- 先进行梯度。在画出标签的图像
因为使用的是_x,_y,所以直接将目标图像画出
- 计算出学习的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()
四、优化:大大减小训练的速度
- 优化的地方一
- 在设置标签值的时候,将x,y设置成一个数组,里面存放线性的值
- 优化地方二
计算梯度和损失的时候,一次性对标签所有值全部进行计算并求和(不在一个点一个点的进行拟合)
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()
五、梯度爆炸产生的原因:
- 学习率过高,即出现了梯度震荡,超过了需要的点,来回的进行震荡
- 解决的办法就是降低学习率,如果出现拟合很慢的情况,那就不断调整学习率,直到合适为止