提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
我们可以放慢脚步,不着急接触Pytorch框架,运用框架学习深度学习,我个人觉得比较有跨越性。所以,我们不妨先接触Numpy,通过numpy认识数据、算法、分类任务的训练到测试。
我们知道python这门语言学起来相对其他语言容易多了,就是因为有很多方法(函数)不需要我们自己写,当我们需要某个功能的时候直接调用就完事了!但笔者个人觉得语言只是一种工具罢了,python使用起来固然方便,但我们还是要从理解底层开始!
从底层基础开始学,不会华而不实!
一、什么是nmpy?
numpy是python的一个第三方程序库,它的名字是由“numerical”和“pyhton”两个词拼接而成。“numerical”:数字的,顾名思义,numpy就是关于数学的库。
我们可以通过numpy对以线性代数为主的数值进行操作,例如向量、矩阵等。进而,我们可以利用numpy实现机器学习算法、图像处理任务以及以及一些高等数学任务。
我们可以在终端输入pip指令安装numpy:
pip install numpy
如果安装速度较慢,也可以选用镜像源安装,此处以清华镜像源为例:
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
二、数组操作
使用numpy的关键在于学会运用数组,这里的数组和传统编程语言中的数组很相像,但意义不同。numpy的数组叫作ndarray,或者array,我们可以理解为矩阵、阵列等等,可见它是有维度的,而且维度可以很高。
我们先看看如何用numpy创建数组。
1.创建数组
numpy创建数组的方式也有好几种。
(1)指定大小、元素值随机的数组
import numpy as np
x = np.empty([3,2], dtype = int)
print (x)
生成了3×2大小的数组,元素值都是随机的。其中dtype对应的是ndarray 对象的元素类型。此处是整型。
'''
[[-544471152 320]
[-616162000 320]
[ 131074 0]]
'''
(2)元素都为0的数组
import numpy as np
x = np.zeros((3,2))
y = np.zeros(3)
z = np.zeros(3,dtype = int)
print (x)
print(y)
print(z)
numpy.zeros()中的第一个元素是数组的形状,当第一个元素是一个整数时,返回结果是一个一维数组,当第一个元素是(n,m)时,返回结果是一个n行m列的二维数组,
当第一个元素是(x,y,z)时,返回结果时一个形状为x×y×z的三维数组,以此类推。
'''
[[0. 0.]
[0. 0.]
[0. 0.]]
[0. 0. 0.]
[0 0 0]
'''
numpy.zeros()中的第一个元素是数组的形状,当第一个元素是一个整数时,返回结果是一个一维数组,当第一个元素是(n,m)时,返回结果是一个n行m列的二维数组,
当第一个元素是(x,y,z)时,返回结果时一个形状为x×y×z的三维数组,以此类推。
(3)元素都为1的数组
import numpy as np
x = np.ones((3,2,2))
y = np.ones(3)
z = np.ones(3,dtype = int)
print (x)
print(y)
print(z)
x是通过numpy.ones()生成的形状为3×2×2的三维数组。
'''
[[[1. 1.]
[1. 1.]]
[[1. 1.]
[1. 1.]]
[[1. 1.]
[1. 1.]]]
[1. 1. 1.]
[1 1 1]
'''
(4)指定数值范围内的数组
numpy.arange(start, stop, step, dtype)可创建一个指定范围和数据类型的数组,其中start是起始位置,stop是终止位置,step是步长,dtype是元素数据类型(默认是int类型)。
import numpy as np
a = np.arange(5)
b = np.arange(5,10)
c = np.arange(0,10,2)
d = np.arange(0,10,2,dtype = float)
print(a)
print(b)
print(c)
print(d)
生成结果如下:
'''
[0 1 2 3 4]
[5 6 7 8 9]
[0 2 4 6 8]
[0. 2. 4. 6. 8.]
'''
(5)使用numpy.array()将list转化为numpy数组
尽管python中的list和其它语言中的数组都有维度这个说法,但是他们不能直接用来存储图像里的数据,但是numpy的array可以,因此,我们有必要熟悉array。
import numpy as np
a = np.array([[1,2,3],[3,4,5]])
print(a)
将二维数组变成了一个两行三列的array了,是不是很像空间里的矩阵(2×3)。
'''
[[1 2 3]
[3 4 5]]
'''
2.切片和索引
与python的列表操作一样,我们可以对numpy的array进行切片和索引,甚至遍历。
除了常见的start、stop、step这三个要素,高维数组还有对各维度数据的切片操作,比如截取一张图片中间的一部分。接下来,依次看看一维数组和二维数组的切片操作吧。
(1)一维数组的切片
import numpy as np
a = np.arange(10)
b = a[:]
c = a[0:10]
d = a[1:9]
e = a[0:10:2]
print(a)
print(b)
print(c)
print(d)
print(e)
生成结果如下:
'''
[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
[1 2 3 4 5 6 7 8]
[0 2 4 6 8]
'''
(2)二维数组的切片
import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
b = a[1:3,1:3]
print(a)
print(b)
高维数组的切片写法,是不是很像坐标的表示,生成结果如下:
'''
[[1 2 3]
[4 5 6]
[7 8 9]]
[[5 6]
[8 9]]
'''
三、广播机制
回顾一下线性代数里的=矩阵运算的知识点,矩阵运算加减、数量积和内积。如果两个不同形状的矩阵相加或相减,那肯定是不行的,但是array可以通过广播机制(broadcasting machanism)实现不同形状的数组运算。
import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
b = np.array([1,2,3])
bb = np.tile(b, (3, 1)) # 重复 b 的各个维度
c = a * b #数组array相乘,不能等同于矩阵相乘,此处是按位相乘
d = a + b #按位相加
dd = a + bb
e = a - b #按位相减
print("a: " + str(a))
print("b: " + str(b))
print("bb: " + str(bb))
print("\n")
print("c: " + str(c))
print("d: " + str(d))
print("dd: " + str(dd))
print("e: " + str(e))
生成结果如下:
'''
a: [[1 2 3]
[4 5 6]
[7 8 9]]
b: [1 2 3]
bb: [[1 2 3]
[1 2 3]
[1 2 3]]
c: [[ 1 4 9]
[ 4 10 18]
[ 7 16 27]]
d: [[ 2 4 6]
[ 5 7 9]
[ 8 10 12]]
dd: [[ 2 4 6]
[ 5 7 9]
[ 8 10 12]]
e: [[0 0 0]
[3 3 3]
[6 6 6]]
'''
这里出现的a+b与a+bb其实是同一种效果,当然还需要注意的是,两个数组形状不同,但是数组最低维度的元素个数一定是要相同的,否则运算就会出错。例如,一个3×2的数组和一个1×3的数组就是不能运算的。
四、数组修改
在编程语言里,对数组或列表的修改一般是对其内部元素进行增删改,但numpy的array除了元素可以改动之外,还可以对其形状或维度进行修改。接下来,我们看看几种常用的数组操作函数。
1.reshape()
reshape()函数有两种写法。
import numpy as np
a = np.arange(10)
print("a: ")
print(a)
b = np.reshape(a,(5,2))
print("b: ")
print(b)
'''
输出结果如下
a:
[0 1 2 3 4 5 6 7 8 9]
b:
[[0 1]
[2 3]
[4 5]
[6 7]
[8 9]]
'''
import numpy as np
a = np.arange(10)
print("a: ")
print(a)
b = a.reshape((5,2))
print("b: ")
print(b)
'''
输出结果如下
a:
[0 1 2 3 4 5 6 7 8 9]
b:
[[0 1]
[2 3]
[4 5]
[6 7]
[8 9]]
'''
2.ravel()
在图像处理领域里,我们可以选择numpy读取图像数据。在“图像分类之图像数据”这篇博客里,我提到过图像本身就是数据,现实里的图像都是三维的彩色图,显然一张图通过numpy的函数转化后,会变成三维数组。
讲述numpy是为了利用numpy实现神经网络的底层逻辑,神经网络可以用来识别图片,其中基础的神经网络叫作Full Connection Neural Network(全连接神经网络),它所需要的输入数据必须是一维的,因此我们在处理输入的时候需要将图像进行降维操作。其中,最简单的降维方法就是平展。
import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
print("a: ")
print(a)
b = a.ravel()
c = a.ravel(order = 'F') #order关键字传参,值为C时是按行,值为F时是按列,默认是C(按行)
print("b: ")
print(b)
print("c: ")
print(c)
'''
输出结果如下
a:
[[1 2 3]
[4 5 6]
[7 8 9]]
b:
[1 2 3 4 5 6 7 8 9]
c:
[1 4 7 2 5 8 3 6 9]
'''
3.transpose()
transpose()函数的功能是将对对应的数组进行转置操作。
import numpy as np
a = np.array([[1,2,3],[4,5,6]])
print("a: ")
print(a)
b = np.transpose(a)
c = a.T #大写的T加在数组后面,类似于矩阵右上角加个T,转置,和transpose功能一样
print("b: ")
print(b)
print("c: ")
print(c)
'''
a:
[[1 2 3]
[4 5 6]]
b:
[[1 4]
[2 5]
[3 6]]
c:
[[1 4]
[2 5]
[3 6]]
'''
五、矩阵/向量运算
这里需要复习一下线性代数的一点点知识点了。
矩阵和矩阵、向量和向量之间都有点乘和叉乘。其中点乘又叫做内积或者数量积,而叉乘叫做外积或者向量积。
点乘的结果是一个标量,并且要求两个矩阵的维数必须是相同的。
import numpy as np
a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
print("a: ")
print(a)
print("b: ")
print(b)
print("矩阵点乘/数量积/内积: ")
print(np.vdot(a,b))
'''
a:
[[1 2]
[3 4]]
b:
[[5 6]
[7 8]]
矩阵点乘/数量积/内积:
70
'''
叉乘的结果依旧是一个向量或一个矩阵。
import numpy as np
a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
print("a: ")
print(a)
print("b: ")
print(b)
print("矩阵叉乘/向量积/外积: ")
print(np.dot(a,b))
'''
输出结果如下
a:
[[1 2]
[3 4]]
b:
[[5 6]
[7 8]]
矩阵叉乘/向量积/外积:
[[19 22]
[43 50]]
'''
总结
接下来我们就可以从数据如手,开始我们的图像分类numpy实现之路啦!