机器学习Linear Regression Experiment 线性回归实验 + Python代码实现

Posted WSKH0929

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器学习Linear Regression Experiment 线性回归实验 + Python代码实现相关的知识,希望对你有一定的参考价值。

文章目录


一、实验目标分析

1.1 主要实验内容

  • 线性回归方程实现
  • 梯度下降效果
  • 对比不同稀度下降策略
  • 建模曲线分析
  • 过拟合与欠拟合
  • 正则化的作用
  • 提前停止策略

1.2 回归方程复习

1.3 构造数据集

# 构造数据集
import numpy as np

X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)

plt.plot(X,y,'bo')
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.grid()
plt.show()

二、参数直接求解方法

2.1 在数据集加上全为1的一列(偏置项)

X_b = np.c_[np.ones((100, 1)), X]
print("X_b的前5行:")
print(X_b[:5])

输出:

X_b的前5:
[[1.         1.21866627]
 [1.         1.80912597]
 [1.         1.31236251]
 [1.         1.35874701]
 [1.         0.45948979]]

2.2 根据公式求最佳theta值

θ ^ = ( X T ⋅ X ) − 1 ⋅ X T ⋅ y \\hat\\theta=\\left(\\mathbfX^T \\cdot \\mathbfX\\right)^-1 \\cdot \\mathbfX^T \\cdot \\mathbfy θ^=(XTX)1XTy

theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)
print("theta_best:")
print(theta_best)

输出:

theta_best:
[[3.9671428 ]
 [3.03417029]]

2.3 可视化回归线

# 两点确定一条直线
X_new =np.array([[0],[2]])
X_new_b =np.c_[np.ones((2,1)),X_new]
y_predict =X_new_b.dot(theta_best)
print("y_predict:\\n",y_predict)

输出:

y_predict:
 [[ 3.9671428 ]
 [10.03548338]]

可视化代码:

plt.plot (X_new,y_predict,'r--')
plt.plot (X,y,'b.')
plt.axis([0,2,0,15])
plt.grid()
plt.show

2.4 sklearn实现线性回归

from sklearn.linear_model import LinearRegression

lin_reg = LinearRegression()
lin_reg.fit(X, y)
print(lin_reg.coef_)
print(lin_reg.intercept_)

输出(可以看到,和 2.2 节的 theta_best 相同,说明sklearn内部也是用了参数直接求解的方法):

[[3.03417029]]
[3.9671428]

三、常用预处理方法

3.1 归一化

把数据变成(0,1)或者(1,1)之间的小数。主要是为了数据处理方便提出来的,把数据映射到0~1范围之内处理,更加便捷快速。2)把有量纲表达式变成无量纲表达式,便于不同单位或量级的指标能够进行比较和加权。归一化是一种简化计算的方式,即将有量纲的表达式,经过变换,化为无量纲的表达式,成为纯量。

3.2 标准化

在机器学习中,我们可能要处理不同种类的资料,例如,音讯和图片上的像素值,这些资料可能是高维度的,资料标准化后会使每个特征中的数值平均变为0(将每个特征的值都减掉原始资料中该特征的平均)、标准差变为1,这个方法被广泛的使用在许多机器学习算法中(例如:支持向量机、逻辑回归和类神经网络)。

3.3 中心化

平均值为0,对标准差无要求

3.4 预处理方法小结

归一化和标准化的区别:归一化是将样本的特征值转换到同一量纲下把数据映射到[0,1]或者[-1, 1]区间内,仅由变量的极值决定,因区间放缩法是归一化的一种。标准化是依照特征矩阵的列处理数据,其通过求z-score的方法,转换为标准正态分布,和整体样本分布相关,每个样本点都能对标准化产生影响。它们的相同点在于都能取消由于量纲不同引起的误差;都是一种线性变换,都是对向量X按照比例压缩再进行平移。

标准化和中心化的区别:标准化是原始分数减去平均数然后除以标准差,中心化是原始分数减去平均数。 所以一般流程为先中心化再标准化。

四、梯度下降模块

  • 找到一个初始位置
  • 以一定步长,沿着当前位置的最大梯度方向移动


∂ ∂ θ j MSE ⁡ ( θ ) = 2 m ∑ i = 1 m ( θ T ⋅ x ( i ) − y ( i ) ) x j ( i ) ∇ θ MSE ⁡ ( θ ) = ( ∂ ∂ θ 0 MSE ⁡ ( θ ) ∂ ∂ θ 1 MSE ⁡ ( θ ) ⋮ ∂ ∂ θ n MSE ⁡ ( θ ) ) = 2 m X T ⋅ ( X ⋅ θ − y ) \\frac\\partial\\partial \\theta_j \\operatornameMSE(\\theta)=\\frac2m \\sum_i=1^m\\left(\\theta^T \\cdot \\mathbfx^(i)-y^(i)\\right) x_j^(i) \\\\ \\nabla_\\theta \\operatornameMSE(\\theta)=\\left(\\beginarrayc \\frac\\partial\\partial \\theta_0 \\operatornameMSE(\\theta) \\\\ \\frac\\partial\\partial \\theta_1 \\operatornameMSE(\\theta) \\\\ \\vdots \\\\ \\frac\\partial\\partial \\theta_n \\operatornameMSE(\\theta) \\endarray\\right)=\\frac2m \\mathbfX^T \\cdot(\\mathbfX \\cdot \\theta-\\mathbfy) θjMSE(θ)=m2i=1m(θTx(i)y(i))xj(i)θMSE(θ)= θ0MSE(θ)θ1MSE(θ)θnMSE(θ) =m2XT(Xθy)

# 步长
step = 0.1
# 迭代次数
n_iterations = 1000
# 数据长度
m = 100
# 初始值
theta = np.random.randn(2, 1)
# 开始梯度下降
for iteration in range(n_iterations):
    # 计算梯度
    gradients = 2 / m * X_b.T.dot(X_b.dot(theta) - y)
    # 朝着梯度方向下降
    theta = theta - step * gradients
# 输出最后的值
print(theta)

输出(和之前计算的一样):

[[3.9671428 ]
 [3.03417029]]

4.1 全批量梯度下降

theta_path_bgd = []


def plot_gradient_descent(theta, eta, theta_path=None):
    m = len(X_b)
    plt.plot(X, y, 'b.')
    n_iterations = 1000
    for iteration in range(n_iterations):
        y_predict = X_new_b.dot(theta)
        plt.plot(X_new,y_predict,'b-')
        gradients = 2 / m * X_b.T.dot(X_b.dot(theta) - y)
        theta = theta - eta * gradients
        if theta_path is not None:
            theta_path.append(theta)
    plt.xlabel('X_1')
    plt.axis([0, 2, 0, 15])
    plt.title('eta ='.format(eta))

theta = np.random.randn(2, 1)

plt.figure(figsize=(10, 4))
plt.subplot(131)
plot_gradient_descent(theta, eta=0.02)
plt.subplot(132)
plot_gradient_descent(theta, eta=0.1, theta_path=theta_path_bgd)
plt.subplot(133)
plot_gradient_descent(theta, eta=0.5)
plt.show()

结论:从上图我们可以看出,当步长较小时,需要迭代较多次才可以收敛。当步长较大时,会导致在最优解附近来回摆动的情况出现。

4.2 随机梯度下降

theta_path_sgd = []
m = len(X_b)
n_epochs = 50
t0 = 5
t1 = 50


# 学习率衰减函数
def learning_schedule(t):
    return t0 / (t1 + t)


# 初始值
theta = np.random.randn(2, 1)

# 开始随机梯度下降
for epoch in range(n_epochs):
    for i in range(m):
        if epoch == 0 and i < 20:
            y_predict = X_new_b.dot(theta)
            plt.plot(X_new, y_predict, 'r-')
        # 随机选取一个样本进行梯度计算
        random_index = np.random.randint(m)
        xi = X_b[random_index:random_index + 1]
        yi = y[random_index:random_index + 1]
        # 计算梯度
        gradients = 2 * xi.T.dot(xi.dot(theta) - yi)
        # 根据梯度和步长更新theta值
        theta = theta - eta * gradients
        theta_path_sgd.append(theta)
        # 更新步长
        eta = learning_schedule(epoch * m + i)

# 画图
plt.plot(X, y, 'b.')
plt.axis([0, 2, 0, 15])
plt.show()

4.3 MiniBatch小批量随机梯度下降

theta_path_mgd = []
n_epochs = 200
minibatch = 16
theta = np.random.randn(2, 1)
t = 0
for epoch in range(n_epochs):
    shuffled_indices = np.random.permutation(m)
    X_b_shuffled = X_b[shuffled_indices]
    y_shuffled = y[shuffled_indices]
    for i in range(0, m, minibatch):
        t += 1
        xi = X_b_shuffled[i:i + minibatch]
        yi = y_shuffled[i:i + minibatch]
        gradients = 2 / minibatch * xi.T.dot(xi.dot(theta) - yi)
        eta = learning_schedule(t)
        theta = theta - eta * gradients
        theta_path_mgd.append(theta)
        
print(theta)

输出:

[[3.96882408]
 [3.03249021]]

4.4 不同梯度下降策略对比

theta_path_bgd = np.array(theta_path_bgd)
theta_path_sgd = np.array(theta_path_sgd)
theta_path_mgd = np.array(theta_path_mgd)

plt.figure

以上是关于机器学习Linear Regression Experiment 线性回归实验 + Python代码实现的主要内容,如果未能解决你的问题,请参考以下文章

机器学习七--回归--多元线性回归Multiple Linear Regression

机器学习 1 linear regression 作业

机器学习1 线性回归(Linear Regression)

机器学习方法:回归:线性回归Linear regression

机器学习 1 linear regression 作业

机器学习 sklearn 监督学习 回归算法 线性回归 Linear Regression