首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >机器学习测试笔记(11)——线性回归方法(上)

机器学习测试笔记(11)——线性回归方法(上)

作者头像
顾翔
发布2021-01-04 11:33:06
1.2K0
发布2021-01-04 11:33:06
举报

顾老师新书《全栈软件测试工程师宝典》

https://item.m.jd.com/product/10023427978355.html

以前两本书的网上购买地址:

《软件测试技术实战设计、工具及管理》:

https://item.jd.com/34295655089.html

《基于Django的电子商务网站》:

https://item.jd.com/12082665.html

1.基本概念

直线是最基本的几何图形,一般的直线可以表达为:y = kx+b,这里的k我们叫做斜率,b叫做截距(x=0的时候,y的值。即直线与y轴的交叉点)。线性回归方法即找出一条直线,使得各个点到这条直线上的误差最小

现在让我们通过Python语言来画一条直线:y = 0.5 * x + 3(这里斜率为0.5, 截距为3)。

# 导入NumPy库 
import numpy as np
# 导入画图工具
import matplotlib.pyplot as plt

def Line_base():
    x = np.linspace(-5,5,100)
    y = 0.5 * x + 3
    plt.plot(x,y,c='green')
    plt.title('Straight Line')
    plt.show()

初中几何课我们就知道:两个点确定唯一的一条直线。现在我们通过sklearn的线性模型中的线性回归(LinearRegression)类来画出一条经过[2,3]和[3,4]的直线。

# 通过两个点([2,3]和[3,4])画出直线
from sklearn.linear_model import LinearRegression
def Line_base_by_two_point():
    X = [[2],[3]]
    y = [3,4]
# 用线性模型拟合这;两个点
    lr =LinearRegression().fit(X,y)
# 画出通过两个点([2,3]和[3,4])直线
    z = np.linspace(-5,5,20)
    plt.scatter(X,y,s=80)
   plt.plot(z,lr.predict(z.reshape(-1,1)),c='k')
    plt.title('Straight Line')
    plt.show()

我们可以通过LinearRegression().coef_[0]和LinearRegression().lr.intercept_来获取直线的斜率和截距,代码如下。

# 显示这条线的斜率和截距
print('y={:.3f}'.format(lr.coef_[0]),'x','+{:.3f}'.format(lr.intercept_))

输出

y=1.000 x +1.000

在这里斜率与截距都为1。

现在我们在[2,3]、[3,4]两个点基础上再加一个点[4,4],来看看画出来的图是什么情形。

# 画出通过三个点([2,3]、[3,4]和[4,4])直线
def Line_base_by_three_point():
    X = [[2],[3],[4]]
    y = [3,4,4]
# 用线性模型拟合这;两个点
    lr =LinearRegression().fit(X,y)
# 画出通过三个点([2,3]、[3,4]和[4,4])直线
    z = np.linspace(-5,5,20)
    plt.scatter(X,y,s=80)
   plt.plot(z,lr.predict(z.reshape(-1,1)),c='k')
    plt.title('Straight Line')
    plt.show()
# 显示这条线的斜率和截距 
   print('y={:.3f}'.format(lr.coef_[0]),'x','+{:.3f}'.format(lr.intercept_))

输出

y=0.500 x +2.167

这条折线不经过[2,3]、[3,4]和[4,4]三个点中任意一个点,但是使得这三个点到这条直线的距离保持最小,这就体现出了线性回归的意义。

到目前为止,点的个数仅仅为三个,数量是非常有限的,我们通过make_regression(n_samples=50…)来制造出50个样本数据,然后用LinearRegression来拟合一条我们需要的直线。

#导入make_regression数据集成生成器
from sklearn.datasets import make_regression
# 画出多个点的直线
def Line_base_by_multiple_point():
    X,y =make_regression(n_samples=50,n_features=1,n_informative=1,noise=50,random_state=1)
# 使用线性模型进行拟合
    reg = LinearRegression()
    reg.fit(X,y)
# z 是我们生成的等差数列,用来画出线性模型
    z =np.linspace(-3,3,200).reshape(-1,1)
   plt.scatter(X,y,c='b',s=60)
   plt.plot(z,reg.predict(z),c='k')
    plt.title('LinearRegression')
    plt.show()
# 显示这条线的斜率和截距
    print('y={:.3f}'.format(reg.coef_[0]),'x','+{:.3f}'.format(reg.intercept_))

输出

y=79.525 x +10.922

这条直线的斜率为79.525,截距为10.922。到50个样本点的平均误差最小。

线性回归方法包括:最小二乘法、逻辑回归、支持向量机、岭回归和套索回归。下面我们进行一一介绍。

2.最小二乘法

2.1原理

我们判断一个西瓜的好坏,可以通过它的色泽、根蒂和敲声参数乘以它们的系数加上一个误差系数(b)来获得。

F好瓜(x) = w1 x色泽+ w2x根蒂+ w3 x敲声+b (1)

假设有m个西瓜,第一个西瓜的参数为:[x1色泽 ,x1根蒂 ,x1敲声],第二个西瓜的参数为:[x2色泽 ,x2根蒂 ,x2敲声],…,第m个西瓜的参数为:[xm色泽 ,xm根蒂 ,xm敲声],我们可以用一个矩阵来表示这m个西瓜。

X =[[x1色泽 ,x1根蒂 ,x1敲声]

[x2色泽 ,x2根蒂 ,x2敲声]

[xm色泽 ,xm根蒂 ,xm敲声]]

我们把色泽、根蒂和敲声系数表示为一个竖向量:

w=[[w色泽系数],

[w根蒂系数],

[w敲声系数]]

w=[[w1] ,

[w2] ,

[w3]]

这样上面式(1)可以表示为:F好瓜(x) = Xw+b。

其中:

Xw= [[x1色泽w1+x1根蒂w2+x1敲声w3]

[x2色泽w1+x2根蒂w2+x2敲声w3]

[xm色泽w1+xm根蒂w2+xm敲声w3]]

假设每个瓜的实际值为Y,

y = w=[[y1] ,

[y2] ,

[ym]]

实际值与计算值差的平方(即方差)为:(Xw-y)2,我们现在知道要求这个方差最小的系数w是多少?我们可以采用(Xw-y)2对w取导数=0的方法来获得这个w。对w求导为:-2XT (y-Xw),使-2XT (y-Xw)=0,得到w的最优解:w = (XTX)-1XTy。

2.2 sklearn.linear_model

sklearn.linear_model的LinearRegression类就是用最小二乘法来实现回归的。

# 导入数据划分模块、分为训练集和测试集
from sklearn.model_selection import train_test_split
def Line_for_sklearn_data():
        X,y =make_regression(n_samples=100,n_features=2,n_informative=2,random_state=8)
       X_train,X_test,y_train,y_test = train_test_split(X, y,random_state=8,test_size=0.3)#测试集占30%
        lr =LinearRegression().fit(X,y)
        print('lr.coef_: {} '.format(lr.coef_[:]))
        print('reg.intercept_:{}'.format(lr.intercept_))
        print('训练集得分:{}'.format(lr.score(X_train,y_train)))
        print('测试集得分: {}'.format(lr.score(X_test,y_test)))

输出

lr.coef_: [82.06262736 7.73658023]
reg.intercept_: -8.881784197001252e-16
训练集得分: 1.0
测试集得分: 1.0

由于有两个参数,线性回归方程:y = 82.06262736x1+7.73658023x2-8.8e-16。另外由于使用make_regression产生的数据没有噪音,所以评分(score)是1.00,非常好。但是不雅开心得太早,我们使用sklearn datasets中的diabetes来进行线性回归,评分(score)就没有那么高了。

from sklearn import datasets
#用线性回归对sklearn数据进行分析
def useing_sklearn_datasets_for_LinearRegression():
        X,y =datasets.load_diabetes().data,datasets.load_diabetes().target
       X_train,X_test,y_train,y_test = train_test_split(X, y,random_state=8,test_size=0.3)
        lr = LinearRegression().fit(X_train,y_train)
        print('斜率: {} '.format(lr.coef_[0))
        print('截距: {:.3f}'.format(lr.intercept_))
        print('糖尿病训练集得分:{:.3f}'.format(lr.score(X_train,y_train)))
        print('糖尿病测试集得分: {:.3f}'.format(lr.score(X_test,y_test)))

输出

斜率: [12.8821982   -280.25543507   525.99221876   407.85755317 -1120.30092255   698.91189157 234.67105524   208.41900324   816.01470258   114.97615609]
截距: 152.535
糖尿病训练集得分: 0.535
糖尿病测试集得分: 0.454

由于有10个斜率,与糖尿病数据有10个特征一致,训练集得分: 0.535,测试集得分: 0.454,显然这个数据是非常低的。我们再来看sklearn datasets对波士顿房价的回归。

Boston =datasets.load_boston()
X,y =Boston.data,Boston.target
X_train,X_test,y_train,y_test= train_test_split(X, y)
lr =LinearRegression().fit(X_train,y_train)
print('斜率: {} '.format(lr.coef_[:]))
print('截距: {}'.format(lr.intercept_))
print('波士顿房价训练集得分:{:.3f}'.format(lr.score(X_train,y_train)))
print('波士顿房价测试集得分:{:.3f}'.format(lr.score(X_test,y_test)))

输出

斜率: [-9.68961053e-02 4.87033096e-02-2.55499190e-02 3.92145072e+00 -1.52816098e+01 4.23762130e+00 -1.84848509e-02-1.56942479e+00 2.79115671e-01 -1.13985910e-02 -9.27575541e-01 1.05878888e-02-4.14823758e-01]
截距: 32.06878785459298
波士顿房价训练集得分: 0.743
波士顿房价测试集得分: 0.716

可见使用最小线性回归的性能还是比较小的。

2.3 StatsModels

Sklearn提供了最小二乘法的数据和算法,StatsModels也提供了最小二乘法的数据和算法。在StatsModels中最小二乘法又可以分为普通最小二乘法(OLS)、加权最小二乘法(WLS)、广义最小二乘法(GLS)和具有相关误差的可行最小二乘法。下面代码使用普通最小二乘法(OLS)来实现。

# 导入StatsModels的API库,C:\Users\xiang>pip3 install statsmodels
import statsmodels.api as sm
#StatsModels 库
# y = w^x+e(e 误差,符合均值为0的正态分布)
def StatsModels_linear_regression():
# 前四行训练构造函数,自变量x 因变量y
# 通过自变量x准备数据,将1~10 数据分割成20份
    x = np.linspace(0,10,20)
# 向数组中添加一列,构成20组x
    X = sm.add_constant(x)
    ratio = np.array([1,10]) #ratio:比例
# 使回归方程的系数点乘x数据集,构成因变量y
#numpy.random.normal(loc=0.0, scale=1.0, size=None)
# loc:float,概率分布的均值,对应着整个分布的中心center
# scale: 概率分布的标准差,对应于分布的宽度,scale越大越矮胖,scale越小,越瘦高
# size: 输出的shape,默认为None,只输出一个值
# np.random.randn(size)所谓标准正太分布(μ=0, σ=1),对应于np.random.normal(loc=0, scale=1, size)
    y = np.dot(X,ratio) +np.random.normal(size=20)
# 执行OLS模型
    testmodel = sm.OLS(y,X)
# 使用fit方法启动模型训练
    results = testmodel.fit()
   print("results.params:\n",results.params,"\nresults.summary():\n",results.summary())

输出

results.params:

[ 0.99796725 10.01634513]

results.summary():

OLS Regression Results

Dep. Variable:

y

R-squared:

0.999

Model:

OLS

Adj. R-squared:

0.999

Method:

Least Squares

F-statistic:

1.734e+04

Date:

Wed, 23 Dec 2020

Prob (F-statistic):

2.58e-28

Time:

17:31:25

Log-Likelihood:

-27.965

No. Observations:

20

AIC:

59.93

Df Residuals:

18

BIC:

61.92

Df Model:

1

Covariance Type:

nonrobust

coef

std err

t

P>|t|

[0.025

0.975]

const

0.9980

0.445

2.243

0.038

0.063

1.933

x1

10.0163

0.076

131.668

0.000

9.857

10.176

Omnibus:

1.628

Durbin-Watson:

1.619

Prob(Omnibus):

0.443

Jarque-Bera (JB):

0.363

Skew:

-0.004

Prob(JB):

0.834

Kurtosis:

3.660

Cond. No.

11.5

Notes:[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

中文译文:

结果参数:

[ 0.99796725 10.01634513]

结果描述:

OLS Regression Results

深度变量:

y

判定系数:

0.999

模型:

OLS

平均判定系数:

0.999

方法:

Least Squares

F统计量:

1.734e+04

日期:

Wed, 23 Dec 2020

试验(F统计量):

2.58e-28

时间:

17:31:25

对数似然:

-27.965

观察号:

20

AIC:

59.93

Df剩余

18

BIC:

61.92

Df模型:

1

协方差类型:

nonrobust

系数

标准误差

t

P>|t|

[0.025

0.975]

const

0.9980

0.445

2.243

0.038

0.063

1.933

x1

10.0163

0.076

131.668

0.000

9.857

10.176

综合:

1.628

Durbin-Watson:

1.619

问题(综合):

0.443

Jarque-Bera (JB):

0.363

偏斜:

-0.004

试验(JB):

0.834

峰度系数:

3.660

条件编号

11.5

注:[1] 标准误差假设误差的协方差矩阵被正确指定。

从中可以看出斜率为9.9462,截距为0.8117。我们用OLS分别对波士顿房价和糖尿病进行模拟。

from sklearn import datasets
def StatsModels_linear_regression_for_sklearn_dataset():
#Load Boston
        Boston =datasets.load_boston()
        X,y =Boston.data[:,5].reshape(-1,1),Boston.target.reshape(-1,1)
        testmodel =sm.OLS(y,X)
        results =testmodel.fit()
       print("results.params(Boston):\n",results.params,"\nresults.summary(Boston):\n",results.summary())
#Load diabetes
        X,y = datasets.load_diabetes().data,datasets.load_diabetes().target
        testmodel =sm.OLS(y,X)
        results =testmodel.fit()
       print("results.params(diabetes):\n",results.params,"\nresults.summary(diabetes):\n",results.summary())

获得参数概要

results.params(Boston):
[3.6533504]
R-squared (uncentered): 0.901
results.params(diabetes):
[ -10.01219782 -239.81908937 519.83978679  324.39042769-792.18416163 476.74583782 101.04457032  177.06417623  751.27932109  67.62538639]
R-squared(uncentered):   0.106

由此可见对波士顿房价还是比较好的(0.901),而对于糖尿病就太不好了(0.106)。

现在我们用OLS、WLS、GLS来对波士顿房价进行评估。

def StatsModels_linear_regression_for_all_model():
#Load Boston
        Boston =datasets.load_boston()
        X,y =Boston.data[:,5].reshape(-1,1),Boston.target.reshape(-1,1)
        testmodel =sm.OLS(y,X)
        results =testmodel.fit()
       print("OLS:\n",results.params,"\nOLS:\n",results.summary())
        Boston =datasets.load_boston()
        X,y =Boston.data[:,5].reshape(-1,1),Boston.target.reshape(-1,1)
        testmodel =sm.WLS(y,X)
        results =testmodel.fit()
       print("WLS:\n",results.params,"\nWLS:\n",results.summary())
        Boston =datasets.load_boston()
        X,y =Boston.data[:,5].reshape(-1,1),Boston.target.reshape(-1,1)
        testmodel =sm.GLS(y,X)
        results =testmodel.fit()
       print("GLS:\n",results.params,"\nGLS:\n",results.summary())

使用这三种方法x均为3.6533504,精度均为0.901。

—————————————————————————————————

顾老师课程欢迎报名

软件安全测试

https://study.163.com/course/courseMain.htm?courseId=1209779852&share=2&shareId=480000002205486

接口自动化测试

https://study.163.com/course/courseMain.htm?courseId=1209794815&share=2&shareId=480000002205486

DevOps 和Jenkins之DevOps

https://study.163.com/course/courseMain.htm?courseId=1209817844&share=2&shareId=480000002205486

DevOps与Jenkins 2.0之Jenkins

https://study.163.com/course/courseMain.htm?courseId=1209819843&share=2&shareId=480000002205486

Selenium自动化测试

https://study.163.com/course/courseMain.htm?courseId=1209835807&share=2&shareId=480000002205486

性能测试第1季:性能测试基础知识

https://study.163.com/course/courseMain.htm?courseId=1209852815&share=2&shareId=480000002205486

性能测试第2季:LoadRunner12使用

https://study.163.com/course/courseMain.htm?courseId=1209980013&share=2&shareId=480000002205486

性能测试第3季:JMeter工具使用

https://study.163.com/course/courseMain.htm?courseId=1209903814&share=2&shareId=480000002205486

性能测试第4季:监控与调优

https://study.163.com/course/courseMain.htm?courseId=1209959801&share=2&shareId=480000002205486

Django入门

https://study.163.com/course/courseMain.htm?courseId=1210020806&share=2&shareId=480000002205486

啄木鸟顾老师漫谈软件测试

https://study.163.com/course/courseMain.htm?courseId=1209958326&share=2&shareId=480000002205486

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件测试培训 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2.最小二乘法
    • 2.1原理
      • 2.2 sklearn.linear_model
        • 2.3 StatsModels
        相关产品与服务
        CODING DevOps
        CODING DevOps 一站式研发管理平台,包括代码托管、项目管理、测试管理、持续集成、制品库等多款产品和服务,涵盖软件开发从构想到交付的一切所需,使研发团队在云端高效协同,实践敏捷开发与 DevOps,提升软件交付质量与速度。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档