构建AI智能体:AI数据科学NumPy — 不可不知、由点及面抽丝剥茧+趣味范例

絕刀狂花
发布: 2025-11-26 18:06:05
原创
703人浏览过

numpy(numerical python)是 python 科学计算生态系统的核心库,提供了高性能的多维数组对象和用于处理这些数组的工具。如:矩阵数据类型、矢量处理,以及精密的运算库。它是几乎所有数据科学、机器学习和科学计算库的基础。广泛应用于数据分析、机器学习等领域,是 pandas 、 scikit-learn 等库的基础。

下图是NumPy通过蒙特卡洛方法估算圆周率π,并提供详细的代码实现和可视化,感兴趣可在后文根据详细注解一探究竟;

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

构建AI智能体:AI数据科学NumPy — 不可不知、由点及面抽丝剥茧+趣味范例

一、NumPy的优势

1. 与Python 列表的比较

与Python列表的比较,直观体现性能优势:

<code class="javascript">import numpy as npimport time# Python 列表的性能问题python_list = list(range(1000000))start_time = time.time()result = [x * 2 for x in python_list]end_time = time.time()print(f"Python列表计算时间: {end_time - start_time:.6f}秒")# NumPy 数组的性能优势numpy_array = np.arange(1000000)start_time = time.time()result = numpy_array * 2end_time = time.time()print(f"NumPy数组计算时间: {end_time - start_time:.6f}秒")</code>
登录后复制

结果展示:

<code class="javascript">Python列表计算时间: 0.045234秒NumPy数组计算时间: 0.001567秒</code>
登录后复制

2、主要优势

由于底层用 C 语言实现,运算速度极快 数组元素在内存中连续存储,效率极高 向量化操作,避免显式循环,一次操作整个数组 广播机制,处理不同形状的数组之间的逐元素运算 丰富的数学函数、线性代数、随机数生成等

二、由浅入深、循序渐进

1. 核心对象:ndarray

1.1 创建数组

<code class="javascript">import numpy as np# 从列表创建arr1 = np.array([1, 2, 3, 4, 5])print("从列表创建:", arr1)# 创建特殊数组zeros = np.zeros((3, 4))        # 全0数组ones = np.ones((2, 3))          # 全1数组empty = np.empty((2, 2))        # 未初始化数组full = np.full((2, 2), 7)       # 填充指定值identity = np.eye(3)            # 单位矩阵print("全0数组:", zeros)print("单位矩阵:", identity)# 创建序列数组range_arr = np.arange(0, 10, 2)  # 类似range,但返回数组linear_arr = np.linspace(0, 1, 5)  # 等间隔数列random_arr = np.random.rand(3, 3)  # 随机数组print("arange创建:", range_arr)print("linspace创建:", linear_arr)print("随机数组:", random_arr)</code>
登录后复制

输出结果:​​​​​​

<code class="javascript">从列表创建: [1 2 3 4 5]全0数组: [[0. 0. 0. 0.] [0. 0. 0. 0.] [0. 0. 0. 0.]]单位矩阵: [[1. 0. 0.] [0. 1. 0.] [0. 0. 1.]]arange创建: [0 2 4 6 8]linspace创建: [0.   0.25 0.5  0.75 1.  ]随机数组: [[0.39898071 0.38841929 0.25706792] [0.4805703  0.79778008 0.96680553] [0.75744912 0.35779339 0.96884091]]</code>
登录后复制

1.2 数组属性

<code class="javascript">import numpy as np# 创建一个示例数组arr = np.array([[1, 2, 3], [4, 5, 6]])print("数组:", arr)print("形状:", arr.shape)        # 数组维度print("大小:", arr.size)         # 元素总数print("维度:", arr.ndim)         # 轴的数量print("数据类型:", arr.dtype)    # 元素类型print("每个元素字节数:", arr.itemsize)print("总字节数:", arr.nbytes)</code>
登录后复制

输出结果:

<code class="javascript">组: [[1 2 3] [4 5 6]]形状: (2, 3)大小: 6维度: 2数据类型: int32每个元素字节数: 4总字节数: 24</code>
登录后复制

2. 数组操作

2.1 索引和切片

<code class="javascript">import numpy as np# 创建示例数组arr = np.arange(1, 13).reshape(3, 4)print("原始数组:", arr)# 基本索引print("第一个元素:", arr[0, 0])print("第一行:", arr[0])print("第一列:", arr[:, 0])# 切片操作print("前两行:", arr[:2])print("后两列:", arr[:, -2:])print("子数组:", arr[1:3, 1:3])# 布尔索引bool_mask = arr > 5print("布尔掩码:", bool_mask)print("大于5的元素:", arr[bool_mask])# 花式索引print("选择特定行:", arr[[0, 2]])print("选择特定列:", arr[:, [1, 3]])</code>
登录后复制

输出结果:

<code class="javascript">始数组: [[ 1  2  3  4] [ 5  6  7  8] [ 9 10 11 12]]第一个元素: 1第一行: [1 2 3 4]第一列: [1 5 9]前两行: [[1 2 3 4] [5 6 7 8]]后两列: [[ 3  4] [ 7  8] [11 12]]子数组: [[ 6  7] [10 11]]布尔掩码: [[False False False False] [False  True  True  True] [ True  True  True  True]]大于5的元素: [ 6  7  8  9 10 11 12]选择特定行: [[ 1  2  3  4] [ 9 10 11 12]]选择特定列: [[ 2  4] [ 6  8] [10 12]]</code>
登录后复制

2.2 形状操作

<code class="javascript">import numpy as nparr = np.arange(12)print("一维数组:", arr)# 改变形状reshaped = arr.reshape(3, 4)print("重塑为3x4:", reshaped)# 展平数组flattened = reshaped.flatten()print("展平:", flattened)# 转置transposed = reshaped.Tprint("转置:", transposed)# 增加/减少维度expanded = np.expand_dims(arr, axis=0)print("增加维度:", expanded.shape)squeezed = np.squeeze(expanded)print("压缩维度:", squeezed.shape)</code>
登录后复制

输出结果:

<code class="javascript">维数组: [ 0  1  2  3  4  5  6  7  8  9 10 11]重塑为3x4: [[ 0  1  2  3] [ 4  5  6  7] [ 8  9 10 11]]展平: [ 0  1  2  3  4  5  6  7  8  9 10 11]转置: [[ 0  4  8] [ 1  5  9] [ 2  6 10] [ 3  7 11]]增加维度: (1, 12)压缩维度: (12,)</code>
登录后复制

3. 数组运算

3.1 数学运算

<code class="javascript">import numpy as npa = np.array([1, 2, 3])b = np.array([4, 5, 6])# 算术运算print("加法:", a + b)print("减法:", a - b)print("乘法:", a * b)    # 元素乘法,不是矩阵乘法print("除法:", a / b)print("幂运算:", a ** 2)# 比较运算print("相等:", a == b)print("大于:", a > 2)# 聚合函数print("总和:", np.sum(a))print("均值:", np.mean(a))print("标准差:", np.std(a))print("最大值:", np.max(a))print("最小值:", np.min(a))# 三角函数angles = np.array([0, np.pi/2, np.pi])print("正弦值:", np.sin(angles))</code>
登录后复制

输出结果:

<code class="javascript">法: [5 7 9]减法: [-3 -3 -3]乘法: [ 4 10 18]除法: [0.25 0.4  0.5 ]幂运算: [1 4 9]相等: [False False False]大于: [False False  True]总和: 6均值: 2.0标准差: 0.816496580927726最大值: 3最小值: 1正弦值: [0.0000000e+00 1.0000000e+00 1.2246468e-16]</code>
登录后复制

3.2 广播机制

<code class="javascript">import numpy as np# 标量与数组arr = np.array([[1, 2, 3], [4, 5, 6]])print("数组 + 标量:", arr + 10)# 不同形状数组vector = np.array([10, 20, 30])print("数组 + 向量:", arr + vector)# 广播规则示例a = np.array([[1], [2], [3]])  # 形状 (3, 1)b = np.array([10, 20, 30])     # 形状 (3,)print("广播加法:", a + b)</code>
登录后复制

输出结果:

<code class="javascript">数组 + 标量: [[11 12 13] [14 15 16]]数组 + 向量: [[11 22 33] [14 25 36]]广播加法: [[11 21 31] [12 22 32] [13 23 33]]</code>
登录后复制

4. 实用功能

4.1 文件操作

<code class="javascript">import numpy as np# 创建示例数据data = np.random.rand(5, 3)# 保存到文件np.savetxt('data.txt', data, delimiter=',')# 从文件加载loaded_data = np.loadtxt('data.txt', delimiter=',')print("从文件加载的数据:", loaded_data)# 二进制格式(更高效)np.save('data.npy', data)binary_loaded = np.load('data.npy')print("二进制加载的数据:", binary_loaded)</code>
登录后复制

输出结果:

<code class="javascript">从文件加载的数据: [[0.4553778  0.49906932 0.97523208] [0.35906304 0.55012335 0.38348623] [0.29169913 0.90129311 0.22774977] [0.97325678 0.32749914 0.85698094] [0.82758157 0.36911462 0.42524159]]二进制加载的数据: [[0.4553778  0.49906932 0.97523208] [0.35906304 0.55012335 0.38348623] [0.29169913 0.90129311 0.22774977] [0.97325678 0.32749914 0.85698094] [0.82758157 0.36911462 0.42524159]]</code>
登录后复制

4.2 随机数生成

<code class="javascript">import numpy as np# 设置随机种子(确保可重复性)np.random.seed(42)# 生成随机数uniform = np.random.rand(5)          # [0,1)均匀分布normal = np.random.randn(5)          # 标准正态分布integers = np.random.randint(0, 10, 5)  # 随机整数print("均匀分布:", uniform)print("正态分布:", normal)print("随机整数:", integers)# 随机抽样choices = np.random.choice(['A', 'B', 'C'], size=10, p=[0.5, 0.3, 0.2])print("随机选择:", choices)</code>
登录后复制

输出结果:

<code class="javascript">匀分布: [0.37454012 0.95071431 0.73199394 0.59865848 0.15601864]正态分布: [ 0.27904129  1.01051528 -0.58087813 -0.52516981 -0.57138017]随机整数: [5 8 0 9 2]随机选择: ['A' 'C' 'A' 'C' 'B' 'A' 'A' 'C' 'B' 'A']</code>
登录后复制

5. 基础应用示例

5.1 数据处理

<code class="javascript">import numpy as np# 创建示例数据集data = np.array([    [1, 2, 3, 4],    [5, 6, 7, 8],    [9, 10, 11, 12]])# 数据筛选filtered = data[data > 5]print("大于5的值:", filtered)# 条件修改data[data % 2 == 0] = -1  # 将所有偶数改为-1print("修改后的数据:", data)# 数据统计print("每列均值:", np.mean(data, axis=0))print("每行最大值:", np.max(data, axis=1))</code>
登录后复制

输出结果:

<code class="javascript">大于5的值: [ 6  7  8  9 10 11 12]修改后的数据: [[ 1 -1  3 -1] [ 5 -1  7 -1] [ 9 -1 11 -1]]每列均值: [ 5. -1.  7. -1.]每行最大值: [ 3  7 11]</code>
登录后复制

5.2 简单图形处理

<code class="javascript">import numpy as np# 模拟一个灰度图像(10x10像素)image = np.random.randint(0, 256, (10, 10))print("原始图像数据:", image)# 图像处理操作brightened = np.clip(image + 50, 0, 255)  # 增加亮度inverted = 255 - image                    # 颜色反转threshold = (image > 128).astype(int)     # 二值化print("亮度增强:", brightened)print("颜色反转:", inverted)print("二值化:", threshold)</code>
登录后复制

输出结果:

<code class="javascript"> 始图像数据: [[ 23 218 156  90 149 255 116 104   8  60] [ 70  42  74 180 227  17 189  92  11  90] [207  61 110 223  21 153  47 136  20 225] [  8  93 153  81  81  14 112 107 249  50] [160 149  95  60 214 233 149 247 127   7] [140 183  32  82 247 128 174  16  44 212] [ 34 203 210  89  98  59  48 200 181 111] [111  23  99 101 108 130  65 215 123 205] [170  93 210  84 230 213  82 126  87 247] [187 250   8 157  78  54  54 227  89 164]]亮度增强: [[ 73 255 206 140 199 255 166 154  58 110] [120  92 124 230 255  67 239 142  61 140] [255 111 160 255  71 203  97 186  70 255] [ 58 143 203 131 131  64 162 157 255 100] [210 199 145 110 255 255 199 255 177  57] [190 233  82 132 255 178 224  66  94 255] [ 84 253 255 139 148 109  98 250 231 161] [161  73 149 151 158 180 115 255 173 255] [220 143 255 134 255 255 132 176 137 255] [237 255  58 207 128 104 104 255 139 214]]颜色反转: [[232  37  99 165 106   0 139 151 247 195] [185 213 181  75  28 238  66 163 244 165] [ 48 194 145  32 234 102 208 119 235  30] [247 162 102 174 174 241 143 148   6 205] [ 95 106 160 195  41  22 106   8 128 248] [115  72 223 173   8 127  81 239 211  43] [221  52  45 166 157 196 207  55  74 144] [144 232 156 154 147 125 190  40 132  50] [ 85 162  45 171  25  42 173 129 168   8] [ 68   5 247  98 177 201 201  28 166  91]]二值化: [[0 1 1 0 1 1 0 0 0 0] [0 0 0 1 1 0 1 0 0 0] [1 0 0 1 0 1 0 1 0 1] [0 0 1 0 0 0 0 0 1 0] [1 1 0 0 1 1 1 1 0 0] [1 1 0 0 1 0 1 0 0 1] [0 1 1 0 0 0 0 1 1 0] [0 0 0 0 0 1 0 1 0 1] [1 0 1 0 1 1 0 0 0 1] [1 1 0 1 0 0 0 1 0 1]]</code>
登录后复制

6. 性能调优和错误处理

6.1 性能优化

<code class="javascript">import numpy as np# 不好的做法:使用Python循环def slow_sum(arr):    result = 0    for x in arr:        result += x    return result# 好的做法:使用NumPy向量化操作def fast_sum(arr):    return np.sum(arr)# 测试性能large_arr = np.random.rand(1000000)import timestart = time.time()slow_result = slow_sum(large_arr)end = time.time()print(f"循环求和: {end - start:.6f}秒")start = time.time()fast_result = fast_sum(large_arr)end = time.time()print(f"向量化求和: {end - start:.6f}秒")</code>
登录后复制

输出结果:

<code class="javascript">循环求和: 0.471191秒向量化求和: 0.003989秒</code>
登录后复制

6.2 常见错误

<code class="javascript">import numpy as np# 错误:视图 vs 副本arr = np.array([1, 2, 3, 4])view = arr[1:3]    # 这是视图,修改会影响原数组copy = arr[1:3].copy()  # 这是副本,独立于原数组view[0] = 999print("原数组被修改:", arr)  # [1, 999, 3, 4]copy[0] = 888print("原数组不变:", arr)    # [1, 999, 3, 4]# 正确使用数据类型float_arr = np.array([1, 2, 3], dtype=np.float64)int_arr = np.array([1.5, 2.7, 3.1], dtype=np.int32)  # 注意会截断print("浮点数组:", float_arr)print("整数数组:", int_arr)  # [1, 2, 3]</code>
登录后复制

输出结果:

<code class="javascript">原数组被修改: [  1 999   3   4]原数组不变: [  1 999   3   4]浮点数组: [1. 2. 3.]整数数组: [1 2 3]</code>
登录后复制

6.3 小结

数组创建:np.array(), np.zeros(), np.ones(), np.arange(), np.linspace() 数组属性:.shape, .dtype, .ndim 索引和切片:基本索引、布尔索引、花式索引 数组操作:reshape(), concatenate(), stack() 数学运算:向量化运算、广播机制 通用函数:np.sin(), np.exp(), np.sqrt()等 线性代数:np.dot(), np.linalg.norm()

三、趣味示例

1. 井字棋游戏 - 理解二维数组

<code class="javascript"> import numpy as np# 创建游戏棋盘def create_board():    """    创建一个3x3的井字棋棋盘,初始状态为全0    返回值: 3x3的NumPy数组,数据类型为整数    0表示空位,1表示玩家X,2表示玩家O    """    # np.zeros((3, 3), dtype=int) 创建一个3行3列的全0数组    return np.zeros((3, 3), dtype=int)# 打印棋盘(美化输出)def print_board(board):    """    将数字表示的棋盘转换为可视化的字符格式并打印    参数:    board: 3x3的NumPy数组,表示当前棋盘状态    """    # 定义数字到符号的映射字典    # 0 -> 空格, 1 -> 'X', 2 -> 'O'    symbols = {0: ' ', 1: 'X', 2: 'O'}    # 遍历每一行    for i in range(3):        # 将当前行的数字转换为对应的符号        row = [symbols[board[i, j]] for j in range(3)]        # 使用' | '连接符号并打印,前面加空格使输出居中        print(' ' + ' | '.join(row))        # 如果不是最后一行,打印分隔线        if i < 2:            print('-----------')    print()  # 打印空行使输出更清晰# 检查胜利条件def check_win(board, player):    """    检查指定玩家是否获胜    参数:    board: 3x3的NumPy数组,表示当前棋盘状态    player: 整数,1表示玩家X,2表示玩家O    返回值:    布尔值,True表示该玩家获胜,False表示未获胜    """    # 检查所有行是否有获胜情况    # np.all() 检查给定轴上的所有元素是否为True    for i in range(3):        # 检查第i行是否全部由当前玩家的棋子占据        if np.all(board[i, :] == player):            return True    # 检查所有列是否有获胜情况    for j in range(3):        # 检查第j列是否全部由当前玩家的棋子占据        if np.all(board[:, j] == player):            return True    # 检查两条对角线是否有获胜情况    # np.diag() 获取矩阵的主对角线元素    # np.fliplr() 左右翻转矩阵,然后获取对角线即为反对角线    if np.all(np.diag(board) == player) or np.all(np.diag(np.fliplr(board)) == player):        return True    # 如果以上条件都不满足,则该玩家未获胜    return False# 游戏演示# 创建初始棋盘board = create_board()print("初始棋盘:")print_board(board)# 模拟几步游戏# 玩家X在左上角(0,0)位置落子board[0, 0] = 1  # X 在左上角# 玩家O在中心(1,1)位置落子board[1, 1] = 2  # O 在中心# 玩家X在上中(0,1)位置落子board[0, 1] = 1  # X 在上中print("游戏进行中:")print_board(board)# 检查玩家X是否获胜print("X 是否获胜?", check_win(board, 1))</code>
登录后复制

输出结果:

<code class="javascript">初始棋盘:   |   |  -----------   |   |-----------   |   |游戏进行中: X | X |-----------   | O |-----------   |   |X 是否获胜? False</code>
登录后复制

体现的知识点

np.zeros() 创建数组 二维数组索引 board[i, j] np.all() 检查所有元素是否满足条件 np.diag() 获取对角线元素 np.fliplr() 左右翻转数组

2. 蒙特卡洛方法估算π的动态可视化

<code class="javascript">import numpy as npimport matplotlib.pyplot as pltimport timefrom matplotlib.animation import FuncAnimationdef animated_monte_carlo(n_samples=10000, frame_interval=100):    """    创建蒙特卡洛方法估算π的动态可视化    参数:    n_samples: 总采样点数,默认10000个点    frame_interval: 每帧更新的点数,默认每100个点更新一次动画    返回:    matplotlib.animation.FuncAnimation对象,用于控制动画    """    # 生成所有随机点:在[-1, 1] x [-1, 1]的正方形区域内均匀采样    # points是一个n_samples x 2的数组,每行代表一个点的(x,y)坐标    points = np.random.uniform(-1, 1, size=(n_samples, 2))    # 计算每个点到原点(0,0)的距离    # 使用欧几里得距离公式:sqrt(x² + y²)    distances = np.sqrt(points[:, 0]**2 + points[:, 1]**2)    # 创建图形窗口,包含左右两个子图    # 左图显示随机点和单位圆,右图显示π估计值的收敛过程    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))    # 初始化左图的散点图(开始时没有点)    scatter = ax1.scatter([], [], s=1, alpha=0.5)  # 小点,半透明    ax1.set_xlim(-1, 1)    # 设置x轴范围    ax1.set_ylim(-1, 1)    # 设置y轴范围    ax1.set_aspect('equal') # 保持纵横比相等,确保圆看起来是圆形    # 在左图绘制单位圆(半径为1的圆)    # 这个圆用于可视化:圆内的点表示落在单位圆内    circle = plt.Circle((0, 0), 1, color='green', fill=False, linewidth=2)    ax1.add_patch(circle)  # 将圆添加到图中    # 初始化右图的收敛曲线(开始时没有数据)    line, = ax2.plot([], [], linewidth=1)    # 在右图添加一条水平线表示π的真实值    ax2.axhline(y=np.pi, color='r', linestyle='--', label='True π')    ax2.set_xlim(0, n_samples)  # 设置x轴范围(点数)    ax2.set_ylim(2.8, 3.4)      # 设置y轴范围(π的估计值范围)    ax2.set_xlabel('Number of points')    # x轴标签    ax2.set_ylabel('Estimate of π')       # y轴标签    ax2.set_title('Convergence of π Estimate')  # 右图标题    ax2.legend()    # 显示图例    ax2.grid(True)  # 显示网格    # 在左图添加文本框,显示当前点数、π估计值和误差    text = ax1.text(0.05, 0.95, '', transform=ax1.transAxes, fontsize=12,                   verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8))    # 动画更新函数 - 每一帧调用一次    def update(frame):        # 计算当前帧应该显示的点数        # 每frame_interval个点更新一次,但不超过总点数n_samples        n = min((frame + 1) * frame_interval, n_samples)        # 更新左图的散点图        # 确定哪些点落在单位圆内(距离<=1)        inside = distances[:n] <= 1        # 落在圆外的点        outside = ~inside  # 逻辑非操作        # 创建颜色数组:圆内的点为蓝色,圆外的点为红色        colors = np.empty(n, dtype=object)  # 创建空对象数组        colors[inside] = 'blue'   # 圆内的点设为蓝色        colors[outside] = 'red'   # 圆外的点设为红色        # 更新散点图的位置和颜色        scatter.set_offsets(points[:n])  # 设置点的位置        scatter.set_color(colors)        # 设置点的颜色        # 更新右图的收敛曲线        # 计算累积落在圆内的点数(使用累积和)        cumulative_inside = np.cumsum(inside)        # 计算π的估计值:4 * (圆内点数 / 总点数)        # 根据公式:π ≈ 4 * (圆内点数 / 总点数)        cumulative_estimate = 4 * cumulative_inside / (np.arange(n) + 1)        # 更新收敛曲线的数据        line.set_data(np.arange(n), cumulative_estimate)        # 更新文本信息        # 获取当前的π估计值(最后一个值)        current_estimate = cumulative_estimate[-1] if n > 0 else 0        # 设置文本内容:点数、估计值和误差        text.set_text(f'Points: {n:,}Estimate: {current_estimate:.6f}Error: {abs(current_estimate - np.pi):.6f}')        # 返回需要更新的图形元素        return scatter, line, text    # 计算总帧数:总点数除以每帧更新的点数    frames = n_samples // frame_interval    # 创建动画对象    # fig: 动画所在的图形    # update: 更新函数    # frames: 总帧数    # interval: 帧间隔时间(毫秒)    # blit: 使用blitting技术优化动画(只重绘变化的部分)    ani = FuncAnimation(fig, update, frames=frames, interval=50, blit=True)    # 调整子图布局,避免重叠    plt.tight_layout()    # 显示动画    plt.show()    # 返回动画对象,以便后续控制(如保存为视频)    return ani# 运行动画# 使用10000个点,每100个点更新一次动画ani = animated_monte_carlo(n_samples=10000, frame_interval=100)</code>
登录后复制
基本原理

这段代码实现了使用蒙特卡洛方法估算π值的动态可视化,其数学原理如下:

基本思想:在一个边长为2的正方形内随机撒点,统计落在内切圆(半径为1)内的点数 面积关系: 正方形面积 = 2 × 2 = 4 圆形面积 = π × 1² = π 概率估计:点在圆内的概率 = 圆形面积 / 正方形面积 = π/4 π估算公式:π ≈ 4 × (圆内点数 / 总点数) 代码亮点解析 向量化计算:使用NumPy一次性生成所有随机点并计算距离,避免了低效的Python循环 动态可视化:使用Matplotlib的动画功能实时展示估算过程 双视图设计:左侧显示随机点分布,右侧显示π估计值的收敛过程 性能优化: 使用blit=True只重绘变化的部分,提高动画性能 分批更新点(每100个点更新一次),平衡视觉效果和性能 信息丰富:实时显示当前点数、π估计值和误差,方便观察收敛过程

3. 图像滤镜 - 理解数组运算

构建AI智能体:AI数据科学NumPy — 不可不知、由点及面抽丝剥茧+趣味范例
<code class="javascript">import numpy as npfrom PIL import Imageimport matplotlib.pyplot as plt# 设置中文字体支持# 确保图表中的中文标题能够正确显示plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体显示中文plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题# 创建简单的测试图像def create_test_image():    """    创建一个自定义的渐变测试图像,用于演示图像处理效果    返回:    一个100x100像素的RGB图像,数据类型为uint8(0-255范围)    """    # 创建从0到1的等间距数组,用于x和y坐标    x = np.linspace(0, 1, 100)  # 100个点,从0到1    y = np.linspace(0, 1, 100)  # 100个点,从0到1    # 创建网格坐标矩阵    # xx的每一行都是x的复制,yy的每一列都是y的复制    xx, yy = np.meshgrid(x, y)    # 创建RGB三个通道的渐变效果    red = xx        # 红色通道:水平渐变(从左到右增强)    green = yy      # 绿色通道:垂直渐变(从下到上增强)    blue = (xx + yy) / 2  # 蓝色通道:对角线渐变(从右下到左上增强)    # 将三个通道堆叠成三维数组(高度×宽度×通道)    # 然后缩放到0-255范围并转换为8位无符号整数    image = np.stack([red, green, blue], axis=2)    return (image * 255).astype(np.uint8)# 定义彩虹色条纹的颜色值(RGB格式,范围0-1)colors = [    [1, 0, 0],    # 红色    [1, 0.5, 0],  # 橙色    [1, 1, 0],    # 黄色    [0, 1, 0],    # 绿色    [0, 0, 1],    # 蓝色    [0.5, 0, 0.5],# 紫色]# 创建彩虹色条纹图像def create_rainbow_stripes(size=100):    """    创建一个彩虹色条纹图像    参数:    size: 图像的大小(将创建size×size的正方形图像)    返回:    一个包含彩虹色条纹的RGB图像    """    # 创建一个全零的三维数组(高度×宽度×3个颜色通道)    image = np.zeros((size, size, 3))    # 计算每个条纹的宽度(将图像水平分成6等份)    stripe_width = size // len(colors)    # 填充彩虹色条纹    for i, color in enumerate(colors):        # 计算当前条纹的起始和结束列索引        start = i * stripe_width        end = (i + 1) * stripe_width if i < len(colors) - 1 else size        # 将当前条纹的所有行和指定列范围设置为当前颜色        image[:, start:end] = color    return image# 应用各种滤镜def apply_filters(image):    """    对输入图像应用多种滤镜效果    参数:    image: 输入图像(NumPy数组,uint8类型,0-255范围)    返回:    四个处理后的图像:灰度图、边缘检测图、颜色反转图、sepia色调图    """    # 将图像转换为浮点数并归一化到0-1范围,便于数学运算    img_float = image.astype(float) / 255.0    # 1. 灰度化:将彩色图像转换为灰度图像    # 方法:取RGB三个通道的平均值    gray = np.mean(img_float, axis=2)    # 2. 边缘检测(使用简化的Sobel算子)    # 定义Sobel算子的x方向和y方向卷积核    sobel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])  # 水平边缘检测    sobel_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])  # 垂直边缘检测    # 初始化边缘强度图    edges = np.zeros_like(gray)    # 对每个颜色通道分别应用Sobel算子    for i in range(3):        # 获取当前颜色通道        channel = img_float[:, :, i]        # 使用卷积计算x方向和y方向的梯度        # 注意:这里使用了一维卷积,需要先将二维数组展平        gx = np.abs(np.convolve(channel.flatten(), sobel_x.flatten(), mode='same').reshape(channel.shape))        gy = np.abs(np.convolve(channel.flatten(), sobel_y.flatten(), mode='same').reshape(channel.shape))        # 计算梯度幅值并累加到边缘图中        edges += np.sqrt(gx**2 + gy**2)    # 对三个通道的结果取平均    edges = edges / 3.0    # 3. 颜色反转:用1减去每个像素值,实现颜色反转效果    inverted = 1.0 - img_float    # 4. Sepia色调(棕褐色调效果)    # 定义Sepia色调的转换矩阵    sepia_matrix = np.array([[0.393, 0.769, 0.189],   # 红色分量转换系数                           [0.349, 0.686, 0.168],     # 绿色分量转换系数                           [0.272, 0.534, 0.131]])    # 蓝色分量转换系数    # 应用矩阵乘法实现颜色转换    sepia = np.dot(img_float, sepia_matrix.T)    # 确保值在0-1范围内(使用np.clip防止溢出)    sepia = np.clip(sepia, 0, 1)    return gray, edges, inverted, sepia# 创建并处理图像# 生成测试图像image = create_test_image()# 应用各种滤镜gray, edges, inverted, sepia = apply_filters(image)# 创建彩虹色条纹图像rainbow_image = create_rainbow_stripes()# 显示结果# 创建2行3列的子图布局fig, axes = plt.subplots(2, 3, figsize=(15, 10))# 第一行第一列:原始图像axes[0, 0].imshow(image)axes[0, 0].set_title('原始图像')axes[0, 0].axis('off')  # 隐藏坐标轴# 第一行第二列:灰度化效果axes[0, 1].imshow(gray, cmap='gray')  # 使用灰度颜色映射axes[0, 1].set_title('灰度化')axes[0, 1].axis('off')# 第一行第三列:边缘检测效果axes[0, 2].imshow(edges, cmap='hot')  # 使用热力图颜色映射axes[0, 2].set_title('边缘检测')axes[0, 2].axis('off')# 第二行第一列:颜色反转效果axes[1, 0].imshow(inverted)axes[1, 0].set_title('颜色反转')axes[1, 0].axis('off')# 第二行第二列:Sepia色调效果axes[1, 1].imshow(sepia)axes[1, 1].set_title('Sepia色调')axes[1, 1].axis('off')# 第二行第三列:彩虹条纹图像axes[1, 2].imshow(rainbow_image)axes[1, 2].set_title('彩虹条纹')axes[1, 2].axis('off')# 自动调整子图参数,使之填充整个图像区域plt.tight_layout()# 显示图形plt.show()</code>
登录后复制

体现的知识点

数组创建和形状操作 数学运算和广播 数组索引和切片 np.convolve() 卷积操作 np.clip() 限制数值范围 np.dot() 矩阵乘法

代码技术亮点

数组操作: 使用np.linspace, np.meshgrid创建坐标网格 广播机制: 在创建渐变图像时利用了NumPy的广播功能 矩阵运算: 在Sepia滤镜中使用矩阵乘法实现颜色转换 卷积操作: 在边缘检测中使用卷积计算图像梯度 数组索引和切片: 在创建彩虹条纹时使用切片操作高效赋值

四、总结

操作

代码示例

说明

创建数组

np.array([1,2,3])

从列表创建

全零数组

Elser AI Comics
Elser AI Comics

一个免费且强大的AI漫画生成工具,助力你三步创作自己的一出好戏

Elser AI Comics 522
查看详情 Elser AI Comics

np.zeros((3,3))

创建全0数组

全一数组

np.ones((2,2))

创建全1数组

范围数组

np.arange(0,10,2)

创建等差数组

随机数组

np.random.rand(3,3)

创建随机数组

改变形状

arr.reshape(2,3)

改变数组形状

数组拼接

np.concatenate([a,b])

连接数组

数学运算

arr + 1, arr * 2

向量化运算

统计函数

np.mean(arr), np.std(arr)

统计计算

以上就是构建AI智能体:AI数据科学NumPy — 不可不知、由点及面抽丝剥茧+趣味范例的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号