【机器学习03】线性回归(回归篇)

【机器学习03】线性回归(回归篇),第1张

3 线性回归(回归篇) 3.1 形式化定义
  1. 假设函数(hypotheses function)

    h θ ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 + . . . + θ n x n = ∑ i = 0 n θ i x i = θ T x h_\theta(x)=\theta_0+\theta_1x_1+\theta_2x_2+...+\theta_nx_n=\sum\limits_{i = 0}^n{{\theta_i}{x_i}}={\theta^T}x hθ(x)=θ0+θ1x1+θ2x2+...+θnxn=i=0nθixi=θTx

    其中, θ 0 {\theta_0} θ0是偏置项, x 0 = 1 x_0=1 x0=1 θ \theta θ x x x都是列向量

  2. 损失函数(loss function):计算一个样本的误差

    L ( θ ) = ( h θ ( x ) − y ) 2 L(\theta)=(h_\theta(x)-y)^2 L(θ)=(hθ(x)y)2

  3. 代价函数(cost function):计算整个训练集上所有样本误差和的平均

    J ( θ ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 = ∑ i = 1 m 1 2 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J(\theta)=\frac{1}{2m}\sum\limits_{i=1}^m(h_\theta(x^{(i)})-y^{(i)})^2=\sum\limits_{i=1}^m\frac{1}{2m}(h_\theta(x^{(i)})-y^{(i)})^2 J(θ)=2m1i=1m(hθ(x(i))y(i))2=i=1m2m1(hθ(x(i))y(i))2

# 输入       输出
  0.5	  	 5.0
  0.6	  	 5.5
  0.8	  	 6.0
  1.1	  	 6.8
  1.4	  	 7.0
  ...  

预测函数:hθ(x) = θ01x

x:已知输入

y:已知输出

hθ(x) :预测输出

θ0和θ1:模型参数

模型训练:根据已知的x和y,找到最佳的模型参数θ0和θ1,尽可能精确地描述出输入和输出的关系

5.0 = θ01 x 0.5

5.5 = θ01 x 0.6

单样本误差:

根据预测函数求出输入为x时的预测值为hθ(x)= θ01x,单样本误差: ( h θ ( x ) − y ) 2 (h_\theta(x)-y)^2 (hθ(x)y)2

总样本误差:

所有单样本误差相加的平均即是总样本误差: 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 \frac{1}{2m}\sum\limits_{i=1}^m(h_\theta(x^{(i)})-y^{(i)})^2 2m1i=1m(hθ(x(i))y(i))2

代价函数:

J ( θ ) = 1 2 m ∑ i = 1 m ( θ 0 + θ 1 x ( i ) − y ( i ) ) 2 J(\theta) = \frac{1}{2m}{\sum\limits_{i=1}^m {\left( {{\theta_0}+{\theta_1}x^{(i)}- y^{(i)}} \right)} ^2} J(θ)=2m1i=1m(θ0+θ1x(i)y(i))2

代价函数就是总样本误差关于模型参数的函数,该函数属于三维数学模型,即需要找到一组θ0和θ1使得 J ( t h e t a ) J(theta) J(theta)取极小值

3.2 梯度下降法(GD)

(批量)梯度下降法(GD):以负梯度方向求解代价函数的全局最小值的一种局部优化迭代方法

梯度就是表示函数在当前位置的偏导数,梯度下降公式记为:

θ = θ − α ∇ J ( θ ) \theta=\theta-\alpha \nabla J(\theta) θ=θαJ(θ)

其中,随机初始化 θ \theta θ θ \theta θ是自变量参数,即下降位置坐标; α \alpha α是学习率,即下降每次前进的一小步(步长参数); ∇ J ( θ ) = α J ( θ ) α θ \nabla J(\theta)={\frac{\alpha J(\theta)}{\alpha \theta}} J(θ)=αθαJ(θ)表示梯度,即 J ( θ ) J(\theta) J(θ) θ \theta θ处的偏导数

线性回归代价函数之梯度求解:

α J ( θ ) α θ j = ∑ i = 1 m 1 2 m ∗ 2 ( h θ ( x ( i ) ) − y ( i ) ) α α θ j ( h θ ( x ( i ) ) − y ( i ) ) \frac{\alpha J(\theta)}{\alpha \theta_j}={\sum\limits_{i=1}^m\frac{1}{2m}*2(h_\theta(x^{(i)})-y^{(i)})}\frac{\alpha}{\alpha \theta_j}(h_\theta(x^{(i)})-y^{(i)}) αθjαJ(θ)=i=1m2m12(hθ(x(i))y(i))αθjα(hθ(x(i))y(i))

= ∑ i = 1 m 1 m ( h θ ( x ( i ) ) − y ( i ) ) α α θ j ( h θ ( x ( i ) ) − y ( i ) ) ={\sum\limits_{i=1}^m\frac{1}{m}(h_\theta(x^{(i)})-y^{(i)})}\frac{\alpha}{\alpha \theta_j}(h_\theta(x^{(i)})-y^{(i)}) =i=1mm1(hθ(x(i))y(i))αθjα(hθ(x(i))y(i))

= ∑ i = 1 m 1 m ( h θ ( x ( i ) ) − y ( i ) ) α α θ j ( ∑ j = 0 n θ j x j ( i ) − y ( i ) ) ={\sum\limits_{i=1}^m\frac{1}{m}(h_\theta(x^{(i)})-y^{(i)})}\frac{\alpha}{\alpha \theta_j}(\sum\limits_{j = 0}^n{{\theta_j}x_j^{(i)}}-y^{(i)}) =i=1mm1(hθ(x(i))y(i))αθjα(j=0nθjxj(i)y(i))

= ∑ i = 1 m 1 m ( h θ ( x ( i ) ) − y ( i ) ) α α θ j ( θ 0 x 0 ( i ) + θ 1 x 1 ( i ) + . . . + θ j x j ( i ) + . . . + θ n x n ( i ) − y ( i ) ) ={\sum\limits_{i=1}^m\frac{1}{m}(h_\theta(x^{(i)})-y^{(i)})}\frac{\alpha}{\alpha \theta_j}(\theta_0x_0^{(i)}+\theta_1x_1^{(i)}+...+\theta_jx_j^{(i)}+...+\theta_nx_n^{(i)}-y^{(i)}) =i=1mm1(hθ(x(i))y(i))αθjα(θ0x0(i)+θ1x1(i)+...+θjxj(i)+...+θnxn(i)y(i))

= 1 m ∑ i = 1 m [ ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) ] =\frac{1}{m}{\sum\limits_{i=1}^m[(h_\theta(x^{(i)})-y^{(i)})}x_j^{(i)}] =m1i=1m[(hθ(x(i))y(i))xj(i)]

梯度下降迭代公式——>更新模型参数θj

θ j = θ j − α α J ( θ ) α θ j = θ j − α 1 m ∑ i = 1 m [ ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) ] \theta_j=\theta_j-\alpha\frac{\alpha J(\theta)}{\alpha \theta_j}=\theta_j-\alpha \frac{1}{m}{\sum\limits_{i=1}^m[(h_\theta(x^{(i)})-y^{(i)})}x_j^{(i)}] θj=θjααθjαJ(θ)=θjαm1i=1m[(hθ(x(i))y(i))xj(i)]

其中, h θ ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 + . . . + θ n x n = ∑ i = 0 n θ i x i = θ T x , x 0 ( i ) = 1 h_\theta(x)=\theta_0+\theta_1x_1+\theta_2x_2+...+\theta_nx_n=\sum\limits_{i = 0}^n{{\theta_i}{x_i}}={\theta^T}x,x_0^{(i)}=1 hθ(x)=θ0+θ1x1+θ2x2+...+θnxn=i=0nθixi=θTxx0(i)=1

案例:整理训练集数据,基于梯度下降法规则,求出θ0和θ1,绘制回归线与代价函数的变化过程

import numpy as np
import matplotlib.pyplot as plt

# 加载数据:读文本
def loaddata():
    # x,y=np.loadtxt("data/single.txt",delimiter=",",unpack=True)
    data=np.loadtxt("data/single.txt",delimiter=",")
    cols=data.shape[1]    # data.shape[1]:列数
    # 取训练数据(特征值)X
    x=data[:,0:cols-1] 
    # 取标签(列向量)y
    y=data[:,-1].reshape(-1,1)          # data[:,-1]:获取所有行的最后一列
    return x,y

# 特征标准化
def featureNormalize(x):
    mean=np.mean(x)
    std=np.std(x)
    X=(x-mean)/std
    return X,mean,std

# 计算代价函数
def computeCost(X,y,theta):
    m=X.shape[0]
    cost=np.sum(np.power(np.dot(X,theta)-y,2))/(2*m)
    return cost

# 梯度下降法求解theta模型参数
def BGD(X,y,theta,max_iter,alpha):
    one=np.ones(X.shape[0])
    X=np.insert(X,0,values=one,axis=1)    # 在X最前面插入一个全1的列(偏置)
    m,n=X.shape
    costs=np.zeros(max_iter)
    # 循环
    for num in range(max_iter):
        for j in range(n):
            # 梯度下降迭代公式
            # theta:列向量
            theta[j]=theta[j]-(alpha/m)*(np.sum((np.dot(X,theta)-y)*X[:,j].reshape(-1,1)))
        # 计算代价
        costs[num]=computeCost(X,y,theta)
    return theta,costs

# 预测数据
def predict(x):
    X=(x-mean)/std
    one=np.ones(X.shape[0])
    X=np.insert(X,0,values=one,axis=1)    # x中加入一个全为1的列
    h=np.dot(X,theta)
    return h

# 加载数据
x,y=loaddata()
# 特征标准化
X,mean,std=featureNormalize(x)
# print(X.shape,y.shape)
# 初始化theta值,一维数组的形状:特征数(列数)+1列theta[0]
theta=np.ones(X.shape[1]+1).reshape(-1,1)
print(theta)
alpha=0.01
max_iter=400
theta,costs=BGD(X,y,theta,max_iter,alpha)
print(theta)

# 通过梯度下降寻找的最佳模型参数theta[0]与theta[1]来绘制回归线
# 训练
line_y=theta[0]+theta[1]*X

# 画图
plt.figure(figsize=(12,6))
plt.subplot(1,2,1)
plt.title("Linear Regression",fontsize=18)
plt.grid(linestyle=":")
# 训练数据散点
plt.scatter(X,y,s=80,marker="o",color="dodgerblue",label="Train Samples")
# 回归线
plt.plot(X,line_y,color="orangered",linewidth=2,label="Regression Line")
plt.xlabel("X")
plt.ylabel("y")

plt.subplot(1,2,2)
plt.title("Cost function")
x_axis=np.linspace(1,max_iter,max_iter)
plt.plot(x_axis,costs[0:max_iter],label="Cost Line")
plt.xlabel("iter")
plt.ylabel("Cost")

plt.legend()
# 紧凑布局
plt.tight_layout()
plt.show()

# 预测
predict([[8.4084]])
pred_y=predict(x)

3.3 随机梯度下降法(SGD)

随机梯度下降迭代公式——>更新模型参数θj

θ j = θ j − α α J ( θ ) α θ j = θ j − α ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) \theta_j=\theta_j-\alpha\frac{\alpha J(\theta)}{\alpha \theta_j}=\theta_j-\alpha(h_\theta(x^{(i)})-y^{(i)})x_j^{(i)} θj=θjααθjαJ(θ)=θjα(hθ(x(i))y(i))xj(i)

其中, h θ ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 + . . . + θ n x n = ∑ i = 0 n θ i x i = θ T x , x 0 ( i ) = 1 h_\theta(x)=\theta_0+\theta_1x_1+\theta_2x_2+...+\theta_nx_n=\sum\limits_{i = 0}^n{{\theta_i}{x_i}}={\theta^T}x,x_0^{(i)}=1 hθ(x)=θ0+θ1x1+θ2x2+...+θnxn=i=0nθixi=θTxx0(i)=1

3.4 小批量梯度下降法(MBGD)

每次使用batch_size个样本进行更新

小批量梯度下降迭代公式——>更新模型参数θj

θ j = θ j − α α J ( θ ) α θ j = θ j − α 1 b a t c h − m ∑ i = 1 b a t c h − m [ ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) ] \theta_j=\theta_j-\alpha\frac{\alpha J(\theta)}{\alpha \theta_j}=\theta_j-\alpha \frac{1}{batch-m}{\sum\limits_{i=1}^{batch-m}[(h_\theta(x^{(i)})-y^{(i)})}x_j^{(i)}] θj=θjααθjαJ(θ)=θjαbatchm1i=1batchm[(hθ(x(i))y(i))xj(i)]

其中, h θ ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 + . . . + θ n x n = ∑ i = 0 n θ i x i = θ T x , x 0 ( i ) = 1 h_\theta(x)=\theta_0+\theta_1x_1+\theta_2x_2+...+\theta_nx_n=\sum\limits_{i = 0}^n{{\theta_i}{x_i}}={\theta^T}x,x_0^{(i)}=1 hθ(x)=θ0+θ1x1+θ2x2+...+θnxn=i=0nθixi=θTxx0(i)=1

3.5 Sklearn之线性回归

线性回归相关API:

# sklearn库
import sklearn.linear_model as lm

# 创建模型(最小二乘法)
model=lm.LinearRegression()
# 训练模型
# 输入:一个二维数组表示的样本矩阵
# 输出:每个样本最终的结果
model.fit(输入,输出) # 通过梯度下降法计算模型参数
# 预测输出
# 输入array是一个二维数组,每一行是一个样本,每一列是一个特征
result=model.predict(array)

案例:基于线性回归训练abnormal.txt中的训练样本,使用模型预测测试样本

import numpy as np
import matplotlib.pyplot as plt
import sklearn.linear_model as lm

# 加载数据:读文本
def loaddata():
    # x,y=np.loadtxt("data/abnormal.txt",delimiter=",",unpack=True)
    data=np.loadtxt("data/abnormal.txt",delimiter=",")
    cols=data.shape[1]    # data.shape[1]:列数
    x=data[:,0:cols-1] 
    y=data[:,-1].reshape(-1,1)          # data[:,-1]:获取所有行的最后一列
    return x,y

x,y=loaddata()

## 线性回归(最小二乘法)
model=lm.LinearRegression()  # 模型构建
model.fit(x,y)  # 模型训练 
print("系数:",model.coef_)
print("截距:",model.intercept_)
pred_y=model.predict(x)     # 模型预测
plt.title("Linear Regression")
plt.scatter(x,y)
plt.plot(x,pred_y)
3.6 模型评估(回归)

线性回归模型训练完毕后,可以利用测试集评估训练结果误差

最普遍的回归模型评价指标:MAE、MSE与RMSE

  • MAE(平均绝对值误差)

    M A E = 1 m ∑ i = 1 m ∣ h ( x i ) − y i ∣ MAE{\rm{ = }}\frac{1}{m}\sum\limits_{i = 1}^m {\left| {h\left( {{x_i}} \right) - {y_i}} \right|} MAE=m1i=1mh(xi)yi

  • MSE(均方误差)

    M S E = 1 m ∑ i = 1 m ( h ( x i ) − y i ) 2 MSE = {\frac{1}{m}\sum\limits_{i = 1}^m {{{\left( {h\left( {{x_i}} \right) - {y_i}} \right)}^2}} } MSE=m1i=1m(h(xi)yi)2

  • RMSE(均方根误差)

    R M S E = 1 m ∑ i = 1 m ( h ( x i ) − y i ) 2 RMSE = \sqrt {\frac{1}{m}\sum\limits_{i = 1}^m {{{\left( {h\left( {{x_i}} \right) - {y_i}} \right)}^2}} } RMSE=m1i=1m(h(xi)yi)2

sklearn.metrics提供了计算模型误差的几个常用算法:

# sklearn库
import sklearn.metrics as sm
import numpy as np

# MAE(平均绝对值误差):1/mΣ|实际输出-预测输出|
sm.mean_absolute_error(y,pred_y)
# MSE(均方误差):1/mΣ(实际输出-预测输出)^2
sm.mean_squared_error(y,pred_y)
# RMSE(均方根误差):SQRT(1/mΣ(实际输出-预测输出)^2)
np.sqrt(sm.mean_squared_error(y,pred_y))
# 中位绝对值误差:MEDIAN(|实际输出-预测输出|)
sm.median_absolute_error(y,pred_y)
# R2_score(R方值):(0,1]区间的分值,即分数越高,误差越小
sm.r2_score(y,pred_y)

案例:在上一个案例中使用sklearn.metrics评估模型误差

## 模型评估
# MAE(平均绝对值误差):1/mΣ|实际输出-预测输出|
def MAE(y,pred_y):
    mae=np.sum(np.abs(y-pred_y))/len(y)
    return mae

# MSE(均方误差):1/mΣ(实际输出-预测输出)^2
def MSE(y,pred_y):
    mse=np.sum(np.power(y-pred_y,2))/len(y)
    return mse

# RMSE(均方根误差):SQRT(1/mΣ(实际输出-预测输出)^2)
def RMSE(y,pred_y):
    rmse=np.sqrt(np.sum(np.power(y-pred_y,2))/len(y))
    return rmse

print("MAE(平均绝对值误差):",MAE(y,pred_y))
print("MSE(均方误差):",MSE(y,pred_y))
print("RMSE(均方根误差):",RMSE(y,pred_y))
print("\n")

# sklearn库
import sklearn.metrics as sm
import numpy as np

# MAE(平均绝对值误差):1/mΣ|实际输出-预测输出|
print("MAE(平均绝对值误差):",sm.mean_absolute_error(y,pred_y))
# MSE(均方误差):1/mΣ(实际输出-预测输出)^2
print("MSE(均方误差):",sm.mean_squared_error(y,pred_y))
# RMSE(均方根误差):SQRT(1/mΣ(实际输出-预测输出)^2)
print("RMSE(均方根误差):",np.sqrt(sm.mean_squared_error(y,pred_y)))
# 中位绝对值误差:MEDIAN(|实际输出-预测输出|)
print("中位绝对值误差:",sm.median_absolute_error(y,pred_y))
# R2_score(R方值):(0,1]区间的分值,即分数越高,误差越小
print("R2_score(R方值):",sm.r2_score(y,pred_y))
3.7 欠拟合与过拟合

欠拟合:过于简单的模型,无论对于训练数据还是测试数据都无法给出足够高的预测精度

过拟合:过于复杂的模型,对于训练数据可以得到较高的预测精度,但对于测试数据通常精度较低,即泛化能力弱

一个性能可以接受的学习模型应该对训练数据和测试数据都有接近的预测精度,而且精度不能太低

# 训练集R2_score(R方值)   测试集R2_score(R方值)
         0.3                   0.4          # 欠拟合:过于简单,无法反映数据的规则
         0.9                   0.2          # 过拟合:过于复杂,太特殊,缺乏一般性,泛化能力弱
         0.7                   0.6          # 可接受:复杂度适中,既反映数据的规则,又不缺失一般性
3.8 模型保存与加载

模型训练是一个耗时的过程,一个优秀的机器学习模型是非常宝贵的

可以将模型保存到磁盘中,也可以在需要使用的时候从磁盘中重新加载模型即可,不需要重新训练,与训练好的模型具有相同的参数

模型保存与加载相关API:

# pickle库:持久化(保存)对象
# pickle模块利用二进制对Python对象进行了序列化或反序列化
import pickle

pickle.dump(模型对象,磁盘文件)     # 保存模型
model=pickle.load(磁盘文件)       # 加载模型

案例:将训练好的模型保存到磁盘中

# pickle库:持久化(保存)对象
import pickle

# 将训练好的模型对象保存到磁盘文件中
with open("model/linear.pkl","wb") as f:   # 二进制写方式打开文件
    pickle.dump(model,f)
    print("dump success!")
    
# 从磁盘文件中加载模型对象(与训练好的模型具有相同的参数)
with open("model/linear.pkl","rb") as f:   # 二进制读方式打开文件
    model=pickle.load(f)
    print("load success!")
    
# 根据输入预测输出
pred_y=model.predcit(x)

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/langs/798350.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存