学习框架
模型建立
线性回归原理
进入一家房产网,可以看到房价、面积、厅室呈现以下数据:
线性回归模型
1. 线性回归的一般形式
2. 极大似然估计(概率角度阐释)
我们建立极大似然函数,即描述数据遵从当前样本分布的概率分布函数。由于样本的数据集独立同分布,因此可以写成:
这一结果即均方误差,因此用这个值作为代价函数来优化模型在统计学的角度是合理的。
学习策略
答:当模型复杂度增加时,有可能对训练集可以模拟的很好,但是预测测试集的效果不好,出现过拟合现象,这就出现了所谓的“结构化风险”。结构风险最小化即为了防止过拟合而提出来的策略,定义模型复杂度为 J(F) ,目标函数可表示为:
算法求解
梯度下降法
当J 为凸函数时,梯度下降法相当于让参数Θ不断向J的最小值位置移动。
最小二乘法矩阵求解
牛顿法的收敛速度非常快,但海森矩阵的计算较为复杂,尤其当参数的维度很多时,会耗费大量计算成本。我们可以用其他矩阵替代海森矩阵,用拟牛顿法进行估计。
牛顿法比梯度下降法收敛速度更快,红色的牛顿法的迭代路径,绿色的是梯度下降法的迭代路径。
拟牛顿法
常用的拟牛顿法算法包括DFP,BFGS等。拟牛顿法的思路是用一个矩阵替代计算复杂的海森矩阵H
,因此要找到符合H性质的矩阵。
要求得海森矩阵符合的条件,同样对泰勒公式求导
线性回归的评估指标
我们可以把R的平方理解为,回归模型可以成功解释的数据方差部分在数据固有方差中所占的比例,
sklearn参数详解
1. it_intercept
默认为True,是否计算该模型的截距。如果使用中心化的数据,可以考虑设置为False,不考虑截距。一般还是要考虑截距。
2. normalize
默认为false. 当fit_intercept设置为false的时候,这个参数会被自动忽略。如果为True,回归器会标准化输入参数:减去平均值,并且除以相应的二范数。当然啦,在这里还是建议将标准化的工作放在训练模型之前。通过设置sklearn.preprocessing.StandardScaler来实现,而在此处设置为false。
3. copy_X
默认为True, 否则X会被改写
4. n_jobs
int 默认为1. 当-1时默认使用全部CPUs ??(这个参数有待尝试)
5. 可用属性
**coef_*训练后的输入端模型系数,如果label有两个,即y值有两列。那么是一个2D的array
6. intercept_: 截距
7. 可用的methods
1.fit(X,y,sample_weight=None):
X: array, 稀疏矩阵 [n_samples,n_features]
y: array [n_samples, n_targets]
sample_weight: 权重 array [n_samples] 在版本0.17后添加了sample_weight
2.get_params(deep=True):返回对regressor 的设置值
3.predict(X): 预测 基于 R^2值
4.score:评估
练习题
请用以下数据(可自行生成尝试,或用其他已有数据集)
首先尝试调用sklearn的线性回归函数进行训练;
用最小二乘法的矩阵求解法训练数据;
用梯度下降法训练数据;
比较各方法得出的结果是否一致。
1. sklearn的线性回归
"""1,使用sklearn中封装的线性回归模型进行预测解决线性回归问题。"""
# 1:生成数据
np.random.seed(1234) # 这个函数控制着随机数的生成。当你将seed值设为某一定值,则np.random下随机数生成函数生成的随机数永远是不变的
x = np.random.rand(500, 3) # 生成500行3列的随机数,0-1之间,作为待预测的值
# 构建映射关系,模拟真实数据待预测值,映射关系为y=4.2*x1+5.7*x2+10.8*x3 ,作为校验的标签
y = x.dot(np.array([4.2, 5.7, 10.8]))
# 2:训练模型
lr = LinearRegression(fit_intercept=True)
lr.fit(x, y)
# 3:预测测试
x_test = np.array([4, 5, 7]).reshape(1, -1) # reshape(1,-1):把数组变成一列,多少行随数组元素的个数决定
y_hat = lr.predict(x_test)
print('真实值为:', x_test.dot(np.array([4.2, 5.7, 10.8])))
print('预测值:', y_hat)
# 4:计算R方,用来评估拟合的效果
print("估计的参数值:%s" % lr.coef_)
print("估计的截距:%s" % lr.intercept_)
print('R2:', (lr.score(x, y)))
2. 最小二乘法
class LR_LS():
def __init__(self):
self.w = None
def fit(self, X, y):
# 最小二乘法矩阵求解
#============================= show me your code =======================
self.w = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y)
#============================= show me your code =======================
def predict(self, X):
# 用已经拟合的参数值预测新自变量
#============================= show me your code =======================
y_pred = X.dot(self.w)
#============================= show me your code =======================
return y_pred
if __name__ == "__main__":
lr_ls = LR_LS()
lr_ls.fit(x,y)
print("估计的参数值:%s" %(lr_ls.w))
x_test = np.array([4,5,7]).reshape(1,-1)
print('真实值为:',x_test.dot(np.array([4.2,5.7,10.8])))
print("预测值为: %s" %(lr_ls.predict(x_test)))
3. 梯度下降法
class LR_GD():
def __init__(self):
self.w = None
def fit(self,X,y,alpha=0.002,loss = 1e-10): # 设定步长为0.002,判断是否收敛的条件为1e-10
y = y.reshape(-1,1) #重塑y值的维度以便矩阵运算
[m,d] = np.shape(X) #自变量的维度
self.w = np.zeros((d)) #将参数的初始值定为0
tol = 1e5
#============================= show me your code =======================
while tol > loss:
h_f = X.dot(self.w).reshape(-1,1)
theta = self.w + alpha*np.mean(X*(y - h_f),axis=0) #计算迭代的参数值
tol = np.sum(np.abs(theta - self.w))
self.w = theta
#============================= show me your code =======================
def predict(self, X):
# 用已经拟合的参数值预测新自变量
y_pred = X.dot(self.w)
return y_pred
if __name__ == "__main__":
lr_gd = LR_GD()
lr_gd.fit(x,y)
print("估计的参数值为:%s" %(lr_gd.w))
x_test = np.array([4,5,7]).reshape(1,-1)
print('真实值为:',x_test.dot(np.array([4.2,5.7,10.8])))
print("预测值为:%s" %(lr_gd.predict(x_test)))
4. 测试
在3维数据上测试sklearn线性回归和最小二乘法的结果相同,梯度下降法略有误差;又在100维数据上测试了一下最小二乘法的结果比sklearn线性回归的结果更好一些。
全部评论