Numpy学习
前言
最近在DL里被各种矩阵计算虐得很渣,决定学习一波numpy
正文
1、先学习一下用numpy打开txt文件
import numpy world_alcohol = numpy.genfromtxt("world_alcohol.txt",delimiter=",",dtype=str) print(type(world_alcohol)) print(world_alcohol) print(help(numpy.genfromtxt))
#
<class 'numpy.ndarray'> [['Year' 'WHO region' 'Country' 'Beverage Types' 'Display Value'] ['1986' 'Western Pacific' 'Viet Nam' 'Wine' '0'] ['1986' 'Americas' 'Uruguay' 'Other' '0.5'] ... ['1987' 'Africa' 'Malawi' 'Other' '0.75'] ['1989' 'Americas' 'Bahamas' 'Wine' '1.5'] ['1985' 'Africa' 'Malawi' 'Spirits' '0.31']]
txt内容如下:
Year,WHO region,Country,Beverage Types,Display Value 1986,Western Pacific,Viet Nam,Wine,0 1986,Americas,Uruguay,Other,0.5 1985,Africa,Cte d'Ivoire,Wine,1.62 1986,Americas,Colombia,Beer,4.27 1987,Americas,Saint Kitts and Nevis,Beer,1.98 1987,Americas,Guatemala,Other,0 1987,Africa,Mauritius,Wine,0.13 1985,Africa,Angola,Spirits,0.39 1986,Americas,Antigua and Barbuda,Spirits,1.55 1984,Africa,Nigeria,Other,6.1 1987,Africa,Botswana,Wine,0.2 1989,Americas,Guatemala,Beer,0.62
参数delimiter表示分割符号;dtype=str表示从文件中提取的数据以str格式存放;
ndarray是numpy中的数据结构;
2.ndarray
vector = numpy.array([5,10,15,20]) matrix = numpy.array([[5,10,15],[20,25,30],[35,40,45]]) print(vector) print(matrix)
#
[ 5 10 15 20] [[ 5 10 15] [20 25 30] [35 40 45]]
看一下维度
vector1 = numpy.array([[1,2,3,4]]) vector2 = numpy.array([1,2,3,4]) print(vector1.shape) print(vector2.shape) matrix = numpy.array([[5,10,15],[20,25,30]]) print(matrix.shape)
#
(1, 4) (4,) (2, 3)
vector1可以看作是1×4的矩阵;vector2是一维数组,可以看作是列向量
再看ndarray的运算
a = np.array([[1,2,3],[4,5,6],[7,8,9]]) b = np.array([1,2,3]) c = np.array([[1,2,3]]) print(np.dot(a,b)) print('------------------') print(np.dot(b,a)) print('------------------') print(np.dot(c,a)) print('------------------') print(np.dot(b,b)) print('------------------') print(a*a)
#
[14 32 50] ------------------ [30 36 42] ------------------ [[30 36 42]] ------------------ 14 ------------------ [[ 1 4 9] [16 25 36] [49 64 81]]
a是3×3的矩阵,b是一个长度为3的一维数组,c是1×3的矩阵
np.dot(a,b)可以看作是3×3的矩阵和3×1的矩阵相乘
np.dot(b,a)看作是1×3的矩阵和3×3的矩阵相乘
np.dot(c,a)看作是矩阵和矩阵相乘
注意,np.dot(b,b)是向量内积,是把各个维度都加起来
a*a是矩阵对应位置上各个元素的乘积
——————分割线——————————————
numbers = numpy.array([1,2,3,'4'])
print(numbers)
numbers.dtype
#
['1' '2' '3' '4']
只要array中有一个元素不是int32或者int64,那么所有的元素数据类型就会变成其他的数据类型
对txt文件进行操作
1 Year,WHO region,Country,Beverage Types,Display Value 2 1986,Western Pacific,Viet Nam,Wine,0 3 1986,Americas,Uruguay,Other,0.5 4 1985,Africa,Cte d'Ivoire,Wine,1.62 5 1986,Americas,Colombia,Beer,4.27 6 1987,Americas,Saint Kitts and Nevis,Beer,1.98 7 1987,Americas,Guatemala,Other,0 8 1987,Africa,Mauritius,Wine,0.13 9 1985,Africa,Angola,Spirits,0.39 10 1986,Americas,Antigua and Barbuda,Spirits,1.55 11 1984,Africa,Nigeria,Other,6.1 12 1987,Africa,Botswana,Wine,0.2 13 1989,Americas,Guatemala,Beer,0.62
①去掉表头,取出第二行,第五列的值以及第三行,第三列的值
world_alcohol = np.genfromtxt("world_alcohol.txt",delimiter=",",dtype=str,skip_header=1) uruguay_other_1986 = world_alcohol[1,4] third_country = world_alcohol[2,2] print(uruguay_other_1986) print(third_country)
#
0.5 Cte d'Ivoire
补充一下切片操作:
vector = numpy.array([5,10,15,20]) print(vector[0:3])
#
[ 5 10 15]
取出第0-2个元素
——————分割线——————————————
matrix = numpy.array([ [5,10,15], [20,25,30], [35,40,45] ]) print(matrix[:,1])
#
[10 25 40]
取出第二列所有元素
——————分割线——————————————
matrix = numpy.array([ [5,10,15], [20,25,30], [35,40,45] ]) print(matrix[:,0:2])
#
[[ 5 10] [20 25] [35 40]]
取出前两列元素
判断
vector = np.array([5.10,15,20]) vector == 10
#
array([False, False, False])
判断当前数据结构中有没有该元素
也可以借bool值来进行索引
vector = np.array([5,10,15,20]) equal_to_ten = (vector == 10) print(equal_to_ten) print(vector[equal_to_ten])
#
[False True False False] [10]
当然,在矩阵中就是如下:
matrix = np.array([ [5,10,15], [20,25,30], [35,40,45] ]) second_column_25 = (matrix[:,1]==25) print(second_column_25) print(matrix[second_column_25, :])
#
[False True False] [[20 25 30]]
对第二列的元素进行判断;然后取出元素等于25的那一列所在行
——————————-分割线——————————————
接下去是数值类型转换
vector = numpy.array(["1","2","3"]) print(vector.dtype) print(vector) vector = vector.astype(float) print(vector.dtype) print(vector)
#
<U1 ['1' '2' '3'] float64 [1. 2. 3.]
从str类型转到float类型
关于sum求和操作
matrix = np.array([ [5,10,15], [20,25,30], [35,40,45] ]) print(matrix.sum(axis=1)) print(matrix.sum(axis=0))
[ 30 75 120]
[60 75 90]
axis=1表示按行求和;axis=0表示按列求和
Numpy常用函数
①矩阵的属性
print(np.arange(15))
a = np.arange(15).reshape(3,5)
print(a)
print(a.shape)
print(a.ndim)
print(a.dtype.name)
print(a.size)
#
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14] [[ 0 1 2 3 4] [ 5 6 7 8 9] [10 11 12 13 14]] (3, 5) 2 int32 15
np.arange,依次生成0-14的一维数组;
reshape(3,5),转换为3×5的矩阵;
ndim看看维度是多少
dtype.name,看看元素数据类型
size看看一共有多少元素
②矩阵的初始化
a = np.zeros((3,4))
a
#
array([[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]])
表示生成3行,四列的全0矩阵,其中(3,4)可以是[3,4]格式;
默认dtype=np.float64
——————————————————分割线——————————
np.ones((2,3,4), dtype=np.int32)
#
array([[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]])
表示生成2个3×4的全1矩阵
——————————————————分割线——————————
np.arange(10,30,5) np.arange(0, 2, 0.3) np.arange(12).reshape(4,3) # [10 15 20 25] [0. 0.3 0.6 0.9 1.2 1.5 1.8] [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 9 10 11]]
从10开始,每隔5取一个数,左闭右开
——————————————————分割线——————————
np.random.random((2,3)) # array([[0.04286104, 0.02303494, 0.35769307], [0.34801234, 0.63580499, 0.99897693]])
表示随机生成2×3的矩阵
——————————————————分割线——————————
from numpy import pi np.linspace(0, 2*pi, 100) # array([0. , 0.06346652, 0.12693304, 0.19039955, 0.25386607, 0.31733259, 0.38079911, 0.44426563, 0.50773215, 0.57119866, 0.63466518, 0.6981317 , 0.76159822, 0.82506474, 0.88853126, 0.95199777, 1.01546429, 1.07893081, 1.14239733, 1.20586385, 1.26933037, 1.33279688, 1.3962634 , 1.45972992, 1.52319644, 1.58666296, 1.65012947, 1.71359599, 1.77706251, 1.84052903, 1.90399555, 1.96746207, 2.03092858, 2.0943951 , 2.15786162, 2.22132814, 2.28479466, 2.34826118, 2.41172769, 2.47519421, 2.53866073, 2.60212725, 2.66559377, 2.72906028, 2.7925268 , 2.85599332, 2.91945984, 2.98292636, 3.04639288, 3.10985939, 3.17332591, 3.23679243, 3.30025895, 3.36372547, 3.42719199, 3.4906585 , 3.55412502, 3.61759154, 3.68105806, 3.74452458, 3.8079911 , 3.87145761, 3.93492413, 3.99839065, 4.06185717, 4.12532369, 4.1887902 , 4.25225672, 4.31572324, 4.37918976, 4.44265628, 4.5061228 , 4.56958931, 4.63305583, 4.69652235, 4.75998887, 4.82345539, 4.88692191, 4.95038842, 5.01385494, 5.07732146, 5.14078798, 5.2042545 , 5.26772102, 5.33118753, 5.39465405, 5.45812057, 5.52158709, 5.58505361, 5.64852012, 5.71198664, 5.77545316, 5.83891968, 5.9023862 , 5.96585272, 6.02931923, 6.09278575, 6.15625227, 6.21971879, 6.28318531])
表示从0开始,到2π,按均匀分布取100个值
——————————————分割线—————————
a = np.array([20,30,40,50]) b = np.arange(4) print(a) print(b) c = a-b print(c) c = c-1 print(c) print(b**2) print(a<35) # [20 30 40 50] [0 1 2 3] [20 29 38 47] [19 28 37 46] [0 1 4 9] [ True True False False]
a-b就是每个对应位置元素相减
———————————————分割线———————
A = np.array([[1,1], [0,1]]) B = np.array([[2,0], [3,4]]) print(A) print('------------') print(B) print('------------') print(A*B) print('------------') print(A.dot(B)) print('------------') print(np.dot(A, B)) # [[1 1] [0 1]] ------------ [[2 0] [3 4]] ------------ [[2 0] [0 4]] ------------ [[5 4] [3 4]] ------------ [[5 4] [3 4]]
前文也详细写了numpy不同乘法的区别
③矩阵常用操作
B = np.arange(3) print(B) print(np.exp(B)) print(np.sqrt(B)) #
[0 1 2] [1. 2.71828183 7.3890561 ] [0. 1. 1.41421356]
exp表示e的x次幂;sqrt表示开平方
———————————————分割线———————
a = np.floor(10*np.random.random((3,4))) print(a) print('--------------') print(a.ravel()) print('--------------') a.shape = (6,2) print(a) print('--------------') print(a.T)
#
[[8. 3. 6. 2.] [0. 8. 7. 3.] [5. 2. 0. 7.]] -------------- [8. 3. 6. 2. 0. 8. 7. 3. 5. 2. 0. 7.] -------------- [[8. 3.] [6. 2.] [0. 8.] [7. 3.] [5. 2.] [0. 7.]] -------------- [[8. 6. 0. 7. 5. 0.] [3. 2. 8. 3. 2. 7.]]
floor表示向下取整,也就是往小的数取整;
a.ravel()表示把矩阵拉成一个向量;
a.shape=(6,2) 相当于a = a.reshape(6,2)
也可以是a.shape=(6,-1)或者a = a.reshape(6,-1)意思是指定一个维度,另一个维度自己去算
a.T也就是求转置
—————————————分割线————————
a = np.floor(10*np.random.random((2,2))) b = np.floor(10*np.random.random((2,2))) print(a) print('-----') print(b) print('-----') print(np.hstack((a,b))) print('-----') print(np.vstack((a,b)))
#
[[6. 7.] [1. 1.]] ----- [[0. 3.] [9. 9.]] ----- [[6. 7. 0. 3.] [1. 1. 9. 9.]] ----- [[6. 7.] [1. 1.] [0. 3.] [9. 9.]]
hstack表示按行拼接;vstack表示按列拼接
————————————————分割线——————
a = np.floor(10*np.random.random((2,12))) print(a) print('------') print(np.hsplit(a,3)) print('------') print(np.hsplit(a,(3,4))) a = np.floor(10*np.random.random((12,2))) print('------') print(a) np.vsplit(a,3)
#
[[4. 6. 5. 6. 0. 9. 7. 9. 3. 3. 0. 6.] [5. 5. 6. 1. 6. 2. 5. 3. 3. 9. 8. 1.]] ------ [array([[4., 6., 5., 6.], [5., 5., 6., 1.]]), array([[0., 9., 7., 9.], [6., 2., 5., 3.]]), array([[3., 3., 0., 6.], [3., 9., 8., 1.]])] ------ [array([[4., 6., 5.], [5., 5., 6.]]), array([[6.], [1.]]), array([[0., 9., 7., 9., 3., 3., 0., 6.], [6., 2., 5., 3., 3., 9., 8., 1.]])] ------ [[2. 0.] [0. 2.] [1. 4.] [3. 7.] [0. 0.] [7. 5.] [0. 7.] [3. 5.] [7. 9.] [1. 4.] [2. 4.] [8. 1.]] [array([[2., 0.], [0., 2.], [1., 4.], [3., 7.]]), array([[0., 0.], [7., 5.], [0., 7.], [3., 5.]]), array([[7., 9.], [1., 4.], [2., 4.], [8., 1.]])]
hsplit(a,3)表示按行切分,均分成3部分;
hsplit(a,(3,4))表示在第2个位置切分,以及第3个位置切分
同理,vsplit表示按列切分
③复制常用操作
a = np.arange(12) b = a print(b is a) b.shape = 3,4 print(a.shape) print(id(a)) print(id(b))
#
True (3, 4) 2570788546080 2570788546080
赋值操作,a和b完全指向一个元素,把b的维度修改一下,a也改变了
————————————————分割线——————————————————
c = a.view() print(c is a) c.shape =2,6 print(a.shape) c[0,4] = 1234 print(a) print(id(a)) print(id(c))
#
False (3, 4) [[ 0 1 2 3] [1234 5 6 7] [ 8 9 10 11]] 2570788546080 2570788626560
可以看出这是一个浅复制,a和c指向不同的元素,但共用值,改变c的元素,其实也改变了a的元素
————————————————分割线——————————————————
那么既想让复制的值指向不同的元素,也不想让他们共用值,可以进行深复制
d = a.copy() d is a d[0,0]= 9999 print(d) print(a) # [[9999 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]]
改变d的元素,对a毫无影响,同时改变a或者d的维度,对对方也毫无影响
————————————————分割线————————————————
补充一点关于索引的内容
data = np.sin(np.arange(20)).reshape(5,4) print(data) ind = data.argmax(axis=0) print(ind) data_max = data[ind, range(data.shape[1])] print(data_max)
#
[[ 0. 0.84147098 0.90929743 0.14112001] [-0.7568025 -0.95892427 -0.2794155 0.6569866 ] [ 0.98935825 0.41211849 -0.54402111 -0.99999021] [-0.53657292 0.42016704 0.99060736 0.65028784] [-0.28790332 -0.96139749 -0.75098725 0.14987721]] [2 0 3 1] [0.98935825 0.84147098 0.99060736 0.6569866 ]
axis表示按列索引;
ind相当于是把每列中最大数的行给拿出来放到一个ndarray中;
注意data[,]取数的方法,很巧妙,ind是按行作索引,range(data.shape[1])相当于把一共多少列给变成了range循环(python基础)
————————————分割线—————————
接下去是扩展操作
a = np.arange(0,40,10) print(a) b= np.tile(a,(3,5)) print(b) # [ 0 10 20 30] [[ 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30] [ 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30] [ 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30 0 10 20 30]]
相当于把一个维度的向量扩展成所需类型的矩阵,矩阵每个元素都是相同的向量
————————————分割————————————
a = np.array([[4,3,5],[1,2,1]]) print(a) print('-------') b = np.sort(a,axis=1) print(b) a.sort(axis=1) print('-------') print(a) a = np.array([4,3,1,2]) j= np.argsort(a) print('-------') print(j) print('-------') print(a[j])
#
[[4 3 5] [1 2 1]] ------- [[3 4 5] [1 1 2]] ------- [[3 4 5] [1 1 2]] ------- [2 3 1 0] ------- [1 2 3 4]
axis=1表示按行索引排序
argsort表示按元素值从小到大,对其索引进行排序
a[j]又表示按照索引对其元素值进行排序,其实就是从小到大排序
————————————————分割线————————————
x_data = np.linspace(-1,1,300)[:, np.newaxis]
比如,今天写了这么一行代码,意思是生成-1到1的300个均匀分布值(300,),然后变成(300,1)
noise = np.random.normal(0,0.05,x_data.shape)
表示生成一个正态分布,均值为0,标准差为0.05,维度为x_data的维度,
所以标准正态分布则是
np.random.normal(loc=0,scale=1,size=None)
也相当于
np.random.randn(size=None)
————————————————分割线————————————
又发现一个很绝的操作,那就是shuffle,先看代码
p = np.random.permutation(3) a = np.array([1,0,2]) print(a,p) print(type(a)) print(type(p)) print(np.array([1,2,3])[a]) print(np.array([1,2,3])[p])
#
[1 0 2] [2 0 1] <class 'numpy.ndarray'> <class 'numpy.ndarray'> [2 1 3] [3 1 2]
np.random.permutation(3)这个其实效果np.array是类似的,都是生成ndarray的一维数组,不同的是前一个函数是“字典”shuffle的,把数组已经打乱了,其实真正神奇的,原来
ndarray格式的数据后面加[ndarray]这个索引,就可以对数组里面的元素起到按索引排序的效果,简直牛逼。。以前一直不知道!