深度学习系列之Numpy基础(一)

写在开头:因为也开始了深度学习课程的学习,对于很多东西还要慢慢理解,所以也打算开一个这个系列来分享一下自己的理解。

深度学习系列

对于本系列的学习内容安排的话,主要涉及的是对于图像识别方面的内容,或许我会在学完后在来写一个目录,今天的内容就是对于python中numpy使用的一些汇总,主要学习来源附在最后的参考文献。

Numpy学习

在使用Numpy之前,我们想进行一些矩阵运算往往只能通过一个又一个的for循环去完成,但有了Numpy库的支持,我们得以用简单的语句完成繁琐的for循环计算,下面我们结合代码开始今天的分享,
首先加载numpy包,

import numpy as np

数组的产生与查看

a = np.array([1, 2, 3])
print("数组的格式",type(a))
print("数组元素的类型",a.dtype)
print("数组的规模",a.shape)
print(a[0], a[1], a[2])
a[0] = 5 #修改值
print("打印数组",a)

b = np.array([[1,2,3],[4,5,6]]) #创建二元数组
print("数组的规模",b.shape) 
print(b[0, 0], b[0, 1], b[1, 0]) #打印二元数组
数组的格式 <class 'numpy.ndarray'>
数组元素的类型 int32
数组的规模 (3,)
1 2 3
打印数组 [5 2 3]
数组的规模 (2, 3)
1 2 4

方便的矩阵生成
其实说是矩阵,也跟数组差不多,numpy提供了不少快捷的矩阵生成函数,

a = np.zeros((2,2)) #产生一个0矩阵
print("零矩阵\n",a)
b = np.ones((1,2)) #产生全为1的矩阵
print("1矩阵\n",b)
c = np.full((2,2), 7) #填充
print("填充矩阵\n",c)
d = np.eye(2) #对角线
print("对角矩阵\n",d)
e = np.random.random((2,2)) #0-1的随机数
print("0,1随机矩阵\n",e)
零矩阵
 [[0. 0.]
 [0. 0.]]
1矩阵
 [[1. 1.]]
填充矩阵
 [[7 7]
 [7 7]]
对角矩阵
 [[1. 0.]
 [0. 1.]]
0,1随机矩阵
 [[0.2336035  0.72817244]
 [0.55966474 0.64770182]]

numpy数组的同步映射与数组选取
这里值得一提的是numpy在数组赋值过后,对赋值后的数组进行数值的变动,会影响原矩阵对应数值的变动,

a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])

b = a[:2, 1:3] #第1行道第2行,也就是index的0到1不包括右边界
print("a矩阵\n",a)
print("b矩阵\n",b)
print("a的第一行第二列的数为:",a[0, 1])
b[0, 0]=83 #对应a[0,1]
print("a的第一行第二列的数为:",a[0, 1]) #这里的index指针是同步的传递,b动了a也会动
a矩阵
 [[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
b矩阵
 [[2 3]
 [6 7]]
a的第一行第二列的数为: 2
a的第一行第二列的数为: 83

然后对于数组的片段选取除了最开始的一个值对应位置的选取以外还有片段式选取,已经二维列表式选取,条件式选取,

#片段式选取
a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
row_r1 = a[1, :]
row_r2 = a[1:2, :]
r3 = a[1:3, 1:3]
print("r1的值\n",row_r1, row_r1.shape)
print("r2的值\n",row_r2, row_r2.shape)
print("r3的值\n",r3, r3.shape)

这里需要注意的是,在片段选取的时候,选取内容不包括右边界,所谓二维列表式选取就是分别单独输入要选取的横坐标已经纵坐标,

#二维列表式选取
a = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
print("输出原数组\n",a)
print("输出3个数\n",a[[0,1,2],[0,1,0]])
print(np.array([a[0,0], a[1,1], a[2,0]])) #np.array变为数组格式

print("输出2个数\n",a[[0,0], [1,1]])
print(np.array([a[0,1], a[0,1]]))#[a[],a[]]前面的为横坐标,后面的为纵坐标

b= np.array([0, 2, 0, 1])
print("变量式选取\n",a[np.arange(4), b])
输出原数组
 [[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
输出3个数
 [1 5 7]
 [1 5 7]
输出2个数
 [2 2]
 [2 2]
变量式选取
 [ 1  6  7 11]

还可以通过设置条件来输出数组的选取,

#条件式选取
a = np.array([[1,2], [3,4], [5,6]])
bool_idx = (a > 2)
print("条件矩阵\n",bool_idx)
print("选取结果\n",a[bool_idx])
条件矩阵
 [[False False]
 [ True  True]
 [ True  True]]
选取结果
 [3 4 5 6]

数组的运算
下面简单分享一下数组的运算,包括加减乘除开方,矩阵乘法,求和,转置,empty_like使用,矩阵循环加法。首先说一下这个加减乘除开方,这些函数都是点对点的进行运算,

x = np.array([[1, 2],[3, 4]], dtype=np.float64)
y = np.array([[5, 6],[7, 8]], dtype=np.float64)

print("数组加法:对应位置相加")
print(x + y)
print(np.add(x, y))

print("数组减法:对应位置相减")
print(x-y)
print(np.subtract(x, y))

print("数组乘法:对应位置相乘")
print(x * y)
print(np.multiply(x, y))#点乘

print("数组除法:对应位置相除")
print(x / y)
print(np.divide(x, y))#点除

print("数组开方")
print(np.sqrt(x))
数组加法:对应位置相加
[[ 6.  8.]
 [10. 12.]]
[[ 6.  8.]
 [10. 12.]]
数组减法:对应位置相减
[[-4. -4.]
 [-4. -4.]]
[[-4. -4.]
 [-4. -4.]]
数组乘法:对应位置相乘
[[ 5. 12.]
 [21. 32.]]
[[ 5. 12.]
 [21. 32.]]
数组除法:对应位置相除
[[0.2        0.33333333]
 [0.42857143 0.5       ]]
[[0.2        0.33333333]
 [0.42857143 0.5       ]]
数组开方
[[1.         1.41421356]
 [1.73205081 2.        ]]

下面进行矩阵的乘法、转置,

x = np.array([[1, 2],[3, 4]])
y = np.array([[5, 6],[7, 8]])#两个维矩阵

v = np.array([9, 10])
w = np.array([11, 12])#两个二维向量

print("向量乘法")
print(v.dot(w))
print(np.dot(v, w)) #矩阵乘法

print("矩阵向量乘法")
print(x.dot(v))
print(np.dot(x, v)) #自动v就转为了列向量

print("矩阵乘法")
print(x.dot(y))
print(np.dot(x, y)) #交换位置实现 左右乘
向量乘法
219
219
矩阵向量乘法
[29 67]
[29 67]
矩阵乘法
[[19 22]
 [43 50]]
[[19 22]
 [43 50]]

注意在这里的矩阵向量乘法中,始终向量是自动调整到能够适应矩阵乘法的方向,当然如果能够相乘的话。因为来python中始终展示的都是行向量所以,他在处理上也自动更换行列向量。下面说说求和与矩阵的转置,

x = np.array([[1, 2],[3, 4]])
print("所有元素加和")
print(np.sum(x))
print("按列加和")
print(np.sum(x, axis = 0)) #按列求和
print("按行加和")
print(np.sum(x, axis = 1)) #按行求和

print("矩阵转置前")
print(x)
print("矩阵转置后")
print(x.T)

v = np.array([1,2,3])
print("向量转置前")
print(v)
print("向量转置后")
print(v.T)#转置操作
所有元素加和
10
按列加和
[4 6]
按行加和
[3 7]
矩阵转置前
[[1 2]
 [3 4]]
矩阵转置后
[[1 3]
 [2 4]]
向量转置前
[1 2 3]
向量转置后
[1 2 3]

可以看到向量的转置无变化,还有几种比较简洁的矩阵计算方法分别是empty_like,tile和直接相加,为了计算一个矩阵与一个向量相加,其实就是每一行都对同一个向量对应位置相加。
empty_like()就是生成一个和目标矩阵一样规模的空矩阵;
tilt()就是扩展成与目标矩阵相对应规模的加项矩阵;
直接相加的方法不够个性化,但还是挺实用的。

#empty_like()
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
v = np.array([1, 0, 1])
y = np.empty_like(x) #相当于不用单独写循环去创建y
for i in range(4):
    y[i, :] = x[i, :] + v #按行相加
print("empty_like()")
print(y)

#tile()
vv = np.tile(v, (4, 1))
print("tile()")
print(vv) #当矩阵维度比较大时,for太慢了,我们就直接生成一个加的矩阵
y = x + vv
print(y)

#直接相加
print("直接相加")
y = x + v
print(y)
empty_like()
[[ 2  2  4]
 [ 5  5  7]
 [ 8  8 10]
 [11 11 13]]
 
 tile()
[[1 0 1]
 [1 0 1]
 [1 0 1]
 [1 0 1]]
[[ 2  2  4]
 [ 5  5  7]
 [ 8  8 10]
 [11 11 13]]
 
 直接相加
[[ 2  2  4]
 [ 5  5  7]
 [ 8  8 10]
 [11 11 13]]

细究矩阵计算
虽然前面说了向量转置无用,但是为了能够满足向量乘法的维度对应,可以使用reshape()函数,来调整向量的结构,dot()矩阵乘法会自动调节矩阵与向量之间行列关系,但是四则运算需要手动调整矩阵向量方向规模,

v = np.array([1,2,3])
w = np.array([4,5])

print(np.reshape(v, (3, 1))*w) #竖着的点乘

x = np.array([[1,2,3], [4,5,6]])#v是3的向量,x有3列所以可以加,以一个[]为单元
print(x + v)
print((x.T + w).T)
print(x + np.reshape(w, (2, 1)))
print(x * 2)
[[ 4  5]
 [ 8 10]
 [12 15]]
 
[[2 4 6]
 [5 7 9]]
 
[[ 5  6  7]
 [ 9 10 11]]
 
[[ 5  6  7]
 [ 9 10 11]]
 
[[ 2  4  6]
 [ 8 10 12]]

结语
以上就是对于Numpy的基础分享。主要涉及的就是一些Numpy在矩阵上的计算技巧。
谢谢阅读。
参考
深度学习cs231n课程numpy讲解

发布了20 篇原创文章 · 获赞 79 · 访问量 2761

猜你喜欢

转载自blog.csdn.net/qq_35149632/article/details/104547249