通过梯度下降法估计数据x与y的关系

算法思路

  1. 加载并图形化数据散点
  2. 预估函数模型
  3. 通过梯度下降法求得模型中的未知参数
  4. 将未知参数代入模型,并用原始数据计算出损失函数值
  5. 对比预测模型和原始数据的对比图像

一、预设函数模型为y=ax+b的形式,进行计算

加载数据并展示

数据通过npz的方式加载

参考代码

import numpy as np
import matplotlib.pyplot as plt

#加载数据
npz = np.load(
    './1229/homework.npz')
x = npz['X']
d = npz['d']

plt.scatter(x, d, c='g')
plt.show()

图形如下

原始散点图

假设函数模型为 y=ax+b

通过已知数据训练未知参数 a b的过程,实际上是通过梯度下降法求得损失函数
loss = Σ(y-d)^2
取最小值时的 a 和 b 其中 y=ax+b x为数据中心的x列 d为数据中心的d列, 此时 x为已知量而a、b为未知量。所以需要求出损失函数对于 a和b的偏导数,作为梯度下降的方向,进行迭代训练。

  • 定义函数模型
#假设函数形式为y=ax+b 定义此函数
def func(xx, a, b):
    return a*xx+b
  • 求偏导
#损失函数梯度
def dfunc(xx, dd, a, b):
    yy = func(xx, a, b)
    dfdu = 2*(yy-dd)
    return dfdu*xx, dfdu

通过梯度下降法求得a、b

几个重要的参数及作用

  • 学习率:表示每次迭代,变量沿梯度方向前几的步长
  • 训练样本长度:因为可能样本数据比较庞大,需要从样本数据中随机抽取一定数量的数据进行训练以提高训练效率,这个随机抽取的数量即为训练样本长度。一般取 32 64 128 256 512 很少超过1000

训练代码

#学习率
eta = 0.01
#a,b初始值
a, b = 0, 0
#每次训练的样本取样大小
batch_size = 32
#开始训练
for i in range(1000):
    #抽样
    idx = np.random.randint(0, 1000, [batch_size])
    xin = x[idx]
    din = d[idx]
    #求梯度方向
    da, db = dfunc(xin, din, a, b)
    da = np.mean(da)
    db = np.mean(db)
    #梯度下降
    a -= eta*da
    b -= eta*db
    #输出每次得到的 a,b进行观察
    print("a={},b={}".format(a, b))

输出结果节选

...
a=5.000158971271038,b=-1.216844509845388
a=5.008072201329656,b=-1.2207602687746635
a=5.004705377973434,b=-1.2237844250445051
a=4.992377923571635,b=-1.233933937545008

从输出的结果可以看到,a、b的取值收敛,并未发生发散现象。如果训练过程中出现发散,可能是学习率过大引起的,可以适当调整学习率,但学习率也不是越小越好,因为学习率越小,收敛速度越慢。如果经过调整仍然发散,说明训练数据质量太低。

计算损失函数

#计算损失函数
y = func(x, a, b)
fv = (y-d)**2
fv = np.sum(fv)
print(fv)

输出

2506.357443475962

绘制对比图像

#训练得出的a/b代入方程并绘制图像
#训练数据集散点
plt.scatter(x, d, c='g')
#拟合数据线
xline = np.linspace(-2, 5, 100)
yline = func(xline, a, b)
plt.plot(xline, yline, c='r')
plt.show()

拟合图

拟合图

可以看到 图像在x∈(0,3)时的拟合较好,其余区间相差较大。说明预估的函数模型可能不是太好,下边设计更为复杂的函数模型进行训练。

二、预设函数模型为y = ax^2+bx+c 的形式,进行计算

加载数据并展示

数据及图像与上边没有差别,略过

假设函数模型为y = ax^2+bx+c

此时损失函数不变,仍然是
loss = Σ(y-d)^2
而函数模型发生了变化
y = ax^2+bx+c

,需要分别求出对于a、b、c的三个偏导数

  • 定义函数模型
#假设函数形式为y=ax^2+bx+c 定义此函数
def func(xx, a, b, c):
    return a*xx**2+b*xx+c
  • 求偏导
#损失函数梯度
def dfunc(xx, dd, a, b, c):
    yy = func(xx, a, b, c)
    dfdu = 2*(yy-dd)
    return 2*dfdu*xx, dfdu*xx, dfdu

通过梯度下降法求得a、b、c

几个重要的参数及作用

训练代码

#学习率
eta = 0.01
#a,b,c初始值
a, b, c = 0, 0, 0
#每次训练的样本取样大小
batch_size = 32
#开始训练
for i in range(1000):
    #抽样
    idx = np.random.randint(0, 1000, [batch_size])
    xin = x[idx]
    din = d[idx]
    #求梯度方向
    da, db, dc = dfunc(xin, din, a, b, c)
    da = np.mean(da)
    db = np.mean(db)
    dc = np.mean(dc)
    #梯度下降
    a -= eta*da
    b -= eta*db
    c -= eta*dc
    #输出每次得到的 a,b,c进行观察
    print("a={},b={},c={}".format(a, b, c))

输出结果节选

...
a=1.4479619445681633,b=0.7239809722840816,c=0.43759564975538157
a=1.397188399611841,b=0.6985941998059205,c=0.4329935818605244
a=1.414083870087496,b=0.707041935043748,c=0.43991713435825186
a=1.4270933097900267,b=0.7135466548950133,c=0.4432868578503474
a=1.4256464616514657,b=0.7128232308257328,c=0.4461338224887574
a=1.447148708817503,b=0.7235743544087515,c=0.4512765222504626

同样预测参数未出现发散现象,如果学习率设为0.1则会出现发散。

计算损失函数

#计算损失函数
y = func(x, a, b, c)
fv = (y-d)**2
fv = np.sum(fv)
print(fv)

输出

750.8559171548692

可见,本次预估的函数模型下,损失函数值大幅度减小,说明函数模型更由于第一次的函数模型。

绘制对比图像

#训练得出的a/b代入方程并绘制图像
#训练数据集散点
plt.scatter(x, d, c='g')
#拟合数据线
xline = np.linspace(-2, 5, 100)
yline = func(xline, a, b, c)
plt.plot(xline, yline, c='r')
plt.show()

拟合图

拟合图

从拟合图中可以看出,拟合效果比上个模型的效果好了很多,但仍然存在一些区间上,预测值与真实值相差较大。

总结

本文只是简单说明了梯度下降法的基本思想,并通过两个简单的模型进行了训练和预测。实际中遇到的数据模型会非常复杂,如何构建更加复杂的模型使预测结果更加贴合实际数据,还需要通过不断的学习。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352