• [Machine learning][Part3] numpy 矢量矩阵操作的基础知识


    很久不接触数学了,machine learning需要用到一些数学知识,这里在重温一下相关的数学基础知识

    矢量

    矢量是有序的数字数组。在表示法中,矢量用小写粗体字母表示。矢量的元素都是相同的类型。例如,矢量不包含字符和数字。数组中元素的数量通常被称为维度,数组中元素的数量通常被称为维度,可以使用索引引用矢量的元素。在数学设置中,索引通常从 1 到 n。在计算机科学和这些实验室中,索引通常从 0 运行到 n-1。下面是两个的对比,在计算机中我们使用的是左边code的那种方式,也就是0到n-1

     Numpy中的阵列

    NumPy 的基本数据结构是一个可索引的 n 维数组,其中包含相同类型 (dtype) 的元素。

    一维向量的操作:

    向量创建
    创建一个指定shape的一维向量,参数可以是整数、元祖等等,参数表示要创建的序列的shape
    1. a= np.zeros(4); print(f"np.zeros(4) : a = {a}, a shape = {a.shape}, a data type = {a.dtype}")
    2. a= np.zeros((4,)); print(f"np.zeros(4,) : a = {a}, a shape = {a.shape}, a data type = {a.dtype}")
    3. a= np.random.random_sample(4); print(f"np.random.random_sample(4): a = {a}, a shape = {a.shape}, a data type = {a.dtype}")
    创建一个不指定shape的一维向量
    1. a = np.arange(4.); print(f"np.arange(4.): a = {a}, a shape = {a.shape}, a data type = {a.dtype}")
    2. a = np.random.rand(4); print(f"np.random.rand(4): a = {a}, a shape = {a.shape}, a data type = {a.dtype}")
    创建指定值的一维向量
    1. a = np.array([5, 4, 3, 2]); print(f"np.array([5,4,3,2]): a = {a}, a shape = {a.shape}, a data type = {a.dtype}")
    2. a = np.array([5., 4, 3, 2]); print(f"np.array([5.,4,3,2]): a = {a}, a shape = {a.shape}, a data type = {a.dtype}")
    向量操作
    获取向量元素:通过index和切片可以获得,这个和列表的操作相似。
    • 通过index获得:
    1. a = np.arange(10)
    2. print(a)
    3. # 获取Index = 2的元素
    4. print(f"a[2].shape: {a[2].shape} a[2] = {a[2]}, Accessing an element returns a scalar")
    5. # 获取最后一个元素
    6. print(f"a[-1]={a[-1]}")
    7. # index 必须在向量有效范围以内,否则会报错
    8. try:
    9. c = a[10]
    10. except Exception as e:
    11. print(e)
    • 切片获取元素
    1. # 切片操作通过(start:stop:step)这个三个参数来控制要获取的元素,
    2. # 切片操作是左闭右开,也就是包括index=start的值,但是不包括index=stop的值
    3. # 向量切片操作
    4. a = np.arange(10)
    5. print(f"a = {a}")
    6. #获取向量中的从index=2开始到Index=7结束的5个元素, 第三个参数1表示step=1,代表连续取值 (start:stop:step)
    7. c = a[2:7:1]; print("a[2:7:1] = ", c)
    8. # 获取向量中的从index=2开始到Index=7结束的元素, 第三个参数1表示step=2,代表隔一个index取一个值 (start:stop:step)
    9. c = a[2:7:2]; print("a[2:7:2] = ", c)
    10. # 取index 大于3的所有值
    11. c = a[3:]; print("a[3:] = ", c)
    12. # 取index小于3的所有值
    13. c = a[:3]; print("a[:3] = ", c)
    14. # 取所有的值
    15. c = a[:]; print("a[:] = ", c)
    • 单个向量的操作
    1. a = np.array([1, 2, 3, 4])
    2. print(f"a: {a}")
    3. # 将向量中的元素全部变为相反数
    4. b = -a
    5. print(f"b: {b}")
    6. # 计算向量中所有元素的和并返回一个和的标量
    7. b = np.sum(a)
    8. print(f"b = np.sum(a) : {b}")
    9. # 求向量的平均值
    10. b = np.mean(a)
    11. print(f"b = np.mean(a): {b}")
    12. # 对向量中每个元素求平法
    13. b = a**2
    14. print(f"b = a**2 : {b}")
    • 对向量元素的操作,numpy很多对数字的操作也都是用于向量的
    1. # 向量a+向量b, 两个向量长度必须相同,不然会报error
    2. a = np.array([1, 2, 3, 4])
    3. b= np.array([-1, -2, 3, 4])
    4. print(f"Binary operators work element wise: {a + b}")
    5. # 标量和向量的操作
    6. a = np.array([1, 2, 3, 4])
    7. b = 5 * a
    8. print(f"b = 5 * a : {b}")
    • 向量与向量的点积

    自定义一个实现点积的方法:

    1. def my_dot(a,b):
    2. """
    3. Compute the dot product of two vectors
    4. Args:
    5. a (ndarray (n,)): input vector
    6. b (ndarray (n,)): input vector with same dimension as a
    7. Returns:
    8. x (scalar):
    9. """
    10. x = 0
    11. for i in range(a.shape[0]):
    12. x= x+a[i]*b[i]
    13. return x
    14. # test my_dot()
    15. a = np.array([1,2,3,4])
    16. b = np.array([-1, 4, 3, 2])
    17. print(f"my_dot(a, b) = {my_dot(a, b)}")

    使用Numpy中的点积方法:

    1. # 使用numpy中的dot来计算点积,返回一个标量
    2. a = np.array([1, 2, 3, 4])
    3. b = np.array([-1, 4, 3, 2])
    4. c = np.dot(a, b)
    5. print(f"NumPy 1-D np.dot(a, b) = {c}, np.dot(a, b).shape = {c.shape} ")
    6. c = np.dot(b, a)
    7. print(f"NumPy 1-D np.dot(b, a) = {c}, np.dot(a, b).shape = {c.shape} ")

    然后对上面两种计算点积的方法做个效率上的对比

    1. # 对比一下numpy 的dot和自己写的my_dot的效率如何,可以看出numpy中的效率要高很多
    2. np.random.seed(1)
    3. a = np.random.rand(10000000) # very large arrays
    4. b = np.random.rand(10000000)
    5. tic = time.time() # capture start time
    6. c = np.dot(a, b)
    7. toc = time.time() # capture end time
    8. print(f"np.dot(a, b) = {c:.4f}")
    9. print(f"Vectorized version duration: {1000*(toc-tic):.4f} ms ")
    10. tic = time.time() # capture start time
    11. c = my_dot(a,b)
    12. toc = time.time() # capture end time
    13. print(f"my_dot(a, b) = {c:.4f}")
    14. print(f"loop version duration: {1000*(toc-tic):.4f} ms ")
    15. del(a);del(b) #remove these big arrays from memory

    运行结果为:可以看到numpy的耗时要少很多

    1. my_dot(a, b) = 24
    2. NumPy 1-D np.dot(a, b) = 24, np.dot(a, b).shape = ()
    3. NumPy 1-D np.dot(b, a) = 24, np.dot(a, b).shape = ()
    4. np.dot(a, b) = 2501072.5817
    5. Vectorized version duration: 6.5184 ms
    6. my_dot(a, b) = 2501072.5817
    7. loop version duration: 2430.3420 ms

    矩阵

    矩阵是一个二维阵列,里面的元素都是同一类型的。一般用大写黑体字母表示。用两个下标m,n表示,m表示行数,n表示列数。通过两个下标可以访问指定的元素

    矩阵操作

    创建矩阵

    与创建向量的方法一样,只是这里的参数要换成元祖
    1. a = np.zeros((1, 5))
    2. print(f"a shape = {a.shape}, a = {a}")
    3. a = np.zeros((2, 1))
    4. print(f"a shape = {a.shape}, a = {a}")
    5. a = np.random.random_sample((1, 1))
    6. print(f"a shape = {a.shape}, a = {a}")
    7. # 2.创建指定元素的矩阵
    8. a= np.array([[5],
    9. [4],
    10. [3]])
    11. print(f" a shape = {a.shape}, np.array: a = {a}")

    矩阵的操作

    1. # 3.矩阵的操作
    2. # 3.1 下标访问
    3. # reshape 是一种比较方便的方法创建矩阵,
    4. a = np.arange(6).reshape(-1, 2) #reshape(-1,2) 表示生成一个6/2行,2列的矩阵,也就是3行两列的矩阵
    5. print(f"a.shape:{a.shape},\na={a}")
    6. # 访问一个元素
    7. print(f"\na[2.0].shape:{a[2:0].shape},a[2,0]={a[2:0]}, type(a[2,0])={type(a[2,0])} Accessing an element returns a scalar\n")
    8. # 访问一行
    9. print(f"a[2].shape:{a[2].shape},a[2] = {a[2]},type(a[2]) = {type(a[2])}")
    10. # 3.2切片访问
    11. a = np.arange(20).reshape(-1, 10)
    12. print(f"a=\n{a}")
    13. # 访问一行中5个连续的元素(start:stop:step)
    14. print("a[0,2:7:1]=",a[0, 2:7:1], "a[0,2:7:1].shape=", a[0, 2:7:1].shape, "a-1D array")
    15. # 访问两行中5个连续的元素(start:stop:step)
    16. print("a[:, 2:7:1] = \n", a[:, 2:7:1], ", a[:, 2:7:1].shape =", a[:, 2:7:1].shape, "a 2-D array")
    17. # 访问矩阵所有元素
    18. print("a[:,:] = \n", a[:,:], ", a[:,:].shape =", a[:,:].shape)
    19. # 访问一行中的所有元素,方法1
    20. print("a[1,:] = ", a[1,:], ", a[1,:].shape =", a[1,:].shape, "a 1-D array")
    21. # 访问一行中的所有元素,方法2
    22. print("a[1] = ", a[1], ", a[1].shape =", a[1].shape, "a 1-D array")

  • 相关阅读:
    小白学Python:提取Word中的所有图片,只需要1行代码
    六月集训(29)分治
    计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序
    PGD(projected gradient descent)算法源码解析
    范德蒙德卷积 学习笔记
    Windows 下使用 cmake 构建工程
    代码风格自动化(二)——husky + lint-staged
    QT基础入门——认识与创建QT(一)
    简化路径(C++解法)
    Spring5 框架 ---- 事务操作
  • 原文地址:https://blog.csdn.net/x1987200567/article/details/133316561