zoukankan      html  css  js  c++  java
  • NumPy 新知

    import numpy as np
    
    a = np.arange(5)
    a
    
    array([0, 1, 2, 3, 4])
    

    增加一个维度:

    b = a[:, None]
    c = a[:,np.newaxis]
    
    b is c
    
    False
    
    b, c
    
    (array([[0],
            [1],
            [2],
            [3],
            [4]]), array([[0],
            [1],
            [2],
            [3],
            [4]]))
    
    import numpy as np
    
    a = [1, 2, 3, 4]     	#
    b = np.array(a)         	# array([1, 2, 3, 4])
    type(b)                   	# <type 'numpy.ndarray'>
    
    numpy.ndarray
    
    b.shape
    
    (4,)
    
    b.argmax()
    
    3
    
    b.max() 
    
    4
    
    b.mean()  
    
    2.5
    
    c = [[1, 2], [3, 4]]  	# 二维列表
    d = np.array(c)         	# 二维numpy数组
    
    d.shape
    
    (2, 2)
    
    d.size 
    
    4
    
    d.max(axis=0)            	# 找维度0,也就是最后一个维度上的最大值,array([3, 4])
    
    array([3, 4])
    
    d.max(axis=1)        	# 找维度1,也就是倒数第二个维度上的最大值,array([2, 4])
    
    array([2, 4])
    
    d.mean(axis=0)          	# 找维度0,也就是第一个维度上的均值,array([ 2.,  3.])
    
    array([2., 3.])
    
    d.flatten()              	# 展开一个numpy数组为1维数组,array([1, 2, 3, 4])
    
    array([1, 2, 3, 4])
    
    np.ravel(c)               # 展开一个可以解析的结构为 1 维数组,array([1, 2, 3, 4])
    
    array([1, 2, 3, 4])
    
    # 3x3的浮点型2维数组,并且初始化所有元素值为1
    e = np.ones((3, 3), dtype=np.float)
    print(e)
    # 创建一个一维数组,元素值是把3重复4次,array([3, 3, 3, 3])
    f = np.repeat(3, 4)
    print(f)
    # 2x2x3的无符号8位整型3维数组,并且初始化所有元素值为0
    g = np.zeros((2, 2, 3), dtype=np.uint8)
    print(g.shape)                    # (2, 2, 3)
    
    [[1. 1. 1.]
     [1. 1. 1.]
     [1. 1. 1.]]
    [3 3 3 3]
    (2, 2, 3)
    
    h = g.astype(np.float)  # 用另一种类型表示
    
    l = np.arange(10)      	# 类似 range,array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    m = np.linspace(0, 6, 5)# 等差数列,0 到 6之间5个取值,array([ 0., 1.5, 3., 4.5, 6.])
    
    p = np.array(
        [[1, 2, 3, 4],
         [5, 6, 7, 8]]
    )
    
    np.save('p.npy', p)     # 保存到文件
    q = np.load('p.npy')    # 从文件读取
    
    a = np.arange(24).reshape((2, 3, 4))
    b = a[1][1][1] 
    b
    
    17
    
    b1 = a[1, 1, 1]
    b1
    
    17
    

    : 表示当前维度上所有下标

    c = a[:, 2, :]
    c
    
    array([[ 8,  9, 10, 11],
           [20, 21, 22, 23]])
    
    d = a[:, :, 1]
    d
    
    array([[ 1,  5,  9],
           [13, 17, 21]])
    

    ... 表示没有明确指出的维度

    e = a[..., 1]
    e
    
    array([[ 1,  5,  9],
           [13, 17, 21]])
    
    f = a[:, 1:, 1:-1]
    f
    
    array([[[ 5,  6],
            [ 9, 10]],
    
           [[17, 18],
            [21, 22]]])
    

    平均分成3份

    g = np.split(np.arange(9), 3)
    g
    
    [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]
    

    按照下标位置进行划分

    h = np.split(np.arange(9), [2, -3])
    h
    
    [array([0, 1]), array([2, 3, 4, 5]), array([6, 7, 8])]
    
    1. vstack 是指沿着纵轴拼接两个 array,vertical
    2. hstack是指沿着横轴拼接两个 array,horizontal
    3. 更广义的拼接用 concatenate 实现,horizontal 后的两句依次等效于 vstackhstack
    4. stack 不是拼接而是在输入 array 的基础上增加一个新的维度
    l0 = np.arange(6).reshape((2, 3))
    l1 = np.arange(6, 12).reshape((2, 3))
    
    m = np.vstack((l0, l1))
    m
    
    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11]])
    
    p = np.hstack((l0, l1))
    p
    
    array([[ 0,  1,  2,  6,  7,  8],
           [ 3,  4,  5,  9, 10, 11]])
    
    q = np.concatenate((l0, l1))
    q
    
    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11]])
    
    r = np.concatenate((l0, l1), axis=-1)
    r
    
    array([[ 0,  1,  2,  6,  7,  8],
           [ 3,  4,  5,  9, 10, 11]])
    
    s = np.stack((l0, l1))
    s
    
    array([[[ 0,  1,  2],
            [ 3,  4,  5]],
    
           [[ 6,  7,  8],
            [ 9, 10, 11]]])
    

    按指定轴进行转置

    t = s.transpose((2, 0, 1))
    t
    
    array([[[ 0,  3],
            [ 6,  9]],
    
           [[ 1,  4],
            [ 7, 10]],
    
           [[ 2,  5],
            [ 8, 11]]])
    

    默认转置将维度倒序,对于 2 维就是横纵轴互换

    u = a[0].transpose()	# 或者u=a[0].T也是获得转置
    u
    
    array([[ 0,  4,  8],
           [ 1,  5,  9],
           [ 2,  6, 10],
           [ 3,  7, 11]])
    

    逆时针旋转90度,第二个参数是旋转次数

    v = np.rot90(u, 3)
    v
    
    array([[ 3,  2,  1,  0],
           [ 7,  6,  5,  4],
           [11, 10,  9,  8]])
    

    沿纵轴左右翻转

    w = np.fliplr(u)
    w
    
    array([[ 8,  4,  0],
           [ 9,  5,  1],
           [10,  6,  2],
           [11,  7,  3]])
    

    沿水平轴上下翻转

    x = np.flipud(u)
    x
    
    array([[ 3,  7, 11],
           [ 2,  6, 10],
           [ 1,  5,  9],
           [ 0,  4,  8]])
    

    按照一维顺序滚动位移

    y = np.roll(u, 1)
    y
    
    array([[11,  0,  4],
           [ 8,  1,  5],
           [ 9,  2,  6],
           [10,  3,  7]])
    

    按照指定轴滚动位移

    z = np.roll(u, 1, axis=1)
    z
    
    array([[ 8,  0,  4],
           [ 9,  1,  5],
           [10,  2,  6],
           [11,  3,  7]])
    
    import numpy as np
    
    # 绝对值,1
    a = np.abs(-1)
    
    # sin函数,1.0
    b = np.sin(np.pi/2)
    
    # tanh逆函数,0.50000107157840523
    c = np.arctanh(0.462118)
    
    # e为底的指数函数,20.085536923187668
    d = np.exp(3)
    
    # 2的3次方,8
    f = np.power(2, 3)
    
    # 点积,1*3+2*4=11
    g = np.dot([1, 2], [3, 4])
    
    # 开方,5
    h = np.sqrt(25)
    
    # 求和,10
    l = np.sum([1, 2, 3, 4])
    
    # 平均值,5.5
    m = np.mean([4, 5, 6, 7])
    
    # 标准差,0.96824583655185426
    p = np.std([1, 2, 3, 2, 1, 3, 2, 0])
    

    广播

    import numpy as np
    
    a = np.array([
        [1, 2, 3],
        [4, 5, 6]
    ])
    
    b = np.array([
        [1, 2, 3],
        [1, 2, 3]
    ])
    
    '''
    维度一样的array,对位计算
    array([[2, 4, 6],
           [5, 7, 9]])
    '''
    a + b
    
    '''
    array([[0, 0, 0],
           [3, 3, 3]])
    '''
    a - b
    
    '''
    array([[ 1,  4,  9],
           [ 4, 10, 18]])
    '''
    a * b
    
    '''
    array([[1, 1, 1],
           [4, 2, 2]])
    '''
    a / b
    
    '''
    array([[ 1,  4,  9],
           [16, 25, 36]])
    '''
    a ** 2
    
    '''
    array([[  1,   4,  27],
           [  4,  25, 216]])
    '''
    a ** b
    
    c = np.array([
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
        [10, 11, 12]
    ])
    d = np.array([2, 2, 2])
    
    '''
    广播机制让计算的表达式保持简洁
    d和c的每一行分别进行运算
    array([[ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11],
           [12, 13, 14]])
    '''
    c + d
    
    '''
    array([[ 2,  4,  6],
           [ 8, 10, 12],
           [14, 16, 18],
           [20, 22, 24]])
    '''
    c * d
    
    '''
    1和c的每个元素分别进行运算
    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11]])
    '''
    c - 1
    
    array([[ 0,  1,  2],
           [ 3,  4,  5],
           [ 6,  7,  8],
           [ 9, 10, 11]])
    

    线性代数模块(linalg)

    import numpy as np
    
    a = np.array([3, 4])
    np.linalg.norm(a)
    
    5.0
    
    b = np.array([
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]
    ])
    c = np.array([1, 0, 1])
    
    # 矩阵和向量之间的乘法
    np.dot(b, c)            		# array([ 4, 10, 16])
    np.dot(c, b.T)          		# array([ 4, 10, 16])
    
    array([ 4, 10, 16])
    
    np.trace(b)             		# 求矩阵的迹,15
    
    15
    
    np.linalg.det(b)        		# 求矩阵的行列式值,0
    
    0.0
    
    np.linalg.matrix_rank(b)	# 求矩阵的秩,2,不满秩,因为行与行之间等差
    
    2
    
    d = np.array([
        [2, 1],
        [1, 2]
    ])
    
    '''
    对正定矩阵求本征值和本征向量
    本征值为u,array([ 3.,  1.])
    本征向量构成的二维array为v,
    array([[ 0.70710678, -0.70710678],
           [ 0.70710678,  0.70710678]])
    是沿着45°方向
    eig()是一般情况的本征值分解,对于更常见的对称实数矩阵,
    eigh()更快且更稳定,不过输出的值的顺序和eig()是相反的
    '''
    
    u, v = np.linalg.eig(d)
    
    print('矩阵 d 的特征值为: 
    {}; 
    
    特征向量为: 
    {}.'.format(str(u), str(v)))
    
    矩阵 d 的特征值为: 
    [3. 1.]; 
    
    特征向量为: 
    [[ 0.70710678 -0.70710678]
     [ 0.70710678  0.70710678]].
    
    # Cholesky 分解并重建
    l = np.linalg.cholesky(d)
    l
    
    array([[1.41421356, 0.        ],
           [0.70710678, 1.22474487]])
    
    np.dot(l, l.T)
    
    array([[2., 1.],
           [1., 2.]])
    
    e = np.array([
        [1, 2],
        [3, 4]
    ])
    
    # 对不正定矩阵,进行 SVD 分解并重建
    U, s, V = np.linalg.svd(e)
    
    S = np.array([
        [s[0], 0],
        [0, s[1]]
    ])
    
    np.dot(U, np.dot(S, V))
    
    array([[1., 2.],
           [3., 4.]])
    

    随机模块(random)

    随机模块包含了随机数产生和统计分布相关的基本函数,Python 本身也有随机模块 mmrandom,不过功能更丰富,还是来看例子:

    import numpy as np
    import numpy.random as random
    
    # 设置随机数种子
    random.seed(42)
    
    # 产生一个1x3,[0,1)之间的浮点型随机数
    random.rand(1, 3)
    
    array([[0.37454012, 0.95071431, 0.73199394]])
    
    # 产生一个[0,1)之间的浮点型随机数
    random.random()
    
    0.5986584841970366
    
    # 下边4个没有区别,都是按照指定大小产生[0,1)之间的浮点型随机数array,不 Pythonic…
    random.random((3, 3))
    random.sample((3, 3))
    random.random_sample((3, 3))
    random.ranf((3, 3))
    
    array([[0.17052412, 0.06505159, 0.94888554],
           [0.96563203, 0.80839735, 0.30461377],
           [0.09767211, 0.68423303, 0.44015249]])
    
    # 产生 10 个 [1,6) 之间的浮点型随机数
    5 * random.random(10) + 1
    
    array([1.59797123, 4.56622394, 4.80392524, 3.80638599, 4.8548359 ,
           3.46897798, 3.61366415, 3.13770509, 1.12709563, 1.53945713])
    
    random.uniform(1, 6, 10)
    
    array([1.15714593, 4.18205206, 2.57177991, 3.54285346, 5.53783237,
           2.24646115, 3.05191462, 4.77775569, 2.14399083, 1.38489955])
    
    # 产生10个[1,6)之间的整型随机数
    random.randint(1, 6, 10)
    
    array([3, 3, 4, 2, 2, 5, 1, 5, 4, 4])
    
    # 产生2x5的标准正态分布样本
    random.normal(size=(5, 2))
    
    array([[-0.41476463, -1.39874088],
           [-0.34408054,  0.75078589],
           [-0.32762518, -0.86159805],
           [-0.2581848 ,  0.46095562],
           [-1.34938997, -1.01907279]])
    
    # 产生5个,n=5,p=0.5的二项分布样本
    random.binomial(n=5, p=0.5, size=5)
    
    array([1, 3, 2, 3, 2])
    
    a = np.arange(10)
    
    # 从a中有回放的随机采样7个
    random.choice(a, 7)
    
    array([7, 5, 7, 8, 3, 0, 0])
    
    # 从a中无回放的随机采样7个
    random.choice(a, 7, replace=False)
    
    array([6, 4, 7, 0, 2, 1, 5])
    
    # 对a进行乱序并返回一个新的array
    b = random.permutation(a)
    b
    
    array([7, 1, 4, 0, 9, 2, 8, 3, 6, 5])
    
    # 对 a 进行 in-place 乱序
    random.shuffle(a)
    a
    
    array([3, 2, 9, 6, 0, 7, 1, 5, 4, 8])
    
    # 生成一个长度为 9 的随机bytes序列并作为 str 返回
    random.bytes(9)
    
    b'xddOx99xe0)xedx1exb2b'
    

    随机模块可以很方便地让我们做一些快速模拟去验证一些结论。比如来考虑一个非常违反直觉的概率题例子:一个选手去参加一个 TV 秀,有三扇门,其中一扇门后有奖品,这扇门只有主持人知道。选手先随机选一扇门,但并不打开,主持人看到后,会打开其余两扇门中没有奖品的一扇门。然后,主持人问选手,是否要改变一开始的选择?

    这个问题的答案是应该改变一开始的选择。在第一次选择的时候,选错的概率是(frac{2}{3}),选对的概率是 (frac{1}{3})。第一次选择之后,主持人相当于帮忙剔除了一个错误答案,所以如果一开始选的是错的,这时候换掉就选对了;而如果一开始就选对,则这时候换掉就错了。根据以上,一开始选错的概率就是换掉之后选对的概率 (frac{2}{3}),这个概率大于一开始就选对的概率 (frac{1}{3}),所以应该换。虽然道理上是这样,但是还是有些绕,要是通过推理就是搞不明白怎么办,没关系,用随机模拟就可以轻松得到答案:

    import numpy.random as random
    
    random.seed(42)
    
    # 做10000次实验
    n_tests = 10000
    
    # 生成每次实验的奖品所在的门的编号
    # 0表示第一扇门,1表示第二扇门,2表示第三扇门
    winning_doors = random.randint(0, 3, n_tests)
    
    # 记录如果换门的中奖次数
    change_mind_wins = 0
    
    # 记录如果坚持的中奖次数
    insist_wins = 0
    
    # winning_door就是获胜门的编号
    for winning_door in winning_doors:
    
        # 随机挑了一扇门
        first_try = random.randint(0, 3)
        
        # 其他门的编号
        remaining_choices = [i for i in range(3) if i != first_try]
      
        # 没有奖品的门的编号,这个信息只有主持人知道
        wrong_choices = [i for i in range(3) if i != winning_door]
    
        # 一开始选择的门主持人没法打开,所以从主持人可以打开的门中剔除
        if first_try in wrong_choices:
            wrong_choices.remove(first_try)
        
        # 这时wrong_choices变量就是主持人可以打开的门的编号
        # 注意此时如果一开始选择正确,则可以打开的门是两扇,主持人随便开一扇门
        # 如果一开始选到了空门,则主持人只能打开剩下一扇空门
        screened_out = random.choice(wrong_choices)
        remaining_choices.remove(screened_out)
        
        # 所以虽然代码写了好些行,如果策略固定的话,
        # 改变主意的获胜概率就是一开始选错的概率,是2/3
        # 而坚持选择的获胜概率就是一开始就选对的概率,是1/3
        
        # 现在除了一开始选择的编号,和主持人帮助剔除的错误编号,只剩下一扇门
        # 如果要改变注意则这扇门就是最终的选择
        changed_mind_try = remaining_choices[0]
    
        # 结果揭晓,记录下来
        change_mind_wins += 1 if changed_mind_try == winning_door else 0
        insist_wins += 1 if first_try == winning_door else 0
    
    # 输出10000次测试的最终结果,和推导的结果差不多:
    # You win 6616 out of 10000 tests if you changed your mind
    # You win 3384 out of 10000 tests if you insist on the initial choice
    print(
        'You win {1} out of {0} tests if you changed your mind
    '
        'You win {2} out of {0} tests if you insist on the initial choice'.format(
            n_tests, change_mind_wins, insist_wins
            )
    )
    
    You win 6616 out of 10000 tests if you changed your mind
    You win 3384 out of 10000 tests if you insist on the initial choice
  • 相关阅读:
    Linux系统服务
    Linux进程管理
    Linux压缩打包
    Linux输入输出
    Linux权限管理
    Linux用户管理
    Linux文件管理
    Linux-Shell
    Centos7 安装jdk1.8
    Python数据分析之路
  • 原文地址:https://www.cnblogs.com/q735613050/p/8325058.html
Copyright © 2011-2022 走看看