作为一位多产的作家,我邀请您探索我的亚马逊图书收藏。 请记得在 Medium 上关注我以获取更新并表示您的支持!非常感谢您的鼓励!
Python 在数据科学和机器学习领域日益突出,需要对大型项目进行高效的内存管理。 数据集规模的扩大和计算需求的增加使得优化内存使用变得至关重要。 我在内存密集型 Python 应用程序方面的经验产生了几种有效的优化策略,我将在这里分享。
我们将从 NumPy 开始,这是一个用于数值计算的基石库。与 Python 列表相比,NumPy 数组具有显着的内存优势,特别是对于大量数据集。 它们的连续内存分配和静态类型最大限度地减少了开销。
考虑这个比较:
<code class="language-python">import numpy as np import sys # Creating a list and a NumPy array with 1 million integers py_list = list(range(1000000)) np_array = np.arange(1000000) # Comparing memory usage print(f"Python list size: {sys.getsizeof(py_list) / 1e6:.2f} MB") print(f"NumPy array size: {np_array.nbytes / 1e6:.2f} MB")</code>
NumPy 数组更小的内存占用是显而易见的。 随着数据集的增大,这种差异变得更加明显。
NumPy 还提供内存高效的操作。 它不是为每个操作生成新数组,而是经常就地修改数组:
<code class="language-python"># In-place operations np_array += 1 # Modifies the original array directly</code>
转向 Pandas,分类数据类型是内存优化的关键。 对于唯一值有限的字符串列,转换为分类类型可以大大减少内存消耗:
<code class="language-python">import pandas as pd # DataFrame with repeated string values df = pd.DataFrame({'category': ['A', 'B', 'C'] * 1000000}) # Memory usage check print(f"Original memory usage: {df.memory_usage(deep=True).sum() / 1e6:.2f} MB") # Conversion to categorical df['category'] = pd.Categorical(df['category']) # Post-conversion memory usage print(f"Memory usage after conversion: {df.memory_usage(deep=True).sum() / 1e6:.2f} MB")</code>
可以节省大量内存,尤其是对于包含重复字符串的大型数据集。
对于稀疏数据集,Pandas 提供稀疏数据结构,仅存储非空值,从而为具有大量空值或零值的数据集节省大量内存:
<code class="language-python"># Creating a sparse series sparse_series = pd.Series([0, 0, 1, 0, 2, 0, 0, 3], dtype="Sparse[int]") print(f"Memory usage: {sparse_series.memory_usage(deep=True) / 1e3:.2f} KB")</code>
当数据集超过可用 RAM 时,内存映射文件就会发生变革。 它们允许像在内存中一样处理大文件,而无需加载整个文件:
<code class="language-python">import mmap import os # Creating a large file with open('large_file.bin', 'wb') as f: f.write(b'0' * 1000000000) # 1 GB file # Memory-mapping the file with open('large_file.bin', 'r+b') as f: mmapped_file = mmap.mmap(f.fileno(), 0) # Reading from the memory-mapped file print(mmapped_file[1000000:1000010]) # Cleaning up mmapped_file.close() os.remove('large_file.bin')</code>
这对于随机访问大文件而不将它们完全加载到内存中特别有用。
生成器表达式和 itertools
对于内存高效的数据处理来说非常强大。它们允许处理大型数据集,而无需同时将所有内容加载到内存中:
<code class="language-python">import itertools # Generator expression sum_squares = sum(x*x for x in range(1000000)) # Using itertools for memory-efficient operations evens = itertools.islice(itertools.count(0, 2), 1000000) sum_evens = sum(evens) print(f"Sum of squares: {sum_squares}") print(f"Sum of even numbers: {sum_evens}")</code>
这些技术在处理大型数据集时最大限度地减少内存开销。
对于性能关键的代码部分,Cython 提供了巨大的优化潜力。 将 Python 代码编译为 C 可以显着提高速度并减少潜在的内存消耗:
<code class="language-cython">def sum_squares_cython(int n): cdef int i cdef long long result = 0 for i in range(n): result += i * i return result # Usage result = sum_squares_cython(1000000) print(f"Sum of squares: {result}")</code>
此 Cython 函数将优于其纯 Python 函数,特别是对于较大的 n
值。
PyPy 是一个即时编译器,提供自动内存优化。 它对于长时间运行的程序特别有益,通常可以显着减少内存使用量:
<code class="language-python">import numpy as np import sys # Creating a list and a NumPy array with 1 million integers py_list = list(range(1000000)) np_array = np.arange(1000000) # Comparing memory usage print(f"Python list size: {sys.getsizeof(py_list) / 1e6:.2f} MB") print(f"NumPy array size: {np_array.nbytes / 1e6:.2f} MB")</code>
与标准 CPython 相比,PyPy 可以提高内存效率和速度。
内存分析对于识别优化机会至关重要。 memory_profiler
库是一个很有价值的工具:
<code class="language-python"># In-place operations np_array += 1 # Modifies the original array directly</code>
使用 mprof run script.py
和 mprof plot
可视化内存使用情况。
解决内存泄漏问题至关重要。 tracemalloc
模块 (Python 3.4 ) 帮助识别内存分配源:
<code class="language-python">import pandas as pd # DataFrame with repeated string values df = pd.DataFrame({'category': ['A', 'B', 'C'] * 1000000}) # Memory usage check print(f"Original memory usage: {df.memory_usage(deep=True).sum() / 1e6:.2f} MB") # Conversion to categorical df['category'] = pd.Categorical(df['category']) # Post-conversion memory usage print(f"Memory usage after conversion: {df.memory_usage(deep=True).sum() / 1e6:.2f} MB")</code>
这可以精确定位内存密集型代码部分。
对于内存极其密集的应用程序,可能需要自定义内存管理。 这可能涉及用于对象重用或自定义缓存的对象池:
<code class="language-python"># Creating a sparse series sparse_series = pd.Series([0, 0, 1, 0, 2, 0, 0, 3], dtype="Sparse[int]") print(f"Memory usage: {sparse_series.memory_usage(deep=True) / 1e3:.2f} KB")</code>
这可以最大限度地减少对象创建/销毁的开销。
对于特别大的数据集,请考虑使用 Dask 等核外计算库:
<code class="language-python">import mmap import os # Creating a large file with open('large_file.bin', 'wb') as f: f.write(b'0' * 1000000000) # 1 GB file # Memory-mapping the file with open('large_file.bin', 'r+b') as f: mmapped_file = mmap.mmap(f.fileno(), 0) # Reading from the memory-mapped file print(mmapped_file[1000000:1000010]) # Cleaning up mmapped_file.close() os.remove('large_file.bin')</code>
Dask 通过将计算分成更小的块来处理大于可用 RAM 的数据集。
算法优化也至关重要。 选择高效的算法可以显着减少内存使用:
<code class="language-python">import itertools # Generator expression sum_squares = sum(x*x for x in range(1000000)) # Using itertools for memory-efficient operations evens = itertools.islice(itertools.count(0, 2), 1000000) sum_evens = sum(evens) print(f"Sum of squares: {sum_squares}") print(f"Sum of even numbers: {sum_evens}")</code>
这个优化的斐波那契函数使用常量内存,与简单的递归实现不同。
总之,有效的 Python 内存优化结合了高效的数据结构、专门的库、内存高效的编码和适当的算法。 这些技术减少了内存占用,从而能够处理更大的数据集和更复杂的计算。 请记住分析您的代码以识别瓶颈并将优化工作集中在它们会产生最大影响的地方。
101 Books是由作家Aarav Joshi联合创立的人工智能出版社,利用人工智能最大限度地降低出版成本,让优质知识触手可及(有些书的价格低至4 美元!)。
在 Amazon 上查找我们的 Golang Clean Code 书。
有关更新和更多内容,请在亚马逊上搜索 Aarav Joshi。 可通过[链接]获得特别折扣。
探索我们的创作:
投资者中心 | 投资者中央西班牙语 | 投资者中德意志 | 智能生活 | 时代与回响 | 令人费解的谜团 | 印度教 | 精英开发 | JS学校
科技考拉洞察 | 时代与回响世界 | 投资者中央媒体 | 令人费解的谜团 | 科学与时代媒介 | 现代印度教
以上是掌握 Python 内存优化:数据科学和机器学习技术的详细内容。更多信息请关注PHP中文网其他相关文章!