# 散点图描绘
(一)准备工作
1.编程环境:Python3.5.2(使用其自带的IDLE,并已经配置好环境变量),win10。
2.使用到的包:numpy,matplotlib,Pandas,sklearn,OrderedDict,matplotlib
(注:可用pip install xxx直接安装,有问题就直接搜索引擎解决)。
3.数据源:
a. ex0.txt :https://pan.baidu.com/s/1kXciH1d 密码: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()
效果图如下:
![](https://i-blog.csdnimg.cn/blog_migrate/0f5bfda15df63b13d0ab798311eb6563.png)
几乎任一数据集都可以用上述方法建立模型,最佳拟合直线将数据视为直线进行建模,并具有十分不错的表现。
(四)实例:有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()
![](https://i-blog.csdnimg.cn/blog_migrate/c9654e9e37d3193ad46a989496c68c13.png)
得出结论:这个数据集适合线性回归的模型。
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()
得出效果图:
![](https://i-blog.csdnimg.cn/blog_migrate/c69b480ba43d94ccf46fde1f2c6e74b7.png)
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