从Python转到Numpy(一)

本文探讨了如何使用Numpy进行向量化计算,通过对比面向对象编程、过程式编程和Numpy的实现,展示了Numpy在处理随机游走问题时的高效性能。通过将循环操作替换为一次性计算,Numpy显著提升了代码运行速度,验证了向量化在提高计算效率方面的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看到一篇比较完整深入讲解Numpy文章,摘要记录。

Numpy简介

Numpy 基本上全部讲的是向量化(或者矢量化)。如果熟悉python,学习numpy面临的最大问题应该是转变思考问题的方式。

举一个简单随机游走的例子。OOP的编程方式可能会定义一个RandomWalker的类,实现一个walk的方法,每走一步后返回当前的位置信息。

OOP实现

class RandomWalker:
    def __init__(self):
        self.position = 0

    def walk(self, n):
        self.position = 0
        for i in range(n):
            yield self.position # 这里用到了生成器
            self.position += 2*random.randint(0, 1) - 1

这种实现方法不错,容易阅读,但是不高效。

# 在notebook 中测试

%%timeit
walker = RandomWalker()
walk = [position for position in walker.walk(1000)]

844 µs ± 4.41 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# 机器不同测试时间会有所差异

过程式实现

对这个简单的问题,可以省去类的定义,只关注walk方法。

def random_walk(n):
    position = 0
    walk = [position]
    for i in range(n):
        position += 2*random.randint(0, 1)-1
        walk.append(position) # 不同于生成器,一次返回整个列表
    return walk

新的方法可以节省一些cpu开销,但不会太多,函数调用和面向对象实现中的方法调用基本相似。

测试结果:780 µs ± 11 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

矢量化实现

换个角度,随机游走实际是随机数的累加,可以一次性生成所有的随机step,然后累加出结果,省去所有循环。使用itertools累加模块可以提高代码效率。

import random
def random_walk_faster(n=1000):
    from itertools import accumulate # Python 3.6以后的版本支持
    steps = random.choices([-1,+1], k=n)
    return [0]+list(accumulate(steps))

测试结果:143 µs ± 313 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

如果使用numpy,还有进一步优化的空间。

import numpy as np
def random_walk_fastest(n=1000):
    steps = np.random.choice([-1,+1], n) # 从-1,1中选择,返回size 为n 的array
    return np.cumsum(steps)

测试结果:24.8 µs ± 139 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

结果是计算效率数量级的提升!

小结 ---- 矢量化的重点  一次性计算 避免循环

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值