前言

numpy是机器学习常用python库,本部分教程列出了常用的numpy的方法。

1. numpy的数组

numpy的数组不同于python数组是高度优化的数据结构。初始化numpy数组:

a = np.array([1, 2, 3, 4, 5])
# 从1开始到6(不含),步长为1
b = np.arange(1, 6, 1)
print(a+b)
[ 2  4  6  8 10]

argsort函数解析

>>> a
array([100, 101,   0, 103, 104])
>>> a.argsort()
array([2, 0, 1, 3, 4])

0在a数组的第三位,所以argsort的第一位是2,因为index从0开始,所以第三位是2.

100在a数组第一位,所以argsort的第二位是0,以此类推。

修改numpy的数组形状

函数定义:np.reshape(a, new_shape, order)

c = a.reshape([5, 1])
print(c)
[[1]
 [2]
 [3]
 [4]
 [5]]

reshape中的特殊参数-1

a = np.arange(0,30,1)
d = a.reshape(5,-1)
print(d)

表示5行,列自动。

[[ 0  1  4  3  8  5]
 [12  7 16  9 20 11]
 [24 13 28 15 32 17]
 [36 19 40 21 44 23]
 [48 25 52 27 56 29]]

squeeze降维

直接降到一维:

>>> e = np.arange(16)
>>> e
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])
>>> e.reshape(2,2,2,2)
array([[[[ 0,  1],
         [ 2,  3]],

        [[ 4,  5],
         [ 6,  7]]],


       [[[ 8,  9],
         [10, 11]],

        [[12, 13],
         [14, 15]]]])
>>> np.squeeze(e)
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])

expand_dims升维

>>> a
array([0,1,2,3,4,5,6,7,8,9])
>>>
>>> b = np.expand_dims(a,0)
>>> b
array([[0,1,2,3,4,5,6,7,8,9]])

数组乘法

d = a*c
print(d)
[[ 1  2  3  4  5]
 [ 2  4  6  8 10]
 [ 3  6  9 12 15]
 [ 4  8 12 16 20]
 [ 5 10 15 20 25]]

数组点积(点乘)

print(a.dot(b))
55

数组切片slice(类似python的切片)

print(a[1:3])
[2 3]

1:3表示从index=1开始一直到index=2,不含3

数组行翻转(第一行换到最后一行,第二行换到倒数第二行,以此类推)

::-1表示逐行,如果是::-2则表示隔行

print(d[::-1,:])
[[ 5 10 15 20 25]
 [ 4  8 12 16 20]
 [ 3  6  9 12 15]
 [ 2  4  6  8 10]
 [ 1  2  3  4  5]]

slice函数

函数定义slice(stop)

函数定义slice(start, stop)

函数定义slice(start, stop, step)

>>> b
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
>>> 
>>> 
>>> b[0,slice(None)] # slice(None)等同于下面
array([0, 1, 2, 3, 4])
>>> b[0,:]
array([0, 1, 2, 3, 4])

nonzero函数

取numpy数组中的非0值

>>> a
array([[1, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])
>>> np.nonzero(a)
(array([0]), array([0]))
>>> c
array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 0]])
>>> np.nonzero(c)
(array([0, 1]), array([0, 1]))

2. numpy处理图片

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

加载图片

image = Image.open('./image/ability.png')
image = np.array(image)
print(image.shape)
(503, 700, 4)

显示原图

print(plt.get_backend())
plt.imshow(image)
plt.show()

使用numpy行翻转

image2 = image[::-1, :, :]
plt.imshow(image2)
plt.show()
# 保存到文件
# im2 = Image.fromarray(image2)
# im2.save('./image/im2.png')

numpy数组第一维是行,执行::-1; 第二位是列,保持不变;第三维是颜色,保持不变

numpy实现图片裁剪

height,width = image.shape[0], image.shape[1]
print('height=%d width=%d'%(height, width))

heightStart = height // 2
heightEnd = height

image3 = image[heightStart:heightEnd, :, :]
plt.imshow(image3)
plt.show()

注意,numpy数组的x = height, y = width

numpy去除图片颜色

image = Image.open('./image/ability.png')
image = np.array(image)
print(image.shape)

image2 = Image.open('./image/ability.png').convert('L')
image2 = np.array(image2)
print(image2.shape)

可以看到颜色那一维被去掉了:

(503, 700, 4)
(503, 700)

numpy实现图片增亮

我们这里是png格式的图片,大小为高度503,宽度700,颜色通道4。我们需要对所有503*700的RGB三个颜色通道做数组乘法。首先我们需要对图片进行切片,以处理我们需要的RGB通道。

首先我们来学习一下numpy多维数组的切片知识

import numpy as np

a = np.arange(0,30,1)

b = a.reshape(5,3,2)

print(b)
# 保持第一维第二维不变,切片第三维度,给第三维的第一列乘与二并覆盖b
b[:, :, 0:1] *=2

print(b)

请看第三维度的所有第一列都乘与二

# 原始的b(5x3x2)
[[[ 0  1]
  [ 2  3]
  [ 4  5]]

 [[ 6  7]
  [ 8  9]
  [10 11]]

 [[12 13]
  [14 15]
  [16 17]]

 [[18 19]
  [20 21]
  [22 23]]

 [[24 25]
  [26 27]
  [28 29]]]


# 计算过之后的b
[[[ 0  1]
  [ 4  3]
  [ 8  5]]

 [[12  7]
  [16  9]
  [20 11]]

 [[24 13]
  [28 15]
  [32 17]]

 [[36 19]
  [40 21]
  [44 23]]

 [[48 25]
  [52 27]
  [56 29]]]

以此类推,PNG图片增亮的写法为:

image4 = image
print(image[320,265,:])
# 0:3表示截取RGB通道
image4[:, :, 0:3] = image4[:, :, 0:3]*2.0
print(image[320,265,:])
# 保证颜色在255之间
image4 = np.clip(image4, a_min=None, a_max=255.)
# astype保证给matplotlib的数据是在0~255之间的无符号整数
plt.imshow(image4.astype('uint8'))
plt.show()

我们从上面的例子可以看到numpy是如何操作图片的。实际上我们有更好的图形库来处理图片增亮问题。我们仅仅是演示numpy的强大能力。

3. clip函数

函数签名:numpy.clip(a, a_min, a_max, out=None)

a = np.array([1, 2, 3, 4, 5])
b= a.clip(2,4)
print(b)

运行结果:

[2 2 3 4 4] #小于最小值直接赋值为最小值,大于最大值赋值为最大值,中间的值不变

clip函数在Relu函数处理中的妙用:

import numpy as np
import matplotlib.pyplot as plt

#设置图片大小
plt.figure(figsize=(6, 6))
# x是1维数组,数组大小是从-10. 到10.的实数,每隔0.1取一个点
x = np.arange(-10, 10, 0.1)

# 计算ReLU函数
y = np.clip(x, a_min = 0., a_max = None)

# 画出函数曲线
plt.plot(x, y, color='g')
# 添加文字说明
plt.text(-3.0, 9, r'$y=ReLU(x)$', fontsize=13)

# 设置坐标轴格式
currentAxis=plt.gca()
currentAxis.xaxis.set_label_text('x', fontsize=15)
currentAxis.yaxis.set_label_text('y', fontsize=15)

plt.show()

np.clip画出了激活函数ReLU,非常简单。

4. random函数

函数签名:np.random.randint(low, high=None, size=None, dtype=’l’ )

np.random.randint(2, size=10)
array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0])

np.random.randint(1, size=10)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

np.random.randint(5, size=(2, 4))
array([[4, 0, 2, 1],
[3, 2, 2, 0]])

函数签名:np.random.normal(loc=0.0, scale=1.0, size=None)

  • loc:此概率分布的均值(对应着整个分布的中心centre)
  • scale:此概率分布的标准差(对应于分布的宽度,scale越大越矮胖,scale越小,越瘦高)
  • size:输出的shape

高斯分布的概率密度随机数:

>>> nd1 = np.random.normal(loc=1,scale=2,size=2)
>>> nd1
array([-1.87225388, -1.80144501])
>>> nd2 = np.random.normal(loc=1,scale=2)
>>> nd2
-0.8067499940336673

函数签名:numpy.random.uniform(low,high,size)

import matplotlib.pyplot as plt
import numpy as np
 
s = np.random.uniform(0,1,10)      # 产生10个[0,1)的数
count, bins, ignored = plt.hist(s) # 图形显示分布
plt.show()

运行结果:

函数签名:np.random.choice(a, size, replace, p)
replace 表示从a中是否不重复抽取,默认可重复
p 给出抽取概率,默认随机

a = np.array([1, 2, 3, 4, 5])
a1 = np.random.choice(a,2)
print(a1)

运行结果:

[1 3]

5.保存数据

np.save()

np.save(file, arr, allow_pickle=False, fix_imports=True)

数据是以未压缩的原始二进制格式保存在扩展名为 .npy 的文件中。python自动完成对象的磁盘序列化

np.load()

np.load(file, mmap_mode=None, allow_pickle=False, fix_imports=True, encoding=‘ASCII’)