• pandas学习笔记Day01->python和numpy知识巩固


    Python进阶复习

    列表推导式

    # 列表推导式
    L = []
    def my_func(x):
        return 2*x
    
    for i in range(5):
        L.append(my_func(i))
    
    # 列表推导式[* for i in *]
    # 第一个 * 为映射函数,其输入为后面 i 指代的内容
    # 第二个 * 表示迭代的对象。
    [my_func(i) for i in range(5)]

    结果为my_func(i),很巧的是,回顾这个问题,code review出同事的一个bug~

    [m + '_' + n for m in ['a','b'] for n in ['c','d']]

    第一个for是外循环,第二个for是内循环

    习题1.3.1 列表推导式的使用

    题目:

     题目分析:

    需要对input 141改写,item是用于累加三层循环的M1[i][k]*M2[k][j],res得到的是经过i和j两层循环后的结果,需要从里层循环到外层循环展开。里层因为得到item的累加和,是结果,故而写在列表推导式的开头,在k这层循环累加,所以是

    sum([M1[i][k]*M2[k][j]  for k in range(M1.shape[1])])

    j层循环(2个列表推导式):

    [sum([M1[i][k]*M2[k][j]  for k in range(M1.shape[1])]) for j in range(M2.shape[1])] 

    i层循环(3个列表推导式):

    [[sum([M1[i][k]*M2[k][j]  for k in range(M1.shape[1])]) for j in range(M2.shape[1])] for i in range(M1.shape[0])]

    放上完整代码:

    import numpy as np
    M1 = np.random.rand(2,3)
    M2 = np.random.rand(3,4)
    # 第一个值为返回值res
    # 原题中item是用于累加求和,在经过i和j两层循环后,将结果存放于res
    res = [[sum([M1[i][k]*M2[k][j]  for k in range(M1.shape[1])]) for j in range(M2.shape[1])] for i in range(M1.shape[0])]
    
    ((M1@M2 - res) < 1e-15).all()

    结果: True

    当结合匿名函数

    # i = 0,1,2,3,4-->i作为lambda匿名函数的自变量
    # 所以lambda x: 2*x -->0,2,4,6,8
    [(lambda x: 2*x)(i) for i in range(5)]
    # 结果:[0, 2, 4, 6, 8]

    注意,利用列表推导式的匿名函数映射,返回的是一个map对象,需要通过list转为列表, map函数会根据提供的函数对指定的序列做映射,map(function,iteration),其中iteration是一个或多个序列

    list(map(lambda x: 2*x, range(5)))

    zip对象和enumerate方法

    自己写代码时非常好用的,比如有两个list,想把其中一个list作为字典的key,另一个list作为字典value(之前需要判断两个list的长度是否一致),然后直接用zip打包即可

    enumerate也是工程中非常好用的遍历方法,可以用index来debug有错误的序列,value打印对应的结果

    zip是压缩的英文,那么也有对应的解压操作~

    numpy

    第一次认真学numpy,笔记有点多~

    初始化构造array

    import numpy as np
    # 一般都用array来构造
    np.array([1,2,3])

    返回的是array类型的结果:

    array([1, 2, 3])

    两种等差序列:(英语好的同学注意拼写,不是arrange,而是arange!)

    # 等差序列,起始、终止(包含),样本个数
    np.linspace(1,5,11)
    # array([1. , 1.4, 1.8, 2.2, 2.6, 3. , 3.4, 3.8, 4.2, 4.6, 5. ])
    
    # 等差序列,起始、终止(不包含)、步长
    np.arange(1,5,1)
    # array([1, 2, 3, 4])

    np.arange第三个参数是步长,故而更适合于创建规则的array,更常用

    特殊矩阵,zeros, eye, full

    # 类型:元组,参数为行和列的维度
    np.zeros((2,3))
    # array([[0., 0., 0.],
    #         [0., 0., 0.]])

    用小括号括起来的参数是维度,原本函数是np.zeros(),在()中加一个元组,第一个参数表示2行,第二个参数表示3列

    # eye,3*3的单位矩阵
    np.eye(3)
    """
        array([[1., 0., 0.],
               [0., 1., 0.],
               [0., 0., 1.]])
    
    """

    np.eye()因为是单位矩阵,只有一个参数,同时代表行和列,第二个参数是偏移主对角线1个单位的伪单位矩阵

    # full,返回类型:元组
    # 第一个参数为矩阵维度,第二个参数为填充的数值
    np.full((2,3),10)
    
    # 返回:array([[10, 10, 10],
    #             [10, 10, 10]])
    
    # 第二个参数为列表,是将该传入列表填充到每行
    np.full((2,3), [1,2,3])
    
    #返回:array([[1, 2, 3],
    #            [1, 2, 3]])        

    随机矩阵

    # 随机矩阵 np.random
    # 生成服从0-1均匀分布的三个随机数
    # 传入的是维度大小,3行3列
    np.random.rand(3,3)
    
    array([[0.66924322, 0.21467023, 0.03326504],
           [0.95161185, 0.592994  , 0.77495745],
           [0.70362244, 0.79596363, 0.778472  ]])
    
    # randn生成了N(0,I)的标准正态分布
    # 标准正态分布,均值μ=0,标准差σ=1
    # 参数是维度
    np.random.randn(2,2)
    
    array([[-0.91070861,  1.91114701],
           [ 0.42962912, -0.59628133]])
    
    # randint可以指定生成随机整数的最小值,最大值和维度大小
    low, high, size = 5, 15, (2,2)
    np.random.randint(low, high, size)
    
    array([[14,  6],
           [ 6,  7]])
    
    
    # choice可以从给定的列表中,以一定概率和方式抽取结果
    # 当不指定第四个参数p概率时,为均匀采样
    # 默认replace抽取方式为有放回抽样
    # 出现a的概率为0.1,出现b的概率为0.7,出现c的概率0.1,出现d的概率为0.1
    my_list = ['a', 'b', 'c', 'd']
    np.random.choice(my_list, 2, replace=False, p=[0.1,0.7,0.1,0.1])
    
    array(['b', 'a'], dtype='<U1')

    其中,<U1的解答链接:https://segmentfault.com/q/1010000012049371

    # permutation打散原列表
    np.random.permutation(my_list)
    array(['d', 'a', 'c', 'b'], dtype='<U1')

    想到了paddlepaddle里面的shuffle参数,如果数据集因为label相同的排列太紧密,会导致模型训练效果很差,所以需要打乱数据,不知道permutation是否也有这奇效呢~

    随机种子

    # 随机种子,能固定随机数的输出结果
    # 参数值不变时,输出的结果也不会变
    np.random.seed(28)
    np.random.rand()
    # 0.7290137422891191

    这个值一旦设定,在任何其他人的电脑上运行同样参数的seed函数,输出的结果都一样~

    非常有用的numpy数组的变形与合并

    # 常用的转置,常用于初始化,2行3列->3行2列
    # 不过 reshape使用更灵活
    np.zeros((2,3)).T
    
    array([[0., 0.],
           [0., 0.],
           [0., 0.]])
    # 维度变换 reshape
    # 能帮助用户把原数组按照新的维度重新排列
    # array([0, 1, 2, 3, 4, 5, 6, 7])重新按照reshape排序
    print(np.arange(8).reshape(2,4))
    
    [[0 1 2 3]
     [4 5 6 7]]
    
    # order为C,逐行顺序进行填充
    # 对target处理顺序为0,1,2,3,4,5,6,7,逐行放置
    target.reshape((4,2), order = 'C')
    
    array([[0, 1],
           [2, 3],
           [4, 5],
           [6, 7]])
    
    # order为F,逐列顺序进行填充
    # 对target处理顺序为0,4,1,5,2,6,3,7,以列重新排序
    target.reshape((4,2), order = 'F')
    
    array([[0, 2],
           [4, 6],
           [1, 3],
           [5, 7]])
    
    # 当被调用数组的大小是确定的时(2*4=8)
    # reshape允许有一个维度存在空缺,比如规定4行,第二个参数可设为-1
    target.reshape((4, -1))
    
    array([[0, 1],
           [2, 3],
           [4, 5],
           [6, 7]])

     reshape的另一个妙用是,有点像.T转置是不是~但reshape用起来更方便

    合并

    # 上下合并
    np.r_[np.zeros((2,3)), np.zeros((2,3))]
    
    array([[0., 0., 0.],
           [0., 0., 0.],
           [0., 0., 0.],
           [0., 0., 0.]])
    
    # 左右合并
    np.c_[np.zeros((2,3)), np.zeros((2,3))]
    
    array([[0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0.]])
    
    # np.array([0,0])是一维数组,np.zeros(2)是二维数组
    # 两者进行合并时,在长度匹配的情况下,只能使用左右合并的c_操作
    np.r_[np.array([0,0]), np.zeros(2)]

    常用函数

    # where,条件函数,可以指定满足条件与不满足条件位置对应的填充值
    a = np.array([-1,1,-1,0])
    # 当为True时,填充a的值,否则填充5
    # 第一个参数是判断条件,第二个参数是对应位置为True的返回结果,第三个参数是对应位置为False的返回结果
    np.where(a>0, a, 5)
    
    array([5, 1, 5, 5])
    
    # 返回索引,nonzero返回非零数的索引,argmax和argmin分别返回最大数和最小数的索引
    a = np.array([-2,-5,0,1,3,-1])
    np.nonzero(a)
    
    (array([0, 1, 3, 4, 5], dtype=int64),)
    
    # cumprod.cumsum 分别表示累乘和累加函数,返回同长度的数组
    a = np.array([1,2,3])
    # 1->1, 1*2->2, 1*2*3->6
    a.cumprod()
    
    array([1, 2, 6], dtype=int32)
    
    a = np.array([1,2,3])
    # 1->1, 1+2->3, 1+2+3->6
    a.cumsum()
    
    array([1, 3, 6], dtype=int32)
    
    # diff表示和前一个元素做差,
    # 由于第一个元素为缺失值,因此在默认情况下,返回长度是原数组减1
    # 数组中的差, 2-1->1, 3-2->1
    np.diff(a)
    
    array([1, 1])

    针对.sum()函数常用的axis参数,用了屡错屡不对

    找了张经典的图:

    # axis参数,能进行某一个维度下的统计特征计算
    target = np.arange(1,10).reshape(3,-1)
    target
    
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])
    
    # 当axis=0时,结果为列的统计指标
    target.sum(0)
    
    array([12, 15, 18])
    
    # 当axis=1时,结果为行的统计指标
    target.sum(1)
    
    array([ 6, 15, 24])

    针对以上知识点,例题2:

     我的分析:更新方法,求每行倒数之和,然后乘以矩阵。那么,对每行倒数求和可以用

    (1/a).sum(1)
    结果是array([1.83333333, 0.61666667, 0.37896825])

    但是,每一行的第一个值都是1.833,第二个值是0.6166,第三个值是0.3789,但是我们还要做和原先A矩阵的每一个值相乘需要将三个值在一列中排列不同变成

    array([[1.83333333],
           [0.61666667],
           [0.37896825]])
    (1/a).sum(1).reshape(-1,1)
    
    array([[1.83333333],
           [0.61666667],
           [0.37896825]])
    # 再乘以矩阵a的每一个值
    result = a*(1/a).sum(1).reshape(-1,1)

    结果:
    array([[1.83333333, 3.66666667, 5.5       ],
           [2.46666667, 3.08333333, 3.7       ],
           [2.65277778, 3.03174603, 3.41071429]])

    向量和矩阵的计算

    # 向量内积dot
    a = np.array([1,2,3])
    b = np.array([1,3,5])
    
    a.dot(b)
    
    #结果:22
    
    # np.linalg.norm第二个参数的用法
    # 向量范数和矩阵范数: np.linalg.norm
    # 1-范数:向量元素绝对值之和
    # 2-范数:向量元素绝对值的平方和再开平方
    # p-范数:向量元素绝对值的p次方和的1/p次幂
    # 矩阵范数:1-范数:所有矩阵列向量绝对值之和的最大值
    # 矩阵范数:2-范数:A'A矩阵的最大特征值的开平方
    # 矩阵范数:Frobenius范数,矩阵元素绝对值的平方和再开平方
    
    matrix_target = np.arange(4).reshape(-1,2)
    # 'fro'是Frobenius norm
    np.linalg.norm(matrix_target, 'fro')
    # 结果:3.7416573867739413
    
    #对于matrics,max(sum(abs(x), axis=1)) 
    # 按行,对每一行的绝对值求和
    np.linalg.norm(matrix_target, np.inf)
    # 5.0

    矩阵乘法

    a = np.arange(4).reshape(-1,2)
    b = np.arange(-4,0).reshape(-1,2)
    a@b
    array([[ -2,  -1],
           [-14,  -9]])g
    
    b@a
    array([[ -6, -13],
           [ -2,  -5]])

    注意两个矩阵相乘前后顺序很重要

    相关习题:

     分析:主要是对B的问题,转换为用内积解决,即np.dot(),也就是对A矩阵的行(axis=1)求和,对A矩阵的列(axis=0)求和,然后相乘。最后再套公式:

    A = np.random.randint(10,20,(8,5))
    B = np.dot(A.sum(axis=1,keepdims=True),A.sum(axis=0,keepdims=True))/A.sum() 
    
    result = (((A-B)**2)/B).sum()

    一开始,没有keepdims=True,是报错的,经查后,才发现这个参数是用来保持矩阵的二维性。如果一个2*3*4的三维矩阵,axis=0,keepdims默认为False,则结果矩阵被降维至3*4(二维矩阵) 。如果keepdims=True, 则矩阵维度保持不变,还是三维,只是第零个维度由2变为1,即1*3*4的三维矩阵。有了这个选项,结果矩阵就可以与原始输入矩阵进行正确的广播运算

    最后这个算法题:

     我的分析:递增可以用np.diff,如果递增且是连续整数,则后一个数减去前一个数,结果一定为1,否则,可以用其他值填充。因为np.diff是会少一位,所以要在首位填充1,可以像bert模型,最,结尾处加一个标识符(1)

    a = np.array([3,2,1,2,3,4,6])
    b = np.r_[1, np.diff(a)!=1, 1]
    b
    
    # 结果:array([1, 1, 1, 0, 0, 0, 1, 1], dtype=int32)

    然后用nonzero返回非零数的索引

    c = np.nonzero(b)
    (array([0, 1, 2, 6, 7], dtype=int64),)

    最后用max函数得到距离最远的索引

    d = np.diff(c).max()
    
    # 正确结果:4
  • 相关阅读:
    代码仓库创建规范
    在阿里云托管的k8s上使用nas做动态存储
    YApi——手摸手,带你在Win10环境下安装YApi可视化接口管理平台
    SwiftUI
    Istio多集群(1)-多控制面
    使用kind搭建kubernetes
    Envoy 代理中的请求的生命周期
    Istio中的流量配置
    Istio 的配置分析
    istio部署模型
  • 原文地址:https://www.cnblogs.com/juranus1412/p/14147463.html
Copyright © 2020-2023  润新知