线性回归实践

理论部分

对于最基本的线性回归问题,公式如下:

X是自变量,也就是我们实际场景中的特征变量,比如我项目中每个时刻芯片的电压,温度,串口状态、串口数据、电流值、功耗、电流波形等等参数;
θ是权重参数,也就是我们需要去梯度下降求解的具体值,(我们拿一堆的数据来拟合出最佳的θ[误])用数据拟合h(x),通过最佳的θ,得到最佳拟合曲线hθ(x),然后在预测的时候就只要直接用这个公式就好了。
梯度下降时,你如何评估你最新的参数是向着正确的方向进行修正的呢?我们引入损失函数,直观上理解就是我更新一组参数后,你效果必须是越来越好的,误差也是越来越少的。

注意:是最小二乘误差的哟,也就是m个样本每个都要计算一次样本(在当前的θ参数下);前面的1/2是为了求偏导时消除系数的。

ps. 为什么用最小二乘作为误差函数呢? 答案在这!知乎上解释的很透彻了。
简单来说就是前提假设是高斯分布,因此化简(见上述链接)后就是最小二乘,而高斯分布是大自然里很自然的一个属性,遵天道。

这是直观化的梯度下降图示:

图片来源百度

梯度下降更新权重参数的过程中我们需要对损失函数求偏导数:


梯度下降标准数学推导

求完偏导数以后就可以进行参数更新了:



上面公式中的alpha就是下面图中的步长lamda:
学习率参数

总结:理论上是先求得误差函数,然后误差函数对参数θ求偏导,求得后再更新参数就好了


实践部分

深度学习的核心理念:输入,然后设定期望的输出,找到二者的相关性。


最小二乘:

我们先猜测函数的位置,然后平方其误差,重新做出猜测,以减少平方误差的和。这是线性回归的种子。


#最小二乘法least squares
################################################################################
#在当前给定的参数a,b下计算所有误差值的平方和并取均值
# ################################################################################
def compute_error_for_line_given_points(b,a,datas):
    totalError = 0
    for i in range(0,len(datas)):
        x = datas[i][0]
        y = datas[i][1]
        totalError += (y-(a*x+b))**2
    return totalError/float(len(datas))

print compute_error_for_line_given_points(1,2,[[3,6],[6,9],[12,18]])

总结:这里讲了如何求误差函数,当然这里求的是最简单的一元变量。在一个给定参数情况下计算整体的平均误差值。


梯度下降:

比如下面这个函数,我们知道在极小值左边导数是小于0的,右边是大于0 的,同时越靠近极值点导数绝对值越小(可理解为梯度很小)。

  • 那么我们可以这样思考:首先我随机选择一个x点,然后计算其导致,假如小于0我就往右挪动一点,大于0我就往左移动一点,最终总会挪动到极值点处的;
  • 这其中需要思考的是:移动步长多少为好呢?太大了不收敛,太小了时间花销大;既然无法确定,那么我们就定一个超参数嘛,让这个值(就是上面参数更新公式中的alpha,也就是下面代码中的学习率)手动来调,多调几次就知道了嘛(目前阶段这样做无可厚非嘛)~
current_x += -learning_rate*slope_at_given_x_value(previous_x)
################################################################################
#http://mp.weixin.qq.com/s/8as8ai5W0RlLOhHT6sswjA
#梯度下降
################################################################################
current_x = 0.5 #启动点
learning_rate = 0.01#学习率
num_iterations = 10 #迭代次数
#这个是斜率
def slope_at_given_x_value(x):
    return 5*x**4 - 6*x**2
#整体表达的是一个移动的概念,往“城市”中心移动(基于斜率)。
#也就是我选定一个初始点,然后看这一点的斜率值,在极小值点左边是斜率小于零,右边是斜率大于零,
#因此我们随机选择一个点后,把当前点加上一个趋势,在极值点左边就加,右边就减去,这样不断迭代就好了。
for i in range(num_iterations):
    previous_x = current_x
    current_x += -learning_rate*slope_at_given_x_value(previous_x)
    print(previous_x)
print "the local minimum occurs at %f" % current_x

这里可以把x看作是梯度下降里面的参数,假设只有一个参数时的情况,属一元变量。

总结:可以将上述的slope_at_given_x_value(x)函数看作误差函数,然后这里讲了如何求导误差函数的极小值,当然也是在一元变量的情况下做的。


线性回归:

通过组合最小二乘法和梯度下降法,就可以得到线性回归。

################################################################################
#最小二乘法 + 梯度下降 == 线性回归
################################################################################
#price of wheat/Kg and the average price of bread
wheat_and_bread = [[0.5,5],[0.6,5.5],[0.8,6],[1.1,6.8],[1.4,7]]

def step_gradient(b_current,a_current,datas,learningRate):
    b_gradient = 0
    a_gradient = 0
    N = float(len(datas))
    #这里是把所有的数据集的误差值求出来,然后
    for i in range(0,len(datas)):
        x = datas[i][0]
        y = datas[i][1]
        b_gradient += -(2/N) * (y - ((a_current*x + b_current)))
        a_gradient += -(2/N) * x * (y - ((a_current*x + b_current)))
    
    new_b = b_current - (learningRate * b_gradient)
    new_a = a_current - (learningRate * a_gradient)
    return [new_b,new_a]

def gradient_descent_runner(datas,starting_b,starting_a,learning_rate,num_iterations):
    b = starting_b
    a = starting_a
    for i in range(num_iterations):
        b,a = step_gradient(b,a,datas,learning_rate)
    return [b,a]
print gradient_descent_runner(wheat_and_bread,1,1,0.01,100)

因为是一元变量的线性拟合,所以拟合函数是y=ax+b,需要求的参数是a,b;

自变量(特征)={x};只有x一个。
参数θ={a,b};两个参数需求解。

因此我的梯度下降是这样做的:首先把a,b参数初始化为0,然后由于已知拟合函数形式了,因此直接代入偏导函数求参数:

梯度下降标准数学推导

对应代码为:
b_gradient += -(2/N) * (y - ((a_current*x + b_current)))
上面的2是因为我们定义误差函数的时候是没有加1/2的,因此这里求偏导后有个2(2次方),同时求得是整体的平均误差,因此每个误差前面乘以个1/N。
a_gradient += -(2/N) * x * (y - ((a_current*x + b_current)))
分析同上,但是这里多乘了个x,为啥?因为梯度公式本来就是这样的啊!那个b_gradient因为是常数项,即x的0次方(特征1)所以直接是1了,省略;而这个是x的1次方(特征2),因此直接按公式将这个特征乘以就好了。

总结:对比之前的那个一元变量的导数(斜率)可知,这里的偏导思路跟那是一样的啊,目标就是更新参数,而参数的更新就是偏导嘛(导数咯),偏导就是上面一元函数里面的斜率嘛,这么对照着直接理解的话就可以知道过程是一样的,都是围绕某一个参数变量求导数(当然数据量多的时候求导数的平均值),然后不断修改之就好啦~


三种梯度下降方法

【资料引用来源】
一般线性回归函数的假设函数为(x是一些特诊变量):

对应的损失函数为(这里的1/2是为了后面求梯度计算方便):


批量梯度下降法(BGD)

我们的目的是要误差函数尽可能的小,即求解weights使误差函数尽可能小。
首先,我们随机初始化weigths,然后不断反复的更新weights使得误差函数减小,直到满足要求时停止。
这里更新算法我们选择梯度下降算法,利用初始化的weights并且反复更新weights:

这里代表学习率,表示每次向着J最陡峭的方向迈步的大小。为了更新weights,我们需要求出函数J的偏导数。首先当我们只有一个数据点(x,y)的时候,J的偏导数是:


则对所有数据点,上述损失函数的偏导(累和)为:

再最小化损失函数的过程中,需要不断反复的更新weights使得误差函数减小,更新过程如下:

那么好了,每次参数更新的伪代码如下:

由上图更新公式我们就可以看到,我们每一次的参数更新都用到了所有的训练数据(比如有m个,就用到了m个),如果训练数据非常多的话,是非常耗时的。
下面给出批梯度下降的收敛图:


随机梯度下降法(SGD)

由于批梯度下降每跟新一个参数的时候,要用到所有的样本数,所以训练速度会随着样本数量的增加而变得非常缓慢。随机梯度下降正是为了解决这个办法而提出的。它是利用每个样本的损失函数对θ求偏导得到对应的梯度,来更新θ:


更新过程如下:

随机梯度下降是通过每个样本来迭代更新一次,对比上面的批量梯度下降,迭代一次需要用到所有训练样本(往往如今真实问题训练数据都是非常巨大),一次迭代不可能最优,如果迭代10次的话就需要遍历训练样本10次。
但是,SGD伴随的一个问题是噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。
随机梯度下降收敛图如下:

我们可以从图中看出SGD迭代的次数较多,在解空间的搜索过程看起来很盲目。但是大体上是往着最优值方向移动。


小批量梯度下降法(MBGD)

我们从上面两种梯度下降法可以看出,其各自均有优缺点,那么能不能在两种方法的性能之间取得一个折衷呢?既算法的训练过程比较快,而且也要保证最终参数训练的准确率,而这正是小批量梯度下降法(Mini-batch Gradient Descent,简称MBGD)的初衷。
我们假设每次更新参数的时候用到的样本数为10个(不同的任务完全不同,这里举一个例子而已
更新伪代码如下:


三种梯度下降方法的总结

  1. 批梯度下降每次更新使用了所有的训练数据,最小化损失函数,如果只有一个极小值,那么批梯度下降是考虑了训练集所有数据,是朝着最小值迭代运动的,但是缺点是如果样本值很大的话,更新速度会很慢。

  2. 随机梯度下降在每次更新的时候,只考虑了一个样本点,这样会大大加快训练数据,也恰好是批梯度下降的缺点,但是有可能由于训练数据的噪声点较多,那么每一次利用噪声点进行更新的过程中,就不一定是朝着极小值方向更新,但是由于更新多轮,整体方向还是大致朝着极小值方向更新,又提高了速度。

  3. 小批量梯度下降法是为了解决批梯度下降法的训练速度慢,以及随机梯度下降法的准确性综合而来,但是这里注意,不同问题的batch是不一样的,根据实验结果来迭代调整。

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

推荐阅读更多精彩内容