回归分析是一种应用极为广泛的数量分析方法。它用于分析事物之间的统计关系,侧重考察变量之间的数量变化规律,并通过回归方程的形式描述和反映这种关系,以帮助人们准确把握变量受其他一个或多个变量影响的程度,进而预测提供科学依据。在大数据分析中,回归分析是一种预测性的建模技术,它研究的是因变量(目标)和自变量(预测器)之间的关系。这种技术通常用于预测分析、时间序列模型,以及发现变量之间的因果关系。
回归分析概述基本概念
回归分析是处理多变量间相关关系的一种数学方法。相关关系不同于函数关系,后者反映变量之间的严格依存性,而前者则表现出一定程度的波动性或随机性,对自变量的每一个取值,因变量可以有多个数值与之相对应。在统计上,研究相关关系可以运用回归分析和相关分析(correlation analysis)。
当自变量为非随机变量而因变量为随机变量时,它们的关系分析成为回归分析;当两者都是随机变量时,它们的关系分析成为相关分析。回归分析和相关分析往往不加区分。广义上说,相关分析包括回归分析,但严格地说两者是有区别的。具有相关关系的两个变量
ξ
xi
ξ和
η
eta
η,他们之间虽存在着密切的关系,但不能由一个变量的数值精准地求出另一个变量地值。通常选定
ξ
=
η
xi = eta
ξ=η时
η
eta
η的数学期望作为对应
ξ
=
η
xi = eta
ξ=η时
η
eta
η的代表值,因为它反映
ξ
=
x
xi = x
ξ=x条件下
η
eta
η取值的平均水平。这样的对应关系称为回归关系。根据回归分析可以建立变量间的数学表达式,称为回归方程。回归方程反映自变量在固定条件下因变量的平均状态变化情况。相关分析是以某一指标来度量回归方程所描述的各个变量间关系的密切程度。相关分析常用回归分析来补充,二者相辅相成。若通过相关分析显示出变量间关系十分密切,则通过所建立的回归方程可以获取相当准确的取值。
可解决的问题
- 建立变量间的数学表达式,通常称为经验公式。
- 利用概率统计基础知识进行分析,从而判断所建立的经验公式的有效性。
- 进行因素分析,确定影响某一变量的若干变量中,何者为主要,何者为次要,以及它们之间的关系。
具体相关关系的变量之间虽然具有某种不确定性,但是通过对现象的不断观察可以探索出它们之间的统计规律,这类统计规律称为回归关系。有关回归关系的理论、计算和分析称为回归分析。
回归分析的步骤
首先确定要进行预测的因变量,然后集中于说明变量,进行多元回归分析的多元回归分析将给出因变量于说明变量之间的关系。这一关系最后以公式形式,通过它预测因变量的未来值。
回归分析可以分为线性回归分析和逻辑回归分析。
简单而言,线性回归就是将输入项分别乘以一些常数,再将结果加起来得到输出。线性回归包括一元线性回归和多元线性回归。
简单线性回归分析线性回归分析中,如果仅有一个自变量于一个因变量,且关系大致上可用一条直线表示,则称之为简单线性回归分析。
如果发现因变量Y和自变量X之间存在高度的正相关,则可以确定一条直线方程,使得所有的数据点尽可能接近这条拟合的直线。简单线性回归分析的模型可以用以下方程表示:
Y
=
a
+
b
x
Y = a + bx
Y=a+bx
其中,Y为因变量,a为截距,b为相关系数,x为自变量。
多元线性回归分析是简单线性回归分析的推广,指的是多个因变量对多个自变量的回归分析。其中最常用的是只限于一个因变量但有多个自变量的情况,也叫多重回归分析。多重回归分析的一般形式如下
Y
=
a
+
b
1
X
1
+
b
2
X
2
+
b
3
X
3
+
⋯
+
b
k
X
k
Y = a + b_{1}X_{1} + b_{2}X_{2} + b_{3}X_{3} +cdots+ b_{k}X_{k}
Y=a+b1X1+b2X2+b3X3+⋯+bkXk
其中,a代表截距,
b
1
,
b
2
,
b
3
⋯
b
k
b_{1},b_{2},b_{3}cdots b_{k}
b1,b2,b3⋯bk为回归系数。
对于线性回归问题,样本点落在空间中的一条直线上或该直线的附近,因此可以使用一个线性函数表示自变量和因变量间的对应关系。然而在一些应用中,变量间的关系呈现曲线形式,因此无法用线性函数表示自变量和因变量间的对应关系,而需要使用非线性函数表示。
数据挖掘中常用的一些非线性回归模型
- 渐进回归模型: Y = a + b e − r X Y = a + be^{-rX} Y=a+be−rX
- 二次曲线模型: Y = a + b 1 X + b 2 X 2 Y = a + b_{1}X + b_{2}X^{2} Y=a+b1X+b2X2
- 双曲线模型: Y = a + b X Y = a + frac{b}{X} Y=a+Xb
由于许多非线性模型是等价的,所以模型的 参数化不是唯一的,这使得非线性模型的拟合和解释相比线性模型复杂得多。在非线性回归分析中估算回归参数的最通用的方法依然是最小二乘法。
最小二乘法推导已知有
n
n
n个数据点:
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
⋯
(
x
n
,
y
n
)
(x_{1},y_{1}),(x_{2},y_{2})cdots(x_{n},y_{n})
(x1,y1),(x2,y2)⋯(xn,yn)
需要对这
n
n
n个数据点进行曲线拟合,通过观察发现,它近似于抛物线假定曲线方程的形式为
y
=
a
2
x
2
+
a
1
x
+
a
0
y=a_{2}x^{2}+a_{1}x+a_{0}
y=a2x2+a1x+a0其中
a
0
,
a
1
,
a
2
a_{0},a_{1},a_{2}
a0,a1,a2是未知的如果把
(
x
1
,
x
2
)
(x_1 , x_2)
(x1,x2)带入方程,得到:
y
1
=
a
2
x
1
2
+
a
1
x
1
+
a
0
y_1 = a_2x_{1}^{2}+a_{1}x_{1}+a_{0}
y1=a2x12+a1x1+a0然后变形:
(
x
1
2
x
1
1
)
(
a
2
a
1
a
0
)
=
y
1
begin{gathered} begin{pmatrix} x_{1}^{2} & x_{1} & 1end{pmatrix} begin{pmatrix} a_{2} \ a_{1} \ a_{0}end{pmatrix} =y_{1} end{gathered}
(x12x11)⎝⎛a2a1a0⎠⎞=y1
同理
(
x
i
,
y
i
)
,
i
=
1
,
2
⋯
n
(x_i,y_i),i=1,2cdots n
(xi,yi),i=1,2⋯n,可以得到:
(
x
i
2
x
i
1
)
(
a
2
a
1
a
0
)
=
y
i
begin{gathered} begin{pmatrix} x_{i}^{2} & x_{i} & 1end{pmatrix} begin{pmatrix} a_{2} \ a_{1} \ a_{0}end{pmatrix} =y_{i} end{gathered}
(xi2xi1)⎝⎛a2a1a0⎠⎞=yi
所以可以组合成矩阵的形式:
(
x
1
2
x
1
1
⋮
⋮
⋮
x
n
2
x
n
1
)
(
a
2
a
1
a
0
)
=
(
y
1
⋮
y
n
)
begin{pmatrix} x_{1}^{2} & x_{1} & 1 \ vdots & vdots & vdots \ x_{n}^{2} & x_{n} & 1 end{pmatrix} begin{pmatrix} a_{2} \ a_{1} \ a_{0}end{pmatrix} =begin{pmatrix} y_{1} \ vdots \ y_{n}end{pmatrix}
⎝⎜⎛x12⋮xn2x1⋮xn1⋮1⎠⎟⎞⎝⎛a2a1a0⎠⎞=⎝⎜⎛y1⋮yn⎠⎟⎞
假设:
(
x
1
2
x
1
1
⋮
⋮
⋮
x
n
2
x
n
1
)
begin{pmatrix} x_{1}^{2} & x_{1} & 1 \ vdots & vdots & vdots \ x_{n}^{2} & x_{n} & 1 end{pmatrix}
⎝⎜⎛x12⋮xn2x1⋮xn1⋮1⎠⎟⎞为A,
(
y
1
⋮
y
n
)
begin{pmatrix} y_{1} \ vdots \ y_{n}end{pmatrix}
⎝⎜⎛y1⋮yn⎠⎟⎞为T,
(
a
2
a
1
a
0
)
begin{pmatrix} a_{2} \ a_{1} \ a_{0}end{pmatrix}
⎝⎛a2a1a0⎠⎞为x
A
x
=
T
Ax=T
Ax=T
⇒
A
T
A
x
=
A
T
T
Rightarrow A^{T}Ax=A^{T}T
⇒ATAx=ATT
⇒
A
T
A
−
1
A
T
A
x
=
A
T
A
−
1
A
T
T
Rightarrow { A^{T}A}^{-1}A^{T}Ax={ A^{T}A}^{-1}A^{T}T
⇒ATA−1ATAx=ATA−1ATT
⇒
x
=
A
T
A
−
1
A
T
T
Rightarrow x={ A^{T}A}^{-1}A^{T}T
⇒x=ATA−1ATT
二次方程线性回归
import numpy as np import matplotlib.pyplot as plt import numpy.linalg as lg t = np.arange(1, 17, 1) y = np.array([4, 6.4, 8, 8.8, 9.22, 9.5, 9.7, 9.86, 10, 10.20, 10.32, 10.42, 10.5, 10.55, 10.58, 10.6]) plt.figure() plt.plot(t, y, 'k*') # y=at^2+bt+c A = np.c_[t ** 2, t, np.ones(t.shape)] w = lg.inv(A.T.dot(A)).dot(A.T).dot(y) plt.plot(t, w[0] * t ** 2 + w[1] * t + w[2]) plt.show()
import numpy as np import matplotlib.pyplot as plt import numpy.linalg as lg t = np.arange(1, 17, 1) y = np.array([4, 6.4, 8, 8.8, 9.22, 9.5, 9.7, 9.86, 10, 10.20, 10.32, 10.42, 10.5, 10.55, 10.58, 10.6]) plt.figure() plt.plot(t, y, 'k*') #y=ax^(1/2)+bx^(1/4)+c A = np.c_[t ** (1 / 2), t ** (1 / 4), np.ones(t.shape)] w = lg.inv(A.T.dot(A)).dot(A.T).dot(y) plt.plot(t, w[0] * t ** (1 / 2) + w[1] * t ** (1 / 4) + w[2]) plt.show()
双曲线线性回归
import numpy as np import matplotlib.pyplot as plt import numpy.linalg as lg t = np.arange(1, 17, 1) y = np.array([4, 6.4, 8, 8.8, 9.22, 9.5, 9.7, 9.86, 10, 10.20, 10.32, 10.42, 10.5, 10.55, 10.58, 10.6]) plt.figure() plt.plot(t, y, 'k*') # y=a/t+b A = np.c_[1 / t, np.ones(t.shape)] w = lg.inv(A.T.dot(A)).dot(A.T).dot(y) plt.plot(t, w[0] / t + w[1]) plt.show()用Python实现一元线性回归
一个简单的线性回归的例子就是房子价值预测问题。一般来说,房子越大,房屋的价值越高。于是可以推断出,房子的价值是房屋面积有关的。
| 编号 | 平方英尺 | 价格(元/平方英尺) |
|---|---|---|
| 1 | 150 | 6450 |
| 2 | 200 | 7450 |
| 3 | 250 | 8450 |
| 4 | 300 | 9450 |
| 5 | 350 | 11450 |
| 6 | 400 | 15400 |
| 7 | 600 | 18450 |
1)在线性回归中,必须在数据中找到一种线性关系,以使我们可以得到a和b。假设方程式如下:
y
(
X
)
=
a
+
b
X
y(X)=a+bX
y(X)=a+bX
其中:
y
(
x
)
y(x)
y(x)是关于特定平方英尺的价格值(要预测的值),意思是价格是平方英尺的线性函数。a是一个常数;b是回归系数。那么现在开始编程:
把数据存储成CSV文件,命名为input_data.csv
id,square_feet,price 1,150,6450 2,200,7450 3,250,8450 4,300,8450 5,350,11450 6,400,15400 7,600,18450
新建python文件predict_house_price.py
import numpy as np
import pandas as pd
from sklearn import datasets, linear_model
import matplotlib.pyplot as plt
# 读取数据函数
def get_data(file_name):
data = pd.read_csv(file_name) # 读取cvs文件
x_parameter = []
y_parameter = []
for single_square_feet, single_price_value in zip(data['square_feet'], data['price']):
# 遍历数据
x_parameter.append([float(single_square_feet)]) # 存储在相应的list列表中
y_parameter.append(float(single_price_value))
return x_parameter, y_parameter
# 将数据拟合到线性模型
def linear_model_main(x_parameters, y_parameters, predict_value):
regr = linear_model.LinearRegression()
regr.fit(x_parameters, y_parameters) # 训练模型
predict_outcome = regr.predict(predict_value)
predictions = {'intercept': regr.intercept_, 'coefficient': regr.coef_, 'predicted_value': predict_outcome}
return predictions
# 显示线性拟合模型的结果
def show_linear_line(x_parameters, y_parameters):
regr = linear_model.LinearRegression()
regr.fit(x_parameters, y_parameters)
plt.scatter(x_parameters, y_parameters, color='blue')
plt.plot(x_parameters, regr.predict(x_parameters), color='red', linewidth=4)
plt.xticks(())
plt.yticks(())
plt.show()
x, y = get_data('input_data.csv')
predictValue = [[700]]
result = linear_model_main(x, y, predictValue)
print("Intercept value", result['intercept'])
print("coefficient", result['coefficient'])
print("Predicted value", result['predicted_value'])
show_linear_line(x, y)
这里使用的是scikit-learn机器学习算法包。该算法包是目前Python实现的机器算法包中最好用的一个。
regr.fit(x_parameters, y_parameters)是输入点对,来训练模型。
regr.predict(predict_value)使用模型来预测某一个x的y值。
regr.intercept_线性回归的截距值,就是a的值
regr.coef_系数,就是b的值
当结果值的影响因素有多个时,可以采用多元线性回归模型。例如,商品的销售额可能与电视广告投入、收音机广告投入、报纸广告投入有关系。可以有 S a l e s = β 0 + β 1 T V + β 2 R a d i o + β 3 N e w s p a p e r Sales=beta_{0}+beta_{1}TV+beta_{2}Radio+beta_{3}Newspaper Sales=β0+β1TV+β2Radio+β3Newspaper
使用pandas读取数据pandas是一个用于数据探索、数据分析和数据处理的Python库。
import pandas as pd
data=pd.read_csv("D:/Data/Advertising.csv")
print(data.head())
上面显示的结果集类似一个电子表格,这个结构称为pandas的数据帧,类型全称是pandas.core.frame.Dataframe。
pandas的两个主要数据结构是Series和Dataframe;Series类似于一维数组,它由一组数据及一组与之相关的数据标签组成;Dataframe是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型。Dataframe既有行索引也有列索引,它可以被看作由Series组成的字典。
import pandas as pd
data=pd.read_csv("D:/Data/Advertising.csv")
print(data.tail())
import pandas as pd
data=pd.read_csv("D:/Data/Advertising.csv")
print(data.shape)
分析数据
TV:在电视上投资的广告费用
Radio:在广播媒体上投资的广告费用
Newspaper:用于报纸媒体的广告费用
相应:连续的值
Sales:对应产品的销量
在这个案例中,通过不同的广告投入,预测产品销量。因为响应变量是一个连续的值,所以这个问题是一个回归问题。数据集一共有200个观测值,每一组观测对应一个市场的情况。
注:这里推荐使用的是seaborn包。这个包的数据可视化效果比较好。其实seaborn也属于Matplotlib的内部包,只是需要单独安装。
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
data = pd.read_csv("D:/Data/Advertising.csv")
# 使用散点图可视化特征与相应之间的关系
sns.pairplot(data, x_vars=['TV', 'radio', 'newspaper'], y_vars='sales', size=7, aspect=0.8,kind='reg')
plt.show()
# 这里选择TV.Radio.Newspaper作为特征,Sales作为观测值
seaborn的pairplot函数绘制X的每一维度都和对应Y的散点图。通过设置size和aspect参数来调节显示的大小和比例。通过加入参数kind=‘reg’,seaborn可以添加一条最佳拟合直线和95%的置信带。
可以看出,TV特征和销量是有比较强的线性关系的,而Radio和Sales线性关系弱一些,Newspaper和Sales线性关系更弱。
优点:快速;没有调节参数;可轻易解释;可理解
缺点:相比其他复杂一些的模型,其预测准确率不高,因为它假设特征和响应之间存在确定的线性关系,这种假设对于非线性的关系,线性回归模型显然不能很好的进行数据建模。
使用pandas构建X(特征向量)和y(标签列)
scikit-learn要求X是一个特征矩阵,y是一个NumPy向量。pandas构建在NumPy之上。因此,X可以是pandas的Dataframe,y可以是pandas的Series,scikit-learn可以理解这种结构。
import pandas as pd
data = pd.read_csv("D:/Data/Advertising.csv")
featrue_cols=['TV','radio','newspaper']
x=data[featrue_cols]
print(x.head())
import pandas as pd
data = pd.read_csv("D:/Data/Advertising.csv")
featrue_cols=['TV','radio','newspaper']
x=data[featrue_cols]
y=data['sales']
print(y.head())
构建训练集与测试集
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn import metrics
import numpy as np
data = pd.read_csv("D:/Data/Advertising.csv")
featrue_cols = ['TV', 'radio', 'newspaper']
x = data[featrue_cols]
y = data['sales']
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1)
print(x_train.shape)
print(x_test.shape)
print(y_train.shape)
print(y_test.shape)
sklearn的线性回归
使用sklearn做线性回归,首先导入相关的线性回归模型,然后做线性回归模拟。
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn import metrics
import numpy as np
data = pd.read_csv("D:/Data/Advertising.csv")
featrue_cols = ['TV', 'radio', 'newspaper']
x = data[featrue_cols]
y = data['sales']
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1)
linreg = LinearRegression()
model = linreg.fit(x_train, y_train)
print(model)
print(linreg.intercept_)
print(linreg.coef_)
线性回归的结果
y
=
2.867
+
0.0465
×
T
V
+
0.179
×
R
a
d
i
o
+
0.00345
×
N
e
w
s
p
a
p
e
r
y=2.867+0.0465times TV+0.179times Radio+0.00345times Newspaper
y=2.867+0.0465×TV+0.179×Radio+0.00345×Newspaper
预测
通过线性模拟求出回归模型之后,可通过模型预测数据,通过predict函数即可求出预测结果。
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn import metrics
import numpy as np
data = pd.read_csv("D:/Data/Advertising.csv")
featrue_cols = ['TV', 'radio', 'newspaper']
x = data[featrue_cols]
y = data['sales']
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1)
linreg = LinearRegression()
model = linreg.fit(x_train, y_train)
y_pred=linreg.predict(x_test)
print(y_pred)
print(type(y_pred))
评价测度
对于分类问题,评价测度是准确率,但其不适用于回归问题,因此使用对连续数值的评价测度。
这里介绍3种常用的针对线性回归的评价测定。
- 平均绝对误差(Mean Absolute Error,MAE)
- 均方误差(Mean Squared Error,MSE)
- 均方根误差(Root Mean Squared Error,RMSE)
print(type(y_pred),type(y_test))
print(len(y_pred),len(y_test))
print(y_pred.shape,y_test.shape)
sum_mean=0
for i in range(len(y_pred)):
sum_mean+=(y_pred[i]-y_test.values[i])**2
sum_erro=np.sqrt(sum_mean/50)
print("RMSE by hand:",sum_erro)
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn import metrics
import numpy as np
data = pd.read_csv("D:/Data/Advertising.csv")
featrue_cols = ['TV', 'radio', 'newspaper']
x = data[featrue_cols]
y = data['sales']
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1)
linreg = LinearRegression()
model = linreg.fit(x_train, y_train)
y_pred=linreg.predict(x_test)
sum_mean=0
for i in range(len(y_pred)):
sum_mean+=(y_pred[i]-y_test.values[i])**2
sum_erro=np.sqrt(sum_mean/50)
plt.figure()
plt.plot(range(len(y_pred)),y_pred,'b',label="predict")
plt.plot(range(len(y_pred)),y_test,'r',label="test")
plt.legend(loc="upper right")
plt.xlabel("the number of sales")
plt.ylabel("value of sales")
plt.show()



