首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python建模是什么?这个案例教会你

Python建模是什么?这个案例教会你

原创
作者头像
半月无霜
发布2025-12-26 17:52:03
发布2025-12-26 17:52:03
1320
举报
文章被收录于专栏:半月无霜半月无霜

一、介绍

Python建模是指使用Python编程语言创建数学模型来模拟、分析和预测现实世界中的系统或现象。

它包含几个关键方面:

  1. 数学抽象:将现实问题转化为数学表达式或算法
  2. 计算机实现:用代码实现数学模型
  3. 模拟分析:通过运行模型来观察系统行为
  4. 结果可视化:将复杂数据转化为直观图表

今天,我将通过一个经典的随机游走案例,带大家理解建模的本质和应用方法。

如果有100个小球在二项坐标轴的原点,限制如下

  1. 每一分钟可以移动一格单位,
  2. 移动的方向完全随机,上下左右

那么经历一小时后,这些小球会呈现什么样的情况

二、案例实战:随机游走

1)建模思路

这是一个典型的随机游走问题,我们可以用Python来模拟这个过程:

代码语言:javascript
复制
 import random
 import matplotlib.pyplot as plt
 import numpy as np
 ​
 def random_walk_simulation(num_balls=100, minutes=60):
     # 初始化小球位置
     positions = [(0, 0) for _ in range(num_balls)]
     
     # 记录所有时刻的位置
     all_positions = [[(0, 0)] for _ in range(num_balls)]
     
     # 每分钟的移动
     for minute in range(minutes):
         for i in range(num_balls):
             x, y = positions[i]
             # 随机选择方向:0-上,1-下,2-左,3-右
             direction = random.randint(0, 3)
             
             if direction == 0:  # 上
                 y += 1
             elif direction == 1:  # 下
                 y -= 1
             elif direction == 2:  # 左
                 x -= 1
             else:  # 右
                 x += 1
                 
             positions[i] = (x, y)
             all_positions[i].append((x, y))
     
     return positions, all_positions
 ​
 # 执行模拟
 final_positions, history = random_walk_simulation()

2)结果分析

代码语言:javascript
复制
 # 分析最终位置
 x_coords = [pos[0] for pos in final_positions]
 y_coords = [pos[1] for pos in final_positions]
 ​
 # 计算统计信息
 mean_x = np.mean(x_coords)
 mean_y = np.mean(y_coords)
 distance_from_origin = [np.sqrt(x**2 + y**2) for x, y in final_positions]
 mean_distance = np.mean(distance_from_origin)
 ​
 print(f"平均X坐标: {mean_x:.2f}")
 print(f"平均Y坐标: {mean_y:.2f}") 
 print(f"平均距离原点: {mean_distance:.2f}")

3)可视化展示

代码语言:javascript
复制
 # 设置中文字体支持
 plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'Arial Unicode MS']
 plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
 ​
 # 创建三维波形图可视化概率分布
 fig = plt.figure(figsize=(16, 12))
 ​
 # 子图1: 二维原始散点图(对照)
 ax1 = fig.add_subplot(221)
 ax1.scatter(x_coords, y_coords, c='blue', alpha=0.6, s=20)
 ax1.set_xlabel('X')
 ax1.set_ylabel('Y')
 ax1.set_title('二维散点图 - 最终位置')
 ax1.grid(True)
 ax1.axhline(y=0, color='k', linestyle='--', alpha=0.3)
 ax1.axvline(x=0, color='k', linestyle='--', alpha=0.3)
 ​
 # 子图2: 三维概率密度波形图
 ax2 = fig.add_subplot(222, projection='3d')
 ​
 # 创建概率密度网格
 # 确定网格范围(基于数据范围,留有余量)
 x_min, x_max = min(x_coords)-5, max(x_coords)+5
 y_min, y_max = min(y_coords)-5, max(y_coords)+5
 ​
 # 创建网格
 grid_size = 40
 x_grid = np.linspace(x_min, x_max, grid_size)
 y_grid = np.linspace(y_min, y_max, grid_size)
 X, Y = np.meshgrid(x_grid, y_grid)
 Z = np.zeros_like(X)
 ​
 # 计算每个网格点的概率密度(二维高斯核密度估计)
 # 使用小球位置计算局部密度
 bandwidth = 2.0  # 带宽参数
 num_sim_balls = len(final_positions)  # 修正变量名
 ​
 for i in range(grid_size):
     for j in range(grid_size):
         # 计算当前网格点到所有小球的距离
         distances = np.sqrt((X[i,j] - np.array(x_coords))**2 + (Y[i,j] - np.array(y_coords))**2)
         # 高斯核密度估计
         density = np.sum(np.exp(-distances**2 / (2 * bandwidth**2))) / (num_sim_balls * bandwidth * np.sqrt(2 * np.pi))
         Z[i,j] = density
 ​
 # 平滑处理
 Z_smooth = gaussian_filter(Z, sigma=1.5)
 ​
 # 绘制三维波形表面
 surf = ax2.plot_surface(X, Y, Z_smooth, cmap='viridis', alpha=0.9, edgecolor='none', antialiased=True)
 ax2.set_xlabel('X')
 ax2.set_ylabel('Y')
 ax2.set_zlabel('概率密度')
 ax2.set_title('三维概率密度波形')
 fig.colorbar(surf, ax=ax2, shrink=0.6, label='密度')
 ax2.grid(True)
 ​
 # 子图3: 三维概率分布曲面(不同视角)
 ax3 = fig.add_subplot(223, projection='3d')
 ​
 # 使用对数变换增强低密度区域的可见性
 Z_log = np.log1p(Z_smooth)  # log(1+x) 避免log(0)
 ​
 # 绘制平滑的概率分布曲面
 surf3 = ax3.plot_surface(X, Y, Z_log, cmap='plasma', alpha=0.8, 
                         edgecolor='none', antialiased=True)
 ax3.set_xlabel('X')
 ax3.set_ylabel('Y')
 ax3.set_zlabel('log(密度)')
 ax3.set_title('三维概率曲面')
 fig.colorbar(surf3, ax=ax3, shrink=0.6, label='log(密度)')
 ax3.grid(True)
 ​
 # 子图4: 概率密度热图(俯视图)
 ax4 = fig.add_subplot(224)
 im = ax4.imshow(Z_smooth, extent=[x_min, x_max, y_min, y_max], 
                 origin='lower', cmap='hot', alpha=0.8)
 ax4.set_xlabel('X')
 ax4.set_ylabel('Y')
 ax4.set_title('概率密度热俯视图')
 fig.colorbar(im, ax=ax4, shrink=0.7, label='密度')
 ax4.grid(True, alpha=0.3)
 ax4.axhline(y=0, color='white', linestyle='--', alpha=0.5)
 ax4.axvline(x=0, color='white', linestyle='--', alpha=0.5)
 ​
 plt.tight_layout()
 plt.show()
 ​
 # 概率分布统计分析
 print("\n=== 概率分布分析 ===")
 print(f"最大概率密度: {np.max(Z_smooth):.4f}")
 print(f"平均概率密度: {np.mean(Z_smooth):.4f}")
 print(f"密度分布范围: [{np.min(Z_smooth):.4f}, {np.max(Z_smooth):.4f}]")
 ​
 # 计算概率质量中心
 total_mass = np.sum(Z_smooth)
 center_x = np.sum(X * Z_smooth) / total_mass
 center_y = np.sum(Y * Z_smooth) / total_mass
 print(f"概率分布中心: ({center_x:.2f}, {center_y:.2f})")
 ​
 # 计算分布的不确定性(香农熵近似)
 prob_normalized = Z_smooth / total_mass
 entropy = -np.sum(prob_normalized * np.log(prob_normalized + 1e-10))
 print(f"分布熵(不确定性): {entropy:.2f}")

那么运行之后,结果会呈现什么样呢,如下

image-20251226173337744
image-20251226173337744

4)小结

可以看到,小球平均位置仍在原点附近,呈现中间多,四周少的一个分布情况

这种情况可以称为正态分布特征

那么如果小球多点,我们放入1000个小球,并且运动的时间足够长呢,那情况还会一样吗,我们将时间拉长至一天,也就是1440,结果如下

image-20251226174716994
image-20251226174716994

可以看到,有些小球走的更远了,但总体分布情况与上面分析的一致,概率呈现中间高,四周低的分布情况

三、总结

通过这个案例,我们理解了Python建模的基本流程:

  1. 问题抽象:将现实问题转化为算法
  2. 代码实现:用Python编写模拟程序
  3. 结果分析:用统计方法解读数据
  4. 验证理论:与数学理论相互印证

建模的本质是用计算代替推导用模拟代替实验。它让我们能够在计算机上"做实验",快速验证想法,预测结果。

学习建模给我最大的启发是:复杂背后往往有简单的规律。随机游走看似混乱,但统计规律却很清晰。这教会我在面对复杂问题时,要先找最简单的模型入手,逐步深入。

Python建模不需要高深的数学,关键是理解问题本质动手实践。多写代码、多做实验,比死记公式更有用。建议大家从这类简单案例开始,培养建模思维,为解决更复杂的问题打基础。

记住:好的模型不是最复杂的,而是能抓住问题核心的

我是半月,祝你编码愉快!!!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、介绍
  • 二、案例实战:随机游走
    • 1)建模思路
    • 2)结果分析
    • 3)可视化展示
    • 4)小结
  • 三、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档