5 线性回归
Sklearn类的线性回归以sklearn.linear_model.LinearRegression为基础,以sklearn.linear_model.Ridge(岭回归)、sklearn.linear_model.Lasso(套索回归)和sklearn.linear_model.ElasticNet(弹性网络)为优化。
我们首先来看一下如何通过Python画一条直线。
画出y = 0.5 × x 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()
画出经过[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()
# 显示这条线的斜率和截距
print('y={:.3f}'.format(lr.coef_[0]),'x',' {:.3f}'.format(lr.intercept_))
输出:
代码语言:javascript复制y=1.000 x 1.000
可以看到,斜率与截距均为1.000。
我们加入第三个点[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 0.500
斜率为0.500,截距为0.500。
该直线到这三个点偏差最小,正如前面所说的,线性回归方法即找出一条直线,使得各个点到这条直线上的误差最小。
接下来介绍一下LinearRegression。
表达式
代码语言:javascript复制sklearn.linear_model.LinearRegression(*, fit_intercept=True, normalize=False, copy_X=True, n_jobs=None, positive=False)
属性
属性 | 解释 |
---|---|
coef_ | array of shape (n_features, ) or (n_targets, n_features)。训练后的输入端模型系数,如果label有两个,即y值有两列。那么是一个2D的array |
intercept_ | float or array of shape (n_targets,).线性模型中的独立项(截距)。如果fit_intercept=False,则设置为0.0 |
rank_ | Int.矩阵X的秩。仅在X稠密时可用。 |
singular_ | array of shape (min(X, y),) . X的奇异值。仅在X为稠密时可用。 |
方法
fit(X, y[, sample_weight]) | 拟合线性模型。 |
---|---|
get_params([deep]) | 获取此估计器的参数。 |
predict(X) | 用线性模型预测。 |
score(X, y[, sample_weight]) | 返回预测的确定系数R2。 |
set_params(**params) | 设置此估计器的参数。 |
这里,特别介绍一下score方法
score (X, y, sample_weight=None)
返回给定测试数据和标签的平均精确度。在多标签分类中,这是子集精度,这是一个苛刻的度量标准,因为您需要为每个样本准确地预测每个标签集。
输入
X:array-like, shape = (n_samples, n_features)。样本。
y :array-like, shape = (n_samples) or (n_samples, n_outputs)。真的X标签。
sample_weight:array-like, shape = [n_samples], optional。测试权重。
输出
代码语言:javascript复制score :float。R2平均精度self.predict(X) wrt. y.
比如:
代码语言:javascript复制clf.score(X_train,y_train)))
clf.score(X_test,y_test)))
5.1 用make_regression数据(无噪音)进行线性回归
代码语言:javascript复制def LinearRegression_for_make_regression():
myutil = util()
X,y = make_regression(n_samples=100,n_features=1,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)
clf = LinearRegression().fit(X,y)
print('lr.coef_: {} '.format(clf.coef_[:]))
print('reg.intercept_: {}'.format(clf.intercept_))
print('训练集得分: {:.2%}'.format(clf.score(X_train,y_train)))
print('测试集得分: {:.2%}'.format(clf.score(X_test,y_test)))
输出
代码语言:javascript复制lr.coef_: [63.7840862]
reg.intercept_: 4.440892098500626e-15
训练集得分: 100.00%
测试集得分: 100.00%
由于有两个参数,线性回归方程:
代码语言:javascript复制y = 63.7840862X 4.440892098500626×10-15。
由于数据集没有噪声,所以score为100.00%。
在util类定义方法show_pic和draw_line
代码语言:javascript复制 #显示图片
def show_pic(self,title):
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
plt.suptitle(title)
plt.show()
#画拟合线
def draw_line(self,X,y,clf,title):
Z = np.linspace(-3,3,100)
plt.scatter(X,y,c='b',s=60)
try:
plt.plot(Z,clf.predict(Z.reshape(-1,1)),c='k')
except Exception as e:
print("不支持画线")
self.show_pic(title)
在上面代码后面加入:
代码语言:javascript复制 myutil = util()
title = "make_regression LinearRegression()回归线(无噪音)"
myutil.draw_line(X[:,0],y,clf,title)
得到如下图。
很显然,拟合度相当好。
最后调用util类中的学习曲线方法。
代码语言:javascript复制myutil.plot_learning_curve(LinearRegression(),X,y,title)
myutil.show_pic(title)
5.2 用make_regression数据(有噪音)进行线性回归
代码语言:javascript复制#加入噪音
def LinearRegression_for_make_regression_add_noise():
myutil = util()
X,y = make_regression(n_samples=100,n_features=1,n_informative=2,noise=50,random_state=8)
X_train,X_test,y_train,y_test = train_test_split(X, y, random_state=8,test_size=0.3)
clf = LinearRegression().fit(X,y)
print('lr.coef_: {} '.format(clf.coef_[:]))
print('reg.intercept_: {}'.format(clf.intercept_))
print('训练集得分: {:.2%}'.format(clf.score(X_train,y_train)))
print('测试集得分: {:.2%}'.format(clf.score(X_test,y_test)))
输出
代码语言:javascript复制lr.coef_: [68.77648945]
reg.intercept_: 1.2498738851984426
训练集得分: 70.18%
测试集得分: 64.27%
有两个参数,线性回归方程:
代码语言:javascript复制y = 68.77648945X 1.2498738851984426
由于数据集有噪声,所以score 不为100.00%.
画出拟合线和得分图。
代码语言:javascript复制myutil = util()
title = "make_regression LinearRegression()回归线(有噪音)"
myutil.draw_line(X[:,0],y,clf,title)
代码语言:javascript复制myutil.plot_learning_curve(LinearRegression(),X,y,title)
myutil.show_pic(title)
得分是非常低的。
5.3 用糖尿病数据进行线性回归
代码语言: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复制斜率: [11.5106203 -282.51347161 534.20455671 401.73142674 -1043.89718398 634.92464089 186.43262636 204.93373199 762.47149733 91.9460394 ]
截距: 152.562
糖尿病训练集得分: 53.04%
糖尿病测试集得分: 45.93%
可见用这个方法来拟合糖尿病数据是非常差的。画出得分图。
代码语言:javascript复制title = "make_regression 糖尿病数据"
myutil.plot_learning_curve(LinearRegression(),X,y,title)
myutil.show_pic(title)
由于这里的直线是10维的,所以不能画出拟合曲线。
5.4 用波士顿房价数据进行线性回归
代码语言: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('波士顿房价训练集得分: {:.2%}'.format(lr.score(X_train,y_train)))
print('波士顿房价测试集得分: {:.2%}'.format(lr.score(X_test,y_test)))
输出
代码语言:javascript复制斜率: [-1.14130415e-01 4.97830423e-02 4.15213771e-02 2.76156785e 00 -1.77723628e 01 3.89701303e 00 -1.08133797e-02 -1.54389831e 00 3.25856015e-01 -1.49890955e-02 -8.77878878e-01 7.79144087e-03 -4.97358277e-01]
截距: 36.38609891153045
波士顿房价训练集得分: 74.86%
波士顿房价测试集得分: 71.54%
画出得分图。
代码语言:javascript复制title = "make_regression 波士顿房价数据"
myutil.plot_learning_curve(LinearRegression(),X,y,title)
myutil.show_pic(title)
同样这里的直线不是2维的,所以不能画出拟合曲线。