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

2021-01-04 11:33:06 浏览数 (1)

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

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)。

代码语言:javascript复制
# 导入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]的直线。

代码语言:javascript复制
# 通过两个点([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_来获取直线的斜率和截距,代码如下。

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

输出

代码语言:javascript复制
y=1.000 x  1.000

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

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

代码语言:javascript复制
# 画出通过三个点([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_))

输出

代码语言:javascript复制
y=0.500 x  2.167

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

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

代码语言:javascript复制
#导入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_))

输出

代码语言:javascript复制
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类就是用最小二乘法来实现回归的。

代码语言:javascript复制
# 导入数据划分模块、分为训练集和测试集
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)))

输出

代码语言:javascript复制
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)就没有那么高了。

代码语言:javascript复制
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)))

输出

代码语言:javascript复制
斜率: [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对波士顿房价的回归。

代码语言:javascript复制
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)))

输出

代码语言:javascript复制
斜率: [-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)来实现。

代码语言:javascript复制
# 导入StatsModels的API库,C:Usersxiang>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分别对波士顿房价和糖尿病进行模拟。

代码语言:javascript复制
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())

获得参数概要

代码语言:javascript复制
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来对波士顿房价进行评估。

代码语言:javascript复制
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

0 人点赞