《python machine learning》chapter 10 Predicting Continuous Target Variables with Regression Analysis
【主要内容】
(1)探索和可视化数据集
(2)用不同方法实现线性回归分析
(3)训练适用于离群值的回归模型
(4)评估回归模型,解决通用问题
(5)调整适用于非线性数据的回归模型
git源码:https://github.com/xuman-Amy/Regression-Analysis
【简单回归模型(单一变量)】
对于单一变量 x (解释变量) 与连续值(目标变量y)之间的关系建模。
为y轴截距,
为解释变量的权值系数。
目标:找到best-fitting line。如下所示
【多变量回归模型】
【housing dataset】
数据说明:
加载数据:
#import data
import pandas as pd
df = pd.read_csv(
'G:\Machine Learning\python machine learning\python machine learning code\code\ch10\housing.data.txt',
header = None,sep = '\s+') #\s 空白字符分割
df.columns = ['CRIM', 'ZN', 'INDUS', 'CHAS',
'NOX', 'RM', 'AGE', 'DIS', 'RAD',
'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
df.head()
目标值为MEDV即价钱。
【Exploratory Data Analysis】探索性数据分析(EDA)
运用EDA的可视化工具查看离群值的分布
接下来用seaborn库的pairplot函数查看特征两两之间的关系
#EDA Exploratory Data Analysis
import matplotlib.pyplot as plt
import seaborn as sns
colms = ['LSTAT', 'INDUS', 'NOX', 'RM', 'MEDV']
sns.pairplot(df[colms], size = 2.5)
#sns.pairplot(df, size = 2.5) #查看所有特征之间的关系
plt.tight_layout()
plt.show()
【利用相关矩阵查看特征之间的关系】
实际上,相关矩阵与由标准化特征计算的协方差矩阵是相同的。
皮尔森相关系数计算公式:
标准化x,y:
协方差计算公式:
对于标准化的x,y,均值为0,公式可以写为:
又
所以标准化的x,y的协方差 公式等同于
最后可以简化公式为
【画相关矩阵的热力图 heatmap】
import numpy as np
cm = np.corrcoef(df.values.T)#相关系数矩阵
sns.set(font_scale = 1.5)
#annot = True在每个方框里写值,fmt 写值的格式,
hm = sns.heatmap(cm,
cbar = True,
annot = True,
fmt = '.2f',
annot_kws = {'size': 5},
yticklabels=df.columns,
xticklabels=df.columns)
plt.show()
从热力图看,LSTAT与MEDV相关系数高达-0.74,但是从散点图看二者为非线性关系。
MEDV第二高相关变量为 RM, 且从散点图看二者呈现线性关系,RM可能是不错的解释变量的选择。
【实现普通的最小二乘线性回归模型】
Ordinary Least Square(OLS) also called Linear Least Square
估计线性回归线的参数,将平方垂直距离的总和最小化。
【梯度递减法解决回归参数的回归问题】
定义cost function:
OLS可以理解为没有单位阶梯函数到的自适应线性神经元 ADAptive LInear NEuron (Adaline) ,得到的是连续目标值,而不再是类标记1,-1
Adaline 的 LinearRegression gradient descent 函数
# Linear regresion gradient descent
class LinearRegressionGD(object):
def __init__(self, eta=0.001, n_iter=20):
self.eta = eta
self.n_iter = n_iter
def fit(self, X, y):
self.w_ = np.zeros(1 + X.shape[1])
self.cost_ = []
for i in range(self.n_iter):
output = self.net_input(X)
errors = (y - output)
self.w_[1:] += self.eta * X.T.dot(errors)
self.w_[0] += self.eta * errors.sum()
cost = (errors**2).sum() / 2.0
self.cost_.append(cost)
return self
def net_input(self, X):
return np.dot(X, self.w_[1:]) + self.w_[0]
def predict(self, X):
return self.net_input(X)
将RM作为解释变量,MEDV作为目标变量
#RM作为解释变量,预测MEDV的值
X = df[['RM']].values
y = df['MEDV'].values
运用GD进行回归分析
#标准化
from sklearn.preprocessing import StandardScaler
sc_x = StandardScaler()
sc_y = StandardScaler()
X_std = sc_x.fit_transform(X)
#因为sklearn的很多transform函数的参数要求是二维的,所以利用np.newaxis将y变为二维,
# 标准化之后将y恢复到一维
y_std = sc_y.fit_transform(y[:, np.newaxis]).flatten()
#调用LRGD函数
lr = LinearRegressionGD()
lr.fit(X_std, y_std)
画出cost函数与迭代次数的关系图
# plot cost function as a function of the number of epoches
sns.reset_orig() #resetmatplotlib style
plt.plot(range(1, lr.n_iter + 1), lr.cost_)
plt.ylabel('SSE')
plt.xlabel('Epoch')
plt.show()
画出回归线与变量X,y 的散点图
# 画出回归线以及X,y的散点图
def lin_regplot(X, y, model):
plt.scatter(X, y, c='steelblue', edgecolor='white', s=70)
plt.plot(X, model.predict(X), color='black', lw=2)
return
lin_regplot(X_std, y_std, lr)
plt.xlabel('Average number of rooms [RM] (standardized)')
plt.ylabel('Price in $1000s [MEDV] (standardized)')
plt.show()
值得一提的是,在标准化变量之后,不必进行截距的权值更新,因为标准化下截距始终为0 。