Numpy重修系列(一) --- 初识Numpy

一、为什么使用Numpy?

1.1、简介

Python科学计算基础包,提供 多维数组对象 、派生对象(掩码数组、矩阵) 数组的快速操作(数学计算、逻辑、形状变化、排序、选择、输入输出、离散傅里叶变换、基本线性代数、基本统计运算 和 随机模拟 等等)

❓: 要搞清楚的概念:

  • 什么是傅里叶变换?
  • 什么是离散傅里叶变换? 它的用途是什么?
  • 基本基本线性代数、统计学运算和随机模拟 都有什么操作?都有什么用途? 如何和绘图工具将它可视化?

核心:矢量化和广播,加速计算。

Numpy的使用场景

  1. 批处理数据
  2. 机器学习、深度学习中涉及 矩阵、向量 运算
  3. 统计信息后,对格式化数据做批量计算
  4. ......

二、安装Numpy

  1. 直接使用pip命令安装 pip install numpy
  2. 使用conda命令安装 conda install numpy

三、Numpy array 和 Python List的异同

  • 1.在大规模计算上,Numpy数组 速度更快一些。

    import time
    import numpy as np
    
    # 初始化一个Python列表和一个NumPy数组
    l_list = list(range(1000))
    l_array = np.array(l_list)
    
    # 记录开始时间,然后对列表使用map函数进行10000次操作
    l_start = time.time()
    for _ in range(10000):
        l = list(map(lambda i: i+1,l_list))  # 使用map和lambda函数将列表中的每个元素加1
    
    print("Python list with map spend{:.3f}s".format(time.time()-l_start))  # 打印操作所花费的时间
    
    # 记录开始时间,然后对NumPy数组进行10000次加1操作
    l_array_start = time.time()
    
    for _ in range(10000):
        l_array +=1  # NumPy数组的元素整体加1
    print("Numpy array spend {:.3f}s".format(time.time() - l_array_start))  # 打印操作所花费的时间
    
    > Python list with map spend0.221s
    > Numpy array spend 0.006s
    

    Numpy array 使用内存中一块连续的物理地址存储数据 Python list 并不是连续存储的,数据分散在不同的物理空间

    1. Numpy数组 创建时具有固定大小,List 可动态增长 。 更改ndarray 大小 将创建新的数组并删除对原来的数组的引用。
    import numpy as np
    
    # 创建一个固定大小的NumPy数组,形状为(3, 4),元素类型为整数,初始值为0
    fixed_size_array = np.zeros((3, 4), dtype=int)
    
    print(fixed_size_array)
    
    输出:
    [[0 0 0 0]
     [0 0 0 0]
     [0 0 0 0]]
    
    # 创建一个空列表
    dynamic_list = []
    
    # 动态添加元素
    for i in range(5):
        dynamic_list.append(i)
    
    print(dynamic_list)
    
    输出:
    [0, 1, 2, 3, 4]
    
    import numpy as np
    
    # 创建一个初始数组
    initial_array = np.array([1, 2, 3, 4, 5])
    
    print("Initial array:")
    print(initial_array)
    
    # 改变数组大小:创建一个新数组,大小为(2, 7),并用旧数组的元素填充
    new_shape = (2, 7)
    new_array = np.resize(initial_array, new_shape)
    
    print("\\nNew resized array:")
    print(new_array)
    
    # 此时,initial_array 仍存在,但已不再使用,其引用计数减1
    # 若后续无其他引用指向 initial_array,它将在适当时候被垃圾回收机制自动清理
    
  • 3.Numpy数组 数组内元素类型相同 , 内存中的大小相同,目的是确保 内存高效性和矢量运算的便利性。有例外情况:Numpy中包含Python对象

    import numpy as np
    
    # 创建一个NumPy数组,其中每个元素都是一个Python字典
    # 注意:尽管元素是字典,但整个数组仍然具有同一种数据类型,即Python对象类型(object)
    nested_arrays = np.array([{'a': 1, 'b': 2.0}, {'c': 'hello', 'd': (1, 2, 3)}])
    
    print(nested_arrays)
    
    在这个例子中:
    
    创建了一个NumPy数组 nested_arrays,它的每个元素都是一个Python字典。
    虽然这些字典的内容各异(第一个字典包含整数和浮点数,第二个字典包含字符串和一个元组),但它们都被视为Python对象,并且在NumPy数组中统一以dtype=object表示。
    即便如此,每个字典在内存中占用的空间大小可能会不同,因为它们内部包含的数据结构(如整数、浮点数、字符串、元组等)大小可能不一致。
    
    但是,从NumPy数组的角度来看,它只关心每个元素作为一个整体在内存中的起始地址,而不会深入管理元素内部的具体数据结构。
    
    总结来说,当NumPy数组的元素是Python对象(如字典、列表、自定义类实例等)时,虽然从NumPy数组层面看元素具有相同的数据类型(即object),
    但这些Python对象内部可以包含不同大小的数据结构。这可以被视为某种程度上的“例外情况”,
    
    这种做法通常会牺牲NumPy数组的部分性能优势,因为它不再能进行高效的矢量化计算。
    
  • 4.Numpy数组 有大量高级数学和其他操作,这些方法执行效率更高。

    #向量加法
    # Python原生列表
    list_a = [1, 2, 3, 4, 5]
    list_b = [6, 7, 8, 9, 10]
    
    result_list = []
    for i in range(len(list_a)):
        result_list.append(list_a[i] + list_b[i])
    
    print(result_list)  # 输出:[7, 9, 11, 13, 15]
    
    import numpy as np
    
    # NumPy数组
    array_a = np.array([1, 2, 3, 4, 5])
    array_b = np.array([6, 7, 8, 9, 10])
    
    result_array = array_a + array_b
    
    print(result_array)  # 输出:[ 7  9 11 13 15]
    
    #矩阵乘法
    # Python原生列表(矩阵乘法)
    matrix_a = [[1, 2], [3, 4]]
    matrix_b = [[5, 6], [7, 8]]
    
    result_matrix = [[sum(a * b for a, b in zip(row_a, col_b)) for col_b in zip(*matrix_b)] for row_a in matrix_a]
    
    print(result_matrix)  # 输出:[[19, 22], [43, 50]]
    
    import numpy as np
    
    # NumPy数组(矩阵乘法)
    matrix_a = np.array([[1, 2], [3, 4]])
    matrix_b = np.array([[5, 6], [7, 8]])
    
    result_matrix = np.dot(matrix_a, matrix_b)
    
    print(result_matrix)  # 输出:[[19 22]
                         #        [43 50]]
    
    #计算统计量
    # Python原生列表(计算平均值)
    data_list = [1, 2, 3, 4, 5]
    mean = sum(data_list) / len(data_list)
    
    print(mean)  # 输出:3.0
    
    # Python原生列表(计算标准差)
    import math
    
    mean = sum(data_list) / len(data_list)
    variance = sum((x - mean) ** 2 for x in data_list) / len(data_list)
    std_dev = math.sqrt(variance)
    
    print(std_dev)  # 输出:1.4142135623730951
    
    import numpy as np
    
    # NumPy数组(计算平均值和标准差)
    data_array = np.array([1, 2, 3, 4, 5])
    
    mean = np.mean(data_array)
    std_dev = np.std(data_array)
    
    print(mean)  # 输出:3.0
    print(std_dev)  # 输出:1.4142135623730951
    

四、为什么Numpy 这么快?

两个核心: 矢量化 和 广播

矢量化和广播带来的优点:

  • 1.避免显示循环,换句话说就是矢量化替换了原生计算中产生for循环。
data = [1, 2, 3, 4, 5]
squared_data = []
for value in data:
    squared_data.append(value ** 2)
    
#矢量化
import numpy as np

data = np.array([1, 2, 3, 4, 5])
squared_data = data ** 2
  • 2.利用底层优化;

    NumPy库的矢量化操作底层是由C和Fortran等编译型语言实现的高效算法,这些算法能够利用CPU的向量化指令集(如SSE、AVX等)进行并行计算。相较于Python解释器执行的循环,矢量化代码能够大幅减少内存访问次数、减少Python函数调用开销,并利用现代处理器的并行能力,从而获得显著的性能提升。

  • 3.直观的高级数学和统计操作;

    NumPy提供了大量的向量化函数和方法,可以直接对数组进行复杂的数学运算、统计分析、线性代数操作等。

    矢量数学运算:

    统计函数:

    线性代数:

    数据过滤和条件操作:

    • 加减乘除:直接使用Python的算术运算符(+-*/)在NumPy数组上进行操作。
    • 指数、对数:numpy.exp()(指数函数)、numpy.log()(自然对数)、numpy.log10()(以10为底的对数)、numpy.log2()(以2为底的对数)等。
    • 三角函数:numpy.sin()(正弦)、numpy.cos()(余弦)、numpy.tan()(正切)、numpy.arcsin()(反正弦)、numpy.arccos()(反余弦)、numpy.arctan()(反正切)等。还有相应的双曲函数如numpy.sinh()numpy.cosh()numpy.tanh()等。
    • 求和:numpy.sum() 。
    • 平均值:numpy.mean() 。
    • 中位数:numpy.median()
    • 标准差:numpy.std() 。
    • 最大值、最小值:numpy.max() ,numpy.min()
    • 百分位数:numpy.percentile()
    • 矩阵乘法:numpy.dot()(二维数组间的乘法)或 numpy.matmul()(一般化的矩阵乘法,支持广播)。
    • 行列式:numpy.linalg.det()
    • 逆矩阵:numpy.linalg.inv()
    • 特征值与特征向量:numpy.linalg.eig() 或 numpy.linalg.eigh()(对于Hermitian或实对称矩阵)。
    • 奇异值分解:numpy.linalg.svd()
    • 使用布尔数组进行索引:直接使用布尔数组(通常是比较操作的结果)作为索引来提取满足条件的元素,如 arr[arr > threshold]
    • numpy.where():实现三元条件运算,如 numpy.where(condition, x, y),根据condition选择xy的元素构建新数组。
    • 逻辑运算:使用逻辑运算符(&|~)进行元素级别的与、或、非操作,或者使用numpy.logical_and()numpy.logical_or()numpy.logical_not()等函数。
  • 4.广播机制

    广播机制允许不同形状的数组在某些条件下进行有效的元素级运算,无需显式地对较小数组进行复制扩展。

    广播规则允许形状不完全匹配的数组在运算时自动调整其形状以匹配较大的数组,从而简化了数组间运算的代码编写。

    # 向量与标量运算
    import numpy as np
    
    # 一个一维数组(向量)
    vector = np.array([1, 2, 3, 4, 5])
    
    # 一个标量(单个数值)
    scalar = 10
    
    # 直接进行元素级加法运算
    result = vector + scalar
    
    print("向量与标量相加结果:", result)
    #向量与标量相加结果: [11 12 13 14 15]
    
    #长度不同的向量计算
    import numpy as np
    
    # 两个不同长度的一维数组(向量)
    vector1 = np.array([1, 2, 3])
    vector2 = np.array([4, 5, 6, 7, 8])
    
    # 直接进行元素级乘法运算
    try:
        result = vector1 * vector2
    except ValueError as e:
        print("错误:", e)
    
    #错误: operands could not be broadcast together with shapes (3,) (5,) 
    #尝试将长度不同的两个向量进行元素级乘法运算会导致ValueError,因为它们的形状无法进行有效的广播。
    
    #向量与同维数但不同长度的向量运算(合法广播)
    import numpy as np
    
    # 两个不同长度但具有相同维数的一维数组(向量)
    vector1 = np.array([1, 2, 3, 4, 5])
    vector2 = np.array([10, 20, 30])
    
    # 将较短的向量在前面补零,使其长度与较长向量匹配
    vector2_padded = np.pad(vector2, (0, len(vector1) - len(vector2)), 'constant', constant_values=0)
    
    # 元素级乘法运算
    result = vector1 * vector2_padded
    
    print("向量与同维数但不同长度的向量相乘结果(手动补零):", result)
    
    # 使用NumPy广播规则进行相同运算
    print("向量的shape:",vector1.shape,vector2[:, np.newaxis].shape)
    print(vector2[:,np.newaxis])
    result_broadcasted = vector1 * vector2[:, np.newaxis]
    # 注意这里广播机制,[1,2,3,4,5] * [10] 这一个元素,广播成 [1,2,3,4,5] * [10,10,10,10,10]
    print("向量与同维数但不同长度的向量相乘结果(使用广播):", result_broadcasted,"shape:",result_broadcasted.shape)
    
    【输出】:
    向量与同维数但不同长度的向量相乘结果(手动补零): [10 40 90  0  0]
    向量的shape: (5,) (3, 1)
    [[10]
     [20]
     [30]]
    向量与同维数但不同长度的向量相乘结果(使用广播): 
    [[ 10  20  30  40  50]
     [ 20  40  60  80 100]
     [ 30  60  90 120 150]] shape: (3, 5)
    
    import numpy as np
    
    # 两个不同长度但具有相同维数的一维数组(向量)
    vector1 = np.array([[0, 0, 0],
                        [10, 10, 10],
                        [20, 20, 20],
                        [30, 30, 30]])
    vector2 = np.array([0, 1,2])
    
    vector_add = vector1 + vector2
    print(vector_add)
    #输出
    [[ 0  1  2]
     [10 11 12]
     [20 21 22]
     [30 31 32]]
    
  • 5.代码可读性与简洁性

    矢量化代码通常更简洁、更接近数学表达式,增强了代码的可读性和可维护性。例如,矢量化代码可以直观地表达矩阵乘法、卷积、傅立叶变换等复杂操作,而无需关注底层循环细节。

    # 定义两个二维数组(矩阵)
    matrix_A = [[1, 2], [3, 4]]
    matrix_B = [[5, 6], [7, 8]]
    
    # 使用循环实现矩阵乘法
    result_matrix = [[0, 0], [0, 0]]  # 初始化结果矩阵
    for i in range(len(matrix_A)):
        for j in range(len(matrix_B[0])):
            for k in range(len(matrix_B)):
                result_matrix[i][j] += matrix_A[i][k] * matrix_B[k][j]
    
    print(result_matrix)
    
    import numpy as np
    
    # 定义两个二维数组(矩阵)
    matrix_A = np.array([[1, 2], [3, 4]])
    matrix_B = np.array([[5, 6], [7, 8]])
    
    # 使用NumPy的矩阵乘法函数(矢量化操作),直接对应于数学中的矩阵乘法符号 A × B
    result_matrix = np.dot(matrix_A, matrix_B)
    
    print(result_matrix)
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/559241.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据分析案例-中国黄金股票市场的EDA与价格预测

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

【数据结构】单链表经典算法题的巧妙解题思路

目录 题目 1.移除链表元素 2.反转链表 3.链表的中间节点 4.合并两个有序链表 5.环形链表的约瑟夫问题 解析 题目1:创建新链表 题目2:巧用三个指针 题目3:快慢指针 题目4:哨兵位节点 题目5:环形链表 介绍完了…

Activity——spring方式创建activiti所需数据表结构

文章目录 前言依赖引入编写数据库连接等配置配置日志文件编写java代码生成数据库表结构问题反馈与解决思路问题一:Cause: java.sql.SQLSyntaxErrorException: Table activiti_02.act_ge_property doesnt exist 为什么文件名必须写死? 前言 在之前创建ac…

循序渐进丨使用 Python 向 MogDB 数据库批量操作数据的方法

当我们有时候需要向数据库里批量插入数据,或者批量导出数据时,除了使用传统的gsql copy命令,也可以通过Python的驱动psycopg2进行批量操作。本文介绍了使用psycopg2里的executemany、copy_from、copy_to、copy_expert等方式来批量操作 MogDB …

js-pytorch:开启前端+AI新世界

嗨, 大家好, 我是 徐小夕。最近在 github 上发现一款非常有意思的框架—— js-pytorch。它可以让前端轻松使用 javascript 来运行深度学习框架。作为一名资深前端技术玩家, 今天就和大家分享一下这款框架。 往期精彩 Nocode/Doc,可…

python爬虫之爬取携程景点评价(5)

一、景点部分评价爬取 【携程攻略】携程旅游攻略,自助游,自驾游,出游,自由行攻略指南 (ctrip.com) import requests from bs4 import BeautifulSoupif __name__ __main__:url https://m.ctrip.com/webapp/you/commentWeb/commentList?seo0&businessId22176&busines…

“中医显示器”是人体健康监测器

随着科技的进步,现代医学设备已经深入到了人们的日常生活中。然而,在这个过程中,我们不应忘记我们的医学根源,中医。我们将中医的望、闻、问、切四诊与现代科技相结合,通过一系列的传感器和算法将人体的生理状态以数字…

3、MYSQL-一条sql如何在MYSQL中执行的

MySQL的内部组件结构 大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。 Server层 主要包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函…

[Algorithm][滑动窗口][无重复字符的最长字串][最大连续的一个数 Ⅲ][将x减到0的最小操作数]详细讲解

目录 1.无重复字符的最长字串1.题目链接2.算法原理详解3.代码实现 2.最大连续的一个数 Ⅲ1.题目链接2.算法原理详解3.代码实现 3.将x减到0的最小操作数1.题目链接2.算法原理详解3.代码实现 1.无重复字符的最长字串 1.题目链接 无重复字符的最长字串 2.算法原理详解 研究的对…

算法打卡day39

今日任务: 1)卡码网57. 爬楼梯(70. 爬楼梯进阶版) 2)322.零钱兑换 3)279.完全平方数 4)复习day14 卡码网57. 爬楼梯(70. 爬楼梯进阶版) 题目链接:57. 爬楼梯…

数据结构从入门到实战——顺序表的应用

目录 一、基于动态顺序表实现通讯录 二、代码实现 2.1 通讯录的初始化 2.2 通讯录的销毁 2.3 通讯录的展示 2.4 通讯录添加联系人信息 2.5 通讯录删除联系人信息 2.6 通讯录修改联系人信息 2.7 通讯录的查找联系人信息 2.8 将通讯录中联系人信息保存到文件中 2.9…

乡政府管理系统|基于Springboot的乡政府管理系统设计与实现(源码+数据库+文档)

乡政府管理系统目录 目录 基于Springboot的乡政府管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、活动信息管理 3、新闻类型管理 4、新闻动态管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推…

考研党们,搭子们,打打鸡血!刷视频免疫了,时间竟然多了起来!——早读(逆天打工人爬取热门微信文章解读)

断舍离,断的是过去 引言Python 代码第一篇 人民日报 一个班级,29人全部“上岸”! 第二篇 人民日报 来了!新闻早班车要闻社会政策 结尾 时间就像河流 它带来一切 也带走一切 不打游戏不刷视频 时间的河流便能带来更丰富的体验 引言…

PSO-GPR单变量时序预测-递归预测未来数据 基于粒子群算法-高斯过程回归递归预测未来数据

文章目录 效果一览文章概述订阅专栏只能获取一份代码部分源码参考资料效果一览 文章概述 PSO-GPR单变量时序预测-递归预测未来数据 基于粒子群算法-高斯过程回归递归预测未来数据 订阅专栏只能获取一份代码 部分源码 %

Java对象克隆-浅拷贝与深拷贝

目录 1、对象的克隆 1.1 对象的浅拷贝 1.2 对象深拷贝 1、对象的克隆 1.1 对象的浅拷贝 在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B&am…

PyQt程序:实现新版本的自动更新检测及下载(FTP服务器实现)

一、实现逻辑 本实例采用相对简单的逻辑实现,用户在客户端使用软件时点击“检测升级”按钮,连接至FTP服务器检索是否有新版本的.exe,如果有,下载最新的.exe安装升级。 本实例服务端待下载.exe所在目录结构 本实例客户端待更新.exe所在目录结构 二、搭建服务器 可以参考…

springcloud第4季 springcloud-alibaba之sentinel

一 sentinel介绍 1.1 sentinel作用 sentinel是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障服务的稳定性。 1.2 组成部分 sen…

学习Rust的第11天:模块系统

Today we are taking a look at the module system of rust. We can use this to manage growing projects and keep track of what modules is stored where… 今天我们来看看Rust的模块系统。我们可以使用它来管理不断增长的项目,并跟踪 modules 存储在何处。 Rus…

MyBatis使用PageHelper分页插件

1、不使用PageHelper分页插件 模块名:mybatis-012-page CarMapper接口package org.example.mapper;import org.apache.ibatis.annotations.Param; import org.example.pojo.Car;import java.util.List;public interface CarMapper {/*** 分页查询* param startInd…

LLMs之Llama3:Llama 3的简介、安装和使用方法、案例应用之详细攻略

LLMs之Llama3:Llama 3的简介、安装和使用方法、案例应用之详细攻略 导读:2024年4月18日,Meta 重磅推出了Meta Llama 3,本文章主要介绍了Meta推出的新的开源大语言模型Meta Llama 3。模型架构 Llama 3 是一种自回归语言模型&#x…