NumPy Zipf Distribution怎么用?生成Zipf分布随机数有哪些方法?

文章导读
Previous Quiz Next 什么是 Zipf 分布? Zipf 分布是一种离散概率分布,用于描述按降序排列的元素频率。
📋 目录
  1. 什么是 Zipf 分布?
  2. 在 NumPy 中生成 Zipf 样本
  3. Zipf 分布的特性
  4. Zipf 分布的应用
  5. 估计 Zipf 指数
  6. 模拟真实世界场景
A A

NumPy - Zipf 分布



Previous
Quiz
Next

什么是 Zipf 分布?

Zipf 分布是一种离散概率分布,用于描述按降序排列的元素频率。

它遵循这样一个原则:元素的频率与其在频率表中的排名成反比,通常在自然语言中可以看到,最常见的词出现的频率是第二常见词的两倍,是第三常见词的三倍,依此类推。

它由参数 "s" 定义,该参数决定了分布的偏度。例如,大型文本语料库中词频的分布往往遵循 Zipf 分布。从数学上讲,Zipf 分布的概率质量函数 (PMF) 表示为:

P(X = k) = (1 / ks) / H(N, s)

这里,k 是排名,s 是表征分布的指数,H(N, s) 是第 N 个广义调和数,用于归一化分布。

在 NumPy 中生成 Zipf 样本

NumPy 提供了 numpy.random.zipf() 函数来从 Zipf 分布中生成随机样本。该函数需要两个主要参数:

  • a: 分布参数,也称为指数。
  • size: 要生成的样本数量(可选)。

示例:生成 Zipf 样本

以下示例生成 10 个来自指数为 2 的 Zipf 分布的随机样本 −

import numpy as np

# 生成 Zipf 样本
a = 2
samples = np.random.zipf(a, size=10)
print("Generated Zipf samples:", samples)

以下是得到的结果 −

Generated Zipf samples: [1 3 1 2 1 1 1 1 2 1]

Zipf 分布的特性

Zipf 分布具有几个独特的特性,使其适用于建模现实世界现象,它们是 −

  • Heavy Tail: 该分布具有长尾特性,即少数事件非常常见,而大多数事件罕见。
  • Power Law: 事件的概率与其排名幂次成反比。
  • Scale-Invariant: 当测量尺度变化时,分布保持不变。

示例:可视化 Zipf 定律

让我们可视化 Zipf 分布,以更好地理解其特性。我们可以使用 Matplotlib 绘制每个排名的出现频率 −

import numpy as np
import matplotlib.pyplot as plt

# 生成大量样本
a = 2
samples = np.random.zipf(a, size=1000)

# 统计每个排名的出现次数
unique, counts = np.unique(samples, return_counts=True)

# 绘制排名-频率分布图
plt.figure(figsize=(10, 6))
plt.loglog(unique, counts, marker="o")
plt.title("Zipf Distribution")
plt.xlabel("Rank")
plt.ylabel("Frequency")
plt.show()

我们得到一个对数-对数图,显示每个排名的频率,展示了 Zipf 分布的长尾和幂律特性 −

Zipf Distribution

Zipf 分布的应用

Zipf 分布用于各个领域来建模少数项目非常常见而多数项目罕见现象。常见应用包括 −

  • 自然语言处理 (NLP): 建模语料库中的词频。
  • 人口研究: 分析城市人口和规模。
  • 互联网流量: 理解网页访问和点击的分布。

示例:文本中的词频

假设我们有一个文本文档,并想使用 Zipf 分布来建模词频 −

import matplotlib.pyplot as plt
from collections import Counter

# 示例文本
text = "the quick brown fox jumps over the lazy dog the quick brown fox"

# 将文本分割成单词
words = text.split()

# 统计词频
word_counts = Counter(words)

# 获取排名和频率
ranks = range(1, len(word_counts) + 1)
frequencies = [count for word, count in word_counts.most_common()]

# 绘制排名-频率分布图
plt.figure(figsize=(10, 6))
plt.loglog(ranks, frequencies, marker="o")
plt.title("Word Frequency Distribution")
plt.xlabel("Rank")
plt.ylabel("Frequency")
plt.show()

我们得到一个对数-对数图,显示文本中每个词排名的频率,遵循 Zipf 分布 −

Word Frequency

估计 Zipf 指数

在实际应用中,我们经常需要估计 Zipf 分布的指数参数。这可以通过各种统计技术来实现。一种简单的方法是对排名与频率的对数-对数图进行直线拟合。

示例:估计指数

在下面的示例中,估计的指数接近实际值 (a = 2),证明了估计方法的准确性 −

import numpy as np
from scipy.stats import linregress

# 生成大量样本
a = 2
samples = np.random.zipf(a, size=1000)

# 统计每个排名的出现次数
unique, counts = np.unique(samples, return_counts=True)

# 对对数-对数图进行线性回归
log_ranks = np.log(unique)
log_counts = np.log(counts)
slope, intercept, r_value, p_value, std_err = linregress(log_ranks, log_counts)

print("Estimated exponent:", -slope)

得到的输出如下所示 −

Estimated exponent: 0.8852106553815038

模拟真实世界场景

让我们使用 Zipf 分布模拟一个真实世界场景。假设我们想建模一个热门新闻网站上网站访问的分布。

示例:网站访问

我们可以从 Zipf 分布生成大量样本,并分析不同页面访问的分布 −

import matplotlib.pyplot as plt
import numpy as np

# 生成 Zipf 样本
a = 1.5
samples = np.random.zipf(a, size=10000)

# 统计每个页面访问的出现次数
unique, counts = np.unique(samples, return_counts=True)

# 绘制排名-频率分布图
plt.figure(figsize=(10, 6))
plt.loglog(unique, counts, marker="o")
plt.title("Website Visits Distribution")
plt.xlabel("Page Rank")
plt.ylabel("Visit Frequency")
plt.show()

我们得到一个对数-对数图,显示网站访问的分布,展示了 Zipf 分布的重尾和幂律特性 −

Website Visits