Python中的并发编程

发布时间: 2024-01-18 01:04:04 阅读量: 44 订阅数: 38
# 1. 引言 ## 1.1 什么是并发编程 并发编程是指在一个程序中同时执行多个独立的任务或操作的编程方式。这些任务可以是完全独立的,也可以是相互依赖的。并发编程的目标是提高程序的性能和效率。 ## 1.2 并发编程的重要性 随着计算机的发展,多核处理器和分布式系统已经成为现代计算的常态。并发编程可以有效地利用这些计算资源,提高程序的响应速度和处理能力。它在许多领域都有广泛的应用,比如网络通信、数据处理、图像处理、游戏开发等。 在Python中,具有良好的并发编程能力可以帮助我们充分发挥多核处理器的优势,实现高效的并行运算。Python提供了多种并发编程的方式,包括多线程编程、多进程编程和协程等。 接下来,我们将深入探讨Python中的并发编程相关知识和技术。 # 2. 基础知识 ### 2.1 并发与并行的区别 在并发编程中,我们经常会提到并发(Concurrency)和并行(Parallelism)这两个概念。虽然它们经常被用来描述同时发生的事情,但实际上它们有着不同的含义。 并发指的是多个任务按照交替执行的方式在同一时间段内执行,这些任务之间可以是互相独立的,也可以通过相互通信来协调和同步。并发的目标是提高系统的响应能力和资源利用率。 而并行则是指多个任务同时进行执行,它们会在不同的处理器上或者是同时使用多核处理器的不同核上执行。并行的目标是加速处理速度。 简单来说,并发是指任务在时间上重叠,而并行是指任务在时间上同时进行。 ### 2.2 线程与进程 在并发编程中,线程和进程是最基本的两个概念。 线程是操作系统能够进行运算调度的最小单位。一个进程内可以有多个线程,这些线程共享同一个进程的地址空间和资源,但每个线程有自己的寄存器和栈。 进程是操作系统进行资源分配和调度的基本单位。每个进程拥有独立的地址空间和系统资源,可以独立运行。 线程与进程的选择取决于具体的应用场景。线程之间的切换开销较小,适合处理密集型计算任务;而进程之间的切换开销较大,适合处理IO密集型任务。 ### 2.3 全局解释器锁 (Global Interpreter Lock, GIL) 的概念与影响 在Python中,由于解释器的限制,存在一个全局解释器锁(GIL)。GIL的作用是确保同一时间只有一个线程能够执行Python的字节码。 GIL的存在对于CPU密集型任务会有一定的影响,因为在同一时间只有一个线程能够执行。但对于IO密集型任务,由于大部分时间都在等待外部IO操作的完成,因此GIL的影响相对较小。 在并发编程中,如果需要充分利用多核处理器,并发执行多个CPU密集型任务,可以利用多进程编程来规避GIL的影响。但对于IO密集型任务,多线程编程可以更好地利用系统资源。 下面是使用Python的`multiprocessing`模块实现多进程并发编程的示例代码: ```python import multiprocessing def task(): # 执行任务的代码 pass if __name__ == '__main__': # 创建进程池 pool = multiprocessing.Pool(processes=4) # 提交任务 for _ in range(10): pool.apply_async(task) # 关闭进程池 pool.close() # 等待所有任务完成 pool.join() ``` 在上面的示例中,我们首先创建了一个进程池`pool`,并指定进程数量为4。然后使用`apply_async`方法提交了10个任务,并最后调用`close`和`join`方法来关闭进程池和等待所有任务完成。 通过这种方式,我们可以利用多进程并发执行任务,充分利用多核处理器的计算能力。 总结: 1. 并发与并行的区别在于任务在时间上是否重叠和同时进行。 2. 线程是操作系统进行运算调度的最小单位,进程是操作系统进行资源分配和调度的基本单位。 3. 全局解释器锁(GIL)会影响Python的并发执行效果,但对于IO密集型任务影响较小。可以使用多进程编程规避GIL的影响。 4. 使用`multiprocessing`模块可以实现多进程并发编程。 # 3. Python与并发 Python作为一种广泛应用于并发编程的语言,提供了多种并发编程的方式,包括多线程、多进程和协程等。在本章节中,我们将详细介绍Python中的并发编程方式,并对每种方式进行深入探讨。 #### 3.1 Python中的多线程编程 在Python中,可以使用内置的`threading`模块进行多线程编程。多线程能够在I/O密集型任务中发挥作用,例如网络请求、文件读写等。 ##### 3.1.1 创建线程 以下是一个简单的多线程示例,用于打印数字: ```python import threading def print_numbers(): for i in range(1, 6): print(f"Number: {i}") # 创建线程 t = threading.Thread(target=print_numbers) t.start() t.join() ``` **代码说明:** - `import threading` 导入线程模块。 - `def print_numbers():` 定义一个函数,用于打印数字。 - `t = threading.Thread(target=print_numbers)` 创建一个线程,目标函数为`print_numbers`。 - `t.start()` 启动线程。 - `t.join()` 等待线程执行结束。 ##### 3.1.2 线程同步与互斥 在多线程编程中,为了避免多个线程同时修改共享数据而导致的数据错误,可以使用锁机制来进行线程同步。Python中提供了`threading.Lock`来实现线程同步与互斥。 ```python import threading num = 0 lock = threading.Lock() def update_num(): global num with lock: # 使用锁 num += 1 print(f"Num: {num}") # 创建多个线程 threads = [] for _ in range(5): t = threading.Thread(target=update_num) threads.append(t) t.start() for t in threads: t.join() print("Final Num:", num) ``` **代码说明:** - `num = 0` 定义一个全局变量`num`。 - `lock = threading.Lock()` 创建一个锁。 - `with lock:` 使用`with`语句进行锁的上下文管理。 - 创建多个线程,均调用`update_num`函数来更新`num`的值。 - 最终打印`num`的值,确认线程同步的正确性。 ##### 3.1.3 线程的安全性问题 在多线程编程中,需要注意共享数据的安全性,尤其是在涉及到对同一份数据进行读写操作时,往往需要考虑线程安全性及使用锁的方式。 #### 3.2 Python中的多进程编程 除了多线程外,Python也提供了多进程编程的支持,可以使用`multiprocessing`模块来创建和管理子进程。 ##### 3.2.1 使用`multiprocessing`模块 以下是一个简单的多进程示例,用于计算两个数的乘积: ```python import multiprocessing def multiply(x, y): return x * y if __name__ == "__main__": x, y = 5, 10 p = multiprocessing.Process(target=multiply, args=(x, y)) p.start() p.join() ``` **代码说明:** - `import multiprocessing` 导入多进程模块。 - `def multiply(x, y):` 定义一个函数,用于计算两个数的乘积。 - `if __name__ == "__main__":` 在多进程编程中,需要在`__main__`保护块中执行,避免创建子进程时再次启动新的子进程。 ##### 3.2.2 进程间通信 在多进程编程中,进程间通信是一个常见的问题。Python的`multiprocessing`模块提供了多种进程间通信的方式,例如使用队列、管道等方式进行数据传输。 ##### 3.2.3 进程间的同步与互斥 与多线程类似,多进程编程中也需要考虑进程间的同步与互斥,可以使用`multiprocessing.Lock`来实现进程间的同步与互斥。 以上是Python中的并发编程的基本内容,包括多线程和多进程编程。在接下来的章节中,我们将继续探讨并发编程中的常见问题以及高级的并发编程技术。 # 4. 并发编程中的常见问题 在并发编程中,我们会遇到一些常见的问题,包括线程安全与死锁、竞态条件和上下文切换、数据共享与通信等。下面将分别介绍这些问题及其解决方案。 #### 4.1 线程安全与死锁 **线程安全**是指多个线程对共享资源进行访问时,不会出现不正确的结果或者不一致的状态。当多个线程同时访问一个共享资源时,可能会产生一些并发问题,如数据竞争、竞态条件等。 **死锁**是指两个或多个线程彼此持有对方所需的资源,导致线程无法继续执行的情况。常见的导致死锁的原因有:资源竞争、循环等待、不可剥夺性和互斥。 解决线程安全和死锁问题的常用方法包括: - 使用锁:使用线程锁可以保证多线程对共享资源的访问是互斥的,避免了数据竞争问题。 - 避免循环等待:通过合理的资源申请顺序来避免循环等待。 下面是一个使用锁解决线程安全问题的示例代码: ```python import threading class Counter: def __init__(self): self.count = 0 self.lock = threading.Lock() def increment(self): with self.lock: self.count += 1 counter = Counter() def worker(): for _ in range(100000): counter.increment() threads = [] for _ in range(10): t = threading.Thread(target=worker) threads.append(t) t.start() for t in threads: t.join() print(counter.count) ``` 在上述代码中,Counter 类使用了一个锁来保证 increment 方法的原子性,从而避免了多线程同时对 count 变量进行操作导致的竞态条件和不正确的结果。 #### 4.2 竞态条件(Race Condition)与上下文切换 **竞态条件**是指多个线程同时访问共享资源,由于执行的顺序不确定而导致的不正确的结果。竞态条件可能会导致意料之外的行为,使得程序的结果不可预测。 **上下文切换**是指操作系统为了让多个线程充分利用 CPU 资源而进行的线程切换。上下文切换的开销很大,会导致性能下降。 要解决竞态条件和上下文切换问题,我们可以采取以下策略: - 使用锁:通过使用锁来保证对共享资源的访问是串行的,避免了竞态条件的发生。 - 减少上下文切换:可以使用线程池、协程等方式来减少线程的创建和销毁,从而减少上下文切换的次数。 下面是一个模拟竞态条件的示例代码: ```python import threading def increment(): global count count += 1 count = 0 threads = [] for _ in range(1000): t = threading.Thread(target=increment) threads.append(t) t.start() for t in threads: t.join() print(count) ``` 在上述代码中,多个线程同时对 count 变量进行自增操作,由于没有使用锁来保护共享资源,会导致竞态条件的发生,从而导致 count 的最终结果与预期不符。 #### 4.3 数据共享与通信 在并发编程中,多个线程或进程之间可能需要进行数据共享和通信。常见的数据共享和通信方式包括: - 共享内存:多个线程或进程可以访问同一块物理内存,通过对内存的读写实现数据共享和通信。 - 消息传递:多个线程或进程之间通过发送消息来进行通信,可以使用消息队列、管道、信号量等方式实现。 在 Python 中,我们可以使用队列(Queue)来实现线程间的数据共享和通信。下面是一个使用队列实现线程间通信的示例代码: ```python import threading from queue import Queue def producer(queue): for i in range(10): queue.put(i) print(f"Producer: {i}") time.sleep(0.1) def consumer(queue): while True: item = queue.get() print(f"Consumer: {item}") time.sleep(0.2) queue.task_done() queue = Queue() p = threading.Thread(target=producer, args=(queue,)) c = threading.Thread(target=consumer, args=(queue,)) p.start() c.start() p.join() c.join() print("Done") ``` 在上述代码中,生产者线程将数据放入队列中,消费者线程从队列中取出数据进行消费。通过队列的 put 方法和 get 方法,生产者和消费者线程之间实现了数据共享和通信。 以上就是在并发编程中常见的问题以及相应的解决方案。了解并能够正确处理这些问题,是编写高效且稳定并发程序的关键。 通过以上介绍,我们对并发编程中常见问题的解决方案有了一个基本的了解。在实际开发中,还需要根据具体情况选择合适的技术和方法来解决并发问题,以保证程序的健壮性和性能。 # 5. 高级并发编程 在本章中,我们将讨论一些高级的并发编程技术,包括协程与生成器、多线程编程的替代方案,以及最佳实践与性能优化。 #### 5.1 协程(Coroutines)与生成器(Generators) ##### 5.1.1 协程的基本概念与原理 在Python中,协程是一种轻量级的线程,它们可以在执行过程中被挂起,并且可以在挂起的位置恢复执行。这种特性使得协程非常适合处理I/O密集型任务,比如网络通信和文件操作。 协程的实现基于生成器(Generators),生成器是一种迭代器,使用yield语句可以实现在函数执行过程中暂停并返回一个中间值。通过yield实现的协程可以像同步代码一样简洁明了地处理异步任务。 让我们来看一个简单的协程示例: ```python def coroutine_example(): while True: x = yield print("Received:", x) # 创建协程对象 coroutine = coroutine_example() # 首次调用,启动协程 next(coroutine) # 发送数据给协程 coroutine.send(10) ``` 运行上面的代码,将会输出:"Received: 10"。在这个示例中,协程在接收到数据后打印出来,然后继续等待下一次数据的到来。 ##### 5.1.2 使用`asyncio`库实现协程 Python标准库中提供了`asyncio`库,它是Python的异步I/O框架,可以用于编写高效的协程代码。下面是一个使用`asyncio`库实现协程的简单示例: ```python import asyncio async def hello(): print("Hello,") await asyncio.sleep(1) print("World!") # 创建事件循环 loop = asyncio.get_event_loop() # 执行协程 loop.run_until_complete(hello()) # 关闭事件循环 loop.close() ``` 上面的代码利用`async`与`await`关键字定义了一个简单的协程,并通过`asyncio`库的事件循环驱动了协程的执行。在这个示例中,协程在输出"Hello,"后暂停1秒,再输出"World!"。 #### 5.2 多线程编程的替代方案 多线程编程虽然能够充分利用多核处理器并发执行任务,但是在实际应用中也存在一些问题,比如线程间的同步与互斥、线程切换带来的性能开销等。在Python中,除了使用标准的`threading`模块进行多线程编程外,还可以使用`concurrent.futures`模块和`asyncio`库进行异步编程,这些都是多线程编程的替代方案。 ##### 5.2.1 使用`concurrent.futures`模块 `concurrent.futures`模块提供了`ThreadPoolExecutor`和`ProcessPoolExecutor`两个类,可以帮助开发者快速实现线程池和进程池,从而简化并发编程的复杂性。下面是`concurrent.futures`模块的一个简单示例: ```python from concurrent.futures import ThreadPoolExecutor def power(x): return x ** 2 # 创建线程池 with ThreadPoolExecutor() as executor: # 提交任务并获取结果 result = executor.submit(power, 10).result() print(result) # 输出:100 ``` 上面的示例中,通过`ThreadPoolExecutor`创建了一个线程池,然后通过`submit`方法提交了一个任务,并通过`result`方法获取了任务的执行结果。 ##### 5.2.2 使用`asyncio`库进行异步编程 除了使用多线程和多进程进行并发编程外,Python还提供了`asyncio`库来进行异步编程,`asyncio`通过协程实现了事件循环和非阻塞I/O,在处理高并发的网络应用程序时非常高效。下面是`asyncio`库的一个简单示例: ```python import asyncio async def say_hello(): print("Hello,") await asyncio.sleep(1) print("World!") # 创建事件循环 loop = asyncio.get_event_loop() # 执行协程 loop.run_until_complete(say_hello()) # 关闭事件循环 loop.close() ``` 在这个示例中,通过`asyncio`库的事件循环执行了一个简单的协程,能够非常高效地处理异步任务。 以上是高级并发编程的一些常用技术和工具,我们可以根据实际需求选择合适的并发模型来进行编程,从而提高程序的性能和可维护性。 通过本节的学习,我们了解了协程与生成器、多线程编程的替代方案,并掌握了如何利用`asyncio`库和`concurrent.futures`模块来实现高效的并发编程。在实际开发中,根据任务的特点和系统的需求,选择合适的并发模型对于提升程序性能和响应速度非常重要。 # 6. 最佳实践与性能优化 在并发编程中,除了掌握基础知识和常见问题的解决方案之外,还需要关注最佳实践和性能优化,以确保代码的效率和稳定性。 #### 6.1 选择合适的并发模型 在选择并发模型时,需要根据具体的应用场景和需求来决定使用多线程、多进程还是协程。对于IO密集型任务,通常使用协程(如Python中的`asyncio`库)能够更好地发挥性能优势;而对于CPU密集型任务,则可能需要考虑使用多线程或多进程。 #### 6.2 避免共享状态 尽可能避免线程或进程间共享状态,因为共享状态会引发复杂的同步和互斥问题。可以通过尽量将数据局部化、使用不可变对象、使用消息传递等方式来避免共享状态。 #### 6.3 使用锁的最佳实践 在需要共享状态的情况下,需要谨慎地使用锁。不恰当的锁使用可能会导致性能下降或死锁,因此需要遵循最佳实践,如避免长时间持有锁、使用适当的粒度等。 #### 6.4 性能优化技巧与工具 在并发编程中,性能优化是至关重要的。可以通过线程池、进程池、批量处理、异步IO等技巧来提升性能。同时,工具如性能分析器、调试器、监控工具等也能帮助发现和解决性能瓶颈问题。 综合考虑最佳实践和性能优化,能够确保并发编程的稳定性和效率,提高代码的质量和可维护性。
corwn 最低0.47元/天 解锁专栏
买1年送3月
点击查看下一篇
profit 百万级 高质量VIP文章无限畅学
profit 千万级 优质资源任意下载
profit C知道 免费提问 ( 生成式Al产品 )

相关推荐

SW_孙维

开发技术专家
知名科技公司工程师,开发技术领域拥有丰富的工作经验和专业知识。曾负责设计和开发多个复杂的软件系统,涉及到大规模数据处理、分布式系统和高性能计算等方面。
专栏简介
零基础Python快速入门教程是一份综合全面的Python学习指南,为初学者提供了从基本语法到高级应用的全方位教学。该专栏包含众多内容,其中包括Python基础语法与变量、条件语句与循环结构、函数与模块的使用等基础知识的讲解。同时,还介绍了文件操作与异常处理、面向对象编程基础、正则表达式等高级主题。专栏还涵盖了常用的第三方库介绍、数据处理与分析、文本处理与分析、GUI编程、Web开发、数据可视化与图表绘制等实际应用。此外,还探讨了并发编程、人工智能与机器学习、自然语言处理、物联网与嵌入式开发、图像处理与计算机视觉等领域中Python的应用。无论是想快速入门Python的初学者,还是希望扩展应用领域的开发者,本专栏都能为您提供丰富的知识和实践经验。通过深入易懂的讲解和实例代码,让您迅速掌握Python,并能将其应用于您的项目中。
最低0.47元/天 解锁专栏
买1年送3月
百万级 高质量VIP文章无限畅学
千万级 优质资源任意下载
C知道 免费提问 ( 生成式Al产品 )

最新推荐

极端事件预测:如何构建有效的预测区间

![机器学习-预测区间(Prediction Interval)](https://d3caycb064h6u1.cloudfront.net/wp-content/uploads/2020/02/3-Layers-of-Neural-Network-Prediction-1-e1679054436378.jpg) # 1. 极端事件预测概述 极端事件预测是风险管理、城市规划、保险业、金融市场等领域不可或缺的技术。这些事件通常具有突发性和破坏性,例如自然灾害、金融市场崩盘或恐怖袭击等。准确预测这类事件不仅可挽救生命、保护财产,而且对于制定应对策略和减少损失至关重要。因此,研究人员和专业人士持

【实时系统空间效率】:确保即时响应的内存管理技巧

![【实时系统空间效率】:确保即时响应的内存管理技巧](https://cdn.educba.com/academy/wp-content/uploads/2024/02/Real-Time-Operating-System.jpg) # 1. 实时系统的内存管理概念 在现代的计算技术中,实时系统凭借其对时间敏感性的要求和对确定性的追求,成为了不可或缺的一部分。实时系统在各个领域中发挥着巨大作用,比如航空航天、医疗设备、工业自动化等。实时系统要求事件的处理能够在确定的时间内完成,这就对系统的设计、实现和资源管理提出了独特的挑战,其中最为核心的是内存管理。 内存管理是操作系统的一个基本组成部

【算法竞赛中的复杂度控制】:在有限时间内求解的秘籍

![【算法竞赛中的复杂度控制】:在有限时间内求解的秘籍](https://dzone.com/storage/temp/13833772-contiguous-memory-locations.png) # 1. 算法竞赛中的时间与空间复杂度基础 ## 1.1 理解算法的性能指标 在算法竞赛中,时间复杂度和空间复杂度是衡量算法性能的两个基本指标。时间复杂度描述了算法运行时间随输入规模增长的趋势,而空间复杂度则反映了算法执行过程中所需的存储空间大小。理解这两个概念对优化算法性能至关重要。 ## 1.2 大O表示法的含义与应用 大O表示法是用于描述算法时间复杂度的一种方式。它关注的是算法运行时

学习率对RNN训练的特殊考虑:循环网络的优化策略

![学习率对RNN训练的特殊考虑:循环网络的优化策略](https://img-blog.csdnimg.cn/20191008175634343.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTYxMTA0NQ==,size_16,color_FFFFFF,t_70) # 1. 循环神经网络(RNN)基础 ## 循环神经网络简介 循环神经网络(RNN)是深度学习领域中处理序列数据的模型之一。由于其内部循环结

Epochs调优的自动化方法

![ Epochs调优的自动化方法](https://img-blog.csdnimg.cn/e6f501b23b43423289ac4f19ec3cac8d.png) # 1. Epochs在机器学习中的重要性 机器学习是一门通过算法来让计算机系统从数据中学习并进行预测和决策的科学。在这一过程中,模型训练是核心步骤之一,而Epochs(迭代周期)是决定模型训练效率和效果的关键参数。理解Epochs的重要性,对于开发高效、准确的机器学习模型至关重要。 在后续章节中,我们将深入探讨Epochs的概念、如何选择合适值以及影响调优的因素,以及如何通过自动化方法和工具来优化Epochs的设置,从而

时间序列分析的置信度应用:预测未来的秘密武器

![时间序列分析的置信度应用:预测未来的秘密武器](https://cdn-news.jin10.com/3ec220e5-ae2d-4e02-807d-1951d29868a5.png) # 1. 时间序列分析的理论基础 在数据科学和统计学中,时间序列分析是研究按照时间顺序排列的数据点集合的过程。通过对时间序列数据的分析,我们可以提取出有价值的信息,揭示数据随时间变化的规律,从而为预测未来趋势和做出决策提供依据。 ## 时间序列的定义 时间序列(Time Series)是一个按照时间顺序排列的观测值序列。这些观测值通常是一个变量在连续时间点的测量结果,可以是每秒的温度记录,每日的股票价

激活函数理论与实践:从入门到高阶应用的全面教程

![激活函数理论与实践:从入门到高阶应用的全面教程](https://365datascience.com/resources/blog/thumb@1024_23xvejdoz92i-xavier-initialization-11.webp) # 1. 激活函数的基本概念 在神经网络中,激活函数扮演了至关重要的角色,它们是赋予网络学习能力的关键元素。本章将介绍激活函数的基础知识,为后续章节中对具体激活函数的探讨和应用打下坚实的基础。 ## 1.1 激活函数的定义 激活函数是神经网络中用于决定神经元是否被激活的数学函数。通过激活函数,神经网络可以捕捉到输入数据的非线性特征。在多层网络结构

【批量大小与存储引擎】:不同数据库引擎下的优化考量

![【批量大小与存储引擎】:不同数据库引擎下的优化考量](https://opengraph.githubassets.com/af70d77741b46282aede9e523a7ac620fa8f2574f9292af0e2dcdb20f9878fb2/gabfl/pg-batch) # 1. 数据库批量操作的理论基础 数据库是现代信息系统的核心组件,而批量操作作为提升数据库性能的重要手段,对于IT专业人员来说是不可或缺的技能。理解批量操作的理论基础,有助于我们更好地掌握其实践应用,并优化性能。 ## 1.1 批量操作的定义和重要性 批量操作是指在数据库管理中,一次性执行多个数据操作命

机器学习性能评估:时间复杂度在模型训练与预测中的重要性

![时间复杂度(Time Complexity)](https://ucc.alicdn.com/pic/developer-ecology/a9a3ddd177e14c6896cb674730dd3564.png) # 1. 机器学习性能评估概述 ## 1.1 机器学习的性能评估重要性 机器学习的性能评估是验证模型效果的关键步骤。它不仅帮助我们了解模型在未知数据上的表现,而且对于模型的优化和改进也至关重要。准确的评估可以确保模型的泛化能力,避免过拟合或欠拟合的问题。 ## 1.2 性能评估指标的选择 选择正确的性能评估指标对于不同类型的机器学习任务至关重要。例如,在分类任务中常用的指标有

【损失函数与随机梯度下降】:探索学习率对损失函数的影响,实现高效模型训练

![【损失函数与随机梯度下降】:探索学习率对损失函数的影响,实现高效模型训练](https://img-blog.csdnimg.cn/20210619170251934.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNjc4MDA1,size_16,color_FFFFFF,t_70) # 1. 损失函数与随机梯度下降基础 在机器学习中,损失函数和随机梯度下降(SGD)是核心概念,它们共同决定着模型的训练过程和效果。本