上一次修改时间:2018-06-26 20:29:11

线性回归-代码

通用说明

如果要训练的数据,数据量大且计算资源不够时,可以使用train_test_split将数据分成训练集和校验集;但如果训练数据不大,或计算资源足够时,推荐使用交叉验证寻找最佳参数;通常情况下交叉验证的效果比train_test_split要好;

导入必要的工具包

# python 2.7    python 2.7    python 2.7    
# import sys
# sys.path.append('./log') #引入不同目录下的文件
#import debug
import numpy as np #linear algebra 开源数值计算扩展,可用来存储和处理大型矩阵
import pandas as pd #data processing, CSV 关系型数据库结构的数据结构和数据分析工具,基于numPy能实现SQL语言的大部分功能,如统计、分组、排序、透视表

from sklearn.metrics import r2_score #评价回归预测模型的性能

import matplotlib.pyplot as plt #2D图形绘制包
import seaborn as sns #一个基于Matplotlib的Python可视化工具包,提供更高层次的用户接口,可以给出漂亮的数据统计图
#color = sns.color_alette()

#将那些用matplotlib绘制的图显示在页面里而不是弹出一个窗口
%matplotlib inline

数据读取(波士顿的房价数据)

dataPath = './data/'
data = pd.read_csv(dataPath + "boston_housing.csv")
# print type(data)
#查看数据的前五行
data.head()
# print(type(data))
# help(pd.core.frame.DataFrame.drop)

image.png

数据基本信息

data.info()

image.png

#数据每列中为空值的行的总数
data.isnull().sum()

image.png

#数据的行数和列数
data.shape

image.png

# 各属性的统计特性
data.describe()

image.pngimage.png

数据探索-----各属性之间的相关性检查

#数据列名获取
cols = data.columns

#计算皮尔森相关系数(pearson co-efficient),通常认为大于0.5的为强相关
data_corr = data.corr().abs()

#画图
plt.subplots(figsize = (13 , 9))
sns.heatmap(data_corr , annot = True)
sns.heatmap(data_corr , mask = data_corr < 1 , cbar = False)

plt.savefig('house_coor.png')
plt.show()

image.png; 

找出强相关的列

# 设置强相关阈值
threshold = 0.5

# 强相关的列的列表
corr_list = []
size = data.shape[1]

for i in range(0, size): #for 'size' features
    for j in range(i+1,size): #avoid repetition
        if (data_corr.iloc[i,j] >= threshold and data_corr.iloc[i,j] < 1) or (data_corr.iloc[i,j] < 0 and data_corr.iloc[i,j] <= -threshold):
            corr_list.append([data_corr.iloc[i,j],i,j]) #store correlation and columns index

# 按相关性的值排序
s_corr_list = sorted(corr_list , key = lambda x: -abs(x[0]))

# 数据打印
for v , i , j in s_corr_list:
    print ("%s and %s = %.2f" % (cols[i] , cols[j] , v))

image.png

数据准备

#将数据分割成训练数据与测试数据
from sklearn.cross_validation import train_test_split

#drop函数中,axis=0(默认值)时,删除行数据,axis=1,删除列数据
y = data['MEDV']
X = data.drop('MEDV' , axis = 1)
#如果只使用某一个或几个特征时,可以将数据中的其它列删除
# X = data.drop(data.columns[[0,1,2,3,4,5,6,7,8,9,10,11,13]], axis = 1)
# help(pd.core.frame.DataFrame.drop)
# print('PIKAQIU' , data['MEDV'])

# 随机采样20%的数据构建测试样本,其余作为训练样本 train_test_split为sklearn.cross_validation下的函数
# train_test_split参数解释:train_data:所要划分的样本特征集;train_target:所要划分的样本结果;test_size:样本占比,如果是整数的话就是样本的数量
#random_state:随机数的种子;随机数种子:其实就是该组随机数的编号,在需要重复试验的时候,保证得到一组一样的随机数。比如你每次都填1,其他参数一样
#的情况下你得到的随机数组是一样的。但填0或不填,每次都会不一样。随机数的产生取决于种子,随机数和种子之间的关系遵从以下两个规则:
#1-种子不同,产生不同的随机数;种子相同,即使实例不同也产生相同的随机数;
X_train , X_test , y_train , y_test = train_test_split(X , y , random_state=33 , test_size=0.2)
#help(train_test_split)

数据预处理(数据标准化示例)

# 发现各特征差异较大,需要进行数据标准化预处理
# 标准化的目的在于避免原始特征值差异过大,导致训练得到的参数权重不一

# 数据标准化:z-score 标准化
from sklearn.preprocessing import StandardScaler

# 分别初始化对特征和目标的标准化器
ss_X = StandardScaler()
ss_y = StandardScaler()

# 分别对训练和测试数据的特征以及目标值进行标准化处理
X_train = ss_X.fit_transform(X_train) #该处fit和transform可以分成两步,fit为求均值和方差等参数,transform才是正式开始标准化
X_test = ss_X.transform(X_test) 

y_train = ss_y.fit_transform(y_train)
y_test = ss_y.transform(y_test)

线性回归

#线性回归
from sklearn.linear_model import LinearRegression

# 使用默认配置初始化,默认配置为普通最小二乘线性回归
lr = LinearRegression()

# 训练模型参数
lr.fit(X_train , y_train)

#预测
lr_y_predict = lr.predict(X_test)
lr_y_predict_train = lr.predict(X_train)

#显示特征的回归系数
print lr.intercept_ #截距,线性函数中的常数项
print lr.coef_ #线性系数,从线性系数中可以看出各列对预测结果影响的程度

image.png

模型评价

f , ax = plt.subplots(figsize=(7 , 5))
f.tight_layout()
ax.hist(y_train - lr_y_predict_train , bins = 40 , label = 'Residuals Linear' , color = 'b' , alpha = .5)
ax.set_title("Histogram of Residuals")
ax.legend(loc = 'best')
#图形为训练的真实y值减去预测值的图形

image.png

#用随机梯度下降优化线性模型(SGDRegressor)
from sklearn.linear_model import SGDRegressor

#使用默认配置初始化线性模型
sgdr = SGDRegressor()

#训练:参数估计
sgdr.fit(X_train , y_train)

#预测
sgdr_y_predict = sgdr.predict(X_test)

sgdr.coef_

image.png

# 使用LinearRegression模型自带的评估模块(r2-score),评估训练集,测试集以及梯度下降后的测试集,越大越好
print 'test:' , lr.score(X_test , y_test)
print 'training:' , lr.score(X_train , y_train)
print 'SGDRegressor_test:' , sgdr.score(X_train , y_train)
#样本数不多时,SGDRegressor可能不如LinearRegression拟合得好。 sklearn建议样本数超过10万采用SGDRegressor

image.png

均方误差MSE,RMSE示例(越小拟合得越好)

from sklearn import metrics

#MSE
print "training_MSE:" , metrics.mean_squared_error(y_train , lr_y_predict_train)
print "test_MSE:" , metrics.mean_squared_error(y_test , lr_y_predict)
print "SGDRegressor_MSE:" , metrics.mean_squared_error(y_test , sgdr_y_predict)

#RMSE,rmse为mse的开方,该值与均绝对误差MAE对应
print "training_RMSE:" , np.sqrt(metrics.mean_squared_error(y_train , lr_y_predict_train))
print "test_RMSE:" , np.sqrt(metrics.mean_squared_error(y_test , lr_y_predict))
print "SGDRegressor_RMSE:" , np.sqrt(metrics.mean_squared_error(y_test , sgdr_y_predict))

image.png

正则化的线性回归------岭回归(知识点)

# 岭回归(L2损失 + L2正则)

# RidgeCV表示岭回归交叉检验,这个交叉检验类似于留一交叉验证法(leave-one-out cross-validation,LOOCV)。
from sklearn.linear_model import RidgeCV

#备选超参数设置,超参数值可随意输入
alphas = [0.01 , 0.1 , 1 , 10 , 20 , 40 , 80 , 100]
reg = RidgeCV(alphas = alphas , store_cv_values = True)
reg.fit(X_train , y_train)
#输出最优参数
print reg.alpha_
#输出线性系数,得到最优参数后,可以进一步选择该最优参数附近值再做一轮以得到更好的参数
print reg.coef_
# 使用LinearRegression模型自带的评估模块(r2_score),并输出评估结果
print 'RidgeCV_r2_score:', reg.score(X_test, y_test)

image.png

# 岭回归的超参数图形1
mse_mean = np.mean(reg.cv_values_, axis = 0)
mse_stds = np.std(reg.cv_values_, axis = 0)

x_axis = np.log10(alphas)
        
plt.errorbar(x_axis, mse_mean, yerr=mse_stds)

plt.title("Ridge for Boston House Price")
plt.xlabel( 'log(alpha)' )
plt.ylabel( 'mse' )
plt.savefig( 'RidgeCV.png' )

plt.show()

image.png

# 岭回归的超参数图形2
mse_mean = np.mean(reg.cv_values_, axis = 0)
plt.plot(np.log10(alphas), mse_mean) 
plt.plot(np.log10(reg.alpha_)*np.ones(3), [0.28, 0.29, 0.30])
plt.xlabel('log(alpha)')
plt.ylabel('mse')
plt.show()

image.png

正则化的线性回归------Lasso回归

#Lasso回归(L2损失 + L1正则)
from sklearn.linear_model import LassoCV

alphas = [0.01 , 0.1 , 1 , 10 ,20, 30 ,40 , 100]

lasso = LassoCV(alphas = alphas)
lasso.fit(X_train , y_train)

#输出最优参数
print lasso.alpha_
#输出线性系数,得到最优参数后,可以进一步选择该最优参数附近值再做一轮以得到更好的参数
print lasso.coef_
# 使用LinearRegression模型自带的评估模块(r2_score),并输出评估结果
print 'LassoCV_r2_score:', lasso.score(X_test, y_test)

image.png

# Lasso回归的超参数图形
mses = np.mean(lasso.mse_path_, axis = 1)
plt.plot(np.log10(lasso.alphas_), mses) 
#plt.plot(np.log10(lasso.alphas_)*np.ones(3), [0.3, 0.4, 1.0])
plt.xlabel('log(alpha)')
plt.ylabel('mse')
plt.show()

image.png