线性回归原理以及Python实现

2018.12.9 星期天 阴 biolearn
在统计学中,线性回归是利用线性回归方程对一个或多个自变量和因变量之间的关系进行建模的一种回归分析方法,只有一个自变量的情况称为一元线性回归,大于一个自变量情况的叫做多元线性回归。

线性回归的模型

  • 一元线性回归
    h_\theta(x)=\theta_0+\theta_1x_1
  • 考虑两个自变量

h_\theta(x)=\theta_0+\theta_1x_1+\theta_2x_2

  • 最终公式可以表达为

h_\theta(x)=\sum_{i=0}^n\theta_ix_i=\theta^Tx

  • θ 的求解过程

那么如何计算得到参数 θ ?通过线性回归预测得到的预测值和真实值之间都存在一个误差 ε,所以模型可以表示为
y^{(i)}=\theta^Tx^{(i)}+\epsilon^{(i)}
由于误差 ε 是独立同分布的,由中心极限定理可得,误差 ε 服从均值为0,方差为某定值 σ2 的高斯分布,可以得到误差 ε 的概率密度函数为

将误差 ε 用真实值减预测值替换可以得到,在给定 x 和 θ 时的关于 y 的概率密度函数


y(i) 的值彼此之间是独立的,所以将所有的 y 相乘可以得到它的似然函数,因为 x 和 y 是已知的,所以是关于参数 θ 的似然函数为

两边取对数得到


在给定 x 和 θ时,希望预测的 y 值和真实值越接近越好,所以需要求似然函数的最大值,将上述式子的常数项消除,所以变为对下面的式子求取最小值,也就是线性回归中的损失函数
J(\theta)=\frac{1}{2}\sum^m_{i=1}(h_\theta(x^{(i)})-y^{(i)})^2

对于由 M 个样本 N 维特征组成的矩阵 X,求解其进行线性回归的参数 θ,上述损失函数可以变成
J(\theta)=\frac{1}{2}\sum^m_{i=1}(h_\theta(x^{(i)})-y^{(i)})^2=\frac{1}{2}(X\theta-y)^T(X\theta-y)
其中 Xθ 理解为预测值,y 表示真实值,为了求解上述式子的最小值,根据最小值必定为函数的驻点,可以对上述式子进行求导

驻点的导数为0,于是得到了参数 θ 的解析式为
\theta=(X^TX)^{-1}X^Ty
以上是参数 θ 的解析式的推导和求解过程,是利用最小二乘法的原理完成的,但是由于求解矩阵的逆很耗费时间,一般是通过梯度下降算法进行计算的。

Python实现线性回归

根据上述推到的求解参数的公式计算参数,构建模型并进行预测,将结果和利用Scikit-Learn中线性回归得到的结果进行比较,查看参数和预测结果是否一致

  • 数据描述

数据来自出版书籍《An Introduction to Statistical Learning with Applications in R》 (Springer, 2013),作者Gareth James, Daniela Witten, Trevor Hastie and Robert Tibshirani。共200 条数据, 每条数据4 个属性。该数据可以从这个链接直接下载得到 http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv

  • 数据集信息,数据共4列200行,每一行为一个特定的商品,前三列为输入特征也就是x,最后一列为输出特征也就是y
  • python
#!/usr/bin/python
# -*- coding:utf-8 -*-
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
from scipy import stats
from sklearn import linear_model

if __name__ == "__main__":
    data = pd.read_csv('./Advertising.csv')    # TV,Radio,Newspaper,Sales
    data['intercept'] = 1
    x = data[['intercept','TV', 'Radio', 'Newspaper']]
    y = data['Sales']
    # 前150行的数据作为train,后50行作为test
    train_x = np.array(x.loc[1:150,])
    test_x = np.array(x.loc[151:,])
    train_y = np.array(y.loc[1:150,])
    test_y = np.array(y.loc[151:,])
    # beta = (X^TX)^(-1)X^Ty,计算参数
    Xt = np.transpose(train_x)
    XtX = np.dot(Xt,train_x)
    Xty = np.dot(Xt,train_y)
    beta = np.linalg.solve(XtX,Xty)
    print(beta)
    # 对后50行的数据进行预测
    pred=[]
    for data, actual in zip(test_x, test_y):
        test = np.transpose(data)
        prediction = np.dot(test, beta)
        pred.append(prediction)
        print('prediction = ' + str(prediction) + ' actual = ' + str(actual))
    #plot
    pcc = stats.pearsonr(test_y, pred)[0]
    print('Pearson Correlation Coefficient = ' + str(pcc))

    mpl.rcParams['font.sans-serif'] = ['simHei']
    mpl.rcParams['axes.unicode_minus'] = False
    plt.figure(figsize=(14, 6),facecolor='w')
    plt.subplot(121)
    t = np.arange(len(test_x))
    plt.plot(t, test_y, 'r-', linewidth=2, label='真实数据')
    plt.plot(t, pred, 'g-', linewidth=2, label='预测数据')
    plt.title('线性回归预测销量', fontsize=18)
    plt.text(10, 20, 'PCC=%0.2f' % pcc, fontsize=15)
    plt.legend(loc='upper left')
    plt.grid(b=True, ls=':')

    ## 利用sklearn中的linear_model
    model = linear_model.LinearRegression()
    model.fit(train_x[:,1:],train_y)
    print('利用sklearn中的linear_model计算的参数:%s\t%s' % (model.coef_, model.intercept_))
    test_y_pred = model.predict(test_x[:,1:])
    pcc_sk = stats.pearsonr(test_y,test_y_pred)[0]
    print('Pearson Correlation Coefficient(sklearn) = ' + str(pcc_sk))
    plt.subplot(122)
    plt.plot(t, test_y, 'r-', linewidth=2, label='真实数据')
    plt.plot(t, pred, 'go-', linewidth=2, label='预测数据')
    plt.title('线性回归预测销量(sklearn)', fontsize=18)
    plt.text(10, 20, 'PCC=%0.2f' % pcc_sk, fontsize=15)
    plt.legend(loc='upper left')
    plt.grid(b=True, ls=':')
    plt.show()
  • 结果输出,可以看到通过自行编写得到的参数以及预测结果和通过使用sklearn得到的结果一模一样
[ 3.07875053e+00  4.65616125e-02  1.80900459e-01 -2.55988893e-03]   #截距以及三个特征的权重
Pearson Correlation Coefficient = 0.9505078535320115
利用sklearn中的linear_model计算的参数:[ 0.04656161  0.18090046 -0.00255989]  3.0787505315686783  # 三个特征的权重以及截距
Pearson Correlation Coefficient(sklearn) = 0.9505078535320114
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容