zoukankan      html  css  js  c++  java
  • 人工智能必备数学知识学习笔记5:向量的高级话题

    • 规范化和单位向量

     

     

     单位向量:表示向量长度(向量模的最小组成单元)的单位

     

     

     

     代码实现:

        

     1.在 _global.py中编写代码:

     

     2.在Vector.py编写代码

     1 #向量类
     2 #__values() 与 _values()区别更多体现在继承上,如果是在类的内部使用时官方建议使用_values()发方法
     3 from ._global import EPSILON
     4 import math
     5 
     6 
     7 class Vector:
     8 
     9     def __init__(self,lst):
    10         self._values = list(lst)#将数组赋值给向量类中(注:使用list方法将列表lst复制一份保证他的不被外界调用时修改)
    11 
    12     #零向量类方法:参数1:为当前的类(cls) 参数2:维度(dim)  返回dim维的零向量
    13     @classmethod
    14     def zero(cls,dim):
    15         return cls([0] * dim)
    16 
    17     #返回向量的模(向量长度):
    18     def norm(self):
    19         return math.sqrt(sum(e**2 for e in self))#sqrt()方法为开平方根,sum()求和方法,e**2 e的平方
    20 
    21     #返回向量的单位向量
    22     def normalize(self):
    23         if self.norm() < EPSILON:  #此处判断一个精度范围(该精度范围调用内部自定义全局变量文件 _global.py)(由于浮点数计算机含有误差所以无法使用 == 0 的操作)
    24             raise ZeroDivisionError("Normalize error! norm is zero.") #考虑零向量时报此处异常即可
    25         #方案一:return Vector(1/self.norm() * [e for e in self])#循环遍历向量中的每个元素分别除以该向量的模即为单位向量
    26         #方案二:return 1/self.norm() * Vector(self._values)#当前向量除以模即为单位向量
    27         return Vector(self._values) / self.norm()
    28 
    29     #向量加法,返回结果向量
    30     def __add__(self, another):
    31         # assert判断传入的向量维度是否相等
    32         assert len(self) == len(another),
    33               "Error in adding. Length of vectors must be same."
    34         return Vector([a+b for a,b in zip(self,another)])#使用zip()方法将两个向量取出来
    35 
    36     # 向量减法
    37     def __sub__(self, another):
    38         assert len(self) == len(another), 
    39             "Error in adding. Length of vectors must be same."
    40         return Vector([a - b for a, b in zip(self, another)])
    41 
    42     # 向量乘法(数乘数组),返回数量乘法的结果向量:self * k
    43     def __mul__(self, k):
    44         return Vector([k * e for e in self])
    45 
    46     # 向量乘法(数组乘数),返回数量乘法的结果向量:k * self
    47     def __rmul__(k, self):
    48         return k * self #此处直接调用的是上方的乘法函数
    49 
    50     # 向量除法:返回数量除法的结果向量 self / k
    51     def __truediv__(self, k):
    52         return (1 / k) * self
    53 
    54     #返回向量取正的结果向量
    55     def __pos__(self):
    56         return 1 * self
    57 
    58     # 返回向量取负的结果向量
    59     def __neg__(self):
    60         return -1 * self
    61 
    62     #返回向量迭代器(当有迭代器时,zip()方法中就不用再次传入两个向量数组,直接传入向量对象即可<zip(self._values,another._values)>)
    63     def __iter__(self):
    64         return self._values.__iter__()
    65 
    66     #取向量的index个元素
    67     def __getitem__(self, index):
    68         return self._values[index]
    69 
    70     #返回向量的长度(有多少个元素)
    71     def __len__(self):
    72         return len(self._values)
    73 
    74     # 向量展示(系统调用)
    75     def __repr__(self):
    76         return "Vector({})".format(self._values)
    77 
    78     # 向量展示(用户调用)
    79     def __str__(self):
    80         return "({})".format(", ".join(str(e) for e in self._values))#通过遍历 self.__values 将e转成字符串通过逗号加空格来链接放入大括号中
    81 
    82 # u = Vector([5,2])
    83 # print(u)

    3.在main_vector.py展示中编写:

     1 from playLA.Vector import Vector
     2 
     3 if __name__ == "__main__":
     4 
     5     vec = Vector([5,2])
     6     print(vec)
     7     print(len(vec))#打印向量的维度
     8     print("vec[0] = {}, vec[1] = {}".format(vec[0],vec[1]))
     9 
    10     #向量加法
    11     vec2 = Vector([3,1])
    12     print("{} + {} = {}".format(vec,vec2,vec+vec2))
    13     #向量减法
    14     print("{} - {} = {}".format(vec, vec2, vec - vec2))
    15     #向量乘法(向量乘以数)
    16     print("{} * {} = {}".format(vec,3,vec * 3))
    17     # 向量乘法(数乘以向量)
    18     print("{} * {} = {}".format(3, vec, 3 * vec))
    19     # 向量取正
    20     print("+{} = {}".format(vec, +vec))
    21     # 向量取负
    22     print("-{} = {}".format(vec, -vec))
    23 
    24     #零向量
    25     zero2 = Vector.zero(2)
    26     print(zero2)
    27     #向量加上零向量
    28     print("{} + {} = {}".format(vec, zero2, vec + zero2))
    29 
    30     #向量的模
    31     print("norm({}) = {}".format(vec,vec.norm()))
    32     print("norm({}) = {}".format(vec2,vec2.norm()))
    33     print("norm({}) = {}".format(zero2, zero2.norm()))
    34 
    35     #单位向量
    36     print("normalize({}) is {}".format(vec,vec.normalize()))
    37     print(vec.normalize().norm())#单位向量的模(长度)基本为数字1
    38     print("normalize({}) is {}".format(vec2, vec2.normalize()))
    39     print(vec2.normalize().norm())  # 单位向量的模(长度)基本为数字1(计算机中会有误差0.9999...)
    40     #print(zero2.normalize())
    41     #捕捉异常 ZeroDivisionError
    42     try:
    43         zero2.normalize()
    44     except ZeroDivisionError:
    45         print("Cannot normalize zero vector {}".format(zero2))

    4.运行main_vector.py结果为:

     1 /Users/liuxiaoming/PycharmProjects/LinearAlgebra/venv/bin/python /Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py --mode=client --port=57619
     2 import sys; print('Python %s on %s' % (sys.version, sys.platform))
     3 sys.path.extend(['/Users/liuxiaoming/PycharmProjects/LinearAlgebra'])
     4 PyDev console: starting.
     5 Python 3.8.2 (v3.8.2:7b3ab5921f, Feb 24 2020, 17:52:18) 
     6 [Clang 6.0 (clang-600.0.57)] on darwin
     7 runfile('/Users/liuxiaoming/PycharmProjects/LinearAlgebra/main_vector.py', wdir='/Users/liuxiaoming/PycharmProjects/LinearAlgebra')
     8 (5, 2)
     9 2
    10 vec[0] = 5, vec[1] = 2
    11 (5, 2) + (3, 1) = (8, 3)
    12 (5, 2) - (3, 1) = (2, 1)
    13 (5, 2) * 3 = (15, 6)
    14 3 * (5, 2) = (15, 6)
    15 +(5, 2) = (5, 2)
    16 -(5, 2) = (-5, -2)
    17 (0, 0)
    18 (5, 2) + (0, 0) = (5, 2)
    19 norm((5, 2)) = 5.385164807134504
    20 norm((3, 1)) = 3.1622776601683795
    21 norm((0, 0)) = 0.0
    22 normalize((5, 2)) is (0.9284766908852593, 0.3713906763541037)
    23 1.0
    24 normalize((3, 1)) is (0.9486832980505138, 0.31622776601683794)
    25 0.9999999999999999
    26 Cannot normalize zero vector (0, 0)


    • 向量的点乘

     

     

     

     余弦定理:

     多维两个向量点乘:

     向量点乘的直观理解:将向量V投影到u向量上长度:将两个向量的指向相同后再相乘

     

     

     代码实现:

    1.在Vector.py编写代码

     1 #向量类
     2 #__values() 与 _values()区别更多体现在继承上,如果是在类的内部使用时官方建议使用_values()发方法
     3 from ._global import EPSILON
     4 import math
     5 
     6 
     7 class Vector:
     8 
     9     def __init__(self,lst):
    10         self._values = list(lst)#将数组赋值给向量类中(注:使用list方法将列表lst复制一份保证他的不被外界调用时修改)
    11 
    12     #零向量类方法:参数1:为当前的类(cls) 参数2:维度(dim)  返回dim维的零向量
    13     @classmethod
    14     def zero(cls,dim):
    15         return cls([0] * dim)
    16 
    17     #返回向量的模(向量长度):
    18     def norm(self):
    19         return math.sqrt(sum(e**2 for e in self))#sqrt()方法为开平方根,sum()求和方法,e**2 e的平方
    20 
    21     #返回向量的单位向量
    22     def normalize(self):
    23         if self.norm() < EPSILON:  #此处判断一个精度范围(该精度范围调用内部自定义全局变量文件 _global.py)(由于浮点数计算机含有误差所以无法使用 == 0 的操作)
    24             raise ZeroDivisionError("Normalize error! norm is zero.") #考虑零向量时报此处异常即可
    25         #方案一:return Vector(1/self.norm() * [e for e in self])#循环遍历向量中的每个元素分别除以该向量的模即为单位向量
    26         #方案二:return 1/self.norm() * Vector(self._values)#当前向量除以模即为单位向量
    27         return Vector(self._values) / self.norm()
    28 
    29     #向量加法,返回结果向量
    30     def __add__(self, another):
    31         # assert判断传入的向量维度是否相等
    32         assert len(self) == len(another),
    33               "Error in adding. Length of vectors must be same."
    34         return Vector([a+b for a,b in zip(self,another)])#使用zip()方法将两个向量取出来
    35 
    36     # 向量减法
    37     def __sub__(self, another):
    38         #判断维度相等
    39         assert len(self) == len(another), 
    40             "Error in adding. Length of vectors must be same."
    41         return Vector([a - b for a, b in zip(self, another)])
    42 
    43     #向量点乘(向量之间相乘):返回结果标量
    44     def dot(self,another):
    45         #判断维度相等
    46         assert len(self) == len(another), 
    47             "Error in dot product. Length of vectors must be same."
    48         return sum(a * b for a,b in zip(self,another))# 方法zip()将两组向量配成对应位置的数据对
    49 
    50     # 向量数量乘法(数乘数组),返回数量乘法的结果向量:self * k
    51     def __mul__(self, k):
    52         return Vector([k * e for e in self])
    53 
    54     # 向量数量乘法(数组乘数),返回数量乘法的结果向量:k * self
    55     def __rmul__(k, self):
    56         return k * self #此处直接调用的是上方的乘法函数
    57 
    58     # 向量除法:返回数量除法的结果向量 self / k
    59     def __truediv__(self, k):
    60         return (1 / k) * self
    61 
    62     #返回向量取正的结果向量
    63     def __pos__(self):
    64         return 1 * self
    65 
    66     # 返回向量取负的结果向量
    67     def __neg__(self):
    68         return -1 * self
    69 
    70     #返回向量迭代器(当有迭代器时,zip()方法中就不用再次传入两个向量数组,直接传入向量对象即可<zip(self._values,another._values)>)
    71     def __iter__(self):
    72         return self._values.__iter__()
    73 
    74     #取向量的index个元素
    75     def __getitem__(self, index):
    76         return self._values[index]
    77 
    78     #返回向量的长度(有多少个元素)
    79     def __len__(self):
    80         return len(self._values)
    81 
    82     # 向量展示(系统调用)
    83     def __repr__(self):
    84         return "Vector({})".format(self._values)
    85 
    86     # 向量展示(用户调用)
    87     def __str__(self):
    88         return "({})".format(", ".join(str(e) for e in self._values))#通过遍历 self.__values 将e转成字符串通过逗号加空格来链接放入大括号中
    89 
    90 # u = Vector([5,2])
    91 # print(u)

    2.在main_vector.py展示中编写:

     1 from playLA.Vector import Vector
     2 
     3 if __name__ == "__main__":
     4 
     5     vec = Vector([5,2])
     6     print(vec)
     7     print(len(vec))#打印向量的维度
     8     print("vec[0] = {}, vec[1] = {}".format(vec[0],vec[1]))
     9 
    10     #向量加法
    11     vec2 = Vector([3,1])
    12     print("{} + {} = {}".format(vec,vec2,vec+vec2))
    13     #向量减法
    14     print("{} - {} = {}".format(vec, vec2, vec - vec2))
    15     #向量乘法(向量乘以数)
    16     print("{} * {} = {}".format(vec,3,vec * 3))
    17     # 向量乘法(数乘以向量)
    18     print("{} * {} = {}".format(3, vec, 3 * vec))
    19     # 向量取正
    20     print("+{} = {}".format(vec, +vec))
    21     # 向量取负
    22     print("-{} = {}".format(vec, -vec))
    23 
    24     #零向量
    25     zero2 = Vector.zero(2)
    26     print(zero2)
    27     #向量加上零向量
    28     print("{} + {} = {}".format(vec, zero2, vec + zero2))
    29 
    30     #向量的模
    31     print("norm({}) = {}".format(vec,vec.norm()))
    32     print("norm({}) = {}".format(vec2,vec2.norm()))
    33     print("norm({}) = {}".format(zero2, zero2.norm()))
    34 
    35     #单位向量
    36     print("normalize({}) is {}".format(vec,vec.normalize()))
    37     print(vec.normalize().norm())#单位向量的模(长度)基本为数字1
    38     print("normalize({}) is {}".format(vec2, vec2.normalize()))
    39     print(vec2.normalize().norm())  # 单位向量的模(长度)基本为数字1(计算机中会有误差0.9999...)
    40     #print(zero2.normalize())
    41     #捕捉异常 ZeroDivisionError
    42     try:
    43         zero2.normalize()
    44     except ZeroDivisionError:
    45         print("Cannot normalize zero vector {}".format(zero2))
    46 
    47     #向量点乘(向量乘以向量)
    48     print(vec.dot(vec2))

    3.运行main_vector.py结果为:

     1 /Users/liuxiaoming/PycharmProjects/LinearAlgebra/venv/bin/python /Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py --mode=client --port=58247
     2 import sys; print('Python %s on %s' % (sys.version, sys.platform))
     3 sys.path.extend(['/Users/liuxiaoming/PycharmProjects/LinearAlgebra'])
     4 PyDev console: starting.
     5 Python 3.8.2 (v3.8.2:7b3ab5921f, Feb 24 2020, 17:52:18) 
     6 [Clang 6.0 (clang-600.0.57)] on darwin
     7 >>> runfile('/Users/liuxiaoming/PycharmProjects/LinearAlgebra/main_vector.py', wdir='/Users/liuxiaoming/PycharmProjects/LinearAlgebra')
     8 (5, 2)
     9 2
    10 vec[0] = 5, vec[1] = 2
    11 (5, 2) + (3, 1) = (8, 3)
    12 (5, 2) - (3, 1) = (2, 1)
    13 (5, 2) * 3 = (15, 6)
    14 3 * (5, 2) = (15, 6)
    15 +(5, 2) = (5, 2)
    16 -(5, 2) = (-5, -2)
    17 (0, 0)
    18 (5, 2) + (0, 0) = (5, 2)
    19 norm((5, 2)) = 5.385164807134504
    20 norm((3, 1)) = 3.1622776601683795
    21 norm((0, 0)) = 0.0
    22 normalize((5, 2)) is (0.9284766908852593, 0.3713906763541037)
    23 1.0
    24 normalize((3, 1)) is (0.9486832980505138, 0.31622776601683794)
    25 0.9999999999999999
    26 Cannot normalize zero vector (0, 0)
    27 17



    •  向量点乘的意义 

     

     

    引申:推荐系统算法基础

     

     几何应用:投影点的方向可以表示为单位向量,所以投影点坐标为单位向量乘以一个投影点的距离



    • numpy的使用(numpy是线性代数库)

    1.创建main_numpy_vector.py文件

     2. 文件 main_numpy_vector.py 编写代码

     1 import numpy as np
     2 if __name__ == "__main__":
     3     #查看 数学库 numpy 的版本号
     4     print(np.__version__)
     5 
     6     lst = [1,2,3]
     7     lst[0] = "Linear Algebra"#线性代数的英文
     8     print(lst)
     9 
    10     #使用numpy中的向量
    11     vec = np.array([1,2,3])
    12     print(vec)
    13     # vec[0] = 666
    14     # print(vec)
    15 
    16     #np.array的创建 (参数1:维度数 参数2:每个维度的元素值)
    17     print(np.zeros(5))
    18     print(np.ones(5))
    19     print(np.full(5,666))
    20 
    21     #np.array的基本属性
    22     print(vec)
    23     print("size=",vec.size)#向量有多少元素(维度数)
    24     print("size=",len(vec))
    25     print(vec[0])#第一个元素值
    26     print(vec[-1])#最后一个元素值
    27     print(vec[0:2])#切片语法,参数1:从哪开始,参数2:步长
    28     print(type(vec[0:2]))#该切片的向量的类
    29 
    30     #np.array的基本运算
    31     vec2 = np.array([4,5,6])
    32     print("{} + {} = {}".format(vec,vec2,vec + vec2))#向量加法
    33     print("{} - {} = {}".format(vec, vec2, vec - vec2))  # 向量减法
    34     print("{} * {} = {}".format(2, vec, 2 * vec))  # 向量乘法(数乘以向量)
    35     print("{} * {} = {}".format(vec, 2, vec * 2))  # 向量乘法(向量乘以数)
    36     print("{} * {} = {}".format(vec, vec2, vec * vec2))  # 向量乘法(向量与向量对应元素相乘-但无数学意义)
    37     print("{}.dot({}) = {}".format(vec, vec2, vec.dot(vec2)))  # 向量点乘(向量与向量点乘)
    38 
    39     #np.linalg 为numpy中线性代数模块("Linear Algebra"的缩写)
    40     print(np.linalg.norm(vec))# 向量的模(向量的长度)
    41     print(vec / np.linalg.norm(vec))# 单位向量
    42     print(np.linalg.norm(vec / np.linalg.norm(vec)))# 单位向量的模
    43 
    44     #numpy涉及零向量的单位向量时会报错,需要自行处理
    45     # zero3 = np.zeros(3)
    46     # zero3 / np.linalg.norm(zero3)

     3. 运行文件 main_numpy_vector.py 结果为:

     1 /Users/liuxiaoming/PycharmProjects/LinearAlgebra/venv/bin/python /Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py --mode=client --port=58662
     2 import sys; print('Python %s on %s' % (sys.version, sys.platform))
     3 sys.path.extend(['/Users/liuxiaoming/PycharmProjects/LinearAlgebra'])
     4 PyDev console: starting.
     5 Python 3.8.2 (v3.8.2:7b3ab5921f, Feb 24 2020, 17:52:18) 
     6 [Clang 6.0 (clang-600.0.57)] on darwin
     7 runfile('/Users/liuxiaoming/PycharmProjects/LinearAlgebra/playLA/main_numpy_vector.py', wdir='/Users/liuxiaoming/PycharmProjects/LinearAlgebra/playLA')
     8 1.19.1
     9 ['Linear Algebra', 2, 3]
    10 [1 2 3]
    11 [0. 0. 0. 0. 0.]
    12 [1. 1. 1. 1. 1.]
    13 [666 666 666 666 666]
    14 [1 2 3]
    15 size= 3
    16 size= 3
    17 1
    18 3
    19 [1 2]
    20 <class 'numpy.ndarray'>
    21 [1 2 3] + [4 5 6] = [5 7 9]
    22 [1 2 3] - [4 5 6] = [-3 -3 -3]
    23 2 * [1 2 3] = [2 4 6]
    24 [1 2 3] * 2 = [2 4 6]
    25 [1 2 3] * [4 5 6] = [ 4 10 18]
    26 [1 2 3].dot([4 5 6]) = 32
    27 3.7416573867739413
    28 [0.26726124 0.53452248 0.80178373]
    29 1.0
  • 相关阅读:
    win7常用快捷键
    java中构造代码块、方法调用顺序问题
    eclipse项目改为maven项目导致svn无法比较历史数据的解决办法
    linux配置Anaconda python集成环境
    DataFrame对行列的基本操作实战
    驱动:电阻屏触摸芯片NS2009
    读书笔记:代码大全(第二版)
    资料:磁角度传感器芯片
    经验:FatFs文件系统实时写入
    笔记:CAN收发器-TJA1051T与TJA1051T/3调试总结
  • 原文地址:https://www.cnblogs.com/liuxiaoming123/p/13435360.html
Copyright © 2011-2022 走看看