基于Python的机器学习系列(3):随机梯度下降与小批量梯度下降

        在前几篇文章中,我们已经探讨了批量梯度下降的基本概念及其应用。然而,尽管批量梯度下降在理论上是完美的,但它在实际应用中可能会遇到计算效率的问题,特别是当数据集非常大时。为了解决这一问题,我们可以采用随机梯度下降和小批量梯度下降的方法,这些方法不仅加快了训练速度,还能够帮助模型跳出局部最优解。

随机梯度下降

        回顾一下批量梯度下降公式:

        θ_j := θ_j - α * Σ(hθ(x(i)) - y(i)) * x_j(i)  for every j

        虽然批量梯度下降是通过使用所有样本来估计梯度的,但在实际应用中,这样的计算可能会非常缓慢。因此,我们可以只使用一个训练样本来更新模型参数,这就是随机梯度下降的基本思想。

        在随机梯度下降中,我们可以有两种采样方式:有放回和无放回。

  • 无放回:意味着在同一轮次中,任何样本都不会重复使用。
  • 有放回:指在同一轮次中,某些样本可能会重复出现。

        其中,轮次(epoch)表示训练集被完整遍历一次。在无放回的情况下,我们从第一个样本开始,遍历到第m个样本,在每次遍历中,仅使用一个样本来更新权重:

        ∂J/∂θ_j = (hθ(x(i)) - y(i)) * x_j
        θ_j := θ_j - α * (hθ(x(i)) - y(i)) * x_j(i)

小批量梯度下降

        由于随机梯度下降在某些情况下可能不够稳定,因此引入了小批量梯度下降(Mini-Batch Gradient Descent)。该方法通过使用一部分样本来计算损失和梯度,从而在批量梯度下降和随机梯度下降之间取得平衡。小批量梯度下降在深度学习中被广泛使用。

        ∂J/∂θ_j = Σ(hθ(x(i)) - y(i)) * x_j for every j in the batch
        θ_j := θ_j - α * Σ(hθ(x(i)) - y(i)) * x_j(i)

        同样地,我们可以选择有放回或无放回的方式。在无放回的情况下,我们将训练集平均分成若干批次,并在一个轮次内用尽所有训练样本。

多项式回归

        线性回归的局限性在于当数据呈现非线性关系时,模型无法很好地拟合数据。在这种情况下,我们可以使用多项式回归,通过多项式变换对特征进行工程化处理。例如,一级多项式回归(直线)可以表示为:

y = ax + b

而三次多项式回归则拟合一个三次曲线:

y = ax^3 + bx^2 + cx + d

代码实现

        在实现过程中,我们将演示如何使用MLFlow进行实验跟踪,这是一个广受欢迎的工具,能够帮助我们记录和管理机器学习实验。以下是代码的关键步骤和注意事项。

        首先,在终端运行以下命令以启动MLFlow服务:

docker compose up

        这将会构建一个MLFlow服务,你可以通过http://localhost:5000进行访问。

        接下来,我们将使用Python代码来演示随机梯度下降和小批量梯度下降的实际应用。

import numpy as np
from sklearn.datasets import load_diabetes
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from time import time
import mlflow
import os

# 加载糖尿病数据集
diabetes = load_diabetes()
X = diabetes.data
y = diabetes.target

# 进行训练集和测试集的划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3)

# 标准化处理
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test  = scaler.transform(X_test)

# 添加截距项
intercept = np.ones((X_train.shape[0], 1))
X_train = np.concatenate((intercept, X_train), axis=1)
intercept = np.ones((X_test.shape[0], 1))
X_test = np.concatenate((intercept, X_test), axis=1)

# 实现线性回归的类
class LinearRegression:
    def __init__(self, lr=0.001, num_epochs=500, batch_size=50, method='batch'):
        self.lr = lr
        self.num_epochs = num_epochs
        self.batch_size = batch_size
        self.method = method

    def mse(self, ytrue, ypred):
        return ((ypred - ytrue) ** 2).sum() / ytrue.shape[0]
    
    def fit(self, X_train, y_train):
        self.theta = np.zeros(X_train.shape[1])
        for epoch in range(self.num_epochs):
            if self.method == 'sto':
                for i in range(X_train.shape[0]):
                    self._train(X_train[i].reshape(1, -1), y_train[i])
            elif self.method == 'mini':
                for i in range(0, X_train.shape[0], self.batch_size):
                    X_batch = X_train[i:i+self.batch_size, :]
                    y_batch = y_train[i:i+self.batch_size]
                    self._train(X_batch, y_batch)
            else:
                self._train(X_train, y_train)
    
    def _train(self, X, y):
        yhat = self.predict(X)
        grad = X.T @ (yhat - y) / X.shape[0]
        self.theta = self.theta - self.lr * grad
    
    def predict(self, X):
        return X @ self.theta
    
    def coef(self):
        return self.theta[1:]
    
    def intercept(self):
        return self.theta[0]

实验

        我们接下来将展示批量梯度下降和小批量梯度下降的实验过程。

# 批量梯度下降
model = LinearRegression(method='batch', lr=0.1)
model.fit(X_train, y_train)
yhat = model.predict(X_test)
mse = model.mse(y_test, yhat)
print("Test MSE: ", mse)

# 小批量梯度下降
model = LinearRegression(method='mini', lr=0.1)
model.fit(X_train, y_train)
yhat = model.predict(X_test)
mse = model.mse(y_test, yhat)
print("Test MSE: ", mse)

结语

       

        随机梯度下降和小批量梯度下降是机器学习模型优化中的核心方法。它们通过不同的方式在性能和效率之间取得平衡,尤其是在处理大型数据集时,显得尤为重要。随机梯度下降虽然速度快,但在更新时可能会引入噪声;而小批量梯度下降则通过结合了批量和随机的优势,提供了更为稳定的更新过程,成为深度学习中的标准选择。

        在实际应用中,理解这些优化算法的工作原理以及如何选择合适的学习率和批量大小,能够帮助我们更好地训练模型并提高其预测准确性。这不仅仅是为了应对大规模数据,还为我们提供了在模型训练中的灵活性和适应性。

        敬请期待下一篇博文:基于Python的机器学习系列(4):正则化。

如果你觉得这篇博文对你有帮助,请点赞、收藏、关注我,并且可以打赏支持我!

欢迎关注我的后续博文,我将分享更多关于人工智能、自然语言处理和计算机视觉的精彩内容。

谢谢大家的支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会飞的Anthony

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值