(85)--Python数据分析:简单线性回归

# 散点图描绘

(一)准备工作

1.编程环境:Python3.5.2(使用其自带的IDLE,并已经配置好环境变量),win10。

2.使用到的包:numpy,matplotlib,Pandas,sklearn,OrderedDict,matplotlib

(注:可用pip install xxx直接安装,有问题就直接搜索引擎解决)。

3.数据源:

a. ex0.txt :pan.baidu.com/s/1kXciH1 密码:ea05

4.参考资料:

a. 线性回归-维基百科

b.《机器学习》第3章线性模型;

c.《机器学习实战》第8章;

d. 猴子哥友情赞助知乎live:机器学习(入门):简单线性回归

e.《统计学习方法》第1、6、7章等。


(二)线性回归的简单介绍

1.线性回归。

线性回归(linear regression),也称回归,目的是预测数值型的目标值。最直接的办法是依据输入写出一个目标值的计算公式。比如,要预测轿车的功率大小,可能会这么计算:

HorsePower = 0.0015*annualSalary - 0.99*hoursListeningToPublicRadio

上式就是所谓的回归方程(regression equation),其中的0.0015和-0.99称作回归系数(regression weights),求解这些回归系数的过程就是回归。

一旦有了回归系数,再给定输入,做预测就简单了。具体的方法是用回归系数乘以输入值,再将全部结果加在一起,就得到了预测值。

简而言之,线性回归意味着可以将输入项分别乘以一些常量,再将结果加起来得到输出。

(注:存在另一种称为非线性回归的回归模型,该模型不认同线性回归的做法,比如认为输出可能是输入的乘积)


2.线性回归的一般方法。

a.收集数据:采用任意方法收集数据。

b.准备数据:回归需要数值型数据,标称型数据将被转成二值型数据。

c.分析数据:绘出数据的可视化二维图将有助于对数据做出理解和分析,在采用缩减法求得新 回归系数之后,可以将新拟合线绘在图上作为对比。

d.训练算法:找到回归系数。

e.测试算法:使用R^2或者预测值和数据的拟合度,来分析模型的效果。

f.使用算法:使用回归,可以在给定输入的时候预测出一个数值,这是对分类方法的提升,因为这样可以预测连续型数据而不仅仅是离散的类别标签。


(三)线性回归实践

1.标准回归函数和数据导入函数。

import matplotlib.pyplot as plt
import numpy as np

#loadDataSet()函数打开一个用tab键分隔的文本文件,这里默认文件每行的最后一个值是目标值。
def loadDataSet(fileName):      
    numFeat = len(open(fileName).readline().split('\t')) - 1  
    dataMat = []; labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr =[]
        curLine = line.strip().split('\t')
        for i in range(numFeat):
            lineArr.append(float(curLine[i]))
        dataMat.append(lineArr)
        labelMat.append(float(curLine[-1]))
    return dataMat,labelMat

#standRegres()函数用于计算最佳拟合直线。
#该函数首先读入x和y并将它们保存到矩阵中,然后计算xTx,然后判断它的行列式是否为0。
#如果行列式为0,那么计算逆矩阵的时候将出现错误。
def standRegres(xArr,yArr):
    xMat = np.mat(xArr); yMat = np.mat(yArr).T
    xTx = xMat.T*xMat
    if np.linalg.det(xTx) == 0.0:
        print ("This matrix is singular, cannot do inverse")
        return
    ws = xTx.I * (xMat.T*yMat)
    return ws


使用loadDataSet()函数将从数据中得到两个数组,分别存放在x和y中。与分类算法中的类别标签类似,这里的y是目标值。

>>> xArr,yArr = loadDataSet('ex0.txt')

首先看前两条数据:

>>> xArr,yArr = loadDataSet('ex0.txt')
>>> xArr[0:2]
[[1.0, 0.067732], [1.0, 0.42781]]

第一个值总是等于1.0,即x0。假设偏移量就是一个常数。第二个值x1,也就是下图中的横坐标值。

现在看一下standRegres()函数的执行效果:

>>> ws = standRegres(xArr,yArr)
>>> ws
matrix([[ 3.00774324],
        [ 1.69532264]])

变量ws存放的就是回归系数。在用内积来预测y的时候,第一维将乘以前面的常数x0,第二维将乘以输入变量x1。因为前面假设了x0=1,所以最终会得到y=ws[0]+ws[1]*x1。

这里的y实际是预测出的,为了和真实的y值区分开来,这里将它记为yHat。

下面使用新的ws值计算yHat:

>>> xMat = np.mat(xArr)
>>> yMat = np.mat(yArr)
>>> yHat = xMat*ws

接下来绘出数据集散点图和最佳拟合直线图:

>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0])
<matplotlib.collections.PathCollection object at 0x000002041E0AAA58>

上述命令创建了图像并绘出了原始的数据。为了绘制计算出的最佳拟合直线,需要绘出yHat的值。如果直线上的数据点次序混乱,绘图时将会出现问题,所以首先要将点按照升序排列:

>>> xCopy = xMat.copy()
>>> xCopy.sort(0)
>>> yHat = xCopy*ws
>>> ax.plot(xCopy[:,1],yHat)
[<matplotlib.lines.Line2D object at 0x000002041E0AAF98>]
>>> plt.show()

效果图如下:

ex0.txt的数据集与它的最佳拟合直线

几乎任一数据集都可以用上述方法建立模型,最佳拟合直线将数据视为直线进行建模,并具有十分不错的表现。


(四)实例:有20名学生,研究这些学生在考前复习时间与得到的成绩之间的相关关系。

代码如下:

from collections import OrderedDict
import pandas as pd
examDict={
    '学习时间':[0.50,0.75,1.00,1.25,1.50,1.75,1.75,2.00,2.25,
            2.50,2.75,3.00,3.25,3.50,4.00,4.25,4.50,4.75,5.00,5.50],
    '分数':    [10,  22,  13,  43,  20,  22,  33,  50,  62,  
              48,  55,  75,  62,  73,  81,  76,  64,  82,  90,  93]
}
examOrderDict=OrderedDict(examDict)
exam=pd.DataFrame(examOrderDict)

输出结果:

>>> exam.head()
   学习时间  分数
0  0.50  10
1  0.75  22
2  1.00  13
3  1.25  43
4  1.50  20


重点来了:

1.接下来通过画图判断适不适合用线性回归的模型。代码如下:

from collections import OrderedDict
import matplotlib.pyplot as plt
import pandas as pd
examDict={
    '学习时间':[0.50,0.75,1.00,1.25,1.50,1.75,1.75,2.00,2.25,
            2.50,2.75,3.00,3.25,3.50,4.00,4.25,4.50,4.75,5.00,5.50],
    '分数':    [10,  22,  13,  43,  20,  22,  33,  50,  62,  
              48,  55,  75,  62,  73,  81,  76,  64,  82,  90,  93]
}
examOrderDict=OrderedDict(examDict)
exam=pd.DataFrame(examOrderDict)

#从dataframe中把标签和特征导出来
exam_X = exam['学习时间']
exam_Y = exam['分数']

#绘制散点图,得出结果后记得注释掉以下4行代码
plt.scatter(exam_X, exam_Y, color = 'green')
#设定X,Y轴标签和title
plt.ylabel('Scores')
plt.xlabel('Times(h)')
plt.title('Exam Data')

输出结果:

>>>plt.show()

得出结论:这个数据集适合线性回归的模型。


2.划分训练集与测试集。(在上文实例的代码中添加以下代码即可)

#第一个参数为特征,第二个参数为标签
from sklearn.cross_validation import train_test_split

#比例为7:3
X_train, X_test, Y_train, Y_test = train_test_split(exam_X,exam_Y, train_size = 0.7)

可以看一下分割后的结果

>>> X_train.head()
13    3.50
11    3.00
19    5.50
2     1.00
5     1.75
Name: 学习时间, dtype: float64
>>> X_train.shape
(14,)

继续添加代码:

#导入线性回归
#sklearn 要求输入的特征为二维数组类型。
#数据集只有1个特征,需要用array.reshape(-1, 1)来改变数组的形状

#改变一下数组的形状
X_train = X_train.values.reshape(-1, 1)
X_test = X_test.values.reshape(-1, 1)

#创建一个模型
model = LinearRegression()
#训练一下
model.fit(X_train, Y_train)

#因为线性回归一般方程为y = a+bx
#b为斜率,a为截距
#截距用intercept_
#斜率用model.coef_
a = model.intercept_
b = model.coef_
a = float(a)
b = float(b)
print('该模型的简单线性回归方程为y = {} + {} * x'.format(a, b))

输出效果:

该模型的简单线性回归方程为y = 6.7287023109531034 + 16.842335566798848 * x

继续添加代码:

#绘制散点图
plt.scatter(exam_X, exam_Y, color = 'green', label = 'train data')
#设定X,Y轴标签和title
plt.ylabel('Scores')
plt.xlabel('Times(h)')

#绘制最佳拟合曲线
Y_train_pred = model.predict(X_train)
plt.plot(X_train, Y_train_pred, color = 'black', label = 'best line')

#输出效果图
plt.legend(loc = 2)
plt.show()

得出效果图:

3.评估模型精度:

当训练集与测试集比例为0.7:0.3,即7:3时,:

该模型的简单线性回归方程为y = 6.7287023109531034 + 16.842335566798848 * x

模型精度:

>>> jingdu = model.score(X_test, Y_test)
>>> jingdu
0.63986766133833073


当训练集与测试集比例为0.8:0.2,即4:1时,:

该模型的简单线性回归方程为y = 10.43548387096775 + 15.645161290322577 * x

模型精度:

>>> jingdu =  model.score(X_test, Y_test)
>>> jingdu
0.83670231421038854

总之,多训练几次,得出最高的精度。


4.最后贴出本实例的全部代码:

from collections import OrderedDict
from sklearn.cross_validation import train_test_split
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
import pandas as pd

examDict={
    '学习时间':[0.50,0.75,1.00,1.25,1.50,1.75,1.75,2.00,2.25,
            2.50,2.75,3.00,3.25,3.50,4.00,4.25,4.50,4.75,5.00,5.50],
    '分数':    [10,  22,  13,  43,  20,  22,  33,  50,  62,  
              48,  55,  75,  62,  73,  81,  76,  64,  82,  90,  93]
}
examOrderDict=OrderedDict(examDict)
exam=pd.DataFrame(examOrderDict)

#从DataFrame中把标签和特征导出来
exam_X = exam['学习时间']
exam_Y = exam['分数']

#绘制散点图,通过画图判断适不适合用线性回归的模型,判断完之后要注释掉
plt.scatter(exam_X, exam_Y, color = 'green')
#设定X,Y轴标签和title
#plt.ylabel('Scores')
#plt.xlabel('Times(h)')
#plt.title('Exam Data')
#plt.show()

#比例为7:3
X_train, X_test, Y_train, Y_test = train_test_split(exam_X,exam_Y, train_size = 0.8)

#导入线性回归模型
#sklearn 要求输入的特征为二维数组类型。
#数据集只有1个特征,需要用array.reshape(-1, 1)来改变数组的形状

#改变一下数组的形状
X_train = X_train.values.reshape(-1, 1)
X_test = X_test.values.reshape(-1, 1)

#创建一个模型
model = LinearRegression()
#训练一下
model.fit(X_train, Y_train)

a = model.intercept_
b = model.coef_
a = float(a)
b = float(b)
print('该模型的简单线性回归方程为y = {} + {} * x'.format(a, b))

#绘制散点图
plt.scatter(exam_X, exam_Y, color = 'green', label = 'train data')
#设定X,Y轴标签和title
plt.ylabel('Scores')
plt.xlabel('Times(h)')

#绘制最佳拟合曲线
Y_train_pred = model.predict(X_train)
plt.plot(X_train, Y_train_pred, color = 'black', label = 'best line')

#输出效果图
plt.legend(loc = 2)
plt.show()

兄弟连学python


Python学习交流、资源共享群:563626388 QQ


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值