第一部分
# 线性回归:
# 如果不计算截距,本质就是矩阵运算,线性代数中的知识
# 如果要计算截距,只能使用梯度下降,多个参数系数,相当于多个变量
# 求偏导数
# 线性回归改进和升级
# Ridge岭回归,通过对系数的大小缩减来解决普通最小二乘的一些问题。
# 当数据的特征比样本点还多时,就不能使用线性回归和梯度下降等方法来预测
# 这是因为输入数据的矩阵X不是满秩矩阵,非满秩矩阵在求逆时会出现问题
# 为了解决这个问题,统计学家引入了岭回归(ridge regression)的概念
import numpy as np
# x + y + z = 10
# 2x + y + z = 10
# 2x - y + z = 10
X = np.array([[1, 1, 1], [2, 1, 1]])
# print(X)
# 在求上面X的逆矩阵时报错了,因为列的数量是3,秩的数量是2,是非满秩矩阵
# inv = np.linalg.inv(X)
# print(inv)
# zhi = np.linalg.matrix_rank(X) # 求出秩,
# print(zhi)
# X2 = np.array([[1, 1, 1], [2, 1, 1], [2, -1, 1]])
# zhi2 = np.linalg.matrix_rank(X2)
# print(zhi2) # 3
# x + y + z = 10
# 2x + y + z = 10
# 2x + 2y + 2z = 20
X3 = np.array([[1, 1, 1], [2, 1, 1], [2, 2, 2]])
zhi3 = np.linalg.matrix_rank(X3) # 因为第三个跟第一个一样了,系统识别了
# print(zhi3) # 2 不是满秩矩阵,就不能求逆,不能求逆就不能解方程
# 简单来说,岭回归就是矩阵XTX上加一个λI从而使得矩阵非奇异,进而能对XTX+λI求逆
# 其中矩阵I是一个m * m的单位矩阵,对角线上元素全为1,其他元素全为0,而λ是一个用户定义的数值
# 在这种情况下,回归系数的计算公式将变成 w = (XTX+λI)-1XTy 注释(T,-1,T)在幂的位置
i = np.eye(3) # 单位矩阵
# print(i)
#
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
X4 = X3 + 0.01 * i # 0.01就是用户自定义的λ
# print(X3)
# [[1 1 1]
# [2 1 1]
# [2 2 2]]
# print(X4)
# [[1.01 1. 1. ]
# [2. 1.01 1. ]
# [2. 2. 2.01]]
# 可以看出,在原来非满秩矩阵经过和(很小的系数*单位矩阵)运算之后,秩变成了满秩
zhi4 = np.linalg.matrix_rank(X4)
# print(zhi4) # 3
ss = np.linalg.inv(X4) # 当矩阵变成满秩矩阵之后就可以求逆矩阵,可以解方程了
# print(ss)
# 岭回归最先用来处理特征数多于样本数的情况,现在也用于在估计中键入偏差,从而的得到更好的估计。
# 这里通过引入λ来限制了所有w之和,通过引入该惩罚项,能够减少不重要的 参数,
# 这个技术在统计学中也叫缩减(shrinkage)
# 缩减方法可以去掉不重要的参数,因此能更好的理解数据。此外,与简单的线性回归相比,缩减发能取得更好的预测效果
# 岭回归是加了二阶正则项的最小二乘,主要适用于过拟合严重或各变量之间存在多重共线性的时候。
# 岭回归是有bias的,这里的bias是为了让variance更小
# Ridge a|w|**2 L2正则化平方
# 正则(re)-----Regularization(规则化)限制,不能让系数无限大
# 系数越大,波动越大,方程越不稳定
# 正则化:防止过拟合,提高泛化能力(面试问答)
# 过拟合(类似走火入魔),让算法学习数据(准确率)---算法预测(新数据)
# 过拟合(学习特征,太较真了),本质就是训练数据准确特别高,预测新数据特别低
# 例如,让算法去识别范冰冰的脸部,给了算法学习数据(照片),在给算法一张别人的照片,算法识别不出来了
# 我们实际需要算法识别的是眼睛到眉毛的距离,结果算法识别了眉毛有多少根,这种情况就是太较真了,是过拟合
# 拟合:寻找特征,寻找函数,数据和目标通过特征和函数建立关系
# 过拟合:系数特别多,系数绝对值很大
# 怎样解决过拟合:01--系数个数减少 02--系数的绝对值变小
# L2正则化,就是将系数的绝对值减小
第二部分
import time
import numpy as np
from sklearn.linear_model import LinearRegression, Ridge # 导入线性回归和岭回归
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split
boston = datasets.load_boston() # 波士顿房价
X = boston["data"] # 数据
y = boston["target"] # 目标
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
lr = LinearRegression() # 初始化一个线性回归对象
lr.fit(X_train, y_train)
print(lr.coef_, lr.score(X_test, y_test))
# 进入源码,可以看到岭回归使用的方程 ||y - Xw||^2_2 + alpha * ||w||^2_2
# 是否存在截距 是否标准化(归一化) 最大迭代次数 最大精度tolerate 容忍
ridge = Ridge(alpha=1.0, fit_intercept=True, normalize=False, copy_X=True, max_iter=None, tol=1e-3, solver="auto",
random_state=None)
ridge.fit(X_train, y_train)
print(ridge.coef_, ridge.score(X_test, y_test))
start = time.perf_counter()
end = time.perf_counter()
print(f"程序耗时为{(end - start).__round__(20)}")