【问题标题】:What does numpy's vectorize do?numpy 的矢量化有什么作用?
【发布时间】:2017-07-23 14:16:24
【问题描述】:

我有一个清除一组停用词文本的功能:

def clean_text(raw_text, stopwords_set):
    # removing everything which is not a letter
    letters_only = re.sub("[^a-zA-Z]", " ", raw_text)
    # lower case + split --> list of words
    words = letters_only.lower().split()             
    # now remove the stop words
    meaningful_words = [w for w in words if not w in stopwords_set]
    # join the remaining words together to get the cleaned tweet
    return " ".join(meaningful_words)

还有一个包含 160 万条推特推文的数据集,位于 pandas 数据框中。如果我只是简单地将apply这个函数添加到这样的数据帧中:

dataframe['clean_text'] = dataframe.apply(
    lambda text: clean_text(text, set(stopwords.words('english'))),
    axis = 1)

计算需要 2 分钟才能完成(大约)。但是,当我像这样使用np.vectorize 时:

dataframe['clean_text'] = np.vectorize(clean_text)(
    dataframe['text'], set(stopwords.words('english')))

计算在 10 秒后完成(大约)。

这本身并不奇怪,如果不是这两种方法都只在我的机器上使用了一个内核。我假设,使用矢量化,它会自动使用多个内核来更快地完成,从而获得更快的速度,但它似乎做了一些不同的事情。

numpy 的 ´vectorize` 有什么“魔力”?

【问题讨论】:

  • 再次,您是否阅读过np.vectorize 上的文档?它声明 - "The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop.".
  • @Divakar 那如何解释加速?即使有知识,我也看不出这是如何解释加速的,所以这对我没有帮助。请保持建设性,谢谢。
  • 你能根据 for-loop 版本计时吗?
  • 与 numpy 数组上的显式循环相比,vectorize 通常显示出小的加速 (20%)。但是您将其与 pandas apply 进行比较。像这样使用可能会非常慢。
  • 确保矢量化工作正常。它可能一次向您的功能提供一个停用词。检查输出的形状。

标签: pandas numpy vectorization stop-words


【解决方案1】:

我想知道vectorize 是如何处理这些输入的。它旨在获取数组输入,将它们相互广播,并将所有元素作为标量提供给您的函数。我特别想知道它是如何处理set 的。

有了你的功能,加上print(stop_words),我得到了

In [98]: words = set('one two three four five'.split())
In [99]: f=np.vectorize(clean_text)
In [100]: f(['this is one line with two words'],words)
{'five', 'four', 'three', 'one', 'two'}
{'five', 'four', 'three', 'one', 'two'}
Out[100]: 
array(['this is line with words'], 
      dtype='<U23')

该集合显示两次,因为vectorize 运行一个测试用例来确定返回数组的 dtype。但与我担心的相反,它将整个集合传递给函数。那是因为将 set 包装在一个数组中只会创建 0d 对象数组:

In [101]: np.array(words)
Out[101]: array({'five', 'four', 'three', 'one', 'two'}, dtype=object)

由于我们不希望向量化函数遍历第二个参数,我们确实应该使用excluded 参数。速度差异可能可以忽略不计。

In [104]: f=np.vectorize(clean_text, excluded=[1])
In [105]: f(['this is one line with two words'],words)

但只有一个数组或数据序列要迭代,vectorize 只不过是一维迭代或列表理解:

In [111]: text = ['this is one line with two words']
In [112]: [clean_text(t, words) for t in text]
Out[112]: ['this is line with words']

如果我让文本列表更长(10000):

In [121]: timeit [clean_text(t, words) for t in text]
10 loops, best of 3: 98.2 ms per loop
In [122]: f=np.vectorize(clean_text, excluded=[1])
In [123]: timeit f(text,words)
10 loops, best of 3: 158 ms per loop
In [124]: f=np.vectorize(clean_text)
In [125]: timeit f(text,words)
10 loops, best of 3: 108 ms per loop

excluded 实际上减慢了vectorize 的速度;没有它,列表理解和向量化执行相同。

因此,如果pandas apply 慢得多,那不是因为vectorize 很神奇。这是因为apply 很慢。

【讨论】:

  • 我明白了。 apply 很慢,vectorize 是“正常”的,所以看起来vectorize 正在加快速度,但实际上它只是让他们回到了他们“应该”的状态(这是一个加速)。也感谢您安排时间!
猜你喜欢
  • 2014-08-10
  • 1970-01-01
  • 2018-03-17
  • 1970-01-01
  • 2017-05-04
  • 2010-11-28
  • 2021-04-27
  • 2020-04-06
  • 1970-01-01
相关资源
最近更新 更多