目录

  • 线性回归 - 宝可梦案例
    • 一、案例分析
    • 二、案例实现
      • (1)准备工作
      • (2)进行数据的导入
      • (3)绘制损失函数的热点图
      • (4)线性回归梯度下降计算w和b
      • (5)绘制结果图
    • 三、结果显示及优化
      • (1)第一次结果
      • (2)优化后第二次结果
      • (3)优化后第三次结果
    • 四、采用Adagrad 算法更新参数
      • (1)什么是Adagrad 算法?
      • (2)Adagrad算法举例及化简
      • (3)通过Adagrad算法实现参数更新
      • (4)使用算法后的结果展示
    • 五、案例总结
      • (1)个人感受
      • (2)过程遇到的疑惑及解答
    • 六、完整代码

线性回归 - 宝可梦案例

一、案例分析

假设有10个已知的 x_data 和 y_data ,x 和 y之间的关系是
y_data = b + w * x_data ,需要通过线性回归学习得到w与b。

其中已知:
进化前cp值,x_data为[338., 333., 328., 207., 226., 25., 179., 60., 208., 606.];
进化后cp值,y_data为[640., 633., 619., 393., 428., 27., 193., 66., 226., 1591.]

模型使用:linear model
工具使用:jupyter

二、案例实现

(1)准备工作

需要用到的库有:numpy、 matplotlib.pyplot

  • 导入库函数
import numpy as np
import matplotlib.pyplot as plt
  • Matplotlib没有中文字体等的动态解决方法
plt.rcParams['font.sans-serif'] = ['Simhei']  # 显示中文
from pylab import mpl
mpl.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题

(2)进行数据的导入

# 进化前的cp值
x_data = [338., 333., 328., 207., 226., 25., 179., 60., 208., 606.]
# 进化后的cp值
y_data = [640., 633., 619., 393., 428., 27., 193., 66., 226., 1591.]

(3)绘制损失函数的热点图

什么是损失函数热点图??
即通过将所有的可能范围内的w和b的组合情况下的损失结果直接在图中通过热力图的形式显示出来,并作为之后的训练过程的背景。
达到的效果:
线性回归中常用的损失函数 Loss function 是:

L(w,b) = ∑ n = 1 10 ( y ˇ n − ( b + w ⋅ x c p ) ) 2 \sum_{n=1}^{10}(\check{y}^{n}-(b+w\cdot x_{cp}))^2 ∑n=110​(yˇ​n−(b+w⋅xcp​))2

x = np.arange(-200, -100, 1)   # x轴坐标-200到200,间距为1
y = np.arange(-5, 5, 0.1)      # y轴坐标-5到5,间距为0.1
#按照x,y轴的长度生成一个二维矩阵,元素全0填充
L = np.zeros((len(x), len(y)))
# 损失值Loss
for i in range(len(x)):for j in range(len(y)):b = x[i]  # b表示横轴w = y[j]  # w表示纵轴# 每一个w和b组合 => 一个Loss Functionfor n in range(len(x_data)):L[j][i] = L[j][i] + (y_data[n] - b - w * x_data[n] ) ** 2 # 损失累加# 计算这种w和b的组合下,损失的平均值L[j][i]  /=  len(x_data)

(4)线性回归梯度下降计算w和b

需要计算 Loss 关于 w 和 b 的偏微分,模拟梯度下降过程。
由Loss function推导公式如下:

∂ L ∂ w = ∑ 1 n 2 ⋅ [ y _ t r u e − ( w ⋅ x i + b ) ] ⋅ ( − x i ) \frac{∂L}{∂w}=\sum_{1}^{n}2\cdot[y\_true-(w\cdot x^i+b)]\cdot(-x^i) ∂w∂L​=∑1n​2⋅[y_true−(w⋅xi+b)]⋅(−xi)

∂ L ∂ b = ∑ 1 n 2 ⋅ [ y _ t r u e − ( w ⋅ x i + b ) ] ⋅ ( − 1 ) \frac{∂L}{∂b}=\sum_{1}^{n}2\cdot[y\_true-(w\cdot x^i+b)]\cdot(-1) ∂b∂L​=∑1n​2⋅[y_true−(w⋅xi+b)]⋅(−1)

# linear regression
#1、给参数赋任意初始值
b = -120    #bias
w = -4      #表示x特征的权重
lr = 0.0000001 #学习率
iteration = 100000 #迭代次数
b_history = [b]   #保存训练过程的所有b
w_history = [w]  #保存训练过程的所有w
#2、模拟梯度下降过程
for i in range(iteration):grad_b = 0.0 # b的偏微分grad_w = 0.0 # w的偏微分#求w和b的偏导for j in range(len(x_data)):grad_b += 2 * (y_data[j] - w * x_data[j] -b) * (-1)grad_w += 2 * (y_data[j] - w * x_data[j] -b) * (-x_data[j])# update w、bb -= lr * grad_bw -= lr * grad_w
#保存参数w、b的历史值b_history.append(b)w_history.append(w)

(5)绘制结果图

利用 matplotlib 里的函数即可

# 填充背景,按照损失的大小绘制等高线
plt.contourf(x, y, L, 50, alpha=0.5, cmap=plt.get_cmap('jet'))
# 绘制出最佳结果点,用x标记
plt.plot([-188.4], [2.67], 'x', ms=12, mew=3, color='orange')
#绘制出w和b历史轨迹
plt.plot(b_history, w_history, 'o-', ms=3, lw=1.5, color='black')
# 图像的基本参数设置
plt.xlim(-200, -100)
plt.ylim(-5, 5)
plt.xlabel('b')
plt.ylabel('w')
plt.title('线性回归')
plt.show()

三、结果显示及优化

(1)第一次结果


这张图是 学习率 Ir 为 0.0000001时 损失函数随w、b变化图,黑色线区域为计算的 w、b的历史轨迹,黄色叉叉处是我们需要得到的最优解。

结果可知,经过100000次的update,我们最终的参数离最佳解仍然非常的遥远。
结论:学习率learning rate不够大,将其增大到Ir = 0.000001(初始的10倍)

(2)优化后第二次结果


结果可知,经过100000次的update,参数离最佳解更近了,但出现了剧烈的震荡,且仍未达到最佳解。

结论:学习率learning rate不够大,将其增大到Ir = 0.00001(初始的100倍)

(3)优化后第三次结果


结果可知,我们的损失函数变化过程中,并没有和理想中的一样 靠近最佳解,反而出现了很大的震荡,说明由于学习速率过大,导致更新参数的时候,一次性步长过大,就很难收敛到我们设定好的理想损失值处,从而呈现出了发散状态。

结论:学习速率过大了,因此上一次直接增大lr为初始值的100倍是不合理的。

解决方案

  • 很明显,若直接将学习率增大到100倍,会导致学习率过大,但是增大到10倍则学习率过小,可以尝试继续采用更新学习率的方式,一步一步的调整学习率,缩小范围,从而得到最佳解。
  • 直接采用 Adagrad 算法更新参数 ,怎么实现呢?接下来,我们来学习尝试一下。

四、采用Adagrad 算法更新参数

(1)什么是Adagrad 算法?

直观看公式
如果常规的梯度下降表示方法是:

w t + 1 = w t − η t ⋅ g t w^{t+1}=w^t-\eta^t\cdot g^t wt+1=wt−ηt⋅gt

那么Adagrad算法的梯度下降就是:

w t + 1 = w t − η t σ t ⋅ g t w^{t+1}=w^t-\frac{\eta^t}{\sigma^t}\cdot g^t wt+1=wt−σtηt​⋅gt

通俗来讲:Adagrad算法就是加入了 σ ,使得原本不变的学习率开始时刻随着 w 与 b 的梯度变化着。

所以公式中的 σ t \sigma^t σt的含义就是:之前参数的所有微分的均方根

(2)Adagrad算法举例及化简

w 1 ⟵ w 0 ⟵ η 0 σ 0 ⋅ g 0 σ 0 = ( g 0 ) 2 w^1\longleftarrow w^0\longleftarrow\frac{\eta^0}{\sigma^0}\cdot g^0\qquad\sigma^0=\sqrt{(g^0)^2} w1⟵w0⟵σ0η0​⋅g0σ0=(g0)2 ​
w 2 ⟵ w 1 ⟵ η 1 σ 1 ⋅ g 1 σ 1 = 1 2 [ ( g 0 ) 2 + ( g 1 ) 2 ] w^2\longleftarrow w^1\longleftarrow\frac{\eta^1}{\sigma^1}\cdot g^1\qquad\sigma^1=\sqrt{\frac{1}{2}[(g^0)^2+(g^1)^2]} w2⟵w1⟵σ1η1​⋅g1σ1=21​[(g0)2+(g1)2] ​
w 3 ⟵ w 2 ⟵ η 2 σ 2 ⋅ g 2 σ 2 = 1 3 [ ( g 0 ) 2 + ( g 1 ) 2 + ( g 2 ) 2 ] w^3\longleftarrow w^2\longleftarrow\frac{\eta^2}{\sigma^2}\cdot g^2\qquad\sigma^2=\sqrt{\frac{1}{3}[(g^0)^2+(g^1)^2+(g^2)^2]} w3⟵w2⟵σ2η2​⋅g2σ2=31​[(g0)2+(g1)2+(g2)2] ​
↓ ↓ ↓ ↓ \downarrow\qquad\qquad\downarrow\qquad\qquad\downarrow\qquad\downarrow ↓↓↓↓
w t + 1 ⟵ w t ⟵ η t σ t ⋅ g t σ t = 1 t + 1 ∑ i = 0 t ( g i ) 2 w^{t+1}\longleftarrow w^t\longleftarrow\frac{\eta^t}{\sigma^t}\cdot g^t\qquad\sigma^t=\sqrt{\frac{1}{t+1}\sum_{i=0}^t(g^i)^2} wt+1⟵wt⟵σtηt​⋅gtσt=t+11​∑i=0t​(gi)2 ​

注意:根号中累加后需要除以计数,然后才开根号(即求均方根)

最后公式可以化简得到w t + 1 = w t − η ∑ i = 0 t ( g i ) 2 ⋅ g t w^{t+1}=w^t-\frac{\eta}{\sqrt{\sum_{i=0}^t(g^i)^2}}\cdot g^t wt+1=wt−∑i=0t​(gi)2 ​η​⋅gt
(化简步骤在本文后的总结疑问中会提到)

(3)通过Adagrad算法实现参数更新

# 1.给参数附任意初始值
b = -120
w = -4
lr = 1  # 学习率
iteration = 100000  # 迭代次数b_history = [b]  # 保存训练过程的所有b
w_history = [w]  # 保存训练过程的所有wlr_w = 0
lr_b = 0
# 2.模拟回归过程
for i in range(iteration):grad_w = 0.0  # w的偏微分grad_b = 0.0  # b的偏微分for j in range(len(x_data)):grad_w += 2 * (y_data[j] - w * x_data[j] - b) * (-x_data[j])grad_b += 2 * (y_data[j] - w * x_data[j] - b) * (-1)# 采用化简后的Adagrad算法公式更新参数lr_w = lr_w + grad_w ** 2lr_b = lr_b + grad_b ** 2w = w - lr / np.sqrt(lr_w) * grad_wb = b - lr / np.sqrt(lr_b) * grad_b# 保存历史参数w_history.append(w)b_history.append(b)

(4)使用算法后的结果展示


该图是采用Adagrad算法更新参数函数的损失变化图,如图可以直观看到,最终我们的参数达到了我们期望的最优解,即完成目标。

五、案例总结

(1)个人感受

本次案例 通过少量的数据 重现了线性回归的模型

涉及的知识点:

  • 损失函数Loss
  • 梯度下降(Gradient Descent)
    • Loss关于w、b的偏微分公式
  • Numpy、matplotlib函数的使用
  • Adagrad算法

通过这次的案例,让我体会了线性回归的整个过程,更深刻得理解了其中w、b的update过程(梯度下降),以及利用梯度下降和Adagrad算法找到最优解的过程,很奇妙。

(2)过程遇到的疑惑及解答

1、为什么Adagrad算法可以达到目的,算法如何化简得到公式: w t + 1 = w t − η ∑ i = 0 t ( g i ) 2 ⋅ g t w^{t+1}=w^t-\frac{\eta}{\sqrt{\sum_{i=0}^t(g^i)^2}}\cdot g^t wt+1=wt−∑i=0t​(gi)2 ​η​⋅gt,化简后的公式有什么用?
答:
普通的梯度下降需要人工手动调整学习率,很明显这是一个麻烦的方法,因为学习率过大或者过小都是不行的,很难手动找到那个合适的值。
而Adagrad算法能够让学习率随着迭代次数增加而变小,初始迭代时,使用较大的学习率加速下降;迭代几次后,减小学习率防止振荡和越过;且对每个参数都使用了不同的却合适的学习率。
公式化简得到 w t + 1 = w t − η ∑ i = 0 t ( g i ) 2 ⋅ g t w^{t+1}=w^t-\frac{\eta}{\sqrt{\sum_{i=0}^t(g^i)^2}}\cdot g^t wt+1=wt−∑i=0t​(gi)2 ​η​⋅gt:
初始公式: w t + 1 = w t − η t σ t ⋅ g t w^{t+1}=w^t-\frac{\eta^t}{\sigma^t}\cdot g^t wt+1=wt−σtηt​⋅gt

而 η t = η t + 1 σ t = 1 t + 1 ⋅ ∑ i = 0 t ( g i ) 2 \eta^t =\frac{\eta}{\sqrt{t+1}}\qquad\sigma^t=\sqrt{\frac{1}{t+1}\cdot \sum_{i=0}^t(g^i)^2} ηt=t+1 ​η​σt=t+11​⋅∑i=0t​(gi)2 ​

将它们代入初始公式中,化简相约,即可得到化简公式

w t + 1 = w t − η ∑ i = 0 t ( g i ) 2 ⋅ g t w^{t+1}=w^t-\frac{\eta}{\sqrt{\sum_{i=0}^t(g^i)^2}}\cdot g^t wt+1=wt−∑i=0t​(gi)2 ​η​⋅gt
而我们就是利用了化简后的公式去计算更新参数的:

# 采用化简后的Adagrad算法公式更新参数
lr_w = lr_w + grad_w ** 2
lr_b = lr_b + grad_b ** 2
w = w - lr / np.sqrt(lr_w) * grad_w
b = b - lr / np.sqrt(lr_b) * grad_b

2、初始加入数据时,数字后 有点 和 没点 有什么区别吗?

答:
其实很简单,有点表示float类型,没点表示int类型,然而在我们的计算中,要保证精确,自然是使用float类型,因此,加上点更合适。
3、除了用常规公式求偏导,其实还有另一种(下图)求偏导的方式,是怎么做到的呢?

答:
常规求偏导是:

对比两种方法,一种用了循环逐一求,一种直接使用了函数对矩阵进行计算,说明一下w的求导变换:
变换后的是:grad_w = -2.0 * np.dot(y_d - y_hat, x_d)
其中:y_hat = w * x_data[j] -b,表示的是预测的y值,则y_d - y_hat就是实际值与预测值间的差值,y_d - y_hat = y_data[j] - w * x_data[j] -b,np.dot()将y_d - y_hat与x_d每一项分别相乘再相加,即达到了(y_data[j] - w * x_data[j] -b) * x_data[j]的效果,最后乘以-2 即 得到2 * (y_data[j] - w * x_data[j] -b) * (-x_data[j])。
b的求导变换也类似。
所以两种方法的式子最后结果都一样,只是运用的方法不同,常规求导更好理解,但另一种方法显得更高级,各有千秋。

六、完整代码

import numpy as np
import matplotlib.pyplot as plt
# matplotlib没有中文字体,动态解决
plt.rcParams['font.sans-serif'] = ['Simhei']  # 显示中文
from pylab import mpl
mpl.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题
# 进化前的cp值
x_data = [338., 333., 328., 207., 226., 25., 179., 60., 208., 606.]
# 进化后的cp值
y_data = [640., 633., 619., 393., 428., 27., 193., 66., 226., 1591.]
x = np.arange(-200, -100, 1)   # x轴坐标-200到200,间距为1
y = np.arange(-5, 5, 0.1)      # y轴坐标-5到5,间距为0.1
#按照x,y轴的长度生成一个二维矩阵,元素全0填充
L = np.zeros((len(x), len(y)))
# 损失值Loss
for i in range(len(x)):for j in range(len(y)):b = x[i]  # b表示横轴w = y[j]  # w表示纵轴# 每一个w和b组合 => 一个Loss Functionfor n in range(len(x_data)):L[j][i] = L[j][i] + (y_data[n] - b - w * x_data[n] ) ** 2 # 损失累加# 计算这种w和b的组合下,损失的平均值L[j][i]  /=  len(x_data)
# 1.给参数附任意初始值
b = -120
w = -4
lr = 1  # 学习率
iteration = 100000  # 迭代次数b_history = [b]  # 保存训练过程的所有b
w_history = [w]  # 保存训练过程的所有wlr_w = 0
lr_b = 0
# 2.模拟回归过程
for i in range(iteration):grad_w = 0.0  # w的偏微分grad_b = 0.0  # b的偏微分for j in range(len(x_data)):grad_w += 2 * (y_data[j] - w * x_data[j] - b) * (-x_data[j])grad_b += 2 * (y_data[j] - w * x_data[j] - b) * (-1)# 采用化简后的Adagrad算法公式更新参数lr_w = lr_w + grad_w ** 2lr_b = lr_b + grad_b ** 2w = w - lr / np.sqrt(lr_w) * grad_wb = b - lr / np.sqrt(lr_b) * grad_b# 保存历史参数w_history.append(w)b_history.append(b)
# 绘制变化图
# 填充等高线
plt.contourf(x, y, L, 50, alpha=0.5, cmap=plt.get_cmap('jet'))
plt.plot([-188.4], [2.67], 'x', ms=12, mew=3, color='orange')
plt.plot(b_history, w_history, 'o-', ms=3, lw=1.5, color='black')
plt.xlim(-200, -100)
plt.ylim(-5, 5)
plt.xlabel('b')
plt.ylabel('w')
plt.title('线性回归')
plt.show()

线性回归 - 宝可梦案例相关推荐

  1. 【惊呆】《精灵宝可梦Go》游戏迷的疯狂行为

    <精灵宝可梦Go>是由任天堂.Pokémon公司和谷歌Niantic Labs公司联合制作开发的现实增强(AR)宠物养成对战类RPG手游.该作于2016年7月7日在澳大利亚新西兰区域首发, ...

  2. python10-宝可梦数据分析-平民最强宝可梦系列(从0-1数据分析实战)

    宝可梦数据分析-平民最强宝可梦选择方案 快来和我一起选择属于你最强的宝可梦吧 数据时代的到来刷新了人们探索未知的方式,从基础能源建设到航天航空工程.在关都地区真新镇大木研究所一直孜孜不倦对精灵宝可梦进 ...

  3. 把宝可梦搬到终端后,摸鱼也不会被老板发现了,收集对战玩法一应俱全|开源...

    鱼羊 发自 凹非寺 量子位 | 公众号 QbitAI 在电脑终端里当上宝可梦大师,是一种怎样的体验? 别说,还真有玩家不满足于在老任家捕捉小精灵,动手把宝可梦游戏搬到了终端里. 玩法那也是像模像样. ...

  4. 给终端装上宝可梦主题!小姐姐路过都爱上了!

    大家好,我是TJ 一个励志推荐10000款开源项目与工具的程序员 就算不怎么玩游戏看动漫的小伙伴,多多少少也应该知道宠物小精灵,按现在的叫法,就是精灵宝可梦,知道那只黄色的会放电的看着毛茸茸超可爱的只 ...

  5. pokemon 下载 android,宝可梦pokemon home

    宝可梦pokemon home是一款非常好玩的卡通画风的模拟经营游戏,游戏名为宝可梦pokemon home,这款游戏的背景就是大家相当熟悉的宝可梦,宝可梦pokemon home这款游戏的操作难度不 ...

  6. 宝可梦维护服务器,宝可梦大师卡在登录界面进不去,宝可梦大师为啥玩不了

    游戏介绍:<宝可梦大师>是一款由The Pokemon Company发行的手机游戏. 游戏中玩家将扮演训练家,带领宝可梦和队员们以"世界宝可梦大师赛"的冠军为目标开始 ...

  7. 用python画皮卡丘源代码-实现童年宝可梦,教你用Python画一只属于自己的皮卡丘...

    原标题:实现童年宝可梦,教你用Python画一只属于自己的皮卡丘 大数据文摘出品 作者:李雷.蒋宝尚 还记得小时候疯狂收集和交换神奇宝贝卡片的经历吗? 还记得和小伙伴拿着精灵球,一起召唤小精灵的中二模 ...

  8. python简单代码画皮卡丘-实现童年宝可梦,教你用Python画一只属于自己的皮卡丘...

    原标题:实现童年宝可梦,教你用Python画一只属于自己的皮卡丘 大数据文摘出品 作者:李雷.蒋宝尚 还记得小时候疯狂收集和交换神奇宝贝卡片的经历吗? 还记得和小伙伴拿着精灵球,一起召唤小精灵的中二模 ...

  9. 用python画皮卡丘代码-实现童年宝可梦,教你用Python画一只属于自己的皮卡丘

    大数据文摘出品 作者:李雷.蒋宝尚 还记得小时候疯狂收集和交换神奇宝贝卡片的经历吗? 还记得和小伙伴拿着精灵球,一起召唤小精灵的中二模样吗? 最近上映的<大侦探皮卡丘>,是否会让你秒回童年 ...

最新文章

  1. Python:爬虫框架Scrapy的安装与基本使用
  2. 简单而又常用的基本的交换路由的一些配置命令
  3. 人工智能、机器学习、数据挖掘著名会议
  4. 预测数值型数据:回归源码分析(1)
  5. linux的less命令如何退出,Linux命令详解之less命令
  6. python BeautifulSoup 爬虫运行出现 exited with code -1073741571
  7. Python int函数 - Python零基础入门教程
  8. phpcmsV9 的 PHPSSO 配置
  9. 【JVM 2,最经典的HashMap图文详解
  10. atomic原子类实现机制_JDK中Atomic开头的原子类实现原子性的原理是什么?
  11. virtualenv搭建虚拟环境
  12. kettle MySQL blob_KETTLE BLOB 问题
  13. h5 神策埋点_神策埋点
  14. mysql超卖问题处理_mysql 解决超卖问题的锁分析
  15. C语言 neutralize函数,因子中性化
  16. 关于(esd保护器)ESD静电二极管方向的不同特性总结
  17. 服装制造企业的云ERP管理
  18. ACwing每日一题3565暴力 绝对值不等式 中位数思维
  19. javascript 全栈_什么是JavaScript? 全栈编程语言
  20. ElasticSearch查询实战之电商商城商品搜索

热门文章

  1. python开发ps插件_3 行 Python 代码实现 5 秒抠图的 AI 神器,告别PS(附教程)
  2. js 里面的键盘码对应的值
  3. 你必须知道的ABI和CPU关系
  4. 看过和想看的电影、连续剧(不断更新)
  5. 摄影构图_摄影中的构图是什么?
  6. xshell登陆Win10 Linux子系统
  7. matlab函数库-optimset,OptimsetOptimget 函数用法
  8. Windows Update无法启动
  9. 【题解】AcWing 第71场周赛题解
  10. Pandas Panel的使用