合并数组

合并数组也是最常见的操作之一,下表列举了常见的用于数组或向量合并的方法。

函数

描述

np.append

内存占用大

np.concatenate

没有内存问题

np.stack

沿着新的轴加入一系列数组

np.hstack

堆栈数组垂直顺序(行)

np.vstack

堆栈数组垂直顺序(列)

np.dstack

堆栈数组按顺序深入(沿第3维)

np.vsplit

将数组分解成垂直的多个子数组的列表

(1)append、concatenate以及stack都有一个axis参数,用于控制数组的合并方式是按行还是列。

(2)对于append和concatenate,待合并的数组必须有相同的行数或列数(满足一个即可)。

(3)stack、hstack、dstack,要求待合并的数组必须具有相同的形状(shape)。

下面进行一些举例:
1.append

合并一维数组

Numpy基础(3.0)_Numpy

合并多维数组:

 

Numpy基础(3.0)_机器学习_02

2.concatenate

 沿指定轴连接数组或矩阵:

Numpy基础(3.0)_python_03

3.stack

沿指定轴堆叠数组或矩阵:

 

Numpy基础(3.0)_算法_04

 1.5批量处理

在深度学习中,由于元数据都比较大,所以通常需要用到批处理。如利用批量来计算梯度的随机梯度法(SGD)就是一个典型应用。深度学习的计算一般比较复杂,并且数据量一般比较大,如果一次处理整个数据,较大概率会出现资源瓶颈。为了更有效地计算,一般将这呢各个数据集分批次处理。与处理这呢各个数据集相反的另一个极端是每次只处理一条记录,这种方法也不科学,一次处理一条记录无法充分发挥GPU、numpy的平行处理优势。因此,在实例使用中往往采用批量处理(Mini-Batch)的方法。

如何把大数据拆分成多个批次呢?可采用如下步骤:

(1)得到数据集

(2)随机打乱数据

(3)定义批大小

(4)批处理数据集

下面我们通过一个实例来具体说明:

import numpy as np
data=np.random.randn(10000,2,3)
print(data.shape)
np.random.shuffle(data)
batch_size=100
for i in range(0,len(data),batch_size):
x=np.sum(data[i:i+batch_size])
print("第{}批次,该批次的数据之和:{}".format(i,x))

Numpy基础(3.0)_算法_05

批次从0开始,所以最后一个批次是9900.

通用函数

numpy提供了两种基本的对象,即ndarray和ufunc对象。前面已经介绍了ndarray,下面我们将介绍numpy的两一个通用函数ufunc。ufunc是一种能对数组的每个元素进行操作的函数。许多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 numpy as np
import time
import math

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)

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

Numpy基础(3.0)_机器学习_06

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

2.循环与向量运算比较

充分使用Python的numpy库的内建函数(built-infunction),来实现计算的向量化,可大大地提高运行速度。Numpy库中的内奸函数使用了SIMD指令。如下使用的向量化要比使用循环计算速度快的多。如果使用GPU,其性能将更强大,不过Numpy不支持GPU。pytorch支持GPU。后面的文章会对pytorch如何使用GPU来加速算法。

import numpy as np
import time
import math

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----- Computer time="+str(1000*(toc-tic))+"ms")

tic1=time.process_time()
#dot1=0
dot1=np.dot(x1,x2)
toc1=time.process_time()
print("dot ="+str(dot1)+"\n verctor version----- Computer time="+str(1000*(toc1-tic1))+"ms")

 

Numpy基础(3.0)_python_07

从运行结果上来看,使用for循环的运行时间大约是向量运算的5倍。因此,在深度学习算法中,一般使用向量化矩阵进行运算。

广播机制

numpy的universal functions中要求输入的数组的shape是一致的,当数组的shape不相等时,则会使用广播机制。不过,调整数组使得shape一样,需要满足一定的规则,否则将出错。这些规则可归纳为以下四条。

(1)让所有输入数组都向其中shape最长的数组看齐,不足的部分通过在前面加1补齐,如:

a:2*3*2

b:3*2

则b向a看齐,在b前面加1,变成1*3*2

(2)输出数组的shape是输入数组shape各个轴上的最大值

(3)如果输入数组的某个轴和输出数组的对应轴的长度相同或者某个轴的长度为1时,这个数组能被用来计算,否则出错。

(4)当输入数组的某个轴的长度为1时,沿着此轴运算时都用(或复制)此轴上的第一组值。

广播在整个Numpy中用于决定如何处理形状迥异的数组,涉及的算术运算包括(+,-,*,/...).这些规则说的很严谨,但不直观,下面我们结合代码来进一步的说明。

目的:A+B,其中A为4*1矩阵,B为一维向量(3,)

要相加,需要做如下处理:

根据规则1,B需要向A看齐,把B变成(1,3)

根据规则2,输出的结果为各个轴上的最大值,即输出结果应该为(4,3)矩阵,那么A如何由(4*1)变成(4*3)矩阵?而B又如何由(1,3)变成(4,3)矩阵?

根据规则4,泳池轴上的第一组值(要主要区分是那个周),进行复制(在世纪处理中不是真正复制,否则太耗内存,而是采用其他对象如ogrid对象,进行网格处理)即可。

代码实现:

import numpy as np
import time
import math

a=np.arange(0,40,10).reshape(4,1)
b=np.arange(0,3)
print(a)
print(b)
print("a矩阵的形状:{},b矩阵的形状:{}".format(a.shape,b.shape))
c=a+b
print("c矩阵的形状:{}".format(c.shape))
print(c)

 

Numpy基础(3.0)_算法_08