这里讲的不错哈哈
函数的输入和输出,很多情况下都是数字,但是也不完全如此。
函数可以反映非数字之间的关系。
有以下两点需要注意。
机器学习中的函数
机器学习基本上等价于寻找函数的过程。机器学习的目的是进行预测、判断,实现某种功能。通过学习训练集中的数据,计算机得到一个从x到y的拟合结果,也就是函数。然后通过这个函数,计算机就能够从任意的x,推知任意的y。这里的自变量x,就是机器学习中数据集的特征,而特征的个数,通常会多于一个,记作x1,x2,…,xn,。如下图中的示例:机器学习通过电影的成本、演员等特征数据,推测这部电影可能收获的票房。
机器学习到的函数,实现了从特征到结果的一个特定推断。
机器学习到的函数模型有时过于复杂,并不总是能通过集合、解析式或者图像描述出来。
可以说,机器学习算法得到的函数,往往能看到数据背后隐藏着的、肉眼所不能发现的秘密。
传统的机器学习算法包括线性回归、逻辑回归、决策树、朴素贝叶斯等,通过应用这些算法可以得到不同的函数。
而深度学习的函数具有复杂的神经网络拓扑结构,网络中的参数通过链式求导来求得,相当于一大堆线性函数的跨层堆叠。它们仿佛存在于一片混沌之中,虽然看不见摸不着,却真实地存在着。
无论是传统的机器学习,还是深度学习,所得到的函数模型都是对样本集中特征到标签的关系的总结,是其相关性的一种函数化的表达。
线性函数
二次函数和多次函数
激活函数(activation function)
还有一组函数在机器学习中相当重要,它们是神经网络中的激活函数( activation function)。
如下图所示。它们的作用是在机器学习算法中实现非线性的、阶跃性质的变换。其中的Sigmoid函数在机器学习的逻辑回归模型中起着重要的作用。
对数函数
机器学习所关心的问题之一是捕捉函数的变化趋势,也就是研究y 如何随着x而变,这个趋势是通过求导和微分来实现的
对多元函数的各参数求偏导数, 然后把所求得的各个参数的偏导 数以向量的形式写出来, 就是梯度。
具体来说, 两个自变量的函数 f ( x 1 , x 2 ) f\left(x_{1}, x_{2}\right) f(x1,x2), 对应着机器学习数据 集中的两个特征, 如果分别对 x 1 , x 2 x_{1}, x_{2} x1,x2 求偏导数, 那么求得的梯度向量就 是 ( ∂ f / ∂ x 1 , ∂ f / ∂ x 2 ) T \left(\partial f / \partial x_{1}, \partial f / \partial x_{2}\right){ }^{\mathrm{T}} (∂f/∂x1,∂f/∂x2)T, 在数学上可以表示成 Δ f ( x 1 , x 2 ) \Delta f\left(x_{1}, x_{2}\right) Δf(x1,x2) 。
那么计算梯度向量的意义何在呢? 其几何意义, 就是函数变化的 方向, 而且是变化最快的方向。
对于函数 f(x), 在点 ( x 0 , y 0 ) \left(x_{0}, y_{0}\right) (x0,y0), 梯 度向量的方向也就是 y 值增加最快的方向。也就是说, 沿着梯度向量的方向 Δ f ( x 0 ) \Delta f\left(x_{0}\right) Δf(x0), 能找到函数的最大值。反过来说, 沿着梯度向量相反的方向, 也就是
− Δ f ( x 0 ) -\Delta f\left(x_{0}\right) −Δf(x0) 的方向, 梯度减少最快, 能找到函数的最小值。
如果某一个点的梯度向量的值为 0 , 那么也就是来到了导数为 0 的函数最低点(或局部最低点)了。
为什么不同教材中凸函数和凹函数的定义是不同的? - 秦浩然的回答 - 知乎 https://www.zhihu.com/question/31160556/answer/51276335
张量是机器学习程序中的数字容器,本质上就是各种不同维度的数组,如下图所示。我们把张量的维度称为轴( axis)(就是数学中的x轴,y轴,…….),轴的个数称为阶(rank)(也就是俗称的维度,但是为了把张量的维度和每个阶的具体维度区分开,这里统一把张量的维度称为张量的阶。NumPy中把它叫作数组的轶)
张量的形状(shape)就是张量的阶,加上每个阶的维度(每个阶的元素数目)。
张量都可以通过NumPy来定义、操作。因此,把NumPy数学函数库里面的数组用好,就可以搞定机器学习里面的数据结构。
我们从最简单的数据结构开始介绍。仅包含一个数字的张量叫作标量(scalar),即0阶张量或0D张量。 标量的功能主要在于程序流程控制、设置参数值等。
下面创建一个NumPy标量
import numpy as np #导入NumPy
X = np.array(5) # 创建0D张量,也就是标量
print("X的值",X)
print("X的阶",X.ndim) #ndim属性显示张量轴的个数
print("X的数据类型",X.dtype) # dtype属性显示张量数据类型
print("X的形状",X.shape) # shape属性显示张量形状
由一组数字组成的数组叫作向量(vector),也就是一阶张量,或称1D张量。一阶张量只有一个轴。
下面创建一个NumPy向量
X = np.array([5,6,7,8,9]) #创建1D张量,也就是向量
print("X的值",X)
print("X的阶",X.ndim) #ndim属性显示张量轴的个数
print("X的形状",X.shape) # shape属性显示张量形状
创建向量的时候要把数字元素放进方括号里面,形成一个包含5个 元素的1D张量。需要再次强调的是,机器学习中把5个元素的向量称 为5维向量。千万不要把5维向量和5阶张量混淆
注意点1
向量的维度
注意点2
再看一下X向量的形状(5,)。这个描述方式也是让初学者比较困惑的地方,如果没有后面的逗号,可能看起来更舒服一点儿。但是我们要习惯,(5,)就表示它是一个1D张量,元素数量是5,也就是5维向量。
下面这个语句又创建了一个向量,这个向量是一个1维向量:
X= np.array([5])#1维向量,也就是1D数组里面只有一个元素
机器学习中的向量数据
结合波士顿房价数据集来理解
from keras.datasets import boston_housing # 波士顿房价数据集
(X_train, y_train), (X_test, y_test) = boston_housing.load_data()
print("X_train的形状:", X_train.shape)
print("X_train中第一个样本的形状:", X_train[0].shape)
print("y_train的形状:", y_train.shape)
X_train[0]又是什么意思呢?它是X_train训练集的第一行数据, 这一行数据,是一个13维向量(也是1D张量)。也就是说,训练集的每行数据都包含13个特征。
向量的点积
两个向量之间可以进行乘法运算,而且不止一种,有点积( dotproduct)(也叫点乘)和叉积 ( cross product) (也叫叉乘),其运算法则不同。机器学习中经常出现点积运算。
[ a 1 a 2 ⋅ ⋅ a n − 1 a n ] ⋅ [ b 1 b 2 ⋅ ⋅ b n − 1 b n ] = a 1 b 1 + a 2 b 2 + ⋯ + a n − 1 b n − 1 + a n b n 向 量 的 点 积 运 算 法 则 \left[\begin{array}{c}\\a_{1} \\\\a_{2} \\\\\cdot \\\\\cdot \\\\a_{n-1} \\\\a_{n}\\\end{array}\right] \cdot\left[\begin{array}{c}\\b_{1} \\\\b_{2} \\\\\cdot \\\\\cdot \\\\b_{n-1} \\\\b_{n}\\\end{array}\right]=a_{1} b_{1}+a_{2} b_{2}+\cdots+a_{n-1} b_{n-1}+a_{n} b_{n}\\\\向量的点积运算法则\\ ⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡a1a2⋅⋅an−1an⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤⋅⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡b1b2⋅⋅bn−1bn⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤=a1b1+a2b2+⋯+an−1bn−1+anbn向量的点积运算法则
简单地说, 就是两个相同维度的向量对应元素先相乘, 后相加, 形成等号右边的多项式
python实现向量点积
weight = np.array([1,-1.8,1,1,2]) # 权重向量(也就是多项式的参数)
X = np.array([1,6,7,8,9]) # 特征向量(也就是一个特定样本中的特征值)
y_hat = np.dot(X,weight) # 通过点积运算构建预测函数
print('函数返回结果:', y_hat) # 输出预测结果
或者下面的也可以
y_hat = weight.dot(X) # X.dot(weight)也可以实现同样结果
y_hat
注意向量点积的结果是一个值,也就是一个标量,而不是一个向量。
通过向量、矩阵等数据结构进行向量化运算是机器学习中的一个关键技术。而Python能够方便地实现向量化运算,正是Python核心优势之一。在上面两段代码中,点积运算就是通过向量化运算直接实现的,过程中没有出现任何for循环语句。
另外,在向量的点积运算中,A·B=B·A,向量可以互换位置。不过,下面要介绍的矩阵间的点积,或者矩阵和向量之间的点积,就没有这么随意了。
矩阵(matrix)是一组一组向量的集合。矩阵中的各元素横着、竖着、斜着都能构成不同的向量。而矩阵,也就是 2 阶张量,或称 2D 张量,其形状为(m,n)。
矩阵里面横向的元素组称为“行”,纵向的元素组称为“列”。 一个矩阵从左上角数起的第 i i i行第 j j j列上的元素称为第 ( i , j ) (i,j) (i,j)项,通常记为 a ( i , j ) a_{(i,j)} a(i,j)。
机器学习中的矩阵数据
机器学习中的矩阵数据比比皆是,因为普通的向量数据集都是读入矩阵后进行处理。
矩阵是2D张量,形状为 (样本,特征)。第一个轴是样本轴, 第二个轴是特征轴。
看一看刚才载入的波士顿房价数据集的特征矩阵,这个矩阵的形状是(404,13),也就是404个样本,13个特征:
print("X_train的内容:", X_train) #X_train是2D张量,即矩阵
矩阵的点积
矩阵之间也可以进行点积。具体来说,是第一个矩阵的行向量和第二个矩阵的列向量进行点积,然后把结果标量放进新矩阵,作为结果矩阵中的一个元素。这个规则如下图所示。
注意,当两个矩阵相乘时,第一个矩阵的列数必须等于第二个矩阵的行数。即形状为(m,n)的矩阵乘以形状为(n,m)的矩阵
结果得到一个矩阵(m,m)。也就是说,如果一个矩阵A的形状是(1,8) ,一个矩阵B的形状是(3,2),那么它们之间就无法进行点积运算。
- 一个可行的解决方案是,将A矩阵变形为4x2矩阵,并将B变形为2x3矩阵,而后进行点积,就得到一个形状为(4,3)的4x3矩阵。在Python中可以用reshape方法对矩阵进行变形操作。
- 和向量的点积一样,矩阵的点积也是通过NumPy的dot方法实现,**这节省了很多的for循环语句**。否则,矩阵的运算是需要循环嵌套循环才能实现的。
# 创建3D张量
X = np.array([[[1, 22, 4, 78, 2],
[2, 59, 6, 56, 1],
[3, 31, 8, 54, 0]],
[[4, 56, 9, 34, 1],
[5, 78, 8, 35, 2],
[6, 34, 7, 36, 0]],
[[7, 45,5, 34, 5],
[8, 53, 6, 35, 4],
[9, 81, 4, 36, 5]]])
那么序列数据多出来哪个轴呢?就是序列的步长。对于时间序列数据来说,就是时戳(timestamp),也叫时间步
因为增加了时戳,所以表里面的行列结构显得更为复杂。读取入机器进行处理时,需要把行里面的时间步拆分出来。
第一个轴—样本轴,一年记录下来的数据共365个,也就是365维。
第二个轴—时间步轴,每天一共是24小时,每小时4个15分钟共96维。
第三个轴─特征轴,一共是温度、湿度、风力3个维度。因此,这个数据集读入机器之后的张量形状是(365,96,3) 。
文字序列数据集
图像数据本身包含高度、宽度,再加上一个颜色深度通道。MNIST数据集中是灰度图像,只有一个颜色深度通道;而GRB格式的彩色图像,颜色深度通道的维度为3。
因此,对于图像数据集来说,长、宽、深再加上数据集大小这个维度,就形成了4D张量(如下图所示),其形状为(样本,图像高度,图像宽度,颜色深度),如MNIST特征数据集的形状为(60000,28,28,1)
在机器学习中,不是对上万个数据样本同时进行处理,那样的话机器也受不了,而是一批一批地并行处理,比如指定批量大小为64。此时每批的100px ×100px的彩色图像张量形状为(64,100,100 ,3),如果是灰度图像,则为(64,100,100,1) 。
机器学习的初学者很少有机会见到比4D更高阶的张量。如果有,视频数据的结构是其中的一种。
视频可以看作是由一帧一帧的彩色图像组成的数据集。
每一帧都保存在一个形状为(高度,宽度,颜色深度)的3D张量中。
一系列帧则保存在一个形状为(帧,高度,宽度,颜色深度)的4D张量中。
因此,视频数据集需要5D张量才放得下,其形状为**(样本,帧,高度,宽度,颜色深度)**。
可以想象,视频数据的数据量是非常大的(例如,一个10分钟的普通视频,每秒采样3~4帧,这个视频转换成机器能处理的张量后,可能包含上亿的数据量)。面对这种规模的数据,普通的机器学习模型会感到手足无措,只有深度学习模型才能够搞定。
数据的维度
前面说过,“维度”这个概念有时会造成一些混淆。因为我们会听到,一维数组、二维数组、三维数组之类的话。而在机器学习中又时常听说数据集中的特征,是一个向量,可能是一维、二维、三维、一百维甚至一万维的向量。
其实,在机器学习中,维度指的是在一个数据轴上的许多点,也就是样本的个数(样本轴上点的个数)或者特征的个数(特征轴上点的个数)。一万个不同的特征,就是一万维;而一万个数据样本,也同样可称为一万维。
空间的维度
这本书铺垫的真的不错哈哈哈
还有一点需要注意,在实际项目中,特征(也就是自变量x)的个数,都是很多的。然而在画图说明的时候,大多以一个特征x或两个特征x1、x2为例来表现x和y的关系,很少画出超过两个特征维度的情况,这是为什么呢?
因为仅有一个特征的数据集,关系很容易被展示,从房屋面积到房价,很直接,x轴特征,y轴标签。此时一个特征维,加上一个标签维,就是二维图形,在纸面上显示没有难度。
如果有两个特征,x1代表房屋面积,x2代表楼层,这两个特征和房价y之间的函数,怎么展示?那么可以画出一个有深度的平面显示x、x坐标,立体显示y值。这是从二维的平面上显示三维图形,已经需要一些透视法的作图技巧。
对于分类问题,也可以x1作为一个轴,x2作为一个轴,用圈、点、叉,或者不同颜色的点显示y的不同分类值。这是另一种用平面显示三维信息的方法。
那么特征再多一维呢?很难展示。比如,凸函数,一维特征的凸函数,是一条曲线,而二维特征的凸函数,就像一个碗。三维特征的凸函数是什么样的呢 ? 我们不知道。如果非要描绘x1、x2、x3与y的关系,就需要先应用降维(dimensionality reduction)算法处理数据,把维度降到二维以内。
这个局限来自空间本身只有3个维度,长、宽、深。绘图的时候,如果特征有两维,再加一维标签y,就把三维空间占全了。因此,我们既无法想象,也无法描绘更多维的函数形状。
如何操作张量
我们知道,机器学习中的张量大多是通过NumPy数组来实现的。 NumPy数组和Python的内置数据类型列表不同。列表的元素在系统内存 中是分散存储的,通过每个元素的指针单独访问,而 NumPy 数组内 各元素则连续的存储在同一个内存块中,方便元素的遍历,并可利用现代CPU的向量化计算进行整体并行操作,提升效率。因此NumPy 数 组要求元素都具有相同的数据类型,而列表中各元素的类型则可以不同。
将列表、元组转化为np数组
import numpy as np # 导入NumPy数学工具集
lis=[1, 2, 3, 4, 5] # 创建列表
array_01=np.array([1,2,3,4,5]) # 列表转化成数组
array_02=np.array((6,7,8,9,10)) # 元组转化成数组
array_03=np.array([[1,2,3],[4,5,6]]) # 列表转化成2D数组
print ('列表:', lis)
print ('列表转化为数组:', array_01)
print ('元组转化为数组:', array_02)
print ('2D数组:', array_03)
print ('数组的形状:', array_01.shape)
# print ('列表的形状:', list.shape) # 列表没有形状,程序会报错
利用np的方法直接创建数组
https://blog.csdn.net/neweastsun/article/details/99676029
array_04=np.arange(1,5,1) # 通过arange函数生成数组
array_05=np.linspace(1,5,5) # 通过linspace函数生成数组
print (array_04)
print (array_05)
arange(a,b,c)函数产生a~b(不包括b),间隔为c的一个数 组;
而linspace(a,b,c)函数是把a~b(包括b),产生c个观测值。
当然,机器学习的数据集并不是在程序里面创建的,大多是先从文本文件中把所有样本读取至Dataframe格式的数据,然后用array方法 或其他方法把Dataframe格式的数据转换为NumPy数组,也就是张量, 再进行后续操作。
可以通过**索引(indexing)和切片(slicing)**这两种方式访问张量, 也就是NumPy数组元素。索引,就是访问整个数据集张量里面的某个具体数据;切片,就是访问一个范围内的数据。
对一阶张量的切片
array_06 = np.arange(10)
print (array_06)
index_01 = array_06[3] # 索引-第4个元素
print ('第4个元素', index_01)
index_02 = array_06[-1] # 索引-最后一个元素
print ('第-1个元素', index_02)
slice_01 = array_06[:4] # 从0到4切片
print ('从0到4切片', slice_01)
slice_02 = array_06[0:12:4] # 从0到12切片,步长为4
print ('从0到12切片,步长为4', slice_02)
数组无论是生成的时候,还是访问的时候,都是从0开始的。索引3,就是第4个元素
负号,表示针对当前轴终点的相对位置,因此这里**-1指的就是倒数第一个元素**。冒号,是指区间内的所有元素,如果没限定区间,就代表轴上面的所有元素。
对多阶张量的切片
将不同轴上的切片操作用逗号隔开
例如,对MNIST数据集中间的 5000个数据样本进行切片:
from keras.datasets import mnist #需要打开internet选项
(X_train, y_train), (X_test, y_test) = mnist.load_data()
print (X_train.shape)
X_train_slice = X_train[10000:15000,:,:]
10000:15000,就是把样本轴进行了切片。而后面两个冒号的意思是,剩下的两个轴里面的数据,全都保留(对这个图片样本集,如果 后面两个轴也切片,图片的28px×28px的结构就被破坏了,相当于把图片进行了裁剪)。
数组访问示例
array_07 = np.array([[1,2,3],[4,5,6]])
print (array_07[1:2],'它的形状是', array_07[1:2].shape)
print (array_07[1:2][0], '它的形状又不同了', array_07[1:2][0].shape)
[[4 5 6]] 它的形状是 (1, 3)
[4 5 6] 它的形状又不同了 (3,)
张量的算术运算,包括加、减、乘、除、乘方等,既可以整体进行,也可以逐元素进行。
例如,下面的语句就是对张量的所有元素进行整体操作:
array_07 += 1 # 数组内全部元素加1
print (array_07)
for i in range(array_07.shape[0]):
for j in range(array_07.shape[1]):
array_07[i,j] += 1
张量变形(reshaping)也是机器学习中的一个常见操作,可以通过 NumPy中的reshape方法实现。
什么是变形?怎么变形?很简单。一个形状为(2,3)的矩阵,可以变形为(3,2)的矩阵。元素还是那些元素,但是形状变了。
例
print (array_07,'形状是', array_07.shape)
print (array_07.reshape(3,2), '形状是', array_07.reshape(3,2).shape)
可以调用方法直接转置(transpose)
array_07 = np.array([[1,2,3],[4,5,6]])
array_07 = array_07.T # 矩阵的转置
print (array_07, ' 矩阵转置后形状是', array_07.shape)
例
array_06 = np.arange(10)
print (array_06,'形状是', array_06.shape,'阶为', array_06.ndim)
array_06 = array_06.reshape(10,1)
print (array_06,'形状是', array_06.shape,'阶为', array_06.ndim)
机器学习领域有这样一种说法,如果使用很多的for循环语句,那么说明此人还未了解机器学习的精髓。
看看前面我们完成的两个项目。一个波士顿房价预测,一个MNIST图片识别,这两个数据集,里面都包含成百 上千乃至上万个数据样本。你们看见任何一行for语句代码了吗?
处理如此大的数据集而不需要循环语句,用传统的编程思维理解起来是不是很离奇呢?
下面说明一下。 首先利用了Python对于数组,也就是张量整体地并行操作。很大、 很高阶的数据集,读入NumPy数组之后,并不需要循环嵌套来处理, 而是作为一个整体,直接加减乘除、赋值、访问。这种操作很好地利 用了现代CPU以及GPU/TPU的并行计算功能,效率提升不少。
另外一个技巧,就是Python的广播(broadcasting)功能。这是 NumPy对形状不完全相同的数组间进行数值计算的方式,可以自动自发地把一个数变成一排的向量,把一个低维的数组变成高维的数组。
举例来说,你们看数组的算术运算通常在相应的元素上进行。这 要求两个数组a和b形状相同,也就是 a.shape = b.shape,那么a+b的结 果就是a与b数组对应位相加。这要求张量的阶相同,且每个轴上的维度(长度)也相同。减、乘(不是指点乘)、除等算术运算,也都是 如此。
广播,就是跟着对应阶中维度较大,也就是较为复杂的张量进行填充。用图展示就更为清楚了,如下图所示。图中a的形状是(4, 3),是二阶张量,b的形状是(1,3),也是二阶张量,那么结果就 是把张量b的行进行复制,拉伸成一个形状为(4,3)的张量,然后再与张量a相加。
示例代码
array_08 = np.array([[0,0,0], [10,10,10], [20,20,20], [30,30,30]])
array_09 = np.array([[0,1,2]])
array_10 = np.array([[0],[1],[2],[3]])
list_11 = [[0,1,2]]
print ('array_08的形状:', array_08.shape)
print ('array_09的形状:', array_09.shape)
print ('array_10的形状:', array_10.shape)
array_12 = array_09.reshape(3)
print ('array_12的形状:', array_12.shape)
array_13 = np.array([1])
print ('array_13的形状:', array_13.shape)
array_14 = array_13.reshape(1,1)
print ('array_14的形状:', array_14.shape)
print ('08 + 09结果:',array_08 + array_09)
print ('08 + 10结果:',array_08 + array_10)
print ('08 + 11结果:',array_08 + list_11)
print ('08 + 12结果:',array_08 + array_12)
print ('08 + 13结果:',array_08 + array_13)
print ('08 + 14结果:',array_08 + array_14)
array_08的形状: (4, 3)
array_09的形状: (1, 3)
array_10的形状: (4, 1)
array_12的形状: (3,)
array_13的形状: (1,)
array_14的形状: (1, 1)
08 + 09结果:
[[ 0 1 2]
[10 11 12]
[20 21 22]
[30 31 32]]
08 + 10结果:
[[ 0 0 0]
[11 11 11]
[22 22 22]
[33 33 33]]
08 + 11结果:
[[ 0 1 2]
[10 11 12]
[20 21 22]
[30 31 32]]
08 + 12结果:
[[ 0 1 2]
[10 11 12]
[20 21 22]
[30 31 32]]
08 + 13结果:
[[ 1 1 1]
[11 11 11]
[21 21 21]
[31 31 31]]
08 + 14结果:
[[ 1 1 1]
[11 11 11]
[21 21 21]
[31 31 31]]
广播规则总结
对两个数组, 从后向前比较它们的每一个阶(若其中一个数组没有 当前阶则忽略此阶的运算)
对于每一个阶, 检查是否满足下列条件:
if当前阶的维度相等
then可以直接进行算术操作;
else if当前阶的维度不相等, 但其中一个的值是1
then通过广播将值为1的维度进行“复制”(也形象地称为 “拉伸”)后, 进行算术操作;
else if, 上述条件都不满足, 那么两个数组当前阶不兼容, 不能 够进行广播操作
then 抛 出 "Value Error: operands could not be broadcast together" 异常;
向量的点积运算
a = [ a 1 , a 2 , ⋯ , a n ] b = [ b 1 , b 2 , ⋯ , b n ] 其 点 积 运 算 规 则 如 下 : a ⋅ b = a 1 b 1 + a 2 b 2 + ⋯ + a n b n \\\\\begin{array}{l}\\a=\left[a_{1}, a_{2}, \cdots, a_{n}\right] \\\\b=\left[b_{1}, b_{2}, \cdots, b_{n}\right] \\\\\end{array}\\\\其点积运算规则如下:\\\\a \cdot b=a_{1} b_{1}+a_{2} b_{2}+\cdots+a_{n} b_{n} a=[a1,a2,⋯,an]b=[b1,b2,⋯,bn]其点积运算规则如下:a⋅b=a1b1+a2b2+⋯+anbn
这个过程中要求向量a和向量b的维度相同。向量点积的结果是一 个标量,也就是一个数值。
点积代码示例
vector_01 = np.array([1,2,3])
vector_02 = np.array([[1],[2],[3]])
vector_03 = np.array([2])
vector_04 = vector_02.reshape(1,3)
print ('vector_01的形状:', vector_01.shape)
print ('vector_02的形状:', vector_02.shape)
print ('vector_03的形状:', vector_03.shape)
print ('vector_04的形状:', vector_04.shape)
print ('01和01的点积:', np.dot(vector_01,vector_01))
print ('01和02的点积:', np.dot(vector_01,vector_02))
print ('04和02的点积:', np.dot(vector_04,vector_02))
print ('01和数字的点积:', np.dot(vector_01,2))
print ('02和03的点积:', np.dot(vector_02,vector_03))
print ('02和04的点积:', np.dot(vector_02,vector_04))
# print ('01和03的点积:', np.dot(vector_01,vector_03)) # 程序会报错
# print ('02和02的点积:', np.dot(vector_02,vector_02))
vector_01的形状: (3,)
vector_02的形状: (3, 1)
vector_03的形状: (1,)
vector_04的形状: (1, 3)
01和01的点积: 14
01和02的点积: [14]
04和02的点积: [[14]]
01和数字的点积: [2 4 6]
02和03的点积: [2 4 6]
02和04的点积:
[[1 2 3]
[2 4 6]
[3 6 9]]
矩阵的点积运算
张量,可以被解释为某种几何空间内点的坐标。这样,机器学习中特征向量就形成了特征空间,这个空间的维度和特征向量的维度相同。
现在考虑这样一个二维向量:A = (0.5,1)
这个向量可以看作二维空间中的一个点,一般将它描绘成原点到这个点的箭头,如上图所示。那么更高维的向量呢?应该也可以想象为更高维空间的点。像这样把平面数字转换为空间坐标的思考方式其实是很有难度的。
张量运算都有几何意义。举个例子,我们来看二维向量的加法,如下图所示。向量的加法在几何上体现为一个封闭的图形。两个向量的和形成一个平行四边形,结果向量就是起点到终点的对角线。
这些例子展示了平面中一些二维向量操作的几何意义,推而广之:**机器学习模型是在更高维度的几何空间中对特征向量进行操作、 变形,计算其间的距离,并寻找从特征向量到标签之间的函数拟合,**这就是从几何角度所阐述的机器学习本质。
几种常见的机器学习模型都可以通过特征空间进行几何描述,如下图所示
深度学习的几何意义。
深度学习的过程,实际上也就是一个数据提纯的过程。数据从比较粗放的格式,到逐渐变得“计算机友好”。
数据为什么需要提纯呢?主要还是因为特征维度过高,导致特征空间十分复杂,进而导致机器学习建模过程难度过大。有一种思路是通过流形(manifold)学习将高维特征空间中的样本分布群“平铺”至一个低维空间,同时能保存原高维空间中样本点之间的局部位置相关信息。
原始数据特征空间中的样本分布可能极其扭曲,平铺之后将更有利于样本之间的距离度量,其距离将能更好地反映两个样本之间的相似性。原始空间中相邻较近的点可能不是同一类点,而相邻较远的点有可能是同一类,“平铺”至低维空间后就能解决这一问题。
在传统的机器学习中,流形学习主要用于特征提取和数据降维,特征提取使特征变得更加友好,降维是因为高维数据通常有冗余。而在深度学习出现之后,有一种说法认为神经网络能够自动自发地将复杂的特征数据流形展开,从而减少了特征提取的需要。从直观上,这个展开过程可以用一团揉皱了的纸来解释,如下图所示。
表中公式都不难理解,最后一个公式P(A| B)的意义叫作条件概率,也叫后验概率。也就是说已知事件B发生的时候,A的概率。
例题
举个例子来解释:某公司男生、女生各占50%,烟民占总人数的10%,而女烟民则占总人数的1%。那么问题来了:现在遇到了一个烟民,这个烟民是女生的可能性有多大?
现在是已知3个概率后,能够算出来第4个概率,根据条件概率公式进行推导计算,需要注意以下几个地方。
我们介绍函数的定义并给出几种类型的函数图像,从直观上去理解机器学习如何通过函数对特征和标签之间的关联性进行拟合。然后介绍的对函数进行求导、微分以及梯度下降方法则是机器学习进行参数优化的最基本原理。具体的细节在下一课中介绍。
机器学习中的数据结构称为张量,下面是几种重要的张量格 式,用于处理不同类型的数据集。
Python语句操作方面,NumPy数组的操作都是重点内容。
import numpy as np # 导入NumPy数学工具箱
import pandas as pd # 导入Pandas数据处理工具箱
from keras.datasets import boston_housing #从Keras中导入mnist数据集
#读入训练集和测试集
(X_train, y_train), (X_test, y_test) = boston_housing.load_data()
print ("数据集张量形状:", X_train.shape) #shape方法显示张量的形状
print ("第一个数据样本:\n", X_train[0]) #注意Python的索引是从0开始的
print ("第101到200个数据样本:\n", X_train[100:199]) #注意Python的索引是从0开始的
print ("第一个数据样本的标签:", y_train[0])