损失函数(Loss Function):度量单样本预测的错误程度,损失函数值越小,模型就越好。
代价函数(Cost Function):度量全部样本集的平均误差。
目标函数(Object Function):代价函数和正则化函数,最终要优化的函数。
常用的损失函数包括:0-1损失函数、平方损失函数、绝对损失函数、对数损失函数等;常用的代价函数包括均方误差、均方根误差、平均绝对误差等。
思考题:既然代价函数已经可以度量样本集的平均误差,为什么还要设定目标函数?
回答:
当模型复杂度增加时,有可能对训练集可以模拟的很好,但是预测测试集的效果不好,出现过拟合现象,这就出现了所谓的“结构化风险”。结构风险最小化即为了防止过拟合而提出来的策略,定义模型复杂度为 J ( F ) J(F) J(F),目标函数可表示为:
m i n f ∈ F 1 n ∑ i = 1 n L ( y i , f ( x i ) ) + λ J ( F ) \underset{f\in F}{min}\, \frac{1}{n}\sum^{n}_{i=1}L(y_i,f(x_i))+\lambda J(F) f∈Fminn1i=1∑nL(yi,f(xi))+λJ(F)
当训练集本身存在噪声时,拟合曲线对未知影响因素的拟合往往不是最好的。 通常,随着模型复杂度的增加,训练误差会减少;但测试误差会先增加后减小。我们的最终目的时试测试误差达到最小,这就是我们为什么需要选取适合的目标函数的原因。
1、梯度下降法
2、最小二乘法矩阵求解
3、牛顿法
4、拟牛顿法
均方误差(MSE): 1 m ∑ i = 1 m ( y ( i ) − y ^ ( i ) ) 2 \frac{1}{m}\sum^{m}_{i=1}(y^{(i)} - \hat y^{(i)})^2 m1∑i=1m(y(i)−y^(i))2
均方根误差(RMSE): M S E = 1 m ∑ i = 1 m ( y ( i ) − y ^ ( i ) ) 2 \sqrt{MSE} = \sqrt{\frac{1}{m}\sum^{m}_{i=1}(y^{(i)} - \hat y^{(i)})^2} MSE=m1∑i=1m(y(i)−y^(i))2
平均绝对误差(MAE): 1 m ∑ i = 1 m ∣ ( y ( i ) − y ^ ( i ) ∣ \frac{1}{m}\sum^{m}_{i=1} | (y^{(i)} - \hat y^{(i)}| m1∑i=1m∣(y(i)−y^(i)∣
但以上评价指标都无法消除量纲不一致而导致的误差值差别大的问题,最常用的指标是 R 2 R^2 R2,可以避免量纲不一致问题
R 2 : = 1 − ∑ i = 1 m ( y ( i ) − y ^ ( i ) ) 2 ∑ i = 1 m ( y ˉ − y ^ ( i ) ) 2 = 1 − 1 m ∑ i = 1 m ( y ( i ) − y ^ ( i ) ) 2 1 m ∑ i = 1 m ( y ˉ − y ^ ( i ) ) 2 = 1 − M S E V A R R^2: = 1-\frac{\sum^{m}_{i=1}(y^{(i)} - \hat y^{(i)})^2}{\sum^{m}_{i=1}(\bar y - \hat y^{(i)})^2} =1-\frac{\frac{1}{m}\sum^{m}_{i=1}(y^{(i)} - \hat y^{(i)})^2}{\frac{1}{m}\sum^{m}_{i=1}(\bar y - \hat y^{(i)})^2} = 1-\frac{MSE}{VAR} R2:=1−∑i=1m(yˉ−y^(i))2∑i=1m(y(i)−y^(i))2=1−m1∑i=1m(yˉ−y^(i))2m1∑i=1m(y(i)−y^(i))2=1−VARMSE
我们可以把 R 2 R^2 R2理解为,回归模型可以成功解释的数据方差部分在数据固有方差中所占的比例, R 2 R^2 R2越接近1,表示可解释力度越大,模型拟合的效果越好
fit_intercept : 默认为True,是否计算该模型的截距。如果使用中心化的数据,可以考虑设置为False,不考虑截距。注意这里是考虑,一般还是要考虑截距
normalize: 默认为false. 当fit_intercept设置为false的时候,这个参数会被自动忽略。如果为True,回归器会标准化输入参数:减去平均值,并且除以相应的二范数。当然啦,在这里还是建议将标准化的工作放在训练模型之前。通过设置sklearn.preprocessing.StandardScaler来实现,而在此处设置为false
copy_X : 默认为True, 否则X会被改写
n_jobs: int 默认为1. 当-1时默认使用全部CPUs ??(这个参数有待尝试)
可用属性:
coef_:训练后的输入端模型系数,如果label有两个,即y值有两列。那么是一个2D的array
intercept_: 截距
可用的methods:
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
get_params(deep=True): 返回对regressor 的设置值
predict(X): 预测 基于 R^2值
score: 评估
参考https://blog.csdn.net/weixin_39175124/article/details/79465558
生成数据
#生成数据
import numpy as np
#生成随机数
np.random.seed(1234)
x = np.random.rand(500,3)
#构建映射关系,模拟真实的数据待预测值,映射关系为y = 4.2 + 5.7*x1 + 10.8*x2,可自行设置值进行尝试
y = x.dot(np.array([4.2,5.7,10.8]))
1、先尝试调用sklearn的线性回归模型训练数据
import numpy as np
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
%matplotlib inline
# 调用模型
lr = LinearRegression(fit_intercept=True)
# 训练模型
lr.fit(x,y)
print("估计的参数值为:%s" %(lr.coef_))
# 计算R平方
print('R2:%s' %(lr.score(x,y)))
# 任意设定变量,预测目标值
x_test = np.array([2,4,5]).reshape(1,-1)
y_hat = lr.predict(x_test)
print("预测值为: %s" %(y_hat))
估计的参数值为:[ 4.2 5.7 10.8]
R2:1.0
预测值为: [85.2]
2、最小二乘法的矩阵求解
classclass LR_LSLR_LS():():
defdef __init____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([2,4,5]).reshape(1,-1)
print("预测值为: %s" %(lr_ls.predict(x_test)))
估计的参数值:[ 4.2 5.7 10.8]
预测值为: [85.2]
3、梯度下降法
class LR_GD():
def __init__(self):
self.w = None
def fit(self,X,y,alpha=0.02,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([2,4,5]).reshape(1,-1)
print("预测值为:%s" %(lr_gd.predict(x_test)))
估计的参数值为:[ 4.20000001 5.70000003 10.79999997]
预测值为:[85.19999995]
参考
吴恩达 CS229课程
周志华 《机器学习》
李航 《统计学习方法》
https://hangzhou.anjuke.com/
https://www.jianshu.com/p/e0eb4f4ccf3e
https://blog.csdn.net/qq_28448117/article/details/79199835
https://blog.csdn.net/weixin_39175124/article/details/79465558