python --Numpy详解(科学计算)
- pip install numpy
-
NumPy系统是Python的一种开源的数值计算扩展
导包
- import numpy as np
-
查看版本
- print(np.__version__) # 获取当前numpy版本号
- # 1.21.3
-
创建ndarray
- import numpy as np
-
- t = np.array([1, 2, 3, 4]) # 一维数组
- print(t, type(t))
- 输出:
- [1 2 3 4] <class 'numpy.ndarray'>
-
-
-
- t = np.array([[1,2,3],[4,5,6]]) # 二维数组
- print(t)
- 输出: [[1 2 3 4]
- [4 5 6 7]]
-
可以使用多种方式来构建多维数组,最常见的是使用列表来构建多维数组。下面的例子便使用一维列表构建了一个一维数组。
- import numpy as np
- nda1 = np.array([1, 2, 3]) # 使用一维列表来作为输入
- nda1
- array([1, 2, 3])6 >>> type(nda1)
- <class 'numpy.ndarray'>
-
如果希望构建二维数组,可以使用下面的方法:
- input_list = [
- ... [1, 2, 3],
- ... [4, 5, 6]
- ... ]
- nda2 = np.array(input_list)
- nda2
- array([[1, 2, 3], # 查看值
- [4, 5, 6]])
- type(nda2) # 查看类型
- <class 'numpy.ndarray'>
-
也可以指定一些特征值,让 NumPy 自动产生相关的数组。例如指定维度,让其产生所有元素都为 0 的数组,代码如下:
- np.zeros(5) # 5个元素的一维数组
- array([0., 0., 0., 0., 0.])
- np.zeros((5, 2)) # 二维数组,5行,2列
- array([[0., 0.],
- [0., 0.],
- [0., 0.],
- [0., 0.],
- [0., 0.]])
-
也可以指定维度,让其产生所有元素值都为 1 的数组,代码如下:
- np.ones((5, 2)) # 二维数组,5行,2列,所有元素都为1
- array([[1., 1.],
- [1., 1.],
- [1., 1.],
- [1., 1.],
- [1., 1.]])
- np.ones(5) # 一维数组,5个元素
- array([1., 1., 1., 1., 1.])
-
还可以让 NumPy 自动产生等差数组,此时需要指定开始值、结束值和步长。代码如下:
- np.arange(3,7,2) # 从3开始,直到7,步长为2
- array([3, 5])
- np.arange(3,7,1) # 从3开始,直到7,步长为1
- array([3, 4, 5, 6])
- np.arange(7, 3, -1) # 从7开始,直到3,步长为-1
- array([7, 6, 5, 4])
- np.arange(7, 3, -2) # 从7开始,直到3,步长为-2
- array([7, 5])
-
arange() 函数和 range() 类似,如果仅提供一个值,那么开始值是 0,步长是 1,代码如下:
- np.arange(7)
- array([0, 1, 2, 3, 4, 5, 6])
- 如果提供两个参数,那么步长为 1:
- np.arange(2, 5) # 从2开始,直到5,步长为1
- array([2, 3, 4])
- np.arange(2, 6) # 从2开始,直到6,步长为1
- array([2, 3, 4, 5])
-
另外一个等差数列函数是 linspace(),其指定开始位置和结束位置,但不指定步长,而是指定元素个数。例如从 1 开始,到 5 结束,一共有 8 个数,那么生成的数组如下面所示:
- np.linspace(1, 5, 8) # 包括1和5,等分8个点
- array([1. , 1.57142857, 2.14285714, 2.71428571, 3.28571429,
- 3.85714286, 4.42857143, 5])
- # 可以发现元素个数和指定的一致,开始值和结束值也都被包含,而且它们的确是等差数列。
-
inspace() 函数比较有用,例如要画正弦函数在 0 到 2π 之间的图形,便可以使用该函数在 0 到 2π 之间产生均匀分布的 100 个点,然后使用 matplotlib 将它们画出来。下面是演示的代码:
- import matplotlib.pyplot as plt
- import numpy as np
- x = np.linspace(0, 2*np.pi, 100)
- y = [np.sin(e) for e in x]
- plt.plot(x, y)
- plt.savefig("sindemo1.png")
-
还可以使用 logspace() 函数让 NumPy 自动产生等比数列,此时需要指定开始点和结束点,同时指定点的个数。如果没有提供点的数目,默认是生成 50 个点。
- np.logspace(2.0, 3.0, num=4) # 4个点,其实位置是102,结束位置是103
- array([ 100. , 215.443469, 464.15888336, 1000.])
-
下面是一个例子,其演示了 logspace() 的用法和参数 endpoint 的用法。endpoint=True 表示结束值被包含在输出数组中,否则表示不包含在输出数组中。下面是完整的代码:
- import matplotlib.pyplot as plt
- import numpy as np
- N = 10 # 一共10个点
- x1 = np.logspace(0.1, 1, N, endpoint=True) # 10被算作是最后一个点
- x2 = np.logspace(0.1, 1, N, endpoint=False) # 10不被算作是最后一个点
- y = np.zeros(N)
- plt.plot(x1, y, 'o')
- plt.plot(x2, y + 0.5, 'x')
- plt.ylim([-0.5, 1]) # y轴的范围是-0.5到1
- plt.savefig("logspace1.png") # 保存图片到文件
-
还可以使用 full() 函数指定维度和一个值,让所有的元素都等于该值。该函数和 ones() 类似,但值是由用户指定的。
- np.full((2, 2), np.inf) # 所有元素都是无穷大
- array([[inf, inf],
- [inf, inf]])
- np.full((2, 2), 11) # 所有元素都是11
- array([[11, 11],
- [11, 11]])
- np.full((2, 2), 1.51) # 所有元素都是1.51
- array([[1.51, 1.51],
- [1.51, 1.51]])
-
使用 eye() 函数还可以自动生成单位矩阵,就是仅对角线上的值为 1,其他位置上的值都为 0。
- np.eye(2) # 2x2的单位矩阵
- array([[1., 0.],
- [0., 1.]])
- np.eye(3) # 3x3的单位矩阵
- array([[1., 0., 0.],
- [0., 1., 0.],
- [0., 0., 1.]])
-
还可以自动产生随机的矩阵,例如可以使用 random.normal() 函数产生一个正态分布的一维矩阵:
- mu, sigma = 0, 0.1 # mu是平均值,sigma代表分散程度
- s = np.random.normal(mu, sigma, 1000)
- s.size # 元素个数为1000
- 1000
- np.mean(s) # 平均值接近0
- -0.0011152161285000821
- abs(mu - np.mean(s)) < 0.01 # 平均值接近mu=0
- True
- abs(sigma - np.std(s, ddof=1)) < 0.01 # 分散程度检查
- True
-
可以将生成的数据画出来,使用下面的代码:
- import matplotlib.pyplot as plt
- import numpy as np
- mu, sigma = 0, 0.1
- s = np.random.normal(mu, sigma, 1000)
- count, bins, ignored = plt.hist(s, 30, density=True)
- plt.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *
- np.exp( - (bins - mu)**2 / (2 * sigma**2) ),
- linewidth=2, color='r')
- plt.savefig("rand1.png")
-
还可以生成完全随机的矩阵,方法是使用 np.random.rand(外形)函数。例如在下面的例子中,就生成了随机内容组成的指定外形的矩阵。
- np.random.rand(3,2) # 3x2的二维矩阵
- array([[0.11319256, 0.84668147],
- [0.4040353 , 0.70912343],
- [0.6511614 , 0.80706271]])
- np.random.rand(3,2,2) # 3x2x2的三维矩阵
- array([[[0.64851863, 0.3895985 ],
- [0.63038544, 0.58402249]],
- [[0.39816687, 0.92149102],
- [0.07113285, 0.17109903]],
- [[0.06713956, 0.39415293],
- [0.06125844, 0.71276929]]])
- np.random.rand(4) # 一维矩阵
- array([0.11918788, 0.91847982, 0.29599804, 0.42242323])
-
ndarray 是一个类,其包含一些属性。
最基本的便是其维度。可以用属性 ndim 来得到指定矩阵的维度,方法如下:
- a = np.array([1, 2, 3])
- a.ndim # 维度为1
- 1
- b = np.eye(3)
- b.ndim # 维度为2
- 2
-
可以用属性 shape 来得到指定数组的外形,方法如下:
- a = np.eye(3) # 3x3的单元矩阵
- a # 查看a的值
- array([[1., 0., 0.],
- [0., 1., 0.],
- [0., 0., 1.]])
- a.shape # a的外形
- (3, 3)
-
可以用属性 dtype 来得到指定矩阵每个元素的类型,方法如下:
- a = np.eye(3, dtype=int) # 指定类型为整型
- a
- array([[1, 0, 0],
- [0, 1, 0],
- [0, 0, 1]])
- a.dtype # 查看类型
- dtype('int64')
-
可以用属性 size 来得到指定矩阵的元素个数,方法如下:
- a = np.eye(3, dtype=int)
- a
- array([[1, 0, 0],
- [0, 1, 0],
- [0, 0, 1]])
- a.size # 矩阵元素个数,9个
- 9
-
可以用属性 T 来得到指定矩阵的转置矩阵,方法如下:
- a = np.array([1, 2, 3]) # 一维矩阵
- a.T # 转置矩阵是自己
- array([1, 2, 3])
- b = np.array([[1, 2, 3], [4, 5, 6]]) # 二维矩阵
- b
- array([[1, 2, 3],
- [4, 5, 6]])
- b.T # 转置矩阵
- array([[1, 4],
- [2, 5],
- [3, 6]])
-
需要注意的是,转置矩阵就是将原矩阵旋转 90 度得到的矩阵,但其仅对二维以及多维矩阵有效。对于一维矩阵来说,其转置矩阵还是自己。
对于多维矩阵,可以进行变形、加减乘除等操作,本节就来介绍常见的相关操作。、
变形reshape(维度列表)
例如原来是 3×4 的矩阵,可以将其变成 6×2 的矩阵。内容不变,但是样子发生了改变。方法如下:
- x = np.arange(1, 7) # 一维矩阵
- x
- array([1, 2, 3, 4, 5, 6])
- y = x.reshape(2, 3) # 变成2行3列的二维矩阵
- y
- array([[1, 2, 3],
- [4, 5, 6]])
-
加减乘除操作
加法操作是指对外形相同的两个矩阵,进行相同位置元素的加法运算,得到一个和输入矩阵相同外形的矩阵。下面的代码便演示了加法操作的使用:
- a = numpy.random.rand(3,2) # a是3行2列的随机二维矩阵
- b = numpy.random.rand(3,2) # b是3行2列的随机二维矩阵
- a # 查看a的值
- array([[0.49219148, 0.30470874],
- [0.42371119, 0.96857757],
- [0.09432051, 0.55935613]])
- b # 查看b的值
- array([[0.41471195, 0.85316671],
- [0.6231908 , 0.98244841],
- [0.65246256, 0.73501929]])
- a+b # a+b的值
- array([[0.90690343, 1.15787545],
- [1.04690199, 1.95102597],
- [0.74678307, 1.29437542]])
-
与之类似的还有减法、乘法和除法操作,其运算符号和普通的数值运算符号相同,都是对相同的位置进行操作。下面的例子是减法操作的使用:
- a = numpy.random.rand(3,2) # 随机生成3x2的矩阵
- b = numpy.random.rand(3,2) # 随机生成3x2的矩阵
- a # 查看矩阵a的内容
- array([[0.49219148, 0.30470874],
- [0.42371119, 0.96857757],
- [0.09432051, 0.55935613]])
- b # 查看矩阵b的内容
- array([[0.41471195, 0.85316671],
- [0.6231908 , 0.98244841],
- [0.65246256, 0.73501929]])
- a-b # 减法操作
- array([[ 0.07747953, -0.54845797],
- [-0.19947961, -0.01387084],
- [-0.55814205, -0.17566316]])
-
下面的例子是乘法操作的使用:
- a = numpy.random.rand(3,2) # 随机生成3x2的矩阵
- b = numpy.random.rand(3,2) # 随机生成3x2的矩阵
- a # 查看矩阵a的内容
- array([[0.49219148, 0.30470874],
- [0.42371119, 0.96857757],
- [0.09432051, 0.55935613]])
- b # 查看矩阵b的内容
- array([[0.41471195, 0.85316671],
- [0.6231908 , 0.98244841],
- [0.65246256, 0.73501929]])
- a * b # 乘法操作
- array([[0.20411769, 0.25996735],
- [0.26405291, 0.95157749],
- [0.0615406 , 0.41113754]])
-
下面是除法操作运算的例子:
- a = numpy.random.rand(3,2) # 随机生成3x2的矩阵
- b = numpy.random.rand(3,2) # 随机生成3x2的矩阵
- a # 查看矩阵a的内容
- array([[0.49219148, 0.30470874],
- [0.42371119, 0.96857757],
- [0.09432051, 0.55935613]])
- b # 查看矩阵b的内容
- array([[0.41471195, 0.85316671],
- [0.6231908 , 0.98244841],
- [0.65246256, 0.73501929]])
- a / b # 除法操作
- array([[1.18682735, 0.3571503 ],
- [0.67990604, 0.98588135],
- [0.1445608 , 0.76100877]])
-
逻辑判断
还可以对矩阵进行逻辑判断,例如判断矩阵元素是否大于 0 或者小于 1。其结果是一个矩阵,分别表示各元素是否满足规定的判断。例如下面就是判断矩阵元素是否小于 0.5 的操作:
- a = np.random.rand(3,2) # 随机生成3x2的矩阵
- a # 查看矩阵a的内容
- array([[0.36826283, 0.1993915 ],
- [0.3278179 , 0.66236192],
- [0.98973706, 0.67244684]])
- a < 0.5 # 各个元素是否小于0.5
- array([[ True, True],
- [ True, False],
- [False, False]])
-
当然也可以和其他矩阵进行比较,例如下面的例子:
- a = numpy.random.rand(3,2) # 随机生成3x2的矩阵
- b = numpy.random.rand(3,2) # 随机生成3x2的矩阵
- a # 查看矩阵a的内容
- array([[0.49219148, 0.30470874],
- [0.42371119, 0.96857757],
- [0.09432051, 0.55935613]])
- b # 查看矩阵b的内容
- array([[0.41471195, 0.85316671],
- [0.6231908 , 0.98244841],
- [0.65246256, 0.73501929]])
- a < b # a的各个元素是否小于b对应的元素
- array([[False, True],
- [ True, True],
- [ True, True]])
-
我们知道 NumPy 有强大的数值计算功能,在生活中,经常会用到的一个计算就是贷款计算。
例如如果贷款 200 万,在 15 年内还清,每个月需要还多少钱?其中支付的利息是多少?再例如,如果购买了一份医疗保险,要求每个月存钱 2000 元,一直存 20 年,20 年内每年最多可以报销医疗费用 5000 元,20 年后可以全额返还本金,这样是否划算?
由于一年期固定存/贷款利率是由央行规定的,所以这个利率在一定时间内基本是固定的。在本节中会经常用到这个概念。
首先来看看存款利息的问题,假定一年期存款利率是 5%,那么每个月存入 100 元,10 年后账户余额是多少?可以使用函数 np.fv() 来处理这类问题,该函数定义如下:
- np.fv(利率,年限,每月存款,当前存款)
-
在上面的问题中,可以这么来求解,月利率是 0.05/12;年限是 12*10 个月;每月存款是 -100,负数表示支出;当前存款是 0。计算方法如下:
- np.fv(0.05/12, 10*12, -100, 0)
- 15528.227944566719
-
其中本金部分是 12000,由此得出利息收入是 3528.22。
下面来看一个贷款的问题。如果我们的还款能力是每个月 13000 元,贷款 300 万,那么应该贷款多长时间呢?可以使用函数 np.nper() 来完成该任务,该函数定义如下:
- numpy.nper(利率, 还款能力, 贷款数目, 剩余贷款数目=0)
-
对于我们的场景,可以使用下面的方法来计算:
- np.nper(0.05/12, -13000, 3000000, 0)
- array(783.57108846)
-
结果是需要 783 个月才能还清。这里有一个问题,如果每个月还款的数目小于贷款每月产生的利息,那么就永远也还不清,而且欠款还会随着时间而增加。例如上面的例子,300 万每个月的利息是 12500,如果还款低于这个值就永远也还不完了。
如果希望查看每个月还的利息是多少,可以使用利息的计算函数 np.ipmt(),该函数定义如下:
- np.ipmt(利率, 时间段列表, 还款年限, 贷款数目, 未来剩余贷款数目=0)
-
还是以上面的买房贷款为例,可以看到下面的情况:
- per = np.arange(10*12) + 1 # 前10年还的利息
- ipmt = np.ipmt(0.05/12, per, 783, 3000000)
- ipmt # 每个月支付的利息,负数表示支付
- array([-12500. , -12497.91151511, -12495.81432821, -12493.70840303,
- -12491.59370315, -12489.47019203, -12487.33783295, -12485.19658903,
- … # 省略中间数据
- -12202.70446367, -12199.37724738, -12196.0361677 , -12192.68116684,
- -12189.31218682, -12185.92916938, -12182.53205603, -12179.12078805])
-
可以很容易发现每个月还的利息数目都在减少,因为每个月都还了一部分本金,随着本金的减少,利息的基数也在减少,所以利息也在减少。
如果希望得到全部利息的数目,也就是贷款所支付的利息总和,可以对利息列表求和,方法如下:
- per = np.arange(783) + 1 # 总计783个月
- ipmt = np.ipmt(0.05/12, per, 783, 3000000)
- ipmt.sum() # 总计利息为717万
- -7179968.0796168335
-
可以看到利息数目比较大,为了解决这个问题,可以提高每个组的还款金额或者减少还款周期,例如调整为 25 年还完,那么利息总额为:
- per = np.arange(12*25) + 1
- ipmt = np.ipmt(0.05/12, per, 12*25, 3000000)
- ipmt.sum() # 利息总额是226万
- -2261310.3735718103
-
所以说在 5% 的年化利率情况下,等额还款方式,贷款 25 年,利息约是本金的 75%。这是比较常见的情况,如果将年限降低为 15 年,那么可以得到如下的利息总额:
- per = np.arange(12*10) + 1
- ipmt = np.ipmt(0.05/12, per, 12*10, 3000000)
- ipmt.sum() # 利息总额是81万
- -818358.548606708
-
可以看到利息数目大幅下降,但每月的还款金额却上升的很大,每月需要支付的还款金额为:
- np.pmt(0.05/12, 12*15, 3000000)
- -23723.808802246393 # 每月支付的金额
-
本金还款计划和利息的计算方法类似,不过需要将 ipmt() 函数改为 ppmt() 函数。下面是贷款 300万,等额还款 783 个月的情况:
- per = np.arange(10*12) + 1 # 头10年还的利息
- ppmt = np.ppmt(0.05/12, per, 783, 3000000)
- ppmt
- array([-501.23637244, -503.32485732, -505.42204423, -507.52796941,
- -509.64266928, -511.7661804 , -513.89853949, -516.0397834 ,
- -518.18994917, -520.34907396, -522.5171951 , -524.69435008,
- -526.88057654, -529.07591227, -531.28039524, -533.49406355,
- -535.71695548, -537.94910947, -540.19056409, -542.44135811,
- -544.70153043, -546.97112014, -549.25016648, -551.53870884,
- -553.83678679, -556.14444007, -558.46170857, -560.78863235,
- -563.12525165, -565.47160687, -567.82773857, -570.19368748,
- -572.56949451, -574.95520073, -577.3508474 , -579.75647593,
- -582.17212792, -584.59784512, -587.03366947, -589.4796431 ,
- -591.93580827, -594.40220748, -596.87888334, -599.36587869,
- -601.86323652, -604.371 , -606.8892125 , -609.41791755,
- -611.95715888, -614.50698037, -617.06742612, -619.6385404 ,
- -622.22036765, -624.81295252, -627.41633982, -630.03057457,
- -632.65570196, -635.29176739, -637.93881642, -640.59689482,
- -643.26604855, -645.94632375, -648.63776676, -651.34042413,
- -654.05434256, -656.77956899, -659.51615052, -662.26413449,
- -665.02356838, -667.79449991, -670.576977 , -673.37104773,
- -676.17676043, -678.9941636 , -681.82330595, -684.66423639,
- -687.51700404, -690.38165823, -693.25824847, -696.1468245 ,
- -699.04743627, -701.96013392, -704.88496782, -707.82198851,
- -710.7712468 , -713.73279366, -716.7066803 , -719.69295814,
- -722.6916788 , -725.70289412, -728.72665618, -731.76301725,
- -734.81202982, -737.87374661, -740.94822056, -744.03550481,
- -747.13565275, -750.24871797, -753.37475429, -756.51381577,
- -759.66595667, -762.83123149, -766.00969495, -769.20140201,
- -772.40640785, -775.62476789, -778.85653775, -782.10177333,
- -785.36053072, -788.63286626, -791.91883654, -795.21849836,
- -798.53190877, -801.85912505, -805.20020474, -808.55520559,
- -811.92418562, -815.30720306, -818.7043164 , -822.11558439])
-
可以看到最开始时还的本金特别少,而且本金在逐月增加。
总的来说,每个月还给银行的钱分为两部分,一部分是利息,一部分是本金,可以使用的公式表示:
本金+利息=每月还款额
因此,如果本金等于 0,那么就永远也还不完;如果本金小于 0,那么不仅还不完,而且背负的债务还会随时间而增加;只有当本金大于 0 时才是正常的还款情况。
利息=剩余本金*利率
剩余本金=上次剩余本金–最近一次归还本金
归还贷款的最终目的就是将剩余本金降低为 0。当剩余本金降低为 0 时,利息也降低为 0。
傅里叶变换是将时域数据转换成频域数据。例如周期为25的正弦波可以用下面的函数来表示:
- y=sin(2π*f*x)=sin(50πx)
-
如果以 150Hz 的采样频率来采样,也就是在 0 到 1 之间有 150 个采样点,那么其时间列表,即公式中的 x 的列表如下:
- [0. 0.00666667 0.01333333 0.02 0.02666667 0.03333333
- 0.04 0.04666667 0.05333333 0.06 0.06666667 0.07333333
- …. 省略中间数据
- 0.88 0.88666667 0.89333333 0.9 0.90666667 0.91333333
- 0.92 0.92666667 0.93333333 0.94 0.94666667 0.95333333
- 0.96 0.96666667 0.97333333 0.98 0.98666667 0.99333333]
-
得到的输出列表,即 y 的列表如下:
- [ 0.00000000e+00 8.66025404e-01 8.66025404e-01 1.22464680e-16
- -8.66025404e-01 -8.66025404e-01 -2.44929360e-16 8.66025404e-01
- …. 省略中间数据
- 2.25434048e-14 8.66025404e-01 8.66025404e-01 -1.17627991e-14
- -8.66025404e-01 -8.66025404e-01]
-
将这些数据画成一个图,就如图 1 所示。
如何将它们转换成频域图呢?很简单,只需将 y 输入到 np.fft.fft() 函数即可。下面是实现的代码:
- import numpy as np
- import matplotlib.pyplot as plt
- from numpy.fft import fft,ifft
- # x是时域值
- # y是频域值
- # time_span是采样时长
- def show(x, ft, time_span = 5):
- n = len(x) # 采样点个数
- interval = time_span / n
- frequency = np.arange(n / 2) / (n * interval)
- nfft = abs(ft[range(int(n / 2))] / n )
- plt.plot(frequency, nfft, 'red')
- plt.xlabel('Freq (Hz)'), plt.ylabel('Amp. Spectrum')
- #plt.show()
- plt.savefig("fftv2_1_1.png")
- time = np.arange(0, 5, .005)
- x = np.sin(2 * np.pi * 10 * time) # 时域信号
- y = np.fft.fft(x) # 频域信号
- show(x, y, 5)
-
如果输入信号中带有两个不同幅度的正弦信号,例如输入信号为:
- y=sin(2*10πx)+3sin(2*50πx)
-
那么它们的傅里叶变换代码如下:
- import numpy as np
- import matplotlib.pyplot as plt
- from numpy.fft import fft, ifft
- # x是时域值
- # y是频域值
- # time_span是采样时长
- def show(x, ft, time_span = 5):
- n = len(x) # 采样点个数
- interval = time_span / n
- frequency = np.arange(n / 2) / (n * interval)
- nfft = abs(ft[range(int(n / 2))] / n )
- plt.plot(frequency, nfft, 'red')
- plt.xlabel('Freq (Hz)'), plt.ylabel('Amp. Spectrum')
- #plt.show()
- plt.savefig("fftv2_1_2.png")
- time = np.arange(0, 5, .0005)
- x0 = np.sin(2 * np.pi * 10 * time) # 10HZ
- x1 = 3 * np.sin(2 * np.pi * 50 * time) # 30HZ
- x = x0 + x1 # 时域信号
- y = np.fft.fft(x) # 频域信号
- show(x, y, 5)
-
反变换也很简单,下面便是一个反变换的例子代码:
- import numpy as np
- import matplotlib.pyplot as plt
- from numpy.fft import fft,ifft
- # 在0到2π之间取50个点
- x = np.linspace(0, 2*np.pi, 50)
- wave = np.cos(x) # 时域的值
- transformed=np.fft.fft(wave) # 傅里叶变换
- reversed_data = np.fft.ifft(transformed) # 反变换
- plt.plot(x, wave, 'r')
- # 反变换出来的值+0.2,以免和变换之前的值重合
- plt.plot(x, reversed_data.real+0.2, 'b')
- plt.savefig("fft4.png")
-
运行该脚本,可以得到如图 5 所示的时域图,其中上面那条曲线是傅里叶变换后再傅里叶反变换并向上移动 0.2 的曲线;下面那条曲线是 y=cos(x) 的曲线。可以发现傅里叶变换后再次反变换得到的曲线近似于输入的曲线。
在 20 世纪,人们认为任何神经网络都可以等效于某个 3 层的神经网络,这样就没有必要去研究多层的神经网络。直到最近几年人们才意识到多层神经的独特用途,其在图片识别、博弈等方面有着很大的优势。但不论是多少层的神经网络,其基本工作单元都是神经元,通过多个神经的不同连接方式来搭建不同的神经网络,从而解决不同的问题。
本节将介绍神经元和最简单的神经网络,以及基本的神经网络参数训练。
由于神经网络是由很多的神经元组成,神经元又是由多个输入和一个输出组成,而对于前向神经网络,最终输出和输入之间的关系基本可以用一个矩阵来表示,这和 NumPy 的基本数据结构 ndarray 是很一致的,所以很多 NumPy 的方法也可以用在神经网络技术上。
每个神经元有 n 个输入 x,一个输出 y,输出和输入的关系可以用下面的数学公式表示
- y=S(m)
- m=w1x2+w2x2+...+wnxn
-
简单来说就是对所有输入求一个加权和,然后通过 S(x) 这个函数输出出来,不同的加权和标识不同的神经网络。我们也可以用图 1 来表示神经元的基本形式。
S(x) 这个函数一般来说是固定的,主要是为了将 y 的输出范围压缩到指定的范围。常用的 S(x) 是 Sigmoid 函数,该函数定义如下:
可以使用下面的代码来画出该函数输入 x 和输出 y 的关系:
- import numpy as np
- import matplotlib.pyplot as plt
- x = np.arange(-10,10,0.01)
- y = 1.0/(np.exp(x*-1.0)+1.0)
- plt.plot(x, y, 'b') # 画图
- plt.savefig("sigmod1.png")
-
我们可以发现其规律如下:曲线是平滑的;输出 y 随输入 x 单调递增;输出 y 的范围是 0~1;当 x 超出 -5~5 这个范围,输出 y 基本等于 0 或者 1,和数字信息一致。由于有这些特性,Sigmoid 函数被广泛应用在各种神经元。
该函数还有一个特别的地方,就是求导特别方便,下面是其导数计算公式:
在训练模型的过程中,如果发现对于输入 x,输出 y 和目标输出 y0 存在差别 ∆y,就需要调整权重 w 来消除这种差别。方法就是找到 ∆w,让新的 w’=w+∆w。
该如何找到这个 ∆w 呢?这时就需要求导了,我们需要知道 y 对 w 的在当前 x 位置的导数 ∂,∆y=∆w∂,由于知道了 ∆y 和 ∂,便可以求出 ∆w。但在实际应用中我们并不会使用这个 ∆w,而是自己定义一个固定的步长 s。∂ 的作用是规定了移动的方向,s 确定了移动的长度,结合 s 和 ∂ 可以让 ∆y 变小。
按照这种方式多次迭代就可以让 ∆y 趋近于 0。这个过程就是模型训练,训练的目的就是调整权重 w 以消除 ∆y。∆y 也叫损失函数,就是真实输出和期待输出之间的差别。这种计算 ∂ 的办法也叫作梯度下降法,就是确定某个位置 x 最快下降方向。
在实际应用中,网络非常复杂,包含的神经元个数庞大,神经元之间的连接方式也是数量庞大。为了演示神经网络的使用,不太可能拿实际使用情况作为例子,这里仅以单个神经元组成的神经网络作为例子。该神经元有 3 个输入,输入基本就是 0 和 1;该神经元有一个输出,输出也只有 0 和 1 两个值,它们可以用图 5 表示。
该神经元的输入和输出的关系如表 6 所示
这里使用单个神经元来达到设计目的。由于仅有一个神经元,所以参数个数也就只有 3 个,分别是 w1、w2 和 w3。我们的任务就是通过给代码输入期望的结果来训练这 3 个参数。
- import numpy as np
- class NeuralNetwork():
- def __init__(self):
- # 设置随机数种子
- np.random.seed(1)
- # 将权重转化为一个3x1的矩阵,其值分布为-1~1,并且均值为0
- self.weights = 2 * np.random.random((3, 1)) - 1
- def sigmoid(self, x):
- # 应用Sigmoid激活函数
- return 1 / (1 + np.exp(-x))
- def sigmoid_derivative(self, x):
- #计算Sigmoid函数的偏导数
- return x * (1 - x)
- def train(self, training_inputs, training_outputs, iterations_num):
- # 训练模型
- # 输入是training_inputs,是一个二维矩阵
- # 期待值是training_outputs,是一个一维矩阵
- # iterations_num是迭代的次数
- for iteration in range(iterations_num):
- # 得到输出
- output = self.think(training_inputs)
- # 计算误差
- error = training_outputs - output
- # 微调权重
- adjustments = np.dot(training_inputs.T, error * self.sigmoid_
- derivative(output))
- self.weights += adjustments
- def think(self, inputs):
- # 基于当前参数,计算inputs的输出
- inputs = inputs.astype(float)
- output = self.sigmoid(np.dot(inputs, self.weights))
- return output
- if __name__ == "__main__":
- # 初始化神经类
- neural_network = NeuralNetwork()
- print(u"随机生成最初的权重值")
- print(u"初始权重值为:", neural_network.weights)
- #训练数据的输入部分
- training_inputs = np.array([[0,0,1],
- [1,1,1],
- [1,0,1],
- [0,1,1]])
- # 训练数据的输出
- training_outputs = np.array([[0,1,1,0]]).T
- # 开始训练,进行150000次训练
- neural_network.train(training_inputs, training_outputs, 15000)
- print(u"训练后的权重:", neural_network.weights)
- # 验证结果
- y = neural_network.think(np.array(training_inputs[0]))
- assert abs(y - training_outputs[0]) < 1e-2
- y = neural_network.think(np.array(training_inputs[1]))
- assert abs(y - training_outputs[1]) < 1e-2
- y = neural_network.think(np.array(training_inputs[2]))
- assert abs(y - training_outputs[2]) < 1e-2
- y = neural_network.think(np.array(training_inputs[3]))
- assert abs(y - training_outputs[3]) < 1e-2
- print(u"验收通过")
-
$ python ex1.py
随机生成最初的权重值
初始权重值为: [[-0.16595599]
[ 0.44064899]
[-0.99977125]]
训练后的权重: [[10.08740896]
[-0.20695366]
[-4.83757835]]
验收通过
可以发现,其实训练就是调整权重参数的一个过程。虽然不知道最终我们期望的参数是多少,但是可以通过比较实际输出和期望输出的差值来微调这些权重,最终可以达到输出和我们的期望一致。
使用np的routines函数创建
注:函数返回给定形状和数据类型的新数组,其中元素的值设置为1。
- t = np.ones([3, 3])
- print(t)
- 输出:
- [[1. 1. 1.]
- [1. 1. 1.]
- [1. 1. 1.]]
-
-
- t = np.ones([3, 3], dtype=int)
- print(t)
- 输出:
- [[1 1 1]
- [1 1 1]
- [1 1 1]]
-
numpy.full(shape, fill_value, dtype=None, order=‘C’)[source]- np.full((2,3), 3) # 2行3列,填充值为3
- 输出:
- [[3, 3, 3],
- [3, 3, 3]]
-
numpy.eye(N, M=None, k=0, dtype=<class ‘float’>, order=‘C’)
注: 返回一个二维数组,其对角线元素为1,其余位置元素为0。
- np.eye(5,k=1) # 5行5列,从第1个元素为对角填充1
- 返回值:维度为(N,M)的多维数组 除了第k条对角线上元素为1以外,其余元素均为0的数组
- 输出:
- [[0., 1., 0., 0., 0.],
- [0., 0., 1., 0., 0.],
- [0., 0., 0., 1., 0.],
- [0., 0., 0., 0., 1.],
- [0., 0., 0., 0., 0.]]
-
-
- np.eye(3,4) # 3行4列
- 输出:
- [1., 0., 0., 0.],
- [0., 1., 0., 0.],
- [0., 0., 1., 0.]]
-
linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
在指定的大间隔内,返回固定间隔的数据。他将返回“num”个等间距的样本,在区间[start, stop]中。其中,区间的结束端点可以被排除在外。
当‘endpoint=False’时,不包含该点。在这种情况下,队列包含除了“num+1"以外的所有等间距的样本。
要注意的是,当‘endpoint=False’时,步长会发生改变。
- np.linspace(0,10,5) # 返回0到10的等差数列(默认包含10)
- 输出:
- [ 0. , 2.5, 5. , 7.5, 10. ]
-
-
- np.linspace(1,11, 6, retstep=True) # 返回步进差值,二元组
- 输出:
- ([ 1., 3., 5., 7., 9., 11.]), 2.0)
-
-
-
- 注意:np.arange([start, ]stop, [step, ]dtype=None) # 返回等差数列,
-
- 区别:
- arange()类似于内置函数range(),通过指定开始值、终值和步长创建表示等差数列的一维数组,注意
- 得到的结果数组不包含终值。
-
- linspace()通过指定开始值、终值和元素个数创建表示等差数列的一维数组,可以通过endpoint参数
- 指定是否包含终值,默认值为True,即包含终值
-
np.random.randint(low, high=None, size=None, dtype=‘l’)
随机数组
- import numpy as np
-
- r = np.random.randint(0, 10, 6)
- print(r)
- # 输出: [1 0 1 3 6 4]
-
np.random.randn(d0, d1, …, dn)
- np.random.randn(10)
- # 每次都不一样
- # 输出结果:
- array([-1.74976547, 0.3426804 , 1.1530358 , -0.25243604, 0.98132079,
- 0.51421884, 0.22117967, -1.07004333, -0.18949583, 0.25500144])
-
-
- //
- np.random.seed(100) #随机的种子,有了种子,每次都一样
- np.random.randn(10)
-
- # 输出结果:
- array([ 0.37332715, -0.2887605 , 0.04985088, -0.93815832, -0.4087037 ,
- 1.13352254, 0.52713526, -0.76014192, -0.97292788, 0.16290446])
-
np.random.random(size=None)
- np.random.random(100)
- # 每次每次都不一样
- # 输出结果:
- array([ 0.01150584, 0.52951883, 0.07689008, 0.72856545, 0.26700953,
- 0.38506149, 0.56252666, 0.59974406, 0.38050248, 0.14719008,
- 0.6360734 , 0.27812695, 0.73241298, 0.10904588, 0.57071762,
- 0.56808218, 0.33192772, 0.61444518, 0.07289501, 0.86464595,
- 0.71140253, 0.3221285 , 0.92556313, 0.26511829, 0.8487166 ,
- 0.38634413, 0.32169243, 0.80473196, 0.92050868, 0.17325157,
- 0.63503329, 0.89463233, 0.02796505, 0.04396453, 0.20603116,
- 0.77663591, 0.96595455, 0.77823865, 0.90867045, 0.39274922,
- 0.89526325, 0.26002297, 0.38606984, 0.69176715, 0.3170825 ,
- 0.86994578, 0.35648567, 0.19945661, 0.16109699, 0.58245076,
- 0.20239367, 0.7099113 , 0.41444565, 0.16725785, 0.01170234,
- 0.79989105, 0.76490449, 0.25418521, 0.55082581, 0.29550998,
- 0.02919009, 0.32737646, 0.29171893, 0.67664205, 0.24447834,
- 0.49631976, 0.41136961, 0.82478264, 0.76439988, 0.78829201,
- 0.24360075, 0.26151563, 0.51388418, 0.19823452, 0.44097815,
- 0.53198973, 0.50187154, 0.72374522, 0.11090765, 0.63469357,
- 0.69199977, 0.97093079, 0.35920669, 0.86493051, 0.01984456,
- 0.32219702, 0.58608421, 0.26591245, 0.51851213, 0.7896492 ,
- 0.04914308, 0.28711285, 0.36225247, 0.21299697, 0.99046025,
- 0.11375325, 0.70964612, 0.06599185, 0.47323442, 0.62003386])
-
- ///
- np.random.random([3,3])
- # 输出结果:
- array([[ 0.37590691, 0.15563239, 0.7754904 ],
- [ 0.40353019, 0.59708594, 0.57000741],
- [ 0.33286511, 0.15678606, 0.58814922]])
-
np.random.normal(loc=0.0, scale=1.0)
- np.random.normal(loc=0.0, scale=1.0)
- # 输出: 0.9705556599476601
-
np.random.rand(d0,d1,…dn)
- 注:使用方法与np.random.randn()函数相同
- 作用:
- 通过本函数可以返回一个或一组服从“0~1”均匀分布的随机样本值。随机样本取值范围是[0,1),不包括1。
- 应用:在深度学习的Dropout正则化方法中,可以用于生成dropout随机向量(dl),例如(keep_prob表
- 示保留神经元的比例):dl = np.random.rand(al.shape[0],al.shape[1]) < keep_prob
-
- np.random.rand(1,2,3)
-
- # 输出:
- [[[0.77655108 0.94720402 0.60342525]
- [0.09466063 0.67177335 0.9059549 ]]]
-
ndim:维度
shape:形状(各维度的长度)
size:总长度
dtype:元素类型
- np.random.seed(0)
- x = np.random.randint(10,size=(3,4,5))
- print(x)
-
- array([[[5, 0, 3, 3, 7],
- [9, 3, 5, 2, 4],
- [7, 6, 8, 8, 1],
- [6, 7, 7, 8, 1]],
-
- [[5, 9, 8, 9, 4],
- [3, 0, 3, 5, 0],
- [2, 3, 8, 1, 3],
- [3, 3, 7, 0, 1]],
-
- [[9, 9, 0, 4, 7],
- [3, 2, 7, 2, 0],
- [0, 4, 5, 5, 6],
- [8, 4, 1, 4, 9]]])
-
- # 维度:x.ndim
- # 形状,各维度的长度:x.shape
- # 总长度:x.size
- 元素类型:x.dtype
-
索引
- # 一维与列表完全一致 多维时同理
- np.random.seed(1)
- x = np.random.randint(10,size=[3,4,5])
- print(x[2,0,0])
- print(x)
-
- 5
- [[[5 8 9 5 0]
- [0 1 7 6 9]
- [2 4 5 2 4]
- [2 4 7 7 9]]
-
- [[1 7 0 6 9]
- [9 7 6 9 1]
- [0 1 8 8 3]
- [9 8 7 3 6]]
-
- [[5 1 9 3 4]
- [8 1 4 0 3]
- [9 2 0 4 9]
- [2 7 7 9 8]]]
-
切片
- np.random.seed(0)
- x = np.random.randint(100,size = (10,4))
- x
-
- # 输出结果:
- array([[44, 47, 64, 67],
- [67, 9, 83, 21],
- [36, 87, 70, 88],
- [88, 12, 58, 65],
- [39, 87, 46, 88],
- [81, 37, 25, 77],
- [72, 9, 20, 80],
- [69, 79, 47, 64],
- [82, 99, 88, 49],
- [29, 19, 19, 14]])
-
- # 切片:
-
- x[7:10]
- # 切片结果:
- array([[69, 79, 47, 64],
- [82, 99, 88, 49],
- [29, 19, 19, 14]])
-
变形
- # 使用reshape函数,注意参数是一个tuple!
- x = np.arange(0,16).reshape(4,4)
- x
-
- # 执行结果:
- array([[ 0, 1, 2, 3],
- [ 4, 5, 6, 7],
- [ 8, 9, 10, 11],
- [12, 13, 14, 15]])
-
- # 类型是:
- type(x.shape)
-
级联
np.concatenate() 级联需要注意的点:
级联的参数是列表:一定要加中括号
维度必须相同
形状相符
【重点】级联的方向默认是shape这个tuple的第一个值所代表的维度方向
可通过axis参数改变级联的方向
- x = np.array([1,2,3])
- y = np.array([1,5,6,7,3,20])
- x
- # 输出 array([1, 2, 3])
- # 输出 array([ 1, 5, 6, 7, 3, 20])
-
- z = np.concatenate([x,y])
- z
- # 输出 array([ 1, 2, 3, 1, 5, 6, 7, 3, 20])
- z.shape
- # 输出 (9,)
-
-
-
-
- #二维
- x = np.array([[1,2,3],[4,5,6]])
- x
-
- array([[1, 2, 3],
- [4, 5, 6]])
-
- x.shape
- (2,3)
-
- p = np.concatenate([x,x]).shape
- p
- (4, 3)
-
axis
- import numpy as np
- x = np.array([[[1,2,3],[2,2,3],[3,3,3]],[[4,4,4],[5,5,5],[6,6,6]]])
- print(x)
- print(x.shape)
-
- # 输出:
- [[[1 2 3]
- [2 2 3]
- [3 3 3]]
-
- [[4 4 4]
- [5 5 5]
- [6 6 6]]]
- (2, 3, 3)
-
- /
- w = np.concatenate([x,x],axis = 0)
- print(w.shape)
- print(w)
- # 输出:
- (4, 3, 3)
- [[[1 2 3]
- [2 2 3]
- [3 3 3]]
-
- [[4 4 4]
- [5 5 5]
- [6 6 6]]
-
- [[1 2 3]
- [2 2 3]
- [3 3 3]]
-
- [[4 4 4]
- [5 5 5]
- [6 6 6]]]
- /
- w = np.concatenate([x,x],axis = 1)
- print(w.shape)
- print(w)
- # 输出:
- (2, 6, 3)
- [[[1 2 3]
- [2 2 3]
- [3 3 3]
- [1 2 3]
- [2 2 3]
- [3 3 3]]
-
- [[4 4 4]
- [5 5 5]
- [6 6 6]
- [4 4 4]
- [5 5 5]
- [6 6 6]]]
- //
- w = np.concatenate([x,x],axis = 2)
- print(w.shape)
- print(w)
-
- # 输出:
- (2, 3, 6)
- [[[1 2 3 1 2 3]
- [2 2 3 2 2 3]
- [3 3 3 3 3 3]]
-
- [[4 4 4 4 4 4]
- [5 5 5 5 5 5]
- [6 6 6 6 6 6]]]
-
np.hstack与np.vstack 水平级联与垂直级联
- x = np.array([[1,1],[2,2],[3,3]])
- y = np.array([1,2,3])
- print(np.hstack(x))
- print(np.vstack(y))
-
- # 输出:
- [1 1 2 2 3 3]
- [[1]
- [2]
- [3]]
-
切分
np.split()
- x = np.arange(1,10)
- x
-
- # 输出:
- array([1, 2, 3, 4, 5, 6, 7, 8, 9])
- //
- x1,x2,x3 = np.split(x,[3,5])
- print(x1,x2,x3)
- 输出: [1 2 3] [4 5] [6 7 8 9]
-
np.hsplit()
- x = np.arange(16).reshape(4,4)
- x
- # 输出:
- array([[ 0, 1, 2, 3],
- [ 4, 5, 6, 7],
- [ 8, 9, 10, 11],
- [12, 13, 14, 15]])
- //
- print(np.hsplit(x,[2,3]))
- # 输出:
- [array([[ 0, 1],[ 4, 5], [ 8, 9], [12, 13]]),
- array([[ 2], [ 6], [10], [14]]),
- array([[ 3], [ 7], [11], [15]])]
-
np.vsplit()
- x = np.arange(16).reshape(4,4)
- x
- # 输出:
- array([[ 0, 1, 2, 3],
- [ 4, 5, 6, 7],
- [ 8, 9, 10, 11],
- [12, 13, 14, 15]])
-
- print(np.vsplit(x,[2,3]))
- //
- # 输出:
- [array([[0, 1, 2, 3],
- [4, 5, 6, 7]]), array([[ 8, 9, 10, 11]]), array([[12, 13, 14, 15]])]
-
所有赋值运算不会为ndarray的任何元素创建副本。对赋值后的对象的操作也对原来的对象生效。
- a = np.array([1,2,3])
- b=a
- print(a,b)
-
- # 输出:
- [1 2 3] [1 2 3]
-
- //
- b[0]=2
- a
- # 输出:
- array([2, 2, 3])
-
可使用copy()函数创建副本
- a = np.array([1,2,3])
- b = a.copy()
- b
- # 输出:
- [1,2,3]
-
- //
- b[0]=3
- print(a,b)
- 输出: [1 2 3] [3 2 3]
-
求和np.sum
- import numpy as np
- np.random.seed(0)
- a = np.random.randint(1000,size = 100)
- print(np.sum(a))
- //
-
- b = np.random.randint(1000,size = (3,4,5))
- print(np.sum(b))
-
- # 输出:
- 52397
- 32865
-
- //
- # 计算求和时间
- %timeit np.sum(a)
-
- # 输出:
- 2.63 µs ± 34.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
-
- //
- l = [1,2,3]
- np.sum(l)
-
最大最小值:np.max/ np.min
- # 求平均值
- np.mean(heights)
- # 求最大值
- np.max(heights)
- # 求最小值
- np.min(heights)
- # 计算标准差
- heights.std()
-
ndarray的矩阵操作
算术运算符(加减乘除):
- a = np.array([[1,2,3],
- [4,5,6]])
- a
- # 输出:
- array([[1, 2, 3],
- [4, 5, 6]])
-
- //
- a+1
- # 输出:
- array([[2, 3, 4],
- [5, 6, 7]])
-
- //
- a*2
- # 输出:
- array([[ 2, 4, 6],
- [ 8, 10, 12]])
-
- //
- a+[[1,4,9],[3,3,3]]
- # 输出:
- array([[ 2, 6, 12],
- [ 7, 8, 9]])
-
- //
- a*2-2
- # 输出:
- array([[ 0, 2, 4],
- [ 6, 8, 10]])
-
矩阵积
- a = np.array([[1,2,3],
- [4,5,6]])
- a
- # 输出:
- array([[1, 2, 3],
- [4, 5, 6]])
-
- //
- b = np.array([[1,1],
- [1,1],
- [1,1]])
- b
-
- # 输出:
- array([[1, 1],
- [1, 1],
- [1, 1]])
-
- //
- np.dot(a,b)
- # 输出:
- array([[ 6, 6],
- [15, 15]])
-
【重要】ndarray广播机制的两条规则
规则一:为缺失的维度补1
规则二:假定缺失元素用已有值填充
- # 例1: m = np.ones((2, 3)) a = np.arange(3) 求m+a
- m = np.ones((2,3))
- m
- # 输出:
- array([[ 1., 1., 1.],
- [ 1., 1., 1.]])
-
- a = np.arange(3)
- a
- # 输出:
- array([0, 1, 2])
-
- m+a
- # 输出:
- array([[ 1., 2., 3.],
- [ 1., 2., 3.]])
-
- # 例2: a = np.arange(3).reshape((3, 1)) b = np.arange(3) 求a+b
- a = np.arange(3).reshape((3,1))
- a
- # 输出:
- array([[0],
- [1],
- [2]])
-
- b = np.arange(3)
- b
- # 输出:
- array([0, 1, 2])
-
- a+b
- # 输出:
- array([[0, 1, 2],
- [1, 2, 3],
- [2, 3, 4]])
-
- # 习题 a = np.ones((4, 1)) b = np.arange(4) 求a+b
- a = np.ones((4,1))
- b = np.arange(4)
- a+b
-
- # 输出:
- array([[ 1., 2., 3., 4.],
- [ 1., 2., 3., 4.],
- [ 1., 2., 3., 4.],
- [ 1., 2., 3., 4.]])
-
ndarray的排序
选择排序
- import numpy as np
- a = np.array([33,2,67,9,88,22,34])
- def selectSort(x):
- for i in range(len(x)):
- swap = np.argmin(x[i:])+i
- [x[i],x[swap]] = [x[swap],x[i]]
- selectSort(a)
- a
-
- # 输出:
- array([ 2, 9, 22, 33, 34, 67, 88])
-
快速排序
- # np.sort()与ndarray.sort()都可以,但有区别:
- # 1. np.sort()不改变输入
- # 2. ndarray.sort()本地处理,不占用空间,但改变输入
-
- # np.sort()不改变输入
- np.random.seed(10)
- a = np.random.randint(0,100,10)
- b = np.random.randint(0,100,10)
- print(a,b)
- print(np.sort(a),a)
-
- # 输入:
- [ 9 15 64 28 89 93 29 8 73 0] [40 36 16 11 54 88 62 33 72 78]
- [ 0 8 9 15 28 29 64 73 89 93] [ 9 15 64 28 89 93 29 8 73 0]
-
-
- # ndarray.sort()本地处理,不占用空间,但改变输入
- np.random.seed(20)
- a = np.random.randint(0,100,10)
- b = np.random.randint(0,100,10)
- print(a,b)
- print(a.sort(),a)
-
- # 输出:
- [99 90 15 95 28 90 9 20 75 22] [71 34 96 40 85 90 26 83 16 62]
- None [ 9 15 20 22 28 75 90 90 95 99]
-