专栏首页华章科技Python必备基础:这些NumPy的神操作你都掌握了吗?

Python必备基础:这些NumPy的神操作你都掌握了吗?

导读:NumPy是Python的基础,更是数据科学的通用语言。

本文简单介绍NumPy模块的两个基本对象ndarray、ufunc,介绍ndarray对象的几种生成方法及如何存取其元素、如何操作矩阵或多维数组、如何进行数据合并与展平等。最后说明通用函数及广播机制。

作者:吴茂贵,王冬,李涛,杨本法

如需转载请联系大数据(ID:hzdashuju)

NumPy为何如此重要?实际上Python本身含有列表(list)和数组(array),但对于大数据来说,这些结构有很多不足。因列表的元素可以是任何对象,因此列表中所保存的是对象的指针。这样为了保存一个简单的[1,2,3],都需要有3个指针和3个整数对象。

对于数值运算来说,这种结构显然比较浪费内存和CPU计算时间。至于array对象,它直接保存数值,和C语言的一维数组比较类似。但是由于它不支持多维,也没有各种运算函数,因此也不适合做数值运算。

NumPy(Numerical Python 的简称)的诞生弥补了这些不足,它提供了两种基本的对象:ndarray(N-dimensional array object)和 ufunc(universal function object)。ndarray是存储单一数据类型的多维数组,而ufunc则是能够对数组进行处理的函数。

NumPy的主要特点:

  • ndarray,快速,节省空间的多维数组,提供数组化的算术运算和高级的广播功能。
  • 使用标准数学函数对整个数组的数据进行快速运算,而不需要编写循环。
  • 读取/写入磁盘上的阵列数据和操作存储器映像文件的工具。
  • 线性代数,随机数生成,以及傅里叶变换的能力。
  • 集成C、C++、Fortran代码的工具。

在使用 NumPy 之前,需要先导入该模块:

import numpy as np

01 生成ndarray的几种方式

NumPy封装了一个新的数据类型ndarray,一个多维数组对象,该对象封装了许多常用的数学运算函数,方便我们进行数据处理以及数据分析,那么如何生成ndarray呢?这里我们介绍生成ndarray的几种方式,如从已有数据中创建;利用random创建;创建特殊多维数组;使用arange函数等。

1. 从已有数据中创建

直接对python的基础数据类型(如列表、元组等)进行转换来生成ndarray。

(1)将列表转换成ndarray

import numpy as np
list1 = [3.14,2.17,0,1,2]
nd1 = np.array(list1)
print(nd1)
print(type(nd1))

打印结果:

[ 3.14  2.17  0.    1.    2.  ]
<class 'numpy.ndarray'>

(2)嵌套列表可以转换成多维ndarray

import numpy as np
list2 = [[3.14,2.17,0,1,2],[1,2,3,4,5]]
nd2 = np.array(list2)
print(nd2)
print(type(nd2))

打印结果:

[[ 3.14  2.17  0.    1.    2.  ]
 [ 1.    2.    3.    4.    5.  ]]
<class 'numpy.ndarray'>

如果把(1)和(2)中的列表换成元组也同样适合。

2. 利用random模块生成ndarray

在深度学习中,我们经常需要对一些变量进行初始化,适当的初始化能提高模型的性能。通常我们用随机数生成模块random来生成,当然random模块又分为多种函数:

  • random生成0到1之间的随机数;
  • uniform生成均匀分布随机数;
  • randn生成标准正态的随机数;
  • normal生成正态分布;
  • shuffle随机打乱顺序;
  • seed设置随机数种子等。

下面我们列举几个简单示例。

import numpy as np

nd5 = np.random.random([3,3])
print(nd5)
print(type(nd5))

打印结果:

[[ 0.88900951  0.47818541  0.91813526]
 [ 0.48329167  0.63730656  0.14301479]
 [ 0.9843789   0.99257093  0.24003961]]
<class 'numpy.ndarray'>

生成一个随机种子,对生成的随机数打乱。

import numpy as np

np.random.seed(123)
nd5_1 = np.random.randn(2,3)
print(nd5_1)
np.random.shuffle(nd5_1)
print("随机打乱后数据")
print(nd5_1)
print(type(nd5_1))

打印结果:

[[-1.0856306   0.99734545  0.2829785 ]
 [-1.50629471 -0.57860025  1.65143654]]

随机打乱后数据为:

[[-1.50629471 -0.57860025  1.65143654]
 [-1.0856306   0.99734545  0.2829785 ]]
<class 'numpy.ndarray'>

3. 创建特定形状的多维数组

数据初始化时,有时需要生成一些特殊矩阵,如0或1的数组或矩阵,这时我们可以利用np.zeros、np.ones、np.diag来实现,下面我们通过几个示例来说明。

import numpy as np

#生成全是0的3x3矩阵
nd6 = np.zeros([3,3])
#生成全是1的3x3矩阵
nd7 = np.ones([3,3])
#生成3阶的单位矩阵
nd8= np.eye(3)
#生成3阶对角矩阵
print (np.diag([1, 2, 3]))

我们还可以把生成的数据保存到磁盘,然后从磁盘读取。

import numpy as np
nd9 = np.random.random([5,5])
np.savetxt(X=nd9,fname='./test2.txt')
nd10 = np.loadtxt('./test2.txt')

4. 利用arange函数

arange是numpy模块中的函数,其格式为:arange([start,] stop[, step,], dtype=None)。根据start与stop指定的范围,以及step设定的步长,生成一个 ndarray,其中start默认为0,步长step可为小数。

import numpy as np

print(np.arange(10))
print(np.arange(0,10))
print(np.arange(1, 4,0.5))
print(np.arange(9, -1, -1))

02 存取元素

上节我们介绍了生成ndarray的几种方法,数据生成后,如何读取我们需要的数据?这节我们介绍几种读取数据的方法。

import numpy as np
np.random.seed(2018)
nd11 = np.random.random([10])
#获取指定位置的数据,获取第4个元素
nd11[3]
#截取一段数据
nd11[3:6]
#截取固定间隔数据
nd11[1:6:2]
#倒序取数
nd11[::-2]
#截取一个多维数组的一个区域内数据
nd12=np.arange(25).reshape([5,5])
nd12[1:3,1:3]
#截取一个多维数组中,数值在一个值域之内的数据
nd12[(nd12>3)&(nd12<10)]
#截取多维数组中,指定的行,如读取第2,3行
nd12[[1,2]]  #或nd12[1:3,:]
##截取多维数组中,指定的列,如读取第2,3列
nd12[:,1:3]

如果你对上面这些获取方式还不是很清楚,没关系,下面我们通过图形的方式说明如何获取多维数组中的元素,如图1-1所示,左边为表达式,右边为对应获取元素。

▲图1-1 获取多维数组中的元素

获取数组中的部分元素除通过指定索引标签外,还可以使用一些函数来实现,如通过random.choice函数从指定的样本中进行随机抽取数据。

import numpy as np
from numpy import random as nr

a=np.arange(1,25,dtype=float)
c1=nr.choice(a,size=(3,4))  #size指定输出数组形状
c2=nr.choice(a,size=(3,4),replace=False)  #replace缺省为True,即可重复抽取
#下式中参数p指定每个元素对应的抽取概率,默认为每个元素被抽取的概率相同
c3=nr.choice(a,size=(3,4),p=a / np.sum(a))
 print("随机可重复抽取")
print(c1)
print("随机但不重复抽取")
print(c2)
print("随机但按制度概率抽取")
print(c3)

打印结果:

随机可重复抽取
[[  7.  22.  19.  21.]
 [  7.   5.   5.   5.]
 [  7.   9.  22.  12.]]
随机但不重复抽取
[[ 21.   9.  15.   4.]
 [ 23.   2.   3.   7.]
 [ 13.   5.   6.   1.]]
随机但按制度概率抽取
[[ 15.  19.  24.   8.]
 [  5.  22.   5.  14.]
 [  3.  22.  13.  17.]]

03 矩阵操作

深度学习中经常涉及多维数组或矩阵的运算,正好NumPy模块提供了许多相关的计算方法,下面介绍一些常用的方法。

import numpy as np

nd14=np.arange(9).reshape([3,3])

#矩阵转置
np.transpose(nd14)

#矩阵乘法运算
a=np.arange(12).reshape([3,4])
b=np.arange(8).reshape([4,2])
a.dot(b)

#求矩阵的迹
a.trace()
#计算矩阵行列式
np.linalg.det(nd14)

#计算逆矩阵
c=np.random.random([3,3])
np.linalg.solve(c,np.eye(3))

上面介绍的几种方法是numpy.linalg模块中的函数,numpy.linalg模块中的函数是满足行业标准级的Fortran库。

numpy.linalg中常用函数:

  • diag:以一维数组方式返回方阵的对角线元素
  • dot:矩阵乘法
  • trace:求迹,即计算对角线元素的和
  • det:计算矩阵列式
  • eig:计算方阵的本征值和本征向量
  • inv:计算方阵的逆
  • qr:计算qr分解
  • svd:计算奇异值分解svd
  • solve:解线性方程组Ax = b,其中A为方阵
  • lstsq:计算Ax=b的最小二乘解

04 数据合并与展平

在机器学习或深度学习中,会经常遇到需要把多个向量或矩阵按某轴方向进行合并的情况,也会遇到展平的情况,如在卷积或循环神经网络中,在全连接层之前,需要把矩阵展平。这节介绍几种数据合并和展平的方法。

1. 合并一维数组

import numpy as np
a=np.array([1,2,3])
b=np.array([4,5,6])
c=np.append(a,b)
print(c)
#或利用concatenate
d=np.concatenate([a,b])
print(d)

打印结果:

[1 2 3 4 5 6]
[1 2 3 4 5 6]

2. 多维数组的合并

import numpy as np
a=np.arange(4).reshape(2,2)
b=np.arange(4).reshape(2,2)
#按行合并
c=np.append(a,b,axis=0)
print(c)
print("合并后数据维度",c.shape)
#按列合并
d=np.append(a,b,axis=1)
print("按列合并结果:")
print(d)
print("合并后数据维度",d.shape)

打印结果:

[[0 1]
 [2 3]
 [0 1]
 [2 3]]
合并后数据维度 (4, 2)
按列合并结果:
[[0 1 0 1]
 [2 3 2 3]]
合并后数据维度 (2, 4) 

3. 矩阵展平

import numpy as np
nd15=np.arange(6).reshape(2,-1)
print(nd15)
#按照列优先,展平。
print("按列优先,展平")
print(nd15.ravel('F'))
#按照行优先,展平。
print("按行优先,展平")
print(nd15.ravel())

打印结果:

[[0 1 2]
 [3 4 5]]
按列优先,展平
[0 3 1 4 2 5]
按行优先,展平
[0 1 2 3 4 5]

05 通用函数

NumPy提供了两种基本的对象,即ndarray和ufunc对象。前面我们对ndarray做了简单介绍,本节将介绍它的另一个对象ufunc。

ufunc(通用函数)是universal function的缩写,它是一种能对数组的每个元素进行操作的函数。许多ufunc函数都是在C语言级别实现的,因此它们的计算速度非常快。

此外,功能比math模块中的函数更灵活。math模块的输入一般是标量,但NumPy中的函数可以是向量或矩阵,而利用向量或矩阵可以避免循环语句,这点在机器学习、深度学习中经常使用。以下为NumPy中的常用几个通用函数:

  • sqrt:计算序列化数据的平方根
  • sin,cos:三角函数
  • abs:计算序列化数据的绝对值
  • dot:矩阵运算
  • log,log10,log2:对数函数
  • exp:指数函数
  • cumsum,cumproduct:累计求和,求积
  • sum:对一个序列化数据进行求和
  • mean:计算均值
  • median:计算中位数
  • std:计算标准差
  • var:计算方差
  • corrcoef:计算相关系数

1. 使用math与numpy函数性能比较

import time
import math
import numpy as np
x = [i * 0.001 for i in np.arange(1000000)]
start = time.clock()
for i, t in enumerate(x):
    x[i] = math.sin(t)
print ("math.sin:", time.clock() - start )

x = [i * 0.001 for i in np.arange(1000000)]
x = np.array(x)
start = time.clock()
np.sin(x)
print ("numpy.sin:", time.clock() - start )

打印结果:

math.sin: 0.5169950000000005
numpy.sin: 0.05381199999999886

由此可见,numpy.sin比math.sin快近10倍。

2. 使用循环与向量运算比较

充分使用Python的NumPy库中的内建函数(built-in function),实现计算的向量化,可大大提高运行速度。NumPy库中的内建函数使用了SIMD指令。例如下面所示在Python中使用向量化要比使用循环计算速度快得多。

import time
import numpy as np

x1 = np.random.rand(1000000)
x2 = np.random.rand(1000000)
##使用循环计算向量点积
tic = time.process_time()
dot = 0
for i in range(len(x1)):
    dot+= x1[i]*x2[i]
toc = time.process_time()
print ("dot = " + str(dot) + "\n for loop----- Computation time = " + str(1000*(toc - tic)) + "ms")
##使用numpy函数求点积
tic = time.process_time()
dot = 0
dot = np.dot(x1,x2)
toc = time.process_time()
print ("dot = " + str(dot) + "\n verctor version---- Computation time = " + str(1000*(toc - tic)) + "ms")

打印结果:

dot = 250215.601995
 for loop----- Computation time = 798.3389819999998ms
dot = 250215.601995
 verctor version---- Computation time = 1.885051999999554ms

从程序运行结果上来看,该例子使用for循环的运行时间是使用向量运算的运行时间的约400倍。因此,深度学习算法中,一般都使用向量化矩阵运算。

06 广播机制

广播机制(Broadcasting)的功能是为了方便不同shape的数组(NumPy库的核心数据结构)进行数学运算。广播提供了一种向量化数组操作的方法,以便在C中而不是在Python中进行循环,这通常会带来更高效的算法实现。广播的兼容原则为:

  • 对齐尾部维度。
  • shape相等or其中shape元素中有一个为1。

以下通过实例来具体说明。

import numpy as np
a=np.arange(10)
b=np.arange(10)
#两个shape相同的数组相加
print(a+b)
#一个数组与标量相加
print(a+3)
#两个向量相乘
print(a*b)

#多维数组之间的运算
c=np.arange(10).reshape([5,2])
d=np.arange(2).reshape([1,2])
#首先将d数组进行复制扩充为[5,2],如何复制请参考图1-2,然后相加。
print(c+d)

▲图1-2 NumPy多维数组相加

打印结果:

[ 0  2  4  6  8 10 12 14 16 18]
[ 3  4  5  6  7  8  9 10 11 12]
[ 0  1  4  9 16 25 36 49 64 81]
[[ 0  2]
 [ 2  4]
 [ 4  6]
 [ 6  8]
 [ 8 10]]

有时为了保证矩阵运算正确,我们可以使用reshape()函数来变更矩阵的维度。

07 小结

阅读完本文,你已get到如下技能:

√ 如何生成NumPy的ndarray的几种方式。

√ 如何存取元素。

√ 如何操作矩阵。

√ 如何合并或拆分数据。

√ NumPy的通用函数。

√ NumPy的广播机制。

如果想进一步了解NumPy,大家可参考: http://www.numpy.org/

关于作者:吴茂贵,BI和大数据专家,就职于中国外汇交易中心,在BI、数据挖掘与分析、数据仓库、机器学习等领域有超过20年的工作经验,在Spark机器学习、TensorFlow深度学习领域大量的实践经验。

王冬,任职于博世(中国)投资有限公司,负责Bosch企业BI及工业4.0相关大数据和数据挖掘项目。对机器学习、人工智能有多年实践经验。

李涛,参与过多个人工智能项目,如研究开发服务机器人、无人售后店等项目。熟悉python、caffe、TensorFlow等,对深度学习、尤其对计算机视觉方面有较深理解。

杨本法,高级算法工程师,在机器学习、文本挖掘、可视化等领域有多年实践经验。熟悉Hadoop、Spark生态圈的相关技术,对Python有丰富的实战经验。

本文摘编自《Python深度学习:基于TensorFlow》,经出版方授权发布。

延伸阅读《Python深度学习:基于TensorFlow》

点击上图了解及购买

转载请联系微信:DoctorData

推荐语:从Python和数学,到机器学习和TensorFlow,再到深度学习的应用和扩展,为深度学习提供全栈解决方案。

本文分享自微信公众号 - 大数据(hzdashuju),作者:吴茂贵 王冬 等

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-03-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 5G的未来投资机会在哪里?(附中国5G产业发展与投资报告全文)

    导读:日前,为了更好地以资本助推5G产业发展,中国移动投资公司与中国移动研究院联合发布了《洞见5G,投资未来——中国5G产业发展与投资报告》,分析了5G对生产和...

    华章科技
  • 实用干货:7个实例教你从PDF、Word和网页中提取数据

    导读:本文的目标是介绍一些Python库,帮助你从类似于PDF和Word DOCX 这样的二进制文件中提取数据。我们也将了解和学习如何从网络信息源(web fe...

    华章科技
  • 6个用于大数据分析的最好工具

    大数据是一个含义广泛的术语,是指数据集,如此庞大而复杂的,他们需要专门设计的硬件和软件工具进行处理。该数据集通常是万亿或EB的大小。这些数据集收集自各种各样的来...

    华章科技
  • 小蛇学python(11)初窥numpy

    读者可以自行输入,观看结果,享受编码的乐趣。注意zeros和ones后面是跟了两组小括号的。

    用户2145057
  • 【机器学习】--Python机器学习库之Numpy

    NumPy(Numerical Python的缩写)是一个开源的Python科学计算库。使用NumPy,就可以很自然地使用数组和矩阵。 NumPy包含很多实用的...

    LhWorld哥陪你聊算法
  • Python数据分析(6)-numpy广播机制

    numpy的广播机制旨在提供一种当被处理数组维度大小不一样时仍然能计算的机制。首先要明白,在数组(或者说是向量,数组的本质就是多维向量的组合)计算时,除了一些特...

    锦小年
  • 002.python科学计算库numpy(下)

    版权声明:本文为博主原创文章,允许转载,请标明出处。 https://blog.csdn.net/qwdafedv/article/deta...

    qubianzhong
  • Python进阶之NumPy快速入门(四)

    NumPy是Python的一个扩展库,负责数组和矩阵运行。相较于传统Python,NumPy运行效率高,速度快,是利用Python处理数据必不可少的工具。

    HuangWeiAI
  • 我的Python分析成长之路8

    Numpy:是Numerical Python的简称,它是目前Python数值计算中最为基础的工具包,Numpy是用于数值科学计算的基础模块,不但能够完成科学...

    py3study
  • 灰太狼的数据世界(四)

    https://baike.baidu.com/item/lu%E5%88%86%E8%A7%A3/764245?fr=aladdin

    我被狗咬了

扫码关注云+社区

领取腾讯云代金券