Py学习  »  机器学习算法

收藏 | 深度学习之Numpy基础入门教程!

小白学视觉 • 2 年前 • 218 次点击  

点击上方小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

本文转自|计算机视觉联盟

0 概述


Numpy (Numerical Python)提供了两种基本对象:

  • ndarray(N-dimensional Array Object),存储单一的数据类型的多维数组

  • ufunc(Universal Function Object),能够对数组进行处理的函数

Numpy 的主要特点:

  • ndarray,快速节省空间的多维数组

  • 使用标准数学函数对整个数组的数据进行快速运算,不需要编写循环

  • 读取、写入磁盘上的阵列数据和操作存储器影像文件的工具

  • 线性代数、随机数生成和傅里叶变换的能力

  • 集成C、C++、Fortran代码

1.1 生成Numpy数组
import numpy as np

如何查看函数的帮助指令

np.add?

1.1.1 从已有数据中创建数组

(1)将列表转换成ndarray

import numpy as np
1st1 = [1.1, 2.2, 3, 4, 5, 6.6]
nd1 = np.array(1st1)
print(nd1)
# [1.1, 2.2, 3, 4, 5, 6.6]
print(type(nd1))
#

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

import numpy as np
1st2 = [[1.1, 2.2, 3, 4, 5, 6.6], [1,2,3,4]]
nd2 = np.array(1st2)
print(nd2)
# [[1.1, 2.2, 3, 4, 5, 6.6]
# [1,2,3,4]]
# [1.1, 2.2, 3, 4, 5, 6.6]
print(type(nd2))
#

1.1.2 利用random模块生成数组

np.random模块常用函数:




    
* np.random.random,生成0-1之间随机数
* np.random.uniform,生成均匀分布的随机数
* np.random.randn,生政标准正太分布的随机数
* np.random.randint,生成随机的证书
* np.random.normal,生成正态分布
* np.random.shuffle,随机打乱顺序
* np.random.seed,设置随机数粽子
* random_sample,生成随机的浮点数

具体使用

import numpy as np
nd3 = np.random.random([3,3])
print(nd3)
#[[]
# []
# []]
print("nd3的形状为:",nd3.shape)
# nd3的形状为:(3,3)

每次生成同一份数据,可以指定一个随机种子,使用shuffle函数打乱生成的随机数

import numpy as np
np.random.seed(123)
nd4 = np.random.randn(2,3)
print(nd4)
np.random.shuffle(nd4)
print("随机打乱后的数据:")
print(nd4)
print(type(nd4))

1.1.3 创建特定形状的多维数组

Numpy数组创建函数

* np.zeros((3,4))       创建3x4的元素全是0的数组
* np.ones((3,4)) 创建3x4的元素全是1的数组
* np.empty((2,3)) 创建2x3的空数组
* np.zeros_like(abc) 创建与abc相同纬度的全是0的数组
* np.ones_like(abc) 创建与abc相同纬度的全是1的数组
* np.empty_like(abc) 创建与abc相同纬度的空数组
* np.eye(5) 创建一个5x5的矩阵,对角线是1,其余是0
* np.full((3,5),666) 创建3x5的元素全是666的数组

有时候还可以把数据保存起来方便后续使用

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

1.1.4 利用arange、linspace函数生成数组

arange

arange([start,] stop[,step,], dtype=None)

start、stop指定范围,step设定步长
start默认是0开始。

import numpy as np
print(np.arange(10))
# [0 1 2 3 4 5 6 7 8 9]
print(np.arange(0,10))
# [0 1 2 3 4 5 6 7 8 9]
print(np.arange(1, 4, 0.5))
# [1 1.5 2 2.5 3 3.5]
print(np.arange(9,-1,-1))
# [9 8 7 6 5 4 3 2 1 0]

linspace

np.linspace(start, stop, num=50, endpoint=True, restep=False, dtype=None)

默认线性等分,默认等分为50

import numpy as np
print(np.linspace(0, 1, 10))
#[0 0.11111 0.22222 ...... 1]
# 这里没有像生成0.1,0.2这样规则的数据,是因为,这里需要包含0,1,所以最后除以了9
#(1-0)/0=0.111111,否则需要改起始位置为0.1即可
1.2 获取元素
import numpy as np
np.random.seed(2019)
nd11 = np.random.random([10])
# 获取指定位置的数据,比如获取第5个元素
nd11[4]
# 获取一段数据
nd11[3:7]
# 获取固定间隔取数,比如每间隔2个取一个
nd11[1:6:2]
# 获取一个多维数组的一个区域内的数据
nd12 = np.arange(25).reshape([5,5])
nd12[1:3,1:3]
# 获取一个多维数组中,数值在一个值域内的数据
nd12[(nd12>3)&(nd12<12)]
# 截取指定的行,比如第2,3行
nd12[[1,2]] # 或 nd12[1:3,:]
# 截取指定的列,比如第2,3列
nd12[:,1:3]

random.choice 可以从指定的样本中随机抽取数据

import numpy as np
from numpy import random as nr
a = np.arange(1,25,dtype=float)
# size指定输出数组形状
c1=nr.choice(a,size=(3,4))
# replace缺省为TUre,即可重复抽取,False就是虽然随机但是不重复
c2=nr.choice(a,size=(3,4),replace=False)
# p这个参数,缺省时每个元素的抽取概率相同,否则按照规则进行
c3=nr.choice(a,size(3,4),p=a/np.sum(a))
print("随机可重复抽取:")
print(c1)
print("随机但不重复抽取:")
print(c2)
print("随机但按制度概率抽取:")
print(c3)
1.3 Numpy的算术运算

1.3.1 对应元素相乘(逐元相乘)

np.mutiply用于数组或者矩阵对应元素相乘

numpy.multiply(x1, x2, /, out=None, *, where=True, casting='same_kind', order='K', dtype=None, subok=True[, signature, extobj])

举例子A与B矩阵相乘

A = np.array([[1, 2], [-1, 4]])
B = np.array([[2, 0], [3, 4]])
A*B
# 或者
numpy.multiply(A,B)
# array([[2, 0],
[-3, 16])

Numpy数组不仅可以与数组进行相乘,还可以进行标量运算

print(A*2.0)
print(A/2.0)

数组通过一些激活函数后,输出与输入的形状一致

X = np.random.rand(2,3)
def softmoid(x):
return 1/(1+np.exp(-x))
def relu(x):
return np.maximum(0,x)
def softmax(x):
return np.exp(x)/np.sum(np.exp(x))

print("输入参数X的形状:", X.shape)
print("激活函数softmoid输出形状:", softmoid(X).shape)
print("激活函数relu输出形状:", relu(X).shape)
print("激活函数softmax输出形状:", softmax(X).shape)

1.3.2 点积运算(矩阵乘法)

np.dot

numpy.dot(a, b, out=None)

这就是真正的矩阵乘法




    
X1=np.array([[1,2],[3,4]])
X2=np.array([[5,6,7],[8,9,10]])
X3=np.dot(X1,X2)
print(X3)
# 下标2x2*2x3=2x3
1.4 数组变形

1.4.1 更改数组的形状

Numpy中改变向量的一些函数

* arr.reshape   重新将维度改变,不改变向量本身
* arr.resize  重新将维度改变,修改向量本身
* arr.T  转置
* arr.ravel   对向量展开成1维数组,不会产生原数组的副本
* arr.flatten  对向量展开成1维数组,会返回原数组的副本
* arr.squeeze  只能对1维降维,对多维不报错但是没有用
* arr.transpose   对高纬矩阵进行轴对换

reshape(不修改向量本身)

import numpy as np
arr = np.arrange(10)
print(arr)
# 变为2行5列
print(arr.reshape(2,5))
# 指定维度时可以只指定其中一个,剩下用-1代替
print(arr.reshape(5,-1))
print(arr.reshape(-1,2))

resize(修改向量本身)

import numpy as np
arr = np.arrage(10)
print(arr)
arr.resize(2,5)
print(arr)

T

import numpy as np
arr = np.arrange(12).reshape(3,4)
print(arr)
print(arr.T)

ravel 向量展平

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

flatten 矩阵转换为向量

常用在卷积网络与全连接层之间

import numpy as np
a = np.floor(10*np.random.random((3,4)))
print(a)
print(a.flatten())

squeeze 降维,含1的维度去掉

import numpy as np
arr = np.arange(3).reshape(3 ,1)
print(arr.shape)
print(arr.squeeze().shape)
arr1 = np.arange(6).reshape(3,1,2,1)
print(arr1.shape)
print(arr1.squeeze().shape)
#(3, 1)
#(3,)
#(3, 1, 2, 1)
#(3, 2)

transpose

实际中经常把颜色顺序从RGB变为GBR就是一个应用

import numpy as np
arr2 = np.arange(24).reshape(2,3,4)
print(arr2)
print(arr2.shape)
print(arr2.transpose(0,1,2).shape)
print(arr2.transpose(1,2,0).shape)
print(arr2.transpose(2,1,0).shape)
# 结果
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
(2, 3, 4)
(2, 3, 4)
(3, 4, 2)
(4, 3, 2)

1.4.2 合并数组

Numpy数组合并方法

* np.append                     内存占用大
* np.concatenate 没有内存问题
* np.stack 沿着新的轴加入一系列数组
* np.hstack 堆栈数组垂直顺序(行)
* np.vstack (列)
* np.dstack 按顺序深入(沿第3维)
* np.vsplit 数组分解成垂直的多个子数组列表

append

# 合并一维数组
import numpy as np
a = np.array([1,2,3])
b = np.array([4,5,6])
c = np.append(a,b)
print(c)
# [1 2 3 4 5 6]
# 合并多维数组
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("按行合并后的结果")
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)

concatenate

沿着指定轴连接数组或者矩阵

import numpy as np
a = np.array([[1,2],[3,4]])
b = np.array([5,6])
c = np.concatenate((a,b), axis=0 ) # 按照行加
print(c)
d = np.concatenate((a, b.T), axis=1)
print(d)
[[1 2]
[3 4]
[5 6]]

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

stack

import numpy as np
a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
print(np.stack((a,b), axis=0))
[[[1 2]
[3 4]]

[[5 6]
[7 8]]]
1.5 批量处理


如何把大数据拆分成多个批次呢?

  1. 拿到数据集

  2. 随机打乱数据

  3. 定义批大小

  4. 批处理数据集

    import numpy as np
    # 生成10000个形状为2x3的矩阵
    data_train = np.random.randn(10000,2,3)
    print(data_train.shape)
    #(10000,2,3)
    # 打乱这10000条数据
    np.random.shuffle(data_train)
    # 定义批量大小
    batch_size = 100
    # 进行批量处理
    for i in range(0,len(data_train),batch_size):
    x_batch_sum = np.sum(data_train[i:i+batch_size])
    print("第{}批次,该批次数据的和:{}".format(i,x_batch_sum))
1.6 通用函数


Numpy提供了两种基本的对象,ndarray和ufunc对象

ufunc 是universal function的缩写,对数组的每个元素进行操作的函数,运算速度快一些

常用的函数

* sqrt                                  平方根
* sin,cos
* abs
* dot 矩阵计算
* log,log10,log2
* exp
* cumsum,cumproduct 累计求和,累计求积
* sum
* mean 均值
* median 中位数
* std 标准差
* var 方差
* corrcoef 相关系数

1.6.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] = match.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)

numpy.sin 比 math.sin 快10倍不止!

1.6.2 循环与向量运算比较

Numpy库中的内建函数使用了SIMD指令,比使用循环速度快很多!

GPU比Numpy更快,但是Numpy不支持GPU,Pytorch支持!

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 循环计算时间为:" + 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 Numpy计算时间为:" + str(1000*(toc-tic)) + "ms")

dot = 249895.7424207973
循环计算时间为:625.0ms
dot = 249895.7424208079
Numpy计算时间为:15.625ms
1.7 广播机制
通常会要求输入的数组的shape是一致的,如果不一致时,需要使用广播机制

归纳为以下四条:

  1. 让所有数组向最长的数组看齐,不足的部分前面补1,举列子就是a:2x3x2,b:3x2,那么b:1x3x2

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

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

  4. 当输入数组的某个轴的长度为1时,沿此轴运算时都要复制此轴上的第一组值

import numpy as npA = np.arange(0, 40, 10).reshape(4,1)print(A)B = np.arange(0,3)print(B)print(“A的形状:{},B的形状:{}”.format(A.shape,B.shape))C = A+Bprint(“C的形状:”+ C.shape)print(C)
[[ 0][10][20][30]][0 1 2]A的形状:(4, 1),B的形状:(3,)C的形状:(4, 3)[[ 0 1 2][10 11 12][20 21 22][30 31 32]]


好消息,小白学视觉团队的知识星球开通啦,为了感谢大家的支持与厚爱,团队决定将价值149元的知识星球现时免费加入。各位小伙伴们要抓住机会哦!


下载1:OpenCV-Contrib扩展模块中文版教程
在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲
小白学视觉公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲
小白学视觉公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群


欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/120287
 
218 次点击