SGD优化算法——提升机器学习模型性能的必备利器

一、什么是SGD优化算法

SGD(Stochastic Gradient Descent)优化算法是机器学习中常用的优化方法,它是一种迭代式的优化方法,用于寻找损失函数的最小值。相较于传统的梯度下降算法,SGD每次随机选择一个样本进行迭代,因此可以避免一些复杂的计算量。常见的SGD算法包括Mini-Batch SGD和普通SGD。

SGD算法的核心思想是通过不断的迭代寻找当损失函数的梯度为0时的参数取值,从而实现对模型的优化。在训练过程中,SGD每次选取一个样本计算梯度,并根据梯度的方向以一定的步长调节参数,以期逐步降低损失函数的值,直到达到预定的收敛精度。

二、SGD优化算法的优点

相较于传统的梯度下降算法,SGD算法具有以下优点:

1、节省内存:每次只需要处理一个样本,可以节省大量的内存空间;

2、处理高维数据效果好:当数据维度比较高时,SGD算法具有更好的效果;

3、收敛速度快:由于每次迭代只处理一个样本,因此收敛的速度很快。

三、SGD优化算法在机器学习中的应用

SGD优化算法被广泛应用在机器学习领域,特别是在深度学习中。以下是一些常见的机器学习模型中使用SGD算法优化的例子:

1、线性回归模型中的SGD优化器;

class LinearRegression:
    def __init__(self, lr=0.01, num_iter=100000, fit_intercept=True, verbose=False):
        self.lr = lr
        self.num_iter = num_iter
        self.fit_intercept = fit_intercept
        self.verbose = verbose
        
    def __add_intercept(self, X):
        intercept = np.ones((X.shape[0], 1))
        return np.concatenate((intercept, X), axis=1)
    
    def __loss(self, h, y):
        return (1/2*len(y)) * np.sum((h-y)**2)
    
    def fit(self, X, y):
        if self.fit_intercept:
            X = self.__add_intercept(X)
            
        self.theta = np.zeros(X.shape[1])
        
        for i in range(self.num_iter):
            rand_idx = np.random.randint(0, X.shape[0])
            X_i = X[rand_idx,:]
            y_i = y[rand_idx]
            h = np.dot(X_i, self.theta)
            gradient = X_i.T.dot(h-y_i)
            self.theta -= self.lr * gradient
                
            if self.verbose and i % 10000 == 0:
                h = np.dot(X, self.theta)
                print(f'Iteration {i}, loss = {self.__loss(h, y)}')
    
    def predict(self, X):
        if self.fit_intercept:
            X = self.__add_intercept(X)
            
        return np.dot(X, self.theta)

2、逻辑回归模型中的SGD优化器;

class LogisticRegression:
    def __init__(self, lr=0.01, num_iter=100000, fit_intercept=True, verbose=False):
        self.lr = lr
        self.num_iter = num_iter
        self.fit_intercept = fit_intercept
        self.verbose = verbose
        
    def __add_intercept(self, X):
        intercept = np.ones((X.shape[0], 1))
        return np.concatenate((intercept, X), axis=1)
    
    def __sigmoid(self, z):
        return 1 / (1 + np.exp(-z))
    
    def __loss(self, h, y):
        return (-1/len(y)) * np.sum(y*np.log(h) + (1-y)*np.log(1-h))
    
    def fit(self, X, y):
        if self.fit_intercept:
            X = self.__add_intercept(X)
            
        self.theta = np.zeros(X.shape[1])
        
        for i in range(self.num_iter):
            rand_idx = np.random.randint(0, X.shape[0])
            X_i = X[rand_idx,:]
            y_i = y[rand_idx]
            z = np.dot(X_i, self.theta)
            h = self.__sigmoid(z)
            gradient = X_i.T.dot(h-y_i)
            self.theta -= self.lr * gradient
                
            if self.verbose and i % 10000 == 0:
                z = np.dot(X, self.theta)
                h = self.__sigmoid(z)
                print(f'Iteration {i}, loss = {self.__loss(h, y)}')
    
    def predict_proba(self, X):
        if self.fit_intercept:
            X = self.__add_intercept(X)
            
        return self.__sigmoid(np.dot(X, self.theta))
    
    def predict(self, X, threshold=0.5):
        return self.predict_proba(X) >= threshold

3、神经网络中的SGD优化器。

import numpy as np

def sigmoid(z):
    return 1 / (1 + np.exp(-z))

class NeuralNetwork:
    def __init__(self, lr=0.01, num_iter=100, hidden_size=4, fit_intercept=True, verbose=False):
        self.lr = lr
        self.num_iter = num_iter
        self.fit_intercept = fit_intercept
        self.verbose = verbose
        self.hidden_size = hidden_size
        
    def __add_intercept(self, X):
        intercept = np.ones((X.shape[0], 1))
        return np.concatenate((intercept, X), axis=1)
    
    def __loss(self, y, y_hat):
        return -np.mean(y * np.log(y_hat) + (1-y) * np.log(1-y_hat))
    
    def initialize_parameters(self, X):
        input_size = X.shape[1]
        output_size = 1
        
        self.params = {
            'W1': np.random.randn(input_size, self.hidden_size) * 0.01,
            'b1': np.zeros((1, self.hidden_size)),
            'W2': np.random.randn(self.hidden_size, output_size) * 0.01,
            'b2': np.zeros((1, output_size))
        }
        
    def forward_propagation(self, X):
        Z1 = np.dot(X, self.params['W1']) + self.params['b1']
        A1 = np.tanh(Z1)
        Z2 = np.dot(A1, self.params['W2']) + self.params['b2']
        y_hat = sigmoid(Z2)
        cache = {
            'A1': A1,
            'Z2': Z2,
            'Z1': Z1
        }
        return y_hat, cache
    
    def backward_propagation(self, X, y, y_hat, cache):
        dZ2 = y_hat - y
        dW2 = np.dot(cache['A1'].T, dZ2) / X.shape[0]
        db2 = np.sum(dZ2, axis=0, keepdims=True) / X.shape[0]
        dZ1 = np.dot(dZ2, self.params['W2'].T) * (1 - np.power(cache['A1'], 2))
        dW1 = np.dot(X.T, dZ1) / X.shape[0]
        db1 = np.sum(dZ1, axis=0, keepdims=True) / X.shape[0]
        
        grads = {
            'dW2': dW2,
            'db2': db2,
            'dW1': dW1,
            'db1': db1
        }
        
        return grads
    
    def update_parameters(self, grads):
        self.params['W1'] -= self.lr * grads['dW1']
        self.params['b1'] -= self.lr * grads['db1']
        self.params['W2'] -= self.lr * grads['dW2']
        self.params['b2'] -= self.lr * grads['db2']
        
    def fit(self, X, y):
        if self.fit_intercept:
            X = self.__add_intercept(X)
        
        self.initialize_parameters(X)
        
        for i in range(self.num_iter):
            y_hat, cache = self.forward_propagation(X)
            loss = self.__loss(y, y_hat)
            grads = self.backward_propagation(X, y, y_hat, cache)
            self.update_parameters(grads)
            
            if self.verbose and i % 10 == 0:
                print(f'Iteration {i}, loss = {loss}')
        
    def predict(self, X):
        if self.fit_intercept:
            X = self.__add_intercept(X)
        
        y_hat, _ = self.forward_propagation(X)
        return y_hat

四、如何选择SGD的超参数

SGD算法中的超参数主要有学习率(learning rate)、迭代次数、batch size等等。合适的超参数对于模型性能的提升至关重要,以下是一些常用的选择方法:

1、学习率(learning rate):通常情况下,学习率的选择会根据具体的数据集和模型来定。如果学习率过大,可能导致算法无法收敛;如果学习率过小,则算法的收敛速度会变得非常缓慢。通常情况下,我们可以初次设置学习率等于0.001,然后根据具体实验进行调整;

2、迭代次数:迭代次数应该足够大,以保证算法能够收敛到最优解。同时,迭代次数也不能太大,否则会导致算法耗费大量的时间和资源。一般来说,可以根据实际数据集大小和模型复杂度来确定迭代次数;

3、batch size:batch size通常是一个比较小的数值,但不宜过小或过大。如果batch size过大,将会导致算法内存不足,而过小则会影响模型的优化效果。因此,我们需要根据具体的数据集大小和配置环境确定一个合适的batch size。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/302890.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-31 11:48
下一篇 2024-12-31 11:48

相关推荐

  • TensorFlow Serving Java:实现开发全功能的模型服务

    TensorFlow Serving Java是作为TensorFlow Serving的Java API,可以轻松地将基于TensorFlow模型的服务集成到Java应用程序中。…

    编程 2025-04-29
  • 蝴蝶优化算法Python版

    蝴蝶优化算法是一种基于仿生学的优化算法,模仿自然界中的蝴蝶进行搜索。它可以应用于多个领域的优化问题,包括数学优化、工程问题、机器学习等。本文将从多个方面对蝴蝶优化算法Python版…

    编程 2025-04-29
  • Python实现爬楼梯算法

    本文介绍使用Python实现爬楼梯算法,该算法用于计算一个人爬n级楼梯有多少种不同的方法。 有一楼梯,小明可以一次走一步、两步或三步。请问小明爬上第 n 级楼梯有多少种不同的爬楼梯…

    编程 2025-04-29
  • Python训练模型后如何投入应用

    Python已成为机器学习和深度学习领域中热门的编程语言之一,在训练完模型后如何将其投入应用中,是一个重要问题。本文将从多个方面为大家详细阐述。 一、模型持久化 在应用中使用训练好…

    编程 2025-04-29
  • AES加密解密算法的C语言实现

    AES(Advanced Encryption Standard)是一种对称加密算法,可用于对数据进行加密和解密。在本篇文章中,我们将介绍C语言中如何实现AES算法,并对实现过程进…

    编程 2025-04-29
  • Harris角点检测算法原理与实现

    本文将从多个方面对Harris角点检测算法进行详细的阐述,包括算法原理、实现步骤、代码实现等。 一、Harris角点检测算法原理 Harris角点检测算法是一种经典的计算机视觉算法…

    编程 2025-04-29
  • Python刷课:优化学习体验的利器

    Python刷课作为一种利用自动化技术优化学习体验的工具已经被广泛应用。它可以帮助用户自动登录、自动答题等,让用户在学习过程中可以更加专注于知识本身,提高效率,增加学习乐趣。 一、…

    编程 2025-04-29
  • 数据结构与算法基础青岛大学PPT解析

    本文将从多个方面对数据结构与算法基础青岛大学PPT进行详细的阐述,包括数据类型、集合类型、排序算法、字符串匹配和动态规划等内容。通过对这些内容的解析,读者可以更好地了解数据结构与算…

    编程 2025-04-29
  • lsw2u1:全能编程开发工程师的利器

    lsw2u1是一款多功能工具,可以为全能编程开发工程师提供便利的支持。本文将从多个方面对lsw2u1做详细阐述,并给出对应代码示例。 一、快速存取代码段 在日常开发中,我们总会使用…

    编程 2025-04-29
  • 瘦脸算法 Python 原理与实现

    本文将从多个方面详细阐述瘦脸算法 Python 实现的原理和方法,包括该算法的意义、流程、代码实现、优化等内容。 一、算法意义 随着科技的发展,瘦脸算法已经成为了人们修图中不可缺少…

    编程 2025-04-29

发表回复

登录后才能评论