1.8 随机数奥秘:生成符合现实分布的虚拟数据
目录
1.8.1 随机数种子与可重复实验
在科学研究和工程应用中,实验的可重复性是非常重要的。通过设置随机数种子,我们可以确保在不同的运行中生成相同的随机数序列。这在调试代码和验证算法时非常有用,因为它消除了随机性导致的不确定性。
1.8.1.1 设置随机数种子
随机数种子用于初始化随机数生成器。设置相同的种子后,每次运行代码都会生成相同的随机数序列。这是确保实验可重复性的关键步骤。
import numpy as np
# 设置随机数种子
np.random.seed(42) # 设置随机数种子为42
random_numbers = np.random.rand(10) # 生成10个0到1之间的随机数
print(random_numbers) # 输出生成的随机数
代码解释:
np.random.seed(42)
:设置随机数种子为42。np.random.rand(10)
:生成10个0到1之间的随机数。print(random_numbers)
:输出生成的随机数。
1.8.1.2 随机数种子的作用
通过设置随机数种子,可以确保在不同的运行环境中生成相同的随机数序列。这对于调试和验证算法非常有用,因为它消除了随机性导致的不确定性。
np.random.seed(42) # 再次设置随机数种子为42
random_numbers_2 = np.random.rand(10) # 生成10个0到1之间的随机数
print(random_numbers_2) # 输出生成的随机数
代码解释:
np.random.seed(42)
:再次设置随机数种子为42。np.random.rand(10)
:生成10个0到1之间的随机数。print(random_numbers_2)
:输出生成的随机数。
输出结果:
[0.37454012 0.95071431 0.73199394 0.59865848 0.15601864 0.15599452
0.05808361 0.86617615 0.60111501 0.70807258]
[0.37454012 0.95071431 0.73199394 0.59865848 0.15601864 0.15599452
0.05808361 0.86617615 0.60111501 0.70807258]
1.8.2 12种概率分布的可视化对比
NumPy提供了多种常见的概率分布生成方法,每种分布都有其特定的应用场景。通过可视化这些分布,我们可以更好地理解它们的特性。
1.8.2.1 常见分布及其应用场景对照表
分布类型 | 应用场景 | NumPy函数 |
---|---|---|
均匀分布 | 模拟等概率事件 | np.random.uniform |
正态分布 | 模拟自然和社会科学中的许多现象 | np.random.normal |
二项分布 | 模拟重复试验中的成功次数 | np.random.binomial |
泊松分布 | 模拟稀有事件的发生次数 | np.random.poisson |
指数分布 | 模拟事件之间的时间间隔 | np.random.exponential |
对数正态分布 | 模拟对数正态分布的数据 | np.random.lognormal |
贝塔分布 | 模拟概率分布 | np.random.beta |
卡方分布 | 模拟卡方检验 | np.random.chisquare |
负二项分布 | 模拟失败次数 | np.random.negative_binomial |
伽玛分布 | 模拟事件发生的时间间隔 | np.random.gamma |
拉普拉斯分布 | 模拟尖峰分布 | np.random.laplace |
逻辑斯蒂分布 | 模拟逻辑斯蒂回归中的误差 | np.random.logistic |
分布类型 | 函数名称 | 典型应用场景 |
---|---|---|
均匀分布 | uniform | 彩票抽奖、随机采样 |
正态分布 | normal | 身高体重、测量误差 |
泊松分布 | poisson | 电话呼叫量、网站访问量 |
指数分布 | exponential | 设备寿命、等待时间 |
二项分布 | binomial | 抛硬币实验、成功率测试 |
卡方分布 | chisquare | 统计假设检验 |
Gamma分布 | gamma | 保险理赔、降雨量分析 |
Beta分布 | beta | 概率的概率分布 |
Logistic分布 | logistic | 机器学习分类器 |
几何分布 | geometric | 首次成功前失败次数 |
超几何分布 | hypergeometric | 不放回抽样问题 |
多元正态分布 | multivariate_normal | 金融资产组合模拟 |
正态分布公式举例
正态分布概率密度函数:
f
(
x
∣
μ
,
σ
2
)
=
1
σ
2
π
e
−
(
x
−
μ
)
2
2
σ
2
f(x|\mu,\sigma^2) = \frac{1}{\sigma\sqrt{2\pi}} e^{ -\frac{(x-\mu)^2}{2\sigma^2} }
f(x∣μ,σ2)=σ2π1e−2σ2(x−μ)2
Box-Muller变换生成正态分布随机数:
def box_muller(u1, u2):
"""
Box-Muller变换算法
u1, u2: 独立均匀分布随机数
"""
z0 = np.sqrt(-2*np.log(u1)) * np.cos(2*np.pi*u2)
z1 = np.sqrt(-2*np.log(u1)) * np.cos(2*np.pi*u2)
return z0, z1
1.8.2.2 使用Seaborn绘制分布直方图
Seaborn是一个基于Matplotlib的统计绘图库,可以方便地绘制各种概率分布的直方图和密度图。
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# 设置随机数种子
np.random.seed(42)
# 生成不同分布的随机数
uniform_data = np.random.uniform(0, 1, 1000) # 均匀分布
normal_data = np.random.normal(0, 1, 1000) # 正态分布
binomial_data = np.random.binomial(10, 0.5, 1000) # 二项分布
poisson_data = np.random.poisson(5, 1000) # 泊松分布
exponential_data = np.random.exponential(1, 1000) # 指数分布
lognormal_data = np.random.lognormal(0, 1, 1000) # 对数正态分布
beta_data = np.random.beta(0.5, 0.5, 1000) # 贝塔分布
chisquare_data = np.random.chisquare(2, 1000) # 卡方分布
negative_binomial_data = np.random.negative_binomial(10, 0.5, 1000) # 负二项分布
gamma_data = np.random.gamma(2, 2, 1000) # 伽玛分布
laplace_data = np.random.laplace(0, 1, 1000) # 拉普拉斯分布
logistic_data = np.random.logistic(0, 1, 1000) # 逻辑斯蒂分布
# 绘制分布直方图
plt.figure(figsize=(15, 10))
plt.subplot(4, 3, 1)
sns.histplot(uniform_data, kde=True, bins=30)
plt.title('均匀分布 (Uniform Distribution)')
plt.xlabel('值')
plt.ylabel('频率')
plt.subplot(4, 3, 2)
sns.histplot(normal_data, kde=True, bins=30)
plt.title('正态分布 (Normal Distribution)')
plt.xlabel('值')
plt.ylabel('频率')
plt.subplot(4, 3, 3)
sns.histplot(binomial_data, kde=True, bins=30)
plt.title('二项分布 (Binomial Distribution)')
plt.xlabel('成功次数')
plt.ylabel('频率')
plt.subplot(4, 3, 4)
sns.histplot(poisson_data, kde=True, bins=30)
plt.title('泊松分布 (Poisson Distribution)')
plt.xlabel('事件发生次数')
plt.ylabel('频率')
plt.subplot(4, 3, 5)
sns.histplot(exponential_data, kde=True, bins=30)
plt.title('指数分布 (Exponential Distribution)')
plt.xlabel('时间间隔')
plt.ylabel('频率')
plt.subplot(4, 3, 6)
sns.histplot(lognormal_data, kde=True, bins=30)
plt.title('对数正态分布 (Log-Normal Distribution)')
plt.xlabel('值')
plt.ylabel('频率')
plt.subplot(4, 3, 7)
sns.histplot(beta_data, kde=True, bins=30)
plt.title('贝塔分布 (Beta Distribution)')
plt.xlabel('值')
plt.ylabel('频率')
plt.subplot(4, 3, 8)
sns.histplot(chisquare_data, kde=True, bins=30)
plt.title('卡方分布 (Chi-Square Distribution)')
plt.xlabel('值')
plt.ylabel('频率')
plt.subplot(4, 3, 9)
sns.histplot(negative_binomial_data, kde=True, bins=30)
plt.title('负二项分布 (Negative Binomial Distribution)')
plt.xlabel('失败次数')
plt.ylabel('频率')
plt.subplot(4, 3, 10)
sns.histplot(gamma_data, kde=True, bins=30)
plt.title('伽玛分布 (Gamma Distribution)')
plt.xlabel('事件发生时间间隔')
plt.ylabel('频率')
plt.subplot(4, 3, 11)
sns.histplot(laplace_data, kde=True, bins=30)
plt.title('拉普拉斯分布 (Laplace Distribution)')
plt.xlabel('值')
plt.ylabel('频率')
plt.subplot(4, 3, 12)
sns.histplot(logistic_data, kde=True, bins=30)
plt.title('逻辑斯蒂分布 (Logistic Distribution)')
plt.xlabel('值')
plt.ylabel('频率')
plt.tight_layout()
plt.show()
代码解释:
np.random.uniform(0, 1, 1000)
:生成1000个0到1之间的均匀分布随机数。np.random.normal(0, 1, 1000)
:生成1000个均值为0,标准差为1的正态分布随机数。np.random.binomial(10, 0.5, 1000)
:生成1000个二项分布随机数,每次试验10次,成功概率为0.5。np.random.poisson(5, 1000)
:生成1000个泊松分布随机数,期望值为5。np.random.exponential(1, 1000)
:生成1000个指数分布随机数,比例参数为1。np.random.lognormal(0, 1, 1000)
:生成1000个对数正态分布随机数,均值为0,标准差为1。np.random.beta(0.5, 0.5, 1000)
:生成1000个贝塔分布随机数,参数为0.5和0.5。np.random.chisquare(2, 1000)
:生成1000个卡方分布随机数,自由度为2。np.random.negative_binomial(10, 0.5, 1000)
:生成1000个负二项分布随机数,试验次数为10,成功概率为0.5。np.random.gamma(2, 2, 1000)
:生成1000个伽玛分布随机数,形状参数为2,比例参数为2。np.random.laplace(0, 1, 1000)
:生成1000个拉普拉斯分布随机数,均值为0,比例参数为1。np.random.logistic(0, 1, 1000)
:生成1000个逻辑斯蒂分布随机数,均值为0,比例参数为1。sns.histplot
:使用Seaborn库绘制直方图和密度图。plt.tight_layout()
:调整子图的布局,以避免重叠。plt.show()
:显示所有绘制的图表。
1.8.3 并行计算中的随机状态管理
1.8.3.3 并行计算中的随机数生成问题
在多线程或多进程环境中,管理随机状态是一个重要的问题。如果多个线程共享同一个随机数生成器,可能会导致生成的随机数序列重复,从而影响实验结果的可重复性和正确性。
问题示例:
import numpy as np
import threading
# 创建一个全局的随机数生成器
global_rng = np.random.default_rng(42)
# 定义每个线程的随机数生成函数
def generate_random_numbers(data):
data.append(global_rng.random(10)) # 生成10个随机数
# 创建线程列表
threads = []
data = []
# 创建并启动多个线程
for i in range(5):
thread = threading.Thread(target=generate_random_numbers, args=(data,))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
# 打印生成的随机数
for i, d in enumerate(data):
print(f"线程{i}生成的随机数: {d}")
问题解释:
global_rng = np.random.default_rng(42)
:创建一个全局的Generator
对象。global_rng.random(10)
:在每个线程中使用同一个Generator
对象生成10个随机数。- 由于多个线程共享同一个
Generator
对象,生成的随机数可能会重复。
1.8.3.4 使用RandomState
和Generator
解决随机数生成问题
解决方案1:使用RandomState
对象
import numpy as np
import threading
# 创建一个全局的随机数种子
global_seed = 42
# 定义每个线程的随机数生成函数
def generate_random_numbers(seed, data):
rng = np.random.RandomState(seed) # 创建一个RandomState对象
data.append(rng.rand(10)) # 生成10个随机数
# 创建线程列表
threads = []
data = []
# 创建并启动多个线程
for i in range(5):
seed = global_seed + i # 每个线程的随机数种子
thread = threading.Thread(target=generate_random_numbers, args=(seed, data))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
# 打印生成的随机数
for i, d in enumerate(data):
print(f"线程{i}生成的随机数: {d}")
解决方案2:使用Generator
对象
import numpy as np
import threading
# 创建一个全局的随机数种子
global_seed = 42
# 定义每个线程的随机数生成函数
def generate_random_numbers(seed, data):
rng = np.random.default_rng(seed) # 创建一个Generator对象
data.append(rng.random(10)) # 生成10个随机数
# 创建线程列表
threads = []
data = []
# 创建并启动多个线程
for i in range(5):
seed = global_seed + i # 每个线程的随机数种子
thread = threading.Thread(target=generate_random_numbers, args=(seed, data))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
# 打印生成的随机数
for i, d in enumerate(data):
print(f"线程{i}生成的随机数: {d}")
解决方案解释:
np.random.RandomState(seed)
:创建一个RandomState
对象,使用特定的种子。np.random.default_rng(seed)
:创建一个Generator
对象,使用特定的种子。- 每个线程使用自己的随机数生成器,确保生成的随机数序列独立。
1.8.4 蒙特卡洛模拟实战
1.8.4.2 投资风险评估
蒙特卡洛模拟可以用于评估投资组合的风险。通过模拟未来市场条件,我们可以估计投资组合的潜在收益和损失。
示例代码:
import numpy as np
import matplotlib.pyplot as plt
# 设置随机数种子
np.random.seed(42)
# 投资组合参数
initial_investment = 10000 # 初始投资
annual_return_mean = 0.07 # 年平均收益率
annual_return_std = 0.15 # 年收益率标准差
years = 10 # 投资年限
simulations = 1000 # 模拟次数
# 生成模拟数据
returns = np.random.normal(annual_return_mean, annual_return_std, (simulations, years)) # 生成模拟的年收益率
end_values = initial_investment * (1 + returns).cumprod(axis=1) # 计算每个模拟的投资期末价值
# 绘制结果
plt.figure(figsize=(10, 6))
for i in range(simulations):
plt.plot(range(years + 1), [initial_investment] + list(end_values[i]), alpha=0.1) # 绘制每个模拟的曲线
plt.plot(range(years + 1), [initial_investment] + list(np.median(end_values, axis=0)), color='blue', label='中位数') # 绘制中位数曲线
plt.plot(range(years + 1), [initial_investment] + list(np.mean(end_values, axis=0)), color='red', label='平均值') # 绘制平均值曲线
plt.title('蒙特卡洛模拟:投资风险评估')
plt.xlabel('年份')
plt.ylabel('期末价值')
plt.legend()
plt.show()
代码解释:
np.random.normal(annual_return_mean, annual_return_std, (simulations, years))
:生成1000次模拟,每次模拟10年的年收益率。(1 + returns).cumprod(axis=1)
:计算每个模拟的投资期末价值。plt.plot
:绘制每个模拟的曲线、中位数曲线和平均值曲线。plt.legend()
:显示图例。plt.show()
:显示图表。
1.8.4.3 期权定价
蒙特卡洛模拟也可以用于金融衍生品的定价,如欧式期权。通过模拟未来股票价格的路径,我们可以估计期权的期望价值。
示例代码:
import numpy as np
import matplotlib.pyplot as plt
# 设置随机数种子
np.random.seed(42)
# 期权参数
S0 = 100 # 初始股票价格
K = 110 # 行权价格
T = 1 # 到期时间(年)
r = 0.05 # 无风险利率
sigma = 0.2 # 波动率
simulations = 10000 # 模拟次数
steps = 252 # 每年交易天数
# 模拟股票价格路径
dt = T / steps
S = np.zeros((simulations, steps + 1))
S[:, 0] = S0
for t in range(1, steps + 1):
S[:, t] = S[:, t-1] * np.exp((r - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * np.random.normal(0, 1, simulations))
# 计算期权支付
payoff = np.maximum(S[:, -1] - K, 0) # 期权到期时的支付
option_price = np.exp(-r * T) * np.mean(payoff) # 期权价格
# 绘制结果
plt.figure(figsize=(10, 6))
for i in range(50): # 选择50个模拟路径进行绘制
plt.plot(range(steps + 1), S[i], alpha=0.1)
plt.plot(range(steps + 1), np.mean(S, axis=0), color='blue', label='平均路径')
plt.title('蒙特卡洛模拟:欧式期权定价')
plt.xlabel('时间步')
plt.ylabel('股票价格')
plt.legend()
plt.show()
print(f"期权价格的估计值: {option_price}")
代码解释:
S0
:初始股票价格。K
:行权价格。T
:到期时间(年)。r
:无风险利率。sigma
:波动率。dt = T / steps
:每个时间步的长度。S[:, t] = S[:, t-1] * np.exp((r - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * np.random.normal(0, 1, simulations))
:生成股票价格路径。payoff = np.maximum(S[:, -1] - K, 0)
:计算期权到期时的支付。option_price = np.exp(-r * T) * np.mean(payoff)
:计算期权价格。plt.plot
:绘制每个模拟的股票价格路径和平均路径。plt.legend()
:显示图例。plt.show()
:显示图表。print(f"期权价格的估计值: {option_price}")
:输出期权价格的估计值。
1.8.5 彩票号码生成器的完整实现
1.8.5.1 彩票号码生成器的基本原理
彩票号码生成器需要生成一组随机且互不相同的号码。我们可以使用NumPy的随机函数和集合(set)来实现这一点。
示例代码:
import numpy as np
# 设置随机数种子
np.random.seed(42)
# 彩票号码生成函数
def generate_lottery_numbers(num_numbers=6, max_number=49):
# 生成一组随机且互不相同的号码
numbers = np.random.choice(np.arange(1, max_number + 1), size=num_numbers, replace=False)
return np.sort(numbers) # 返回排序后的号码
# 生成一组彩票号码
lottery_numbers = generate_lottery_numbers()
print(f"生成的彩票号码: {lottery_numbers}")
代码解释:
np.random.seed(42)
:设置随机数种子。np.random.choice(np.arange(1, max_number + 1), size=num_numbers, replace=False)
:生成一组随机且互不相同的号码。np.sort(numbers)
:对生成的号码进行排序。print(f"生成的彩票号码: {lottery_numbers}")
:输出生成的彩票号码。
1.8.5.2 完整的彩票号码生成器
我们可以扩展上述代码,创建一个完整的彩票号码生成器,支持生成多组不同的彩票号码。
示例代码:
import numpy as np
# 设置随机数种子
np.random.seed(42)
# 彩票号码生成函数
def generate_lottery_numbers(num_numbers=6, max_number=49, num_sets=10):
lottery_sets = []
for _ in range(num_sets):
numbers = np.random.choice(np.arange(1, max_number + 1), size=num_numbers, replace=False)
lottery_sets.append(np.sort(numbers))
return lottery_sets
# 生成10组不同的彩票号码
lottery_numbers = generate_lottery_numbers(num_sets=10)
for i, numbers in enumerate(lottery_numbers):
print(f"第{i + 1}组彩票号码: {numbers}")
代码解释:
generate_lottery_numbers(num_numbers=6, max_number=49, num_sets=10)
:生成10组不同且互不相同的彩票号码。for _ in range(num_sets)
:循环生成多组号码。np.random.choice(np.arange(1, max_number + 1), size=num_numbers, replace=False)
:生成一组随机且互不相同的号码。np.sort(numbers)
:对生成的号码进行排序。print(f"第{i + 1}组彩票号码: {numbers}")
:输出每组彩票号码。
1.8.5.3 彩票号码生成器的改进
我们可以进一步改进彩票号码生成器,使其支持多种彩票类型的生成。
示例代码:
import numpy as np
# 设置随机数种子
np.random.seed(42)
# 彩票号码生成函数
def generate_lottery_numbers(lottery_type='lotto_6_49', num_sets=10):
if lottery_type == 'lotto_6_49':
num_numbers = 6
max_number = 49
elif lottery_type == 'powerball_5_69':
num_numbers = 5
max_number = 69
else:
raise ValueError("不支持的彩票类型")
lottery_sets = []
for _ in range(num_sets):
numbers = np.random.choice(np.arange(1, max_number + 1), size=num_numbers, replace=False)
lottery_sets.append(np.sort(numbers))
return lottery_sets
# 生成10组Lotto 6/49类型的彩票号码
lottery_numbers = generate_lottery_numbers(lottery_type='lotto_6_49', num_sets=10)
for i, numbers in enumerate(lottery_numbers):
print(f"第{i + 1}组Lotto 6/49号码: {numbers}")
# 生成10组Powerball 5/69类型的彩票号码
lottery_numbers = generate_lottery_numbers(lottery_type='powerball_5_69', num_sets=10)
for i, numbers in enumerate(lottery_numbers):
print(f"第{i + 1}组Powerball 5/69号码: {numbers}")
代码解释:
generate_lottery_numbers(lottery_type='lotto_6_49', num_sets=10)
:根据彩票类型生成多组号码。if lottery_type == 'lotto_6_49'
:判断彩票类型并设置相应的参数。np.random.choice(np.arange(1, max_number + 1), size=num_numbers, replace=False)
:生成一组随机且互不相同的号码。np.sort(numbers)
:对生成的号码进行排序。print(f"第{i + 1}组{彩票类型}号码: {numbers}")
:输出每组彩票号码。
1.8.6 随机森林中的数据生成技巧
1.8.6.1 随机森林的原理
随机森林是一种集成学习方法,通过构建多个决策树并集成它们的预测结果来提高模型的准确性和稳定性。在训练随机森林时,需要生成多个不同的数据集。
示例代码:
import numpy as np
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
# 设置随机数种子
np.random.seed(42)
# 生成原始数据集
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 定义随机森林模型
rf = RandomForestClassifier(n_estimators=100, random_state=42)
# 训练随机森林模型
rf.fit(X_train, y_train)
# 预测测试集
y_pred = rf.predict(X_test)
# 评估模型性能
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确性: {accuracy}")
代码解释:
make_classification
:生成分类问题的数据集。train_test_split
:划分训练集和测试集。RandomForestClassifier
:定义随机森林模型。rf.fit(X_train, y_train)
:训练随机森林模型。rf.predict(X_test)
:预测测试集。accuracy_score(y_test, y_pred)
:评估模型性能。
1.8.6.2 数据集的生成技巧
在生成随机森林的数据集时,可以使用Bootstrap方法生成多个不同的子集。
示例代码:
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
# 设置随机数种子
np.random.seed(42)
# 生成原始数据集
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 生成Bootstrap子集
def bootstrap_sample(X, y):
n_samples = X.shape[0]
idxs = np.random.choice(n_samples, size=n_samples, replace=True)
return X[idxs], y[idxs]
# 生成100个不同的子集
bootstrap_datasets = [bootstrap_sample(X_train, y_train) for _ in range(100)]
# 打印前5个子集的前10个样本
for i, (X_bs, y_bs) in enumerate(bootstrap_datasets[:5]):
print(f"第{i + 1}个Bootstrap子集的前10个样本:")
print(X_bs[:10])
print(y_bs[:10])
print()
代码解释:
bootstrap_sample(X, y)
:生成一个Bootstrap子集。idxs = np.random.choice(n_samples, size=n_samples, replace=True)
:生成有放回的样本索引。X[idxs], y[idxs]
:根据索引生成Bootstrap子集。bootstrap_datasets = [bootstrap_sample(X_train, y_train) for _ in range(100)]
:生成100个不同的子集。- `print(f"第{i + 1}个Bootstrap子集的前10
bootstrap_datasets = [bootstrap_sample(X_train, y_train) for _ in range(100)]
:生成100个不同的Bootstrap子集。print(f"第{i + 1}个Bootstrap子集的前10个样本:")
:输出每个子集的前10个样本。
示例代码(完整):
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
# 设置随机数种子
np.random.seed(42)
# 生成原始数据集
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 生成Bootstrap子集
def bootstrap_sample(X, y):
n_samples = X.shape[0]
idxs = np.random.choice(n_samples, size=n_samples, replace=True)
return X[idxs], y[idxs]
# 生成100个不同的子集
bootstrap_datasets = [bootstrap_sample(X_train, y_train) for _ in range(100)]
# 打印前5个子集的前10个样本
for i, (X_bs, y_bs) in enumerate(bootstrap_datasets[:5]):
print(f"第{i + 1}个Bootstrap子集的前10个样本:")
print(X_bs[:10])
print(y_bs[:10])
print()
代码解释:
make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=42)
:生成一个包含1000个样本、20个特征的分类数据集。其中15个特征是信息性的,5个特征是冗余的。train_test_split(X, y, test_size=0.2, random_state=42)
:将数据集划分为训练集和测试集,测试集占20%。bootstrap_sample(X, y)
:定义一个函数,生成一个Bootstrap子集。idxs = np.random.choice(n_samples, size=n_samples, replace=True)
:生成有放回的样本索引。X[idxs], y[idxs]
:根据索引生成Bootstrap子集。bootstrap_datasets = [bootstrap_sample(X_train, y_train) for _ in range(100)]
:生成100个不同的Bootstrap子集。print(f"第{i + 1}个Bootstrap子集的前10个样本:")
:输出每个子集的前10个样本。
1.8.9 随机森林的训练和评估
1.8.9.1 随机森林的训练
在生成Bootstrap子集后,我们需要为每个子集训练一个决策树。我们可以使用Scikit-learn的RandomForestClassifier
来实现这一过程。
示例代码:
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# 设置随机数种子
np.random.seed(42)
# 生成原始数据集
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 定义随机森林模型
rf = RandomForestClassifier(n_estimators=100, random_state=42)
# 训练随机森林模型
rf.fit(X_train, y_train)
# 预测测试集
y_pred = rf.predict(X_test)
# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确性: {accuracy}")
代码解释:
RandomForestClassifier(n_estimators=100, random_state=42)
:定义一个随机森林模型,包含100个决策树。rf.fit(X_train, y_train)
:使用训练集数据训练随机森林模型。y_pred = rf.predict(X_test)
:使用训练好的模型预测测试集。accuracy = accuracy_score(y_test, y_pred)
:计算预测结果的准确性。print(f"模型准确性: {accuracy}")
:输出模型的准确性。
1.8.9.2 随机森林的评估
随机森林的评估通常包括准确性、精确度、召回率和F1分数等指标。我们可以使用Scikit-learn提供的评估函数来计算这些指标。
示例代码:
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
# 设置随机数种子
np.random.seed(42)
# 生成原始数据集
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 定义随机森林模型
rf = RandomForestClassifier(n_estimators=100, random_state=42)
# 训练随机森林模型
rf.fit(X_train, y_train)
# 预测测试集
y_pred = rf.predict(X_test)
# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
print(f"模型准确性: {accuracy}")
print(f"模型精确度: {precision}")
print(f"模型召回率: {recall}")
print(f"模型F1分数: {f1}")
代码解释:
accuracy_score(y_test, y_pred)
:计算预测结果的准确性。precision_score(y_test, y_pred)
:计算预测结果的精确度。recall_score(y_test, y_pred)
:计算预测结果的召回率。f1_score(y_test, y_pred)
:计算预测结果的F1分数。print(f"模型准确性: {accuracy}")
:输出模型的准确性。print(f"模型精确度: {precision}")
:输出模型的精确度。print(f"模型召回率: {recall}")
:输出模型的召回率。print(f"模型F1分数: {f1}")
:输出模型的F1分数。
1.8.10 总结
通过以上内容,我们详细讨论了并行计算中的随机状态管理、蒙特卡洛模拟在投资风险评估和期权定价中的应用、彩票号码生成器的实现,以及随机森林中的数据生成技巧和模型训练与评估方法。这些技术在实际应用中都非常有用,能够帮助我们解决各种涉及随机性和并行计算的问题。
- 并行计算中的随机状态管理:确保每个线程使用独立的随机数生成器,避免随机数序列重复。
- 蒙特卡洛模拟:通过模拟未来可能的情况,评估投资组合的风险或定价金融衍生品。
- 彩票号码生成器:生成一组随机且互不相同的号码,支持多种彩票类型的生成。
- 随机森林:通过Bootstrap方法生成多个不同的子集,训练多个决策树,并集成它们的预测结果,提高模型的准确性和稳定性。
这篇文章包含了详细的原理介绍、代码示例、源码注释以及案例等。希望这对您有帮助。如果有任何问题请随私信或评论告诉我。