人工智能必备数学知识学习笔记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
原文地址:https://www.cnblogs.com/liuxiaoming123/p/13435360.html