通用说明
如果要训练的数据,数据量大且计算资源不够时,可以使用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)
;
数据基本信息
data.info()
;
#数据每列中为空值的行的总数 data.isnull().sum()
;
#数据的行数和列数 data.shape
;
# 各属性的统计特性 data.describe()
;
数据探索-----各属性之间的相关性检查
#数据列名获取 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()
;
找出强相关的列
# 设置强相关阈值 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))
;
数据准备
#将数据分割成训练数据与测试数据 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_ #线性系数,从线性系数中可以看出各列对预测结果影响的程度
;
模型评价
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值减去预测值的图形
;
#用随机梯度下降优化线性模型(SGDRegressor) from sklearn.linear_model import SGDRegressor #使用默认配置初始化线性模型 sgdr = SGDRegressor() #训练:参数估计 sgdr.fit(X_train , y_train) #预测 sgdr_y_predict = sgdr.predict(X_test) sgdr.coef_
;
# 使用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
;
均方误差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))
正则化的线性回归------岭回归(知识点)
# 岭回归(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)
;
# 岭回归的超参数图形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()
;
# 岭回归的超参数图形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()
;
正则化的线性回归------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)
;
# 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()
;