目录
前言
本节主要介绍使用数组进行文件输入和输出、线性代数和伪随机数生成。
一、使用数组进行文件输入和输出
numpy可以在硬盘中将数据以文本或二进制文件的形式进行存入硬盘或由硬盘载入。
np.save 和 np.load 是高效存取硬盘数据的两大工具函数。
代码:
import numpy as np
arr = np.arange(10)
np.save('some_array', arr)
a = np.load('some_array.npy')
print(a)
二、线性代数
numpy 中的 * 是矩阵的逐元素乘积,不是矩阵的点乘积。
代码:
import numpy as np
x = np.array([[1., 2., 3.], [4., 5., 6.]])
y = np.array([[6., 23.], [-1, 7], [8, 9]])
'''正常理解的矩阵乘法'''
z = np.dot(x, y)
print('z is :')
print(z)
'''一个二维数组和一个长度合适的一维数组'''
a = np.ones(3)
b = np.dot(x, a)
print('b is :')
print(b)
#x的第一行和ones(3)相乘,然后加起来,第二行也是类似操作,然后形成矩阵
结果:
z is :
[[ 28. 64.]
[ 67. 181.]]
b is :
[ 6. 15.]
numpy.linalg 拥有一个矩阵分解的标准函数集,以及其他常用函数,具体如下:
示例:
代码:
import numpy as np
from numpy.linalg import inv, qr
x = np.random.randn(5, 5)
x_T = x.T
mat = np.dot(x_T, x)
Inv = inv(mat)
print(Inv.round(4))
result = np.dot(mat, Inv)
print(result.round(4))
结果:
[[ 0.4508 -0.1697 -0.105 0.5279 -0.2396]
[-0.1697 0.2645 -0.0727 -0.2067 0.1752]
[-0.105 -0.0727 0.836 -0.172 -0.0875]
[ 0.5279 -0.2067 -0.172 1.6191 -0.1698]
[-0.2396 0.1752 -0.0875 -0.1698 0.3813]]
[[ 1. -0. -0. 0. 0.]
[ 0. 1. 0. 0. 0.]
[ 0. -0. 1. 0. -0.]
[-0. 0. -0. 1. 0.]
[ 0. 0. -0. 0. 1.]]
三、伪随机数生成
numpy.random 可以高效地生成多种概率分布下地完整样本数组。具体如下表所示:
1. 随机数种子
随机数种子(random seed)在伪随机数生成器中用于生成伪随机数的初始数值。对于一个伪随机数生成器,从相同的随机数种子出发,可以得到相同的随机数序列。随机数种子通常由当前计算机状态确定,如当前的时间。
示例:
没有随机数时:
import numpy as np
#np.random.seed(10)
samples = np.random.normal(size = (4, 4))
print(samples)
两次运行结果:
[[-0.00497107 -0.57611807 1.28986872 -0.76243425]
[ 0.13608203 -0.73315417 0.66520774 -1.02985713]
[ 0.80703359 0.18494467 -0.09032636 -0.39237101]
[ 0.60811744 1.81548702 -1.18619687 0.12754176]]
runfile('C:/Users/Administrator/.spyder-py3/untitled0.py', wdir='C:/Users/Administrator/.spyder-py3')
[[-0.49937121 -0.20125874 -0.97962712 -0.79342261]
[ 2.91945642 -0.0277508 -1.72219211 -1.92251742]
[-1.68700434 -0.90374663 1.81195271 2.06828702]
[ 0.07127939 -1.340553 -1.20237213 -1.10419474]]
可以看出,每次的数据都是随机的,不一样的。
当设置了随机数种子:
import numpy as np
np.random.seed(10)
samples = np.random.normal(size = (4, 4))
print(samples)
连续两次运行结果:
[[ 1.3315865 0.71527897 -1.54540029 -0.00838385]
[ 0.62133597 -0.72008556 0.26551159 0.10854853]
[ 0.00429143 -0.17460021 0.43302619 1.20303737]
[-0.96506567 1.02827408 0.22863013 0.44513761]]
runfile('C:/Users/Administrator/.spyder-py3/untitled0.py', wdir='C:/Users/Administrator/.spyder-py3')
[[ 1.3315865 0.71527897 -1.54540029 -0.00838385]
[ 0.62133597 -0.72008556 0.26551159 0.10854853]
[ 0.00429143 -0.17460021 0.43302619 1.20303737]
[-0.96506567 1.02827408 0.22863013 0.44513761]]
可以看出,是一样的。
设置随机数种子,可以让每次的随机数都保持相同,使得实验结果是可复现的。
四、示例:随机漫步
随机漫步的模拟提供了一个使用数组操作的说明性应用。
首先考虑一个简单的随机漫步,从0开始,步进为1和-1,且两种步进发生的概率相等。
代码:
import numpy as np
import matplotlib.pyplot as plt
position = 0
walk = [position]
steps = 100
for i in range(steps):
if np.random.randint(0, 2):
step = 1
else:
step = -1
position += step
walk.append(position)
plt.plot(walk[:100])
结果:
说明:
主要是这一行代码
虽然网上的相关资料都显示,该函数是左闭右闭区间,但是真正测试发现是左闭右开区间,因此不能写成(0,1),而应写为(0,2)
具体测试如下:
import numpy as np
result_1 = []
for i in range(100):
a = np.random.randint(0, 2)
result_1.append(a)
print(result_1)
result_2 = []
for j in range(100):
b = np.random.randint(0, 1)
result_2.append(a)
print(result_2)
结果:
[0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
但是将随机生成的数值改小之后,又会变得不一样,具体测试如下:
import numpy as np
result_1 = []
for i in range(10):
a = np.random.randint(0, 2)
result_1.append(a)
print(result_1)
result_2 = []
for j in range(10):
b = np.random.randint(0, 1)
result_2.append(a)
print(result_2)
结果:
[1, 0, 1, 0, 1, 0, 1, 0, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
可能有一定的运气在里面?还挺有意思
具体细节详见往期文章
使用np.random 模块一次性抽取1000次投掷硬币的结果,每次投掷的结果为1或-1,然后计算累计值
代码:
import numpy as np
nsteps = 100
draws = np.random.randint(0, 2, size = nsteps)
steps = np.where(draws > 0, 1, -1)
walk = steps.cumsum()
print(walk)
Min = walk.min()
print(Min)
Max = walk.max()
print(Max)
结果:
[ 1 2 3 4 3 4 5 4 5 6 7 6 5 6 7 6 7 6 5 6 7 8 7 6
7 8 9 10 11 10 11 12 13 12 11 12 13 14 15 16 17 16 15 14 13 12 13 14
13 14 13 12 11 12 13 14 15 14 13 14 15 16 15 16 15 14 13 14 13 14 13 12
11 12 13 14 13 14 15 14 13 14 15 14 13 12 11 10 11 12 13 14 13 14 13 12
11 12 13 12]
1
17
总结
本系列的后续文章,会集中在打造pandas数据处理技能上。